@toon-protocol/client 0.17.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 +19 -24
- package/dist/index.d.ts +730 -9
- package/dist/index.js +896 -63
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import * as _toon_protocol_core from '@toon-protocol/core';
|
|
2
|
-
import { IlpPeerInfo, IlpSendResult, IlpClient, NetworkFamilyStatus, ConnectorAdminClient, ConnectorChannelClient, OpenChannelParams, OpenChannelResult, ChannelState } from '@toon-protocol/core';
|
|
2
|
+
import { IlpPeerInfo, IlpSendResult, IlpClient, SwapPair, NetworkFamilyStatus, ConnectorAdminClient, ConnectorChannelClient, OpenChannelParams, OpenChannelResult, ChannelState } from '@toon-protocol/core';
|
|
3
3
|
export { UI_RENDERER_KIND, UI_TAG, UiCoordinate, buildUiCoordinate, getUiCoordinate, parseUiCoordinate, selectLatestAddressable } from '@toon-protocol/core';
|
|
4
4
|
import { NostrEvent, EventTemplate } from 'nostr-tools/pure';
|
|
5
|
-
import {
|
|
5
|
+
import { MinaSignerClientLike, SettlementBundle } from '@toon-protocol/sdk';
|
|
6
|
+
import { AccumulatedClaim } from '@toon-protocol/sdk/swap';
|
|
7
|
+
import { PrivateKeyAccount, Hex } from 'viem';
|
|
8
|
+
import { PrivateKeyAccount as PrivateKeyAccount$1 } from 'viem/accounts';
|
|
6
9
|
export { A2uiDecision, ConsentDecision, ConsentRequest, DispatchGuardInfo, DispatchInput, GenerateContext, GeneratedRenderer, GenerativeDecision, GenerativeFallbackOptions, GenerativeFallbackRenderer, GenerativeFallbackResult, GuardedDispatchInput, IntentClassification, KindRegistry, MIME_A2UI, MIME_MCP_APP, McpUiDecision, NativeDecision, PublishBackOptions, RenderBranch, RenderDecision, RenderTrust, RendererGenerator, RendererPin, RendererPinStore, RendererPublisher, RendererSigner, ResolvedCoordinate, SwapApproval, SwapDecision, SwapRejection, SwapRejectionReason, UiResource, VerifyRendererInput, WidgetIntent, buildConsentRequest, buildRendererEventTemplate, classifyIntent, deterministicGenerator, extractUiResource, guardedRenderDispatch, isTrustDowngrade, publishBackCoordinate, renderDeterministicHtml, renderDispatch, resolveRendererMime, resolveUiCoordinate, resolveUiRenderer, verifyRendererTrust } from './render/index.js';
|
|
7
10
|
|
|
8
11
|
/** One on-chain wallet token balance. `amount` is base-unit integer, decimal. */
|
|
@@ -404,6 +407,24 @@ interface ToonClientConfig {
|
|
|
404
407
|
* gated (distinct from the connector #88 on-chain-settle gate).
|
|
405
408
|
*/
|
|
406
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
|
+
}>;
|
|
407
428
|
/** File path for persisting payment channel nonce/amount state across restarts */
|
|
408
429
|
channelStorePath?: string;
|
|
409
430
|
/** Nostr relay URL for peer discovery. Default: 'ws://localhost:7100' */
|
|
@@ -678,9 +699,10 @@ interface IlpSendParams {
|
|
|
678
699
|
executionCondition?: Uint8Array;
|
|
679
700
|
/**
|
|
680
701
|
* Explicit PREPARE `expiresAt` (spec R7). Defaults to `now + timeout`,
|
|
681
|
-
* preserving pre-#350 behavior.
|
|
702
|
+
* preserving pre-#350 behavior. Accepts a `Date` or an ISO 8601 string —
|
|
703
|
+
* `@toon-protocol/core` ≥2.1.0's `IlpClient` passes the string form.
|
|
682
704
|
*/
|
|
683
|
-
expiresAt?: Date;
|
|
705
|
+
expiresAt?: Date | string;
|
|
684
706
|
}
|
|
685
707
|
/**
|
|
686
708
|
* `IlpSendResult` plus the FULFILL preimage when a sender-chosen condition
|
|
@@ -1117,6 +1139,173 @@ declare function serializeHttpRequest(req: {
|
|
|
1117
1139
|
*/
|
|
1118
1140
|
declare function parseHttpResponse(bytes: Uint8Array): Response;
|
|
1119
1141
|
|
|
1142
|
+
/**
|
|
1143
|
+
* The persisted receive-side watermark for one swap target channel: the
|
|
1144
|
+
* HIGHEST-NONCE verified chain-B claim per `(chain, channelId)` (toon-client
|
|
1145
|
+
* issue #352, rolling-swap spec toon-meta docs/rolling-swap.md §3.2/§9).
|
|
1146
|
+
*
|
|
1147
|
+
* Claims are cumulative balance proofs — a higher-nonce claim supersedes every
|
|
1148
|
+
* earlier one — so persisting only the winner per channel is lossless for
|
|
1149
|
+
* settlement: `buildSettlementTx` redeems exactly this claim. Superseded claims
|
|
1150
|
+
* are informational and dropped.
|
|
1151
|
+
*/
|
|
1152
|
+
interface ReceivedClaimEntry {
|
|
1153
|
+
/** Target chain the claim settles on (`pair.to.chain`, e.g. `evm:base:8453`). */
|
|
1154
|
+
chain: string;
|
|
1155
|
+
/** Payment-channel id on the target chain (0x-hex for EVM, base58 otherwise). */
|
|
1156
|
+
channelId: string;
|
|
1157
|
+
/** Balance-proof nonce (strictly increasing per channel). */
|
|
1158
|
+
nonce: bigint;
|
|
1159
|
+
/** Cumulative transferred amount, target micro-units. */
|
|
1160
|
+
cumulativeAmount: bigint;
|
|
1161
|
+
/** Recipient address the claim pays (the sender's `chainRecipient`). */
|
|
1162
|
+
recipient: string;
|
|
1163
|
+
/** Swap peer's on-chain signer address the signature verified against. */
|
|
1164
|
+
swapSignerAddress: string;
|
|
1165
|
+
/** The verified signed claim bytes (chain-specific encoding). */
|
|
1166
|
+
claimBytes: Uint8Array;
|
|
1167
|
+
/** Optional swap-side claim id. */
|
|
1168
|
+
claimId?: string;
|
|
1169
|
+
/** The SwapPair the claim was priced against (settlement-time routing). */
|
|
1170
|
+
pair: SwapPair;
|
|
1171
|
+
/** Unix ms the winning claim was accepted off the wire. */
|
|
1172
|
+
receivedAt: number;
|
|
1173
|
+
/** Unix ms this entry was last advanced. */
|
|
1174
|
+
updatedAt: number;
|
|
1175
|
+
/** Unix ms of the last successful on-chain settlement submission. */
|
|
1176
|
+
settledAt?: number;
|
|
1177
|
+
/** Watermark nonce redeemed by that settlement (claims ≤ this are settled). */
|
|
1178
|
+
settledNonce?: bigint;
|
|
1179
|
+
/** Tx hash of the last settlement submission. */
|
|
1180
|
+
settleTxHash?: string;
|
|
1181
|
+
}
|
|
1182
|
+
/**
|
|
1183
|
+
* Persistence interface for received (chain-B) swap claims. Mirrors
|
|
1184
|
+
* {@link ChannelStore}'s sync surface; keyed by `(chain, channelId)`.
|
|
1185
|
+
*/
|
|
1186
|
+
interface ReceivedClaimStore {
|
|
1187
|
+
save(entry: ReceivedClaimEntry): void;
|
|
1188
|
+
load(chain: string, channelId: string): ReceivedClaimEntry | undefined;
|
|
1189
|
+
list(): ReceivedClaimEntry[];
|
|
1190
|
+
delete(chain: string, channelId: string): void;
|
|
1191
|
+
}
|
|
1192
|
+
/**
|
|
1193
|
+
* JSON file-backed {@link ReceivedClaimStore}. Synchronous I/O to match the
|
|
1194
|
+
* `JsonFileChannelStore` pattern (`ChannelStore.ts`); the parent directory is
|
|
1195
|
+
* created on first save so a fresh daemon home works out of the box.
|
|
1196
|
+
*/
|
|
1197
|
+
declare class JsonFileReceivedClaimStore implements ReceivedClaimStore {
|
|
1198
|
+
private readonly filePath;
|
|
1199
|
+
constructor(filePath: string);
|
|
1200
|
+
save(entry: ReceivedClaimEntry): void;
|
|
1201
|
+
load(chain: string, channelId: string): ReceivedClaimEntry | undefined;
|
|
1202
|
+
list(): ReceivedClaimEntry[];
|
|
1203
|
+
delete(chain: string, channelId: string): void;
|
|
1204
|
+
private readFile;
|
|
1205
|
+
private writeFile;
|
|
1206
|
+
}
|
|
1207
|
+
/**
|
|
1208
|
+
* In-memory {@link ReceivedClaimStore} for tests and path-less configs. NOT
|
|
1209
|
+
* restart-safe — a daemon should always be given a `JsonFileReceivedClaimStore`.
|
|
1210
|
+
*/
|
|
1211
|
+
declare class InMemoryReceivedClaimStore implements ReceivedClaimStore {
|
|
1212
|
+
private readonly entries;
|
|
1213
|
+
save(entry: ReceivedClaimEntry): void;
|
|
1214
|
+
load(chain: string, channelId: string): ReceivedClaimEntry | undefined;
|
|
1215
|
+
list(): ReceivedClaimEntry[];
|
|
1216
|
+
delete(chain: string, channelId: string): void;
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
/**
|
|
1220
|
+
* Receive-side swap settlement (toon-client#352): turn persisted
|
|
1221
|
+
* {@link ReceivedClaimEntry} watermarks into on-chain settlement submissions.
|
|
1222
|
+
*
|
|
1223
|
+
* Building is pure and chain-agnostic — `buildSettlementTx` (sdk) re-verifies
|
|
1224
|
+
* the stored claim's signature and produces one {@link SettlementBundle} per
|
|
1225
|
+
* `(chain, channelId)` with the FINAL watermark, so N received advances net to
|
|
1226
|
+
* one on-chain close per channel (spec §9). Submission is chain-gated:
|
|
1227
|
+
*
|
|
1228
|
+
* - **EVM** — implemented here ({@link submitEvmSettlement}): the bundle's
|
|
1229
|
+
* unsigned RLP is decoded for `to`/calldata, gas is estimated against the
|
|
1230
|
+
* configured RPC, and the tx is signed by the client's EVM account (the
|
|
1231
|
+
* claim recipient) and broadcast. Real submission is therefore env-gated on
|
|
1232
|
+
* `chainRpcUrls[chain]` — absent RPC config yields a built-not-submitted
|
|
1233
|
+
* result, never a throw.
|
|
1234
|
+
* - **Solana** — the bundle carries a serialized Message; a submission path is
|
|
1235
|
+
* not wired yet (follow-up under toon-meta#145).
|
|
1236
|
+
* - **Mina** — receive-side redemption needs a co-sign (`claimFromChannel`
|
|
1237
|
+
* takes `signatureA` AND `signatureB`) plus o1js proof generation; the
|
|
1238
|
+
* client has no receive-side co-sign path. Explicitly out of scope for #352
|
|
1239
|
+
* (documented gap; follow-up: toon-client#357).
|
|
1240
|
+
*/
|
|
1241
|
+
|
|
1242
|
+
/** One per-channel settlement build outcome (result-shaped, never thrown). */
|
|
1243
|
+
interface SwapSettlementBuild {
|
|
1244
|
+
chain: string;
|
|
1245
|
+
channelId: string;
|
|
1246
|
+
/** The bundle, when the claim verified and the chain config sufficed. */
|
|
1247
|
+
bundle?: SettlementBundle;
|
|
1248
|
+
/** Why no bundle was produced (missing config, failed re-verification, …). */
|
|
1249
|
+
error?: {
|
|
1250
|
+
code: string;
|
|
1251
|
+
message: string;
|
|
1252
|
+
};
|
|
1253
|
+
}
|
|
1254
|
+
interface BuildSwapSettlementsParams {
|
|
1255
|
+
/** Persisted watermarks to settle (typically `store.list()`, filtered). */
|
|
1256
|
+
entries: readonly ReceivedClaimEntry[];
|
|
1257
|
+
/**
|
|
1258
|
+
* Per-chain settlement contract: EVM TokenNetwork address / Solana
|
|
1259
|
+
* programId, keyed by the FULL chain key (e.g. `evm:base:8453`). Matches the
|
|
1260
|
+
* daemon config's `tokenNetworks` map.
|
|
1261
|
+
*/
|
|
1262
|
+
tokenNetworks?: Record<string, string>;
|
|
1263
|
+
/** Pre-loaded `mina-signer` client for `mina:*` re-verification. */
|
|
1264
|
+
minaSignerClient?: MinaSignerClientLike;
|
|
1265
|
+
}
|
|
1266
|
+
/** Rebuild the sdk `AccumulatedClaim` shape from a persisted entry. */
|
|
1267
|
+
declare function entryToAccumulatedClaim(entry: ReceivedClaimEntry): AccumulatedClaim;
|
|
1268
|
+
/**
|
|
1269
|
+
* Parse the numeric chain id off an `evm:{network}:{chainId}` / `evm:{chainId}`
|
|
1270
|
+
* chain key. Returns undefined for malformed keys (reported result-shaped).
|
|
1271
|
+
*/
|
|
1272
|
+
declare function parseEvmChainId(chain: string): number | undefined;
|
|
1273
|
+
/**
|
|
1274
|
+
* Build one settlement bundle per persisted entry via the sdk's
|
|
1275
|
+
* `buildSettlementTx` (signature re-verified at settle time — a tampered
|
|
1276
|
+
* store never reaches a submission). Per-entry isolation: one bad channel
|
|
1277
|
+
* cannot block the others.
|
|
1278
|
+
*/
|
|
1279
|
+
declare function buildSwapSettlements(params: BuildSwapSettlementsParams): SwapSettlementBuild[];
|
|
1280
|
+
interface SubmitEvmSettlementParams {
|
|
1281
|
+
/** JSON-RPC endpoint of the bundle's chain (`chainRpcUrls[bundle.chain]`). */
|
|
1282
|
+
rpcUrl: string;
|
|
1283
|
+
/** The claim recipient's EVM account (signs + pays gas for the redeem). */
|
|
1284
|
+
account: PrivateKeyAccount;
|
|
1285
|
+
/** Receipt wait bound, ms (default 60_000). */
|
|
1286
|
+
timeoutMs?: number;
|
|
1287
|
+
}
|
|
1288
|
+
interface SubmitEvmSettlementResult {
|
|
1289
|
+
txHash: string;
|
|
1290
|
+
/** Receipt status when the wait succeeded within the bound. */
|
|
1291
|
+
status?: 'success' | 'reverted';
|
|
1292
|
+
}
|
|
1293
|
+
/**
|
|
1294
|
+
* Decode the unsigned legacy-RLP tx a settlement bundle carries.
|
|
1295
|
+
* Layout (EIP-155 unsigned): [nonce, gasPrice, gasLimit, to, value, data, chainId, 0, 0].
|
|
1296
|
+
*/
|
|
1297
|
+
declare function decodeEvmSettlementTx(bundle: SettlementBundle): {
|
|
1298
|
+
to: Hex;
|
|
1299
|
+
data: Hex;
|
|
1300
|
+
chainId: number;
|
|
1301
|
+
};
|
|
1302
|
+
/**
|
|
1303
|
+
* Sign + broadcast an EVM settlement bundle from the recipient's account.
|
|
1304
|
+
* Gas/nonce are read from the RPC; the tx is signed locally (non-custodial)
|
|
1305
|
+
* and sent as a raw transaction, then awaited to a receipt (bounded).
|
|
1306
|
+
*/
|
|
1307
|
+
declare function submitEvmSettlement(bundle: SettlementBundle, params: SubmitEvmSettlementParams): Promise<SubmitEvmSettlementResult>;
|
|
1308
|
+
|
|
1120
1309
|
/**
|
|
1121
1310
|
* ToonClient - High-level client for interacting with TOON network.
|
|
1122
1311
|
*
|
|
@@ -1390,8 +1579,6 @@ declare class ToonClient {
|
|
|
1390
1579
|
private getClaimTransport;
|
|
1391
1580
|
/**
|
|
1392
1581
|
* Shared claim-resolution logic used by `publishEvent` and `sendSwapPacket`.
|
|
1393
|
-
* TODO(12.5 followup): also factor `publishEvent`'s inline claim resolution
|
|
1394
|
-
* to call this helper. Kept duplicated for now to minimize regression risk.
|
|
1395
1582
|
*/
|
|
1396
1583
|
private resolveClaimForDestination;
|
|
1397
1584
|
/**
|
|
@@ -1471,6 +1658,19 @@ declare class ToonClient {
|
|
|
1471
1658
|
channelId: string;
|
|
1472
1659
|
txHash?: string;
|
|
1473
1660
|
}>;
|
|
1661
|
+
/**
|
|
1662
|
+
* Submit a receive-side swap settlement bundle on-chain (toon-client#352).
|
|
1663
|
+
* The bundle comes from the sdk's `buildSettlementTx` over persisted,
|
|
1664
|
+
* verified chain-B claims (`buildSwapSettlements`); this signs it with the
|
|
1665
|
+
* client's EVM account (the claim recipient) and broadcasts it.
|
|
1666
|
+
*
|
|
1667
|
+
* Env-gated seam: EVM only, and only when `chainRpcUrls[bundle.chain]` is
|
|
1668
|
+
* configured — otherwise this throws a clear config error and callers
|
|
1669
|
+
* surface a built-not-submitted result. Solana submission and the Mina
|
|
1670
|
+
* receive-side co-sign path are explicit follow-ups (see
|
|
1671
|
+
* swap/settle-received-claims.ts module doc).
|
|
1672
|
+
*/
|
|
1673
|
+
settleSwapBundle(bundle: SettlementBundle): Promise<SubmitEvmSettlementResult>;
|
|
1474
1674
|
/** Where a tracked channel sits in the withdraw journey. */
|
|
1475
1675
|
getChannelCloseState(channelId: string): 'open' | 'closing' | 'settleable' | 'settled';
|
|
1476
1676
|
getSettleableAt(channelId: string): bigint | undefined;
|
|
@@ -2153,7 +2353,7 @@ declare class EvmSigner {
|
|
|
2153
2353
|
/** ChainSigner identifier — EVM address */
|
|
2154
2354
|
get signerIdentifier(): string;
|
|
2155
2355
|
/** Viem PrivateKeyAccount — usable with walletClient for on-chain transactions */
|
|
2156
|
-
get account(): PrivateKeyAccount;
|
|
2356
|
+
get account(): PrivateKeyAccount$1;
|
|
2157
2357
|
/**
|
|
2158
2358
|
* Signs a balance proof using EIP-712 typed data.
|
|
2159
2359
|
*
|
|
@@ -2751,6 +2951,526 @@ declare class ChannelManager {
|
|
|
2751
2951
|
* @param fetchImpl - injectable for tests; defaults to global `fetch`.
|
|
2752
2952
|
*/
|
|
2753
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>;
|
|
2992
|
+
|
|
2993
|
+
/**
|
|
2994
|
+
* Receive-side swap-claim ingestion + verification (toon-client#352, part of
|
|
2995
|
+
* the rolling-swap epic toon-meta#145; spec: toon-meta docs/rolling-swap.md
|
|
2996
|
+
* §3.2/§9 dependency 1).
|
|
2997
|
+
*
|
|
2998
|
+
* The deployed client used to accept swapped-in chain-B claims blind: no
|
|
2999
|
+
* signature check, no watermark, no persistence — `buildSettlementTx` /
|
|
3000
|
+
* `verifyAccumulatedClaim` had zero call sites in this repo. This module is
|
|
3001
|
+
* the missing pipeline: every accumulated claim harvested from a swap stream
|
|
3002
|
+
* is VERIFIED at receipt time and, only if it passes, persisted as the
|
|
3003
|
+
* highest-nonce watermark for its `(chain, channelId)` in a
|
|
3004
|
+
* {@link ReceivedClaimStore}. A claim that fails verification is NEVER counted
|
|
3005
|
+
* as value received — failures are loud and result-shaped, not thrown.
|
|
3006
|
+
*
|
|
3007
|
+
* Verification order per claim (cheapest first, every check fail-closed):
|
|
3008
|
+
* 1. settlement metadata completeness — a claim missing any of channelId /
|
|
3009
|
+
* nonce / cumulativeAmount / recipient / swapSignerAddress cannot be
|
|
3010
|
+
* settled (`MISSING_SETTLEMENT_METADATA` later) and is bucketed `legacy`
|
|
3011
|
+
* (the pre-rename-peer path, #349) rather than rejected: the existing
|
|
3012
|
+
* loud swap-time warning stays the surface for those.
|
|
3013
|
+
* 2. chain consistency — the claim must settle on the session's target chain.
|
|
3014
|
+
* 3. recipient — must equal the session `chainRecipient` (EVM
|
|
3015
|
+
* case-insensitive), the anti-substitution check.
|
|
3016
|
+
* 4. advertised signer — when the caller supplies the maker's advertised
|
|
3017
|
+
* `swapSignerAddress` (kind:10032 discovery / operator config), the
|
|
3018
|
+
* claim's self-reported signer must match (`SWAP_SIGNER_MISMATCH`,
|
|
3019
|
+
* sdk 2.x vocabulary).
|
|
3020
|
+
* 5. signature — `verifyAccumulatedClaim` (sdk) against the expected signer:
|
|
3021
|
+
* the advertised address when given, else the claim's self-reported one
|
|
3022
|
+
* (which then still proves the claim is internally consistent and pins
|
|
3023
|
+
* the address the settlement tx will verify against on-chain).
|
|
3024
|
+
* 6. signer pinning — a claim may not silently rotate the signer of an
|
|
3025
|
+
* already-persisted watermark for the same channel.
|
|
3026
|
+
* 7. nonce/cumulative monotonicity vs the locally persisted watermark —
|
|
3027
|
+
* strictly increasing nonce AND cumulative; the cumulative advance must
|
|
3028
|
+
* cover this packet's `targetAmount` (an under-delivering advance means
|
|
3029
|
+
* the maker short-paid the packet).
|
|
3030
|
+
*/
|
|
3031
|
+
|
|
3032
|
+
/** Why a claim was rejected at receipt time. Codes are stable API. */
|
|
3033
|
+
type ReceivedClaimRejectionCode = 'CHAIN_MISMATCH' | 'RECIPIENT_MISMATCH' | 'SWAP_SIGNER_MISMATCH' | 'SIGNER_MISMATCH' | 'SIGNATURE_INVALID' | 'MINA_VERIFICATION_UNSUPPORTED' | 'UNSUPPORTED_CHAIN' | 'NON_MONOTONIC_NONCE' | 'NON_MONOTONIC_CUMULATIVE' | 'CUMULATIVE_SHORTFALL' | 'MALFORMED_METADATA';
|
|
3034
|
+
interface ReceivedClaimRejection {
|
|
3035
|
+
claim: AccumulatedClaim;
|
|
3036
|
+
code: ReceivedClaimRejectionCode;
|
|
3037
|
+
message: string;
|
|
3038
|
+
}
|
|
3039
|
+
interface VerifiedReceivedClaim {
|
|
3040
|
+
claim: AccumulatedClaim;
|
|
3041
|
+
/** How far this claim advanced the persisted cumulative watermark. */
|
|
3042
|
+
watermarkAdvance: bigint;
|
|
3043
|
+
}
|
|
3044
|
+
interface IngestReceivedClaimsParams {
|
|
3045
|
+
/** Accumulated claims off a swap stream (`streamSwap().claims`), in order. */
|
|
3046
|
+
claims: readonly AccumulatedClaim[];
|
|
3047
|
+
/** The session's target chain (`pair.to.chain` of the requested swap). */
|
|
3048
|
+
expectedChain: string;
|
|
3049
|
+
/** The session's payout address on `expectedChain`. */
|
|
3050
|
+
chainRecipient: string;
|
|
3051
|
+
/**
|
|
3052
|
+
* The maker's ADVERTISED on-chain signer address for `expectedChain`
|
|
3053
|
+
* (kind:10032 discovery or operator-supplied). When set, a claim whose
|
|
3054
|
+
* self-reported `swapSignerAddress` differs is rejected with
|
|
3055
|
+
* `SWAP_SIGNER_MISMATCH` and the signature is verified against THIS address,
|
|
3056
|
+
* never the claim's own.
|
|
3057
|
+
*/
|
|
3058
|
+
expectedSignerAddress?: string;
|
|
3059
|
+
/** Durable watermark store; verified claims are persisted here. */
|
|
3060
|
+
store: ReceivedClaimStore;
|
|
3061
|
+
/** Pre-loaded `mina-signer` client — required to verify `mina:*` claims. */
|
|
3062
|
+
minaSignerClient?: MinaSignerClientLike;
|
|
3063
|
+
/** Clock seam for tests. */
|
|
3064
|
+
now?: () => number;
|
|
3065
|
+
}
|
|
3066
|
+
interface IngestReceivedClaimsResult {
|
|
3067
|
+
/** Claims that passed every check and advanced a persisted watermark. */
|
|
3068
|
+
verified: VerifiedReceivedClaim[];
|
|
3069
|
+
/** Claims that failed verification. NEVER counted as value received. */
|
|
3070
|
+
rejected: ReceivedClaimRejection[];
|
|
3071
|
+
/**
|
|
3072
|
+
* Claims missing settlement metadata (pre-rename / legacy swap peer, #349).
|
|
3073
|
+
* Not verified, not persisted, surfaced through the existing swap-time
|
|
3074
|
+
* warning — behavior for legacy no-metadata swaps is unchanged.
|
|
3075
|
+
*/
|
|
3076
|
+
legacy: AccumulatedClaim[];
|
|
3077
|
+
/** Total watermark advance across verified claims (target micro-units). */
|
|
3078
|
+
valueReceived: bigint;
|
|
3079
|
+
}
|
|
3080
|
+
/** True when the claim carries every settlement-context field. */
|
|
3081
|
+
declare function hasSettlementMetadata(claim: AccumulatedClaim): claim is AccumulatedClaim & Required<Pick<AccumulatedClaim, 'channelId' | 'nonce' | 'cumulativeAmount' | 'recipient' | 'swapSignerAddress'>>;
|
|
3082
|
+
/**
|
|
3083
|
+
* Verify a batch of received chain-B claims and persist the winning watermark
|
|
3084
|
+
* per `(chain, channelId)`. See the module doc for the check ladder.
|
|
3085
|
+
*
|
|
3086
|
+
* Result-shaped: never throws on a bad claim — it lands in `rejected` with a
|
|
3087
|
+
* stable code, and later claims are still processed (a channel's watermark
|
|
3088
|
+
* only advances through claims that verified).
|
|
3089
|
+
*/
|
|
3090
|
+
declare function ingestReceivedClaims(params: IngestReceivedClaimsParams): IngestReceivedClaimsResult;
|
|
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;
|
|
2754
3474
|
|
|
2755
3475
|
/**
|
|
2756
3476
|
* Configuration options for retry behavior with exponential backoff.
|
|
@@ -2991,7 +3711,7 @@ declare function validateConfig(config: ToonClientConfig): void;
|
|
|
2991
3711
|
* The resolved config type after defaults are applied.
|
|
2992
3712
|
* secretKey is guaranteed to be present (auto-generated if omitted).
|
|
2993
3713
|
*/
|
|
2994
|
-
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'>> & {
|
|
2995
3715
|
connector?: unknown;
|
|
2996
3716
|
/** Always present after applyDefaults() — derived from secretKey if not explicitly provided */
|
|
2997
3717
|
evmPrivateKey: string | Uint8Array;
|
|
@@ -3025,6 +3745,7 @@ type ResolvedConfig = Required<Omit<ToonClientConfig, 'connector' | 'mnemonic' |
|
|
|
3025
3745
|
settlementTimeout?: number;
|
|
3026
3746
|
solanaChannel?: ToonClientConfig['solanaChannel'];
|
|
3027
3747
|
minaChannel?: ToonClientConfig['minaChannel'];
|
|
3748
|
+
swapMinaMakerSignatures?: ToonClientConfig['swapMinaMakerSignatures'];
|
|
3028
3749
|
channelStorePath?: string;
|
|
3029
3750
|
knownPeers?: {
|
|
3030
3751
|
pubkey: string;
|
|
@@ -3454,4 +4175,4 @@ declare function loadKeystore(path: string, password: string): string;
|
|
|
3454
4175
|
*/
|
|
3455
4176
|
declare function writeKeystoreFile(path: string, keystore: EncryptedKeystore): void;
|
|
3456
4177
|
|
|
3457
|
-
export { type BackupPayload, type BalanceProofParams, BtpRuntimeClient, type BtpRuntimeClientConfig, 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, KeyManager, type KeyManagerConfig, type MinaClaimMessage, type MinaDepositReader, MinaSigner, type MinaSignerOptions, NetworkError, OnChainChannelClient, type OnChainChannelClientConfig, type ParsedFulfillHttp, type ParsedX402Challenge, type PasskeyInfo, type PublishEventResult, type RequestBlobStorageParams, type RequestBlobStorageResult, type RetryOptions, type SelectIlpTransportOptions, type SignedBalanceProof, type SolanaChannelClientOptions, type SolanaClaimMessage, SolanaSigner, type ToonChannelAccept, ToonClient, type ToonClientConfig, ToonClientError, type ToonIdentity, type ToonSigners, type ToonStartResult, ValidationError, type VaultData, type WalletBalance, type WalletBalanceSources, type WalletChainBalances, type WalletTokenAmount, applyDefaults, applyNetworkPresets, assertValidCondition, buildBackupEvent, buildBackupFilter, buildSettlementInfo, buildStoreWriteEnvelope, decryptMnemonic, defaultFaucetTimeout, deriveFromNsec, deriveFullIdentity, deriveNostrKeyFromMnemonic, encryptMnemonic, extractArweaveTxId, fulfillmentMatchesCondition, fundWallet, generateKeystore, generateMnemonic, generateRandomIdentity, getNetworkStatus, httpEndpointToBtpUrl, importKeystore, isInsufficientGasError, isPrfSupported, isZeroCondition, loadKeystore, mintExecutionCondition, parseBackupPayload, parseFulfillHttp, parseFulfillHttpBytes, parseHttpResponse, parseX402Body, parseX402Challenge, proxyIlpEndpoint, readDiscoveredIlpPeer, readEvmNativeBalance, readEvmTokenBalance, readMinaBalance, readMinaDepositTotal, readSolanaNativeBalance, readSolanaTokenBalance, readWalletBalances, requestBlobStorage, selectIlpTransport, serializeHttpRequest, 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 };
|