Skip to content

Latest commit

 

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@caict-bif/bif-typescript-sdk

直连 BIF 底层链节点的 TypeScript SDK(CommonJS)。

接口范围以链对外公开的 HTTP/WebSocket 接口为准,仅包含本 SDK 实际提供的方法。

项目结构

src/
├── bif-core/            # 传输层:HTTP 客户端(BifHttpClient)、WebSocket 订阅客户端、订阅协议
├── bif-sdk/             # SDK 层
│   ├── provider.ts      # BifProvider 入口:聚合五个域服务
│   └── interface/
│       ├── signer.ts    # BifSigner(账户 + 交易签名)
│       ├── service/     # 域服务:chain / account / ledger / transaction / contract
│       └── builder/     # 离线交易构造:buildPayCoin / buildTransaction / ...
├── abi/                 # Solidity ABI 工具(ethers 封装)
└── proto/               # 链 protobuf wire 编解码

安装

npm install @caict-bif/bif-typescript-sdk

快速开始

import { BifProvider, BifSigner, generateKeyPair } from "@caict-bif/bif-typescript-sdk";

const provider = new BifProvider({
  baseUrl: "https://your-bif-node.example", // 替换为你的 BIF 节点地址
  allowInsecureTls: true, // 测试网 TLS 证书链不完整时使用;生产环境不要开启
});

(async () => {
  // 链信息
  console.log(await provider.chain.hello());

  // 账户查询
  const account = await provider.account.getAccountBase("did:bid:ef...");
  console.log(account);

  // 区块查询
  console.log(await provider.ledger.getLedger({ seq: 1 }));
})();

签名器(Signer)

签名器可通过 connect(provider) 绑定后直接获得在线能力。

import { BifProvider, BifSigner, generateKeyPair } from "@caict-bif/bif-typescript-sdk";

const provider = new BifProvider({ baseUrl: "https://your-bif-node.example" });
const pair = generateKeyPair();
const signer = new BifSigner(pair.privateKey).connect(provider);

// 离线能力
const sig = signer.sign("aabb...");                        // 交易 blob → hex 签名
const ok = signer.verify("aabb...", "sighex");             // 验签

// 在线能力(connect 后)
await signer.getAccount();          // 查自己账户
await signer.getAccountBalance();   // 查自己余额
await signer.getLedgerNumber();     // 最新区块高度
await signer.estimateGas({ operations, gasPrice });  // 费用评估

// 绑定后的签名者可直接用于交易
await provider.transaction.sendTransaction({ signer, tx: {...} });

交易

交易支持两种流程,均与底层链 chain.proto 对齐:

1. 本地构造 + 签名 + 提交(推荐,零额外步骤)

import { BifProvider, OperationType, buildPayCoin, buildSetMetadata } from "@caict-bif/bif-typescript-sdk";

const provider = new BifProvider({ baseUrl: "https://your-bif-node.example" });
const signer = new BifSigner("你的编码私钥");

const result = await provider.transaction.sendTransaction({
  signer,
  tx: {
    sourceAddress: signer.address,
    nonce: 1, // INCREASE_NONCE 模式填账户当前 nonce;RANDOM_NONCE 模式填任意
    feeLimit: 10_000_000,
    gasPrice: 1000,
    operations: [
      buildPayCoin({ destAddress: "did:bid:ef...", amount: 1000, input: "" }),
      buildSetMetadata({ key: "k", value: "v" }),
    ],
  },
});
console.log(result); // { hash, error_code, error_desc }

本地序列化使用 SDK 自带的手写 protobuf wire 编码器,hash = SHA256(序列化字节), 与链端 HashWrapper::Crypto(hash_type=0 时)一致。

2. 链端生成 blob(getTransactionBlob)

const tx = buildTransaction({ sourceAddress: signer.address, nonce: 1, operations: [...] });
const blob = await provider.transaction.getTransactionBlob(tx); // { transactionBlob, hash }
const signature = signer.signTransaction(blob.transactionBlob);
const results = await provider.transaction.submitTransaction([{ transaction_blob: blob.transactionBlob, signatures: [signature] }]);

离线交易构造接口

离线 operation 构造器(可与 sendTransaction / buildTransaction 组合):

构造器 底层 Operation
buildPayCoin({destAddress, amount, input?}) PAY_COIN
buildContractInvoke({contractAddress, amount?, input?}) PAY_COIN → 合约
buildSetMetadata({key, value, version?, deleteFlag?}) SET_METADATA
buildCreateAccount({destAddress, initBalance?, contract?, priv?, ...}) CREATE_ACCOUNT
buildActivateAccount(destAddress, initBalance?) CREATE_ACCOUNT + 默认权限
buildSetPrivilege({masterWeight?, signers?, txThreshold?, typeThresholds?}) SET_PRIVILEGE
buildBatchGasSend(items[]) 批量 PAY_COIN
buildBatchContractInvoke(items[]) 批量合约调用

多签离线签名(无需网络):

const { transactionBlob, hash, signatures } = provider.transaction.buildSignedBlob(
  { sourceAddress, nonce: 1, operations: [...] },
  [signerA, signerB],        // 多签者
  { dissPubkey: false },
);
// signatures[].sign_data / .public_key 可直接提交 provider.transaction.submitTransaction

对外接口清单

chain(链信息)

方法 对应链接口 说明
provider.chain.hello() GET /hello 链基础信息
provider.chain.getNetworkId() / getChainVersion() GET /hello 网络 ID / 节点版本

account(账户)

方法 对应链接口 说明
provider.account.getAccount(address, opts?) GET /getAccount 账户信息
provider.account.getAccountBase(address) GET /getAccountBase 账户基础信息
provider.account.getAccountMetaData(address, key?) GET /getAccountMetaData 账户 metadata
provider.account.getAccountNonce(address) GET /getAccountBase 账户 nonce
provider.account.getAccountBalance(address) GET /getAccountBase 账户余额
provider.account.getAccountPriv(address) GET /getAccountBase 账户权限

ledger(账本)

方法 对应链接口 说明
provider.ledger.getLedgerNumber() GET /getLedger 最新区块高度
provider.ledger.getLedger(opts?) GET /getLedger 区块信息(seq/withFee/withValidator/withConsvalue/withLeader)
provider.ledger.getLedgerTransactions(seq) GET /getLedger 区块内交易列表

transaction(交易)

方法 对应链接口 说明
provider.transaction.getTxCacheSize() GET /getTxCacheSize 交易池条数
provider.transaction.getTransactionCache(opts?) GET /getTransactionCache 交易池缓存
provider.transaction.getTransactionHistory(opts?) GET /getTransactionHistory 链上交易
provider.transaction.getTransactionBlob(tx) POST /getTransactionBlob 交易转 blob
provider.transaction.submitTransaction(items) POST /submitTransaction 提交交易
provider.transaction.testTransaction(item) POST /testTransaction 节点内测试交易(不上链)
provider.transaction.sendTransaction({tx, signer}) 本地构造+签名+提交 一键交易
provider.transaction.buildBlob(params) / buildSignedBlob(...) 本地 离线构造 / 多签离线签名

contract(合约)

方法 对应链接口 说明
provider.contract.callContract(params) POST /callContract 合约只读调用
provider.contract.getContractInfo(address) GET /getAccountBase 合约账户信息
provider.contract.getContractAddress(hash) GET /getTransactionHistory 合约创建交易 hash → 合约地址列表

WebSocket 订阅

import { BifWsClient, MessageType, chainTxStatusCodec, ledgerHeaderCodec } from "@caict-bif/bif-typescript-sdk";

const ws = new BifWsClient({ url: "wss://your-bif-node.example/ws", });
  • MessageType.CHAIN_LEDGER_HEADER(16) 订阅区块头 → ledgerHeaderCodec
  • MessageType.CHAIN_LEDGER_TXS(18) 订阅完整区块
  • MessageType.CHAIN_CONTRACT_LOG(17) 订阅合约 TLOG → tlogSubscribeResponseCodec
  • MessageType.CHAIN_SUBSCRIBE_TX(19) 订阅指定地址交易
  • MessageType.SUBSCIBE_TXS(21) 订阅交易丢弃状态 → txSubscribeResponseCodec
  • MessageType.CHAIN_TX_STATUS(11) 交易执行状态推送 → chainTxStatusCodec
  • MessageType.CHAIN_HELLO(10) 连接握手,链端默认开启区块/区块头/交易状态推送

Solidity ABI 工具(EVM 合约,基于 ethers v6)

提供 Solidity 合约的 ABI 编解码能力,仅服务 EVM 合约 (原生 JS 合约 input 为 JSON 字符串,不走本工具)。

import { encodeFunctionInput, decodeFunctionOutput, getEventTopic, getFunctionSelector, encodeAbiTypes } from "@caict-bif/bif-typescript-sdk";

const abi = [
  "function transfer(address to, uint256 amount) returns (bool)",
  "function balanceOf(address account) view returns (uint256)",
  "event Transfer(address indexed from, address indexed to, uint256 value)",
];

const input = encodeFunctionInput({ abi, name: "transfer", args: [to, 1000n] }); // 0x + selector + 参数,可直接作 contractInvoke 的 input
const returns = decodeFunctionOutput({ abi, name: "balanceOf", data: rawResult }); // [42n]
const topic = getEventTopic({ abi, name: "Transfer" }); // 事件 topicHash
const selector = getFunctionSelector("transfer(address,uint256)"); // 0xa9059cbb

扩展能力

方法 说明
provider.transaction.parseBlob(blobHex) 本地反序列化交易 blob → {transaction, hash},无需网络
provider.contract.getContractAddress(hash) 合约创建交易 hash → 合约地址列表(解析交易 error_desc)
provider.transaction.evaluateFee({sourceAddress, operations, nonceType?, feeLimit?, gasPrice?, remarks?}) 费用评估:nonceType=0 自动取账户 nonce+1;=1 本地随机 nonce + maxLedgerSeq,底层走 /testTransaction
const fee = await provider.transaction.evaluateFee({
  sourceAddress: "did:bid:ef...",
  operations: [buildContractInvoke({ contractAddress: "did:bid:efContract", input: "{}" })],
  gasPrice: 1000,
});

Sample

仓库提供 sample/ 目录,覆盖基础查询、交易构造/提交、签名器、ABI/合约与 WebSocket 订阅场景。 提交到 git 的示例只包含占位连接地址和占位账户,不包含真实节点、私钥或 API Key。

npm run build
node sample/run-all.js --list

需要跑联网或写交易场景时,在本地复制配置文件并填写真实值:

cp sample/config.example.js sample/config.local.js

sample/config.local.js 已被 .gitignore 忽略,用来填写本地敏感信息:

  • baseUrl:HTTP 节点地址(查询、费用评估、testTransaction 使用)
  • wsUrl:WebSocket 订阅地址
  • readerAddress:只读查询账户地址
  • contractAddress / contractDeployHash:合约在线示例需要时填写
  • writerPrivateKey:写交易账户编码私钥,仅保存在本地
  • enableWriteRuns:写交易总开关,必须显式设为 true 才会发送交易

也可以用环境变量临时覆盖:BIF_BASE_URL、BIF_WS_URL、BIF_READER_ADDRESS、BIF_WRITER_PRIVATE_KEY。

npm run sample -- --list
npm run sample
npm run sample -- --only=tx-offline-builders

默认占位配置下,离线场景会运行;联网、WebSocket 和写交易场景会跳过并提示需要填写的本地配置。

开发

npm install
npm test          # tsc 编译 + mocha(33 个用例:wire/编解码/签名/交易构造/ABI/扩展能力)
npm run build

说明

  • allowInsecureTls: true 仅用于测试网联调(节点 TLS 证书链不完整)。
  • int64 字段内部用 BigInt 处理,响应解码时安全范围内的值返回 number。
  • 交易 JSON(getTransactionBlob)中 bytes 字段以 hex 字符串表示(与链端 Json2Proto 一致)。

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages