@coinbase/cdp-core

中文文档
0.0.130发布于 2026/11/10TypeScriptES Module近 30 天下载 3.8万

这个软件包包含了CDP前端SDK的核心业务逻辑. 它用于使用纯打字符的非反应应用.

中文使用文档
文档目录23 节
  1. 快速启动
  2. 安装
  3. 收集您的 CDP 项目信息
  4. 允许列出本地应用程序
  5. 反应原生存储
  6. 初始化 SDK
  7. 签名 在用户中
  8. 链接其他认证方法
  9. 签名 使用自定义认证
  10. 查看用户信息
  11. 多事实认证
  12. 手动创建账户
  13. 发送 EVM 交易
  14. 智能账户操作
  15. 开发者代表团
  16. 签署索拉纳交易
  17. 签署索拉纳信件
  18. 发送索拉纳交易
  19. 签名信件和输入的数据
  20. 导出私有密钥
  21. X402 支付协议支助
  22. EIP-1193 供应商
  23. Viem 账户

这个软件包包含了CDP前端SDK的核心业务逻辑. 它用于使用纯打字符的非反应应用.

快速启动

这个向导会帮助您开始 @coinbase/cdp-core你会学会如何安装软件包, 初始化SDK,并拨打你的第一个API电话.

安装

首先,使用您首选的软件包管理器将软件包添加到您的项目中 .

# With pnpm
pnpm add @coinbase/cdp-core

# With yarn
yarn add @coinbase/cdp-core

# With npm
npm install @coinbase/cdp-core

收集您的 CDP 项目信息

  1. 在此处签名或创建账户 CDP 门户
  2. 在您的仪表板上,从最上方的下拉位置选择一个项目,并复制项目ID

允许列出本地应用程序

  1. 导航到 嵌入式钱包配置 在 CDP 门户网站中,单击添加来源以包含本地应用程序
  2. 输入本地运行的应用程序的出处 - 例如 , http://localhost:3000
  3. 点击 重新添加来源以保存您的更改

反应原生存储

在回放原生时, SDK 存储状态通过 @react-native-async-storage/async-storage 以 默认。 AsyncStorage 是可选的对等对等依赖 @coinbase/cdp-core使用 不同的商店提供适配器 configurePlatformServices。在启动时、之后配置它 导入 @coinbase/cdp-core 电话之前 initialize。 。 。 .

configurePlatformServices 仅取代您通过的服务。 其他服务都保留着 反应原生默认 。 平台存储持有待处理的 OAuth 流程 ID, 备份 OAuth 流程 校验, 持有嵌入式钱包存储器, 并在平台上镜像刷新符号, 不 安全存储. getItemWithOutcome 在自定义适配器上可选。 SDK来源于 getItem 当你忽略它.

待定的OAuth流量ID为CSRF状态. 它的商店必须是私人的应用 并且不能是 可被另一个来源或应用程序写入.

一个应用没有 @react-native-async-storage/async-storage 很可能还缺少 expo-secure-store,SDK在原生地上用于刷新符号. 此应用程序必须安装 expo-secure-store 或同时通过 secureStorage 改为 configurePlatformServices没有安全 存储中,应用程序可以签名,然后在下个符号刷新时签名出.

例如,创建 cdp-storage.ts 带有 缩略语:MMKV 适配器. createMMKV 这是 react-native-mmkv v4 API; 使用的 v2 和 v3 new MMKV()。 。 。 .

import { configurePlatformServices, type PlatformStorageOverride } from "@coinbase/cdp-core";
import { createMMKV } from "react-native-mmkv";

const mmkv = createMMKV({ id: "cdp" });

export const mmkvStorage: PlatformStorageOverride = {
  async getItem(key) {
    return mmkv.getString(key) ?? null;
  },
  async setItem(key, value) {
    mmkv.set(key, value);
  },
  async removeItem(key) {
    mmkv.remove(key);
  },
  async clear() {
    mmkv.clearAll();
  },
};

configurePlatformServices({ storage: mmkvStorage });

SDK从不打电话 clear() 自己来. clearAll() 这里很安全,因为 createMMKV({ id: "cdp" }) 将实例指定为 CDP 。 共享实例的适配器必须 范围 clear 到 CDP 键.

在调用代码之前, 从您的应用程序入口导入该文件的副作用 initialize数字 :

import "./cdp-storage";
import "expo-router/entry";

初始化 SDK

在调用 SDK 中的任何方法之前, 您必须首先初始化 :

import { Config, initialize } from "@coinbase/cdp-core";

const config: Config = {
  // Copy and paste your project ID here.
  projectId: "your-project-id",
}

await initialize(config);

分析

默认SDK会释放出使用分析器来帮助我们改进SDK. 如果您想选择退出,您可以通过设置 disableAnalytics 配置选项到 true。 。 。 .

const config: Config = {
  projectId: "your-project-id",
  disableAnalytics: true,
}

await initialize(config);

账户配置

您可以配置 SDK 为新用户创建不同类型的账户 :

智能账户配置 :

const config: Config = {
  projectId: "your-project-id",
  ethereum: {
    createOnLogin: "smart", // Creates Smart Accounts instead of EOAs
  },
}

await initialize(config);

何时 ethereum.createOnLogin 设置为 "smart"SDK会:

  1. 自动创建 EOA( 外部拥有账户) 作为所有者
  2. 创建该 EOA 拥有的智能账户
  3. 这两个账户都将在用户对象上可用

索拉纳账户配置 :

const config: Config = {
  projectId: "your-project-id",
  solana: {
    createOnLogin: true, // Creates Solana accounts
  },
}

await initialize(config);

何时 solana.createOnLogin 设置为 trueSDK会:

  1. 为新用户创建索拉纳账户
  2. 索拉纳账户将在 solanaAccounts 属性

递延账户的创建

可以省略 createOnLogin 完全防止自动创建账户,而是在需要时手工创建账户:

const config: Config = {
  projectId: "your-project-id",
  // No ethereum or solana createOnLogin configuration
}

await initialize(config);

何时 createOnLogin 省略, SDK 将:

  1. 用户登录时不自动创建任何账户
  2. 需要使用账户创建动作手动创建账户(见下文)
  3. 完全控制创建时间和类型的账户

多账户支助

用户可以拥有多种类型账户:

  • 最多10个EVM EOA账户
  • 最多10个索拉纳账户
  • 最多10个EVM智能账户(每个EVM EOA可以拥有一个智能账户)

使用账户对象( 建议) :

SDK为丰富的账户对象提供了更多元数据,如创建时间戳和所有者关系:

import { getCurrentUser } from "@coinbase/cdp-core";

const user = await getCurrentUser();

// Access all EVM EOA accounts with metadata
if (user?.evmAccountObjects) {
  user.evmAccountObjects.forEach((account, index) => {
    console.log(`EVM Account ${index + 1}:`, account.address);
    console.log(`Created:`, new Date(account.createdAt).toLocaleDateString());
  });
}

// Access all Solana accounts with metadata
if (user?.solanaAccountObjects) {
  user.solanaAccountObjects.forEach((account, index) => {
    console.log(`Solana Account ${index + 1}:`, account.address);
    console.log(`Created:`, new Date(account.createdAt).toLocaleDateString());
  });
}

// Access all EVM Smart Accounts with owner information
if (user?.evmSmartAccountObjects) {
  user.evmSmartAccountObjects.forEach((account, index) => {
    console.log(`Smart Account ${index + 1}:`, account.address);
    console.log(`Owners:`, account.ownerAddresses.join(', '));
    console.log(`Created:`, new Date(account.createdAt).toLocaleDateString());
  });
}

遗留账户矩阵( 已过期) :

对于后向相容性,SDK仍然提供简单的地址阵列,但这些被贬损:

// ⚠️ DEPRECATED - Use evmAccountObjects instead
const evmAddresses = user?.evmAccounts; // string[]

// ⚠️ DEPRECATED - Use solanaAccountObjects instead
const solanaAddresses = user?.solanaAccounts; // string[]

// ⚠️ DEPRECATED - Use evmSmartAccountObjects instead
const smartAccounts = user?.evmSmartAccounts; // string[]

签名 在用户中

你现在准备开始呼叫 由包提供的API! 终端用户中的以下代码符号:

import { signInWithEmail, verifyEmailOTP } from "@coinbase/cdp-core";

// Send an email to [email protected] with a One Time Password (OTP).
const authResult = await signInWithEmail({
  email: "[email protected]"
});

// Input the OTP sent to [email protected].
const verifyResult = await verifyEmailOTP({
  flowId: authResult.flowId,
  otp: "123456", // Hardcoded for convenience here.
});

// Get the authenticated end user.
const user = verifyResult.user;

一旦一个用户被认证,您就可以将额外的认证方法链接到他们的账户. 这允许用户在使用多种方法(电子邮件,短消息,OAuth提供商)时签名,使用相同的嵌入式钱包.

import { linkEmail, verifyEmailOTP } from "@coinbase/cdp-core";

// User must be signed in first
const result = await linkEmail("[email protected]");

// Verify the OTP sent to the email
await verifyEmailOTP({
  flowId: result.flowId,
  otp: "123456"
});
import { linkSms, verifySmsOTP } from "@coinbase/cdp-core";

// User must be signed in first
const result = await linkSms("+14155552671");

// Verify the OTP sent via SMS
await verifySmsOTP({
  flowId: result.flowId,
  otp: "123456"
});
import { linkGoogle } from "@coinbase/cdp-core";

// User must be signed in first
// This initiates the OAuth flow to link a Google account
await linkGoogle();
// The user will be redirected to Google for authentication
// After successful authentication, the Google account will be linked
import { linkApple } from "@coinbase/cdp-core";

// User must be signed in first
await linkApple();
import { linkOAuth } from "@coinbase/cdp-core";

// User must be signed in first
// Link a Google account
await linkOAuth("google");

// Link an Apple account
await linkOAuth("apple");

签名 使用自定义认证

如果使用第三方身份提供商(Auth0,Firebase,AWS Cognitto,或任何符合OIDC的提供商),可以从提供商那里认证使用JWT的用户.

先决条件

在使用自定义认证前 :

  1. 在 CDP 门户网站中配置身份提供者数字 :

    • 导航到 嵌入式钱包配置
    • 点击自定义认证标签
    • 添加您的 JWKS 端点 URL( 例如 ), https://your-domain.auth0.com/.well-known/jwks.json(中文(简体) )
    • 配置您的 JWT 发行者和观众
  2. 提供a customAuth.getJwt 回调 初始化 SDK 时 :

import { initialize, authenticateWithJWT } from "@coinbase/cdp-core";

await initialize({
  projectId: "your-project-id",
  customAuth: {
    // This callback should return a fresh JWT from your identity provider
    getJwt: async () => {
      // Return a JWT from your IDP (Auth0, Firebase, Cognito, etc.)
      // This will be called automatically when the SDK needs a fresh token
      const token = await yourAuthProvider.getAccessToken();
      return token;
    }
  },
  ethereum: {
    createOnLogin: "eoa" // Optional: configure wallet creation
  }
});

认证用户

配置后,请拨 authenticateWithJWT() 认证用户:

import { authenticateWithJWT, getCurrentUser } from "@coinbase/cdp-core";

// After your user has signed in to your IDP (Auth0, Firebase, etc.)
const result = await authenticateWithJWT();

console.log("User authenticated:", result.user);
console.log("Is new user:", result.isNewUser);

// The user is now signed in and wallets are created based on your config
const user = await getCurrentUser();
if (user?.evmAccounts?.[0]) {
  console.log("EVM Address:", user.evmAccountObjects[0]?.address);
}

如何运作

  1. 您的用户标记为身份提供者( Auth0, Firebase, Cognitto等)
  2. 你打电话 authenticateWithJWT() 内部呼唤你的 customAuth.getJwt 回调
  3. SDK 将 JWT 发送到 CDP 的后端, 以您配置的 JWKS 进行验证
  4. 如果有效, 用户会被认证, 钱包根据您的配置自动创建
  5. 这个 customAuth.getJwt 每当 SDK 需要新符号时, 便自动调用

查看用户信息

一旦最终用户签名,您可以在您的应用程序中显示其信息:

import { getCurrentUser, isSignedIn } from "@coinbase/cdp-core";

// Check if user is signed in
const signedIn = await isSignedIn();

if (signedIn) {
  // Get the user's information
  const user = await getCurrentUser();
  console.log("User ID:", user.userId);

  // Display different account types based on configuration
  if (user.evmAccountObjects?.length > 0) {
    console.log("EVM Accounts (EOAs):", user.evmAccountObjects);
  }
  if (user.evmSmartAccountObjects?.length > 0) {
    console.log("EVM Smart Accounts:", user.evmSmartAccountObjects);
  }
  if (user.solanaAccountObjects?.length > 0) {
    console.log("Solana Accounts:", user.solanaAccountObjects);
  }

  // Find the user's email address (if they logged in with email/otp)
  const email = user.authenticationMethods.email?.email;
  console.log("Email Address:", email);
}

多事实认证

SDK支持两种多因子认证方法,为您的应用程序添加多层安全性:

  • TOTP( 基于时间的一次性密码): 用户使用Google认证或Authy等认证程序注册
  • 简讯: 用户通过短信到其电话号码接收验证码

重要:用户必须经过认证(签名),才能报名参加外交部或进行外交部核查.

MFA 入学流程

入学流程包括两个步骤:

  1. 开始入学 - 对于TOTP:生成一个秘密和QR代码. 短信:将检察官办公室发送给电话号码
  2. 提交入学情况 - 校验用户代码以完成入学
TOTP 注册
import {
  initiateMfaEnrollment,
  submitMfaEnrollment,
  getCurrentUser
} from "@coinbase/cdp-core";

// Step 1: Initiate TOTP MFA enrollment (user must be signed in)
const enrollment = await initiateMfaEnrollment({
  mfaMethod: "totp"
});

// Display QR code for user to scan with their authenticator app
console.log("Scan this QR code URL:", enrollment.authUrl);
// Or display the secret for manual entry
console.log("Or enter this secret manually:", enrollment.secret);

// Step 2: After user adds to their authenticator app, verify with the 6-digit code
const result = await submitMfaEnrollment({
  mfaMethod: "totp",
  mfaCode: "123456" // The 6-digit code from the user's authenticator app
});

// After successful enrollment, the user object is updated with MFA information
console.log("MFA enrolled for user:", result.user.userId);
console.log("TOTP enrollment info:", result.user.mfaMethods?.totp);
// Output: { enrolledAt: "2024-01-01T00:00:00Z" }
短消息录入
import {
  initiateMfaEnrollment,
  submitMfaEnrollment
} from "@coinbase/cdp-core";

// Step 1: Initiate SMS MFA enrollment (user must be signed in)
// Phone number must be in E.164 format (e.g., +14155552671)
const enrollment = await initiateMfaEnrollment({
  mfaMethod: "sms",
  phoneNumber: "+14155552671"  // Can be any phone number, doesn't have to match auth phone
});

console.log("SMS sent:", enrollment.success);
// User receives SMS with 6-digit code

// Step 2: Submit the code received via SMS
const result = await submitMfaEnrollment({
  mfaMethod: "sms",
  mfaCode: "654321" // The 6-digit code from SMS
});

console.log("SMS MFA enrolled for user:", result.user.userId);
console.log("SMS enrollment info:", result.user.mfaMethods?.sms);
// Output: { enrolledAt: "2024-01-16T10:30:00Z" }

// Check current user's MFA methods
const user = await getCurrentUser();
console.log("User MFA methods:", user.mfaMethods);

外交部核查流程

在进行需要外交部核查的敏感作业时,使用核查流程:

TOTP 验证
import {
  initiateMfaVerification,
  submitMfaVerification
} from "@coinbase/cdp-core";

// Step 1: Initiate TOTP MFA verification (user must be signed in and enrolled)
await initiateMfaVerification({
  mfaMethod: "totp"
});

// Step 2: Submit the 6-digit code from the user's authenticator app
await submitMfaVerification({
  mfaMethod: "totp",
  mfaCode: "654321" // The current 6-digit code from the authenticator app
});

// MFA verification successful - user can now perform sensitive operations
console.log("TOTP verification completed");
短消息核查
import {
  initiateMfaVerification,
  submitMfaVerification
} from "@coinbase/cdp-core";

// Step 1: Initiate SMS MFA verification (user must be signed in and enrolled)
// This sends a 6-digit code to the user's enrolled phone number
await initiateMfaVerification({
  mfaMethod: "sms"
});

console.log("SMS sent to enrolled phone number");
// User receives SMS with 6-digit code

// Step 2: Submit the 6-digit code from SMS
await submitMfaVerification({
  mfaMethod: "sms",
  mfaCode: "123456" // The code received via SMS
});

// MFA verification successful - user can now perform sensitive operations
console.log("SMS verification completed");

完整示例:外交部设置和使用

import {
  initialize,
  signInWithEmail,
  verifyEmailOTP,
  initiateMfaEnrollment,
  submitMfaEnrollment,
  initiateMfaVerification,
  submitMfaVerification,
  getCurrentUser,
  signEvmTransaction
} from "@coinbase/cdp-core";

// Initialize the SDK
await initialize({
  projectId: "your-project-id"
});

// Sign in the user first
const { flowId } = await signInWithEmail({ 
  email: "[email protected]" 
});

const { user } = await verifyEmailOTP({
  flowId,
  otp: "123456"
});

// Check if user has MFA enabled
if (!user.mfaMethods?.totp) {
  // Enroll in MFA
  const enrollment = await initiateMfaEnrollment({ 
    mfaMethod: "totp" 
  });
  
  // Show QR code to user (in a real app, you'd display this as an actual QR code)
  console.log("Please scan this QR code with your authenticator app:");
  console.log(enrollment.authUrl);
  
  // Get the code from user input
  const mfaCode = prompt("Enter the 6-digit code from your authenticator app:");
  
  // Complete enrollment
  const result = await submitMfaEnrollment({
    mfaMethod: "totp",
    mfaCode
  });
  
  console.log("MFA successfully enabled!");
  console.log("Enrolled at:", result.user.mfaMethods.totp.enrolledAt);
}

// Later, when performing a sensitive operation that requires MFA...
try {
  // Attempt the operation
  await signEvmTransaction({ /* ... */ });
} catch (error) {
  // If MFA is required, the operation will fail
  // Initiate MFA verification
  await initiateMfaVerification({ 
    mfaMethod: "totp" 
  });
  
  // Get MFA code from user
  const verificationCode = prompt("Enter your 6-digit MFA code:");
  
  // Submit verification
  await submitMfaVerification({
    mfaMethod: "totp",
    mfaCode: verificationCode
  });
  
  // Retry the operation after successful MFA verification
  await signEvmTransaction({ /* ... */ });
}

处理多个外交部的方法

当用户有多个 MFA 方法登录时,使用帮助器函数检查注册状态,让用户选择自己喜欢的方法:

import {
  getCurrentUser,
  getEnrolledMfaMethods,
  isEnrolledInMfa,
  initiateMfaVerification,
  submitMfaVerification
} from "@coinbase/cdp-core";

const user = await getCurrentUser();

// Get all enrolled MFA methods
const methods = getEnrolledMfaMethods(user);
console.log("Enrolled methods:", methods);
// Output: ['totp', 'sms'] or ['totp'] or ['sms'] or []

// Check if user has any MFA enrolled
if (isEnrolledInMfa(user)) {
  console.log("User has MFA enabled");
}

// Check if user has specific method enrolled
if (isEnrolledInMfa(user, "totp")) {
  console.log("User has TOTP enabled");
}

if (isEnrolledInMfa(user, "sms")) {
  console.log("User has SMS enabled");
}

// When user has multiple methods, let them choose
if (methods.length > 1) {
  console.log("Please choose your MFA method:");
  methods.forEach((method, index) => {
    console.log(`${index + 1}. ${method.toUpperCase()}`);
  });

  // Get user's choice (in a real app, this would be a UI selection)
  const choice = prompt("Enter 1 for TOTP or 2 for SMS:");
  const selectedMethod = methods[parseInt(choice) - 1];

  // Use the selected method for verification
  await initiateMfaVerification({ mfaMethod: selectedMethod });
  const code = prompt(`Enter your ${selectedMethod.toUpperCase()} code:`);
  await submitMfaVerification({ mfaMethod: selectedMethod, mfaCode: code });
}

电话号码验证

报名时,电话号码必须采用E.164格式。 SDK提供严格的验证:

import { validatePhoneNumber } from "@coinbase/cdp-core";

try {
  // Valid formats
  validatePhoneNumber("+14155552671");  // US
  validatePhoneNumber("+442071838750"); // UK
  validatePhoneNumber("+81312345678");  // Japan
  console.log("Phone number is valid");
} catch (error) {
  // Invalid formats will throw an error
  console.error(error.message);
  // Example: "Invalid phone number format: '4155552671'. Phone number must be in E.164 format..."
}

// Common invalid formats:
// validatePhoneNumber("4155552671");       // Missing +
// validatePhoneNumber("+1-415-555-2671");  // Contains hyphens
// validatePhoneNumber("+1 415 555 2671");  // Contains spaces
// validatePhoneNumber("+0412345678");      // Starts with 0

检查 MFA 配置

检查 MFA 是否启用您的工程和视图配置设置 :

import { getMfaConfig } from "@coinbase/cdp-core";

// Retrieve MFA configuration for the current project
const config = await getMfaConfig();

console.log("MFA enabled:", config.enabled);
console.log("TOTP enabled:", config.totpConfig.enabled);
console.log("SMS enabled:", config.smsConfig?.enabled);
console.log("Configuration created:", config.createdAt);
console.log("Last updated:", config.updatedAt);

// Example response:
// {
//   projectId: "your-project-id",
//   enabled: true,
//   totpConfig: { enabled: true },
//   smsConfig: { enabled: true },
//   createdAt: "2024-01-01T00:00:00Z",
//   updatedAt: "2024-01-15T10:30:00Z"
// }

音轨 MFA 录入提示

当用户被显示时, 民政部的入学记录会及时追踪入学机会 :

import { recordMfaEnrollmentPrompted, getCurrentUser } from "@coinbase/cdp-core";

// When showing the MFA enrollment prompt to a user (must be signed in)
const result = await recordMfaEnrollmentPrompted();

console.log("Enrollment prompt recorded at:", result.enrollmentPromptedAt);

// The user's state is updated with the prompt timestamp
const user = await getCurrentUser();
console.log("Last prompted:", user.mfaMethods?.enrollmentPromptedAt);
// Output: "2024-01-15T10:30:00Z"

// This helps track when users skip MFA enrollment so you can
// decide when to prompt them again

使用案例跟踪录入提示 :

  • 用户跳过 MFA 注册时跟踪
  • 执行智能再提示逻辑(例如30天不要再次提示)
  • 分析外交部的收养率
  • 识别被催促但尚未注册的用户

手动创建账户

如果您没有配置 SDK createOnLogin,您可以在需要的时候手动为认证的用户创建账户。 这样你就可以完全控制账户的创建.

创建 EVM EOA 账户

import { createEvmEoaAccount, getCurrentUser } from "@coinbase/cdp-core";

// User must be signed in first
const user = await getCurrentUser();

if (!user.evmAccountObjects?.length) {
  // Create an EVM EOA (Externally Owned Account)
  const evmAddress = await createEvmEoaAccount();
  console.log("Created EVM EOA:", evmAddress);

  // The user object is automatically updated
  const updatedUser = await getCurrentUser();
  console.log("User now has EVM EOA:", updatedUser.evmAccountObjects[0]?.address);
}

说明: createEvmEoaAccount() 如果用户已拥有 EVM EOA 账户, 则会丢出错误 .

创建 EVM 智能账户

import { createEvmSmartAccount, getCurrentUser } from "@coinbase/cdp-core";

// User must be signed in first
const user = await getCurrentUser();

if (!user.evmSmartAccountObjects?.length) {
  // Create a Smart Account (a new EOA will be created as the owner)
  const smartAccountAddress = await createEvmSmartAccount();
  console.log("Created Smart Account:", smartAccountAddress);

  // The user object is automatically updated
  const updatedUser = await getCurrentUser();
  console.log("User now has Smart Account:", updatedUser.evmSmartAccountObjects[0]?.address);
  console.log("And EOA (used as owner):", updatedUser.evmAccountObjects[0]?.address);
}

说明: 默认, createEvmSmartAccount() 总是创建一个新的EOA来作为智能账户的拥有者.

您也可以在创建智能账户时启用使用权限 :

import { createEvmSmartAccount } from "@coinbase/cdp-core";

// Create Smart Account with spend permissions enabled
const smartAccountAddress = await createEvmSmartAccount({
  enableSpendPermissions: true
});

console.log("Created Smart Account with spend permissions:", smartAccountAddress);

使用特定所有人:

您可以指定一个现有的 EOA 地址作为所有者使用,而不是创建一个新的地址 :

import { createEvmSmartAccount, getCurrentUser } from "@coinbase/cdp-core";

const user = await getCurrentUser();
const existingEoaAddress = user.evmAccountObjects[0]?.address;

// Create Smart Account with a specific owner
// Note: The owner must not already control another smart account for this user
const smartAccountAddress = await createEvmSmartAccount({
  owner: existingEoaAddress,
  enableSpendPermissions: false
});

console.log("Created Smart Account with specific owner:", smartAccountAddress);

创建一个索拉纳账户

import { createSolanaAccount, getCurrentUser } from "@coinbase/cdp-core";

// User must be signed in first
const user = await getCurrentUser();

if (!user.solanaAccountObjects?.length) {
  // Create a Solana account
  const solanaAddress = await createSolanaAccount();
  console.log("Created Solana account:", solanaAddress);

  // The user object is automatically updated
  const updatedUser = await getCurrentUser();
  console.log("User now has Solana account:", updatedUser.solanaAccountObjects[0]?.address);
}

说明: createSolanaAccount() 如果用户已经有一个索拉纳账户,则会出错.

发送 EVM 交易

我们支持在以下网络的单一呼吁中签署和发送EVM交易:

  • 基础
  • 塞波利亚基地
  • 以利亚
  • 伊特鲁姆·塞波利亚
  • 雪崩
  • 坐标
  • 乐观主义
  • 多边形
import { sendEvmTransaction, getCurrentUser } from "@coinbase/cdp-core";

const user = await getCurrentUser();
const evmAccount = user.evmAccountObjects[0]?.address;

const result = await sendEvmTransaction({
  evmAccount,
  transaction: {
    to: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
    value: 100000000000000n, // 0.0001 ETH in wei
    nonce: 0,
    gas: 21000n,
    maxFeePerGas: 30000000000n,
    maxPriorityFeePerGas: 1000000000n,
    chainId: 84532, // Base Sepolia
    type: "eip1559",
  }
});

console.log("Transaction Hash:", result.transactionHash);

对于除CDP API支持的EVM网络外的EVM网络,您的终端用户必须签名交易,然后 您必须亲自广播交易。 此示例使用来自 viem 广播交易.

import { signEvmTransaction, getCurrentUser } from "@coinbase/cdp-core";
import { http, createPublicClient } from "viem";
import { tron } from "viem/chains";

const user = await getCurrentUser();
const evmAccount = user.evmAccountObjects[0]?.address;

// Sign the transaction
const { signedTransaction } = await signEvmTransaction({
  evmAccount,
  transaction: {
    to: "0x...",
    value: 100000000000000n,
    nonce: 0,
    gas: 21000n,
    maxFeePerGas: 30000000000n,
    maxPriorityFeePerGas: 1000000000n,
    chainId: 728126428, // Tron
    type: "eip1559",
  }
});

// Broadcast signed transaction to non-Base chain
const client = createPublicClient({
  chain: tron,
  transport: http()
});

const hash = await client.sendRawTransaction({
  serializedTransaction: signedTransaction
});

智能账户操作

Smart counts提供高级账户抽象功能,包括用户操作和付费主支持.

创建支出权限

支出许可允许Smart Accounts在规定的期限和期限内将支出授权给其他账户. 这样可以使用订阅付款,自动DeFi策略等案例,并自动地充值AI代理资金.

import { createSpendPermission, getCurrentUser } from "@coinbase/cdp-core";

const user = await getCurrentUser();
const smartAccount = user.evmSmartAccountObjects[0]?.address;

const result = await createSpendPermission({
  evmSmartAccount: smartAccount,
  network: "base-sepolia",
  spender: "0x742D35Cc6634C0532925a3b8D6Ec6F1C2b9c1E46", // Address that can spend tokens
  token: "eth", // Token symbol ("eth", "usdc") or contract address
  allowance: "1000000000000000000", // 1 ETH in wei
  period: 86400, // 24 hours in seconds
  start: new Date(), // Start time (optional, defaults to now)
  end: new Date(Date.now() + 86400 * 30 * 1000), // End time (optional, defaults to no expiration)
  useCdpPaymaster: true, // Use CDP paymaster for gas sponsorship
});

console.log("User Operation Hash:", result.userOperationHash);

您还可以使用 periodInDays 一个更人性化的API:

const result = await createSpendPermission({
  evmSmartAccount: smartAccount,
  network: "base-sepolia",
  spender: "0x742D35Cc6634C0532925a3b8D6Ec6F1C2b9c1E46",
  token: "usdc", // USDC token
  allowance: "10000000", // 10 USDC (6 decimals)
  periodInDays: 7, // Weekly recurring allowance
  useCdpPaymaster: true
});

列表支出权限

获取智能账户的所有使用权限 :

import { listSpendPermissions, getCurrentUser } from "@coinbase/cdp-core";

const user = await getCurrentUser();
const smartAccount = user.evmSmartAccountObjects[0]?.address;

const result = await listSpendPermissions({
  evmSmartAccount: smartAccount,
  network: "base-sepolia",
  pageSize: 10
});

console.log("Found", result.spendPermissions.length, "spend permissions");
for (const permission of result.spendPermissions) {
  console.log("Permission:", permission.permissionHash, "Revoked:", permission.revoked);
  console.log("Spender:", permission.permission.spender);
  console.log("Token:", permission.permission.token);
  console.log("Allowance:", permission.permission.allowance);
}

// Paginate through results if needed
if (result.hasNextPage) {
  const nextPage = await listSpendPermissions({
    evmSmartAccount: smartAccount,
    network: "base-sepolia",
    pageToken: result.nextPageToken
  });
}

撤销支出权限

取消智能账户的支出权限 :

import { revokeSpendPermission, getCurrentUser } from "@coinbase/cdp-core";

const user = await getCurrentUser();
const smartAccount = user.evmSmartAccountObjects[0]?.address;

const result = await revokeSpendPermission({
  evmSmartAccount: smartAccount,
  network: "base-sepolia",
  permissionHash: "0x5678...",
  useCdpPaymaster: true
});

console.log("User Operation Hash:", result.userOperationHash);

开发者代表团

开发者代表团允许开发者代表最终用户在指定期限内签署交易. 最终用户必须经过认证才能授权授权.

创建代表团

import { createDelegation } from "@coinbase/cdp-core";

// Create a delegation valid for 24 hours
const result = await createDelegation({
  expiresAt: new Date(Date.now() + 86400 * 1000).toISOString(),
});

console.log("Delegation expires at:", result.expiresAt);

获取主动代表团

import { getDelegation } from "@coinbase/cdp-core";

// Get the active delegation for the current user
const delegation = await getDelegation();

console.log("Delegation expires at:", delegation.expiresAt);

撤销代表团

import { revokeDelegation } from "@coinbase/cdp-core";

// Revoke all active delegations for the current user
await revokeDelegation();

console.log("All active delegations revoked");

签署索拉纳交易

当您的应用程序配置为 solana: { createOnLogin: true }您可以在索拉纳交易上签名:

import { signSolanaTransaction, getCurrentUser } from "@coinbase/cdp-core";

const user = await getCurrentUser();
const solanaAccount = user.solanaAccountObjects[0]?.address;

const result = await signSolanaTransaction({
  solanaAccount,
  transaction: "base64-encoded-solana-transaction"  // Your Solana transaction here
});

console.log("Signed Transaction:", result.signedTransaction);
// The signedTransaction can now be broadcast to the Solana network

签署索拉纳信件

您也可以在索拉纳账户上签名任意消息 :

import { signSolanaMessage, getCurrentUser } from "@coinbase/cdp-core";

const user = await getCurrentUser();
const solanaAccount = user.solanaAccountObjects[0]?.address;

const message = Buffer.from("Hello, Solana!", "utf8").toString("base64");
const result = await signSolanaMessage({
  solanaAccount,
  message // Base64 encoded message to sign
});

console.log("Message Signature:", result.signature);
// The signature can be used for authentication or verification purposes

发送索拉纳交易

您可以在下列索拉纳网络的单一呼叫中签名并发送索拉纳交易:

  • 索拉纳主网
  • 索拉纳·德夫内
import { sendSolanaTransaction, getCurrentUser } from "@coinbase/cdp-core";

const user = await getCurrentUser();
const solanaAccount = user.solanaAccountObjects[0]?.address;

const result = await sendSolanaTransaction({
  solanaAccount,
  network: "solana-devnet", // or "solana" for mainnet
  transaction: "base64-encoded-solana-transaction",  // Your Solana transaction here
  useCdpSponsor: true, // Optional: CDP sponsors the transaction fee
});

console.log("Transaction Signature:", result.transactionSignature);
// The transaction has been broadcast to the Solana network

发送用户操作

从智能账户发送用户操作 :

import { sendUserOperation, getCurrentUser } from "@coinbase/cdp-core";

const user = await getCurrentUser();
const smartAccount = user.evmSmartAccountObjects[0]?.address;

const result = await sendUserOperation({
  evmSmartAccount: smartAccount,
  network: "base-sepolia",
  calls: [
    {
      to: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
      value: 1000000000000000000n, // 1 ETH in wei
      data: "0x", // Optional contract interaction data
    }
  ],
  // Optional paymaster for gas sponsorship. Get your free Base paymaster URL [from the CDP Portal](https://portal.cdp.coinbase.com/products/node).
  paymasterUrl: "https://paymaster.example.com",
});

console.log("User Operation Hash:", result.userOperationHash);

与EIP-8021的交易归属:

您可以在用户操作中添加归属数据, 用于跟踪应用使用情况和收入共享 :

import { sendUserOperation, getCurrentUser } from "@coinbase/cdp-core";

const user = await getCurrentUser();
const smartAccount = user.evmSmartAccountObjects[0]?.address;

// EIP-8021 data suffix for "baseapp" attribution (Schema ID 0)
// Format: {codes}{codesLength}{schemaId}{ercSuffix}
const dataSuffix = "0xdddddddd62617365617070070080218021802180218021802180218021";

const result = await sendUserOperation({
  evmSmartAccount: smartAccount,
  network: "base-sepolia",
  calls: [
    {
      to: "0xTargetContract",
      value: 0n,
      data: "0x",
    }
  ],
  dataSuffix, // Attribution data appended to callData
  useCdpPaymaster: true,
});

console.log("User Operation Hash:", result.userOperationHash);
// The dataSuffix will be appended to the user operation's callData for onchain attribution

这个 dataSuffix 是一条遵循 EIP-8021标准 用于交易归属。 它允许应用跟踪使用情况并启用收入分享机制. 后缀自动附加到用户操作的 callData 在提交来文之前.

获取用户操作状态

发送用户操作后, 您可以获取其状态并获取结果 :

import { getUserOperation } from "@coinbase/cdp-core";

// Get the status of a user operation
const userOperationResult = await getUserOperation({
  userOperationHash: result.userOperationHash,
  evmSmartAccount: smartAccount,
  network: "base-sepolia"
});

console.log("Status:", userOperationResult.status); // "pending", "complete", or "failed"

if (userOperationResult.status === "complete") {
  console.log("Transaction Hash:", userOperationResult.transactionHash);
  console.log("Block Number:", userOperationResult.receipts?.[0]?.blockNumber);
} else if (userOperationResult.status === "failed") {
  console.log("Failure reason:", userOperationResult.receipts?.[0]?.revert?.message);
}

签名信件和输入的数据

终端用户可以签名EVM消息,散列和打出的数据来生成各种链上应用程序的签名.

import { signEvmMessage, signEvmTypedData, getCurrentUser } from "@coinbase/cdp-core";

const user = await getCurrentUser();
const evmAccount = user.evmAccountObjects[0]?.address;

// Sign a message
const messageResult = await signEvmMessage({
  evmAccount,
  message: "Hello World"
});

// Sign typed data (EIP-712)
const typedDataResult = await signEvmTypedData({
  evmAccount,
  typedData: {
    domain: {
      name: "Example DApp",
      version: "1",
      chainId: 84532,
    },
    types: {
      Person: [
        { name: "name", type: "string" },
        { name: "wallet", type: "address" }
      ]
    },
    primaryType: "Person",
    message: {
      name: "Bob",
      wallet: evmAccount
    }
  }
});

导出私有密钥

终端用户可以从嵌入式钱包中导出私人密钥,让他们能将密钥导入自己选择的相容钱包.

安全 Iframe 导出

私人密钥导出只通过安全的iframe流支持. 它创建了一个安全的iframe,将私钥直接复制到用户的剪贴板上,而不会暴露在应用程序的JavaScript上下文中.

通过 Iframe 导出 EVM 私钥
import { createEvmKeyExportIframe } from "@coinbase/cdp-core";

const container = document.getElementById("key-export-container");

const { cleanup } = await createEvmKeyExportIframe({
  address: "0x1234...",
  target: container,
  projectId: "your-project-id",
  label: "Copy Private Key",
  onStatusUpdate: (status, message) => {
    if (status === "success") {
      console.log("Key copied to clipboard!");
    } else if (status === "error") {
      console.error("Error:", message);
    }
  }
});

// The iframe will auto-cleanup when the session expires, or you can manually cleanup:
// cleanup();
通过 Iframe 导出 Solana 私钥
import { createSolanaKeyExportIframe } from "@coinbase/cdp-core";

const container = document.getElementById("key-export-container");

const { cleanup } = await createSolanaKeyExportIframe({
  address: "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
  target: container,
  projectId: "your-project-id",
  label: "Copy Private Key",
  onStatusUpdate: (status, message) => {
    if (status === "success") {
      console.log("Key copied to clipboard!");
    } else if (status === "error") {
      console.error("Error:", message);
    }
  }
});
通过 Iframe 导出回收词

设定 exportFormat: "mnemonic" 以导出 EVM 或 Solana 账户的 24 字恢复短语 。 检查 availableExportFormats 在提供选项之前包括它。 清单中不包括的格式 error 无需出口请求。 如果列表缺失,则由服务器决定. 选择 exportFormat 输出私钥.

import { createEvmKeyExportIframe, getCurrentUser } from "@coinbase/cdp-core";

const user = await getCurrentUser();
const account = user?.evmAccountObjects?.[0];
const canExportMnemonic = account?.availableExportFormats?.includes("mnemonic") ?? false;

if (account && canExportMnemonic) {
  const { cleanup } = await createEvmKeyExportIframe({
    address: account.address,
    target: document.getElementById("key-export-container"),
    projectId: "your-project-id",
    exportFormat: "mnemonic",
    label: "Copy recovery phrase",
    onStatusUpdate: (status, message) => {
      if (status === "error") console.error("Error:", message);
    },
  });
}

该短语遵循标准的衍生路径(m/44'/60'/0'/0/0 用于EVM和 m/44'/501'/0'/0' ,所以可以导入任何相容的钱包。 与私钥一样,该短语被复制到iframe内部的剪贴板上,并且从未被您应用程序的JavaScript所曝光.

X402 支付协议支助

SDK包括了对X402支付协议的内置支持,这使得HTTP请求能够有微额支付. 这样可以访问需要为每项请求付费的付费API和服务.

安装

确保您已单独安装 x402-fetch 软件包 :

npm install x402-fetch

基本用途

这个 fetchWithX402 函数提供一个包裹的获取 API,自动处理 X402 付款请求 :

import { fetchWithX402, getCurrentUser } from "@coinbase/cdp-core";

// The user must be authenticated first
const user = await getCurrentUser();

// Create a fetch function with X402 payment handling
const { fetchWithPayment } = fetchWithX402();

// Make a request to an X402-protected resource
try {
  const response = await fetchWithPayment("https://api.example.com/paid-endpoint", {
    method: "GET",
    headers: {
      "Content-Type": "application/json"
    }
  });

  const data = await response.json();
  console.log("Paid API response:", data);
} catch (error) {
  console.error("X402 payment failed:", error);
}

高级配置

您可以用选项自定义 X402 行为 :

// Use a specific address for payments (instead of the user's default)
const { fetchWithPayment } = fetchWithX402({
  address: "0x1234567890123456789012345678901234567890"
});

// Use a custom fetch implementation
const customFetch = (url, options) => {
  console.log("Making request to:", url);
  return fetch(url, options);
};

const { fetchWithPayment } = fetchWithX402({
  fetch: customFetch
});

如何运作

  1. 当您向 X402- 受保护的资源提出请求时, 服务器会用一个 402 Payment Required 状态
  2. 被包裹的获取函数自动 :
    • 从服务器的响应中提取付款细节
    • 使用用户钱包创建并签名支付交易
    • 在重试请求中包括付款证明
  3. 服务器验证付款并返回请求的资源

智能账户支持

默认, fetchWithX402 将使用用户的 Smart 账户( 如果可用), 返回到他们的 EVM 常规账户 :

const user = await getCurrentUser();
console.log("Using account:", user.evmSmartAccountObjects?.[0] || user.evmAccountObjects?.[0]);

// This will automatically use the appropriate account type
const { fetchWithPayment } = await fetchWithX402();

索拉纳支助

索拉纳从框中支持 fetchWithX402。如果终端用户同时拥有EVM和Solana账户,则默认使用EVM账户。 你可以把索拉纳地址传给 fetchWithX402 用索拉纳账户代替.

const user = await getCurrentUser();

const { fetchWithPayment } = fetchWithX402({
  address: user.solanaAccountObjects[0]?.address
});

EIP-1193 供应商

核心包包括一个EIP-1193相容的提供商. 此提供者可用于签名和发送交易 .

提供者通过呼叫创建 createCDPEmbeddedWallet,它暴露一个 .provider 属性. createCDPEmbeddedWallet 必须利用理想的链条来支持这些链条的运输.

供应商将首先连接到 chains 阵列。 运输一般为HTTP RPC端点,内部用于广播非Base交易. 有关运输的更多信息,参见: 瓦格米的书 createConfig 设置。 。 。 .

import { base, mainnet } from "viem/chains";
import { http } from "viem"

// Basic usage with default configuration
const wallet = createCDPEmbeddedWallet({
  chains:[base, mainnet],
  transports: {
    [base.id]: http(),
    [mainnet.id]: http()
  }
});
const provider = wallet.provider;

// Request account access
const accounts = await provider.request({
  method: "eth_requestAccounts"
});

// Sign a message
const signature = await provider.request({
  method: "personal_sign",
  params: ["Hello, World!", accounts[0]]
});

// Send a transaction
const txHash = await provider.request({
  method: "eth_sendTransaction",
  params: [{
    from: accounts[0],
    to: "0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6",
    value: "0x1000000000000000000"
  }]
});

// Listen for connection events
provider.on("connect", (connectInfo) => {
  console.log("Connected to chain:", connectInfo.chainId);
});

provider.on("disconnect", () => {
  console.log("Disconnected from wallet");
});

Viem 账户

核心软件包包括: toViemAccount 可以将嵌入的钱包打入 Viem 账户相容界面的功能。 这使得账户能够作为接受Viem账户的任何库或框架的倒置替换.

import { toViemAccount, getCurrentUser } from "@coinbase/cdp-core";
import { createWalletClient } from "viem";
import { mainnet } from "viem/chains";
import { http } from "viem";

const user = await getCurrentUser();
const evmAccount = user.evmAccountObjects[0]?.address;

const viemAccount = toViemAccount(evmAccount);

const client = createWalletClient({
  account: viemAccount,
  transport: http("https://example.com"),
  chain: mainnet,
});

版本与发布记录

@coinbase/cdp-core 共发布 129 个版本,首次发布于 2025/07/12;过去 12 个月发布了 71 个版本。

版本发布日期距今
0.0.130latest2026/11/10今天
0.0.1292026/11/055 天前
0.0.1282026/10/2219 天前
0.0.1272026/10/071 个月前
0.0.1262026/09/191 个月前
0.0.1252026/09/191 个月前

其他发布通道:placeholder → 0.0.0。

关于 @coinbase/cdp-core 的常见问题

@coinbase/cdp-core 是什么?

这个软件包包含了CDP前端SDK的核心业务逻辑. 它用于使用纯打字符的非反应应用.

如何安装 @coinbase/cdp-core?

在项目目录运行 npm install @coinbase/cdp-core,或使用 pnpm add / yarn add / bun add。

@coinbase/cdp-core 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@coinbase/cdp-core 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@coinbase/cdp-core 可以商用吗?

@coinbase/cdp-core 使用 未声明 许可。package.json 没有声明许可证。没有许可证的代码默认保留全部权利,商用前请联系作者或查看仓库中的 LICENSE 文件。以上为概括,不构成法律意见,请以许可原文为准。

@coinbase/cdp-core 的下载量有多少?

根据 npm 官方下载统计,@coinbase/cdp-core 在 2026/10/11 – 2026/11/09 这 30 天内被下载 38,464 次,日均约 1,282 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@coinbase/cdp-core 还在维护吗?

最新版本 0.0.130 发布于 2026/11/10(今天);至今共发布 129 个版本,其中过去 12 个月发布了 71 个;首次发布于 2025/07/12。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。