Conversation
|
@sirdeggen is attempting to deploy a commit to the Coinbase Team on Vercel. A member of the Team first needs to authorize it. |
Add new @x402/bsv mechanism package implementing the exact payment scheme for the BSV blockchain, including client, server, and facilitator scheme implementations with unit and integration tests. - Add scheme_exact_bsv.md spec and reference it from scheme_exact.md - Wire BSV into advanced client, server, and facilitator all_networks examples - Add scoped npm publish workflow and changeset for the new package Signed-off-by: Deggen <d.kellenschwiler@bsvassociation.org>
e96ec4c to
ecb9235
Compare
On (1) — network identifiersAgree with names over One wrinkle worth pinning while it's cheap: On (3) — strict amount equalityKeep rule 6 exact. From designing a BSV merchant gateway on WooCommerce, I'd argue the case for equality in a machine protocol is stronger than just "defensible." The core reason isn't tolerance bands — it's that a checkout has out-of-band recovery a 402 exchange doesn't. In my gateway an overpayment becomes "contact the customer to arrange a refund," and an underpayment becomes "waiting for the remaining amount," which only resolves because a reused address lets the buyer top up or the storeowner steps in. A machine-to-machine 402 has neither channel: the payer builds one funding tx to a unique derived output and that's the whole conversation. Tolerating a mismatch there doesn't degrade gracefully, it produces a state with no automated resolution. Equality means the only outcomes are "paid" and "retry" — which is what you want when there's no human in the loop. Where my own code does tolerate a shortfall, it's context-specific rather than a global policy: a background poller watching a reused address slackens by The drift one would otherwise use a tolerance band to absorb — price/FX movement between quote and pay — is better handled the way this scheme already does it: pin the amount at challenge issuance, bound it with the freshness window, and fold any buffer into the quoted price. It's a quote-validity lever, not an accepted-amount lever. Strict equality + the 30s / On conformance / test vectorsA note for when the Go/Python ports arrive. The pieces that already have test vectors are BRC-42 key derivation (the sample vectors in the BRC-42 spec) and the BRC-100 wire format (vectors live with that project). What has none yet is the part this PR newly adds: the exact-amount check at I've spent a good amount of time working in a Rust port of the BRC-100 wallet-toolbox, so the replay/internalize path in particular is familiar. Happy to help put together a small known-answer fixture for just those new rules as a follow-up, once there's a second implementation to check against. |
|
Wrinkle on network is fair. Perhaps we just register them all now. mainnet I think no one is using stn since Teranode. We also have mockchain in some software. Which is modern regtest with spv, but neither are needed for this which would only make sense if there is some network being used. So perhaps just adding two additional networks would suffice. |
Add security and correctness hardening to the BSV exact scheme: - Enforce BSV-only asset: reject non-BSV PaymentRequirements.asset at verify - Require the BRC-29 derivation prefix to base64-decode to at least 8 bytes - Add optional spvOnVerify callback to SPV-check the BEEF at verify time, closing an unfunded-BEEF DoS surface (settle stays authoritative) - Size the duplicate-settlement dedup TTL to the full settlement window (paymentWindow + maxTimeoutSeconds + margin) with a fixed floor, so a replay cannot outlive re-verification - Roll back the dedup mark on soft wallet rejection so a valid retry is not falsely flagged as a duplicate - Validate explicit satoshi amounts (positive integer within supply) at parse time on the server scheme Docs: note single-network scheme registration, dedup persistence/sticky-session requirements, and float-conversion trade-off. Add unit tests covering all new paths. Signed-off-by: Deggen <d.kellenschwiler@bsvassociation.org>
Registering them explicitly now seems right — naming a network later is much cheaper than migrating clients that already guessed. One implementer data point, since we're running a plain-P2PKH exact mode on mainnet today: we currently emit Agree on skipping mockchain/regtest — there's nothing to pay on. |
Align BSV network identifiers with ChainAgnostic namespaces#190: bsv:mainnet, bsv:testnet, bsv:ttn, bsv:tstn. Map CAIP-2 ids to BRC-100 wallet network names, and require clients/facilitators to refuse ambiguous Bitcoin-family (bip122 genesis) identifiers rather than defaulting them to BSV.
Network identifiers updateFollowing the discussion on registering the Teranode test networks explicitly (and @andyrowe’s note that ambiguous Bitcoin-family IDs are an unrecoverable footgun), this PR is now aligned with ChainAgnostic/namespaces#190: Registered CAIP-2 networks
Ambiguous The spec and TypeScript reference now require clients/facilitators to refuse ambiguous Bitcoin-family identifiers (including genesis-only Implementation notes
Namespaces PR updated in lockstep: ChainAgnostic/namespaces#190 |
Resolve conflicts with upstream main (ALGORAND_TESTNET_CAIP2 import and Starknet safety appendix) while keeping BSV exact-scheme support.
|
nice |
|
x402 for sure will live up to its aim; include everyone, so I’m sure this will be added without any fuzz. |
|
Extending the already class leading x402 support! Yeah! |
|
X402 |
|
good |
|
BSV! |
|
+1 on getting this merged. We have users and use cases lined up ready to build on x402 payments over BSV as soon as it lands. |
|
gm |
|
This is a well-structured and detailed PR @sirdeggen |
|
It is obviously right to have good BSV support because BSV has proof-of-concept tested over 1 million peer-to-peer transactions per second, and has very low transaction fees. |
|
Really thorough write-up — you clearly went deep on the BRC-121 → x402 mapping rather than bolting on a generic "chain #N" integration. A few things that stand out: Explicit registration of bsv:ttn and bsv:tstn alongside bsv:mainnet / bsv:testnet, together with the hard refusal of ambiguous bip122 (genesis-hash) identifiers, is the correct hardening. Paying the right amount on the wrong chain is unrecoverable in an automated protocol. The divergence from BRC-121's overpayment tolerance to strict amount equality is well-justified for machine-to-machine flows. Equality produces only two terminal states ("paid" or "retry"), which is exactly the contract an automated agent needs. Pinning the amount at challenge time and bounding it with the freshness window is the cleaner composition. Keeping the facilitator as the recipient's own BRC-100 wallet preserves the core privacy property (the identity key never appears on-chain) and eliminates custody risk. The optional spvOnVerify callback is a useful early filter. Citing the specific BRC standards (BRC-121, BRC-29, BRC-42, BRC-100, BRC-69, BRC-94) and showing how they compose end-to-end is a strong signal that the underlying specs were actually read. 103 unit tests + live integration smoke is solid. Known-answer vectors for the exact-amount check at outputIndex, the ms timestamp in the derivation suffix (+ freshness edges), and the replay signals (txid dedup TTL + isMerge / no-new-satoshis) would help future Go/Python ports. The Key Linkage Revelation & Auditability appendix (BRC-69/BRC-94) is a thoughtful addition, especially for regulated-asset use cases. |
|
x402 on BSV is the only viable solution despite any surrounding politics, imo. |
|
Great job Deggen! AI will find BSV the undeniably optimal choice for machine 2 machine economies. |
|
I'd like to see this merged. |
|
Quick update on the network-identifier question flagged above: the CAIP-2 registration this PR was waiting on just merged — ChainAgnostic/namespaces#190 (2026-08-18). So As an interop datapoint (not a competing proposal): we switched our live BSV x402 service over to emit |
# Conflicts: # examples/typescript/facilitator/advanced/all_networks.ts
Upstream added required defaultAssetTransferMethod/paymentFlows to SchemeNetworkServer and widened MoneyParser's amount param to string | number (and parseMoneyString now returns a string). Update the BSV exact scheme and money parser to match.
andyrowe
left a comment
There was a problem hiding this comment.
LGTM, approving. Confirmed this tracks the upstream SchemeNetworkServer/MoneyParser changes cleanly — defaultAssetTransferMethod = "default" + the single authorization flow lines up with the other non-EVM mechanisms (near/aptos/hedera/keeta), and widening the WhatsOnChain parser to string | number keeps the guards intact (empty string → 0 and non-numeric → NaN are both still rejected).
One non-blocking note: the fork's CI is sitting at action_required, so unit/lint haven't actually run on this commit. — might be worth kicking off the workflow so it's green on record before merge.
A wallet-less, publicly-verifiable profile for HTTP 402 settlement on BSV using plain P2PKH payments to a per-invoice address. Any BSV holder can pay (no BRC-100 wallet, BRC-42 derivation, identity key, or BEEF), and settlement is verifiable by any third party from public chain data alone. Complements x402-foundation/x402#2890 (BRC-29/42 mode) rather than competing with it. Backed by a live mainnet reference implementation at bsv.cx and a captured real settlement transaction. Adds the file to the root and payments indexes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A wallet-less, publicly-verifiable profile for HTTP 402 settlement on BSV using plain P2PKH payments to a per-invoice address. Any BSV holder can pay (no BRC-100 wallet, BRC-42 derivation, identity key, or BEEF), and settlement is verifiable by any third party from public chain data alone. Complements x402-foundation/x402#2890 (BRC-29/42 mode) rather than competing with it. Backed by a live mainnet reference implementation at bsv.cx and a captured real settlement transaction. Adds the file to the root and payments indexes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A wallet-less, publicly-verifiable profile for HTTP 402 settlement on BSV using plain P2PKH payments to a per-invoice address. Any BSV holder can pay (no BRC-100 wallet, BRC-42 derivation, identity key, or BEEF), and settlement is verifiable by any third party from public chain data alone. Complements x402-foundation/x402#2890 (BRC-29/42 mode) rather than competing with it. Backed by a live mainnet reference implementation at bsv.cx and a captured real settlement transaction. Adds the file to the root and payments indexes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Pre-existing formatting issue caught by lint:check; auto-fixed via eslint --fix (whitespace only, no behavior change).
ChainAgnostic/namespaces#190 merged on 2026-08-18. Point the spec, package README, and network-constant comments at the registered bsv/caip2.md instead of describing registration as in progress. Signed-off-by: Deggen <d.kellenschwiler@bsvassociation.org>
The text merge of upstream/main left a stale vitest resolution entry for @x402/bsv. Regenerating via pnpm install fixes it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CnGKX5y5ib3oMZcxRGSeZe
# Conflicts: # e2e/pnpm-lock.yaml # examples/typescript/clients/advanced/all_networks.ts # examples/typescript/clients/advanced/package.json # examples/typescript/facilitator/advanced/all_networks.ts # examples/typescript/facilitator/advanced/package.json # examples/typescript/pnpm-lock.yaml # examples/typescript/pnpm-workspace.yaml # examples/typescript/servers/advanced/all_networks.ts # examples/typescript/servers/advanced/package.json # typescript/.changeset/config.json # typescript/pnpm-lock.yaml
Summary
Adds BSV (Bitcoin SV) as an x402 payment mechanism for the
exactscheme: a new@x402/bsvpackage (client / server / facilitator), a per-chain spec, example wiring, and a USD price feed. It builds on the BRC-121 "Simple 402 Payments" flow (BRC-29 payments over BRC-42 key derivation) already used in production BSV tooling.Per CONTRIBUTING's new-chain process this PR is the spec + TypeScript reference implementation; Go/Python ports would follow once this is accepted. The CAIP-2
bsvnamespace is registered (ChainAgnostic/namespaces#190, merged 2026-08-18; spec: bsv/caip2.md).How BRC-121 maps onto x402
payTo= the recipient wallet's BRC-100 identity public key. It never appears on chain — every payment pays a fresh key derived from it (BRC-42), so on-chain observers cannot link payments to the payee.{ transaction (base64 BEEF), derivationPrefix, derivationSuffix, senderIdentityKey, outputIndex }. The suffix decodes to a Unix-ms timestamp (BRC-121 freshness).createAction— the payer covers the miner fee, so there is no facilitator gas sponsorship.verifychecks structure, wallet-chain agreement, freshness, exact amount, and the derived destination;settleinternalizes the output viainternalizeAction, backed by a txid dedup cache plus the wallet'sisMergesignal for replay defense. (Either counterparty can voluntarily prove a payment's linkage viarevealSpecificKeyLinkage— BRC-69, verifiable through BRC-94's Schnorr ZKP — see the spec's auditability appendix and note 2 below.)bsv:mainnet/bsv:testnet/bsv:ttn/bsv:tstn.What's included
@x402/bsv(typescript/packages/mechanisms/bsv), modeled on the Concordium mechanism:exact/client— derives the per-payment key and builds the funded BEEF paymentexact/facilitator— verifies and settles into the recipient walletexact/server— buildsPaymentRequirementswith satoshi price parsing (8 decimals)createWhatsOnChainMoneyParser— converts USD prices ("$0.001") to satoshis via the WhatsOnChain exchange-rate API (60 s cache, single-flight refresh, bounded stale fallback)Spec:
specs/schemes/exact/scheme_exact_bsv.md(fullexact-on-BSV spec with a Key Linkage Revelation & Auditability appendix), plus BSV safety invariants added to the sharedscheme_exact.mdappendix.Examples: all three
all_networksexamples wired —BSV_WALLET=true+ a running BRC-100 wallet (e.g. BSV Desktop)BSV_SERVER_PRIVATE_KEY+BSV_WALLET_STORAGE_URLvia@bsv/simpleServerWalletBSV_IDENTITY_KEY, priced in USD through the money parserSecurity
Key facilitator invariants (also in the spec's Critical Validation Requirements):
verifyderives the expected BRC-42 key (getPublicKeyforSelf) and matches it against the P2PKH output, so an unfundable or mispaid BEEF is rejected before any resource work runs.atomicTxid, i.e. exactly the transaction the wallet will internalize (not "the last tx in the BEEF").requirements.amount(stricter than plain BRC-121, which tolerates overpayment).maxTimeoutSecondsso slow handlers don't void a valid payment.isMerge(a wallet-toolbox extension, not core BRC-100);verifyre-runs at settlement.getNetwork()against the requested network;transactionis empty on any failure per the core v2 schema.Testing
pnpm testin the package) — payload construction, verify/settle rules, Atomic BEEF subject resolution, replay paths, timestamp windows, and the rate-feed parser (cache / stale / error paths).BSV_INTEGRATION=true pnpm test:integrationwith a BRC-100 wallet running (create → verify → settle → replay-reject); requires a funded wallet.Notes for reviewers
bsv:mainnet/bsv:testnet/bsv:ttn/bsv:tstnuse human-readable network names (following thecasperCAIP-2 precedent). Thebsvnamespace has been registered (ChainAgnostic/namespaces#190, merged 2026-08-18; spec: bsv/caip2.md).bip122could alternatively identify BSV by its fork-block hash (as it does for Bitcoin Cash); happy to switch the network IDs if that's preferred.exactdiverges from BRC-121's overpay tolerance; documented in the spec.AI-usage disclosure (per CONTRIBUTING): the implementation, tests, spec, and this description were drafted with AI assistance (Claude Code) and reviewed by the author before submission; an AI-driven adversarial review pass produced 24 fixes now folded into the branch.