@dankest-llc/xchain-sdk

中文文档
0.27.0发布于 2026/11/01AGPL-3.0-or-laterTypeScriptCommonJS构建来源已验证近 30 天下载 2762

xchain-sdk generates XChain Platform ACTION commands and encodes them into unsigned blockchain transactions as well as pulls data from the XChain APIs such as balances and transaction history.

原始使用文档
文档目录8 节
  1. Features
  2. Documentation
  3. Install
  4. Quick Start
  5. Configuration
  6. Scripts
  7. API server module
  8. Test Suite

XChain Platform - Software Developer Kit (SDK)

npm version Tests Node License

Coverage

Developer-facing SDK for the XChain Platform: generate XChain transactions and query blockchain data.

Features

  • 31 ACTION types: sdk.send(), sdk.issue(), sdk.mint(), sdk.stake(), and 27 more convenience methods
  • Transaction lifecycle: sdk.submitAction() handles the full encode -> sign -> broadcast -> wait pipeline in one call
  • Wallet sessions: sdk.session(wif) bundles address/key/UTXO state for repeated actions from one address
  • Fee estimation: sdk.estimateFees() returns fee info without signing or broadcasting
  • UTXO chaining: in-memory UTXO cache prevents double-spend on rapid sequential transactions
  • Workflow recipes: sdk.issueAndDistribute(), sdk.deployAndFund(), sdk.stakeAndDelegate(), and more
  • Cross-chain helpers: coordinate swaps and parallel actions across BTC, LTC, and DOGE SDK instances
  • Event-driven confirmation: sdk.waitForAction(txid) resolves when the indexer processes a transaction
  • Contract settle gate: sdk.waitForContractState(index, { key: 'status', equals: 'FUNDED' }) and sdk.waitForContractBalance(index, tick, { minQuantity }) wait on the contract's own state, which is the only signal that cannot race the indexer; submitAction({ awaitContract: {...} }) runs the same gate inline, so a deposit does not hand control back before the contract has been credited
  • Interactive REPL: npm run repl drops into a live session with a pre-configured SDK instance
  • Automatic format selection: picks the smallest encoding format for every action
  • PSBT generation: integrates with xchain-encoder to produce unsigned transactions
  • 115+ explorer query methods: balances, tokens, transactions, markets, history, contracts
  • Batch builder: fluent API: await sdk.batch().send({...}).mint({...}).build() (build() is async)
  • Real-time events: WebSocket streaming with automatic reconnection and catch-up via onBlock(), onAction(), onAddress(), onToken(), onMarket(), onDispenser(), onBetFeed(), onXcall(), onAttestation(), and more; sdk.ws exposes the low-level client (subscribe(), on(), listSubscriptions(), ...) directly
  • Encrypted messaging: ECIES, ECDH, and AES encryption for MESSAGE actions; messaging.send() accepts a Buffer payload and getMessages() exposes msg.bytes for binary ECIES
  • Token-gated file publishing: sdk.gatedFile.encryptFileBytes() and sdk.gatedFile.encryptPack() produce AES-256-GCM ciphertext + key for FILE v1 gated content; key handoff as a compact 33-byte binary payload via serializeKeyPayload() / parseKeyPayload() (sent through ECIES in binary mode). See Token-Gated Content
  • Attestation envelope helpers: AttestationHelpers.llm({...}) builds the JSON envelope a VM contract passes to xchain.attestation.request(...) with provider_id 'llm'; AttestationHelpers.httpGet({url}) validates the URL and returns the payload string for 'http_get'; AttestationHelpers.requestOptions({redundancy, deadlineBlocks}) builds the gateway options object. By design these are envelope builders only: there is no user-submittable ATTEST action. ATTEST v0 (request) and v1 (response) are VM-emitted: a contract calls xchain.attestation.request(...) and validators emit the on-chain attestation. So the SDK helps you shape the request a contract makes, and you read the results via getAttestations(). It does not (and cannot) encode an ATTEST action directly, the same way XCALL is VM-emission-only.
  • Token-ownership trading helpers: ORDER/SWAP/DISPENSER v0 carry GIVE_OWNERSHIP / GET_OWNERSHIP flags; SWEEP carries independent ORDERS / SWAPS / DISPENSERS flags (was a single ESCROWS flag)
  • HTTP 402 payments: X402Client and X402Gateway implement an XChain-native, x402-shaped pay-per-call flow over on-chain SEND actions, with xchain-send (pay-per-call), xchain-dispenser (hold-to-access), and xchain-deposit (metered spend ledger) schemes; the client pays only ticks given a per-tick maxAmount ceiling and refuses every offer when none is set. See x402 Payments
  • Contract-targeted staking: session.stakeToContract({ amount, signingPubkey, targetContractIndex, tick }), session.unstakeFromContract({...}), and session.delegateForContract({...}) emit STAKE v3 / UNSTAKE v1 / DELEGATE v1 against a smart contract deployed via DEPLOY v1 (with COOLDOWN_BLOCKS + SLASH_DESTINATION). High-level recipes: sdk.deployStakeableContract() and sdk.stakeToContractAndDelegate()
  • NFT helpers: sdk.nft.unique(), sdk.nft.edition(), sdk.nft.collectionItem(), sdk.nft.attachContentParams(), and sdk.nft.isNft() for building the NFT pattern (ISSUE with DECIMALS=0 + LOCK_MAX_SUPPLY=1) plus high-level sdk.issueNft(), sdk.issueNftEdition(), sdk.issueCollectionItem(), and sdk.attachContent() submit recipes
  • Project registry helpers: sdk.project.rosterParams() and sdk.project.rosterEditParams() build LIST actions for owner-attested token rosters; sdk.setRoster() runs LIST then LINK and waits for the indexer
  • Ticker compaction: on by default; resolves token tickers to their compact ^id wire form via the explorer before encoding to shrink on-chain payload size; opt out with { compactTickers: false }
  • MCP server: npx xchain-mcp exposes all explorer query tools as Model Context Protocol tools for AI agent use
  • Wallet & auth: key management, PSBT signing, challenge-response verification
  • Smart contracts: deploy, execute, deposit, withdraw via xchain-vm integration
  • Contract identity pre-flight: a deployed contract must export meta: { name, description, version } (CONTRACT_META_REQUIRED). sdk.deploy(), session.deploy(), session.deployChunk(), sdk.deployAndFund() and sdk.deployStakeableContract() read it statically before the action is composed and refuse with the chain's own verdict string, so a contract the indexer will reject never costs a fee. sdk.contracts.getExportedMeta(source) exposes the same read
  • Hub discovery: auto-resolves service endpoints from xchain-hub
  • Retry with backoff: handles HTTP 429/502/503/504, respects Retry-After headers
  • Request hooks: onRequest, onResponse, onError, onRetry callbacks
  • TypeScript definitions: full .d.ts for IDE autocomplete
  • Browser bundle: Browserify build for client-side use

Documentation

Full SDK developer guide is published at docs.xchain.io/components/sdk:

DocumentDescription
READMEOverview, installation, usage modes
ConfigurationConstructor options, env vars, hub discovery, retry, pooling, hooks
ActionsAll 31 ACTION types: params, validation rules, format versions, examples
Transaction LifecyclesubmitAction, fee estimation, UTXO chaining, P2SH two-phase handling
Wallet SessionsBound wallet sessions, convenience methods, UTXO cache
WorkflowsHigh-level recipes: issueAndDistribute, deployAndFund, stakeAndDelegate
Cross-ChainMulti-chain coordination: parallel actions, swaps, links
ExplorerAll 115+ query methods: balances, tokens, transactions, markets
EncoderPSBT generation: encoding types, options, pre-flight validation, P2SH two-phase
Batch BuilderFluent API for multi-action transactions
ContractsVM smart contract integration: deploy, execute, deposit, withdraw
WebSocketReal-time event streaming: blocks, actions, addresses, markets
Wallet & AuthKey management, PSBT signing, challenge-response verification
MessagingECIES/ECDH/AES encryption for MESSAGE actions
Light Client (SPV)Cryptographic balance/action verification against stake-weighted checkpoints
NFT & Registry BuildersNFT pattern builders, collection/content attachment, project roster LIST/LINK
Format SelectionHow the SDK picks the optimal format version
ErrorsAll error classes, codes, and troubleshooting
ExamplesEnd-to-end code examples

Install

npm install @dankest-llc/xchain-sdk

Node 22 or newer. For development against the source, clone this repository and npm install inside it; the companion MCP server for AI agents is published separately as xchain-mcp.

Quick Start

const { XChainSDK } = require('@dankest-llc/xchain-sdk');

// Zero-config: a network alone targets the public XChain Platform.
// Mainnet/testnet default to the public hosts (hub.xchain.io discovers
// explorer/encoder, falling back to explorer.xchain.io / encoder.xchain.io);
// on any *-regtest network only the explorer defaults to localhost:8080. The
// encoder (needed for writes) needs ENCODER_URL or ENCODER_PORT, and the
// WebSocket needs a WEBSOCKET_* or EXPLORER_* URL or port (or the matching
// constructor options).
const sdk = new XChainSDK({ network: 'bitcoin-mainnet' });

// To point at your own services, pass full URLs (include the scheme; a
// bare host is treated as http://host:<dev-port>):
// const sdk = new XChainSDK({
//     network: 'bitcoin-mainnet',
//     explorerUrl: 'https://explorer.example.com',
//     encoderUrl:  'https://encoder.example.com'
// });

// Generate an action string
const result = await sdk.send({
    tick: 'MYTOKEN',
    amount: '100',
    destination: 'bc1q...',
    memo: 'Payment'
});
console.log(result.actionString); // 'SEND|0|MYTOKEN|100|bc1q...|Payment'

// Multi-destination SEND: one entry per recipient. The wire format version
// is chosen from the legs (v1 shared tick, v2 per-leg tick, v3 per-leg memo).
// A flat {tick, amount, destination} map can only ever express ONE leg, so
// the SDK refuses one against a multi-leg format instead of repeating leg 1.
const multi = await sdk.send({
    tick: 'MYTOKEN',
    legs: [
        { amount: '100', destination: 'bc1qaddr1...' },
        { amount: '250', destination: 'bc1qaddr2...' }
    ]
});
console.log(multi.actionString); // 'SEND|1|MYTOKEN|100|bc1qaddr1...|250|bc1qaddr2...'

// Full lifecycle: create, encode, sign, broadcast, wait for indexer
const tx = await sdk.submitAction(
    { action: 'SEND', params: { tick: 'MYTOKEN', amount: '100', destination: 'bc1q...' } },
    { pubkey: '02abc123...' },
    { wif: 'your-wif-key' }
);
console.log(tx.txid);    // transaction hash
console.log(tx.indexed); // action data from the indexer

// Wallet session: bind to a key and send multiple actions
const session = sdk.session('your-wif-key');
await session.send({ tick: 'MYTOKEN', amount: '50', destination: 'bc1q...' });
await session.send({ tick: 'MYTOKEN', amount: '50', destination: 'bc1q...' });
const balances = await session.getBalances();

// Workflow recipes: multi-step operations in one call
await sdk.issueAndDistribute('your-wif-key',
    { tick: 'NEWTOKEN', maxSupply: '1000000', decimals: 8 },
    [
        { destination: 'bc1qaddr1...', amount: '500000' },
        { destination: 'bc1qaddr2...', amount: '300000' }
    ]
);

// Deploy a smart contract. Every contract must export its identity: `meta.name`
// and `meta.description` are consensus-required (CONTRACT_META_REQUIRED), and
// `meta.version` is optional but indexed. Use STRING LITERALS: the chain evaluates
// `meta` at deploy, so a computed name is not what you read in the source, and the
// pre-flight cannot check it for you.
const code = `module.exports = {
    meta: {
        name:        'Escrow',                           // 1..64 bytes
        description: 'Two-party escrow with an arbiter', // 1..512 bytes
        version:     '1.0.0'                             // optional, 1..32 bytes
    },
    permissions: ['SEND'],
    initialize(xchain) { xchain.state.set('status', 'OPEN'); }
};`;
await session.deploy({ code, gasLimit: 200000 });

// A contract with no conforming meta is refused BEFORE anything is composed,
// signed or broadcast, with the exact verdict the indexer would have written:
//   SDKContractError: invalid: CONTRACT_MANIFEST (meta required)
// Pass { preflight: 'warn' | 'off' } (session/workflow seams) or
// { lint: 'warn' | 'off' } (sdk.deploy) to downgrade or skip the check; the
// deploy is still rejected on-chain. A computed or unreadable `meta` only warns.
sdk.contracts.getExportedMeta(code);  // { status: 'present', name: 'Escrow', ... }

// Query blockchain data. The token record arrives NESTED under `info`:
const token = await sdk.getToken('MYTOKEN');
token.info.tick_id;   // '42'   <- the fields live here
token.tick_id;        // undefined

// A tick that does not exist answers HTTP 404, so getToken() THROWS
// SDKExplorerError (code EXPLORER_HTTP_404) instead of answering an empty
// body. Use these for an existence check rather than a try/catch:
await sdk.tokenExists('MYTOKEN');   // true / false, never throws on absence
await sdk.findToken('MYTOKEN');     // the unwrapped info record, or null

// Both answer "absent" only for the 404. A timeout, network failure, 429 or
// 5xx still throws, because an explorer that could not answer is not proof
// that the ticker is free.

Configuration

VariableRequiredDefaultDescription
NETWORKYes(none)Default coin and network (e.g. bitcoin-regtest, dogecoin-mainnet)
SDK_API_PORTNo3005Port for the optional SDK helper API
SDK_API_KEYNo(none)API key for the helper API; required as Authorization: Bearer <key> on every method except ping (methods reject with 401 when unset)
CORS_ORIGINNoDisabledCORS allowed origin for the helper API
SDK_API_MAX_BATCHNo20Maximum JSON-RPC calls in one array (batch) body. Anything other than a positive whole number (1e3, 50abc, 0, -5) falls back to 20 and logs a warning at startup; no value disables the cap
SDK_API_RATE_LIMITNo300Requests per window per credential (per source address when unauthenticated). A non-numeric or negative value falls back to 300; an explicit 0 disables the limiter and is the only way to turn it off
SDK_API_RATE_WINDOW_MSNo60000Length of the fixed rate-limit window, in milliseconds. Anything other than a positive whole number of milliseconds (60s, 1e5, 1.5, 0) falls back to 60000 and logs a warning at startup
EXPLORER_URL / EXPLORER_PORTNo127.0.0.1 / 8080xchain-explorer location. An explorerPort option given without a URL points the explorer and its WebSocket at localhost on every network and pins them against hub discovery. The helper API and the REPL pass EXPLORER_PORT in as that option, so there, on mainnet and testnet, EXPLORER_PORT without EXPLORER_URL points at localhost; in library use, EXPLORER_PORT alone leaves the public explorer in place
ENCODER_URL / ENCODER_PORTNo127.0.0.1 / 3003xchain-encoder location
ENCODER_API_KEYNo(none)API key sent as x-api-key to an xchain-encoder whose operator set API_KEY; also settable per instance as the encoderApiKey option. Only an encoderUrl or encoderPort constructor option pins the encoder: without one, hub discovery can repoint the encoder client and the key then goes to whatever encoder host the hub names. An encoderPort option given without a URL points the encoder at localhost on every network. The helper API (npm run api) and the REPL (npm run repl) pass ENCODER_URL and ENCODER_PORT in as those options, so there either one pins; in library use, the variables alone do not. Treat as a credential
HUB_URLNo(none)Full xchain-hub URL read only by the REPL (npm run repl), where it takes precedence over HUB_API_HOST; the library and the helper API ignore it
HUB_API_HOST / HUB_PORTNohttps://hub.xchain.io/<COIN> on mainnet and testnet; no hub on regtestxchain-hub location read by the library and the helper API. Takes a bare host (joined with HUB_PORT, default 10000) or a full http:// or https:// URL, in which case HUB_PORT is ignored. The helper API passes HUB_PORT in as the hubPort option, so there, on mainnet and testnet, HUB_PORT without HUB_API_HOST points at a hub on localhost; in library use, HUB_PORT alone leaves the public hub in place
HUB_API_KEYNo(none)API key for getallconfigs against keyed hubs; public zero-config discovery should use the hub's chain-registry endpoint instead
WEBSOCKET_URL / WEBSOCKET_PORTNo127.0.0.1 / 3007Explorer WebSocket endpoint for live updates. A bare host is joined with WEBSOCKET_PORT; a full ws:// or wss:// URL is used as given, and a full http:// or https:// URL becomes ws:// or wss://, with no port added in either case

Scripts

CommandDescription
npm run apiStart JSON-RPC server (port from SDK_API_PORT, default 3005)
npm testRun unit tests (6,351 tests)
npm run replStart interactive REPL with a pre-configured SDK instance
npm run buildProduction browser bundle -> dist/xchain_sdk.min.js
npm run build:devDevelopment browser bundle -> dist/xchain_sdk.js

API server module

npm run api (node ./src/api/index.js) runs the JSON-RPC server as a standalone process, opening a listener on SDK_API_PORT at load. A consumer that wants to own the server instead, mounting it under an existing express app, choosing its own listen path, or starting and stopping it from a test, requires the module directly rather than shelling out to the script:

const { createApp, startApi } = require('@dankest-llc/xchain-sdk/src/api');

// createApp(sdk) is synchronous and listener-free: it wires the same guard
// stack (rate limit, auth gate, batch cap, /openrpc.json, JSON-RPC router)
// as the CLI entry and returns the express app to mount yourself.
const app = createApp(sdk);

// startApi({ port }) builds the SDK from the environment, runs hub discovery,
// and resolves to the listening http.Server (port 0 for an ephemeral port).
const server = await startApi({ port: 0 });
await new Promise((resolve) => server.close(resolve));

Requiring src/api never opens a socket; only the CLI entry (npm run api / node ./src/api/index.js) starts listening automatically.

Test Suite

TypeTests
Unit: actions, validators, format selection, convenience methods, explorer, encoder, retry, WebSocket, wallet, auth, contracts, co-signer3206+
Integration: cross-module flows, VM/contract integration, hub discovery98+
Security: input attack surface, auth gates18+
Regression: curated critical-path suite, including round-trip serialize -> parse -> verify23+
Boundary: exact encoding limits35+
Fuzz: garbage types, unicode, prototype pollution65+
Chaos: malformed responses, HTTP errors, timeouts27+
Smoke: boot API server, end-to-end JSON-RPC9+
Performance3
Total3484+

Copyright © 2025-2026 Dankest, LLC

Based on XChain Platform by Dankest, LLC – https://dankest.llc

Licensed under the GNU Affero General Public License v3.0 (AGPL-3.0-or-later) with a commercial license available for proprietary use.

You may use, modify, and distribute this material under the terms of the License. See LICENSE and NOTICE for full terms. See the licensing overview.

版本与发布记录

@dankest-llc/xchain-sdk 共发布 26 个版本,首次发布于 2026/08/02;过去 12 个月发布了 26 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.27.0latest2026/11/0110 天前
0.26.22026/10/2220 天前
0.26.12026/10/2220 天前
0.26.02026/10/2121 天前
0.25.02026/10/1923 天前
0.23.02026/10/1230 天前

关于 @dankest-llc/xchain-sdk 的常见问题

@dankest-llc/xchain-sdk 是什么?

xchain-sdk generates XChain Platform ACTION commands and encodes them into unsigned blockchain transactions as well as pulls data from the XChain APIs such as balances and transaction history.

如何安装 @dankest-llc/xchain-sdk?

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

@dankest-llc/xchain-sdk 支持 TypeScript 吗?

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

@dankest-llc/xchain-sdk 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@dankest-llc/xchain-sdk 需要什么版本的 Node.js?

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

@dankest-llc/xchain-sdk 可以商用吗?

@dankest-llc/xchain-sdk 使用 AGPL-3.0-or-later 许可。最严格的 Copyleft:除分发外,通过网络向用户提供基于它的服务也需要开源对应源码。闭源 SaaS 使用前务必评估。以上为概括,不构成法律意见,请以许可原文为准。

@dankest-llc/xchain-sdk 的下载量有多少?

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

@dankest-llc/xchain-sdk 还在维护吗?

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