@circle-fin/onramp-kit

中文文档
1.0.8发布于 2026/11/06TypeScriptESM + CJS近 30 天下载 2.5万

嵌入Arc Onramp部件的官方 Circle SDK——服务器侧会话创建和客户端侧部件安装.

中文使用文档
文档目录21 节
  1. 目录
  2. 概览
  3. 安装
  4. 沙盒对生产
  5. 快开始
  6. 1. 在服务器上显示会话创建路径
  7. 2. 在浏览器中启动部件
  8. 弹出模式
  9. 替代品:自带交通工具
  10. 倾听生命周期事件
  11. 确认购买
  12. 处理会话过期/ 闲置
  13. 总是在卸载时拆卸
  14. 处理错误
  15. 浏览器支持和托管要求
  16. 内容安全政策
  17. 集装箱要求(框架模式)
  18. 弹出模式限制
  19. iOS Safari和第三方存储
  20. 社区与支持
  21. 许可证

@circle-fin/onramp-kit (英语)

嵌入 Arc Onramp 部件的官方圆形 SDK —— 服务器侧 会话创建和客户端部件正在安装.

目录

概览

onramp-kit 被拆分成两个互补的地表 同一个 npm 包 :

表面导入路径它运行的地方目的
服务器包@circle-fin/onramp-kit/server节点交换你的 apiKey 短暂的 sessionToken。 。 。 .
客户包@circle-fin/onramp-kit浏览器使用会话符记号挂载 .
原始协议@circle-fin/onramp-kit/protocol两者共享常数,事件信封,会话形状.
模拟助手@circle-fin/onramp-kit/mocks测试对服务器和客户端包进行模拟.

分裂的存在是因为 apiKey 是一个长寿的证书,必须 永远不能到达浏览器。 服务器包创建一个每个用户 sessionToken 安全地交给客户.

安装

npm install @circle-fin/onramp-kit
# or
yarn add @circle-fin/onramp-kit

沙盒对生产

工具包的目标是默认的生产。 使用沙盒促进地方发展 以及测试,它不会移动真正的钱 并提供测试网的标志。 这个 只接受生产部件 https: 嵌入页面, 因此是一个本地 dev 打开服务器 http://localhost 必须使用沙盒( 也允许 http://localhost:*) (中文(简体) ).

设置开始沙盒生产(违约)
apiKey服务器测试网 API 密钥主网 API 密钥
baseUrl服务器https://api-test.circle.comhttps://api.circle.com
widgetBaseUrl服务器和客户端https://onramp-sandbox.arc.iohttps://onramp.arc.io

将 API 密钥和两个 URL 保存在同一环境中: 使用测试网 键有沙盒,主网键有生产。 服务器和 客户端 widgetBaseUrl 值必须匹配.

// server
const server = createOnrampServerKit({
  apiKey: process.env.ONRAMP_API_KEY!,
  baseUrl: process.env.ONRAMP_BASE_URL, // https://api-test.circle.com
  widgetBaseUrl: process.env.ONRAMP_WIDGET_BASE_URL, // https://onramp-sandbox.arc.io
})

// browser
const onramp = createOnrampKit({
  widgetBaseUrl: import.meta.env.VITE_ONRAMP_WIDGET_BASE_URL, // https://onramp-sandbox.arc.io
})

快开始

建议的流量是两个简短的代码: 您的服务器调用 SDK , 而浏览器中有一个调用 将客户端指向该路线.

1. 在服务器上显示会话创建路径

// app/api/onramp/sessions/route.ts (Next.js App Router)
import {
  createOnrampServerKit,
  createSessionRouteHandler,
} from '@circle-fin/onramp-kit/server'

const server = createOnrampServerKit({
  apiKey: process.env.ONRAMP_API_KEY!,
})

export const POST = createSessionRouteHandler(server)

apiKey 格式 : 精确使用圆形发布的值 操纵台 钥匙看起来像 <ENV>_API_KEY:<keyId>:<keySecret>。工具包发送 它作为无记名的迹象Authorization: Bearer <value>页:1 脱去或重新添加前缀.

createSessionRouteHandler 是一个滴入 Request → Response 处理器 即:

  • 仅接受 POST (回报) 405 否则,
  • 根据共享的会话请求计划验证天体 (单位:千美元)400 在形状不匹配的情况下,
  • 电话 server.createSession(body) 并返回会话为 JSON,
  • 投出地图 KitErrors 到明智的 HTTP 状态代码 (单位:千美元)INPUT - 400个, RATE_LIMIT − 429个, NETWORK • 504, SERVICE编号 :RPC − 502,否则为500,
  • 套装 Cache-Control: no-store 到处都是会议标志 寿命很短,绝不能缓存.

它在任何会讲 Facker API 标准的运行时间都起作用——Next.js App路由器,Hono,Cloudflare工人,Bun,Deno,现代节点. 主机 在快递上 / 快递可以继续呼叫 server.createSession() 直接说.

插入您的自定义/ authz

import { auth } from '@/lib/auth'

export const POST = createSessionRouteHandler(server, {
  authorize: async (request) => {
    const session = await auth(request)
    return session?.user != null
  },
})

返回时 false 401. 丢出一个 KitError - 相应的状况. 返回时 true 或者说 undefined 继续.

2. 在浏览器中启动部件

客户端套件暴露出两个同步挂载助手—— mountIframe (内在)和 openWindow (弹出)——和一个可选的REST取取取器 (单位:千美元)fetchOnrampSession) (中文(简体) ). 他们被故意分开 所以弹出模式 可以在同步用户手势框架(浏览器块)内运行 弹出,否则).

两种模式的手势规则不同. mountIframe 已经 没有 需要用户手势——它只是插入一个 <iframe> 输入 自己拥有的容器,所以在一页后调用页面负载是安全的 await在反应中 useEffect等 (中文(简体) ). openWindow 必须 为: 从用户手势(点击处理框架)中同步调用或 浏览器屏蔽弹出——见 弹出模式 见下文.

import { createOnrampKit, fetchOnrampSession } from '@circle-fin/onramp-kit'

const onramp = createOnrampKit()

async function startOnramp() {
  const session = await fetchOnrampSession({
    url: '/api/onramp/sessions',
    body: {
      appUserId: 'user-123',
      destinationAddress: '0xabc...',
    },
  })

  const widget = onramp.mountIframe({
    session,
    container: document.getElementById('onramp-root')!,
    onInitializationSuccess: () => console.log('ready'),
    onDepositSettled: ({ payload }) => {
      console.log('settled', payload.amount, payload.tokenSymbol)
    },
  })

  return widget
}

定义部件提供的标志/链条

通过可选 assets 请求限制 部件中显示的符号/链对 。 每个领域都是可选的,它们 结合和语义;省略 assets 用于完整支持的目录 :

await fetchOnrampSession({
  url: '/api/onramp/sessions',
  body: {
    appUserId: 'user-123',
    destinationAddress: '0xabc...',
    assets: { chains: ['arc'] }, // Arc only, all tokens
    // assets: { tokens: ['USDC'] },                          // USDC on every chain
    // assets: { pairs: [{ token: 'USDC', chain: 'arc' }] },  // exact pairs
  },
})

chains 接受链式标识或显示标签; tokens 一个符号。 范围界定 仅显示 —— 部件的目录和资格将保留为真相的来源, 因此从浏览器中设置是安全的.

授权您的嵌入域( N)referrerDomain(中文(简体) )

当您将部件嵌入您自己的网站时, 设置 referrerDomain 因此,您的页面被授权作为框架祖先 支付供应商的嵌入式iframe。 当部件运行时关闭它 顶级页面或弹出模式.

referrerDomain 是一个 服务器包上的构建选项,而不是一个 每会话参数——按设计。 它配置了帧祖先 允许列表( 安全边界) , 因此它必须来自您自己信任的 配置并永远不能被客户端设置. 把它放在包里(而不是 比过去 createSession)指客户端提交的会话机构不能 影响它,即使通过滴入 createSessionRouteHandler数字 :

// server entry — configured once from trusted config
const server = createOnrampServerKit({
  apiKey: process.env.ONRAMP_API_KEY!,
  referrerDomain: process.env.ONRAMP_REFERRER_DOMAIN, // e.g. 'portal.arc.io'
})

// the drop-in route stays a safe one-liner — `referrerDomain` is applied
// server-side to every mint, and nothing in the request body can override it
export const POST = createSessionRouteHandler(server)

值规则 :

  • 仅主机名 ——没有计划,端口,路径,通配符.
    • ✅ portal.arc.io
    • ❌ https://portal.arc.io • 妇女 portal.arc.io:443 • 妇女 portal.arc.io/buy • 妇女 *.arc.io
  • 对于一个子域,通过准确的主机,页面从 (单位:千美元)buy.arc.io),而不是最高域.

这是与你网站分开的 社区支助方案:社区支助方案 让您的页面框架 onramp.arc.io· ; referrerDomain 让提供者 鸟巢Iframe接受你的一页作为祖先. 一个正确嵌入的 Iframe 两者都需要.

弹出模式

openWindow 必须援引 同步 从用户手势 (例如直接在点击处理器内)或浏览器会屏蔽 弹出. 返回值对 'opened' 财务报告和审定财务报表 'blocked' 成果 - 'blocked' 是正常流动,不是 非常特别的.

// Hint: create the session beforehand (e.g. when the form is rendered),
// then call openWindow synchronously on click.
const session = await fetchOnrampSession({ url: '/api/onramp/sessions', body })

button.addEventListener('click', () => {
  const result = onramp.openWindow({
    session,
    onDepositSettled: ({ payload }) => …,
  })

  if (result.status === 'blocked') {
    // Branch on `reason` to tailor recovery:
    //  - 'popup_blocked'  → ask the user to retry (another sync click)
    //  - 'in_app_browser' → fall back to mountIframe(), or prompt the
    //                       user to open the page in the system browser
    //  - 'pwa_standalone' → fall back to mountIframe()
    if (result.reason === 'popup_blocked') {
      showPopupRetryDialog(result.errorMessage)
    } else {
      onramp.mountIframe({ session, container })
    }
    return
  }

  result.widget.on('DEPOSIT_NOT_COMPLETED', ({ code }) => …)
})

弹出闭塞信号. 如果顾客之前关闭了弹出 提交押金,工具箱检测它并发射a DEPOSIT_NOT_COMPLETED 有代码的事件 CANCELED_BY_CUSTOMER这样  onDepositNotCompleted 操作员在无额外投票的情况下运行 在你身边.

替代品:自带交通工具

如果您的应用程序已经拥有自己的数据层( tRPC, GraphQL, 服务器) 组件,反应-平滑) fetchOnrampSession 手动 已决出会议 mountIframe 编号 : openWindow 直接说 这个 会话形状与您返回的服务器套件相同.

const session = await trpc.onramp.createSession.mutate({
  appUserId,
  destinationAddress,
})
const widget = onramp.mountIframe({ session, container })

倾听生命周期事件

每一艘发来的信封船 { event, code, payload? }编辑 event 描述主机可见效果 code 缩小 事业。 见 ONRAMP_EVENT_TYPES 财务报告和审定财务报表 ONRAMP_EVENT_CODES 内 @circle-fin/onramp-kit/protocol。 。 。 .

widget.on('INITIALIZATION_ERROR', ({ code, payload }) => {
  if (code === 'INVALID_SESSION_TOKEN') return refreshSession()
  if (code === 'PAGE_NOT_LOADED') return showLoadFailureToast()
})

widget.on('*', (envelope) => analytics.track('onramp', envelope))

由设计与前相兼容. 套装是 没有 验证 事件 { event, code, payload } 对付一个封闭的阴谋 一个部件 添加新事件、代码、支付方法或有效载荷字段的释放 交给您 onAnyEvent 编号 : on('*') 逐字记录员 而不是被丢弃——所以SDK从来不会落后主机应用. 已知的事件仍然会获得自动完成的完整类型回调.

事件只到达启动部件的页面 . 部件 将事件张贴到嵌入它( 框架模式) 或打开它的页面 (弹出模式). 如果您打开部件 URL 作为顶级页面 - for 例如,来自系统浏览器中的本地应用程序(Safari View) Chrome Custom Tabs公司主计长——没有收到任何事件。 为了得到 它们,在您自己的页面上以 mountIframe 或者说 openWindow,然后打开页面.

确认购买

红外线 Kit 不向您的服务器发送 Webhoks, 没有 服务器端命令状态 API. 生命周期事件为浏览器 postMessage 信号:使用它们驱动您的用户界面,而不是作为证明一个 采购完成.

  • DEPOSIT_SUBMITTED 指客户完成了部件流. 这个 不带 transactionHash。 。 。 .
    • 卡,苹果支付,和谷歌支付: amount 即已支付的数额, 而不是交付的象征性金额.
    • 银行转账:当客户关闭银行详细信息时,它就会起火 屏幕,在任何钱移动之前. amount 是它们的数量 他们将永不派遣.
  • DEPOSIT_SETTLED 是最佳和火灾 只为卡,苹果支付, 和谷歌付费购买。 通常会加入链上 transactionHash,但只有在部件在 买下就解决了 一个客户谁先关闭标签 触发它,即使购买完成. 不要治疗 没有 DEPOSIT_SETTLED 作为"没有存款"

当您的应用程序需要可靠记录 购买完成时, 请检查 服务器上的链条 :

  1. 请检查access-date=中的日期值 (帮助) destinationAddress 你准备好了 会议闭幕。 使用 transactionHash 从 DEPOSIT_SETTLED 当你 拥有它.
  2. 从链取出量. 交付的金额是扣除费用后的净额, 因此,它不等于虚伪 amount 在事件有效载荷.
  3. 每次转账一次,按其交易散列键.

银行转账需要额外照顾:

  • 回来的客户可以选择他们开的银行转账账户 之前的会议。 押金就落在那个账户上 钱包,可能不同于会话 destinationAddress。 。 。 .
  • 银行转账账户保持开户,然后转入账户 链上没有部件事件.
  • orderId 是客户的银行转账参考。 一样 所以它不能告诉存款 或账户分开.

不用发送地址识别交货。 送货来自 支付提供者的钱包,因环境和支付而异 方法,不能保证保持不变.

处理会话过期/ 闲置

当一个会话在部件打开时闲置出会话时,主机程序会释放 DEPOSIT_NOT_COMPLETED 有代码 SESSION_TIMEOUT。工具包也浮出水面 这个(和 INVALID_SESSION_TOKEN 输入错误) onSessionExpired 调用后, 不需要手动分拆代码 这是你的"创建新的会话并重新发射"信号.

onramp.mountIframe({
  session,
  container,
  onSessionExpired: async () => {
    // The current session is dead — create a fresh one and re-mount.
    const fresh = await fetchOnrampSession({
      url: '/api/onramp/sessions',
      body,
    })
    onramp.mountIframe({ session: fresh, container })
  },
})

匹配 onDepositNotCompleted 编号 : onInitializationError 回调 仍然开火,所以现有的操作员继续工作.

总是在卸载时拆卸

部件控制器附加一个 message 监听器 window 财务报告和审定财务报表 保持一个超时计时器. 打电话 widget.close() 当你的视野 卸载 因此,这些被释放。 对于 Iframe 模式,工具包也安装了 (单位:千美元) MutationObserver 如果iframe脱离 dOM 没有 close() 你不应该依赖它作为 你的主要清理路径.

// React
useEffect(() => {
  const widget = onramp.mountIframe({ session, container: ref.current! })
  return () => widget.close()
}, [session])

处理错误

装备投出的所有东西都是 KitError (从 @circle-fin/onramp-kit),这样你就可以 instanceof- 检查它和树枝 它的结构化,稳定的字段而不是解析信件字符串 :

外地分行请..
type对失败进行分类—— 'INPUT', (中文(简体) ), 'NETWORK', (中文(简体) ), 'SERVICE', (中文(简体) ), 'RATE_LIMIT', (中文(简体) ), 'RPC', (中文(简体) ), 'UNKNOWN'。 。 。 .
recoverability决定是否重试 - 'RETRYABLE', (中文(简体) ), 'RESUMABLE',或 'FATAL'。 。 。 .
name 编号 : code精确匹配、记录和遥测的稳定标识.
import { KitError, fetchOnrampSession } from '@circle-fin/onramp-kit'

try {
  const session = await fetchOnrampSession({ url, body })
  onramp.mountIframe({ session, container })
} catch (err) {
  if (err instanceof KitError) {
    if (err.recoverability === 'RETRYABLE') return scheduleRetry()
    if (err.type === 'INPUT') return showValidationError(err.message)
  }
  throw err
}

偏爱 type + 键 recoverability 为了控制流动,他们是稳定的, 远期合同。 使用 name 编号 : code 只有精确匹配, 伐木或遥测。 服务器路由处理器 (单位:千美元)createSessionRouteHandler)这些地图相同 types 到 HTTP 状态代码 自动( 见 步骤 1) (中文(简体) ).

浏览器支持和托管要求

横跨出处的自 https://onramp.arc.io (生产)或 https://onramp-sandbox.arc.io (散装箱). 有一些东道方的先决条件.

内容安全政策

如果您的网站发送了 CSP, 它必须允许部件来源用于 你的目标环境。 没有这个指令, Iframe沉默地 无法渲染 —— 没有出错事件, 因为浏览器块 我们代码运行前的负载.

生产:

frame-src https://onramp.arc.io;

沙盒 :

frame-src https://onramp-sandbox.arc.io;

Iframe或弹出式中继部件本身的CSP后, 不是你的页面,所以没有 connect-src 他们需要进入。 装备箱 只从您的页面请求到您的会话路由 .

集装箱要求(框架模式)

呼叫时适用两个东道方先决条件 mountIframe数字 :

  1. 容器必须已经附在文件上 何时 你打电话 mountIframe。工具箱同步附加了框架 并安装 MutationObserver 如果容器自动处理 后分道扬镳. 在反应中,从一个 useEffect (未在 因此,裁判员是人;在香草代码中,等待 DOMContentLoaded 或者自己在呼叫前插入容器.

  2. 容器需要明确,非零高. 框架 于 width: 100%; height: 100%跨原生地框架 无法大小到内容, 所以没有解决的高度 iframe 崩溃到 0px 而用户看不到任何信息 .

    #onramp-root {
      height: 720px;
    } /* or min-height, or a flex child with a sized parent */
    

弹出模式限制

openWindow 是最佳效果并返回 a 'blocked' 结果(从未) 当无法打开可用弹出时:

reason原因建议退后
popup_blocked封锁者,或 await 在电话之前跑掉了从新同步点击重试
in_app_browserInstagram / Facebook / TikTok / LinkedIn WebView等. 腾讯网.mountIframe,或在系统浏览器中打开
pwa_standalone在独立显示模式下安装 PWAmountIframe

附加说明:

  • 在移动浏览器上, window.open 打开一个 选项卡大小的 弹出—— width编号 :height 特性被忽略。 两者的设计.
  • 习惯 target 联 合 国 '_blank' 禁用弹出特性; 通过 a 已命名目标(默认) 'circle-onramp'一个真正的弹出.
  • 弹出故意保持 window.opener (我们省略) noopener编号 :noreferrer这样它就可以 postMessage 结果回来。 这个 信任边界是圆形本身的部件来源.

iOS Safari和第三方存储

iOS Safari的IPP可以限制嵌入式应用程序对自身的访问 存储在 Iframe 中。 如果您看到 KYC/ 会话问题被隔离到 iOS 萨法里,更喜欢 openWindow 模式在平台.

社区与支持

许可证

这个项目根据Apache 2.0许可证获得许可. 联系人 支助 详细情况.


准备好开始接受注意存款了吗?

加入磁盘

由 Circle 创建

版本与发布记录

@circle-fin/onramp-kit 共发布 9 个版本,首次发布于 2026/09/16;过去 12 个月发布了 9 个版本。

版本发布日期距今
1.0.8latest2026/11/063 天前
1.0.72026/10/319 天前
1.0.62026/10/2317 天前
1.0.52026/10/2119 天前
1.0.42026/10/1624 天前
1.0.32026/09/301 个月前

关于 @circle-fin/onramp-kit 的常见问题

@circle-fin/onramp-kit 是什么?

嵌入Arc Onramp部件的官方 Circle SDK——服务器侧会话创建和客户端侧部件安装.

如何安装 @circle-fin/onramp-kit?

在项目目录运行 npm install @circle-fin/onramp-kit,或使用 pnpm add / yarn add / bun add。

@circle-fin/onramp-kit 支持 TypeScript 吗?

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

@circle-fin/onramp-kit 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@circle-fin/onramp-kit 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@circle-fin/onramp-kit 可以商用吗?

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

@circle-fin/onramp-kit 的下载量有多少?

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

@circle-fin/onramp-kit 还在维护吗?

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