@toon-protocol/sdk 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -4
- package/dist/chunk-UP2VWCW5.js +38 -0
- package/dist/chunk-UP2VWCW5.js.map +1 -0
- package/dist/index.d.ts +646 -6
- package/dist/index.js +1046 -17
- package/dist/index.js.map +1 -1
- package/dist/node-WPA2UDEH.js +8221 -0
- package/dist/node-WPA2UDEH.js.map +1 -0
- package/package.json +6 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ToonError, HandlePacketAcceptResponse, HandlePacketRejectResponse, SkillDescriptor, EmbeddableConnectorLike, KnownPeer, SettlementConfig, ConnectorChannelClient, BootstrapEventListener, BootstrapResult, DvmJobStatus, IlpSendResult } from '@toon-protocol/core';
|
|
1
|
+
import { ToonError, HandlePacketAcceptResponse, HandlePacketRejectResponse, ReputationScore, SkillDescriptor, EmbeddableConnectorLike, KnownPeer, SettlementConfig, ChainProviderConfigEntry, ConnectorChannelClient, BootstrapEventListener, BootstrapResult, DvmJobStatus, IlpSendResult, ParsedWorkflowDefinition } from '@toon-protocol/core';
|
|
2
2
|
export { BootstrapEvent, BootstrapEventListener, HandlePacketAcceptResponse, HandlePacketRejectResponse, SkillDescriptor } from '@toon-protocol/core';
|
|
3
3
|
import { NostrEvent } from 'nostr-tools/pure';
|
|
4
4
|
import { ToonRoutingMeta } from '@toon-protocol/core/toon';
|
|
@@ -251,7 +251,6 @@ interface PaymentRequest {
|
|
|
251
251
|
}
|
|
252
252
|
interface PaymentResponse {
|
|
253
253
|
accept: boolean;
|
|
254
|
-
fulfillment?: string;
|
|
255
254
|
code?: string;
|
|
256
255
|
message?: string;
|
|
257
256
|
data?: string;
|
|
@@ -309,6 +308,15 @@ interface BuildSkillDescriptorConfig {
|
|
|
309
308
|
inputSchema?: Record<string, unknown>;
|
|
310
309
|
/** Available AI models. */
|
|
311
310
|
models?: string[];
|
|
311
|
+
/** Pre-computed reputation score for the skill descriptor. */
|
|
312
|
+
reputation?: ReputationScore;
|
|
313
|
+
/** TEE attestation metadata for the skill descriptor. */
|
|
314
|
+
attestation?: {
|
|
315
|
+
/** 64-char hex event ID of the provider's latest kind:10033 attestation event. */
|
|
316
|
+
eventId: string;
|
|
317
|
+
/** Enclave image hash for the TEE environment. */
|
|
318
|
+
enclaveImageHash: string;
|
|
319
|
+
};
|
|
312
320
|
}
|
|
313
321
|
/**
|
|
314
322
|
* Builds a SkillDescriptor from the handler registry and configuration.
|
|
@@ -387,7 +395,19 @@ interface NodeConfig {
|
|
|
387
395
|
* If not set, the identity's secp256k1 key is used.
|
|
388
396
|
*/
|
|
389
397
|
settlementPrivateKey?: string;
|
|
390
|
-
/**
|
|
398
|
+
/**
|
|
399
|
+
* Upstream peer's ILP address prefix for address derivation.
|
|
400
|
+
* When set, the node derives its ILP address as
|
|
401
|
+
* `deriveChildAddress(upstreamPrefix, pubkey)` and ignores `ilpAddress`.
|
|
402
|
+
*/
|
|
403
|
+
upstreamPrefix?: string;
|
|
404
|
+
/**
|
|
405
|
+
* Multiple upstream peer prefixes for multi-peered nodes (Story 7.3).
|
|
406
|
+
* When set, derives one ILP address per upstream prefix. Takes priority
|
|
407
|
+
* over `upstreamPrefix` (singular) when both are set.
|
|
408
|
+
*/
|
|
409
|
+
upstreamPrefixes?: string[];
|
|
410
|
+
/** ILP address (default: derived from pubkey under ILP_ROOT_PREFIX) */
|
|
391
411
|
ilpAddress?: string;
|
|
392
412
|
/** BTP endpoint URL advertised in kind:10032 announcements */
|
|
393
413
|
btpEndpoint?: string;
|
|
@@ -403,6 +423,11 @@ interface NodeConfig {
|
|
|
403
423
|
* A 1KB event costs 10,240 micro-USDC = ~$0.01.
|
|
404
424
|
*/
|
|
405
425
|
basePricePerByte?: bigint;
|
|
426
|
+
/**
|
|
427
|
+
* Routing fee per byte charged by this node as an intermediary (default: 0n = free routing).
|
|
428
|
+
* Advertised in kind:10032 peer info events as a non-negative integer string.
|
|
429
|
+
*/
|
|
430
|
+
feePerByte?: bigint;
|
|
406
431
|
/** Dev mode skips signature verification (default: false) */
|
|
407
432
|
devMode?: boolean;
|
|
408
433
|
/** TOON encoder function */
|
|
@@ -419,6 +444,28 @@ interface NodeConfig {
|
|
|
419
444
|
ardriveEnabled?: boolean;
|
|
420
445
|
/** Per-kind pricing overrides */
|
|
421
446
|
kindPricing?: Record<number, bigint>;
|
|
447
|
+
/**
|
|
448
|
+
* Multi-chain provider configuration for the embedded connector.
|
|
449
|
+
* When provided, passed directly to ConnectorNode as `chainProviders`.
|
|
450
|
+
* Takes priority over the legacy `settlementInfra` auto-configuration.
|
|
451
|
+
* Only used when auto-creating an embedded connector.
|
|
452
|
+
*/
|
|
453
|
+
chainProviders?: ChainProviderConfigEntry[];
|
|
454
|
+
/**
|
|
455
|
+
* NIP-59 transport privacy configuration for the embedded connector.
|
|
456
|
+
* When enabled, per-packet claims are wrapped in three-layer encryption.
|
|
457
|
+
* Only used when auto-creating an embedded connector.
|
|
458
|
+
*/
|
|
459
|
+
nip59?: {
|
|
460
|
+
enabled: boolean;
|
|
461
|
+
};
|
|
462
|
+
/**
|
|
463
|
+
* Per-peer NIP-59 public keys for claim encryption.
|
|
464
|
+
* Map of peer ID to compressed secp256k1 public key (hex, 66 chars).
|
|
465
|
+
* Applied to peer configs when registering peers with the connector.
|
|
466
|
+
* Only used when auto-creating an embedded connector.
|
|
467
|
+
*/
|
|
468
|
+
peerNip59PublicKeys?: Record<string, string>;
|
|
422
469
|
/** Config-based handler registration (alternative to post-creation .on()) */
|
|
423
470
|
handlers?: Record<number, Handler>;
|
|
424
471
|
/** Config-based default handler (alternative to post-creation .onDefault()) */
|
|
@@ -447,7 +494,8 @@ interface StartResult {
|
|
|
447
494
|
interface PublishEventResult {
|
|
448
495
|
success: boolean;
|
|
449
496
|
eventId: string;
|
|
450
|
-
|
|
497
|
+
/** Response data from the ILP FULFILL packet (e.g., Arweave tx ID for kind:5094). */
|
|
498
|
+
data?: string;
|
|
451
499
|
code?: string;
|
|
452
500
|
message?: string;
|
|
453
501
|
}
|
|
@@ -482,11 +530,17 @@ interface ServiceNode {
|
|
|
482
530
|
* ILP PREPARE packet via the runtime client.
|
|
483
531
|
*
|
|
484
532
|
* @param event - The Nostr event to publish
|
|
485
|
-
* @param options - Must include destination ILP address
|
|
533
|
+
* @param options - Must include destination ILP address. Optional `amount`
|
|
534
|
+
* overrides the default basePricePerByte * toonData.length calculation
|
|
535
|
+
* (prepaid model: send exact destination amount). Optional `bid` is a
|
|
536
|
+
* client-side safety cap: if the destination amount exceeds `bid`, the
|
|
537
|
+
* SDK throws before sending any ILP packet.
|
|
486
538
|
* @returns Result with success/failure info and event ID
|
|
487
539
|
*/
|
|
488
540
|
publishEvent(event: NostrEvent, options?: {
|
|
489
541
|
destination: string;
|
|
542
|
+
amount?: bigint;
|
|
543
|
+
bid?: bigint;
|
|
490
544
|
}): Promise<PublishEventResult>;
|
|
491
545
|
/**
|
|
492
546
|
* Publish a Kind 7000 DVM job feedback event via ILP PREPARE.
|
|
@@ -541,6 +595,10 @@ interface ServiceNode {
|
|
|
541
595
|
* The payment routes through the ILP mesh using the same infrastructure
|
|
542
596
|
* as relay write fees.
|
|
543
597
|
*
|
|
598
|
+
* @deprecated Use publishEvent() with amount option instead. Prepaid model:
|
|
599
|
+
* send job request + payment in one packet via
|
|
600
|
+
* `publishEvent(event, { destination, amount: computePrice })`.
|
|
601
|
+
*
|
|
544
602
|
* @param resultEvent - Kind 6xxx result event with amount tag
|
|
545
603
|
* @param providerIlpAddress - Provider's ILP address from kind:10035
|
|
546
604
|
* @param options - Optional originalBid for bid validation (E5-R005)
|
|
@@ -549,6 +607,40 @@ interface ServiceNode {
|
|
|
549
607
|
settleCompute(resultEvent: NostrEvent, providerIlpAddress: string, options?: {
|
|
550
608
|
originalBid?: string;
|
|
551
609
|
}): Promise<IlpSendResult>;
|
|
610
|
+
/**
|
|
611
|
+
* Add a new upstream peer, deriving and registering its ILP address.
|
|
612
|
+
*
|
|
613
|
+
* Updates the AddressRegistry, registers a self-route in the embedded
|
|
614
|
+
* connector, and triggers kind:10032 republication via BootstrapService.
|
|
615
|
+
*
|
|
616
|
+
* @param upstreamPrefix - The upstream peer's ILP address prefix
|
|
617
|
+
*/
|
|
618
|
+
addUpstreamPeer(upstreamPrefix: string): void;
|
|
619
|
+
/**
|
|
620
|
+
* Remove an upstream peer, unregistering its derived ILP address.
|
|
621
|
+
*
|
|
622
|
+
* Updates the AddressRegistry, removes the self-route from the embedded
|
|
623
|
+
* connector, and triggers kind:10032 republication via BootstrapService.
|
|
624
|
+
*
|
|
625
|
+
* @param upstreamPrefix - The upstream prefix to remove
|
|
626
|
+
*/
|
|
627
|
+
removeUpstreamPeer(upstreamPrefix: string): void;
|
|
628
|
+
/**
|
|
629
|
+
* Claim a prefix from an upstream peer by sending a prefix claim event
|
|
630
|
+
* with payment via ILP.
|
|
631
|
+
*
|
|
632
|
+
* Builds a Kind 10034 prefix claim event, reads the upstream's prefix
|
|
633
|
+
* pricing from its kind:10032 advertisement, and calls publishEvent()
|
|
634
|
+
* with the appropriate amount.
|
|
635
|
+
*
|
|
636
|
+
* @param prefix - The prefix string to claim (e.g., 'useast')
|
|
637
|
+
* @param upstreamDestination - ILP address of the upstream node
|
|
638
|
+
* @param options - Optional prefixPrice override (defaults to upstream's prefixPricing.basePrice from discovery)
|
|
639
|
+
* @returns Result with success/failure info and event ID
|
|
640
|
+
*/
|
|
641
|
+
claimPrefix(prefix: string, upstreamDestination: string, options?: {
|
|
642
|
+
prefixPrice?: bigint;
|
|
643
|
+
}): Promise<PublishEventResult>;
|
|
552
644
|
}
|
|
553
645
|
/**
|
|
554
646
|
* Creates a fully wired ServiceNode from configuration.
|
|
@@ -570,4 +662,552 @@ interface ServiceNode {
|
|
|
570
662
|
*/
|
|
571
663
|
declare function createNode(config: NodeConfig): ServiceNode;
|
|
572
664
|
|
|
573
|
-
|
|
665
|
+
/**
|
|
666
|
+
* Workflow Orchestrator for multi-step DVM pipelines (Story 6.1).
|
|
667
|
+
*
|
|
668
|
+
* Manages the lifecycle of a workflow chain: creates step job requests,
|
|
669
|
+
* detects step completion/failure, advances to the next step, handles
|
|
670
|
+
* timeouts, and settles compute payments per step.
|
|
671
|
+
*
|
|
672
|
+
* The orchestrator uses the TOON relay as the orchestration layer --
|
|
673
|
+
* there is no separate workflow engine. Step completion is detected
|
|
674
|
+
* via relay event subscriptions (Kind 6xxx results, Kind 7000 feedback).
|
|
675
|
+
*
|
|
676
|
+
* State machine states:
|
|
677
|
+
* - `pending`: Workflow created but not yet started
|
|
678
|
+
* - `step_N_running`: Step N's job request published, waiting for result
|
|
679
|
+
* - `step_N_failed`: Step N failed (error or timeout), workflow aborted
|
|
680
|
+
* - `completed`: All steps finished successfully
|
|
681
|
+
*
|
|
682
|
+
* Settlement: Each step settles individually via settleCompute().
|
|
683
|
+
* The orchestrator validates sum(step_amounts) <= total_bid before settlement.
|
|
684
|
+
*
|
|
685
|
+
* Forward-compatible with Epic 7 prepaid protocol: settlement logic is
|
|
686
|
+
* isolated in handleStepResult() so swapping to prepaid per-step payment
|
|
687
|
+
* requires changes only in that method.
|
|
688
|
+
*/
|
|
689
|
+
|
|
690
|
+
/**
|
|
691
|
+
* Workflow state type. Uses template literal types for step-indexed states.
|
|
692
|
+
* Note: Timeout is represented as `step_N_failed` (timeout is a failure mode,
|
|
693
|
+
* not a separate terminal state). The timeout cause is communicated in the
|
|
694
|
+
* customer notification content.
|
|
695
|
+
*/
|
|
696
|
+
type WorkflowState = 'pending' | `step_${number}_running` | `step_${number}_failed` | 'completed';
|
|
697
|
+
/**
|
|
698
|
+
* Event store interface for workflow state persistence.
|
|
699
|
+
* Minimal interface -- only store() and query() are needed.
|
|
700
|
+
*/
|
|
701
|
+
interface WorkflowEventStore {
|
|
702
|
+
store(event: NostrEvent): Promise<void>;
|
|
703
|
+
query(filter: {
|
|
704
|
+
kinds?: number[];
|
|
705
|
+
'#e'?: string[];
|
|
706
|
+
}): Promise<NostrEvent[]>;
|
|
707
|
+
}
|
|
708
|
+
/**
|
|
709
|
+
* Configuration options for the WorkflowOrchestrator.
|
|
710
|
+
*/
|
|
711
|
+
interface WorkflowOrchestratorOptions {
|
|
712
|
+
/** Secret key for signing step job request events (32-byte Uint8Array). */
|
|
713
|
+
secretKey?: Uint8Array;
|
|
714
|
+
/** Per-step timeout in milliseconds (default: 300000 = 5 minutes). */
|
|
715
|
+
stepTimeoutMs?: number;
|
|
716
|
+
/** Injectable time source for deterministic testing. */
|
|
717
|
+
now?: () => number;
|
|
718
|
+
/**
|
|
719
|
+
* Injectable timer factory for deterministic testing.
|
|
720
|
+
* Defaults to global setTimeout. Inject a custom implementation
|
|
721
|
+
* to control timer advancement in tests without vi.useFakeTimers().
|
|
722
|
+
*/
|
|
723
|
+
setTimer?: (callback: () => void, ms: number) => ReturnType<typeof setTimeout>;
|
|
724
|
+
/**
|
|
725
|
+
* Injectable timer cancellation for deterministic testing.
|
|
726
|
+
* Defaults to global clearTimeout. Must pair with setTimer.
|
|
727
|
+
*/
|
|
728
|
+
clearTimer?: (handle: ReturnType<typeof setTimeout>) => void;
|
|
729
|
+
/** Optional event store for workflow state persistence. */
|
|
730
|
+
eventStore?: WorkflowEventStore;
|
|
731
|
+
/** Default destination ILP address for publishing events. */
|
|
732
|
+
destination?: string;
|
|
733
|
+
/** Workflow definition event ID (for referencing in notifications). */
|
|
734
|
+
workflowEventId?: string;
|
|
735
|
+
/** Customer pubkey (for directing notifications). */
|
|
736
|
+
customerPubkey?: string;
|
|
737
|
+
}
|
|
738
|
+
/**
|
|
739
|
+
* Per-step state tracking.
|
|
740
|
+
*/
|
|
741
|
+
interface StepState {
|
|
742
|
+
/** Index of this step (0-based). */
|
|
743
|
+
index: number;
|
|
744
|
+
/** The job request event ID published for this step. */
|
|
745
|
+
requestEventId?: string;
|
|
746
|
+
/** The result event received for this step. */
|
|
747
|
+
resultEvent?: NostrEvent;
|
|
748
|
+
/** Whether this step has been settled. */
|
|
749
|
+
settled: boolean;
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* Orchestrates a multi-step DVM workflow chain.
|
|
753
|
+
*
|
|
754
|
+
* Each instance manages a single workflow. For concurrent workflows,
|
|
755
|
+
* create multiple WorkflowOrchestrator instances sharing the same
|
|
756
|
+
* ServiceNode.
|
|
757
|
+
*/
|
|
758
|
+
declare class WorkflowOrchestrator {
|
|
759
|
+
private readonly node;
|
|
760
|
+
private readonly options;
|
|
761
|
+
private state;
|
|
762
|
+
private definition;
|
|
763
|
+
private workflowEventId;
|
|
764
|
+
private customerPubkey;
|
|
765
|
+
private currentStepIndex;
|
|
766
|
+
private stepStates;
|
|
767
|
+
private timeoutHandle;
|
|
768
|
+
private processedResultIds;
|
|
769
|
+
constructor(node: ServiceNode, options?: WorkflowOrchestratorOptions);
|
|
770
|
+
/**
|
|
771
|
+
* Returns the current workflow state.
|
|
772
|
+
*/
|
|
773
|
+
getState(): WorkflowState;
|
|
774
|
+
/**
|
|
775
|
+
* Returns per-step state tracking data (for testing/debugging).
|
|
776
|
+
*/
|
|
777
|
+
getStepStates(): readonly Readonly<StepState>[];
|
|
778
|
+
/**
|
|
779
|
+
* Starts a workflow: parses the definition, creates and publishes
|
|
780
|
+
* the Kind 5xxx job request for step 1, sets state to step_1_running.
|
|
781
|
+
*/
|
|
782
|
+
startWorkflow(definition: ParsedWorkflowDefinition): Promise<void>;
|
|
783
|
+
/**
|
|
784
|
+
* Handles a Kind 6xxx result event for the current step.
|
|
785
|
+
*
|
|
786
|
+
* If the current step matches, extracts the result content and either:
|
|
787
|
+
* - Advances to the next step (publishes Kind 5xxx for step N+1)
|
|
788
|
+
* - Marks workflow as completed (if this was the final step)
|
|
789
|
+
*
|
|
790
|
+
* Idempotent: re-processing a result for an already-advanced step is a no-op.
|
|
791
|
+
*/
|
|
792
|
+
handleStepResult(resultEvent: NostrEvent): Promise<void>;
|
|
793
|
+
/**
|
|
794
|
+
* Handles a Kind 7000 feedback event for the current step.
|
|
795
|
+
*
|
|
796
|
+
* If the feedback status is 'error', marks the workflow as failed
|
|
797
|
+
* and notifies the customer.
|
|
798
|
+
*/
|
|
799
|
+
handleStepFeedback(feedbackEvent: NostrEvent): Promise<void>;
|
|
800
|
+
/**
|
|
801
|
+
* Cleans up resources (timeout handles).
|
|
802
|
+
*/
|
|
803
|
+
destroy(): void;
|
|
804
|
+
/**
|
|
805
|
+
* Publishes a Kind 5xxx job request for the given step.
|
|
806
|
+
*/
|
|
807
|
+
private publishStepRequest;
|
|
808
|
+
/**
|
|
809
|
+
* Settles compute payment for a completed step.
|
|
810
|
+
*/
|
|
811
|
+
private settleStep;
|
|
812
|
+
/**
|
|
813
|
+
* Returns the bid allocation for a specific step.
|
|
814
|
+
* Uses explicit bidAllocation if set, otherwise proportional split.
|
|
815
|
+
*/
|
|
816
|
+
private getStepBid;
|
|
817
|
+
/**
|
|
818
|
+
* Publishes a Kind 7000 workflow notification to the customer.
|
|
819
|
+
*/
|
|
820
|
+
private publishWorkflowNotification;
|
|
821
|
+
/**
|
|
822
|
+
* Starts a timeout timer for the current step.
|
|
823
|
+
*/
|
|
824
|
+
private startStepTimeout;
|
|
825
|
+
/**
|
|
826
|
+
* Returns the secret key for signing step events.
|
|
827
|
+
* Falls back to a deterministic key derived from the node pubkey
|
|
828
|
+
* (for testing -- production should always pass secretKey in options).
|
|
829
|
+
*/
|
|
830
|
+
private getSecretKey;
|
|
831
|
+
/**
|
|
832
|
+
* Clears the current step timeout.
|
|
833
|
+
*/
|
|
834
|
+
private clearStepTimeout;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
/**
|
|
838
|
+
* Swarm Coordinator for competitive DVM bidding (Story 6.2).
|
|
839
|
+
*
|
|
840
|
+
* Manages the lifecycle of a competitive swarm: collects provider
|
|
841
|
+
* submissions, handles timeout-based judging deadlines, validates
|
|
842
|
+
* winner selection, and settles compute payment to the winner only.
|
|
843
|
+
*
|
|
844
|
+
* The coordinator uses the TOON relay as the orchestration layer --
|
|
845
|
+
* there is no separate swarm engine. Submission arrival is detected
|
|
846
|
+
* via relay event subscriptions (Kind 6xxx results).
|
|
847
|
+
*
|
|
848
|
+
* State machine states:
|
|
849
|
+
* - `collecting`: Waiting for provider submissions (Kind 6xxx results)
|
|
850
|
+
* - `judging`: Timeout or max submissions reached; customer selects winner
|
|
851
|
+
* - `settled`: Winner paid via settleCompute(); swarm complete
|
|
852
|
+
* - `failed`: No submissions within timeout or error
|
|
853
|
+
*
|
|
854
|
+
* Settlement: Only the winning provider receives compute payment.
|
|
855
|
+
* Losing providers paid relay write fees (sunk cost) but receive
|
|
856
|
+
* no compute payment -- this is by design to incentivize quality.
|
|
857
|
+
*
|
|
858
|
+
* Forward-compatible with Epic 7 prepaid protocol: settlement logic
|
|
859
|
+
* is isolated in selectWinner() so swapping to prepaid per-winner
|
|
860
|
+
* payment requires changes only in that method.
|
|
861
|
+
*/
|
|
862
|
+
|
|
863
|
+
/**
|
|
864
|
+
* Swarm state type.
|
|
865
|
+
* - `collecting`: Waiting for provider submissions.
|
|
866
|
+
* - `judging`: Timeout or max submissions reached; awaiting winner selection.
|
|
867
|
+
* - `settled`: Winner paid; swarm complete.
|
|
868
|
+
* - `failed`: No submissions within timeout or error.
|
|
869
|
+
*/
|
|
870
|
+
type SwarmState = 'collecting' | 'judging' | 'settled' | 'failed';
|
|
871
|
+
/**
|
|
872
|
+
* Configuration options for the SwarmCoordinator.
|
|
873
|
+
*/
|
|
874
|
+
interface SwarmCoordinatorOptions {
|
|
875
|
+
/** Secret key for signing events (32-byte Uint8Array). */
|
|
876
|
+
secretKey?: Uint8Array;
|
|
877
|
+
/** Swarm collection timeout in milliseconds (default: 600000 = 10 minutes). */
|
|
878
|
+
timeoutMs?: number;
|
|
879
|
+
/** Injectable time source for deterministic testing. */
|
|
880
|
+
now?: () => number;
|
|
881
|
+
/**
|
|
882
|
+
* Injectable timer factory for deterministic testing.
|
|
883
|
+
* Defaults to global setTimeout. Inject a custom implementation
|
|
884
|
+
* to control timer advancement in tests without vi.useFakeTimers().
|
|
885
|
+
*/
|
|
886
|
+
setTimer?: (callback: () => void, ms: number) => ReturnType<typeof setTimeout>;
|
|
887
|
+
/**
|
|
888
|
+
* Injectable timer cancellation for deterministic testing.
|
|
889
|
+
* Defaults to global clearTimeout. Must pair with setTimer.
|
|
890
|
+
*/
|
|
891
|
+
clearTimer?: (handle: ReturnType<typeof setTimeout>) => void;
|
|
892
|
+
/** Optional event store for swarm state persistence. */
|
|
893
|
+
eventStore?: WorkflowEventStore;
|
|
894
|
+
/** Default destination ILP address for publishing events. */
|
|
895
|
+
destination?: string;
|
|
896
|
+
}
|
|
897
|
+
/**
|
|
898
|
+
* Coordinates a competitive DVM swarm.
|
|
899
|
+
*
|
|
900
|
+
* Each instance manages a single swarm. For concurrent swarms,
|
|
901
|
+
* create multiple SwarmCoordinator instances sharing the same
|
|
902
|
+
* ServiceNode.
|
|
903
|
+
*/
|
|
904
|
+
declare class SwarmCoordinator {
|
|
905
|
+
private readonly node;
|
|
906
|
+
private readonly options;
|
|
907
|
+
private state;
|
|
908
|
+
private swarmRequestId;
|
|
909
|
+
private customerPubkey;
|
|
910
|
+
private maxProviders;
|
|
911
|
+
private submissions;
|
|
912
|
+
private timeoutHandle;
|
|
913
|
+
private started;
|
|
914
|
+
private settlementSucceeded;
|
|
915
|
+
private submissionIds;
|
|
916
|
+
constructor(node: ServiceNode, options?: SwarmCoordinatorOptions);
|
|
917
|
+
/**
|
|
918
|
+
* Returns the current swarm state.
|
|
919
|
+
*/
|
|
920
|
+
getState(): SwarmState;
|
|
921
|
+
/**
|
|
922
|
+
* Returns whether settlement was successfully completed.
|
|
923
|
+
* Only meaningful when state is 'settled' (returns true).
|
|
924
|
+
* If settlement fails, the state remains 'judging' and this returns false.
|
|
925
|
+
*/
|
|
926
|
+
isSettlementSucceeded(): boolean;
|
|
927
|
+
/**
|
|
928
|
+
* Returns the collected eligible submissions.
|
|
929
|
+
*/
|
|
930
|
+
getSubmissions(): readonly NostrEvent[];
|
|
931
|
+
/**
|
|
932
|
+
* Starts a swarm: parses the swarm request, initializes collection,
|
|
933
|
+
* and starts the timeout timer.
|
|
934
|
+
*/
|
|
935
|
+
startSwarm(swarmRequest: NostrEvent): Promise<void>;
|
|
936
|
+
/**
|
|
937
|
+
* Handles a Kind 6xxx result event (provider submission).
|
|
938
|
+
*
|
|
939
|
+
* Validates the `e` tag references the swarm request, adds to the
|
|
940
|
+
* submissions list, and checks if max providers is reached.
|
|
941
|
+
*
|
|
942
|
+
* Late submissions (after timeout or max reached) are ignored.
|
|
943
|
+
* Submissions before startSwarm() are silently ignored.
|
|
944
|
+
*/
|
|
945
|
+
handleSubmission(resultEvent: NostrEvent): Promise<void>;
|
|
946
|
+
/**
|
|
947
|
+
* Selects the winner and settles compute payment.
|
|
948
|
+
*
|
|
949
|
+
* Validates:
|
|
950
|
+
* - Swarm is in `judging` state (not `collecting`, `settled`, or `failed`)
|
|
951
|
+
* - Selection references a submission in the collected set
|
|
952
|
+
* - Swarm has not already been settled (idempotency guard)
|
|
953
|
+
*
|
|
954
|
+
* @throws ToonError with code DVM_SWARM_ALREADY_SETTLED if already settled
|
|
955
|
+
* @throws ToonError with code DVM_SWARM_INVALID_SELECTION if winner not in submissions
|
|
956
|
+
*/
|
|
957
|
+
selectWinner(selectionEvent: NostrEvent): Promise<void>;
|
|
958
|
+
/**
|
|
959
|
+
* Cleans up resources (timeout handles).
|
|
960
|
+
*/
|
|
961
|
+
destroy(): void;
|
|
962
|
+
/**
|
|
963
|
+
* Starts the collection timeout timer.
|
|
964
|
+
*/
|
|
965
|
+
private startTimeout;
|
|
966
|
+
/**
|
|
967
|
+
* Publishes a Kind 7000 feedback event indicating no submissions were received.
|
|
968
|
+
*/
|
|
969
|
+
private publishNoSubmissionsFeedback;
|
|
970
|
+
/**
|
|
971
|
+
* Clears the current timeout timer.
|
|
972
|
+
*/
|
|
973
|
+
private clearTimeout;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
/**
|
|
977
|
+
* Prefix claim handler for the TOON prefix marketplace.
|
|
978
|
+
*
|
|
979
|
+
* Creates a handler that processes kind 10034 prefix claim events,
|
|
980
|
+
* validates payment and prefix availability, and publishes grant
|
|
981
|
+
* confirmations. Lives in SDK (not core) because it depends on
|
|
982
|
+
* the SDK's Handler type and HandlerContext interface.
|
|
983
|
+
*/
|
|
984
|
+
|
|
985
|
+
/**
|
|
986
|
+
* Options for creating a prefix claim handler.
|
|
987
|
+
*/
|
|
988
|
+
interface PrefixClaimHandlerOptions {
|
|
989
|
+
/** Pricing configuration for prefix claims. */
|
|
990
|
+
prefixPricing: {
|
|
991
|
+
basePrice: bigint;
|
|
992
|
+
};
|
|
993
|
+
/** Secret key for signing grant events. */
|
|
994
|
+
secretKey: Uint8Array;
|
|
995
|
+
/** Returns the current map of claimed prefixes (prefix -> claimer pubkey). */
|
|
996
|
+
getClaimedPrefixes: () => Map<string, string>;
|
|
997
|
+
/**
|
|
998
|
+
* Atomically claim a prefix for a pubkey. Returns true if the claim
|
|
999
|
+
* succeeded, false if the prefix was already taken. This is the
|
|
1000
|
+
* serialization point for race condition defense.
|
|
1001
|
+
*/
|
|
1002
|
+
claimPrefix: (prefix: string, claimerPubkey: string) => boolean;
|
|
1003
|
+
/** Publish the grant event (e.g., to the local relay). */
|
|
1004
|
+
publishGrant: (grantEvent: NostrEvent) => Promise<void>;
|
|
1005
|
+
/** ILP address prefix to include in the grant event (default: 'g.toon'). */
|
|
1006
|
+
ilpAddressPrefix?: string;
|
|
1007
|
+
}
|
|
1008
|
+
/**
|
|
1009
|
+
* Creates a handler for kind 10034 prefix claim events.
|
|
1010
|
+
*
|
|
1011
|
+
* The handler validates payment, prefix availability, and prefix format,
|
|
1012
|
+
* then atomically claims the prefix and publishes a grant confirmation.
|
|
1013
|
+
*
|
|
1014
|
+
* @param options - Handler configuration
|
|
1015
|
+
* @returns A Handler function for kind 10034 events
|
|
1016
|
+
*/
|
|
1017
|
+
declare function createPrefixClaimHandler(options: PrefixClaimHandlerOptions): Handler;
|
|
1018
|
+
|
|
1019
|
+
/**
|
|
1020
|
+
* Arweave upload adapter wrapping @ardrive/turbo-sdk.
|
|
1021
|
+
*
|
|
1022
|
+
* This is the ONLY file that imports @ardrive/turbo-sdk, isolating the
|
|
1023
|
+
* external dependency behind an interface (risk E8-R002).
|
|
1024
|
+
*/
|
|
1025
|
+
/**
|
|
1026
|
+
* Interface for uploading data to Arweave.
|
|
1027
|
+
* Implementations wrap a specific Arweave upload SDK.
|
|
1028
|
+
*/
|
|
1029
|
+
interface ArweaveUploadAdapter {
|
|
1030
|
+
upload(data: Buffer, tags?: Record<string, string>): Promise<{
|
|
1031
|
+
txId: string;
|
|
1032
|
+
}>;
|
|
1033
|
+
}
|
|
1034
|
+
/**
|
|
1035
|
+
* Turbo SDK upload adapter using @ardrive/turbo-sdk.
|
|
1036
|
+
*
|
|
1037
|
+
* - Dev/free tier (<=100KB): pass no turboClient, uses TurboFactory.unauthenticated()
|
|
1038
|
+
* - Prod (paid, uncapped): pass a TurboAuthenticatedClient from TurboFactory.authenticated()
|
|
1039
|
+
*
|
|
1040
|
+
* The turboClient is typed as `unknown` to avoid importing @ardrive/turbo-sdk types
|
|
1041
|
+
* in this interface. The actual TurboAuthenticatedClient or TurboUnauthenticatedClient
|
|
1042
|
+
* is duck-typed at runtime.
|
|
1043
|
+
*/
|
|
1044
|
+
declare class TurboUploadAdapter implements ArweaveUploadAdapter {
|
|
1045
|
+
private turboClient;
|
|
1046
|
+
private initialized;
|
|
1047
|
+
constructor(turboClient?: unknown);
|
|
1048
|
+
private getClient;
|
|
1049
|
+
upload(data: Buffer, tags?: Record<string, string>): Promise<{
|
|
1050
|
+
txId: string;
|
|
1051
|
+
}>;
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
/**
|
|
1055
|
+
* Chunk state manager for multi-packet blob uploads.
|
|
1056
|
+
*
|
|
1057
|
+
* Accumulates chunks for a given uploadId, assembles them in order
|
|
1058
|
+
* when all chunks have arrived, and enforces timeout and memory caps.
|
|
1059
|
+
*/
|
|
1060
|
+
interface ChunkManagerConfig {
|
|
1061
|
+
/** Timeout in milliseconds before partial uploads are discarded (default: 300_000 = 5 min). */
|
|
1062
|
+
timeoutMs?: number;
|
|
1063
|
+
/** Maximum number of concurrent active uploads (default: 100). */
|
|
1064
|
+
maxActiveUploads?: number;
|
|
1065
|
+
/** Maximum total bytes accumulated per upload before rejection (default: 50MB). */
|
|
1066
|
+
maxBytesPerUpload?: number;
|
|
1067
|
+
}
|
|
1068
|
+
interface AddChunkResult {
|
|
1069
|
+
/** Whether all chunks have been received and the blob is fully assembled. */
|
|
1070
|
+
complete: boolean;
|
|
1071
|
+
/** The assembled blob (only present when complete is true). */
|
|
1072
|
+
assembled?: Buffer;
|
|
1073
|
+
/** Error message if the chunk was rejected. */
|
|
1074
|
+
error?: string;
|
|
1075
|
+
}
|
|
1076
|
+
/**
|
|
1077
|
+
* Manages chunked upload state for the Arweave DVM handler.
|
|
1078
|
+
*/
|
|
1079
|
+
declare class ChunkManager {
|
|
1080
|
+
private uploads;
|
|
1081
|
+
private readonly timeoutMs;
|
|
1082
|
+
private readonly maxActiveUploads;
|
|
1083
|
+
private readonly maxBytesPerUpload;
|
|
1084
|
+
constructor(config?: ChunkManagerConfig);
|
|
1085
|
+
/**
|
|
1086
|
+
* Add a chunk for a given uploadId.
|
|
1087
|
+
*
|
|
1088
|
+
* @param uploadId - Unique identifier for the upload session.
|
|
1089
|
+
* @param chunkIndex - Zero-based index of this chunk.
|
|
1090
|
+
* @param totalChunks - Total number of chunks expected.
|
|
1091
|
+
* @param data - The chunk data.
|
|
1092
|
+
* @returns Result indicating completion status or error.
|
|
1093
|
+
* @throws Error if memory cap reached or duplicate chunk.
|
|
1094
|
+
*/
|
|
1095
|
+
addChunk(uploadId: string, chunkIndex: number, totalChunks: number, data: Buffer): AddChunkResult;
|
|
1096
|
+
/**
|
|
1097
|
+
* Check if an upload is complete (all chunks received).
|
|
1098
|
+
* Returns false if the uploadId is unknown (cleaned up or never started).
|
|
1099
|
+
*/
|
|
1100
|
+
isComplete(uploadId: string): boolean;
|
|
1101
|
+
/**
|
|
1102
|
+
* Clean up state for a given uploadId, clearing the timeout timer.
|
|
1103
|
+
*/
|
|
1104
|
+
cleanup(uploadId: string): void;
|
|
1105
|
+
/**
|
|
1106
|
+
* Clean up all active uploads and their timers.
|
|
1107
|
+
* Call this on node shutdown to prevent timer leaks.
|
|
1108
|
+
*/
|
|
1109
|
+
destroyAll(): void;
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
/**
|
|
1113
|
+
* Arweave DVM handler for kind:5094 blob storage requests.
|
|
1114
|
+
*
|
|
1115
|
+
* Creates a handler function that:
|
|
1116
|
+
* 1. Parses the kind:5094 event from the HandlerContext
|
|
1117
|
+
* 2. For single-packet uploads: uploads directly to Arweave via the adapter
|
|
1118
|
+
* 3. For chunked uploads: accumulates via ChunkManager, uploads on completion
|
|
1119
|
+
*
|
|
1120
|
+
* The handler does NOT validate pricing -- the SDK pricing validator
|
|
1121
|
+
* (packages/sdk/src/pricing-validator.ts) runs BEFORE the handler is invoked.
|
|
1122
|
+
*
|
|
1123
|
+
* Returns HandlePacketAcceptResponse with `data` field containing the Arweave
|
|
1124
|
+
* tx ID -- NOT via ctx.accept() which only supports metadata.
|
|
1125
|
+
*/
|
|
1126
|
+
|
|
1127
|
+
interface ArweaveDvmConfig {
|
|
1128
|
+
/** Arweave upload adapter (wraps @ardrive/turbo-sdk). */
|
|
1129
|
+
turboAdapter: ArweaveUploadAdapter;
|
|
1130
|
+
/** Chunk state manager for multi-packet uploads. */
|
|
1131
|
+
chunkManager: ChunkManager;
|
|
1132
|
+
/** Optional default Arweave data item tags (e.g., Content-Type). */
|
|
1133
|
+
arweaveTags?: Record<string, string>;
|
|
1134
|
+
}
|
|
1135
|
+
/**
|
|
1136
|
+
* Creates an Arweave DVM handler for kind:5094 blob storage requests.
|
|
1137
|
+
*
|
|
1138
|
+
* @param config - Handler configuration with adapter and chunk manager.
|
|
1139
|
+
* @returns A handler function compatible with HandlerRegistry.on().
|
|
1140
|
+
*/
|
|
1141
|
+
declare function createArweaveDvmHandler(config: ArweaveDvmConfig): (ctx: HandlerContext) => Promise<HandlerResponse>;
|
|
1142
|
+
|
|
1143
|
+
/**
|
|
1144
|
+
* Client-side helpers for uploading blobs to an Arweave DVM provider.
|
|
1145
|
+
*
|
|
1146
|
+
* - uploadBlob(): single-packet upload for blobs under the chunk threshold
|
|
1147
|
+
* - uploadBlobChunked(): multi-packet upload that splits large blobs into chunks
|
|
1148
|
+
*
|
|
1149
|
+
* Both use publishEvent() with the amount override (Story 7.6, D7-007).
|
|
1150
|
+
*/
|
|
1151
|
+
|
|
1152
|
+
/**
|
|
1153
|
+
* Minimal interface for publishing events. Matches ServiceNode.publishEvent().
|
|
1154
|
+
*/
|
|
1155
|
+
interface PublishableNode {
|
|
1156
|
+
publishEvent(event: NostrEvent, options?: {
|
|
1157
|
+
destination: string;
|
|
1158
|
+
amount?: bigint;
|
|
1159
|
+
}): Promise<Pick<PublishEventResult, 'success' | 'eventId' | 'data' | 'message'>>;
|
|
1160
|
+
}
|
|
1161
|
+
/**
|
|
1162
|
+
* Options for single-packet blob upload.
|
|
1163
|
+
*/
|
|
1164
|
+
interface UploadBlobOptions {
|
|
1165
|
+
/** MIME type of the blob (default: 'application/octet-stream'). */
|
|
1166
|
+
contentType?: string;
|
|
1167
|
+
/** Secret key for signing the event. */
|
|
1168
|
+
secretKey: Uint8Array;
|
|
1169
|
+
/** Price per byte in USDC micro-units for amount calculation. */
|
|
1170
|
+
pricePerByte?: bigint;
|
|
1171
|
+
}
|
|
1172
|
+
/**
|
|
1173
|
+
* Options for chunked blob upload.
|
|
1174
|
+
*/
|
|
1175
|
+
interface UploadBlobChunkedOptions {
|
|
1176
|
+
/** Chunk size in bytes (default: 500_000, under 512KB threshold). */
|
|
1177
|
+
chunkSize?: number;
|
|
1178
|
+
/** MIME type of the blob (default: 'application/octet-stream'). */
|
|
1179
|
+
contentType?: string;
|
|
1180
|
+
/** Secret key for signing events. */
|
|
1181
|
+
secretKey: Uint8Array;
|
|
1182
|
+
/** Price per byte in USDC micro-units for amount calculation. */
|
|
1183
|
+
pricePerByte?: bigint;
|
|
1184
|
+
}
|
|
1185
|
+
/**
|
|
1186
|
+
* Upload a blob to an Arweave DVM provider in a single ILP packet.
|
|
1187
|
+
*
|
|
1188
|
+
* Uses publishEvent() with amount override (D7-007) to send the blob
|
|
1189
|
+
* and payment in one ILP PREPARE.
|
|
1190
|
+
*
|
|
1191
|
+
* @param node - The ServiceNode (or compatible) to publish through.
|
|
1192
|
+
* @param blob - The raw blob data to upload.
|
|
1193
|
+
* @param destination - The provider's ILP address.
|
|
1194
|
+
* @param options - Upload options including secretKey for signing.
|
|
1195
|
+
* @returns The Arweave transaction ID from the FULFILL data field.
|
|
1196
|
+
*/
|
|
1197
|
+
declare function uploadBlob(node: PublishableNode, blob: Buffer, destination: string, options: UploadBlobOptions): Promise<string>;
|
|
1198
|
+
/**
|
|
1199
|
+
* Upload a large blob to an Arweave DVM provider using chunked uploads.
|
|
1200
|
+
*
|
|
1201
|
+
* Splits the blob into chunks, each sent as a separate kind:5094 ILP PREPARE
|
|
1202
|
+
* with uploadId, chunkIndex, and totalChunks params. Each chunk carries its
|
|
1203
|
+
* own payment. The final chunk's FULFILL data contains the Arweave tx ID.
|
|
1204
|
+
*
|
|
1205
|
+
* @param node - The ServiceNode (or compatible) to publish through.
|
|
1206
|
+
* @param blob - The raw blob data to upload.
|
|
1207
|
+
* @param destination - The provider's ILP address.
|
|
1208
|
+
* @param options - Chunked upload options including secretKey for signing.
|
|
1209
|
+
* @returns The Arweave transaction ID from the final chunk's FULFILL data.
|
|
1210
|
+
*/
|
|
1211
|
+
declare function uploadBlobChunked(node: PublishableNode, blob: Buffer, destination: string, options: UploadBlobChunkedOptions): Promise<string>;
|
|
1212
|
+
|
|
1213
|
+
export { type AddChunkResult, type ArweaveDvmConfig, type ArweaveUploadAdapter, type BuildSkillDescriptorConfig, ChunkManager, type ChunkManagerConfig, type CreateHandlerContextOptions, type FromMnemonicOptions, type Handler, type HandlerContext, HandlerError, HandlerRegistry, type HandlerResponse, IdentityError, type NodeConfig, NodeError, type NodeIdentity, type PaymentHandlerBridgeConfig, type PaymentRequest, type PaymentResponse, type PrefixClaimHandlerOptions, PricingError, type PricingValidationResult, type PricingValidatorConfig, type PublishEventResult, type PublishableNode, type ServiceNode, type StartResult, SwarmCoordinator, type SwarmCoordinatorOptions, type SwarmState, TurboUploadAdapter, type UploadBlobChunkedOptions, type UploadBlobOptions, VerificationError, type VerificationPipelineConfig, type VerificationResult, type WorkflowEventStore, WorkflowOrchestrator, type WorkflowOrchestratorOptions, type WorkflowState, buildSkillDescriptor, createArweaveDvmHandler, createEventStorageHandler, createHandlerContext, createNode, createPaymentHandlerBridge, createPrefixClaimHandler, createPricingValidator, createVerificationPipeline, fromMnemonic, fromSecretKey, generateMnemonic, uploadBlob, uploadBlobChunked };
|