@coinbase/cdp-sdk
Version:
SDK for interacting with the Coinbase Developer Platform Wallet API
1,298 lines • 62.4 kB
JavaScript
"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