@toon-protocol/core 1.1.1
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 +25 -0
- package/dist/chunk-7AHDGE4H.js +189 -0
- package/dist/chunk-7AHDGE4H.js.map +1 -0
- package/dist/index-DSgMeweu.d.ts +104 -0
- package/dist/index.d.ts +2853 -0
- package/dist/index.js +3495 -0
- package/dist/index.js.map +1 -0
- package/dist/nip34/index.d.ts +350 -0
- package/dist/nip34/index.js +562 -0
- package/dist/nip34/index.js.map +1 -0
- package/dist/toon/index.d.ts +2 -0
- package/dist/toon/index.js +17 -0
- package/dist/toon/index.js.map +1 -0
- package/package.json +75 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,2853 @@
|
|
|
1
|
+
import { T as ToonError } from './index-DSgMeweu.js';
|
|
2
|
+
export { I as InvalidEventError, P as PeerDiscoveryError, a as ToonDecodeError, b as ToonEncodeError, c as ToonRoutingMeta, d as decodeEventFromToon, e as encodeEventToToon, f as encodeEventToToonString, s as shallowParseToon } from './index-DSgMeweu.js';
|
|
3
|
+
import { NostrEvent } from 'nostr-tools/pure';
|
|
4
|
+
import { SimplePool } from 'nostr-tools/pool';
|
|
5
|
+
import { TurboAuthenticatedClient } from '@ardrive/turbo-sdk';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Nostr event kind constants for ILP-related events.
|
|
9
|
+
*
|
|
10
|
+
* These follow the NIP convention for replaceable (10000-19999) event kinds.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* ILP Peer Info (kind 10032)
|
|
14
|
+
* Replaceable event containing connector's ILP address, BTP endpoint, and settlement info.
|
|
15
|
+
*/
|
|
16
|
+
declare const ILP_PEER_INFO_KIND = 10032;
|
|
17
|
+
/**
|
|
18
|
+
* Service Discovery (kind 10035)
|
|
19
|
+
* Replaceable event advertising a node's capabilities, pricing, and endpoints.
|
|
20
|
+
* Published to the local relay and optionally to peers so that clients and
|
|
21
|
+
* agents can programmatically discover available services.
|
|
22
|
+
* NIP-16 replaceable: relays store only the latest event per pubkey + kind.
|
|
23
|
+
*/
|
|
24
|
+
declare const SERVICE_DISCOVERY_KIND = 10035;
|
|
25
|
+
/**
|
|
26
|
+
* Seed Relay List (kind 10036)
|
|
27
|
+
* Replaceable event containing a list of relay nodes that serve as bootstrap
|
|
28
|
+
* entry points for new network participants. Published to public Nostr relays.
|
|
29
|
+
* NIP-16 replaceable: relays store only the latest event per pubkey + kind.
|
|
30
|
+
*/
|
|
31
|
+
declare const SEED_RELAY_LIST_KIND = 10036;
|
|
32
|
+
/**
|
|
33
|
+
* TEE Attestation (kind 10033)
|
|
34
|
+
* NIP-16 replaceable event containing TEE attestation data: PCR values,
|
|
35
|
+
* enclave image hash, and attestation documents from the TEE platform.
|
|
36
|
+
* Published by nodes running in a Trusted Execution Environment (e.g.,
|
|
37
|
+
* Marlin Oyster CVM / AWS Nitro Enclaves). Relays store only the latest
|
|
38
|
+
* event per pubkey + kind. No `d` tag needed -- NIP-16 replaces by
|
|
39
|
+
* pubkey + kind alone (unlike NIP-33 parameterized replaceable events).
|
|
40
|
+
*/
|
|
41
|
+
declare const TEE_ATTESTATION_KIND = 10033;
|
|
42
|
+
/**
|
|
43
|
+
* Base kind for NIP-90 DVM job requests (kind range 5000-5999).
|
|
44
|
+
* Job requests are regular (non-replaceable) events. Each specific DVM task
|
|
45
|
+
* type is assigned a unique kind within this range (e.g., 5100 for text
|
|
46
|
+
* generation). Providers listen for requests in their supported kind range.
|
|
47
|
+
*/
|
|
48
|
+
declare const JOB_REQUEST_KIND_BASE = 5000;
|
|
49
|
+
/**
|
|
50
|
+
* Base kind for NIP-90 DVM job results (kind range 6000-6999).
|
|
51
|
+
* Result kind = request kind + 1000 (e.g., Kind 5100 request -> Kind 6100
|
|
52
|
+
* result). Result events reference the original request via an `e` tag and
|
|
53
|
+
* include the compute cost in an `amount` tag.
|
|
54
|
+
*/
|
|
55
|
+
declare const JOB_RESULT_KIND_BASE = 6000;
|
|
56
|
+
/**
|
|
57
|
+
* NIP-90 DVM job feedback (kind 7000).
|
|
58
|
+
* A single kind used for all feedback messages (processing, error, success,
|
|
59
|
+
* partial). Feedback events reference the original request via an `e` tag
|
|
60
|
+
* and carry a `status` tag indicating the current job state.
|
|
61
|
+
*/
|
|
62
|
+
declare const JOB_FEEDBACK_KIND = 7000;
|
|
63
|
+
/**
|
|
64
|
+
* Text Generation DVM kind (kind 5100).
|
|
65
|
+
* Reference DVM kind for the TOON protocol. Used for general-purpose
|
|
66
|
+
* text generation tasks (e.g., LLM inference, summarization, Q&A).
|
|
67
|
+
*/
|
|
68
|
+
declare const TEXT_GENERATION_KIND = 5100;
|
|
69
|
+
/**
|
|
70
|
+
* Image Generation DVM kind (kind 5200).
|
|
71
|
+
* Used for image generation tasks (e.g., text-to-image, image editing).
|
|
72
|
+
* Optional provider support -- not all nodes are required to handle this kind.
|
|
73
|
+
*/
|
|
74
|
+
declare const IMAGE_GENERATION_KIND = 5200;
|
|
75
|
+
/**
|
|
76
|
+
* Text-to-Speech DVM kind (kind 5300).
|
|
77
|
+
* Used for text-to-speech conversion tasks.
|
|
78
|
+
* Optional provider support -- not all nodes are required to handle this kind.
|
|
79
|
+
*/
|
|
80
|
+
declare const TEXT_TO_SPEECH_KIND = 5300;
|
|
81
|
+
/**
|
|
82
|
+
* Translation DVM kind (kind 5302).
|
|
83
|
+
* Used for language translation tasks.
|
|
84
|
+
* Optional provider support -- not all nodes are required to handle this kind.
|
|
85
|
+
*/
|
|
86
|
+
declare const TRANSLATION_KIND = 5302;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* TypeScript interfaces for ILP-related Nostr events.
|
|
90
|
+
*/
|
|
91
|
+
/**
|
|
92
|
+
* ILP Peer Info - Published as kind 10032 event.
|
|
93
|
+
* Contains information needed to establish an ILP peering relationship.
|
|
94
|
+
*/
|
|
95
|
+
interface IlpPeerInfo {
|
|
96
|
+
/** Nostr pubkey of the peer (64-char hex) */
|
|
97
|
+
pubkey?: string;
|
|
98
|
+
/** ILP address of the peer's connector (e.g., "g.example.connector") */
|
|
99
|
+
ilpAddress: string;
|
|
100
|
+
/** BTP WebSocket endpoint URL for packet exchange */
|
|
101
|
+
btpEndpoint: string;
|
|
102
|
+
/** Optional BLS HTTP endpoint for direct packet delivery (bootstrap only) */
|
|
103
|
+
blsHttpEndpoint?: string;
|
|
104
|
+
/** @deprecated Use supportedChains instead. Kept for backward compatibility. */
|
|
105
|
+
settlementEngine?: string;
|
|
106
|
+
/** Asset code for the peering relationship (e.g., "USD", "XRP") */
|
|
107
|
+
assetCode: string;
|
|
108
|
+
/** Asset scale - number of decimal places (e.g., 9 for XRP, 6 for USD cents) */
|
|
109
|
+
assetScale: number;
|
|
110
|
+
/** Supported settlement chain identifiers in {blockchain}:{network}:{chainId} format (e.g., ["evm:base:8453", "xrp:mainnet"]) */
|
|
111
|
+
supportedChains?: string[];
|
|
112
|
+
/** Maps chain identifier to the peer's settlement address on that chain */
|
|
113
|
+
settlementAddresses?: Record<string, string>;
|
|
114
|
+
/** Maps chain identifier to preferred token contract address */
|
|
115
|
+
preferredTokens?: Record<string, string>;
|
|
116
|
+
/** Maps chain identifier to TokenNetwork contract address (EVM-specific) */
|
|
117
|
+
tokenNetworks?: Record<string, string>;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Subscription handle for real-time event updates.
|
|
121
|
+
* Returned by subscription methods to allow cleanup.
|
|
122
|
+
*/
|
|
123
|
+
interface Subscription {
|
|
124
|
+
/** Stops receiving updates and closes the underlying relay subscription */
|
|
125
|
+
unsubscribe(): void;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Parameters for opening a payment channel via the connector Admin API.
|
|
129
|
+
*/
|
|
130
|
+
interface OpenChannelParams {
|
|
131
|
+
/** Connector peer identifier */
|
|
132
|
+
peerId: string;
|
|
133
|
+
/** Settlement chain identifier (e.g., "evm:base:8453") */
|
|
134
|
+
chain: string;
|
|
135
|
+
/** Token contract address on the chain */
|
|
136
|
+
token?: string;
|
|
137
|
+
/** TokenNetwork contract address (EVM-specific) */
|
|
138
|
+
tokenNetwork?: string;
|
|
139
|
+
/** Peer's settlement address on the chain */
|
|
140
|
+
peerAddress: string;
|
|
141
|
+
/** Initial deposit amount */
|
|
142
|
+
initialDeposit?: string;
|
|
143
|
+
/** Challenge period in seconds */
|
|
144
|
+
settlementTimeout?: number;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Result of opening a payment channel.
|
|
148
|
+
*/
|
|
149
|
+
interface OpenChannelResult {
|
|
150
|
+
/** Unique channel identifier */
|
|
151
|
+
channelId: string;
|
|
152
|
+
/** Channel status after open request */
|
|
153
|
+
status: string;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* State of a payment channel from the connector.
|
|
157
|
+
*/
|
|
158
|
+
interface ChannelState {
|
|
159
|
+
/** Unique channel identifier */
|
|
160
|
+
channelId: string;
|
|
161
|
+
/** Current channel status */
|
|
162
|
+
status: 'opening' | 'open' | 'closed' | 'settled';
|
|
163
|
+
/** Settlement chain identifier */
|
|
164
|
+
chain: string;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* TEE Attestation content for kind:10033 events (Pattern 14).
|
|
168
|
+
* Contains attestation data from a Trusted Execution Environment.
|
|
169
|
+
*/
|
|
170
|
+
interface TeeAttestation {
|
|
171
|
+
/** Enclave type identifier (e.g., 'aws-nitro', 'marlin-oyster'). */
|
|
172
|
+
enclave: string;
|
|
173
|
+
/** Platform Configuration Register 0 (SHA-384 hex, 96 chars). */
|
|
174
|
+
pcr0: string;
|
|
175
|
+
/** Platform Configuration Register 1 (SHA-384 hex, 96 chars). */
|
|
176
|
+
pcr1: string;
|
|
177
|
+
/** Platform Configuration Register 2 (SHA-384 hex, 96 chars). */
|
|
178
|
+
pcr2: string;
|
|
179
|
+
/** Base64-encoded attestation document from the TEE platform. */
|
|
180
|
+
attestationDoc: string;
|
|
181
|
+
/** Attestation format version. */
|
|
182
|
+
version: string;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Interface for interacting with the connector's channel Admin API.
|
|
186
|
+
* Abstracts POST /admin/channels and GET /admin/channels/:channelId.
|
|
187
|
+
*/
|
|
188
|
+
interface ConnectorChannelClient {
|
|
189
|
+
/** Opens a new payment channel via POST /admin/channels */
|
|
190
|
+
openChannel(params: OpenChannelParams): Promise<OpenChannelResult>;
|
|
191
|
+
/** Gets channel state via GET /admin/channels/:channelId */
|
|
192
|
+
getChannelState(channelId: string): Promise<ChannelState>;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Parsers for ILP-related Nostr events.
|
|
197
|
+
*/
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Validates a chain identifier string.
|
|
201
|
+
* Valid format: {blockchain}:{network} or {blockchain}:{network}:{chainId}
|
|
202
|
+
* Minimum 2 segments, maximum 3, separated by `:`. All segments must be non-empty.
|
|
203
|
+
*
|
|
204
|
+
* @param chainId - The chain identifier to validate
|
|
205
|
+
* @returns true if the chain identifier is valid
|
|
206
|
+
*/
|
|
207
|
+
declare function validateChainId(chainId: string): boolean;
|
|
208
|
+
/**
|
|
209
|
+
* Parses a kind:10032 Nostr event into an IlpPeerInfo object.
|
|
210
|
+
*
|
|
211
|
+
* @param event - The Nostr event to parse
|
|
212
|
+
* @returns The parsed IlpPeerInfo object
|
|
213
|
+
* @throws InvalidEventError if the event is malformed or missing required fields
|
|
214
|
+
*/
|
|
215
|
+
declare function parseIlpPeerInfo(event: NostrEvent): IlpPeerInfo;
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Builders for ILP-related Nostr events.
|
|
219
|
+
*/
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Builds and signs a kind:10032 Nostr event from IlpPeerInfo data.
|
|
223
|
+
*
|
|
224
|
+
* @param info - The ILP peer info to serialize into the event
|
|
225
|
+
* @param secretKey - The secret key to sign the event with
|
|
226
|
+
* @returns A signed Nostr event
|
|
227
|
+
*/
|
|
228
|
+
declare function buildIlpPeerInfoEvent(info: IlpPeerInfo, secretKey: Uint8Array): NostrEvent;
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Event builder and parser for kind:10036 Seed Relay List events.
|
|
232
|
+
*
|
|
233
|
+
* Kind 10036 is a NIP-16 replaceable event (kind 10000-19999) published to
|
|
234
|
+
* public Nostr relays. Relays store only the latest event per `pubkey + kind`.
|
|
235
|
+
* The `d` tag with value `toon-seed-list` is included as a content marker
|
|
236
|
+
* for filtering.
|
|
237
|
+
*
|
|
238
|
+
* Seed relay list events advertise relay nodes that can serve as bootstrap
|
|
239
|
+
* entry points for new network participants.
|
|
240
|
+
*/
|
|
241
|
+
|
|
242
|
+
/** Content payload for a kind:10036 Seed Relay List event. */
|
|
243
|
+
interface SeedRelayEntry {
|
|
244
|
+
/** WebSocket URL of the relay (wss:// for production, ws:// for dev). */
|
|
245
|
+
url: string;
|
|
246
|
+
/** Nostr pubkey of the relay operator (64-char lowercase hex). */
|
|
247
|
+
pubkey: string;
|
|
248
|
+
/** Optional metadata. */
|
|
249
|
+
metadata?: {
|
|
250
|
+
region?: string;
|
|
251
|
+
version?: string;
|
|
252
|
+
services?: string[];
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Builds a kind:10036 Seed Relay List event (NIP-16 replaceable).
|
|
257
|
+
* Uses 'd' tag with value 'toon-seed-list' for replaceable event pattern.
|
|
258
|
+
*
|
|
259
|
+
* @param secretKey - The secret key to sign the event with.
|
|
260
|
+
* @param entries - The seed relay entries to include.
|
|
261
|
+
* @returns A signed Nostr event.
|
|
262
|
+
*/
|
|
263
|
+
declare function buildSeedRelayListEvent(secretKey: Uint8Array, entries: SeedRelayEntry[]): NostrEvent;
|
|
264
|
+
/**
|
|
265
|
+
* Parses a kind:10036 event content into SeedRelayEntry[].
|
|
266
|
+
* Validates URLs (WebSocket scheme prefix) and pubkeys (64-char hex).
|
|
267
|
+
* Malformed entries are silently skipped (graceful degradation).
|
|
268
|
+
*
|
|
269
|
+
* @param event - The Nostr event to parse.
|
|
270
|
+
* @returns An array of valid SeedRelayEntry objects.
|
|
271
|
+
*/
|
|
272
|
+
declare function parseSeedRelayList(event: NostrEvent): SeedRelayEntry[];
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Event builder and parser for kind:10035 Service Discovery events.
|
|
276
|
+
*
|
|
277
|
+
* Kind 10035 is a NIP-16 replaceable event (kind 10000-19999) published to
|
|
278
|
+
* the local relay and optionally to peers. Relays store only the latest event
|
|
279
|
+
* per `pubkey + kind`. The `d` tag with value `toon-service-discovery` is
|
|
280
|
+
* included as a content marker for filtering.
|
|
281
|
+
*
|
|
282
|
+
* Service discovery events advertise a node's capabilities, pricing, and
|
|
283
|
+
* endpoints so that clients and AI agents can programmatically discover
|
|
284
|
+
* available services.
|
|
285
|
+
*/
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Structured skill descriptor for DVM service discovery.
|
|
289
|
+
*
|
|
290
|
+
* Embedded in kind:10035 events to advertise DVM capabilities.
|
|
291
|
+
* Enables programmatic agent-to-agent service discovery: agents
|
|
292
|
+
* can read `inputSchema` to construct valid Kind 5xxx job requests
|
|
293
|
+
* without prior knowledge of the provider's capabilities.
|
|
294
|
+
*
|
|
295
|
+
* The `attestation` field is a placeholder for Epic 6 TEE integration
|
|
296
|
+
* (Story 6.3: TEE-attested DVM results).
|
|
297
|
+
*/
|
|
298
|
+
interface SkillDescriptor {
|
|
299
|
+
/** Service identifier (e.g., 'toon-dvm'). */
|
|
300
|
+
name: string;
|
|
301
|
+
/** Schema version (e.g., '1.0'). */
|
|
302
|
+
version: string;
|
|
303
|
+
/** Supported DVM Kind 5xxx numbers (e.g., [5100, 5200]). */
|
|
304
|
+
kinds: number[];
|
|
305
|
+
/** Capability list (e.g., ['text-generation', 'streaming']). */
|
|
306
|
+
features: string[];
|
|
307
|
+
/** JSON Schema draft-07 object describing job request parameters. */
|
|
308
|
+
inputSchema: Record<string, unknown>;
|
|
309
|
+
/** Kind number (as string) -> USDC micro-units cost (as string). */
|
|
310
|
+
pricing: Record<string, string>;
|
|
311
|
+
/** Available AI models (e.g., ['gpt-4', 'claude-3']). */
|
|
312
|
+
models?: string[];
|
|
313
|
+
/** Placeholder for Epic 6 TEE attestation integration. */
|
|
314
|
+
attestation?: Record<string, unknown>;
|
|
315
|
+
}
|
|
316
|
+
/** Content payload for a kind:10035 Service Discovery event. */
|
|
317
|
+
interface ServiceDiscoveryContent {
|
|
318
|
+
/** Service type identifier (e.g., 'relay', 'rig'). */
|
|
319
|
+
serviceType: string;
|
|
320
|
+
/** ILP address of the node's connector. */
|
|
321
|
+
ilpAddress: string;
|
|
322
|
+
/** Pricing configuration. */
|
|
323
|
+
pricing: {
|
|
324
|
+
/** Base price per byte in smallest token unit. */
|
|
325
|
+
basePricePerByte: number;
|
|
326
|
+
/** Payment token symbol (e.g., 'USDC'). */
|
|
327
|
+
currency: string;
|
|
328
|
+
};
|
|
329
|
+
/**
|
|
330
|
+
* x402 endpoint configuration.
|
|
331
|
+
* Omitted entirely when x402 is disabled (not set to `{ enabled: false }`).
|
|
332
|
+
*/
|
|
333
|
+
x402?: {
|
|
334
|
+
/** Whether x402 is enabled. */
|
|
335
|
+
enabled: boolean;
|
|
336
|
+
/** HTTP endpoint path (e.g., '/publish'). */
|
|
337
|
+
endpoint?: string;
|
|
338
|
+
};
|
|
339
|
+
/** Nostr event kinds this node accepts for storage. */
|
|
340
|
+
supportedKinds: number[];
|
|
341
|
+
/** Capabilities advertised by this node (e.g., ['relay', 'x402']). */
|
|
342
|
+
capabilities: string[];
|
|
343
|
+
/** Chain preset name (e.g., 'anvil', 'arbitrum-one'). */
|
|
344
|
+
chain: string;
|
|
345
|
+
/** Node software version. */
|
|
346
|
+
version: string;
|
|
347
|
+
/**
|
|
348
|
+
* Optional DVM skill descriptor.
|
|
349
|
+
* Present when the node has DVM handlers registered; omitted otherwise
|
|
350
|
+
* (backward compatible with pre-DVM kind:10035 events).
|
|
351
|
+
*/
|
|
352
|
+
skill?: SkillDescriptor;
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Builds a kind:10035 Service Discovery event (NIP-16 replaceable).
|
|
356
|
+
* Kind 10035 is in the 10000-19999 replaceable range (NIP-16).
|
|
357
|
+
* Relays store only the latest event per pubkey + kind.
|
|
358
|
+
* Includes 'd' tag with value 'toon-service-discovery' as a content marker.
|
|
359
|
+
*
|
|
360
|
+
* @param content - The service discovery payload.
|
|
361
|
+
* @param secretKey - The secret key to sign the event with.
|
|
362
|
+
* @returns A signed Nostr event.
|
|
363
|
+
*/
|
|
364
|
+
declare function buildServiceDiscoveryEvent(content: ServiceDiscoveryContent, secretKey: Uint8Array): NostrEvent;
|
|
365
|
+
/**
|
|
366
|
+
* Parses a kind:10035 event content into ServiceDiscoveryContent.
|
|
367
|
+
* Validates required fields. Returns null for malformed content.
|
|
368
|
+
*
|
|
369
|
+
* @param event - The Nostr event to parse.
|
|
370
|
+
* @returns The parsed content, or null if invalid.
|
|
371
|
+
*/
|
|
372
|
+
declare function parseServiceDiscovery(event: NostrEvent): ServiceDiscoveryContent | null;
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Event builder and parser for kind:10033 TEE Attestation events.
|
|
376
|
+
*
|
|
377
|
+
* Kind 10033 is a NIP-16 replaceable event (kind 10000-19999) published by
|
|
378
|
+
* nodes running in a Trusted Execution Environment (TEE). Relays store only
|
|
379
|
+
* the latest event per `pubkey + kind`. No `d` tag is needed -- NIP-16
|
|
380
|
+
* replaces by pubkey + kind alone (unlike NIP-33 parameterized replaceable
|
|
381
|
+
* events in the 30000-39999 range).
|
|
382
|
+
*
|
|
383
|
+
* TEE attestation events contain PCR measurements, enclave type, and the
|
|
384
|
+
* base64-encoded attestation document from the TEE platform (e.g., AWS Nitro
|
|
385
|
+
* Enclaves via Marlin Oyster CVM).
|
|
386
|
+
*
|
|
387
|
+
* Content format (Pattern 14):
|
|
388
|
+
* ```json
|
|
389
|
+
* {
|
|
390
|
+
* "enclave": "marlin-oyster",
|
|
391
|
+
* "pcr0": "<sha384-hex-96-chars>",
|
|
392
|
+
* "pcr1": "<sha384-hex-96-chars>",
|
|
393
|
+
* "pcr2": "<sha384-hex-96-chars>",
|
|
394
|
+
* "attestationDoc": "<base64-encoded>",
|
|
395
|
+
* "version": "1.0.0"
|
|
396
|
+
* }
|
|
397
|
+
* ```
|
|
398
|
+
*
|
|
399
|
+
* Tags: ['relay', url], ['chain', chainId], ['expiry', unixTimestamp]
|
|
400
|
+
*/
|
|
401
|
+
|
|
402
|
+
/** Options for building a kind:10033 attestation event. */
|
|
403
|
+
interface AttestationEventOptions {
|
|
404
|
+
/** WebSocket URL where this relay can be reached. */
|
|
405
|
+
relay: string;
|
|
406
|
+
/** Chain identifier (e.g., '42161' for Arbitrum One). */
|
|
407
|
+
chain: string;
|
|
408
|
+
/** Unix timestamp when this attestation expires. */
|
|
409
|
+
expiry: number;
|
|
410
|
+
}
|
|
411
|
+
/** Parsed result from a kind:10033 attestation event. */
|
|
412
|
+
interface ParsedAttestation {
|
|
413
|
+
/** The attestation content fields. */
|
|
414
|
+
attestation: TeeAttestation;
|
|
415
|
+
/** WebSocket relay URL from the 'relay' tag. */
|
|
416
|
+
relay: string;
|
|
417
|
+
/** Chain identifier from the 'chain' tag. */
|
|
418
|
+
chain: string;
|
|
419
|
+
/** Expiry unix timestamp from the 'expiry' tag. */
|
|
420
|
+
expiry: number;
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Builds a kind:10033 TEE Attestation event (NIP-16 replaceable).
|
|
424
|
+
*
|
|
425
|
+
* Content is `JSON.stringify(attestation)` per enforcement guideline 11.
|
|
426
|
+
* Tags include relay, chain, and expiry. No `d` tag is included -- NIP-16
|
|
427
|
+
* replaces by pubkey + kind alone.
|
|
428
|
+
*
|
|
429
|
+
* @param attestation - The TEE attestation content payload.
|
|
430
|
+
* @param secretKey - The secret key to sign the event with.
|
|
431
|
+
* @param options - Event options (relay URL, chain ID, expiry timestamp).
|
|
432
|
+
* @returns A signed Nostr event.
|
|
433
|
+
*/
|
|
434
|
+
declare function buildAttestationEvent(attestation: TeeAttestation, secretKey: Uint8Array, options: AttestationEventOptions): NostrEvent;
|
|
435
|
+
/**
|
|
436
|
+
* Parses a kind:10033 event into a ParsedAttestation.
|
|
437
|
+
*
|
|
438
|
+
* Validates required content fields (enclave, pcr0-2, attestationDoc, version)
|
|
439
|
+
* and required tags (relay, chain, expiry). Returns `null` for malformed or
|
|
440
|
+
* missing data.
|
|
441
|
+
*
|
|
442
|
+
* When `options.verify` is `true`, performs strict validation:
|
|
443
|
+
* - PCR values must be 96-char lowercase hex (SHA-384)
|
|
444
|
+
* - attestationDoc must be non-empty valid base64
|
|
445
|
+
* Throws on invalid data when verify=true (adversarial input gate).
|
|
446
|
+
*
|
|
447
|
+
* @param event - The Nostr event to parse.
|
|
448
|
+
* @param options - Optional parse options. `verify: true` enables strict validation.
|
|
449
|
+
* @returns The parsed attestation, or null if invalid.
|
|
450
|
+
*/
|
|
451
|
+
declare function parseAttestation(event: NostrEvent, options?: {
|
|
452
|
+
verify?: boolean;
|
|
453
|
+
}): ParsedAttestation | null;
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Event builders and parsers for NIP-90 DVM (Data Vending Machine) events.
|
|
457
|
+
*
|
|
458
|
+
* NIP-90 defines three event categories for the DVM protocol:
|
|
459
|
+
* - Kind 5000-5999: Job requests (each task type has a unique kind)
|
|
460
|
+
* - Kind 6000-6999: Job results (result kind = request kind + 1000)
|
|
461
|
+
* - Kind 7000: Job feedback (single kind for all status updates)
|
|
462
|
+
*
|
|
463
|
+
* TOON adopts NIP-90 kinds for cross-network interoperability with the
|
|
464
|
+
* broader Nostr DVM ecosystem. The `bid` and `amount` tags extend NIP-90
|
|
465
|
+
* with a third element ('usdc') for explicit currency declaration. NIP-90
|
|
466
|
+
* uses satoshis; TOON uses USDC micro-units (6 decimals).
|
|
467
|
+
*
|
|
468
|
+
* DVM events are standard Nostr events with specific kinds. They flow
|
|
469
|
+
* through the same SDK processing pipeline as all other events: shallow
|
|
470
|
+
* parse -> verify -> price -> dispatch. No special-casing required.
|
|
471
|
+
*
|
|
472
|
+
* Tag reference:
|
|
473
|
+
*
|
|
474
|
+
* Kind 5xxx (Job Request):
|
|
475
|
+
* Required: ['i', data, type, relay?, marker?], ['bid', amount, 'usdc'], ['output', mimeType]
|
|
476
|
+
* Optional: ['p', providerPubkey], ['param', key, value], ['relays', url1, ...]
|
|
477
|
+
*
|
|
478
|
+
* Kind 6xxx (Job Result):
|
|
479
|
+
* Required: ['e', requestEventId], ['p', customerPubkey], ['amount', cost, 'usdc']
|
|
480
|
+
* Content: result data
|
|
481
|
+
*
|
|
482
|
+
* Kind 7000 (Job Feedback):
|
|
483
|
+
* Required: ['e', requestEventId], ['p', customerPubkey], ['status', statusValue]
|
|
484
|
+
* Content: optional status details
|
|
485
|
+
*/
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* DVM job status values per NIP-90.
|
|
489
|
+
* - `'processing'`: Job is currently being processed.
|
|
490
|
+
* - `'error'`: Job failed with an error.
|
|
491
|
+
* - `'success'`: Job completed successfully.
|
|
492
|
+
* - `'partial'`: Job returned partial results (more to come).
|
|
493
|
+
*/
|
|
494
|
+
type DvmJobStatus = 'processing' | 'error' | 'success' | 'partial';
|
|
495
|
+
/**
|
|
496
|
+
* Parameters for building a Kind 5xxx DVM job request event.
|
|
497
|
+
*
|
|
498
|
+
* The `kind` field must be in the 5000-5999 range (NIP-90 job request range).
|
|
499
|
+
* The `bid` field is the amount the requester is willing to pay, expressed as
|
|
500
|
+
* a string of USDC micro-units (6 decimals) for bigint compatibility.
|
|
501
|
+
*/
|
|
502
|
+
interface JobRequestParams {
|
|
503
|
+
/** Event kind in 5000-5999 range (e.g., 5100 for text generation). */
|
|
504
|
+
kind: number;
|
|
505
|
+
/** Input data with type classification. */
|
|
506
|
+
input: {
|
|
507
|
+
/** The input data (text, URL, event ID, etc.). */
|
|
508
|
+
data: string;
|
|
509
|
+
/** Input type identifier (e.g., 'text', 'url', 'event', 'job'). */
|
|
510
|
+
type: string;
|
|
511
|
+
/** Optional relay URL where the input data can be found. */
|
|
512
|
+
relay?: string;
|
|
513
|
+
/** Optional marker for input disambiguation. */
|
|
514
|
+
marker?: string;
|
|
515
|
+
};
|
|
516
|
+
/** Bid amount in USDC micro-units as string (bigint-compatible). */
|
|
517
|
+
bid: string;
|
|
518
|
+
/** Expected output MIME type (e.g., 'text/plain', 'image/png'). */
|
|
519
|
+
output: string;
|
|
520
|
+
/** Optional body text for the event content field. */
|
|
521
|
+
content?: string;
|
|
522
|
+
/** Optional 64-char hex pubkey of a specific target provider. */
|
|
523
|
+
targetProvider?: string;
|
|
524
|
+
/** Optional key-value parameters for the job (repeatable). */
|
|
525
|
+
params?: {
|
|
526
|
+
key: string;
|
|
527
|
+
value: string;
|
|
528
|
+
}[];
|
|
529
|
+
/** Optional preferred relay URLs for result delivery. */
|
|
530
|
+
relays?: string[];
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* Parameters for building a Kind 6xxx DVM job result event.
|
|
534
|
+
*
|
|
535
|
+
* The `kind` field must be in the 6000-6999 range. Result kind = request
|
|
536
|
+
* kind + 1000 (e.g., Kind 5100 request -> Kind 6100 result).
|
|
537
|
+
* The `amount` field is the actual compute cost in USDC micro-units.
|
|
538
|
+
*/
|
|
539
|
+
interface JobResultParams {
|
|
540
|
+
/** Event kind in 6000-6999 range (= request kind + 1000). */
|
|
541
|
+
kind: number;
|
|
542
|
+
/** 64-char hex event ID of the original Kind 5xxx request. */
|
|
543
|
+
requestEventId: string;
|
|
544
|
+
/** 64-char hex pubkey of the customer who posted the request. */
|
|
545
|
+
customerPubkey: string;
|
|
546
|
+
/** Compute cost in USDC micro-units as string (bigint-compatible). */
|
|
547
|
+
amount: string;
|
|
548
|
+
/** Result data (text, URL, etc.). */
|
|
549
|
+
content: string;
|
|
550
|
+
}
|
|
551
|
+
/**
|
|
552
|
+
* Parameters for building a Kind 7000 DVM job feedback event.
|
|
553
|
+
*
|
|
554
|
+
* Feedback events carry status updates about in-progress jobs. The `status`
|
|
555
|
+
* field must be one of the four NIP-90 status values.
|
|
556
|
+
*/
|
|
557
|
+
interface JobFeedbackParams {
|
|
558
|
+
/** 64-char hex event ID of the original Kind 5xxx request. */
|
|
559
|
+
requestEventId: string;
|
|
560
|
+
/** 64-char hex pubkey of the customer who posted the request. */
|
|
561
|
+
customerPubkey: string;
|
|
562
|
+
/** Job status value. */
|
|
563
|
+
status: DvmJobStatus;
|
|
564
|
+
/** Optional status details or error message. */
|
|
565
|
+
content?: string;
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Parsed result from a Kind 5xxx DVM job request event.
|
|
569
|
+
*/
|
|
570
|
+
interface ParsedJobRequest {
|
|
571
|
+
/** Event kind (5000-5999). */
|
|
572
|
+
kind: number;
|
|
573
|
+
/** Input data with type classification. */
|
|
574
|
+
input: {
|
|
575
|
+
/** The input data. */
|
|
576
|
+
data: string;
|
|
577
|
+
/** Input type identifier. */
|
|
578
|
+
type: string;
|
|
579
|
+
/** Optional relay URL. */
|
|
580
|
+
relay?: string;
|
|
581
|
+
/** Optional marker. */
|
|
582
|
+
marker?: string;
|
|
583
|
+
};
|
|
584
|
+
/** Bid amount in USDC micro-units as string. */
|
|
585
|
+
bid: string;
|
|
586
|
+
/** Expected output MIME type. */
|
|
587
|
+
output: string;
|
|
588
|
+
/** Event content field (may be empty string). */
|
|
589
|
+
content: string;
|
|
590
|
+
/** Target provider pubkey if this is a targeted request. */
|
|
591
|
+
targetProvider?: string;
|
|
592
|
+
/** Key-value parameters (may be empty array). */
|
|
593
|
+
params: {
|
|
594
|
+
key: string;
|
|
595
|
+
value: string;
|
|
596
|
+
}[];
|
|
597
|
+
/** Preferred relay URLs (may be empty array). */
|
|
598
|
+
relays: string[];
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* Parsed result from a Kind 6xxx DVM job result event.
|
|
602
|
+
*/
|
|
603
|
+
interface ParsedJobResult {
|
|
604
|
+
/** Event kind (6000-6999). */
|
|
605
|
+
kind: number;
|
|
606
|
+
/** Event ID of the original request. */
|
|
607
|
+
requestEventId: string;
|
|
608
|
+
/** Pubkey of the customer who posted the request. */
|
|
609
|
+
customerPubkey: string;
|
|
610
|
+
/** Compute cost in USDC micro-units as string. */
|
|
611
|
+
amount: string;
|
|
612
|
+
/** Result data from the content field. */
|
|
613
|
+
content: string;
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* Parsed result from a Kind 7000 DVM job feedback event.
|
|
617
|
+
*/
|
|
618
|
+
interface ParsedJobFeedback {
|
|
619
|
+
/** Event ID of the original request. */
|
|
620
|
+
requestEventId: string;
|
|
621
|
+
/** Pubkey of the customer who posted the request. */
|
|
622
|
+
customerPubkey: string;
|
|
623
|
+
/** Job status value. */
|
|
624
|
+
status: DvmJobStatus;
|
|
625
|
+
/** Status details from the content field (may be empty string). */
|
|
626
|
+
content: string;
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Builds a Kind 5xxx DVM job request event (NIP-90).
|
|
630
|
+
*
|
|
631
|
+
* Constructs a signed Nostr event with NIP-90 required tags: `i` (input),
|
|
632
|
+
* `bid` (payment offer), and `output` (expected MIME type). Optional tags
|
|
633
|
+
* include `p` (target provider), `param` (key-value pairs), and `relays`
|
|
634
|
+
* (preferred relay URLs).
|
|
635
|
+
*
|
|
636
|
+
* @param params - The job request parameters.
|
|
637
|
+
* @param secretKey - The secret key to sign the event with.
|
|
638
|
+
* @returns A signed Nostr event.
|
|
639
|
+
* @throws ToonError if required params are missing or kind is out of range.
|
|
640
|
+
*/
|
|
641
|
+
declare function buildJobRequestEvent(params: JobRequestParams, secretKey: Uint8Array): NostrEvent;
|
|
642
|
+
/**
|
|
643
|
+
* Builds a Kind 6xxx DVM job result event (NIP-90).
|
|
644
|
+
*
|
|
645
|
+
* Constructs a signed Nostr event with NIP-90 required tags: `e` (request
|
|
646
|
+
* reference), `p` (customer pubkey), and `amount` (compute cost). The
|
|
647
|
+
* content field carries the result data.
|
|
648
|
+
*
|
|
649
|
+
* @param params - The job result parameters.
|
|
650
|
+
* @param secretKey - The secret key to sign the event with.
|
|
651
|
+
* @returns A signed Nostr event.
|
|
652
|
+
* @throws ToonError if required params are missing or kind is out of range.
|
|
653
|
+
*/
|
|
654
|
+
declare function buildJobResultEvent(params: JobResultParams, secretKey: Uint8Array): NostrEvent;
|
|
655
|
+
/**
|
|
656
|
+
* Builds a Kind 7000 DVM job feedback event (NIP-90).
|
|
657
|
+
*
|
|
658
|
+
* Constructs a signed Nostr event with NIP-90 required tags: `e` (request
|
|
659
|
+
* reference), `p` (customer pubkey), and `status` (job state). The content
|
|
660
|
+
* field carries optional status details or error messages.
|
|
661
|
+
*
|
|
662
|
+
* @param params - The job feedback parameters.
|
|
663
|
+
* @param secretKey - The secret key to sign the event with.
|
|
664
|
+
* @returns A signed Nostr event.
|
|
665
|
+
* @throws ToonError if required params are missing or status is invalid.
|
|
666
|
+
*/
|
|
667
|
+
declare function buildJobFeedbackEvent(params: JobFeedbackParams, secretKey: Uint8Array): NostrEvent;
|
|
668
|
+
/**
|
|
669
|
+
* Parses a Kind 5xxx event into a ParsedJobRequest.
|
|
670
|
+
*
|
|
671
|
+
* Validates the event kind is in the 5000-5999 range and extracts required
|
|
672
|
+
* NIP-90 tags: `i` (input), `bid` (amount + currency), and `output` (MIME
|
|
673
|
+
* type). Also extracts optional tags: `p` (target provider), `param`
|
|
674
|
+
* (key-value pairs), and `relays` (preferred URLs).
|
|
675
|
+
*
|
|
676
|
+
* Returns `null` for malformed events (missing required tags, invalid kind
|
|
677
|
+
* range). Follows the lenient parse pattern established by
|
|
678
|
+
* `parseServiceDiscovery()` and `parseAttestation()`.
|
|
679
|
+
*
|
|
680
|
+
* @param event - The Nostr event to parse.
|
|
681
|
+
* @returns The parsed job request, or null if invalid.
|
|
682
|
+
*/
|
|
683
|
+
declare function parseJobRequest(event: NostrEvent): ParsedJobRequest | null;
|
|
684
|
+
/**
|
|
685
|
+
* Parses a Kind 6xxx event into a ParsedJobResult.
|
|
686
|
+
*
|
|
687
|
+
* Validates the event kind is in the 6000-6999 range and extracts required
|
|
688
|
+
* NIP-90 tags: `e` (request event ID), `p` (customer pubkey), and `amount`
|
|
689
|
+
* (compute cost + currency).
|
|
690
|
+
*
|
|
691
|
+
* Returns `null` for malformed events. Follows the lenient parse pattern.
|
|
692
|
+
*
|
|
693
|
+
* @param event - The Nostr event to parse.
|
|
694
|
+
* @returns The parsed job result, or null if invalid.
|
|
695
|
+
*/
|
|
696
|
+
declare function parseJobResult(event: NostrEvent): ParsedJobResult | null;
|
|
697
|
+
/**
|
|
698
|
+
* Parses a Kind 7000 event into a ParsedJobFeedback.
|
|
699
|
+
*
|
|
700
|
+
* Validates the event kind is exactly 7000 and extracts required NIP-90
|
|
701
|
+
* tags: `e` (request event ID), `p` (customer pubkey), and `status`
|
|
702
|
+
* (job state). The status value must be one of: `'processing'`, `'error'`,
|
|
703
|
+
* `'success'`, `'partial'`.
|
|
704
|
+
*
|
|
705
|
+
* Returns `null` for malformed events or invalid status values.
|
|
706
|
+
* Follows the lenient parse pattern.
|
|
707
|
+
*
|
|
708
|
+
* @param event - The Nostr event to parse.
|
|
709
|
+
* @returns The parsed job feedback, or null if invalid.
|
|
710
|
+
*/
|
|
711
|
+
declare function parseJobFeedback(event: NostrEvent): ParsedJobFeedback | null;
|
|
712
|
+
|
|
713
|
+
/**
|
|
714
|
+
* Peer discovery using Nostr NIP-02 follow lists.
|
|
715
|
+
*/
|
|
716
|
+
|
|
717
|
+
/**
|
|
718
|
+
* Discovers ILP peers by querying Nostr relays for NIP-02 follow lists.
|
|
719
|
+
*/
|
|
720
|
+
declare class NostrPeerDiscovery {
|
|
721
|
+
private readonly relayUrls;
|
|
722
|
+
private readonly pool;
|
|
723
|
+
/**
|
|
724
|
+
* Creates a new NostrPeerDiscovery instance.
|
|
725
|
+
*
|
|
726
|
+
* @param relayUrls - Array of relay WebSocket URLs to query
|
|
727
|
+
* @param pool - Optional SimplePool instance (creates new one if not provided)
|
|
728
|
+
*/
|
|
729
|
+
constructor(relayUrls: string[], pool?: SimplePool);
|
|
730
|
+
/**
|
|
731
|
+
* Retrieves the list of pubkeys that a given pubkey follows.
|
|
732
|
+
*
|
|
733
|
+
* Queries NIP-02 kind:3 events from configured relays and returns
|
|
734
|
+
* the followed pubkeys from the most recent event.
|
|
735
|
+
*
|
|
736
|
+
* @param pubkey - The 64-character hex pubkey to get follows for
|
|
737
|
+
* @returns Array of followed pubkeys (deduplicated)
|
|
738
|
+
* @throws PeerDiscoveryError if pubkey format is invalid
|
|
739
|
+
*/
|
|
740
|
+
getFollows(pubkey: string): Promise<string[]>;
|
|
741
|
+
/**
|
|
742
|
+
* Discovers ILP peers by querying follow list and their ILP peer info events.
|
|
743
|
+
*
|
|
744
|
+
* For each followed pubkey, queries kind:10032 events to retrieve ILP connection info.
|
|
745
|
+
* Peers without kind:10032 events or with malformed events are silently excluded.
|
|
746
|
+
*
|
|
747
|
+
* @param pubkey - The 64-character hex pubkey to discover peers for
|
|
748
|
+
* @returns Map of pubkey → IlpPeerInfo for peers with valid ILP info
|
|
749
|
+
* @throws PeerDiscoveryError if pubkey format is invalid
|
|
750
|
+
*/
|
|
751
|
+
discoverPeers(pubkey: string): Promise<Map<string, IlpPeerInfo>>;
|
|
752
|
+
/**
|
|
753
|
+
* Subscribes to ILP peer info updates from followed pubkeys.
|
|
754
|
+
*
|
|
755
|
+
* Sets up a real-time subscription for kind:10032 events from all pubkeys
|
|
756
|
+
* that the given pubkey follows. The callback is invoked whenever a new
|
|
757
|
+
* or updated ILP peer info event is received.
|
|
758
|
+
*
|
|
759
|
+
* @param pubkey - The 64-character hex pubkey whose follows to monitor
|
|
760
|
+
* @param callback - Function called with (peerPubkey, parsedInfo) for each update
|
|
761
|
+
* @returns Subscription object with unsubscribe() method
|
|
762
|
+
* @throws PeerDiscoveryError if pubkey format is invalid
|
|
763
|
+
*/
|
|
764
|
+
subscribeToPeerUpdates(pubkey: string, callback: (pubkey: string, info: IlpPeerInfo) => void): Promise<Subscription>;
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
/**
|
|
768
|
+
* Genesis peer loader for bootstrapping new nodes into the network.
|
|
769
|
+
*
|
|
770
|
+
* Loads well-known genesis peers from a bundled JSON file and supports
|
|
771
|
+
* merging with runtime-provided additional peers.
|
|
772
|
+
*/
|
|
773
|
+
/** A genesis peer entry used for network bootstrapping. */
|
|
774
|
+
interface GenesisPeer {
|
|
775
|
+
pubkey: string;
|
|
776
|
+
relayUrl: string;
|
|
777
|
+
ilpAddress: string;
|
|
778
|
+
btpEndpoint: string;
|
|
779
|
+
}
|
|
780
|
+
/** Load and validate genesis peers from the bundled JSON file. */
|
|
781
|
+
declare function loadGenesisPeers(): GenesisPeer[];
|
|
782
|
+
/** Parse and validate additional peers from a JSON string. */
|
|
783
|
+
declare function loadAdditionalPeers(json: string): GenesisPeer[];
|
|
784
|
+
/** Load genesis peers and optionally merge with additional peers. */
|
|
785
|
+
declare function loadAllPeers(additionalPeersJson?: string): GenesisPeer[];
|
|
786
|
+
declare const GenesisPeerLoader: {
|
|
787
|
+
readonly loadGenesisPeers: typeof loadGenesisPeers;
|
|
788
|
+
readonly loadAdditionalPeers: typeof loadAdditionalPeers;
|
|
789
|
+
readonly loadAllPeers: typeof loadAllPeers;
|
|
790
|
+
};
|
|
791
|
+
|
|
792
|
+
/**
|
|
793
|
+
* ArDrive-based peer registry for permanent, decentralized storage
|
|
794
|
+
* of ILP peer info on Arweave.
|
|
795
|
+
*
|
|
796
|
+
* Read path: queries Arweave GraphQL gateway (free, no wallet needed).
|
|
797
|
+
* Write path: uploads via @ardrive/turbo-sdk (caller provides authenticated client).
|
|
798
|
+
*/
|
|
799
|
+
|
|
800
|
+
declare function fetchPeers(gatewayUrl?: string): Promise<Map<string, IlpPeerInfo>>;
|
|
801
|
+
declare function publishPeerInfo(peerInfo: IlpPeerInfo, pubkey: string, turboClient: TurboAuthenticatedClient): Promise<string>;
|
|
802
|
+
declare const ArDrivePeerRegistry: {
|
|
803
|
+
readonly fetchPeers: typeof fetchPeers;
|
|
804
|
+
readonly publishPeerInfo: typeof publishPeerInfo;
|
|
805
|
+
};
|
|
806
|
+
|
|
807
|
+
/**
|
|
808
|
+
* Social graph-based peer discovery (passive).
|
|
809
|
+
*
|
|
810
|
+
* Subscribes to NIP-02 follow list changes and emits events
|
|
811
|
+
* for new follows and unfollows. Does NOT auto-peer — the caller
|
|
812
|
+
* decides when and whether to initiate peering.
|
|
813
|
+
*/
|
|
814
|
+
|
|
815
|
+
/**
|
|
816
|
+
* Events emitted by SocialPeerDiscovery.
|
|
817
|
+
*/
|
|
818
|
+
type SocialDiscoveryEvent = {
|
|
819
|
+
type: 'social:follow-discovered';
|
|
820
|
+
pubkey: string;
|
|
821
|
+
} | {
|
|
822
|
+
type: 'social:follow-removed';
|
|
823
|
+
pubkey: string;
|
|
824
|
+
};
|
|
825
|
+
/**
|
|
826
|
+
* Listener callback for social discovery events.
|
|
827
|
+
*/
|
|
828
|
+
type SocialDiscoveryEventListener = (event: SocialDiscoveryEvent) => void;
|
|
829
|
+
/**
|
|
830
|
+
* Configuration for SocialPeerDiscovery.
|
|
831
|
+
*/
|
|
832
|
+
interface SocialPeerDiscoveryConfig {
|
|
833
|
+
/** Relays to subscribe to for kind:3 events */
|
|
834
|
+
relayUrls: string[];
|
|
835
|
+
}
|
|
836
|
+
/**
|
|
837
|
+
* Passive social graph peer discovery.
|
|
838
|
+
*
|
|
839
|
+
* Subscribes to NIP-02 kind:3 follow list events and emits:
|
|
840
|
+
* - `social:follow-discovered` when a new pubkey appears in the follow list
|
|
841
|
+
* - `social:follow-removed` when a pubkey disappears from the follow list
|
|
842
|
+
*
|
|
843
|
+
* The caller decides when to peer via `on()` listener.
|
|
844
|
+
*/
|
|
845
|
+
declare class SocialPeerDiscovery {
|
|
846
|
+
private readonly config;
|
|
847
|
+
private readonly pubkey;
|
|
848
|
+
private readonly pool;
|
|
849
|
+
private readonly listeners;
|
|
850
|
+
private previousFollows;
|
|
851
|
+
private started;
|
|
852
|
+
/**
|
|
853
|
+
* Creates a new SocialPeerDiscovery instance.
|
|
854
|
+
*
|
|
855
|
+
* @param config - Discovery configuration
|
|
856
|
+
* @param secretKey - Our Nostr secret key (used to derive pubkey)
|
|
857
|
+
* @param pool - Optional SimplePool instance (creates new one if not provided)
|
|
858
|
+
*/
|
|
859
|
+
constructor(config: SocialPeerDiscoveryConfig, secretKey: Uint8Array, pool?: SimplePool);
|
|
860
|
+
/**
|
|
861
|
+
* Register a listener for social discovery events.
|
|
862
|
+
*/
|
|
863
|
+
on(listener: SocialDiscoveryEventListener): void;
|
|
864
|
+
/**
|
|
865
|
+
* Remove a previously registered listener.
|
|
866
|
+
*/
|
|
867
|
+
off(listener: SocialDiscoveryEventListener): void;
|
|
868
|
+
/**
|
|
869
|
+
* Start subscribing to kind:3 follow list events for the node's pubkey.
|
|
870
|
+
*
|
|
871
|
+
* @returns Subscription with unsubscribe() to stop discovery
|
|
872
|
+
* @throws PeerDiscoveryError if already started
|
|
873
|
+
*/
|
|
874
|
+
start(): Subscription;
|
|
875
|
+
/**
|
|
876
|
+
* Process a follow list update by diffing against previous state.
|
|
877
|
+
*/
|
|
878
|
+
private processFollowListUpdate;
|
|
879
|
+
/**
|
|
880
|
+
* Emit an event to all registered listeners.
|
|
881
|
+
*/
|
|
882
|
+
private emit;
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
/**
|
|
886
|
+
* Seed Relay Discovery -- discovers peers via kind:10036 seed relay list events.
|
|
887
|
+
*
|
|
888
|
+
* Uses raw `ws` WebSocket connections to avoid the `ReferenceError: window is
|
|
889
|
+
* not defined` issue that occurs with nostr-tools pool utilities in Node.js
|
|
890
|
+
* containers.
|
|
891
|
+
*
|
|
892
|
+
* Discovery flow:
|
|
893
|
+
* 1. Connect to public Nostr relays and query for kind:10036 events.
|
|
894
|
+
* 2. Parse seed relay entries from kind:10036 event content.
|
|
895
|
+
* 3. Connect to seed relays sequentially (fallback on failure).
|
|
896
|
+
* 4. Subscribe to kind:10032 on the first connected seed relay.
|
|
897
|
+
* 5. Return discovered peers as IlpPeerInfo[].
|
|
898
|
+
*/
|
|
899
|
+
|
|
900
|
+
/** Configuration for seed relay discovery. */
|
|
901
|
+
interface SeedRelayDiscoveryConfig {
|
|
902
|
+
/** Public Nostr relay URLs to query for kind:10036 events. */
|
|
903
|
+
publicRelays: string[];
|
|
904
|
+
/** Timeout for relay connections in ms (default: 10000). */
|
|
905
|
+
connectionTimeout?: number;
|
|
906
|
+
/** Timeout for kind:10036 queries in ms (default: 5000). */
|
|
907
|
+
queryTimeout?: number;
|
|
908
|
+
}
|
|
909
|
+
/** Result of seed relay discovery. */
|
|
910
|
+
interface SeedRelayDiscoveryResult {
|
|
911
|
+
/** Number of seed relays successfully connected to. */
|
|
912
|
+
seedRelaysConnected: number;
|
|
913
|
+
/** Total seed relays attempted. */
|
|
914
|
+
attemptedSeeds: number;
|
|
915
|
+
/** WebSocket URLs of connected seed relays. */
|
|
916
|
+
connectedUrls: string[];
|
|
917
|
+
/** Peers discovered via kind:10032 from seed relays. */
|
|
918
|
+
discoveredPeers: IlpPeerInfo[];
|
|
919
|
+
}
|
|
920
|
+
/** Configuration for publishing a seed relay entry. */
|
|
921
|
+
interface PublishSeedRelayConfig {
|
|
922
|
+
/** Secret key for signing the event. */
|
|
923
|
+
secretKey: Uint8Array;
|
|
924
|
+
/** This node's WebSocket relay URL (e.g., wss://my-relay.example.com). */
|
|
925
|
+
relayUrl: string;
|
|
926
|
+
/** Public Nostr relay URLs to publish to. */
|
|
927
|
+
publicRelays: string[];
|
|
928
|
+
/** Optional metadata. */
|
|
929
|
+
metadata?: SeedRelayEntry['metadata'];
|
|
930
|
+
}
|
|
931
|
+
/**
|
|
932
|
+
* Discovers peers via the seed relay list model.
|
|
933
|
+
*
|
|
934
|
+
* Queries public Nostr relays for kind:10036 events, parses seed relay
|
|
935
|
+
* entries, connects to seed relays, and subscribes to kind:10032 events
|
|
936
|
+
* to discover network peers.
|
|
937
|
+
*/
|
|
938
|
+
declare class SeedRelayDiscovery {
|
|
939
|
+
private readonly config;
|
|
940
|
+
private readonly connectionTimeout;
|
|
941
|
+
private readonly queryTimeout;
|
|
942
|
+
private readonly openSockets;
|
|
943
|
+
constructor(config: SeedRelayDiscoveryConfig);
|
|
944
|
+
/**
|
|
945
|
+
* Discover peers via seed relay list.
|
|
946
|
+
*
|
|
947
|
+
* 1. Query publicRelays for kind:10036 events
|
|
948
|
+
* 2. Parse seed relay entries
|
|
949
|
+
* 3. Connect to seed relays sequentially (fallback on failure)
|
|
950
|
+
* 4. Subscribe to kind:10032 on connected seed relay
|
|
951
|
+
* 5. Return discovered peers
|
|
952
|
+
*
|
|
953
|
+
* @throws PeerDiscoveryError if all seed relays are exhausted
|
|
954
|
+
*/
|
|
955
|
+
discover(): Promise<SeedRelayDiscoveryResult>;
|
|
956
|
+
/**
|
|
957
|
+
* Stop discovery and close all open WebSocket connections.
|
|
958
|
+
*/
|
|
959
|
+
close(): Promise<void>;
|
|
960
|
+
/**
|
|
961
|
+
* Query public relays for kind:10036 events and parse seed relay entries.
|
|
962
|
+
*/
|
|
963
|
+
private querySeedRelayLists;
|
|
964
|
+
/**
|
|
965
|
+
* Deduplicate seed relay entries by URL, keeping the first occurrence.
|
|
966
|
+
*/
|
|
967
|
+
private deduplicateByUrl;
|
|
968
|
+
}
|
|
969
|
+
/**
|
|
970
|
+
* Publish a kind:10036 event advertising this node as a seed relay.
|
|
971
|
+
* Connects to each publicRelay and publishes the event.
|
|
972
|
+
* Returns the number of relays the event was published to.
|
|
973
|
+
*
|
|
974
|
+
* @param config - Configuration for publishing the seed relay entry.
|
|
975
|
+
* @returns The count of successful publishes and the event ID.
|
|
976
|
+
*/
|
|
977
|
+
declare function publishSeedRelayEntry(config: PublishSeedRelayConfig): Promise<{
|
|
978
|
+
publishedTo: number;
|
|
979
|
+
eventId: string;
|
|
980
|
+
}>;
|
|
981
|
+
|
|
982
|
+
/**
|
|
983
|
+
* Pure functions for settlement chain negotiation.
|
|
984
|
+
* No I/O or side effects — used during peer registration to determine
|
|
985
|
+
* the best matching settlement chain and token.
|
|
986
|
+
*/
|
|
987
|
+
/**
|
|
988
|
+
* Negotiates the best matching settlement chain between requester and responder.
|
|
989
|
+
*
|
|
990
|
+
* Preference order:
|
|
991
|
+
* 1. Chain in intersection with requester's preferred token
|
|
992
|
+
* 2. Chain in intersection with responder's preferred token
|
|
993
|
+
* 3. First chain in intersection (requester's order preserved)
|
|
994
|
+
*
|
|
995
|
+
* @param requesterChains - Chain identifiers the requester supports
|
|
996
|
+
* @param responderChains - Chain identifiers the responder supports
|
|
997
|
+
* @param requesterPreferredTokens - Requester's preferred tokens by chain
|
|
998
|
+
* @param responderPreferredTokens - Responder's preferred tokens by chain
|
|
999
|
+
* @returns The negotiated chain identifier, or null if no intersection
|
|
1000
|
+
*/
|
|
1001
|
+
declare function negotiateSettlementChain(requesterChains: string[], responderChains: string[], requesterPreferredTokens?: Record<string, string>, responderPreferredTokens?: Record<string, string>): string | null;
|
|
1002
|
+
/**
|
|
1003
|
+
* Resolves which token to use for a given chain.
|
|
1004
|
+
*
|
|
1005
|
+
* Priority: requester's preference > responder's preference > undefined
|
|
1006
|
+
*
|
|
1007
|
+
* @param chain - The chain identifier to resolve token for
|
|
1008
|
+
* @param requesterPreferredTokens - Requester's preferred tokens by chain
|
|
1009
|
+
* @param responderPreferredTokens - Responder's preferred tokens by chain
|
|
1010
|
+
* @returns The token address, or undefined if neither party has a preference
|
|
1011
|
+
*/
|
|
1012
|
+
declare function resolveTokenForChain(chain: string, requesterPreferredTokens?: Record<string, string>, responderPreferredTokens?: Record<string, string>): string | undefined;
|
|
1013
|
+
|
|
1014
|
+
/**
|
|
1015
|
+
* Bootstrap state machine types, event types, and client interfaces.
|
|
1016
|
+
*/
|
|
1017
|
+
|
|
1018
|
+
/**
|
|
1019
|
+
* A peer discovered via kind:10032 relay events but not yet peered with.
|
|
1020
|
+
*/
|
|
1021
|
+
interface DiscoveredPeer {
|
|
1022
|
+
/** Nostr pubkey of the discovered peer (64-char hex) */
|
|
1023
|
+
pubkey: string;
|
|
1024
|
+
/** Connector peer ID (e.g., "nostr-aabb11cc22dd33ee") */
|
|
1025
|
+
peerId: string;
|
|
1026
|
+
/** Parsed ILP peer info from the kind:10032 event */
|
|
1027
|
+
peerInfo: IlpPeerInfo;
|
|
1028
|
+
/** Timestamp (seconds since epoch) when the peer was first discovered */
|
|
1029
|
+
discoveredAt: number;
|
|
1030
|
+
}
|
|
1031
|
+
/**
|
|
1032
|
+
* Represents a known peer for bootstrap.
|
|
1033
|
+
*/
|
|
1034
|
+
interface KnownPeer {
|
|
1035
|
+
/** Nostr pubkey of the peer (64-char hex) */
|
|
1036
|
+
pubkey: string;
|
|
1037
|
+
/** WebSocket URL of the peer's Nostr relay */
|
|
1038
|
+
relayUrl: string;
|
|
1039
|
+
/** BTP WebSocket endpoint for direct connection during bootstrap */
|
|
1040
|
+
btpEndpoint: string;
|
|
1041
|
+
}
|
|
1042
|
+
/**
|
|
1043
|
+
* Result of a successful peer bootstrap.
|
|
1044
|
+
*/
|
|
1045
|
+
interface BootstrapResult {
|
|
1046
|
+
/** The known peer that was bootstrapped with */
|
|
1047
|
+
knownPeer: KnownPeer;
|
|
1048
|
+
/** The peer's ILP info from their kind:10032 event */
|
|
1049
|
+
peerInfo: IlpPeerInfo;
|
|
1050
|
+
/** The ID used when registering with the connector (e.g., "nostr-aabb11cc22dd33ee") */
|
|
1051
|
+
registeredPeerId: string;
|
|
1052
|
+
/** Channel ID from unilateral channel opening */
|
|
1053
|
+
channelId?: string;
|
|
1054
|
+
/** Negotiated chain from local settlement negotiation */
|
|
1055
|
+
negotiatedChain?: string;
|
|
1056
|
+
/** Peer's settlement address */
|
|
1057
|
+
settlementAddress?: string;
|
|
1058
|
+
}
|
|
1059
|
+
/**
|
|
1060
|
+
* Callback interface for connector Admin API operations.
|
|
1061
|
+
* Matches the connector admin API shape: POST /admin/peers
|
|
1062
|
+
*/
|
|
1063
|
+
interface ConnectorAdminClient {
|
|
1064
|
+
/**
|
|
1065
|
+
* Add a peer to the connector via the admin API.
|
|
1066
|
+
* @param config - Peer configuration matching the connector admin API shape
|
|
1067
|
+
*/
|
|
1068
|
+
addPeer(config: {
|
|
1069
|
+
id: string;
|
|
1070
|
+
url: string;
|
|
1071
|
+
authToken: string;
|
|
1072
|
+
routes?: {
|
|
1073
|
+
prefix: string;
|
|
1074
|
+
priority?: number;
|
|
1075
|
+
}[];
|
|
1076
|
+
settlement?: {
|
|
1077
|
+
preference: string;
|
|
1078
|
+
evmAddress?: string;
|
|
1079
|
+
tokenAddress?: string;
|
|
1080
|
+
tokenNetworkAddress?: string;
|
|
1081
|
+
chainId?: number;
|
|
1082
|
+
channelId?: string;
|
|
1083
|
+
initialDeposit?: string;
|
|
1084
|
+
};
|
|
1085
|
+
}): Promise<void>;
|
|
1086
|
+
/**
|
|
1087
|
+
* Remove a peer from the connector via the admin API.
|
|
1088
|
+
* Optional -- not all callers will implement peer removal.
|
|
1089
|
+
* @param peerId - The peer ID to remove
|
|
1090
|
+
*/
|
|
1091
|
+
removePeer?(peerId: string): Promise<void>;
|
|
1092
|
+
}
|
|
1093
|
+
/**
|
|
1094
|
+
* Bootstrap phase states.
|
|
1095
|
+
* Two-phase flow: discovering -> registering -> announcing -> ready | failed
|
|
1096
|
+
*/
|
|
1097
|
+
type BootstrapPhase = 'discovering' | 'registering' | 'announcing' | 'ready' | 'failed';
|
|
1098
|
+
/**
|
|
1099
|
+
* Bootstrap events emitted during the bootstrap lifecycle.
|
|
1100
|
+
*/
|
|
1101
|
+
type BootstrapEvent = {
|
|
1102
|
+
type: 'bootstrap:phase';
|
|
1103
|
+
phase: BootstrapPhase;
|
|
1104
|
+
previousPhase?: BootstrapPhase;
|
|
1105
|
+
} | {
|
|
1106
|
+
type: 'bootstrap:peer-registered';
|
|
1107
|
+
peerId: string;
|
|
1108
|
+
peerPubkey: string;
|
|
1109
|
+
ilpAddress: string;
|
|
1110
|
+
} | {
|
|
1111
|
+
type: 'bootstrap:channel-opened';
|
|
1112
|
+
peerId: string;
|
|
1113
|
+
channelId: string;
|
|
1114
|
+
negotiatedChain: string;
|
|
1115
|
+
} | {
|
|
1116
|
+
type: 'bootstrap:settlement-failed';
|
|
1117
|
+
peerId: string;
|
|
1118
|
+
reason: string;
|
|
1119
|
+
} | {
|
|
1120
|
+
type: 'bootstrap:announced';
|
|
1121
|
+
peerId: string;
|
|
1122
|
+
eventId: string;
|
|
1123
|
+
amount: string;
|
|
1124
|
+
} | {
|
|
1125
|
+
type: 'bootstrap:announce-failed';
|
|
1126
|
+
peerId: string;
|
|
1127
|
+
reason: string;
|
|
1128
|
+
} | {
|
|
1129
|
+
type: 'bootstrap:ready';
|
|
1130
|
+
peerCount: number;
|
|
1131
|
+
channelCount: number;
|
|
1132
|
+
} | {
|
|
1133
|
+
type: 'bootstrap:peer-discovered';
|
|
1134
|
+
peerPubkey: string;
|
|
1135
|
+
ilpAddress: string;
|
|
1136
|
+
} | {
|
|
1137
|
+
type: 'bootstrap:peer-deregistered';
|
|
1138
|
+
peerId: string;
|
|
1139
|
+
peerPubkey: string;
|
|
1140
|
+
reason: string;
|
|
1141
|
+
};
|
|
1142
|
+
/**
|
|
1143
|
+
* Listener callback for bootstrap events.
|
|
1144
|
+
*/
|
|
1145
|
+
type BootstrapEventListener = (event: BootstrapEvent) => void;
|
|
1146
|
+
/**
|
|
1147
|
+
* Result of sending an ILP packet via the connector.
|
|
1148
|
+
* The connector may return either `accepted` or `fulfilled` as the
|
|
1149
|
+
* success indicator. IlpClient normalizes to `accepted`.
|
|
1150
|
+
*/
|
|
1151
|
+
interface IlpSendResult {
|
|
1152
|
+
accepted: boolean;
|
|
1153
|
+
fulfillment?: string;
|
|
1154
|
+
data?: string;
|
|
1155
|
+
code?: string;
|
|
1156
|
+
message?: string;
|
|
1157
|
+
}
|
|
1158
|
+
/**
|
|
1159
|
+
* Client interface for sending ILP packets via the connector.
|
|
1160
|
+
*/
|
|
1161
|
+
interface IlpClient {
|
|
1162
|
+
sendIlpPacket(params: {
|
|
1163
|
+
destination: string;
|
|
1164
|
+
amount: string;
|
|
1165
|
+
data: string;
|
|
1166
|
+
timeout?: number;
|
|
1167
|
+
}): Promise<IlpSendResult>;
|
|
1168
|
+
/**
|
|
1169
|
+
* Optional: Send ILP packet with signed balance proof claim (BTP only).
|
|
1170
|
+
* Falls back to sendIlpPacket if not implemented.
|
|
1171
|
+
*/
|
|
1172
|
+
sendIlpPacketWithClaim?(params: {
|
|
1173
|
+
destination: string;
|
|
1174
|
+
amount: string;
|
|
1175
|
+
data: string;
|
|
1176
|
+
timeout?: number;
|
|
1177
|
+
}, claim: unknown): Promise<IlpSendResult>;
|
|
1178
|
+
}
|
|
1179
|
+
/**
|
|
1180
|
+
* @deprecated Use IlpClient instead
|
|
1181
|
+
*/
|
|
1182
|
+
type AgentRuntimeClient = IlpClient;
|
|
1183
|
+
/**
|
|
1184
|
+
* Own settlement configuration for local chain selection during registration.
|
|
1185
|
+
*/
|
|
1186
|
+
interface SettlementConfig {
|
|
1187
|
+
/** Chain identifiers this node supports */
|
|
1188
|
+
supportedChains?: string[];
|
|
1189
|
+
/** Maps chain identifier to this node's settlement address */
|
|
1190
|
+
settlementAddresses?: Record<string, string>;
|
|
1191
|
+
/** Maps chain identifier to this node's preferred token contract address */
|
|
1192
|
+
preferredTokens?: Record<string, string>;
|
|
1193
|
+
/** Maps chain identifier to TokenNetwork contract address (EVM only) */
|
|
1194
|
+
tokenNetworks?: Record<string, string>;
|
|
1195
|
+
}
|
|
1196
|
+
/**
|
|
1197
|
+
* Base configuration for the bootstrap service.
|
|
1198
|
+
*/
|
|
1199
|
+
interface BootstrapConfig {
|
|
1200
|
+
/** List of known peers to bootstrap with */
|
|
1201
|
+
knownPeers: KnownPeer[];
|
|
1202
|
+
/** Timeout for relay queries in milliseconds (default: 5000) */
|
|
1203
|
+
queryTimeout?: number;
|
|
1204
|
+
/** Enable ArDrive peer lookup (default: true) */
|
|
1205
|
+
ardriveEnabled?: boolean;
|
|
1206
|
+
/** Default relay URL for ArDrive-sourced peers that lack relay URLs */
|
|
1207
|
+
defaultRelayUrl?: string;
|
|
1208
|
+
}
|
|
1209
|
+
/**
|
|
1210
|
+
* Extended configuration for the bootstrap service with ILP-first flow support.
|
|
1211
|
+
*/
|
|
1212
|
+
interface BootstrapServiceConfig extends BootstrapConfig {
|
|
1213
|
+
/** Own settlement preferences for settlement during peer registration */
|
|
1214
|
+
settlementInfo?: SettlementConfig;
|
|
1215
|
+
/** This node's ILP address (for building ILP PREPARE destinations) */
|
|
1216
|
+
ownIlpAddress?: string;
|
|
1217
|
+
/** DI callback for TOON encoding (avoids circular dep) */
|
|
1218
|
+
toonEncoder?: (event: NostrEvent) => Uint8Array;
|
|
1219
|
+
/** DI callback for TOON decoding (avoids circular dep) */
|
|
1220
|
+
toonDecoder?: (bytes: Uint8Array) => NostrEvent;
|
|
1221
|
+
/** Static BTP secret for initial peer registration (before settlement) */
|
|
1222
|
+
btpSecret?: string;
|
|
1223
|
+
/** Base price per byte for ILP packet pricing (default: 10n) */
|
|
1224
|
+
basePricePerByte?: bigint;
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
/**
|
|
1228
|
+
* Bootstrap service for peer discovery and network initialization.
|
|
1229
|
+
*
|
|
1230
|
+
* Handles the initial peer discovery and registration process
|
|
1231
|
+
* with known peers to bootstrap into the ILP network.
|
|
1232
|
+
*
|
|
1233
|
+
* Two-phase bootstrap:
|
|
1234
|
+
* 1. Discover & Register: Load peers, query relays for kind:10032,
|
|
1235
|
+
* register with connector, select chain locally, open channel unilaterally
|
|
1236
|
+
* 2. Announce: Publish own kind:10032 as paid ILP PREPARE
|
|
1237
|
+
*/
|
|
1238
|
+
|
|
1239
|
+
/**
|
|
1240
|
+
* Error thrown when bootstrap operations fail.
|
|
1241
|
+
*/
|
|
1242
|
+
declare class BootstrapError extends ToonError {
|
|
1243
|
+
constructor(message: string, cause?: Error);
|
|
1244
|
+
}
|
|
1245
|
+
/**
|
|
1246
|
+
* Service for bootstrapping into the ILP network via known Nostr peers.
|
|
1247
|
+
*
|
|
1248
|
+
* The bootstrap process:
|
|
1249
|
+
* Phase 1 (Discover & Register): Load peers from config, ArDrive, and env var.
|
|
1250
|
+
* For each peer, query their relay for kind:10032 (ILP Peer Info).
|
|
1251
|
+
* Register peer via connector admin API.
|
|
1252
|
+
* Select chain locally and open channel unilaterally.
|
|
1253
|
+
* Phase 2 (Announce): Publish own kind:10032 as paid ILP PREPARE.
|
|
1254
|
+
*/
|
|
1255
|
+
declare class BootstrapService {
|
|
1256
|
+
private readonly config;
|
|
1257
|
+
private readonly secretKey;
|
|
1258
|
+
private readonly pubkey;
|
|
1259
|
+
private readonly ownIlpInfo;
|
|
1260
|
+
private readonly pool;
|
|
1261
|
+
private connectorAdmin?;
|
|
1262
|
+
private channelClient?;
|
|
1263
|
+
private claimSigner?;
|
|
1264
|
+
private readonly ilpClient?;
|
|
1265
|
+
private readonly settlementInfo?;
|
|
1266
|
+
private readonly ownIlpAddress?;
|
|
1267
|
+
private readonly toonEncoder?;
|
|
1268
|
+
private readonly toonDecoder?;
|
|
1269
|
+
private readonly basePricePerByte;
|
|
1270
|
+
private listeners;
|
|
1271
|
+
private phase;
|
|
1272
|
+
/**
|
|
1273
|
+
* Creates a new BootstrapService instance.
|
|
1274
|
+
*
|
|
1275
|
+
* @param config - Bootstrap configuration with known peers and optional ILP-first settings
|
|
1276
|
+
* @param secretKey - Our Nostr secret key for signing events
|
|
1277
|
+
* @param ownIlpInfo - Our ILP peer info to publish
|
|
1278
|
+
* @param pool - Optional SimplePool instance (creates new one if not provided)
|
|
1279
|
+
*/
|
|
1280
|
+
constructor(config: BootstrapServiceConfig, secretKey: Uint8Array, ownIlpInfo: IlpPeerInfo, pool?: SimplePool);
|
|
1281
|
+
/**
|
|
1282
|
+
* Set the ILP client for sending packets via the connector.
|
|
1283
|
+
* Kept separate from constructor for backward compatibility with existing code
|
|
1284
|
+
* that creates the client after construction.
|
|
1285
|
+
*/
|
|
1286
|
+
setIlpClient(client: IlpClient): void;
|
|
1287
|
+
/**
|
|
1288
|
+
* @deprecated Use setIlpClient instead
|
|
1289
|
+
*/
|
|
1290
|
+
setAgentRuntimeClient(client: IlpClient): void;
|
|
1291
|
+
/**
|
|
1292
|
+
* Set the connector admin client for adding peers/routes.
|
|
1293
|
+
*/
|
|
1294
|
+
setConnectorAdmin(admin: ConnectorAdminClient): void;
|
|
1295
|
+
/**
|
|
1296
|
+
* Set the channel client for opening payment channels.
|
|
1297
|
+
*/
|
|
1298
|
+
setChannelClient(client: ConnectorChannelClient): void;
|
|
1299
|
+
/**
|
|
1300
|
+
* Set the claim signer for creating signed balance proofs.
|
|
1301
|
+
* Used by clients to sign payment channel claims for ILP packets.
|
|
1302
|
+
*/
|
|
1303
|
+
setClaimSigner(signer: (channelId: string, amount: bigint) => Promise<unknown>): void;
|
|
1304
|
+
/**
|
|
1305
|
+
* Get the current bootstrap phase.
|
|
1306
|
+
*/
|
|
1307
|
+
getPhase(): BootstrapPhase;
|
|
1308
|
+
/**
|
|
1309
|
+
* Register an event listener.
|
|
1310
|
+
*/
|
|
1311
|
+
on(listener: BootstrapEventListener): void;
|
|
1312
|
+
/**
|
|
1313
|
+
* Unregister an event listener.
|
|
1314
|
+
*/
|
|
1315
|
+
off(listener: BootstrapEventListener): void;
|
|
1316
|
+
/**
|
|
1317
|
+
* Emit a bootstrap event to all listeners.
|
|
1318
|
+
*/
|
|
1319
|
+
private emit;
|
|
1320
|
+
/**
|
|
1321
|
+
* Transition to a new phase, emitting phase change event.
|
|
1322
|
+
*/
|
|
1323
|
+
private setPhase;
|
|
1324
|
+
/**
|
|
1325
|
+
* Load peers from genesis config, ArDrive, and optional env var JSON.
|
|
1326
|
+
* Merges all sources, deduplicating by pubkey (ArDrive overrides genesis for matching pubkeys).
|
|
1327
|
+
*/
|
|
1328
|
+
loadPeers(additionalPeersJson?: string): Promise<GenesisPeer[]>;
|
|
1329
|
+
/**
|
|
1330
|
+
* Bootstrap with all known peers.
|
|
1331
|
+
*
|
|
1332
|
+
* Loads peers from genesis config, ArDrive, and optional env var JSON,
|
|
1333
|
+
* then attempts to bootstrap with each peer in order.
|
|
1334
|
+
* Returns results for successfully bootstrapped peers.
|
|
1335
|
+
* Continues to next peer on failure.
|
|
1336
|
+
*
|
|
1337
|
+
* @param additionalPeersJson - Optional JSON string of additional peers to merge
|
|
1338
|
+
* @returns Array of successful bootstrap results
|
|
1339
|
+
*/
|
|
1340
|
+
bootstrap(additionalPeersJson?: string): Promise<BootstrapResult[]>;
|
|
1341
|
+
/**
|
|
1342
|
+
* Bootstrap with a single known peer.
|
|
1343
|
+
*
|
|
1344
|
+
* @param knownPeer - The known peer to bootstrap with
|
|
1345
|
+
* @returns Bootstrap result with peer info and registered peer ID
|
|
1346
|
+
* @throws BootstrapError if pubkey is invalid or peer info query fails
|
|
1347
|
+
*/
|
|
1348
|
+
bootstrapWithPeer(knownPeer: KnownPeer): Promise<BootstrapResult>;
|
|
1349
|
+
/**
|
|
1350
|
+
* Announce own kind:10032 as paid ILP PREPARE (Phase 2).
|
|
1351
|
+
*/
|
|
1352
|
+
private announceViaIlp;
|
|
1353
|
+
/**
|
|
1354
|
+
* Query a peer's relay for their kind:10032 ILP Peer Info event.
|
|
1355
|
+
* Uses direct WebSocket connection for reliable container-to-container communication.
|
|
1356
|
+
*/
|
|
1357
|
+
private queryPeerInfo;
|
|
1358
|
+
/**
|
|
1359
|
+
* Add a peer to the connector via Admin API.
|
|
1360
|
+
*/
|
|
1361
|
+
private addPeerToConnector;
|
|
1362
|
+
/**
|
|
1363
|
+
* Publish our own kind:10032 ILP Peer Info to a relay.
|
|
1364
|
+
*/
|
|
1365
|
+
private publishOurInfo;
|
|
1366
|
+
/**
|
|
1367
|
+
* Query a peer's relay for other peers' kind:10032 events.
|
|
1368
|
+
*
|
|
1369
|
+
* Used after bootstrapping to discover additional peers
|
|
1370
|
+
* that have also published to the bootstrap node's relay.
|
|
1371
|
+
*
|
|
1372
|
+
* @param relayUrl - The relay URL to query
|
|
1373
|
+
* @param excludePubkeys - Pubkeys to exclude from results (e.g., our own, known peers)
|
|
1374
|
+
* @returns Map of pubkey to IlpPeerInfo for discovered peers
|
|
1375
|
+
*/
|
|
1376
|
+
discoverPeersViaRelay(relayUrl: string, excludePubkeys?: string[]): Promise<Map<string, IlpPeerInfo>>;
|
|
1377
|
+
/**
|
|
1378
|
+
* Get our pubkey.
|
|
1379
|
+
*/
|
|
1380
|
+
getPubkey(): string;
|
|
1381
|
+
/**
|
|
1382
|
+
* Publish our ILP info to a specific relay.
|
|
1383
|
+
*
|
|
1384
|
+
* @param relayUrl - The relay URL to publish to (defaults to 'ws://localhost:7100')
|
|
1385
|
+
*/
|
|
1386
|
+
publishToRelay(relayUrl?: string): Promise<void>;
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
/**
|
|
1390
|
+
* Discovery tracker for processing kind:10032 events and managing peer discovery.
|
|
1391
|
+
*
|
|
1392
|
+
* Unlike RelayMonitor, the tracker does NOT own a subscription — callers feed
|
|
1393
|
+
* events in via processEvent(). This enables use from any event source:
|
|
1394
|
+
* relay subscriptions, ILP handlers, or test harnesses.
|
|
1395
|
+
*/
|
|
1396
|
+
|
|
1397
|
+
/**
|
|
1398
|
+
* Configuration for creating a DiscoveryTracker.
|
|
1399
|
+
*/
|
|
1400
|
+
interface DiscoveryTrackerConfig {
|
|
1401
|
+
/** Nostr secret key for deriving own pubkey (excluded from discovery) */
|
|
1402
|
+
secretKey: Uint8Array;
|
|
1403
|
+
/** Own settlement preferences for local chain negotiation */
|
|
1404
|
+
settlementInfo?: SettlementConfig;
|
|
1405
|
+
}
|
|
1406
|
+
/**
|
|
1407
|
+
* Discovery tracker interface — processes kind:10032 events and manages
|
|
1408
|
+
* peer discovery state without owning a subscription.
|
|
1409
|
+
*/
|
|
1410
|
+
interface DiscoveryTracker {
|
|
1411
|
+
/** Process a kind:10032 event for discovery. Called by relay subscription or ILP handler. */
|
|
1412
|
+
processEvent(event: NostrEvent): void;
|
|
1413
|
+
/** Explicitly peer with a discovered peer (register + open channel). */
|
|
1414
|
+
peerWith(pubkey: string): Promise<void>;
|
|
1415
|
+
/** Get discovered peers not yet peered with. */
|
|
1416
|
+
getDiscoveredPeers(): DiscoveredPeer[];
|
|
1417
|
+
/** Check if a pubkey has been actively peered with. */
|
|
1418
|
+
isPeered(pubkey: string): boolean;
|
|
1419
|
+
/** Count of registered (peered) peers. */
|
|
1420
|
+
getPeerCount(): number;
|
|
1421
|
+
/** Count of all discovered peers (including peered). */
|
|
1422
|
+
getDiscoveredCount(): number;
|
|
1423
|
+
/** Register an event listener. */
|
|
1424
|
+
on(listener: BootstrapEventListener): void;
|
|
1425
|
+
/** Unregister an event listener. */
|
|
1426
|
+
off(listener: BootstrapEventListener): void;
|
|
1427
|
+
/** Set connector admin for peer registration (required before peerWith). */
|
|
1428
|
+
setConnectorAdmin(admin: ConnectorAdminClient): void;
|
|
1429
|
+
/** Set channel client for payment channel opening (optional). */
|
|
1430
|
+
setChannelClient(client: ConnectorChannelClient): void;
|
|
1431
|
+
/** Mark pubkeys as already-peered (e.g., from bootstrap phase). */
|
|
1432
|
+
addExcludedPubkeys(pubkeys: string[]): void;
|
|
1433
|
+
}
|
|
1434
|
+
/**
|
|
1435
|
+
* Create a discovery tracker that processes kind:10032 events.
|
|
1436
|
+
*
|
|
1437
|
+
* The tracker does not own a subscription — callers feed events in via
|
|
1438
|
+
* processEvent(). It handles discovery, stale-event filtering,
|
|
1439
|
+
* deregistration, and explicit peering via peerWith().
|
|
1440
|
+
*/
|
|
1441
|
+
declare function createDiscoveryTracker(config: DiscoveryTrackerConfig): DiscoveryTracker;
|
|
1442
|
+
|
|
1443
|
+
/**
|
|
1444
|
+
* HTTP client for sending ILP packets via the connector's POST /ilp/send endpoint.
|
|
1445
|
+
*/
|
|
1446
|
+
|
|
1447
|
+
/**
|
|
1448
|
+
* Creates an HTTP-based IlpClient that sends ILP packets via POST /ilp/send.
|
|
1449
|
+
*
|
|
1450
|
+
* @param baseUrl - Base URL of the connector (e.g., "http://localhost:3000")
|
|
1451
|
+
* @returns An IlpClient instance
|
|
1452
|
+
* @throws BootstrapError if baseUrl is not a valid URL
|
|
1453
|
+
*/
|
|
1454
|
+
declare function createHttpIlpClient$1(baseUrl: string): IlpClient;
|
|
1455
|
+
/**
|
|
1456
|
+
* @deprecated Use createHttpIlpClient instead
|
|
1457
|
+
*/
|
|
1458
|
+
declare const createHttpRuntimeClient: typeof createHttpIlpClient$1;
|
|
1459
|
+
/**
|
|
1460
|
+
* @deprecated Use createHttpIlpClient instead
|
|
1461
|
+
*/
|
|
1462
|
+
declare const createAgentRuntimeClient: typeof createHttpIlpClient$1;
|
|
1463
|
+
|
|
1464
|
+
/**
|
|
1465
|
+
* Direct (in-process) client for sending ILP packets via a ConnectorNode.
|
|
1466
|
+
*
|
|
1467
|
+
* Unlike the HTTP-based createHttpIlpClient(), this factory wraps a
|
|
1468
|
+
* ConnectorNode's sendPacket() method as an IlpClient, enabling
|
|
1469
|
+
* zero-latency embedded mode without network overhead.
|
|
1470
|
+
*/
|
|
1471
|
+
|
|
1472
|
+
/**
|
|
1473
|
+
* Parameters accepted by ConnectorNode.sendPacket().
|
|
1474
|
+
*/
|
|
1475
|
+
interface SendPacketParams {
|
|
1476
|
+
/** ILP destination address */
|
|
1477
|
+
destination: string;
|
|
1478
|
+
/** Amount as BigInt (not string) */
|
|
1479
|
+
amount: bigint;
|
|
1480
|
+
/** Binary data (not base64 string) */
|
|
1481
|
+
data: Uint8Array;
|
|
1482
|
+
/** 32-byte SHA-256 execution condition */
|
|
1483
|
+
executionCondition?: Uint8Array;
|
|
1484
|
+
/**
|
|
1485
|
+
* Packet expiration. Included for structural compatibility with ConnectorNode
|
|
1486
|
+
* but is not set by the direct client — callers or the connector provide it
|
|
1487
|
+
* if needed.
|
|
1488
|
+
*/
|
|
1489
|
+
expiresAt?: Date;
|
|
1490
|
+
}
|
|
1491
|
+
/**
|
|
1492
|
+
* Result returned by ConnectorNode.sendPacket().
|
|
1493
|
+
*
|
|
1494
|
+
* Accepts both string discriminants ('fulfill'/'reject') for backward
|
|
1495
|
+
* compatibility with test mocks, and numeric PacketType enum values
|
|
1496
|
+
* (13 = FULFILL, 14 = REJECT) used by @toon-protocol/connector@1.6.0+.
|
|
1497
|
+
*/
|
|
1498
|
+
type SendPacketResult = {
|
|
1499
|
+
type: 'fulfill';
|
|
1500
|
+
fulfillment: Uint8Array | Buffer;
|
|
1501
|
+
data?: Uint8Array | Buffer;
|
|
1502
|
+
} | {
|
|
1503
|
+
type: 13;
|
|
1504
|
+
fulfillment: Uint8Array | Buffer;
|
|
1505
|
+
data?: Uint8Array | Buffer;
|
|
1506
|
+
} | {
|
|
1507
|
+
type: 'reject';
|
|
1508
|
+
code: string;
|
|
1509
|
+
message: string;
|
|
1510
|
+
data?: Uint8Array | Buffer;
|
|
1511
|
+
} | {
|
|
1512
|
+
type: 14;
|
|
1513
|
+
code: string;
|
|
1514
|
+
message: string;
|
|
1515
|
+
data?: Uint8Array | Buffer;
|
|
1516
|
+
};
|
|
1517
|
+
/**
|
|
1518
|
+
* Structural interface matching ConnectorNode's sendPacket() method.
|
|
1519
|
+
*
|
|
1520
|
+
* Consumers pass a `@toon-protocol/connector` ConnectorNode instance without
|
|
1521
|
+
* needing to import `@toon-protocol/connector` as a dependency.
|
|
1522
|
+
* TypeScript's structural type system handles compatibility automatically.
|
|
1523
|
+
*/
|
|
1524
|
+
interface ConnectorNodeLike {
|
|
1525
|
+
sendPacket(params: SendPacketParams): Promise<SendPacketResult>;
|
|
1526
|
+
}
|
|
1527
|
+
/**
|
|
1528
|
+
* Configuration options for the direct runtime client.
|
|
1529
|
+
*/
|
|
1530
|
+
interface DirectRuntimeClientConfig {
|
|
1531
|
+
/**
|
|
1532
|
+
* Optional callback for extracting the Nostr event ID from TOON-encoded data.
|
|
1533
|
+
*
|
|
1534
|
+
* When provided, the client computes
|
|
1535
|
+
* `executionCondition = SHA256(SHA256(event.id))` and passes it to
|
|
1536
|
+
* `sendPacket()`.
|
|
1537
|
+
*
|
|
1538
|
+
* When omitted, no executionCondition is set (connector uses its default).
|
|
1539
|
+
*
|
|
1540
|
+
* Note: this is intentionally a narrower type than
|
|
1541
|
+
* `BootstrapServiceConfig.toonDecoder` (which returns a full `NostrEvent`).
|
|
1542
|
+
* Only the `id` field is needed for condition computation, so the interface
|
|
1543
|
+
* is minimal.
|
|
1544
|
+
*/
|
|
1545
|
+
toonDecoder?: (bytes: Uint8Array) => {
|
|
1546
|
+
id: string;
|
|
1547
|
+
};
|
|
1548
|
+
}
|
|
1549
|
+
/**
|
|
1550
|
+
* Creates an IlpClient that sends ILP packets by calling
|
|
1551
|
+
* `connector.sendPacket()` directly (no HTTP).
|
|
1552
|
+
*
|
|
1553
|
+
* @param connector - A ConnectorNode-like object with a sendPacket() method
|
|
1554
|
+
* @param config - Optional configuration (e.g., toonDecoder for condition computation)
|
|
1555
|
+
* @returns An IlpClient instance
|
|
1556
|
+
*/
|
|
1557
|
+
declare function createDirectIlpClient(connector: ConnectorNodeLike, config?: DirectRuntimeClientConfig): IlpClient;
|
|
1558
|
+
/**
|
|
1559
|
+
* @deprecated Use createDirectIlpClient instead
|
|
1560
|
+
*/
|
|
1561
|
+
declare const createDirectRuntimeClient: typeof createDirectIlpClient;
|
|
1562
|
+
|
|
1563
|
+
/**
|
|
1564
|
+
* Parameters for registering a peer on the connector.
|
|
1565
|
+
* Maps to ConnectorNode.registerPeer() params in @toon-protocol/connector.
|
|
1566
|
+
*/
|
|
1567
|
+
interface RegisterPeerParams {
|
|
1568
|
+
id: string;
|
|
1569
|
+
url: string;
|
|
1570
|
+
authToken?: string;
|
|
1571
|
+
routes?: {
|
|
1572
|
+
prefix: string;
|
|
1573
|
+
priority?: number;
|
|
1574
|
+
}[];
|
|
1575
|
+
settlement?: Record<string, unknown>;
|
|
1576
|
+
}
|
|
1577
|
+
/**
|
|
1578
|
+
* Structural interface for ConnectorNode admin methods.
|
|
1579
|
+
*
|
|
1580
|
+
* This is a structural interface — consumers pass an `@toon-protocol/connector`
|
|
1581
|
+
* ConnectorNode instance without importing it as a dependency. The ConnectorNode's
|
|
1582
|
+
* `registerPeer()` and `removePeer()` methods match this shape, allowing
|
|
1583
|
+
* zero-dependency coupling for embedded mode.
|
|
1584
|
+
*/
|
|
1585
|
+
interface ConnectorAdminLike {
|
|
1586
|
+
registerPeer(params: RegisterPeerParams): Promise<void>;
|
|
1587
|
+
removePeer(peerId: string): Promise<void>;
|
|
1588
|
+
}
|
|
1589
|
+
/**
|
|
1590
|
+
* Creates a ConnectorAdminClient that calls ConnectorNode methods directly
|
|
1591
|
+
* instead of making HTTP requests.
|
|
1592
|
+
*
|
|
1593
|
+
* Used for embedded mode where the ConnectorNode runs in-process.
|
|
1594
|
+
* The returned client conforms to the ConnectorAdminClient interface,
|
|
1595
|
+
* making it a drop-in replacement for the HTTP-based admin client.
|
|
1596
|
+
*
|
|
1597
|
+
* @param connector - A ConnectorNode instance (or any object matching ConnectorAdminLike)
|
|
1598
|
+
* @returns A ConnectorAdminClient that manages peers via direct function calls
|
|
1599
|
+
*
|
|
1600
|
+
* @example
|
|
1601
|
+
* ```typescript
|
|
1602
|
+
* import { ConnectorNode } from '@toon-protocol/connector';
|
|
1603
|
+
* import { createDirectConnectorAdmin } from '@toon-protocol/core/bootstrap';
|
|
1604
|
+
*
|
|
1605
|
+
* const connector = new ConnectorNode({ ... });
|
|
1606
|
+
* const adminClient = createDirectConnectorAdmin(connector);
|
|
1607
|
+
*
|
|
1608
|
+
* await adminClient.addPeer({
|
|
1609
|
+
* id: 'peer1',
|
|
1610
|
+
* url: 'btp+ws://peer1.example.com',
|
|
1611
|
+
* authToken: 'secret',
|
|
1612
|
+
* routes: [{ prefix: 'g.alice', priority: 1 }],
|
|
1613
|
+
* });
|
|
1614
|
+
* ```
|
|
1615
|
+
*/
|
|
1616
|
+
declare function createDirectConnectorAdmin(connector: ConnectorAdminLike): ConnectorAdminClient;
|
|
1617
|
+
|
|
1618
|
+
/**
|
|
1619
|
+
* Direct (in-process) client for payment channel operations via a ConnectorNode.
|
|
1620
|
+
*
|
|
1621
|
+
* Unlike HTTP-based channel clients, this factory wraps a ConnectorNode's
|
|
1622
|
+
* openChannel() and getChannelState() methods as a ConnectorChannelClient,
|
|
1623
|
+
* enabling zero-latency embedded mode without network overhead.
|
|
1624
|
+
*
|
|
1625
|
+
* Requires @toon-protocol/connector >=1.2.0 which exposes these methods
|
|
1626
|
+
* as public API on ConnectorNode.
|
|
1627
|
+
*/
|
|
1628
|
+
|
|
1629
|
+
/**
|
|
1630
|
+
* Structural interface matching ConnectorNode's channel methods.
|
|
1631
|
+
*
|
|
1632
|
+
* Consumers pass an `@toon-protocol/connector` ConnectorNode instance without
|
|
1633
|
+
* toon needing to import `@toon-protocol/connector` as a dependency.
|
|
1634
|
+
* TypeScript's structural type system handles compatibility automatically.
|
|
1635
|
+
*/
|
|
1636
|
+
interface ConnectorChannelLike {
|
|
1637
|
+
openChannel(params: {
|
|
1638
|
+
peerId: string;
|
|
1639
|
+
chain: string;
|
|
1640
|
+
token?: string;
|
|
1641
|
+
tokenNetwork?: string;
|
|
1642
|
+
peerAddress: string;
|
|
1643
|
+
initialDeposit?: string;
|
|
1644
|
+
settlementTimeout?: number;
|
|
1645
|
+
}): Promise<{
|
|
1646
|
+
channelId: string;
|
|
1647
|
+
status: string;
|
|
1648
|
+
}>;
|
|
1649
|
+
getChannelState(channelId: string): Promise<{
|
|
1650
|
+
channelId: string;
|
|
1651
|
+
status: 'opening' | 'open' | 'closed' | 'settled';
|
|
1652
|
+
chain: string;
|
|
1653
|
+
}>;
|
|
1654
|
+
}
|
|
1655
|
+
/**
|
|
1656
|
+
* Creates a ConnectorChannelClient that calls ConnectorNode methods directly
|
|
1657
|
+
* instead of making HTTP requests.
|
|
1658
|
+
*
|
|
1659
|
+
* Used for embedded mode where the ConnectorNode runs in-process.
|
|
1660
|
+
* The returned client conforms to the ConnectorChannelClient interface,
|
|
1661
|
+
* making it a drop-in replacement for the HTTP-based channel client.
|
|
1662
|
+
*
|
|
1663
|
+
* @param connector - A ConnectorNode instance (or any object matching ConnectorChannelLike)
|
|
1664
|
+
* @returns A ConnectorChannelClient that manages channels via direct function calls
|
|
1665
|
+
*
|
|
1666
|
+
* @example
|
|
1667
|
+
* ```typescript
|
|
1668
|
+
* import { ConnectorNode } from '@toon-protocol/connector';
|
|
1669
|
+
* import { createDirectChannelClient } from '@toon-protocol/core/bootstrap';
|
|
1670
|
+
*
|
|
1671
|
+
* const connector = new ConnectorNode({ ... });
|
|
1672
|
+
* const channelClient = createDirectChannelClient(connector);
|
|
1673
|
+
*
|
|
1674
|
+
* const result = await channelClient.openChannel({
|
|
1675
|
+
* peerId: 'nostr-54dad746e52dab00',
|
|
1676
|
+
* chain: 'evm:base:84532',
|
|
1677
|
+
* peerAddress: '0x6AFbC4...',
|
|
1678
|
+
* });
|
|
1679
|
+
* ```
|
|
1680
|
+
*/
|
|
1681
|
+
declare function createDirectChannelClient(connector: ConnectorChannelLike): ConnectorChannelClient;
|
|
1682
|
+
|
|
1683
|
+
/**
|
|
1684
|
+
* HTTP-based client for connector admin operations.
|
|
1685
|
+
*
|
|
1686
|
+
* Calls the connector's Admin API over HTTP to register/remove peers.
|
|
1687
|
+
*/
|
|
1688
|
+
|
|
1689
|
+
/**
|
|
1690
|
+
* Creates a ConnectorAdminClient that calls the Connector Admin API via HTTP.
|
|
1691
|
+
*
|
|
1692
|
+
* @param adminUrl - Base URL of the connector admin API (e.g., "http://connector:8081")
|
|
1693
|
+
* @param btpSecret - Shared secret for BTP authentication
|
|
1694
|
+
* @returns A ConnectorAdminClient that manages peers via HTTP
|
|
1695
|
+
*
|
|
1696
|
+
* @example
|
|
1697
|
+
* ```typescript
|
|
1698
|
+
* const adminClient = createHttpConnectorAdmin('http://localhost:8091', 'secret');
|
|
1699
|
+
*
|
|
1700
|
+
* await adminClient.addPeer({
|
|
1701
|
+
* id: 'peer2',
|
|
1702
|
+
* url: 'ws://connector-peer2:3000',
|
|
1703
|
+
* authToken: JSON.stringify({ peerId: 'peer2', secret: 'secret' }),
|
|
1704
|
+
* routes: [{ prefix: 'g.toon.peer2', priority: 0 }],
|
|
1705
|
+
* settlement: {
|
|
1706
|
+
* preference: 'evm',
|
|
1707
|
+
* evmAddress: '0x...',
|
|
1708
|
+
* chainId: 31337,
|
|
1709
|
+
* },
|
|
1710
|
+
* });
|
|
1711
|
+
* ```
|
|
1712
|
+
*/
|
|
1713
|
+
declare function createHttpConnectorAdmin(adminUrl: string, btpSecret: string): ConnectorAdminClient;
|
|
1714
|
+
|
|
1715
|
+
/**
|
|
1716
|
+
* HTTP-based client for sending ILP packets via the connector API.
|
|
1717
|
+
*
|
|
1718
|
+
* Calls the connector's packet handling endpoint over HTTP.
|
|
1719
|
+
*/
|
|
1720
|
+
|
|
1721
|
+
/**
|
|
1722
|
+
* Creates an IlpClient that sends ILP packets via HTTP.
|
|
1723
|
+
*
|
|
1724
|
+
* @param connectorUrl - Base URL of the connector (e.g., "http://connector:8080")
|
|
1725
|
+
* @returns An IlpClient instance
|
|
1726
|
+
*
|
|
1727
|
+
* @example
|
|
1728
|
+
* ```typescript
|
|
1729
|
+
* const ilpClient = createHttpIlpClient('http://localhost:8081');
|
|
1730
|
+
*
|
|
1731
|
+
* const result = await ilpClient.sendIlpPacket({
|
|
1732
|
+
* destination: 'g.toon.peer2',
|
|
1733
|
+
* amount: '1000',
|
|
1734
|
+
* data: base64EncodedToon,
|
|
1735
|
+
* });
|
|
1736
|
+
* ```
|
|
1737
|
+
*/
|
|
1738
|
+
declare function createHttpIlpClient(connectorUrl: string): IlpClient;
|
|
1739
|
+
|
|
1740
|
+
/**
|
|
1741
|
+
* HTTP-based client for payment channel operations.
|
|
1742
|
+
*
|
|
1743
|
+
* Calls the connector's Admin API to open channels and query channel state.
|
|
1744
|
+
*/
|
|
1745
|
+
|
|
1746
|
+
/**
|
|
1747
|
+
* Creates a ConnectorChannelClient that calls the Connector Admin API via HTTP.
|
|
1748
|
+
*
|
|
1749
|
+
* @param adminUrl - Base URL of the connector admin API (e.g., "http://connector:8081")
|
|
1750
|
+
* @returns A ConnectorChannelClient that manages channels via HTTP
|
|
1751
|
+
*
|
|
1752
|
+
* @example
|
|
1753
|
+
* ```typescript
|
|
1754
|
+
* const channelClient = createHttpChannelClient('http://localhost:8091');
|
|
1755
|
+
*
|
|
1756
|
+
* const result = await channelClient.openChannel({
|
|
1757
|
+
* peerId: 'peer2',
|
|
1758
|
+
* chain: 'evm:base:31337',
|
|
1759
|
+
* peerAddress: '0x90F79bf6EB2c4f870365E785982E1f101E93b906',
|
|
1760
|
+
* initialDeposit: '100000',
|
|
1761
|
+
* });
|
|
1762
|
+
* ```
|
|
1763
|
+
*/
|
|
1764
|
+
declare function createHttpChannelClient(adminUrl: string): ConnectorChannelClient;
|
|
1765
|
+
|
|
1766
|
+
/**
|
|
1767
|
+
* AttestationVerifier -- TEE attestation verification, state lifecycle,
|
|
1768
|
+
* and attestation-aware peer ranking for Story 4.3.
|
|
1769
|
+
*
|
|
1770
|
+
* This is a pure logic class with no transport layer. It receives parsed
|
|
1771
|
+
* attestation data and returns verification results. The transport layer
|
|
1772
|
+
* (subscribing to kind:10033 events on relays) is a Story 4.6 concern.
|
|
1773
|
+
*
|
|
1774
|
+
* The AttestationVerifier is the single source of truth for attestation
|
|
1775
|
+
* state (R-E4-008). Both the kind:10033 Nostr event path and the /health
|
|
1776
|
+
* HTTP endpoint derive their TEE state from the same verifier instance.
|
|
1777
|
+
*
|
|
1778
|
+
* Attestation State Machine (Decision 12):
|
|
1779
|
+
* VALID (within validitySeconds)
|
|
1780
|
+
* -> STALE (within graceSeconds after validity expires)
|
|
1781
|
+
* -> UNATTESTED (after grace period expires)
|
|
1782
|
+
*
|
|
1783
|
+
* Trust degrades; money doesn't -- attestation state changes never
|
|
1784
|
+
* trigger payment channel closure.
|
|
1785
|
+
*/
|
|
1786
|
+
|
|
1787
|
+
/**
|
|
1788
|
+
* Attestation lifecycle state.
|
|
1789
|
+
*
|
|
1790
|
+
* Transitions: VALID -> STALE -> UNATTESTED.
|
|
1791
|
+
* A peer that was never attested starts as UNATTESTED.
|
|
1792
|
+
*/
|
|
1793
|
+
declare enum AttestationState {
|
|
1794
|
+
/** Attestation is within validity period. */
|
|
1795
|
+
VALID = "valid",
|
|
1796
|
+
/** Attestation has expired but is within the grace period. */
|
|
1797
|
+
STALE = "stale",
|
|
1798
|
+
/** Attestation has expired past the grace period or was never attested. */
|
|
1799
|
+
UNATTESTED = "unattested"
|
|
1800
|
+
}
|
|
1801
|
+
/** Result of PCR verification against a known-good registry. */
|
|
1802
|
+
interface VerificationResult {
|
|
1803
|
+
valid: boolean;
|
|
1804
|
+
reason?: string;
|
|
1805
|
+
}
|
|
1806
|
+
/**
|
|
1807
|
+
* Descriptor for a peer in the attestation-aware ranking system.
|
|
1808
|
+
* Used by `rankPeers()` to order peers by attestation status.
|
|
1809
|
+
*/
|
|
1810
|
+
interface PeerDescriptor {
|
|
1811
|
+
pubkey: string;
|
|
1812
|
+
relayUrl: string;
|
|
1813
|
+
attested: boolean;
|
|
1814
|
+
attestationTimestamp?: number;
|
|
1815
|
+
}
|
|
1816
|
+
/**
|
|
1817
|
+
* Configuration for the AttestationVerifier.
|
|
1818
|
+
*/
|
|
1819
|
+
interface AttestationVerifierConfig {
|
|
1820
|
+
/** Map of known-good PCR values. Key is PCR hash, value is trust status. */
|
|
1821
|
+
knownGoodPcrs: Map<string, boolean>;
|
|
1822
|
+
/** Attestation validity period in seconds (default: 300). */
|
|
1823
|
+
validitySeconds?: number;
|
|
1824
|
+
/** Grace period in seconds after validity expires before marking as unattested (default: 30). */
|
|
1825
|
+
graceSeconds?: number;
|
|
1826
|
+
}
|
|
1827
|
+
/**
|
|
1828
|
+
* Verifies TEE attestations, computes attestation lifecycle state,
|
|
1829
|
+
* and ranks peers by attestation status.
|
|
1830
|
+
*
|
|
1831
|
+
* Single source of truth for attestation state (R-E4-008).
|
|
1832
|
+
*/
|
|
1833
|
+
declare class AttestationVerifier {
|
|
1834
|
+
private readonly knownGoodPcrs;
|
|
1835
|
+
private readonly validitySeconds;
|
|
1836
|
+
private readonly graceSeconds;
|
|
1837
|
+
constructor(config: AttestationVerifierConfig);
|
|
1838
|
+
/**
|
|
1839
|
+
* Verifies a TEE attestation's PCR values against the known-good registry.
|
|
1840
|
+
*
|
|
1841
|
+
* All three PCR values (pcr0, pcr1, pcr2) must be present and truthy in
|
|
1842
|
+
* the registry for verification to pass.
|
|
1843
|
+
*
|
|
1844
|
+
* @param attestation - The TEE attestation to verify.
|
|
1845
|
+
* @returns Verification result with `valid: true` or `valid: false` with reason.
|
|
1846
|
+
*/
|
|
1847
|
+
verify(attestation: TeeAttestation): VerificationResult;
|
|
1848
|
+
/**
|
|
1849
|
+
* Computes the attestation lifecycle state based on timing.
|
|
1850
|
+
*
|
|
1851
|
+
* Boundary behavior:
|
|
1852
|
+
* - At exactly `attestedAt + validitySeconds`: VALID (inclusive <=)
|
|
1853
|
+
* - At exactly `attestedAt + validitySeconds + graceSeconds`: STALE (inclusive <=)
|
|
1854
|
+
* - After grace expires: UNATTESTED
|
|
1855
|
+
*
|
|
1856
|
+
* @param _attestation - The TEE attestation (unused, reserved for future per-attestation logic).
|
|
1857
|
+
* @param attestedAt - Unix timestamp when the attestation was created.
|
|
1858
|
+
* @param now - Optional current unix timestamp (defaults to real clock).
|
|
1859
|
+
* @returns The current attestation state.
|
|
1860
|
+
*/
|
|
1861
|
+
getAttestationState(_attestation: TeeAttestation, attestedAt: number, now?: number): AttestationState;
|
|
1862
|
+
/**
|
|
1863
|
+
* Ranks peers by attestation status: attested peers first, then non-attested.
|
|
1864
|
+
*
|
|
1865
|
+
* Preserves relative order within each group (stable sort via filter).
|
|
1866
|
+
* Does NOT mutate the input array -- returns a new sorted array.
|
|
1867
|
+
*
|
|
1868
|
+
* Attestation is a preference, not a requirement. Non-attested peers
|
|
1869
|
+
* remain in the result and are connectable.
|
|
1870
|
+
*
|
|
1871
|
+
* @param peers - Array of peer descriptors to rank.
|
|
1872
|
+
* @returns New array with attested peers first, preserving relative order.
|
|
1873
|
+
*/
|
|
1874
|
+
rankPeers(peers: PeerDescriptor[]): PeerDescriptor[];
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1877
|
+
/**
|
|
1878
|
+
* AttestationBootstrap -- attestation-first seed relay bootstrap for Story 4.6.
|
|
1879
|
+
*
|
|
1880
|
+
* Implements FR-TEE-6: the bootstrap trust flow that verifies kind:10033 TEE
|
|
1881
|
+
* attestation on each seed relay BEFORE trusting its kind:10032 peer list.
|
|
1882
|
+
* This prevents seed relay list poisoning (R-E4-004).
|
|
1883
|
+
*
|
|
1884
|
+
* Trust flow:
|
|
1885
|
+
* 1. Read seed relay list from kind:10036 (Story 3.4)
|
|
1886
|
+
* 2. Connect to seed relay
|
|
1887
|
+
* 3. Query kind:10033 attestation
|
|
1888
|
+
* 4. Verify PCR measurement (Story 4.3)
|
|
1889
|
+
* 5. If valid -> subscribe to kind:10032 -> discover peers
|
|
1890
|
+
* 6. If invalid -> fall back to next seed relay
|
|
1891
|
+
*
|
|
1892
|
+
* This is a pure orchestration class with no transport logic. The
|
|
1893
|
+
* `queryAttestation` and `subscribePeers` callbacks are injected via DI,
|
|
1894
|
+
* keeping the class fully testable without WebSocket mocks.
|
|
1895
|
+
*
|
|
1896
|
+
* Decision 12 invariant: "Trust degrades; money doesn't." This class
|
|
1897
|
+
* never touches payment channel state.
|
|
1898
|
+
*/
|
|
1899
|
+
|
|
1900
|
+
/**
|
|
1901
|
+
* Configuration for the attestation-first bootstrap flow.
|
|
1902
|
+
*/
|
|
1903
|
+
interface AttestationBootstrapConfig {
|
|
1904
|
+
/** Seed relay WebSocket URLs from kind:10036 */
|
|
1905
|
+
seedRelays: string[];
|
|
1906
|
+
/**
|
|
1907
|
+
* Nostr secret key for signing (reserved for future use).
|
|
1908
|
+
* @remarks Stored in config but not accessed by bootstrap(). Maintained for
|
|
1909
|
+
* API consistency with BootstrapService and future subscription signing.
|
|
1910
|
+
*/
|
|
1911
|
+
secretKey: Uint8Array;
|
|
1912
|
+
/**
|
|
1913
|
+
* Verifier instance (or mock) with verify method.
|
|
1914
|
+
*
|
|
1915
|
+
* The DI interface accepts NostrEvent (the raw attestation event) and
|
|
1916
|
+
* returns boolean | Promise<boolean> | VerificationResult to support
|
|
1917
|
+
* both the real verifier (after caller extracts TeeAttestation) and
|
|
1918
|
+
* test mocks (which return Promise<boolean> via mockResolvedValue).
|
|
1919
|
+
*
|
|
1920
|
+
* The implementation normalizes via: await Promise.resolve(verifier.verify(event))
|
|
1921
|
+
*/
|
|
1922
|
+
verifier: {
|
|
1923
|
+
verify: (attestation: NostrEvent) => boolean | VerificationResult | Promise<boolean | VerificationResult>;
|
|
1924
|
+
getState?: (...args: unknown[]) => unknown;
|
|
1925
|
+
};
|
|
1926
|
+
/** DI callback: query a relay for its kind:10033 attestation event */
|
|
1927
|
+
queryAttestation: (relayUrl: string) => Promise<NostrEvent | null>;
|
|
1928
|
+
/** DI callback: subscribe to a relay's kind:10032 peer info events */
|
|
1929
|
+
subscribePeers: (relayUrl: string) => Promise<NostrEvent[]>;
|
|
1930
|
+
}
|
|
1931
|
+
/**
|
|
1932
|
+
* Result of the attestation-first bootstrap flow.
|
|
1933
|
+
*/
|
|
1934
|
+
interface AttestationBootstrapResult {
|
|
1935
|
+
/** 'attested' if at least one seed relay passed verification, 'degraded' otherwise */
|
|
1936
|
+
mode: 'attested' | 'degraded';
|
|
1937
|
+
/** URL of the first seed relay that passed attestation (undefined in degraded mode) */
|
|
1938
|
+
attestedSeedRelay?: string;
|
|
1939
|
+
/** Peer info events discovered from attested seed relays */
|
|
1940
|
+
discoveredPeers: NostrEvent[];
|
|
1941
|
+
}
|
|
1942
|
+
/**
|
|
1943
|
+
* Lifecycle events emitted during attestation-first bootstrap.
|
|
1944
|
+
*/
|
|
1945
|
+
type AttestationBootstrapEvent = {
|
|
1946
|
+
type: 'attestation:seed-connected';
|
|
1947
|
+
relayUrl: string;
|
|
1948
|
+
} | {
|
|
1949
|
+
type: 'attestation:verified';
|
|
1950
|
+
relayUrl: string;
|
|
1951
|
+
pubkey: string;
|
|
1952
|
+
} | {
|
|
1953
|
+
type: 'attestation:verification-failed';
|
|
1954
|
+
relayUrl: string;
|
|
1955
|
+
reason: string;
|
|
1956
|
+
} | {
|
|
1957
|
+
type: 'attestation:peers-discovered';
|
|
1958
|
+
relayUrl: string;
|
|
1959
|
+
peerCount: number;
|
|
1960
|
+
} | {
|
|
1961
|
+
type: 'attestation:degraded';
|
|
1962
|
+
triedCount: number;
|
|
1963
|
+
};
|
|
1964
|
+
/** Listener callback for attestation bootstrap events. */
|
|
1965
|
+
type AttestationBootstrapEventListener = (event: AttestationBootstrapEvent) => void;
|
|
1966
|
+
/**
|
|
1967
|
+
* Orchestrates attestation-first seed relay bootstrap.
|
|
1968
|
+
*
|
|
1969
|
+
* Iterates seed relays sequentially, verifying kind:10033 attestation
|
|
1970
|
+
* before subscribing to kind:10032 peer info events. Falls back to
|
|
1971
|
+
* degraded mode when all seed relays fail attestation verification.
|
|
1972
|
+
*/
|
|
1973
|
+
declare class AttestationBootstrap {
|
|
1974
|
+
private readonly config;
|
|
1975
|
+
private listeners;
|
|
1976
|
+
constructor(config: AttestationBootstrapConfig);
|
|
1977
|
+
/**
|
|
1978
|
+
* Register an event listener.
|
|
1979
|
+
*/
|
|
1980
|
+
on(listener: AttestationBootstrapEventListener): void;
|
|
1981
|
+
/**
|
|
1982
|
+
* Unregister an event listener.
|
|
1983
|
+
*/
|
|
1984
|
+
off(listener: AttestationBootstrapEventListener): void;
|
|
1985
|
+
/**
|
|
1986
|
+
* Emit an attestation bootstrap event to all listeners.
|
|
1987
|
+
*/
|
|
1988
|
+
private emit;
|
|
1989
|
+
/**
|
|
1990
|
+
* Execute the attestation-first bootstrap flow.
|
|
1991
|
+
*
|
|
1992
|
+
* Iterates seed relays in order:
|
|
1993
|
+
* 1. Emit seed-connected, query attestation
|
|
1994
|
+
* 2. If null or verify fails or error: emit verification-failed, try next
|
|
1995
|
+
* 3. If valid: emit verified, subscribe peers, emit peers-discovered
|
|
1996
|
+
* 4. Return attested result with discovered peers
|
|
1997
|
+
* 5. If ALL fail: log warning, emit degraded, return degraded result
|
|
1998
|
+
*/
|
|
1999
|
+
bootstrap(): Promise<AttestationBootstrapResult>;
|
|
2000
|
+
}
|
|
2001
|
+
|
|
2002
|
+
/**
|
|
2003
|
+
* TOON Node composition API.
|
|
2004
|
+
*
|
|
2005
|
+
* Provides createToonNode() — a single composition function that wires
|
|
2006
|
+
* ConnectorNode ↔ BLS ↔ BootstrapService ↔ DiscoveryTracker into one object
|
|
2007
|
+
* with start() / stop() lifecycle, enabling zero-latency embedded mode without
|
|
2008
|
+
* manually wiring each component.
|
|
2009
|
+
*/
|
|
2010
|
+
|
|
2011
|
+
/**
|
|
2012
|
+
* Structural type for incoming ILP packet handler request.
|
|
2013
|
+
*
|
|
2014
|
+
* Matches the shape of BLS HandlePacketRequest without creating a cross-package
|
|
2015
|
+
* dependency from @toon-protocol/core → @toon-protocol/bls.
|
|
2016
|
+
*/
|
|
2017
|
+
interface HandlePacketRequest {
|
|
2018
|
+
/** Payment amount as string (parsed to bigint) */
|
|
2019
|
+
amount: string;
|
|
2020
|
+
/** ILP destination address */
|
|
2021
|
+
destination: string;
|
|
2022
|
+
/** Base64-encoded TOON Nostr event */
|
|
2023
|
+
data: string;
|
|
2024
|
+
/** Source ILP address */
|
|
2025
|
+
sourceAccount?: string;
|
|
2026
|
+
}
|
|
2027
|
+
/**
|
|
2028
|
+
* Structural type for ILP packet handler accept response.
|
|
2029
|
+
*/
|
|
2030
|
+
interface HandlePacketAcceptResponse {
|
|
2031
|
+
accept: true;
|
|
2032
|
+
/** Base64-encoded fulfillment (SHA-256 of event.id) */
|
|
2033
|
+
fulfillment: string;
|
|
2034
|
+
/** Base64-encoded response data (e.g., TOON-encoded response for relay back in ILP FULFILL) */
|
|
2035
|
+
data?: string;
|
|
2036
|
+
metadata?: Record<string, unknown>;
|
|
2037
|
+
}
|
|
2038
|
+
/**
|
|
2039
|
+
* Structural type for ILP packet handler reject response.
|
|
2040
|
+
*/
|
|
2041
|
+
interface HandlePacketRejectResponse {
|
|
2042
|
+
accept: false;
|
|
2043
|
+
/** ILP error code (F00, F06, T00) */
|
|
2044
|
+
code: string;
|
|
2045
|
+
/** Human-readable error message */
|
|
2046
|
+
message: string;
|
|
2047
|
+
metadata?: Record<string, unknown>;
|
|
2048
|
+
}
|
|
2049
|
+
/**
|
|
2050
|
+
* Union type for ILP packet handler response.
|
|
2051
|
+
*/
|
|
2052
|
+
type HandlePacketResponse = HandlePacketAcceptResponse | HandlePacketRejectResponse;
|
|
2053
|
+
/**
|
|
2054
|
+
* Callback invoked by the connector for incoming ILP packets.
|
|
2055
|
+
*
|
|
2056
|
+
* **NOTE:** This is a **function** (not a BusinessLogicServer instance) because
|
|
2057
|
+
* packet handling logic lives in the caller's entrypoint code, not in
|
|
2058
|
+
* BusinessLogicServer. The caller provides the full handler that knows how to
|
|
2059
|
+
* process incoming events.
|
|
2060
|
+
*/
|
|
2061
|
+
type PacketHandler = (request: HandlePacketRequest) => HandlePacketResponse | Promise<HandlePacketResponse>;
|
|
2062
|
+
/**
|
|
2063
|
+
* Structural interface for the full embedded connector API.
|
|
2064
|
+
*
|
|
2065
|
+
* Combines:
|
|
2066
|
+
* 1. ConnectorNodeLike (sendPacket) — for outbound ILP packets
|
|
2067
|
+
* 2. ConnectorAdminLike (registerPeer, removePeer) — for peer management
|
|
2068
|
+
* 3. setPacketHandler(handler) — for registering the incoming packet callback
|
|
2069
|
+
*
|
|
2070
|
+
* This structural interface allows @toon-protocol/connector's ConnectorNode to
|
|
2071
|
+
* be passed directly without importing it as a dependency.
|
|
2072
|
+
*/
|
|
2073
|
+
interface EmbeddableConnectorLike {
|
|
2074
|
+
/** Send an outbound ILP packet */
|
|
2075
|
+
sendPacket(params: SendPacketParams): Promise<SendPacketResult>;
|
|
2076
|
+
/** Register a peer with the connector */
|
|
2077
|
+
registerPeer(params: RegisterPeerParams): Promise<void>;
|
|
2078
|
+
/** Remove a peer from the connector */
|
|
2079
|
+
removePeer(peerId: string): Promise<void>;
|
|
2080
|
+
/**
|
|
2081
|
+
* Register the incoming packet handler callback.
|
|
2082
|
+
* The connector invokes this handler for each incoming ILP packet.
|
|
2083
|
+
* Optional in HTTP mode where packets are delivered via local delivery HTTP endpoint.
|
|
2084
|
+
*/
|
|
2085
|
+
setPacketHandler?(handler: (request: HandlePacketRequest) => HandlePacketResponse | Promise<HandlePacketResponse>): void;
|
|
2086
|
+
/**
|
|
2087
|
+
* Open a payment channel via the connector's settlement layer.
|
|
2088
|
+
* Optional — only available on ConnectorNode >=1.2.0.
|
|
2089
|
+
*/
|
|
2090
|
+
openChannel?(params: {
|
|
2091
|
+
peerId: string;
|
|
2092
|
+
chain: string;
|
|
2093
|
+
token?: string;
|
|
2094
|
+
tokenNetwork?: string;
|
|
2095
|
+
peerAddress: string;
|
|
2096
|
+
initialDeposit?: string;
|
|
2097
|
+
settlementTimeout?: number;
|
|
2098
|
+
}): Promise<{
|
|
2099
|
+
channelId: string;
|
|
2100
|
+
status: string;
|
|
2101
|
+
}>;
|
|
2102
|
+
/**
|
|
2103
|
+
* Get the state of a payment channel.
|
|
2104
|
+
* Optional — only available on ConnectorNode >=1.2.0.
|
|
2105
|
+
*/
|
|
2106
|
+
getChannelState?(channelId: string): Promise<{
|
|
2107
|
+
channelId: string;
|
|
2108
|
+
status: 'opening' | 'open' | 'closed' | 'settled';
|
|
2109
|
+
chain: string;
|
|
2110
|
+
}>;
|
|
2111
|
+
}
|
|
2112
|
+
/**
|
|
2113
|
+
* Configuration for creating an TOON Node.
|
|
2114
|
+
*/
|
|
2115
|
+
interface ToonNodeConfig {
|
|
2116
|
+
/** The ConnectorNode instance (embeddable connector) */
|
|
2117
|
+
connector: EmbeddableConnectorLike;
|
|
2118
|
+
/**
|
|
2119
|
+
* Callback for incoming ILP packets.
|
|
2120
|
+
*
|
|
2121
|
+
* **NOTE:** Provided as a **function** (not a BLS instance) because packet
|
|
2122
|
+
* handling logic lives in the caller's entrypoint code.
|
|
2123
|
+
*/
|
|
2124
|
+
handlePacket: PacketHandler;
|
|
2125
|
+
/** Nostr secret key (32 bytes) */
|
|
2126
|
+
secretKey: Uint8Array;
|
|
2127
|
+
/** Own ILP peer info (ilpAddress, btpEndpoint, assetCode, assetScale) */
|
|
2128
|
+
ilpInfo: IlpPeerInfo;
|
|
2129
|
+
/**
|
|
2130
|
+
* TOON encoder — **required** for encoding Nostr events to binary.
|
|
2131
|
+
* Used by BootstrapService.
|
|
2132
|
+
*/
|
|
2133
|
+
toonEncoder: (event: NostrEvent) => Uint8Array;
|
|
2134
|
+
/**
|
|
2135
|
+
* TOON decoder — **required** for decoding binary to Nostr events.
|
|
2136
|
+
* Used by BootstrapService and DirectRuntimeClient.
|
|
2137
|
+
*/
|
|
2138
|
+
toonDecoder: (bytes: Uint8Array) => NostrEvent;
|
|
2139
|
+
/** Relay WebSocket URL for monitoring (default: 'ws://localhost:7100') */
|
|
2140
|
+
relayUrl?: string;
|
|
2141
|
+
/** Initial bootstrap peers (default: []) */
|
|
2142
|
+
knownPeers?: KnownPeer[];
|
|
2143
|
+
/** Optional settlement preferences for peer registration */
|
|
2144
|
+
settlementInfo?: SettlementConfig;
|
|
2145
|
+
/** Base price per byte for ILP packet pricing (default: 10n) */
|
|
2146
|
+
basePricePerByte?: bigint;
|
|
2147
|
+
/** Enable ArDrive peer lookup (default: true) */
|
|
2148
|
+
ardriveEnabled?: boolean;
|
|
2149
|
+
/** Default relay URL for ArDrive-sourced peers that lack relay URLs (default: '') */
|
|
2150
|
+
defaultRelayUrl?: string;
|
|
2151
|
+
/** Timeout for relay queries in milliseconds (default: 5000) */
|
|
2152
|
+
queryTimeout?: number;
|
|
2153
|
+
/** Optional extra peers JSON for bootstrap */
|
|
2154
|
+
additionalPeersJson?: string;
|
|
2155
|
+
}
|
|
2156
|
+
/**
|
|
2157
|
+
* Result returned by ToonNode.start().
|
|
2158
|
+
*/
|
|
2159
|
+
interface ToonNodeStartResult {
|
|
2160
|
+
/** Results from the bootstrap phase */
|
|
2161
|
+
bootstrapResults: BootstrapResult[];
|
|
2162
|
+
/** Number of peers successfully bootstrapped */
|
|
2163
|
+
peerCount: number;
|
|
2164
|
+
/** Number of payment channels opened */
|
|
2165
|
+
channelCount: number;
|
|
2166
|
+
}
|
|
2167
|
+
/**
|
|
2168
|
+
* TOON Node instance with lifecycle methods.
|
|
2169
|
+
*/
|
|
2170
|
+
interface ToonNode {
|
|
2171
|
+
/**
|
|
2172
|
+
* Wire components and run bootstrap.
|
|
2173
|
+
* Throws BootstrapError if already started or on bootstrap failure.
|
|
2174
|
+
*/
|
|
2175
|
+
start(): Promise<ToonNodeStartResult>;
|
|
2176
|
+
/**
|
|
2177
|
+
* Tear down and clean up.
|
|
2178
|
+
* Safe to call when not started (no-op).
|
|
2179
|
+
*/
|
|
2180
|
+
stop(): Promise<void>;
|
|
2181
|
+
/**
|
|
2182
|
+
* Read-only access to the bootstrap service.
|
|
2183
|
+
* Allows attaching event listeners before calling start().
|
|
2184
|
+
*/
|
|
2185
|
+
readonly bootstrapService: BootstrapService;
|
|
2186
|
+
/**
|
|
2187
|
+
* Read-only access to the discovery tracker.
|
|
2188
|
+
* Allows attaching event listeners before calling start().
|
|
2189
|
+
*/
|
|
2190
|
+
readonly discoveryTracker: DiscoveryTracker;
|
|
2191
|
+
/**
|
|
2192
|
+
* Channel client for payment channel operations.
|
|
2193
|
+
* Null if the connector does not expose openChannel()/getChannelState().
|
|
2194
|
+
* Available when using @toon-protocol/connector >=1.2.0.
|
|
2195
|
+
*/
|
|
2196
|
+
readonly channelClient: ConnectorChannelClient | null;
|
|
2197
|
+
/**
|
|
2198
|
+
* Read-only access to the ILP client for sending packets.
|
|
2199
|
+
* Used by ServiceNode.publishEvent() to send outbound events.
|
|
2200
|
+
*/
|
|
2201
|
+
readonly ilpClient: IlpClient;
|
|
2202
|
+
/**
|
|
2203
|
+
* Initiate peering with a discovered peer.
|
|
2204
|
+
* The peer must have been discovered by the discovery tracker first.
|
|
2205
|
+
* Registers the peer with the connector and attempts settlement.
|
|
2206
|
+
*/
|
|
2207
|
+
peerWith(pubkey: string): Promise<void>;
|
|
2208
|
+
}
|
|
2209
|
+
/**
|
|
2210
|
+
* Create a TOON Node with integrated bootstrap and discovery tracking.
|
|
2211
|
+
*
|
|
2212
|
+
* This composition function wires ConnectorNode ↔ DirectRuntimeClient ↔
|
|
2213
|
+
* DirectConnectorAdmin ↔ BootstrapService ↔ DiscoveryTracker into a single
|
|
2214
|
+
* object with start() / stop() lifecycle, enabling zero-latency embedded mode
|
|
2215
|
+
* without manually wiring each component.
|
|
2216
|
+
*
|
|
2217
|
+
* @param config - Configuration for the node
|
|
2218
|
+
* @returns ToonNode instance with start() / stop() methods
|
|
2219
|
+
*
|
|
2220
|
+
* @example
|
|
2221
|
+
* ```typescript
|
|
2222
|
+
* import { ConnectorNode } from '@toon-protocol/connector';
|
|
2223
|
+
* import { createToonNode } from '@toon-protocol/core/compose';
|
|
2224
|
+
* import { encodeEvent, decodeEvent } from '@toon-protocol/relay';
|
|
2225
|
+
*
|
|
2226
|
+
* const connector = new ConnectorNode({ ... });
|
|
2227
|
+
*
|
|
2228
|
+
* const node = createToonNode({
|
|
2229
|
+
* connector,
|
|
2230
|
+
* handlePacket: async (req) => { ... },
|
|
2231
|
+
* secretKey: new Uint8Array(32),
|
|
2232
|
+
* ilpInfo: { ilpAddress: 'g.example', ... },
|
|
2233
|
+
* toonEncoder: encodeEvent,
|
|
2234
|
+
* toonDecoder: decodeEvent,
|
|
2235
|
+
* });
|
|
2236
|
+
*
|
|
2237
|
+
* // Attach event listeners before start
|
|
2238
|
+
* node.bootstrapService.on((event) => console.log('bootstrap:', event));
|
|
2239
|
+
* node.discoveryTracker.on((event) => console.log('discovery:', event));
|
|
2240
|
+
*
|
|
2241
|
+
* // Start the node
|
|
2242
|
+
* const result = await node.start();
|
|
2243
|
+
* console.log(`Bootstrapped ${result.peerCount} peers`);
|
|
2244
|
+
*
|
|
2245
|
+
* // Clean up
|
|
2246
|
+
* await node.stop();
|
|
2247
|
+
* ```
|
|
2248
|
+
*/
|
|
2249
|
+
declare function createToonNode(config: ToonNodeConfig): ToonNode;
|
|
2250
|
+
|
|
2251
|
+
/**
|
|
2252
|
+
* Mock USDC token configuration for local development (Anvil).
|
|
2253
|
+
*
|
|
2254
|
+
* In production, USDC is the native Circle USD Coin on Arbitrum One:
|
|
2255
|
+
* 0xaf88d065e77c8cC2239327C5EDb3A432268e5831
|
|
2256
|
+
*
|
|
2257
|
+
* For local development on Anvil, a mock ERC-20 is deployed at a
|
|
2258
|
+
* deterministic address by the DeployLocal.s.sol script in the connector
|
|
2259
|
+
* repo. This contract serves as the mock USDC for payment channel testing.
|
|
2260
|
+
*
|
|
2261
|
+
* **On-chain decimal discrepancy (Anvil only):**
|
|
2262
|
+
* The legacy on-chain mock contract on Anvil uses 18 decimals (inherited
|
|
2263
|
+
* from the original ERC-20 deploy script in the connector repo). The
|
|
2264
|
+
* constants below reflect production USDC semantics (6 decimals). When
|
|
2265
|
+
* interacting with the Anvil mock contract directly (e.g., fund-peer-wallet.sh,
|
|
2266
|
+
* faucet), use 18 decimals for on-chain amounts. The pricing pipeline
|
|
2267
|
+
* (basePricePerByte * toonLength) is denomination-agnostic (bigint math)
|
|
2268
|
+
* and works correctly regardless of on-chain decimals.
|
|
2269
|
+
*
|
|
2270
|
+
* **FiatTokenV2_2-compatible mock (Epic 5 prep):**
|
|
2271
|
+
* For DVM compute settlement and x402 testing with proper 6-decimal
|
|
2272
|
+
* semantics and EIP-3009 `transferWithAuthorization` support, deploy
|
|
2273
|
+
* the FiatTokenV2_2-compatible mock:
|
|
2274
|
+
* `./scripts/deploy-mock-usdc.sh`
|
|
2275
|
+
* This deploys a contract with 6 decimals, EIP-3009, and EIP-712
|
|
2276
|
+
* domain matching production USDC ("USD Coin", version "2").
|
|
2277
|
+
*
|
|
2278
|
+
* USDC uses 6 decimals (not 18 like most ERC-20 tokens):
|
|
2279
|
+
* 1 USDC = 1,000,000 micro-USDC (10^6)
|
|
2280
|
+
*
|
|
2281
|
+
* @module
|
|
2282
|
+
*/
|
|
2283
|
+
/**
|
|
2284
|
+
* Mock USDC contract address on Anvil (deterministic from deployment).
|
|
2285
|
+
*
|
|
2286
|
+
* This is the first contract deployed by DeployLocal.s.sol using
|
|
2287
|
+
* Anvil Account #0 at nonce 0, giving it a deterministic address.
|
|
2288
|
+
*/
|
|
2289
|
+
declare const MOCK_USDC_ADDRESS: "0x5FbDB2315678afecb367f032d93F642f64180aa3";
|
|
2290
|
+
/**
|
|
2291
|
+
* USDC uses 6 decimals (1 USDC = 1,000,000 micro-units).
|
|
2292
|
+
*
|
|
2293
|
+
* This differs from most ERC-20 tokens which use 18 decimals.
|
|
2294
|
+
* All pricing amounts in the TOON protocol are denominated
|
|
2295
|
+
* in USDC micro-units when using USDC as the settlement token.
|
|
2296
|
+
*/
|
|
2297
|
+
declare const USDC_DECIMALS: 6;
|
|
2298
|
+
/** USDC token symbol. */
|
|
2299
|
+
declare const USDC_SYMBOL: "USDC";
|
|
2300
|
+
/** USDC token name. */
|
|
2301
|
+
declare const USDC_NAME: "USD Coin";
|
|
2302
|
+
/**
|
|
2303
|
+
* Configuration for the mock USDC contract deployment.
|
|
2304
|
+
*/
|
|
2305
|
+
interface MockUsdcConfig {
|
|
2306
|
+
/** Contract address on the target chain */
|
|
2307
|
+
address: string;
|
|
2308
|
+
/** Number of decimal places (6 for USDC) */
|
|
2309
|
+
decimals: number;
|
|
2310
|
+
/** Token symbol */
|
|
2311
|
+
symbol: string;
|
|
2312
|
+
/** Token name */
|
|
2313
|
+
name: string;
|
|
2314
|
+
}
|
|
2315
|
+
/**
|
|
2316
|
+
* Default mock USDC configuration for Anvil local development.
|
|
2317
|
+
*/
|
|
2318
|
+
declare const MOCK_USDC_CONFIG: MockUsdcConfig;
|
|
2319
|
+
|
|
2320
|
+
/**
|
|
2321
|
+
* Multi-environment chain configuration for TOON relay nodes.
|
|
2322
|
+
*
|
|
2323
|
+
* Provides chain presets for three deployment environments:
|
|
2324
|
+
* - **anvil** (local dev): Deterministic Anvil addresses, localhost RPC
|
|
2325
|
+
* - **arbitrum-sepolia** (staging): Circle testnet USDC on Arbitrum Sepolia
|
|
2326
|
+
* - **arbitrum-one** (production): Native USDC on Arbitrum One
|
|
2327
|
+
*
|
|
2328
|
+
* Environment variable overrides:
|
|
2329
|
+
* - `TOON_CHAIN` overrides the config-level chain parameter
|
|
2330
|
+
* - `TOON_RPC_URL` overrides the preset RPC endpoint
|
|
2331
|
+
* - `TOON_TOKEN_NETWORK` overrides the preset TokenNetwork address
|
|
2332
|
+
*
|
|
2333
|
+
* @module
|
|
2334
|
+
*/
|
|
2335
|
+
/**
|
|
2336
|
+
* Supported chain preset names.
|
|
2337
|
+
*/
|
|
2338
|
+
type ChainName = 'anvil' | 'arbitrum-sepolia' | 'arbitrum-one';
|
|
2339
|
+
/**
|
|
2340
|
+
* Resolved chain configuration with all fields populated.
|
|
2341
|
+
*/
|
|
2342
|
+
interface ChainPreset {
|
|
2343
|
+
/** Preset identifier ('anvil' | 'arbitrum-sepolia' | 'arbitrum-one'). */
|
|
2344
|
+
name: string;
|
|
2345
|
+
/** EVM chain ID. */
|
|
2346
|
+
chainId: number;
|
|
2347
|
+
/** Default RPC endpoint URL. */
|
|
2348
|
+
rpcUrl: string;
|
|
2349
|
+
/** USDC token contract address on this chain. */
|
|
2350
|
+
usdcAddress: string;
|
|
2351
|
+
/** TokenNetwork contract address for USDC on this chain. */
|
|
2352
|
+
tokenNetworkAddress: string;
|
|
2353
|
+
}
|
|
2354
|
+
/**
|
|
2355
|
+
* Built-in chain presets for supported deployment environments.
|
|
2356
|
+
*
|
|
2357
|
+
* Each preset provides the chainId, RPC URL, USDC address, and
|
|
2358
|
+
* TokenNetwork address for its environment. Fields can be overridden
|
|
2359
|
+
* at runtime via environment variables.
|
|
2360
|
+
*/
|
|
2361
|
+
declare const CHAIN_PRESETS: Record<ChainName, ChainPreset>;
|
|
2362
|
+
/**
|
|
2363
|
+
* Resolve chain configuration from a chain name, with environment
|
|
2364
|
+
* variable overrides applied.
|
|
2365
|
+
*
|
|
2366
|
+
* Resolution order:
|
|
2367
|
+
* 1. `TOON_CHAIN` env var overrides the `chain` parameter
|
|
2368
|
+
* 2. Defaults to `'anvil'` if neither is provided
|
|
2369
|
+
* 3. Looks up the chain name in `CHAIN_PRESETS`
|
|
2370
|
+
* 4. `TOON_RPC_URL` env var overrides the preset's `rpcUrl`
|
|
2371
|
+
* 5. `TOON_TOKEN_NETWORK` env var overrides the preset's `tokenNetworkAddress`
|
|
2372
|
+
*
|
|
2373
|
+
* Returns a defensive copy -- callers can mutate the result without
|
|
2374
|
+
* affecting the shared preset objects.
|
|
2375
|
+
*
|
|
2376
|
+
* @param chain - Chain name to resolve (default: 'anvil')
|
|
2377
|
+
* @returns Resolved chain preset with env var overrides applied
|
|
2378
|
+
* @throws ToonError if the chain name is not recognized
|
|
2379
|
+
*/
|
|
2380
|
+
declare function resolveChainConfig(chain?: ChainName | string): ChainPreset;
|
|
2381
|
+
/**
|
|
2382
|
+
* Build an EIP-712 domain separator from a resolved chain configuration.
|
|
2383
|
+
*
|
|
2384
|
+
* The returned domain matches the structure used by
|
|
2385
|
+
* `getBalanceProofDomain()` in `packages/client/src/signing/evm-signer.ts`:
|
|
2386
|
+
*
|
|
2387
|
+
* ```typescript
|
|
2388
|
+
* { name: 'TokenNetwork', version: '1', chainId, verifyingContract }
|
|
2389
|
+
* ```
|
|
2390
|
+
*
|
|
2391
|
+
* Since `@toon-protocol/core` does not depend on viem, the `verifyingContract`
|
|
2392
|
+
* field is typed as `string` (not viem's `Hex`). Consumers in the client
|
|
2393
|
+
* package can cast to `Hex` if needed.
|
|
2394
|
+
*
|
|
2395
|
+
* @param config - Resolved chain preset
|
|
2396
|
+
* @returns EIP-712 domain separator object
|
|
2397
|
+
*/
|
|
2398
|
+
declare function buildEip712Domain(config: ChainPreset): {
|
|
2399
|
+
name: string;
|
|
2400
|
+
version: string;
|
|
2401
|
+
chainId: number;
|
|
2402
|
+
verifyingContract: string;
|
|
2403
|
+
};
|
|
2404
|
+
|
|
2405
|
+
/**
|
|
2406
|
+
* Shared ILP PREPARE packet construction for the TOON protocol.
|
|
2407
|
+
*
|
|
2408
|
+
* This function is the **single point of truth** for constructing ILP PREPARE
|
|
2409
|
+
* packet parameters. Both the x402 `/publish` handler and the existing
|
|
2410
|
+
* `publishEvent()` in the SDK must use it (or produce equivalent output).
|
|
2411
|
+
*
|
|
2412
|
+
* This ensures packet equivalence: the destination relay cannot distinguish
|
|
2413
|
+
* between packets sent via the x402 HTTP on-ramp and the ILP-native rail.
|
|
2414
|
+
*
|
|
2415
|
+
* @module
|
|
2416
|
+
*/
|
|
2417
|
+
/**
|
|
2418
|
+
* Parameters for constructing an ILP PREPARE packet.
|
|
2419
|
+
*/
|
|
2420
|
+
interface BuildIlpPrepareParams {
|
|
2421
|
+
/** ILP destination address (e.g., "g.toon.target-relay"). */
|
|
2422
|
+
destination: string;
|
|
2423
|
+
/** Payment amount in ILP units (bigint). */
|
|
2424
|
+
amount: bigint;
|
|
2425
|
+
/** TOON-encoded event as raw bytes. */
|
|
2426
|
+
data: Uint8Array;
|
|
2427
|
+
/** Packet expiry. Default: 30 seconds from now. */
|
|
2428
|
+
expiresAt?: Date;
|
|
2429
|
+
}
|
|
2430
|
+
/**
|
|
2431
|
+
* Result of building an ILP PREPARE packet.
|
|
2432
|
+
*
|
|
2433
|
+
* This matches the shape expected by `IlpClient.sendIlpPacket()`:
|
|
2434
|
+
* `{ destination, amount, data }` where amount is a string and data
|
|
2435
|
+
* is base64-encoded.
|
|
2436
|
+
*/
|
|
2437
|
+
interface IlpPreparePacket {
|
|
2438
|
+
/** ILP destination address. */
|
|
2439
|
+
destination: string;
|
|
2440
|
+
/** Payment amount as a string (BigInt.toString()). */
|
|
2441
|
+
amount: string;
|
|
2442
|
+
/** TOON-encoded event as base64 string. */
|
|
2443
|
+
data: string;
|
|
2444
|
+
}
|
|
2445
|
+
/**
|
|
2446
|
+
* Build an ILP PREPARE packet from the given parameters.
|
|
2447
|
+
*
|
|
2448
|
+
* Converts the bigint amount to a string, encodes the TOON data to base64,
|
|
2449
|
+
* and passes through the destination. This is deliberately simple -- the
|
|
2450
|
+
* value is in having ONE function both the x402 and ILP paths call, not
|
|
2451
|
+
* in complex logic.
|
|
2452
|
+
*
|
|
2453
|
+
* @param params - Packet construction parameters.
|
|
2454
|
+
* @returns ILP PREPARE packet fields ready for `sendIlpPacket()`.
|
|
2455
|
+
*/
|
|
2456
|
+
declare function buildIlpPrepare(params: BuildIlpPrepareParams): IlpPreparePacket;
|
|
2457
|
+
|
|
2458
|
+
/**
|
|
2459
|
+
* KMS identity derivation for TEE enclave-bound keypairs.
|
|
2460
|
+
*
|
|
2461
|
+
* Derives a Nostr-compatible secp256k1 keypair from a raw 32-byte Nautilus
|
|
2462
|
+
* KMS seed using the NIP-06 derivation path (m/44'/1237'/0'/0/{index}).
|
|
2463
|
+
*
|
|
2464
|
+
* The KMS seed is only accessible when the enclave's attestation is valid
|
|
2465
|
+
* (correct PCR values). If the relay code changes, PCR values change,
|
|
2466
|
+
* attestation fails, KMS seed becomes inaccessible, and the relay loses its
|
|
2467
|
+
* identity -- creating a cryptographic binding: identity proves code integrity.
|
|
2468
|
+
*
|
|
2469
|
+
* This module lives in @toon-protocol/core (not SDK) because Docker entrypoints
|
|
2470
|
+
* import from core. It does NOT include EVM address derivation (SDK concern).
|
|
2471
|
+
*/
|
|
2472
|
+
|
|
2473
|
+
/**
|
|
2474
|
+
* Error thrown when KMS identity derivation fails.
|
|
2475
|
+
* Signals that the enclave cannot derive its identity -- this is a
|
|
2476
|
+
* security-critical condition that must NEVER fall back to random keys.
|
|
2477
|
+
*/
|
|
2478
|
+
declare class KmsIdentityError extends ToonError {
|
|
2479
|
+
constructor(message: string, cause?: Error);
|
|
2480
|
+
}
|
|
2481
|
+
/** A Nostr keypair derived from a KMS seed. */
|
|
2482
|
+
interface KmsKeypair {
|
|
2483
|
+
/** The 32-byte secp256k1 secret key derived from the KMS seed. */
|
|
2484
|
+
secretKey: Uint8Array;
|
|
2485
|
+
/** The x-only Schnorr public key (32 bytes, 64 lowercase hex characters). */
|
|
2486
|
+
pubkey: string;
|
|
2487
|
+
}
|
|
2488
|
+
/** Options for `deriveFromKmsSeed()`. */
|
|
2489
|
+
interface DeriveFromKmsSeedOptions {
|
|
2490
|
+
/** BIP-39 mnemonic -- when provided, takes precedence over raw seed for derivation. */
|
|
2491
|
+
mnemonic?: string;
|
|
2492
|
+
/** Key index in the NIP-06 derivation path. Defaults to 0. */
|
|
2493
|
+
accountIndex?: number;
|
|
2494
|
+
}
|
|
2495
|
+
/**
|
|
2496
|
+
* Derives a Nostr keypair from a raw 32-byte KMS seed or BIP-39 mnemonic
|
|
2497
|
+
* using the NIP-06 derivation path.
|
|
2498
|
+
*
|
|
2499
|
+
* When `options.mnemonic` is provided it takes precedence over the raw seed.
|
|
2500
|
+
* The raw seed is still validated even when a mnemonic is supplied (caller
|
|
2501
|
+
* must always provide a valid seed to prove KMS reachability).
|
|
2502
|
+
*
|
|
2503
|
+
* @param seed - A 32-byte Uint8Array from Nautilus KMS.
|
|
2504
|
+
* @param options - Optional derivation overrides (mnemonic, accountIndex).
|
|
2505
|
+
* @returns A `KmsKeypair` with `secretKey` and `pubkey`.
|
|
2506
|
+
* @throws {KmsIdentityError} If the seed is invalid or derivation fails.
|
|
2507
|
+
*/
|
|
2508
|
+
declare function deriveFromKmsSeed(seed: Uint8Array, options?: DeriveFromKmsSeedOptions): KmsKeypair;
|
|
2509
|
+
|
|
2510
|
+
/**
|
|
2511
|
+
* Nix Build Orchestration for Reproducible Docker Images
|
|
2512
|
+
*
|
|
2513
|
+
* The NixBuilder class wraps the `nix build` CLI invocation to produce
|
|
2514
|
+
* deterministic Docker images for TEE (Trusted Execution Environment)
|
|
2515
|
+
* deployment. Each build returns a NixBuildResult containing the image
|
|
2516
|
+
* hash, PCR (Platform Configuration Register) values, and Nix store path.
|
|
2517
|
+
*
|
|
2518
|
+
* PCR values are SHA-384 hashes measured by the TEE hardware from the
|
|
2519
|
+
* loaded image. If the Docker image is deterministic (identical content
|
|
2520
|
+
* hash across builds), then PCR values will also be identical -- enabling
|
|
2521
|
+
* remote attestation verification (Story 4.3 AttestationVerifier).
|
|
2522
|
+
*
|
|
2523
|
+
* IMPORTANT: The NixBuilder shells out to `nix build` -- it requires
|
|
2524
|
+
* the Nix package manager to be installed on the build machine. Tests
|
|
2525
|
+
* that exercise actual Nix builds should be conditionally skipped when
|
|
2526
|
+
* Nix is not available. Unit tests use mocked child_process.
|
|
2527
|
+
*
|
|
2528
|
+
* @module
|
|
2529
|
+
*/
|
|
2530
|
+
/**
|
|
2531
|
+
* Result of a Nix build invocation.
|
|
2532
|
+
* Contains the Docker image content hash, PCR values derived from the image,
|
|
2533
|
+
* the Nix store path, and the build timestamp.
|
|
2534
|
+
*/
|
|
2535
|
+
interface NixBuildResult {
|
|
2536
|
+
/** Docker image content hash (sha256:... -- 64 lowercase hex chars after prefix) */
|
|
2537
|
+
imageHash: string;
|
|
2538
|
+
/** PCR0 -- SHA-384 hash of the enclave image (96 lowercase hex chars) */
|
|
2539
|
+
pcr0: string;
|
|
2540
|
+
/** PCR1 -- SHA-384 hash of the kernel (96 lowercase hex chars) */
|
|
2541
|
+
pcr1: string;
|
|
2542
|
+
/** PCR2 -- SHA-384 hash of the application (96 lowercase hex chars) */
|
|
2543
|
+
pcr2: string;
|
|
2544
|
+
/** Path to the image in the Nix store (/nix/store/...) */
|
|
2545
|
+
imagePath: string;
|
|
2546
|
+
/** Unix timestamp (seconds since epoch) of the build */
|
|
2547
|
+
buildTimestamp: number;
|
|
2548
|
+
}
|
|
2549
|
+
/**
|
|
2550
|
+
* Configuration for the NixBuilder.
|
|
2551
|
+
*/
|
|
2552
|
+
interface NixBuilderConfig {
|
|
2553
|
+
/** Root directory of the project (containing flake.nix) */
|
|
2554
|
+
projectRoot: string;
|
|
2555
|
+
/** Path to Dockerfile.nix relative to projectRoot */
|
|
2556
|
+
dockerfilePath: string;
|
|
2557
|
+
/**
|
|
2558
|
+
* Optional source overrides for testing. Keys are relative paths from
|
|
2559
|
+
* projectRoot, values are the file content to write. When set, NixBuilder
|
|
2560
|
+
* creates a temporary copy of the source tree with the overrides applied
|
|
2561
|
+
* before running the build. This allows testing that source changes
|
|
2562
|
+
* produce different PCR values.
|
|
2563
|
+
*/
|
|
2564
|
+
sourceOverride?: Record<string, string>;
|
|
2565
|
+
}
|
|
2566
|
+
/**
|
|
2567
|
+
* Orchestrates Nix-based Docker image builds for reproducible TEE deployment.
|
|
2568
|
+
*
|
|
2569
|
+
* The build() method shells out to `nix build .#docker-image` and parses the
|
|
2570
|
+
* output to extract the image hash, Nix store path, and PCR values. PCR values
|
|
2571
|
+
* are computed from the image content using SHA-384 to simulate the measurement
|
|
2572
|
+
* that would be performed by the TEE hardware (AWS Nitro hypervisor).
|
|
2573
|
+
*
|
|
2574
|
+
* @example
|
|
2575
|
+
* ```typescript
|
|
2576
|
+
* const builder = new NixBuilder({
|
|
2577
|
+
* projectRoot: '/path/to/toon',
|
|
2578
|
+
* dockerfilePath: 'docker/Dockerfile.nix',
|
|
2579
|
+
* });
|
|
2580
|
+
* const result = await builder.build();
|
|
2581
|
+
* console.log(result.imageHash); // sha256:abc123...
|
|
2582
|
+
* console.log(result.pcr0); // 96-char hex string
|
|
2583
|
+
* ```
|
|
2584
|
+
*/
|
|
2585
|
+
declare class NixBuilder {
|
|
2586
|
+
private readonly config;
|
|
2587
|
+
constructor(config: NixBuilderConfig);
|
|
2588
|
+
/**
|
|
2589
|
+
* Execute a Nix build and return the result.
|
|
2590
|
+
*
|
|
2591
|
+
* Shells out to `nix build .#docker-image` in the project root directory.
|
|
2592
|
+
* If sourceOverride is configured, creates a temporary modified source tree.
|
|
2593
|
+
*
|
|
2594
|
+
* @throws Error if Nix is not installed or the build fails
|
|
2595
|
+
*/
|
|
2596
|
+
build(): Promise<NixBuildResult>;
|
|
2597
|
+
}
|
|
2598
|
+
|
|
2599
|
+
/**
|
|
2600
|
+
* PCR Validation and Dockerfile Determinism Analysis
|
|
2601
|
+
*
|
|
2602
|
+
* Provides utilities for verifying PCR (Platform Configuration Register)
|
|
2603
|
+
* reproducibility across independent Nix builds, and for statically
|
|
2604
|
+
* analyzing Dockerfile.nix expressions for non-deterministic patterns.
|
|
2605
|
+
*
|
|
2606
|
+
* PCR values are SHA-384 hashes (96 lowercase hex characters) measured
|
|
2607
|
+
* by the TEE hardware. If two builds of the same source tree produce
|
|
2608
|
+
* different PCR values, the attestation verification model collapses
|
|
2609
|
+
* (R-E4-002, Score 6) because the AttestationVerifier cannot compare
|
|
2610
|
+
* observed PCR values against a known-good registry.
|
|
2611
|
+
*
|
|
2612
|
+
* @module
|
|
2613
|
+
*/
|
|
2614
|
+
|
|
2615
|
+
/**
|
|
2616
|
+
* A forbidden pattern that must not appear in a deterministic Dockerfile/Nix
|
|
2617
|
+
* expression. Each entry includes a regex, a human-readable name, and an
|
|
2618
|
+
* explanation of why the pattern breaks reproducibility.
|
|
2619
|
+
*/
|
|
2620
|
+
interface ForbiddenPattern {
|
|
2621
|
+
/** Regex to match against each line of the Dockerfile */
|
|
2622
|
+
pattern: RegExp;
|
|
2623
|
+
/** Human-readable name of the pattern (e.g., 'apt-get update') */
|
|
2624
|
+
name: string;
|
|
2625
|
+
/** Explanation of why this pattern breaks reproducibility */
|
|
2626
|
+
reason: string;
|
|
2627
|
+
}
|
|
2628
|
+
/**
|
|
2629
|
+
* A single violation found during determinism analysis. Includes the line
|
|
2630
|
+
* number (1-indexed), the name of the matched pattern, and the text that
|
|
2631
|
+
* triggered the match.
|
|
2632
|
+
*/
|
|
2633
|
+
interface Violation {
|
|
2634
|
+
/** Line number (1-indexed) where the violation was found */
|
|
2635
|
+
line: number;
|
|
2636
|
+
/** Name of the forbidden pattern that matched */
|
|
2637
|
+
patternName: string;
|
|
2638
|
+
/** The text from the line that triggered the match */
|
|
2639
|
+
matchedText: string;
|
|
2640
|
+
}
|
|
2641
|
+
/**
|
|
2642
|
+
* Result of analyzing a Dockerfile for non-deterministic patterns.
|
|
2643
|
+
*/
|
|
2644
|
+
interface DeterminismReport {
|
|
2645
|
+
/** True if no forbidden patterns were found */
|
|
2646
|
+
deterministic: boolean;
|
|
2647
|
+
/** List of violations found (empty if deterministic) */
|
|
2648
|
+
violations: Violation[];
|
|
2649
|
+
/** Number of lines scanned */
|
|
2650
|
+
scannedLines: number;
|
|
2651
|
+
}
|
|
2652
|
+
/**
|
|
2653
|
+
* Result of comparing two NixBuildResults for PCR reproducibility.
|
|
2654
|
+
*/
|
|
2655
|
+
interface PcrReproducibilityResult {
|
|
2656
|
+
/** True if all PCR values and image hash match */
|
|
2657
|
+
reproducible: boolean;
|
|
2658
|
+
/** Whether PCR0 values match */
|
|
2659
|
+
pcr0Match: boolean;
|
|
2660
|
+
/** Whether PCR1 values match */
|
|
2661
|
+
pcr1Match: boolean;
|
|
2662
|
+
/** Whether PCR2 values match */
|
|
2663
|
+
pcr2Match: boolean;
|
|
2664
|
+
/** Whether Docker image content hashes match */
|
|
2665
|
+
imageHashMatch: boolean;
|
|
2666
|
+
/** The actual PCR and hash values from both builds for debugging */
|
|
2667
|
+
details: {
|
|
2668
|
+
buildA: {
|
|
2669
|
+
pcr0: string;
|
|
2670
|
+
pcr1: string;
|
|
2671
|
+
pcr2: string;
|
|
2672
|
+
imageHash: string;
|
|
2673
|
+
};
|
|
2674
|
+
buildB: {
|
|
2675
|
+
pcr0: string;
|
|
2676
|
+
pcr1: string;
|
|
2677
|
+
pcr2: string;
|
|
2678
|
+
imageHash: string;
|
|
2679
|
+
};
|
|
2680
|
+
};
|
|
2681
|
+
/** Human-readable summary suitable for CI log output */
|
|
2682
|
+
summary: string;
|
|
2683
|
+
}
|
|
2684
|
+
/**
|
|
2685
|
+
* Options for verifyPcrReproducibility().
|
|
2686
|
+
*/
|
|
2687
|
+
interface VerifyOptions {
|
|
2688
|
+
/** If true, throws PcrReproducibilityError when builds diverge */
|
|
2689
|
+
throwOnMismatch?: boolean;
|
|
2690
|
+
}
|
|
2691
|
+
/**
|
|
2692
|
+
* Error thrown when PCR reproducibility verification fails (builds diverge).
|
|
2693
|
+
* Contains both build results in the error message for CI debugging.
|
|
2694
|
+
*/
|
|
2695
|
+
declare class PcrReproducibilityError extends ToonError {
|
|
2696
|
+
constructor(buildA: NixBuildResult, buildB: NixBuildResult);
|
|
2697
|
+
}
|
|
2698
|
+
/**
|
|
2699
|
+
* Reads the content of a Dockerfile.nix file from disk.
|
|
2700
|
+
*
|
|
2701
|
+
* This is a thin I/O wrapper separated from the analysis function to keep
|
|
2702
|
+
* `analyzeDockerfileForNonDeterminism()` a pure function (no side effects).
|
|
2703
|
+
*
|
|
2704
|
+
* @param filePath - Absolute path to the Dockerfile.nix file
|
|
2705
|
+
* @returns The file content as a UTF-8 string
|
|
2706
|
+
*/
|
|
2707
|
+
declare function readDockerfileNix(filePath: string): Promise<string>;
|
|
2708
|
+
/**
|
|
2709
|
+
* Analyzes a Dockerfile/Nix expression for non-deterministic patterns.
|
|
2710
|
+
*
|
|
2711
|
+
* This is a pure function -- it takes the file content as a string and an
|
|
2712
|
+
* array of forbidden patterns, and returns a structured report. No I/O is
|
|
2713
|
+
* performed; file reading is handled by `readDockerfileNix()`.
|
|
2714
|
+
*
|
|
2715
|
+
* Each line of the content is tested against every forbidden pattern. Lines
|
|
2716
|
+
* that start with '#' (comments) are skipped since they don't affect the
|
|
2717
|
+
* build output.
|
|
2718
|
+
*
|
|
2719
|
+
* @param content - The Dockerfile/Nix expression content as a string
|
|
2720
|
+
* @param forbiddenPatterns - Array of patterns that indicate non-determinism
|
|
2721
|
+
* @returns A DeterminismReport with violations and line numbers
|
|
2722
|
+
*
|
|
2723
|
+
* @example
|
|
2724
|
+
* ```typescript
|
|
2725
|
+
* const report = analyzeDockerfileForNonDeterminism(content, [
|
|
2726
|
+
* { pattern: /apt-get\s+update/, name: 'apt-get update', reason: '...' },
|
|
2727
|
+
* ]);
|
|
2728
|
+
* if (!report.deterministic) {
|
|
2729
|
+
* console.error('Violations:', report.violations);
|
|
2730
|
+
* }
|
|
2731
|
+
* ```
|
|
2732
|
+
*/
|
|
2733
|
+
declare function analyzeDockerfileForNonDeterminism(content: string, forbiddenPatterns: ForbiddenPattern[]): DeterminismReport;
|
|
2734
|
+
/**
|
|
2735
|
+
* Verifies that two NixBuildResults are reproducible -- i.e., they produce
|
|
2736
|
+
* identical PCR values and Docker image content hashes.
|
|
2737
|
+
*
|
|
2738
|
+
* This function is intended for CI pipelines: build the Docker image twice
|
|
2739
|
+
* from the same source tree, then call this function to verify the outputs
|
|
2740
|
+
* match. If they don't, the build is non-deterministic and PCR-based
|
|
2741
|
+
* attestation verification will fail.
|
|
2742
|
+
*
|
|
2743
|
+
* PCR values are normalized to lowercase before comparison to avoid
|
|
2744
|
+
* case-sensitivity issues.
|
|
2745
|
+
*
|
|
2746
|
+
* @param buildA - Result from the first build
|
|
2747
|
+
* @param buildB - Result from the second build
|
|
2748
|
+
* @param options - Optional: throwOnMismatch to throw PcrReproducibilityError
|
|
2749
|
+
* @returns A structured PcrReproducibilityResult with match details and summary
|
|
2750
|
+
*
|
|
2751
|
+
* Note: This function is async by API contract (Story 4.5 AC #4) to allow
|
|
2752
|
+
* future implementations to perform I/O (e.g., fetching PCR values from a
|
|
2753
|
+
* remote registry). The current implementation is synchronous.
|
|
2754
|
+
*
|
|
2755
|
+
* @example
|
|
2756
|
+
* ```typescript
|
|
2757
|
+
* const buildA = await builder.build();
|
|
2758
|
+
* const buildB = await builder.build();
|
|
2759
|
+
* const result = await verifyPcrReproducibility(buildA, buildB, {
|
|
2760
|
+
* throwOnMismatch: true,
|
|
2761
|
+
* });
|
|
2762
|
+
* console.log(result.summary); // "PCR reproducibility: PASS ..."
|
|
2763
|
+
* ```
|
|
2764
|
+
*/
|
|
2765
|
+
declare function verifyPcrReproducibility(buildA: NixBuildResult, buildB: NixBuildResult, options?: VerifyOptions): Promise<PcrReproducibilityResult>;
|
|
2766
|
+
|
|
2767
|
+
/**
|
|
2768
|
+
* Structured logging for the TOON protocol.
|
|
2769
|
+
*
|
|
2770
|
+
* Provides JSON-formatted log output with contextual fields for:
|
|
2771
|
+
* - TEE enclave observability (component, enclaveType)
|
|
2772
|
+
* - DVM job log correlation (correlationId)
|
|
2773
|
+
* - Multi-node debugging (nodeId, pubkey)
|
|
2774
|
+
*
|
|
2775
|
+
* Zero runtime dependencies. Uses console.log/console.error as the
|
|
2776
|
+
* transport layer. Output is structured JSON when `json: true` (default
|
|
2777
|
+
* in production), or human-readable when `json: false` (development).
|
|
2778
|
+
*
|
|
2779
|
+
* @module
|
|
2780
|
+
*/
|
|
2781
|
+
/**
|
|
2782
|
+
* Log levels ordered by severity.
|
|
2783
|
+
*/
|
|
2784
|
+
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
2785
|
+
/**
|
|
2786
|
+
* Configuration for creating a Logger instance.
|
|
2787
|
+
*/
|
|
2788
|
+
interface LoggerConfig {
|
|
2789
|
+
/** Component name (e.g., 'bootstrap', 'x402', 'attestation') */
|
|
2790
|
+
component: string;
|
|
2791
|
+
/** Minimum log level to emit. Default: 'info' */
|
|
2792
|
+
level?: LogLevel;
|
|
2793
|
+
/** Output as JSON. Default: true */
|
|
2794
|
+
json?: boolean;
|
|
2795
|
+
/** Static context fields merged into every log entry */
|
|
2796
|
+
context?: Record<string, unknown>;
|
|
2797
|
+
}
|
|
2798
|
+
/**
|
|
2799
|
+
* A structured log entry.
|
|
2800
|
+
*/
|
|
2801
|
+
interface LogEntry {
|
|
2802
|
+
/** ISO 8601 timestamp */
|
|
2803
|
+
timestamp: string;
|
|
2804
|
+
/** Log level */
|
|
2805
|
+
level: LogLevel;
|
|
2806
|
+
/** Component that produced the log */
|
|
2807
|
+
component: string;
|
|
2808
|
+
/** Log message */
|
|
2809
|
+
msg: string;
|
|
2810
|
+
/** Additional structured fields */
|
|
2811
|
+
[key: string]: unknown;
|
|
2812
|
+
}
|
|
2813
|
+
/**
|
|
2814
|
+
* Structured logger with contextual fields.
|
|
2815
|
+
*
|
|
2816
|
+
* Usage:
|
|
2817
|
+
* ```typescript
|
|
2818
|
+
* const log = createLogger({ component: 'bootstrap' });
|
|
2819
|
+
* log.info('Peer registered', { peerId: 'abc', ilpAddress: 'g.toon.peer' });
|
|
2820
|
+
* log.error('Bootstrap failed', { error: err.message });
|
|
2821
|
+
*
|
|
2822
|
+
* // Child logger with additional context
|
|
2823
|
+
* const jobLog = log.child({ correlationId: 'job-123' });
|
|
2824
|
+
* jobLog.info('DVM job started');
|
|
2825
|
+
* ```
|
|
2826
|
+
*/
|
|
2827
|
+
interface Logger {
|
|
2828
|
+
debug(msg: string, fields?: Record<string, unknown>): void;
|
|
2829
|
+
info(msg: string, fields?: Record<string, unknown>): void;
|
|
2830
|
+
warn(msg: string, fields?: Record<string, unknown>): void;
|
|
2831
|
+
error(msg: string, fields?: Record<string, unknown>): void;
|
|
2832
|
+
/**
|
|
2833
|
+
* Create a child logger with additional context fields.
|
|
2834
|
+
* The child inherits all parent context and adds its own.
|
|
2835
|
+
*/
|
|
2836
|
+
child(context: Record<string, unknown>): Logger;
|
|
2837
|
+
}
|
|
2838
|
+
/**
|
|
2839
|
+
* Create a structured logger.
|
|
2840
|
+
*
|
|
2841
|
+
* @param config - Logger configuration
|
|
2842
|
+
* @returns A Logger instance
|
|
2843
|
+
*/
|
|
2844
|
+
declare function createLogger(config: LoggerConfig): Logger;
|
|
2845
|
+
|
|
2846
|
+
/**
|
|
2847
|
+
* @toon-protocol/core
|
|
2848
|
+
*
|
|
2849
|
+
* Core library for Nostr-based ILP peer discovery.
|
|
2850
|
+
*/
|
|
2851
|
+
declare const VERSION = "0.1.0";
|
|
2852
|
+
|
|
2853
|
+
export { type AgentRuntimeClient, ArDrivePeerRegistry, AttestationBootstrap, type AttestationBootstrapConfig, type AttestationBootstrapEvent, type AttestationBootstrapEventListener, type AttestationBootstrapResult, type AttestationEventOptions, AttestationState, AttestationVerifier, type AttestationVerifierConfig, type BootstrapConfig, BootstrapError, type BootstrapEvent, type BootstrapEventListener, type BootstrapPhase, type BootstrapResult, BootstrapService, type BootstrapServiceConfig, type BuildIlpPrepareParams, CHAIN_PRESETS, type ChainName, type ChainPreset, type ChannelState, type ConnectorAdminClient, type ConnectorAdminLike, type ConnectorChannelClient, type ConnectorChannelLike, type ConnectorNodeLike, type DeriveFromKmsSeedOptions, type DeterminismReport, type DirectRuntimeClientConfig, type DiscoveredPeer, type DiscoveryTracker, type DiscoveryTrackerConfig, type DvmJobStatus, type EmbeddableConnectorLike, type ForbiddenPattern, type GenesisPeer, GenesisPeerLoader, type HandlePacketAcceptResponse, type HandlePacketRejectResponse, type HandlePacketRequest, type HandlePacketResponse, ILP_PEER_INFO_KIND, IMAGE_GENERATION_KIND, type IlpClient, type IlpPeerInfo, type IlpPreparePacket, type IlpSendResult, JOB_FEEDBACK_KIND, JOB_REQUEST_KIND_BASE, JOB_RESULT_KIND_BASE, type JobFeedbackParams, type JobRequestParams, type JobResultParams, KmsIdentityError, type KmsKeypair, type KnownPeer, type LogEntry, type LogLevel, type Logger, type LoggerConfig, MOCK_USDC_ADDRESS, MOCK_USDC_CONFIG, type MockUsdcConfig, type NixBuildResult, NixBuilder, type NixBuilderConfig, NostrPeerDiscovery, type OpenChannelParams, type OpenChannelResult, type PacketHandler, type ParsedAttestation, type ParsedJobFeedback, type ParsedJobRequest, type ParsedJobResult, PcrReproducibilityError, type PcrReproducibilityResult, type PeerDescriptor, type PublishSeedRelayConfig, type RegisterPeerParams, SEED_RELAY_LIST_KIND, SERVICE_DISCOVERY_KIND, SeedRelayDiscovery, type SeedRelayDiscoveryConfig, type SeedRelayDiscoveryResult, type SeedRelayEntry, type SendPacketParams, type SendPacketResult, type ServiceDiscoveryContent, type SettlementConfig, type SkillDescriptor, type SocialDiscoveryEvent, type SocialDiscoveryEventListener, SocialPeerDiscovery, type SocialPeerDiscoveryConfig, type Subscription, TEE_ATTESTATION_KIND, TEXT_GENERATION_KIND, TEXT_TO_SPEECH_KIND, TRANSLATION_KIND, type TeeAttestation, ToonError, type ToonNode, type ToonNodeConfig, type ToonNodeStartResult, USDC_DECIMALS, USDC_NAME, USDC_SYMBOL, VERSION, type VerificationResult, type VerifyOptions, type Violation, analyzeDockerfileForNonDeterminism, buildAttestationEvent, buildEip712Domain, buildIlpPeerInfoEvent, buildIlpPrepare, buildJobFeedbackEvent, buildJobRequestEvent, buildJobResultEvent, buildSeedRelayListEvent, buildServiceDiscoveryEvent, createAgentRuntimeClient, createDirectChannelClient, createDirectConnectorAdmin, createDirectIlpClient, createDirectRuntimeClient, createDiscoveryTracker, createHttpChannelClient, createHttpConnectorAdmin, createHttpIlpClient$1 as createHttpIlpClient, createHttpRuntimeClient, createHttpIlpClient as createHttpRuntimeClientV2, createLogger, createToonNode, deriveFromKmsSeed, negotiateSettlementChain, parseAttestation, parseIlpPeerInfo, parseJobFeedback, parseJobRequest, parseJobResult, parseSeedRelayList, parseServiceDiscovery, publishSeedRelayEntry, readDockerfileNix, resolveChainConfig, resolveTokenForChain, validateChainId, verifyPcrReproducibility };
|