@bsv/sdk 1.9.2 → 1.9.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/dist/cjs/package.json +1 -1
- package/dist/cjs/src/kvstore/GlobalKVStore.js +116 -98
- package/dist/cjs/src/kvstore/GlobalKVStore.js.map +1 -1
- package/dist/cjs/src/kvstore/types.js.map +1 -1
- package/dist/cjs/src/overlay-tools/index.js +1 -0
- package/dist/cjs/src/overlay-tools/index.js.map +1 -1
- package/dist/cjs/src/overlay-tools/withDoubleSpendRetry.js +55 -0
- package/dist/cjs/src/overlay-tools/withDoubleSpendRetry.js.map +1 -0
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/src/kvstore/GlobalKVStore.js +117 -99
- package/dist/esm/src/kvstore/GlobalKVStore.js.map +1 -1
- package/dist/esm/src/kvstore/types.js.map +1 -1
- package/dist/esm/src/overlay-tools/index.js +1 -0
- package/dist/esm/src/overlay-tools/index.js.map +1 -1
- package/dist/esm/src/overlay-tools/withDoubleSpendRetry.js +48 -0
- package/dist/esm/src/overlay-tools/withDoubleSpendRetry.js.map +1 -0
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/src/kvstore/GlobalKVStore.d.ts.map +1 -1
- package/dist/types/src/kvstore/types.d.ts +2 -0
- package/dist/types/src/kvstore/types.d.ts.map +1 -1
- package/dist/types/src/overlay-tools/index.d.ts +1 -0
- package/dist/types/src/overlay-tools/index.d.ts.map +1 -1
- package/dist/types/src/overlay-tools/withDoubleSpendRetry.d.ts +14 -0
- package/dist/types/src/overlay-tools/withDoubleSpendRetry.d.ts.map +1 -0
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/dist/umd/bundle.js +2 -2
- package/dist/umd/bundle.js.map +1 -1
- package/docs/fast-docs.png +0 -0
- package/docs/index.md +49 -44
- package/docs/reference/kvstore.md +9 -0
- package/docs/reference/overlay-tools.md +32 -0
- package/docs/swagger.png +0 -0
- package/package.json +1 -1
- package/src/kvstore/GlobalKVStore.ts +134 -114
- package/src/kvstore/__tests/GlobalKVStore.test.ts +11 -1
- package/src/kvstore/types.ts +2 -0
- package/src/overlay-tools/index.ts +1 -0
- package/src/overlay-tools/withDoubleSpendRetry.ts +71 -0
- package/docs/MARKDOWN_VALIDATION_GUIDE.md +0 -175
- package/docs/concepts/beef.md +0 -92
- package/docs/concepts/chain-tracking.md +0 -134
- package/docs/concepts/decentralized-identity.md +0 -221
- package/docs/concepts/fees.md +0 -249
- package/docs/concepts/identity-certificates.md +0 -307
- package/docs/concepts/index.md +0 -77
- package/docs/concepts/key-management.md +0 -185
- package/docs/concepts/script-templates.md +0 -176
- package/docs/concepts/sdk-philosophy.md +0 -80
- package/docs/concepts/signatures.md +0 -194
- package/docs/concepts/spv-verification.md +0 -118
- package/docs/concepts/transaction-encoding.md +0 -167
- package/docs/concepts/transaction-structure.md +0 -67
- package/docs/concepts/trust-model.md +0 -139
- package/docs/concepts/verification.md +0 -250
- package/docs/concepts/wallet-integration.md +0 -101
- package/docs/guides/development-wallet-setup.md +0 -374
- package/docs/guides/direct-transaction-creation.md +0 -147
- package/docs/guides/http-client-configuration.md +0 -488
- package/docs/guides/index.md +0 -138
- package/docs/guides/large-transactions.md +0 -448
- package/docs/guides/multisig-transactions.md +0 -792
- package/docs/guides/security-best-practices.md +0 -494
- package/docs/guides/transaction-batching.md +0 -132
- package/docs/guides/transaction-signing-methods.md +0 -419
- package/docs/reference/arc-config.md +0 -698
- package/docs/reference/brc-100.md +0 -33
- package/docs/reference/configuration.md +0 -835
- package/docs/reference/debugging.md +0 -705
- package/docs/reference/errors.md +0 -597
- package/docs/reference/index.md +0 -111
- package/docs/reference/network-config.md +0 -914
- package/docs/reference/op-codes.md +0 -325
- package/docs/reference/transaction-signatures.md +0 -95
- package/docs/tutorials/advanced-transaction.md +0 -572
- package/docs/tutorials/aes-encryption.md +0 -949
- package/docs/tutorials/authfetch-tutorial.md +0 -986
- package/docs/tutorials/ecdh-key-exchange.md +0 -549
- package/docs/tutorials/elliptic-curve-fundamentals.md +0 -606
- package/docs/tutorials/error-handling.md +0 -1216
- package/docs/tutorials/first-transaction-low-level.md +0 -205
- package/docs/tutorials/first-transaction.md +0 -275
- package/docs/tutorials/hashes-and-hmacs.md +0 -788
- package/docs/tutorials/identity-management.md +0 -729
- package/docs/tutorials/index.md +0 -219
- package/docs/tutorials/key-management.md +0 -538
- package/docs/tutorials/protowallet-development.md +0 -743
- package/docs/tutorials/script-construction.md +0 -690
- package/docs/tutorials/spv-merkle-proofs.md +0 -685
- package/docs/tutorials/testnet-transactions-low-level.md +0 -359
- package/docs/tutorials/transaction-broadcasting.md +0 -538
- package/docs/tutorials/transaction-types.md +0 -420
- package/docs/tutorials/type-42.md +0 -568
- package/docs/tutorials/uhrp-storage.md +0 -599
|
@@ -1,729 +0,0 @@
|
|
|
1
|
-
# Identity Management and Certificates
|
|
2
|
-
|
|
3
|
-
**Duration**: 90 minutes
|
|
4
|
-
**Prerequisites**: Node.js, basic TypeScript knowledge, understanding of digital certificates
|
|
5
|
-
**Learning Goals**:
|
|
6
|
-
|
|
7
|
-
- Understand decentralized identity concepts
|
|
8
|
-
- Use IdentityClient for certificate management
|
|
9
|
-
- Implement identity verification systems
|
|
10
|
-
- Build identity-based applications
|
|
11
|
-
|
|
12
|
-
## Introduction
|
|
13
|
-
|
|
14
|
-
The BSV ecosystem uses a decentralized identity system based on cryptographic certificates. The `IdentityClient` provides tools for managing identity certificates, verifying identities, and building identity-aware applications.
|
|
15
|
-
|
|
16
|
-
## Key Concepts
|
|
17
|
-
|
|
18
|
-
- **Identity Certificates**: Cryptographically signed identity claims
|
|
19
|
-
- **Certificate Revelation**: Publicly revealing identity attributes
|
|
20
|
-
- **Identity Resolution**: Finding identities by key or attributes
|
|
21
|
-
- **Certificate Verification**: Validating identity claims
|
|
22
|
-
|
|
23
|
-
## What You'll Build
|
|
24
|
-
|
|
25
|
-
- Identity certificate management system
|
|
26
|
-
- Identity verification service
|
|
27
|
-
- Public identity revelation
|
|
28
|
-
- Identity-based authentication
|
|
29
|
-
|
|
30
|
-
## Setting Up Identity Management with `WalletClient`
|
|
31
|
-
|
|
32
|
-
### Basic Identity Operations
|
|
33
|
-
|
|
34
|
-
```typescript
|
|
35
|
-
import { IdentityClient, WalletClient } from '@bsv/sdk'
|
|
36
|
-
|
|
37
|
-
async function basicIdentityOperations() {
|
|
38
|
-
const wallet = new WalletClient()
|
|
39
|
-
const identityClient = new IdentityClient(wallet)
|
|
40
|
-
|
|
41
|
-
console.log('Identity client initialized')
|
|
42
|
-
|
|
43
|
-
// Get our identity key
|
|
44
|
-
const { publicKey: identityKey } = await wallet.getPublicKey({
|
|
45
|
-
identityKey: true
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
console.log('Our identity key:', identityKey.substring(0, 20) + '...')
|
|
49
|
-
|
|
50
|
-
return { identityClient, identityKey }
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
basicIdentityOperations().catch(console.error)
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
### Resolving Identities by Key
|
|
57
|
-
|
|
58
|
-
```typescript
|
|
59
|
-
import { IdentityClient, WalletClient } from '@bsv/sdk'
|
|
60
|
-
|
|
61
|
-
async function resolveIdentityByKey(identityKey: string) {
|
|
62
|
-
const identityClient = new IdentityClient()
|
|
63
|
-
|
|
64
|
-
try {
|
|
65
|
-
console.log('Resolving identity for key:', identityKey.substring(0, 20) + '...')
|
|
66
|
-
|
|
67
|
-
const identities = await identityClient.resolveByIdentityKey({
|
|
68
|
-
identityKey
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
console.log('Found identities:', identities.length)
|
|
72
|
-
|
|
73
|
-
identities.forEach((identity, index) => {
|
|
74
|
-
console.log(`Identity ${index + 1}:`)
|
|
75
|
-
console.log(' Name:', identity.name)
|
|
76
|
-
console.log(' Badge:', identity.badgeLabel)
|
|
77
|
-
console.log(' Avatar:', identity.avatarURL)
|
|
78
|
-
console.log(' Key:', identity.abbreviatedKey)
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
return identities
|
|
82
|
-
} catch (error) {
|
|
83
|
-
console.error('Failed to resolve identity:', error)
|
|
84
|
-
return []
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Example usage (replace with actual identity key)
|
|
89
|
-
// resolveIdentityByKey('actual-identity-key-here').catch(console.error)
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### Resolving Identities by Attributes
|
|
93
|
-
|
|
94
|
-
```typescript
|
|
95
|
-
import { IdentityClient } from '@bsv/sdk'
|
|
96
|
-
|
|
97
|
-
async function resolveIdentityByAttributes() {
|
|
98
|
-
const identityClient = new IdentityClient()
|
|
99
|
-
|
|
100
|
-
try {
|
|
101
|
-
console.log('Searching for identities by attributes...')
|
|
102
|
-
|
|
103
|
-
const identities = await identityClient.resolveByAttributes({
|
|
104
|
-
attributes: {
|
|
105
|
-
email: 'user@example.com'
|
|
106
|
-
}
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
console.log('Found identities with matching attributes:', identities.length)
|
|
110
|
-
|
|
111
|
-
identities.forEach((identity, index) => {
|
|
112
|
-
console.log(`Match ${index + 1}:`)
|
|
113
|
-
console.log(' Name:', identity.name)
|
|
114
|
-
console.log(' Badge:', identity.badgeLabel)
|
|
115
|
-
console.log(' Identity Key:', identity.identityKey.substring(0, 20) + '...')
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
return identities
|
|
119
|
-
} catch (error) {
|
|
120
|
-
console.error('Failed to resolve by attributes:', error)
|
|
121
|
-
return []
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
resolveIdentityByAttributes().catch(console.error)
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
## Certificate Management System
|
|
129
|
-
|
|
130
|
-
### Identity Manager Class
|
|
131
|
-
|
|
132
|
-
```typescript
|
|
133
|
-
import { IdentityClient, WalletClient } from '@bsv/sdk'
|
|
134
|
-
|
|
135
|
-
interface IdentityRecord {
|
|
136
|
-
identityKey: string
|
|
137
|
-
name: string
|
|
138
|
-
badgeLabel: string
|
|
139
|
-
avatarURL: string
|
|
140
|
-
verificationStatus: 'verified' | 'unverified' | 'pending'
|
|
141
|
-
certificates: any[]
|
|
142
|
-
lastUpdated: Date
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
class IdentityManager {
|
|
146
|
-
private identityClient: IdentityClient
|
|
147
|
-
private wallet: WalletClient
|
|
148
|
-
private identityCache: Map<string, IdentityRecord> = new Map()
|
|
149
|
-
|
|
150
|
-
constructor(wallet?: WalletClient) {
|
|
151
|
-
this.wallet = wallet || new WalletClient()
|
|
152
|
-
this.identityClient = new IdentityClient(this.wallet)
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
async getOurIdentity(): Promise<string> {
|
|
156
|
-
const { publicKey } = await this.wallet.getPublicKey({
|
|
157
|
-
identityKey: true
|
|
158
|
-
})
|
|
159
|
-
return publicKey
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
async verifyIdentity(identityKey: string): Promise<IdentityRecord | null> {
|
|
163
|
-
try {
|
|
164
|
-
console.log('Verifying identity:', identityKey.substring(0, 20) + '...')
|
|
165
|
-
|
|
166
|
-
// Check cache first
|
|
167
|
-
const cached = this.identityCache.get(identityKey)
|
|
168
|
-
if (cached && this.isCacheValid(cached)) {
|
|
169
|
-
console.log('Using cached identity data')
|
|
170
|
-
return cached
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// Resolve identity from network
|
|
174
|
-
const identities = await this.identityClient.resolveByIdentityKey({
|
|
175
|
-
identityKey
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
if (identities.length === 0) {
|
|
179
|
-
console.log('No identity found for key')
|
|
180
|
-
return null
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
// Use the first identity found
|
|
184
|
-
const identity = identities[0]
|
|
185
|
-
|
|
186
|
-
const record: IdentityRecord = {
|
|
187
|
-
identityKey,
|
|
188
|
-
name: identity.name,
|
|
189
|
-
badgeLabel: identity.badgeLabel,
|
|
190
|
-
avatarURL: identity.avatarURL,
|
|
191
|
-
verificationStatus: 'verified',
|
|
192
|
-
certificates: [], // Would contain actual certificates
|
|
193
|
-
lastUpdated: new Date()
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// Cache the result
|
|
197
|
-
this.identityCache.set(identityKey, record)
|
|
198
|
-
|
|
199
|
-
console.log('Identity verified:', record.name)
|
|
200
|
-
return record
|
|
201
|
-
} catch (error) {
|
|
202
|
-
console.error('Identity verification failed:', error)
|
|
203
|
-
return null
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
async searchIdentities(query: {
|
|
208
|
-
name?: string
|
|
209
|
-
email?: string
|
|
210
|
-
attributes?: Record<string, string>
|
|
211
|
-
}): Promise<IdentityRecord[]> {
|
|
212
|
-
try {
|
|
213
|
-
console.log('Searching identities with query:', query)
|
|
214
|
-
|
|
215
|
-
const searchAttributes = {
|
|
216
|
-
...query.attributes,
|
|
217
|
-
...(query.name && { name: query.name }),
|
|
218
|
-
...(query.email && { email: query.email })
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
const identities = await this.identityClient.resolveByAttributes({
|
|
222
|
-
attributes: searchAttributes
|
|
223
|
-
})
|
|
224
|
-
|
|
225
|
-
const records: IdentityRecord[] = identities.map(identity => ({
|
|
226
|
-
identityKey: identity.identityKey,
|
|
227
|
-
name: identity.name,
|
|
228
|
-
badgeLabel: identity.badgeLabel,
|
|
229
|
-
avatarURL: identity.avatarURL,
|
|
230
|
-
verificationStatus: 'verified' as const,
|
|
231
|
-
certificates: [],
|
|
232
|
-
lastUpdated: new Date()
|
|
233
|
-
}))
|
|
234
|
-
|
|
235
|
-
console.log('Found', records.length, 'matching identities')
|
|
236
|
-
return records
|
|
237
|
-
} catch (error) {
|
|
238
|
-
console.error('Identity search failed:', error)
|
|
239
|
-
return []
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
async revealPublicAttributes(
|
|
244
|
-
certificate: any,
|
|
245
|
-
fieldsToReveal: string[]
|
|
246
|
-
): Promise<boolean> {
|
|
247
|
-
try {
|
|
248
|
-
console.log('Revealing public attributes:', fieldsToReveal)
|
|
249
|
-
|
|
250
|
-
const result = await this.identityClient.publiclyRevealAttributes(
|
|
251
|
-
certificate,
|
|
252
|
-
fieldsToReveal
|
|
253
|
-
)
|
|
254
|
-
|
|
255
|
-
console.log('Attributes revealed successfully')
|
|
256
|
-
return true
|
|
257
|
-
} catch (error) {
|
|
258
|
-
console.error('Failed to reveal attributes:', error)
|
|
259
|
-
return false
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
private isCacheValid(record: IdentityRecord): boolean {
|
|
264
|
-
const cacheAge = Date.now() - record.lastUpdated.getTime()
|
|
265
|
-
const maxAge = 60 * 60 * 1000 // 1 hour
|
|
266
|
-
return cacheAge < maxAge
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
getCachedIdentities(): IdentityRecord[] {
|
|
270
|
-
return Array.from(this.identityCache.values())
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
clearCache(): void {
|
|
274
|
-
this.identityCache.clear()
|
|
275
|
-
console.log('Identity cache cleared')
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
async function demonstrateIdentityManager() {
|
|
280
|
-
const identityManager = new IdentityManager()
|
|
281
|
-
|
|
282
|
-
console.log('=== Identity Manager Demo ===')
|
|
283
|
-
|
|
284
|
-
// Get our own identity
|
|
285
|
-
const ourIdentity = await identityManager.getOurIdentity()
|
|
286
|
-
console.log('Our identity key:', ourIdentity.substring(0, 20) + '...')
|
|
287
|
-
|
|
288
|
-
// Search for identities
|
|
289
|
-
const searchResults = await identityManager.searchIdentities({
|
|
290
|
-
name: 'John'
|
|
291
|
-
})
|
|
292
|
-
|
|
293
|
-
console.log('Search results:', searchResults.length)
|
|
294
|
-
|
|
295
|
-
// Verify specific identities
|
|
296
|
-
for (const result of searchResults.slice(0, 2)) { // Limit to first 2
|
|
297
|
-
const verified = await identityManager.verifyIdentity(result.identityKey)
|
|
298
|
-
if (verified) {
|
|
299
|
-
console.log('Verified identity:', verified.name)
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
// Show cached identities
|
|
304
|
-
const cached = identityManager.getCachedIdentities()
|
|
305
|
-
console.log('Cached identities:', cached.length)
|
|
306
|
-
|
|
307
|
-
return { ourIdentity, searchResults, cached }
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
demonstrateIdentityManager().catch(console.error)
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
## Identity-Based Authentication
|
|
314
|
-
|
|
315
|
-
### Authentication Service
|
|
316
|
-
|
|
317
|
-
```typescript
|
|
318
|
-
import { IdentityClient, WalletClient } from '@bsv/sdk'
|
|
319
|
-
|
|
320
|
-
interface AuthenticationResult {
|
|
321
|
-
success: boolean
|
|
322
|
-
identityKey?: string
|
|
323
|
-
identity?: any
|
|
324
|
-
error?: string
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
class IdentityAuthService {
|
|
328
|
-
private identityClient: IdentityClient
|
|
329
|
-
private authenticatedUsers: Map<string, {
|
|
330
|
-
identity: any
|
|
331
|
-
sessionStart: Date
|
|
332
|
-
lastActivity: Date
|
|
333
|
-
}> = new Map()
|
|
334
|
-
|
|
335
|
-
constructor(wallet?: WalletClient) {
|
|
336
|
-
this.identityClient = new IdentityClient(wallet)
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
async authenticateUser(identityKey: string): Promise<AuthenticationResult> {
|
|
340
|
-
try {
|
|
341
|
-
console.log('Authenticating user:', identityKey.substring(0, 20) + '...')
|
|
342
|
-
|
|
343
|
-
// Resolve identity
|
|
344
|
-
const identities = await this.identityClient.resolveByIdentityKey({
|
|
345
|
-
identityKey
|
|
346
|
-
})
|
|
347
|
-
|
|
348
|
-
if (identities.length === 0) {
|
|
349
|
-
return {
|
|
350
|
-
success: false,
|
|
351
|
-
error: 'Identity not found'
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
const identity = identities[0]
|
|
356
|
-
|
|
357
|
-
// Create session
|
|
358
|
-
this.authenticatedUsers.set(identityKey, {
|
|
359
|
-
identity,
|
|
360
|
-
sessionStart: new Date(),
|
|
361
|
-
lastActivity: new Date()
|
|
362
|
-
})
|
|
363
|
-
|
|
364
|
-
console.log('User authenticated:', identity.name)
|
|
365
|
-
|
|
366
|
-
return {
|
|
367
|
-
success: true,
|
|
368
|
-
identityKey,
|
|
369
|
-
identity
|
|
370
|
-
}
|
|
371
|
-
} catch (error) {
|
|
372
|
-
console.error('Authentication failed:', error)
|
|
373
|
-
return {
|
|
374
|
-
success: false,
|
|
375
|
-
error: error.message
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
async verifySession(identityKey: string): Promise<boolean> {
|
|
381
|
-
const session = this.authenticatedUsers.get(identityKey)
|
|
382
|
-
|
|
383
|
-
if (!session) {
|
|
384
|
-
return false
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
// Check session timeout (24 hours)
|
|
388
|
-
const sessionAge = Date.now() - session.sessionStart.getTime()
|
|
389
|
-
const maxAge = 24 * 60 * 60 * 1000
|
|
390
|
-
|
|
391
|
-
if (sessionAge > maxAge) {
|
|
392
|
-
this.authenticatedUsers.delete(identityKey)
|
|
393
|
-
return false
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
// Update last activity
|
|
397
|
-
session.lastActivity = new Date()
|
|
398
|
-
return true
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
async requireAuthentication(identityKey: string): Promise<{
|
|
402
|
-
authorized: boolean
|
|
403
|
-
identity?: any
|
|
404
|
-
error?: string
|
|
405
|
-
}> {
|
|
406
|
-
const isValid = await this.verifySession(identityKey)
|
|
407
|
-
|
|
408
|
-
if (!isValid) {
|
|
409
|
-
return {
|
|
410
|
-
authorized: false,
|
|
411
|
-
error: 'Authentication required'
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
const session = this.authenticatedUsers.get(identityKey)
|
|
416
|
-
return {
|
|
417
|
-
authorized: true,
|
|
418
|
-
identity: session?.identity
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
logout(identityKey: string): void {
|
|
423
|
-
this.authenticatedUsers.delete(identityKey)
|
|
424
|
-
console.log('User logged out:', identityKey.substring(0, 20) + '...')
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
getActiveSessions(): Array<{
|
|
428
|
-
identityKey: string
|
|
429
|
-
name: string
|
|
430
|
-
sessionStart: Date
|
|
431
|
-
lastActivity: Date
|
|
432
|
-
}> {
|
|
433
|
-
return Array.from(this.authenticatedUsers.entries()).map(([key, session]) => ({
|
|
434
|
-
identityKey: key,
|
|
435
|
-
name: session.identity.name,
|
|
436
|
-
sessionStart: session.sessionStart,
|
|
437
|
-
lastActivity: session.lastActivity
|
|
438
|
-
}))
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
async function demonstrateAuthentication() {
|
|
443
|
-
const authService = new IdentityAuthService()
|
|
444
|
-
|
|
445
|
-
console.log('=== Identity Authentication Demo ===')
|
|
446
|
-
|
|
447
|
-
// Simulate user authentication
|
|
448
|
-
const wallet = new WalletClient()
|
|
449
|
-
const { publicKey: userIdentity } = await wallet.getPublicKey({
|
|
450
|
-
identityKey: true
|
|
451
|
-
})
|
|
452
|
-
|
|
453
|
-
// Authenticate user
|
|
454
|
-
const authResult = await authService.authenticateUser(userIdentity)
|
|
455
|
-
|
|
456
|
-
if (authResult.success) {
|
|
457
|
-
console.log('✅ Authentication successful')
|
|
458
|
-
console.log('User:', authResult.identity?.name || 'Unknown')
|
|
459
|
-
|
|
460
|
-
// Verify session
|
|
461
|
-
const sessionValid = await authService.verifySession(userIdentity)
|
|
462
|
-
console.log('Session valid:', sessionValid)
|
|
463
|
-
|
|
464
|
-
// Test authorization
|
|
465
|
-
const authCheck = await authService.requireAuthentication(userIdentity)
|
|
466
|
-
console.log('Authorization check:', authCheck.authorized ? 'PASSED' : 'FAILED')
|
|
467
|
-
|
|
468
|
-
// Show active sessions
|
|
469
|
-
const sessions = authService.getActiveSessions()
|
|
470
|
-
console.log('Active sessions:', sessions.length)
|
|
471
|
-
|
|
472
|
-
// Logout
|
|
473
|
-
authService.logout(userIdentity)
|
|
474
|
-
console.log('User logged out')
|
|
475
|
-
|
|
476
|
-
} else {
|
|
477
|
-
console.log('❌ Authentication failed:', authResult.error)
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
return authResult
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
demonstrateAuthentication().catch(console.error)
|
|
484
|
-
```
|
|
485
|
-
|
|
486
|
-
## Identity Verification Service
|
|
487
|
-
|
|
488
|
-
### Complete Verification System
|
|
489
|
-
|
|
490
|
-
```typescript
|
|
491
|
-
import { IdentityClient, WalletClient } from '@bsv/sdk'
|
|
492
|
-
|
|
493
|
-
interface VerificationRequest {
|
|
494
|
-
identityKey: string
|
|
495
|
-
requiredCertificates: string[]
|
|
496
|
-
purpose: string
|
|
497
|
-
timestamp: Date
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
interface VerificationResult {
|
|
501
|
-
verified: boolean
|
|
502
|
-
identityKey: string
|
|
503
|
-
certificates: any[]
|
|
504
|
-
trustScore: number
|
|
505
|
-
issues: string[]
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
class IdentityVerificationService {
|
|
509
|
-
private identityClient: IdentityClient
|
|
510
|
-
private verificationHistory: Map<string, VerificationResult[]> = new Map()
|
|
511
|
-
|
|
512
|
-
constructor(wallet?: WalletClient) {
|
|
513
|
-
this.identityClient = new IdentityClient(wallet)
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
async verifyIdentity(request: VerificationRequest): Promise<VerificationResult> {
|
|
517
|
-
console.log('Starting identity verification for:', request.identityKey.substring(0, 20) + '...')
|
|
518
|
-
console.log('Purpose:', request.purpose)
|
|
519
|
-
|
|
520
|
-
const result: VerificationResult = {
|
|
521
|
-
verified: false,
|
|
522
|
-
identityKey: request.identityKey,
|
|
523
|
-
certificates: [],
|
|
524
|
-
trustScore: 0,
|
|
525
|
-
issues: []
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
try {
|
|
529
|
-
// Resolve identity
|
|
530
|
-
const identities = await this.identityClient.resolveByIdentityKey({
|
|
531
|
-
identityKey: request.identityKey
|
|
532
|
-
})
|
|
533
|
-
|
|
534
|
-
if (identities.length === 0) {
|
|
535
|
-
result.issues.push('Identity not found')
|
|
536
|
-
return result
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
const identity = identities[0]
|
|
540
|
-
|
|
541
|
-
// Calculate trust score based on available information
|
|
542
|
-
result.trustScore = this.calculateTrustScore(identity)
|
|
543
|
-
|
|
544
|
-
// Check if verification meets requirements
|
|
545
|
-
if (result.trustScore >= 70) { // Minimum trust score
|
|
546
|
-
result.verified = true
|
|
547
|
-
console.log('✅ Identity verified:', identity.name)
|
|
548
|
-
} else {
|
|
549
|
-
result.issues.push('Insufficient trust score')
|
|
550
|
-
console.log('❌ Identity verification failed: low trust score')
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
// Store verification history
|
|
554
|
-
const history = this.verificationHistory.get(request.identityKey) || []
|
|
555
|
-
history.push(result)
|
|
556
|
-
this.verificationHistory.set(request.identityKey, history)
|
|
557
|
-
|
|
558
|
-
} catch (error) {
|
|
559
|
-
result.issues.push(`Verification error: ${error.message}`)
|
|
560
|
-
console.error('Verification error:', error)
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
return result
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
private calculateTrustScore(identity: any): number {
|
|
567
|
-
let score = 0
|
|
568
|
-
|
|
569
|
-
// Base score for having an identity
|
|
570
|
-
score += 30
|
|
571
|
-
|
|
572
|
-
// Score for having a name
|
|
573
|
-
if (identity.name && identity.name !== 'Unknown') {
|
|
574
|
-
score += 20
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
// Score for having an avatar
|
|
578
|
-
if (identity.avatarURL) {
|
|
579
|
-
score += 10
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
// Score for having a badge
|
|
583
|
-
if (identity.badgeLabel) {
|
|
584
|
-
score += 20
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
// Additional score for verified badge
|
|
588
|
-
if (identity.badgeLabel?.includes('Verified')) {
|
|
589
|
-
score += 20
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
return Math.min(score, 100) // Cap at 100
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
async batchVerify(identityKeys: string[], purpose: string): Promise<{
|
|
596
|
-
verified: VerificationResult[]
|
|
597
|
-
failed: VerificationResult[]
|
|
598
|
-
}> {
|
|
599
|
-
console.log(`Starting batch verification of ${identityKeys.length} identities`)
|
|
600
|
-
|
|
601
|
-
const requests = identityKeys.map(key => ({
|
|
602
|
-
identityKey: key,
|
|
603
|
-
requiredCertificates: [],
|
|
604
|
-
purpose,
|
|
605
|
-
timestamp: new Date()
|
|
606
|
-
}))
|
|
607
|
-
|
|
608
|
-
const results = await Promise.all(
|
|
609
|
-
requests.map(request => this.verifyIdentity(request))
|
|
610
|
-
)
|
|
611
|
-
|
|
612
|
-
const verified = results.filter(r => r.verified)
|
|
613
|
-
const failed = results.filter(r => !r.verified)
|
|
614
|
-
|
|
615
|
-
console.log(`Batch verification complete: ${verified.length} verified, ${failed.length} failed`)
|
|
616
|
-
|
|
617
|
-
return { verified, failed }
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
getVerificationHistory(identityKey: string): VerificationResult[] {
|
|
621
|
-
return this.verificationHistory.get(identityKey) || []
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
getTrustStatistics(): {
|
|
625
|
-
totalVerifications: number
|
|
626
|
-
successRate: number
|
|
627
|
-
averageTrustScore: number
|
|
628
|
-
} {
|
|
629
|
-
let totalVerifications = 0
|
|
630
|
-
let successfulVerifications = 0
|
|
631
|
-
let totalTrustScore = 0
|
|
632
|
-
|
|
633
|
-
for (const history of this.verificationHistory.values()) {
|
|
634
|
-
for (const result of history) {
|
|
635
|
-
totalVerifications++
|
|
636
|
-
totalTrustScore += result.trustScore
|
|
637
|
-
|
|
638
|
-
if (result.verified) {
|
|
639
|
-
successfulVerifications++
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
return {
|
|
645
|
-
totalVerifications,
|
|
646
|
-
successRate: totalVerifications > 0 ? successfulVerifications / totalVerifications : 0,
|
|
647
|
-
averageTrustScore: totalVerifications > 0 ? totalTrustScore / totalVerifications : 0
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
async function demonstrateVerificationService() {
|
|
653
|
-
const verificationService = new IdentityVerificationService()
|
|
654
|
-
|
|
655
|
-
console.log('=== Identity Verification Service Demo ===')
|
|
656
|
-
|
|
657
|
-
// Create test identities
|
|
658
|
-
const wallet1 = new WalletClient()
|
|
659
|
-
const wallet2 = new WalletClient()
|
|
660
|
-
|
|
661
|
-
const { publicKey: identity1 } = await wallet1.getPublicKey({ identityKey: true })
|
|
662
|
-
const { publicKey: identity2 } = await wallet2.getPublicKey({ identityKey: true })
|
|
663
|
-
|
|
664
|
-
const testIdentities = [identity1, identity2]
|
|
665
|
-
|
|
666
|
-
// Batch verification
|
|
667
|
-
const batchResult = await verificationService.batchVerify(
|
|
668
|
-
testIdentities,
|
|
669
|
-
'User registration verification'
|
|
670
|
-
)
|
|
671
|
-
|
|
672
|
-
console.log('Batch verification results:')
|
|
673
|
-
console.log(' Verified:', batchResult.verified.length)
|
|
674
|
-
console.log(' Failed:', batchResult.failed.length)
|
|
675
|
-
|
|
676
|
-
// Individual verification with details
|
|
677
|
-
for (const identity of testIdentities.slice(0, 1)) { // Just first one
|
|
678
|
-
const request: VerificationRequest = {
|
|
679
|
-
identityKey: identity,
|
|
680
|
-
requiredCertificates: ['identity'],
|
|
681
|
-
purpose: 'Account access verification',
|
|
682
|
-
timestamp: new Date()
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
const result = await verificationService.verifyIdentity(request)
|
|
686
|
-
|
|
687
|
-
console.log(`\nVerification for ${identity.substring(0, 20)}...`)
|
|
688
|
-
console.log(' Verified:', result.verified)
|
|
689
|
-
console.log(' Trust Score:', result.trustScore)
|
|
690
|
-
console.log(' Issues:', result.issues)
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
// Get statistics
|
|
694
|
-
const stats = verificationService.getTrustStatistics()
|
|
695
|
-
console.log('\nVerification Statistics:')
|
|
696
|
-
console.log(' Total Verifications:', stats.totalVerifications)
|
|
697
|
-
console.log(' Success Rate:', (stats.successRate * 100).toFixed(1) + '%')
|
|
698
|
-
console.log(' Average Trust Score:', stats.averageTrustScore.toFixed(1))
|
|
699
|
-
|
|
700
|
-
return { batchResult, stats }
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
demonstrateVerificationService().catch(console.error)
|
|
704
|
-
```
|
|
705
|
-
|
|
706
|
-
## Conclusion
|
|
707
|
-
|
|
708
|
-
Congratulations! You've successfully built a comprehensive identity management system using the BSV TypeScript SDK. In this tutorial, you've learned how to create, manage, and verify digital identities on the BSV blockchain.
|
|
709
|
-
|
|
710
|
-
### Core Concepts Mastered
|
|
711
|
-
|
|
712
|
-
1. **Identity Creation**: Generated unique BSV identities using cryptographic key pairs
|
|
713
|
-
2. **Certificate Management**: Created and managed identity certificates for enhanced trust
|
|
714
|
-
3. **Identity Resolution**: Implemented identity lookup and verification services
|
|
715
|
-
4. **Trust Scoring**: Built systems to calculate and evaluate identity trustworthiness
|
|
716
|
-
5. **Batch Processing**: Optimized identity operations for handling multiple identities efficiently
|
|
717
|
-
|
|
718
|
-
## Next Steps
|
|
719
|
-
|
|
720
|
-
- Learn about [AuthFetch Integration](./authfetch-tutorial.md) to use identities for API authentication
|
|
721
|
-
- Explore [Identity Verification Systems](../guides/identity-verification-systems.md) for advanced verification patterns
|
|
722
|
-
- Understand [Security Best Practices](../guides/security-best-practices.md) for production identity systems
|
|
723
|
-
|
|
724
|
-
## Additional Resources
|
|
725
|
-
|
|
726
|
-
- [Identity Client API Reference](../reference/identity.md)
|
|
727
|
-
- [Certificate Management Guide](../concepts/identity-certificates.md)
|
|
728
|
-
- [Decentralized Identity Concepts](../concepts/decentralized-identity.md)
|
|
729
|
-
- [BSV Identity Standards](https://projectbabbage.com/docs/guides/identity)
|