Repository navigation
fix(wallet-toolbox): send and return BEEF as bytes so negotiated binary JSON carries it - #774
Merged
ty-everett merged 12 commits intoOct 10, 2026
Merged
Conversation
…ry JSON carries it binaryRequests encodes only Uint8Array values, but the toolbox built its largest storage payloads as number[]: StorageClientBase.createAction set inputBEEF from pruned.toBinary(), and the signer's internalizeAction passed ab.toBinaryAtomic(txid). They travelled as JSON number arrays even with binary negotiated, and a BEEF over ~100 KB exceeded the auth middleware's 100,000-value request limit. Use the SDK's toUint8Array() / toUint8ArrayAtomic() for createAction and no-send-expiry inputBEEF and internalizeAction AtomicBEEF, and return listOutputs BEEF, createAction sourceTransaction and competingBeef as Uint8Array from Knex storage. BEEF and AtomicBEEF already allow Uint8Array, and the server's byte validation accepts it. Legacy peers that have not negotiated binary still receive number arrays.
BRC-177 Prefunding step 2 requires the anchor to be large enough both to fund the protected action and to be reclaimed, net of a reclaim fee. The anchor was sized for the protected action only, so value-neutral actions (e.g. a 1-sat token transfer) were refused because the anchor could not pay for its own reclaim. Size the anchor as the larger of the protected action's need and the reclaim floor (reclaim fee plus minimum reclaim output). The protected action carries no change, so the funding planner now runs with a zero change cap and pays any surplus as fee. generateChangeSdk accepts maxChangeOutputs: 0 to mean "create no change". Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R53QzSzGv4LkfmxBd4URiD
Replace the "maxChangeOutputs: 0 means no change" overload with a dedicated GenerateChangeSdkParams.surplusToFee flag. When set, the planner creates no change output and pays any surplus beyond the required fee as fee. maxChangeOutputs keeps its original rule (minimum 1, default 8); the BRC-177 protected branch goes back to a cap of 1 and sets surplusToFee. The protected funding plan is the only setter. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R53QzSzGv4LkfmxBd4URiD
Compute the change-output cap as before, then zero it when surplusToFee is set. No behaviour change (SonarCloud typescript:S3358). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R53QzSzGv4LkfmxBd4URiD
… JSON StorageServer converts the byte columns of findOutputsAuth and findProvenTxReqs results when the client negotiated binary JSON, as it already does for getSyncChunk. Clients convert them back to number[] in validateEntities. Restore competingBeef to number[] in createAction's WERR_REVIEW_ACTIONS. Thrown errors are serialized with stringifyBRC100, so it never reached the binary codec.
shruggr
marked this pull request as ready for review
October 3, 2026 22:49
shruggr
requested review from
BraydenLangley,
sirdeggen,
tonesnotes and
ty-everett
as code owners
October 3, 2026 22:49
shruggr
added a commit
to yours-org/yours-wallet
that referenced
this pull request
Oct 4, 2026
Binary BEEF over negotiated binary JSON (bsv-blockchain/ts-stack#774), BRC-169 handle payments.
ty-everett
approved these changes
Oct 10, 2026
# Conflicts: # docs/reference/package-api-migrations.md # governance/package-release-notes.json # packages/wallet/wallet-toolbox/CHANGELOG.md
ty-everett
marked this pull request as draft
October 10, 2026 23:30
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
ty-everett
marked this pull request as ready for review
October 10, 2026 23:41
ty-everett
approved these changes
Oct 10, 2026
This was referenced Oct 11, 2026
Draft
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Program and scope
Compact BEEF transport uses the existing negotiated binary JSON codec for signer/internalization bytes, create-action/expiry request BEEF, Knex response BEEF/source transactions, and schema-declared row bytes. Older peers retain numeric-array JSON and identical transaction/proof content. Authentication, request/response ceilings and arbitrary numeric-array values are preserved.
Integrated qualified #775 and current main. Exact reviewed head:
9c28e5037a71d959d76fd00a0655489f0d803d54. The main integration changed ancestry only: the candidate tree remained identical.Impact
Verification
pnpm health:check,pnpm lint,pnpm format:check,pnpm build,pnpm typecheck,pnpm audit:security,pnpm docs:build: passed; zero high/critical advisories.pack:checkcontracts passed, including exports/declarations/source maps/publint/strict type resolution and clean consumers.git diff --checkpassed. Generated test reports excluded.Hosted CI 38095324610, conformance 38095324644 and CodeQL 38095324668 passed on the exact head. Aggregate and merge gates, Sonar zero-findings, Socket and patch coverage passed; expected scope skips were validated by the merge gate.
Security and dependencies
Release and operations
Completion evidence
Original implementation explanation
With binary JSON negotiated, the storage client and server still sent their largest byte fields as JSON number arrays. The codec only encodes
Uint8Arrayvalues, and these fields werenumber[].A request BEEF over 100,000 bytes also exceeds the 100,000-item array limit in
@bsv/auth-express-middlewareand fails with HTTP 400ERR_AUTH_MALFORMED.Changes
Requests, when the client has
binaryRequestson and the server advertises binary:createAction,prepareNoSendExpiryandactivateNoSendExpirysendinputBEEFas bytes.internalizeActionsendstxas bytes.Responses, when the client sends
X-BSV-Binary-Encoding:listOutputsreturnsBEEFas bytes.createActionreturnssourceTransactionas bytes.findOutputsAuth(lockingScript) andfindProvenTxReqs(rawTx,inputBEEF) rows are sent as bytes. The client converts them back tonumber[].Peers that have not negotiated binary get number arrays as before.
StorageKnexnow produces thelistOutputsBEEFandsourceTransactionasUint8Arrayin process too. The declared types already allow it, andWallet.listOutputsre-serializes as before.Not changed, because existing peers do not support bytes there:
competingBeefinprocessAction/internalizeActionresults, byte fields in error payloads, andmerklePathinupdateProvenTxReqWithNewProvenTx.Tests
$bsvBinaryon the wire.number[]returns the 400; sent as bytes it passes authentication.pnpm lint,pnpm health:check, and the packagetypecheckandformat:checkpass.