LeapFi 早期预览:一个非托管 RGB++ 资产管理 DApp 的开发笔记
各位开发者好,我最近做了一个 RGB++ 资产管理工具:LeapFi。
预览地址:https://leapfi-preview.netlify.app/
LeapFi 想解决的问题很直接:让用户可以在一个非托管应用里查看和管理自己的 RGB++ 资产,包括 UDT 和 Spore,并完成常见操作:
-
Leap to BTC -
Transfer on BTC -
Leap to CKB -
BTC / CKB 两侧资产查看
-
长交易流程的状态追踪与恢复
这还不是一个正式版发布,更像是一次早期预览。我想借这个帖子分享一下开发过程中的一些心得,也想听听社区对 RGB++ 应用开发体验的看法。
这里先说明一下我对 “DApp” 这个词的使用边界:LeapFi 并不是一个完全去中心化的应用,它仍然依赖 btc-assets-api 这样的中心化基础设施来做资产查询、BTC 信息、SPV 和交易状态推进。但用户私钥始终保留在本地钱包里,btc-assets-api 不能替用户签名,资产状态最终也由 BTC / CKB 链上交易决定。所以我更愿意把 LeapFi 称为一个 non-custodial RGB++ DApp,而不是 fully decentralized app。
为什么做 LeapFi?
RGB++ 的协议设计很有吸引力:通过 Bitcoin UTXO 和 CKB Cell 的同构绑定,让资产既能保留 Bitcoin 的所有权语义,又能获得 CKB 的可编程能力。
但从应用层看,目前 RGB++ 生态里还缺少一个比较直观的资产管理入口。开发者可以通过 SDK 和 API 构造交易、查询资产,但普通用户很难在一个地方看清楚自己的 RGB++ UDT / Spore 分别在 BTC 还是 CKB,也很难顺手完成 Leap、Transfer、状态追踪这些操作。
LeapFi 最初就是想补这个空缺:先做一个足够简单的 RGB++ 资产管理界面,让用户可以看到资产、发起操作,也让开发者能从一个真实 DApp 里观察 RGB++ 工作流的复杂度。
但真正做成面向用户的 DApp 后,我发现最难的地方不只是“构造交易”,而是让用户理解并顺利走完一条比较长的交易链路。
比如一次 Transfer on BTC,背后可能包括:
-
构造 CKB partial transaction
-
构造 BTC PSBT
-
签名并广播 BTC 交易
-
等待 BTC 区块确认
-
获取 SPV proof
-
签名并广播 CKB 交易
-
等待 CKB 交易确认
对协议来说,这些步骤都有必要。但对普通用户来说,他只是点了一个按钮。
所以 LeapFi 里做了 transaction pipeline,把每个步骤拆开显示:当前在构造 PSBT,还是在等 BTC 确认,还是在推进 CKB 交易。这样至少用户不会觉得页面“卡住了”。
开发心得:长流程、恢复与基础设施边界
做 LeapFi 的过程中,最明显的感受是:RGB++ DApp 的复杂度不只来自交易构造本身,还来自长流程状态管理、交易恢复、以及前端和 btc-assets-api 之间的职责划分。
长交易流程里的 checkpoint
RGB++ 交易流程中,有些中间结果必须保存。
尤其是 BTC 交易签名并广播之后,应用需要保存当时用于 commitment 的 CKB partial transaction。因为如果页面刷新后重新构造,UTXO 选择或交易结构可能已经变了,最后就可能和 BTC 交易里的 commitment 对不上。
所以 LeapFi 目前做了 checkpoint:
-
BTC 广播后保存
btcTxId -
保存 seal output index 或 receiver 信息
-
保存序列化后的 CKB partial transaction
-
页面刷新后尽量从 checkpoint 恢复,而不是重新猜一遍流程
这部分做下来,我感觉 RGB++ SDK 未来可以考虑提供更标准的 transaction session / resume API。
比如类似这样的 workflow helper:
await rgbpp.workflow.transferOnBtc(params, {
onStep,
persistence,
waitStrategy,
});
这里的重点不是把协议细节黑盒化,而是让 SDK 内置一套可恢复的状态机。
onStep 负责把结构化进度抛给 UI。DApp 不需要自己定义一堆状态名,比如 building PSBT、waiting BTC confirmation、generating SPV、broadcasting CKB。SDK 可以直接告诉应用当前走到哪一步。
persistence 负责保存恢复交易必须的数据,比如 operation、network、BTC txid、CKB partial transaction、commitment、last completed step。浏览器应用可以存在 IndexedDB 或 localStorage,更成熟的应用也可以存在自己的后端。
waitStrategy 则负责等待策略:前端轮询、后端 job、SSE、webhook,都可以放在这个层面扩展。
这样每个 DApp 就不用各自实现一套 checkpoint 规则,也不用反复判断哪些步骤可以重试、哪些步骤必须恢复原始交易、哪些步骤需要重新请求钱包签名。
btc-assets-api 是否适合承担更多 BTC 交易编排?
目前 btc-assets-api 已经在 RGB++ 工作流里承担了很多 BTC 广播之后的事情,比如等待 BTC 确认、SPV、job status 等。进一步的问题是:BTC 交易的构建和广播,是否也可以更多交给 btc-assets-api?
我觉得这个方向是可以讨论的,而且对用户体验可能是好事。但边界要非常清楚。
比较合理的流程可能是:
-
前端把用户意图提交给 btc-assets-api:资产、receiver、fee rate、change address 等
-
btc-assets-api 返回 unsigned PSBT、committed CKB transaction data、job/session id
-
前端或 SDK 校验 PSBT 是否符合用户意图
-
用户钱包签名 PSBT
-
前端把 signed PSBT 或 raw BTC tx 提交给 btc-assets-api
-
btc-assets-api 广播 BTC 交易,并继续推进后续 SPV / CKB job
也就是说,btc-assets-api 可以构建 unsigned PSBT,也可以广播用户已经签好的 BTC 交易,但不应该替用户签名,也不应该让用户盲签一个无法验证的 PSBT。
这里最大的安全问题是:普通 BTC 钱包通常只能展示 BTC 输入输出,不理解“这笔 BTC 交易背后绑定的是哪个 RGB++ 资产”。如果用户只是看到几个 sats、一个 OP_RETURN,然后直接签名,风险会比较高。
所以如果 btc-assets-api 参与 BTC 交易构建,SDK 或前端必须做 PSBT 语义校验:
-
receiver BTC address 是否正确
-
RGB++ asset input 是否正是用户选择的资产
-
CKB partial transaction 的 commitment 是否和 BTC transaction 匹配
-
change address 是否属于用户
-
fee 是否没有超过用户设置的上限
-
是否存在多余 input / output
-
网络是否正确
-
sighash 是否符合预期
更理想的是 btc-assets-api 返回一个结构化的 prepare response:
{
jobId,
psbt,
operation,
assetSummary,
receivers,
fee,
commitment,
ckbPartialTxHash,
expectedBtcOutputs,
}
然后 @ckb-ccc/rgbpp 提供类似:
rgbpp.verifyPreparedTransfer(response, userIntent);
只有校验通过后,DApp 才把 PSBT 交给钱包签名。
所以我的判断是:把 BTC 构建和广播纳入 btc-assets-api 是合理的,甚至可能是更好的 UX;但必须保留用户本地签名,并且必须有客户端语义校验。 btc-assets-api 可以成为 workflow coordinator,但不应该变成用户资产的信任方。
主网 JWT 与前端 DApp 的访问模型
btc-assets-api 是 RGB++ 应用里很关键的基础设施。它负责资产查询、BTC 信息、SPV、交易队列等能力。资源消耗型服务做权限控制和限流是合理的。
但主网 JWT 对纯前端 DApp 来说有点尴尬。
Token 不能放在前端代码里,普通用户也不方便自己申请 JWT。现在比较现实的做法是应用自己搭一个后端 proxy,把 token 放在服务端,由 proxy 转发请求。
LeapFi 目前也是这个思路。
这个方案能跑,但会带来一些额外成本:
-
前端 Demo 也需要后端
-
App 方要维护 proxy
-
app-level token 很难区分具体用户
-
不同资源成本的接口被放进同一种认证模型里
我觉得可以考虑分层:
-
低频资产查询开放匿名访问或低限流访问
-
重资源接口继续需要认证
-
支持钱包签名换短期 token
-
token 可以按地址、scope、endpoint、过期时间限制
-
verified app token 继续保留,但不是唯一入口
这不是说 JWT 不应该存在,而是现在的模型更适合“有后端的应用”,对开放 Web DApp 还可以再友好一点。
想听听大家的想法
LeapFi 还在早期,我更想把它当成一个真实应用实验场:看看 RGB++ 从 SDK、API 到用户体验,中间还有哪些地方可以打磨。
我特别想讨论几个问题:
-
@ckb-ccc/rgbpp是否应该提供更高层的 workflow / session API,把 checkpoint、resume、step tracking 这些逻辑标准化? -
btc-assets-api 的职责边界应该在哪里?它是否适合从 BTC 广播后的 job 处理,进一步扩展到 unsigned PSBT 构建和 signed tx 广播?
-
如果 PSBT 由 API 构建,客户端和 SDK 需要做哪些语义校验,才能避免用户盲签?
-
主网 API 的认证和限流,怎样对纯前端 DApp 更友好,同时又能控制资源消耗?
-
作为一个早期 RGB++ 资产管理 DApp,LeapFi 接下来最应该补齐哪些功能或体验?
欢迎体验 LeapFi preview,也欢迎在下面直接拍砖。