@bsv/wallet-toolbox 2.0.0-beta.0 → 2.0.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.
Files changed (97) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/docs/README.md +1 -0
  3. package/docs/client.md +409 -267
  4. package/docs/services.md +15 -3
  5. package/docs/storage.md +48 -88
  6. package/docs/wab-shamir.md +311 -0
  7. package/docs/wallet.md +409 -267
  8. package/out/src/ShamirWalletManager.d.ts +213 -0
  9. package/out/src/ShamirWalletManager.d.ts.map +1 -0
  10. package/out/src/ShamirWalletManager.js +363 -0
  11. package/out/src/ShamirWalletManager.js.map +1 -0
  12. package/out/src/Wallet.d.ts +1 -1
  13. package/out/src/Wallet.d.ts.map +1 -1
  14. package/out/src/Wallet.js +23 -7
  15. package/out/src/Wallet.js.map +1 -1
  16. package/out/src/WalletPermissionsManager.d.ts +84 -1
  17. package/out/src/WalletPermissionsManager.d.ts.map +1 -1
  18. package/out/src/WalletPermissionsManager.js +1045 -214
  19. package/out/src/WalletPermissionsManager.js.map +1 -1
  20. package/out/src/__tests/ShamirWalletManager.test.d.ts +2 -0
  21. package/out/src/__tests/ShamirWalletManager.test.d.ts.map +1 -0
  22. package/out/src/__tests/ShamirWalletManager.test.js +298 -0
  23. package/out/src/__tests/ShamirWalletManager.test.js.map +1 -0
  24. package/out/src/__tests/WalletPermissionsManager.callbacks.test.js +134 -0
  25. package/out/src/__tests/WalletPermissionsManager.callbacks.test.js.map +1 -1
  26. package/out/src/__tests/WalletPermissionsManager.fixtures.d.ts.map +1 -1
  27. package/out/src/__tests/WalletPermissionsManager.fixtures.js +9 -0
  28. package/out/src/__tests/WalletPermissionsManager.fixtures.js.map +1 -1
  29. package/out/src/__tests/WalletPermissionsManager.flows.test.js +121 -0
  30. package/out/src/__tests/WalletPermissionsManager.flows.test.js.map +1 -1
  31. package/out/src/__tests/WalletPermissionsManager.pmodules.test.js +111 -0
  32. package/out/src/__tests/WalletPermissionsManager.pmodules.test.js.map +1 -1
  33. package/out/src/entropy/EntropyCollector.d.ts +89 -0
  34. package/out/src/entropy/EntropyCollector.d.ts.map +1 -0
  35. package/out/src/entropy/EntropyCollector.js +176 -0
  36. package/out/src/entropy/EntropyCollector.js.map +1 -0
  37. package/out/src/entropy/__tests/EntropyCollector.test.d.ts +2 -0
  38. package/out/src/entropy/__tests/EntropyCollector.test.d.ts.map +1 -0
  39. package/out/src/entropy/__tests/EntropyCollector.test.js +137 -0
  40. package/out/src/entropy/__tests/EntropyCollector.test.js.map +1 -0
  41. package/out/src/index.all.d.ts +2 -0
  42. package/out/src/index.all.d.ts.map +1 -1
  43. package/out/src/index.all.js +2 -0
  44. package/out/src/index.all.js.map +1 -1
  45. package/out/src/sdk/WalletServices.interfaces.d.ts.map +1 -1
  46. package/out/src/sdk/WalletStorage.interfaces.d.ts +3 -3
  47. package/out/src/sdk/WalletStorage.interfaces.d.ts.map +1 -1
  48. package/out/src/services/__tests/getRawTx.test.js +3 -0
  49. package/out/src/services/__tests/getRawTx.test.js.map +1 -1
  50. package/out/src/services/chaintracker/chaintracks/Ingest/BulkIngestorWhatsOnChainCdn.d.ts +1 -1
  51. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageBase.d.ts.map +1 -1
  52. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageBase.js +4 -1
  53. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageBase.js.map +1 -1
  54. package/out/src/services/chaintracker/chaintracks/__tests/Chaintracks.test.js +3 -1
  55. package/out/src/services/chaintracker/chaintracks/__tests/Chaintracks.test.js.map +1 -1
  56. package/out/src/services/chaintracker/chaintracks/util/blockHeaderUtilities.d.ts.map +1 -1
  57. package/out/src/services/chaintracker/chaintracks/util/blockHeaderUtilities.js +1 -2
  58. package/out/src/services/chaintracker/chaintracks/util/blockHeaderUtilities.js.map +1 -1
  59. package/out/src/services/chaintracker/chaintracks/util/validBulkHeaderFilesByFileHash.d.ts.map +1 -1
  60. package/out/src/services/chaintracker/chaintracks/util/validBulkHeaderFilesByFileHash.js +12 -0
  61. package/out/src/services/chaintracker/chaintracks/util/validBulkHeaderFilesByFileHash.js.map +1 -1
  62. package/out/src/storage/StorageProvider.d.ts +16 -2
  63. package/out/src/storage/StorageProvider.d.ts.map +1 -1
  64. package/out/src/storage/StorageProvider.js +33 -4
  65. package/out/src/storage/StorageProvider.js.map +1 -1
  66. package/out/src/storage/methods/ListOutputsSpecOp.d.ts +15 -1
  67. package/out/src/storage/methods/ListOutputsSpecOp.d.ts.map +1 -1
  68. package/out/src/storage/methods/ListOutputsSpecOp.js +52 -2
  69. package/out/src/storage/methods/ListOutputsSpecOp.js.map +1 -1
  70. package/out/src/storage/methods/__test/offsetKey.test.js +266 -100
  71. package/out/src/storage/methods/__test/offsetKey.test.js.map +1 -1
  72. package/out/src/storage/methods/getBeefForTransaction.js +1 -1
  73. package/out/src/storage/methods/getBeefForTransaction.js.map +1 -1
  74. package/out/src/storage/methods/internalizeAction.d.ts.map +1 -1
  75. package/out/src/storage/methods/internalizeAction.js +2 -2
  76. package/out/src/storage/methods/internalizeAction.js.map +1 -1
  77. package/out/src/storage/methods/listOutputsIdb.d.ts.map +1 -1
  78. package/out/src/storage/methods/listOutputsIdb.js +10 -17
  79. package/out/src/storage/methods/listOutputsIdb.js.map +1 -1
  80. package/out/src/storage/methods/listOutputsKnex.d.ts.map +1 -1
  81. package/out/src/storage/methods/listOutputsKnex.js +44 -26
  82. package/out/src/storage/methods/listOutputsKnex.js.map +1 -1
  83. package/out/src/storage/schema/entities/__tests/ProvenTxTests.test.js +4 -0
  84. package/out/src/storage/schema/entities/__tests/ProvenTxTests.test.js.map +1 -1
  85. package/out/src/wab-client/WABClient.d.ts +65 -0
  86. package/out/src/wab-client/WABClient.d.ts.map +1 -1
  87. package/out/src/wab-client/WABClient.js +107 -0
  88. package/out/src/wab-client/WABClient.js.map +1 -1
  89. package/package.json +8 -4
  90. package/out/src/sdk/validationHelpers.d.ts +0 -303
  91. package/out/src/sdk/validationHelpers.d.ts.map +0 -1
  92. package/out/src/sdk/validationHelpers.js +0 -632
  93. package/out/src/sdk/validationHelpers.js.map +0 -1
  94. package/out/src/utility/ReaderUint8Array.d.ts +0 -28
  95. package/out/src/utility/ReaderUint8Array.d.ts.map +0 -1
  96. package/out/src/utility/ReaderUint8Array.js +0 -166
  97. package/out/src/utility/ReaderUint8Array.js.map +0 -1
package/docs/services.md CHANGED
@@ -610,7 +610,7 @@ enableCache: boolean
610
610
 
611
611
  ###### Property idleWait
612
612
 
613
- Maximum msces of "normal" pause with no new data arriving.
613
+ Maximum msecs of "normal" pause with no new data arriving.
614
614
 
615
615
  ```ts
616
616
  idleWait: number | undefined
@@ -5222,7 +5222,7 @@ Deserialize a BaseBlockHeader from an 80 byte buffer
5222
5222
 
5223
5223
  ```ts
5224
5224
  export function deserializeBaseBlockHeader(buffer: number[] | Uint8Array, offset = 0): BaseBlockHeader {
5225
- const reader = ReaderUint8Array.makeReader(buffer, offset);
5225
+ const reader = Utils.ReaderUint8Array.makeReader(buffer, offset);
5226
5226
  const header: BaseBlockHeader = {
5227
5227
  version: reader.readUInt32LE(),
5228
5228
  previousHash: asString(reader.read(32).reverse()),
@@ -5235,7 +5235,7 @@ export function deserializeBaseBlockHeader(buffer: number[] | Uint8Array, offset
5235
5235
  }
5236
5236
  ```
5237
5237
 
5238
- See also: [BaseBlockHeader](./client.md#interface-baseblockheader), [ReaderUint8Array](./client.md#class-readeruint8array), [asString](./client.md#function-asstring), [readUInt32LE](./services.md#function-readuint32le)
5238
+ See also: [BaseBlockHeader](./client.md#interface-baseblockheader), [asString](./client.md#function-asstring), [readUInt32LE](./services.md#function-readuint32le)
5239
5239
 
5240
5240
  Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
5241
5241
 
@@ -6364,6 +6364,18 @@ validBulkHeaderFiles: BulkHeaderFileInfo[] = [
6364
6364
  prevHash: "00000000000000000e7dcc27c06ee353bd37260b2e7e664314c204f0324a5087",
6365
6365
  sourceUrl: "https://cdn.projectbabbage.com/blockheaders",
6366
6366
  validated: true
6367
+ },
6368
+ {
6369
+ chain: "main",
6370
+ count: 31772,
6371
+ fileHash: "NuVsRUrI5QnjILbYy4LS3A/Udl6PH/m8Y9uVguEsekM=",
6372
+ fileName: "mainNet_9.headers",
6373
+ firstHeight: 900000,
6374
+ lastChainWork: "0000000000000000000000000000000000000000016ab16bb9b31430588788d3",
6375
+ lastHash: "0000000000000000024a2f1caef4b0ffdc1a036b09f9ed7f48b538f619f32ef2",
6376
+ prevChainWork: "000000000000000000000000000000000000000001664db1f2d50327928007e0",
6377
+ prevHash: "00000000000000000e7dcc27c06ee353bd37260b2e7e664314c204f0324a5087",
6378
+ sourceUrl: "https://cdn.projectbabbage.com/blockheaders"
6367
6379
  }
6368
6380
  ]
6369
6381
  ```
package/docs/storage.md CHANGED
@@ -334,6 +334,7 @@ export interface ListOutputsSpecOp {
334
334
  ignoreLimit?: boolean;
335
335
  includeOutputScripts?: boolean;
336
336
  includeSpent?: boolean;
337
+ totalOutputsIsSumOfSatoshis?: boolean;
337
338
  resultFromTags?: (s: StorageProvider, auth: AuthId, vargs: Validation.ValidListOutputsArgs, specOpTags: string[]) => Promise<ListOutputsResult>;
338
339
  resultFromOutputs?: (s: StorageProvider, auth: AuthId, vargs: Validation.ValidListOutputsArgs, specOpTags: string[], outputs: TableOutput[]) => Promise<ListOutputsResult>;
339
340
  filterOutputs?: (s: StorageProvider, auth: AuthId, vargs: Validation.ValidListOutputsArgs, specOpTags: string[], outputs: TableOutput[]) => Promise<TableOutput[]>;
@@ -362,6 +363,14 @@ or an explicit array of tags to intercept.
362
363
  tagsToIntercept?: string[]
363
364
  ```
364
365
 
366
+ ###### Property totalOutputsIsSumOfSatoshis
367
+
368
+ If true, and supported by storage, maximum performance optimization, computing balance done in the query itself.
369
+
370
+ ```ts
371
+ totalOutputsIsSumOfSatoshis?: boolean
372
+ ```
373
+
365
374
  Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
366
375
 
367
376
  ---
@@ -3949,7 +3958,7 @@ export abstract class StorageProvider extends StorageReaderWriter implements Wal
3949
3958
  async listCertificates(auth: AuthId, args: Validation.ValidListCertificatesArgs): Promise<ListCertificatesResult>
3950
3959
  async verifyKnownValidTransaction(txid: string, trx?: TrxToken): Promise<boolean>
3951
3960
  async getValidBeefForKnownTxid(txid: string, mergeToBeef?: Beef, trustSelf?: TrustSelf, knownTxids?: string[], trx?: TrxToken, requiredLevels?: number): Promise<Beef>
3952
- async getValidBeefForTxid(txid: string, mergeToBeef?: Beef, trustSelf?: TrustSelf, knownTxids?: string[], trx?: TrxToken, requiredLevels?: number): Promise<Beef | undefined>
3961
+ async getValidBeefForTxid(txid: string, mergeToBeef?: Beef, trustSelf?: TrustSelf, knownTxids?: string[], trx?: TrxToken, requiredLevels?: number, chainTracker?: ChainTracker, skipInvalidProofs?: boolean): Promise<Beef | undefined>
3953
3962
  async getBeefForTransaction(txid: string, options: StorageGetBeefOptions): Promise<Beef>
3954
3963
  async findMonitorEventById(id: number, trx?: TrxToken): Promise<TableMonitorEvent | undefined>
3955
3964
  async relinquishCertificate(auth: AuthId, args: RelinquishCertificateArgs): Promise<number>
@@ -4010,6 +4019,18 @@ async getReqsAndBeefToShareWithWorld(txids: string[], knownTxids: string[], trx?
4010
4019
  ```
4011
4020
  See also: [GetReqsAndBeefResult](./storage.md#interface-getreqsandbeefresult), [TrxToken](./client.md#interface-trxtoken)
4012
4021
 
4022
+ ###### Method getValidBeefForKnownTxid
4023
+
4024
+ Pulls data from storage to build a valid beef for a txid.
4025
+
4026
+ Optionally merges the data into an existing beef.
4027
+ Optionally requires a minimum number of proof levels.
4028
+
4029
+ ```ts
4030
+ async getValidBeefForKnownTxid(txid: string, mergeToBeef?: Beef, trustSelf?: TrustSelf, knownTxids?: string[], trx?: TrxToken, requiredLevels?: number): Promise<Beef>
4031
+ ```
4032
+ See also: [TrxToken](./client.md#interface-trxtoken)
4033
+
4013
4034
  ###### Method updateProvenTxReqWithNewProvenTx
4014
4035
 
4015
4036
  Handles storage changes when a valid MerklePath and mined block header are found for a ProvenTxReq txid.
@@ -4583,18 +4604,18 @@ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](
4583
4604
 
4584
4605
  | | | |
4585
4606
  | --- | --- | --- |
4586
- | [attemptToPostReqsToNetwork](#function-attempttopostreqstonetwork) | [listActionsIdb](#function-listactionsidb) | [reviewStatusIdb](#function-reviewstatusidb) |
4587
- | [createAction](#function-createaction) | [listCertificates](#function-listcertificates) | [setDisableDoubleSpendCheckForTest](#function-setdisabledoublespendcheckfortest) |
4588
- | [createStorageServiceChargeScript](#function-createstorageservicechargescript) | [listOutputs](#function-listoutputs) | [shareReqsWithWorld](#function-sharereqswithworld) |
4589
- | [createSyncMap](#function-createsyncmap) | [listOutputsIdb](#function-listoutputsidb) | [transactionInputSize](#function-transactioninputsize) |
4590
- | [determineDBType](#function-determinedbtype) | [lockScriptWithKeyOffsetFromPubKey](#function-lockscriptwithkeyoffsetfrompubkey) | [transactionOutputSize](#function-transactionoutputsize) |
4591
- | [generateChangeSdk](#function-generatechangesdk) | [offsetPrivKey](#function-offsetprivkey) | [transactionSize](#function-transactionsize) |
4592
- | [generateChangeSdkMakeStorage](#function-generatechangesdkmakestorage) | [offsetPubKey](#function-offsetpubkey) | [validateGenerateChangeSdkParams](#function-validategeneratechangesdkparams) |
4593
- | [getBeefForTransaction](#function-getbeeffortransaction) | [processAction](#function-processaction) | [validateGenerateChangeSdkResult](#function-validategeneratechangesdkresult) |
4607
+ | [attemptToPostReqsToNetwork](#function-attempttopostreqstonetwork) | [listActions](#function-listactions) | [reviewStatus](#function-reviewstatus) |
4608
+ | [createAction](#function-createaction) | [listActionsIdb](#function-listactionsidb) | [reviewStatusIdb](#function-reviewstatusidb) |
4609
+ | [createStorageServiceChargeScript](#function-createstorageservicechargescript) | [listCertificates](#function-listcertificates) | [setDisableDoubleSpendCheckForTest](#function-setdisabledoublespendcheckfortest) |
4610
+ | [createSyncMap](#function-createsyncmap) | [listOutputs](#function-listoutputs) | [shareReqsWithWorld](#function-sharereqswithworld) |
4611
+ | [determineDBType](#function-determinedbtype) | [listOutputsIdb](#function-listoutputsidb) | [transactionInputSize](#function-transactioninputsize) |
4612
+ | [generateChangeSdk](#function-generatechangesdk) | [lockScriptWithKeyOffsetFromPubKey](#function-lockscriptwithkeyoffsetfrompubkey) | [transactionOutputSize](#function-transactionoutputsize) |
4613
+ | [generateChangeSdkMakeStorage](#function-generatechangesdkmakestorage) | [offsetPrivKey](#function-offsetprivkey) | [transactionSize](#function-transactionsize) |
4614
+ | [getBeefForTransaction](#function-getbeeffortransaction) | [offsetPubKey](#function-offsetpubkey) | [validateGenerateChangeSdkParams](#function-validategeneratechangesdkparams) |
4615
+ | [getListOutputsSpecOp](#function-getlistoutputsspecop) | [processAction](#function-processaction) | [validateGenerateChangeSdkResult](#function-validategeneratechangesdkresult) |
4594
4616
  | [getSyncChunk](#function-getsyncchunk) | [purgeData](#function-purgedata) | [validateStorageFeeModel](#function-validatestoragefeemodel) |
4595
4617
  | [internalizeAction](#function-internalizeaction) | [purgeDataIdb](#function-purgedataidb) | [varUintSize](#function-varuintsize) |
4596
4618
  | [keyOffsetToHashedSecret](#function-keyoffsettohashedsecret) | [redeemServiceCharges](#function-redeemservicecharges) | |
4597
- | [listActions](#function-listactions) | [reviewStatus](#function-reviewstatus) | |
4598
4619
 
4599
4620
  Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
4600
4621
 
@@ -4725,6 +4746,23 @@ Argument Details
4725
4746
 
4726
4747
  Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
4727
4748
 
4749
+ ---
4750
+ ##### Function: getListOutputsSpecOp
4751
+
4752
+ Check basket and tags arguments passed to listOutputs to determine if they trigger a special operation execution mode.
4753
+
4754
+ ```ts
4755
+ export function getListOutputsSpecOp(basket: string, tags: string[]): {
4756
+ specOp: ListOutputsSpecOp | undefined;
4757
+ basket?: string;
4758
+ tags: string[];
4759
+ }
4760
+ ```
4761
+
4762
+ See also: [ListOutputsSpecOp](./storage.md#interface-listoutputsspecop)
4763
+
4764
+ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
4765
+
4728
4766
  ---
4729
4767
  ##### Function: getSyncChunk
4730
4768
 
@@ -5167,7 +5205,6 @@ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](
5167
5205
 
5168
5206
  | |
5169
5207
  | --- |
5170
- | [getBasketToSpecOp](#variable-getbaskettospecop) |
5171
5208
  | [getLabelToSpecOp](#variable-getlabeltospecop) |
5172
5209
  | [maxPossibleSatoshis](#variable-maxpossiblesatoshis) |
5173
5210
  | [outputColumnsWithoutLockingScript](#variable-outputcolumnswithoutlockingscript) |
@@ -5177,83 +5214,6 @@ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](
5177
5214
 
5178
5215
  ---
5179
5216
 
5180
- ##### Variable: getBasketToSpecOp
5181
-
5182
- ```ts
5183
- getBasketToSpecOp: () => Record<string, ListOutputsSpecOp> = () => {
5184
- return {
5185
- [specOpWalletBalance]: {
5186
- name: "totalOutputsIsWalletBalance",
5187
- useBasket: "default",
5188
- ignoreLimit: true,
5189
- resultFromOutputs: async (s: StorageProvider, auth: AuthId, vargs: Validation.ValidListOutputsArgs, specOpTags: string[], outputs: TableOutput[]): Promise<ListOutputsResult> => {
5190
- let totalOutputs = 0;
5191
- for (const o of outputs)
5192
- totalOutputs += o.satoshis;
5193
- return { totalOutputs, outputs: [] };
5194
- }
5195
- },
5196
- [specOpInvalidChange]: {
5197
- name: "invalidChangeOutputs",
5198
- useBasket: "default",
5199
- ignoreLimit: true,
5200
- includeOutputScripts: true,
5201
- includeSpent: false,
5202
- tagsToIntercept: ["release", "all"],
5203
- filterOutputs: async (s: StorageProvider, auth: AuthId, vargs: Validation.ValidListOutputsArgs, specOpTags: string[], outputs: TableOutput[]): Promise<TableOutput[]> => {
5204
- const filteredOutputs: TableOutput[] = [];
5205
- const services = s.getServices();
5206
- for (const o of outputs) {
5207
- if (!o.basketId)
5208
- continue;
5209
- await s.validateOutputScript(o);
5210
- let ok: boolean | undefined = false;
5211
- if (o.lockingScript && o.lockingScript.length > 0) {
5212
- ok = await services.isUtxo(o);
5213
- }
5214
- else {
5215
- ok = undefined;
5216
- }
5217
- if (ok === false) {
5218
- filteredOutputs.push(o);
5219
- }
5220
- }
5221
- if (specOpTags.indexOf("release") >= 0) {
5222
- for (const o of filteredOutputs) {
5223
- await s.updateOutput(o.outputId, { spendable: false });
5224
- o.spendable = false;
5225
- }
5226
- }
5227
- return filteredOutputs;
5228
- }
5229
- },
5230
- [specOpSetWalletChangeParams]: {
5231
- name: "setWalletChangeParams",
5232
- tagsParamsCount: 2,
5233
- resultFromTags: async (s: StorageProvider, auth: AuthId, vargs: Validation.ValidListOutputsArgs, specOpTags: string[]): Promise<ListOutputsResult> => {
5234
- if (specOpTags.length !== 2)
5235
- throw new WERR_INVALID_PARAMETER("numberOfDesiredUTXOs and minimumDesiredUTXOValue", "valid");
5236
- const numberOfDesiredUTXOs: number = verifyInteger(Number(specOpTags[0]));
5237
- const minimumDesiredUTXOValue: number = verifyInteger(Number(specOpTags[1]));
5238
- const basket = verifyOne(await s.findOutputBaskets({
5239
- partial: { userId: verifyId(auth.userId), name: "default" }
5240
- }));
5241
- await s.updateOutputBasket(basket.basketId, {
5242
- numberOfDesiredUTXOs,
5243
- minimumDesiredUTXOValue
5244
- });
5245
- return { totalOutputs: 0, outputs: [] };
5246
- }
5247
- }
5248
- };
5249
- }
5250
- ```
5251
-
5252
- See also: [AuthId](./client.md#interface-authid), [ListOutputsSpecOp](./storage.md#interface-listoutputsspecop), [StorageProvider](./storage.md#class-storageprovider), [TableOutput](./storage.md#interface-tableoutput), [WERR_INVALID_PARAMETER](./client.md#class-werr_invalid_parameter), [specOpInvalidChange](./client.md#variable-specopinvalidchange), [specOpSetWalletChangeParams](./client.md#variable-specopsetwalletchangeparams), [specOpWalletBalance](./client.md#variable-specopwalletbalance), [verifyId](./client.md#function-verifyid), [verifyInteger](./client.md#function-verifyinteger), [verifyOne](./client.md#function-verifyone)
5253
-
5254
- Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
5255
-
5256
- ---
5257
5217
  ##### Variable: getLabelToSpecOp
5258
5218
 
5259
5219
  ```ts
@@ -0,0 +1,311 @@
1
+ # WAB Shamir Key Recovery
2
+
3
+ This guide covers the Shamir Secret Sharing key recovery system, which provides secure wallet backup and recovery using a configurable threshold scheme.
4
+
5
+ ## Overview
6
+
7
+ The Shamir system splits your wallet's root private key into multiple shares. A configurable threshold of shares can reconstruct the key:
8
+
9
+ - **Server share**: Stored on WAB server, released only after OTP verification
10
+ - **User shares**: Application decides how to store (print, password manager, hardware device, etc.)
11
+
12
+ **Default configuration (2-of-3):**
13
+ - 3 total shares, 2 required to reconstruct
14
+ - Server holds 1 share, user receives 2 shares
15
+ - Any 2 shares can recover the key
16
+
17
+ **Example configurations:**
18
+
19
+ | Threshold | Total | Server | User Shares | Use Case |
20
+ |-----------|-------|--------|-------------|----------|
21
+ | 2 | 3 | 1 | 2 | Standard (default) |
22
+ | 2 | 4 | 1 | 3 | Extra redundancy |
23
+ | 3 | 5 | 1 | 4 | High security |
24
+ | 3 | 4 | 1 | 3 | Balanced security |
25
+
26
+ **Important constraint:** User must always have at least `threshold` shares so they can recover independently without the server. This prevents the WAB from becoming a custodian of user funds. For example, 2-of-2 is not allowed because the user would only have 1 share and could not recover without server cooperation.
27
+
28
+ The WAB server always stores exactly one share and cannot reconstruct the key alone.
29
+
30
+ ## Generating a Secure Key with Entropy Collection
31
+
32
+ For maximum security, keys are generated using mouse movement entropy mixed with the system's cryptographically secure random number generator (CSPRNG).
33
+
34
+ ```ts
35
+ import { EntropyCollector } from '@bsv/wallet-toolbox'
36
+
37
+ // Create collector (default: 256 samples)
38
+ const collector = new EntropyCollector({
39
+ targetSamples: 256,
40
+ minSampleInterval: 10 // ms between samples
41
+ })
42
+
43
+ // Option 1: Manual collection from mousemove events
44
+ document.addEventListener('mousemove', (event) => {
45
+ const progress = collector.addMouseSample(event.clientX, event.clientY)
46
+ if (progress) {
47
+ console.log(`Entropy: ${progress.percent}% (${progress.collected}/${progress.target})`)
48
+ }
49
+ })
50
+
51
+ // Check when complete
52
+ if (collector.isComplete()) {
53
+ const entropy = collector.generateEntropy() // 32 bytes
54
+ }
55
+
56
+ // Option 2: Automatic browser collection with progress callback
57
+ const entropy = await collector.collectFromBrowser(document, (progress) => {
58
+ updateProgressBar(progress.percent)
59
+ })
60
+ ```
61
+
62
+ The `generateEntropy()` method:
63
+ 1. Extracts raw entropy from mouse positions and timing
64
+ 2. Hashes it with SHA-256 to whiten the data
65
+ 3. XORs with `crypto.getRandomValues()` output
66
+ 4. Final SHA-256 hash ensures uniform distribution
67
+
68
+ ## Using ShamirWalletManager
69
+
70
+ The `ShamirWalletManager` class handles the complete wallet lifecycle with Shamir shares.
71
+
72
+ ### Configuration
73
+
74
+ ```ts
75
+ import { ShamirWalletManager, Setup, PrivateKey, PrivilegedKeyManager } from '@bsv/wallet-toolbox'
76
+
77
+ const manager = new ShamirWalletManager({
78
+ wabServerUrl: 'https://your-wab-server.com',
79
+ authMethodType: 'TwilioPhone', // or 'DevConsole' for development
80
+
81
+ // Optional: customize threshold scheme (defaults to 2-of-3)
82
+ threshold: 2, // shares needed to reconstruct (min: 2)
83
+ totalShares: 3, // total shares generated (min: 3, must be >= threshold + 1)
84
+
85
+ walletBuilder: async (privateKey, privilegedKeyManager) => {
86
+ const { wallet } = await Setup.createWalletSQLite({
87
+ filePath: './wallet.sqlite',
88
+ databaseName: 'myWallet',
89
+ chain: 'main',
90
+ rootKeyHex: privateKey.toHex(),
91
+ privilegedKeyManager
92
+ })
93
+ return wallet
94
+ }
95
+ })
96
+
97
+ // Check configuration
98
+ console.log(`Using ${manager.getThreshold()}-of-${manager.getTotalShares()} scheme`)
99
+ ```
100
+
101
+ ### Creating a New Wallet
102
+
103
+ ```ts
104
+ // 1. Collect entropy (show user a "move your mouse" UI)
105
+ await manager.collectEntropyFromBrowser(document, (progress) => {
106
+ document.getElementById('progress').textContent = `${progress.percent}%`
107
+ })
108
+
109
+ // 2. Start OTP verification (user receives SMS)
110
+ const wabClient = new WABClient('https://your-wab-server.com')
111
+ await wabClient.startShareAuth('TwilioPhone', userIdHash, {
112
+ phoneNumber: '+1234567890'
113
+ })
114
+
115
+ // 3. User enters OTP code, then create wallet
116
+ const result = await manager.createNewWallet(
117
+ { phoneNumber: '+1234567890', otp: '123456' },
118
+ async (userShares, threshold, totalShares) => {
119
+ // Application decides how to handle user shares
120
+ // For 2-of-3: userShares has 2 shares
121
+ console.log(`Save these ${userShares.length} shares (${threshold}-of-${totalShares} scheme)`)
122
+
123
+ // Example: first share for printing, second for password manager
124
+ await showPrintableBackup(userShares[0])
125
+ await showCopyableText(userShares[1])
126
+
127
+ return await confirmUserSavedShares()
128
+ }
129
+ )
130
+
131
+ console.log('User ID Hash:', result.userIdHash)
132
+ console.log('User Shares:', result.userShares)
133
+ console.log(`Scheme: ${result.threshold}-of-${result.totalShares}`)
134
+
135
+ // 4. Build and use the wallet
136
+ const wallet = await manager.buildWallet()
137
+ ```
138
+
139
+ ### Recovery with Server Share
140
+
141
+ When the user has enough shares but needs the server share to meet threshold:
142
+
143
+ ```ts
144
+ const manager = new ShamirWalletManager({ /* config */ })
145
+
146
+ // User provides their userIdHash
147
+ manager.setUserIdHash(savedUserIdHash)
148
+
149
+ // Start OTP to retrieve server share
150
+ await manager.startOTPVerification({ phoneNumber: '+1234567890' })
151
+
152
+ // Recover with user shares (need threshold-1 shares)
153
+ // For 2-of-3: need 1 user share + server share
154
+ const privateKey = await manager.recoverWithServerShare(
155
+ [userShare1], // Array of user-held shares
156
+ { phoneNumber: '+1234567890', otp: '123456' }
157
+ )
158
+
159
+ const wallet = await manager.buildWallet()
160
+ ```
161
+
162
+ ### Recovery with User Shares Only (Offline)
163
+
164
+ When the user has enough shares to meet threshold without the server:
165
+
166
+ ```ts
167
+ const manager = new ShamirWalletManager({ /* config */ })
168
+
169
+ // Recover using user-held shares (need at least threshold shares)
170
+ // For 2-of-3: need 2 user shares
171
+ const privateKey = await manager.recoverWithUserShares([userShare1, userShare2])
172
+
173
+ const wallet = await manager.buildWallet()
174
+ ```
175
+
176
+ ## Using WABClient Directly
177
+
178
+ For lower-level control, use `WABClient` directly:
179
+
180
+ ```ts
181
+ import { WABClient } from '@bsv/wallet-toolbox'
182
+
183
+ const client = new WABClient('https://your-wab-server.com')
184
+
185
+ // Start OTP verification
186
+ await client.startShareAuth('TwilioPhone', userIdHash, {
187
+ phoneNumber: '+1234567890'
188
+ })
189
+
190
+ // Store the server share (after OTP verification)
191
+ const storeResult = await client.storeShare(
192
+ 'TwilioPhone',
193
+ { phoneNumber: '+1234567890', otp: '123456' },
194
+ serverShare, // The share to store (format: x.y.threshold.integrity)
195
+ userIdHash
196
+ )
197
+
198
+ // Retrieve the server share (requires OTP)
199
+ const retrieveResult = await client.retrieveShare(
200
+ 'TwilioPhone',
201
+ { phoneNumber: '+1234567890', otp: '654321' },
202
+ userIdHash
203
+ )
204
+ console.log('Retrieved server share:', retrieveResult.shareB)
205
+
206
+ // Update share (for key rotation)
207
+ await client.updateShare(
208
+ 'TwilioPhone',
209
+ { phoneNumber: '+1234567890', otp: '111222' },
210
+ userIdHash,
211
+ newServerShare
212
+ )
213
+
214
+ // Delete account and stored share
215
+ await client.deleteShamirUser(
216
+ 'TwilioPhone',
217
+ { phoneNumber: '+1234567890', otp: '333444' },
218
+ userIdHash
219
+ )
220
+ ```
221
+
222
+ ## Key Rotation
223
+
224
+ To rotate keys (generate new shares while maintaining access):
225
+
226
+ ```ts
227
+ // Collect fresh entropy
228
+ manager.resetEntropy()
229
+ await manager.collectEntropyFromBrowser(document, onProgress)
230
+
231
+ // Rotate keys (requires OTP verification)
232
+ const newResult = await manager.rotateKeys(
233
+ { phoneNumber: '+1234567890', otp: '123456' },
234
+ async (userShares, threshold, totalShares) => {
235
+ console.log(`Save these ${userShares.length} NEW shares`)
236
+ // User must save all new shares
237
+ return await confirmUserSavedShares()
238
+ }
239
+ )
240
+
241
+ // Server share is automatically updated
242
+ // User must save new user shares
243
+ ```
244
+
245
+ ## Account Deletion
246
+
247
+ To delete a Shamir account and its stored share:
248
+
249
+ ```ts
250
+ // Requires OTP verification
251
+ await manager.deleteAccount({
252
+ phoneNumber: '+1234567890',
253
+ otp: '123456'
254
+ })
255
+ // WARNING: Server share is permanently deleted
256
+ // User needs enough remaining shares to meet threshold
257
+ ```
258
+
259
+ ## Share Format
260
+
261
+ Shamir shares use the format: `x.y.threshold.integrity`
262
+
263
+ - **x**: Share index (1, 2, 3, ...)
264
+ - **y**: Share data (Base58 encoded)
265
+ - **threshold**: Number of shares required (e.g., 2)
266
+ - **integrity**: Checksum for validation
267
+
268
+ Example share:
269
+ ```
270
+ 1.7KvWLhJ3rQ9FnBZxYmUdNpTsR6CwEiAoH8bVfGjDkM2.2.5XyZ
271
+ ```
272
+
273
+ ## Security Considerations
274
+
275
+ 1. **Share Storage**: Store user shares in separate, secure locations
276
+ 2. **Threshold Selection**: Higher threshold = more security but less convenience
277
+ 3. **OTP Security**: Consider SIM-swap risks with SMS; email may be safer for some users
278
+ 4. **Entropy Quality**: Always collect full entropy before key generation
279
+ 5. **User ID Hash**: Store separately - it identifies your account but cannot recover keys
280
+
281
+ ### Recommended Share Storage by Scheme
282
+
283
+ **2-of-3 (default):**
284
+ - Share 1: Print and store in safe/safety deposit box
285
+ - Share 2: Save in password manager
286
+
287
+ **3-of-5 (high security):**
288
+ - Share 1: Print and store in safe
289
+ - Share 2: Save in password manager
290
+ - Share 3: Store on hardware device (USB)
291
+ - Share 4: Give to trusted family member
292
+
293
+ ## Error Handling
294
+
295
+ ```ts
296
+ try {
297
+ await manager.recoverWithServerShare(userShares, authPayload)
298
+ } catch (error) {
299
+ if (error.message.includes('Rate limited')) {
300
+ // Too many attempts - wait and retry
301
+ } else if (error.message.includes('OTP verification failed')) {
302
+ // Wrong code - let user retry
303
+ } else if (error.message.includes('integrity check failed')) {
304
+ // Shares don't match - wrong share or corrupted
305
+ } else if (error.message.includes('Need at least')) {
306
+ // Not enough shares provided
307
+ }
308
+ }
309
+ ```
310
+
311
+ [Return to Documentation](./README.md)