pwc-sdk-wallet 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +2062 -0
  2. package/dist/Vault.d.ts +493 -0
  3. package/dist/Vault.js +1090 -0
  4. package/dist/chain/ChainService.d.ts +84 -0
  5. package/dist/chain/ChainService.js +136 -0
  6. package/dist/chain/SolanaChainService.d.ts +94 -0
  7. package/dist/chain/SolanaChainService.js +167 -0
  8. package/dist/config/chains.d.ts +233 -0
  9. package/dist/config/chains.js +285 -0
  10. package/dist/config/constants.d.ts +102 -0
  11. package/dist/config/constants.js +109 -0
  12. package/dist/config/environment.d.ts +46 -0
  13. package/dist/config/environment.js +114 -0
  14. package/dist/config/gas.d.ts +107 -0
  15. package/dist/config/gas.js +123 -0
  16. package/dist/crypto/EncryptionService.d.ts +74 -0
  17. package/dist/crypto/EncryptionService.js +178 -0
  18. package/dist/index.d.ts +22 -0
  19. package/dist/index.js +96 -0
  20. package/dist/keyrings/HDKeyring.d.ts +72 -0
  21. package/dist/keyrings/HDKeyring.js +156 -0
  22. package/dist/keyrings/SimpleKeyring.d.ts +31 -0
  23. package/dist/keyrings/SimpleKeyring.js +49 -0
  24. package/dist/keyrings/SolanaKeyring.d.ts +71 -0
  25. package/dist/keyrings/SolanaKeyring.js +159 -0
  26. package/dist/services/BatchProcessor.d.ts +42 -0
  27. package/dist/services/BatchProcessor.js +188 -0
  28. package/dist/services/MultiTransferService.d.ts +78 -0
  29. package/dist/services/MultiTransferService.js +252 -0
  30. package/dist/services/QRCodeService.d.ts +193 -0
  31. package/dist/services/QRCodeService.js +299 -0
  32. package/dist/services/TokenUtils.d.ts +307 -0
  33. package/dist/services/TokenUtils.js +429 -0
  34. package/dist/services/nft/MetadataResolver.d.ts +57 -0
  35. package/dist/services/nft/MetadataResolver.js +162 -0
  36. package/dist/services/nft/NFTAPIService.d.ts +53 -0
  37. package/dist/services/nft/NFTAPIService.js +122 -0
  38. package/dist/services/nft/NFTService.d.ts +241 -0
  39. package/dist/services/nft/NFTService.js +910 -0
  40. package/dist/types/multiTransfer.d.ts +68 -0
  41. package/dist/types/multiTransfer.js +2 -0
  42. package/dist/types/nft/index.d.ts +68 -0
  43. package/dist/types/nft/index.js +2 -0
  44. package/dist/types/nft.d.ts +265 -0
  45. package/dist/types/nft.js +6 -0
  46. package/package.json +70 -0
package/README.md ADDED
@@ -0,0 +1,2062 @@
1
+ # PWC Wallet SDK
2
+
3
+ A comprehensive, secure, and user-friendly wallet SDK for React Native applications. This SDK provides a complete solution for managing cryptocurrency wallets with support for multiple blockchains, HD wallet generation, vanity addresses, NFT support, and advanced features like multi-transfer operations.
4
+
5
+ ## 📋 Table of Contents
6
+
7
+ ### 🚀 Quick Start
8
+ - [Installation](#installation)
9
+ - [Basic Wallet Creation](#1-basic-wallet-creation)
10
+ - [Import Existing Wallet from Seed Phrase](#11-import-existing-wallet-from-seed-phrase)
11
+ - [Vanity Wallet Generation](#2-vanity-wallet-generation)
12
+ - [Custom Chain Configuration](#3-custom-chain-configuration)
13
+
14
+ ### 📱 React Native Usage
15
+ - [Simple Wallet Component](#simple-wallet-component)
16
+ - [Custom Hook for Wallet Management](#custom-hook-for-wallet-management)
17
+
18
+ ### ⚙️ Configuration
19
+ - [Hybrid Configuration (Mobile App & SDK)](#hybrid-configuration-mobile-app--sdk)
20
+ - [Built-in Chains](#built-in-chains)
21
+ - [Custom Chain Management](#custom-chain-management)
22
+ - [Override Built-in Chains](#override-built-in-chains)
23
+ - [Add Custom Chains](#add-custom-chains)
24
+ - [Setup All Chains at Once](#setup-all-chains-at-once)
25
+ - [Chain Configuration Priority](#chain-configuration-priority)
26
+ - [Utility Functions](#utility-functions)
27
+ - [Vanity Wallet Settings](#vanity-wallet-settings)
28
+ - [Supported Chains](#supported-chains)
29
+
30
+ ### 💰 Core Wallet Functions
31
+ - [Account Management](#account-management)
32
+ - [Add New HD Account](#add-new-hd-account)
33
+ - [Add New Solana Account](#add-new-solana-account)
34
+ - [Import Account](#import-account)
35
+ - [Get Accounts](#get-accounts)
36
+ - [Balance & Token Functions](#balance--token-functions)
37
+ - [Get Native Balance](#get-native-balance)
38
+ - [Get Token Balance](#get-token-balance)
39
+ - [Get Token Info](#get-token-info)
40
+ - [Transaction Functions](#transaction-functions)
41
+ - [Send Native Token](#send-native-token)
42
+ - [Send Token](#send-token)
43
+ - [Export Mnemonic](#export-mnemonic)
44
+
45
+ ### 🔄 Multi-Transfer Operations
46
+ - [Batch Send Native Tokens](#batch-send-native-tokens)
47
+ - [Batch Send ERC-20 Tokens](#batch-send-erc-20-tokens)
48
+
49
+ ### 📱 QR Code Functionality
50
+ - [Generate Address QR](#generate-address-qr)
51
+ - [Generate Mnemonic QR](#generate-mnemonic-qr)
52
+ - [Generate Transaction QR](#generate-transaction-qr)
53
+ - [Import Wallet from QR](#import-wallet-from-qr)
54
+ - [Process Transaction from QR](#process-transaction-from-qr)
55
+ - [Validate QR Code](#validate-qr-code)
56
+ - [Generate EIP-681 Compatible Address QR (for Metamask, Binance, Trust Wallet)](#generate-eip-681-compatible-address-qr-for-metamask-binance-trust-wallet)
57
+
58
+ ### 🖼️ NFT Functionality
59
+ - [Get NFT Details](#get-nft-details)
60
+ - [Get NFT Balance](#get-nft-balance)
61
+ - [Get Collection Information](#get-collection-information)
62
+ - [NFT Metadata & Attributes](#nft-metadata--attributes)
63
+ - [NFT Transaction History](#nft-transaction-history)
64
+ - [NFT Types and Interfaces](#nft-types-and-interfaces)
65
+ - [React Native NFT Component Example](#react-native-nft-component-example)
66
+ - [Get Owned NFTs](#get-owned-nfts)
67
+ - [Transfer NFT](#transfer-nft)
68
+ - [Estimate NFT Transfer Gas](#estimate-nft-transfer-gas)
69
+
70
+ ### ⛽ Advanced Features
71
+ - [Gas Estimation](#gas-estimation)
72
+ - [Estimate Native Transfer Gas](#estimate-native-transfer-gas)
73
+ - [Estimate Token Transfer Gas](#estimate-token-transfer-gas)
74
+ - [Estimate Multi-Transfer Gas](#estimate-multi-transfer-gas)
75
+ - [Estimate NFT Transfer Gas](#estimate-nft-transfer-gas)
76
+
77
+ ### 🛠️ Advanced Transaction Utilities
78
+ - [Build Generic Transaction](#build-generic-transaction)
79
+ - [Sign Transaction](#sign-transaction)
80
+ - [Send Raw Transaction](#send-raw-transaction)
81
+ - [Approve Token (Public Utility)](#approve-token-public-utility)
82
+ - [Track Transaction Status](#track-transaction-status)
83
+
84
+ ### 🔐 Message Signing
85
+ - [Sign Message (Vault)](#sign-message-recommended---using-vault)
86
+ - [Sign Message (Private Key)](#sign-message-deprecated---using-private-key)
87
+ - [Verify Message](#verify-message)
88
+ - [Sign Typed Data (Vault)](#sign-typed-data-recommended---using-vault)
89
+ - [Sign Typed Data (Private Key)](#sign-typed-data-deprecated---using-private-key)
90
+ - [Verify Typed Data](#verify-typed-data)
91
+
92
+ ### 🔢 Nonce Management
93
+ - [Get Nonce](#get-nonce)
94
+ - [Sign Message with Nonce (Vault)](#sign-message-with-nonce-recommended---using-vault)
95
+ - [Sign Message with Nonce (Private Key)](#sign-message-with-nonce-deprecated---using-private-key)
96
+ - [Verify Message with Nonce](#verify-message-with-nonce)
97
+
98
+ ### 🔍 Read-Only Utilities (Token & NFT)
99
+ - [Get Token Balance](#get-token-balance)
100
+ - [Get Token Info](#get-token-info)
101
+ - [Get Native Balance](#get-native-balance)
102
+ - [Check Allowance](#check-allowance)
103
+ - [Get NFT Details](#get-nft-details)
104
+ - [Get NFT Balance](#get-nft-balance)
105
+ - [Get Owned NFTs](#get-owned-nfts)
106
+
107
+ ### 🔒 Security & Error Handling
108
+ - [Security Considerations](#security-considerations)
109
+ - [Error Handling](#error-handling)
110
+
111
+ ### 🛠️ Development
112
+ - [Contributing](#contributing)
113
+
114
+ ### 🛠️ Advanced Transaction Utilities
115
+
116
+ ### Build Generic Transaction
117
+ Builds an unsigned transaction for any contract method.
118
+
119
+ **Parameters:**
120
+ - `contractAddress` - The contract address to interact with
121
+ - `abi` - The contract ABI array
122
+ - `method` - The method name to call
123
+ - `args` - Arguments to pass to the method (optional)
124
+ - `value` - Native token value to send (optional)
125
+ - `chainId` - The chain ID (e.g., '1' for Ethereum, '56' for BSC)
126
+
127
+ ```typescript
128
+ import { buildTransaction } from 'pwc-wallet-sdk/services/TokenUtils';
129
+
130
+ const unsignedTx = await buildTransaction({
131
+ contractAddress: '0xA0b86a33E6441b8c4C8C8C8C8C8C8C8C8C8C8C8', // USDT contract
132
+ abi: [
133
+ "function transfer(address to, uint256 amount) returns (bool)",
134
+ "function balanceOf(address account) view returns (uint256)"
135
+ ],
136
+ method: 'transfer',
137
+ args: ['0xRecipientAddress...', '1000000000'], // to address, amount (in smallest unit)
138
+ chainId: '1' // Ethereum mainnet
139
+ });
140
+ ```
141
+
142
+ ### Sign Transaction (RECOMMENDED - Using Vault)
143
+ Signs an unsigned transaction using Vault for better security.
144
+
145
+ **Parameters:**
146
+ - `unsignedTx` - The unsigned transaction object from buildTransaction
147
+ - `vault` - The vault instance containing the account
148
+ - `fromAddress` - The sender's address
149
+ - `chainId` - The chain ID
150
+
151
+ ```typescript
152
+ import { signTransactionWithVault } from 'pwc-wallet-sdk/services/TokenUtils';
153
+
154
+ const signedTx = await signTransactionWithVault(unsignedTx, vault, '0xYourAddress', '1');
155
+ ```
156
+
157
+ ### Sign Transaction (DEPRECATED - Using Private Key)
158
+ ⚠️ **DEPRECATED**: Use signTransactionWithVault instead for better security.
159
+
160
+ **Parameters:**
161
+ - `unsignedTx` - The unsigned transaction object from buildTransaction
162
+ - `privateKey` - The private key to sign with (without 0x prefix)
163
+ - `chainId` - The chain ID
164
+
165
+ ```typescript
166
+ import { signTransaction } from 'pwc-wallet-sdk/services/TokenUtils';
167
+
168
+ const privateKey = 'your-private-key-without-0x-prefix';
169
+ const signedTx = await signTransaction(unsignedTx, privateKey, '1');
170
+ ```
171
+
172
+ ### Send Raw Transaction
173
+ Broadcasts a signed transaction to the network.
174
+
175
+ **Parameters:**
176
+ - `signedTx` - The signed transaction as hex string
177
+ - `chainId` - The chain ID
178
+
179
+ ```typescript
180
+ import { sendTransaction } from 'pwc-wallet-sdk/services/TokenUtils';
181
+
182
+ const txResponse = await sendTransaction(signedTx, '1');
183
+ console.log('Transaction hash:', txResponse.hash);
184
+ console.log('Block number:', txResponse.blockNumber);
185
+ ```
186
+
187
+ ### Approve Token (RECOMMENDED - Using Vault)
188
+ Approves a spender to spend tokens using Vault for better security.
189
+
190
+ **Parameters:**
191
+ - `vault` - The vault instance containing the owner's account
192
+ - `fromAddress` - The owner's address
193
+ - `tokenAddress` - The ERC-20 token contract address
194
+ - `spender` - The spender's address (e.g., DEX contract address)
195
+ - `amount` - The amount to approve (string or bigint)
196
+ - `chainId` - The chain ID
197
+
198
+ ```typescript
199
+ import { approveTokenWithVault } from 'pwc-wallet-sdk/services/TokenUtils';
200
+
201
+ const receipt = await approveTokenWithVault(
202
+ vault,
203
+ '0xOwner...',
204
+ '0xToken...',
205
+ '0xSpender...',
206
+ '1000',
207
+ '1'
208
+ );
209
+ ```
210
+
211
+ ### Approve Token (DEPRECATED - Using Private Key)
212
+ ⚠️ **DEPRECATED**: Use approveTokenWithVault instead for better security.
213
+
214
+ **Parameters:**
215
+ - `privateKey` - The owner's private key (without 0x prefix)
216
+ - `tokenAddress` - The ERC-20 token contract address
217
+ - `spender` - The spender's address (e.g., DEX contract address)
218
+ - `amount` - The amount to approve (string or bigint)
219
+ - `chainId` - The chain ID
220
+
221
+ ```typescript
222
+ import { approveToken } from 'pwc-wallet-sdk/services/TokenUtils';
223
+
224
+ const receipt = await approveToken('privateKey...', '0xToken...', '0xSpender...', '1000', '1');
225
+ ```
226
+
227
+ ### Track Transaction Status
228
+ Tracks the status of a transaction with polling and callback notifications.
229
+
230
+ **Parameters:**
231
+ - `txHash` - The transaction hash to track
232
+ - `chainId` - The chain ID
233
+ - `callback` - Function called with status updates ('pending', 'confirmed', 'failed')
234
+ - `pollInterval` - Polling interval in milliseconds (optional, default: 3000)
235
+
236
+ ```typescript
237
+ import { trackTxStatus } from 'pwc-wallet-sdk/services/TokenUtils';
238
+
239
+ trackTxStatus('0xTransactionHash...', '1', (status, receipt) => {
240
+ switch (status) {
241
+ case 'pending':
242
+ console.log('Transaction is pending...');
243
+ break;
244
+ case 'confirmed':
245
+ console.log('Transaction confirmed!', receipt?.transactionHash);
246
+ break;
247
+ case 'failed':
248
+ console.log('Transaction failed!', receipt?.transactionHash);
249
+ break;
250
+ }
251
+ }, 5000); // Poll every 5 seconds
252
+ ```
253
+
254
+ ### 🔐 Message Signing
255
+
256
+ ### Sign Message (RECOMMENDED - Using Vault)
257
+ Signs a message using Vault for better security. This is equivalent to MetaMask's `personal_sign` method.
258
+
259
+ **Parameters:**
260
+ - `message` - The message to sign (string or hex string)
261
+ - `vault` - The vault instance containing the account
262
+ - `fromAddress` - The signer's address
263
+
264
+ ```typescript
265
+ import { signMessageWithVault } from 'pwc-wallet-sdk/services/TokenUtils';
266
+
267
+ const signature = await signMessageWithVault('Hello World', vault, '0xYourAddress');
268
+ console.log('Signature:', signature);
269
+ ```
270
+
271
+ ### Sign Message (DEPRECATED - Using Private Key)
272
+ ⚠️ **DEPRECATED**: Use `signMessageWithVault` instead for better security.
273
+
274
+ **Parameters:**
275
+ - `message` - The message to sign (string or hex string)
276
+ - `privateKey` - The private key to sign with (without 0x prefix)
277
+
278
+ ```typescript
279
+ import { signMessage } from 'pwc-wallet-sdk/services/TokenUtils';
280
+
281
+ const signature = await signMessage('Hello World', 'your-private-key');
282
+ console.log('Signature:', signature);
283
+ ```
284
+
285
+ ### Verify Message
286
+ Verifies a message signature and returns the signer's address.
287
+
288
+ **Parameters:**
289
+ - `message` - The original message that was signed
290
+ - `signature` - The signature to verify
291
+
292
+ ```typescript
293
+ import { verifyMessage } from 'pwc-wallet-sdk/services/TokenUtils';
294
+
295
+ const signerAddress = await verifyMessage('Hello World', '0xSignature...');
296
+ console.log('Message was signed by:', signerAddress);
297
+ ```
298
+
299
+ ### Sign Typed Data (RECOMMENDED - Using Vault)
300
+ Signs a typed data message using Vault. This is equivalent to MetaMask's `eth_signTypedData` method.
301
+
302
+ **Parameters:**
303
+ - `typedData` - The typed data object to sign
304
+ - `vault` - The vault instance containing the account
305
+ - `fromAddress` - The signer's address
306
+
307
+ ```typescript
308
+ import { signTypedDataWithVault } from 'pwc-wallet-sdk/services/TokenUtils';
309
+
310
+ const typedData = {
311
+ types: {
312
+ Person: [
313
+ { name: 'name', type: 'string' },
314
+ { name: 'wallet', type: 'address' }
315
+ ]
316
+ },
317
+ primaryType: 'Person',
318
+ domain: { name: 'MyApp', version: '1' },
319
+ message: { name: 'Alice', wallet: '0x123...' }
320
+ };
321
+
322
+ const signature = await signTypedDataWithVault(typedData, vault, '0xYourAddress');
323
+ console.log('Typed Data Signature:', signature);
324
+ ```
325
+
326
+ ### Sign Typed Data (DEPRECATED - Using Private Key)
327
+ ⚠️ **DEPRECATED**: Use `signTypedDataWithVault` instead for better security.
328
+
329
+ **Parameters:**
330
+ - `typedData` - The typed data object to sign
331
+ - `privateKey` - The private key to sign with (without 0x prefix)
332
+
333
+ ```typescript
334
+ import { signTypedData } from 'pwc-wallet-sdk/services/TokenUtils';
335
+
336
+ const typedData = {
337
+ types: { Person: [{ name: 'name', type: 'string' }] },
338
+ primaryType: 'Person',
339
+ domain: { name: 'MyApp' },
340
+ message: { name: 'Alice' }
341
+ };
342
+
343
+ const signature = await signTypedData(typedData, 'your-private-key');
344
+ console.log('Typed Data Signature:', signature);
345
+ ```
346
+
347
+ ### Verify Typed Data
348
+ Verifies a typed data signature and returns the signer's address.
349
+
350
+ **Parameters:**
351
+ - `typedData` - The original typed data that was signed
352
+ - `signature` - The signature to verify
353
+
354
+ ```typescript
355
+ import { verifyTypedData } from 'pwc-wallet-sdk/services/TokenUtils';
356
+
357
+ const signerAddress = await verifyTypedData(typedData, '0xSignature...');
358
+ console.log('Typed data was signed by:', signerAddress);
359
+ ```
360
+
361
+ ### 🔢 Nonce Management
362
+
363
+ ### Get Nonce
364
+ Gets the transaction count (nonce) for an address. Useful for message signing with nonce and transaction building.
365
+
366
+ **Parameters:**
367
+ - `address` - The address to get nonce for
368
+ - `chainId` - The chain ID (e.g., '1' for Ethereum, '56' for BSC)
369
+
370
+ ```typescript
371
+ import { getNonce } from 'pwc-wallet-sdk/services/TokenUtils';
372
+
373
+ const nonce = await getNonce('0xYourAddress', '1');
374
+ console.log('Current nonce:', nonce);
375
+ ```
376
+
377
+ ### Sign Message with Nonce (RECOMMENDED - Using Vault)
378
+ Signs a message with nonce using Vault for better security. This prevents replay attacks by including the current nonce in the message.
379
+
380
+ **Parameters:**
381
+ - `message` - The message to sign (string or hex string)
382
+ - `vault` - The vault instance containing the account
383
+ - `fromAddress` - The signer's address
384
+ - `chainId` - The chain ID
385
+
386
+ ```typescript
387
+ import { signMessageWithNonce } from 'pwc-wallet-sdk/services/TokenUtils';
388
+
389
+ const result = await signMessageWithNonce('Hello World', vault, '0xYourAddress', '1');
390
+ console.log('Signature:', result.signature);
391
+ console.log('Nonce:', result.nonce);
392
+ ```
393
+
394
+ ### Sign Message with Nonce (DEPRECATED - Using Private Key)
395
+ ⚠️ **DEPRECATED**: Use `signMessageWithNonce` with Vault instead for better security.
396
+
397
+ **Parameters:**
398
+ - `message` - The message to sign (string or hex string)
399
+ - `privateKey` - The private key to sign with (without 0x prefix)
400
+ - `address` - The signer's address (needed to get nonce)
401
+ - `chainId` - The chain ID
402
+
403
+ ```typescript
404
+ import { signMessageWithNoncePrivateKey } from 'pwc-wallet-sdk/services/TokenUtils';
405
+
406
+ const result = await signMessageWithNoncePrivateKey('Hello World', 'your-private-key', '0xYourAddress', '1');
407
+ console.log('Signature:', result.signature);
408
+ console.log('Nonce:', result.nonce);
409
+ ```
410
+
411
+ ### Verify Message with Nonce
412
+ Verifies a message signature with nonce and returns the signer's address.
413
+
414
+ **Parameters:**
415
+ - `message` - The original message that was signed (without nonce)
416
+ - `signature` - The signature to verify
417
+ - `nonce` - The nonce that was used in signing
418
+
419
+ ```typescript
420
+ import { verifyMessageWithNonce } from 'pwc-wallet-sdk/services/TokenUtils';
421
+
422
+ const signerAddress = await verifyMessageWithNonce('Hello World', '0xSignature...', 5);
423
+ console.log('Message was signed by:', signerAddress);
424
+ ```
425
+
426
+ ### 🔍 Read-Only Utilities (Token & NFT)
427
+
428
+ ### Get Token Balance
429
+ Gets the token balance for a specific account.
430
+
431
+ **Parameters:**
432
+ - `tokenAddress` - The ERC-20 token contract address
433
+ - `account` - The account address to check balance for
434
+ - `chainId` - The chain ID
435
+
436
+ ```typescript
437
+ import { getTokenBalance } from 'pwc-wallet-sdk/services/TokenUtils';
438
+
439
+ const balance = await getTokenBalance(
440
+ '0xA0b86a33E6441b8c4C8C8C8C8C8C8C8C8C8C8C8', // USDT contract
441
+ '0xYourWalletAddress...',
442
+ '1' // Ethereum mainnet
443
+ );
444
+ console.log('USDT Balance:', ethers.formatUnits(balance, 6)); // USDT has 6 decimals
445
+ ```
446
+
447
+ ### Get Token Info
448
+ Gets comprehensive information about an ERC-20 token.
449
+
450
+ **Parameters:**
451
+ - `tokenAddress` - The ERC-20 token contract address
452
+ - `chainId` - The chain ID
453
+
454
+ ```typescript
455
+ import { getTokenInfo } from 'pwc-wallet-sdk/services/TokenUtils';
456
+
457
+ const info = await getTokenInfo(
458
+ '0xA0b86a33E6441b8c4C8C8C8C8C8C8C8C8C8C8C8', // USDT contract
459
+ '1' // Ethereum mainnet
460
+ );
461
+ console.log('Token:', info.name, '(', info.symbol, ')');
462
+ console.log('Decimals:', info.decimals);
463
+ console.log('Total Supply:', ethers.formatUnits(info.totalSupply, info.decimals));
464
+ ```
465
+
466
+ ### Get Native Balance
467
+ Gets the native token balance (ETH, BNB, MATIC, etc.) for an account.
468
+
469
+ **Parameters:**
470
+ - `account` - The account address to check balance for
471
+ - `chainId` - The chain ID
472
+
473
+ ```typescript
474
+ import { getNativeBalance } from 'pwc-wallet-sdk/services/TokenUtils';
475
+
476
+ const balance = await getNativeBalance('0xYourWalletAddress...', '1');
477
+ console.log('ETH Balance:', ethers.formatEther(balance));
478
+
479
+ // For BSC
480
+ const bnbBalance = await getNativeBalance('0xYourWalletAddress...', '56');
481
+ console.log('BNB Balance:', ethers.formatEther(bnbBalance));
482
+ ```
483
+
484
+ ### Check Allowance
485
+ Checks the allowance granted by an owner to a spender for a specific token.
486
+
487
+ **Parameters:**
488
+ - `tokenAddress` - The ERC-20 token contract address
489
+ - `owner` - The token owner's address
490
+ - `spender` - The spender's address (e.g., DEX contract address)
491
+ - `chainId` - The chain ID
492
+
493
+ ```typescript
494
+ import { checkAllowance } from 'pwc-wallet-sdk/services/TokenUtils';
495
+
496
+ const allowance = await checkAllowance(
497
+ '0xA0b86a33E6441b8c4C8C8C8C8C8C8C8C8C8C8C8', // USDT contract
498
+ '0xYourWalletAddress...', // Owner
499
+ '0xDexContractAddress...', // Spender (DEX)
500
+ '1' // Ethereum mainnet
501
+ );
502
+ console.log('Allowance:', ethers.formatUnits(allowance, 6)); // USDT has 6 decimals
503
+ ```
504
+
505
+ ### Get NFT Details
506
+ Gets comprehensive NFT detail by reading directly from blockchain. Supports both ERC-721 and ERC-1155 NFTs.
507
+
508
+ **ERC-1155 Support Features:**
509
+ - ✅ **Auto-detection**: Automatically detects ERC-721 vs ERC-1155 contracts
510
+ - ✅ **Metadata resolution**: Reads metadata from `uri(tokenId)` function
511
+ - ✅ **Transaction history**: Supports TransferSingle and TransferBatch events
512
+ - ✅ **Collection info**: Gets collection name and symbol
513
+ - ✅ **Token validation**: Checks if token exists via `exists(tokenId)`
514
+ - ✅ **Multiple owners**: Handles ERC-1155's multiple ownership model
515
+
516
+ **Parameters:**
517
+ - `contractAddress` - NFT contract address
518
+ - `tokenId` - Token ID (string)
519
+ - `options` - Optional parameters for additional data
520
+ - `includeMetadata` - Whether to fetch metadata (default: false)
521
+ - `includeHistory` - Whether to fetch transaction history (default: false)
522
+ - `includeCollection` - Whether to fetch collection info (default: false)
523
+
524
+ ```typescript
525
+ import { NFTService } from 'pwc-wallet-sdk';
526
+
527
+ const nftService = new NFTService('1'); // chainId = '1' for Ethereum (read-only)
528
+
529
+ // For ERC-721 NFTs
530
+ const nftDetail = await nftService.getNFTDetail(
531
+ '0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D', // BAYC contract
532
+ '1234', // Token ID
533
+ {
534
+ includeMetadata: true,
535
+ includeHistory: true,
536
+ includeCollection: true
537
+ }
538
+ );
539
+ console.log('NFT Name:', nftDetail.name);
540
+ console.log('Owner:', nftDetail.owner);
541
+ console.log('Image URL:', nftDetail.image);
542
+ console.log('Attributes:', nftDetail.attributes);
543
+
544
+ // For ERC-1155 NFTs
545
+ const erc1155Detail = await nftService.getNFTDetail(
546
+ '0xERC1155Contract...', // ERC-1155 contract
547
+ '123', // Token ID
548
+ {
549
+ includeMetadata: true,
550
+ includeHistory: true,
551
+ includeCollection: true
552
+ }
553
+ );
554
+ console.log('ERC-1155 Name:', erc1155Detail.name);
555
+ console.log('Owner:', erc1155Detail.owner); // 'Multiple Owners' for ERC-1155
556
+ console.log('Token Type:', erc1155Detail.tokenType); // 'ERC-1155'
557
+ ```
558
+
559
+ ### Get NFT Balance
560
+ Gets NFT balance for an address from a specific contract. Supports both ERC-721 and ERC-1155.
561
+
562
+ **Parameters:**
563
+ - `address` - Wallet address to check balance for
564
+ - `contractAddress` - NFT contract address
565
+ - `tokenId` - (Optional) Token ID for ERC-1155 contracts
566
+
567
+ ```typescript
568
+ // For ERC-721 NFTs
569
+ const nftBalance = await nftService.getNFTBalance(
570
+ '0xYourWalletAddress...',
571
+ '0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D' // BAYC contract
572
+ );
573
+ console.log('ERC-721 Count:', nftBalance.count);
574
+
575
+ // For ERC-1155 NFTs (with specific token ID)
576
+ const nftBalance = await nftService.getNFTBalance(
577
+ '0xYourWalletAddress...',
578
+ '0xERC1155Contract...',
579
+ '123' // Token ID
580
+ );
581
+ console.log('ERC-1155 Balance:', nftBalance.count);
582
+ ```
583
+
584
+ ### Get ERC-1155 Balance
585
+ Gets ERC-1155 token balance for a specific address and token ID.
586
+
587
+ **Parameters:**
588
+ - `address` - Wallet address to check balance for
589
+ - `contractAddress` - ERC-1155 contract address
590
+ - `tokenId` - Token ID to check balance for
591
+
592
+ ```typescript
593
+ const balance = await nftService.getERC1155Balance(
594
+ '0xYourWalletAddress...',
595
+ '0xERC1155Contract...',
596
+ '123' // Token ID
597
+ );
598
+ console.log('ERC-1155 Balance:', balance.toString());
599
+ ```
600
+
601
+ ### Get Multiple ERC-1155 Balances
602
+ Gets balances for multiple ERC-1155 tokens at once.
603
+
604
+ **Parameters:**
605
+ - `address` - Wallet address to check balances for
606
+ - `contractAddress` - ERC-1155 contract address
607
+ - `tokenIds` - Array of token IDs to check
608
+
609
+ ```typescript
610
+ const balances = await nftService.getERC1155Balances(
611
+ '0xYourWalletAddress...',
612
+ '0xERC1155Contract...',
613
+ ['123', '456', '789'] // Multiple token IDs
614
+ );
615
+
616
+ balances.forEach(balance => {
617
+ console.log(`Token ${balance.tokenId}: ${balance.amount.toString()}`);
618
+ });
619
+ ```
620
+
621
+ ### Get Collection Information
622
+ Gets collection information directly from the NFT contract.
623
+
624
+ **Parameters:**
625
+ - `contractAddress` - NFT contract address
626
+
627
+ ```typescript
628
+ const collection = await nftService.getCollectionInfo('0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D');
629
+ console.log('Collection Name:', collection.name);
630
+ console.log('Total Supply:', collection.totalSupply);
631
+ console.log('Token Type:', collection.tokenType);
632
+ ```
633
+
634
+ ### NFT Metadata & Attributes
635
+ NFT metadata is automatically resolved from tokenURI (IPFS or HTTP). Works for both ERC-721 and ERC-1155.
636
+
637
+ **Key Differences:**
638
+ - **ERC-721**: Single owner per token, uses `tokenURI(tokenId)`
639
+ - **ERC-1155**: Multiple owners possible, uses `uri(tokenId)`, owner field shows "Multiple Owners"
640
+
641
+ ```typescript
642
+ import { NFTDetail, NFTDetailExtended, NFTCollection, NFTOptions } from 'pwc-wallet-sdk';
643
+
644
+ // Basic NFT information (on-chain data)
645
+ interface NFTDetail {
646
+ contractAddress: string;
647
+ tokenId: string;
648
+ name: string;
649
+ owner: string;
650
+ tokenType: 'ERC-721' | 'ERC-1155' | 'SPL-NFT';
651
+ chainId: string;
652
+ tokenUri?: string;
653
+ createdAt?: number;
654
+ lastTransferAt?: number;
655
+ }
656
+
657
+ // Extended NFT information with metadata
658
+ interface NFTDetailExtended extends NFTDetail {
659
+ description?: string;
660
+ image?: string;
661
+ attributes?: Array<{ trait_type: string; value: string; display_type?: string }>;
662
+ metadata?: NFTMetadata;
663
+ collection?: NFTCollection;
664
+ transactionHistory?: NFTTransaction[];
665
+ metadataSource?: 'ipfs' | 'http';
666
+ lastUpdated: number;
667
+ }
668
+
669
+ // Collection information
670
+ interface NFTCollection {
671
+ contractAddress: string;
672
+ name: string;
673
+ symbol: string;
674
+ tokenType: string;
675
+ chainId: string;
676
+ totalSupply?: number;
677
+ }
678
+ ```
679
+
680
+ ### NFT Transaction History
681
+ Gets transaction history from blockchain events.
682
+
683
+ **Parameters:**
684
+ - `contractAddress` - NFT contract address
685
+ - `tokenId` - Token ID (string)
686
+
687
+ ```typescript
688
+ const history = await nftService.getTransactionHistory(
689
+ '0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D', // NFT contract
690
+ '1234' // Token ID
691
+ );
692
+ console.log('Transaction History:', history);
693
+ // Returns array of: { hash, from, to, blockNumber, timestamp, type }
694
+ ```
695
+
696
+ ### NFT Types and Interfaces
697
+ Complete TypeScript interfaces for NFT functionality.
698
+
699
+ ```typescript
700
+ import {
701
+ NFTDetail,
702
+ NFTDetailExtended,
703
+ NFTCollection,
704
+ NFTOptions,
705
+ NFTMetadata,
706
+ NFTTransaction,
707
+ NFTBalance
708
+ } from 'pwc-wallet-sdk';
709
+
710
+ // Basic NFT information (on-chain data)
711
+ interface NFTDetail {
712
+ contractAddress: string;
713
+ tokenId: string;
714
+ name: string;
715
+ owner: string;
716
+ tokenType: 'ERC-721' | 'ERC-1155' | 'SPL-NFT';
717
+ chainId: string;
718
+ tokenUri?: string;
719
+ createdAt?: number;
720
+ lastTransferAt?: number;
721
+ }
722
+
723
+ // Extended NFT information with metadata
724
+ interface NFTDetailExtended extends NFTDetail {
725
+ description?: string;
726
+ image?: string;
727
+ attributes?: Array<{ trait_type: string; value: string; display_type?: string }>;
728
+ metadata?: NFTMetadata;
729
+ collection?: NFTCollection;
730
+ transactionHistory?: NFTTransaction[];
731
+ metadataSource?: 'ipfs' | 'http';
732
+ lastUpdated: number;
733
+ }
734
+
735
+ // NFT metadata from tokenURI
736
+ interface NFTMetadata {
737
+ name: string;
738
+ description?: string;
739
+ image?: string;
740
+ attributes?: Array<{ trait_type: string; value: string; display_type?: string }>;
741
+ external_url?: string;
742
+ animation_url?: string;
743
+ }
744
+
745
+ // Collection information
746
+ interface NFTCollection {
747
+ contractAddress: string;
748
+ name: string;
749
+ symbol: string;
750
+ tokenType: string;
751
+ chainId: string;
752
+ totalSupply?: number;
753
+ }
754
+
755
+ // NFT transaction history
756
+ interface NFTTransaction {
757
+ hash: string;
758
+ from: string;
759
+ to: string;
760
+ blockNumber: number;
761
+ timestamp: number;
762
+ type: 'mint' | 'transfer';
763
+ }
764
+
765
+ // NFT balance information
766
+ interface NFTBalance {
767
+ contractAddress: string;
768
+ tokenIds: string[];
769
+ count: number;
770
+ tokenType: string;
771
+ chainId: string;
772
+ }
773
+
774
+ // NFT options for queries
775
+ interface NFTOptions {
776
+ includeMetadata?: boolean;
777
+ includeHistory?: boolean;
778
+ includeCollection?: boolean;
779
+ }
780
+ ```
781
+
782
+ ### React Native NFT Component Example
783
+ ```typescript
784
+ import React, { useState, useEffect } from 'react';
785
+ import { View, Text, Image, ScrollView } from 'react-native';
786
+ import { NFTService, NFTDetailExtended } from 'pwc-wallet-sdk';
787
+
788
+ const NFTDetailView = ({ contractAddress, tokenId, chainId }) => {
789
+ const [nft, setNft] = useState(null);
790
+ const [loading, setLoading] = useState(true);
791
+ const [error, setError] = useState(null);
792
+
793
+ useEffect(() => {
794
+ loadNFTDetail();
795
+ }, [contractAddress, tokenId]);
796
+
797
+ const loadNFTDetail = async () => {
798
+ try {
799
+ setLoading(true);
800
+ setError(null);
801
+
802
+ const nftService = new NFTService(chainId); // Read-only operations
803
+ const nftDetail = await nftService.getNFTDetail(
804
+ contractAddress,
805
+ tokenId,
806
+ { includeMetadata: true, includeHistory: true }
807
+ );
808
+ setNft(nftDetail);
809
+ } catch (err) {
810
+ setError(err.message);
811
+ console.error('Failed to load NFT:', err);
812
+ } finally {
813
+ setLoading(false);
814
+ }
815
+ };
816
+
817
+ if (loading) {
818
+ return <Text>Loading NFT...</Text>;
819
+ }
820
+
821
+ if (error) {
822
+ return <Text>Error: {error}</Text>;
823
+ }
824
+
825
+ if (!nft) {
826
+ return <Text>NFT not found</Text>;
827
+ }
828
+
829
+ return (
830
+ <ScrollView style={{ padding: 20 }}>
831
+ {nft.image && (
832
+ <Image
833
+ source={{ uri: nft.image }}
834
+ style={{ width: 300, height: 300, alignSelf: 'center' }}
835
+ resizeMode="cover"
836
+ />
837
+ )}
838
+ <Text style={{ fontSize: 24, fontWeight: 'bold', marginTop: 10 }}>
839
+ {nft.name}
840
+ </Text>
841
+ {nft.description && (
842
+ <Text style={{ marginTop: 5 }}>{nft.description}</Text>
843
+ )}
844
+ <Text style={{ marginTop: 10 }}>
845
+ Contract: {nft.contractAddress}
846
+ </Text>
847
+ <Text>Token ID: {nft.tokenId}</Text>
848
+ <Text>Owner: {nft.owner}</Text>
849
+ <Text>Type: {nft.tokenType}</Text>
850
+
851
+ {nft.attributes && nft.attributes.length > 0 && (
852
+ <View style={{ marginTop: 15 }}>
853
+ <Text style={{ fontSize: 18, fontWeight: 'bold' }}>Attributes:</Text>
854
+ {nft.attributes.map((attr, index) => (
855
+ <Text key={index}>
856
+ {attr.trait_type}: {attr.value}
857
+ </Text>
858
+ ))}
859
+ </View>
860
+ )}
861
+ </ScrollView>
862
+ );
863
+ };
864
+ ```
865
+
866
+ ### Get Owned NFTs
867
+ Gets all NFTs owned by an address from multiple contracts.
868
+
869
+ **Parameters:**
870
+ - `account` - Wallet address to check
871
+ - `contractAddresses` - Array of NFT contract addresses
872
+ - `options` - Optional parameters (same as getNFTDetail)
873
+
874
+ ```typescript
875
+ const nfts = await nftService.getOwnedNFTs(
876
+ '0xYourWalletAddress...',
877
+ ['0xContract1...', '0xContract2...'],
878
+ { includeMetadata: true }
879
+ );
880
+ console.log('Total NFTs:', nfts.length);
881
+ nfts.forEach(nft => {
882
+ console.log(`${nft.name} (${nft.contractAddress})`);
883
+ });
884
+ ```
885
+
886
+ ### Transfer NFT
887
+ Transfers an NFT (ERC-721) from one address to another.
888
+
889
+ **Parameters:**
890
+ - `fromAddress` - Sender's address
891
+ - `toAddress` - Recipient's address
892
+ - `contractAddress` - NFT contract address (ERC-721)
893
+ - `tokenId` - Token ID to transfer (string)
894
+
895
+ ```typescript
896
+ // Gửi NFT ERC-721 từ ví này sang ví khác
897
+ const tx = await vault.transferNFT(
898
+ '0xSenderAddress',
899
+ '0xRecipientAddress',
900
+ '0xNFTContractAddress',
901
+ '1234' // Token ID
902
+ );
903
+ console.log('NFT transfer tx hash:', tx.hash);
904
+ ```
905
+
906
+ > **Note:** Hiện tại chỉ hỗ trợ EVM chains (Ethereum, BSC, v.v.). Solana NFT transfer chưa được hỗ trợ.
907
+
908
+ ---
909
+
910
+ ## NFT Transfer (ERC-721 & ERC-1155)
911
+
912
+ ### Initialize NFTService for Transfer Operations
913
+ For transfer operations, you need to initialize `NFTService` with vault and sender address:
914
+
915
+ ```typescript
916
+ import { NFTService, Vault } from 'pwc-wallet-sdk';
917
+
918
+ // Initialize for read-only operations
919
+ const nftService = new NFTService('1'); // chainId = '1' for Ethereum
920
+
921
+ // Initialize for write operations (transfer)
922
+ const nftService = new NFTService('1', vault, fromAddress);
923
+ ```
924
+
925
+ ### Transfer NFT (RECOMMENDED - Using Vault)
926
+ The `transferNFTWithVault` function supports transferring both ERC-721 and ERC-1155 NFTs.
927
+
928
+ **Parameters:**
929
+ - `vault` - The Vault instance containing the sender's account
930
+ - `fromAddress` - The sender's wallet address
931
+ - `toAddress` - The recipient's wallet address
932
+ - `contractAddress` - The NFT contract address
933
+ - `tokenId` - The token ID to transfer
934
+ - `amount` (optional, default "1") - The amount to transfer (required for ERC-1155, default 1 for ERC-721)
935
+
936
+ **Usage:**
937
+ ```typescript
938
+ // Initialize NFTService for transfer operations
939
+ const nftService = new NFTService('1', vault, fromAddress);
940
+
941
+ // ERC-721: only basic parameters are required
942
+ await nftService.transferNFTWithVault(
943
+ fromAddress,
944
+ toAddress,
945
+ contractAddress,
946
+ tokenId
947
+ );
948
+
949
+ // ERC-1155: specify the amount (number of NFTs to transfer)
950
+ await nftService.transferNFTWithVault(
951
+ fromAddress,
952
+ toAddress,
953
+ contractAddress,
954
+ tokenId,
955
+ "5" // transfer 5 ERC-1155 NFTs
956
+ );
957
+ ```
958
+
959
+ - The function will automatically detect the contract type (ERC-721 or ERC-1155) and call the correct transfer method.
960
+ - If the contract is ERC-721, `amount` will default to 1.
961
+ - If the contract is ERC-1155, `amount` is the number of NFTs to transfer.
962
+
963
+ ### Deprecated: transferNFT
964
+ The `transferNFT` function (without vault) also supports both standards, but is **not recommended for production**.
965
+
966
+ ### Estimate NFT Transfer Gas
967
+ Estimates the gas cost for transferring NFTs (ERC-721 and ERC-1155).
968
+
969
+ **Parameters:**
970
+ - `fromAddress` - The sender's address
971
+ - `toAddress` - The recipient's address
972
+ - `contractAddress` - The NFT contract address
973
+ - `tokenId` - The token ID to transfer
974
+ - `amount` (optional, default "1") - The amount to transfer (for ERC-1155, default 1 for ERC-721)
975
+
976
+ **Usage:**
977
+ ```typescript
978
+ import { NFTService } from 'pwc-wallet-sdk';
979
+
980
+ // Initialize NFTService
981
+ const nftService = new NFTService('1'); // Ethereum mainnet
982
+
983
+ // Estimate gas for ERC-721 transfer
984
+ const erc721Gas = await nftService.estimateGasForTransfer(
985
+ '0xSender...',
986
+ '0xRecipient...',
987
+ '0xContract...',
988
+ '123'
989
+ );
990
+ console.log('ERC-721 transfer gas:', erc721Gas.toString());
991
+
992
+ // Estimate gas for ERC-1155 transfer
993
+ const erc1155Gas = await nftService.estimateGasForTransfer(
994
+ '0xSender...',
995
+ '0xRecipient...',
996
+ '0xContract...',
997
+ '123',
998
+ '5' // transfer 5 ERC-1155 NFTs
999
+ );
1000
+ console.log('ERC-1155 transfer gas:', erc1155Gas.toString());
1001
+ ```
1002
+
1003
+ ### Estimate Gas for Various NFT Operations
1004
+ Estimates gas cost for different NFT operations including transfer, approve, and setApprovalForAll.
1005
+
1006
+ **Parameters:**
1007
+ - `operation` - The operation type: 'transfer', 'approve', or 'setApprovalForAll'
1008
+ - `contractAddress` - The NFT contract address
1009
+ - `params` - Operation-specific parameters
1010
+
1011
+ **Usage:**
1012
+ ```typescript
1013
+ // Estimate gas for ERC-721 approve
1014
+ const approveGas = await nftService.estimateGas('approve', '0xContract...', {
1015
+ toAddress: '0xSpender...',
1016
+ tokenId: '123'
1017
+ });
1018
+
1019
+ // Estimate gas for ERC-721 setApprovalForAll
1020
+ const setApprovalGas = await nftService.estimateGas('setApprovalForAll', '0xContract...', {
1021
+ toAddress: '0xOperator...',
1022
+ approved: true
1023
+ });
1024
+
1025
+ // Estimate gas for ERC-721 transfer
1026
+ const transferGas = await nftService.estimateGas('transfer', '0xContract...', {
1027
+ fromAddress: '0xSender...',
1028
+ toAddress: '0xRecipient...',
1029
+ tokenId: '123'
1030
+ });
1031
+
1032
+ // Estimate gas for ERC-1155 transfer
1033
+ const erc1155TransferGas = await nftService.estimateGas('transfer', '0xContract...', {
1034
+ fromAddress: '0xSender...',
1035
+ toAddress: '0xRecipient...',
1036
+ tokenId: '123',
1037
+ amount: '3'
1038
+ });
1039
+
1040
+ console.log('Approve gas:', approveGas.toString());
1041
+ console.log('Set approval gas:', setApprovalGas.toString());
1042
+ console.log('Transfer gas:', transferGas.toString());
1043
+ console.log('ERC-1155 transfer gas:', erc1155TransferGas.toString());
1044
+ ```
1045
+
1046
+ **Supported Operations:**
1047
+ - **ERC-721**: `transfer`, `approve`, `setApprovalForAll`
1048
+ - **ERC-1155**: `transfer` only (approve operations not supported)
1049
+
1050
+ **Features:**
1051
+ - ✅ **Automatic Contract Detection**: Automatically detects ERC-721 vs ERC-1155
1052
+ - ✅ **Token Validation**: Verifies token exists before estimating gas
1053
+ - ✅ **Parameter Validation**: Validates required parameters for each operation
1054
+ - ✅ **Error Handling**: Comprehensive error messages for invalid operations
1055
+
1056
+ ---
1057
+
1058
+ ## Features
1059
+
1060
+ - 🔐 **Secure HD Wallet Management**: BIP-44 compliant hierarchical deterministic wallets
1061
+ - 🎯 **Vanity Address Generation**: Generate wallets with custom address prefixes
1062
+ - 🔗 **Multi-Chain Support**: Ethereum, BSC, Polygon, Arbitrum, Optimism, Base, and Solana
1063
+ - 🚀 **Multi-Transfer Operations**: Batch send tokens to multiple recipients
1064
+ - 🔧 **Custom Chain Support**: Add custom chains and override built-in configurations
1065
+ - 📱 **React Native Optimized**: Designed specifically for mobile applications
1066
+ - 🔒 **Encryption**: AES-256 encryption for secure vault storage
1067
+ - 🎨 **TypeScript**: Full TypeScript support with comprehensive type definitions
1068
+ - 🖼️ **NFT Support**: Core NFT functionality for individual tokens and collections
1069
+ - ⛽ **Gas Estimation**: Comprehensive gas estimation for native tokens, ERC-20 tokens, and NFTs
1070
+
1071
+ ## Installation
1072
+
1073
+ ```bash
1074
+ npm install pwc-wallet-sdk
1075
+ ```
1076
+
1077
+ ## Quick Start
1078
+
1079
+ ### 1. Basic Wallet Creation
1080
+
1081
+ ```typescript
1082
+ import { Vault } from 'pwc-wallet-sdk';
1083
+
1084
+ // Create a new wallet
1085
+ const { vault, encryptedVault } = await Vault.createNew('your-secure-password');
1086
+
1087
+ // Get wallet accounts
1088
+ const accounts = vault.getAccounts();
1089
+ console.log('Wallet addresses:', accounts.map(acc => acc.address));
1090
+ ```
1091
+
1092
+ ### 1.1. Import Existing Wallet from Seed Phrase
1093
+
1094
+ ```typescript
1095
+ import { Vault } from 'pwc-wallet-sdk';
1096
+
1097
+ // Import wallet from existing mnemonic phrase
1098
+ const existingMnemonic = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
1099
+
1100
+ // For EVM chains (Ethereum, BSC, Polygon, etc.)
1101
+ const { vault, encryptedVault } = await Vault.createFromMnemonic(
1102
+ existingMnemonic,
1103
+ 'your-secure-password',
1104
+ 'evm'
1105
+ );
1106
+
1107
+ // For Solana
1108
+ const { vault, encryptedVault } = await Vault.createFromMnemonic(
1109
+ existingMnemonic,
1110
+ 'your-secure-password',
1111
+ 'solana'
1112
+ );
1113
+
1114
+ // Get wallet accounts
1115
+ const accounts = vault.getAccounts();
1116
+ console.log('Imported wallet addresses:', accounts.map(acc => acc.address));
1117
+
1118
+ // Validate mnemonic before importing (optional)
1119
+ import { EncryptionService } from 'pwc-wallet-sdk';
1120
+
1121
+ const isValid = EncryptionService.validateMnemonic(existingMnemonic);
1122
+ if (!isValid) {
1123
+ throw new Error('Invalid mnemonic phrase');
1124
+ }
1125
+ ```
1126
+
1127
+ ### 2. Vanity Wallet Generation
1128
+
1129
+ ```typescript
1130
+ // Generate wallet with custom address prefix
1131
+ const { vault, encryptedVault, attempts, foundAddress } =
1132
+ await Vault.generateVanityHDWallet('your-password', (attempts, currentAddress) => {
1133
+ console.log(`Attempt ${attempts}: ${currentAddress}`);
1134
+ });
1135
+
1136
+ console.log(`Found address with prefix after ${attempts} attempts: ${foundAddress}`);
1137
+ ```
1138
+
1139
+ #### Mobile-Optimized Vanity Wallet Generation
1140
+
1141
+ For mobile applications, use the mobile-optimized version for better performance:
1142
+
1143
+ ```typescript
1144
+ // Mobile-optimized vanity wallet generation
1145
+ const { vault, encryptedVault, attempts, foundAddress } =
1146
+ await Vault.generateVanityHDWalletMobile('your-password', (attempts, currentAddress) => {
1147
+ console.log(`Mobile attempt ${attempts}: ${currentAddress}`);
1148
+ }, {
1149
+ prefix: 'a', // Single character prefix (much faster)
1150
+ maxAttempts: 50000, // Lower limit for mobile
1151
+ timeout: 30000, // 30 seconds timeout
1152
+ caseSensitive: false
1153
+ });
1154
+
1155
+ console.log(`Mobile vanity wallet generated in ${attempts} attempts: ${foundAddress}`);
1156
+ ```
1157
+
1158
+ **Mobile Optimizations:**
1159
+ - ✅ Batch processing (100 attempts per batch)
1160
+ - ✅ Shorter default prefix (1 character vs 3)
1161
+ - ✅ Lower max attempts (50K vs 1M)
1162
+ - ✅ Timeout protection (30 seconds)
1163
+ - ✅ More frequent progress updates
1164
+ - ✅ More frequent non-blocking yields
1165
+
1166
+ ### 3. Custom Chain Configuration
1167
+
1168
+ ```typescript
1169
+ import { setupChainConfigs, registerCustomChain, overrideChain } from 'pwc-wallet-sdk';
1170
+
1171
+ // Setup custom chains and overrides (call once when app starts)
1172
+ setupChainConfigs({
1173
+ // Override built-in chains
1174
+ overrides: {
1175
+ '1': { rpcUrl: 'https://my-eth-rpc.com' }, // Use custom Ethereum RPC
1176
+ '56': { rpcUrl: 'https://my-bsc-rpc.com' }, // Use custom BSC RPC
1177
+ },
1178
+ // Add custom chains
1179
+ customChains: {
1180
+ 'custom-1': {
1181
+ name: 'My Custom Chain',
1182
+ rpcUrl: 'https://my-custom-rpc.com',
1183
+ explorerUrl: 'https://my-explorer.com',
1184
+ nativeCurrency: { name: 'Token', symbol: 'TKN', decimals: 18 },
1185
+ type: 'evm'
1186
+ },
1187
+ 'custom-solana': {
1188
+ name: 'My Solana Chain',
1189
+ rpcUrl: 'https://my-solana-rpc.com',
1190
+ explorerUrl: 'https://my-solana-explorer.com',
1191
+ nativeCurrency: { name: 'SOL', symbol: 'SOL', decimals: 9 },
1192
+ type: 'solana'
1193
+ }
1194
+ }
1195
+ });
1196
+
1197
+ // Load vault
1198
+ const vault = await Vault.load(password, encryptedVault);
1199
+
1200
+ // Use custom chains normally
1201
+ await vault.sendToken(from, to, amount, tokenAddress, 'custom-1');
1202
+ await vault.getNativeBalance(address, 'custom-solana');
1203
+ ```
1204
+
1205
+ ## React Native Usage
1206
+
1207
+ ### Simple Wallet Component
1208
+
1209
+ ```typescript
1210
+ import React, { useState, useEffect } from 'react';
1211
+ import { Vault, setupChainConfigs } from 'pwc-wallet-sdk';
1212
+
1213
+ const WalletComponent = () => {
1214
+ const [vault, setVault] = useState(null);
1215
+ const [balance, setBalance] = useState('0');
1216
+
1217
+ useEffect(() => {
1218
+ // Setup custom chains when component mounts
1219
+ setupChainConfigs({
1220
+ overrides: {
1221
+ '1': { rpcUrl: 'https://my-eth-rpc.com' }
1222
+ },
1223
+ customChains: {
1224
+ 'custom-1': {
1225
+ name: 'My Chain',
1226
+ rpcUrl: 'https://my-rpc.com',
1227
+ type: 'evm'
1228
+ }
1229
+ }
1230
+ });
1231
+
1232
+ loadWallet();
1233
+ }, []);
1234
+
1235
+ const loadWallet = async () => {
1236
+ try {
1237
+ const loadedVault = await Vault.load(password, encryptedVault);
1238
+ setVault(loadedVault);
1239
+
1240
+ // Get balance using custom chain
1241
+ const balance = await loadedVault.getNativeBalance(address, 'custom-1');
1242
+ setBalance(ethers.formatEther(balance));
1243
+ } catch (error) {
1244
+ console.error('Failed to load wallet:', error);
1245
+ }
1246
+ };
1247
+
1248
+ const sendTransaction = async () => {
1249
+ if (!vault) return;
1250
+
1251
+ try {
1252
+ // Send using custom chain
1253
+ const tx = await vault.sendToken(from, to, amount, tokenAddress, 'custom-1');
1254
+ console.log('Transaction sent:', tx.hash);
1255
+ } catch (error) {
1256
+ console.error('Transaction failed:', error);
1257
+ }
1258
+ };
1259
+
1260
+ return (
1261
+ <View>
1262
+ <Text>Balance: {balance}</Text>
1263
+ <Button title="Send Transaction" onPress={sendTransaction} />
1264
+ </View>
1265
+ );
1266
+ };
1267
+ ```
1268
+
1269
+ ### Custom Hook for Wallet Management
1270
+
1271
+ ```typescript
1272
+ import { useState, useEffect } from 'react';
1273
+ import { Vault, setupChainConfigs } from 'pwc-wallet-sdk';
1274
+
1275
+ export const useWallet = (password: string, encryptedVault: EncryptedData) => {
1276
+ const [vault, setVault] = useState(null);
1277
+ const [loading, setLoading] = useState(true);
1278
+ const [error, setError] = useState(null);
1279
+
1280
+ useEffect(() => {
1281
+ initializeWallet();
1282
+ }, []);
1283
+
1284
+ const initializeWallet = async () => {
1285
+ try {
1286
+ setLoading(true);
1287
+
1288
+ // Setup chains
1289
+ setupChainConfigs({
1290
+ overrides: {
1291
+ '1': { rpcUrl: 'https://my-eth-rpc.com' }
1292
+ }
1293
+ });
1294
+
1295
+ const loadedVault = await Vault.load(password, encryptedVault);
1296
+ setVault(loadedVault);
1297
+ } catch (err) {
1298
+ setError(err.message);
1299
+ } finally {
1300
+ setLoading(false);
1301
+ }
1302
+ };
1303
+
1304
+ const sendToken = async (from: string, to: string, amount: string, tokenAddress: string, chainId: string) => {
1305
+ if (!vault) throw new Error('Wallet not loaded');
1306
+ return vault.sendToken(from, to, amount, tokenAddress, chainId);
1307
+ };
1308
+
1309
+ const getBalance = async (address: string, chainId: string) => {
1310
+ if (!vault) throw new Error('Wallet not loaded');
1311
+ return vault.getNativeBalance(address, chainId);
1312
+ };
1313
+
1314
+ return {
1315
+ vault,
1316
+ loading,
1317
+ error,
1318
+ sendToken,
1319
+ getBalance
1320
+ };
1321
+ };
1322
+ ```
1323
+
1324
+ ## Configuration
1325
+
1326
+ ### Vanity Wallet Settings
1327
+
1328
+ ```typescript
1329
+ import { VANITY_WALLET_CONFIG } from 'pwc-wallet-sdk';
1330
+
1331
+ // Default settings
1332
+ console.log(VANITY_WALLET_CONFIG.DEFAULT_PREFIX); // 'aaa'
1333
+ console.log(VANITY_WALLET_CONFIG.DEFAULT_MAX_ATTEMPTS); // 1000000
1334
+ console.log(VANITY_WALLET_CONFIG.DEFAULT_CASE_SENSITIVE); // false
1335
+ ```
1336
+
1337
+ ### Supported Chains
1338
+
1339
+ ```typescript
1340
+ import { SUPPORTED_CHAINS } from 'pwc-wallet-sdk';
1341
+
1342
+ // View all supported chains
1343
+ Object.entries(SUPPORTED_CHAINS).forEach(([chainId, config]) => {
1344
+ console.log(`${chainId}: ${config.name} (${config.type})`);
1345
+ });
1346
+ ```
1347
+
1348
+ ## Core Wallet Functions
1349
+
1350
+ ### Account Management
1351
+
1352
+ #### Add New HD Account
1353
+ ```typescript
1354
+ // Add a new HD account to the vault
1355
+ const newAccount = vault.addHDAccount();
1356
+ console.log('New account address:', newAccount.address);
1357
+ ```
1358
+
1359
+ #### Add New Solana Account
1360
+ ```typescript
1361
+ // Add a new Solana account
1362
+ const newSolanaAccount = vault.addSolanaAccount();
1363
+ console.log('New Solana account:', newSolanaAccount.address);
1364
+ ```
1365
+
1366
+ #### Import Account
1367
+ ```typescript
1368
+ // Import an existing account with private key
1369
+ const importedAccount = vault.importAccount('private-key-without-0x-prefix');
1370
+ console.log('Imported account:', importedAccount.address);
1371
+ ```
1372
+
1373
+ #### Get Accounts
1374
+ ```typescript
1375
+ // Get all accounts in the vault
1376
+ const accounts = vault.getAccounts();
1377
+ console.log('All accounts:', accounts.map(acc => acc.address));
1378
+ ```
1379
+
1380
+ ### Balance & Token Functions
1381
+
1382
+ #### Get Native Balance
1383
+ ```typescript
1384
+ // Get native token balance (ETH, BNB, MATIC, etc.)
1385
+ const balance = await vault.getNativeBalance(address, '1'); // Ethereum
1386
+ console.log('ETH Balance:', ethers.formatEther(balance));
1387
+ ```
1388
+
1389
+ #### Get Token Balance
1390
+ ```typescript
1391
+ // Get ERC-20 token balance
1392
+ const tokenBalance = await vault.getTokenBalance(address, tokenAddress, '1');
1393
+ console.log('Token Balance:', ethers.formatUnits(tokenBalance, 18));
1394
+ ```
1395
+
1396
+ #### Get Token Info
1397
+ ```typescript
1398
+ // Get token information
1399
+ const tokenInfo = await vault.getTokenInfo(tokenAddress, '1');
1400
+ console.log('Token:', tokenInfo.name, '(', tokenInfo.symbol, ')');
1401
+ ```
1402
+
1403
+ ### Transaction Functions
1404
+
1405
+ #### Send Native Token
1406
+ ```typescript
1407
+ // Send native tokens (ETH, BNB, etc.)
1408
+ const tx = await vault.sendNativeToken(from, to, amount, '1');
1409
+ console.log('Transaction hash:', tx.hash);
1410
+ ```
1411
+
1412
+ #### Send Token
1413
+ ```typescript
1414
+ // Send ERC-20 tokens
1415
+ const tx = await vault.sendToken(from, to, amount, tokenAddress, '1');
1416
+ console.log('Transaction hash:', tx.hash);
1417
+ ```
1418
+
1419
+ #### Export Mnemonic
1420
+ ```typescript
1421
+ // Export the mnemonic phrase (requires password)
1422
+ const mnemonic = await vault.exportMnemonic(password);
1423
+ console.log('Mnemonic:', mnemonic);
1424
+ ```
1425
+
1426
+ ## Multi-Transfer Operations
1427
+
1428
+ ### Batch Send Native Tokens
1429
+ ```typescript
1430
+ import { MultiTransferService } from 'pwc-wallet-sdk';
1431
+
1432
+ const multiTransferService = new MultiTransferService(vault, chainService, '1'); // '1' là chainId cho Ethereum mainnet
1433
+ const recipients = [
1434
+ { address: '0x1111...', amount: '0.01' },
1435
+ { address: '0x2222...', amount: '0.02' },
1436
+ { address: '0x3333...', amount: '0.005' }
1437
+ ];
1438
+
1439
+ const result = await multiTransferService.transferNativeTokens(
1440
+ fromAddress,
1441
+ recipients,
1442
+ '1', // chainId
1443
+ { batchSize: 5, onProgress: (progress) => console.log('Progress:', progress) }
1444
+ );
1445
+
1446
+ console.log('Successful:', result.successfulCount);
1447
+ console.log('Failed:', result.failedCount);
1448
+ console.log('Total gas used:', result.totalGasUsed.toString());
1449
+ ```
1450
+
1451
+ ### Batch Send ERC-20 Tokens
1452
+ ```typescript
1453
+ const result = await multiTransferService.transferTokens(
1454
+ fromAddress,
1455
+ tokenAddress, // USDT, USDC, etc.
1456
+ recipients,
1457
+ '1', // chainId
1458
+ { batchSize: 10 }
1459
+ );
1460
+
1461
+ console.log('Token transfers completed:', result.successfulCount);
1462
+ ```
1463
+
1464
+ ## Configuration
1465
+
1466
+ ### ⚡️ Hybrid Configuration (Mobile App & SDK)
1467
+
1468
+ > **New in vX.X.X:** You can now override all important config (RPC, explorer, gas, network gas, feature flags, etc.) directly from your app code, not just via environment variables. This enables full control for mobile/web apps and advanced use cases.
1469
+
1470
+ #### How Hybrid Config Works
1471
+ - **Priority:**1*Mobile App Config** (passed to SDK at runtime)
1472
+ 2ironment Variables** (process.env)
1473
+ 3. **SDK Defaults** (hardcoded fallback)
1474
+
1475
+ #### VaultConfig Interface
1476
+ ```typescript
1477
+ import { Vault, type VaultConfig } from 'pwc-wallet-sdk';
1478
+
1479
+ const config: VaultConfig = [object Object] rpcUrls:[object Object] 1https://your-eth-rpc.com',
1480
+ 56:https://your-bsc-rpc.com, },
1481
+ explorerUrls:[object Object]1https://etherscan.io',
1482
+ 56: 'https://bscscan.com',
1483
+ },
1484
+ gasConfig:[object Object] ERC20_TRANSFER:700,
1485
+ NATIVE_TRANSFER: 2200,
1486
+ BATCH_MULTIPLIER: 12
1487
+ DEFAULT_PRIORITY_FEE: 200
1488
+ },
1489
+ networkGasConfig: {
1490
+ 1: { maxFeePerGas:400000000 maxPriorityFeePerGas: 150000},
1491
+ 56: { maxFeePerGas: 30000000 maxPriorityFeePerGas: 500 },
1492
+ },
1493
+ defaultChainId: '1
1494
+ features: [object Object]
1495
+ enableEIP1559: true,
1496
+ enableBatchProcessing: true,
1497
+ }
1498
+ };
1499
+ ```
1500
+
1501
+ #### Usage Example (Recommended for Mobile Apps)
1502
+ ```typescript
1503
+ import { Vault, type VaultConfig } from 'pwc-wallet-sdk;// Define your app config once
1504
+ const appConfig: VaultConfig =[object Object]
1505
+ rpcUrls: { 1https://your-eth-rpc.com' },
1506
+ gasConfig: { ERC20RANSFER: 7000 networkGasConfig: { '1: { maxFeePerGas: 400000n } },
1507
+ };
1508
+
1509
+ // Pass config when creating new vault
1510
+ const [object Object] vault, encryptedVault } = await Vault.createNew(password', 'evm, appConfig);
1511
+
1512
+ // Pass config when loading existing vault
1513
+ const vault = await Vault.load('password, encryptedVault, appConfig);
1514
+
1515
+ // All operations will use the config automatically
1516
+ await vault.sendToken(from, to, amount, tokenAddress, '1');
1517
+ ```
1518
+
1519
+ #### Alternative: Global Config (Advanced)
1520
+ You can also set config globally for all vaults:
1521
+ ```typescript
1522
+ import { setGlobalRPCConfig, setGlobalGasConfig, setGlobalNetworkGasConfig } from 'pwc-wallet-sdk';
1523
+
1524
+ setGlobalRPCConfig([object Object]1:https://my-eth-rpc.com });setGlobalGasConfig({ ERC20ANSFER: 70;
1525
+ setGlobalNetworkGasConfig({ '1: { maxFeePerGas: 4000 });
1526
+ ```
1527
+
1528
+ #### Why Use Hybrid Config?
1529
+ - **Security:** Use your own RPC endpoints, not public ones
1530
+ - **Performance:** Optimize gas and network for your users
1531
+ - **Flexibility:** Switch between testnet/mainnet, or use custom chains
1532
+ - **Mobile/Web Ready:** No need to rely on process.env in mobile/web
1533
+ - **Simple:** Just pass config when creating/loading vault - no need to call global functions repeatedly
1534
+
1535
+ ### Built-in Chains
1536
+ The SDK supports multiple blockchain networks out of the box:
1537
+
1538
+ ```typescript
1539
+ import { SUPPORTED_CHAINS } from 'pwc-wallet-sdk';
1540
+
1541
+ // View all supported chains
1542
+ Object.entries(SUPPORTED_CHAINS).forEach(([chainId, config]) => {
1543
+ console.log(`${chainId}: ${config.name} (${config.type})`);
1544
+ });
1545
+ ```
1546
+
1547
+ ### Custom Chain Management
1548
+
1549
+ #### Override Built-in Chains
1550
+ ```typescript
1551
+ import { overrideChain } from 'pwc-wallet-sdk';
1552
+
1553
+ // Override Ethereum RPC URL
1554
+ overrideChain('1', {
1555
+ rpcUrl: 'https://my-eth-rpc.com'
1556
+ });
1557
+ ```
1558
+
1559
+ #### Add Custom Chains
1560
+ ```typescript
1561
+ import { registerCustomChain } from 'pwc-wallet-sdk';
1562
+
1563
+ registerCustomChain('custom-1', {
1564
+ name: 'My Custom Chain',
1565
+ rpcUrl: 'https://my-custom-rpc.com',
1566
+ explorerUrl: 'https://my-explorer.com',
1567
+ nativeCurrency: { name: 'Token', symbol: 'TKN', decimals: 18 },
1568
+ type: 'evm'
1569
+ });
1570
+ ```
1571
+
1572
+ #### Setup All Chains at Once
1573
+ ```typescript
1574
+ import { setupChainConfigs } from 'pwc-wallet-sdk';
1575
+
1576
+ setupChainConfigs({
1577
+ overrides: {
1578
+ '1': { rpcUrl: 'https://my-eth-rpc.com' },
1579
+ '56': { rpcUrl: 'https://my-bsc-rpc.com' }
1580
+ },
1581
+ customChains: {
1582
+ 'custom-1': {
1583
+ name: 'My Chain',
1584
+ rpcUrl: 'https://my-rpc.com',
1585
+ explorerUrl: 'https://my-explorer.com',
1586
+ nativeCurrency: { name: 'Token', symbol: 'TKN', decimals: 18 },
1587
+ type: 'evm'
1588
+ }
1589
+ }
1590
+ });
1591
+ ```
1592
+
1593
+ #### Chain Configuration Priority
1594
+ 1. **Custom chains** (highest priority)
1595
+ 2. **Overrides** (modify built-in chains)
1596
+ 3. **Built-in chains** (default configuration)
1597
+
1598
+ ### Utility Functions
1599
+ ```typescript
1600
+ import {
1601
+ getChainConfig,
1602
+ getAllAvailableChains,
1603
+ clearCustomChains,
1604
+ clearOverrides
1605
+ } from 'pwc-wallet-sdk';
1606
+
1607
+ // Get chain configuration
1608
+ const config = getChainConfig('1');
1609
+
1610
+ // Get all available chains
1611
+ const allChains = getAllAvailableChains();
1612
+
1613
+ // Clear custom configurations
1614
+ clearCustomChains();
1615
+ clearOverrides();
1616
+ ```
1617
+
1618
+ ### Vanity Wallet Settings
1619
+ ```typescript
1620
+ import { VANITY_WALLET_CONFIG } from 'pwc-wallet-sdk';
1621
+
1622
+ // Default settings
1623
+ console.log(VANITY_WALLET_CONFIG.DEFAULT_PREFIX); // 'aaa'
1624
+ console.log(VANITY_WALLET_CONFIG.DEFAULT_MAX_ATTEMPTS); // 1000000
1625
+ console.log(VANITY_WALLET_CONFIG.DEFAULT_CASE_SENSITIVE); // false
1626
+ ```
1627
+
1628
+ ### Supported Chains
1629
+ ```typescript
1630
+ import { SUPPORTED_CHAINS } from 'pwc-wallet-sdk';
1631
+
1632
+ // View all supported chains
1633
+ Object.entries(SUPPORTED_CHAINS).forEach(([chainId, config]) => {
1634
+ console.log(`${chainId}: ${config.name} (${config.type})`);
1635
+ });
1636
+ ```
1637
+
1638
+ ## Advanced Features
1639
+
1640
+ ### Gas Estimation
1641
+
1642
+ ### Estimate Native Transfer Gas
1643
+ ```typescript
1644
+ const gasEstimate = await vault.estimateNativeTransferGas(
1645
+ fromAddress,
1646
+ toAddress,
1647
+ amount,
1648
+ '1'
1649
+ );
1650
+ console.log('Estimated gas:', gasEstimate.toString());
1651
+ console.log('Estimated cost (in ETH):', ethers.formatEther(gasEstimate * gasPrice));
1652
+ ```
1653
+
1654
+ ### Estimate Token Transfer Gas
1655
+ ```typescript
1656
+ const gasEstimate = await vault.estimateTokenTransferGas(
1657
+ fromAddress,
1658
+ tokenAddress,
1659
+ toAddress,
1660
+ amount,
1661
+ '1'
1662
+ );
1663
+ console.log('Estimated gas for token transfer:', gasEstimate.toString());
1664
+ ```
1665
+
1666
+ ### Estimate Multi-Transfer Gas
1667
+ ```typescript
1668
+ const recipients = [
1669
+ { address: '0x1111...', amount: '0.01' },
1670
+ { address: '0x2222...', amount: '0.02' },
1671
+ { address: '0x3333...', amount: '0.005' }
1672
+ ];
1673
+
1674
+ // Estimate for native token multi-transfer
1675
+ const nativeGasEstimate = await multiTransferService.estimateGasCost(
1676
+ recipients,
1677
+ '1', // chainId
1678
+ true // Native tokens
1679
+ );
1680
+
1681
+ // Estimate for token multi-transfer
1682
+ const tokenGasEstimate = await multiTransferService.estimateGasCost(
1683
+ recipients,
1684
+ '1', // chainId
1685
+ false, // ERC-20 tokens
1686
+ tokenAddress // USDC
1687
+ );
1688
+
1689
+ console.log('Native multi-transfer gas:', nativeGasEstimate.toString());
1690
+ console.log('Token multi-transfer gas:', tokenGasEstimate.toString());
1691
+ ```
1692
+
1693
+ ### Estimate NFT Transfer Gas
1694
+ ```typescript
1695
+ import { NFTService } from 'pwc-wallet-sdk';
1696
+
1697
+ const nftService = new NFTService('1'); // Ethereum mainnet
1698
+
1699
+ // Estimate gas for ERC-721 transfer
1700
+ const erc721Gas = await nftService.estimateGasForTransfer(
1701
+ '0xSender...',
1702
+ '0xRecipient...',
1703
+ '0xContract...',
1704
+ '123'
1705
+ );
1706
+
1707
+ // Estimate gas for ERC-1155 transfer
1708
+ const erc1155Gas = await nftService.estimateGasForTransfer(
1709
+ '0xSender...',
1710
+ '0xRecipient...',
1711
+ '0xContract...',
1712
+ '123',
1713
+ '5' // transfer 5 ERC-1155 NFTs
1714
+ );
1715
+
1716
+ // Estimate gas for ERC-721 approve
1717
+ const approveGas = await nftService.estimateGas('approve', '0xContract...', {
1718
+ toAddress: '0xSpender...',
1719
+ tokenId: '123'
1720
+ });
1721
+
1722
+ console.log('ERC-721 transfer gas:', erc721Gas.toString());
1723
+ console.log('ERC-1155 transfer gas:', erc1155Gas.toString());
1724
+ console.log('ERC-721 approve gas:', approveGas.toString());
1725
+ ```
1726
+
1727
+ ### ERC-1155 Gas Estimation Notes
1728
+ For ERC-1155 tokens, gas estimation requires the sender's private key to pass the "caller is not owner nor approved" check. The SDK uses the vault to securely access the private key:
1729
+
1730
+ ```typescript
1731
+ // With vault (recommended) - accurate gas estimation
1732
+ const nftService = new NFTService('1', vault);
1733
+ const gasEstimate = await nftService.estimateGasForTransfer(
1734
+ '0xSender...',
1735
+ '0xRecipient...',
1736
+ '0xERC1155Contract...',
1737
+ '123',
1738
+ '5' // amount
1739
+ );
1740
+
1741
+ // Without vault - returns conservative estimate
1742
+ const nftService = new NFTService('1');
1743
+ const gasEstimate = await nftService.estimateGasForTransfer(
1744
+ '0xSender...',
1745
+ '0xRecipient...',
1746
+ '0xERC1155Contract...',
1747
+ '123'
1748
+ );
1749
+ // Returns ~65,000 gas (conservative estimate)
1750
+ ```
1751
+
1752
+ **Why use vault?** The vault securely manages private keys and provides them only when needed for gas estimation, ensuring your private keys are never exposed in plain text.
1753
+
1754
+ ### Check ERC-1155 Transfer Permissions
1755
+ Check if an address can transfer an ERC-1155 token:
1756
+
1757
+ ```typescript
1758
+ const canTransfer = await nftService.canTransferERC1155(
1759
+ '0xAddress...',
1760
+ '0xERC1155Contract...',
1761
+ '123' // token ID
1762
+ );
1763
+
1764
+ if (canTransfer) {
1765
+ console.log('Address can transfer this token');
1766
+ } else {
1767
+ console.log('Address cannot transfer this token (not owner or approved)');
1768
+ }
1769
+ ```
1770
+
1771
+ ## Security Considerations
1772
+
1773
+ - **Password Strength**: Use strong passwords for vault encryption
1774
+ - **Private Key Storage**: Private keys are never stored in plain text
1775
+ - **Memory Safety**: Sensitive data is cleared from memory when possible
1776
+ - **Encryption**: All vault data is encrypted using AES-256
1777
+ - **Validation**: Input validation prevents common attack vectors
1778
+
1779
+ ## Error Handling
1780
+
1781
+ ```typescript
1782
+ try {
1783
+ const vault = await Vault.load(password, encryptedVault);
1784
+ await vault.sendToken(from, to, amount, tokenAddress, '1');
1785
+ } catch (error) {
1786
+ if (error.message.includes('incorrect password')) {
1787
+ // Handle password error
1788
+ } else if (error.message.includes('insufficient balance')) {
1789
+ // Handle balance error
1790
+ } else {
1791
+ // Handle other errors
1792
+ }
1793
+ }
1794
+ ```
1795
+
1796
+ ## Contributing
1797
+
1798
+ 1. Fork the repository
1799
+ 2. Create a feature branch
1800
+ 3. Make your changes
1801
+ 4. Add tests
1802
+ 5. Submit a pull request
1803
+
1804
+ ## License
1805
+
1806
+ MIT License - see LICENSE file for details.
1807
+
1808
+ ## 🔥 New API: Simple chainId-based usage
1809
+
1810
+ All read-only and write operations now only require `chainId`, `address`, `token`, ...
1811
+ No need to manage or pass provider from your app. The SDK manages providers internally.
1812
+
1813
+ ### Example: Get native balance
1814
+ ```ts
1815
+ import { getNativeBalance } from 'pwc-wallet-sdk';
1816
+ const balance = await getNativeBalance('0x123...', '1'); // Ethereum mainnet
1817
+ ```
1818
+
1819
+ ### Example: Get ERC-20 token balance
1820
+ ```ts
1821
+ import { getTokenBalance } from 'pwc-wallet-sdk';
1822
+ const balance = await getTokenBalance('0xToken...', '0x123...', '1');
1823
+ ```
1824
+
1825
+ ### Example: MultiTransfer
1826
+ ```ts
1827
+ import { MultiTransferService } from 'pwc-wallet-sdk';
1828
+ const service = new MultiTransferService(vault, chainService, '1'); // truyền chainId rõ ràng
1829
+ await service.transferNativeTokens('0x123...', [{ address: '0xabc...', amount: '0.1' }], '1');
1830
+ ```
1831
+
1832
+ ### Example: NFTService
1833
+ ```ts
1834
+ import { NFTService } from 'pwc-wallet-sdk';
1835
+
1836
+ // Read-only operations
1837
+ const nftService = new NFTService('1'); // chainId = '1' for Ethereum
1838
+ const nftDetail = await nftService.getNFTDetail('0xContract...', '123');
1839
+
1840
+ // Write operations (transfer)
1841
+ const nftService = new NFTService('1', vault, fromAddress);
1842
+ await nftService.transferNFTWithVault(fromAddress, toAddress, contractAddress, tokenId);
1843
+
1844
+ // Estimate gas for NFT operations
1845
+ const transferGas = await nftService.estimateGasForTransfer(
1846
+ fromAddress,
1847
+ toAddress,
1848
+ contractAddress,
1849
+ tokenId
1850
+ );
1851
+ const approveGas = await nftService.estimateGas('approve', contractAddress, {
1852
+ toAddress: '0xSpender...',
1853
+ tokenId: tokenId
1854
+ });
1855
+ console.log('NFT transfer gas:', transferGas.toString());
1856
+ console.log('NFT approve gas:', approveGas.toString());
1857
+ ```
1858
+
1859
+ ## Advanced: Override RPC URLs
1860
+ You can override RPC URLs for any chain via config if needed.
1861
+
1862
+ ### 📱 QR Code Functionality
1863
+
1864
+ #### Generate Address QR
1865
+ Generates QR code data for a wallet address.
1866
+
1867
+ **Parameters:**
1868
+ - `address` - The wallet address to encode
1869
+ - `label` - Optional label for the address
1870
+
1871
+ ```typescript
1872
+ import { QRCodeService } from 'pwc-wallet-sdk';
1873
+
1874
+ // Generate QR for any address
1875
+ const qrData = QRCodeService.generateAddressQR('0x1234...', 'My Wallet');
1876
+
1877
+ // Generate QR from Vault account
1878
+ const qrData = QRCodeService.generateAddressQRFromVault(vault, 0, 'My Wallet');
1879
+ ```
1880
+
1881
+ #### Generate Mnemonic QR
1882
+ Generates encrypted QR code data for mnemonic backup.
1883
+
1884
+ **Parameters:**
1885
+ - `mnemonic` - The mnemonic phrase to encrypt
1886
+ - `password` - Password for encryption
1887
+ - `chainType` - Type of blockchain (evm, solana, etc.) - defaults to 'evm'
1888
+ - `accountCount` - Number of accounts to import - defaults to 1
1889
+
1890
+ ```typescript
1891
+ import { QRCodeService } from 'pwc-wallet-sdk';
1892
+
1893
+ // Generate QR for mnemonic
1894
+ const qrData = await QRCodeService.generateMnemonicQR(
1895
+ 'abandon abandon abandon...',
1896
+ 'my-password',
1897
+ 'evm',
1898
+ 3
1899
+ );
1900
+
1901
+ // Generate QR from Vault
1902
+ const qrData = await QRCodeService.generateMnemonicQRFromVault(
1903
+ vault,
1904
+ 'my-password',
1905
+ 3
1906
+ );
1907
+ ```
1908
+
1909
+ #### Generate Transaction QR
1910
+ Generates QR code data for transaction signing.
1911
+
1912
+ **Parameters:**
1913
+ - `transactionData` - Transaction details object with required fields:
1914
+ - `txType` - 'native', 'token', or 'nft'
1915
+ - `chainId` - Chain ID (e.g., '1' for Ethereum mainnet)
1916
+ - `to` - Recipient address
1917
+ - `amount` - Amount to send
1918
+ - `tokenAddress` - Optional: Token contract address (for token transfers)
1919
+ - `tokenId` - Optional: Token ID (for NFT transfers)
1920
+ - `gasLimit` - Optional: Gas limit
1921
+ - `gasPrice` - Optional: Gas price
1922
+
1923
+ ```typescript
1924
+ import { QRCodeService } from 'pwc-wallet-sdk';
1925
+
1926
+ // Native token transfer
1927
+ const nativeTxData = {
1928
+ txType: 'native',
1929
+ chainId: '1',
1930
+ to: '0x1234...',
1931
+ amount: '0.1',
1932
+ gasLimit: '21000'
1933
+ };
1934
+
1935
+ // ERC-20 token transfer
1936
+ const tokenTxData = {
1937
+ txType: 'token',
1938
+ chainId: '1',
1939
+ to: '0x1234...',
1940
+ amount: '100',
1941
+ tokenAddress: '0xA0b86a33E6441b8c4C8C8C8C8C8C8C8C8C8C8C8C8',
1942
+ gasLimit: '65000'
1943
+ };
1944
+
1945
+ const qrData = QRCodeService.generateTransactionQR(nativeTxData);
1946
+ ```
1947
+
1948
+ #### Parse and Extract QR Data
1949
+ Parse QR code data and extract specific information.
1950
+
1951
+ ```typescript
1952
+ import { QRCodeService } from 'pwc-wallet-sdk';
1953
+
1954
+ // Parse any QR code
1955
+ const qrData = QRCodeService.parseQRData(qrString);
1956
+
1957
+ // Extract specific data types
1958
+ const address = QRCodeService.extractAddress(qrString);
1959
+ const walletData = QRCodeService.extractWalletImportData(qrString);
1960
+ const txData = QRCodeService.extractTransactionData(qrString);
1961
+
1962
+ // Validate address types
1963
+ const addressType = QRCodeService.getAddressType('0x1234...'); // 'ethereum'
1964
+ const isValidEth = QRCodeService.isValidEthereumAddress('0x1234...');
1965
+ const isValidSol = QRCodeService.isValidSolanaAddress('ABC123...');
1966
+ ```
1967
+
1968
+ #### Import Wallet from QR
1969
+ Imports wallet from QR code data (requires Vault).
1970
+
1971
+ **Parameters:**
1972
+ - `qrString` - QR code string to parse
1973
+ - `password` - Password to decrypt the mnemonic
1974
+
1975
+ ```typescript
1976
+ // Import wallet from scanned QR code
1977
+ const accounts = await vault.importFromQR(qrString, 'my-password');
1978
+ console.log('Imported accounts:', accounts);
1979
+ ```
1980
+
1981
+ #### Process Transaction from QR
1982
+ Processes transaction from QR code data (requires Vault).
1983
+
1984
+ **Parameters:**
1985
+ - `qrString` - QR code string to parse
1986
+ - `fromAddress` - Sender's address
1987
+
1988
+ ```typescript
1989
+ // Process transaction from scanned QR code
1990
+ const result = await vault.processTransactionFromQR(qrString, '0x1234...');
1991
+ console.log('Transaction hash:', result.hash);
1992
+ ```
1993
+
1994
+ #### Validate QR Code
1995
+ Validates QR code data without processing it.
1996
+
1997
+ **Parameters:**
1998
+ - `qrString` - QR code string to validate
1999
+
2000
+ **Returns:**
2001
+ - `isValid` - Boolean indicating if QR is valid
2002
+ - `type` - Type of QR code ('address', 'wallet-import', 'transaction', or 'unknown')
2003
+ - `data` - Parsed data if valid, null if invalid
2004
+
2005
+ ```typescript
2006
+ import { QRCodeService } from 'pwc-wallet-sdk';
2007
+
2008
+ // Validate QR code before processing
2009
+ const validation = QRCodeService.validateQRCode(qrString);
2010
+ console.log('QR type:', validation.type);
2011
+ console.log('Is valid:', validation.isValid);
2012
+ if (validation.isValid) {
2013
+ console.log('QR data:', validation.data);
2014
+ }
2015
+ ```
2016
+
2017
+ ### Multi-Transfer (Batch Send) - Simple Usage
2018
+ ```typescript
2019
+ import { MultiTransferService } from 'pwc-wallet-sdk';
2020
+
2021
+ // Create the service easily (no need to handle privateKey or chainService)
2022
+ const multiTransferService = await MultiTransferService.fromVault(vault, fromAddress, '1');
2023
+
2024
+ // Batch send native tokens
2025
+ const recipients = [
2026
+ { address: '0x1111...', amount: '0.01' },
2027
+ { address: '0x2222...', amount: '0.02' }
2028
+ ];
2029
+ const result = await multiTransferService.transferNativeTokens(
2030
+ fromAddress,
2031
+ recipients,
2032
+ '1',
2033
+ { batchSize: 2, onProgress: (completed, total, txHash) => console.log(completed, total, txHash) }
2034
+ );
2035
+ console.log('Batch result:', result);
2036
+
2037
+ // Batch send ERC-20 tokens
2038
+ const tokenResult = await multiTransferService.transferTokens(
2039
+ fromAddress,
2040
+ '0xTokenContractAddress...',
2041
+ recipients,
2042
+ '1',
2043
+ { batchSize: 2 }
2044
+ );
2045
+ console.log('Token batch result:', tokenResult);
2046
+ ```
2047
+
2048
+ #### Generate EIP-681 Compatible Address QR (for Metamask, Binance, Trust Wallet)
2049
+ Generates a QR code string in EIP-681 format, which is compatible with most popular wallets.
2050
+
2051
+ **Parameters:**
2052
+ - `address` - The wallet address to encode
2053
+
2054
+ ```typescript
2055
+ import { QRCodeService } from 'pwc-wallet-sdk';
2056
+
2057
+ // Generate EIP-681 QR string (recommended for wallet compatibility)
2058
+ const qrString = QRCodeService.generateEIP681AddressQR('0x1234abcd...');
2059
+ // Pass this string to your QR code generator (e.g., react-native-qrcode-svg, qrcode.react, etc.)
2060
+ ```
2061
+
2062
+ > **Tip:** Use this format if you want users to scan your QR code with Metamask, Binance, Trust Wallet, or other EVM wallets. If you use the default generateAddressQR, it will only work with your own app.