npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@caict-bif/bif-typescript-sdk

v0.2.0

Published

BIF 底层链对外开放接口 TypeScript SDK (直连链节点)

Readme

@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 一致)。