@toon-protocol/client 0.18.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -51,14 +51,11 @@ pnpm add mina-signer
51
51
  These coordinates go straight into the [`ToonClient` config](#quick-start) below.
52
52
 
53
53
  > **Local development (from a clone of this repo, not the npm package).** To try the client
54
- > end-to-end against a throwaway local network, start the monorepo's SDK E2E stack Anvil + two peer
55
- > nodes + relays. This script ships with the repo, **not** the published package:
56
- >
57
- > ```bash
58
- > ./scripts/sdk-e2e-infra.sh up # start (Ctrl-C-safe; `down` to stop)
59
- > curl http://localhost:19100/health # peer 1 health
60
- > ./scripts/sdk-e2e-infra.sh down # stop
61
- > ```
54
+ > end-to-end against a throwaway local network Anvil + two peer nodes + relays see
55
+ > [`packages/client/tests/e2e/README.md`](tests/e2e/README.md) for the service topology and manual
56
+ > testing snippet. Its automated setup steps assume the monorepo's `scripts/sdk-e2e-infra.sh`
57
+ > wrapper and a `docker-compose-sdk-e2e.yml`, neither of which ships in this extracted repo; treat
58
+ > those steps as a reference for provisioning the equivalent infrastructure yourself.
62
59
  >
63
60
  > | Service | Port | Purpose |
64
61
  > | ---------------- | ----- | --------------------------------------------------- |
@@ -275,38 +272,36 @@ pnpm test:coverage # Run with coverage report
275
272
 
276
273
  ### E2E Tests
277
274
 
278
- E2E tests require the SDK E2E infrastructure:
275
+ E2E tests require Docker Compose infrastructure. See
276
+ [tests/e2e/README.md](tests/e2e/README.md) for the service topology — note its automated setup
277
+ script isn't included in this extracted repo either (see the Prerequisites section above), so
278
+ provision the equivalent infrastructure manually, then run:
279
279
 
280
280
  ```bash
281
- # Start infrastructure
282
- ./scripts/sdk-e2e-infra.sh up
283
-
284
- # Run E2E tests
285
281
  cd packages/client
286
282
  pnpm test:e2e
287
283
  ```
288
284
 
289
- See [tests/e2e/README.md](tests/e2e/README.md) for detailed E2E setup.
290
-
291
285
  ---
292
286
 
293
287
  ## Examples
294
288
 
295
- See [examples/client-example/](../../examples/client-example/) for standalone client examples:
289
+ See [examples/](examples/) for standalone client examples:
296
290
 
297
- - **01 - Publish Event** (`01-publish-event.ts`): Full client lifecycle with self-describing claims
298
- - **02 - Payment Channel Lifecycle** (`02-payment-channel.ts`): Multiple events with incrementing balance proofs
299
- - **03 - Multi-Chain Publish** (`03-multi-chain-publish.ts`): Publishing with multiple settlement chains configured
300
- - **04 - Subscribe to Events** (`04-subscribe-events.ts`): Reading events back from the relay (free)
291
+ - **Basic Publish** (`basic-publish.ts`): Publish a Nostr event to the TOON network
292
+ - **Publish and Verify** (`publish-and-verify.ts`): Publish an event and verify via connector logs
293
+ - **Publish to Peer1** (`publish-to-peer1.ts`): Multi-hop ILP routing via a peer connector
294
+ - **Multi-Hop Routing** (`multi-hop-routing.ts`): Route an event through peer1 to the genesis relay
295
+ - **With Payment Channels** (`with-payment-channels.ts`): Configure EVM payment channels and publish with a signed balance proof
301
296
 
302
297
  ---
303
298
 
304
299
  ## Related Packages
305
300
 
306
- - **[@toon-protocol/core](../core/)** — Core protocol (peer discovery, bootstrap, `buildBlobStorageRequest`)
307
- - **[@toon-protocol/relay](../relay/)** — Operator product running the apex connector plus relay/swap/store nodes; also exports `encodeEventToToon` / `decodeEventFromToon` for event encoding
308
- - **[@toon-protocol/sdk](../sdk/)** — Higher-level helpers including `streamSwap()` for multi-chain swaps via a **swap**
309
- - **[@toon-protocol/bls](../bls/)** — Business Logic Server (pricing, validation, storage)
301
+ - **[@toon-protocol/core](https://www.npmjs.com/package/@toon-protocol/core)** — Core protocol (peer discovery, bootstrap, `buildBlobStorageRequest`)
302
+ - **[@toon-protocol/relay](https://www.npmjs.com/package/@toon-protocol/relay)** — Operator product running the apex connector plus relay/swap/store nodes; also exports `encodeEventToToon` / `decodeEventFromToon` for event encoding
303
+ - **[@toon-protocol/sdk](https://www.npmjs.com/package/@toon-protocol/sdk)** — Higher-level helpers including `streamSwap()` for multi-chain swaps via a **swap**
304
+ - **[@toon-protocol/bls](https://www.npmjs.com/package/@toon-protocol/bls)** — Business Logic Server (pricing, validation, storage)
310
305
 
311
306
  ---
312
307
 
package/dist/index.d.ts CHANGED
@@ -407,6 +407,24 @@ interface ToonClientConfig {
407
407
  * gated (distinct from the connector #88 on-chain-settle gate).
408
408
  */
409
409
  minaChannel?: MinaChannelClientOptions;
410
+ /**
411
+ * Receive-side Mina swap-claim redemption (#357): maker on-chain co-signatures
412
+ * keyed by dest-channel zkApp address (B62).
413
+ *
414
+ * On-chain `claimFromChannel` is dual-party — it verifies BOTH participants
415
+ * signed `[commitment, nonce, channelHash]`. The recipient (this client)
416
+ * produces its own co-signature from the derived Mina key, but the swap-wire
417
+ * claim only carries the maker's `balanceProofFieldsMina` signature (a
418
+ * DIFFERENT message), so the maker must additionally deliver a
419
+ * payment-channel-commitment-form co-signature. Until that flows over the swap
420
+ * wire, an operator can inject the maker's `{ r, s }` here to complete a
421
+ * receive-side redemption. Absent one, settlement fails closed with
422
+ * `MINA_MAKER_COSIGN_REQUIRED` (never a silent pass).
423
+ */
424
+ swapMinaMakerSignatures?: Record<string, {
425
+ r: string;
426
+ s: string;
427
+ }>;
410
428
  /** File path for persisting payment channel nonce/amount state across restarts */
411
429
  channelStorePath?: string;
412
430
  /** Nostr relay URL for peer discovery. Default: 'ws://localhost:7100' */
@@ -1561,8 +1579,6 @@ declare class ToonClient {
1561
1579
  private getClaimTransport;
1562
1580
  /**
1563
1581
  * Shared claim-resolution logic used by `publishEvent` and `sendSwapPacket`.
1564
- * TODO(12.5 followup): also factor `publishEvent`'s inline claim resolution
1565
- * to call this helper. Kept duplicated for now to minimize regression risk.
1566
1582
  */
1567
1583
  private resolveClaimForDestination;
1568
1584
  /**
@@ -2935,6 +2951,44 @@ declare class ChannelManager {
2935
2951
  * @param fetchImpl - injectable for tests; defaults to global `fetch`.
2936
2952
  */
2937
2953
  declare function readMinaDepositTotal(graphqlUrl: string, zkAppAddress: string, fetchImpl?: typeof fetch): Promise<bigint>;
2954
+ /** Channel-lifecycle enum written to `channelState` (matches the zkApp). */
2955
+ declare const MINA_CHANNEL_STATE: {
2956
+ readonly UNINITIALIZED: 0;
2957
+ readonly OPEN: 1;
2958
+ readonly CLOSING: 2;
2959
+ readonly SETTLED: 3;
2960
+ };
2961
+ /**
2962
+ * On-chain `PaymentChannel` state the receive-side settler needs to assemble a
2963
+ * co-signed `claimFromChannel` — all read via plain GraphQL (NO o1js / WASM), so
2964
+ * the read path stays lightweight and unit-testable. Field semantics match
2965
+ * {@link MinaChannelState} in the connector's Mina SDK.
2966
+ */
2967
+ interface MinaOnChainChannelState {
2968
+ /** `Poseidon([participantA.x, participantB.x, channelNonce])`, decimal Field. */
2969
+ channelHash: string;
2970
+ /** Current `Poseidon([balanceA, balanceB, salt])`, decimal Field. */
2971
+ balanceCommitment: string;
2972
+ /** Highest claimed nonce recorded on-chain. */
2973
+ nonceField: bigint;
2974
+ /** {@link MINA_CHANNEL_STATE} enum value. */
2975
+ channelState: number;
2976
+ /** Total escrowed deposit (base units). */
2977
+ depositTotal: bigint;
2978
+ }
2979
+ /**
2980
+ * Read the channel's on-chain `PaymentChannel` state via GraphQL.
2981
+ *
2982
+ * Reuses the same `account(publicKey).zkappState` query as
2983
+ * {@link readMinaDepositTotal} and decodes the fields the co-signed
2984
+ * `claimFromChannel` assembly binds: `channelHash` (participant identity),
2985
+ * `depositTotal` (balance conservation), `nonceField` (monotonicity gate), and
2986
+ * `channelState` (must be OPEN). No o1js is loaded — the values are raw Field
2987
+ * decimal strings straight off the node.
2988
+ *
2989
+ * @param fetchImpl - injectable for tests; defaults to global `fetch`.
2990
+ */
2991
+ declare function readMinaChannelState(graphqlUrl: string, zkAppAddress: string, fetchImpl?: typeof fetch): Promise<MinaOnChainChannelState>;
2938
2992
 
2939
2993
  /**
2940
2994
  * Receive-side swap-claim ingestion + verification (toon-client#352, part of
@@ -3035,6 +3089,389 @@ declare function hasSettlementMetadata(claim: AccumulatedClaim): claim is Accumu
3035
3089
  */
3036
3090
  declare function ingestReceivedClaims(params: IngestReceivedClaimsParams): IngestReceivedClaimsResult;
3037
3091
 
3092
+ /**
3093
+ * Per-packet preimage retention (toon-client#360, rolling-swap epic
3094
+ * toon-meta#145 — spec `docs/rolling-swap.md` §3 R1 / §3.2 leg-B reveal).
3095
+ *
3096
+ * `withSenderConditions` (toon-client#354) mints a fresh 32-byte preimage
3097
+ * `P_i` per fill packet, sets `C_i = sha256(P_i)` on the leg-A PREPARE, and —
3098
+ * before this module — DISCARDED `P_i`. Leg-B reveal (spec §3.2) is the commit
3099
+ * act: the sender reveals `P_i` only AFTER verifying the leg-B claim, so the
3100
+ * daemon must retain each `P_i` from mint time until the reveal step consumes
3101
+ * it. This is that retention seam.
3102
+ *
3103
+ * Keyed by `packetIndex` — the 0-indexed position in the swap's packet stream.
3104
+ * `packetIndex` is the one identifier shared between the send side (the wrapper
3105
+ * mints one condition per `sendSwapPacket` call, which `streamSwap` issues in
3106
+ * strictly increasing `packetIndex` order) and the receive side
3107
+ * (`AccumulatedClaim.packetIndex`), so it correlates a retained preimage to the
3108
+ * claim whose reveal will consume it.
3109
+ *
3110
+ * Reveal is single-use: {@link PreimageRetentionStore.take} removes the entry
3111
+ * so a preimage is never revealed twice (spec R1 — a reused preimage lets an
3112
+ * observer of packet *i* fulfill packet *i+1* without the sender's consent).
3113
+ *
3114
+ * Session-scoped and in-memory by design: a preimage is only meaningful within
3115
+ * the swap stream that minted it (a fresh stream mints fresh preimages), and a
3116
+ * preimage revealed after a crash would commit leg A for a leg-B claim the
3117
+ * restarted daemon can no longer verify. Durability lives on the *watermark*
3118
+ * (`ReceivedClaimStore`), not here.
3119
+ */
3120
+ /** A retained per-packet hashlock secret awaiting (or past) its leg-B reveal. */
3121
+ interface RetainedPreimage {
3122
+ /** 0-indexed position in the swap's packet stream; the correlation key. */
3123
+ packetIndex: number;
3124
+ /** The 32-byte preimage `P_i` — revealed to commit leg A (spec R6). */
3125
+ preimage: Uint8Array;
3126
+ /** `C_i = sha256(P_i)` — what went on the leg-A PREPARE (kept for auditing). */
3127
+ condition: Uint8Array;
3128
+ /** Unix ms the preimage was minted/retained. */
3129
+ retainedAt: number;
3130
+ }
3131
+ /**
3132
+ * Retention interface for per-packet preimages, keyed by `packetIndex`. Mirrors
3133
+ * the sync surface of the daemon's other stores ({@link ReceivedClaimStore}).
3134
+ */
3135
+ interface PreimageRetentionStore {
3136
+ /** Retain `entry`, replacing any prior entry for the same `packetIndex`. */
3137
+ retain(entry: RetainedPreimage): void;
3138
+ /** Peek the retained preimage for `packetIndex` without consuming it. */
3139
+ get(packetIndex: number): RetainedPreimage | undefined;
3140
+ /** Consume (return AND remove) the preimage — single-use reveal (spec R1). */
3141
+ take(packetIndex: number): RetainedPreimage | undefined;
3142
+ /** Number of preimages still retained (awaiting reveal). */
3143
+ size(): number;
3144
+ /** Drop every retained preimage — call when the session ends. */
3145
+ clear(): void;
3146
+ }
3147
+ /**
3148
+ * In-memory {@link PreimageRetentionStore}. The only implementation: preimages
3149
+ * are session-scoped secrets that MUST NOT outlive their stream (see the module
3150
+ * doc), so there is deliberately no file-backed variant.
3151
+ */
3152
+ declare class InMemoryPreimageRetentionStore implements PreimageRetentionStore {
3153
+ private readonly entries;
3154
+ retain(entry: RetainedPreimage): void;
3155
+ get(packetIndex: number): RetainedPreimage | undefined;
3156
+ take(packetIndex: number): RetainedPreimage | undefined;
3157
+ size(): number;
3158
+ clear(): void;
3159
+ }
3160
+
3161
+ /**
3162
+ * Atomic verify -> persist -> reveal composition (toon-client#360, rolling-swap
3163
+ * epic toon-meta#145 — spec `docs/rolling-swap.md` §3 R5/R8, §3.2 leg-B reveal).
3164
+ *
3165
+ * {@link ingestReceivedClaims} (toon-client#358) verifies a received chain-B
3166
+ * claim and persists its watermark AT VERIFY TIME. But verification is not the
3167
+ * commit: leg-B reveal is (spec R5 — the sender reveals `P_i` only after the
3168
+ * claim verifies). A daemon that verifies a claim, advances the watermark, and
3169
+ * then WITHHOLDS or FAILS the reveal has advanced a watermark for value it never
3170
+ * committed to. Left there, engine rule R8 bites: after the maker rolls its own
3171
+ * side back it REUSES the rolled-back nonce for the next fill, and the client's
3172
+ * monotonicity check (`nonce <= watermark.nonce -> NON_MONOTONIC_NONCE`) would
3173
+ * falsely reject that legitimate re-fill.
3174
+ *
3175
+ * So verify/persist/reveal must compose as ONE unit whose durable effect is
3176
+ * "watermark advanced iff the reveal committed":
3177
+ *
3178
+ * 1. snapshot the prior watermark for the claim's `(chain, channelId)`;
3179
+ * 2. verify + persist via {@link ingestReceivedClaims} (single claim);
3180
+ * 3. reveal the retained preimage `P_i` for `claim.packetIndex`;
3181
+ * 4. on `withheld` / thrown / preimage-missing -> COMPENSATING ROLLBACK:
3182
+ * restore the snapshot (or delete when there was none), so the watermark
3183
+ * tracks only ACCEPTED/REVEALED packets and R8's reused nonce is accepted.
3184
+ *
3185
+ * Claims are processed strictly in order and each claim's fate is decided
3186
+ * before the next is verified, so cross-claim monotonicity flows through the
3187
+ * durable store: a rolled-back claim leaves no trace for the next to trip over.
3188
+ * Legacy no-metadata claims (spec §349 path) and hard verification rejects
3189
+ * never reach a reveal and never touch a watermark — behavior unchanged.
3190
+ */
3191
+
3192
+ /** The sender's leg-B decision for a verified claim (spec R5). */
3193
+ type RevealDecision = 'revealed' | 'withheld';
3194
+ interface RevealResult {
3195
+ decision: RevealDecision;
3196
+ /** Human-readable detail, surfaced on a rolled-back record when withheld. */
3197
+ reason?: string;
3198
+ }
3199
+ /**
3200
+ * Reveal a verified claim's preimage to commit leg A, OR withhold it. Receives
3201
+ * the claim and the retained preimage for its `packetIndex` (`undefined` when
3202
+ * none was retained — e.g. a legacy zero-condition packet reaching this path).
3203
+ * Returning `withheld`, resolving to no decision, or THROWING all trigger the
3204
+ * compensating rollback; only `revealed` keeps the watermark advance.
3205
+ */
3206
+ type RevealFn = (claim: AccumulatedClaim, preimage: RetainedPreimage | undefined) => RevealResult | Promise<RevealResult>;
3207
+ interface IngestAndRevealParams extends IngestReceivedClaimsParams {
3208
+ /** Leg-B reveal decision, invoked once per VERIFIED claim (spec R5/R6). */
3209
+ reveal: RevealFn;
3210
+ /**
3211
+ * Retained per-packet preimages ({@link PreimageRetentionStore}). The reveal
3212
+ * for a verified claim CONSUMES (`take`) the preimage for its `packetIndex`,
3213
+ * so a preimage is never revealed twice (spec R1). Optional: without it the
3214
+ * reveal fn receives `undefined` and decides on its own.
3215
+ */
3216
+ preimages?: PreimageRetentionStore;
3217
+ }
3218
+ interface RevealedClaim {
3219
+ claim: AccumulatedClaim;
3220
+ /** How far the (now committed) watermark advanced. */
3221
+ watermarkAdvance: bigint;
3222
+ }
3223
+ interface RolledBackClaim {
3224
+ claim: AccumulatedClaim;
3225
+ /** The advance that was persisted then rolled back (never counted). */
3226
+ watermarkAdvance: bigint;
3227
+ /** Why the reveal did not commit (withheld reason, or the thrown error). */
3228
+ reason: string;
3229
+ }
3230
+ interface IngestAndRevealResult {
3231
+ /** Claims that verified AND revealed — the only ones whose value counts. */
3232
+ revealed: RevealedClaim[];
3233
+ /**
3234
+ * Claims that verified but whose reveal was withheld/failed: the watermark
3235
+ * advance was persisted then ROLLED BACK, so a subsequent re-fill reusing
3236
+ * the same nonce (engine R8) is accepted, not falsely rejected.
3237
+ */
3238
+ rolledBack: RolledBackClaim[];
3239
+ /** Claims that failed verification. NEVER revealed, NEVER persisted. */
3240
+ rejected: ReceivedClaimRejection[];
3241
+ /** Legacy no-metadata claims (spec §349). Unchanged: not verified/revealed. */
3242
+ legacy: AccumulatedClaim[];
3243
+ /** Total watermark advance across REVEALED claims only. */
3244
+ valueRevealed: bigint;
3245
+ }
3246
+ /**
3247
+ * Verify, persist, and reveal a batch of received chain-B claims atomically:
3248
+ * a verified claim's watermark advance survives iff its reveal commits, and is
3249
+ * rolled back otherwise (see the module doc for why R8 needs this).
3250
+ *
3251
+ * Never throws on a bad claim or a throwing reveal — both land in the result
3252
+ * (`rejected` / `rolledBack`) with the durable watermark left consistent.
3253
+ */
3254
+ declare function ingestAndReveal(params: IngestAndRevealParams): Promise<IngestAndRevealResult>;
3255
+
3256
+ /**
3257
+ * Mina receive-side swap settlement (toon-client#357, part of the rolling-swap
3258
+ * epic toon-meta#145; follow-up to the #352 receive-side ingestion PR).
3259
+ *
3260
+ * #352 shipped VERIFICATION of swapped-in Mina claims but explicitly left
3261
+ * REDEMPTION out: `POST /swap/settle` returned `SUBMISSION_UNSUPPORTED` for
3262
+ * `mina:*` bundles. This module is the missing redemption seam — it turns a
3263
+ * verified accumulated Mina claim into an on-chain co-signed `claimFromChannel`
3264
+ * transaction against the payment-channel zkApp.
3265
+ *
3266
+ * ## Why Mina needs a co-sign (and EVM/Solana do not)
3267
+ *
3268
+ * The zkApp's `claimFromChannel(newBalanceA, newBalanceB, newSalt, signatureA,
3269
+ * signatureB, participantA, participantB, channelNonce, newBalanceCommitment,
3270
+ * newNonce)` is DUAL-PARTY (connector#84): it verifies BOTH participants signed
3271
+ * the SAME message `[newBalanceCommitment, newNonce, storedChannelHash]`
3272
+ * (`packages/mina-zkapp/src/PaymentChannel.ts`). The client's existing
3273
+ * {@link MinaSigner} is payer-side only. On the swap RECEIVE side the client is
3274
+ * the RECIPIENT of the channel, so it must contribute the recipient's
3275
+ * co-signature (`signatureB` for its participant slot).
3276
+ *
3277
+ * ## Signature-message mismatch — the maker-side dependency
3278
+ *
3279
+ * The swap-wire claim (`AccumulatedClaim.claimBytes`) carries the maker's
3280
+ * Schnorr signature over `balanceProofFieldsMina(channelId, cumulativeAmount,
3281
+ * nonce, recipient)` (verified by the sdk's `verifyMinaSignature`). That is a
3282
+ * DIFFERENT message than the on-chain `[commitment, nonce, channelHash]`, so it
3283
+ * CANNOT be reused as an on-chain participant signature. On-chain redemption
3284
+ * therefore needs the maker to ALSO contribute a payment-channel-commitment-form
3285
+ * signature over `[commitment, nonce, channelHash]` (the same form the connector
3286
+ * payment-channel provider produces from a client claim). Until a maker delivers
3287
+ * that, {@link submitMinaSettlement} fails closed with
3288
+ * `MINA_MAKER_COSIGN_REQUIRED` (never a silent pass). See the PR body for the
3289
+ * cross-repo maker/wire follow-up.
3290
+ *
3291
+ * ## globalSlot preconditions
3292
+ *
3293
+ * Unlike `initiateClose`/`settle` (which pin `network.globalSlotSinceGenesis`
3294
+ * and were the subject of the #202 exact-slot-precondition bug), the zkApp's
3295
+ * `claimFromChannel` binds NO slot precondition — only `channelState == OPEN`,
3296
+ * `channelHash`, `depositTotal`, and a strictly-increasing `nonceField`. The
3297
+ * redeem path is therefore immune to the #202 slot-drift failure. The eventual
3298
+ * close+settle that pays escrow out to the recipient DOES touch the slot window
3299
+ * and remains the connector's `settleChannel` responsibility (a separate step).
3300
+ *
3301
+ * ## What runs where
3302
+ *
3303
+ * - On-chain STATE READ + co-sign assembly ({@link buildMinaCoSignedClaim}):
3304
+ * plain GraphQL + `mina-signer` (Pallas Schnorr / Poseidon) — NO o1js, fully
3305
+ * unit-testable in-process.
3306
+ * - Proof generation + broadcast ({@link submitMinaSettlement}): drives an
3307
+ * injectable {@link MinaClaimSubmitter}; the default is an o1js-backed settler
3308
+ * ({@link createO1jsMinaClaimSubmitter}) that dynamically imports `o1js` +
3309
+ * `@toon-protocol/mina-zkapp` only when invoked (never loaded by the non-Mina
3310
+ * suite). o1js circuit compilation + proving is slow (30-120s) and is exercised
3311
+ * only against live devnet Mina behind an env gate.
3312
+ */
3313
+
3314
+ /** Bare Pallas Schnorr signature in the o1js JSON (decimal `r`/`s`) form. */
3315
+ interface MinaSignaturePair {
3316
+ r: string;
3317
+ s: string;
3318
+ }
3319
+ /** Stable failure codes for Mina receive-side settlement. */
3320
+ type MinaSettlementErrorCode = 'NOT_MINA_BUNDLE' | 'NO_GRAPHQL_CONFIGURED' | 'CHANNEL_NOT_OPEN' | 'NONCE_NOT_ADVANCING' | 'CHANNEL_HASH_MISMATCH' | 'CUMULATIVE_EXCEEDS_DEPOSIT' | 'MINA_MAKER_COSIGN_REQUIRED' | 'PROVING_FAILED';
3321
+ /** Result-shaped-by-throw settlement error carrying a stable {@link code}. */
3322
+ declare class MinaSettlementError extends Error {
3323
+ readonly code: MinaSettlementErrorCode;
3324
+ constructor(code: MinaSettlementErrorCode, message: string);
3325
+ }
3326
+ /** Inputs to {@link buildMinaCoSignedClaim} (pure assembly, no o1js). */
3327
+ interface MinaCoSignInputs {
3328
+ /** Deployed payment-channel zkApp address (B62) — the on-chain channel id. */
3329
+ channelId: string;
3330
+ /** Claim nonce being redeemed (must exceed the on-chain `nonceField`). */
3331
+ nonce: bigint;
3332
+ /** Cumulative amount credited to the recipient (base units). */
3333
+ cumulativeAmount: bigint;
3334
+ /** Recipient's Mina B62 pubkey — one channel participant (the co-signer). */
3335
+ recipient: string;
3336
+ /** Swap maker's Mina B62 pubkey — the other channel participant. */
3337
+ swapSignerAddress: string;
3338
+ /** On-chain `depositTotal` (base units) for balance conservation. */
3339
+ depositTotal: bigint;
3340
+ /** On-chain `channelHash` (decimal Field) used to resolve A/B ordering. */
3341
+ onChainChannelHash: string;
3342
+ /** Recipient's Mina private key (big-endian hex scalar OR `EK…` base58). */
3343
+ recipientPrivateKey: string;
3344
+ /** Channel nonce baked into the on-chain `channelHash` (default 0). */
3345
+ channelNonce?: bigint;
3346
+ /** Override the deterministic salt (else {@link deriveMinaSalt}). */
3347
+ saltOverride?: bigint;
3348
+ /**
3349
+ * Maker's payment-channel-commitment-form signature over
3350
+ * `[commitment, nonce, channelHash]`. REQUIRED for a fully-redeemable claim;
3351
+ * when absent the returned claim reports {@link makerSignatureMissing}.
3352
+ */
3353
+ makerSignature?: MinaSignaturePair;
3354
+ }
3355
+ /** A dual-party claim assembled for the zkApp's `claimFromChannel`. */
3356
+ interface MinaCoSignedClaim {
3357
+ channelId: string;
3358
+ /** Balance credited to `participantA` (base units). */
3359
+ balanceA: bigint;
3360
+ /** Balance credited to `participantB` (`depositTotal - balanceA`). */
3361
+ balanceB: bigint;
3362
+ salt: bigint;
3363
+ nonce: bigint;
3364
+ channelNonce: bigint;
3365
+ /** `Poseidon([balanceA, balanceB, salt])`, decimal Field. */
3366
+ balanceCommitment: string;
3367
+ /** Participant A B62 (ordered to reproduce the on-chain `channelHash`). */
3368
+ participantA: string;
3369
+ /** Participant B B62. */
3370
+ participantB: string;
3371
+ /** Which participant slot the recipient/co-signer occupies. */
3372
+ recipientRole: 'A' | 'B';
3373
+ /** The recipient's co-signature over `[commitment, nonce, channelHash]`. */
3374
+ recipientSignature: MinaSignaturePair;
3375
+ /** Signature for participant A (recipient's or maker's per {@link recipientRole}). */
3376
+ signatureA?: MinaSignaturePair;
3377
+ /** Signature for participant B. */
3378
+ signatureB?: MinaSignaturePair;
3379
+ /** True when no maker co-signature was supplied (claim not yet redeemable). */
3380
+ makerSignatureMissing: boolean;
3381
+ }
3382
+ /**
3383
+ * Assemble a dual-party `claimFromChannel` claim from a verified swap claim.
3384
+ *
3385
+ * Pure crypto (GraphQL-read state is passed in): resolves the on-chain A/B
3386
+ * participant ordering by reproducing `channelHash`, conserves balances against
3387
+ * `depositTotal`, computes the Poseidon commitment, and produces the recipient's
3388
+ * co-signature over `[commitment, nonce, channelHash]` with `mina-signer`. No
3389
+ * o1js is loaded.
3390
+ *
3391
+ * @throws {MinaSettlementError} `CHANNEL_HASH_MISMATCH` when neither ordering of
3392
+ * `{recipient, swapSignerAddress}` reproduces `onChainChannelHash`;
3393
+ * `CUMULATIVE_EXCEEDS_DEPOSIT` when the credit exceeds the escrow.
3394
+ */
3395
+ declare function buildMinaCoSignedClaim(inputs: MinaCoSignInputs): Promise<MinaCoSignedClaim>;
3396
+ /** Arguments handed to a {@link MinaClaimSubmitter} (o1js proving boundary). */
3397
+ interface MinaClaimSubmitArgs {
3398
+ /** Mina GraphQL endpoint bound as the active o1js network. */
3399
+ graphqlUrl: string;
3400
+ /** Channel zkApp address (B62). */
3401
+ channelId: string;
3402
+ balanceA: bigint;
3403
+ balanceB: bigint;
3404
+ salt: bigint;
3405
+ nonce: bigint;
3406
+ /** Participant pubkeys (B62), ordered to match the on-chain `channelHash`. */
3407
+ participantA: string;
3408
+ participantB: string;
3409
+ channelNonce: bigint;
3410
+ signatureA: MinaSignaturePair;
3411
+ signatureB: MinaSignaturePair;
3412
+ /** Fee-payer / submitter Mina private key (hex scalar or `EK…` base58). */
3413
+ feePayerPrivateKey: string;
3414
+ /** zkApp tx fee (nanomina); the default settler applies 0.1 MINA when unset. */
3415
+ txFeeNanomina?: bigint;
3416
+ }
3417
+ /**
3418
+ * Generates the o1js proof and broadcasts the `claimFromChannel` tx. Injected so
3419
+ * the assembly logic can be unit-tested without loading the WASM circuit runtime.
3420
+ */
3421
+ interface MinaClaimSubmitter {
3422
+ claimFromChannel(args: MinaClaimSubmitArgs): Promise<{
3423
+ txHash: string;
3424
+ }>;
3425
+ }
3426
+ /** Read seam for the on-chain channel state (default: plain GraphQL). */
3427
+ type MinaChannelStateReader = (graphqlUrl: string, zkAppAddress: string) => Promise<MinaOnChainChannelState>;
3428
+ /** Context for {@link submitMinaSettlement}. */
3429
+ interface MinaSettlementContext {
3430
+ /** Mina GraphQL URL (reads state + binds the o1js network). */
3431
+ graphqlUrl?: string;
3432
+ /** Recipient's Mina private key (co-signs; also the default fee payer). */
3433
+ recipientPrivateKey: string;
3434
+ /** Maker's on-chain-form co-signature over `[commitment, nonce, channelHash]`. */
3435
+ makerSignature?: MinaSignaturePair;
3436
+ /** Fee-payer key override (defaults to `recipientPrivateKey`). */
3437
+ feePayerPrivateKey?: string;
3438
+ /** zkApp tx fee (nanomina). */
3439
+ txFeeNanomina?: bigint;
3440
+ /** Channel nonce for the on-chain `channelHash` (default 0). */
3441
+ channelNonce?: bigint;
3442
+ /** Inject a state reader (tests). Defaults to {@link readMinaChannelState}. */
3443
+ reader?: MinaChannelStateReader;
3444
+ /** Inject a proof submitter (tests). Defaults to an o1js-backed settler. */
3445
+ submitter?: MinaClaimSubmitter;
3446
+ }
3447
+ interface MinaSettlementResult {
3448
+ txHash: string;
3449
+ }
3450
+ /**
3451
+ * Redeem a verified Mina swap claim via a co-signed on-chain `claimFromChannel`.
3452
+ *
3453
+ * Env/config-gated like the EVM path: with no `graphqlUrl` the caller gets
3454
+ * `NO_GRAPHQL_CONFIGURED` (built-not-submitted). Reads the live channel state,
3455
+ * asserts it is OPEN and the claim nonce advances the on-chain watermark,
3456
+ * assembles the dual-party claim ({@link buildMinaCoSignedClaim}), and — only
3457
+ * with a maker co-signature present — drives the o1js proof + broadcast.
3458
+ *
3459
+ * @throws {MinaSettlementError} with a stable {@link MinaSettlementErrorCode}.
3460
+ */
3461
+ declare function submitMinaSettlement(bundle: SettlementBundle, context: MinaSettlementContext): Promise<MinaSettlementResult>;
3462
+ /**
3463
+ * Build the default o1js-backed {@link MinaClaimSubmitter}.
3464
+ *
3465
+ * Mirrors the connector's `MinaPaymentChannelSDK.claimFromChannel`: binds the
3466
+ * active Mina network, fetches the channel + fee-payer accounts, deserializes the
3467
+ * `{r,s}` signatures, and builds + proves + broadcasts the zkApp
3468
+ * `claimFromChannel` method. o1js and `@toon-protocol/mina-zkapp` are imported
3469
+ * dynamically INSIDE `claimFromChannel` so the non-Mina test suite never loads
3470
+ * the multi-hundred-MB WASM circuit runtime. Compilation + proving are slow
3471
+ * (30-120s) and only run against live devnet Mina.
3472
+ */
3473
+ declare function createO1jsMinaClaimSubmitter(): MinaClaimSubmitter;
3474
+
3038
3475
  /**
3039
3476
  * Configuration options for retry behavior with exponential backoff.
3040
3477
  */
@@ -3274,7 +3711,7 @@ declare function validateConfig(config: ToonClientConfig): void;
3274
3711
  * The resolved config type after defaults are applied.
3275
3712
  * secretKey is guaranteed to be present (auto-generated if omitted).
3276
3713
  */
3277
- type ResolvedConfig = Required<Omit<ToonClientConfig, 'connector' | 'mnemonic' | 'mnemonicAccountIndex' | 'evmPrivateKey' | 'network' | 'supportedChains' | 'settlementAddresses' | 'preferredTokens' | 'tokenNetworks' | 'btpUrl' | 'btpAuthToken' | 'btpPeerId' | 'connectorHttpEndpoint' | 'proxyUrl' | 'faucetUrl' | 'connectorSupportsUpgrade' | 'chainRpcUrls' | 'initialDeposit' | 'settlementTimeout' | 'solanaChannel' | 'minaChannel' | 'channelStorePath' | 'knownPeers' | 'destinationAddress'>> & {
3714
+ type ResolvedConfig = Required<Omit<ToonClientConfig, 'connector' | 'mnemonic' | 'mnemonicAccountIndex' | 'evmPrivateKey' | 'network' | 'supportedChains' | 'settlementAddresses' | 'preferredTokens' | 'tokenNetworks' | 'btpUrl' | 'btpAuthToken' | 'btpPeerId' | 'connectorHttpEndpoint' | 'proxyUrl' | 'faucetUrl' | 'connectorSupportsUpgrade' | 'chainRpcUrls' | 'initialDeposit' | 'settlementTimeout' | 'solanaChannel' | 'minaChannel' | 'swapMinaMakerSignatures' | 'channelStorePath' | 'knownPeers' | 'destinationAddress'>> & {
3278
3715
  connector?: unknown;
3279
3716
  /** Always present after applyDefaults() — derived from secretKey if not explicitly provided */
3280
3717
  evmPrivateKey: string | Uint8Array;
@@ -3308,6 +3745,7 @@ type ResolvedConfig = Required<Omit<ToonClientConfig, 'connector' | 'mnemonic' |
3308
3745
  settlementTimeout?: number;
3309
3746
  solanaChannel?: ToonClientConfig['solanaChannel'];
3310
3747
  minaChannel?: ToonClientConfig['minaChannel'];
3748
+ swapMinaMakerSignatures?: ToonClientConfig['swapMinaMakerSignatures'];
3311
3749
  channelStorePath?: string;
3312
3750
  knownPeers?: {
3313
3751
  pubkey: string;
@@ -3737,4 +4175,4 @@ declare function loadKeystore(path: string, password: string): string;
3737
4175
  */
3738
4176
  declare function writeKeystoreFile(path: string, keystore: EncryptedKeystore): void;
3739
4177
 
3740
- export { type BackupPayload, type BalanceProofParams, BtpRuntimeClient, type BtpRuntimeClientConfig, type BuildSwapSettlementsParams, CONDITION_LENGTH, type ChainMetadata, type ChainSigner, ChannelFundingError, ChannelManager, type ClaimMessage, type ClaimResolver, ConnectorError, type DiscoveredIlpPeer, type EVMClaimMessage, type EncryptedKeystore, EvmSigner, type ExecutionConditionPair, FULFILLMENT_MISMATCH_CODE, FULFILLMENT_MISMATCH_MESSAGE, type FaucetChain, type FundWalletOptions, type FundWalletResult, type H402FetchOptions, Http402Client, type Http402ClientConfig, HttpConnectorAdmin, type HttpConnectorAdminConfig, HttpIlpClient, type HttpIlpClientConfig, type HttpIlpClientFactory, HttpRuntimeClient, type HttpRuntimeClientConfig, ILP_CLAIM_HEADER, ILP_CLAIM_WRAPPED_HEADER, ILP_PEER_ID_HEADER, type IlpSendParams, type IlpSendResultWithFulfillment, type IlpTransportChoice, InMemoryReceivedClaimStore, type IngestReceivedClaimsParams, type IngestReceivedClaimsResult, JsonFileReceivedClaimStore, KeyManager, type KeyManagerConfig, type MinaClaimMessage, type MinaDepositReader, MinaSigner, type MinaSignerOptions, NetworkError, OnChainChannelClient, type OnChainChannelClientConfig, type ParsedFulfillHttp, type ParsedX402Challenge, type PasskeyInfo, type PublishEventResult, type ReceivedClaimEntry, type ReceivedClaimRejection, type ReceivedClaimRejectionCode, type ReceivedClaimStore, type RequestBlobStorageParams, type RequestBlobStorageResult, type RetryOptions, type SelectIlpTransportOptions, type SignedBalanceProof, type SolanaChannelClientOptions, type SolanaClaimMessage, SolanaSigner, type SubmitEvmSettlementParams, type SubmitEvmSettlementResult, type SwapSettlementBuild, type ToonChannelAccept, ToonClient, type ToonClientConfig, ToonClientError, type ToonIdentity, type ToonSigners, type ToonStartResult, ValidationError, type VaultData, type VerifiedReceivedClaim, type WalletBalance, type WalletBalanceSources, type WalletChainBalances, type WalletTokenAmount, applyDefaults, applyNetworkPresets, assertValidCondition, buildBackupEvent, buildBackupFilter, buildSettlementInfo, buildStoreWriteEnvelope, buildSwapSettlements, decodeEvmSettlementTx, decryptMnemonic, defaultFaucetTimeout, deriveFromNsec, deriveFullIdentity, deriveNostrKeyFromMnemonic, encryptMnemonic, entryToAccumulatedClaim, extractArweaveTxId, fulfillmentMatchesCondition, fundWallet, generateKeystore, generateMnemonic, generateRandomIdentity, getNetworkStatus, hasSettlementMetadata, httpEndpointToBtpUrl, importKeystore, ingestReceivedClaims, isInsufficientGasError, isPrfSupported, isZeroCondition, loadKeystore, mintExecutionCondition, parseBackupPayload, parseEvmChainId, parseFulfillHttp, parseFulfillHttpBytes, parseHttpResponse, parseX402Body, parseX402Challenge, proxyIlpEndpoint, readDiscoveredIlpPeer, readEvmNativeBalance, readEvmTokenBalance, readMinaBalance, readMinaDepositTotal, readSolanaNativeBalance, readSolanaTokenBalance, readWalletBalances, requestBlobStorage, selectIlpTransport, serializeHttpRequest, submitEvmSettlement, validateConfig, validateMnemonic, withRetry, writeKeystoreFile };
4178
+ export { type BackupPayload, type BalanceProofParams, BtpRuntimeClient, type BtpRuntimeClientConfig, type BuildSwapSettlementsParams, CONDITION_LENGTH, type ChainMetadata, type ChainSigner, ChannelFundingError, ChannelManager, type ClaimMessage, type ClaimResolver, ConnectorError, type DiscoveredIlpPeer, type EVMClaimMessage, type EncryptedKeystore, EvmSigner, type ExecutionConditionPair, FULFILLMENT_MISMATCH_CODE, FULFILLMENT_MISMATCH_MESSAGE, type FaucetChain, type FundWalletOptions, type FundWalletResult, type H402FetchOptions, Http402Client, type Http402ClientConfig, HttpConnectorAdmin, type HttpConnectorAdminConfig, HttpIlpClient, type HttpIlpClientConfig, type HttpIlpClientFactory, HttpRuntimeClient, type HttpRuntimeClientConfig, ILP_CLAIM_HEADER, ILP_CLAIM_WRAPPED_HEADER, ILP_PEER_ID_HEADER, type IlpSendParams, type IlpSendResultWithFulfillment, type IlpTransportChoice, InMemoryPreimageRetentionStore, InMemoryReceivedClaimStore, type IngestAndRevealParams, type IngestAndRevealResult, type IngestReceivedClaimsParams, type IngestReceivedClaimsResult, JsonFileReceivedClaimStore, KeyManager, type KeyManagerConfig, MINA_CHANNEL_STATE, type MinaChannelStateReader, type MinaClaimMessage, type MinaClaimSubmitArgs, type MinaClaimSubmitter, type MinaCoSignInputs, type MinaCoSignedClaim, type MinaDepositReader, type MinaOnChainChannelState, type MinaSettlementContext, MinaSettlementError, type MinaSettlementErrorCode, type MinaSettlementResult, type MinaSignaturePair, MinaSigner, type MinaSignerOptions, NetworkError, OnChainChannelClient, type OnChainChannelClientConfig, type ParsedFulfillHttp, type ParsedX402Challenge, type PasskeyInfo, type PreimageRetentionStore, type PublishEventResult, type ReceivedClaimEntry, type ReceivedClaimRejection, type ReceivedClaimRejectionCode, type ReceivedClaimStore, type RequestBlobStorageParams, type RequestBlobStorageResult, type RetainedPreimage, type RetryOptions, type RevealDecision, type RevealFn, type RevealResult, type RevealedClaim, type RolledBackClaim, type SelectIlpTransportOptions, type SignedBalanceProof, type SolanaChannelClientOptions, type SolanaClaimMessage, SolanaSigner, type SubmitEvmSettlementParams, type SubmitEvmSettlementResult, type SwapSettlementBuild, type ToonChannelAccept, ToonClient, type ToonClientConfig, ToonClientError, type ToonIdentity, type ToonSigners, type ToonStartResult, ValidationError, type VaultData, type VerifiedReceivedClaim, type WalletBalance, type WalletBalanceSources, type WalletChainBalances, type WalletTokenAmount, applyDefaults, applyNetworkPresets, assertValidCondition, buildBackupEvent, buildBackupFilter, buildMinaCoSignedClaim, buildSettlementInfo, buildStoreWriteEnvelope, buildSwapSettlements, createO1jsMinaClaimSubmitter, decodeEvmSettlementTx, decryptMnemonic, defaultFaucetTimeout, deriveFromNsec, deriveFullIdentity, deriveNostrKeyFromMnemonic, encryptMnemonic, entryToAccumulatedClaim, extractArweaveTxId, fulfillmentMatchesCondition, fundWallet, generateKeystore, generateMnemonic, generateRandomIdentity, getNetworkStatus, hasSettlementMetadata, httpEndpointToBtpUrl, importKeystore, ingestAndReveal, ingestReceivedClaims, isInsufficientGasError, isPrfSupported, isZeroCondition, loadKeystore, mintExecutionCondition, parseBackupPayload, parseEvmChainId, parseFulfillHttp, parseFulfillHttpBytes, parseHttpResponse, parseX402Body, parseX402Challenge, proxyIlpEndpoint, readDiscoveredIlpPeer, readEvmNativeBalance, readEvmTokenBalance, readMinaBalance, readMinaChannelState, readMinaDepositTotal, readSolanaNativeBalance, readSolanaTokenBalance, readWalletBalances, requestBlobStorage, selectIlpTransport, serializeHttpRequest, submitEvmSettlement, submitMinaSettlement, validateConfig, validateMnemonic, withRetry, writeKeystoreFile };