@deserialize/multi-vm-wallet 1.4.2 → 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 +9 -51
- package/dist/evm/evm.js +338 -76
- 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.js +0 -1
- package/dist/savings/saving-manager.d.ts +10 -11
- package/dist/savings/saving-manager.js +79 -22
- 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 +11 -1
- package/dist/svm/svm.js +267 -27
- 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 +6 -98
- 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 +12 -2
- package/dist/vm.js +61 -16
- package/dist/walletBip32.js +15 -70
- 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/evm/evm.ts +554 -8
- 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/saving-manager.ts +526 -16
- package/utils/savings/savings-operations.ts +509 -0
- package/utils/savings/validation.ts +187 -0
- package/utils/svm/svm.ts +476 -5
- package/utils/test.ts +2 -2
- package/utils/transaction-utils.ts +394 -0
- package/utils/types.ts +100 -0
- package/utils/vm-validation.ts +280 -0
- package/utils/vm.ts +197 -10
- package/utils/walletBip32.ts +39 -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/saving-manager.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
|
@@ -5,109 +5,47 @@ exports.getEVMTransactionHistoryWithAPI = getEVMTransactionHistoryWithAPI;
|
|
|
5
5
|
const viem_1 = require("viem");
|
|
6
6
|
const constant_1 = require("../constant");
|
|
7
7
|
const helpers_1 = require("../helpers");
|
|
8
|
-
// Mapping of chainId to RouteScan network name
|
|
9
8
|
const CHAIN_ID_TO_NETWORK = {
|
|
10
|
-
1: 'mainnet',
|
|
11
|
-
5: 'testnet',
|
|
12
|
-
11155111: 'testnet',
|
|
13
|
-
137: 'mainnet',
|
|
14
|
-
80001: 'testnet',
|
|
15
|
-
56: 'mainnet',
|
|
16
|
-
97: 'testnet',
|
|
17
|
-
43114: 'mainnet',
|
|
18
|
-
43113: 'testnet',
|
|
19
|
-
42161: 'mainnet',
|
|
20
|
-
421611: 'testnet',
|
|
21
|
-
10: 'mainnet',
|
|
22
|
-
420: 'testnet',
|
|
23
|
-
8453: 'mainnet',
|
|
24
|
-
84531: 'testnet',
|
|
25
|
-
16661: 'mainnet',
|
|
9
|
+
1: 'mainnet',
|
|
10
|
+
5: 'testnet',
|
|
11
|
+
11155111: 'testnet',
|
|
12
|
+
137: 'mainnet',
|
|
13
|
+
80001: 'testnet',
|
|
14
|
+
56: 'mainnet',
|
|
15
|
+
97: 'testnet',
|
|
16
|
+
43114: 'mainnet',
|
|
17
|
+
43113: 'testnet',
|
|
18
|
+
42161: 'mainnet',
|
|
19
|
+
421611: 'testnet',
|
|
20
|
+
10: 'mainnet',
|
|
21
|
+
420: 'testnet',
|
|
22
|
+
8453: 'mainnet',
|
|
23
|
+
84531: 'testnet',
|
|
24
|
+
16661: 'mainnet',
|
|
26
25
|
};
|
|
27
|
-
// ERC20 Transfer event signature
|
|
28
26
|
const ERC20_TRANSFER_EVENT = (0, viem_1.parseAbi)([
|
|
29
27
|
'event Transfer(address indexed from, address indexed to, uint256 value)'
|
|
30
28
|
]);
|
|
31
|
-
// ERC721 Transfer event signature
|
|
32
29
|
const ERC721_TRANSFER_EVENT = (0, viem_1.parseAbi)([
|
|
33
30
|
'event Transfer(address indexed from, address indexed to, uint256 indexed tokenId)'
|
|
34
31
|
]);
|
|
35
|
-
// ERC1155 TransferSingle event signature
|
|
36
32
|
const ERC1155_TRANSFER_SINGLE_EVENT = (0, viem_1.parseAbi)([
|
|
37
33
|
'event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value)'
|
|
38
34
|
]);
|
|
39
|
-
// ERC1155 TransferBatch event signature
|
|
40
35
|
const ERC1155_TRANSFER_BATCH_EVENT = (0, viem_1.parseAbi)([
|
|
41
36
|
'event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values)'
|
|
42
37
|
]);
|
|
43
|
-
/**
|
|
44
|
-
* Fetches and parses transaction history for an EVM wallet address
|
|
45
|
-
* @param client - Viem public client
|
|
46
|
-
* @param walletAddress - Ethereum address
|
|
47
|
-
* @param options - Optional parameters for filtering and features
|
|
48
|
-
* @returns Array of parsed transaction history items
|
|
49
|
-
*/
|
|
50
38
|
async function getEVMTransactionHistory(client, walletAddress, options = {}) {
|
|
51
|
-
// const {
|
|
52
|
-
// startBlock = 0n,
|
|
53
|
-
// endBlock,
|
|
54
|
-
// includeTokenTransfers = true,
|
|
55
|
-
// includeNFTTransfers = true,
|
|
56
|
-
// } = options;
|
|
57
|
-
// try {
|
|
58
|
-
// const currentBlock = await client.getBlockNumber();
|
|
59
|
-
// const toBlock = endBlock || currentBlock;
|
|
60
|
-
// // For wallet UI, we typically want recent transactions
|
|
61
|
-
// // Start scanning from current block backwards
|
|
62
|
-
// const scanStartBlock = startBlock > 0n ? startBlock : (currentBlock > 5000n ? currentBlock - 5000n : 0n);
|
|
63
|
-
// console.log(`Fetching recent transactions from block ${scanStartBlock} to ${toBlock}`);
|
|
64
|
-
// // Get transaction hashes for the address (max 15 transactions)
|
|
65
|
-
// const txHashes = await getRecentTransactionHashes(
|
|
66
|
-
// client,
|
|
67
|
-
// walletAddress,
|
|
68
|
-
// scanStartBlock,
|
|
69
|
-
// toBlock,
|
|
70
|
-
// 15 // max transactions to fetch
|
|
71
|
-
// );
|
|
72
|
-
// console.log(`Found ${txHashes.length} unique transactions`);
|
|
73
|
-
// // Fetch full transaction details in batches
|
|
74
|
-
// const transactions = await fetchTransactionsInBatches(client, txHashes, 10);
|
|
75
|
-
// // Parse each transaction
|
|
76
|
-
// const history: EVMTransactionHistoryItem[] = [];
|
|
77
|
-
// for (const { tx, receipt, block } of transactions) {
|
|
78
|
-
// if (!tx || !receipt) continue;
|
|
79
|
-
// const parsed = await parseEVMTransaction(
|
|
80
|
-
// client,
|
|
81
|
-
// tx,
|
|
82
|
-
// receipt,
|
|
83
|
-
// block?.timestamp || null,
|
|
84
|
-
// walletAddress,
|
|
85
|
-
// includeTokenTransfers,
|
|
86
|
-
// includeNFTTransfers
|
|
87
|
-
// );
|
|
88
|
-
// history.push(parsed);
|
|
89
|
-
// }
|
|
90
|
-
// // Sort by block number (newest first)
|
|
91
|
-
// history.sort((a, b) => Number(b.blockNumber - a.blockNumber));
|
|
92
|
-
// return history;
|
|
93
|
-
// } catch (error) {
|
|
94
|
-
// console.error('Error fetching EVM transaction history:', error);
|
|
95
|
-
// throw error;
|
|
96
|
-
// }
|
|
97
39
|
if (client.chain?.id === undefined)
|
|
98
40
|
throw new Error("Chain Id is Undefined");
|
|
99
41
|
const chainId = client.chain.id;
|
|
100
42
|
const network = CHAIN_ID_TO_NETWORK[chainId];
|
|
101
|
-
// Try RouteScan first if network mapping exists
|
|
102
43
|
if (network) {
|
|
103
44
|
try {
|
|
104
45
|
console.log(`Fetching transaction history from RouteScan for chain ${chainId} (${network})`);
|
|
105
|
-
const routeScanResponse = await helpers_1.RouteScanAPI.getTxList(network, chainId, walletAddress, 0, 99999999, 1, 20,
|
|
106
|
-
'desc' // newest first
|
|
107
|
-
);
|
|
46
|
+
const routeScanResponse = await helpers_1.RouteScanAPI.getTxList(network, chainId, walletAddress, 0, 99999999, 1, 20, 'desc');
|
|
108
47
|
if (routeScanResponse.status === '1' && routeScanResponse.result) {
|
|
109
48
|
console.log(`RouteScan returned ${routeScanResponse.result.length} transactions`);
|
|
110
|
-
// Convert RouteScan format to our EVMTransactionHistoryItem format
|
|
111
49
|
return routeScanResponse.result.map(tx => ({
|
|
112
50
|
hash: tx.hash,
|
|
113
51
|
timestamp: parseInt(tx.timeStamp),
|
|
@@ -118,11 +56,9 @@ async function getEVMTransactionHistory(client, walletAddress, options = {}) {
|
|
|
118
56
|
to: tx.to || null,
|
|
119
57
|
blockNumber: BigInt(tx.blockNumber),
|
|
120
58
|
gasUsed: BigInt(tx.gasUsed),
|
|
121
|
-
gasPrice: (0, viem_1.formatUnits)(BigInt(tx.gasPrice), 9),
|
|
59
|
+
gasPrice: (0, viem_1.formatUnits)(BigInt(tx.gasPrice), 9),
|
|
122
60
|
value: (0, viem_1.formatEther)(BigInt(tx.value)),
|
|
123
61
|
method: tx.methodId || undefined,
|
|
124
|
-
// Token and NFT transfers would need additional API calls
|
|
125
|
-
// We'll skip them for now to keep it simple
|
|
126
62
|
}));
|
|
127
63
|
}
|
|
128
64
|
}
|
|
@@ -130,34 +66,26 @@ async function getEVMTransactionHistory(client, walletAddress, options = {}) {
|
|
|
130
66
|
console.warn('RouteScan failed, falling back to HelperAPI:', error);
|
|
131
67
|
}
|
|
132
68
|
}
|
|
133
|
-
// Fallback to HelperAPI
|
|
134
69
|
console.log(`Fetching transaction history from HelperAPI for chain ${chainId}`);
|
|
135
70
|
return await helpers_1.HelperAPI.getTransactionHistory(walletAddress, "EVM", chainId);
|
|
136
71
|
}
|
|
137
|
-
/**
|
|
138
|
-
* Determine transaction type from input data and value (simpler version for RouteScan data)
|
|
139
|
-
*/
|
|
140
72
|
function determineTransactionTypeFromInput(input, value) {
|
|
141
73
|
if (input === '0x' || input === '') {
|
|
142
74
|
return BigInt(value) > 0n ? constant_1.TRANSACTION_TYPE.NATIVE_TRANSFER : constant_1.TRANSACTION_TYPE.CONTRACT_INTERACTION;
|
|
143
75
|
}
|
|
144
76
|
const methodSig = input.slice(0, 10);
|
|
145
77
|
if (methodSig === '0xa9059cbb')
|
|
146
|
-
return constant_1.TRANSACTION_TYPE.TOKEN_TRANSFER;
|
|
78
|
+
return constant_1.TRANSACTION_TYPE.TOKEN_TRANSFER;
|
|
147
79
|
if (methodSig === '0x23b872dd')
|
|
148
|
-
return constant_1.TRANSACTION_TYPE.TOKEN_TRANSFER;
|
|
80
|
+
return constant_1.TRANSACTION_TYPE.TOKEN_TRANSFER;
|
|
149
81
|
if (methodSig === '0x42842e0e')
|
|
150
|
-
return constant_1.TRANSACTION_TYPE.NFT_TRANSFER;
|
|
82
|
+
return constant_1.TRANSACTION_TYPE.NFT_TRANSFER;
|
|
151
83
|
if (methodSig === '0xf242432a')
|
|
152
|
-
return constant_1.TRANSACTION_TYPE.NFT_TRANSFER;
|
|
84
|
+
return constant_1.TRANSACTION_TYPE.NFT_TRANSFER;
|
|
153
85
|
if (BigInt(value) > 0n)
|
|
154
86
|
return constant_1.TRANSACTION_TYPE.NATIVE_TRANSFER;
|
|
155
87
|
return constant_1.TRANSACTION_TYPE.CONTRACT_INTERACTION;
|
|
156
88
|
}
|
|
157
|
-
/**
|
|
158
|
-
* Gets recent transaction hashes by scanning blocks backwards
|
|
159
|
-
* Uses batched parallel requests for better performance
|
|
160
|
-
*/
|
|
161
89
|
async function getRecentTransactionHashes(client, address, startBlock, endBlock, maxTransactions = 15, batchSize = 9) {
|
|
162
90
|
const txHashes = [];
|
|
163
91
|
const seenHashes = new Map();
|
|
@@ -165,16 +93,13 @@ async function getRecentTransactionHashes(client, address, startBlock, endBlock,
|
|
|
165
93
|
let currentBlock = endBlock;
|
|
166
94
|
let blocksScanned = 0n;
|
|
167
95
|
console.log(`Scanning blocks backwards from ${endBlock}...`);
|
|
168
|
-
// Iterate backwards in batches
|
|
169
96
|
while (currentBlock >= startBlock && txHashes.length < maxTransactions) {
|
|
170
|
-
// Create batch of block numbers to fetch
|
|
171
97
|
const blockNumbers = [];
|
|
172
98
|
for (let i = 0; i < batchSize && currentBlock >= startBlock; i++) {
|
|
173
99
|
blockNumbers.push(currentBlock);
|
|
174
100
|
currentBlock--;
|
|
175
101
|
}
|
|
176
102
|
try {
|
|
177
|
-
// Fetch all blocks in parallel
|
|
178
103
|
const blocks = await Promise.all(blockNumbers.map(blockNumber => client.getBlock({
|
|
179
104
|
blockNumber,
|
|
180
105
|
includeTransactions: true,
|
|
@@ -184,14 +109,12 @@ async function getRecentTransactionHashes(client, address, startBlock, endBlock,
|
|
|
184
109
|
})));
|
|
185
110
|
blocks.length;
|
|
186
111
|
console.log('blocks.length: ', blocks.length);
|
|
187
|
-
// Process blocks in order (newest to oldest)
|
|
188
112
|
for (const block of blocks) {
|
|
189
113
|
if (!block || !block.transactions)
|
|
190
114
|
continue;
|
|
191
115
|
for (let i = 0; i < block.transactions.length && txHashes.length < maxTransactions; i++) {
|
|
192
116
|
const tx = block.transactions[i];
|
|
193
117
|
if (typeof tx === 'object') {
|
|
194
|
-
// Check if wallet is sender or receiver
|
|
195
118
|
const isSender = tx.from.toLowerCase() === addressLower;
|
|
196
119
|
const isReceiver = tx.to?.toLowerCase() === addressLower;
|
|
197
120
|
if ((isSender || isReceiver) && !seenHashes.has(tx.hash)) {
|
|
@@ -203,12 +126,10 @@ async function getRecentTransactionHashes(client, address, startBlock, endBlock,
|
|
|
203
126
|
console.log("Transaction is not an object: ", tx);
|
|
204
127
|
}
|
|
205
128
|
}
|
|
206
|
-
// Early exit if we found enough transactions
|
|
207
129
|
if (txHashes.length >= maxTransactions)
|
|
208
130
|
break;
|
|
209
131
|
}
|
|
210
132
|
blocksScanned += BigInt(blockNumbers.length);
|
|
211
|
-
// Log progress
|
|
212
133
|
if (blocksScanned % 50n === 0n || blocksScanned < 50n) {
|
|
213
134
|
console.log(`Scanned ${blocksScanned} blocks, found ${txHashes.length} transactions`);
|
|
214
135
|
}
|
|
@@ -221,19 +142,14 @@ async function getRecentTransactionHashes(client, address, startBlock, endBlock,
|
|
|
221
142
|
console.log(`Found ${txHashes.length} transactions after scanning ${blocksScanned} blocks`);
|
|
222
143
|
return txHashes;
|
|
223
144
|
}
|
|
224
|
-
/**
|
|
225
|
-
* Alternative function that uses Etherscan-like API
|
|
226
|
-
* This is the recommended approach for production use
|
|
227
|
-
*/
|
|
228
145
|
async function getEVMTransactionHistoryWithAPI(client, walletAddress, apiEndpoint, apiKey, options = {}) {
|
|
229
146
|
const { includeTokenTransfers = true, includeNFTTransfers = true } = options;
|
|
230
147
|
try {
|
|
231
|
-
// Fetch normal transactions
|
|
232
148
|
const normalTxResponse = await fetch(`${apiEndpoint}?module=account&action=txlist&address=${walletAddress}&startblock=0&endblock=99999999&sort=desc&apikey=${apiKey}`);
|
|
233
149
|
const normalTxData = await normalTxResponse.json();
|
|
234
150
|
const history = [];
|
|
235
151
|
if (normalTxData.status === '1' && normalTxData.result) {
|
|
236
|
-
for (const tx of normalTxData.result.slice(0, 50)) {
|
|
152
|
+
for (const tx of normalTxData.result.slice(0, 50)) {
|
|
237
153
|
const receipt = await client.getTransactionReceipt({ hash: tx.hash });
|
|
238
154
|
const parsed = await parseEVMTransaction(client, {
|
|
239
155
|
hash: tx.hash,
|
|
@@ -256,16 +172,11 @@ async function getEVMTransactionHistoryWithAPI(client, walletAddress, apiEndpoin
|
|
|
256
172
|
throw error;
|
|
257
173
|
}
|
|
258
174
|
}
|
|
259
|
-
/**
|
|
260
|
-
* Fetches transaction hashes for an address by iterating through blocks
|
|
261
|
-
* Efficient for recent transactions (last 10-15 txs)
|
|
262
|
-
*/
|
|
263
175
|
async function getTransactionHashesByAddress(client, address, startBlock, endBlock, direction, maxTransactions = 15) {
|
|
264
176
|
const txHashes = [];
|
|
265
177
|
const addressLower = address.toLowerCase();
|
|
266
178
|
let currentBlock = endBlock;
|
|
267
179
|
console.log(`Scanning blocks backwards from ${endBlock} to ${startBlock}...`);
|
|
268
|
-
// Iterate backwards from most recent block
|
|
269
180
|
while (currentBlock >= startBlock && txHashes.length < maxTransactions) {
|
|
270
181
|
try {
|
|
271
182
|
const block = await client.getBlock({
|
|
@@ -274,7 +185,6 @@ async function getTransactionHashesByAddress(client, address, startBlock, endBlo
|
|
|
274
185
|
});
|
|
275
186
|
if (block.transactions) {
|
|
276
187
|
for (const tx of block.transactions) {
|
|
277
|
-
// Check if transaction matches the direction filter
|
|
278
188
|
if (typeof tx === 'object') {
|
|
279
189
|
const matchesDirection = (direction === 'from' && tx.from.toLowerCase() === addressLower) ||
|
|
280
190
|
(direction === 'to' && tx.to?.toLowerCase() === addressLower) ||
|
|
@@ -282,7 +192,6 @@ async function getTransactionHashesByAddress(client, address, startBlock, endBlo
|
|
|
282
192
|
(direction === 'to' && tx.to?.toLowerCase() === addressLower);
|
|
283
193
|
if (matchesDirection) {
|
|
284
194
|
txHashes.push(tx.hash);
|
|
285
|
-
// Stop if we've found enough transactions
|
|
286
195
|
if (txHashes.length >= maxTransactions) {
|
|
287
196
|
break;
|
|
288
197
|
}
|
|
@@ -291,7 +200,6 @@ async function getTransactionHashesByAddress(client, address, startBlock, endBlo
|
|
|
291
200
|
}
|
|
292
201
|
}
|
|
293
202
|
currentBlock--;
|
|
294
|
-
// Log progress every 100 blocks
|
|
295
203
|
if ((endBlock - currentBlock) % 100n === 0n) {
|
|
296
204
|
console.log(`Scanned ${endBlock - currentBlock} blocks, found ${txHashes.length} transactions`);
|
|
297
205
|
}
|
|
@@ -305,9 +213,6 @@ async function getTransactionHashesByAddress(client, address, startBlock, endBlo
|
|
|
305
213
|
console.log(`Found ${txHashes.length} transactions after scanning ${endBlock - currentBlock} blocks`);
|
|
306
214
|
return txHashes;
|
|
307
215
|
}
|
|
308
|
-
/**
|
|
309
|
-
* Fetches full transaction details in batches
|
|
310
|
-
*/
|
|
311
216
|
async function fetchTransactionsInBatches(client, hashes, batchSize) {
|
|
312
217
|
const results = [];
|
|
313
218
|
for (let i = 0; i < hashes.length; i += batchSize) {
|
|
@@ -330,28 +235,21 @@ async function fetchTransactionsInBatches(client, hashes, batchSize) {
|
|
|
330
235
|
}
|
|
331
236
|
}));
|
|
332
237
|
results.push(...batchResults);
|
|
333
|
-
// Small delay to avoid rate limiting
|
|
334
238
|
if (i + batchSize < hashes.length) {
|
|
335
239
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
336
240
|
}
|
|
337
241
|
}
|
|
338
242
|
return results;
|
|
339
243
|
}
|
|
340
|
-
/**
|
|
341
|
-
* Parses a single EVM transaction
|
|
342
|
-
*/
|
|
343
244
|
async function parseEVMTransaction(client, tx, receipt, timestamp, walletAddress, includeTokenTransfers, includeNFTTransfers) {
|
|
344
245
|
const gasUsed = receipt.gasUsed;
|
|
345
246
|
const effectiveGasPrice = receipt.effectiveGasPrice || tx.gasPrice || 0n;
|
|
346
247
|
const fee = (0, viem_1.formatEther)(gasUsed * effectiveGasPrice);
|
|
347
|
-
const gasPrice = (0, viem_1.formatUnits)(effectiveGasPrice, 9);
|
|
348
|
-
// Determine transaction type
|
|
248
|
+
const gasPrice = (0, viem_1.formatUnits)(effectiveGasPrice, 9);
|
|
349
249
|
const type = determineTransactionType(tx, receipt);
|
|
350
|
-
// Extract method signature
|
|
351
250
|
const method = tx.input && tx.input.length >= 10
|
|
352
251
|
? tx.input.slice(0, 10)
|
|
353
252
|
: undefined;
|
|
354
|
-
// Parse token transfers from logs
|
|
355
253
|
let tokenTransfers = [];
|
|
356
254
|
let nftTransfers = [];
|
|
357
255
|
if (includeTokenTransfers || includeNFTTransfers) {
|
|
@@ -376,27 +274,20 @@ async function parseEVMTransaction(client, tx, receipt, timestamp, walletAddress
|
|
|
376
274
|
nftTransfers: nftTransfers.length > 0 ? nftTransfers : undefined,
|
|
377
275
|
};
|
|
378
276
|
}
|
|
379
|
-
/**
|
|
380
|
-
* Determines the transaction type
|
|
381
|
-
*/
|
|
382
277
|
function determineTransactionType(tx, receipt) {
|
|
383
|
-
// Contract creation
|
|
384
278
|
if (!tx.to)
|
|
385
279
|
return constant_1.TRANSACTION_TYPE.CONTRACT_CREATION;
|
|
386
|
-
// Check if it's a token/NFT transfer based on method signature
|
|
387
280
|
const methodSig = tx.input?.slice(0, 10);
|
|
388
281
|
if (methodSig === '0xa9059cbb')
|
|
389
|
-
return constant_1.TRANSACTION_TYPE.TOKEN_TRANSFER;
|
|
282
|
+
return constant_1.TRANSACTION_TYPE.TOKEN_TRANSFER;
|
|
390
283
|
if (methodSig === '0x23b872dd')
|
|
391
|
-
return constant_1.TRANSACTION_TYPE.TOKEN_TRANSFER;
|
|
284
|
+
return constant_1.TRANSACTION_TYPE.TOKEN_TRANSFER;
|
|
392
285
|
if (methodSig === '0x42842e0e')
|
|
393
|
-
return constant_1.TRANSACTION_TYPE.NFT_TRANSFER;
|
|
286
|
+
return constant_1.TRANSACTION_TYPE.NFT_TRANSFER;
|
|
394
287
|
if (methodSig === '0xf242432a')
|
|
395
|
-
return constant_1.TRANSACTION_TYPE.NFT_TRANSFER;
|
|
396
|
-
// Check value
|
|
288
|
+
return constant_1.TRANSACTION_TYPE.NFT_TRANSFER;
|
|
397
289
|
if (tx.value && tx.value > 0n)
|
|
398
290
|
return constant_1.TRANSACTION_TYPE.NATIVE_TRANSFER;
|
|
399
|
-
// Check logs for common patterns
|
|
400
291
|
if (receipt.logs.some(log => log.topics[0]?.includes('Swap')))
|
|
401
292
|
return constant_1.TRANSACTION_TYPE.SWAP;
|
|
402
293
|
if (receipt.logs.some(log => log.topics[0]?.includes('Deposit')))
|
|
@@ -405,15 +296,11 @@ function determineTransactionType(tx, receipt) {
|
|
|
405
296
|
return constant_1.TRANSACTION_TYPE.WITHDRAWAL;
|
|
406
297
|
return constant_1.TRANSACTION_TYPE.CONTRACT_INTERACTION;
|
|
407
298
|
}
|
|
408
|
-
/**
|
|
409
|
-
* Parses transfer events from transaction logs
|
|
410
|
-
*/
|
|
411
299
|
async function parseTransferLogs(client, logs, walletAddress, includeTokenTransfers, includeNFTTransfers) {
|
|
412
300
|
const tokens = [];
|
|
413
301
|
const nfts = [];
|
|
414
302
|
for (const log of logs) {
|
|
415
303
|
try {
|
|
416
|
-
// Try ERC20 Transfer
|
|
417
304
|
if (includeTokenTransfers && log.topics.length === 3) {
|
|
418
305
|
try {
|
|
419
306
|
const decoded = (0, viem_1.decodeEventLog)({
|
|
@@ -423,10 +310,8 @@ async function parseTransferLogs(client, logs, walletAddress, includeTokenTransf
|
|
|
423
310
|
});
|
|
424
311
|
if (decoded.eventName === 'Transfer') {
|
|
425
312
|
const { from, to, value } = decoded.args;
|
|
426
|
-
// Only include if wallet is involved
|
|
427
313
|
if (from.toLowerCase() === walletAddress.toLowerCase() ||
|
|
428
314
|
to.toLowerCase() === walletAddress.toLowerCase()) {
|
|
429
|
-
// Try to get token info (this might fail for non-standard tokens)
|
|
430
315
|
let decimals = 18;
|
|
431
316
|
try {
|
|
432
317
|
decimals = await client.readContract({
|
|
@@ -450,7 +335,6 @@ async function parseTransferLogs(client, logs, walletAddress, includeTokenTransf
|
|
|
450
335
|
}
|
|
451
336
|
catch { }
|
|
452
337
|
}
|
|
453
|
-
// Try ERC721 Transfer (has indexed tokenId)
|
|
454
338
|
if (includeNFTTransfers && log.topics.length === 4) {
|
|
455
339
|
try {
|
|
456
340
|
const decoded = (0, viem_1.decodeEventLog)({
|
|
@@ -474,7 +358,6 @@ async function parseTransferLogs(client, logs, walletAddress, includeTokenTransf
|
|
|
474
358
|
}
|
|
475
359
|
catch { }
|
|
476
360
|
}
|
|
477
|
-
// Try ERC1155 TransferSingle
|
|
478
361
|
if (includeNFTTransfers) {
|
|
479
362
|
try {
|
|
480
363
|
const decoded = (0, viem_1.decodeEventLog)({
|
|
@@ -501,10 +384,8 @@ async function parseTransferLogs(client, logs, walletAddress, includeTokenTransf
|
|
|
501
384
|
}
|
|
502
385
|
}
|
|
503
386
|
catch (error) {
|
|
504
|
-
// Skip logs that don't match our patterns
|
|
505
387
|
continue;
|
|
506
388
|
}
|
|
507
389
|
}
|
|
508
390
|
return { tokens, nfts };
|
|
509
391
|
}
|
|
510
|
-
//# sourceMappingURL=transactionParsing.js.map
|
package/dist/evm/utils.d.ts
CHANGED
|
@@ -180,9 +180,6 @@ export declare function viemReceiptToEthersReceipt(receipt: ViemTransactionRecei
|
|
|
180
180
|
export declare const getNativeBalance: (address: Hex, client: PublicClient) => Promise<Balance>;
|
|
181
181
|
export declare const getTokenInfo: (tokenAddress: Hex, client: PublicClient) => Promise<TokenInfo>;
|
|
182
182
|
export declare const getTokenBalance: (tokenAddress: Hex, walletAddress: Hex, client: PublicClient) => Promise<Balance>;
|
|
183
|
-
/**
|
|
184
|
-
* Sign, send, and confirm any EVM transaction
|
|
185
|
-
*/
|
|
186
183
|
export declare const signSendAndConfirm: (walletClient: WalletClient, publicClient: PublicClient, params: {
|
|
187
184
|
to: Hex;
|
|
188
185
|
data?: Hex;
|
|
@@ -192,25 +189,13 @@ export declare const signSendAndConfirm: (walletClient: WalletClient, publicClie
|
|
|
192
189
|
maxFeePerGas?: bigint;
|
|
193
190
|
maxPriorityFeePerGas?: bigint;
|
|
194
191
|
}, confirmations?: number) => Promise<TransactionResult>;
|
|
195
|
-
/**
|
|
196
|
-
* Send native token (ETH, BNB, MATIC, etc.)
|
|
197
|
-
*/
|
|
198
192
|
export declare const sendNativeToken: (walletClient: WalletClient, publicClient: PublicClient, to: Hex, amount: string | bigint, confirmations?: number) => Promise<TransactionResult>;
|
|
199
|
-
/**
|
|
200
|
-
* Send ERC-20 token
|
|
201
|
-
*/
|
|
202
193
|
export declare const sendERC20Token: (walletClient: WalletClient, publicClient: PublicClient, tokenAddress: Hex, to: Hex, amount: bigint, confirmations?: number) => Promise<TransactionResult>;
|
|
203
|
-
/**
|
|
204
|
-
* Get current gas prices (both legacy and EIP-1559)
|
|
205
|
-
*/
|
|
206
194
|
export declare const getGasPrices: (client: PublicClient) => Promise<{
|
|
207
195
|
gasPrice: undefined;
|
|
208
196
|
maxFeePerGas: bigint;
|
|
209
197
|
maxPriorityFeePerGas: bigint;
|
|
210
198
|
}>;
|
|
211
|
-
/**
|
|
212
|
-
* Estimate gas for a transaction
|
|
213
|
-
*/
|
|
214
199
|
export declare const estimateGas: (client: PublicClient, params: {
|
|
215
200
|
to: Hex;
|
|
216
201
|
data?: Hex;
|
|
@@ -221,34 +206,15 @@ export declare const checkAllowance: (client: PublicClient, tokenAddress: Hex, o
|
|
|
221
206
|
formatted: string;
|
|
222
207
|
decimals: number;
|
|
223
208
|
}>;
|
|
224
|
-
/**
|
|
225
|
-
* Check if allowance is sufficient for a transaction
|
|
226
|
-
*/
|
|
227
209
|
export declare const isAllowanceSufficient: (publicClient: PublicClient, tokenAddress: `0x${string}`, owner: `0x${string}`, spender: `0x${string}`, requiredAmount: string | bigint) => Promise<boolean>;
|
|
228
|
-
/**
|
|
229
|
-
* Approve ERC-20 token spending
|
|
230
|
-
*/
|
|
231
210
|
export declare const approveToken: (walletClient: WalletClient, publicClient: PublicClient, tokenAddress: Hex, spender: Hex, amount: bigint, confirmations?: number) => Promise<TransactionResult>;
|
|
232
|
-
/**
|
|
233
|
-
* Approve unlimited token spending (MaxUint256)
|
|
234
|
-
*/
|
|
235
211
|
export declare const approveTokenUnlimited: (walletClient: WalletClient, publicClient: PublicClient, tokenAddress: `0x${string}`, spender: `0x${string}`, gas?: bigint, confirmations?: number) => Promise<TransactionResult>;
|
|
236
|
-
/**
|
|
237
|
-
* Check allowance and approve if necessary
|
|
238
|
-
*/
|
|
239
212
|
export declare const checkAndApprove: (walletClient: WalletClient, publicClient: PublicClient, tokenAddress: `0x${string}`, spender: `0x${string}`, requiredAmount: bigint, approvalAmount?: bigint, gas?: bigint, confirmations?: number) => Promise<{
|
|
240
213
|
approvalNeeded: boolean;
|
|
241
214
|
currentAllowance: bigint;
|
|
242
215
|
approvalResult?: TransactionResult;
|
|
243
216
|
}>;
|
|
244
|
-
/**
|
|
245
|
-
* Reset token allowance to zero (security best practice before setting new allowance)
|
|
246
|
-
*/
|
|
247
217
|
export declare const resetAllowance: (walletClient: WalletClient, publicClient: PublicClient, tokenAddress: `0x${string}`, spender: `0x${string}`, gas?: bigint, confirmations?: number) => Promise<TransactionResult>;
|
|
248
|
-
/**
|
|
249
|
-
* Safe approve: Reset to zero first, then approve the desired amount
|
|
250
|
-
* (Some tokens like USDT require this)
|
|
251
|
-
*/
|
|
252
218
|
export declare const safeApprove: (walletClient: WalletClient, publicClient: PublicClient, tokenAddress: `0x${string}`, spender: `0x${string}`, amount: bigint, gas?: bigint, confirmations?: number) => Promise<{
|
|
253
219
|
resetResult: TransactionResult;
|
|
254
220
|
approveResult: TransactionResult;
|
|
@@ -256,21 +222,9 @@ export declare const safeApprove: (walletClient: WalletClient, publicClient: Pub
|
|
|
256
222
|
export declare const discoverTokens: (wallet: string, chain: ChainWalletConfig) => Promise<UserTokenBalance<string>[]>;
|
|
257
223
|
export declare function calcGasTotal(gasLimit?: string, gasPrice?: string): string;
|
|
258
224
|
export declare function toPrecisionWithoutTrailingZeros(n: number, precision: number): string;
|
|
259
|
-
/**
|
|
260
|
-
* @param {number|string|BigNumber} value
|
|
261
|
-
* @param {number=} decimals
|
|
262
|
-
* @returns {BigNumber}
|
|
263
|
-
*/
|
|
264
225
|
export declare function calcTokenAmount(value: number | string | BigNumber, decimals?: number): BigNumber;
|
|
265
226
|
export declare const transformEVMNFTToUnified: (nft: EVMNFT) => NFT;
|
|
266
227
|
export declare const discoverNFTs: (wallet: string, chain: ChainWalletConfig) => Promise<NFT[]>;
|
|
267
228
|
export declare const discoverAllNFTs: (wallet: string, chain: ChainWalletConfig) => Promise<NFT[]>;
|
|
268
|
-
/**
|
|
269
|
-
* Get NFT collection details for a specific collection
|
|
270
|
-
* @param wallet - User's wallet address
|
|
271
|
-
* @param collectionAddress - The NFT collection contract address
|
|
272
|
-
* @param chain - Chain configuration
|
|
273
|
-
* @returns NFTCollection object with collection details and user's NFTs in that collection
|
|
274
|
-
*/
|
|
275
229
|
export declare const getNFTCollection: (wallet: string, collectionAddress: string, chain: ChainWalletConfig) => Promise<NFTCollection | null>;
|
|
276
230
|
export {};
|