摘要
这个 RFC 定义了 CKB Provider JavaScript API,让不同的应用使用同样的 API 通过 Provider 与 CKB 节点进行交互。
名词解释
Wallet
用来管理用户的公钥和私钥,为交易签名。
Provider
Provider 可以看做是一组 API,用来方便应用与区块链进行交互。一方面可以代替应用向 CKB 节点发送 RPC 请求,就好像互联网服务提供商(Provider)一样,为应用提供了访问互联网的能力,而区块链的 Provider 为应用提供了访问区块链的能力。另一方面,除了访问区块链,Provider 本身还可以提供额外的功能,比如返回用户的钱包地址、签名等。通常 Provider 会内置在 Wallet 中,也可以是一个单独的库。
CKB 节点
CKB 节点是实现了 CKB 协议的客户端,也称为区块链节点,接收来自 Provider 或者用户 的 Remote Procedure Call (RPC),并返回结果。
应用(Application)
面向用户的程序,通常具有用户界面,允许用户与其交互,并返回特定的结果。
动机
不同的 Provider 会定义不同的 API 名称,这样会导致定义和交互方式的碎片化,而通过定义一个统一的接口可以避免这类问题,给应用开发者更好的开发体验。例如,对于一个浏览器插件钱包,钱包会提供 API 给 DApp 开发者使用,如:
getAddresses: any[]; // 获取可用的地址列表
而另外一个桌面端钱包也提供了类似的 API:
methodCall({ method: "getAddressList", pubKey: string }): { message: string, result: any[] }; // 获取可用的地址列表
虽然这两个 API 的功能类似,但却使用了不同的调用方式和返回的数据结构。
通过使用 JSON RPC 的方式可以将不同的 API 调用方式统一起来:
// getAddresses
--> {"jsonrpc": "2.0", "method": "getAddresses", "params": [], "id": 1}
<-- {"jsonrpc": "2.0", "result": [], "id": 1}
// getAddressList
--> {"jsonrpc": "2.0", "method": "getAddressList", "params": ["0x11"], "id": 2}
<-- {"jsonrpc": "2.0", "result": [], "id": 2}
这样就提供了几个优点:
- 提供统一的调用方式。无论是对于 CKB 节点的直接 RPC 调用,还是调用 Provider 提供的 RPC 方法,调用方法都是一样的,应用开发者不需要进行区分。
- 兼顾了接口统一和灵活扩展。开发者在使用统一接口的基础上,通过添加自定义的方法来进行扩展。
但是 JSON RPC 的调用方式构造起来有点复杂,为了简化调用方式,我们提议使用一个统一的 API 名称: request
。
规范
API
request: 封装了 JSON RPC 调用,方便用户与区块链进行交互。
interface Request {
method: string;
params?: Array<any>;
}
interface Result {
result: any;
error: Error;
}
interface Error {
message: string;
code: number;
data?: any;
}
Provider.request(args: Request): Promise<Result>;
请求
请求的参数需要符合下面的结构:
interface Request {
method: string;
params?: Array<any>;
}
Provider.request(args: Request)
返回值
interface Result {
result: any;
error: Error;
}
- 成功: 返回
result
由具体的方法指定。 - 失败: 返回
error
符合下面Error
的定义。
Error
如果发生错误,返回的数据结构需要符合下面的定义:
interface Error {
message: string;
code: number;
data?: any;
}
- message: 人类可读的字符串。
- code: 错误码,正整数。参考下面的 Error Code 的定义。
- data: 任何其它的信息。
Error Code
Code | Name | Explanation |
---|---|---|
1001 | Rejected | Request is rejected by user |
1004 | UnknownError | Other error |
1100 | Unauthorized | Method or account is not authorized by user |
1200 | Unsupported | Method is not supported by provider |
Example:
import Provider from "ckb-provider";
const provider = new Provider(["http://127.0.0.1:8114"]);
const tx = {
version: "0x0",
cellDeps: [{
outPoint: {
// a fixed value for testnet
txHash: "0xf8de3bb47d055cdf460d93a2a6e1b05f7432f9777c8c474abf4eec1d4aee5d37",
index: "0x0"
},
depType: "depGroup",
}],
headerDeps: [],
inputs: [],
outputs: [],
witnesses: [],
outputsData: []
};
const result: Result = await provider.request({
method: "send_transaction",
params: [tx]
});