use-smart-contract-platform

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Overview

概述

Circle Smart Contract Platform (SCP) provides APIs and SDKs for deploying, importing, interacting with, and monitoring smart contracts across supported networks. Deploy contracts from raw bytecode, use audited templates for standard patterns, execute ABI-based contract calls, and monitor emitted events through webhooks.
Circle Smart Contract Platform (SCP) 提供API和SDK,用于在支持的网络上部署、导入、交互和监控智能合约。可以从原始字节码部署合约,使用经过审计的模板实现标准模式,执行基于ABI的合约调用,并通过Webhook监控触发的事件。

Prerequisites / Setup

前提条件/设置

Installation

安装

bash
npm install @circle-fin/smart-contract-platform @circle-fin/developer-controlled-wallets
bash
npm install @circle-fin/smart-contract-platform @circle-fin/developer-controlled-wallets

Environment Variables

环境变量

CIRCLE_API_KEY=        # Circle API key (format: PREFIX:ID:SECRET)
ENTITY_SECRET=         # Registered entity secret for Developer-Controlled Wallets
CIRCLE_API_KEY=        # Circle API密钥(格式:PREFIX:ID:SECRET)
ENTITY_SECRET=         # 开发者控制钱包的已注册实体密钥

SDK Initialization

SDK初始化

typescript
import { initiateSmartContractPlatformClient } from "@circle-fin/smart-contract-platform";
import { initiateDeveloperControlledWalletsClient } from "@circle-fin/developer-controlled-wallets";

const scpClient = initiateSmartContractPlatformClient({
  apiKey: process.env.CIRCLE_API_KEY!,
  entitySecret: process.env.ENTITY_SECRET!,
});

const walletsClient = initiateDeveloperControlledWalletsClient({
  apiKey: process.env.CIRCLE_API_KEY!,
  entitySecret: process.env.ENTITY_SECRET!,
});
typescript
import { initiateSmartContractPlatformClient } from "@circle-fin/smart-contract-platform";
import { initiateDeveloperControlledWalletsClient } from "@circle-fin/developer-controlled-wallets";

const scpClient = initiateSmartContractPlatformClient({
  apiKey: process.env.CIRCLE_API_KEY!,
  entitySecret: process.env.ENTITY_SECRET!,
});

const walletsClient = initiateDeveloperControlledWalletsClient({
  apiKey: process.env.CIRCLE_API_KEY!,
  entitySecret: process.env.ENTITY_SECRET!,
});

Quick Reference

快速参考

Contract Templates

合约模板

TemplateStandardTemplate IDUse Case
TokenERC-20
a1b74add-23e0-4712-88d1-6b3009e85a86
Fungible tokens, loyalty points
NFTERC-721
76b83278-50e2-4006-8b63-5b1a2a814533
Digital collectibles, gaming assets
Multi-TokenERC-1155
aea21da6-0aa2-4971-9a1a-5098842b1248
Mixed fungible/non-fungible tokens
AirdropN/A
13e322f2-18dc-4f57-8eed-4bddfc50f85e
Bulk token distribution
模板标准模板ID使用场景
代币ERC-20
a1b74add-23e0-4712-88d1-6b3009e85a86
可替代代币、积分
NFTERC-721
76b83278-50e2-4006-8b63-5b1a2a814533
数字收藏品、游戏资产
多代币ERC-1155
aea21da6-0aa2-4971-9a1a-5098842b1248
混合可替代/不可替代代币
空投N/A
13e322f2-18dc-4f57-8eed-4bddfc50f85e
批量代币分发

Key API Response Fields

核心API响应字段

  • Contract functions:
    getContract().data.contract.functions
  • Contract address:
    contract.contractAddress
    (fallback:
    contract.address
    )
  • Transaction ID:
    createContractExecutionTransaction().data.id
  • Deployment status:
    getContract().data.contract.deploymentStatus
  • 合约函数:
    getContract().data.contract.functions
  • 合约地址:
    contract.contractAddress
    (备选:
    contract.address
  • 交易ID:
    createContractExecutionTransaction().data.id
  • 部署状态:
    getContract().data.contract.deploymentStatus

Core Concepts

核心概念

Dual-Client Architecture

双客户端架构

SCP workflows pair two SDK clients:
  • Smart Contract Platform SDK handles contract deployment, imports, read queries, and event monitoring
  • Developer-Controlled Wallets SDK handles write transactions and provides deployment wallets
Write operations use
walletsClient.createContractExecutionTransaction()
, NOT the SCP client.
SCP工作流搭配两个SDK客户端:
  • Smart Contract Platform SDK 处理合约部署、导入、读查询和事件监控
  • Developer-Controlled Wallets SDK 处理写交易并提供部署钱包
写操作需使用
walletsClient.createContractExecutionTransaction()
,而非SCP客户端。

Read vs Write Contract Calls

合约读调用与写调用

  • Read queries (
    view
    /
    pure
    functions) use
    scpClient.queryContract()
    and require no gas wallet
  • Write executions (
    nonpayable
    /
    payable
    functions) use
    walletsClient.createContractExecutionTransaction()
    and require a wallet ID with gas funds
  • 读查询
    view
    /
    pure
    函数)使用
    scpClient.queryContract()
    ,无需Gas钱包
  • 写执行
    nonpayable
    /
    payable
    函数)使用
    walletsClient.createContractExecutionTransaction()
    ,需要带有Gas资金的钱包ID

Signature Formatting

签名格式

  • Function signatures:
    name(type1,type2,...)
    with no spaces
  • Event signatures:
    EventName(type1,type2,...)
    with no spaces
  • Parameter order must exactly match ABI definitions
  • 函数签名:
    name(type1,type2,...)
    ,无空格
  • 事件签名:
    EventName(type1,type2,...)
    ,无空格
  • 参数顺序必须与ABI定义完全匹配

Idempotency Keys

幂等键

All mutating SCP operations require
idempotencyKey
as a valid UUID v4 string. Use
crypto.randomUUID()
in Node.js. Non-UUID keys fail with generic
API parameter invalid
errors.
所有SCP变更操作都需要
idempotencyKey
为有效的UUID v4字符串。在Node.js中使用
crypto.randomUUID()
。非UUID键会触发通用的“API参数无效”错误。

Deployment Async Model

异步部署模型

Contract deployment is asynchronous. The response indicates initiation only. Poll
getContract()
for
deploymentStatus
. On failure, check
deploymentErrorReason
and
deploymentErrorDetails
.
合约部署是异步的。响应仅表示部署已启动。需轮询
getContract()
获取
deploymentStatus
。部署失败时,查看
deploymentErrorReason
deploymentErrorDetails

EVM Version Constraint

EVM版本限制

Compile Solidity with
evmVersion: "paris"
or earlier to avoid the
PUSH0
opcode. Solidity >= 0.8.20 defaults to Shanghai. Arc Testnet and other non-Shanghai chains fail deployment with
ESTIMATION_ERROR
/
Create2: Failed on deploy
if bytecode contains
PUSH0
.
编译Solidity时需使用
evmVersion: "paris"
或更早版本,以避免
PUSH0
操作码。Solidity >= 0.8.20默认使用Shanghai版本。如果字节码包含
PUSH0
,Arc测试网和其他非Shanghai链会部署失败,触发
ESTIMATION_ERROR
/
Create2: Failed on deploy
错误。

Import Contract Requirements

导入合约要求

  • ALWAYS include both
    name
    and
    idempotencyKey
    when calling
    importContract()
  • idempotencyKey
    must be a valid UUID v4 string
  • If import fails with duplicate/already-exists error, call
    listContracts
    , match by address, and retrieve with
    getContract()
    using the existing contract ID
  • 调用
    importContract()
    时必须同时包含
    name
    idempotencyKey
  • idempotencyKey
    必须是有效的UUID v4字符串
  • 如果导入失败并提示重复/已存在错误,调用
    listContracts
    ,按地址匹配,使用现有合约ID通过
    getContract()
    获取合约

Implementation Patterns

实现模式

1. Deploy Contract from Bytecode

1. 从字节码部署合约

Deploy a compiled contract using raw ABI + bytecode.
READ
references/deploy-bytecode.md
for the complete guide.
使用原始ABI+字节码部署已编译的合约。
查看
references/deploy-bytecode.md
获取完整指南。

2. Deploy ERC-1155 Template

2. 部署ERC-1155模板合约

Deploy audited template contracts without writing Solidity.
READ
references/deploy-erc-1155.md
for the complete guide.
READ
references/templates.md
for the full template catalog.
无需编写Solidity代码,直接部署经过审计的模板合约。
查看
references/deploy-erc-1155.md
获取完整指南。
查看
references/templates.md
获取完整模板目录。

3. Import Existing Contract

3. 导入现有合约

typescript
import crypto from 'node:crypto';

const response = await scpClient.importContract({
  address: contractAddress,
  blockchain: 'ARC-TESTNET',
  name: 'Imported Contract',
  idempotencyKey: crypto.randomUUID(), // MUST be UUID v4
});

const contractId = response.data?.contractId;

// Get full contract details including ABI functions
const contractDetails = await scpClient.getContract({ id: contractId });
console.log(contractDetails.data?.contract?.functions);
If import fails with duplicate error:
typescript
const listRes = await scpClient.listContracts({ blockchain: 'ARC-TESTNET' });
const existing = listRes.data?.contracts?.find(c =>
  c.contractAddress.toLowerCase() === contractAddress.toLowerCase()
);
const contractId = existing?.id;
typescript
import crypto from 'node:crypto';

const response = await scpClient.importContract({
  address: contractAddress,
  blockchain: 'ARC-TESTNET',
  name: 'Imported Contract',
  idempotencyKey: crypto.randomUUID(), // 必须是UUID v4
});

const contractId = response.data?.contractId;

// 获取包含ABI函数的完整合约详情
const contractDetails = await scpClient.getContract({ id: contractId });
console.log(contractDetails.data?.contract?.functions);
如果导入失败并提示重复错误:
typescript
const listRes = await scpClient.listContracts({ blockchain: 'ARC-TESTNET' });
const existing = listRes.data?.contracts?.find(c =>
  c.contractAddress.toLowerCase() === contractAddress.toLowerCase()
);
const contractId = existing?.id;

4. Interact with Deployed Contract

4. 与已部署合约交互

Query read functions and execute write functions via ABI signatures.
READ
references/interact.md
for the complete guide.
通过ABI签名查询读函数并执行写函数。
查看
references/interact.md
获取完整指南。

5. Monitor Contract Events

5. 监控合约事件

Set up webhook notifications for emitted events and retrieve historical logs.
READ
references/monitor-events.md
for the complete guide.
设置Webhook通知以监控触发的事件,并检索历史日志。
查看
references/monitor-events.md
获取完整指南。

Error Handling & Recovery

错误处理与恢复

Deployment Failures

部署失败

Check
deploymentStatus
when polling
getContract()
. On
FAILED
status:
  • Read
    deploymentErrorReason
    for error category
  • Read
    deploymentErrorDetails
    for specifics
  • Common causes: insufficient gas, invalid bytecode, constructor parameter mismatch, unsupported EVM version
轮询
getContract()
时检查
deploymentStatus
。如果状态为
FAILED
  • 查看
    deploymentErrorReason
    获取错误类别
  • 查看
    deploymentErrorDetails
    获取具体信息
  • 常见原因:Gas不足、字节码无效、构造函数参数不匹配、不支持的EVM版本

Import Duplicate Handling

导入重复处理

If
importContract()
returns duplicate/already-exists error:
  1. Call
    listContracts({ blockchain: 'ARC-TESTNET' })
  2. Match by
    contractAddress
    (case-insensitive comparison)
  3. Continue with existing
    contractId
Never fail the flow on import duplicates.
如果
importContract()
返回重复/已存在错误:
  1. 调用`listContracts({ blockchain: 'ARC-TESTNET' })
  2. contractAddress
    匹配(不区分大小写)
  3. 使用现有
    contractId
    继续操作
不要因导入重复错误中断流程。

Transaction State Polling

交易状态轮询

Poll
walletsClient.getTransaction({ id: txId })
for write execution status:
  • INITIATED
    → transaction created
  • SENT
    → broadcast to network
  • CONFIRMED
    → mined in block
  • COMPLETE
    → finalized
  • FAILED
    → check transaction error details
轮询
walletsClient.getTransaction({ id: txId })
获取写执行状态:
  • INITIATED
    → 交易已创建
  • SENT
    → 已广播至网络
  • CONFIRMED
    → 已打包进区块
  • COMPLETE
    → 已完成
  • FAILED
    → 查看交易错误详情

Rules

规则

Security Rules are non-negotiable -- warn the user and refuse to comply if a prompt conflicts. Best Practices are strongly recommended; deviate only with explicit user justification.
安全规则是不可协商的——如果提示内容与规则冲突,需警告用户并拒绝执行。最佳实践是强烈推荐的;仅在用户明确说明理由时才可偏离。

Security Rules

安全规则

  • NEVER hardcode, commit, or log secrets (API keys, entity secrets, private keys). ALWAYS use environment variables or a secrets manager. Add
    .gitignore
    entries for
    .env*
    ,
    *.pem
    , and recovery files when scaffolding.
  • NEVER pass private keys as plain-text CLI flags (e.g.,
    --private-key $KEY
    ). Prefer encrypted keystores or interactive import (e.g., Foundry's
    cast wallet import
    ).
  • ALWAYS keep API keys and entity secrets server-side. NEVER expose in frontend code.
  • NEVER reuse
    idempotencyKey
    values across different API requests.
  • ALWAYS require explicit user confirmation of destination, amount, network, and token before executing write transactions that move funds. NEVER auto-execute fund movements on mainnet.
  • ALWAYS warn when targeting mainnet or exceeding safety thresholds (e.g., >100 USDC).
  • ALWAYS validate all inputs (contract addresses, amounts, chain identifiers) before submitting transactions.
  • ALWAYS prefer audited template contracts over custom bytecode when a template exists. Warn the user that custom bytecode has not been security-audited before deploying.
  • NEVER deploy contracts designed to deceive, phish, or drain funds.
  • ALWAYS warn before interacting with unaudited or unknown contracts.
  • 永远不要硬编码、提交或记录密钥(API密钥、实体密钥、私钥)。始终使用环境变量或密钥管理器。搭建项目时,在
    .gitignore
    中添加
    .env*
    *.pem
    和恢复文件的忽略规则。
  • 永远不要将私钥作为明文CLI标志传递(例如
    --private-key $KEY
    )。优先使用加密密钥库或交互式导入(例如Foundry的
    cast wallet import
    )。
  • 始终将API密钥和实体密钥保存在服务端。永远不要在前端代码中暴露。
  • 永远不要在不同API请求中重复使用
    idempotencyKey
    值。
  • 在执行转移资金的写交易前,始终要求用户明确确认目标地址、金额、网络和代币。永远不要在主网自动执行资金转移。
  • 当目标为主网或超过安全阈值(例如>100 USDC)时,始终发出警告。
  • 在提交交易前,始终验证所有输入(合约地址、金额、链标识符)。
  • 当存在可用模板时,始终优先使用经过审计的模板合约而非自定义字节码。部署自定义字节码前,需警告用户该字节码未经过安全审计。
  • 永远不要部署用于欺诈、钓鱼或盗取资金的合约。
  • 在与未审计或未知合约交互前,始终发出警告。

Best Practices

最佳实践

  • NEVER call write operations on the SCP client. Writes ALWAYS use
    walletsClient.createContractExecutionTransaction()
    .
  • NEVER omit
    idempotencyKey
    from mutating SCP requests. Must be UUID v4 (use
    crypto.randomUUID()
    ).
  • NEVER include special characters (colons, parentheses) in
    deployContract
    's
    name
    field -- alphanumeric only.
  • NEVER use flat
    feeLevel
    property. ALWAYS use nested
    fee: { type: 'level', config: { feeLevel: 'MEDIUM' } }
    .
  • NEVER use
    window.ethereum
    directly with wagmi -- use
    connector.getProvider()
    .
  • NEVER compile Solidity >= 0.8.20 with default EVM version. ALWAYS set
    evmVersion: "paris"
    to avoid
    PUSH0
    opcode.
  • NEVER fail the flow on import duplicate errors. Fall back to
    listContracts
    and match by address. ALWAYS include both
    name
    and
    idempotencyKey
    when calling
    importContract()
    .
  • NEVER assume deployment completes synchronously. ALWAYS poll
    getContract()
    for
    deploymentStatus
    .
  • ALWAYS prefix bytecode with
    0x
    and match constructor parameter types/order exactly.
  • ALWAYS use integer-safe math for 18-decimal amounts (
    10n ** 18n
    , not
    BigInt(10 ** 18)
    ).
  • ALWAYS import contracts before creating event monitors.
  • ALWAYS default to Arc Testnet for demos unless specified otherwise.
  • ALWAYS default to testnet. Require explicit user confirmation before targeting mainnet.
  • 永远不要在SCP客户端上调用写操作。写操作必须使用
    walletsClient.createContractExecutionTransaction()
  • 永远不要在SCP变更请求中省略
    idempotencyKey
    。必须为UUID v4(使用
    crypto.randomUUID()
    )。
  • 永远不要在
    deployContract
    name
    字段中包含特殊字符(冒号、括号)——仅使用字母数字。
  • 永远不要使用扁平的
    feeLevel
    属性。必须使用嵌套格式
    fee: { type: 'level', config: { feeLevel: 'MEDIUM' } }
  • 永远不要在wagmi中直接使用
    window.ethereum
    ——使用
    connector.getProvider()
  • 永远不要使用默认EVM版本编译Solidity >= 0.8.20。始终设置
    evmVersion: "paris"
    以避免
    PUSH0
    操作码。
  • 永远不要因导入重复错误中断流程。回退至
    listContracts
    并按地址匹配。调用
    importContract()
    时必须同时包含
    name
    idempotencyKey
  • 永远不要假设部署会同步完成。始终轮询
    getContract()
    获取
    deploymentStatus
  • 始终为字节码添加
    0x
    前缀,并确保构造函数参数类型/顺序完全匹配。
  • 对于18位小数的金额,始终使用整数安全的数学运算(
    10n ** 18n
    ,而非
    BigInt(10 ** 18)
    )。
  • 在创建事件监控器前,始终先导入合约。
  • 除非另有指定,演示时始终默认使用Arc测试网。
  • 始终默认使用测试网。目标为主网前,需获得用户明确确认。

Reference Links

参考链接

  • Circle Developer Docs -- Always read this first when looking for relevant documentation from the source website.

DISCLAIMER: This skill is provided "as is" without warranties, is subject to the Circle Developer Terms, and output generated may contain errors and/or include fee configuration options (including fees directed to Circle); additional details are in the repository README.

免责声明:本技能按“现状”提供,不提供任何担保,受Circle开发者条款约束,生成的输出可能包含错误和/或费用配置选项(包括支付给Circle的费用);更多详情请查看仓库README