@bsv/wallet-toolbox 2.11.0 → 2.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +100 -4
- package/README.md +186 -2
- package/docs/sync-transfer.md +144 -0
- package/out/src/Wallet.js +4 -2
- package/out/src/Wallet.js.map +1 -1
- package/out/src/WalletAuthenticationManager.d.ts +12 -0
- package/out/src/WalletAuthenticationManager.d.ts.map +1 -1
- package/out/src/WalletAuthenticationManager.js +92 -28
- package/out/src/WalletAuthenticationManager.js.map +1 -1
- package/out/src/WalletPermissionsManager.d.ts +11 -5
- package/out/src/WalletPermissionsManager.d.ts.map +1 -1
- package/out/src/WalletPermissionsManager.js +70 -55
- package/out/src/WalletPermissionsManager.js.map +1 -1
- package/out/src/sdk/WalletServices.interfaces.d.ts +6 -0
- package/out/src/sdk/WalletServices.interfaces.d.ts.map +1 -1
- package/out/src/sdk/WalletStorage.interfaces.d.ts +49 -3
- package/out/src/sdk/WalletStorage.interfaces.d.ts.map +1 -1
- package/out/src/services/ServiceCollection.js +2 -2
- package/out/src/services/ServiceCollection.js.map +1 -1
- package/out/src/services/Services.d.ts +1 -0
- package/out/src/services/Services.d.ts.map +1 -1
- package/out/src/services/Services.js +23 -0
- package/out/src/services/Services.js.map +1 -1
- package/out/src/services/providers/ArcSSEClient.d.ts.map +1 -1
- package/out/src/services/providers/ArcSSEClient.js +40 -9
- package/out/src/services/providers/ArcSSEClient.js.map +1 -1
- package/out/src/storage/StorageIdb.d.ts +1 -0
- package/out/src/storage/StorageIdb.d.ts.map +1 -1
- package/out/src/storage/StorageIdb.js +55 -22
- package/out/src/storage/StorageIdb.js.map +1 -1
- package/out/src/storage/StorageKnex.d.ts +3 -1
- package/out/src/storage/StorageKnex.d.ts.map +1 -1
- package/out/src/storage/StorageKnex.js +43 -0
- package/out/src/storage/StorageKnex.js.map +1 -1
- package/out/src/storage/StorageProvider.d.ts.map +1 -1
- package/out/src/storage/StorageProvider.js +17 -2
- package/out/src/storage/StorageProvider.js.map +1 -1
- package/out/src/storage/StorageReader.d.ts +6 -0
- package/out/src/storage/StorageReader.d.ts.map +1 -1
- package/out/src/storage/StorageReader.js +8 -0
- package/out/src/storage/StorageReader.js.map +1 -1
- package/out/src/storage/StorageReaderWriter.d.ts +1 -0
- package/out/src/storage/StorageReaderWriter.d.ts.map +1 -1
- package/out/src/storage/StorageReaderWriter.js +26 -2
- package/out/src/storage/StorageReaderWriter.js.map +1 -1
- package/out/src/storage/WalletStorageManager.d.ts +1 -0
- package/out/src/storage/WalletStorageManager.d.ts.map +1 -1
- package/out/src/storage/WalletStorageManager.js +42 -9
- package/out/src/storage/WalletStorageManager.js.map +1 -1
- package/out/src/storage/methods/getSyncChunk.d.ts.map +1 -1
- package/out/src/storage/methods/getSyncChunk.js +42 -11
- package/out/src/storage/methods/getSyncChunk.js.map +1 -1
- package/out/src/storage/methods/validateSyncProof.d.ts +10 -2
- package/out/src/storage/methods/validateSyncProof.d.ts.map +1 -1
- package/out/src/storage/methods/validateSyncProof.js +24 -1
- package/out/src/storage/methods/validateSyncProof.js.map +1 -1
- package/out/src/storage/remoting/BinaryJson.d.ts.map +1 -1
- package/out/src/storage/remoting/BinaryJson.js +57 -8
- package/out/src/storage/remoting/BinaryJson.js.map +1 -1
- package/out/src/storage/remoting/KnexSyncTransferStore.d.ts +26 -0
- package/out/src/storage/remoting/KnexSyncTransferStore.d.ts.map +1 -0
- package/out/src/storage/remoting/KnexSyncTransferStore.js +223 -0
- package/out/src/storage/remoting/KnexSyncTransferStore.js.map +1 -0
- package/out/src/storage/remoting/StorageClient.js +2 -2
- package/out/src/storage/remoting/StorageClient.js.map +1 -1
- package/out/src/storage/remoting/StorageClientBase.d.ts +30 -4
- package/out/src/storage/remoting/StorageClientBase.d.ts.map +1 -1
- package/out/src/storage/remoting/StorageClientBase.js +194 -2
- package/out/src/storage/remoting/StorageClientBase.js.map +1 -1
- package/out/src/storage/remoting/StorageMobile.js +2 -2
- package/out/src/storage/remoting/StorageMobile.js.map +1 -1
- package/out/src/storage/remoting/StorageServer.d.ts +5 -0
- package/out/src/storage/remoting/StorageServer.d.ts.map +1 -1
- package/out/src/storage/remoting/StorageServer.js +123 -14
- package/out/src/storage/remoting/StorageServer.js.map +1 -1
- package/out/src/storage/remoting/SyncTransfer.d.ts +29 -0
- package/out/src/storage/remoting/SyncTransfer.d.ts.map +1 -0
- package/out/src/storage/remoting/SyncTransfer.js +152 -0
- package/out/src/storage/remoting/SyncTransfer.js.map +1 -0
- package/out/src/storage/remoting/entityValidationHelpers.d.ts.map +1 -1
- package/out/src/storage/remoting/entityValidationHelpers.js +35 -0
- package/out/src/storage/remoting/entityValidationHelpers.js.map +1 -1
- package/out/src/storage/remoting/syncChunkBinary.d.ts +4 -0
- package/out/src/storage/remoting/syncChunkBinary.d.ts.map +1 -0
- package/out/src/storage/remoting/syncChunkBinary.js +38 -0
- package/out/src/storage/remoting/syncChunkBinary.js.map +1 -0
- package/out/src/storage/remoting/validateRpcSyncProofs.d.ts +5 -0
- package/out/src/storage/remoting/validateRpcSyncProofs.d.ts.map +1 -0
- package/out/src/storage/remoting/validateRpcSyncProofs.js +82 -0
- package/out/src/storage/remoting/validateRpcSyncProofs.js.map +1 -0
- package/out/src/storage/schema/KnexMigrations.d.ts +2 -0
- package/out/src/storage/schema/KnexMigrations.d.ts.map +1 -1
- package/out/src/storage/schema/KnexMigrations.js +66 -1
- package/out/src/storage/schema/KnexMigrations.js.map +1 -1
- package/out/src/storage/schema/StorageIdbSchema.d.ts +1 -0
- package/out/src/storage/schema/StorageIdbSchema.d.ts.map +1 -1
- package/out/src/storage/schema/entities/EntityProvenTx.js +2 -2
- package/out/src/storage/schema/entities/EntityProvenTx.js.map +1 -1
- package/out/src/storage/schema/entities/EntitySyncState.d.ts +3 -1
- package/out/src/storage/schema/entities/EntitySyncState.d.ts.map +1 -1
- package/out/src/storage/schema/entities/EntitySyncState.js +6 -0
- package/out/src/storage/schema/entities/EntitySyncState.js.map +1 -1
- package/out/src/storage/sync/SyncPageBudget.d.ts +8 -0
- package/out/src/storage/sync/SyncPageBudget.d.ts.map +1 -0
- package/out/src/storage/sync/SyncPageBudget.js +24 -0
- package/out/src/storage/sync/SyncPageBudget.js.map +1 -0
- package/out/src/storage/sync/syncCheckpoint.d.ts +4 -0
- package/out/src/storage/sync/syncCheckpoint.d.ts.map +1 -0
- package/out/src/storage/sync/syncCheckpoint.js +49 -0
- package/out/src/storage/sync/syncCheckpoint.js.map +1 -0
- package/out/src/utility/identityUtils.js +2 -1
- package/out/src/utility/identityUtils.js.map +1 -1
- package/out/src/wab-client/WABClient.d.ts +1 -0
- package/out/src/wab-client/WABClient.d.ts.map +1 -1
- package/out/src/wab-client/WABClient.js +7 -0
- package/out/src/wab-client/WABClient.js.map +1 -1
- package/out/src/wab-client/auth-method-interactors/AuthMethodInteractor.d.ts +2 -0
- package/out/src/wab-client/auth-method-interactors/AuthMethodInteractor.d.ts.map +1 -1
- package/out/src/wab-client/auth-method-interactors/AuthMethodInteractor.js.map +1 -1
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,78 @@ attention to changes that materially alter behavior or extend functionality.
|
|
|
6
6
|
|
|
7
7
|
## wallet-toolbox (unreleased)
|
|
8
8
|
|
|
9
|
+
- Integrate upstream security corrections without dropping the sync recovery contracts.
|
|
10
|
+
Record combined browser/mobile artifact costs and limits in the sync transfer guide.
|
|
11
|
+
|
|
12
|
+
- Validate replacement proofs across providers before reconciling stale RPC sync metadata; preserve raw transactions and checkpoints on failure.
|
|
13
|
+
|
|
14
|
+
- Start sync copies conservatively and adapt page work after committed responses.
|
|
15
|
+
Validate at most eight remote proofs concurrently, draining failure work before
|
|
16
|
+
rejecting the page. Preserve all proof and checkpoint checks. Record-transfer
|
|
17
|
+
candidates now use 2.13.0 to distinguish them from published 2.12.0.
|
|
18
|
+
|
|
19
|
+
- Require an affirmative certifier-signature verification result before
|
|
20
|
+
storing directly acquired or issuer-returned certificates. Identity overlay
|
|
21
|
+
results are verified before decryption and trust scoring, so forged
|
|
22
|
+
certificates cannot become wallet-held or trusted discovered identities. The
|
|
23
|
+
synchronized browser Vite ceilings advance to 1,695,000 raw and 401,000 gzip,
|
|
24
|
+
covering measured 1,694,211-byte and 400,048-byte bundles; Brotli is unchanged.
|
|
25
|
+
The mobile Metro raw ceiling advances to 1,750,000 for the measured
|
|
26
|
+
1,748,892-byte bundle. The browser esbuild raw ceiling advances to 1,323,000
|
|
27
|
+
for the measured 1,321,768-byte bundle, its gzip ceiling advances to 365,000
|
|
28
|
+
for the measured 364,413-byte bundle, and the optimized Hermes gzip ceiling
|
|
29
|
+
advances to 1,442,000 for the measured 1,441,531-byte bytecode; remaining
|
|
30
|
+
compressed ceilings are unchanged.
|
|
31
|
+
- Never cache, coalesce, or reuse spending approvals, give each prompt a
|
|
32
|
+
distinct request identity, and paginate the complete action history before
|
|
33
|
+
calculating an authorization token's prior spending.
|
|
34
|
+
- Require HTTPS for credential-bearing remote storage and Arcade SSE outside
|
|
35
|
+
explicit loopback development, disable dependency debug output, and avoid
|
|
36
|
+
serializing credential-bearing transport errors. Snapshot formats remain
|
|
37
|
+
unchanged and are documented as wallet-equivalent secrets.
|
|
38
|
+
- Make new WAB account creation resumable when wallet setup, funding, KDF, UMP
|
|
39
|
+
publication, or the final acknowledgement is interrupted. The manager accepts
|
|
40
|
+
a clean missing-token result only for a server-declared pending registration,
|
|
41
|
+
finalizes after successful publication, repairs a lost acknowledgement on the
|
|
42
|
+
next login, and preserves fail-closed continuity for active and legacy WABs.
|
|
43
|
+
- Add optional bounded sync transfers for oversized records, authenticated pieces,
|
|
44
|
+
durable Knex staging, full-frame SHA-256 verification, and stale-checkpoint
|
|
45
|
+
rejection before merging. Add the two staging tables through migration
|
|
46
|
+
`2026-09-09-001`; reverse only that migration before restarting older code. Frames are limited
|
|
47
|
+
to 64 MiB and ordinary pages keep their existing transport. See
|
|
48
|
+
[the transport and migration guide](./docs/sync-transfer.md).
|
|
49
|
+
|
|
50
|
+
- Upgrade IndexedDB to schema version 6 with a non-unique transaction-ID/user
|
|
51
|
+
index. Use existing reference, reclaim, commission, and relation keys for
|
|
52
|
+
sync lookups, avoiding repeated scans as a local wallet grows. Preserve
|
|
53
|
+
user filtering, pagination, existing bytes, and duplicate transaction IDs.
|
|
54
|
+
Proof-batch preflight checks resolve only requested transaction IDs through
|
|
55
|
+
the existing index, preserving proof validation and primary-key ordering.
|
|
56
|
+
Older clients requesting schema version 5 cannot open the upgraded database.
|
|
57
|
+
|
|
58
|
+
- Add negotiated compact sync checkpoints, reusing committed page progress while
|
|
59
|
+
retaining complete writer-side ID mappings and the legacy provider fallback.
|
|
60
|
+
Avoid per-scalar reviver callbacks when decoding binary JSON pages without
|
|
61
|
+
changing marker escaping or byte semantics. Use the already negotiated binary
|
|
62
|
+
codec for large schema-defined sync response byte arrays, reducing wire and
|
|
63
|
+
authentication payload size while preserving legacy arrays and unrelated data.
|
|
64
|
+
Retain authenticated full-copy,
|
|
65
|
+
resume, malformed-input, and transport CPU/payload regression coverage.
|
|
66
|
+
Local packed measurements are 1,701,711 raw / 401,038 gzip / 314,272 Brotli
|
|
67
|
+
bytes (Vite), 1,327,368 / 364,550 / 293,224 (esbuild),
|
|
68
|
+
1,753,648 / 445,136 / 345,369 (Metro), and
|
|
69
|
+
3,557,663 / 1,426,740 / 1,121,821 (Hermes). The raw ceilings become
|
|
70
|
+
1,702,000, 1,327,500, 1,755,000, and 3,558,500 respectively.
|
|
71
|
+
Vite and esbuild gzip ceilings increase to 402,000 and 366,000 bytes.
|
|
72
|
+
Hosted Linux measures 365,818 esbuild gzip bytes and 1,445,624 Hermes gzip
|
|
73
|
+
bytes; the Hermes gzip ceiling becomes 1,446,500.
|
|
74
|
+
The esbuild Brotli ceiling is 293,750 bytes. Asynchronous platform hashing
|
|
75
|
+
for large SDK signature payloads brings the Vite Brotli ceiling to 314,500
|
|
76
|
+
bytes, the Hermes raw ceiling to 3,560,000 bytes, and its Brotli ceiling to
|
|
77
|
+
1,125,000 bytes (measured 1,124,446); other compressed ceilings remain unchanged.
|
|
78
|
+
The added portable sync/progress and decoding paths account for
|
|
79
|
+
the increase; no Node-only backend is introduced into portable bundles.
|
|
80
|
+
|
|
9
81
|
- Keep Argon2id-backed UMP v3 wallets available in React Native and other
|
|
10
82
|
runtimes without WebAssembly by falling back to an asynchronously yielding,
|
|
11
83
|
standards-compatible JavaScript implementation. The same KDF parameters and
|
|
@@ -22,10 +94,15 @@ attention to changes that materially alter behavior or extend functionality.
|
|
|
22
94
|
bytes with Vite, 1,319,059 raw / 362,220 gzip / 291,206 Brotli bytes with
|
|
23
95
|
esbuild, 1,746,067 raw / 442,648 gzip / 343,342 Brotli bytes with Metro, and
|
|
24
96
|
3,542,034 raw / 1,419,515 gzip / 1,117,531 Brotli bytes as optimized Hermes
|
|
25
|
-
bytecode; hosted Linux measures 1,439,166 gzip bytes.
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
97
|
+
bytecode; hosted Linux measures 1,439,166 gzip bytes. Combined with the
|
|
98
|
+
interrupted-registration recovery path above, current measurements are
|
|
99
|
+
1,694,823 raw / 399,940 gzip / 312,528 Brotli bytes with Vite, 1,322,223 raw
|
|
100
|
+
/ 364,260 gzip / 291,914 Brotli bytes with esbuild, 1,749,694 raw / 443,665
|
|
101
|
+
gzip / 344,059 Brotli bytes with Metro, and 3,549,495 raw / 1,441,622 gzip /
|
|
102
|
+
1,119,600 Brotli bytes as optimized Hermes bytecode. The reviewed ceilings
|
|
103
|
+
advance to 1,697,000 raw / 400,000 gzip Vite bytes, 1,324,000 raw / 365,000
|
|
104
|
+
gzip esbuild bytes, 1,752,000 raw Metro bytes, and 3,552,000 raw / 1,442,000
|
|
105
|
+
gzip Hermes bytes; Brotli ceilings remain unchanged.
|
|
29
106
|
|
|
30
107
|
- Extend the BRC-98/99/111 permission-module interface with an optional semantic
|
|
31
108
|
`handleRequest` hook. A module can now return a conforming BRC-100 result
|
|
@@ -107,6 +184,25 @@ attention to changes that materially alter behavior or extend functionality.
|
|
|
107
184
|
transaction startup/commit cycles, failed pages roll back without advancing
|
|
108
185
|
the checkpoint, and abort cleanup preserves the original storage error.
|
|
109
186
|
|
|
187
|
+
- Fill wallet-storage sync pages with adaptive, size-aware source queries and
|
|
188
|
+
add composite SQL indexes for user-scoped proof lookups. Sync clients may
|
|
189
|
+
request optional source record totals for exact progress and ETA displays;
|
|
190
|
+
older clients and providers remain wire-compatible and do not incur count
|
|
191
|
+
queries unless totals are requested. Remote clients also recover from a
|
|
192
|
+
provider's HTTP 413 response ceiling by retrying the read-only sync request
|
|
193
|
+
with a smaller chunk budget and reusing the working limit for later pages.
|
|
194
|
+
Runtime validation rejects malformed remote totals, and MySQL rollback
|
|
195
|
+
restores the foreign-key support index before removing the new composites.
|
|
196
|
+
The retained authenticated candidate-provider benchmark fills a 250-record
|
|
197
|
+
proof page with three source reads (`10, 80, 160`) on SQLite and MySQL.
|
|
198
|
+
Clean macOS fixtures measure Vite at 1,609,916 raw, 379,552 gzip, and 297,188
|
|
199
|
+
Brotli bytes; esbuild at 1,254,827 raw, 344,883 gzip, and 277,729 Brotli
|
|
200
|
+
bytes; Metro at 1,662,714 raw, 419,740 gzip, and 326,785 Brotli bytes; and
|
|
201
|
+
Hermes at 3,371,236 raw, 1,347,950 gzip, and 1,061,946 Brotli bytes. The
|
|
202
|
+
reviewed ceilings advance to 1,611,000/380,000/297,500 for Vite,
|
|
203
|
+
1,256,000/346,000/278,200 for esbuild, and 3,373,000/1,368,000 raw/gzip for
|
|
204
|
+
Hermes. Metro and the Hermes Brotli ceiling remain unchanged.
|
|
205
|
+
|
|
110
206
|
- Make verified phone changes interruption-safe by staging the replacement key
|
|
111
207
|
in WAB, publishing the UMP rotation, and then finalizing WAB. Authentication
|
|
112
208
|
can recover an interrupted transition from the current or pending key and
|
package/README.md
CHANGED
|
@@ -6,6 +6,27 @@
|
|
|
6
6
|
|
|
7
7
|
A [BRC-100](https://github.com/bitcoin-sv/BRCs/blob/master/wallet/0100.md) conforming wallet implementation for the BSV blockchain, built on the [BSV SDK](https://bsv-blockchain.github.io/ts-stack/packages/sdk/). Provides persistent storage, protocol-based key derivation, transaction monitoring, chain tracking, and signing — everything needed to build wallet-powered applications on BSV.
|
|
8
8
|
|
|
9
|
+
## Backup and sync: tested results
|
|
10
|
+
|
|
11
|
+
**Live E2E testing used a large wallet in the native desktop client**, covering
|
|
12
|
+
complete local copies, restart recovery, and repeat sync. Transfer size and oversized-record recovery were
|
|
13
|
+
measured separately with synthetic fixtures. The latest proof-recovery follow-up
|
|
14
|
+
has synthetic HTTP and read-only source-data validation; its live full-backup
|
|
15
|
+
retest is pending.
|
|
16
|
+
|
|
17
|
+
| Test | Verified result |
|
|
18
|
+
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
19
|
+
| Full native desktop restores | **Two complete copies; identical entity counts.** Second run: **12m 50s vs 16m 30s (22.3% less time)**. |
|
|
20
|
+
| Retained local backup | Completed after cancellation, a connectivity pause, and restart recovery; all **12 entity-store counts preserved** on another restart. |
|
|
21
|
+
| Local reads and repeat sync | Transaction/output reads passed; sampled transaction bytes matched; repeat sync made **0 inserts, 0 updates**. |
|
|
22
|
+
| Transfer size | **62.7% smaller** encoded byte payload in a synthetic fixture. |
|
|
23
|
+
| Oversized single record | **7 MiB restored in real browser IndexedDB**, matching SHA-256; interrupted upload resumed, corrupt download rejected, repeat sync unchanged. |
|
|
24
|
+
| Automated integration | Authenticated HTTP backup/restore, interrupted pages, lost acknowledgements, binary byte round-trips, user isolation, and legacy compatibility covered. |
|
|
25
|
+
|
|
26
|
+
Timing compares successive candidates, not a controlled comparison against upstream
|
|
27
|
+
`main`. Byte verification was sampled, not database-wide. See
|
|
28
|
+
[test methods and limits](#sync-performance-and-recovery) for details.
|
|
29
|
+
|
|
9
30
|
## Overview
|
|
10
31
|
|
|
11
32
|
The Wallet Toolbox is the reference implementation of the BRC-100 wallet interface. It connects the BSV SDK's cryptographic primitives to real storage backends, network services, and signing flows so that application developers don't have to wire these layers together themselves.
|
|
@@ -54,10 +75,141 @@ The toolbox publishes three npm packages from this repo:
|
|
|
54
75
|
- **[`@bsv/wallet-toolbox-client`](https://www.npmjs.com/package/@bsv/wallet-toolbox-client)** — Browser build; excludes Node-only backends (Knex/SQLite/MySQL)
|
|
55
76
|
- **[`@bsv/wallet-toolbox-mobile`](https://www.npmjs.com/package/@bsv/wallet-toolbox-mobile)** — Mobile build; remote wallet storage plus portable local ChainTracks components and adapter contracts
|
|
56
77
|
|
|
78
|
+
### Sync performance and recovery
|
|
79
|
+
|
|
80
|
+
Sync pages start at 64 records and adapt after successful commits toward a
|
|
81
|
+
five-second page budget. Proof-bearing pages cap growth at 128 records; cheap
|
|
82
|
+
metadata pages can grow to 1,000, while provider byte/item ceilings still apply.
|
|
83
|
+
The server checks at most eight proofs concurrently and waits for all started
|
|
84
|
+
checks to settle on failure before rejecting the page. Every proof still passes
|
|
85
|
+
transaction, Merkle path, active-root and active-header validation before a merge.
|
|
86
|
+
An authenticated HTTP regression covers 250 synthetic proofs and confirms that
|
|
87
|
+
an invalid follow-up page cannot change the committed checkpoint. Stale proofs
|
|
88
|
+
can be reconciled through another provider, but only after the replacement passes
|
|
89
|
+
the same transaction, membership and active-chain checks. Transaction bytes,
|
|
90
|
+
wallet references and source cursor timestamps are preserved. Corrected destination
|
|
91
|
+
proofs receive a fresh local timestamp for incremental replication. Unverifiable replacements
|
|
92
|
+
stop the page with a recovery message; no record is silently skipped.
|
|
93
|
+
|
|
94
|
+
A read-only deployment-host sample of 250 proofs took 42.6 seconds with sequential
|
|
95
|
+
validation and 5.58 seconds with bounded concurrency, with the same 250 root and
|
|
96
|
+
250 header checks. This measures validation only, not full-copy throughput.
|
|
97
|
+
Timeouts remain possible during dependency outages; writes are never blindly
|
|
98
|
+
replayed, and resumed sync rereads durable destination progress.
|
|
99
|
+
|
|
100
|
+
The adaptive page controller and optional validated-proof lookup add a small
|
|
101
|
+
client bundle cost. The [artifact measurements and limits](./docs/sync-transfer.md#artifact-cost-requiring-review)
|
|
102
|
+
include the combined upstream security fixes. These are explicit feature costs;
|
|
103
|
+
the RPC validation coordinator remains excluded from browser/mobile bundles.
|
|
104
|
+
|
|
105
|
+
The transfer extension is an **unpublished 2.13.0 candidate**. Published 2.12.0
|
|
106
|
+
has no record-transfer methods. Check exact build provenance and authenticated
|
|
107
|
+
runtime capabilities, not a version label alone. An oversized record on a legacy
|
|
108
|
+
source cannot be rescued by upgrading only its destination; upgrade the source
|
|
109
|
+
before retrying. Records exceeding the negotiated 64 MiB frame limit fail safely
|
|
110
|
+
without being skipped or advancing their checkpoint.
|
|
111
|
+
|
|
112
|
+
Large individual records can use the negotiated
|
|
113
|
+
[bounded transfer protocol](./docs/sync-transfer.md), with durable staging,
|
|
114
|
+
integrity verification and checkpoint replay protection. Its authenticated
|
|
115
|
+
HTTP/SQLite/IndexedDB regression exercises a 7 MiB binary record, an interrupted
|
|
116
|
+
upload across client/server restart, a lost part acknowledgement, corrupted
|
|
117
|
+
download rejection and a verified restore followed by an unchanged resync.
|
|
118
|
+
The current frame limit is 64 MiB; legacy providers must be upgraded to use it.
|
|
119
|
+
It also passes with a one-second delay on every authenticated transport send;
|
|
120
|
+
that models added latency, not a measured bandwidth limit or a real mobile network.
|
|
121
|
+
These synthetic regressions are separate from the large-wallet timing evidence above.
|
|
122
|
+
|
|
57
123
|
Wallet storage replication applies each received page and its durable sync
|
|
58
124
|
checkpoint in one provider transaction. IndexedDB and Knex therefore avoid
|
|
59
125
|
per-record transaction startup, and a failed page rolls back without advancing
|
|
60
|
-
the checkpoint.
|
|
126
|
+
the checkpoint. Sources fill each bounded page with adaptive, size-aware reads,
|
|
127
|
+
and Knex storage adds user-scoped proof lookup indexes. Clients may set
|
|
128
|
+
`includeTotals` on a sync-chunk request to receive optional source record totals
|
|
129
|
+
for exact progress reporting. Older providers ignore the hint, and totals are
|
|
130
|
+
not counted unless requested. New clients also send the writer-local sync-state
|
|
131
|
+
identifier selected during provider registration. New providers use it to
|
|
132
|
+
disambiguate legacy duplicate checkpoints, while either side remains compatible
|
|
133
|
+
with older protocol peers. When a provider rejects a sync page because its
|
|
134
|
+
serialized RPC response exceeds the service ceiling, remote clients retry the
|
|
135
|
+
read-only request with a smaller chunk budget and remember the working limit
|
|
136
|
+
for the rest of the session.
|
|
137
|
+
|
|
138
|
+
IndexedDB schema version 6 adds a non-unique transaction-ID/user index. Sync
|
|
139
|
+
identity lookups, commissions, and relation maps use selective indexes or exact
|
|
140
|
+
keys instead of scanning the growing wallet for each row. Proof batch checks
|
|
141
|
+
resolve requested transaction IDs through the existing index, preserving primary-key
|
|
142
|
+
ordering, pagination, and proof-validation rules. Existing bytes and
|
|
143
|
+
legacy duplicate transaction IDs are preserved. Databases upgrade automatically;
|
|
144
|
+
older clients that open schema version 5 cannot reopen an upgraded database, so
|
|
145
|
+
keep a compatible client when retaining a local backup.
|
|
146
|
+
|
|
147
|
+
Updated servers advertise `syncCheckpointVersion: 1` in runtime settings.
|
|
148
|
+
Compatible clients fetch a compact checkpoint once, then use the checkpoint
|
|
149
|
+
returned by each committed page. The complete ID mapping remains durable on
|
|
150
|
+
the writer and is no longer downloaded before every page. Older providers use
|
|
151
|
+
the existing full-state path; authentication, gateway, and malformed checkpoint
|
|
152
|
+
errors remain failures rather than compatibility fallbacks. A retry starts
|
|
153
|
+
from the writer's durable checkpoint. `includeNextCheckpoint` is optional, and
|
|
154
|
+
legacy requests retain their existing response shape.
|
|
155
|
+
|
|
156
|
+
When a reader negotiates binary JSON, large schema-defined sync byte fields
|
|
157
|
+
are encoded as base64 instead of decimal number arrays. Legacy readers retain
|
|
158
|
+
the existing arrays; unrelated numeric fields are never reinterpreted as bytes.
|
|
159
|
+
Clients with `binaryRequests: true` use the same compact representation for
|
|
160
|
+
sync uploads after the server negotiates binary request support. The default
|
|
161
|
+
request setting is unchanged.
|
|
162
|
+
Binary JSON parsing preserves the existing marker and escaping rules while
|
|
163
|
+
avoiding a JavaScript reviver callback for every scalar byte. The SDK also
|
|
164
|
+
prevents certificate work or session recovery from dispatching another request
|
|
165
|
+
after the caller's authentication deadline has expired. This does not cancel a
|
|
166
|
+
write already received by a server or automatically replay failed writes.
|
|
167
|
+
|
|
168
|
+
Run the authenticated candidate-provider sync benchmark with:
|
|
169
|
+
|
|
170
|
+
```sh
|
|
171
|
+
pnpm bench:storage-sync
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Set `WALLET_TOOLBOX_BENCH_MYSQL=true`, `MYSQL_CONNECTION`, and optionally
|
|
175
|
+
`WALLET_TOOLBOX_BENCH_MYSQL_DATABASE` to exercise the same fixture through a
|
|
176
|
+
MySQL-backed provider. The benchmark reports HTTP p50/p95 latency and the
|
|
177
|
+
source-query limits used to fill a 250-record page; it is observational rather
|
|
178
|
+
than a cross-machine latency SLA. It also compares the old reviver with the
|
|
179
|
+
current parser on identical synthetic data and measures checkpoint size. On
|
|
180
|
+
one local Node 24 run, a 1 MiB numeric-array fixture (3.74 MB of JSON) measured
|
|
181
|
+
501.2 ms versus 10.1 ms median parsing time across nine alternating samples.
|
|
182
|
+
A synthetic 50,000-entry mapping occupied 678,850 bytes; its compact checkpoint
|
|
183
|
+
occupied 432 bytes. These are CPU and payload measurements, not a claim of the
|
|
184
|
+
same end-to-end network speedup. Encoding the synthetic byte field through
|
|
185
|
+
the negotiated sync codec reduced its JSON payload from 3,743,771 to 1,398,163
|
|
186
|
+
bytes (62.7%).
|
|
187
|
+
|
|
188
|
+
Retained integration tests cover authenticated HTTP backup and complete restore
|
|
189
|
+
into a fresh IndexedDB store, multipage progression, no-change resync,
|
|
190
|
+
interruption/resume, user isolation, malformed checkpoints, and legacy-provider
|
|
191
|
+
fallback. Live deployment results must be reported separately with the tested
|
|
192
|
+
revision and scope; a partial page sample is not a full restore verification.
|
|
193
|
+
|
|
194
|
+
A native desktop integration run against candidate runtime
|
|
195
|
+
`a88d18abf14b75a3227016bfd947d5a08b3ee236` completed a full remote-to-local
|
|
196
|
+
copy in 769.5 seconds, compared with 990.3 seconds for the preceding candidate
|
|
197
|
+
run with identical entity counts. Remote reads took 619.2 seconds, local writes
|
|
198
|
+
146.0 seconds, and measurement 4.1 seconds. Proof-page writes fell from 75.7 to
|
|
199
|
+
9.8 seconds after indexed preflight lookup. These are sequential observations,
|
|
200
|
+
not a controlled full-wallet comparison against upstream main. The all-state
|
|
201
|
+
100 ms timer probe reported p95 delay of 908 ms; foreground focus was not recorded,
|
|
202
|
+
so this does not establish foreground UI latency. Separate 90-second native
|
|
203
|
+
foreground probes during a retained backup measured p95 delays of 5 ms for
|
|
204
|
+
transactions, 8 ms for outputs, 10 ms for heavier output pages, and 5 ms for
|
|
205
|
+
proof requests. Their maxima were 60, 51, 298, and 62 ms respectively; these
|
|
206
|
+
samples are not a whole-copy latency guarantee. The retained-backup test also
|
|
207
|
+
verified cancellation at a page boundary and automatic checkpoint recovery after
|
|
208
|
+
a full native app restart. Development testing required refreshing Vite's cached
|
|
209
|
+
linked dependencies to load the candidate schema consistently. See
|
|
210
|
+
[PR486](https://github.com/bsv-blockchain/ts-stack/pull/486) for final integration
|
|
211
|
+
completion and release evidence. Personal deployment and wallet details are
|
|
212
|
+
retained privately, outside this repository.
|
|
61
213
|
|
|
62
214
|
`listOutputs` reports `totalOutputs` as the full matching result count on every
|
|
63
215
|
page for both Knex and IndexedDB storage, including short final pages and pages
|
|
@@ -92,13 +244,22 @@ checks leave multiple valid UMP tokens, and only when the pinned outpoint is
|
|
|
92
244
|
present in the verified candidates. A pin cannot introduce an outpoint that the
|
|
93
245
|
wallet did not independently retrieve and validate.
|
|
94
246
|
|
|
247
|
+
New WAB registrations are interruption-safe across the off-chain/on-chain
|
|
248
|
+
boundary. A WAB that advertises `registrationStatus: "pending"` lets a verified
|
|
249
|
+
retry reuse the stored presentation key when a clean UMP lookup confirms that
|
|
250
|
+
publication has not happened. After publishing the UMP token, the manager
|
|
251
|
+
finalizes WAB idempotently. A lost finalization response is non-fatal: the next
|
|
252
|
+
verified login finds the published token and repairs the pending state. Missing
|
|
253
|
+
or invalid lifecycle metadata remains fail-closed for established accounts, and
|
|
254
|
+
older WAB servers and clients retain their existing wire behavior.
|
|
255
|
+
|
|
95
256
|
Authenticated applications can verify a phone number and roll the presentation
|
|
96
257
|
key, including when the user enters the same phone number:
|
|
97
258
|
|
|
98
259
|
```ts
|
|
99
260
|
await manager.startPhoneNumberChange('+12065550100')
|
|
100
261
|
await manager.completePhoneNumberChange(code)
|
|
101
|
-
await
|
|
262
|
+
await platformKeyStore.storeSecret('wallet-snapshot', manager.saveSnapshot())
|
|
102
263
|
```
|
|
103
264
|
|
|
104
265
|
The completion call first stages the verified phone association and new key in
|
|
@@ -112,6 +273,29 @@ also resumes an unpublished staged change without committing another key.
|
|
|
112
273
|
Persist the snapshot immediately after success. Deploy the compatible overlay
|
|
113
274
|
topic and WAB schema/routes before enabling this UI.
|
|
114
275
|
|
|
276
|
+
### Snapshot security
|
|
277
|
+
|
|
278
|
+
`CWIStyleWalletManager` and `SimpleWalletManager` snapshots contain wallet root
|
|
279
|
+
key material and intentionally embed the key needed to restore that material.
|
|
280
|
+
Encryption protects their internal representation, but it does not make the
|
|
281
|
+
snapshot safe to disclose: **access to a snapshot is access to the wallet**.
|
|
282
|
+
Store the complete snapshot as a secret in an OS Keychain, hardware-backed
|
|
283
|
+
keystore, or comparably trusted storage. Do not put snapshots in ordinary
|
|
284
|
+
localStorage/AsyncStorage, logs, analytics, crash reports, unprotected backups,
|
|
285
|
+
clipboard data, or cloud sync. If a snapshot may have escaped trusted storage,
|
|
286
|
+
treat the wallet credentials as compromised and rotate them; deleting one copy
|
|
287
|
+
does not revoke other copies.
|
|
288
|
+
|
|
289
|
+
Remote `StorageClient` and credential-bearing Arcade SSE endpoints require
|
|
290
|
+
HTTPS. Plain HTTP is accepted only for explicit loopback hosts during local
|
|
291
|
+
development. Arcade SSE dependency debug logging remains disabled because its
|
|
292
|
+
request URL and headers carry wallet callback credentials.
|
|
293
|
+
|
|
294
|
+
Certificate signatures fail closed at every wallet trust boundary. Direct and
|
|
295
|
+
issuer-mediated acquisition require an affirmative certifier-signature result
|
|
296
|
+
before storage, and identity discovery verifies each untrusted overlay
|
|
297
|
+
certificate before decryption or trust scoring.
|
|
298
|
+
|
|
115
299
|
### ChainTracks sources and networks
|
|
116
300
|
|
|
117
301
|
Wallet services do not require a WhatsOnChain key for ChainTracks. Node
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# Bounded wallet sync transfers, version 1
|
|
2
|
+
|
|
3
|
+
This optional transport carries complete BRC-40 request/response objects across
|
|
4
|
+
HTTP message limits. It does not change the BRC-40 entity order, inclusive
|
|
5
|
+
watermark, ID maps, tombstones, merge rules, or completion condition. Ordinary
|
|
6
|
+
pages continue to use `getSyncChunk` and `processSyncChunk`.
|
|
7
|
+
|
|
8
|
+
## Negotiation and limits
|
|
9
|
+
|
|
10
|
+
A migrated Knex-backed `StorageServer` advertises `syncTransfer` in runtime
|
|
11
|
+
settings: `{ version: 1, maxBytes, partBytes, inlineBytes }`. These are transport
|
|
12
|
+
capabilities, not persisted settings columns. `syncTransfers: false` disables
|
|
13
|
+
advertisement and transfer RPCs during a mixed-version deployment. A client
|
|
14
|
+
must not infer support from compact checkpoints or binary JSON alone.
|
|
15
|
+
|
|
16
|
+
Version 1 accepts frames up to 64 MiB, with parts no larger than 256 KiB. Parts
|
|
17
|
+
are carried by the existing authenticated binary-JSON codec. The frame itself
|
|
18
|
+
stores binary fields directly, avoiding a second base64 encoding. The server
|
|
19
|
+
uses smaller parts for smaller request or response limits, and leaves this
|
|
20
|
+
feature disabled when either limit is below 4096 bytes. This is bounded transfer of
|
|
21
|
+
large records, not unlimited-size or constant-memory database streaming: the
|
|
22
|
+
current storage and merge APIs still materialize a complete record/page. Records
|
|
23
|
+
above the advertised limit fail explicitly; they are never skipped.
|
|
24
|
+
|
|
25
|
+
## Framing and integrity
|
|
26
|
+
|
|
27
|
+
A frame starts with a four-byte unsigned big-endian JSON-header byte length,
|
|
28
|
+
followed by that many UTF-8 bytes encoded with the existing binary-JSON escaping
|
|
29
|
+
rules. The header is `{ version: 1, value, fields }`. Each `fields` entry is
|
|
30
|
+
`{ path, length }`: `path` identifies a null placeholder in `value` using object
|
|
31
|
+
keys or numeric array indices. Raw field bytes follow the header in entry order.
|
|
32
|
+
Dates retain their existing ISO JSON representation. Only actual byte views are
|
|
33
|
+
extracted; sync callers first select the declared binary fields with
|
|
34
|
+
`syncChunkBinary`. Ordinary numeric arrays retain their semantics.
|
|
35
|
+
|
|
36
|
+
Decoders reject invalid lengths, missing/duplicate placeholders, unsafe paths,
|
|
37
|
+
more than 4096 byte fields, paths deeper than 64 levels, trailing bytes, and
|
|
38
|
+
unsupported versions. The manifest SHA-256 covers the entire frame. A receiver
|
|
39
|
+
must verify it before decoding and merging. BRC-103 authentication additionally
|
|
40
|
+
binds every request/response to the authenticated session.
|
|
41
|
+
|
|
42
|
+
## RPC sequence
|
|
43
|
+
|
|
44
|
+
After negotiation a `getSyncChunk` request can include `syncTransferVersion: 1`.
|
|
45
|
+
If its normal response exceeds the HTTP ceiling, the server returns
|
|
46
|
+
`{ syncTransfer: manifest }` in the JSON-RPC result instead of HTTP 413. The
|
|
47
|
+
client reads, verifies and decodes the staged frame before exposing the ordinary
|
|
48
|
+
`SyncChunk` to its caller. Requests without the hint keep their legacy response
|
|
49
|
+
shape. This avoids repeated oversized responses and repeated source queries.
|
|
50
|
+
|
|
51
|
+
Every transfer method takes one object in `params`, including the authenticated
|
|
52
|
+
`identityKey`. Method arguments below are additional fields in that object.
|
|
53
|
+
|
|
54
|
+
- `beginReadSyncTransfer`: `{ args: RequestSyncChunkArgs }` returns a manifest.
|
|
55
|
+
The source validates the ordinary sync request and stages an immutable frame.
|
|
56
|
+
- `readSyncTransferPart`: `{ transferId, offset }` returns `{ offset, bytes }`.
|
|
57
|
+
Offsets are aligned to `partBytes`; the final part may be shorter.
|
|
58
|
+
- `beginWriteSyncTransfer`: `{ digest, totalBytes }` returns a manifest plus
|
|
59
|
+
`receivedBytes`. Identical staged uploads resume after process restarts.
|
|
60
|
+
- `writeSyncTransferPart`: `{ transferId, offset, bytes }` returns the next byte
|
|
61
|
+
offset. An identical replay is accepted; changed or out-of-order bytes fail.
|
|
62
|
+
- `commitSyncTransfer`: `{ transferId }` verifies a complete frame containing
|
|
63
|
+
`{ args, chunk }`, validates the wallet/storage identities and proofs, then
|
|
64
|
+
invokes the existing atomic page merge with a matching-checkpoint guard.
|
|
65
|
+
- `releaseSyncTransfer`: `{ transferId }` removes only staging data.
|
|
66
|
+
|
|
67
|
+
Manifests contain `{ transferId, digest, totalBytes, partBytes, expiresAt }`.
|
|
68
|
+
Identifiers and hashes are 64 lowercase hexadecimal characters. Expiry is Unix
|
|
69
|
+
milliseconds. Transfer identifiers never grant access: all lookups also require
|
|
70
|
+
the authenticated wallet identity. Unknown/expired and another user's transfers
|
|
71
|
+
produce the same unavailable response.
|
|
72
|
+
|
|
73
|
+
## Recovery and resource ownership
|
|
74
|
+
|
|
75
|
+
The additive `2026-09-09-001` migration creates `sync_transfers` and
|
|
76
|
+
`sync_transfer_parts`. Eight fixed staging slots, at most two per identity,
|
|
77
|
+
bound storage to at most 512 MiB of frame data, plus metadata/database overhead.
|
|
78
|
+
Allocation and part updates serialize through a database row lock, shared across
|
|
79
|
+
replicas. Expired staging is reclaimed on subsequent allocation. The fixed
|
|
80
|
+
15-minute expiry bounds retention but may require restarting an expired record.
|
|
81
|
+
Staging is storage-global operational data and is excluded from BRC-38 exports.
|
|
82
|
+
|
|
83
|
+
Uploads retain acknowledged pieces across client/server restart. Interrupted
|
|
84
|
+
downloads can retry individual immutable pieces within an attempt; after an app
|
|
85
|
+
restart, sync resumes at the last durable BRC-40 record checkpoint and may
|
|
86
|
+
re-download the incomplete record. No partial record becomes wallet data.
|
|
87
|
+
|
|
88
|
+
A lost commit acknowledgement is not automatically replayed by the client.
|
|
89
|
+
Retrying sync first rereads the writer checkpoint. A staged commit requires its
|
|
90
|
+
watermark and offsets to match the current durable checkpoint under the page
|
|
91
|
+
transaction; stale commits cannot advance counters twice. Completed transfer
|
|
92
|
+
results are retained until release/expiry, including after a server restart.
|
|
93
|
+
|
|
94
|
+
Run the wallet migration before enabling the new server code on every replica.
|
|
95
|
+
For rollback, stop transfer traffic, preserve the current database, then use the
|
|
96
|
+
new runtime's Knex migration source to run **only** this migration down (including
|
|
97
|
+
its ledger entry) before restarting the old runtime. This removes incomplete
|
|
98
|
+
staging, not wallet records or committed checkpoints; clients can resume those
|
|
99
|
+
records. Merely leaving an unknown migration in the ledger can prevent an older
|
|
100
|
+
runtime from starting. Never restore an older database over later wallet writes.
|
|
101
|
+
The SQLite migration is transactional; table/slot creation is also restart-safe
|
|
102
|
+
for MySQL's implicit DDL commits.
|
|
103
|
+
|
|
104
|
+
## Standards scope
|
|
105
|
+
|
|
106
|
+
BRC-40 is transport-agnostic. This framing is an optional transport extension;
|
|
107
|
+
its reassembled objects retain BRC-40 semantics. Legacy peers still use ordinary
|
|
108
|
+
pages and cannot transfer records above their message limits.
|
|
109
|
+
|
|
110
|
+
BRC-38 specifies canonical portable wallet exports, and BRC-39 specifies their
|
|
111
|
+
password-encrypted wrapper. This transport changes neither file format. A live
|
|
112
|
+
IndexedDB replica is not itself a BRC-38 or BRC-39 export file. Passing portable
|
|
113
|
+
export/import regression tests is evidence for those tested paths, not a blanket
|
|
114
|
+
claim that every wallet feature or legacy migration is strictly conformant.
|
|
115
|
+
|
|
116
|
+
## Artifact cost requiring review
|
|
117
|
+
|
|
118
|
+
The framing, integrity checks, adaptive page controller and validated proof-provider
|
|
119
|
+
lookup add portable code. After integrating upstream security fixes, exact packed
|
|
120
|
+
macOS consumers measured the following bytes. Hermes compression varies slightly
|
|
121
|
+
with build paths.
|
|
122
|
+
|
|
123
|
+
| Artifact | Raw | Gzip | Brotli | Raw ceiling | Gzip ceiling | Brotli ceiling |
|
|
124
|
+
| --- | ---: | ---: | ---: | ---: | ---: | ---: |
|
|
125
|
+
| Vite | 1,716,150 | 404,965 | 316,747 | 1,717,000 | 406,500 | 317,000 |
|
|
126
|
+
| esbuild | 1,338,800 | 368,089 | 295,540 | 1,339,500 | 369,500 | 296,000 |
|
|
127
|
+
| Metro | 1,767,013 | 448,892 | 347,746 | 1,768,000 | 455,000 | 360,000 |
|
|
128
|
+
| Hermes | 3,586,809 | 1,439,723 | 1,133,805 | 3,588,000 | 1,460,500 | 1,135,000 |
|
|
129
|
+
|
|
130
|
+
Before upstream integration, Linux CI measured Vite gzip at 404,970 and Hermes
|
|
131
|
+
gzip at 1,457,902, above the corresponding macOS measurements. The combined
|
|
132
|
+
ceilings retain that platform allowance and the upstream security artifact costs.
|
|
133
|
+
The combined Linux esbuild artifact measured 369,222 gzip bytes; its ceiling is
|
|
134
|
+
369,500 bytes. The complete hosted platform checks must pass these limits before
|
|
135
|
+
review.
|
|
136
|
+
|
|
137
|
+
Browser composition contains only the existing SDK, wallet client, noble hashes,
|
|
138
|
+
hash-wasm and IndexedDB dependencies. No Node storage or new dependency enters
|
|
139
|
+
the graph. Server staging and RPC proof orchestration remain outside
|
|
140
|
+
browser/mobile exports. The SDK's combined esbuild consumer measures 560,560 raw
|
|
141
|
+
bytes against a 561,000-byte ceiling; its compressed ceilings are unchanged.
|
|
142
|
+
|
|
143
|
+
These are explicit feature costs requiring maintainer review under the repository
|
|
144
|
+
artifact-growth policy, not claims of reduced application bundle size.
|
package/out/src/Wallet.js
CHANGED
|
@@ -369,7 +369,8 @@ class Wallet {
|
|
|
369
369
|
})).publicKey;
|
|
370
370
|
try {
|
|
371
371
|
const certificate = new sdk_1.MasterCertificate(vargs.type, vargs.serialNumber, vargs.subject, vargs.certifier, vargs.revocationOutpoint, vargs.fields, vargs.keyringForSubject, vargs.signature);
|
|
372
|
-
await certificate.verify()
|
|
372
|
+
if (!(await certificate.verify()))
|
|
373
|
+
throw new Error('Certificate verification failed');
|
|
373
374
|
await sdk_1.MasterCertificate.decryptFields(this, vargs.keyringForSubject, vargs.fields, vargs.certifier, vargs.privileged, vargs.privilegedReason);
|
|
374
375
|
}
|
|
375
376
|
catch (error_) {
|
|
@@ -442,7 +443,8 @@ class Wallet {
|
|
|
442
443
|
if (!valid)
|
|
443
444
|
throw new Error('Invalid serialNumber');
|
|
444
445
|
this.validateIssuedCertificate(signedCertificate, vargs, certificateFields);
|
|
445
|
-
await signedCertificate.verify()
|
|
446
|
+
if (!(await signedCertificate.verify()))
|
|
447
|
+
throw new Error('Certificate verification failed');
|
|
446
448
|
await sdk_1.MasterCertificate.decryptFields(this, masterKeyring, certificate.fields, vargs.certifier);
|
|
447
449
|
return await (0, acquireDirectCertificate_1.acquireDirectCertificate)(this, auth, {
|
|
448
450
|
...certificate,
|