UNPKG

@coinbase/cdp-sdk

Version:

SDK for interacting with the Coinbase Developer Platform Wallet API

321 lines (296 loc) 11 kB
import { getBaseNodeRpcUrl } from "./getBaseNodeRpcUrl.js"; import { isMethodSupportedOnNetwork } from "./networkCapabilities.js"; import { fund } from "../../actions/evm/fund/fund.js"; import { quoteFund } from "../../actions/evm/fund/quoteFund.js"; import { getUserOperation } from "../../actions/evm/getUserOperation.js"; import { listTokenBalances } from "../../actions/evm/listTokenBalances.js"; import { requestFaucet } from "../../actions/evm/requestFaucet.js"; import { sendUserOperation } from "../../actions/evm/sendUserOperation.js"; import { UseSpendPermissionOptions } from "../../actions/evm/spend-permissions/types.js"; import { createSwapQuote } from "../../actions/evm/swap/createSwapQuote.js"; import { sendSwapOperation } from "../../actions/evm/swap/sendSwapOperation.js"; import { smartAccountTransferStrategy } from "../../actions/evm/transfer/smartAccountTransferStrategy.js"; import { transfer } from "../../actions/evm/transfer/transfer.js"; import { waitForUserOperation } from "../../actions/evm/waitForUserOperation.js"; import { waitForFundOperationReceipt } from "../../actions/waitForFundOperationReceipt.js"; import { Analytics } from "../../analytics.js"; import type { EvmAccount, EvmSmartAccount, KnownEvmNetworks, NetworkScopedEvmSmartAccount, } from "./types.js"; import type { EvmFundOptions } from "../../actions/evm/fund/fund.js"; import type { EvmQuoteFundOptions } from "../../actions/evm/fund/quoteFund.js"; import type { ListTokenBalancesOptions } from "../../actions/evm/listTokenBalances.js"; import type { RequestFaucetOptions } from "../../actions/evm/requestFaucet.js"; import type { SendUserOperationOptions } from "../../actions/evm/sendUserOperation.js"; import type { SmartAccountQuoteSwapOptions, SmartAccountSwapNetwork, SmartAccountSwapOptions, } from "../../actions/evm/swap/types.js"; import type { SmartAccountTransferOptions } from "../../actions/evm/transfer/types.js"; import type { WaitForUserOperationOptions } from "../../actions/evm/waitForUserOperation.js"; import type { WaitForFundOperationOptions } from "../../actions/waitForFundOperationReceipt.js"; import type { GetUserOperationOptions } from "../../client/evm/evm.types.js"; import type { CdpOpenApiClientType, EvmUserOperationNetwork, ListEvmTokenBalancesNetwork, SpendPermissionNetwork, } from "../../openapi-client/index.js"; /** * Options for converting a pre-existing EvmSmartAccount and owner to a NetworkScopedEvmSmartAccount */ export type ToNetworkScopedEvmSmartAccountOptions = { /** The pre-existing EvmSmartAccount. */ smartAccount: EvmSmartAccount; /** The network to scope the smart account object to. */ network: KnownEvmNetworks; /** The owner of the smart account. */ owner: EvmAccount; }; /** * Creates a NetworkScopedEvmSmartAccount instance from an existing EvmSmartAccount and owner. * Use this to interact with previously deployed EvmSmartAccounts, rather than creating new ones. * * The owner must be the original owner of the evm smart account. * * @param {CdpOpenApiClientType} apiClient - The API client. * @param {ToNetworkScopedEvmSmartAccountOptions} options - Configuration options. * @param {EvmSmartAccount} options.smartAccount - The deployed evm smart account. * @param {EvmAccount} options.owner - The owner which signs for the smart account. * @param {KnownEvmNetworks} options.network - The network to scope the smart account to. * @returns {NetworkScopedEvmSmartAccount} A configured NetworkScopedEvmSmartAccount instance ready for user operation submission. */ export async function toNetworkScopedEvmSmartAccount<Network extends KnownEvmNetworks>( apiClient: CdpOpenApiClientType, options: ToNetworkScopedEvmSmartAccountOptions & { network: Network }, ): Promise<NetworkScopedEvmSmartAccount<Network>> { const paymasterUrl = await (async () => { if (options.network === "base") { return getBaseNodeRpcUrl(options.network); } return undefined; })(); const account = { address: options.smartAccount.address, network: options.network, owners: [options.owner], name: options.smartAccount.name, type: "evm-smart", sendUserOperation: async ( userOpOptions: Omit<SendUserOperationOptions<unknown[]>, "smartAccount" | "network">, ) => { Analytics.trackAction({ action: "send_user_operation", accountType: "evm_smart", properties: { network: options.network, managed: true, }, }); return sendUserOperation(apiClient, { ...userOpOptions, smartAccount: options.smartAccount, network: options.network as EvmUserOperationNetwork, paymasterUrl: userOpOptions.paymasterUrl ?? paymasterUrl, }); }, waitForUserOperation: async ( waitOptions: Omit<WaitForUserOperationOptions, "smartAccountAddress">, ) => { Analytics.trackAction({ action: "wait_for_user_operation", accountType: "evm_smart", properties: { managed: true, }, }); return waitForUserOperation(apiClient, { ...waitOptions, smartAccountAddress: options.smartAccount.address, }); }, getUserOperation: async (getOptions: Omit<GetUserOperationOptions, "smartAccount">) => { Analytics.trackAction({ action: "get_user_operation", accountType: "evm_smart", properties: { managed: true, }, }); return getUserOperation(apiClient, { ...getOptions, smartAccount: options.smartAccount, }); }, } as NetworkScopedEvmSmartAccount<Network>; if (isMethodSupportedOnNetwork("transfer", options.network)) { Object.assign(account, { transfer: async (transferOptions: Omit<SmartAccountTransferOptions, "network">) => { Analytics.trackAction({ action: "transfer", accountType: "evm_smart", properties: { network: options.network, managed: true, }, }); return transfer( apiClient, options.smartAccount, { ...transferOptions, network: options.network as EvmUserOperationNetwork, paymasterUrl: transferOptions.paymasterUrl ?? paymasterUrl, }, smartAccountTransferStrategy, ); }, }); } if (isMethodSupportedOnNetwork("listTokenBalances", options.network)) { Object.assign(account, { listTokenBalances: async ( listOptions: Omit<ListTokenBalancesOptions, "address" | "network">, ) => { Analytics.trackAction({ action: "list_token_balances", accountType: "evm_smart", properties: { network: options.network, managed: true, }, }); return listTokenBalances(apiClient, { ...listOptions, address: options.smartAccount.address, network: options.network as ListEvmTokenBalancesNetwork, }); }, }); } if (isMethodSupportedOnNetwork("requestFaucet", options.network)) { Object.assign(account, { requestFaucet: async (faucetOptions: Omit<RequestFaucetOptions, "address" | "network">) => { Analytics.trackAction({ action: "request_faucet", accountType: "evm_smart", properties: { network: options.network, managed: true, }, }); return requestFaucet(apiClient, { ...faucetOptions, address: options.smartAccount.address, network: options.network as "base-sepolia" | "ethereum-sepolia", }); }, }); } if (isMethodSupportedOnNetwork("quoteFund", options.network)) { Object.assign(account, { quoteFund: async (quoteOptions: Omit<EvmQuoteFundOptions, "address">) => { Analytics.trackAction({ action: "quote_fund", accountType: "evm_smart", properties: { network: options.network, managed: true, }, }); return quoteFund(apiClient, { ...quoteOptions, address: options.smartAccount.address, }); }, }); } if (isMethodSupportedOnNetwork("fund", options.network)) { Object.assign(account, { fund: async (fundOptions: Omit<EvmFundOptions, "address">) => { Analytics.trackAction({ action: "fund", accountType: "evm_smart", properties: { network: options.network, managed: true, }, }); return fund(apiClient, { ...fundOptions, address: options.smartAccount.address, }); }, waitForFundOperationReceipt: async (waitOptions: WaitForFundOperationOptions) => { return waitForFundOperationReceipt(apiClient, waitOptions); }, }); } if (isMethodSupportedOnNetwork("quoteSwap", options.network)) { Object.assign(account, { quoteSwap: async (quoteSwapOptions: SmartAccountQuoteSwapOptions) => { Analytics.trackAction({ action: "quote_swap", accountType: "evm_smart", properties: { network: options.network, managed: true, }, }); return createSwapQuote(apiClient, { ...quoteSwapOptions, taker: options.smartAccount.address, signerAddress: options.owner.address, smartAccount: options.smartAccount, network: options.network as SmartAccountSwapNetwork, }); }, }); } if (isMethodSupportedOnNetwork("swap", options.network)) { Object.assign(account, { swap: async (swapOptions: SmartAccountSwapOptions) => { Analytics.trackAction({ action: "swap", accountType: "evm_smart", properties: { network: options.network, managed: true, }, }); return sendSwapOperation(apiClient, { ...swapOptions, smartAccount: options.smartAccount, taker: options.smartAccount.address, signerAddress: options.owner.address, network: options.network as SmartAccountSwapNetwork, paymasterUrl: swapOptions.paymasterUrl ?? paymasterUrl, }); }, }); } if (isMethodSupportedOnNetwork("useSpendPermission", options.network)) { Object.assign(account, { useSpendPermission: async ( spendPermissionOptions: Omit<UseSpendPermissionOptions, "network">, ) => { Analytics.trackAction({ action: "use_spend_permission", accountType: "evm_smart", properties: { managed: true, }, }); return options.smartAccount.useSpendPermission({ ...spendPermissionOptions, network: options.network as SpendPermissionNetwork, }); }, }); } return account; }