@toon-protocol/client-mcp 0.1.0 → 0.2.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.
- package/README.md +1 -1
- package/dist/app/index.html +166 -0
- package/dist/{chunk-FSS45ZX3.js → chunk-DLYE6U2Z.js} +1516 -316
- package/dist/chunk-DLYE6U2Z.js.map +1 -0
- package/dist/chunk-KNQ2DKNN.js +861 -0
- package/dist/chunk-KNQ2DKNN.js.map +1 -0
- package/dist/{chunk-3NAWISI5.js → chunk-L6F2B3GX.js} +254 -4
- package/dist/chunk-L6F2B3GX.js.map +1 -0
- package/dist/{chunk-5KFXUT5Q.js → chunk-NP35YO5O.js} +706 -397
- package/dist/chunk-NP35YO5O.js.map +1 -0
- package/dist/daemon.js +3 -3
- package/dist/{ed25519-2QVPINLS.js → ed25519-2LFQXLYS.js} +6 -2
- package/dist/index.d.ts +222 -2
- package/dist/index.js +40 -4
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +39 -5
- package/dist/mcp.js.map +1 -1
- package/package.json +4 -3
- package/dist/chunk-3NAWISI5.js.map +0 -1
- package/dist/chunk-5KFXUT5Q.js.map +0 -1
- package/dist/chunk-FSS45ZX3.js.map +0 -1
- package/dist/chunk-ZQKYZJWT.js +0 -359
- package/dist/chunk-ZQKYZJWT.js.map +0 -1
- /package/dist/{ed25519-2QVPINLS.js.map → ed25519-2LFQXLYS.js.map} +0 -0
|
@@ -3,11 +3,13 @@ import {
|
|
|
3
3
|
hmac
|
|
4
4
|
} from "./chunk-32QD72IL.js";
|
|
5
5
|
import {
|
|
6
|
-
ed25519
|
|
7
|
-
|
|
6
|
+
ed25519,
|
|
7
|
+
hexToBytes,
|
|
8
|
+
sha256
|
|
9
|
+
} from "./chunk-DLYE6U2Z.js";
|
|
8
10
|
import {
|
|
9
11
|
HashMD,
|
|
10
|
-
sha256,
|
|
12
|
+
sha256 as sha2562,
|
|
11
13
|
sha512
|
|
12
14
|
} from "./chunk-LR7W2ISE.js";
|
|
13
15
|
import {
|
|
@@ -20,7 +22,7 @@ import {
|
|
|
20
22
|
concatBytes,
|
|
21
23
|
createHasher,
|
|
22
24
|
createView,
|
|
23
|
-
hexToBytes,
|
|
25
|
+
hexToBytes as hexToBytes2,
|
|
24
26
|
isBytes,
|
|
25
27
|
kdfInputToBytes,
|
|
26
28
|
randomBytes,
|
|
@@ -29,7 +31,7 @@ import {
|
|
|
29
31
|
} from "./chunk-VA7XC4FD.js";
|
|
30
32
|
|
|
31
33
|
// ../client/dist/index.js
|
|
32
|
-
import { generateSecretKey as generateSecretKey3, getPublicKey as getPublicKey22 } from "nostr-tools/pure";
|
|
34
|
+
import { generateSecretKey as generateSecretKey3, getPublicKey as getPublicKey22, finalizeEvent as finalizeEvent11 } from "nostr-tools/pure";
|
|
33
35
|
import { generateSecretKey as generateSecretKey2 } from "nostr-tools/pure";
|
|
34
36
|
|
|
35
37
|
// ../../node_modules/.pnpm/@toon-protocol+core@1.4.2_@toon-protocol+connector@3.13.0_typescript@5.9.3/node_modules/@toon-protocol/core/dist/chunk-5WT7ISKC.js
|
|
@@ -164,380 +166,13 @@ import { SimplePool as SimplePool2 } from "nostr-tools/pool";
|
|
|
164
166
|
import { getPublicKey } from "nostr-tools/pure";
|
|
165
167
|
import WebSocket2 from "ws";
|
|
166
168
|
import { getPublicKey as getPublicKey2, verifyEvent } from "nostr-tools/pure";
|
|
167
|
-
|
|
168
|
-
// ../../node_modules/.pnpm/@noble+hashes@2.2.0/node_modules/@noble/hashes/utils.js
|
|
169
|
-
function isBytes2(a) {
|
|
170
|
-
return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array" && "BYTES_PER_ELEMENT" in a && a.BYTES_PER_ELEMENT === 1;
|
|
171
|
-
}
|
|
172
|
-
function abytes2(value, length, title = "") {
|
|
173
|
-
const bytes = isBytes2(value);
|
|
174
|
-
const len = value?.length;
|
|
175
|
-
const needsLen = length !== void 0;
|
|
176
|
-
if (!bytes || needsLen && len !== length) {
|
|
177
|
-
const prefix = title && `"${title}" `;
|
|
178
|
-
const ofLen = needsLen ? ` of length ${length}` : "";
|
|
179
|
-
const got = bytes ? `length=${len}` : `type=${typeof value}`;
|
|
180
|
-
const message = prefix + "expected Uint8Array" + ofLen + ", got " + got;
|
|
181
|
-
if (!bytes)
|
|
182
|
-
throw new TypeError(message);
|
|
183
|
-
throw new RangeError(message);
|
|
184
|
-
}
|
|
185
|
-
return value;
|
|
186
|
-
}
|
|
187
|
-
function aexists(instance, checkFinished = true) {
|
|
188
|
-
if (instance.destroyed)
|
|
189
|
-
throw new Error("Hash instance has been destroyed");
|
|
190
|
-
if (checkFinished && instance.finished)
|
|
191
|
-
throw new Error("Hash#digest() has already been called");
|
|
192
|
-
}
|
|
193
|
-
function aoutput(out, instance) {
|
|
194
|
-
abytes2(out, void 0, "digestInto() output");
|
|
195
|
-
const min = instance.outputLen;
|
|
196
|
-
if (out.length < min) {
|
|
197
|
-
throw new RangeError('"digestInto() output" expected to be of length >=' + min);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
function clean2(...arrays) {
|
|
201
|
-
for (let i = 0; i < arrays.length; i++) {
|
|
202
|
-
arrays[i].fill(0);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
function createView2(arr) {
|
|
206
|
-
return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
|
|
207
|
-
}
|
|
208
|
-
function rotr(word, shift) {
|
|
209
|
-
return word << 32 - shift | word >>> shift;
|
|
210
|
-
}
|
|
211
|
-
var hasHexBuiltin = /* @__PURE__ */ (() => (
|
|
212
|
-
// @ts-ignore
|
|
213
|
-
typeof Uint8Array.from([]).toHex === "function" && typeof Uint8Array.fromHex === "function"
|
|
214
|
-
))();
|
|
215
|
-
var asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 };
|
|
216
|
-
function asciiToBase16(ch) {
|
|
217
|
-
if (ch >= asciis._0 && ch <= asciis._9)
|
|
218
|
-
return ch - asciis._0;
|
|
219
|
-
if (ch >= asciis.A && ch <= asciis.F)
|
|
220
|
-
return ch - (asciis.A - 10);
|
|
221
|
-
if (ch >= asciis.a && ch <= asciis.f)
|
|
222
|
-
return ch - (asciis.a - 10);
|
|
223
|
-
return;
|
|
224
|
-
}
|
|
225
|
-
function hexToBytes2(hex) {
|
|
226
|
-
if (typeof hex !== "string")
|
|
227
|
-
throw new TypeError("hex string expected, got " + typeof hex);
|
|
228
|
-
if (hasHexBuiltin) {
|
|
229
|
-
try {
|
|
230
|
-
return Uint8Array.fromHex(hex);
|
|
231
|
-
} catch (error) {
|
|
232
|
-
if (error instanceof SyntaxError)
|
|
233
|
-
throw new RangeError(error.message);
|
|
234
|
-
throw error;
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
const hl = hex.length;
|
|
238
|
-
const al = hl / 2;
|
|
239
|
-
if (hl % 2)
|
|
240
|
-
throw new RangeError("hex string expected, got unpadded hex of length " + hl);
|
|
241
|
-
const array = new Uint8Array(al);
|
|
242
|
-
for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
|
|
243
|
-
const n1 = asciiToBase16(hex.charCodeAt(hi));
|
|
244
|
-
const n2 = asciiToBase16(hex.charCodeAt(hi + 1));
|
|
245
|
-
if (n1 === void 0 || n2 === void 0) {
|
|
246
|
-
const char = hex[hi] + hex[hi + 1];
|
|
247
|
-
throw new RangeError('hex string expected, got non-hex character "' + char + '" at index ' + hi);
|
|
248
|
-
}
|
|
249
|
-
array[ai] = n1 * 16 + n2;
|
|
250
|
-
}
|
|
251
|
-
return array;
|
|
252
|
-
}
|
|
253
|
-
function createHasher2(hashCons, info = {}) {
|
|
254
|
-
const hashC = (msg, opts) => hashCons(opts).update(msg).digest();
|
|
255
|
-
const tmp = hashCons(void 0);
|
|
256
|
-
hashC.outputLen = tmp.outputLen;
|
|
257
|
-
hashC.blockLen = tmp.blockLen;
|
|
258
|
-
hashC.canXOF = tmp.canXOF;
|
|
259
|
-
hashC.create = (opts) => hashCons(opts);
|
|
260
|
-
Object.assign(hashC, info);
|
|
261
|
-
return Object.freeze(hashC);
|
|
262
|
-
}
|
|
263
|
-
var oidNist = (suffix) => ({
|
|
264
|
-
// Current NIST hashAlgs suffixes used here fit in one DER subidentifier octet.
|
|
265
|
-
// Larger suffix values would need base-128 OID encoding and a different length byte.
|
|
266
|
-
oid: Uint8Array.from([6, 9, 96, 134, 72, 1, 101, 3, 4, 2, suffix])
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
// ../../node_modules/.pnpm/@noble+hashes@2.2.0/node_modules/@noble/hashes/_md.js
|
|
270
|
-
function Chi(a, b, c) {
|
|
271
|
-
return a & b ^ ~a & c;
|
|
272
|
-
}
|
|
273
|
-
function Maj(a, b, c) {
|
|
274
|
-
return a & b ^ a & c ^ b & c;
|
|
275
|
-
}
|
|
276
|
-
var HashMD2 = class {
|
|
277
|
-
blockLen;
|
|
278
|
-
outputLen;
|
|
279
|
-
canXOF = false;
|
|
280
|
-
padOffset;
|
|
281
|
-
isLE;
|
|
282
|
-
// For partial updates less than block size
|
|
283
|
-
buffer;
|
|
284
|
-
view;
|
|
285
|
-
finished = false;
|
|
286
|
-
length = 0;
|
|
287
|
-
pos = 0;
|
|
288
|
-
destroyed = false;
|
|
289
|
-
constructor(blockLen, outputLen, padOffset, isLE) {
|
|
290
|
-
this.blockLen = blockLen;
|
|
291
|
-
this.outputLen = outputLen;
|
|
292
|
-
this.padOffset = padOffset;
|
|
293
|
-
this.isLE = isLE;
|
|
294
|
-
this.buffer = new Uint8Array(blockLen);
|
|
295
|
-
this.view = createView2(this.buffer);
|
|
296
|
-
}
|
|
297
|
-
update(data) {
|
|
298
|
-
aexists(this);
|
|
299
|
-
abytes2(data);
|
|
300
|
-
const { view, buffer, blockLen } = this;
|
|
301
|
-
const len = data.length;
|
|
302
|
-
for (let pos = 0; pos < len; ) {
|
|
303
|
-
const take = Math.min(blockLen - this.pos, len - pos);
|
|
304
|
-
if (take === blockLen) {
|
|
305
|
-
const dataView = createView2(data);
|
|
306
|
-
for (; blockLen <= len - pos; pos += blockLen)
|
|
307
|
-
this.process(dataView, pos);
|
|
308
|
-
continue;
|
|
309
|
-
}
|
|
310
|
-
buffer.set(data.subarray(pos, pos + take), this.pos);
|
|
311
|
-
this.pos += take;
|
|
312
|
-
pos += take;
|
|
313
|
-
if (this.pos === blockLen) {
|
|
314
|
-
this.process(view, 0);
|
|
315
|
-
this.pos = 0;
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
this.length += data.length;
|
|
319
|
-
this.roundClean();
|
|
320
|
-
return this;
|
|
321
|
-
}
|
|
322
|
-
digestInto(out) {
|
|
323
|
-
aexists(this);
|
|
324
|
-
aoutput(out, this);
|
|
325
|
-
this.finished = true;
|
|
326
|
-
const { buffer, view, blockLen, isLE } = this;
|
|
327
|
-
let { pos } = this;
|
|
328
|
-
buffer[pos++] = 128;
|
|
329
|
-
clean2(this.buffer.subarray(pos));
|
|
330
|
-
if (this.padOffset > blockLen - pos) {
|
|
331
|
-
this.process(view, 0);
|
|
332
|
-
pos = 0;
|
|
333
|
-
}
|
|
334
|
-
for (let i = pos; i < blockLen; i++)
|
|
335
|
-
buffer[i] = 0;
|
|
336
|
-
view.setBigUint64(blockLen - 8, BigInt(this.length * 8), isLE);
|
|
337
|
-
this.process(view, 0);
|
|
338
|
-
const oview = createView2(out);
|
|
339
|
-
const len = this.outputLen;
|
|
340
|
-
if (len % 4)
|
|
341
|
-
throw new Error("_sha2: outputLen must be aligned to 32bit");
|
|
342
|
-
const outLen = len / 4;
|
|
343
|
-
const state = this.get();
|
|
344
|
-
if (outLen > state.length)
|
|
345
|
-
throw new Error("_sha2: outputLen bigger than state");
|
|
346
|
-
for (let i = 0; i < outLen; i++)
|
|
347
|
-
oview.setUint32(4 * i, state[i], isLE);
|
|
348
|
-
}
|
|
349
|
-
digest() {
|
|
350
|
-
const { buffer, outputLen } = this;
|
|
351
|
-
this.digestInto(buffer);
|
|
352
|
-
const res = buffer.slice(0, outputLen);
|
|
353
|
-
this.destroy();
|
|
354
|
-
return res;
|
|
355
|
-
}
|
|
356
|
-
_cloneInto(to) {
|
|
357
|
-
to ||= new this.constructor();
|
|
358
|
-
to.set(...this.get());
|
|
359
|
-
const { blockLen, buffer, length, finished, destroyed, pos } = this;
|
|
360
|
-
to.destroyed = destroyed;
|
|
361
|
-
to.finished = finished;
|
|
362
|
-
to.length = length;
|
|
363
|
-
to.pos = pos;
|
|
364
|
-
if (length % blockLen)
|
|
365
|
-
to.buffer.set(buffer);
|
|
366
|
-
return to;
|
|
367
|
-
}
|
|
368
|
-
clone() {
|
|
369
|
-
return this._cloneInto();
|
|
370
|
-
}
|
|
371
|
-
};
|
|
372
|
-
var SHA256_IV = /* @__PURE__ */ Uint32Array.from([
|
|
373
|
-
1779033703,
|
|
374
|
-
3144134277,
|
|
375
|
-
1013904242,
|
|
376
|
-
2773480762,
|
|
377
|
-
1359893119,
|
|
378
|
-
2600822924,
|
|
379
|
-
528734635,
|
|
380
|
-
1541459225
|
|
381
|
-
]);
|
|
382
|
-
|
|
383
|
-
// ../../node_modules/.pnpm/@noble+hashes@2.2.0/node_modules/@noble/hashes/sha2.js
|
|
384
|
-
var SHA256_K = /* @__PURE__ */ Uint32Array.from([
|
|
385
|
-
1116352408,
|
|
386
|
-
1899447441,
|
|
387
|
-
3049323471,
|
|
388
|
-
3921009573,
|
|
389
|
-
961987163,
|
|
390
|
-
1508970993,
|
|
391
|
-
2453635748,
|
|
392
|
-
2870763221,
|
|
393
|
-
3624381080,
|
|
394
|
-
310598401,
|
|
395
|
-
607225278,
|
|
396
|
-
1426881987,
|
|
397
|
-
1925078388,
|
|
398
|
-
2162078206,
|
|
399
|
-
2614888103,
|
|
400
|
-
3248222580,
|
|
401
|
-
3835390401,
|
|
402
|
-
4022224774,
|
|
403
|
-
264347078,
|
|
404
|
-
604807628,
|
|
405
|
-
770255983,
|
|
406
|
-
1249150122,
|
|
407
|
-
1555081692,
|
|
408
|
-
1996064986,
|
|
409
|
-
2554220882,
|
|
410
|
-
2821834349,
|
|
411
|
-
2952996808,
|
|
412
|
-
3210313671,
|
|
413
|
-
3336571891,
|
|
414
|
-
3584528711,
|
|
415
|
-
113926993,
|
|
416
|
-
338241895,
|
|
417
|
-
666307205,
|
|
418
|
-
773529912,
|
|
419
|
-
1294757372,
|
|
420
|
-
1396182291,
|
|
421
|
-
1695183700,
|
|
422
|
-
1986661051,
|
|
423
|
-
2177026350,
|
|
424
|
-
2456956037,
|
|
425
|
-
2730485921,
|
|
426
|
-
2820302411,
|
|
427
|
-
3259730800,
|
|
428
|
-
3345764771,
|
|
429
|
-
3516065817,
|
|
430
|
-
3600352804,
|
|
431
|
-
4094571909,
|
|
432
|
-
275423344,
|
|
433
|
-
430227734,
|
|
434
|
-
506948616,
|
|
435
|
-
659060556,
|
|
436
|
-
883997877,
|
|
437
|
-
958139571,
|
|
438
|
-
1322822218,
|
|
439
|
-
1537002063,
|
|
440
|
-
1747873779,
|
|
441
|
-
1955562222,
|
|
442
|
-
2024104815,
|
|
443
|
-
2227730452,
|
|
444
|
-
2361852424,
|
|
445
|
-
2428436474,
|
|
446
|
-
2756734187,
|
|
447
|
-
3204031479,
|
|
448
|
-
3329325298
|
|
449
|
-
]);
|
|
450
|
-
var SHA256_W = /* @__PURE__ */ new Uint32Array(64);
|
|
451
|
-
var SHA2_32B = class extends HashMD2 {
|
|
452
|
-
constructor(outputLen) {
|
|
453
|
-
super(64, outputLen, 8, false);
|
|
454
|
-
}
|
|
455
|
-
get() {
|
|
456
|
-
const { A, B, C, D, E, F, G, H } = this;
|
|
457
|
-
return [A, B, C, D, E, F, G, H];
|
|
458
|
-
}
|
|
459
|
-
// prettier-ignore
|
|
460
|
-
set(A, B, C, D, E, F, G, H) {
|
|
461
|
-
this.A = A | 0;
|
|
462
|
-
this.B = B | 0;
|
|
463
|
-
this.C = C | 0;
|
|
464
|
-
this.D = D | 0;
|
|
465
|
-
this.E = E | 0;
|
|
466
|
-
this.F = F | 0;
|
|
467
|
-
this.G = G | 0;
|
|
468
|
-
this.H = H | 0;
|
|
469
|
-
}
|
|
470
|
-
process(view, offset) {
|
|
471
|
-
for (let i = 0; i < 16; i++, offset += 4)
|
|
472
|
-
SHA256_W[i] = view.getUint32(offset, false);
|
|
473
|
-
for (let i = 16; i < 64; i++) {
|
|
474
|
-
const W15 = SHA256_W[i - 15];
|
|
475
|
-
const W2 = SHA256_W[i - 2];
|
|
476
|
-
const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ W15 >>> 3;
|
|
477
|
-
const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ W2 >>> 10;
|
|
478
|
-
SHA256_W[i] = s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16] | 0;
|
|
479
|
-
}
|
|
480
|
-
let { A, B, C, D, E, F, G, H } = this;
|
|
481
|
-
for (let i = 0; i < 64; i++) {
|
|
482
|
-
const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);
|
|
483
|
-
const T1 = H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i] | 0;
|
|
484
|
-
const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);
|
|
485
|
-
const T2 = sigma0 + Maj(A, B, C) | 0;
|
|
486
|
-
H = G;
|
|
487
|
-
G = F;
|
|
488
|
-
F = E;
|
|
489
|
-
E = D + T1 | 0;
|
|
490
|
-
D = C;
|
|
491
|
-
C = B;
|
|
492
|
-
B = A;
|
|
493
|
-
A = T1 + T2 | 0;
|
|
494
|
-
}
|
|
495
|
-
A = A + this.A | 0;
|
|
496
|
-
B = B + this.B | 0;
|
|
497
|
-
C = C + this.C | 0;
|
|
498
|
-
D = D + this.D | 0;
|
|
499
|
-
E = E + this.E | 0;
|
|
500
|
-
F = F + this.F | 0;
|
|
501
|
-
G = G + this.G | 0;
|
|
502
|
-
H = H + this.H | 0;
|
|
503
|
-
this.set(A, B, C, D, E, F, G, H);
|
|
504
|
-
}
|
|
505
|
-
roundClean() {
|
|
506
|
-
clean2(SHA256_W);
|
|
507
|
-
}
|
|
508
|
-
destroy() {
|
|
509
|
-
this.destroyed = true;
|
|
510
|
-
this.set(0, 0, 0, 0, 0, 0, 0, 0);
|
|
511
|
-
clean2(this.buffer);
|
|
512
|
-
}
|
|
513
|
-
};
|
|
514
|
-
var _SHA256 = class extends SHA2_32B {
|
|
515
|
-
// We cannot use array here since array allows indexing by variable
|
|
516
|
-
// which means optimizer/compiler cannot use registers.
|
|
517
|
-
A = SHA256_IV[0] | 0;
|
|
518
|
-
B = SHA256_IV[1] | 0;
|
|
519
|
-
C = SHA256_IV[2] | 0;
|
|
520
|
-
D = SHA256_IV[3] | 0;
|
|
521
|
-
E = SHA256_IV[4] | 0;
|
|
522
|
-
F = SHA256_IV[5] | 0;
|
|
523
|
-
G = SHA256_IV[6] | 0;
|
|
524
|
-
H = SHA256_IV[7] | 0;
|
|
525
|
-
constructor() {
|
|
526
|
-
super(32);
|
|
527
|
-
}
|
|
528
|
-
};
|
|
529
|
-
var sha2562 = /* @__PURE__ */ createHasher2(
|
|
530
|
-
() => new _SHA256(),
|
|
531
|
-
/* @__PURE__ */ oidNist(1)
|
|
532
|
-
);
|
|
533
|
-
|
|
534
|
-
// ../../node_modules/.pnpm/@toon-protocol+core@1.4.2_@toon-protocol+connector@3.13.0_typescript@5.9.3/node_modules/@toon-protocol/core/dist/index.js
|
|
535
169
|
import { SimplePool as SimplePool3 } from "nostr-tools/pool";
|
|
536
170
|
import { getPublicKey as getPublicKey3 } from "nostr-tools/pure";
|
|
537
171
|
import WebSocket22 from "ws";
|
|
538
172
|
import { getPublicKey as getPublicKey4 } from "nostr-tools/pure";
|
|
539
173
|
import { getPublicKey as getPublicKey5 } from "nostr-tools/pure";
|
|
540
174
|
var ILP_PEER_INFO_KIND = 10032;
|
|
175
|
+
var BLOB_STORAGE_REQUEST_KIND = 5094;
|
|
541
176
|
var ILP_SEGMENT_PATTERN = /^[a-z0-9-]+$/;
|
|
542
177
|
var MAX_ILP_ADDRESS_LENGTH = 1023;
|
|
543
178
|
function isValidIlpAddressStructure(address) {
|
|
@@ -920,6 +555,40 @@ function buildIlpPeerInfoEvent(info, secretKey, options = {}) {
|
|
|
920
555
|
secretKey
|
|
921
556
|
);
|
|
922
557
|
}
|
|
558
|
+
function buildBlobStorageRequest(params, secretKey) {
|
|
559
|
+
if (!params.blobData || params.blobData.length === 0) {
|
|
560
|
+
throw new ToonError(
|
|
561
|
+
"Blob storage request blobData is required and must not be empty",
|
|
562
|
+
"DVM_MISSING_INPUT"
|
|
563
|
+
);
|
|
564
|
+
}
|
|
565
|
+
if (typeof params.bid !== "string" || params.bid === "") {
|
|
566
|
+
throw new ToonError(
|
|
567
|
+
"Blob storage request bid must be a non-empty string (USDC micro-units)",
|
|
568
|
+
"DVM_INVALID_BID"
|
|
569
|
+
);
|
|
570
|
+
}
|
|
571
|
+
const contentType = params.contentType ?? "application/octet-stream";
|
|
572
|
+
const base64Blob = params.blobData.toString("base64");
|
|
573
|
+
const tags = [];
|
|
574
|
+
tags.push(["i", base64Blob, "blob"]);
|
|
575
|
+
tags.push(["bid", params.bid, "usdc"]);
|
|
576
|
+
tags.push(["output", contentType]);
|
|
577
|
+
if (params.params !== void 0) {
|
|
578
|
+
for (const p of params.params) {
|
|
579
|
+
tags.push(["param", p.key, p.value]);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
return finalizeEvent9(
|
|
583
|
+
{
|
|
584
|
+
kind: BLOB_STORAGE_REQUEST_KIND,
|
|
585
|
+
content: "",
|
|
586
|
+
tags,
|
|
587
|
+
created_at: Math.floor(Date.now() / 1e3)
|
|
588
|
+
},
|
|
589
|
+
secretKey
|
|
590
|
+
);
|
|
591
|
+
}
|
|
923
592
|
var genesis_peers_default = [];
|
|
924
593
|
var PUBKEY_REGEX3 = /^[0-9a-f]{64}$/;
|
|
925
594
|
var ILP_ADDRESS_REGEX = /^g\.[a-zA-Z0-9.-]+$/;
|
|
@@ -1132,11 +801,11 @@ function resolveTokenForChain(chain2, requesterPreferredTokens, responderPreferr
|
|
|
1132
801
|
return void 0;
|
|
1133
802
|
}
|
|
1134
803
|
function hexToBytes3(hex) {
|
|
1135
|
-
const
|
|
1136
|
-
if (
|
|
804
|
+
const clean2 = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
805
|
+
if (clean2.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(clean2)) {
|
|
1137
806
|
throw new Error(`Invalid hex string: ${hex}`);
|
|
1138
807
|
}
|
|
1139
|
-
return
|
|
808
|
+
return hexToBytes(clean2);
|
|
1140
809
|
}
|
|
1141
810
|
function concatBytes2(...parts) {
|
|
1142
811
|
let len = 0;
|
|
@@ -1197,7 +866,7 @@ function hexToMinaBase58PrivateKey(privateKey) {
|
|
|
1197
866
|
Uint8Array.from([MINA_PRIVATE_KEY_VERSION, 1]),
|
|
1198
867
|
leScalar
|
|
1199
868
|
);
|
|
1200
|
-
const checksum2 =
|
|
869
|
+
const checksum2 = sha256(sha256(payload)).slice(0, 4);
|
|
1201
870
|
return base58Encode(concatBytes2(payload, checksum2));
|
|
1202
871
|
}
|
|
1203
872
|
var BootstrapError = class extends ToonError {
|
|
@@ -2343,7 +2012,7 @@ function pbkdf2(hash, password, salt, opts) {
|
|
|
2343
2012
|
}
|
|
2344
2013
|
|
|
2345
2014
|
// ../../node_modules/.pnpm/@scure+base@1.2.6/node_modules/@scure/base/lib/esm/index.js
|
|
2346
|
-
function
|
|
2015
|
+
function isBytes2(a) {
|
|
2347
2016
|
return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
|
|
2348
2017
|
}
|
|
2349
2018
|
function isArrayOf(isString, arr) {
|
|
@@ -2558,7 +2227,7 @@ function radix(num) {
|
|
|
2558
2227
|
const _256 = 2 ** 8;
|
|
2559
2228
|
return {
|
|
2560
2229
|
encode: (bytes) => {
|
|
2561
|
-
if (!
|
|
2230
|
+
if (!isBytes2(bytes))
|
|
2562
2231
|
throw new Error("radix.encode input should be Uint8Array");
|
|
2563
2232
|
return convertRadix(Array.from(bytes), _256, num);
|
|
2564
2233
|
},
|
|
@@ -2577,7 +2246,7 @@ function radix2(bits, revPadding = false) {
|
|
|
2577
2246
|
throw new Error("radix2: carry overflow");
|
|
2578
2247
|
return {
|
|
2579
2248
|
encode: (bytes) => {
|
|
2580
|
-
if (!
|
|
2249
|
+
if (!isBytes2(bytes))
|
|
2581
2250
|
throw new Error("radix2.encode input should be Uint8Array");
|
|
2582
2251
|
return convertRadix2(Array.from(bytes), 8, bits, !revPadding);
|
|
2583
2252
|
},
|
|
@@ -2592,7 +2261,7 @@ function checksum(len, fn) {
|
|
|
2592
2261
|
afn(fn);
|
|
2593
2262
|
return {
|
|
2594
2263
|
encode(data) {
|
|
2595
|
-
if (!
|
|
2264
|
+
if (!isBytes2(data))
|
|
2596
2265
|
throw new Error("checksum.encode: input should be Uint8Array");
|
|
2597
2266
|
const sum = fn(data).slice(0, len);
|
|
2598
2267
|
const res = new Uint8Array(data.length + len);
|
|
@@ -2601,7 +2270,7 @@ function checksum(len, fn) {
|
|
|
2601
2270
|
return res;
|
|
2602
2271
|
},
|
|
2603
2272
|
decode(data) {
|
|
2604
|
-
if (!
|
|
2273
|
+
if (!isBytes2(data))
|
|
2605
2274
|
throw new Error("checksum.decode: input should be Uint8Array");
|
|
2606
2275
|
const payload = data.slice(0, -len);
|
|
2607
2276
|
const oldChecksum = data.slice(-len);
|
|
@@ -2653,7 +2322,7 @@ function generateMnemonic(wordlist2, strength = 128) {
|
|
|
2653
2322
|
}
|
|
2654
2323
|
var calcChecksum = (entropy) => {
|
|
2655
2324
|
const bitsLeft = 8 - entropy.length / 4;
|
|
2656
|
-
return new Uint8Array([
|
|
2325
|
+
return new Uint8Array([sha2562(entropy)[0] >> bitsLeft << bitsLeft]);
|
|
2657
2326
|
};
|
|
2658
2327
|
function getCoder(wordlist2) {
|
|
2659
2328
|
if (!Array.isArray(wordlist2) || wordlist2.length !== 2048 || typeof wordlist2[0] !== "string")
|
|
@@ -4777,7 +4446,7 @@ function bytesToNumberLE(bytes) {
|
|
|
4777
4446
|
return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse()));
|
|
4778
4447
|
}
|
|
4779
4448
|
function numberToBytesBE(n, len) {
|
|
4780
|
-
return
|
|
4449
|
+
return hexToBytes2(n.toString(16).padStart(len * 2, "0"));
|
|
4781
4450
|
}
|
|
4782
4451
|
function numberToBytesLE(n, len) {
|
|
4783
4452
|
return numberToBytesBE(n, len).reverse();
|
|
@@ -4786,7 +4455,7 @@ function ensureBytes(title, hex, expectedLength) {
|
|
|
4786
4455
|
let res;
|
|
4787
4456
|
if (typeof hex === "string") {
|
|
4788
4457
|
try {
|
|
4789
|
-
res =
|
|
4458
|
+
res = hexToBytes2(hex);
|
|
4790
4459
|
} catch (e) {
|
|
4791
4460
|
throw new Error(title + " must be hex string or Uint8Array, cause: " + e);
|
|
4792
4461
|
}
|
|
@@ -6266,7 +5935,7 @@ function ecdsa(Point2, hash, ecdsaOpts = {}) {
|
|
|
6266
5935
|
return new Signature(Fn.fromBytes(r), Fn.fromBytes(s), recid);
|
|
6267
5936
|
}
|
|
6268
5937
|
static fromHex(hex, format) {
|
|
6269
|
-
return this.fromBytes(
|
|
5938
|
+
return this.fromBytes(hexToBytes2(hex), format);
|
|
6270
5939
|
}
|
|
6271
5940
|
addRecoveryBit(recovery) {
|
|
6272
5941
|
return new Signature(this.r, this.s, recovery);
|
|
@@ -6301,7 +5970,7 @@ function ecdsa(Point2, hash, ecdsaOpts = {}) {
|
|
|
6301
5970
|
toBytes(format = defaultSigOpts_format) {
|
|
6302
5971
|
validateSigFormat(format);
|
|
6303
5972
|
if (format === "der")
|
|
6304
|
-
return
|
|
5973
|
+
return hexToBytes2(DER.hexFromSig(this));
|
|
6305
5974
|
const r = Fn.toBytes(this.r);
|
|
6306
5975
|
const s = Fn.toBytes(this.s);
|
|
6307
5976
|
if (format === "recovered") {
|
|
@@ -6575,7 +6244,7 @@ function sqrtMod(y) {
|
|
|
6575
6244
|
return root;
|
|
6576
6245
|
}
|
|
6577
6246
|
var Fpk1 = Field(secp256k1_CURVE.p, { sqrt: sqrtMod });
|
|
6578
|
-
var secp256k1 = createCurve({ ...secp256k1_CURVE, Fp: Fpk1, lowS: true, endo: secp256k1_ENDO },
|
|
6247
|
+
var secp256k1 = createCurve({ ...secp256k1_CURVE, Fp: Fpk1, lowS: true, endo: secp256k1_ENDO }, sha2562);
|
|
6579
6248
|
|
|
6580
6249
|
// ../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/esm/legacy.js
|
|
6581
6250
|
var Rho160 = /* @__PURE__ */ Uint8Array.from([
|
|
@@ -6697,7 +6366,7 @@ var ripemd160 = /* @__PURE__ */ createHasher(() => new RIPEMD160());
|
|
|
6697
6366
|
|
|
6698
6367
|
// ../../node_modules/.pnpm/@scure+bip32@1.7.0/node_modules/@scure/bip32/lib/esm/index.js
|
|
6699
6368
|
var Point = secp256k1.ProjectivePoint;
|
|
6700
|
-
var base58check = createBase58check(
|
|
6369
|
+
var base58check = createBase58check(sha2562);
|
|
6701
6370
|
function bytesToNumber(bytes) {
|
|
6702
6371
|
abytes(bytes);
|
|
6703
6372
|
const h = bytes.length === 0 ? "0" : bytesToHex(bytes);
|
|
@@ -6706,12 +6375,12 @@ function bytesToNumber(bytes) {
|
|
|
6706
6375
|
function numberToBytes(num) {
|
|
6707
6376
|
if (typeof num !== "bigint")
|
|
6708
6377
|
throw new Error("bigint expected");
|
|
6709
|
-
return
|
|
6378
|
+
return hexToBytes2(num.toString(16).padStart(64, "0"));
|
|
6710
6379
|
}
|
|
6711
6380
|
var MASTER_SECRET = utf8ToBytes("Bitcoin seed");
|
|
6712
6381
|
var BITCOIN_VERSIONS = { private: 76066276, public: 76067358 };
|
|
6713
6382
|
var HARDENED_OFFSET = 2147483648;
|
|
6714
|
-
var hash160 = (data) => ripemd160(
|
|
6383
|
+
var hash160 = (data) => ripemd160(sha2562(data));
|
|
6715
6384
|
var fromU32 = (data) => createView(data).getUint32(0, false);
|
|
6716
6385
|
var toU32 = (n) => {
|
|
6717
6386
|
if (!Number.isSafeInteger(n) || n < 0 || n > 2 ** 32 - 1) {
|
|
@@ -6952,7 +6621,7 @@ import {
|
|
|
6952
6621
|
import { privateKeyToAccount as privateKeyToAccount2 } from "viem/accounts";
|
|
6953
6622
|
import { toHex as toHex3 } from "viem";
|
|
6954
6623
|
import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
6955
|
-
import { finalizeEvent as
|
|
6624
|
+
import { finalizeEvent as finalizeEvent22 } from "nostr-tools/pure";
|
|
6956
6625
|
import { nip19 } from "nostr-tools";
|
|
6957
6626
|
import { getPublicKey as getPublicKey32 } from "nostr-tools/pure";
|
|
6958
6627
|
import {
|
|
@@ -6968,6 +6637,7 @@ var ToonClientError = class extends Error {
|
|
|
6968
6637
|
this.code = code;
|
|
6969
6638
|
this.name = "ToonClientError";
|
|
6970
6639
|
}
|
|
6640
|
+
code;
|
|
6971
6641
|
};
|
|
6972
6642
|
var NetworkError = class extends ToonClientError {
|
|
6973
6643
|
constructor(message, cause) {
|
|
@@ -7021,7 +6691,7 @@ function deriveEvmIdentity(secretKey) {
|
|
|
7021
6691
|
async function deriveSolanaKey(seed, accountIndex = 0) {
|
|
7022
6692
|
const { hmac: hmac2 } = await import("./hmac-26UC6YKX.js");
|
|
7023
6693
|
const { sha512: sha5122 } = await import("./sha512-WYC446ZM.js");
|
|
7024
|
-
const { ed25519: ed255194 } = await import("./ed25519-
|
|
6694
|
+
const { ed25519: ed255194 } = await import("./ed25519-2LFQXLYS.js");
|
|
7025
6695
|
const encoder = new TextEncoder();
|
|
7026
6696
|
let I = hmac2(sha5122, encoder.encode("ed25519 seed"), seed);
|
|
7027
6697
|
let key = I.slice(0, 32);
|
|
@@ -7369,6 +7039,9 @@ function toHex2(bytes) {
|
|
|
7369
7039
|
function encodeUtf8(str) {
|
|
7370
7040
|
return new TextEncoder().encode(str);
|
|
7371
7041
|
}
|
|
7042
|
+
function decodeUtf8(bytes) {
|
|
7043
|
+
return new TextDecoder().decode(bytes);
|
|
7044
|
+
}
|
|
7372
7045
|
function isBase64(str) {
|
|
7373
7046
|
return /^[A-Za-z0-9+/]*={0,2}$/.test(str);
|
|
7374
7047
|
}
|
|
@@ -8232,6 +7905,227 @@ var BtpRuntimeClient = class {
|
|
|
8232
7905
|
};
|
|
8233
7906
|
}
|
|
8234
7907
|
};
|
|
7908
|
+
var ILP_CLAIM_HEADER = "ILP-Payment-Channel-Claim";
|
|
7909
|
+
var ILP_PEER_ID_HEADER = "ILP-Peer-Id";
|
|
7910
|
+
var HttpIlpClient = class {
|
|
7911
|
+
httpEndpoint;
|
|
7912
|
+
peerId;
|
|
7913
|
+
authToken;
|
|
7914
|
+
timeout;
|
|
7915
|
+
retryConfig;
|
|
7916
|
+
httpClient;
|
|
7917
|
+
createWebSocket;
|
|
7918
|
+
constructor(config) {
|
|
7919
|
+
this.httpEndpoint = config.httpEndpoint;
|
|
7920
|
+
this.peerId = config.peerId;
|
|
7921
|
+
this.authToken = config.authToken;
|
|
7922
|
+
this.timeout = config.timeout ?? 3e4;
|
|
7923
|
+
this.retryConfig = {
|
|
7924
|
+
maxRetries: config.maxRetries ?? 3,
|
|
7925
|
+
retryDelay: config.retryDelay ?? 1e3
|
|
7926
|
+
};
|
|
7927
|
+
this.httpClient = config.httpClient ?? fetch;
|
|
7928
|
+
this.createWebSocket = config.createWebSocket;
|
|
7929
|
+
}
|
|
7930
|
+
/**
|
|
7931
|
+
* Send an ILP PREPARE via `POST /ilp` WITHOUT a claim. The connector accepts
|
|
7932
|
+
* this only on free/zero-amount routes; paid writes must use
|
|
7933
|
+
* {@link sendIlpPacketWithClaim}. Satisfies the IlpClient interface.
|
|
7934
|
+
*/
|
|
7935
|
+
async sendIlpPacket(params) {
|
|
7936
|
+
return withRetry(() => this.postPrepare(params), {
|
|
7937
|
+
maxRetries: this.retryConfig.maxRetries,
|
|
7938
|
+
retryDelay: this.retryConfig.retryDelay,
|
|
7939
|
+
exponentialBackoff: true,
|
|
7940
|
+
shouldRetry: (error) => error instanceof NetworkError
|
|
7941
|
+
});
|
|
7942
|
+
}
|
|
7943
|
+
/**
|
|
7944
|
+
* Send an ILP PREPARE via `POST /ilp` with the payment-channel claim attached
|
|
7945
|
+
* as the `ILP-Payment-Channel-Claim` header. `claim` is the SAME JSON object
|
|
7946
|
+
* the BTP path attaches as the `payment-channel-claim` protocolData entry —
|
|
7947
|
+
* we base64(JSON.stringify(claim)) it, byte-for-byte identical to BTP.
|
|
7948
|
+
*/
|
|
7949
|
+
async sendIlpPacketWithClaim(params, claim) {
|
|
7950
|
+
return withRetry(() => this.postPrepare(params, claim), {
|
|
7951
|
+
maxRetries: this.retryConfig.maxRetries,
|
|
7952
|
+
retryDelay: this.retryConfig.retryDelay,
|
|
7953
|
+
exponentialBackoff: true,
|
|
7954
|
+
shouldRetry: (error) => error instanceof NetworkError
|
|
7955
|
+
});
|
|
7956
|
+
}
|
|
7957
|
+
/**
|
|
7958
|
+
* Upgrade to a duplex BTP session over the SAME endpoint.
|
|
7959
|
+
*
|
|
7960
|
+
* Derives the `ws(s)://` URL from `httpEndpoint`, opens a WebSocket with
|
|
7961
|
+
* `Sec-WebSocket-Protocol: btp` and the same `ILP-Peer-Id` + `Authorization`
|
|
7962
|
+
* headers, and returns a connected {@link BtpRuntimeClient}. When auth headers
|
|
7963
|
+
* are present the connector pre-authenticates the session (no in-band auth
|
|
7964
|
+
* frame); without them the BtpRuntimeClient falls back to the normal BTP
|
|
7965
|
+
* auth-frame flow.
|
|
7966
|
+
*
|
|
7967
|
+
* NOTE: passing per-connection headers + a subprotocol to a WebSocket is
|
|
7968
|
+
* Node-only (the `ws` package). Browsers cannot set arbitrary request headers
|
|
7969
|
+
* on a WebSocket handshake, so a browser consumer must use the gateway
|
|
7970
|
+
* transport or BTP-with-auth-frame instead.
|
|
7971
|
+
*/
|
|
7972
|
+
async upgradeToBtp() {
|
|
7973
|
+
const btpUrl = httpEndpointToBtpUrl(this.httpEndpoint);
|
|
7974
|
+
const createWebSocket = this.createWebSocket ?? await makeBtpWebSocketFactory(this.authHeaders());
|
|
7975
|
+
const client = new BtpRuntimeClient({
|
|
7976
|
+
btpUrl,
|
|
7977
|
+
// BtpRuntimeClient sends an auth frame using these; when the connector
|
|
7978
|
+
// pre-authenticated via Upgrade headers it accepts the (redundant) frame.
|
|
7979
|
+
peerId: this.peerId ?? "client",
|
|
7980
|
+
authToken: this.authToken ?? "",
|
|
7981
|
+
createWebSocket
|
|
7982
|
+
});
|
|
7983
|
+
await client.connect();
|
|
7984
|
+
return client;
|
|
7985
|
+
}
|
|
7986
|
+
// ─── Private ──────────────────────────────────────────────────────────────
|
|
7987
|
+
authHeaders() {
|
|
7988
|
+
const headers = {};
|
|
7989
|
+
if (this.peerId) headers[ILP_PEER_ID_HEADER] = this.peerId;
|
|
7990
|
+
if (this.authToken) headers["Authorization"] = `Bearer ${this.authToken}`;
|
|
7991
|
+
return headers;
|
|
7992
|
+
}
|
|
7993
|
+
/**
|
|
7994
|
+
* Single attempt: serialize the PREPARE, POST it, and map the response.
|
|
7995
|
+
* @throws {NetworkError} On connection/timeout failures (retried).
|
|
7996
|
+
* @throws {ConnectorError} On non-retryable transport errors (5xx / unexpected).
|
|
7997
|
+
*/
|
|
7998
|
+
async postPrepare(params, claim) {
|
|
7999
|
+
const requestTimeout = params.timeout ?? this.timeout;
|
|
8000
|
+
const prepare = serializeIlpPrepare({
|
|
8001
|
+
type: ILPPacketType.PREPARE,
|
|
8002
|
+
amount: BigInt(params.amount),
|
|
8003
|
+
destination: params.destination,
|
|
8004
|
+
executionCondition: new Uint8Array(32),
|
|
8005
|
+
expiresAt: new Date(Date.now() + requestTimeout),
|
|
8006
|
+
data: fromBase64(params.data)
|
|
8007
|
+
});
|
|
8008
|
+
const headers = {
|
|
8009
|
+
"Content-Type": "application/octet-stream",
|
|
8010
|
+
...this.authHeaders()
|
|
8011
|
+
};
|
|
8012
|
+
if (claim !== void 0) {
|
|
8013
|
+
headers[ILP_CLAIM_HEADER] = toBase64(
|
|
8014
|
+
encodeUtf8(JSON.stringify(claim))
|
|
8015
|
+
);
|
|
8016
|
+
}
|
|
8017
|
+
const controller = new AbortController();
|
|
8018
|
+
const timeoutId = setTimeout(() => controller.abort(), requestTimeout);
|
|
8019
|
+
try {
|
|
8020
|
+
const response = await this.httpClient(this.httpEndpoint, {
|
|
8021
|
+
method: "POST",
|
|
8022
|
+
headers,
|
|
8023
|
+
// Copy into a fresh ArrayBuffer so fetch sees a clean body, not a view.
|
|
8024
|
+
body: prepare.slice(),
|
|
8025
|
+
signal: controller.signal
|
|
8026
|
+
});
|
|
8027
|
+
clearTimeout(timeoutId);
|
|
8028
|
+
return await this.mapResponse(response);
|
|
8029
|
+
} catch (error) {
|
|
8030
|
+
clearTimeout(timeoutId);
|
|
8031
|
+
throw this.mapTransportError(error, requestTimeout);
|
|
8032
|
+
}
|
|
8033
|
+
}
|
|
8034
|
+
/**
|
|
8035
|
+
* Map a `200 OK` body (OER FULFILL/REJECT) to an IlpSendResult; map a non-2xx
|
|
8036
|
+
* to a transport error. Per the wire contract, ILP-level rejects arrive as a
|
|
8037
|
+
* 200 + REJECT body — only HTTP non-2xx means a transport-layer failure.
|
|
8038
|
+
*/
|
|
8039
|
+
async mapResponse(response) {
|
|
8040
|
+
if (response.ok) {
|
|
8041
|
+
const buf = new Uint8Array(await response.arrayBuffer());
|
|
8042
|
+
if (buf.length === 0) {
|
|
8043
|
+
throw new ConnectorError("Empty 200 body from /ilp (expected OER ILP response)");
|
|
8044
|
+
}
|
|
8045
|
+
const ilp = deserializeIlpPacket(buf);
|
|
8046
|
+
if (ilp.type === ILPPacketType.FULFILL) {
|
|
8047
|
+
return {
|
|
8048
|
+
accepted: true,
|
|
8049
|
+
data: ilp.data.length > 0 ? toBase64(ilp.data) : void 0
|
|
8050
|
+
};
|
|
8051
|
+
}
|
|
8052
|
+
return {
|
|
8053
|
+
accepted: false,
|
|
8054
|
+
code: ilp.code,
|
|
8055
|
+
message: ilp.message,
|
|
8056
|
+
data: ilp.data.length > 0 ? toBase64(ilp.data) : void 0
|
|
8057
|
+
};
|
|
8058
|
+
}
|
|
8059
|
+
const body = await response.text().catch(() => "");
|
|
8060
|
+
const detail = body ? `: ${body}` : "";
|
|
8061
|
+
if (response.status >= 500) {
|
|
8062
|
+
throw new ConnectorError(
|
|
8063
|
+
`Connector transport error (${response.status} ${response.statusText})${detail}`
|
|
8064
|
+
);
|
|
8065
|
+
}
|
|
8066
|
+
throw new ConnectorError(
|
|
8067
|
+
`ILP-over-HTTP request rejected (${response.status} ${response.statusText})${detail}`
|
|
8068
|
+
);
|
|
8069
|
+
}
|
|
8070
|
+
mapTransportError(error, requestTimeout) {
|
|
8071
|
+
if (error instanceof ConnectorError || error instanceof NetworkError) {
|
|
8072
|
+
return error;
|
|
8073
|
+
}
|
|
8074
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
8075
|
+
return new NetworkError(`Request timeout after ${requestTimeout}ms`, error);
|
|
8076
|
+
}
|
|
8077
|
+
if (error instanceof TypeError && (error.message.includes("fetch failed") || error.message.includes("ECONNREFUSED") || error.message.includes("ECONNRESET") || error.message.includes("ETIMEDOUT") || error.message.includes("network"))) {
|
|
8078
|
+
return new NetworkError(`Network connection failed: ${error.message}`, error);
|
|
8079
|
+
}
|
|
8080
|
+
return new ConnectorError(
|
|
8081
|
+
`Unexpected error during ILP-over-HTTP request: ${error instanceof Error ? error.message : String(error)}`,
|
|
8082
|
+
error instanceof Error ? error : void 0
|
|
8083
|
+
);
|
|
8084
|
+
}
|
|
8085
|
+
};
|
|
8086
|
+
function httpEndpointToBtpUrl(httpEndpoint) {
|
|
8087
|
+
return httpEndpoint.replace(/^https:\/\//i, "wss://").replace(/^http:\/\//i, "ws://");
|
|
8088
|
+
}
|
|
8089
|
+
async function makeBtpWebSocketFactory(headers) {
|
|
8090
|
+
const { createRequire } = await import("module");
|
|
8091
|
+
const require2 = createRequire(import.meta.url);
|
|
8092
|
+
const WS = require2("ws");
|
|
8093
|
+
const ws = WS;
|
|
8094
|
+
const WSClass = typeof ws === "function" ? ws : typeof ws.default === "function" ? ws.default : typeof ws.WebSocket === "function" ? ws.WebSocket : null;
|
|
8095
|
+
if (WSClass === null) {
|
|
8096
|
+
throw new Error(
|
|
8097
|
+
"makeBtpWebSocketFactory: require('ws') did not yield a constructor on .default, .WebSocket, or the module root."
|
|
8098
|
+
);
|
|
8099
|
+
}
|
|
8100
|
+
return (url) => (
|
|
8101
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8102
|
+
new WSClass(url, "btp", { headers })
|
|
8103
|
+
);
|
|
8104
|
+
}
|
|
8105
|
+
function readDiscoveredIlpPeer(peer) {
|
|
8106
|
+
const p = peer ?? {};
|
|
8107
|
+
return {
|
|
8108
|
+
btpEndpoint: typeof p["btpEndpoint"] === "string" ? p["btpEndpoint"] : void 0,
|
|
8109
|
+
httpEndpoint: typeof p["httpEndpoint"] === "string" ? p["httpEndpoint"] : void 0,
|
|
8110
|
+
supportsUpgrade: typeof p["supportsUpgrade"] === "boolean" ? p["supportsUpgrade"] : void 0
|
|
8111
|
+
};
|
|
8112
|
+
}
|
|
8113
|
+
function selectIlpTransport(peer, options = {}) {
|
|
8114
|
+
const needsDuplex = options.needsDuplex ?? false;
|
|
8115
|
+
const http2 = peer.httpEndpoint?.trim() || void 0;
|
|
8116
|
+
const btp = peer.btpEndpoint?.trim() || void 0;
|
|
8117
|
+
const canUpgrade = peer.supportsUpgrade === true;
|
|
8118
|
+
if (needsDuplex) {
|
|
8119
|
+
if (btp) return { kind: "btp", btpEndpoint: btp };
|
|
8120
|
+
if (http2 && canUpgrade) return { kind: "http-upgradable", httpEndpoint: http2 };
|
|
8121
|
+
throw new Error(
|
|
8122
|
+
"Duplex transport required but peer exposes neither a btpEndpoint nor an upgradable httpEndpoint"
|
|
8123
|
+
);
|
|
8124
|
+
}
|
|
8125
|
+
if (http2) return { kind: "http", httpEndpoint: http2, canUpgrade };
|
|
8126
|
+
if (btp) return { kind: "btp", btpEndpoint: btp };
|
|
8127
|
+
throw new Error("Peer exposes neither an httpEndpoint nor a btpEndpoint");
|
|
8128
|
+
}
|
|
8235
8129
|
var TOKEN_PROGRAM_ID = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
|
|
8236
8130
|
var SYSTEM_PROGRAM_ID = "11111111111111111111111111111111";
|
|
8237
8131
|
var RENT_SYSVAR_ID = "SysvarRent111111111111111111111111111111111";
|
|
@@ -8319,7 +8213,7 @@ function findProgramAddress(seeds, programId) {
|
|
|
8319
8213
|
input.set(programId, offset);
|
|
8320
8214
|
offset += programId.length;
|
|
8321
8215
|
input.set(PDA_MARKER, offset);
|
|
8322
|
-
const hash =
|
|
8216
|
+
const hash = sha2562(input);
|
|
8323
8217
|
if (!isOnCurve(hash)) return { pda: hash, bump };
|
|
8324
8218
|
}
|
|
8325
8219
|
throw new Error("Could not find a viable PDA bump seed");
|
|
@@ -9399,6 +9293,12 @@ async function initializeHttpMode(config) {
|
|
|
9399
9293
|
const effectiveBtpUrl = transport.btpUrl ?? config.btpUrl;
|
|
9400
9294
|
const effectiveConnectorUrl = transport.connectorUrl ?? config.connectorUrl;
|
|
9401
9295
|
const settlementInfo = buildSettlementInfo(config);
|
|
9296
|
+
const discoveredPeer = readDiscoveredIlpPeer({
|
|
9297
|
+
btpEndpoint: effectiveBtpUrl,
|
|
9298
|
+
httpEndpoint: config.connectorHttpEndpoint,
|
|
9299
|
+
supportsUpgrade: config.connectorSupportsUpgrade
|
|
9300
|
+
});
|
|
9301
|
+
const transportChoice = discoveredPeer.httpEndpoint || discoveredPeer.btpEndpoint ? selectIlpTransport(discoveredPeer, { needsDuplex: false }) : null;
|
|
9402
9302
|
let btpClient = null;
|
|
9403
9303
|
if (effectiveBtpUrl) {
|
|
9404
9304
|
btpClient = new BtpRuntimeClient({
|
|
@@ -9409,7 +9309,20 @@ async function initializeHttpMode(config) {
|
|
|
9409
9309
|
});
|
|
9410
9310
|
await btpClient.connect();
|
|
9411
9311
|
}
|
|
9412
|
-
|
|
9312
|
+
let httpIlpClient = null;
|
|
9313
|
+
if (transportChoice && (transportChoice.kind === "http" || transportChoice.kind === "http-upgradable")) {
|
|
9314
|
+
httpIlpClient = new HttpIlpClient({
|
|
9315
|
+
httpEndpoint: transportChoice.httpEndpoint,
|
|
9316
|
+
...config.btpPeerId !== void 0 ? { peerId: config.btpPeerId } : {},
|
|
9317
|
+
...config.btpAuthToken !== void 0 ? { authToken: config.btpAuthToken } : {},
|
|
9318
|
+
timeout: config.queryTimeout,
|
|
9319
|
+
maxRetries: config.maxRetries,
|
|
9320
|
+
retryDelay: config.retryDelay,
|
|
9321
|
+
...transport.httpClient !== void 0 ? { httpClient: transport.httpClient } : {},
|
|
9322
|
+
...transport.createWebSocket !== void 0 ? { createWebSocket: transport.createWebSocket } : {}
|
|
9323
|
+
});
|
|
9324
|
+
}
|
|
9325
|
+
const runtimeClient = httpIlpClient ?? btpClient ?? new HttpRuntimeClient({
|
|
9413
9326
|
connectorUrl: effectiveConnectorUrl,
|
|
9414
9327
|
timeout: config.queryTimeout,
|
|
9415
9328
|
maxRetries: config.maxRetries,
|
|
@@ -9666,7 +9579,7 @@ var DEFAULT_MINA_TOKEN_ID = "MINA";
|
|
|
9666
9579
|
var MINA_CLAIM_NETWORK = "devnet";
|
|
9667
9580
|
function deriveMinaSalt(zkAppAddress, nonce) {
|
|
9668
9581
|
const digestHex = bytesToHex(
|
|
9669
|
-
|
|
9582
|
+
sha2562(new TextEncoder().encode(`mina-pc-salt:${zkAppAddress}:${nonce}`))
|
|
9670
9583
|
);
|
|
9671
9584
|
const salt = BigInt("0x" + digestHex.slice(0, 60));
|
|
9672
9585
|
return salt === 0n ? 1n : salt;
|
|
@@ -10134,6 +10047,319 @@ var JsonFileChannelStore = class {
|
|
|
10134
10047
|
writeFileSync(this.filePath, JSON.stringify(data, null, 2), "utf-8");
|
|
10135
10048
|
}
|
|
10136
10049
|
};
|
|
10050
|
+
var ARWEAVE_TX_ID_REGEX = /^[A-Za-z0-9_-]{43}$/;
|
|
10051
|
+
async function requestBlobStorage(client, secretKey, params) {
|
|
10052
|
+
const bid = params.bid ?? (params.ilpAmount !== void 0 ? String(params.ilpAmount) : void 0);
|
|
10053
|
+
if (bid === void 0 || bid === "") {
|
|
10054
|
+
return {
|
|
10055
|
+
success: false,
|
|
10056
|
+
error: "requestBlobStorage requires a bid (or ilpAmount to derive it)"
|
|
10057
|
+
};
|
|
10058
|
+
}
|
|
10059
|
+
const blobBuffer = Buffer.from(
|
|
10060
|
+
params.blobData.buffer,
|
|
10061
|
+
params.blobData.byteOffset,
|
|
10062
|
+
params.blobData.byteLength
|
|
10063
|
+
);
|
|
10064
|
+
let event;
|
|
10065
|
+
try {
|
|
10066
|
+
event = buildBlobStorageRequest(
|
|
10067
|
+
{
|
|
10068
|
+
blobData: blobBuffer,
|
|
10069
|
+
contentType: params.contentType,
|
|
10070
|
+
bid
|
|
10071
|
+
},
|
|
10072
|
+
secretKey
|
|
10073
|
+
);
|
|
10074
|
+
} catch (error) {
|
|
10075
|
+
return {
|
|
10076
|
+
success: false,
|
|
10077
|
+
error: error instanceof Error ? error.message : String(error)
|
|
10078
|
+
};
|
|
10079
|
+
}
|
|
10080
|
+
const result = await client.publishEvent(event, {
|
|
10081
|
+
destination: params.destination,
|
|
10082
|
+
claim: params.claim,
|
|
10083
|
+
ilpAmount: params.ilpAmount
|
|
10084
|
+
});
|
|
10085
|
+
if (!result.success) {
|
|
10086
|
+
return {
|
|
10087
|
+
success: false,
|
|
10088
|
+
eventId: result.eventId ?? event.id,
|
|
10089
|
+
error: result.error ?? "Blob storage request rejected"
|
|
10090
|
+
};
|
|
10091
|
+
}
|
|
10092
|
+
if (!result.data) {
|
|
10093
|
+
return {
|
|
10094
|
+
success: false,
|
|
10095
|
+
eventId: event.id,
|
|
10096
|
+
error: "FULFILL contained no data; expected base64-encoded Arweave tx ID"
|
|
10097
|
+
};
|
|
10098
|
+
}
|
|
10099
|
+
const txId = decodeUtf8(fromBase64(result.data));
|
|
10100
|
+
if (!ARWEAVE_TX_ID_REGEX.test(txId)) {
|
|
10101
|
+
return {
|
|
10102
|
+
success: false,
|
|
10103
|
+
eventId: event.id,
|
|
10104
|
+
error: `Decoded FULFILL data is not a valid Arweave tx ID: "${txId}"`
|
|
10105
|
+
};
|
|
10106
|
+
}
|
|
10107
|
+
return {
|
|
10108
|
+
success: true,
|
|
10109
|
+
txId,
|
|
10110
|
+
eventId: event.id
|
|
10111
|
+
};
|
|
10112
|
+
}
|
|
10113
|
+
var Http402Client = class {
|
|
10114
|
+
fetchImpl;
|
|
10115
|
+
resolveClaim;
|
|
10116
|
+
createIlpClient;
|
|
10117
|
+
needsDuplex;
|
|
10118
|
+
constructor(config = {}) {
|
|
10119
|
+
this.fetchImpl = config.fetch ?? fetch;
|
|
10120
|
+
this.resolveClaim = config.resolveClaim;
|
|
10121
|
+
this.createIlpClient = config.createIlpClient ?? ((httpEndpoint) => new HttpIlpClient({ httpEndpoint }));
|
|
10122
|
+
this.needsDuplex = config.needsDuplex ?? false;
|
|
10123
|
+
}
|
|
10124
|
+
/**
|
|
10125
|
+
* `fetch()`-like entry point. Issues the request; on `402` parses the x402
|
|
10126
|
+
* challenge and — when a usable `toon-channel` offer is present and a claim
|
|
10127
|
+
* resolver is configured — pays over TOON and returns the reconstructed
|
|
10128
|
+
* `Response`. Otherwise returns the original 402 unchanged (AC5).
|
|
10129
|
+
*/
|
|
10130
|
+
async fetch(url, opts = {}) {
|
|
10131
|
+
const method = (opts.method ?? "GET").toUpperCase();
|
|
10132
|
+
const probe = await this.fetchImpl(url, {
|
|
10133
|
+
method,
|
|
10134
|
+
...opts.headers ? { headers: opts.headers } : {},
|
|
10135
|
+
...opts.body !== void 0 ? { body: opts.body } : {},
|
|
10136
|
+
...opts.timeout !== void 0 ? { signal: AbortSignal.timeout(opts.timeout) } : {}
|
|
10137
|
+
});
|
|
10138
|
+
if (probe.status !== 402) return probe;
|
|
10139
|
+
const challenge = await parseX402Challenge(probe.clone());
|
|
10140
|
+
const accept = challenge.toonChannel;
|
|
10141
|
+
if (!accept || !this.resolveClaim) return probe;
|
|
10142
|
+
return this.payOverToon(url, method, opts, accept, this.resolveClaim);
|
|
10143
|
+
}
|
|
10144
|
+
/**
|
|
10145
|
+
* Open/reuse a channel (via the injected claim resolver), serialize the HTTP
|
|
10146
|
+
* request into the ILP packet `data`, send it to `POST /ilp` with the claim,
|
|
10147
|
+
* and reconstruct the origin `Response` from the FULFILL `data`.
|
|
10148
|
+
*/
|
|
10149
|
+
async payOverToon(url, method, opts, accept, resolveClaim) {
|
|
10150
|
+
const destination = opts.destination ?? accept.destination;
|
|
10151
|
+
const claim = await resolveClaim(destination, accept.amount);
|
|
10152
|
+
const requestBytes = serializeHttpRequest({
|
|
10153
|
+
method,
|
|
10154
|
+
url,
|
|
10155
|
+
headers: opts.headers,
|
|
10156
|
+
body: opts.body
|
|
10157
|
+
});
|
|
10158
|
+
const peer = {
|
|
10159
|
+
httpEndpoint: accept.httpEndpoint,
|
|
10160
|
+
supportsUpgrade: accept.supportsUpgrade
|
|
10161
|
+
};
|
|
10162
|
+
const choice = selectIlpTransport(peer, {
|
|
10163
|
+
needsDuplex: this.needsDuplex
|
|
10164
|
+
});
|
|
10165
|
+
const ilpClient = this.createIlpClient(accept.httpEndpoint);
|
|
10166
|
+
const result = await this.sendOverChoice(
|
|
10167
|
+
ilpClient,
|
|
10168
|
+
choice,
|
|
10169
|
+
{
|
|
10170
|
+
destination,
|
|
10171
|
+
amount: String(accept.amount),
|
|
10172
|
+
data: toBase64(requestBytes),
|
|
10173
|
+
...opts.timeout !== void 0 ? { timeout: opts.timeout } : {}
|
|
10174
|
+
},
|
|
10175
|
+
claim
|
|
10176
|
+
);
|
|
10177
|
+
if (!result.accepted) {
|
|
10178
|
+
throw new ConnectorError(
|
|
10179
|
+
`h402 payment rejected by connector: ${result.code ?? "F00"} ${result.message ?? ""}`.trim()
|
|
10180
|
+
);
|
|
10181
|
+
}
|
|
10182
|
+
if (!result.data) {
|
|
10183
|
+
throw new ConnectorError(
|
|
10184
|
+
"h402 FULFILL carried no data (expected an HTTP response payload)"
|
|
10185
|
+
);
|
|
10186
|
+
}
|
|
10187
|
+
return parseHttpResponse(fromBase64(result.data));
|
|
10188
|
+
}
|
|
10189
|
+
/**
|
|
10190
|
+
* Send the serialized HTTP-in-ILP PREPARE over the selected transport.
|
|
10191
|
+
*
|
|
10192
|
+
* - `http` / `http-upgradable`: stateless one-shot `POST /ilp` with the claim.
|
|
10193
|
+
* - `http-upgradable` additionally exercises {@link HttpIlpClient.upgradeToBtp}
|
|
10194
|
+
* for the duplex/streaming path (AC4). v1 still drives the actual write over
|
|
10195
|
+
* the one-shot HTTP method even after upgrading — full duplex body streaming
|
|
10196
|
+
* is a documented follow-up — but the upgrade call path is wired here.
|
|
10197
|
+
* - `btp`: not reachable from h402 (the x402 offer only carries an
|
|
10198
|
+
* `httpEndpoint`); guarded for completeness.
|
|
10199
|
+
*/
|
|
10200
|
+
async sendOverChoice(ilpClient, choice, params, claim) {
|
|
10201
|
+
if (choice.kind === "http-upgradable") {
|
|
10202
|
+
const btp = await ilpClient.upgradeToBtp();
|
|
10203
|
+
try {
|
|
10204
|
+
return await btp.sendIlpPacketWithClaim(
|
|
10205
|
+
params,
|
|
10206
|
+
claim
|
|
10207
|
+
);
|
|
10208
|
+
} finally {
|
|
10209
|
+
await btp.disconnect().catch(() => {
|
|
10210
|
+
});
|
|
10211
|
+
}
|
|
10212
|
+
}
|
|
10213
|
+
if (choice.kind === "btp") {
|
|
10214
|
+
throw new ToonClientError(
|
|
10215
|
+
"h402 offer resolved to a BTP-only transport; the x402 toon-channel entry must advertise an httpEndpoint",
|
|
10216
|
+
"INVALID_STATE"
|
|
10217
|
+
);
|
|
10218
|
+
}
|
|
10219
|
+
return ilpClient.sendIlpPacketWithClaim(params, claim);
|
|
10220
|
+
}
|
|
10221
|
+
};
|
|
10222
|
+
function readString(obj, keys) {
|
|
10223
|
+
for (const k of keys) {
|
|
10224
|
+
const v = obj[k];
|
|
10225
|
+
if (typeof v === "string" && v.trim().length > 0) return v.trim();
|
|
10226
|
+
}
|
|
10227
|
+
return void 0;
|
|
10228
|
+
}
|
|
10229
|
+
function readAmount(obj, keys) {
|
|
10230
|
+
for (const k of keys) {
|
|
10231
|
+
const v = obj[k];
|
|
10232
|
+
if (typeof v === "bigint") return v;
|
|
10233
|
+
if (typeof v === "number" && Number.isFinite(v)) return BigInt(Math.trunc(v));
|
|
10234
|
+
if (typeof v === "string" && /^\d+$/.test(v.trim())) return BigInt(v.trim());
|
|
10235
|
+
}
|
|
10236
|
+
return void 0;
|
|
10237
|
+
}
|
|
10238
|
+
async function parseX402Challenge(response) {
|
|
10239
|
+
let body;
|
|
10240
|
+
try {
|
|
10241
|
+
body = await response.json();
|
|
10242
|
+
} catch {
|
|
10243
|
+
return {};
|
|
10244
|
+
}
|
|
10245
|
+
return parseX402Body(body);
|
|
10246
|
+
}
|
|
10247
|
+
function parseX402Body(body) {
|
|
10248
|
+
if (typeof body !== "object" || body === null) return {};
|
|
10249
|
+
const b = body;
|
|
10250
|
+
const version = typeof b["x402Version"] === "number" ? b["x402Version"] : void 0;
|
|
10251
|
+
const accepts = Array.isArray(b["accepts"]) ? b["accepts"] : [];
|
|
10252
|
+
for (const raw of accepts) {
|
|
10253
|
+
if (typeof raw !== "object" || raw === null) continue;
|
|
10254
|
+
const entry = raw;
|
|
10255
|
+
const scheme = readString(entry, ["scheme"]);
|
|
10256
|
+
if (scheme !== "toon-channel") continue;
|
|
10257
|
+
const destination = readString(entry, [
|
|
10258
|
+
"destination",
|
|
10259
|
+
"ilpAddress",
|
|
10260
|
+
"payTo"
|
|
10261
|
+
]);
|
|
10262
|
+
const httpEndpoint = readString(entry, [
|
|
10263
|
+
"httpEndpoint",
|
|
10264
|
+
"ilpEndpoint",
|
|
10265
|
+
"endpoint"
|
|
10266
|
+
]);
|
|
10267
|
+
const amount = readAmount(entry, ["amount", "price", "maxAmountRequired"]);
|
|
10268
|
+
if (!destination || !httpEndpoint || amount === void 0) continue;
|
|
10269
|
+
const network = readString(entry, ["network", "chain"]);
|
|
10270
|
+
const supportsUpgrade = entry["supportsUpgrade"] === true || entry["upgradable"] === true;
|
|
10271
|
+
return {
|
|
10272
|
+
...version !== void 0 ? { x402Version: version } : {},
|
|
10273
|
+
toonChannel: {
|
|
10274
|
+
scheme: "toon-channel",
|
|
10275
|
+
...network !== void 0 ? { network } : {},
|
|
10276
|
+
destination,
|
|
10277
|
+
amount,
|
|
10278
|
+
httpEndpoint,
|
|
10279
|
+
supportsUpgrade
|
|
10280
|
+
}
|
|
10281
|
+
};
|
|
10282
|
+
}
|
|
10283
|
+
return version !== void 0 ? { x402Version: version } : {};
|
|
10284
|
+
}
|
|
10285
|
+
var CRLF = "\r\n";
|
|
10286
|
+
function concatHeadAndBody(head, body) {
|
|
10287
|
+
const headBytes = encodeUtf8(head);
|
|
10288
|
+
const out = new Uint8Array(headBytes.length + body.length);
|
|
10289
|
+
out.set(headBytes, 0);
|
|
10290
|
+
out.set(body, headBytes.length);
|
|
10291
|
+
return out;
|
|
10292
|
+
}
|
|
10293
|
+
function bodyToBytes(body) {
|
|
10294
|
+
if (body === void 0) return new Uint8Array(0);
|
|
10295
|
+
return typeof body === "string" ? encodeUtf8(body) : body;
|
|
10296
|
+
}
|
|
10297
|
+
function serializeHttpRequest(req) {
|
|
10298
|
+
const u = new URL(req.url);
|
|
10299
|
+
const target = `${u.pathname}${u.search}` || "/";
|
|
10300
|
+
const bodyBytes = bodyToBytes(req.body);
|
|
10301
|
+
const headers = /* @__PURE__ */ new Map();
|
|
10302
|
+
const put = (name, value) => headers.set(name.toLowerCase(), `${name}: ${value}`);
|
|
10303
|
+
const has = (name) => headers.has(name.toLowerCase());
|
|
10304
|
+
for (const [name, value] of Object.entries(req.headers ?? {})) {
|
|
10305
|
+
put(name, value);
|
|
10306
|
+
}
|
|
10307
|
+
if (!has("host")) put("Host", u.host);
|
|
10308
|
+
if (bodyBytes.length > 0 && !has("content-length")) {
|
|
10309
|
+
put("Content-Length", String(bodyBytes.length));
|
|
10310
|
+
}
|
|
10311
|
+
const lines = [
|
|
10312
|
+
`${req.method.toUpperCase()} ${target} HTTP/1.1`,
|
|
10313
|
+
...headers.values()
|
|
10314
|
+
];
|
|
10315
|
+
const head = lines.join(CRLF) + CRLF + CRLF;
|
|
10316
|
+
return concatHeadAndBody(head, bodyBytes);
|
|
10317
|
+
}
|
|
10318
|
+
function findHeaderEnd(bytes) {
|
|
10319
|
+
for (let i = 0; i + 3 < bytes.length; i++) {
|
|
10320
|
+
if (bytes[i] === 13 && bytes[i + 1] === 10 && bytes[i + 2] === 13 && bytes[i + 3] === 10) {
|
|
10321
|
+
return i + 4;
|
|
10322
|
+
}
|
|
10323
|
+
}
|
|
10324
|
+
return -1;
|
|
10325
|
+
}
|
|
10326
|
+
function parseHttpResponse(bytes) {
|
|
10327
|
+
const headerEnd = findHeaderEnd(bytes);
|
|
10328
|
+
const headBytes = headerEnd === -1 ? bytes : bytes.subarray(0, headerEnd - 2);
|
|
10329
|
+
const body = headerEnd === -1 ? new Uint8Array(0) : bytes.subarray(headerEnd);
|
|
10330
|
+
const headText = decodeUtf8(headBytes);
|
|
10331
|
+
const lines = headText.split(CRLF).filter((l) => l.length > 0);
|
|
10332
|
+
const statusLine = lines.shift();
|
|
10333
|
+
if (!statusLine) {
|
|
10334
|
+
throw new ConnectorError(
|
|
10335
|
+
"h402 response payload had no HTTP status line"
|
|
10336
|
+
);
|
|
10337
|
+
}
|
|
10338
|
+
const match = /^HTTP\/\d\.\d\s+(\d{3})(?:\s+(.*))?$/.exec(statusLine.trim());
|
|
10339
|
+
if (!match) {
|
|
10340
|
+
throw new ConnectorError(
|
|
10341
|
+
`h402 response payload had a malformed status line: "${statusLine}"`
|
|
10342
|
+
);
|
|
10343
|
+
}
|
|
10344
|
+
const status = parseInt(match[1], 10);
|
|
10345
|
+
const statusText = match[2] ?? "";
|
|
10346
|
+
const headers = new Headers();
|
|
10347
|
+
for (const line of lines) {
|
|
10348
|
+
const idx = line.indexOf(":");
|
|
10349
|
+
if (idx === -1) continue;
|
|
10350
|
+
const name = line.slice(0, idx).trim();
|
|
10351
|
+
const value = line.slice(idx + 1).trim();
|
|
10352
|
+
if (name.length === 0) continue;
|
|
10353
|
+
headers.append(name, value);
|
|
10354
|
+
}
|
|
10355
|
+
const nullBodyStatus = status === 101 || status === 204 || status === 205 || status === 304;
|
|
10356
|
+
const init = { status, headers };
|
|
10357
|
+
if (statusText) init.statusText = statusText;
|
|
10358
|
+
return new Response(
|
|
10359
|
+
nullBodyStatus || body.length === 0 ? null : body.slice(),
|
|
10360
|
+
init
|
|
10361
|
+
);
|
|
10362
|
+
}
|
|
10137
10363
|
var ToonClient = class {
|
|
10138
10364
|
config;
|
|
10139
10365
|
state = null;
|
|
@@ -10184,6 +10410,28 @@ var ToonClient = class {
|
|
|
10184
10410
|
getPublicKey() {
|
|
10185
10411
|
return getPublicKey22(this.config.secretKey);
|
|
10186
10412
|
}
|
|
10413
|
+
/**
|
|
10414
|
+
* Sign an unsigned Nostr event template with the client's Nostr secret key,
|
|
10415
|
+
* returning a fully-signed event (id + pubkey + sig).
|
|
10416
|
+
*
|
|
10417
|
+
* This is the key primitive behind the daemon's sign-and-publish path: a UI
|
|
10418
|
+
* or agent supplies only `{ kind, content, tags, created_at }` and never holds
|
|
10419
|
+
* the private key — signing happens here, inside the key owner.
|
|
10420
|
+
*/
|
|
10421
|
+
signEvent(template) {
|
|
10422
|
+
return finalizeEvent11(template, this.config.secretKey);
|
|
10423
|
+
}
|
|
10424
|
+
/**
|
|
10425
|
+
* Upload bytes to Arweave via the kind:5094 blob-storage DVM (single-packet),
|
|
10426
|
+
* signing the request with this client's Nostr key and paying through its
|
|
10427
|
+
* existing channel. Returns the Arweave tx id on success.
|
|
10428
|
+
*
|
|
10429
|
+
* Backs the daemon's `upload-media` path: the key and claim/channel plumbing
|
|
10430
|
+
* stay inside the client; callers pass only the bytes.
|
|
10431
|
+
*/
|
|
10432
|
+
async uploadBlob(params) {
|
|
10433
|
+
return requestBlobStorage(this, this.config.secretKey, params);
|
|
10434
|
+
}
|
|
10187
10435
|
/**
|
|
10188
10436
|
* Per-chain settlement readiness for the configured `network` tier, mirroring
|
|
10189
10437
|
* the townhouse node's status. Returns `undefined` when no named `network` is
|
|
@@ -10466,6 +10714,46 @@ var ToonClient = class {
|
|
|
10466
10714
|
);
|
|
10467
10715
|
}
|
|
10468
10716
|
}
|
|
10717
|
+
/**
|
|
10718
|
+
* Payment-aware HTTP fetch over TOON (issue #50). A `fetch()`-like method that
|
|
10719
|
+
* makes paying for an HTTP resource transparent:
|
|
10720
|
+
*
|
|
10721
|
+
* 1. Issues the HTTP request to `url`.
|
|
10722
|
+
* 2. On `402`, parses the x402 `accepts` array and selects the
|
|
10723
|
+
* `toon-channel` entry (see {@link Http402Client} for the wire shape).
|
|
10724
|
+
* 3. Opens/reuses a payment channel for the entry's ILP destination (via
|
|
10725
|
+
* ChannelManager), signs a balance proof for the demanded price, and
|
|
10726
|
+
* re-sends the SAME HTTP request as a transparent HTTP-in-ILP packet to
|
|
10727
|
+
* the connector's `POST /ilp` (via {@link HttpIlpClient}), with the claim
|
|
10728
|
+
* in the `ILP-Payment-Channel-Claim` header.
|
|
10729
|
+
* 4. Reconstructs and returns a standard Web `Response` from the FULFILL
|
|
10730
|
+
* `data`. The caller never sees ILP.
|
|
10731
|
+
*
|
|
10732
|
+
* If the origin offers no `toon-channel` entry, the original `402` Response is
|
|
10733
|
+
* returned unchanged (the caller sees the vanilla x402 challenge).
|
|
10734
|
+
*
|
|
10735
|
+
* The channel/claim plumbing is wired to the live ChannelManager + per-chain
|
|
10736
|
+
* signer via `resolveClaimForDestination` — identical to `publishEvent`. The
|
|
10737
|
+
* `amount` paid comes from the selected x402 entry (the resource's price).
|
|
10738
|
+
*
|
|
10739
|
+
* @throws {ToonClientError} If the client is not started.
|
|
10740
|
+
* @throws {ConnectorError} If the connector rejects the payment or returns no
|
|
10741
|
+
* HTTP payload.
|
|
10742
|
+
*/
|
|
10743
|
+
async h402Fetch(url, opts) {
|
|
10744
|
+
if (!this.state) {
|
|
10745
|
+
throw new ToonClientError(
|
|
10746
|
+
"Client not started. Call start() first.",
|
|
10747
|
+
"INVALID_STATE"
|
|
10748
|
+
);
|
|
10749
|
+
}
|
|
10750
|
+
const client = new Http402Client({
|
|
10751
|
+
...this.channelManager ? {
|
|
10752
|
+
resolveClaim: (destination, amount) => this.resolveClaimForDestination(destination, amount)
|
|
10753
|
+
} : {}
|
|
10754
|
+
});
|
|
10755
|
+
return client.fetch(url, opts);
|
|
10756
|
+
}
|
|
10469
10757
|
/**
|
|
10470
10758
|
* Sends a raw swap ILP packet (Story 12.5) to a Mill peer with an attached
|
|
10471
10759
|
* balance-proof claim. This is a lower-level surface than `publishEvent`:
|
|
@@ -11073,6 +11361,9 @@ var ControlApiError = class extends Error {
|
|
|
11073
11361
|
this.detail = detail;
|
|
11074
11362
|
this.name = "ControlApiError";
|
|
11075
11363
|
}
|
|
11364
|
+
status;
|
|
11365
|
+
retryable;
|
|
11366
|
+
detail;
|
|
11076
11367
|
};
|
|
11077
11368
|
var DaemonUnreachableError = class extends Error {
|
|
11078
11369
|
constructor(baseUrl, causedBy) {
|
|
@@ -11081,6 +11372,8 @@ var DaemonUnreachableError = class extends Error {
|
|
|
11081
11372
|
this.causedBy = causedBy;
|
|
11082
11373
|
this.name = "DaemonUnreachableError";
|
|
11083
11374
|
}
|
|
11375
|
+
baseUrl;
|
|
11376
|
+
causedBy;
|
|
11084
11377
|
};
|
|
11085
11378
|
var ControlClient = class {
|
|
11086
11379
|
baseUrl;
|
|
@@ -11107,9 +11400,18 @@ var ControlClient = class {
|
|
|
11107
11400
|
publish(body) {
|
|
11108
11401
|
return this.request("POST", "/publish", body);
|
|
11109
11402
|
}
|
|
11403
|
+
publishUnsigned(body) {
|
|
11404
|
+
return this.request("POST", "/publish-unsigned", body);
|
|
11405
|
+
}
|
|
11406
|
+
uploadMedia(body) {
|
|
11407
|
+
return this.request("POST", "/upload-media", body);
|
|
11408
|
+
}
|
|
11110
11409
|
subscribe(body) {
|
|
11111
11410
|
return this.request("POST", "/subscribe", body);
|
|
11112
11411
|
}
|
|
11412
|
+
query(body) {
|
|
11413
|
+
return this.request("POST", "/query", body);
|
|
11414
|
+
}
|
|
11113
11415
|
events(query = {}) {
|
|
11114
11416
|
const qs = new URLSearchParams();
|
|
11115
11417
|
if (query.subId) qs.set("subId", query.subId);
|
|
@@ -11128,6 +11430,13 @@ var ControlClient = class {
|
|
|
11128
11430
|
swap(body) {
|
|
11129
11431
|
return this.request("POST", "/swap", body);
|
|
11130
11432
|
}
|
|
11433
|
+
httpFetchPaid(body) {
|
|
11434
|
+
return this.request(
|
|
11435
|
+
"POST",
|
|
11436
|
+
"/http-fetch-paid",
|
|
11437
|
+
body
|
|
11438
|
+
);
|
|
11439
|
+
}
|
|
11131
11440
|
targets() {
|
|
11132
11441
|
return this.request("GET", "/targets");
|
|
11133
11442
|
}
|
|
@@ -11318,4 +11627,4 @@ export {
|
|
|
11318
11627
|
@scure/bip32/lib/esm/index.js:
|
|
11319
11628
|
(*! scure-bip32 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) *)
|
|
11320
11629
|
*/
|
|
11321
|
-
//# sourceMappingURL=chunk-
|
|
11630
|
+
//# sourceMappingURL=chunk-NP35YO5O.js.map
|