@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/svm/svm.js
CHANGED
|
@@ -8,9 +8,11 @@ const web3_js_1 = require("@solana/web3.js");
|
|
|
8
8
|
const walletBip32_1 = require("../walletBip32");
|
|
9
9
|
const vm_1 = require("../vm");
|
|
10
10
|
const IChainWallet_1 = require("../IChainWallet");
|
|
11
|
+
const vm_validation_1 = require("../vm-validation");
|
|
11
12
|
const utils_1 = require("./utils");
|
|
12
13
|
const bn_js_1 = __importDefault(require("bn.js"));
|
|
13
14
|
const tweetnacl_1 = __importDefault(require("tweetnacl"));
|
|
15
|
+
const bs58_1 = __importDefault(require("bs58"));
|
|
14
16
|
const price_1 = require("../price");
|
|
15
17
|
const transactionParsing_1 = require("./transactionParsing");
|
|
16
18
|
class SVMVM extends vm_1.VM {
|
|
@@ -25,7 +27,7 @@ class SVMVM extends vm_1.VM {
|
|
|
25
27
|
return false;
|
|
26
28
|
}
|
|
27
29
|
}
|
|
28
|
-
derivationPath = "m/44'/501'/";
|
|
30
|
+
derivationPath = "m/44'/501'/";
|
|
29
31
|
constructor(seed) {
|
|
30
32
|
super(seed, "SVM");
|
|
31
33
|
}
|
|
@@ -46,45 +48,286 @@ class SVMVM extends vm_1.VM {
|
|
|
46
48
|
return web3_js_1.Keypair.fromSeed(Buffer.from(entropy));
|
|
47
49
|
};
|
|
48
50
|
generatePrivateKey(index, seed, mnemonic, derivationPath = this.derivationPath) {
|
|
51
|
+
vm_validation_1.VMValidation.validateIndex(index, 'Wallet index');
|
|
52
|
+
vm_validation_1.VMValidation.validateDerivationPath(derivationPath + index + "'", 'SVM');
|
|
49
53
|
let _seed;
|
|
50
54
|
if (seed) {
|
|
55
|
+
vm_validation_1.VMValidation.validateSeed(seed);
|
|
51
56
|
_seed = seed;
|
|
52
57
|
}
|
|
53
58
|
else if (mnemonic) {
|
|
59
|
+
vm_validation_1.VMValidation.validateMnemonic(mnemonic);
|
|
54
60
|
_seed = vm_1.VM.mnemonicToSeed(mnemonic);
|
|
55
61
|
}
|
|
56
62
|
else {
|
|
63
|
+
this.checkNotDisposed();
|
|
57
64
|
_seed = this.seed;
|
|
58
65
|
}
|
|
59
66
|
const privateKey = (0, walletBip32_1.SVMDeriveChildPrivateKey)(_seed, index, derivationPath);
|
|
60
67
|
return { privateKey, index };
|
|
61
68
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
* - Main wallet: m/44'/501'/0'/0/0 (account index 0)
|
|
67
|
-
* - Savings 1: m/44'/501'/1'/0/0 (account index 1)
|
|
68
|
-
* - Savings 2: m/44'/501'/2'/0/0 (account index 2)
|
|
69
|
-
*
|
|
70
|
-
* @param accountIndex - The BIP-44 account index (0 for main, 1+ for savings)
|
|
71
|
-
* @returns Object containing privateKey (Keypair), address (PublicKey), and derivation path
|
|
72
|
-
*/
|
|
69
|
+
static fromMnemonic(mnemonic) {
|
|
70
|
+
const seed = vm_1.VM.mnemonicToSeed(mnemonic);
|
|
71
|
+
return new SVMVM(seed);
|
|
72
|
+
}
|
|
73
73
|
deriveSavingsAccount(accountIndex) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const derivationPath = `m/44'/501'/${accountIndex}'/0/0`;
|
|
77
|
-
// Derive the keypair using the account index in the path
|
|
78
|
-
const keypair = (0, walletBip32_1.SVMDeriveChildPrivateKey)(this.seed, 0, `m/44'/501'/${accountIndex}'/0/`);
|
|
74
|
+
const derivationPath = `m/44'/501'/${accountIndex}'/0'`;
|
|
75
|
+
const keypair = (0, walletBip32_1.SVMDeriveChildPrivateKey)(this.seed, 0, `m/44'/501'/${accountIndex}'/`);
|
|
79
76
|
return {
|
|
80
77
|
privateKey: keypair,
|
|
81
78
|
address: keypair.publicKey,
|
|
82
79
|
derivationPath
|
|
83
80
|
};
|
|
84
81
|
}
|
|
85
|
-
|
|
86
|
-
const
|
|
87
|
-
|
|
82
|
+
async discoverWallets(connection, options) {
|
|
83
|
+
const startTime = Date.now();
|
|
84
|
+
const { startIndex = 0, maxIndex = 100, gapLimit = 20, minBalance = BigInt(0), includeZeroBalance = false, includePrivateKeys = false, checkInParallel = true, batchSize = 10, checkDelay = checkInParallel ? 200 : 50, onProgress, onDiscovered } = options || {};
|
|
85
|
+
const discovered = [];
|
|
86
|
+
let consecutiveEmpty = 0;
|
|
87
|
+
let scannedIndices = 0;
|
|
88
|
+
let stoppedByGapLimit = false;
|
|
89
|
+
if (checkInParallel) {
|
|
90
|
+
for (let i = startIndex; i <= maxIndex; i += batchSize) {
|
|
91
|
+
const batchEnd = Math.min(i + batchSize, maxIndex + 1);
|
|
92
|
+
const batchPromises = [];
|
|
93
|
+
for (let j = i; j < batchEnd; j++) {
|
|
94
|
+
batchPromises.push(this.checkWalletBalance(j, connection));
|
|
95
|
+
}
|
|
96
|
+
const batchResults = await Promise.all(batchPromises);
|
|
97
|
+
for (let k = 0; k < batchResults.length; k++) {
|
|
98
|
+
const index = i + k;
|
|
99
|
+
const wallet = batchResults[k];
|
|
100
|
+
scannedIndices++;
|
|
101
|
+
if (wallet) {
|
|
102
|
+
const hasBalance = wallet.nativeBalance.amount > minBalance;
|
|
103
|
+
if (hasBalance || includeZeroBalance) {
|
|
104
|
+
if (!includePrivateKeys) {
|
|
105
|
+
delete wallet.privateKey;
|
|
106
|
+
}
|
|
107
|
+
discovered.push(wallet);
|
|
108
|
+
consecutiveEmpty = 0;
|
|
109
|
+
onDiscovered?.(wallet);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
consecutiveEmpty++;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
consecutiveEmpty++;
|
|
117
|
+
}
|
|
118
|
+
onProgress?.(scannedIndices, maxIndex - startIndex + 1, discovered.length);
|
|
119
|
+
if (consecutiveEmpty >= gapLimit) {
|
|
120
|
+
stoppedByGapLimit = true;
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (stoppedByGapLimit) {
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
if (batchEnd <= maxIndex) {
|
|
128
|
+
await this.sleep(checkDelay);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
for (let i = startIndex; i <= maxIndex; i++) {
|
|
134
|
+
const wallet = await this.checkWalletBalance(i, connection);
|
|
135
|
+
scannedIndices++;
|
|
136
|
+
if (wallet) {
|
|
137
|
+
const hasBalance = wallet.nativeBalance.amount > minBalance;
|
|
138
|
+
if (hasBalance || includeZeroBalance) {
|
|
139
|
+
if (!includePrivateKeys) {
|
|
140
|
+
delete wallet.privateKey;
|
|
141
|
+
}
|
|
142
|
+
discovered.push(wallet);
|
|
143
|
+
consecutiveEmpty = 0;
|
|
144
|
+
onDiscovered?.(wallet);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
consecutiveEmpty++;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
consecutiveEmpty++;
|
|
152
|
+
}
|
|
153
|
+
onProgress?.(scannedIndices, maxIndex - startIndex + 1, discovered.length);
|
|
154
|
+
if (consecutiveEmpty >= gapLimit) {
|
|
155
|
+
stoppedByGapLimit = true;
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
if (i < maxIndex) {
|
|
159
|
+
await this.sleep(checkDelay);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const totalBalance = discovered.reduce((sum, wallet) => sum + wallet.nativeBalance.amount, BigInt(0));
|
|
164
|
+
const duration = Date.now() - startTime;
|
|
165
|
+
return {
|
|
166
|
+
discovered,
|
|
167
|
+
scannedIndices,
|
|
168
|
+
highestIndex: startIndex + scannedIndices - 1,
|
|
169
|
+
totalBalance,
|
|
170
|
+
stoppedByGapLimit,
|
|
171
|
+
duration
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
async checkWalletBalance(index, connection, maxRetries = 3) {
|
|
175
|
+
const derivationPath = `m/44'/501'/${index}'/0'`;
|
|
176
|
+
const keypair = (0, walletBip32_1.SVMDeriveChildPrivateKey)(this.seed, 0, `m/44'/501'/${index}'/`);
|
|
177
|
+
const address = keypair.publicKey;
|
|
178
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
179
|
+
try {
|
|
180
|
+
const balanceLamports = await connection.getBalance(address);
|
|
181
|
+
const balanceSOL = balanceLamports / 1_000_000_000;
|
|
182
|
+
return {
|
|
183
|
+
index,
|
|
184
|
+
address: address.toString(),
|
|
185
|
+
derivationPath,
|
|
186
|
+
nativeBalance: {
|
|
187
|
+
amount: BigInt(balanceLamports),
|
|
188
|
+
formatted: balanceSOL,
|
|
189
|
+
symbol: 'SOL'
|
|
190
|
+
},
|
|
191
|
+
privateKey: bs58_1.default.encode(keypair.secretKey)
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
if (attempt === maxRetries - 1) {
|
|
196
|
+
console.error(`Failed to check balance for index ${index} after ${maxRetries} attempts:`, error);
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
const backoffMs = 1000 * Math.pow(2, attempt);
|
|
200
|
+
await this.sleep(backoffMs);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
205
|
+
sleep(ms) {
|
|
206
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
207
|
+
}
|
|
208
|
+
async discoverPockets(connection, options) {
|
|
209
|
+
const startTime = Date.now();
|
|
210
|
+
const { startIndex = 0, maxIndex = 100, gapLimit = 20, minBalance = BigInt(0), includeZeroBalance = false, includePrivateKeys = false, checkInParallel = true, batchSize = 10, checkDelay = checkInParallel ? 200 : 50, onProgress, onDiscovered, walletIndex = 0, } = options || {};
|
|
211
|
+
const discovered = [];
|
|
212
|
+
let consecutiveEmpty = 0;
|
|
213
|
+
let scannedIndices = 0;
|
|
214
|
+
let stoppedByGapLimit = false;
|
|
215
|
+
if (checkInParallel) {
|
|
216
|
+
for (let i = startIndex; i <= maxIndex; i += batchSize) {
|
|
217
|
+
const batchEnd = Math.min(i + batchSize, maxIndex + 1);
|
|
218
|
+
const batchPromises = [];
|
|
219
|
+
for (let j = i; j < batchEnd; j++) {
|
|
220
|
+
batchPromises.push(this.checkPocketBalance(j, walletIndex, connection));
|
|
221
|
+
}
|
|
222
|
+
const batchResults = await Promise.all(batchPromises);
|
|
223
|
+
for (let k = 0; k < batchResults.length; k++) {
|
|
224
|
+
const index = i + k;
|
|
225
|
+
const pocket = batchResults[k];
|
|
226
|
+
scannedIndices++;
|
|
227
|
+
if (pocket) {
|
|
228
|
+
const hasBalance = pocket.nativeBalance.amount > minBalance;
|
|
229
|
+
if (hasBalance || includeZeroBalance) {
|
|
230
|
+
if (!includePrivateKeys) {
|
|
231
|
+
delete pocket.privateKey;
|
|
232
|
+
}
|
|
233
|
+
discovered.push(pocket);
|
|
234
|
+
consecutiveEmpty = 0;
|
|
235
|
+
onDiscovered?.(pocket);
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
consecutiveEmpty++;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
consecutiveEmpty++;
|
|
243
|
+
}
|
|
244
|
+
onProgress?.(scannedIndices, maxIndex - startIndex + 1, discovered.length);
|
|
245
|
+
if (consecutiveEmpty >= gapLimit) {
|
|
246
|
+
stoppedByGapLimit = true;
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
if (stoppedByGapLimit) {
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
if (batchEnd <= maxIndex) {
|
|
254
|
+
await this.sleep(checkDelay);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
for (let i = startIndex; i <= maxIndex; i++) {
|
|
260
|
+
const pocket = await this.checkPocketBalance(i, walletIndex, connection);
|
|
261
|
+
scannedIndices++;
|
|
262
|
+
if (pocket) {
|
|
263
|
+
const hasBalance = pocket.nativeBalance.amount > minBalance;
|
|
264
|
+
if (hasBalance || includeZeroBalance) {
|
|
265
|
+
if (!includePrivateKeys) {
|
|
266
|
+
delete pocket.privateKey;
|
|
267
|
+
}
|
|
268
|
+
discovered.push(pocket);
|
|
269
|
+
consecutiveEmpty = 0;
|
|
270
|
+
onDiscovered?.(pocket);
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
consecutiveEmpty++;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
consecutiveEmpty++;
|
|
278
|
+
}
|
|
279
|
+
onProgress?.(scannedIndices, maxIndex - startIndex + 1, discovered.length);
|
|
280
|
+
if (consecutiveEmpty >= gapLimit) {
|
|
281
|
+
stoppedByGapLimit = true;
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
284
|
+
if (i < maxIndex) {
|
|
285
|
+
await this.sleep(checkDelay);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
const totalBalance = discovered.reduce((sum, pocket) => sum + pocket.nativeBalance.amount, BigInt(0));
|
|
290
|
+
const duration = Date.now() - startTime;
|
|
291
|
+
return {
|
|
292
|
+
discovered,
|
|
293
|
+
scannedIndices,
|
|
294
|
+
highestIndex: startIndex + scannedIndices - 1,
|
|
295
|
+
totalBalance,
|
|
296
|
+
stoppedByGapLimit,
|
|
297
|
+
duration
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
async checkPocketBalance(accountIndex, walletIndex, connection, maxRetries = 3) {
|
|
301
|
+
const pocketIndex = accountIndex + 1;
|
|
302
|
+
const derivationPath = `m/44'/501'/${pocketIndex}'/0'`;
|
|
303
|
+
const keypair = (0, walletBip32_1.SVMDeriveChildPrivateKey)(this.seed, 0, `m/44'/501'/${pocketIndex}'/`);
|
|
304
|
+
const address = keypair.publicKey;
|
|
305
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
306
|
+
try {
|
|
307
|
+
const balanceLamports = await connection.getBalance(address);
|
|
308
|
+
const balanceSOL = balanceLamports / 1_000_000_000;
|
|
309
|
+
return {
|
|
310
|
+
index: accountIndex,
|
|
311
|
+
address: address.toString(),
|
|
312
|
+
derivationPath,
|
|
313
|
+
nativeBalance: {
|
|
314
|
+
amount: BigInt(balanceLamports),
|
|
315
|
+
formatted: balanceSOL,
|
|
316
|
+
symbol: 'SOL'
|
|
317
|
+
},
|
|
318
|
+
privateKey: bs58_1.default.encode(keypair.secretKey)
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
catch (error) {
|
|
322
|
+
if (attempt === maxRetries - 1) {
|
|
323
|
+
console.error(`Failed to check pocket at account ${accountIndex} after ${maxRetries} attempts:`, error);
|
|
324
|
+
return null;
|
|
325
|
+
}
|
|
326
|
+
const backoffMs = 1000 * Math.pow(2, attempt);
|
|
327
|
+
await this.sleep(backoffMs);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return null;
|
|
88
331
|
}
|
|
89
332
|
}
|
|
90
333
|
exports.SVMVM = SVMVM;
|
|
@@ -102,31 +345,25 @@ class SVMChainWallet extends IChainWallet_1.ChainWallet {
|
|
|
102
345
|
return web3_js_1.Keypair.fromSeed(Buffer.from(entropy));
|
|
103
346
|
};
|
|
104
347
|
async getNativeBalance() {
|
|
105
|
-
// Implement native balance retrieval logic here
|
|
106
348
|
return await SVMVM.getNativeBalance(this.address, this.connection);
|
|
107
349
|
}
|
|
108
350
|
async getTokenBalance(tokenAddress) {
|
|
109
|
-
// Implement token balance retrieval logic here
|
|
110
351
|
return await SVMVM.getTokenBalance(this.address, (tokenAddress), this.connection);
|
|
111
352
|
}
|
|
112
353
|
async discoverToken() {
|
|
113
|
-
// Implement token discovery logic here
|
|
114
354
|
const tokens = await (0, utils_1.discoverTokens)(this.address, this.connection);
|
|
115
355
|
return tokens;
|
|
116
356
|
}
|
|
117
357
|
async discoverNFT() {
|
|
118
|
-
// Implement NFT discovery logic here
|
|
119
358
|
const nfts = await (0, utils_1.fetchWalletNfts)(this.address, this.connection);
|
|
120
359
|
return nfts;
|
|
121
360
|
}
|
|
122
361
|
async transferNative(to, amount) {
|
|
123
|
-
// Implement native transfer logic here
|
|
124
362
|
const transaction = await (0, utils_1.getTransferNativeTransaction)(this.privateKey, to, amount, this.connection);
|
|
125
363
|
const hash = await SVMVM.signAndSendTransaction(transaction, this.connection, this.privateKey);
|
|
126
364
|
return { success: true, hash };
|
|
127
365
|
}
|
|
128
366
|
async transferToken(token, to, amount) {
|
|
129
|
-
// Implement token transfer logic here
|
|
130
367
|
const transaction = await (0, utils_1.getTransferTokenTransaction)(this.privateKey, new web3_js_1.PublicKey(to), token, amount, this.connection);
|
|
131
368
|
const hash = await SVMVM.signAndSendTransaction(transaction, this.connection, this.privateKey);
|
|
132
369
|
return { success: true, hash };
|
|
@@ -176,26 +413,7 @@ class SVMChainWallet extends IChainWallet_1.ChainWallet {
|
|
|
176
413
|
}
|
|
177
414
|
const fromTokenMint = new web3_js_1.PublicKey(fromToken.address);
|
|
178
415
|
const toTokenMint = toToken;
|
|
179
|
-
// const validation = await validateJupiterTokens(
|
|
180
|
-
// fromTokenMint.toString(),
|
|
181
|
-
// toTokenMint.toString()
|
|
182
|
-
// );
|
|
183
|
-
// if (!validation.valid) {
|
|
184
|
-
// return {
|
|
185
|
-
// success: false,
|
|
186
|
-
// hash: "",
|
|
187
|
-
// error: validation.message || "Token validation failed"
|
|
188
|
-
// };
|
|
189
|
-
// }
|
|
190
416
|
const baseAmount = (0, utils_1.uiAmountToBaseUnits)(amount, fromToken.decimals);
|
|
191
|
-
// const balance = await this.getTokenBalance(fromTokenMint);
|
|
192
|
-
// if (balance.balance.lt(new BN(baseAmount))) {
|
|
193
|
-
// return {
|
|
194
|
-
// success: false,
|
|
195
|
-
// hash: "",
|
|
196
|
-
// error: "Insufficient balance for swap"
|
|
197
|
-
// };
|
|
198
|
-
// }
|
|
199
417
|
const swapResult = await (0, utils_1.executeJupiterSwap)({
|
|
200
418
|
fromToken: fromTokenMint,
|
|
201
419
|
toToken: toTokenMint,
|
|
@@ -251,4 +469,3 @@ class SVMChainWallet extends IChainWallet_1.ChainWallet {
|
|
|
251
469
|
};
|
|
252
470
|
}
|
|
253
471
|
exports.SVMChainWallet = SVMChainWallet;
|
|
254
|
-
//# sourceMappingURL=svm.js.map
|
|
@@ -18,11 +18,4 @@ export interface TransactionHistoryOptions {
|
|
|
18
18
|
before?: string;
|
|
19
19
|
until?: string;
|
|
20
20
|
}
|
|
21
|
-
/**
|
|
22
|
-
* Fetches and parses transaction history for a Solana wallet address
|
|
23
|
-
* @param connection - Solana RPC connection
|
|
24
|
-
* @param walletAddress - Public key of the wallet (string or PublicKey)
|
|
25
|
-
* @param options - Optional parameters for pagination and filtering
|
|
26
|
-
* @returns Array of parsed transaction history items
|
|
27
|
-
*/
|
|
28
21
|
export declare function getSVMTransactionHistory(connection: Connection, walletAddress: PublicKey, options?: TransactionHistoryOptions): Promise<SVMTransactionHistoryItem[]>;
|
|
@@ -3,36 +3,24 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.getSVMTransactionHistory = getSVMTransactionHistory;
|
|
4
4
|
const web3_js_1 = require("@solana/web3.js");
|
|
5
5
|
const constant_1 = require("../constant");
|
|
6
|
-
/**
|
|
7
|
-
* Fetches and parses transaction history for a Solana wallet address
|
|
8
|
-
* @param connection - Solana RPC connection
|
|
9
|
-
* @param walletAddress - Public key of the wallet (string or PublicKey)
|
|
10
|
-
* @param options - Optional parameters for pagination and filtering
|
|
11
|
-
* @returns Array of parsed transaction history items
|
|
12
|
-
*/
|
|
13
6
|
async function getSVMTransactionHistory(connection, walletAddress, options = {}) {
|
|
14
7
|
const { limit = 50, before, until } = options;
|
|
15
8
|
const publicKey = typeof walletAddress === 'string'
|
|
16
9
|
? new web3_js_1.PublicKey(walletAddress)
|
|
17
10
|
: walletAddress;
|
|
18
11
|
try {
|
|
19
|
-
// Fetch signature info
|
|
20
12
|
const signatures = await connection.getSignaturesForAddress(publicKey, {
|
|
21
13
|
limit,
|
|
22
14
|
before,
|
|
23
15
|
until,
|
|
24
16
|
});
|
|
25
17
|
console.log(`Found ${signatures.length} transactions`);
|
|
26
|
-
|
|
27
|
-
const transactions = await fetchTransactionsInBatches(connection, signatures, 5 // batch size
|
|
28
|
-
);
|
|
29
|
-
// Parse transactions into a user-friendly format
|
|
18
|
+
const transactions = await fetchTransactionsInBatches(connection, signatures, 5);
|
|
30
19
|
const history = [];
|
|
31
20
|
for (let i = 0; i < transactions.length; i++) {
|
|
32
21
|
const tx = transactions[i];
|
|
33
22
|
const sigInfo = signatures[i];
|
|
34
23
|
if (!tx) {
|
|
35
|
-
// Transaction might be null if it's not available
|
|
36
24
|
history.push({
|
|
37
25
|
hash: sigInfo.signature,
|
|
38
26
|
timestamp: sigInfo.blockTime,
|
|
@@ -63,9 +51,6 @@ async function getSVMTransactionHistory(connection, walletAddress, options = {})
|
|
|
63
51
|
throw error;
|
|
64
52
|
}
|
|
65
53
|
}
|
|
66
|
-
/**
|
|
67
|
-
* Fetches transactions in batches to avoid overwhelming the RPC
|
|
68
|
-
*/
|
|
69
54
|
async function fetchTransactionsInBatches(connection, signatures, batchSize) {
|
|
70
55
|
const transactions = [];
|
|
71
56
|
for (let i = 0; i < signatures.length; i += batchSize) {
|
|
@@ -75,23 +60,16 @@ async function fetchTransactionsInBatches(connection, signatures, batchSize) {
|
|
|
75
60
|
}));
|
|
76
61
|
const batchResults = await Promise.all(batchPromises);
|
|
77
62
|
transactions.push(...batchResults);
|
|
78
|
-
// Small delay to avoid rate limiting
|
|
79
63
|
if (i + batchSize < signatures.length) {
|
|
80
64
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
81
65
|
}
|
|
82
66
|
}
|
|
83
67
|
return transactions;
|
|
84
68
|
}
|
|
85
|
-
/**
|
|
86
|
-
* Parses a transaction into a simplified format
|
|
87
|
-
*/
|
|
88
69
|
function parseTransaction(tx, walletAddress) {
|
|
89
70
|
const fee = tx.meta?.fee || 0;
|
|
90
|
-
// Try to determine transaction type and extract relevant info
|
|
91
71
|
const instructions = tx.transaction.message.instructions;
|
|
92
|
-
// Check for token transfers
|
|
93
72
|
if (tx.meta?.preTokenBalances && tx.meta?.postTokenBalances) {
|
|
94
|
-
// console.log('tx.meta: ', tx.meta);
|
|
95
73
|
const tokenTransfer = findTokenTransfer(tx.meta.preTokenBalances, tx.meta.postTokenBalances, walletAddress);
|
|
96
74
|
if (tokenTransfer) {
|
|
97
75
|
return {
|
|
@@ -104,7 +82,6 @@ function parseTransaction(tx, walletAddress) {
|
|
|
104
82
|
};
|
|
105
83
|
}
|
|
106
84
|
}
|
|
107
|
-
// Check for SOL transfers
|
|
108
85
|
if (tx.meta?.preBalances && tx.meta?.postBalances) {
|
|
109
86
|
const solTransfer = findSolTransfer(tx.meta.preBalances, tx.meta.postBalances, tx.transaction.message.accountKeys, walletAddress);
|
|
110
87
|
if (solTransfer) {
|
|
@@ -118,9 +95,7 @@ function parseTransaction(tx, walletAddress) {
|
|
|
118
95
|
};
|
|
119
96
|
}
|
|
120
97
|
}
|
|
121
|
-
// Check for memo
|
|
122
98
|
const memo = extractMemo(instructions);
|
|
123
|
-
// Determine general type based on instructions
|
|
124
99
|
const type = determineTransactionType(instructions);
|
|
125
100
|
return {
|
|
126
101
|
fee,
|
|
@@ -128,9 +103,6 @@ function parseTransaction(tx, walletAddress) {
|
|
|
128
103
|
memo,
|
|
129
104
|
};
|
|
130
105
|
}
|
|
131
|
-
/**
|
|
132
|
-
* Finds token transfers in the transaction
|
|
133
|
-
*/
|
|
134
106
|
function findTokenTransfer(preBalances, postBalances, walletAddress) {
|
|
135
107
|
for (let i = 0; i < postBalances.length; i++) {
|
|
136
108
|
const post = postBalances[i];
|
|
@@ -158,27 +130,21 @@ function findTokenTransfer(preBalances, postBalances, walletAddress) {
|
|
|
158
130
|
}
|
|
159
131
|
return null;
|
|
160
132
|
}
|
|
161
|
-
/**
|
|
162
|
-
* Finds SOL transfers in the transaction
|
|
163
|
-
*/
|
|
164
133
|
function findSolTransfer(preBalances, postBalances, accountKeys, walletAddress) {
|
|
165
134
|
for (let i = 0; i < preBalances.length; i++) {
|
|
166
135
|
const diff = postBalances[i] - preBalances[i];
|
|
167
136
|
const account = accountKeys[i];
|
|
168
137
|
const accountPubkey = typeof account === 'string' ? account : account.pubkey.toBase58();
|
|
169
|
-
if (Math.abs(diff) > 5000 && accountPubkey === walletAddress) {
|
|
138
|
+
if (Math.abs(diff) > 5000 && accountPubkey === walletAddress) {
|
|
170
139
|
return {
|
|
171
140
|
from: diff < 0 ? accountPubkey : 'unknown',
|
|
172
141
|
to: diff > 0 ? accountPubkey : 'unknown',
|
|
173
|
-
amount: Math.abs(diff) / 1e9,
|
|
142
|
+
amount: Math.abs(diff) / 1e9,
|
|
174
143
|
};
|
|
175
144
|
}
|
|
176
145
|
}
|
|
177
146
|
return null;
|
|
178
147
|
}
|
|
179
|
-
/**
|
|
180
|
-
* Extracts memo from transaction instructions
|
|
181
|
-
*/
|
|
182
148
|
function extractMemo(instructions) {
|
|
183
149
|
for (const instruction of instructions) {
|
|
184
150
|
if (instruction.program === 'spl-memo' || instruction.programId?.toBase58() === 'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr') {
|
|
@@ -187,9 +153,6 @@ function extractMemo(instructions) {
|
|
|
187
153
|
}
|
|
188
154
|
return undefined;
|
|
189
155
|
}
|
|
190
|
-
/**
|
|
191
|
-
* Determines the general type of transaction
|
|
192
|
-
*/
|
|
193
156
|
function determineTransactionType(instructions) {
|
|
194
157
|
if (instructions.length === 0)
|
|
195
158
|
return constant_1.TRANSACTION_TYPE.UNKNOWN;
|
|
@@ -204,4 +167,3 @@ function determineTransactionType(instructions) {
|
|
|
204
167
|
return constant_1.TRANSACTION_TYPE.STAKING;
|
|
205
168
|
return constant_1.TRANSACTION_TYPE.PROGRAM_INTERACTION;
|
|
206
169
|
}
|
|
207
|
-
//# sourceMappingURL=transactionParsing.js.map
|
|
@@ -31,8 +31,6 @@ async function transactionSenderAndConfirmationWaiter({ connection, serializedTr
|
|
|
31
31
|
try {
|
|
32
32
|
abortableResender();
|
|
33
33
|
const lastValidBlockHeight = blockhashWithExpiryBlockHeight.lastValidBlockHeight - 150;
|
|
34
|
-
// this would throw TransactionExpiredBlockheightExceededError
|
|
35
|
-
// console.log("conforming the transaction ....")
|
|
36
34
|
const res = await Promise.race([
|
|
37
35
|
connection.confirmTransaction({
|
|
38
36
|
...blockhashWithExpiryBlockHeight,
|
|
@@ -41,7 +39,6 @@ async function transactionSenderAndConfirmationWaiter({ connection, serializedTr
|
|
|
41
39
|
abortSignal,
|
|
42
40
|
}, "confirmed"),
|
|
43
41
|
new Promise(async (resolve) => {
|
|
44
|
-
// in case ws socket died
|
|
45
42
|
while (!abortSignal.aborted) {
|
|
46
43
|
await wait(2_000);
|
|
47
44
|
const tx = await connection.getSignatureStatus(txid, {
|
|
@@ -56,20 +53,15 @@ async function transactionSenderAndConfirmationWaiter({ connection, serializedTr
|
|
|
56
53
|
console.log('res: ', res);
|
|
57
54
|
}
|
|
58
55
|
catch (e) {
|
|
59
|
-
// console.log('e: ', e);
|
|
60
56
|
if (e instanceof web3_js_1.TransactionExpiredBlockheightExceededError) {
|
|
61
|
-
// we consume this error and getTransaction would return null
|
|
62
|
-
// return null;
|
|
63
57
|
}
|
|
64
58
|
else {
|
|
65
|
-
// invalid state from web3.js
|
|
66
59
|
throw e;
|
|
67
60
|
}
|
|
68
61
|
}
|
|
69
62
|
finally {
|
|
70
63
|
controller.abort();
|
|
71
64
|
}
|
|
72
|
-
// in case rpc is not synced yet, we add some retries
|
|
73
65
|
const response = (0, promise_retry_1.default)(async (retry) => {
|
|
74
66
|
const response = await connection.getTransaction(txid, {
|
|
75
67
|
commitment: "confirmed",
|
|
@@ -85,4 +77,3 @@ async function transactionSenderAndConfirmationWaiter({ connection, serializedTr
|
|
|
85
77
|
});
|
|
86
78
|
return response;
|
|
87
79
|
}
|
|
88
|
-
//# sourceMappingURL=transactionSender.js.map
|
package/dist/svm/utils.d.ts
CHANGED
|
@@ -91,17 +91,5 @@ export declare const validateJupiterTokens: (inputMint: string, outputMint: stri
|
|
|
91
91
|
}>;
|
|
92
92
|
export declare const transformSolanaNFTToUnified: (nft: SolanaNFT) => NFT;
|
|
93
93
|
export declare const fetchWalletNfts: (walletAddress: PublicKey, connection: Connection) => Promise<NFT[]>;
|
|
94
|
-
/**
|
|
95
|
-
* Get NFT collection details for a specific collection on Solana
|
|
96
|
-
* @param walletAddress - User's wallet public key
|
|
97
|
-
* @param collectionAddress - The NFT collection address (can be collection mint or update authority)
|
|
98
|
-
* @param connection - Solana connection
|
|
99
|
-
* @returns NFTCollection object with collection details and user's NFTs in that collection
|
|
100
|
-
*
|
|
101
|
-
* Note: On Solana, collections can be identified by:
|
|
102
|
-
* - Collection mint address (from collection field in NFT metadata)
|
|
103
|
-
* - Update authority (who can modify the NFT metadata)
|
|
104
|
-
* This function filters by the collection.address field which is typically the collection mint
|
|
105
|
-
*/
|
|
106
94
|
export declare const getNFTCollection: (walletAddress: PublicKey, collectionAddress: string, connection: Connection) => Promise<NFTCollection | null>;
|
|
107
95
|
export {};
|