# @coinbase/cdp-core 中文文档

规范地址：https://npmcn.com/package/%40coinbase/cdp-core/

版本：0\.0\.130
npm 元数据更新时间：2026-11-09T23:37:23.888Z
中文译文更新时间：2026-11-10T10:25:02.749Z
软件包许可：未声明

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40coinbase/cdp-core
原文对照：https://npmcn.com/package/%40coinbase/cdp-core/?lang=original

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：2.2 MB，1349 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：8 个
- peer 依赖：x402-fetch ^1\.0\.0，expo-web-browser ^15\.0\.0，expo-secure-store ^15\.0\.0，@react-native-async-storage/async-storage ^2\.0\.0
- 首次发布：2025-07-11T19:23:43.957Z
- 最新版本发布：2026-11-09T23:37:23.653Z
- 近 30 天下载量：38464（2026-10-11 至 2026-11-09，npm 官方下载统计）
- 已发布版本数：129（近 12 个月 71 个）

## 中文简介

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

## 安装

```sh
npm install @coinbase/cdp-core
```

也可以使用：`pnpm add @coinbase/cdp-core`、`yarn add @coinbase/cdp-core`、`bun add @coinbase/cdp-core`

## README

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

## 快速启动

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

### 安装

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

```bash
# With pnpm
pnpm add @coinbase/cdp-core

# With yarn
yarn add @coinbase/cdp-core

# With npm
npm install @coinbase/cdp-core
```

### 收集您的 CDP 项目信息

1.  在此处签名或创建账户 [CDP 门户](https://portal.cdp.coinbase.com/)
2.  在您的仪表板上,从最上方的下拉位置选择一个项目,并复制项目ID

### 允许列出本地应用程序

1.  导航到 [嵌入式钱包配置](https://portal.cdp.coinbase.com/products/embedded-wallets/cors) 在 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](https://github.com/mrousavy/react-native-mmkv) 适配器. `createMMKV` 这是 `react-native-mmkv` v4 API; 使用的 v2 和 v3 `new MMKV()`。 。 。 .

```ts
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`数字 :

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

### 初始化 SDK

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

```ts
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`。 。 。 .

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

await initialize(config);
```

#### 账户配置

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

**智能账户配置 :**

```ts
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.  这两个账户都将在用户对象上可用

**索拉纳账户配置 :**

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

await initialize(config);
```

何时 `solana.createOnLogin` 设置为 `true`SDK会:

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

#### 递延账户的创建

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

```ts
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为丰富的账户对象提供了更多元数据,如创建时间戳和所有者关系:

```ts
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仍然提供简单的地址阵列,但这些被贬损:

```ts
// ⚠️ 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! 终端用户中的以下代码符号:

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

// Send an email to user@example.com with a One Time Password (OTP).
const authResult = await signInWithEmail({
  email: "user@example.com"
});

// Input the OTP sent to user@example.com.
const verifyResult = await verifyEmailOTP({
  flowId: authResult.flowId,
  otp: "123456", // Hardcoded for convenience here.
});

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

### 链接其他认证方法

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

#### 链接电子邮件地址

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

// User must be signed in first
const result = await linkEmail("additional-email@example.com");

// Verify the OTP sent to the email
await verifyEmailOTP({
  flowId: result.flowId,
  otp: "123456"
});
```

#### 链接电话号码

```typescript
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"
});
```

#### 链接一个谷歌账户

```typescript
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
```

#### 链接一个苹果账户

```typescript
import { linkApple } from "@coinbase/cdp-core";

// User must be signed in first
await linkApple();
```

#### 链接任何 OAuth 提供者

```typescript
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 门户网站中配置身份提供者**数字 :
    
    -   导航到 [嵌入式钱包配置](https://portal.cdp.coinbase.com/products/embedded-wallets)
    -   点击自定义认证标签
    -   添加您的 JWKS 端点 URL( 例如 ), `https://your-domain.auth0.com/.well-known/jwks.json`(中文(简体) )
    -   配置您的 JWT 发行者和观众
2.  **提供a `customAuth.getJwt` 回调** 初始化 SDK 时 :
    

```ts
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()` 认证用户:

```ts
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 需要新符号时, 便自动调用

### 查看用户信息

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

```typescript
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 注册

```typescript
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" }
```

##### 短消息录入

```typescript
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 验证

```typescript
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");
```

##### 短消息核查

```typescript
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");
```

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

```typescript
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: "user@example.com" 
});

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 方法登录时,使用帮助器函数检查注册状态,让用户选择自己喜欢的方法:

```typescript
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提供严格的验证:

```typescript
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 是否启用您的工程和视图配置设置 :

```typescript
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 录入提示

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

```typescript
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 账户

```typescript
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 智能账户

```typescript
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来作为智能账户的拥有者.

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

```typescript
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 地址作为所有者使用,而不是创建一个新的地址 :

```typescript
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);
```

#### 创建一个索拉纳账户

```typescript
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交易:

-   基础
-   塞波利亚基地
-   以利亚
-   伊特鲁姆·塞波利亚
-   雪崩
-   坐标
-   乐观主义
-   多边形

```typescript
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` 广播交易.

```typescript
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代理资金.

```typescript
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:

```typescript
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
});
```

#### 列表支出权限

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

```typescript
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
  });
}
```

#### 撤销支出权限

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

```typescript
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);
```

### 开发者代表团

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

#### 创建代表团

```typescript
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);
```

#### 获取主动代表团

```typescript
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);
```

#### 撤销代表团

```typescript
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 }`您可以在索拉纳交易上签名:

```typescript
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
```

### 签署索拉纳信件

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

```typescript
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
```

### 发送索拉纳交易

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

-   索拉纳主网
-   索拉纳·德夫内

```typescript
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
```

#### 发送用户操作

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

```typescript
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的交易归属:**

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

```typescript
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标准](https://eip.tools/eip/8021) 用于交易归属。 它允许应用跟踪使用情况并启用收入分享机制. 后缀自动附加到用户操作的 `callData` 在提交来文之前.

#### 获取用户操作状态

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

```typescript
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消息,散列和打出的数据来生成各种链上应用程序的签名.

```typescript
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 私钥

```typescript
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 私钥

```typescript
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` 输出私钥.

```typescript
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` 软件包 :

```bash
npm install x402-fetch
```

#### 基本用途

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

```typescript
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 行为 :

```typescript
// 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 常规账户 :

```typescript
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` 用索拉纳账户代替.

```typescript
const user = await getCurrentUser();

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

### EIP-1193 供应商

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

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

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

```typescript
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账户的任何库或框架的倒置替换.

```typescript
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 是什么？

这个软件包包含了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 和提交记录判断。

