这个软件包包含了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 项目信息
- 在此处签名或创建账户 CDP 门户
- 在您的仪表板上,从最上方的下拉位置选择一个项目,并复制项目ID
允许列出本地应用程序
- 导航到 嵌入式钱包配置 在 CDP 门户网站中,单击添加来源以包含本地应用程序
- 输入本地运行的应用程序的出处 - 例如 ,
http://localhost:3000 - 点击 重新添加来源以保存您的更改
反应原生存储
在回放原生时, 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会:
- 自动创建 EOA( 外部拥有账户) 作为所有者
- 创建该 EOA 拥有的智能账户
- 这两个账户都将在用户对象上可用
索拉纳账户配置 :
const config: Config = {
projectId: "your-project-id",
solana: {
createOnLogin: true, // Creates Solana accounts
},
}
await initialize(config);
何时 solana.createOnLogin 设置为 trueSDK会:
- 为新用户创建索拉纳账户
- 索拉纳账户将在
solanaAccounts属性
递延账户的创建
可以省略 createOnLogin 完全防止自动创建账户,而是在需要时手工创建账户:
const config: Config = {
projectId: "your-project-id",
// No ethereum or solana createOnLogin configuration
}
await initialize(config);
何时 createOnLogin 省略, SDK 将:
- 用户登录时不自动创建任何账户
- 需要使用账户创建动作手动创建账户(见下文)
- 完全控制创建时间和类型的账户
多账户支助
用户可以拥有多种类型账户:
- 最多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();
链接任何 OAuth 提供者
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的用户.
先决条件
在使用自定义认证前 :
-
在 CDP 门户网站中配置身份提供者数字 :
- 导航到 嵌入式钱包配置
- 点击自定义认证标签
- 添加您的 JWKS 端点 URL( 例如 ),
https://your-domain.auth0.com/.well-known/jwks.json(中文(简体) ) - 配置您的 JWT 发行者和观众
-
提供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);
}
如何运作
- 您的用户标记为身份提供者( Auth0, Firebase, Cognitto等)
- 你打电话
authenticateWithJWT()内部呼唤你的customAuth.getJwt回调 - SDK 将 JWT 发送到 CDP 的后端, 以您配置的 JWKS 进行验证
- 如果有效, 用户会被认证, 钱包根据您的配置自动创建
- 这个
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 入学流程
入学流程包括两个步骤:
- 开始入学 - 对于TOTP:生成一个秘密和QR代码. 短信:将检察官办公室发送给电话号码
- 提交入学情况 - 校验用户代码以完成入学
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
});
如何运作
- 当您向 X402- 受保护的资源提出请求时, 服务器会用一个
402 Payment Required状态 - 被包裹的获取函数自动 :
- 从服务器的响应中提取付款细节
- 使用用户钱包创建并签名支付交易
- 在重试请求中包括付款证明
- 服务器验证付款并返回请求的资源
智能账户支持
默认, 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,
});