agentvault 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (292) hide show
  1. package/.claude/settings.local.json +9 -0
  2. package/dist/cli/commands/approve.js +5 -5
  3. package/dist/cli/commands/archive.js +5 -5
  4. package/dist/cli/commands/backup.js +5 -5
  5. package/dist/cli/commands/cloud-backup.js +12 -12
  6. package/dist/cli/commands/decrypt.js +2 -2
  7. package/dist/cli/commands/deploy.js +1 -1
  8. package/dist/cli/commands/exec.js +2 -2
  9. package/dist/cli/commands/fetch.js +4 -4
  10. package/dist/cli/commands/inference.js +5 -5
  11. package/dist/cli/commands/init.d.ts +1 -1
  12. package/dist/cli/commands/init.js +16 -16
  13. package/dist/cli/commands/list.js +4 -4
  14. package/dist/cli/commands/package.js +2 -2
  15. package/dist/cli/commands/profile.js +1 -1
  16. package/dist/cli/commands/rebuild.js +2 -2
  17. package/dist/cli/commands/show.js +1 -1
  18. package/dist/cli/commands/status.d.ts +1 -1
  19. package/dist/cli/commands/status.js +8 -8
  20. package/dist/cli/commands/trace.js +1 -1
  21. package/dist/cli/commands/wallet-export.js +1 -1
  22. package/dist/cli/commands/wallet-sign.js +1 -1
  23. package/dist/cli/commands/wallet.d.ts +1 -1
  24. package/dist/cli/commands/wallet.js +1 -1
  25. package/dist/cli/index.d.ts +2 -2
  26. package/dist/cli/index.js +3 -3
  27. package/dist/src/archival/archive-manager.d.ts +85 -0
  28. package/dist/src/archival/archive-manager.js +294 -0
  29. package/dist/src/archival/arweave-client.d.ts +88 -0
  30. package/dist/src/archival/arweave-client.js +223 -0
  31. package/dist/src/archival/index.d.ts +8 -0
  32. package/{src/archival/index.ts → dist/src/archival/index.js} +1 -1
  33. package/dist/src/backup/backup.d.ts +67 -0
  34. package/dist/src/backup/backup.js +231 -0
  35. package/dist/src/backup/index.d.ts +7 -0
  36. package/{src/backup/index.ts → dist/src/backup/index.js} +1 -1
  37. package/dist/src/cloud-storage/cloud-sync.d.ts +49 -0
  38. package/dist/src/cloud-storage/cloud-sync.js +372 -0
  39. package/dist/src/cloud-storage/index.d.ts +11 -0
  40. package/{src/cloud-storage/index.ts → dist/src/cloud-storage/index.js} +1 -1
  41. package/dist/src/cloud-storage/provider-detector.d.ts +34 -0
  42. package/dist/src/cloud-storage/provider-detector.js +158 -0
  43. package/{src/cloud-storage/types.ts → dist/src/cloud-storage/types.d.ts} +40 -53
  44. package/dist/src/cloud-storage/types.js +10 -0
  45. package/dist/src/debugging/index.d.ts +6 -0
  46. package/{src/debugging/index.ts → dist/src/debugging/index.js} +1 -1
  47. package/dist/src/debugging/logs.d.ts +32 -0
  48. package/dist/src/debugging/logs.js +158 -0
  49. package/dist/src/debugging/types.d.ts +91 -0
  50. package/dist/src/debugging/types.js +5 -0
  51. package/dist/src/deployment/deployer.d.ts +52 -0
  52. package/dist/src/deployment/deployer.js +211 -0
  53. package/dist/src/deployment/icpClient.d.ts +144 -0
  54. package/dist/src/deployment/icpClient.js +545 -0
  55. package/dist/src/deployment/index.d.ts +11 -0
  56. package/dist/src/deployment/index.js +14 -0
  57. package/dist/src/deployment/promotion.d.ts +32 -0
  58. package/dist/src/deployment/promotion.js +114 -0
  59. package/dist/src/deployment/types.d.ts +101 -0
  60. package/dist/src/deployment/types.js +5 -0
  61. package/dist/src/icp/batch.d.ts +112 -0
  62. package/dist/src/icp/batch.js +273 -0
  63. package/dist/src/icp/cycles.d.ts +29 -0
  64. package/{src/icp/cycles.ts → dist/src/icp/cycles.js} +8 -22
  65. package/dist/src/icp/environment.d.ts +60 -0
  66. package/dist/src/icp/environment.js +183 -0
  67. package/dist/src/icp/icpcli.d.ts +204 -0
  68. package/dist/src/icp/icpcli.js +374 -0
  69. package/dist/src/icp/icwasm.d.ts +94 -0
  70. package/dist/src/icp/icwasm.js +197 -0
  71. package/dist/src/icp/identity.d.ts +50 -0
  72. package/{src/icp/identity.ts → dist/src/icp/identity.js} +15 -28
  73. package/dist/src/icp/index.d.ts +16 -0
  74. package/dist/src/icp/index.js +20 -0
  75. package/dist/src/icp/optimization.d.ts +16 -0
  76. package/dist/src/icp/optimization.js +225 -0
  77. package/dist/src/icp/tokens.d.ts +24 -0
  78. package/{src/icp/tokens.ts → dist/src/icp/tokens.js} +5 -12
  79. package/dist/src/icp/tool-detector.d.ts +31 -0
  80. package/dist/src/icp/tool-detector.js +104 -0
  81. package/dist/src/icp/types.d.ts +493 -0
  82. package/dist/src/icp/types.js +7 -0
  83. package/dist/src/index.d.ts +12 -0
  84. package/dist/src/index.js +18 -0
  85. package/dist/src/inference/bittensor-client.d.ts +108 -0
  86. package/dist/src/inference/bittensor-client.js +224 -0
  87. package/dist/src/inference/index.d.ts +8 -0
  88. package/{src/inference/index.ts → dist/src/inference/index.js} +1 -1
  89. package/dist/src/inference/inference-manager.d.ts +76 -0
  90. package/dist/src/inference/inference-manager.js +228 -0
  91. package/dist/src/metrics/index.d.ts +7 -0
  92. package/{src/metrics/index.ts → dist/src/metrics/index.js} +1 -1
  93. package/dist/src/metrics/metrics.d.ts +39 -0
  94. package/dist/src/metrics/metrics.js +129 -0
  95. package/dist/src/monitoring/alerting.d.ts +51 -0
  96. package/dist/src/monitoring/alerting.js +169 -0
  97. package/dist/src/monitoring/health.d.ts +40 -0
  98. package/dist/src/monitoring/health.js +164 -0
  99. package/dist/src/monitoring/index.d.ts +10 -0
  100. package/dist/src/monitoring/index.js +12 -0
  101. package/dist/src/monitoring/info.d.ts +15 -0
  102. package/dist/src/monitoring/info.js +109 -0
  103. package/dist/src/monitoring/types.d.ts +93 -0
  104. package/dist/src/monitoring/types.js +7 -0
  105. package/dist/src/network/index.d.ts +5 -0
  106. package/{src/network/index.ts → dist/src/network/index.js} +1 -1
  107. package/dist/src/network/network-config.d.ts +31 -0
  108. package/dist/src/network/network-config.js +109 -0
  109. package/dist/src/packaging/compiler.d.ts +61 -0
  110. package/dist/src/packaging/compiler.js +562 -0
  111. package/dist/src/packaging/config-persistence.d.ts +46 -0
  112. package/dist/src/packaging/config-persistence.js +108 -0
  113. package/dist/src/packaging/config-schemas.d.ts +115 -0
  114. package/dist/src/packaging/config-schemas.js +43 -0
  115. package/dist/src/packaging/detector.d.ts +26 -0
  116. package/dist/src/packaging/detector.js +193 -0
  117. package/dist/src/packaging/index.d.ts +16 -0
  118. package/dist/src/packaging/index.js +22 -0
  119. package/dist/src/packaging/packager.d.ts +31 -0
  120. package/dist/src/packaging/packager.js +90 -0
  121. package/dist/src/packaging/parsers/clawdbot.d.ts +19 -0
  122. package/dist/src/packaging/parsers/clawdbot.js +231 -0
  123. package/dist/src/packaging/parsers/cline.d.ts +26 -0
  124. package/dist/src/packaging/parsers/cline.js +185 -0
  125. package/dist/src/packaging/parsers/generic.d.ts +27 -0
  126. package/dist/src/packaging/parsers/generic.js +228 -0
  127. package/dist/src/packaging/parsers/goose.d.ts +26 -0
  128. package/dist/src/packaging/parsers/goose.js +175 -0
  129. package/dist/src/packaging/parsers/index.d.ts +11 -0
  130. package/{src/packaging/parsers/index.ts → dist/src/packaging/parsers/index.js} +1 -1
  131. package/dist/src/packaging/serializer.d.ts +108 -0
  132. package/dist/src/packaging/serializer.js +153 -0
  133. package/dist/src/packaging/types.d.ts +131 -0
  134. package/dist/src/packaging/types.js +5 -0
  135. package/dist/src/packaging/wasmedge-compiler.d.ts +76 -0
  136. package/dist/src/packaging/wasmedge-compiler.js +349 -0
  137. package/dist/src/security/index.d.ts +11 -0
  138. package/{src/security/index.ts → dist/src/security/index.js} +1 -4
  139. package/dist/src/security/multisig.d.ts +102 -0
  140. package/dist/src/security/multisig.js +283 -0
  141. package/dist/src/security/types.d.ts +207 -0
  142. package/dist/src/security/types.js +217 -0
  143. package/dist/src/security/vetkeys.d.ts +179 -0
  144. package/dist/src/security/vetkeys.js +499 -0
  145. package/dist/src/testing/index.d.ts +6 -0
  146. package/{src/testing/index.ts → dist/src/testing/index.js} +1 -1
  147. package/dist/src/testing/local-runner.d.ts +23 -0
  148. package/dist/src/testing/local-runner.js +226 -0
  149. package/dist/src/testing/types.d.ts +98 -0
  150. package/dist/src/testing/types.js +5 -0
  151. package/dist/src/wallet/cbor-serializer.d.ts +82 -0
  152. package/dist/src/wallet/cbor-serializer.js +282 -0
  153. package/dist/src/wallet/chain-dispatcher.d.ts +112 -0
  154. package/dist/src/wallet/chain-dispatcher.js +241 -0
  155. package/dist/src/wallet/cross-chain-aggregator.d.ts +119 -0
  156. package/dist/src/wallet/cross-chain-aggregator.js +235 -0
  157. package/dist/src/wallet/index.d.ts +16 -0
  158. package/dist/src/wallet/index.js +22 -0
  159. package/dist/src/wallet/key-derivation.d.ts +117 -0
  160. package/dist/src/wallet/key-derivation.js +325 -0
  161. package/dist/src/wallet/providers/base-provider.d.ts +111 -0
  162. package/dist/src/wallet/providers/base-provider.js +58 -0
  163. package/dist/src/wallet/providers/cketh-provider.d.ts +104 -0
  164. package/dist/src/wallet/providers/cketh-provider.js +343 -0
  165. package/dist/src/wallet/providers/polkadot-provider.d.ts +115 -0
  166. package/dist/src/wallet/providers/polkadot-provider.js +407 -0
  167. package/dist/src/wallet/providers/solana-provider.d.ts +102 -0
  168. package/dist/src/wallet/providers/solana-provider.js +393 -0
  169. package/dist/src/wallet/transaction-queue.d.ts +133 -0
  170. package/dist/src/wallet/transaction-queue.js +195 -0
  171. package/dist/src/wallet/types.d.ts +167 -0
  172. package/dist/src/wallet/types.js +5 -0
  173. package/dist/src/wallet/vetkeys-adapter.d.ts +134 -0
  174. package/dist/src/wallet/vetkeys-adapter.js +313 -0
  175. package/dist/src/wallet/wallet-manager.d.ts +202 -0
  176. package/dist/src/wallet/wallet-manager.js +451 -0
  177. package/dist/src/wallet/wallet-storage.d.ts +131 -0
  178. package/dist/src/wallet/wallet-storage.js +274 -0
  179. package/macos-wallet-app/AgentVaultWallet/App/AgentVaultWalletApp.swift +54 -0
  180. package/macos-wallet-app/AgentVaultWallet/Models/AppState.swift +102 -0
  181. package/macos-wallet-app/AgentVaultWallet/Models/Chain.swift +121 -0
  182. package/macos-wallet-app/AgentVaultWallet/Models/Wallet.swift +98 -0
  183. package/macos-wallet-app/AgentVaultWallet/Resources/AgentVaultWallet.entitlements +27 -0
  184. package/macos-wallet-app/AgentVaultWallet/Resources/Info.plist +69 -0
  185. package/macos-wallet-app/AgentVaultWallet/Services/BackupService.swift +270 -0
  186. package/macos-wallet-app/AgentVaultWallet/Services/CLIBridge.swift +367 -0
  187. package/macos-wallet-app/AgentVaultWallet/Services/CryptoService.swift +157 -0
  188. package/macos-wallet-app/AgentVaultWallet/Services/FileService.swift +120 -0
  189. package/macos-wallet-app/AgentVaultWallet/Services/KeychainService.swift +219 -0
  190. package/macos-wallet-app/AgentVaultWallet/Utilities/Constants.swift +44 -0
  191. package/macos-wallet-app/AgentVaultWallet/Utilities/Extensions.swift +115 -0
  192. package/macos-wallet-app/AgentVaultWallet/ViewModels/BackupViewModel.swift +237 -0
  193. package/macos-wallet-app/AgentVaultWallet/ViewModels/CreateWalletViewModel.swift +137 -0
  194. package/macos-wallet-app/AgentVaultWallet/ViewModels/ImportWalletViewModel.swift +179 -0
  195. package/macos-wallet-app/AgentVaultWallet/ViewModels/WalletStore.swift +286 -0
  196. package/macos-wallet-app/AgentVaultWallet/Views/Backup/BackupView.swift +235 -0
  197. package/macos-wallet-app/AgentVaultWallet/Views/Backup/RestoreView.swift +316 -0
  198. package/macos-wallet-app/AgentVaultWallet/Views/Create/CreateWalletFlow.swift +438 -0
  199. package/macos-wallet-app/AgentVaultWallet/Views/Import/ImportWalletFlow.swift +399 -0
  200. package/macos-wallet-app/AgentVaultWallet/Views/MainView.swift +134 -0
  201. package/macos-wallet-app/AgentVaultWallet/Views/Settings/SettingsView.swift +276 -0
  202. package/macos-wallet-app/AgentVaultWallet/Views/Sidebar/SidebarView.swift +133 -0
  203. package/macos-wallet-app/AgentVaultWallet/Views/Wallet/DashboardView.swift +233 -0
  204. package/macos-wallet-app/AgentVaultWallet/Views/Wallet/WalletDetailView.swift +281 -0
  205. package/macos-wallet-app/AgentVaultWallet/Views/Wallet/WalletListView.swift +280 -0
  206. package/macos-wallet-app/AgentVaultWallet/Views/Welcome/WelcomeView.swift +176 -0
  207. package/macos-wallet-app/Makefile +47 -0
  208. package/macos-wallet-app/project.yml +40 -0
  209. package/macos-wallet-app/setup.sh +73 -0
  210. package/package.json +10 -2
  211. package/backups/agentvault-backup-test-agent-2026-02-12T17-54-28-967Z.json +0 -28
  212. package/backups/agentvault-backup-test-agent-2026-02-12T17-54-29-032Z.backup +0 -1
  213. package/backups/agentvault-backup-test-agent-2026-02-12T17-57-42-373Z.json +0 -28
  214. package/backups/agentvault-backup-test-agent-2026-02-12T17-57-42-428Z.backup +0 -1
  215. package/backups/agentvault-backup-test-agent-2026-02-12T18-52-25-132Z.json +0 -28
  216. package/backups/agentvault-backup-test-agent-2026-02-12T18-52-25-247Z.backup +0 -1
  217. package/backups/agentvault-backup-test-agent-2026-02-12T18-54-09-216Z.json +0 -28
  218. package/backups/agentvault-backup-test-agent-2026-02-12T18-54-09-283Z.backup +0 -1
  219. package/backups/agentvault-backup-test-agent-2026-02-12T22-18-22-772Z.backup +0 -1
  220. package/backups/agentvault-backup-test-agent-2026-02-12T22-18-22-793Z.json +0 -28
  221. package/backups/test-backup.json +0 -28
  222. package/scripts/dev-dashboard.mjs +0 -84
  223. package/site/README.md +0 -63
  224. package/site/docusaurus.config.ts +0 -148
  225. package/site/package-lock.json +0 -18383
  226. package/site/package.json +0 -47
  227. package/site/sidebars.ts +0 -86
  228. package/site/static/.gitkeep +0 -0
  229. package/site/static/img/logo.svg +0 -28
  230. package/site/static/img/og-image.svg +0 -35
  231. package/src/archival/archive-manager.ts +0 -372
  232. package/src/archival/arweave-client.ts +0 -289
  233. package/src/backup/backup.ts +0 -315
  234. package/src/cloud-storage/cloud-sync.ts +0 -461
  235. package/src/cloud-storage/provider-detector.ts +0 -198
  236. package/src/debugging/logs.ts +0 -193
  237. package/src/debugging/types.ts +0 -100
  238. package/src/deployment/deployer.ts +0 -274
  239. package/src/deployment/icpClient.ts +0 -620
  240. package/src/deployment/index.ts +0 -46
  241. package/src/deployment/promotion.ts +0 -161
  242. package/src/deployment/types.ts +0 -111
  243. package/src/icp/batch.ts +0 -374
  244. package/src/icp/environment.ts +0 -215
  245. package/src/icp/icpcli.ts +0 -438
  246. package/src/icp/icwasm.ts +0 -222
  247. package/src/icp/index.ts +0 -94
  248. package/src/icp/optimization.ts +0 -242
  249. package/src/icp/tool-detector.ts +0 -110
  250. package/src/icp/types.ts +0 -574
  251. package/src/index.ts +0 -25
  252. package/src/inference/bittensor-client.ts +0 -304
  253. package/src/inference/inference-manager.ts +0 -327
  254. package/src/metrics/metrics.ts +0 -186
  255. package/src/monitoring/alerting.ts +0 -190
  256. package/src/monitoring/health.ts +0 -197
  257. package/src/monitoring/index.ts +0 -38
  258. package/src/monitoring/info.ts +0 -114
  259. package/src/monitoring/types.ts +0 -99
  260. package/src/network/network-config.ts +0 -129
  261. package/src/packaging/compiler.ts +0 -647
  262. package/src/packaging/config-persistence.ts +0 -135
  263. package/src/packaging/config-schemas.ts +0 -156
  264. package/src/packaging/detector.ts +0 -220
  265. package/src/packaging/index.ts +0 -90
  266. package/src/packaging/packager.ts +0 -118
  267. package/src/packaging/parsers/clawdbot.ts +0 -278
  268. package/src/packaging/parsers/cline.ts +0 -223
  269. package/src/packaging/parsers/generic.ts +0 -266
  270. package/src/packaging/parsers/goose.ts +0 -214
  271. package/src/packaging/serializer.ts +0 -260
  272. package/src/packaging/types.ts +0 -144
  273. package/src/packaging/wasmedge-compiler.ts +0 -406
  274. package/src/security/multisig.ts +0 -415
  275. package/src/security/types.ts +0 -416
  276. package/src/security/vetkeys.ts +0 -655
  277. package/src/testing/local-runner.ts +0 -264
  278. package/src/testing/types.ts +0 -104
  279. package/src/wallet/cbor-serializer.ts +0 -323
  280. package/src/wallet/chain-dispatcher.ts +0 -313
  281. package/src/wallet/cross-chain-aggregator.ts +0 -346
  282. package/src/wallet/index.ts +0 -76
  283. package/src/wallet/key-derivation.ts +0 -425
  284. package/src/wallet/providers/base-provider.ts +0 -154
  285. package/src/wallet/providers/cketh-provider.ts +0 -434
  286. package/src/wallet/providers/polkadot-provider.ts +0 -503
  287. package/src/wallet/providers/solana-provider.ts +0 -490
  288. package/src/wallet/transaction-queue.ts +0 -284
  289. package/src/wallet/types.ts +0 -178
  290. package/src/wallet/vetkeys-adapter.ts +0 -431
  291. package/src/wallet/wallet-manager.ts +0 -597
  292. package/src/wallet/wallet-storage.ts +0 -380
@@ -0,0 +1,69 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>CFBundleName</key>
6
+ <string>AgentVault Wallet</string>
7
+ <key>CFBundleDisplayName</key>
8
+ <string>AgentVault Wallet</string>
9
+ <key>CFBundleIdentifier</key>
10
+ <string>com.agentvault.wallet</string>
11
+ <key>CFBundleVersion</key>
12
+ <string>1</string>
13
+ <key>CFBundleShortVersionString</key>
14
+ <string>1.0.0</string>
15
+ <key>CFBundlePackageType</key>
16
+ <string>APPL</string>
17
+ <key>CFBundleExecutable</key>
18
+ <string>$(EXECUTABLE_NAME)</string>
19
+ <key>CFBundleInfoDictionaryVersion</key>
20
+ <string>6.0</string>
21
+ <key>LSMinimumSystemVersion</key>
22
+ <string>14.0</string>
23
+ <key>LSApplicationCategoryType</key>
24
+ <string>public.app-category.finance</string>
25
+ <key>NSMainNibFile</key>
26
+ <string></string>
27
+ <key>NSPrincipalClass</key>
28
+ <string>NSApplication</string>
29
+ <key>NSHumanReadableCopyright</key>
30
+ <string>Copyright 2024 AgentVault. All rights reserved.</string>
31
+ <key>CFBundleDocumentTypes</key>
32
+ <array>
33
+ <dict>
34
+ <key>CFBundleTypeName</key>
35
+ <string>AgentVault Backup</string>
36
+ <key>CFBundleTypeExtensions</key>
37
+ <array>
38
+ <string>avbackup</string>
39
+ </array>
40
+ <key>CFBundleTypeRole</key>
41
+ <string>Editor</string>
42
+ <key>LSHandlerRank</key>
43
+ <string>Owner</string>
44
+ <key>CFBundleTypeIconFiles</key>
45
+ <array/>
46
+ </dict>
47
+ </array>
48
+ <key>UTExportedTypeDeclarations</key>
49
+ <array>
50
+ <dict>
51
+ <key>UTTypeIdentifier</key>
52
+ <string>com.agentvault.backup</string>
53
+ <key>UTTypeDescription</key>
54
+ <string>AgentVault Wallet Backup</string>
55
+ <key>UTTypeConformsTo</key>
56
+ <array>
57
+ <string>public.data</string>
58
+ </array>
59
+ <key>UTTypeTagSpecification</key>
60
+ <dict>
61
+ <key>public.filename-extension</key>
62
+ <array>
63
+ <string>avbackup</string>
64
+ </array>
65
+ </dict>
66
+ </dict>
67
+ </array>
68
+ </dict>
69
+ </plist>
@@ -0,0 +1,270 @@
1
+ import Foundation
2
+
3
+ /// Handles wallet backup creation and restoration.
4
+ /// Backups are encrypted with AES-256-GCM using a user-provided password.
5
+ final class BackupService {
6
+
7
+ static let shared = BackupService()
8
+
9
+ private let crypto = CryptoService.shared
10
+ private let keychain = KeychainService.shared
11
+ private let fileManager = FileManager.default
12
+
13
+ enum BackupError: LocalizedError {
14
+ case noWalletsToBackup
15
+ case serializationFailed
16
+ case fileWriteFailed(String)
17
+ case fileReadFailed(String)
18
+ case invalidBackupFormat
19
+ case versionMismatch(Int)
20
+ case decryptionFailed
21
+ case corruptedBackup
22
+
23
+ var errorDescription: String? {
24
+ switch self {
25
+ case .noWalletsToBackup:
26
+ return "No wallets to back up"
27
+ case .serializationFailed:
28
+ return "Failed to serialize wallet data"
29
+ case .fileWriteFailed(let path):
30
+ return "Failed to write backup file to \(path)"
31
+ case .fileReadFailed(let path):
32
+ return "Failed to read backup file at \(path)"
33
+ case .invalidBackupFormat:
34
+ return "The selected file is not a valid AgentVault backup"
35
+ case .versionMismatch(let v):
36
+ return "Backup version \(v) is not supported by this app version"
37
+ case .decryptionFailed:
38
+ return "Failed to decrypt backup — incorrect password?"
39
+ case .corruptedBackup:
40
+ return "Backup file appears to be corrupted"
41
+ }
42
+ }
43
+ }
44
+
45
+ private init() {}
46
+
47
+ // MARK: - Backup Creation
48
+
49
+ /// Create an encrypted backup of all provided wallets
50
+ func createBackup(wallets: [Wallet], password: String) throws -> Data {
51
+ guard !wallets.isEmpty else {
52
+ throw BackupError.noWalletsToBackup
53
+ }
54
+
55
+ // Collect secrets for each wallet
56
+ var secrets: [[String: String]] = []
57
+ for wallet in wallets {
58
+ var entry: [String: String] = [
59
+ "id": wallet.id.uuidString,
60
+ "chain": wallet.chain.rawValue,
61
+ ]
62
+
63
+ if let mnemonic = try? keychain.getMnemonic(forWalletId: wallet.id) {
64
+ entry["mnemonic"] = mnemonic
65
+ }
66
+ if let privateKey = try? keychain.getPrivateKey(forWalletId: wallet.id) {
67
+ entry["privateKey"] = privateKey
68
+ }
69
+ if let jwkData = try? keychain.getJWK(forWalletId: wallet.id) {
70
+ entry["jwk"] = String(data: jwkData, encoding: .utf8)
71
+ }
72
+
73
+ secrets.append(entry)
74
+ }
75
+
76
+ // Serialize secrets to JSON
77
+ guard let secretsData = try? JSONSerialization.data(withJSONObject: secrets, options: []) else {
78
+ throw BackupError.serializationFailed
79
+ }
80
+
81
+ // Encrypt secrets
82
+ let encrypted = try crypto.encrypt(data: secretsData, password: password)
83
+
84
+ // Build backup entries
85
+ let entries = wallets.map { wallet in
86
+ WalletBackupEntry(
87
+ id: wallet.id,
88
+ name: wallet.name,
89
+ chain: wallet.chain,
90
+ address: wallet.address,
91
+ createdAt: wallet.createdAt,
92
+ derivationPath: wallet.derivationPath,
93
+ hasMnemonicBackup: wallet.hasMnemonicBackup
94
+ )
95
+ }
96
+
97
+ // Create backup structure
98
+ let backup = WalletBackup(
99
+ version: WalletBackup.currentVersion,
100
+ createdAt: Date(),
101
+ appVersion: Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "1.0.0",
102
+ wallets: entries,
103
+ encryptedPayload: encrypted.ciphertext,
104
+ salt: encrypted.salt,
105
+ iv: encrypted.nonce
106
+ )
107
+
108
+ // Encode to JSON
109
+ let encoder = JSONEncoder()
110
+ encoder.dateEncodingStrategy = .iso8601
111
+ encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
112
+
113
+ guard let backupData = try? encoder.encode(backup) else {
114
+ throw BackupError.serializationFailed
115
+ }
116
+
117
+ return backupData
118
+ }
119
+
120
+ /// Write backup data to a file
121
+ func writeBackup(_ data: Data, to url: URL) throws {
122
+ do {
123
+ try data.write(to: url, options: [.atomic, .completeFileProtection])
124
+ } catch {
125
+ throw BackupError.fileWriteFailed(url.path)
126
+ }
127
+ }
128
+
129
+ // MARK: - Backup Restoration
130
+
131
+ /// Read and validate a backup file, returning the metadata (before decryption)
132
+ func readBackupMetadata(from url: URL) throws -> WalletBackup {
133
+ guard let data = try? Data(contentsOf: url) else {
134
+ throw BackupError.fileReadFailed(url.path)
135
+ }
136
+
137
+ let decoder = JSONDecoder()
138
+ decoder.dateDecodingStrategy = .iso8601
139
+
140
+ guard let backup = try? decoder.decode(WalletBackup.self, from: data) else {
141
+ throw BackupError.invalidBackupFormat
142
+ }
143
+
144
+ guard backup.version <= WalletBackup.currentVersion else {
145
+ throw BackupError.versionMismatch(backup.version)
146
+ }
147
+
148
+ return backup
149
+ }
150
+
151
+ /// Decrypt and extract wallet secrets from a backup
152
+ func restoreSecrets(from backup: WalletBackup, password: String) throws -> [RestoredWalletSecret] {
153
+ let encrypted = CryptoService.EncryptedData(
154
+ ciphertext: backup.encryptedPayload,
155
+ nonce: backup.iv,
156
+ tag: Data(repeating: 0, count: 16), // Tag is embedded in ciphertext for our format
157
+ salt: backup.salt
158
+ )
159
+
160
+ let decryptedData: Data
161
+ do {
162
+ decryptedData = try crypto.decrypt(encrypted: encrypted, password: password)
163
+ } catch {
164
+ throw BackupError.decryptionFailed
165
+ }
166
+
167
+ guard let secrets = try? JSONSerialization.jsonObject(with: decryptedData) as? [[String: String]] else {
168
+ throw BackupError.corruptedBackup
169
+ }
170
+
171
+ return secrets.compactMap { entry in
172
+ guard let idStr = entry["id"],
173
+ let id = UUID(uuidString: idStr),
174
+ let chainStr = entry["chain"],
175
+ let chain = Chain(rawValue: chainStr) else {
176
+ return nil
177
+ }
178
+
179
+ return RestoredWalletSecret(
180
+ walletId: id,
181
+ chain: chain,
182
+ mnemonic: entry["mnemonic"],
183
+ privateKey: entry["privateKey"],
184
+ jwkJSON: entry["jwk"]
185
+ )
186
+ }
187
+ }
188
+
189
+ /// Save restored secrets to Keychain
190
+ func saveRestoredSecrets(_ secrets: [RestoredWalletSecret]) throws {
191
+ for secret in secrets {
192
+ if let mnemonic = secret.mnemonic {
193
+ try keychain.saveMnemonic(mnemonic, forWalletId: secret.walletId)
194
+ }
195
+ if let privateKey = secret.privateKey {
196
+ try keychain.savePrivateKey(privateKey, forWalletId: secret.walletId)
197
+ }
198
+ if let jwkJSON = secret.jwkJSON, let jwkData = jwkJSON.data(using: .utf8) {
199
+ try keychain.saveJWK(jwkData, forWalletId: secret.walletId)
200
+ }
201
+ }
202
+ }
203
+
204
+ // MARK: - Backup File Management
205
+
206
+ /// Default backup directory
207
+ var defaultBackupDirectory: URL {
208
+ let appSupport = fileManager.urls(for: .applicationSupportDirectory, in: .userDomainMask).first!
209
+ let backupDir = appSupport.appendingPathComponent("AgentVaultWallet/Backups", isDirectory: true)
210
+ try? fileManager.createDirectory(at: backupDir, withIntermediateDirectories: true)
211
+ return backupDir
212
+ }
213
+
214
+ /// Generate a default backup filename
215
+ func defaultBackupFilename() -> String {
216
+ let formatter = DateFormatter()
217
+ formatter.dateFormat = "yyyy-MM-dd_HHmmss"
218
+ return "agentvault-backup-\(formatter.string(from: Date())).avbackup"
219
+ }
220
+
221
+ /// List existing backup files in the default directory
222
+ func listBackups() -> [BackupFileInfo] {
223
+ guard let contents = try? fileManager.contentsOfDirectory(
224
+ at: defaultBackupDirectory,
225
+ includingPropertiesForKeys: [.creationDateKey, .fileSizeKey],
226
+ options: .skipsHiddenFiles
227
+ ) else { return [] }
228
+
229
+ return contents
230
+ .filter { $0.pathExtension == "avbackup" }
231
+ .compactMap { url -> BackupFileInfo? in
232
+ let attrs = try? fileManager.attributesOfItem(atPath: url.path)
233
+ let size = attrs?[.size] as? Int ?? 0
234
+ let created = attrs?[.creationDate] as? Date ?? Date()
235
+ let walletCount = (try? readBackupMetadata(from: url))?.wallets.count
236
+
237
+ return BackupFileInfo(
238
+ url: url,
239
+ filename: url.lastPathComponent,
240
+ createdAt: created,
241
+ fileSize: size,
242
+ walletCount: walletCount
243
+ )
244
+ }
245
+ .sorted { $0.createdAt > $1.createdAt }
246
+ }
247
+ }
248
+
249
+ /// Secrets extracted from a backup for a single wallet
250
+ struct RestoredWalletSecret {
251
+ let walletId: UUID
252
+ let chain: Chain
253
+ let mnemonic: String?
254
+ let privateKey: String?
255
+ let jwkJSON: String?
256
+ }
257
+
258
+ /// Metadata about a backup file on disk
259
+ struct BackupFileInfo: Identifiable {
260
+ let id = UUID()
261
+ let url: URL
262
+ let filename: String
263
+ let createdAt: Date
264
+ let fileSize: Int
265
+ let walletCount: Int?
266
+
267
+ var formattedSize: String {
268
+ ByteCountFormatter.string(fromByteCount: Int64(fileSize), countStyle: .file)
269
+ }
270
+ }