直连 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-sdkimport { 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 }));
})();签名器可通过 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 对齐:
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 时)一致。
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| 方法 | 对应链接口 | 说明 |
|---|---|---|
provider.chain.hello() |
GET /hello | 链基础信息 |
provider.chain.getNetworkId() / getChainVersion() |
GET /hello | 网络 ID / 节点版本 |
| 方法 | 对应链接口 | 说明 |
|---|---|---|
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 | 账户权限 |
| 方法 | 对应链接口 | 说明 |
|---|---|---|
provider.ledger.getLedgerNumber() |
GET /getLedger | 最新区块高度 |
provider.ledger.getLedger(opts?) |
GET /getLedger | 区块信息(seq/withFee/withValidator/withConsvalue/withLeader) |
provider.ledger.getLedgerTransactions(seq) |
GET /getLedger | 区块内交易列表 |
| 方法 | 对应链接口 | 说明 |
|---|---|---|
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(...) |
本地 | 离线构造 / 多签离线签名 |
| 方法 | 对应链接口 | 说明 |
|---|---|---|
provider.contract.callContract(params) |
POST /callContract | 合约只读调用 |
provider.contract.getContractInfo(address) |
GET /getAccountBase | 合约账户信息 |
provider.contract.getContractAddress(hash) |
GET /getTransactionHistory | 合约创建交易 hash → 合约地址列表 |
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) 订阅区块头 →ledgerHeaderCodecMessageType.CHAIN_LEDGER_TXS(18) 订阅完整区块MessageType.CHAIN_CONTRACT_LOG(17) 订阅合约 TLOG →tlogSubscribeResponseCodecMessageType.CHAIN_SUBSCRIBE_TX(19) 订阅指定地址交易MessageType.SUBSCIBE_TXS(21) 订阅交易丢弃状态 →txSubscribeResponseCodecMessageType.CHAIN_TX_STATUS(11) 交易执行状态推送 →chainTxStatusCodecMessageType.CHAIN_HELLO(10) 连接握手,链端默认开启区块/区块头/交易状态推送
提供 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/ 目录,覆盖基础查询、交易构造/提交、签名器、ABI/合约与 WebSocket 订阅场景。
提交到 git 的示例只包含占位连接地址和占位账户,不包含真实节点、私钥或 API Key。
npm run build
node sample/run-all.js --list需要跑联网或写交易场景时,在本地复制配置文件并填写真实值:
cp sample/config.example.js sample/config.local.jssample/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 buildallowInsecureTls: true仅用于测试网联调(节点 TLS 证书链不完整)。- int64 字段内部用 BigInt 处理,响应解码时安全范围内的值返回
number。 - 交易 JSON(
getTransactionBlob)中 bytes 字段以 hex 字符串表示(与链端Json2Proto一致)。