@cryptforge/blockchain-evm 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +230 -0
- package/dist/index.d.mts +580 -0
- package/dist/index.d.ts +580 -0
- package/dist/index.js +1146 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1140 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +56 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/EVMAdapter.ts","../src/utils/formatBalance.ts","../src/providers/AlchemyProvider.ts","../src/providers/EtherscanProvider.ts","../src/chains/ethereum.ts","../src/chains/sonic.ts"],"names":["ethers"],"mappings":"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","file":"index.js","sourcesContent":["import { ethers } from \"ethers\";\nimport type {\n BlockchainAdapter,\n ChainData,\n KeyData,\n Transaction,\n TokenBalance,\n TokenTransfer,\n TransactionOptions,\n} from \"@cryptforge/core\";\nimport type { BlockchainDataProvider } from \"./providers/BlockchainDataProvider\";\n\n/**\n * Network configuration for a specific blockchain network (mainnet, testnet, etc.)\n */\nexport interface NetworkConfig {\n /** Network name (e.g., \"Ethereum Mainnet\", \"Sonic Testnet\") */\n name: string;\n /** RPC endpoint URL */\n rpcUrl: string;\n /** Block explorer URL (optional) */\n explorerUrl?: string;\n /** Chain ID for the network */\n chainId: number;\n}\n\n/**\n * Configuration options for EVM blockchain adapter\n */\nexport interface EVMAdapterConfig {\n /** Chain metadata (name, symbol, CMC ID) */\n chainData: ChainData;\n /** BIP44 coin type (default: 60 for Ethereum) */\n coinType?: number;\n /** Standard decimals for the chain's native token (default: 18) */\n standardDecimals?: number;\n /** Network configurations (mainnet, testnet, custom networks) */\n networks?: {\n mainnet?: NetworkConfig;\n testnet?: NetworkConfig;\n [key: string]: NetworkConfig | undefined;\n };\n /** Default network to use (default: 'mainnet') */\n defaultNetwork?: string;\n /** Optional data provider for fetching balances and transactions */\n dataProvider?: BlockchainDataProvider;\n /** BIP44 account index (default: 0) */\n account?: number;\n /** BIP44 change index (default: 0) */\n change?: number;\n /** BIP44 address index (default: 0) */\n addressIndex?: number;\n}\n\n/**\n * Configurable EVM blockchain adapter for CryptForge SDK.\n * Supports all EVM-compatible blockchains (Ethereum, Sonic, Polygon, BSC, etc.)\n * Uses ethers.js for key derivation and wallet operations.\n */\nexport class EVMAdapter implements BlockchainAdapter {\n public readonly chainData: ChainData;\n public readonly standardDecimals: number;\n private readonly coinType: number;\n private readonly account: number;\n private readonly change: number;\n private readonly addressIndex: number;\n private readonly networks: Record<string, NetworkConfig>;\n private currentNetworkKey: string;\n private dataProvider?: BlockchainDataProvider;\n\n /**\n * Create a new EVM blockchain adapter\n * @param config - Chain configuration\n */\n constructor(config: EVMAdapterConfig) {\n this.chainData = config.chainData;\n this.coinType = config.coinType ?? 60; // Standard Ethereum coin type\n this.standardDecimals = config.standardDecimals ?? 18; // Standard EVM decimals\n this.account = config.account ?? 0;\n this.change = config.change ?? 0;\n this.addressIndex = config.addressIndex ?? 0;\n\n // Filter out undefined values from networks\n this.networks = {};\n if (config.networks) {\n for (const [key, value] of Object.entries(config.networks)) {\n if (value !== undefined) {\n this.networks[key] = value;\n }\n }\n }\n\n this.currentNetworkKey = config.defaultNetwork ?? \"mainnet\";\n this.dataProvider = config.dataProvider;\n }\n\n /**\n * Get the BIP44 derivation path for this chain\n * @returns BIP44 path string (e.g., \"m/44'/60'/0'/0/0\")\n */\n private getDerivationPath(): string {\n return `m/44'/${this.coinType}'/${this.account}'/${this.change}/${this.addressIndex}`;\n }\n\n /**\n * Get the current network configuration\n * @returns Current network configuration, or undefined if no network is configured\n */\n public getNetwork(): NetworkConfig | undefined {\n return this.networks[this.currentNetworkKey];\n }\n\n /**\n * Get the current network key (e.g., 'mainnet', 'testnet')\n * @returns Current network key\n */\n public getCurrentNetworkKey(): string {\n return this.currentNetworkKey;\n }\n\n /**\n * Set the active network\n * @param networkKey - Network key to switch to (e.g., 'mainnet', 'testnet')\n * @throws Error if the network key doesn't exist\n */\n public setNetwork(networkKey: string): void {\n if (!this.networks[networkKey]) {\n throw new Error(\n `Network \"${networkKey}\" is not configured for ${this.chainData.name}. ` +\n `Available networks: ${Object.keys(this.networks).join(\", \")}`\n );\n }\n this.currentNetworkKey = networkKey;\n }\n\n /**\n * Get all available network keys\n * @returns Array of network keys (e.g., ['mainnet', 'testnet'])\n */\n public getAvailableNetworks(): string[] {\n return Object.keys(this.networks);\n }\n\n /**\n * Check if a network is configured\n * @param networkKey - Network key to check\n * @returns True if the network exists\n */\n public hasNetwork(networkKey: string): boolean {\n return networkKey in this.networks;\n }\n\n /**\n * Derive EVM keys from a BIP39 mnemonic.\n * Uses the BIP44 derivation path specified in the configuration.\n *\n * @param mnemonic - BIP39 mnemonic phrase\n * @returns KeyData with derived keys and address\n */\n public async deriveKeys(mnemonic: string): Promise<KeyData> {\n // Validate mnemonic\n if (!ethers.Mnemonic.isValidMnemonic(mnemonic)) {\n throw new Error(\"Invalid mnemonic phrase\");\n }\n\n // Get derivation path\n const path = this.getDerivationPath();\n\n // Create HD wallet from mnemonic\n const hdNode = ethers.HDNodeWallet.fromPhrase(mnemonic, undefined, path);\n\n // Get the private key (with 0x prefix)\n const privateKeyHex = hdNode.privateKey;\n\n // Remove 0x prefix and convert to Uint8Array\n const privateKeyBuffer = this.hexToBytes(privateKeyHex.slice(2));\n\n // Get public key (uncompressed, 65 bytes with 0x04 prefix)\n const publicKeyHex = hdNode.publicKey;\n const publicKeyBuffer = this.hexToBytes(publicKeyHex.slice(2));\n\n // Get EVM address (checksummed per EIP-55)\n const address = hdNode.address;\n\n // Get seed from mnemonic (for compatibility)\n const seed = this.hexToBytes(ethers.id(mnemonic).slice(2));\n\n return {\n mnemonic: mnemonic,\n seed: seed,\n privateKey: privateKeyBuffer,\n privateKeyHex: privateKeyHex.slice(2), // Without 0x prefix\n publicKey: publicKeyBuffer,\n publicKeyHex: publicKeyHex.slice(2), // Without 0x prefix\n address: address,\n path: path,\n };\n }\n\n /**\n * Derive keys at a specific address index\n * @param mnemonic - BIP39 mnemonic phrase\n * @param addressIndex - Address index in the BIP44 path\n * @returns KeyData with derived keys\n */\n public async deriveKeysAtIndex(\n mnemonic: string,\n addressIndex: number\n ): Promise<KeyData> {\n // Validate mnemonic\n if (!ethers.Mnemonic.isValidMnemonic(mnemonic)) {\n throw new Error(\"Invalid mnemonic phrase\");\n }\n\n // Build path with custom address index\n const path = `m/44'/${this.coinType}'/${this.account}'/${this.change}/${addressIndex}`;\n\n // Create HD wallet from mnemonic\n const hdNode = ethers.HDNodeWallet.fromPhrase(mnemonic, undefined, path);\n\n // Get the private key (with 0x prefix)\n const privateKeyHex = hdNode.privateKey;\n\n // Remove 0x prefix and convert to Uint8Array\n const privateKeyBuffer = this.hexToBytes(privateKeyHex.slice(2));\n\n // Get public key (uncompressed, 65 bytes with 0x04 prefix)\n const publicKeyHex = hdNode.publicKey;\n const publicKeyBuffer = this.hexToBytes(publicKeyHex.slice(2));\n\n // Get EVM address (checksummed per EIP-55)\n const address = hdNode.address;\n\n // Get seed from mnemonic (for compatibility)\n const seed = this.hexToBytes(ethers.id(mnemonic).slice(2));\n\n return {\n mnemonic: mnemonic,\n seed: seed,\n privateKey: privateKeyBuffer,\n privateKeyHex: privateKeyHex.slice(2), // Without 0x prefix\n publicKey: publicKeyBuffer,\n publicKeyHex: publicKeyHex.slice(2), // Without 0x prefix\n address: address,\n path: path,\n };\n }\n\n /**\n * Derive keys at a custom derivation path\n * @param mnemonic - BIP39 mnemonic phrase\n * @param path - Full BIP44 derivation path\n * @returns KeyData with derived keys\n */\n public async deriveKeysAtPath(\n mnemonic: string,\n path: string\n ): Promise<KeyData> {\n // Validate mnemonic\n if (!ethers.Mnemonic.isValidMnemonic(mnemonic)) {\n throw new Error(\"Invalid mnemonic phrase\");\n }\n\n // Create HD wallet from mnemonic\n const hdNode = ethers.HDNodeWallet.fromPhrase(mnemonic, undefined, path);\n\n // Get the private key (with 0x prefix)\n const privateKeyHex = hdNode.privateKey;\n\n // Remove 0x prefix and convert to Uint8Array\n const privateKeyBuffer = this.hexToBytes(privateKeyHex.slice(2));\n\n // Get public key (uncompressed, 65 bytes with 0x04 prefix)\n const publicKeyHex = hdNode.publicKey;\n const publicKeyBuffer = this.hexToBytes(publicKeyHex.slice(2));\n\n // Get EVM address (checksummed per EIP-55)\n const address = hdNode.address;\n\n // Get seed from mnemonic (for compatibility)\n const seed = this.hexToBytes(ethers.id(mnemonic).slice(2));\n\n return {\n mnemonic: mnemonic,\n seed: seed,\n privateKey: privateKeyBuffer,\n privateKeyHex: privateKeyHex.slice(2), // Without 0x prefix\n publicKey: publicKeyBuffer,\n publicKeyHex: publicKeyHex.slice(2), // Without 0x prefix\n address: address,\n path: path,\n };\n }\n\n /**\n * Get address at a specific index (read-only, no private key)\n * @param mnemonic - BIP39 mnemonic phrase\n * @param index - Address index\n * @returns Address and public key information\n */\n public async getAddressAtIndex(\n mnemonic: string,\n index: number\n ): Promise<{\n address: string;\n publicKey: string;\n path: string;\n }> {\n // Validate mnemonic\n if (!ethers.Mnemonic.isValidMnemonic(mnemonic)) {\n throw new Error(\"Invalid mnemonic phrase\");\n }\n\n // Build path with custom address index\n const path = `m/44'/${this.coinType}'/${this.account}'/${this.change}/${index}`;\n\n // Create HD wallet from mnemonic\n const hdNode = ethers.HDNodeWallet.fromPhrase(mnemonic, undefined, path);\n\n return {\n address: hdNode.address,\n publicKey: hdNode.publicKey.slice(2), // Without 0x prefix\n path: path,\n };\n }\n\n /**\n * Get multiple addresses starting from an index\n * @param mnemonic - BIP39 mnemonic phrase\n * @param startIndex - Starting address index\n * @param count - Number of addresses to generate\n * @returns Array of addresses with metadata\n */\n public async getAddresses(\n mnemonic: string,\n startIndex: number,\n count: number\n ): Promise<Array<{ address: string; path: string; index: number }>> {\n // Validate mnemonic\n if (!ethers.Mnemonic.isValidMnemonic(mnemonic)) {\n throw new Error(\"Invalid mnemonic phrase\");\n }\n\n const addresses: Array<{ address: string; path: string; index: number }> =\n [];\n\n for (let i = 0; i < count; i++) {\n const index = startIndex + i;\n const path = `m/44'/${this.coinType}'/${this.account}'/${this.change}/${index}`;\n\n // Create HD wallet from mnemonic\n const hdNode = ethers.HDNodeWallet.fromPhrase(mnemonic, undefined, path);\n\n addresses.push({\n address: hdNode.address,\n path: path,\n index: index,\n });\n }\n\n return addresses;\n }\n\n /**\n * Sign a message with a private key\n * @param privateKey - Private key as Uint8Array\n * @param message - Message to sign (string or Uint8Array)\n * @returns Signature\n */\n public async signMessage(\n privateKey: Uint8Array,\n message: string | Uint8Array\n ): Promise<{\n signature: string;\n }> {\n // Convert Uint8Array to hex string with 0x prefix\n const privateKeyHex = \"0x\" + this.bytesToHex(privateKey);\n\n // Create wallet from private key\n const wallet = new ethers.Wallet(privateKeyHex);\n\n // Convert message to string if it's Uint8Array\n const messageStr =\n typeof message === \"string\" ? message : new TextDecoder().decode(message);\n\n // Sign the message\n const signature = await wallet.signMessage(messageStr);\n\n return { signature };\n }\n\n /**\n * Sign a transaction with a private key\n * @param privateKey - Private key as Uint8Array\n * @param transaction - Chain-specific transaction object\n * @returns Signed transaction and signature\n */\n public async signTransaction(\n privateKey: Uint8Array,\n transaction: any\n ): Promise<{\n signedTransaction: any;\n signature: string;\n }> {\n // Convert Uint8Array to hex string with 0x prefix\n const privateKeyHex = \"0x\" + this.bytesToHex(privateKey);\n\n // Create wallet from private key\n const wallet = new ethers.Wallet(privateKeyHex);\n\n // Sign the transaction\n const signedTransaction = await wallet.signTransaction(transaction);\n\n // Extract signature from signed transaction\n const tx = ethers.Transaction.from(signedTransaction);\n const signature = tx.signature\n ? ethers.Signature.from(tx.signature).serialized\n : \"\";\n\n return {\n signedTransaction,\n signature,\n };\n }\n\n /**\n * Verify a signature against a public key\n * @param message - Original message\n * @param signature - Signature to verify\n * @param publicKey - Public key (hex string)\n * @returns True if signature is valid\n */\n public async verifySignature(\n message: string | Uint8Array,\n signature: string,\n publicKey: string\n ): Promise<boolean> {\n try {\n // Convert message to string if it's Uint8Array\n const messageStr =\n typeof message === \"string\"\n ? message\n : new TextDecoder().decode(message);\n\n // Recover address from signature\n const recoveredAddress = ethers.verifyMessage(messageStr, signature);\n\n // Derive address from public key\n const publicKeyWithPrefix = publicKey.startsWith(\"0x\")\n ? publicKey\n : \"0x\" + publicKey;\n const computedAddress = ethers.computeAddress(publicKeyWithPrefix);\n\n // Compare addresses\n return recoveredAddress.toLowerCase() === computedAddress.toLowerCase();\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Set or update the data provider\n * @param provider - The blockchain data provider to use\n */\n public setDataProvider(provider: BlockchainDataProvider): void {\n this.dataProvider = provider;\n }\n\n /**\n * Get the current data provider\n * @returns The current data provider, or undefined if not set\n */\n public getDataProvider(): BlockchainDataProvider | undefined {\n return this.dataProvider;\n }\n\n /**\n * Ensure a data provider is configured\n * @throws Error if no data provider is set\n */\n private ensureProvider(): void {\n if (!this.dataProvider) {\n throw new Error(\n `No data provider configured for ${this.chainData.name}. ` +\n `Please provide a BlockchainDataProvider (e.g., AlchemyProvider) in the adapter configuration.`\n );\n }\n }\n\n /**\n * Get native token balance for an address\n * @param address - Wallet address\n * @returns TokenBalance object with native token information\n * @throws Error if no data provider is configured\n */\n public async getNativeBalance(address: string): Promise<TokenBalance> {\n this.ensureProvider();\n return this.dataProvider!.getNativeBalance(address);\n }\n\n /**\n * Get all ERC-20 token balances for an address\n * @param address - Wallet address\n * @returns Array of token balances with metadata\n * @throws Error if no data provider is configured\n */\n public async getTokenBalances(address: string): Promise<TokenBalance[]> {\n this.ensureProvider();\n return this.dataProvider!.getTokenBalances(address);\n }\n\n /**\n * Get balance for a specific ERC-20 token\n * @param address - Wallet address\n * @param tokenAddress - Token contract address\n * @returns Balance in smallest unit as string\n * @throws Error if no data provider is configured\n */\n public async getTokenBalance(\n address: string,\n tokenAddress: string\n ): Promise<string> {\n this.ensureProvider();\n return this.dataProvider!.getTokenBalance(address, tokenAddress);\n }\n\n /**\n * Get all transactions for an address\n * @param address - Wallet address\n * @param options - Optional filtering and pagination options\n * @returns Array of transactions\n * @throws Error if no data provider is configured\n */\n public async getTransactions(\n address: string,\n options?: TransactionOptions\n ): Promise<Transaction[]> {\n this.ensureProvider();\n return this.dataProvider!.getTransactions(address, options);\n }\n\n /**\n * Get all ERC-20 token transfers for an address\n * @param address - Wallet address\n * @param options - Optional filtering and pagination options\n * @returns Array of token transfers\n * @throws Error if no data provider is configured\n */\n public async getTokenTransfers(\n address: string,\n options?: TransactionOptions\n ): Promise<TokenTransfer[]> {\n this.ensureProvider();\n return this.dataProvider!.getTokenTransfers(address, options);\n }\n\n /**\n * Validate if an address is a valid ERC-20 token contract\n * @param tokenAddress - Token contract address\n * @returns True if valid ERC-20, false otherwise\n */\n public async validateTokenContract(tokenAddress: string): Promise<boolean> {\n try {\n const network = this.getNetwork();\n if (!network) {\n throw new Error(`No network configured for ${this.chainData.name}`);\n }\n\n const provider = new ethers.JsonRpcProvider(network.rpcUrl);\n\n // Try to call the symbol() function (standard ERC-20 method)\n const contract = new ethers.Contract(\n tokenAddress,\n [\"function symbol() view returns (string)\"],\n provider\n );\n\n const symbol = await contract.symbol();\n return typeof symbol === \"string\" && symbol.length > 0;\n } catch (error) {\n // If symbol() call fails, it's not a valid ERC-20\n return false;\n }\n }\n\n /**\n * Send native tokens (ETH, S, etc.)\n * @param params - Transaction parameters including private key\n * @returns Transaction receipt\n */\n public async sendNativeToken(params: {\n privateKey: Uint8Array;\n to: string;\n amount: string;\n }): Promise<{\n hash: string;\n from: string;\n to: string;\n value: string;\n chainId: number;\n status: \"pending\";\n nonce: number;\n }> {\n try {\n const network = this.getNetwork();\n if (!network) {\n throw new Error(`No network configured for ${this.chainData.name}`);\n }\n\n // Convert private key to hex and create wallet\n const privateKeyHex = \"0x\" + this.bytesToHex(params.privateKey);\n const wallet = new ethers.Wallet(privateKeyHex);\n\n // Connect wallet to provider\n const provider = new ethers.JsonRpcProvider(network.rpcUrl);\n const connectedSigner = wallet.connect(provider);\n\n // Send transaction (ethers.js auto-estimates gas)\n const tx = await connectedSigner.sendTransaction({\n to: params.to,\n value: params.amount,\n });\n\n // Return receipt immediately (pending status)\n return {\n hash: tx.hash,\n from: tx.from,\n to: tx.to!,\n value: tx.value.toString(),\n chainId: network.chainId,\n status: \"pending\",\n nonce: tx.nonce,\n };\n } catch (error) {\n throw new Error(\n `Failed to send native token: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Send ERC-20 tokens\n * Private key must be obtained from AuthClient after password verification\n * @param params - Transaction parameters including private key and token address\n * @returns Transaction receipt\n */\n public async sendToken(params: {\n privateKey: Uint8Array;\n to: string;\n tokenAddress: string;\n amount: string;\n }): Promise<{\n hash: string;\n from: string;\n to: string;\n value: string;\n chainId: number;\n status: \"pending\";\n nonce: number;\n }> {\n try {\n // Validate token contract\n const isValidToken = await this.validateTokenContract(\n params.tokenAddress\n );\n if (!isValidToken) {\n throw new Error(\n `Invalid ERC-20 token contract: ${params.tokenAddress}`\n );\n }\n\n const network = this.getNetwork();\n if (!network) {\n throw new Error(`No network configured for ${this.chainData.name}`);\n }\n\n // Convert private key to hex and create wallet\n const privateKeyHex = \"0x\" + this.bytesToHex(params.privateKey);\n const wallet = new ethers.Wallet(privateKeyHex);\n\n // Connect wallet to provider\n const provider = new ethers.JsonRpcProvider(network.rpcUrl);\n const connectedSigner = wallet.connect(provider);\n\n // Create ERC-20 contract instance\n const tokenContract = new ethers.Contract(\n params.tokenAddress,\n [\n \"function transfer(address to, uint256 amount) returns (bool)\",\n \"function decimals() view returns (uint8)\",\n \"function symbol() view returns (string)\",\n ],\n connectedSigner\n );\n\n // Send token transfer transaction (ethers.js auto-estimates gas)\n const tx = await tokenContract.transfer(params.to, params.amount);\n\n // Return receipt immediately (pending status)\n return {\n hash: tx.hash,\n from: tx.from,\n to: params.tokenAddress, // For token transfers, 'to' is the contract address\n value: \"0\", // Native value is 0 for token transfers\n chainId: network.chainId,\n status: \"pending\",\n nonce: tx.nonce,\n };\n } catch (error) {\n throw new Error(\n `Failed to send token: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Wait for transaction confirmation and return detailed status\n * @param hash - Transaction hash\n * @returns Transaction status update\n */\n public async getTransactionStatus(hash: string): Promise<{\n hash: string;\n status: \"pending\" | \"confirmed\" | \"failed\";\n blockNumber?: number;\n confirmations?: number;\n error?: string;\n gasUsed?: string;\n }> {\n try {\n const network = this.getNetwork();\n if (!network) {\n throw new Error(`No network configured for ${this.chainData.name}`);\n }\n\n const provider = new ethers.JsonRpcProvider(network.rpcUrl);\n\n // Try to get transaction receipt\n const receipt = await provider.getTransactionReceipt(hash);\n\n if (!receipt) {\n // Transaction not yet mined\n return {\n hash,\n status: \"pending\",\n };\n }\n\n // Transaction is mined\n const currentBlock = await provider.getBlockNumber();\n const confirmations = currentBlock - receipt.blockNumber + 1;\n\n return {\n hash,\n status: receipt.status === 1 ? \"confirmed\" : \"failed\",\n blockNumber: receipt.blockNumber,\n confirmations,\n gasUsed: receipt.gasUsed.toString(),\n error: receipt.status === 0 ? \"Transaction failed\" : undefined,\n };\n } catch (error) {\n throw new Error(\n `Failed to get transaction status: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n // Helper methods for byte/hex conversion\n private bytesToHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n }\n\n private hexToBytes(hex: string): Uint8Array {\n const bytes = new Uint8Array(hex.length / 2);\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);\n }\n return bytes;\n }\n}\n","/**\n * Helper function to format balance from smallest unit to human-readable\n * @param balance - Balance in smallest unit (wei)\n * @param decimals - Token decimals\n * @returns Formatted balance as string\n */\nexport const formatBalance = (balance: string, decimals: number): string => {\n const divisor = Math.pow(10, decimals);\n const balanceNum = parseFloat(balance) / divisor;\n\n // Return with appropriate precision, removing trailing zeros\n return balanceNum.toLocaleString(\"en-US\", {\n minimumFractionDigits: 0,\n maximumFractionDigits: decimals,\n useGrouping: false,\n });\n};\n","import { ethers } from \"ethers\";\nimport type { BlockchainDataProvider } from \"./BlockchainDataProvider\";\nimport type {\n Transaction,\n TokenBalance,\n TokenTransfer,\n TransactionOptions,\n} from \"@cryptforge/core\";\nimport { formatBalance } from \"../utils\";\n\n/**\n * Configuration for Alchemy provider\n */\nexport interface AlchemyProviderConfig {\n /** Alchemy API key */\n apiKey: string;\n /** Network identifier for Portfolio API (e.g., \"sonic-mainnet\", \"eth-mainnet\") */\n network: string;\n /** RPC URL for direct blockchain queries */\n rpcUrl: string;\n /** Native token symbol (e.g., \"ETH\", \"S\") */\n nativeTokenSymbol: string;\n /** Native token name (e.g., \"Ethereum\", \"Sonic\") */\n nativeTokenName: string;\n /** Native token decimals (default: 18) */\n nativeTokenDecimals?: number;\n /** CoinMarketCap ID for logo URL */\n cmc_id: number;\n}\n\n/**\n * Blockchain data provider using Alchemy Portfolio API.\n * Fetches wallet balances, transactions, and token data from Alchemy's indexer.\n *\n * Uses Alchemy's Portfolio API for token balances and direct RPC for other queries.\n *\n * @example\n * ```typescript\n * import { AlchemyProvider } from '@cryptforge/blockchain-evm';\n *\n * const provider = new AlchemyProvider({\n * apiKey: process.env.ALCHEMY_API_KEY!,\n * network: \"sonic-mainnet\",\n * rpcUrl: \"https://sonic-mainnet.g.alchemy.com/v2/YOUR_API_KEY\",\n * });\n *\n * const balance = await provider.getNativeBalance('0x...');\n * const tokens = await provider.getTokenBalances('0x...');\n * ```\n */\nexport class AlchemyProvider implements BlockchainDataProvider {\n private apiKey: string;\n private network: string;\n private provider: ethers.JsonRpcProvider;\n private nativeTokenSymbol: string;\n private nativeTokenName: string;\n private nativeTokenDecimals: number;\n private cmc_id: number;\n\n constructor(config: AlchemyProviderConfig) {\n this.apiKey = config.apiKey;\n this.network = config.network;\n this.provider = new ethers.JsonRpcProvider(config.rpcUrl);\n this.nativeTokenSymbol = config.nativeTokenSymbol;\n this.nativeTokenName = config.nativeTokenName;\n this.nativeTokenDecimals = config.nativeTokenDecimals ?? 18;\n this.cmc_id = config.cmc_id;\n\n console.log(`✅ AlchemyProvider initialized for ${config.network}`);\n }\n\n /**\n * Get native token balance (e.g., ETH, S) for an address using RPC\n */\n async getNativeBalance(address: string): Promise<TokenBalance> {\n try {\n const balance = await this.provider.getBalance(address);\n const balanceStr = balance.toString();\n return {\n contractAddress: \"native\", // Native token doesn't have a contract address\n balance: balanceStr,\n balanceFormatted: formatBalance(balanceStr, this.nativeTokenDecimals),\n symbol: this.nativeTokenSymbol,\n name: this.nativeTokenName,\n decimals: this.nativeTokenDecimals,\n logo: `https://s2.coinmarketcap.com/static/img/coins/128x128/${this.cmc_id}.png`,\n isNFT: false,\n };\n } catch (error) {\n throw new Error(\n `Failed to fetch native balance: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Get all ERC-20 token balances for an address using Alchemy Portfolio API\n */\n async getTokenBalances(address: string): Promise<TokenBalance[]> {\n try {\n const url = `https://api.g.alchemy.com/data/v1/${this.apiKey}/assets/tokens/by-address`;\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n addresses: [\n {\n address: address,\n networks: [this.network],\n },\n ],\n withMetadata: true,\n includeNativeTokens: false, // We get native balance separately\n includeErc20Tokens: true,\n }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Portfolio API request failed: ${response.status} ${errorText}`\n );\n }\n\n const data = (await response.json()) as {\n data?: {\n tokens?: Array<{\n address: string;\n network: string;\n tokenAddress: string;\n tokenBalance: string;\n tokenMetadata?: {\n decimals?: number;\n logo?: string;\n name?: string;\n symbol?: string;\n };\n error?: string | null;\n }>;\n pageKey?: string;\n };\n };\n\n const tokens = data.data?.tokens || [];\n const tokenBalances: TokenBalance[] = [];\n\n for (const token of tokens) {\n // Skip if there was an error fetching this token\n if (token.error) {\n console.warn(\n `Error fetching token ${token.tokenAddress}:`,\n token.error\n );\n continue;\n }\n\n // Convert hex balance to decimal if needed\n let balance = token.tokenBalance || \"0\";\n if (balance.startsWith(\"0x\")) {\n balance = BigInt(balance).toString();\n }\n\n // Skip tokens with zero balance\n if (balance === \"0\") {\n continue;\n }\n\n const decimals = token.tokenMetadata?.decimals ?? 18;\n tokenBalances.push({\n contractAddress: token.tokenAddress,\n balance: balance,\n balanceFormatted: formatBalance(balance, decimals),\n symbol: token.tokenMetadata?.symbol || \"UNKNOWN\",\n name: token.tokenMetadata?.name || \"Unknown Token\",\n decimals,\n logo: token.tokenMetadata?.logo,\n // This endpoint returns ERC-20 tokens only, not NFTs\n isNFT: false,\n });\n }\n\n return tokenBalances;\n } catch (error) {\n throw new Error(\n `Failed to fetch token balances: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Get balance for a specific ERC-20 token using RPC\n */\n async getTokenBalance(\n address: string,\n tokenAddress: string\n ): Promise<string> {\n try {\n const contract = new ethers.Contract(\n tokenAddress,\n [\"function balanceOf(address) view returns (uint256)\"],\n this.provider\n );\n\n const balance = await contract.balanceOf(address);\n return balance.toString();\n } catch (error) {\n throw new Error(\n `Failed to fetch token balance: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Get all transactions for an address using Alchemy's getAssetTransfers API\n */\n async getTransactions(\n address: string,\n options: TransactionOptions = {}\n ): Promise<Transaction[]> {\n try {\n const transactions: Transaction[] = [];\n\n // Fetch sent transactions (fromAddress)\n const sentTransfers = await this.fetchAssetTransfers({\n fromAddress: address,\n category: [\"external\", \"internal\"],\n order: options.sort === \"asc\" ? \"asc\" : \"desc\",\n maxCount: options.offset ? `0x${options.offset.toString(16)}` : \"0x64\", // Default 100\n withMetadata: true,\n });\n\n // Fetch received transactions (toAddress)\n const receivedTransfers = await this.fetchAssetTransfers({\n toAddress: address,\n category: [\"external\", \"internal\"],\n order: options.sort === \"asc\" ? \"asc\" : \"desc\",\n maxCount: options.offset ? `0x${options.offset.toString(16)}` : \"0x64\",\n withMetadata: true,\n });\n\n // Combine and deduplicate by hash\n const allTransfers = [\n ...sentTransfers.transfers,\n ...receivedTransfers.transfers,\n ];\n const uniqueHashes = new Set<string>();\n\n for (const transfer of allTransfers) {\n if (uniqueHashes.has(transfer.hash)) continue;\n uniqueHashes.add(transfer.hash);\n\n transactions.push({\n hash: transfer.hash,\n from: transfer.from,\n to: transfer.to || \"\",\n value: transfer.value ? transfer.value.toString() : \"0\",\n timestamp: transfer.metadata?.blockTimestamp\n ? new Date(transfer.metadata.blockTimestamp).getTime() / 1000\n : 0,\n blockNumber: parseInt(transfer.blockNum, 16),\n gasUsed: \"0\", // Not provided by getAssetTransfers\n gasPrice: \"0\", // Not provided by getAssetTransfers\n status: \"success\", // Transfers API only returns successful transactions\n isError: false,\n });\n }\n\n // Sort by block number (descending by default)\n transactions.sort((a, b) =>\n options.sort === \"asc\"\n ? a.blockNumber - b.blockNumber\n : b.blockNumber - a.blockNumber\n );\n\n return transactions;\n } catch (error) {\n throw new Error(\n `Failed to fetch transactions: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Get all ERC-20 token transfers for an address using Alchemy's getAssetTransfers API\n */\n async getTokenTransfers(\n address: string,\n options: TransactionOptions = {}\n ): Promise<TokenTransfer[]> {\n try {\n const tokenTransfers: TokenTransfer[] = [];\n\n // Fetch sent token transfers (fromAddress)\n const sentTransfers = await this.fetchAssetTransfers({\n fromAddress: address,\n category: [\"erc20\"],\n order: options.sort === \"asc\" ? \"asc\" : \"desc\",\n maxCount: options.offset ? `0x${options.offset.toString(16)}` : \"0x64\",\n withMetadata: true,\n });\n\n // Fetch received token transfers (toAddress)\n const receivedTransfers = await this.fetchAssetTransfers({\n toAddress: address,\n category: [\"erc20\"],\n order: options.sort === \"asc\" ? \"asc\" : \"desc\",\n maxCount: options.offset ? `0x${options.offset.toString(16)}` : \"0x64\",\n withMetadata: true,\n });\n\n // Combine and deduplicate by uniqueId\n const allTransfers = [\n ...sentTransfers.transfers,\n ...receivedTransfers.transfers,\n ];\n const uniqueIds = new Set<string>();\n\n for (const transfer of allTransfers) {\n if (uniqueIds.has(transfer.uniqueId)) continue;\n uniqueIds.add(transfer.uniqueId);\n\n tokenTransfers.push({\n hash: transfer.hash,\n from: transfer.from,\n to: transfer.to || \"\",\n value: transfer.value ? transfer.value.toString() : \"0\",\n timestamp: transfer.metadata?.blockTimestamp\n ? new Date(transfer.metadata.blockTimestamp).getTime() / 1000\n : 0,\n blockNumber: parseInt(transfer.blockNum, 16),\n tokenAddress: transfer.rawContract?.address || \"\",\n tokenSymbol: transfer.asset || \"UNKNOWN\",\n tokenName: transfer.asset || \"Unknown Token\",\n tokenDecimal: transfer.rawContract?.decimal || \"18\",\n });\n }\n\n // Sort by block number (descending by default)\n tokenTransfers.sort((a, b) =>\n options.sort === \"asc\"\n ? a.blockNumber - b.blockNumber\n : b.blockNumber - a.blockNumber\n );\n\n return tokenTransfers;\n } catch (error) {\n throw new Error(\n `Failed to fetch token transfers: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Helper method to fetch asset transfers from Alchemy API\n */\n private async fetchAssetTransfers(params: {\n fromAddress?: string;\n toAddress?: string;\n category: string[];\n order: \"asc\" | \"desc\";\n maxCount: string;\n withMetadata: boolean;\n }): Promise<{\n transfers: Array<{\n category: string;\n blockNum: string;\n from: string;\n to: string | null;\n value: number | null;\n asset: string | null;\n uniqueId: string;\n hash: string;\n rawContract?: {\n value: string | null;\n address: string | null;\n decimal: string | null;\n };\n metadata?: {\n blockTimestamp: string;\n };\n }>;\n pageKey?: string;\n }> {\n const response = await fetch(this.provider._getConnection().url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: 1,\n method: \"alchemy_getAssetTransfers\",\n params: [\n {\n fromBlock: \"0x0\",\n toBlock: \"latest\",\n ...params,\n excludeZeroValue: true,\n },\n ],\n }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `getAssetTransfers request failed: ${response.status} ${errorText}`\n );\n }\n\n const data = (await response.json()) as {\n result?: {\n transfers: Array<{\n category: string;\n blockNum: string;\n from: string;\n to: string | null;\n value: number | null;\n asset: string | null;\n uniqueId: string;\n hash: string;\n rawContract?: {\n value: string | null;\n address: string | null;\n decimal: string | null;\n };\n metadata?: {\n blockTimestamp: string;\n };\n }>;\n pageKey?: string;\n };\n error?: {\n code: number;\n message: string;\n };\n };\n\n if (data.error) {\n throw new Error(`Alchemy API error: ${data.error.message}`);\n }\n\n return data.result || { transfers: [] };\n }\n}\n","import type { BlockchainDataProvider } from \"./BlockchainDataProvider\";\nimport type {\n Transaction,\n TokenBalance,\n TokenTransfer,\n TransactionOptions,\n} from \"@cryptforge/core\";\nimport { formatBalance } from \"../utils\";\n\n/**\n * Standard Etherscan API response structure\n */\ninterface EtherscanResponse<T = unknown> {\n status: string;\n message: string;\n result: T;\n}\n\n/**\n * Etherscan API token balance response\n */\ninterface EtherscanTokenBalance {\n TokenAddress: string;\n TokenName: string;\n TokenSymbol: string;\n TokenQuantity: string;\n TokenDivisor: string;\n}\n\n/**\n * Etherscan API token transfer response\n */\ninterface EtherscanTokenTransfer {\n blockNumber: string;\n timeStamp: string;\n hash: string;\n nonce: string;\n blockHash: string;\n from: string;\n contractAddress: string;\n to: string;\n value: string;\n tokenName: string;\n tokenSymbol: string;\n tokenDecimal: string;\n transactionIndex: string;\n gas: string;\n gasPrice: string;\n gasUsed: string;\n cumulativeGasUsed: string;\n input: string;\n confirmations: string;\n}\n\n/**\n * Etherscan API transaction response\n */\ninterface EtherscanTransaction {\n blockNumber: string;\n timeStamp: string;\n hash: string;\n nonce: string;\n blockHash: string;\n transactionIndex: string;\n from: string;\n to: string;\n value: string;\n gas: string;\n gasPrice: string;\n isError: string;\n txreceipt_status: string;\n input: string;\n contractAddress: string;\n cumulativeGasUsed: string;\n gasUsed: string;\n confirmations: string;\n}\n\n/**\n * Etherscan provider configuration\n */\nexport interface EtherscanProviderConfig {\n /** Etherscan API key (works across all supported chains) */\n apiKey: string;\n /** Chain ID (e.g., 1 for Ethereum, 146 for Sonic, 137 for Polygon) */\n chainId: number;\n /** Native token symbol (e.g., \"ETH\", \"S\") */\n nativeTokenSymbol: string;\n /** Native token name (e.g., \"Ethereum\", \"Sonic\") */\n nativeTokenName: string;\n /** Native token decimals (default: 18) */\n nativeTokenDecimals?: number;\n /** CoinMarketCap ID for logo URL */\n cmc_id: number;\n /** Etherscan API V2 base URL (default: https://api.etherscan.io/v2/api) */\n baseUrl?: string;\n}\n\n/**\n * Etherscan-based blockchain data provider\n * Uses Etherscan API V2 to fetch wallet data and transaction history\n */\nexport class EtherscanProvider implements BlockchainDataProvider {\n private apiKey: string;\n private chainId: number;\n private baseUrl: string;\n private nativeTokenSymbol: string;\n private nativeTokenName: string;\n private nativeTokenDecimals: number;\n private cmc_id: number;\n\n /**\n * Create an Etherscan provider using API V2\n * @param config - Provider configuration\n */\n constructor(config: EtherscanProviderConfig) {\n this.apiKey = config.apiKey;\n this.chainId = config.chainId;\n this.nativeTokenSymbol = config.nativeTokenSymbol;\n this.nativeTokenName = config.nativeTokenName;\n this.nativeTokenDecimals = config.nativeTokenDecimals ?? 18;\n this.cmc_id = config.cmc_id;\n this.baseUrl = config.baseUrl ?? \"https://api.etherscan.io/v2/api\";\n }\n\n /**\n * Get native token balance for an address\n * @param address - Wallet address\n * @returns TokenBalance object with native token information\n */\n async getNativeBalance(address: string): Promise<TokenBalance> {\n const params = new URLSearchParams({\n chainid: this.chainId.toString(),\n module: \"account\",\n action: \"balance\",\n address: address,\n tag: \"latest\",\n apikey: this.apiKey,\n });\n\n const url = `${this.baseUrl}?${params.toString()}`;\n const response = await this.fetchWithRetry(url);\n\n const data = (await response.json()) as EtherscanResponse<string>;\n\n if (data.status !== \"1\") {\n throw new Error(\n `Etherscan API error: ${data.message} (result: ${data.result})`\n );\n }\n\n // Return as TokenBalance object\n return {\n contractAddress: \"native\", // Native token doesn't have a contract address\n balance: data.result,\n balanceFormatted: formatBalance(data.result, this.nativeTokenDecimals),\n symbol: this.nativeTokenSymbol,\n name: this.nativeTokenName,\n decimals: this.nativeTokenDecimals,\n logo: `https://s2.coinmarketcap.com/static/img/coins/128x128/${this.cmc_id}.png`,\n isNFT: false,\n };\n }\n\n /**\n * Get all ERC-20 token balances for an address\n * @param address - Wallet address\n * @returns Array of token balances with metadata\n *\n * Note: This endpoint prefers the Etherscan API Pro endpoint for better performance,\n * but automatically falls back to a free-tier compatible approach if needed.\n */\n async getTokenBalances(address: string): Promise<TokenBalance[]> {\n const params = new URLSearchParams({\n chainid: this.chainId.toString(),\n module: \"account\",\n action: \"addresstokenbalance\",\n address: address,\n page: \"1\",\n offset: \"100\",\n apikey: this.apiKey,\n });\n\n const url = `${this.baseUrl}?${params.toString()}`;\n const response = await this.fetchWithRetry(url);\n\n const data = (await response.json()) as EtherscanResponse<\n EtherscanTokenBalance[] | string\n >;\n\n if (data.status !== \"1\") {\n // Check if this is an API Pro limitation error - fall back to free tier approach\n if (\n data.result &&\n typeof data.result === \"string\" &&\n data.result.includes(\"API Pro\")\n ) {\n return this.getTokenBalancesFallback(address);\n }\n\n // Check if this is a rate limit error - fall back with delay\n if (\n data.result &&\n typeof data.result === \"string\" &&\n data.result.includes(\"rate limit\")\n ) {\n console.warn(\"Rate limit hit, using fallback method with delays...\");\n await this.delay(1000); // Wait 1 second before fallback\n return this.getTokenBalancesFallback(address);\n }\n\n throw new Error(\n `Etherscan API error: ${data.message} (result: ${data.result})`\n );\n }\n\n // Type guard: ensure result is an array\n if (!Array.isArray(data.result)) {\n throw new Error(\"Unexpected API response format\");\n }\n\n // Map Etherscan response to TokenBalance interface\n return data.result.map((token) => {\n const decimals = parseInt(token.TokenDivisor, 10);\n return {\n contractAddress: token.TokenAddress,\n balance: token.TokenQuantity,\n balanceFormatted: formatBalance(token.TokenQuantity, decimals),\n symbol: token.TokenSymbol,\n name: token.TokenName,\n decimals,\n // This endpoint returns ERC-20 tokens only, not NFTs\n isNFT: false,\n };\n });\n }\n\n /**\n * Free-tier fallback for getTokenBalances\n * Discovers tokens via transfer history and fetches individual balances\n * Rate-limited to respect Etherscan free tier limits (3 calls/sec)\n * @param address - Wallet address\n * @returns Array of token balances with metadata\n */\n private async getTokenBalancesFallback(\n address: string\n ): Promise<TokenBalance[]> {\n // Get token transfers to discover tokens (free tier compatible)\n const transfers = await this.getTokenTransfers(address, {\n page: 1,\n offset: 10000, // Get more transfers to discover more tokens\n });\n\n if (transfers.length === 0) {\n return [];\n }\n\n // Extract unique token addresses with their metadata\n const uniqueTokens = new Map<\n string,\n { symbol: string; name: string; decimals: number }\n >();\n\n for (const transfer of transfers) {\n if (!uniqueTokens.has(transfer.tokenAddress)) {\n uniqueTokens.set(transfer.tokenAddress, {\n symbol: transfer.tokenSymbol,\n name: transfer.tokenName,\n decimals: parseInt(transfer.tokenDecimal, 10),\n });\n }\n }\n\n // Add delay after getTokenTransfers to avoid rate limit on first balance call\n // This accounts for previous API calls (getNativeBalance, addresstokenbalance attempt, etc.)\n await this.delay(1000); // 1 second delay to ensure we're clear of rate limit\n\n // Fetch balance for each unique token with rate limiting\n const balances: TokenBalance[] = [];\n const batchSize = 2; // Process 2 tokens per second (conservative for 3 calls/sec limit)\n const delayMs = 1000; // 1 second delay between batches\n\n const tokenEntries = Array.from(uniqueTokens.entries());\n\n for (let i = 0; i < tokenEntries.length; i++) {\n const [contractAddress, metadata] = tokenEntries[i];\n\n try {\n const balance = await this.getTokenBalance(address, contractAddress);\n\n // Only include tokens with non-zero balance\n if (balance !== \"0\") {\n balances.push({\n contractAddress,\n balance,\n balanceFormatted: formatBalance(balance, metadata.decimals),\n symbol: metadata.symbol,\n name: metadata.name,\n decimals: metadata.decimals,\n // This endpoint returns ERC-20 tokens only, not NFTs\n isNFT: false,\n });\n }\n } catch (error) {\n // Skip tokens that fail to fetch (might be invalid contracts)\n console.warn(\n `Failed to fetch balance for token ${contractAddress}:`,\n error\n );\n }\n\n // Add delay after each batch to respect rate limits\n if ((i + 1) % batchSize === 0 && i + 1 < tokenEntries.length) {\n await this.delay(delayMs);\n }\n }\n\n return balances;\n }\n\n /**\n * Helper method to add delay (for rate limiting)\n * @param ms - Milliseconds to delay\n */\n private delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n /**\n * Wrapper for fetch with automatic retry on rate limit\n * @param url - URL to fetch\n * @param maxRetries - Maximum number of retries (default: 2)\n * @returns Response\n */\n private async fetchWithRetry(\n url: string,\n maxRetries: number = 2\n ): Promise<Response> {\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const response = await fetch(url);\n\n if (!response.ok) {\n // If it's a rate limit response, wait and retry\n if (response.status === 429) {\n if (attempt < maxRetries) {\n const delayMs = 1000 * (attempt + 1); // Exponential backoff: 1s, 2s, 3s\n console.warn(\n `Rate limit hit (429), retrying in ${delayMs}ms... (attempt ${attempt + 1}/${maxRetries})`\n );\n await this.delay(delayMs);\n continue;\n }\n }\n throw new Error(\n `HTTP error! status: ${response.status} ${response.statusText}`\n );\n }\n\n return response;\n }\n\n throw new Error(\"Max retries exceeded\");\n }\n\n /**\n * Get balance for a specific ERC-20 token\n * @param address - Wallet address\n * @param tokenAddress - Token contract address\n * @returns Balance in smallest unit as string\n */\n async getTokenBalance(\n address: string,\n tokenAddress: string\n ): Promise<string> {\n const params = new URLSearchParams({\n chainid: this.chainId.toString(),\n module: \"account\",\n action: \"tokenbalance\",\n contractaddress: tokenAddress,\n address: address,\n tag: \"latest\",\n apikey: this.apiKey,\n });\n\n const url = `${this.baseUrl}?${params.toString()}`;\n const response = await this.fetchWithRetry(url);\n\n const data = (await response.json()) as EtherscanResponse<string>;\n\n if (data.status !== \"1\") {\n throw new Error(\n `Etherscan API error: ${data.message} (result: ${data.result})`\n );\n }\n\n return data.result;\n }\n\n /**\n * Get all transactions for an address\n * @param address - Wallet address\n * @param options - Optional filtering and pagination options\n * @returns Array of transactions\n */\n async getTransactions(\n address: string,\n options?: TransactionOptions\n ): Promise<Transaction[]> {\n const params = new URLSearchParams({\n chainid: this.chainId.toString(),\n module: \"account\",\n action: \"txlist\",\n address: address,\n startblock: (options?.startBlock ?? 0).toString(),\n endblock: (options?.endBlock ?? 99999999).toString(),\n page: (options?.page ?? 1).toString(),\n offset: (options?.offset ?? 100).toString(),\n sort: options?.sort ?? \"desc\",\n apikey: this.apiKey,\n });\n\n const url = `${this.baseUrl}?${params.toString()}`;\n const response = await this.fetchWithRetry(url);\n\n const data = (await response.json()) as EtherscanResponse<\n EtherscanTransaction[]\n >;\n\n if (data.status !== \"1\") {\n // Empty result is not an error\n if (data.message === \"No transactions found\") {\n return [];\n }\n throw new Error(\n `Etherscan API error: ${data.message} (result: ${data.result})`\n );\n }\n\n // Map Etherscan response to Transaction interface\n return data.result.map((tx) => ({\n hash: tx.hash,\n from: tx.from,\n to: tx.to,\n value: tx.value,\n timestamp: parseInt(tx.timeStamp, 10),\n blockNumber: parseInt(tx.blockNumber, 10),\n gasUsed: tx.gasUsed,\n gasPrice: tx.gasPrice,\n status:\n tx.txreceipt_status === \"1\"\n ? \"success\"\n : tx.txreceipt_status === \"0\"\n ? \"failed\"\n : \"pending\",\n isError: tx.isError === \"1\",\n }));\n }\n\n /**\n * Get all ERC-20 token transfers for an address\n * @param address - Wallet address\n * @param options - Optional filtering and pagination options\n * @returns Array of token transfers\n */\n async getTokenTransfers(\n address: string,\n options?: TransactionOptions\n ): Promise<TokenTransfer[]> {\n const params = new URLSearchParams({\n chainid: this.chainId.toString(),\n module: \"account\",\n action: \"tokentx\",\n address: address,\n startblock: (options?.startBlock ?? 0).toString(),\n endblock: (options?.endBlock ?? 99999999).toString(),\n page: (options?.page ?? 1).toString(),\n offset: (options?.offset ?? 100).toString(),\n sort: options?.sort ?? \"desc\",\n apikey: this.apiKey,\n });\n\n const url = `${this.baseUrl}?${params.toString()}`;\n const response = await this.fetchWithRetry(url);\n\n const data = (await response.json()) as EtherscanResponse<\n EtherscanTokenTransfer[]\n >;\n\n if (data.status !== \"1\") {\n // Empty result is not an error\n if (data.message === \"No transactions found\") {\n return [];\n }\n throw new Error(\n `Etherscan API error: ${data.message} (result: ${data.result})`\n );\n }\n\n // Map Etherscan response to TokenTransfer interface\n return data.result.map((tx) => ({\n hash: tx.hash,\n from: tx.from,\n to: tx.to,\n value: tx.value,\n timestamp: parseInt(tx.timeStamp, 10),\n blockNumber: parseInt(tx.blockNumber, 10),\n tokenAddress: tx.contractAddress,\n tokenSymbol: tx.tokenSymbol,\n tokenName: tx.tokenName,\n tokenDecimal: tx.tokenDecimal,\n }));\n }\n}\n","import { EVMAdapter } from \"../EVMAdapter\";\n\n/**\n * Pre-configured Ethereum adapter.\n * Uses standard Ethereum derivation path: m/44'/60'/0'/0/0\n *\n * Network Configuration:\n * - Mainnet: Ethereum Mainnet (Chain ID: 1)\n * - Testnet: Sepolia (Chain ID: 11155111)\n *\n * Note: RPC URLs use Infura. Replace 'YOUR_INFURA_API_KEY' with your actual API key,\n * or create a custom adapter with your preferred RPC provider.\n *\n * @example\n * ```typescript\n * import { EthereumAdapter } from '@cryptforge/blockchain-evm';\n *\n * // Use pre-configured adapter\n * setupCryptForgeHandlers({\n * blockchainAdapters: {\n * Ethereum: EthereumAdapter,\n * }\n * });\n *\n * // Get network info\n * const network = EthereumAdapter.getNetwork(); // mainnet by default\n * console.log(network?.rpcUrl);\n *\n * // Switch to testnet\n * EthereumAdapter.setNetwork('testnet');\n * ```\n *\n * @example Custom RPC Configuration\n * ```typescript\n * import { EVMAdapter } from '@cryptforge/blockchain-evm';\n *\n * const CustomEthereum = new EVMAdapter({\n * chainData: { name: \"Ethereum\", symbol: \"ETH\", cmc_id: 1027 },\n * coinType: 60,\n * standardDecimals: 18,\n * networks: {\n * mainnet: {\n * name: \"Ethereum Mainnet\",\n * rpcUrl: `https://mainnet.infura.io/v3/${process.env.INFURA_API_KEY}`,\n * explorerUrl: \"https://etherscan.io\",\n * chainId: 1,\n * },\n * testnet: {\n * name: \"Ethereum Testnet (Sepolia)\",\n * rpcUrl: `https://sepolia.infura.io/v3/${process.env.INFURA_API_KEY}`,\n * explorerUrl: \"https://sepolia.etherscan.io\",\n * chainId: 11155111,\n * },\n * },\n * });\n * ```\n */\nexport const EthereumAdapter = new EVMAdapter({\n chainData: {\n name: \"Ethereum\",\n symbol: \"ETH\",\n tokenStandard: \"ERC20\",\n chainId: 60,\n cmc_id: 1027, // CoinMarketCap ID for Ethereum\n decimals: 18,\n },\n coinType: 60, // Standard Ethereum BIP44 coin type\n standardDecimals: 18,\n networks: {\n mainnet: {\n name: \"Ethereum Mainnet\",\n rpcUrl: \"https://mainnet.infura.io/v3/YOUR_INFURA_API_KEY\", // Replace with your API key\n explorerUrl: \"https://etherscan.io\",\n chainId: 1,\n },\n testnet: {\n name: \"Ethereum Testnet (Sepolia)\",\n rpcUrl: \"https://sepolia.infura.io/v3/YOUR_INFURA_API_KEY\", // Replace with your API key\n explorerUrl: \"https://sepolia.etherscan.io\",\n chainId: 11155111,\n },\n },\n defaultNetwork: \"mainnet\",\n});\n","import { EVMAdapter } from \"../EVMAdapter\";\n\n/**\n * Pre-configured Sonic adapter.\n * Sonic is an EVM-compatible Layer 2 blockchain.\n * Uses standard Ethereum derivation path: m/44'/60'/0'/0/0\n *\n * Network Configuration:\n * - Mainnet: Sonic Mainnet (Chain ID: 146)\n * - Testnet: Sonic Testnet (Chain ID: 57054)\n *\n * @example\n * ```typescript\n * import { SonicAdapter } from '@cryptforge/blockchain-evm';\n *\n * // Use pre-configured adapter\n * setupCryptForgeHandlers({\n * blockchainAdapters: {\n * Sonic: SonicAdapter,\n * }\n * });\n *\n * // Get network info\n * const network = SonicAdapter.getNetwork(); // mainnet by default\n * console.log(network?.rpcUrl); // \"https://rpc.sonic.soniclabs.com\"\n * console.log(network?.chainId); // 146\n *\n * // Switch to testnet\n * SonicAdapter.setNetwork('testnet');\n * const testnetNetwork = SonicAdapter.getNetwork();\n * console.log(testnetNetwork?.chainId); // 57054\n * ```\n */\nexport const SonicAdapter = new EVMAdapter({\n chainData: {\n name: \"Sonic\",\n symbol: \"S\",\n tokenStandard: \"ERC20\",\n chainId: 60,\n cmc_id: 32684, // CoinMarketCap ID for Sonic\n decimals: 18,\n },\n coinType: 60, // Uses standard Ethereum coin type (EVM-compatible)\n standardDecimals: 18,\n networks: {\n mainnet: {\n name: \"Sonic Mainnet\",\n rpcUrl: \"https://rpc.sonic.soniclabs.com\",\n explorerUrl: \"https://sonicscan.org\",\n chainId: 146,\n },\n testnet: {\n name: \"Sonic Testnet\",\n rpcUrl: \"https://rpc.blaze.soniclabs.com\",\n explorerUrl: \"https://testnet.sonicscan.org\",\n chainId: 57054,\n },\n },\n defaultNetwork: \"mainnet\",\n});\n"]}
|