@mycelium-sdk/core 0.1.0 → 1.0.0-alpha.1

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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/wallet/DefaultSmartWallet.ts","../src/abis/smartWalletFactory.ts","../src/constants/addresses.ts","../src/tools/TokenBalance.ts","../src/constants/tokens.ts","../src/utils/tokens.ts","../src/utils/assets.ts","../src/wallet/base/wallets/SmartWallet.ts","../src/tools/ChainManager.ts","../src/constants/chains.ts","../src/utils/chains.ts","../src/types/logger.ts","../src/tools/Logger.ts","../src/wallet/WalletNamespace.ts","../src/index.ts","../src/wallet/providers/DefaultSmartWalletProvider.ts","../src/wallet/base/providers/SmartWalletProvider.ts","../src/wallet/WalletProvider.ts","../src/wallet/providers/PrivyEmbeddedWalletProvider.ts","../src/wallet/PrivyWallet.ts","../src/wallet/base/wallets/EmbeddedWallet.ts","../src/wallet/base/providers/EmbeddedWalletProvider.ts","../src/protocols/base/BaseProtocol.ts","../src/protocols/implementations/SparkProtocol.ts","../src/abis/protocols/spark.ts","../src/protocols/constants/spark.ts","../src/constants/protocols.ts","../src/tools/ApiKeysValidator.ts","../src/router/base/ProtocolRouterBase.ts","../src/router/ProtocolRouter.ts","../src/tools/CoinbaseCDP.ts","../src/utils/urls.ts"],"sourcesContent":["import {\n type Address,\n type Hash,\n type LocalAccount,\n encodeFunctionData,\n erc20Abi,\n pad,\n} from 'viem';\nimport { type WebAuthnAccount, toCoinbaseSmartAccount } from 'viem/account-abstraction';\n\nimport { smartWalletFactoryAbi } from '@/abis/smartWalletFactory';\nimport { smartWalletFactoryAddress } from '@/constants/addresses';\nimport type { SupportedChainId } from '@/constants/chains';\nimport type { ChainManager } from '@/tools/ChainManager';\nimport { fetchERC20Balance, fetchETHBalance } from '@/tools/TokenBalance';\nimport { SUPPORTED_TOKENS } from '@/constants/tokens';\nimport type { TokenBalance } from '@/types/token';\nimport { type AssetIdentifier, parseAssetAmount, resolveAsset } from '@/utils/assets';\nimport { SmartWallet } from '@/wallet/base/wallets/SmartWallet';\nimport type { TransactionData } from '@/types/transaction';\nimport type { VaultBalance, VaultTxnResult, Protocol } from '@/types/protocols/general';\nimport type { CoinbaseCDP } from '@/tools/CoinbaseCDP';\nimport type { OffRampUrlResponse, OnRampUrlResponse } from '@/types/ramp';\n\n/**\n * Default ERC-4337 smart wallet implementation. Implements main methods that a user can use to interact with DeFi protocols and use all related functionalities\n *\n * @public\n * @category Wallets operations\n * @remarks\n * Backed by Coinbase Smart Account and compatible with ERC-4337 UserOperations\n * Supports multi-owner wallets (EVM addresses or WebAuthn owners), gas-sponsored flows,\n * and cross-chain operations via {@link ChainManager}\n */\nexport class DefaultSmartWallet extends SmartWallet {\n /** Owners (EVM addresses or WebAuthn public keys) */\n private owners: Array<Address | WebAuthnAccount>;\n /** Signer for transactions and UserOperations */\n private _signer: LocalAccount;\n /** Index of signer within the owners array (undefined → default 0) */\n private signerOwnerIndex?: number;\n /** Known deployment address (if already deployed) */\n private deploymentAddress?: Address;\n /** Network and client management */\n private chainManager: ChainManager;\n /** Nonce (salt) for deterministic address calculation */\n private nonce?: bigint;\n /** Selected protocol provider instance */\n private protocolProvider: Protocol['instance'];\n /** Coinbase CDP instance to interact with Coinbase CDP API */\n private coinbaseCDP: CoinbaseCDP | null;\n\n /**\n * Creates a smart wallet instance\n *\n * @internal\n * @param owners Owners (addresses or WebAuthn accounts)\n * @param signer Local account used to sign\n * @param chainManager Chain/client manager\n * @param protocolProvider Protocol provider instance (selected upstream)\n * @param deploymentAddress Optional known deployment address\n * @param signerOwnerIndex Optional index of `signer` in owners (default 0)\n * @param nonce Optional salt for deterministic address calc (default 0)\n */\n constructor(\n owners: Array<Address | WebAuthnAccount>,\n signer: LocalAccount,\n chainManager: ChainManager,\n protocolProvider: Protocol['instance'],\n coinbaseCDP: CoinbaseCDP | null,\n deploymentAddress?: Address,\n signerOwnerIndex?: number,\n nonce?: bigint,\n ) {\n super();\n this.owners = owners;\n this._signer = signer;\n this.signerOwnerIndex = signerOwnerIndex;\n this.deploymentAddress = deploymentAddress;\n this.chainManager = chainManager;\n this.nonce = nonce;\n this.protocolProvider = protocolProvider;\n this.coinbaseCDP = coinbaseCDP;\n }\n\n /**\n * Returns the signer account for this smart wallet\n *\n * @public\n * @category Account\n * @remarks\n * Used to authorize UserOperations and on-chain transactions\n */\n get signer(): LocalAccount {\n return this._signer;\n }\n\n /**\n * Resolves the smart wallet address\n *\n * @public\n * @category Account\n * @remarks\n * If `deploymentAddress` is known, returns it. Otherwise derives a deterministic address\n * via the factory (`getAddress`) using owners and `nonce` (CREATE2-style)\n *\n * @returns Promise that resolves to the wallet address\n * @throws Error if no supported chains are configured\n * @throws Error if an owner has an invalid type\n */\n async getAddress() {\n if (this.deploymentAddress) {\n return this.deploymentAddress;\n }\n\n const owners_bytes = this.owners.map((owner) => {\n if (typeof owner === 'string') {\n return pad(owner);\n }\n if (owner.type === 'webAuthn') {\n return owner.publicKey;\n }\n throw new Error('invalid owner type');\n });\n\n // Factory is the same across all chains, so we can use the first chain to get the wallet address\n const supportedChain = this.chainManager.getSupportedChain();\n if (!supportedChain) {\n throw new Error('No supported chains configured');\n }\n const publicClient = this.chainManager.getPublicClient(supportedChain);\n const smartWalletAddress = await publicClient.readContract({\n abi: smartWalletFactoryAbi,\n address: smartWalletFactoryAddress,\n functionName: 'getAddress',\n args: [owners_bytes, this.nonce || 0n],\n });\n return smartWalletAddress;\n }\n\n /**\n * Builds a Coinbase Smart Account for a specific chain\n *\n * @internal\n * @category Account\n * @param chainId Target chain ID\n * @returns Viem Coinbase Smart Account for the given chain\n */\n async getCoinbaseSmartAccount(\n chainId: SupportedChainId,\n ): ReturnType<typeof toCoinbaseSmartAccount> {\n return toCoinbaseSmartAccount({\n address: this.deploymentAddress,\n ownerIndex: this.signerOwnerIndex,\n client: this.chainManager.getPublicClient(chainId),\n owners: [this.signer],\n nonce: this.nonce,\n version: '1.1',\n });\n }\n\n /**\n * Fetches balances (ETH + ERC-20) for a smart account across supported chains\n *\n * @public\n * @category Account\n * @returns Promise resolving to a list of {@link TokenBalance}\n */\n async getBalance(): Promise<TokenBalance[]> {\n const address = await this.getAddress();\n const tokenBalancePromises = Object.values(SUPPORTED_TOKENS).map(async (token) => {\n return fetchERC20Balance(this.chainManager, address, token);\n });\n\n const ethBalancePromise = fetchETHBalance(this.chainManager, address);\n\n return Promise.all([ethBalancePromise, ...tokenBalancePromises]);\n }\n\n /**\n * Deposits into the selected protocol’s vault to start earning yield\n * @public\n * @category Earn\n * @remarks\n * The protocol is selected on the SDK initialization step\n * @param amount Human-readable amount string\n * @returns Transaction result for the deposit\n */\n async earn(amount: string): Promise<VaultTxnResult> {\n this.chainManager.getSupportedChain();\n\n const depositTransactionResult = this.protocolProvider.deposit(amount, this);\n\n return depositTransactionResult;\n }\n\n /**\n * Reads current deposit balance from the selected protocol’s vault\n * Method to read the current deposit balance from the selected protocol’s vault for a smart account\n *\n * @public\n * @category Earn\n * @returns Vault balance or `null` if nothing deposited\n */\n async getEarnBalance(): Promise<VaultBalance | null> {\n const depositedVault = await this.protocolProvider.fetchDepositedVaults(this);\n\n if (!depositedVault) {\n return null;\n }\n\n const userAddress = await this.getAddress();\n return this.protocolProvider.getBalance(depositedVault, userAddress);\n }\n\n /**\n * Withdraws from the selected protocol’s vault\n * @public\n * @category Earn\n * @param amount Human-readable amount string\n * @returns Transaction result for the withdrawal\n * @throws Error if the withdrawal fails\n * @throws Error a user didn't deposit anything\n */\n async withdraw(amount: string): Promise<VaultTxnResult> {\n const withdrawTransactionResult = await this.protocolProvider.withdraw(amount, this);\n\n return withdrawTransactionResult;\n }\n\n /**\n * Builds a UserOperation and submits via the bundler, then waits for inclusion\n\n *\n * @public\n * @category Transactions\n *\n * @param transactionData Transaction details (`to`, `value`, `data`)\n * @param chainId Target chain ID\n * @returns Promise that resolves to the UserOperation hash\n * @throws Error with a readable message if submission or inclusion fails\n */\n async send(transactionData: TransactionData, chainId: SupportedChainId): Promise<Hash> {\n try {\n const account = await this.getCoinbaseSmartAccount(chainId);\n const bundlerClient = this.chainManager.getBundlerClient(chainId, account);\n\n // Extra buffer for gas limits\n const bump = (x: bigint, pct = 40n) => x + (x * pct) / 100n;\n\n const gas = await bundlerClient.estimateUserOperationGas({\n account,\n calls: [transactionData],\n });\n\n const hash = await bundlerClient.sendUserOperation({\n account,\n calls: [transactionData],\n callGasLimit: bump(gas.callGasLimit),\n verificationGasLimit: bump(gas.verificationGasLimit),\n preVerificationGas: bump(gas.preVerificationGas),\n });\n\n // Wait for the transaction to be included in a block\n await bundlerClient.waitForUserOperationReceipt({\n hash,\n });\n\n return hash;\n } catch (error) {\n throw new Error(\n `Failed to send transaction: ${error instanceof Error ? error.message : 'Unknown error'}`,\n );\n }\n }\n\n /**\n * Builds a UserOperation from several onchain transactions and submits via the bundler, then waits for inclusion\n *\n * @public\n * @category Transactions\n *\n * @param transactionData An array of calls to execute\n * @param chainId Target chain ID\n * @returns Promise that resolves to the UserOperation hash for the batch\n * @throws Error with a readable message if submission or inclusion fails\n */\n async sendBatch(transactionData: TransactionData[], chainId: SupportedChainId): Promise<Hash> {\n try {\n const account = await this.getCoinbaseSmartAccount(chainId);\n const bundlerClient = this.chainManager.getBundlerClient(chainId, account);\n\n // Extra buffer for gas limits\n const bump = (x: bigint, pct = 40n) => x + (x * pct) / 100n;\n\n const gas = await bundlerClient.estimateUserOperationGas({\n account,\n calls: transactionData,\n });\n\n // Wait for the transaction to be included in a block\n const hash = await bundlerClient.sendUserOperation({\n account,\n calls: transactionData,\n callGasLimit: bump(gas.callGasLimit),\n verificationGasLimit: bump(gas.verificationGasLimit),\n preVerificationGas: bump(gas.preVerificationGas),\n });\n\n await bundlerClient.waitForUserOperationReceipt({\n hash,\n });\n\n return hash;\n } catch (error) {\n throw new Error(\n `Failed to send transaction: ${error instanceof Error ? error.message : 'Unknown error'}`,\n );\n }\n }\n\n /**\n * Funds the smart wallet with the specified amount of the specified token via Coinbase CDP on-ramp service\n *\n * @public\n * @category Ramp\n *\n * @remarks\n * If Coinbase CDP is not initialized, the method will throw an error. For more details, visit @see {@link https://docs.cdp.coinbase.com/api-reference/v2/rest-api/onramp/create-an-onramp-session}\n *\n * @param amount Amount of token that a user wants to purchase and top up his account with (e.g., `\"100\"`, `\"1.5\"`)\n * @param redirectUrl URL to redirect to after the on-ramp is complete. It's required to be a valid URL\n * @param purchaseCurrency Purchase currency (e.g., `\"USDC\"`, `\"ETH\"`)\n * @param paymentCurrency Payment currency (e.g., `\"USD\"`, `\"EUR\"`)\n * @param paymentMethod Payment method (e.g., `\"CARD\"`)\n * @param chain Chain name (e.g., `\"base\"`)\n * @param country Country code (e.g., `\"US\"`)\n *\n *\n * @returns @see {@link OnRampUrlResponse}\n */\n async topUp(\n amount: string,\n redirectUrl: string,\n purchaseCurrency?: string,\n paymentCurrency?: string,\n paymentMethod?: string,\n country?: string,\n ): Promise<OnRampUrlResponse> {\n if (!this.coinbaseCDP) {\n throw new Error(\n 'Coinbase CDP is not initialized. Please, provide the configuration in the SDK initialization',\n );\n }\n\n const address = await this.getAddress();\n\n const onRampLink = await this.coinbaseCDP.getOnRampLink(\n address,\n redirectUrl,\n amount,\n purchaseCurrency,\n paymentCurrency,\n paymentMethod,\n country,\n );\n\n return onRampLink;\n }\n\n /**\n * Cashout token from smart wallet to fiat currency via Coinbase CDP off-ramp service\n *\n * @public\n * @category Ramp\n *\n * @remarks\n * If Coinbase CDP is not initialized, the method will throw an error. For more details, visit @see {@link https://docs.cdp.coinbase.com/api-reference/rest-api/onramp-offramp/create-sell-quote}\n *\n * @param country Country code (e.g., `\"US\"`)\n * @param paymentMethod Payment method (e.g., `\"CARD\"`). To get the ful list, visit \"\"\n * @param redirectUrl URL to redirect to after the off-ramp is complete. It's required to be a valid URL\n * @param sellAmount Amount of token that a user wants to sell (e.g., `\"100\"`, `\"1.5\"`)\n * @param cashoutCurrency Cashout currency (e.g., `\"USD\"`, `\"EUR\"`). To get the ful list, visit \"\"\n * @param sellCurrency Sell currency (e.g., `\"USDC\"`, `\"ETH\"`). To get the ful list, visit \"\"\n *\n *\n * @returns @see {@link OffRampUrlResponse}\n */\n async cashOut(\n country: string,\n paymentMethod: string,\n redirectUrl: string,\n sellAmount: string,\n cashoutCurrency?: string,\n sellCurrency?: string,\n ): Promise<OffRampUrlResponse> {\n if (!this.coinbaseCDP) {\n throw new Error(\n 'Coinbase CDP is not initialized. Please, provide the configuration in the SDK initialization',\n );\n }\n\n const address = await this.getAddress();\n\n const offRampLink = await this.coinbaseCDP.getOffRampLink(\n address,\n country,\n paymentMethod,\n redirectUrl,\n sellAmount,\n cashoutCurrency,\n sellCurrency,\n );\n\n return offRampLink;\n }\n\n /**\n * Send tokens from a smart account to another address\n *\n * @public\n * @category Transactions\n *\n * @param amount Human-readable amount (e.g., `1.5`)\n * @param asset Asset symbol (e.g., `\"usdc\"`, `\"eth\"`) or token address\n * @param recipientAddress Destination address\n * @returns Transaction data suitable for inclusion in a UserOperation/call\n * @throws Error if `recipientAddress` is missing, `amount` ≤ 0, or asset cannot be resolved\n */\n async sendTokens(\n amount: number,\n asset: AssetIdentifier,\n recipientAddress: Address,\n ): Promise<TransactionData> {\n if (!recipientAddress) {\n throw new Error('Recipient address is required');\n }\n\n // Validate amount\n if (amount <= 0) {\n throw new Error('Amount must be greater than 0');\n }\n\n const chainId = this.chainManager.getSupportedChain();\n\n // Handle ETH transfers\n if (asset.toLowerCase() === 'eth') {\n const parsedAmount = parseAssetAmount(amount, 18); // ETH has 18 decimals\n\n return {\n to: recipientAddress,\n value: parsedAmount,\n data: '0x',\n };\n }\n\n // Handle ERC20 token transfers\n const resolvedAsset = resolveAsset(asset, chainId);\n const parsedAmount = parseAssetAmount(amount, resolvedAsset.decimals);\n\n // Encode ERC20 transfer function call\n const transferData = encodeFunctionData({\n abi: erc20Abi,\n functionName: 'transfer',\n args: [recipientAddress, parsedAmount],\n });\n\n return {\n to: resolvedAsset.address,\n value: 0n,\n data: transferData,\n };\n }\n}\n","export const smartWalletFactoryAbi = [\n {\n type: 'constructor',\n inputs: [\n { name: 'implementation_', type: 'address', internalType: 'address' },\n ],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n name: 'createAccount',\n inputs: [\n { name: 'owners', type: 'bytes[]', internalType: 'bytes[]' },\n { name: 'nonce', type: 'uint256', internalType: 'uint256' },\n ],\n outputs: [\n {\n name: 'account',\n type: 'address',\n internalType: 'contract CoinbaseSmartWallet',\n },\n ],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n name: 'getAddress',\n inputs: [\n { name: 'owners', type: 'bytes[]', internalType: 'bytes[]' },\n { name: 'nonce', type: 'uint256', internalType: 'uint256' },\n ],\n outputs: [{ name: '', type: 'address', internalType: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'implementation',\n inputs: [],\n outputs: [{ name: '', type: 'address', internalType: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'initCodeHash',\n inputs: [],\n outputs: [{ name: '', type: 'bytes32', internalType: 'bytes32' }],\n stateMutability: 'view',\n },\n {\n type: 'event',\n name: 'AccountCreated',\n inputs: [\n {\n name: 'account',\n type: 'address',\n indexed: true,\n internalType: 'address',\n },\n {\n name: 'owners',\n type: 'bytes[]',\n indexed: false,\n internalType: 'bytes[]',\n },\n {\n name: 'nonce',\n type: 'uint256',\n indexed: false,\n internalType: 'uint256',\n },\n ],\n anonymous: false,\n },\n { type: 'error', name: 'ImplementationUndeployed', inputs: [] },\n { type: 'error', name: 'OwnerRequired', inputs: [] },\n] as const\n","export const smartWalletFactoryAddress = '0xBA5ED110eFDBa3D005bfC882d75358ACBbB85842';\n","import { type Address, erc20Abi, formatEther, formatUnits } from 'viem';\n\nimport type { SupportedChainId } from '@/constants/chains';\nimport type { ChainManager } from '@/tools/ChainManager';\nimport { getTokenAddress, type TokenInfo } from '@/utils/tokens';\nimport type { TokenBalance } from '@/types/token';\n\n/**\n * Fetches the ETH balance for a wallet across configured supported chain\n *\n * @internal\n * @category Balances\n * @param chainManager Chain manager instance\n * @param walletAddress Target wallet address\n * @returns Promise resolving to a {@link TokenBalance} object for ETH\n */\nexport async function fetchETHBalance(\n chainManager: ChainManager,\n walletAddress: Address,\n): Promise<TokenBalance> {\n const supportedChain = chainManager.getSupportedChain();\n\n const publicClient = chainManager.getPublicClient(supportedChain);\n const balance = await publicClient.getBalance({\n address: walletAddress,\n });\n\n return {\n symbol: 'ETH',\n totalBalance: balance,\n totalFormattedBalance: formatEther(balance),\n chainBalances: [\n {\n chainId: supportedChain,\n balance,\n formattedBalance: formatEther(balance),\n },\n ],\n };\n}\n\n/**\n * Fetches the ERC20 token balance for a wallet across the configured supported chain\n *\n * @internal\n * @category Balances\n * @param chainManager Chain manager instance\n * @param walletAddress Target wallet address\n * @param token Token metadata including address and decimals\n * @returns Promise resolving to a {@link TokenBalance} object for the token\n */\nexport async function fetchERC20Balance(\n chainManager: ChainManager,\n walletAddress: Address,\n token: TokenInfo,\n): Promise<TokenBalance> {\n const supportedChain = chainManager.getSupportedChain();\n\n const balance = await fetchERC20BalanceForChain(\n token,\n supportedChain,\n walletAddress,\n chainManager,\n );\n\n return {\n symbol: token.symbol,\n totalBalance: balance,\n totalFormattedBalance: formatUnits(balance, token.decimals),\n chainBalances: [\n {\n chainId: supportedChain,\n balance,\n formattedBalance: formatUnits(balance, token.decimals),\n },\n ],\n };\n}\n\n/**\n * Fetches the ERC20 token balance for a wallet on a specific chain\n *\n * @internal\n * @category Balances\n * @remarks\n * Falls back to native ETH balance if `token.symbol` is ETH\n *\n * @param token Token metadata\n * @param chainId Chain ID to query\n * @param walletAddress Target wallet address\n * @param chainManager Chain manager instance\n * @returns Promise resolving to raw bigint balance\n * @throws Error if token is not supported on the given chain\n */\nasync function fetchERC20BalanceForChain(\n token: TokenInfo,\n chainId: SupportedChainId,\n walletAddress: Address,\n chainManager: ChainManager,\n): Promise<bigint> {\n const tokenAddress = getTokenAddress(token.symbol, chainId);\n if (!tokenAddress) {\n throw new Error(`${token.symbol} not supported on chain ${chainId}`);\n }\n\n const publicClient = chainManager.getPublicClient(chainId);\n\n // Handle native ETH balance\n if (token.symbol === 'ETH') {\n return publicClient.getBalance({\n address: walletAddress,\n });\n }\n\n // Handle ERC20 token balance\n return publicClient.readContract({\n address: tokenAddress,\n abi: erc20Abi,\n functionName: 'balanceOf',\n args: [walletAddress],\n });\n}\n","import type { TokenInfo } from '@/utils/tokens';\nimport { mainnet, unichain, base, baseSepolia, sepolia } from 'viem/chains';\n\nexport const SUPPORTED_TOKENS: Record<string, TokenInfo> = {\n ETH: {\n symbol: 'ETH',\n name: 'Ethereum',\n decimals: 18,\n addresses: {\n [mainnet.id]: '0x0000000000000000000000000000000000000000',\n [unichain.id]: '0x0000000000000000000000000000000000000000',\n [base.id]: '0x0000000000000000000000000000000000000000',\n [baseSepolia.id]: '0x0000000000000000000000000000000000000000',\n [sepolia.id]: '0x0000000000000000000000000000000000000000',\n },\n },\n USDC: {\n symbol: 'USDC',\n name: 'USDC',\n decimals: 6,\n addresses: {\n [mainnet.id]: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',\n [unichain.id]: '0x078d782b760474a361dda0af3839290b0ef57ad6',\n [baseSepolia.id]: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n [sepolia.id]: '0xf08A50178dfcDe18524640EA6618a1f965821715',\n [base.id]: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n },\n },\n};\n","import type { Address } from 'viem';\nimport type { SupportedChainId } from '@/constants/chains';\nimport { SUPPORTED_TOKENS } from '@/constants/tokens';\n\nexport interface TokenInfo {\n symbol: string;\n name: string;\n decimals: number;\n addresses: Partial<Record<SupportedChainId, Address>>; // chainId -> address\n}\n\n/**\n * Find token by address and chain ID\n * @param address Token address\n * @param chainId Chain ID\n * @returns Token symbol or null if not found\n */\nexport function findTokenByAddress(address: Address, chainId: SupportedChainId): string | null {\n const normalizedAddress = address.toLowerCase();\n\n for (const [symbol, token] of Object.entries(SUPPORTED_TOKENS)) {\n const tokenAddress = token.addresses[chainId];\n if (tokenAddress && tokenAddress.toLowerCase() === normalizedAddress) {\n return symbol;\n }\n }\n\n return null;\n}\n\n/**\n * Get token address for a specific chain\n * @param symbol Token symbol\n * @param chainId Chain ID\n * @returns Token address or null if not supported on that chain\n */\nexport function getTokenAddress(symbol: string, chainId: SupportedChainId): Address | null {\n const token = SUPPORTED_TOKENS[symbol];\n return token?.addresses[chainId] || null;\n}\n","import { type Address, parseUnits } from 'viem';\n\nimport type { SupportedChainId } from '@/constants/chains';\nimport { getTokenAddress } from '@/utils/tokens';\nimport { SUPPORTED_TOKENS } from '@/constants/tokens';\n\n/**\n * Asset identifier - can be a symbol (like 'usdc') or address\n */\nexport type AssetIdentifier = string | Address;\n\n/**\n * Resolved asset information\n */\nexport interface ResolvedAsset {\n address: Address;\n symbol: string;\n decimals: number;\n}\n\n/**\n * Resolve asset identifier to address and metadata\n * @param asset - Asset symbol (e.g. 'usdc') or address\n * @param chainId - Chain ID to resolve for\n * @returns Resolved asset information\n * @throws Error if asset is not supported or found\n */\nexport function resolveAsset(asset: AssetIdentifier, chainId: SupportedChainId): ResolvedAsset {\n // If it's an address (starts with 0x), validate and find symbol\n if (asset.startsWith('0x')) {\n const address = asset as Address;\n\n // Try to find the symbol for this address\n for (const [, tokenInfo] of Object.entries(SUPPORTED_TOKENS)) {\n const tokenAddress = tokenInfo.addresses[chainId];\n if (tokenAddress && tokenAddress.toLowerCase() === address.toLowerCase()) {\n return {\n address: tokenAddress,\n symbol: tokenInfo.symbol,\n decimals: tokenInfo.decimals,\n };\n }\n }\n\n // If not found in supported tokens, we can't determine decimals\n throw new Error(\n `Unknown asset address: ${address}. Please use a supported asset symbol like 'usdc' or add the token to SUPPORTED_TOKENS.`,\n );\n }\n\n // If it's a symbol, resolve to address\n const normalizedSymbol = asset.toUpperCase();\n const tokenInfo = SUPPORTED_TOKENS[normalizedSymbol];\n\n if (!tokenInfo) {\n const availableSymbols = Object.keys(SUPPORTED_TOKENS).join(', ');\n throw new Error(`Unsupported asset symbol: ${asset}. Supported assets: ${availableSymbols}`);\n }\n\n const address = getTokenAddress(normalizedSymbol, chainId);\n if (!address) {\n throw new Error(\n `Asset ${asset} is not supported on chain ${chainId}. Available chains: ${Object.keys(tokenInfo.addresses).join(', ')}`,\n );\n }\n\n return {\n address,\n symbol: tokenInfo.symbol,\n decimals: tokenInfo.decimals,\n };\n}\n\n/**\n * Parse human-readable amount to wei/smallest unit\n * @param amount - Human-readable amount (e.g. 1.5)\n * @param decimals - Token decimals\n * @returns Amount in smallest unit (wei equivalent)\n */\nexport function parseAssetAmount(amount: number, decimals: number): bigint {\n // Convert number to string with proper precision\n const amountStr = amount.toString();\n\n // Use viem's parseUnits for proper decimal handling\n return parseUnits(amountStr, decimals);\n}\n\n/**\n * Convert wei/smallest unit back to human-readable amount\n * @param amount - Amount in smallest unit\n * @param decimals - Token decimals\n * @returns Human-readable amount as number\n */\nexport function formatAssetAmount(amount: bigint, decimals: number): number {\n // Convert to string, then to number\n const divisor = 10n ** BigInt(decimals);\n const wholePart = amount / divisor;\n const fractionalPart = amount % divisor;\n\n // Handle fractional part with proper precision\n const fractionalStr = fractionalPart.toString().padStart(decimals, '0');\n const result = `${wholePart}.${fractionalStr}`;\n\n return parseFloat(result);\n}\n\n/**\n * Validate and parse lend parameters\n * @param amount - Human-readable amount\n * @param asset - Asset identifier\n * @param chainId - Chain ID\n * @returns Parsed lend parameters\n */\nexport function parseLendParams(\n amount: number,\n asset: AssetIdentifier,\n chainId: SupportedChainId,\n): {\n amount: bigint;\n asset: ResolvedAsset;\n} {\n if (amount <= 0) {\n throw new Error('Amount must be greater than 0');\n }\n\n const resolvedAsset = resolveAsset(asset, chainId);\n const parsedAmount = parseAssetAmount(amount, resolvedAsset.decimals);\n\n return {\n amount: parsedAmount,\n asset: resolvedAsset,\n };\n}\n","import type { Address, Hash, LocalAccount } from 'viem';\n\nimport type { SupportedChainId } from '@/constants/chains';\nimport type { TokenBalance } from '@/types/token';\nimport type { AssetIdentifier } from '@/utils/assets';\nimport type { TransactionData } from '@/types/transaction';\nimport type { VaultBalance, VaultTxnResult } from '@/types/protocols/general';\nimport type { OffRampUrlResponse, OnRampUrlResponse } from '@/types/ramp';\n\n/**\n * Abstract base class for smart wallet implementations\n *\n * @internal\n * @category Wallets\n * @remarks\n * Provides the interface for ERC-4337 compatible wallets\n * Extended by concrete classes such as {@link DefaultSmartWallet}\n */\nexport abstract class SmartWallet {\n /** LocalAccount used for signing transactions on behalf of this smart wallet */\n abstract signer: LocalAccount;\n\n /**\n * Returns the deployed or predicted address of this smart wallet\n *\n * @internal\n * @category Addressing\n * @remarks\n * For undeployed wallets this returns the deterministic CREATE2 address\n *\n * @returns Promise resolving to the wallet Ethereum address\n */\n abstract getAddress(): Promise<Address>;\n\n /**\n * Retrieves balances for all supported tokens held by this smart wallet\n *\n * @internal\n * @category Balances\n * @returns Promise resolving to an array of {@link TokenBalance} entries\n */\n abstract getBalance(): Promise<TokenBalance[]>;\n\n // TODO: add addSigner method\n // TODO: add removeSigner method\n\n /**\n * Executes a transaction through the smart wallet\n *\n * @internal\n * @category Transactions\n * @remarks\n * Handles gas sponsorship and ERC-4337 UserOperation creation automatically\n *\n * @param transactionData Transaction data to execute\n * @param chainId Target blockchain chain ID\n * @returns Promise resolving to the transaction {@link Hash}\n */\n abstract send(transactionData: TransactionData, chainId: SupportedChainId): Promise<Hash>;\n\n /**\n * Executes a batch of transactions through the smart wallet\n *\n * @internal\n * @category Transactions\n * @remarks\n * Transactions are executed in the order they are provided\n * Handles gas sponsorship and ERC-4337 UserOperation creation automatically\n *\n * @param transactionData Array of transaction data objects\n * @param chainId Target blockchain chain ID\n * @returns Promise resolving to the transaction {@link Hash}\n */\n abstract sendBatch(transactionData: TransactionData[], chainId: SupportedChainId): Promise<Hash>;\n\n /**\n * Prepares transaction data for sending tokens to another address\n *\n * @internal\n * @category Transactions\n * @param amount Human-readable amount to send\n * @param asset Token or asset identifier\n * @param recipientAddress Destination address\n * @returns Promise resolving to prepared {@link TransactionData}\n */\n abstract sendTokens(\n amount: number,\n asset: AssetIdentifier,\n recipientAddress: Address,\n ): Promise<TransactionData>;\n\n /**\n * Deposits funds into a selected protocol vault to start earning yield\n *\n * @internal\n * @category Yield\n * @param amount Amount to deposit in human-readable format\n * @returns Promise resolving to a {@link VaultTxnResult}\n */\n abstract earn(amount: string): Promise<VaultTxnResult>;\n\n /**\n * Retrieves the balance of deposited funds in the selected protocol vault\n *\n * @internal\n * @category Yield\n * @returns Promise resolving to a {@link VaultBalance} or null if none\n */\n abstract getEarnBalance(): Promise<VaultBalance | null>;\n\n /**\n * Withdraws a specific amount of shares from the protocol vault\n *\n * @internal\n * @category Yield\n * @param amount Human-readable amount of shares to withdraw\n * @returns Promise resolving to a {@link VaultTxnResult}\n */\n abstract withdraw(amount: string): Promise<VaultTxnResult>;\n\n /**\n * Funds the smart wallet with the specified amount of the specified token via Coinbase CDP on-ramp service\n *\n * @internal\n * @category Ramp\n *\n * @remarks\n * If Coinbase CDP is not initialized, the method will throw an error\n *\n * @param amount Amount of token that a user wants to purchase and top up his account with (e.g., `\"100\"`, `\"1.5\"`)\n * @param redirectUrl URL to redirect to after the on-ramp is complete. It's required to be a valid URL\n * @param purchaseCurrency Purchase currency (e.g., `\"USDC\"`, `\"ETH\"`). To get the ful list, visit \"\"\n * @param paymentCurrency Payment currency (e.g., `\"USD\"`, `\"EUR\"`). To get the ful list, visit \"\"\n * @param paymentMethod Payment method (e.g., `\"CARD\"`). To get the ful list, visit \"\"\n * @param chain Chain name (e.g., `\"base\"`)\n * @param country Country code (e.g., `\"US\"`)\n *\n *\n * @returns A URL string to the on-ramp service\n */\n abstract topUp(\n amount: string,\n redirectUrl: string,\n purchaseCurrency?: string,\n paymentCurrency?: string,\n paymentMethod?: string,\n country?: string,\n ): Promise<OnRampUrlResponse>;\n\n /**\n * @internal\n * Cash out funds from the smart wallet to a specified currency via Coinbase CDP off-ramp service\n * @category Ramp\n *\n * @param country\n * @param paymentMethod\n * @param redirectUrl\n * @param sellAmount\n * @param cashoutCurrency\n * @param sellCurrency\n * @returns A URL string to the off-ramp service\n *\n */\n abstract cashOut(\n country: string,\n paymentMethod: string,\n redirectUrl: string,\n sellAmount: string,\n cashoutCurrency?: string,\n sellCurrency?: string,\n ): Promise<OffRampUrlResponse>;\n}\n","import { type Chain, createPublicClient, http, type PublicClient } from 'viem';\nimport {\n type BundlerClient,\n type SmartAccount,\n createBundlerClient,\n} from 'viem/account-abstraction';\n\nimport { type SUPPORTED_CHAIN_IDS, CHAINS_MAP } from '@/constants/chains';\nimport type { ChainConfig } from '@/types/chain';\nimport { chainById } from '@/utils/chains';\nimport { logger } from '@/tools/Logger';\n\n/**\n * Service for managing supported blockchain networks and their clients\n *\n * @internal\n * @category Infrastructure\n * @remarks\n * Provides RPC and bundler URL access, creates {@link PublicClient} and {@link BundlerClient} instances\n * Central point for chain-level configuration in the SDK\n */\nexport class ChainManager {\n /** Public client for the configured chain */\n private publicClient: PublicClient;\n /** Chain configuration */\n private chainConfigs: ChainConfig;\n /** Map of chain names to chain metadata */\n private chainNames: Record<string, Chain>;\n\n /**\n * Initializes the chain manager with the given configuration\n *\n * @internal\n * @param chains Configuration object for a supported chain\n */\n constructor(chains: ChainConfig) {\n this.chainConfigs = chains;\n this.publicClient = this.createPublicClient(chains);\n this.chainNames = CHAINS_MAP;\n }\n\n /**\n * Utility to validate if a string is a valid HTTP(S) URL\n *\n * @internal\n * @param url Candidate URL\n * @returns True if valid, false otherwise\n */\n private isValidUrl(url: string): boolean {\n return /^https?:\\/\\/.+$/.test(url);\n }\n\n /**\n * Returns a {@link PublicClient} for the given chain ID\n *\n * @internal\n * @category Clients\n * @param chainId Target chain ID\n * @returns {@link PublicClient} instance\n * @throws Error if client is not configured\n */\n getPublicClient(chainId: (typeof SUPPORTED_CHAIN_IDS)[number]): PublicClient {\n const client = this.publicClient;\n if (!client) {\n throw new Error(`No public client configured for chain ID: ${chainId}`);\n }\n return client;\n }\n\n /**\n * Returns a {@link BundlerClient} for the given chain ID\n *\n * @internal\n * @category Clients\n * @param chainId Target chain ID\n * @param account SmartAccount to bind to the bundler client\n * @returns {@link BundlerClient} instance\n * @throws Error if no bundler URL is configured\n */\n getBundlerClient(\n chainId: (typeof SUPPORTED_CHAIN_IDS)[number],\n account: SmartAccount,\n ): BundlerClient {\n const rpcUrl = this.getRpcUrl(chainId);\n const bundlerUrl = this.getBundlerUrl(chainId);\n if (!bundlerUrl) {\n throw new Error(`No bundler URL configured for chain ID: ${chainId}`);\n }\n\n logger.info('Public client setup:', { bundlerUrl, chainId }, 'ChainManager');\n const client = createPublicClient({\n chain: this.getChain(chainId),\n transport: http(rpcUrl),\n });\n\n return createBundlerClient({\n account,\n client,\n transport: http(bundlerUrl),\n chain: this.getChain(chainId),\n });\n }\n\n /**\n * Returns the RPC URL for the given chain ID\n *\n * @internal\n * @category URLs\n * @param chainId Target chain ID\n * @returns RPC URL string\n * @throws Error if chain config is missing or URL is invalid\n */\n getRpcUrl(chainId: (typeof SUPPORTED_CHAIN_IDS)[number]): string {\n const chainConfig = this.chainConfigs;\n if (!chainConfig) {\n throw new Error(`No chain config found for chain ID: ${chainId}`);\n }\n\n if (!this.isValidUrl(chainConfig.rpcUrl)) {\n throw new Error(`Invalid RPC URL for chain ID: ${chainId}`);\n }\n\n return chainConfig.rpcUrl;\n }\n\n /**\n * Returns the bundler URL for the given chain ID\n *\n * @internal\n * @category URLs\n * @param chainId Target chain ID\n * @returns Bundler URL string\n * @throws Error if chain config is missing or URL is invalid\n */\n getBundlerUrl(chainId: (typeof SUPPORTED_CHAIN_IDS)[number]): string | undefined {\n const chainConfig = this.chainConfigs;\n if (!chainConfig) {\n throw new Error(`No chain config found for chain ID: ${chainId}`);\n }\n\n if (!this.isValidUrl(chainConfig.bundlerUrl)) {\n throw new Error(`Invalid bundler URL for chain ID: ${chainId}`);\n }\n return chainConfig.bundlerUrl;\n }\n\n /**\n * Returns the {@link Chain} object for the given chain ID\n *\n * @internal\n * @category Info\n * @param chainId Target chain ID\n * @returns Chain metadata\n * @throws Error if chain is not found\n */\n getChain(chainId: (typeof SUPPORTED_CHAIN_IDS)[number]): Chain {\n const chain = chainById[chainId];\n if (!chain) {\n throw new Error(`Chain not found for ID: ${chainId}`);\n }\n return chain;\n }\n\n /**\n * Returns the currently configured supported chain ID\n *\n * @internal\n * @category Info\n * @returns Supported chain ID\n */\n getSupportedChain() {\n return this.chainConfigs.chainId;\n }\n\n /**\n * Creates a {@link PublicClient} for a chain\n *\n * @internal\n * @category Clients\n * @param chain Chain configuration\n * @returns PublicClient instance\n */\n private createPublicClient(chain: ChainConfig): PublicClient {\n const chainObject = chainById[chain.chainId];\n\n const client = createPublicClient({\n chain: chainObject,\n transport: http(chain.rpcUrl),\n });\n\n return client;\n }\n}\n","import { base, baseSepolia, type Chain } from 'viem/chains';\n\nexport const CHAINS_MAP: Record<string, Chain> = {\n base,\n baseSepolia,\n};\n\nexport const SUPPORTED_CHAIN_IDS = Object.values(CHAINS_MAP).map((c) => c.id);\n\nexport type SupportedChainId = (typeof SUPPORTED_CHAIN_IDS)[number];\n","import { type Chain } from 'viem';\nimport * as viemChains from 'viem/chains';\n\n/** Runtime map: chain ID -> Chain */\nexport const chainById: Record<number, Chain> = Object.values(viemChains).reduce(\n (acc, maybeChain) => {\n // viem/chains exports both chain objects and helpers; pick only real Chain objects\n if (\n maybeChain &&\n typeof maybeChain === 'object' &&\n 'id' in maybeChain &&\n typeof (maybeChain as any).id === 'number' &&\n 'name' in maybeChain\n ) {\n const chain = maybeChain as Chain;\n acc[chain.id] = chain;\n }\n return acc;\n },\n {} as Record<number, Chain>,\n);\n","export enum LogLevel {\n DEBUG = 0,\n INFO = 1,\n WARN = 2,\n ERROR = 3,\n}\n\nexport interface LogEntry {\n timestamp: string;\n level: LogLevel;\n message: string;\n data?: any;\n context?: string;\n}\n","/* eslint-disable no-console */\nimport { LogLevel, type LogEntry } from '@/types/logger';\n\n/**\n * Logger service\n *\n * @internal\n * @category Utilities\n * @remarks\n * Provides a singleton logger with configurable log levels, console output,\n * and an in-memory log buffer. Supports exporting logs for debugging or analytics\n */\nexport class Logger {\n private static instance: Logger;\n private logLevel: LogLevel;\n private logs: LogEntry[] = [];\n private maxLogs: number = 1000;\n\n /**\n * Create a new logger instance\n * @param logLevel Initial log level, defaults to DEBUG\n */\n private constructor(logLevel: LogLevel = LogLevel.DEBUG) {\n this.logLevel = logLevel;\n }\n /**\n * Get singleton instance of the logger\n * @param logLevel Optional log level to initialize if instance not yet created\n * @returns Logger instance\n */\n public static getInstance(logLevel?: LogLevel): Logger {\n if (!Logger.instance) {\n Logger.instance = new Logger(logLevel);\n }\n return Logger.instance;\n }\n /** Set the log level */\n public setLogLevel(level: LogLevel): void {\n this.logLevel = level;\n }\n /** Get the current log level */\n public getLogLevel(): LogLevel {\n return this.logLevel;\n }\n /** Internal check if a message should be logged */\n private shouldLog(level: LogLevel): boolean {\n return level >= this.logLevel;\n }\n /** Format log message into a readable string */\n private formatMessage(level: LogLevel, message: string, data?: any, context?: string): string {\n const timestamp = new Date().toISOString();\n const levelName = LogLevel[level];\n const contextStr = context ? `[${context}]` : '';\n\n return `${timestamp} ${levelName}${contextStr}: ${message}`;\n }\n /** Add a log entry and output to console */\n private addLog(level: LogLevel, message: string, data?: any, context?: string): void {\n if (!this.shouldLog(level)) {\n return;\n }\n\n const logEntry: LogEntry = {\n timestamp: new Date().toISOString(),\n level,\n message,\n data,\n context,\n };\n\n this.logs.push(logEntry);\n\n // Keep only the last maxLogs entries\n if (this.logs.length > this.maxLogs) {\n this.logs = this.logs.slice(-this.maxLogs);\n }\n\n // Console output with colors\n const formattedMessage = this.formatMessage(level, message, data, context);\n\n switch (level) {\n case LogLevel.DEBUG:\n console.debug(`🔍 ${formattedMessage}`, data || '');\n break;\n case LogLevel.INFO:\n console.info(`ℹ️ ${formattedMessage}`, data || '');\n break;\n case LogLevel.WARN:\n console.warn(`⚠️ ${formattedMessage}`, data || '');\n break;\n case LogLevel.ERROR:\n console.error(`❌ ${formattedMessage}`, data || '');\n break;\n }\n }\n /** Log a debug message */\n public debug(message: string, data?: any, context?: string): void {\n this.addLog(LogLevel.DEBUG, message, data, context);\n }\n /** Log an info message */\n public info(message: string, data?: any, context?: string): void {\n this.addLog(LogLevel.INFO, message, data, context);\n }\n /** Log a warning message */\n public warn(message: string, data?: any, context?: string): void {\n this.addLog(LogLevel.WARN, message, data, context);\n }\n /** Log an error message */\n public error(message: string, data?: any, context?: string): void {\n this.addLog(LogLevel.ERROR, message, data, context);\n }\n /** Get all logs */\n public getLogs(): LogEntry[] {\n return [...this.logs];\n }\n /** Get logs by level */\n public getLogsByLevel(level: LogLevel): LogEntry[] {\n return this.logs.filter((log) => log.level === level);\n }\n /** Clear all logs */\n public clearLogs(): void {\n this.logs = [];\n }\n /** Export logs as a JSON string */\n public exportLogs(): string {\n return JSON.stringify(this.logs, null, 2);\n }\n /** Set maximum number of logs to retain in memory */\n public setMaxLogs(max: number): void {\n this.maxLogs = max;\n }\n}\n/** Global logger instance */\nexport const logger = Logger.getInstance();\n/**\n * Shorthand log methods\n * @internal\n */\nexport const log = {\n debug: (message: string, data?: any, context?: string) => logger.debug(message, data, context),\n info: (message: string, data?: any, context?: string) => logger.info(message, data, context),\n warn: (message: string, data?: any, context?: string) => logger.warn(message, data, context),\n error: (message: string, data?: any, context?: string) => logger.error(message, data, context),\n};\n","import type {\n CreateSmartWalletOptions,\n CreateWalletWithEmbeddedSignerOptions,\n GetEmbeddedWalletOptions,\n GetSmartWalletOptions,\n GetSmartWalletWithEmbeddedSignerOptions,\n} from '@/types/wallet';\nimport type { EmbeddedWallet } from '@/wallet/base/wallets/EmbeddedWallet';\nimport type { SmartWallet } from '@/wallet/base/wallets/SmartWallet';\nimport type { WalletProvider } from '@/wallet/WalletProvider';\n\n/**\n * Public wallet namespace that exposes unified wallet operations\n *\n * @public\n * @category Wallets creation and retrieval\n * @remarks\n * This class is returned by {@link MyceliumSDK} and provides a simplified\n * interface for wallet creation and retrieval. Advanced functionality can be accessed through\n * the underlying providers via the getters {@link embeddedWalletProvider} and\n * {@link smartWalletProvider}\n *\n * Typical flows:\n * - Create embedded wallet only: {@link createEmbeddedWallet}\n * - Create smart wallet only (you provide signer/owners): {@link createSmartWallet}\n * - Create smart wallet with embedded as signer: {@link createWalletWithEmbeddedSigner}\n * - Get smart wallet using embedded as signer: {@link getSmartWalletWithEmbeddedSigner}\n * - Get smart wallet using a provided signer: {@link getSmartWallet}\n */\nexport class WalletNamespace {\n /**\n * Internal provider facade that implements the actual logic\n * @internal\n */\n private provider: WalletProvider;\n\n /**\n * Creates a wallet namespace to manage embedded and smart wallets\n * @param provider Unified provider that composes embedded & smart providers\n */\n constructor(provider: WalletProvider) {\n this.provider = provider;\n }\n\n /**\n * Direct access to the underlying embedded wallet provider\n *\n * @public\n * @category Providers\n * @remarks\n * Useful when you need advanced functionality beyond the unified namespace. By default, you should use the unified namespace\n *\n * @returns The configured embedded wallet provider instance\n */\n get embeddedWalletProvider() {\n return this.provider.embeddedWalletProvider;\n }\n\n /**\n * Direct access to the underlying smart wallet provider\n *\n * @public\n * @category Providers\n * @remarks\n * Useful when you need advanced functionality beyond the unified namespace. By default, you should use the unified namespace\n *\n * @returns The configured smart wallet provider instance\n */\n get smartWalletProvider() {\n return this.provider.smartWalletProvider;\n }\n\n /**\n * Creates an embedded wallet\n *\n * @public\n * @category Creation\n * @remarks\n * Thin wrapper around the embedded wallet provider’s `createWallet`\n *\n * @returns Promise that resolves to the newly created {@link EmbeddedWallet}\n */\n async createEmbeddedWallet(): Promise<EmbeddedWallet> {\n return this.provider.createEmbeddedWallet();\n }\n\n /**\n * Creates a smart wallet (you provide signer and owners)\n *\n * @public\n * @category Creation\n * @remarks\n * Use this when you already control a signer (e.g., `LocalAccount`) and want to\n * create a smart wallet without creating an embedded wallet\n *\n * @param params Smart wallet creation parameters\n * @param params.owners Owners for the smart wallet (addresses or WebAuthn public keys)\n * @param params.signer Local account used for signing transactions\n * @param params.nonce Optional nonce/salt for deterministic address generation (defaults to 0)\n * @returns Promise that resolves to the created {@link SmartWallet}\n */\n async createSmartWallet(params: CreateSmartWalletOptions): Promise<SmartWallet> {\n return this.provider.createSmartWallet(params);\n }\n\n /**\n * Creates a smart wallet with an embedded wallet as signer\n *\n * @public\n * @category Creation\n * @remarks\n * Creates an embedded wallet first, inserts its address into the owners array,\n * and uses its account as the signer for the smart wallet\n *\n * @param params Optional creation parameters\n * @param params.owners Optional additional owners. The embedded wallet address is inserted at the specified index\n * @param params.embeddedWalletIndex Optional index at which to insert the embedded wallet address (defaults to end)\n * @param params.nonce Optional nonce/salt for deterministic address generation (defaults to 0)\n * @returns Promise that resolves to the created {@link SmartWallet}\n */\n async createWalletWithEmbeddedSigner(\n params?: CreateWalletWithEmbeddedSignerOptions,\n ): Promise<SmartWallet> {\n return this.provider.createWalletWithEmbeddedSigner(params);\n }\n\n /**\n * Gets a smart wallet using an embedded wallet as the signer\n *\n * @public\n * @category Retrieval\n * @remarks\n * Looks up an embedded wallet by `walletId` and uses it as signer\n * If neither `walletAddress` nor `deploymentOwners` is provided, defaults to using\n * the embedded wallet as the single owner for deterministic address calculation\n *\n * @param params Retrieval parameters\n * @param params.walletId Embedded wallet ID used to locate the signer wallet\n * @param params.deploymentOwners Optional original deployment owners used for address calculation\n * @param params.signerOwnerIndex Index of the signer within the **current** owners set (defaults to 0)\n * @param params.walletAddress Optional explicit smart wallet address (skips calculation)\n * @param params.nonce Optional nonce used during original creation\n * @returns Promise that resolves to the {@link SmartWallet}\n * @throws Error if the embedded wallet cannot be found\n */\n async getSmartWalletWithEmbeddedSigner(params: GetSmartWalletWithEmbeddedSignerOptions) {\n return this.provider.getSmartWalletWithEmbeddedSigner(params);\n }\n\n /**\n * Gets an existing embedded wallet by ID\n *\n * @public\n * @category Retrieval\n * @param params Retrieval parameters\n * @param params.walletId Embedded wallet ID to retrieve\n * @returns Promise that resolves to the {@link EmbeddedWallet} (or `null/undefined` per provider contract)\n */\n async getEmbeddedWallet(params: GetEmbeddedWalletOptions) {\n return this.provider.getEmbeddedWallet(params);\n }\n\n /**\n * Gets a smart wallet using a provided signer\n *\n * @public\n * @category Retrieval\n * @remarks\n * Use when you already control a signer. Requires either:\n * - `walletAddress`, or\n * - `deploymentOwners` (+ optional `nonce`) to derive the address\n *\n * @param params Retrieval parameters\n * @param params.signer Signer (local account)\n * @param params.deploymentOwners Original deployment owners (required if `walletAddress` is not provided)\n * @param params.signerOwnerIndex Index of the signer within the **current** owners set (defaults to 0)\n * @param params.walletAddress Explicit smart wallet address (skips calculation)\n * @param params.nonce Optional nonce used during original creation\n * @returns Promise that resolves to the {@link SmartWallet}\n * @throws Error if neither `walletAddress` nor `deploymentOwners` is provided\n */\n async getSmartWallet(params: GetSmartWalletOptions) {\n return this.provider.getSmartWallet(params);\n }\n}\n","/**\n * @packageDocumentation\n * Entry point for the Mycelium SDK\n *\n * Exports stable types and the main SDK facade (`MyceliumSDK`)\n * Internal base classes and implementations are not part of the public API\n * and are hidden from public documentation\n */\n\nexport * from '@/public/types';\n\n/** @internal */\nexport { DefaultSmartWallet } from '@/wallet/DefaultSmartWallet';\n\nimport { ChainManager } from '@/tools/ChainManager';\nimport type { SmartWalletProvider } from '@/wallet/base/providers/SmartWalletProvider';\nimport { WalletNamespace } from '@/wallet/WalletNamespace';\nimport { type MyceliumSDKConfig } from '@/types/sdk';\nimport { base } from 'viem/chains';\nimport { DefaultSmartWalletProvider } from '@/wallet/providers/DefaultSmartWalletProvider';\nimport { WalletProvider } from '@/wallet/WalletProvider';\nimport type { EmbeddedWalletProvider } from '@/wallet/base/providers/EmbeddedWalletProvider';\nimport { PrivyEmbeddedWalletProvider } from './wallet/providers/PrivyEmbeddedWalletProvider';\nimport { PrivyClient } from '@privy-io/server-auth';\nimport { ProtocolRouter } from '@/router/ProtocolRouter';\nimport type { Protocol } from '@/types/protocols/general';\nimport { logger } from '@/tools/Logger';\nimport { CoinbaseCDP, type CoinbaseCDP as CoinbaseCDPType } from './tools/CoinbaseCDP';\n\n/**\n * Main SDK facade for integrating wallets and protocols.\n *\n * @public\n * @category Get started\n * @remarks\n * This class encapsulates:\n * - protocol selection and initialization (`Smart Router`),\n * - chain/network management (`ChainManager`),\n * - public wallet namespace (accessible through {@link MyceliumSDK.wallet | wallet}).\n *\n * By default, if no chain config is provided, it uses the public RPC\n * and Bundler for the Base chain\n *\n * @example\n * ```ts\n * import { MyceliumSDK, type MyceliumSDKConfig } from '@mycelium-sdk/core';\n *\n * const config: MyceliumSDKConfig = {\n * walletsConfig: { /* ... *\\/ },\n * protocolsRouterConfig: { /* ... *\\/ },\n * chain: { /* ... *\\/ },\n * coinbaseCDPConfig: { /* ... *\\/ },\n * integratorId: 'MyceliumApp',\n * };\n *\n * const sdk = new MyceliumSDK(config);\n *\n * const embeddedWallet = await sdk.wallet.createEmbeddedWallet();\n * const wallet = await sdk.wallet.createSmartWallet({\n * owners: [embeddedWallet.address],\n * signer: await embeddedWallet.account(),\n * })\n * const balance = await wallet.getBalance();\n * ```\n */\nexport class MyceliumSDK {\n /**\n * Unified wallet namespace to manage embedded/smart wallets and related operations\n * @public\n * @category Wallets\n */\n public readonly wallet: WalletNamespace;\n\n /**\n * Chain manager instance to manage chain related entities\n * @internal\n */\n private _chainManager: ChainManager;\n\n /** @internal */\n private embeddedWalletProvider!: EmbeddedWalletProvider;\n\n /** @internal */\n private smartWalletProvider!: SmartWalletProvider;\n\n /**\n * Protocol instance to perform earn related operations with a selected protocol\n * @internal\n */\n private protocol: Protocol;\n\n /**\n * Coinbase CDP instance to Coinbase related and onchain operations using Coinbase CDP API\n * @remarks\n * If the configuration is not provided, the Coinbase CDP functionality will be disabled.\n * Calling the respective method will throw an error.\n * @internal\n */\n private coinbaseCDP: CoinbaseCDPType | null = null;\n\n /**\n * Creates a new SDK instance\n *\n * @param config SDK configuration (networks, wallets, protocol router settings)\n * @throws Throws if an unsupported wallet provider is given\n * @see MyceliumSDKConfig\n */\n constructor(config: MyceliumSDKConfig) {\n this._chainManager = new ChainManager(\n config.chain || {\n chainId: base.id,\n rpcUrl: base.rpcUrls.default.http[0],\n bundlerUrl: 'https://public.pimlico.io/v2/8453/rpc',\n },\n );\n\n if (!config.chain) {\n logger.warn(\n 'No chain config provided, using default public RPC and Bundler URLs',\n 'MyceliumSDK',\n );\n }\n\n if (config.coinbaseCDPConfig) {\n this.coinbaseCDP = new CoinbaseCDP(\n config.coinbaseCDPConfig.apiKeyId,\n config.coinbaseCDPConfig.apiKeySecret,\n config.integratorId,\n this.chainManager,\n );\n }\n\n const protocolsRouterConfig = config.protocolsRouterConfig || {\n riskLevel: 'low',\n };\n\n // protocolsRouterConfig is the abstract settings that are clear for a dev, e.g. risk level, basic apy, etc\n this.protocol = this.findProtocol(protocolsRouterConfig);\n\n this.wallet = this.createWalletNamespace(config.walletsConfig);\n }\n\n /**\n * Returns the chain manager instance for multi-chain operations\n * @public\n * @category Tools\n *\n * @returns ChainManager instance of the type {@link ChainManager}\n */\n get chainManager(): ChainManager {\n return this._chainManager;\n }\n\n /**\n * Coinbase CDP configuration methods for ramp operations\n * @public\n * @category Tools\n */\n public readonly rampConfig = {\n /**\n * Return all supported countries and payment methods for on-ramp by Coinbase CDP\n * @public\n * @category Ramp\n *\n * @returns @see {@link RampConfigResponse} with supported countries and payment methods for top-up\n * @throws If API returned an error\n */\n getTopUpConfig: async () => {\n if (!this.coinbaseCDP) {\n throw new Error(\n 'Coinbase CDP is not initialized. Please, provide the configuration in the SDK initialization',\n );\n }\n\n return await this.coinbaseCDP.getOnRampConfig();\n },\n /**\n * Return all supported countries and payment methods for off-ramp by Coinbase CDP\n * @public\n * @category Ramp\n *\n *\n * @returns @see {@link RampConfigResponse} with supported countries and payment methods for cash out\n * @throws If API returned an error\n */\n getCashOutConfig: async () => {\n if (!this.coinbaseCDP) {\n throw new Error(\n 'Coinbase CDP is not initialized. Please, provide the configuration in the SDK initialization',\n );\n }\n\n return await this.coinbaseCDP.getOffRampConfig();\n },\n };\n\n /**\n * Recommends and initializes a protocol based on router settings\n *\n * @internal\n * @param config Protocol router configuration (e.g. risk level)\n * @returns Selected protocol object of the type {@link Protocol}\n */\n private findProtocol(config: MyceliumSDKConfig['protocolsRouterConfig']): Protocol {\n // 1. Create a smart router with the given config\n // 2. Smart router will fetch available protocols\n // 3. Smart router will find the best protocol based on the given config\n // 4. Smart router should somehow save selected protocols here for future use of this particular integrator\n // 5. Smart router will return the best protocol here\n\n const protocolRouter = new ProtocolRouter(config!, this.chainManager);\n\n const protocol: Protocol = protocolRouter.recommend();\n\n // Right now we have a protocol instance to manage a protocol instance + all protocol info\n\n // Initialize the selected protocol\n protocol.instance.init(this.chainManager);\n\n return protocol;\n }\n\n /**\n * Creates a wallet provider (embedded + smart) and combines them\n *\n * @internal\n * @param config Wallet configuration\n * @returns Configured {@link WalletProvider}\n * @throws If an unsupported wallet provider type is specified\n */\n private createWalletProvider(config: MyceliumSDKConfig['walletsConfig']) {\n if (config.embeddedWalletConfig.provider.type === 'privy') {\n const privyClient = new PrivyClient(\n config.embeddedWalletConfig.provider.providerConfig.appId,\n config.embeddedWalletConfig.provider.providerConfig.appSecret,\n );\n\n this.embeddedWalletProvider = new PrivyEmbeddedWalletProvider(\n privyClient,\n this._chainManager,\n );\n } else {\n throw new Error(\n `Unsupported embedded wallet provider: ${config.embeddedWalletConfig.provider.type}`,\n );\n }\n\n if (!config.smartWalletConfig || config.smartWalletConfig.provider.type === 'default') {\n this.smartWalletProvider = new DefaultSmartWalletProvider(\n this.chainManager,\n this.protocol,\n this.coinbaseCDP,\n );\n } else {\n throw new Error(\n `Unsupported smart wallet provider: ${config.smartWalletConfig.provider.type}`,\n );\n }\n\n const walletProvider = new WalletProvider(\n this.embeddedWalletProvider,\n this.smartWalletProvider,\n );\n\n return walletProvider;\n }\n\n /**\n * Creates the public wallet namespace\n *\n * @internal\n * @param config Wallet configuration.\n * @returns A {@link WalletNamespace} instance\n */\n private createWalletNamespace(config: MyceliumSDKConfig['walletsConfig']) {\n const walletProvider = this.createWalletProvider(config);\n return new WalletNamespace(walletProvider);\n }\n}\n","import { pad, type Address, type LocalAccount } from 'viem';\nimport { type WebAuthnAccount } from 'viem/account-abstraction';\n\nimport { smartWalletFactoryAbi } from '@/abis/smartWalletFactory';\nimport { smartWalletFactoryAddress } from '@/constants/addresses';\nimport type { ChainManager } from '@/tools/ChainManager';\nimport { DefaultSmartWallet } from '@/wallet/DefaultSmartWallet';\nimport { SmartWalletProvider } from '@/wallet/base/providers/SmartWalletProvider';\nimport type { Protocol } from '@/types/protocols/general';\nimport type { CoinbaseCDP } from '@/tools/CoinbaseCDP';\n\n/**\n * Default provider for creating and managing ERC-4337 smart wallets\n *\n * @internal\n * @category Wallets\n * @remarks\n * Factory that composes {@link DefaultSmartWallet} instances\n * Handles deterministic address prediction and instance construction\n */\nexport class DefaultSmartWalletProvider extends SmartWalletProvider {\n /** Manages supported blockchain networks */\n private chainManager: ChainManager;\n\n /** Already initialized protocol provider instance */\n private protocolProvider: Protocol['instance'];\n\n /** Coinbase CDP instance to interact with Coinbase CDP API */\n private coinbaseCDP: CoinbaseCDP | null;\n\n /**\n * Initializes the smart wallet provider\n *\n * @internal\n * @param chainManager Manager for chains and viem clients\n * @param protocol Selected protocol descriptor that exposes an initialized instance\n */\n constructor(chainManager: ChainManager, protocol: Protocol, coinbaseCDP: CoinbaseCDP | null) {\n super();\n this.chainManager = chainManager;\n this.protocolProvider = protocol.instance;\n this.coinbaseCDP = coinbaseCDP;\n }\n\n /**\n * Creates a new smart wallet instance that deploys on first use\n *\n * @internal\n * @category Creation\n * @remarks\n * Address is derived deterministically from `owners` and `nonce`\n *\n * @param params Parameters for wallet creation\n * @param params.owners Owners as EVM addresses or WebAuthn owners\n * @param params.signer Local account used to sign UserOperations and transactions\n * @param params.nonce Optional salt for deterministic address calculation, default 0\n * @returns Promise that resolves to a {@link DefaultSmartWallet} instance\n */\n async createWallet(params: {\n owners: Array<Address | WebAuthnAccount>;\n signer: LocalAccount;\n nonce?: bigint;\n }): Promise<DefaultSmartWallet> {\n const { owners, signer, nonce } = params;\n return new DefaultSmartWallet(\n owners,\n signer,\n this.chainManager,\n this.protocolProvider,\n this.coinbaseCDP,\n undefined,\n undefined,\n nonce,\n );\n }\n\n /**\n * Predicts the deterministic smart wallet address for the given owners and nonce\n *\n * @internal\n * @category Addressing\n * @remarks\n * Uses the smart wallet factory `getAddress` to compute the CREATE2 address\n *\n * @param params Address prediction parameters\n * @param params.owners Owners as EVM addresses or WebAuthn owners\n * @param params.nonce Optional salt for deterministic address calculation, default 0\n * @returns Promise that resolves to the predicted wallet address\n * @throws Error if no supported chains are configured\n * @throws Error if an owner has an invalid type\n */\n async getWalletAddress(params: { owners: Array<Address | WebAuthnAccount>; nonce?: bigint }) {\n const { owners, nonce = 0n } = params;\n const owners_bytes = owners.map((owner) => {\n if (typeof owner === 'string') {\n return pad(owner);\n }\n if (owner.type === 'webAuthn') {\n return owner.publicKey;\n }\n throw new Error('invalid owner type');\n });\n\n // Factory is the same accross all chains, so we can use the first chain to get the wallet address\n const supportedChain = this.chainManager.getSupportedChain();\n if (!supportedChain) {\n throw new Error('No supported chains configured');\n }\n const publicClient = this.chainManager.getPublicClient(supportedChain);\n const smartWalletAddress = await publicClient.readContract({\n abi: smartWalletFactoryAbi,\n address: smartWalletFactoryAddress,\n functionName: 'getAddress',\n args: [owners_bytes, nonce],\n });\n return smartWalletAddress;\n }\n\n /**\n * Returns a smart wallet instance for an already deployed address\n *\n * @internal\n * @category Retrieval\n * @remarks\n * Use when you already know the deployment address and want an instance bound to a signer\n *\n * @param params Retrieval parameters\n * @param params.walletAddress Deployed smart wallet address\n * @param params.signer Local account to operate the wallet\n * @param params.ownerIndex Optional index of `signer` within the current owners set, default 0\n * @returns A {@link DefaultSmartWallet} instance\n */\n getWallet(params: {\n walletAddress: Address;\n signer: LocalAccount;\n ownerIndex?: number;\n }): DefaultSmartWallet {\n const { walletAddress, signer, ownerIndex } = params;\n return new DefaultSmartWallet(\n [signer.address],\n signer,\n this.chainManager,\n this.protocolProvider,\n this.coinbaseCDP,\n walletAddress,\n ownerIndex,\n );\n }\n\n /**\n * Funds a wallet via a faucet if supported by the selected chain\n *\n * @internal\n * @category Funding\n * @remarks\n * Placeholder for testnet faucet integration\n *\n * @returns Future transaction hash or provider response\n */\n fundViaFaucet() {}\n}\n","import type { Address, LocalAccount } from 'viem';\nimport type { WebAuthnAccount } from 'viem/account-abstraction';\nimport type { SmartWallet } from '@/wallet/base/wallets/SmartWallet';\n\n/**\n * Abstract base class for smart wallet providers\n *\n * @internal\n * @category Wallet Providers\n * @remarks\n * Defines the interface for factories that create and manage {@link SmartWallet} instances\n * Extended by implementations such as {@link DefaultSmartWalletProvider}\n */\nexport abstract class SmartWalletProvider {\n /**\n * Creates a new smart wallet instance that will be deployed on first transaction\n *\n * @internal\n * @category Creation\n * @remarks\n * Address is calculated deterministically using owners and nonce\n *\n * @param params Wallet creation parameters\n * @param params.owners Array of wallet owners (addresses or WebAuthn accounts)\n * @param params.signer Local account used for signing\n * @param params.nonce Optional nonce for address derivation, default 0\n * @returns Promise resolving to a {@link SmartWallet} instance\n */\n abstract createWallet(params: {\n owners: Array<Address | WebAuthnAccount>;\n signer: LocalAccount;\n nonce?: bigint;\n }): Promise<SmartWallet>;\n\n /**\n * Returns a smart wallet instance for an already deployed contract\n *\n * @internal\n * @category Retrieval\n * @remarks\n * Use when the wallet address is already known\n *\n * @param params Wallet retrieval parameters\n * @param params.walletAddress Deployed smart wallet address\n * @param params.signer Local account to operate the wallet\n * @param params.ownerIndex Optional index of signer in the owners list, default 0\n * @returns A {@link SmartWallet} instance\n */\n abstract getWallet(params: {\n walletAddress: Address;\n signer: LocalAccount;\n ownerIndex?: number;\n }): SmartWallet;\n\n /**\n * Predicts the deterministic address of a smart wallet\n *\n * @internal\n * @category Addressing\n * @remarks\n * Uses CREATE2 with owners and nonce to calculate the wallet address\n *\n * @param params Prediction parameters\n * @param params.owners Array of wallet owners (addresses or WebAuthn accounts)\n * @param params.nonce Optional nonce, default 0\n * @returns Promise resolving to the predicted {@link Address}\n */\n abstract getWalletAddress(params: {\n owners: Array<Address | WebAuthnAccount>;\n nonce?: bigint;\n }): Promise<Address>;\n}\n","import type { Address } from 'viem';\nimport type { WebAuthnAccount } from 'viem/account-abstraction';\n\nimport type {\n CreateSmartWalletOptions,\n CreateWalletWithEmbeddedSignerOptions,\n GetEmbeddedWalletOptions,\n GetSmartWalletOptions,\n GetSmartWalletWithEmbeddedSignerOptions,\n} from '@/types/wallet';\nimport type { EmbeddedWallet } from '@/wallet/base/wallets/EmbeddedWallet';\nimport type { SmartWallet } from '@/wallet/base/wallets/SmartWallet';\nimport type { EmbeddedWalletProvider } from '@/wallet/base/providers/EmbeddedWalletProvider';\nimport type { SmartWalletProvider } from '@/wallet/base/providers/SmartWalletProvider';\nimport { logger } from '@/tools/Logger';\n\n/**\n * Unified Wallet Provider class\n *\n * @internal\n * @category Wallets\n * @remarks\n * Internal facade that composes an embedded wallet provider and a smart wallet provider\n * and exposes higher-level creation/retrieval flows. Not exported from user's usage\n *\n * Used in a higher level class - {@link WalletNamespace}\n *\n * Typical flows:\n * - Create embedded wallet only: {@link createEmbeddedWallet}\n * - Create smart wallet only (you provide signer/owners): {@link createSmartWallet}\n * - Create smart wallet with embedded wallet as signer: {@link createWalletWithEmbeddedSigner}\n * - Get smart wallet using embedded wallet as signer: {@link getSmartWalletWithEmbeddedSigner}\n * - Get smart wallet using a provided signer: {@link getSmartWallet}\n */\nexport class WalletProvider {\n /**\n * Embedded wallet provider instance\n * @internal\n */\n public readonly embeddedWalletProvider: EmbeddedWalletProvider;\n\n /**\n * Smart wallet provider instance\n * @internal\n */\n public readonly smartWalletProvider: SmartWalletProvider;\n\n /**\n * Creates a unified wallet provider\n *\n * @internal\n * @param embeddedWalletProvider Provider for embedded wallet operations\n * @param smartWalletProvider Provider for smart wallet operations\n */\n constructor(\n embeddedWalletProvider: EmbeddedWalletProvider,\n smartWalletProvider: SmartWalletProvider,\n ) {\n this.embeddedWalletProvider = embeddedWalletProvider;\n this.smartWalletProvider = smartWalletProvider;\n }\n\n /**\n * Creates an embedded wallet\n *\n * @internal\n * @remarks\n * Thin wrapper around the embedded wallet provider’s `createWallet`\n *\n * @returns Promise that resolves to the newly created {@link EmbeddedWallet}\n */\n async createEmbeddedWallet(): Promise<EmbeddedWallet> {\n return this.embeddedWalletProvider.createWallet();\n }\n\n /**\n * Creates a smart wallet (you provide signer and owners)\n *\n * @internal\n * @remarks\n * Use when you already control a signer and want to create a smart\n * wallet without creating an embedded wallet\n *\n * @param params Smart wallet creation parameters\n * @param params.owners Owners array for the smart wallet (EVM addresses or WebAuthn owners)\n * @param params.signer Signer (local account) used for transactions\n * @param params.nonce Optional salt/nonce for deterministic address calculation (defaults to 0)\n * @returns Promise that resolves to the created {@link SmartWallet}\n */\n async createSmartWallet(params: CreateSmartWalletOptions): Promise<SmartWallet> {\n const { owners, signer, nonce } = params;\n\n return this.smartWalletProvider.createWallet({\n owners,\n signer,\n nonce,\n });\n }\n\n /**\n * Creates a smart wallet with an embedded wallet as signer\n *\n * @internal\n * @remarks\n * Creates an embedded wallet first, then inserts its address into the owners array\n * and uses its account as the signer for the smart wallet. Default SDK option, embedded wallets manager is necessary to be provided\n *\n * @param params Optional creation parameters\n * @param params.owners Optional additional owners. The embedded wallet address is inserted at the specified index\n * @param params.embeddedWalletIndex Optional index where the embedded wallet address should be inserted (defaults to the end)\n * @param params.nonce Optional salt/nonce for deterministic address calculation (defaults to 0)\n * @returns Promise that resolves to the created {@link SmartWallet}\n */\n async createWalletWithEmbeddedSigner(\n params?: CreateWalletWithEmbeddedSignerOptions,\n ): Promise<SmartWallet> {\n const { owners: ownersParam, embeddedWalletIndex, nonce } = params || {};\n const embeddedWallet = await this.embeddedWalletProvider.createWallet();\n const account = await embeddedWallet.account();\n\n let owners: Array<Address | WebAuthnAccount>;\n if (ownersParam) {\n owners = [...ownersParam]; // Create a copy to avoid mutating the original\n const insertIndex = embeddedWalletIndex ?? owners.length; // Default to end if not specified\n owners.splice(insertIndex, 0, embeddedWallet.address); // Insert embedded wallet at specified index\n } else {\n owners = [embeddedWallet.address]; // Default to just the embedded wallet\n }\n\n return this.smartWalletProvider.createWallet({\n owners,\n signer: account,\n nonce,\n });\n }\n\n /**\n * Gets a smart wallet using an embedded wallet as the signer\n *\n * @internal\n * @remarks\n * Fetches an embedded wallet by `walletId` and uses it as signer.\n * If neither `walletAddress` nor `deploymentOwners` is provided, defaults to using\n * the embedded wallet as the single owner for deterministic address calculation\n *\n * @param params Retrieval parameters\n * @param params.walletId Embedded wallet ID used to locate the signer wallet\n * @param params.deploymentOwners Optional original deployment owners used for address calculation\n * @param params.signerOwnerIndex Index of the signer in the **current** owners set (defaults to 0)\n * @param params.walletAddress Optional explicit smart wallet address (skips calculation)\n * @param params.nonce Optional nonce used during original creation\n * @returns Promise that resolves to the {@link SmartWallet}\n * @throws Error if the embedded wallet cannot be found\n */\n async getSmartWalletWithEmbeddedSigner(params: GetSmartWalletWithEmbeddedSignerOptions) {\n const { walletId, deploymentOwners, walletAddress } = params;\n const embeddedWallet = await this.embeddedWalletProvider.getWallet({\n walletId,\n });\n if (!embeddedWallet) {\n throw new Error('Embedded wallet not found');\n }\n const account = await embeddedWallet.account();\n\n // If neither walletAddress nor deploymentOwners provided, default to embedded wallet as single owner\n const finalDeploymentOwners =\n deploymentOwners || (walletAddress ? undefined : [embeddedWallet.address]);\n\n return this.getSmartWallet({\n signer: account,\n ...params,\n deploymentOwners: finalDeploymentOwners,\n });\n }\n\n /**\n * Gets an existing embedded wallet by ID\n *\n * @internal\n * @param params Retrieval parameters\n * @param params.walletId Embedded wallet ID\n * @returns Promise that resolves to the {@link EmbeddedWallet}, or `null/undefined` per provider’s contract\n */\n async getEmbeddedWallet(params: GetEmbeddedWalletOptions) {\n const { walletId } = params;\n return this.embeddedWalletProvider.getWallet({\n walletId,\n });\n }\n\n /**\n * Gets a smart wallet using a provided signer\n *\n * @internal\n * @remarks\n * Use when you already control a `LocalAccount` signer\n * Requires either:\n * - `walletAddress`, or\n * - `deploymentOwners` (+ optional `nonce`) to deterministically derive the address\n *\n * @param params Retrieval parameters\n * @param params.signer Signer (local account)\n * @param params.deploymentOwners Original deployment owners (required if `walletAddress` is not provided)\n * @param params.signerOwnerIndex Index of `signer` within the **current** owners set (defaults to 0)\n * @param params.walletAddress Explicit smart wallet address (skips calculation)\n * @param params.nonce Optional nonce used during original creation\n * @returns Promise that resolves to the {@link SmartWallet}\n * @throws Error if neither `walletAddress` nor `deploymentOwners` is provided\n */\n async getSmartWallet(params: GetSmartWalletOptions) {\n const {\n signer,\n deploymentOwners,\n signerOwnerIndex,\n walletAddress: walletAddressParam,\n nonce,\n } = params;\n\n if (!walletAddressParam && !deploymentOwners) {\n try {\n throw new Error(\n 'Either walletAddress or deploymentOwners array must be provided to locate the smart wallet',\n );\n } catch (error) {\n logger.error('Error getting smart wallet', error, 'WalletProvider');\n throw new Error(\n 'Either walletAddress or deploymentOwners array must be provided to locate the smart wallet',\n );\n }\n }\n\n const ownerIndex = signerOwnerIndex ?? 0;\n\n const walletAddress =\n walletAddressParam ||\n (await this.smartWalletProvider.getWalletAddress({\n // Safe to use ! since we validated above\n owners: deploymentOwners!,\n nonce,\n }));\n return this.smartWalletProvider.getWallet({\n walletAddress,\n signer,\n ownerIndex,\n });\n }\n}\n","import type { PrivyClient } from '@privy-io/server-auth';\nimport { getAddress } from 'viem';\n\nimport type { ChainManager } from '@/tools/ChainManager';\nimport { PrivyWallet } from '@/wallet/PrivyWallet';\nimport { EmbeddedWalletProvider } from '@/wallet/base/providers/EmbeddedWalletProvider';\nimport { logger } from '@/tools/Logger';\n\n/**\n * Options for querying all Privy wallets\n *\n * @internal\n * @category Wallets\n */\nexport interface PrivyProviderGetAllWalletsOptions {\n /** Maximum number of wallets to return */\n limit?: number;\n /** Cursor for pagination */\n cursor?: string;\n}\n\n/**\n * Embedded wallet provider backed by Privy\n *\n * @internal\n * @category Wallets\n * @remarks\n * Wraps Privy client API for creating, retrieving, and listing wallets\n * Produces {@link PrivyWallet} instances used internally by the SDK\n */\nexport class PrivyEmbeddedWalletProvider extends EmbeddedWalletProvider {\n /** Privy client instance */\n public privy: PrivyClient;\n /** Manager for supported chains and clients */\n private chainManager: ChainManager;\n /**\n * Creates a new Privy-backed embedded wallet provider\n *\n * @internal\n * @param privyClient Privy client instance\n * @param chainManager Chain and client manager\n */\n constructor(privyClient: PrivyClient, chainManager: ChainManager) {\n super();\n this.privy = privyClient;\n this.chainManager = chainManager;\n }\n\n /**\n * Creates a new wallet using Privy’s wallet API\n *\n * @internal\n * @category Creation\n * @returns Promise that resolves to a new {@link PrivyWallet} instance\n * @throws Error if wallet creation fails\n */\n async createWallet(): Promise<PrivyWallet> {\n try {\n const wallet = await this.privy.walletApi.createWallet({\n chainType: 'ethereum',\n });\n\n const walletInstance = new PrivyWallet(\n this.privy,\n wallet.id,\n getAddress(wallet.address),\n this.chainManager,\n );\n return walletInstance;\n } catch (error) {\n logger.error('Failed to create wallet: ', error, 'PrivyEmbeddedWalletProvider');\n throw new Error(`Failed to create wallet: ${error}`);\n }\n }\n\n /**\n * Retrieves a wallet by its ID via Privy\n *\n * @internal\n * @category Retrieval\n * @param params Parameters containing walletId\n * @returns Promise that resolves to a {@link PrivyWallet} instance\n * @throws Error if the wallet cannot be retrieved\n */\n async getWallet(params: { walletId: string }): Promise<PrivyWallet> {\n try {\n const wallet = await this.privy.walletApi.getWallet({\n id: params.walletId,\n });\n\n const walletInstance = new PrivyWallet(\n this.privy,\n wallet.id,\n getAddress(wallet.address),\n this.chainManager,\n );\n return walletInstance;\n } catch {\n throw new Error(`Failed to get wallet with id: ${params.walletId}`);\n }\n }\n\n /**\n * Retrieves all wallets from Privy with optional filtering and pagination\n *\n * @internal\n * @category Retrieval\n * @param options Optional filtering and pagination parameters\n * @returns Promise that resolves to an array of {@link PrivyWallet} instances\n * @throws Error if wallets cannot be retrieved\n */\n async getAllWallets(options?: PrivyProviderGetAllWalletsOptions): Promise<PrivyWallet[]> {\n try {\n const response = await this.privy.walletApi.getWallets({\n limit: options?.limit,\n cursor: options?.cursor,\n });\n\n return response.data.map((wallet) => {\n const walletInstance = new PrivyWallet(\n this.privy,\n wallet.id,\n getAddress(wallet.address),\n this.chainManager,\n );\n return walletInstance;\n });\n } catch {\n throw new Error('Failed to retrieve wallets');\n }\n }\n}\n","import type { PrivyClient } from '@privy-io/server-auth';\nimport { createViemAccount, type GetViemAccountInputType } from '@privy-io/server-auth/viem';\nimport {\n type Address,\n createWalletClient,\n type Hash,\n http,\n type LocalAccount,\n type WalletClient,\n} from 'viem';\nimport { unichain } from 'viem/chains';\n\nimport type { SupportedChainId } from '@/constants/chains';\nimport type { ChainManager } from '@/tools/ChainManager';\nimport { EmbeddedWallet } from '@/wallet/base/wallets/EmbeddedWallet';\nimport type { TransactionData } from '@/types/transaction';\nimport { logger } from '@/tools/Logger';\n\n/**\n * Internal embedded wallet implementation backed by Privy\n *\n * @internal\n * @category Wallets\n * @remarks\n * Wraps Privy’s server-auth wallet to expose a viem-compatible {@link LocalAccount}\n * and {@link WalletClient}\n * Not exported in the public API — composed by higher-level providers/namespaces\n */\nexport class PrivyWallet extends EmbeddedWallet {\n /** Privy wallet ID */\n public override walletId: string;\n /** Privy client instance */\n private privyClient: PrivyClient;\n /** Network and client manager */\n private chainManager: ChainManager;\n /**\n * Creates a Privy-backed embedded wallet\n *\n * @internal\n * @param privyClient Privy client used to access wallet and signing APIs\n * @param walletId Privy wallet identifier\n * @param address Wallet EVM address\n * @param chainManager Chain and client manager\n */\n constructor(\n privyClient: PrivyClient,\n walletId: string,\n address: Address,\n chainManager: ChainManager,\n ) {\n super(address, walletId);\n this.privyClient = privyClient;\n this.walletId = walletId;\n this.chainManager = chainManager;\n }\n\n /**\n * Returns a viem-compatible {@link LocalAccount} for this Privy wallet\n *\n * @internal\n * @category Accounts\n * @remarks\n * Uses Privy’s signing infra under the hood while exposing the standard viem interface\n *\n * @returns Promise that resolves to a {@link LocalAccount}\n * @throws Error if wallet retrieval or account construction fails\n */\n async account(): Promise<LocalAccount> {\n const account = await createViemAccount({\n walletId: this.walletId,\n address: this.address,\n\n privy: this.privyClient as unknown as GetViemAccountInputType['privy'],\n });\n return account;\n }\n\n /**\n * Creates a viem {@link WalletClient} for a given chain\n *\n * @internal\n * @category Accounts\n * @param chainId Target chain ID\n * @returns Promise that resolves to a {@link WalletClient}\n * @throws Error if the chain is unsupported or client creation fails\n */\n async walletClient(chainId: SupportedChainId): Promise<WalletClient> {\n const account = await this.account();\n return createWalletClient({\n account,\n chain: this.chainManager.getChain(chainId),\n transport: http(this.chainManager.getRpcUrl(chainId)),\n });\n }\n\n /**\n * Signs a transaction without broadcasting it\n *\n * @internal\n * @category Signing\n * @param transactionData Transaction payload to sign\n * @returns Promise that resolves to a signed transaction hex string\n */\n async sign(transactionData: TransactionData): Promise<`0x${string}`> {\n return (await this.signOnly(transactionData)) as `0x${string}`;\n }\n\n /**\n * Produces a signed transaction using Privy’s wallet API without sending it\n *\n * @internal\n * @category Signing\n * @remarks\n * Estimates gas, fees, and nonce to build a complete EIP-1559 transaction\n * Per Privy docs, if any gas field is set, all must be set\n *\n * @param transactionData Transaction payload to sign\n * @returns Promise that resolves to a signed transaction string\n * @throws Error if signing fails\n */\n async signOnly(transactionData: TransactionData): Promise<string> {\n try {\n const privyWallet = await this.privyClient.walletApi.getWallet({\n id: this.walletId,\n });\n // Get public client for gas estimation\n const publicClient = this.chainManager.getPublicClient(unichain.id); // Unichain\n\n // Estimate gas limit\n const gasLimit = await publicClient.estimateGas({\n account: privyWallet.address as Address,\n to: transactionData.to,\n data: transactionData.data as `0x${string}`,\n value: BigInt(transactionData.value || 0),\n });\n\n // Get current gas price and fee data\n const feeData = await publicClient.estimateFeesPerGas();\n\n // Get current nonce for the wallet - manual management since Privy isn't handling it properly\n const nonce = await publicClient.getTransactionCount({\n address: privyWallet.address as Address,\n blockTag: 'pending', // Use pending to get the next nonce including any pending txs\n });\n\n // According to Privy docs: if you provide ANY gas parameters, you must provide ALL of them\n const txParams: any = {\n to: transactionData.to,\n data: transactionData.data as `0x${string}`,\n value: transactionData.value,\n chainId: 130, // Unichain\n type: 2, // EIP-1559\n gasLimit: `0x${gasLimit.toString(16)}`,\n maxFeePerGas: `0x${(feeData.maxFeePerGas || BigInt(1000000000)).toString(16)}`, // fallback to 1 gwei\n maxPriorityFeePerGas: `0x${(feeData.maxPriorityFeePerGas || BigInt(100000000)).toString(16)}`, // fallback to 0.1 gwei\n nonce: `0x${nonce.toString(16)}`, // Explicitly provide the correct nonce\n };\n\n logger.info(\n 'Complete tx params: ',\n {\n txParamsType: txParams.type,\n txParamsNonce: nonce,\n txParamsLimit: gasLimit,\n txParamsMaxFee: feeData.maxFeePerGas || 'fallback',\n txParamsPriority: feeData.maxPriorityFeePerGas || 'fallback',\n },\n 'PrivyWallet',\n );\n\n const response = await this.privyClient.walletApi.ethereum.signTransaction({\n walletId: this.walletId,\n transaction: txParams,\n });\n\n return response.signedTransaction;\n } catch (error) {\n throw new Error(\n `Failed to sign transaction for wallet ${this.walletId}: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`,\n );\n }\n }\n\n /**\n * Broadcasts a previously-signed transaction\n *\n * @internal\n * @category Sending\n * @param signedTransaction Signed transaction hex\n * @param publicClient Viem public client to send the transaction\n * @returns Promise that resolves to the transaction {@link Hash}\n * @throws Error if submission fails\n */\n async send(signedTransaction: string, publicClient: any): Promise<Hash> {\n try {\n const hash = await publicClient.sendRawTransaction({\n serializedTransaction: signedTransaction as `0x${string}`,\n });\n return hash;\n } catch (error) {\n throw new Error(\n `Failed to send transaction: ${error instanceof Error ? error.message : 'Unknown error'}`,\n );\n }\n }\n}\n","import type { Address, LocalAccount, WalletClient } from 'viem';\n\nimport type { SupportedChainId } from '@/constants/chains';\n\n/**\n * Abstract base class for embedded wallet implementations\n *\n * @internal\n * @category Wallets\n * @remarks\n * Provides a standard interface for embedded wallets (Privy, Dynamic, etc.)\n * Can be used as a signer for smart wallets when the embedded wallet is an owner\n */\nexport abstract class EmbeddedWallet {\n /** Ethereum address of the wallet */\n public readonly address: Address;\n /** Optional provider-specific wallet identifier */\n public readonly walletId?: string;\n\n /**\n * Creates an embedded wallet instance\n *\n * @internal\n * @param address Ethereum address of the wallet\n * @param walletId Optional provider-specific identifier\n */\n constructor(address: Address, walletId?: string) {\n this.address = address;\n this.walletId = walletId;\n }\n\n /**\n * Returns a {@link LocalAccount} that can sign transactions and messages\n *\n * @internal\n * @category Accounts\n * @remarks\n * Useful for smart wallet operations if the embedded wallet is included as an owner\n *\n * @returns Promise resolving to a {@link LocalAccount}\n */\n abstract account(): Promise<LocalAccount>;\n\n /**\n * Returns a {@link WalletClient} for interacting with contracts on a specific chain\n *\n * @internal\n * @category Accounts\n * @param chainId Target chain ID\n * @returns Promise resolving to a {@link WalletClient} configured for the given chain\n */\n abstract walletClient(chainId: SupportedChainId): Promise<WalletClient>;\n}\n","import type { EmbeddedWallet } from '@/wallet/base/wallets/EmbeddedWallet';\n\n/**\n * Abstract base class for embedded wallet providers\n *\n * @internal\n * @category Wallet Providers\n * @remarks\n * Defines the interface for providers that manage {@link EmbeddedWallet} instances\n * Extended by implementations such as {@link PrivyEmbeddedWalletProvider}\n */\nexport abstract class EmbeddedWalletProvider {\n /**\n * Creates a new embedded wallet instance\n *\n * @internal\n * @category Creation\n * @remarks\n * Uses the provider’s infrastructure to provision a new embedded wallet ready for signing\n *\n * @returns Promise resolving to a new {@link EmbeddedWallet}\n */\n abstract createWallet(): Promise<EmbeddedWallet>;\n\n /**\n * Retrieves an existing embedded wallet by its unique identifier\n *\n * @internal\n * @category Retrieval\n * @remarks\n * The wallet must have been created previously through this provider\n *\n * @param params Wallet retrieval parameters\n * @param params.walletId Unique identifier for the embedded wallet\n * @returns Promise resolving to an {@link EmbeddedWallet}\n * @throws Error if no wallet with the specified ID exists\n */\n abstract getWallet(params: { walletId: string }): Promise<EmbeddedWallet>;\n}\n","import type { ChainManager } from '@/tools/ChainManager';\nimport {\n type Address,\n type LocalAccount,\n erc20Abi,\n createWalletClient,\n http,\n parseGwei,\n} from 'viem';\nimport type { SupportedChainId } from '@/constants/chains';\nimport type { SmartWallet } from '@/wallet/base/wallets/SmartWallet';\nimport type { VaultInfo, VaultBalance, VaultTxnResult } from '@/types/protocols/general';\n\n/**\n * Base Protocol\n *\n * @internal\n * @abstract\n * @category Protocols\n * @remarks\n * Abstract class defining the contract for protocol integrations (e.g. Spark, Beefy, Aave, Morpho)\n * Provides lifecycle hooks (`init`) and required methods for vault discovery, deposit, withdrawal,\n * and balance tracking\n *\n * Generic parameters allow protocol-specific typing for vault info, balances, and transaction results\n */\nexport abstract class BaseProtocol<\n TVaultInfo extends VaultInfo = VaultInfo,\n TVaultBalance extends VaultBalance = VaultBalance,\n TVaultTxnResult extends VaultTxnResult = VaultTxnResult,\n> {\n /** Chain manager instance injected during initialization */\n public chainManager: ChainManager | undefined;\n\n /**\n * Initialize the protocol\n * @param chainManager Chain manager for accessing RPC and bundler clients\n */\n abstract init(chainManager: ChainManager): Promise<void>;\n\n /**\n * Ensure the protocol has been initialized\n * @throws Error if `init()` has not been called\n */\n protected ensureInitialized(): void {\n if (!this.chainManager) {\n throw new Error('Protocol must be initialized before use. Call init() first.');\n }\n }\n\n /**\n * Get all available vaults\n * @returns List of vaults that support deposits\n */\n abstract getVaults(): Promise<TVaultInfo[]> | TVaultInfo[];\n\n /**\n * Get the best vault for deposits\n * @returns Single vault considered optimal for deposit\n */\n abstract getBestVault(): Promise<TVaultInfo> | TVaultInfo;\n\n /**\n * Get a vault where funds may already be deposited\n * @param smartWallet Wallet to check for existing deposits\n * @returns Vault info if deposits exist, otherwise null\n */\n abstract fetchDepositedVaults(smartWallet: SmartWallet): Promise<TVaultInfo | null>;\n\n /**\n * Deposit funds into a vault\n * @param amount Amount in human-readable format\n * @param smartWallet Wallet executing the deposit\n * @returns Result of the deposit transaction\n */\n abstract deposit(amount: string, smartWallet: SmartWallet): Promise<TVaultTxnResult>;\n\n /**\n * Withdraw funds from a vault\n * @param amountInShares Amount of shares to withdraw\n * @param smartWallet Wallet executing the withdrawal\n * @returns Result of the withdrawal transaction\n */\n abstract withdraw(amountInShares: string, smartWallet: SmartWallet): Promise<TVaultTxnResult>;\n\n /**\n * Get deposited balance in a vault\n * @param vaultInfo Vault info for a selected protocol\n * @param walletAddress Wallet address to check the balance of\n * @returns Balance of deposited funds\n */\n abstract getBalance(vaultInfo: TVaultInfo, walletAddress: Address): Promise<TVaultBalance>;\n\n /**\n * Approve a token for protocol use\n * @param tokenAddress Token address\n * @param spenderAddress Spender address\n * @param amount Allowance amount in wei\n * @param chainId Target chain ID\n * @param account Account authorizing the approval\n * @returns Transaction hash\n */\n protected async approveToken(\n tokenAddress: Address,\n spenderAddress: Address,\n amount: bigint,\n chainId: SupportedChainId,\n account: LocalAccount,\n ): Promise<string> {\n this.ensureInitialized();\n\n const walletClient = createWalletClient({\n account,\n chain: this.chainManager!.getChain(chainId),\n transport: http(this.chainManager!.getRpcUrl(chainId)),\n });\n\n const hash = await walletClient.writeContract({\n address: tokenAddress,\n abi: erc20Abi,\n functionName: 'approve',\n args: [spenderAddress, amount],\n gas: 100000n,\n maxFeePerGas: parseGwei('20'),\n maxPriorityFeePerGas: parseGwei('2'),\n });\n\n return hash;\n }\n\n /**\n * Check token allowance for a spender\n * @param tokenAddress Token address\n * @param spenderAddress Spender address\n * @param walletAddress Wallet address granting allowance\n * @param chainId Target chain ID\n * @returns Current allowance amount\n */\n protected async checkAllowance(\n tokenAddress: Address,\n spenderAddress: Address,\n walletAddress: Address,\n chainId: SupportedChainId,\n ): Promise<bigint> {\n this.ensureInitialized();\n\n const publicClient = this.chainManager!.getPublicClient(chainId);\n\n return await publicClient.readContract({\n address: tokenAddress,\n abi: erc20Abi,\n functionName: 'allowance',\n args: [walletAddress, spenderAddress],\n });\n }\n}\n","import { BaseProtocol } from '@/protocols/base/BaseProtocol';\nimport type { ChainManager } from '@/tools/ChainManager';\nimport type { SupportedChainId } from '@/constants/chains';\nimport type { SmartWallet } from '@/wallet/base/wallets/SmartWallet';\nimport type {\n SparkVaultInfo,\n SparkVaultTxnResult,\n SparkVaultBalance,\n} from '@/types/protocols/spark';\n\nimport {\n type Address,\n encodeFunctionData,\n erc20Abi,\n formatUnits,\n parseUnits,\n type PublicClient,\n} from 'viem';\n\nimport { SPARK_VAULT_ABI, SPARK_SSR_ORACLE_ABI } from '@/abis/protocols/spark';\nimport {\n RAY,\n SECONDS_PER_YEAR,\n SPARK_SSR_ORACLE_ADDRESS,\n SPARK_VAULT,\n} from '@/protocols/constants/spark';\nimport { logger } from '@/tools/Logger';\n\n/**\n * @internal\n * @category Protocols\n * @class SparkProtocol\n * @classdesc\n * Internal implementation of the Spark Protocol adapter\n * Provides ERC-4626 vault management including deposits, withdrawals, and balance tracking\n * Used by the SDK to interact with Spark-based yield vaults\n */\nexport class SparkProtocol extends BaseProtocol<\n SparkVaultInfo,\n SparkVaultBalance,\n SparkVaultTxnResult\n> {\n private selectedChainId: SupportedChainId | undefined;\n private allVaults: SparkVaultInfo[] = [];\n private publicClient: PublicClient | undefined;\n\n /**\n * Initialize the Spark protocol with the provided chain manager\n * @param chainManager Chain manager instance used for network operations\n */\n async init(chainManager: ChainManager): Promise<void> {\n this.chainManager = chainManager;\n this.selectedChainId = chainManager.getSupportedChain();\n\n this.publicClient = chainManager.getPublicClient(this.selectedChainId!);\n\n this.allVaults = this.getVaults();\n }\n\n /**\n * Get the SSR (Sky Saving Rate) of the Spark protocol\n * @remarks\n * The parameter ius necessary to calculate the APY of a vault\n * @returns\n */\n private async getSSR(): Promise<number> {\n if (!this.publicClient) {\n throw new Error('Public client not initialized');\n }\n\n const ssrRaw = await this.publicClient.readContract({\n address: SPARK_SSR_ORACLE_ADDRESS,\n abi: SPARK_SSR_ORACLE_ABI,\n functionName: 'getSSR',\n });\n\n const ssr = Number(ssrRaw) / Number(RAY);\n return ssr;\n }\n\n /**\n * Get the APY of the Spark protocol\n * @remarks\n * Calculation based on the formula from the documentation:\n * https://docs.spark.fi/dev/integration-guides/susds-lending-market#rates\n * @returns The APY of the Spark protocol in percentage\n */\n async getAPY(): Promise<number> {\n const ssr = await this.getSSR();\n\n const apy = Math.exp(Math.log(ssr) * SECONDS_PER_YEAR) - 1;\n\n return Number((apy * 100).toFixed(2));\n }\n\n /**\n *\n * Get all vault info from a Spark protocol\n * @returns The list of vaults\n */\n getVaults(): SparkVaultInfo[] {\n return SPARK_VAULT;\n }\n\n /**\n * Get the best available Spark vault\n * @returns The top-ranked Spark vault\n * @throws Error if no vaults found\n */\n async getBestVault(): Promise<SparkVaultInfo> {\n if (this.allVaults.length === 0) {\n throw new Error('No vaults found');\n }\n\n // Currently, the vault is only one and relates to sUSDC\n // More Spark vaults can be added in the future, but the APY calculation will remain the same\n const selectedVault = this.allVaults[0]!;\n\n // The APY for Spark vaults calculates the same for all vaults\n selectedVault.metadata!.apy = await this.getAPY();\n\n return selectedVault;\n }\n\n /**\n * Fetch a vault where the user previously deposited funds\n * @param smartWallet Smart wallet to inspect\n * @returns The vault with user deposits, or null if none found\n */\n async fetchDepositedVaults(smartWallet: SmartWallet): Promise<SparkVaultInfo | null> {\n let depositedVault: SparkVaultInfo | undefined = undefined;\n const userAddress = await smartWallet.getAddress();\n for (const vault of this.allVaults) {\n const balance = await this.getBalance(vault, userAddress);\n if (parseInt(balance.depositedAmount) > 0) {\n depositedVault = vault;\n }\n }\n\n if (depositedVault) {\n depositedVault.metadata!.apy = await this.getAPY();\n }\n logger.info('Deposited vaults:', { depositedVault }, 'SparkProtocol');\n\n return depositedVault || null;\n }\n\n /**\n * Deposit funds into a Spark vault\n * @param amount Amount to deposit (human-readable)\n * @param smartWallet Smart wallet instance to use\n * @returns Transaction result with hash\n */\n async deposit(amount: string, smartWallet: SmartWallet): Promise<SparkVaultTxnResult> {\n // Check if a user deposited previously to any vault of the protocol\n const depositedVault = await this.fetchDepositedVaults(smartWallet);\n\n let vaultInfoToDeposit: SparkVaultInfo;\n logger.info('Previously deposited vault:', { depositedVault }, 'SparkProtocol');\n if (depositedVault) {\n vaultInfoToDeposit = depositedVault;\n } else {\n // Find the best pool to deposit for a protocol\n vaultInfoToDeposit = await this.getBestVault();\n logger.info('Best vault that found:', { bestVault: vaultInfoToDeposit }, 'SparkProtocol');\n }\n\n const owner = await smartWallet.getAddress();\n const assets = parseUnits(amount, vaultInfoToDeposit.depositTokenDecimals);\n logger.info('Raw deposit amount:', { amount, assets }, 'SparkProtocol');\n\n const allowance = await this.checkAllowance(\n vaultInfoToDeposit.depositTokenAddress,\n vaultInfoToDeposit.vaultAddress,\n owner,\n this.selectedChainId!,\n );\n\n logger.info('Current vault contract allowance:', { allowance }, 'SparkProtocol');\n\n const ops: { to: Address; data: `0x${string}` }[] = [];\n\n if (allowance < assets) {\n ops.push({\n to: vaultInfoToDeposit.depositTokenAddress,\n data: encodeFunctionData({\n abi: erc20Abi,\n functionName: 'approve',\n args: [vaultInfoToDeposit.vaultAddress, assets],\n }),\n });\n }\n ops.push({\n to: vaultInfoToDeposit.vaultAddress,\n data: encodeFunctionData({\n abi: SPARK_VAULT_ABI,\n functionName: 'deposit',\n args: [assets, owner] as const,\n }),\n });\n\n const hash = await smartWallet.sendBatch(ops, this.selectedChainId!);\n return { success: true, hash };\n }\n\n /**\n * Withdraw funds from a Spark vault\n * @param amountInUnderlying Amount in base token units (or undefined to withdraw all)\n * @param smartWallet Smart wallet instance to withdraw from\n * @returns Transaction result with hash\n * @throws Error if no deposited vault found\n */\n async withdraw(\n amountInUnderlying: string | undefined,\n smartWallet: SmartWallet,\n ): Promise<SparkVaultTxnResult> {\n const depositedVault = await this.fetchDepositedVaults(smartWallet);\n\n if (!depositedVault) {\n throw new Error('No vault found to withdraw from');\n }\n\n const owner = await smartWallet.getAddress();\n\n let withdrawData: { to: Address; data: `0x${string}` };\n\n if (amountInUnderlying) {\n const assets = parseUnits(amountInUnderlying, depositedVault.depositTokenDecimals);\n logger.info('Withdraw amount:', { amountInUnderlying, assets }, 'SparkProtocol');\n withdrawData = {\n to: depositedVault.vaultAddress,\n data: encodeFunctionData({\n abi: SPARK_VAULT_ABI,\n functionName: 'withdraw',\n args: [assets, owner, owner] as const,\n }),\n };\n } else {\n const maxShares = await this.getMaxRedeemableShares(depositedVault, owner);\n logger.info('Withdrawing all funds:', { maxShares }, 'SparkProtocol');\n withdrawData = {\n to: depositedVault.vaultAddress,\n data: encodeFunctionData({\n abi: SPARK_VAULT_ABI,\n functionName: 'redeem',\n args: [maxShares, owner, owner] as const,\n }),\n };\n }\n\n const hash = await smartWallet.send(withdrawData, this.selectedChainId!);\n logger.info('Withdraw transaction sent:', { hash }, 'SparkProtocol');\n return { success: true, hash };\n }\n\n /**\n * Get the maximum redeemable shares for a wallet\n * @param vaultInfo Vault information\n * @param walletAddress Wallet address to check\n * @returns Maximum redeemable shares as bigint\n */\n private async getMaxRedeemableShares(\n vaultInfo: SparkVaultInfo,\n walletAddress: Address,\n ): Promise<bigint> {\n if (!this.publicClient) {\n throw new Error('Public client not initialized');\n }\n\n const shares = await this.publicClient.readContract({\n address: vaultInfo.vaultAddress,\n abi: SPARK_VAULT_ABI,\n functionName: 'balanceOf',\n args: [walletAddress],\n });\n\n return shares;\n }\n\n /**\n * Get amount that a wallet has deposited in a vault\n * @param vaultInfo Vault information\n * @param walletAddress Wallet address to check\n * @returns Object containing shares and deposited amount\n */\n async getBalance(vaultInfo: SparkVaultInfo, walletAddress: Address): Promise<SparkVaultBalance> {\n if (!this.publicClient) {\n throw new Error('Public client not initialized');\n }\n\n const shares = await this.publicClient.readContract({\n address: vaultInfo.vaultAddress,\n abi: SPARK_VAULT_ABI,\n functionName: 'balanceOf',\n args: [walletAddress],\n });\n\n if (shares === 0n) {\n return { shares: '0', depositedAmount: '0', vaultInfo };\n }\n\n const assets = await this.publicClient.readContract({\n address: vaultInfo.vaultAddress,\n abi: SPARK_VAULT_ABI,\n functionName: 'convertToAssets',\n args: [shares],\n });\n\n return {\n shares: formatUnits(shares, vaultInfo.earnTokenDecimals),\n depositedAmount: formatUnits(assets, vaultInfo.depositTokenDecimals),\n vaultInfo,\n };\n }\n}\n","export const SPARK_VAULT_ABI = [\n { type: 'function', name: 'asset', stateMutability: 'view', inputs: [], outputs: [{ type: 'address' }] },\n { type: 'function', name: 'totalAssets', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint256' }] },\n { type: 'function', name: 'convertToShares', stateMutability: 'view', inputs: [{ name: 'assets', type: 'uint256' }], outputs: [{ type: 'uint256' }] },\n { type: 'function', name: 'convertToAssets', stateMutability: 'view', inputs: [{ name: 'shares', type: 'uint256' }], outputs: [{ type: 'uint256' }] },\n { type: 'function', name: 'balanceOf', stateMutability: 'view', inputs: [{ name: 'owner', type: 'address' }], outputs: [{ type: 'uint256' }] },\n\n { type: 'function', name: 'deposit', stateMutability: 'nonpayable', inputs: [\n { name: 'assets', type: 'uint256' },\n { name: 'receiver', type: 'address' }\n ], outputs: [{ type: 'uint256' }] },\n { type: 'function', name: 'withdraw', stateMutability: 'nonpayable', inputs: [\n { name: 'assets', type: 'uint256' },\n { name: 'receiver', type: 'address' },\n { name: 'owner', type: 'address' }\n ], outputs: [{ type: 'uint256' }] },\n { type: 'function', name: 'redeem', stateMutability: 'nonpayable', inputs: [\n { name: 'shares', type: 'uint256' },\n { name: 'receiver', type: 'address' },\n { name: 'owner', type: 'address' }\n ], outputs: [{ type: 'uint256' }] },\n] as const;\n\n\n\nexport const SPARK_SSR_ORACLE_ABI = [\n {\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},\n {\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},\n {\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},\n {\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},\n {\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},\n {\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},\n {\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maxSSR\",\"type\":\"uint256\"}],\"name\":\"SetMaxSSR\",\"type\":\"event\"},\n {\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"ssr\",\"type\":\"uint96\"},{\"internalType\":\"uint120\",\"name\":\"chi\",\"type\":\"uint120\"},{\"internalType\":\"uint40\",\"name\":\"rho\",\"type\":\"uint40\"}],\"indexed\":false,\"internalType\":\"struct ISSROracle.SUSDSData\",\"name\":\"nextData\",\"type\":\"tuple\"}],\"name\":\"SetSUSDSData\",\"type\":\"event\"},\n {\"inputs\":[],\"name\":\"DATA_PROVIDER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[],\"name\":\"getAPR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[],\"name\":\"getChi\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getConversionRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[],\"name\":\"getConversionRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getConversionRateBinomialApprox\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[],\"name\":\"getConversionRateBinomialApprox\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getConversionRateLinearApprox\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[],\"name\":\"getConversionRateLinearApprox\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[],\"name\":\"getRho\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[],\"name\":\"getSSR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[],\"name\":\"getSUSDSData\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"ssr\",\"type\":\"uint96\"},{\"internalType\":\"uint120\",\"name\":\"chi\",\"type\":\"uint120\"},{\"internalType\":\"uint40\",\"name\":\"rho\",\"type\":\"uint40\"}],\"internalType\":\"struct ISSROracle.SUSDSData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},\n {\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[],\"name\":\"maxSSR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},\n {\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},\n {\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_maxSSR\",\"type\":\"uint256\"}],\"name\":\"setMaxSSR\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},\n {\"inputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"ssr\",\"type\":\"uint96\"},{\"internalType\":\"uint120\",\"name\":\"chi\",\"type\":\"uint120\"},{\"internalType\":\"uint40\",\"name\":\"rho\",\"type\":\"uint40\"}],\"internalType\":\"struct ISSROracle.SUSDSData\",\"name\":\"nextData\",\"type\":\"tuple\"}],\"name\":\"setSUSDSData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},\n {\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}\n] as const;","import type { SparkVaultInfo } from '@/types/protocols/spark';\n\nexport const SPARK_SSR_ORACLE_ADDRESS = '0x65d946e533748A998B1f0E430803e39A6388f7a1';\n\nexport const SPARK_VAULT: SparkVaultInfo[] = [\n {\n id: 'sUSDC',\n chain: 'base',\n vaultAddress: '0x3128a0f7f0ea68e7b7c9b00afa7e41045828e858',\n depositTokenAddress: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913',\n depositTokenDecimals: 6,\n depositTokenSymbol: 'USDC',\n earnTokenAddress: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913',\n earnTokenDecimals: 18,\n earnTokenSymbol: 'sUSDC',\n metadata: {},\n },\n];\n\nexport const SECONDS_PER_YEAR = 60 * 60 * 24 * 365;\nexport const RAY = BigInt('1000000000000000000000000000');\n","import { SparkProtocol } from '@/protocols/implementations/SparkProtocol';\nimport type { Protocol } from '@/types/protocols/general';\n\n/**\n * Current config of protocols should have correct supportedChains array as it used to:\n * 1. Fetch vaults per chain to find the best vault for the protocol\n * 2. Deposit funds of users to a best found vault\n */\nexport const availableProtocols: Protocol[] = [\n {\n info: {\n id: 'spark',\n name: 'Spark',\n website: 'https://spark.fi/',\n logo: '/logos/spark.png',\n supportedChains: [1, 8453, 42161],\n riskLevel: 'low',\n isPremium: false,\n },\n instance: new SparkProtocol(),\n },\n];\n","import type { ProtocolsRouterConfig } from '@/types/protocols/general';\nimport { logger } from '@/tools/Logger';\n\n/**\n * Utility class for validating API keys used in protocol configurations\n *\n * @internal\n * @category Utilities\n * @remarks\n * API keys may be required for accessing premium protocols with higher APY\n * Validation helps prevent invalid configurations and potential security risks\n */\nexport class ApiKeysValidator {\n // TODO: Implement the validation logic\n\n /**\n * Validates whether the provided API key is valid\n *\n * @internal\n * @param apiKey API key from {@link ProtocolsRouterConfig}\n * @returns True if the API key is considered valid\n */\n validate(apiKey: ProtocolsRouterConfig['apiKey']) {\n logger.info('Validating api key...', apiKey, 'ApiKeysValidator');\n return true;\n }\n}\n","import type { SupportedChainId } from '@/constants/chains';\nimport type { ChainManager } from '@/tools/ChainManager';\nimport { ApiKeysValidator } from '@/tools/ApiKeysValidator';\nimport type { Protocol, ProtocolsRouterConfig } from '@/types/protocols/general';\n\n/**\n * Base Protocol Router\n *\n * @internal\n * @abstract\n * @category Protocols\n * @remarks\n * Abstract base class for protocol router implementations such as Spark, Beefy, Aave, Morpho, etc\n * Provides a standard interface for selecting protocols based on configuration parameters\n */\nexport abstract class ProtocolRouterBase {\n /** Required risk level specified by the integrator */\n public readonly riskLevel: ProtocolsRouterConfig['riskLevel'];\n\n /** Minimum APY required by the integrator */\n public readonly minApy?: ProtocolsRouterConfig['minApy'];\n\n /** API key to access premium protocols with higher yields */\n public readonly apiKey?: string; // TODO: Add an API key validation\n\n /** API key validator instance */\n public readonly apiKeyValidator: ApiKeysValidator = new ApiKeysValidator();\n\n /** Chain manager instance for network access */\n public readonly chainManager: ChainManager;\n\n /**\n * Initialize a base protocol router\n * @param riskLevel Risk level required by the integrator\n * @param chainManager Chain manager instance for network operations\n * @param minApy Optional minimum APY filter\n * @param apiKey Optional API key for premium protocol access\n */\n constructor(\n riskLevel: ProtocolsRouterConfig['riskLevel'],\n chainManager: ChainManager,\n minApy?: ProtocolsRouterConfig['minApy'],\n apiKey?: ProtocolsRouterConfig['apiKey'],\n ) {\n this.riskLevel = riskLevel;\n this.minApy = minApy;\n this.apiKey = apiKey;\n this.chainManager = chainManager;\n }\n\n /**\n * Get all supported protocols\n * @returns Array of protocols supported by this router\n */\n abstract getProtocols(): Protocol[];\n\n /**\n * Check if the given chains are supported by the router\n * @param chainIds List of chain IDs to check\n * @returns True if at least one chain is supported\n */\n abstract isProtocolSupportedChain(chainIds: SupportedChainId[]): boolean;\n\n /**\n * Recommend the most suitable protocol based on router configuration\n * Returns a protocol that best matches the configured risk level, APY, and chain support\n * @returns Protocol instance considered the best match\n */\n abstract recommend(): Protocol;\n}\n","import type { SupportedChainId } from '@/constants/chains';\nimport { availableProtocols } from '@/constants/protocols';\nimport { ProtocolRouterBase } from '@/router/base/ProtocolRouterBase';\nimport type { ChainManager } from '@/tools/ChainManager';\nimport type { Protocol, ProtocolsRouterConfig } from '@/types/protocols/general';\n\n/**\n * Protocol Router\n *\n * @internal\n * @category Protocols\n * @remarks\n * Selects and recommends protocols for yield strategies based on router configuration,\n * available protocols, and API key for paid protocols\n */\nexport class ProtocolRouter extends ProtocolRouterBase {\n /**\n * Initialize the protocol router\n * @param config Router configuration including risk level, min APY, and optional API key\n * @param chainManager Chain manager instance for network validation\n */\n constructor(config: ProtocolsRouterConfig, chainManager: ChainManager) {\n super(config.riskLevel, chainManager, config.minApy, config.apiKey);\n }\n /**\n * Get all protocols available for the current configuration\n *\n * Includes all non-premium protocols and premium protocols if the API key is valid\n * @returns Array of available protocol definitions\n */\n getProtocols(): Protocol[] {\n const isKeyValid = this.apiKeyValidator.validate(this.apiKey);\n\n // Filter protocols based on two conditions:\n // 1. Include all non-premium protocols\n // 2. Include premium protocols only if API key is valid\n const allAvailableProtocols = availableProtocols.filter((protocol) => {\n // Always include non-premium protocols\n if (!protocol.info.isPremium) {\n return true;\n }\n\n // Include premium protocols only if API key is valid\n return protocol.info.isPremium && isKeyValid;\n });\n\n return allAvailableProtocols;\n }\n\n /**\n * Check if any protocol supports a given set of chains\n * @param chainIds List of chain IDs to validate\n * @returns True if at least one chain is supported by the router\n */\n isProtocolSupportedChain(chainIds: SupportedChainId[]): boolean {\n return chainIds.some((chainId) => this.chainManager.getSupportedChain() === chainId);\n }\n\n /**\n * Recommend the best protocol for the current router configuration\n *\n * Filters available protocols by risk level and supported chains. More criteria will be added later on\n *\n *\n * @remarks\n * Currently returns the first match. Future improvements will add\n * smarter sorting and pool-based APY checks\n *\n * @throws Error if no protocols are available for the current risk level\n * @returns Protocol instance considered the best match\n */\n recommend(): Protocol {\n const protocols = this.getProtocols();\n\n // TODO: Implement the recommendation logic => fetch pools for each protocol and then check APY for each pool to make sure the protocols is the best suited for the given router config\n // Filter protocols that match the risk level. Later on add more conditions for the recommendation\n const eligibleProtocols = protocols.filter((protocol) => {\n // Check if protocol matches risk level\n const riskMatches = protocol.info.riskLevel === this.riskLevel;\n\n const isSupportedChain = this.isProtocolSupportedChain(protocol.info.supportedChains);\n\n return riskMatches && isSupportedChain;\n });\n\n if (eligibleProtocols.length === 0) {\n throw new Error(`No protocols available for risk level: ${this.riskLevel}`);\n }\n\n // TODO: Add a smarter sorting of protocols here and then return the best one\n // For now, we just return the first protocol that matches the risk level\n const bestProtocol = eligibleProtocols[0];\n\n return bestProtocol!;\n }\n}\n","import { generateJwt } from '@coinbase/cdp-sdk/auth';\nimport axios, { type AxiosInstance, type AxiosResponse } from 'axios';\nimport type {\n CoinbaseCDPAuthParams,\n OnRampUrlResponse,\n CoinbaseCDPError,\n RampConfigResponse,\n OffRampUrlResponse,\n} from '@/types/ramp';\nimport type { Address } from 'viem';\nimport type { ChainManager } from '@/tools/ChainManager';\nimport { checkValidUrl } from '@/utils/urls';\nimport { chainById } from '@/utils/chains';\n\nexport class CoinbaseCDP {\n private readonly apiKeyId: string;\n private readonly apiKeySecret: string;\n private readonly chainManager: ChainManager;\n private readonly integratorId: string;\n\n private readonly coinbaseCdpV2Hostname: string = 'https://api.cdp.coinbase.com';\n private readonly coinbaseCdpV1Hostname: string = 'https://api.developer.coinbase.com';\n\n private readonly onRampUrlAuthParams: CoinbaseCDPAuthParams = {\n requestMethod: 'POST',\n requestHost: 'api.cdp.coinbase.com',\n requestPath: '/platform/v2/onramp/sessions',\n expiresIn: 120,\n };\n\n private readonly onRampConfigAuthParams: CoinbaseCDPAuthParams = {\n requestMethod: 'GET',\n requestHost: 'api.developer.coinbase.com',\n requestPath: '/onramp/v1/buy/config',\n expiresIn: 120,\n };\n\n private readonly offRampUrlAuthParams: CoinbaseCDPAuthParams = {\n requestMethod: 'POST',\n requestHost: 'api.developer.coinbase.com',\n requestPath: '/onramp/v1/sell/quote',\n expiresIn: 120,\n };\n\n private readonly offRampConfigAuthParams: CoinbaseCDPAuthParams = {\n requestMethod: 'GET',\n requestHost: 'api.developer.coinbase.com',\n requestPath: '/onramp/v1/sell/config',\n expiresIn: 120,\n };\n\n private readonly clientV2: AxiosInstance = axios.create({\n baseURL: this.coinbaseCdpV2Hostname,\n });\n private readonly clientV1: AxiosInstance = axios.create({\n baseURL: this.coinbaseCdpV1Hostname,\n });\n constructor(\n apiKeyId: string,\n apiKeySecret: string,\n integratorId: string,\n chainManager: ChainManager,\n ) {\n this.apiKeyId = apiKeyId;\n this.apiKeySecret = apiKeySecret;\n this.chainManager = chainManager;\n this.integratorId = integratorId;\n\n this.verifyParameters();\n }\n\n private verifyParameters(): void {\n if (!this.apiKeyId || !this.apiKeySecret || !this.integratorId) {\n throw new Error('API key ID, secret and integrator ID are required');\n }\n }\n\n /**\n * @internal\n * Generate a JWT token for a provided API endpoint and hostname to make a request after\n * @category Ramp\n *\n * @param authParams Authentication parameters\n * @returns JWT token\n * @throws Error if the JWT token generation fails\n */\n async auth(authParams: CoinbaseCDPAuthParams): Promise<string> {\n const jwtToken = await generateJwt({\n apiKeyId: this.apiKeyId,\n apiKeySecret: this.apiKeySecret,\n ...authParams,\n });\n\n return jwtToken;\n }\n\n /**\n * @internal\n * Return a on-ramp URL for the given parameters via Coinbase CDP V2 API\n * @category Ramp\n *\n * @param receiverAddress\n * @param redirectUrl\n * @param amount\n * @param purchaseCurrency\n * @param paymentCurrency\n * @param paymentMethod\n * @param country\n * @returns OnRampUrlResponse\n * @throws Error if redirect URL is not a valid URL\n * @throws CoinbaseCDPError if the request fails\n */\n async getOnRampLink(\n receiverAddress: Address,\n redirectUrl: string,\n amount: string,\n purchaseCurrency: string = 'USDC',\n paymentCurrency: string = 'USD',\n paymentMethod: string = 'CARD',\n country?: string,\n ): Promise<OnRampUrlResponse> {\n if (!checkValidUrl(redirectUrl)) {\n throw new Error('Redirect URL is not a valid URL');\n }\n\n const chainId = this.chainManager.getSupportedChain();\n const chainName = chainById[chainId]?.name.toLowerCase();\n\n const authJwtToken = await this.auth(this.onRampUrlAuthParams);\n\n const response: AxiosResponse<OnRampUrlResponse | CoinbaseCDPError> = await this.clientV2.post(\n this.onRampUrlAuthParams.requestPath,\n {\n destinationAddress: receiverAddress,\n destinationNetwork: chainName,\n redirectUrl,\n paymentAmount: amount,\n purchaseCurrency,\n paymentCurrency,\n paymentMethod,\n country: country,\n },\n {\n method: this.onRampUrlAuthParams.requestMethod,\n headers: { Authorization: `Bearer ${authJwtToken}`, 'Content-Type': 'application/json' },\n },\n );\n\n if (response.status !== 200 && response.status !== 201) {\n const error = response.data as CoinbaseCDPError;\n throw error;\n }\n\n const onRampResponse = response.data as OnRampUrlResponse;\n\n return onRampResponse;\n }\n\n /**\n * @internal\n * Current method return all supported countries and payment methods for on-ramp by Coinbase CDP\n * @category Ramp\n *\n * @returns Config with supported countries and payment methods for on-ramp\n * @throws If API returned an error\n */\n public async getOnRampConfig(): Promise<RampConfigResponse> {\n const authJwtToken = await this.auth(this.onRampConfigAuthParams);\n\n const response: AxiosResponse<RampConfigResponse | CoinbaseCDPError> = await this.clientV1.get(\n this.onRampConfigAuthParams.requestPath,\n {\n headers: { Authorization: `Bearer ${authJwtToken}` },\n },\n );\n\n if (response.status !== 200) {\n const error = response.data as CoinbaseCDPError;\n throw error;\n }\n\n const onRampConfigResponse = response.data as RampConfigResponse;\n return onRampConfigResponse;\n }\n\n /**\n * @internal\n * Return a off-ramp URL for the given parameters via Coinbase CDP V1 API\n * @remarks\n * Use an integratorId as a partnerUserId in Coinbase CDP API\n * @category Ramp\n *\n * @param address\n * @param country\n * @param paymentMethod\n * @param redirectUrl\n * @param sellAmount\n * @param cashoutCurrency\n * @param sellCurrency\n * @returns OffRampUrlResponse\n * @throws Error if redirect URL is not a valid URL\n * @throws CoinbaseCDPError if the request fails\n */\n async getOffRampLink(\n address: Address,\n country: string,\n paymentMethod: string,\n redirectUrl: string,\n sellAmount: string,\n cashoutCurrency: string = 'USD',\n sellCurrency: string = 'USDC',\n ): Promise<OffRampUrlResponse> {\n if (!checkValidUrl(redirectUrl)) {\n throw new Error('Redirect URL is not a valid URL');\n }\n\n const chainId = this.chainManager.getSupportedChain();\n const chainName = chainById[chainId]?.name.toLowerCase();\n\n const authJwtToken = await this.auth(this.offRampUrlAuthParams);\n\n const response: AxiosResponse<OffRampUrlResponse | CoinbaseCDPError> = await this.clientV1.post(\n this.offRampUrlAuthParams.requestPath,\n {\n sourceAddress: address,\n country,\n paymentMethod,\n partnerUserId: this.integratorId,\n redirectUrl,\n sellAmount,\n sellNetwork: chainName,\n cashoutCurrency,\n sellCurrency,\n },\n {\n method: this.offRampUrlAuthParams.requestMethod,\n headers: { Authorization: `Bearer ${authJwtToken}`, 'Content-Type': 'application/json' },\n },\n );\n\n if (response.status !== 200 && response.status !== 201) {\n const error = response.data as CoinbaseCDPError;\n throw error;\n }\n\n const offRampResponse = response.data as OffRampUrlResponse;\n\n return offRampResponse;\n }\n\n /**\n * @internal\n * Current method return all supported countries and payment methods for off-ramp by Coinbase CDP\n * @category Ramp\n * @returns Config with supported countries and payment methods for off-ramp\n * @throws If API returned an error\n */\n public async getOffRampConfig(): Promise<RampConfigResponse> {\n const authJwtToken = await this.auth(this.offRampConfigAuthParams);\n\n const response: AxiosResponse<RampConfigResponse | CoinbaseCDPError> = await this.clientV1.get(\n this.offRampConfigAuthParams.requestPath,\n {\n headers: { Authorization: `Bearer ${authJwtToken}` },\n },\n );\n\n if (response.status !== 200) {\n const error = response.data as CoinbaseCDPError;\n throw error;\n }\n\n const offRampConfigResponse = response.data as RampConfigResponse;\n return offRampConfigResponse;\n }\n}\n","export const checkValidUrl = (url: string): boolean => {\n return /^https?:\\/\\/.+$/.test(url);\n};\n"],"mappings":"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","names":["erc20Abi","address","tokenInfo","parsedAmount","erc20Abi","base","baseSepolia","LogLevel","base","pad","pad","http","unichain","http","unichain","erc20Abi","createWalletClient","http","encodeFunctionData","erc20Abi","formatUnits","parseUnits","parseUnits","encodeFunctionData","erc20Abi","formatUnits","base"]}
1
+ {"version":3,"sources":["../src/wallet/DefaultSmartWallet.ts","../src/abis/smartWalletFactory.ts","../src/constants/addresses.ts","../src/tools/TokenBalance.ts","../src/constants/tokens.ts","../src/utils/tokens.ts","../src/utils/assets.ts","../src/wallet/base/wallets/SmartWallet.ts","../src/ramp/FundingNamespace.ts","../src/tools/ChainManager.ts","../src/constants/chains.ts","../src/utils/chains.ts","../src/wallet/WalletNamespace.ts","../src/index.ts","../src/wallet/providers/DefaultSmartWalletProvider.ts","../src/wallet/base/providers/SmartWalletProvider.ts","../src/wallet/WalletProvider.ts","../src/wallet/providers/PrivyEmbeddedWalletProvider.ts","../src/wallet/PrivyWallet.ts","../src/wallet/base/wallets/EmbeddedWallet.ts","../src/types/logger.ts","../src/tools/Logger.ts","../src/wallet/base/providers/EmbeddedWalletProvider.ts","../src/protocols/base/BaseProtocol.ts","../src/protocols/implementations/SparkProtocol.ts","../src/abis/protocols/spark.ts","../src/protocols/constants/spark.ts","../src/constants/protocols.ts","../src/protocols/implementations/ProxyProtocol.ts","../src/router/ProtocolRouter.ts","../src/tools/CoinbaseCDP.ts","../src/utils/urls.ts","../src/protocols/ProtocolsNamespace.ts","../src/constants/general.ts","../src/tools/ApiClient.ts"],"sourcesContent":["import {\n type Address,\n type Hash,\n type LocalAccount,\n encodeFunctionData,\n erc20Abi,\n pad,\n} from 'viem';\nimport { type WebAuthnAccount, toCoinbaseSmartAccount } from 'viem/account-abstraction';\n\nimport { smartWalletFactoryAbi } from '@/abis/smartWalletFactory';\nimport { smartWalletFactoryAddress } from '@/constants/addresses';\nimport type { SupportedChainId } from '@/constants/chains';\nimport type { ChainManager } from '@/tools/ChainManager';\nimport { fetchERC20Balance, fetchETHBalance } from '@/tools/TokenBalance';\nimport { SUPPORTED_TOKENS } from '@/constants/tokens';\nimport type { TokenBalance } from '@/types/token';\nimport { type AssetIdentifier, parseAssetAmount, resolveAsset } from '@/utils/assets';\nimport { SmartWallet } from '@/wallet/base/wallets/SmartWallet';\nimport type { TransactionData } from '@/types/transaction';\nimport type { VaultBalance, VaultInfo, VaultTxnResult } from '@/types/protocols/general';\nimport type { CoinbaseCDP } from '@/tools/CoinbaseCDP';\nimport type { OffRampUrlResponse, OnRampUrlResponse } from '@/types/ramp';\nimport type { BaseProtocol } from '@/protocols/base/BaseProtocol';\n\n/**\n * Default ERC-4337 smart wallet implementation. Implements main methods that a user can use to interact with DeFi protocols and use all related functionalities\n *\n * @public\n * @category 3. Account operations\n * @remarks\n * Backed by Coinbase Smart Account and compatible with ERC-4337 UserOperations\n * Supports multi-owner wallets (EVM addresses or WebAuthn owners), gas-sponsored flows,\n * and cross-chain operations via {@link ChainManager}\n */\nexport class DefaultSmartWallet extends SmartWallet {\n /** Owners (EVM addresses or WebAuthn public keys) */\n private owners: Array<Address | WebAuthnAccount>;\n /** Signer for transactions and UserOperations */\n private _signer: LocalAccount;\n /** Index of signer within the owners array (undefined → default 0) */\n private signerOwnerIndex?: number;\n /** Known deployment address (if already deployed) */\n private deploymentAddress?: Address;\n /** Network and client management */\n private chainManager: ChainManager;\n /** Nonce (salt) for deterministic address calculation */\n private nonce?: bigint;\n /** Selected protocol provider instance */\n private protocolProvider: BaseProtocol; // Protocol['instance'];\n /** Coinbase CDP instance to interact with Coinbase CDP API */\n private coinbaseCDP: CoinbaseCDP | null;\n\n /**\n * Creates a smart wallet instance\n *\n * @internal\n * @param owners Owners (addresses or WebAuthn accounts)\n * @param signer Local account used to sign\n * @param chainManager Chain/client manager\n * @param protocolProvider Protocol provider instance (selected upstream)\n * @param deploymentAddress Optional known deployment address\n * @param signerOwnerIndex Optional index of `signer` in owners (default 0)\n * @param nonce Optional salt for deterministic address calc (default 0)\n */\n constructor(\n owners: Array<Address | WebAuthnAccount>,\n signer: LocalAccount,\n chainManager: ChainManager,\n protocolProvider: BaseProtocol, // Protocol['instance'],\n coinbaseCDP: CoinbaseCDP | null,\n deploymentAddress?: Address,\n signerOwnerIndex?: number,\n nonce?: bigint,\n ) {\n super();\n this.owners = owners;\n this._signer = signer;\n this.signerOwnerIndex = signerOwnerIndex;\n this.deploymentAddress = deploymentAddress;\n this.chainManager = chainManager;\n this.nonce = nonce;\n this.protocolProvider = protocolProvider;\n this.coinbaseCDP = coinbaseCDP;\n }\n\n /**\n * Returns the signer account for this smart wallet\n *\n * @public\n * @category Account\n * @remarks\n * Used to authorize UserOperations and on-chain transactions\n */\n get signer(): LocalAccount {\n return this._signer;\n }\n\n /**\n * Resolves the smart wallet address\n *\n * @public\n * @category Account\n * @remarks\n * If `deploymentAddress` is known, returns it. Otherwise derives a deterministic address\n * via the factory (`getAddress`) using owners and `nonce` (CREATE2-style)\n *\n * @returns Promise that resolves to the wallet address\n * @throws Error if no supported chains are configured\n * @throws Error if an owner has an invalid type\n */\n async getAddress() {\n if (this.deploymentAddress) {\n return this.deploymentAddress;\n }\n\n const owners_bytes = this.owners.map((owner) => {\n if (typeof owner === 'string') {\n return pad(owner);\n }\n if (owner.type === 'webAuthn') {\n return owner.publicKey;\n }\n throw new Error('invalid owner type');\n });\n\n // Factory is the same across all chains, so we can use the first chain to get the wallet address\n const supportedChain = this.chainManager.getSupportedChain();\n if (!supportedChain) {\n throw new Error('No supported chains configured');\n }\n const publicClient = this.chainManager.getPublicClient(supportedChain);\n const smartWalletAddress = await publicClient.readContract({\n abi: smartWalletFactoryAbi,\n address: smartWalletFactoryAddress,\n functionName: 'getAddress',\n args: [owners_bytes, this.nonce || 0n],\n });\n return smartWalletAddress;\n }\n\n /**\n * Builds a Coinbase Smart Account for a specific chain\n *\n * @internal\n * @category Account\n * @param chainId Target chain ID\n * @returns Viem Coinbase Smart Account for the given chain\n */\n async getCoinbaseSmartAccount(\n chainId: SupportedChainId,\n ): ReturnType<typeof toCoinbaseSmartAccount> {\n return toCoinbaseSmartAccount({\n address: this.deploymentAddress,\n ownerIndex: this.signerOwnerIndex,\n client: this.chainManager.getPublicClient(chainId),\n owners: [this.signer],\n nonce: this.nonce,\n version: '1.1',\n });\n }\n\n /**\n * Fetches balances (ETH + ERC-20) for a smart account across supported chains\n *\n * @public\n * @category Account\n * @returns Promise resolving to a list of {@link TokenBalance}\n */\n async getBalance(): Promise<TokenBalance[]> {\n const address = await this.getAddress();\n const tokenBalancePromises = Object.values(SUPPORTED_TOKENS).map(async (token) => {\n return fetchERC20Balance(this.chainManager, address, token);\n });\n\n const ethBalancePromise = fetchETHBalance(this.chainManager, address);\n\n return Promise.all([ethBalancePromise, ...tokenBalancePromises]);\n }\n\n /**\n * Deposits into the selected protocol’s vault to start earning yield\n * @public\n * @category Earn\n * @remarks\n * The protocol is selected on the SDK initialization step\n * @param amount Human-readable amount string\n * @returns Transaction result for the deposit\n */\n async earn(vaultInfo: VaultInfo, amount: string): Promise<VaultTxnResult> {\n this.chainManager.getSupportedChain();\n\n const depositTransactionResult = this.protocolProvider.deposit(vaultInfo, amount, this);\n\n return depositTransactionResult;\n }\n\n /**\n * Reads current deposit balance from the selected protocol’s vault\n * Method to read the current deposit balance from the selected protocol’s vault for a smart account\n *\n * @public\n * @category Earn\n * @returns Vault balance or `null` if nothing deposited\n */\n async getEarnBalances(): Promise<VaultBalance[]> {\n const userAddress = await this.getAddress();\n return this.protocolProvider.getBalances(userAddress);\n }\n\n /**\n * Withdraws from the selected protocol’s vault\n * @public\n * @category Earn\n * @param amount Human-readable amount string\n * @returns Transaction result for the withdrawal\n * @throws Error if the withdrawal fails\n * @throws Error a user didn't deposit anything\n */\n async withdraw(vaultInfo: VaultInfo, amount: string): Promise<VaultTxnResult> {\n const withdrawTransactionResult = await this.protocolProvider.withdraw(vaultInfo, amount, this);\n\n return withdrawTransactionResult;\n }\n\n /**\n * Builds a UserOperation and submits via the bundler, then waits for inclusion\n\n *\n * @public\n * @category Transactions\n *\n * @param transactionData Transaction details (`to`, `value`, `data`)\n * @param chainId Target chain ID\n * @returns Promise that resolves to the UserOperation hash\n * @throws Error with a readable message if submission or inclusion fails\n */\n async send(transactionData: TransactionData, chainId: SupportedChainId): Promise<Hash> {\n try {\n const account = await this.getCoinbaseSmartAccount(chainId);\n const bundlerClient = this.chainManager.getBundlerClient(chainId, account);\n\n // Extra buffer for gas limits\n const bump = (x: bigint, pct = 40n) => x + (x * pct) / 100n;\n\n const gas = await bundlerClient.estimateUserOperationGas({\n account,\n calls: [transactionData],\n });\n\n const hash = await bundlerClient.sendUserOperation({\n account,\n calls: [transactionData],\n callGasLimit: bump(gas.callGasLimit),\n verificationGasLimit: bump(gas.verificationGasLimit),\n preVerificationGas: bump(gas.preVerificationGas),\n });\n\n // Wait for the transaction to be included in a block\n await bundlerClient.waitForUserOperationReceipt({\n hash,\n });\n\n return hash;\n } catch (error) {\n throw new Error(\n `Failed to send transaction: ${error instanceof Error ? error.message.toString().slice(0, 100) : 'Unknown error'}`,\n );\n }\n }\n\n /**\n * Builds a UserOperation from several onchain transactions and submits via the bundler, then waits for inclusion\n *\n * @public\n * @category Transactions\n *\n * @param transactionData An array of calls to execute\n * @param chainId Target chain ID\n * @returns Promise that resolves to the UserOperation hash for the batch\n * @throws Error with a readable message if submission or inclusion fails\n */\n async sendBatch(transactionData: TransactionData[], chainId: SupportedChainId): Promise<Hash> {\n try {\n const account = await this.getCoinbaseSmartAccount(chainId);\n const bundlerClient = this.chainManager.getBundlerClient(chainId, account);\n\n // Extra buffer for gas limits\n const bump = (x: bigint, pct = 40n) => x + (x * pct) / 100n;\n\n const gas = await bundlerClient.estimateUserOperationGas({\n account,\n calls: transactionData,\n });\n\n // Wait for the transaction to be included in a block\n const hash = await bundlerClient.sendUserOperation({\n account,\n calls: transactionData,\n callGasLimit: bump(gas.callGasLimit),\n verificationGasLimit: bump(gas.verificationGasLimit),\n preVerificationGas: bump(gas.preVerificationGas),\n });\n\n await bundlerClient.waitForUserOperationReceipt({\n hash,\n });\n\n return hash;\n } catch (error) {\n throw new Error(\n `Failed to send transaction: ${error instanceof Error ? error.message : 'Unknown error'}`,\n );\n }\n }\n\n /**\n * Funds the smart wallet with the specified amount of the specified token via Coinbase CDP on-ramp service\n *\n * @public\n * @category Funding\n *\n * @remarks\n * If Coinbase CDP is not initialized, the method will throw an error. For more details, visit @see {@link https://docs.cdp.coinbase.com/api-reference/v2/rest-api/onramp/create-an-onramp-session}\n *\n * @param amount Amount of token that a user wants to purchase and top up his account with (e.g., `\"100\"`, `\"1.5\"`)\n * @param redirectUrl URL to redirect to after the on-ramp is complete. It's required to be a valid URL\n * @param purchaseCurrency Purchase currency (e.g., `\"USDC\"`, `\"ETH\"`)\n * @param paymentCurrency Payment currency (e.g., `\"USD\"`, `\"EUR\"`)\n * @param paymentMethod Payment method (e.g., `\"CARD\"`)\n * @param chain Chain name (e.g., `\"base\"`)\n * @param country Country code (e.g., `\"US\"`)\n *\n *\n * @returns @see {@link OnRampUrlResponse}\n */\n async topUp(\n amount: string,\n redirectUrl: string,\n purchaseCurrency?: string,\n paymentCurrency?: string,\n paymentMethod?: string,\n country?: string,\n ): Promise<OnRampUrlResponse> {\n if (!this.coinbaseCDP) {\n throw new Error(\n 'Coinbase CDP is not initialized. Please, provide the configuration in the SDK initialization',\n );\n }\n\n const address = await this.getAddress();\n\n const onRampLink = await this.coinbaseCDP.getOnRampLink(\n address,\n redirectUrl,\n amount,\n purchaseCurrency,\n paymentCurrency,\n paymentMethod,\n country,\n );\n\n return onRampLink;\n }\n\n /**\n * Cashout token from smart wallet to fiat currency via Coinbase CDP off-ramp service\n *\n * @public\n * @category Funding\n *\n * @remarks\n * If Coinbase CDP is not initialized, the method will throw an error. For more details, visit @see {@link https://docs.cdp.coinbase.com/api-reference/rest-api/onramp-offramp/create-sell-quote}\n *\n * @param country Country code (e.g., `\"US\"`)\n * @param paymentMethod Payment method (e.g., `\"CARD\"`). To get the ful list, visit \"\"\n * @param redirectUrl URL to redirect to after the off-ramp is complete. It's required to be a valid URL\n * @param sellAmount Amount of token that a user wants to sell (e.g., `\"100\"`, `\"1.5\"`)\n * @param cashoutCurrency Cashout currency (e.g., `\"USD\"`, `\"EUR\"`). To get the ful list, visit \"\"\n * @param sellCurrency Sell currency (e.g., `\"USDC\"`, `\"ETH\"`). To get the ful list, visit \"\"\n *\n *\n * @returns @see {@link OffRampUrlResponse}\n */\n async cashOut(\n country: string,\n paymentMethod: string,\n redirectUrl: string,\n sellAmount: string,\n cashoutCurrency?: string,\n sellCurrency?: string,\n ): Promise<OffRampUrlResponse> {\n if (!this.coinbaseCDP) {\n throw new Error(\n 'Coinbase CDP is not initialized. Please, provide the configuration in the SDK initialization',\n );\n }\n\n const address = await this.getAddress();\n\n const offRampLink = await this.coinbaseCDP.getOffRampLink(\n address,\n country,\n paymentMethod,\n redirectUrl,\n sellAmount,\n cashoutCurrency,\n sellCurrency,\n );\n\n return offRampLink;\n }\n\n /**\n * Send tokens from a smart account to another address\n *\n * @public\n * @category Transactions\n *\n * @param amount Human-readable amount (e.g., `1.5`)\n * @param asset Asset symbol (e.g., `\"usdc\"`, `\"eth\"`) or token address\n * @param recipientAddress Destination address\n * @returns Transaction data suitable for inclusion in a UserOperation/call\n * @throws Error if `recipientAddress` is missing, `amount` ≤ 0, or asset cannot be resolved\n */\n async sendTokens(\n amount: number,\n asset: AssetIdentifier,\n recipientAddress: Address,\n ): Promise<TransactionData> {\n if (!recipientAddress) {\n throw new Error('Recipient address is required');\n }\n\n // Validate amount\n if (amount <= 0) {\n throw new Error('Amount must be greater than 0');\n }\n\n const chainId = this.chainManager.getSupportedChain();\n\n // Handle ETH transfers\n if (asset.toLowerCase() === 'eth') {\n const parsedAmount = parseAssetAmount(amount, 18); // ETH has 18 decimals\n\n return {\n to: recipientAddress,\n value: parsedAmount,\n data: '0x',\n };\n }\n\n // Handle ERC20 token transfers\n const resolvedAsset = resolveAsset(asset, chainId);\n const parsedAmount = parseAssetAmount(amount, resolvedAsset.decimals);\n\n // Encode ERC20 transfer function call\n const transferData = encodeFunctionData({\n abi: erc20Abi,\n functionName: 'transfer',\n args: [recipientAddress, parsedAmount],\n });\n\n return {\n to: resolvedAsset.address,\n value: 0n,\n data: transferData,\n };\n }\n}\n","export const smartWalletFactoryAbi = [\n {\n type: 'constructor',\n inputs: [\n { name: 'implementation_', type: 'address', internalType: 'address' },\n ],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n name: 'createAccount',\n inputs: [\n { name: 'owners', type: 'bytes[]', internalType: 'bytes[]' },\n { name: 'nonce', type: 'uint256', internalType: 'uint256' },\n ],\n outputs: [\n {\n name: 'account',\n type: 'address',\n internalType: 'contract CoinbaseSmartWallet',\n },\n ],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n name: 'getAddress',\n inputs: [\n { name: 'owners', type: 'bytes[]', internalType: 'bytes[]' },\n { name: 'nonce', type: 'uint256', internalType: 'uint256' },\n ],\n outputs: [{ name: '', type: 'address', internalType: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'implementation',\n inputs: [],\n outputs: [{ name: '', type: 'address', internalType: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'initCodeHash',\n inputs: [],\n outputs: [{ name: '', type: 'bytes32', internalType: 'bytes32' }],\n stateMutability: 'view',\n },\n {\n type: 'event',\n name: 'AccountCreated',\n inputs: [\n {\n name: 'account',\n type: 'address',\n indexed: true,\n internalType: 'address',\n },\n {\n name: 'owners',\n type: 'bytes[]',\n indexed: false,\n internalType: 'bytes[]',\n },\n {\n name: 'nonce',\n type: 'uint256',\n indexed: false,\n internalType: 'uint256',\n },\n ],\n anonymous: false,\n },\n { type: 'error', name: 'ImplementationUndeployed', inputs: [] },\n { type: 'error', name: 'OwnerRequired', inputs: [] },\n] as const\n","export const smartWalletFactoryAddress = '0xBA5ED110eFDBa3D005bfC882d75358ACBbB85842';\n","import { type Address, erc20Abi, formatEther, formatUnits } from 'viem';\n\nimport type { SupportedChainId } from '@/constants/chains';\nimport type { ChainManager } from '@/tools/ChainManager';\nimport { getTokenAddress, type TokenInfo } from '@/utils/tokens';\nimport type { TokenBalance } from '@/types/token';\n\n/**\n * Fetches the ETH balance for a wallet across configured supported chain\n *\n * @internal\n * @category Balances\n * @param chainManager Chain manager instance\n * @param walletAddress Target wallet address\n * @returns Promise resolving to a {@link TokenBalance} object for ETH\n */\nexport async function fetchETHBalance(\n chainManager: ChainManager,\n walletAddress: Address,\n): Promise<TokenBalance> {\n const supportedChain = chainManager.getSupportedChain();\n\n const publicClient = chainManager.getPublicClient(supportedChain);\n const balance = await publicClient.getBalance({\n address: walletAddress,\n });\n\n return {\n symbol: 'ETH',\n totalBalance: balance,\n totalFormattedBalance: formatEther(balance),\n chainBalances: [\n {\n chainId: supportedChain,\n balance,\n formattedBalance: formatEther(balance),\n },\n ],\n };\n}\n\n/**\n * Fetches the ERC20 token balance for a wallet across the configured supported chain\n *\n * @internal\n * @category Balances\n * @param chainManager Chain manager instance\n * @param walletAddress Target wallet address\n * @param token Token metadata including address and decimals\n * @returns Promise resolving to a {@link TokenBalance} object for the token\n */\nexport async function fetchERC20Balance(\n chainManager: ChainManager,\n walletAddress: Address,\n token: TokenInfo,\n): Promise<TokenBalance> {\n const supportedChain = chainManager.getSupportedChain();\n\n const balance = await fetchERC20BalanceForChain(\n token,\n supportedChain,\n walletAddress,\n chainManager,\n );\n\n return {\n symbol: token.symbol,\n totalBalance: balance,\n totalFormattedBalance: formatUnits(balance, token.decimals),\n chainBalances: [\n {\n chainId: supportedChain,\n balance,\n formattedBalance: formatUnits(balance, token.decimals),\n },\n ],\n };\n}\n\n/**\n * Fetches the ERC20 token balance for a wallet on a specific chain\n *\n * @internal\n * @category Balances\n * @remarks\n * Falls back to native ETH balance if `token.symbol` is ETH\n *\n * @param token Token metadata\n * @param chainId Chain ID to query\n * @param walletAddress Target wallet address\n * @param chainManager Chain manager instance\n * @returns Promise resolving to raw bigint balance\n * @throws Error if token is not supported on the given chain\n */\nasync function fetchERC20BalanceForChain(\n token: TokenInfo,\n chainId: SupportedChainId,\n walletAddress: Address,\n chainManager: ChainManager,\n): Promise<bigint> {\n const tokenAddress = getTokenAddress(token.symbol, chainId);\n if (!tokenAddress) {\n throw new Error(`${token.symbol} not supported on chain ${chainId}`);\n }\n\n const publicClient = chainManager.getPublicClient(chainId);\n\n // Handle native ETH balance\n if (token.symbol === 'ETH') {\n return publicClient.getBalance({\n address: walletAddress,\n });\n }\n\n // Handle ERC20 token balance\n return publicClient.readContract({\n address: tokenAddress,\n abi: erc20Abi,\n functionName: 'balanceOf',\n args: [walletAddress],\n });\n}\n","import type { TokenInfo } from '@/utils/tokens';\nimport { mainnet, unichain, base, baseSepolia, sepolia } from 'viem/chains';\n\nexport const SUPPORTED_TOKENS: Record<string, TokenInfo> = {\n ETH: {\n symbol: 'ETH',\n name: 'Ethereum',\n decimals: 18,\n addresses: {\n [mainnet.id]: '0x0000000000000000000000000000000000000000',\n [unichain.id]: '0x0000000000000000000000000000000000000000',\n [base.id]: '0x0000000000000000000000000000000000000000',\n [baseSepolia.id]: '0x0000000000000000000000000000000000000000',\n [sepolia.id]: '0x0000000000000000000000000000000000000000',\n },\n },\n USDC: {\n symbol: 'USDC',\n name: 'USDC',\n decimals: 6,\n addresses: {\n [mainnet.id]: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',\n [unichain.id]: '0x078d782b760474a361dda0af3839290b0ef57ad6',\n [baseSepolia.id]: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n [sepolia.id]: '0xf08A50178dfcDe18524640EA6618a1f965821715',\n [base.id]: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n },\n },\n};\n","import type { Address } from 'viem';\nimport type { SupportedChainId } from '@/constants/chains';\nimport { SUPPORTED_TOKENS } from '@/constants/tokens';\n\nexport interface TokenInfo {\n symbol: string;\n name: string;\n decimals: number;\n addresses: Partial<Record<SupportedChainId, Address>>; // chainId -> address\n}\n\n/**\n * Find token by address and chain ID\n * @param address Token address\n * @param chainId Chain ID\n * @returns Token symbol or null if not found\n */\nexport function findTokenByAddress(address: Address, chainId: SupportedChainId): string | null {\n const normalizedAddress = address.toLowerCase();\n\n for (const [symbol, token] of Object.entries(SUPPORTED_TOKENS)) {\n const tokenAddress = token.addresses[chainId];\n if (tokenAddress && tokenAddress.toLowerCase() === normalizedAddress) {\n return symbol;\n }\n }\n\n return null;\n}\n\n/**\n * Get token address for a specific chain\n * @param symbol Token symbol\n * @param chainId Chain ID\n * @returns Token address or null if not supported on that chain\n */\nexport function getTokenAddress(symbol: string, chainId: SupportedChainId): Address | null {\n const token = SUPPORTED_TOKENS[symbol];\n return token?.addresses[chainId] || null;\n}\n","import { type Address, parseUnits } from 'viem';\n\nimport type { SupportedChainId } from '@/constants/chains';\nimport { getTokenAddress } from '@/utils/tokens';\nimport { SUPPORTED_TOKENS } from '@/constants/tokens';\n\n/**\n * Asset identifier - can be a symbol (like 'usdc') or address\n */\nexport type AssetIdentifier = string | Address;\n\n/**\n * Resolved asset information\n */\nexport interface ResolvedAsset {\n address: Address;\n symbol: string;\n decimals: number;\n}\n\n/**\n * Resolve asset identifier to address and metadata\n * @param asset - Asset symbol (e.g. 'usdc') or address\n * @param chainId - Chain ID to resolve for\n * @returns Resolved asset information\n * @throws Error if asset is not supported or found\n */\nexport function resolveAsset(asset: AssetIdentifier, chainId: SupportedChainId): ResolvedAsset {\n // If it's an address (starts with 0x), validate and find symbol\n if (asset.startsWith('0x')) {\n const address = asset as Address;\n\n // Try to find the symbol for this address\n for (const [, tokenInfo] of Object.entries(SUPPORTED_TOKENS)) {\n const tokenAddress = tokenInfo.addresses[chainId];\n if (tokenAddress && tokenAddress.toLowerCase() === address.toLowerCase()) {\n return {\n address: tokenAddress,\n symbol: tokenInfo.symbol,\n decimals: tokenInfo.decimals,\n };\n }\n }\n\n // If not found in supported tokens, we can't determine decimals\n throw new Error(\n `Unknown asset address: ${address}. Please use a supported asset symbol like 'usdc' or add the token to SUPPORTED_TOKENS.`,\n );\n }\n\n // If it's a symbol, resolve to address\n const normalizedSymbol = asset.toUpperCase();\n const tokenInfo = SUPPORTED_TOKENS[normalizedSymbol];\n\n if (!tokenInfo) {\n const availableSymbols = Object.keys(SUPPORTED_TOKENS).join(', ');\n throw new Error(`Unsupported asset symbol: ${asset}. Supported assets: ${availableSymbols}`);\n }\n\n const address = getTokenAddress(normalizedSymbol, chainId);\n if (!address) {\n throw new Error(\n `Asset ${asset} is not supported on chain ${chainId}. Available chains: ${Object.keys(tokenInfo.addresses).join(', ')}`,\n );\n }\n\n return {\n address,\n symbol: tokenInfo.symbol,\n decimals: tokenInfo.decimals,\n };\n}\n\n/**\n * Parse human-readable amount to wei/smallest unit\n * @param amount - Human-readable amount (e.g. 1.5)\n * @param decimals - Token decimals\n * @returns Amount in smallest unit (wei equivalent)\n */\nexport function parseAssetAmount(amount: number, decimals: number): bigint {\n // Convert number to string with proper precision\n const amountStr = amount.toString();\n\n // Use viem's parseUnits for proper decimal handling\n return parseUnits(amountStr, decimals);\n}\n\n/**\n * Convert wei/smallest unit back to human-readable amount\n * @param amount - Amount in smallest unit\n * @param decimals - Token decimals\n * @returns Human-readable amount as number\n */\nexport function formatAssetAmount(amount: bigint, decimals: number): number {\n // Convert to string, then to number\n const divisor = 10n ** BigInt(decimals);\n const wholePart = amount / divisor;\n const fractionalPart = amount % divisor;\n\n // Handle fractional part with proper precision\n const fractionalStr = fractionalPart.toString().padStart(decimals, '0');\n const result = `${wholePart}.${fractionalStr}`;\n\n return parseFloat(result);\n}\n\n/**\n * Validate and parse lend parameters\n * @param amount - Human-readable amount\n * @param asset - Asset identifier\n * @param chainId - Chain ID\n * @returns Parsed lend parameters\n */\nexport function parseLendParams(\n amount: number,\n asset: AssetIdentifier,\n chainId: SupportedChainId,\n): {\n amount: bigint;\n asset: ResolvedAsset;\n} {\n if (amount <= 0) {\n throw new Error('Amount must be greater than 0');\n }\n\n const resolvedAsset = resolveAsset(asset, chainId);\n const parsedAmount = parseAssetAmount(amount, resolvedAsset.decimals);\n\n return {\n amount: parsedAmount,\n asset: resolvedAsset,\n };\n}\n","import type { Address, Hash, LocalAccount } from 'viem';\n\nimport type { SupportedChainId } from '@/constants/chains';\nimport type { TokenBalance } from '@/types/token';\nimport type { AssetIdentifier } from '@/utils/assets';\nimport type { TransactionData } from '@/types/transaction';\nimport type { VaultBalance, VaultInfo, VaultTxnResult } from '@/types/protocols/general';\nimport type { OffRampUrlResponse, OnRampUrlResponse } from '@/types/ramp';\n\n/**\n * Abstract base class for smart wallet implementations\n *\n * @internal\n * @category Wallets\n * @remarks\n * Provides the interface for ERC-4337 compatible wallets\n * Extended by concrete classes such as {@link DefaultSmartWallet}\n */\nexport abstract class SmartWallet {\n /** LocalAccount used for signing transactions on behalf of this smart wallet */\n abstract signer: LocalAccount;\n\n /**\n * Returns the deployed or predicted address of this smart wallet\n *\n * @internal\n * @category Addressing\n * @remarks\n * For undeployed wallets this returns the deterministic CREATE2 address\n *\n * @returns Promise resolving to the wallet Ethereum address\n */\n abstract getAddress(): Promise<Address>;\n\n /**\n * Retrieves balances for all supported tokens held by this smart wallet\n *\n * @internal\n * @category Balances\n * @returns Promise resolving to an array of {@link TokenBalance} entries\n */\n abstract getBalance(): Promise<TokenBalance[]>;\n\n // TODO: add addSigner method\n // TODO: add removeSigner method\n\n /**\n * Executes a transaction through the smart wallet\n *\n * @internal\n * @category Transactions\n * @remarks\n * Handles gas sponsorship and ERC-4337 UserOperation creation automatically\n *\n * @param transactionData Transaction data to execute\n * @param chainId Target blockchain chain ID\n * @returns Promise resolving to the transaction {@link Hash}\n */\n abstract send(transactionData: TransactionData, chainId: SupportedChainId): Promise<Hash>;\n\n /**\n * Executes a batch of transactions through the smart wallet\n *\n * @internal\n * @category Transactions\n * @remarks\n * Transactions are executed in the order they are provided\n * Handles gas sponsorship and ERC-4337 UserOperation creation automatically\n *\n * @param transactionData Array of transaction data objects\n * @param chainId Target blockchain chain ID\n * @returns Promise resolving to the transaction {@link Hash}\n */\n abstract sendBatch(transactionData: TransactionData[], chainId: SupportedChainId): Promise<Hash>;\n\n /**\n * Prepares transaction data for sending tokens to another address\n *\n * @internal\n * @category Transactions\n * @param amount Human-readable amount to send\n * @param asset Token or asset identifier\n * @param recipientAddress Destination address\n * @returns Promise resolving to prepared {@link TransactionData}\n */\n abstract sendTokens(\n amount: number,\n asset: AssetIdentifier,\n recipientAddress: Address,\n ): Promise<TransactionData>;\n\n /**\n * Deposits funds into a selected protocol vault to start earning yield\n *\n * @internal\n * @category Yield\n * @param amount Amount to deposit in human-readable format\n * @returns Promise resolving to a {@link VaultTxnResult}\n */\n abstract earn(vaultInfo: VaultInfo, amount: string): Promise<VaultTxnResult>;\n\n /**\n * Retrieves the balance of deposited funds in the selected protocol vault\n *\n * @internal\n * @category Yield\n * @returns Promise resolving to a {@link VaultBalance} or null if none\n */\n abstract getEarnBalances(): Promise<VaultBalance[] | null>;\n\n /**\n * Withdraws a specific amount of shares from the protocol vault\n *\n * @internal\n * @category Yield\n * @param amount Human-readable amount of shares to withdraw\n * @returns Promise resolving to a {@link VaultTxnResult}\n */\n abstract withdraw(vaultInfo: VaultInfo, amount: string): Promise<VaultTxnResult>;\n\n /**\n * Funds the smart wallet with the specified amount of the specified token via Coinbase CDP on-ramp service\n *\n * @internal\n * @category Ramp\n *\n * @remarks\n * If Coinbase CDP is not initialized, the method will throw an error\n *\n * @param amount Amount of token that a user wants to purchase and top up his account with (e.g., `\"100\"`, `\"1.5\"`)\n * @param redirectUrl URL to redirect to after the on-ramp is complete. It's required to be a valid URL\n * @param purchaseCurrency Purchase currency (e.g., `\"USDC\"`, `\"ETH\"`). To get the ful list, visit \"\"\n * @param paymentCurrency Payment currency (e.g., `\"USD\"`, `\"EUR\"`). To get the ful list, visit \"\"\n * @param paymentMethod Payment method (e.g., `\"CARD\"`). To get the ful list, visit \"\"\n * @param chain Chain name (e.g., `\"base\"`)\n * @param country Country code (e.g., `\"US\"`)\n *\n *\n * @returns A URL string to the on-ramp service\n */\n abstract topUp(\n amount: string,\n redirectUrl: string,\n purchaseCurrency?: string,\n paymentCurrency?: string,\n paymentMethod?: string,\n country?: string,\n ): Promise<OnRampUrlResponse>;\n\n /**\n * @internal\n * Cash out funds from the smart wallet to a specified currency via Coinbase CDP off-ramp service\n * @category Ramp\n *\n * @param country\n * @param paymentMethod\n * @param redirectUrl\n * @param sellAmount\n * @param cashoutCurrency\n * @param sellCurrency\n * @returns A URL string to the off-ramp service\n *\n */\n abstract cashOut(\n country: string,\n paymentMethod: string,\n redirectUrl: string,\n sellAmount: string,\n cashoutCurrency?: string,\n sellCurrency?: string,\n ): Promise<OffRampUrlResponse>;\n}\n","import type { CoinbaseCDP } from '@/tools/CoinbaseCDP';\nimport type { RampConfigResponse } from '@/types/ramp';\n\n/**\n * Namespace to manage funding & payouts of an account\n * @public\n * @remarks\n * Contains 2 methods to get available options to top up an account and cash out funds\n * - {@link getTopUpConfig} to get available options to top up an account\n * - {@link getCashOutConfig} to get available options to cash out funds\n *\n * @example\n * ```ts\n * const topUpConfig = await myceliumSDK.funding.getTopUpConfig();\n * const cashOutConfig = await myceliumSDK.funding.getCashOutConfig();\n * ```\n * @category 4. Funding & payouts\n */\nexport class FundingNamespace {\n private readonly coinbaseCDP: CoinbaseCDP | null = null;\n\n constructor(coinbaseCDP: CoinbaseCDP) {\n if (!coinbaseCDP) {\n throw new Error(\n 'Coinbase CDP is not initialized. Please, provide the configuration in the SDK initialization',\n );\n }\n\n this.coinbaseCDP = coinbaseCDP;\n }\n\n /**\n * Return all supported countries and payment methods for on-ramp by Coinbase CDP\n * @public\n * @category Funding\n *\n * @returns @see {@link RampConfigResponse} with supported countries and payment methods for top-up\n * @throws If API returned an error\n */\n async getTopUpConfig(): Promise<RampConfigResponse> {\n return await this.coinbaseCDP!.getOnRampConfig();\n }\n\n /**\n * Return all supported countries and payment methods for off-ramp by Coinbase CDP\n * @public\n * @category Funding\n *\n *\n * @returns @see {@link RampConfigResponse} with supported countries and payment methods for cash out\n * @throws If API returned an error\n */\n async getCashOutConfig(): Promise<RampConfigResponse> {\n return await this.coinbaseCDP!.getOffRampConfig();\n }\n}\n","import { type Chain, createPublicClient, http, type PublicClient } from 'viem';\nimport {\n type BundlerClient,\n type SmartAccount,\n createBundlerClient,\n} from 'viem/account-abstraction';\n\nimport { type SUPPORTED_CHAIN_IDS, CHAINS_MAP } from '@/constants/chains';\nimport type { ChainConfig } from '@/types/chain';\nimport { chainById } from '@/utils/chains';\n\n/**\n * Service for managing supported blockchain networks and their clients\n *\n * @internal\n * @category Infrastructure\n * @remarks\n * Provides RPC and bundler URL access, creates {@link PublicClient} and {@link BundlerClient} instances\n * Central point for chain-level configuration in the SDK\n */\nexport class ChainManager {\n /** Public client for the configured chain */\n private publicClient: PublicClient;\n /** Chain configuration */\n private chainConfigs: ChainConfig;\n /** Map of chain names to chain metadata */\n private chainNames: Record<string, Chain>;\n\n /**\n * Initializes the chain manager with the given configuration\n *\n * @internal\n * @param chains Configuration object for a supported chain\n */\n constructor(chains: ChainConfig) {\n this.chainConfigs = chains;\n this.publicClient = this.createPublicClient(chains);\n this.chainNames = CHAINS_MAP;\n }\n\n /**\n * Utility to validate if a string is a valid HTTP(S) URL\n *\n * @internal\n * @param url Candidate URL\n * @returns True if valid, false otherwise\n */\n private isValidUrl(url: string): boolean {\n return /^https?:\\/\\/.+$/.test(url);\n }\n\n /**\n * Returns a {@link PublicClient} for the given chain ID\n *\n * @internal\n * @category Clients\n * @param chainId Target chain ID\n * @returns {@link PublicClient} instance\n * @throws Error if client is not configured\n */\n getPublicClient(chainId: (typeof SUPPORTED_CHAIN_IDS)[number]): PublicClient {\n const client = this.publicClient;\n if (!client) {\n throw new Error(`No public client configured for chain ID: ${chainId}`);\n }\n return client;\n }\n\n /**\n * Returns a {@link BundlerClient} for the given chain ID\n *\n * @internal\n * @category Clients\n * @param chainId Target chain ID\n * @param account SmartAccount to bind to the bundler client\n * @returns {@link BundlerClient} instance\n * @throws Error if no bundler URL is configured\n */\n getBundlerClient(\n chainId: (typeof SUPPORTED_CHAIN_IDS)[number],\n account: SmartAccount,\n ): BundlerClient {\n const rpcUrl = this.getRpcUrl(chainId);\n const bundlerUrl = this.getBundlerUrl(chainId);\n if (!bundlerUrl) {\n throw new Error(`No bundler URL configured for chain ID: ${chainId}`);\n }\n\n const client = createPublicClient({\n chain: this.getChain(chainId),\n transport: http(rpcUrl),\n });\n\n return createBundlerClient({\n account,\n client,\n transport: http(bundlerUrl),\n chain: this.getChain(chainId),\n });\n }\n\n /**\n * Returns the RPC URL for the given chain ID\n *\n * @internal\n * @category URLs\n * @param chainId Target chain ID\n * @returns RPC URL string\n * @throws Error if chain config is missing or URL is invalid\n */\n getRpcUrl(chainId: (typeof SUPPORTED_CHAIN_IDS)[number]): string {\n const chainConfig = this.chainConfigs;\n if (!chainConfig) {\n throw new Error(`No chain config found for chain ID: ${chainId}`);\n }\n\n if (!this.isValidUrl(chainConfig.rpcUrl)) {\n throw new Error(`Invalid RPC URL for chain ID: ${chainId}`);\n }\n\n return chainConfig.rpcUrl;\n }\n\n /**\n * Returns the bundler URL for the given chain ID\n *\n * @internal\n * @category URLs\n * @param chainId Target chain ID\n * @returns Bundler URL string\n * @throws Error if chain config is missing or URL is invalid\n */\n getBundlerUrl(chainId: (typeof SUPPORTED_CHAIN_IDS)[number]): string | undefined {\n const chainConfig = this.chainConfigs;\n if (!chainConfig) {\n throw new Error(`No chain config found for chain ID: ${chainId}`);\n }\n\n if (!this.isValidUrl(chainConfig.bundlerUrl)) {\n throw new Error(`Invalid bundler URL for chain ID: ${chainId}`);\n }\n return chainConfig.bundlerUrl;\n }\n\n /**\n * Returns the {@link Chain} object for the given chain ID\n *\n * @internal\n * @category Info\n * @param chainId Target chain ID\n * @returns Chain metadata\n * @throws Error if chain is not found\n */\n getChain(chainId: (typeof SUPPORTED_CHAIN_IDS)[number]): Chain {\n const chain = chainById[chainId];\n if (!chain) {\n throw new Error(`Chain not found for ID: ${chainId}`);\n }\n return chain;\n }\n\n /**\n * Returns the currently configured supported chain ID\n *\n * @internal\n * @category Info\n * @returns Supported chain ID\n */\n getSupportedChain() {\n return this.chainConfigs.chainId;\n }\n\n /**\n * Creates a {@link PublicClient} for a chain\n *\n * @internal\n * @category Clients\n * @param chain Chain configuration\n * @returns PublicClient instance\n */\n private createPublicClient(chain: ChainConfig): PublicClient {\n const chainObject = chainById[chain.chainId];\n\n const client = createPublicClient({\n chain: chainObject,\n transport: http(chain.rpcUrl),\n });\n\n return client;\n }\n}\n","import { base, baseSepolia, type Chain } from 'viem/chains';\n\nexport const CHAINS_MAP: Record<string, Chain> = {\n base,\n baseSepolia,\n};\n\nexport const SUPPORTED_CHAIN_IDS = Object.values(CHAINS_MAP).map((c) => c.id);\n\nexport type SupportedChainId = (typeof SUPPORTED_CHAIN_IDS)[number];\n","import { type Chain } from 'viem';\nimport * as viemChains from 'viem/chains';\n\n/** Runtime map: chain ID -> Chain */\nexport const chainById: Record<number, Chain> = Object.values(viemChains).reduce(\n (acc, maybeChain) => {\n // viem/chains exports both chain objects and helpers; pick only real Chain objects\n if (\n maybeChain &&\n typeof maybeChain === 'object' &&\n 'id' in maybeChain &&\n typeof (maybeChain as any).id === 'number' &&\n 'name' in maybeChain\n ) {\n const chain = maybeChain as Chain;\n acc[chain.id] = chain;\n }\n return acc;\n },\n {} as Record<number, Chain>,\n);\n","import type {\n CreateAccountOptions,\n CreateSmartWalletOptions,\n GetEmbeddedWalletOptions,\n GetSmartWalletOptions,\n GetAccountOptions,\n CreateAccountResult,\n} from '@/types/wallet';\nimport type { EmbeddedWallet } from '@/wallet/base/wallets/EmbeddedWallet';\nimport type { SmartWallet } from '@/wallet/base/wallets/SmartWallet';\nimport type { WalletProvider } from '@/wallet/WalletProvider';\n\n/**\n * Wallet namespace to create and retrieve different wallet formats and overall web3 account\n *\n * @public\n * @category 2. Accounts creation and retrieval\n * @remarks\n * This class is returned by {@link MyceliumSDK} and provides a methods to create and retrieve different wallet formats\n * The common methods are:\n * - {@link createAccount} which creates a unified account: a smart wallet with an embedded wallet as signer\n * - {@link getAccount} which retrieves a unified account: a smart wallet using an embedded walletId\n * More advanced option are also available\n *\n * @example\n * ```ts\n * // Create a smart wallet and related embedded wallet\n * const { embeddedWalletId, smartWallet } = await myceliumSDK.wallet.createAccount();\n *\n * // Get the smart wallet using the embedded walletId\n * const smartWallet = await myceliumSDK.wallet.getAccount({\n * embeddedWalletId,\n * });\n * ```\n */\nexport class WalletNamespace {\n /**\n * Internal provider facade that implements the actual logic\n * @internal\n */\n private provider: WalletProvider;\n\n /**\n * Creates a wallet namespace to manage embedded and smart wallets\n * @param provider Unified provider that composes embedded & smart providers\n */\n constructor(provider: WalletProvider) {\n this.provider = provider;\n }\n\n /**\n * Creates an embedded wallet\n *\n * @public\n * @category Creation\n * @remarks\n * Thin wrapper around the embedded wallet provider’s `createWallet`\n *\n * @returns Promise that resolves to the newly created {@link EmbeddedWallet}\n */\n async createEmbeddedWallet(): Promise<EmbeddedWallet> {\n return this.provider.createEmbeddedWallet();\n }\n\n /**\n * Creates a smart wallet (you provide signer and owners)\n *\n * @public\n * @category Creation\n * @remarks\n * Use this when you already control a signer (e.g., `LocalAccount`) and want to\n * create a smart wallet without creating an embedded wallet\n *\n * @param params Smart wallet creation parameters\n * @param params.owners Owners for the smart wallet (addresses or WebAuthn public keys)\n * @param params.signer Local account used for signing transactions\n * @param params.nonce Optional nonce/salt for deterministic address generation (defaults to 0)\n * @returns Promise that resolves to the created {@link SmartWallet}\n */\n async createSmartWallet(params: CreateSmartWalletOptions): Promise<SmartWallet> {\n return this.provider.createSmartWallet(params);\n }\n\n /**\n * A unified a web3 account: creates a smart wallet with an embedded wallet as signer\n *\n * @public\n * @category Creation\n * @remarks\n * Creates an embedded wallet first, inserts its address into the owners array,\n * and uses its account as the signer for the smart wallet\n *\n * @param params Optional creation parameters\n * @param params.owners Optional additional owners. The embedded wallet address is inserted at the specified index\n * @param params.embeddedWalletIndex Optional index at which to insert the embedded wallet address (defaults to end)\n * @param params.nonce Optional nonce/salt for deterministic address generation (defaults to 0)\n * @returns Promise that resolves to the created {@link SmartWallet}\n */\n async createAccount(params?: CreateAccountOptions): Promise<CreateAccountResult> {\n return this.provider.createAccount(params);\n }\n\n /**\n * Gets a unified web3 account: a smart wallet using an embedded wallet as the signer\n *\n * @public\n * @category Retrieval\n * @remarks\n * Looks up an embedded wallet by `walletId` and uses it as signer\n * If neither `walletAddress` nor `deploymentOwners` is provided, defaults to using\n * the embedded wallet as the single owner for deterministic address calculation\n *\n * @param params Retrieval parameters\n * @param params.walletId Embedded wallet ID used to locate the signer wallet\n * @param params.deploymentOwners Optional original deployment owners used for address calculation\n * @param params.signerOwnerIndex Index of the signer within the **current** owners set (defaults to 0)\n * @param params.walletAddress Optional explicit smart wallet address (skips calculation)\n * @param params.nonce Optional nonce used during original creation\n * @returns Promise that resolves to the {@link SmartWallet}\n * @throws Error if the embedded wallet cannot be found\n */\n async getAccount(params: GetAccountOptions) {\n return this.provider.getAccount(params);\n }\n\n /**\n * Gets an existing embedded wallet by ID\n *\n * @public\n * @category Retrieval\n * @param params Retrieval parameters\n * @param params.walletId Embedded wallet ID to retrieve\n * @returns Promise that resolves to the {@link EmbeddedWallet} (or `null/undefined` per provider contract)\n */\n async getEmbeddedWallet(params: GetEmbeddedWalletOptions) {\n return this.provider.getEmbeddedWallet(params);\n }\n\n /**\n * Gets a smart wallet using a provided signer\n *\n * @public\n * @category Retrieval\n * @remarks\n * Use when you already control a signer. Requires either:\n * - `walletAddress`, or\n * - `deploymentOwners` (+ optional `nonce`) to derive the address\n *\n * @param params Retrieval parameters\n * @param params.signer Signer (local account)\n * @param params.deploymentOwners Original deployment owners (required if `walletAddress` is not provided)\n * @param params.signerOwnerIndex Index of the signer within the **current** owners set (defaults to 0)\n * @param params.walletAddress Explicit smart wallet address (skips calculation)\n * @param params.nonce Optional nonce used during original creation\n * @returns Promise that resolves to the {@link SmartWallet}\n * @throws Error if neither `walletAddress` nor `deploymentOwners` is provided\n */\n async getSmartWallet(params: GetSmartWalletOptions) {\n return this.provider.getSmartWallet(params);\n }\n}\n","/**\n * @packageDocumentation\n * Entry point for the Mycelium SDK\n *\n * Exports stable types and the main SDK facade (`MyceliumSDK`)\n * Internal base classes and implementations are not part of the public API\n * and are hidden from public documentation\n */\n\nexport * from '@/public/types';\n\n/** @internal */\nexport { DefaultSmartWallet } from '@/wallet/DefaultSmartWallet';\nexport { FundingNamespace } from '@/ramp/FundingNamespace';\n\nimport { ChainManager } from '@/tools/ChainManager';\nimport type { SmartWalletProvider } from '@/wallet/base/providers/SmartWalletProvider';\nimport { WalletNamespace } from '@/wallet/WalletNamespace';\nimport { type BasicMyceliumSDKConfig, type MyceliumSDKConfig } from '@/types/sdk';\nimport { base } from 'viem/chains';\nimport { DefaultSmartWalletProvider } from '@/wallet/providers/DefaultSmartWalletProvider';\nimport { WalletProvider } from '@/wallet/WalletProvider';\nimport type { EmbeddedWalletProvider } from '@/wallet/base/providers/EmbeddedWalletProvider';\nimport { PrivyEmbeddedWalletProvider } from '@/wallet/providers/PrivyEmbeddedWalletProvider';\nimport { PrivyClient } from '@privy-io/server-auth';\nimport { ProtocolRouter } from '@/router/ProtocolRouter';\nimport { CoinbaseCDP, type CoinbaseCDP as CoinbaseCDPType } from '@/tools/CoinbaseCDP';\nimport { FundingNamespace } from '@/ramp/FundingNamespace';\nimport type { BaseProtocol } from '@/protocols/base/BaseProtocol';\nimport { ProtocolsNamespace } from '@/protocols/ProtocolsNamespace';\nimport { ApiClient } from '@/tools/ApiClient';\nimport type { OnchainConfig } from '@/types/api';\n\n/**\n * Main SDK facade for integrating wallets and protocols.\n *\n * @public\n * @category 1. Getting started\n * @remarks\n * This class encapsulates:\n * - protocol selection and initialization\n * - chain/network management (`ChainManager`),\n * - public wallet namespace (accessible through {@link MyceliumSDK.wallet | wallet}).\n *\n * By default, if no chain config is provided, it uses the public RPC\n * and Bundler for the Base chain\n *\n * The SDK can be initialized in two ways:\n * 1. With an API key - fetches configuration from backend automatically\n * 2. With full configuration - uses provided configuration directly\n *\n * @example\n *\n * import { MyceliumSDK, type MyceliumSDKConfig, type BasicMyceliumSDKConfig } from '@mycelium-sdk/core';\n *\n * // Option 1: Initialize with API key (fetches config from backend)\n * const sdk = await MyceliumSDK.init({\n * apiKey: 'sk_...'\n * });\n *\n * // Option 2: Initialize with full configuration\n * const config: MyceliumSDKConfig = {\n * walletsConfig: { /* ... *\\/ },\n * protocolsSecurityConfig: { riskLevel: 'low' },\n * chain: { /* ... *\\/ },\n * coinbaseCDPConfig: { /* ... *\\/ },\n * integratorId: 'MyceliumApp',\n * };\n * const sdk = await MyceliumSDK.init(config);\n *\n * const {embeddedWalletId, smartWallet} = await sdk.wallet.createAccount();\n * const balance = await smartWallet.getBalance();\n * */\nexport class MyceliumSDK {\n /**\n * Returns a unified wallet namespace to manage embedded/smart wallets and related operations\n * @public\n * @category Wallets\n */\n public readonly wallet: WalletNamespace;\n\n /**\n * Protocol namespace to manage protocol related operations\n * @public\n * @category Protocols\n */\n public readonly protocols: ProtocolsNamespace;\n\n /**\n * Ramp namespace to manage ramp operations. Methods are available on {@link RampNamespace}\n * @internal\n * @remarks\n * If the Coinbase CDP configuration is not provided, the ramp functionality will be disabled.\n * Calling the respective method will throw an error\n * @category Tools\n */\n public readonly fundingNamespace: FundingNamespace | null = null;\n\n /**\n * Chain manager instance to manage chain related entities\n * @internal\n */\n private _chainManager: ChainManager;\n\n /** @internal */\n private embeddedWalletProvider!: EmbeddedWalletProvider;\n\n /** @internal */\n private smartWalletProvider!: SmartWalletProvider;\n\n /**\n * Protocol instance to perform earn related operations with a selected protocol\n * @internal\n */\n private protocol: BaseProtocol;\n\n /** API client for the backend API */\n apiClient: ApiClient | undefined;\n\n /**\n * Coinbase CDP instance to Coinbase related and onchain operations using Coinbase CDP API\n * @remarks\n * If the configuration is not provided, the Coinbase CDP functionality will be disabled.\n * Calling the respective method will throw an error.\n * @internal\n */\n private coinbaseCDP: CoinbaseCDPType | null = null;\n\n /**\n * Initializes the SDK\n * @param config SDK configuration (networks, wallets, protocol router settings)\n * @returns SDK instance\n */\n static async init(config: BasicMyceliumSDKConfig | MyceliumSDKConfig): Promise<MyceliumSDK> {\n let finalConfig: MyceliumSDKConfig;\n let isPremiumAvailable = false;\n\n if ('apiKey' in config && config.apiKey) {\n const apiClient = new ApiClient(config.apiKey);\n isPremiumAvailable = await apiClient.validate();\n\n if (isPremiumAvailable) {\n const apiResponse = await apiClient.sendRequest('config');\n\n if (!apiResponse.success) {\n throw new Error(apiResponse.error || 'Failed to get onchain config');\n }\n\n const backendConfig: OnchainConfig = apiResponse.data as unknown as OnchainConfig;\n\n finalConfig = {\n integratorId: backendConfig.integratorId,\n walletsConfig: {\n embeddedWalletConfig: {\n provider: {\n type: 'privy',\n providerConfig: {\n appId: backendConfig.privyAppId,\n appSecret: backendConfig.privyAppSecret,\n },\n },\n },\n smartWalletConfig: {\n provider: {\n type: 'default',\n },\n },\n },\n chain: {\n chainId: config.chainId || backendConfig.chainId,\n rpcUrl: backendConfig.rpcUrl,\n bundlerUrl: backendConfig.bundlerUrl,\n },\n protocolsSecurityConfig: config.protocolsSecurityConfig,\n coinbaseCDPConfig: {\n apiKeyId: backendConfig.coinbaseCdpApiKey,\n apiKeySecret: backendConfig.coinbaseCdpApiKeySecret,\n },\n };\n\n const sdk = new MyceliumSDK(finalConfig, isPremiumAvailable, apiClient);\n sdk.apiClient = apiClient;\n return sdk;\n }\n }\n\n finalConfig = config as MyceliumSDKConfig;\n\n const sdk = new MyceliumSDK(finalConfig, isPremiumAvailable);\n return sdk;\n }\n\n /**\n * Creates a new SDK instance\n *\n * @param config SDK configuration (networks, wallets, protocol router settings)\n * @throws Throws if an unsupported wallet provider is given\n * @see MyceliumSDKConfig\n */\n constructor(config: MyceliumSDKConfig, isPremiumAvailable: boolean, apiClient?: ApiClient) {\n this._chainManager = new ChainManager(\n config.chain || {\n chainId: base.id,\n rpcUrl: base.rpcUrls.default.http[0],\n bundlerUrl: 'https://public.pimlico.io/v2/8453/rpc',\n },\n );\n\n if (config.protocolsSecurityConfig) {\n // protocolsRouterConfig is the abstract settings that are clear for a dev, e.g. risk level, basic apy, etc\n this.protocol = this.selectProtocol(\n config.protocolsSecurityConfig,\n isPremiumAvailable,\n apiClient,\n );\n } else {\n throw new Error('Protocols router config is required');\n }\n\n if (config.coinbaseCDPConfig) {\n this.coinbaseCDP = new CoinbaseCDP(\n config.coinbaseCDPConfig.apiKeyId,\n config.coinbaseCDPConfig.apiKeySecret,\n config.integratorId,\n this.chainManager,\n );\n\n this.fundingNamespace = new FundingNamespace(this.coinbaseCDP);\n }\n\n this.wallet = this.createWalletNamespace(config.walletsConfig);\n\n this.protocols = new ProtocolsNamespace(this.protocol);\n }\n\n /**\n * Returns the chain manager instance for multi-chain operations\n * @public\n * @remarks\n * More about methods in {@link ChainManager}\n * @category Tools\n *\n * @returns ChainManager instance of the type {@link ChainManager}\n */\n get chainManager(): ChainManager {\n return this._chainManager;\n }\n\n /**\n * Returns a funding namespace to manage top ups & cash outs configurations\n * @public\n * @remarks\n * More about methods in {@link FundingNamespace}\n * @category Tools\n *\n * @returns Funding namespace of the type {@link FundingNamespace}\n */\n get funding(): FundingNamespace {\n if (!this.fundingNamespace) {\n throw new Error(\n 'Ramp namespace is not initialized. Please, provide the configuration in the SDK initialization',\n );\n }\n\n return this.fundingNamespace;\n }\n\n /**\n * Recommends and initializes a protocol based on router settings\n *\n * @internal\n * @param config Protocol router configuration (e.g. risk level)\n * @returns Selected protocol object of the type {@link Protocol}\n */\n private selectProtocol(\n config: MyceliumSDKConfig['protocolsSecurityConfig'],\n isPremiumAvailable: boolean,\n apiClient?: ApiClient,\n ): BaseProtocol {\n const protocolRouter = new ProtocolRouter(this.chainManager, isPremiumAvailable);\n\n const protocol: BaseProtocol = protocolRouter.select();\n\n if (!config) {\n throw new Error('Protocols security config is required');\n }\n\n protocol.init(this.chainManager, config, apiClient);\n\n return protocol;\n }\n\n /**\n * Creates a wallet provider (embedded + smart) and combines them\n *\n * @internal\n * @param config Wallet configuration\n * @returns Configured {@link WalletProvider}\n * @throws If an unsupported wallet provider type is specified\n */\n private createWalletProvider(config: MyceliumSDKConfig['walletsConfig']) {\n if (config.embeddedWalletConfig.provider.type === 'privy') {\n const privyClient = new PrivyClient(\n config.embeddedWalletConfig.provider.providerConfig.appId,\n config.embeddedWalletConfig.provider.providerConfig.appSecret,\n );\n\n this.embeddedWalletProvider = new PrivyEmbeddedWalletProvider(\n privyClient,\n this._chainManager,\n );\n } else {\n throw new Error(\n `Unsupported embedded wallet provider: ${config.embeddedWalletConfig.provider.type}`,\n );\n }\n\n if (!config.smartWalletConfig || config.smartWalletConfig.provider.type === 'default') {\n this.smartWalletProvider = new DefaultSmartWalletProvider(\n this.chainManager,\n this.protocol,\n this.coinbaseCDP,\n );\n } else {\n throw new Error(\n `Unsupported smart wallet provider: ${config.smartWalletConfig.provider.type}`,\n );\n }\n\n const walletProvider = new WalletProvider(\n this.embeddedWalletProvider,\n this.smartWalletProvider,\n );\n\n return walletProvider;\n }\n\n /**\n * Creates the public wallet namespace\n *\n * @internal\n * @param config Wallet configuration.\n * @returns A {@link WalletNamespace} instance\n */\n private createWalletNamespace(config: MyceliumSDKConfig['walletsConfig']) {\n const walletProvider = this.createWalletProvider(config);\n return new WalletNamespace(walletProvider);\n }\n}\n","import { pad, type Address, type LocalAccount } from 'viem';\nimport { type WebAuthnAccount } from 'viem/account-abstraction';\n\nimport { smartWalletFactoryAbi } from '@/abis/smartWalletFactory';\nimport { smartWalletFactoryAddress } from '@/constants/addresses';\nimport type { ChainManager } from '@/tools/ChainManager';\nimport { DefaultSmartWallet } from '@/wallet/DefaultSmartWallet';\nimport { SmartWalletProvider } from '@/wallet/base/providers/SmartWalletProvider';\nimport type { CoinbaseCDP } from '@/tools/CoinbaseCDP';\nimport type { BaseProtocol } from '@/protocols/base/BaseProtocol';\n\n/**\n * Default provider for creating and managing ERC-4337 smart wallets\n *\n * @internal\n * @category Wallets\n * @remarks\n * Factory that composes {@link DefaultSmartWallet} instances\n * Handles deterministic address prediction and instance construction\n */\nexport class DefaultSmartWalletProvider extends SmartWalletProvider {\n /** Manages supported blockchain networks */\n private chainManager: ChainManager;\n\n /** Already initialized protocol provider instance */\n private protocolProvider: BaseProtocol;\n\n /** Coinbase CDP instance to interact with Coinbase CDP API */\n private coinbaseCDP: CoinbaseCDP | null;\n\n /**\n * Initializes the smart wallet provider\n *\n * @internal\n * @param chainManager Manager for chains and viem clients\n * @param protocol Selected protocol descriptor that exposes an initialized instance\n */\n constructor(chainManager: ChainManager, protocol: BaseProtocol, coinbaseCDP: CoinbaseCDP | null) {\n super();\n this.chainManager = chainManager;\n this.protocolProvider = protocol;\n this.coinbaseCDP = coinbaseCDP;\n }\n\n /**\n * Creates a new smart wallet instance that deploys on first use\n *\n * @internal\n * @category Creation\n * @remarks\n * Address is derived deterministically from `owners` and `nonce`\n *\n * @param params Parameters for wallet creation\n * @param params.owners Owners as EVM addresses or WebAuthn owners\n * @param params.signer Local account used to sign UserOperations and transactions\n * @param params.nonce Optional salt for deterministic address calculation, default 0\n * @returns Promise that resolves to a {@link DefaultSmartWallet} instance\n */\n async createWallet(params: {\n owners: Array<Address | WebAuthnAccount>;\n signer: LocalAccount;\n nonce?: bigint;\n }): Promise<DefaultSmartWallet> {\n const { owners, signer, nonce } = params;\n return new DefaultSmartWallet(\n owners,\n signer,\n this.chainManager,\n this.protocolProvider,\n this.coinbaseCDP,\n undefined,\n undefined,\n nonce,\n );\n }\n\n /**\n * Predicts the deterministic smart wallet address for the given owners and nonce\n *\n * @internal\n * @category Addressing\n * @remarks\n * Uses the smart wallet factory `getAddress` to compute the CREATE2 address\n *\n * @param params Address prediction parameters\n * @param params.owners Owners as EVM addresses or WebAuthn owners\n * @param params.nonce Optional salt for deterministic address calculation, default 0\n * @returns Promise that resolves to the predicted wallet address\n * @throws Error if no supported chains are configured\n * @throws Error if an owner has an invalid type\n */\n async getWalletAddress(params: { owners: Array<Address | WebAuthnAccount>; nonce?: bigint }) {\n const { owners, nonce = 0n } = params;\n const owners_bytes = owners.map((owner) => {\n if (typeof owner === 'string') {\n return pad(owner);\n }\n if (owner.type === 'webAuthn') {\n return owner.publicKey;\n }\n throw new Error('invalid owner type');\n });\n\n // Factory is the same accross all chains, so we can use the first chain to get the wallet address\n const supportedChain = this.chainManager.getSupportedChain();\n if (!supportedChain) {\n throw new Error('No supported chains configured');\n }\n const publicClient = this.chainManager.getPublicClient(supportedChain);\n const smartWalletAddress = await publicClient.readContract({\n abi: smartWalletFactoryAbi,\n address: smartWalletFactoryAddress,\n functionName: 'getAddress',\n args: [owners_bytes, nonce],\n });\n return smartWalletAddress;\n }\n\n /**\n * Returns a smart wallet instance for an already deployed address\n *\n * @internal\n * @category Retrieval\n * @remarks\n * Use when you already know the deployment address and want an instance bound to a signer\n *\n * @param params Retrieval parameters\n * @param params.walletAddress Deployed smart wallet address\n * @param params.signer Local account to operate the wallet\n * @param params.ownerIndex Optional index of `signer` within the current owners set, default 0\n * @returns A {@link DefaultSmartWallet} instance\n */\n getWallet(params: {\n walletAddress: Address;\n signer: LocalAccount;\n ownerIndex?: number;\n }): DefaultSmartWallet {\n const { walletAddress, signer, ownerIndex } = params;\n return new DefaultSmartWallet(\n [signer.address],\n signer,\n this.chainManager,\n this.protocolProvider,\n this.coinbaseCDP,\n walletAddress,\n ownerIndex,\n );\n }\n}\n","import type { Address, LocalAccount } from 'viem';\nimport type { WebAuthnAccount } from 'viem/account-abstraction';\nimport type { SmartWallet } from '@/wallet/base/wallets/SmartWallet';\n\n/**\n * Abstract base class for smart wallet providers\n *\n * @internal\n * @category Wallet Providers\n * @remarks\n * Defines the interface for factories that create and manage {@link SmartWallet} instances\n * Extended by implementations such as {@link DefaultSmartWalletProvider}\n */\nexport abstract class SmartWalletProvider {\n /**\n * Creates a new smart wallet instance that will be deployed on first transaction\n *\n * @internal\n * @category Creation\n * @remarks\n * Address is calculated deterministically using owners and nonce\n *\n * @param params Wallet creation parameters\n * @param params.owners Array of wallet owners (addresses or WebAuthn accounts)\n * @param params.signer Local account used for signing\n * @param params.nonce Optional nonce for address derivation, default 0\n * @returns Promise resolving to a {@link SmartWallet} instance\n */\n abstract createWallet(params: {\n owners: Array<Address | WebAuthnAccount>;\n signer: LocalAccount;\n nonce?: bigint;\n }): Promise<SmartWallet>;\n\n /**\n * Returns a smart wallet instance for an already deployed contract\n *\n * @internal\n * @category Retrieval\n * @remarks\n * Use when the wallet address is already known\n *\n * @param params Wallet retrieval parameters\n * @param params.walletAddress Deployed smart wallet address\n * @param params.signer Local account to operate the wallet\n * @param params.ownerIndex Optional index of signer in the owners list, default 0\n * @returns A {@link SmartWallet} instance\n */\n abstract getWallet(params: {\n walletAddress: Address;\n signer: LocalAccount;\n ownerIndex?: number;\n }): SmartWallet;\n\n /**\n * Predicts the deterministic address of a smart wallet\n *\n * @internal\n * @category Addressing\n * @remarks\n * Uses CREATE2 with owners and nonce to calculate the wallet address\n *\n * @param params Prediction parameters\n * @param params.owners Array of wallet owners (addresses or WebAuthn accounts)\n * @param params.nonce Optional nonce, default 0\n * @returns Promise resolving to the predicted {@link Address}\n */\n abstract getWalletAddress(params: {\n owners: Array<Address | WebAuthnAccount>;\n nonce?: bigint;\n }): Promise<Address>;\n}\n","import type { Address } from 'viem';\nimport type { WebAuthnAccount } from 'viem/account-abstraction';\n\nimport type {\n CreateSmartWalletOptions,\n CreateAccountOptions,\n GetEmbeddedWalletOptions,\n GetSmartWalletOptions,\n GetAccountOptions,\n CreateAccountResult,\n} from '@/types/wallet';\nimport type { EmbeddedWallet } from '@/wallet/base/wallets/EmbeddedWallet';\nimport type { SmartWallet } from '@/wallet/base/wallets/SmartWallet';\nimport type { EmbeddedWalletProvider } from '@/wallet/base/providers/EmbeddedWalletProvider';\nimport type { SmartWalletProvider } from '@/wallet/base/providers/SmartWalletProvider';\n\n/**\n * Unified Wallet Provider class\n *\n * @internal\n * @category Wallets\n * @remarks\n * Internal facade that composes an embedded wallet provider and a smart wallet provider\n * and exposes higher-level creation/retrieval flows. Not exported from user's usage\n *\n * Used in a higher level class - {@link WalletNamespace}\n *\n * Typical flows:\n * - Create embedded wallet only: {@link createEmbeddedWallet}\n * - Create smart wallet only (you provide signer/owners): {@link createSmartWallet}\n * - Create smart wallet with embedded wallet as signer: {@link createWalletWithEmbeddedSigner}\n * - Get smart wallet using embedded wallet as signer: {@link getSmartWalletWithEmbeddedSigner}\n * - Get smart wallet using a provided signer: {@link getSmartWallet}\n */\nexport class WalletProvider {\n /**\n * Embedded wallet provider instance\n * @internal\n */\n public readonly embeddedWalletProvider: EmbeddedWalletProvider;\n\n /**\n * Smart wallet provider instance\n * @internal\n */\n public readonly smartWalletProvider: SmartWalletProvider;\n\n /**\n * Creates a unified wallet provider\n *\n * @internal\n * @param embeddedWalletProvider Provider for embedded wallet operations\n * @param smartWalletProvider Provider for smart wallet operations\n */\n constructor(\n embeddedWalletProvider: EmbeddedWalletProvider,\n smartWalletProvider: SmartWalletProvider,\n ) {\n this.embeddedWalletProvider = embeddedWalletProvider;\n this.smartWalletProvider = smartWalletProvider;\n }\n\n /**\n * Creates an embedded wallet\n *\n * @internal\n * @remarks\n * Thin wrapper around the embedded wallet provider’s `createWallet`\n *\n * @returns Promise that resolves to the newly created {@link EmbeddedWallet}\n */\n async createEmbeddedWallet(): Promise<EmbeddedWallet> {\n return this.embeddedWalletProvider.createWallet();\n }\n\n /**\n * Creates a smart wallet (you provide signer and owners)\n *\n * @internal\n * @remarks\n * Use when you already control a signer and want to create a smart\n * wallet without creating an embedded wallet\n *\n * @param params Smart wallet creation parameters\n * @param params.owners Owners array for the smart wallet (EVM addresses or WebAuthn owners)\n * @param params.signer Signer (local account) used for transactions\n * @param params.nonce Optional salt/nonce for deterministic address calculation (defaults to 0)\n * @returns Promise that resolves to the created {@link SmartWallet}\n */\n async createSmartWallet(params: CreateSmartWalletOptions): Promise<SmartWallet> {\n const { owners, signer, nonce } = params;\n\n return this.smartWalletProvider.createWallet({\n owners,\n signer,\n nonce,\n });\n }\n\n /**\n * Creates a smart wallet with an embedded wallet as signer\n *\n * @internal\n * @remarks\n * Creates an embedded wallet first, then inserts its address into the owners array\n * and uses its account as the signer for the smart wallet. Default SDK option, embedded wallets manager is necessary to be provided\n *\n * @param params Optional creation parameters\n * @param params.owners Optional additional owners. The embedded wallet address is inserted at the specified index\n * @param params.embeddedWalletIndex Optional index where the embedded wallet address should be inserted (defaults to the end)\n * @param params.nonce Optional salt/nonce for deterministic address calculation (defaults to 0)\n * @returns Promise that resolves to the created {@link SmartWallet}\n */\n async createAccount(params?: CreateAccountOptions): Promise<CreateAccountResult> {\n const { owners: ownersParam, embeddedWalletIndex, nonce } = params || {};\n const embeddedWallet = await this.embeddedWalletProvider.createWallet();\n\n if (!embeddedWallet.walletId) {\n throw new Error('Failed to create embedded wallet. No wallet ID returned');\n }\n\n const account = await embeddedWallet.account();\n\n let owners: Array<Address | WebAuthnAccount>;\n if (ownersParam) {\n owners = [...ownersParam]; // Create a copy to avoid mutating the original\n const insertIndex = embeddedWalletIndex ?? owners.length; // Default to end if not specified\n owners.splice(insertIndex, 0, embeddedWallet.address); // Insert embedded wallet at specified index\n } else {\n owners = [embeddedWallet.address]; // Default to just the embedded wallet\n }\n\n const smartWallet = await this.smartWalletProvider.createWallet({\n owners,\n signer: account,\n nonce,\n });\n\n return {\n embeddedWalletId: embeddedWallet.walletId,\n smartWallet,\n };\n }\n\n /**\n * Gets a unified web3 account: a smart wallet using an embedded wallet as the signer\n *\n * @internal\n * @remarks\n * Fetches an embedded wallet by `walletId` and uses it as signer.\n * If neither `walletAddress` nor `deploymentOwners` is provided, defaults to using\n * the embedded wallet as the single owner for deterministic address calculation\n *\n * @param params Retrieval parameters\n * @param params.walletId Embedded wallet ID used to locate the signer wallet\n * @param params.deploymentOwners Optional original deployment owners used for address calculation\n * @param params.signerOwnerIndex Index of the signer in the **current** owners set (defaults to 0)\n * @param params.walletAddress Optional explicit smart wallet address (skips calculation)\n * @param params.nonce Optional nonce used during original creation\n * @returns Promise that resolves to the {@link SmartWallet}\n * @throws Error if the embedded wallet cannot be found\n */\n async getAccount(params: GetAccountOptions) {\n const { walletId, deploymentOwners, walletAddress } = params;\n const embeddedWallet = await this.embeddedWalletProvider.getWallet({\n walletId,\n });\n if (!embeddedWallet) {\n throw new Error('Embedded wallet not found');\n }\n const account = await embeddedWallet.account();\n\n // If neither walletAddress nor deploymentOwners provided, default to embedded wallet as single owner\n const finalDeploymentOwners =\n deploymentOwners || (walletAddress ? undefined : [embeddedWallet.address]);\n\n return this.getSmartWallet({\n signer: account,\n ...params,\n deploymentOwners: finalDeploymentOwners,\n });\n }\n\n /**\n * Gets an existing embedded wallet by ID\n *\n * @internal\n * @param params Retrieval parameters\n * @param params.walletId Embedded wallet ID\n * @returns Promise that resolves to the {@link EmbeddedWallet}, or `null/undefined` per provider’s contract\n */\n async getEmbeddedWallet(params: GetEmbeddedWalletOptions) {\n const { walletId } = params;\n return this.embeddedWalletProvider.getWallet({\n walletId,\n });\n }\n\n /**\n * Gets a smart wallet using a provided signer\n *\n * @internal\n * @remarks\n * Use when you already control a `LocalAccount` signer\n * Requires either:\n * - `walletAddress`, or\n * - `deploymentOwners` (+ optional `nonce`) to deterministically derive the address\n *\n * @param params Retrieval parameters\n * @param params.signer Signer (local account)\n * @param params.deploymentOwners Original deployment owners (required if `walletAddress` is not provided)\n * @param params.signerOwnerIndex Index of `signer` within the **current** owners set (defaults to 0)\n * @param params.walletAddress Explicit smart wallet address (skips calculation)\n * @param params.nonce Optional nonce used during original creation\n * @returns Promise that resolves to the {@link SmartWallet}\n * @throws Error if neither `walletAddress` nor `deploymentOwners` is provided\n */\n async getSmartWallet(params: GetSmartWalletOptions) {\n const {\n signer,\n deploymentOwners,\n signerOwnerIndex,\n walletAddress: walletAddressParam,\n nonce,\n } = params;\n\n if (!walletAddressParam && !deploymentOwners) {\n try {\n throw new Error(\n 'Either walletAddress or deploymentOwners array must be provided to locate the smart wallet',\n );\n } catch {\n throw new Error(\n 'Either walletAddress or deploymentOwners array must be provided to locate the smart wallet',\n );\n }\n }\n\n const ownerIndex = signerOwnerIndex ?? 0;\n\n const walletAddress =\n walletAddressParam ||\n (await this.smartWalletProvider.getWalletAddress({\n // Safe to use ! since we validated above\n owners: deploymentOwners!,\n nonce,\n }));\n return this.smartWalletProvider.getWallet({\n walletAddress,\n signer,\n ownerIndex,\n });\n }\n}\n","import type { PrivyClient } from '@privy-io/server-auth';\nimport { getAddress } from 'viem';\n\nimport type { ChainManager } from '@/tools/ChainManager';\nimport { PrivyWallet } from '@/wallet/PrivyWallet';\nimport { EmbeddedWalletProvider } from '@/wallet/base/providers/EmbeddedWalletProvider';\nimport { logger } from '@/tools/Logger';\n\n/**\n * Options for querying all Privy wallets\n *\n * @internal\n * @category Wallets\n */\nexport interface PrivyProviderGetAllWalletsOptions {\n /** Maximum number of wallets to return */\n limit?: number;\n /** Cursor for pagination */\n cursor?: string;\n}\n\n/**\n * Embedded wallet provider backed by Privy\n *\n * @internal\n * @category Wallets\n * @remarks\n * Wraps Privy client API for creating, retrieving, and listing wallets\n * Produces {@link PrivyWallet} instances used internally by the SDK\n */\nexport class PrivyEmbeddedWalletProvider extends EmbeddedWalletProvider {\n /** Privy client instance */\n public privy: PrivyClient;\n /** Manager for supported chains and clients */\n private chainManager: ChainManager;\n /**\n * Creates a new Privy-backed embedded wallet provider\n *\n * @internal\n * @param privyClient Privy client instance\n * @param chainManager Chain and client manager\n */\n constructor(privyClient: PrivyClient, chainManager: ChainManager) {\n super();\n this.privy = privyClient;\n this.chainManager = chainManager;\n }\n\n /**\n * Creates a new wallet using Privy’s wallet API\n *\n * @internal\n * @category Creation\n * @returns Promise that resolves to a new {@link PrivyWallet} instance\n * @throws Error if wallet creation fails\n */\n async createWallet(): Promise<PrivyWallet> {\n try {\n const wallet = await this.privy.walletApi.createWallet({\n chainType: 'ethereum',\n });\n\n const walletInstance = new PrivyWallet(\n this.privy,\n wallet.id,\n getAddress(wallet.address),\n this.chainManager,\n );\n return walletInstance;\n } catch (error) {\n logger.error('Failed to create wallet: ', error, 'PrivyEmbeddedWalletProvider');\n throw new Error(`Failed to create wallet: ${error}`);\n }\n }\n\n /**\n * Retrieves a wallet by its ID via Privy\n *\n * @internal\n * @category Retrieval\n * @param params Parameters containing walletId\n * @returns Promise that resolves to a {@link PrivyWallet} instance\n * @throws Error if the wallet cannot be retrieved\n */\n async getWallet(params: { walletId: string }): Promise<PrivyWallet> {\n try {\n const wallet = await this.privy.walletApi.getWallet({\n id: params.walletId,\n });\n\n const walletInstance = new PrivyWallet(\n this.privy,\n wallet.id,\n getAddress(wallet.address),\n this.chainManager,\n );\n return walletInstance;\n } catch {\n throw new Error(`Failed to get wallet with id: ${params.walletId}`);\n }\n }\n\n /**\n * Retrieves all wallets from Privy with optional filtering and pagination\n *\n * @internal\n * @category Retrieval\n * @param options Optional filtering and pagination parameters\n * @returns Promise that resolves to an array of {@link PrivyWallet} instances\n * @throws Error if wallets cannot be retrieved\n */\n async getAllWallets(options?: PrivyProviderGetAllWalletsOptions): Promise<PrivyWallet[]> {\n try {\n const response = await this.privy.walletApi.getWallets({\n limit: options?.limit,\n cursor: options?.cursor,\n });\n\n return response.data.map((wallet) => {\n const walletInstance = new PrivyWallet(\n this.privy,\n wallet.id,\n getAddress(wallet.address),\n this.chainManager,\n );\n return walletInstance;\n });\n } catch {\n throw new Error('Failed to retrieve wallets');\n }\n }\n}\n","import type { PrivyClient } from '@privy-io/server-auth';\nimport { createViemAccount, type GetViemAccountInputType } from '@privy-io/server-auth/viem';\nimport {\n type Address,\n createWalletClient,\n type Hash,\n http,\n type LocalAccount,\n type WalletClient,\n} from 'viem';\nimport { unichain } from 'viem/chains';\n\nimport type { SupportedChainId } from '@/constants/chains';\nimport type { ChainManager } from '@/tools/ChainManager';\nimport { EmbeddedWallet } from '@/wallet/base/wallets/EmbeddedWallet';\nimport type { TransactionData } from '@/types/transaction';\nimport { logger } from '@/tools/Logger';\n\n/**\n * Internal embedded wallet implementation backed by Privy\n *\n * @internal\n * @category Wallets\n * @remarks\n * Wraps Privy’s server-auth wallet to expose a viem-compatible {@link LocalAccount}\n * and {@link WalletClient}\n * Not exported in the public API — composed by higher-level providers/namespaces\n */\nexport class PrivyWallet extends EmbeddedWallet {\n /** Privy wallet ID */\n public override walletId: string;\n /** Privy client instance */\n private privyClient: PrivyClient;\n /** Network and client manager */\n private chainManager: ChainManager;\n /**\n * Creates a Privy-backed embedded wallet\n *\n * @internal\n * @param privyClient Privy client used to access wallet and signing APIs\n * @param walletId Privy wallet identifier\n * @param address Wallet EVM address\n * @param chainManager Chain and client manager\n */\n constructor(\n privyClient: PrivyClient,\n walletId: string,\n address: Address,\n chainManager: ChainManager,\n ) {\n super(address, walletId);\n this.privyClient = privyClient;\n this.walletId = walletId;\n this.chainManager = chainManager;\n }\n\n /**\n * Returns a viem-compatible {@link LocalAccount} for this Privy wallet\n *\n * @internal\n * @category Accounts\n * @remarks\n * Uses Privy’s signing infra under the hood while exposing the standard viem interface\n *\n * @returns Promise that resolves to a {@link LocalAccount}\n * @throws Error if wallet retrieval or account construction fails\n */\n async account(): Promise<LocalAccount> {\n const account = await createViemAccount({\n walletId: this.walletId,\n address: this.address,\n\n privy: this.privyClient as unknown as GetViemAccountInputType['privy'],\n });\n return account;\n }\n\n /**\n * Creates a viem {@link WalletClient} for a given chain\n *\n * @internal\n * @category Accounts\n * @param chainId Target chain ID\n * @returns Promise that resolves to a {@link WalletClient}\n * @throws Error if the chain is unsupported or client creation fails\n */\n async walletClient(chainId: SupportedChainId): Promise<WalletClient> {\n const account = await this.account();\n return createWalletClient({\n account,\n chain: this.chainManager.getChain(chainId),\n transport: http(this.chainManager.getRpcUrl(chainId)),\n });\n }\n\n /**\n * Signs a transaction without broadcasting it\n *\n * @internal\n * @category Signing\n * @param transactionData Transaction payload to sign\n * @returns Promise that resolves to a signed transaction hex string\n */\n async sign(transactionData: TransactionData): Promise<`0x${string}`> {\n return (await this.signOnly(transactionData)) as `0x${string}`;\n }\n\n /**\n * Produces a signed transaction using Privy’s wallet API without sending it\n *\n * @internal\n * @category Signing\n * @remarks\n * Estimates gas, fees, and nonce to build a complete EIP-1559 transaction\n * Per Privy docs, if any gas field is set, all must be set\n *\n * @param transactionData Transaction payload to sign\n * @returns Promise that resolves to a signed transaction string\n * @throws Error if signing fails\n */\n async signOnly(transactionData: TransactionData): Promise<string> {\n try {\n const privyWallet = await this.privyClient.walletApi.getWallet({\n id: this.walletId,\n });\n // Get public client for gas estimation\n const publicClient = this.chainManager.getPublicClient(unichain.id); // Unichain\n\n // Estimate gas limit\n const gasLimit = await publicClient.estimateGas({\n account: privyWallet.address as Address,\n to: transactionData.to,\n data: transactionData.data as `0x${string}`,\n value: BigInt(transactionData.value || 0),\n });\n\n // Get current gas price and fee data\n const feeData = await publicClient.estimateFeesPerGas();\n\n // Get current nonce for the wallet - manual management since Privy isn't handling it properly\n const nonce = await publicClient.getTransactionCount({\n address: privyWallet.address as Address,\n blockTag: 'pending', // Use pending to get the next nonce including any pending txs\n });\n\n // According to Privy docs: if you provide ANY gas parameters, you must provide ALL of them\n const txParams: any = {\n to: transactionData.to,\n data: transactionData.data as `0x${string}`,\n value: transactionData.value,\n chainId: 130, // Unichain\n type: 2, // EIP-1559\n gasLimit: `0x${gasLimit.toString(16)}`,\n maxFeePerGas: `0x${(feeData.maxFeePerGas || BigInt(1000000000)).toString(16)}`, // fallback to 1 gwei\n maxPriorityFeePerGas: `0x${(feeData.maxPriorityFeePerGas || BigInt(100000000)).toString(16)}`, // fallback to 0.1 gwei\n nonce: `0x${nonce.toString(16)}`, // Explicitly provide the correct nonce\n };\n\n logger.info(\n 'Complete tx params: ',\n {\n txParamsType: txParams.type,\n txParamsNonce: nonce,\n txParamsLimit: gasLimit,\n txParamsMaxFee: feeData.maxFeePerGas || 'fallback',\n txParamsPriority: feeData.maxPriorityFeePerGas || 'fallback',\n },\n 'PrivyWallet',\n );\n\n const response = await this.privyClient.walletApi.ethereum.signTransaction({\n walletId: this.walletId,\n transaction: txParams,\n });\n\n return response.signedTransaction;\n } catch (error) {\n throw new Error(\n `Failed to sign transaction for wallet ${this.walletId}: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`,\n );\n }\n }\n\n /**\n * Broadcasts a previously-signed transaction\n *\n * @internal\n * @category Sending\n * @param signedTransaction Signed transaction hex\n * @param publicClient Viem public client to send the transaction\n * @returns Promise that resolves to the transaction {@link Hash}\n * @throws Error if submission fails\n */\n async send(signedTransaction: string, publicClient: any): Promise<Hash> {\n try {\n const hash = await publicClient.sendRawTransaction({\n serializedTransaction: signedTransaction as `0x${string}`,\n });\n return hash;\n } catch (error) {\n throw new Error(\n `Failed to send transaction: ${error instanceof Error ? error.message : 'Unknown error'}`,\n );\n }\n }\n}\n","import type { Address, LocalAccount, WalletClient } from 'viem';\n\nimport type { SupportedChainId } from '@/constants/chains';\n\n/**\n * Abstract base class for embedded wallet implementations\n *\n * @internal\n * @category Wallets\n * @remarks\n * Provides a standard interface for embedded wallets (Privy, Dynamic, etc.)\n * Can be used as a signer for smart wallets when the embedded wallet is an owner\n */\nexport abstract class EmbeddedWallet {\n /** Ethereum address of the wallet */\n public readonly address: Address;\n /** Optional provider-specific wallet identifier */\n public readonly walletId?: string;\n\n /**\n * Creates an embedded wallet instance\n *\n * @internal\n * @param address Ethereum address of the wallet\n * @param walletId Optional provider-specific identifier\n */\n constructor(address: Address, walletId?: string) {\n this.address = address;\n this.walletId = walletId;\n }\n\n /**\n * Returns a {@link LocalAccount} that can sign transactions and messages\n *\n * @internal\n * @category Accounts\n * @remarks\n * Useful for smart wallet operations if the embedded wallet is included as an owner\n *\n * @returns Promise resolving to a {@link LocalAccount}\n */\n abstract account(): Promise<LocalAccount>;\n\n /**\n * Returns a {@link WalletClient} for interacting with contracts on a specific chain\n *\n * @internal\n * @category Accounts\n * @param chainId Target chain ID\n * @returns Promise resolving to a {@link WalletClient} configured for the given chain\n */\n abstract walletClient(chainId: SupportedChainId): Promise<WalletClient>;\n}\n","export enum LogLevel {\n DEBUG = 0,\n INFO = 1,\n WARN = 2,\n ERROR = 3,\n}\n\nexport interface LogEntry {\n timestamp: string;\n level: LogLevel;\n message: string;\n data?: any;\n context?: string;\n}\n","/* eslint-disable no-console */\nimport { LogLevel, type LogEntry } from '@/types/logger';\n\n/**\n * Logger service\n *\n * @internal\n * @category Utilities\n * @remarks\n * Provides a singleton logger with configurable log levels, console output,\n * and an in-memory log buffer. Supports exporting logs for debugging or analytics\n */\nexport class Logger {\n private static instance: Logger;\n private logLevel: LogLevel;\n private logs: LogEntry[] = [];\n private maxLogs: number = 1000;\n\n /**\n * Create a new logger instance\n * @param logLevel Initial log level, defaults to DEBUG\n */\n private constructor(logLevel: LogLevel = LogLevel.DEBUG) {\n this.logLevel = logLevel;\n }\n /**\n * Get singleton instance of the logger\n * @param logLevel Optional log level to initialize if instance not yet created\n * @returns Logger instance\n */\n public static getInstance(logLevel?: LogLevel): Logger {\n if (!Logger.instance) {\n Logger.instance = new Logger(logLevel);\n }\n return Logger.instance;\n }\n /** Set the log level */\n public setLogLevel(level: LogLevel): void {\n this.logLevel = level;\n }\n /** Get the current log level */\n public getLogLevel(): LogLevel {\n return this.logLevel;\n }\n /** Internal check if a message should be logged */\n private shouldLog(level: LogLevel): boolean {\n return level >= this.logLevel;\n }\n /** Format log message into a readable string */\n private formatMessage(level: LogLevel, message: string, data?: any, context?: string): string {\n const timestamp = new Date().toISOString();\n const levelName = LogLevel[level];\n const contextStr = context ? `[${context}]` : '';\n\n return `${timestamp} ${levelName}${contextStr}: ${message}`;\n }\n /** Add a log entry and output to console */\n private addLog(level: LogLevel, message: string, data?: any, context?: string): void {\n if (!this.shouldLog(level)) {\n return;\n }\n\n const logEntry: LogEntry = {\n timestamp: new Date().toISOString(),\n level,\n message,\n data,\n context,\n };\n\n this.logs.push(logEntry);\n\n // Keep only the last maxLogs entries\n if (this.logs.length > this.maxLogs) {\n this.logs = this.logs.slice(-this.maxLogs);\n }\n\n // Console output with colors\n const formattedMessage = this.formatMessage(level, message, data, context);\n\n switch (level) {\n case LogLevel.DEBUG:\n console.debug(`🔍 ${formattedMessage}`, data || '');\n break;\n case LogLevel.INFO:\n console.info(`ℹ️ ${formattedMessage}`, data || '');\n break;\n case LogLevel.WARN:\n console.warn(`⚠️ ${formattedMessage}`, data || '');\n break;\n case LogLevel.ERROR:\n console.error(`❌ ${formattedMessage}`, data || '');\n break;\n }\n }\n /** Log a debug message */\n public debug(message: string, data?: any, context?: string): void {\n this.addLog(LogLevel.DEBUG, message, data, context);\n }\n /** Log an info message */\n public info(message: string, data?: any, context?: string): void {\n this.addLog(LogLevel.INFO, message, data, context);\n }\n /** Log a warning message */\n public warn(message: string, data?: any, context?: string): void {\n this.addLog(LogLevel.WARN, message, data, context);\n }\n /** Log an error message */\n public error(message: string, data?: any, context?: string): void {\n this.addLog(LogLevel.ERROR, message, data, context);\n }\n /** Get all logs */\n public getLogs(): LogEntry[] {\n return [...this.logs];\n }\n /** Get logs by level */\n public getLogsByLevel(level: LogLevel): LogEntry[] {\n return this.logs.filter((log) => log.level === level);\n }\n /** Clear all logs */\n public clearLogs(): void {\n this.logs = [];\n }\n /** Export logs as a JSON string */\n public exportLogs(): string {\n return JSON.stringify(this.logs, null, 2);\n }\n /** Set maximum number of logs to retain in memory */\n public setMaxLogs(max: number): void {\n this.maxLogs = max;\n }\n}\n/** Global logger instance */\nexport const logger = Logger.getInstance();\n/**\n * Shorthand log methods\n * @internal\n */\nexport const log = {\n debug: (message: string, data?: any, context?: string) => logger.debug(message, data, context),\n info: (message: string, data?: any, context?: string) => logger.info(message, data, context),\n warn: (message: string, data?: any, context?: string) => logger.warn(message, data, context),\n error: (message: string, data?: any, context?: string) => logger.error(message, data, context),\n};\n","import type { EmbeddedWallet } from '@/wallet/base/wallets/EmbeddedWallet';\n\n/**\n * Abstract base class for embedded wallet providers\n *\n * @internal\n * @category Wallet Providers\n * @remarks\n * Defines the interface for providers that manage {@link EmbeddedWallet} instances\n * Extended by implementations such as {@link PrivyEmbeddedWalletProvider}\n */\nexport abstract class EmbeddedWalletProvider {\n /**\n * Creates a new embedded wallet instance\n *\n * @internal\n * @category Creation\n * @remarks\n * Uses the provider’s infrastructure to provision a new embedded wallet ready for signing\n *\n * @returns Promise resolving to a new {@link EmbeddedWallet}\n */\n abstract createWallet(): Promise<EmbeddedWallet>;\n\n /**\n * Retrieves an existing embedded wallet by its unique identifier\n *\n * @internal\n * @category Retrieval\n * @remarks\n * The wallet must have been created previously through this provider\n *\n * @param params Wallet retrieval parameters\n * @param params.walletId Unique identifier for the embedded wallet\n * @returns Promise resolving to an {@link EmbeddedWallet}\n * @throws Error if no wallet with the specified ID exists\n */\n abstract getWallet(params: { walletId: string }): Promise<EmbeddedWallet>;\n}\n","import type { ChainManager } from '@/tools/ChainManager';\nimport {\n type Address,\n type LocalAccount,\n erc20Abi,\n createWalletClient,\n http,\n parseGwei,\n type PublicClient,\n} from 'viem';\nimport type { SupportedChainId } from '@/constants/chains';\nimport type { SmartWallet } from '@/wallet/base/wallets/SmartWallet';\nimport type {\n VaultInfo,\n VaultBalance,\n VaultTxnResult,\n Vaults,\n ProtocolsSecurityConfig,\n} from '@/types/protocols/general';\nimport type { ApiClient } from '@/tools/ApiClient';\n\n/**\n * Base Protocol\n *\n * @internal\n * @abstract\n * @category Protocols\n * @remarks\n * Abstract class defining the contract for protocol integrations (e.g. Spark, Beefy, Aave, Morpho)\n * Provides lifecycle hooks (`init`) and required methods for vault discovery, deposit, withdrawal,\n * and balance tracking\n *\n * Generic parameters allow protocol-specific typing for vault info, balances, and transaction results\n */\nexport abstract class BaseProtocol {\n /** Selected chain ID for the protocol */\n protected selectedChainId: SupportedChainId | undefined;\n\n /** Public client to make requests to RPC */\n protected publicClient: PublicClient | undefined;\n\n /** Chain manager instance for network access */\n public chainManager: ChainManager | undefined;\n\n /**\n * Initialize the protocol\n * @param chainManager Chain manager for accessing RPC and bundler clients\n */\n abstract init(\n chainManager: ChainManager,\n protocolsSecurityConfig: ProtocolsSecurityConfig,\n apiClient?: ApiClient,\n ): Promise<void>;\n\n /**\n * Ensure the protocol has been initialized\n * @throws Error if `init()` has not been called\n */\n protected ensureInitialized(): void {\n if (!this.chainManager) {\n throw new Error('Protocol must be initialized before use. Call init() first.');\n }\n }\n\n /**\n * Get the best vault for deposits\n * @returns Single vault considered optimal for deposit\n */\n abstract getBestVaults(\n stableVaultsLimit?: number,\n nonStableVaultsLimit?: number,\n ): Promise<Vaults> | Vaults;\n\n /**\n * Deposit funds into a vault\n * @param vaultInfo Vault information\n * @param amount Amount in human-readable format\n * @param smartWallet Wallet executing the deposit\n * @returns Result of the deposit transaction\n */\n abstract deposit(\n vaultInfo: VaultInfo,\n amount: string,\n smartWallet: SmartWallet,\n ): Promise<VaultTxnResult>;\n\n /**\n * Withdraw funds from a vault\n * @param vaultInfo Vault information\n * @param amount Amount in human-readable format (or undefined to withdraw all)\n * @param smartWallet Wallet executing the withdrawal\n * @returns Result of the withdrawal transaction\n */\n abstract withdraw(\n vaultInfo: VaultInfo,\n amountInShares: string,\n smartWallet: SmartWallet,\n ): Promise<VaultTxnResult>;\n\n /**\n * Get deposited balance in a vault\n * @param walletAddress Wallet address to check the balance of\n * @param protocolId Protocol ID to get balances for\n * @returns Balance of deposited funds\n */\n abstract getBalances(walletAddress: Address, protocolId?: string): Promise<VaultBalance[]>;\n\n /**\n * Approve a token for protocol use\n * @param tokenAddress Token address\n * @param spenderAddress Spender address\n * @param amount Allowance amount in wei\n * @param chainId Target chain ID\n * @param account Account authorizing the approval\n * @returns Transaction hash\n */\n protected async approveToken(\n tokenAddress: Address,\n spenderAddress: Address,\n amount: bigint,\n chainId: SupportedChainId,\n account: LocalAccount,\n ): Promise<string> {\n this.ensureInitialized();\n\n const walletClient = createWalletClient({\n account,\n chain: this.chainManager!.getChain(chainId),\n transport: http(this.chainManager!.getRpcUrl(chainId)),\n });\n\n const hash = await walletClient.writeContract({\n address: tokenAddress,\n abi: erc20Abi,\n functionName: 'approve',\n args: [spenderAddress, amount],\n gas: 100000n,\n maxFeePerGas: parseGwei('20'),\n maxPriorityFeePerGas: parseGwei('2'),\n });\n\n return hash;\n }\n\n /**\n * Check token allowance for a spender\n * @param tokenAddress Token address\n * @param spenderAddress Spender address\n * @param walletAddress Wallet address granting allowance\n * @param chainId Target chain ID\n * @returns Current allowance amount\n */\n protected async checkAllowance(\n tokenAddress: Address,\n spenderAddress: Address,\n walletAddress: Address,\n chainId: SupportedChainId,\n ): Promise<bigint> {\n this.ensureInitialized();\n\n const publicClient = this.chainManager!.getPublicClient(chainId);\n\n return await publicClient.readContract({\n address: tokenAddress,\n abi: erc20Abi,\n functionName: 'allowance',\n args: [walletAddress, spenderAddress],\n });\n }\n}\n","import { BaseProtocol } from '@/protocols/base/BaseProtocol';\nimport type { ChainManager } from '@/tools/ChainManager';\nimport type { SmartWallet } from '@/wallet/base/wallets/SmartWallet';\n\nimport { type Address, encodeFunctionData, erc20Abi, formatUnits, parseUnits } from 'viem';\n\nimport { SPARK_VAULT_ABI, SPARK_SSR_ORACLE_ABI } from '@/abis/protocols/spark';\nimport {\n RAY,\n SECONDS_PER_YEAR,\n SPARK_SSR_ORACLE_ADDRESS,\n SPARK_VAULT,\n} from '@/protocols/constants/spark';\nimport type { VaultBalance, VaultInfo, Vaults, VaultTxnResult } from '@/types/protocols/general';\n\n/**\n * @internal\n * @category Protocols\n * @class SparkProtocol\n * @classdesc\n * Internal implementation of the Spark Protocol adapter\n * Provides ERC-4626 vault management including deposits, withdrawals, and balance tracking\n * Used by the SDK to interact with Spark-based yield vaults\n */\nexport class SparkProtocol extends BaseProtocol {\n /** All Spark vaults */\n private allVaults: VaultInfo[] = [];\n\n /**\n * Initialize the Spark protocol with the provided chain manager\n * @param chainManager Chain manager instance used for network operations\n */\n async init(chainManager: ChainManager): Promise<void> {\n this.chainManager = chainManager;\n this.selectedChainId = chainManager.getSupportedChain();\n\n this.publicClient = chainManager.getPublicClient(this.selectedChainId!);\n\n this.allVaults = SPARK_VAULT;\n }\n\n /**\n * Get the SSR (Sky Saving Rate) of the Spark protocol\n * @remarks\n * The parameter ius necessary to calculate the APY of a vault\n * @returns\n */\n private async getSSR(): Promise<number> {\n if (!this.publicClient) {\n throw new Error('Public client not initialized');\n }\n\n const ssrRaw = await this.publicClient.readContract({\n address: SPARK_SSR_ORACLE_ADDRESS,\n abi: SPARK_SSR_ORACLE_ABI,\n functionName: 'getSSR',\n });\n\n const ssr = Number(ssrRaw) / Number(RAY);\n return ssr;\n }\n\n /**\n * Get the APY of the Spark protocol\n * @remarks\n * Calculation based on the formula from the documentation:\n * https://docs.spark.fi/dev/integration-guides/susds-lending-market#rates\n * @returns The APY of the Spark protocol in percentage\n */\n async getAPY(): Promise<number> {\n const ssr = await this.getSSR();\n\n const apy = Math.exp(Math.log(ssr) * SECONDS_PER_YEAR) - 1;\n\n return apy;\n }\n\n /**\n * Get the best available Spark vaults\n * @remarks Currently, the vault is only one and relates to sUSDC. Currently return only one stable vault\n * @returns Best Spark vaults in 2 groups: stable and non-stable\n * @throws Error if no vaults found\n */\n async getBestVaults(): Promise<Vaults> {\n if (this.allVaults.length === 0) {\n throw new Error('No vaults found');\n }\n\n // Currently, the vault is only one and relates to sUSDC\n // More Spark vaults can be added in the future, but the APY calculation will remain the same\n const selectedVault = this.allVaults[0]!;\n\n // The APY for Spark vaults calculates the same for all vaults\n selectedVault.metadata!.apy = await this.getAPY();\n\n return {\n stable: [selectedVault],\n nonStable: [],\n };\n }\n\n /**\n * Deposit funds into a Spark vault\n * @param vaultInfo Vault information\n * @param amount Amount to deposit (human-readable)\n * @param smartWallet Smart wallet instance to use\n * @returns Transaction result with hash\n */\n async deposit(\n vaultInfo: VaultInfo,\n amount: string,\n smartWallet: SmartWallet,\n ): Promise<VaultTxnResult> {\n const owner = await smartWallet.getAddress();\n const assets = parseUnits(amount, vaultInfo.tokenDecimals);\n\n const allowance = await this.checkAllowance(\n vaultInfo.tokenAddress,\n vaultInfo.vaultAddress,\n owner,\n this.selectedChainId!,\n );\n\n const ops: { to: Address; data: `0x${string}` }[] = [];\n\n if (allowance < assets) {\n ops.push({\n to: vaultInfo.tokenAddress,\n data: encodeFunctionData({\n abi: erc20Abi,\n functionName: 'approve',\n args: [vaultInfo.vaultAddress, assets],\n }),\n });\n }\n ops.push({\n to: vaultInfo.vaultAddress,\n data: encodeFunctionData({\n abi: SPARK_VAULT_ABI,\n functionName: 'deposit',\n args: [assets, owner] as const,\n }),\n });\n\n const hash = await smartWallet.sendBatch(ops, this.selectedChainId!);\n return { success: true, hash };\n }\n\n /**\n * Withdraw funds from a Spark vault\n * @param vaultInfo Vault information\n * @param amount Amount in base token units (or undefined to withdraw all)\n * @param smartWallet Smart wallet instance to withdraw from\n * @returns Transaction result with hash\n * @throws Error if no deposited vault found\n */\n async withdraw(\n vaultInfo: VaultInfo,\n amount: string | undefined,\n smartWallet: SmartWallet,\n ): Promise<VaultTxnResult> {\n const owner = await smartWallet.getAddress();\n\n let withdrawData: { to: Address; data: `0x${string}` };\n\n if (amount) {\n const assets = parseUnits(amount, vaultInfo.tokenDecimals);\n\n withdrawData = {\n to: vaultInfo.vaultAddress,\n data: encodeFunctionData({\n abi: SPARK_VAULT_ABI,\n functionName: 'withdraw',\n args: [assets, owner, owner] as const,\n }),\n };\n } else {\n const maxShares = await this.getMaxRedeemableShares(vaultInfo, owner);\n\n withdrawData = {\n to: vaultInfo.vaultAddress,\n data: encodeFunctionData({\n abi: SPARK_VAULT_ABI,\n functionName: 'redeem',\n args: [maxShares, owner, owner] as const,\n }),\n };\n }\n\n const hash = await smartWallet.send(withdrawData, this.selectedChainId!);\n\n return { success: true, hash };\n }\n\n /**\n * Get the maximum redeemable shares for a wallet\n * @param vaultInfo Vault information\n * @param walletAddress Wallet address to check\n * @returns Maximum redeemable shares as bigint\n */\n private async getMaxRedeemableShares(\n vaultInfo: VaultInfo,\n walletAddress: Address,\n ): Promise<bigint> {\n if (!this.publicClient) {\n throw new Error('Public client not initialized');\n }\n\n const shares = await this.publicClient.readContract({\n address: vaultInfo.vaultAddress,\n abi: SPARK_VAULT_ABI,\n functionName: 'balanceOf',\n args: [walletAddress],\n });\n\n return shares;\n }\n\n /**\n * Get amount that a wallet has deposited in a vault\n * @param walletAddress Wallet address to check\n * @returns Array of vault balances with vaults info\n */\n async getBalances(walletAddress: Address): Promise<VaultBalance[]> {\n if (!this.publicClient) {\n throw new Error('Public client not initialized');\n }\n\n // TODO: Support multiple options of Spark vaults\n // Use just one spark vault in this implementation\n const vaultInfo = SPARK_VAULT[0]!;\n vaultInfo.metadata!.apy = await this.getAPY();\n\n const shares = await this.publicClient.readContract({\n address: vaultInfo.vaultAddress,\n abi: SPARK_VAULT_ABI,\n functionName: 'balanceOf',\n args: [walletAddress],\n });\n\n if (shares === 0n) {\n return [{ balance: null, vaultInfo }];\n }\n\n const assets = await this.publicClient.readContract({\n address: vaultInfo.vaultAddress,\n abi: SPARK_VAULT_ABI,\n functionName: 'convertToAssets',\n args: [shares],\n });\n\n return [\n {\n balance: formatUnits(assets, vaultInfo.tokenDecimals),\n vaultInfo,\n },\n ];\n }\n}\n","export const SPARK_VAULT_ABI = [\n { type: 'function', name: 'asset', stateMutability: 'view', inputs: [], outputs: [{ type: 'address' }] },\n { type: 'function', name: 'totalAssets', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint256' }] },\n { type: 'function', name: 'convertToShares', stateMutability: 'view', inputs: [{ name: 'assets', type: 'uint256' }], outputs: [{ type: 'uint256' }] },\n { type: 'function', name: 'convertToAssets', stateMutability: 'view', inputs: [{ name: 'shares', type: 'uint256' }], outputs: [{ type: 'uint256' }] },\n { type: 'function', name: 'balanceOf', stateMutability: 'view', inputs: [{ name: 'owner', type: 'address' }], outputs: [{ type: 'uint256' }] },\n\n { type: 'function', name: 'deposit', stateMutability: 'nonpayable', inputs: [\n { name: 'assets', type: 'uint256' },\n { name: 'receiver', type: 'address' }\n ], outputs: [{ type: 'uint256' }] },\n { type: 'function', name: 'withdraw', stateMutability: 'nonpayable', inputs: [\n { name: 'assets', type: 'uint256' },\n { name: 'receiver', type: 'address' },\n { name: 'owner', type: 'address' }\n ], outputs: [{ type: 'uint256' }] },\n { type: 'function', name: 'redeem', stateMutability: 'nonpayable', inputs: [\n { name: 'shares', type: 'uint256' },\n { name: 'receiver', type: 'address' },\n { name: 'owner', type: 'address' }\n ], outputs: [{ type: 'uint256' }] },\n] as const;\n\n\n\nexport const SPARK_SSR_ORACLE_ABI = [\n {\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},\n {\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},\n {\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},\n {\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},\n {\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},\n {\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},\n {\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maxSSR\",\"type\":\"uint256\"}],\"name\":\"SetMaxSSR\",\"type\":\"event\"},\n {\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"ssr\",\"type\":\"uint96\"},{\"internalType\":\"uint120\",\"name\":\"chi\",\"type\":\"uint120\"},{\"internalType\":\"uint40\",\"name\":\"rho\",\"type\":\"uint40\"}],\"indexed\":false,\"internalType\":\"struct ISSROracle.SUSDSData\",\"name\":\"nextData\",\"type\":\"tuple\"}],\"name\":\"SetSUSDSData\",\"type\":\"event\"},\n {\"inputs\":[],\"name\":\"DATA_PROVIDER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[],\"name\":\"getAPR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[],\"name\":\"getChi\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getConversionRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[],\"name\":\"getConversionRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getConversionRateBinomialApprox\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[],\"name\":\"getConversionRateBinomialApprox\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"getConversionRateLinearApprox\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[],\"name\":\"getConversionRateLinearApprox\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[],\"name\":\"getRho\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[],\"name\":\"getSSR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[],\"name\":\"getSUSDSData\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"ssr\",\"type\":\"uint96\"},{\"internalType\":\"uint120\",\"name\":\"chi\",\"type\":\"uint120\"},{\"internalType\":\"uint40\",\"name\":\"rho\",\"type\":\"uint40\"}],\"internalType\":\"struct ISSROracle.SUSDSData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},\n {\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[],\"name\":\"maxSSR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},\n {\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},\n {\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},\n {\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_maxSSR\",\"type\":\"uint256\"}],\"name\":\"setMaxSSR\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},\n {\"inputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"ssr\",\"type\":\"uint96\"},{\"internalType\":\"uint120\",\"name\":\"chi\",\"type\":\"uint120\"},{\"internalType\":\"uint40\",\"name\":\"rho\",\"type\":\"uint40\"}],\"internalType\":\"struct ISSROracle.SUSDSData\",\"name\":\"nextData\",\"type\":\"tuple\"}],\"name\":\"setSUSDSData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},\n {\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}\n] as const;","import type { VaultInfo } from '@/types/protocols/general';\n\nexport const SPARK_SSR_ORACLE_ADDRESS = '0x65d946e533748A998B1f0E430803e39A6388f7a1';\n\nexport const SPARK_VAULT: VaultInfo[] = [\n {\n id: 'sUSDC',\n protocolId: 'spark',\n name: 'sUSDC',\n type: 'stable',\n chain: 'base',\n vaultAddress: '0x3128a0f7f0ea68e7b7c9b00afa7e41045828e858',\n tokenAddress: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913',\n tokenDecimals: 6,\n tokenSymbol: 'USDC',\n metadata: {},\n },\n];\n\nexport const SECONDS_PER_YEAR = 60 * 60 * 24 * 365;\nexport const RAY = BigInt('1000000000000000000000000000');\n","import { SparkProtocol } from '@/protocols/implementations/SparkProtocol';\nimport type { Protocol } from '@/types/protocols/general';\n\n/**\n * Current config of protocols should have correct supportedChains array as it used to:\n * 1. Fetch vaults per chain to find the best vault for the protocol\n * 2. Deposit funds of users to a best found vault\n */\nexport const availableProtocols: Protocol[] = [\n {\n info: {\n id: 'spark',\n name: 'Spark',\n website: 'https://spark.fi/',\n logo: '/logos/spark.png',\n supportedChains: [8453],\n riskLevel: 'low',\n isActive: true,\n },\n instance: new SparkProtocol(),\n },\n];\n","import { BaseProtocol } from '@/protocols/base/BaseProtocol';\nimport type { ChainManager } from '@/tools/ChainManager';\nimport type {\n ProtocolsSecurityConfig,\n VaultBalance,\n VaultInfo,\n Vaults,\n VaultTxnResult,\n} from '@/types/protocols/general';\nimport type { OperationCallDataType, ProxyBalance, ProxyVaults } from '@/types/protocols/proxy';\nimport { encodeFunctionData, erc20Abi, parseUnits, type Address, type Hash } from 'viem';\nimport type { SmartWallet } from '@/public/types';\nimport type { ApiClient } from '@/tools/ApiClient';\n\n/**\n * Proxy protocol implementation that communicates with the backend to find optimal vaults\n * and interact with optimal protocols\n *\n * @internal\n * @category Protocols\n * @remarks\n * This class works as a proxy protocol class that:\n * - Communicates with the backend API to discover and select optimal vaults\n * - Interacts with optimal protocols based on security configuration\n * - Handles all operations related to protocol interactions including deposits, withdrawals,\n * balance queries, and operation logging\n * - Acts as an intermediary layer between the SDK and underlying DeFi protocols\n */\nexport class ProxyProtocol extends BaseProtocol {\n /** API client for the backend API */\n private apiClient!: ApiClient;\n\n /** Protocols security config */\n private protocolsSecurityConfig!: ProtocolsSecurityConfig;\n\n /**\n * Initialize the Spark protocol with the provided chain manager\n * @param chainManager Chain manager instance used for network operations\n */\n async init(\n chainManager: ChainManager,\n protocolsSecurityConfig: ProtocolsSecurityConfig,\n apiClient: ApiClient,\n ): Promise<void> {\n this.chainManager = chainManager;\n this.selectedChainId = chainManager.getSupportedChain();\n\n this.publicClient = chainManager.getPublicClient(this.selectedChainId!);\n\n this.apiClient = apiClient;\n\n this.protocolsSecurityConfig = protocolsSecurityConfig;\n }\n\n /**\n * Log a vault-related operation after deposit or withdraw funds\n * @param userAddress Address of the user who performed the operation\n * @param hash Hash of the operation\n * @param vaultInfo Information about the vault where the operation was performed\n * @param chainId Chain ID where the operation was performed\n * @param amount Amount of the operation\n * @param operationType Type of the operation\n * @param operationStatus Status of the operation\n */\n private async logOperation(\n userAddress: Address,\n hash: Hash,\n vaultInfo: VaultInfo,\n chainId: number,\n amount: string,\n operationType: 'deposit' | 'withdrawal',\n operationStatus: 'completed' | 'failed',\n ): Promise<void> {\n const apiResponse = await this.apiClient.sendRequest('log', undefined, undefined, {\n userAddress,\n protocolId: vaultInfo.protocolId,\n vaultAddress: vaultInfo.vaultAddress,\n transactionHash: hash,\n chainId: chainId.toString(),\n amount,\n status: operationStatus,\n operationType,\n });\n\n if (!apiResponse.success) {\n throw new Error(\n apiResponse.error || `Failed to log operation: ${operationType} for vault: ${vaultInfo}`,\n );\n }\n }\n\n /**\n * Get the best vaults to deposit funds\n * @param stableVaultsLimit Limit of stable vaults to get. Optional, default is 1\n * @param nonStableVaultsLimit Limit of non-stable vaults to get. Optional, default is 1\n * @returns Best vaults to deposit funds in 2 groups: stable and non-stable\n */\n async getBestVaults(\n stableVaultsLimit: number = 1,\n nonStableVaultsLimit: number = 1,\n ): Promise<Vaults> {\n const pathParams = {\n risk_level: this.protocolsSecurityConfig.riskLevel,\n chain_id: this.selectedChainId!.toString(),\n stable_vaults_limit: stableVaultsLimit.toString(),\n non_stable_vaults_limit: nonStableVaultsLimit.toString(),\n };\n\n const apiResponse = await this.apiClient.sendRequest('vaults', pathParams);\n\n if (!apiResponse.success) {\n throw new Error(apiResponse.error || 'Failed to get best vaults');\n }\n\n const vaults: ProxyVaults = apiResponse.data as unknown as ProxyVaults;\n\n return {\n stable: vaults.stableVaults.map((vault: VaultInfo): VaultInfo => {\n return {\n ...vault,\n metadata: {\n apy: vault.metadata?.apy,\n poolTvlUsd: vault.metadata?.poolTvlUsd,\n },\n } as VaultInfo;\n }),\n nonStable: vaults.nonStableVaults.map((vault: VaultInfo): VaultInfo => {\n return {\n ...vault,\n metadata: {\n apy: vault.metadata?.apy,\n poolTvlUsd: vault.metadata?.poolTvlUsd,\n },\n } as VaultInfo;\n }),\n };\n }\n\n /**\n * Deposit funds to a provided vault\n * @param vaultInfo Information about the vault to deposit funds to\n * @param amount Amount of funds to deposit\n * @param smartWallet Smart wallet to use for the deposit\n * @returns Result of the deposit transaction\n */\n async deposit(\n vaultInfo: VaultInfo,\n amount: string,\n smartWallet: SmartWallet,\n ): Promise<VaultTxnResult> {\n const currentAddress = await smartWallet.getAddress();\n\n const operationsCallData = [];\n const depositTokenDecimals = vaultInfo.tokenDecimals;\n const depositTokenAddress = vaultInfo.tokenAddress;\n const vaultAddress = vaultInfo.vaultAddress;\n\n const rawDepositAmount = parseUnits(amount, depositTokenDecimals);\n\n const allowance = await this.checkAllowance(\n depositTokenAddress,\n vaultAddress,\n currentAddress,\n this.selectedChainId!,\n );\n\n if (allowance < rawDepositAmount) {\n const approveData = {\n to: depositTokenAddress,\n data: encodeFunctionData({\n abi: erc20Abi,\n functionName: 'approve',\n args: [vaultAddress, rawDepositAmount],\n }),\n };\n\n operationsCallData.push(approveData);\n }\n\n if (!vaultInfo.protocolId) {\n throw new Error('Vault protocol ID is required');\n }\n\n const apiResponse = await this.apiClient.sendRequest(\n 'deposit',\n undefined,\n vaultInfo.protocolId,\n {\n vaultInfo,\n amount: amount.toString(),\n chainId: this.selectedChainId!.toString(),\n },\n );\n\n if (!apiResponse.success) {\n throw new Error(apiResponse.error || 'Failed to receive deposit operations call data');\n }\n\n const receivedOperationsCallData = apiResponse.data as unknown as OperationCallDataType;\n\n operationsCallData.push(receivedOperationsCallData);\n\n const hash = await smartWallet.sendBatch(operationsCallData, this.selectedChainId!);\n\n const operationStatus = hash ? 'completed' : ('failed' as 'completed' | 'failed');\n\n this.logOperation(\n currentAddress,\n hash,\n vaultInfo,\n this.selectedChainId!,\n amount,\n 'deposit',\n operationStatus,\n );\n\n return { hash, success: true };\n }\n\n /**\n * Withdraw funds from a provided vault\n * @param vaultInfo Information about the vault to withdraw funds from\n * @param amount Amount of funds to withdraw\n * @param smartWallet Smart wallet to use for the withdrawal\n * @returns Result of the withdrawal transaction\n */\n async withdraw(\n vaultInfo: VaultInfo,\n amount: string,\n smartWallet: SmartWallet,\n ): Promise<VaultTxnResult> {\n const currentAddress = await smartWallet.getAddress();\n\n const earningBalances = await smartWallet.getEarnBalances();\n\n if (!earningBalances) {\n throw new Error('No earning balances found');\n }\n\n const earningBalance = earningBalances.find((balance) => balance.vaultInfo.id === vaultInfo.id);\n\n if (!earningBalance) {\n throw new Error('No earning balance found');\n }\n const balanceInfo = earningBalance.balance as ProxyBalance;\n\n const amountToWithdraw = amount ? amount : balanceInfo.currentBalance;\n\n const apiResponse = await this.apiClient.sendRequest(\n 'withdraw',\n undefined,\n vaultInfo.protocolId,\n {\n vaultInfo,\n amount: amountToWithdraw,\n chainId: this.selectedChainId!.toString(),\n },\n );\n\n if (!apiResponse.success) {\n throw new Error(apiResponse.error || 'Failed to receive withdraw operations call data');\n }\n\n const withdrawOperationCallData = apiResponse.data as unknown as OperationCallDataType;\n\n const hash = await smartWallet.send(withdrawOperationCallData, this.selectedChainId!);\n\n const operationStatus = hash ? 'completed' : ('failed' as 'completed' | 'failed');\n\n this.logOperation(\n currentAddress,\n hash,\n vaultInfo,\n this.selectedChainId!,\n amountToWithdraw,\n 'withdrawal',\n operationStatus,\n );\n\n return { hash, success: true };\n }\n\n /**\n * Get the balances of a user by a provided address\n * @param walletAddress Address of the user to get the balances of\n * @param protocolId Protocol ID to get the balances for. Optional, default is undefined\n * @returns Balances of the user in the protocol vaults\n */\n async getBalances(walletAddress: Address, protocolId?: string): Promise<VaultBalance[]> {\n const pathParams = {\n chain_id: this.selectedChainId!.toString(),\n protocol_id: protocolId || '',\n userAddress: walletAddress,\n };\n\n const apiResponse = await this.apiClient.sendRequest('balances', pathParams);\n\n if (!apiResponse.success) {\n throw new Error(apiResponse.error || 'Failed to get balances');\n }\n\n const balances: VaultBalance[] = apiResponse.data as unknown as VaultBalance[];\n\n return balances;\n }\n}\n","import type { SupportedChainId } from '@/constants/chains';\nimport { availableProtocols } from '@/constants/protocols';\nimport type { BaseProtocol } from '@/protocols/base/BaseProtocol';\nimport { ProxyProtocol } from '@/protocols/implementations/ProxyProtocol';\nimport type { ChainManager } from '@/tools/ChainManager';\nimport type { Protocol } from '@/types/protocols/general';\n\n/**\n * Protocol Router\n *\n * @internal\n * @category Protocols\n * @remarks\n * Selects and recommends protocols for yield strategies based on router configuration,\n * available protocols, and API key for paid protocols\n */\nexport class ProtocolRouter {\n /** Chain manager instance for network access */\n private readonly chainManager: ChainManager;\n\n private readonly isApiKeyValid: boolean;\n\n /**\n * Initialize the protocol router\n * @param config Router configuration including risk level, min APY, and optional API key\n * @param chainManager Chain manager instance for network validation\n */\n constructor(chainManager: ChainManager, isApiKeyValid: boolean) {\n this.chainManager = chainManager;\n this.isApiKeyValid = isApiKeyValid;\n }\n\n /**\n * Get all protocols available for the current configuration\n *\n * Includes all non-premium protocols and premium protocols if the API key is valid\n * @returns Array of available protocol definitions\n */\n getActivePublicProtocols(): Protocol[] {\n const allAvailableProtocols = availableProtocols.filter((protocol) => {\n return protocol.info.isActive;\n });\n\n return allAvailableProtocols;\n }\n\n /**\n * Check if any protocol supports a given set of chains\n * @param chainIds List of chain IDs to validate\n * @returns True if at least one chain is supported by the router\n */\n isProtocolSupportedChain(chainIds: SupportedChainId[]): boolean {\n return chainIds.some((chainId) => this.chainManager.getSupportedChain() === chainId);\n }\n\n /**\n * Recommend the best protocol for the current router configuration\n *\n * Filters available protocols by risk level and supported chains. More criteria will be added later on\n *\n *\n * @remarks\n * Currently returns the first match. Future improvements will add\n * smarter sorting and pool-based APY checks\n *\n * @throws Error if no protocols are available for the current risk level\n * @returns Protocol instance considered the best match\n */\n select(): BaseProtocol {\n if (this.isApiKeyValid) {\n return new ProxyProtocol();\n }\n\n const protocols = this.getActivePublicProtocols();\n\n const eligibleProtocols = protocols.filter((protocol) => {\n const isSupportedChain = this.isProtocolSupportedChain(protocol.info.supportedChains);\n\n return isSupportedChain;\n });\n\n if (eligibleProtocols.length === 0) {\n throw new Error(`No protocols available`);\n }\n\n // For now, we just return the first protocol from public protocols that matches the risk level\n const bestProtocol = eligibleProtocols[0];\n\n return bestProtocol!.instance;\n }\n}\n","import { generateJwt } from '@coinbase/cdp-sdk/auth';\nimport axios, { type AxiosInstance, type AxiosResponse } from 'axios';\nimport type {\n CoinbaseCDPAuthParams,\n OnRampUrlResponse,\n CoinbaseCDPError,\n RampConfigResponse,\n OffRampUrlResponse,\n} from '@/types/ramp';\nimport type { Address } from 'viem';\nimport type { ChainManager } from '@/tools/ChainManager';\nimport { checkValidUrl } from '@/utils/urls';\nimport { chainById } from '@/utils/chains';\n\nexport class CoinbaseCDP {\n private readonly apiKeyId: string;\n private readonly apiKeySecret: string;\n private readonly chainManager: ChainManager;\n private readonly integratorId: string;\n\n private readonly coinbaseCdpV2Hostname: string = 'https://api.cdp.coinbase.com';\n private readonly coinbaseCdpV1Hostname: string = 'https://api.developer.coinbase.com';\n\n private readonly onRampUrlAuthParams: CoinbaseCDPAuthParams = {\n requestMethod: 'POST',\n requestHost: 'api.cdp.coinbase.com',\n requestPath: '/platform/v2/onramp/sessions',\n expiresIn: 120,\n };\n\n private readonly onRampConfigAuthParams: CoinbaseCDPAuthParams = {\n requestMethod: 'GET',\n requestHost: 'api.developer.coinbase.com',\n requestPath: '/onramp/v1/buy/config',\n expiresIn: 120,\n };\n\n private readonly offRampUrlAuthParams: CoinbaseCDPAuthParams = {\n requestMethod: 'POST',\n requestHost: 'api.developer.coinbase.com',\n requestPath: '/onramp/v1/sell/quote',\n expiresIn: 120,\n };\n\n private readonly offRampConfigAuthParams: CoinbaseCDPAuthParams = {\n requestMethod: 'GET',\n requestHost: 'api.developer.coinbase.com',\n requestPath: '/onramp/v1/sell/config',\n expiresIn: 120,\n };\n\n private readonly clientV2: AxiosInstance = axios.create({\n baseURL: this.coinbaseCdpV2Hostname,\n });\n private readonly clientV1: AxiosInstance = axios.create({\n baseURL: this.coinbaseCdpV1Hostname,\n });\n constructor(\n apiKeyId: string,\n apiKeySecret: string,\n integratorId: string,\n chainManager: ChainManager,\n ) {\n this.apiKeyId = apiKeyId;\n this.apiKeySecret = apiKeySecret;\n this.chainManager = chainManager;\n this.integratorId = integratorId;\n\n this.verifyParameters();\n }\n\n private verifyParameters(): void {\n if (!this.apiKeyId || !this.apiKeySecret || !this.integratorId) {\n throw new Error('API key ID, secret and integrator ID are required');\n }\n }\n\n /**\n * @internal\n * Generate a JWT token for a provided API endpoint and hostname to make a request after\n * @category Ramp\n *\n * @param authParams Authentication parameters\n * @returns JWT token\n * @throws Error if the JWT token generation fails\n */\n async auth(authParams: CoinbaseCDPAuthParams): Promise<string> {\n const jwtToken = await generateJwt({\n apiKeyId: this.apiKeyId,\n apiKeySecret: this.apiKeySecret,\n ...authParams,\n });\n\n return jwtToken;\n }\n\n /**\n * @internal\n * Return a on-ramp URL for the given parameters via Coinbase CDP V2 API\n * @category Ramp\n *\n * @param receiverAddress\n * @param redirectUrl\n * @param amount\n * @param purchaseCurrency\n * @param paymentCurrency\n * @param paymentMethod\n * @param country\n * @returns OnRampUrlResponse\n * @throws Error if redirect URL is not a valid URL\n * @throws CoinbaseCDPError if the request fails\n */\n async getOnRampLink(\n receiverAddress: Address,\n redirectUrl: string,\n amount: string,\n purchaseCurrency: string = 'USDC',\n paymentCurrency: string = 'USD',\n paymentMethod: string = 'CARD',\n country?: string,\n ): Promise<OnRampUrlResponse> {\n if (!checkValidUrl(redirectUrl)) {\n throw new Error('Redirect URL is not a valid URL');\n }\n\n const chainId = this.chainManager.getSupportedChain();\n const chainName = chainById[chainId]?.name.toLowerCase();\n\n const authJwtToken = await this.auth(this.onRampUrlAuthParams);\n\n const response: AxiosResponse<OnRampUrlResponse | CoinbaseCDPError> = await this.clientV2.post(\n this.onRampUrlAuthParams.requestPath,\n {\n destinationAddress: receiverAddress,\n destinationNetwork: chainName,\n redirectUrl,\n paymentAmount: amount,\n purchaseCurrency,\n paymentCurrency,\n paymentMethod,\n country: country,\n },\n {\n method: this.onRampUrlAuthParams.requestMethod,\n headers: { Authorization: `Bearer ${authJwtToken}`, 'Content-Type': 'application/json' },\n },\n );\n\n if (response.status !== 200 && response.status !== 201) {\n const error = response.data as CoinbaseCDPError;\n throw error;\n }\n\n const onRampResponse = response.data as OnRampUrlResponse;\n\n return onRampResponse;\n }\n\n /**\n * @internal\n * Current method return all supported countries and payment methods for on-ramp by Coinbase CDP\n * @category Ramp\n *\n * @returns Config with supported countries and payment methods for on-ramp\n * @throws If API returned an error\n */\n public async getOnRampConfig(): Promise<RampConfigResponse> {\n const authJwtToken = await this.auth(this.onRampConfigAuthParams);\n\n const response: AxiosResponse<RampConfigResponse | CoinbaseCDPError> = await this.clientV1.get(\n this.onRampConfigAuthParams.requestPath,\n {\n headers: { Authorization: `Bearer ${authJwtToken}` },\n },\n );\n\n if (response.status !== 200) {\n const error = response.data as CoinbaseCDPError;\n throw error;\n }\n\n const onRampConfigResponse = response.data as RampConfigResponse;\n return onRampConfigResponse;\n }\n\n /**\n * @internal\n * Return a off-ramp URL for the given parameters via Coinbase CDP V1 API\n * @remarks\n * Use an integratorId as a partnerUserId in Coinbase CDP API\n * @category Ramp\n *\n * @param address\n * @param country\n * @param paymentMethod\n * @param redirectUrl\n * @param sellAmount\n * @param cashoutCurrency\n * @param sellCurrency\n * @returns OffRampUrlResponse\n * @throws Error if redirect URL is not a valid URL\n * @throws CoinbaseCDPError if the request fails\n */\n async getOffRampLink(\n address: Address,\n country: string,\n paymentMethod: string,\n redirectUrl: string,\n sellAmount: string,\n cashoutCurrency: string = 'USD',\n sellCurrency: string = 'USDC',\n ): Promise<OffRampUrlResponse> {\n if (!checkValidUrl(redirectUrl)) {\n throw new Error('Redirect URL is not a valid URL');\n }\n\n const chainId = this.chainManager.getSupportedChain();\n const chainName = chainById[chainId]?.name.toLowerCase();\n\n const authJwtToken = await this.auth(this.offRampUrlAuthParams);\n\n const response: AxiosResponse<OffRampUrlResponse | CoinbaseCDPError> = await this.clientV1.post(\n this.offRampUrlAuthParams.requestPath,\n {\n sourceAddress: address,\n country,\n paymentMethod,\n partnerUserId: this.integratorId,\n redirectUrl,\n sellAmount,\n sellNetwork: chainName,\n cashoutCurrency,\n sellCurrency,\n },\n {\n method: this.offRampUrlAuthParams.requestMethod,\n headers: { Authorization: `Bearer ${authJwtToken}`, 'Content-Type': 'application/json' },\n },\n );\n\n if (response.status !== 200 && response.status !== 201) {\n const error = response.data as CoinbaseCDPError;\n throw error;\n }\n\n const offRampResponse = response.data as OffRampUrlResponse;\n\n return offRampResponse;\n }\n\n /**\n * @internal\n * Current method return all supported countries and payment methods for off-ramp by Coinbase CDP\n * @category Ramp\n * @returns Config with supported countries and payment methods for off-ramp\n * @throws If API returned an error\n */\n public async getOffRampConfig(): Promise<RampConfigResponse> {\n const authJwtToken = await this.auth(this.offRampConfigAuthParams);\n\n const response: AxiosResponse<RampConfigResponse | CoinbaseCDPError> = await this.clientV1.get(\n this.offRampConfigAuthParams.requestPath,\n {\n headers: { Authorization: `Bearer ${authJwtToken}` },\n },\n );\n\n if (response.status !== 200) {\n const error = response.data as CoinbaseCDPError;\n throw error;\n }\n\n const offRampConfigResponse = response.data as RampConfigResponse;\n return offRampConfigResponse;\n }\n}\n","export const checkValidUrl = (url: string): boolean => {\n return /^https?:\\/\\/.+$/.test(url);\n};\n","import type { BaseProtocol } from '@/protocols/base/BaseProtocol';\nimport type { Vaults } from '@/types/protocols/general';\n\n/**\n * Protocol namespace to manage protocol related operations, e.g. get best vaults\n * @public\n * @category Protocols\n */\nexport class ProtocolsNamespace {\n private protocol: BaseProtocol;\n\n constructor(protocol: BaseProtocol) {\n this.protocol = protocol;\n }\n\n /**\n * Find the best vaults for protocols that were selected based on integrator's settings\n *\n * @returns Best vaults for protocols that were selected based on integrator's settings\n */\n async getBestVaults(\n stableVaultsLimit: number = 1,\n nonStableVaultsLimit: number = 1,\n ): Promise<Vaults> {\n return await this.protocol.getBestVaults(stableVaultsLimit, nonStableVaultsLimit);\n }\n}\n","export const BACKEND_HOSTNAME = 'http://localhost:3000';\n","import { BACKEND_HOSTNAME } from '@/constants/general';\nimport type { VaultInfo } from '@/public/types';\nimport type { ApiResponse, OperationType, RequestSettings } from '@/types/api';\nimport axios, { type AxiosInstance, type AxiosResponse } from 'axios';\n\nexport class ApiClient {\n private readonly client: AxiosInstance = axios.create({\n baseURL: BACKEND_HOSTNAME,\n });\n\n /** URL settings for the endpoint: get the best vaults to deposit funds */\n private readonly bestVaultUrlSettings: RequestSettings = {\n method: 'GET',\n path: 'api/v1/public/protocols/best',\n };\n\n /** URL settings for the endpoint: deposit funds to a provided vault */\n private readonly depositUrlSettings: RequestSettings = {\n method: 'POST',\n path: 'api/v1/public/protocols/details/:protocolId/deposit',\n };\n\n /** URL settings for the endpoint: log a vault-related operation after deposit or withdraw funds */\n private readonly logOperationSettings: RequestSettings = {\n method: 'POST',\n path: 'api/v1/public/log/operation',\n };\n\n /** URL settings for the endpoint: withdraw funds from a provided vault */\n private readonly withdrawUrlSettings: RequestSettings = {\n method: 'POST',\n path: 'api/v1/public/protocols/details/:protocolId/withdraw',\n };\n\n /** URL settings for the endpoint: get the balances of a user by a provided address */\n private readonly balancesUrlSettings: RequestSettings = {\n method: 'GET',\n path: 'api/v1/public/user/:userAddress/balances',\n };\n\n /** URL settings for the endpoint: validate the API key */\n private readonly apiKeyValidUrlSettings: RequestSettings = {\n method: 'GET',\n path: 'api/v1/public/valid',\n };\n\n /** URL settings for the endpoint: get the config for services */\n private readonly configUrlSettings: RequestSettings = {\n method: 'GET',\n path: 'api/v1/public/config',\n };\n\n /** URL settings mapping with operation types */\n private readonly operationTypeToUrlSettings: Record<OperationType, RequestSettings> = {\n deposit: this.depositUrlSettings,\n withdraw: this.withdrawUrlSettings,\n log: this.logOperationSettings,\n vaults: this.bestVaultUrlSettings,\n balances: this.balancesUrlSettings,\n apiKeyValidation: this.apiKeyValidUrlSettings,\n config: this.configUrlSettings,\n };\n\n /** API key for the backend API */\n private apiKey: string;\n\n constructor(apiKey: string) {\n this.apiKey = apiKey;\n\n if (!this.validateApiKeyFormat()) {\n throw new Error('Invalid API key format');\n }\n }\n\n /**\n * Send a request to the backend API\n * @param path Path of the endpoint to send the request to\n * @param method Method of the request\n * @param body Body of the request\n * @returns Response from the backend API\n */\n async sendRequest(\n operationType: OperationType,\n params?: Record<string, string>,\n protocolId?: string,\n body?: Record<string, string | VaultInfo>,\n ): Promise<ApiResponse<unknown>> {\n const { path, method } = this.operationTypeToUrlSettings[operationType];\n\n let requestPath = path;\n // TODO: Make processing of params in a request more clear\n if (protocolId) {\n requestPath = requestPath.replace(':protocolId', protocolId);\n }\n if (params?.userAddress) {\n requestPath = requestPath.replace(':userAddress', params.userAddress);\n delete params.userAddress;\n }\n\n const urlParams = new URLSearchParams(params).toString();\n\n if (urlParams) {\n requestPath += `?${urlParams}`;\n }\n\n const response: AxiosResponse<ApiResponse<unknown>> = await this.client.request({\n method,\n url: requestPath,\n data: body,\n headers: { Authorization: `Bearer ${this.apiKey}`, 'Content-Type': 'application/json' },\n });\n\n if (response.status !== 200) {\n throw new Error(`Failed to send request to ${path}`);\n }\n\n const apiResponse = response.data as ApiResponse<unknown>;\n\n return apiResponse;\n }\n\n /**\n * Validates whether the provided API key is valid\n *\n * @internal\n * @param apiKey API key from {@link ProtocolsRouterConfig}\n * @returns True if the API key is considered valid\n */\n async validate() {\n if (!this.validateApiKeyFormat()) {\n throw new Error('Invalid API key format');\n }\n\n const apiResponse = await this.sendRequest('apiKeyValidation');\n\n if (!apiResponse.success) {\n throw new Error(apiResponse.error || 'Failed to validate API key');\n }\n\n return true;\n }\n\n /**\n *\n * Validates the format of the API key. Must start with 'sk_' and contain only hexadecimal characters\n *\n * @internal\n * @param apiKey API key from {@link ProtocolsRouterConfig}\n * @returns\n */\n private validateApiKeyFormat() {\n if (!this.apiKey) {\n return false;\n }\n\n const prefix = 'sk_';\n if (!this.apiKey.startsWith(prefix)) {\n return false;\n }\n\n const keyPart = this.apiKey.slice(prefix.length);\n\n if (keyPart.length < 32 || keyPart.length > 128) {\n return false;\n }\n\n const hexPattern = /^[0-9a-fA-F]+$/;\n if (!hexPattern.test(keyPart)) {\n return false;\n }\n\n return true;\n }\n}\n"],"mappings":"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","names":["erc20Abi","address","tokenInfo","parsedAmount","erc20Abi","base","baseSepolia","base","pad","pad","http","unichain","LogLevel","http","unichain","erc20Abi","createWalletClient","http","encodeFunctionData","erc20Abi","formatUnits","parseUnits","parseUnits","encodeFunctionData","erc20Abi","formatUnits","encodeFunctionData","erc20Abi","parseUnits","axios","base","sdk"]}