@toon-protocol/sdk 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -19
- package/dist/chunk-XTHUXP63.js +1637 -0
- package/dist/chunk-XTHUXP63.js.map +1 -0
- package/dist/index.d.ts +1951 -0
- package/dist/index.js +1185 -301
- package/dist/index.js.map +1 -1
- package/dist/swap-D4Ozr_BM.d.ts +484 -0
- package/dist/swap.d.ts +3 -0
- package/dist/swap.js +14 -0
- package/dist/swap.js.map +1 -0
- package/package.json +23 -18
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1951 @@
|
|
|
1
|
+
import { ToonError, HandlePacketAcceptResponse, HandlePacketRejectResponse, ReputationScore, SkillDescriptor, EmbeddableConnectorLike, KnownPeer, SettlementConfig, ChainProviderConfigEntry, ConnectorChannelClient, BootstrapEventListener, BootstrapResult, DvmJobStatus, IlpSendResult, ParsedWorkflowDefinition, SwapPair } from '@toon-protocol/core';
|
|
2
|
+
export { BootstrapEvent, BootstrapEventListener, HandlePacketAcceptResponse, HandlePacketRejectResponse, SkillDescriptor, balanceProofFieldsMina, balanceProofHashEvm, balanceProofHashSolana, bigintToBytes32BE, concatBytes, hexToBytes, minaHashToField } from '@toon-protocol/core';
|
|
3
|
+
import { NostrEvent, UnsignedEvent } from 'nostr-tools/pure';
|
|
4
|
+
import { ToonRoutingMeta } from '@toon-protocol/core/toon';
|
|
5
|
+
import { TransportConfig } from '@toon-protocol/connector';
|
|
6
|
+
export { TransportConfig } from '@toon-protocol/connector';
|
|
7
|
+
import { A as AccumulatedClaim } from './swap-D4Ozr_BM.js';
|
|
8
|
+
export { D as DecryptFulfillClaimParams, E as EncryptFulfillClaimParams, a as EncryptFulfillClaimResult, P as PacketProgress, R as RateMonitorCallback, S as StreamSwapController, b as StreamSwapParams, c as StreamSwapResult, U as UnwrapSwapPacketFromToonParams, d as UnwrapSwapPacketParams, e as UnwrapSwapPacketResult, W as WrapSwapPacketParams, f as WrapSwapPacketResult, g as WrapSwapPacketToToonParams, h as WrapSwapPacketToToonResult, _ as __streamSwapTesting, i as decryptFulfillClaim, j as encryptFulfillClaim, s as streamSwap, k as streamSwapControlled, u as unwrapSwapPacket, l as unwrapSwapPacketFromToon, w as wrapSwapPacket, m as wrapSwapPacketToToon } from './swap-D4Ozr_BM.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Unified identity module for @toon-protocol/sdk.
|
|
12
|
+
*
|
|
13
|
+
* Derives both a Nostr pubkey (x-only Schnorr, BIP-340) and an EVM address
|
|
14
|
+
* (Keccak-256) from a single secp256k1 private key, following the NIP-06
|
|
15
|
+
* derivation standard.
|
|
16
|
+
*
|
|
17
|
+
* Both Nostr and EVM use the secp256k1 elliptic curve, so a single 12-word
|
|
18
|
+
* seed phrase can recover the complete identity across both layers.
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Represents a node's complete identity: secret key, Nostr pubkey, and EVM address.
|
|
22
|
+
*/
|
|
23
|
+
interface NodeIdentity {
|
|
24
|
+
/** The 32-byte secp256k1 secret key. */
|
|
25
|
+
secretKey: Uint8Array;
|
|
26
|
+
/** The x-only Schnorr public key (32 bytes, 64 lowercase hex characters). */
|
|
27
|
+
pubkey: string;
|
|
28
|
+
/** The EIP-55 checksummed EVM address (0x-prefixed, 42 characters). */
|
|
29
|
+
evmAddress: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Solana Ed25519 identity derived via SLIP-0010 from a BIP-39 mnemonic.
|
|
33
|
+
*/
|
|
34
|
+
interface SolanaIdentity {
|
|
35
|
+
/** 64-byte Ed25519 keypair (32-byte private key + 32-byte public key). */
|
|
36
|
+
secretKey: Uint8Array;
|
|
37
|
+
/** Base58-encoded Ed25519 public key (Solana address). */
|
|
38
|
+
publicKey: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Mina Pallas identity derived from a BIP-39 mnemonic via mina-signer.
|
|
42
|
+
*/
|
|
43
|
+
interface MinaIdentity {
|
|
44
|
+
/** Hex-encoded Pallas private key. */
|
|
45
|
+
privateKey: string;
|
|
46
|
+
/** Base58 Mina public key (B62 prefix). */
|
|
47
|
+
publicKey: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Full multi-chain identity derived from a single BIP-39 mnemonic.
|
|
51
|
+
* Extends NodeIdentity (Nostr + EVM) with Solana and optionally Mina.
|
|
52
|
+
*/
|
|
53
|
+
interface ToonIdentity extends NodeIdentity {
|
|
54
|
+
/** Solana Ed25519 identity (always populated from mnemonic derivation). */
|
|
55
|
+
solana: SolanaIdentity;
|
|
56
|
+
/** Mina Pallas identity (undefined when mina-signer is not installed). */
|
|
57
|
+
mina?: MinaIdentity;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Options for mnemonic-based key derivation.
|
|
61
|
+
*/
|
|
62
|
+
interface FromMnemonicOptions {
|
|
63
|
+
/** Key index in the NIP-06 derivation path. Defaults to 0. */
|
|
64
|
+
accountIndex?: number;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Generates a valid 12-word BIP-39 mnemonic using 128-bit entropy.
|
|
68
|
+
*
|
|
69
|
+
* @returns A space-separated string of 12 BIP-39 English words.
|
|
70
|
+
*/
|
|
71
|
+
declare function generateMnemonic(): string;
|
|
72
|
+
/**
|
|
73
|
+
* Derives a complete NodeIdentity from a BIP-39 mnemonic phrase.
|
|
74
|
+
*
|
|
75
|
+
* Uses the NIP-06 derivation path: m/44'/1237'/0'/0/{accountIndex}
|
|
76
|
+
*
|
|
77
|
+
* @param mnemonic - A valid BIP-39 mnemonic (12 or 24 words).
|
|
78
|
+
* @param options - Optional derivation options (accountIndex defaults to 0).
|
|
79
|
+
* @returns The derived NodeIdentity with secretKey, pubkey, and evmAddress.
|
|
80
|
+
* @throws {IdentityError} If the mnemonic is invalid.
|
|
81
|
+
*/
|
|
82
|
+
declare function fromMnemonic(mnemonic: string, options?: FromMnemonicOptions): ToonIdentity;
|
|
83
|
+
/**
|
|
84
|
+
* Derives a complete NodeIdentity from an existing 32-byte secret key.
|
|
85
|
+
*
|
|
86
|
+
* @param secretKey - A 32-byte secp256k1 secret key.
|
|
87
|
+
* @returns The derived NodeIdentity with secretKey, pubkey, and evmAddress.
|
|
88
|
+
* @throws {IdentityError} If the secret key is not exactly 32 bytes.
|
|
89
|
+
*/
|
|
90
|
+
declare function fromSecretKey(secretKey: Uint8Array): NodeIdentity;
|
|
91
|
+
/**
|
|
92
|
+
* Derives a full multi-chain ToonIdentity from a BIP-39 mnemonic,
|
|
93
|
+
* including async Mina derivation (requires mina-signer).
|
|
94
|
+
*
|
|
95
|
+
* Chains derived:
|
|
96
|
+
* - Nostr (secp256k1): m/44'/1237'/0'/0/{accountIndex}
|
|
97
|
+
* - EVM (secp256k1): same key as Nostr, Keccak-256 for address
|
|
98
|
+
* - Solana (Ed25519): m/44'/501'/{accountIndex}'/0' (SLIP-0010)
|
|
99
|
+
* - Mina (Pallas): m/44'/12586'/{accountIndex}'/0/0 (optional, requires mina-signer)
|
|
100
|
+
*
|
|
101
|
+
* All four chains vary by `accountIndex`, so distinct indices yield fully
|
|
102
|
+
* distinct multi-chain identities from one seed. Index 0 is unchanged from the
|
|
103
|
+
* historical fixed paths.
|
|
104
|
+
*
|
|
105
|
+
* @param mnemonic - A valid BIP-39 mnemonic (12 or 24 words).
|
|
106
|
+
* @param options - Optional derivation options (accountIndex defaults to 0).
|
|
107
|
+
* @returns The derived ToonIdentity with all chain identities populated.
|
|
108
|
+
* @throws {IdentityError} If the mnemonic is invalid.
|
|
109
|
+
*/
|
|
110
|
+
declare function fromMnemonicFull(mnemonic: string, options?: FromMnemonicOptions): Promise<ToonIdentity>;
|
|
111
|
+
/**
|
|
112
|
+
* Generates a random Solana Ed25519 keypair (non-deterministic).
|
|
113
|
+
*
|
|
114
|
+
* For deterministic derivation from a mnemonic, use fromMnemonic() instead.
|
|
115
|
+
*
|
|
116
|
+
* @returns A SolanaIdentity with random keypair.
|
|
117
|
+
*/
|
|
118
|
+
declare function generateSolanaKeypair(): SolanaIdentity;
|
|
119
|
+
/**
|
|
120
|
+
* Encodes a byte array to a Base58 string (Bitcoin/Solana alphabet).
|
|
121
|
+
*/
|
|
122
|
+
declare function base58Encode(bytes: Uint8Array): string;
|
|
123
|
+
/**
|
|
124
|
+
* Decodes a Base58 string to a byte array (Bitcoin/Solana alphabet).
|
|
125
|
+
*/
|
|
126
|
+
declare function base58Decode(str: string): Uint8Array;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* SDK-specific error classes for @toon-protocol/sdk.
|
|
130
|
+
* All errors extend ToonError from @toon-protocol/core for a consistent error hierarchy.
|
|
131
|
+
*/
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Error thrown when identity operations fail.
|
|
135
|
+
* Used for invalid mnemonics, invalid secret keys, and key derivation failures.
|
|
136
|
+
*/
|
|
137
|
+
declare class IdentityError extends ToonError {
|
|
138
|
+
constructor(message: string, cause?: Error);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Error thrown when node lifecycle operations fail.
|
|
142
|
+
* Used for start/stop failures, configuration errors, etc.
|
|
143
|
+
*/
|
|
144
|
+
declare class NodeError extends ToonError {
|
|
145
|
+
constructor(message: string, cause?: Error);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Error thrown when handler dispatch operations fail.
|
|
149
|
+
* Used for handler registration conflicts, missing handlers, and dispatch errors.
|
|
150
|
+
*/
|
|
151
|
+
declare class HandlerError extends ToonError {
|
|
152
|
+
constructor(message: string, cause?: Error);
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Error thrown when Schnorr signature verification fails.
|
|
156
|
+
* Used for invalid signatures, malformed events, and verification pipeline errors.
|
|
157
|
+
*/
|
|
158
|
+
declare class VerificationError extends ToonError {
|
|
159
|
+
constructor(message: string, cause?: Error);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Error thrown when payment validation fails.
|
|
163
|
+
* Used for pricing calculation errors, insufficient payment, and pricing policy violations.
|
|
164
|
+
*/
|
|
165
|
+
declare class PricingError extends ToonError {
|
|
166
|
+
constructor(message: string, cause?: Error);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Error thrown when NIP-59 gift wrap or NIP-44 FULFILL encryption operations fail.
|
|
170
|
+
* Used for wrap/unwrap failures, decryption errors, and malformed gift wrap events.
|
|
171
|
+
*/
|
|
172
|
+
declare class GiftWrapError extends ToonError {
|
|
173
|
+
constructor(message: string, cause?: Error);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Error thrown when Mill swap handler orchestration fails.
|
|
177
|
+
* Used for rate-conversion errors (invalid format, zero, overflow guards),
|
|
178
|
+
* unsupported pair lookups, and issuer-boundary failures that are NOT
|
|
179
|
+
* gift-wrap-specific. Gift-wrap failures continue to surface as `GiftWrapError`.
|
|
180
|
+
*/
|
|
181
|
+
declare class SwapHandlerError extends ToonError {
|
|
182
|
+
constructor(message: string, cause?: Error);
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Error thrown by the sender-side `streamSwap()` API (Story 12.5).
|
|
186
|
+
*
|
|
187
|
+
* All failures are categorized by a narrow `code` so callers can branch on
|
|
188
|
+
* cause. `INVALID_*` codes are construction-time validation failures (thrown
|
|
189
|
+
* synchronously before any packet fires). `FULFILL_DECODE_FAILED` surfaces
|
|
190
|
+
* when the Mill returns `accepted: true` but the FULFILL data cannot be
|
|
191
|
+
* decoded — this is a non-fatal per-packet error and is captured in
|
|
192
|
+
* `StreamSwapResult.errors[]`.
|
|
193
|
+
*/
|
|
194
|
+
declare class StreamSwapError extends Error {
|
|
195
|
+
readonly code: 'INVALID_AMOUNT' | 'INVALID_CHUNKING' | 'INVALID_PAIR' | 'INVALID_STATE' | 'INVALID_CHAIN_RECIPIENT' | 'FULFILL_DECODE_FAILED';
|
|
196
|
+
readonly cause?: unknown;
|
|
197
|
+
constructor(code: StreamSwapError['code'], message: string, options?: {
|
|
198
|
+
cause?: unknown;
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Error thrown by the sender-side `buildSettlementTx()` helper (Story 12.6).
|
|
203
|
+
*
|
|
204
|
+
* Settlement is a post-swap one-shot computation, so this error class is
|
|
205
|
+
* THROWN synchronously (unlike `streamSwap` which routes per-packet failures
|
|
206
|
+
* through `StreamSwapResult`). Callers are expected to wrap the call in
|
|
207
|
+
* `try/catch`.
|
|
208
|
+
*
|
|
209
|
+
* Narrow `code` union lets callers branch on cause — see
|
|
210
|
+
* `_bmad-output/implementation-artifacts/12-6-build-settlement-tx.md` AC-11
|
|
211
|
+
* for the per-code semantics.
|
|
212
|
+
*
|
|
213
|
+
* @since 12.6
|
|
214
|
+
* @stable — Epic 13 Chain Bridge DVM depends on this error shape.
|
|
215
|
+
*/
|
|
216
|
+
declare class SettlementTxError extends Error {
|
|
217
|
+
readonly code: 'INVALID_INPUT' | 'MISSING_SETTLEMENT_METADATA' | 'UNSUPPORTED_CHAIN' | 'MISSING_RECIPIENT' | 'RECIPIENT_MISMATCH' | 'MILL_SIGNER_MISMATCH' | 'DUPLICATE_NONCE' | 'NON_MONOTONIC_CUMULATIVE' | 'INVALID_SIGNATURE_LENGTH' | 'INVALID_SIGNATURE_V' | 'ENCODING_FAILED';
|
|
218
|
+
readonly cause?: unknown;
|
|
219
|
+
constructor(code: SettlementTxError['code'], message: string, options?: {
|
|
220
|
+
cause?: unknown;
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Handler context for @toon-protocol/sdk.
|
|
226
|
+
*
|
|
227
|
+
* Provides a context object passed to kind-based handlers with methods
|
|
228
|
+
* for accessing TOON data, shallow-parsed metadata, and accept/reject actions.
|
|
229
|
+
*/
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* The handler context passed to each kind-based handler.
|
|
233
|
+
*/
|
|
234
|
+
interface HandlerContext {
|
|
235
|
+
/** Raw TOON string (base64-encoded). */
|
|
236
|
+
readonly toon: string;
|
|
237
|
+
/** Event kind from shallow parse. */
|
|
238
|
+
readonly kind: number;
|
|
239
|
+
/** Event pubkey from shallow parse. */
|
|
240
|
+
readonly pubkey: string;
|
|
241
|
+
/** Payment amount in the ILP packet. */
|
|
242
|
+
readonly amount: bigint;
|
|
243
|
+
/** ILP destination address. */
|
|
244
|
+
readonly destination: string;
|
|
245
|
+
/** Lazy-decode the TOON payload into a full NostrEvent. */
|
|
246
|
+
decode(): NostrEvent;
|
|
247
|
+
/** Accept the packet with optional metadata. */
|
|
248
|
+
accept(metadata?: Record<string, unknown>): HandlePacketAcceptResponse;
|
|
249
|
+
/** Reject the packet with an ILP error code and message. */
|
|
250
|
+
reject(code: string, message: string): HandlePacketRejectResponse;
|
|
251
|
+
}
|
|
252
|
+
interface CreateHandlerContextOptions {
|
|
253
|
+
toon: string;
|
|
254
|
+
meta: ToonRoutingMeta;
|
|
255
|
+
amount: bigint;
|
|
256
|
+
destination: string;
|
|
257
|
+
toonDecoder: (toon: string) => NostrEvent;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Creates a HandlerContext from the given options.
|
|
261
|
+
*/
|
|
262
|
+
declare function createHandlerContext(options: CreateHandlerContextOptions): HandlerContext;
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Handler registry for @toon-protocol/sdk.
|
|
266
|
+
*
|
|
267
|
+
* Maps event kinds to handler functions for dispatching incoming ILP packets.
|
|
268
|
+
*/
|
|
269
|
+
|
|
270
|
+
type HandlerResponse = HandlePacketAcceptResponse | HandlePacketRejectResponse;
|
|
271
|
+
type Handler = (ctx: HandlerContext) => Promise<HandlerResponse>;
|
|
272
|
+
/**
|
|
273
|
+
* Registry that maps Nostr event kinds to handler functions.
|
|
274
|
+
*/
|
|
275
|
+
declare class HandlerRegistry {
|
|
276
|
+
private handlers;
|
|
277
|
+
private defaultHandler;
|
|
278
|
+
/**
|
|
279
|
+
* Register a handler for a specific event kind.
|
|
280
|
+
* Replaces any existing handler for that kind.
|
|
281
|
+
*/
|
|
282
|
+
on(kind: number, handler: Handler): this;
|
|
283
|
+
/**
|
|
284
|
+
* Register a default handler for unrecognized kinds.
|
|
285
|
+
*/
|
|
286
|
+
onDefault(handler: Handler): this;
|
|
287
|
+
/**
|
|
288
|
+
* Returns all registered kind numbers, sorted ascending.
|
|
289
|
+
*/
|
|
290
|
+
getRegisteredKinds(): number[];
|
|
291
|
+
/**
|
|
292
|
+
* Returns the handler registered for `kind`, or `undefined` if none.
|
|
293
|
+
* Added for Story 12.7 AC-10 (handler-registration verification).
|
|
294
|
+
*/
|
|
295
|
+
get(kind: number): Handler | undefined;
|
|
296
|
+
/**
|
|
297
|
+
* Returns registered kinds in the DVM request range (5000-5999), sorted ascending.
|
|
298
|
+
* Uses JOB_REQUEST_KIND_BASE (5000) as the range start.
|
|
299
|
+
*/
|
|
300
|
+
getDvmKinds(): number[];
|
|
301
|
+
/**
|
|
302
|
+
* Dispatch a context to the appropriate handler based on kind.
|
|
303
|
+
*/
|
|
304
|
+
dispatch(ctx: HandlerContext): Promise<HandlerResponse>;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Pricing validator for @toon-protocol/sdk.
|
|
309
|
+
*
|
|
310
|
+
* Validates that incoming ILP payments meet the required price based on
|
|
311
|
+
* TOON payload size and configured price per byte.
|
|
312
|
+
*/
|
|
313
|
+
|
|
314
|
+
interface PricingValidatorConfig {
|
|
315
|
+
basePricePerByte?: bigint;
|
|
316
|
+
ownPubkey: string;
|
|
317
|
+
kindPricing?: Record<number, bigint>;
|
|
318
|
+
}
|
|
319
|
+
interface PricingValidationResult {
|
|
320
|
+
accepted: boolean;
|
|
321
|
+
rejection?: {
|
|
322
|
+
accept: false;
|
|
323
|
+
code: string;
|
|
324
|
+
message: string;
|
|
325
|
+
metadata?: Record<string, string>;
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Creates a pricing validator that checks payment amounts against TOON size.
|
|
330
|
+
*/
|
|
331
|
+
declare function createPricingValidator(config: PricingValidatorConfig): {
|
|
332
|
+
validate(meta: ToonRoutingMeta, amount: bigint): PricingValidationResult;
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Verification pipeline for @toon-protocol/sdk.
|
|
337
|
+
*
|
|
338
|
+
* Verifies Schnorr signatures on incoming TOON payloads before dispatching
|
|
339
|
+
* to handlers. In dev mode, verification is skipped.
|
|
340
|
+
*/
|
|
341
|
+
|
|
342
|
+
interface VerificationResult {
|
|
343
|
+
verified: boolean;
|
|
344
|
+
rejection?: {
|
|
345
|
+
accept: false;
|
|
346
|
+
code: string;
|
|
347
|
+
message: string;
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
interface VerificationPipelineConfig {
|
|
351
|
+
devMode: boolean;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Creates a verification pipeline that checks Schnorr signatures.
|
|
355
|
+
*/
|
|
356
|
+
declare function createVerificationPipeline(config: VerificationPipelineConfig): {
|
|
357
|
+
verify(meta: ToonRoutingMeta, _toonData: string): Promise<VerificationResult>;
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Payment handler bridge for @toon-protocol/sdk.
|
|
362
|
+
*
|
|
363
|
+
* Bridges between ILP packet handling and the handler registry,
|
|
364
|
+
* using isTransit to distinguish fire-and-forget from await semantics.
|
|
365
|
+
*/
|
|
366
|
+
|
|
367
|
+
interface PaymentHandlerBridgeConfig {
|
|
368
|
+
registry: HandlerRegistry;
|
|
369
|
+
devMode: boolean;
|
|
370
|
+
ownPubkey: string;
|
|
371
|
+
basePricePerByte: bigint;
|
|
372
|
+
}
|
|
373
|
+
interface PaymentRequest {
|
|
374
|
+
paymentId: string;
|
|
375
|
+
destination: string;
|
|
376
|
+
amount: string;
|
|
377
|
+
data: string;
|
|
378
|
+
isTransit: boolean;
|
|
379
|
+
}
|
|
380
|
+
interface PaymentResponse {
|
|
381
|
+
accept: boolean;
|
|
382
|
+
code?: string;
|
|
383
|
+
message?: string;
|
|
384
|
+
data?: string;
|
|
385
|
+
metadata?: Record<string, unknown>;
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Creates a payment handler bridge that connects ILP packets to the handler registry.
|
|
389
|
+
*/
|
|
390
|
+
declare function createPaymentHandlerBridge(config: PaymentHandlerBridgeConfig): {
|
|
391
|
+
handlePayment(request: PaymentRequest): Promise<PaymentResponse>;
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Event storage handler stub for @toon-protocol/sdk.
|
|
396
|
+
*
|
|
397
|
+
* This is a stub that throws. The real implementation lives in
|
|
398
|
+
* `@toon-protocol/town` -- see `createEventStorageHandler` from that package.
|
|
399
|
+
*
|
|
400
|
+
* The SDK is the framework; Town is the relay implementation. SDK consumers
|
|
401
|
+
* building relay functionality should use `@toon-protocol/town` directly.
|
|
402
|
+
*/
|
|
403
|
+
/**
|
|
404
|
+
* Creates an event storage handler.
|
|
405
|
+
*
|
|
406
|
+
* **Stub** -- throws "not yet implemented". See `@toon-protocol/town` for the
|
|
407
|
+
* real relay implementation of this handler.
|
|
408
|
+
*
|
|
409
|
+
* @see {@link https://github.com/ALLiDoizCode/toon/tree/main/packages/town | @toon-protocol/town}
|
|
410
|
+
*/
|
|
411
|
+
declare function createEventStorageHandler(_config: unknown): unknown;
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Skill descriptor builder for DVM service discovery.
|
|
415
|
+
*
|
|
416
|
+
* Computes a SkillDescriptor from the handler registry and node configuration.
|
|
417
|
+
* The descriptor is embedded in kind:10035 events to advertise DVM capabilities.
|
|
418
|
+
*
|
|
419
|
+
* Returns `undefined` when no DVM handlers are registered (backward compatible
|
|
420
|
+
* with pre-DVM kind:10035 events).
|
|
421
|
+
*/
|
|
422
|
+
|
|
423
|
+
/** Configuration for building a skill descriptor. */
|
|
424
|
+
interface BuildSkillDescriptorConfig {
|
|
425
|
+
/** Base price per byte in USDC micro-units (default: 10n). */
|
|
426
|
+
basePricePerByte?: bigint;
|
|
427
|
+
/** Per-kind pricing overrides (kind number -> price in USDC micro-units). */
|
|
428
|
+
kindPricing?: Record<number, bigint>;
|
|
429
|
+
/** Service name override (default: 'toon-dvm'). */
|
|
430
|
+
name?: string;
|
|
431
|
+
/** Schema version override (default: '1.0'). */
|
|
432
|
+
version?: string;
|
|
433
|
+
/** Feature list override. */
|
|
434
|
+
features?: string[];
|
|
435
|
+
/** JSON Schema draft-07 object for job request parameters. */
|
|
436
|
+
inputSchema?: Record<string, unknown>;
|
|
437
|
+
/** Available AI models. */
|
|
438
|
+
models?: string[];
|
|
439
|
+
/** Pre-computed reputation score for the skill descriptor. */
|
|
440
|
+
reputation?: ReputationScore;
|
|
441
|
+
/** TEE attestation metadata for the skill descriptor. */
|
|
442
|
+
attestation?: {
|
|
443
|
+
/** 64-char hex event ID of the provider's latest kind:10033 attestation event. */
|
|
444
|
+
eventId: string;
|
|
445
|
+
/** Enclave image hash for the TEE environment. */
|
|
446
|
+
enclaveImageHash: string;
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Builds a SkillDescriptor from the handler registry and configuration.
|
|
451
|
+
*
|
|
452
|
+
* Returns `undefined` when the registry has no DVM handlers (kinds 5000-5999).
|
|
453
|
+
* When DVM kinds exist, auto-populates the descriptor:
|
|
454
|
+
* - `kinds` from `registry.getDvmKinds()`
|
|
455
|
+
* - `pricing` from `config.kindPricing` overrides or `config.basePricePerByte` fallback
|
|
456
|
+
* - `name`, `version`, `features`, `inputSchema`, `models` from config or defaults
|
|
457
|
+
*
|
|
458
|
+
* @param registry - The handler registry to read DVM kinds from.
|
|
459
|
+
* @param config - Node configuration for pricing and optional overrides.
|
|
460
|
+
* @returns A SkillDescriptor, or undefined if no DVM handlers are registered.
|
|
461
|
+
*/
|
|
462
|
+
declare function buildSkillDescriptor(registry: HandlerRegistry, config?: BuildSkillDescriptorConfig): SkillDescriptor | undefined;
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* createNode() composition for @toon-protocol/sdk.
|
|
466
|
+
*
|
|
467
|
+
* Wires the full ILP packet processing pipeline:
|
|
468
|
+
* shallow TOON parse -> Schnorr signature verification -> pricing validation -> handler dispatch
|
|
469
|
+
*
|
|
470
|
+
* Provides start() / stop() lifecycle management by delegating to
|
|
471
|
+
* the core ToonNode composition (embedded mode) or manual HTTP
|
|
472
|
+
* composition (standalone mode).
|
|
473
|
+
*
|
|
474
|
+
* ## Deployment Modes
|
|
475
|
+
*
|
|
476
|
+
* - **Embedded** (`connector`): Pass an EmbeddableConnectorLike directly.
|
|
477
|
+
* Zero-latency packet delivery via direct function calls.
|
|
478
|
+
* - **Standalone** (`connectorUrl` + `handlerPort`): Connect to an external
|
|
479
|
+
* connector via HTTP. The SDK starts an HTTP server to receive packets.
|
|
480
|
+
*/
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Configuration for creating a ServiceNode via createNode().
|
|
484
|
+
*
|
|
485
|
+
* Supports three deployment modes:
|
|
486
|
+
* - **Default** (no connector args): Auto-creates an embedded ConnectorNode via
|
|
487
|
+
* dynamic import. Requires `@toon-protocol/connector` as peer dependency.
|
|
488
|
+
* - **Embedded** (`connector`): Pass a pre-configured EmbeddableConnectorLike.
|
|
489
|
+
* - **Standalone** (`connectorUrl` + `handlerPort`): Connect to an external
|
|
490
|
+
* connector via HTTP. The SDK starts an HTTP server to receive packets.
|
|
491
|
+
*
|
|
492
|
+
* Provide `connector` OR (`connectorUrl` + `handlerPort`), or neither (auto-create).
|
|
493
|
+
*/
|
|
494
|
+
interface NodeConfig {
|
|
495
|
+
/** 32-byte secp256k1 secret key */
|
|
496
|
+
secretKey: Uint8Array;
|
|
497
|
+
/** Chain preset name (default: 'anvil'). See resolveChainConfig(). */
|
|
498
|
+
chain?: string;
|
|
499
|
+
/**
|
|
500
|
+
* Embedded connector instance for zero-latency mode.
|
|
501
|
+
* If neither `connector` nor `connectorUrl` is provided, an embedded
|
|
502
|
+
* ConnectorNode is auto-created (requires @toon-protocol/connector peer dep).
|
|
503
|
+
*/
|
|
504
|
+
connector?: EmbeddableConnectorLike;
|
|
505
|
+
/**
|
|
506
|
+
* External connector admin URL for standalone mode (e.g., "http://localhost:8081").
|
|
507
|
+
* Must be provided with `handlerPort`.
|
|
508
|
+
*/
|
|
509
|
+
connectorUrl?: string;
|
|
510
|
+
/**
|
|
511
|
+
* Port for the HTTP server that receives ILP packets from the external connector.
|
|
512
|
+
* Must be provided with `connectorUrl`.
|
|
513
|
+
*/
|
|
514
|
+
handlerPort?: number;
|
|
515
|
+
/**
|
|
516
|
+
* BTP server port for the auto-created embedded connector (default: 3000).
|
|
517
|
+
* Only used when neither `connector` nor `connectorUrl` is provided.
|
|
518
|
+
*/
|
|
519
|
+
btpServerPort?: number;
|
|
520
|
+
/**
|
|
521
|
+
* EVM private key for settlement infrastructure.
|
|
522
|
+
* Only used when auto-creating an embedded connector.
|
|
523
|
+
* If not set, the identity's secp256k1 key is used.
|
|
524
|
+
*/
|
|
525
|
+
settlementPrivateKey?: string;
|
|
526
|
+
/**
|
|
527
|
+
* Upstream peer's ILP address prefix for address derivation.
|
|
528
|
+
* When set, the node derives its ILP address as
|
|
529
|
+
* `deriveChildAddress(upstreamPrefix, pubkey)` and ignores `ilpAddress`.
|
|
530
|
+
*/
|
|
531
|
+
upstreamPrefix?: string;
|
|
532
|
+
/**
|
|
533
|
+
* Multiple upstream peer prefixes for multi-peered nodes (Story 7.3).
|
|
534
|
+
* When set, derives one ILP address per upstream prefix. Takes priority
|
|
535
|
+
* over `upstreamPrefix` (singular) when both are set.
|
|
536
|
+
*/
|
|
537
|
+
upstreamPrefixes?: string[];
|
|
538
|
+
/** ILP address (default: derived from pubkey under ILP_ROOT_PREFIX) */
|
|
539
|
+
ilpAddress?: string;
|
|
540
|
+
/** BTP endpoint URL advertised in kind:10032 announcements */
|
|
541
|
+
btpEndpoint?: string;
|
|
542
|
+
/** Asset code (default: 'USD') */
|
|
543
|
+
assetCode?: string;
|
|
544
|
+
/** Asset scale (default: 6) */
|
|
545
|
+
assetScale?: number;
|
|
546
|
+
/**
|
|
547
|
+
* Base price per byte for pricing validation (default: 10n).
|
|
548
|
+
*
|
|
549
|
+
* Amounts are in USDC micro-units (6 decimals) for production.
|
|
550
|
+
* Default 10n = 10 micro-USDC per byte = $0.00001/byte.
|
|
551
|
+
* A 1KB event costs 10,240 micro-USDC = ~$0.01.
|
|
552
|
+
*/
|
|
553
|
+
basePricePerByte?: bigint;
|
|
554
|
+
/**
|
|
555
|
+
* Routing fee per byte charged by this node as an intermediary (default: 0n = free routing).
|
|
556
|
+
* Advertised in kind:10032 peer info events as a non-negative integer string.
|
|
557
|
+
*/
|
|
558
|
+
feePerByte?: bigint;
|
|
559
|
+
/** Dev mode skips signature verification (default: false) */
|
|
560
|
+
devMode?: boolean;
|
|
561
|
+
/** TOON encoder function */
|
|
562
|
+
toonEncoder?: (event: NostrEvent) => Uint8Array;
|
|
563
|
+
/** TOON decoder function */
|
|
564
|
+
toonDecoder?: (bytes: Uint8Array) => NostrEvent;
|
|
565
|
+
/** Initial known peers for bootstrap */
|
|
566
|
+
knownPeers?: KnownPeer[];
|
|
567
|
+
/** Relay WebSocket URL */
|
|
568
|
+
relayUrl?: string;
|
|
569
|
+
/** Settlement info for peer registration */
|
|
570
|
+
settlementInfo?: SettlementConfig;
|
|
571
|
+
/** Enable ArDrive peer lookup */
|
|
572
|
+
ardriveEnabled?: boolean;
|
|
573
|
+
/** Per-kind pricing overrides */
|
|
574
|
+
kindPricing?: Record<number, bigint>;
|
|
575
|
+
/**
|
|
576
|
+
* Multi-chain provider configuration for the embedded connector.
|
|
577
|
+
* When provided, passed directly to ConnectorNode as `chainProviders`.
|
|
578
|
+
* Takes priority over the legacy `settlementInfra` auto-configuration.
|
|
579
|
+
* Only used when auto-creating an embedded connector.
|
|
580
|
+
*/
|
|
581
|
+
chainProviders?: ChainProviderConfigEntry[];
|
|
582
|
+
/**
|
|
583
|
+
* Transport configuration for the embedded connector (ator/SOCKS5 privacy overlay).
|
|
584
|
+
* When provided, passed directly to ConnectorNode as `transport`.
|
|
585
|
+
* Only used when auto-creating an embedded connector.
|
|
586
|
+
*/
|
|
587
|
+
transport?: TransportConfig;
|
|
588
|
+
/**
|
|
589
|
+
* NIP-59 transport privacy configuration for the embedded connector.
|
|
590
|
+
* When enabled, per-packet claims are wrapped in three-layer encryption.
|
|
591
|
+
* Only used when auto-creating an embedded connector.
|
|
592
|
+
*/
|
|
593
|
+
nip59?: {
|
|
594
|
+
enabled: boolean;
|
|
595
|
+
};
|
|
596
|
+
/**
|
|
597
|
+
* Per-peer NIP-59 public keys for claim encryption.
|
|
598
|
+
* Map of peer ID to compressed secp256k1 public key (hex, 66 chars).
|
|
599
|
+
* Applied to peer configs when registering peers with the connector.
|
|
600
|
+
* Only used when auto-creating an embedded connector.
|
|
601
|
+
*/
|
|
602
|
+
peerNip59PublicKeys?: Record<string, string>;
|
|
603
|
+
/** Config-based handler registration (alternative to post-creation .on()) */
|
|
604
|
+
handlers?: Record<number, Handler>;
|
|
605
|
+
/** Config-based default handler (alternative to post-creation .onDefault()) */
|
|
606
|
+
defaultHandler?: Handler;
|
|
607
|
+
/**
|
|
608
|
+
* Optional skill descriptor configuration overrides.
|
|
609
|
+
* When DVM handlers are registered, these values override the auto-derived
|
|
610
|
+
* defaults in the skill descriptor. See buildSkillDescriptor().
|
|
611
|
+
*/
|
|
612
|
+
skillConfig?: Omit<BuildSkillDescriptorConfig, 'basePricePerByte' | 'kindPricing'>;
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* Result returned by ServiceNode.start().
|
|
616
|
+
*/
|
|
617
|
+
interface StartResult {
|
|
618
|
+
/** Number of peers successfully bootstrapped */
|
|
619
|
+
peerCount: number;
|
|
620
|
+
/** Number of payment channels opened */
|
|
621
|
+
channelCount: number;
|
|
622
|
+
/** Detailed results from the bootstrap phase */
|
|
623
|
+
bootstrapResults: BootstrapResult[];
|
|
624
|
+
}
|
|
625
|
+
/**
|
|
626
|
+
* Result returned by ServiceNode.publishEvent().
|
|
627
|
+
*/
|
|
628
|
+
interface PublishEventResult {
|
|
629
|
+
success: boolean;
|
|
630
|
+
eventId: string;
|
|
631
|
+
/** Response data from the ILP FULFILL packet (e.g., Arweave tx ID for kind:5094). */
|
|
632
|
+
data?: string;
|
|
633
|
+
code?: string;
|
|
634
|
+
message?: string;
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* A fully wired TOON node with lifecycle management.
|
|
638
|
+
*/
|
|
639
|
+
interface ServiceNode {
|
|
640
|
+
/** Nostr x-only public key (32 bytes, 64 hex chars) */
|
|
641
|
+
readonly pubkey: string;
|
|
642
|
+
/** EVM address derived from the same secp256k1 key */
|
|
643
|
+
readonly evmAddress: string;
|
|
644
|
+
/** Pass-through to the underlying connector (null in standalone mode) */
|
|
645
|
+
readonly connector: EmbeddableConnectorLike | null;
|
|
646
|
+
/** Channel client (null if connector lacks channel support or in standalone mode) */
|
|
647
|
+
readonly channelClient: ConnectorChannelClient | null;
|
|
648
|
+
/** Register a handler for a specific event kind (builder pattern) */
|
|
649
|
+
on(kind: number, handler: Handler): ServiceNode;
|
|
650
|
+
/** Register a lifecycle event listener */
|
|
651
|
+
on(event: 'bootstrap', listener: BootstrapEventListener): ServiceNode;
|
|
652
|
+
/** Register a default handler for unrecognized kinds (builder pattern) */
|
|
653
|
+
onDefault(handler: Handler): ServiceNode;
|
|
654
|
+
/** Start the node: wire packet handler, run bootstrap, start discovery */
|
|
655
|
+
start(): Promise<StartResult>;
|
|
656
|
+
/** Stop the node: clean up lifecycle state */
|
|
657
|
+
stop(): Promise<void>;
|
|
658
|
+
/** Initiate peering with a discovered peer (register + settlement) */
|
|
659
|
+
peerWith(pubkey: string): Promise<void>;
|
|
660
|
+
/**
|
|
661
|
+
* Publish a Nostr event to a remote peer via the embedded connector.
|
|
662
|
+
*
|
|
663
|
+
* TOON-encodes the event, computes payment amount, and sends as an
|
|
664
|
+
* ILP PREPARE packet via the runtime client.
|
|
665
|
+
*
|
|
666
|
+
* @param event - The Nostr event to publish
|
|
667
|
+
* @param options - Must include destination ILP address. Optional `amount`
|
|
668
|
+
* overrides the default basePricePerByte * toonData.length calculation
|
|
669
|
+
* (prepaid model: send exact destination amount). Optional `bid` is a
|
|
670
|
+
* client-side safety cap: if the destination amount exceeds `bid`, the
|
|
671
|
+
* SDK throws before sending any ILP packet.
|
|
672
|
+
* @returns Result with success/failure info and event ID
|
|
673
|
+
*/
|
|
674
|
+
publishEvent(event: NostrEvent, options?: {
|
|
675
|
+
destination: string;
|
|
676
|
+
amount?: bigint;
|
|
677
|
+
bid?: bigint;
|
|
678
|
+
}): Promise<PublishEventResult>;
|
|
679
|
+
/**
|
|
680
|
+
* Publish a Kind 7000 DVM job feedback event via ILP PREPARE.
|
|
681
|
+
*
|
|
682
|
+
* Builds a signed Kind 7000 feedback event with NIP-90 tags (e, p, status)
|
|
683
|
+
* and delegates to publishEvent() for TOON encoding and ILP delivery.
|
|
684
|
+
* Standard relay write fee applies: basePricePerByte * toonData.length.
|
|
685
|
+
*
|
|
686
|
+
* @param requestEventId - 64-char hex event ID of the original Kind 5xxx request
|
|
687
|
+
* @param customerPubkey - 64-char hex pubkey of the customer who posted the request
|
|
688
|
+
* @param status - Job status value ('processing', 'error', 'success', 'partial')
|
|
689
|
+
* @param content - Optional status details or error message
|
|
690
|
+
* @param options - Must include destination ILP address
|
|
691
|
+
* @returns Result with success/failure info and event ID
|
|
692
|
+
*/
|
|
693
|
+
publishFeedback(requestEventId: string, customerPubkey: string, status: DvmJobStatus, content?: string, options?: {
|
|
694
|
+
destination: string;
|
|
695
|
+
}): Promise<PublishEventResult>;
|
|
696
|
+
/**
|
|
697
|
+
* Publish a Kind 6xxx DVM job result event via ILP PREPARE.
|
|
698
|
+
*
|
|
699
|
+
* Builds a signed Kind 6xxx result event with NIP-90 tags (e, p, amount)
|
|
700
|
+
* and delegates to publishEvent() for TOON encoding and ILP delivery.
|
|
701
|
+
* Standard relay write fee applies: basePricePerByte * toonData.length.
|
|
702
|
+
*
|
|
703
|
+
* @param requestEventId - 64-char hex event ID of the original Kind 5xxx request
|
|
704
|
+
* @param customerPubkey - 64-char hex pubkey of the customer who posted the request
|
|
705
|
+
* @param amount - Compute cost in USDC micro-units as string
|
|
706
|
+
* @param content - Result data (text, URL, etc.)
|
|
707
|
+
* @param options - Must include destination; optional kind (default: 6100)
|
|
708
|
+
* @returns Result with success/failure info and event ID
|
|
709
|
+
*/
|
|
710
|
+
publishResult(requestEventId: string, customerPubkey: string, amount: string, content: string, options?: {
|
|
711
|
+
destination: string;
|
|
712
|
+
kind?: number;
|
|
713
|
+
}): Promise<PublishEventResult>;
|
|
714
|
+
/**
|
|
715
|
+
* Returns the computed skill descriptor for this node's DVM capabilities.
|
|
716
|
+
* Returns `undefined` if no DVM handlers (kinds 5000-5999) are registered.
|
|
717
|
+
* The descriptor is computed from the handler registry and node config.
|
|
718
|
+
*/
|
|
719
|
+
getSkillDescriptor(): SkillDescriptor | undefined;
|
|
720
|
+
/**
|
|
721
|
+
* Send an ILP payment to a provider for compute settlement.
|
|
722
|
+
*
|
|
723
|
+
* Extracts the compute cost from the result event's `amount` tag via
|
|
724
|
+
* parseJobResult(), optionally validates against the original bid amount
|
|
725
|
+
* (E5-R005 bid validation), and sends a pure ILP value transfer
|
|
726
|
+
* (empty data field) to the provider's ILP address.
|
|
727
|
+
*
|
|
728
|
+
* This is a payment-only operation -- no TOON encoding, no relay write.
|
|
729
|
+
* The payment routes through the ILP mesh using the same infrastructure
|
|
730
|
+
* as relay write fees.
|
|
731
|
+
*
|
|
732
|
+
* @deprecated Use publishEvent() with amount option instead. Prepaid model:
|
|
733
|
+
* send job request + payment in one packet via
|
|
734
|
+
* `publishEvent(event, { destination, amount: computePrice })`.
|
|
735
|
+
*
|
|
736
|
+
* @param resultEvent - Kind 6xxx result event with amount tag
|
|
737
|
+
* @param providerIlpAddress - Provider's ILP address from kind:10035
|
|
738
|
+
* @param options - Optional originalBid for bid validation (E5-R005)
|
|
739
|
+
* @returns ILP send result with accepted/rejected status
|
|
740
|
+
*/
|
|
741
|
+
settleCompute(resultEvent: NostrEvent, providerIlpAddress: string, options?: {
|
|
742
|
+
originalBid?: string;
|
|
743
|
+
}): Promise<IlpSendResult>;
|
|
744
|
+
/**
|
|
745
|
+
* Add a new upstream peer, deriving and registering its ILP address.
|
|
746
|
+
*
|
|
747
|
+
* Updates the AddressRegistry, registers a self-route in the embedded
|
|
748
|
+
* connector, and triggers kind:10032 republication via BootstrapService.
|
|
749
|
+
*
|
|
750
|
+
* @param upstreamPrefix - The upstream peer's ILP address prefix
|
|
751
|
+
*/
|
|
752
|
+
addUpstreamPeer(upstreamPrefix: string): void;
|
|
753
|
+
/**
|
|
754
|
+
* Remove an upstream peer, unregistering its derived ILP address.
|
|
755
|
+
*
|
|
756
|
+
* Updates the AddressRegistry, removes the self-route from the embedded
|
|
757
|
+
* connector, and triggers kind:10032 republication via BootstrapService.
|
|
758
|
+
*
|
|
759
|
+
* @param upstreamPrefix - The upstream prefix to remove
|
|
760
|
+
*/
|
|
761
|
+
removeUpstreamPeer(upstreamPrefix: string): void;
|
|
762
|
+
/**
|
|
763
|
+
* Claim a prefix from an upstream peer by sending a prefix claim event
|
|
764
|
+
* with payment via ILP.
|
|
765
|
+
*
|
|
766
|
+
* Builds a Kind 10034 prefix claim event, reads the upstream's prefix
|
|
767
|
+
* pricing from its kind:10032 advertisement, and calls publishEvent()
|
|
768
|
+
* with the appropriate amount.
|
|
769
|
+
*
|
|
770
|
+
* @param prefix - The prefix string to claim (e.g., 'useast')
|
|
771
|
+
* @param upstreamDestination - ILP address of the upstream node
|
|
772
|
+
* @param options - Optional prefixPrice override (defaults to upstream's prefixPricing.basePrice from discovery)
|
|
773
|
+
* @returns Result with success/failure info and event ID
|
|
774
|
+
*/
|
|
775
|
+
claimPrefix(prefix: string, upstreamDestination: string, options?: {
|
|
776
|
+
prefixPrice?: bigint;
|
|
777
|
+
}): Promise<PublishEventResult>;
|
|
778
|
+
}
|
|
779
|
+
/**
|
|
780
|
+
* Creates a fully wired ServiceNode from configuration.
|
|
781
|
+
*
|
|
782
|
+
* The returned node has the full ILP packet processing pipeline wired in the
|
|
783
|
+
* correct order:
|
|
784
|
+
* 1. Shallow TOON parse (extract routing metadata)
|
|
785
|
+
* 2. Schnorr signature verification (reject with F06 if invalid)
|
|
786
|
+
* 3. Pricing validation (reject with F04 if underpaid)
|
|
787
|
+
* 4. Handler dispatch (route to kind-specific or default handler)
|
|
788
|
+
*
|
|
789
|
+
* Supports two deployment modes:
|
|
790
|
+
* - **Embedded** (`connector`): Uses createToonNode for zero-latency
|
|
791
|
+
* packet delivery via direct function calls.
|
|
792
|
+
* - **Standalone** (`connectorUrl` + `handlerPort`): Starts an HTTP server
|
|
793
|
+
* to receive packets and uses HTTP clients for the connector API.
|
|
794
|
+
*
|
|
795
|
+
* Handlers can be registered via config or post-creation .on()/.onDefault().
|
|
796
|
+
*/
|
|
797
|
+
declare function createNode(config: NodeConfig): ServiceNode;
|
|
798
|
+
|
|
799
|
+
/**
|
|
800
|
+
* Workflow Orchestrator for multi-step DVM pipelines (Story 6.1).
|
|
801
|
+
*
|
|
802
|
+
* Manages the lifecycle of a workflow chain: creates step job requests,
|
|
803
|
+
* detects step completion/failure, advances to the next step, handles
|
|
804
|
+
* timeouts, and settles compute payments per step.
|
|
805
|
+
*
|
|
806
|
+
* The orchestrator uses the TOON relay as the orchestration layer --
|
|
807
|
+
* there is no separate workflow engine. Step completion is detected
|
|
808
|
+
* via relay event subscriptions (Kind 6xxx results, Kind 7000 feedback).
|
|
809
|
+
*
|
|
810
|
+
* State machine states:
|
|
811
|
+
* - `pending`: Workflow created but not yet started
|
|
812
|
+
* - `step_N_running`: Step N's job request published, waiting for result
|
|
813
|
+
* - `step_N_failed`: Step N failed (error or timeout), workflow aborted
|
|
814
|
+
* - `completed`: All steps finished successfully
|
|
815
|
+
*
|
|
816
|
+
* Settlement: Each step settles individually via settleCompute().
|
|
817
|
+
* The orchestrator validates sum(step_amounts) <= total_bid before settlement.
|
|
818
|
+
*
|
|
819
|
+
* Forward-compatible with Epic 7 prepaid protocol: settlement logic is
|
|
820
|
+
* isolated in handleStepResult() so swapping to prepaid per-step payment
|
|
821
|
+
* requires changes only in that method.
|
|
822
|
+
*/
|
|
823
|
+
|
|
824
|
+
/**
|
|
825
|
+
* Workflow state type. Uses template literal types for step-indexed states.
|
|
826
|
+
* Note: Timeout is represented as `step_N_failed` (timeout is a failure mode,
|
|
827
|
+
* not a separate terminal state). The timeout cause is communicated in the
|
|
828
|
+
* customer notification content.
|
|
829
|
+
*/
|
|
830
|
+
type WorkflowState = 'pending' | `step_${number}_running` | `step_${number}_failed` | 'completed';
|
|
831
|
+
/**
|
|
832
|
+
* Event store interface for workflow state persistence.
|
|
833
|
+
* Minimal interface -- only store() and query() are needed.
|
|
834
|
+
*/
|
|
835
|
+
interface WorkflowEventStore {
|
|
836
|
+
store(event: NostrEvent): Promise<void>;
|
|
837
|
+
query(filter: {
|
|
838
|
+
kinds?: number[];
|
|
839
|
+
'#e'?: string[];
|
|
840
|
+
}): Promise<NostrEvent[]>;
|
|
841
|
+
}
|
|
842
|
+
/**
|
|
843
|
+
* Configuration options for the WorkflowOrchestrator.
|
|
844
|
+
*/
|
|
845
|
+
interface WorkflowOrchestratorOptions {
|
|
846
|
+
/** Secret key for signing step job request events (32-byte Uint8Array). */
|
|
847
|
+
secretKey?: Uint8Array;
|
|
848
|
+
/** Per-step timeout in milliseconds (default: 300000 = 5 minutes). */
|
|
849
|
+
stepTimeoutMs?: number;
|
|
850
|
+
/** Injectable time source for deterministic testing. */
|
|
851
|
+
now?: () => number;
|
|
852
|
+
/**
|
|
853
|
+
* Injectable timer factory for deterministic testing.
|
|
854
|
+
* Defaults to global setTimeout. Inject a custom implementation
|
|
855
|
+
* to control timer advancement in tests without vi.useFakeTimers().
|
|
856
|
+
*/
|
|
857
|
+
setTimer?: (callback: () => void, ms: number) => ReturnType<typeof setTimeout>;
|
|
858
|
+
/**
|
|
859
|
+
* Injectable timer cancellation for deterministic testing.
|
|
860
|
+
* Defaults to global clearTimeout. Must pair with setTimer.
|
|
861
|
+
*/
|
|
862
|
+
clearTimer?: (handle: ReturnType<typeof setTimeout>) => void;
|
|
863
|
+
/** Optional event store for workflow state persistence. */
|
|
864
|
+
eventStore?: WorkflowEventStore;
|
|
865
|
+
/** Default destination ILP address for publishing events. */
|
|
866
|
+
destination?: string;
|
|
867
|
+
/** Workflow definition event ID (for referencing in notifications). */
|
|
868
|
+
workflowEventId?: string;
|
|
869
|
+
/** Customer pubkey (for directing notifications). */
|
|
870
|
+
customerPubkey?: string;
|
|
871
|
+
}
|
|
872
|
+
/**
|
|
873
|
+
* Per-step state tracking.
|
|
874
|
+
*/
|
|
875
|
+
interface StepState {
|
|
876
|
+
/** Index of this step (0-based). */
|
|
877
|
+
index: number;
|
|
878
|
+
/** The job request event ID published for this step. */
|
|
879
|
+
requestEventId?: string;
|
|
880
|
+
/** The result event received for this step. */
|
|
881
|
+
resultEvent?: NostrEvent;
|
|
882
|
+
/** Whether this step has been settled. */
|
|
883
|
+
settled: boolean;
|
|
884
|
+
}
|
|
885
|
+
/**
|
|
886
|
+
* Orchestrates a multi-step DVM workflow chain.
|
|
887
|
+
*
|
|
888
|
+
* Each instance manages a single workflow. For concurrent workflows,
|
|
889
|
+
* create multiple WorkflowOrchestrator instances sharing the same
|
|
890
|
+
* ServiceNode.
|
|
891
|
+
*/
|
|
892
|
+
declare class WorkflowOrchestrator {
|
|
893
|
+
private readonly node;
|
|
894
|
+
private readonly options;
|
|
895
|
+
private state;
|
|
896
|
+
private definition;
|
|
897
|
+
private workflowEventId;
|
|
898
|
+
private customerPubkey;
|
|
899
|
+
private currentStepIndex;
|
|
900
|
+
private stepStates;
|
|
901
|
+
private timeoutHandle;
|
|
902
|
+
private processedResultIds;
|
|
903
|
+
constructor(node: ServiceNode, options?: WorkflowOrchestratorOptions);
|
|
904
|
+
/**
|
|
905
|
+
* Returns the current workflow state.
|
|
906
|
+
*/
|
|
907
|
+
getState(): WorkflowState;
|
|
908
|
+
/**
|
|
909
|
+
* Returns per-step state tracking data (for testing/debugging).
|
|
910
|
+
*/
|
|
911
|
+
getStepStates(): readonly Readonly<StepState>[];
|
|
912
|
+
/**
|
|
913
|
+
* Starts a workflow: parses the definition, creates and publishes
|
|
914
|
+
* the Kind 5xxx job request for step 1, sets state to step_1_running.
|
|
915
|
+
*/
|
|
916
|
+
startWorkflow(definition: ParsedWorkflowDefinition): Promise<void>;
|
|
917
|
+
/**
|
|
918
|
+
* Handles a Kind 6xxx result event for the current step.
|
|
919
|
+
*
|
|
920
|
+
* If the current step matches, extracts the result content and either:
|
|
921
|
+
* - Advances to the next step (publishes Kind 5xxx for step N+1)
|
|
922
|
+
* - Marks workflow as completed (if this was the final step)
|
|
923
|
+
*
|
|
924
|
+
* Idempotent: re-processing a result for an already-advanced step is a no-op.
|
|
925
|
+
*/
|
|
926
|
+
handleStepResult(resultEvent: NostrEvent): Promise<void>;
|
|
927
|
+
/**
|
|
928
|
+
* Handles a Kind 7000 feedback event for the current step.
|
|
929
|
+
*
|
|
930
|
+
* If the feedback status is 'error', marks the workflow as failed
|
|
931
|
+
* and notifies the customer.
|
|
932
|
+
*/
|
|
933
|
+
handleStepFeedback(feedbackEvent: NostrEvent): Promise<void>;
|
|
934
|
+
/**
|
|
935
|
+
* Cleans up resources (timeout handles).
|
|
936
|
+
*/
|
|
937
|
+
destroy(): void;
|
|
938
|
+
/**
|
|
939
|
+
* Publishes a Kind 5xxx job request for the given step.
|
|
940
|
+
*/
|
|
941
|
+
private publishStepRequest;
|
|
942
|
+
/**
|
|
943
|
+
* Settles compute payment for a completed step.
|
|
944
|
+
*/
|
|
945
|
+
private settleStep;
|
|
946
|
+
/**
|
|
947
|
+
* Returns the bid allocation for a specific step.
|
|
948
|
+
* Uses explicit bidAllocation if set, otherwise proportional split.
|
|
949
|
+
*/
|
|
950
|
+
private getStepBid;
|
|
951
|
+
/**
|
|
952
|
+
* Publishes a Kind 7000 workflow notification to the customer.
|
|
953
|
+
*/
|
|
954
|
+
private publishWorkflowNotification;
|
|
955
|
+
/**
|
|
956
|
+
* Starts a timeout timer for the current step.
|
|
957
|
+
*/
|
|
958
|
+
private startStepTimeout;
|
|
959
|
+
/**
|
|
960
|
+
* Returns the secret key for signing step events.
|
|
961
|
+
* Falls back to a deterministic key derived from the node pubkey
|
|
962
|
+
* (for testing -- production should always pass secretKey in options).
|
|
963
|
+
*/
|
|
964
|
+
private getSecretKey;
|
|
965
|
+
/**
|
|
966
|
+
* Clears the current step timeout.
|
|
967
|
+
*/
|
|
968
|
+
private clearStepTimeout;
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
/**
|
|
972
|
+
* Swarm Coordinator for competitive DVM bidding (Story 6.2).
|
|
973
|
+
*
|
|
974
|
+
* Manages the lifecycle of a competitive swarm: collects provider
|
|
975
|
+
* submissions, handles timeout-based judging deadlines, validates
|
|
976
|
+
* winner selection, and settles compute payment to the winner only.
|
|
977
|
+
*
|
|
978
|
+
* The coordinator uses the TOON relay as the orchestration layer --
|
|
979
|
+
* there is no separate swarm engine. Submission arrival is detected
|
|
980
|
+
* via relay event subscriptions (Kind 6xxx results).
|
|
981
|
+
*
|
|
982
|
+
* State machine states:
|
|
983
|
+
* - `collecting`: Waiting for provider submissions (Kind 6xxx results)
|
|
984
|
+
* - `judging`: Timeout or max submissions reached; customer selects winner
|
|
985
|
+
* - `settled`: Winner paid via settleCompute(); swarm complete
|
|
986
|
+
* - `failed`: No submissions within timeout or error
|
|
987
|
+
*
|
|
988
|
+
* Settlement: Only the winning provider receives compute payment.
|
|
989
|
+
* Losing providers paid relay write fees (sunk cost) but receive
|
|
990
|
+
* no compute payment -- this is by design to incentivize quality.
|
|
991
|
+
*
|
|
992
|
+
* Forward-compatible with Epic 7 prepaid protocol: settlement logic
|
|
993
|
+
* is isolated in selectWinner() so swapping to prepaid per-winner
|
|
994
|
+
* payment requires changes only in that method.
|
|
995
|
+
*/
|
|
996
|
+
|
|
997
|
+
/**
|
|
998
|
+
* Swarm state type.
|
|
999
|
+
* - `collecting`: Waiting for provider submissions.
|
|
1000
|
+
* - `judging`: Timeout or max submissions reached; awaiting winner selection.
|
|
1001
|
+
* - `settled`: Winner paid; swarm complete.
|
|
1002
|
+
* - `failed`: No submissions within timeout or error.
|
|
1003
|
+
*/
|
|
1004
|
+
type SwarmState = 'collecting' | 'judging' | 'settled' | 'failed';
|
|
1005
|
+
/**
|
|
1006
|
+
* Configuration options for the SwarmCoordinator.
|
|
1007
|
+
*/
|
|
1008
|
+
interface SwarmCoordinatorOptions {
|
|
1009
|
+
/** Secret key for signing events (32-byte Uint8Array). */
|
|
1010
|
+
secretKey?: Uint8Array;
|
|
1011
|
+
/** Swarm collection timeout in milliseconds (default: 600000 = 10 minutes). */
|
|
1012
|
+
timeoutMs?: number;
|
|
1013
|
+
/** Injectable time source for deterministic testing. */
|
|
1014
|
+
now?: () => number;
|
|
1015
|
+
/**
|
|
1016
|
+
* Injectable timer factory for deterministic testing.
|
|
1017
|
+
* Defaults to global setTimeout. Inject a custom implementation
|
|
1018
|
+
* to control timer advancement in tests without vi.useFakeTimers().
|
|
1019
|
+
*/
|
|
1020
|
+
setTimer?: (callback: () => void, ms: number) => ReturnType<typeof setTimeout>;
|
|
1021
|
+
/**
|
|
1022
|
+
* Injectable timer cancellation for deterministic testing.
|
|
1023
|
+
* Defaults to global clearTimeout. Must pair with setTimer.
|
|
1024
|
+
*/
|
|
1025
|
+
clearTimer?: (handle: ReturnType<typeof setTimeout>) => void;
|
|
1026
|
+
/** Optional event store for swarm state persistence. */
|
|
1027
|
+
eventStore?: WorkflowEventStore;
|
|
1028
|
+
/** Default destination ILP address for publishing events. */
|
|
1029
|
+
destination?: string;
|
|
1030
|
+
}
|
|
1031
|
+
/**
|
|
1032
|
+
* Coordinates a competitive DVM swarm.
|
|
1033
|
+
*
|
|
1034
|
+
* Each instance manages a single swarm. For concurrent swarms,
|
|
1035
|
+
* create multiple SwarmCoordinator instances sharing the same
|
|
1036
|
+
* ServiceNode.
|
|
1037
|
+
*/
|
|
1038
|
+
declare class SwarmCoordinator {
|
|
1039
|
+
private readonly node;
|
|
1040
|
+
private readonly options;
|
|
1041
|
+
private state;
|
|
1042
|
+
private swarmRequestId;
|
|
1043
|
+
private customerPubkey;
|
|
1044
|
+
private maxProviders;
|
|
1045
|
+
private submissions;
|
|
1046
|
+
private timeoutHandle;
|
|
1047
|
+
private started;
|
|
1048
|
+
private settlementSucceeded;
|
|
1049
|
+
private submissionIds;
|
|
1050
|
+
constructor(node: ServiceNode, options?: SwarmCoordinatorOptions);
|
|
1051
|
+
/**
|
|
1052
|
+
* Returns the current swarm state.
|
|
1053
|
+
*/
|
|
1054
|
+
getState(): SwarmState;
|
|
1055
|
+
/**
|
|
1056
|
+
* Returns whether settlement was successfully completed.
|
|
1057
|
+
* Only meaningful when state is 'settled' (returns true).
|
|
1058
|
+
* If settlement fails, the state remains 'judging' and this returns false.
|
|
1059
|
+
*/
|
|
1060
|
+
isSettlementSucceeded(): boolean;
|
|
1061
|
+
/**
|
|
1062
|
+
* Returns the collected eligible submissions.
|
|
1063
|
+
*/
|
|
1064
|
+
getSubmissions(): readonly NostrEvent[];
|
|
1065
|
+
/**
|
|
1066
|
+
* Starts a swarm: parses the swarm request, initializes collection,
|
|
1067
|
+
* and starts the timeout timer.
|
|
1068
|
+
*/
|
|
1069
|
+
startSwarm(swarmRequest: NostrEvent): Promise<void>;
|
|
1070
|
+
/**
|
|
1071
|
+
* Handles a Kind 6xxx result event (provider submission).
|
|
1072
|
+
*
|
|
1073
|
+
* Validates the `e` tag references the swarm request, adds to the
|
|
1074
|
+
* submissions list, and checks if max providers is reached.
|
|
1075
|
+
*
|
|
1076
|
+
* Late submissions (after timeout or max reached) are ignored.
|
|
1077
|
+
* Submissions before startSwarm() are silently ignored.
|
|
1078
|
+
*/
|
|
1079
|
+
handleSubmission(resultEvent: NostrEvent): Promise<void>;
|
|
1080
|
+
/**
|
|
1081
|
+
* Selects the winner and settles compute payment.
|
|
1082
|
+
*
|
|
1083
|
+
* Validates:
|
|
1084
|
+
* - Swarm is in `judging` state (not `collecting`, `settled`, or `failed`)
|
|
1085
|
+
* - Selection references a submission in the collected set
|
|
1086
|
+
* - Swarm has not already been settled (idempotency guard)
|
|
1087
|
+
*
|
|
1088
|
+
* @throws ToonError with code DVM_SWARM_ALREADY_SETTLED if already settled
|
|
1089
|
+
* @throws ToonError with code DVM_SWARM_INVALID_SELECTION if winner not in submissions
|
|
1090
|
+
*/
|
|
1091
|
+
selectWinner(selectionEvent: NostrEvent): Promise<void>;
|
|
1092
|
+
/**
|
|
1093
|
+
* Cleans up resources (timeout handles).
|
|
1094
|
+
*/
|
|
1095
|
+
destroy(): void;
|
|
1096
|
+
/**
|
|
1097
|
+
* Starts the collection timeout timer.
|
|
1098
|
+
*/
|
|
1099
|
+
private startTimeout;
|
|
1100
|
+
/**
|
|
1101
|
+
* Publishes a Kind 7000 feedback event indicating no submissions were received.
|
|
1102
|
+
*/
|
|
1103
|
+
private publishNoSubmissionsFeedback;
|
|
1104
|
+
/**
|
|
1105
|
+
* Clears the current timeout timer.
|
|
1106
|
+
*/
|
|
1107
|
+
private clearTimeout;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
/**
|
|
1111
|
+
* Prefix claim handler for the TOON prefix marketplace.
|
|
1112
|
+
*
|
|
1113
|
+
* Creates a handler that processes kind 10034 prefix claim events,
|
|
1114
|
+
* validates payment and prefix availability, and publishes grant
|
|
1115
|
+
* confirmations. Lives in SDK (not core) because it depends on
|
|
1116
|
+
* the SDK's Handler type and HandlerContext interface.
|
|
1117
|
+
*/
|
|
1118
|
+
|
|
1119
|
+
/**
|
|
1120
|
+
* Options for creating a prefix claim handler.
|
|
1121
|
+
*/
|
|
1122
|
+
interface PrefixClaimHandlerOptions {
|
|
1123
|
+
/** Pricing configuration for prefix claims. */
|
|
1124
|
+
prefixPricing: {
|
|
1125
|
+
basePrice: bigint;
|
|
1126
|
+
};
|
|
1127
|
+
/** Secret key for signing grant events. */
|
|
1128
|
+
secretKey: Uint8Array;
|
|
1129
|
+
/** Returns the current map of claimed prefixes (prefix -> claimer pubkey). */
|
|
1130
|
+
getClaimedPrefixes: () => Map<string, string>;
|
|
1131
|
+
/**
|
|
1132
|
+
* Atomically claim a prefix for a pubkey. Returns true if the claim
|
|
1133
|
+
* succeeded, false if the prefix was already taken. This is the
|
|
1134
|
+
* serialization point for race condition defense.
|
|
1135
|
+
*/
|
|
1136
|
+
claimPrefix: (prefix: string, claimerPubkey: string) => boolean;
|
|
1137
|
+
/** Publish the grant event (e.g., to the local relay). */
|
|
1138
|
+
publishGrant: (grantEvent: NostrEvent) => Promise<void>;
|
|
1139
|
+
/** ILP address prefix to include in the grant event (default: 'g.toon'). */
|
|
1140
|
+
ilpAddressPrefix?: string;
|
|
1141
|
+
}
|
|
1142
|
+
/**
|
|
1143
|
+
* Creates a handler for kind 10034 prefix claim events.
|
|
1144
|
+
*
|
|
1145
|
+
* The handler validates payment, prefix availability, and prefix format,
|
|
1146
|
+
* then atomically claims the prefix and publishes a grant confirmation.
|
|
1147
|
+
*
|
|
1148
|
+
* @param options - Handler configuration
|
|
1149
|
+
* @returns A Handler function for kind 10034 events
|
|
1150
|
+
*/
|
|
1151
|
+
declare function createPrefixClaimHandler(options: PrefixClaimHandlerOptions): Handler;
|
|
1152
|
+
|
|
1153
|
+
/**
|
|
1154
|
+
* Arweave upload adapter wrapping @ardrive/turbo-sdk.
|
|
1155
|
+
*
|
|
1156
|
+
* This is the ONLY file that imports @ardrive/turbo-sdk, isolating the
|
|
1157
|
+
* external dependency behind an interface (risk E8-R002).
|
|
1158
|
+
*/
|
|
1159
|
+
/**
|
|
1160
|
+
* Interface for uploading data to Arweave.
|
|
1161
|
+
* Implementations wrap a specific Arweave upload SDK.
|
|
1162
|
+
*/
|
|
1163
|
+
interface ArweaveUploadAdapter {
|
|
1164
|
+
upload(data: Buffer, tags?: Record<string, string>): Promise<{
|
|
1165
|
+
txId: string;
|
|
1166
|
+
}>;
|
|
1167
|
+
}
|
|
1168
|
+
/**
|
|
1169
|
+
* Turbo SDK upload adapter using @ardrive/turbo-sdk.
|
|
1170
|
+
*
|
|
1171
|
+
* - Dev/free tier (<=100KB): pass no turboClient. getClient() lazily generates an
|
|
1172
|
+
* ephemeral RSA JWK and builds a TurboFactory.authenticated() client. The upload
|
|
1173
|
+
* service grants free small-data-item uploads to any valid signer regardless of
|
|
1174
|
+
* balance, so no deposit is required. NOTE: TurboFactory.unauthenticated() is NOT
|
|
1175
|
+
* usable here — in @ardrive/turbo-sdk >=1.40 uploadFile() exists only on the
|
|
1176
|
+
* authenticated client; the unauthenticated client exposes only uploadSignedDataItem().
|
|
1177
|
+
* - Prod (paid, uncapped): pass a TurboAuthenticatedClient from a funded wallet.
|
|
1178
|
+
*
|
|
1179
|
+
* The turboClient is typed as `unknown` to avoid importing @ardrive/turbo-sdk types
|
|
1180
|
+
* in this interface. The actual TurboAuthenticatedClient is duck-typed at runtime.
|
|
1181
|
+
*/
|
|
1182
|
+
declare class TurboUploadAdapter implements ArweaveUploadAdapter {
|
|
1183
|
+
private turboClient;
|
|
1184
|
+
private initialized;
|
|
1185
|
+
constructor(turboClient?: unknown);
|
|
1186
|
+
private getClient;
|
|
1187
|
+
upload(data: Buffer, tags?: Record<string, string>): Promise<{
|
|
1188
|
+
txId: string;
|
|
1189
|
+
}>;
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
/**
|
|
1193
|
+
* Chunk state manager for multi-packet blob uploads.
|
|
1194
|
+
*
|
|
1195
|
+
* Accumulates chunks for a given uploadId, assembles them in order
|
|
1196
|
+
* when all chunks have arrived, and enforces timeout and memory caps.
|
|
1197
|
+
*/
|
|
1198
|
+
interface ChunkManagerConfig {
|
|
1199
|
+
/** Timeout in milliseconds before partial uploads are discarded (default: 300_000 = 5 min). */
|
|
1200
|
+
timeoutMs?: number;
|
|
1201
|
+
/** Maximum number of concurrent active uploads (default: 100). */
|
|
1202
|
+
maxActiveUploads?: number;
|
|
1203
|
+
/** Maximum total bytes accumulated per upload before rejection (default: 50MB). */
|
|
1204
|
+
maxBytesPerUpload?: number;
|
|
1205
|
+
}
|
|
1206
|
+
interface AddChunkResult {
|
|
1207
|
+
/** Whether all chunks have been received and the blob is fully assembled. */
|
|
1208
|
+
complete: boolean;
|
|
1209
|
+
/** The assembled blob (only present when complete is true). */
|
|
1210
|
+
assembled?: Buffer;
|
|
1211
|
+
/** Error message if the chunk was rejected. */
|
|
1212
|
+
error?: string;
|
|
1213
|
+
}
|
|
1214
|
+
/**
|
|
1215
|
+
* Manages chunked upload state for the Arweave DVM handler.
|
|
1216
|
+
*/
|
|
1217
|
+
declare class ChunkManager {
|
|
1218
|
+
private uploads;
|
|
1219
|
+
private readonly timeoutMs;
|
|
1220
|
+
private readonly maxActiveUploads;
|
|
1221
|
+
private readonly maxBytesPerUpload;
|
|
1222
|
+
constructor(config?: ChunkManagerConfig);
|
|
1223
|
+
/**
|
|
1224
|
+
* Add a chunk for a given uploadId.
|
|
1225
|
+
*
|
|
1226
|
+
* @param uploadId - Unique identifier for the upload session.
|
|
1227
|
+
* @param chunkIndex - Zero-based index of this chunk.
|
|
1228
|
+
* @param totalChunks - Total number of chunks expected.
|
|
1229
|
+
* @param data - The chunk data.
|
|
1230
|
+
* @returns Result indicating completion status or error.
|
|
1231
|
+
* @throws Error if memory cap reached or duplicate chunk.
|
|
1232
|
+
*/
|
|
1233
|
+
addChunk(uploadId: string, chunkIndex: number, totalChunks: number, data: Buffer): AddChunkResult;
|
|
1234
|
+
/**
|
|
1235
|
+
* Check if an upload is complete (all chunks received).
|
|
1236
|
+
* Returns false if the uploadId is unknown (cleaned up or never started).
|
|
1237
|
+
*/
|
|
1238
|
+
isComplete(uploadId: string): boolean;
|
|
1239
|
+
/**
|
|
1240
|
+
* Clean up state for a given uploadId, clearing the timeout timer.
|
|
1241
|
+
*/
|
|
1242
|
+
cleanup(uploadId: string): void;
|
|
1243
|
+
/**
|
|
1244
|
+
* Clean up all active uploads and their timers.
|
|
1245
|
+
* Call this on node shutdown to prevent timer leaks.
|
|
1246
|
+
*/
|
|
1247
|
+
destroyAll(): void;
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
/**
|
|
1251
|
+
* Arweave DVM handler for kind:5094 blob storage requests.
|
|
1252
|
+
*
|
|
1253
|
+
* Creates a handler function that:
|
|
1254
|
+
* 1. Parses the kind:5094 event from the HandlerContext
|
|
1255
|
+
* 2. For single-packet uploads: uploads directly to Arweave via the adapter
|
|
1256
|
+
* 3. For chunked uploads: accumulates via ChunkManager, uploads on completion
|
|
1257
|
+
*
|
|
1258
|
+
* The handler does NOT validate pricing -- the SDK pricing validator
|
|
1259
|
+
* (packages/sdk/src/pricing-validator.ts) runs BEFORE the handler is invoked.
|
|
1260
|
+
*
|
|
1261
|
+
* Returns HandlePacketAcceptResponse with `data` field containing the Arweave
|
|
1262
|
+
* tx ID -- NOT via ctx.accept() which only supports metadata.
|
|
1263
|
+
*/
|
|
1264
|
+
|
|
1265
|
+
interface ArweaveDvmConfig {
|
|
1266
|
+
/** Arweave upload adapter (wraps @ardrive/turbo-sdk). */
|
|
1267
|
+
turboAdapter: ArweaveUploadAdapter;
|
|
1268
|
+
/** Chunk state manager for multi-packet uploads. */
|
|
1269
|
+
chunkManager: ChunkManager;
|
|
1270
|
+
/** Optional default Arweave data item tags (e.g., Content-Type). */
|
|
1271
|
+
arweaveTags?: Record<string, string>;
|
|
1272
|
+
}
|
|
1273
|
+
/**
|
|
1274
|
+
* Creates an Arweave DVM handler for kind:5094 blob storage requests.
|
|
1275
|
+
*
|
|
1276
|
+
* @param config - Handler configuration with adapter and chunk manager.
|
|
1277
|
+
* @returns A handler function compatible with HandlerRegistry.on().
|
|
1278
|
+
*/
|
|
1279
|
+
declare function createArweaveDvmHandler(config: ArweaveDvmConfig): (ctx: HandlerContext) => Promise<HandlerResponse>;
|
|
1280
|
+
|
|
1281
|
+
/**
|
|
1282
|
+
* Client-side helpers for uploading blobs to an Arweave DVM provider.
|
|
1283
|
+
*
|
|
1284
|
+
* - uploadBlob(): single-packet upload for blobs under the chunk threshold
|
|
1285
|
+
* - uploadBlobChunked(): multi-packet upload that splits large blobs into chunks
|
|
1286
|
+
*
|
|
1287
|
+
* Both use publishEvent() with the amount override (Story 7.6, D7-007).
|
|
1288
|
+
*/
|
|
1289
|
+
|
|
1290
|
+
/**
|
|
1291
|
+
* Minimal interface for publishing events. Matches ServiceNode.publishEvent().
|
|
1292
|
+
*/
|
|
1293
|
+
interface PublishableNode {
|
|
1294
|
+
publishEvent(event: NostrEvent, options?: {
|
|
1295
|
+
destination: string;
|
|
1296
|
+
amount?: bigint;
|
|
1297
|
+
}): Promise<Pick<PublishEventResult, 'success' | 'eventId' | 'data' | 'message'>>;
|
|
1298
|
+
}
|
|
1299
|
+
/**
|
|
1300
|
+
* Options for single-packet blob upload.
|
|
1301
|
+
*/
|
|
1302
|
+
interface UploadBlobOptions {
|
|
1303
|
+
/** MIME type of the blob (default: 'application/octet-stream'). */
|
|
1304
|
+
contentType?: string;
|
|
1305
|
+
/** Secret key for signing the event. */
|
|
1306
|
+
secretKey: Uint8Array;
|
|
1307
|
+
/** Price per byte in USDC micro-units for amount calculation. */
|
|
1308
|
+
pricePerByte?: bigint;
|
|
1309
|
+
}
|
|
1310
|
+
/**
|
|
1311
|
+
* Options for chunked blob upload.
|
|
1312
|
+
*/
|
|
1313
|
+
interface UploadBlobChunkedOptions {
|
|
1314
|
+
/** Chunk size in bytes (default: 500_000, under 512KB threshold). */
|
|
1315
|
+
chunkSize?: number;
|
|
1316
|
+
/** MIME type of the blob (default: 'application/octet-stream'). */
|
|
1317
|
+
contentType?: string;
|
|
1318
|
+
/** Secret key for signing events. */
|
|
1319
|
+
secretKey: Uint8Array;
|
|
1320
|
+
/** Price per byte in USDC micro-units for amount calculation. */
|
|
1321
|
+
pricePerByte?: bigint;
|
|
1322
|
+
}
|
|
1323
|
+
/**
|
|
1324
|
+
* Upload a blob to an Arweave DVM provider in a single ILP packet.
|
|
1325
|
+
*
|
|
1326
|
+
* Uses publishEvent() with amount override (D7-007) to send the blob
|
|
1327
|
+
* and payment in one ILP PREPARE.
|
|
1328
|
+
*
|
|
1329
|
+
* @param node - The ServiceNode (or compatible) to publish through.
|
|
1330
|
+
* @param blob - The raw blob data to upload.
|
|
1331
|
+
* @param destination - The provider's ILP address.
|
|
1332
|
+
* @param options - Upload options including secretKey for signing.
|
|
1333
|
+
* @returns The Arweave transaction ID from the FULFILL data field.
|
|
1334
|
+
*/
|
|
1335
|
+
declare function uploadBlob(node: PublishableNode, blob: Buffer, destination: string, options: UploadBlobOptions): Promise<string>;
|
|
1336
|
+
/**
|
|
1337
|
+
* Upload a large blob to an Arweave DVM provider using chunked uploads.
|
|
1338
|
+
*
|
|
1339
|
+
* Splits the blob into chunks, each sent as a separate kind:5094 ILP PREPARE
|
|
1340
|
+
* with uploadId, chunkIndex, and totalChunks params. Each chunk carries its
|
|
1341
|
+
* own payment. The final chunk's FULFILL data contains the Arweave tx ID.
|
|
1342
|
+
*
|
|
1343
|
+
* @param node - The ServiceNode (or compatible) to publish through.
|
|
1344
|
+
* @param blob - The raw blob data to upload.
|
|
1345
|
+
* @param destination - The provider's ILP address.
|
|
1346
|
+
* @param options - Chunked upload options including secretKey for signing.
|
|
1347
|
+
* @returns The Arweave transaction ID from the final chunk's FULFILL data.
|
|
1348
|
+
*/
|
|
1349
|
+
declare function uploadBlobChunked(node: PublishableNode, blob: Buffer, destination: string, options: UploadBlobChunkedOptions): Promise<string>;
|
|
1350
|
+
|
|
1351
|
+
/**
|
|
1352
|
+
* Mill Swap Handler (Story 12.3)
|
|
1353
|
+
*
|
|
1354
|
+
* `createSwapHandler()` factory produces a kind:1059 `Handler` that:
|
|
1355
|
+
* 1. Unwraps an incoming NIP-59 gift-wrapped ILP swap packet (via Story 12.2).
|
|
1356
|
+
* 2. Identifies the requested `SwapPair` from inner-rumor `swap-from` / `swap-to` tags.
|
|
1357
|
+
* 3. Applies a per-packet exchange rate (pair.rate or live rateProvider hook).
|
|
1358
|
+
* 4. Delegates signed claim issuance to a pluggable `ClaimIssuer` (Story 12.4).
|
|
1359
|
+
* 5. NIP-44 encrypts the claim with an ephemeral key (Story 12.2) for return.
|
|
1360
|
+
*
|
|
1361
|
+
* The handler is a pure application-layer composition — no connector, routing,
|
|
1362
|
+
* or wallet code lives here. See `_bmad-output/epics/epic-12-token-swap-primitive.md`
|
|
1363
|
+
* for D12-001/D12-008/D12-009/D12-010 and the scope fence.
|
|
1364
|
+
*
|
|
1365
|
+
* Transport encoding: the `accept()` metadata emits `claim` as a base64-encoded
|
|
1366
|
+
* NIP-44 ciphertext, `ephemeralPubkey` as 64-char lowercase hex, and optional
|
|
1367
|
+
* `claimId`. The sender-side `streamSwap()` (Story 12.5) base64-decodes `claim`
|
|
1368
|
+
* before calling `decryptFulfillClaim`.
|
|
1369
|
+
*
|
|
1370
|
+
* @module
|
|
1371
|
+
*/
|
|
1372
|
+
|
|
1373
|
+
/** Parameters passed to a {@link ClaimIssuer.issueClaim} call. */
|
|
1374
|
+
interface IssueClaimParams {
|
|
1375
|
+
/** Source-asset amount received by the Mill (ILP packet amount, source micro-units). */
|
|
1376
|
+
sourceAmount: bigint;
|
|
1377
|
+
/** Target-asset amount owed to the sender (post-rate-conversion, target micro-units). */
|
|
1378
|
+
targetAmount: bigint;
|
|
1379
|
+
/** The `SwapPair` this packet is being priced against. */
|
|
1380
|
+
pair: SwapPair;
|
|
1381
|
+
/**
|
|
1382
|
+
* The sender's real Nostr pubkey (extracted from the unwrapped seal).
|
|
1383
|
+
*
|
|
1384
|
+
* Identity-layer key only: used by the Mill for inventory ledger keying and
|
|
1385
|
+
* the sender→channel sticky binding (`channelState.reserve()` /
|
|
1386
|
+
* `channelState.release()`). The Mill MUST NOT pass this to chain-layer
|
|
1387
|
+
* signers as the balance-proof `recipient` — use {@link chainRecipient}
|
|
1388
|
+
* for that (Story 12.9 D12-011).
|
|
1389
|
+
*/
|
|
1390
|
+
senderPubkey: string;
|
|
1391
|
+
/**
|
|
1392
|
+
* The sender's chain-specific payout address for `pair.to.chain`
|
|
1393
|
+
* (Story 12.9 AC-10). Extracted and format-validated from the rumor's
|
|
1394
|
+
* `chain-recipient` tag by the swap handler. REQUIRED. This is the
|
|
1395
|
+
* address the Mill's `PaymentChannelSigner` MUST use as the balance-proof
|
|
1396
|
+
* `recipient` (e.g., 20-byte EVM address, 32-byte Solana Ed25519 pubkey).
|
|
1397
|
+
*/
|
|
1398
|
+
chainRecipient: string;
|
|
1399
|
+
/** The inner rumor (for optional Mill-side context; may be ignored by the issuer). */
|
|
1400
|
+
rumor: UnsignedEvent;
|
|
1401
|
+
}
|
|
1402
|
+
/**
|
|
1403
|
+
* Result returned from {@link ClaimIssuer.issueClaim}.
|
|
1404
|
+
*
|
|
1405
|
+
* Story 12.6 extension: additive settlement-context fields let the sender
|
|
1406
|
+
* reconstruct the balance-proof message hash for signature verification and
|
|
1407
|
+
* on-chain settlement (see `buildSettlementTx()`).
|
|
1408
|
+
*/
|
|
1409
|
+
interface IssueClaimResult {
|
|
1410
|
+
/** Signed claim bytes ready for NIP-44 encryption (chain-specific format). */
|
|
1411
|
+
claim: Uint8Array;
|
|
1412
|
+
/** Optional Mill-side claim ID for logging/tracing. */
|
|
1413
|
+
claimId?: string;
|
|
1414
|
+
/** Channel identifier on the target chain. */
|
|
1415
|
+
channelId?: string;
|
|
1416
|
+
/** Balance-proof nonce (monotonically increasing per channel). */
|
|
1417
|
+
nonce?: bigint;
|
|
1418
|
+
/** Cumulative transferred amount on the channel (target micro-units). */
|
|
1419
|
+
cumulativeAmount?: bigint;
|
|
1420
|
+
/** Recipient address (the sender's target-asset address). */
|
|
1421
|
+
recipient?: string;
|
|
1422
|
+
/** Mill's on-chain signer address. */
|
|
1423
|
+
millSignerAddress?: string;
|
|
1424
|
+
}
|
|
1425
|
+
/**
|
|
1426
|
+
* Pluggable signed-claim issuer. Story 12.3 defines only the contract — the
|
|
1427
|
+
* concrete multi-chain implementation ships in Story 12.4.
|
|
1428
|
+
*
|
|
1429
|
+
* The issuer owns inventory accounting and signing-key material. The handler
|
|
1430
|
+
* relies on `issueClaim()` being atomic with inventory debit: if the call
|
|
1431
|
+
* resolves, the target-asset amount MUST be considered committed from the
|
|
1432
|
+
* Mill's reserves. If the call throws, no inventory change SHOULD have occurred.
|
|
1433
|
+
*/
|
|
1434
|
+
interface ClaimIssuer {
|
|
1435
|
+
/**
|
|
1436
|
+
* Produce a signed off-chain payment-channel claim in the target asset.
|
|
1437
|
+
*
|
|
1438
|
+
* @throws Error (or subclass) on insufficient reserves, unsupported pair,
|
|
1439
|
+
* or signing failure. Errors with `code === 'INSUFFICIENT_INVENTORY'` or
|
|
1440
|
+
* messages matching `/insufficient/i` are surfaced as ILP T04; all other
|
|
1441
|
+
* errors as T00.
|
|
1442
|
+
*/
|
|
1443
|
+
issueClaim(params: IssueClaimParams): Promise<IssueClaimResult>;
|
|
1444
|
+
}
|
|
1445
|
+
/** Parameters for {@link applyRate}. */
|
|
1446
|
+
interface ApplyRateParams {
|
|
1447
|
+
/** Source amount in source micro-units. */
|
|
1448
|
+
sourceAmount: bigint;
|
|
1449
|
+
/** `SwapPair.from.assetScale` (number of decimals on source side). */
|
|
1450
|
+
fromScale: number;
|
|
1451
|
+
/** `SwapPair.to.assetScale` (number of decimals on target side). */
|
|
1452
|
+
toScale: number;
|
|
1453
|
+
/** Decimal-string rate (target whole-units per source whole-unit). */
|
|
1454
|
+
rate: string;
|
|
1455
|
+
}
|
|
1456
|
+
/** Minimal pino-compatible logger interface. */
|
|
1457
|
+
interface SwapHandlerLogger {
|
|
1458
|
+
debug: (...args: unknown[]) => void;
|
|
1459
|
+
info: (...args: unknown[]) => void;
|
|
1460
|
+
warn: (...args: unknown[]) => void;
|
|
1461
|
+
error: (...args: unknown[]) => void;
|
|
1462
|
+
}
|
|
1463
|
+
/**
|
|
1464
|
+
* Minimal `Set`-like contract the handler requires from
|
|
1465
|
+
* `seenPacketIds`. Both the native `Set<string>` and
|
|
1466
|
+
* {@link BoundedSeenPacketIds} satisfy this; operators can swap in a
|
|
1467
|
+
* persistent/remote-backed replacement too.
|
|
1468
|
+
*/
|
|
1469
|
+
interface SeenPacketIdsLike {
|
|
1470
|
+
has(value: string): boolean;
|
|
1471
|
+
add(value: string): unknown;
|
|
1472
|
+
delete(value: string): boolean;
|
|
1473
|
+
}
|
|
1474
|
+
/** Configuration for {@link createSwapHandler}. */
|
|
1475
|
+
interface CreateSwapHandlerConfig {
|
|
1476
|
+
/** Mill's secp256k1 secret key for unwrapping gift-wrapped packets (32 bytes). */
|
|
1477
|
+
recipientSecretKey: Uint8Array;
|
|
1478
|
+
/** Swap pairs this Mill currently supports. */
|
|
1479
|
+
swapPairs: SwapPair[];
|
|
1480
|
+
/** Claim issuer delegate (Story 12.4 plugs in the multi-chain implementation). */
|
|
1481
|
+
claimIssuer: ClaimIssuer;
|
|
1482
|
+
/**
|
|
1483
|
+
* Optional live-rate override hook. When provided, the handler calls this per
|
|
1484
|
+
* packet instead of reading `pair.rate`. MUST return a decimal string matching
|
|
1485
|
+
* `SwapPair.rate` format: /^(0|[1-9]\d*)(\.\d+)?$/.
|
|
1486
|
+
*/
|
|
1487
|
+
rateProvider?: (pair: SwapPair) => string | Promise<string>;
|
|
1488
|
+
/**
|
|
1489
|
+
* Optional replay-protection set. When provided, the handler uses it
|
|
1490
|
+
* VERBATIM (operator-owned — bounding/persistence is the operator's
|
|
1491
|
+
* responsibility). When OMITTED (Story 12.8 AC-14), the handler
|
|
1492
|
+
* defaults to a {@link BoundedSeenPacketIds} with cap
|
|
1493
|
+
* {@link DEFAULT_SEEN_PACKET_IDS_CAP}. Any `Set`-shaped object with
|
|
1494
|
+
* `has`/`add`/`delete` (and a `size` getter for test introspection)
|
|
1495
|
+
* satisfies the contract.
|
|
1496
|
+
*/
|
|
1497
|
+
seenPacketIds?: SeenPacketIdsLike;
|
|
1498
|
+
/** Optional pino-compatible logger. Defaults to a no-op logger. */
|
|
1499
|
+
logger?: SwapHandlerLogger;
|
|
1500
|
+
}
|
|
1501
|
+
/**
|
|
1502
|
+
* ILP REJECT codes emitted by `createSwapHandler()`.
|
|
1503
|
+
*
|
|
1504
|
+
* Exported as named constants so tests (Story 12.8 AC-3 forbids hardcoded
|
|
1505
|
+
* error-code strings) and downstream integrators can assert against the
|
|
1506
|
+
* same symbolic source the handler uses. Values follow RFC 27 / ILPv4
|
|
1507
|
+
* reject-code conventions (F01 = malformed, F02 = unreachable, F04 =
|
|
1508
|
+
* duplicate, F06 = unsupported pair, T00 = transient internal, T04 =
|
|
1509
|
+
* insufficient liquidity).
|
|
1510
|
+
*/
|
|
1511
|
+
declare const SWAP_HANDLER_REJECT_CODES: {
|
|
1512
|
+
/** Malformed / invalid PREPARE content — gift-wrap shape or amount invalid. */
|
|
1513
|
+
readonly INVALID_GIFT_WRAP: "F01";
|
|
1514
|
+
/** No route — the handler did not match a registered destination. */
|
|
1515
|
+
readonly UNREACHABLE: "F02";
|
|
1516
|
+
/** Duplicate packet — `seenPacketIds` replay hit. */
|
|
1517
|
+
readonly DUPLICATE_PACKET: "F04";
|
|
1518
|
+
/** Requested swap pair is not advertised by this Mill. */
|
|
1519
|
+
readonly UNSUPPORTED_PAIR: "F06";
|
|
1520
|
+
/** Transient internal failure — signing, rate provider, or unexpected. */
|
|
1521
|
+
readonly INTERNAL: "T00";
|
|
1522
|
+
/** Insufficient Mill inventory for the requested amount. */
|
|
1523
|
+
readonly INSUFFICIENT_LIQUIDITY: "T04";
|
|
1524
|
+
};
|
|
1525
|
+
/**
|
|
1526
|
+
* Human-readable reject messages emitted by `createSwapHandler()`.
|
|
1527
|
+
*
|
|
1528
|
+
* Tests may assert against these verbatim rather than matching regexes
|
|
1529
|
+
* (Story 12.8 AC-3 guidance).
|
|
1530
|
+
*/
|
|
1531
|
+
declare const SWAP_HANDLER_REJECT_MESSAGES: {
|
|
1532
|
+
readonly INVALID_GIFT_WRAP: "Invalid gift wrap";
|
|
1533
|
+
readonly INVALID_AMOUNT: "Invalid amount";
|
|
1534
|
+
readonly UNREACHABLE: "Unreachable";
|
|
1535
|
+
readonly DUPLICATE_PACKET: "Duplicate packet";
|
|
1536
|
+
readonly UNSUPPORTED_PAIR: "Unsupported swap pair";
|
|
1537
|
+
readonly INTERNAL: "Internal error";
|
|
1538
|
+
readonly INSUFFICIENT_LIQUIDITY: "Insufficient liquidity";
|
|
1539
|
+
readonly RATE_PROVIDER: "Rate provider error";
|
|
1540
|
+
readonly RATE_CONVERSION: "Rate conversion error";
|
|
1541
|
+
};
|
|
1542
|
+
/**
|
|
1543
|
+
* Apply a decimal-string exchange rate to a source amount across asset scales.
|
|
1544
|
+
* Uses BigInt arithmetic throughout — never coerces to `Number` — to preserve
|
|
1545
|
+
* 18-decimal EVM precision (Epic 11 retro MAX_SAFE_INTEGER guard).
|
|
1546
|
+
*
|
|
1547
|
+
* Rounds toward zero (integer division), which economically favors the Mill
|
|
1548
|
+
* (standard market-maker convention).
|
|
1549
|
+
*
|
|
1550
|
+
* @throws {SwapHandlerError} If rate format is invalid, rate is zero, or
|
|
1551
|
+
* sourceAmount is not positive.
|
|
1552
|
+
*/
|
|
1553
|
+
declare function applyRate(params: ApplyRateParams): bigint;
|
|
1554
|
+
/**
|
|
1555
|
+
* Find the `SwapPair` identified by the rumor's `swap-from` / `swap-to` tags.
|
|
1556
|
+
*
|
|
1557
|
+
* Each tag value is parsed as `<assetCode>:<chain>`, split on the FIRST `:`
|
|
1558
|
+
* so multi-segment chain IDs like `evm:base:8453` remain intact as the chain
|
|
1559
|
+
* portion. Returns `null` for any malformed/missing tag — the handler
|
|
1560
|
+
* interprets `null` as "unsupported pair" and rejects via ILP F06.
|
|
1561
|
+
*/
|
|
1562
|
+
declare function findSwapPair(rumor: UnsignedEvent, pairs: SwapPair[]): SwapPair | null;
|
|
1563
|
+
/**
|
|
1564
|
+
* Construct a kind:1059 Mill inbound-swap handler.
|
|
1565
|
+
*
|
|
1566
|
+
* The returned `Handler` is a pure closure over `config`; two calls with the
|
|
1567
|
+
* same config yield two independent-but-equivalent handlers. Register via
|
|
1568
|
+
* `node.handlers.on(1059, handler)` (Story 12.7).
|
|
1569
|
+
*
|
|
1570
|
+
* @throws {SwapHandlerError} At construction time if config is malformed.
|
|
1571
|
+
*/
|
|
1572
|
+
declare function createSwapHandler(config: CreateSwapHandlerConfig): Handler;
|
|
1573
|
+
|
|
1574
|
+
/**
|
|
1575
|
+
* Mina-specific settlement: balance-proof signature verification +
|
|
1576
|
+
* settlement-bundle construction (Story 12.8 follow-up to 12.6 AC-9).
|
|
1577
|
+
*
|
|
1578
|
+
* ## What is implemented (and unit-tested)
|
|
1579
|
+
*
|
|
1580
|
+
* - {@link verifyMinaSignature}: verifies the Mill's off-chain balance-proof
|
|
1581
|
+
* signature using `mina-signer` (`verifyFields`). This is the EXACT inverse
|
|
1582
|
+
* of the Mill's {@link MinaPaymentChannelSigner} (`packages/mill/src/payment-channel-signer.ts`),
|
|
1583
|
+
* which signs `balanceProofFieldsMina(channelId, cumulativeAmount, nonce, recipient)`
|
|
1584
|
+
* via `mina-signer`'s `signFields` and emits the base58 signature string as
|
|
1585
|
+
* the claim's `claimBytes` (UTF-8). The field-element derivation lives in
|
|
1586
|
+
* `hashes.ts` so signer and verifier cannot drift (same single-source-of-
|
|
1587
|
+
* truth pattern as EVM/Solana).
|
|
1588
|
+
* - {@link buildMinaSettlementTx}: constructs a {@link SettlementBundle}
|
|
1589
|
+
* envelope (chain metadata + the verified balance proof bytes) so a Chain
|
|
1590
|
+
* Bridge DVM / direct sender has everything needed to drive the on-chain
|
|
1591
|
+
* claim. The signature is re-emitted verbatim in `unsignedTxBytes`.
|
|
1592
|
+
*
|
|
1593
|
+
* ## What remains (documented gap — NOT silently stubbed)
|
|
1594
|
+
*
|
|
1595
|
+
* The final on-chain step — submitting a Mina zkApp `claimFromChannel`
|
|
1596
|
+
* transaction that settles the channel — requires **o1js circuit compilation
|
|
1597
|
+
* + zk-SNARK proof generation** (Poseidon balance-commitment, zkApp method
|
|
1598
|
+
* proving). The connector already implements this in
|
|
1599
|
+
* `MinaPaymentChannelSDK.claimFromChannel()` (o1js, heavyweight). That proof
|
|
1600
|
+
* generation is intentionally NOT done here: o1js circuit compilation is far
|
|
1601
|
+
* too heavy for a unit-testable SDK helper and would pull a multi-hundred-MB
|
|
1602
|
+
* WASM dependency into every SDK consumer. Instead, the bundle carries the
|
|
1603
|
+
* verified balance proof so a Mina-capable settler (the connector's
|
|
1604
|
+
* `MinaPaymentChannelProvider`, or a future o1js-backed Chain Bridge DVM) can
|
|
1605
|
+
* generate the proof + broadcast. See the on-chain settlement note below
|
|
1606
|
+
* (connector 3.8.1 wires the dual-party claim path — connector#84).
|
|
1607
|
+
*
|
|
1608
|
+
* Note also: the Mill↔sender wire proof here (a Schnorr signature over four
|
|
1609
|
+
* field elements) is a DIFFERENT object than the connector's on-chain
|
|
1610
|
+
* `MinaPaymentChannelSDK` Poseidon-commitment proof shape
|
|
1611
|
+
* (`{ commitment, signature, nonce }`). The verifier matches the Mill's
|
|
1612
|
+
* actual emitted format (`MinaPaymentChannelSigner`), which is what a sender
|
|
1613
|
+
* receives on-wire.
|
|
1614
|
+
*
|
|
1615
|
+
* @module
|
|
1616
|
+
* @since 12.8
|
|
1617
|
+
*/
|
|
1618
|
+
|
|
1619
|
+
/**
|
|
1620
|
+
* Minimal structural type for the slice of the `mina-signer` `Client` we use.
|
|
1621
|
+
* Declared locally so the SDK does not hard-depend on the optional peer dep's
|
|
1622
|
+
* full type surface (the ambient `mina-signer.d.ts` only declares
|
|
1623
|
+
* `derivePublicKey`). `verifyFields` is synchronous.
|
|
1624
|
+
*/
|
|
1625
|
+
interface MinaSignerClientLike {
|
|
1626
|
+
verifyFields(input: {
|
|
1627
|
+
data: bigint[];
|
|
1628
|
+
signature: string;
|
|
1629
|
+
publicKey: string;
|
|
1630
|
+
}): boolean;
|
|
1631
|
+
}
|
|
1632
|
+
/**
|
|
1633
|
+
* Lazily load `mina-signer` (optional peer dep) and instantiate a `Client`
|
|
1634
|
+
* bound to {@link MINA_NETWORK}. Returns `undefined` when the peer dep is not
|
|
1635
|
+
* installed — callers MUST treat that as "cannot verify Mina claims" rather
|
|
1636
|
+
* than "claim is valid".
|
|
1637
|
+
*
|
|
1638
|
+
* Mirrors the dynamic-import pattern in `identity.ts` (`deriveMinaIdentity`).
|
|
1639
|
+
*
|
|
1640
|
+
* @since 12.8
|
|
1641
|
+
*/
|
|
1642
|
+
declare function loadMinaSignerClient(): Promise<MinaSignerClientLike | undefined>;
|
|
1643
|
+
/**
|
|
1644
|
+
* Verify a Mina balance-proof Schnorr signature carried in an
|
|
1645
|
+
* `AccumulatedClaim`.
|
|
1646
|
+
*
|
|
1647
|
+
* Re-derives the signed field-element message via {@link balanceProofFieldsMina}
|
|
1648
|
+
* (identical to the Mill signer), decodes the claim's `claimBytes` to the
|
|
1649
|
+
* base58 signature string the Mill emitted, and verifies it against
|
|
1650
|
+
* `expectedSignerAddress` using a `mina-signer` `Client`.
|
|
1651
|
+
*
|
|
1652
|
+
* `client` MUST be a pre-loaded `mina-signer` `Client` (see
|
|
1653
|
+
* {@link loadMinaSignerClient}). It is injected (rather than imported inline)
|
|
1654
|
+
* so the synchronous `buildSettlementTx()` pipeline can verify Mina claims
|
|
1655
|
+
* without becoming async.
|
|
1656
|
+
*
|
|
1657
|
+
* @returns `true` iff the signature is valid for the given signer address.
|
|
1658
|
+
* @throws {SettlementTxError} on missing settlement metadata or a malformed
|
|
1659
|
+
* (non-UTF-8 / empty) signature payload.
|
|
1660
|
+
* @since 12.8
|
|
1661
|
+
*/
|
|
1662
|
+
declare function verifyMinaSignature(claim: AccumulatedClaim, expectedSignerAddress: string, client: MinaSignerClientLike): boolean;
|
|
1663
|
+
|
|
1664
|
+
/**
|
|
1665
|
+
* Public types for `buildSettlementTx()` (Story 12.6).
|
|
1666
|
+
*
|
|
1667
|
+
* @module
|
|
1668
|
+
* @since 12.6
|
|
1669
|
+
* @see _bmad-output/implementation-artifacts/12-6-build-settlement-tx.md
|
|
1670
|
+
*/
|
|
1671
|
+
|
|
1672
|
+
/**
|
|
1673
|
+
* Chain-specific raw settlement transaction bundle, produced by
|
|
1674
|
+
* `buildSettlementTx()`. Contains everything a Chain Bridge DVM
|
|
1675
|
+
* (Epic 13, kind:5260) or a direct sender needs to submit the settlement
|
|
1676
|
+
* on-chain.
|
|
1677
|
+
*
|
|
1678
|
+
* @stable — Epic 13 Chain Bridge DVM depends on this shape.
|
|
1679
|
+
* @since 12.6
|
|
1680
|
+
*/
|
|
1681
|
+
interface SettlementBundle {
|
|
1682
|
+
/** Target chain identifier (e.g., `'evm:8453'`, `'evm:42161'`, `'solana:mainnet'`, `'mina:mainnet'`). */
|
|
1683
|
+
chain: string;
|
|
1684
|
+
/** Chain family — drives per-chain parsing. */
|
|
1685
|
+
chainKind: 'evm' | 'solana' | 'mina';
|
|
1686
|
+
/** Channel identifier on the target chain (lowercase hex with 0x prefix for EVM; base58 for Solana). */
|
|
1687
|
+
channelId: string;
|
|
1688
|
+
/** Cumulative transferred amount settled by this tx (target micro-units, decimal string). */
|
|
1689
|
+
cumulativeAmount: string;
|
|
1690
|
+
/** Balance-proof nonce settled by this tx (decimal string). */
|
|
1691
|
+
nonce: string;
|
|
1692
|
+
/** Recipient address (the sender's target-asset address — the one that will receive funds). */
|
|
1693
|
+
recipient: string;
|
|
1694
|
+
/** Mill's on-chain signer address (expected signer of the balance-proof signature). */
|
|
1695
|
+
millSignerAddress: string;
|
|
1696
|
+
/**
|
|
1697
|
+
* Raw UNSIGNED transaction bytes ready for the caller to sign (or for a
|
|
1698
|
+
* Chain Bridge DVM to gas-sponsor + sign). EVM: RLP-encoded tx with
|
|
1699
|
+
* placeholder gas fields (tx nonce / gasPrice / gasLimit = 0) per EIP-155.
|
|
1700
|
+
* Solana: serialized Message (not Transaction — Transaction requires signatures).
|
|
1701
|
+
* Mina: the verified balance-proof signature bytes (envelope). The final
|
|
1702
|
+
* on-chain `claimFromChannel` zkApp tx requires o1js proof generation and is
|
|
1703
|
+
* produced by a Mina-capable settler — see the on-chain settlement note in
|
|
1704
|
+
* `packages/sdk/src/settlement/mina.ts` (connector 3.8.1 wires the dual-party
|
|
1705
|
+
* claim path — connector#84).
|
|
1706
|
+
*/
|
|
1707
|
+
unsignedTxBytes: Uint8Array;
|
|
1708
|
+
/**
|
|
1709
|
+
* Expected on-chain event signature (hex, 0x-prefixed keccak256 for EVM)
|
|
1710
|
+
* so a Chain Bridge DVM can watch for confirmation. Optional for
|
|
1711
|
+
* non-EVM chains that lack topic-based event signatures.
|
|
1712
|
+
*/
|
|
1713
|
+
expectedEventSignature?: string;
|
|
1714
|
+
/**
|
|
1715
|
+
* Number of `AccumulatedClaim` inputs in THIS bundle's `(chain, channelId)`
|
|
1716
|
+
* group that survived signature verification.
|
|
1717
|
+
*/
|
|
1718
|
+
claimsMerged: number;
|
|
1719
|
+
/** Index of the winning claim in the ORIGINAL input array (`BuildSettlementTxParams.claims`). */
|
|
1720
|
+
selectedClaimIndex: number;
|
|
1721
|
+
/** Source-asset chain of the SwapPair (for Chain Bridge bill-back). */
|
|
1722
|
+
sourceChain: string;
|
|
1723
|
+
/** Source-asset code of the SwapPair (for Chain Bridge bill-back). */
|
|
1724
|
+
sourceAssetCode: string;
|
|
1725
|
+
}
|
|
1726
|
+
/**
|
|
1727
|
+
* Per-chain Mill signer configuration.
|
|
1728
|
+
*
|
|
1729
|
+
* @since 12.6
|
|
1730
|
+
*/
|
|
1731
|
+
interface MillSignerConfig {
|
|
1732
|
+
/**
|
|
1733
|
+
* Expected on-chain signer address for the Mill. EVM: 0x + 40 lowercase
|
|
1734
|
+
* hex chars. Solana: base58-encoded 32-byte Ed25519 pubkey. Mina: base58 pubkey.
|
|
1735
|
+
*/
|
|
1736
|
+
address: string;
|
|
1737
|
+
/**
|
|
1738
|
+
* On-chain payment-channel contract address (EVM-only).
|
|
1739
|
+
*/
|
|
1740
|
+
contractAddress?: string;
|
|
1741
|
+
/**
|
|
1742
|
+
* Solana on-chain program ID. Required for Solana claims.
|
|
1743
|
+
*/
|
|
1744
|
+
programId?: string;
|
|
1745
|
+
/**
|
|
1746
|
+
* EVM chain-id (decimal). Required for EVM claims — baked into RLP per EIP-155.
|
|
1747
|
+
*/
|
|
1748
|
+
chainId?: number;
|
|
1749
|
+
}
|
|
1750
|
+
/**
|
|
1751
|
+
* Parameters for `buildSettlementTx()`.
|
|
1752
|
+
*
|
|
1753
|
+
* @stable — Epic 13 Chain Bridge DVM depends on this shape.
|
|
1754
|
+
* @since 12.6
|
|
1755
|
+
*/
|
|
1756
|
+
interface BuildSettlementTxParams {
|
|
1757
|
+
/** Claims to settle. Typically `streamSwapResult.claims`. MUST be non-empty. */
|
|
1758
|
+
claims: readonly AccumulatedClaim[];
|
|
1759
|
+
/** Per-chain Mill signer configuration. Keyed by `claim.pair.to.chain`. */
|
|
1760
|
+
signers: Record<string, MillSignerConfig>;
|
|
1761
|
+
/** Sender's target-asset address per chain. Keyed by `claim.pair.to.chain`. */
|
|
1762
|
+
recipients: Record<string, string>;
|
|
1763
|
+
/** When `true` (default), verify every claim's signature against `signers[chain].address`. */
|
|
1764
|
+
verifySignatures?: boolean;
|
|
1765
|
+
/**
|
|
1766
|
+
* Pre-loaded `mina-signer` `Client` (optional peer dep). REQUIRED to verify
|
|
1767
|
+
* `mina:*` claims when `verifySignatures` is on: `buildSettlementTx()` is
|
|
1768
|
+
* synchronous and `mina-signer` only loads via async `import()`, so the
|
|
1769
|
+
* caller must load it up front (see `loadMinaSignerClient()`) and inject it
|
|
1770
|
+
* here. When a `mina:*` claim is present and this is absent, that claim is
|
|
1771
|
+
* rejected with `MINA_VERIFICATION_UNSUPPORTED` rather than passed through
|
|
1772
|
+
* unverified. Ignored for EVM/Solana claims.
|
|
1773
|
+
*/
|
|
1774
|
+
minaSignerClient?: MinaSignerClientLike;
|
|
1775
|
+
/** When `true`, include superseded claims in `result.superseded[]`. Default false. */
|
|
1776
|
+
includeSuperseded?: boolean;
|
|
1777
|
+
/** Optional pino-compatible logger. */
|
|
1778
|
+
logger?: {
|
|
1779
|
+
debug: (...a: unknown[]) => void;
|
|
1780
|
+
info: (...a: unknown[]) => void;
|
|
1781
|
+
warn: (...a: unknown[]) => void;
|
|
1782
|
+
error: (...a: unknown[]) => void;
|
|
1783
|
+
};
|
|
1784
|
+
}
|
|
1785
|
+
/**
|
|
1786
|
+
* Result of `buildSettlementTx()`.
|
|
1787
|
+
*
|
|
1788
|
+
* @stable — Epic 13 Chain Bridge DVM depends on this shape.
|
|
1789
|
+
* @since 12.6
|
|
1790
|
+
*/
|
|
1791
|
+
interface BuildSettlementTxResult {
|
|
1792
|
+
/** One bundle per unique (chain, channelId) group that had at least one surviving claim. */
|
|
1793
|
+
bundles: SettlementBundle[];
|
|
1794
|
+
/** Claims rejected during signature verification. */
|
|
1795
|
+
rejected: {
|
|
1796
|
+
claim: AccumulatedClaim;
|
|
1797
|
+
reason: 'SIGNATURE_INVALID' | 'SIGNER_MISMATCH' | 'MINA_VERIFICATION_UNSUPPORTED';
|
|
1798
|
+
details?: string;
|
|
1799
|
+
}[];
|
|
1800
|
+
/** Claims superseded by a higher-nonce claim in the same group (only populated if params.includeSuperseded). */
|
|
1801
|
+
superseded: AccumulatedClaim[];
|
|
1802
|
+
}
|
|
1803
|
+
|
|
1804
|
+
/**
|
|
1805
|
+
* EVM-specific settlement tx construction + signature verification
|
|
1806
|
+
* (Story 12.6 AC-7).
|
|
1807
|
+
*
|
|
1808
|
+
* @module
|
|
1809
|
+
* @since 12.6
|
|
1810
|
+
* @see _bmad-output/implementation-artifacts/12-6-build-settlement-tx.md
|
|
1811
|
+
*/
|
|
1812
|
+
|
|
1813
|
+
/**
|
|
1814
|
+
* Re-encode an EVM settlement bundle's RLP with real tx-nonce / gasPrice /
|
|
1815
|
+
* gasLimit values. The `to`, `value`, `data`, `chainId` fields are preserved
|
|
1816
|
+
* from the original bundle.
|
|
1817
|
+
*
|
|
1818
|
+
* @stable
|
|
1819
|
+
* @since 12.6
|
|
1820
|
+
*/
|
|
1821
|
+
declare function fillEvmSettlementTxGas(bundle: SettlementBundle, gas: {
|
|
1822
|
+
nonce: bigint;
|
|
1823
|
+
gasPrice: bigint;
|
|
1824
|
+
gasLimit: bigint;
|
|
1825
|
+
}, signer: MillSignerConfig): Uint8Array;
|
|
1826
|
+
|
|
1827
|
+
/**
|
|
1828
|
+
* `buildSettlementTx()` — public entrypoint for Story 12.6.
|
|
1829
|
+
*
|
|
1830
|
+
* Takes the output `claims` array from `streamSwap()` + per-chain signer
|
|
1831
|
+
* config + per-chain recipient addresses, and produces one
|
|
1832
|
+
* {@link SettlementBundle} per unique `(chain, channelId)` group.
|
|
1833
|
+
*
|
|
1834
|
+
* @module
|
|
1835
|
+
* @since 12.6
|
|
1836
|
+
* @see _bmad-output/implementation-artifacts/12-6-build-settlement-tx.md
|
|
1837
|
+
*/
|
|
1838
|
+
|
|
1839
|
+
/**
|
|
1840
|
+
* Build raw unsigned settlement transactions from a bag of accumulated
|
|
1841
|
+
* swap claims.
|
|
1842
|
+
*
|
|
1843
|
+
* Algorithm:
|
|
1844
|
+
* 1. Validate params (synchronous throws on malformed input).
|
|
1845
|
+
* 2. Optionally verify each claim's signature. Rejected claims land in
|
|
1846
|
+
* `result.rejected[]` and are dropped from further processing.
|
|
1847
|
+
* 3. Group surviving claims by `(chain, channelId)`. Within each group,
|
|
1848
|
+
* assert recipient + millSignerAddress consensus, unique nonces, and
|
|
1849
|
+
* non-decreasing cumulativeAmount with nonce.
|
|
1850
|
+
* 4. Pick the winning claim per group (highest nonce).
|
|
1851
|
+
* 5. Dispatch each winner to its chain-specific tx builder.
|
|
1852
|
+
*
|
|
1853
|
+
* @stable
|
|
1854
|
+
* @since 12.6
|
|
1855
|
+
* @throws {SettlementTxError} Synchronously on malformed input, group-level
|
|
1856
|
+
* inconsistency, or chain dispatch failures.
|
|
1857
|
+
*
|
|
1858
|
+
* @example
|
|
1859
|
+
* ```ts
|
|
1860
|
+
* const result = await streamSwap({ ... });
|
|
1861
|
+
* const { bundles } = buildSettlementTx({
|
|
1862
|
+
* claims: result.claims,
|
|
1863
|
+
* signers: {
|
|
1864
|
+
* 'evm:base:8453': {
|
|
1865
|
+
* address: '0xmill...',
|
|
1866
|
+
* contractAddress: '0xtokennetwork...',
|
|
1867
|
+
* chainId: 8453,
|
|
1868
|
+
* },
|
|
1869
|
+
* },
|
|
1870
|
+
* recipients: { 'evm:base:8453': '0xsender...' },
|
|
1871
|
+
* });
|
|
1872
|
+
* // Feed bundles[0].unsignedTxBytes into fillEvmSettlementTxGas → sign → eth_sendRawTransaction.
|
|
1873
|
+
* ```
|
|
1874
|
+
*/
|
|
1875
|
+
declare function buildSettlementTx(params: BuildSettlementTxParams): BuildSettlementTxResult;
|
|
1876
|
+
/**
|
|
1877
|
+
* Standalone utility: verify a single `AccumulatedClaim`'s signature against
|
|
1878
|
+
* a `MillSignerConfig` without running the full grouping/winner pipeline.
|
|
1879
|
+
*
|
|
1880
|
+
* Useful inside a `streamSwap()` `onPacket` callback for mid-stream claim
|
|
1881
|
+
* validation.
|
|
1882
|
+
*
|
|
1883
|
+
* For `mina:*` claims, pass a pre-loaded `mina-signer` `Client` as
|
|
1884
|
+
* `minaSignerClient` (see `loadMinaSignerClient()`); without it, Mina claims
|
|
1885
|
+
* return `MINA_VERIFICATION_UNSUPPORTED` (same contract as
|
|
1886
|
+
* `buildSettlementTx`).
|
|
1887
|
+
*
|
|
1888
|
+
* @stable
|
|
1889
|
+
* @since 12.6
|
|
1890
|
+
*/
|
|
1891
|
+
declare function verifyAccumulatedClaim(claim: AccumulatedClaim, signer: MillSignerConfig, minaSignerClient?: MinaSignerClientLike): {
|
|
1892
|
+
valid: true;
|
|
1893
|
+
} | {
|
|
1894
|
+
valid: false;
|
|
1895
|
+
reason: string;
|
|
1896
|
+
};
|
|
1897
|
+
|
|
1898
|
+
/**
|
|
1899
|
+
* Solana-specific settlement tx construction + signature verification
|
|
1900
|
+
* (Story 12.6 AC-9).
|
|
1901
|
+
*
|
|
1902
|
+
* @module
|
|
1903
|
+
* @since 12.6
|
|
1904
|
+
* @see _bmad-output/implementation-artifacts/12-6-build-settlement-tx.md
|
|
1905
|
+
*/
|
|
1906
|
+
|
|
1907
|
+
/**
|
|
1908
|
+
* Verify a Solana Ed25519 balance-proof signature.
|
|
1909
|
+
*
|
|
1910
|
+
* @since 12.6
|
|
1911
|
+
*/
|
|
1912
|
+
declare function verifyEd25519Signature(claim: AccumulatedClaim, expectedSignerAddress: string): boolean;
|
|
1913
|
+
|
|
1914
|
+
/**
|
|
1915
|
+
* DvmHealthResponse — canonical type for the DVM BLS health endpoint.
|
|
1916
|
+
* Exported from @toon-protocol/sdk so Townhouse and the entrypoint share
|
|
1917
|
+
* the same definition (mirrors MillHealthResponse from @toon-protocol/mill).
|
|
1918
|
+
*/
|
|
1919
|
+
/** Per-kind job count for jobsRecent.byKind */
|
|
1920
|
+
interface DvmJobsByKindEntry {
|
|
1921
|
+
kind: number;
|
|
1922
|
+
count: number;
|
|
1923
|
+
}
|
|
1924
|
+
/** Per-status job counts for the sliding window */
|
|
1925
|
+
interface DvmJobsByStatus {
|
|
1926
|
+
processing: number;
|
|
1927
|
+
success: number;
|
|
1928
|
+
error: number;
|
|
1929
|
+
partial: number;
|
|
1930
|
+
}
|
|
1931
|
+
/** Windowed recent-jobs telemetry (default window: 5 min) */
|
|
1932
|
+
interface DvmJobsRecent {
|
|
1933
|
+
total: number;
|
|
1934
|
+
byKind: DvmJobsByKindEntry[];
|
|
1935
|
+
byStatus: DvmJobsByStatus;
|
|
1936
|
+
}
|
|
1937
|
+
/** Response shape for GET /health on the DVM BLS server (port 3400). */
|
|
1938
|
+
interface DvmHealthResponse {
|
|
1939
|
+
status: 'starting' | 'ok' | 'stopping' | 'stopped' | 'error';
|
|
1940
|
+
version: string;
|
|
1941
|
+
nodePubkey: string;
|
|
1942
|
+
uptimeSec: number;
|
|
1943
|
+
/** Registered handler event kinds (e.g. [5094, 5250]). */
|
|
1944
|
+
handlerKinds: number[];
|
|
1945
|
+
/** Per-kind pricing in string-encoded bigint (e.g. { "5094": "10", "5250": "10000" }). */
|
|
1946
|
+
kindPricing: Record<string, string>;
|
|
1947
|
+
basePricePerByte: string;
|
|
1948
|
+
jobsRecent: DvmJobsRecent;
|
|
1949
|
+
}
|
|
1950
|
+
|
|
1951
|
+
export { AccumulatedClaim, type AddChunkResult, type ApplyRateParams, type ArweaveDvmConfig, type ArweaveUploadAdapter, type BuildSettlementTxParams, type BuildSettlementTxResult, type BuildSkillDescriptorConfig, ChunkManager, type ChunkManagerConfig, type ClaimIssuer, type CreateHandlerContextOptions, type CreateSwapHandlerConfig, type DvmHealthResponse, type DvmJobsByKindEntry, type DvmJobsByStatus, type DvmJobsRecent, type FromMnemonicOptions, GiftWrapError, type Handler, type HandlerContext, HandlerError, HandlerRegistry, type HandlerResponse, IdentityError, type IssueClaimParams, type IssueClaimResult, type MillSignerConfig, type MinaIdentity, type MinaSignerClientLike, type NodeConfig, NodeError, type NodeIdentity, type PaymentHandlerBridgeConfig, type PaymentRequest, type PaymentResponse, type PrefixClaimHandlerOptions, PricingError, type PricingValidationResult, type PricingValidatorConfig, type PublishEventResult, type PublishableNode, SWAP_HANDLER_REJECT_CODES, SWAP_HANDLER_REJECT_MESSAGES, type ServiceNode, type SettlementBundle, SettlementTxError, type SolanaIdentity, type StartResult, StreamSwapError, SwapHandlerError, type SwapHandlerLogger, SwarmCoordinator, type SwarmCoordinatorOptions, type SwarmState, type ToonIdentity, TurboUploadAdapter, type UploadBlobChunkedOptions, type UploadBlobOptions, VerificationError, type VerificationPipelineConfig, type VerificationResult, type WorkflowEventStore, WorkflowOrchestrator, type WorkflowOrchestratorOptions, type WorkflowState, applyRate, base58Decode, base58Encode, buildSettlementTx, buildSkillDescriptor, createArweaveDvmHandler, createEventStorageHandler, createHandlerContext, createNode, createPaymentHandlerBridge, createPrefixClaimHandler, createPricingValidator, createSwapHandler, createVerificationPipeline, fillEvmSettlementTxGas, findSwapPair, fromMnemonic, fromMnemonicFull, fromSecretKey, generateMnemonic, generateSolanaKeypair, loadMinaSignerClient, uploadBlob, uploadBlobChunked, verifyAccumulatedClaim, verifyEd25519Signature, verifyMinaSignature };
|