@toon-protocol/client 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +208 -0
- package/dist/index.d.ts +966 -0
- package/dist/index.js +1728 -0
- package/dist/index.js.map +1 -0
- package/package.json +52 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,966 @@
|
|
|
1
|
+
import * as _toon_protocol_core from '@toon-protocol/core';
|
|
2
|
+
import { IlpPeerInfo, IlpSendResult, IlpClient, ConnectorAdminClient, ConnectorChannelClient, OpenChannelParams, OpenChannelResult, ChannelState } from '@toon-protocol/core';
|
|
3
|
+
import { NostrEvent } from 'nostr-tools/pure';
|
|
4
|
+
import { PrivateKeyAccount } from 'viem/accounts';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Configuration for ToonClient.
|
|
8
|
+
*
|
|
9
|
+
* This story implements HTTP mode only. Embedded mode will be added in a future epic.
|
|
10
|
+
*
|
|
11
|
+
* @example HTTP Mode (implemented)
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const client = new ToonClient({
|
|
14
|
+
* connectorUrl: 'http://localhost:8080',
|
|
15
|
+
* secretKey,
|
|
16
|
+
* ilpInfo: { ilpAddress, btpEndpoint, pubkey },
|
|
17
|
+
* toonEncoder: encodeEvent,
|
|
18
|
+
* toonDecoder: decodeEvent,
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @example Embedded Mode (not yet implemented)
|
|
23
|
+
* ```typescript
|
|
24
|
+
* const client = new ToonClient({
|
|
25
|
+
* connector: embeddedConnectorInstance, // Will throw error: "Embedded mode not yet implemented"
|
|
26
|
+
* secretKey,
|
|
27
|
+
* ilpInfo,
|
|
28
|
+
* toonEncoder,
|
|
29
|
+
* toonDecoder,
|
|
30
|
+
* });
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
interface ToonClientConfig {
|
|
34
|
+
/**
|
|
35
|
+
* HTTP URL of external connector service.
|
|
36
|
+
* Required for HTTP mode.
|
|
37
|
+
* Example: 'http://localhost:8080'
|
|
38
|
+
*/
|
|
39
|
+
connectorUrl?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Embedded connector instance - NOT IMPLEMENTED in this story.
|
|
42
|
+
* Will throw error: "Embedded mode not yet implemented in ToonClient."
|
|
43
|
+
* Reserved for future implementation.
|
|
44
|
+
*/
|
|
45
|
+
connector?: unknown;
|
|
46
|
+
/**
|
|
47
|
+
* 32-byte Nostr private key (hex or Uint8Array).
|
|
48
|
+
* Optional — if omitted, a keypair is auto-generated in applyDefaults().
|
|
49
|
+
*/
|
|
50
|
+
secretKey?: Uint8Array;
|
|
51
|
+
/** ILP peer information for this client */
|
|
52
|
+
ilpInfo: IlpPeerInfo;
|
|
53
|
+
/** Function to encode Nostr events to TOON binary format */
|
|
54
|
+
toonEncoder: (event: NostrEvent) => Uint8Array;
|
|
55
|
+
/** Function to decode TOON binary format to Nostr events */
|
|
56
|
+
toonDecoder: (bytes: Uint8Array) => NostrEvent;
|
|
57
|
+
/**
|
|
58
|
+
* EVM private key for signing balance proofs and on-chain transactions.
|
|
59
|
+
*
|
|
60
|
+
* By default, this is derived from `secretKey` — both Nostr and EVM use
|
|
61
|
+
* secp256k1, so a single key provides both identities (matching the SDK's
|
|
62
|
+
* `fromMnemonic()`/`fromSecretKey()` behavior).
|
|
63
|
+
*
|
|
64
|
+
* Only set this if you need a *different* EVM key than your Nostr key
|
|
65
|
+
* (e.g., hardware wallet, custodial key, or legacy key separation).
|
|
66
|
+
*/
|
|
67
|
+
evmPrivateKey?: string | Uint8Array;
|
|
68
|
+
/** Supported settlement chain identifiers (e.g., ["evm:anvil:31337"]) */
|
|
69
|
+
supportedChains?: string[];
|
|
70
|
+
/** Maps chain identifier to EVM settlement address */
|
|
71
|
+
settlementAddresses?: Record<string, string>;
|
|
72
|
+
/** Maps chain identifier to preferred token contract address */
|
|
73
|
+
preferredTokens?: Record<string, string>;
|
|
74
|
+
/** Maps chain identifier to TokenNetwork contract address (EVM only) */
|
|
75
|
+
tokenNetworks?: Record<string, string>;
|
|
76
|
+
/** BTP WebSocket URL (e.g., "ws://localhost:3000") */
|
|
77
|
+
btpUrl?: string;
|
|
78
|
+
/** Auth token for BTP handshake */
|
|
79
|
+
btpAuthToken?: string;
|
|
80
|
+
/** Peer ID for BTP connection (used in connector env var BTP_PEER_{ID}_SECRET) */
|
|
81
|
+
btpPeerId?: string;
|
|
82
|
+
/**
|
|
83
|
+
* ILP destination address for event publishing.
|
|
84
|
+
* Defaults to the connector's local address (derived from connectorUrl host).
|
|
85
|
+
* For multi-hop routing, set this to the target node's ILP address.
|
|
86
|
+
* Examples:
|
|
87
|
+
* - 'g.toon.genesis' - Publish to genesis node
|
|
88
|
+
* - 'g.toon.peer1' - Publish to peer1 node
|
|
89
|
+
*/
|
|
90
|
+
destinationAddress?: string;
|
|
91
|
+
/** Maps chain identifier to RPC URL (e.g., {"evm:anvil:31337": "http://localhost:8545"}) */
|
|
92
|
+
chainRpcUrls?: Record<string, string>;
|
|
93
|
+
/** Amount to deposit when opening channel (default: "0") */
|
|
94
|
+
initialDeposit?: string;
|
|
95
|
+
/** Challenge period in seconds (default: 86400) */
|
|
96
|
+
settlementTimeout?: number;
|
|
97
|
+
/** File path for persisting payment channel nonce/amount state across restarts */
|
|
98
|
+
channelStorePath?: string;
|
|
99
|
+
/** Nostr relay URL for peer discovery. Default: 'ws://localhost:7100' */
|
|
100
|
+
relayUrl?: string;
|
|
101
|
+
/**
|
|
102
|
+
* Known peers to bootstrap with.
|
|
103
|
+
* If provided, these peers will be used for initial bootstrap.
|
|
104
|
+
* DiscoveryTracker will discover additional peers from kind:10032 events after bootstrap.
|
|
105
|
+
*/
|
|
106
|
+
knownPeers?: {
|
|
107
|
+
pubkey: string;
|
|
108
|
+
relayUrl: string;
|
|
109
|
+
btpEndpoint?: string;
|
|
110
|
+
}[];
|
|
111
|
+
/** Query timeout in milliseconds. Default: 30000 */
|
|
112
|
+
queryTimeout?: number;
|
|
113
|
+
/** Maximum number of retries for failed operations. Default: 3 */
|
|
114
|
+
maxRetries?: number;
|
|
115
|
+
/** Delay between retries in milliseconds. Default: 1000 */
|
|
116
|
+
retryDelay?: number;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Result returned by ToonClient.start()
|
|
120
|
+
*/
|
|
121
|
+
interface ToonStartResult {
|
|
122
|
+
/** Number of peers discovered during bootstrap */
|
|
123
|
+
peersDiscovered: number;
|
|
124
|
+
/** Mode the client is running in */
|
|
125
|
+
mode: 'http' | 'embedded';
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Result returned by ToonClient.publishEvent()
|
|
129
|
+
*/
|
|
130
|
+
interface PublishEventResult {
|
|
131
|
+
/** Whether the event was successfully published */
|
|
132
|
+
success: boolean;
|
|
133
|
+
/** ID of the published event */
|
|
134
|
+
eventId?: string;
|
|
135
|
+
/** ILP fulfillment from the relay (proof of payment) */
|
|
136
|
+
fulfillment?: string;
|
|
137
|
+
/** Error message if success is false */
|
|
138
|
+
error?: string;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Parameters for signing a balance proof.
|
|
142
|
+
*/
|
|
143
|
+
interface BalanceProofParams {
|
|
144
|
+
/** Payment channel identifier */
|
|
145
|
+
channelId: string;
|
|
146
|
+
/** Monotonically increasing nonce */
|
|
147
|
+
nonce: number;
|
|
148
|
+
/** Cumulative amount transferred */
|
|
149
|
+
transferredAmount: bigint;
|
|
150
|
+
/** Amount locked in pending transfers */
|
|
151
|
+
lockedAmount: bigint;
|
|
152
|
+
/** Merkle root of pending lock hashes */
|
|
153
|
+
locksRoot: string;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* A signed balance proof with EIP-712 signature.
|
|
157
|
+
*/
|
|
158
|
+
interface SignedBalanceProof extends BalanceProofParams {
|
|
159
|
+
/** EIP-712 signature */
|
|
160
|
+
signature: string;
|
|
161
|
+
/** Address of the signer */
|
|
162
|
+
signerAddress: string;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* ToonClient - High-level client for interacting with TOON network.
|
|
167
|
+
*
|
|
168
|
+
* This story implements HTTP mode only. Embedded mode will be added in a future epic.
|
|
169
|
+
*
|
|
170
|
+
* @example HTTP Mode
|
|
171
|
+
* ```typescript
|
|
172
|
+
* import { ToonClient } from '@toon-protocol/client';
|
|
173
|
+
* import { generateSecretKey, getPublicKey } from 'nostr-tools/pure';
|
|
174
|
+
* import { encodeEvent, decodeEvent } from '@toon-protocol/relay';
|
|
175
|
+
*
|
|
176
|
+
* const secretKey = generateSecretKey();
|
|
177
|
+
* const pubkey = getPublicKey(secretKey);
|
|
178
|
+
*
|
|
179
|
+
* const client = new ToonClient({
|
|
180
|
+
* connectorUrl: 'http://localhost:8080',
|
|
181
|
+
* secretKey,
|
|
182
|
+
* ilpInfo: {
|
|
183
|
+
* pubkey,
|
|
184
|
+
* ilpAddress: `g.toon.${pubkey.slice(0, 8)}`,
|
|
185
|
+
* btpEndpoint: 'ws://localhost:3000',
|
|
186
|
+
* },
|
|
187
|
+
* toonEncoder: encodeEvent,
|
|
188
|
+
* toonDecoder: decodeEvent,
|
|
189
|
+
* });
|
|
190
|
+
*
|
|
191
|
+
* await client.start(); // Bootstrap peers, start monitoring
|
|
192
|
+
*
|
|
193
|
+
* // Publish to default destination (from config)
|
|
194
|
+
* await client.publishEvent(signedEvent);
|
|
195
|
+
*
|
|
196
|
+
* // Publish to specific destination (multi-hop routing)
|
|
197
|
+
* await client.publishEvent(signedEvent, { destination: 'g.toon.peer1' });
|
|
198
|
+
*
|
|
199
|
+
* await client.stop(); // Cleanup
|
|
200
|
+
* ```
|
|
201
|
+
*/
|
|
202
|
+
declare class ToonClient {
|
|
203
|
+
private readonly config;
|
|
204
|
+
private state;
|
|
205
|
+
private readonly evmSigner?;
|
|
206
|
+
private channelManager?;
|
|
207
|
+
/**
|
|
208
|
+
* Creates a new ToonClient instance.
|
|
209
|
+
*
|
|
210
|
+
* @param config - Client configuration
|
|
211
|
+
* @throws {ValidationError} If configuration is invalid
|
|
212
|
+
*/
|
|
213
|
+
constructor(config: ToonClientConfig);
|
|
214
|
+
/**
|
|
215
|
+
* Generates a new Nostr keypair.
|
|
216
|
+
*
|
|
217
|
+
* @returns Object with secretKey (Uint8Array) and pubkey (hex string)
|
|
218
|
+
*/
|
|
219
|
+
static generateKeypair(): {
|
|
220
|
+
secretKey: Uint8Array;
|
|
221
|
+
pubkey: string;
|
|
222
|
+
};
|
|
223
|
+
/**
|
|
224
|
+
* Gets the Nostr public key derived from the secret key.
|
|
225
|
+
* Works before start() is called.
|
|
226
|
+
*/
|
|
227
|
+
getPublicKey(): string;
|
|
228
|
+
/**
|
|
229
|
+
* Gets the EVM address derived from the Nostr secret key (or explicit evmPrivateKey override).
|
|
230
|
+
*/
|
|
231
|
+
getEvmAddress(): string | undefined;
|
|
232
|
+
/**
|
|
233
|
+
* Starts the ToonClient.
|
|
234
|
+
*
|
|
235
|
+
* This will:
|
|
236
|
+
* 1. Initialize HTTP mode components (runtime client, admin client, bootstrap, monitor)
|
|
237
|
+
* 2. Bootstrap the network (discover peers, register, and open channels)
|
|
238
|
+
* 3. Start monitoring relay for new peers (kind:10032 events)
|
|
239
|
+
*
|
|
240
|
+
* @returns Result with number of peers discovered and mode
|
|
241
|
+
* @throws {ToonClientError} If client is already started
|
|
242
|
+
* @throws {ToonClientError} If initialization fails
|
|
243
|
+
*/
|
|
244
|
+
start(): Promise<ToonStartResult>;
|
|
245
|
+
/**
|
|
246
|
+
* Publishes a Nostr event to the relay via ILP payment.
|
|
247
|
+
*
|
|
248
|
+
* The event must already be finalized (signed with id, pubkey, sig).
|
|
249
|
+
*
|
|
250
|
+
* @param event - Signed Nostr event to publish
|
|
251
|
+
* @param options - Optional options including destination and signed balance proof claim
|
|
252
|
+
* @returns Result with success status, event ID, and fulfillment
|
|
253
|
+
* @throws {ToonClientError} If client is not started
|
|
254
|
+
* @throws {ToonClientError} If event publishing fails
|
|
255
|
+
*/
|
|
256
|
+
publishEvent(event: NostrEvent, options?: {
|
|
257
|
+
destination?: string;
|
|
258
|
+
claim?: SignedBalanceProof;
|
|
259
|
+
}): Promise<PublishEventResult>;
|
|
260
|
+
/**
|
|
261
|
+
* Signs a balance proof for the given channel with the specified amount.
|
|
262
|
+
* Delegates to ChannelManager which auto-increments nonce and tracks cumulative amount.
|
|
263
|
+
*
|
|
264
|
+
* @param channelId - Payment channel identifier
|
|
265
|
+
* @param amount - Additional amount to add to cumulative transferred amount
|
|
266
|
+
* @returns Signed balance proof
|
|
267
|
+
* @throws {ToonClientError} If no EVM signer configured or channel not tracked
|
|
268
|
+
*/
|
|
269
|
+
signBalanceProof(channelId: string, amount: bigint): Promise<SignedBalanceProof>;
|
|
270
|
+
/**
|
|
271
|
+
* Gets list of tracked payment channel IDs.
|
|
272
|
+
*/
|
|
273
|
+
getTrackedChannels(): string[];
|
|
274
|
+
/**
|
|
275
|
+
* Sends an ILP payment, optionally with a balance proof claim via BTP.
|
|
276
|
+
*
|
|
277
|
+
* @param params - Payment parameters
|
|
278
|
+
* @returns ILP send result
|
|
279
|
+
* @throws {ToonClientError} If client is not started
|
|
280
|
+
*/
|
|
281
|
+
sendPayment(params: {
|
|
282
|
+
destination: string;
|
|
283
|
+
amount: string;
|
|
284
|
+
data?: string;
|
|
285
|
+
claim?: SignedBalanceProof;
|
|
286
|
+
}): Promise<IlpSendResult>;
|
|
287
|
+
/**
|
|
288
|
+
* Stops the ToonClient and cleans up resources.
|
|
289
|
+
*
|
|
290
|
+
* This will:
|
|
291
|
+
* 1. Disconnect BTP client if connected
|
|
292
|
+
* 2. Clear internal state
|
|
293
|
+
*
|
|
294
|
+
* @throws {ToonClientError} If client is not started
|
|
295
|
+
*/
|
|
296
|
+
stop(): Promise<void>;
|
|
297
|
+
/**
|
|
298
|
+
* Returns true if the client is currently started.
|
|
299
|
+
*/
|
|
300
|
+
isStarted(): boolean;
|
|
301
|
+
/**
|
|
302
|
+
* Gets the number of peers discovered during bootstrap.
|
|
303
|
+
*
|
|
304
|
+
* @returns Number of peers discovered
|
|
305
|
+
* @throws {ToonClientError} If client is not started
|
|
306
|
+
*/
|
|
307
|
+
getPeersCount(): number;
|
|
308
|
+
/**
|
|
309
|
+
* Gets the list of peers discovered by the relay monitor.
|
|
310
|
+
*
|
|
311
|
+
* @returns Array of discovered peer objects
|
|
312
|
+
* @throws {ToonClientError} If client is not started
|
|
313
|
+
*/
|
|
314
|
+
getDiscoveredPeers(): _toon_protocol_core.DiscoveredPeer[];
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Base error class for all TOON client errors.
|
|
319
|
+
*/
|
|
320
|
+
declare class ToonClientError extends Error {
|
|
321
|
+
readonly code: string;
|
|
322
|
+
constructor(message: string, code: string, cause?: Error);
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Network error for connection failures (ECONNREFUSED, ETIMEDOUT).
|
|
326
|
+
* These errors trigger retry logic with exponential backoff.
|
|
327
|
+
*/
|
|
328
|
+
declare class NetworkError extends ToonClientError {
|
|
329
|
+
constructor(message: string, cause?: Error);
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Connector error for 5xx server errors.
|
|
333
|
+
* These errors indicate the connector is unavailable or malfunctioning.
|
|
334
|
+
*/
|
|
335
|
+
declare class ConnectorError extends ToonClientError {
|
|
336
|
+
constructor(message: string, cause?: Error);
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Validation error for invalid input parameters.
|
|
340
|
+
* These errors are thrown before making any HTTP requests.
|
|
341
|
+
*/
|
|
342
|
+
declare class ValidationError extends ToonClientError {
|
|
343
|
+
constructor(message: string, cause?: Error);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Configuration options for HttpRuntimeClient.
|
|
348
|
+
*/
|
|
349
|
+
interface HttpRuntimeClientConfig {
|
|
350
|
+
/** Connector runtime API base URL (e.g., 'http://localhost:8080') */
|
|
351
|
+
connectorUrl: string;
|
|
352
|
+
/** Request timeout in milliseconds (default: 30000) */
|
|
353
|
+
timeout?: number;
|
|
354
|
+
/** Maximum retry attempts for network failures (default: 3) */
|
|
355
|
+
maxRetries?: number;
|
|
356
|
+
/** Initial retry delay in milliseconds (default: 1000) */
|
|
357
|
+
retryDelay?: number;
|
|
358
|
+
/** HTTP client implementation (for testing) */
|
|
359
|
+
httpClient?: typeof fetch;
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* HTTP client for sending ILP packets to an external connector runtime API.
|
|
363
|
+
*
|
|
364
|
+
* Implements the IlpClient interface for use with TOON agents
|
|
365
|
+
* that need to send ILP packets without embedding a full connector.
|
|
366
|
+
*
|
|
367
|
+
* Features:
|
|
368
|
+
* - Request validation (destination, amount, data)
|
|
369
|
+
* - Retry logic with exponential backoff for transient network failures
|
|
370
|
+
* - Typed error handling (NetworkError, ConnectorError, ValidationError)
|
|
371
|
+
* - Connection pooling and keep-alive (via Node.js fetch)
|
|
372
|
+
*
|
|
373
|
+
* @example
|
|
374
|
+
* ```typescript
|
|
375
|
+
* const client = new HttpRuntimeClient({
|
|
376
|
+
* connectorUrl: 'http://localhost:8080'
|
|
377
|
+
* });
|
|
378
|
+
*
|
|
379
|
+
* const result = await client.sendIlpPacket({
|
|
380
|
+
* destination: 'g.toon.alice',
|
|
381
|
+
* amount: '1000',
|
|
382
|
+
* data: 'base64EncodedToonData==',
|
|
383
|
+
* });
|
|
384
|
+
*
|
|
385
|
+
* if (result.accepted) {
|
|
386
|
+
* console.log('Payment accepted:', result.fulfillment);
|
|
387
|
+
* } else {
|
|
388
|
+
* console.error('Payment rejected:', result.code, result.message);
|
|
389
|
+
* }
|
|
390
|
+
* ```
|
|
391
|
+
*/
|
|
392
|
+
declare class HttpRuntimeClient implements IlpClient {
|
|
393
|
+
private readonly connectorUrl;
|
|
394
|
+
private readonly timeout;
|
|
395
|
+
private readonly retryConfig;
|
|
396
|
+
private readonly httpClient;
|
|
397
|
+
constructor(config: HttpRuntimeClientConfig);
|
|
398
|
+
/**
|
|
399
|
+
* Send an ILP packet to the connector runtime API.
|
|
400
|
+
*
|
|
401
|
+
* @param params - ILP packet parameters
|
|
402
|
+
* @returns ILP packet response with acceptance status
|
|
403
|
+
* @throws {ValidationError} If request parameters are invalid
|
|
404
|
+
* @throws {NetworkError} If network connection fails after retries
|
|
405
|
+
* @throws {ConnectorError} If connector returns 5xx server error
|
|
406
|
+
*/
|
|
407
|
+
sendIlpPacket(params: {
|
|
408
|
+
destination: string;
|
|
409
|
+
amount: string;
|
|
410
|
+
data: string;
|
|
411
|
+
timeout?: number;
|
|
412
|
+
}): Promise<IlpSendResult>;
|
|
413
|
+
/**
|
|
414
|
+
* Validate ILP packet request parameters.
|
|
415
|
+
*
|
|
416
|
+
* @throws {ValidationError} If any parameter is invalid
|
|
417
|
+
*/
|
|
418
|
+
private validateRequest;
|
|
419
|
+
/**
|
|
420
|
+
* Send HTTP POST request to connector runtime API.
|
|
421
|
+
*
|
|
422
|
+
* @throws {NetworkError} On connection failures (ECONNREFUSED, ETIMEDOUT)
|
|
423
|
+
* @throws {ConnectorError} On 5xx server errors
|
|
424
|
+
* @returns IlpSendResult with acceptance status
|
|
425
|
+
*/
|
|
426
|
+
private sendHttpRequest;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Configuration for HttpConnectorAdmin.
|
|
431
|
+
*/
|
|
432
|
+
interface HttpConnectorAdminConfig {
|
|
433
|
+
/** Admin API base URL (e.g., 'http://localhost:8081') */
|
|
434
|
+
adminUrl: string;
|
|
435
|
+
/** Request timeout in milliseconds (default: 30000) */
|
|
436
|
+
timeout?: number;
|
|
437
|
+
/** Maximum retry attempts for network failures (default: 3) */
|
|
438
|
+
maxRetries?: number;
|
|
439
|
+
/** Initial retry delay in milliseconds (default: 1000) */
|
|
440
|
+
retryDelay?: number;
|
|
441
|
+
/** HTTP client for testing (default: global fetch) */
|
|
442
|
+
httpClient?: typeof fetch;
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Result of a bulk peer operation.
|
|
446
|
+
*/
|
|
447
|
+
interface PeerOperationResult {
|
|
448
|
+
/** Peer ID that was operated on */
|
|
449
|
+
peerId: string;
|
|
450
|
+
/** Whether the operation succeeded */
|
|
451
|
+
success: boolean;
|
|
452
|
+
/** Error that occurred (if failed) */
|
|
453
|
+
error?: Error;
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* HTTP-based connector admin client for managing ILP peers via REST API.
|
|
457
|
+
*
|
|
458
|
+
* Implements the ConnectorAdminClient interface using HTTP requests to the
|
|
459
|
+
* connector's admin API (typically port 8081).
|
|
460
|
+
*
|
|
461
|
+
* @example
|
|
462
|
+
* ```typescript
|
|
463
|
+
* // Embedded mode (DirectConnectorAdmin)
|
|
464
|
+
* const adminClient = new DirectConnectorAdmin(connectorNode);
|
|
465
|
+
*
|
|
466
|
+
* // HTTP mode (HttpConnectorAdmin)
|
|
467
|
+
* const adminClient = new HttpConnectorAdmin({
|
|
468
|
+
* adminUrl: 'http://localhost:8081'
|
|
469
|
+
* });
|
|
470
|
+
*
|
|
471
|
+
* // Add peer
|
|
472
|
+
* await adminClient.addPeer({
|
|
473
|
+
* id: 'nostr-abc123',
|
|
474
|
+
* url: 'btp+ws://alice.example.com:3000',
|
|
475
|
+
* authToken: 'secret-token',
|
|
476
|
+
* routes: [{ prefix: 'g.toon.alice' }]
|
|
477
|
+
* });
|
|
478
|
+
*
|
|
479
|
+
* // Remove peer
|
|
480
|
+
* await adminClient.removePeer('nostr-abc123');
|
|
481
|
+
* ```
|
|
482
|
+
*
|
|
483
|
+
* @throws {ValidationError} Input validation failed (before HTTP request)
|
|
484
|
+
* @throws {NetworkError} Connection failed (ECONNREFUSED, ETIMEDOUT)
|
|
485
|
+
* @throws {UnauthorizedError} Admin API returned 401 (missing/invalid auth)
|
|
486
|
+
* @throws {PeerAlreadyExistsError} Admin API returned 409 (duplicate peer)
|
|
487
|
+
* @throws {PeerNotFoundError} Admin API returned 404 (peer not found)
|
|
488
|
+
* @throws {ConnectorError} Admin API returned 5xx (server error)
|
|
489
|
+
*/
|
|
490
|
+
declare class HttpConnectorAdmin implements ConnectorAdminClient {
|
|
491
|
+
private readonly adminUrl;
|
|
492
|
+
private readonly timeout;
|
|
493
|
+
private readonly retryConfig;
|
|
494
|
+
private readonly httpClient;
|
|
495
|
+
constructor(config: HttpConnectorAdminConfig);
|
|
496
|
+
/**
|
|
497
|
+
* Add a peer to the connector via the admin API.
|
|
498
|
+
*
|
|
499
|
+
* Validates peer config parameters and sends HTTP POST to /admin/peers.
|
|
500
|
+
*
|
|
501
|
+
* @param config - Peer configuration
|
|
502
|
+
* @param config.id - Unique peer identifier (non-empty string)
|
|
503
|
+
* @param config.url - BTP WebSocket URL (must start with 'btp+ws://' or 'btp+wss://')
|
|
504
|
+
* @param config.authToken - Authentication token (non-empty string)
|
|
505
|
+
* @param config.routes - Optional routing table entries
|
|
506
|
+
* @param config.settlement - Optional settlement configuration
|
|
507
|
+
*
|
|
508
|
+
* @throws {ValidationError} Invalid peer config (missing id, invalid url, etc.)
|
|
509
|
+
* @throws {PeerAlreadyExistsError} Peer with same ID already exists (409 Conflict)
|
|
510
|
+
* @throws {UnauthorizedError} Admin API authentication failed (401)
|
|
511
|
+
* @throws {NetworkError} Connection to admin API failed
|
|
512
|
+
* @throws {ConnectorError} Admin API server error (5xx)
|
|
513
|
+
*/
|
|
514
|
+
addPeer(config: {
|
|
515
|
+
id: string;
|
|
516
|
+
url: string;
|
|
517
|
+
authToken: string;
|
|
518
|
+
routes?: {
|
|
519
|
+
prefix: string;
|
|
520
|
+
priority?: number;
|
|
521
|
+
}[];
|
|
522
|
+
settlement?: {
|
|
523
|
+
preference: string;
|
|
524
|
+
evmAddress?: string;
|
|
525
|
+
tokenAddress?: string;
|
|
526
|
+
tokenNetworkAddress?: string;
|
|
527
|
+
chainId?: number;
|
|
528
|
+
channelId?: string;
|
|
529
|
+
initialDeposit?: string;
|
|
530
|
+
};
|
|
531
|
+
}): Promise<void>;
|
|
532
|
+
/**
|
|
533
|
+
* Remove a peer from the connector via the admin API.
|
|
534
|
+
*
|
|
535
|
+
* Sends HTTP DELETE to /admin/peers/:id.
|
|
536
|
+
*
|
|
537
|
+
* @param peerId - Unique peer identifier to remove (non-empty string)
|
|
538
|
+
*
|
|
539
|
+
* @throws {ValidationError} Invalid peerId (empty string)
|
|
540
|
+
* @throws {PeerNotFoundError} Peer does not exist (404 Not Found)
|
|
541
|
+
* @throws {UnauthorizedError} Admin API authentication failed (401)
|
|
542
|
+
* @throws {NetworkError} Connection to admin API failed
|
|
543
|
+
* @throws {ConnectorError} Admin API server error (5xx)
|
|
544
|
+
*/
|
|
545
|
+
removePeer(peerId: string): Promise<void>;
|
|
546
|
+
/**
|
|
547
|
+
* Add multiple peers in parallel for efficient bootstrapping.
|
|
548
|
+
*
|
|
549
|
+
* Uses Promise.allSettled() to execute peer additions concurrently,
|
|
550
|
+
* returning results for each operation regardless of individual failures.
|
|
551
|
+
*
|
|
552
|
+
* @param configs - Array of peer configurations to add
|
|
553
|
+
* @returns Array of results indicating success/failure for each peer
|
|
554
|
+
*
|
|
555
|
+
* @example
|
|
556
|
+
* ```typescript
|
|
557
|
+
* const results = await admin.addPeers([
|
|
558
|
+
* { id: 'peer1', url: 'btp+ws://...', authToken: 'token1' },
|
|
559
|
+
* { id: 'peer2', url: 'btp+ws://...', authToken: 'token2' },
|
|
560
|
+
* ]);
|
|
561
|
+
*
|
|
562
|
+
* results.forEach(result => {
|
|
563
|
+
* if (result.success) {
|
|
564
|
+
* console.log(`Added peer: ${result.peerId}`);
|
|
565
|
+
* } else {
|
|
566
|
+
* console.error(`Failed to add ${result.peerId}:`, result.error);
|
|
567
|
+
* }
|
|
568
|
+
* });
|
|
569
|
+
* ```
|
|
570
|
+
*/
|
|
571
|
+
addPeers(configs: {
|
|
572
|
+
id: string;
|
|
573
|
+
url: string;
|
|
574
|
+
authToken: string;
|
|
575
|
+
routes?: {
|
|
576
|
+
prefix: string;
|
|
577
|
+
priority?: number;
|
|
578
|
+
}[];
|
|
579
|
+
settlement?: {
|
|
580
|
+
preference: string;
|
|
581
|
+
evmAddress?: string;
|
|
582
|
+
tokenAddress?: string;
|
|
583
|
+
tokenNetworkAddress?: string;
|
|
584
|
+
chainId?: number;
|
|
585
|
+
channelId?: string;
|
|
586
|
+
initialDeposit?: string;
|
|
587
|
+
};
|
|
588
|
+
}[]): Promise<PeerOperationResult[]>;
|
|
589
|
+
/**
|
|
590
|
+
* Remove multiple peers in parallel.
|
|
591
|
+
*
|
|
592
|
+
* Uses Promise.allSettled() to execute peer removals concurrently,
|
|
593
|
+
* returning results for each operation regardless of individual failures.
|
|
594
|
+
*
|
|
595
|
+
* @param peerIds - Array of peer IDs to remove
|
|
596
|
+
* @returns Array of results indicating success/failure for each peer
|
|
597
|
+
*
|
|
598
|
+
* @example
|
|
599
|
+
* ```typescript
|
|
600
|
+
* const results = await admin.removePeers(['peer1', 'peer2', 'peer3']);
|
|
601
|
+
*
|
|
602
|
+
* const succeeded = results.filter(r => r.success).length;
|
|
603
|
+
* console.log(`Removed ${succeeded}/${results.length} peers`);
|
|
604
|
+
* ```
|
|
605
|
+
*/
|
|
606
|
+
removePeers(peerIds: string[]): Promise<PeerOperationResult[]>;
|
|
607
|
+
/**
|
|
608
|
+
* Send HTTP POST request to add a peer.
|
|
609
|
+
* Separated for retry logic wrapping.
|
|
610
|
+
*/
|
|
611
|
+
private sendAddPeerRequest;
|
|
612
|
+
/**
|
|
613
|
+
* Send HTTP DELETE request to remove a peer.
|
|
614
|
+
* Separated for retry logic wrapping.
|
|
615
|
+
*/
|
|
616
|
+
private sendRemovePeerRequest;
|
|
617
|
+
/**
|
|
618
|
+
* Handle network errors from HTTP requests.
|
|
619
|
+
*
|
|
620
|
+
* Converts connection failures, timeouts, and unknown errors to NetworkError.
|
|
621
|
+
* Re-throws existing ToonClientError instances.
|
|
622
|
+
*
|
|
623
|
+
* @param error - Error thrown by HTTP client
|
|
624
|
+
* @param url - Request URL (for error messages)
|
|
625
|
+
* @param operation - Operation name (for error messages)
|
|
626
|
+
* @throws {NetworkError} Network connection or timeout error
|
|
627
|
+
*/
|
|
628
|
+
private handleNetworkError;
|
|
629
|
+
/**
|
|
630
|
+
* Handle HTTP error responses from the admin API.
|
|
631
|
+
*
|
|
632
|
+
* Converts HTTP status codes to appropriate error types.
|
|
633
|
+
*
|
|
634
|
+
* @param response - HTTP response from admin API
|
|
635
|
+
* @param endpoint - Endpoint being called (for error messages)
|
|
636
|
+
* @param peerId - Peer ID (for error messages)
|
|
637
|
+
* @throws {UnauthorizedError} 401 Unauthorized
|
|
638
|
+
* @throws {PeerNotFoundError} 404 Not Found
|
|
639
|
+
* @throws {PeerAlreadyExistsError} 409 Conflict
|
|
640
|
+
* @throws {ConnectorError} 5xx Server Error
|
|
641
|
+
*/
|
|
642
|
+
private handleErrorResponse;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
/**
|
|
646
|
+
* EVM claim message for BTP protocol data.
|
|
647
|
+
* Matches @toon-protocol/connector's EVMClaimMessage interface.
|
|
648
|
+
*/
|
|
649
|
+
interface EVMClaimMessage {
|
|
650
|
+
blockchain: 'evm';
|
|
651
|
+
senderId: string;
|
|
652
|
+
channelId: string;
|
|
653
|
+
nonce: number;
|
|
654
|
+
transferredAmount: string;
|
|
655
|
+
lockedAmount: string;
|
|
656
|
+
locksRoot: string;
|
|
657
|
+
signature: string;
|
|
658
|
+
signerAddress: string;
|
|
659
|
+
}
|
|
660
|
+
/**
|
|
661
|
+
* EVM signer for EIP-712 balance proofs and on-chain transactions.
|
|
662
|
+
*
|
|
663
|
+
* Encapsulates the private key — no getPrivateKey() method is exposed.
|
|
664
|
+
*/
|
|
665
|
+
declare class EvmSigner {
|
|
666
|
+
private readonly _account;
|
|
667
|
+
/**
|
|
668
|
+
* @param privateKey - EVM private key as hex string (with or without 0x prefix) or Uint8Array
|
|
669
|
+
*/
|
|
670
|
+
constructor(privateKey: string | Uint8Array);
|
|
671
|
+
/** Derived 0x EVM address */
|
|
672
|
+
get address(): string;
|
|
673
|
+
/** Viem PrivateKeyAccount — usable with walletClient for on-chain transactions */
|
|
674
|
+
get account(): PrivateKeyAccount;
|
|
675
|
+
/**
|
|
676
|
+
* Signs a balance proof using EIP-712 typed data.
|
|
677
|
+
*
|
|
678
|
+
* @param params - Balance proof parameters plus chain context
|
|
679
|
+
* @returns Signed balance proof with signature
|
|
680
|
+
*/
|
|
681
|
+
signBalanceProof(params: BalanceProofParams & {
|
|
682
|
+
chainId: number;
|
|
683
|
+
tokenNetworkAddress: string;
|
|
684
|
+
}): Promise<SignedBalanceProof>;
|
|
685
|
+
/**
|
|
686
|
+
* Builds an EVMClaimMessage from a signed balance proof.
|
|
687
|
+
* Static so it can be called without an EvmSigner instance.
|
|
688
|
+
*
|
|
689
|
+
* @param proof - Signed balance proof
|
|
690
|
+
* @param senderId - Nostr pubkey or identifier of the sender
|
|
691
|
+
* @returns EVMClaimMessage compatible with BTP_CLAIM_PROTOCOL
|
|
692
|
+
*/
|
|
693
|
+
static buildClaimMessage(proof: SignedBalanceProof, senderId: string): EVMClaimMessage;
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
/** Pino-compatible logger interface */
|
|
697
|
+
interface ConsoleLogger {
|
|
698
|
+
level: string;
|
|
699
|
+
silent: (...args: unknown[]) => void;
|
|
700
|
+
info: typeof console.info;
|
|
701
|
+
warn: typeof console.warn;
|
|
702
|
+
error: typeof console.error;
|
|
703
|
+
debug: typeof console.debug;
|
|
704
|
+
trace: typeof console.debug;
|
|
705
|
+
fatal: typeof console.error;
|
|
706
|
+
child: () => ConsoleLogger;
|
|
707
|
+
}
|
|
708
|
+
interface BtpRuntimeClientConfig {
|
|
709
|
+
btpUrl: string;
|
|
710
|
+
peerId: string;
|
|
711
|
+
authToken: string;
|
|
712
|
+
logger?: ConsoleLogger;
|
|
713
|
+
/** Max reconnection attempts on send failure (default: 3) */
|
|
714
|
+
maxRetries?: number;
|
|
715
|
+
/** Delay between reconnection attempts in ms (default: 1000) */
|
|
716
|
+
retryDelay?: number;
|
|
717
|
+
}
|
|
718
|
+
/**
|
|
719
|
+
* BTP transport implementing IlpClient.
|
|
720
|
+
* Wraps BTPClient from @toon-protocol/connector with auto-reconnect on connection loss.
|
|
721
|
+
*/
|
|
722
|
+
declare class BtpRuntimeClient implements IlpClient {
|
|
723
|
+
private btpClient;
|
|
724
|
+
private readonly config;
|
|
725
|
+
private _isConnected;
|
|
726
|
+
private readonly logger;
|
|
727
|
+
constructor(config: BtpRuntimeClientConfig);
|
|
728
|
+
/**
|
|
729
|
+
* Connects to the BTP peer via WebSocket.
|
|
730
|
+
*/
|
|
731
|
+
connect(): Promise<void>;
|
|
732
|
+
/**
|
|
733
|
+
* Attempts to reconnect by creating a fresh BTPClient and connecting.
|
|
734
|
+
*/
|
|
735
|
+
reconnect(): Promise<void>;
|
|
736
|
+
/**
|
|
737
|
+
* Disconnects from the BTP peer.
|
|
738
|
+
*/
|
|
739
|
+
disconnect(): Promise<void>;
|
|
740
|
+
get isConnected(): boolean;
|
|
741
|
+
/**
|
|
742
|
+
* Sends an ILP packet via BTP with auto-reconnect on connection errors.
|
|
743
|
+
* Satisfies IlpClient interface.
|
|
744
|
+
*/
|
|
745
|
+
sendIlpPacket(params: {
|
|
746
|
+
destination: string;
|
|
747
|
+
amount: string;
|
|
748
|
+
data: string;
|
|
749
|
+
timeout?: number;
|
|
750
|
+
}): Promise<IlpSendResult>;
|
|
751
|
+
/**
|
|
752
|
+
* Sends a balance proof claim via BTP protocol data, then sends an ILP packet.
|
|
753
|
+
* Auto-reconnects on connection errors.
|
|
754
|
+
*/
|
|
755
|
+
sendIlpPacketWithClaim(params: {
|
|
756
|
+
destination: string;
|
|
757
|
+
amount: string;
|
|
758
|
+
data: string;
|
|
759
|
+
timeout?: number;
|
|
760
|
+
}, claim: EVMClaimMessage): Promise<IlpSendResult>;
|
|
761
|
+
/**
|
|
762
|
+
* Single-attempt ILP packet send. Reconnects if not connected.
|
|
763
|
+
*/
|
|
764
|
+
private _sendIlpPacketOnce;
|
|
765
|
+
/**
|
|
766
|
+
* Single-attempt claim + ILP packet send. Reconnects if not connected.
|
|
767
|
+
*/
|
|
768
|
+
private _sendIlpPacketWithClaimOnce;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
interface OnChainChannelClientConfig {
|
|
772
|
+
evmSigner: EvmSigner;
|
|
773
|
+
chainRpcUrls: Record<string, string>;
|
|
774
|
+
}
|
|
775
|
+
/**
|
|
776
|
+
* Implements ConnectorChannelClient using viem for direct on-chain
|
|
777
|
+
* interaction with TokenNetwork smart contract.
|
|
778
|
+
*
|
|
779
|
+
* Fully non-custodial — the client deposits its own funds on-chain.
|
|
780
|
+
*/
|
|
781
|
+
declare class OnChainChannelClient implements ConnectorChannelClient {
|
|
782
|
+
private readonly evmSigner;
|
|
783
|
+
private readonly chainRpcUrls;
|
|
784
|
+
private readonly channelContext;
|
|
785
|
+
constructor(config: OnChainChannelClientConfig);
|
|
786
|
+
/**
|
|
787
|
+
* Parse chain identifier to extract chainId.
|
|
788
|
+
* Format: "evm:{network}:{chainId}" e.g., "evm:anvil:31337"
|
|
789
|
+
*/
|
|
790
|
+
private parseChainId;
|
|
791
|
+
/**
|
|
792
|
+
* Create viem clients for a given chain.
|
|
793
|
+
*/
|
|
794
|
+
private createClients;
|
|
795
|
+
/**
|
|
796
|
+
* Opens a new payment channel on-chain.
|
|
797
|
+
*
|
|
798
|
+
* 1. Approve token spend if needed
|
|
799
|
+
* 2. Call TokenNetwork.openChannel()
|
|
800
|
+
* 3. Extract channelId from ChannelOpened event
|
|
801
|
+
* 4. Deposit initial funds if specified
|
|
802
|
+
*/
|
|
803
|
+
openChannel(params: OpenChannelParams): Promise<OpenChannelResult>;
|
|
804
|
+
/**
|
|
805
|
+
* Gets the current state of a payment channel from on-chain data.
|
|
806
|
+
*/
|
|
807
|
+
getChannelState(channelId: string): Promise<ChannelState>;
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
interface ChannelStoreEntry {
|
|
811
|
+
nonce: number;
|
|
812
|
+
cumulativeAmount: bigint;
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Persistence interface for payment channel nonce/amount state.
|
|
816
|
+
*/
|
|
817
|
+
interface ChannelStore {
|
|
818
|
+
save(channelId: string, tracking: ChannelStoreEntry): void;
|
|
819
|
+
load(channelId: string): ChannelStoreEntry | undefined;
|
|
820
|
+
list(): string[];
|
|
821
|
+
delete(channelId: string): void;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
/**
|
|
825
|
+
* Local nonce tracking and claim signing.
|
|
826
|
+
*
|
|
827
|
+
* Does NOT make any network calls — it only manages state
|
|
828
|
+
* and delegates signing to EvmSigner.
|
|
829
|
+
*/
|
|
830
|
+
declare class ChannelManager {
|
|
831
|
+
private readonly evmSigner;
|
|
832
|
+
private readonly channels;
|
|
833
|
+
private readonly store?;
|
|
834
|
+
constructor(evmSigner: EvmSigner, store?: ChannelStore);
|
|
835
|
+
/**
|
|
836
|
+
* Start tracking a channel.
|
|
837
|
+
* Called after bootstrap returns a channelId.
|
|
838
|
+
*
|
|
839
|
+
* @param channelId - Payment channel identifier
|
|
840
|
+
* @param initialNonce - Starting nonce (default: 0)
|
|
841
|
+
* @param initialAmount - Starting cumulative amount (default: 0n)
|
|
842
|
+
*/
|
|
843
|
+
trackChannel(channelId: string, initialNonce?: number, initialAmount?: bigint): void;
|
|
844
|
+
/**
|
|
845
|
+
* Signs a balance proof for the given channel.
|
|
846
|
+
* Auto-increments nonce and adds to cumulative amount.
|
|
847
|
+
*
|
|
848
|
+
* @param channelId - Payment channel identifier
|
|
849
|
+
* @param additionalAmount - Amount to add to cumulative transferred amount
|
|
850
|
+
* @returns Signed balance proof
|
|
851
|
+
* @throws Error if channel is not being tracked
|
|
852
|
+
*/
|
|
853
|
+
signBalanceProof(channelId: string, additionalAmount: bigint): Promise<SignedBalanceProof>;
|
|
854
|
+
/**
|
|
855
|
+
* Gets the current nonce for a tracked channel.
|
|
856
|
+
*/
|
|
857
|
+
getNonce(channelId: string): number;
|
|
858
|
+
/**
|
|
859
|
+
* Gets the cumulative transferred amount for a tracked channel.
|
|
860
|
+
*/
|
|
861
|
+
getCumulativeAmount(channelId: string): bigint;
|
|
862
|
+
/**
|
|
863
|
+
* Gets all tracked channel IDs.
|
|
864
|
+
*/
|
|
865
|
+
getTrackedChannels(): string[];
|
|
866
|
+
/**
|
|
867
|
+
* Returns true if the channel is being tracked.
|
|
868
|
+
*/
|
|
869
|
+
isTracking(channelId: string): boolean;
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
/**
|
|
873
|
+
* Configuration options for retry behavior with exponential backoff.
|
|
874
|
+
*/
|
|
875
|
+
interface RetryOptions {
|
|
876
|
+
/** Maximum number of retry attempts (default: 3) */
|
|
877
|
+
maxRetries: number;
|
|
878
|
+
/** Initial delay in milliseconds between retries (default: 1000) */
|
|
879
|
+
retryDelay: number;
|
|
880
|
+
/** Use exponential backoff for delays (default: true) */
|
|
881
|
+
exponentialBackoff?: boolean;
|
|
882
|
+
/** Maximum delay cap in milliseconds (default: 30000) */
|
|
883
|
+
maxDelay?: number;
|
|
884
|
+
/** Custom predicate to determine if an error should trigger a retry */
|
|
885
|
+
shouldRetry?: (error: Error) => boolean;
|
|
886
|
+
}
|
|
887
|
+
/**
|
|
888
|
+
* Executes an async operation with retry logic and exponential backoff.
|
|
889
|
+
*
|
|
890
|
+
* @param operation - The async function to execute
|
|
891
|
+
* @param options - Retry configuration options
|
|
892
|
+
* @returns The result of the successful operation
|
|
893
|
+
* @throws The last error if all retries are exhausted
|
|
894
|
+
*
|
|
895
|
+
* @example
|
|
896
|
+
* ```typescript
|
|
897
|
+
* const result = await withRetry(
|
|
898
|
+
* async () => fetchData(),
|
|
899
|
+
* {
|
|
900
|
+
* maxRetries: 3,
|
|
901
|
+
* retryDelay: 1000,
|
|
902
|
+
* shouldRetry: (err) => err.name === 'NetworkError'
|
|
903
|
+
* }
|
|
904
|
+
* );
|
|
905
|
+
* ```
|
|
906
|
+
*/
|
|
907
|
+
declare function withRetry<T>(operation: () => Promise<T>, options: RetryOptions): Promise<T>;
|
|
908
|
+
|
|
909
|
+
/**
|
|
910
|
+
* Settlement info produced by buildSettlementInfo().
|
|
911
|
+
* Extends the core SettlementConfig shape with ilpAddress for client use.
|
|
912
|
+
*/
|
|
913
|
+
interface ClientSettlementInfo {
|
|
914
|
+
ilpAddress?: string;
|
|
915
|
+
supportedChains?: string[];
|
|
916
|
+
settlementAddresses?: Record<string, string>;
|
|
917
|
+
preferredTokens?: Record<string, string>;
|
|
918
|
+
tokenNetworks?: Record<string, string>;
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* Validates ToonClient configuration.
|
|
922
|
+
*
|
|
923
|
+
* This story implements HTTP mode only. Embedded mode validation will be added in a future epic.
|
|
924
|
+
*
|
|
925
|
+
* @throws {ValidationError} If configuration is invalid
|
|
926
|
+
*/
|
|
927
|
+
declare function validateConfig(config: ToonClientConfig): void;
|
|
928
|
+
/**
|
|
929
|
+
* The resolved config type after defaults are applied.
|
|
930
|
+
* secretKey is guaranteed to be present (auto-generated if omitted).
|
|
931
|
+
*/
|
|
932
|
+
type ResolvedConfig = Required<Omit<ToonClientConfig, 'connector' | 'evmPrivateKey' | 'supportedChains' | 'settlementAddresses' | 'preferredTokens' | 'tokenNetworks' | 'btpUrl' | 'btpAuthToken' | 'btpPeerId' | 'chainRpcUrls' | 'initialDeposit' | 'settlementTimeout' | 'channelStorePath' | 'knownPeers' | 'destinationAddress'>> & {
|
|
933
|
+
connector?: unknown;
|
|
934
|
+
/** Always present after applyDefaults() — derived from secretKey if not explicitly provided */
|
|
935
|
+
evmPrivateKey: string | Uint8Array;
|
|
936
|
+
supportedChains?: string[];
|
|
937
|
+
settlementAddresses?: Record<string, string>;
|
|
938
|
+
preferredTokens?: Record<string, string>;
|
|
939
|
+
tokenNetworks?: Record<string, string>;
|
|
940
|
+
btpUrl?: string;
|
|
941
|
+
btpAuthToken?: string;
|
|
942
|
+
btpPeerId?: string;
|
|
943
|
+
chainRpcUrls?: Record<string, string>;
|
|
944
|
+
initialDeposit?: string;
|
|
945
|
+
settlementTimeout?: number;
|
|
946
|
+
channelStorePath?: string;
|
|
947
|
+
knownPeers?: {
|
|
948
|
+
pubkey: string;
|
|
949
|
+
relayUrl: string;
|
|
950
|
+
btpEndpoint?: string;
|
|
951
|
+
}[];
|
|
952
|
+
destinationAddress: string;
|
|
953
|
+
};
|
|
954
|
+
/**
|
|
955
|
+
* Applies default values to optional configuration fields.
|
|
956
|
+
* Auto-generates a Nostr keypair when secretKey is omitted.
|
|
957
|
+
* Derives btpUrl from connectorUrl when not provided.
|
|
958
|
+
*/
|
|
959
|
+
declare function applyDefaults(config: ToonClientConfig): ResolvedConfig;
|
|
960
|
+
/**
|
|
961
|
+
* Builds SettlementConfig from client config.
|
|
962
|
+
* Returns undefined if no settlement-related config is present.
|
|
963
|
+
*/
|
|
964
|
+
declare function buildSettlementInfo(config: ToonClientConfig): ClientSettlementInfo | undefined;
|
|
965
|
+
|
|
966
|
+
export { type BalanceProofParams, BtpRuntimeClient, type BtpRuntimeClientConfig, ChannelManager, ConnectorError, type EVMClaimMessage, EvmSigner, HttpConnectorAdmin, type HttpConnectorAdminConfig, HttpRuntimeClient, type HttpRuntimeClientConfig, NetworkError, OnChainChannelClient, type OnChainChannelClientConfig, type PublishEventResult, type RetryOptions, type SignedBalanceProof, ToonClient, type ToonClientConfig, ToonClientError, type ToonStartResult, ValidationError, applyDefaults, buildSettlementInfo, validateConfig, withRetry };
|