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,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wallet Module
|
|
3
|
+
*
|
|
4
|
+
* Complete wallet management system for ckETH, Polkadot, and Solana.
|
|
5
|
+
* Provides per-agent wallet isolation, encryption, and CBOR serialization.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Types
|
|
9
|
+
export * from './types.js';
|
|
10
|
+
|
|
11
|
+
// CBOR Serialization
|
|
12
|
+
export {
|
|
13
|
+
serializeWallet,
|
|
14
|
+
deserializeWallet,
|
|
15
|
+
serializeTransaction,
|
|
16
|
+
deserializeTransaction,
|
|
17
|
+
serializeTransactionRequest,
|
|
18
|
+
deserializeTransactionRequest,
|
|
19
|
+
serializeSignedTransaction,
|
|
20
|
+
deserializeSignedTransaction,
|
|
21
|
+
validateCborData,
|
|
22
|
+
} from './cbor-serializer.js';
|
|
23
|
+
|
|
24
|
+
// Wallet Storage
|
|
25
|
+
export {
|
|
26
|
+
getWalletBaseDir,
|
|
27
|
+
getAgentWalletDir,
|
|
28
|
+
getWalletFilePath,
|
|
29
|
+
ensureWalletDirectories,
|
|
30
|
+
saveWallet,
|
|
31
|
+
loadWallet,
|
|
32
|
+
deleteWallet,
|
|
33
|
+
listWallets,
|
|
34
|
+
listAgents,
|
|
35
|
+
walletExists,
|
|
36
|
+
getWalletStats,
|
|
37
|
+
backupWallets,
|
|
38
|
+
restoreWallets,
|
|
39
|
+
clearWallets,
|
|
40
|
+
getWalletStorageSize,
|
|
41
|
+
} from './wallet-storage.js';
|
|
42
|
+
|
|
43
|
+
// Key Derivation
|
|
44
|
+
export {
|
|
45
|
+
parseDerivationPath,
|
|
46
|
+
buildDerivationPath,
|
|
47
|
+
validateSeedPhrase,
|
|
48
|
+
generateSeedFromMnemonic,
|
|
49
|
+
generateMnemonic,
|
|
50
|
+
getDefaultDerivationPath,
|
|
51
|
+
deriveWalletKey,
|
|
52
|
+
} from './key-derivation.js';
|
|
53
|
+
|
|
54
|
+
// Wallet Manager
|
|
55
|
+
export {
|
|
56
|
+
createWallet,
|
|
57
|
+
importWalletFromPrivateKey,
|
|
58
|
+
importWalletFromSeed,
|
|
59
|
+
importWalletFromMnemonic,
|
|
60
|
+
generateWallet,
|
|
61
|
+
getWallet,
|
|
62
|
+
listAgentWallets,
|
|
63
|
+
hasWallet,
|
|
64
|
+
removeWallet,
|
|
65
|
+
clearAgentWallets,
|
|
66
|
+
cacheWalletConnection,
|
|
67
|
+
getCachedConnection,
|
|
68
|
+
clearCachedConnection,
|
|
69
|
+
validateSeedPhraseWrapper,
|
|
70
|
+
} from './wallet-manager.js';
|
|
71
|
+
|
|
72
|
+
// Providers
|
|
73
|
+
export { BaseWalletProvider } from './providers/base-provider.js';
|
|
74
|
+
export { CkEthProvider } from './providers/cketh-provider.js';
|
|
75
|
+
export { PolkadotProvider } from './providers/polkadot-provider.js';
|
|
76
|
+
export { SolanaProvider } from './providers/solana-provider.js';
|
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Key Derivation Module
|
|
3
|
+
*
|
|
4
|
+
* Implements BIP39 seed phrase derivation for wallet keys.
|
|
5
|
+
* Supports multiple derivation paths for different blockchains.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import * as bip39 from 'bip39';
|
|
9
|
+
import * as crypto from 'node:crypto';
|
|
10
|
+
import { encodeAddress } from '@polkadot/util-crypto';
|
|
11
|
+
import type { WalletCreationMethod } from './types.js';
|
|
12
|
+
import { Keypair } from '@solana/web3.js';
|
|
13
|
+
import { HDNodeWallet, SigningKey, computeAddress } from 'ethers';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Derivation path components
|
|
17
|
+
*/
|
|
18
|
+
export interface DerivationPathComponents {
|
|
19
|
+
/** Purpose (e.g., 44' for BIP44) */
|
|
20
|
+
purpose: number;
|
|
21
|
+
/** Coin type (e.g., 60' for ETH, 0' for BTC) */
|
|
22
|
+
coinType: number;
|
|
23
|
+
/** Account index */
|
|
24
|
+
account: number;
|
|
25
|
+
/** Change index (0 for external, 1 for internal) */
|
|
26
|
+
change: number;
|
|
27
|
+
/** Address index */
|
|
28
|
+
index: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Derived key information
|
|
33
|
+
*/
|
|
34
|
+
export interface DerivedKey {
|
|
35
|
+
/** Private key (hex) */
|
|
36
|
+
privateKey: string;
|
|
37
|
+
/** Public key (hex) */
|
|
38
|
+
publicKey: string;
|
|
39
|
+
/** Address (chain-specific format) */
|
|
40
|
+
address: string;
|
|
41
|
+
/** Derivation path used */
|
|
42
|
+
derivationPath: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Default derivation paths for different chains
|
|
47
|
+
*/
|
|
48
|
+
const DEFAULT_DERIVATION_PATHS: Record<string, string> = {
|
|
49
|
+
// Ethereum / ckETH (BIP44)
|
|
50
|
+
eth: "m/44'/60'/0'/0/0",
|
|
51
|
+
// Polkadot (Substrate)
|
|
52
|
+
polkadot: "//hard//stash",
|
|
53
|
+
// Solana (BIP44)
|
|
54
|
+
solana: "m/44'/501'/0'/0'/0'",
|
|
55
|
+
// Bitcoin
|
|
56
|
+
btc: "m/44'/0'/0'/0/0",
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Parse derivation path string
|
|
61
|
+
*
|
|
62
|
+
* @param path - Derivation path string (e.g., "m/44'/60'/0'/0/0")
|
|
63
|
+
* @returns Parsed path components
|
|
64
|
+
*/
|
|
65
|
+
export function parseDerivationPath(path: string): DerivationPathComponents {
|
|
66
|
+
const parts = path.split('/');
|
|
67
|
+
|
|
68
|
+
if (parts[0] !== 'm') {
|
|
69
|
+
throw new Error('Invalid derivation path: must start with "m"');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const components: DerivationPathComponents = {
|
|
73
|
+
purpose: 0,
|
|
74
|
+
coinType: 0,
|
|
75
|
+
account: 0,
|
|
76
|
+
change: 0,
|
|
77
|
+
index: 0,
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
for (let i = 1; i < parts.length; i++) {
|
|
81
|
+
const part = parts[i]?.replace(/'/g, '') || '0';
|
|
82
|
+
const num = parseInt(part, 10);
|
|
83
|
+
|
|
84
|
+
switch (i) {
|
|
85
|
+
case 1:
|
|
86
|
+
components.purpose = num;
|
|
87
|
+
break;
|
|
88
|
+
case 2:
|
|
89
|
+
components.coinType = num;
|
|
90
|
+
break;
|
|
91
|
+
case 3:
|
|
92
|
+
components.account = num;
|
|
93
|
+
break;
|
|
94
|
+
case 4:
|
|
95
|
+
components.change = num;
|
|
96
|
+
break;
|
|
97
|
+
case 5:
|
|
98
|
+
components.index = num;
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return components;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Build derivation path from components
|
|
108
|
+
*
|
|
109
|
+
* @param components - Path components
|
|
110
|
+
* @returns Derivation path string
|
|
111
|
+
*/
|
|
112
|
+
export function buildDerivationPath(
|
|
113
|
+
components: DerivationPathComponents
|
|
114
|
+
): string {
|
|
115
|
+
const parts = ['m'];
|
|
116
|
+
|
|
117
|
+
parts.push(`${components.purpose}'`);
|
|
118
|
+
parts.push(`${components.coinType}'`);
|
|
119
|
+
parts.push(`${components.account}'`);
|
|
120
|
+
parts.push(`${components.change}`);
|
|
121
|
+
parts.push(`${components.index}`);
|
|
122
|
+
|
|
123
|
+
return parts.join('/');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Validate seed phrase (BIP39)
|
|
128
|
+
*
|
|
129
|
+
* @param seedPhrase - Seed phrase to validate
|
|
130
|
+
* @returns True if valid BIP39 phrase
|
|
131
|
+
*/
|
|
132
|
+
export function validateSeedPhrase(seedPhrase: string): boolean {
|
|
133
|
+
return bip39.validateMnemonic(seedPhrase);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Generate seed from seed phrase
|
|
138
|
+
*
|
|
139
|
+
* @param seedPhrase - BIP39 seed phrase
|
|
140
|
+
* @param passphrase - Optional passphrase (default empty)
|
|
141
|
+
* @returns Seed bytes
|
|
142
|
+
*/
|
|
143
|
+
export function generateSeedFromMnemonic(
|
|
144
|
+
seedPhrase: string,
|
|
145
|
+
passphrase: string = ''
|
|
146
|
+
): Buffer {
|
|
147
|
+
return bip39.mnemonicToSeedSync(seedPhrase, passphrase);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Generate mnemonic from entropy
|
|
152
|
+
*
|
|
153
|
+
* @param strength - Entropy strength in bits (128, 160, 192, 224, 256)
|
|
154
|
+
* @param rng - Optional RNG function
|
|
155
|
+
* @returns BIP39 mnemonic phrase
|
|
156
|
+
*/
|
|
157
|
+
export function generateMnemonic(
|
|
158
|
+
strength: number = 128,
|
|
159
|
+
rng?: (size: number) => Buffer
|
|
160
|
+
): string {
|
|
161
|
+
return bip39.generateMnemonic(strength, rng);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Derive key from seed using HMAC-SHA512
|
|
166
|
+
*
|
|
167
|
+
* @param seed - Seed bytes
|
|
168
|
+
* @param derivationPath - Derivation path
|
|
169
|
+
* @returns Derived key (32 bytes private, 32 bytes chain code)
|
|
170
|
+
*/
|
|
171
|
+
function deriveKeyFromSeed(
|
|
172
|
+
seed: Buffer,
|
|
173
|
+
derivationPath: string
|
|
174
|
+
): { privateKey: Buffer; chainCode: Buffer } {
|
|
175
|
+
const parts = parseDerivationPath(derivationPath);
|
|
176
|
+
|
|
177
|
+
let key: Buffer = seed.slice(0, 32);
|
|
178
|
+
let chainCode: Buffer = seed.slice(32, 64);
|
|
179
|
+
|
|
180
|
+
for (const part of [parts.purpose, parts.coinType, parts.account, parts.change, parts.index]) {
|
|
181
|
+
const isHardened = part >= 0x80000000;
|
|
182
|
+
|
|
183
|
+
const data = Buffer.concat([
|
|
184
|
+
key,
|
|
185
|
+
Buffer.from([0x00]),
|
|
186
|
+
Buffer.alloc(4),
|
|
187
|
+
]);
|
|
188
|
+
|
|
189
|
+
data.writeUint32BE(isHardened ? part : part + 0x80000000, 4);
|
|
190
|
+
|
|
191
|
+
const hmac = crypto.createHmac('sha512', chainCode);
|
|
192
|
+
hmac.update(data);
|
|
193
|
+
|
|
194
|
+
const result = hmac.digest();
|
|
195
|
+
key = result.slice(0, 32);
|
|
196
|
+
chainCode = result.slice(32, 64);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return { privateKey: key, chainCode };
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Derive Ethereum-compatible key
|
|
204
|
+
*
|
|
205
|
+
* @param seed - Seed bytes
|
|
206
|
+
* @param derivationPath - Derivation path (default: "m/44'/60'/0'/0/0")
|
|
207
|
+
* @returns Derived key with ETH address
|
|
208
|
+
*/
|
|
209
|
+
export function deriveEthKey(
|
|
210
|
+
seed: Buffer,
|
|
211
|
+
derivationPath: string = DEFAULT_DERIVATION_PATHS.eth!
|
|
212
|
+
): DerivedKey {
|
|
213
|
+
const root = HDNodeWallet.fromSeed(seed);
|
|
214
|
+
const node = root.derivePath(derivationPath);
|
|
215
|
+
|
|
216
|
+
const privateKeyHex = stripHexPrefix(node.privateKey);
|
|
217
|
+
const publicKeyHex = stripHexPrefix(SigningKey.computePublicKey(node.privateKey, false));
|
|
218
|
+
const address = node.address;
|
|
219
|
+
|
|
220
|
+
return {
|
|
221
|
+
privateKey: privateKeyHex,
|
|
222
|
+
publicKey: publicKeyHex,
|
|
223
|
+
address,
|
|
224
|
+
derivationPath,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Derive Polkadot-compatible key
|
|
230
|
+
*
|
|
231
|
+
* Uses SR25519 for key derivation and SS58 for address encoding.
|
|
232
|
+
*
|
|
233
|
+
* @param seed - Seed bytes
|
|
234
|
+
* @param derivationPath - Derivation path (default: "//hard//stash")
|
|
235
|
+
* @returns Derived key with Polkadot address
|
|
236
|
+
*/
|
|
237
|
+
export function derivePolkadotKey(
|
|
238
|
+
seed: Buffer,
|
|
239
|
+
derivationPath: string = DEFAULT_DERIVATION_PATHS.polkadot!
|
|
240
|
+
): DerivedKey {
|
|
241
|
+
const privateKey = seed.slice(0, 32);
|
|
242
|
+
|
|
243
|
+
const publicKey = derivePublicKey(privateKey);
|
|
244
|
+
|
|
245
|
+
const address = derivePolkadotAddress(Buffer.from(publicKey));
|
|
246
|
+
|
|
247
|
+
return {
|
|
248
|
+
privateKey: privateKey.toString('hex'),
|
|
249
|
+
publicKey: publicKey.toString('hex'),
|
|
250
|
+
address,
|
|
251
|
+
derivationPath,
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Derive Solana-compatible key
|
|
257
|
+
*
|
|
258
|
+
* @param seed - Seed bytes
|
|
259
|
+
* @param derivationPath - Derivation path (default: "m/44'/501'/0'/0'/0'")
|
|
260
|
+
* @returns Derived key with Solana address
|
|
261
|
+
*/
|
|
262
|
+
export function deriveSolanaKey(
|
|
263
|
+
seed: Buffer,
|
|
264
|
+
derivationPath: string = DEFAULT_DERIVATION_PATHS.solana!
|
|
265
|
+
): DerivedKey {
|
|
266
|
+
// Use BIP44 derivation for Solana
|
|
267
|
+
const derived = deriveKeyFromSeed(seed, derivationPath);
|
|
268
|
+
|
|
269
|
+
if (!derived || !derived.privateKey) {
|
|
270
|
+
throw new Error('Failed to derive Solana key');
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Solana uses Ed25519, takes first 32 bytes as seed material
|
|
274
|
+
const privateKeyBytes = derived.privateKey.subarray(0, 32);
|
|
275
|
+
|
|
276
|
+
// Use Solana's Keypair for proper Ed25519 key generation
|
|
277
|
+
const keypair = Keypair.fromSeed(privateKeyBytes);
|
|
278
|
+
|
|
279
|
+
return {
|
|
280
|
+
privateKey: Buffer.from(keypair.secretKey).toString('hex'),
|
|
281
|
+
publicKey: Buffer.from(keypair.publicKey.toBytes()).toString('hex'),
|
|
282
|
+
address: keypair.publicKey.toBase58(),
|
|
283
|
+
derivationPath,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Derive public key from private key (simplified)
|
|
289
|
+
*
|
|
290
|
+
* @param privateKey - Private key bytes
|
|
291
|
+
* @returns Public key bytes
|
|
292
|
+
*/
|
|
293
|
+
function derivePublicKey(privateKey: Buffer): Buffer {
|
|
294
|
+
// Default to secp256k1 for generic key derivation paths.
|
|
295
|
+
// Chain-specific derivation functions should prefer their own primitives.
|
|
296
|
+
const privateKeyHex = `0x${privateKey.toString('hex')}`;
|
|
297
|
+
const publicKeyHex = SigningKey.computePublicKey(privateKeyHex, false);
|
|
298
|
+
return Buffer.from(stripHexPrefix(publicKeyHex), 'hex');
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Derive Polkadot address from public key
|
|
303
|
+
*
|
|
304
|
+
* Uses proper SS58 encoding with Polkadot prefix (0).
|
|
305
|
+
*
|
|
306
|
+
* @param publicKey - Public key bytes (32 bytes for SR25519/ED25519)
|
|
307
|
+
* @returns Polkadot address (SS58 format)
|
|
308
|
+
*/
|
|
309
|
+
function derivePolkadotAddress(publicKey: Buffer): string {
|
|
310
|
+
if (publicKey.length !== 32) {
|
|
311
|
+
throw new Error(`Invalid public key length: expected 32 bytes, got ${publicKey.length}`);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
try {
|
|
315
|
+
const address = encodeAddress(publicKey, 0);
|
|
316
|
+
return address;
|
|
317
|
+
} catch (error) {
|
|
318
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
319
|
+
throw new Error(`Failed to derive Polkadot address: ${message}`);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Get default derivation path for chain
|
|
325
|
+
*
|
|
326
|
+
* @param chain - Blockchain type
|
|
327
|
+
* @returns Default derivation path
|
|
328
|
+
*/
|
|
329
|
+
export function getDefaultDerivationPath(chain: string): string {
|
|
330
|
+
switch (chain.toLowerCase()) {
|
|
331
|
+
case 'cketh':
|
|
332
|
+
case 'ethereum':
|
|
333
|
+
case 'eth':
|
|
334
|
+
return DEFAULT_DERIVATION_PATHS.eth!;
|
|
335
|
+
case 'polkadot':
|
|
336
|
+
case 'dot':
|
|
337
|
+
return DEFAULT_DERIVATION_PATHS.polkadot!;
|
|
338
|
+
case 'solana':
|
|
339
|
+
case 'sol':
|
|
340
|
+
return DEFAULT_DERIVATION_PATHS.solana!;
|
|
341
|
+
default:
|
|
342
|
+
return DEFAULT_DERIVATION_PATHS.eth!;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Derive wallet key based on creation method
|
|
348
|
+
*
|
|
349
|
+
* @param method - Wallet creation method
|
|
350
|
+
* @param seedPhrase - Seed phrase (for 'seed' and 'mnemonic' methods)
|
|
351
|
+
* @param privateKey - Private key (for 'private-key' method)
|
|
352
|
+
* @param derivationPath - Custom derivation path
|
|
353
|
+
* @param chain - Blockchain type
|
|
354
|
+
* @returns Derived key information
|
|
355
|
+
*/
|
|
356
|
+
export function deriveWalletKey(
|
|
357
|
+
method: WalletCreationMethod,
|
|
358
|
+
seedPhrase?: string,
|
|
359
|
+
privateKey?: string,
|
|
360
|
+
derivationPath?: string,
|
|
361
|
+
chain: string = 'cketh'
|
|
362
|
+
): DerivedKey {
|
|
363
|
+
const effectiveDerivationPath =
|
|
364
|
+
derivationPath || getDefaultDerivationPath(chain);
|
|
365
|
+
|
|
366
|
+
if (method === 'private-key' && privateKey) {
|
|
367
|
+
const normalizedPrivateKey = normalizePrivateKey(privateKey);
|
|
368
|
+
const privateKeyBuffer = Buffer.from(stripHexPrefix(normalizedPrivateKey), 'hex');
|
|
369
|
+
|
|
370
|
+
let address: string;
|
|
371
|
+
let publicKeyHex: string;
|
|
372
|
+
|
|
373
|
+
if (chain === 'cketh' || chain === 'ethereum') {
|
|
374
|
+
publicKeyHex = stripHexPrefix(SigningKey.computePublicKey(normalizedPrivateKey, false));
|
|
375
|
+
address = computeAddress(normalizedPrivateKey);
|
|
376
|
+
} else if (chain === 'polkadot') {
|
|
377
|
+
const publicKey = derivePublicKey(privateKeyBuffer);
|
|
378
|
+
publicKeyHex = publicKey.toString('hex');
|
|
379
|
+
address = derivePolkadotAddress(publicKey);
|
|
380
|
+
} else {
|
|
381
|
+
// Solana accepts either 32-byte seed or 64-byte secret key material.
|
|
382
|
+
const keypair = privateKeyBuffer.length >= 64
|
|
383
|
+
? Keypair.fromSecretKey(privateKeyBuffer.subarray(0, 64))
|
|
384
|
+
: Keypair.fromSeed(privateKeyBuffer.subarray(0, 32));
|
|
385
|
+
publicKeyHex = Buffer.from(keypair.publicKey.toBytes()).toString('hex');
|
|
386
|
+
address = keypair.publicKey.toBase58();
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
return {
|
|
390
|
+
privateKey: stripHexPrefix(normalizedPrivateKey),
|
|
391
|
+
publicKey: publicKeyHex,
|
|
392
|
+
address,
|
|
393
|
+
derivationPath: effectiveDerivationPath,
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
if ((method === 'seed' || method === 'mnemonic') && seedPhrase) {
|
|
398
|
+
// Derive from seed phrase
|
|
399
|
+
if (!validateSeedPhrase(seedPhrase)) {
|
|
400
|
+
throw new Error('Invalid seed phrase');
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
const seed = generateSeedFromMnemonic(seedPhrase);
|
|
404
|
+
|
|
405
|
+
if (chain === 'cketh' || chain === 'ethereum') {
|
|
406
|
+
return deriveEthKey(seed, effectiveDerivationPath);
|
|
407
|
+
} else if (chain === 'polkadot') {
|
|
408
|
+
return derivePolkadotKey(seed, effectiveDerivationPath);
|
|
409
|
+
} else if (chain === 'solana') {
|
|
410
|
+
return deriveSolanaKey(seed, effectiveDerivationPath);
|
|
411
|
+
} else {
|
|
412
|
+
return deriveEthKey(seed, effectiveDerivationPath);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
throw new Error(`Invalid wallet creation method: ${method}`);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
function stripHexPrefix(value: string): string {
|
|
420
|
+
return value.startsWith('0x') ? value.slice(2) : value;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
function normalizePrivateKey(value: string): string {
|
|
424
|
+
return value.startsWith('0x') ? value : `0x${value}`;
|
|
425
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base Wallet Provider
|
|
3
|
+
*
|
|
4
|
+
* Abstract base class for all blockchain wallet providers.
|
|
5
|
+
* Defines common interface for wallet operations.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type {
|
|
9
|
+
ChainType,
|
|
10
|
+
Balance,
|
|
11
|
+
Transaction,
|
|
12
|
+
TransactionRequest,
|
|
13
|
+
SignedTransaction,
|
|
14
|
+
ProviderConfig,
|
|
15
|
+
} from '../types.js';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Abstract base class for wallet providers
|
|
19
|
+
*/
|
|
20
|
+
export abstract class BaseWalletProvider {
|
|
21
|
+
protected config: ProviderConfig;
|
|
22
|
+
protected connected: boolean;
|
|
23
|
+
|
|
24
|
+
constructor(config: ProviderConfig) {
|
|
25
|
+
this.config = config;
|
|
26
|
+
this.connected = false;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Connect to blockchain network
|
|
31
|
+
*/
|
|
32
|
+
abstract connect(): Promise<void>;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Disconnect from blockchain network
|
|
36
|
+
*/
|
|
37
|
+
abstract disconnect(): Promise<void>;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Get wallet balance
|
|
41
|
+
*
|
|
42
|
+
* @param address - Wallet address
|
|
43
|
+
* @returns Wallet balance
|
|
44
|
+
*/
|
|
45
|
+
abstract getBalance(address: string): Promise<Balance>;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Send transaction
|
|
49
|
+
*
|
|
50
|
+
* @param from - From address
|
|
51
|
+
* @param request - Transaction request
|
|
52
|
+
* @returns Transaction result
|
|
53
|
+
*/
|
|
54
|
+
abstract sendTransaction(
|
|
55
|
+
from: string,
|
|
56
|
+
request: TransactionRequest
|
|
57
|
+
): Promise<Transaction>;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Sign transaction
|
|
61
|
+
*
|
|
62
|
+
* @param tx - Transaction object
|
|
63
|
+
* @param privateKey - Private key for signing
|
|
64
|
+
* @returns Signed transaction
|
|
65
|
+
*/
|
|
66
|
+
abstract signTransaction(
|
|
67
|
+
tx: any,
|
|
68
|
+
privateKey: string
|
|
69
|
+
): Promise<SignedTransaction>;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Get transaction history
|
|
73
|
+
*
|
|
74
|
+
* @param address - Wallet address
|
|
75
|
+
* @returns Transaction history
|
|
76
|
+
*/
|
|
77
|
+
abstract getTransactionHistory(address: string): Promise<Transaction[]>;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Validate address format
|
|
81
|
+
*
|
|
82
|
+
* @param address - Address to validate
|
|
83
|
+
* @returns True if address is valid
|
|
84
|
+
*/
|
|
85
|
+
abstract validateAddress(address: string): boolean;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Check connection status
|
|
89
|
+
*
|
|
90
|
+
* @returns True if connected
|
|
91
|
+
*/
|
|
92
|
+
isConnected(): boolean {
|
|
93
|
+
return this.connected;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Get chain type
|
|
98
|
+
*
|
|
99
|
+
* @returns Chain type
|
|
100
|
+
*/
|
|
101
|
+
getChain(): ChainType {
|
|
102
|
+
return this.config.chain;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Get provider configuration
|
|
107
|
+
*
|
|
108
|
+
* @returns Provider configuration
|
|
109
|
+
*/
|
|
110
|
+
getConfig(): ProviderConfig {
|
|
111
|
+
return this.config;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Get RPC URL
|
|
116
|
+
*
|
|
117
|
+
* @returns RPC endpoint URL
|
|
118
|
+
*/
|
|
119
|
+
getRpcUrl(): string {
|
|
120
|
+
return this.config.rpcUrl || '';
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Check if connected to testnet
|
|
125
|
+
*
|
|
126
|
+
* @returns True if using testnet
|
|
127
|
+
*/
|
|
128
|
+
isTestnet(): boolean {
|
|
129
|
+
return this.config.isTestnet ?? false;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Estimate transaction fee
|
|
134
|
+
*
|
|
135
|
+
* @param request - Transaction request
|
|
136
|
+
* @returns Estimated fee (as string)
|
|
137
|
+
*/
|
|
138
|
+
abstract estimateFee(request: TransactionRequest): Promise<string>;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Get current block number
|
|
142
|
+
*
|
|
143
|
+
* @returns Block number
|
|
144
|
+
*/
|
|
145
|
+
abstract getBlockNumber(): Promise<number>;
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Get transaction by hash
|
|
149
|
+
*
|
|
150
|
+
* @param txHash - Transaction hash
|
|
151
|
+
* @returns Transaction details
|
|
152
|
+
*/
|
|
153
|
+
abstract getTransaction(txHash: string): Promise<Transaction | null>;
|
|
154
|
+
}
|