@toon-protocol/client 0.9.0 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +168 -34
- package/dist/anon-proxy-W3KMM7GU.js +23 -0
- package/dist/chunk-WHAEQLIW.js +276 -0
- package/dist/chunk-WHAEQLIW.js.map +1 -0
- package/dist/gateway-QOK47RKS.js +13 -0
- package/dist/gateway-QOK47RKS.js.map +1 -0
- package/dist/index.d.ts +1413 -34
- package/dist/index.js +2530 -430
- package/dist/index.js.map +1 -1
- package/dist/socks5-WTJBYGME.js +136 -0
- package/dist/socks5-WTJBYGME.js.map +1 -0
- package/package.json +21 -15
- package/dist/chunk-5WRI5ZAA.js +0 -31
- package/dist/mina-signer-J7GFWOGO.js +0 -6317
- package/dist/mina-signer-J7GFWOGO.js.map +0 -1
- /package/dist/{chunk-5WRI5ZAA.js.map → anon-proxy-W3KMM7GU.js.map} +0 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,75 @@
|
|
|
1
1
|
import * as _toon_protocol_core from '@toon-protocol/core';
|
|
2
|
-
import { IlpPeerInfo, IlpSendResult, IlpClient, ConnectorAdminClient, ConnectorChannelClient, OpenChannelParams, OpenChannelResult, ChannelState } from '@toon-protocol/core';
|
|
2
|
+
import { IlpPeerInfo, NetworkFamilyStatus, IlpSendResult, IlpClient, ConnectorAdminClient, ConnectorChannelClient, OpenChannelParams, OpenChannelResult, ChannelState } from '@toon-protocol/core';
|
|
3
3
|
import { NostrEvent } from 'nostr-tools/pure';
|
|
4
4
|
import { PrivateKeyAccount } from 'viem/accounts';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Solana payment-channel parameters supplied via `ToonClientConfig.solanaChannel`.
|
|
8
|
+
*
|
|
9
|
+
* Mirrors the `SolanaChannelConfig` consumed by `OnChainChannelClient`, minus
|
|
10
|
+
* the Ed25519 keypair (derived from the client's `mnemonic`, see
|
|
11
|
+
* `ToonClientConfig.solanaChannel`).
|
|
12
|
+
*/
|
|
13
|
+
interface SolanaChannelClientOptions {
|
|
14
|
+
/** Solana JSON-RPC URL used to open the channel + read PDA state. */
|
|
15
|
+
rpcUrl: string;
|
|
16
|
+
/** Deployed payment-channel program id (base58). */
|
|
17
|
+
programId: string;
|
|
18
|
+
/**
|
|
19
|
+
* Default SPL token mint (base58) for PDA derivation. The per-channel
|
|
20
|
+
* negotiated token (the peer's preferred token) takes precedence when present.
|
|
21
|
+
*/
|
|
22
|
+
tokenMint?: string;
|
|
23
|
+
/** Challenge-period duration (seconds) for `initialize_channel`. */
|
|
24
|
+
challengeDuration?: number;
|
|
25
|
+
/**
|
|
26
|
+
* Optional on-chain deposit when opening the channel: `amount` in base units
|
|
27
|
+
* (string) drawn from `payerTokenAccount` (the client's funded SPL token
|
|
28
|
+
* account / ATA, base58). When omitted, the channel is opened without a
|
|
29
|
+
* deposit (connector accepts on `opened` status + participant membership).
|
|
30
|
+
*/
|
|
31
|
+
deposit?: {
|
|
32
|
+
amount: string;
|
|
33
|
+
payerTokenAccount: string;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Mina payment-channel parameters supplied via `ToonClientConfig.minaChannel`.
|
|
38
|
+
*
|
|
39
|
+
* Mirrors the `MinaChannelConfig` consumed by `OnChainChannelClient`, minus the
|
|
40
|
+
* Mina private key (derived from the client's `mnemonic`, the same key that
|
|
41
|
+
* produces the registered Mina signer — so the channel-open key and the
|
|
42
|
+
* claim-signing key are guaranteed identical).
|
|
43
|
+
*
|
|
44
|
+
* ────────────────────────────────────────────────────────────────────────────
|
|
45
|
+
* PHASE-2 STAGE-3: the client's Mina claim now matches connector 3.9.0's
|
|
46
|
+
* `MinaClaimMessage` contract — `{ zkAppAddress, tokenId, balanceCommitment,
|
|
47
|
+
* proof (base64), salt, nonce }`, with the proof a Pallas Schnorr signature over
|
|
48
|
+
* the connector's `Poseidon([balA,balB,salt]) / Poseidon(zkApp.x)` commitment
|
|
49
|
+
* (verified field-by-field against the connector's o1js verify). A
|
|
50
|
+
* Mina-denominated paid publish is ACCEPTED at `validateClaimMessage` and the
|
|
51
|
+
* apex FULFILLs to town. On-chain SETTLE remains gated for non-EVM dynamic
|
|
52
|
+
* hidden-service peers by connector#88 (`No chain configured for peer`).
|
|
53
|
+
* `zkAppAddress` must be a REAL deployed payment-channel zkApp the apex's Mina
|
|
54
|
+
* provider can resolve on-chain (the e2e harness deploys it deterministically).
|
|
55
|
+
* ────────────────────────────────────────────────────────────────────────────
|
|
56
|
+
*/
|
|
57
|
+
interface MinaChannelClientOptions {
|
|
58
|
+
/** Mina GraphQL URL used to open the channel + read zkApp state. */
|
|
59
|
+
graphqlUrl: string;
|
|
60
|
+
/** Deployed payment-channel zkApp address (B62 base58). */
|
|
61
|
+
zkAppAddress: string;
|
|
62
|
+
/** Channel settlement timeout in slots for `initializeChannel` (default 86400). */
|
|
63
|
+
challengeDuration?: number;
|
|
64
|
+
/** Mina token id field (decimal string) for `initializeChannel` (default '1'). */
|
|
65
|
+
tokenId?: string;
|
|
66
|
+
/** Optional on-chain deposit (base units, string) after the channel opens. */
|
|
67
|
+
deposit?: {
|
|
68
|
+
amount: string;
|
|
69
|
+
};
|
|
70
|
+
/** Mina network id for the account/Schnorr prefix (default 'devnet'). */
|
|
71
|
+
networkId?: 'devnet' | 'mainnet';
|
|
72
|
+
}
|
|
6
73
|
/**
|
|
7
74
|
* Configuration for ToonClient.
|
|
8
75
|
*
|
|
@@ -43,9 +110,41 @@ interface ToonClientConfig {
|
|
|
43
110
|
* Reserved for future implementation.
|
|
44
111
|
*/
|
|
45
112
|
connector?: unknown;
|
|
113
|
+
/**
|
|
114
|
+
* BIP-39 mnemonic phrase to derive a full multi-chain identity from.
|
|
115
|
+
*
|
|
116
|
+
* When provided, the client derives the Nostr (NIP-06) + EVM keys
|
|
117
|
+
* synchronously at construction and the Solana (Ed25519) + Mina (Pallas) keys
|
|
118
|
+
* lazily in `start()`, registering per-chain signers so balance-proof claims
|
|
119
|
+
* can be settled on any of those chains. This is the recommended way to use
|
|
120
|
+
* non-EVM settlement (the raw `secretKey` path is secp256k1-only).
|
|
121
|
+
*
|
|
122
|
+
* Cannot be combined with `secretKey` (ambiguous Nostr identity). May be
|
|
123
|
+
* combined with `evmPrivateKey` to use a separate EVM key (e.g. hardware
|
|
124
|
+
* wallet) while still deriving Solana/Mina from the phrase.
|
|
125
|
+
*
|
|
126
|
+
* SECURITY: JavaScript strings are immutable and cannot be zeroed from
|
|
127
|
+
* memory — the phrase may persist in the heap until GC. Prefer
|
|
128
|
+
* passing a pre-derived `secretKey`/identity in high-security contexts.
|
|
129
|
+
*/
|
|
130
|
+
mnemonic?: string;
|
|
131
|
+
/**
|
|
132
|
+
* BIP-44 account index used when deriving the multi-chain identity from
|
|
133
|
+
* `mnemonic`. Defaults to 0 (back-compat). A non-zero index derives a
|
|
134
|
+
* dedicated wallet from a shared mnemonic, producing the SAME addresses as
|
|
135
|
+
* the SDK's `fromMnemonicFull(mnemonic, { accountIndex })`:
|
|
136
|
+
* - Nostr (secp256k1): m/44'/1237'/0'/0/{index}
|
|
137
|
+
* - EVM (secp256k1): same key as Nostr
|
|
138
|
+
* - Solana (Ed25519): m/44'/501'/{index}'/0' (SLIP-0010)
|
|
139
|
+
* - Mina (Pallas): m/44'/12586'/{index}'/0/0
|
|
140
|
+
*
|
|
141
|
+
* Ignored unless `mnemonic` is provided.
|
|
142
|
+
*/
|
|
143
|
+
mnemonicAccountIndex?: number;
|
|
46
144
|
/**
|
|
47
145
|
* 32-byte Nostr private key (hex or Uint8Array).
|
|
48
|
-
* Optional — if omitted, a keypair is auto-generated in applyDefaults()
|
|
146
|
+
* Optional — if omitted, a keypair is auto-generated in applyDefaults()
|
|
147
|
+
* (or derived from `mnemonic` when that is provided instead).
|
|
49
148
|
*/
|
|
50
149
|
secretKey?: Uint8Array;
|
|
51
150
|
/** ILP peer information for this client */
|
|
@@ -65,6 +164,27 @@ interface ToonClientConfig {
|
|
|
65
164
|
* (e.g., hardware wallet, custodial key, or legacy key separation).
|
|
66
165
|
*/
|
|
67
166
|
evmPrivateKey?: string | Uint8Array;
|
|
167
|
+
/**
|
|
168
|
+
* Named network tier. When set (and != `'custom'`), the client defaults all
|
|
169
|
+
* settlement-related config — RPC/GraphQL URLs, supported chain identifiers,
|
|
170
|
+
* preferred tokens, EVM TokenNetwork addresses, and the Solana/Mina channel
|
|
171
|
+
* params (programId / zkApp) — from the shared core presets
|
|
172
|
+
* (`resolveClientNetwork`), so the caller no longer hand-wires every address.
|
|
173
|
+
* This is the client-side mirror of the townhouse node's `network` selector;
|
|
174
|
+
* both resolve the SAME deployed contracts.
|
|
175
|
+
*
|
|
176
|
+
* Precedence: any explicit per-chain field (`supportedChains`,
|
|
177
|
+
* `chainRpcUrls`, `settlementAddresses`, `preferredTokens`, `tokenNetworks`,
|
|
178
|
+
* `solanaChannel`, `minaChannel`) you also pass OVERRIDES the preset for that
|
|
179
|
+
* field. `'custom'` keeps the fully-manual path (no preset defaults). When
|
|
180
|
+
* unset, behaviour is unchanged (fully backward compatible).
|
|
181
|
+
*
|
|
182
|
+
* - `mainnet` — Base mainnet + public Solana/Mina (TOON contracts not yet
|
|
183
|
+
* deployed → settlement unconfigured, relay-only).
|
|
184
|
+
* - `testnet` / `devnet` — Base Sepolia + Solana/Mina devnet with the LIVE
|
|
185
|
+
* deployed TOON settlement contracts.
|
|
186
|
+
*/
|
|
187
|
+
network?: 'mainnet' | 'testnet' | 'devnet' | 'custom';
|
|
68
188
|
/** Supported settlement chain identifiers (e.g., ["evm:anvil:31337"]) */
|
|
69
189
|
supportedChains?: string[];
|
|
70
190
|
/** Maps chain identifier to EVM settlement address */
|
|
@@ -94,8 +214,66 @@ interface ToonClientConfig {
|
|
|
94
214
|
initialDeposit?: string;
|
|
95
215
|
/** Challenge period in seconds (default: 86400) */
|
|
96
216
|
settlementTimeout?: number;
|
|
217
|
+
/**
|
|
218
|
+
* Solana payment-channel parameters for opening a REAL on-chain channel and
|
|
219
|
+
* signing a connector-format Solana balance proof.
|
|
220
|
+
*
|
|
221
|
+
* When present (and the client has a Solana signer — i.e. it was constructed
|
|
222
|
+
* from a `mnemonic`), `ToonClient.start()` wires these into the on-chain
|
|
223
|
+
* channel client so that negotiating a `solana:*` chain opens an on-chain
|
|
224
|
+
* channel at the connector-parity PDA and pays a Solana-denominated claim.
|
|
225
|
+
*
|
|
226
|
+
* The Ed25519 keypair is NOT carried here — it is derived from the same
|
|
227
|
+
* `mnemonic` that produces the Solana signer, so the channel-open key and the
|
|
228
|
+
* claim-signing key are guaranteed identical.
|
|
229
|
+
*/
|
|
230
|
+
solanaChannel?: SolanaChannelClientOptions;
|
|
231
|
+
/**
|
|
232
|
+
* Mina payment-channel parameters (graphqlUrl + zkAppAddress). When present
|
|
233
|
+
* (and the client has a Mina signer — i.e. it was constructed from a
|
|
234
|
+
* `mnemonic` AND `mina-signer` is installed), `ToonClient.start()` wires these
|
|
235
|
+
* into the on-chain channel client so negotiating a `mina:*` chain routes
|
|
236
|
+
* through `openMinaChannel` and pays a Mina-denominated claim.
|
|
237
|
+
*
|
|
238
|
+
* The Mina private key is NOT carried here — it is derived from the same
|
|
239
|
+
* `mnemonic` that produces the Mina signer.
|
|
240
|
+
*
|
|
241
|
+
* NOTE (Phase-2 Stage-3 gate): see `MinaChannelClientOptions` — supplying this
|
|
242
|
+
* wires the negotiation path but the resulting claim does not yet satisfy
|
|
243
|
+
* connector 3.9.0's Mina claim contract, so a live loop is claim-validation
|
|
244
|
+
* gated (distinct from the connector #88 on-chain-settle gate).
|
|
245
|
+
*/
|
|
246
|
+
minaChannel?: MinaChannelClientOptions;
|
|
97
247
|
/** File path for persisting payment channel nonce/amount state across restarts */
|
|
98
248
|
channelStorePath?: string;
|
|
249
|
+
/**
|
|
250
|
+
* Transport configuration for privacy-preserving connections.
|
|
251
|
+
*
|
|
252
|
+
* - `direct` (default): No privacy overlay, connect directly.
|
|
253
|
+
* - `socks5`: Route connections through a SOCKS5 proxy (Node.js only).
|
|
254
|
+
* Requires `socks5h://` scheme for DNS leak prevention.
|
|
255
|
+
* - `gateway`: Route connections through an ator gateway URL (browser-compatible).
|
|
256
|
+
* The gateway proxies through ator server-side.
|
|
257
|
+
*/
|
|
258
|
+
transport?: ClientTransportConfig;
|
|
259
|
+
/**
|
|
260
|
+
* Self-managed `anon` (anyone-protocol / ATOR) SOCKS5h proxy (Node.js only).
|
|
261
|
+
*
|
|
262
|
+
* When the `btpUrl` host ends in `.anyone` and NO explicit proxy is configured
|
|
263
|
+
* (`transport.socksProxy` / `transport.type === 'gateway'`) and the
|
|
264
|
+
* `ANYONE_PROXY_URLS` env var is unset, the SDK auto-downloads + spawns its own
|
|
265
|
+
* `anon` daemon, waits for it to bootstrap + bind a loopback SOCKS5 port, and
|
|
266
|
+
* routes BTP/HTTP through it — ZERO manual proxy setup. `client.stop()` tears
|
|
267
|
+
* the daemon down.
|
|
268
|
+
*
|
|
269
|
+
* - `undefined` (default): auto — managed proxy starts for `.anyone` hosts.
|
|
270
|
+
* - `false`: opt out — never auto-start (you must supply your own proxy).
|
|
271
|
+
*
|
|
272
|
+
* Ignored in browser bundles (the node-only daemon module is never loaded).
|
|
273
|
+
*/
|
|
274
|
+
managedAnonProxy?: boolean;
|
|
275
|
+
/** Loopback SOCKS port the managed `anon` daemon binds. Default 9050. */
|
|
276
|
+
managedAnonSocksPort?: number;
|
|
99
277
|
/** Nostr relay URL for peer discovery. Default: 'ws://localhost:7100' */
|
|
100
278
|
relayUrl?: string;
|
|
101
279
|
/**
|
|
@@ -166,7 +344,52 @@ interface SignedBalanceProof extends BalanceProofParams {
|
|
|
166
344
|
tokenNetworkAddress: string;
|
|
167
345
|
/** ERC-20 token address (e.g. USDC) for self-describing claim verification */
|
|
168
346
|
tokenAddress?: string;
|
|
347
|
+
/**
|
|
348
|
+
* Counterparty settlement address the balance proof is bound to.
|
|
349
|
+
*
|
|
350
|
+
* Required for Solana/Mina, where the canonical balance-proof message folds
|
|
351
|
+
* the recipient in (`balanceProofHashSolana` / `balanceProofFieldsMina`).
|
|
352
|
+
* Unused for the client's EVM path (EIP-712 `BalanceProof` has no recipient
|
|
353
|
+
* term). Carried here so it flows from signing through to `buildClaimMessage`.
|
|
354
|
+
*/
|
|
355
|
+
recipient?: string;
|
|
356
|
+
/**
|
|
357
|
+
* Mina payment-channel claim fields (connector 3.9.0 `MinaClaimMessage`).
|
|
358
|
+
*
|
|
359
|
+
* Populated only by {@link MinaSigner}, which produces the connector's
|
|
360
|
+
* `Poseidon([balA,balB,salt])` balance commitment + a Pallas Schnorr `proof`
|
|
361
|
+
* over `[commitment, Field(nonce), Poseidon(zkApp.x)]` rather than reusing the
|
|
362
|
+
* generic `signature` field. Carried so they flow from signing through to
|
|
363
|
+
* `MinaSigner.buildClaimMessage`. Absent for EVM/Solana.
|
|
364
|
+
*/
|
|
365
|
+
mina?: {
|
|
366
|
+
/** `Poseidon([balanceA, balanceB, salt]).toString()`. */
|
|
367
|
+
balanceCommitment: string;
|
|
368
|
+
/** base64-encoded JSON proof `{ commitment, signature: { r, s }, nonce, signerPublicKey }`. */
|
|
369
|
+
proof: string;
|
|
370
|
+
/** Decimal salt string. */
|
|
371
|
+
salt: string;
|
|
372
|
+
/** Mina token id (default `'MINA'`). */
|
|
373
|
+
tokenId: string;
|
|
374
|
+
};
|
|
169
375
|
}
|
|
376
|
+
/**
|
|
377
|
+
* Transport configuration for privacy-preserving connections.
|
|
378
|
+
*
|
|
379
|
+
* Node.js: Use `socks5` to route WebSocket and HTTP through a SOCKS5 proxy.
|
|
380
|
+
* Browser: Use `gateway` to route through a server-side ator gateway.
|
|
381
|
+
*/
|
|
382
|
+
type ClientTransportConfig = {
|
|
383
|
+
type: 'direct';
|
|
384
|
+
} | {
|
|
385
|
+
type: 'socks5';
|
|
386
|
+
/** SOCKS5 proxy URL. MUST use `socks5h://` scheme (DNS leak prevention). */
|
|
387
|
+
socksProxy: string;
|
|
388
|
+
} | {
|
|
389
|
+
type: 'gateway';
|
|
390
|
+
/** Gateway base URL that proxies connections through ator server-side. */
|
|
391
|
+
gatewayUrl: string;
|
|
392
|
+
};
|
|
170
393
|
|
|
171
394
|
/**
|
|
172
395
|
* ToonClient - High-level client for interacting with TOON network.
|
|
@@ -209,6 +432,20 @@ declare class ToonClient {
|
|
|
209
432
|
private readonly config;
|
|
210
433
|
private state;
|
|
211
434
|
private readonly evmSigner?;
|
|
435
|
+
private solanaSigner?;
|
|
436
|
+
/**
|
|
437
|
+
* Ed25519 signing seed (32 bytes) derived from the mnemonic for the Solana
|
|
438
|
+
* identity. Retained so `start()` can inject it into the on-chain channel
|
|
439
|
+
* client's Solana config (same key as `solanaSigner`).
|
|
440
|
+
*/
|
|
441
|
+
private solanaSeed?;
|
|
442
|
+
private minaSigner?;
|
|
443
|
+
/**
|
|
444
|
+
* Mina private key (big-endian hex scalar, as `deriveFullIdentity` emits)
|
|
445
|
+
* derived from the mnemonic. Retained so `start()` can inject it into the
|
|
446
|
+
* on-chain channel client's Mina config (same key as `minaSigner`).
|
|
447
|
+
*/
|
|
448
|
+
private minaPrivateKey?;
|
|
212
449
|
private channelManager?;
|
|
213
450
|
private readonly peerNegotiations;
|
|
214
451
|
/**
|
|
@@ -232,10 +469,34 @@ declare class ToonClient {
|
|
|
232
469
|
* Works before start() is called.
|
|
233
470
|
*/
|
|
234
471
|
getPublicKey(): string;
|
|
472
|
+
/**
|
|
473
|
+
* Per-chain settlement readiness for the configured `network` tier, mirroring
|
|
474
|
+
* the townhouse node's status. Returns `undefined` when no named `network` is
|
|
475
|
+
* set (or `network: 'custom'`), since there is no preset tier to report on.
|
|
476
|
+
*/
|
|
477
|
+
getNetworkStatus(): NetworkFamilyStatus | undefined;
|
|
235
478
|
/**
|
|
236
479
|
* Gets the EVM address derived from the Nostr secret key (or explicit evmPrivateKey override).
|
|
237
480
|
*/
|
|
238
481
|
getEvmAddress(): string | undefined;
|
|
482
|
+
/**
|
|
483
|
+
* Gets the Solana (base58) address, when the client was constructed from a
|
|
484
|
+
* `mnemonic`. Available only AFTER `start()` (Solana keys are derived
|
|
485
|
+
* asynchronously). Returns undefined otherwise.
|
|
486
|
+
*/
|
|
487
|
+
getSolanaAddress(): string | undefined;
|
|
488
|
+
/**
|
|
489
|
+
* Gets the Mina (base58) address, when the client was constructed from a
|
|
490
|
+
* `mnemonic` AND `mina-signer` is installed. Available only AFTER `start()`.
|
|
491
|
+
* Returns undefined otherwise.
|
|
492
|
+
*/
|
|
493
|
+
getMinaAddress(): string | undefined;
|
|
494
|
+
/**
|
|
495
|
+
* Derive the Solana/Mina keys from the mnemonic and register their signers on
|
|
496
|
+
* the ChannelManager. Mirrors how the EVM signer is wired, but for the
|
|
497
|
+
* non-secp256k1 chains. Skips any chain whose optional dependency is missing.
|
|
498
|
+
*/
|
|
499
|
+
private registerMnemonicChainSigners;
|
|
239
500
|
/**
|
|
240
501
|
* Starts the ToonClient.
|
|
241
502
|
*
|
|
@@ -263,7 +524,58 @@ declare class ToonClient {
|
|
|
263
524
|
publishEvent(event: NostrEvent, options?: {
|
|
264
525
|
destination?: string;
|
|
265
526
|
claim?: SignedBalanceProof;
|
|
527
|
+
ilpAmount?: bigint;
|
|
266
528
|
}): Promise<PublishEventResult>;
|
|
529
|
+
/**
|
|
530
|
+
* Sends a raw swap ILP packet (Story 12.5) to a Mill peer with an attached
|
|
531
|
+
* balance-proof claim. This is a lower-level surface than `publishEvent`:
|
|
532
|
+
* it forwards the raw `IlpSendResult` so the sender (`streamSwap()`) can
|
|
533
|
+
* decode FULFILL metadata itself.
|
|
534
|
+
*
|
|
535
|
+
* Claim resolution mirrors `publishEvent`:
|
|
536
|
+
* (a) explicit `params.claim` -> use it,
|
|
537
|
+
* (b) `channelManager` present -> auto-open + auto-sign for the peer
|
|
538
|
+
* matching `destination`,
|
|
539
|
+
* (c) neither -> throw MISSING_CLAIM.
|
|
540
|
+
*
|
|
541
|
+
* @throws {ToonClientError} INVALID_STATE / NO_BTP_CLIENT / MISSING_CLAIM
|
|
542
|
+
*/
|
|
543
|
+
sendSwapPacket(params: {
|
|
544
|
+
destination: string;
|
|
545
|
+
amount: bigint;
|
|
546
|
+
toonData: Uint8Array;
|
|
547
|
+
timeout?: number;
|
|
548
|
+
claim?: SignedBalanceProof;
|
|
549
|
+
}): Promise<IlpSendResult>;
|
|
550
|
+
/**
|
|
551
|
+
* Build a BTP claim message from a pre-signed balance proof using the
|
|
552
|
+
* CHAIN-APPROPRIATE signer.
|
|
553
|
+
*
|
|
554
|
+
* The explicit-claim path (caller signs the balance proof, then passes
|
|
555
|
+
* `{ claim }`) must wrap the proof with the signer matching the channel's
|
|
556
|
+
* chain. Hardcoding `EvmSigner.buildClaimMessage` here produced an EVM
|
|
557
|
+
* `BTPClaimMessage` for a Solana/Mina balance proof — no `blockchain`
|
|
558
|
+
* discriminator and the base58 channel account placed in the EVM
|
|
559
|
+
* `channelId` field — which the connector's inbound validator classifies
|
|
560
|
+
* as EVM and rejects with F06 (`Invalid channelId format`).
|
|
561
|
+
*
|
|
562
|
+
* When the proof's `channelId` is tracked we use
|
|
563
|
+
* `getSignerForChannel(channelId).buildClaimMessage`, which emits the
|
|
564
|
+
* correct per-chain envelope (e.g. `blockchain:'solana'` + base58
|
|
565
|
+
* `channelAccount`). When it is not tracked we fall back to the EVM signer
|
|
566
|
+
* to preserve prior behavior for lightweight/EVM-only callers.
|
|
567
|
+
*
|
|
568
|
+
* EVM output is byte-identical to the previous hardcoded path (the EVM
|
|
569
|
+
* adapter in `getSignerForChannel` delegates to the same
|
|
570
|
+
* `EvmSigner.buildClaimMessage`).
|
|
571
|
+
*/
|
|
572
|
+
private buildClaimMessageForProof;
|
|
573
|
+
/**
|
|
574
|
+
* Shared claim-resolution logic used by `publishEvent` and `sendSwapPacket`.
|
|
575
|
+
* TODO(12.5 followup): also factor `publishEvent`'s inline claim resolution
|
|
576
|
+
* to call this helper. Kept duplicated for now to minimize regression risk.
|
|
577
|
+
*/
|
|
578
|
+
private resolveClaimForDestination;
|
|
267
579
|
/**
|
|
268
580
|
* Signs a balance proof for the given channel with the specified amount.
|
|
269
581
|
* Delegates to ChannelManager which auto-increments nonce and tracks cumulative amount.
|
|
@@ -274,6 +586,22 @@ declare class ToonClient {
|
|
|
274
586
|
* @throws {ToonClientError} If no EVM signer configured or channel not tracked
|
|
275
587
|
*/
|
|
276
588
|
signBalanceProof(channelId: string, amount: bigint): Promise<SignedBalanceProof>;
|
|
589
|
+
/**
|
|
590
|
+
* Eagerly open (or return existing) payment channel for the given destination.
|
|
591
|
+
*
|
|
592
|
+
* Channels are normally opened lazily on the first `publishEvent()` /
|
|
593
|
+
* `sendSwapPacket()` call. This method exposes the lazy-open path so
|
|
594
|
+
* callers (and E2E tests) that need a tracked `channelId` BEFORE publishing
|
|
595
|
+
* can force the open. Idempotent — returns the existing channel ID for the
|
|
596
|
+
* peer if one is already open.
|
|
597
|
+
*
|
|
598
|
+
* @param destination - Optional ILP destination address. Defaults to
|
|
599
|
+
* `config.destinationAddress`.
|
|
600
|
+
* @returns The channel ID of the (now) open channel.
|
|
601
|
+
* @throws {ToonClientError} If client not started, no channel manager
|
|
602
|
+
* configured, or peer negotiation metadata missing.
|
|
603
|
+
*/
|
|
604
|
+
openChannel(destination?: string): Promise<string>;
|
|
277
605
|
/**
|
|
278
606
|
* Gets list of tracked payment channel IDs.
|
|
279
607
|
*/
|
|
@@ -343,6 +671,48 @@ declare class ToonClient {
|
|
|
343
671
|
getDiscoveredPeers(): _toon_protocol_core.DiscoveredPeer[];
|
|
344
672
|
}
|
|
345
673
|
|
|
674
|
+
/**
|
|
675
|
+
* Hidden-service hostname validation for the anyone-protocol / ATOR network.
|
|
676
|
+
*
|
|
677
|
+
* The `anon` binary routes hidden-service hostnames under the **`.anyone`** TLD
|
|
678
|
+
* ONLY. A `<host>.anon` name is NOT recognized as a hidden service — anon treats
|
|
679
|
+
* it as a clearnet name and tries to exit-resolve it, which fails
|
|
680
|
+
* (`resolve failed` / `HostUnreachable`). Only `<host>.anyone` triggers anon's
|
|
681
|
+
* `parse_extended_hostname: Anyone dns address lookup` and is validated.
|
|
682
|
+
*
|
|
683
|
+
* Historically the client and the toon-client pod accepted BOTH `.anon` and
|
|
684
|
+
* `.anyone`, so a `.anon` address was silently accepted and then failed deep in
|
|
685
|
+
* the transport with an opaque error. This module makes `.anyone` the single
|
|
686
|
+
* accepted/routable HS TLD and rejects `.anon` up front with an actionable
|
|
687
|
+
* message (see issue #201).
|
|
688
|
+
*
|
|
689
|
+
* This is a pure, browser-safe helper (no Node built-ins) so it can be imported
|
|
690
|
+
* from any transport path.
|
|
691
|
+
*/
|
|
692
|
+
/**
|
|
693
|
+
* A `<host>.anyone` hidden-service hostname. The label is base32 (`a-z2-7`),
|
|
694
|
+
* matching the on-wire onion-style address alphabet anon uses.
|
|
695
|
+
*/
|
|
696
|
+
declare const HS_HOSTNAME_REGEX: RegExp;
|
|
697
|
+
/** Max length of an HS hostname (defensive bound against pathological input). */
|
|
698
|
+
declare const HS_HOSTNAME_MAX_LENGTH = 80;
|
|
699
|
+
/**
|
|
700
|
+
* Returns true iff `s` is a routable `.anyone` hidden-service hostname.
|
|
701
|
+
* Does NOT accept the legacy `.anon` TLD (see {@link assertRoutableHsHostname}).
|
|
702
|
+
*/
|
|
703
|
+
declare function isRoutableHsHostname(s: unknown): s is string;
|
|
704
|
+
/**
|
|
705
|
+
* Validates that `hostname` is a routable `.anyone` hidden-service address.
|
|
706
|
+
*
|
|
707
|
+
* - `<host>.anyone` → returns the hostname unchanged.
|
|
708
|
+
* - `<host>.anon` → throws with an actionable message pointing at `.anyone`
|
|
709
|
+
* (anon does NOT route `.anon`; it would silently fail in the transport).
|
|
710
|
+
* - anything else → throws a generic format error.
|
|
711
|
+
*
|
|
712
|
+
* @throws {Error} if the hostname is not a routable `.anyone` HS address.
|
|
713
|
+
*/
|
|
714
|
+
declare function assertRoutableHsHostname(hostname: unknown): string;
|
|
715
|
+
|
|
346
716
|
/**
|
|
347
717
|
* Base error class for all TOON client errors.
|
|
348
718
|
*/
|
|
@@ -679,6 +1049,8 @@ interface BtpRuntimeClientConfig {
|
|
|
679
1049
|
maxRetries?: number;
|
|
680
1050
|
/** Delay between reconnection attempts in ms (default: 1000) */
|
|
681
1051
|
retryDelay?: number;
|
|
1052
|
+
/** Custom WebSocket constructor (for SOCKS5 proxy support). */
|
|
1053
|
+
createWebSocket?: (url: string) => WebSocket;
|
|
682
1054
|
}
|
|
683
1055
|
/**
|
|
684
1056
|
* BTP transport implementing IlpClient.
|
|
@@ -722,6 +1094,14 @@ declare class BtpRuntimeClient implements IlpClient {
|
|
|
722
1094
|
data: string;
|
|
723
1095
|
timeout?: number;
|
|
724
1096
|
}, claim: Record<string, unknown>): Promise<IlpSendResult>;
|
|
1097
|
+
/**
|
|
1098
|
+
* Send a standalone `payment-channel-claim` BTP MESSAGE (no ILP packet
|
|
1099
|
+
* attached). The connector's ClaimReceiver consumes this fire-and-forget
|
|
1100
|
+
* to register cumulative claim state independently of the per-packet
|
|
1101
|
+
* forwarding path. Auto-reconnects on connection errors.
|
|
1102
|
+
*/
|
|
1103
|
+
sendClaimMessage(claim: Record<string, unknown>): Promise<void>;
|
|
1104
|
+
private _sendClaimMessageOnce;
|
|
725
1105
|
/**
|
|
726
1106
|
* Single-attempt ILP packet send. Reconnects if not connected.
|
|
727
1107
|
*/
|
|
@@ -761,36 +1141,92 @@ interface ChainSigner {
|
|
|
761
1141
|
transferredAmount: bigint;
|
|
762
1142
|
lockedAmount: bigint;
|
|
763
1143
|
locksRoot: string;
|
|
1144
|
+
/**
|
|
1145
|
+
* Counterparty settlement address the proof is bound to. Required for
|
|
1146
|
+
* Solana/Mina (folded into the canonical balance-proof message); the EVM
|
|
1147
|
+
* adapter ignores it (EIP-712 has no recipient term).
|
|
1148
|
+
*/
|
|
1149
|
+
recipient: string;
|
|
764
1150
|
metadata: ChainMetadata;
|
|
1151
|
+
/**
|
|
1152
|
+
* On-chain channel `depositTotal` (base units). When supplied (>0), a Mina
|
|
1153
|
+
* signer binds the conserved `balanceB = depositTotal − balanceA` commitment
|
|
1154
|
+
* required to settle on a funded zkApp (connector#133); EVM/Solana signers
|
|
1155
|
+
* ignore it. When omitted, a Mina signer self-resolves it from chain if it
|
|
1156
|
+
* was configured with a GraphQL URL (#223), else falls back to the legacy
|
|
1157
|
+
* `balanceB = 0` form.
|
|
1158
|
+
*/
|
|
1159
|
+
depositTotal?: bigint;
|
|
765
1160
|
}): Promise<SignedBalanceProof>;
|
|
766
1161
|
buildClaimMessage(proof: SignedBalanceProof, senderId: string): ClaimMessage;
|
|
767
1162
|
}
|
|
768
1163
|
type ClaimMessage = EVMClaimMessage | SolanaClaimMessage | MinaClaimMessage;
|
|
1164
|
+
/**
|
|
1165
|
+
* Solana payment-channel claim — wire-compatible with the connector's
|
|
1166
|
+
* `SolanaClaimMessage` (`@toon-protocol/connector` `btp/btp-claim-types.ts`).
|
|
1167
|
+
* Field names match the connector's `validateSolanaClaim` exactly:
|
|
1168
|
+
* `channelAccount` (base58 PDA), `signerPublicKey` (base58), base64 `signature`.
|
|
1169
|
+
*/
|
|
769
1170
|
interface SolanaClaimMessage {
|
|
770
1171
|
version: '1.0';
|
|
771
1172
|
blockchain: 'solana';
|
|
772
1173
|
messageId: string;
|
|
773
1174
|
timestamp: string;
|
|
774
1175
|
senderId: string;
|
|
775
|
-
|
|
1176
|
+
/** On-chain PDA account address for the payment channel (base58). */
|
|
1177
|
+
channelAccount: string;
|
|
776
1178
|
nonce: number;
|
|
1179
|
+
/** Cumulative transferred amount (string for bigint precision). */
|
|
777
1180
|
transferredAmount: string;
|
|
1181
|
+
/** Ed25519 signature over the 48-byte balance-proof message (base64). */
|
|
778
1182
|
signature: string;
|
|
779
|
-
|
|
1183
|
+
/** Base58-encoded Ed25519 public key of the signer. */
|
|
1184
|
+
signerPublicKey: string;
|
|
1185
|
+
/** Solana program id for the payment-channel program (base58). */
|
|
780
1186
|
programId: string;
|
|
781
1187
|
}
|
|
1188
|
+
/**
|
|
1189
|
+
* Mina payment-channel claim — wire-compatible with the connector's
|
|
1190
|
+
* `MinaClaimMessage` (`@toon-protocol/connector` `btp/btp-claim-types.ts`).
|
|
1191
|
+
* Field names + types match `validateMinaClaim` exactly: `zkAppAddress`
|
|
1192
|
+
* (B62-prefixed 55-char base58, the channel id), `tokenId`, `balanceCommitment`
|
|
1193
|
+
* (`Poseidon([balA,balB,salt])` decimal string), integer `nonce`, base64 `proof`,
|
|
1194
|
+
* and `salt`. `transferredAmount`/`balanceB`/`signatureB`/`network` are OPTIONAL
|
|
1195
|
+
* at validation; the apex-as-recipient single-direction claim sends party-A only.
|
|
1196
|
+
*/
|
|
782
1197
|
interface MinaClaimMessage {
|
|
783
1198
|
version: '1.0';
|
|
784
1199
|
blockchain: 'mina';
|
|
785
1200
|
messageId: string;
|
|
786
1201
|
timestamp: string;
|
|
787
1202
|
senderId: string;
|
|
788
|
-
|
|
789
|
-
nonce: number;
|
|
790
|
-
transferredAmount: string;
|
|
791
|
-
commitment: string;
|
|
792
|
-
signerAddress: string;
|
|
1203
|
+
/** Deployed payment-channel zkApp address (B62 base58) — the channel id. */
|
|
793
1204
|
zkAppAddress: string;
|
|
1205
|
+
/** Mina token id (default `'MINA'`). */
|
|
1206
|
+
tokenId: string;
|
|
1207
|
+
/** `Poseidon([balanceA, balanceB, salt]).toString()`. */
|
|
1208
|
+
balanceCommitment: string;
|
|
1209
|
+
nonce: number;
|
|
1210
|
+
/** base64-encoded JSON `{ commitment, signature: { r, s }, nonce, signerPublicKey }`. */
|
|
1211
|
+
proof: string;
|
|
1212
|
+
/** Commitment salt (decimal string). */
|
|
1213
|
+
salt: string;
|
|
1214
|
+
/** Cumulative transferred amount (optional; string for bigint precision). */
|
|
1215
|
+
transferredAmount?: string;
|
|
1216
|
+
/**
|
|
1217
|
+
* Signer's Mina public key (B62 base58) — the claiming participant.
|
|
1218
|
+
*
|
|
1219
|
+
* Surfaced top-level (in addition to being embedded in `proof`) so the
|
|
1220
|
+
* connector's `SettlementExecutor` can resolve participant keys for the
|
|
1221
|
+
* on-chain `claimFromChannel` on an externally-opened (inbound) channel. The
|
|
1222
|
+
* connector reads `latestClaim.signerPublicKey` directly (not the proof blob);
|
|
1223
|
+
* without it the Mina SDK's `claimFromChannel` throws `ACCOUNT_NOT_FOUND`
|
|
1224
|
+
* ("Participant keys not found in cache and none were supplied"). The
|
|
1225
|
+
* connector accepts this as an optional `MinaClaimMessage` field.
|
|
1226
|
+
*/
|
|
1227
|
+
signerPublicKey?: string;
|
|
1228
|
+
/** Mina network id — defaults to `devnet` connector-side when omitted. */
|
|
1229
|
+
network?: 'mainnet' | 'devnet' | 'berkeley' | 'lightnet';
|
|
794
1230
|
}
|
|
795
1231
|
|
|
796
1232
|
/**
|
|
@@ -862,17 +1298,33 @@ declare class EvmSigner {
|
|
|
862
1298
|
}
|
|
863
1299
|
|
|
864
1300
|
/**
|
|
865
|
-
* Solana signer for
|
|
1301
|
+
* Solana signer for the connector payment-channel claim path.
|
|
866
1302
|
*
|
|
867
|
-
* Signs
|
|
868
|
-
*
|
|
1303
|
+
* Signs the connector's on-chain payment-channel balance-proof message — the
|
|
1304
|
+
* raw 48-byte `channel_pda(32) || nonce(8 LE) || transferredAmount(8 LE)` (see
|
|
1305
|
+
* `@toon-protocol/connector` `SolanaPaymentChannelSDK._buildBalanceProofMessage`
|
|
1306
|
+
* + `solana-payment-channel-provider.verifyBalanceProof`). The produced 64-byte
|
|
1307
|
+
* Ed25519 signature verifies on the connector's `verifySolanaClaim` path, which
|
|
1308
|
+
* is what makes a client-issued Solana payment-channel claim (paying the apex
|
|
1309
|
+
* to write) acceptable on connector 3.9.0.
|
|
1310
|
+
*
|
|
1311
|
+
* NOTE: this is a DIFFERENT message from the Mill ↔ sender swap-claim wire
|
|
1312
|
+
* contract (`balanceProofHashSolana`, SDK `verifyEd25519Signature`). The client
|
|
1313
|
+
* here is paying a payment-channel claim to the apex, not issuing a swap claim,
|
|
1314
|
+
* so it must sign the connector's on-chain payment-channel message. `channelId`
|
|
1315
|
+
* MUST be the base58 channel PDA (produced by `OnChainChannelClient.openChannel`).
|
|
869
1316
|
*/
|
|
870
1317
|
declare class SolanaSigner implements ChainSigner {
|
|
871
1318
|
readonly chainType: "solana";
|
|
1319
|
+
/** 32-byte Ed25519 seed. */
|
|
872
1320
|
private readonly privateKey;
|
|
873
|
-
private publicKey?;
|
|
874
1321
|
private pubkeyBase58Cache?;
|
|
875
|
-
|
|
1322
|
+
/**
|
|
1323
|
+
* @param privateKey - 32-byte Ed25519 seed (e.g. `identity.solana.secretKey.slice(0, 32)`).
|
|
1324
|
+
* @param publicKeyBase58 - Optional base58 public key (e.g. `identity.solana.publicKey`).
|
|
1325
|
+
* When omitted it is derived lazily from `privateKey`.
|
|
1326
|
+
*/
|
|
1327
|
+
constructor(privateKey: Uint8Array, publicKeyBase58?: string);
|
|
876
1328
|
private ensurePublicKey;
|
|
877
1329
|
get signerIdentifier(): string;
|
|
878
1330
|
signBalanceProof(params: {
|
|
@@ -881,44 +1333,170 @@ declare class SolanaSigner implements ChainSigner {
|
|
|
881
1333
|
transferredAmount: bigint;
|
|
882
1334
|
lockedAmount: bigint;
|
|
883
1335
|
locksRoot: string;
|
|
1336
|
+
recipient: string;
|
|
884
1337
|
metadata: ChainMetadata;
|
|
885
1338
|
}): Promise<SignedBalanceProof>;
|
|
886
1339
|
buildClaimMessage(proof: SignedBalanceProof, senderId: string): ClaimMessage;
|
|
887
1340
|
}
|
|
888
1341
|
|
|
1342
|
+
/** Reads a channel zkApp's on-chain `depositTotal` (base units). */
|
|
1343
|
+
type MinaDepositReader = (zkAppAddress: string) => Promise<bigint>;
|
|
1344
|
+
/** Optional `MinaSigner` wiring for on-chain `depositTotal` resolution. */
|
|
1345
|
+
interface MinaSignerOptions {
|
|
1346
|
+
/**
|
|
1347
|
+
* Mina GraphQL URL used to read the channel's on-chain `depositTotal` when a
|
|
1348
|
+
* caller doesn't supply it to `signBalanceProof`. Enables conserved
|
|
1349
|
+
* `balanceB = depositTotal − balanceA` claims (settleable on funded zkApps).
|
|
1350
|
+
*/
|
|
1351
|
+
graphqlUrl?: string;
|
|
1352
|
+
/** Inject a deposit reader (tests / custom transport). Overrides `graphqlUrl`. */
|
|
1353
|
+
depositReader?: MinaDepositReader;
|
|
1354
|
+
}
|
|
889
1355
|
/**
|
|
890
|
-
* Mina signer for
|
|
1356
|
+
* Mina (Pallas) signer for the connector payment-channel claim path.
|
|
1357
|
+
*
|
|
1358
|
+
* Produces the connector 3.9.0 `MinaClaimMessage` contract — `{ zkAppAddress,
|
|
1359
|
+
* tokenId, balanceCommitment, proof (base64), salt, nonce }` — by reproducing
|
|
1360
|
+
* `MinaPaymentChannelSDK.signBalanceProof` exactly (via
|
|
1361
|
+
* {@link buildMinaPaymentChannelProof}):
|
|
1362
|
+
*
|
|
1363
|
+
* commitment = Poseidon([Field(balanceA), Field(0), Field(salt)])
|
|
1364
|
+
* channelHashField = Poseidon([participantA.x, participantB.x, 0]) (see below)
|
|
1365
|
+
* proof = base64(JSON{ commitment, signature: { r, s }, nonce, signerPublicKey })
|
|
1366
|
+
*
|
|
1367
|
+
* with the Schnorr signature computed over `[commitment, Field(nonce),
|
|
1368
|
+
* channelHashField]` using the Mina `'devnet'` network id (matching o1js's
|
|
1369
|
+
* hardcoded `Signature.create` prefix). Verified field-by-field against the
|
|
1370
|
+
* connector's o1js `Signature.fromJSON({r,s}).verify` (see the package tests).
|
|
1371
|
+
*
|
|
1372
|
+
* `channelHashField` is the ON-CHAIN participant form
|
|
1373
|
+
* (`Poseidon([client.x, apex.x, 0])`, participantA=client, participantB=apex)
|
|
1374
|
+
* whenever the apex's Mina pubkey is known (the negotiated `recipient`), so the
|
|
1375
|
+
* claim can SETTLE on-chain via the zkApp's `claimFromChannel` (which only
|
|
1376
|
+
* verifies the participant form). When the apex pubkey is unavailable the signer
|
|
1377
|
+
* falls back to the legacy zkApp-x form (`Poseidon([zkApp.x])`); the connector's
|
|
1378
|
+
* off-chain `verifyBalanceProof` accepts EITHER, so off-chain store/FULFILL works
|
|
1379
|
+
* in both cases — only on-chain settle requires the participant form.
|
|
1380
|
+
*
|
|
1381
|
+
* NOTE: this is a DIFFERENT message + format from the Mill ↔ sender swap-claim
|
|
1382
|
+
* wire contract (`balanceProofFieldsMina` in `@toon-protocol/core`, verified by
|
|
1383
|
+
* the SDK's `verifyMinaSignature`). The client here pays a payment-channel claim
|
|
1384
|
+
* to the apex, so it signs the connector's on-chain payment-channel scheme; the
|
|
1385
|
+
* swap-format hash is left untouched (mirrors the Solana #105 separation).
|
|
891
1386
|
*
|
|
892
|
-
*
|
|
893
|
-
*
|
|
1387
|
+
* `channelId` MUST be the deployed payment-channel zkApp B62 address (the same
|
|
1388
|
+
* address the apex's Mina provider resolves on-chain via `getChannelState`),
|
|
1389
|
+
* which is what `OnChainChannelClient.openMinaChannel` returns.
|
|
1390
|
+
*
|
|
1391
|
+
* `mina-signer` is an OPTIONAL dependency: its crypto (Poseidon, Pallas Schnorr,
|
|
1392
|
+
* the base58 signature codec) is loaded dynamically so the client builds and runs
|
|
1393
|
+
* for non-Mina users without it installed, and WITHOUT pulling the o1js WASM
|
|
1394
|
+
* circuit runtime.
|
|
894
1395
|
*/
|
|
895
1396
|
declare class MinaSigner implements ChainSigner {
|
|
896
1397
|
readonly chainType: "mina";
|
|
897
|
-
private
|
|
898
|
-
private
|
|
899
|
-
|
|
1398
|
+
/** Big-endian hex scalar (or already-`EK…` base58) Mina private key. */
|
|
1399
|
+
private readonly privateKey;
|
|
1400
|
+
private publicKeyBase58?;
|
|
1401
|
+
private readonly depositReader?;
|
|
1402
|
+
/** Per-zkApp `depositTotal` cache (deposits are rare; the connector re-reads). */
|
|
1403
|
+
private readonly depositCache;
|
|
1404
|
+
/**
|
|
1405
|
+
* @param privateKey - Mina private key as big-endian hex scalar (the form
|
|
1406
|
+
* `deriveFullIdentity()` emits, `identity.mina.privateKey`) or an `EK…`
|
|
1407
|
+
* base58 key. Converted to the base58check form mina-signer requires.
|
|
1408
|
+
* @param publicKeyBase58 - Optional base58 public key (e.g.
|
|
1409
|
+
* `identity.mina.publicKey`). When omitted it is derived during signing.
|
|
1410
|
+
* @param options - Optional on-chain `depositTotal` resolution (graphqlUrl or
|
|
1411
|
+
* an injected reader) so claims conserve balances on funded zkApps.
|
|
1412
|
+
*/
|
|
1413
|
+
constructor(privateKey: string, publicKeyBase58?: string, options?: MinaSignerOptions);
|
|
1414
|
+
/**
|
|
1415
|
+
* Resolve the channel's on-chain `depositTotal`, caching per zkApp. Returns
|
|
1416
|
+
* `undefined` when no reader is configured or the read fails — callers then
|
|
1417
|
+
* fall back to the legacy `balanceB = 0` commitment.
|
|
1418
|
+
*/
|
|
1419
|
+
private resolveDepositTotal;
|
|
900
1420
|
get signerIdentifier(): string;
|
|
901
|
-
private
|
|
1421
|
+
/** Derive this signer's B62 public key from its (base58) private key. */
|
|
1422
|
+
private deriveOwnPublicKey;
|
|
902
1423
|
signBalanceProof(params: {
|
|
903
1424
|
channelId: string;
|
|
904
1425
|
nonce: number;
|
|
905
1426
|
transferredAmount: bigint;
|
|
906
1427
|
lockedAmount: bigint;
|
|
907
1428
|
locksRoot: string;
|
|
1429
|
+
recipient: string;
|
|
908
1430
|
metadata: ChainMetadata;
|
|
1431
|
+
/**
|
|
1432
|
+
* On-chain channel `depositTotal`. When provided (>0), the signed commitment
|
|
1433
|
+
* binds `balanceB = depositTotal − balanceA` (the funder's remaining
|
|
1434
|
+
* balance), matching the connector's claimFromChannel reconstruction
|
|
1435
|
+
* (toon-protocol/connector#133) and the on-chain circuit's
|
|
1436
|
+
* `balanceA + balanceB == depositTotal` invariant. Omitted/0 keeps the
|
|
1437
|
+
* legacy `balanceB = 0` form (off-chain-store-only, non-settleable).
|
|
1438
|
+
*/
|
|
1439
|
+
depositTotal?: bigint;
|
|
909
1440
|
}): Promise<SignedBalanceProof>;
|
|
910
1441
|
buildClaimMessage(proof: SignedBalanceProof, senderId: string): ClaimMessage;
|
|
911
1442
|
}
|
|
912
1443
|
|
|
913
1444
|
interface SolanaChannelConfig {
|
|
914
1445
|
rpcUrl: string;
|
|
1446
|
+
/**
|
|
1447
|
+
* Ed25519 keypair material. Accepts either a 32-byte seed or a 64-byte
|
|
1448
|
+
* `secretKey` (seed || pubkey, as produced by `deriveFullIdentity`). The first
|
|
1449
|
+
* 32 bytes are the signing seed; the public key is derived from it.
|
|
1450
|
+
*/
|
|
915
1451
|
keypair: Uint8Array;
|
|
916
1452
|
programId: string;
|
|
1453
|
+
/**
|
|
1454
|
+
* SPL token mint (base58) for PDA derivation. Optional — the per-channel
|
|
1455
|
+
* negotiated token (`OpenChannelParams.token`) takes precedence when present.
|
|
1456
|
+
*/
|
|
1457
|
+
tokenMint?: string;
|
|
1458
|
+
/**
|
|
1459
|
+
* Challenge-period duration in seconds for `initialize_channel`. Defaults to
|
|
1460
|
+
* `OpenChannelParams.settlementTimeout` or 86400.
|
|
1461
|
+
*/
|
|
1462
|
+
challengeDuration?: number;
|
|
1463
|
+
/**
|
|
1464
|
+
* Optional deposit amount (base units, string) + the payer's funded SPL token
|
|
1465
|
+
* account (ATA, base58). When omitted, the channel is opened (initialized)
|
|
1466
|
+
* without an on-chain deposit — the connector accepts the claim on channel
|
|
1467
|
+
* `opened` status + participant membership; deposit is only consumed at
|
|
1468
|
+
* on-chain claim/settle time.
|
|
1469
|
+
*/
|
|
1470
|
+
deposit?: {
|
|
1471
|
+
amount: string;
|
|
1472
|
+
payerTokenAccount: string;
|
|
1473
|
+
};
|
|
917
1474
|
}
|
|
918
1475
|
interface MinaChannelConfig {
|
|
919
1476
|
graphqlUrl: string;
|
|
920
1477
|
privateKey: string;
|
|
921
1478
|
zkAppAddress: string;
|
|
1479
|
+
/**
|
|
1480
|
+
* Channel settlement timeout in slots for `initializeChannel`. Defaults to
|
|
1481
|
+
* `OpenChannelParams.settlementTimeout` or 86400.
|
|
1482
|
+
*/
|
|
1483
|
+
challengeDuration?: number;
|
|
1484
|
+
/**
|
|
1485
|
+
* Mina token id field (decimal string) for `initializeChannel`. Default '1'
|
|
1486
|
+
* (native MINA). The connector reads this only as on-chain channel metadata.
|
|
1487
|
+
*/
|
|
1488
|
+
tokenId?: string;
|
|
1489
|
+
/**
|
|
1490
|
+
* Optional on-chain deposit (base units, string) submitted after the channel
|
|
1491
|
+
* is initialized. When omitted, the channel is opened (OPEN state) without a
|
|
1492
|
+
* deposit — the connector accepts the claim on `opened` status; deposit is
|
|
1493
|
+
* only consumed at on-chain settle time.
|
|
1494
|
+
*/
|
|
1495
|
+
deposit?: {
|
|
1496
|
+
amount: string;
|
|
1497
|
+
};
|
|
1498
|
+
/** Mina network id for the account/Schnorr prefix. Default 'devnet'. */
|
|
1499
|
+
networkId?: 'devnet' | 'mainnet';
|
|
922
1500
|
}
|
|
923
1501
|
interface OnChainChannelClientConfig {
|
|
924
1502
|
evmSigner: EvmSigner;
|
|
@@ -935,10 +1513,29 @@ interface OnChainChannelClientConfig {
|
|
|
935
1513
|
declare class OnChainChannelClient implements ConnectorChannelClient {
|
|
936
1514
|
private readonly evmSigner;
|
|
937
1515
|
private readonly chainRpcUrls;
|
|
938
|
-
private
|
|
939
|
-
private
|
|
1516
|
+
private solanaConfig?;
|
|
1517
|
+
private minaConfig?;
|
|
940
1518
|
private readonly channelContext;
|
|
941
1519
|
constructor(config: OnChainChannelClientConfig);
|
|
1520
|
+
/**
|
|
1521
|
+
* Late-binds the Solana channel config.
|
|
1522
|
+
*
|
|
1523
|
+
* `ToonClient.start()` derives the Solana Ed25519 keypair from the client's
|
|
1524
|
+
* mnemonic asynchronously (after this client is constructed), so the keypair
|
|
1525
|
+
* is injected here rather than at construction. Same keypair as the
|
|
1526
|
+
* registered Solana signer — guarantees the channel-open key and the
|
|
1527
|
+
* claim-signing key match.
|
|
1528
|
+
*/
|
|
1529
|
+
setSolanaConfig(config: SolanaChannelConfig): void;
|
|
1530
|
+
/**
|
|
1531
|
+
* Late-binds the Mina channel config.
|
|
1532
|
+
*
|
|
1533
|
+
* Parallel to `setSolanaConfig`: `ToonClient.start()` derives the Mina private
|
|
1534
|
+
* key from the client's mnemonic asynchronously (after this client is
|
|
1535
|
+
* constructed), so the key is injected here rather than at construction. Same
|
|
1536
|
+
* key as the registered Mina signer.
|
|
1537
|
+
*/
|
|
1538
|
+
setMinaConfig(config: MinaChannelConfig): void;
|
|
942
1539
|
/**
|
|
943
1540
|
* Parse chain identifier to extract chainId.
|
|
944
1541
|
* Format: "evm:{network}:{chainId}" e.g., "evm:anvil:31337"
|
|
@@ -958,12 +1555,48 @@ declare class OnChainChannelClient implements ConnectorChannelClient {
|
|
|
958
1555
|
*/
|
|
959
1556
|
openChannel(params: OpenChannelParams): Promise<OpenChannelResult>;
|
|
960
1557
|
/**
|
|
961
|
-
* Opens a Solana payment channel
|
|
1558
|
+
* Opens a REAL on-chain Solana payment channel.
|
|
1559
|
+
*
|
|
1560
|
+
* Derives the connector-parity channel PDA
|
|
1561
|
+
* (`[b"channel", min_pubkey, max_pubkey, token_mint]`), submits the
|
|
1562
|
+
* `initialize_channel` instruction (+ optional `deposit`) to the deployed
|
|
1563
|
+
* payment-channel program, and returns the base58 PDA as the channel id. That
|
|
1564
|
+
* PDA is what the claim carries as `channelAccount`, and the on-chain channel
|
|
1565
|
+
* is what the connector's `verifySolanaClaim` reads via
|
|
1566
|
+
* `provider.getChannelState` before accepting the claim.
|
|
1567
|
+
*
|
|
1568
|
+
* Mirrors `openEvmChannel`'s open(+deposit) structure. Idempotent: if the
|
|
1569
|
+
* channel account already exists on-chain, returns its PDA without
|
|
1570
|
+
* re-initializing.
|
|
962
1571
|
*/
|
|
963
1572
|
private openSolanaChannel;
|
|
964
1573
|
/**
|
|
965
|
-
* Opens a Mina payment channel
|
|
966
|
-
*
|
|
1574
|
+
* Opens a REAL on-chain Mina payment channel on the deployed `PaymentChannel`
|
|
1575
|
+
* zkApp.
|
|
1576
|
+
*
|
|
1577
|
+
* The zkApp is deployed out-of-band (the operator/e2e harness deploys it
|
|
1578
|
+
* deterministically and advertises its B62 address). This client then calls
|
|
1579
|
+
* `initializeChannel` on that zkApp so its on-chain `channelState` becomes
|
|
1580
|
+
* `OPEN` — which is what the connector's `MinaPaymentChannelSDK.getChannelState`
|
|
1581
|
+
* reads to return status `'opened'` (claim verification otherwise fails with
|
|
1582
|
+
* `mina_claim_verification_failed`). The deployed zkApp address IS the channel
|
|
1583
|
+
* id: `MinaClaimMessage.zkAppAddress` is both the claim's channel identifier
|
|
1584
|
+
* AND the channel-hash preimage the off-chain proof binds to (see
|
|
1585
|
+
* `mina-payment-channel.ts`), so the channel-open id and the claim's channel id
|
|
1586
|
+
* are guaranteed identical.
|
|
1587
|
+
*
|
|
1588
|
+
* This is the Mina analog of `openSolanaChannel` (connector#105): the client
|
|
1589
|
+
* opens its own per-channel on-chain state (initialize + optional deposit). The
|
|
1590
|
+
* heavyweight o1js + `@toon-protocol/mina-zkapp` proof work is lazily imported
|
|
1591
|
+
* inside `openMinaChannelOnChain` so npm consumers who never open a Mina
|
|
1592
|
+
* channel don't pay the o1js cost.
|
|
1593
|
+
*
|
|
1594
|
+
* Idempotent: if the on-chain channel is already `OPEN`, the opener returns
|
|
1595
|
+
* without re-initializing.
|
|
1596
|
+
*
|
|
1597
|
+
* NOTE: full on-chain Mina SETTLE remains gated by the connector-side
|
|
1598
|
+
* settlement-executor (the same blocker that stops the Solana SETTLE); reaching
|
|
1599
|
+
* `opened` + a stored claim is parity with Solana.
|
|
967
1600
|
*/
|
|
968
1601
|
private openMinaChannel;
|
|
969
1602
|
/**
|
|
@@ -1062,6 +1695,8 @@ declare class ChannelManager {
|
|
|
1062
1695
|
chainId: number;
|
|
1063
1696
|
tokenNetworkAddress: string;
|
|
1064
1697
|
tokenAddress?: string;
|
|
1698
|
+
recipient?: string;
|
|
1699
|
+
depositTotal?: bigint;
|
|
1065
1700
|
}, initialNonce?: number, initialAmount?: bigint): void;
|
|
1066
1701
|
/**
|
|
1067
1702
|
* Signs a balance proof for the given channel.
|
|
@@ -1093,6 +1728,26 @@ declare class ChannelManager {
|
|
|
1093
1728
|
isTracking(channelId: string): boolean;
|
|
1094
1729
|
}
|
|
1095
1730
|
|
|
1731
|
+
/**
|
|
1732
|
+
* Read a Mina payment-channel zkApp's on-chain `depositTotal` via a plain
|
|
1733
|
+
* GraphQL query (no o1js / WASM). Used by {@link MinaSigner} to bind the
|
|
1734
|
+
* conserved `balanceB = depositTotal − balanceA` commitment that a FUNDED zkApp
|
|
1735
|
+
* requires (connector#133); without it the connector's `claimFromChannel`
|
|
1736
|
+
* verification rejects the claim with `F06 - Invalid zk-SNARK proof on claim`.
|
|
1737
|
+
*
|
|
1738
|
+
* The `PaymentChannel` zkApp app-state field order is
|
|
1739
|
+
* `[channelHash, balanceCommitment, nonceField, channelState, depositTotal, …]`
|
|
1740
|
+
* (see `mina-channel-open.ts`), so `depositTotal` is `zkappState[4]`.
|
|
1741
|
+
*/
|
|
1742
|
+
/**
|
|
1743
|
+
* Query `account(publicKey).zkappState` and return the channel's `depositTotal`
|
|
1744
|
+
* (base units). Throws when the account/state is unavailable so callers can fall
|
|
1745
|
+
* back to the legacy `balanceB = 0` behavior.
|
|
1746
|
+
*
|
|
1747
|
+
* @param fetchImpl - injectable for tests; defaults to global `fetch`.
|
|
1748
|
+
*/
|
|
1749
|
+
declare function readMinaDepositTotal(graphqlUrl: string, zkAppAddress: string, fetchImpl?: typeof fetch): Promise<bigint>;
|
|
1750
|
+
|
|
1096
1751
|
/**
|
|
1097
1752
|
* Configuration options for retry behavior with exponential backoff.
|
|
1098
1753
|
*/
|
|
@@ -1130,6 +1785,95 @@ interface RetryOptions {
|
|
|
1130
1785
|
*/
|
|
1131
1786
|
declare function withRetry<T>(operation: () => Promise<T>, options: RetryOptions): Promise<T>;
|
|
1132
1787
|
|
|
1788
|
+
/**
|
|
1789
|
+
* Self-managed `anon` (anyone-protocol / ATOR) SOCKS5h proxy (Node.js only).
|
|
1790
|
+
*
|
|
1791
|
+
* Lets a `@toon-protocol/client` consumer reach a `.anyone` hidden service with
|
|
1792
|
+
* ZERO manual proxy setup: the SDK downloads, verifies, extracts, and spawns its
|
|
1793
|
+
* own `anon` daemon, waits for it to bootstrap + bind a loopback SOCKS5 port, and
|
|
1794
|
+
* hands back a `socks5h://127.0.0.1:<port>` URL. The proven reference is the
|
|
1795
|
+
* server-side pod entrypoint `docker/src/entrypoint-toon-client.ts` (`writeTorrc`,
|
|
1796
|
+
* `spawnAnon`, `waitForAnonSocks`, `tcpProbe`); this module ports that daemon
|
|
1797
|
+
* logic into the client package and adds the binary download + checksum gate so it
|
|
1798
|
+
* works without an OS-level `anon` install.
|
|
1799
|
+
*
|
|
1800
|
+
* BROWSER SAFETY: this module is dynamically imported only from `resolveTransport`
|
|
1801
|
+
* when a managed proxy is actually needed (Node-only path). Every Node built-in is
|
|
1802
|
+
* pulled in lazily via the ESM-safe `require(...)` built off `import.meta.url`
|
|
1803
|
+
* (the same pattern as `socks5.ts`), so a browser bundler that statically analyses
|
|
1804
|
+
* the package never reaches `node:child_process`/`node:fs`/`node:https`/`node:net`.
|
|
1805
|
+
*/
|
|
1806
|
+
/**
|
|
1807
|
+
* Pinned `anon` release. "beta" is the channel slug embedded in the per-platform
|
|
1808
|
+
* zip asset names (e.g. `anon-beta-macos-arm64.zip`).
|
|
1809
|
+
*/
|
|
1810
|
+
declare const ANON_VERSION = "v0.4.10.0-beta";
|
|
1811
|
+
/**
|
|
1812
|
+
* Per-platform `anon` zip asset descriptor. `sha256` is the pinned checksum of the
|
|
1813
|
+
* release zip. All supported platforms are pinned (issue #204); the type stays
|
|
1814
|
+
* `string | null` and the download gate still defensively refuses a `null` entry,
|
|
1815
|
+
* so adding a new (not-yet-hashed) platform fails closed rather than skipping
|
|
1816
|
+
* verification.
|
|
1817
|
+
*/
|
|
1818
|
+
interface AnonAsset {
|
|
1819
|
+
/** Release asset file name, e.g. `anon-beta-macos-arm64.zip`. */
|
|
1820
|
+
assetName: string;
|
|
1821
|
+
/** Pinned sha256 of the zip, or null when not yet pinned (issue #204). */
|
|
1822
|
+
sha256: string | null;
|
|
1823
|
+
}
|
|
1824
|
+
/**
|
|
1825
|
+
* Platform → asset map keyed by `${os.platform()}-${os.arch()}` (Node values).
|
|
1826
|
+
* Only macOS + Linux on x64/arm64 are supported (the `anon` releases that ship a
|
|
1827
|
+
* SOCKS-capable binary). Windows is intentionally absent.
|
|
1828
|
+
*
|
|
1829
|
+
* Pinned checksums (issue #204): all four supported platforms are pinned to the
|
|
1830
|
+
* sha256 of the `v0.4.10.0-beta` release zips (downloaded + hashed; the
|
|
1831
|
+
* darwin-arm64 value matches the previously-verified manual flow).
|
|
1832
|
+
*/
|
|
1833
|
+
declare const ANON_ASSETS: Record<string, AnonAsset>;
|
|
1834
|
+
/**
|
|
1835
|
+
* Resolves the `anon` release asset for a platform/arch pair (Node
|
|
1836
|
+
* `os.platform()` / `os.arch()` values).
|
|
1837
|
+
*
|
|
1838
|
+
* @throws If the platform/arch combination has no known `anon` asset.
|
|
1839
|
+
*/
|
|
1840
|
+
declare function selectAnonAsset(platform: string, arch: string): AnonAsset;
|
|
1841
|
+
/**
|
|
1842
|
+
* Handle returned by `startManagedAnonProxy`. `socksProxy` is the loopback
|
|
1843
|
+
* `socks5h://` URL to wire into `transport: { type: 'socks5', socksProxy }`.
|
|
1844
|
+
* `stop()` SIGTERMs the daemon and is idempotent.
|
|
1845
|
+
*/
|
|
1846
|
+
interface ManagedAnonProxy {
|
|
1847
|
+
socksProxy: string;
|
|
1848
|
+
stop(): Promise<void>;
|
|
1849
|
+
}
|
|
1850
|
+
/**
|
|
1851
|
+
* Options for `startManagedAnonProxy`. All have sensible defaults; tests inject
|
|
1852
|
+
* the deps to avoid real downloads/spawns.
|
|
1853
|
+
*/
|
|
1854
|
+
interface StartManagedAnonProxyOptions {
|
|
1855
|
+
/** Cache dir for the binary + torrc + data. Default: {@link defaultCacheDir}. */
|
|
1856
|
+
cacheDir?: string;
|
|
1857
|
+
/** Loopback SOCKS5 port. Default 9050. */
|
|
1858
|
+
socksPort?: number;
|
|
1859
|
+
/** Bootstrap deadline in ms. Default 180_000. */
|
|
1860
|
+
bootstrapTimeoutMs?: number;
|
|
1861
|
+
/** Logger. Default: no-op. */
|
|
1862
|
+
log?: (msg: string) => void;
|
|
1863
|
+
/** os.platform() override (tests). */
|
|
1864
|
+
platform?: string;
|
|
1865
|
+
/** os.arch() override (tests). */
|
|
1866
|
+
arch?: string;
|
|
1867
|
+
}
|
|
1868
|
+
/**
|
|
1869
|
+
* Downloads (if needed) + spawns a managed `anon` daemon and waits for its SOCKS5
|
|
1870
|
+
* port to bind. Returns a {@link ManagedAnonProxy} whose `socksProxy` is ready for
|
|
1871
|
+
* `transport: { type: 'socks5', socksProxy }`.
|
|
1872
|
+
*
|
|
1873
|
+
* @throws If the platform is unsupported, the checksum fails, or anon never binds.
|
|
1874
|
+
*/
|
|
1875
|
+
declare function startManagedAnonProxy(options?: StartManagedAnonProxyOptions): Promise<ManagedAnonProxy>;
|
|
1876
|
+
|
|
1133
1877
|
/**
|
|
1134
1878
|
* Settlement info produced by buildSettlementInfo().
|
|
1135
1879
|
* Extends the core SettlementConfig shape with ilpAddress for client use.
|
|
@@ -1141,6 +1885,27 @@ interface ClientSettlementInfo {
|
|
|
1141
1885
|
preferredTokens?: Record<string, string>;
|
|
1142
1886
|
tokenNetworks?: Record<string, string>;
|
|
1143
1887
|
}
|
|
1888
|
+
/**
|
|
1889
|
+
* Applies named-network preset defaults to a client config.
|
|
1890
|
+
*
|
|
1891
|
+
* When `config.network` is set and != `'custom'`, the settlement-related
|
|
1892
|
+
* fields are defaulted from the shared core presets (`resolveClientNetwork`):
|
|
1893
|
+
* RPC/GraphQL URLs, supported chain identifiers, preferred tokens, EVM
|
|
1894
|
+
* TokenNetwork addresses, and the Solana/Mina channel params. Any explicit
|
|
1895
|
+
* per-chain field on `config` OVERRIDES the preset (explicit always wins).
|
|
1896
|
+
*
|
|
1897
|
+
* `'custom'` and the unset case both pass `config` through untouched, keeping
|
|
1898
|
+
* the fully-manual path and full backward compatibility.
|
|
1899
|
+
*
|
|
1900
|
+
* @returns A shallow copy with preset defaults merged in (never mutates input).
|
|
1901
|
+
*/
|
|
1902
|
+
declare function applyNetworkPresets(config: ToonClientConfig): ToonClientConfig;
|
|
1903
|
+
/**
|
|
1904
|
+
* Returns per-chain settlement readiness for the configured `network` tier,
|
|
1905
|
+
* mirroring the townhouse node's status. Returns `undefined` when `network` is
|
|
1906
|
+
* unset or `'custom'` (no preset tier to report on).
|
|
1907
|
+
*/
|
|
1908
|
+
declare function getNetworkStatus(config: ToonClientConfig): NetworkFamilyStatus | undefined;
|
|
1144
1909
|
/**
|
|
1145
1910
|
* Validates ToonClient configuration.
|
|
1146
1911
|
*
|
|
@@ -1153,10 +1918,30 @@ declare function validateConfig(config: ToonClientConfig): void;
|
|
|
1153
1918
|
* The resolved config type after defaults are applied.
|
|
1154
1919
|
* secretKey is guaranteed to be present (auto-generated if omitted).
|
|
1155
1920
|
*/
|
|
1156
|
-
type ResolvedConfig = Required<Omit<ToonClientConfig, 'connector' | 'evmPrivateKey' | 'supportedChains' | 'settlementAddresses' | 'preferredTokens' | 'tokenNetworks' | 'btpUrl' | 'btpAuthToken' | 'btpPeerId' | 'chainRpcUrls' | 'initialDeposit' | 'settlementTimeout' | 'channelStorePath' | 'knownPeers' | 'destinationAddress'>> & {
|
|
1921
|
+
type ResolvedConfig = Required<Omit<ToonClientConfig, 'connector' | 'mnemonic' | 'mnemonicAccountIndex' | 'evmPrivateKey' | 'network' | 'supportedChains' | 'settlementAddresses' | 'preferredTokens' | 'tokenNetworks' | 'btpUrl' | 'btpAuthToken' | 'btpPeerId' | 'chainRpcUrls' | 'initialDeposit' | 'settlementTimeout' | 'solanaChannel' | 'minaChannel' | 'channelStorePath' | 'knownPeers' | 'destinationAddress' | 'transport' | 'managedAnonProxy' | 'managedAnonSocksPort'>> & {
|
|
1157
1922
|
connector?: unknown;
|
|
1158
1923
|
/** Always present after applyDefaults() — derived from secretKey if not explicitly provided */
|
|
1159
1924
|
evmPrivateKey: string | Uint8Array;
|
|
1925
|
+
/**
|
|
1926
|
+
* BIP-39 phrase retained so `ToonClient.start()` can derive the Solana/Mina
|
|
1927
|
+
* keys asynchronously and register the corresponding signers. The Nostr/EVM
|
|
1928
|
+
* keys are already resolved synchronously into `secretKey`/`evmPrivateKey`.
|
|
1929
|
+
*/
|
|
1930
|
+
mnemonic?: string;
|
|
1931
|
+
/**
|
|
1932
|
+
* BIP-44 account index for mnemonic-based derivation (defaults to 0).
|
|
1933
|
+
* Retained so `ToonClient.start()` derives the Solana/Mina signers at the
|
|
1934
|
+
* same index as the synchronously-resolved Nostr/EVM keys.
|
|
1935
|
+
*/
|
|
1936
|
+
mnemonicAccountIndex?: number;
|
|
1937
|
+
/** Transport privacy config (optional — defaults to direct). */
|
|
1938
|
+
transport?: ClientTransportConfig;
|
|
1939
|
+
/** Named network tier, retained for `getNetworkStatus()`. */
|
|
1940
|
+
network?: ToonClientConfig['network'];
|
|
1941
|
+
/** Self-managed `anon` SOCKS5h proxy opt-out (default auto). */
|
|
1942
|
+
managedAnonProxy?: boolean;
|
|
1943
|
+
/** Loopback SOCKS port for the managed `anon` daemon (default 9050). */
|
|
1944
|
+
managedAnonSocksPort?: number;
|
|
1160
1945
|
supportedChains?: string[];
|
|
1161
1946
|
settlementAddresses?: Record<string, string>;
|
|
1162
1947
|
preferredTokens?: Record<string, string>;
|
|
@@ -1167,6 +1952,8 @@ type ResolvedConfig = Required<Omit<ToonClientConfig, 'connector' | 'evmPrivateK
|
|
|
1167
1952
|
chainRpcUrls?: Record<string, string>;
|
|
1168
1953
|
initialDeposit?: string;
|
|
1169
1954
|
settlementTimeout?: number;
|
|
1955
|
+
solanaChannel?: ToonClientConfig['solanaChannel'];
|
|
1956
|
+
minaChannel?: ToonClientConfig['minaChannel'];
|
|
1170
1957
|
channelStorePath?: string;
|
|
1171
1958
|
knownPeers?: {
|
|
1172
1959
|
pubkey: string;
|
|
@@ -1180,12 +1967,509 @@ type ResolvedConfig = Required<Omit<ToonClientConfig, 'connector' | 'evmPrivateK
|
|
|
1180
1967
|
* Auto-generates a Nostr keypair when secretKey is omitted.
|
|
1181
1968
|
* Derives btpUrl from connectorUrl when not provided.
|
|
1182
1969
|
*/
|
|
1183
|
-
declare function applyDefaults(
|
|
1970
|
+
declare function applyDefaults(rawConfig: ToonClientConfig): ResolvedConfig;
|
|
1184
1971
|
/**
|
|
1185
1972
|
* Builds SettlementConfig from client config.
|
|
1186
1973
|
* Returns undefined if no settlement-related config is present.
|
|
1187
1974
|
*/
|
|
1188
|
-
declare function buildSettlementInfo(
|
|
1975
|
+
declare function buildSettlementInfo(rawConfig: ToonClientConfig): ClientSettlementInfo | undefined;
|
|
1976
|
+
|
|
1977
|
+
/**
|
|
1978
|
+
* Pet DVM Client-Side Types
|
|
1979
|
+
*
|
|
1980
|
+
* Locally defined types for pet DVM interaction utilities.
|
|
1981
|
+
* These mirror server-side types but do NOT import from @toon-protocol/pet-dvm,
|
|
1982
|
+
* @toon-protocol/pet-circuit, or @toon-protocol/memvid-node.
|
|
1983
|
+
*
|
|
1984
|
+
* @module pet/types
|
|
1985
|
+
*/
|
|
1986
|
+
/** Plain-number stat values (all clamped to [1, 100]) */
|
|
1987
|
+
interface StatValues {
|
|
1988
|
+
hunger: number;
|
|
1989
|
+
happiness: number;
|
|
1990
|
+
health: number;
|
|
1991
|
+
hygiene: number;
|
|
1992
|
+
energy: number;
|
|
1993
|
+
}
|
|
1994
|
+
/** Metadata for a pet DVM provider discovered via Kind 10035 events */
|
|
1995
|
+
interface PetDvmProvider {
|
|
1996
|
+
/** ILP address of the provider's connector */
|
|
1997
|
+
ilpAddress: string;
|
|
1998
|
+
/** Per-interaction cost from skill.pricing['5900'] */
|
|
1999
|
+
pricing: string;
|
|
2000
|
+
/** Provider's Nostr pubkey (cryptographically bound from event.pubkey) */
|
|
2001
|
+
pubkey: string;
|
|
2002
|
+
/** Feature list from skill.features */
|
|
2003
|
+
features: string[];
|
|
2004
|
+
}
|
|
2005
|
+
/** Parameters for building a Kind 5900 pet interaction request */
|
|
2006
|
+
interface PetInteractionRequestParams {
|
|
2007
|
+
/** Blobbi identifier (non-empty string) */
|
|
2008
|
+
blobbiId: string;
|
|
2009
|
+
/** Action type (0-10, maps to Feed/Play/Clean/etc.) */
|
|
2010
|
+
actionType: number;
|
|
2011
|
+
/** Item identifier (>= 0) */
|
|
2012
|
+
itemId: number;
|
|
2013
|
+
/** Token cost for this interaction (>= 0) */
|
|
2014
|
+
tokenCost: number;
|
|
2015
|
+
/** Whether the pet is currently sleeping */
|
|
2016
|
+
isSleeping: boolean;
|
|
2017
|
+
}
|
|
2018
|
+
/** Unsigned Nostr event structure compatible with nostr-tools finalizeEvent */
|
|
2019
|
+
interface UnsignedNostrEvent {
|
|
2020
|
+
kind: number;
|
|
2021
|
+
created_at: number;
|
|
2022
|
+
tags: string[][];
|
|
2023
|
+
content: string;
|
|
2024
|
+
}
|
|
2025
|
+
/** Parsed result data from Kind 6900 DVM response (base64 JSON in IlpSendResult.data) */
|
|
2026
|
+
interface PetInteractionResultData {
|
|
2027
|
+
/** Current stat values */
|
|
2028
|
+
stats: StatValues;
|
|
2029
|
+
/** Current stage (0=Egg, 1=Baby, 2=Adult) */
|
|
2030
|
+
stage: number;
|
|
2031
|
+
/** Current evolution cycle (>= 0) */
|
|
2032
|
+
cycle: number;
|
|
2033
|
+
/** Unix timestamp of last interaction */
|
|
2034
|
+
lastInteraction: number;
|
|
2035
|
+
/** 64-char hex BLAKE3 hash of brain state */
|
|
2036
|
+
brainHash: string;
|
|
2037
|
+
/** Per-action-type cooldown timestamps */
|
|
2038
|
+
cooldownTimestamps: number[];
|
|
2039
|
+
}
|
|
2040
|
+
/** Stat snapshot used in interaction result content */
|
|
2041
|
+
interface InteractionResultContent {
|
|
2042
|
+
priorStats: StatValues;
|
|
2043
|
+
decayedStats: StatValues;
|
|
2044
|
+
finalStats: StatValues;
|
|
2045
|
+
cycle: number;
|
|
2046
|
+
stage: number;
|
|
2047
|
+
tokenCost: number;
|
|
2048
|
+
}
|
|
2049
|
+
/** Proof status of a Kind 14919 event */
|
|
2050
|
+
type ProofStatus = 'optimistic' | 'proven';
|
|
2051
|
+
/** Parameters for building a Kind 30402 pet-for-sale classified listing */
|
|
2052
|
+
interface PetListingParams {
|
|
2053
|
+
/** Blobbi identifier (non-empty string) — used as the 'd' tag */
|
|
2054
|
+
blobbiId: string;
|
|
2055
|
+
/** Asking price in USDC (> 0) */
|
|
2056
|
+
askPriceUsdc: number;
|
|
2057
|
+
/** 64-char hex lifecycleHash from on-chain PetZkApp state */
|
|
2058
|
+
lifecycleHash: string;
|
|
2059
|
+
/** Cumulative PET tokens spent (numeric string, >= "0") */
|
|
2060
|
+
totalSpent: string;
|
|
2061
|
+
/** Current stage: 0=Egg, 1=Baby, 2=Adult */
|
|
2062
|
+
stage: number;
|
|
2063
|
+
/** Current pet stats */
|
|
2064
|
+
stats: StatValues;
|
|
2065
|
+
/** Seller's Nostr pubkey (64-char hex) */
|
|
2066
|
+
sellerPubkey: string;
|
|
2067
|
+
/** Preferred relay URL for event relay routing */
|
|
2068
|
+
relayUrl: string;
|
|
2069
|
+
/** Listing expiry as unix timestamp */
|
|
2070
|
+
expiresAt: number;
|
|
2071
|
+
}
|
|
2072
|
+
/** A parsed pet-for-sale listing (extends PetListingParams with event metadata) */
|
|
2073
|
+
interface PetListing extends PetListingParams {
|
|
2074
|
+
/** Nostr event ID of the kind:30402 listing event */
|
|
2075
|
+
eventId: string;
|
|
2076
|
+
/** Unix timestamp when the listing event was created */
|
|
2077
|
+
createdAt: number;
|
|
2078
|
+
}
|
|
2079
|
+
/** Filter options for filterPetListings() */
|
|
2080
|
+
interface PetListingFilterOptions {
|
|
2081
|
+
/** Only include listings for pets at or above this stage */
|
|
2082
|
+
minStage?: number;
|
|
2083
|
+
/** Only include listings at or below this USDC price */
|
|
2084
|
+
maxAskPriceUsdc?: number;
|
|
2085
|
+
/** Only include listings where totalSpent >= this value (numeric string comparison) */
|
|
2086
|
+
minTotalSpent?: string;
|
|
2087
|
+
/** Only include listings from this seller pubkey */
|
|
2088
|
+
sellerPubkey?: string;
|
|
2089
|
+
}
|
|
2090
|
+
/** Parameters for building a Kind 5900 pet purchase request (transfer-ownership) */
|
|
2091
|
+
interface PetPurchaseRequestParams {
|
|
2092
|
+
/** Blobbi identifier being purchased */
|
|
2093
|
+
blobbiId: string;
|
|
2094
|
+
/** Nostr event ID of the kind:30402 listing being purchased */
|
|
2095
|
+
listingEventId: string;
|
|
2096
|
+
/** Buyer's Nostr pubkey (64-char hex) */
|
|
2097
|
+
buyerPubkey: string;
|
|
2098
|
+
/** Token cost for the purchase (>= 0) */
|
|
2099
|
+
tokenCost: number;
|
|
2100
|
+
/** Seller's Nostr pubkey — ILP payment routed to this pubkey (64-char hex) */
|
|
2101
|
+
sellerPubkey: string;
|
|
2102
|
+
}
|
|
2103
|
+
/** Parsed data from a Kind 14919 pet interaction event */
|
|
2104
|
+
interface PetInteractionEventData {
|
|
2105
|
+
/** Blobbi identifier from 'd' tag */
|
|
2106
|
+
blobbiId: string;
|
|
2107
|
+
/** Action type from 'action' tag */
|
|
2108
|
+
actionType: number;
|
|
2109
|
+
/** Item identifier from 'item' tag */
|
|
2110
|
+
itemId: number;
|
|
2111
|
+
/** Token cost from 'cost' tag */
|
|
2112
|
+
tokenCost: number;
|
|
2113
|
+
/** Evolution cycle from 'cycle' tag */
|
|
2114
|
+
cycle: number;
|
|
2115
|
+
/** Stage from 'stage' tag */
|
|
2116
|
+
stage: number;
|
|
2117
|
+
/** Brain hash from 'brain_hash' tag */
|
|
2118
|
+
brainHash: string;
|
|
2119
|
+
/** Proof status: 'optimistic' (no proof tag) or 'proven' (has proof + mina_tx tags) */
|
|
2120
|
+
proofStatus: ProofStatus;
|
|
2121
|
+
/** Parsed content JSON (stats before/after) */
|
|
2122
|
+
content: InteractionResultContent | null;
|
|
2123
|
+
/** Base64 proof data (only present when proven) */
|
|
2124
|
+
proof?: string;
|
|
2125
|
+
/** Mina transaction hash (only present when proven) */
|
|
2126
|
+
minaTx?: string;
|
|
2127
|
+
}
|
|
2128
|
+
|
|
2129
|
+
/**
|
|
2130
|
+
* Pet DVM Provider Discovery
|
|
2131
|
+
*
|
|
2132
|
+
* Filters Kind 10035 service discovery events to find providers that
|
|
2133
|
+
* support Pet DVM interactions (Kind 5900).
|
|
2134
|
+
*
|
|
2135
|
+
* @module pet/filterPetDvmProviders
|
|
2136
|
+
*/
|
|
2137
|
+
|
|
2138
|
+
/**
|
|
2139
|
+
* Minimal Nostr event shape needed for filtering.
|
|
2140
|
+
* Using a local interface to avoid importing nostr-tools types.
|
|
2141
|
+
*/
|
|
2142
|
+
interface NostrEventLike$3 {
|
|
2143
|
+
kind: number;
|
|
2144
|
+
pubkey: string;
|
|
2145
|
+
content: string;
|
|
2146
|
+
tags: string[][];
|
|
2147
|
+
id: string;
|
|
2148
|
+
sig: string;
|
|
2149
|
+
created_at: number;
|
|
2150
|
+
}
|
|
2151
|
+
/**
|
|
2152
|
+
* Filter Kind 10035 service discovery events to find pet DVM providers.
|
|
2153
|
+
*
|
|
2154
|
+
* Accepts raw NostrEvent[] and internally parses content via parseServiceDiscovery.
|
|
2155
|
+
* Filters events where skill.kinds includes 5900 (PET_INTERACTION_REQUEST_KIND).
|
|
2156
|
+
* Returns provider metadata sorted by price ascending (cheapest first).
|
|
2157
|
+
*
|
|
2158
|
+
* Handles missing/malformed skill descriptors gracefully (returns empty array, no throw).
|
|
2159
|
+
*
|
|
2160
|
+
* @param events - Array of raw Nostr events (kind:10035)
|
|
2161
|
+
* @returns Array of PetDvmProvider metadata, sorted by price ascending
|
|
2162
|
+
*/
|
|
2163
|
+
declare function filterPetDvmProviders(events: NostrEventLike$3[]): PetDvmProvider[];
|
|
2164
|
+
|
|
2165
|
+
/**
|
|
2166
|
+
* Pet Interaction Request Builder (Kind 5900)
|
|
2167
|
+
*
|
|
2168
|
+
* Builds unsigned Kind 5900 Nostr events for pet DVM interaction requests.
|
|
2169
|
+
* Compatible with nostr-tools/pure finalizeEvent for signing.
|
|
2170
|
+
*
|
|
2171
|
+
* @module pet/buildPetInteractionRequest
|
|
2172
|
+
*/
|
|
2173
|
+
|
|
2174
|
+
/**
|
|
2175
|
+
* Build an unsigned Kind 5900 pet interaction request event.
|
|
2176
|
+
*
|
|
2177
|
+
* All tag values are stringified per Nostr protocol convention.
|
|
2178
|
+
* The returned event is compatible with nostr-tools `finalizeEvent`.
|
|
2179
|
+
*
|
|
2180
|
+
* @param params - Typed interaction parameters
|
|
2181
|
+
* @returns Unsigned Nostr event ready for signing
|
|
2182
|
+
* @throws ValidationError for invalid input
|
|
2183
|
+
*/
|
|
2184
|
+
declare function buildPetInteractionRequest(params: PetInteractionRequestParams): UnsignedNostrEvent;
|
|
2185
|
+
|
|
2186
|
+
/**
|
|
2187
|
+
* Pet Interaction Result Parser (Kind 6900)
|
|
2188
|
+
*
|
|
2189
|
+
* Decodes base64-encoded JSON from IlpSendResult.data field.
|
|
2190
|
+
* Uses browser-safe atob() -- NOT Node.js Buffer -- for ditto React SPA compatibility.
|
|
2191
|
+
*
|
|
2192
|
+
* @module pet/parsePetInteractionResult
|
|
2193
|
+
*/
|
|
2194
|
+
|
|
2195
|
+
/**
|
|
2196
|
+
* Parse base64-encoded JSON result data from a Kind 6900 DVM response.
|
|
2197
|
+
*
|
|
2198
|
+
* Uses atob() for browser compatibility (ditto React SPA).
|
|
2199
|
+
* Returns null for malformed/missing data (no throw).
|
|
2200
|
+
*
|
|
2201
|
+
* Validates:
|
|
2202
|
+
* - brainHash is 64-char hex
|
|
2203
|
+
* - stats has all 5 fields
|
|
2204
|
+
* - cycle >= 0
|
|
2205
|
+
* - stage 0-2
|
|
2206
|
+
*
|
|
2207
|
+
* @param data - Base64-encoded JSON string from IlpSendResult.data
|
|
2208
|
+
* @returns Parsed PetInteractionResultData or null if invalid
|
|
2209
|
+
*/
|
|
2210
|
+
declare function parsePetInteractionResult(data: string): PetInteractionResultData | null;
|
|
2211
|
+
|
|
2212
|
+
/**
|
|
2213
|
+
* Pet Interaction Event Parser (Kind 14919)
|
|
2214
|
+
*
|
|
2215
|
+
* Parses Kind 14919 optimistic/proven pet interaction events.
|
|
2216
|
+
* Detects proof status from presence of 'proof' + 'mina_tx' tags.
|
|
2217
|
+
*
|
|
2218
|
+
* @module pet/parsePetInteractionEvent
|
|
2219
|
+
*/
|
|
2220
|
+
|
|
2221
|
+
/**
|
|
2222
|
+
* Minimal Nostr event shape needed for parsing.
|
|
2223
|
+
*/
|
|
2224
|
+
interface NostrEventLike$2 {
|
|
2225
|
+
kind: number;
|
|
2226
|
+
pubkey: string;
|
|
2227
|
+
content: string;
|
|
2228
|
+
tags: string[][];
|
|
2229
|
+
id: string;
|
|
2230
|
+
sig: string;
|
|
2231
|
+
created_at: number;
|
|
2232
|
+
}
|
|
2233
|
+
/**
|
|
2234
|
+
* Parse a Kind 14919 pet interaction event.
|
|
2235
|
+
*
|
|
2236
|
+
* Extracts all tag values and detects proof status:
|
|
2237
|
+
* - 'optimistic': no 'proof' tag
|
|
2238
|
+
* - 'proven': has 'proof' + 'mina_tx' tags
|
|
2239
|
+
*
|
|
2240
|
+
* Returns null if required tags are missing.
|
|
2241
|
+
*
|
|
2242
|
+
* @param event - A Nostr event (Kind 14919)
|
|
2243
|
+
* @returns Parsed PetInteractionEventData or null if malformed
|
|
2244
|
+
*/
|
|
2245
|
+
declare function parsePetInteractionEvent(event: NostrEventLike$2): PetInteractionEventData | null;
|
|
2246
|
+
|
|
2247
|
+
/**
|
|
2248
|
+
* Pet Listing Event Builder (Kind 30402)
|
|
2249
|
+
*
|
|
2250
|
+
* Builds unsigned Kind 30402 (NIP-99 classified listing) Nostr events
|
|
2251
|
+
* for pet-for-sale marketplace listings. Every listing includes a
|
|
2252
|
+
* verified biography attachment (lifecycleHash + totalSpent) so buyers
|
|
2253
|
+
* can verify the listing against on-chain PetZkApp state.
|
|
2254
|
+
*
|
|
2255
|
+
* Browser-compatible — no Node.js-only imports.
|
|
2256
|
+
*
|
|
2257
|
+
* @module pet/buildPetListingEvent
|
|
2258
|
+
*/
|
|
2259
|
+
|
|
2260
|
+
/**
|
|
2261
|
+
* Build an unsigned Kind 30402 pet-for-sale classified listing event.
|
|
2262
|
+
*
|
|
2263
|
+
* The listing uses the NIP-99 classified listing format with TOON-specific
|
|
2264
|
+
* extension tags for verified biography (lifecycleHash, totalSpent).
|
|
2265
|
+
* The `d` tag is set to `blobbiId` for stable parameterized replaceability —
|
|
2266
|
+
* republishing with the same `d` tag updates the listing on relays.
|
|
2267
|
+
*
|
|
2268
|
+
* The returned event is compatible with nostr-tools `finalizeEvent`.
|
|
2269
|
+
*
|
|
2270
|
+
* @param params - Typed listing parameters
|
|
2271
|
+
* @returns Unsigned Nostr event ready for signing and publishing
|
|
2272
|
+
*/
|
|
2273
|
+
declare function buildPetListingEvent(params: PetListingParams): UnsignedNostrEvent;
|
|
2274
|
+
|
|
2275
|
+
/**
|
|
2276
|
+
* Pet Listing Parser (Kind 30402)
|
|
2277
|
+
*
|
|
2278
|
+
* Parses Kind 30402 (NIP-99 classified listing) Nostr events into
|
|
2279
|
+
* typed PetListing objects. Returns null for invalid or malformed events.
|
|
2280
|
+
*
|
|
2281
|
+
* Browser-compatible — no Node.js-only imports.
|
|
2282
|
+
*
|
|
2283
|
+
* @module pet/parsePetListing
|
|
2284
|
+
*/
|
|
2285
|
+
|
|
2286
|
+
/** Minimal Nostr event shape required for parsing */
|
|
2287
|
+
interface NostrEventLike$1 {
|
|
2288
|
+
id: string;
|
|
2289
|
+
kind: number;
|
|
2290
|
+
pubkey: string;
|
|
2291
|
+
tags: string[][];
|
|
2292
|
+
content: string;
|
|
2293
|
+
created_at: number;
|
|
2294
|
+
}
|
|
2295
|
+
/**
|
|
2296
|
+
* Parse a Kind 30402 pet classified listing event into a PetListing.
|
|
2297
|
+
*
|
|
2298
|
+
* Validation rules:
|
|
2299
|
+
* - event.kind must be 30402
|
|
2300
|
+
* - 'd' tag must be present and non-empty
|
|
2301
|
+
* - 'price' tag must be present with a valid positive numeric first element
|
|
2302
|
+
* - 'lifecycle_hash' tag must be a 64-char hex string
|
|
2303
|
+
* - 'total_spent' tag must be a valid non-negative numeric string
|
|
2304
|
+
* - 'stage' tag must be present
|
|
2305
|
+
*
|
|
2306
|
+
* Stats are parsed from content JSON; unparseable content falls back to DEFAULT_STATS.
|
|
2307
|
+
*
|
|
2308
|
+
* @param event - A Nostr event (expected Kind 30402)
|
|
2309
|
+
* @returns Parsed PetListing or null if invalid
|
|
2310
|
+
*/
|
|
2311
|
+
declare function parsePetListing(event: NostrEventLike$1): PetListing | null;
|
|
2312
|
+
|
|
2313
|
+
/**
|
|
2314
|
+
* Pet Listing Discovery Filter
|
|
2315
|
+
*
|
|
2316
|
+
* Filters and sorts Kind 30402 pet marketplace listing events into
|
|
2317
|
+
* typed PetListing objects. Handles expiry, stage, price, biography
|
|
2318
|
+
* value, and seller filtering. Results sorted by totalSpent descending
|
|
2319
|
+
* (highest biography value first) to surface the most battle-hardened pets.
|
|
2320
|
+
*
|
|
2321
|
+
* Browser-compatible — no Node.js-only imports.
|
|
2322
|
+
*
|
|
2323
|
+
* @module pet/filterPetListings
|
|
2324
|
+
*/
|
|
2325
|
+
|
|
2326
|
+
/** Minimal Nostr event shape accepted by the filter */
|
|
2327
|
+
interface NostrEventLike {
|
|
2328
|
+
id: string;
|
|
2329
|
+
kind: number;
|
|
2330
|
+
pubkey: string;
|
|
2331
|
+
tags: string[][];
|
|
2332
|
+
content: string;
|
|
2333
|
+
created_at: number;
|
|
2334
|
+
}
|
|
2335
|
+
/**
|
|
2336
|
+
* Filter and sort Kind 30402 pet marketplace listing events.
|
|
2337
|
+
*
|
|
2338
|
+
* Parsing is done via parsePetListing — invalid events are silently dropped.
|
|
2339
|
+
* Expired listings (expiration tag < current unix time) are excluded.
|
|
2340
|
+
* Options allow additional filtering by stage, price, biography value, and seller.
|
|
2341
|
+
* Results are sorted by totalSpent descending (highest biography value first).
|
|
2342
|
+
*
|
|
2343
|
+
* @param events - Array of raw Nostr events to filter
|
|
2344
|
+
* @param options - Optional filter criteria
|
|
2345
|
+
* @returns Filtered and sorted array of PetListing objects
|
|
2346
|
+
*/
|
|
2347
|
+
declare function filterPetListings(events: NostrEventLike[], options?: PetListingFilterOptions): PetListing[];
|
|
2348
|
+
|
|
2349
|
+
/**
|
|
2350
|
+
* Pet Purchase Request Builder (Kind 5900, action type 9)
|
|
2351
|
+
*
|
|
2352
|
+
* Builds unsigned Kind 5900 Nostr events for pet transfer-ownership
|
|
2353
|
+
* purchase requests. Action type 9 is a reserved slot in the pet DVM
|
|
2354
|
+
* protocol — this event signals purchase intent and routes ILP payment
|
|
2355
|
+
* to the seller. The actual Mina on-chain ownership transfer (PetZkApp
|
|
2356
|
+
* .transferOperator) is handled by downstream stories.
|
|
2357
|
+
*
|
|
2358
|
+
* Browser-compatible — no Node.js-only imports.
|
|
2359
|
+
*
|
|
2360
|
+
* @module pet/buildPetPurchaseRequest
|
|
2361
|
+
*/
|
|
2362
|
+
|
|
2363
|
+
/**
|
|
2364
|
+
* Build an unsigned Kind 5900 pet purchase request event.
|
|
2365
|
+
*
|
|
2366
|
+
* Reuses the existing pet interaction event kind (5900) with action type 9
|
|
2367
|
+
* (transfer-ownership). The `listing` tag references the kind:30402 listing
|
|
2368
|
+
* event being purchased. The `p` tag routes ILP payment to the seller.
|
|
2369
|
+
*
|
|
2370
|
+
* The returned event is compatible with nostr-tools `finalizeEvent`.
|
|
2371
|
+
*
|
|
2372
|
+
* @param params - Typed purchase request parameters
|
|
2373
|
+
* @returns Unsigned Nostr event ready for signing and publishing
|
|
2374
|
+
*/
|
|
2375
|
+
declare function buildPetPurchaseRequest(params: PetPurchaseRequestParams): UnsignedNostrEvent;
|
|
2376
|
+
|
|
2377
|
+
/**
|
|
2378
|
+
* Client-side helper for kind:5094 Arweave blob storage DVM requests.
|
|
2379
|
+
*
|
|
2380
|
+
* This composes the three steps a caller previously had to wire by hand:
|
|
2381
|
+
* 1. Build the kind:5094 event via `buildBlobStorageRequest()` (@toon-protocol/core).
|
|
2382
|
+
* 2. Publish it to the DVM destination over ILP via `ToonClient.publishEvent()`
|
|
2383
|
+
* (reusing the existing claim / channel plumbing).
|
|
2384
|
+
* 3. Decode the FULFILL `data` field into the Arweave transaction ID.
|
|
2385
|
+
*
|
|
2386
|
+
* ## FULFILL data contract
|
|
2387
|
+
*
|
|
2388
|
+
* For a successful single-packet (non-chunked) blob upload, the DVM provider
|
|
2389
|
+
* returns the Arweave transaction ID as a **UTF-8 string, base64-encoded** in
|
|
2390
|
+
* the ILP FULFILL `data` field (the connector validates that FULFILL data is
|
|
2391
|
+
* base64). An Arweave tx ID is a 43-character base64url string (32 raw bytes).
|
|
2392
|
+
*
|
|
2393
|
+
* So the decode is:
|
|
2394
|
+
* `txId = utf8(base64decode(result.data))`
|
|
2395
|
+
*
|
|
2396
|
+
* See `packages/sdk/src/arweave/arweave-dvm-handler.ts` for the server side and
|
|
2397
|
+
* `packages/client/tests/e2e/docker-arweave-dvm-e2e.test.ts` for the reference
|
|
2398
|
+
* end-to-end flow this helper mirrors.
|
|
2399
|
+
*
|
|
2400
|
+
* Chunked uploads (multi-packet, via `uploadId` / `chunkIndex` / `totalChunks`
|
|
2401
|
+
* params) are intentionally out of scope for this single-packet helper — the
|
|
2402
|
+
* provider returns `ack:<n>` for intermediate chunks and the tx ID only on the
|
|
2403
|
+
* final chunk. Callers needing chunking should drive `publishEvent()` directly
|
|
2404
|
+
* (see the chunked case in the reference E2E test). Tracked as a follow-up.
|
|
2405
|
+
*/
|
|
2406
|
+
|
|
2407
|
+
/**
|
|
2408
|
+
* Parameters for {@link requestBlobStorage}.
|
|
2409
|
+
*/
|
|
2410
|
+
interface RequestBlobStorageParams {
|
|
2411
|
+
/** The raw blob data to store on Arweave. */
|
|
2412
|
+
blobData: Uint8Array;
|
|
2413
|
+
/**
|
|
2414
|
+
* MIME type of the blob. Defaults to `'application/octet-stream'`
|
|
2415
|
+
* (matching `buildBlobStorageRequest`).
|
|
2416
|
+
*/
|
|
2417
|
+
contentType?: string;
|
|
2418
|
+
/**
|
|
2419
|
+
* Bid amount in USDC micro-units, as a string (declared in the event's
|
|
2420
|
+
* `bid` tag). Defaults to the stringified `ilpAmount` when omitted.
|
|
2421
|
+
*
|
|
2422
|
+
* At least one of `bid` / `ilpAmount` should be provided so the declared
|
|
2423
|
+
* bid and the paid ILP amount agree.
|
|
2424
|
+
*/
|
|
2425
|
+
bid?: string;
|
|
2426
|
+
/**
|
|
2427
|
+
* ILP destination address of the DVM that performs the upload
|
|
2428
|
+
* (e.g. `'g.toon.peer1'`). Falls back to the client's configured
|
|
2429
|
+
* `destinationAddress` when omitted.
|
|
2430
|
+
*/
|
|
2431
|
+
destination?: string;
|
|
2432
|
+
/**
|
|
2433
|
+
* Pre-signed balance proof claim for this packet. When omitted, the
|
|
2434
|
+
* client's channel manager auto-opens a channel and auto-signs a claim
|
|
2435
|
+
* (same lazy-channel behavior as `publishEvent`).
|
|
2436
|
+
*/
|
|
2437
|
+
claim?: SignedBalanceProof;
|
|
2438
|
+
/**
|
|
2439
|
+
* Explicit ILP payment amount (bigint micro-units). When omitted,
|
|
2440
|
+
* `publishEvent` computes it from the encoded event size. When `bid`
|
|
2441
|
+
* is omitted, this value is stringified to populate the event's bid tag.
|
|
2442
|
+
*/
|
|
2443
|
+
ilpAmount?: bigint;
|
|
2444
|
+
}
|
|
2445
|
+
/**
|
|
2446
|
+
* Typed result of {@link requestBlobStorage}.
|
|
2447
|
+
*/
|
|
2448
|
+
interface RequestBlobStorageResult {
|
|
2449
|
+
/** Whether the upload succeeded and a tx ID was decoded. */
|
|
2450
|
+
success: boolean;
|
|
2451
|
+
/** The Arweave transaction ID (43-char base64url) when `success` is true. */
|
|
2452
|
+
txId?: string;
|
|
2453
|
+
/** The id of the kind:5094 event that was published. */
|
|
2454
|
+
eventId?: string;
|
|
2455
|
+
/** Error message when `success` is false. */
|
|
2456
|
+
error?: string;
|
|
2457
|
+
}
|
|
2458
|
+
/**
|
|
2459
|
+
* Requests permanent Arweave blob storage from a DVM in a single ILP packet.
|
|
2460
|
+
*
|
|
2461
|
+
* Mirrors the single-packet flow in
|
|
2462
|
+
* `packages/client/tests/e2e/docker-arweave-dvm-e2e.test.ts`: builds a signed
|
|
2463
|
+
* kind:5094 event, publishes it through the supplied {@link ToonClient}
|
|
2464
|
+
* (reusing its claim/channel plumbing), and decodes the FULFILL `data` field
|
|
2465
|
+
* into an Arweave transaction ID.
|
|
2466
|
+
*
|
|
2467
|
+
* @param client - A started `ToonClient` (call `client.start()` first).
|
|
2468
|
+
* @param secretKey - The Nostr secret key used to sign the kind:5094 event.
|
|
2469
|
+
* @param params - Blob, content type, bid, destination, and payment options.
|
|
2470
|
+
* @returns `{ success, txId?, eventId?, error? }`.
|
|
2471
|
+
*/
|
|
2472
|
+
declare function requestBlobStorage(client: ToonClient, secretKey: Uint8Array, params: RequestBlobStorageParams): Promise<RequestBlobStorageResult>;
|
|
1189
2473
|
|
|
1190
2474
|
/**
|
|
1191
2475
|
* Full multi-chain identity derived from a single BIP-39 mnemonic.
|
|
@@ -1384,16 +2668,38 @@ declare function generateMnemonic(): string;
|
|
|
1384
2668
|
* Validate a BIP-39 mnemonic phrase.
|
|
1385
2669
|
*/
|
|
1386
2670
|
declare function validateMnemonic(mnemonic: string): boolean;
|
|
2671
|
+
/**
|
|
2672
|
+
* Synchronously derive ONLY the Nostr secp256k1 key (NIP-06) from a mnemonic.
|
|
2673
|
+
*
|
|
2674
|
+
* The EVM key shares this same secp256k1 key. Solana (Ed25519) and Mina
|
|
2675
|
+
* (Pallas) require async dynamic imports — use {@link deriveFullIdentity} for
|
|
2676
|
+
* those. This sync subset exists so `ToonClient`'s synchronous constructor can
|
|
2677
|
+
* resolve the Nostr/EVM identity from a `mnemonic` config field without an
|
|
2678
|
+
* async factory; the client derives Solana/Mina lazily in `start()`.
|
|
2679
|
+
*/
|
|
2680
|
+
declare function deriveNostrKeyFromMnemonic(mnemonic: string, accountIndex?: number): {
|
|
2681
|
+
secretKey: Uint8Array;
|
|
2682
|
+
pubkey: string;
|
|
2683
|
+
};
|
|
1387
2684
|
/**
|
|
1388
2685
|
* Derive a full multi-chain ToonIdentity from a BIP-39 mnemonic.
|
|
1389
2686
|
*
|
|
2687
|
+
* All four chains vary by `accountIndex` (default 0), matching the SDK's
|
|
2688
|
+
* {@link https://www.npmjs.com/package/@toon-protocol/sdk `fromMnemonicFull`}
|
|
2689
|
+
* path-per-index scheme so a non-zero index produces the SAME addresses as
|
|
2690
|
+
* `fromMnemonicFull(mnemonic, { accountIndex })`. Index 0 is unchanged from the
|
|
2691
|
+
* historical fixed paths (back-compat).
|
|
2692
|
+
*
|
|
1390
2693
|
* Chains derived:
|
|
1391
|
-
* - Nostr (secp256k1): m/44'/1237'/0'/0/
|
|
2694
|
+
* - Nostr (secp256k1): m/44'/1237'/0'/0/{accountIndex}
|
|
1392
2695
|
* - EVM (secp256k1): same key as Nostr
|
|
1393
|
-
* - Solana (Ed25519): m/44'/501'/
|
|
1394
|
-
* - Mina (Pallas): m/44'/12586'/
|
|
2696
|
+
* - Solana (Ed25519): m/44'/501'/{accountIndex}'/0' (SLIP-0010)
|
|
2697
|
+
* - Mina (Pallas): m/44'/12586'/{accountIndex}'/0/0
|
|
2698
|
+
*
|
|
2699
|
+
* @param mnemonic - A valid BIP-39 mnemonic (12 or 24 words).
|
|
2700
|
+
* @param accountIndex - BIP-44 account index (default 0).
|
|
1395
2701
|
*/
|
|
1396
|
-
declare function deriveFullIdentity(mnemonic: string): Promise<ToonIdentity>;
|
|
2702
|
+
declare function deriveFullIdentity(mnemonic: string, accountIndex?: number): Promise<ToonIdentity>;
|
|
1397
2703
|
/**
|
|
1398
2704
|
* Derive a partial identity from an nsec (Nostr-only private key).
|
|
1399
2705
|
* Nostr + EVM share the same secp256k1 key.
|
|
@@ -1441,4 +2747,77 @@ declare function parseBackupPayload(content: string): VaultData;
|
|
|
1441
2747
|
*/
|
|
1442
2748
|
declare function isPrfSupported(): boolean;
|
|
1443
2749
|
|
|
1444
|
-
|
|
2750
|
+
/**
|
|
2751
|
+
* Node-only encrypted mnemonic keystore for @toon-protocol/client.
|
|
2752
|
+
*
|
|
2753
|
+
* Mirrors the Townhouse node wallet crypto (`packages/townhouse/src/wallet/
|
|
2754
|
+
* crypto.ts`): a BIP-39 mnemonic is encrypted at rest with scrypt (KDF) +
|
|
2755
|
+
* AES-256-GCM (authenticated encryption), serialized as JSON, and written to
|
|
2756
|
+
* disk with mode 0o600. Decryption requires the operator password; a wrong
|
|
2757
|
+
* password fails the GCM auth-tag verification and throws.
|
|
2758
|
+
*
|
|
2759
|
+
* This is the Node-side counterpart to the browser Passkey/IndexedDB
|
|
2760
|
+
* `KeyManager`/`KeyVault` flow — it does NOT touch those. It is guarded against
|
|
2761
|
+
* browser bundling: every entry point throws if `node:crypto`/`node:fs` are not
|
|
2762
|
+
* available (e.g. when accidentally imported in a browser bundle).
|
|
2763
|
+
*
|
|
2764
|
+
* @module
|
|
2765
|
+
*/
|
|
2766
|
+
/**
|
|
2767
|
+
* Encrypted keystore file format (JSON, all binary fields base64-encoded).
|
|
2768
|
+
* Wire-compatible with Townhouse's `EncryptedWallet`.
|
|
2769
|
+
*/
|
|
2770
|
+
interface EncryptedKeystore {
|
|
2771
|
+
/** scrypt salt (base64). */
|
|
2772
|
+
salt: string;
|
|
2773
|
+
/** AES-GCM initialization vector (base64). */
|
|
2774
|
+
iv: string;
|
|
2775
|
+
/** AES-256-GCM ciphertext (base64). */
|
|
2776
|
+
ciphertext: string;
|
|
2777
|
+
/** AES-GCM authentication tag (base64). */
|
|
2778
|
+
tag: string;
|
|
2779
|
+
/** Envelope version for forward-compat (currently 1). */
|
|
2780
|
+
version?: number;
|
|
2781
|
+
}
|
|
2782
|
+
/**
|
|
2783
|
+
* Encrypt a mnemonic with a password using scrypt + AES-256-GCM.
|
|
2784
|
+
* Returns the JSON-serializable encrypted envelope (does NOT write to disk).
|
|
2785
|
+
*/
|
|
2786
|
+
declare function encryptMnemonic(mnemonic: string, password: string): EncryptedKeystore;
|
|
2787
|
+
/**
|
|
2788
|
+
* Decrypt an encrypted keystore envelope with a password.
|
|
2789
|
+
* Throws on a wrong password (GCM auth-tag verification failure) or corruption.
|
|
2790
|
+
*/
|
|
2791
|
+
declare function decryptMnemonic(encrypted: EncryptedKeystore, password: string): string;
|
|
2792
|
+
/**
|
|
2793
|
+
* Generate a fresh 12-word BIP-39 mnemonic, encrypt it under `password`, and
|
|
2794
|
+
* write the encrypted keystore to `path` with mode 0o600.
|
|
2795
|
+
*
|
|
2796
|
+
* Returns the mnemonic (for one-time display/backup) alongside the encrypted
|
|
2797
|
+
* envelope. The caller is responsible for displaying the mnemonic securely and
|
|
2798
|
+
* NOT persisting it in plaintext.
|
|
2799
|
+
*/
|
|
2800
|
+
declare function generateKeystore(path: string, password: string): {
|
|
2801
|
+
mnemonic: string;
|
|
2802
|
+
keystore: EncryptedKeystore;
|
|
2803
|
+
};
|
|
2804
|
+
/**
|
|
2805
|
+
* Import an existing BIP-39 mnemonic (12 or 24 words), encrypt it under
|
|
2806
|
+
* `password`, and write the encrypted keystore to `path` with mode 0o600.
|
|
2807
|
+
*
|
|
2808
|
+
* Throws if the mnemonic is not a valid BIP-39 phrase (wrong checksum/word
|
|
2809
|
+
* count) before any file is written.
|
|
2810
|
+
*/
|
|
2811
|
+
declare function importKeystore(path: string, mnemonic: string, password: string): EncryptedKeystore;
|
|
2812
|
+
/**
|
|
2813
|
+
* Load and decrypt a keystore file at `path` with `password`, returning the
|
|
2814
|
+
* plaintext mnemonic. Throws on a wrong password or corruption.
|
|
2815
|
+
*/
|
|
2816
|
+
declare function loadKeystore(path: string, password: string): string;
|
|
2817
|
+
/**
|
|
2818
|
+
* Serialize and write an encrypted keystore to disk with mode 0o600
|
|
2819
|
+
* (owner read/write only), mirroring the Townhouse wallet file permissions.
|
|
2820
|
+
*/
|
|
2821
|
+
declare function writeKeystoreFile(path: string, keystore: EncryptedKeystore): void;
|
|
2822
|
+
|
|
2823
|
+
export { ANON_ASSETS, ANON_VERSION, type AnonAsset, type BackupPayload, type BalanceProofParams, BtpRuntimeClient, type BtpRuntimeClientConfig, type ChainMetadata, type ChainSigner, ChannelManager, type ClaimMessage, type ClientTransportConfig, ConnectorError, type EVMClaimMessage, type EncryptedKeystore, EvmSigner, HS_HOSTNAME_MAX_LENGTH, HS_HOSTNAME_REGEX, HttpConnectorAdmin, type HttpConnectorAdminConfig, HttpRuntimeClient, type HttpRuntimeClientConfig, type InteractionResultContent, KeyManager, type KeyManagerConfig, type ManagedAnonProxy, type MinaClaimMessage, type MinaDepositReader, MinaSigner, type MinaSignerOptions, NetworkError, OnChainChannelClient, type OnChainChannelClientConfig, type PasskeyInfo, type PetDvmProvider, type PetInteractionEventData, type PetInteractionRequestParams, type PetInteractionResultData, type PetListing, type PetListingFilterOptions, type PetListingParams, type PetPurchaseRequestParams, type ProofStatus, type PublishEventResult, type RequestBlobStorageParams, type RequestBlobStorageResult, type RetryOptions, type SignedBalanceProof, type SolanaChannelClientOptions, type SolanaClaimMessage, SolanaSigner, type StartManagedAnonProxyOptions, type StatValues, ToonClient, type ToonClientConfig, ToonClientError, type ToonIdentity, type ToonSigners, type ToonStartResult, type UnsignedNostrEvent, ValidationError, type VaultData, applyDefaults, applyNetworkPresets, assertRoutableHsHostname, buildBackupEvent, buildBackupFilter, buildPetInteractionRequest, buildPetListingEvent, buildPetPurchaseRequest, buildSettlementInfo, decryptMnemonic, deriveFromNsec, deriveFullIdentity, deriveNostrKeyFromMnemonic, encryptMnemonic, filterPetDvmProviders, filterPetListings, generateKeystore, generateMnemonic, generateRandomIdentity, getNetworkStatus, importKeystore, isPrfSupported, isRoutableHsHostname, loadKeystore, parseBackupPayload, parsePetInteractionEvent, parsePetInteractionResult, parsePetListing, readMinaDepositTotal, requestBlobStorage, selectAnonAsset, startManagedAnonProxy, validateConfig, validateMnemonic, withRetry, writeKeystoreFile };
|