@toon-protocol/client-mcp 0.18.0 → 0.20.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.
Files changed (33) hide show
  1. package/README.md +5 -7
  2. package/dist/app/index.html +69 -69
  3. package/dist/{chunk-VA7XC4FD.js → chunk-3DDN4CJQ.js} +17 -1
  4. package/dist/{chunk-VA7XC4FD.js.map → chunk-3DDN4CJQ.js.map} +1 -1
  5. package/dist/{chunk-FXPDLGDN.js → chunk-5SFBB4PJ.js} +168 -38
  6. package/dist/chunk-5SFBB4PJ.js.map +1 -0
  7. package/dist/{chunk-LR7W2ISE.js → chunk-HMD5EVQI.js} +11 -2
  8. package/dist/{chunk-LR7W2ISE.js.map → chunk-HMD5EVQI.js.map} +1 -1
  9. package/dist/{chunk-LSPAGZXL.js → chunk-HSSJFB3I.js} +1426 -213
  10. package/dist/chunk-HSSJFB3I.js.map +1 -0
  11. package/dist/{chunk-56TTQYS7.js → chunk-KYQUVXEY.js} +2 -2
  12. package/dist/{chunk-XQUUFAIM.js → chunk-LN2OF264.js} +4 -2
  13. package/dist/{chunk-CTDRHEDX.js → chunk-SLMGETW7.js} +2 -2
  14. package/dist/{chunk-CTDRHEDX.js.map → chunk-SLMGETW7.js.map} +1 -1
  15. package/dist/{chunk-32QD72IL.js → chunk-T3WCTWRP.js} +2 -2
  16. package/dist/daemon.js +7 -7
  17. package/dist/{ed25519-U4PTEOFD.js → ed25519-VBPL32VX.js} +2 -2
  18. package/dist/{hmac-CMZORX4Y.js → hmac-GNBDA4UC.js} +3 -3
  19. package/dist/index.d.ts +11 -8
  20. package/dist/index.js +8 -8
  21. package/dist/mcp.js +7 -7
  22. package/dist/{node-WPA2UDEH-72L4MKGB.js → node-WPA2UDEH-SRYDHHAV.js} +3 -3
  23. package/dist/{node-WPA2UDEH-72L4MKGB.js.map → node-WPA2UDEH-SRYDHHAV.js.map} +1 -1
  24. package/dist/{sha512-4LOCATJH.js → sha512-D7TTPT7I.js} +3 -3
  25. package/package.json +6 -6
  26. package/dist/chunk-FXPDLGDN.js.map +0 -1
  27. package/dist/chunk-LSPAGZXL.js.map +0 -1
  28. /package/dist/{chunk-56TTQYS7.js.map → chunk-KYQUVXEY.js.map} +0 -0
  29. /package/dist/{chunk-XQUUFAIM.js.map → chunk-LN2OF264.js.map} +0 -0
  30. /package/dist/{chunk-32QD72IL.js.map → chunk-T3WCTWRP.js.map} +0 -0
  31. /package/dist/{ed25519-U4PTEOFD.js.map → ed25519-VBPL32VX.js.map} +0 -0
  32. /package/dist/{hmac-CMZORX4Y.js.map → hmac-GNBDA4UC.js.map} +0 -0
  33. /package/dist/{sha512-4LOCATJH.js.map → sha512-D7TTPT7I.js.map} +0 -0
@@ -1,19 +1,27 @@
1
1
  import { createRequire as __cr } from 'module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  __require
4
- } from "./chunk-CTDRHEDX.js";
4
+ } from "./chunk-SLMGETW7.js";
5
5
  import {
6
6
  HashMD,
7
+ rotlBH as rotlBH2,
8
+ rotlBL as rotlBL2,
9
+ rotlSH as rotlSH2,
10
+ rotlSL as rotlSL2,
7
11
  sha256 as sha2562,
8
- sha512
9
- } from "./chunk-LR7W2ISE.js";
12
+ sha512,
13
+ split as split2
14
+ } from "./chunk-HMD5EVQI.js";
10
15
  import {
11
16
  hmac
12
- } from "./chunk-32QD72IL.js";
17
+ } from "./chunk-T3WCTWRP.js";
13
18
  import {
19
+ Hash,
14
20
  abytes as abytes3,
21
+ aexists as aexists2,
15
22
  ahash as ahash2,
16
23
  anumber as anumber2,
24
+ aoutput as aoutput2,
17
25
  bytesToHex as bytesToHex3,
18
26
  checkOpts,
19
27
  clean as clean2,
@@ -23,10 +31,13 @@ import {
23
31
  hexToBytes as hexToBytes3,
24
32
  isBytes as isBytes2,
25
33
  kdfInputToBytes,
26
- randomBytes as randomBytes2,
34
+ randomBytes as randomBytes3,
27
35
  rotl,
36
+ swap32IfBE as swap32IfBE2,
37
+ toBytes,
38
+ u32 as u322,
28
39
  utf8ToBytes
29
- } from "./chunk-VA7XC4FD.js";
40
+ } from "./chunk-3DDN4CJQ.js";
30
41
  import {
31
42
  Field,
32
43
  aInRange,
@@ -39,6 +50,7 @@ import {
39
50
  anumber,
40
51
  aoutput,
41
52
  asafenumber,
53
+ asciiToBytes,
42
54
  bitLen,
43
55
  bitMask,
44
56
  bytesToHex,
@@ -62,6 +74,7 @@ import {
62
74
  numberToHexUnpadded,
63
75
  pow2,
64
76
  randomBytes,
77
+ randomBytes2,
65
78
  rotlBH,
66
79
  rotlBL,
67
80
  rotlSH,
@@ -72,13 +85,13 @@ import {
72
85
  u32,
73
86
  validateObject,
74
87
  wNAF
75
- } from "./chunk-XQUUFAIM.js";
88
+ } from "./chunk-LN2OF264.js";
76
89
  import {
77
90
  createBase58check,
78
91
  utils
79
92
  } from "./chunk-NL7NYWPC.js";
80
93
 
81
- // ../../node_modules/.pnpm/@toon-protocol+core@2.1.0_typescript@5.9.3/node_modules/@toon-protocol/core/dist/chunk-5WT7ISKC.js
94
+ // ../../node_modules/.pnpm/@toon-protocol+core@3.0.0_typescript@5.9.3/node_modules/@toon-protocol/core/dist/chunk-5WT7ISKC.js
82
95
  import { encode } from "@toon-format/toon";
83
96
  import { decode } from "@toon-format/toon";
84
97
  import { decode as decode2 } from "@toon-format/toon";
@@ -194,7 +207,7 @@ function decodeEventFromToon(data) {
194
207
  }
195
208
  }
196
209
 
197
- // ../../node_modules/.pnpm/@toon-protocol+core@2.1.0_typescript@5.9.3/node_modules/@toon-protocol/core/dist/index.js
210
+ // ../../node_modules/.pnpm/@toon-protocol+core@3.0.0_typescript@5.9.3/node_modules/@toon-protocol/core/dist/index.js
198
211
  import { finalizeEvent } from "nostr-tools/pure";
199
212
  import { finalizeEvent as finalizeEvent2 } from "nostr-tools/pure";
200
213
  import { finalizeEvent as finalizeEvent3 } from "nostr-tools/pure";
@@ -411,7 +424,7 @@ var Keccak = class _Keccak {
411
424
  var genKeccak = (suffix, blockLen, outputLen, info = {}) => createHasher(() => new Keccak(blockLen, suffix, outputLen), info);
412
425
  var keccak_256 = /* @__PURE__ */ genKeccak(1, 136, 32);
413
426
 
414
- // ../../node_modules/.pnpm/@toon-protocol+core@2.1.0_typescript@5.9.3/node_modules/@toon-protocol/core/dist/index.js
427
+ // ../../node_modules/.pnpm/@toon-protocol+core@3.0.0_typescript@5.9.3/node_modules/@toon-protocol/core/dist/index.js
415
428
  import { SimplePool as SimplePool3 } from "nostr-tools/pool";
416
429
  import { getPublicKey as getPublicKey3 } from "nostr-tools/pure";
417
430
  import WebSocket22 from "ws";
@@ -494,7 +507,7 @@ var hmac2 = /* @__PURE__ */ (() => {
494
507
  })();
495
508
 
496
509
  // ../../node_modules/.pnpm/@noble+curves@2.2.0/node_modules/@noble/curves/abstract/weierstrass.js
497
- var divNearest = (num, den) => (num + (num >= 0 ? den : -den) / _2n2) / den;
510
+ var divNearest = (num2, den) => (num2 + (num2 >= 0 ? den : -den) / _2n2) / den;
498
511
  function _splitEndoScalar(k, basis, n) {
499
512
  aInRange("scalar", k, _0n2, n);
500
513
  const [[a1, b1], [a2, b2]] = basis;
@@ -600,12 +613,12 @@ var DER = {
600
613
  // - add zero byte if exists
601
614
  // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding)
602
615
  _int: {
603
- encode(num) {
616
+ encode(num2) {
604
617
  const { Err: E } = DER;
605
- abignumber(num);
606
- if (num < _0n2)
618
+ abignumber(num2);
619
+ if (num2 < _0n2)
607
620
  throw new E("integer: negative integers are not allowed");
608
- let hex = numberToHexUnpadded(num);
621
+ let hex = numberToHexUnpadded(num2);
609
622
  if (Number.parseInt(hex[0], 16) & 8)
610
623
  hex = "00" + hex;
611
624
  if (hex.length & 1)
@@ -676,7 +689,7 @@ function weierstrass(params, extraOpts = {}) {
676
689
  if (!Fp.isOdd)
677
690
  throw new Error("compression is not supported: Field does not have .isOdd()");
678
691
  }
679
- function pointToBytes(_c, point, isCompressed) {
692
+ function pointToBytes2(_c, point, isCompressed) {
680
693
  if (allowInfinityPoint && point.is0())
681
694
  return Uint8Array.of(0);
682
695
  const { x, y } = point.toAffine();
@@ -727,7 +740,7 @@ function weierstrass(params, extraOpts = {}) {
727
740
  throw new Error(`bad point: got length ${length}, expected compressed=${comp} or uncompressed=${uncomp}`);
728
741
  }
729
742
  }
730
- const encodePoint = extraOpts.toBytes === void 0 ? pointToBytes : extraOpts.toBytes;
743
+ const encodePoint = extraOpts.toBytes === void 0 ? pointToBytes2 : extraOpts.toBytes;
731
744
  const decodePoint = extraOpts.fromBytes === void 0 ? pointFromBytes : extraOpts.fromBytes;
732
745
  function weierstrassEquation(x) {
733
746
  const x2 = Fp.sqr(x);
@@ -1100,14 +1113,14 @@ function getWLengths(Fp, Fn) {
1100
1113
  }
1101
1114
  function ecdh(Point2, ecdhOpts = {}) {
1102
1115
  const { Fn } = Point2;
1103
- const randomBytes_ = ecdhOpts.randomBytes === void 0 ? randomBytes : ecdhOpts.randomBytes;
1116
+ const randomBytes_ = ecdhOpts.randomBytes === void 0 ? randomBytes2 : ecdhOpts.randomBytes;
1104
1117
  const lengths = Object.assign(getWLengths(Point2.Fp, Fn), {
1105
1118
  seed: Math.max(getMinHashLength(Fn.ORDER), 16)
1106
1119
  });
1107
1120
  function isValidSecretKey(secretKey) {
1108
1121
  try {
1109
- const num = Fn.fromBytes(secretKey);
1110
- return Fn.isValidNot0(num);
1122
+ const num2 = Fn.fromBytes(secretKey);
1123
+ return Fn.isValidNot0(num2);
1111
1124
  } catch (error) {
1112
1125
  return false;
1113
1126
  }
@@ -1174,7 +1187,7 @@ function ecdsa(Point2, hash, ecdsaOpts = {}) {
1174
1187
  bits2int_modN: "function"
1175
1188
  });
1176
1189
  ecdsaOpts = Object.assign({}, ecdsaOpts);
1177
- const randomBytes3 = ecdsaOpts.randomBytes === void 0 ? randomBytes : ecdsaOpts.randomBytes;
1190
+ const randomBytes4 = ecdsaOpts.randomBytes === void 0 ? randomBytes2 : ecdsaOpts.randomBytes;
1178
1191
  const hmac3 = ecdsaOpts.hmac === void 0 ? (key2, msg) => hmac2(hash_, key2, msg) : ecdsaOpts.hmac;
1179
1192
  const { Fp, Fn } = Point2;
1180
1193
  const { ORDER: CURVE_ORDER, BITS: fnBits } = Fn;
@@ -1190,10 +1203,10 @@ function ecdsa(Point2, hash, ecdsaOpts = {}) {
1190
1203
  const HALF = CURVE_ORDER >> _1n2;
1191
1204
  return number > HALF;
1192
1205
  }
1193
- function validateRS(title, num) {
1194
- if (!Fn.isValidNot0(num))
1206
+ function validateRS(title, num2) {
1207
+ if (!Fn.isValidNot0(num2))
1195
1208
  throw new Error(`invalid signature ${title}: out of range 1..Point.Fn.ORDER`);
1196
- return num;
1209
+ return num2;
1197
1210
  }
1198
1211
  function assertRecoverableCurve() {
1199
1212
  if (hasLargeRecoveryLifts)
@@ -1295,17 +1308,17 @@ function ecdsa(Point2, hash, ecdsaOpts = {}) {
1295
1308
  const bits2int = ecdsaOpts.bits2int === void 0 ? function bits2int_def(bytes) {
1296
1309
  if (bytes.length > 8192)
1297
1310
  throw new Error("input is too large");
1298
- const num = bytesToNumberBE(bytes);
1311
+ const num2 = bytesToNumberBE(bytes);
1299
1312
  const delta = bytes.length * 8 - fnBits;
1300
- return delta > 0 ? num >> BigInt(delta) : num;
1313
+ return delta > 0 ? num2 >> BigInt(delta) : num2;
1301
1314
  } : ecdsaOpts.bits2int;
1302
1315
  const bits2int_modN = ecdsaOpts.bits2int_modN === void 0 ? function bits2int_modN_def(bytes) {
1303
1316
  return Fn.create(bits2int(bytes));
1304
1317
  } : ecdsaOpts.bits2int_modN;
1305
1318
  const ORDER_MASK = bitMask(fnBits);
1306
- function int2octets(num) {
1307
- aInRange("num < 2^" + fnBits, num, _0n2, ORDER_MASK);
1308
- return Fn.toBytes(num);
1319
+ function int2octets(num2) {
1320
+ aInRange("num < 2^" + fnBits, num2, _0n2, ORDER_MASK);
1321
+ return Fn.toBytes(num2);
1309
1322
  }
1310
1323
  function validateMsgAndHash(message, prehash) {
1311
1324
  abytes2(message, void 0, "message");
@@ -1320,7 +1333,7 @@ function ecdsa(Point2, hash, ecdsaOpts = {}) {
1320
1333
  throw new Error("invalid private key");
1321
1334
  const seedArgs = [int2octets(d), int2octets(h1int)];
1322
1335
  if (extraEntropy != null && extraEntropy !== false) {
1323
- const e = extraEntropy === true ? randomBytes3(lengths.secretKey) : extraEntropy;
1336
+ const e = extraEntropy === true ? randomBytes4(lengths.secretKey) : extraEntropy;
1324
1337
  seedArgs.push(abytes2(e, void 0, "extraEntropy"));
1325
1338
  }
1326
1339
  const seed = concatBytes(...seedArgs);
@@ -1418,6 +1431,7 @@ var secp256k1_ENDO = {
1418
1431
  [BigInt("0x114ca50f7a8e2f3f657c1108d9d44cfd8"), BigInt("0x3086d221a7d46bcde86c90e49284eb15")]
1419
1432
  ]
1420
1433
  };
1434
+ var _0n3 = /* @__PURE__ */ BigInt(0);
1421
1435
  var _2n3 = /* @__PURE__ */ BigInt(2);
1422
1436
  function sqrtMod(y) {
1423
1437
  const P = secp256k1_CURVE.p;
@@ -1447,8 +1461,119 @@ var Pointk1 = /* @__PURE__ */ weierstrass(secp256k1_CURVE, {
1447
1461
  endo: secp256k1_ENDO
1448
1462
  });
1449
1463
  var secp256k1 = /* @__PURE__ */ ecdsa(Pointk1, sha256);
1464
+ var TAGGED_HASH_PREFIXES = {};
1465
+ function taggedHash(tag, ...messages) {
1466
+ let tagP = TAGGED_HASH_PREFIXES[tag];
1467
+ if (tagP === void 0) {
1468
+ const tagH = sha256(asciiToBytes(tag));
1469
+ tagP = concatBytes(tagH, tagH);
1470
+ TAGGED_HASH_PREFIXES[tag] = tagP;
1471
+ }
1472
+ return sha256(concatBytes(tagP, ...messages));
1473
+ }
1474
+ var pointToBytes = (point) => point.toBytes(true).slice(1);
1475
+ var hasEven = (y) => y % _2n3 === _0n3;
1476
+ function schnorrGetExtPubKey(priv) {
1477
+ const { Fn, BASE } = Pointk1;
1478
+ const d_ = Fn.fromBytes(priv);
1479
+ const p = BASE.multiply(d_);
1480
+ const scalar = hasEven(p.y) ? d_ : Fn.neg(d_);
1481
+ return { scalar, bytes: pointToBytes(p) };
1482
+ }
1483
+ function lift_x(x) {
1484
+ const Fp = Fpk1;
1485
+ if (!Fp.isValidNot0(x))
1486
+ throw new Error("invalid x: Fail if x \u2265 p");
1487
+ const xx = Fp.create(x * x);
1488
+ const c = Fp.create(xx * x + BigInt(7));
1489
+ let y = Fp.sqrt(c);
1490
+ if (!hasEven(y))
1491
+ y = Fp.neg(y);
1492
+ const p = Pointk1.fromAffine({ x, y });
1493
+ p.assertValidity();
1494
+ return p;
1495
+ }
1496
+ var num = bytesToNumberBE;
1497
+ function challenge(...args) {
1498
+ return Pointk1.Fn.create(num(taggedHash("BIP0340/challenge", ...args)));
1499
+ }
1500
+ function schnorrGetPublicKey(secretKey) {
1501
+ return schnorrGetExtPubKey(secretKey).bytes;
1502
+ }
1503
+ function schnorrSign(message, secretKey, auxRand = randomBytes(32)) {
1504
+ const { Fn, BASE } = Pointk1;
1505
+ const m = abytes2(message, void 0, "message");
1506
+ const { bytes: px, scalar: d } = schnorrGetExtPubKey(secretKey);
1507
+ const a = abytes2(auxRand, 32, "auxRand");
1508
+ const t = Fn.toBytes(d ^ num(taggedHash("BIP0340/aux", a)));
1509
+ const rand = taggedHash("BIP0340/nonce", t, px, m);
1510
+ const k_ = Fn.create(num(rand));
1511
+ if (k_ === 0n)
1512
+ throw new Error("sign failed: k is zero");
1513
+ const p = BASE.multiply(k_);
1514
+ const k = hasEven(p.y) ? k_ : Fn.neg(k_);
1515
+ const rx = pointToBytes(p);
1516
+ const e = challenge(rx, px, m);
1517
+ const sig = new Uint8Array(64);
1518
+ sig.set(rx, 0);
1519
+ sig.set(Fn.toBytes(Fn.create(k + e * d)), 32);
1520
+ if (!schnorrVerify(sig, m, px))
1521
+ throw new Error("sign: Invalid signature produced");
1522
+ return sig;
1523
+ }
1524
+ function schnorrVerify(signature, message, publicKey) {
1525
+ const { Fp, Fn, BASE } = Pointk1;
1526
+ const sig = abytes2(signature, 64, "signature");
1527
+ const m = abytes2(message, void 0, "message");
1528
+ const pub = abytes2(publicKey, 32, "publicKey");
1529
+ try {
1530
+ const P = lift_x(num(pub));
1531
+ const r = num(sig.subarray(0, 32));
1532
+ if (!Fp.isValidNot0(r))
1533
+ return false;
1534
+ const s = num(sig.subarray(32, 64));
1535
+ if (!Fn.isValidNot0(s))
1536
+ return false;
1537
+ const e = challenge(Fn.toBytes(r), pointToBytes(P), m);
1538
+ const R = BASE.multiplyUnsafe(s).add(P.multiplyUnsafe(Fn.neg(e)));
1539
+ const { x, y } = R.toAffine();
1540
+ if (R.is0() || !hasEven(y) || x !== r)
1541
+ return false;
1542
+ return true;
1543
+ } catch (error) {
1544
+ return false;
1545
+ }
1546
+ }
1547
+ var schnorr = /* @__PURE__ */ (() => {
1548
+ const size = 32;
1549
+ const seedLength = 48;
1550
+ const randomSecretKey = (seed) => {
1551
+ seed = seed === void 0 ? randomBytes(seedLength) : seed;
1552
+ return mapHashToField(seed, secp256k1_CURVE.n);
1553
+ };
1554
+ return Object.freeze({
1555
+ keygen: createKeygen(randomSecretKey, schnorrGetPublicKey),
1556
+ getPublicKey: schnorrGetPublicKey,
1557
+ sign: schnorrSign,
1558
+ verify: schnorrVerify,
1559
+ Point: Pointk1,
1560
+ utils: Object.freeze({
1561
+ randomSecretKey,
1562
+ taggedHash,
1563
+ lift_x,
1564
+ pointToBytes
1565
+ }),
1566
+ lengths: Object.freeze({
1567
+ secretKey: size,
1568
+ publicKey: size,
1569
+ publicKeyHasPrefix: false,
1570
+ signature: size * 2,
1571
+ seed: seedLength
1572
+ })
1573
+ });
1574
+ })();
1450
1575
 
1451
- // ../../node_modules/.pnpm/@toon-protocol+core@2.1.0_typescript@5.9.3/node_modules/@toon-protocol/core/dist/index.js
1576
+ // ../../node_modules/.pnpm/@toon-protocol+core@3.0.0_typescript@5.9.3/node_modules/@toon-protocol/core/dist/index.js
1452
1577
  import { getPublicKey as getPublicKey5 } from "nostr-tools/pure";
1453
1578
  var ILP_PEER_INFO_KIND = 10032;
1454
1579
  var BLOB_STORAGE_REQUEST_KIND = 5094;
@@ -2152,15 +2277,71 @@ function concatBytes3(...parts) {
2152
2277
  }
2153
2278
  return out;
2154
2279
  }
2155
- function balanceProofHashEvm(channelIdBytes, cumulativeAmount, nonce, recipientBytes) {
2280
+ var EIP712_PREFIX = new Uint8Array([25, 1]);
2281
+ var EIP712DOMAIN_TYPEHASH = keccak_256(
2282
+ new TextEncoder().encode(
2283
+ "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
2284
+ )
2285
+ );
2286
+ var DOMAIN_NAME_HASH = keccak_256(new TextEncoder().encode("RollingSwapChannel"));
2287
+ var DOMAIN_VERSION_HASH = keccak_256(new TextEncoder().encode("2"));
2288
+ var CLAIM_TYPEHASH = keccak_256(
2289
+ new TextEncoder().encode(
2290
+ "ClaimBalanceProof(bytes32 channelId,uint256 cumulativeAmount,uint256 nonce,address recipient)"
2291
+ )
2292
+ );
2293
+ var COOP_CLOSE_TYPEHASH = keccak_256(
2294
+ new TextEncoder().encode(
2295
+ "CooperativeClose(bytes32 channelId,uint256 cumulativeAmount,uint256 nonce)"
2296
+ )
2297
+ );
2298
+ function leftPad32(bytes) {
2299
+ if (bytes.length > 32) {
2300
+ throw new Error(`cannot left-pad ${bytes.length} bytes into 32`);
2301
+ }
2302
+ const out = new Uint8Array(32);
2303
+ out.set(bytes, 32 - bytes.length);
2304
+ return out;
2305
+ }
2306
+ function eip712DomainSeparatorEvm(chainId, verifyingContractBytes) {
2307
+ if (verifyingContractBytes.length !== 20) {
2308
+ throw new Error(
2309
+ `verifyingContract must be 20 bytes (got ${verifyingContractBytes.length})`
2310
+ );
2311
+ }
2156
2312
  return keccak_256(
2157
2313
  concatBytes3(
2314
+ EIP712DOMAIN_TYPEHASH,
2315
+ DOMAIN_NAME_HASH,
2316
+ DOMAIN_VERSION_HASH,
2317
+ bigintToBytes32BE(chainId),
2318
+ leftPad32(verifyingContractBytes)
2319
+ )
2320
+ );
2321
+ }
2322
+ function eip712Digest(domainSeparator, structHash) {
2323
+ return keccak_256(concatBytes3(EIP712_PREFIX, domainSeparator, structHash));
2324
+ }
2325
+ function balanceProofHashEvm(channelIdBytes, cumulativeAmount, nonce, recipientBytes, chainId, verifyingContractBytes) {
2326
+ if (channelIdBytes.length !== 32) {
2327
+ throw new Error(`channelId must be 32 bytes (got ${channelIdBytes.length})`);
2328
+ }
2329
+ if (recipientBytes.length !== 20) {
2330
+ throw new Error(`recipient must be 20 bytes (got ${recipientBytes.length})`);
2331
+ }
2332
+ const structHash = keccak_256(
2333
+ concatBytes3(
2334
+ CLAIM_TYPEHASH,
2158
2335
  channelIdBytes,
2159
2336
  bigintToBytes32BE(cumulativeAmount),
2160
2337
  bigintToBytes32BE(nonce),
2161
- recipientBytes
2338
+ leftPad32(recipientBytes)
2162
2339
  )
2163
2340
  );
2341
+ return eip712Digest(
2342
+ eip712DomainSeparatorEvm(chainId, verifyingContractBytes),
2343
+ structHash
2344
+ );
2164
2345
  }
2165
2346
  function balanceProofHashSolana(channelId, cumulativeAmount, nonce, recipient) {
2166
2347
  return sha256(
@@ -3407,7 +3588,7 @@ function generateMnemonic(wordlist2, strength = 128) {
3407
3588
  anumber2(strength);
3408
3589
  if (strength % 32 !== 0 || strength > 256)
3409
3590
  throw new TypeError("Invalid entropy");
3410
- return entropyToMnemonic(randomBytes2(strength / 8), wordlist2);
3591
+ return entropyToMnemonic(randomBytes3(strength / 8), wordlist2);
3411
3592
  }
3412
3593
  var calcChecksum = (entropy) => {
3413
3594
  const bitsLeft = 8 - entropy.length / 4;
@@ -5497,7 +5678,7 @@ zone
5497
5678
  zoo`.split("\n");
5498
5679
 
5499
5680
  // ../../node_modules/.pnpm/@noble+curves@1.9.7/node_modules/@noble/curves/esm/utils.js
5500
- var _0n3 = /* @__PURE__ */ BigInt(0);
5681
+ var _0n4 = /* @__PURE__ */ BigInt(0);
5501
5682
  var _1n3 = /* @__PURE__ */ BigInt(1);
5502
5683
  function _abool2(value, title = "") {
5503
5684
  if (typeof value !== "boolean") {
@@ -5518,14 +5699,14 @@ function _abytes2(value, length, title = "") {
5518
5699
  }
5519
5700
  return value;
5520
5701
  }
5521
- function numberToHexUnpadded2(num) {
5522
- const hex = num.toString(16);
5702
+ function numberToHexUnpadded2(num2) {
5703
+ const hex = num2.toString(16);
5523
5704
  return hex.length & 1 ? "0" + hex : hex;
5524
5705
  }
5525
5706
  function hexToNumber(hex) {
5526
5707
  if (typeof hex !== "string")
5527
5708
  throw new Error("hex string expected, got " + typeof hex);
5528
- return hex === "" ? _0n3 : BigInt("0x" + hex);
5709
+ return hex === "" ? _0n4 : BigInt("0x" + hex);
5529
5710
  }
5530
5711
  function bytesToNumberBE2(bytes) {
5531
5712
  return hexToNumber(bytesToHex3(bytes));
@@ -5558,7 +5739,7 @@ function ensureBytes(title, hex, expectedLength) {
5558
5739
  throw new Error(title + " of length " + expectedLength + " expected, got " + len);
5559
5740
  return res;
5560
5741
  }
5561
- var isPosBig = (n) => typeof n === "bigint" && _0n3 <= n;
5742
+ var isPosBig = (n) => typeof n === "bigint" && _0n4 <= n;
5562
5743
  function inRange(n, min, max) {
5563
5744
  return isPosBig(n) && isPosBig(min) && isPosBig(max) && min <= n && n < max;
5564
5745
  }
@@ -5568,7 +5749,7 @@ function aInRange2(title, n, min, max) {
5568
5749
  }
5569
5750
  function bitLen2(n) {
5570
5751
  let len;
5571
- for (len = 0; n > _0n3; n >>= _1n3, len += 1)
5752
+ for (len = 0; n > _0n4; n >>= _1n3, len += 1)
5572
5753
  ;
5573
5754
  return len;
5574
5755
  }
@@ -5599,7 +5780,7 @@ function createHmacDrbg2(hashLen, qByteLen, hmacFn) {
5599
5780
  k = h(u8of(1), seed);
5600
5781
  v = h();
5601
5782
  };
5602
- const gen = () => {
5783
+ const gen2 = () => {
5603
5784
  if (i++ >= 1e3)
5604
5785
  throw new Error("drbg: tried 1000 values");
5605
5786
  let len = 0;
@@ -5616,7 +5797,7 @@ function createHmacDrbg2(hashLen, qByteLen, hmacFn) {
5616
5797
  reset();
5617
5798
  reseed(seed);
5618
5799
  let res = void 0;
5619
- while (!(res = pred(gen())))
5800
+ while (!(res = pred(gen2())))
5620
5801
  reseed();
5621
5802
  reset();
5622
5803
  return res;
@@ -5650,7 +5831,7 @@ function memoized(fn) {
5650
5831
  }
5651
5832
 
5652
5833
  // ../../node_modules/.pnpm/@noble+curves@1.9.7/node_modules/@noble/curves/esm/abstract/modular.js
5653
- var _0n4 = BigInt(0);
5834
+ var _0n5 = BigInt(0);
5654
5835
  var _1n4 = BigInt(1);
5655
5836
  var _2n4 = /* @__PURE__ */ BigInt(2);
5656
5837
  var _3n2 = /* @__PURE__ */ BigInt(3);
@@ -5662,25 +5843,25 @@ var _9n = /* @__PURE__ */ BigInt(9);
5662
5843
  var _16n = /* @__PURE__ */ BigInt(16);
5663
5844
  function mod(a, b) {
5664
5845
  const result = a % b;
5665
- return result >= _0n4 ? result : b + result;
5846
+ return result >= _0n5 ? result : b + result;
5666
5847
  }
5667
5848
  function pow22(x, power, modulo) {
5668
5849
  let res = x;
5669
- while (power-- > _0n4) {
5850
+ while (power-- > _0n5) {
5670
5851
  res *= res;
5671
5852
  res %= modulo;
5672
5853
  }
5673
5854
  return res;
5674
5855
  }
5675
5856
  function invert(number, modulo) {
5676
- if (number === _0n4)
5857
+ if (number === _0n5)
5677
5858
  throw new Error("invert: expected non-zero number");
5678
- if (modulo <= _0n4)
5859
+ if (modulo <= _0n5)
5679
5860
  throw new Error("invert: expected positive modulus, got " + modulo);
5680
5861
  let a = mod(number, modulo);
5681
5862
  let b = modulo;
5682
- let x = _0n4, y = _1n4, u = _1n4, v = _0n4;
5683
- while (a !== _0n4) {
5863
+ let x = _0n5, y = _1n4, u = _1n4, v = _0n5;
5864
+ while (a !== _0n5) {
5684
5865
  const q = b / a;
5685
5866
  const r = b % a;
5686
5867
  const m = x - u * q;
@@ -5739,7 +5920,7 @@ function tonelliShanks(P) {
5739
5920
  throw new Error("sqrt is not defined for small field");
5740
5921
  let Q = P - _1n4;
5741
5922
  let S = 0;
5742
- while (Q % _2n4 === _0n4) {
5923
+ while (Q % _2n4 === _0n5) {
5743
5924
  Q /= _2n4;
5744
5925
  S++;
5745
5926
  }
@@ -5825,16 +6006,16 @@ function validateField2(field) {
5825
6006
  _validateObject(field, opts);
5826
6007
  return field;
5827
6008
  }
5828
- function FpPow(Fp, num, power) {
5829
- if (power < _0n4)
6009
+ function FpPow(Fp, num2, power) {
6010
+ if (power < _0n5)
5830
6011
  throw new Error("invalid exponent, negatives unsupported");
5831
- if (power === _0n4)
6012
+ if (power === _0n5)
5832
6013
  return Fp.ONE;
5833
6014
  if (power === _1n4)
5834
- return num;
6015
+ return num2;
5835
6016
  let p = Fp.ONE;
5836
- let d = num;
5837
- while (power > _0n4) {
6017
+ let d = num2;
6018
+ while (power > _0n5) {
5838
6019
  if (power & _1n4)
5839
6020
  p = Fp.mul(p, d);
5840
6021
  d = Fp.sqr(d);
@@ -5844,18 +6025,18 @@ function FpPow(Fp, num, power) {
5844
6025
  }
5845
6026
  function FpInvertBatch2(Fp, nums, passZero = false) {
5846
6027
  const inverted = new Array(nums.length).fill(passZero ? Fp.ZERO : void 0);
5847
- const multipliedAcc = nums.reduce((acc, num, i) => {
5848
- if (Fp.is0(num))
6028
+ const multipliedAcc = nums.reduce((acc, num2, i) => {
6029
+ if (Fp.is0(num2))
5849
6030
  return acc;
5850
6031
  inverted[i] = acc;
5851
- return Fp.mul(acc, num);
6032
+ return Fp.mul(acc, num2);
5852
6033
  }, Fp.ONE);
5853
6034
  const invertedAcc = Fp.inv(multipliedAcc);
5854
- nums.reduceRight((acc, num, i) => {
5855
- if (Fp.is0(num))
6035
+ nums.reduceRight((acc, num2, i) => {
6036
+ if (Fp.is0(num2))
5856
6037
  return acc;
5857
6038
  inverted[i] = Fp.mul(acc, inverted[i]);
5858
- return Fp.mul(acc, num);
6039
+ return Fp.mul(acc, num2);
5859
6040
  }, invertedAcc);
5860
6041
  return inverted;
5861
6042
  }
@@ -5877,7 +6058,7 @@ function nLength(n, nBitLength) {
5877
6058
  return { nBitLength: _nBitLength, nByteLength };
5878
6059
  }
5879
6060
  function Field2(ORDER, bitLenOrOpts, isLE = false, opts = {}) {
5880
- if (ORDER <= _0n4)
6061
+ if (ORDER <= _0n5)
5881
6062
  throw new Error("invalid field: expected ORDER > 0, got " + ORDER);
5882
6063
  let _nbitLength = void 0;
5883
6064
  let _sqrt = void 0;
@@ -5912,39 +6093,39 @@ function Field2(ORDER, bitLenOrOpts, isLE = false, opts = {}) {
5912
6093
  BITS,
5913
6094
  BYTES,
5914
6095
  MASK: bitMask2(BITS),
5915
- ZERO: _0n4,
6096
+ ZERO: _0n5,
5916
6097
  ONE: _1n4,
5917
6098
  allowedLengths,
5918
- create: (num) => mod(num, ORDER),
5919
- isValid: (num) => {
5920
- if (typeof num !== "bigint")
5921
- throw new Error("invalid field element: expected bigint, got " + typeof num);
5922
- return _0n4 <= num && num < ORDER;
6099
+ create: (num2) => mod(num2, ORDER),
6100
+ isValid: (num2) => {
6101
+ if (typeof num2 !== "bigint")
6102
+ throw new Error("invalid field element: expected bigint, got " + typeof num2);
6103
+ return _0n5 <= num2 && num2 < ORDER;
5923
6104
  },
5924
- is0: (num) => num === _0n4,
6105
+ is0: (num2) => num2 === _0n5,
5925
6106
  // is valid and invertible
5926
- isValidNot0: (num) => !f.is0(num) && f.isValid(num),
5927
- isOdd: (num) => (num & _1n4) === _1n4,
5928
- neg: (num) => mod(-num, ORDER),
6107
+ isValidNot0: (num2) => !f.is0(num2) && f.isValid(num2),
6108
+ isOdd: (num2) => (num2 & _1n4) === _1n4,
6109
+ neg: (num2) => mod(-num2, ORDER),
5929
6110
  eql: (lhs, rhs) => lhs === rhs,
5930
- sqr: (num) => mod(num * num, ORDER),
6111
+ sqr: (num2) => mod(num2 * num2, ORDER),
5931
6112
  add: (lhs, rhs) => mod(lhs + rhs, ORDER),
5932
6113
  sub: (lhs, rhs) => mod(lhs - rhs, ORDER),
5933
6114
  mul: (lhs, rhs) => mod(lhs * rhs, ORDER),
5934
- pow: (num, power) => FpPow(f, num, power),
6115
+ pow: (num2, power) => FpPow(f, num2, power),
5935
6116
  div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER),
5936
6117
  // Same as above, but doesn't normalize
5937
- sqrN: (num) => num * num,
6118
+ sqrN: (num2) => num2 * num2,
5938
6119
  addN: (lhs, rhs) => lhs + rhs,
5939
6120
  subN: (lhs, rhs) => lhs - rhs,
5940
6121
  mulN: (lhs, rhs) => lhs * rhs,
5941
- inv: (num) => invert(num, ORDER),
6122
+ inv: (num2) => invert(num2, ORDER),
5942
6123
  sqrt: _sqrt || ((n) => {
5943
6124
  if (!sqrtP)
5944
6125
  sqrtP = FpSqrt(ORDER);
5945
6126
  return sqrtP(f, n);
5946
6127
  }),
5947
- toBytes: (num) => isLE ? numberToBytesLE(num, BYTES) : numberToBytesBE(num, BYTES),
6128
+ toBytes: (num2) => isLE ? numberToBytesLE(num2, BYTES) : numberToBytesBE(num2, BYTES),
5948
6129
  fromBytes: (bytes, skipValidation = true) => {
5949
6130
  if (allowedLengths) {
5950
6131
  if (!allowedLengths.includes(bytes.length) || bytes.length > BYTES) {
@@ -5989,13 +6170,13 @@ function mapHashToField2(key2, fieldOrder, isLE = false) {
5989
6170
  const minLen = getMinHashLength2(fieldOrder);
5990
6171
  if (len < 16 || len < minLen || len > 1024)
5991
6172
  throw new Error("expected " + minLen + "-1024 bytes of input, got " + len);
5992
- const num = isLE ? bytesToNumberLE(key2) : bytesToNumberBE2(key2);
5993
- const reduced = mod(num, fieldOrder - _1n4) + _1n4;
6173
+ const num2 = isLE ? bytesToNumberLE(key2) : bytesToNumberBE2(key2);
6174
+ const reduced = mod(num2, fieldOrder - _1n4) + _1n4;
5994
6175
  return isLE ? numberToBytesLE(reduced, fieldLen) : numberToBytesBE(reduced, fieldLen);
5995
6176
  }
5996
6177
 
5997
6178
  // ../../node_modules/.pnpm/@noble+curves@1.9.7/node_modules/@noble/curves/esm/abstract/curve.js
5998
- var _0n5 = BigInt(0);
6179
+ var _0n6 = BigInt(0);
5999
6180
  var _1n5 = BigInt(1);
6000
6181
  function negateCt2(condition, item) {
6001
6182
  const neg = item.negate();
@@ -6056,7 +6237,7 @@ function getW(P) {
6056
6237
  return pointWindowSizes.get(P) || 1;
6057
6238
  }
6058
6239
  function assert0(n) {
6059
- if (n !== _0n5)
6240
+ if (n !== _0n6)
6060
6241
  throw new Error("invalid wNAF");
6061
6242
  }
6062
6243
  var wNAF2 = class {
@@ -6070,7 +6251,7 @@ var wNAF2 = class {
6070
6251
  // non-const time multiplication ladder
6071
6252
  _unsafeLadder(elm, n, p = this.ZERO) {
6072
6253
  let d = elm;
6073
- while (n > _0n5) {
6254
+ while (n > _0n6) {
6074
6255
  if (n & _1n5)
6075
6256
  p = p.add(d);
6076
6257
  d = d.double();
@@ -6138,7 +6319,7 @@ var wNAF2 = class {
6138
6319
  wNAFUnsafe(W, precomputes, n, acc = this.ZERO) {
6139
6320
  const wo = calcWOpts(W, this.bits);
6140
6321
  for (let window2 = 0; window2 < wo.windows; window2++) {
6141
- if (n === _0n5)
6322
+ if (n === _0n6)
6142
6323
  break;
6143
6324
  const { nextN, offset, isZero, isNeg } = calcOffsets(n, window2, wo);
6144
6325
  n = nextN;
@@ -6190,7 +6371,7 @@ function mulEndoUnsafe2(Point2, point, k1, k2) {
6190
6371
  let acc = point;
6191
6372
  let p1 = Point2.ZERO;
6192
6373
  let p2 = Point2.ZERO;
6193
- while (k1 > _0n5 || k2 > _0n5) {
6374
+ while (k1 > _0n6 || k2 > _0n6) {
6194
6375
  if (k1 & _1n5)
6195
6376
  p1 = p1.add(acc);
6196
6377
  if (k2 & _1n5)
@@ -6257,7 +6438,7 @@ function _createCurveFields(type, CURVE, curveOpts = {}, FpFnLE) {
6257
6438
  throw new Error(`expected valid ${type} CURVE object`);
6258
6439
  for (const p of ["p", "n", "h"]) {
6259
6440
  const val = CURVE[p];
6260
- if (!(typeof val === "bigint" && val > _0n5))
6441
+ if (!(typeof val === "bigint" && val > _0n6))
6261
6442
  throw new Error(`CURVE.${p} must be positive bigint`);
6262
6443
  }
6263
6444
  const Fp = createField(CURVE.p, curveOpts.Fp, FpFnLE);
@@ -6273,21 +6454,21 @@ function _createCurveFields(type, CURVE, curveOpts = {}, FpFnLE) {
6273
6454
  }
6274
6455
 
6275
6456
  // ../../node_modules/.pnpm/@noble+curves@1.9.7/node_modules/@noble/curves/esm/abstract/weierstrass.js
6276
- var divNearest2 = (num, den) => (num + (num >= 0 ? den : -den) / _2n5) / den;
6457
+ var divNearest2 = (num2, den) => (num2 + (num2 >= 0 ? den : -den) / _2n5) / den;
6277
6458
  function _splitEndoScalar2(k, basis, n) {
6278
6459
  const [[a1, b1], [a2, b2]] = basis;
6279
6460
  const c1 = divNearest2(b2 * k, n);
6280
6461
  const c2 = divNearest2(-b1 * k, n);
6281
6462
  let k1 = k - c1 * a1 - c2 * a2;
6282
6463
  let k2 = -c1 * b1 - c2 * b2;
6283
- const k1neg = k1 < _0n6;
6284
- const k2neg = k2 < _0n6;
6464
+ const k1neg = k1 < _0n7;
6465
+ const k2neg = k2 < _0n7;
6285
6466
  if (k1neg)
6286
6467
  k1 = -k1;
6287
6468
  if (k2neg)
6288
6469
  k2 = -k2;
6289
6470
  const MAX_NUM = bitMask2(Math.ceil(bitLen2(n) / 2)) + _1n6;
6290
- if (k1 < _0n6 || k1 >= MAX_NUM || k2 < _0n6 || k2 >= MAX_NUM) {
6471
+ if (k1 < _0n7 || k1 >= MAX_NUM || k2 < _0n7 || k2 >= MAX_NUM) {
6291
6472
  throw new Error("splitScalar (endomorphism): failed, k=" + k);
6292
6473
  }
6293
6474
  return { k1neg, k1, k2neg, k2 };
@@ -6373,11 +6554,11 @@ var DER2 = {
6373
6554
  // - add zero byte if exists
6374
6555
  // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding)
6375
6556
  _int: {
6376
- encode(num) {
6557
+ encode(num2) {
6377
6558
  const { Err: E } = DER2;
6378
- if (num < _0n6)
6559
+ if (num2 < _0n7)
6379
6560
  throw new E("integer: negative integers are not allowed");
6380
- let hex = numberToHexUnpadded2(num);
6561
+ let hex = numberToHexUnpadded2(num2);
6381
6562
  if (Number.parseInt(hex[0], 16) & 8)
6382
6563
  hex = "00" + hex;
6383
6564
  if (hex.length & 1)
@@ -6413,27 +6594,27 @@ var DER2 = {
6413
6594
  return tlv.encode(48, seq);
6414
6595
  }
6415
6596
  };
6416
- var _0n6 = BigInt(0);
6597
+ var _0n7 = BigInt(0);
6417
6598
  var _1n6 = BigInt(1);
6418
6599
  var _2n5 = BigInt(2);
6419
6600
  var _3n3 = BigInt(3);
6420
6601
  var _4n3 = BigInt(4);
6421
6602
  function _normFnElement(Fn, key2) {
6422
6603
  const { BYTES: expected } = Fn;
6423
- let num;
6604
+ let num2;
6424
6605
  if (typeof key2 === "bigint") {
6425
- num = key2;
6606
+ num2 = key2;
6426
6607
  } else {
6427
6608
  let bytes = ensureBytes("private key", key2);
6428
6609
  try {
6429
- num = Fn.fromBytes(bytes);
6610
+ num2 = Fn.fromBytes(bytes);
6430
6611
  } catch (error) {
6431
6612
  throw new Error(`invalid private key: expected ui8a of size ${expected}, got ${typeof key2}`);
6432
6613
  }
6433
6614
  }
6434
- if (!Fn.isValidNot0(num))
6615
+ if (!Fn.isValidNot0(num2))
6435
6616
  throw new Error("invalid private key: out of range [1..N-1]");
6436
- return num;
6617
+ return num2;
6437
6618
  }
6438
6619
  function weierstrassN(params, extraOpts = {}) {
6439
6620
  const validated = _createCurveFields("weierstrass", params, extraOpts);
@@ -6460,7 +6641,7 @@ function weierstrassN(params, extraOpts = {}) {
6460
6641
  if (!Fp.isOdd)
6461
6642
  throw new Error("compression is not supported: Field does not have .isOdd()");
6462
6643
  }
6463
- function pointToBytes(_c, point, isCompressed) {
6644
+ function pointToBytes2(_c, point, isCompressed) {
6464
6645
  const { x, y } = point.toAffine();
6465
6646
  const bx = Fp.toBytes(x);
6466
6647
  _abool2(isCompressed, "isCompressed");
@@ -6507,7 +6688,7 @@ function weierstrassN(params, extraOpts = {}) {
6507
6688
  throw new Error(`bad point: got length ${length}, expected compressed=${comp} or uncompressed=${uncomp}`);
6508
6689
  }
6509
6690
  }
6510
- const encodePoint = extraOpts.toBytes || pointToBytes;
6691
+ const encodePoint = extraOpts.toBytes || pointToBytes2;
6511
6692
  const decodePoint = extraOpts.fromBytes || pointFromBytes;
6512
6693
  function weierstrassEquation(x) {
6513
6694
  const x2 = Fp.sqr(x);
@@ -6787,7 +6968,7 @@ function weierstrassN(params, extraOpts = {}) {
6787
6968
  const p = this;
6788
6969
  if (!Fn.isValid(sc))
6789
6970
  throw new Error("invalid scalar: out of range");
6790
- if (sc === _0n6 || p.is0())
6971
+ if (sc === _0n7 || p.is0())
6791
6972
  return Point2.ZERO;
6792
6973
  if (sc === _1n6)
6793
6974
  return p;
@@ -6895,7 +7076,7 @@ function getWLengths2(Fp, Fn) {
6895
7076
  }
6896
7077
  function ecdh2(Point2, ecdhOpts = {}) {
6897
7078
  const { Fn } = Point2;
6898
- const randomBytes_ = ecdhOpts.randomBytes || randomBytes2;
7079
+ const randomBytes_ = ecdhOpts.randomBytes || randomBytes3;
6899
7080
  const lengths = Object.assign(getWLengths2(Point2.Fp, Fn), { seed: getMinHashLength2(Fn.ORDER) });
6900
7081
  function isValidSecretKey(secretKey) {
6901
7082
  try {
@@ -6970,7 +7151,7 @@ function ecdsa2(Point2, hash, ecdsaOpts = {}) {
6970
7151
  bits2int: "function",
6971
7152
  bits2int_modN: "function"
6972
7153
  });
6973
- const randomBytes3 = ecdsaOpts.randomBytes || randomBytes2;
7154
+ const randomBytes4 = ecdsaOpts.randomBytes || randomBytes3;
6974
7155
  const hmac3 = ecdsaOpts.hmac || ((key2, ...msgs) => hmac(hash, key2, concatBytes2(...msgs)));
6975
7156
  const { Fp, Fn } = Point2;
6976
7157
  const { ORDER: CURVE_ORDER, BITS: fnBits } = Fn;
@@ -6987,10 +7168,10 @@ function ecdsa2(Point2, hash, ecdsaOpts = {}) {
6987
7168
  const HALF = CURVE_ORDER >> _1n6;
6988
7169
  return number > HALF;
6989
7170
  }
6990
- function validateRS(title, num) {
6991
- if (!Fn.isValidNot0(num))
7171
+ function validateRS(title, num2) {
7172
+ if (!Fn.isValidNot0(num2))
6992
7173
  throw new Error(`invalid signature ${title}: out of range 1..Point.Fn.ORDER`);
6993
- return num;
7174
+ return num2;
6994
7175
  }
6995
7176
  function validateSigLength(bytes, format) {
6996
7177
  validateSigFormat2(format);
@@ -7100,17 +7281,17 @@ function ecdsa2(Point2, hash, ecdsaOpts = {}) {
7100
7281
  const bits2int = ecdsaOpts.bits2int || function bits2int_def(bytes) {
7101
7282
  if (bytes.length > 8192)
7102
7283
  throw new Error("input is too large");
7103
- const num = bytesToNumberBE2(bytes);
7284
+ const num2 = bytesToNumberBE2(bytes);
7104
7285
  const delta = bytes.length * 8 - fnBits;
7105
- return delta > 0 ? num >> BigInt(delta) : num;
7286
+ return delta > 0 ? num2 >> BigInt(delta) : num2;
7106
7287
  };
7107
7288
  const bits2int_modN = ecdsaOpts.bits2int_modN || function bits2int_modN_def(bytes) {
7108
7289
  return Fn.create(bits2int(bytes));
7109
7290
  };
7110
7291
  const ORDER_MASK = bitMask2(fnBits);
7111
- function int2octets(num) {
7112
- aInRange2("num < 2^" + fnBits, num, _0n6, ORDER_MASK);
7113
- return Fn.toBytes(num);
7292
+ function int2octets(num2) {
7293
+ aInRange2("num < 2^" + fnBits, num2, _0n7, ORDER_MASK);
7294
+ return Fn.toBytes(num2);
7114
7295
  }
7115
7296
  function validateMsgAndHash(message, prehash) {
7116
7297
  _abytes2(message, void 0, "message");
@@ -7125,7 +7306,7 @@ function ecdsa2(Point2, hash, ecdsaOpts = {}) {
7125
7306
  const d = _normFnElement(Fn, privateKey);
7126
7307
  const seedArgs = [int2octets(d), int2octets(h1int)];
7127
7308
  if (extraEntropy != null && extraEntropy !== false) {
7128
- const e = extraEntropy === true ? randomBytes3(lengths.secretKey) : extraEntropy;
7309
+ const e = extraEntropy === true ? randomBytes4(lengths.secretKey) : extraEntropy;
7129
7310
  seedArgs.push(ensureBytes("extraEntropy", e));
7130
7311
  }
7131
7312
  const seed = concatBytes2(...seedArgs);
@@ -7137,10 +7318,10 @@ function ecdsa2(Point2, hash, ecdsaOpts = {}) {
7137
7318
  const ik = Fn.inv(k);
7138
7319
  const q = Point2.BASE.multiply(k).toAffine();
7139
7320
  const r = Fn.create(q.x);
7140
- if (r === _0n6)
7321
+ if (r === _0n7)
7141
7322
  return;
7142
7323
  const s = Fn.create(ik * Fn.create(m + r * d));
7143
- if (s === _0n6)
7324
+ if (s === _0n7)
7144
7325
  return;
7145
7326
  let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n6);
7146
7327
  let normS = s;
@@ -7461,10 +7642,10 @@ function bytesToNumber(bytes) {
7461
7642
  const h = bytes.length === 0 ? "0" : bytesToHex3(bytes);
7462
7643
  return BigInt("0x" + h);
7463
7644
  }
7464
- function numberToBytes(num) {
7465
- if (typeof num !== "bigint")
7645
+ function numberToBytes(num2) {
7646
+ if (typeof num2 !== "bigint")
7466
7647
  throw new Error("bigint expected");
7467
- return hexToBytes3(num.toString(16).padStart(64, "0"));
7648
+ return hexToBytes3(num2.toString(16).padStart(64, "0"));
7468
7649
  }
7469
7650
  var MASTER_SECRET = utf8ToBytes("Bitcoin seed");
7470
7651
  var BITCOIN_VERSIONS = { private: 76066276, public: 76067358 };
@@ -7712,7 +7893,7 @@ import { toHex as toHex3 } from "viem";
7712
7893
  import { readFileSync, writeFileSync, existsSync } from "fs";
7713
7894
  import { createPublicClient as createPublicClient2, http as http2, defineChain as defineChain2 } from "viem";
7714
7895
 
7715
- // ../../node_modules/.pnpm/@toon-protocol+sdk@2.1.0_mina-signer@3.1.0_typescript@5.9.3/node_modules/@toon-protocol/sdk/dist/chunk-7LBYFU4L.js
7896
+ // ../../node_modules/.pnpm/@toon-protocol+sdk@3.0.0_mina-signer@3.1.0_typescript@5.9.3/node_modules/@toon-protocol/sdk/dist/chunk-RAZRWSJF.js
7716
7897
  import { getPublicKey as getPublicKey6 } from "nostr-tools/pure";
7717
7898
  import { generateSecretKey, getPublicKey as getPublicKey22 } from "nostr-tools/pure";
7718
7899
  import { createRumor, createSeal, createWrap } from "nostr-tools/nip59";
@@ -7874,10 +8055,218 @@ function decryptFulfillClaim(params) {
7874
8055
  }
7875
8056
  }
7876
8057
  }
8058
+ var STREAM_RECEIPT_VERSION = 1;
8059
+ var STREAM_RECEIPT_SIGNING_TAG = "toon.stream-receipt.v1";
8060
+ var STREAM_NONCE_REGEX = /^[0-9a-f]{32}$/;
8061
+ var SIG_REGEX = /^[0-9a-f]{128}$/;
8062
+ var HEX64_REGEX = /^[0-9a-f]{64}$/;
8063
+ var DECIMAL_UINT_REGEX = /^(0|[1-9]\d*)$/;
7877
8064
  var RATE_REGEX2 = /^(0|[1-9]\d*)(\.\d+)?$/;
8065
+ function isValidStreamNonce(value) {
8066
+ return typeof value === "string" && STREAM_NONCE_REGEX.test(value);
8067
+ }
8068
+ function parseStreamReceipt(value) {
8069
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
8070
+ throw new Error("receipt must be an object");
8071
+ }
8072
+ const obj = value;
8073
+ if (obj["v"] !== STREAM_RECEIPT_VERSION) {
8074
+ throw new Error(
8075
+ `receipt.v must be ${STREAM_RECEIPT_VERSION}, got ${String(obj["v"])}`
8076
+ );
8077
+ }
8078
+ if (!isValidStreamNonce(obj["streamNonce"])) {
8079
+ throw new Error("receipt.streamNonce must be 32-char lowercase hex");
8080
+ }
8081
+ const seq = obj["seq"];
8082
+ if (typeof seq !== "number" || !Number.isSafeInteger(seq) || seq < 1) {
8083
+ throw new Error("receipt.seq must be a positive safe integer");
8084
+ }
8085
+ const cumulativeDelivered = obj["cumulativeDelivered"];
8086
+ if (typeof cumulativeDelivered !== "string" || !DECIMAL_UINT_REGEX.test(cumulativeDelivered)) {
8087
+ throw new Error(
8088
+ "receipt.cumulativeDelivered must be a non-negative integer decimal string"
8089
+ );
8090
+ }
8091
+ const rate = obj["rate"];
8092
+ if (typeof rate !== "string" || !RATE_REGEX2.test(rate) || /^0(\.0+)?$/.test(rate)) {
8093
+ throw new Error("receipt.rate must be a positive decimal string");
8094
+ }
8095
+ const rateTimestamp = obj["rateTimestamp"];
8096
+ if (typeof rateTimestamp !== "number" || !Number.isInteger(rateTimestamp) || rateTimestamp <= 0) {
8097
+ throw new Error(
8098
+ "receipt.rateTimestamp must be a positive integer (unix ms)"
8099
+ );
8100
+ }
8101
+ const sig = obj["sig"];
8102
+ if (typeof sig !== "string" || !SIG_REGEX.test(sig)) {
8103
+ throw new Error("receipt.sig must be 128-char lowercase hex");
8104
+ }
8105
+ return {
8106
+ v: STREAM_RECEIPT_VERSION,
8107
+ streamNonce: obj["streamNonce"],
8108
+ seq,
8109
+ cumulativeDelivered,
8110
+ rate,
8111
+ rateTimestamp,
8112
+ sig
8113
+ };
8114
+ }
8115
+ function encodeReceiptSigningPayload(fields) {
8116
+ if (!isValidStreamNonce(fields.streamNonce)) {
8117
+ throw new Error("streamNonce must be 32-char lowercase hex");
8118
+ }
8119
+ const tag = Buffer.from(STREAM_RECEIPT_SIGNING_TAG, "utf8");
8120
+ const cumulative = Buffer.from(fields.cumulativeDelivered, "utf8");
8121
+ const rate = Buffer.from(fields.rate, "utf8");
8122
+ const buf = Buffer.alloc(
8123
+ 4 + tag.length + 1 + 16 + 8 + 4 + cumulative.length + 4 + rate.length + 8
8124
+ );
8125
+ let off = 0;
8126
+ buf.writeUInt32BE(tag.length, off);
8127
+ off += 4;
8128
+ tag.copy(buf, off);
8129
+ off += tag.length;
8130
+ buf.writeUInt8(fields.v, off);
8131
+ off += 1;
8132
+ Buffer.from(hexToBytes(fields.streamNonce)).copy(buf, off);
8133
+ off += 16;
8134
+ buf.writeBigUInt64BE(BigInt(fields.seq), off);
8135
+ off += 8;
8136
+ buf.writeUInt32BE(cumulative.length, off);
8137
+ off += 4;
8138
+ cumulative.copy(buf, off);
8139
+ off += cumulative.length;
8140
+ buf.writeUInt32BE(rate.length, off);
8141
+ off += 4;
8142
+ rate.copy(buf, off);
8143
+ off += rate.length;
8144
+ buf.writeBigUInt64BE(BigInt(fields.rateTimestamp), off);
8145
+ return new Uint8Array(buf);
8146
+ }
8147
+ function verifyStreamReceipt(receipt, makerPubkey) {
8148
+ if (typeof makerPubkey !== "string" || !HEX64_REGEX.test(makerPubkey)) {
8149
+ return false;
8150
+ }
8151
+ if (typeof receipt.sig !== "string" || !SIG_REGEX.test(receipt.sig)) {
8152
+ return false;
8153
+ }
8154
+ try {
8155
+ const { sig: _sig, ...fields } = receipt;
8156
+ const digest = sha256(encodeReceiptSigningPayload(fields));
8157
+ return schnorr.verify(
8158
+ hexToBytes(receipt.sig),
8159
+ digest,
8160
+ hexToBytes(makerPubkey)
8161
+ );
8162
+ } catch {
8163
+ return false;
8164
+ }
8165
+ }
8166
+ var ReceiptChainTracker = class {
8167
+ #streamNonce;
8168
+ #makerPubkey;
8169
+ /** Verified receipts, kept sorted by ascending seq. */
8170
+ #receipts = [];
8171
+ #seqs = /* @__PURE__ */ new Set();
8172
+ constructor(input) {
8173
+ if (!isValidStreamNonce(input.streamNonce)) {
8174
+ throw new Error("streamNonce must be 32-char lowercase hex");
8175
+ }
8176
+ if (typeof input.makerPubkey !== "string" || !HEX64_REGEX.test(input.makerPubkey)) {
8177
+ throw new Error("makerPubkey must be a 64-char lowercase hex string");
8178
+ }
8179
+ this.#streamNonce = input.streamNonce;
8180
+ this.#makerPubkey = input.makerPubkey;
8181
+ }
8182
+ get streamNonce() {
8183
+ return this.#streamNonce;
8184
+ }
8185
+ /** Number of verified receipts accumulated so far. */
8186
+ get size() {
8187
+ return this.#receipts.length;
8188
+ }
8189
+ /**
8190
+ * Verify + accumulate one receipt. On `{ok: false}` the receipt is NOT
8191
+ * added and the chain is unchanged.
8192
+ */
8193
+ add(receipt) {
8194
+ if (receipt.streamNonce !== this.#streamNonce) {
8195
+ return {
8196
+ ok: false,
8197
+ code: "WRONG_STREAM_NONCE",
8198
+ message: `receipt streamNonce ${receipt.streamNonce} does not match session ${this.#streamNonce}`
8199
+ };
8200
+ }
8201
+ if (!verifyStreamReceipt(receipt, this.#makerPubkey)) {
8202
+ return {
8203
+ ok: false,
8204
+ code: "BAD_SIGNATURE",
8205
+ message: `receipt seq ${receipt.seq} signature does not verify against maker key ${this.#makerPubkey}`
8206
+ };
8207
+ }
8208
+ if (this.#seqs.has(receipt.seq)) {
8209
+ return {
8210
+ ok: false,
8211
+ code: "DUPLICATE_SEQ",
8212
+ message: `duplicate receipt seq ${receipt.seq}`
8213
+ };
8214
+ }
8215
+ let lo = 0;
8216
+ let hi = this.#receipts.length;
8217
+ while (lo < hi) {
8218
+ const mid = lo + hi >>> 1;
8219
+ const midReceipt = this.#receipts[mid];
8220
+ if (midReceipt.seq < receipt.seq) lo = mid + 1;
8221
+ else hi = mid;
8222
+ }
8223
+ const cumulative = BigInt(receipt.cumulativeDelivered);
8224
+ const lower = lo > 0 ? this.#receipts[lo - 1] : void 0;
8225
+ const higher = lo < this.#receipts.length ? this.#receipts[lo] : void 0;
8226
+ if (lower && BigInt(lower.cumulativeDelivered) > cumulative) {
8227
+ return {
8228
+ ok: false,
8229
+ code: "NON_MONOTONIC",
8230
+ message: `receipt seq ${receipt.seq} cumulativeDelivered ${receipt.cumulativeDelivered} is below seq ${lower.seq}'s ${lower.cumulativeDelivered}`
8231
+ };
8232
+ }
8233
+ if (higher && BigInt(higher.cumulativeDelivered) < cumulative) {
8234
+ return {
8235
+ ok: false,
8236
+ code: "NON_MONOTONIC",
8237
+ message: `receipt seq ${receipt.seq} cumulativeDelivered ${receipt.cumulativeDelivered} is above seq ${higher.seq}'s ${higher.cumulativeDelivered}`
8238
+ };
8239
+ }
8240
+ this.#receipts.splice(lo, 0, receipt);
8241
+ this.#seqs.add(receipt.seq);
8242
+ return { ok: true };
8243
+ }
8244
+ /**
8245
+ * Snapshot the accumulated chain: sorted receipts, the superseding latest,
8246
+ * the signed total delivered, and any `seq` holes in `[1, latest.seq]`.
8247
+ */
8248
+ chain() {
8249
+ const receipts = [...this.#receipts];
8250
+ const latest = receipts[receipts.length - 1];
8251
+ const holes = [];
8252
+ if (latest) {
8253
+ for (let seq = 1; seq <= latest.seq; seq++) {
8254
+ if (!this.#seqs.has(seq)) holes.push(seq);
8255
+ }
8256
+ }
8257
+ return {
8258
+ streamNonce: this.#streamNonce,
8259
+ receipts,
8260
+ ...latest !== void 0 && { latest },
8261
+ totalDelivered: latest?.cumulativeDelivered ?? "0",
8262
+ holes
8263
+ };
8264
+ }
8265
+ };
8266
+ var RATE_REGEX22 = /^(0|[1-9]\d*)(\.\d+)?$/;
7878
8267
  function applyRate(params) {
7879
8268
  const { sourceAmount, fromScale, toScale, rate } = params;
7880
- if (!RATE_REGEX2.test(rate)) {
8269
+ if (!RATE_REGEX22.test(rate)) {
7881
8270
  throw new SwapHandlerError(`Invalid rate format: ${rate}`);
7882
8271
  }
7883
8272
  if (/^0(\.0+)?$/.test(rate)) {
@@ -7897,8 +8286,8 @@ function applyRate(params) {
7897
8286
  const scaleDown = 10n ** BigInt(fromScale);
7898
8287
  return sourceAmount * rateNumerator * scaleUp / (rateDenominator * scaleDown);
7899
8288
  }
7900
- var RATE_REGEX22 = /^(0|[1-9]\d*)(\.\d+)?$/;
7901
- var HEX64_REGEX = /^[0-9a-f]{64}$/;
8289
+ var RATE_REGEX3 = /^(0|[1-9]\d*)(\.\d+)?$/;
8290
+ var HEX64_REGEX2 = /^[0-9a-f]{64}$/;
7902
8291
  var BASE64_REGEX = /^[A-Za-z0-9+/]+={0,2}$/;
7903
8292
  function isBase64(s) {
7904
8293
  if (s.length === 0 || s.length % 4 !== 0) return false;
@@ -7934,26 +8323,29 @@ function buildSwapRumor(input) {
7934
8323
  totalPackets,
7935
8324
  nonce,
7936
8325
  createdAt,
7937
- chainRecipient
8326
+ chainRecipient,
8327
+ streamNonce
7938
8328
  } = input;
8329
+ const tags = [
8330
+ ["swap-from", `${pair.from.assetCode}:${pair.from.chain}`],
8331
+ ["swap-to", `${pair.to.assetCode}:${pair.to.chain}`],
8332
+ ["amount", sourceAmount.toString()],
8333
+ ["seq", String(packetIndex), String(totalPackets)],
8334
+ ["nonce", Buffer.from(nonce).toString("hex")],
8335
+ ["chain-recipient", chainRecipient]
8336
+ ];
8337
+ if (streamNonce !== void 0) tags.push(["stream-nonce", streamNonce]);
7939
8338
  return {
7940
8339
  kind: 20032,
7941
8340
  pubkey: senderPubkey,
7942
8341
  content: "",
7943
8342
  created_at: createdAt,
7944
- tags: [
7945
- ["swap-from", `${pair.from.assetCode}:${pair.from.chain}`],
7946
- ["swap-to", `${pair.to.assetCode}:${pair.to.chain}`],
7947
- ["amount", sourceAmount.toString()],
7948
- ["seq", String(packetIndex), String(totalPackets)],
7949
- ["nonce", Buffer.from(nonce).toString("hex")],
7950
- ["chain-recipient", chainRecipient]
7951
- ]
8343
+ tags
7952
8344
  };
7953
8345
  }
7954
8346
  var EVM_CHANNEL_ID_REGEX = /^0x[0-9a-f]{64}$/;
7955
8347
  var EVM_ADDRESS_REGEX = /^0x[0-9a-f]{40}$/;
7956
- var DECIMAL_UINT_REGEX = /^(0|[1-9]\d*)$/;
8348
+ var DECIMAL_UINT_REGEX2 = /^(0|[1-9]\d*)$/;
7957
8349
  var BASE58_REGEX = /^[1-9A-HJ-NP-Za-km-z]+$/;
7958
8350
  function validateChainAddress(value, chain, kind) {
7959
8351
  if (chain.startsWith("evm:")) {
@@ -8020,7 +8412,7 @@ function decodeFulfillMetadata(data, chain, opts) {
8020
8412
  "FULFILL metadata.claim is missing or not base64 string"
8021
8413
  );
8022
8414
  }
8023
- if (typeof ephemeralPubkey !== "string" || !HEX64_REGEX.test(ephemeralPubkey)) {
8415
+ if (typeof ephemeralPubkey !== "string" || !HEX64_REGEX2.test(ephemeralPubkey)) {
8024
8416
  throw new StreamSwapError(
8025
8417
  "FULFILL_DECODE_FAILED",
8026
8418
  "FULFILL metadata.ephemeralPubkey is missing or not 64-char hex"
@@ -8054,7 +8446,7 @@ function decodeFulfillMetadata(data, chain, opts) {
8054
8446
  );
8055
8447
  }
8056
8448
  if (hasRate) {
8057
- if (typeof tapeRate !== "string" || !RATE_REGEX22.test(tapeRate) || /^0(\.0+)?$/.test(tapeRate)) {
8449
+ if (typeof tapeRate !== "string" || !RATE_REGEX3.test(tapeRate) || /^0(\.0+)?$/.test(tapeRate)) {
8058
8450
  throw new StreamSwapError(
8059
8451
  "FULFILL_DECODE_FAILED",
8060
8452
  "FULFILL metadata.rate must be a positive decimal string"
@@ -8074,16 +8466,27 @@ function decodeFulfillMetadata(data, chain, opts) {
8074
8466
  "FULFILL metadata is missing the quote tape (rate + rateTimestamp) required when minExchangeRate is set"
8075
8467
  );
8076
8468
  }
8469
+ if (obj["receipt"] !== void 0) {
8470
+ try {
8471
+ result.receipt = parseStreamReceipt(obj["receipt"]);
8472
+ } catch (err) {
8473
+ throw new StreamSwapError(
8474
+ "FULFILL_DECODE_FAILED",
8475
+ `FULFILL metadata.receipt is malformed: ${err instanceof Error ? err.message : String(err)}`,
8476
+ { cause: err }
8477
+ );
8478
+ }
8479
+ }
8077
8480
  const channelId = obj["channelId"];
8078
8481
  if (typeof channelId === "string" && (!chain || validateChainAddress(channelId, chain, "channelId"))) {
8079
8482
  result.channelId = channelId;
8080
8483
  }
8081
8484
  const nonce = obj["nonce"];
8082
- if (typeof nonce === "string" && DECIMAL_UINT_REGEX.test(nonce)) {
8485
+ if (typeof nonce === "string" && DECIMAL_UINT_REGEX2.test(nonce)) {
8083
8486
  result.nonce = nonce;
8084
8487
  }
8085
8488
  const cumulativeAmount = obj["cumulativeAmount"];
8086
- if (typeof cumulativeAmount === "string" && DECIMAL_UINT_REGEX.test(cumulativeAmount)) {
8489
+ if (typeof cumulativeAmount === "string" && DECIMAL_UINT_REGEX2.test(cumulativeAmount)) {
8087
8490
  result.cumulativeAmount = cumulativeAmount;
8088
8491
  }
8089
8492
  const recipient = obj["recipient"];
@@ -8097,12 +8500,12 @@ function decodeFulfillMetadata(data, chain, opts) {
8097
8500
  return result;
8098
8501
  }
8099
8502
  function compareDecimalRates(a, b) {
8100
- const split2 = (s) => {
8503
+ const split3 = (s) => {
8101
8504
  const dot = s.indexOf(".");
8102
8505
  return dot === -1 ? { int: s, frac: "" } : { int: s.slice(0, dot), frac: s.slice(dot + 1) };
8103
8506
  };
8104
- const pa = split2(a);
8105
- const pb = split2(b);
8507
+ const pa = split3(a);
8508
+ const pb = split3(b);
8106
8509
  const scale = Math.max(pa.frac.length, pb.frac.length);
8107
8510
  const av = BigInt(pa.int + pa.frac.padEnd(scale, "0"));
8108
8511
  const bv = BigInt(pb.int + pb.frac.padEnd(scale, "0"));
@@ -8199,7 +8602,7 @@ function validateParams(params) {
8199
8602
  "senderSecretKey must be a 32-byte Uint8Array"
8200
8603
  );
8201
8604
  }
8202
- if (typeof params.swapPubkey !== "string" || !HEX64_REGEX.test(params.swapPubkey)) {
8605
+ if (typeof params.swapPubkey !== "string" || !HEX64_REGEX2.test(params.swapPubkey)) {
8203
8606
  throw new StreamSwapError(
8204
8607
  "INVALID_STATE",
8205
8608
  "swapPubkey must be a 64-char lowercase hex string"
@@ -8220,10 +8623,10 @@ function validateParams(params) {
8220
8623
  "pair.to must have { assetCode: string, assetScale: number, chain: string }"
8221
8624
  );
8222
8625
  }
8223
- if (typeof params.pair.rate !== "string" || !RATE_REGEX22.test(params.pair.rate)) {
8626
+ if (typeof params.pair.rate !== "string" || !RATE_REGEX3.test(params.pair.rate)) {
8224
8627
  throw new StreamSwapError(
8225
8628
  "INVALID_PAIR",
8226
- `pair.rate must match ${RATE_REGEX22}, got ${params.pair.rate}`
8629
+ `pair.rate must match ${RATE_REGEX3}, got ${params.pair.rate}`
8227
8630
  );
8228
8631
  }
8229
8632
  try {
@@ -8247,15 +8650,27 @@ function validateParams(params) {
8247
8650
  );
8248
8651
  }
8249
8652
  if (params.minExchangeRate !== void 0) {
8250
- if (typeof params.minExchangeRate !== "string" || !RATE_REGEX22.test(params.minExchangeRate) || /^0(\.0+)?$/.test(params.minExchangeRate)) {
8653
+ if (typeof params.minExchangeRate !== "string" || !RATE_REGEX3.test(params.minExchangeRate) || /^0(\.0+)?$/.test(params.minExchangeRate)) {
8251
8654
  throw new StreamSwapError(
8252
8655
  "INVALID_STATE",
8253
- `minExchangeRate must be a positive decimal string matching ${RATE_REGEX22}, got ${String(
8656
+ `minExchangeRate must be a positive decimal string matching ${RATE_REGEX3}, got ${String(
8254
8657
  params.minExchangeRate
8255
8658
  )}`
8256
8659
  );
8257
8660
  }
8258
8661
  }
8662
+ if (params.receiptPubkey !== void 0 && (typeof params.receiptPubkey !== "string" || !HEX64_REGEX2.test(params.receiptPubkey))) {
8663
+ throw new StreamSwapError(
8664
+ "INVALID_STATE",
8665
+ "receiptPubkey must be a 64-char lowercase hex string"
8666
+ );
8667
+ }
8668
+ if (params.requireReceipts !== void 0 && typeof params.requireReceipts !== "boolean") {
8669
+ throw new StreamSwapError(
8670
+ "INVALID_STATE",
8671
+ `requireReceipts must be a boolean, got ${String(params.requireReceipts)}`
8672
+ );
8673
+ }
8259
8674
  if (params.packetExpiryMs !== void 0 && (typeof params.packetExpiryMs !== "number" || !Number.isInteger(params.packetExpiryMs) || params.packetExpiryMs <= 0)) {
8260
8675
  throw new StreamSwapError(
8261
8676
  "INVALID_STATE",
@@ -8292,6 +8707,9 @@ function streamSwapControlled(params) {
8292
8707
  rate: params.pair.rate
8293
8708
  });
8294
8709
  const senderPubkey = getPublicKey32(params.senderSecretKey);
8710
+ const streamNonceBytes = new Uint8Array(16);
8711
+ getRandomValues(streamNonceBytes);
8712
+ const streamNonce = Buffer.from(streamNonceBytes).toString("hex");
8295
8713
  let streamState = "running";
8296
8714
  let resumeDeferred = null;
8297
8715
  const controller = {
@@ -8342,6 +8760,7 @@ function streamSwapControlled(params) {
8342
8760
  params,
8343
8761
  frozenPair,
8344
8762
  senderPubkey,
8763
+ streamNonce,
8345
8764
  logger,
8346
8765
  getState,
8347
8766
  setState,
@@ -8351,6 +8770,7 @@ function streamSwapControlled(params) {
8351
8770
  frozenPair,
8352
8771
  schedule,
8353
8772
  senderPubkey,
8773
+ streamNonce,
8354
8774
  logger,
8355
8775
  getState,
8356
8776
  setState,
@@ -8359,7 +8779,15 @@ function streamSwapControlled(params) {
8359
8779
  return { result, controller };
8360
8780
  }
8361
8781
  function buildAndWrapPacket(input) {
8362
- const { params, pair, senderPubkey, sourceAmount, seq, totalPackets } = input;
8782
+ const {
8783
+ params,
8784
+ pair,
8785
+ senderPubkey,
8786
+ sourceAmount,
8787
+ seq,
8788
+ totalPackets,
8789
+ streamNonce
8790
+ } = input;
8363
8791
  const nonce = new Uint8Array(16);
8364
8792
  getRandomValues(nonce);
8365
8793
  const rumor = buildSwapRumor({
@@ -8370,7 +8798,8 @@ function buildAndWrapPacket(input) {
8370
8798
  totalPackets,
8371
8799
  nonce,
8372
8800
  createdAt: Math.floor(Date.now() / 1e3),
8373
- chainRecipient: params.chainRecipient
8801
+ chainRecipient: params.chainRecipient,
8802
+ streamNonce
8374
8803
  });
8375
8804
  const packetExpiresAt = params.packetExpiryMs !== void 0 ? new Date(Date.now() + params.packetExpiryMs) : void 0;
8376
8805
  const wrapped = wrapSwapPacketToToon({
@@ -8460,6 +8889,47 @@ async function processAcceptedPacket(ctx, args) {
8460
8889
  return { status: "below-floor" };
8461
8890
  }
8462
8891
  }
8892
+ let verifiedReceipt;
8893
+ if (metadata.receipt !== void 0) {
8894
+ const receipt = metadata.receipt;
8895
+ let failure;
8896
+ if (metadata.rate !== void 0 && receipt.rate !== metadata.rate) {
8897
+ failure = `receipt.rate ${receipt.rate} does not match tape rate ${metadata.rate}`;
8898
+ } else if (metadata.rateTimestamp !== void 0 && receipt.rateTimestamp !== metadata.rateTimestamp) {
8899
+ failure = `receipt.rateTimestamp ${receipt.rateTimestamp} does not match tape rateTimestamp ${metadata.rateTimestamp}`;
8900
+ } else {
8901
+ const added = ctx.receiptTracker.add(receipt);
8902
+ if (!added.ok) failure = `${added.code}: ${added.message}`;
8903
+ }
8904
+ if (failure !== void 0) {
8905
+ logger.warn({
8906
+ event: "stream_swap.receipt_invalid",
8907
+ packetIndex,
8908
+ seq: receipt.seq,
8909
+ error: failure
8910
+ });
8911
+ ctx.rejections.push({
8912
+ packetIndex,
8913
+ sourceAmount,
8914
+ code: "RECEIPT_INVALID",
8915
+ message: `Stream receipt failed verification: ${failure}`
8916
+ });
8917
+ return { status: "receipt-invalid" };
8918
+ }
8919
+ verifiedReceipt = receipt;
8920
+ } else if (params.requireReceipts === true) {
8921
+ logger.warn({
8922
+ event: "stream_swap.receipt_missing",
8923
+ packetIndex
8924
+ });
8925
+ ctx.rejections.push({
8926
+ packetIndex,
8927
+ sourceAmount,
8928
+ code: "RECEIPT_MISSING",
8929
+ message: "FULFILL carried no stream receipt but requireReceipts is set (legacy maker without rfc-0039 receipt support?)"
8930
+ });
8931
+ return { status: "receipt-invalid" };
8932
+ }
8463
8933
  let claimBytes;
8464
8934
  try {
8465
8935
  const ciphertext = new Uint8Array(Buffer.from(metadata.claim, "base64"));
@@ -8535,6 +9005,7 @@ async function processAcceptedPacket(ctx, args) {
8535
9005
  accumulated.rate = metadata.rate;
8536
9006
  accumulated.rateTimestamp = metadata.rateTimestamp;
8537
9007
  }
9008
+ if (verifiedReceipt !== void 0) accumulated.receipt = verifiedReceipt;
8538
9009
  ctx.claims.push(accumulated);
8539
9010
  logger.debug({
8540
9011
  event: "stream_swap.packet_accepted",
@@ -8559,6 +9030,8 @@ async function processAcceptedPacket(ctx, args) {
8559
9030
  rate: metadata.rate,
8560
9031
  rateTimestamp: metadata.rateTimestamp
8561
9032
  },
9033
+ // Issue #84: surface the verified per-fulfill receipt to the callback.
9034
+ ...verifiedReceipt !== void 0 && { receipt: verifiedReceipt },
8562
9035
  state: ctx.getState() === "paused" ? "paused" : ctx.getState() === "stopped" ? "stopped" : "running"
8563
9036
  });
8564
9037
  try {
@@ -8613,10 +9086,13 @@ function finalizeResult(input) {
8613
9086
  cumulativeSource: cumulative.source,
8614
9087
  cumulativeTarget: cumulative.target,
8615
9088
  packetsSent: input.packetsSent,
8616
- packetsScheduled: input.packetsScheduled
9089
+ packetsScheduled: input.packetsScheduled,
9090
+ // Issue #84: the verified receipt chain — present on abort too,
9091
+ // covering exactly the packets that filled before the halt.
9092
+ receipts: input.ctx.receiptTracker.chain()
8617
9093
  };
8618
9094
  }
8619
- async function runLoop(params, pair, schedule, senderPubkey, logger, getState, setState, waitForResumeOrStop) {
9095
+ async function runLoop(params, pair, schedule, senderPubkey, streamNonce, logger, getState, setState, waitForResumeOrStop) {
8620
9096
  const ctx = {
8621
9097
  params,
8622
9098
  pair,
@@ -8625,7 +9101,11 @@ async function runLoop(params, pair, schedule, senderPubkey, logger, getState, s
8625
9101
  claims: [],
8626
9102
  rejections: [],
8627
9103
  errors: [],
8628
- cumulative: { source: 0n, target: 0n }
9104
+ cumulative: { source: 0n, target: 0n },
9105
+ receiptTracker: new ReceiptChainTracker({
9106
+ streamNonce,
9107
+ makerPubkey: params.receiptPubkey ?? params.swapPubkey
9108
+ })
8629
9109
  };
8630
9110
  let packetsSent = 0;
8631
9111
  let abortReason = "complete";
@@ -8666,7 +9146,8 @@ async function runLoop(params, pair, schedule, senderPubkey, logger, getState, s
8666
9146
  senderPubkey,
8667
9147
  sourceAmount,
8668
9148
  seq: packetIndex + 1,
8669
- totalPackets
9149
+ totalPackets,
9150
+ streamNonce
8670
9151
  });
8671
9152
  } catch (err) {
8672
9153
  logger.error({
@@ -8729,6 +9210,10 @@ async function runLoop(params, pair, schedule, senderPubkey, logger, getState, s
8729
9210
  abortReason = "below-floor";
8730
9211
  break packetLoop;
8731
9212
  }
9213
+ if (outcome.status === "receipt-invalid") {
9214
+ abortReason = "receipt-invalid";
9215
+ break packetLoop;
9216
+ }
8732
9217
  if (outcome.status === "callback-throw") {
8733
9218
  abortReason = "callback-throw";
8734
9219
  break packetLoop;
@@ -8764,7 +9249,7 @@ function classifyReject(code, message) {
8764
9249
  }
8765
9250
  return "reject";
8766
9251
  }
8767
- async function runAdaptiveLoop(params, pair, senderPubkey, logger, getState, setState, waitForResumeOrStop) {
9252
+ async function runAdaptiveLoop(params, pair, senderPubkey, streamNonce, logger, getState, setState, waitForResumeOrStop) {
8768
9253
  const controller = params.controller;
8769
9254
  const ctx = {
8770
9255
  params,
@@ -8774,7 +9259,11 @@ async function runAdaptiveLoop(params, pair, senderPubkey, logger, getState, set
8774
9259
  claims: [],
8775
9260
  rejections: [],
8776
9261
  errors: [],
8777
- cumulative: { source: 0n, target: 0n }
9262
+ cumulative: { source: 0n, target: 0n },
9263
+ receiptTracker: new ReceiptChainTracker({
9264
+ streamNonce,
9265
+ makerPubkey: params.receiptPubkey ?? params.swapPubkey
9266
+ })
8778
9267
  };
8779
9268
  let packetsSent = 0;
8780
9269
  let abortReason = "complete";
@@ -8841,7 +9330,8 @@ async function runAdaptiveLoop(params, pair, senderPubkey, logger, getState, set
8841
9330
  seq: packetIndex + 1,
8842
9331
  // Adaptive mode: the final packet count is unknown upfront —
8843
9332
  // `0` in the rumor's `seq` tag total position means "open".
8844
- totalPackets: 0
9333
+ totalPackets: 0,
9334
+ streamNonce
8845
9335
  });
8846
9336
  } catch (err) {
8847
9337
  logger.error({
@@ -8961,6 +9451,14 @@ async function runAdaptiveLoop(params, pair, senderPubkey, logger, getState, set
8961
9451
  });
8962
9452
  halt("below-floor");
8963
9453
  break;
9454
+ case "receipt-invalid":
9455
+ await observeSafe({
9456
+ resolution: "reject",
9457
+ rttMs: settled.rttMs,
9458
+ remaining
9459
+ });
9460
+ halt("receipt-invalid");
9461
+ break;
8964
9462
  case "callback-throw":
8965
9463
  await observeSafe({
8966
9464
  resolution: "fulfill",
@@ -9019,18 +9517,18 @@ function getRandomValues(buf) {
9019
9517
  );
9020
9518
  }
9021
9519
 
9022
- // ../../node_modules/.pnpm/@toon-protocol+sdk@2.1.0_mina-signer@3.1.0_typescript@5.9.3/node_modules/@toon-protocol/sdk/dist/index.js
9520
+ // ../../node_modules/.pnpm/@toon-protocol+sdk@3.0.0_mina-signer@3.1.0_typescript@5.9.3/node_modules/@toon-protocol/sdk/dist/index.js
9023
9521
  var SwapControllerError = class extends ToonError {
9024
9522
  constructor(message, cause) {
9025
9523
  super(message, "SWAP_CONTROLLER_ERROR", cause);
9026
9524
  this.name = "SwapControllerError";
9027
9525
  }
9028
9526
  };
9029
- var DECIMAL_UINT_REGEX2 = /^(0|[1-9]\d*)$/;
9527
+ var DECIMAL_UINT_REGEX3 = /^(0|[1-9]\d*)$/;
9030
9528
  function isSwapControllerState(value) {
9031
9529
  if (!value || typeof value !== "object") return false;
9032
9530
  const s = value;
9033
- return s["v"] === 1 && typeof s["delta"] === "string" && DECIMAL_UINT_REGEX2.test(s["delta"]) && typeof s["W"] === "number" && Number.isInteger(s["W"]) && s["W"] >= 1 && typeof s["vEwma"] === "number" && Number.isFinite(s["vEwma"]) && s["vEwma"] >= 0 && typeof s["tauEwma"] === "number" && Number.isFinite(s["tauEwma"]) && s["tauEwma"] >= 0 && typeof s["cleanStreak"] === "number" && Number.isInteger(s["cleanStreak"]) && s["cleanStreak"] >= 0 && typeof s["everShrunk"] === "boolean" && (s["lastWidened"] === "delta" || s["lastWidened"] === "window") && typeof s["updatedAt"] === "number";
9531
+ return s["v"] === 1 && typeof s["delta"] === "string" && DECIMAL_UINT_REGEX3.test(s["delta"]) && typeof s["W"] === "number" && Number.isInteger(s["W"]) && s["W"] >= 1 && typeof s["vEwma"] === "number" && Number.isFinite(s["vEwma"]) && s["vEwma"] >= 0 && typeof s["tauEwma"] === "number" && Number.isFinite(s["tauEwma"]) && s["tauEwma"] >= 0 && typeof s["cleanStreak"] === "number" && Number.isInteger(s["cleanStreak"]) && s["cleanStreak"] >= 0 && typeof s["everShrunk"] === "boolean" && (s["lastWidened"] === "delta" || s["lastWidened"] === "window") && typeof s["updatedAt"] === "number";
9034
9532
  }
9035
9533
  function swapControllerStateKey(params) {
9036
9534
  const { makerPubkey, pair } = params;
@@ -9379,7 +9877,19 @@ var EVM_SETTLEMENT_FUNCTION_SELECTOR = keccak_256(
9379
9877
  var EVM_SETTLEMENT_EVENT_TOPIC = "0x" + bytesToHex(
9380
9878
  keccak_256(new TextEncoder().encode(EVM_SETTLEMENT_EVENT_SIGNATURE))
9381
9879
  );
9382
- function recoverEvmSignerAddress(claim) {
9880
+ function recoverEvmSignerAddress(claim, chainId, verifyingContract) {
9881
+ if (typeof chainId !== "number" || !Number.isInteger(chainId) || chainId <= 0) {
9882
+ throw new SettlementTxError(
9883
+ "INVALID_INPUT",
9884
+ `EVM v2 digest requires a positive integer chainId, got ${chainId}`
9885
+ );
9886
+ }
9887
+ if (!verifyingContract) {
9888
+ throw new SettlementTxError(
9889
+ "INVALID_INPUT",
9890
+ "EVM v2 digest requires verifyingContract (RollingSwapChannel address)"
9891
+ );
9892
+ }
9383
9893
  if (claim.channelId === void 0 || claim.cumulativeAmount === void 0 || claim.nonce === void 0 || claim.recipient === void 0) {
9384
9894
  throw new SettlementTxError(
9385
9895
  "MISSING_SETTLEMENT_METADATA",
@@ -9406,6 +9916,7 @@ function recoverEvmSignerAddress(claim) {
9406
9916
  try {
9407
9917
  const channelIdBytes = hexToBytes4(claim.channelId);
9408
9918
  const recipientBytes = hexToBytes4(claim.recipient);
9919
+ const verifyingContractBytes = hexToBytes4(verifyingContract);
9409
9920
  if (channelIdBytes.length !== 32) {
9410
9921
  throw new Error(
9411
9922
  `channelId must be 32 bytes (got ${channelIdBytes.length})`
@@ -9416,11 +9927,18 @@ function recoverEvmSignerAddress(claim) {
9416
9927
  `recipient must be 20 bytes (got ${recipientBytes.length})`
9417
9928
  );
9418
9929
  }
9930
+ if (verifyingContractBytes.length !== 20) {
9931
+ throw new Error(
9932
+ `verifyingContract must be 20 bytes (got ${verifyingContractBytes.length})`
9933
+ );
9934
+ }
9419
9935
  msgHash = balanceProofHashEvm(
9420
9936
  channelIdBytes,
9421
9937
  BigInt(claim.cumulativeAmount),
9422
9938
  BigInt(claim.nonce),
9423
- recipientBytes
9939
+ recipientBytes,
9940
+ BigInt(chainId),
9941
+ verifyingContractBytes
9424
9942
  );
9425
9943
  const sig = secp256k1.Signature.fromBytes(
9426
9944
  compactRS,
@@ -9594,8 +10112,8 @@ function buildEvmSettlementTx(winner, signer, recipient, selectedClaimIndex, cla
9594
10112
  sourceAssetCode: winner.pair.from.assetCode
9595
10113
  };
9596
10114
  }
9597
- function verifyEvmClaimSignature(claim, expectedAddress) {
9598
- const recovered = recoverEvmSignerAddress(claim);
10115
+ function verifyEvmClaimSignature(claim, expectedAddress, chainId, verifyingContract) {
10116
+ const recovered = recoverEvmSignerAddress(claim, chainId, verifyingContract);
9599
10117
  const expected = expectedAddress.toLowerCase();
9600
10118
  return {
9601
10119
  valid: recovered.toLowerCase() === expected,
@@ -9953,7 +10471,9 @@ function buildSettlementTx(params) {
9953
10471
  try {
9954
10472
  const { valid, recovered } = verifyEvmClaimSignature(
9955
10473
  claim,
9956
- signer.address
10474
+ signer.address,
10475
+ signer.chainId,
10476
+ signer.contractAddress
9957
10477
  );
9958
10478
  if (!valid) {
9959
10479
  rejected.push({
@@ -10203,10 +10723,18 @@ function buildSettlementTx(params) {
10203
10723
  function verifyAccumulatedClaim(claim, signer, minaSignerClient) {
10204
10724
  const kind = chainKindOf(claim.pair.to.chain);
10205
10725
  if (kind === "evm") {
10726
+ if (typeof signer.chainId !== "number" || !Number.isInteger(signer.chainId) || signer.chainId <= 0 || !signer.contractAddress) {
10727
+ return {
10728
+ valid: false,
10729
+ reason: "INVALID_INPUT: EVM signer requires chainId (positive integer) + contractAddress for the v2 EIP-712 digest (connector#324 finding #1)"
10730
+ };
10731
+ }
10206
10732
  try {
10207
10733
  const { valid, recovered } = verifyEvmClaimSignature(
10208
10734
  claim,
10209
- signer.address
10735
+ signer.address,
10736
+ signer.chainId,
10737
+ signer.contractAddress
10210
10738
  );
10211
10739
  if (valid) return { valid: true };
10212
10740
  return {
@@ -10269,6 +10797,192 @@ import {
10269
10797
  } from "viem";
10270
10798
  import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, existsSync as existsSync2, mkdirSync } from "fs";
10271
10799
  import { dirname } from "path";
10800
+ import {
10801
+ hashTypedData
10802
+ } from "viem";
10803
+
10804
+ // ../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/esm/sha3.js
10805
+ var _0n8 = BigInt(0);
10806
+ var _1n7 = BigInt(1);
10807
+ var _2n7 = BigInt(2);
10808
+ var _7n3 = BigInt(7);
10809
+ var _256n2 = BigInt(256);
10810
+ var _0x71n2 = BigInt(113);
10811
+ var SHA3_PI2 = [];
10812
+ var SHA3_ROTL2 = [];
10813
+ var _SHA3_IOTA2 = [];
10814
+ for (let round = 0, R = _1n7, x = 1, y = 0; round < 24; round++) {
10815
+ [x, y] = [y, (2 * x + 3 * y) % 5];
10816
+ SHA3_PI2.push(2 * (5 * y + x));
10817
+ SHA3_ROTL2.push((round + 1) * (round + 2) / 2 % 64);
10818
+ let t = _0n8;
10819
+ for (let j = 0; j < 7; j++) {
10820
+ R = (R << _1n7 ^ (R >> _7n3) * _0x71n2) % _256n2;
10821
+ if (R & _2n7)
10822
+ t ^= _1n7 << (_1n7 << /* @__PURE__ */ BigInt(j)) - _1n7;
10823
+ }
10824
+ _SHA3_IOTA2.push(t);
10825
+ }
10826
+ var IOTAS2 = split2(_SHA3_IOTA2, true);
10827
+ var SHA3_IOTA_H2 = IOTAS2[0];
10828
+ var SHA3_IOTA_L2 = IOTAS2[1];
10829
+ var rotlH2 = (h, l, s) => s > 32 ? rotlBH2(h, l, s) : rotlSH2(h, l, s);
10830
+ var rotlL2 = (h, l, s) => s > 32 ? rotlBL2(h, l, s) : rotlSL2(h, l, s);
10831
+ function keccakP2(s, rounds = 24) {
10832
+ const B = new Uint32Array(5 * 2);
10833
+ for (let round = 24 - rounds; round < 24; round++) {
10834
+ for (let x = 0; x < 10; x++)
10835
+ B[x] = s[x] ^ s[x + 10] ^ s[x + 20] ^ s[x + 30] ^ s[x + 40];
10836
+ for (let x = 0; x < 10; x += 2) {
10837
+ const idx1 = (x + 8) % 10;
10838
+ const idx0 = (x + 2) % 10;
10839
+ const B0 = B[idx0];
10840
+ const B1 = B[idx0 + 1];
10841
+ const Th = rotlH2(B0, B1, 1) ^ B[idx1];
10842
+ const Tl = rotlL2(B0, B1, 1) ^ B[idx1 + 1];
10843
+ for (let y = 0; y < 50; y += 10) {
10844
+ s[x + y] ^= Th;
10845
+ s[x + y + 1] ^= Tl;
10846
+ }
10847
+ }
10848
+ let curH = s[2];
10849
+ let curL = s[3];
10850
+ for (let t = 0; t < 24; t++) {
10851
+ const shift = SHA3_ROTL2[t];
10852
+ const Th = rotlH2(curH, curL, shift);
10853
+ const Tl = rotlL2(curH, curL, shift);
10854
+ const PI = SHA3_PI2[t];
10855
+ curH = s[PI];
10856
+ curL = s[PI + 1];
10857
+ s[PI] = Th;
10858
+ s[PI + 1] = Tl;
10859
+ }
10860
+ for (let y = 0; y < 50; y += 10) {
10861
+ for (let x = 0; x < 10; x++)
10862
+ B[x] = s[y + x];
10863
+ for (let x = 0; x < 10; x++)
10864
+ s[y + x] ^= ~B[(x + 2) % 10] & B[(x + 4) % 10];
10865
+ }
10866
+ s[0] ^= SHA3_IOTA_H2[round];
10867
+ s[1] ^= SHA3_IOTA_L2[round];
10868
+ }
10869
+ clean2(B);
10870
+ }
10871
+ var Keccak2 = class _Keccak extends Hash {
10872
+ // NOTE: we accept arguments in bytes instead of bits here.
10873
+ constructor(blockLen, suffix, outputLen, enableXOF = false, rounds = 24) {
10874
+ super();
10875
+ this.pos = 0;
10876
+ this.posOut = 0;
10877
+ this.finished = false;
10878
+ this.destroyed = false;
10879
+ this.enableXOF = false;
10880
+ this.blockLen = blockLen;
10881
+ this.suffix = suffix;
10882
+ this.outputLen = outputLen;
10883
+ this.enableXOF = enableXOF;
10884
+ this.rounds = rounds;
10885
+ anumber2(outputLen);
10886
+ if (!(0 < blockLen && blockLen < 200))
10887
+ throw new Error("only keccak-f1600 function is supported");
10888
+ this.state = new Uint8Array(200);
10889
+ this.state32 = u322(this.state);
10890
+ }
10891
+ clone() {
10892
+ return this._cloneInto();
10893
+ }
10894
+ keccak() {
10895
+ swap32IfBE2(this.state32);
10896
+ keccakP2(this.state32, this.rounds);
10897
+ swap32IfBE2(this.state32);
10898
+ this.posOut = 0;
10899
+ this.pos = 0;
10900
+ }
10901
+ update(data) {
10902
+ aexists2(this);
10903
+ data = toBytes(data);
10904
+ abytes3(data);
10905
+ const { blockLen, state } = this;
10906
+ const len = data.length;
10907
+ for (let pos = 0; pos < len; ) {
10908
+ const take = Math.min(blockLen - this.pos, len - pos);
10909
+ for (let i = 0; i < take; i++)
10910
+ state[this.pos++] ^= data[pos++];
10911
+ if (this.pos === blockLen)
10912
+ this.keccak();
10913
+ }
10914
+ return this;
10915
+ }
10916
+ finish() {
10917
+ if (this.finished)
10918
+ return;
10919
+ this.finished = true;
10920
+ const { state, suffix, pos, blockLen } = this;
10921
+ state[pos] ^= suffix;
10922
+ if ((suffix & 128) !== 0 && pos === blockLen - 1)
10923
+ this.keccak();
10924
+ state[blockLen - 1] ^= 128;
10925
+ this.keccak();
10926
+ }
10927
+ writeInto(out) {
10928
+ aexists2(this, false);
10929
+ abytes3(out);
10930
+ this.finish();
10931
+ const bufferOut = this.state;
10932
+ const { blockLen } = this;
10933
+ for (let pos = 0, len = out.length; pos < len; ) {
10934
+ if (this.posOut >= blockLen)
10935
+ this.keccak();
10936
+ const take = Math.min(blockLen - this.posOut, len - pos);
10937
+ out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos);
10938
+ this.posOut += take;
10939
+ pos += take;
10940
+ }
10941
+ return out;
10942
+ }
10943
+ xofInto(out) {
10944
+ if (!this.enableXOF)
10945
+ throw new Error("XOF is not possible for this instance");
10946
+ return this.writeInto(out);
10947
+ }
10948
+ xof(bytes) {
10949
+ anumber2(bytes);
10950
+ return this.xofInto(new Uint8Array(bytes));
10951
+ }
10952
+ digestInto(out) {
10953
+ aoutput2(out, this);
10954
+ if (this.finished)
10955
+ throw new Error("digest() was already called");
10956
+ this.writeInto(out);
10957
+ this.destroy();
10958
+ return out;
10959
+ }
10960
+ digest() {
10961
+ return this.digestInto(new Uint8Array(this.outputLen));
10962
+ }
10963
+ destroy() {
10964
+ this.destroyed = true;
10965
+ clean2(this.state);
10966
+ }
10967
+ _cloneInto(to) {
10968
+ const { blockLen, suffix, outputLen, rounds, enableXOF } = this;
10969
+ to || (to = new _Keccak(blockLen, suffix, outputLen, enableXOF, rounds));
10970
+ to.state32.set(this.state32);
10971
+ to.pos = this.pos;
10972
+ to.posOut = this.posOut;
10973
+ to.finished = this.finished;
10974
+ to.rounds = rounds;
10975
+ to.suffix = suffix;
10976
+ to.outputLen = outputLen;
10977
+ to.enableXOF = enableXOF;
10978
+ to.destroyed = this.destroyed;
10979
+ return to;
10980
+ }
10981
+ };
10982
+ var gen = (suffix, blockLen, outputLen) => createHasher2(() => new Keccak2(blockLen, suffix, outputLen));
10983
+ var keccak_2562 = /* @__PURE__ */ (() => gen(1, 136, 256 / 8))();
10984
+
10985
+ // ../client/dist/index.js
10272
10986
  import { finalizeEvent as finalizeEvent22 } from "nostr-tools/pure";
10273
10987
  import { nip19 } from "nostr-tools";
10274
10988
  import { getPublicKey as getPublicKey33 } from "nostr-tools/pure";
@@ -10360,9 +11074,9 @@ function deriveEvmIdentity(secretKey) {
10360
11074
  };
10361
11075
  }
10362
11076
  async function deriveSolanaKey(seed, accountIndex = 0) {
10363
- const { hmac: hmac3 } = await import("./hmac-CMZORX4Y.js");
10364
- const { sha512: sha5122 } = await import("./sha512-4LOCATJH.js");
10365
- const { ed25519: ed255194 } = await import("./ed25519-U4PTEOFD.js");
11077
+ const { hmac: hmac3 } = await import("./hmac-GNBDA4UC.js");
11078
+ const { sha512: sha5122 } = await import("./sha512-D7TTPT7I.js");
11079
+ const { ed25519: ed255194 } = await import("./ed25519-VBPL32VX.js");
10366
11080
  const encoder = new TextEncoder();
10367
11081
  let I = hmac3(sha5122, encoder.encode("ed25519 seed"), seed);
10368
11082
  let key2 = I.slice(0, 32);
@@ -10452,12 +11166,12 @@ async function deriveFullIdentity(mnemonic, accountIndex = 0) {
10452
11166
  }
10453
11167
  var BASE58_ALPHABET3 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
10454
11168
  function toBase58(bytes) {
10455
- let num = BigInt(0);
10456
- for (const b of bytes) num = num * 256n + BigInt(b);
11169
+ let num2 = BigInt(0);
11170
+ for (const b of bytes) num2 = num2 * 256n + BigInt(b);
10457
11171
  let result = "";
10458
- while (num > 0n) {
10459
- result = BASE58_ALPHABET3[Number(num % 58n)] + result;
10460
- num = num / 58n;
11172
+ while (num2 > 0n) {
11173
+ result = BASE58_ALPHABET3[Number(num2 % 58n)] + result;
11174
+ num2 = num2 / 58n;
10461
11175
  }
10462
11176
  for (const b of bytes) {
10463
11177
  if (b === 0) result = "1" + result;
@@ -11454,7 +12168,7 @@ var IsomorphicBtpClient = class {
11454
12168
  };
11455
12169
  var CONDITION_LENGTH = 32;
11456
12170
  function mintExecutionCondition() {
11457
- const preimage = randomBytes2(CONDITION_LENGTH);
12171
+ const preimage = randomBytes3(CONDITION_LENGTH);
11458
12172
  return { preimage, condition: sha2562(preimage) };
11459
12173
  }
11460
12174
  function isZeroCondition(condition) {
@@ -13533,7 +14247,14 @@ async function buildMinaPaymentChannelProof(params) {
13533
14247
  signerPublicKey
13534
14248
  };
13535
14249
  }
13536
- var DEPOSIT_TOTAL_STATE_INDEX = 4;
14250
+ var CHANNEL_STATE_INDEX = {
14251
+ channelHash: 0,
14252
+ balanceCommitment: 1,
14253
+ nonceField: 2,
14254
+ channelState: 3,
14255
+ depositTotal: 4
14256
+ };
14257
+ var DEPOSIT_TOTAL_STATE_INDEX = CHANNEL_STATE_INDEX.depositTotal;
13537
14258
  async function readMinaDepositTotal(graphqlUrl, zkAppAddress, fetchImpl = fetch) {
13538
14259
  const query = "query($pk:String!){account(publicKey:$pk){zkappState}}";
13539
14260
  const res = await fetchImpl(graphqlUrl, {
@@ -13558,6 +14279,42 @@ async function readMinaDepositTotal(graphqlUrl, zkAppAddress, fetchImpl = fetch)
13558
14279
  }
13559
14280
  return BigInt(state[DEPOSIT_TOTAL_STATE_INDEX]);
13560
14281
  }
14282
+ var MINA_CHANNEL_STATE = {
14283
+ UNINITIALIZED: 0,
14284
+ OPEN: 1,
14285
+ CLOSING: 2,
14286
+ SETTLED: 3
14287
+ };
14288
+ async function readMinaChannelState(graphqlUrl, zkAppAddress, fetchImpl = fetch) {
14289
+ const query = "query($pk:String!){account(publicKey:$pk){zkappState}}";
14290
+ const res = await fetchImpl(graphqlUrl, {
14291
+ method: "POST",
14292
+ headers: { "content-type": "application/json" },
14293
+ body: JSON.stringify({ query, variables: { pk: zkAppAddress } })
14294
+ });
14295
+ if (!res.ok) {
14296
+ throw new Error(`Mina GraphQL request failed: HTTP ${res.status}`);
14297
+ }
14298
+ const json = await res.json();
14299
+ if (json.errors && json.errors.length > 0) {
14300
+ throw new Error(
14301
+ `Mina GraphQL error: ${json.errors[0]?.message ?? "unknown"}`
14302
+ );
14303
+ }
14304
+ const state = json.data?.account?.zkappState;
14305
+ if (!state || state.length <= DEPOSIT_TOTAL_STATE_INDEX) {
14306
+ throw new Error(
14307
+ `Mina zkApp ${zkAppAddress} has no readable zkappState (account not found or not a zkApp)`
14308
+ );
14309
+ }
14310
+ return {
14311
+ channelHash: String(state[CHANNEL_STATE_INDEX.channelHash]),
14312
+ balanceCommitment: String(state[CHANNEL_STATE_INDEX.balanceCommitment]),
14313
+ nonceField: BigInt(state[CHANNEL_STATE_INDEX.nonceField]),
14314
+ channelState: Number(state[CHANNEL_STATE_INDEX.channelState]),
14315
+ depositTotal: BigInt(state[CHANNEL_STATE_INDEX.depositTotal])
14316
+ };
14317
+ }
13561
14318
  var DEFAULT_MINA_TOKEN_ID = "MINA";
13562
14319
  var MINA_CLAIM_NETWORK = "devnet";
13563
14320
  function deriveMinaSalt(zkAppAddress, nonce) {
@@ -14450,8 +15207,8 @@ var Http402Client = class {
14450
15207
  ...opts.timeout !== void 0 ? { signal: AbortSignal.timeout(opts.timeout) } : {}
14451
15208
  });
14452
15209
  if (probe.status !== 402) return probe;
14453
- const challenge = await parseX402Challenge(probe.clone());
14454
- const accept = challenge.toonChannel;
15210
+ const challenge2 = await parseX402Challenge(probe.clone());
15211
+ const accept = challenge2.toonChannel;
14455
15212
  if (!accept || !this.resolveClaim) return probe;
14456
15213
  return this.payOverToon(url, method, opts, accept, this.resolveClaim);
14457
15214
  }
@@ -14731,6 +15488,7 @@ function buildSwapSettlements(params) {
14731
15488
  claims: [entryToAccumulatedClaim(entry)],
14732
15489
  signers: { [entry.chain]: signer },
14733
15490
  recipients: { [entry.chain]: entry.recipient },
15491
+ ...params.verifySignatures !== void 0 ? { verifySignatures: params.verifySignatures } : {},
14734
15492
  ...params.minaSignerClient ? { minaSignerClient: params.minaSignerClient } : {}
14735
15493
  });
14736
15494
  const firstRejected = result.rejected[0];
@@ -14778,7 +15536,9 @@ function decodeEvmSettlementTx(bundle) {
14778
15536
  const chainIdHex = fields[6];
14779
15537
  const chainId = Number.parseInt(chainIdHex === "0x" ? "0x0" : chainIdHex, 16);
14780
15538
  if (typeof to !== "string" || to.length !== 42) {
14781
- throw new Error(`settlement tx "to" is not a 20-byte address: ${String(to)}`);
15539
+ throw new Error(
15540
+ `settlement tx "to" is not a 20-byte address: ${String(to)}`
15541
+ );
14782
15542
  }
14783
15543
  return { to, data: data === "0x" ? "0x" : data, chainId };
14784
15544
  }
@@ -14795,7 +15555,10 @@ async function submitEvmSettlement(bundle, params) {
14795
15555
  nativeCurrency: { name: "ETH", symbol: "ETH", decimals: 18 },
14796
15556
  rpcUrls: { default: { http: [params.rpcUrl] } }
14797
15557
  });
14798
- const publicClient = createPublicClient3({ chain, transport: http3(params.rpcUrl) });
15558
+ const publicClient = createPublicClient3({
15559
+ chain,
15560
+ transport: http3(params.rpcUrl)
15561
+ });
14799
15562
  const [nonce, gasPrice, gas] = await Promise.all([
14800
15563
  publicClient.getTransactionCount({
14801
15564
  address: params.account.address,
@@ -14827,6 +15590,261 @@ async function submitEvmSettlement(bundle, params) {
14827
15590
  return { txHash };
14828
15591
  }
14829
15592
  }
15593
+ var MinaSettlementError = class extends Error {
15594
+ code;
15595
+ constructor(code, message) {
15596
+ super(`${code}: ${message}`);
15597
+ this.name = "MinaSettlementError";
15598
+ this.code = code;
15599
+ }
15600
+ };
15601
+ function parseProofSignature(proofJson) {
15602
+ const parsed = JSON.parse(proofJson);
15603
+ const r = parsed.signature?.r;
15604
+ const s = parsed.signature?.s;
15605
+ if (typeof r !== "string" || typeof s !== "string") {
15606
+ throw new Error("recipient co-signature proof did not carry string r/s");
15607
+ }
15608
+ return { r, s };
15609
+ }
15610
+ async function buildMinaCoSignedClaim(inputs) {
15611
+ const channelNonce = inputs.channelNonce ?? 0n;
15612
+ const salt = inputs.saltOverride ?? deriveMinaSalt(inputs.channelId, Number(inputs.nonce));
15613
+ if (inputs.cumulativeAmount > inputs.depositTotal) {
15614
+ throw new MinaSettlementError(
15615
+ "CUMULATIVE_EXCEEDS_DEPOSIT",
15616
+ `claim cumulativeAmount (${inputs.cumulativeAmount}) exceeds the channel depositTotal (${inputs.depositTotal}) \u2014 cannot conserve balances`
15617
+ );
15618
+ }
15619
+ const { Poseidon, PublicKey } = await loadMinaPaymentChannelBindings();
15620
+ const hashRecipientFirst = minaParticipantChannelHashField(
15621
+ Poseidon,
15622
+ PublicKey,
15623
+ inputs.recipient,
15624
+ inputs.swapSignerAddress,
15625
+ channelNonce
15626
+ ).toString();
15627
+ const hashMakerFirst = minaParticipantChannelHashField(
15628
+ Poseidon,
15629
+ PublicKey,
15630
+ inputs.swapSignerAddress,
15631
+ inputs.recipient,
15632
+ channelNonce
15633
+ ).toString();
15634
+ let participantA;
15635
+ let participantB;
15636
+ let recipientRole;
15637
+ if (hashRecipientFirst === inputs.onChainChannelHash) {
15638
+ participantA = inputs.recipient;
15639
+ participantB = inputs.swapSignerAddress;
15640
+ recipientRole = "A";
15641
+ } else if (hashMakerFirst === inputs.onChainChannelHash) {
15642
+ participantA = inputs.swapSignerAddress;
15643
+ participantB = inputs.recipient;
15644
+ recipientRole = "B";
15645
+ } else {
15646
+ throw new MinaSettlementError(
15647
+ "CHANNEL_HASH_MISMATCH",
15648
+ `neither ordering of recipient ${inputs.recipient} / maker ${inputs.swapSignerAddress} reproduces the on-chain channelHash ${inputs.onChainChannelHash} (channelNonce ${channelNonce})`
15649
+ );
15650
+ }
15651
+ const recipientBalance = inputs.cumulativeAmount;
15652
+ const makerBalance = inputs.depositTotal - inputs.cumulativeAmount;
15653
+ const balanceA = recipientRole === "A" ? recipientBalance : makerBalance;
15654
+ const balanceB = inputs.depositTotal - balanceA;
15655
+ const balanceCommitment = minaBalanceCommitment(
15656
+ Poseidon,
15657
+ balanceA,
15658
+ balanceB,
15659
+ salt
15660
+ ).toString();
15661
+ const recipientPrivateKeyBase58 = hexToMinaBase58PrivateKey(
15662
+ inputs.recipientPrivateKey
15663
+ );
15664
+ const built = await buildMinaPaymentChannelProof({
15665
+ zkAppAddress: inputs.channelId,
15666
+ minaPrivateKeyBase58: recipientPrivateKeyBase58,
15667
+ signerPublicKey: inputs.recipient,
15668
+ balanceA,
15669
+ balanceB,
15670
+ salt,
15671
+ nonce: inputs.nonce,
15672
+ participantA,
15673
+ participantB,
15674
+ channelNonce,
15675
+ proofEncoding: "json"
15676
+ });
15677
+ if (built.balanceCommitment !== balanceCommitment) {
15678
+ throw new Error(
15679
+ `co-sign commitment drift: builder ${built.balanceCommitment} != ${balanceCommitment}`
15680
+ );
15681
+ }
15682
+ const recipientSignature = parseProofSignature(built.proof);
15683
+ const signatureA = recipientRole === "A" ? recipientSignature : inputs.makerSignature;
15684
+ const signatureB = recipientRole === "B" ? recipientSignature : inputs.makerSignature;
15685
+ return {
15686
+ channelId: inputs.channelId,
15687
+ balanceA,
15688
+ balanceB,
15689
+ salt,
15690
+ nonce: inputs.nonce,
15691
+ channelNonce,
15692
+ balanceCommitment,
15693
+ participantA,
15694
+ participantB,
15695
+ recipientRole,
15696
+ recipientSignature,
15697
+ ...signatureA ? { signatureA } : {},
15698
+ ...signatureB ? { signatureB } : {},
15699
+ makerSignatureMissing: inputs.makerSignature === void 0
15700
+ };
15701
+ }
15702
+ async function submitMinaSettlement(bundle, context) {
15703
+ if (bundle.chainKind !== "mina") {
15704
+ throw new MinaSettlementError(
15705
+ "NOT_MINA_BUNDLE",
15706
+ `submitMinaSettlement only settles mina bundles (got ${bundle.chainKind} for ${bundle.chain})`
15707
+ );
15708
+ }
15709
+ if (!context.graphqlUrl) {
15710
+ throw new MinaSettlementError(
15711
+ "NO_GRAPHQL_CONFIGURED",
15712
+ `no Mina graphqlUrl configured for "${bundle.chain}" \u2014 set minaChannel.graphqlUrl to enable receive-side settlement.`
15713
+ );
15714
+ }
15715
+ const graphqlUrl = context.graphqlUrl;
15716
+ const channelNonce = context.channelNonce ?? 0n;
15717
+ const nonce = BigInt(bundle.nonce);
15718
+ const cumulativeAmount = BigInt(bundle.cumulativeAmount);
15719
+ const read = context.reader ?? readMinaChannelState;
15720
+ const state = await read(graphqlUrl, bundle.channelId);
15721
+ if (state.channelState !== MINA_CHANNEL_STATE.OPEN) {
15722
+ throw new MinaSettlementError(
15723
+ "CHANNEL_NOT_OPEN",
15724
+ `channel ${bundle.channelId} is not OPEN (channelState=${state.channelState}); claimFromChannel only applies to an OPEN channel.`
15725
+ );
15726
+ }
15727
+ if (nonce <= state.nonceField) {
15728
+ throw new MinaSettlementError(
15729
+ "NONCE_NOT_ADVANCING",
15730
+ `claim nonce ${nonce} does not advance the on-chain nonceField ${state.nonceField} for ${bundle.channelId} (already claimed).`
15731
+ );
15732
+ }
15733
+ const claim = await buildMinaCoSignedClaim({
15734
+ channelId: bundle.channelId,
15735
+ nonce,
15736
+ cumulativeAmount,
15737
+ recipient: bundle.recipient,
15738
+ swapSignerAddress: bundle.swapSignerAddress,
15739
+ depositTotal: state.depositTotal,
15740
+ onChainChannelHash: state.channelHash,
15741
+ recipientPrivateKey: context.recipientPrivateKey,
15742
+ channelNonce,
15743
+ ...context.makerSignature ? { makerSignature: context.makerSignature } : {}
15744
+ });
15745
+ if (claim.makerSignatureMissing || !claim.signatureA || !claim.signatureB) {
15746
+ throw new MinaSettlementError(
15747
+ "MINA_MAKER_COSIGN_REQUIRED",
15748
+ `on-chain claimFromChannel is dual-party: it needs the maker's payment-channel-commitment signature over [commitment, nonce, channelHash] in addition to the recipient's co-signature. The swap-wire claim only carries the maker's balanceProofFieldsMina signature (a different message), so the maker must additionally deliver an on-chain-form co-signature. Recipient co-signature assembled and ready (${bundle.channelId} nonce ${nonce}).`
15749
+ );
15750
+ }
15751
+ const submitter = context.submitter ?? createO1jsMinaClaimSubmitter();
15752
+ const { txHash } = await submitter.claimFromChannel({
15753
+ graphqlUrl,
15754
+ channelId: bundle.channelId,
15755
+ balanceA: claim.balanceA,
15756
+ balanceB: claim.balanceB,
15757
+ salt: claim.salt,
15758
+ nonce: claim.nonce,
15759
+ participantA: claim.participantA,
15760
+ participantB: claim.participantB,
15761
+ channelNonce: claim.channelNonce,
15762
+ signatureA: claim.signatureA,
15763
+ signatureB: claim.signatureB,
15764
+ feePayerPrivateKey: context.feePayerPrivateKey ?? context.recipientPrivateKey,
15765
+ ...context.txFeeNanomina !== void 0 ? { txFeeNanomina: context.txFeeNanomina } : {}
15766
+ });
15767
+ return { txHash };
15768
+ }
15769
+ var DEFAULT_MINA_TX_FEE_NANOMINA = 100000000n;
15770
+ function createO1jsMinaClaimSubmitter() {
15771
+ return {
15772
+ async claimFromChannel(args) {
15773
+ try {
15774
+ const o1js = await import("o1js");
15775
+ const {
15776
+ Mina,
15777
+ PrivateKey,
15778
+ PublicKey,
15779
+ Field: Field3,
15780
+ Poseidon,
15781
+ Signature,
15782
+ fetchAccount
15783
+ } = o1js;
15784
+ const zkAppMod = await import("@toon-protocol/mina-zkapp");
15785
+ const PaymentChannel = zkAppMod.PaymentChannel;
15786
+ Mina.setActiveInstance(Mina.Network(args.graphqlUrl));
15787
+ const feePayerKey = PrivateKey.fromBase58(
15788
+ hexToMinaBase58PrivateKey(args.feePayerPrivateKey)
15789
+ );
15790
+ const feePayerPub = feePayerKey.toPublicKey();
15791
+ await PaymentChannel.compile();
15792
+ const zkAppPub = PublicKey.fromBase58(args.channelId);
15793
+ await fetchAccount({ publicKey: zkAppPub });
15794
+ await fetchAccount({ publicKey: feePayerPub });
15795
+ const zkApp = new PaymentChannel(zkAppPub);
15796
+ const balA = Field3(args.balanceA);
15797
+ const balB = Field3(args.balanceB);
15798
+ const saltField = Field3(args.salt);
15799
+ const newNonce = Field3(args.nonce);
15800
+ const channelNonce = Field3(args.channelNonce);
15801
+ const newBalanceCommitment = Poseidon.hash([balA, balB, saltField]);
15802
+ const sigA = Signature.fromJSON({
15803
+ r: args.signatureA.r,
15804
+ s: args.signatureA.s
15805
+ });
15806
+ const sigB = Signature.fromJSON({
15807
+ r: args.signatureB.r,
15808
+ s: args.signatureB.s
15809
+ });
15810
+ const partA = PublicKey.fromBase58(args.participantA);
15811
+ const partB = PublicKey.fromBase58(args.participantB);
15812
+ const fee = (args.txFeeNanomina ?? DEFAULT_MINA_TX_FEE_NANOMINA).toString();
15813
+ const txn = await Mina.transaction(
15814
+ { sender: feePayerPub, fee },
15815
+ async () => {
15816
+ await zkApp.claimFromChannel(
15817
+ balA,
15818
+ balB,
15819
+ saltField,
15820
+ sigA,
15821
+ sigB,
15822
+ partA,
15823
+ partB,
15824
+ channelNonce,
15825
+ newBalanceCommitment,
15826
+ newNonce
15827
+ );
15828
+ }
15829
+ );
15830
+ await txn.prove();
15831
+ const sent = await txn.sign([feePayerKey]).send();
15832
+ return { txHash: sent.hash ?? "" };
15833
+ } catch (err) {
15834
+ throw new MinaSettlementError(
15835
+ "PROVING_FAILED",
15836
+ err instanceof Error ? err.message : String(err)
15837
+ );
15838
+ }
15839
+ }
15840
+ };
15841
+ }
15842
+ function parseMakerMinaSignature(raw) {
15843
+ if (raw && typeof raw.r === "string" && raw.r.length > 0 && typeof raw.s === "string" && raw.s.length > 0) {
15844
+ return { r: raw.r, s: raw.s };
15845
+ }
15846
+ return void 0;
15847
+ }
14830
15848
  var ToonClient = class {
14831
15849
  config;
14832
15850
  state = null;
@@ -15111,34 +16129,11 @@ var ToonClient = class {
15111
16129
  const writeData = buildStoreWriteEnvelope(event, options?.proxyPath);
15112
16130
  const destination = options?.destination ?? this.config.destinationAddress;
15113
16131
  const transport = this.getClaimTransport();
15114
- let claimMessage;
15115
- if (options?.claim) {
15116
- claimMessage = this.buildClaimMessageForProof(options.claim);
15117
- } else if (this.channelManager) {
15118
- const peerId = this.resolvePeerId(destination);
15119
- const negotiation = this.peerNegotiations.get(peerId);
15120
- if (!negotiation) {
15121
- throw new ToonClientError(
15122
- `No negotiation metadata for peer "${peerId}" \u2014 was bootstrap completed?`,
15123
- "PEER_NOT_NEGOTIATED"
15124
- );
15125
- }
15126
- const channelId = await this.channelManager.ensureChannel(
15127
- peerId,
15128
- negotiation
15129
- );
15130
- const proof = await this.channelManager.signBalanceProof(
15131
- channelId,
15132
- BigInt(amount)
15133
- );
15134
- const signer = this.channelManager.getSignerForChannel(channelId);
15135
- claimMessage = signer.buildClaimMessage(proof, this.getPublicKey());
15136
- } else {
15137
- throw new ToonClientError(
15138
- "No claim provided and no channel manager configured",
15139
- "MISSING_CLAIM"
15140
- );
15141
- }
16132
+ const claimMessage = await this.resolveClaimForDestination(
16133
+ destination,
16134
+ BigInt(amount),
16135
+ options?.claim
16136
+ );
15142
16137
  const response = await transport.sendIlpPacketWithClaim(
15143
16138
  {
15144
16139
  destination,
@@ -15345,8 +16340,6 @@ var ToonClient = class {
15345
16340
  }
15346
16341
  /**
15347
16342
  * Shared claim-resolution logic used by `publishEvent` and `sendSwapPacket`.
15348
- * TODO(12.5 followup): also factor `publishEvent`'s inline claim resolution
15349
- * to call this helper. Kept duplicated for now to minimize regression risk.
15350
16343
  */
15351
16344
  async resolveClaimForDestination(destination, amount, explicitClaim) {
15352
16345
  if (explicitClaim) {
@@ -15555,6 +16548,22 @@ var ToonClient = class {
15555
16548
  * swap/settle-received-claims.ts module doc).
15556
16549
  */
15557
16550
  async settleSwapBundle(bundle) {
16551
+ if (bundle.chainKind === "mina") {
16552
+ if (!this.minaPrivateKey) {
16553
+ throw new Error(
16554
+ "Mina signer not configured (no mnemonic / mina-signer) \u2014 cannot co-sign the receive-side claim."
16555
+ );
16556
+ }
16557
+ const makerSignature = parseMakerMinaSignature(
16558
+ this.config.swapMinaMakerSignatures?.[bundle.channelId]
16559
+ );
16560
+ const { txHash } = await submitMinaSettlement(bundle, {
16561
+ recipientPrivateKey: this.minaPrivateKey,
16562
+ ...this.config.minaChannel?.graphqlUrl ? { graphqlUrl: this.config.minaChannel.graphqlUrl } : {},
16563
+ ...makerSignature ? { makerSignature } : {}
16564
+ });
16565
+ return { txHash };
16566
+ }
15558
16567
  if (bundle.chainKind !== "evm") {
15559
16568
  throw new Error(
15560
16569
  `Swap settlement submission for ${bundle.chainKind} (${bundle.chain}) is not wired yet \u2014 EVM only today.`
@@ -15948,6 +16957,85 @@ function fromJson(entry) {
15948
16957
  ...entry.settleTxHash !== void 0 ? { settleTxHash: entry.settleTxHash } : {}
15949
16958
  };
15950
16959
  }
16960
+ var ROLLING_SWAP_DOMAIN_NAME = "RollingSwapChannel";
16961
+ var ROLLING_SWAP_DOMAIN_VERSION = "2";
16962
+ var CLAIM_TYPES = {
16963
+ ClaimBalanceProof: [
16964
+ { name: "channelId", type: "bytes32" },
16965
+ { name: "cumulativeAmount", type: "uint256" },
16966
+ { name: "nonce", type: "uint256" },
16967
+ { name: "recipient", type: "address" }
16968
+ ]
16969
+ };
16970
+ function normalizeAddress(addr) {
16971
+ return addr.toLowerCase();
16972
+ }
16973
+ function domainOf(ctx) {
16974
+ return {
16975
+ name: ROLLING_SWAP_DOMAIN_NAME,
16976
+ version: ROLLING_SWAP_DOMAIN_VERSION,
16977
+ chainId: ctx.chainId,
16978
+ verifyingContract: normalizeAddress(ctx.verifyingContract)
16979
+ };
16980
+ }
16981
+ function evmClaimDigest(ctx, message) {
16982
+ return hashTypedData({
16983
+ domain: domainOf(ctx),
16984
+ types: CLAIM_TYPES,
16985
+ primaryType: "ClaimBalanceProof",
16986
+ message: {
16987
+ channelId: message.channelId,
16988
+ cumulativeAmount: message.cumulativeAmount,
16989
+ nonce: message.nonce,
16990
+ recipient: normalizeAddress(message.recipient)
16991
+ }
16992
+ });
16993
+ }
16994
+ var SIG_BYTES = 65;
16995
+ function signatureToBytes(sig) {
16996
+ if (typeof sig !== "string") return sig;
16997
+ const hex = sig.startsWith("0x") ? sig.slice(2) : sig;
16998
+ return hexToBytes3(hex);
16999
+ }
17000
+ function recoverEvmClaimSigner(ctx, message, signature) {
17001
+ const bytes = signatureToBytes(signature);
17002
+ if (bytes.length !== SIG_BYTES) {
17003
+ throw new Error(
17004
+ `EVM signature must be 65 bytes (r||s||v), got ${bytes.length}`
17005
+ );
17006
+ }
17007
+ const v = bytes[64];
17008
+ if (v !== 27 && v !== 28) {
17009
+ throw new Error(`EVM signature v must be 27 or 28, got ${v}`);
17010
+ }
17011
+ const digest = evmClaimDigest(ctx, message).slice(2);
17012
+ const recovered = secp256k1.Signature.fromBytes(bytes.slice(0, 64), "compact").addRecoveryBit(v - 27).recoverPublicKey(hexToBytes3(digest));
17013
+ const uncompressed = recovered.toBytes(false);
17014
+ const addrHash = keccak_2562(uncompressed.slice(1));
17015
+ return `0x${bytesToHex3(addrHash.slice(-20))}`;
17016
+ }
17017
+ function verifyEvmClaimSignature2(params) {
17018
+ let recovered;
17019
+ try {
17020
+ recovered = recoverEvmClaimSigner(
17021
+ params.ctx,
17022
+ params.message,
17023
+ params.signature
17024
+ );
17025
+ } catch (err) {
17026
+ return {
17027
+ valid: false,
17028
+ reason: `SIGNATURE_INVALID: ${err instanceof Error ? err.message : String(err)}`
17029
+ };
17030
+ }
17031
+ if (recovered.toLowerCase() !== params.expectedSigner.toLowerCase()) {
17032
+ return {
17033
+ valid: false,
17034
+ reason: `SIGNER_MISMATCH: recovered ${recovered}, expected ${params.expectedSigner}`
17035
+ };
17036
+ }
17037
+ return { valid: true, recovered };
17038
+ }
15951
17039
  function hasSettlementMetadata(claim) {
15952
17040
  return claim.channelId !== void 0 && claim.nonce !== void 0 && claim.cumulativeAmount !== void 0 && claim.recipient !== void 0 && claim.swapSignerAddress !== void 0;
15953
17041
  }
@@ -16002,11 +17090,49 @@ function ingestReceivedClaims(params) {
16002
17090
  continue;
16003
17091
  }
16004
17092
  const expectedSigner = params.expectedSignerAddress ?? claim.swapSignerAddress;
16005
- const sig = verifyAccumulatedClaim(
16006
- claim,
16007
- { address: expectedSigner },
16008
- params.minaSignerClient
16009
- );
17093
+ let sig;
17094
+ if (chain.startsWith("evm")) {
17095
+ const chainId = parseEvmChainId2(chain);
17096
+ const verifyingContract = params.tokenNetworks?.[chain];
17097
+ if (chainId === void 0 || !verifyingContract) {
17098
+ reject(
17099
+ claim,
17100
+ "MISSING_CHAIN_CONFIG",
17101
+ `EVM v2 balance-proof verification for ${chain} needs a numeric chain id in the chain key AND tokenNetworks["${chain}"] (the RollingSwapChannel / verifyingContract) to reconstruct the EIP-712 domain; supply it from the connector/swap session context.`
17102
+ );
17103
+ continue;
17104
+ }
17105
+ let msgNonce;
17106
+ let msgCumulative;
17107
+ try {
17108
+ msgNonce = BigInt(claim.nonce);
17109
+ msgCumulative = BigInt(claim.cumulativeAmount);
17110
+ } catch {
17111
+ reject(
17112
+ claim,
17113
+ "MALFORMED_METADATA",
17114
+ `nonce "${claim.nonce}" / cumulativeAmount "${claim.cumulativeAmount}" are not decimal integers`
17115
+ );
17116
+ continue;
17117
+ }
17118
+ sig = verifyEvmClaimSignature2({
17119
+ ctx: { chainId, verifyingContract },
17120
+ message: {
17121
+ channelId: claim.channelId,
17122
+ cumulativeAmount: msgCumulative,
17123
+ nonce: msgNonce,
17124
+ recipient: claim.recipient
17125
+ },
17126
+ signature: claim.claimBytes,
17127
+ expectedSigner
17128
+ });
17129
+ } else {
17130
+ sig = verifyAccumulatedClaim(
17131
+ claim,
17132
+ { address: expectedSigner },
17133
+ params.minaSignerClient
17134
+ );
17135
+ }
16010
17136
  if (!sig.valid) {
16011
17137
  reject(claim, signatureRejectionCode(sig.reason), sig.reason);
16012
17138
  continue;
@@ -16085,6 +17211,92 @@ function ingestReceivedClaims(params) {
16085
17211
  }
16086
17212
  return { verified, rejected, legacy, valueReceived };
16087
17213
  }
17214
+ function copy(entry) {
17215
+ return {
17216
+ packetIndex: entry.packetIndex,
17217
+ preimage: Uint8Array.from(entry.preimage),
17218
+ condition: Uint8Array.from(entry.condition),
17219
+ retainedAt: entry.retainedAt
17220
+ };
17221
+ }
17222
+ var InMemoryPreimageRetentionStore = class {
17223
+ entries = /* @__PURE__ */ new Map();
17224
+ retain(entry) {
17225
+ this.entries.set(entry.packetIndex, copy(entry));
17226
+ }
17227
+ get(packetIndex) {
17228
+ const entry = this.entries.get(packetIndex);
17229
+ return entry ? copy(entry) : void 0;
17230
+ }
17231
+ take(packetIndex) {
17232
+ const entry = this.entries.get(packetIndex);
17233
+ if (!entry) return void 0;
17234
+ this.entries.delete(packetIndex);
17235
+ return copy(entry);
17236
+ }
17237
+ size() {
17238
+ return this.entries.size;
17239
+ }
17240
+ clear() {
17241
+ this.entries.clear();
17242
+ }
17243
+ };
17244
+ function rollbackWatermark(store, chain, channelId, prior) {
17245
+ if (prior === void 0) {
17246
+ store.delete(chain, channelId);
17247
+ } else {
17248
+ store.save(prior);
17249
+ }
17250
+ }
17251
+ async function ingestAndReveal(params) {
17252
+ const { reveal, preimages, claims, store, ...shared } = params;
17253
+ const revealed = [];
17254
+ const rolledBack = [];
17255
+ const rejected = [];
17256
+ const legacy = [];
17257
+ let valueRevealed = 0n;
17258
+ for (const claim of claims) {
17259
+ const hasMeta = hasSettlementMetadata(claim);
17260
+ const chain = hasMeta ? claim.pair.to.chain : void 0;
17261
+ const channelId = hasMeta ? claim.channelId : void 0;
17262
+ const prior = chain !== void 0 && channelId !== void 0 ? store.load(chain, channelId) : void 0;
17263
+ const ingest = ingestReceivedClaims({ ...shared, claims: [claim], store });
17264
+ if (ingest.legacy.length > 0) {
17265
+ legacy.push(claim);
17266
+ continue;
17267
+ }
17268
+ const rejection = ingest.rejected[0];
17269
+ if (rejection) {
17270
+ rejected.push(rejection);
17271
+ continue;
17272
+ }
17273
+ const verified = ingest.verified[0];
17274
+ if (!verified || chain === void 0 || channelId === void 0) continue;
17275
+ const advance = verified.watermarkAdvance;
17276
+ const preimage = preimages?.take(claim.packetIndex);
17277
+ let outcome;
17278
+ try {
17279
+ outcome = await reveal(claim, preimage);
17280
+ } catch (err) {
17281
+ outcome = {
17282
+ decision: "withheld",
17283
+ reason: err instanceof Error ? err.message : String(err)
17284
+ };
17285
+ }
17286
+ if (outcome.decision === "revealed") {
17287
+ revealed.push({ claim, watermarkAdvance: advance });
17288
+ valueRevealed += advance;
17289
+ continue;
17290
+ }
17291
+ rollbackWatermark(store, chain, channelId, prior);
17292
+ rolledBack.push({
17293
+ claim,
17294
+ watermarkAdvance: advance,
17295
+ reason: outcome.reason ?? "reveal withheld"
17296
+ });
17297
+ }
17298
+ return { revealed, rolledBack, rejected, legacy, valueRevealed };
17299
+ }
16088
17300
  function defaultFaucetTimeout(chain) {
16089
17301
  return chain === "mina" ? 12e4 : 3e4;
16090
17302
  }
@@ -16804,7 +18016,8 @@ export {
16804
18016
  ToonClient,
16805
18017
  JsonFileReceivedClaimStore,
16806
18018
  InMemoryReceivedClaimStore,
16807
- ingestReceivedClaims,
18019
+ InMemoryPreimageRetentionStore,
18020
+ ingestAndReveal,
16808
18021
  fundWallet,
16809
18022
  generateKeystore,
16810
18023
  ARWEAVE_GATEWAYS,
@@ -16844,4 +18057,4 @@ export {
16844
18057
  @scure/bip32/lib/esm/index.js:
16845
18058
  (*! scure-bip32 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) *)
16846
18059
  */
16847
- //# sourceMappingURL=chunk-LSPAGZXL.js.map
18060
+ //# sourceMappingURL=chunk-HSSJFB3I.js.map