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.
- package/.claude/settings.local.json +9 -0
- package/dist/cli/commands/approve.js +5 -5
- package/dist/cli/commands/archive.js +5 -5
- package/dist/cli/commands/backup.js +5 -5
- package/dist/cli/commands/cloud-backup.js +12 -12
- package/dist/cli/commands/decrypt.js +2 -2
- package/dist/cli/commands/deploy.js +1 -1
- package/dist/cli/commands/exec.js +2 -2
- package/dist/cli/commands/fetch.js +4 -4
- package/dist/cli/commands/inference.js +5 -5
- package/dist/cli/commands/init.d.ts +1 -1
- package/dist/cli/commands/init.js +16 -16
- package/dist/cli/commands/list.js +4 -4
- package/dist/cli/commands/package.js +2 -2
- package/dist/cli/commands/profile.js +1 -1
- package/dist/cli/commands/rebuild.js +2 -2
- package/dist/cli/commands/show.js +1 -1
- package/dist/cli/commands/status.d.ts +1 -1
- package/dist/cli/commands/status.js +8 -8
- package/dist/cli/commands/trace.js +1 -1
- package/dist/cli/commands/wallet-export.js +1 -1
- package/dist/cli/commands/wallet-sign.js +1 -1
- package/dist/cli/commands/wallet.d.ts +1 -1
- package/dist/cli/commands/wallet.js +1 -1
- package/dist/cli/index.d.ts +2 -2
- package/dist/cli/index.js +3 -3
- package/dist/src/archival/archive-manager.d.ts +85 -0
- package/dist/src/archival/archive-manager.js +294 -0
- package/dist/src/archival/arweave-client.d.ts +88 -0
- package/dist/src/archival/arweave-client.js +223 -0
- package/dist/src/archival/index.d.ts +8 -0
- package/{src/archival/index.ts → dist/src/archival/index.js} +1 -1
- package/dist/src/backup/backup.d.ts +67 -0
- package/dist/src/backup/backup.js +231 -0
- package/dist/src/backup/index.d.ts +7 -0
- package/{src/backup/index.ts → dist/src/backup/index.js} +1 -1
- package/dist/src/cloud-storage/cloud-sync.d.ts +49 -0
- package/dist/src/cloud-storage/cloud-sync.js +372 -0
- package/dist/src/cloud-storage/index.d.ts +11 -0
- package/{src/cloud-storage/index.ts → dist/src/cloud-storage/index.js} +1 -1
- package/dist/src/cloud-storage/provider-detector.d.ts +34 -0
- package/dist/src/cloud-storage/provider-detector.js +158 -0
- package/{src/cloud-storage/types.ts → dist/src/cloud-storage/types.d.ts} +40 -53
- package/dist/src/cloud-storage/types.js +10 -0
- package/dist/src/debugging/index.d.ts +6 -0
- package/{src/debugging/index.ts → dist/src/debugging/index.js} +1 -1
- package/dist/src/debugging/logs.d.ts +32 -0
- package/dist/src/debugging/logs.js +158 -0
- package/dist/src/debugging/types.d.ts +91 -0
- package/dist/src/debugging/types.js +5 -0
- package/dist/src/deployment/deployer.d.ts +52 -0
- package/dist/src/deployment/deployer.js +211 -0
- package/dist/src/deployment/icpClient.d.ts +144 -0
- package/dist/src/deployment/icpClient.js +545 -0
- package/dist/src/deployment/index.d.ts +11 -0
- package/dist/src/deployment/index.js +14 -0
- package/dist/src/deployment/promotion.d.ts +32 -0
- package/dist/src/deployment/promotion.js +114 -0
- package/dist/src/deployment/types.d.ts +101 -0
- package/dist/src/deployment/types.js +5 -0
- package/dist/src/icp/batch.d.ts +112 -0
- package/dist/src/icp/batch.js +273 -0
- package/dist/src/icp/cycles.d.ts +29 -0
- package/{src/icp/cycles.ts → dist/src/icp/cycles.js} +8 -22
- package/dist/src/icp/environment.d.ts +60 -0
- package/dist/src/icp/environment.js +183 -0
- package/dist/src/icp/icpcli.d.ts +204 -0
- package/dist/src/icp/icpcli.js +374 -0
- package/dist/src/icp/icwasm.d.ts +94 -0
- package/dist/src/icp/icwasm.js +197 -0
- package/dist/src/icp/identity.d.ts +50 -0
- package/{src/icp/identity.ts → dist/src/icp/identity.js} +15 -28
- package/dist/src/icp/index.d.ts +16 -0
- package/dist/src/icp/index.js +20 -0
- package/dist/src/icp/optimization.d.ts +16 -0
- package/dist/src/icp/optimization.js +225 -0
- package/dist/src/icp/tokens.d.ts +24 -0
- package/{src/icp/tokens.ts → dist/src/icp/tokens.js} +5 -12
- package/dist/src/icp/tool-detector.d.ts +31 -0
- package/dist/src/icp/tool-detector.js +104 -0
- package/dist/src/icp/types.d.ts +493 -0
- package/dist/src/icp/types.js +7 -0
- package/dist/src/index.d.ts +12 -0
- package/dist/src/index.js +18 -0
- package/dist/src/inference/bittensor-client.d.ts +108 -0
- package/dist/src/inference/bittensor-client.js +224 -0
- package/dist/src/inference/index.d.ts +8 -0
- package/{src/inference/index.ts → dist/src/inference/index.js} +1 -1
- package/dist/src/inference/inference-manager.d.ts +76 -0
- package/dist/src/inference/inference-manager.js +228 -0
- package/dist/src/metrics/index.d.ts +7 -0
- package/{src/metrics/index.ts → dist/src/metrics/index.js} +1 -1
- package/dist/src/metrics/metrics.d.ts +39 -0
- package/dist/src/metrics/metrics.js +129 -0
- package/dist/src/monitoring/alerting.d.ts +51 -0
- package/dist/src/monitoring/alerting.js +169 -0
- package/dist/src/monitoring/health.d.ts +40 -0
- package/dist/src/monitoring/health.js +164 -0
- package/dist/src/monitoring/index.d.ts +10 -0
- package/dist/src/monitoring/index.js +12 -0
- package/dist/src/monitoring/info.d.ts +15 -0
- package/dist/src/monitoring/info.js +109 -0
- package/dist/src/monitoring/types.d.ts +93 -0
- package/dist/src/monitoring/types.js +7 -0
- package/dist/src/network/index.d.ts +5 -0
- package/{src/network/index.ts → dist/src/network/index.js} +1 -1
- package/dist/src/network/network-config.d.ts +31 -0
- package/dist/src/network/network-config.js +109 -0
- package/dist/src/packaging/compiler.d.ts +61 -0
- package/dist/src/packaging/compiler.js +562 -0
- package/dist/src/packaging/config-persistence.d.ts +46 -0
- package/dist/src/packaging/config-persistence.js +108 -0
- package/dist/src/packaging/config-schemas.d.ts +115 -0
- package/dist/src/packaging/config-schemas.js +43 -0
- package/dist/src/packaging/detector.d.ts +26 -0
- package/dist/src/packaging/detector.js +193 -0
- package/dist/src/packaging/index.d.ts +16 -0
- package/dist/src/packaging/index.js +22 -0
- package/dist/src/packaging/packager.d.ts +31 -0
- package/dist/src/packaging/packager.js +90 -0
- package/dist/src/packaging/parsers/clawdbot.d.ts +19 -0
- package/dist/src/packaging/parsers/clawdbot.js +231 -0
- package/dist/src/packaging/parsers/cline.d.ts +26 -0
- package/dist/src/packaging/parsers/cline.js +185 -0
- package/dist/src/packaging/parsers/generic.d.ts +27 -0
- package/dist/src/packaging/parsers/generic.js +228 -0
- package/dist/src/packaging/parsers/goose.d.ts +26 -0
- package/dist/src/packaging/parsers/goose.js +175 -0
- package/dist/src/packaging/parsers/index.d.ts +11 -0
- package/{src/packaging/parsers/index.ts → dist/src/packaging/parsers/index.js} +1 -1
- package/dist/src/packaging/serializer.d.ts +108 -0
- package/dist/src/packaging/serializer.js +153 -0
- package/dist/src/packaging/types.d.ts +131 -0
- package/dist/src/packaging/types.js +5 -0
- package/dist/src/packaging/wasmedge-compiler.d.ts +76 -0
- package/dist/src/packaging/wasmedge-compiler.js +349 -0
- package/dist/src/security/index.d.ts +11 -0
- package/{src/security/index.ts → dist/src/security/index.js} +1 -4
- package/dist/src/security/multisig.d.ts +102 -0
- package/dist/src/security/multisig.js +283 -0
- package/dist/src/security/types.d.ts +207 -0
- package/dist/src/security/types.js +217 -0
- package/dist/src/security/vetkeys.d.ts +179 -0
- package/dist/src/security/vetkeys.js +499 -0
- package/dist/src/testing/index.d.ts +6 -0
- package/{src/testing/index.ts → dist/src/testing/index.js} +1 -1
- package/dist/src/testing/local-runner.d.ts +23 -0
- package/dist/src/testing/local-runner.js +226 -0
- package/dist/src/testing/types.d.ts +98 -0
- package/dist/src/testing/types.js +5 -0
- package/dist/src/wallet/cbor-serializer.d.ts +82 -0
- package/dist/src/wallet/cbor-serializer.js +282 -0
- package/dist/src/wallet/chain-dispatcher.d.ts +112 -0
- package/dist/src/wallet/chain-dispatcher.js +241 -0
- package/dist/src/wallet/cross-chain-aggregator.d.ts +119 -0
- package/dist/src/wallet/cross-chain-aggregator.js +235 -0
- package/dist/src/wallet/index.d.ts +16 -0
- package/dist/src/wallet/index.js +22 -0
- package/dist/src/wallet/key-derivation.d.ts +117 -0
- package/dist/src/wallet/key-derivation.js +325 -0
- package/dist/src/wallet/providers/base-provider.d.ts +111 -0
- package/dist/src/wallet/providers/base-provider.js +58 -0
- package/dist/src/wallet/providers/cketh-provider.d.ts +104 -0
- package/dist/src/wallet/providers/cketh-provider.js +343 -0
- package/dist/src/wallet/providers/polkadot-provider.d.ts +115 -0
- package/dist/src/wallet/providers/polkadot-provider.js +407 -0
- package/dist/src/wallet/providers/solana-provider.d.ts +102 -0
- package/dist/src/wallet/providers/solana-provider.js +393 -0
- package/dist/src/wallet/transaction-queue.d.ts +133 -0
- package/dist/src/wallet/transaction-queue.js +195 -0
- package/dist/src/wallet/types.d.ts +167 -0
- package/dist/src/wallet/types.js +5 -0
- package/dist/src/wallet/vetkeys-adapter.d.ts +134 -0
- package/dist/src/wallet/vetkeys-adapter.js +313 -0
- package/dist/src/wallet/wallet-manager.d.ts +202 -0
- package/dist/src/wallet/wallet-manager.js +451 -0
- package/dist/src/wallet/wallet-storage.d.ts +131 -0
- package/dist/src/wallet/wallet-storage.js +274 -0
- package/macos-wallet-app/AgentVaultWallet/App/AgentVaultWalletApp.swift +54 -0
- package/macos-wallet-app/AgentVaultWallet/Models/AppState.swift +102 -0
- package/macos-wallet-app/AgentVaultWallet/Models/Chain.swift +121 -0
- package/macos-wallet-app/AgentVaultWallet/Models/Wallet.swift +98 -0
- package/macos-wallet-app/AgentVaultWallet/Resources/AgentVaultWallet.entitlements +27 -0
- package/macos-wallet-app/AgentVaultWallet/Resources/Info.plist +69 -0
- package/macos-wallet-app/AgentVaultWallet/Services/BackupService.swift +270 -0
- package/macos-wallet-app/AgentVaultWallet/Services/CLIBridge.swift +367 -0
- package/macos-wallet-app/AgentVaultWallet/Services/CryptoService.swift +157 -0
- package/macos-wallet-app/AgentVaultWallet/Services/FileService.swift +120 -0
- package/macos-wallet-app/AgentVaultWallet/Services/KeychainService.swift +219 -0
- package/macos-wallet-app/AgentVaultWallet/Utilities/Constants.swift +44 -0
- package/macos-wallet-app/AgentVaultWallet/Utilities/Extensions.swift +115 -0
- package/macos-wallet-app/AgentVaultWallet/ViewModels/BackupViewModel.swift +237 -0
- package/macos-wallet-app/AgentVaultWallet/ViewModels/CreateWalletViewModel.swift +137 -0
- package/macos-wallet-app/AgentVaultWallet/ViewModels/ImportWalletViewModel.swift +179 -0
- package/macos-wallet-app/AgentVaultWallet/ViewModels/WalletStore.swift +286 -0
- package/macos-wallet-app/AgentVaultWallet/Views/Backup/BackupView.swift +235 -0
- package/macos-wallet-app/AgentVaultWallet/Views/Backup/RestoreView.swift +316 -0
- package/macos-wallet-app/AgentVaultWallet/Views/Create/CreateWalletFlow.swift +438 -0
- package/macos-wallet-app/AgentVaultWallet/Views/Import/ImportWalletFlow.swift +399 -0
- package/macos-wallet-app/AgentVaultWallet/Views/MainView.swift +134 -0
- package/macos-wallet-app/AgentVaultWallet/Views/Settings/SettingsView.swift +276 -0
- package/macos-wallet-app/AgentVaultWallet/Views/Sidebar/SidebarView.swift +133 -0
- package/macos-wallet-app/AgentVaultWallet/Views/Wallet/DashboardView.swift +233 -0
- package/macos-wallet-app/AgentVaultWallet/Views/Wallet/WalletDetailView.swift +281 -0
- package/macos-wallet-app/AgentVaultWallet/Views/Wallet/WalletListView.swift +280 -0
- package/macos-wallet-app/AgentVaultWallet/Views/Welcome/WelcomeView.swift +176 -0
- package/macos-wallet-app/Makefile +47 -0
- package/macos-wallet-app/project.yml +40 -0
- package/macos-wallet-app/setup.sh +73 -0
- package/package.json +10 -2
- package/backups/agentvault-backup-test-agent-2026-02-12T17-54-28-967Z.json +0 -28
- package/backups/agentvault-backup-test-agent-2026-02-12T17-54-29-032Z.backup +0 -1
- package/backups/agentvault-backup-test-agent-2026-02-12T17-57-42-373Z.json +0 -28
- package/backups/agentvault-backup-test-agent-2026-02-12T17-57-42-428Z.backup +0 -1
- package/backups/agentvault-backup-test-agent-2026-02-12T18-52-25-132Z.json +0 -28
- package/backups/agentvault-backup-test-agent-2026-02-12T18-52-25-247Z.backup +0 -1
- package/backups/agentvault-backup-test-agent-2026-02-12T18-54-09-216Z.json +0 -28
- package/backups/agentvault-backup-test-agent-2026-02-12T18-54-09-283Z.backup +0 -1
- package/backups/agentvault-backup-test-agent-2026-02-12T22-18-22-772Z.backup +0 -1
- package/backups/agentvault-backup-test-agent-2026-02-12T22-18-22-793Z.json +0 -28
- package/backups/test-backup.json +0 -28
- package/scripts/dev-dashboard.mjs +0 -84
- package/site/README.md +0 -63
- package/site/docusaurus.config.ts +0 -148
- package/site/package-lock.json +0 -18383
- package/site/package.json +0 -47
- package/site/sidebars.ts +0 -86
- package/site/static/.gitkeep +0 -0
- package/site/static/img/logo.svg +0 -28
- package/site/static/img/og-image.svg +0 -35
- package/src/archival/archive-manager.ts +0 -372
- package/src/archival/arweave-client.ts +0 -289
- package/src/backup/backup.ts +0 -315
- package/src/cloud-storage/cloud-sync.ts +0 -461
- package/src/cloud-storage/provider-detector.ts +0 -198
- package/src/debugging/logs.ts +0 -193
- package/src/debugging/types.ts +0 -100
- package/src/deployment/deployer.ts +0 -274
- package/src/deployment/icpClient.ts +0 -620
- package/src/deployment/index.ts +0 -46
- package/src/deployment/promotion.ts +0 -161
- package/src/deployment/types.ts +0 -111
- package/src/icp/batch.ts +0 -374
- package/src/icp/environment.ts +0 -215
- package/src/icp/icpcli.ts +0 -438
- package/src/icp/icwasm.ts +0 -222
- package/src/icp/index.ts +0 -94
- package/src/icp/optimization.ts +0 -242
- package/src/icp/tool-detector.ts +0 -110
- package/src/icp/types.ts +0 -574
- package/src/index.ts +0 -25
- package/src/inference/bittensor-client.ts +0 -304
- package/src/inference/inference-manager.ts +0 -327
- package/src/metrics/metrics.ts +0 -186
- package/src/monitoring/alerting.ts +0 -190
- package/src/monitoring/health.ts +0 -197
- package/src/monitoring/index.ts +0 -38
- package/src/monitoring/info.ts +0 -114
- package/src/monitoring/types.ts +0 -99
- package/src/network/network-config.ts +0 -129
- package/src/packaging/compiler.ts +0 -647
- package/src/packaging/config-persistence.ts +0 -135
- package/src/packaging/config-schemas.ts +0 -156
- package/src/packaging/detector.ts +0 -220
- package/src/packaging/index.ts +0 -90
- package/src/packaging/packager.ts +0 -118
- package/src/packaging/parsers/clawdbot.ts +0 -278
- package/src/packaging/parsers/cline.ts +0 -223
- package/src/packaging/parsers/generic.ts +0 -266
- package/src/packaging/parsers/goose.ts +0 -214
- package/src/packaging/serializer.ts +0 -260
- package/src/packaging/types.ts +0 -144
- package/src/packaging/wasmedge-compiler.ts +0 -406
- package/src/security/multisig.ts +0 -415
- package/src/security/types.ts +0 -416
- package/src/security/vetkeys.ts +0 -655
- package/src/testing/local-runner.ts +0 -264
- package/src/testing/types.ts +0 -104
- package/src/wallet/cbor-serializer.ts +0 -323
- package/src/wallet/chain-dispatcher.ts +0 -313
- package/src/wallet/cross-chain-aggregator.ts +0 -346
- package/src/wallet/index.ts +0 -76
- package/src/wallet/key-derivation.ts +0 -425
- package/src/wallet/providers/base-provider.ts +0 -154
- package/src/wallet/providers/cketh-provider.ts +0 -434
- package/src/wallet/providers/polkadot-provider.ts +0 -503
- package/src/wallet/providers/solana-provider.ts +0 -490
- package/src/wallet/transaction-queue.ts +0 -284
- package/src/wallet/types.ts +0 -178
- package/src/wallet/vetkeys-adapter.ts +0 -431
- package/src/wallet/wallet-manager.ts +0 -597
- package/src/wallet/wallet-storage.ts +0 -380
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wallet Storage Module
|
|
3
|
+
*
|
|
4
|
+
* Manages encrypted wallet persistence in ~/.agentvault/wallets/
|
|
5
|
+
* Provides per-agent wallet isolation and encryption.
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from 'node:fs';
|
|
8
|
+
import * as path from 'node:path';
|
|
9
|
+
import * as os from 'node:os';
|
|
10
|
+
import { serializeWallet, deserializeWallet, validateCborData, } from './cbor-serializer.js';
|
|
11
|
+
/**
|
|
12
|
+
* Get base directory for wallet storage
|
|
13
|
+
*
|
|
14
|
+
* @param options - Storage options
|
|
15
|
+
* @returns Wallet base directory
|
|
16
|
+
*/
|
|
17
|
+
export function getWalletBaseDir(options = {}) {
|
|
18
|
+
const baseDir = options.baseDir || path.join(os.homedir(), '.agentvault', 'wallets');
|
|
19
|
+
return baseDir;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Get agent-specific wallet directory
|
|
23
|
+
*
|
|
24
|
+
* @param agentId - Agent ID
|
|
25
|
+
* @param options - Storage options
|
|
26
|
+
* @returns Agent wallet directory
|
|
27
|
+
*/
|
|
28
|
+
export function getAgentWalletDir(agentId, options = {}) {
|
|
29
|
+
const baseDir = getWalletBaseDir(options);
|
|
30
|
+
return path.join(baseDir, agentId);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get wallet file path
|
|
34
|
+
*
|
|
35
|
+
* @param agentId - Agent ID
|
|
36
|
+
* @param walletId - Wallet ID
|
|
37
|
+
* @param options - Storage options
|
|
38
|
+
* @returns Wallet file path
|
|
39
|
+
*/
|
|
40
|
+
export function getWalletFilePath(agentId, walletId, options = {}) {
|
|
41
|
+
const agentDir = getAgentWalletDir(agentId, options);
|
|
42
|
+
return path.join(agentDir, `${walletId}.wallet`);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Ensure wallet directories exist
|
|
46
|
+
*
|
|
47
|
+
* @param agentId - Agent ID
|
|
48
|
+
* @param options - Storage options
|
|
49
|
+
*/
|
|
50
|
+
export function ensureWalletDirectories(agentId, options = {}) {
|
|
51
|
+
const agentDir = getAgentWalletDir(agentId, options);
|
|
52
|
+
if (!fs.existsSync(agentDir)) {
|
|
53
|
+
fs.mkdirSync(agentDir, { recursive: true });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Save wallet to encrypted storage
|
|
58
|
+
*
|
|
59
|
+
* @param wallet - Wallet data to save
|
|
60
|
+
* @param options - Storage options
|
|
61
|
+
*/
|
|
62
|
+
export function saveWallet(wallet, options = {}) {
|
|
63
|
+
// Ensure directories exist
|
|
64
|
+
ensureWalletDirectories(wallet.agentId, options);
|
|
65
|
+
// Serialize wallet to CBOR
|
|
66
|
+
const serialized = serializeWallet(wallet);
|
|
67
|
+
// Get wallet file path
|
|
68
|
+
const walletPath = getWalletFilePath(wallet.agentId, wallet.id, options);
|
|
69
|
+
// Write wallet file
|
|
70
|
+
fs.writeFileSync(walletPath, Buffer.from(serialized));
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Load wallet from storage
|
|
74
|
+
*
|
|
75
|
+
* @param agentId - Agent ID
|
|
76
|
+
* @param walletId - Wallet ID
|
|
77
|
+
* @param options - Storage options
|
|
78
|
+
* @returns Loaded wallet data or null if not found
|
|
79
|
+
*/
|
|
80
|
+
export function loadWallet(agentId, walletId, options = {}) {
|
|
81
|
+
const walletPath = getWalletFilePath(agentId, walletId, options);
|
|
82
|
+
// Check if wallet file exists
|
|
83
|
+
if (!fs.existsSync(walletPath)) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
// Read wallet file
|
|
87
|
+
const data = fs.readFileSync(walletPath);
|
|
88
|
+
// Validate CBOR data
|
|
89
|
+
if (!validateCborData(new Uint8Array(data))) {
|
|
90
|
+
throw new Error(`Invalid wallet data: ${walletId}`);
|
|
91
|
+
}
|
|
92
|
+
// Deserialize wallet
|
|
93
|
+
const wallet = deserializeWallet(new Uint8Array(data));
|
|
94
|
+
return wallet;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Delete wallet from storage
|
|
98
|
+
*
|
|
99
|
+
* @param agentId - Agent ID
|
|
100
|
+
* @param walletId - Wallet ID
|
|
101
|
+
* @param options - Storage options
|
|
102
|
+
*/
|
|
103
|
+
export function deleteWallet(agentId, walletId, options = {}) {
|
|
104
|
+
const walletPath = getWalletFilePath(agentId, walletId, options);
|
|
105
|
+
// Check if wallet file exists
|
|
106
|
+
if (fs.existsSync(walletPath)) {
|
|
107
|
+
fs.unlinkSync(walletPath);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* List all wallets for an agent
|
|
112
|
+
*
|
|
113
|
+
* @param agentId - Agent ID
|
|
114
|
+
* @param options - Storage options
|
|
115
|
+
* @returns Array of wallet IDs
|
|
116
|
+
*/
|
|
117
|
+
export function listWallets(agentId, options = {}) {
|
|
118
|
+
const agentDir = getAgentWalletDir(agentId, options);
|
|
119
|
+
// Check if agent directory exists
|
|
120
|
+
if (!fs.existsSync(agentDir)) {
|
|
121
|
+
return [];
|
|
122
|
+
}
|
|
123
|
+
// Read all wallet files
|
|
124
|
+
const files = fs.readdirSync(agentDir);
|
|
125
|
+
// Filter and extract wallet IDs
|
|
126
|
+
const walletIds = files
|
|
127
|
+
.filter((file) => file.endsWith('.wallet'))
|
|
128
|
+
.map((file) => file.replace('.wallet', ''));
|
|
129
|
+
return walletIds;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* List all agents with wallets
|
|
133
|
+
*
|
|
134
|
+
* @param options - Storage options
|
|
135
|
+
* @returns Array of agent IDs
|
|
136
|
+
*/
|
|
137
|
+
export function listAgents(options = {}) {
|
|
138
|
+
const baseDir = getWalletBaseDir(options);
|
|
139
|
+
// Check if base directory exists
|
|
140
|
+
if (!fs.existsSync(baseDir)) {
|
|
141
|
+
return [];
|
|
142
|
+
}
|
|
143
|
+
// Read all agent directories
|
|
144
|
+
const agents = fs.readdirSync(baseDir);
|
|
145
|
+
// Filter out non-directories
|
|
146
|
+
const agentIds = agents.filter((agent) => {
|
|
147
|
+
const agentPath = path.join(baseDir, agent);
|
|
148
|
+
return fs.statSync(agentPath).isDirectory();
|
|
149
|
+
});
|
|
150
|
+
return agentIds;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Check if wallet exists
|
|
154
|
+
*
|
|
155
|
+
* @param agentId - Agent ID
|
|
156
|
+
* @param walletId - Wallet ID
|
|
157
|
+
* @param options - Storage options
|
|
158
|
+
* @returns True if wallet exists
|
|
159
|
+
*/
|
|
160
|
+
export function walletExists(agentId, walletId, options = {}) {
|
|
161
|
+
const walletPath = getWalletFilePath(agentId, walletId, options);
|
|
162
|
+
return fs.existsSync(walletPath);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Get wallet file stats
|
|
166
|
+
*
|
|
167
|
+
* @param agentId - Agent ID
|
|
168
|
+
* @param walletId - Wallet ID
|
|
169
|
+
* @param options - Storage options
|
|
170
|
+
* @returns Wallet file stats or null if not found
|
|
171
|
+
*/
|
|
172
|
+
export function getWalletStats(agentId, walletId, options = {}) {
|
|
173
|
+
const walletPath = getWalletFilePath(agentId, walletId, options);
|
|
174
|
+
if (!fs.existsSync(walletPath)) {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
const stats = fs.statSync(walletPath);
|
|
178
|
+
return {
|
|
179
|
+
size: stats.size,
|
|
180
|
+
modified: stats.mtime,
|
|
181
|
+
created: stats.birthtime,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Backup all wallets for an agent
|
|
186
|
+
*
|
|
187
|
+
* @param agentId - Agent ID
|
|
188
|
+
* @param backupPath - Path to save backup
|
|
189
|
+
* @param options - Storage options
|
|
190
|
+
*/
|
|
191
|
+
export function backupWallets(agentId, backupPath, options = {}) {
|
|
192
|
+
const agentDir = getAgentWalletDir(agentId, options);
|
|
193
|
+
if (!fs.existsSync(agentDir)) {
|
|
194
|
+
throw new Error(`No wallets found for agent: ${agentId}`);
|
|
195
|
+
}
|
|
196
|
+
// Create backup directory
|
|
197
|
+
const backupDir = path.join(backupPath, agentId);
|
|
198
|
+
if (!fs.existsSync(backupDir)) {
|
|
199
|
+
fs.mkdirSync(backupDir, { recursive: true });
|
|
200
|
+
}
|
|
201
|
+
// Copy all wallet files
|
|
202
|
+
const files = fs.readdirSync(agentDir);
|
|
203
|
+
for (const file of files) {
|
|
204
|
+
const srcPath = path.join(agentDir, file);
|
|
205
|
+
const destPath = path.join(backupDir, file);
|
|
206
|
+
fs.copyFileSync(srcPath, destPath);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Restore wallets from backup
|
|
211
|
+
*
|
|
212
|
+
* @param agentId - Agent ID
|
|
213
|
+
* @param backupPath - Path to backup directory
|
|
214
|
+
* @param options - Storage options
|
|
215
|
+
*/
|
|
216
|
+
export function restoreWallets(agentId, backupPath, options = {}) {
|
|
217
|
+
const agentDir = getAgentWalletDir(agentId, options);
|
|
218
|
+
if (!fs.existsSync(backupPath)) {
|
|
219
|
+
throw new Error(`Backup directory not found: ${backupPath}`);
|
|
220
|
+
}
|
|
221
|
+
// Ensure agent directory exists
|
|
222
|
+
ensureWalletDirectories(agentId, options);
|
|
223
|
+
// Copy all wallet files from backup
|
|
224
|
+
const files = fs.readdirSync(backupPath);
|
|
225
|
+
for (const file of files) {
|
|
226
|
+
if (file.endsWith('.wallet')) {
|
|
227
|
+
const srcPath = path.join(backupPath, file);
|
|
228
|
+
const destPath = path.join(agentDir, file);
|
|
229
|
+
fs.copyFileSync(srcPath, destPath);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Clear all wallets for an agent
|
|
235
|
+
*
|
|
236
|
+
* @param agentId - Agent ID
|
|
237
|
+
* @param options - Storage options
|
|
238
|
+
*/
|
|
239
|
+
export function clearWallets(agentId, options = {}) {
|
|
240
|
+
const agentDir = getAgentWalletDir(agentId, options);
|
|
241
|
+
if (!fs.existsSync(agentDir)) {
|
|
242
|
+
return; // Nothing to clear
|
|
243
|
+
}
|
|
244
|
+
// Delete all wallet files
|
|
245
|
+
const files = fs.readdirSync(agentDir);
|
|
246
|
+
for (const file of files) {
|
|
247
|
+
const filePath = path.join(agentDir, file);
|
|
248
|
+
fs.unlinkSync(filePath);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Get total storage size for an agent
|
|
253
|
+
*
|
|
254
|
+
* @param agentId - Agent ID
|
|
255
|
+
* @param options - Storage options
|
|
256
|
+
* @returns Total size in bytes
|
|
257
|
+
*/
|
|
258
|
+
export function getWalletStorageSize(agentId, options = {}) {
|
|
259
|
+
const agentDir = getAgentWalletDir(agentId, options);
|
|
260
|
+
if (!fs.existsSync(agentDir)) {
|
|
261
|
+
return 0;
|
|
262
|
+
}
|
|
263
|
+
let totalSize = 0;
|
|
264
|
+
const files = fs.readdirSync(agentDir);
|
|
265
|
+
for (const file of files) {
|
|
266
|
+
const filePath = path.join(agentDir, file);
|
|
267
|
+
const stats = fs.statSync(filePath);
|
|
268
|
+
if (stats.isFile() && file.endsWith('.wallet')) {
|
|
269
|
+
totalSize += stats.size;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return totalSize;
|
|
273
|
+
}
|
|
274
|
+
//# sourceMappingURL=wallet-storage.js.map
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import SwiftUI
|
|
2
|
+
|
|
3
|
+
@main
|
|
4
|
+
struct AgentVaultWalletApp: App {
|
|
5
|
+
@StateObject private var walletStore = WalletStore()
|
|
6
|
+
@StateObject private var appState = AppState()
|
|
7
|
+
|
|
8
|
+
var body: some Scene {
|
|
9
|
+
WindowGroup {
|
|
10
|
+
MainView()
|
|
11
|
+
.environmentObject(walletStore)
|
|
12
|
+
.environmentObject(appState)
|
|
13
|
+
.frame(minWidth: 900, minHeight: 600)
|
|
14
|
+
.onAppear {
|
|
15
|
+
walletStore.loadWallets()
|
|
16
|
+
appState.checkEnvironment()
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
.windowStyle(.titleBar)
|
|
20
|
+
.windowToolbarStyle(.unified(showsTitle: true))
|
|
21
|
+
.defaultSize(width: 1100, height: 720)
|
|
22
|
+
.commands {
|
|
23
|
+
CommandGroup(replacing: .newItem) {
|
|
24
|
+
Button("New Wallet...") {
|
|
25
|
+
appState.activeSheet = .createWallet
|
|
26
|
+
}
|
|
27
|
+
.keyboardShortcut("n", modifiers: .command)
|
|
28
|
+
|
|
29
|
+
Button("Import Wallet...") {
|
|
30
|
+
appState.activeSheet = .importWallet
|
|
31
|
+
}
|
|
32
|
+
.keyboardShortcut("i", modifiers: .command)
|
|
33
|
+
|
|
34
|
+
Divider()
|
|
35
|
+
|
|
36
|
+
Button("Backup All Wallets...") {
|
|
37
|
+
appState.activeSheet = .backup
|
|
38
|
+
}
|
|
39
|
+
.keyboardShortcut("b", modifiers: [.command, .shift])
|
|
40
|
+
|
|
41
|
+
Button("Restore from Backup...") {
|
|
42
|
+
appState.activeSheet = .restore
|
|
43
|
+
}
|
|
44
|
+
.keyboardShortcut("r", modifiers: [.command, .shift])
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
Settings {
|
|
49
|
+
SettingsView()
|
|
50
|
+
.environmentObject(walletStore)
|
|
51
|
+
.environmentObject(appState)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import SwiftUI
|
|
2
|
+
import Combine
|
|
3
|
+
|
|
4
|
+
/// Sheets/modals the app can present
|
|
5
|
+
enum ActiveSheet: Identifiable {
|
|
6
|
+
case createWallet
|
|
7
|
+
case importWallet
|
|
8
|
+
case backup
|
|
9
|
+
case restore
|
|
10
|
+
case walletDetail(Wallet)
|
|
11
|
+
case mnemonicReveal(UUID)
|
|
12
|
+
|
|
13
|
+
var id: String {
|
|
14
|
+
switch self {
|
|
15
|
+
case .createWallet: return "create"
|
|
16
|
+
case .importWallet: return "import"
|
|
17
|
+
case .backup: return "backup"
|
|
18
|
+
case .restore: return "restore"
|
|
19
|
+
case .walletDetail(let w): return "detail-\(w.id)"
|
|
20
|
+
case .mnemonicReveal(let id): return "mnemonic-\(id)"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/// Navigation destinations for the sidebar
|
|
26
|
+
enum NavigationDestination: Hashable {
|
|
27
|
+
case dashboard
|
|
28
|
+
case walletList
|
|
29
|
+
case walletDetail(UUID)
|
|
30
|
+
case backup
|
|
31
|
+
case settings
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/// Alert types
|
|
35
|
+
struct AlertInfo: Identifiable {
|
|
36
|
+
let id = UUID()
|
|
37
|
+
let title: String
|
|
38
|
+
let message: String
|
|
39
|
+
let style: AlertStyle
|
|
40
|
+
|
|
41
|
+
enum AlertStyle {
|
|
42
|
+
case info, success, warning, error
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/// Environment health check results
|
|
47
|
+
struct EnvironmentStatus {
|
|
48
|
+
var nodeInstalled: Bool = false
|
|
49
|
+
var nodeVersion: String?
|
|
50
|
+
var npmInstalled: Bool = false
|
|
51
|
+
var agentVaultInstalled: Bool = false
|
|
52
|
+
var agentVaultVersion: String?
|
|
53
|
+
var isReady: Bool { nodeInstalled && npmInstalled }
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/// Global application state
|
|
57
|
+
@MainActor
|
|
58
|
+
final class AppState: ObservableObject {
|
|
59
|
+
@Published var activeSheet: ActiveSheet?
|
|
60
|
+
@Published var selectedDestination: NavigationDestination = .dashboard
|
|
61
|
+
@Published var alert: AlertInfo?
|
|
62
|
+
@Published var isFirstLaunch: Bool = true
|
|
63
|
+
@Published var environment = EnvironmentStatus()
|
|
64
|
+
@Published var isCheckingEnvironment: Bool = false
|
|
65
|
+
|
|
66
|
+
@AppStorage("hasCompletedOnboarding") var hasCompletedOnboarding: Bool = false
|
|
67
|
+
@AppStorage("agentVaultCLIPath") var cliPath: String = ""
|
|
68
|
+
@AppStorage("autoRefreshBalances") var autoRefreshBalances: Bool = true
|
|
69
|
+
@AppStorage("defaultChain") var defaultChain: String = Chain.ethereum.rawValue
|
|
70
|
+
|
|
71
|
+
private let cliBridge = CLIBridge()
|
|
72
|
+
|
|
73
|
+
init() {
|
|
74
|
+
isFirstLaunch = !hasCompletedOnboarding
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
func completeOnboarding() {
|
|
78
|
+
hasCompletedOnboarding = true
|
|
79
|
+
isFirstLaunch = false
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
func checkEnvironment() {
|
|
83
|
+
isCheckingEnvironment = true
|
|
84
|
+
Task {
|
|
85
|
+
let env = await cliBridge.checkEnvironment()
|
|
86
|
+
self.environment = env
|
|
87
|
+
self.isCheckingEnvironment = false
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
func showAlert(title: String, message: String, style: AlertInfo.AlertStyle = .info) {
|
|
92
|
+
alert = AlertInfo(title: title, message: message, style: style)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
func showError(_ message: String) {
|
|
96
|
+
showAlert(title: "Error", message: message, style: .error)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
func showSuccess(_ message: String) {
|
|
100
|
+
showAlert(title: "Success", message: message, style: .success)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import SwiftUI
|
|
2
|
+
|
|
3
|
+
/// Supported blockchain networks
|
|
4
|
+
enum Chain: String, CaseIterable, Identifiable, Codable {
|
|
5
|
+
case icp = "ICP"
|
|
6
|
+
case ethereum = "ETH"
|
|
7
|
+
case arweave = "AR"
|
|
8
|
+
|
|
9
|
+
var id: String { rawValue }
|
|
10
|
+
|
|
11
|
+
var displayName: String {
|
|
12
|
+
switch self {
|
|
13
|
+
case .icp: return "Internet Computer"
|
|
14
|
+
case .ethereum: return "Ethereum"
|
|
15
|
+
case .arweave: return "Arweave"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
var symbol: String { rawValue }
|
|
20
|
+
|
|
21
|
+
var iconName: String {
|
|
22
|
+
switch self {
|
|
23
|
+
case .icp: return "infinity"
|
|
24
|
+
case .ethereum: return "diamond.fill"
|
|
25
|
+
case .arweave: return "archivebox.fill"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
var color: Color {
|
|
30
|
+
switch self {
|
|
31
|
+
case .icp: return Color(red: 0.24, green: 0.07, blue: 0.53)
|
|
32
|
+
case .ethereum: return Color(red: 0.39, green: 0.46, blue: 0.84)
|
|
33
|
+
case .arweave: return Color(red: 0.13, green: 0.13, blue: 0.13)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
var gradientColors: [Color] {
|
|
38
|
+
switch self {
|
|
39
|
+
case .icp:
|
|
40
|
+
return [Color(red: 0.24, green: 0.07, blue: 0.53), Color(red: 0.58, green: 0.0, blue: 0.83)]
|
|
41
|
+
case .ethereum:
|
|
42
|
+
return [Color(red: 0.39, green: 0.46, blue: 0.84), Color(red: 0.25, green: 0.32, blue: 0.71)]
|
|
43
|
+
case .arweave:
|
|
44
|
+
return [Color(red: 0.13, green: 0.13, blue: 0.13), Color(red: 0.33, green: 0.33, blue: 0.33)]
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
var derivationPath: String {
|
|
49
|
+
switch self {
|
|
50
|
+
case .icp: return "m/44'/223'/0'/0/0"
|
|
51
|
+
case .ethereum: return "m/44'/60'/0'/0/0"
|
|
52
|
+
case .arweave: return "" // Arweave uses RSA JWK, not HD derivation
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/// What import methods are available for this chain
|
|
57
|
+
var supportedImportMethods: [ImportMethod] {
|
|
58
|
+
switch self {
|
|
59
|
+
case .icp: return [.mnemonic, .privateKey, .pemFile]
|
|
60
|
+
case .ethereum: return [.mnemonic, .privateKey, .keystoreJSON]
|
|
61
|
+
case .arweave: return [.jwkFile, .mnemonic]
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
var addressPrefix: String {
|
|
66
|
+
switch self {
|
|
67
|
+
case .icp: return "Principal"
|
|
68
|
+
case .ethereum: return "0x"
|
|
69
|
+
case .arweave: return "ar://"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
var explorerURLBase: String? {
|
|
74
|
+
switch self {
|
|
75
|
+
case .icp: return "https://dashboard.internetcomputer.org/account/"
|
|
76
|
+
case .ethereum: return "https://etherscan.io/address/"
|
|
77
|
+
case .arweave: return "https://viewblock.io/arweave/address/"
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/// Methods for importing an existing wallet
|
|
83
|
+
enum ImportMethod: String, CaseIterable, Identifiable {
|
|
84
|
+
case mnemonic = "mnemonic"
|
|
85
|
+
case privateKey = "private_key"
|
|
86
|
+
case pemFile = "pem_file"
|
|
87
|
+
case keystoreJSON = "keystore_json"
|
|
88
|
+
case jwkFile = "jwk_file"
|
|
89
|
+
|
|
90
|
+
var id: String { rawValue }
|
|
91
|
+
|
|
92
|
+
var displayName: String {
|
|
93
|
+
switch self {
|
|
94
|
+
case .mnemonic: return "Recovery Phrase"
|
|
95
|
+
case .privateKey: return "Private Key"
|
|
96
|
+
case .pemFile: return "PEM File"
|
|
97
|
+
case .keystoreJSON: return "Keystore JSON"
|
|
98
|
+
case .jwkFile: return "JWK Key File"
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
var description: String {
|
|
103
|
+
switch self {
|
|
104
|
+
case .mnemonic: return "Enter your 12 or 24-word recovery phrase"
|
|
105
|
+
case .privateKey: return "Paste your hex-encoded private key"
|
|
106
|
+
case .pemFile: return "Select a PEM identity file"
|
|
107
|
+
case .keystoreJSON: return "Select an Ethereum keystore JSON file"
|
|
108
|
+
case .jwkFile: return "Select an Arweave JWK wallet file"
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
var iconName: String {
|
|
113
|
+
switch self {
|
|
114
|
+
case .mnemonic: return "text.word.spacing"
|
|
115
|
+
case .privateKey: return "key.fill"
|
|
116
|
+
case .pemFile: return "doc.text.fill"
|
|
117
|
+
case .keystoreJSON: return "lock.doc.fill"
|
|
118
|
+
case .jwkFile: return "doc.badge.gearshape.fill"
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
/// Represents a single wallet managed by the application
|
|
4
|
+
struct Wallet: Identifiable, Codable, Hashable {
|
|
5
|
+
let id: UUID
|
|
6
|
+
var name: String
|
|
7
|
+
let chain: Chain
|
|
8
|
+
let address: String
|
|
9
|
+
let createdAt: Date
|
|
10
|
+
var lastAccessedAt: Date
|
|
11
|
+
|
|
12
|
+
/// Whether this wallet was imported (vs. created fresh)
|
|
13
|
+
let isImported: Bool
|
|
14
|
+
|
|
15
|
+
/// Optional balance cached from last refresh
|
|
16
|
+
var cachedBalance: String?
|
|
17
|
+
var balanceLastUpdated: Date?
|
|
18
|
+
|
|
19
|
+
/// Derivation path used (empty for Arweave JWK)
|
|
20
|
+
let derivationPath: String
|
|
21
|
+
|
|
22
|
+
/// Whether the mnemonic is stored in Keychain
|
|
23
|
+
let hasMnemonicBackup: Bool
|
|
24
|
+
|
|
25
|
+
init(
|
|
26
|
+
id: UUID = UUID(),
|
|
27
|
+
name: String,
|
|
28
|
+
chain: Chain,
|
|
29
|
+
address: String,
|
|
30
|
+
isImported: Bool = false,
|
|
31
|
+
derivationPath: String = "",
|
|
32
|
+
hasMnemonicBackup: Bool = false
|
|
33
|
+
) {
|
|
34
|
+
self.id = id
|
|
35
|
+
self.name = name
|
|
36
|
+
self.chain = chain
|
|
37
|
+
self.address = address
|
|
38
|
+
self.createdAt = Date()
|
|
39
|
+
self.lastAccessedAt = Date()
|
|
40
|
+
self.isImported = isImported
|
|
41
|
+
self.derivationPath = derivationPath
|
|
42
|
+
self.hasMnemonicBackup = hasMnemonicBackup
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/// Truncated address for display
|
|
46
|
+
var shortAddress: String {
|
|
47
|
+
if address.count > 20 {
|
|
48
|
+
let prefix = String(address.prefix(10))
|
|
49
|
+
let suffix = String(address.suffix(8))
|
|
50
|
+
return "\(prefix)...\(suffix)"
|
|
51
|
+
}
|
|
52
|
+
return address
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/// Explorer URL for this wallet's address
|
|
56
|
+
var explorerURL: URL? {
|
|
57
|
+
guard let base = chain.explorerURLBase else { return nil }
|
|
58
|
+
return URL(string: base + address)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/// Formatted balance string with symbol
|
|
62
|
+
var displayBalance: String {
|
|
63
|
+
guard let balance = cachedBalance else { return "—" }
|
|
64
|
+
return "\(balance) \(chain.symbol)"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/// Represents the result of a wallet generation or import
|
|
69
|
+
struct WalletCreationResult {
|
|
70
|
+
let wallet: Wallet
|
|
71
|
+
let mnemonic: String? // 12/24-word phrase (nil for JWK imports)
|
|
72
|
+
let privateKeyHex: String? // Hex-encoded private key
|
|
73
|
+
let jwkData: Data? // Arweave JWK JSON (only for Arweave)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/// Wallet metadata stored in the backup manifest
|
|
77
|
+
struct WalletBackupEntry: Codable, Identifiable {
|
|
78
|
+
let id: UUID
|
|
79
|
+
let name: String
|
|
80
|
+
let chain: Chain
|
|
81
|
+
let address: String
|
|
82
|
+
let createdAt: Date
|
|
83
|
+
let derivationPath: String
|
|
84
|
+
let hasMnemonicBackup: Bool
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/// Full backup file structure
|
|
88
|
+
struct WalletBackup: Codable {
|
|
89
|
+
let version: Int
|
|
90
|
+
let createdAt: Date
|
|
91
|
+
let appVersion: String
|
|
92
|
+
let wallets: [WalletBackupEntry]
|
|
93
|
+
let encryptedPayload: Data // AES-256-GCM encrypted wallet secrets
|
|
94
|
+
let salt: Data // PBKDF2 salt
|
|
95
|
+
let iv: Data // AES IV/nonce
|
|
96
|
+
|
|
97
|
+
static let currentVersion = 1
|
|
98
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
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
|
+
<!-- Hardened runtime -->
|
|
6
|
+
<key>com.apple.security.app-sandbox</key>
|
|
7
|
+
<false/>
|
|
8
|
+
|
|
9
|
+
<!-- Keychain access for storing wallet secrets -->
|
|
10
|
+
<key>com.apple.security.keychain-access-groups</key>
|
|
11
|
+
<array>
|
|
12
|
+
<string>$(AppIdentifierPrefix)com.agentvault.wallet</string>
|
|
13
|
+
</array>
|
|
14
|
+
|
|
15
|
+
<!-- Network access for balance checks and chain RPC calls -->
|
|
16
|
+
<key>com.apple.security.network.client</key>
|
|
17
|
+
<true/>
|
|
18
|
+
|
|
19
|
+
<!-- File access for backups and JWK/PEM imports -->
|
|
20
|
+
<key>com.apple.security.files.user-selected.read-write</key>
|
|
21
|
+
<true/>
|
|
22
|
+
|
|
23
|
+
<!-- Allow spawning Node.js / CLI processes -->
|
|
24
|
+
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
|
25
|
+
<true/>
|
|
26
|
+
</dict>
|
|
27
|
+
</plist>
|