Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
aa0fb08
fix(wallet-toolbox): send and return BEEF as bytes so negotiated bina…
shruggr Oct 3, 2026
3c6cdac
fix(wallet-toolbox): size the BRC-177 anchor to cover the reclaim
shruggr Oct 3, 2026
ae6923a
refactor(wallet-toolbox): use an explicit surplusToFee planner flag
shruggr Oct 3, 2026
ad4920c
refactor(wallet-toolbox): replace nested ternary in the change cap
shruggr Oct 3, 2026
9e2fe18
fix(wallet-toolbox): return find rows as bytes over negotiated binary…
shruggr Oct 3, 2026
9273371
fix(wallet-toolbox): StorageIdb treats empty array filters as no filter
shruggr Oct 4, 2026
2a27439
fix(wallet-toolbox): broadcast on internalize when the transaction is…
shruggr Oct 6, 2026
03e92cf
Merge branch 'main' into fix/brc177-anchor-covers-reclaim
ty-everett Oct 10, 2026
5efd597
Merge branch 'main' into fix/storage-binary-beef
ty-everett Oct 10, 2026
7201f5e
Merge remote-tracking branch 'origin/main' into review/david-775
ty-everett Oct 10, 2026
06a6df4
fix(wallet-toolbox): qualify BRC-177 reclaim funding release
ty-everett Oct 10, 2026
a442327
Merge branch 'review/david-775' into review/david-774
ty-everett Oct 10, 2026
7b060de
test(wallet-toolbox): qualify compact BEEF transport and compatibility
ty-everett Oct 10, 2026
d75d1dc
Merge branch 'review/david-774' into review/david-792
ty-everett Oct 10, 2026
9c28e50
Merge remote-tracking branch 'origin/main' into review/david-774
ty-everett Oct 10, 2026
c5f6a97
test(wallet-toolbox): qualify empty IndexedDB filters and ownership
ty-everett Oct 10, 2026
2560fa0
Merge branch 'review/david-774' into review/david-792
ty-everett Oct 10, 2026
fe236a5
Merge branch 'review/david-792' into review/david-856
ty-everett Oct 10, 2026
3cc18d8
test(wallet-toolbox): verify filter parity across IndexedDB and SQLite
ty-everett Oct 10, 2026
dc7dd36
Merge branch 'review/david-792' into review/david-856
ty-everett Oct 10, 2026
a272dd1
fix(wallet-toolbox): qualify new-user internalization broadcast release
ty-everett Oct 10, 2026
df80aa6
test(wallet-toolbox): mock and assert concurrent no-send broadcasts
ty-everett Oct 10, 2026
258a59f
Merge qualified IndexedDB main before final broadcast qualification
ty-everett Oct 10, 2026
168053b
test(wallet-toolbox): prove nonmatching status filters remain restric…
ty-everett Oct 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/packages/wallet/wallet-toolbox-client.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ output-tag ID arrays like omitted optional filters, matching Knex. Nonempty
arrays, partial predicates and user ownership remain enforced. No API, wire
or database migration is required.

Internalizing an unproven transaction new to a user attempts broadcast before
storing recipient outputs, including a sender's no-send transaction already
known to shared storage. Rejected broadcasts return a review-actions error
and store no recipient outputs. Transactions backed by a mining proof are
not rebroadcast. Upgrade active storage; no API, wire or schema migration is required.

## Backup and recovery

Recover both key material and wallet records; a manager snapshot or device
Expand Down
6 changes: 6 additions & 0 deletions docs/packages/wallet/wallet-toolbox-mobile.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ negotiated compact binary JSON codec. Legacy peers retain numeric-array JSON
and identical transaction/proof bytes. Authentication and payload ceilings
remain unchanged; upgrade both clients and active storage for the savings.

Internalizing an unproven transaction new to a user attempts broadcast before
storing recipient outputs, including a sender's no-send transaction already
known to shared storage. Rejected broadcasts return a review-actions error
and store no recipient outputs. Transactions backed by a mining proof are
not rebroadcast. Upgrade active storage; no API, wire or schema migration is required.

## Backup and recovery

Recover both key material and wallet records; a manager snapshot or device
Expand Down
6 changes: 6 additions & 0 deletions docs/packages/wallet/wallet-toolbox.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ output-tag ID arrays like omitted optional filters, matching Knex. Nonempty
arrays, partial predicates and user ownership remain enforced. No API, wire
or database migration is required.

Internalizing an unproven transaction new to a user attempts broadcast before
storing recipient outputs, including a sender's no-send transaction already
known to shared storage. Rejected broadcasts return a review-actions error
and store no recipient outputs. Transactions backed by a mining proof are
not rebroadcast. Upgrade active storage; no API, wire or schema migration is required.

## Optional registry descriptions

ProtoMap, BasketMap and CertMap supply descriptive metadata, not permission grants.
Expand Down
18 changes: 9 additions & 9 deletions docs/reference/package-api-migrations.md

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions governance/package-release-notes.json

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions packages/wallet/wallet-toolbox/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ attention to changes that materially alter behavior or extend functionality.

## wallet-toolbox 2.14.7

- Internalization broadcasts unproven transactions new to the receiving user,
including shared-storage no-send payments. A rejected broadcast stores no
recipient outputs; proven transactions are not rebroadcast. Upgrade active
storage; no API, wire or schema migration is required.

- IndexedDB empty certificate certifier/type, transaction status and output-tag
ID arrays mean no optional filter, matching Knex. Nonempty arrays, partial
predicates and user ownership remain enforced; no schema migration is required.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,15 @@ describe('WalletStorageManager tests', () => {
isValidRootForHeight: async (_root: string, _height: number) => true
}))
fred.services.getChainTracker = getChainTracker
// Receiving an unproven no-send payment now broadcasts it. Keep this
// writer-batch fixture independent of public transaction processors too.
const postBeef = jest.spyOn(fred.services, 'postBeef').mockImplementation(async (_beef, txids) => [
{
name: 'writer-batch-fixture',
status: 'success' as const,
txidResults: txids.map(txid => ({ txid, status: 'success' as const }))
}
])
const promises: Array<Promise<number>> = []
const result: Array<{ i: number; r: any }> = []
const crs1: bsv.CreateActionResult[] = []
Expand Down Expand Up @@ -310,6 +319,8 @@ describe('WalletStorageManager tests', () => {
for (let i = 0; i < maxI; i++) promises.push(makeWriter2(fred, crs1[j++], i, result))
await Promise.all(promises)
expect(result).toHaveLength(maxI)
expect(new Set(postBeef.mock.calls.flatMap(call => call[1]))).toEqual(new Set(crs1.map(cr => cr.txid)))
postBeef.mockRestore()
expect(getChainTracker).toHaveBeenCalled()
await fred.wallet.destroy()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ class InternalizeActionContext {
if (btx == null) throw new WERR_INTERNAL(`Could not find transaction ${this.txid} in AtomicBEEF`)
const bump = this.ab.findBump(this.txid)

let pr: StorageProvenOrReq = { isNew: false, proven: undefined, req: undefined }
let pr: StorageProvenOrReq = { proven: undefined, req: undefined }

await this.storage.transaction(async trx => {
if (bump != null) {
Expand Down Expand Up @@ -694,9 +694,8 @@ class InternalizeActionContext {

const transactionId = this.etx!.transactionId

if (pr.isNew) {
// This storage didn't know about this txid and the beef didn't include a mining proof.
// Assume the transaction has never been broadcast.
if (pr.proven == null) {
// The transaction is new to this user and the beef didn't include a mining proof.
// Attempt to broadcast it to the network, throwing an error if it fails.

// Skip looking up txids and building an aggregate beef,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ describe('idb find tests', () => {
expect(await storage.findTransactions({ partial: {}, status: [status] })).toEqual(
rows.filter(row => row.status === status)
)
// A nonempty status filter must still reject rows that do not match.
expect(rows.every(row => row.status !== 'failed')).toBe(true)
expect(await storage.findTransactions({ partial: {}, status: ['failed'] })).toEqual([])
expect(await storage.findTransactions({ partial: { userId: setup.u1.userId }, status: [] })).toEqual(
rows.filter(row => row.userId === setup.u1.userId)
)
Expand Down
Loading
Loading