@bsv/sdk 1.3.1 → 1.3.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/dist/cjs/package.json +1 -1
- package/dist/cjs/src/auth/Peer.js +19 -1
- package/dist/cjs/src/auth/Peer.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/src/auth/Peer.js +21 -1
- package/dist/esm/src/auth/Peer.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/src/auth/Peer.d.ts +4 -1
- package/dist/types/src/auth/Peer.d.ts.map +1 -1
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/dist/umd/bundle.js +1 -1
- package/docs/auth.md +7 -5
- package/package.json +1 -1
- package/src/auth/Peer.ts +47 -22
package/docs/auth.md
CHANGED
|
@@ -134,7 +134,7 @@ See also: [RequestedCertificateSet](#interface-requestedcertificateset), [Sessio
|
|
|
134
134
|
|
|
135
135
|
#### Constructor
|
|
136
136
|
|
|
137
|
-
Constructs a new
|
|
137
|
+
Constructs a new AuthFetch instance.
|
|
138
138
|
|
|
139
139
|
```ts
|
|
140
140
|
constructor(wallet: Wallet, requestedCertificates?: RequestedCertificateSet, sessionManager?: SessionManager)
|
|
@@ -459,7 +459,7 @@ and sending and receiving general messages over a transport layer.
|
|
|
459
459
|
export class Peer {
|
|
460
460
|
public sessionManager: SessionManager;
|
|
461
461
|
certificatesToRequest: RequestedCertificateSet;
|
|
462
|
-
constructor(wallet: Wallet, transport: Transport, certificatesToRequest?: RequestedCertificateSet, sessionManager?: SessionManager)
|
|
462
|
+
constructor(wallet: Wallet, transport: Transport, certificatesToRequest?: RequestedCertificateSet, sessionManager?: SessionManager, autoPersistLastSession?: boolean)
|
|
463
463
|
async toPeer(message: number[], identityKey?: string, maxWaitTime?: number): Promise<void>
|
|
464
464
|
async requestCertificates(certificatesToRequest: RequestedCertificateSet, identityKey?: string, maxWaitTime = 10000): Promise<void>
|
|
465
465
|
async getAuthenticatedSession(identityKey?: string, maxWaitTime?: number): Promise<PeerSession>
|
|
@@ -485,7 +485,7 @@ See also: [AuthMessage](#interface-authmessage), [PeerSession](#interface-peerse
|
|
|
485
485
|
Creates a new Peer instance
|
|
486
486
|
|
|
487
487
|
```ts
|
|
488
|
-
constructor(wallet: Wallet, transport: Transport, certificatesToRequest?: RequestedCertificateSet, sessionManager?: SessionManager)
|
|
488
|
+
constructor(wallet: Wallet, transport: Transport, certificatesToRequest?: RequestedCertificateSet, sessionManager?: SessionManager, autoPersistLastSession?: boolean)
|
|
489
489
|
```
|
|
490
490
|
See also: [RequestedCertificateSet](#interface-requestedcertificateset), [SessionManager](#class-sessionmanager), [Transport](#interface-transport), [Wallet](#interface-wallet)
|
|
491
491
|
|
|
@@ -499,6 +499,8 @@ Argument Details
|
|
|
499
499
|
+ Optional set of certificates to request from a peer during the initial handshake.
|
|
500
500
|
+ **sessionManager**
|
|
501
501
|
+ Optional SessionManager to be used for managing peer sessions.
|
|
502
|
+
+ **autoPersistLastSession**
|
|
503
|
+
+ Whether to auto-persist the session with the last-interacted-with peer. Defaults to true.
|
|
502
504
|
|
|
503
505
|
#### Method getAuthenticatedSession
|
|
504
506
|
|
|
@@ -822,7 +824,7 @@ This class integrates with fetch to send and receive authenticated messages betw
|
|
|
822
824
|
export class SimplifiedFetchTransport implements Transport {
|
|
823
825
|
fetchClient: typeof fetch;
|
|
824
826
|
baseUrl: string;
|
|
825
|
-
constructor(baseUrl: string, fetchClient =
|
|
827
|
+
constructor(baseUrl: string, fetchClient = defaultFetch)
|
|
826
828
|
async send(message: AuthMessage): Promise<void>
|
|
827
829
|
async onData(callback: (message: AuthMessage) => Promise<void>): Promise<void>
|
|
828
830
|
deserializeRequestPayload(payload: number[]): {
|
|
@@ -846,7 +848,7 @@ See also: [AuthMessage](#interface-authmessage), [Transport](#interface-transpor
|
|
|
846
848
|
Constructs a new instance of SimplifiedFetchTransport.
|
|
847
849
|
|
|
848
850
|
```ts
|
|
849
|
-
constructor(baseUrl: string, fetchClient =
|
|
851
|
+
constructor(baseUrl: string, fetchClient = defaultFetch)
|
|
850
852
|
```
|
|
851
853
|
|
|
852
854
|
Argument Details
|
package/package.json
CHANGED
package/src/auth/Peer.ts
CHANGED
|
@@ -24,6 +24,12 @@ export class Peer {
|
|
|
24
24
|
// Single shared counter for all callback types
|
|
25
25
|
private callbackIdCounter: number = 0
|
|
26
26
|
|
|
27
|
+
// Whether to auto-persist the session with the last-interacted-with peer
|
|
28
|
+
private autoPersistLastSession: boolean = true
|
|
29
|
+
|
|
30
|
+
// Last-interacted-with peer identity key
|
|
31
|
+
private lastInteractedWithPeer: string | undefined
|
|
32
|
+
|
|
27
33
|
/**
|
|
28
34
|
* Creates a new Peer instance
|
|
29
35
|
*
|
|
@@ -31,18 +37,25 @@ export class Peer {
|
|
|
31
37
|
* @param {Transport} transport - The transport mechanism used for sending and receiving messages.
|
|
32
38
|
* @param {RequestedCertificateSet} [certificatesToRequest] - Optional set of certificates to request from a peer during the initial handshake.
|
|
33
39
|
* @param {SessionManager} [sessionManager] - Optional SessionManager to be used for managing peer sessions.
|
|
40
|
+
* @param {boolean} [autoPersistLastSession] - Whether to auto-persist the session with the last-interacted-with peer. Defaults to true.
|
|
34
41
|
*/
|
|
35
|
-
constructor
|
|
42
|
+
constructor(
|
|
36
43
|
wallet: Wallet,
|
|
37
44
|
transport: Transport,
|
|
38
45
|
certificatesToRequest?: RequestedCertificateSet,
|
|
39
|
-
sessionManager?: SessionManager
|
|
46
|
+
sessionManager?: SessionManager,
|
|
47
|
+
autoPersistLastSession?: boolean
|
|
40
48
|
) {
|
|
41
49
|
this.wallet = wallet
|
|
42
50
|
this.transport = transport
|
|
43
51
|
this.certificatesToRequest = certificatesToRequest ?? { certifiers: [], types: {} }
|
|
44
52
|
this.transport.onData(this.handleIncomingMessage.bind(this))
|
|
45
53
|
this.sessionManager = sessionManager || new SessionManager()
|
|
54
|
+
if (autoPersistLastSession === false) {
|
|
55
|
+
this.autoPersistLastSession = false
|
|
56
|
+
} else {
|
|
57
|
+
this.autoPersistLastSession = true
|
|
58
|
+
}
|
|
46
59
|
}
|
|
47
60
|
|
|
48
61
|
/**
|
|
@@ -53,7 +66,10 @@ export class Peer {
|
|
|
53
66
|
* @returns {Promise<void>}
|
|
54
67
|
* @throws Will throw an error if the message fails to send.
|
|
55
68
|
*/
|
|
56
|
-
async toPeer
|
|
69
|
+
async toPeer(message: number[], identityKey?: string, maxWaitTime?: number): Promise<void> {
|
|
70
|
+
if (this.autoPersistLastSession && this.lastInteractedWithPeer && typeof identityKey !== 'string') {
|
|
71
|
+
identityKey = this.lastInteractedWithPeer
|
|
72
|
+
}
|
|
57
73
|
const peerSession = await this.getAuthenticatedSession(identityKey, maxWaitTime)
|
|
58
74
|
|
|
59
75
|
// Prepare the general message
|
|
@@ -95,7 +111,7 @@ export class Peer {
|
|
|
95
111
|
* @returns {Promise<void>} Resolves if the certificate request message is successfully sent.
|
|
96
112
|
* @throws Will throw an error if the peer session is not authenticated or if sending the request fails.
|
|
97
113
|
*/
|
|
98
|
-
async requestCertificates
|
|
114
|
+
async requestCertificates(certificatesToRequest: RequestedCertificateSet, identityKey?: string, maxWaitTime = 10000): Promise<void> {
|
|
99
115
|
const peerSession = await this.getAuthenticatedSession(identityKey, maxWaitTime)
|
|
100
116
|
|
|
101
117
|
// Prepare the general message
|
|
@@ -136,7 +152,7 @@ export class Peer {
|
|
|
136
152
|
* @returns {Promise<PeerSession>} - A promise that resolves with an authenticated `PeerSession`.
|
|
137
153
|
* @throws {Error} - Throws an error if the transport is not connected or if the handshake fails.
|
|
138
154
|
*/
|
|
139
|
-
async getAuthenticatedSession
|
|
155
|
+
async getAuthenticatedSession(identityKey?: string, maxWaitTime?: number): Promise<PeerSession> {
|
|
140
156
|
if (!this.transport) {
|
|
141
157
|
throw new Error('Peer transport is not connected!')
|
|
142
158
|
}
|
|
@@ -159,7 +175,7 @@ export class Peer {
|
|
|
159
175
|
* @param {(senderPublicKey: string, payload: number[]) => void} callback - The function to call when a general message is received.
|
|
160
176
|
* @returns {number} The ID of the callback listener.
|
|
161
177
|
*/
|
|
162
|
-
listenForGeneralMessages
|
|
178
|
+
listenForGeneralMessages(callback: (senderPublicKey: string, payload: number[]) => void): number {
|
|
163
179
|
const callbackID = this.callbackIdCounter++
|
|
164
180
|
this.onGeneralMessageReceivedCallbacks.set(callbackID, callback)
|
|
165
181
|
return callbackID
|
|
@@ -170,7 +186,7 @@ export class Peer {
|
|
|
170
186
|
*
|
|
171
187
|
* @param {number} callbackID - The ID of the callback to remove.
|
|
172
188
|
*/
|
|
173
|
-
stopListeningForGeneralMessages
|
|
189
|
+
stopListeningForGeneralMessages(callbackID: number): void {
|
|
174
190
|
this.onGeneralMessageReceivedCallbacks.delete(callbackID)
|
|
175
191
|
}
|
|
176
192
|
|
|
@@ -180,7 +196,7 @@ export class Peer {
|
|
|
180
196
|
* @param {(certs: VerifiableCertificate[]) => void} callback - The function to call when certificates are received.
|
|
181
197
|
* @returns {number} The ID of the callback listener.
|
|
182
198
|
*/
|
|
183
|
-
listenForCertificatesReceived
|
|
199
|
+
listenForCertificatesReceived(callback: (senderPublicKey: string, certs: VerifiableCertificate[]) => void): number {
|
|
184
200
|
const callbackID = this.callbackIdCounter++
|
|
185
201
|
this.onCertificatesReceivedCallbacks.set(callbackID, callback)
|
|
186
202
|
return callbackID
|
|
@@ -191,7 +207,7 @@ export class Peer {
|
|
|
191
207
|
*
|
|
192
208
|
* @param {number} callbackID - The ID of the certificates received callback to cancel.
|
|
193
209
|
*/
|
|
194
|
-
stopListeningForCertificatesReceived
|
|
210
|
+
stopListeningForCertificatesReceived(callbackID: number): void {
|
|
195
211
|
this.onCertificatesReceivedCallbacks.delete(callbackID)
|
|
196
212
|
}
|
|
197
213
|
|
|
@@ -201,7 +217,7 @@ export class Peer {
|
|
|
201
217
|
* @param {(requestedCertificates: RequestedCertificateSet) => void} callback - The function to call when a certificate request is received
|
|
202
218
|
* @returns {number} The ID of the callback listener.
|
|
203
219
|
*/
|
|
204
|
-
listenForCertificatesRequested
|
|
220
|
+
listenForCertificatesRequested(callback: (senderPublicKey: string, requestedCertificates: RequestedCertificateSet) => void): number {
|
|
205
221
|
const callbackID = this.callbackIdCounter++
|
|
206
222
|
this.onCertificateRequestReceivedCallbacks.set(callbackID, callback)
|
|
207
223
|
return callbackID
|
|
@@ -212,7 +228,7 @@ export class Peer {
|
|
|
212
228
|
*
|
|
213
229
|
* @param {number} callbackID - The ID of the requested certificates callback to cancel.
|
|
214
230
|
*/
|
|
215
|
-
stopListeningForCertificatesRequested
|
|
231
|
+
stopListeningForCertificatesRequested(callbackID: number): void {
|
|
216
232
|
this.onCertificateRequestReceivedCallbacks.delete(callbackID)
|
|
217
233
|
}
|
|
218
234
|
|
|
@@ -223,7 +239,7 @@ export class Peer {
|
|
|
223
239
|
* @param {string} [identityKey] - The identity public key of the peer.
|
|
224
240
|
* @returns {Promise<string>} A promise that resolves to the session nonce.
|
|
225
241
|
*/
|
|
226
|
-
private async initiateHandshake
|
|
242
|
+
private async initiateHandshake(identityKey?: string, maxWaitTime = 10000): Promise<string> {
|
|
227
243
|
const sessionNonce = await createNonce(this.wallet) // Initial request nonce
|
|
228
244
|
this.sessionManager.addSession({
|
|
229
245
|
isAuthenticated: false,
|
|
@@ -249,7 +265,7 @@ export class Peer {
|
|
|
249
265
|
* @param {string} sessionNonce - The session nonce created in the initial request.
|
|
250
266
|
* @returns {Promise<string>} A promise that resolves with the session nonce when the initial response is received.
|
|
251
267
|
*/
|
|
252
|
-
private async waitForInitialResponse
|
|
268
|
+
private async waitForInitialResponse(sessionNonce: string, maxWaitTime = 10000): Promise<string> {
|
|
253
269
|
return await new Promise((resolve, reject) => {
|
|
254
270
|
const callbackID = this.listenForInitialResponse(sessionNonce, (sessionNonce) => {
|
|
255
271
|
clearTimeout(timeoutHandle)
|
|
@@ -272,7 +288,7 @@ export class Peer {
|
|
|
272
288
|
* @param {(sessionNonce: string) => void} callback - The callback to invoke when the initial response is received.
|
|
273
289
|
* @returns {number} The ID of the callback listener.
|
|
274
290
|
*/
|
|
275
|
-
private listenForInitialResponse
|
|
291
|
+
private listenForInitialResponse(sessionNonce: string, callback: (sessionNonce: string) => void) {
|
|
276
292
|
const callbackID = this.callbackIdCounter++
|
|
277
293
|
this.onInitialResponseReceivedCallbacks.set(callbackID, { callback, sessionNonce })
|
|
278
294
|
return callbackID
|
|
@@ -284,7 +300,7 @@ export class Peer {
|
|
|
284
300
|
* @private
|
|
285
301
|
* @param {number} callbackID - The ID of the callback to remove.
|
|
286
302
|
*/
|
|
287
|
-
private stopListeningForInitialResponses
|
|
303
|
+
private stopListeningForInitialResponses(callbackID: number) {
|
|
288
304
|
this.onInitialResponseReceivedCallbacks.delete(callbackID)
|
|
289
305
|
}
|
|
290
306
|
|
|
@@ -294,7 +310,7 @@ export class Peer {
|
|
|
294
310
|
* @param {AuthMessage} message - The incoming message to process.
|
|
295
311
|
* @returns {Promise<void>}
|
|
296
312
|
*/
|
|
297
|
-
private async handleIncomingMessage
|
|
313
|
+
private async handleIncomingMessage(message: AuthMessage): Promise<void> {
|
|
298
314
|
if (!message.version || message.version !== AUTH_VERSION) {
|
|
299
315
|
console.error(`Invalid message auth version! Received: ${message.version}, expected: ${AUTH_VERSION}`)
|
|
300
316
|
return
|
|
@@ -327,7 +343,7 @@ export class Peer {
|
|
|
327
343
|
* @param {AuthMessage} message - The incoming initial request message.
|
|
328
344
|
* @returns {Promise<void>}
|
|
329
345
|
*/
|
|
330
|
-
async processInitialRequest
|
|
346
|
+
async processInitialRequest(message: AuthMessage) {
|
|
331
347
|
if (!message.identityKey || !message.initialNonce) {
|
|
332
348
|
throw new Error('Missing required fields in initialResponse message.')
|
|
333
349
|
}
|
|
@@ -374,6 +390,11 @@ export class Peer {
|
|
|
374
390
|
signature
|
|
375
391
|
}
|
|
376
392
|
|
|
393
|
+
// For security, only set the last-interacted-with peer here if this is the first peer we've interacted with.
|
|
394
|
+
if (!this.lastInteractedWithPeer) {
|
|
395
|
+
this.lastInteractedWithPeer = message.identityKey
|
|
396
|
+
}
|
|
397
|
+
|
|
377
398
|
await this.transport.send(initialResponseMessage)
|
|
378
399
|
}
|
|
379
400
|
|
|
@@ -385,7 +406,7 @@ export class Peer {
|
|
|
385
406
|
* @returns {Promise<void>}
|
|
386
407
|
* @throws Will throw an error if nonce verification or signature verification fails.
|
|
387
408
|
*/
|
|
388
|
-
private async processInitialResponse
|
|
409
|
+
private async processInitialResponse(message: AuthMessage) {
|
|
389
410
|
const validNonce = await verifyNonce(message.yourNonce, this.wallet)
|
|
390
411
|
if (!validNonce) {
|
|
391
412
|
throw new Error(`Initial response nonce verification failed from peer: ${message.identityKey}`)
|
|
@@ -426,6 +447,8 @@ export class Peer {
|
|
|
426
447
|
)
|
|
427
448
|
}
|
|
428
449
|
|
|
450
|
+
this.lastInteractedWithPeer = message.identityKey
|
|
451
|
+
|
|
429
452
|
this.onInitialResponseReceivedCallbacks.forEach((entry) => {
|
|
430
453
|
if (entry && entry.sessionNonce === peerSession.sessionNonce) {
|
|
431
454
|
entry.callback(peerSession.sessionNonce)
|
|
@@ -455,7 +478,7 @@ export class Peer {
|
|
|
455
478
|
* @param {AuthMessage} message - The certificate request message received from the peer.
|
|
456
479
|
* @throws {Error} Throws an error if nonce verification fails, or the message signature is invalid.
|
|
457
480
|
*/
|
|
458
|
-
private async processCertificateRequest
|
|
481
|
+
private async processCertificateRequest(message: AuthMessage) {
|
|
459
482
|
const validNonce = await verifyNonce(message.yourNonce, this.wallet)
|
|
460
483
|
if (!validNonce) {
|
|
461
484
|
throw new Error(`Unable to verify nonce for certificate request message from: ${message.identityKey}`)
|
|
@@ -497,7 +520,7 @@ export class Peer {
|
|
|
497
520
|
*
|
|
498
521
|
* @throws {Error} Throws an error if the peer session could not be authenticated or if message signing fails.
|
|
499
522
|
*/
|
|
500
|
-
async sendCertificateResponse
|
|
523
|
+
async sendCertificateResponse(
|
|
501
524
|
verifierIdentityKey: string,
|
|
502
525
|
certificates: VerifiableCertificate[]
|
|
503
526
|
) {
|
|
@@ -536,7 +559,7 @@ export class Peer {
|
|
|
536
559
|
* @returns {Promise<void>}
|
|
537
560
|
* @throws Will throw an error if nonce verification or signature verification fails.
|
|
538
561
|
*/
|
|
539
|
-
private async processCertificateResponse
|
|
562
|
+
private async processCertificateResponse(
|
|
540
563
|
message: AuthMessage
|
|
541
564
|
) {
|
|
542
565
|
const validNonce = await verifyNonce(message.yourNonce, this.wallet)
|
|
@@ -574,7 +597,7 @@ export class Peer {
|
|
|
574
597
|
* @returns {Promise<void>}
|
|
575
598
|
* @throws Will throw an error if nonce verification or signature verification fails.
|
|
576
599
|
*/
|
|
577
|
-
private async processGeneralMessage
|
|
600
|
+
private async processGeneralMessage(message: AuthMessage) {
|
|
578
601
|
const validNonce = await verifyNonce(message.yourNonce, this.wallet)
|
|
579
602
|
if (!validNonce) {
|
|
580
603
|
throw new Error(`Unable to verify nonce for general message from: ${message.identityKey}`)
|
|
@@ -593,6 +616,8 @@ export class Peer {
|
|
|
593
616
|
throw new Error(`Invalid signature in generalMessage from ${peerSession.peerIdentityKey}`)
|
|
594
617
|
}
|
|
595
618
|
|
|
619
|
+
this.lastInteractedWithPeer = message.identityKey
|
|
620
|
+
|
|
596
621
|
this.onGeneralMessageReceivedCallbacks.forEach(callback => {
|
|
597
622
|
callback(message.identityKey, message.payload)
|
|
598
623
|
})
|