@toon-protocol/core 3.3.0 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,591 @@
1
+ // src/wire/oer.ts
2
+ var OerErrorKind = /* @__PURE__ */ ((OerErrorKind2) => {
3
+ OerErrorKind2["BufferUnderflow"] = "buffer_underflow";
4
+ OerErrorKind2["NonCanonicalLength"] = "non_canonical_length";
5
+ OerErrorKind2["LengthDeterminantOverflow"] = "length_determinant_overflow";
6
+ return OerErrorKind2;
7
+ })(OerErrorKind || {});
8
+ var OerError = class extends Error {
9
+ constructor(kind) {
10
+ super(OER_ERROR_MESSAGES[kind]);
11
+ this.kind = kind;
12
+ this.name = "OerError";
13
+ }
14
+ };
15
+ var OER_ERROR_MESSAGES = {
16
+ ["buffer_underflow" /* BufferUnderflow */]: "buffer underflow: the value is truncated",
17
+ ["non_canonical_length" /* NonCanonicalLength */]: "non-canonical OER length determinant: not the minimal encoding of its value",
18
+ ["length_determinant_overflow" /* LengthDeterminantOverflow */]: "OER length determinant wider than 8 bytes"
19
+ };
20
+ var MAX_DETERMINANT_BYTES = 8;
21
+ function encodeVarUint(value) {
22
+ if (value < 0n)
23
+ throw new RangeError("VarUInt cannot encode a negative value");
24
+ if (value <= 127n) return Uint8Array.of(Number(value));
25
+ const body = [];
26
+ let remaining = value;
27
+ while (remaining > 0n) {
28
+ body.unshift(Number(remaining & 0xffn));
29
+ remaining >>= 8n;
30
+ }
31
+ if (body.length > MAX_DETERMINANT_BYTES) {
32
+ throw new RangeError("VarUInt cannot encode a value wider than 8 bytes");
33
+ }
34
+ return Uint8Array.from([128 | body.length, ...body]);
35
+ }
36
+ function decodeVarUint(buf, offset) {
37
+ const first = buf[offset];
38
+ if (first === void 0) throw new OerError("buffer_underflow" /* BufferUnderflow */);
39
+ if (first <= 127) return { value: BigInt(first), consumed: 1 };
40
+ const length = first & 127;
41
+ if (length > MAX_DETERMINANT_BYTES) {
42
+ throw new OerError("length_determinant_overflow" /* LengthDeterminantOverflow */);
43
+ }
44
+ const start = offset + 1;
45
+ const end = start + length;
46
+ if (end > buf.length) throw new OerError("buffer_underflow" /* BufferUnderflow */);
47
+ let value = 0n;
48
+ for (let i = start; i < end; i++) {
49
+ value = value << 8n | BigInt(buf[i]);
50
+ }
51
+ const consumed = 1 + length;
52
+ const canonical = encodeVarUint(value);
53
+ if (canonical.length !== consumed || !canonical.every((byte, i) => byte === buf[offset + i])) {
54
+ throw new OerError("non_canonical_length" /* NonCanonicalLength */);
55
+ }
56
+ return { value, consumed };
57
+ }
58
+ function encodeVarOctetString(data) {
59
+ const prefix = encodeVarUint(BigInt(data.length));
60
+ const out = new Uint8Array(prefix.length + data.length);
61
+ out.set(prefix, 0);
62
+ out.set(data, prefix.length);
63
+ return out;
64
+ }
65
+ function decodeVarOctetString(buf, offset) {
66
+ const { value: length, consumed: lengthBytes } = decodeVarUint(buf, offset);
67
+ if (length > BigInt(buf.length)) {
68
+ throw new OerError("buffer_underflow" /* BufferUnderflow */);
69
+ }
70
+ const start = offset + lengthBytes;
71
+ const end = start + Number(length);
72
+ if (end > buf.length) throw new OerError("buffer_underflow" /* BufferUnderflow */);
73
+ return {
74
+ value: buf.slice(start, end),
75
+ consumed: lengthBytes + Number(length)
76
+ };
77
+ }
78
+
79
+ // src/wire/envelope.ts
80
+ var TYPE_ENVELOPE_REQUEST = 1;
81
+ var TYPE_ENVELOPE_RESPONSE = 2;
82
+ var EnvelopeErrorKind = /* @__PURE__ */ ((EnvelopeErrorKind2) => {
83
+ EnvelopeErrorKind2["BufferUnderflow"] = "buffer_underflow";
84
+ EnvelopeErrorKind2["NonCanonicalLength"] = "non_canonical_length";
85
+ EnvelopeErrorKind2["LengthDeterminantOverflow"] = "length_determinant_overflow";
86
+ EnvelopeErrorKind2["InvalidType"] = "invalid_type";
87
+ EnvelopeErrorKind2["InvalidUtf8"] = "invalid_utf8";
88
+ EnvelopeErrorKind2["TrailingBytes"] = "trailing_bytes";
89
+ return EnvelopeErrorKind2;
90
+ })(EnvelopeErrorKind || {});
91
+ var EnvelopeError = class extends Error {
92
+ constructor(kind, field) {
93
+ super(
94
+ field === void 0 ? ENVELOPE_ERROR_MESSAGES[kind] : `${ENVELOPE_ERROR_MESSAGES[kind]} (field '${field}')`
95
+ );
96
+ this.kind = kind;
97
+ this.field = field;
98
+ this.name = "EnvelopeError";
99
+ }
100
+ };
101
+ var ENVELOPE_ERROR_MESSAGES = {
102
+ ["buffer_underflow" /* BufferUnderflow */]: "buffer underflow: envelope is truncated",
103
+ ["non_canonical_length" /* NonCanonicalLength */]: "non-canonical OER length determinant: not the minimal encoding of its value",
104
+ ["length_determinant_overflow" /* LengthDeterminantOverflow */]: "OER length determinant wider than 8 bytes",
105
+ ["invalid_type" /* InvalidType */]: "invalid envelope type byte: expected 1 (REQUEST) or 2 (RESPONSE)",
106
+ ["invalid_utf8" /* InvalidUtf8 */]: "invalid UTF-8 in envelope field",
107
+ ["trailing_bytes" /* TrailingBytes */]: "trailing bytes after a fully decoded envelope"
108
+ };
109
+ var UTF8_ENCODER = new TextEncoder();
110
+ var UTF8_DECODER = new TextDecoder("utf-8", { fatal: true });
111
+ function fromOerError(error) {
112
+ if (error instanceof OerError) {
113
+ switch (error.kind) {
114
+ case "buffer_underflow" /* BufferUnderflow */:
115
+ return new EnvelopeError("buffer_underflow" /* BufferUnderflow */);
116
+ case "non_canonical_length" /* NonCanonicalLength */:
117
+ return new EnvelopeError("non_canonical_length" /* NonCanonicalLength */);
118
+ case "length_determinant_overflow" /* LengthDeterminantOverflow */:
119
+ return new EnvelopeError("length_determinant_overflow" /* LengthDeterminantOverflow */);
120
+ }
121
+ }
122
+ throw error;
123
+ }
124
+ function decodeOctets(buf, offset) {
125
+ try {
126
+ return decodeVarOctetString(buf, offset);
127
+ } catch (error) {
128
+ throw fromOerError(error);
129
+ }
130
+ }
131
+ function decodeCount(buf, offset) {
132
+ try {
133
+ return decodeVarUint(buf, offset);
134
+ } catch (error) {
135
+ throw fromOerError(error);
136
+ }
137
+ }
138
+ function decodeStringField(buf, offset, field) {
139
+ const { value: bytes, consumed } = decodeOctets(buf, offset);
140
+ try {
141
+ return { value: UTF8_DECODER.decode(bytes), consumed };
142
+ } catch {
143
+ throw new EnvelopeError("invalid_utf8" /* InvalidUtf8 */, field);
144
+ }
145
+ }
146
+ function checkTypeByte(buf, expected) {
147
+ const typeByte = buf[0];
148
+ if (typeByte === void 0) {
149
+ throw new EnvelopeError("buffer_underflow" /* BufferUnderflow */);
150
+ }
151
+ if (typeByte !== expected) {
152
+ throw new EnvelopeError("invalid_type" /* InvalidType */);
153
+ }
154
+ return 1;
155
+ }
156
+ function concat(parts) {
157
+ const total = parts.reduce((sum, part) => sum + part.length, 0);
158
+ const out = new Uint8Array(total);
159
+ let offset = 0;
160
+ for (const part of parts) {
161
+ out.set(part, offset);
162
+ offset += part.length;
163
+ }
164
+ return out;
165
+ }
166
+ function encodeHeaders(headers) {
167
+ const parts = [encodeVarUint(BigInt(headers.length))];
168
+ for (const [name, value] of headers) {
169
+ parts.push(encodeVarOctetString(UTF8_ENCODER.encode(name)));
170
+ parts.push(encodeVarOctetString(UTF8_ENCODER.encode(value)));
171
+ }
172
+ return concat(parts);
173
+ }
174
+ function decodeHeaders(buf, offset) {
175
+ const { value: count, consumed: countBytes } = decodeCount(buf, offset);
176
+ if (count * 2n > BigInt(buf.length - offset - countBytes)) {
177
+ throw new EnvelopeError("buffer_underflow" /* BufferUnderflow */);
178
+ }
179
+ let consumed = countBytes;
180
+ const headers = [];
181
+ for (let i = 0n; i < count; i++) {
182
+ const name = decodeStringField(buf, offset + consumed, "header name");
183
+ consumed += name.consumed;
184
+ const value = decodeStringField(buf, offset + consumed, "header value");
185
+ consumed += value.consumed;
186
+ headers.push([name.value, value.value]);
187
+ }
188
+ return { value: headers, consumed };
189
+ }
190
+ function encodeEnvelopeRequest(request) {
191
+ return concat([
192
+ Uint8Array.of(TYPE_ENVELOPE_REQUEST),
193
+ encodeVarOctetString(UTF8_ENCODER.encode(request.method)),
194
+ encodeVarOctetString(UTF8_ENCODER.encode(request.target)),
195
+ encodeHeaders(request.headers),
196
+ encodeVarOctetString(request.body)
197
+ ]);
198
+ }
199
+ function decodeEnvelopeRequest(buf) {
200
+ let offset = checkTypeByte(buf, TYPE_ENVELOPE_REQUEST);
201
+ const method = decodeStringField(buf, offset, "method");
202
+ offset += method.consumed;
203
+ const target = decodeStringField(buf, offset, "target");
204
+ offset += target.consumed;
205
+ const headers = decodeHeaders(buf, offset);
206
+ offset += headers.consumed;
207
+ const body = decodeOctets(buf, offset);
208
+ offset += body.consumed;
209
+ if (offset !== buf.length) {
210
+ throw new EnvelopeError("trailing_bytes" /* TrailingBytes */);
211
+ }
212
+ return {
213
+ method: method.value,
214
+ target: target.value,
215
+ headers: headers.value,
216
+ body: body.value
217
+ };
218
+ }
219
+ function encodeEnvelopeResponse(response) {
220
+ if (!Number.isInteger(response.status) || response.status < 0 || response.status > 65535) {
221
+ throw new RangeError(
222
+ `envelope status must fit two bytes, got ${response.status}`
223
+ );
224
+ }
225
+ return concat([
226
+ Uint8Array.of(
227
+ TYPE_ENVELOPE_RESPONSE,
228
+ response.status >> 8 & 255,
229
+ response.status & 255
230
+ ),
231
+ encodeHeaders(response.headers),
232
+ encodeVarOctetString(response.body)
233
+ ]);
234
+ }
235
+ function decodeEnvelopeResponse(buf) {
236
+ let offset = checkTypeByte(buf, TYPE_ENVELOPE_RESPONSE);
237
+ const high = buf[offset];
238
+ const low = buf[offset + 1];
239
+ if (high === void 0 || low === void 0) {
240
+ throw new EnvelopeError("buffer_underflow" /* BufferUnderflow */);
241
+ }
242
+ const status = high << 8 | low;
243
+ offset += 2;
244
+ const headers = decodeHeaders(buf, offset);
245
+ offset += headers.consumed;
246
+ const body = decodeOctets(buf, offset);
247
+ offset += body.consumed;
248
+ if (offset !== buf.length) {
249
+ throw new EnvelopeError("trailing_bytes" /* TrailingBytes */);
250
+ }
251
+ return { status, headers: headers.value, body: body.value };
252
+ }
253
+ function encodeEnvelope(envelope) {
254
+ return envelope.direction === "request" ? encodeEnvelopeRequest(envelope) : encodeEnvelopeResponse(envelope);
255
+ }
256
+ function decodeEnvelope(buf, direction) {
257
+ return direction === "request" ? { direction, ...decodeEnvelopeRequest(buf) } : { direction, ...decodeEnvelopeResponse(buf) };
258
+ }
259
+
260
+ // src/wire/giftwrap.ts
261
+ import { secp256k1 } from "@noble/curves/secp256k1.js";
262
+ import { chacha20poly1305 } from "@noble/ciphers/chacha.js";
263
+ import { hkdf } from "@noble/hashes/hkdf.js";
264
+ import { sha256 } from "@noble/hashes/sha2.js";
265
+ import { randomBytes } from "@noble/hashes/utils.js";
266
+ var GIFTWRAP_NONCE_LENGTH = 12;
267
+ var GIFTWRAP_SECRET_LENGTH = 32;
268
+ var GIFTWRAP_PUBLIC_KEY_LENGTH = 65;
269
+ var REQUEST_INFO = "toon-giftwrap-request";
270
+ var RESPONSE_INFO = "toon-giftwrap-response";
271
+ var FULFILLMENT_INFO = "toon-giftwrap-fulfillment";
272
+ var GIFTWRAP_TYPE_REQUEST = 1;
273
+ var GIFTWRAP_TYPE_RESPONSE = 2;
274
+ var TAG_LENGTH = 16;
275
+ var GiftWrapErrorKind = /* @__PURE__ */ ((GiftWrapErrorKind2) => {
276
+ GiftWrapErrorKind2["InvalidType"] = "invalid_type";
277
+ GiftWrapErrorKind2["Truncated"] = "truncated";
278
+ GiftWrapErrorKind2["InvalidKey"] = "invalid_key";
279
+ GiftWrapErrorKind2["OpenFailed"] = "open_failed";
280
+ return GiftWrapErrorKind2;
281
+ })(GiftWrapErrorKind || {});
282
+ var GIFTWRAP_ERROR_MESSAGES = {
283
+ ["invalid_type" /* InvalidType */]: "invalid gift wrap type byte",
284
+ ["truncated" /* Truncated */]: "gift wrap is truncated",
285
+ ["invalid_key" /* InvalidKey */]: "invalid ephemeral or peer public key",
286
+ ["open_failed" /* OpenFailed */]: "gift wrap failed to decrypt"
287
+ };
288
+ var GiftWrapError = class extends Error {
289
+ constructor(kind, expectedType) {
290
+ super(
291
+ expectedType === void 0 ? GIFTWRAP_ERROR_MESSAGES[kind] : `${GIFTWRAP_ERROR_MESSAGES[kind]}: expected ${expectedType}`
292
+ );
293
+ this.kind = kind;
294
+ this.expectedType = expectedType;
295
+ this.name = "GiftWrapError";
296
+ }
297
+ };
298
+ function concat2(parts) {
299
+ const total = parts.reduce((sum, part) => sum + part.length, 0);
300
+ const out = new Uint8Array(total);
301
+ let offset = 0;
302
+ for (const part of parts) {
303
+ out.set(part, offset);
304
+ offset += part.length;
305
+ }
306
+ return out;
307
+ }
308
+ var UTF8_ENCODER2 = new TextEncoder();
309
+ function hkdfKey(ikm, info) {
310
+ return hkdf(sha256, ikm, void 0, UTF8_ENCODER2.encode(info), 32);
311
+ }
312
+ function encryptWithNonce(key, plaintext, nonce) {
313
+ return concat2([nonce, chacha20poly1305(key, nonce).encrypt(plaintext)]);
314
+ }
315
+ function decrypt(key, nonceAndCiphertext) {
316
+ if (nonceAndCiphertext.length < GIFTWRAP_NONCE_LENGTH) {
317
+ throw new GiftWrapError("truncated" /* Truncated */);
318
+ }
319
+ const nonce = nonceAndCiphertext.subarray(0, GIFTWRAP_NONCE_LENGTH);
320
+ const ciphertext = nonceAndCiphertext.subarray(GIFTWRAP_NONCE_LENGTH);
321
+ if (ciphertext.length < TAG_LENGTH) {
322
+ throw new GiftWrapError("truncated" /* Truncated */);
323
+ }
324
+ try {
325
+ return chacha20poly1305(key, nonce).decrypt(ciphertext);
326
+ } catch {
327
+ throw new GiftWrapError("open_failed" /* OpenFailed */);
328
+ }
329
+ }
330
+ function ecdhXCoordinate(secretKey, publicKey) {
331
+ let compressed;
332
+ try {
333
+ compressed = secp256k1.getSharedSecret(secretKey, publicKey, true);
334
+ } catch {
335
+ throw new GiftWrapError("invalid_key" /* InvalidKey */);
336
+ }
337
+ return compressed.slice(1);
338
+ }
339
+ function localGiftWrapEcdh(secretKey) {
340
+ return {
341
+ ecdh: (ephemeralPublicKey) => ecdhXCoordinate(secretKey, ephemeralPublicKey)
342
+ };
343
+ }
344
+ function giftWrapPublicKey(secretKey) {
345
+ try {
346
+ return secp256k1.getPublicKey(secretKey, false);
347
+ } catch {
348
+ throw new GiftWrapError("invalid_key" /* InvalidKey */);
349
+ }
350
+ }
351
+ function sealRequestWithRandomness(plaintext, receiverPublicKey, ephemeralSecretKey, sharedSecret, nonce) {
352
+ if (sharedSecret.length !== GIFTWRAP_SECRET_LENGTH) {
353
+ throw new GiftWrapError("truncated" /* Truncated */);
354
+ }
355
+ if (nonce.length !== GIFTWRAP_NONCE_LENGTH) {
356
+ throw new GiftWrapError("truncated" /* Truncated */);
357
+ }
358
+ let ephemeralPublicKey;
359
+ try {
360
+ ephemeralPublicKey = secp256k1.getPublicKey(ephemeralSecretKey, false);
361
+ } catch {
362
+ throw new GiftWrapError("invalid_key" /* InvalidKey */);
363
+ }
364
+ const aeadKey = hkdfKey(
365
+ ecdhXCoordinate(ephemeralSecretKey, receiverPublicKey),
366
+ REQUEST_INFO
367
+ );
368
+ const inner = concat2([sharedSecret, plaintext]);
369
+ return concat2([
370
+ Uint8Array.of(GIFTWRAP_TYPE_REQUEST),
371
+ ephemeralPublicKey,
372
+ encryptWithNonce(aeadKey, inner, nonce)
373
+ ]);
374
+ }
375
+ function sealRequest(plaintext, receiverPublicKey) {
376
+ const ephemeralSecretKey = secp256k1.utils.randomSecretKey();
377
+ const sharedSecret = randomBytes(GIFTWRAP_SECRET_LENGTH);
378
+ const nonce = randomBytes(GIFTWRAP_NONCE_LENGTH);
379
+ return {
380
+ wrapped: sealRequestWithRandomness(
381
+ plaintext,
382
+ receiverPublicKey,
383
+ ephemeralSecretKey,
384
+ sharedSecret,
385
+ nonce
386
+ ),
387
+ sharedSecret
388
+ };
389
+ }
390
+ function openRequest(bytes, identity) {
391
+ if (bytes.length === 0) {
392
+ throw new GiftWrapError("truncated" /* Truncated */);
393
+ }
394
+ if (bytes[0] !== GIFTWRAP_TYPE_REQUEST) {
395
+ throw new GiftWrapError(
396
+ "invalid_type" /* InvalidType */,
397
+ GIFTWRAP_TYPE_REQUEST
398
+ );
399
+ }
400
+ if (bytes.length < 1 + GIFTWRAP_PUBLIC_KEY_LENGTH) {
401
+ throw new GiftWrapError("truncated" /* Truncated */);
402
+ }
403
+ const ephemeralPublicKey = bytes.slice(1, 1 + GIFTWRAP_PUBLIC_KEY_LENGTH);
404
+ const ciphertext = bytes.subarray(1 + GIFTWRAP_PUBLIC_KEY_LENGTH);
405
+ const agreement = identity instanceof Uint8Array ? localGiftWrapEcdh(identity) : identity;
406
+ let ecdhSecret;
407
+ try {
408
+ ecdhSecret = agreement.ecdh(ephemeralPublicKey);
409
+ } catch (error) {
410
+ throw error instanceof GiftWrapError ? error : new GiftWrapError("invalid_key" /* InvalidKey */);
411
+ }
412
+ const plaintext = decrypt(hkdfKey(ecdhSecret, REQUEST_INFO), ciphertext);
413
+ if (plaintext.length < GIFTWRAP_SECRET_LENGTH) {
414
+ throw new GiftWrapError("truncated" /* Truncated */);
415
+ }
416
+ return {
417
+ envelopeBytes: plaintext.slice(GIFTWRAP_SECRET_LENGTH),
418
+ sharedSecret: plaintext.slice(0, GIFTWRAP_SECRET_LENGTH)
419
+ };
420
+ }
421
+ function sealResponseWithRandomness(sharedSecret, plaintext, nonce) {
422
+ if (sharedSecret.length !== GIFTWRAP_SECRET_LENGTH) {
423
+ throw new GiftWrapError("truncated" /* Truncated */);
424
+ }
425
+ if (nonce.length !== GIFTWRAP_NONCE_LENGTH) {
426
+ throw new GiftWrapError("truncated" /* Truncated */);
427
+ }
428
+ return concat2([
429
+ Uint8Array.of(GIFTWRAP_TYPE_RESPONSE),
430
+ encryptWithNonce(hkdfKey(sharedSecret, RESPONSE_INFO), plaintext, nonce)
431
+ ]);
432
+ }
433
+ function sealResponse(sharedSecret, plaintext) {
434
+ return sealResponseWithRandomness(
435
+ sharedSecret,
436
+ plaintext,
437
+ randomBytes(GIFTWRAP_NONCE_LENGTH)
438
+ );
439
+ }
440
+ function openResponse(sharedSecret, bytes) {
441
+ if (bytes.length === 0) {
442
+ throw new GiftWrapError("truncated" /* Truncated */);
443
+ }
444
+ if (bytes[0] !== GIFTWRAP_TYPE_RESPONSE) {
445
+ throw new GiftWrapError(
446
+ "invalid_type" /* InvalidType */,
447
+ GIFTWRAP_TYPE_RESPONSE
448
+ );
449
+ }
450
+ if (sharedSecret.length !== GIFTWRAP_SECRET_LENGTH) {
451
+ throw new GiftWrapError("truncated" /* Truncated */);
452
+ }
453
+ return decrypt(hkdfKey(sharedSecret, RESPONSE_INFO), bytes.subarray(1));
454
+ }
455
+ function looksLikeSealedResponse(bytes) {
456
+ return bytes.length > 0 && bytes[0] === GIFTWRAP_TYPE_RESPONSE;
457
+ }
458
+ function deriveFulfillment(sharedSecret) {
459
+ if (sharedSecret.length !== GIFTWRAP_SECRET_LENGTH) {
460
+ throw new GiftWrapError("truncated" /* Truncated */);
461
+ }
462
+ return hkdfKey(sharedSecret, FULFILLMENT_INFO);
463
+ }
464
+ function deriveCondition(fulfillment) {
465
+ return sha256(fulfillment);
466
+ }
467
+
468
+ // src/wire/sealed-exchange.ts
469
+ var SealedResponseError = class extends Error {
470
+ constructor(kind, message, cause) {
471
+ super(message);
472
+ this.kind = kind;
473
+ this.cause = cause;
474
+ this.name = "SealedResponseError";
475
+ }
476
+ };
477
+ function sealExchange(request, connectorPublicKey) {
478
+ const { wrapped, sharedSecret } = sealRequest(
479
+ encodeEnvelopeRequest(request),
480
+ connectorPublicKey
481
+ );
482
+ const fulfillment = deriveFulfillment(sharedSecret);
483
+ return {
484
+ data: wrapped,
485
+ condition: deriveCondition(fulfillment),
486
+ sharedSecret,
487
+ fulfillment
488
+ };
489
+ }
490
+ function readExchangeOutcome(result, data, sharedSecret) {
491
+ if (result.accepted) {
492
+ return { kind: "answered", response: openAnswer(data, sharedSecret) };
493
+ }
494
+ const code = result.code ?? "F00";
495
+ const message = result.message ?? "";
496
+ if (data !== void 0 && looksLikeSealedResponse(data)) {
497
+ try {
498
+ return {
499
+ kind: "destination-refused",
500
+ code,
501
+ message,
502
+ detail: openResponse(sharedSecret, data)
503
+ };
504
+ } catch (error) {
505
+ if (!(error instanceof GiftWrapError)) throw error;
506
+ }
507
+ }
508
+ return { kind: "path-refused", code, message };
509
+ }
510
+ function openAnswer(data, sharedSecret) {
511
+ if (data === void 0 || data.length === 0) {
512
+ throw new SealedResponseError(
513
+ "not-sealed",
514
+ "FULFILL carried no data; a terminated route always seals a response envelope"
515
+ );
516
+ }
517
+ if (!looksLikeSealedResponse(data)) {
518
+ throw new SealedResponseError(
519
+ "not-sealed",
520
+ `FULFILL data is not a sealed response (leading byte 0x${(data[0] ?? 0).toString(16).padStart(2, "0")}, expected 0x02)`
521
+ );
522
+ }
523
+ let opened;
524
+ try {
525
+ opened = openResponse(sharedSecret, data);
526
+ } catch (error) {
527
+ if (!(error instanceof GiftWrapError)) throw error;
528
+ throw new SealedResponseError(
529
+ "unopenable",
530
+ "FULFILL data did not open under this packet's shared secret",
531
+ error
532
+ );
533
+ }
534
+ try {
535
+ return decodeEnvelopeResponse(opened);
536
+ } catch (error) {
537
+ if (!(error instanceof EnvelopeError)) throw error;
538
+ throw new SealedResponseError(
539
+ "malformed-envelope",
540
+ `sealed answer opened but did not decode as a response envelope: ${error.message}`,
541
+ error
542
+ );
543
+ }
544
+ }
545
+ function envelopeHeader(response, name) {
546
+ const wanted = name.toLowerCase();
547
+ for (const [header, value] of response.headers) {
548
+ if (header.toLowerCase() === wanted) return value;
549
+ }
550
+ return void 0;
551
+ }
552
+
553
+ export {
554
+ OerErrorKind,
555
+ OerError,
556
+ encodeVarUint,
557
+ decodeVarUint,
558
+ encodeVarOctetString,
559
+ decodeVarOctetString,
560
+ EnvelopeErrorKind,
561
+ EnvelopeError,
562
+ encodeEnvelopeRequest,
563
+ decodeEnvelopeRequest,
564
+ encodeEnvelopeResponse,
565
+ decodeEnvelopeResponse,
566
+ encodeEnvelope,
567
+ decodeEnvelope,
568
+ GIFTWRAP_NONCE_LENGTH,
569
+ GIFTWRAP_SECRET_LENGTH,
570
+ GIFTWRAP_PUBLIC_KEY_LENGTH,
571
+ GIFTWRAP_TYPE_REQUEST,
572
+ GIFTWRAP_TYPE_RESPONSE,
573
+ GiftWrapErrorKind,
574
+ GiftWrapError,
575
+ localGiftWrapEcdh,
576
+ giftWrapPublicKey,
577
+ sealRequestWithRandomness,
578
+ sealRequest,
579
+ openRequest,
580
+ sealResponseWithRandomness,
581
+ sealResponse,
582
+ openResponse,
583
+ looksLikeSealedResponse,
584
+ deriveFulfillment,
585
+ deriveCondition,
586
+ SealedResponseError,
587
+ sealExchange,
588
+ readExchangeOutcome,
589
+ envelopeHeader
590
+ };
591
+ //# sourceMappingURL=chunk-K72H36Y4.js.map