@bsv/wallet-toolbox 1.7.22 → 1.8.2
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 +8 -0
- package/docs/README.md +1 -0
- package/docs/client.md +135 -0
- package/docs/wab-shamir.md +311 -0
- package/docs/wallet.md +135 -0
- package/out/src/ShamirWalletManager.d.ts +213 -0
- package/out/src/ShamirWalletManager.d.ts.map +1 -0
- package/out/src/ShamirWalletManager.js +363 -0
- package/out/src/ShamirWalletManager.js.map +1 -0
- package/out/src/WalletPermissionsManager.d.ts +27 -0
- package/out/src/WalletPermissionsManager.d.ts.map +1 -1
- package/out/src/WalletPermissionsManager.js +308 -147
- package/out/src/WalletPermissionsManager.js.map +1 -1
- package/out/src/__tests/ShamirWalletManager.test.d.ts +2 -0
- package/out/src/__tests/ShamirWalletManager.test.d.ts.map +1 -0
- package/out/src/__tests/ShamirWalletManager.test.js +298 -0
- package/out/src/__tests/ShamirWalletManager.test.js.map +1 -0
- package/out/src/__tests/WalletPermissionsManager.callbacks.test.js +116 -0
- package/out/src/__tests/WalletPermissionsManager.callbacks.test.js.map +1 -1
- package/out/src/__tests/WalletPermissionsManager.pmodules.test.js +111 -0
- package/out/src/__tests/WalletPermissionsManager.pmodules.test.js.map +1 -1
- package/out/src/entropy/EntropyCollector.d.ts +89 -0
- package/out/src/entropy/EntropyCollector.d.ts.map +1 -0
- package/out/src/entropy/EntropyCollector.js +176 -0
- package/out/src/entropy/EntropyCollector.js.map +1 -0
- package/out/src/entropy/__tests/EntropyCollector.test.d.ts +2 -0
- package/out/src/entropy/__tests/EntropyCollector.test.d.ts.map +1 -0
- package/out/src/entropy/__tests/EntropyCollector.test.js +137 -0
- package/out/src/entropy/__tests/EntropyCollector.test.js.map +1 -0
- package/out/src/index.all.d.ts +2 -0
- package/out/src/index.all.d.ts.map +1 -1
- package/out/src/index.all.js +2 -0
- package/out/src/index.all.js.map +1 -1
- package/out/src/sdk/WalletServices.interfaces.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageBase.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageBase.js +4 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageBase.js.map +1 -1
- package/out/src/wab-client/WABClient.d.ts +65 -0
- package/out/src/wab-client/WABClient.d.ts.map +1 -1
- package/out/src/wab-client/WABClient.js +107 -0
- package/out/src/wab-client/WABClient.js.map +1 -1
- package/out/tsconfig.all.tsbuildinfo +1 -1
- package/package.json +5 -1
- package/src/ShamirWalletManager.ts +499 -0
- package/src/WalletPermissionsManager.ts +368 -181
- package/src/__tests/ShamirWalletManager.test.ts +369 -0
- package/src/__tests/WalletPermissionsManager.callbacks.test.ts +140 -1
- package/src/__tests/WalletPermissionsManager.pmodules.test.ts +152 -0
- package/src/entropy/EntropyCollector.ts +228 -0
- package/src/entropy/__tests/EntropyCollector.test.ts +182 -0
- package/src/index.all.ts +2 -0
- package/src/sdk/WalletServices.interfaces.ts +0 -1
- package/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageBase.ts +4 -1
- package/src/wab-client/WABClient.ts +135 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,14 @@ This document captures the history of significant changes to the wallet-toolbox
|
|
|
4
4
|
The git commit history contains the details but is unable to draw
|
|
5
5
|
attention to changes that materially alter behavior or extend functionality.
|
|
6
6
|
|
|
7
|
+
## wallet-toolbox 1.7.24
|
|
8
|
+
|
|
9
|
+
- Add full P-label (permissioned label) support per BRC-111 specification.
|
|
10
|
+
- Implement P-label format validation: p <moduleId> <payload> with strict parsing rules.
|
|
11
|
+
- Updated createAction, internalizeAction, and listActions to handle P-labels with permission module delegation.
|
|
12
|
+
- Add comprehensive test coverage for P-label delegation, multi-module chaining, and format validation.
|
|
13
|
+
- Added small fix to reject pending promises on grantGroupedPermission error.
|
|
14
|
+
|
|
7
15
|
## wallet-toolbox 1.7.17
|
|
8
16
|
|
|
9
17
|
- Fix push.yaml to sync versions, correct root package contents (no mobile), and publish client and mobile
|
package/docs/README.md
CHANGED
|
@@ -9,6 +9,7 @@ The documentation is split into various pages, each covering a set of related fu
|
|
|
9
9
|
- [Storage](./storage.md) — Wallet data persistent storage classes and related APIs.
|
|
10
10
|
- [Services](./services.md) — Support for abstracted external network services.
|
|
11
11
|
- [Monitor](./monitor.md) — Background task manager for wallet action validation and processing.
|
|
12
|
+
- [WAB Shamir](./wab-shamir.md) — Shamir 2-of-3 key recovery system with entropy collection and WAB server integration.
|
|
12
13
|
|
|
13
14
|
## Open API
|
|
14
15
|
|
package/docs/client.md
CHANGED
|
@@ -14069,6 +14069,29 @@ export class WABClient {
|
|
|
14069
14069
|
public async unlinkMethod(presentationKey: string, authMethodId: number)
|
|
14070
14070
|
public async requestFaucet(presentationKey: string)
|
|
14071
14071
|
public async deleteUser(presentationKey: string)
|
|
14072
|
+
public async startShareAuth(methodType: string, userIdHash: string, payload: any): Promise<{
|
|
14073
|
+
success: boolean;
|
|
14074
|
+
message: string;
|
|
14075
|
+
}>
|
|
14076
|
+
public async storeShare(methodType: string, payload: any, shareB: string, userIdHash: string): Promise<{
|
|
14077
|
+
success: boolean;
|
|
14078
|
+
message: string;
|
|
14079
|
+
userId?: number;
|
|
14080
|
+
}>
|
|
14081
|
+
public async retrieveShare(methodType: string, payload: any, userIdHash: string): Promise<{
|
|
14082
|
+
success: boolean;
|
|
14083
|
+
shareB?: string;
|
|
14084
|
+
message: string;
|
|
14085
|
+
}>
|
|
14086
|
+
public async updateShare(methodType: string, payload: any, userIdHash: string, newShareB: string): Promise<{
|
|
14087
|
+
success: boolean;
|
|
14088
|
+
message: string;
|
|
14089
|
+
shareVersion?: number;
|
|
14090
|
+
}>
|
|
14091
|
+
public async deleteShamirUser(methodType: string, payload: any, userIdHash: string): Promise<{
|
|
14092
|
+
success: boolean;
|
|
14093
|
+
message: string;
|
|
14094
|
+
}>
|
|
14072
14095
|
}
|
|
14073
14096
|
```
|
|
14074
14097
|
|
|
@@ -14083,6 +14106,27 @@ public async completeAuthMethod(authMethod: AuthMethodInteractor, presentationKe
|
|
|
14083
14106
|
```
|
|
14084
14107
|
See also: [AuthMethodInteractor](./client.md#class-authmethodinteractor)
|
|
14085
14108
|
|
|
14109
|
+
###### Method deleteShamirUser
|
|
14110
|
+
|
|
14111
|
+
Delete a Shamir user's account and stored share
|
|
14112
|
+
Requires OTP verification
|
|
14113
|
+
|
|
14114
|
+
```ts
|
|
14115
|
+
public async deleteShamirUser(methodType: string, payload: any, userIdHash: string): Promise<{
|
|
14116
|
+
success: boolean;
|
|
14117
|
+
message: string;
|
|
14118
|
+
}>
|
|
14119
|
+
```
|
|
14120
|
+
|
|
14121
|
+
Argument Details
|
|
14122
|
+
|
|
14123
|
+
+ **methodType**
|
|
14124
|
+
+ The auth method type used for verification
|
|
14125
|
+
+ **payload**
|
|
14126
|
+
+ Contains the OTP code and auth method specific data
|
|
14127
|
+
+ **userIdHash**
|
|
14128
|
+
+ SHA256 hash of the user's identity key
|
|
14129
|
+
|
|
14086
14130
|
###### Method deleteUser
|
|
14087
14131
|
|
|
14088
14132
|
Delete user
|
|
@@ -14123,6 +14167,28 @@ Request faucet
|
|
|
14123
14167
|
public async requestFaucet(presentationKey: string)
|
|
14124
14168
|
```
|
|
14125
14169
|
|
|
14170
|
+
###### Method retrieveShare
|
|
14171
|
+
|
|
14172
|
+
Retrieve a Shamir share (Share B) from the server
|
|
14173
|
+
Requires OTP verification
|
|
14174
|
+
|
|
14175
|
+
```ts
|
|
14176
|
+
public async retrieveShare(methodType: string, payload: any, userIdHash: string): Promise<{
|
|
14177
|
+
success: boolean;
|
|
14178
|
+
shareB?: string;
|
|
14179
|
+
message: string;
|
|
14180
|
+
}>
|
|
14181
|
+
```
|
|
14182
|
+
|
|
14183
|
+
Argument Details
|
|
14184
|
+
|
|
14185
|
+
+ **methodType**
|
|
14186
|
+
+ The auth method type used for verification
|
|
14187
|
+
+ **payload**
|
|
14188
|
+
+ Contains the OTP code and auth method specific data
|
|
14189
|
+
+ **userIdHash**
|
|
14190
|
+
+ SHA256 hash of the user's identity key
|
|
14191
|
+
|
|
14126
14192
|
###### Method startAuthMethod
|
|
14127
14193
|
|
|
14128
14194
|
Start an Auth Method flow
|
|
@@ -14132,6 +14198,51 @@ public async startAuthMethod(authMethod: AuthMethodInteractor, presentationKey:
|
|
|
14132
14198
|
```
|
|
14133
14199
|
See also: [AuthMethodInteractor](./client.md#class-authmethodinteractor)
|
|
14134
14200
|
|
|
14201
|
+
###### Method startShareAuth
|
|
14202
|
+
|
|
14203
|
+
Start OTP verification for share operations
|
|
14204
|
+
This initiates the auth flow (e.g., sends SMS code via Twilio)
|
|
14205
|
+
|
|
14206
|
+
```ts
|
|
14207
|
+
public async startShareAuth(methodType: string, userIdHash: string, payload: any): Promise<{
|
|
14208
|
+
success: boolean;
|
|
14209
|
+
message: string;
|
|
14210
|
+
}>
|
|
14211
|
+
```
|
|
14212
|
+
|
|
14213
|
+
Argument Details
|
|
14214
|
+
|
|
14215
|
+
+ **methodType**
|
|
14216
|
+
+ The auth method type (e.g., "TwilioPhone", "DevConsole")
|
|
14217
|
+
+ **userIdHash**
|
|
14218
|
+
+ SHA256 hash of the user's identity key
|
|
14219
|
+
+ **payload**
|
|
14220
|
+
+ Auth method specific data (e.g., { phoneNumber: "+1..." })
|
|
14221
|
+
|
|
14222
|
+
###### Method storeShare
|
|
14223
|
+
|
|
14224
|
+
Store a Shamir share (Share B) on the server
|
|
14225
|
+
Requires prior OTP verification via startShareAuth
|
|
14226
|
+
|
|
14227
|
+
```ts
|
|
14228
|
+
public async storeShare(methodType: string, payload: any, shareB: string, userIdHash: string): Promise<{
|
|
14229
|
+
success: boolean;
|
|
14230
|
+
message: string;
|
|
14231
|
+
userId?: number;
|
|
14232
|
+
}>
|
|
14233
|
+
```
|
|
14234
|
+
|
|
14235
|
+
Argument Details
|
|
14236
|
+
|
|
14237
|
+
+ **methodType**
|
|
14238
|
+
+ The auth method type used for verification
|
|
14239
|
+
+ **payload**
|
|
14240
|
+
+ Contains the OTP code and auth method specific data
|
|
14241
|
+
+ **shareB**
|
|
14242
|
+
+ The Shamir share to store (format: x.y.threshold.integrity)
|
|
14243
|
+
+ **userIdHash**
|
|
14244
|
+
+ SHA256 hash of the user's identity key
|
|
14245
|
+
|
|
14135
14246
|
###### Method unlinkMethod
|
|
14136
14247
|
|
|
14137
14248
|
Unlink a given Auth Method by ID
|
|
@@ -14140,6 +14251,30 @@ Unlink a given Auth Method by ID
|
|
|
14140
14251
|
public async unlinkMethod(presentationKey: string, authMethodId: number)
|
|
14141
14252
|
```
|
|
14142
14253
|
|
|
14254
|
+
###### Method updateShare
|
|
14255
|
+
|
|
14256
|
+
Update a Shamir share (for key rotation)
|
|
14257
|
+
Requires OTP verification
|
|
14258
|
+
|
|
14259
|
+
```ts
|
|
14260
|
+
public async updateShare(methodType: string, payload: any, userIdHash: string, newShareB: string): Promise<{
|
|
14261
|
+
success: boolean;
|
|
14262
|
+
message: string;
|
|
14263
|
+
shareVersion?: number;
|
|
14264
|
+
}>
|
|
14265
|
+
```
|
|
14266
|
+
|
|
14267
|
+
Argument Details
|
|
14268
|
+
|
|
14269
|
+
+ **methodType**
|
|
14270
|
+
+ The auth method type used for verification
|
|
14271
|
+
+ **payload**
|
|
14272
|
+
+ Contains the OTP code and auth method specific data
|
|
14273
|
+
+ **userIdHash**
|
|
14274
|
+
+ SHA256 hash of the user's identity key
|
|
14275
|
+
+ **newShareB**
|
|
14276
|
+
+ The new Shamir share to store
|
|
14277
|
+
|
|
14143
14278
|
Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
14144
14279
|
|
|
14145
14280
|
---
|
|
@@ -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)
|
package/docs/wallet.md
CHANGED
|
@@ -14068,6 +14068,29 @@ export class WABClient {
|
|
|
14068
14068
|
public async unlinkMethod(presentationKey: string, authMethodId: number)
|
|
14069
14069
|
public async requestFaucet(presentationKey: string)
|
|
14070
14070
|
public async deleteUser(presentationKey: string)
|
|
14071
|
+
public async startShareAuth(methodType: string, userIdHash: string, payload: any): Promise<{
|
|
14072
|
+
success: boolean;
|
|
14073
|
+
message: string;
|
|
14074
|
+
}>
|
|
14075
|
+
public async storeShare(methodType: string, payload: any, shareB: string, userIdHash: string): Promise<{
|
|
14076
|
+
success: boolean;
|
|
14077
|
+
message: string;
|
|
14078
|
+
userId?: number;
|
|
14079
|
+
}>
|
|
14080
|
+
public async retrieveShare(methodType: string, payload: any, userIdHash: string): Promise<{
|
|
14081
|
+
success: boolean;
|
|
14082
|
+
shareB?: string;
|
|
14083
|
+
message: string;
|
|
14084
|
+
}>
|
|
14085
|
+
public async updateShare(methodType: string, payload: any, userIdHash: string, newShareB: string): Promise<{
|
|
14086
|
+
success: boolean;
|
|
14087
|
+
message: string;
|
|
14088
|
+
shareVersion?: number;
|
|
14089
|
+
}>
|
|
14090
|
+
public async deleteShamirUser(methodType: string, payload: any, userIdHash: string): Promise<{
|
|
14091
|
+
success: boolean;
|
|
14092
|
+
message: string;
|
|
14093
|
+
}>
|
|
14071
14094
|
}
|
|
14072
14095
|
```
|
|
14073
14096
|
|
|
@@ -14082,6 +14105,27 @@ public async completeAuthMethod(authMethod: AuthMethodInteractor, presentationKe
|
|
|
14082
14105
|
```
|
|
14083
14106
|
See also: [AuthMethodInteractor](./client.md#class-authmethodinteractor)
|
|
14084
14107
|
|
|
14108
|
+
###### Method deleteShamirUser
|
|
14109
|
+
|
|
14110
|
+
Delete a Shamir user's account and stored share
|
|
14111
|
+
Requires OTP verification
|
|
14112
|
+
|
|
14113
|
+
```ts
|
|
14114
|
+
public async deleteShamirUser(methodType: string, payload: any, userIdHash: string): Promise<{
|
|
14115
|
+
success: boolean;
|
|
14116
|
+
message: string;
|
|
14117
|
+
}>
|
|
14118
|
+
```
|
|
14119
|
+
|
|
14120
|
+
Argument Details
|
|
14121
|
+
|
|
14122
|
+
+ **methodType**
|
|
14123
|
+
+ The auth method type used for verification
|
|
14124
|
+
+ **payload**
|
|
14125
|
+
+ Contains the OTP code and auth method specific data
|
|
14126
|
+
+ **userIdHash**
|
|
14127
|
+
+ SHA256 hash of the user's identity key
|
|
14128
|
+
|
|
14085
14129
|
###### Method deleteUser
|
|
14086
14130
|
|
|
14087
14131
|
Delete user
|
|
@@ -14122,6 +14166,28 @@ Request faucet
|
|
|
14122
14166
|
public async requestFaucet(presentationKey: string)
|
|
14123
14167
|
```
|
|
14124
14168
|
|
|
14169
|
+
###### Method retrieveShare
|
|
14170
|
+
|
|
14171
|
+
Retrieve a Shamir share (Share B) from the server
|
|
14172
|
+
Requires OTP verification
|
|
14173
|
+
|
|
14174
|
+
```ts
|
|
14175
|
+
public async retrieveShare(methodType: string, payload: any, userIdHash: string): Promise<{
|
|
14176
|
+
success: boolean;
|
|
14177
|
+
shareB?: string;
|
|
14178
|
+
message: string;
|
|
14179
|
+
}>
|
|
14180
|
+
```
|
|
14181
|
+
|
|
14182
|
+
Argument Details
|
|
14183
|
+
|
|
14184
|
+
+ **methodType**
|
|
14185
|
+
+ The auth method type used for verification
|
|
14186
|
+
+ **payload**
|
|
14187
|
+
+ Contains the OTP code and auth method specific data
|
|
14188
|
+
+ **userIdHash**
|
|
14189
|
+
+ SHA256 hash of the user's identity key
|
|
14190
|
+
|
|
14125
14191
|
###### Method startAuthMethod
|
|
14126
14192
|
|
|
14127
14193
|
Start an Auth Method flow
|
|
@@ -14131,6 +14197,51 @@ public async startAuthMethod(authMethod: AuthMethodInteractor, presentationKey:
|
|
|
14131
14197
|
```
|
|
14132
14198
|
See also: [AuthMethodInteractor](./client.md#class-authmethodinteractor)
|
|
14133
14199
|
|
|
14200
|
+
###### Method startShareAuth
|
|
14201
|
+
|
|
14202
|
+
Start OTP verification for share operations
|
|
14203
|
+
This initiates the auth flow (e.g., sends SMS code via Twilio)
|
|
14204
|
+
|
|
14205
|
+
```ts
|
|
14206
|
+
public async startShareAuth(methodType: string, userIdHash: string, payload: any): Promise<{
|
|
14207
|
+
success: boolean;
|
|
14208
|
+
message: string;
|
|
14209
|
+
}>
|
|
14210
|
+
```
|
|
14211
|
+
|
|
14212
|
+
Argument Details
|
|
14213
|
+
|
|
14214
|
+
+ **methodType**
|
|
14215
|
+
+ The auth method type (e.g., "TwilioPhone", "DevConsole")
|
|
14216
|
+
+ **userIdHash**
|
|
14217
|
+
+ SHA256 hash of the user's identity key
|
|
14218
|
+
+ **payload**
|
|
14219
|
+
+ Auth method specific data (e.g., { phoneNumber: "+1..." })
|
|
14220
|
+
|
|
14221
|
+
###### Method storeShare
|
|
14222
|
+
|
|
14223
|
+
Store a Shamir share (Share B) on the server
|
|
14224
|
+
Requires prior OTP verification via startShareAuth
|
|
14225
|
+
|
|
14226
|
+
```ts
|
|
14227
|
+
public async storeShare(methodType: string, payload: any, shareB: string, userIdHash: string): Promise<{
|
|
14228
|
+
success: boolean;
|
|
14229
|
+
message: string;
|
|
14230
|
+
userId?: number;
|
|
14231
|
+
}>
|
|
14232
|
+
```
|
|
14233
|
+
|
|
14234
|
+
Argument Details
|
|
14235
|
+
|
|
14236
|
+
+ **methodType**
|
|
14237
|
+
+ The auth method type used for verification
|
|
14238
|
+
+ **payload**
|
|
14239
|
+
+ Contains the OTP code and auth method specific data
|
|
14240
|
+
+ **shareB**
|
|
14241
|
+
+ The Shamir share to store (format: x.y.threshold.integrity)
|
|
14242
|
+
+ **userIdHash**
|
|
14243
|
+
+ SHA256 hash of the user's identity key
|
|
14244
|
+
|
|
14134
14245
|
###### Method unlinkMethod
|
|
14135
14246
|
|
|
14136
14247
|
Unlink a given Auth Method by ID
|
|
@@ -14139,6 +14250,30 @@ Unlink a given Auth Method by ID
|
|
|
14139
14250
|
public async unlinkMethod(presentationKey: string, authMethodId: number)
|
|
14140
14251
|
```
|
|
14141
14252
|
|
|
14253
|
+
###### Method updateShare
|
|
14254
|
+
|
|
14255
|
+
Update a Shamir share (for key rotation)
|
|
14256
|
+
Requires OTP verification
|
|
14257
|
+
|
|
14258
|
+
```ts
|
|
14259
|
+
public async updateShare(methodType: string, payload: any, userIdHash: string, newShareB: string): Promise<{
|
|
14260
|
+
success: boolean;
|
|
14261
|
+
message: string;
|
|
14262
|
+
shareVersion?: number;
|
|
14263
|
+
}>
|
|
14264
|
+
```
|
|
14265
|
+
|
|
14266
|
+
Argument Details
|
|
14267
|
+
|
|
14268
|
+
+ **methodType**
|
|
14269
|
+
+ The auth method type used for verification
|
|
14270
|
+
+ **payload**
|
|
14271
|
+
+ Contains the OTP code and auth method specific data
|
|
14272
|
+
+ **userIdHash**
|
|
14273
|
+
+ SHA256 hash of the user's identity key
|
|
14274
|
+
+ **newShareB**
|
|
14275
|
+
+ The new Shamir share to store
|
|
14276
|
+
|
|
14142
14277
|
Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
14143
14278
|
|
|
14144
14279
|
---
|