以太s v6 适应器
目录
- 以太s v6 适应器
概览
Ethers v6 适配器是强烈类型的执行 Adapter 接口 与EVM兼容的区块链。在大众之上建造 以太为 v6 库中,它通过一个统一接口提供类型安全的区块链交互,该接口旨在与该区无缝地工作 桥套 用于索拉纳网络和EVM网络之间跨链的USDC转移,以及用于额外稳定币业务的任何未来工具包。 任何使用App Kits架构建造的Kit和/或任何插入这些工具包的供应商都可以使用.
为什么以太s v6适应器?
- 带上你自己的设定: 使用您现有的以太
JsonRpcProvider财务报告和审定财务报表Wallet实例 - EVM 兼容: 与Ethereum, Base, Arbitrium 和所有 EVM 链条一起工作
- QQ 类型安全: 以 TypeScript 严格模式用于完整类型安全
- 简单 API: 复杂区块链操作上的清洁抽象
- 交易生命周期 - 完成编制/估计/执行工作流程
- * 跨链准备就绪 - EVM链与索拉纳之间无缝接通的USDC
何时使用此适配器
对于 Kit 用户
如果使用Bridge Kit或其他App Kit进行跨链操作,只需即时处理出一个适配器并传递给工具包. 同一个适配器在所有支持的链条上工作.
// Single adapter instance for multi-chain operations
// Note: Private keys can be provided with or without '0x' prefix
const adapter = createEthersAdapterFromPrivateKey({
privateKey: process.env.PRIVATE_KEY as `0x${string}`, // Both '0x...' and '...' work
})
// Both formats are automatically normalized:
const adapter1 = createEthersAdapterFromPrivateKey({
privateKey: '0x1234...', // With prefix ✅
})
const adapter2 = createEthersAdapterFromPrivateKey({
privateKey: '1234...', // Without prefix ✅ (automatically normalized)
})
对于 Kit 提供者开发者
若建供养者(如道俗 BridgingProvider 执行),您将使用适配器的抽象方法与不同的链条相互作用. 行动Context模式使多链操作无缝.
安装
npm install @circle-fin/adapter-ethers-v6 ethers
# or
yarn add @circle-fin/adapter-ethers-v6 ethers
同伴依赖关系
这个适配器需要 ethers (v6)作为同伴依赖. 与适配器一起安装 :
npm install @circle-fin/adapter-ethers-v6 ethers
# or
yarn add @circle-fin/adapter-ethers-v6 ethers
已支持的版本 : ^6.11.0 (6.11.x至6.x.x,不包括7.x.x.x.)
解决版本冲突
如果遇到同伴依赖警告:
- 检查你的
ethers版本 :npm ls ethers - 保证醚 v6 介于 6.1.10. 至 7.0.0 (排他性)之间
- 使用
npm install ethers@^6.11.0以安装兼容的版本 - 说明: 这个适配器是 没有 兼容醚 v5 或 v7
快速启动
Zero-Config 设置( 建议)
最简单的方式是从懒惰的初始化开始. 默认配置自动处理适配器设置.
import { createEthersAdapterFromPrivateKey } from '@circle-fin/adapter-ethers-v6'
// Minimal configuration with lazy initialization
// Note: Private keys work with or without '0x' prefix
const adapter = createEthersAdapterFromPrivateKey({
privateKey: process.env.PRIVATE_KEY as `0x${string}`, // Both '0x...' and '...' work
// Defaults applied:
// - addressContext: 'user-controlled'
// - supportedChains: all EVM chains (~34 networks)
// - Lazy initialization: wallet connects to chain on first operation
})
// Chain specified per operation via OperationContext
const prepared = await adapter.prepare(
{
address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC on Ethereum
abi: usdcAbi,
functionName: 'transfer',
args: ['0xrecipient', '1000000'],
},
{ chain: 'Ethereum' }, // Chain specified in context
)
const txHash = await prepared.execute()
生产设置
对于生产用途,提供定制RPC终点,以提高可靠性和性能:
import { createEthersAdapterFromPrivateKey } from '@circle-fin/adapter-ethers-v6'
import { JsonRpcProvider } from 'ethers'
import { Ethereum, Base, Polygon } from '@circle-fin/bridge-kit/chains'
// Production-ready with custom RPC endpoints and lazy initialization
const adapter = createEthersAdapterFromPrivateKey({
privateKey: process.env.PRIVATE_KEY as `0x${string}`,
// Custom RPC provider with explicit chain mapping
getProvider: ({ chain }) => {
// Map chain names to RPC endpoints
// Customize this mapping based on your RPC provider
const rpcEndpoints: Record<string, string> = {
Ethereum: `https://eth-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_KEY}`,
Base: `https://base-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_KEY}`,
Polygon: `https://polygon-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_KEY}`,
}
const endpoint = rpcEndpoints[chain.name]
if (!endpoint) {
throw new Error(`RPC endpoint not configured for chain: ${chain.name}`)
}
return new JsonRpcProvider(endpoint, chain.chainId)
},
// Optionally restrict to specific chains
capabilities: {
supportedChains: [Ethereum, Base, Polygon],
},
})
生产说明: 默认工厂方法使用公共RPC端点,这些端点可能具有速率限制. 用于生产,使用Alchemy,Infura,或QuickNode等专用供应商.
浏览器钱包设置
对于带有MetaMask或钱包连接的浏览器环境:
import { createEthersAdapterFromProvider } from '@circle-fin/adapter-ethers-v6'
// Minimal browser wallet configuration
const adapter = await createEthersAdapterFromProvider({
provider: window.ethereum,
// Default capabilities applied automatically
})
// User will be prompted to connect wallet
// Address is automatically resolved from connected wallet
const prepared = await adapter.prepare(
{
address: '0xcontract',
abi: contractAbi,
functionName: 'approve',
args: ['0xspender', '1000000'],
},
{ chain: 'Polygon' },
)
下一个Generation API(/next(中文(简体) )
预览 - 电话
/next入口是即将到来的默认适配器架构. 它与目前所支持的桥梁流量的切入点相当,并且与所有现有工具包(Bridge Kit等)完全兼容。 在下一个主要发布,/next将会成为默认的导入,当前切入点将会被退出。 见 目前的限制/next在通过之前.
开始 /next
通过改变单一导入路径来切换到新架构. 其他一切不变:
import { createEthersAdapterFromPrivateKey } from '@circle-fin/adapter-ethers-v6/next'
const adapter = createEthersAdapterFromPrivateKey({
privateKey: process.env.PRIVATE_KEY as string,
})
// Pass it to the Bridge Kit exactly as before — no changes needed downstream
提示 : 这个
/next工厂接受privateKey作为一个平地string- 那个0x前缀为可选并自动正常化。 不需要模板字面类型的断言 .
浏览器钱包工作相同 :
import { createEthersAdapterFromProvider } from '@circle-fin/adapter-ethers-v6/next'
import { Ethereum, Base, Polygon } from '@circle-fin/bridge-kit/chains'
const adapter = createEthersAdapterFromProvider({
provider: window.ethereum,
capabilities: {
addressContext: 'user-controlled',
supportedChains: [Ethereum, Base, Polygon],
},
})
createEthersAdapterFromProvider 也接受一种醚 Provider
直接 – 在您已经使用过的服务器侧工作流程中有用
维持a JsonRpcProvider 并且希望适配器能重用它
将输入包入每个链 BrowserProvider数字 :
import { createEthersAdapterFromProvider } from '@circle-fin/adapter-ethers-v6/next'
import { JsonRpcProvider } from 'ethers'
const provider = new JsonRpcProvider(process.env.RPC_URL)
const adapter = createEthersAdapterFromProvider({ provider })
工厂在运行时检测输入形状: EIP-1193 提供商
(单位:千美元){ request }每条链被包裹,而乙醚 Provider
(单位:千美元){ getNetwork }直接使用并返回自己的 getSigner()
结果.
为什么 /next? 吗?
| 当前切入点 | /next 切入点 | |
|---|---|---|
| 套装大小 | 包含全部适配器 | 私人进口 解锁树摇; 默认工厂仍然拉 compat shim — 看 捆绑大小 |
| 准备结果 | estimate() 财务报告和审定财务报表 execute() | estimate(), (中文(简体) ), simulate(),以及 execute(overrides?) |
| 收费模式 | { gas, gasPrice, fee } | { fee, units, unitPrice } ——所有生态系统保持一致 |
| 观察性 | 不详 | 内建伐木、计量和事件仪器 |
| 重试恢复能力( R) | 不详 | 可配置重试, 以指数倒置表示短暂的失败 |
| 调制解析 | 硬码地址 | 累加式符号登记——用符号解决任何符号跨链 |
| 交易调试 | 固定气体默认值 | 可配置的费用缓冲、优先收费下限和确认超时 |
套装大小注释
这个 /next 入口的清洁建筑设计
按原产地计算可动摇树:进口 createPrepare
无 createBatchExecute 只能运送准备路径。 单位
当前预览释放默认 createAdapter 工厂仍然
牵扯在遗产 compat shim (withLegacyCompat →
@core/adapter-compat消费者可以通过
生成的适配器与现有工具包和提供者不作改动.
那闪电是默认的 /next 捆绑量度~11%
大于我们内部基准中遗留的切入点.
如果捆绑大小对您至关重要,则直接通过
assembleAdapter 从 @core/adapter-base 跳过
withLegacyCompat。未来微小的释放将分裂共通
在单独的入口后面,所以默认的工厂
仅新建 API.
目前的限制 /next
这个 /next 以太适配器与当前切入点对等
支持的桥流,但一些能力仍在
进展。 在项目问题跟踪器中跟踪这些结果,以采取后续行动
释放:
- 没有原子批量批准+活化. EIP-5792 信息技术
wallet_sendCalls只能用Viem 进行批量/next适配器; 以太 适配器(以及 CCTP)/next桥由它驱动时的桥流)提交 核准和烧为两个单独的交易. - 圆形钱包适配器尚未迁移到
/next。 。 。 . 仅 eVM (viem/ethers) 和索拉纳适配器显示/next入场点; 圆形钱包留在目前的出入口上. - 中止语义只停止本地等待 . 通过中止(或
可中止)
signal取消数waitForTransaction并预防 未经同意execute从广播,但 一经交易 播放, 中止不会在链上取消 交易 并且应该通过散列进行调和.
已编制交易:估计、模拟、执行
当您准备通过 /next 适配器,你用三种生命周期方法返回更丰富的对象:
const prepared = await adapter.prepare(
{
address: '0xContractAddress',
abi: contractAbi,
functionName: 'transfer',
args: ['0xRecipient', 1_000_000n],
},
{ chain: 'Base' },
)
// 1. Estimate gas and fees before committing
const { fee, units, unitPrice } = await prepared.estimate()
// 2. Simulate the transaction to catch reverts without spending gas
const simulation = await prepared.simulate()
// 3. Execute when ready (with optional gas overrides)
const result = await prepared.execute()
// `result` is a `{ txId, wait }` envelope:
// - `txId` is the transaction hash on EVM (the field is named `txId`
// rather than `hash` so the same shape works across ecosystems).
// - `wait()` resolves once the transaction is confirmed on-chain.
console.log('submitted tx:', result.txId)
const confirmation = await result.wait()
console.log('confirmed in block:', confirmation.blockNumber)
这个 simulate() 步骤是新建的 /next ——它根据当前链状状态对交易进行干燥,表面在耗用气体前还原原因.
日志
传出 a runtime 选项以获取每个适配器操作的结构化日志,包括 RPC 调用、重试和出错。 最快的方法是使用内置 createRuntime 帮助者 :
import {
createEthersAdapterFromPrivateKey,
createRuntime,
} from '@circle-fin/adapter-ethers-v6/next'
const adapter = createEthersAdapterFromPrivateKey({
privateKey: process.env.PRIVATE_KEY as string,
runtime: createRuntime(), // Logs to stdout via pino at 'info' level
})
要与自己的日志集成, 请通过执行对象 debug, (中文(简体) ), info, (中文(简体) ), warn, (中文(简体) ), error,以及 child 改为 createRuntime。日志接口使用 (message, fields) 参数顺序——皮诺等库使用 (fields, message),所以需要一个薄薄的包装:
import {
createEthersAdapterFromPrivateKey,
createRuntime,
} from '@circle-fin/adapter-ethers-v6/next'
import pino from 'pino'
function wrapPino(p: pino.Logger) {
return {
debug: (msg: string, fields?: Record<string, unknown>) =>
p.debug(fields, msg),
info: (msg: string, fields?: Record<string, unknown>) =>
p.info(fields, msg),
warn: (msg: string, fields?: Record<string, unknown>) =>
p.warn(fields, msg),
error: (msg: string, fields?: Record<string, unknown>) =>
p.error(fields, msg),
child: (tags: Record<string, unknown>) => wrapPino(p.child(tags)),
}
}
const adapter = createEthersAdapterFromPrivateKey({
privateKey: process.env.PRIVATE_KEY as string,
runtime: createRuntime({ logger: wrapPino(pino({ level: 'debug' })) }),
})
计量
这个 runtime 选项还接受 metrics 用于计数器、直方图和计时器的执行。 插入普罗米修斯,StatsD, Datadog, OpenTeleometry, 或任何其他后端 :
import {
createEthersAdapterFromPrivateKey,
createRuntime,
} from '@circle-fin/adapter-ethers-v6/next'
const adapter = createEthersAdapterFromPrivateKey({
privateKey: process.env.PRIVATE_KEY as string,
runtime: createRuntime({
metrics: {
counter: (name) => ({
inc: (labels, value) => {
/* emit counter */
},
}),
histogram: (name) => ({
observe: (labels, value) => {
/* emit histogram */
},
}),
timer: (name) => ({
start: (labels) => {
const t0 = Date.now()
return () => {
/* observe Date.now() - t0 */
}
},
}),
child: (labels) => {
/* return scoped Metrics with base labels merged */
},
},
}),
})
否时 metrics 平面电话是无声的 无声的 零起落.
托肯书记官处
默认情况下,适配器知道USDC(和其他内置符)在每个支持链上的情况. 这个 tokens 选项允许您注册额外的符号,以便它们可以通过符号而不是原始地址来引用.
import {
createEthersAdapterFromPrivateKey,
createTokenRegistry,
} from '@circle-fin/adapter-ethers-v6/next'
const tokens = createTokenRegistry({
tokens: [
{
symbol: 'WETH',
decimals: 18,
locators: {
Ethereum: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
Base: '0x4200000000000000000000000000000000000006',
},
},
],
})
const adapter = createEthersAdapterFromPrivateKey({
privateKey: process.env.PRIVATE_KEY as string,
tokens,
})
登记册自动解决每个链条的正确合同地址和小数,因此下游代码可以指: 'WETH' 而不是每个网络的硬编码地址.
交易调制
这个 config 选项允许您调制气价、 重试行为和确认超时 :
import { createEthersAdapterFromPrivateKey } from '@circle-fin/adapter-ethers-v6/next'
const adapter = createEthersAdapterFromPrivateKey({
privateKey: process.env.PRIVATE_KEY as string,
config: {
transaction: {
feePriceBufferBps: 2000n, // 20% buffer on gas pricing (default)
minPriorityFeeWei: 1_500_000_000n, // 1.5 gwei priority-fee floor
confirmationTimeoutMs: 120_000, // 2 minute confirmation timeout
},
retry: {
maxAttempts: 3,
baseDelayMs: 1000,
},
},
})
| 设置 | 它控制着什么 | 默认 |
|---|---|---|
feePriceBufferBps | 减少天然气定价,防止估算和纳入之间的价格波动(基准点;10 000=100%) | 2000n (20%) |
minPriorityFeeWei | 下限 maxPriorityFeePerGas ——防止近零小费被验证者静悄悄地投出 | 1_500_000_000n (1.5克维) |
confirmationTimeoutMs | 多长时间 waitForTransaction 等待时间结束 | 客户违约 |
retry.maxAttempts | 最大尝试次数( 不包括初始尝试) | 3 |
retry.baseDelayMs | 以毫秒为单位的重试之间的基数延迟( 每次重试时通过指数倒置) | 200 |
设定 retry: false 完全禁用自动重试.
遥测密钥编辑出错( C)
KitError.cause.trace 是SDK用于遥测管道的诊断表面. 它带有有用的死后背景—— 修饰的 rawError 形状, 提供者 code,则a shortMessage 字段。 这些字段的字符串 能够 包括配置的 RPC URL 和任何嵌入的 API 密钥, 因为 ethers v6's makeError() 格式 info 键直接输入信件串本身,例如:
missing response (requestUrl="https://mainnet.infura.io/v3/MY_KEY", code=SERVER_ERROR, ...)
同样的图案在Viem的表面 HttpRequestError.shortMessageSDK分两层处理:
- 对象图条( 总是在) - 那个
request, (中文(简体) ),info来源XMLHttpRequest,以及transport.url属性从未嵌入cause.trace. 这是从第一轮重排开始的合同. - 信件内容擦除( 对 ~ 12 已知 RPC 提供者默认操作; 操作员可扩展) - SDK飞船
defaultMessageRedactor在模块加载时活动,将API-key片段从信件字符串醚/viem格式的内部清除出,用于最常用的没有操作员配置的公用RPC供应商. URL 分类通过平台实现URL解析器加一个主机后缀列表( p)DEFAULT_RPC_HOST_SUFFIXES因此,添加一个新的提供者是一行变更,不需要正则审计.
默认会从盒子里抓出什么
| 提供者 | 主机后缀 |
|---|---|
| 炼金术 | .g.alchemy.com |
| 因福拉语Name | .infura.io |
| 快速节点 | .quiknode.pro |
| 安克尔 | .ankr.com |
| 链层 | .p2pify.com |
| 温柔 | .gateway.tenderly.co |
| 块化PI | .blockpi.network |
| 获取锁定 | .getblock.io |
| 莫拉利斯语Name | .moralis-nodes.com |
| 赫利乌斯(索拉纳) | .helius-rpc.com, (中文(简体) ), .helius.xyz |
| 特里通(索拉纳语) | .rpcpool.com |
| 一般查询字符串 | ?api-key=…, (中文(简体) ), ?apikey=…, (中文(简体) ), ?token=…, (中文(简体) ), ?secret=…, (中文(简体) ), ?key=… |
| 一般认证信头 | Bearer <token> |
任何 URL 内容 host.endsWith(suffix) 匹配表格的批发 [REDACTED]. 分类由同一人进行 URL 解析平台用途 fetch(),因此它不能不慎匹配调用数据,合同地址,交易散列,或者返回原因(其中没有一个解析为URL).
防御深度,不是保证
3件事情仍然需要你注意, 即使默认:
-
自定义或自托管的 RPC URL 不被默认覆盖. 扩展主机后缀列表
composeRedactor数字 :import { composeRedactor, setMessageRedactor, DEFAULT_RPC_HOST_SUFFIXES, } from '@core/errors' setMessageRedactor( composeRedactor({ hostSuffixes: [...DEFAULT_RPC_HOST_SUFFIXES, '.rpc.my-corp.example'], }), ) -
错误消息仍然不可信输出 . 不要写到持久存储器(S3,日志文件,出票系统,支持笔录)上,没有你自己的日志寄出层洗涤. SDK保护了JSON.string的遥测管
cause.trace;它不保护临时console.error(err)调用您的应用程序代码. -
默认可以作假-否定. 新的提供者, URL 格式的更改, 或自定义传输的奇数错误形状可能会滑过. 将每个错误信息视为可能包含一个你无法识别的秘密,并在您的日志发送层进行针擦除(Sentry's)
denyUrls编号 :beforeSend数据犬redact-paths你自己的前卫.
其他逃生舱
| 目标 | 打电话 |
|---|---|
| 在自定义策略后恢复默认值 | resetMessageRedactor() |
读取活动策略( 例如 ) . /healthz(中文(简体) ) | getMessageRedactor() |
| 完全禁用编辑( 本地 dev / 原始提供者测试) | setMessageRedactor(undefined) |
| 长度保留编辑( 函数表) | setMessageRedactor((msg) => msg.replace(/[A-Fa-f0-9]{32,64}/g, (m) => '*'.repeat(m.length))) |
设置器 替换 积极政策——使用 composeRedactor({ hostSuffixes, patterns }) (或打电话) defaultMessageRedactor(msg) 如果想要扩展而不是替换,则从函数形式重排符中选择)。 见 setMessageRedactor这是JSDoc的合同.
为何默认
跨越现代 SDKs 的主导模式( AWS SDK v3 中间软件, Stale 的请求日志器, Sentry's Default Integrations, OpenTeleometry 的 URL/ query-param 洗涤器) 是默认情况下为高自信模式进行秘密洗涤并让操作员延伸或禁用. 与此相反的姿态——“错误可能包含秘密,自己擦除这些秘密”——在历史上是一个经常导致证书漏入整个JS生态系统的日志汇总器的原因(特别是轴向器,它把全部请求的URL倒入) error.config (默认情况下). SDK有意采用保守-默认姿态.
迁移路径
这个 /next 入站点设计为零平移:
- 现在 - 从
@circle-fin/adapter-ethers-v6/next. 返回的适配器与所有现有的工具包和提供者完全兼容——他们方面不需要改动. - 下一个主要发布 - 电话
/next架构成为默认条目(@circle-fin/adapter-ethers-v6) (中文(简体) ). 当前基于类的适配器将被删除.
我需要改变什么? 如果您仅使用工厂功能( Q)createEthersAdapterFromPrivateKey, (中文(简体) ), createEthersAdapterFromProvider),并将适配器传递给一个工具包,没有超出导入路径的. 适配器满足了工具包所期望的相同接口.
操作 Context 模式
为什么是Context行动?
Context行动模式是多链操作的现代方法. 您不锁定单个链的适配器,而是指定每个操作的链. 这样就能够形成强大的模式,如使用单一适配器进行跨链接通.
福利:
- ✅ 一个适配器,许多链条 - 无需为每个网络创建单独的适配器
- ✅ 明确比较好 - 链条在代码里总是清晰的
- ✅ 类型安全 - 完整类型脚本支持和编译时间检查
- ✅ 消除模糊 - 不混淆使用哪个链条
基本用途
每个操作接受一个 OperationContext 指定链的参数:
import { createEthersAdapterFromPrivateKey } from '@circle-fin/adapter-ethers-v6'
// Create adapter without specifying a chain - true lazy initialization
const adapter = createEthersAdapterFromPrivateKey({
privateKey: process.env.PRIVATE_KEY as `0x${string}`,
})
// Chain specified explicitly in every operation
const prepared = await adapter.prepare(
{
address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
abi: usdcAbi,
functionName: 'transfer',
args: ['0xrecipient', '1000000'],
},
{ chain: 'Ethereum' },
)
const gas = await prepared.estimate()
const txHash = await prepared.execute()
多频道业务
单个适配器用于跨多个链条的操作:
// Create adapter once for use across multiple chains
const adapter = createEthersAdapterFromPrivateKey({
privateKey: process.env.PRIVATE_KEY as `0x${string}`,
})
// Transfer USDC on Ethereum
const ethPrepared = await adapter.prepare(
{
address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC on Ethereum
abi: usdcAbi,
functionName: 'transfer',
args: ['0xrecipient', '1000000'],
},
{ chain: 'Ethereum' },
)
// Transfer USDC on Base using the same adapter
const basePrepared = await adapter.prepare(
{
address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC on Base
abi: usdcAbi,
functionName: 'transfer',
args: ['0xrecipient', '1000000'],
},
{ chain: 'Base' },
)
// Execute both transfers
await ethPrepared.execute()
await basePrepared.execute()
地址背景指南
适配器支持两个地址控制模式. 选一个适合你的用法.
用户控制( 建议)
最佳服务: 私钥钱包、浏览器钱包(MetaMask)、硬件钱包
如何运作: 地址由连接的签名人/钱包自动解决。 您不需要在“ Context” 行动中指定它 .
何时使用 :
- QQ 构建用户连接钱包的 dApp
- 使用私人密钥进行后端自动化
- QQ 单一钱包签名所有交易
- QQ 具有一个身份的服务器侧脚本
// User-controlled adapter (default for factory functions)
const adapter = createEthersAdapterFromPrivateKey({
privateKey: process.env.PRIVATE_KEY as `0x${string}`,
// addressContext: 'user-controlled' is the default
})
// Address automatically resolved from private key/wallet
const prepared = await adapter.prepare(
{
address: '0xcontract',
abi: contractAbi,
functionName: 'approve',
args: ['0xspender', '1000000'],
},
{ chain: 'Polygon' }, // No address needed in context for user-controlled
)
开发者控制( 高级)
最佳服务: 保管解决方案、多实体系统、企业应用程序
如何运作: 每项行动必须在行动内容中明确提供地址.
何时使用 :
- QQ 构建管理多个客户端钱包的监护解决方案
- 企业系统,不同用户有不同的签名密钥
- 多西格或授权签字基础设施
- 每个交易地址不同的系统
import { EthersAdapter } from '@circle-fin/adapter-ethers-v6'
import { Ethereum, Base } from '@circle-fin/bridge-kit/chains'
// Developer-controlled adapter (manual constructor)
const adapter = new EthersAdapter(
{
getProvider: ({ chain }) => new JsonRpcProvider('https://...'),
signer: wallet,
},
{
addressContext: 'developer-controlled', // ← Explicit address required
supportedChains: [Ethereum, Base],
},
)
// Address must be provided in context for developer-controlled adapters
const prepared = await adapter.prepare(
{
address: '0xcontract',
abi: contractAbi,
functionName: 'approve',
args: ['0xspender', '1000000'],
},
{
chain: 'Ethereum',
address: '0x1234...', // Required for developer-controlled
},
)
用法实例
合同互动
转移 USDC 使用同一适配器的跨不同链条:
import { createEthersAdapterFromPrivateKey } from '@circle-fin/adapter-ethers-v6'
// Create adapter with lazy initialization
const adapter = createEthersAdapterFromPrivateKey({
privateKey: process.env.PRIVATE_KEY as `0x${string}`,
})
const usdcAbi = ['function transfer(address to, uint256 amount) returns (bool)']
// Transfer on Ethereum - chain specified in operation
const ethPrepared = await adapter.prepare(
{
address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC on Ethereum
abi: usdcAbi,
functionName: 'transfer',
args: ['0xrecipient', '1000000'], // 1 USDC (6 decimals)
},
{ chain: 'Ethereum' },
)
// Estimate and execute
const gas = await ethPrepared.estimate()
console.log('Estimated gas:', gas.gas)
const txHash = await ethPrepared.execute()
console.log('Transaction hash:', txHash)
EIP-712 签署
签字许可批准 用于批准无气证:
import { createEthersAdapterFromPrivateKey } from '@circle-fin/adapter-ethers-v6'
const adapter = createEthersAdapterFromPrivateKey({
privateKey: process.env.PRIVATE_KEY as `0x${string}`,
})
// Sign ERC-2612 permit (gasless USDC approval)
const signature = await adapter.signTypedData(
{
domain: {
name: 'USD Coin',
version: '2',
chainId: 1,
verifyingContract: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
},
types: {
Permit: [
{ name: 'owner', type: 'address' },
{ name: 'spender', type: 'address' },
{ name: 'value', type: 'uint256' },
{ name: 'nonce', type: 'uint256' },
{ name: 'deadline', type: 'uint256' },
],
},
primaryType: 'Permit',
message: {
owner: '0xowner',
spender: '0xspender',
value: '1000000',
nonce: '0',
deadline: '1735689600',
},
},
{ chain: 'Ethereum' }, // Chain must be specified
)
console.log('Permit signature:', signature)
// Use signature for gasless approval
跨越海峡
桥梁 USDC 使用带有 Context 操作的桥套:
import { createEthersAdapterFromPrivateKey } from '@circle-fin/adapter-ethers-v6'
import { BridgeKit } from '@circle-fin/bridge-kit'
// Create adapter for multi-chain operations
const adapter = createEthersAdapterFromPrivateKey({
privateKey: process.env.PRIVATE_KEY as `0x${string}`,
})
const kit = new BridgeKit()
// Bridge from Ethereum to Base using the same adapter
const result = await kit.bridge({
from: { adapter, chain: 'Ethereum' },
to: { adapter, chain: 'Base' },
amount: '100.50',
token: 'USDC',
})
console.log('Bridge transaction:', result.transactionHash)
API 参考
工厂功能
createEthersAdapterFromPrivateKey(params)
从私钥创建适配器供服务器侧使用.
参数:
privateKey- 32字节十六进制字符串(有无)0x前缀 - 自动正常化)getProvider?- 可选自定义提供者功能capabilities?- 可选部分能力(默认:用户控制+所有EVM链)
回返情况: EthersAdapter 懒惰的初始化实例
说明: 创建时不需要链条 。 适配器在第一次操作时会以懒惰的方式连接链.
const adapter = createEthersAdapterFromPrivateKey({
privateKey: '0x...',
})
createEthersAdapterFromProvider(params)
从浏览器钱包提供者(MetaMask, WaletConnect等)创建适配器.
参数:
provider- EIP-1193兼容供应商getProvider?- 可选自定义提供者功能capabilities?- 可选部分能力(默认:用户控制+所有EVM链)
回返情况: Promise<EthersAdapter> 实例
const adapter = await createEthersAdapterFromProvider({
provider: window.ethereum,
})
核心方法
prepare(params, ctx)
拟订合同职能,要求估算和执行.
参数:
params- 合同呼叫参数(地址、ABI、函数) 名称, 参数)ctx- 说吧 需求 有链式规格的操作Context
回返情况: Promise<PreparedChainRequest> 与 estimate() 财务报告和审定财务报表 execute() 方法
const prepared = await adapter.prepare(
{
address: '0xcontract',
abi: contractAbi,
functionName: 'transfer',
args: ['0xto', '1000000'],
},
{ chain: 'Ethereum' }, // Required
)
signTypedData(typedData, ctx)
签出EIP-712打入的许可证,元交易等数据.
参数:
typedData- EIP-712结构数据ctx- 说吧 需求 有链式规格的操作Context
回返情况: Promise<string> - 签名为正弦
const signature = await adapter.signTypedData(permitData, {
chain: 'Ethereum',
})
waitForTransaction(txHash, config?)
等待交易确认.
参数:
txHash- 交易散列等待config?- 备选等待配置(确认、超时)
回返情况: Promise<TransactionReceipt>
const receipt = await adapter.waitForTransaction('0x...')
getAddress(chain)
获取连接的钱包地址 。 链条参数由操作Context分辨率自动提供.
回返情况: Promise<string> - 钱包地址
调试操作
使用动作系统构建的符号操作 :
// Get USDC balance
const balance = await adapter.actions.usdc.balanceOf({
address: '0xwallet',
chain: 'Ethereum',
})
// Get token allowance
const allowance = await adapter.actions.token.allowance({
tokenAddress: '0xtoken',
owner: '0xowner',
spender: '0xspender',
chain: 'Base',
})
支持的链路( R)
Ethers v6适配器解决了Circle的CCTP v2协议所支持的任何EVM相容链条——它在运行时验证了链条类型,而不是硬编码链条列表,因此随着链条被添加而自动保持同步. 见 主读取器 用于完整,最新的支持主网和测试网链列表.
发展
这个包是App Kits monorepo的一部分.
# Build
nx build @circle-fin/adapter-ethers-v6
# Test
nx test @circle-fin/adapter-ethers-v6
许可证
这个项目根据Apache 2.0许可证获得许可. 联系人 支助 详细情况.