UNPKG

@coinbase/cdp-sdk

Version:

SDK for interacting with the Coinbase Developer Platform Wallet API

1,298 lines 62.4 kB
"use strict"; /** * @module Client */ Object.defineProperty(exports, "__esModule", { value: true }); exports.EvmClient = void 0; const crypto_1 = require("crypto"); const viem_1 = require("viem"); const toEvmServerAccount_js_1 = require("../../accounts/evm/toEvmServerAccount.js"); const toEvmSmartAccount_js_1 = require("../../accounts/evm/toEvmSmartAccount.js"); const getUserOperation_js_1 = require("../../actions/evm/getUserOperation.js"); const listSpendPermissions_js_1 = require("../../actions/evm/listSpendPermissions.js"); const listTokenBalances_js_1 = require("../../actions/evm/listTokenBalances.js"); const requestFaucet_js_1 = require("../../actions/evm/requestFaucet.js"); const sendTransaction_js_1 = require("../../actions/evm/sendTransaction.js"); const sendUserOperation_js_1 = require("../../actions/evm/sendUserOperation.js"); const resolveSpendPermission_js_1 = require("../../actions/evm/spend-permissions/resolveSpendPermission.js"); const createSwapQuote_js_1 = require("../../actions/evm/swap/createSwapQuote.js"); const getSwapPrice_js_1 = require("../../actions/evm/swap/getSwapPrice.js"); const waitForEvmEip7702DelegationStatus_js_1 = require("../../actions/evm/waitForEvmEip7702DelegationStatus.js"); const waitForUserOperation_js_1 = require("../../actions/evm/waitForUserOperation.js"); const analytics_js_1 = require("../../analytics.js"); const constants_js_1 = require("../../constants.js"); const errors_js_1 = require("../../errors.js"); const errors_js_2 = require("../../openapi-client/errors.js"); const index_js_1 = require("../../openapi-client/index.js"); const constants_js_2 = require("../../spend-permissions/constants.js"); const export_js_1 = require("../../utils/export.js"); /** * The namespace containing all EVM methods. */ class EvmClient { /** * Creates a new CDP EVM account. * * @param {CreateServerAccountOptions} [options] - Optional parameters for creating the account. * @param {string} [options.name] - A name for the account to create. * @param {string} [options.idempotencyKey] - An idempotency key. * * @returns A promise that resolves to the newly created account. * * @example **Without arguments** * ```ts * const account = await cdp.evm.createAccount(); * ``` * * @example **With a name** * ```ts * const account = await cdp.evm.createAccount({ name: "MyAccount" }); * ``` * * @example **With an idempotency key** * ```ts * const idempotencyKey = uuidv4(); * * // First call * await cdp.evm.createAccount({ * idempotencyKey, * }); * * // Second call with the same idempotency key will return the same account * await cdp.evm.createAccount({ * idempotencyKey, * }); * ``` */ async createAccount(options = {}) { analytics_js_1.Analytics.trackAction({ action: "create_account", accountType: "evm_server", }); try { return await this._createAccountInternal(options); } catch (error) { analytics_js_1.Analytics.trackError(error, "createAccount"); throw error; } } /** * Imports a CDP EVM account from an external source. * * @param {ImportServerAccountOptions} options - Parameters for importing the account. * @param {string} options.privateKey - The private key of the account to import. * @param {string} [options.name] - A name for the account to import. * @param {string} [options.idempotencyKey] - An idempotency key. * * @returns A promise that resolves to the imported account. * * @example **Without arguments** * ```ts * const account = await cdp.evm.importAccount({ * privateKey: "0x123456" * }); * ``` * * @example **With a name** * ```ts * const account = await cdp.evm.importAccount({ * privateKey: "0x123456", * name: "MyAccount" * }); * ``` * * @example **With an idempotency key** * ```ts * const idempotencyKey = uuidv4(); * * // First call * await cdp.evm.importAccount({ * privateKey: "0x123456", * idempotencyKey, * }); * * // Second call with the same idempotency key will return the same account * await cdp.evm.importAccount({ * privateKey: "0x123456" * idempotencyKey, * }); * ``` */ async importAccount(options) { analytics_js_1.Analytics.trackAction({ action: "import_account", accountType: "evm_server", }); try { const encryptionPublicKey = options.encryptionPublicKey || constants_js_1.ImportAccountPublicRSAKey; const privateKeyHex = options.privateKey.startsWith("0x") ? options.privateKey.slice(2) : options.privateKey; if (!/^[0-9a-fA-F]+$/.test(privateKeyHex)) { throw new errors_js_1.UserInputValidationError("Private key must be a valid hexadecimal string"); } const privateKeyBytes = Buffer.from(privateKeyHex, "hex"); const encryptedPrivateKey = (0, crypto_1.publicEncrypt)({ key: encryptionPublicKey, padding: crypto_1.constants.RSA_PKCS1_OAEP_PADDING, oaepHash: "sha256", }, privateKeyBytes); const openApiAccount = await index_js_1.CdpOpenApiClient.importEvmAccount({ name: options.name, encryptedPrivateKey: encryptedPrivateKey.toString("base64"), }, options.idempotencyKey); const account = (0, toEvmServerAccount_js_1.toEvmServerAccount)(index_js_1.CdpOpenApiClient, { account: openApiAccount, }); return account; } catch (error) { if (!(error instanceof errors_js_1.UserInputValidationError)) { analytics_js_1.Analytics.trackError(error, "importAccount"); } if (error instanceof errors_js_2.APIError) { throw error; } throw new Error(`Failed to import account: ${String(error)}`); } } /** * Exports a CDP EVM account's private key. * It is important to store the private key in a secure place after it's exported. * * @param {ExportServerAccountOptions} options - Parameters for exporting the account. * @param {string} [options.address] - The address of the account to export. * @param {string} [options.name] - The name of the account to export. * @param {string} [options.idempotencyKey] - An idempotency key. * * @returns A promise that resolves to the exported account’s 32-byte private key as a hex string, without the "0x" prefix. * * @example **With an address** * ```ts * const privateKey = await cdp.evm.exportAccount({ * address: "0x1234567890123456789012345678901234567890", * }); * ``` * * @example **With a name** * ```ts * const privateKey = await cdp.evm.exportAccount({ * name: "MyAccount", * }); * ``` */ async exportAccount(options) { analytics_js_1.Analytics.trackAction({ action: "export_account", accountType: "evm_server", }); try { const { publicKey, privateKey } = await (0, export_js_1.generateExportEncryptionKeyPair)(); const { encryptedPrivateKey } = await (async () => { if (options.address) { return index_js_1.CdpOpenApiClient.exportEvmAccount(options.address, { exportEncryptionKey: publicKey, }, options.idempotencyKey); } if (options.name) { return index_js_1.CdpOpenApiClient.exportEvmAccountByName(options.name, { exportEncryptionKey: publicKey, }, options.idempotencyKey); } throw new errors_js_1.UserInputValidationError("Either address or name must be provided"); })(); return (0, export_js_1.decryptWithPrivateKey)(privateKey, encryptedPrivateKey); } catch (error) { if (!(error instanceof errors_js_1.UserInputValidationError)) { analytics_js_1.Analytics.trackError(error, "exportAccount"); } throw error; } } /** * Creates a new CDP EVM smart account. * * @param {CreateSmartAccountOptions} options - Parameters for creating the smart account. * @param {Account} options.owner - The owner of the smart account. * The owner can be any Ethereum account with signing capabilities, * such as a CDP EVM account or a Viem LocalAccount. * @param {string} [options.idempotencyKey] - An idempotency key. * * @returns A promise that resolves to the newly created smart account. * * @example **With a CDP EVM Account as the owner** * ```ts * const account = await cdp.evm.createAccount(); * const smartAccount = await cdp.evm.createSmartAccount({ * owner: account, * }); * ``` * * @example **With a Viem LocalAccount as the owner** * ```ts * // See https://viem.sh/docs/accounts/local/privateKeyToAccount * const privateKey = generatePrivateKey(); * const account = privateKeyToAccount(privateKey); * const smartAccount = await client.evm.createSmartAccount({ * owner: account, * }); * ``` * * @example **With an idempotency key** * ```ts * const idempotencyKey = uuidv4(); * * // First call * await cdp.evm.createSmartAccount({ * owner: account, * idempotencyKey, * }); * * // Second call with the same idempotency key will return the same smart account * await cdp.evm.createSmartAccount({ * owner: account, * idempotencyKey, * ``` */ async createSmartAccount(options) { analytics_js_1.Analytics.trackAction({ action: "create_smart_account", accountType: "evm_smart", }); try { return await this._createSmartAccountInternal(options); } catch (error) { analytics_js_1.Analytics.trackError(error, "createSmartAccount"); throw error; } } /** * Creates a spend permission for a smart account. * * @param {CreateSpendPermissionOptions} options - Parameters for creating the spend permission. * @param {SpendPermission} options.spendPermission - The spend permission to create. * @param {string} [options.idempotencyKey] - The idempotency key to use for the spend permission. * * @returns A promise that resolves to the spend permission. * * @example * ```ts * const userOperation = await cdp.evm.createSpendPermission({ * spendPermission, * network: "base-sepolia", * }); * ``` */ async createSpendPermission(options) { analytics_js_1.Analytics.trackAction({ action: "create_spend_permission", }); try { const resolvedSpendPermission = (0, resolveSpendPermission_js_1.resolveSpendPermission)(options.spendPermission, options.network); const userOperation = await index_js_1.CdpOpenApiClient.createSpendPermission(resolvedSpendPermission.account, { spender: resolvedSpendPermission.spender, token: resolvedSpendPermission.token, allowance: resolvedSpendPermission.allowance.toString(), period: resolvedSpendPermission.period.toString(), start: resolvedSpendPermission.start.toString(), end: resolvedSpendPermission.end.toString(), salt: resolvedSpendPermission.salt.toString(), extraData: resolvedSpendPermission.extraData, network: options.network, paymasterUrl: options.paymasterUrl, }, options.idempotencyKey); return { network: userOperation.network, userOpHash: userOperation.userOpHash, status: userOperation.status, calls: userOperation.calls.map(call => ({ to: call.to, value: BigInt(call.value), data: call.data, })), }; } catch (error) { analytics_js_1.Analytics.trackError(error, "createSpendPermission"); throw error; } } /** * Revokes a spend permission for a smart account. * * @param {RevokeSpendPermissionOptions} options - Parameters for revoking the spend permission. * @param {string} options.address - The address of the smart account. * @param {string} options.permissionHash - The hash of the spend permission to revoke. * @param {string} options.network - The network of the spend permission. * @param {string} [options.paymasterUrl] - The paymaster URL of the spend permission. * * @returns A promise that resolves to the user operation. * * @example * ```ts * const userOperation = await cdp.evm.revokeSpendPermission({ * address: "0x1234567890123456789012345678901234567890", * permissionHash: "0x1234567890123456789012345678901234567890123456789012345678901234", * network: "base-sepolia", * }); * ``` */ async revokeSpendPermission(options) { analytics_js_1.Analytics.trackAction({ action: "revoke_spend_permission", }); try { const userOperation = await index_js_1.CdpOpenApiClient.revokeSpendPermission(options.address, { network: options.network, permissionHash: options.permissionHash, paymasterUrl: options.paymasterUrl, }, options.idempotencyKey); return { network: userOperation.network, userOpHash: userOperation.userOpHash, status: userOperation.status, calls: userOperation.calls.map(call => ({ to: call.to, value: BigInt(call.value), data: call.data, })), }; } catch (error) { analytics_js_1.Analytics.trackError(error, "revokeSpendPermission"); throw error; } } /** * Gets a CDP EVM account. * * @param {GetServerAccountOptions} options - Parameters for getting the account. * Either `address` or `name` must be provided. * If both are provided, lookup will be done by `address` and `name` will be ignored. * @param {string} [options.address] - The address of the account to get. * @param {string} [options.name] - The name of the account to get. * * @returns A promise that resolves to the account. * * @example **Get an account by address** * ```ts * const account = await cdp.evm.getAccount({ * address: "0x1234567890123456789012345678901234567890", * }); * ``` * * @example **Get an account by name** * ```ts * const account = await cdp.evm.getAccount({ * name: "MyAccount", * }); * ``` */ async getAccount(options) { analytics_js_1.Analytics.trackAction({ action: "get_account", accountType: "evm_server", }); try { return await this._getAccountInternal(options); } catch (error) { analytics_js_1.Analytics.trackError(error, "getAccount"); throw error; } } /** * Gets a CDP EVM smart account. * * @param {GetSmartAccountOptions} options - Parameters for getting the smart account. * Either `address` or `name` must be provided. * If both are provided, lookup will be done by `address` and `name` will be ignored. * @param {string} [options.address] - The address of the smart account to get. * @param {string} [options.name] - The name of the smart account to get. * @param {Account} options.owner - The owner of the smart account. * You must pass the signing-capable owner of the smart account so that the returned smart account * can be functional. * * @returns A promise that resolves to the smart account. * * @example * ```ts * const smartAccount = await cdp.evm.getSmartAccount({ * address: "0x1234567890123456789012345678901234567890", * owner: account, * }); * ``` */ async getSmartAccount(options) { analytics_js_1.Analytics.trackAction({ action: "get_smart_account", }); try { return await this._getSmartAccountInternal(options); } catch (error) { analytics_js_1.Analytics.trackError(error, "getSmartAccount"); throw error; } } /** * Gets a CDP EVM account, or creates one if it doesn't exist. * * @param {GetOrCreateServerAccountOptions} options - Parameters for getting or creating the account. * @param {string} [options.name] - The name of the account to get or create. * * @returns A promise that resolves to the account. * * @example * ```ts * const account = await cdp.evm.getOrCreateAccount({ * name: "MyAccount", * }); * ``` */ async getOrCreateAccount(options) { analytics_js_1.Analytics.trackAction({ action: "get_or_create_account", accountType: "evm_server", }); try { try { const account = await this._getAccountInternal(options); return account; } catch (error) { // If it failed because the account doesn't exist, create it const doesAccountNotExist = error instanceof errors_js_2.APIError && error.statusCode === 404; if (doesAccountNotExist) { try { const account = await this._createAccountInternal(options); return account; } catch (error) { // If it failed because the account already exists, get the existing account const doesAccountAlreadyExist = error instanceof errors_js_2.APIError && error.statusCode === 409; if (doesAccountAlreadyExist) { const account = await this._getAccountInternal(options); return account; } throw error; } } throw error; } } catch (error) { analytics_js_1.Analytics.trackError(error, "getOrCreateAccount"); throw error; } } /** * Gets a CDP EVM smart account, or creates one if it doesn't exist. * This method first attempts to retrieve an existing smart account with the given parameters. * If no account exists, it creates a new one with the specified owner. * * @param {GetOrCreateSmartAccountOptions} options - Configuration options for getting or creating the smart account. * @param {string} [options.name] - The name of the smart account to get or create. * @param {Account} options.owner - The owner of the smart account. * * @returns {Promise<SmartAccount>} A promise that resolves to the retrieved or newly created smart account. * * @example * ```ts * const smartAccount = await cdp.evm.getOrCreateSmartAccount({ * name: "MySmartAccount", * owner: account, * }); * ``` */ async getOrCreateSmartAccount(options) { analytics_js_1.Analytics.trackAction({ action: "get_or_create_smart_account", accountType: "evm_smart", }); try { try { const account = await this._getSmartAccountInternal(options); return account; } catch (error) { // If it failed because the account doesn't exist, create it const doesAccountNotExist = error instanceof errors_js_2.APIError && error.statusCode === 404; if (doesAccountNotExist) { try { const account = await this._createSmartAccountInternal(options); return account; } catch (error) { // If it failed because the account already exists, get the existing account const doesAccountAlreadyExist = error instanceof errors_js_2.APIError && error.statusCode === 409; if (doesAccountAlreadyExist) { const account = await this._getSmartAccountInternal(options); return account; } throw error; } } throw error; } } catch (error) { analytics_js_1.Analytics.trackError(error, "getOrCreateSmartAccount"); throw error; } } /** * Gets the price for a swap between two tokens on an EVM network. * * @param {GetSwapPriceOptions} options - The options for getting a swap price. * * @returns {Promise<GetSwapPriceResult | SwapUnavailableResult>} A promise that resolves to the swap price result or a response indicating that liquidity is unavailable. * * @example * ```typescript * const price = await cdp.evm.getSwapPrice({ * network: "ethereum-mainnet", * toToken: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC * fromToken: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH * fromAmount: BigInt("1000000000000000000"), // 1 WETH * taker: "0x1234567890123456789012345678901234567890" * }); * ``` */ async getSwapPrice(options) { analytics_js_1.Analytics.trackAction({ action: "get_swap_price", properties: { network: options.network, }, }); try { return await (0, getSwapPrice_js_1.getSwapPrice)(index_js_1.CdpOpenApiClient, options); } catch (error) { analytics_js_1.Analytics.trackError(error, "getSwapPrice"); throw error; } } /** * Creates a quote for a swap between two tokens on an EVM network. * * @param {CreateSwapQuoteOptions} options - The options for creating a swap quote. * * @returns {Promise<CreateSwapQuoteResult | SwapUnavailableResult>} A promise that resolves to the swap quote result or a response indicating that liquidity is unavailable. * * @example * ```typescript * const swapQuote = await cdp.evm.createSwapQuote({ * network: "ethereum", * toToken: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC * fromToken: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH * fromAmount: BigInt("1000000000000000000"), // 1 WETH * taker: "0x1234567890123456789012345678901234567890" * }); * ``` */ async createSwapQuote(options) { analytics_js_1.Analytics.trackAction({ action: "create_swap_quote", properties: { network: options.network, }, }); try { return await (0, createSwapQuote_js_1.createSwapQuote)(index_js_1.CdpOpenApiClient, options); } catch (error) { analytics_js_1.Analytics.trackError(error, "createSwapQuote"); throw error; } } /** * Gets a user operation for a smart account by user operation hash. * * @param {GetUserOperationOptions} options - Parameters for getting the user operation. * @param {SmartAccount} options.smartAccount - The smart account signing the user operation. * @param {string} options.userOpHash - The user operation hash. * * @returns A promise that resolves to the user operation. * * @example * ```ts * const userOp = await cdp.evm.getUserOperation({ * smartAccount, * userOpHash: "0x1234567890123456789012345678901234567890123456789012345678901234", * }); * ``` */ async getUserOperation(options) { analytics_js_1.Analytics.trackAction({ action: "get_user_operation", }); try { return await (0, getUserOperation_js_1.getUserOperation)(index_js_1.CdpOpenApiClient, options); } catch (error) { analytics_js_1.Analytics.trackError(error, "getUserOperation"); throw error; } } /** * Lists CDP EVM accounts. * * @param {ListServerAccountsOptions} [options] - Optional parameters for listing the accounts. * @param {number} [options.pageSize] - The number of accounts to return. * @param {string} [options.pageToken] - The page token to begin listing from. * This is obtained by previous calls to this method. * * @returns A promise that resolves to an array of accounts, and a token to paginate through the accounts. * * @example * ```ts * const accounts = await cdp.evm.listAccounts(); * ``` * * @example **With pagination** * ```ts * let page = await cdp.evm.listAccounts(); * * while (page.nextPageToken) { * page = await cdp.evm.listAccounts({ pageToken: page.nextPageToken }); * } * ``` */ async listAccounts(options = {}) { analytics_js_1.Analytics.trackAction({ action: "list_accounts", accountType: "evm_server", }); try { const ethAccounts = await index_js_1.CdpOpenApiClient.listEvmAccounts({ pageSize: options.pageSize, pageToken: options.pageToken, }); return { accounts: ethAccounts.accounts.map(account => { const evmAccount = (0, toEvmServerAccount_js_1.toEvmServerAccount)(index_js_1.CdpOpenApiClient, { account, }); return evmAccount; }), nextPageToken: ethAccounts.nextPageToken, }; } catch (error) { analytics_js_1.Analytics.trackError(error, "listAccounts"); throw error; } } /** * Lists CDP EVM token balances. * * @param {ListTokenBalancesOptions} options - Parameters for listing the token balances. * @param {number} [options.pageSize] - The number of token balances to return. * @param {string} [options.pageToken] - The page token to begin listing from. * This is obtained by previous calls to this method. * * @returns A promise that resolves to an array of token balances, and a token to paginate through the token balances. * * @example * ```ts * const tokenBalances = await cdp.evm.listTokenBalances({ * address: "0x1234567890123456789012345678901234567890", * network: "base-sepolia", * }); * ``` * * @example * **With pagination** * ```ts * let page = await cdp.evm.listTokenBalances({ * address: "0x1234567890123456789012345678901234567890", * network: "base-sepolia", * }); * * while (page.nextPageToken) { * page = await cdp.evm.listTokenBalances({ * address: "0x1234567890123456789012345678901234567890", * network: "base-sepolia", * pageToken: page.nextPageToken, * }); * } */ async listTokenBalances(options) { analytics_js_1.Analytics.trackAction({ action: "list_token_balances", properties: { network: options.network, }, }); try { return await (0, listTokenBalances_js_1.listTokenBalances)(index_js_1.CdpOpenApiClient, options); } catch (error) { analytics_js_1.Analytics.trackError(error, "listTokenBalances"); throw error; } } /** * Lists CDP EVM smart accounts. * * @param {ListSmartAccountsOptions} options - Parameters for listing the smart accounts. * @param {number} [options.pageSize] - The number of smart accounts to return. * @param {string} [options.pageToken] - The page token to begin listing from. * This is obtained by previous calls to this method. * * @returns A promise that resolves to an array of smart accounts, and a token to paginate through the smart accounts. * * @example * ```ts * const smartAccounts = await cdp.evm.listSmartAccounts(); * ``` * * @example **With pagination** * ```ts * let page = await cdp.evm.listSmartAccounts(); * * while (page.nextPageToken) { * page = await cdp.evm.listSmartAccounts({ pageToken: page.nextPageToken }); * } * ``` */ async listSmartAccounts(options = {}) { analytics_js_1.Analytics.trackAction({ action: "list_smart_accounts", }); try { const smartAccounts = await index_js_1.CdpOpenApiClient.listEvmSmartAccounts({ pageSize: options.pageSize, pageToken: options.pageToken, }); return { accounts: smartAccounts.accounts.map(account => ({ address: account.address, owners: [account.owners[0]], type: "evm-smart", policies: account.policies, })), nextPageToken: smartAccounts.nextPageToken, }; } catch (error) { analytics_js_1.Analytics.trackError(error, "listSmartAccounts"); throw error; } } /** * Lists the spend permissions for a smart account. * * @param {ListSpendPermissionsOptions} options - Parameters for listing the spend permissions. * @param {string} options.address - The address of the smart account. * @param {number} [options.pageSize] - The number of spend permissions to return. * @param {string} [options.pageToken] - The page token to return the next page of spend permissions. * * @returns A promise that resolves to the spend permissions. */ async listSpendPermissions(options) { analytics_js_1.Analytics.trackAction({ action: "list_spend_permissions", }); try { return await (0, listSpendPermissions_js_1.listSpendPermissions)(index_js_1.CdpOpenApiClient, options); } catch (error) { analytics_js_1.Analytics.trackError(error, "listSpendPermissions"); throw error; } } /** * Prepares a user operation for a smart account. * * @param {PrepareUserOperationOptions} options - Parameters for preparing the user operation. * @param {SmartAccount} options.smartAccount - The smart account signing the user operation. * @param {string} options.network - The network to prepare the user operation for. * @param {EvmCall[]} options.calls - The calls to include in the user operation. * @param {string} [options.paymasterUrl] - The optional paymaster URL to use for the user operation. * @param {PaymasterContext} [options.paymasterContext] - The optional ERC-7677 paymaster context. Only valid when a paymaster is configured. * * @returns A promise that resolves to the user operation hash. * * @example * ```ts * const userOp = await cdp.evm.prepareUserOperation({ * smartAccount, * network: "base-sepolia", * calls: [ * { * to: "0x1234567890123456789012345678901234567890", * value: parseEther("0.000001"), * data: "0x", * }, * ], * }); * ``` */ async prepareUserOperation(options) { analytics_js_1.Analytics.trackAction({ action: "prepare_user_operation", properties: { network: options.network, }, }); try { const userOp = await index_js_1.CdpOpenApiClient.prepareUserOperation(options.smartAccount.address, { network: options.network, calls: options.calls.map(call => ({ to: call.to, value: call.value.toString(), data: call.data, overrideGasLimit: call.overrideGasLimit, })), paymasterUrl: options.paymasterUrl, paymasterContext: options.paymasterContext, dataSuffix: options.dataSuffix, }); return { network: userOp.network, userOpHash: userOp.userOpHash, status: userOp.status, calls: userOp.calls.map(call => ({ to: call.to, value: BigInt(call.value), data: call.data, })), expiresAt: userOp.expiresAt, }; } catch (error) { analytics_js_1.Analytics.trackError(error, "prepareUserOperation"); throw error; } } /** * Prepares and sends a user operation for a smart account. * * @param {PrepareAndSendUserOperationOptions} options - Parameters for preparing and sending the user operation. * @param {SmartAccount} options.smartAccount - The smart account signing the user operation. * @param {string} options.network - The network to prepare and send the user operation on. * @param {EvmCall[]} options.calls - The calls to include in the user operation. * @param {string} [options.paymasterUrl] - The optional paymaster URL to use for the user operation. * * @returns A promise that resolves to the smart account address, user operation hash, and status of the user operation. * * @example * ```ts * const { userOpHash } = await cdp.evm.prepareAndSendUserOperation({ * smartAccount, * network: "base-sepolia", * calls: [ * { * to: "0x1234567890123456789012345678901234567890", * value: parseEther("0.000001"), * data: "0x", * }, * ], * }); * ``` */ async prepareAndSendUserOperation(options) { analytics_js_1.Analytics.trackAction({ action: "prepare_and_send_user_operation", properties: { network: options.network, }, }); try { const userOp = await index_js_1.CdpOpenApiClient.prepareAndSendUserOperation(options.smartAccount.address, { network: options.network, calls: options.calls.map(call => ({ to: call.to, value: call.value.toString(), data: call.data, })), paymasterUrl: options.paymasterUrl, }, options.idempotencyKey); return { smartAccountAddress: options.smartAccount.address, userOpHash: userOp.userOpHash, status: userOp.status, expiresAt: userOp.expiresAt, }; } catch (error) { analytics_js_1.Analytics.trackError(error, "prepareAndSendUserOperation"); throw error; } } /** * Requests funds from an EVM faucet. * * @param {RequestFaucetOptions} options - Parameters for requesting funds from the EVM faucet. * @param {string} options.address - The address to request funds for. * @param {string} options.network - The network to request funds from. * @param {string} options.token - The token to request funds for. * @param {string} [options.idempotencyKey] - An idempotency key. * * @returns A promise that resolves to the transaction hash. * * @example * ```ts * const result = await cdp.evm.requestFaucet({ * address: "0x1234567890123456789012345678901234567890", * network: "base-sepolia", * token: "eth", * }); * ``` */ async requestFaucet(options) { analytics_js_1.Analytics.trackAction({ action: "request_faucet", properties: { network: options.network, }, }); try { return await (0, requestFaucet_js_1.requestFaucet)(index_js_1.CdpOpenApiClient, options); } catch (error) { analytics_js_1.Analytics.trackError(error, "requestFaucet"); throw error; } } /** * Signs an EVM transaction and sends it to the specified network using the Coinbase API. * This method handles nonce management and gas estimation automatically. * * @param {SendTransactionOptions} options - Configuration options for sending the transaction. * @returns A promise that resolves to the transaction hash. * * @example * **Sending an RLP-encoded transaction** * ```ts * import { parseEther, serializeTransaction } from "viem"; * import { baseSepolia } from "viem/chains"; * * const { transactionHash } = await cdp.evm.sendTransaction({ * address: account.address, * transaction: serializeTransaction({ * to: "0x4252e0c9A3da5A2700e7d91cb50aEf522D0C6Fe8", * value: parseEther("0.000001"), * chainId: baseSepolia.id, * // Fields below are optional, CDP API will populate them if omitted. * // nonce * // maxPriorityFeePerGas * // maxFeePerGas * // gas * }), * network: "base-sepolia", * }); * ``` * @example * **Sending an EIP-1559 transaction request object** * ```ts * const { transactionHash } = await cdp.evm.sendTransaction({ * address: account.address, * transaction: { * to: "0x4252e0c9A3da5A2700e7d91cb50aEf522D0C6Fe8", * value: parseEther("0.000001"), * // Fields below are optional, CDP API will populate them if omitted. * // nonce * // maxPriorityFeePerGas * // maxFeePerGas * // gas * }, * network: "base-sepolia", * }); * ``` */ async sendTransaction(options) { analytics_js_1.Analytics.trackAction({ action: "send_transaction", properties: { network: options.network, }, }); try { return await (0, sendTransaction_js_1.sendTransaction)(index_js_1.CdpOpenApiClient, options); } catch (error) { analytics_js_1.Analytics.trackError(error, "sendTransaction"); throw error; } } /** * Sends a user operation. * * @param {SendUserOperationOptions} options - Parameters for sending the user operation. * @param {SmartAccount} options.smartAccount - The smart account sending the user operation. * @param {string} options.network - The network to send the user operation on. * @param {EvmCall[]} options.calls - The calls to include in the user operation. * @param {string} [options.paymasterUrl] - The optional paymaster URL to use for the user operation. * @param {string} [options.idempotencyKey] - An idempotency key. * * @returns A promise that resolves to an object containing the smart account address, * the user operation hash, and the status of the user operation. * * @example * ```ts * const userOp = await cdp.evm.sendUserOperation({ * smartAccount, * network: "base-sepolia", * calls: [ * { * to: "0x1234567890123456789012345678901234567890", * value: parseEther("0.000001"), * data: "0x", * }, * ], * }); * ``` */ async sendUserOperation(options) { analytics_js_1.Analytics.trackAction({ action: "send_user_operation", properties: { network: options.network, }, }); try { return await (0, sendUserOperation_js_1.sendUserOperation)(index_js_1.CdpOpenApiClient, { smartAccount: options.smartAccount, network: options.network, calls: options.calls, paymasterUrl: options.paymasterUrl, paymasterContext: options.paymasterContext, idempotencyKey: options.idempotencyKey, dataSuffix: options.dataSuffix, }); } catch (error) { analytics_js_1.Analytics.trackError(error, "sendUserOperation"); throw error; } } /** * Signs an EVM hash. * * @param {SignHashOptions} options - Parameters for signing the hash. * @param {string} options.address - The address to sign the hash for. * @param {string} options.hash - The hash to sign. * @param {string} [options.idempotencyKey] - An idempotency key. * * @returns A promise that resolves to the signature. * * @example * ```ts * // Create a new EVM server account to sign with * const ethAccount = await cdp.createEvmServerAccount({}); * * const signature = await cdp.evm.signHash({ * address: ethAccount.address, * hash: "0x1234567890123456789012345678901234567890123456789012345678901234", * }); * ``` */ async signHash(options) { analytics_js_1.Analytics.trackAction({ action: "sign_hash", }); try { const signature = await index_js_1.CdpOpenApiClient.signEvmHash(options.address, { hash: options.hash, }, options.idempotencyKey); return { signature: signature.signature, }; } catch (error) { analytics_js_1.Analytics.trackError(error, "signHash"); throw error; } } /** * Signs an EIP-191 message. * * @param {SignMessageOptions} options - Parameters for signing the message. * @param {string} options.address - The address to sign the message for. * @param {string} options.message - The message to sign. * @param {string} [options.idempotencyKey] - An idempotency key. * * @returns A promise that resolves to the signature. * * @example * ```ts * // Create a new EVM server account to sign with * const ethAccount = await cdp.createEvmServerAccount({}); * * const signature = await cdp.evm.signMessage({ * address: ethAccount.address, * message: "Hello, world!", * }); * ``` */ async signMessage(options) { analytics_js_1.Analytics.trackAction({ action: "sign_message", }); try { const signature = await index_js_1.CdpOpenApiClient.signEvmMessage(options.address, { message: options.message, }, options.idempotencyKey); return { signature: signature.signature, }; } catch (error) { analytics_js_1.Analytics.trackError(error, "signMessage"); throw error; } } /** * Signs an EIP-712 message. * * @param {SignTypedDataOptions} options - Parameters for signing the EIP-712 message. * @returns A promise that resolves to the signature. * * @example * ```ts * const signature = await cdp.evm.signTypedData({ * address: account.address, * domain: { * name: "Permit2", * chainId: 1, * verifyingContract: "0x000000000022D473030F116dDEE9F6B43aC78BA3", * }, * types: { * EIP712Domain: [ * { name: "name", type: "string" }, * { name: "chainId", type: "uint256" }, * { name: "verifyingContract", type: "address" }, * ], * PermitTransferFrom: [ * { name: "permitted", type: "TokenPermissions" }, * { name: "spender", type: "address" }, * { name: "nonce", type: "uint256" }, * { name: "deadline", type: "uint256" }, * ], * TokenPermissions: [ * { name: "token", type: "address" }, * { name: "amount", type: "uint256" }, * ], * }, * primaryType: "PermitTransferFrom", * message: { * permitted: { * token: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", * amount: "1000000", * }, * spender: "0xFfFfFfFFfFFfFFfFFfFFFFFffFFFffffFfFFFfFf", * nonce: "0", * deadline: "1717123200", * }, * }); * ``` */ async signTypedData(options) { analytics_js_1.Analytics.trackAction({ action: "sign_typed_data", }); try { const { domain, message, primaryType } = options; const types = { EIP712Domain: (0, viem_1.getTypesForEIP712Domain)({ domain }), ...options.types, }; const openApiMessage = { domain, types, primaryType, message, }; const signature = await index_js_1.CdpOpenApiClient.signEvmTypedData(options.address, openApiMessage, options.idempotencyKey); return { signature: signature.signature, }; } catch (error) { analytics_js_1.Analytics.trackError(error, "signTypedData"); throw error; } } /** * Signs an EVM transaction. * * @param {SignTransactionOptions} options - Configuration options for signing the transaction. * @returns A promise that resolves to the signature. * * @example * ```ts * import { parseEther, serializeTransaction } from "viem"; * import { baseSepolia } from "viem/chains"; * * // Create a new EVM server account to sign with * const ethAccount = await cdp.createEvmServerAccount({}); * * const serializedTx = serializeTransaction( * { * chainId: baseSepolia.id, * data: "0x", * to: "0x4252e0c9A3da5A2700e7d91cb50aEf522D0C6Fe8", * type: "eip1559", * value: parseEther("0.000001"), * }, * ); * * const signature = await cdp.evm.signTransaction({ * address: ethAccount.address, * transaction: serializedTx, * }); * ``` */ async signTransaction(options) { analytics_js_1.Analytics.trackAction({ action: "sign_transaction", }); try { const signature = await index_js_1.CdpOpenApiClient.signEvmTransaction(options.address, { transaction: options.transaction, }, options.idempotencyKey); return { signature: signature.signedTransaction, }; } catch (error) { analytics_js_1.Analytics.trackError(error, "signTransaction"); throw error; } } /** * Updates a CDP EVM account. * * @param {UpdateEvmAccountOptions} [options] - Optional parameters for creating the account. * @param {string} options.address - The address of the account to update * @param {UpdateEvmAccountBody} options.update - An object containing account fields to update. * @param {string} [options.update.name] - The new name for the account. * @param {string} [options.update.accountPolicy] - The ID of a Policy to apply to the account. * @param {string} [options.idempotencyKey] - An idempotency key. * * @returns A promise that resolves to the updated account. * * @example **With a name** * ```ts * const account = await cdp.evm.updateAccount({ address: "0x...", update: { name: "New Name" } }); * ``` * * @example **With an account policy** * ```ts * const account = await cdp.evm.updateAccount({ address: "0x...", update: { accountPolicy: "73bcaeeb-d7af-4615-b064-42b5fe83a31e" } }); * ``` * * @example **With an idempotency key** * ```ts * const idempotencyKey = uuidv4(); * * // First call * await cdp.evm.updateAccount({ * addre