@toon-protocol/client 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -23,7 +23,6 @@ This client handles:
23
23
  - **Unified Identity**: One Nostr key = one EVM address (both secp256k1, derived automatically) — or a single BIP-39 **mnemonic** to derive a full multi-chain identity
24
24
  - **Multi-Chain Settlement**: Sign payment-channel claims on EVM (EIP-712), Solana (Ed25519), and Mina (Pallas) from one mnemonic. A Townhouse apex validates the claim and redeems it on-chain on the matching chain (EVM/Solana credit the recipient; Mina redeems each claim on-chain with recipient credit-at-close deferred — see [Multi-Chain Settlement notes](#identity--multi-chain-settlement))
25
25
  - **Multi-Hop Routing**: Publish to any destination address (`destination` / `destinationAddress`), not just your direct peer
26
- - **Private Transport**: Optionally reach a townhouse apex at its ATOR `.anyone` address through a SOCKS5h proxy (see [Connecting over `.anyone`](#connecting-to-an-apex-over-anyone))
27
26
  - **Network Bootstrap**: Automatically discover and register with ILP peers via NIP-02 follow lists
28
27
  - **TOON Encoding**: Native binary format for agent-friendly event encoding
29
28
 
@@ -44,8 +43,7 @@ pnpm add mina-signer
44
43
  - **A TOON apex to pay.** You don't run any node yourself; you connect to a running
45
44
  [`@toon-protocol/townhouse`](https://www.npmjs.com/package/@toon-protocol/townhouse) apex (or any
46
45
  TOON connector) and pay it. From its operator you need:
47
- - a **connector endpoint** — either an HTTP `connectorUrl`, or an ATOR `.anyone` BTP endpoint reached
48
- through a **SOCKS5h** proxy (see [Connecting over `.anyone`](#connecting-to-an-apex-over-anyone));
46
+ - a **connector endpoint** — an HTTP `connectorUrl` and/or a BTP WebSocket `btpUrl`;
49
47
  - a **settlement-chain RPC URL** and a **funded key** on that chain, so the client can open a
50
48
  payment channel and sign EIP-712 claims;
51
49
  - the **token** and **TokenNetwork** contract addresses that apex accepts on that chain (e.g. USDC).
@@ -256,29 +254,6 @@ const client = new ToonClient({
256
254
 
257
255
  ---
258
256
 
259
- ## Connecting to an apex over `.anyone`
260
-
261
- In production a townhouse apex is reachable at an ATOR `.anyone` hidden-service address rather than a plain `ws://` host. To dial it, route the client's BTP/HTTP traffic through a **SOCKS5h** proxy via the `transport` option. The `socks5h://` scheme is required so DNS resolution happens at the proxy (no DNS leaks):
262
-
263
- ```typescript
264
- const client = new ToonClient({
265
- connectorUrl: 'http://localhost:8080', // local connector admin, if any
266
- secretKey,
267
- ilpInfo: { pubkey, ilpAddress: `g.toon.${pubkey.slice(0, 8)}`, btpEndpoint: 'ws://abc...xyz.anyone:3000' },
268
- btpUrl: 'ws://abc...xyz.anyone:3000', // the apex's BTP endpoint at its .anyone address
269
- destinationAddress: 'g.townhouse', // pay the apex; it forwards to the town/dvm/mill child
270
- toonEncoder: encodeEventToToon,
271
- toonDecoder: decodeEventFromToon,
272
-
273
- // Route the connection through a SOCKS5h proxy (Node.js only).
274
- transport: { type: 'socks5', socksProxy: 'socks5h://127.0.0.1:9050' },
275
- });
276
- ```
277
-
278
- In the browser, use `transport: { type: 'gateway', gatewayUrl: 'https://…' }` to proxy through an ator gateway server-side instead. (Default is `{ type: 'direct' }`.)
279
-
280
- ---
281
-
282
257
  ## Documentation
283
258
 
284
259
  - **[API Reference](docs/api-reference.md)** — Constructor, config interface, and all methods
package/dist/index.d.ts CHANGED
@@ -213,6 +213,30 @@ interface ToonClientConfig {
213
213
  * core release with these fields ship).
214
214
  */
215
215
  connectorHttpEndpoint?: string;
216
+ /**
217
+ * Connector-PROXY base URL for the deployed devnet/testnet edge (e.g.
218
+ * `https://proxy.devnet.toonprotocol.dev`). The connector is now a
219
+ * payment-proxy that serves ILP-over-HTTP at `POST /ilp`; setting `proxyUrl`
220
+ * is the high-level way to route paid writes through that proxy WITHOUT a
221
+ * persistent BTP socket.
222
+ *
223
+ * When set, `applyDefaults` derives `connectorHttpEndpoint` from it (appending
224
+ * `/ilp` to the base unless the URL already ends in `/ilp`), so the existing
225
+ * {@link HttpIlpClient} transport selection (`selectIlpTransport`) picks the
226
+ * stateless one-shot HTTP transport for `publishEvent`/`sendSwapPacket`/
227
+ * `sendPayment`. An explicit `connectorHttpEndpoint` always wins over this.
228
+ *
229
+ * The eventual home for these endpoints is a `@toon-protocol/core` devnet
230
+ * preset; until that ships, set this field explicitly.
231
+ */
232
+ proxyUrl?: string;
233
+ /**
234
+ * Faucet base URL for the deployed devnet (e.g.
235
+ * `https://faucet.devnet.toonprotocol.dev`). Consumed by the {@link fundWallet}
236
+ * helper to drip test funds to the client's chain address before publishing.
237
+ * Has no effect on the runtime transport; it is config carried for tooling/e2e.
238
+ */
239
+ faucetUrl?: string;
216
240
  /**
217
241
  * Whether the uplink connector accepts a BTP `Upgrade` over its HTTP endpoint
218
242
  * (mirrors `IlpPeerInfo.supportsUpgrade`, toon PR #29). Only consulted when
@@ -267,34 +291,6 @@ interface ToonClientConfig {
267
291
  minaChannel?: MinaChannelClientOptions;
268
292
  /** File path for persisting payment channel nonce/amount state across restarts */
269
293
  channelStorePath?: string;
270
- /**
271
- * Transport configuration for privacy-preserving connections.
272
- *
273
- * - `direct` (default): No privacy overlay, connect directly.
274
- * - `socks5`: Route connections through a SOCKS5 proxy (Node.js only).
275
- * Requires `socks5h://` scheme for DNS leak prevention.
276
- * - `gateway`: Route connections through an ator gateway URL (browser-compatible).
277
- * The gateway proxies through ator server-side.
278
- */
279
- transport?: ClientTransportConfig;
280
- /**
281
- * Self-managed `anon` (anyone-protocol / ATOR) SOCKS5h proxy (Node.js only).
282
- *
283
- * When the `btpUrl` host ends in `.anyone` and NO explicit proxy is configured
284
- * (`transport.socksProxy` / `transport.type === 'gateway'`) and the
285
- * `ANYONE_PROXY_URLS` env var is unset, the SDK auto-downloads + spawns its own
286
- * `anon` daemon, waits for it to bootstrap + bind a loopback SOCKS5 port, and
287
- * routes BTP/HTTP through it — ZERO manual proxy setup. `client.stop()` tears
288
- * the daemon down.
289
- *
290
- * - `undefined` (default): auto — managed proxy starts for `.anyone` hosts.
291
- * - `false`: opt out — never auto-start (you must supply your own proxy).
292
- *
293
- * Ignored in browser bundles (the node-only daemon module is never loaded).
294
- */
295
- managedAnonProxy?: boolean;
296
- /** Loopback SOCKS port the managed `anon` daemon binds. Default 9050. */
297
- managedAnonSocksPort?: number;
298
294
  /** Nostr relay URL for peer discovery. Default: 'ws://localhost:7100' */
299
295
  relayUrl?: string;
300
296
  /**
@@ -394,23 +390,6 @@ interface SignedBalanceProof extends BalanceProofParams {
394
390
  tokenId: string;
395
391
  };
396
392
  }
397
- /**
398
- * Transport configuration for privacy-preserving connections.
399
- *
400
- * Node.js: Use `socks5` to route WebSocket and HTTP through a SOCKS5 proxy.
401
- * Browser: Use `gateway` to route through a server-side ator gateway.
402
- */
403
- type ClientTransportConfig = {
404
- type: 'direct';
405
- } | {
406
- type: 'socks5';
407
- /** SOCKS5 proxy URL. MUST use `socks5h://` scheme (DNS leak prevention). */
408
- socksProxy: string;
409
- } | {
410
- type: 'gateway';
411
- /** Gateway base URL that proxies connections through ator server-side. */
412
- gatewayUrl: string;
413
- };
414
393
 
415
394
  /**
416
395
  * Client-side helper for kind:5094 Arweave blob storage DVM requests.
@@ -517,7 +496,7 @@ interface BtpRuntimeClientConfig {
517
496
  maxRetries?: number;
518
497
  /** Delay between reconnection attempts in ms (default: 1000) */
519
498
  retryDelay?: number;
520
- /** Custom WebSocket constructor (for SOCKS5 proxy support). */
499
+ /** Custom WebSocket constructor (for testing / custom transports). */
521
500
  createWebSocket?: (url: string) => WebSocket;
522
501
  }
523
502
  /**
@@ -632,11 +611,11 @@ interface HttpIlpClientConfig {
632
611
  maxRetries?: number;
633
612
  /** Initial retry delay in milliseconds (default: 1000). */
634
613
  retryDelay?: number;
635
- /** Custom fetch implementation (SOCKS5 mode / testing). */
614
+ /** Custom fetch implementation (for testing / custom transports). */
636
615
  httpClient?: typeof fetch;
637
616
  /**
638
- * Custom WebSocket constructor for the BTP upgrade path (SOCKS5 mode).
639
- * Forwarded to the underlying BtpRuntimeClient.
617
+ * Custom WebSocket constructor for the BTP upgrade path (for testing /
618
+ * custom transports). Forwarded to the underlying BtpRuntimeClient.
640
619
  */
641
620
  createWebSocket?: (url: string) => WebSocket;
642
621
  }
@@ -832,7 +811,7 @@ interface Http402ClientConfig {
832
811
  resolveClaim?: ClaimResolver;
833
812
  /**
834
813
  * Builds the {@link HttpIlpClient} for a resolved endpoint. Default: construct
835
- * a new `HttpIlpClient({ httpEndpoint })`. Injectable for tests / SOCKS5.
814
+ * a new `HttpIlpClient({ httpEndpoint })`. Injectable for tests.
836
815
  */
837
816
  createIlpClient?: HttpIlpClientFactory;
838
817
  /**
@@ -1118,7 +1097,7 @@ declare class ToonClient {
1118
1097
  * matching `destination`,
1119
1098
  * (c) neither -> throw MISSING_CLAIM.
1120
1099
  *
1121
- * @throws {ToonClientError} INVALID_STATE / NO_BTP_CLIENT / MISSING_CLAIM
1100
+ * @throws {ToonClientError} INVALID_STATE / NO_ILP_TRANSPORT / MISSING_CLAIM
1122
1101
  */
1123
1102
  sendSwapPacket(params: {
1124
1103
  destination: string;
@@ -1150,6 +1129,30 @@ declare class ToonClient {
1150
1129
  * `EvmSigner.buildClaimMessage`).
1151
1130
  */
1152
1131
  private buildClaimMessageForProof;
1132
+ /**
1133
+ * Resolve the ILP transport for a paid (claim-bearing) write.
1134
+ *
1135
+ * The connector is a payment-proxy: paid writes carry an ILP PREPARE plus the
1136
+ * signed payment-channel claim. Either transport speaks the SAME claim
1137
+ * contract — the BTP `payment-channel-claim` protocolData entry and the
1138
+ * ILP-over-HTTP `ILP-Payment-Channel-Claim` header serialize the same claim
1139
+ * JSON — so we route through whichever transport is ACTIVE rather than
1140
+ * hard-requiring BTP.
1141
+ *
1142
+ * Selection (mirrors `modes/http.ts` runtime-client precedence):
1143
+ * 1. `runtimeClient` when it implements `sendIlpPacketWithClaim` — this is
1144
+ * the HttpIlpClient (proxy `POST /ilp`) when a `proxyUrl`/
1145
+ * `connectorHttpEndpoint` is configured, else the BtpRuntimeClient.
1146
+ * 2. `btpClient` as an explicit fallback (always present when `btpUrl` is set).
1147
+ *
1148
+ * The level-3 `HttpRuntimeClient` (connector-admin HTTP, no `btpUrl` AND no
1149
+ * proxy) does NOT implement `sendIlpPacketWithClaim`; in that case there is no
1150
+ * paid-write transport and we throw a clear, actionable error.
1151
+ *
1152
+ * @throws {ToonClientError} NO_ILP_TRANSPORT when no active transport can send
1153
+ * a packet+claim.
1154
+ */
1155
+ private getClaimTransport;
1153
1156
  /**
1154
1157
  * Shared claim-resolution logic used by `publishEvent` and `sendSwapPacket`.
1155
1158
  * TODO(12.5 followup): also factor `publishEvent`'s inline claim resolution
@@ -1251,48 +1254,6 @@ declare class ToonClient {
1251
1254
  getDiscoveredPeers(): _toon_protocol_core.DiscoveredPeer[];
1252
1255
  }
1253
1256
 
1254
- /**
1255
- * Hidden-service hostname validation for the anyone-protocol / ATOR network.
1256
- *
1257
- * The `anon` binary routes hidden-service hostnames under the **`.anyone`** TLD
1258
- * ONLY. A `<host>.anon` name is NOT recognized as a hidden service — anon treats
1259
- * it as a clearnet name and tries to exit-resolve it, which fails
1260
- * (`resolve failed` / `HostUnreachable`). Only `<host>.anyone` triggers anon's
1261
- * `parse_extended_hostname: Anyone dns address lookup` and is validated.
1262
- *
1263
- * Historically the client and the toon-client pod accepted BOTH `.anon` and
1264
- * `.anyone`, so a `.anon` address was silently accepted and then failed deep in
1265
- * the transport with an opaque error. This module makes `.anyone` the single
1266
- * accepted/routable HS TLD and rejects `.anon` up front with an actionable
1267
- * message (see issue #201).
1268
- *
1269
- * This is a pure, browser-safe helper (no Node built-ins) so it can be imported
1270
- * from any transport path.
1271
- */
1272
- /**
1273
- * A `<host>.anyone` hidden-service hostname. The label is base32 (`a-z2-7`),
1274
- * matching the on-wire onion-style address alphabet anon uses.
1275
- */
1276
- declare const HS_HOSTNAME_REGEX: RegExp;
1277
- /** Max length of an HS hostname (defensive bound against pathological input). */
1278
- declare const HS_HOSTNAME_MAX_LENGTH = 80;
1279
- /**
1280
- * Returns true iff `s` is a routable `.anyone` hidden-service hostname.
1281
- * Does NOT accept the legacy `.anon` TLD (see {@link assertRoutableHsHostname}).
1282
- */
1283
- declare function isRoutableHsHostname(s: unknown): s is string;
1284
- /**
1285
- * Validates that `hostname` is a routable `.anyone` hidden-service address.
1286
- *
1287
- * - `<host>.anyone` → returns the hostname unchanged.
1288
- * - `<host>.anon` → throws with an actionable message pointing at `.anyone`
1289
- * (anon does NOT route `.anon`; it would silently fail in the transport).
1290
- * - anything else → throws a generic format error.
1291
- *
1292
- * @throws {Error} if the hostname is not a routable `.anyone` HS address.
1293
- */
1294
- declare function assertRoutableHsHostname(hostname: unknown): string;
1295
-
1296
1257
  /**
1297
1258
  * Base error class for all TOON client errors.
1298
1259
  */
@@ -2368,93 +2329,42 @@ interface RetryOptions {
2368
2329
  declare function withRetry<T>(operation: () => Promise<T>, options: RetryOptions): Promise<T>;
2369
2330
 
2370
2331
  /**
2371
- * Self-managed `anon` (anyone-protocol / ATOR) SOCKS5h proxy (Node.js only).
2332
+ * Store-write HTTP envelope for the payment-proxy (HTTP-in-ILP) path.
2372
2333
  *
2373
- * Lets a `@toon-protocol/client` consumer reach a `.anyone` hidden service with
2374
- * ZERO manual proxy setup: the SDK downloads, verifies, extracts, and spawns its
2375
- * own `anon` daemon, waits for it to bootstrap + bind a loopback SOCKS5 port, and
2376
- * hands back a `socks5h://127.0.0.1:<port>` URL. The proven reference is the
2377
- * server-side pod entrypoint `docker/src/entrypoint-toon-client.ts` (`writeTorrc`,
2378
- * `spawnAnon`, `waitForAnonSocks`, `tcpProbe`); this module ports that daemon
2379
- * logic into the client package and adds the binary download + checksum gate so it
2380
- * works without an OS-level `anon` install.
2334
+ * The deployed connector is a payment-proxy: it terminates a paid write by
2335
+ * decoding the ILP PREPARE `data` as a literal RFC 7230 HTTP/1.1 request and
2336
+ * reverse-proxying it to the relay store's `POST /write` (see the connector's
2337
+ * `HttpProxyHandler.decodeHttpRequest`). The ILP `data` MUST therefore be a
2338
+ * full HTTP request envelope:
2381
2339
  *
2382
- * BROWSER SAFETY: this module is dynamically imported only from `resolveTransport`
2383
- * when a managed proxy is actually needed (Node-only path). Every Node built-in is
2384
- * pulled in lazily via the ESM-safe `require(...)` built off `import.meta.url`
2385
- * (the same pattern as `socks5.ts`), so a browser bundler that statically analyses
2386
- * the package never reaches `node:child_process`/`node:fs`/`node:https`/`node:net`.
2387
- */
2388
- /**
2389
- * Pinned `anon` release. "beta" is the channel slug embedded in the per-platform
2390
- * zip asset names (e.g. `anon-beta-macos-arm64.zip`).
2391
- */
2392
- declare const ANON_VERSION = "v0.4.10.0-beta";
2393
- /**
2394
- * Per-platform `anon` zip asset descriptor. `sha256` is the pinned checksum of the
2395
- * release zip. All supported platforms are pinned (issue #204); the type stays
2396
- * `string | null` and the download gate still defensively refuses a `null` entry,
2397
- * so adding a new (not-yet-hashed) platform fails closed rather than skipping
2398
- * verification.
2399
- */
2400
- interface AnonAsset {
2401
- /** Release asset file name, e.g. `anon-beta-macos-arm64.zip`. */
2402
- assetName: string;
2403
- /** Pinned sha256 of the zip, or null when not yet pinned (issue #204). */
2404
- sha256: string | null;
2405
- }
2406
- /**
2407
- * Platform → asset map keyed by `${os.platform()}-${os.arch()}` (Node values).
2408
- * Only macOS + Linux on x64/arm64 are supported (the `anon` releases that ship a
2409
- * SOCKS-capable binary). Windows is intentionally absent.
2340
+ * POST /write HTTP/1.1\r\n
2341
+ * Host: relay\r\n
2342
+ * Content-Type: application/json\r\n
2343
+ * \r\n
2344
+ * {"event": <signed nostr event object>}
2410
2345
  *
2411
- * Pinned checksums (issue #204): all four supported platforms are pinned to the
2412
- * sha256 of the `v0.4.10.0-beta` release zips (downloaded + hashed; the
2413
- * darwin-arm64 value matches the previously-verified manual flow).
2414
- */
2415
- declare const ANON_ASSETS: Record<string, AnonAsset>;
2416
- /**
2417
- * Resolves the `anon` release asset for a platform/arch pair (Node
2418
- * `os.platform()` / `os.arch()` values).
2346
+ * Sending the bare TOON-encoded event (no request-line) makes the proxy reject
2347
+ * with `F01 - Invalid HTTP envelope: malformed request-line`. The relay's
2348
+ * `/write` handler parses the body as JSON and reads `body.event` as a full
2349
+ * signed Nostr event OBJECT (it runs `verifyEvent(event)` + `store(event)`), so
2350
+ * the body carries the event object verbatim — NOT the TOON string.
2419
2351
  *
2420
- * @throws If the platform/arch combination has no known `anon` asset.
2421
- */
2422
- declare function selectAnonAsset(platform: string, arch: string): AnonAsset;
2423
- /**
2424
- * Handle returned by `startManagedAnonProxy`. `socksProxy` is the loopback
2425
- * `socks5h://` URL to wire into `transport: { type: 'socks5', socksProxy }`.
2426
- * `stop()` SIGTERMs the daemon and is idempotent.
2352
+ * This helper is the single source of truth for that envelope so the proxy
2353
+ * paid-write path (`ToonClient.publishEvent`) and any future caller stay
2354
+ * byte-compatible with the deployed store. It is isomorphic (Node + browser):
2355
+ * `JSON.stringify` escapes non-ASCII to `\uXXXX`, so the serialized envelope is
2356
+ * pure ASCII and `encodeUtf8` matches the bytes the store expects.
2427
2357
  */
2428
- interface ManagedAnonProxy {
2429
- socksProxy: string;
2430
- stop(): Promise<void>;
2431
- }
2432
- /**
2433
- * Options for `startManagedAnonProxy`. All have sensible defaults; tests inject
2434
- * the deps to avoid real downloads/spawns.
2435
- */
2436
- interface StartManagedAnonProxyOptions {
2437
- /** Cache dir for the binary + torrc + data. Default: {@link defaultCacheDir}. */
2438
- cacheDir?: string;
2439
- /** Loopback SOCKS5 port. Default 9050. */
2440
- socksPort?: number;
2441
- /** Bootstrap deadline in ms. Default 180_000. */
2442
- bootstrapTimeoutMs?: number;
2443
- /** Logger. Default: no-op. */
2444
- log?: (msg: string) => void;
2445
- /** os.platform() override (tests). */
2446
- platform?: string;
2447
- /** os.arch() override (tests). */
2448
- arch?: string;
2449
- }
2358
+
2450
2359
  /**
2451
- * Downloads (if needed) + spawns a managed `anon` daemon and waits for its SOCKS5
2452
- * port to bind. Returns a {@link ManagedAnonProxy} whose `socksProxy` is ready for
2453
- * `transport: { type: 'socks5', socksProxy }`.
2360
+ * Wrap a signed Nostr event in the `POST /write` HTTP envelope the deployed
2361
+ * payment-proxy reverse-proxies to the relay store.
2454
2362
  *
2455
- * @throws If the platform is unsupported, the checksum fails, or anon never binds.
2363
+ * @param event - A finalized (signed) Nostr event passed through to the store
2364
+ * as the JSON `event` field verbatim (the store re-verifies the signature).
2365
+ * @returns The envelope bytes to use as the ILP PREPARE `data`.
2456
2366
  */
2457
- declare function startManagedAnonProxy(options?: StartManagedAnonProxyOptions): Promise<ManagedAnonProxy>;
2367
+ declare function buildStoreWriteEnvelope(event: NostrEvent): Uint8Array;
2458
2368
 
2459
2369
  /**
2460
2370
  * Settlement info produced by buildSettlementInfo().
@@ -2488,6 +2398,16 @@ declare function applyNetworkPresets(config: ToonClientConfig): ToonClientConfig
2488
2398
  * unset or `'custom'` (no preset tier to report on).
2489
2399
  */
2490
2400
  declare function getNetworkStatus(config: ToonClientConfig): NetworkFamilyStatus | undefined;
2401
+ /**
2402
+ * Normalize a connector-proxy base URL into its `POST /ilp` endpoint.
2403
+ *
2404
+ * `https://proxy.devnet.toonprotocol.dev` → `https://proxy.devnet.toonprotocol.dev/ilp`
2405
+ * `https://proxy.devnet.toonprotocol.dev/ilp` → unchanged (idempotent)
2406
+ * `https://proxy.devnet.toonprotocol.dev/` → `https://proxy.devnet.toonprotocol.dev/ilp`
2407
+ *
2408
+ * Returns `undefined` for an empty/falsy input so callers can `??`-chain it.
2409
+ */
2410
+ declare function proxyIlpEndpoint(proxyUrl: string | undefined): string | undefined;
2491
2411
  /**
2492
2412
  * Validates ToonClient configuration.
2493
2413
  *
@@ -2500,7 +2420,7 @@ declare function validateConfig(config: ToonClientConfig): void;
2500
2420
  * The resolved config type after defaults are applied.
2501
2421
  * secretKey is guaranteed to be present (auto-generated if omitted).
2502
2422
  */
2503
- type ResolvedConfig = Required<Omit<ToonClientConfig, 'connector' | 'mnemonic' | 'mnemonicAccountIndex' | 'evmPrivateKey' | 'network' | 'supportedChains' | 'settlementAddresses' | 'preferredTokens' | 'tokenNetworks' | 'btpUrl' | 'btpAuthToken' | 'btpPeerId' | 'connectorHttpEndpoint' | 'connectorSupportsUpgrade' | 'chainRpcUrls' | 'initialDeposit' | 'settlementTimeout' | 'solanaChannel' | 'minaChannel' | 'channelStorePath' | 'knownPeers' | 'destinationAddress' | 'transport' | 'managedAnonProxy' | 'managedAnonSocksPort'>> & {
2423
+ type ResolvedConfig = Required<Omit<ToonClientConfig, 'connector' | 'mnemonic' | 'mnemonicAccountIndex' | 'evmPrivateKey' | 'network' | 'supportedChains' | 'settlementAddresses' | 'preferredTokens' | 'tokenNetworks' | 'btpUrl' | 'btpAuthToken' | 'btpPeerId' | 'connectorHttpEndpoint' | 'proxyUrl' | 'faucetUrl' | 'connectorSupportsUpgrade' | 'chainRpcUrls' | 'initialDeposit' | 'settlementTimeout' | 'solanaChannel' | 'minaChannel' | 'channelStorePath' | 'knownPeers' | 'destinationAddress'>> & {
2504
2424
  connector?: unknown;
2505
2425
  /** Always present after applyDefaults() — derived from secretKey if not explicitly provided */
2506
2426
  evmPrivateKey: string | Uint8Array;
@@ -2516,14 +2436,8 @@ type ResolvedConfig = Required<Omit<ToonClientConfig, 'connector' | 'mnemonic' |
2516
2436
  * same index as the synchronously-resolved Nostr/EVM keys.
2517
2437
  */
2518
2438
  mnemonicAccountIndex?: number;
2519
- /** Transport privacy config (optional — defaults to direct). */
2520
- transport?: ClientTransportConfig;
2521
2439
  /** Named network tier, retained for `getNetworkStatus()`. */
2522
2440
  network?: ToonClientConfig['network'];
2523
- /** Self-managed `anon` SOCKS5h proxy opt-out (default auto). */
2524
- managedAnonProxy?: boolean;
2525
- /** Loopback SOCKS port for the managed `anon` daemon (default 9050). */
2526
- managedAnonSocksPort?: number;
2527
2441
  supportedChains?: string[];
2528
2442
  settlementAddresses?: Record<string, string>;
2529
2443
  preferredTokens?: Record<string, string>;
@@ -2532,6 +2446,8 @@ type ResolvedConfig = Required<Omit<ToonClientConfig, 'connector' | 'mnemonic' |
2532
2446
  btpAuthToken?: string;
2533
2447
  btpPeerId?: string;
2534
2448
  connectorHttpEndpoint?: string;
2449
+ proxyUrl?: string;
2450
+ faucetUrl?: string;
2535
2451
  connectorSupportsUpgrade?: boolean;
2536
2452
  chainRpcUrls?: Record<string, string>;
2537
2453
  initialDeposit?: string;
@@ -2958,6 +2874,51 @@ declare function filterPetListings(events: NostrEventLike[], options?: PetListin
2958
2874
  */
2959
2875
  declare function buildPetPurchaseRequest(params: PetPurchaseRequestParams): UnsignedNostrEvent;
2960
2876
 
2877
+ /**
2878
+ * Devnet faucet helper.
2879
+ *
2880
+ * The deployed TOON devnet exposes a faucet that drips test funds to a given
2881
+ * chain address so a client can open payment channels and pay for writes:
2882
+ *
2883
+ * EVM `POST {faucetUrl}/api/request` body `{ address }` → 100 ETH + 10k USDC
2884
+ * Solana `POST {faucetUrl}/api/solana/request` body `{ address }` → SOL + USDC
2885
+ * Mina `POST {faucetUrl}/api/mina/request` body `{ address }` → native MINA only
2886
+ *
2887
+ * Devnet edge (today): `https://faucet.devnet.toonprotocol.dev`.
2888
+ *
2889
+ * EVM is implemented fully. Solana/Mina are deferred to a later milestone (WS3)
2890
+ * and throw a clear error so callers don't silently assume funding happened.
2891
+ */
2892
+ /** Supported faucet chains. */
2893
+ type FaucetChain = 'evm' | 'solana' | 'mina';
2894
+ /** Result of a successful faucet drip. */
2895
+ interface FundWalletResult {
2896
+ /** The chain that was funded. */
2897
+ chain: FaucetChain;
2898
+ /** The funded address (echoed back). */
2899
+ address: string;
2900
+ /** Raw parsed JSON body from the faucet (shape is faucet-defined). */
2901
+ response: unknown;
2902
+ }
2903
+ /** Options for {@link fundWallet}. */
2904
+ interface FundWalletOptions {
2905
+ /** Custom fetch implementation (for testing / custom transports). */
2906
+ fetchImpl?: typeof fetch;
2907
+ /** Request timeout in milliseconds (default: 30000). */
2908
+ timeout?: number;
2909
+ }
2910
+ /**
2911
+ * Drip test funds to `address` on `chain` from the devnet `faucetUrl`.
2912
+ *
2913
+ * @param faucetUrl - Faucet base URL, e.g. `https://faucet.devnet.toonprotocol.dev`.
2914
+ * A trailing `/` is tolerated.
2915
+ * @param address - The chain address to fund (EVM 0x address, Solana base58, etc).
2916
+ * @param chain - `'evm'` (implemented) | `'solana'` | `'mina'` (deferred — throw).
2917
+ * @throws {Error} If `faucetUrl`/`address` is missing, or the chain is deferred.
2918
+ * @throws {NetworkError} On transport failure or a non-2xx faucet response.
2919
+ */
2920
+ declare function fundWallet(faucetUrl: string, address: string, chain: FaucetChain, options?: FundWalletOptions): Promise<FundWalletResult>;
2921
+
2961
2922
  /**
2962
2923
  * Full multi-chain identity derived from a single BIP-39 mnemonic.
2963
2924
  */
@@ -3307,4 +3268,4 @@ declare function loadKeystore(path: string, password: string): string;
3307
3268
  */
3308
3269
  declare function writeKeystoreFile(path: string, keystore: EncryptedKeystore): void;
3309
3270
 
3310
- export { ANON_ASSETS, ANON_VERSION, type AnonAsset, type BackupPayload, type BalanceProofParams, BtpRuntimeClient, type BtpRuntimeClientConfig, type ChainMetadata, type ChainSigner, ChannelManager, type ClaimMessage, type ClaimResolver, type ClientTransportConfig, ConnectorError, type DiscoveredIlpPeer, type EVMClaimMessage, type EncryptedKeystore, EvmSigner, type H402FetchOptions, HS_HOSTNAME_MAX_LENGTH, HS_HOSTNAME_REGEX, Http402Client, type Http402ClientConfig, HttpConnectorAdmin, type HttpConnectorAdminConfig, HttpIlpClient, type HttpIlpClientConfig, type HttpIlpClientFactory, HttpRuntimeClient, type HttpRuntimeClientConfig, ILP_CLAIM_HEADER, ILP_CLAIM_WRAPPED_HEADER, ILP_PEER_ID_HEADER, type IlpTransportChoice, type InteractionResultContent, KeyManager, type KeyManagerConfig, type ManagedAnonProxy, type MinaClaimMessage, type MinaDepositReader, MinaSigner, type MinaSignerOptions, NetworkError, OnChainChannelClient, type OnChainChannelClientConfig, type ParsedX402Challenge, 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 SelectIlpTransportOptions, type SignedBalanceProof, type SolanaChannelClientOptions, type SolanaClaimMessage, SolanaSigner, type StartManagedAnonProxyOptions, type StatValues, type ToonChannelAccept, 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, httpEndpointToBtpUrl, importKeystore, isPrfSupported, isRoutableHsHostname, loadKeystore, parseBackupPayload, parseHttpResponse, parsePetInteractionEvent, parsePetInteractionResult, parsePetListing, parseX402Body, parseX402Challenge, readDiscoveredIlpPeer, readMinaDepositTotal, requestBlobStorage, selectAnonAsset, selectIlpTransport, serializeHttpRequest, startManagedAnonProxy, validateConfig, validateMnemonic, withRetry, writeKeystoreFile };
3271
+ export { type BackupPayload, type BalanceProofParams, BtpRuntimeClient, type BtpRuntimeClientConfig, type ChainMetadata, type ChainSigner, ChannelManager, type ClaimMessage, type ClaimResolver, ConnectorError, type DiscoveredIlpPeer, type EVMClaimMessage, type EncryptedKeystore, EvmSigner, type FaucetChain, type FundWalletOptions, type FundWalletResult, type H402FetchOptions, Http402Client, type Http402ClientConfig, HttpConnectorAdmin, type HttpConnectorAdminConfig, HttpIlpClient, type HttpIlpClientConfig, type HttpIlpClientFactory, HttpRuntimeClient, type HttpRuntimeClientConfig, ILP_CLAIM_HEADER, ILP_CLAIM_WRAPPED_HEADER, ILP_PEER_ID_HEADER, type IlpTransportChoice, type InteractionResultContent, KeyManager, type KeyManagerConfig, type MinaClaimMessage, type MinaDepositReader, MinaSigner, type MinaSignerOptions, NetworkError, OnChainChannelClient, type OnChainChannelClientConfig, type ParsedX402Challenge, 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 SelectIlpTransportOptions, type SignedBalanceProof, type SolanaChannelClientOptions, type SolanaClaimMessage, SolanaSigner, type StatValues, type ToonChannelAccept, ToonClient, type ToonClientConfig, ToonClientError, type ToonIdentity, type ToonSigners, type ToonStartResult, type UnsignedNostrEvent, ValidationError, type VaultData, applyDefaults, applyNetworkPresets, buildBackupEvent, buildBackupFilter, buildPetInteractionRequest, buildPetListingEvent, buildPetPurchaseRequest, buildSettlementInfo, buildStoreWriteEnvelope, decryptMnemonic, deriveFromNsec, deriveFullIdentity, deriveNostrKeyFromMnemonic, encryptMnemonic, filterPetDvmProviders, filterPetListings, fundWallet, generateKeystore, generateMnemonic, generateRandomIdentity, getNetworkStatus, httpEndpointToBtpUrl, importKeystore, isPrfSupported, loadKeystore, parseBackupPayload, parseHttpResponse, parsePetInteractionEvent, parsePetInteractionResult, parsePetListing, parseX402Body, parseX402Challenge, proxyIlpEndpoint, readDiscoveredIlpPeer, readMinaDepositTotal, requestBlobStorage, selectIlpTransport, serializeHttpRequest, validateConfig, validateMnemonic, withRetry, writeKeystoreFile };