[翻译]:让 PW-Core 能够适配后端使用的提案(有 50000 CKB+ 的奖励!!)

针对IndexerCollector 抛砖引玉~ :grinning_face_with_smiling_eyes:

  1. 实现getBalance。根据ckb-indexer,可以直接调用get_cells_capacity,输入是script和scrip_type,输出的capacity的单位应该是ckb。
// get capacity by lock script
  async getBalance(address: Address): Promise<Amount> {
    const data = {
      data: {
        script: address.toLockScript().serializeJson(),
        scrip_type: "lock",
      }
    };
    
    const res = await axios.post(
      `${
        this.apiBase
      }/get_cells_capacity`,
      data
    );
    /* result data: {
        capacity - total capacity
        block_hash - indexed tip block hash
        block_number - indexed tip block number
      }
    */
    //PwCollector: return new Amount(res.data.data, AmountUnit.shannon);
    return new Amount(res.data.capacity, AmountUnit.ckb);
  }
  1. 实现collect。根据含义应该是get unspent cells。可以根据上面的代码调用rpc的 get_cells
// get unspent cells
  async collect(address: Address, options: CollectorOptions): Promise<Cell[]> {
    if (!options || !options.neededAmount) {
      throw new Error("'neededAmount' in options must be provided");
    }
    const addressLockScript = address.toLockScript();
    const cells: Cell[] = [];
    // 怎么把capacity=${options.neededAmount.toHexString()}传进去?
    const reqData = {
      data: {
        script: address.toLockScript().serializeJson(),
        scrip_type: "lock",
      }
    };
    const res = await axios.post(
      `${
        this.apiBase
      }/get_cells`,
      reqData
    );
    /* result data: {
        objects - live cells
        last_cursor - pagination parameter
      }
    */
    for (let liveCell of res.data.objects) {
      // capacity = new Amount(capacity, AmountUnit.shannon);
      // outPoint = new OutPoint(outPoint.txHash, outPoint.index);
      //cells.push(new Cell(capacity, addressLockScript, null, outPoint));
      cells.push(Cell.fromRPC(liveCell)); // 应该可以直接fromRPC吧?
    }
    return cells;
  }
  1. 浏览时从ckb-js-toolkit中发现了RPC,尝试直接调用rpc.collect如下,最后对数据遍历时,没有找到怎么获取capacity:
constructor(public apiBase: string = "https://mainnet.ckb.dev/indexer") {
    super();
    this.apiBase = apiBase;
    this.rpc = new RPC(this.apiBase);
  }

// get unspent cells
  async collect(address: Address, options: CollectorOptions): Promise<Cell[]> {
    if (!options || !options.neededAmount) {
      throw new Error("'neededAmount' in options must be provided");
    }
    const addressLockScript = address.toLockScript();
    const rpcc = new cell_collectors.RPCCollector(this.rpc, addressLockScript.toHash(), {
      skipCellWithContent: true,
      loadData: true
    });
    const data = rpcc.collect();
    const cells: Cell[] = [];

    (async () => {
        for await (const x of data) {
          // 这里的capacity怎么读取?
          const cap= new Amount(capacity, AmountUnit.shannon);
          const outPoint = OutPoint.fromRPC(x.data);
          cells.push(new Cell(cap, addressLockScript, null, outPoint));
        }
    })();
    return cells;
  }
  1. 找资料时,找到了 CKBRPC in ckb-sdk-core
    当前项目中没找到@nervosnetwork/ckb-sdk-core,尝试安装,失败。
    CKBRPC中的getCapacityByLockHash应该就是IndexerCollector的getBalance需要的方法;没有找到可直接用的通过neededAmount查询的方法。
    不知道为什么没有引入@nervosnetwork/ckb-sdk-core,有了这个库,就不需要通过axios进行查询了。

  2. 关于如何实现collect的一个思路。
    在wile(true)循环中,可以通过第2条或者CKBRPC. getLiveCellsByLockHash获取一个分页的cells,然后比较neededAmount和分页中所有cell的capacity之和:小于,取分页中最小够用的cells集合,跳出循环;大于,继续获取下一个分页的数据。

const resultCells = [];
while(true){
   const cells = ..... // 第2条的axios调用,或者CKBRPC. getLiveCellsByLockHash
   const totalCapacity = ... // 遍历cells数组计算capacity之和
   if(totalCapacity >= neededAmount){
      // cells --> resultCells: 可能只需要cells中的一部分而非全部
      break;
   }
}
2 Likes