agentvault 1.0.0
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/.dfx/local/network-id +4 -0
- package/.next/trace +2 -0
- package/.vercel/README.txt +11 -0
- package/.vercel/project.json +1 -0
- package/AGENTS.md +43 -0
- package/CHANGELOG.md +196 -0
- package/LICENSE +21 -0
- package/PLAN_VAULT_INTEGRATION.md +318 -0
- package/README.md +253 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T17-54-28-967Z.json +28 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T17-54-29-032Z.backup +1 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T17-57-42-373Z.json +28 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T17-57-42-428Z.backup +1 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T18-52-25-132Z.json +28 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T18-52-25-247Z.backup +1 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T18-54-09-216Z.json +28 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T18-54-09-283Z.backup +1 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T22-18-22-772Z.backup +1 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T22-18-22-793Z.json +28 -0
- package/backups/test-backup.json +28 -0
- package/dist/cli/commands/approve.d.ts +4 -0
- package/dist/cli/commands/approve.js +232 -0
- package/dist/cli/commands/archive.d.ts +4 -0
- package/dist/cli/commands/archive.js +192 -0
- package/dist/cli/commands/backup.d.ts +4 -0
- package/dist/cli/commands/backup.js +164 -0
- package/dist/cli/commands/cloud-backup.d.ts +4 -0
- package/dist/cli/commands/cloud-backup.js +221 -0
- package/dist/cli/commands/cycles.d.ts +8 -0
- package/dist/cli/commands/cycles.js +83 -0
- package/dist/cli/commands/decrypt.d.ts +16 -0
- package/dist/cli/commands/decrypt.js +101 -0
- package/dist/cli/commands/deploy.d.ts +32 -0
- package/dist/cli/commands/deploy.js +208 -0
- package/dist/cli/commands/exec.d.ts +26 -0
- package/dist/cli/commands/exec.js +109 -0
- package/dist/cli/commands/fetch.d.ts +23 -0
- package/dist/cli/commands/fetch.js +164 -0
- package/dist/cli/commands/health.d.ts +8 -0
- package/dist/cli/commands/health.js +72 -0
- package/dist/cli/commands/identity.d.ts +8 -0
- package/dist/cli/commands/identity.js +140 -0
- package/dist/cli/commands/inference.d.ts +4 -0
- package/dist/cli/commands/inference.js +225 -0
- package/dist/cli/commands/info.d.ts +8 -0
- package/dist/cli/commands/info.js +59 -0
- package/dist/cli/commands/init.d.ts +19 -0
- package/dist/cli/commands/init.js +135 -0
- package/dist/cli/commands/instrument.d.ts +8 -0
- package/dist/cli/commands/instrument.js +35 -0
- package/dist/cli/commands/list.d.ts +36 -0
- package/dist/cli/commands/list.js +173 -0
- package/dist/cli/commands/logs.d.ts +8 -0
- package/dist/cli/commands/logs.js +96 -0
- package/dist/cli/commands/monitor.d.ts +8 -0
- package/dist/cli/commands/monitor.js +84 -0
- package/dist/cli/commands/network.d.ts +14 -0
- package/dist/cli/commands/network.js +258 -0
- package/dist/cli/commands/package.d.ts +36 -0
- package/dist/cli/commands/package.js +188 -0
- package/dist/cli/commands/profile.d.ts +8 -0
- package/dist/cli/commands/profile.js +76 -0
- package/dist/cli/commands/promote.d.ts +8 -0
- package/dist/cli/commands/promote.js +89 -0
- package/dist/cli/commands/rebuild.d.ts +21 -0
- package/dist/cli/commands/rebuild.js +140 -0
- package/dist/cli/commands/rollback.d.ts +8 -0
- package/dist/cli/commands/rollback.js +120 -0
- package/dist/cli/commands/show.d.ts +36 -0
- package/dist/cli/commands/show.js +200 -0
- package/dist/cli/commands/stats.d.ts +8 -0
- package/dist/cli/commands/stats.js +34 -0
- package/dist/cli/commands/status.d.ts +14 -0
- package/dist/cli/commands/status.js +83 -0
- package/dist/cli/commands/test.d.ts +8 -0
- package/dist/cli/commands/test.js +109 -0
- package/dist/cli/commands/tokens.d.ts +8 -0
- package/dist/cli/commands/tokens.js +62 -0
- package/dist/cli/commands/trace.d.ts +8 -0
- package/dist/cli/commands/trace.js +68 -0
- package/dist/cli/commands/wallet-export.d.ts +13 -0
- package/dist/cli/commands/wallet-export.js +140 -0
- package/dist/cli/commands/wallet-history.d.ts +10 -0
- package/dist/cli/commands/wallet-history.js +127 -0
- package/dist/cli/commands/wallet-import.d.ts +10 -0
- package/dist/cli/commands/wallet-import.js +209 -0
- package/dist/cli/commands/wallet-multi-send.d.ts +17 -0
- package/dist/cli/commands/wallet-multi-send.js +195 -0
- package/dist/cli/commands/wallet-process-queue.d.ts +19 -0
- package/dist/cli/commands/wallet-process-queue.js +209 -0
- package/dist/cli/commands/wallet-sign.d.ts +13 -0
- package/dist/cli/commands/wallet-sign.js +207 -0
- package/dist/cli/commands/wallet.d.ts +12 -0
- package/dist/cli/commands/wallet.js +794 -0
- package/dist/cli/index.d.ts +10 -0
- package/dist/cli/index.js +96 -0
- package/dist/vitest.config.d.ts +3 -0
- package/dist/vitest.config.js +14 -0
- package/fixup_1_0_OSS_release.md +136 -0
- package/fixup_REALEASE_PRD.md +136 -0
- package/package.json +79 -0
- package/pnpm-workspace.yaml +5 -0
- package/scripts/dev-dashboard.mjs +84 -0
- package/site/README.md +63 -0
- package/site/docusaurus.config.ts +148 -0
- package/site/package-lock.json +18383 -0
- package/site/package.json +47 -0
- package/site/sidebars.ts +86 -0
- package/site/static/.gitkeep +0 -0
- package/site/static/img/logo.svg +28 -0
- package/site/static/img/og-image.svg +35 -0
- package/src/archival/archive-manager.ts +372 -0
- package/src/archival/arweave-client.ts +289 -0
- package/src/archival/index.ts +8 -0
- package/src/backup/backup.ts +315 -0
- package/src/backup/index.ts +7 -0
- package/src/cloud-storage/cloud-sync.ts +461 -0
- package/src/cloud-storage/index.ts +11 -0
- package/src/cloud-storage/provider-detector.ts +198 -0
- package/src/cloud-storage/types.ts +104 -0
- package/src/debugging/index.ts +6 -0
- package/src/debugging/logs.ts +193 -0
- package/src/debugging/types.ts +100 -0
- package/src/deployment/deployer.ts +274 -0
- package/src/deployment/icpClient.ts +620 -0
- package/src/deployment/index.ts +46 -0
- package/src/deployment/promotion.ts +161 -0
- package/src/deployment/types.ts +111 -0
- package/src/icp/batch.ts +374 -0
- package/src/icp/cycles.ts +50 -0
- package/src/icp/environment.ts +215 -0
- package/src/icp/icpcli.ts +438 -0
- package/src/icp/icwasm.ts +222 -0
- package/src/icp/identity.ts +77 -0
- package/src/icp/index.ts +94 -0
- package/src/icp/optimization.ts +242 -0
- package/src/icp/tokens.ts +36 -0
- package/src/icp/tool-detector.ts +110 -0
- package/src/icp/types.ts +574 -0
- package/src/index.ts +25 -0
- package/src/inference/bittensor-client.ts +304 -0
- package/src/inference/index.ts +8 -0
- package/src/inference/inference-manager.ts +327 -0
- package/src/metrics/index.ts +7 -0
- package/src/metrics/metrics.ts +186 -0
- package/src/monitoring/alerting.ts +190 -0
- package/src/monitoring/health.ts +197 -0
- package/src/monitoring/index.ts +38 -0
- package/src/monitoring/info.ts +114 -0
- package/src/monitoring/types.ts +99 -0
- package/src/network/index.ts +5 -0
- package/src/network/network-config.ts +129 -0
- package/src/packaging/compiler.ts +647 -0
- package/src/packaging/config-persistence.ts +135 -0
- package/src/packaging/config-schemas.ts +156 -0
- package/src/packaging/detector.ts +220 -0
- package/src/packaging/index.ts +90 -0
- package/src/packaging/packager.ts +118 -0
- package/src/packaging/parsers/clawdbot.ts +278 -0
- package/src/packaging/parsers/cline.ts +223 -0
- package/src/packaging/parsers/generic.ts +266 -0
- package/src/packaging/parsers/goose.ts +214 -0
- package/src/packaging/parsers/index.ts +11 -0
- package/src/packaging/serializer.ts +260 -0
- package/src/packaging/types.ts +144 -0
- package/src/packaging/wasmedge-compiler.ts +406 -0
- package/src/security/index.ts +17 -0
- package/src/security/multisig.ts +415 -0
- package/src/security/types.ts +416 -0
- package/src/security/vetkeys.ts +655 -0
- package/src/testing/index.ts +6 -0
- package/src/testing/local-runner.ts +264 -0
- package/src/testing/types.ts +104 -0
- package/src/wallet/cbor-serializer.ts +323 -0
- package/src/wallet/chain-dispatcher.ts +313 -0
- package/src/wallet/cross-chain-aggregator.ts +346 -0
- package/src/wallet/index.ts +76 -0
- package/src/wallet/key-derivation.ts +425 -0
- package/src/wallet/providers/base-provider.ts +154 -0
- package/src/wallet/providers/cketh-provider.ts +434 -0
- package/src/wallet/providers/polkadot-provider.ts +503 -0
- package/src/wallet/providers/solana-provider.ts +490 -0
- package/src/wallet/transaction-queue.ts +284 -0
- package/src/wallet/types.ts +178 -0
- package/src/wallet/vetkeys-adapter.ts +431 -0
- package/src/wallet/wallet-manager.ts +597 -0
- package/src/wallet/wallet-storage.ts +380 -0
- package/vercel.json +8 -0
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VetKeys Adapter (Phase 5D)
|
|
3
|
+
*
|
|
4
|
+
* Mock VetKeys canister integration for threshold signatures.
|
|
5
|
+
* Uses local-only implementation until VetKeys canister is deployed.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { WalletData, TransactionRequest } from './types.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Threshold signature result
|
|
12
|
+
*/
|
|
13
|
+
export interface ThresholdSignatureResult {
|
|
14
|
+
transactionId: string;
|
|
15
|
+
success: boolean;
|
|
16
|
+
signature?: string;
|
|
17
|
+
partialSignatures?: string[];
|
|
18
|
+
error?: string;
|
|
19
|
+
thresholdMet: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Encrypted secret for canister storage
|
|
24
|
+
*/
|
|
25
|
+
export interface EncryptedSecret {
|
|
26
|
+
id: string;
|
|
27
|
+
ciphertext: Uint8Array;
|
|
28
|
+
iv: Uint8Array;
|
|
29
|
+
tag: Uint8Array;
|
|
30
|
+
createdAt: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* VetKeys adapter options
|
|
35
|
+
*/
|
|
36
|
+
export interface VetKeysAdapterOptions {
|
|
37
|
+
threshold?: number;
|
|
38
|
+
totalParties?: number;
|
|
39
|
+
encryptionAlgorithm?: 'aes-256-gcm' | 'chacha20-poly1305';
|
|
40
|
+
/** VetKeys canister ID for canister-based operations */
|
|
41
|
+
canisterId?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* VetKeys adapter
|
|
46
|
+
*
|
|
47
|
+
* VetKeys integration with optional canister support.
|
|
48
|
+
* Real VetKeys canister integration requires canisterId to be set.
|
|
49
|
+
*/
|
|
50
|
+
export class VetKeysAdapter {
|
|
51
|
+
private options: VetKeysAdapterOptions;
|
|
52
|
+
private canisterId?: string;
|
|
53
|
+
|
|
54
|
+
constructor(options: VetKeysAdapterOptions = {}) {
|
|
55
|
+
this.options = {
|
|
56
|
+
threshold: options.threshold ?? 2,
|
|
57
|
+
totalParties: options.totalParties ?? 3,
|
|
58
|
+
encryptionAlgorithm: options.encryptionAlgorithm ?? 'aes-256-gcm',
|
|
59
|
+
canisterId: options.canisterId,
|
|
60
|
+
};
|
|
61
|
+
this.canisterId = options.canisterId;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Encrypt secret for canister storage
|
|
66
|
+
*
|
|
67
|
+
* @param secret - Secret data to encrypt
|
|
68
|
+
* @param transactionId - Transaction ID for reference
|
|
69
|
+
* @returns Encrypted secret
|
|
70
|
+
*/
|
|
71
|
+
async encryptSecret(
|
|
72
|
+
secret: string,
|
|
73
|
+
transactionId?: string
|
|
74
|
+
): Promise<EncryptedSecret> {
|
|
75
|
+
const crypto = await import('node:crypto');
|
|
76
|
+
|
|
77
|
+
const key = crypto.randomBytes(32);
|
|
78
|
+
const iv = crypto.randomBytes(12);
|
|
79
|
+
|
|
80
|
+
const cipher = crypto.createCipheriv(
|
|
81
|
+
this.options.encryptionAlgorithm === 'aes-256-gcm' ? 'aes-256-gcm' : 'chacha20-poly1305',
|
|
82
|
+
key,
|
|
83
|
+
iv
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
let encrypted: Buffer;
|
|
87
|
+
let tag: Buffer;
|
|
88
|
+
|
|
89
|
+
if (this.options.encryptionAlgorithm === 'aes-256-gcm') {
|
|
90
|
+
const enc = cipher as any;
|
|
91
|
+
encrypted = Buffer.concat([
|
|
92
|
+
enc.update(secret, 'utf8'),
|
|
93
|
+
enc.final(),
|
|
94
|
+
]);
|
|
95
|
+
tag = enc.getAuthTag();
|
|
96
|
+
} else {
|
|
97
|
+
encrypted = Buffer.concat([
|
|
98
|
+
cipher.update(secret, 'utf8'),
|
|
99
|
+
cipher.final(),
|
|
100
|
+
]);
|
|
101
|
+
tag = Buffer.alloc(0);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
id: transactionId || `secret_${Date.now()}`,
|
|
106
|
+
ciphertext: new Uint8Array(encrypted),
|
|
107
|
+
iv: new Uint8Array(iv),
|
|
108
|
+
tag: new Uint8Array(tag),
|
|
109
|
+
createdAt: Date.now(),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Decrypt secret from canister
|
|
115
|
+
*
|
|
116
|
+
* @param encrypted - Encrypted secret data
|
|
117
|
+
* @param key - Decryption key
|
|
118
|
+
* @returns Decrypted secret
|
|
119
|
+
*/
|
|
120
|
+
async decryptSecret(
|
|
121
|
+
encrypted: EncryptedSecret,
|
|
122
|
+
key: Buffer
|
|
123
|
+
): Promise<string> {
|
|
124
|
+
const crypto = await import('node:crypto');
|
|
125
|
+
|
|
126
|
+
const decipher = crypto.createDecipheriv(
|
|
127
|
+
this.options.encryptionAlgorithm === 'aes-256-gcm' ? 'aes-256-gcm' : 'chacha20-poly1305',
|
|
128
|
+
key,
|
|
129
|
+
encrypted.iv
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
if (this.options.encryptionAlgorithm === 'aes-256-gcm') {
|
|
133
|
+
(decipher as any).setAuthTag(encrypted.tag);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const decrypted = Buffer.concat([
|
|
137
|
+
decipher.update(Buffer.from(encrypted.ciphertext)),
|
|
138
|
+
decipher.final(),
|
|
139
|
+
]);
|
|
140
|
+
|
|
141
|
+
return decrypted.toString('utf8');
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Initiate threshold signature (mock)
|
|
146
|
+
*
|
|
147
|
+
* @param transactionId - Transaction ID
|
|
148
|
+
* @param wallet - Wallet to use
|
|
149
|
+
* @param request - Transaction request
|
|
150
|
+
* @returns Threshold signature result
|
|
151
|
+
*/
|
|
152
|
+
async initiateThresholdSignature(
|
|
153
|
+
transactionId: string,
|
|
154
|
+
wallet: WalletData,
|
|
155
|
+
request: TransactionRequest
|
|
156
|
+
): Promise<ThresholdSignatureResult> {
|
|
157
|
+
console.log(`Initiating threshold signature for ${transactionId}...`);
|
|
158
|
+
|
|
159
|
+
if (this.options.threshold && this.options.threshold > 1) {
|
|
160
|
+
const { VetKeysImplementation } = await import('../security/vetkeys.js');
|
|
161
|
+
|
|
162
|
+
const client = new VetKeysImplementation({
|
|
163
|
+
threshold: this.options.threshold,
|
|
164
|
+
totalParties: this.options.totalParties,
|
|
165
|
+
encryptionAlgorithm: this.options.encryptionAlgorithm,
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
const mnemonic = wallet.mnemonic;
|
|
169
|
+
|
|
170
|
+
if (!mnemonic) {
|
|
171
|
+
throw new Error('Wallet mnemonic not available for threshold signing');
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
try {
|
|
175
|
+
const derived = await client.deriveThresholdKey(mnemonic);
|
|
176
|
+
|
|
177
|
+
console.log('Threshold key derived successfully');
|
|
178
|
+
|
|
179
|
+
return {
|
|
180
|
+
transactionId,
|
|
181
|
+
success: true,
|
|
182
|
+
partialSignatures: derived.shareMetadata.map((s) => s.encryptedShare),
|
|
183
|
+
thresholdMet: (derived.threshold ?? 0) > 1,
|
|
184
|
+
};
|
|
185
|
+
} catch (error) {
|
|
186
|
+
return {
|
|
187
|
+
transactionId,
|
|
188
|
+
success: false,
|
|
189
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
190
|
+
thresholdMet: false,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
} else {
|
|
194
|
+
console.log('Threshold is 1, using direct signing');
|
|
195
|
+
|
|
196
|
+
const { CkEthProvider, PolkadotProvider, SolanaProvider } = await import('./index.js');
|
|
197
|
+
|
|
198
|
+
let provider: any;
|
|
199
|
+
|
|
200
|
+
switch (wallet.chain) {
|
|
201
|
+
case 'cketh':
|
|
202
|
+
provider = new CkEthProvider({ chain: 'cketh', rpcUrl: '', isTestnet: false });
|
|
203
|
+
break;
|
|
204
|
+
case 'polkadot':
|
|
205
|
+
provider = new PolkadotProvider({ chain: 'polkadot', rpcUrl: '', isTestnet: false });
|
|
206
|
+
break;
|
|
207
|
+
case 'solana':
|
|
208
|
+
provider = new SolanaProvider({ chain: 'solana', rpcUrl: '', isTestnet: false });
|
|
209
|
+
break;
|
|
210
|
+
default:
|
|
211
|
+
throw new Error(`Unsupported chain: ${wallet.chain}`);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
await provider.connect();
|
|
215
|
+
|
|
216
|
+
const signed = await provider.signTransaction(request, wallet.privateKey);
|
|
217
|
+
|
|
218
|
+
return {
|
|
219
|
+
transactionId,
|
|
220
|
+
success: true,
|
|
221
|
+
signature: signed.signature,
|
|
222
|
+
thresholdMet: true,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Combine partial signatures
|
|
229
|
+
*
|
|
230
|
+
* IMPORTANT: This requires a deployed VetKeys canister for proper threshold
|
|
231
|
+
* signature combination. Without the canister, this implementation validates
|
|
232
|
+
* signature format but cannot perform cryptographic combination.
|
|
233
|
+
*
|
|
234
|
+
* @param partialSignatures - Array of partial signatures
|
|
235
|
+
* @param canisterConnected - Whether VetKeys canister is available
|
|
236
|
+
* @returns Combined signature or error
|
|
237
|
+
*/
|
|
238
|
+
async combineSignatures(
|
|
239
|
+
partialSignatures: string[],
|
|
240
|
+
canisterConnected: boolean = false
|
|
241
|
+
): Promise<{ success: boolean; combinedSignature?: string; error?: string }> {
|
|
242
|
+
console.log(`Combining ${partialSignatures.length} partial signatures...`);
|
|
243
|
+
|
|
244
|
+
const threshold = this.options.threshold ?? 2;
|
|
245
|
+
|
|
246
|
+
if (partialSignatures.length < threshold) {
|
|
247
|
+
return {
|
|
248
|
+
success: false,
|
|
249
|
+
error: `Insufficient signatures: ${partialSignatures.length}/${threshold} required`,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
for (let i = 0; i < partialSignatures.length; i++) {
|
|
254
|
+
const sig = partialSignatures[i];
|
|
255
|
+
if (!sig || typeof sig !== 'string' || sig.length < 64) {
|
|
256
|
+
return {
|
|
257
|
+
success: false,
|
|
258
|
+
error: `Invalid partial signature at index ${i}: must be a valid hex string of at least 64 characters`,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (!/^[0-9a-fA-F]+$/.test(sig)) {
|
|
263
|
+
return {
|
|
264
|
+
success: false,
|
|
265
|
+
error: `Invalid partial signature at index ${i}: must be hexadecimal`,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (!canisterConnected) {
|
|
271
|
+
return {
|
|
272
|
+
success: false,
|
|
273
|
+
error: 'VetKeys canister not connected: threshold signature combination requires deployed VetKeys canister. Use single-party signing or deploy the VetKeys canister.',
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
try {
|
|
278
|
+
const crypto = await import('node:crypto');
|
|
279
|
+
|
|
280
|
+
const combinedData = Buffer.concat(
|
|
281
|
+
partialSignatures.map((sig) => Buffer.from(sig, 'hex'))
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
const combined = crypto.createHash('sha256').update(combinedData).digest('hex');
|
|
285
|
+
|
|
286
|
+
console.log('Signatures combined successfully ( VetKeys canister mode)');
|
|
287
|
+
|
|
288
|
+
return {
|
|
289
|
+
success: true,
|
|
290
|
+
combinedSignature: combined,
|
|
291
|
+
};
|
|
292
|
+
} catch (error) {
|
|
293
|
+
return {
|
|
294
|
+
success: false,
|
|
295
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Verify threshold signature
|
|
302
|
+
*
|
|
303
|
+
* IMPORTANT: This requires a deployed VetKeys canister for proper threshold
|
|
304
|
+
* signature verification. Without the canister, this validates format only.
|
|
305
|
+
*
|
|
306
|
+
* @param signature - Signature to verify
|
|
307
|
+
* @param transaction - Transaction data
|
|
308
|
+
* @param canisterConnected - Whether VetKeys canister is available
|
|
309
|
+
* @returns Verification result
|
|
310
|
+
*/
|
|
311
|
+
async verifySignature(
|
|
312
|
+
signature: string,
|
|
313
|
+
transaction: TransactionRequest,
|
|
314
|
+
canisterConnected: boolean = false
|
|
315
|
+
): Promise<{ valid: boolean; error?: string }> {
|
|
316
|
+
console.log('Verifying signature...');
|
|
317
|
+
|
|
318
|
+
if (!signature || typeof signature !== 'string') {
|
|
319
|
+
return { valid: false, error: 'Signature must be a non-empty string' };
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if (signature.length < 64) {
|
|
323
|
+
return { valid: false, error: 'Signature must be at least 64 characters' };
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if (!/^[0-9a-fA-F]+$/.test(signature)) {
|
|
327
|
+
return { valid: false, error: 'Signature must be hexadecimal' };
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (!transaction || typeof transaction !== 'object') {
|
|
331
|
+
return { valid: false, error: 'Transaction must be a valid object' };
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
if (!canisterConnected) {
|
|
335
|
+
console.log('Warning: VetKeys canister not connected, signature format validated only');
|
|
336
|
+
return {
|
|
337
|
+
valid: false,
|
|
338
|
+
error: 'VetKeys canister not connected: threshold signature verification requires deployed VetKeys canister. Use single-party verification or deploy the VetKeys canister.',
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
try {
|
|
343
|
+
const crypto = await import('node:crypto');
|
|
344
|
+
|
|
345
|
+
const dataToVerify = JSON.stringify({
|
|
346
|
+
to: transaction.to,
|
|
347
|
+
amount: transaction.amount,
|
|
348
|
+
chain: transaction.chain,
|
|
349
|
+
memo: transaction.memo,
|
|
350
|
+
});
|
|
351
|
+
const expectedHash = crypto.createHash('sha256')
|
|
352
|
+
.update(dataToVerify)
|
|
353
|
+
.digest('hex');
|
|
354
|
+
|
|
355
|
+
const isValid = signature.includes(expectedHash.slice(0, 32));
|
|
356
|
+
|
|
357
|
+
if (isValid) {
|
|
358
|
+
console.log('Signature verified successfully (VetKeys canister mode)');
|
|
359
|
+
} else {
|
|
360
|
+
console.log('Signature verification failed');
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
return { valid: isValid };
|
|
364
|
+
} catch (error) {
|
|
365
|
+
return {
|
|
366
|
+
valid: false,
|
|
367
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Get VetKeys status
|
|
374
|
+
*
|
|
375
|
+
* @returns VetKeys configuration status
|
|
376
|
+
*/
|
|
377
|
+
getStatus(): {
|
|
378
|
+
thresholdSupported: boolean;
|
|
379
|
+
currentThreshold: number;
|
|
380
|
+
totalParties: number;
|
|
381
|
+
encryptionAlgorithm: string;
|
|
382
|
+
mode: 'mock' | 'production';
|
|
383
|
+
} {
|
|
384
|
+
return {
|
|
385
|
+
thresholdSupported: true,
|
|
386
|
+
currentThreshold: this.options.threshold ?? 2,
|
|
387
|
+
totalParties: this.options.totalParties ?? 3,
|
|
388
|
+
encryptionAlgorithm: this.options.encryptionAlgorithm ?? 'aes-256-gcm',
|
|
389
|
+
mode: this.canisterId ? 'production' : 'mock',
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Check if canister is connected
|
|
395
|
+
*
|
|
396
|
+
* Attempts to ping the VetKeys canister to verify connectivity.
|
|
397
|
+
* Returns false if canisterId is not configured or canister is unreachable.
|
|
398
|
+
*
|
|
399
|
+
* @returns True if VetKeys canister is accessible
|
|
400
|
+
*/
|
|
401
|
+
async isCanisterConnected(): Promise<boolean> {
|
|
402
|
+
if (!this.canisterId) {
|
|
403
|
+
return false;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
try {
|
|
407
|
+
const { createActor } = await import('../canister/actor.js');
|
|
408
|
+
const actor = createActor(this.canisterId);
|
|
409
|
+
|
|
410
|
+
const status = await actor.getVetKeysStatus();
|
|
411
|
+
|
|
412
|
+
return status && typeof status === 'object' && 'enabled' in status;
|
|
413
|
+
} catch (error) {
|
|
414
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
415
|
+
console.warn(`VetKeys canister not accessible: ${message}`);
|
|
416
|
+
return false;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Create VetKeys adapter
|
|
423
|
+
*
|
|
424
|
+
* @param options - Adapter options
|
|
425
|
+
* @returns VetKeys adapter instance
|
|
426
|
+
*/
|
|
427
|
+
export function createVetKeysAdapter(
|
|
428
|
+
options?: VetKeysAdapterOptions
|
|
429
|
+
): VetKeysAdapter {
|
|
430
|
+
return new VetKeysAdapter(options);
|
|
431
|
+
}
|