@toon-protocol/core 1.1.2 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -84,6 +84,315 @@ declare const TEXT_TO_SPEECH_KIND = 5300;
84
84
  * Optional provider support -- not all nodes are required to handle this kind.
85
85
  */
86
86
  declare const TRANSLATION_KIND = 5302;
87
+ /**
88
+ * Workflow Chain definition (kind 10040).
89
+ * Replaceable event defining a multi-step DVM pipeline where each step's
90
+ * output feeds into the next step's input. Uses a unique `d` tag per
91
+ * workflow instance for NIP-33 parameterized replaceable semantics.
92
+ * In the TOON-specific replaceable range (10032-10099).
93
+ */
94
+ declare const WORKFLOW_CHAIN_KIND = 10040;
95
+ /**
96
+ * Job Review (kind 31117)
97
+ * NIP-33 parameterized replaceable event for post-job reviews.
98
+ * `d` tag = job request event ID enforces one review per job per reviewer.
99
+ * Rating tag contains integer 1-5. Role tag indicates 'customer' or 'provider'.
100
+ */
101
+ declare const JOB_REVIEW_KIND = 31117;
102
+ /**
103
+ * Web of Trust declaration (kind 30382)
104
+ * NIP-33 parameterized replaceable event endorsing a provider pubkey.
105
+ * `d` tag = target provider pubkey enforces one WoT declaration per
106
+ * declarer per target. Used for reputation scoring sybil defense.
107
+ */
108
+ declare const WEB_OF_TRUST_KIND = 30382;
109
+ /**
110
+ * Prefix Claim (kind 10034)
111
+ * Replaceable event requesting a prefix claim from an upstream node.
112
+ * The content field contains a PrefixClaimContent JSON payload with the
113
+ * requested prefix string. Payment is carried in the ILP PREPARE packet.
114
+ */
115
+ declare const PREFIX_CLAIM_KIND = 10034;
116
+ /**
117
+ * Prefix Grant (kind 10037)
118
+ * Replaceable event confirming a prefix claim was accepted by the upstream node.
119
+ * Published by the upstream node after validating payment and prefix availability.
120
+ * Contains the granted prefix, claimer's pubkey, and derived ILP address.
121
+ */
122
+ declare const PREFIX_GRANT_KIND = 10037;
123
+ /**
124
+ * ILP root prefix for the TOON network.
125
+ * `g.` is the ILP global allocation prefix (standard ILP convention).
126
+ * `toon` is the TOON network identifier.
127
+ * The genesis node uses this directly -- it does not derive its address from a pubkey.
128
+ * All other nodes derive addresses as children of their upstream peer's prefix.
129
+ */
130
+ /**
131
+ * Blob Storage DVM kind (kind 5094).
132
+ * Used for permanent blob storage requests (e.g., Arweave uploads).
133
+ * The blob data is base64-encoded in the `i` tag with type `blob`.
134
+ * Payment is carried in the ILP PREPARE packet (prepaid model).
135
+ */
136
+ declare const BLOB_STORAGE_REQUEST_KIND = 5094;
137
+ /**
138
+ * Blob Storage Result DVM kind (kind 6094).
139
+ * Reserved for informational result events. In the prepaid model,
140
+ * the Arweave tx ID is returned in the ILP FULFILL data field,
141
+ * NOT as a kind:6094 event.
142
+ */
143
+ declare const BLOB_STORAGE_RESULT_KIND = 6094;
144
+ declare const ILP_ROOT_PREFIX = "g.toon";
145
+
146
+ /**
147
+ * Shared ILP address validation utilities.
148
+ *
149
+ * Centralizes ILP address structure validation used by both
150
+ * `derive-child-address.ts` and `btp-prefix-exchange.ts`.
151
+ *
152
+ * @module
153
+ */
154
+ /**
155
+ * Returns `true` if the string is a structurally valid ILP address
156
+ * (dot-separated, non-empty segments, valid characters only).
157
+ */
158
+ declare function isValidIlpAddressStructure(address: string): boolean;
159
+ /**
160
+ * Validates that a string is a valid ILP address. Throws a `ToonError`
161
+ * with code `ADDRESS_INVALID_PREFIX` on any structural violation.
162
+ *
163
+ * @throws {ToonError} With code `ADDRESS_INVALID_PREFIX` if the address
164
+ * contains empty segments or invalid characters.
165
+ */
166
+ declare function validateIlpAddress(address: string): void;
167
+
168
+ /**
169
+ * Deterministic ILP address derivation from Nostr pubkeys.
170
+ *
171
+ * Derives a child ILP address by appending the first 8 hex characters
172
+ * of a Nostr pubkey as a new segment to a parent ILP address prefix.
173
+ *
174
+ * @module
175
+ */
176
+ /**
177
+ * Derives a child ILP address by appending the first 8 hex characters of a
178
+ * Nostr pubkey as a new segment to a parent ILP address prefix.
179
+ *
180
+ * @param parentPrefix - The parent ILP address prefix (e.g., `g.toon` or `g.toon.ef567890`)
181
+ * @param childPubkey - The child's Nostr pubkey (hex string, at least 8 characters)
182
+ * @returns The derived child ILP address (e.g., `g.toon.abcd1234`)
183
+ *
184
+ * @throws {ToonError} With code `ADDRESS_INVALID_PREFIX` if `parentPrefix` is empty or
185
+ * contains invalid ILP address characters.
186
+ * @throws {ToonError} With code `ADDRESS_INVALID_PUBKEY` if `childPubkey` is shorter than
187
+ * 8 hex characters or contains non-hex characters.
188
+ *
189
+ * @example
190
+ * ```ts
191
+ * deriveChildAddress('g.toon', 'abcd1234abcd1234...') // => 'g.toon.abcd1234'
192
+ * deriveChildAddress('g.toon.ef567890', '11aabb22...') // => 'g.toon.ef567890.11aabb22'
193
+ * ```
194
+ */
195
+ declare function deriveChildAddress(parentPrefix: string, childPubkey: string): string;
196
+
197
+ /**
198
+ * BTP handshake prefix exchange utilities.
199
+ *
200
+ * Provides extraction, building, and validation functions for the prefix
201
+ * data exchanged during BTP handshake. This module defines the structural
202
+ * type for prefix extension data but does NOT modify the BTP wire protocol
203
+ * (which lives in @toon-protocol/connector).
204
+ *
205
+ * @module
206
+ */
207
+ /**
208
+ * Shape of prefix data in BTP handshake messages.
209
+ * Upstream peers include this in their handshake response so that
210
+ * connecting nodes can derive their own ILP address.
211
+ */
212
+ interface BtpHandshakeExtension {
213
+ prefix: string;
214
+ }
215
+ /**
216
+ * Extracts and validates the prefix field from BTP handshake response data.
217
+ *
218
+ * Fail-closed behavior: throws if the prefix is absent, empty, or invalid.
219
+ * This is the critical safety contract -- nodes MUST NOT fall back to
220
+ * hardcoded addresses when the upstream peer omits the prefix.
221
+ *
222
+ * @param handshakeData - The handshake response data object
223
+ * @returns The validated prefix string
224
+ *
225
+ * @throws {ToonError} With code `ADDRESS_MISSING_PREFIX` if the `prefix` field
226
+ * is absent or empty.
227
+ * @throws {ToonError} With code `ADDRESS_INVALID_PREFIX` if the prefix fails
228
+ * ILP address validation.
229
+ */
230
+ declare function extractPrefixFromHandshake(handshakeData: Record<string, unknown>): string;
231
+ /**
232
+ * Constructs the prefix extension data that upstream peers include
233
+ * in their handshake response.
234
+ *
235
+ * Validates the address before building the handshake data to ensure
236
+ * upstream peers never send structurally invalid prefixes.
237
+ *
238
+ * @param ownIlpAddress - The upstream peer's own ILP address
239
+ * @returns The handshake extension data containing the prefix
240
+ *
241
+ * @throws {ToonError} With code `ADDRESS_INVALID_PREFIX` if the address
242
+ * is not a valid ILP address.
243
+ */
244
+ declare function buildPrefixHandshakeData(ownIlpAddress: string): BtpHandshakeExtension;
245
+ /**
246
+ * Cross-validates the handshake prefix against the upstream peer's
247
+ * kind:10032 advertised address.
248
+ *
249
+ * When both values are available and they do not match, throws a
250
+ * ToonError indicating potential prefix spoofing. When the advertised
251
+ * prefix is undefined (kind:10032 not yet discovered), validation is
252
+ * deferred (no-op).
253
+ *
254
+ * @param handshakePrefix - The prefix received during BTP handshake
255
+ * @param advertisedPrefix - The upstream peer's kind:10032 advertised address (optional)
256
+ *
257
+ * @throws {ToonError} With code `ADDRESS_PREFIX_MISMATCH` if both values
258
+ * are available and do not match.
259
+ */
260
+ declare function validatePrefixConsistency(handshakePrefix: string, advertisedPrefix?: string): void;
261
+ /**
262
+ * Checks whether a derived address collides with any known peer addresses.
263
+ *
264
+ * Safety net for the 8-char truncation collision case (exceedingly unlikely
265
+ * at < 9,292 peers, but the check exists per E7-R001).
266
+ *
267
+ * @param derivedAddress - The newly derived ILP address
268
+ * @param knownPeerAddresses - List of existing peer addresses to check against
269
+ *
270
+ * @throws {ToonError} With code `ADDRESS_COLLISION` if the derived address
271
+ * already exists in the known peer list.
272
+ */
273
+ declare function checkAddressCollision(derivedAddress: string, knownPeerAddresses: string[]): void;
274
+
275
+ /**
276
+ * Address assignment orchestration layer.
277
+ *
278
+ * Combines BTP prefix extraction with deterministic address derivation
279
+ * to assign ILP addresses during the handshake process.
280
+ *
281
+ * @module
282
+ */
283
+ /**
284
+ * Orchestrates address assignment from BTP handshake data:
285
+ * 1. Extracts and validates the prefix from handshake data
286
+ * 2. Derives the child address using `deriveChildAddress(prefix, ownPubkey)`
287
+ *
288
+ * @param handshakeData - The BTP handshake response data object
289
+ * @param ownPubkey - The connecting node's Nostr pubkey (hex string)
290
+ * @returns The derived ILP address
291
+ *
292
+ * @throws {ToonError} With code `ADDRESS_MISSING_PREFIX` if the handshake
293
+ * data lacks a prefix field (fail-closed behavior).
294
+ * @throws {ToonError} With code `ADDRESS_INVALID_PREFIX` if the prefix is
295
+ * not a valid ILP address.
296
+ * @throws {ToonError} With code `ADDRESS_INVALID_PUBKEY` if the pubkey is
297
+ * shorter than 8 hex characters or contains non-hex characters.
298
+ */
299
+ declare function assignAddressFromHandshake(handshakeData: Record<string, unknown>, ownPubkey: string): string;
300
+ /**
301
+ * Determines whether a node configuration represents a genesis node.
302
+ *
303
+ * Genesis nodes use `ILP_ROOT_PREFIX` (`g.toon`) directly without
304
+ * derivation -- they are the root of the address hierarchy and do
305
+ * not need a handshake to learn their prefix.
306
+ *
307
+ * @param config - Node configuration with optional ilpAddress
308
+ * @returns `true` if the node's configured address equals `ILP_ROOT_PREFIX`
309
+ */
310
+ declare function isGenesisNode(config: {
311
+ ilpAddress?: string;
312
+ }): boolean;
313
+
314
+ /**
315
+ * AddressRegistry tracks upstream prefix -> derived ILP address mappings.
316
+ *
317
+ * Used by multi-peered nodes to manage address lifecycle: when an upstream
318
+ * peer connects, the node derives and registers an address; when the peer
319
+ * disconnects, the address is removed and kind:10032 republished.
320
+ *
321
+ * Addresses are returned in insertion order so that the primary address
322
+ * (first inserted) is stable across lifecycle events.
323
+ *
324
+ * @module
325
+ */
326
+ /**
327
+ * Tracks the mapping from upstream ILP prefix to derived ILP address.
328
+ *
329
+ * Uses a `Map<string, string>` internally, which preserves insertion order
330
+ * per the ECMAScript specification.
331
+ */
332
+ declare class AddressRegistry {
333
+ private readonly prefixToAddress;
334
+ /**
335
+ * Registers a new upstream prefix -> derived address mapping.
336
+ *
337
+ * @param upstreamPrefix - The upstream peer's ILP address prefix
338
+ * @param derivedAddress - The derived ILP address for this node under that prefix
339
+ */
340
+ addAddress(upstreamPrefix: string, derivedAddress: string): void;
341
+ /**
342
+ * Removes the mapping for the given upstream prefix.
343
+ *
344
+ * @param upstreamPrefix - The upstream prefix to remove
345
+ * @returns The removed derived address, or `undefined` if the prefix was not found
346
+ */
347
+ removeAddress(upstreamPrefix: string): string | undefined;
348
+ /**
349
+ * Returns all derived addresses in insertion order.
350
+ */
351
+ getAddresses(): string[];
352
+ /**
353
+ * Returns `true` if the given upstream prefix is registered.
354
+ */
355
+ hasPrefix(upstreamPrefix: string): boolean;
356
+ /**
357
+ * Returns the number of registered addresses.
358
+ */
359
+ get size(): number;
360
+ /**
361
+ * Returns the primary (first inserted) address.
362
+ *
363
+ * @returns The first address, or `undefined` if the registry is empty
364
+ */
365
+ getPrimaryAddress(): string | undefined;
366
+ }
367
+
368
+ /**
369
+ * Prefix validation utility for the TOON prefix claim marketplace.
370
+ *
371
+ * Validates requested prefix strings against naming rules:
372
+ * lowercase alphanumeric only, length constraints, no reserved words.
373
+ */
374
+ /**
375
+ * Result of prefix validation.
376
+ */
377
+ interface PrefixValidationResult {
378
+ /** Whether the prefix is valid. */
379
+ valid: boolean;
380
+ /** Reason for rejection (only present when valid is false). */
381
+ reason?: string;
382
+ }
383
+ /**
384
+ * Validates a prefix string for use in the prefix claim marketplace.
385
+ *
386
+ * Rules:
387
+ * - Lowercase alphanumeric only (`[a-z0-9]`)
388
+ * - Minimum 2 characters
389
+ * - Maximum 16 characters
390
+ * - No reserved words (`toon`, `ilp`, `local`, `peer`, `test`)
391
+ *
392
+ * @param prefix - The prefix string to validate
393
+ * @returns Validation result with valid flag and optional reason
394
+ */
395
+ declare function validatePrefix(prefix: string): PrefixValidationResult;
87
396
 
88
397
  /**
89
398
  * TypeScript interfaces for ILP-related Nostr events.
@@ -97,6 +406,8 @@ interface IlpPeerInfo {
97
406
  pubkey?: string;
98
407
  /** ILP address of the peer's connector (e.g., "g.example.connector") */
99
408
  ilpAddress: string;
409
+ /** All ILP addresses of this peer (one per upstream peering). When absent (pre-Epic-7 events), consumers should default to [ilpAddress]. */
410
+ ilpAddresses?: string[];
100
411
  /** BTP WebSocket endpoint URL for packet exchange */
101
412
  btpEndpoint: string;
102
413
  /** Optional BLS HTTP endpoint for direct packet delivery (bootstrap only) */
@@ -115,6 +426,12 @@ interface IlpPeerInfo {
115
426
  preferredTokens?: Record<string, string>;
116
427
  /** Maps chain identifier to TokenNetwork contract address (EVM-specific) */
117
428
  tokenNetworks?: Record<string, string>;
429
+ /** Routing fee per byte charged by this node as an intermediary, serialized as a non-negative integer string (e.g., '2'). Defaults to '0' (free routing) when absent. */
430
+ feePerByte?: string;
431
+ /** Prefix pricing for prefix claim marketplace. basePrice is in USDC micro-units as a non-negative integer string. */
432
+ prefixPricing?: {
433
+ basePrice: string;
434
+ };
118
435
  }
119
436
  /**
120
437
  * Subscription handle for real-time event updates.
@@ -221,9 +538,17 @@ declare function parseIlpPeerInfo(event: NostrEvent): IlpPeerInfo;
221
538
  /**
222
539
  * Builds and signs a kind:10032 Nostr event from IlpPeerInfo data.
223
540
  *
541
+ * When `ilpAddresses` is present, validates that the array is non-empty and
542
+ * that all elements are structurally valid ILP addresses. Normalizes
543
+ * `ilpAddress` (singular) to equal `ilpAddresses[0]` for backward compatibility.
544
+ *
224
545
  * @param info - The ILP peer info to serialize into the event
225
546
  * @param secretKey - The secret key to sign the event with
226
547
  * @returns A signed Nostr event
548
+ *
549
+ * @throws {ToonError} With code `INVALID_FEE` if `feePerByte` is not a non-negative integer string
550
+ * @throws {ToonError} With code `ADDRESS_EMPTY_ADDRESSES` if `ilpAddresses` is an empty array
551
+ * @throws {ToonError} With code `ADDRESS_INVALID_PREFIX` if any element of `ilpAddresses` is invalid
227
552
  */
228
553
  declare function buildIlpPeerInfoEvent(info: IlpPeerInfo, secretKey: Uint8Array): NostrEvent;
229
554
 
@@ -271,6 +596,184 @@ declare function buildSeedRelayListEvent(secretKey: Uint8Array, entries: SeedRel
271
596
  */
272
597
  declare function parseSeedRelayList(event: NostrEvent): SeedRelayEntry[];
273
598
 
599
+ /**
600
+ * Event builders, parsers, and reputation scoring for DVM reputation system.
601
+ *
602
+ * Defines two new event kinds:
603
+ * - Kind 31117 (Job Review): NIP-33 parameterized replaceable event for
604
+ * post-job reviews with integer 1-5 ratings.
605
+ * - Kind 30382 (Web of Trust): NIP-33 parameterized replaceable event for
606
+ * endorsing provider pubkeys.
607
+ *
608
+ * Also provides:
609
+ * - `ReputationScoreCalculator`: Pure logic class computing composite
610
+ * reputation scores from pre-gathered signals.
611
+ * - `hasMinReputation()`: Utility for extracting `min_reputation` parameter
612
+ * from parsed job request params.
613
+ */
614
+
615
+ /** Parameters for building a Kind 31117 Job Review event. */
616
+ interface JobReviewParams {
617
+ /** 64-char hex event ID of the original Kind 5xxx job request. */
618
+ jobRequestEventId: string;
619
+ /** 64-char hex pubkey of the target provider being reviewed. */
620
+ targetPubkey: string;
621
+ /** Integer rating 1-5. */
622
+ rating: number;
623
+ /** Role of the reviewer: 'customer' or 'provider'. */
624
+ role: 'customer' | 'provider';
625
+ /** Optional text review content. */
626
+ content?: string;
627
+ }
628
+ /** Parsed result from a Kind 31117 Job Review event. */
629
+ interface ParsedJobReview {
630
+ /** Job request event ID from the `d` tag. */
631
+ jobRequestEventId: string;
632
+ /** Target provider pubkey from the `p` tag. */
633
+ targetPubkey: string;
634
+ /** Integer rating 1-5. */
635
+ rating: number;
636
+ /** Role of the reviewer. */
637
+ role: 'customer' | 'provider';
638
+ /** Review text content. */
639
+ content: string;
640
+ }
641
+ /** Parameters for building a Kind 30382 Web of Trust declaration event. */
642
+ interface WotDeclarationParams {
643
+ /** 64-char hex pubkey of the target provider being endorsed. */
644
+ targetPubkey: string;
645
+ /** Optional endorsement reason. */
646
+ content?: string;
647
+ }
648
+ /** Parsed result from a Kind 30382 Web of Trust declaration event. */
649
+ interface ParsedWotDeclaration {
650
+ /** Target provider pubkey from the `p` tag. */
651
+ targetPubkey: string;
652
+ /** Declarer pubkey from the event's pubkey field. */
653
+ declarerPubkey: string;
654
+ /** Endorsement content. */
655
+ content: string;
656
+ }
657
+ /** Individual reputation signal values. */
658
+ interface ReputationSignals {
659
+ /** Count of WoT declarations from non-zero-volume declarers. */
660
+ trustedBy: number;
661
+ /** Total USDC settled through the provider's payment channels. */
662
+ channelVolumeUsdc: number;
663
+ /** Count of Kind 6xxx result events published by the provider. */
664
+ jobsCompleted: number;
665
+ /** Mean rating from verified customer reviews (0 when no reviews). */
666
+ avgRating: number;
667
+ }
668
+ /** Composite reputation score with individual signal values. */
669
+ interface ReputationScore {
670
+ /** The composite reputation score. */
671
+ score: number;
672
+ /** Individual signal values used to compute the score. */
673
+ signals: ReputationSignals;
674
+ }
675
+ /**
676
+ * Builds a Kind 31117 Job Review event (NIP-33 parameterized replaceable).
677
+ *
678
+ * The `d` tag = job request event ID enforces one review per job per reviewer.
679
+ * Tags: `d` (job request ID), `p` (target pubkey), `rating`, `role`.
680
+ *
681
+ * @param params - The job review parameters.
682
+ * @param secretKey - The secret key to sign the event with.
683
+ * @returns A signed Nostr event.
684
+ * @throws ToonError for invalid inputs.
685
+ */
686
+ declare function buildJobReviewEvent(params: JobReviewParams, secretKey: Uint8Array): NostrEvent;
687
+ /**
688
+ * Parses a Kind 31117 event into a ParsedJobReview.
689
+ *
690
+ * Returns `null` for malformed events (wrong kind, missing tags, invalid rating).
691
+ *
692
+ * @param event - The Nostr event to parse.
693
+ * @returns The parsed job review, or null if invalid.
694
+ */
695
+ declare function parseJobReview(event: NostrEvent): ParsedJobReview | null;
696
+ /**
697
+ * Builds a Kind 30382 Web of Trust declaration event (NIP-33 parameterized replaceable).
698
+ *
699
+ * The `d` tag = target pubkey enforces one WoT declaration per declarer per target.
700
+ *
701
+ * @param params - The WoT declaration parameters.
702
+ * @param secretKey - The secret key to sign the event with.
703
+ * @returns A signed Nostr event.
704
+ * @throws ToonError for invalid inputs.
705
+ */
706
+ declare function buildWotDeclarationEvent(params: WotDeclarationParams, secretKey: Uint8Array): NostrEvent;
707
+ /**
708
+ * Parses a Kind 30382 event into a ParsedWotDeclaration.
709
+ *
710
+ * Returns `null` for malformed events (wrong kind, missing tags,
711
+ * d tag not matching p tag).
712
+ *
713
+ * @param event - The Nostr event to parse.
714
+ * @returns The parsed WoT declaration, or null if invalid.
715
+ */
716
+ declare function parseWotDeclaration(event: NostrEvent): ParsedWotDeclaration | null;
717
+ /**
718
+ * Pure logic class for computing composite reputation scores.
719
+ *
720
+ * Receives pre-computed signals (WoT declarations, reviews, channel volume,
721
+ * job count) and calculates the composite score. Does NOT perform relay
722
+ * queries or on-chain reads. The caller is responsible for gathering signals.
723
+ *
724
+ * Formula: score = (trusted_by x 100) + (log10(max(1, channel_volume_usdc)) x 10)
725
+ * + (jobs_completed x 5) + (avg_rating x 20)
726
+ */
727
+ declare class ReputationScoreCalculator {
728
+ /**
729
+ * Computes the composite reputation score from pre-computed signals.
730
+ *
731
+ * @param signals - The individual signal values.
732
+ * @returns The composite score with individual signals.
733
+ */
734
+ calculateScore(signals: ReputationSignals): ReputationScore;
735
+ /**
736
+ * Computes the threshold-filtered trusted_by count from WoT declarations.
737
+ *
738
+ * Declarers with non-zero channel volume contribute 1 to the count.
739
+ * Declarers with zero channel volume contribute 0 (sybil defense).
740
+ *
741
+ * @param wotDeclarations - Parsed WoT declarations targeting the provider.
742
+ * @param getChannelVolume - Callback to look up a declarer's channel volume.
743
+ * @returns The count of WoT declarations from non-zero-volume declarers.
744
+ */
745
+ computeTrustedBy(wotDeclarations: ParsedWotDeclaration[], getChannelVolume: (pubkey: string) => number): number;
746
+ /**
747
+ * Computes the average rating from verified customer reviews only.
748
+ *
749
+ * Reviews are provided as tuples of `{ review, reviewerPubkey }` so the
750
+ * calculator can filter by the verified customer set. Reviews from pubkeys
751
+ * NOT in `verifiedCustomerPubkeys` are excluded entirely (customer-gate
752
+ * sybil defense per E6-R013).
753
+ *
754
+ * @param reviews - Parsed job reviews with reviewer pubkeys.
755
+ * @param verifiedCustomerPubkeys - Set of pubkeys that authored Kind 5xxx requests.
756
+ * @returns The mean rating from verified reviews, or 0 when no verified reviews exist.
757
+ */
758
+ computeAvgRating(reviews: {
759
+ review: ParsedJobReview;
760
+ reviewerPubkey: string;
761
+ }[], verifiedCustomerPubkeys: Set<string>): number;
762
+ }
763
+ /**
764
+ * Extracts the `min_reputation` parameter value from parsed job request params.
765
+ *
766
+ * Follows the same pattern as `hasRequireAttestation()`.
767
+ *
768
+ * @param params - The params array from a parsed job request.
769
+ * @returns The numeric threshold value, null if not present, or throws on invalid value.
770
+ * @throws ToonError with code REPUTATION_INVALID_MIN_REPUTATION if value is non-numeric.
771
+ */
772
+ declare function hasMinReputation(params: {
773
+ key: string;
774
+ value: string;
775
+ }[]): number | null;
776
+
274
777
  /**
275
778
  * Event builder and parser for kind:10035 Service Discovery events.
276
779
  *
@@ -312,6 +815,8 @@ interface SkillDescriptor {
312
815
  models?: string[];
313
816
  /** Placeholder for Epic 6 TEE attestation integration. */
314
817
  attestation?: Record<string, unknown>;
818
+ /** Composite reputation score with individual signal values (Story 6.4). */
819
+ reputation?: ReputationScore;
315
820
  }
316
821
  /** Content payload for a kind:10035 Service Discovery event. */
317
822
  interface ServiceDiscoveryContent {
@@ -547,6 +1052,8 @@ interface JobResultParams {
547
1052
  amount: string;
548
1053
  /** Result data (text, URL, etc.). */
549
1054
  content: string;
1055
+ /** Optional 64-char hex event ID of the provider's latest kind:10033 attestation event. */
1056
+ attestationEventId?: string;
550
1057
  }
551
1058
  /**
552
1059
  * Parameters for building a Kind 7000 DVM job feedback event.
@@ -611,6 +1118,8 @@ interface ParsedJobResult {
611
1118
  amount: string;
612
1119
  /** Result data from the content field. */
613
1120
  content: string;
1121
+ /** Optional event ID of the provider's kind:10033 attestation event. */
1122
+ attestationEventId?: string;
614
1123
  }
615
1124
  /**
616
1125
  * Parsed result from a Kind 7000 DVM job feedback event.
@@ -688,6 +1197,12 @@ declare function parseJobRequest(event: NostrEvent): ParsedJobRequest | null;
688
1197
  * NIP-90 tags: `e` (request event ID), `p` (customer pubkey), and `amount`
689
1198
  * (compute cost + currency).
690
1199
  *
1200
+ * The `amount` tag is **informational** (a receipt of the agreed price).
1201
+ * In the prepaid protocol model, payment is sent with the job request
1202
+ * (via `publishEvent()` with the `amount` option), NOT triggered by
1203
+ * parsing the result event's amount tag. The amount tag serves as a
1204
+ * record of what was agreed upon, not as a payment trigger.
1205
+ *
691
1206
  * Returns `null` for malformed events. Follows the lenient parse pattern.
692
1207
  *
693
1208
  * @param event - The Nostr event to parse.
@@ -697,18 +1212,534 @@ declare function parseJobResult(event: NostrEvent): ParsedJobResult | null;
697
1212
  /**
698
1213
  * Parses a Kind 7000 event into a ParsedJobFeedback.
699
1214
  *
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'`.
1215
+ * Validates the event kind is exactly 7000 and extracts required NIP-90
1216
+ * tags: `e` (request event ID), `p` (customer pubkey), and `status`
1217
+ * (job state). The status value must be one of: `'processing'`, `'error'`,
1218
+ * `'success'`, `'partial'`.
1219
+ *
1220
+ * Returns `null` for malformed events or invalid status values.
1221
+ * Follows the lenient parse pattern.
1222
+ *
1223
+ * @param event - The Nostr event to parse.
1224
+ * @returns The parsed job feedback, or null if invalid.
1225
+ */
1226
+ declare function parseJobFeedback(event: NostrEvent): ParsedJobFeedback | null;
1227
+
1228
+ /**
1229
+ * Event builder and parser for Workflow Chain events (kind:10040).
1230
+ *
1231
+ * Workflow chains define multi-step DVM pipelines where each step's output
1232
+ * automatically feeds into the next step's input. The workflow definition
1233
+ * event contains an ordered list of steps, initial input, and a total bid
1234
+ * that is split across steps.
1235
+ *
1236
+ * Kind:10040 is in the TOON-specific replaceable range (10032-10099).
1237
+ * Each workflow instance uses a unique `d` tag to avoid unintentional
1238
+ * replacement of in-progress workflows.
1239
+ *
1240
+ * Tag reference (kind:10040):
1241
+ * Content: JSON-serialized workflow definition body
1242
+ * Required: ['d', uniqueWorkflowId], ['bid', totalBid, 'usdc']
1243
+ * Content JSON: { steps: WorkflowStep[], initialInput: { data, type }, totalBid }
1244
+ */
1245
+
1246
+ /**
1247
+ * A single step in a workflow chain.
1248
+ *
1249
+ * Each step specifies a DVM kind (5000-5999) and a description.
1250
+ * Optionally, a step can target a specific provider and allocate
1251
+ * an explicit portion of the total bid.
1252
+ */
1253
+ interface WorkflowStep {
1254
+ /** DVM job request kind (5000-5999 range). */
1255
+ kind: number;
1256
+ /** Human-readable description of the step's purpose. */
1257
+ description: string;
1258
+ /** Optional 64-char hex pubkey of a specific target provider. */
1259
+ targetProvider?: string;
1260
+ /** Optional explicit bid allocation in USDC micro-units as string. */
1261
+ bidAllocation?: string;
1262
+ }
1263
+ /**
1264
+ * Parameters for building a kind:10040 Workflow Chain event.
1265
+ */
1266
+ interface WorkflowDefinitionParams {
1267
+ /** Ordered list of workflow steps (at least one required). */
1268
+ steps: WorkflowStep[];
1269
+ /** Initial input for the first step. */
1270
+ initialInput: {
1271
+ /** The input data (text, JSON, etc.). */
1272
+ data: string;
1273
+ /** Input type identifier (e.g., 'text', 'json'). */
1274
+ type: string;
1275
+ };
1276
+ /** Total bid for the entire workflow in USDC micro-units as string. */
1277
+ totalBid: string;
1278
+ /** Optional body text for the event content field. */
1279
+ content?: string;
1280
+ /** Optional workflow ID for deterministic `d` tag (defaults to timestamp-based). */
1281
+ workflowId?: string;
1282
+ }
1283
+ /**
1284
+ * Parsed result from a kind:10040 Workflow Chain event.
1285
+ */
1286
+ interface ParsedWorkflowDefinition {
1287
+ /** Ordered list of workflow steps. */
1288
+ steps: WorkflowStep[];
1289
+ /** Initial input for the first step. */
1290
+ initialInput: {
1291
+ /** The input data. */
1292
+ data: string;
1293
+ /** Input type identifier. */
1294
+ type: string;
1295
+ };
1296
+ /** Total bid for the entire workflow in USDC micro-units as string. */
1297
+ totalBid: string;
1298
+ /** Event content field (JSON-serialized workflow body). */
1299
+ content: string;
1300
+ }
1301
+ /**
1302
+ * Builds a kind:10040 Workflow Chain event.
1303
+ *
1304
+ * Validates steps, initial input, total bid, and per-step bid allocations
1305
+ * (if provided). Serializes the workflow definition as JSON content.
1306
+ *
1307
+ * @param params - The workflow definition parameters.
1308
+ * @param secretKey - The secret key to sign the event with.
1309
+ * @returns A signed Nostr event.
1310
+ * @throws ToonError if validation fails.
1311
+ */
1312
+ declare function buildWorkflowDefinitionEvent(params: WorkflowDefinitionParams, secretKey: Uint8Array): NostrEvent;
1313
+ /**
1314
+ * Parses a kind:10040 event into a ParsedWorkflowDefinition.
1315
+ *
1316
+ * Validates the event kind, parses JSON content, validates the steps
1317
+ * array, initialInput, and totalBid. Returns `null` for malformed events.
1318
+ *
1319
+ * @param event - The Nostr event to parse.
1320
+ * @returns The parsed workflow definition, or null if invalid.
1321
+ */
1322
+ declare function parseWorkflowDefinition(event: NostrEvent): ParsedWorkflowDefinition | null;
1323
+
1324
+ /**
1325
+ * Event builders and parsers for DVM Agent Swarm events (Story 6.2).
1326
+ *
1327
+ * Swarm events extend NIP-90 DVM events with competitive bidding tags:
1328
+ * - `['swarm', maxProviders]` -- maximum number of providers in the swarm
1329
+ * - `['judge', judgeIdentifier]` -- who selects the winner (default: 'customer')
1330
+ *
1331
+ * Swarm request events are standard Kind 5xxx events with additional tags.
1332
+ * Non-swarm-aware providers can still participate via the standard Kind 5xxx path.
1333
+ *
1334
+ * Selection events are Kind 7000 feedback events with a `winner` tag
1335
+ * referencing the winning Kind 6xxx result event ID.
1336
+ *
1337
+ * Tag reference (swarm-specific additions):
1338
+ *
1339
+ * Kind 5xxx (Swarm Job Request):
1340
+ * Standard NIP-90 tags + ['swarm', maxProviders], ['judge', judgeId]
1341
+ *
1342
+ * Kind 7000 (Swarm Selection):
1343
+ * Standard NIP-90 feedback tags + ['winner', winnerResultEventId]
1344
+ */
1345
+
1346
+ /**
1347
+ * Parameters for building a swarm request event (Kind 5xxx with swarm tags).
1348
+ *
1349
+ * Extends `JobRequestParams` with swarm-specific fields:
1350
+ * - `maxProviders`: Maximum number of providers in the competitive swarm (>= 1).
1351
+ * - `judge`: Who selects the winner (default: 'customer'). Can be 'customer',
1352
+ * 'auto', or a specific pubkey.
1353
+ */
1354
+ interface SwarmRequestParams extends JobRequestParams {
1355
+ /** Maximum number of providers to collect submissions from (>= 1). */
1356
+ maxProviders: number;
1357
+ /** Who selects the winner (default: 'customer'). */
1358
+ judge?: string;
1359
+ }
1360
+ /**
1361
+ * Parameters for building a swarm selection event (Kind 7000 with winner tag).
1362
+ */
1363
+ interface SwarmSelectionParams {
1364
+ /** 64-char hex event ID of the original swarm request. */
1365
+ swarmRequestEventId: string;
1366
+ /** 64-char hex event ID of the winning Kind 6xxx result. */
1367
+ winnerResultEventId: string;
1368
+ /** 64-char hex pubkey of the customer who posted the swarm request. */
1369
+ customerPubkey: string;
1370
+ }
1371
+ /**
1372
+ * Parsed result from a Kind 5xxx swarm request event.
1373
+ * Extends `ParsedJobRequest` with swarm-specific fields.
1374
+ */
1375
+ interface ParsedSwarmRequest extends ParsedJobRequest {
1376
+ /** Maximum number of providers in the swarm. */
1377
+ maxProviders: number;
1378
+ /** Who selects the winner. */
1379
+ judge: string;
1380
+ }
1381
+ /**
1382
+ * Parsed result from a Kind 7000 swarm selection event.
1383
+ */
1384
+ interface ParsedSwarmSelection {
1385
+ /** Event ID of the original swarm request. */
1386
+ swarmRequestEventId: string;
1387
+ /** Event ID of the winning Kind 6xxx result. */
1388
+ winnerResultEventId: string;
1389
+ }
1390
+ /**
1391
+ * Builds a Kind 5xxx swarm request event.
1392
+ *
1393
+ * Delegates to `buildJobRequestEvent()` for the base NIP-90 event, then
1394
+ * appends swarm-specific tags: `swarm` (max providers) and `judge` (selector).
1395
+ *
1396
+ * The resulting event is a valid Kind 5xxx event that non-swarm-aware
1397
+ * providers can also parse via `parseJobRequest()`.
1398
+ *
1399
+ * @param params - The swarm request parameters.
1400
+ * @param secretKey - The secret key to sign the event with.
1401
+ * @returns A signed Nostr event.
1402
+ * @throws ToonError if maxProviders < 1 or base params are invalid.
1403
+ */
1404
+ declare function buildSwarmRequestEvent(params: SwarmRequestParams, secretKey: Uint8Array): NostrEvent;
1405
+ /**
1406
+ * Builds a Kind 7000 swarm selection event.
1407
+ *
1408
+ * Creates a feedback event with `status: 'success'`, an `e` tag referencing
1409
+ * the swarm request, and a `winner` tag referencing the winning result.
1410
+ *
1411
+ * @param params - The swarm selection parameters.
1412
+ * @param secretKey - The secret key to sign the event with.
1413
+ * @returns A signed Nostr event.
1414
+ * @throws ToonError if event IDs or pubkey are not valid 64-char hex.
1415
+ */
1416
+ declare function buildSwarmSelectionEvent(params: SwarmSelectionParams, secretKey: Uint8Array): NostrEvent;
1417
+ /**
1418
+ * Parses a Kind 5xxx event into a ParsedSwarmRequest.
1419
+ *
1420
+ * Delegates to `parseJobRequest()` for base fields, then extracts the
1421
+ * `swarm` and `judge` tags. Returns `null` if the event is not a valid
1422
+ * swarm request (missing `swarm` tag, invalid kind range, etc.).
1423
+ *
1424
+ * @param event - The Nostr event to parse.
1425
+ * @returns The parsed swarm request, or null if invalid/not a swarm request.
1426
+ */
1427
+ declare function parseSwarmRequest(event: NostrEvent): ParsedSwarmRequest | null;
1428
+ /**
1429
+ * Parses a Kind 7000 event into a ParsedSwarmSelection.
1430
+ *
1431
+ * Validates the event kind is exactly 7000 and extracts the `winner` tag
1432
+ * and `e` tag (swarm request reference). Returns `null` if the event is
1433
+ * not a valid swarm selection (missing `winner` tag, wrong kind, etc.).
1434
+ *
1435
+ * @param event - The Nostr event to parse.
1436
+ * @returns The parsed swarm selection, or null if invalid.
1437
+ */
1438
+ declare function parseSwarmSelection(event: NostrEvent): ParsedSwarmSelection | null;
1439
+
1440
+ /**
1441
+ * Event builders and parsers for prefix claim (kind 10034) and
1442
+ * prefix grant (kind 10037) events.
1443
+ *
1444
+ * Prefix claims are part of the TOON prefix marketplace: a node sends a
1445
+ * kind 10034 event with payment to claim a prefix from an upstream peer.
1446
+ * The upstream responds with a kind 10037 grant confirmation.
1447
+ */
1448
+
1449
+ /** Content payload for a kind 10034 prefix claim event. */
1450
+ interface PrefixClaimContent {
1451
+ /** The prefix string being requested (e.g., 'useast'). */
1452
+ requestedPrefix: string;
1453
+ }
1454
+ /** Content payload for a kind 10037 prefix grant event. */
1455
+ interface PrefixGrantContent {
1456
+ /** The prefix that was granted. */
1457
+ grantedPrefix: string;
1458
+ /** Pubkey of the node that received the prefix. */
1459
+ claimerPubkey: string;
1460
+ /** The ILP address derived from the granted prefix. */
1461
+ ilpAddress: string;
1462
+ }
1463
+ /**
1464
+ * Builds and signs a kind 10034 prefix claim event.
1465
+ *
1466
+ * @param content - The prefix claim content with the requested prefix
1467
+ * @param secretKey - The 32-byte secret key to sign the event with
1468
+ * @returns A signed Nostr event of kind 10034
1469
+ */
1470
+ declare function buildPrefixClaimEvent(content: PrefixClaimContent, secretKey: Uint8Array): NostrEvent;
1471
+ /**
1472
+ * Parses a kind 10034 prefix claim event into PrefixClaimContent.
1473
+ *
1474
+ * Returns null for malformed events. Follows the lenient parse pattern.
1475
+ *
1476
+ * @param event - The Nostr event to parse
1477
+ * @returns The parsed prefix claim content, or null if invalid
1478
+ */
1479
+ declare function parsePrefixClaimEvent(event: NostrEvent): PrefixClaimContent | null;
1480
+ /**
1481
+ * Builds and signs a kind 10037 prefix grant event.
1482
+ *
1483
+ * @param content - The prefix grant content with granted prefix details
1484
+ * @param secretKey - The 32-byte secret key to sign the event with
1485
+ * @returns A signed Nostr event of kind 10037
1486
+ */
1487
+ declare function buildPrefixGrantEvent(content: PrefixGrantContent, secretKey: Uint8Array): NostrEvent;
1488
+ /**
1489
+ * Parses a kind 10037 prefix grant event into PrefixGrantContent.
1490
+ *
1491
+ * Returns null for malformed events. Follows the lenient parse pattern.
1492
+ *
1493
+ * @param event - The Nostr event to parse
1494
+ * @returns The parsed prefix grant content, or null if invalid
1495
+ */
1496
+ declare function parsePrefixGrantEvent(event: NostrEvent): PrefixGrantContent | null;
1497
+
1498
+ /**
1499
+ * AttestationVerifier -- TEE attestation verification, state lifecycle,
1500
+ * and attestation-aware peer ranking for Story 4.3.
1501
+ *
1502
+ * This is a pure logic class with no transport layer. It receives parsed
1503
+ * attestation data and returns verification results. The transport layer
1504
+ * (subscribing to kind:10033 events on relays) is a Story 4.6 concern.
1505
+ *
1506
+ * The AttestationVerifier is the single source of truth for attestation
1507
+ * state (R-E4-008). Both the kind:10033 Nostr event path and the /health
1508
+ * HTTP endpoint derive their TEE state from the same verifier instance.
1509
+ *
1510
+ * Attestation State Machine (Decision 12):
1511
+ * VALID (within validitySeconds)
1512
+ * -> STALE (within graceSeconds after validity expires)
1513
+ * -> UNATTESTED (after grace period expires)
1514
+ *
1515
+ * Trust degrades; money doesn't -- attestation state changes never
1516
+ * trigger payment channel closure.
1517
+ */
1518
+
1519
+ /**
1520
+ * Attestation lifecycle state.
1521
+ *
1522
+ * Transitions: VALID -> STALE -> UNATTESTED.
1523
+ * A peer that was never attested starts as UNATTESTED.
1524
+ */
1525
+ declare enum AttestationState {
1526
+ /** Attestation is within validity period. */
1527
+ VALID = "valid",
1528
+ /** Attestation has expired but is within the grace period. */
1529
+ STALE = "stale",
1530
+ /** Attestation has expired past the grace period or was never attested. */
1531
+ UNATTESTED = "unattested"
1532
+ }
1533
+ /** Result of PCR verification against a known-good registry. */
1534
+ interface VerificationResult {
1535
+ valid: boolean;
1536
+ reason?: string;
1537
+ }
1538
+ /**
1539
+ * Descriptor for a peer in the attestation-aware ranking system.
1540
+ * Used by `rankPeers()` to order peers by attestation status.
1541
+ */
1542
+ interface PeerDescriptor {
1543
+ pubkey: string;
1544
+ relayUrl: string;
1545
+ attested: boolean;
1546
+ attestationTimestamp?: number;
1547
+ }
1548
+ /**
1549
+ * Configuration for the AttestationVerifier.
1550
+ */
1551
+ interface AttestationVerifierConfig {
1552
+ /** Map of known-good PCR values. Key is PCR hash, value is trust status. */
1553
+ knownGoodPcrs: Map<string, boolean>;
1554
+ /** Attestation validity period in seconds (default: 300). */
1555
+ validitySeconds?: number;
1556
+ /** Grace period in seconds after validity expires before marking as unattested (default: 30). */
1557
+ graceSeconds?: number;
1558
+ }
1559
+ /**
1560
+ * Verifies TEE attestations, computes attestation lifecycle state,
1561
+ * and ranks peers by attestation status.
1562
+ *
1563
+ * Single source of truth for attestation state (R-E4-008).
1564
+ */
1565
+ declare class AttestationVerifier {
1566
+ private readonly knownGoodPcrs;
1567
+ private readonly validitySeconds;
1568
+ private readonly graceSeconds;
1569
+ constructor(config: AttestationVerifierConfig);
1570
+ /**
1571
+ * Verifies a TEE attestation's PCR values against the known-good registry.
1572
+ *
1573
+ * All three PCR values (pcr0, pcr1, pcr2) must be present and truthy in
1574
+ * the registry for verification to pass.
1575
+ *
1576
+ * @param attestation - The TEE attestation to verify.
1577
+ * @returns Verification result with `valid: true` or `valid: false` with reason.
1578
+ */
1579
+ verify(attestation: TeeAttestation): VerificationResult;
1580
+ /**
1581
+ * Computes the attestation lifecycle state based on timing.
1582
+ *
1583
+ * Boundary behavior:
1584
+ * - At exactly `attestedAt + validitySeconds`: VALID (inclusive <=)
1585
+ * - At exactly `attestedAt + validitySeconds + graceSeconds`: STALE (inclusive <=)
1586
+ * - After grace expires: UNATTESTED
1587
+ *
1588
+ * @param _attestation - The TEE attestation (unused, reserved for future per-attestation logic).
1589
+ * @param attestedAt - Unix timestamp when the attestation was created.
1590
+ * @param now - Optional current unix timestamp (defaults to real clock).
1591
+ * @returns The current attestation state.
1592
+ */
1593
+ getAttestationState(_attestation: TeeAttestation, attestedAt: number, now?: number): AttestationState;
1594
+ /**
1595
+ * Ranks peers by attestation status: attested peers first, then non-attested.
1596
+ *
1597
+ * Preserves relative order within each group (stable sort via filter).
1598
+ * Does NOT mutate the input array -- returns a new sorted array.
1599
+ *
1600
+ * Attestation is a preference, not a requirement. Non-attested peers
1601
+ * remain in the result and are connectable.
1602
+ *
1603
+ * @param peers - Array of peer descriptors to rank.
1604
+ * @returns New array with attested peers first, preserving relative order.
1605
+ */
1606
+ rankPeers(peers: PeerDescriptor[]): PeerDescriptor[];
1607
+ }
1608
+
1609
+ /**
1610
+ * Customer-side attestation result verifier for TEE-attested DVM results.
1611
+ *
1612
+ * Verifies that a Kind 6xxx DVM result was computed in a valid TEE enclave
1613
+ * by checking the referenced kind:10033 attestation event. Three checks:
1614
+ * 1. Pubkey match: kind:10033 author === Kind 6xxx author (same provider)
1615
+ * 2. PCR validity: PCR values pass AttestationVerifier.verify()
1616
+ * 3. Time validity: attestation was VALID at result creation time
1617
+ *
1618
+ * This is a pure logic class with no transport concerns. The caller is
1619
+ * responsible for fetching the attestation event from the relay.
1620
+ */
1621
+
1622
+ /** Configuration for constructing an AttestedResultVerifier. */
1623
+ interface AttestedResultVerificationOptions {
1624
+ /** The AttestationVerifier instance for PCR and state checks. */
1625
+ attestationVerifier: AttestationVerifier;
1626
+ }
1627
+ /** Result of verifying an attested DVM result. */
1628
+ interface AttestedResultVerificationResult {
1629
+ /** Whether the attestation verification passed all checks. */
1630
+ valid: boolean;
1631
+ /** Reason for failure (undefined when valid). */
1632
+ reason?: string;
1633
+ /** Attestation lifecycle state (undefined when verification fails before state check). */
1634
+ attestationState?: AttestationState;
1635
+ }
1636
+ /**
1637
+ * Verifies TEE attestation on Kind 6xxx DVM result events.
1638
+ *
1639
+ * Follows the same pure-logic pattern as AttestationVerifier (Story 4.3).
1640
+ * Time injection is NOT at construction -- `resultEvent.created_at` is
1641
+ * used as the `now` parameter at call site.
1642
+ */
1643
+ declare class AttestedResultVerifier {
1644
+ private readonly attestationVerifier;
1645
+ constructor(options: AttestedResultVerificationOptions);
1646
+ /**
1647
+ * Verifies that a Kind 6xxx result was computed in a valid TEE enclave.
1648
+ *
1649
+ * Performs three checks:
1650
+ * (a) Pubkey match: attestationEvent.pubkey === resultEvent.pubkey
1651
+ * (b) PCR validity: AttestationVerifier.verify(parsedAttestation.attestation)
1652
+ * (c) Time validity: attestation was VALID at resultEvent.created_at
1653
+ *
1654
+ * @param resultEvent - The Kind 6xxx result Nostr event.
1655
+ * @param _parsedResult - The parsed job result (reserved for future use).
1656
+ * @param attestationEvent - The kind:10033 attestation Nostr event.
1657
+ * @param parsedAttestation - The parsed attestation data.
1658
+ * @returns Verification result with valid flag, reason, and attestation state.
1659
+ */
1660
+ verifyAttestedResult(resultEvent: NostrEvent, _parsedResult: ParsedJobResult, attestationEvent: NostrEvent, parsedAttestation: ParsedAttestation): AttestedResultVerificationResult;
1661
+ }
1662
+ /**
1663
+ * Checks whether a parsed job request's params include `require_attestation=true`.
1664
+ *
1665
+ * @param params - The params array from a parsed job request.
1666
+ * @returns true if `require_attestation` is set to `'true'`.
1667
+ */
1668
+ declare function hasRequireAttestation(params: {
1669
+ key: string;
1670
+ value: string;
1671
+ }[]): boolean;
1672
+
1673
+ /**
1674
+ * Event builders and parsers for kind:5094 Blob Storage DVM requests.
1675
+ *
1676
+ * Kind 5094 is a NIP-90 DVM job request for permanent blob storage (Arweave).
1677
+ * The blob data is base64-encoded in the `i` tag with type `blob`.
1678
+ * Payment is carried in the ILP PREPARE packet (prepaid model, D7-001).
1679
+ *
1680
+ * Tag layout:
1681
+ * Required: ['i', base64Blob, 'blob'], ['bid', amount, 'usdc'], ['output', contentType]
1682
+ * Optional: ['param', 'uploadId', uuid], ['param', 'chunkIndex', idx],
1683
+ * ['param', 'totalChunks', total], ['param', 'contentType', type]
1684
+ */
1685
+
1686
+ /**
1687
+ * Parameters for building a kind:5094 Blob Storage DVM request event.
1688
+ */
1689
+ interface BlobStorageRequestParams {
1690
+ /** The raw blob data to store. */
1691
+ blobData: Buffer;
1692
+ /** MIME type of the blob (default: 'application/octet-stream'). */
1693
+ contentType?: string;
1694
+ /** Bid amount in USDC micro-units as string (bigint-compatible). */
1695
+ bid: string;
1696
+ /** Optional key-value parameters (e.g., uploadId, chunkIndex, totalChunks). */
1697
+ params?: {
1698
+ key: string;
1699
+ value: string;
1700
+ }[];
1701
+ }
1702
+ /**
1703
+ * Parsed result from a kind:5094 Blob Storage DVM request event.
1704
+ */
1705
+ interface ParsedBlobStorageRequest {
1706
+ /** The decoded blob data. */
1707
+ blobData: Buffer;
1708
+ /** MIME type of the blob. */
1709
+ contentType: string;
1710
+ /** Upload ID for chunked uploads. */
1711
+ uploadId?: string;
1712
+ /** Chunk index for chunked uploads. */
1713
+ chunkIndex?: number;
1714
+ /** Total number of chunks for chunked uploads. */
1715
+ totalChunks?: number;
1716
+ }
1717
+ /**
1718
+ * Builds a kind:5094 Blob Storage DVM request event.
1719
+ *
1720
+ * Constructs a signed Nostr event with the blob base64-encoded in the `i` tag,
1721
+ * a `bid` tag for payment declaration, and an `output` tag for content type.
1722
+ *
1723
+ * @param params - The blob storage request parameters.
1724
+ * @param secretKey - The secret key to sign the event with.
1725
+ * @returns A signed Nostr event.
1726
+ * @throws ToonError if required params are missing.
1727
+ */
1728
+ declare function buildBlobStorageRequest(params: BlobStorageRequestParams, secretKey: Uint8Array): NostrEvent;
1729
+ /**
1730
+ * Parses a kind:5094 event into a ParsedBlobStorageRequest.
1731
+ *
1732
+ * Validates the event kind is 5094, extracts the base64-encoded blob from the
1733
+ * `i` tag, the content type from the `output` tag, and optional chunked upload
1734
+ * params from `param` tags.
704
1735
  *
705
- * Returns `null` for malformed events or invalid status values.
706
- * Follows the lenient parse pattern.
1736
+ * Returns `null` for malformed events (wrong kind, missing required tags,
1737
+ * invalid base64). Follows the lenient parse pattern.
707
1738
  *
708
1739
  * @param event - The Nostr event to parse.
709
- * @returns The parsed job feedback, or null if invalid.
1740
+ * @returns The parsed blob storage request, or null if invalid.
710
1741
  */
711
- declare function parseJobFeedback(event: NostrEvent): ParsedJobFeedback | null;
1742
+ declare function parseBlobStorageRequest(event: NostrEvent): ParsedBlobStorageRequest | null;
712
1743
 
713
1744
  /**
714
1745
  * Peer discovery using Nostr NIP-02 follow lists.
@@ -980,36 +2011,32 @@ declare function publishSeedRelayEntry(config: PublishSeedRelayConfig): Promise<
980
2011
  }>;
981
2012
 
982
2013
  /**
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.
2014
+ * Pure function for calculating ILP PREPARE amount including intermediary routing fees.
989
2015
  *
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)
2016
+ * Formula: totalAmount = basePricePerByte * packetBytes + SUM(hopFees[i] * packetBytes)
994
2017
  *
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
2018
+ * All arithmetic uses bigint -- no floating point, no overflow risk.
1000
2019
  */
1001
- declare function negotiateSettlementChain(requesterChains: string[], responderChains: string[], requesterPreferredTokens?: Record<string, string>, responderPreferredTokens?: Record<string, string>): string | null;
1002
2020
  /**
1003
- * Resolves which token to use for a given chain.
2021
+ * Parameters for route-aware fee calculation.
2022
+ */
2023
+ interface CalculateRouteAmountParams {
2024
+ /** Base price per byte charged by the destination node. */
2025
+ basePricePerByte: bigint;
2026
+ /** Length of the TOON-encoded packet in bytes. */
2027
+ packetByteLength: number;
2028
+ /** Per-byte fees for each intermediary hop on the route (ordered sender-to-destination). */
2029
+ hopFees: bigint[];
2030
+ }
2031
+ /**
2032
+ * Calculates the total ILP PREPARE amount including intermediary routing fees.
1004
2033
  *
1005
- * Priority: requester's preference > responder's preference > undefined
2034
+ * For a direct route (empty hopFees), returns basePricePerByte * packetByteLength.
2035
+ * For multi-hop routes, adds each intermediary's feePerByte * packetByteLength.
1006
2036
  *
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
2037
+ * @returns Total amount as bigint.
1011
2038
  */
1012
- declare function resolveTokenForChain(chain: string, requesterPreferredTokens?: Record<string, string>, responderPreferredTokens?: Record<string, string>): string | undefined;
2039
+ declare function calculateRouteAmount(params: CalculateRouteAmountParams): bigint;
1013
2040
 
1014
2041
  /**
1015
2042
  * Bootstrap state machine types, event types, and client interfaces.
@@ -1150,7 +2177,6 @@ type BootstrapEventListener = (event: BootstrapEvent) => void;
1150
2177
  */
1151
2178
  interface IlpSendResult {
1152
2179
  accepted: boolean;
1153
- fulfillment?: string;
1154
2180
  data?: string;
1155
2181
  code?: string;
1156
2182
  message?: string;
@@ -1224,6 +2250,83 @@ interface BootstrapServiceConfig extends BootstrapConfig {
1224
2250
  basePricePerByte?: bigint;
1225
2251
  }
1226
2252
 
2253
+ /**
2254
+ * Resolves intermediary routing fees from discovered peers using LCA-based
2255
+ * route resolution on the ILP address tree.
2256
+ *
2257
+ * Algorithm:
2258
+ * 1. Split sender and destination ILP addresses into segments.
2259
+ * 2. Find the longest common ancestor (LCA) -- shared prefix of segments.
2260
+ * 3. Intermediaries are the segments on the path from LCA down to destination's parent.
2261
+ * 4. For each intermediary, look up feePerByte from discovered peers.
2262
+ * 5. Unknown intermediaries default to feePerByte 0n with a warning.
2263
+ */
2264
+
2265
+ /**
2266
+ * Parameters for resolving route fees.
2267
+ */
2268
+ interface ResolveRouteFeesParams {
2269
+ /** ILP address of the destination node. */
2270
+ destination: string;
2271
+ /** ILP address of the sender (own node). */
2272
+ ownIlpAddress: string;
2273
+ /** All discovered peers (including peered ones) with their ILP peer info. */
2274
+ discoveredPeers: DiscoveredPeer[];
2275
+ }
2276
+ /**
2277
+ * Result of route fee resolution.
2278
+ */
2279
+ interface ResolveRouteFeesResult {
2280
+ /** Per-byte fees for each intermediary hop, ordered sender-to-destination. */
2281
+ hopFees: bigint[];
2282
+ /** Warning messages for unknown intermediaries that defaulted to 0. */
2283
+ warnings: string[];
2284
+ }
2285
+ /**
2286
+ * Resolves intermediary routing fees for a route from sender to destination.
2287
+ *
2288
+ * Uses LCA-based route resolution: intermediary hops are the ILP address
2289
+ * segments between the longest common ancestor and the destination's parent.
2290
+ *
2291
+ * The peer lookup map is cached by array reference to avoid rebuilding it
2292
+ * on every call when the same discoveredPeers array is passed repeatedly.
2293
+ *
2294
+ * @returns Hop fees and any warnings about unknown intermediaries.
2295
+ */
2296
+ declare function resolveRouteFees(params: ResolveRouteFeesParams): ResolveRouteFeesResult;
2297
+
2298
+ /**
2299
+ * Pure functions for settlement chain negotiation.
2300
+ * No I/O or side effects — used during peer registration to determine
2301
+ * the best matching settlement chain and token.
2302
+ */
2303
+ /**
2304
+ * Negotiates the best matching settlement chain between requester and responder.
2305
+ *
2306
+ * Preference order:
2307
+ * 1. Chain in intersection with requester's preferred token
2308
+ * 2. Chain in intersection with responder's preferred token
2309
+ * 3. First chain in intersection (requester's order preserved)
2310
+ *
2311
+ * @param requesterChains - Chain identifiers the requester supports
2312
+ * @param responderChains - Chain identifiers the responder supports
2313
+ * @param requesterPreferredTokens - Requester's preferred tokens by chain
2314
+ * @param responderPreferredTokens - Responder's preferred tokens by chain
2315
+ * @returns The negotiated chain identifier, or null if no intersection
2316
+ */
2317
+ declare function negotiateSettlementChain(requesterChains: string[], responderChains: string[], requesterPreferredTokens?: Record<string, string>, responderPreferredTokens?: Record<string, string>): string | null;
2318
+ /**
2319
+ * Resolves which token to use for a given chain.
2320
+ *
2321
+ * Priority: requester's preference > responder's preference > undefined
2322
+ *
2323
+ * @param chain - The chain identifier to resolve token for
2324
+ * @param requesterPreferredTokens - Requester's preferred tokens by chain
2325
+ * @param responderPreferredTokens - Responder's preferred tokens by chain
2326
+ * @returns The token address, or undefined if neither party has a preference
2327
+ */
2328
+ declare function resolveTokenForChain(chain: string, requesterPreferredTokens?: Record<string, string>, responderPreferredTokens?: Record<string, string>): string | undefined;
2329
+
1227
2330
  /**
1228
2331
  * Bootstrap service for peer discovery and network initialization.
1229
2332
  *
@@ -1374,6 +2477,19 @@ declare class BootstrapService {
1374
2477
  * @returns Map of pubkey to IlpPeerInfo for discovered peers
1375
2478
  */
1376
2479
  discoverPeersViaRelay(relayUrl: string, excludePubkeys?: string[]): Promise<Map<string, IlpPeerInfo>>;
2480
+ /**
2481
+ * Re-advertise own kind:10032 to all previously bootstrapped peers.
2482
+ *
2483
+ * Called after topology changes (addUpstreamPeer/removeUpstreamPeer) to
2484
+ * propagate updated ILP address lists to the network. Uses the same
2485
+ * ILP-first announcement path as the initial Phase 2 bootstrap.
2486
+ *
2487
+ * For non-ILP mode, publishes directly to each peer's relay URL.
2488
+ *
2489
+ * @param results - The bootstrap results from the initial bootstrap() call
2490
+ * @returns Number of peers successfully re-announced to
2491
+ */
2492
+ republish(results: BootstrapResult[]): Promise<number>;
1377
2493
  /**
1378
2494
  * Get our pubkey.
1379
2495
  */
@@ -1414,6 +2530,8 @@ interface DiscoveryTracker {
1414
2530
  peerWith(pubkey: string): Promise<void>;
1415
2531
  /** Get discovered peers not yet peered with. */
1416
2532
  getDiscoveredPeers(): DiscoveredPeer[];
2533
+ /** Get all discovered peers regardless of peering status (for fee calculation). */
2534
+ getAllDiscoveredPeers(): DiscoveredPeer[];
1417
2535
  /** Check if a pubkey has been actively peered with. */
1418
2536
  isPeered(pubkey: string): boolean;
1419
2537
  /** Count of registered (peered) peers. */
@@ -1478,9 +2596,7 @@ interface SendPacketParams {
1478
2596
  /** Amount as BigInt (not string) */
1479
2597
  amount: bigint;
1480
2598
  /** Binary data (not base64 string) */
1481
- data: Uint8Array;
1482
- /** 32-byte SHA-256 execution condition */
1483
- executionCondition?: Uint8Array;
2599
+ data?: Uint8Array;
1484
2600
  /**
1485
2601
  * Packet expiration. Included for structural compatibility with ConnectorNode
1486
2602
  * but is not set by the direct client — callers or the connector provide it
@@ -1493,15 +2609,13 @@ interface SendPacketParams {
1493
2609
  *
1494
2610
  * Accepts both string discriminants ('fulfill'/'reject') for backward
1495
2611
  * compatibility with test mocks, and numeric PacketType enum values
1496
- * (13 = FULFILL, 14 = REJECT) used by @toon-protocol/connector@1.6.0+.
2612
+ * (13 = FULFILL, 14 = REJECT) used by @toon-protocol/connector@2.0.0+.
1497
2613
  */
1498
2614
  type SendPacketResult = {
1499
2615
  type: 'fulfill';
1500
- fulfillment: Uint8Array | Buffer;
1501
2616
  data?: Uint8Array | Buffer;
1502
2617
  } | {
1503
2618
  type: 13;
1504
- fulfillment: Uint8Array | Buffer;
1505
2619
  data?: Uint8Array | Buffer;
1506
2620
  } | {
1507
2621
  type: 'reject';
@@ -1525,23 +2639,10 @@ interface ConnectorNodeLike {
1525
2639
  sendPacket(params: SendPacketParams): Promise<SendPacketResult>;
1526
2640
  }
1527
2641
  /**
1528
- * Configuration options for the direct runtime client.
2642
+ * @deprecated No longer used. Kept for backward compatibility.
1529
2643
  */
1530
2644
  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
- */
2645
+ /** @deprecated No longer used. */
1545
2646
  toonDecoder?: (bytes: Uint8Array) => {
1546
2647
  id: string;
1547
2648
  };
@@ -1554,7 +2655,7 @@ interface DirectRuntimeClientConfig {
1554
2655
  * @param config - Optional configuration (e.g., toonDecoder for condition computation)
1555
2656
  * @returns An IlpClient instance
1556
2657
  */
1557
- declare function createDirectIlpClient(connector: ConnectorNodeLike, config?: DirectRuntimeClientConfig): IlpClient;
2658
+ declare function createDirectIlpClient(connector: ConnectorNodeLike, _config?: DirectRuntimeClientConfig): IlpClient;
1558
2659
  /**
1559
2660
  * @deprecated Use createDirectIlpClient instead
1560
2661
  */
@@ -1763,117 +2864,6 @@ declare function createHttpIlpClient(connectorUrl: string): IlpClient;
1763
2864
  */
1764
2865
  declare function createHttpChannelClient(adminUrl: string): ConnectorChannelClient;
1765
2866
 
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
2867
  /**
1878
2868
  * AttestationBootstrap -- attestation-first seed relay bootstrap for Story 4.6.
1879
2869
  *
@@ -2029,8 +3019,6 @@ interface HandlePacketRequest {
2029
3019
  */
2030
3020
  interface HandlePacketAcceptResponse {
2031
3021
  accept: true;
2032
- /** Base64-encoded fulfillment (SHA-256 of event.id) */
2033
- fulfillment: string;
2034
3022
  /** Base64-encoded response data (e.g., TOON-encoded response for relay back in ILP FULFILL) */
2035
3023
  data?: string;
2036
3024
  metadata?: Record<string, unknown>;
@@ -2262,7 +3250,7 @@ declare function createToonNode(config: ToonNodeConfig): ToonNode;
2262
3250
  * The legacy on-chain mock contract on Anvil uses 18 decimals (inherited
2263
3251
  * from the original ERC-20 deploy script in the connector repo). The
2264
3252
  * constants below reflect production USDC semantics (6 decimals). When
2265
- * interacting with the Anvil mock contract directly (e.g., fund-peer-wallet.sh,
3253
+ * interacting with the Anvil mock contract directly (e.g., via the
2266
3254
  * faucet), use 18 decimals for on-chain amounts. The pricing pipeline
2267
3255
  * (basePricePerByte * toonLength) is denomination-agnostic (bigint math)
2268
3256
  * and works correctly regardless of on-chain decimals.
@@ -2320,10 +3308,10 @@ declare const MOCK_USDC_CONFIG: MockUsdcConfig;
2320
3308
  /**
2321
3309
  * Multi-environment chain configuration for TOON relay nodes.
2322
3310
  *
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
3311
+ * Provides chain presets for three blockchain families:
3312
+ * - **EVM**: Anvil (local dev), Arbitrum Sepolia (staging), Arbitrum One (production)
3313
+ * - **Solana**: solana-devnet (local dev)
3314
+ * - **Mina**: mina-devnet (local dev)
2327
3315
  *
2328
3316
  * Environment variable overrides:
2329
3317
  * - `TOON_CHAIN` overrides the config-level chain parameter
@@ -2333,11 +3321,27 @@ declare const MOCK_USDC_CONFIG: MockUsdcConfig;
2333
3321
  * @module
2334
3322
  */
2335
3323
  /**
2336
- * Supported chain preset names.
3324
+ * Blockchain family type. Matches the connector's BlockchainType.
3325
+ */
3326
+ type ChainType = 'evm' | 'solana' | 'mina';
3327
+ /**
3328
+ * Supported EVM chain preset names (backward-compatible).
2337
3329
  */
2338
3330
  type ChainName = 'anvil' | 'arbitrum-sepolia' | 'arbitrum-one';
2339
3331
  /**
2340
- * Resolved chain configuration with all fields populated.
3332
+ * Supported Solana chain preset names.
3333
+ */
3334
+ type SolanaChainName = 'solana-devnet';
3335
+ /**
3336
+ * Supported Mina chain preset names.
3337
+ */
3338
+ type MinaChainName = 'mina-devnet';
3339
+ /**
3340
+ * All supported chain preset names across all chain types.
3341
+ */
3342
+ type MultiChainName = ChainName | SolanaChainName | MinaChainName;
3343
+ /**
3344
+ * Resolved EVM chain configuration with all fields populated.
2341
3345
  */
2342
3346
  interface ChainPreset {
2343
3347
  /** Preset identifier ('anvil' | 'arbitrum-sepolia' | 'arbitrum-one'). */
@@ -2350,9 +3354,85 @@ interface ChainPreset {
2350
3354
  usdcAddress: string;
2351
3355
  /** TokenNetwork contract address for USDC on this chain. */
2352
3356
  tokenNetworkAddress: string;
3357
+ /** TokenNetworkRegistry contract address on this chain. */
3358
+ registryAddress: string;
3359
+ }
3360
+ /**
3361
+ * Resolved Solana chain configuration.
3362
+ */
3363
+ interface SolanaChainPreset {
3364
+ /** Preset identifier (e.g., 'solana-devnet'). */
3365
+ name: string;
3366
+ /** Chain type discriminator. */
3367
+ chainType: 'solana';
3368
+ /** Solana cluster RPC endpoint (HTTP). */
3369
+ rpcUrl: string;
3370
+ /** Payment channel program ID (base58-encoded). TBD until deployed. */
3371
+ programId: string;
3372
+ /** Solana cluster name for chain ID namespacing (e.g., 'devnet'). */
3373
+ cluster: string;
3374
+ /** Optional SPL token mint address. */
3375
+ tokenMint?: string;
3376
+ }
3377
+ /**
3378
+ * Resolved Mina chain configuration.
3379
+ */
3380
+ interface MinaChainPreset {
3381
+ /** Preset identifier (e.g., 'mina-devnet'). */
3382
+ name: string;
3383
+ /** Chain type discriminator. */
3384
+ chainType: 'mina';
3385
+ /** Mina GraphQL endpoint. */
3386
+ graphqlUrl: string;
3387
+ /** zkApp address for the payment channel contract. TBD until deployed. */
3388
+ zkAppAddress: string;
3389
+ /** Mina network name (e.g., 'devnet'). */
3390
+ network: string;
3391
+ /** Optional Mina token ID. */
3392
+ tokenId?: string;
3393
+ }
3394
+ /**
3395
+ * EVM-specific provider configuration entry.
3396
+ */
3397
+ interface EVMProviderConfigEntry {
3398
+ chainType: 'evm';
3399
+ chainId: string;
3400
+ rpcUrl: string;
3401
+ registryAddress: string;
3402
+ keyId: string;
3403
+ }
3404
+ /**
3405
+ * Solana-specific provider configuration entry.
3406
+ */
3407
+ interface SolanaProviderConfigEntry {
3408
+ chainType: 'solana';
3409
+ chainId: string;
3410
+ rpcUrl: string;
3411
+ programId: string;
3412
+ keyId: string;
3413
+ wsUrl?: string;
3414
+ cluster?: string;
3415
+ tokenMint?: string;
3416
+ }
3417
+ /**
3418
+ * Mina-specific provider configuration entry.
3419
+ */
3420
+ interface MinaProviderConfigEntry {
3421
+ chainType: 'mina';
3422
+ chainId: string;
3423
+ graphqlUrl: string;
3424
+ zkAppAddress: string;
3425
+ keyId?: string;
3426
+ tokenId?: string;
3427
+ network?: string;
2353
3428
  }
2354
3429
  /**
2355
- * Built-in chain presets for supported deployment environments.
3430
+ * Discriminated union of all chain provider config entries.
3431
+ * Mirrors the connector's ChainProviderConfigEntry type for passthrough.
3432
+ */
3433
+ type ChainProviderConfigEntry = EVMProviderConfigEntry | SolanaProviderConfigEntry | MinaProviderConfigEntry;
3434
+ /**
3435
+ * Built-in EVM chain presets for supported deployment environments.
2356
3436
  *
2357
3437
  * Each preset provides the chainId, RPC URL, USDC address, and
2358
3438
  * TokenNetwork address for its environment. Fields can be overridden
@@ -2369,6 +3449,7 @@ declare const CHAIN_PRESETS: Record<ChainName, ChainPreset>;
2369
3449
  * 3. Looks up the chain name in `CHAIN_PRESETS`
2370
3450
  * 4. `TOON_RPC_URL` env var overrides the preset's `rpcUrl`
2371
3451
  * 5. `TOON_TOKEN_NETWORK` env var overrides the preset's `tokenNetworkAddress`
3452
+ * 6. `TOON_REGISTRY_ADDRESS` env var overrides the preset's `registryAddress`
2372
3453
  *
2373
3454
  * Returns a defensive copy -- callers can mutate the result without
2374
3455
  * affecting the shared preset objects.
@@ -2401,6 +3482,65 @@ declare function buildEip712Domain(config: ChainPreset): {
2401
3482
  chainId: number;
2402
3483
  verifyingContract: string;
2403
3484
  };
3485
+ /**
3486
+ * Built-in Solana chain presets.
3487
+ */
3488
+ declare const SOLANA_CHAIN_PRESETS: Record<SolanaChainName, SolanaChainPreset>;
3489
+ /**
3490
+ * Built-in Mina chain presets.
3491
+ */
3492
+ declare const MINA_CHAIN_PRESETS: Record<MinaChainName, MinaChainPreset>;
3493
+ /**
3494
+ * Resolve a Solana chain preset by name, with env var overrides.
3495
+ *
3496
+ * Environment variable overrides:
3497
+ * - `SOLANA_RPC_URL` overrides the preset's rpcUrl
3498
+ * - `SOLANA_PROGRAM_ID` overrides the preset's programId
3499
+ *
3500
+ * @param name - Solana chain preset name
3501
+ * @returns Resolved Solana chain preset
3502
+ * @throws ToonError if the name is not recognized
3503
+ */
3504
+ declare function resolveSolanaChainConfig(name: SolanaChainName): SolanaChainPreset;
3505
+ /**
3506
+ * Resolve a Mina chain preset by name, with env var overrides.
3507
+ *
3508
+ * Environment variable overrides:
3509
+ * - `MINA_GRAPHQL_URL` overrides the preset's graphqlUrl
3510
+ * - `MINA_ZKAPP_ADDRESS` overrides the preset's zkAppAddress
3511
+ *
3512
+ * @param name - Mina chain preset name
3513
+ * @returns Resolved Mina chain preset
3514
+ * @throws ToonError if the name is not recognized
3515
+ */
3516
+ declare function resolveMinaChainConfig(name: MinaChainName): MinaChainPreset;
3517
+ /**
3518
+ * Build a ChainProviderConfigEntry from a resolved EVM chain preset.
3519
+ *
3520
+ * Converts the TOON-specific ChainPreset into the connector's
3521
+ * ChainProviderConfigEntry format for the `chainProviders` array.
3522
+ *
3523
+ * @param config - Resolved EVM chain preset
3524
+ * @param keyId - Key identifier for signing operations
3525
+ * @returns EVM chain provider config entry
3526
+ */
3527
+ declare function buildEvmProviderEntry(config: ChainPreset, keyId: string): EVMProviderConfigEntry;
3528
+ /**
3529
+ * Build a ChainProviderConfigEntry from a resolved Solana chain preset.
3530
+ *
3531
+ * @param config - Resolved Solana chain preset
3532
+ * @param keyId - Key identifier for Ed25519 signing operations
3533
+ * @returns Solana chain provider config entry
3534
+ */
3535
+ declare function buildSolanaProviderEntry(config: SolanaChainPreset, keyId: string): SolanaProviderConfigEntry;
3536
+ /**
3537
+ * Build a ChainProviderConfigEntry from a resolved Mina chain preset.
3538
+ *
3539
+ * @param config - Resolved Mina chain preset
3540
+ * @param keyId - Optional key identifier for signing operations
3541
+ * @returns Mina chain provider config entry
3542
+ */
3543
+ declare function buildMinaProviderEntry(config: MinaChainPreset, keyId?: string): MinaProviderConfigEntry;
2404
3544
 
2405
3545
  /**
2406
3546
  * Shared ILP PREPARE packet construction for the TOON protocol.
@@ -2850,4 +3990,4 @@ declare function createLogger(config: LoggerConfig): Logger;
2850
3990
  */
2851
3991
  declare const VERSION = "0.1.0";
2852
3992
 
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 };
3993
+ export { AddressRegistry, type AgentRuntimeClient, ArDrivePeerRegistry, AttestationBootstrap, type AttestationBootstrapConfig, type AttestationBootstrapEvent, type AttestationBootstrapEventListener, type AttestationBootstrapResult, type AttestationEventOptions, AttestationState, AttestationVerifier, type AttestationVerifierConfig, type AttestedResultVerificationOptions, type AttestedResultVerificationResult, AttestedResultVerifier, BLOB_STORAGE_REQUEST_KIND, BLOB_STORAGE_RESULT_KIND, type BlobStorageRequestParams, type BootstrapConfig, BootstrapError, type BootstrapEvent, type BootstrapEventListener, type BootstrapPhase, type BootstrapResult, BootstrapService, type BootstrapServiceConfig, type BtpHandshakeExtension, type BuildIlpPrepareParams, CHAIN_PRESETS, type CalculateRouteAmountParams, type ChainName, type ChainPreset, type ChainProviderConfigEntry, type ChainType, 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 EVMProviderConfigEntry, type EmbeddableConnectorLike, type ForbiddenPattern, type GenesisPeer, GenesisPeerLoader, type HandlePacketAcceptResponse, type HandlePacketRejectResponse, type HandlePacketRequest, type HandlePacketResponse, ILP_PEER_INFO_KIND, ILP_ROOT_PREFIX, IMAGE_GENERATION_KIND, type IlpClient, type IlpPeerInfo, type IlpPreparePacket, type IlpSendResult, JOB_FEEDBACK_KIND, JOB_REQUEST_KIND_BASE, JOB_RESULT_KIND_BASE, JOB_REVIEW_KIND, type JobFeedbackParams, type JobRequestParams, type JobResultParams, type JobReviewParams, KmsIdentityError, type KmsKeypair, type KnownPeer, type LogEntry, type LogLevel, type Logger, type LoggerConfig, MINA_CHAIN_PRESETS, MOCK_USDC_ADDRESS, MOCK_USDC_CONFIG, type MinaChainName, type MinaChainPreset, type MinaProviderConfigEntry, type MockUsdcConfig, type MultiChainName, type NixBuildResult, NixBuilder, type NixBuilderConfig, NostrPeerDiscovery, type OpenChannelParams, type OpenChannelResult, PREFIX_CLAIM_KIND, PREFIX_GRANT_KIND, type PacketHandler, type ParsedAttestation, type ParsedBlobStorageRequest, type ParsedJobFeedback, type ParsedJobRequest, type ParsedJobResult, type ParsedJobReview, type ParsedSwarmRequest, type ParsedSwarmSelection, type ParsedWorkflowDefinition, type ParsedWotDeclaration, PcrReproducibilityError, type PcrReproducibilityResult, type PeerDescriptor, type PrefixClaimContent, type PrefixGrantContent, type PrefixValidationResult, type PublishSeedRelayConfig, type RegisterPeerParams, type ReputationScore, ReputationScoreCalculator, type ReputationSignals, type ResolveRouteFeesParams, type ResolveRouteFeesResult, SEED_RELAY_LIST_KIND, SERVICE_DISCOVERY_KIND, SOLANA_CHAIN_PRESETS, 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 SolanaChainName, type SolanaChainPreset, type SolanaProviderConfigEntry, type Subscription, type SwarmRequestParams, type SwarmSelectionParams, 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, WEB_OF_TRUST_KIND, WORKFLOW_CHAIN_KIND, type WorkflowDefinitionParams, type WorkflowStep, type WotDeclarationParams, analyzeDockerfileForNonDeterminism, assignAddressFromHandshake, buildAttestationEvent, buildBlobStorageRequest, buildEip712Domain, buildEvmProviderEntry, buildIlpPeerInfoEvent, buildIlpPrepare, buildJobFeedbackEvent, buildJobRequestEvent, buildJobResultEvent, buildJobReviewEvent, buildMinaProviderEntry, buildPrefixClaimEvent, buildPrefixGrantEvent, buildPrefixHandshakeData, buildSeedRelayListEvent, buildServiceDiscoveryEvent, buildSolanaProviderEntry, buildSwarmRequestEvent, buildSwarmSelectionEvent, buildWorkflowDefinitionEvent, buildWotDeclarationEvent, calculateRouteAmount, checkAddressCollision, createAgentRuntimeClient, createDirectChannelClient, createDirectConnectorAdmin, createDirectIlpClient, createDirectRuntimeClient, createDiscoveryTracker, createHttpChannelClient, createHttpConnectorAdmin, createHttpIlpClient$1 as createHttpIlpClient, createHttpRuntimeClient, createHttpIlpClient as createHttpRuntimeClientV2, createLogger, createToonNode, deriveChildAddress, deriveFromKmsSeed, extractPrefixFromHandshake, hasMinReputation, hasRequireAttestation, isGenesisNode, isValidIlpAddressStructure, negotiateSettlementChain, parseAttestation, parseBlobStorageRequest, parseIlpPeerInfo, parseJobFeedback, parseJobRequest, parseJobResult, parseJobReview, parsePrefixClaimEvent, parsePrefixGrantEvent, parseSeedRelayList, parseServiceDiscovery, parseSwarmRequest, parseSwarmSelection, parseWorkflowDefinition, parseWotDeclaration, publishSeedRelayEntry, readDockerfileNix, resolveChainConfig, resolveMinaChainConfig, resolveRouteFees, resolveSolanaChainConfig, resolveTokenForChain, validateChainId, validateIlpAddress, validatePrefix, validatePrefixConsistency, verifyPcrReproducibility };