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

@optnlabs/x402-bch

v0.1.0

Published

Standalone TypeScript Bitcoin Cash exact payment mechanism for x402

Readme

@optnlabs/x402-bch

This package is distributed as ESM because its Libauth dependency is ESM-only. Use import or dynamic import() from Node.js and bundlers; CommonJS require() is not supported.

Bitcoin Cash support for x402 v2 exact payments. BCH payments carry a complete, client-signed transaction rather than an account authorization.

The public x402 network identifiers are bch:bitcoincash (mainnet) and bch:bchtest (Chipnet). The wallet-facing transaction request uses the corresponding network names mainnet and chipnet.

The package supports native BCH and CashTokens, including fungible tokens and NFTs, with P2PKH, P2SH20, and P2SH32 payment outputs. Libauth is used for BCH transaction parsing, serialization, signing serialization, CashToken data, and address/script handling. Merchant and provider address boundaries accept CashAddr and legacy Base58Check P2PKH/P2SH20 addresses; CashToken merchant payments require a token-aware CashAddr. CashScript contracts are represented by their compiled locking bytecode; x402 pays the contract output but does not execute or validate the contract's later spending conditions.

BCH transaction model

Unlike account-based networks, BCH does not have a balance, nonce, or facilitator-side transfer call. A wallet must construct a state transition:

consume selected UTXOs
  -> required merchant output (BCH and optional CashToken state)
  -> one or more BCH/token change or application outputs
  -> optional OP_RETURN metadata
  -> miner fee

The wallet owns UTXO discovery, selection and reservation, fee calculation, change-address selection, signing, and broadcast. The x402 client owns the payment protocol and validates the wallet's returned transaction before placing it in the payment payload. Mnemonics and private keys remain inside the wallet adapter and are not part of the x402 client API.

The facilitator fetches authoritative source outputs from its provider and checks input/output value, complete CashToken state conservation, signatures, network, payment output, fee/dust policy, and transaction identity before broadcasting the same raw transaction. It does not add inputs, rewrite outputs, or create BCH change after signing.

The exact-payment validator requires exactly one matching merchant output, but it may carry additional wallet or application outputs up to the configured policy limit. Additional outputs may use P2PKH, P2SH20, P2SH32, other valid BCH locking bytecode, or OP_RETURN metadata. CashToken state is conserved across all inputs and outputs, including unrelated token categories selected by a wallet. Token genesis, minting, burning, and unrelated NFT capability changes are not implicitly authorized by an exact payment.

Client

import type { BchWallet } from '@optnlabs/x402-bch';
import { ExactBchScheme } from '@optnlabs/x402-bch/exact/client';

client.register('bch:*', new ExactBchScheme(signer, provider));

For a low-level integration, BchSigner signs BCH sighash digests and BchProvider supplies UTXOs and authoritative source outputs. For a normal wallet integration, implement BchWallet.createPayment(request) and let the wallet perform the complete transaction construction and signing:

const wallet: BchWallet = {
  async createPayment(request) {
    // Select and reserve UTXOs, add BCH/token change, and sign locally.
    return walletBackend.createSignedBchTransaction(request);
  },
};

const clientScheme = new ExactBchScheme(wallet, provider);
client.register('bch:*', clientScheme);

BchTransactionRequest contains network, recipient.address, and value, the BCH satoshis assigned to the merchant output. For a fungible CashToken, token.amount contains the token quantity and token.category contains the category. For an NFT it additionally contains nft.capability (none, mutable, or minting) and its commitment; an empty commitment is valid. Token-bearing P2PKH outputs use a conservative default of 687 satoshis for standardness, while native BCH outputs use the 546-satoshi default. Wallets may receive a different explicit value when the payment requirements specify one.

BchSigner is retained for integrations that already own UTXO selection and transaction construction. FulcrumProvider implements the Electrum Cash JSON-RPC boundary. Facilitators should inject a shared BchSettlementStore when running more than one process.

The adapter accounts for Fulcrum's two amount encodings: verbose transaction outputs are BCH decimal values, while blockchain.scripthash.listunspent returns integer satoshis.

The package test suite includes deterministic local fixtures such as test/fixtures/bch-exact-p2pkh.json. They cover the serialized transaction, source output, merchant value, payer, transaction ID, and fee without requiring another repository or external service.

Electrum endpoint redundancy

The FulcrumProvider accepts an injected FulcrumTransport; it does not silently select or trust a public server. For live deployments, applications should configure a failover transport with more than one endpoint and prefer TLS (port 50002) or WSS (port 50004) where available. The following set is the BCH Electrum set referenced by CashScript's network-provider sources and migration notes:

| Network | Endpoints | | ------- | -------------------------------------------------------------- | | Mainnet | bch.imaginary.cash, blackie.c3-soft.com, electroncash.dk | | Chipnet | chipnet.bch.ninja |

FailoverFulcrumTransport provides the minimum sequential failover behavior: pass it caller-created transports in the desired order. It retries all requests, including broadcasts; if a broadcast response is lost after the server accepts a transaction, applications must reconcile the result by checking transaction status rather than assuming the broadcast failed.

const transport = new FailoverFulcrumTransport([primaryTransport, secondaryTransport]);
const provider = new FulcrumProvider('bch:bitcoincash', transport);

Availability redundancy is not chain verification. A failover transport may retry a request against another server, but applications should compare chain tip/header data across independent servers when making operational decisions.

Endpoint availability and chain consistency are deployment concerns and should be revalidated by each operator. Do not disable certificate validation for a failover endpoint.

Facilitator

import { ExactBchFacilitatorScheme } from '@optnlabs/x402-bch/exact/facilitator';

facilitator.register(
  'bch:*',
  new ExactBchFacilitatorScheme(provider, {
    settlementStrategy: { kind: 'confirmations', count: 1 },
  }),
);

Mempool/0-conf mode is opt-in. The noDoubleSpendProof strategy accepts an unconfirmed transaction only while the provider reports no BCH double-spend proof; a proof is conflict evidence, not confirmation.

Server

import { ExactBchServerScheme } from '@optnlabs/x402-bch/exact/server';

server.register('bch:*', new ExactBchServerScheme());

Use { amount: '1000', asset: 'BCH' } for a 1,000-satoshi native BCH price. CashToken requirements use the token category as asset and describe the fungible/NFT state in extra.token with extra.assetTransferMethod: 'cashtoken'. Amounts are decimal strings in the x402 wire objects; wallet-facing amounts are converted to bigint. NFT-only requirements use a token amount of 0 plus the NFT capability and commitment.

Network and settlement notes

bch:bitcoincash and bch:bchtest are distinct networks. A mainnet address, UTXO, provider, or transaction must never be reused for Chipnet. maxTimeoutSeconds is an HTTP/resource acceptance window; it is not a BCH transaction expiry.

The facilitator can use mempool, no-double-spend-proof, or confirmation-count settlement strategies. Mempool/0-conf acceptance is an explicit deployment choice, not a confirmation. A broadcast whose status is temporarily unknown must be reconciled by transaction ID rather than blindly rebuilt, because BCH inputs are discrete outpoints and a retry can conflict with the original transaction.

Scope boundary

This package supports exact upfront payments. It does not turn x402 into a general CashScript compiler or contract protocol, provide facilitator fee sponsorship, or implement account-style upto debits. Libauth validates P2SH20/P2SH32 input programs when the provider supplies their source outputs; application-specific covenant successor rules remain an explicit extension. PSBT, hardware-wallet transport, WalletConnect, address discovery, UTXO reservation, and recovery from wallet storage remain wallet/application responsibilities; the finalized raw transaction is the x402 settlement object.

Examples

The examples/ directory keeps each integration concern in a separate file and uses common.ts for shared network, wallet, and provider helpers:

| Example | Covers | | ---------------------------------------------- | -------------------------------------------------------- | | client.ts | Wallet-agnostic x402 client integration | | native-signer-client.ts | Low-level signer-backed client and HD mnemonic boundary | | cashtoken-client.ts | Fungible and NFT CashToken requests | | payment-request-shapes.ts | Native, fungible-token, and NFT wallet requests | | cashscript-p2sh32.ts | CashScript/P2SH32 payment destinations | | address-formats.ts | CashAddr, token-aware, P2SH, and legacy address handling | | transaction-primitives.ts | Libauth transaction serialization and signing hashes | | payment-validation.ts | Provider-backed VM and payment validation | | script-toolkit.ts | Script classification and P2PKH input verification | | settlement-store.ts | Idempotent settlement claims and conflicts | | hd-discovery.ts | Gap-limited receive/change address discovery | | walletconnect-adapter.ts | WalletConnect-style fully signed transaction adapter | | networks-and-hd-wallet.ts | Mainnet/Chipnet and BIP44 receive/change derivation | | provider-failover.ts | Multiple Fulcrum transport endpoints | | server.ts and server-pricing.ts | Resource server registration and BCH/token pricing | | facilitator.ts and facilitator-policies.ts | Confirmation, mempool, and double-spend-aware settlement | | utxo-wallet-lifecycle.ts | Reservation, broadcast, and failure recovery | | http-payment-flow.ts | Framework-neutral 402 retry boundary |

Typecheck them with:

npm run typecheck:examples