@toon-protocol/sdk 0.1.4
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 +115 -0
- package/dist/index.d.ts +557 -0
- package/dist/index.js +945 -0
- package/dist/index.js.map +1 -0
- package/package.json +74 -0
package/README.md
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# @toon-protocol/sdk
|
|
2
|
+
|
|
3
|
+
The building blocks for creating services that participate in the TOON network.
|
|
4
|
+
|
|
5
|
+
## What It Does
|
|
6
|
+
|
|
7
|
+
The SDK provides a framework for processing ILP-paid Nostr events. You register handlers for specific event kinds, and the SDK handles everything else: identity derivation, Schnorr signature verification, payment validation, and handler dispatch.
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Incoming ILP packet
|
|
11
|
+
→ Size check (1MB max)
|
|
12
|
+
→ TOON parse (extract metadata)
|
|
13
|
+
→ Signature verification (Schnorr)
|
|
14
|
+
→ Payment validation (per-byte pricing)
|
|
15
|
+
→ Your handler (business logic)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install @toon-protocol/sdk
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Quick Example
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
import { createNode, fromMnemonic } from '@toon-protocol/sdk';
|
|
28
|
+
import { ConnectorNode } from '@toon-protocol/connector';
|
|
29
|
+
|
|
30
|
+
// 1. Create an identity
|
|
31
|
+
const identity = fromMnemonic('your twelve word mnemonic phrase here');
|
|
32
|
+
|
|
33
|
+
// 2. Create an embedded ILP connector
|
|
34
|
+
const connector = new ConnectorNode({
|
|
35
|
+
nodeId: 'my-node',
|
|
36
|
+
btpServerPort: 3000,
|
|
37
|
+
environment: 'development',
|
|
38
|
+
deploymentMode: 'embedded',
|
|
39
|
+
peers: [],
|
|
40
|
+
routes: [],
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// 3. Create a node with the connector
|
|
44
|
+
const node = createNode({
|
|
45
|
+
secretKey: identity.secretKey,
|
|
46
|
+
connector,
|
|
47
|
+
basePricePerByte: 10n,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// 4. Register handlers for specific event kinds
|
|
51
|
+
node.on(1, async (ctx) => {
|
|
52
|
+
const event = ctx.decode();
|
|
53
|
+
console.log(`Received kind:${ctx.kind} from ${ctx.pubkey}`);
|
|
54
|
+
console.log(`Paid: ${ctx.amount} units`);
|
|
55
|
+
return ctx.accept({ eventId: event.id });
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// 5. Start the node
|
|
59
|
+
const result = await node.start();
|
|
60
|
+
console.log(`Connected to ${result.peerCount} peers`);
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
> **Easier path:** If you just want to run a relay, use [`@toon-protocol/town`](../town) — it manages the connector externally so you don't need to embed one. The SDK is for building custom services where you control the full pipeline.
|
|
64
|
+
|
|
65
|
+
## Where It Sits
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
┌─────────────────────────┐
|
|
69
|
+
│ Your Application │ ← You write this
|
|
70
|
+
├─────────────────────────┤
|
|
71
|
+
│ @toon-protocol/sdk │ ← Identity, verification, pricing, handlers
|
|
72
|
+
├─────────────────────────┤
|
|
73
|
+
│ @toon-protocol/core │ ← Bootstrap, discovery, peering
|
|
74
|
+
├─────────────────────────┤
|
|
75
|
+
│ ILP Connector │ ← Payment routing
|
|
76
|
+
└─────────────────────────┘
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
The SDK is the framework layer. You bring handlers; it handles the protocol.
|
|
80
|
+
|
|
81
|
+
## API Overview
|
|
82
|
+
|
|
83
|
+
| Export | Purpose |
|
|
84
|
+
|--------|---------|
|
|
85
|
+
| `createNode(config)` | Compose a full service node |
|
|
86
|
+
| `fromMnemonic(phrase)` | Derive identity from BIP-39 mnemonic |
|
|
87
|
+
| `fromSecretKey(key)` | Derive identity from raw secret key |
|
|
88
|
+
| `generateMnemonic()` | Generate a new 12-word mnemonic |
|
|
89
|
+
| `HandlerRegistry` | Kind-based handler routing |
|
|
90
|
+
| `createHandlerContext()` | Build handler context objects |
|
|
91
|
+
| `createVerificationPipeline()` | Schnorr signature verifier |
|
|
92
|
+
| `createPricingValidator()` | Payment amount validator |
|
|
93
|
+
|
|
94
|
+
## Key Concepts
|
|
95
|
+
|
|
96
|
+
| Concept | Description |
|
|
97
|
+
|---------|-------------|
|
|
98
|
+
| **Unified identity** | One secp256k1 key produces both a Nostr pubkey and an EVM address |
|
|
99
|
+
| **Handler pattern** | `ctx.accept()` / `ctx.reject()` — handlers respond, not return |
|
|
100
|
+
| **Self-write bypass** | Events from your own pubkey skip pricing |
|
|
101
|
+
| **Dev mode** | Skip verification and pricing for testing |
|
|
102
|
+
| **TOON encoding** | Events encoded in compact text format, not JSON |
|
|
103
|
+
|
|
104
|
+
## Full Documentation
|
|
105
|
+
|
|
106
|
+
See the [SDK Guide](../../docs/sdk-guide.md) for the complete API reference, handler patterns, verification pipeline details, publishing events, and error handling.
|
|
107
|
+
|
|
108
|
+
## Requirements
|
|
109
|
+
|
|
110
|
+
- Node.js >= 20
|
|
111
|
+
- `@toon-protocol/connector` >= 1.6.0 (peer dependency, optional)
|
|
112
|
+
|
|
113
|
+
## License
|
|
114
|
+
|
|
115
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,557 @@
|
|
|
1
|
+
import { ToonError, HandlePacketAcceptResponse, HandlePacketRejectResponse, SkillDescriptor, EmbeddableConnectorLike, KnownPeer, SettlementConfig, ConnectorChannelClient, BootstrapEventListener, BootstrapResult, DvmJobStatus, IlpSendResult } from '@toon-protocol/core';
|
|
2
|
+
export { BootstrapEvent, BootstrapEventListener, HandlePacketAcceptResponse, HandlePacketRejectResponse, SkillDescriptor } from '@toon-protocol/core';
|
|
3
|
+
import { NostrEvent } from 'nostr-tools/pure';
|
|
4
|
+
import { ToonRoutingMeta } from '@toon-protocol/core/toon';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Unified identity module for @toon-protocol/sdk.
|
|
8
|
+
*
|
|
9
|
+
* Derives both a Nostr pubkey (x-only Schnorr, BIP-340) and an EVM address
|
|
10
|
+
* (Keccak-256) from a single secp256k1 private key, following the NIP-06
|
|
11
|
+
* derivation standard.
|
|
12
|
+
*
|
|
13
|
+
* Both Nostr and EVM use the secp256k1 elliptic curve, so a single 12-word
|
|
14
|
+
* seed phrase can recover the complete identity across both layers.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Represents a node's complete identity: secret key, Nostr pubkey, and EVM address.
|
|
18
|
+
*/
|
|
19
|
+
interface NodeIdentity {
|
|
20
|
+
/** The 32-byte secp256k1 secret key. */
|
|
21
|
+
secretKey: Uint8Array;
|
|
22
|
+
/** The x-only Schnorr public key (32 bytes, 64 lowercase hex characters). */
|
|
23
|
+
pubkey: string;
|
|
24
|
+
/** The EIP-55 checksummed EVM address (0x-prefixed, 42 characters). */
|
|
25
|
+
evmAddress: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Options for mnemonic-based key derivation.
|
|
29
|
+
*/
|
|
30
|
+
interface FromMnemonicOptions {
|
|
31
|
+
/** Key index in the NIP-06 derivation path. Defaults to 0. */
|
|
32
|
+
accountIndex?: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Generates a valid 12-word BIP-39 mnemonic using 128-bit entropy.
|
|
36
|
+
*
|
|
37
|
+
* @returns A space-separated string of 12 BIP-39 English words.
|
|
38
|
+
*/
|
|
39
|
+
declare function generateMnemonic(): string;
|
|
40
|
+
/**
|
|
41
|
+
* Derives a complete NodeIdentity from a BIP-39 mnemonic phrase.
|
|
42
|
+
*
|
|
43
|
+
* Uses the NIP-06 derivation path: m/44'/1237'/0'/0/{accountIndex}
|
|
44
|
+
*
|
|
45
|
+
* @param mnemonic - A valid BIP-39 mnemonic (12 or 24 words).
|
|
46
|
+
* @param options - Optional derivation options (accountIndex defaults to 0).
|
|
47
|
+
* @returns The derived NodeIdentity with secretKey, pubkey, and evmAddress.
|
|
48
|
+
* @throws {IdentityError} If the mnemonic is invalid.
|
|
49
|
+
*/
|
|
50
|
+
declare function fromMnemonic(mnemonic: string, options?: FromMnemonicOptions): NodeIdentity;
|
|
51
|
+
/**
|
|
52
|
+
* Derives a complete NodeIdentity from an existing 32-byte secret key.
|
|
53
|
+
*
|
|
54
|
+
* @param secretKey - A 32-byte secp256k1 secret key.
|
|
55
|
+
* @returns The derived NodeIdentity with secretKey, pubkey, and evmAddress.
|
|
56
|
+
* @throws {IdentityError} If the secret key is not exactly 32 bytes.
|
|
57
|
+
*/
|
|
58
|
+
declare function fromSecretKey(secretKey: Uint8Array): NodeIdentity;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* SDK-specific error classes for @toon-protocol/sdk.
|
|
62
|
+
* All errors extend ToonError from @toon-protocol/core for a consistent error hierarchy.
|
|
63
|
+
*/
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Error thrown when identity operations fail.
|
|
67
|
+
* Used for invalid mnemonics, invalid secret keys, and key derivation failures.
|
|
68
|
+
*/
|
|
69
|
+
declare class IdentityError extends ToonError {
|
|
70
|
+
constructor(message: string, cause?: Error);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Error thrown when node lifecycle operations fail.
|
|
74
|
+
* Used for start/stop failures, configuration errors, etc.
|
|
75
|
+
*/
|
|
76
|
+
declare class NodeError extends ToonError {
|
|
77
|
+
constructor(message: string, cause?: Error);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Error thrown when handler dispatch operations fail.
|
|
81
|
+
* Used for handler registration conflicts, missing handlers, and dispatch errors.
|
|
82
|
+
*/
|
|
83
|
+
declare class HandlerError extends ToonError {
|
|
84
|
+
constructor(message: string, cause?: Error);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Error thrown when Schnorr signature verification fails.
|
|
88
|
+
* Used for invalid signatures, malformed events, and verification pipeline errors.
|
|
89
|
+
*/
|
|
90
|
+
declare class VerificationError extends ToonError {
|
|
91
|
+
constructor(message: string, cause?: Error);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Error thrown when payment validation fails.
|
|
95
|
+
* Used for pricing calculation errors, insufficient payment, and pricing policy violations.
|
|
96
|
+
*/
|
|
97
|
+
declare class PricingError extends ToonError {
|
|
98
|
+
constructor(message: string, cause?: Error);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Handler context for @toon-protocol/sdk.
|
|
103
|
+
*
|
|
104
|
+
* Provides a context object passed to kind-based handlers with methods
|
|
105
|
+
* for accessing TOON data, shallow-parsed metadata, and accept/reject actions.
|
|
106
|
+
*/
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* The handler context passed to each kind-based handler.
|
|
110
|
+
*/
|
|
111
|
+
interface HandlerContext {
|
|
112
|
+
/** Raw TOON string (base64-encoded). */
|
|
113
|
+
readonly toon: string;
|
|
114
|
+
/** Event kind from shallow parse. */
|
|
115
|
+
readonly kind: number;
|
|
116
|
+
/** Event pubkey from shallow parse. */
|
|
117
|
+
readonly pubkey: string;
|
|
118
|
+
/** Payment amount in the ILP packet. */
|
|
119
|
+
readonly amount: bigint;
|
|
120
|
+
/** ILP destination address. */
|
|
121
|
+
readonly destination: string;
|
|
122
|
+
/** Lazy-decode the TOON payload into a full NostrEvent. */
|
|
123
|
+
decode(): NostrEvent;
|
|
124
|
+
/** Accept the packet with optional metadata. */
|
|
125
|
+
accept(metadata?: Record<string, unknown>): HandlePacketAcceptResponse;
|
|
126
|
+
/** Reject the packet with an ILP error code and message. */
|
|
127
|
+
reject(code: string, message: string): HandlePacketRejectResponse;
|
|
128
|
+
}
|
|
129
|
+
interface CreateHandlerContextOptions {
|
|
130
|
+
toon: string;
|
|
131
|
+
meta: ToonRoutingMeta;
|
|
132
|
+
amount: bigint;
|
|
133
|
+
destination: string;
|
|
134
|
+
toonDecoder: (toon: string) => NostrEvent;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Creates a HandlerContext from the given options.
|
|
138
|
+
*/
|
|
139
|
+
declare function createHandlerContext(options: CreateHandlerContextOptions): HandlerContext;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Handler registry for @toon-protocol/sdk.
|
|
143
|
+
*
|
|
144
|
+
* Maps event kinds to handler functions for dispatching incoming ILP packets.
|
|
145
|
+
*/
|
|
146
|
+
|
|
147
|
+
type HandlerResponse = HandlePacketAcceptResponse | HandlePacketRejectResponse;
|
|
148
|
+
type Handler = (ctx: HandlerContext) => Promise<HandlerResponse>;
|
|
149
|
+
/**
|
|
150
|
+
* Registry that maps Nostr event kinds to handler functions.
|
|
151
|
+
*/
|
|
152
|
+
declare class HandlerRegistry {
|
|
153
|
+
private handlers;
|
|
154
|
+
private defaultHandler;
|
|
155
|
+
/**
|
|
156
|
+
* Register a handler for a specific event kind.
|
|
157
|
+
* Replaces any existing handler for that kind.
|
|
158
|
+
*/
|
|
159
|
+
on(kind: number, handler: Handler): this;
|
|
160
|
+
/**
|
|
161
|
+
* Register a default handler for unrecognized kinds.
|
|
162
|
+
*/
|
|
163
|
+
onDefault(handler: Handler): this;
|
|
164
|
+
/**
|
|
165
|
+
* Returns all registered kind numbers, sorted ascending.
|
|
166
|
+
*/
|
|
167
|
+
getRegisteredKinds(): number[];
|
|
168
|
+
/**
|
|
169
|
+
* Returns registered kinds in the DVM request range (5000-5999), sorted ascending.
|
|
170
|
+
* Uses JOB_REQUEST_KIND_BASE (5000) as the range start.
|
|
171
|
+
*/
|
|
172
|
+
getDvmKinds(): number[];
|
|
173
|
+
/**
|
|
174
|
+
* Dispatch a context to the appropriate handler based on kind.
|
|
175
|
+
*/
|
|
176
|
+
dispatch(ctx: HandlerContext): Promise<HandlerResponse>;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Pricing validator for @toon-protocol/sdk.
|
|
181
|
+
*
|
|
182
|
+
* Validates that incoming ILP payments meet the required price based on
|
|
183
|
+
* TOON payload size and configured price per byte.
|
|
184
|
+
*/
|
|
185
|
+
|
|
186
|
+
interface PricingValidatorConfig {
|
|
187
|
+
basePricePerByte?: bigint;
|
|
188
|
+
ownPubkey: string;
|
|
189
|
+
kindPricing?: Record<number, bigint>;
|
|
190
|
+
}
|
|
191
|
+
interface PricingValidationResult {
|
|
192
|
+
accepted: boolean;
|
|
193
|
+
rejection?: {
|
|
194
|
+
accept: false;
|
|
195
|
+
code: string;
|
|
196
|
+
message: string;
|
|
197
|
+
metadata?: Record<string, string>;
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Creates a pricing validator that checks payment amounts against TOON size.
|
|
202
|
+
*/
|
|
203
|
+
declare function createPricingValidator(config: PricingValidatorConfig): {
|
|
204
|
+
validate(meta: ToonRoutingMeta, amount: bigint): PricingValidationResult;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Verification pipeline for @toon-protocol/sdk.
|
|
209
|
+
*
|
|
210
|
+
* Verifies Schnorr signatures on incoming TOON payloads before dispatching
|
|
211
|
+
* to handlers. In dev mode, verification is skipped.
|
|
212
|
+
*/
|
|
213
|
+
|
|
214
|
+
interface VerificationResult {
|
|
215
|
+
verified: boolean;
|
|
216
|
+
rejection?: {
|
|
217
|
+
accept: false;
|
|
218
|
+
code: string;
|
|
219
|
+
message: string;
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
interface VerificationPipelineConfig {
|
|
223
|
+
devMode: boolean;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Creates a verification pipeline that checks Schnorr signatures.
|
|
227
|
+
*/
|
|
228
|
+
declare function createVerificationPipeline(config: VerificationPipelineConfig): {
|
|
229
|
+
verify(meta: ToonRoutingMeta, _toonData: string): Promise<VerificationResult>;
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Payment handler bridge for @toon-protocol/sdk.
|
|
234
|
+
*
|
|
235
|
+
* Bridges between ILP packet handling and the handler registry,
|
|
236
|
+
* using isTransit to distinguish fire-and-forget from await semantics.
|
|
237
|
+
*/
|
|
238
|
+
|
|
239
|
+
interface PaymentHandlerBridgeConfig {
|
|
240
|
+
registry: HandlerRegistry;
|
|
241
|
+
devMode: boolean;
|
|
242
|
+
ownPubkey: string;
|
|
243
|
+
basePricePerByte: bigint;
|
|
244
|
+
}
|
|
245
|
+
interface PaymentRequest {
|
|
246
|
+
paymentId: string;
|
|
247
|
+
destination: string;
|
|
248
|
+
amount: string;
|
|
249
|
+
data: string;
|
|
250
|
+
isTransit: boolean;
|
|
251
|
+
}
|
|
252
|
+
interface PaymentResponse {
|
|
253
|
+
accept: boolean;
|
|
254
|
+
fulfillment?: string;
|
|
255
|
+
code?: string;
|
|
256
|
+
message?: string;
|
|
257
|
+
data?: string;
|
|
258
|
+
metadata?: Record<string, unknown>;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Creates a payment handler bridge that connects ILP packets to the handler registry.
|
|
262
|
+
*/
|
|
263
|
+
declare function createPaymentHandlerBridge(config: PaymentHandlerBridgeConfig): {
|
|
264
|
+
handlePayment(request: PaymentRequest): Promise<PaymentResponse>;
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Event storage handler stub for @toon-protocol/sdk.
|
|
269
|
+
*
|
|
270
|
+
* This is a stub that throws. The real implementation lives in
|
|
271
|
+
* `@toon-protocol/town` -- see `createEventStorageHandler` from that package.
|
|
272
|
+
*
|
|
273
|
+
* The SDK is the framework; Town is the relay implementation. SDK consumers
|
|
274
|
+
* building relay functionality should use `@toon-protocol/town` directly.
|
|
275
|
+
*/
|
|
276
|
+
/**
|
|
277
|
+
* Creates an event storage handler.
|
|
278
|
+
*
|
|
279
|
+
* **Stub** -- throws "not yet implemented". See `@toon-protocol/town` for the
|
|
280
|
+
* real relay implementation of this handler.
|
|
281
|
+
*
|
|
282
|
+
* @see {@link https://github.com/ALLiDoizCode/toon/tree/main/packages/town | @toon-protocol/town}
|
|
283
|
+
*/
|
|
284
|
+
declare function createEventStorageHandler(_config: unknown): unknown;
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Skill descriptor builder for DVM service discovery.
|
|
288
|
+
*
|
|
289
|
+
* Computes a SkillDescriptor from the handler registry and node configuration.
|
|
290
|
+
* The descriptor is embedded in kind:10035 events to advertise DVM capabilities.
|
|
291
|
+
*
|
|
292
|
+
* Returns `undefined` when no DVM handlers are registered (backward compatible
|
|
293
|
+
* with pre-DVM kind:10035 events).
|
|
294
|
+
*/
|
|
295
|
+
|
|
296
|
+
/** Configuration for building a skill descriptor. */
|
|
297
|
+
interface BuildSkillDescriptorConfig {
|
|
298
|
+
/** Base price per byte in USDC micro-units (default: 10n). */
|
|
299
|
+
basePricePerByte?: bigint;
|
|
300
|
+
/** Per-kind pricing overrides (kind number -> price in USDC micro-units). */
|
|
301
|
+
kindPricing?: Record<number, bigint>;
|
|
302
|
+
/** Service name override (default: 'toon-dvm'). */
|
|
303
|
+
name?: string;
|
|
304
|
+
/** Schema version override (default: '1.0'). */
|
|
305
|
+
version?: string;
|
|
306
|
+
/** Feature list override. */
|
|
307
|
+
features?: string[];
|
|
308
|
+
/** JSON Schema draft-07 object for job request parameters. */
|
|
309
|
+
inputSchema?: Record<string, unknown>;
|
|
310
|
+
/** Available AI models. */
|
|
311
|
+
models?: string[];
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Builds a SkillDescriptor from the handler registry and configuration.
|
|
315
|
+
*
|
|
316
|
+
* Returns `undefined` when the registry has no DVM handlers (kinds 5000-5999).
|
|
317
|
+
* When DVM kinds exist, auto-populates the descriptor:
|
|
318
|
+
* - `kinds` from `registry.getDvmKinds()`
|
|
319
|
+
* - `pricing` from `config.kindPricing` overrides or `config.basePricePerByte` fallback
|
|
320
|
+
* - `name`, `version`, `features`, `inputSchema`, `models` from config or defaults
|
|
321
|
+
*
|
|
322
|
+
* @param registry - The handler registry to read DVM kinds from.
|
|
323
|
+
* @param config - Node configuration for pricing and optional overrides.
|
|
324
|
+
* @returns A SkillDescriptor, or undefined if no DVM handlers are registered.
|
|
325
|
+
*/
|
|
326
|
+
declare function buildSkillDescriptor(registry: HandlerRegistry, config?: BuildSkillDescriptorConfig): SkillDescriptor | undefined;
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* createNode() composition for @toon-protocol/sdk.
|
|
330
|
+
*
|
|
331
|
+
* Wires the full ILP packet processing pipeline:
|
|
332
|
+
* shallow TOON parse -> Schnorr signature verification -> pricing validation -> handler dispatch
|
|
333
|
+
*
|
|
334
|
+
* Provides start() / stop() lifecycle management by delegating to
|
|
335
|
+
* the core ToonNode composition (embedded mode) or manual HTTP
|
|
336
|
+
* composition (standalone mode).
|
|
337
|
+
*
|
|
338
|
+
* ## Deployment Modes
|
|
339
|
+
*
|
|
340
|
+
* - **Embedded** (`connector`): Pass an EmbeddableConnectorLike directly.
|
|
341
|
+
* Zero-latency packet delivery via direct function calls.
|
|
342
|
+
* - **Standalone** (`connectorUrl` + `handlerPort`): Connect to an external
|
|
343
|
+
* connector via HTTP. The SDK starts an HTTP server to receive packets.
|
|
344
|
+
*/
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Configuration for creating a ServiceNode via createNode().
|
|
348
|
+
*
|
|
349
|
+
* Supports two deployment modes:
|
|
350
|
+
* - **Embedded** (`connector`): Pass an EmbeddableConnectorLike directly for
|
|
351
|
+
* zero-latency packet delivery.
|
|
352
|
+
* - **Standalone** (`connectorUrl` + `handlerPort`): Connect to an external
|
|
353
|
+
* connector via HTTP. The SDK starts an HTTP server to receive packets.
|
|
354
|
+
*
|
|
355
|
+
* Provide `connector` OR (`connectorUrl` + `handlerPort`), not both.
|
|
356
|
+
*/
|
|
357
|
+
interface NodeConfig {
|
|
358
|
+
/** 32-byte secp256k1 secret key */
|
|
359
|
+
secretKey: Uint8Array;
|
|
360
|
+
/** Chain preset name (default: 'anvil'). See resolveChainConfig(). */
|
|
361
|
+
chain?: string;
|
|
362
|
+
/** Embedded connector instance for zero-latency mode. */
|
|
363
|
+
connector?: EmbeddableConnectorLike;
|
|
364
|
+
/**
|
|
365
|
+
* External connector admin URL for standalone mode (e.g., "http://localhost:8081").
|
|
366
|
+
* Must be provided with `handlerPort`.
|
|
367
|
+
*/
|
|
368
|
+
connectorUrl?: string;
|
|
369
|
+
/**
|
|
370
|
+
* Port for the HTTP server that receives ILP packets from the external connector.
|
|
371
|
+
* Must be provided with `connectorUrl`.
|
|
372
|
+
*/
|
|
373
|
+
handlerPort?: number;
|
|
374
|
+
/** ILP address (default: 'g.toon.local') */
|
|
375
|
+
ilpAddress?: string;
|
|
376
|
+
/** BTP endpoint URL advertised in kind:10032 announcements */
|
|
377
|
+
btpEndpoint?: string;
|
|
378
|
+
/** Asset code (default: 'USD') */
|
|
379
|
+
assetCode?: string;
|
|
380
|
+
/** Asset scale (default: 6) */
|
|
381
|
+
assetScale?: number;
|
|
382
|
+
/**
|
|
383
|
+
* Base price per byte for pricing validation (default: 10n).
|
|
384
|
+
*
|
|
385
|
+
* Amounts are in USDC micro-units (6 decimals) for production.
|
|
386
|
+
* Default 10n = 10 micro-USDC per byte = $0.00001/byte.
|
|
387
|
+
* A 1KB event costs 10,240 micro-USDC = ~$0.01.
|
|
388
|
+
*/
|
|
389
|
+
basePricePerByte?: bigint;
|
|
390
|
+
/** Dev mode skips signature verification (default: false) */
|
|
391
|
+
devMode?: boolean;
|
|
392
|
+
/** TOON encoder function */
|
|
393
|
+
toonEncoder?: (event: NostrEvent) => Uint8Array;
|
|
394
|
+
/** TOON decoder function */
|
|
395
|
+
toonDecoder?: (bytes: Uint8Array) => NostrEvent;
|
|
396
|
+
/** Initial known peers for bootstrap */
|
|
397
|
+
knownPeers?: KnownPeer[];
|
|
398
|
+
/** Relay WebSocket URL */
|
|
399
|
+
relayUrl?: string;
|
|
400
|
+
/** Settlement info for peer registration */
|
|
401
|
+
settlementInfo?: SettlementConfig;
|
|
402
|
+
/** Enable ArDrive peer lookup */
|
|
403
|
+
ardriveEnabled?: boolean;
|
|
404
|
+
/** Per-kind pricing overrides */
|
|
405
|
+
kindPricing?: Record<number, bigint>;
|
|
406
|
+
/** Config-based handler registration (alternative to post-creation .on()) */
|
|
407
|
+
handlers?: Record<number, Handler>;
|
|
408
|
+
/** Config-based default handler (alternative to post-creation .onDefault()) */
|
|
409
|
+
defaultHandler?: Handler;
|
|
410
|
+
/**
|
|
411
|
+
* Optional skill descriptor configuration overrides.
|
|
412
|
+
* When DVM handlers are registered, these values override the auto-derived
|
|
413
|
+
* defaults in the skill descriptor. See buildSkillDescriptor().
|
|
414
|
+
*/
|
|
415
|
+
skillConfig?: Omit<BuildSkillDescriptorConfig, 'basePricePerByte' | 'kindPricing'>;
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Result returned by ServiceNode.start().
|
|
419
|
+
*/
|
|
420
|
+
interface StartResult {
|
|
421
|
+
/** Number of peers successfully bootstrapped */
|
|
422
|
+
peerCount: number;
|
|
423
|
+
/** Number of payment channels opened */
|
|
424
|
+
channelCount: number;
|
|
425
|
+
/** Detailed results from the bootstrap phase */
|
|
426
|
+
bootstrapResults: BootstrapResult[];
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Result returned by ServiceNode.publishEvent().
|
|
430
|
+
*/
|
|
431
|
+
interface PublishEventResult {
|
|
432
|
+
success: boolean;
|
|
433
|
+
eventId: string;
|
|
434
|
+
fulfillment?: string;
|
|
435
|
+
code?: string;
|
|
436
|
+
message?: string;
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* A fully wired TOON node with lifecycle management.
|
|
440
|
+
*/
|
|
441
|
+
interface ServiceNode {
|
|
442
|
+
/** Nostr x-only public key (32 bytes, 64 hex chars) */
|
|
443
|
+
readonly pubkey: string;
|
|
444
|
+
/** EVM address derived from the same secp256k1 key */
|
|
445
|
+
readonly evmAddress: string;
|
|
446
|
+
/** Pass-through to the underlying connector (null in standalone mode) */
|
|
447
|
+
readonly connector: EmbeddableConnectorLike | null;
|
|
448
|
+
/** Channel client (null if connector lacks channel support or in standalone mode) */
|
|
449
|
+
readonly channelClient: ConnectorChannelClient | null;
|
|
450
|
+
/** Register a handler for a specific event kind (builder pattern) */
|
|
451
|
+
on(kind: number, handler: Handler): ServiceNode;
|
|
452
|
+
/** Register a lifecycle event listener */
|
|
453
|
+
on(event: 'bootstrap', listener: BootstrapEventListener): ServiceNode;
|
|
454
|
+
/** Register a default handler for unrecognized kinds (builder pattern) */
|
|
455
|
+
onDefault(handler: Handler): ServiceNode;
|
|
456
|
+
/** Start the node: wire packet handler, run bootstrap, start discovery */
|
|
457
|
+
start(): Promise<StartResult>;
|
|
458
|
+
/** Stop the node: clean up lifecycle state */
|
|
459
|
+
stop(): Promise<void>;
|
|
460
|
+
/** Initiate peering with a discovered peer (register + settlement) */
|
|
461
|
+
peerWith(pubkey: string): Promise<void>;
|
|
462
|
+
/**
|
|
463
|
+
* Publish a Nostr event to a remote peer via the embedded connector.
|
|
464
|
+
*
|
|
465
|
+
* TOON-encodes the event, computes payment amount, and sends as an
|
|
466
|
+
* ILP PREPARE packet via the runtime client.
|
|
467
|
+
*
|
|
468
|
+
* @param event - The Nostr event to publish
|
|
469
|
+
* @param options - Must include destination ILP address
|
|
470
|
+
* @returns Result with success/failure info and event ID
|
|
471
|
+
*/
|
|
472
|
+
publishEvent(event: NostrEvent, options?: {
|
|
473
|
+
destination: string;
|
|
474
|
+
}): Promise<PublishEventResult>;
|
|
475
|
+
/**
|
|
476
|
+
* Publish a Kind 7000 DVM job feedback event via ILP PREPARE.
|
|
477
|
+
*
|
|
478
|
+
* Builds a signed Kind 7000 feedback event with NIP-90 tags (e, p, status)
|
|
479
|
+
* and delegates to publishEvent() for TOON encoding and ILP delivery.
|
|
480
|
+
* Standard relay write fee applies: basePricePerByte * toonData.length.
|
|
481
|
+
*
|
|
482
|
+
* @param requestEventId - 64-char hex event ID of the original Kind 5xxx request
|
|
483
|
+
* @param customerPubkey - 64-char hex pubkey of the customer who posted the request
|
|
484
|
+
* @param status - Job status value ('processing', 'error', 'success', 'partial')
|
|
485
|
+
* @param content - Optional status details or error message
|
|
486
|
+
* @param options - Must include destination ILP address
|
|
487
|
+
* @returns Result with success/failure info and event ID
|
|
488
|
+
*/
|
|
489
|
+
publishFeedback(requestEventId: string, customerPubkey: string, status: DvmJobStatus, content?: string, options?: {
|
|
490
|
+
destination: string;
|
|
491
|
+
}): Promise<PublishEventResult>;
|
|
492
|
+
/**
|
|
493
|
+
* Publish a Kind 6xxx DVM job result event via ILP PREPARE.
|
|
494
|
+
*
|
|
495
|
+
* Builds a signed Kind 6xxx result event with NIP-90 tags (e, p, amount)
|
|
496
|
+
* and delegates to publishEvent() for TOON encoding and ILP delivery.
|
|
497
|
+
* Standard relay write fee applies: basePricePerByte * toonData.length.
|
|
498
|
+
*
|
|
499
|
+
* @param requestEventId - 64-char hex event ID of the original Kind 5xxx request
|
|
500
|
+
* @param customerPubkey - 64-char hex pubkey of the customer who posted the request
|
|
501
|
+
* @param amount - Compute cost in USDC micro-units as string
|
|
502
|
+
* @param content - Result data (text, URL, etc.)
|
|
503
|
+
* @param options - Must include destination; optional kind (default: 6100)
|
|
504
|
+
* @returns Result with success/failure info and event ID
|
|
505
|
+
*/
|
|
506
|
+
publishResult(requestEventId: string, customerPubkey: string, amount: string, content: string, options?: {
|
|
507
|
+
destination: string;
|
|
508
|
+
kind?: number;
|
|
509
|
+
}): Promise<PublishEventResult>;
|
|
510
|
+
/**
|
|
511
|
+
* Returns the computed skill descriptor for this node's DVM capabilities.
|
|
512
|
+
* Returns `undefined` if no DVM handlers (kinds 5000-5999) are registered.
|
|
513
|
+
* The descriptor is computed from the handler registry and node config.
|
|
514
|
+
*/
|
|
515
|
+
getSkillDescriptor(): SkillDescriptor | undefined;
|
|
516
|
+
/**
|
|
517
|
+
* Send an ILP payment to a provider for compute settlement.
|
|
518
|
+
*
|
|
519
|
+
* Extracts the compute cost from the result event's `amount` tag via
|
|
520
|
+
* parseJobResult(), optionally validates against the original bid amount
|
|
521
|
+
* (E5-R005 bid validation), and sends a pure ILP value transfer
|
|
522
|
+
* (empty data field) to the provider's ILP address.
|
|
523
|
+
*
|
|
524
|
+
* This is a payment-only operation -- no TOON encoding, no relay write.
|
|
525
|
+
* The payment routes through the ILP mesh using the same infrastructure
|
|
526
|
+
* as relay write fees.
|
|
527
|
+
*
|
|
528
|
+
* @param resultEvent - Kind 6xxx result event with amount tag
|
|
529
|
+
* @param providerIlpAddress - Provider's ILP address from kind:10035
|
|
530
|
+
* @param options - Optional originalBid for bid validation (E5-R005)
|
|
531
|
+
* @returns ILP send result with accepted/rejected status
|
|
532
|
+
*/
|
|
533
|
+
settleCompute(resultEvent: NostrEvent, providerIlpAddress: string, options?: {
|
|
534
|
+
originalBid?: string;
|
|
535
|
+
}): Promise<IlpSendResult>;
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* Creates a fully wired ServiceNode from configuration.
|
|
539
|
+
*
|
|
540
|
+
* The returned node has the full ILP packet processing pipeline wired in the
|
|
541
|
+
* correct order:
|
|
542
|
+
* 1. Shallow TOON parse (extract routing metadata)
|
|
543
|
+
* 2. Schnorr signature verification (reject with F06 if invalid)
|
|
544
|
+
* 3. Pricing validation (reject with F04 if underpaid)
|
|
545
|
+
* 4. Handler dispatch (route to kind-specific or default handler)
|
|
546
|
+
*
|
|
547
|
+
* Supports two deployment modes:
|
|
548
|
+
* - **Embedded** (`connector`): Uses createToonNode for zero-latency
|
|
549
|
+
* packet delivery via direct function calls.
|
|
550
|
+
* - **Standalone** (`connectorUrl` + `handlerPort`): Starts an HTTP server
|
|
551
|
+
* to receive packets and uses HTTP clients for the connector API.
|
|
552
|
+
*
|
|
553
|
+
* Handlers can be registered via config or post-creation .on()/.onDefault().
|
|
554
|
+
*/
|
|
555
|
+
declare function createNode(config: NodeConfig): ServiceNode;
|
|
556
|
+
|
|
557
|
+
export { type BuildSkillDescriptorConfig, type CreateHandlerContextOptions, type FromMnemonicOptions, type Handler, type HandlerContext, HandlerError, HandlerRegistry, type HandlerResponse, IdentityError, type NodeConfig, NodeError, type NodeIdentity, type PaymentHandlerBridgeConfig, type PaymentRequest, type PaymentResponse, PricingError, type PricingValidationResult, type PricingValidatorConfig, type PublishEventResult, type ServiceNode, type StartResult, VerificationError, type VerificationPipelineConfig, type VerificationResult, buildSkillDescriptor, createEventStorageHandler, createHandlerContext, createNode, createPaymentHandlerBridge, createPricingValidator, createVerificationPipeline, fromMnemonic, fromSecretKey, generateMnemonic };
|