@toon-protocol/core 1.4.1 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +508 -8
- package/dist/index.js +651 -22
- package/dist/index.js.map +1 -1
- package/package.json +11 -10
package/dist/index.js
CHANGED
|
@@ -27,12 +27,12 @@ var JOB_REVIEW_KIND = 31117;
|
|
|
27
27
|
var WEB_OF_TRUST_KIND = 30382;
|
|
28
28
|
var PREFIX_CLAIM_KIND = 10034;
|
|
29
29
|
var PREFIX_GRANT_KIND = 10037;
|
|
30
|
+
var ILP_ROOT_PREFIX = "g.toon";
|
|
30
31
|
var BLOB_STORAGE_REQUEST_KIND = 5094;
|
|
31
32
|
var BLOB_STORAGE_RESULT_KIND = 6094;
|
|
32
33
|
var PET_INTERACTION_REQUEST_KIND = 5900;
|
|
33
34
|
var PET_INTERACTION_RESULT_KIND = 6900;
|
|
34
35
|
var PET_INTERACTION_EVENT_KIND = 14919;
|
|
35
|
-
var ILP_ROOT_PREFIX = "g.toon";
|
|
36
36
|
|
|
37
37
|
// src/address/ilp-address-validation.ts
|
|
38
38
|
var ILP_SEGMENT_PATTERN = /^[a-z0-9-]+$/;
|
|
@@ -277,15 +277,121 @@ function validatePrefix(prefix) {
|
|
|
277
277
|
return { valid: true };
|
|
278
278
|
}
|
|
279
279
|
|
|
280
|
-
// src/
|
|
280
|
+
// src/chain/chain-id.ts
|
|
281
281
|
function validateChainId(chainId) {
|
|
282
282
|
if (!chainId) return false;
|
|
283
283
|
const segments = chainId.split(":");
|
|
284
284
|
if (segments.length < 2 || segments.length > 3) return false;
|
|
285
285
|
return segments.every((s) => s.length > 0);
|
|
286
286
|
}
|
|
287
|
+
|
|
288
|
+
// src/events/swap-pair-validation.ts
|
|
289
|
+
var RATE_REGEX = /^(0|[1-9]\d*)(\.\d+)?$/;
|
|
290
|
+
var AMOUNT_REGEX = /^\d+$/;
|
|
291
|
+
var MAX_NUMERIC_STRING_LENGTH = 80;
|
|
287
292
|
function isObject(value) {
|
|
288
|
-
return typeof value === "object" && value !== null;
|
|
293
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
294
|
+
}
|
|
295
|
+
function isNonEmptyString(value) {
|
|
296
|
+
return typeof value === "string" && value.length > 0;
|
|
297
|
+
}
|
|
298
|
+
function isNonNegativeInteger(value) {
|
|
299
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 0;
|
|
300
|
+
}
|
|
301
|
+
function validateAsset(asset, side) {
|
|
302
|
+
if (!isObject(asset)) {
|
|
303
|
+
return {
|
|
304
|
+
valid: false,
|
|
305
|
+
reason: `${side} must be an object`,
|
|
306
|
+
field: side
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
if (!isNonEmptyString(asset.assetCode)) {
|
|
310
|
+
return {
|
|
311
|
+
valid: false,
|
|
312
|
+
reason: `${side}.assetCode must be a non-empty string`,
|
|
313
|
+
field: `${side}.assetCode`
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
if (!isNonNegativeInteger(asset.assetScale)) {
|
|
317
|
+
return {
|
|
318
|
+
valid: false,
|
|
319
|
+
reason: `${side}.assetScale must be a non-negative integer`,
|
|
320
|
+
field: `${side}.assetScale`
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
if (typeof asset.chain !== "string" || !validateChainId(asset.chain)) {
|
|
324
|
+
return {
|
|
325
|
+
valid: false,
|
|
326
|
+
reason: `${side}.chain must be a valid chain identifier (e.g., "evm:base:8453")`,
|
|
327
|
+
field: `${side}.chain`
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
return { valid: true };
|
|
331
|
+
}
|
|
332
|
+
function isValidSwapPair(pair) {
|
|
333
|
+
if (!isObject(pair)) {
|
|
334
|
+
return { valid: false, reason: "pair must be an object", field: "" };
|
|
335
|
+
}
|
|
336
|
+
const fromResult = validateAsset(pair.from, "from");
|
|
337
|
+
if (!fromResult.valid) return fromResult;
|
|
338
|
+
const toResult = validateAsset(pair.to, "to");
|
|
339
|
+
if (!toResult.valid) return toResult;
|
|
340
|
+
if (typeof pair.rate !== "string" || pair.rate.length > MAX_NUMERIC_STRING_LENGTH || !RATE_REGEX.test(pair.rate)) {
|
|
341
|
+
return {
|
|
342
|
+
valid: false,
|
|
343
|
+
reason: `rate must be a non-negative decimal string (no leading zeros, no exponent, max ${MAX_NUMERIC_STRING_LENGTH} chars)`,
|
|
344
|
+
field: "rate"
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
if (pair.minAmount !== void 0) {
|
|
348
|
+
if (typeof pair.minAmount !== "string" || pair.minAmount.length > MAX_NUMERIC_STRING_LENGTH || !AMOUNT_REGEX.test(pair.minAmount)) {
|
|
349
|
+
return {
|
|
350
|
+
valid: false,
|
|
351
|
+
reason: `minAmount must be a non-negative integer string (max ${MAX_NUMERIC_STRING_LENGTH} digits)`,
|
|
352
|
+
field: "minAmount"
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
if (pair.maxAmount !== void 0) {
|
|
357
|
+
if (typeof pair.maxAmount !== "string" || pair.maxAmount.length > MAX_NUMERIC_STRING_LENGTH || !AMOUNT_REGEX.test(pair.maxAmount)) {
|
|
358
|
+
return {
|
|
359
|
+
valid: false,
|
|
360
|
+
reason: `maxAmount must be a non-negative integer string (max ${MAX_NUMERIC_STRING_LENGTH} digits)`,
|
|
361
|
+
field: "maxAmount"
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
if (pair.minAmount !== void 0 && pair.maxAmount !== void 0) {
|
|
366
|
+
if (BigInt(pair.minAmount) > BigInt(pair.maxAmount)) {
|
|
367
|
+
return {
|
|
368
|
+
valid: false,
|
|
369
|
+
reason: "minAmount must not exceed maxAmount",
|
|
370
|
+
field: "minAmount/maxAmount"
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
return { valid: true };
|
|
375
|
+
}
|
|
376
|
+
function formatMessage(index, result) {
|
|
377
|
+
return `swapPairs[${index}]: ${result.reason} (field: ${result.field})`;
|
|
378
|
+
}
|
|
379
|
+
function assertSwapPairForBuild(pair, index) {
|
|
380
|
+
const result = isValidSwapPair(pair);
|
|
381
|
+
if (!result.valid) {
|
|
382
|
+
throw new ToonError(formatMessage(index, result), "INVALID_SWAP_PAIR");
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
function assertSwapPairForParse(pair, index) {
|
|
386
|
+
const result = isValidSwapPair(pair);
|
|
387
|
+
if (!result.valid) {
|
|
388
|
+
throw new InvalidEventError(formatMessage(index, result));
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// src/events/parsers.ts
|
|
393
|
+
function isObject2(value) {
|
|
394
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
289
395
|
}
|
|
290
396
|
function parseIlpPeerInfo(event) {
|
|
291
397
|
if (event.kind !== ILP_PEER_INFO_KIND) {
|
|
@@ -302,12 +408,14 @@ function parseIlpPeerInfo(event) {
|
|
|
302
408
|
err instanceof Error ? err : void 0
|
|
303
409
|
);
|
|
304
410
|
}
|
|
305
|
-
if (!
|
|
411
|
+
if (!isObject2(parsed)) {
|
|
306
412
|
throw new InvalidEventError("Event content must be a JSON object");
|
|
307
413
|
}
|
|
308
414
|
const {
|
|
309
415
|
ilpAddress,
|
|
310
416
|
btpEndpoint,
|
|
417
|
+
httpEndpoint,
|
|
418
|
+
supportsUpgrade,
|
|
311
419
|
blsHttpEndpoint,
|
|
312
420
|
settlementEngine,
|
|
313
421
|
assetCode,
|
|
@@ -319,10 +427,14 @@ function parseIlpPeerInfo(event) {
|
|
|
319
427
|
"Missing or invalid required field: ilpAddress"
|
|
320
428
|
);
|
|
321
429
|
}
|
|
322
|
-
if (typeof btpEndpoint !== "string"
|
|
323
|
-
throw new InvalidEventError(
|
|
324
|
-
|
|
325
|
-
|
|
430
|
+
if (btpEndpoint !== void 0 && typeof btpEndpoint !== "string") {
|
|
431
|
+
throw new InvalidEventError("Invalid field: btpEndpoint must be a string");
|
|
432
|
+
}
|
|
433
|
+
if (httpEndpoint !== void 0 && typeof httpEndpoint !== "string") {
|
|
434
|
+
throw new InvalidEventError("Invalid field: httpEndpoint must be a string");
|
|
435
|
+
}
|
|
436
|
+
if (supportsUpgrade !== void 0 && typeof supportsUpgrade !== "boolean") {
|
|
437
|
+
throw new InvalidEventError("Invalid field: supportsUpgrade must be a boolean");
|
|
326
438
|
}
|
|
327
439
|
if (typeof assetCode !== "string" || assetCode.length === 0) {
|
|
328
440
|
throw new InvalidEventError("Missing or invalid required field: assetCode");
|
|
@@ -361,7 +473,7 @@ function parseIlpPeerInfo(event) {
|
|
|
361
473
|
}
|
|
362
474
|
}
|
|
363
475
|
if (settlementAddresses !== void 0) {
|
|
364
|
-
if (!
|
|
476
|
+
if (!isObject2(settlementAddresses)) {
|
|
365
477
|
throw new InvalidEventError("settlementAddresses must be an object");
|
|
366
478
|
}
|
|
367
479
|
for (const [key, value] of Object.entries(settlementAddresses)) {
|
|
@@ -388,12 +500,12 @@ function parseIlpPeerInfo(event) {
|
|
|
388
500
|
}
|
|
389
501
|
}
|
|
390
502
|
if (preferredTokens !== void 0) {
|
|
391
|
-
if (!
|
|
503
|
+
if (!isObject2(preferredTokens)) {
|
|
392
504
|
throw new InvalidEventError("preferredTokens must be an object");
|
|
393
505
|
}
|
|
394
506
|
}
|
|
395
507
|
if (tokenNetworks !== void 0) {
|
|
396
|
-
if (!
|
|
508
|
+
if (!isObject2(tokenNetworks)) {
|
|
397
509
|
throw new InvalidEventError("tokenNetworks must be an object");
|
|
398
510
|
}
|
|
399
511
|
}
|
|
@@ -411,7 +523,7 @@ function parseIlpPeerInfo(event) {
|
|
|
411
523
|
const { prefixPricing: rawPrefixPricing } = parsed;
|
|
412
524
|
let prefixPricing;
|
|
413
525
|
if (rawPrefixPricing !== void 0) {
|
|
414
|
-
if (!
|
|
526
|
+
if (!isObject2(rawPrefixPricing)) {
|
|
415
527
|
throw new InvalidEventError("prefixPricing must be an object");
|
|
416
528
|
}
|
|
417
529
|
const { basePrice } = rawPrefixPricing;
|
|
@@ -422,6 +534,17 @@ function parseIlpPeerInfo(event) {
|
|
|
422
534
|
}
|
|
423
535
|
prefixPricing = { basePrice };
|
|
424
536
|
}
|
|
537
|
+
const { swapPairs: rawSwapPairs } = parsed;
|
|
538
|
+
let swapPairs;
|
|
539
|
+
if (rawSwapPairs !== void 0) {
|
|
540
|
+
if (!Array.isArray(rawSwapPairs)) {
|
|
541
|
+
throw new InvalidEventError("swapPairs must be an array");
|
|
542
|
+
}
|
|
543
|
+
rawSwapPairs.forEach((pair, index) => {
|
|
544
|
+
assertSwapPairForParse(pair, index);
|
|
545
|
+
});
|
|
546
|
+
swapPairs = rawSwapPairs;
|
|
547
|
+
}
|
|
425
548
|
let ilpAddresses;
|
|
426
549
|
if (rawIlpAddresses !== void 0) {
|
|
427
550
|
if (!Array.isArray(rawIlpAddresses)) {
|
|
@@ -445,7 +568,9 @@ function parseIlpPeerInfo(event) {
|
|
|
445
568
|
}
|
|
446
569
|
return {
|
|
447
570
|
ilpAddress,
|
|
448
|
-
btpEndpoint,
|
|
571
|
+
btpEndpoint: typeof btpEndpoint === "string" ? btpEndpoint : "",
|
|
572
|
+
...httpEndpoint !== void 0 && typeof httpEndpoint === "string" && { httpEndpoint },
|
|
573
|
+
...supportsUpgrade !== void 0 && typeof supportsUpgrade === "boolean" && { supportsUpgrade },
|
|
449
574
|
...blsHttpEndpoint !== void 0 && typeof blsHttpEndpoint === "string" && { blsHttpEndpoint },
|
|
450
575
|
assetCode,
|
|
451
576
|
assetScale,
|
|
@@ -460,13 +585,30 @@ function parseIlpPeerInfo(event) {
|
|
|
460
585
|
},
|
|
461
586
|
ilpAddresses,
|
|
462
587
|
feePerByte,
|
|
463
|
-
...prefixPricing !== void 0 && { prefixPricing }
|
|
588
|
+
...prefixPricing !== void 0 && { prefixPricing },
|
|
589
|
+
...swapPairs !== void 0 && { swapPairs }
|
|
464
590
|
};
|
|
465
591
|
}
|
|
466
592
|
|
|
467
593
|
// src/events/builders.ts
|
|
468
594
|
import { finalizeEvent } from "nostr-tools/pure";
|
|
469
|
-
|
|
595
|
+
|
|
596
|
+
// src/events/nip40.ts
|
|
597
|
+
var EXPIRATION_TAG = "expiration";
|
|
598
|
+
function getEventExpiration(event) {
|
|
599
|
+
const tag = event.tags.find((t) => t[0] === EXPIRATION_TAG);
|
|
600
|
+
if (!tag || tag[1] === void 0) return void 0;
|
|
601
|
+
const ts = Number(tag[1]);
|
|
602
|
+
if (!Number.isFinite(ts) || ts < 0) return void 0;
|
|
603
|
+
return ts;
|
|
604
|
+
}
|
|
605
|
+
function isEventExpired(event, nowSeconds = Math.floor(Date.now() / 1e3)) {
|
|
606
|
+
const exp = getEventExpiration(event);
|
|
607
|
+
return exp !== void 0 && exp <= nowSeconds;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
// src/events/builders.ts
|
|
611
|
+
function buildIlpPeerInfoEvent(info, secretKey, options = {}) {
|
|
470
612
|
if (info.feePerByte !== void 0) {
|
|
471
613
|
if (typeof info.feePerByte !== "string" || !/^\d+$/.test(info.feePerByte)) {
|
|
472
614
|
throw new ToonError(
|
|
@@ -498,12 +640,31 @@ function buildIlpPeerInfoEvent(info, secretKey) {
|
|
|
498
640
|
ilpAddress: primaryAddress
|
|
499
641
|
};
|
|
500
642
|
}
|
|
643
|
+
if (info.swapPairs !== void 0) {
|
|
644
|
+
if (!Array.isArray(info.swapPairs)) {
|
|
645
|
+
throw new ToonError(
|
|
646
|
+
"swapPairs must be an array when provided",
|
|
647
|
+
"INVALID_SWAP_PAIR"
|
|
648
|
+
);
|
|
649
|
+
}
|
|
650
|
+
info.swapPairs.forEach((pair, index) => {
|
|
651
|
+
assertSwapPairForBuild(pair, index);
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
const createdAt = Math.floor(Date.now() / 1e3);
|
|
655
|
+
const tags = [];
|
|
656
|
+
if (options.ttlSeconds !== void 0 && options.ttlSeconds > 0) {
|
|
657
|
+
tags.push([
|
|
658
|
+
EXPIRATION_TAG,
|
|
659
|
+
String(createdAt + Math.floor(options.ttlSeconds))
|
|
660
|
+
]);
|
|
661
|
+
}
|
|
501
662
|
return finalizeEvent(
|
|
502
663
|
{
|
|
503
664
|
kind: ILP_PEER_INFO_KIND,
|
|
504
665
|
content: JSON.stringify(effectiveInfo),
|
|
505
|
-
tags
|
|
506
|
-
created_at:
|
|
666
|
+
tags,
|
|
667
|
+
created_at: createdAt
|
|
507
668
|
},
|
|
508
669
|
secretKey
|
|
509
670
|
);
|
|
@@ -1220,7 +1381,8 @@ function buildWorkflowDefinitionEvent(params, secretKey) {
|
|
|
1220
1381
|
};
|
|
1221
1382
|
const contentJson = JSON.stringify(contentBody);
|
|
1222
1383
|
const tags = [];
|
|
1223
|
-
const
|
|
1384
|
+
const randomSuffix = Math.random().toString(36).slice(2, 8);
|
|
1385
|
+
const dTag = params.workflowId ?? `wf-${Date.now()}-${params.steps.length}-${randomSuffix}`;
|
|
1224
1386
|
tags.push(["d", dTag]);
|
|
1225
1387
|
tags.push(["bid", params.totalBid, "usdc"]);
|
|
1226
1388
|
return finalizeEvent6(
|
|
@@ -2486,6 +2648,12 @@ var SeedRelayDiscovery = class {
|
|
|
2486
2648
|
);
|
|
2487
2649
|
continue;
|
|
2488
2650
|
}
|
|
2651
|
+
if (isEventExpired(event)) {
|
|
2652
|
+
console.warn(
|
|
2653
|
+
`[SeedRelayDiscovery] Skipping expired kind:10032 announcement: ${event.id}`
|
|
2654
|
+
);
|
|
2655
|
+
continue;
|
|
2656
|
+
}
|
|
2489
2657
|
const info = parseIlpPeerInfo(event);
|
|
2490
2658
|
info.pubkey = event.pubkey;
|
|
2491
2659
|
discoveredPeers.push(info);
|
|
@@ -2749,6 +2917,152 @@ function resolveTokenForChain(chain, requesterPreferredTokens, responderPreferre
|
|
|
2749
2917
|
return void 0;
|
|
2750
2918
|
}
|
|
2751
2919
|
|
|
2920
|
+
// src/settlement/hashes.ts
|
|
2921
|
+
import { keccak_256 } from "@noble/hashes/sha3.js";
|
|
2922
|
+
import { sha256 } from "@noble/hashes/sha2.js";
|
|
2923
|
+
import {
|
|
2924
|
+
bytesToHex,
|
|
2925
|
+
hexToBytes as nobleHexToBytes
|
|
2926
|
+
} from "@noble/hashes/utils.js";
|
|
2927
|
+
function hexToBytes(hex) {
|
|
2928
|
+
const clean = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
2929
|
+
if (clean.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(clean)) {
|
|
2930
|
+
throw new Error(`Invalid hex string: ${hex}`);
|
|
2931
|
+
}
|
|
2932
|
+
return nobleHexToBytes(clean);
|
|
2933
|
+
}
|
|
2934
|
+
function bigintToBytes32BE(x) {
|
|
2935
|
+
if (x < 0n) {
|
|
2936
|
+
throw new Error("bigint must be non-negative for balance-proof encoding");
|
|
2937
|
+
}
|
|
2938
|
+
const out = new Uint8Array(32);
|
|
2939
|
+
let v = x;
|
|
2940
|
+
for (let i = 31; i >= 0; i--) {
|
|
2941
|
+
out[i] = Number(v & 0xffn);
|
|
2942
|
+
v >>= 8n;
|
|
2943
|
+
}
|
|
2944
|
+
if (v !== 0n) {
|
|
2945
|
+
throw new Error("bigint exceeds 256 bits");
|
|
2946
|
+
}
|
|
2947
|
+
return out;
|
|
2948
|
+
}
|
|
2949
|
+
function concatBytes(...parts) {
|
|
2950
|
+
let len = 0;
|
|
2951
|
+
for (const p of parts) len += p.length;
|
|
2952
|
+
const out = new Uint8Array(len);
|
|
2953
|
+
let o = 0;
|
|
2954
|
+
for (const p of parts) {
|
|
2955
|
+
out.set(p, o);
|
|
2956
|
+
o += p.length;
|
|
2957
|
+
}
|
|
2958
|
+
return out;
|
|
2959
|
+
}
|
|
2960
|
+
function balanceProofHashEvm(channelIdBytes, cumulativeAmount, nonce, recipientBytes) {
|
|
2961
|
+
return keccak_256(
|
|
2962
|
+
concatBytes(
|
|
2963
|
+
channelIdBytes,
|
|
2964
|
+
bigintToBytes32BE(cumulativeAmount),
|
|
2965
|
+
bigintToBytes32BE(nonce),
|
|
2966
|
+
recipientBytes
|
|
2967
|
+
)
|
|
2968
|
+
);
|
|
2969
|
+
}
|
|
2970
|
+
function balanceProofHashSolana(channelId, cumulativeAmount, nonce, recipient) {
|
|
2971
|
+
return sha256(
|
|
2972
|
+
concatBytes(
|
|
2973
|
+
new TextEncoder().encode(channelId),
|
|
2974
|
+
bigintToBytes32BE(cumulativeAmount),
|
|
2975
|
+
bigintToBytes32BE(nonce),
|
|
2976
|
+
new TextEncoder().encode(recipient)
|
|
2977
|
+
)
|
|
2978
|
+
);
|
|
2979
|
+
}
|
|
2980
|
+
function minaHashToField(s) {
|
|
2981
|
+
const digestHex = bytesToHex(sha256(new TextEncoder().encode(s)));
|
|
2982
|
+
return BigInt("0x" + digestHex.slice(0, 60));
|
|
2983
|
+
}
|
|
2984
|
+
function balanceProofFieldsMina(channelId, cumulativeAmount, nonce, recipient) {
|
|
2985
|
+
return [
|
|
2986
|
+
minaHashToField(channelId),
|
|
2987
|
+
cumulativeAmount,
|
|
2988
|
+
nonce,
|
|
2989
|
+
minaHashToField(recipient)
|
|
2990
|
+
];
|
|
2991
|
+
}
|
|
2992
|
+
|
|
2993
|
+
// src/settlement/base58.ts
|
|
2994
|
+
var BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
2995
|
+
function base58Encode(bytes) {
|
|
2996
|
+
let zeros = 0;
|
|
2997
|
+
for (let i = 0; i < bytes.length && bytes[i] === 0; i++) zeros++;
|
|
2998
|
+
let value = 0n;
|
|
2999
|
+
for (const byte of bytes) {
|
|
3000
|
+
value = value * 256n + BigInt(byte);
|
|
3001
|
+
}
|
|
3002
|
+
let result = "";
|
|
3003
|
+
while (value > 0n) {
|
|
3004
|
+
result = BASE58_ALPHABET[Number(value % 58n)] + result;
|
|
3005
|
+
value = value / 58n;
|
|
3006
|
+
}
|
|
3007
|
+
for (let i = 0; i < zeros; i++) {
|
|
3008
|
+
result = "1" + result;
|
|
3009
|
+
}
|
|
3010
|
+
return result || "1";
|
|
3011
|
+
}
|
|
3012
|
+
function base58Decode(str) {
|
|
3013
|
+
let zeros = 0;
|
|
3014
|
+
for (let i = 0; i < str.length && str[i] === "1"; i++) zeros++;
|
|
3015
|
+
let value = 0n;
|
|
3016
|
+
for (const ch of str) {
|
|
3017
|
+
const idx = BASE58_ALPHABET.indexOf(ch);
|
|
3018
|
+
if (idx === -1) throw new Error(`Invalid base58 character: ${ch}`);
|
|
3019
|
+
value = value * 58n + BigInt(idx);
|
|
3020
|
+
}
|
|
3021
|
+
const hex = value === 0n ? "" : value.toString(16);
|
|
3022
|
+
const hexPadded = hex.length % 2 ? "0" + hex : hex;
|
|
3023
|
+
const rawBytes = [];
|
|
3024
|
+
for (let i = 0; i < hexPadded.length; i += 2) {
|
|
3025
|
+
rawBytes.push(parseInt(hexPadded.slice(i, i + 2), 16));
|
|
3026
|
+
}
|
|
3027
|
+
const result = new Uint8Array(zeros + rawBytes.length);
|
|
3028
|
+
result.set(rawBytes, zeros);
|
|
3029
|
+
return result;
|
|
3030
|
+
}
|
|
3031
|
+
|
|
3032
|
+
// src/settlement/mina-key.ts
|
|
3033
|
+
import { sha256 as sha2562 } from "@noble/hashes/sha2.js";
|
|
3034
|
+
var MINA_PRIVATE_KEY_VERSION = 90;
|
|
3035
|
+
function hexToMinaBase58PrivateKey(privateKey) {
|
|
3036
|
+
if (!/^(0x)?[0-9a-fA-F]{64}$/.test(privateKey)) {
|
|
3037
|
+
return privateKey;
|
|
3038
|
+
}
|
|
3039
|
+
const beScalar = hexToBytes(privateKey);
|
|
3040
|
+
const leScalar = Uint8Array.from(beScalar).reverse();
|
|
3041
|
+
const payload = concatBytes(
|
|
3042
|
+
Uint8Array.from([MINA_PRIVATE_KEY_VERSION, 1]),
|
|
3043
|
+
leScalar
|
|
3044
|
+
);
|
|
3045
|
+
const checksum = sha2562(sha2562(payload)).slice(0, 4);
|
|
3046
|
+
return base58Encode(concatBytes(payload, checksum));
|
|
3047
|
+
}
|
|
3048
|
+
async function deriveMinaPublicKeyBase58(privateKey) {
|
|
3049
|
+
let signerModule = null;
|
|
3050
|
+
try {
|
|
3051
|
+
const specifier = "mina-signer";
|
|
3052
|
+
signerModule = await import(
|
|
3053
|
+
/* @vite-ignore */
|
|
3054
|
+
specifier
|
|
3055
|
+
);
|
|
3056
|
+
} catch {
|
|
3057
|
+
return null;
|
|
3058
|
+
}
|
|
3059
|
+
if (!signerModule) return null;
|
|
3060
|
+
const mod = signerModule;
|
|
3061
|
+
const ClientCtor = mod.default ?? mod;
|
|
3062
|
+
const client = new ClientCtor({ network: "mainnet" });
|
|
3063
|
+
return client.derivePublicKey(hexToMinaBase58PrivateKey(privateKey));
|
|
3064
|
+
}
|
|
3065
|
+
|
|
2752
3066
|
// src/bootstrap/BootstrapService.ts
|
|
2753
3067
|
import { SimplePool as SimplePool3 } from "nostr-tools/pool";
|
|
2754
3068
|
import { getPublicKey as getPublicKey3 } from "nostr-tools/pure";
|
|
@@ -4097,6 +4411,32 @@ var AttestationBootstrap = class {
|
|
|
4097
4411
|
}
|
|
4098
4412
|
};
|
|
4099
4413
|
|
|
4414
|
+
// src/utils/reject-code.ts
|
|
4415
|
+
var ILP_TO_SEMANTIC = Object.freeze({
|
|
4416
|
+
T00: "internal_error",
|
|
4417
|
+
T04: "insufficient_funds",
|
|
4418
|
+
F00: "invalid_request",
|
|
4419
|
+
// F01 ("Invalid Packet" in ILP terms — emitted by the swap handler for
|
|
4420
|
+
// "Invalid gift wrap" / "Invalid amount") has NO dedicated entry in the
|
|
4421
|
+
// connector's REJECT_CODE_MAP (accepted semantics are: insufficient_funds,
|
|
4422
|
+
// expired, unreachable, invalid_request, invalid_amount,
|
|
4423
|
+
// insufficient_destination_amount, unexpected_payment, application_error,
|
|
4424
|
+
// internal_error, timeout). The closest faithful reason is `invalid_request`,
|
|
4425
|
+
// which the connector re-encodes to wire code F00. We map F01 EXPLICITLY
|
|
4426
|
+
// (rather than relying on the fallback below) so the F01 -> F00 normalization
|
|
4427
|
+
// is intentional and test-pinned, not a silent collapse that misleads callers
|
|
4428
|
+
// into thinking they hit a different failure class. See issue #86.
|
|
4429
|
+
F01: "invalid_request",
|
|
4430
|
+
F02: "unreachable",
|
|
4431
|
+
F03: "invalid_amount",
|
|
4432
|
+
F04: "insufficient_destination_amount",
|
|
4433
|
+
F06: "unexpected_payment",
|
|
4434
|
+
R00: "expired"
|
|
4435
|
+
});
|
|
4436
|
+
function ilpCodeToSemantic(ilpCode) {
|
|
4437
|
+
return ILP_TO_SEMANTIC[ilpCode] ?? "invalid_request";
|
|
4438
|
+
}
|
|
4439
|
+
|
|
4100
4440
|
// src/compose.ts
|
|
4101
4441
|
function createToonNode(config) {
|
|
4102
4442
|
const directIlpClient = createDirectIlpClient(config.connector, {
|
|
@@ -4156,7 +4496,7 @@ function createToonNode(config) {
|
|
|
4156
4496
|
}
|
|
4157
4497
|
const adapted = result;
|
|
4158
4498
|
adapted.rejectReason = {
|
|
4159
|
-
code: result.code,
|
|
4499
|
+
code: ilpCodeToSemantic(result.code),
|
|
4160
4500
|
message: result.message
|
|
4161
4501
|
};
|
|
4162
4502
|
return adapted;
|
|
@@ -4227,6 +4567,29 @@ var CHAIN_PRESETS = {
|
|
|
4227
4567
|
usdcAddress: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
|
|
4228
4568
|
tokenNetworkAddress: "",
|
|
4229
4569
|
registryAddress: ""
|
|
4570
|
+
},
|
|
4571
|
+
// Base Sepolia (public testnet) — TOON's deployed public-testnet settlement
|
|
4572
|
+
// environment (source of truth: e2e/testnets.json). USDC is the deployed test
|
|
4573
|
+
// token the TokenNetwork was opened against (NOT Circle's native testnet USDC,
|
|
4574
|
+
// which the channel would not recognise). Registry + TokenNetwork are live, so
|
|
4575
|
+
// this preset is settlement-complete: `--network testnet|devnet` settles here.
|
|
4576
|
+
"base-sepolia": {
|
|
4577
|
+
name: "base-sepolia",
|
|
4578
|
+
chainId: 84532,
|
|
4579
|
+
rpcUrl: "https://sepolia.base.org",
|
|
4580
|
+
usdcAddress: "0xac80670b86db1eeb5c18c82e18a6bda98fcb4504",
|
|
4581
|
+
tokenNetworkAddress: "0x47616F4b9cF4dA25F74FD727Cd85E9CA0C70Ec5C",
|
|
4582
|
+
registryAddress: "0xb9516c6c53c016c43f3671b1e5eb6096c83ec2c7"
|
|
4583
|
+
},
|
|
4584
|
+
// Base mainnet (public). USDC is Circle's native USDC on Base.
|
|
4585
|
+
// TOON TokenNetwork/registry not deployed yet → settlement relay-only.
|
|
4586
|
+
"base-mainnet": {
|
|
4587
|
+
name: "base-mainnet",
|
|
4588
|
+
chainId: 8453,
|
|
4589
|
+
rpcUrl: "https://mainnet.base.org",
|
|
4590
|
+
usdcAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
4591
|
+
tokenNetworkAddress: "",
|
|
4592
|
+
registryAddress: ""
|
|
4230
4593
|
}
|
|
4231
4594
|
};
|
|
4232
4595
|
function resolveChainConfig(chain) {
|
|
@@ -4234,8 +4597,9 @@ function resolveChainConfig(chain) {
|
|
|
4234
4597
|
const name = envChain || chain || "anvil";
|
|
4235
4598
|
const preset = CHAIN_PRESETS[name];
|
|
4236
4599
|
if (!preset) {
|
|
4600
|
+
const validNames = Object.keys(CHAIN_PRESETS).join(", ");
|
|
4237
4601
|
throw new ToonError(
|
|
4238
|
-
`Unknown chain "${name}". Valid chains:
|
|
4602
|
+
`Unknown chain "${name}". Valid chains: ${validNames}`,
|
|
4239
4603
|
"INVALID_CHAIN"
|
|
4240
4604
|
);
|
|
4241
4605
|
}
|
|
@@ -4328,6 +4692,7 @@ function buildEvmProviderEntry(config, keyId) {
|
|
|
4328
4692
|
chainId: `evm:${config.chainId}`,
|
|
4329
4693
|
rpcUrl: config.rpcUrl,
|
|
4330
4694
|
registryAddress: config.registryAddress,
|
|
4695
|
+
tokenAddress: config.usdcAddress,
|
|
4331
4696
|
keyId
|
|
4332
4697
|
};
|
|
4333
4698
|
}
|
|
@@ -4354,6 +4719,251 @@ function buildMinaProviderEntry(config, keyId) {
|
|
|
4354
4719
|
};
|
|
4355
4720
|
}
|
|
4356
4721
|
|
|
4722
|
+
// src/chain/network-profile.ts
|
|
4723
|
+
var DEV_EVM_PRESET = "anvil";
|
|
4724
|
+
var DEV_SOLANA = {
|
|
4725
|
+
usdcMint: "6GbdrVghwNKTz9raga7y3Y4qqX5Zgg3AC4d48Kt7C59Q",
|
|
4726
|
+
programId: ""
|
|
4727
|
+
// TOON payment-channel program not deployed on the dev Solana node
|
|
4728
|
+
};
|
|
4729
|
+
var RELAY_ONLY_CHAIN = "none";
|
|
4730
|
+
var EVM_TIER = {
|
|
4731
|
+
mainnet: { primary: "base-mainnet", also: ["arbitrum-one"] },
|
|
4732
|
+
testnet: { primary: "base-sepolia", also: ["arbitrum-sepolia"] },
|
|
4733
|
+
// EVM has no public devnet → the public Sepolia testnets serve the devnet tier.
|
|
4734
|
+
devnet: { primary: "base-sepolia", also: ["arbitrum-sepolia"] }
|
|
4735
|
+
};
|
|
4736
|
+
var SOLANA_DEPLOYED_DEVNET = {
|
|
4737
|
+
rpcUrl: "https://api.devnet.solana.com",
|
|
4738
|
+
cluster: "devnet",
|
|
4739
|
+
usdcMint: "9FtYCXjNiGDn17jSGvZuB5P4dZAKgVxUsDiQpLc8rbWy",
|
|
4740
|
+
programId: "EdJxYPDxGvaJuu57DSUptf4soLv8enpdyQJJhHDLiydG"
|
|
4741
|
+
};
|
|
4742
|
+
var SOLANA_TIER = {
|
|
4743
|
+
mainnet: {
|
|
4744
|
+
rpcUrl: "https://api.mainnet-beta.solana.com",
|
|
4745
|
+
cluster: "mainnet-beta",
|
|
4746
|
+
usdcMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
|
|
4747
|
+
programId: ""
|
|
4748
|
+
// TOON payment-channel program not deployed on mainnet
|
|
4749
|
+
},
|
|
4750
|
+
testnet: SOLANA_DEPLOYED_DEVNET,
|
|
4751
|
+
devnet: SOLANA_DEPLOYED_DEVNET
|
|
4752
|
+
};
|
|
4753
|
+
var MINA_DEPLOYED_DEVNET = {
|
|
4754
|
+
graphqlUrl: "https://api.minascan.io/node/devnet/v1/graphql",
|
|
4755
|
+
network: "devnet",
|
|
4756
|
+
// Reconciled with e2e/testnets.json (#205): the previous address
|
|
4757
|
+
// (B62qjFgX…) is a bare, unfunded zkApp on-chain (balance 0, channel
|
|
4758
|
+
// nonceField 0) — usable for claim issuance only. This is the funded,
|
|
4759
|
+
// on-chain-settling PaymentChannel zkApp (balance ~4 MINA, nonceField 21
|
|
4760
|
+
// — the on-chain settle proven in #217), same VK hash 21482326…
|
|
4761
|
+
zkAppAddress: "B62qrH1As4odHiNyKpTZMHaM6tRs6gi5DJ53efZKQBtbaR5CUctbDs6"
|
|
4762
|
+
};
|
|
4763
|
+
var MINA_TIER = {
|
|
4764
|
+
mainnet: {
|
|
4765
|
+
graphqlUrl: "https://api.minascan.io/node/mainnet/v1/graphql",
|
|
4766
|
+
network: "mainnet",
|
|
4767
|
+
zkAppAddress: ""
|
|
4768
|
+
// TOON payment-channel zkApp not deployed on mainnet
|
|
4769
|
+
},
|
|
4770
|
+
testnet: MINA_DEPLOYED_DEVNET,
|
|
4771
|
+
devnet: MINA_DEPLOYED_DEVNET
|
|
4772
|
+
};
|
|
4773
|
+
function evmSettlementComplete(p) {
|
|
4774
|
+
return p.registryAddress !== "" && p.tokenNetworkAddress !== "";
|
|
4775
|
+
}
|
|
4776
|
+
function resolveNetworkProfile(network, opts = {}) {
|
|
4777
|
+
if (network === "custom") {
|
|
4778
|
+
return resolveCustom(
|
|
4779
|
+
opts.customProviders ?? [],
|
|
4780
|
+
opts.endpoints ?? {},
|
|
4781
|
+
opts.keyId
|
|
4782
|
+
);
|
|
4783
|
+
}
|
|
4784
|
+
const tier = network;
|
|
4785
|
+
const chainProviders = [];
|
|
4786
|
+
const status = {
|
|
4787
|
+
evm: "unconfigured",
|
|
4788
|
+
solana: "unconfigured",
|
|
4789
|
+
mina: "unconfigured"
|
|
4790
|
+
};
|
|
4791
|
+
const primary = CHAIN_PRESETS[EVM_TIER[tier].primary];
|
|
4792
|
+
const nodeEnv = {
|
|
4793
|
+
EVM_CHAIN: primary.name,
|
|
4794
|
+
EVM_RPC_URL: primary.rpcUrl,
|
|
4795
|
+
EVM_CHAIN_ID: String(primary.chainId),
|
|
4796
|
+
EVM_USDC_ADDRESS: primary.usdcAddress
|
|
4797
|
+
};
|
|
4798
|
+
if (opts.keyId) {
|
|
4799
|
+
for (const name of [EVM_TIER[tier].primary, ...EVM_TIER[tier].also]) {
|
|
4800
|
+
const preset = CHAIN_PRESETS[name];
|
|
4801
|
+
if (evmSettlementComplete(preset)) {
|
|
4802
|
+
chainProviders.push(buildEvmProviderEntry(preset, opts.keyId));
|
|
4803
|
+
status.evm = "configured";
|
|
4804
|
+
}
|
|
4805
|
+
}
|
|
4806
|
+
}
|
|
4807
|
+
const sol = SOLANA_TIER[tier];
|
|
4808
|
+
nodeEnv.SOLANA_RPC_URL = sol.rpcUrl;
|
|
4809
|
+
if (sol.usdcMint) nodeEnv.SOLANA_USDC_MINT = sol.usdcMint;
|
|
4810
|
+
if (opts.keyId && sol.programId) {
|
|
4811
|
+
chainProviders.push(
|
|
4812
|
+
buildSolanaProviderEntry(
|
|
4813
|
+
{
|
|
4814
|
+
name: `solana-${sol.cluster}`,
|
|
4815
|
+
chainType: "solana",
|
|
4816
|
+
rpcUrl: sol.rpcUrl,
|
|
4817
|
+
programId: sol.programId,
|
|
4818
|
+
cluster: sol.cluster,
|
|
4819
|
+
...sol.usdcMint && { tokenMint: sol.usdcMint }
|
|
4820
|
+
},
|
|
4821
|
+
opts.keyId
|
|
4822
|
+
)
|
|
4823
|
+
);
|
|
4824
|
+
status.solana = "configured";
|
|
4825
|
+
}
|
|
4826
|
+
const mina = MINA_TIER[tier];
|
|
4827
|
+
if (opts.keyId && mina.zkAppAddress) {
|
|
4828
|
+
chainProviders.push(
|
|
4829
|
+
buildMinaProviderEntry(
|
|
4830
|
+
{
|
|
4831
|
+
name: `mina-${mina.network}`,
|
|
4832
|
+
chainType: "mina",
|
|
4833
|
+
graphqlUrl: mina.graphqlUrl,
|
|
4834
|
+
zkAppAddress: mina.zkAppAddress,
|
|
4835
|
+
network: mina.network
|
|
4836
|
+
},
|
|
4837
|
+
opts.keyId
|
|
4838
|
+
)
|
|
4839
|
+
);
|
|
4840
|
+
status.mina = "configured";
|
|
4841
|
+
}
|
|
4842
|
+
return { network, chainProviders, nodeEnv, status };
|
|
4843
|
+
}
|
|
4844
|
+
function evmClientId(preset) {
|
|
4845
|
+
const family = preset.name.split("-")[0] ?? preset.name;
|
|
4846
|
+
return `evm:${family}:${preset.chainId}`;
|
|
4847
|
+
}
|
|
4848
|
+
function resolveClientNetwork(network) {
|
|
4849
|
+
const supportedChains = [];
|
|
4850
|
+
const chainRpcUrls = {};
|
|
4851
|
+
const preferredTokens = {};
|
|
4852
|
+
const tokenNetworks = {};
|
|
4853
|
+
const status = {
|
|
4854
|
+
evm: "unconfigured",
|
|
4855
|
+
solana: "unconfigured",
|
|
4856
|
+
mina: "unconfigured"
|
|
4857
|
+
};
|
|
4858
|
+
const evm = CHAIN_PRESETS[EVM_TIER[network].primary];
|
|
4859
|
+
const evmId = evmClientId(evm);
|
|
4860
|
+
supportedChains.push(evmId);
|
|
4861
|
+
chainRpcUrls[evmId] = evm.rpcUrl;
|
|
4862
|
+
if (evm.usdcAddress) preferredTokens[evmId] = evm.usdcAddress;
|
|
4863
|
+
if (evmSettlementComplete(evm)) {
|
|
4864
|
+
tokenNetworks[evmId] = evm.tokenNetworkAddress;
|
|
4865
|
+
status.evm = "configured";
|
|
4866
|
+
}
|
|
4867
|
+
const sol = SOLANA_TIER[network];
|
|
4868
|
+
const solId = `solana:${sol.cluster}`;
|
|
4869
|
+
supportedChains.push(solId);
|
|
4870
|
+
chainRpcUrls[solId] = sol.rpcUrl;
|
|
4871
|
+
if (sol.usdcMint) preferredTokens[solId] = sol.usdcMint;
|
|
4872
|
+
let solanaChannel;
|
|
4873
|
+
if (sol.programId) {
|
|
4874
|
+
solanaChannel = {
|
|
4875
|
+
rpcUrl: sol.rpcUrl,
|
|
4876
|
+
programId: sol.programId,
|
|
4877
|
+
...sol.usdcMint && { tokenMint: sol.usdcMint }
|
|
4878
|
+
};
|
|
4879
|
+
status.solana = "configured";
|
|
4880
|
+
}
|
|
4881
|
+
const mina = MINA_TIER[network];
|
|
4882
|
+
const minaId = `mina:${mina.network}`;
|
|
4883
|
+
supportedChains.push(minaId);
|
|
4884
|
+
chainRpcUrls[minaId] = mina.graphqlUrl;
|
|
4885
|
+
let minaChannel;
|
|
4886
|
+
if (mina.zkAppAddress) {
|
|
4887
|
+
minaChannel = {
|
|
4888
|
+
graphqlUrl: mina.graphqlUrl,
|
|
4889
|
+
zkAppAddress: mina.zkAppAddress,
|
|
4890
|
+
networkId: mina.network === "mainnet" ? "mainnet" : "devnet"
|
|
4891
|
+
};
|
|
4892
|
+
status.mina = "configured";
|
|
4893
|
+
}
|
|
4894
|
+
return {
|
|
4895
|
+
supportedChains,
|
|
4896
|
+
chainRpcUrls,
|
|
4897
|
+
preferredTokens,
|
|
4898
|
+
tokenNetworks,
|
|
4899
|
+
...solanaChannel && { solanaChannel },
|
|
4900
|
+
...minaChannel && { minaChannel },
|
|
4901
|
+
status
|
|
4902
|
+
};
|
|
4903
|
+
}
|
|
4904
|
+
function resolveCustom(providers, endpoints, keyId) {
|
|
4905
|
+
if (providers.length === 0 && (endpoints.evmUrl || endpoints.solUrl)) {
|
|
4906
|
+
return resolveCustomEndpoints(endpoints, keyId);
|
|
4907
|
+
}
|
|
4908
|
+
const status = {
|
|
4909
|
+
evm: "unconfigured",
|
|
4910
|
+
solana: "unconfigured",
|
|
4911
|
+
mina: "unconfigured"
|
|
4912
|
+
};
|
|
4913
|
+
const nodeEnv = {};
|
|
4914
|
+
const evm = providers.find((p) => p.chainType === "evm");
|
|
4915
|
+
if (evm && evm.chainType === "evm") {
|
|
4916
|
+
nodeEnv.EVM_RPC_URL = evm.rpcUrl;
|
|
4917
|
+
nodeEnv.EVM_CHAIN_ID = evm.chainId.replace(/^evm:/, "");
|
|
4918
|
+
nodeEnv.EVM_USDC_ADDRESS = evm.tokenAddress;
|
|
4919
|
+
nodeEnv.EVM_CHAIN = RELAY_ONLY_CHAIN;
|
|
4920
|
+
if (evm.registryAddress) status.evm = "configured";
|
|
4921
|
+
} else {
|
|
4922
|
+
nodeEnv.EVM_CHAIN = RELAY_ONLY_CHAIN;
|
|
4923
|
+
}
|
|
4924
|
+
const sol = providers.find((p) => p.chainType === "solana");
|
|
4925
|
+
if (sol && sol.chainType === "solana") {
|
|
4926
|
+
nodeEnv.SOLANA_RPC_URL = sol.rpcUrl;
|
|
4927
|
+
if (sol.tokenMint) nodeEnv.SOLANA_USDC_MINT = sol.tokenMint;
|
|
4928
|
+
if (sol.programId) status.solana = "configured";
|
|
4929
|
+
}
|
|
4930
|
+
const mina = providers.find((p) => p.chainType === "mina");
|
|
4931
|
+
if (mina && mina.chainType === "mina" && mina.zkAppAddress) {
|
|
4932
|
+
status.mina = "configured";
|
|
4933
|
+
}
|
|
4934
|
+
return { network: "custom", chainProviders: providers, nodeEnv, status };
|
|
4935
|
+
}
|
|
4936
|
+
function resolveCustomEndpoints(endpoints, keyId) {
|
|
4937
|
+
const evm = CHAIN_PRESETS[DEV_EVM_PRESET];
|
|
4938
|
+
const status = {
|
|
4939
|
+
evm: "unconfigured",
|
|
4940
|
+
solana: "unconfigured",
|
|
4941
|
+
mina: "unconfigured"
|
|
4942
|
+
};
|
|
4943
|
+
const chainProviders = [];
|
|
4944
|
+
const nodeEnv = {
|
|
4945
|
+
EVM_CHAIN: DEV_EVM_PRESET,
|
|
4946
|
+
EVM_CHAIN_ID: String(evm.chainId),
|
|
4947
|
+
EVM_USDC_ADDRESS: evm.usdcAddress
|
|
4948
|
+
};
|
|
4949
|
+
if (endpoints.evmUrl) {
|
|
4950
|
+
nodeEnv.EVM_RPC_URL = endpoints.evmUrl;
|
|
4951
|
+
status.evm = "configured";
|
|
4952
|
+
if (keyId) {
|
|
4953
|
+
chainProviders.push(
|
|
4954
|
+
buildEvmProviderEntry({ ...evm, rpcUrl: endpoints.evmUrl }, keyId)
|
|
4955
|
+
);
|
|
4956
|
+
}
|
|
4957
|
+
} else {
|
|
4958
|
+
nodeEnv.EVM_CHAIN = RELAY_ONLY_CHAIN;
|
|
4959
|
+
}
|
|
4960
|
+
if (endpoints.solUrl) {
|
|
4961
|
+
nodeEnv.SOLANA_RPC_URL = endpoints.solUrl;
|
|
4962
|
+
nodeEnv.SOLANA_USDC_MINT = DEV_SOLANA.usdcMint;
|
|
4963
|
+
}
|
|
4964
|
+
return { network: "custom", chainProviders, nodeEnv, status };
|
|
4965
|
+
}
|
|
4966
|
+
|
|
4357
4967
|
// src/x402/build-ilp-prepare.ts
|
|
4358
4968
|
function buildIlpPrepare(params) {
|
|
4359
4969
|
return {
|
|
@@ -4500,8 +5110,8 @@ var NixBuilder = class {
|
|
|
4500
5110
|
);
|
|
4501
5111
|
}
|
|
4502
5112
|
const imageData = await readFile(imagePath);
|
|
4503
|
-
const
|
|
4504
|
-
const imageHash = `sha256:${
|
|
5113
|
+
const sha2563 = createHash("sha256").update(imageData).digest("hex");
|
|
5114
|
+
const imageHash = `sha256:${sha2563}`;
|
|
4505
5115
|
const pcr0 = createHash("sha384").update(imageData).digest("hex");
|
|
4506
5116
|
const KERNEL_REGION_SIZE = 1024 * 1024;
|
|
4507
5117
|
const kernelRegion = imageData.subarray(
|
|
@@ -4714,9 +5324,11 @@ export {
|
|
|
4714
5324
|
BootstrapError,
|
|
4715
5325
|
BootstrapService,
|
|
4716
5326
|
CHAIN_PRESETS,
|
|
5327
|
+
EXPIRATION_TAG,
|
|
4717
5328
|
GenesisPeerLoader,
|
|
4718
5329
|
ILP_PEER_INFO_KIND,
|
|
4719
5330
|
ILP_ROOT_PREFIX,
|
|
5331
|
+
ILP_TO_SEMANTIC,
|
|
4720
5332
|
IMAGE_GENERATION_KIND,
|
|
4721
5333
|
InvalidEventError,
|
|
4722
5334
|
JOB_FEEDBACK_KIND,
|
|
@@ -4736,6 +5348,7 @@ export {
|
|
|
4736
5348
|
PREFIX_GRANT_KIND,
|
|
4737
5349
|
PcrReproducibilityError,
|
|
4738
5350
|
PeerDiscoveryError,
|
|
5351
|
+
RELAY_ONLY_CHAIN,
|
|
4739
5352
|
ReputationScoreCalculator,
|
|
4740
5353
|
SEED_RELAY_LIST_KIND,
|
|
4741
5354
|
SERVICE_DISCOVERY_KIND,
|
|
@@ -4757,6 +5370,12 @@ export {
|
|
|
4757
5370
|
WORKFLOW_CHAIN_KIND,
|
|
4758
5371
|
analyzeDockerfileForNonDeterminism,
|
|
4759
5372
|
assignAddressFromHandshake,
|
|
5373
|
+
balanceProofFieldsMina,
|
|
5374
|
+
balanceProofHashEvm,
|
|
5375
|
+
balanceProofHashSolana,
|
|
5376
|
+
base58Decode,
|
|
5377
|
+
base58Encode,
|
|
5378
|
+
bigintToBytes32BE,
|
|
4760
5379
|
buildAttestationEvent,
|
|
4761
5380
|
buildBlobStorageRequest,
|
|
4762
5381
|
buildEip712Domain,
|
|
@@ -4780,6 +5399,7 @@ export {
|
|
|
4780
5399
|
buildWotDeclarationEvent,
|
|
4781
5400
|
calculateRouteAmount,
|
|
4782
5401
|
checkAddressCollision,
|
|
5402
|
+
concatBytes,
|
|
4783
5403
|
createAgentRuntimeClient,
|
|
4784
5404
|
createDirectChannelClient,
|
|
4785
5405
|
createDirectConnectorAdmin,
|
|
@@ -4796,13 +5416,20 @@ export {
|
|
|
4796
5416
|
decodeEventFromToon,
|
|
4797
5417
|
deriveChildAddress,
|
|
4798
5418
|
deriveFromKmsSeed,
|
|
5419
|
+
deriveMinaPublicKeyBase58,
|
|
4799
5420
|
encodeEventToToon,
|
|
4800
5421
|
encodeEventToToonString,
|
|
4801
5422
|
extractPrefixFromHandshake,
|
|
5423
|
+
getEventExpiration,
|
|
4802
5424
|
hasMinReputation,
|
|
4803
5425
|
hasRequireAttestation,
|
|
5426
|
+
hexToBytes,
|
|
5427
|
+
hexToMinaBase58PrivateKey,
|
|
5428
|
+
ilpCodeToSemantic,
|
|
5429
|
+
isEventExpired,
|
|
4804
5430
|
isGenesisNode,
|
|
4805
5431
|
isValidIlpAddressStructure,
|
|
5432
|
+
minaHashToField,
|
|
4806
5433
|
negotiateSettlementChain,
|
|
4807
5434
|
parseAttestation,
|
|
4808
5435
|
parseBlobStorageRequest,
|
|
@@ -4822,7 +5449,9 @@ export {
|
|
|
4822
5449
|
publishSeedRelayEntry,
|
|
4823
5450
|
readDockerfileNix,
|
|
4824
5451
|
resolveChainConfig,
|
|
5452
|
+
resolveClientNetwork,
|
|
4825
5453
|
resolveMinaChainConfig,
|
|
5454
|
+
resolveNetworkProfile,
|
|
4826
5455
|
resolveRouteFees,
|
|
4827
5456
|
resolveSolanaChainConfig,
|
|
4828
5457
|
resolveTokenForChain,
|