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
@@ -0,0 +1,252 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MultiTransferService = void 0;
4
+ const ChainService_1 = require("../chain/ChainService");
5
+ const SolanaChainService_1 = require("../chain/SolanaChainService");
6
+ const BatchProcessor_1 = require("./BatchProcessor");
7
+ const ethers_1 = require("ethers");
8
+ const gas_1 = require("../config/gas");
9
+ const TokenUtils_1 = require("./TokenUtils");
10
+ const chains_1 = require("../config/chains");
11
+ /**
12
+ * Service for handling multi-transfer operations across different blockchain networks.
13
+ * Supports both native tokens and ERC-20/SPL tokens with batch processing and progress tracking.
14
+ */
15
+ class MultiTransferService {
16
+ /**
17
+ * Creates a new MultiTransferService instance.
18
+ * @param vault - The vault instance containing the accounts
19
+ * @param chainService - The chain service for the target blockchain
20
+ * @param chainId - The chain ID for all operations
21
+ */
22
+ constructor(vault, chainService, chainId) {
23
+ this.vault = vault;
24
+ this.chainService = chainService;
25
+ this.chainId = chainId;
26
+ }
27
+ /**
28
+ * Transfers native tokens to multiple recipients.
29
+ * @param fromAddress - The sender's address
30
+ * @param recipients - Array of recipients with addresses and amounts
31
+ * @param chainId - The chain ID for the transfer
32
+ * @param options - Optional configuration for the transfer operation
33
+ * @returns Promise resolving to the multi-transfer result
34
+ * @throws Error if validation fails or insufficient balance
35
+ */
36
+ async transferNativeTokens(fromAddress, recipients, chainId, options = {}) {
37
+ // Validate inputs
38
+ const validation = this.validateTransferInputs(fromAddress, recipients, options);
39
+ if (!validation.isValid) {
40
+ throw new Error(`Validation failed: ${validation.errors.join(', ')}`);
41
+ }
42
+ // Check balance
43
+ await this.checkBalance(fromAddress, validation.totalAmount, true, undefined, chainId);
44
+ // Process transfers
45
+ const batchSize = options.batchSize || 10;
46
+ const batches = BatchProcessor_1.BatchProcessor.splitIntoBatches(recipients, batchSize);
47
+ const allSuccessful = [];
48
+ const allFailed = [];
49
+ let totalGasUsed = BigInt(0);
50
+ for (let batchIndex = 0; batchIndex < batches.length; batchIndex++) {
51
+ const batch = batches[batchIndex];
52
+ const batchResult = await BatchProcessor_1.BatchProcessor.processNativeTokenBatch(this.chainService, batch, options.onProgress);
53
+ allSuccessful.push(...batchResult.transactions);
54
+ allFailed.push(...batchResult.failed);
55
+ totalGasUsed += batchResult.gasUsed;
56
+ // Small delay between batches
57
+ if (batchIndex < batches.length - 1) {
58
+ await new Promise(resolve => setTimeout(resolve, 500));
59
+ }
60
+ }
61
+ return {
62
+ successful: allSuccessful,
63
+ failed: allFailed,
64
+ totalGasUsed,
65
+ totalAmount: validation.totalAmount,
66
+ totalRecipients: recipients.length,
67
+ successfulCount: allSuccessful.length,
68
+ failedCount: allFailed.length
69
+ };
70
+ }
71
+ /**
72
+ * Transfers ERC-20/SPL tokens to multiple recipients.
73
+ * @param fromAddress - The sender's address
74
+ * @param tokenAddress - The token contract address
75
+ * @param recipients - Array of recipients with addresses and amounts
76
+ * @param chainId - The chain ID for the transfer
77
+ * @param options - Optional configuration for the transfer operation
78
+ * @returns Promise resolving to the multi-transfer result
79
+ * @throws Error if validation fails or insufficient balance
80
+ */
81
+ async transferTokens(fromAddress, tokenAddress, recipients, chainId, options = {}) {
82
+ // Validate inputs
83
+ const validation = this.validateTransferInputs(fromAddress, recipients, options);
84
+ if (!validation.isValid) {
85
+ throw new Error(`Validation failed: ${validation.errors.join(', ')}`);
86
+ }
87
+ // Check token balance
88
+ await this.checkBalance(fromAddress, validation.totalAmount, false, tokenAddress, chainId);
89
+ // Process transfers
90
+ const batchSize = options.batchSize || 10;
91
+ const batches = BatchProcessor_1.BatchProcessor.splitIntoBatches(recipients, batchSize);
92
+ const allSuccessful = [];
93
+ const allFailed = [];
94
+ let totalGasUsed = BigInt(0);
95
+ for (let batchIndex = 0; batchIndex < batches.length; batchIndex++) {
96
+ const batch = batches[batchIndex];
97
+ const batchResult = await BatchProcessor_1.BatchProcessor.processTokenBatch(this.chainService, tokenAddress, batch, options.onProgress);
98
+ allSuccessful.push(...batchResult.transactions);
99
+ allFailed.push(...batchResult.failed);
100
+ totalGasUsed += batchResult.gasUsed;
101
+ // Small delay between batches
102
+ if (batchIndex < batches.length - 1) {
103
+ await new Promise(resolve => setTimeout(resolve, 500));
104
+ }
105
+ }
106
+ return {
107
+ successful: allSuccessful,
108
+ failed: allFailed,
109
+ totalGasUsed,
110
+ totalAmount: validation.totalAmount,
111
+ totalRecipients: recipients.length,
112
+ successfulCount: allSuccessful.length,
113
+ failedCount: allFailed.length
114
+ };
115
+ }
116
+ /**
117
+ * Validates transfer inputs including recipients and amounts.
118
+ * @param fromAddress - The sender's address
119
+ * @param recipients - Array of recipients to validate
120
+ * @param options - Transfer options
121
+ * @returns Validation result with errors and total amount
122
+ */
123
+ validateTransferInputs(fromAddress, recipients, options) {
124
+ const errors = [];
125
+ // Validate sender address
126
+ if (!fromAddress || fromAddress.trim() === '') {
127
+ errors.push('Invalid sender address');
128
+ }
129
+ // Validate recipients
130
+ const recipientValidation = BatchProcessor_1.BatchProcessor.validateRecipients(recipients);
131
+ if (!recipientValidation.isValid) {
132
+ errors.push(...recipientValidation.errors);
133
+ }
134
+ // Validate batch size
135
+ if (options.batchSize && (options.batchSize < 1 || options.batchSize > 50)) {
136
+ errors.push('Batch size must be between 1 and 50');
137
+ }
138
+ // Calculate total amount
139
+ let totalAmount = '0';
140
+ if (recipients.length > 0) {
141
+ const total = recipients.reduce((sum, recipient) => {
142
+ return sum + parseFloat(recipient.amount);
143
+ }, 0);
144
+ totalAmount = total.toString();
145
+ }
146
+ return {
147
+ isValid: errors.length === 0,
148
+ errors,
149
+ totalAmount
150
+ };
151
+ }
152
+ /**
153
+ * Checks if the account has sufficient balance for the transfer.
154
+ * @param address - The account address to check
155
+ * @param amount - The amount to transfer
156
+ * @param isNative - Whether checking native token balance
157
+ * @param tokenAddress - Token address (for non-native tokens)
158
+ * @param chainId - The chain ID for the check
159
+ * @throws Error if insufficient balance
160
+ */
161
+ async checkBalance(address, amount, isNative, tokenAddress, chainId) {
162
+ let balance;
163
+ let amountWei;
164
+ const useChainId = chainId || this.chainId;
165
+ if (isNative) {
166
+ balance = await (0, TokenUtils_1.getNativeBalance)(address, useChainId);
167
+ amountWei = ethers_1.ethers.parseEther(amount);
168
+ }
169
+ else if (tokenAddress) {
170
+ balance = await (0, TokenUtils_1.getTokenBalance)(tokenAddress, address, useChainId);
171
+ // For token transfers, we need to get token decimals to parse amount correctly
172
+ // For now, we'll use a default of 18 decimals (most common)
173
+ // In a real implementation, you'd get this from the token contract
174
+ amountWei = ethers_1.ethers.parseUnits(amount, 18);
175
+ }
176
+ else {
177
+ throw new Error('Token address required for token balance check');
178
+ }
179
+ if (balance < amountWei) {
180
+ const balanceEth = isNative ? ethers_1.ethers.formatEther(balance) : ethers_1.ethers.formatUnits(balance, 18);
181
+ const amountEth = isNative ? ethers_1.ethers.formatEther(amountWei) : ethers_1.ethers.formatUnits(amountWei, 18);
182
+ throw new Error(`Insufficient balance. Available: ${balanceEth}, Required: ${amountEth}`);
183
+ }
184
+ }
185
+ /**
186
+ * Estimates gas cost for a multi-transfer operation.
187
+ * @param recipients - Array of recipients to estimate gas for
188
+ * @param chainId - The chain ID for the estimation
189
+ * @param isNative - Whether estimating for native tokens (default: true)
190
+ * @param tokenAddress - Token contract address (required for non-native tokens)
191
+ * @returns Promise resolving to estimated gas cost in wei
192
+ */
193
+ async estimateGasCost(recipients, chainId, isNative = true, tokenAddress) {
194
+ if (recipients.length === 0) {
195
+ return BigInt(0);
196
+ }
197
+ // Use first recipient for estimation
198
+ const sampleRecipient = recipients[0];
199
+ let estimatedGas;
200
+ try {
201
+ if (isNative) {
202
+ // Estimate native token transfer
203
+ const tx = {
204
+ to: sampleRecipient.address,
205
+ value: ethers_1.ethers.parseEther(sampleRecipient.amount)
206
+ };
207
+ if (this.chainService instanceof ChainService_1.ChainService) {
208
+ estimatedGas = await this.chainService.estimateGas(tx);
209
+ }
210
+ else {
211
+ // For Solana, estimate based on transaction fee
212
+ estimatedGas = await this.chainService.estimateTransactionFee();
213
+ }
214
+ }
215
+ else if (tokenAddress) {
216
+ // Use configuration constant instead of hardcoded value
217
+ estimatedGas = BigInt(gas_1.GAS_CONFIG.ERC20_TRANSFER);
218
+ }
219
+ else {
220
+ throw new Error('Token address required for token transfer gas estimation');
221
+ }
222
+ // Apply batch multiplier for multiple recipients
223
+ const totalGas = estimatedGas * BigInt(recipients.length);
224
+ const adjustedGas = totalGas * BigInt(Math.ceil(gas_1.GAS_CONFIG.BATCH_MULTIPLIER * 100)) / BigInt(100);
225
+ return adjustedGas;
226
+ }
227
+ catch (error) {
228
+ throw new Error(`Failed to estimate gas cost: ${error instanceof Error ? error.message : 'Unknown error'}`);
229
+ }
230
+ }
231
+ /**
232
+ * Factory method: Create MultiTransferService from vault, fromAddress, and chainId.
233
+ * Handles private key and chainService creation internally for simplicity.
234
+ * @param vault - The vault instance
235
+ * @param fromAddress - The sender's address
236
+ * @param chainId - The chain ID
237
+ * @returns Promise resolving to a MultiTransferService instance
238
+ */
239
+ static async fromVault(vault, fromAddress, chainId) {
240
+ const chainInfo = (0, chains_1.getChainConfig)(chainId);
241
+ const privateKey = await vault.getPrivateKeyFor(fromAddress);
242
+ let chainService;
243
+ if (chainInfo.type === 'solana') {
244
+ chainService = new SolanaChainService_1.SolanaChainService(privateKey, chainInfo);
245
+ }
246
+ else {
247
+ chainService = new ChainService_1.ChainService(privateKey, chainInfo);
248
+ }
249
+ return new MultiTransferService(vault, chainService, chainId);
250
+ }
251
+ }
252
+ exports.MultiTransferService = MultiTransferService;
@@ -0,0 +1,193 @@
1
+ import { EncryptedData } from '../crypto/EncryptionService';
2
+ /**
3
+ * Interface for QR code data structure
4
+ */
5
+ export interface QRCodeData {
6
+ /** Type of QR code data */
7
+ type: 'address' | 'mnemonic' | 'transaction' | 'wallet-import';
8
+ /** The actual data content */
9
+ data: any;
10
+ /** Timestamp when QR was generated */
11
+ timestamp: number;
12
+ /** Version for future compatibility */
13
+ version: string;
14
+ }
15
+ /**
16
+ * Interface for wallet import QR data
17
+ */
18
+ export interface WalletImportData {
19
+ /** Encrypted mnemonic data */
20
+ encryptedMnemonic: EncryptedData;
21
+ /** Chain type */
22
+ chainType: string;
23
+ /** Number of accounts to import */
24
+ accountCount: number;
25
+ }
26
+ /**
27
+ * Interface for transaction QR data
28
+ */
29
+ export interface TransactionData {
30
+ /** Transaction type */
31
+ txType: 'native' | 'token' | 'nft';
32
+ /** Chain ID */
33
+ chainId: string;
34
+ /** Recipient address */
35
+ to: string;
36
+ /** Amount to send */
37
+ amount: string;
38
+ /** Token contract address (for token transfers) */
39
+ tokenAddress?: string;
40
+ /** Token ID (for NFT transfers) */
41
+ tokenId?: string;
42
+ /** Gas limit */
43
+ gasLimit?: string;
44
+ /** Gas price */
45
+ gasPrice?: string;
46
+ }
47
+ /**
48
+ * Service for generating and scanning QR codes for wallet operations.
49
+ * Supports address sharing, mnemonic backup, and transaction signing.
50
+ */
51
+ export declare class QRCodeService {
52
+ private static readonly QR_VERSION;
53
+ /**
54
+ * Generates QR code data for a wallet address
55
+ * @param address - The wallet address to encode
56
+ * @param label - Optional label for the address
57
+ * @returns QR code data string
58
+ */
59
+ static generateAddressQR(address: string, label?: string): string;
60
+ /**
61
+ * Generates QR code data for encrypted mnemonic backup
62
+ * @param mnemonic - The mnemonic phrase to encrypt
63
+ * @param password - Password for encryption
64
+ * @param chainType - Type of blockchain (evm, solana, etc.)
65
+ * @param accountCount - Number of accounts to import
66
+ * @returns Promise resolving to QR code data string
67
+ * @throws Error if encryption fails
68
+ */
69
+ static generateMnemonicQR(mnemonic: string, password: string, chainType?: string, accountCount?: number): Promise<string>;
70
+ /**
71
+ * Generates QR code data for transaction signing
72
+ * @param transactionData - Transaction details
73
+ * @returns QR code data string
74
+ */
75
+ static generateTransactionQR(transactionData: TransactionData): string;
76
+ /**
77
+ * Parses QR code data and validates its structure
78
+ * @param qrString - The QR code string to parse
79
+ * @returns Parsed QR code data
80
+ * @throws Error if QR data is invalid or unsupported
81
+ */
82
+ static parseQRData(qrString: string): QRCodeData;
83
+ /**
84
+ * Extracts wallet address from QR code data
85
+ * @param qrString - The QR code string
86
+ * @returns The wallet address
87
+ * @throws Error if QR code doesn't contain address data
88
+ */
89
+ static extractAddress(qrString: string): string;
90
+ /**
91
+ * Extracts wallet import data from QR code
92
+ * @param qrString - The QR code string
93
+ * @returns Wallet import data
94
+ * @throws Error if QR code doesn't contain wallet import data
95
+ */
96
+ static extractWalletImportData(qrString: string): WalletImportData;
97
+ /**
98
+ * Extracts transaction data from QR code
99
+ * @param qrString - The QR code string
100
+ * @returns Transaction data
101
+ * @throws Error if QR code doesn't contain transaction data
102
+ */
103
+ static extractTransactionData(qrString: string): TransactionData;
104
+ /**
105
+ * Validates if a string is a valid Ethereum address
106
+ * @param address - Address to validate
107
+ * @returns True if valid Ethereum address
108
+ */
109
+ static isValidEthereumAddress(address: string): boolean;
110
+ /**
111
+ * Validates if a string is a valid Solana address
112
+ * @param address - Address to validate
113
+ * @returns True if valid Solana address
114
+ */
115
+ static isValidSolanaAddress(address: string): boolean;
116
+ /**
117
+ * Gets the address type based on format
118
+ * @param address - Address to check
119
+ * @returns 'ethereum', 'solana', or 'unknown'
120
+ */
121
+ static getAddressType(address: string): 'ethereum' | 'solana' | 'unknown';
122
+ /**
123
+ * Clears sensitive data from memory
124
+ * @param data - Sensitive data to clear
125
+ */
126
+ static clearSensitiveData(data: string): void;
127
+ /**
128
+ * Generates QR code data for a wallet address from Vault.
129
+ * Utility function to be used outside of Vault class.
130
+ * @param vault - The vault instance
131
+ * @param accountIndex - Index of the account to generate QR for (default: 0)
132
+ * @param label - Optional label for the address
133
+ * @returns QR code data string
134
+ * @throws Error if account index is invalid
135
+ *
136
+ * @example
137
+ * ```typescript
138
+ * import { QRCodeService, Vault } from 'pwc-wallet-sdk';
139
+ *
140
+ * // Generate QR for first account
141
+ * const qrData = QRCodeService.generateAddressQRFromVault(vault, 0, 'My Wallet');
142
+ * ```
143
+ */
144
+ static generateAddressQRFromVault(vault: any, accountIndex?: number, label?: string): string;
145
+ /**
146
+ * Generates QR code data for encrypted mnemonic backup from Vault.
147
+ * Utility function to be used outside of Vault class.
148
+ * @param vault - The vault instance
149
+ * @param password - Password for encryption
150
+ * @param accountCount - Number of accounts to import (default: 1)
151
+ * @returns Promise resolving to QR code data string
152
+ * @throws Error if encryption fails or no HD keyring available
153
+ *
154
+ * @example
155
+ * ```typescript
156
+ * import { QRCodeService, Vault } from 'pwc-wallet-sdk';
157
+ *
158
+ * // Generate backup QR with password
159
+ * const qrData = await QRCodeService.generateMnemonicQRFromVault(vault, 'my-secure-password', 3);
160
+ * ```
161
+ */
162
+ static generateMnemonicQRFromVault(vault: any, password: string, accountCount?: number): Promise<string>;
163
+ /**
164
+ * Validates QR code data without processing it.
165
+ * @param qrString - QR code string to validate
166
+ * @returns Object containing validation result and data type
167
+ *
168
+ * @example
169
+ * ```typescript
170
+ * // Validate QR code before processing
171
+ * const validation = QRCodeService.validateQRCode(qrString);
172
+ * console.log('QR type:', validation.type);
173
+ * console.log('Is valid:', validation.isValid);
174
+ * ```
175
+ */
176
+ static validateQRCode(qrString: string): {
177
+ isValid: boolean;
178
+ type: string;
179
+ data?: any;
180
+ };
181
+ /**
182
+ * Generates an EIP-681 compatible QR string for wallet address.
183
+ * This format is compatible with Metamask, Binance, Trust Wallet, etc.
184
+ * @param address - The wallet address to encode
185
+ * @returns EIP-681 URI string (e.g., 'ethereum:0x1234...')
186
+ * @example
187
+ * ```typescript
188
+ * const qrString = QRCodeService.generateEIP681AddressQR('0x1234...');
189
+ * // Use this string with a QR code generator for maximum wallet compatibility
190
+ * ```
191
+ */
192
+ static generateEIP681AddressQR(address: string): string;
193
+ }