@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.
- package/.claude/settings.local.json +7 -1
- package/BUILD_OPTIMIZATION_PLAN.md +640 -0
- package/BUILD_RESULTS.md +282 -0
- package/BUN_MIGRATION.md +415 -0
- package/CHANGELOG_SECURITY.md +573 -0
- package/IMPLEMENTATION_SUMMARY.md +494 -0
- package/SECURITY_AUDIT.md +1124 -0
- package/bun.lock +553 -0
- package/dist/IChainWallet.js +0 -5
- package/dist/bip32Old.js +0 -885
- package/dist/bip32Small.js +0 -79
- package/dist/bipTest.js +0 -362
- package/dist/constant.js +0 -17
- package/dist/english.js +0 -1
- package/dist/evm/aa-service/index.d.ts +0 -5
- package/dist/evm/aa-service/index.js +0 -14
- package/dist/evm/aa-service/lib/account-adapter.d.ts +0 -22
- package/dist/evm/aa-service/lib/account-adapter.js +0 -24
- package/dist/evm/aa-service/lib/kernel-account.d.ts +0 -30
- package/dist/evm/aa-service/lib/kernel-account.js +2 -67
- package/dist/evm/aa-service/lib/kernel-modules.d.ts +0 -177
- package/dist/evm/aa-service/lib/kernel-modules.js +4 -202
- package/dist/evm/aa-service/lib/session-keys.d.ts +0 -118
- package/dist/evm/aa-service/lib/session-keys.js +7 -151
- package/dist/evm/aa-service/lib/type.d.ts +0 -55
- package/dist/evm/aa-service/lib/type.js +0 -10
- package/dist/evm/aa-service/services/account-abstraction.d.ts +0 -426
- package/dist/evm/aa-service/services/account-abstraction.js +0 -461
- package/dist/evm/aa-service/services/bundler.d.ts +0 -6
- package/dist/evm/aa-service/services/bundler.js +0 -54
- package/dist/evm/evm.d.ts +10 -67
- package/dist/evm/evm.js +340 -102
- package/dist/evm/index.js +0 -3
- package/dist/evm/script.js +3 -17
- package/dist/evm/smartWallet.d.ts +0 -173
- package/dist/evm/smartWallet.js +0 -206
- package/dist/evm/smartWallet.types.d.ts +0 -6
- package/dist/evm/smartWallet.types.js +0 -8
- package/dist/evm/transaction.utils.d.ts +0 -242
- package/dist/evm/transaction.utils.js +4 -320
- package/dist/evm/transactionParsing.d.ts +0 -11
- package/dist/evm/transactionParsing.js +28 -147
- package/dist/evm/utils.d.ts +0 -46
- package/dist/evm/utils.js +1 -57
- package/dist/helpers/index.d.ts +0 -4
- package/dist/helpers/index.js +8 -44
- package/dist/helpers/routeScan.js +0 -1
- package/dist/index.js +0 -1
- package/dist/old.js +0 -884
- package/dist/price.js +0 -1
- package/dist/price.types.js +0 -2
- package/dist/rate-limiter.d.ts +28 -0
- package/dist/rate-limiter.js +95 -0
- package/dist/retry-logic.d.ts +14 -0
- package/dist/retry-logic.js +120 -0
- package/dist/savings/index.d.ts +1 -0
- package/dist/savings/index.js +16 -2
- package/dist/savings/saving-manager.d.ts +46 -0
- package/dist/savings/saving-manager.js +176 -0
- package/dist/savings/savings-operations.d.ts +39 -0
- package/dist/savings/savings-operations.js +141 -0
- package/dist/savings/smart-savings.d.ts +0 -63
- package/dist/savings/smart-savings.js +0 -78
- package/dist/savings/types.d.ts +0 -69
- package/dist/savings/types.js +0 -7
- package/dist/savings/validation.d.ts +9 -0
- package/dist/savings/validation.js +85 -0
- package/dist/svm/constant.js +0 -1
- package/dist/svm/index.js +0 -1
- package/dist/svm/svm.d.ts +7 -13
- package/dist/svm/svm.js +263 -46
- package/dist/svm/transactionParsing.d.ts +0 -7
- package/dist/svm/transactionParsing.js +3 -41
- package/dist/svm/transactionSender.js +0 -9
- package/dist/svm/utils.d.ts +0 -12
- package/dist/svm/utils.js +9 -60
- package/dist/test.d.ts +0 -4
- package/dist/test.js +15 -95
- package/dist/transaction-utils.d.ts +38 -0
- package/dist/transaction-utils.js +168 -0
- package/dist/types.d.ts +36 -0
- package/dist/types.js +0 -1
- package/dist/utils.js +0 -1
- package/dist/vm-validation.d.ts +11 -0
- package/dist/vm-validation.js +151 -0
- package/dist/vm.d.ts +14 -16
- package/dist/vm.js +64 -53
- package/dist/walletBip32.d.ts +2 -0
- package/dist/walletBip32.js +33 -66
- package/package.json +9 -4
- package/test-discovery.ts +235 -0
- package/test-pocket-discovery.ts +84 -0
- package/tsconfig.json +18 -11
- package/tsconfig.prod.json +10 -0
- package/utils/IChainWallet.ts +2 -0
- package/utils/evm/evm.ts +560 -39
- package/utils/rate-limiter.ts +179 -0
- package/utils/retry-logic.ts +271 -0
- package/utils/savings/EXAMPLES.md +883 -0
- package/utils/savings/SECURITY.md +731 -0
- package/utils/savings/index.ts +1 -1
- package/utils/savings/saving-manager.ts +656 -0
- package/utils/savings/savings-operations.ts +509 -0
- package/utils/savings/validation.ts +187 -0
- package/utils/svm/svm.ts +467 -20
- package/utils/test.ts +26 -3
- package/utils/transaction-utils.ts +394 -0
- package/utils/types.ts +100 -0
- package/utils/vm-validation.ts +280 -0
- package/utils/vm.ts +202 -24
- package/utils/walletBip32.ts +63 -3
- package/dist/IChainWallet.js.map +0 -1
- package/dist/bip32.d.ts +0 -9
- package/dist/bip32.js +0 -172
- package/dist/bip32.js.map +0 -1
- package/dist/bip32Old.js.map +0 -1
- package/dist/bip32Small.js.map +0 -1
- package/dist/bipTest.js.map +0 -1
- package/dist/constant.js.map +0 -1
- package/dist/english.js.map +0 -1
- package/dist/evm/SMART_WALLET_EXAMPLES.d.ts +0 -20
- package/dist/evm/SMART_WALLET_EXAMPLES.js +0 -451
- package/dist/evm/SMART_WALLET_EXAMPLES.js.map +0 -1
- package/dist/evm/aa-service/index.js.map +0 -1
- package/dist/evm/aa-service/lib/account-adapter.js.map +0 -1
- package/dist/evm/aa-service/lib/kernel-account.js.map +0 -1
- package/dist/evm/aa-service/lib/kernel-modules.js.map +0 -1
- package/dist/evm/aa-service/lib/session-keys.js.map +0 -1
- package/dist/evm/aa-service/lib/type.js.map +0 -1
- package/dist/evm/aa-service/services/account-abstraction.js.map +0 -1
- package/dist/evm/aa-service/services/bundler.js.map +0 -1
- package/dist/evm/evm.js.map +0 -1
- package/dist/evm/index.js.map +0 -1
- package/dist/evm/script.js.map +0 -1
- package/dist/evm/smartWallet.js.map +0 -1
- package/dist/evm/smartWallet.types.js.map +0 -1
- package/dist/evm/transaction.utils.js.map +0 -1
- package/dist/evm/transactionParsing.js.map +0 -1
- package/dist/evm/utils.js.map +0 -1
- package/dist/helpers/index.js.map +0 -1
- package/dist/helpers/routeScan.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/old.js.map +0 -1
- package/dist/price.js.map +0 -1
- package/dist/price.types.js.map +0 -1
- package/dist/privacy/artifact-manager.d.ts +0 -117
- package/dist/privacy/artifact-manager.js +0 -251
- package/dist/privacy/artifact-manager.js.map +0 -1
- package/dist/privacy/broadcaster-client.d.ts +0 -166
- package/dist/privacy/broadcaster-client.js +0 -261
- package/dist/privacy/broadcaster-client.js.map +0 -1
- package/dist/privacy/index.d.ts +0 -34
- package/dist/privacy/index.js +0 -56
- package/dist/privacy/index.js.map +0 -1
- package/dist/privacy/network-config.d.ts +0 -57
- package/dist/privacy/network-config.js +0 -118
- package/dist/privacy/network-config.js.map +0 -1
- package/dist/privacy/poi-helper.d.ts +0 -161
- package/dist/privacy/poi-helper.js +0 -249
- package/dist/privacy/poi-helper.js.map +0 -1
- package/dist/privacy/railgun-engine.d.ts +0 -135
- package/dist/privacy/railgun-engine.js +0 -205
- package/dist/privacy/railgun-engine.js.map +0 -1
- package/dist/privacy/railgun-privacy-wallet.d.ts +0 -288
- package/dist/privacy/railgun-privacy-wallet.js +0 -539
- package/dist/privacy/railgun-privacy-wallet.js.map +0 -1
- package/dist/privacy/types.d.ts +0 -229
- package/dist/privacy/types.js +0 -26
- package/dist/privacy/types.js.map +0 -1
- package/dist/savings/index.js.map +0 -1
- package/dist/savings/saving-actions.d.ts +0 -0
- package/dist/savings/saving-actions.js +0 -78
- package/dist/savings/saving-actions.js.map +0 -1
- package/dist/savings/savings-manager.d.ts +0 -126
- package/dist/savings/savings-manager.js +0 -234
- package/dist/savings/savings-manager.js.map +0 -1
- package/dist/savings/smart-savings.js.map +0 -1
- package/dist/savings/types.js.map +0 -1
- package/dist/svm/constant.js.map +0 -1
- package/dist/svm/index.js.map +0 -1
- package/dist/svm/svm.js.map +0 -1
- package/dist/svm/transactionParsing.js.map +0 -1
- package/dist/svm/transactionSender.js.map +0 -1
- package/dist/svm/utils.js.map +0 -1
- package/dist/test.js.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/utils.js.map +0 -1
- package/dist/vm.js.map +0 -1
- package/dist/walletBip32.js.map +0 -1
- package/utils/savings/saving-actions.ts +0 -92
- 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
package/dist/utils.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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 =
|
|
51
|
-
|
|
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();
|
|
34
|
+
return crypto_js_1.default.lib.WordArray.random(16).toString();
|
|
55
35
|
}
|
|
56
|
-
static
|
|
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
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
|
|
68
|
-
|
|
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
|
-
|
|
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
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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("
|
|
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
|
package/dist/walletBip32.d.ts
CHANGED
|
@@ -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): {
|
package/dist/walletBip32.js
CHANGED
|
@@ -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");
|
|
46
|
+
const buffer_1 = require("buffer");
|
|
100
47
|
if (typeof window !== 'undefined') {
|
|
101
|
-
window.Buffer = buffer_1.Buffer;
|
|
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),
|
|
169
|
-
chainCode: hmacResult.slice(32, 64)
|
|
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.
|
|
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": "
|
|
44
|
-
"
|
|
45
|
-
"
|
|
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"
|