@boing-network/boing-sdk

中文文档
0.5.40发布于 2026/11/06MITTypeScriptES Module近 30 天下载 3329

Seamless SDK for building on Boing Network

原始使用文档
文档目录13 节
  1. Install
  2. Consuming via file: (e.g. boing.finance )
  3. Publish to npm (CI)
  4. Tests
  5. Quick start
  6. API
  7. Tokens (mirrors boing token )
  8. Native AMM pools (mirrors boing pool )
  9. Submitting transactions
  10. Simulate → access list → submit (P4)
  11. API additions (transaction flows)
  12. Tests
  13. Planned

Boing SDK

🛠️ Developers: this is the TypeScript client for Boing JSON-RPC, QA errors, native DEX calldata, and wallet glue.
👋 Everyday users: you use this indirectly through boing.express, boing.observer, and boing.finance.
🛰️ Operators: after SDK source changes, run npm run build here and commit dist/. Tutorial file: consumers need a fresh dist/.

TypeScript/JavaScript client for Boing Network: typed RPC client, hex utilities, and structured errors (including QA rejection feedback).

flowchart LR
  App[dApp / finance / explorer] --> SDK["@boing-network/boing-sdk"]
  SDK --> RPC[boing_chainHeight / getAccount / qaCheck / listDex*]
  SDK --> Wallet[window.boing helpers]

Install

Consumers (npm):

npm install @boing-network/boing-sdk

Current registry latest: see the npm package page (this repo's package.json is 0.5.39). Package page: npmjs.com/package/@boing-network/boing-sdk. Do not install unscoped boing-sdk — that name is abandoned/locked and is not updated by this repo.

Monorepo / contributors (this directory):

npm install
npm run build

Consuming via file: (e.g. boing.finance)

The compiled output lives in dist/, which is committed in Boing-Network/boing.network (repo root .gitignore ignores generic dist/ but not boing-sdk/dist/). Clones and CI siblings therefore get a usable dist/index.js without a separate SDK build step.

When you change SDK source (src/), run npm run build in boing-sdk and commit the updated dist/. The boing-sdk workflow fails if dist/ drifts from the TypeScript build output.

boing.finance checks out boing.network only so the file: path resolves; it does not build the SDK first. boing.finance’s frontend/scripts/postinstall-boing-sdk.mjs only runs npm run build in the linked package when dist/index.js is missing (e.g. local SDK development or a broken checkout) and fails the install if that build does not succeed.

Publish to npm (CI)

Package name on the registry: @boing-network/boing-sdk (scoped). Unscoped boing-sdk remains abandoned/locked and is not published from this workflow.

Scoped publish is live. Routine releases use the Publish boing-sdk GitHub Action (.github/workflows/boing-sdk-publish.yml) on tags boing-sdk/v* with repository secret NPM_TOKEN.

Required GitHub secret (ENEEDAUTH if missing):

  1. On npmjs.com as a user that can publish @boing-network/boing-sdk, create an Automation token (or granular token with publish on that package; Automation avoids interactive OTP in CI).
  2. In the Boing-Network/boing.network repo: Settings → Secrets and variables → Actions → New repository secret.
  3. Name: NPM_TOKEN. Value: the npm token (npm_…).
  4. Smoke-check without publishing: Actions → Publish boing-sdk → Run workflow with auth_only = true (expects npm whoami to succeed).

Historical tag publishes failed with ENEEDAUTH when this secret was absent (empty NODE_AUTH_TOKEN in CI). The workflow now fails fast with a clear error if the secret is missing.

Each release (after package.json version + CHANGELOG + committed dist/ are on main):

git checkout main && git pull origin main
node -p "require('./boing-sdk/package.json').version"   # e.g. 0.5.39
git tag -a "boing-sdk/v$(node -p "require('./boing-sdk/package.json').version")" -m "@boing-network/boing-sdk $(node -p "require('./boing-sdk/package.json').version")"
git push origin "boing-sdk/v$(node -p "require('./boing-sdk/package.json').version")"

Watch Actions → Publish boing-sdk. Then: npm view @boing-network/boing-sdk version. Prefer registry installs for FreshMint and other apps (npm install @boing-network/boing-sdk); GitHub path:/boing-sdk pins are not the preferred consumer path.

Tests

  • Unit / offline: npm test — Vitest; does not require a running Boing node.
  • Optional RPC integration: tests/rpcIntegration.test.ts runs only when BOING_INTEGRATION_RPC_URL is set (e.g. http://127.0.0.1:8545). If it is unset, Vitest skips that whole suite so default runs stay offline-friendly. Core cases: sync state (or getBlockByHeight fallback), blocks + receipts, getLogsChunked, fetchBlocksWithReceiptsForHeightRange, getTransactionReceipt (unknown tx → null). Endpoints that return -32601 for boing_getSyncState or boing_getLogs still pass where noted. With BOING_EXPECT_FULL_RPC=1 (see .github/workflows/boing-sdk-rpc-integration.yml), an extra test asserts boing_clientVersion, boing_rpcSupportedMethods, and probeBoingRpcCapabilities (6/6 core methods, including boing_getNetworkInfo / boing_getBlockByHeight / boing_getTransactionReceipt).
  • Operator / tutorial smoke (separate from Vitest): in examples/native-boing-tutorial, npm run preflight-rpc (or check-testnet-rpc only) with BOING_RPC_URL — same scripts CI runs after starting a local node; see NODE-OPERATOR-COMMANDS.md. From the monorepo root, the same npm run <script> names delegate to the tutorial package (see root package.json).
  • npm run verify — same as npm test, then prints a short note explaining the skip when the env var is missing.

Quick start

import { createClient, BoingRpcError, explainBoingRpcError } from '@boing-network/boing-sdk';

// Local node (no retries needed):
const local = createClient('http://localhost:8545');

// Public testnet RPC — recommend maxRetries (default is 0):
const client = createClient({
  baseUrl: 'https://testnet-rpc.boing.network/',
  maxRetries: 3,
});

// Read chain and account state
const height = await client.chainHeight();
const account = await client.getAccount('0x' + '00'.repeat(32)); // 32-byte hex
console.log(account.balance, account.nonce, account.stake);

// Pre-flight QA check before deploying a contract
const qa = await client.qaCheck('0x600160005260206000f3'); // hex bytecode
if (qa.result === 'reject') {
  console.error('QA rejected:', qa.rule_id, qa.message);
} else if (qa.result === 'allow') {
  // Submit signed tx (hex from Rust CLI or future signer)
  await client.submitTransaction(hexSignedTx);
}

// Handle structured QA / rate-limit errors on submit
try {
  await client.submitTransaction(hexSignedTx);
} catch (e) {
  if (e instanceof BoingRpcError && e.isQaRejected) {
    const { rule_id, message } = e.qaData ?? {};
    console.error('Deployment rejected:', rule_id, message);
  }
  if (e instanceof BoingRpcError) {
    console.error(explainBoingRpcError(e)); // HTTP 429 / -32016 / gateway limits
  }
  throw e;
}

Public RPC / 429: Cloudflare in front of testnet-rpc.boing.network may return HTTP 429. Default maxRetries is 0; for public RPC pass maxRetries: 2–3 so transient limits and faucet -32016 can back off (honors Retry-After). See BOING-RPC-ERROR-CODES-FOR-DAPPS.md.

API

  • createClient(config) — config can be a URL string or { baseUrl, fetch?, timeoutMs?, maxRetries?, retryBaseDelayMs? }. Default timeout 30s; set timeoutMs: 0 to disable. Default maxRetries: 0 (no retries); use 2–3 against public testnet RPC.
  • BoingClient — typed methods for all RPCs (32-byte account/hash params are validated locally before sending):
    • RPC probe — probeBoingRpcCapabilities returns { clientVersion, supportedMethods, methods } plus countAvailableBoingRpcMethods, explainBoingRpcProbeGaps (rpcCapabilities.ts): detect -32601 missing methods; CLI: npm run build then npm run probe-rpc (or npm run probe-rpc from repo root); diagnosis in JSON explains stale node vs current repo; node discovery: boing_clientVersion, boing_rpcSupportedMethods
    • chainHeight(), getBalance(hexAccountId), getAccount(hexAccountId)
    • getBlockByHeight(height, includeReceipts?), getBlockByHash(hexHash, includeReceipts?)
    • getTransactionReceipt(hexTxId), getLogs(filter) — bounded log query (RPC-API-SPEC.md)
    • Receipt/log helpers: normalizeTopicWord, iterBlockReceiptLogs, filterReceiptLogsByTopic0, … (receiptLogs.ts; see INDEXER-RECEIPT-AND-LOG-INGESTION.md)
    • getAccountProof(hexAccountId), verifyAccountProof(hexProof, hexStateRoot)
    • simulateTransaction(hexSignedTx), submitTransaction(hexSignedTx)
    • High-level flows: submitTransferWithSimulationRetry, submitContractCallWithSimulationRetry, submitDeployWithPurposeFlow (see Simulate → access list → submit below)
    • Linked NFT ↔ token (on-chain registry) — live public testnet registry CANONICAL_BOING_TESTNET_LINKED_NFT_TOKEN_REGISTRY_HEX (0xf704485a…655dd on https://testnet-rpc.boing.network/, salt BOING_NFT_TOKEN_LINK_REG_V2, selectors 0xE0–0xE8); v1 0xebf9f019…3dd8 is history-only as CANONICAL_BOING_TESTNET_LINKED_NFT_TOKEN_REGISTRY_V1_HEX; dApp buildLinkedNftTokenProjectPack (joint deploy + claim×2 + register), buildLinkedNftTokenPairDeploys, buildLinkedNftTokenRegisterFlowTxs, registry deploy/encoders; optional cache schema boing.linked_nft_token.v1 (linkedNftTokenProjectPack.ts, linkedNftTokenRegistry.ts, linkedNftToken.ts; BOING-LINKED-NFT-TOKEN.md)
    • Builder attestation (on-chain registry) — live public testnet registry CANONICAL_BOING_TESTNET_BUILDER_ATTESTATION_REGISTRY_HEX (0x734077a9…1816 on https://testnet-rpc.boing.network/, salt BOING_BUILDER_ATTEST_REG_V1, selectors 0xE0–0xE6); dual asset claimer separate from companions; buildBuilderAttestationAttestFlowTxs, deploy/encoders (builderAttestationRegistry.ts; BOING-BUILDER-ATTESTATION.md). Soft wallet proofs are not authority.
    • Pinned native deploy (Boing Express tx objects) — buildContractDeployMetaTx (optional create2SaltHex / create2_salt), buildReferenceFungibleDeployMetaTx / buildReferenceFungibleSecuredDeployMetaTx / buildReferenceNftCollectionDeployMetaTx (wizard-friendly one-call builders), resolveReferenceFungibleTemplateBytecodeHex, resolveReferenceFungibleSecuredTemplateBytecodeHex, resolveReferenceNftCollectionTemplateBytecodeHex, ensure0xHex, DEFAULT_REFERENCE_FUNGIBLE_SECURED_TEMPLATE_BYTECODE_HEX, REFERENCE_FUNGIBLE_TEMPLATE_VERSION, REFERENCE_FUNGIBLE_SECURED_TEMPLATE_VERSION, REFERENCE_NFT_COLLECTION_TEMPLATE_VERSION (canonicalDeployArtifacts.ts; BOING-CANONICAL-DEPLOY-ARTIFACTS.md); multi-network wizards: isBoingTestnetChainId, normalizeBoingChainIdHex, BOING_TESTNET_CHAIN_ID_* (chainIds.ts); review-step QA (dappDeploy.ts; BOING-DAPP-INTEGRATION.md § One wizard, two backends): buildAndPreflightReferenceFungibleDeploy, buildAndPreflightReferenceNftCollectionDeployMeta, preflightContractDeployMetaWithUi, describeContractDeployMetaQaResponse, preflightContractDeployMetaQa, BOING_QA_PLACEHOLDER_DESCRIPTION_HASH_HEX
    • Generic calldata words — calldataSelectorLastByte, calldataU128BeWord, calldataAccountIdWord, calldataFixedWord32, concatCalldata (same layout as reference token/NFT encoders; use for custom contracts)
    • Typed call builder — BoingCalldataWord, assertBoingCalldataWord, boingWordU128 / boingWordAccount / boingWordFixed / boingWordSelector (32-byte argument words), encodeBoingCall(selectorLowByte, args) (reference-style first word + argument words)
    • Minimal call ABI (Boing-native) — encodeBoingCallTyped(selector, ['u128','account',…], values), encodeBoingCallFromAbiArgs, BoingReferenceCallDescriptors (fixed-width reference token / NFT / native AMM layouts) + encodeBoingCallFromDescriptor — not Solidity ABI / keccak4; matches docs/BOING-REFERENCE-TOKEN.md, BOING-REFERENCE-NFT.md, NATIVE-AMM-CALLDATA.md
    • Reference NFT — SELECTOR_MINT_BATCH (0x06), MAX_REFERENCE_NFT_MINT_BATCH (500), encodeReferenceMintBatchCalldata / encodeReferenceMintBatchCalldataHex (layout 96+64n; zero hash skips metadata SSTORE), plus 96-byte encodeReferenceOwnerOf* / TransferNft* / SetMetadataHash*; storage key helpers (referenceNft.ts). Do not encode mint_batch via BoingReferenceCallDescriptors. Template version "3", artifact id boing.reference_nft_collection.v0; dump line 3 / embed-reference-nft-collection-template-hex.mjs. Needs GAS_PER_CONTRACT_CALL = 40_000_000 on the node for full n=500 (Fly public testnet redeploy after merge). For 10k mints: chunk 20×500 — OpenSea-scale media upload ≠ one Boing consensus tx.
    • Native CP pool (MVP) — buildNativeConstantProductPoolAccessList, buildNativeConstantProductContractCallTx, mergeNativePoolAccessListWithSimulation; fetchNativeConstantProductReserves, fetchNativeConstantProductPoolSnapshot (batched reserves + total LP ± signer LP), fetchNativeConstantProductTotalLpSupply, fetchNativeConstantProductSwapFeeBps (v3/v4), fetchNativeAmmSignerLpBalance, decodeBoingStorageWordU128, decodeNativeAmmAddLiquidityReturnLpMinted, decodeNativeAmmLogDataU128Triple, reserve / total-LP / token / swap-fee-bps key helpers (nativeAmmPool.ts); tryParseNativeAmmLog2, filterMapNativeAmmRpcLogs (nativeAmmLogs.ts); constantProductAmountOut / constantProductAmountOutWithFeeBps / constantProductAmountOutNoFee / encodeNativeAmmSetTokensCalldata / encodeNativeAmmSetSwapFeeBpsCalldata / NATIVE_CP_SWAP_FEE_BPS / NATIVE_AMM_TOPIC_*_HEX / nativeAmmLogTopic0Utf8 (nativeAmm.ts; NATIVE-AMM-CALLDATA.md); LP vault — encodeNativeAmmLpVaultConfigureCalldata, buildNativeAmmLpVaultDepositAddAccessList, buildNativeAmmLpVaultDepositAddContractCallTx, merge helpers (nativeAmmLpVault.ts; NATIVE-AMM-LP-VAULT.md); LP share token — encoders + buildLpShareTokenAccessList, buildLpShareTokenContractCallTx, mergeLpShareTokenAccessListWithSimulation (nativeLpShareToken.ts; NATIVE-LP-SHARE-TOKEN.md); CANONICAL_BOING_TESTNET_NATIVE_CP_POOL_HEX (canonicalTestnet.ts) — convenience mirror of RPC-API-SPEC.md § Native constant-product AMM (bump when the on-chain canonical pool changes)
    • Native DEX (pair directory + routers) — BOING-NATIVE-DEX-CAPABILITY.md: factory calldata + access lists (nativeDexFactory.ts), fetchNativeDexFactoryPairsCount, findNativeDexFactoryPoolByTokens, Log3 parsers (nativeDexFactoryPool.ts, nativeDexFactoryLogs.ts; NATIVE-DEX-FACTORY.md); ledger-router forward calldata + tx builders v1–v3 (nativeDexLedgerRouter.ts; NATIVE-DEX-LEDGER-ROUTER.md); swap2 + multihop encoders (nativeDexSwap2Router.ts; NATIVE-DEX-SWAP2-ROUTER.md, NATIVE-DEX-MULTIHOP-SWAP-ROUTER.md); CREATE2 predictors + salts (create2.ts); tutorial deploy-native-dex-directory (examples/native-boing-tutorial README §7c2)
    • Seamless defaults + wallet glue — fetchNativeDexIntegrationDefaults / mergeNativeDexIntegrationDefaults (dexIntegration.ts): merge boing_getNetworkInfo.end_user (BOING_CANONICAL_NATIVE_CP_POOL / BOING_CANONICAL_NATIVE_DEX_FACTORY) with overrides and 6913 embedded pool fallback; fetchNativeDexFactoryRegisterLogs for chunked register_pair scans; getInjectedEip1193Provider, boingSendTransaction, requestAccounts, readChainIdHex, providerSupportsBoingNativeRpc (walletProvider.ts; BOING-DAPP-INTEGRATION.md)
    • Directory snapshot (Boing-only) — fetchNativeDexDirectorySnapshot (defaults + pairs_count + optional log backfill), pickNativeDexPoolFromRegisterLogs, resolveNativeDexPoolForTokens (logs | simulate | auto), nativeDexPairKey, suggestNativeDexRegisterLogCatchUpRange (nativeDexDirectory.ts; no external chain RPC)
    • DEX onboarding + preflight — formatBoingNativeDexNotEvmDisclaimer, describeNativeDexDefaultGaps, assertBoingNativeDexToolkitRpc, formatNativeDexToolkitPreflightForUi, buildNativeCpPoolSwapExpressTx, buildNativeDexMultihopSwapExpressTxFromRoute128 / 160, applyNativeDexMultihopSimulationToContractCallTx (nativeDexSeamless.ts); wallet copy BOING_WALLET_RPC_METHODS_NATIVE_DAPP, explainEthSendTransactionInsufficientForBoingNativeCall, connectInjectedBoingWallet, mapInjectedProviderErrorToUiMessage (walletProvider.ts)
    • CP routing + aggregation (off-chain) — quoteCpPoolSwap, rankDirectCpPools, findBestCpRoutes, pickFirstMultihopCpRoute, uniqueSortedTokenHex32FromCpRoute, minOutFloorAfterSlippageBps, encodeNativeDexMultihopRouterCalldata*FromRoute, quoteCpEvenSplitAcrossDirectPools, hydrateCpPoolVenuesFromRpc, fetchCpRoutingFromDirectoryLogs (nativeDexRouting.ts); buildNativeDexMultihopRouterAccessList, mergeNativeDexMultihopRouterAccessListWithSimulation (nativeAmmPool.ts)
    • CREATE2 address prediction — predictCreate2ContractAddress, predictNativeCpPoolCreate2Address … predictNativeCpPoolV5Create2Address, nativeCpPoolCreate2SaltV1Hex … nativeCpPoolCreate2SaltV5Hex, NATIVE_CP_POOL_CREATE2_SALT_V1 … V5 (create2.ts; matches boing_primitives::create2_contract_address / native_amm.rs; see NATIVE-AMM-CALLDATA.md § CREATE2)
    • Indexer-scale reads — getIndexerChainTips / clampIndexerHeightRange / planIndexerChainTipsWithFallback / planIndexerCatchUp (indexerSync.ts; fallback when boing_getSyncState is -32601); fetchBlocksWithReceiptsForHeightRange (replay path: full blocks + receipts; demos: fetch-blocks-range.mjs, indexer-ingest-tick.mjs); summarizeIndexerFetchGaps, mergeInclusiveHeightRanges, unionInclusiveHeightRanges, subtractInclusiveRangeFromRanges, blockHeightGapRowsForInsert, nextContiguousIndexedHeightAfterOmittedFetch (indexerBatch.ts, indexerGaps.ts; pruned gaps, D1 row shapes, archive backfill subtraction); getLogsChunked / planLogBlockChunks (≤128-block spans per RPC-API-SPEC.md); optional maxConcurrent on chunked logs and height-range fetches; mapWithConcurrencyLimit; flattenReceiptsFromBundles; fetchReceiptsForBlockHeight; fetchReceiptsForHeightRange (optional onMissingBlock: 'omit') — ingestion pseudo-flow: INDEXER-RECEIPT-AND-LOG-INGESTION.md; example DDL: tools/observer-indexer-schema.sql; JSON + SQLite ingest: examples/observer-ingest-reference (ingest-tick, ingest-sqlite-tick + BOING_SQLITE_PATH); D1 cron sample: examples/observer-d1-worker; backlog: NEXT-STEPS-FUTURE-WORK.md
    • Universal contract deploy index — rpcTransactionJsonToTransactionInput, transactionIdFromUnsignedRpcTransaction, extractUniversalContractDeploymentsFromBlock / extractUniversalContractDeploymentsFromBlockJson, CONTRACT_DEPLOY_INIT_CODE_MARKER, row types (universalContractDeployIndex.ts; shipped 0.3.1+). Optional hosted materialization + REST/SSE: HANDOFF_Universal_Contract_Deploy_Indexer.md, workers/deploy-registry-indexer.
    • Fixed contract submitter — createNativeContractSubmitter({ client, secretKey32, senderHex, contractHex, accessList? }) → .submitCalldata(bytes)
    • registerDappMetrics(hexContract, hexOwner), submitIntent(hexSignedIntent)
    • qaCheck(hexBytecode, purposeCategory?, descriptionHash?, assetName?, assetSymbol?) — pre-flight QA without submitting (same param order as node boing_qaCheck)
    • qaPoolList(), qaPoolConfig(), qaPoolVote(txHashHex, voterHex, vote, signedVoteTxHex?) — QA pool for Unsure deploys (public_membership requires a signed QaPoolVote tx)
    • getNetworkFeePolicy(), operatorApplyFeePolicy(json) — native fee split / treasury levies
    • faucetRequest(hexAccountId) — testnet only
  • BoingRpcError — code, message, data, method; isQaRejected, isQaPendingPool, pendingPoolTxHash, isQaPoolDisabled, isQaPoolFull, isQaPoolDeployerCap, qaData; toString() for logging.
  • Hex helpers — ensureHex, bytesToHex, hexToBytes, accountIdToHex, hexToAccountId, validateHex32, isBoingNativeAccountIdHex (32-byte account id check for multi-wallet wizards).

All 32-byte IDs (account, hash) are hex strings with or without 0x prefix. Invalid hex or wrong length throws before the request.

Tokens (mirrors boing token)

Deploy, mint, transfer and read the canonical reference fungible token. Output is byte-identical to the Rust CLI (see BOING-REFERENCE-TOKEN.md).

import { createClient, deployBoingToken, transferBoingToken, getBoingTokenBalance, hexToBytes } from '@boing-network/boing-sdk';

const client = createClient('https://testnet-rpc.boing.network');
const seed = hexToBytes(process.env.BOING_SECRET_HEX!); // 32-byte Ed25519 seed; never hard-code or commit it

const { tokenHex, deployerHex } = await deployBoingToken(client, seed, {
  symbol: 'TKN',
  name: 'My Token',
  initialSupply: 1_000_000n, // one-time mint_first at nonce + 1 (fixed supply)
});
await transferBoingToken(client, seed, { tokenHex, toHex: '0x…', amount: 250_000n });
console.log(await getBoingTokenBalance(client, tokenHex, deployerHex));

Pass dryRun: true (and nonce) to get { txId, signedHex } without submitting. Unsigned builders (buildBoingTokenDeployTransaction, buildBoingTokenMintTransaction, buildBoingTokenTransferTransaction) work with signTransactionInputWithSigner or a wallet.

Native AMM pools (mirrors boing pool)

Create, fund, swap with slippage protection, and read native constant-product pools (templates v1..v7). Byte-identical to the Rust CLI; see NATIVE-AMM-CLI.md, including the custody caveat (deposits and swap inputs are ledger-only in v1..v7).

import { createClient, createBoingPool, addBoingPoolLiquidity, swapBoingPool, getBoingPoolState, hexToBytes } from '@boing-network/boing-sdk';

const client = createClient('http://127.0.0.1:8545');
const seed = hexToBytes(process.env.BOING_SECRET_HEX!);
const { poolHex } = await createBoingPool(client, seed, { version: 7, feeBps: 30n });
await addBoingPoolLiquidity(client, seed, { poolHex, amountA: 10_000n, amountB: 40_000n });
await swapBoingPool(client, seed, { poolHex, direction: 'a-to-b', amountIn: 1_000n, slippageBps: 50n });
console.log(await getBoingPoolState(client, poolHex));

Submitting transactions

The node expects hex-encoded bincode-serialized SignedTransaction. Encoding matches Rust boing-primitives (bincode 1.3); see BOING-SIGNED-TRANSACTION-ENCODING.md.

Options:

  1. TypeScript (Node or bundler) — build + sign with a 32-byte Ed25519 secret key:
import {
  createClient,
  fetchNextNonce,
  buildTransferTransaction,
  signTransactionInput,
} from '@boing-network/boing-sdk';

const client = createClient('http://localhost:8545');
const senderHex = '0x' + '<64-hex of public key>';
const secret32 = new Uint8Array(32); // your signing seed / secret key bytes
const nonce = await fetchNextNonce(client, senderHex);
const tx = buildTransferTransaction({
  nonce,
  senderHex,
  toHex: '0x' + '<64-hex recipient>',
  amount: 1n,
});
const signedHex = await signTransactionInput(tx, secret32);
await client.simulateTransaction(signedHex);
await client.submitTransaction(signedHex);
  1. Injected wallet — boing_sendTransaction / boing_signTransaction in Boing Express (BOING-EXPRESS-WALLET.md).

  2. Rust CLI — cargo run -p boing-cli -- … for local dev.

  3. Custom signer — signTransactionInputWithSigner(tx, async (hash) => …) (must return 64-byte Ed25519 signature over hash).

Protocol QA: Contract deploys are checked in the mempool (boing_qa). Use qaCheck before submit and purpose-bearing deploy types from the wallet. See QUALITY-ASSURANCE-NETWORK.md.

dApp checklist: BOING-DAPP-INTEGRATION.md.

See RPC-API-SPEC.md, BUILD-ROADMAP.md, and BOING-VM-CAPABILITY-PARITY-ROADMAP.md.

Simulate → access list → submit (P4)

Use submitTransferWithSimulationRetry, submitContractCallWithSimulationRetry, or submitDeployWithPurposeFlow so the node can widen access_list when boing_simulateTransaction returns access_list_covers_suggestion: false (merges suggested_access_list via mergeAccessListWithSimulation).

import {
  createClient,
  submitTransferWithSimulationRetry,
  explainBoingRpcError,
  senderHexFromSecretKey,
  hexToBytes,
} from '@boing-network/boing-sdk';

const client = createClient(process.env.BOING_RPC_URL ?? 'http://127.0.0.1:8545');
const secret = hexToBytes(process.env.BOING_SECRET_HEX!); // 0x + 64 hex
const senderHex = await senderHexFromSecretKey(secret);

try {
  const { tx_hash, lastSimulation, attempts } = await submitTransferWithSimulationRetry({
    client,
    secretKey32: secret,
    senderHex,
    toHex: process.env.BOING_TO_HEX!,
    amount: 10n,
  });
  console.log({ tx_hash, gas: lastSimulation.gas_used, attempts });
} catch (e) {
  console.error(explainBoingRpcError(e));
}

Deploy path runs boing_qaCheck first; reject throws BoingRpcError with isQaRejected. On submitTransaction, catch BoingRpcError for mempool QA (-32050), pool (-32051), and pool caps (-32054..-32056). Code reference: BOING-RPC-ERROR-CODES-FOR-DAPPS.md.

Canonical scripts: examples/native-boing-tutorial (transfer, contract-call, deploy-minimal).

API additions (transaction flows)

  • senderHexFromSecretKey(secret32) — derive AccountId hex from signing seed.
  • submitTransferWithSimulationRetry, submitContractCallWithSimulationRetry, submitDeployWithPurposeFlow — see submitFlow.ts.
  • SimulationFailedError — simulation failed without an access-list retry path.
  • explainBoingRpcError(e) — human-readable string for BoingRpcError and QA pool codes.

Tests

cd boing-sdk && npm install && npm test

Golden vectors are tied to cargo run -p boing-primitives --example dump_bincode.

Planned

版本与发布记录

@boing-network/boing-sdk 共发布 17 个版本,首次发布于 2026/10/24;过去 12 个月发布了 17 个版本。

版本发布日期距今
0.5.40latest2026/11/062 天前
0.5.392026/11/053 天前
0.5.382026/10/2514 天前
0.5.362026/10/2414 天前
0.5.352026/10/2414 天前
0.5.342026/10/2414 天前

关于 @boing-network/boing-sdk 的常见问题

@boing-network/boing-sdk 是什么?

Seamless SDK for building on Boing Network

如何安装 @boing-network/boing-sdk?

在项目目录运行 npm install @boing-network/boing-sdk,或使用 pnpm add / yarn add / bun add。

@boing-network/boing-sdk 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@boing-network/boing-sdk 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@boing-network/boing-sdk 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@boing-network/boing-sdk 可以商用吗?

@boing-network/boing-sdk 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@boing-network/boing-sdk 的下载量有多少?

根据 npm 官方下载统计,@boing-network/boing-sdk 在 2026/10/09 – 2026/11/07 这 30 天内被下载 3,329 次,日均约 111 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@boing-network/boing-sdk 还在维护吗?

最新版本 0.5.40 发布于 2026/11/06(2 天前);至今共发布 17 个版本,其中过去 12 个月发布了 17 个;首次发布于 2026/10/24。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。