@owlmeans/client-did 0.1.2 → 0.1.4
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/README.md +20 -683
- package/package.json +10 -9
- package/tsconfig.json +6 -10
package/README.md
CHANGED
|
@@ -1,713 +1,50 @@
|
|
|
1
1
|
# @owlmeans/client-did
|
|
2
2
|
|
|
3
|
-
Client-side
|
|
3
|
+
Client-side DID wallet service for managing decentralized identity keys in browser environments.
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
- **DID Account Models**: Account abstraction for authentication and signing operations
|
|
11
|
-
- **Resource Integration**: Seamless integration with client resource system for persistent storage
|
|
12
|
-
- **Authentication Support**: DID-based authentication credential generation
|
|
13
|
-
- **State Management**: Integration with OwlMeans state system for reactive updates
|
|
14
|
-
- **Cross-Platform Support**: Works in web browsers and React Native environments
|
|
15
|
-
|
|
16
|
-
This package is part of the OwlMeans DID ecosystem:
|
|
17
|
-
- **@owlmeans/did**: Core DID functionality and wallet implementation
|
|
18
|
-
- **@owlmeans/client-did**: Client-side DID implementation *(this package)*
|
|
19
|
-
- **@owlmeans/basic-keys**: Cryptographic key management
|
|
7
|
+
- `makeWalletService(alias?)` — creates the DID wallet service for client context registration
|
|
8
|
+
- The service wraps `@owlmeans/did`'s `makeWallet()` with browser-compatible storage
|
|
9
|
+
- Used by the authentication flow when the app uses Ed25519-based DID authentication
|
|
20
10
|
|
|
21
11
|
## Installation
|
|
22
12
|
|
|
23
13
|
```bash
|
|
24
|
-
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## Dependencies
|
|
28
|
-
|
|
29
|
-
This package requires:
|
|
30
|
-
- `@owlmeans/did`: Core DID functionality
|
|
31
|
-
- `@owlmeans/client-context`: Client context management
|
|
32
|
-
- `@owlmeans/client-resource`: Client resource system
|
|
33
|
-
- `@owlmeans/basic-keys`: Cryptographic operations
|
|
34
|
-
- `@owlmeans/auth`: Authentication types and interfaces
|
|
35
|
-
- `@owlmeans/state`: State management integration
|
|
36
|
-
|
|
37
|
-
## Core Concepts
|
|
38
|
-
|
|
39
|
-
### DID Wallet Service
|
|
40
|
-
|
|
41
|
-
The DID wallet service manages the lifecycle of decentralized identity wallets, including creation, initialization, and persistence across client sessions.
|
|
42
|
-
|
|
43
|
-
### DID Account Model
|
|
44
|
-
|
|
45
|
-
Account models provide a simplified interface for DID-based authentication and credential generation.
|
|
46
|
-
|
|
47
|
-
### Resource Dependencies
|
|
48
|
-
|
|
49
|
-
The service uses three key resources for persistent storage:
|
|
50
|
-
- **Keys Resource**: Stores cryptographic key pairs
|
|
51
|
-
- **Meta Resource**: Stores metadata about DID keys
|
|
52
|
-
- **Master Resource**: Stores master wallet configuration
|
|
53
|
-
|
|
54
|
-
## API Reference
|
|
55
|
-
|
|
56
|
-
### Types
|
|
57
|
-
|
|
58
|
-
#### `DIDService`
|
|
59
|
-
|
|
60
|
-
Main service interface for DID wallet management.
|
|
61
|
-
|
|
62
|
-
```typescript
|
|
63
|
-
interface DIDService extends LazyService {
|
|
64
|
-
wallet: DIDWallet // Current wallet instance
|
|
65
|
-
exists(): Promise<boolean> // Check if wallet exists
|
|
66
|
-
create(opts?: MakeDIDWalletOptions): Promise<DIDWallet> // Create new wallet
|
|
67
|
-
intialize(): Promise<DIDWallet> // Initialize existing wallet
|
|
68
|
-
get(): DIDWallet // Get current wallet
|
|
69
|
-
}
|
|
14
|
+
bun add @owlmeans/client-did
|
|
70
15
|
```
|
|
71
16
|
|
|
72
|
-
|
|
17
|
+
## Usage
|
|
73
18
|
|
|
74
|
-
|
|
19
|
+
Register the wallet service in context setup:
|
|
75
20
|
|
|
76
|
-
```typescript
|
|
77
|
-
interface DIDServiceAppend {
|
|
78
|
-
getDidService(alias?: string): DIDService
|
|
79
|
-
}
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
#### `DIDServiceDeps`
|
|
83
|
-
|
|
84
|
-
Configuration for service resource dependencies.
|
|
85
|
-
|
|
86
|
-
```typescript
|
|
87
|
-
interface DIDServiceDeps {
|
|
88
|
-
keys: string // Key pair resource alias
|
|
89
|
-
meta: string // Key metadata resource alias
|
|
90
|
-
master: string // Master wallet resource alias
|
|
91
|
-
}
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
#### `DIDAccountModel`
|
|
95
|
-
|
|
96
|
-
Account model interface for DID-based authentication.
|
|
97
|
-
|
|
98
|
-
```typescript
|
|
99
|
-
interface DIDAccountModel {
|
|
100
|
-
did: DIDKeyModel // DID key model
|
|
101
|
-
authenticate<T extends Partial<AuthCredentials>>(auth: T): Promise<T> // Generate auth credentials
|
|
102
|
-
}
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
### Factory Functions
|
|
106
|
-
|
|
107
|
-
#### `makeWalletService(alias?: string, deps?: DIDServiceDeps): DIDService`
|
|
108
|
-
|
|
109
|
-
Creates a DID wallet service with resource dependencies.
|
|
110
|
-
|
|
111
|
-
**Parameters:**
|
|
112
|
-
- `alias`: Service alias (default: 'did-wallet')
|
|
113
|
-
- `deps`: Resource dependencies configuration
|
|
114
|
-
|
|
115
|
-
**Returns:** DIDService instance
|
|
116
|
-
|
|
117
|
-
**Example:**
|
|
118
21
|
```typescript
|
|
119
22
|
import { makeWalletService } from '@owlmeans/client-did'
|
|
120
23
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
// Custom resource dependencies
|
|
124
|
-
const customService = makeWalletService('custom-wallet', {
|
|
125
|
-
keys: 'custom-keys',
|
|
126
|
-
meta: 'custom-meta',
|
|
127
|
-
master: 'custom-master'
|
|
128
|
-
})
|
|
24
|
+
// In context.ts
|
|
25
|
+
context.registerService(makeWalletService())
|
|
129
26
|
```
|
|
130
27
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
Appends DID service capabilities to a client context.
|
|
134
|
-
|
|
135
|
-
**Parameters:**
|
|
136
|
-
- `ctx`: Client context to extend
|
|
137
|
-
- `alias`: Service alias (default: 'did-wallet')
|
|
138
|
-
- `customDeps`: Custom resource dependencies
|
|
28
|
+
Access from a component (via auth service):
|
|
139
29
|
|
|
140
|
-
**Returns:** Context with DID service capabilities
|
|
141
|
-
|
|
142
|
-
**Features:**
|
|
143
|
-
- Automatically creates required resources if they don't exist
|
|
144
|
-
- Registers DID service with context
|
|
145
|
-
- Adds `getDidService()` method to context
|
|
146
|
-
- Integrates with state debugging
|
|
147
|
-
|
|
148
|
-
**Example:**
|
|
149
30
|
```typescript
|
|
150
|
-
import {
|
|
151
|
-
import { makeClientContext } from '@owlmeans/client-context'
|
|
152
|
-
|
|
153
|
-
const context = makeClientContext(config)
|
|
154
|
-
const contextWithDid = appendDidService(context)
|
|
31
|
+
import { DEFAULT_ALIAS } from '@owlmeans/client-did'
|
|
155
32
|
|
|
156
|
-
|
|
157
|
-
await
|
|
158
|
-
|
|
159
|
-
// Access DID service
|
|
160
|
-
const didService = contextWithDid.getDidService()
|
|
33
|
+
const walletService = context.service(DEFAULT_ALIAS)
|
|
34
|
+
const key = await walletService.getKey({ entityId })
|
|
161
35
|
```
|
|
162
36
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
Creates a DID account model for authentication operations.
|
|
166
|
-
|
|
167
|
-
**Parameters:**
|
|
168
|
-
- `did`: DID key material (KeyPair, DIDKeyModel, or string)
|
|
169
|
-
- `isPub`: Whether the string is a public key (default: false)
|
|
37
|
+
## API
|
|
170
38
|
|
|
171
|
-
|
|
39
|
+
### `makeWalletService(alias?): WalletService`
|
|
172
40
|
|
|
173
|
-
|
|
174
|
-
```typescript
|
|
175
|
-
import { makeDidAccountModel } from '@owlmeans/client-did'
|
|
176
|
-
|
|
177
|
-
// From existing DID key model
|
|
178
|
-
const account1 = makeDidAccountModel(didKeyModel)
|
|
179
|
-
|
|
180
|
-
// From key pair
|
|
181
|
-
const account2 = makeDidAccountModel(keyPair)
|
|
182
|
-
|
|
183
|
-
// From private key string
|
|
184
|
-
const account3 = makeDidAccountModel('ed25519:privateKeyString')
|
|
185
|
-
|
|
186
|
-
// From public key string
|
|
187
|
-
const account4 = makeDidAccountModel('ed25519:publicKeyString', true)
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
### Service Methods
|
|
191
|
-
|
|
192
|
-
#### `exists(): Promise<boolean>`
|
|
193
|
-
|
|
194
|
-
Checks if a DID wallet already exists in persistent storage.
|
|
195
|
-
|
|
196
|
-
**Returns:** Promise resolving to boolean indicating existence
|
|
197
|
-
|
|
198
|
-
**Example:**
|
|
199
|
-
```typescript
|
|
200
|
-
const didService = makeWalletService()
|
|
201
|
-
|
|
202
|
-
if (await didService.exists()) {
|
|
203
|
-
console.log('Wallet already exists')
|
|
204
|
-
await didService.intialize()
|
|
205
|
-
} else {
|
|
206
|
-
console.log('Creating new wallet')
|
|
207
|
-
await didService.create()
|
|
208
|
-
}
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
#### `create(opts?: MakeDIDWalletOptions): Promise<DIDWallet>`
|
|
212
|
-
|
|
213
|
-
Creates a new DID wallet. Throws error if wallet already exists.
|
|
214
|
-
|
|
215
|
-
**Parameters:**
|
|
216
|
-
- `opts`: Wallet creation options
|
|
217
|
-
|
|
218
|
-
**Returns:** Promise resolving to new DIDWallet
|
|
219
|
-
|
|
220
|
-
**Throws:** `DIDInitializationError` if wallet already exists
|
|
221
|
-
|
|
222
|
-
**Example:**
|
|
223
|
-
```typescript
|
|
224
|
-
try {
|
|
225
|
-
const wallet = await didService.create({
|
|
226
|
-
// Custom wallet options
|
|
227
|
-
keyType: 'ed25519',
|
|
228
|
-
derivationPath: "m/44'/60'/0'/0/0"
|
|
229
|
-
})
|
|
230
|
-
|
|
231
|
-
console.log('Wallet created:', wallet.exportAddress())
|
|
232
|
-
} catch (error) {
|
|
233
|
-
if (error instanceof DIDInitializationError) {
|
|
234
|
-
console.error('Wallet already exists')
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
#### `intialize(): Promise<DIDWallet>`
|
|
240
|
-
|
|
241
|
-
Initializes an existing DID wallet from persistent storage.
|
|
242
|
-
|
|
243
|
-
**Returns:** Promise resolving to initialized DIDWallet
|
|
244
|
-
|
|
245
|
-
**Example:**
|
|
246
|
-
```typescript
|
|
247
|
-
const wallet = await didService.intialize()
|
|
248
|
-
console.log('Wallet initialized:', wallet.exportAddress())
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
#### `get(): DIDWallet`
|
|
252
|
-
|
|
253
|
-
Gets the current wallet instance (must be initialized first).
|
|
254
|
-
|
|
255
|
-
**Returns:** Current DIDWallet instance
|
|
256
|
-
|
|
257
|
-
**Example:**
|
|
258
|
-
```typescript
|
|
259
|
-
await didService.intialize()
|
|
260
|
-
const wallet = didService.get()
|
|
261
|
-
|
|
262
|
-
// Use wallet for operations
|
|
263
|
-
const signature = await wallet.sign('message to sign')
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
### Account Model Methods
|
|
267
|
-
|
|
268
|
-
#### `authenticate<T extends Partial<AuthCredentials>>(auth: T): Promise<T>`
|
|
269
|
-
|
|
270
|
-
Generates authentication credentials using the DID key.
|
|
271
|
-
|
|
272
|
-
**Parameters:**
|
|
273
|
-
- `auth`: Partial authentication credentials with challenge
|
|
274
|
-
|
|
275
|
-
**Returns:** Promise resolving to complete authentication credentials
|
|
276
|
-
|
|
277
|
-
**Process:**
|
|
278
|
-
1. Sets `userId` to DID address
|
|
279
|
-
2. Sets `publicKey` to DID public key
|
|
280
|
-
3. Signs the challenge and sets `credential`
|
|
281
|
-
|
|
282
|
-
**Example:**
|
|
283
|
-
```typescript
|
|
284
|
-
const account = makeDidAccountModel(didKeyModel)
|
|
285
|
-
|
|
286
|
-
// Authenticate with challenge
|
|
287
|
-
const authResult = await account.authenticate({
|
|
288
|
-
challenge: 'authentication-challenge-string',
|
|
289
|
-
type: 'ed25519'
|
|
290
|
-
})
|
|
291
|
-
|
|
292
|
-
console.log('User ID:', authResult.userId)
|
|
293
|
-
console.log('Public Key:', authResult.publicKey)
|
|
294
|
-
console.log('Credential:', authResult.credential)
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
### Constants
|
|
298
|
-
|
|
299
|
-
#### Service Configuration
|
|
300
|
-
```typescript
|
|
301
|
-
const DEFAULT_ALIAS = 'did-wallet' // Default service alias
|
|
302
|
-
|
|
303
|
-
const DEF_KEYS_RESOURCE = 'did-wallet-keys' // Default keys resource
|
|
304
|
-
const DEF_META_RESOURCE = 'did-wallet-meta' // Default meta resource
|
|
305
|
-
const DEF_MASTER_RESOURCE = 'did-wallet-master' // Default master resource
|
|
306
|
-
|
|
307
|
-
const defDeps: DIDServiceDeps = {
|
|
308
|
-
keys: DEF_KEYS_RESOURCE,
|
|
309
|
-
meta: DEF_META_RESOURCE,
|
|
310
|
-
master: DEF_MASTER_RESOURCE
|
|
311
|
-
}
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
## Usage Examples
|
|
315
|
-
|
|
316
|
-
### Basic DID Wallet Setup
|
|
317
|
-
|
|
318
|
-
```typescript
|
|
319
|
-
import { appendDidService } from '@owlmeans/client-did'
|
|
320
|
-
import { makeClientContext } from '@owlmeans/client-context'
|
|
321
|
-
|
|
322
|
-
// Create context with DID capabilities
|
|
323
|
-
const context = makeClientContext({
|
|
324
|
-
service: 'my-app',
|
|
325
|
-
// ... other config
|
|
326
|
-
})
|
|
327
|
-
|
|
328
|
-
const contextWithDid = appendDidService(context)
|
|
329
|
-
|
|
330
|
-
// Initialize context
|
|
331
|
-
await contextWithDid.configure().init()
|
|
332
|
-
|
|
333
|
-
// Access DID service
|
|
334
|
-
const didService = contextWithDid.getDidService()
|
|
335
|
-
|
|
336
|
-
// Check if wallet exists
|
|
337
|
-
if (await didService.exists()) {
|
|
338
|
-
await didService.intialize()
|
|
339
|
-
console.log('Wallet loaded')
|
|
340
|
-
} else {
|
|
341
|
-
await didService.create()
|
|
342
|
-
console.log('New wallet created')
|
|
343
|
-
}
|
|
344
|
-
```
|
|
345
|
-
|
|
346
|
-
### DID-Based Authentication
|
|
347
|
-
|
|
348
|
-
```typescript
|
|
349
|
-
import { makeDidAccountModel } from '@owlmeans/client-did'
|
|
350
|
-
|
|
351
|
-
// Create account from wallet
|
|
352
|
-
const didService = context.getDidService()
|
|
353
|
-
const wallet = didService.get()
|
|
354
|
-
const account = makeDidAccountModel(wallet.master)
|
|
355
|
-
|
|
356
|
-
// Authenticate with server challenge
|
|
357
|
-
const challenge = 'server-provided-challenge'
|
|
358
|
-
const authCredentials = await account.authenticate({
|
|
359
|
-
challenge,
|
|
360
|
-
type: 'ed25519'
|
|
361
|
-
})
|
|
362
|
-
|
|
363
|
-
// Send credentials to server
|
|
364
|
-
const response = await fetch('/api/authenticate', {
|
|
365
|
-
method: 'POST',
|
|
366
|
-
headers: { 'Content-Type': 'application/json' },
|
|
367
|
-
body: JSON.stringify(authCredentials)
|
|
368
|
-
})
|
|
369
|
-
```
|
|
370
|
-
|
|
371
|
-
### Multiple DID Wallets
|
|
372
|
-
|
|
373
|
-
```typescript
|
|
374
|
-
// Create multiple wallet services
|
|
375
|
-
const primaryContext = appendDidService(context, 'primary', {
|
|
376
|
-
keys: 'primary-keys',
|
|
377
|
-
meta: 'primary-meta',
|
|
378
|
-
master: 'primary-master'
|
|
379
|
-
})
|
|
380
|
-
|
|
381
|
-
const backupContext = appendDidService(primaryContext, 'backup', {
|
|
382
|
-
keys: 'backup-keys',
|
|
383
|
-
meta: 'backup-meta',
|
|
384
|
-
master: 'backup-master'
|
|
385
|
-
})
|
|
386
|
-
|
|
387
|
-
await backupContext.configure().init()
|
|
388
|
-
|
|
389
|
-
// Use different wallets
|
|
390
|
-
const primaryDid = backupContext.getDidService('primary')
|
|
391
|
-
const backupDid = backupContext.getDidService('backup')
|
|
392
|
-
|
|
393
|
-
// Create both wallets
|
|
394
|
-
if (!await primaryDid.exists()) {
|
|
395
|
-
await primaryDid.create()
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
if (!await backupDid.exists()) {
|
|
399
|
-
await backupDid.create()
|
|
400
|
-
}
|
|
401
|
-
```
|
|
402
|
-
|
|
403
|
-
### Wallet Recovery and Import
|
|
404
|
-
|
|
405
|
-
```typescript
|
|
406
|
-
import { makeDidAccountModel } from '@owlmeans/client-did'
|
|
407
|
-
|
|
408
|
-
// Recovery from private key
|
|
409
|
-
const recoverWallet = async (privateKeyString: string) => {
|
|
410
|
-
const account = makeDidAccountModel(privateKeyString)
|
|
411
|
-
console.log('Recovered wallet address:', account.did.exportAddress())
|
|
412
|
-
|
|
413
|
-
return account
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
// Import from existing key pair
|
|
417
|
-
const importWallet = async (keyPair: KeyPair) => {
|
|
418
|
-
const account = makeDidAccountModel(keyPair)
|
|
419
|
-
|
|
420
|
-
// Authenticate to verify ownership
|
|
421
|
-
const authTest = await account.authenticate({
|
|
422
|
-
challenge: 'ownership-verification'
|
|
423
|
-
})
|
|
424
|
-
|
|
425
|
-
return account
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
// Usage
|
|
429
|
-
const recovered = await recoverWallet('ed25519:private-key-string')
|
|
430
|
-
const imported = await importWallet(existingKeyPair)
|
|
431
|
-
```
|
|
432
|
-
|
|
433
|
-
### Signing and Verification
|
|
434
|
-
|
|
435
|
-
```typescript
|
|
436
|
-
// Sign messages with DID wallet
|
|
437
|
-
const didService = context.getDidService()
|
|
438
|
-
const wallet = didService.get()
|
|
439
|
-
|
|
440
|
-
// Sign arbitrary data
|
|
441
|
-
const signature = await wallet.sign('important message')
|
|
442
|
-
console.log('Signature:', signature)
|
|
443
|
-
|
|
444
|
-
// Verify signature
|
|
445
|
-
const isValid = await wallet.verify('important message', signature)
|
|
446
|
-
console.log('Signature valid:', isValid)
|
|
447
|
-
|
|
448
|
-
// Account-based signing
|
|
449
|
-
const account = makeDidAccountModel(wallet.master)
|
|
450
|
-
const authSig = await account.authenticate({
|
|
451
|
-
challenge: 'server-challenge'
|
|
452
|
-
})
|
|
453
|
-
```
|
|
454
|
-
|
|
455
|
-
### Integration with Authentication Flow
|
|
456
|
-
|
|
457
|
-
```typescript
|
|
458
|
-
import { AuthenticationStage } from '@owlmeans/auth'
|
|
459
|
-
|
|
460
|
-
class DIDAuthenticationFlow {
|
|
461
|
-
private account: DIDAccountModel
|
|
462
|
-
|
|
463
|
-
constructor(didService: DIDService) {
|
|
464
|
-
this.account = makeDidAccountModel(didService.get().master)
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
async initialize() {
|
|
468
|
-
return {
|
|
469
|
-
stage: AuthenticationStage.Init,
|
|
470
|
-
publicKey: this.account.did.exportPublic(),
|
|
471
|
-
address: this.account.did.exportAddress()
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
async authenticate(challenge: string) {
|
|
476
|
-
const credentials = await this.account.authenticate({
|
|
477
|
-
challenge,
|
|
478
|
-
type: 'ed25519'
|
|
479
|
-
})
|
|
480
|
-
|
|
481
|
-
return {
|
|
482
|
-
stage: AuthenticationStage.Authenticated,
|
|
483
|
-
...credentials
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
// Usage
|
|
489
|
-
const authFlow = new DIDAuthenticationFlow(didService)
|
|
490
|
-
const initResult = await authFlow.initialize()
|
|
491
|
-
|
|
492
|
-
// Send init to server, receive challenge
|
|
493
|
-
const challenge = await sendToServer('/auth/init', initResult)
|
|
494
|
-
const authResult = await authFlow.authenticate(challenge.challenge)
|
|
495
|
-
```
|
|
496
|
-
|
|
497
|
-
### State Management Integration
|
|
498
|
-
|
|
499
|
-
```typescript
|
|
500
|
-
// The service automatically integrates with state debugging
|
|
501
|
-
const contextWithDid = appendDidService(context)
|
|
502
|
-
|
|
503
|
-
// State changes are tracked for resources
|
|
504
|
-
contextWithDid.getDidService() // State debugging enabled for did-wallet-*
|
|
505
|
-
|
|
506
|
-
// Monitor wallet state changes
|
|
507
|
-
const stateService = contextWithDid.service('state')
|
|
508
|
-
stateService.subscribe('did-wallet-master', (change) => {
|
|
509
|
-
console.log('Wallet state changed:', change)
|
|
510
|
-
})
|
|
511
|
-
```
|
|
512
|
-
|
|
513
|
-
### Error Handling
|
|
514
|
-
|
|
515
|
-
```typescript
|
|
516
|
-
import { DIDInitializationError } from '@owlmeans/did'
|
|
517
|
-
|
|
518
|
-
try {
|
|
519
|
-
const didService = makeWalletService()
|
|
520
|
-
|
|
521
|
-
// Try to create wallet
|
|
522
|
-
await didService.create()
|
|
523
|
-
} catch (error) {
|
|
524
|
-
if (error instanceof DIDInitializationError) {
|
|
525
|
-
if (error.message.includes('exists:service')) {
|
|
526
|
-
console.log('Wallet already exists, initializing instead')
|
|
527
|
-
await didService.intialize()
|
|
528
|
-
} else {
|
|
529
|
-
console.error('DID initialization failed:', error.message)
|
|
530
|
-
}
|
|
531
|
-
} else {
|
|
532
|
-
console.error('Unexpected error:', error)
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
```
|
|
536
|
-
|
|
537
|
-
### Custom Resource Configuration
|
|
538
|
-
|
|
539
|
-
```typescript
|
|
540
|
-
// Custom resource aliases for different use cases
|
|
541
|
-
const customDeps: DIDServiceDeps = {
|
|
542
|
-
keys: 'secure-keys',
|
|
543
|
-
meta: 'wallet-metadata',
|
|
544
|
-
master: 'master-wallet'
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
const secureDidService = makeWalletService('secure-wallet', customDeps)
|
|
548
|
-
|
|
549
|
-
// Or use with appendDidService
|
|
550
|
-
const contextWithCustomDid = appendDidService(context, 'custom', {
|
|
551
|
-
keys: 'custom-keys-resource',
|
|
552
|
-
meta: 'custom-meta-resource'
|
|
553
|
-
// master will default to 'custom-master'
|
|
554
|
-
})
|
|
555
|
-
```
|
|
556
|
-
|
|
557
|
-
### Cross-Platform Considerations
|
|
558
|
-
|
|
559
|
-
```typescript
|
|
560
|
-
// Browser-specific initialization
|
|
561
|
-
if (typeof window !== 'undefined') {
|
|
562
|
-
// Browser environment
|
|
563
|
-
const context = makeClientContext(browserConfig)
|
|
564
|
-
const contextWithDid = appendDidService(context)
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
// React Native-specific initialization
|
|
568
|
-
if (typeof global !== 'undefined' && global.navigator?.product === 'ReactNative') {
|
|
569
|
-
// React Native environment
|
|
570
|
-
const context = makeClientContext(reactNativeConfig)
|
|
571
|
-
const contextWithDid = appendDidService(context)
|
|
572
|
-
}
|
|
573
|
-
```
|
|
574
|
-
|
|
575
|
-
## Advanced Features
|
|
576
|
-
|
|
577
|
-
### Wallet Export and Backup
|
|
578
|
-
|
|
579
|
-
```typescript
|
|
580
|
-
// Export wallet for backup
|
|
581
|
-
const didService = context.getDidService()
|
|
582
|
-
const wallet = didService.get()
|
|
583
|
-
|
|
584
|
-
const exportData = {
|
|
585
|
-
address: wallet.exportAddress(),
|
|
586
|
-
publicKey: wallet.exportPublic(),
|
|
587
|
-
// Note: private key export depends on wallet implementation
|
|
588
|
-
masterKey: wallet.master?.export?.() // If available
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
// Store backup securely
|
|
592
|
-
localStorage.setItem('wallet-backup', JSON.stringify(exportData))
|
|
593
|
-
```
|
|
594
|
-
|
|
595
|
-
### Multi-Signature Support
|
|
596
|
-
|
|
597
|
-
```typescript
|
|
598
|
-
// Create multiple accounts for multi-sig
|
|
599
|
-
const wallet = didService.get()
|
|
600
|
-
const accounts = [
|
|
601
|
-
makeDidAccountModel(wallet.master),
|
|
602
|
-
makeDidAccountModel(wallet.createDerived?.(1) || wallet.master),
|
|
603
|
-
makeDidAccountModel(wallet.createDerived?.(2) || wallet.master)
|
|
604
|
-
]
|
|
605
|
-
|
|
606
|
-
// Multi-signature authentication
|
|
607
|
-
const multiAuth = async (challenge: string) => {
|
|
608
|
-
const signatures = await Promise.all(
|
|
609
|
-
accounts.map(account =>
|
|
610
|
-
account.authenticate({ challenge, type: 'ed25519' })
|
|
611
|
-
)
|
|
612
|
-
)
|
|
613
|
-
|
|
614
|
-
return {
|
|
615
|
-
type: 'multi-sig',
|
|
616
|
-
signatures,
|
|
617
|
-
threshold: 2 // Require 2 of 3 signatures
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
```
|
|
621
|
-
|
|
622
|
-
### Hierarchical Deterministic Support
|
|
623
|
-
|
|
624
|
-
```typescript
|
|
625
|
-
// If wallet supports HD derivation
|
|
626
|
-
const wallet = didService.get()
|
|
627
|
-
|
|
628
|
-
// Create derived accounts for different purposes
|
|
629
|
-
const tradingAccount = wallet.deriveAccount?.('m/44\'/60\'/0\'/0/0')
|
|
630
|
-
const savingsAccount = wallet.deriveAccount?.('m/44\'/60\'/0\'/0/1')
|
|
631
|
-
|
|
632
|
-
if (tradingAccount && savingsAccount) {
|
|
633
|
-
const tradingDid = makeDidAccountModel(tradingAccount)
|
|
634
|
-
const savingsDid = makeDidAccountModel(savingsAccount)
|
|
635
|
-
|
|
636
|
-
console.log('Trading address:', tradingDid.did.exportAddress())
|
|
637
|
-
console.log('Savings address:', savingsDid.did.exportAddress())
|
|
638
|
-
}
|
|
639
|
-
```
|
|
640
|
-
|
|
641
|
-
## Security Considerations
|
|
642
|
-
|
|
643
|
-
### Private Key Protection
|
|
644
|
-
- Private keys are stored using client resource system
|
|
645
|
-
- Use appropriate security measures for key storage
|
|
646
|
-
- Consider hardware security modules for high-value applications
|
|
647
|
-
|
|
648
|
-
### Authentication Security
|
|
649
|
-
- Always verify challenges come from trusted sources
|
|
650
|
-
- Implement replay attack protection
|
|
651
|
-
- Use secure communication channels for credential exchange
|
|
652
|
-
|
|
653
|
-
### Wallet Management
|
|
654
|
-
- Implement proper wallet backup and recovery procedures
|
|
655
|
-
- Use strong entropy for wallet generation
|
|
656
|
-
- Consider multi-factor authentication for wallet access
|
|
657
|
-
|
|
658
|
-
## Best Practices
|
|
659
|
-
|
|
660
|
-
1. **Initialization**: Check wallet existence before creation
|
|
661
|
-
2. **Error Handling**: Properly handle DID initialization errors
|
|
662
|
-
3. **Resource Management**: Use meaningful resource aliases
|
|
663
|
-
4. **State Integration**: Leverage state debugging for development
|
|
664
|
-
5. **Security**: Never expose private keys in logs or error messages
|
|
665
|
-
6. **Backup**: Implement secure wallet backup procedures
|
|
666
|
-
7. **Testing**: Test authentication flows thoroughly
|
|
667
|
-
|
|
668
|
-
## Integration with OwlMeans Ecosystem
|
|
669
|
-
|
|
670
|
-
### Authentication Integration
|
|
671
|
-
```typescript
|
|
672
|
-
import { AuthService } from '@owlmeans/client-auth'
|
|
673
|
-
|
|
674
|
-
// Use DID for OwlMeans authentication
|
|
675
|
-
const authService = context.service<AuthService>('auth')
|
|
676
|
-
const didService = context.getDidService()
|
|
677
|
-
|
|
678
|
-
// Custom DID-based authentication
|
|
679
|
-
const authenticateWithDid = async (challenge: string) => {
|
|
680
|
-
const account = makeDidAccountModel(didService.get().master)
|
|
681
|
-
const credentials = await account.authenticate({ challenge })
|
|
682
|
-
|
|
683
|
-
await authService.authenticate({ token: credentials.credential })
|
|
684
|
-
}
|
|
685
|
-
```
|
|
686
|
-
|
|
687
|
-
### Context Integration
|
|
688
|
-
```typescript
|
|
689
|
-
import { makeClientContext } from '@owlmeans/client-context'
|
|
690
|
-
|
|
691
|
-
// DID service integrates seamlessly with client context
|
|
692
|
-
const context = makeClientContext(config)
|
|
693
|
-
const contextWithDid = appendDidService(context)
|
|
694
|
-
|
|
695
|
-
// All OwlMeans services work together
|
|
696
|
-
await contextWithDid.configure().init()
|
|
697
|
-
```
|
|
41
|
+
Creates the DID wallet service. `alias` defaults to a standard DID wallet alias.
|
|
698
42
|
|
|
699
|
-
|
|
43
|
+
### `DEFAULT_ALIAS`
|
|
700
44
|
|
|
701
|
-
|
|
702
|
-
- **Resource Caching**: Resources are cached after first access
|
|
703
|
-
- **Cryptographic Operations**: Ed25519 operations are computationally efficient
|
|
704
|
-
- **State Updates**: State changes are optimized for performance
|
|
45
|
+
Default service alias for the wallet service.
|
|
705
46
|
|
|
706
47
|
## Related Packages
|
|
707
48
|
|
|
708
|
-
- [`@owlmeans/did`](../did)
|
|
709
|
-
- [`@owlmeans/
|
|
710
|
-
- [`@owlmeans/client-context`](../client-context) - Client context management
|
|
711
|
-
- [`@owlmeans/client-resource`](../client-resource) - Client resource system
|
|
712
|
-
- [`@owlmeans/auth`](../auth) - Authentication types and interfaces
|
|
713
|
-
- [`@owlmeans/state`](../state) - State management system
|
|
49
|
+
- [`@owlmeans/did`](../did) — `makeWallet` called internally
|
|
50
|
+
- [`@owlmeans/client-auth`](../client-auth) — uses the wallet service during authentication
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owlmeans/client-did",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -21,17 +21,18 @@
|
|
|
21
21
|
}
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@owlmeans/auth": "^0.1.
|
|
25
|
-
"@owlmeans/client": "^0.1.
|
|
26
|
-
"@owlmeans/client-context": "^0.1.
|
|
27
|
-
"@owlmeans/client-resource": "^0.1.
|
|
28
|
-
"@owlmeans/context": "^0.1.
|
|
29
|
-
"@owlmeans/did": "^0.1.
|
|
30
|
-
"@owlmeans/state": "^0.1.
|
|
24
|
+
"@owlmeans/auth": "^0.1.4",
|
|
25
|
+
"@owlmeans/client": "^0.1.4",
|
|
26
|
+
"@owlmeans/client-context": "^0.1.4",
|
|
27
|
+
"@owlmeans/client-resource": "^0.1.4",
|
|
28
|
+
"@owlmeans/context": "^0.1.4",
|
|
29
|
+
"@owlmeans/did": "^0.1.4",
|
|
30
|
+
"@owlmeans/state": "^0.1.4"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
+
"@owlmeans/dep-config": "workspace:*",
|
|
33
34
|
"nodemon": "^3.1.11",
|
|
34
|
-
"typescript": "^
|
|
35
|
+
"typescript": "^6.0.2"
|
|
35
36
|
},
|
|
36
37
|
"publishConfig": {
|
|
37
38
|
"access": "public"
|
package/tsconfig.json
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"extends": [
|
|
3
|
-
"
|
|
4
|
-
"
|
|
3
|
+
"@owlmeans/dep-config/tsconfig.base.json",
|
|
4
|
+
"@owlmeans/dep-config/tsconfig.react.json"
|
|
5
5
|
],
|
|
6
6
|
"compilerOptions": {
|
|
7
|
-
"rootDir": "./src/",
|
|
8
|
-
"outDir": "./build/"
|
|
7
|
+
"rootDir": "./src/",
|
|
8
|
+
"outDir": "./build/"
|
|
9
9
|
},
|
|
10
|
-
"exclude": [
|
|
11
|
-
|
|
12
|
-
"./build/**/*",
|
|
13
|
-
"./*.ts"
|
|
14
|
-
]
|
|
15
|
-
}
|
|
10
|
+
"exclude": ["./dist/**/*", "./build/**/*", "./*.ts"]
|
|
11
|
+
}
|