RPC 调用使用了 method missing 自动生成,统一返回结果是 Hash,而不是定义的 Class Type。优点:ckb 新加或者调整 rpc 方法,sdk 不需要跟随升级,缺点:需要查看 ckb 文档调用,ruby doc 无法生成文档,IDE 无自动提示。
RPC 参数做了 Integer 到 Hex 自动转化,方便调用(特别是分页参数这种)
调用方式和之前一样:
rpc = CKB::RPC.new
rpc.get_tip_header
rpc.get_header_by_number(255)
rpc.get_header_by_number(0xff)
Types 直接从 hash 构建出对象,对于 hex string,内部统一使用 bytes,避免原先 SDK 代码里面有大量的 bin_to_hex / hex_to_bin 转化
CKB::Types::OutPoint.new(tx_hash: "0xff44", index: "0xff")
#<CKB::Types::OutPoint @tx_hash=[255, 68], @index=255>
把构建交易拆成了2个步骤:生成未签名交易/用私钥对交易进行签名
生成未签名交易(TransactionBuilder#generate) 会通过 collector 来收集 CellMeta
,每收集到一个 CellMeta
,根据它对应的 output,去修改交易数据,比如添加 inputs / cell_deps / witnesses 等数据,相关代码请参考 CellMeta#generate
默认提供了2种 collector,一个通过 rpc get_cells_by_lock_hash
从高度0开始遍历(性能差),另外一个是通过 rpc get_live_cells_by_lock_hash
(需要节点开启 Indexer 模块)。用户可以实现其他的 Collector 来满足不同的需求,只要返回 Enumerator<CellMeta>
即可
用私钥对交易进行签名(TransactionBuilder#sign) 会依次调用 CellMeta#sign
Wallet 是对 Transaction Builder 的包装,提供了一个易用的接口专门用于生成转账交易:
rpc = CKB::RPC.new
wallet = CKB::Wallet.new(rpc)
tx = wallet.gen_tx(
"ckt1qyqvsv5240xeh85wvnau2eky8pwrhh4jr8ts8vyj37",
"ckt1qyqywrwdchjyqeysjegpzw38fvandtktdhrs0zaxl4",
100_0000_0000,
"0xd00c06bfd800d27397002dca6fb0993d5ba6399b4238b2f29ee9deb97593d2bc".from_hex
)
rpc.send_transaction(tx.as_json)
-
在这个 sdk 代码结构里面,构建交易和签名的核心代码都移到了
CellMeta
上,它做的两件事情:根据 input 的 lock / type 不同,给交易添加或者修改不同的数据,以及进行不同的签名逻辑。目前是用 if else 来做分支判断,这里的接口需要重新设计一下,将它独立出来,包括实现 DAO 的处理 -
构建交易和签名所需要的 context 不同,比如单签 lock,构建交易的时候 context 不需要提供私钥,签名的时候需要私钥。而多签 lock,构建交易的时候,需要 S/M/N/pubkeys 这个 context,而签名的时候只需要 private keys
-
序列化是手写的,应该考虑基于 molecule code-gen 生成
-
默认的 Collector 要实现开箱可用,需要改成接受从某个高度开始扫描的参数,这样用户就可用一个临时文件保存扫描的高度,而不是每次从0开始扫描