@deserialize/multi-vm-wallet 1.5.11 โ†’ 1.5.21

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.
@@ -0,0 +1,428 @@
1
+ # Multi-Chain Savings Manager - Usage Guide
2
+
3
+ **Status**: โœ… **Implementation Complete**
4
+ **Date**: 2026-02-02
5
+
6
+ ---
7
+
8
+ ## ๐ŸŽ‰ What's Been Implemented
9
+
10
+ Following the same pattern as EVM/SVM VM classes, we've implemented a complete multi-chain savings manager system:
11
+
12
+ ### Files Created
13
+
14
+ ```
15
+ utils/savings/
16
+ โ”œโ”€โ”€ savings-manager.ts # Abstract base class
17
+ โ”œโ”€โ”€ evm-savings.ts # EVM implementation (Ethereum, Polygon, BSC, etc.)
18
+ โ”œโ”€โ”€ svm-savings.ts # Solana implementation
19
+ โ”œโ”€โ”€ multi-chain-savings.ts # Multi-chain orchestrator
20
+ โ””โ”€โ”€ index.ts # Updated exports
21
+ ```
22
+
23
+ ### Architecture
24
+
25
+ ```typescript
26
+ // Abstract base (like VM class)
27
+ abstract class SavingsManager<AddressType, ClientType, WalletClientType>
28
+
29
+ โ†“
30
+
31
+ // EVM implementation
32
+ EVMSavingsManager extends SavingsManager<Hex, PublicClient, WalletClient>
33
+
34
+ // Solana implementation
35
+ SVMSavingsManager extends SavingsManager<PublicKey, Connection, Keypair>
36
+
37
+ โ†“
38
+
39
+ // Multi-chain orchestrator
40
+ MultiChainSavingsManager (manages both EVM and SVM)
41
+ ```
42
+
43
+ ---
44
+
45
+ ## ๐Ÿ“– Usage Examples
46
+
47
+ ### Example 1: Single EVM Chain (Ethereum)
48
+
49
+ ```typescript
50
+ import { EVMSavingsManager } from './utils/savings';
51
+
52
+ const manager = new EVMSavingsManager(
53
+ mnemonic,
54
+ {
55
+ chainId: 1,
56
+ name: 'ethereum',
57
+ rpcUrl: 'https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY'
58
+ },
59
+ 0 // wallet index
60
+ );
61
+
62
+ // Get pocket 0
63
+ const pocket = manager.getPocket(0);
64
+ console.log('Pocket address:', pocket.address);
65
+ console.log('Derivation path:', pocket.derivationPath);
66
+
67
+ // Get balances for pocket 0
68
+ const balances = await manager.getPocketBalance(0, [
69
+ '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' // USDC
70
+ ]);
71
+
72
+ console.log('Native ETH:', balances[0].balance.formatted);
73
+ console.log('USDC:', balances[1].balance.formatted);
74
+
75
+ // Transfer 0.1 ETH to pocket 0
76
+ await manager.transferToPocket(walletClient, 0, '0.1');
77
+
78
+ // Transfer from pocket back to main wallet
79
+ await manager.sendToMainWallet(0, 100000000n, 'native');
80
+
81
+ // Cleanup
82
+ manager.dispose();
83
+ ```
84
+
85
+ ---
86
+
87
+ ### Example 2: Solana (SVM)
88
+
89
+ ```typescript
90
+ import { SVMSavingsManager } from './utils/savings';
91
+ import { Keypair } from '@solana/web3.js';
92
+
93
+ const manager = new SVMSavingsManager(
94
+ mnemonic,
95
+ 'https://api.mainnet-beta.solana.com',
96
+ 0 // wallet index
97
+ );
98
+
99
+ // Get pocket 0
100
+ const pocket = manager.getPocket(0);
101
+ console.log('Pocket address:', pocket.address.toBase58());
102
+ console.log('Derivation path:', pocket.derivationPath);
103
+
104
+ // Get balances for pocket 0
105
+ const balances = await manager.getPocketBalance(0, [
106
+ 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' // USDC on Solana
107
+ ]);
108
+
109
+ console.log('Native SOL:', balances[0].balance.formatted);
110
+ console.log('USDC:', balances[1].balance.formatted);
111
+
112
+ // Transfer 1 SOL to pocket 0
113
+ const mainWalletKeypair = manager.getMainWallet().privateKey;
114
+ await manager.transferToPocket(mainWalletKeypair, 0, 1000000000n); // 1 SOL
115
+
116
+ // Transfer SPL token
117
+ await manager.transferTokenToPocket(
118
+ mainWalletKeypair,
119
+ { address: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', decimals: 6 },
120
+ 0,
121
+ 1000000n // 1 USDC
122
+ );
123
+
124
+ // Cleanup
125
+ manager.dispose();
126
+ ```
127
+
128
+ ---
129
+
130
+ ### Example 3: Multi-Chain (The Full Power!)
131
+
132
+ ```typescript
133
+ import { MultiChainSavingsManager } from './utils/savings';
134
+
135
+ // Create manager with multiple chains
136
+ const manager = new MultiChainSavingsManager(
137
+ mnemonic,
138
+ [
139
+ // EVM chains
140
+ {
141
+ id: 'ethereum',
142
+ type: 'EVM',
143
+ config: {
144
+ chainId: 1,
145
+ name: 'ethereum',
146
+ rpcUrl: 'https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY'
147
+ }
148
+ },
149
+ {
150
+ id: 'polygon',
151
+ type: 'EVM',
152
+ config: {
153
+ chainId: 137,
154
+ name: 'polygon',
155
+ rpcUrl: 'https://polygon-mainnet.g.alchemy.com/v2/YOUR_KEY'
156
+ }
157
+ },
158
+ {
159
+ id: 'bsc',
160
+ type: 'EVM',
161
+ config: {
162
+ chainId: 56,
163
+ name: 'bsc',
164
+ rpcUrl: 'https://bsc-dataseed1.binance.org'
165
+ }
166
+ },
167
+ // Solana
168
+ {
169
+ id: 'solana',
170
+ type: 'SVM',
171
+ config: {
172
+ rpcUrl: 'https://api.mainnet-beta.solana.com'
173
+ }
174
+ }
175
+ ],
176
+ 0 // wallet index
177
+ );
178
+
179
+ // Get pocket addresses (notice EVM chains share addresses!)
180
+ const ethAddress = manager.getPocketAddress('ethereum', 0);
181
+ const polyAddress = manager.getPocketAddress('polygon', 0);
182
+ const bscAddress = manager.getPocketAddress('bsc', 0);
183
+ const solAddress = manager.getPocketAddress('solana', 0);
184
+
185
+ console.log('Ethereum pocket 0:', ethAddress);
186
+ console.log('Polygon pocket 0:', polyAddress);
187
+ console.log('BSC pocket 0:', bscAddress);
188
+ console.log('Solana pocket 0:', solAddress);
189
+
190
+ console.log('ETH === Polygon?', ethAddress === polyAddress); // true!
191
+ console.log('ETH === BSC?', ethAddress === bscAddress); // true!
192
+ console.log('ETH === Solana?', ethAddress === solAddress); // false (different chain)
193
+
194
+ // Get balances across all chains for pocket 0
195
+ const balances = await manager.getPocketBalanceAcrossChains(
196
+ 0, // pocket index
197
+ new Map([
198
+ ['ethereum', ['0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48']], // USDC on Ethereum
199
+ ['polygon', ['0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174']], // USDC on Polygon
200
+ ['bsc', ['0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d']], // USDC on BSC
201
+ ['solana', ['EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v']] // USDC on Solana
202
+ ])
203
+ );
204
+
205
+ // Display balances by chain
206
+ balances.forEach(chainBalance => {
207
+ console.log(`\n${chainBalance.chainId.toUpperCase()}:`);
208
+ console.log(` Address: ${chainBalance.address}`);
209
+ chainBalance.balances.forEach(bal => {
210
+ const tokenName = bal.token === 'native' ? 'Native' : 'USDC';
211
+ console.log(` ${tokenName}: ${bal.balance.formatted}`);
212
+ });
213
+ });
214
+
215
+ // Get all pockets (0, 1, 2) balances across all chains
216
+ const allBalances = await manager.getAllPocketsBalanceAcrossChains(
217
+ [0, 1, 2], // pocket indices
218
+ new Map([
219
+ ['ethereum', ['0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48']],
220
+ ['polygon', ['0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174']],
221
+ ['solana', ['EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v']]
222
+ ])
223
+ );
224
+
225
+ // Display total across all pockets and chains
226
+ for (const [pocketIndex, chainBalances] of allBalances) {
227
+ console.log(`\nPocket ${pocketIndex}:`);
228
+ chainBalances.forEach(cb => {
229
+ console.log(` ${cb.chainId}: ${cb.balances.length} tokens`);
230
+ });
231
+ }
232
+
233
+ // Advanced: Get specific chain manager for direct operations
234
+ const ethManager = manager.getEVMManager('ethereum');
235
+ await ethManager.transferToPocket(ethWalletClient, 0, '0.1');
236
+
237
+ const solManager = manager.getSVMManager('solana');
238
+ await solManager.transferToPocket(solKeypair, 0, 1000000000n);
239
+
240
+ // Cleanup all chains
241
+ manager.dispose();
242
+ ```
243
+
244
+ ---
245
+
246
+ ## ๐Ÿ”‘ Key Features
247
+
248
+ ### 1. EVM Address Sharing โœ…
249
+ All EVM-compatible chains (Ethereum, Polygon, BSC, Arbitrum, Optimism, etc.) share the same addresses because they all use BIP-44 coin type 60.
250
+
251
+ ```typescript
252
+ // Same pocket, same address across all EVM chains
253
+ const ethPocket = manager.getPocketAddress('ethereum', 0);
254
+ const polyPocket = manager.getPocketAddress('polygon', 0);
255
+ // ethPocket === polyPocket โœ…
256
+ ```
257
+
258
+ ### 2. Solana Has Different Addresses โœ…
259
+ Solana uses BIP-44 coin type 501, so it generates different addresses.
260
+
261
+ ```typescript
262
+ const ethPocket = manager.getPocketAddress('ethereum', 0); // 0x...
263
+ const solPocket = manager.getPocketAddress('solana', 0); // Different!
264
+ ```
265
+
266
+ ### 3. Memory Management โœ…
267
+ Following the VM pattern, all managers support proper cleanup:
268
+
269
+ ```typescript
270
+ // Clear specific pocket
271
+ manager.clearPocket(0);
272
+
273
+ // Clear all pockets
274
+ manager.clearAllPockets();
275
+
276
+ // Clear all RPC clients
277
+ manager.clearAllClients();
278
+
279
+ // Dispose everything (clear mnemonic + all data)
280
+ manager.dispose();
281
+ ```
282
+
283
+ ### 4. Lazy RPC Client Creation โœ…
284
+ RPC clients are created on-demand and can be garbage collected:
285
+
286
+ ```typescript
287
+ // Client created when first accessed
288
+ const balance = await manager.getPocketBalance(...);
289
+
290
+ // Clear client to free memory
291
+ manager.clearClient(); // Single chain
292
+ manager.clearAllClients(); // Multi-chain
293
+ ```
294
+
295
+ ---
296
+
297
+ ## ๐Ÿ—๏ธ Architecture Highlights
298
+
299
+ ### Follows VM Pattern Exactly
300
+
301
+ ```typescript
302
+ // VM Pattern
303
+ abstract class VM<AddressType, PrivateKeyType, ConnectionType> { }
304
+ class EVMVM extends VM<string, string, PublicClient> { }
305
+ class SVMVM extends VM<PublicKey, Keypair, Connection> { }
306
+
307
+ // Savings Pattern (Same Structure!)
308
+ abstract class SavingsManager<AddressType, ClientType, WalletClientType> { }
309
+ class EVMSavingsManager extends SavingsManager<Hex, PublicClient, WalletClient> { }
310
+ class SVMSavingsManager extends SavingsManager<PublicKey, Connection, Keypair> { }
311
+ ```
312
+
313
+ ### Type Safety
314
+
315
+ All managers are fully typed with generics:
316
+ - **AddressType**: `Hex` for EVM, `PublicKey` for Solana
317
+ - **ClientType**: `PublicClient` for EVM, `Connection` for Solana
318
+ - **WalletClientType**: `WalletClient` for EVM, `Keypair` for Solana
319
+
320
+ ---
321
+
322
+ ## ๐Ÿ“Š Comparison: Single-Chain vs Multi-Chain
323
+
324
+ ### Before (Old Pattern)
325
+ ```typescript
326
+ // Old: Single chain only
327
+ const manager = new BaseSavingsManager(mnemonic, 0, ethConfig);
328
+ const pocket = manager.getPocket(0);
329
+ const balances = await manager.getPocketTokenBalance([usdc], 0);
330
+ ```
331
+
332
+ ### After (New Pattern)
333
+ ```typescript
334
+ // New: Single chain (still works the same)
335
+ const manager = new EVMSavingsManager(mnemonic, ethConfig, 0);
336
+ const pocket = manager.getPocket(0);
337
+ const balances = await manager.getPocketBalance(0, [usdc]);
338
+
339
+ // OR Multi-chain (new capability!)
340
+ const multiManager = new MultiChainSavingsManager(mnemonic, [
341
+ { id: 'ethereum', type: 'EVM', config: ethConfig },
342
+ { id: 'polygon', type: 'EVM', config: polyConfig },
343
+ { id: 'solana', type: 'SVM', config: { rpcUrl: '...' } }
344
+ ], 0);
345
+
346
+ // Query all chains at once
347
+ const allBalances = await multiManager.getPocketBalanceAcrossChains(0, tokensByChain);
348
+ ```
349
+
350
+ ---
351
+
352
+ ## ๐ŸŽฏ Migration Guide
353
+
354
+ ### Old Code (Legacy Manager)
355
+ ```typescript
356
+ import { SavingsManager } from './utils/savings';
357
+
358
+ const manager = new SavingsManager(mnemonic, ethConfig, 0);
359
+ ```
360
+
361
+ **Status**: โœ… Still works! Legacy exports maintained for backward compatibility.
362
+
363
+ ### New Code (Multi-Chain)
364
+ ```typescript
365
+ import { EVMSavingsManager, SVMSavingsManager, MultiChainSavingsManager } from './utils/savings';
366
+
367
+ // Single EVM chain
368
+ const evmManager = new EVMSavingsManager(mnemonic, ethConfig, 0);
369
+
370
+ // Single Solana chain
371
+ const svmManager = new SVMSavingsManager(mnemonic, rpcUrl, 0);
372
+
373
+ // Multi-chain
374
+ const multiManager = new MultiChainSavingsManager(mnemonic, chains, 0);
375
+ ```
376
+
377
+ ---
378
+
379
+ ## ๐Ÿงช Testing Checklist
380
+
381
+ - [x] Abstract base class created
382
+ - [x] EVM implementation complete
383
+ - [x] Solana implementation complete
384
+ - [x] Multi-chain orchestrator complete
385
+ - [x] Exports updated
386
+ - [x] Build successful (no TypeScript errors in savings module)
387
+ - [ ] Unit tests (TODO)
388
+ - [ ] Integration tests (TODO)
389
+ - [ ] End-to-end tests (TODO)
390
+
391
+ ---
392
+
393
+ ## ๐Ÿ“ Next Steps (Optional)
394
+
395
+ 1. **Add Unit Tests**
396
+ - Test pocket derivation
397
+ - Test balance queries
398
+ - Test transfers
399
+
400
+ 2. **Add Integration Tests**
401
+ - Test with real RPC endpoints (testnet)
402
+ - Test cross-chain operations
403
+
404
+ 3. **Performance Optimizations**
405
+ - Implement balance caching
406
+ - Batch RPC requests
407
+ - Add rate limiting helpers
408
+
409
+ 4. **Additional Features**
410
+ - Pocket discovery (scan for pockets with balances)
411
+ - Transaction history per pocket
412
+ - USD value aggregation (with price feeds)
413
+
414
+ ---
415
+
416
+ ## ๐ŸŽ‰ Summary
417
+
418
+ โœ… **Complete multi-chain savings manager implemented**
419
+ - Follows EVM/SVM VM pattern exactly
420
+ - Supports all EVM chains + Solana
421
+ - EVM chains share addresses (coin type 60)
422
+ - Solana has different addresses (coin type 501)
423
+ - Full type safety with generics
424
+ - Memory management and disposal patterns
425
+ - Lazy RPC client creation
426
+ - Backward compatible with legacy code
427
+
428
+ **Ready to use!** ๐Ÿš€