@deserialize/multi-vm-wallet 1.4.12 → 1.5.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.
Files changed (191) hide show
  1. package/.claude/settings.local.json +7 -1
  2. package/BUILD_OPTIMIZATION_PLAN.md +640 -0
  3. package/BUILD_RESULTS.md +282 -0
  4. package/BUN_MIGRATION.md +415 -0
  5. package/CHANGELOG_SECURITY.md +573 -0
  6. package/IMPLEMENTATION_SUMMARY.md +494 -0
  7. package/SECURITY_AUDIT.md +1124 -0
  8. package/bun.lock +553 -0
  9. package/dist/IChainWallet.js +0 -5
  10. package/dist/bip32Old.js +0 -885
  11. package/dist/bip32Small.js +0 -79
  12. package/dist/bipTest.js +0 -362
  13. package/dist/constant.js +0 -17
  14. package/dist/english.js +0 -1
  15. package/dist/evm/aa-service/index.d.ts +0 -5
  16. package/dist/evm/aa-service/index.js +0 -14
  17. package/dist/evm/aa-service/lib/account-adapter.d.ts +0 -22
  18. package/dist/evm/aa-service/lib/account-adapter.js +0 -24
  19. package/dist/evm/aa-service/lib/kernel-account.d.ts +0 -30
  20. package/dist/evm/aa-service/lib/kernel-account.js +2 -67
  21. package/dist/evm/aa-service/lib/kernel-modules.d.ts +0 -177
  22. package/dist/evm/aa-service/lib/kernel-modules.js +4 -202
  23. package/dist/evm/aa-service/lib/session-keys.d.ts +0 -118
  24. package/dist/evm/aa-service/lib/session-keys.js +7 -151
  25. package/dist/evm/aa-service/lib/type.d.ts +0 -55
  26. package/dist/evm/aa-service/lib/type.js +0 -10
  27. package/dist/evm/aa-service/services/account-abstraction.d.ts +0 -426
  28. package/dist/evm/aa-service/services/account-abstraction.js +0 -461
  29. package/dist/evm/aa-service/services/bundler.d.ts +0 -6
  30. package/dist/evm/aa-service/services/bundler.js +0 -54
  31. package/dist/evm/evm.d.ts +10 -67
  32. package/dist/evm/evm.js +340 -102
  33. package/dist/evm/index.js +0 -3
  34. package/dist/evm/script.js +3 -17
  35. package/dist/evm/smartWallet.d.ts +0 -173
  36. package/dist/evm/smartWallet.js +0 -206
  37. package/dist/evm/smartWallet.types.d.ts +0 -6
  38. package/dist/evm/smartWallet.types.js +0 -8
  39. package/dist/evm/transaction.utils.d.ts +0 -242
  40. package/dist/evm/transaction.utils.js +4 -320
  41. package/dist/evm/transactionParsing.d.ts +0 -11
  42. package/dist/evm/transactionParsing.js +28 -147
  43. package/dist/evm/utils.d.ts +0 -46
  44. package/dist/evm/utils.js +1 -57
  45. package/dist/helpers/index.d.ts +0 -4
  46. package/dist/helpers/index.js +8 -44
  47. package/dist/helpers/routeScan.js +0 -1
  48. package/dist/index.js +0 -1
  49. package/dist/old.js +0 -884
  50. package/dist/price.js +0 -1
  51. package/dist/price.types.js +0 -2
  52. package/dist/rate-limiter.d.ts +28 -0
  53. package/dist/rate-limiter.js +95 -0
  54. package/dist/retry-logic.d.ts +14 -0
  55. package/dist/retry-logic.js +120 -0
  56. package/dist/savings/index.d.ts +1 -0
  57. package/dist/savings/index.js +16 -2
  58. package/dist/savings/saving-manager.d.ts +46 -0
  59. package/dist/savings/saving-manager.js +176 -0
  60. package/dist/savings/savings-operations.d.ts +39 -0
  61. package/dist/savings/savings-operations.js +141 -0
  62. package/dist/savings/smart-savings.d.ts +0 -63
  63. package/dist/savings/smart-savings.js +0 -78
  64. package/dist/savings/types.d.ts +0 -69
  65. package/dist/savings/types.js +0 -7
  66. package/dist/savings/validation.d.ts +9 -0
  67. package/dist/savings/validation.js +85 -0
  68. package/dist/svm/constant.js +0 -1
  69. package/dist/svm/index.js +0 -1
  70. package/dist/svm/svm.d.ts +7 -13
  71. package/dist/svm/svm.js +263 -46
  72. package/dist/svm/transactionParsing.d.ts +0 -7
  73. package/dist/svm/transactionParsing.js +3 -41
  74. package/dist/svm/transactionSender.js +0 -9
  75. package/dist/svm/utils.d.ts +0 -12
  76. package/dist/svm/utils.js +9 -60
  77. package/dist/test.d.ts +0 -4
  78. package/dist/test.js +15 -95
  79. package/dist/transaction-utils.d.ts +38 -0
  80. package/dist/transaction-utils.js +168 -0
  81. package/dist/types.d.ts +36 -0
  82. package/dist/types.js +0 -1
  83. package/dist/utils.js +0 -1
  84. package/dist/vm-validation.d.ts +11 -0
  85. package/dist/vm-validation.js +151 -0
  86. package/dist/vm.d.ts +14 -16
  87. package/dist/vm.js +64 -53
  88. package/dist/walletBip32.d.ts +2 -0
  89. package/dist/walletBip32.js +33 -66
  90. package/package.json +9 -4
  91. package/test-discovery.ts +235 -0
  92. package/test-pocket-discovery.ts +84 -0
  93. package/tsconfig.json +18 -11
  94. package/tsconfig.prod.json +10 -0
  95. package/utils/IChainWallet.ts +2 -0
  96. package/utils/evm/evm.ts +560 -39
  97. package/utils/rate-limiter.ts +179 -0
  98. package/utils/retry-logic.ts +271 -0
  99. package/utils/savings/EXAMPLES.md +883 -0
  100. package/utils/savings/SECURITY.md +731 -0
  101. package/utils/savings/index.ts +1 -1
  102. package/utils/savings/saving-manager.ts +656 -0
  103. package/utils/savings/savings-operations.ts +509 -0
  104. package/utils/savings/validation.ts +187 -0
  105. package/utils/svm/svm.ts +467 -20
  106. package/utils/test.ts +26 -3
  107. package/utils/transaction-utils.ts +394 -0
  108. package/utils/types.ts +100 -0
  109. package/utils/vm-validation.ts +280 -0
  110. package/utils/vm.ts +202 -24
  111. package/utils/walletBip32.ts +63 -3
  112. package/dist/IChainWallet.js.map +0 -1
  113. package/dist/bip32.d.ts +0 -9
  114. package/dist/bip32.js +0 -172
  115. package/dist/bip32.js.map +0 -1
  116. package/dist/bip32Old.js.map +0 -1
  117. package/dist/bip32Small.js.map +0 -1
  118. package/dist/bipTest.js.map +0 -1
  119. package/dist/constant.js.map +0 -1
  120. package/dist/english.js.map +0 -1
  121. package/dist/evm/SMART_WALLET_EXAMPLES.d.ts +0 -20
  122. package/dist/evm/SMART_WALLET_EXAMPLES.js +0 -451
  123. package/dist/evm/SMART_WALLET_EXAMPLES.js.map +0 -1
  124. package/dist/evm/aa-service/index.js.map +0 -1
  125. package/dist/evm/aa-service/lib/account-adapter.js.map +0 -1
  126. package/dist/evm/aa-service/lib/kernel-account.js.map +0 -1
  127. package/dist/evm/aa-service/lib/kernel-modules.js.map +0 -1
  128. package/dist/evm/aa-service/lib/session-keys.js.map +0 -1
  129. package/dist/evm/aa-service/lib/type.js.map +0 -1
  130. package/dist/evm/aa-service/services/account-abstraction.js.map +0 -1
  131. package/dist/evm/aa-service/services/bundler.js.map +0 -1
  132. package/dist/evm/evm.js.map +0 -1
  133. package/dist/evm/index.js.map +0 -1
  134. package/dist/evm/script.js.map +0 -1
  135. package/dist/evm/smartWallet.js.map +0 -1
  136. package/dist/evm/smartWallet.types.js.map +0 -1
  137. package/dist/evm/transaction.utils.js.map +0 -1
  138. package/dist/evm/transactionParsing.js.map +0 -1
  139. package/dist/evm/utils.js.map +0 -1
  140. package/dist/helpers/index.js.map +0 -1
  141. package/dist/helpers/routeScan.js.map +0 -1
  142. package/dist/index.js.map +0 -1
  143. package/dist/old.js.map +0 -1
  144. package/dist/price.js.map +0 -1
  145. package/dist/price.types.js.map +0 -1
  146. package/dist/privacy/artifact-manager.d.ts +0 -117
  147. package/dist/privacy/artifact-manager.js +0 -251
  148. package/dist/privacy/artifact-manager.js.map +0 -1
  149. package/dist/privacy/broadcaster-client.d.ts +0 -166
  150. package/dist/privacy/broadcaster-client.js +0 -261
  151. package/dist/privacy/broadcaster-client.js.map +0 -1
  152. package/dist/privacy/index.d.ts +0 -34
  153. package/dist/privacy/index.js +0 -56
  154. package/dist/privacy/index.js.map +0 -1
  155. package/dist/privacy/network-config.d.ts +0 -57
  156. package/dist/privacy/network-config.js +0 -118
  157. package/dist/privacy/network-config.js.map +0 -1
  158. package/dist/privacy/poi-helper.d.ts +0 -161
  159. package/dist/privacy/poi-helper.js +0 -249
  160. package/dist/privacy/poi-helper.js.map +0 -1
  161. package/dist/privacy/railgun-engine.d.ts +0 -135
  162. package/dist/privacy/railgun-engine.js +0 -205
  163. package/dist/privacy/railgun-engine.js.map +0 -1
  164. package/dist/privacy/railgun-privacy-wallet.d.ts +0 -288
  165. package/dist/privacy/railgun-privacy-wallet.js +0 -539
  166. package/dist/privacy/railgun-privacy-wallet.js.map +0 -1
  167. package/dist/privacy/types.d.ts +0 -229
  168. package/dist/privacy/types.js +0 -26
  169. package/dist/privacy/types.js.map +0 -1
  170. package/dist/savings/index.js.map +0 -1
  171. package/dist/savings/saving-actions.d.ts +0 -0
  172. package/dist/savings/saving-actions.js +0 -78
  173. package/dist/savings/saving-actions.js.map +0 -1
  174. package/dist/savings/savings-manager.d.ts +0 -126
  175. package/dist/savings/savings-manager.js +0 -234
  176. package/dist/savings/savings-manager.js.map +0 -1
  177. package/dist/savings/smart-savings.js.map +0 -1
  178. package/dist/savings/types.js.map +0 -1
  179. package/dist/svm/constant.js.map +0 -1
  180. package/dist/svm/index.js.map +0 -1
  181. package/dist/svm/svm.js.map +0 -1
  182. package/dist/svm/transactionParsing.js.map +0 -1
  183. package/dist/svm/transactionSender.js.map +0 -1
  184. package/dist/svm/utils.js.map +0 -1
  185. package/dist/test.js.map +0 -1
  186. package/dist/types.js.map +0 -1
  187. package/dist/utils.js.map +0 -1
  188. package/dist/vm.js.map +0 -1
  189. package/dist/walletBip32.js.map +0 -1
  190. package/utils/savings/saving-actions.ts +0 -92
  191. package/utils/savings/savings-manager.ts +0 -271
package/dist/types.d.ts CHANGED
@@ -208,6 +208,42 @@ export interface Balance {
208
208
  formatted: number;
209
209
  decimal: number;
210
210
  }
211
+ export interface DiscoveredWallet {
212
+ index: number;
213
+ address: string;
214
+ derivationPath: string;
215
+ nativeBalance: {
216
+ amount: bigint;
217
+ formatted: number;
218
+ symbol: string;
219
+ };
220
+ privateKey?: string;
221
+ }
222
+ export interface WalletDiscoveryOptions {
223
+ startIndex?: number;
224
+ maxIndex?: number;
225
+ gapLimit?: number;
226
+ minBalance?: bigint;
227
+ includeZeroBalance?: boolean;
228
+ includePrivateKeys?: boolean;
229
+ checkInParallel?: boolean;
230
+ batchSize?: number;
231
+ checkDelay?: number;
232
+ onProgress?: (current: number, total: number, found: number) => void;
233
+ onDiscovered?: (wallet: DiscoveredWallet) => void;
234
+ }
235
+ export interface PocketDiscoveryOptions extends Omit<WalletDiscoveryOptions, 'onDiscovered'> {
236
+ walletIndex?: number;
237
+ onDiscovered?: (pocket: DiscoveredWallet) => void;
238
+ }
239
+ export interface WalletDiscoveryResult {
240
+ discovered: DiscoveredWallet[];
241
+ scannedIndices: number;
242
+ highestIndex: number;
243
+ totalBalance: bigint;
244
+ stoppedByGapLimit: boolean;
245
+ duration: number;
246
+ }
211
247
  export declare const SUPPORTED_VM: {
212
248
  readonly EVM: typeof EVMVM;
213
249
  readonly SVM: typeof SVMVM;
package/dist/types.js CHANGED
@@ -7,4 +7,3 @@ exports.SUPPORTED_VM = {
7
7
  'EVM': evm_1.EVMVM,
8
8
  'SVM': svm_1.SVMVM
9
9
  };
10
- //# sourceMappingURL=types.js.map
package/dist/utils.js CHANGED
@@ -20,4 +20,3 @@ const getPrivateKeyFromAnother = (privateKey, fromVm, toVm) => {
20
20
  }
21
21
  };
22
22
  exports.getPrivateKeyFromAnother = getPrivateKeyFromAnother;
23
- //# sourceMappingURL=utils.js.map
@@ -0,0 +1,11 @@
1
+ export declare class VMValidation {
2
+ static validateIndex(index: number, label?: string): void;
3
+ static validateSeed(seed: string): void;
4
+ static validateMnemonic(mnemonic: string): void;
5
+ static validateDerivationPath(path: string, vmType?: 'EVM' | 'SVM'): void;
6
+ static validatePassword(password: string, minLength?: number): void;
7
+ static validateAmount(amount: bigint, label?: string): void;
8
+ static validateEthereumAddress(address: string, label?: string): void;
9
+ }
10
+ export declare function sanitizeError(error: any, additionalSensitiveFields?: string[]): Error;
11
+ export declare function logSafeError(message: string, error: any, context?: Record<string, any>): void;
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VMValidation = void 0;
4
+ exports.sanitizeError = sanitizeError;
5
+ exports.logSafeError = logSafeError;
6
+ class VMValidation {
7
+ static validateIndex(index, label = 'Index') {
8
+ if (!Number.isInteger(index)) {
9
+ throw new Error(`${label} must be an integer, got: ${index}`);
10
+ }
11
+ if (index < 0) {
12
+ throw new Error(`${label} must be non-negative, got: ${index}`);
13
+ }
14
+ if (index > 0x7FFFFFFF) {
15
+ throw new Error(`${label} exceeds maximum (2147483647), got: ${index}`);
16
+ }
17
+ }
18
+ static validateSeed(seed) {
19
+ if (typeof seed !== 'string') {
20
+ throw new Error(`Seed must be a string, got: ${typeof seed}`);
21
+ }
22
+ if (seed.length === 0) {
23
+ throw new Error('Seed cannot be empty');
24
+ }
25
+ if (!/^[0-9a-fA-F]+$/.test(seed)) {
26
+ throw new Error('Seed must be a hex string');
27
+ }
28
+ if (seed.length < 32) {
29
+ throw new Error(`Seed too short: ${seed.length} chars (minimum 32)`);
30
+ }
31
+ }
32
+ static validateMnemonic(mnemonic) {
33
+ if (typeof mnemonic !== 'string') {
34
+ throw new Error(`Mnemonic must be a string, got: ${typeof mnemonic}`);
35
+ }
36
+ const trimmed = mnemonic.trim();
37
+ if (trimmed.length === 0) {
38
+ throw new Error('Mnemonic cannot be empty');
39
+ }
40
+ const words = trimmed.split(/\s+/);
41
+ const validWordCounts = [12, 15, 18, 21, 24];
42
+ if (!validWordCounts.includes(words.length)) {
43
+ throw new Error(`Mnemonic must have 12, 15, 18, 21, or 24 words (BIP-39 standard), got: ${words.length} words`);
44
+ }
45
+ }
46
+ static validateDerivationPath(path, vmType) {
47
+ if (typeof path !== 'string') {
48
+ throw new Error(`Derivation path must be a string, got: ${typeof path}`);
49
+ }
50
+ const pathRegex = /^m(\/\d+')+$/;
51
+ if (!pathRegex.test(path)) {
52
+ throw new Error(`Invalid derivation path format: ${path}. ` +
53
+ `Expected format: m/44'/cointype'/account'/... (all segments hardened)`);
54
+ }
55
+ const parts = path.split('/');
56
+ if (parts.length < 3) {
57
+ throw new Error(`Derivation path too short: ${path}`);
58
+ }
59
+ const purpose = parseInt(parts[1].replace("'", ""));
60
+ if (purpose !== 44) {
61
+ console.warn(`Warning: Non-BIP-44 purpose value: ${purpose}`);
62
+ }
63
+ if (vmType && parts.length >= 3) {
64
+ const coinType = parseInt(parts[2].replace("'", ""));
65
+ if (vmType === 'EVM' && coinType !== 60) {
66
+ throw new Error(`Invalid coin type for EVM: ${coinType}. Expected 60 (Ethereum).`);
67
+ }
68
+ if (vmType === 'SVM' && coinType !== 501) {
69
+ throw new Error(`Invalid coin type for SVM: ${coinType}. Expected 501 (Solana).`);
70
+ }
71
+ }
72
+ for (let i = 1; i < parts.length; i++) {
73
+ const indexStr = parts[i].replace("'", "");
74
+ const index = parseInt(indexStr);
75
+ if (isNaN(index)) {
76
+ throw new Error(`Invalid index in path segment ${i}: ${parts[i]}`);
77
+ }
78
+ if (parts[i].endsWith("'")) {
79
+ if (index > 0x7FFFFFFF) {
80
+ throw new Error(`Hardened index ${index} exceeds maximum`);
81
+ }
82
+ }
83
+ else {
84
+ if (index > 0x7FFFFFFF) {
85
+ throw new Error(`Non-hardened index ${index} exceeds maximum`);
86
+ }
87
+ }
88
+ }
89
+ }
90
+ static validatePassword(password, minLength = 8) {
91
+ if (typeof password !== 'string') {
92
+ throw new Error(`Password must be a string, got: ${typeof password}`);
93
+ }
94
+ if (password.length < minLength) {
95
+ throw new Error(`Password too short. Minimum length: ${minLength}, got: ${password.length}`);
96
+ }
97
+ const weakPasswords = ['password', '12345678', 'qwerty', 'abc123'];
98
+ if (weakPasswords.includes(password.toLowerCase())) {
99
+ throw new Error('Password is too weak. Choose a stronger password.');
100
+ }
101
+ }
102
+ static validateAmount(amount, label = 'Amount') {
103
+ if (typeof amount !== 'bigint') {
104
+ throw new Error(`${label} must be a bigint, got: ${typeof amount}`);
105
+ }
106
+ if (amount <= 0n) {
107
+ throw new Error(`${label} must be positive, got: ${amount}`);
108
+ }
109
+ }
110
+ static validateEthereumAddress(address, label = 'Address') {
111
+ if (typeof address !== 'string') {
112
+ throw new Error(`${label} must be a string, got: ${typeof address}`);
113
+ }
114
+ if (!/^0x[a-fA-F0-9]{40}$/.test(address)) {
115
+ throw new Error(`${label} has invalid format. Expected 0x followed by 40 hex characters, got: ${address}`);
116
+ }
117
+ }
118
+ }
119
+ exports.VMValidation = VMValidation;
120
+ function sanitizeError(error, additionalSensitiveFields = []) {
121
+ const message = error.message || error.toString();
122
+ let sanitized = message
123
+ .replace(/seed:\s*[0-9a-fA-F]{32,}/gi, 'seed: [REDACTED]')
124
+ .replace(/password:\s*\S+/gi, 'password: [REDACTED]')
125
+ .replace(/mnemonic:\s*.+/gi, 'mnemonic: [REDACTED]')
126
+ .replace(/private\s*key:\s*[0-9a-fA-F]+/gi, 'privateKey: [REDACTED]')
127
+ .replace(/0x[0-9a-fA-F]{64,}/g, '[PRIVATE_KEY_REDACTED]')
128
+ .replace(/secret:\s*\S+/gi, 'secret: [REDACTED]');
129
+ additionalSensitiveFields.forEach(field => {
130
+ const regex = new RegExp(`${field}:\\s*\\S+`, 'gi');
131
+ sanitized = sanitized.replace(regex, `${field}: [REDACTED]`);
132
+ });
133
+ const sanitizedError = new Error(sanitized);
134
+ sanitizedError.stack = error.stack;
135
+ return sanitizedError;
136
+ }
137
+ function logSafeError(message, error, context) {
138
+ const sanitized = sanitizeError(error);
139
+ const safeContext = context ? { ...context } : {};
140
+ const sensitiveKeys = ['seed', 'mnemonic', 'privateKey', 'password', 'secret'];
141
+ sensitiveKeys.forEach(key => {
142
+ if (safeContext[key]) {
143
+ safeContext[key] = '[REDACTED]';
144
+ }
145
+ });
146
+ console.error(message, {
147
+ error: sanitized.message,
148
+ stack: sanitized.stack,
149
+ context: safeContext
150
+ });
151
+ }
package/dist/vm.d.ts CHANGED
@@ -1,16 +1,28 @@
1
1
  import { TokenInfo, vmTypes } from "./types";
2
+ import { EntropyToMnemonic } from "./walletBip32";
2
3
  export declare abstract class VM<AddressType, PrivateKeyType, ConnectionType> {
3
4
  protected seed: string;
4
5
  type: vmTypes;
6
+ private disposed;
5
7
  constructor(seed: string, vm: vmTypes);
6
8
  static mnemonicToSeed: (mnemonic: string) => string;
9
+ dispose(): void;
10
+ isDisposed(): boolean;
11
+ protected checkNotDisposed(): void;
7
12
  static generateSalt(): string;
13
+ static getMnemonicFromEntropy: typeof EntropyToMnemonic;
8
14
  static deriveKey(password: string, salt: string, iterations?: number, keySize?: number): string;
9
- static encryptSeedPhrase(seedPhrase: string, password: string): {
15
+ static encryptSeedPhrase(seedPhrase: string, password: string, iterations?: number): {
10
16
  encrypted: string;
11
17
  salt: string;
18
+ iterations: number;
12
19
  };
13
- static decryptSeedPhrase(encryptedSeedPhrase: string, password: string, salt: string): string | null;
20
+ static encryptSeedPhraseLegacy(seedPhrase: string, password: string): {
21
+ encrypted: string;
22
+ salt: string;
23
+ };
24
+ static decryptSeedPhrase(encryptedSeedPhrase: string, password: string, salt: string, iterations?: number): string | null;
25
+ static decryptSeedPhraseLegacy(encryptedSeedPhrase: string, password: string, salt: string): string | null;
14
26
  generateSalt: typeof VM.generateSalt;
15
27
  deriveKey: typeof VM.deriveKey;
16
28
  encryptSeedPhrase: typeof VM.encryptSeedPhrase;
@@ -21,18 +33,4 @@ export declare abstract class VM<AddressType, PrivateKeyType, ConnectionType> {
21
33
  index: number;
22
34
  };
23
35
  abstract getTokenInfo(tokenAddress: AddressType, connection: ConnectionType): Promise<TokenInfo>;
24
- /**
25
- * Derive a savings account using BIP-44 account index
26
- *
27
- * Main wallet uses: m/44'/60'/0'/0/0 (account index 0)
28
- * Savings accounts use: m/44'/60'/N'/0/0 (account index N)
29
- *
30
- * @param accountIndex - The BIP-44 account index (1 for first savings, 2 for second, etc.)
31
- * @returns Object containing privateKey, address, and derivation path
32
- */
33
- abstract deriveSavingsAccount(accountIndex: number): {
34
- privateKey: PrivateKeyType;
35
- address: AddressType;
36
- derivationPath: string;
37
- };
38
36
  }
package/dist/vm.js CHANGED
@@ -1,91 +1,102 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
36
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
4
  };
38
5
  Object.defineProperty(exports, "__esModule", { value: true });
39
6
  exports.VM = void 0;
40
- const bip39 = __importStar(require("@scure/bip39"));
41
7
  const crypto_js_1 = __importDefault(require("crypto-js"));
42
- // Abstract Base Classes
8
+ const walletBip32_1 = require("./walletBip32");
43
9
  class VM {
44
10
  seed;
45
11
  type;
12
+ disposed = false;
46
13
  constructor(seed, vm) {
47
14
  this.type = vm;
48
15
  this.seed = seed;
49
16
  }
50
- static mnemonicToSeed = (mnemonic) => {
51
- return Buffer.from(bip39.mnemonicToSeedSync(mnemonic)).toString("hex");
52
- };
17
+ static mnemonicToSeed = walletBip32_1.mnemonicToSeed;
18
+ dispose() {
19
+ if (this.disposed) {
20
+ return;
21
+ }
22
+ this.seed = '';
23
+ this.disposed = true;
24
+ }
25
+ isDisposed() {
26
+ return this.disposed || !this.seed || this.seed === '';
27
+ }
28
+ checkNotDisposed() {
29
+ if (this.isDisposed()) {
30
+ throw new Error('VM has been disposed. Create a new instance to perform operations.');
31
+ }
32
+ }
53
33
  static generateSalt() {
54
- return crypto_js_1.default.lib.WordArray.random(16).toString(); // 128-bit salt
34
+ return crypto_js_1.default.lib.WordArray.random(16).toString();
55
35
  }
56
- static deriveKey(password, salt, iterations = 10000, keySize = 256 / 32) {
36
+ static getMnemonicFromEntropy = walletBip32_1.EntropyToMnemonic;
37
+ static deriveKey(password, salt, iterations = 600000, keySize = 256 / 32) {
38
+ if (!password || password.length < 8) {
39
+ throw new Error('Password must be at least 8 characters');
40
+ }
41
+ if (!salt) {
42
+ throw new Error('Salt is required');
43
+ }
44
+ if (iterations < 100000) {
45
+ console.warn(`⚠️ WARNING: Using ${iterations} PBKDF2 iterations is insecure. ` +
46
+ `Minimum recommended: 100,000. Recommended: 600,000.`);
47
+ }
57
48
  return crypto_js_1.default.PBKDF2(password, crypto_js_1.default.enc.Hex.parse(salt), {
58
49
  keySize: keySize,
59
50
  iterations: iterations,
51
+ hasher: crypto_js_1.default.algo.SHA256
60
52
  }).toString();
61
53
  }
62
- static encryptSeedPhrase(seedPhrase, password) {
63
- const salt = this.generateSalt(); // Generate a unique salt for this encryption
64
- const key = this.deriveKey(password, salt); // Derive a key using PBKDF2
65
- // Encrypt the seed phrase with AES using the derived key
54
+ static encryptSeedPhrase(seedPhrase, password, iterations = 600000) {
55
+ if (!seedPhrase || seedPhrase.trim().length === 0) {
56
+ throw new Error('Seed phrase cannot be empty');
57
+ }
58
+ if (!password || password.length < 8) {
59
+ throw new Error('Password must be at least 8 characters');
60
+ }
61
+ const salt = this.generateSalt();
62
+ const key = this.deriveKey(password, salt, iterations);
66
63
  const encrypted = crypto_js_1.default.AES.encrypt(seedPhrase, key).toString();
67
- // Return the encrypted data and the salt (needed for decryption)
68
- return { encrypted, salt };
64
+ return { encrypted, salt, iterations };
65
+ }
66
+ static encryptSeedPhraseLegacy(seedPhrase, password) {
67
+ const result = this.encryptSeedPhrase(seedPhrase, password, 10000);
68
+ return { encrypted: result.encrypted, salt: result.salt };
69
69
  }
70
- static decryptSeedPhrase(encryptedSeedPhrase, password, salt) {
70
+ static decryptSeedPhrase(encryptedSeedPhrase, password, salt, iterations = 600000) {
71
71
  try {
72
- const key = this.deriveKey(password, salt); // Derive the key using the same salt
72
+ if (!encryptedSeedPhrase) {
73
+ throw new Error('Encrypted seed phrase is required');
74
+ }
75
+ if (!password || password.length < 8) {
76
+ throw new Error('Password must be at least 8 characters');
77
+ }
78
+ if (!salt) {
79
+ throw new Error('Salt is required');
80
+ }
81
+ const key = this.deriveKey(password, salt, iterations);
73
82
  const bytes = crypto_js_1.default.AES.decrypt(encryptedSeedPhrase, key);
74
83
  const seedPhrase = bytes.toString(crypto_js_1.default.enc.Utf8);
75
- // Check if decryption was successful
76
- if (!seedPhrase)
77
- throw new Error("Decryption failed.");
84
+ if (!seedPhrase || seedPhrase.trim().length === 0) {
85
+ throw new Error("Decryption failed - invalid password or corrupted data");
86
+ }
78
87
  return seedPhrase;
79
88
  }
80
89
  catch (e) {
81
- console.error("Invalid password or corrupted data:", e.message);
90
+ console.error("Decryption failed:", e.message);
82
91
  return null;
83
92
  }
84
93
  }
94
+ static decryptSeedPhraseLegacy(encryptedSeedPhrase, password, salt) {
95
+ return this.decryptSeedPhrase(encryptedSeedPhrase, password, salt, 10000);
96
+ }
85
97
  generateSalt = VM.generateSalt;
86
98
  deriveKey = VM.deriveKey;
87
99
  encryptSeedPhrase = VM.encryptSeedPhrase;
88
100
  decryptSeedPhrase = VM.decryptSeedPhrase;
89
101
  }
90
102
  exports.VM = VM;
91
- //# sourceMappingURL=vm.js.map
@@ -1,5 +1,7 @@
1
1
  import { Keypair } from "@solana/web3.js";
2
2
  export declare function GenerateNewMnemonic(): string;
3
+ export declare const mnemonicToSeed: (mnemonic: string) => string;
4
+ export declare function EntropyToMnemonic(entropy: string): string;
3
5
  export declare function ValidateMnemonic(mnemonic: string): true;
4
6
  export declare function GenerateSeed(_mnemonic?: string): Uint8Array<ArrayBufferLike>;
5
7
  export declare function EVMDeriveChildPrivateKey(seed: string, index: number, derivationPath: string): {
@@ -1,10 +1,4 @@
1
1
  "use strict";
2
- // import * as bip39 from "bip39";
3
- // import BIP32Factory from "bip32";
4
- // import * as ecc from "tiny-secp256k1";
5
- // import { BIP32Interface } from "bip32";
6
- // import * as ed25519 from "ed25519-hd-key";
7
- // import { Keypair } from "@solana/web3.js";
8
2
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
3
  if (k2 === undefined) k2 = k;
10
4
  var desc = Object.getOwnPropertyDescriptor(m, k);
@@ -39,74 +33,45 @@ var __importStar = (this && this.__importStar) || (function () {
39
33
  };
40
34
  })();
41
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.mnemonicToSeed = void 0;
42
37
  exports.GenerateNewMnemonic = GenerateNewMnemonic;
38
+ exports.EntropyToMnemonic = EntropyToMnemonic;
43
39
  exports.ValidateMnemonic = ValidateMnemonic;
44
40
  exports.GenerateSeed = GenerateSeed;
45
41
  exports.EVMDeriveChildPrivateKey = EVMDeriveChildPrivateKey;
46
42
  exports.SVMDeriveChildPrivateKey = SVMDeriveChildPrivateKey;
47
- // // export function getPublicKeyFromSeed(seed: string, index: number) {
48
- // // const node = getSeedNode(seed);
49
- // // const { publicKey } = deriveChildPrivateKey(node, index);
50
- // // return publicKey;
51
- // // }
52
- // // export function getPrivateKeyFromSeed(seed: string, index: number) {
53
- // // const node = getSeedNode(seed);
54
- // // const keyPair = deriveChildPrivateKey(node, index);
55
- // // return keyPair.privateKey;
56
- // // }
57
- // export function GenerateNewMnemonic() {
58
- // const mnemonic = bip39.generateMnemonic();
59
- // return mnemonic;
60
- // }
61
- // export function ValidateMnemonic(mnemonic: string) {
62
- // const isValid = bip39.validateMnemonic(mnemonic);
63
- // if (!isValid) {
64
- // throw new Error("Invalid mnemonic");
65
- // }
66
- // return isValid;
67
- // }
68
- // export function GenerateSeed(_mnemonic?: string) {
69
- // const mnemonic = _mnemonic || bip39.generateMnemonic();
70
- // const seed = bip39.mnemonicToSeedSync(mnemonic);
71
- // const seedString = seed.toString("hex");
72
- // return seedString;
73
- // }
74
- // export function getSeedNode(seed: string) {
75
- // const bip32 = BIP32Factory(ecc);
76
- // const restoredSeedBuffer = Buffer.from(seed, "hex");
77
- // const node: BIP32Interface = bip32.fromSeed(restoredSeedBuffer);
78
- // return node;
79
- // }
80
- // //EVM
81
- // export function EVMDeriveChildPrivateKey(seed: string, index: number, derivationPath: string) {
82
- // const node = getSeedNode(seed);
83
- // const child = node.derivePath(`${derivationPath}${index}'`);
84
- // const privateKey = child.privateKey!.toString("hex");
85
- // const publicKey = child.publicKey.toString("hex");
86
- // return { privateKey, publicKey };
87
- // }
88
- // //SVM
89
- // export function SVMDeriveChildPrivateKey(seed: string, index: number, derivationPath: string) {
90
- // const path = `${derivationPath}${index}'`;
91
- // // Derive a seed from the given path
92
- // const derivedSeed = ed25519.derivePath(path, seed).key;
93
- // const derivedKeyPair = Keypair.fromSeed(derivedSeed);
94
- // return derivedKeyPair;
95
- // }
96
43
  const web3_js_1 = require("@solana/web3.js");
97
44
  const bip39 = __importStar(require("@scure/bip39"));
98
45
  const bip32_1 = require("@scure/bip32");
99
- const buffer_1 = require("buffer"); // Import the polyfill
46
+ const buffer_1 = require("buffer");
100
47
  if (typeof window !== 'undefined') {
101
- window.Buffer = buffer_1.Buffer; // Inject Buffer into the global scope
48
+ window.Buffer = buffer_1.Buffer;
102
49
  }
103
50
  const english_1 = require("./english");
104
51
  const hmac_1 = require("@noble/hashes/hmac");
105
52
  const sha2_1 = require("@noble/hashes/sha2");
53
+ const vm_validation_1 = require("./vm-validation");
106
54
  function GenerateNewMnemonic() {
107
55
  const mnemonic = bip39.generateMnemonic(english_1.wordlist);
108
56
  return mnemonic;
109
57
  }
58
+ const mnemonicToSeed = (mnemonic) => {
59
+ return buffer_1.Buffer.from(bip39.mnemonicToSeedSync(mnemonic)).toString("hex");
60
+ };
61
+ exports.mnemonicToSeed = mnemonicToSeed;
62
+ function EntropyToMnemonic(entropy) {
63
+ const entropyBytes = buffer_1.Buffer.from(entropy);
64
+ const validLength = 16;
65
+ const truncatedBytes = entropyBytes.length >= validLength
66
+ ? entropyBytes.slice(0, validLength)
67
+ : entropyBytes;
68
+ if (truncatedBytes.length < validLength) {
69
+ const padded = buffer_1.Buffer.alloc(validLength, 0);
70
+ truncatedBytes.copy(padded);
71
+ return bip39.entropyToMnemonic(padded, english_1.wordlist);
72
+ }
73
+ return bip39.entropyToMnemonic(truncatedBytes, english_1.wordlist);
74
+ }
110
75
  function ValidateMnemonic(mnemonic) {
111
76
  const isValid = bip39.validateMnemonic(mnemonic, english_1.wordlist);
112
77
  if (!isValid) {
@@ -119,19 +84,25 @@ function GenerateSeed(_mnemonic) {
119
84
  const seedString = bip39.mnemonicToSeedSync(mnemonic);
120
85
  return seedString;
121
86
  }
122
- //EVM
123
87
  function EVMDeriveChildPrivateKey(seed, index, derivationPath) {
88
+ vm_validation_1.VMValidation.validateSeed(seed);
89
+ vm_validation_1.VMValidation.validateIndex(index, 'Wallet index');
90
+ vm_validation_1.VMValidation.validateDerivationPath(derivationPath + index + "'", 'EVM');
124
91
  const path = `${derivationPath}${index}'`;
125
92
  const scureNode = bip32_1.HDKey.fromMasterSeed(buffer_1.Buffer.from(seed, "hex"));
126
93
  const child = scureNode.derive(path);
94
+ if (!child.privateKey) {
95
+ throw new Error(`Failed to derive private key at path: ${path}`);
96
+ }
127
97
  const privateKey = buffer_1.Buffer.from(child.privateKey).toString("hex");
128
98
  const publicKey = buffer_1.Buffer.from(child.publicKey).toString("hex");
129
99
  return { privateKey, publicKey };
130
100
  }
131
- //SVM
132
101
  function SVMDeriveChildPrivateKey(seed, index, derivationPath) {
102
+ vm_validation_1.VMValidation.validateSeed(seed);
103
+ vm_validation_1.VMValidation.validateIndex(index, 'Wallet index');
104
+ vm_validation_1.VMValidation.validateDerivationPath(derivationPath + index + "'", 'SVM');
133
105
  const path = `${derivationPath}${index}'`;
134
- // Derive a seed from the given path
135
106
  const derivedSeed = derivePathEclipticCurve(path, buffer_1.Buffer.from(seed, "hex")).key;
136
107
  const derivedKeyPair = web3_js_1.Keypair.fromSeed(derivedSeed);
137
108
  return derivedKeyPair;
@@ -146,11 +117,9 @@ function derivePathEclipticCurve(path, seed) {
146
117
  }
147
118
  return parseInt(seg.slice(0, -1), 10) + 0x80000000;
148
119
  });
149
- // Initialize with master key derivation
150
120
  let hmacResult = (0, hmac_1.hmac)(sha2_1.sha512, buffer_1.Buffer.from("ed25519 seed"), seed);
151
121
  let key = hmacResult.slice(0, 32);
152
122
  let chainCode = hmacResult.slice(32, 64);
153
- // Derive each path segment
154
123
  for (const segment of segments) {
155
124
  const result = hardenedDerivation(key, chainCode, segment);
156
125
  key = buffer_1.Buffer.from(result.key);
@@ -161,12 +130,10 @@ function derivePathEclipticCurve(path, seed) {
161
130
  function hardenedDerivation(parentKey, parentChainCode, index) {
162
131
  const indexBuffer = new Uint8Array(4);
163
132
  new DataView(indexBuffer.buffer).setUint32(0, index, false);
164
- // Proper SLIP-0010 format: 0x00 + parent_key + index
165
133
  const data = new Uint8Array([0x00, ...parentKey, ...indexBuffer]);
166
134
  const hmacResult = (0, hmac_1.hmac)(sha2_1.sha512, parentChainCode, data);
167
135
  return {
168
- key: hmacResult.slice(0, 32), // Left 32 bytes
169
- chainCode: hmacResult.slice(32, 64) // Right 32 bytes
136
+ key: hmacResult.slice(0, 32),
137
+ chainCode: hmacResult.slice(32, 64)
170
138
  };
171
139
  }
172
- //# sourceMappingURL=walletBip32.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deserialize/multi-vm-wallet",
3
- "version": "1.4.12",
3
+ "version": "1.5.0",
4
4
  "devDependencies": {
5
5
  "@types/bn.js": "^5.2.0",
6
6
  "@types/crypto-js": "^4.2.2",
@@ -40,10 +40,15 @@
40
40
  "types": "dist/index.d.ts",
41
41
  "scripts": {
42
42
  "test": "echo \"Error: no test specified\" && exit 1",
43
- "build": "tsc -p tsconfig.json",
44
- "dev": "ts-node-dev --respawn --transpile-only utils/index.ts",
45
- "publish:sdk": "npm run build && npm publish --access=public"
43
+ "build": "bun run build:tsc",
44
+ "build:tsc": "tsc -p tsconfig.prod.json",
45
+ "build:fast": "bun build utils/index.ts --outdir dist --target node --format cjs --sourcemap && tsc -p tsconfig.prod.json --emitDeclarationOnly",
46
+ "build:dev": "tsc -p tsconfig.json",
47
+ "build:watch": "tsc -p tsconfig.json --watch",
48
+ "dev": "bun --watch utils/index.ts",
49
+ "publish:sdk": "bun run build && npm publish --access=public"
46
50
  },
51
+ "packageManager": "bun@1.3.1",
47
52
  "repository": {
48
53
  "type": "git",
49
54
  "url": "git+https://github.com/Bravark/deserialize-swap-sdk.git"