@toon-protocol/core 1.4.1 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -127,6 +127,7 @@ declare const PREFIX_GRANT_KIND = 10037;
127
127
  * The genesis node uses this directly -- it does not derive its address from a pubkey.
128
128
  * All other nodes derive addresses as children of their upstream peer's prefix.
129
129
  */
130
+ declare const ILP_ROOT_PREFIX = "g.toon";
130
131
  /**
131
132
  * Blob Storage DVM kind (kind 5094).
132
133
  * Used for permanent blob storage requests (e.g., Arweave uploads).
@@ -163,7 +164,6 @@ declare const PET_INTERACTION_RESULT_KIND = 6900;
163
164
  * pipeline after ZK proof generation.
164
165
  */
165
166
  declare const PET_INTERACTION_EVENT_KIND = 14919;
166
- declare const ILP_ROOT_PREFIX = "g.toon";
167
167
 
168
168
  /**
169
169
  * Shared ILP address validation utilities.
@@ -430,8 +430,14 @@ interface IlpPeerInfo {
430
430
  ilpAddress: string;
431
431
  /** All ILP addresses of this peer (one per upstream peering). When absent (pre-Epic-7 events), consumers should default to [ilpAddress]. */
432
432
  ilpAddresses?: string[];
433
- /** BTP WebSocket endpoint URL for packet exchange */
433
+ /** BTP WebSocket endpoint URL for packet exchange (pay-per-event writes) */
434
434
  btpEndpoint: string;
435
+ /**
436
+ * Public Nostr relay WebSocket URL for FREE reads (e.g. `wss://<addr>.anyone/`
437
+ * or `ws://host:7100`). Lets a client discover where to subscribe/read without
438
+ * out-of-band config. Absent when the relay isn't publicly exposed.
439
+ */
440
+ relayUrl?: string;
435
441
  /** Optional BLS HTTP endpoint for direct packet delivery (bootstrap only) */
436
442
  blsHttpEndpoint?: string;
437
443
  /** @deprecated Use supportedChains instead. Kept for backward compatibility. */
@@ -454,6 +460,36 @@ interface IlpPeerInfo {
454
460
  prefixPricing?: {
455
461
  basePrice: string;
456
462
  };
463
+ /** Token pairs this peer can swap, with current rates. Absent = no swap support. */
464
+ swapPairs?: SwapPair[];
465
+ }
466
+ /**
467
+ * Declarative advertisement of a token swap pair supported by a swap-capable peer (Mill).
468
+ *
469
+ * Source and target assets use the same `{blockchain}:{network}[:{chainId}]` chain format
470
+ * as `IlpPeerInfo.supportedChains`. Rate is serialized as a decimal string (not a float) to
471
+ * preserve arbitrary precision — D12-006. Min/max amounts are source-asset micro-unit integer
472
+ * strings that may exceed `Number.MAX_SAFE_INTEGER`; compare via `BigInt`.
473
+ */
474
+ interface SwapPair {
475
+ /** Source asset */
476
+ from: {
477
+ assetCode: string;
478
+ assetScale: number;
479
+ chain: string;
480
+ };
481
+ /** Target asset */
482
+ to: {
483
+ assetCode: string;
484
+ assetScale: number;
485
+ chain: string;
486
+ };
487
+ /** Exchange rate as decimal string (target units per source unit) */
488
+ rate: string;
489
+ /** Minimum swap amount per packet in source asset micro-units (optional) */
490
+ minAmount?: string;
491
+ /** Maximum swap amount per packet in source asset micro-units (optional) */
492
+ maxAmount?: string;
457
493
  }
458
494
  /**
459
495
  * Subscription handle for real-time event updates.
@@ -490,6 +526,14 @@ interface OpenChannelResult {
490
526
  channelId: string;
491
527
  /** Channel status after open request */
492
528
  status: string;
529
+ /**
530
+ * On-chain channel `depositTotal` (base units), read at open time. Only
531
+ * surfaced by the Mina opener: the Mina balance-proof signer must bind
532
+ * `balanceB = depositTotal − balanceA` so the on-chain `claimFromChannel`
533
+ * signatureA check passes (toon-protocol/connector#133). Left undefined by the
534
+ * EVM and Solana openers, which do not need it.
535
+ */
536
+ depositTotal?: bigint;
493
537
  }
494
538
  /**
495
539
  * State of a payment channel from the connector.
@@ -532,9 +576,12 @@ interface ConnectorChannelClient {
532
576
  }
533
577
 
534
578
  /**
535
- * Parsers for ILP-related Nostr events.
579
+ * Chain identifier validation.
580
+ *
581
+ * Shared helper used by `parseIlpPeerInfo` and `swap-pair-validation` to avoid
582
+ * a circular import between `events/parsers.ts` and `events/swap-pair-validation.ts`
583
+ * (Story 12.1 Task 2.2 fallback).
536
584
  */
537
-
538
585
  /**
539
586
  * Validates a chain identifier string.
540
587
  * Valid format: {blockchain}:{network} or {blockchain}:{network}:{chainId}
@@ -544,12 +591,20 @@ interface ConnectorChannelClient {
544
591
  * @returns true if the chain identifier is valid
545
592
  */
546
593
  declare function validateChainId(chainId: string): boolean;
594
+
595
+ /**
596
+ * Parsers for ILP-related Nostr events.
597
+ */
598
+
547
599
  /**
548
600
  * Parses a kind:10032 Nostr event into an IlpPeerInfo object.
549
601
  *
550
602
  * @param event - The Nostr event to parse
551
603
  * @returns The parsed IlpPeerInfo object
552
- * @throws InvalidEventError if the event is malformed or missing required fields
604
+ * @throws {InvalidEventError} if the event is malformed or missing required fields.
605
+ * This includes: malformed JSON, invalid required fields, invalid `feePerByte`,
606
+ * invalid `prefixPricing`, invalid `ilpAddresses`, `swapPairs` not being an array,
607
+ * or any `SwapPair` element failing structural validation (Story 12.1 AC-5).
553
608
  */
554
609
  declare function parseIlpPeerInfo(event: NostrEvent): IlpPeerInfo;
555
610
 
@@ -557,6 +612,16 @@ declare function parseIlpPeerInfo(event: NostrEvent): IlpPeerInfo;
557
612
  * Builders for ILP-related Nostr events.
558
613
  */
559
614
 
615
+ /** Options controlling how a kind:10032 announcement event is built. */
616
+ interface BuildIlpPeerInfoOptions {
617
+ /**
618
+ * NIP-40 time-to-live, in seconds. When set to a positive value, the event
619
+ * carries an `["expiration", created_at + ttlSeconds]` tag so a stale
620
+ * announcement from an offline apex expires instead of lingering forever
621
+ * (issue #261). Omit (or pass a non-positive value) for a non-expiring event.
622
+ */
623
+ ttlSeconds?: number;
624
+ }
560
625
  /**
561
626
  * Builds and signs a kind:10032 Nostr event from IlpPeerInfo data.
562
627
  *
@@ -566,13 +631,49 @@ declare function parseIlpPeerInfo(event: NostrEvent): IlpPeerInfo;
566
631
  *
567
632
  * @param info - The ILP peer info to serialize into the event
568
633
  * @param secretKey - The secret key to sign the event with
634
+ * @param options - Optional build options (e.g. a NIP-40 `ttlSeconds`)
569
635
  * @returns A signed Nostr event
570
636
  *
571
637
  * @throws {ToonError} With code `INVALID_FEE` if `feePerByte` is not a non-negative integer string
572
638
  * @throws {ToonError} With code `ADDRESS_EMPTY_ADDRESSES` if `ilpAddresses` is an empty array
573
639
  * @throws {ToonError} With code `ADDRESS_INVALID_PREFIX` if any element of `ilpAddresses` is invalid
640
+ * @throws {ToonError} With code `INVALID_SWAP_PAIR` if any element of `swapPairs` is structurally invalid
641
+ */
642
+ declare function buildIlpPeerInfoEvent(info: IlpPeerInfo, secretKey: Uint8Array, options?: BuildIlpPeerInfoOptions): NostrEvent;
643
+
644
+ /**
645
+ * NIP-40 expiration-timestamp helpers.
646
+ *
647
+ * A kind:10032 announcement (`ILP_PEER_INFO_KIND`) is a replaceable event: a
648
+ * relay keeps only the latest per author, so a stale announcement from an apex
649
+ * that has since gone offline lingers forever and clients faithfully dial its
650
+ * dead BTP endpoint (issue #261). Stamping the announcement with a NIP-40
651
+ * `["expiration", <unix-seconds>]` tag turns it into a liveness signal: a live
652
+ * apex re-publishes before the tag elapses, and once it stops, NIP-40-aware
653
+ * relays drop the event and discovery skips it.
654
+ */
655
+
656
+ /** Tag name carrying the NIP-40 expiration timestamp (unix seconds). */
657
+ declare const EXPIRATION_TAG = "expiration";
658
+ /**
659
+ * Read the NIP-40 expiration timestamp (unix seconds) from an event's tags.
660
+ *
661
+ * @returns The timestamp, or `undefined` when the event carries no valid
662
+ * `expiration` tag (no tag, non-numeric, or negative value).
663
+ */
664
+ declare function getEventExpiration(event: NostrEvent): number | undefined;
665
+ /**
666
+ * Whether an event has expired per its NIP-40 `expiration` tag.
667
+ *
668
+ * Events with no (or malformed) expiration tag never expire — they return
669
+ * `false`, preserving backward compatibility with announcements published
670
+ * before TTLs existed.
671
+ *
672
+ * @param event - The event to test.
673
+ * @param nowSeconds - Reference time in unix seconds (defaults to now).
674
+ * Injectable for deterministic tests.
574
675
  */
575
- declare function buildIlpPeerInfoEvent(info: IlpPeerInfo, secretKey: Uint8Array): NostrEvent;
676
+ declare function isEventExpired(event: NostrEvent, nowSeconds?: number): boolean;
576
677
 
577
678
  /**
578
679
  * Event builder and parser for kind:10036 Seed Relay List events.
@@ -2353,6 +2454,162 @@ declare function negotiateSettlementChain(requesterChains: string[], responderCh
2353
2454
  */
2354
2455
  declare function resolveTokenForChain(chain: string, requesterPreferredTokens?: Record<string, string>, responderPreferredTokens?: Record<string, string>): string | undefined;
2355
2456
 
2457
+ /**
2458
+ * Shared balance-proof hash helpers — the single source of truth for the
2459
+ * byte/field layout that ALL signers and verifiers across the monorepo depend
2460
+ * on:
2461
+ * - the Mill-side signer (`packages/mill/src/payment-channel-signer.ts`)
2462
+ * - the sender-side settlement verifier (`packages/sdk/src/settlement/{evm,solana,mina}.ts`)
2463
+ * - the client-side balance-proof signers (`packages/client/src/signing/{solana,mina}-signer.ts`)
2464
+ *
2465
+ * Originally extracted from the Mill signer (Story 12.4) into `@toon-protocol/sdk`
2466
+ * (Story 12.6 AC-6). Relocated here to `@toon-protocol/core` so the client can
2467
+ * consume the canonical hashes WITHOUT taking a dependency on `@toon-protocol/sdk`
2468
+ * (the client only depends on core). `@toon-protocol/sdk` re-exports these names
2469
+ * unchanged, so Mill and existing SDK consumers are unaffected.
2470
+ *
2471
+ * Any change to a hash layout here automatically applies to every signer AND
2472
+ * verifier — they cannot drift.
2473
+ *
2474
+ * @module
2475
+ */
2476
+ /**
2477
+ * Convert a hex string (with or without `0x` prefix) to bytes. Rejects
2478
+ * odd-length and non-hex input.
2479
+ */
2480
+ declare function hexToBytes(hex: string): Uint8Array;
2481
+ /**
2482
+ * Encode a non-negative bigint as 32-byte big-endian. Throws if negative or
2483
+ * exceeds 256 bits.
2484
+ */
2485
+ declare function bigintToBytes32BE(x: bigint): Uint8Array;
2486
+ /**
2487
+ * Concat N Uint8Arrays into one new Uint8Array.
2488
+ */
2489
+ declare function concatBytes(...parts: Uint8Array[]): Uint8Array;
2490
+ /**
2491
+ * Compute the EVM balance-proof message hash:
2492
+ * keccak256(channelId || cumulativeAmount(32BE) || nonce(32BE) || recipient)
2493
+ *
2494
+ * `channelIdBytes` MUST be 32 bytes. `recipientBytes` MUST be 20 bytes.
2495
+ * This hash is what `EvmPaymentChannelSigner.signBalanceProof` signs and
2496
+ * what `recoverEvmSignerAddress` recovers against.
2497
+ *
2498
+ * @stable — signer and verifier depend on the exact byte layout.
2499
+ */
2500
+ declare function balanceProofHashEvm(channelIdBytes: Uint8Array, cumulativeAmount: bigint, nonce: bigint, recipientBytes: Uint8Array): Uint8Array;
2501
+ /**
2502
+ * Compute the Solana balance-proof message hash:
2503
+ * sha256(utf8(channelId) || cumulativeAmount(32BE) || nonce(32BE) || utf8(recipient))
2504
+ *
2505
+ * `channelId` and `recipient` are base58-encoded strings (ASCII-subset of
2506
+ * UTF-8). This hash is what `SolanaPaymentChannelSigner.signBalanceProof`
2507
+ * signs and what `verifyEd25519Signature` verifies against.
2508
+ *
2509
+ * @stable — signer and verifier depend on the exact byte layout.
2510
+ */
2511
+ declare function balanceProofHashSolana(channelId: string, cumulativeAmount: bigint, nonce: bigint, recipient: string): Uint8Array;
2512
+ /**
2513
+ * Hash an arbitrary string to a Pallas-field-safe bigint.
2514
+ *
2515
+ * The Pallas base field order is slightly below 2^254, so we take the first
2516
+ * 240 bits (60 hex chars / 30 bytes) of `sha256(utf8(s))` as a conservative,
2517
+ * guaranteed-in-field representation. Used to fold the variable-length
2518
+ * `channelId` / `recipient` strings into the fixed field-element array a Mina
2519
+ * Schnorr signature is computed over.
2520
+ *
2521
+ * @stable — Mill signer and SDK verifier depend on the exact derivation.
2522
+ */
2523
+ declare function minaHashToField(s: string): bigint;
2524
+ /**
2525
+ * Compute the Mina balance-proof field-element message:
2526
+ * [ minaHashToField(channelId),
2527
+ * cumulativeAmount,
2528
+ * nonce,
2529
+ * minaHashToField(recipient) ]
2530
+ *
2531
+ * This is the EXACT `fields` array that the Mill's `MinaPaymentChannelSigner`
2532
+ * passes to `mina-signer`'s `signFields(...)`, and that the sender-side
2533
+ * `verifyMinaSignature` re-derives and passes to `verifyFields(...)`. Keeping
2534
+ * the derivation here (shared across `@toon-protocol/mill`, `@toon-protocol/sdk`,
2535
+ * and `@toon-protocol/client`) prevents signer/verifier drift — mirroring the
2536
+ * EVM/Solana hash helpers above.
2537
+ *
2538
+ * NOTE: this is the Mill↔sender wire contract (a Schnorr signature over four
2539
+ * field elements), NOT the connector's on-chain `MinaPaymentChannelSDK`
2540
+ * Poseidon-commitment proof shape. The two are distinct; see
2541
+ * `packages/sdk/src/settlement/mina.ts` for the relationship + the
2542
+ * remaining on-chain-settlement gap.
2543
+ *
2544
+ * @stable — Mill signer and SDK verifier depend on the exact byte layout.
2545
+ */
2546
+ declare function balanceProofFieldsMina(channelId: string, cumulativeAmount: bigint, nonce: bigint, recipient: string): bigint[];
2547
+
2548
+ /**
2549
+ * Base58 (Bitcoin/Solana alphabet) encode/decode.
2550
+ *
2551
+ * Identical implementation to `@toon-protocol/sdk`'s `identity.ts` helpers —
2552
+ * relocated/duplicated here so `@toon-protocol/core` (and its `client`
2553
+ * consumer) can base58-encode Solana addresses and the Mina base58check
2554
+ * private-key format without depending on the SDK.
2555
+ *
2556
+ * @module
2557
+ */
2558
+ /**
2559
+ * Encodes a byte array to a Base58 string (Bitcoin/Solana alphabet).
2560
+ */
2561
+ declare function base58Encode(bytes: Uint8Array): string;
2562
+ /**
2563
+ * Decodes a Base58 string to a byte array (Bitcoin/Solana alphabet).
2564
+ */
2565
+ declare function base58Decode(str: string): Uint8Array;
2566
+
2567
+ /**
2568
+ * Mina private-key format conversion.
2569
+ *
2570
+ * `deriveFullIdentity()` / `deriveMillKeys()` emit a Mina Pallas scalar as a
2571
+ * big-endian hex string, but `mina-signer`'s `signFields`/`derivePublicKey`
2572
+ * require the Mina base58check (`EK…`) private-key format. This helper bridges
2573
+ * the two so a hex-derived Mina key produces signatures verifiable by the
2574
+ * sender-side `verifyMinaSignature`.
2575
+ *
2576
+ * Mirrors `hexToMinaBase58PrivateKey` in `packages/mill/src/payment-channel-signer.ts`
2577
+ * (same fixed Mina base58check wire standard — version byte `0x5a`, non-zero
2578
+ * tag `0x01`, little-endian scalar, double-sha256 checksum).
2579
+ *
2580
+ * @module
2581
+ */
2582
+ /**
2583
+ * Convert a big-endian 32-byte hex scalar (the form `deriveFullIdentity()`
2584
+ * emits for Mina) into the Mina base58check private-key string mina-signer's
2585
+ * `signFields`/`derivePublicKey` require. If the input already looks like a
2586
+ * base58 `EK…` key it is returned unchanged.
2587
+ *
2588
+ * Layout (pre-checksum): `[0x5a, 0x01, <scalar bytes little-endian>]`, then
2589
+ * append the first 4 bytes of `sha256(sha256(payload))` and base58-encode.
2590
+ */
2591
+ declare function hexToMinaBase58PrivateKey(privateKey: string): string;
2592
+ /**
2593
+ * Derive the Mina base58 (`B62…`) public key for a private-key scalar, using
2594
+ * the optional `mina-signer` peer dep.
2595
+ *
2596
+ * `deriveFullIdentity()` / `deriveMillKeys()` emit only a keccak **hex
2597
+ * placeholder** for the Mina public key — they deliberately avoid pulling
2598
+ * Pallas curve math into derivation. That placeholder is unfundable and is
2599
+ * rejected by Mina GraphQL balance queries, so wallet views that display it
2600
+ * (e.g. the townhouse `/wallet/balances` mill Mina leg) show an unusable hex
2601
+ * string. This resolves the real, fundable `B62…` address when `mina-signer`
2602
+ * is installed.
2603
+ *
2604
+ * Returns `null` (not a throw) when `mina-signer` is absent — a missing
2605
+ * optional peer dep is not an error; callers fall back to the hex placeholder.
2606
+ * The B62 encoding is network-agnostic, so the chosen `network` is irrelevant.
2607
+ *
2608
+ * @param privateKey big-endian hex scalar (as derivation emits) or an
2609
+ * already-base58 `EK…` Mina private key.
2610
+ */
2611
+ declare function deriveMinaPublicKeyBase58(privateKey: string): Promise<string | null>;
2612
+
2356
2613
  /**
2357
2614
  * Bootstrap service for peer discovery and network initialization.
2358
2615
  *
@@ -3270,6 +3527,47 @@ interface ToonNode {
3270
3527
  */
3271
3528
  declare function createToonNode(config: ToonNodeConfig): ToonNode;
3272
3529
 
3530
+ /**
3531
+ * ILP wire-code → connector semantic-reason translation.
3532
+ *
3533
+ * Connector v3.3.2 introduced the contract: its payment-handler adapter
3534
+ * (`payment-handler.js`'s `mapRejectCode()`) takes a SEMANTIC reason key
3535
+ * (e.g. `'internal_error'`) and looks it up in `REJECT_CODE_MAP` to produce
3536
+ * the wire code (`'T00'`). If a caller passes a raw wire code (`'T00'`) it
3537
+ * is not a key in the map, so the connector falls back to the generic
3538
+ * `'F99'` code — collapsing every reject reason regardless of its true
3539
+ * cause.
3540
+ *
3541
+ * The TOON SDK / handlers express rejections via `ctx.reject(ilpCode, msg)`
3542
+ * using ILP wire codes (T00, F00, F02, F03, F04, F06, T04, R00, ...). This
3543
+ * helper inverts the connector's `REJECT_CODE_MAP` so callers can translate
3544
+ * back to the semantic key the connector now expects.
3545
+ *
3546
+ * Source of truth for the connector's accepted keys:
3547
+ * `@toon-protocol/connector` v3.3.3 — `core/payment-handler.ts`'s
3548
+ * `REJECT_CODE_MAP` and the `AcceptedSemanticCode` literal-union it
3549
+ * `satisfies`. v3.3.3 added `unreachable` (F02) and
3550
+ * `insufficient_destination_amount` (F04). The `satisfies` constraint
3551
+ * structurally prevents drift between the published vocabulary and the
3552
+ * wire-code mapping.
3553
+ */
3554
+ /**
3555
+ * Inverse of the connector's `REJECT_CODE_MAP`.
3556
+ *
3557
+ * Maps every ILP wire code the SDK currently emits to a semantic reason
3558
+ * the connector recognises. Codes outside this set fall back to
3559
+ * `'invalid_request'` (`'F00'`) so we still produce a meaningful,
3560
+ * non-`F99` wire code at the far side.
3561
+ */
3562
+ declare const ILP_TO_SEMANTIC: Readonly<Record<string, string>>;
3563
+ /**
3564
+ * Translate an ILP wire code (T00, F00, ...) to the semantic reason the
3565
+ * connector's `mapRejectCode()` expects. Falls back to `'invalid_request'`
3566
+ * for unknown codes — yields `'F00'` at the wire instead of the generic
3567
+ * `'F99'`.
3568
+ */
3569
+ declare function ilpCodeToSemantic(ilpCode: string): string;
3570
+
3273
3571
  /**
3274
3572
  * Mock USDC token configuration for local development (Anvil).
3275
3573
  *
@@ -3360,8 +3658,13 @@ declare const MOCK_USDC_CONFIG: MockUsdcConfig;
3360
3658
  type ChainType = 'evm' | 'solana' | 'mina';
3361
3659
  /**
3362
3660
  * Supported EVM chain preset names (backward-compatible).
3661
+ *
3662
+ * `anvil` is the local-dev chain. `arbitrum-*` and `base-*` are the public
3663
+ * Arbitrum and Base networks used by the network-mode resolver
3664
+ * (see network-profile.ts). Base is the primary EVM chain for single-EVM
3665
+ * nodes; the apex connector and Mill can hold providers for both families.
3363
3666
  */
3364
- type ChainName = 'anvil' | 'arbitrum-sepolia' | 'arbitrum-one';
3667
+ type ChainName = 'anvil' | 'arbitrum-sepolia' | 'arbitrum-one' | 'base-sepolia' | 'base-mainnet';
3365
3668
  /**
3366
3669
  * Supported Solana chain preset names.
3367
3670
  */
@@ -3434,6 +3737,21 @@ interface EVMProviderConfigEntry {
3434
3737
  rpcUrl: string;
3435
3738
  registryAddress: string;
3436
3739
  keyId: string;
3740
+ tokenAddress: string;
3741
+ privateKey?: string;
3742
+ /**
3743
+ * Settlement tuning knobs. The connector reads its GLOBAL settlement
3744
+ * threshold from the first EVM provider carrying `settlementOptions` and
3745
+ * applies that single `threshold` across all chains (EVM/Solana/Mina).
3746
+ * Mirrors the connector's `EVMProviderConfig.settlementOptions` so a custom
3747
+ * provider entry can pass it straight through.
3748
+ */
3749
+ settlementOptions?: {
3750
+ threshold?: string;
3751
+ settlementTimeoutSecs?: number;
3752
+ initialDepositMultiplier?: number;
3753
+ pollingIntervalMs?: number;
3754
+ };
3437
3755
  }
3438
3756
  /**
3439
3757
  * Solana-specific provider configuration entry.
@@ -3576,6 +3894,173 @@ declare function buildSolanaProviderEntry(config: SolanaChainPreset, keyId: stri
3576
3894
  */
3577
3895
  declare function buildMinaProviderEntry(config: MinaChainPreset, keyId?: string): MinaProviderConfigEntry;
3578
3896
 
3897
+ /**
3898
+ * Network-mode resolution for the Townhouse `network` flag.
3899
+ *
3900
+ * A single operator-facing selector — `mainnet | testnet | devnet | custom` —
3901
+ * resolves a coherent multi-chain configuration that is consumed by BOTH:
3902
+ * (`custom` additionally accepts operator RPC URLs via `--evm-url`/`--sol-url`
3903
+ * to point at the project's dev chains — e.g. the Akash-hosted anvil + solana.)
3904
+ *
3905
+ * - the **apex** standalone connector (its `chainProviders` settlement array), and
3906
+ * - the **children** node containers (town/mill), via a small set of env vars the
3907
+ * HS compose template interpolates (`EVM_CHAIN`, `EVM_RPC_URL`, `EVM_CHAIN_ID`,
3908
+ * `EVM_USDC_ADDRESS`, `SOLANA_RPC_URL`, `SOLANA_USDC_MINT`).
3909
+ *
3910
+ * Design notes:
3911
+ * - **All tiers are public.** No tier resolves to a local chain (anvil/lightnet),
3912
+ * so a node never points at an unreachable `localhost` RPC. This is what fixes
3913
+ * the "JsonRpcProvider failed to detect network" boot-loop that left town nodes
3914
+ * permanently disconnected (an empty RPC fell back to the `anvil` preset whose
3915
+ * `localhost:8545` does not exist in the HS network).
3916
+ * - **EVM = Base (primary) + Arbitrum.** The single-EVM town node uses Base; the
3917
+ * apex connector and Mill can hold providers for both families.
3918
+ * - **Settlement status.** TOON's settlement contracts are deployed for the
3919
+ * public **testnet/devnet** tiers (EVM Base Sepolia registry + TokenNetwork,
3920
+ * Solana devnet program, Mina devnet zkApp — source of truth: e2e/testnets.json),
3921
+ * so those families resolve `configured` and the apex builds real
3922
+ * `chainProviders` for them. **Mainnet remains unconfigured** (contracts not
3923
+ * deployed there yet) → relay-only. The resolver only builds a connector
3924
+ * `chainProviders` entry for a family once its on-chain addresses are present.
3925
+ * No addresses are invented; filling the remaining (mainnet) presets later
3926
+ * requires no change here. The deployed testnet/devnet addresses are
3927
+ * maintained in sync with e2e/testnets.json (the one-time public deploy).
3928
+ *
3929
+ * The low-level local `solana-devnet` / `mina-devnet` presets in chain-config.ts
3930
+ * (used by the dev/e2e stack) are intentionally NOT reused — this module defines
3931
+ * the public Solana/Mina endpoints itself.
3932
+ *
3933
+ * @module
3934
+ */
3935
+
3936
+ /** Operator-facing network selector. */
3937
+ type NetworkMode = 'mainnet' | 'testnet' | 'devnet' | 'custom';
3938
+ /** The three preset-derivable public tiers (everything except custom). */
3939
+ type DerivableTier = Exclude<NetworkMode, 'custom'>;
3940
+ /**
3941
+ * Operator-supplied RPC URLs for `network: 'custom'`
3942
+ * (`--evm-url` / `--sol-url`). Use this to point the apex + nodes at the
3943
+ * project's dev chains hosted anywhere — e.g. the anvil + solana that
3944
+ * scripts/akash-deploy.sh deploys to Akash (whose ingress hostnames rotate per
3945
+ * redeploy, so the operator passes the current URLs). The EVM chain is assumed
3946
+ * to be the chain-id 31338 `akash-anvil` deploy (deterministic TOON settlement
3947
+ * contracts → settlement-complete); Solana is RPC + Mock-USDC (relay-only, no
3948
+ * program). For arbitrary real chains with their own contracts, use the full
3949
+ * `customProviders` (chains editor) path instead.
3950
+ */
3951
+ interface CustomEndpoints {
3952
+ /** EVM JSON-RPC URL (the project's anvil deploy). */
3953
+ evmUrl?: string;
3954
+ /** Solana JSON-RPC URL. */
3955
+ solUrl?: string;
3956
+ }
3957
+ /** Per-family settlement readiness, for honest UX. */
3958
+ interface NetworkFamilyStatus {
3959
+ /** `configured` once the family has on-chain settlement addresses for this tier. */
3960
+ evm: 'configured' | 'unconfigured';
3961
+ solana: 'configured' | 'unconfigured';
3962
+ mina: 'configured' | 'unconfigured';
3963
+ }
3964
+ /**
3965
+ * Env vars the HS compose template interpolates into the node containers.
3966
+ * Only keys with real values are present (absent ⇒ compose `${VAR:-}` default).
3967
+ */
3968
+ interface NetworkNodeEnv {
3969
+ /** Primary EVM chain preset name → town `TOON_CHAIN` (`'none'` ⇒ relay-only). */
3970
+ EVM_CHAIN?: string;
3971
+ EVM_RPC_URL?: string;
3972
+ EVM_CHAIN_ID?: string;
3973
+ EVM_USDC_ADDRESS?: string;
3974
+ SOLANA_RPC_URL?: string;
3975
+ SOLANA_USDC_MINT?: string;
3976
+ /** Solana payment-channel program id (filled per-deploy; empty in presets). */
3977
+ SOLANA_PROGRAM_ID?: string;
3978
+ /** Mina payment-channel zkApp address (filled per-deploy; empty in presets). */
3979
+ MINA_ZKAPP_ADDRESS?: string;
3980
+ }
3981
+ /** Resolved network configuration for apex + children. */
3982
+ interface NetworkProfile {
3983
+ network: NetworkMode;
3984
+ /**
3985
+ * Connector `chainProviders` for the apex. Contains only settlement-complete
3986
+ * families (omitted when on-chain addresses are absent — the caller falls back
3987
+ * to its own default in that case).
3988
+ */
3989
+ chainProviders: ChainProviderConfigEntry[];
3990
+ /** Env overlay for the node containers. */
3991
+ nodeEnv: NetworkNodeEnv;
3992
+ /** Per-family settlement readiness. */
3993
+ status: NetworkFamilyStatus;
3994
+ }
3995
+ /** Sentinel for the town node meaning "no EVM settlement chain — run relay-only". */
3996
+ declare const RELAY_ONLY_CHAIN = "none";
3997
+ /**
3998
+ * Resolve a {@link NetworkProfile} from a network mode.
3999
+ *
4000
+ * @param network - The operator-selected network mode.
4001
+ * @param opts.keyId - Settlement signing key for connector `chainProviders`
4002
+ * entries. Required to emit settlement-complete providers; omit for the common
4003
+ * relay-only case (no providers are built without it).
4004
+ * @param opts.customProviders - For `network: 'custom'`, the operator-supplied
4005
+ * `chainProviders` to pass through verbatim (and to derive node env from).
4006
+ * @param opts.endpoints - For `network: 'custom'`, operator-supplied RPC URLs
4007
+ * (`--evm-url` / `--sol-url`) pointing at the project's dev chains. Used when
4008
+ * `customProviders` is empty (the lightweight URL-only path).
4009
+ */
4010
+ declare function resolveNetworkProfile(network: NetworkMode, opts?: {
4011
+ keyId?: string;
4012
+ customProviders?: ChainProviderConfigEntry[];
4013
+ endpoints?: CustomEndpoints;
4014
+ }): NetworkProfile;
4015
+ /**
4016
+ * Client-facing per-chain settlement presets resolved from a network mode.
4017
+ *
4018
+ * Where {@link NetworkProfile} targets the apex connector + node containers
4019
+ * (env overlay + `chainProviders`), this targets the @toon-protocol/client
4020
+ * `ToonClientConfig` shape: identifier-keyed maps (`evm:<name>:<chainId>`,
4021
+ * `solana:<cluster>`, `mina:<network>`) plus the Solana/Mina channel params.
4022
+ * It draws from the SAME presets (`CHAIN_PRESETS`, `SOLANA_TIER`, `MINA_TIER`),
4023
+ * so node and client default to the identical live contracts — no duplicated
4024
+ * address tables in the client package.
4025
+ *
4026
+ * Only `mainnet | testnet | devnet` are resolvable here; `custom` is the
4027
+ * client's fully-manual path and is intentionally not handled.
4028
+ */
4029
+ interface ClientNetworkPresets {
4030
+ /** Chain identifiers (`evm:base:84532`, `solana:devnet`, `mina:devnet`). */
4031
+ supportedChains: string[];
4032
+ /** identifier → JSON-RPC / GraphQL URL. */
4033
+ chainRpcUrls: Record<string, string>;
4034
+ /** identifier → preferred token (USDC / SPL mint) address. */
4035
+ preferredTokens: Record<string, string>;
4036
+ /** identifier → EVM TokenNetwork contract address (EVM only). */
4037
+ tokenNetworks: Record<string, string>;
4038
+ /** Solana channel params (rpcUrl + programId + tokenMint), if deployed. */
4039
+ solanaChannel?: {
4040
+ rpcUrl: string;
4041
+ programId: string;
4042
+ tokenMint?: string;
4043
+ };
4044
+ /** Mina channel params (graphqlUrl + zkAppAddress + networkId), if deployed. */
4045
+ minaChannel?: {
4046
+ graphqlUrl: string;
4047
+ zkAppAddress: string;
4048
+ networkId: 'devnet' | 'mainnet';
4049
+ };
4050
+ /** Per-family settlement readiness (mirrors the node). */
4051
+ status: NetworkFamilyStatus;
4052
+ }
4053
+ /**
4054
+ * Resolve {@link ClientNetworkPresets} for a derivable network tier.
4055
+ *
4056
+ * Mirrors {@link resolveNetworkProfile}'s address sourcing but emits the
4057
+ * client config shape. The EVM family is the tier's primary chain (Base);
4058
+ * Solana/Mina are the public tier endpoints. Only families with deployed TOON
4059
+ * contracts contribute settlement maps + channel params (others stay relay-only
4060
+ * and are reported `unconfigured`).
4061
+ */
4062
+ declare function resolveClientNetwork(network: DerivableTier): ClientNetworkPresets;
4063
+
3579
4064
  /**
3580
4065
  * Shared ILP PREPARE packet construction for the TOON protocol.
3581
4066
  *
@@ -4024,4 +4509,4 @@ declare function createLogger(config: LoggerConfig): Logger;
4024
4509
  */
4025
4510
  declare const VERSION = "0.1.0";
4026
4511
 
4027
- export { AddressRegistry, type AgentRuntimeClient, ArDrivePeerRegistry, AttestationBootstrap, type AttestationBootstrapConfig, type AttestationBootstrapEvent, type AttestationBootstrapEventListener, type AttestationBootstrapResult, type AttestationEventOptions, AttestationState, AttestationVerifier, type AttestationVerifierConfig, type AttestedResultVerificationOptions, type AttestedResultVerificationResult, AttestedResultVerifier, BLOB_STORAGE_REQUEST_KIND, BLOB_STORAGE_RESULT_KIND, type BlobStorageRequestParams, type BootstrapConfig, BootstrapError, type BootstrapEvent, type BootstrapEventListener, type BootstrapPhase, type BootstrapResult, BootstrapService, type BootstrapServiceConfig, type BtpHandshakeExtension, type BuildIlpPrepareParams, CHAIN_PRESETS, type CalculateRouteAmountParams, type ChainName, type ChainPreset, type ChainProviderConfigEntry, type ChainType, type ChannelState, type ConnectorAdminClient, type ConnectorAdminLike, type ConnectorChannelClient, type ConnectorChannelLike, type ConnectorNodeLike, type DeriveFromKmsSeedOptions, type DeterminismReport, type DirectRuntimeClientConfig, type DiscoveredPeer, type DiscoveryTracker, type DiscoveryTrackerConfig, type DvmJobStatus, type EVMProviderConfigEntry, type EmbeddableConnectorLike, type ForbiddenPattern, type GenesisPeer, GenesisPeerLoader, type HandlePacketAcceptResponse, type HandlePacketRejectResponse, type HandlePacketRequest, type HandlePacketResponse, ILP_PEER_INFO_KIND, ILP_ROOT_PREFIX, IMAGE_GENERATION_KIND, type IlpClient, type IlpPeerInfo, type IlpPreparePacket, type IlpSendResult, JOB_FEEDBACK_KIND, JOB_REQUEST_KIND_BASE, JOB_RESULT_KIND_BASE, JOB_REVIEW_KIND, type JobFeedbackParams, type JobRequestParams, type JobResultParams, type JobReviewParams, KmsIdentityError, type KmsKeypair, type KnownPeer, type LogEntry, type LogLevel, type Logger, type LoggerConfig, MINA_CHAIN_PRESETS, MOCK_USDC_ADDRESS, MOCK_USDC_CONFIG, type MinaChainName, type MinaChainPreset, type MinaProviderConfigEntry, type MockUsdcConfig, type MultiChainName, type NixBuildResult, NixBuilder, type NixBuilderConfig, NostrPeerDiscovery, type OpenChannelParams, type OpenChannelResult, PET_INTERACTION_EVENT_KIND, PET_INTERACTION_REQUEST_KIND, PET_INTERACTION_RESULT_KIND, PREFIX_CLAIM_KIND, PREFIX_GRANT_KIND, type PacketHandler, type ParsedAttestation, type ParsedBlobStorageRequest, type ParsedJobFeedback, type ParsedJobRequest, type ParsedJobResult, type ParsedJobReview, type ParsedSwarmRequest, type ParsedSwarmSelection, type ParsedWorkflowDefinition, type ParsedWotDeclaration, PcrReproducibilityError, type PcrReproducibilityResult, type PeerDescriptor, type PrefixClaimContent, type PrefixGrantContent, type PrefixValidationResult, type PublishSeedRelayConfig, type RegisterPeerParams, type ReputationScore, ReputationScoreCalculator, type ReputationSignals, type ResolveRouteFeesParams, type ResolveRouteFeesResult, SEED_RELAY_LIST_KIND, SERVICE_DISCOVERY_KIND, SOLANA_CHAIN_PRESETS, SeedRelayDiscovery, type SeedRelayDiscoveryConfig, type SeedRelayDiscoveryResult, type SeedRelayEntry, type SendPacketParams, type SendPacketResult, type ServiceDiscoveryContent, type SettlementConfig, type SkillDescriptor, type SocialDiscoveryEvent, type SocialDiscoveryEventListener, SocialPeerDiscovery, type SocialPeerDiscoveryConfig, type SolanaChainName, type SolanaChainPreset, type SolanaProviderConfigEntry, type Subscription, type SwarmRequestParams, type SwarmSelectionParams, TEE_ATTESTATION_KIND, TEXT_GENERATION_KIND, TEXT_TO_SPEECH_KIND, TRANSLATION_KIND, type TeeAttestation, ToonError, type ToonNode, type ToonNodeConfig, type ToonNodeStartResult, USDC_DECIMALS, USDC_NAME, USDC_SYMBOL, VERSION, type VerificationResult, type VerifyOptions, type Violation, WEB_OF_TRUST_KIND, WORKFLOW_CHAIN_KIND, type WorkflowDefinitionParams, type WorkflowStep, type WotDeclarationParams, analyzeDockerfileForNonDeterminism, assignAddressFromHandshake, buildAttestationEvent, buildBlobStorageRequest, buildEip712Domain, buildEvmProviderEntry, buildIlpPeerInfoEvent, buildIlpPrepare, buildJobFeedbackEvent, buildJobRequestEvent, buildJobResultEvent, buildJobReviewEvent, buildMinaProviderEntry, buildPrefixClaimEvent, buildPrefixGrantEvent, buildPrefixHandshakeData, buildSeedRelayListEvent, buildServiceDiscoveryEvent, buildSolanaProviderEntry, buildSwarmRequestEvent, buildSwarmSelectionEvent, buildWorkflowDefinitionEvent, buildWotDeclarationEvent, calculateRouteAmount, checkAddressCollision, createAgentRuntimeClient, createDirectChannelClient, createDirectConnectorAdmin, createDirectIlpClient, createDirectRuntimeClient, createDiscoveryTracker, createHttpChannelClient, createHttpConnectorAdmin, createHttpIlpClient$1 as createHttpIlpClient, createHttpRuntimeClient, createHttpIlpClient as createHttpRuntimeClientV2, createLogger, createToonNode, deriveChildAddress, deriveFromKmsSeed, extractPrefixFromHandshake, hasMinReputation, hasRequireAttestation, isGenesisNode, isValidIlpAddressStructure, negotiateSettlementChain, parseAttestation, parseBlobStorageRequest, parseIlpPeerInfo, parseJobFeedback, parseJobRequest, parseJobResult, parseJobReview, parsePrefixClaimEvent, parsePrefixGrantEvent, parseSeedRelayList, parseServiceDiscovery, parseSwarmRequest, parseSwarmSelection, parseWorkflowDefinition, parseWotDeclaration, publishSeedRelayEntry, readDockerfileNix, resolveChainConfig, resolveMinaChainConfig, resolveRouteFees, resolveSolanaChainConfig, resolveTokenForChain, validateChainId, validateIlpAddress, validatePrefix, validatePrefixConsistency, verifyPcrReproducibility };
4512
+ export { AddressRegistry, type AgentRuntimeClient, ArDrivePeerRegistry, AttestationBootstrap, type AttestationBootstrapConfig, type AttestationBootstrapEvent, type AttestationBootstrapEventListener, type AttestationBootstrapResult, type AttestationEventOptions, AttestationState, AttestationVerifier, type AttestationVerifierConfig, type AttestedResultVerificationOptions, type AttestedResultVerificationResult, AttestedResultVerifier, BLOB_STORAGE_REQUEST_KIND, BLOB_STORAGE_RESULT_KIND, type BlobStorageRequestParams, type BootstrapConfig, BootstrapError, type BootstrapEvent, type BootstrapEventListener, type BootstrapPhase, type BootstrapResult, BootstrapService, type BootstrapServiceConfig, type BtpHandshakeExtension, type BuildIlpPeerInfoOptions, type BuildIlpPrepareParams, CHAIN_PRESETS, type CalculateRouteAmountParams, type ChainName, type ChainPreset, type ChainProviderConfigEntry, type ChainType, type ChannelState, type ClientNetworkPresets, type ConnectorAdminClient, type ConnectorAdminLike, type ConnectorChannelClient, type ConnectorChannelLike, type ConnectorNodeLike, type CustomEndpoints, type DeriveFromKmsSeedOptions, type DeterminismReport, type DirectRuntimeClientConfig, type DiscoveredPeer, type DiscoveryTracker, type DiscoveryTrackerConfig, type DvmJobStatus, type EVMProviderConfigEntry, EXPIRATION_TAG, type EmbeddableConnectorLike, type ForbiddenPattern, type GenesisPeer, GenesisPeerLoader, type HandlePacketAcceptResponse, type HandlePacketRejectResponse, type HandlePacketRequest, type HandlePacketResponse, ILP_PEER_INFO_KIND, ILP_ROOT_PREFIX, ILP_TO_SEMANTIC, IMAGE_GENERATION_KIND, type IlpClient, type IlpPeerInfo, type IlpPreparePacket, type IlpSendResult, JOB_FEEDBACK_KIND, JOB_REQUEST_KIND_BASE, JOB_RESULT_KIND_BASE, JOB_REVIEW_KIND, type JobFeedbackParams, type JobRequestParams, type JobResultParams, type JobReviewParams, KmsIdentityError, type KmsKeypair, type KnownPeer, type LogEntry, type LogLevel, type Logger, type LoggerConfig, MINA_CHAIN_PRESETS, MOCK_USDC_ADDRESS, MOCK_USDC_CONFIG, type MinaChainName, type MinaChainPreset, type MinaProviderConfigEntry, type MockUsdcConfig, type MultiChainName, type NetworkFamilyStatus, type NetworkMode, type NetworkNodeEnv, type NetworkProfile, type NixBuildResult, NixBuilder, type NixBuilderConfig, NostrPeerDiscovery, type OpenChannelParams, type OpenChannelResult, PET_INTERACTION_EVENT_KIND, PET_INTERACTION_REQUEST_KIND, PET_INTERACTION_RESULT_KIND, PREFIX_CLAIM_KIND, PREFIX_GRANT_KIND, type PacketHandler, type ParsedAttestation, type ParsedBlobStorageRequest, type ParsedJobFeedback, type ParsedJobRequest, type ParsedJobResult, type ParsedJobReview, type ParsedSwarmRequest, type ParsedSwarmSelection, type ParsedWorkflowDefinition, type ParsedWotDeclaration, PcrReproducibilityError, type PcrReproducibilityResult, type PeerDescriptor, type PrefixClaimContent, type PrefixGrantContent, type PrefixValidationResult, type PublishSeedRelayConfig, RELAY_ONLY_CHAIN, type RegisterPeerParams, type ReputationScore, ReputationScoreCalculator, type ReputationSignals, type ResolveRouteFeesParams, type ResolveRouteFeesResult, SEED_RELAY_LIST_KIND, SERVICE_DISCOVERY_KIND, SOLANA_CHAIN_PRESETS, SeedRelayDiscovery, type SeedRelayDiscoveryConfig, type SeedRelayDiscoveryResult, type SeedRelayEntry, type SendPacketParams, type SendPacketResult, type ServiceDiscoveryContent, type SettlementConfig, type SkillDescriptor, type SocialDiscoveryEvent, type SocialDiscoveryEventListener, SocialPeerDiscovery, type SocialPeerDiscoveryConfig, type SolanaChainName, type SolanaChainPreset, type SolanaProviderConfigEntry, type Subscription, type SwapPair, type SwarmRequestParams, type SwarmSelectionParams, TEE_ATTESTATION_KIND, TEXT_GENERATION_KIND, TEXT_TO_SPEECH_KIND, TRANSLATION_KIND, type TeeAttestation, ToonError, type ToonNode, type ToonNodeConfig, type ToonNodeStartResult, USDC_DECIMALS, USDC_NAME, USDC_SYMBOL, VERSION, type VerificationResult, type VerifyOptions, type Violation, WEB_OF_TRUST_KIND, WORKFLOW_CHAIN_KIND, type WorkflowDefinitionParams, type WorkflowStep, type WotDeclarationParams, analyzeDockerfileForNonDeterminism, assignAddressFromHandshake, balanceProofFieldsMina, balanceProofHashEvm, balanceProofHashSolana, base58Decode, base58Encode, bigintToBytes32BE, buildAttestationEvent, buildBlobStorageRequest, buildEip712Domain, buildEvmProviderEntry, buildIlpPeerInfoEvent, buildIlpPrepare, buildJobFeedbackEvent, buildJobRequestEvent, buildJobResultEvent, buildJobReviewEvent, buildMinaProviderEntry, buildPrefixClaimEvent, buildPrefixGrantEvent, buildPrefixHandshakeData, buildSeedRelayListEvent, buildServiceDiscoveryEvent, buildSolanaProviderEntry, buildSwarmRequestEvent, buildSwarmSelectionEvent, buildWorkflowDefinitionEvent, buildWotDeclarationEvent, calculateRouteAmount, checkAddressCollision, concatBytes, createAgentRuntimeClient, createDirectChannelClient, createDirectConnectorAdmin, createDirectIlpClient, createDirectRuntimeClient, createDiscoveryTracker, createHttpChannelClient, createHttpConnectorAdmin, createHttpIlpClient$1 as createHttpIlpClient, createHttpRuntimeClient, createHttpIlpClient as createHttpRuntimeClientV2, createLogger, createToonNode, deriveChildAddress, deriveFromKmsSeed, deriveMinaPublicKeyBase58, extractPrefixFromHandshake, getEventExpiration, hasMinReputation, hasRequireAttestation, hexToBytes, hexToMinaBase58PrivateKey, ilpCodeToSemantic, isEventExpired, isGenesisNode, isValidIlpAddressStructure, minaHashToField, negotiateSettlementChain, parseAttestation, parseBlobStorageRequest, parseIlpPeerInfo, parseJobFeedback, parseJobRequest, parseJobResult, parseJobReview, parsePrefixClaimEvent, parsePrefixGrantEvent, parseSeedRelayList, parseServiceDiscovery, parseSwarmRequest, parseSwarmSelection, parseWorkflowDefinition, parseWotDeclaration, publishSeedRelayEntry, readDockerfileNix, resolveChainConfig, resolveClientNetwork, resolveMinaChainConfig, resolveNetworkProfile, resolveRouteFees, resolveSolanaChainConfig, resolveTokenForChain, validateChainId, validateIlpAddress, validatePrefix, validatePrefixConsistency, verifyPcrReproducibility };