@toon-protocol/client-mcp 0.7.1 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -6
- package/dist/app/index.html +73 -68
- package/dist/{chunk-Y5U4UCHU.js → chunk-57G7AAEG.js} +44 -14
- package/dist/chunk-57G7AAEG.js.map +1 -0
- package/dist/{chunk-6N2FGTST.js → chunk-G5H3OD5N.js} +24 -14
- package/dist/chunk-G5H3OD5N.js.map +1 -0
- package/dist/{chunk-CHTBE4PI.js → chunk-UEP6PFZN.js} +4 -4
- package/dist/chunk-UEP6PFZN.js.map +1 -0
- package/dist/daemon.js +2 -2
- package/dist/index.d.ts +22 -22
- package/dist/index.js +10 -10
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +2 -2
- package/package.json +4 -4
- package/dist/chunk-6N2FGTST.js.map +0 -1
- package/dist/chunk-CHTBE4PI.js.map +0 -1
- package/dist/chunk-Y5U4UCHU.js.map +0 -1
package/dist/daemon.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
ClientRunner,
|
|
5
5
|
registerRoutes,
|
|
6
6
|
scaffoldFirstRun
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-G5H3OD5N.js";
|
|
8
8
|
import {
|
|
9
9
|
ControlClient,
|
|
10
10
|
ToonClient,
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
resolveConfig,
|
|
18
18
|
spawnDaemonDetached,
|
|
19
19
|
waitForReady
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-UEP6PFZN.js";
|
|
21
21
|
import "./chunk-32QD72IL.js";
|
|
22
22
|
import "./chunk-DLYE6U2Z.js";
|
|
23
23
|
import "./chunk-LR7W2ISE.js";
|
package/dist/index.d.ts
CHANGED
|
@@ -202,22 +202,22 @@ interface ChannelsResponse {
|
|
|
202
202
|
channels: ChannelInfo[];
|
|
203
203
|
}
|
|
204
204
|
/**
|
|
205
|
-
* `POST /swap` — pay asset A to a
|
|
205
|
+
* `POST /swap` — pay asset A to a swap peer, receive asset B + a signed
|
|
206
206
|
* target-chain claim. The daemon builds the NIP-59 gift-wrapped kind:20032 swap
|
|
207
207
|
* rumor and streams it via SDK `streamSwap`, signing the source-asset claim
|
|
208
|
-
* against the open apex channel (the
|
|
208
|
+
* against the open apex channel (the swap peer must be routed via
|
|
209
209
|
* `apexChildPeers`).
|
|
210
210
|
*/
|
|
211
211
|
interface SwapRequest {
|
|
212
|
-
/**
|
|
212
|
+
/** Swap peer ILP destination (e.g. `g.proxy.swap`). */
|
|
213
213
|
destination: string;
|
|
214
214
|
/** Total source-asset amount to swap, in source micro-units. */
|
|
215
215
|
amount: string;
|
|
216
|
-
/**
|
|
217
|
-
|
|
216
|
+
/** Swap peer's 64-char lowercase hex Nostr pubkey (NIP-59 gift-wrap recipient). */
|
|
217
|
+
swapPubkey: string;
|
|
218
218
|
/**
|
|
219
219
|
* The swap pair to execute — from kind:10032 discovery, or operator-supplied
|
|
220
|
-
* when the
|
|
220
|
+
* when the swap peer announces pairs to a relay other than the town relay.
|
|
221
221
|
*/
|
|
222
222
|
pair: SwapPair;
|
|
223
223
|
/**
|
|
@@ -229,7 +229,7 @@ interface SwapRequest {
|
|
|
229
229
|
packetCount?: number;
|
|
230
230
|
/**
|
|
231
231
|
* Which apex to settle the source-asset claim through (default: the
|
|
232
|
-
* config-seeded apex). The
|
|
232
|
+
* config-seeded apex). The swap peer must be a child peer of this apex.
|
|
233
233
|
*/
|
|
234
234
|
btpUrl?: string;
|
|
235
235
|
}
|
|
@@ -243,11 +243,11 @@ interface SwapClaim {
|
|
|
243
243
|
claim: string;
|
|
244
244
|
/** Target-chain channel id (real on-chain id, or a dev placeholder). */
|
|
245
245
|
channelId?: string;
|
|
246
|
-
/** Sender's payout address echoed by the
|
|
246
|
+
/** Sender's payout address echoed by the swap peer. */
|
|
247
247
|
recipient?: string;
|
|
248
|
-
/**
|
|
249
|
-
|
|
250
|
-
/**
|
|
248
|
+
/** Swap peer's on-chain signer address. */
|
|
249
|
+
swapSignerAddress?: string;
|
|
250
|
+
/** Swap-side claim id. */
|
|
251
251
|
claimId?: string;
|
|
252
252
|
/** Balance-proof nonce on the target channel (decimal). */
|
|
253
253
|
nonce?: string;
|
|
@@ -257,7 +257,7 @@ interface SwapClaim {
|
|
|
257
257
|
interface SwapResponse {
|
|
258
258
|
/** True when at least one packet FULFILLed with a usable claim. */
|
|
259
259
|
accepted: boolean;
|
|
260
|
-
/** Number of packets the
|
|
260
|
+
/** Number of packets the swap peer FULFILLed. */
|
|
261
261
|
packetsAccepted: number;
|
|
262
262
|
/** Per-packet accumulated claims (settlement metadata + signed claim). */
|
|
263
263
|
claims: SwapClaim[];
|
|
@@ -267,7 +267,7 @@ interface SwapResponse {
|
|
|
267
267
|
cumulativeTarget: string;
|
|
268
268
|
/** Final stream state. */
|
|
269
269
|
state: 'completed' | 'failed' | 'stopped';
|
|
270
|
-
/** First rejection code from the
|
|
270
|
+
/** First rejection code from the swap peer, if any (e.g. `F99`). */
|
|
271
271
|
code?: string;
|
|
272
272
|
/** First rejection message, if any. */
|
|
273
273
|
message?: string;
|
|
@@ -317,7 +317,7 @@ interface RemoveRelayRequest {
|
|
|
317
317
|
* hand-supplies chain/settlement details.
|
|
318
318
|
*/
|
|
319
319
|
interface AddApexRequest {
|
|
320
|
-
/** ILP address of the apex to add (e.g. `g.
|
|
320
|
+
/** ILP address of the apex to add (e.g. `g.proxy`). */
|
|
321
321
|
ilpAddress: string;
|
|
322
322
|
/**
|
|
323
323
|
* Relay to discover the apex's `kind:10032` on. If it isn't already a read
|
|
@@ -328,7 +328,7 @@ interface AddApexRequest {
|
|
|
328
328
|
pubkey?: string;
|
|
329
329
|
/** Preferred settlement chain family; defaults to the apex's first chain. */
|
|
330
330
|
chain?: SettlementChain;
|
|
331
|
-
/** Child peers reached via this apex's channel (e.g. `["
|
|
331
|
+
/** Child peers reached via this apex's channel (e.g. `["store","swap"]`). */
|
|
332
332
|
childPeers?: string[];
|
|
333
333
|
/** Per-write fee override (base units) for this apex. */
|
|
334
334
|
feePerEvent?: string;
|
|
@@ -607,9 +607,9 @@ declare class RelaySubscription {
|
|
|
607
607
|
|
|
608
608
|
/** Apex/town settlement parameters injected as a peer negotiation. */
|
|
609
609
|
interface ApexNegotiationConfig {
|
|
610
|
-
/** ILP destination address, e.g. `g.
|
|
610
|
+
/** ILP destination address, e.g. `g.proxy`. */
|
|
611
611
|
destination: string;
|
|
612
|
-
/** Peer id key used in the negotiation map (last ILP segment, e.g. `
|
|
612
|
+
/** Peer id key used in the negotiation map (last ILP segment, e.g. `proxy`). */
|
|
613
613
|
peerId: string;
|
|
614
614
|
/** Settlement chain family. */
|
|
615
615
|
chain: SettlementChain;
|
|
@@ -704,9 +704,9 @@ interface DaemonConfigFile {
|
|
|
704
704
|
*/
|
|
705
705
|
apexChains?: Partial<Record<SettlementChain, ApexNegotiationConfig>>;
|
|
706
706
|
/**
|
|
707
|
-
* Additional apex CHILD peers (last ILP segment, e.g. `["
|
|
707
|
+
* Additional apex CHILD peers (last ILP segment, e.g. `["store","swap"]`)
|
|
708
708
|
* reachable via the SAME apex channel — used when publishing/swapping to
|
|
709
|
-
* `g.
|
|
709
|
+
* `g.proxy.store` / `g.proxy.swap`. The runner injects the apex
|
|
710
710
|
* negotiation under each and points it at the open apex channel (no extra
|
|
711
711
|
* on-chain channel). The apex `peerId` itself is always handled.
|
|
712
712
|
*/
|
|
@@ -756,7 +756,7 @@ interface ResolvedDaemonConfig {
|
|
|
756
756
|
storeDestination: string;
|
|
757
757
|
feePerEvent: bigint;
|
|
758
758
|
apex?: ApexNegotiationConfig;
|
|
759
|
-
/** Apex child peers reached via the same apex channel (e.g.
|
|
759
|
+
/** Apex child peers reached via the same apex channel (e.g. store, swap). */
|
|
760
760
|
apexChildPeers?: string[];
|
|
761
761
|
/** The active settlement chain for paid writes. */
|
|
762
762
|
chain: SettlementChain;
|
|
@@ -1016,7 +1016,7 @@ declare class ClientRunner {
|
|
|
1016
1016
|
private discoverApexNegotiation;
|
|
1017
1017
|
/** Inject the apex settlement negotiation directly into its ToonClient. */
|
|
1018
1018
|
private injectApexNegotiation;
|
|
1019
|
-
/** Route apex CHILD peers (
|
|
1019
|
+
/** Route apex CHILD peers (store/swap) through the SAME apex payment channel. */
|
|
1020
1020
|
private routeChildPeersThroughApexChannel;
|
|
1021
1021
|
private defaultApex;
|
|
1022
1022
|
/** Whether any apex has finished bootstrapping. */
|
|
@@ -1065,7 +1065,7 @@ declare class ClientRunner {
|
|
|
1065
1065
|
}>;
|
|
1066
1066
|
/** List tracked channels across ALL apexes with nonce + cumulative amount. */
|
|
1067
1067
|
getChannels(): ChannelsResponse;
|
|
1068
|
-
/** Swap source→target asset against a
|
|
1068
|
+
/** Swap source→target asset against a swap peer via the selected apex. */
|
|
1069
1069
|
swap(req: SwapRequest): Promise<SwapResponse>;
|
|
1070
1070
|
/**
|
|
1071
1071
|
* Payment-aware HTTP fetch through an apex's client. The client issues the
|
package/dist/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
hasConfiguredIdentity,
|
|
9
9
|
registerRoutes,
|
|
10
10
|
scaffoldFirstRun
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-G5H3OD5N.js";
|
|
12
12
|
import {
|
|
13
13
|
PUBLISH_TOOL,
|
|
14
14
|
TOOL_DEFINITIONS,
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
buildFollowListFilter,
|
|
19
19
|
buildProfileFilter,
|
|
20
20
|
dispatchTool
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-57G7AAEG.js";
|
|
22
22
|
import {
|
|
23
23
|
ControlApiError,
|
|
24
24
|
ControlClient,
|
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
resolveMnemonic,
|
|
37
37
|
spawnDaemonDetached,
|
|
38
38
|
waitForReady
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-UEP6PFZN.js";
|
|
40
40
|
import "./chunk-32QD72IL.js";
|
|
41
41
|
import "./chunk-DLYE6U2Z.js";
|
|
42
42
|
import "./chunk-LR7W2ISE.js";
|
|
@@ -176,11 +176,11 @@ function socialFiJourney(opts) {
|
|
|
176
176
|
};
|
|
177
177
|
}
|
|
178
178
|
},
|
|
179
|
-
// ── Step 5:
|
|
179
|
+
// ── Step 5: Store upload (kind:1063) + media-embed read-back ──────────────
|
|
180
180
|
// Use toon_status (read-only) for the auto-call; the actual upload is
|
|
181
181
|
// user-initiated via the panel's media-uploader action (spendy, confirmed).
|
|
182
182
|
{
|
|
183
|
-
id: "
|
|
183
|
+
id: "store-upload",
|
|
184
184
|
toolName: "toon_status",
|
|
185
185
|
buildInput: () => ({}),
|
|
186
186
|
renderPanel: (_data, state) => ({
|
|
@@ -241,7 +241,7 @@ function deFiJourney(opts) {
|
|
|
241
241
|
const args = {
|
|
242
242
|
destination: opts.destination,
|
|
243
243
|
amount: opts.amount,
|
|
244
|
-
|
|
244
|
+
swapPubkey: opts.swapPubkey,
|
|
245
245
|
pair: opts.pair,
|
|
246
246
|
chainRecipient: opts.chainRecipient
|
|
247
247
|
};
|
|
@@ -381,12 +381,12 @@ async function main(env = process.env) {
|
|
|
381
381
|
const baseUrl = env["TOON_DAEMON_URL"] ?? "http://127.0.0.1:8787";
|
|
382
382
|
const destination = env["TOON_SWAP_DEST"];
|
|
383
383
|
const amount = env["TOON_SWAP_AMOUNT"];
|
|
384
|
-
const
|
|
384
|
+
const swapPubkey = env["TOON_SWAP_PUBKEY"];
|
|
385
385
|
const chainRecipient = env["TOON_CHAIN_RECIPIENT"];
|
|
386
386
|
const pairRaw = env["TOON_SWAP_PAIR"];
|
|
387
|
-
if (!destination || !amount || !
|
|
387
|
+
if (!destination || !amount || !swapPubkey || !chainRecipient || !pairRaw) {
|
|
388
388
|
console.error(
|
|
389
|
-
"[capstone] missing required env: TOON_SWAP_DEST, TOON_SWAP_AMOUNT,
|
|
389
|
+
"[capstone] missing required env: TOON_SWAP_DEST, TOON_SWAP_AMOUNT, TOON_SWAP_PUBKEY, TOON_CHAIN_RECIPIENT, TOON_SWAP_PAIR are all required for the live DeFi leg. See the module header for the full env contract."
|
|
390
390
|
);
|
|
391
391
|
return 2;
|
|
392
392
|
}
|
|
@@ -401,7 +401,7 @@ async function main(env = process.env) {
|
|
|
401
401
|
const socialFiPubkey = env["TOON_SOCIALFI_PUBKEY"];
|
|
402
402
|
return runCapstoneDemo(client, {
|
|
403
403
|
...socialFiPubkey ? { socialFi: { pubkey: socialFiPubkey } } : {},
|
|
404
|
-
deFi: { destination, amount,
|
|
404
|
+
deFi: { destination, amount, swapPubkey, chainRecipient, pair }
|
|
405
405
|
});
|
|
406
406
|
}
|
|
407
407
|
var invokedDirectly = typeof process !== "undefined" && Array.isArray(process.argv) && /[/\\]journey[/\\]demo\.(ts|js|mjs)$/.test(process.argv[1] ?? "");
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/journey/runner.ts","../src/journey/socialfi.ts","../src/journey/defi.ts","../src/journey/demo.ts"],"sourcesContent":["import { dispatchTool, type ToolResult } from '../mcp-tools.js';\nimport type { ControlClient } from '../control-client.js';\nimport type { JourneyPlan, JourneyResult, JourneyState } from './types.js';\n\n/**\n * Run all steps in the plan sequentially against the given ControlClient.\n * Each step's result is threaded forward into the next step's buildInput via\n * JourneyState. Halts on the first tool error and returns a partial result.\n */\nexport async function runJourney(\n plan: JourneyPlan,\n client: ControlClient\n): Promise<JourneyResult> {\n const state: JourneyState = {};\n const completedSteps: JourneyResult['steps'] = [];\n\n for (const step of plan.steps) {\n const toolResult = await dispatchTool(client, step.toolName, step.buildInput(state));\n\n if (toolResult.isError) {\n return {\n completed: false,\n steps: completedSteps,\n error: { stepId: step.id, message: toolResult.content[0]?.text ?? 'Tool error' },\n };\n }\n\n const data = extractData(toolResult);\n state[step.id] = data;\n\n const viewSpec = step.renderPanel(data, state);\n const panel: ToolResult = {\n content: [{ type: 'text', text: `Journey step: ${step.id}` }],\n structuredContent: { viewSpec },\n };\n\n completedSteps.push({ stepId: step.id, toolResult, panel });\n }\n\n return { completed: true, steps: completedSteps };\n}\n\n/** Extract the data payload from a successful ToolResult for state threading. */\nfunction extractData(result: ToolResult): unknown {\n if (result.structuredContent !== undefined) return result.structuredContent;\n const text = result.content[0]?.text;\n if (!text) return null;\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n","import {\n buildProfileFilter,\n buildFeedFilter,\n buildFollowListFilter,\n buildFileMetadataFilter,\n PUBLISH_TOOL,\n UPLOAD_TOOL,\n} from '@toon-protocol/views';\nimport type { JourneyPlan, JourneyState } from './types.js';\n\nfunction pubkeyFromState(state: JourneyState, fallback?: string): string {\n const onboard = state['onboard'] as { identity?: { nostrPubkey?: string } } | undefined;\n return onboard?.identity?.nostrPubkey ?? fallback ?? '';\n}\n\n/**\n * The canonical five-step SocialFi journey:\n * onboard → publish profile (kind:0) → publish note (kind:1) → follow (kind:3)\n * → DVM media upload (kind:1063) with media-embed read-back.\n *\n * Pass `opts.pubkey` to seed the panel bind-queries with the user's pubkey\n * without waiting for the onboard step to surface it; the follow step's\n * buildInput also reads it from `state['onboard'].identity.nostrPubkey` so\n * the correct pubkey is used in the kind:3 tags even when opts is omitted.\n */\nexport function socialFiJourney(opts?: { pubkey?: string }): JourneyPlan {\n return {\n id: 'socialfi',\n title: 'SocialFi Journey',\n steps: [\n // ── Step 1: onboard ─────────────────────────────────────────────────────\n {\n id: 'onboard',\n toolName: 'toon_status',\n buildInput: () => ({}),\n renderPanel: (data) => {\n const s = data as { ready?: boolean } | undefined;\n return {\n title: 'Onboard',\n root: {\n atom: 'section',\n props: { title: s?.ready ? 'Ready to publish' : 'Connecting…' },\n children: [{ atom: 'card', children: [{ atom: 'generic-event' }] }],\n },\n };\n },\n },\n\n // ── Step 2: publish profile (kind:0) ────────────────────────────────────\n {\n id: 'publish-profile',\n toolName: 'toon_publish_unsigned',\n buildInput: () => ({\n kind: 0,\n content: JSON.stringify({ name: 'TOON User', about: 'Published via the SocialFi journey.' }),\n }),\n renderPanel: (_data, state) => ({\n title: 'Profile',\n root: {\n atom: 'profile-header',\n bind: { query: buildProfileFilter([pubkeyFromState(state, opts?.pubkey)]) },\n },\n }),\n },\n\n // ── Step 3: publish note (kind:1) ───────────────────────────────────────\n {\n id: 'publish-note',\n toolName: 'toon_publish_unsigned',\n buildInput: () => ({\n kind: 1,\n content: 'Hello from TOON Protocol!',\n }),\n renderPanel: (_data, state) => ({\n title: 'Note',\n root: {\n atom: 'stack',\n children: [\n {\n atom: 'composer',\n props: { placeholder: \"What's happening?\", label: 'Post' },\n actions: { post: { tool: PUBLISH_TOOL, args: { kind: 1 } } },\n },\n {\n atom: 'note-card',\n bind: { query: buildFeedFilter([pubkeyFromState(state, opts?.pubkey)], 50), kindAuto: true },\n },\n ],\n },\n }),\n },\n\n // ── Step 4: follow (kind:3) ─────────────────────────────────────────────\n {\n id: 'follow',\n toolName: 'toon_publish_unsigned',\n buildInput: (state: JourneyState) => {\n const pubkey = pubkeyFromState(state, opts?.pubkey);\n return { kind: 3, tags: [['p', pubkey]] };\n },\n renderPanel: (_data, state) => {\n const pubkey = pubkeyFromState(state, opts?.pubkey);\n return {\n title: 'Follow',\n root: {\n atom: 'stack',\n children: [\n {\n atom: 'follow-button',\n props: { label: 'Follow' },\n actions: { follow: { tool: PUBLISH_TOOL, args: { kind: 3, tags: [['p', pubkey]] } } },\n },\n {\n atom: 'note-card',\n bind: { query: buildFollowListFilter(pubkey), kindAuto: true },\n },\n ],\n },\n };\n },\n },\n\n // ── Step 5: DVM upload (kind:1063) + media-embed read-back ──────────────\n // Use toon_status (read-only) for the auto-call; the actual upload is\n // user-initiated via the panel's media-uploader action (spendy, confirmed).\n {\n id: 'dvm-upload',\n toolName: 'toon_status',\n buildInput: () => ({}),\n renderPanel: (_data, state) => ({\n title: 'Media Upload',\n root: {\n atom: 'stack',\n children: [\n {\n atom: 'media-uploader',\n props: { label: 'Upload media' },\n actions: {\n upload: {\n tool: UPLOAD_TOOL,\n args: { kind: 1063 },\n spendy: true,\n confirmLabel: 'Upload to Arweave (spendy)',\n },\n },\n },\n {\n atom: 'media-embed',\n bind: { query: buildFileMetadataFilter([pubkeyFromState(state, opts?.pubkey)], 30), kindAuto: true },\n },\n ],\n },\n }),\n },\n ],\n };\n}\n","import type { ViewSpec } from '@toon-protocol/views';\nimport type { ChannelsResponse, SwapRequest, SwapResponse } from '../control-api.js';\nimport type { JourneyPlan } from './types.js';\n\nexport interface DeFiJourneyOpts {\n /** ILP destination used for both channel open and the swap (e.g. mill peer). */\n destination: string;\n /** Total source-asset amount to swap, in source micro-units. */\n amount: string;\n /** Mill's 64-char lowercase hex Nostr pubkey (gift-wrap recipient). */\n millPubkey: string;\n /** Swap pair from kind:10032 discovery or operator-supplied. */\n pair: SwapRequest['pair'];\n /** Sender's payout address on the target chain. */\n chainRecipient: string;\n /** Split the swap into N equal packets (default 1). */\n packetCount?: number;\n}\n\n/**\n * DeFi journey: pre-open payment channel → tiny testnet swap → settlement receipt.\n *\n * Step 3's settlement-receipt panel is built by joining the swap result\n * (captured from step 2's renderPanel via closure) with the toon_channels\n * watermark — no non-existent toon_settle tool is involved.\n */\nexport function deFiJourney(opts: DeFiJourneyOpts): JourneyPlan {\n let capturedSwap: SwapResponse | undefined;\n\n return {\n id: 'defi',\n title: 'DeFi Journey: Open Channel → Swap → Settlement Receipt',\n steps: [\n {\n id: 'open-channel',\n toolName: 'toon_open_channel',\n buildInput: (_state) => ({ destination: opts.destination }),\n renderPanel: (data): ViewSpec => {\n const { channelId } = data as { channelId: string };\n return {\n title: 'Payment Channel',\n root: {\n atom: 'stack',\n children: [{ atom: 'channel-card', props: { channelId } }],\n },\n };\n },\n },\n {\n id: 'swap',\n toolName: 'toon_swap',\n buildInput: (_state): Record<string, unknown> => {\n const args: Record<string, unknown> = {\n destination: opts.destination,\n amount: opts.amount,\n millPubkey: opts.millPubkey,\n pair: opts.pair,\n chainRecipient: opts.chainRecipient,\n };\n if (opts.packetCount !== undefined) {\n args['packetCount'] = opts.packetCount;\n }\n return args;\n },\n renderPanel: (data): ViewSpec => {\n capturedSwap = data as SwapResponse;\n return {\n title: 'Swap',\n root: {\n atom: 'stack',\n children: [\n {\n atom: 'swap-form',\n props: {\n accepted: capturedSwap.accepted,\n packetsAccepted: capturedSwap.packetsAccepted,\n cumulativeSource: capturedSwap.cumulativeSource,\n cumulativeTarget: capturedSwap.cumulativeTarget,\n state: capturedSwap.state,\n claims: capturedSwap.claims,\n },\n },\n ],\n },\n };\n },\n },\n {\n id: 'settlement-receipt',\n toolName: 'toon_channels',\n buildInput: (_state) => ({}),\n renderPanel: (data): ViewSpec => {\n const { channels } = data as ChannelsResponse;\n const swap = capturedSwap;\n return {\n title: 'Settlement Receipt',\n root: {\n atom: 'stack',\n children: [\n {\n atom: 'settlement-receipt',\n props: {\n accepted: swap?.accepted,\n cumulativeSource: swap?.cumulativeSource,\n cumulativeTarget: swap?.cumulativeTarget,\n claims: swap?.claims ?? [],\n channels,\n },\n },\n ],\n },\n };\n },\n },\n ],\n };\n}\n","/**\n * Capstone journey demo (#25): chain the merged SocialFi and DeFi journeys into\n * one ordered plan, run it against a `toon-clientd` daemon, print each step's\n * ViewSpec panel, and print the settlement receipt sourced from the `swap`\n * response joined with the `channels()` watermark.\n *\n * There is intentionally NO `settle()`/`toon_settle` step: the receipt is the\n * swap result (cumulative source/target + signed claims) reconciled against the\n * channel nonce watermark, exactly as `deFiJourney`'s `settlement-receipt` panel\n * already does. This module just chains the two existing journeys and renders\n * their output to stdout for the demo.\n *\n * Run from source (root devDep `tsx`):\n * pnpm --filter @toon-protocol/client-mcp demo:journey\n * or against a built dist:\n * node dist/journey/demo.js\n *\n * The daemon must already be running (toon-clientd). Live config + funding is a\n * human prerequisite (Base Sepolia treasury) and is OUT OF SCOPE for CI; the\n * dry-run unit test (`demo.test.ts`) covers the orchestration with a mocked\n * ControlClient and no network/funds.\n */\n\nimport type { ChannelsResponse, SwapResponse } from '../control-api.js';\nimport { ControlClient } from '../control-client.js';\nimport { runJourney } from './runner.js';\nimport { socialFiJourney } from './socialfi.js';\nimport { deFiJourney, type DeFiJourneyOpts } from './defi.js';\nimport type { JourneyPlan, JourneyResult } from './types.js';\n\n/**\n * Concatenate several journey plans into one ordered plan. Step ids are\n * namespaced with the source plan id (`<planId>:<stepId>`) so the combined\n * `JourneyState` keys never collide when two legs reuse a step id.\n *\n * Note: each leg's `buildInput`/`renderPanel` reads its OWN step ids out of\n * `JourneyState`, so re-keying here would break that threading. We therefore\n * keep the original step ids on the steps themselves and only namespace the\n * combined plan's *reported* ids via a wrapper is unnecessary because the two\n * legs (`socialfi`, `defi`) share no step ids. We assert that invariant.\n */\nexport function chainJourneys(\n id: string,\n title: string,\n ...plans: JourneyPlan[]\n): JourneyPlan {\n const steps = plans.flatMap((p) => p.steps);\n const seen = new Set<string>();\n for (const step of steps) {\n if (seen.has(step.id)) {\n throw new Error(\n `chainJourneys: duplicate step id \"${step.id}\" across chained plans — ` +\n `state threading requires unique step ids`\n );\n }\n seen.add(step.id);\n }\n return { id, title, steps };\n}\n\n/** Build the capstone SocialFi → DeFi plan. */\nexport function capstoneJourney(opts: {\n socialFi?: { pubkey?: string };\n deFi: DeFiJourneyOpts;\n}): JourneyPlan {\n return chainJourneys(\n 'capstone',\n 'Capstone Journey: SocialFi → DeFi',\n socialFiJourney(opts.socialFi),\n deFiJourney(opts.deFi)\n );\n}\n\n/** The settlement receipt, derived from the swap response + channel watermark. */\nexport interface SettlementReceipt {\n accepted: boolean;\n state: SwapResponse['state'];\n cumulativeSource: string;\n cumulativeTarget: string;\n claims: SwapResponse['claims'];\n channels: ChannelsResponse['channels'];\n}\n\n/**\n * Reconstruct the settlement receipt from a completed journey result. Sources\n * the swap payload from the `swap` step's raw ToolResult and the channel\n * watermark from the `settlement-receipt` step's raw ToolResult. Returns\n * undefined if either step is missing (e.g. the run halted before DeFi).\n */\nexport function extractReceipt(result: JourneyResult): SettlementReceipt | undefined {\n const swapStep = result.steps.find((s) => s.stepId === 'swap');\n const channelsStep = result.steps.find((s) => s.stepId === 'settlement-receipt');\n if (!swapStep || !channelsStep) return undefined;\n\n const swap = parseToolText<SwapResponse>(swapStep.toolResult.content[0]?.text);\n const channelsRes = parseToolText<ChannelsResponse>(\n channelsStep.toolResult.content[0]?.text\n );\n if (!swap || !channelsRes) return undefined;\n\n return {\n accepted: swap.accepted,\n state: swap.state,\n cumulativeSource: swap.cumulativeSource,\n cumulativeTarget: swap.cumulativeTarget,\n claims: swap.claims ?? [],\n channels: channelsRes.channels,\n };\n}\n\nfunction parseToolText<T>(text: string | undefined): T | undefined {\n if (!text) return undefined;\n try {\n return JSON.parse(text) as T;\n } catch {\n return undefined;\n }\n}\n\n/** Minimal console surface so the runner is testable with a captured logger. */\nexport interface DemoLogger {\n log: (msg: string) => void;\n error: (msg: string) => void;\n}\n\n/**\n * Run the capstone journey against a ControlClient, printing each step's panel\n * JSON and the final settlement receipt. Returns the process exit code: 0 on a\n * fully-completed journey, 1 if any step errored. Does no network I/O itself —\n * the ControlClient does. No funds move in the dry-run test (mocked client).\n */\nexport async function runCapstoneDemo(\n client: ControlClient,\n opts: { socialFi?: { pubkey?: string }; deFi: DeFiJourneyOpts },\n logger: DemoLogger = console\n): Promise<number> {\n const plan = capstoneJourney(opts);\n logger.log(`\\n=== ${plan.title} (${plan.steps.length} steps) ===\\n`);\n\n const result = await runJourney(plan, client);\n\n for (const step of result.steps) {\n const viewSpec = step.panel.structuredContent?.['viewSpec'];\n logger.log(`--- panel: ${step.stepId} ---`);\n logger.log(JSON.stringify(viewSpec, null, 2));\n }\n\n if (!result.completed) {\n logger.error(\n `\\n[capstone] FAILED at step \"${result.error?.stepId}\": ${result.error?.message}`\n );\n return 1;\n }\n\n const receipt = extractReceipt(result);\n logger.log('\\n=== Settlement Receipt ===');\n logger.log(JSON.stringify(receipt, null, 2));\n logger.log(`\\n[capstone] completed all ${result.steps.length} steps.`);\n return 0;\n}\n\n/**\n * CLI entry. Reads connection + DeFi opts from env and runs the demo against a\n * live daemon. See module header for the live-run prerequisites.\n *\n * Env:\n * TOON_DAEMON_URL daemon control-plane base URL (default http://127.0.0.1:8787)\n * TOON_SWAP_DEST mill ILP destination (e.g. g.townhouse.mill)\n * TOON_SWAP_AMOUNT source-asset amount, micro-units (e.g. 1000000)\n * TOON_MILL_PUBKEY mill 64-char hex Nostr pubkey\n * TOON_CHAIN_RECIPIENT payout address on the target chain\n * TOON_SWAP_PAIR JSON SwapPair ({ from, to, rate, ... })\n * TOON_SOCIALFI_PUBKEY optional: seed panel bind-queries before onboard surfaces it\n */\nexport async function main(env: NodeJS.ProcessEnv = process.env): Promise<number> {\n const baseUrl = env['TOON_DAEMON_URL'] ?? 'http://127.0.0.1:8787';\n\n const destination = env['TOON_SWAP_DEST'];\n const amount = env['TOON_SWAP_AMOUNT'];\n const millPubkey = env['TOON_MILL_PUBKEY'];\n const chainRecipient = env['TOON_CHAIN_RECIPIENT'];\n const pairRaw = env['TOON_SWAP_PAIR'];\n\n if (!destination || !amount || !millPubkey || !chainRecipient || !pairRaw) {\n console.error(\n '[capstone] missing required env: TOON_SWAP_DEST, TOON_SWAP_AMOUNT, ' +\n 'TOON_MILL_PUBKEY, TOON_CHAIN_RECIPIENT, TOON_SWAP_PAIR are all required ' +\n 'for the live DeFi leg. See the module header for the full env contract.'\n );\n return 2;\n }\n\n let pair: DeFiJourneyOpts['pair'];\n try {\n pair = JSON.parse(pairRaw) as DeFiJourneyOpts['pair'];\n } catch (e) {\n console.error(`[capstone] TOON_SWAP_PAIR is not valid JSON: ${String(e)}`);\n return 2;\n }\n\n const client = new ControlClient({ baseUrl });\n const socialFiPubkey = env['TOON_SOCIALFI_PUBKEY'];\n\n return runCapstoneDemo(client, {\n ...(socialFiPubkey ? { socialFi: { pubkey: socialFiPubkey } } : {}),\n deFi: { destination, amount, millPubkey, chainRecipient, pair },\n });\n}\n\n// Run when invoked directly (tsx src/journey/demo.ts or node dist/journey/demo.js).\nconst invokedDirectly =\n typeof process !== 'undefined' &&\n Array.isArray(process.argv) &&\n /[/\\\\]journey[/\\\\]demo\\.(ts|js|mjs)$/.test(process.argv[1] ?? '');\n\nif (invokedDirectly) {\n main()\n .then((code) => process.exit(code))\n .catch((err) => {\n console.error('[capstone] fatal:', err instanceof Error ? err.message : err);\n process.exit(1);\n });\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/journey/runner.ts","../src/journey/socialfi.ts","../src/journey/defi.ts","../src/journey/demo.ts"],"sourcesContent":["import { dispatchTool, type ToolResult } from '../mcp-tools.js';\nimport type { ControlClient } from '../control-client.js';\nimport type { JourneyPlan, JourneyResult, JourneyState } from './types.js';\n\n/**\n * Run all steps in the plan sequentially against the given ControlClient.\n * Each step's result is threaded forward into the next step's buildInput via\n * JourneyState. Halts on the first tool error and returns a partial result.\n */\nexport async function runJourney(\n plan: JourneyPlan,\n client: ControlClient\n): Promise<JourneyResult> {\n const state: JourneyState = {};\n const completedSteps: JourneyResult['steps'] = [];\n\n for (const step of plan.steps) {\n const toolResult = await dispatchTool(client, step.toolName, step.buildInput(state));\n\n if (toolResult.isError) {\n return {\n completed: false,\n steps: completedSteps,\n error: { stepId: step.id, message: toolResult.content[0]?.text ?? 'Tool error' },\n };\n }\n\n const data = extractData(toolResult);\n state[step.id] = data;\n\n const viewSpec = step.renderPanel(data, state);\n const panel: ToolResult = {\n content: [{ type: 'text', text: `Journey step: ${step.id}` }],\n structuredContent: { viewSpec },\n };\n\n completedSteps.push({ stepId: step.id, toolResult, panel });\n }\n\n return { completed: true, steps: completedSteps };\n}\n\n/** Extract the data payload from a successful ToolResult for state threading. */\nfunction extractData(result: ToolResult): unknown {\n if (result.structuredContent !== undefined) return result.structuredContent;\n const text = result.content[0]?.text;\n if (!text) return null;\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n","import {\n buildProfileFilter,\n buildFeedFilter,\n buildFollowListFilter,\n buildFileMetadataFilter,\n PUBLISH_TOOL,\n UPLOAD_TOOL,\n} from '@toon-protocol/views';\nimport type { JourneyPlan, JourneyState } from './types.js';\n\nfunction pubkeyFromState(state: JourneyState, fallback?: string): string {\n const onboard = state['onboard'] as { identity?: { nostrPubkey?: string } } | undefined;\n return onboard?.identity?.nostrPubkey ?? fallback ?? '';\n}\n\n/**\n * The canonical five-step SocialFi journey:\n * onboard → publish profile (kind:0) → publish note (kind:1) → follow (kind:3)\n * → Store media upload (kind:1063) with media-embed read-back.\n *\n * Pass `opts.pubkey` to seed the panel bind-queries with the user's pubkey\n * without waiting for the onboard step to surface it; the follow step's\n * buildInput also reads it from `state['onboard'].identity.nostrPubkey` so\n * the correct pubkey is used in the kind:3 tags even when opts is omitted.\n */\nexport function socialFiJourney(opts?: { pubkey?: string }): JourneyPlan {\n return {\n id: 'socialfi',\n title: 'SocialFi Journey',\n steps: [\n // ── Step 1: onboard ─────────────────────────────────────────────────────\n {\n id: 'onboard',\n toolName: 'toon_status',\n buildInput: () => ({}),\n renderPanel: (data) => {\n const s = data as { ready?: boolean } | undefined;\n return {\n title: 'Onboard',\n root: {\n atom: 'section',\n props: { title: s?.ready ? 'Ready to publish' : 'Connecting…' },\n children: [{ atom: 'card', children: [{ atom: 'generic-event' }] }],\n },\n };\n },\n },\n\n // ── Step 2: publish profile (kind:0) ────────────────────────────────────\n {\n id: 'publish-profile',\n toolName: 'toon_publish_unsigned',\n buildInput: () => ({\n kind: 0,\n content: JSON.stringify({ name: 'TOON User', about: 'Published via the SocialFi journey.' }),\n }),\n renderPanel: (_data, state) => ({\n title: 'Profile',\n root: {\n atom: 'profile-header',\n bind: { query: buildProfileFilter([pubkeyFromState(state, opts?.pubkey)]) },\n },\n }),\n },\n\n // ── Step 3: publish note (kind:1) ───────────────────────────────────────\n {\n id: 'publish-note',\n toolName: 'toon_publish_unsigned',\n buildInput: () => ({\n kind: 1,\n content: 'Hello from TOON Protocol!',\n }),\n renderPanel: (_data, state) => ({\n title: 'Note',\n root: {\n atom: 'stack',\n children: [\n {\n atom: 'composer',\n props: { placeholder: \"What's happening?\", label: 'Post' },\n actions: { post: { tool: PUBLISH_TOOL, args: { kind: 1 } } },\n },\n {\n atom: 'note-card',\n bind: { query: buildFeedFilter([pubkeyFromState(state, opts?.pubkey)], 50), kindAuto: true },\n },\n ],\n },\n }),\n },\n\n // ── Step 4: follow (kind:3) ─────────────────────────────────────────────\n {\n id: 'follow',\n toolName: 'toon_publish_unsigned',\n buildInput: (state: JourneyState) => {\n const pubkey = pubkeyFromState(state, opts?.pubkey);\n return { kind: 3, tags: [['p', pubkey]] };\n },\n renderPanel: (_data, state) => {\n const pubkey = pubkeyFromState(state, opts?.pubkey);\n return {\n title: 'Follow',\n root: {\n atom: 'stack',\n children: [\n {\n atom: 'follow-button',\n props: { label: 'Follow' },\n actions: { follow: { tool: PUBLISH_TOOL, args: { kind: 3, tags: [['p', pubkey]] } } },\n },\n {\n atom: 'note-card',\n bind: { query: buildFollowListFilter(pubkey), kindAuto: true },\n },\n ],\n },\n };\n },\n },\n\n // ── Step 5: Store upload (kind:1063) + media-embed read-back ──────────────\n // Use toon_status (read-only) for the auto-call; the actual upload is\n // user-initiated via the panel's media-uploader action (spendy, confirmed).\n {\n id: 'store-upload',\n toolName: 'toon_status',\n buildInput: () => ({}),\n renderPanel: (_data, state) => ({\n title: 'Media Upload',\n root: {\n atom: 'stack',\n children: [\n {\n atom: 'media-uploader',\n props: { label: 'Upload media' },\n actions: {\n upload: {\n tool: UPLOAD_TOOL,\n args: { kind: 1063 },\n spendy: true,\n confirmLabel: 'Upload to Arweave (spendy)',\n },\n },\n },\n {\n atom: 'media-embed',\n bind: { query: buildFileMetadataFilter([pubkeyFromState(state, opts?.pubkey)], 30), kindAuto: true },\n },\n ],\n },\n }),\n },\n ],\n };\n}\n","import type { ViewSpec } from '@toon-protocol/views';\nimport type { ChannelsResponse, SwapRequest, SwapResponse } from '../control-api.js';\nimport type { JourneyPlan } from './types.js';\n\nexport interface DeFiJourneyOpts {\n /** ILP destination used for both channel open and the swap (e.g. swap peer). */\n destination: string;\n /** Total source-asset amount to swap, in source micro-units. */\n amount: string;\n /** Swap peer's 64-char lowercase hex Nostr pubkey (gift-wrap recipient). */\n swapPubkey: string;\n /** Swap pair from kind:10032 discovery or operator-supplied. */\n pair: SwapRequest['pair'];\n /** Sender's payout address on the target chain. */\n chainRecipient: string;\n /** Split the swap into N equal packets (default 1). */\n packetCount?: number;\n}\n\n/**\n * DeFi journey: pre-open payment channel → tiny testnet swap → settlement receipt.\n *\n * Step 3's settlement-receipt panel is built by joining the swap result\n * (captured from step 2's renderPanel via closure) with the toon_channels\n * watermark — no non-existent toon_settle tool is involved.\n */\nexport function deFiJourney(opts: DeFiJourneyOpts): JourneyPlan {\n let capturedSwap: SwapResponse | undefined;\n\n return {\n id: 'defi',\n title: 'DeFi Journey: Open Channel → Swap → Settlement Receipt',\n steps: [\n {\n id: 'open-channel',\n toolName: 'toon_open_channel',\n buildInput: (_state) => ({ destination: opts.destination }),\n renderPanel: (data): ViewSpec => {\n const { channelId } = data as { channelId: string };\n return {\n title: 'Payment Channel',\n root: {\n atom: 'stack',\n children: [{ atom: 'channel-card', props: { channelId } }],\n },\n };\n },\n },\n {\n id: 'swap',\n toolName: 'toon_swap',\n buildInput: (_state): Record<string, unknown> => {\n const args: Record<string, unknown> = {\n destination: opts.destination,\n amount: opts.amount,\n swapPubkey: opts.swapPubkey,\n pair: opts.pair,\n chainRecipient: opts.chainRecipient,\n };\n if (opts.packetCount !== undefined) {\n args['packetCount'] = opts.packetCount;\n }\n return args;\n },\n renderPanel: (data): ViewSpec => {\n capturedSwap = data as SwapResponse;\n return {\n title: 'Swap',\n root: {\n atom: 'stack',\n children: [\n {\n atom: 'swap-form',\n props: {\n accepted: capturedSwap.accepted,\n packetsAccepted: capturedSwap.packetsAccepted,\n cumulativeSource: capturedSwap.cumulativeSource,\n cumulativeTarget: capturedSwap.cumulativeTarget,\n state: capturedSwap.state,\n claims: capturedSwap.claims,\n },\n },\n ],\n },\n };\n },\n },\n {\n id: 'settlement-receipt',\n toolName: 'toon_channels',\n buildInput: (_state) => ({}),\n renderPanel: (data): ViewSpec => {\n const { channels } = data as ChannelsResponse;\n const swap = capturedSwap;\n return {\n title: 'Settlement Receipt',\n root: {\n atom: 'stack',\n children: [\n {\n atom: 'settlement-receipt',\n props: {\n accepted: swap?.accepted,\n cumulativeSource: swap?.cumulativeSource,\n cumulativeTarget: swap?.cumulativeTarget,\n claims: swap?.claims ?? [],\n channels,\n },\n },\n ],\n },\n };\n },\n },\n ],\n };\n}\n","/**\n * Capstone journey demo (#25): chain the merged SocialFi and DeFi journeys into\n * one ordered plan, run it against a `toon-clientd` daemon, print each step's\n * ViewSpec panel, and print the settlement receipt sourced from the `swap`\n * response joined with the `channels()` watermark.\n *\n * There is intentionally NO `settle()`/`toon_settle` step: the receipt is the\n * swap result (cumulative source/target + signed claims) reconciled against the\n * channel nonce watermark, exactly as `deFiJourney`'s `settlement-receipt` panel\n * already does. This module just chains the two existing journeys and renders\n * their output to stdout for the demo.\n *\n * Run from source (root devDep `tsx`):\n * pnpm --filter @toon-protocol/client-mcp demo:journey\n * or against a built dist:\n * node dist/journey/demo.js\n *\n * The daemon must already be running (toon-clientd). Live config + funding is a\n * human prerequisite (Base Sepolia treasury) and is OUT OF SCOPE for CI; the\n * dry-run unit test (`demo.test.ts`) covers the orchestration with a mocked\n * ControlClient and no network/funds.\n */\n\nimport type { ChannelsResponse, SwapResponse } from '../control-api.js';\nimport { ControlClient } from '../control-client.js';\nimport { runJourney } from './runner.js';\nimport { socialFiJourney } from './socialfi.js';\nimport { deFiJourney, type DeFiJourneyOpts } from './defi.js';\nimport type { JourneyPlan, JourneyResult } from './types.js';\n\n/**\n * Concatenate several journey plans into one ordered plan. Step ids are\n * namespaced with the source plan id (`<planId>:<stepId>`) so the combined\n * `JourneyState` keys never collide when two legs reuse a step id.\n *\n * Note: each leg's `buildInput`/`renderPanel` reads its OWN step ids out of\n * `JourneyState`, so re-keying here would break that threading. We therefore\n * keep the original step ids on the steps themselves and only namespace the\n * combined plan's *reported* ids via a wrapper is unnecessary because the two\n * legs (`socialfi`, `defi`) share no step ids. We assert that invariant.\n */\nexport function chainJourneys(\n id: string,\n title: string,\n ...plans: JourneyPlan[]\n): JourneyPlan {\n const steps = plans.flatMap((p) => p.steps);\n const seen = new Set<string>();\n for (const step of steps) {\n if (seen.has(step.id)) {\n throw new Error(\n `chainJourneys: duplicate step id \"${step.id}\" across chained plans — ` +\n `state threading requires unique step ids`\n );\n }\n seen.add(step.id);\n }\n return { id, title, steps };\n}\n\n/** Build the capstone SocialFi → DeFi plan. */\nexport function capstoneJourney(opts: {\n socialFi?: { pubkey?: string };\n deFi: DeFiJourneyOpts;\n}): JourneyPlan {\n return chainJourneys(\n 'capstone',\n 'Capstone Journey: SocialFi → DeFi',\n socialFiJourney(opts.socialFi),\n deFiJourney(opts.deFi)\n );\n}\n\n/** The settlement receipt, derived from the swap response + channel watermark. */\nexport interface SettlementReceipt {\n accepted: boolean;\n state: SwapResponse['state'];\n cumulativeSource: string;\n cumulativeTarget: string;\n claims: SwapResponse['claims'];\n channels: ChannelsResponse['channels'];\n}\n\n/**\n * Reconstruct the settlement receipt from a completed journey result. Sources\n * the swap payload from the `swap` step's raw ToolResult and the channel\n * watermark from the `settlement-receipt` step's raw ToolResult. Returns\n * undefined if either step is missing (e.g. the run halted before DeFi).\n */\nexport function extractReceipt(result: JourneyResult): SettlementReceipt | undefined {\n const swapStep = result.steps.find((s) => s.stepId === 'swap');\n const channelsStep = result.steps.find((s) => s.stepId === 'settlement-receipt');\n if (!swapStep || !channelsStep) return undefined;\n\n const swap = parseToolText<SwapResponse>(swapStep.toolResult.content[0]?.text);\n const channelsRes = parseToolText<ChannelsResponse>(\n channelsStep.toolResult.content[0]?.text\n );\n if (!swap || !channelsRes) return undefined;\n\n return {\n accepted: swap.accepted,\n state: swap.state,\n cumulativeSource: swap.cumulativeSource,\n cumulativeTarget: swap.cumulativeTarget,\n claims: swap.claims ?? [],\n channels: channelsRes.channels,\n };\n}\n\nfunction parseToolText<T>(text: string | undefined): T | undefined {\n if (!text) return undefined;\n try {\n return JSON.parse(text) as T;\n } catch {\n return undefined;\n }\n}\n\n/** Minimal console surface so the runner is testable with a captured logger. */\nexport interface DemoLogger {\n log: (msg: string) => void;\n error: (msg: string) => void;\n}\n\n/**\n * Run the capstone journey against a ControlClient, printing each step's panel\n * JSON and the final settlement receipt. Returns the process exit code: 0 on a\n * fully-completed journey, 1 if any step errored. Does no network I/O itself —\n * the ControlClient does. No funds move in the dry-run test (mocked client).\n */\nexport async function runCapstoneDemo(\n client: ControlClient,\n opts: { socialFi?: { pubkey?: string }; deFi: DeFiJourneyOpts },\n logger: DemoLogger = console\n): Promise<number> {\n const plan = capstoneJourney(opts);\n logger.log(`\\n=== ${plan.title} (${plan.steps.length} steps) ===\\n`);\n\n const result = await runJourney(plan, client);\n\n for (const step of result.steps) {\n const viewSpec = step.panel.structuredContent?.['viewSpec'];\n logger.log(`--- panel: ${step.stepId} ---`);\n logger.log(JSON.stringify(viewSpec, null, 2));\n }\n\n if (!result.completed) {\n logger.error(\n `\\n[capstone] FAILED at step \"${result.error?.stepId}\": ${result.error?.message}`\n );\n return 1;\n }\n\n const receipt = extractReceipt(result);\n logger.log('\\n=== Settlement Receipt ===');\n logger.log(JSON.stringify(receipt, null, 2));\n logger.log(`\\n[capstone] completed all ${result.steps.length} steps.`);\n return 0;\n}\n\n/**\n * CLI entry. Reads connection + DeFi opts from env and runs the demo against a\n * live daemon. See module header for the live-run prerequisites.\n *\n * Env:\n * TOON_DAEMON_URL daemon control-plane base URL (default http://127.0.0.1:8787)\n * TOON_SWAP_DEST swap ILP destination (e.g. g.proxy.swap)\n * TOON_SWAP_AMOUNT source-asset amount, micro-units (e.g. 1000000)\n * TOON_SWAP_PUBKEY swap peer 64-char hex Nostr pubkey\n * TOON_CHAIN_RECIPIENT payout address on the target chain\n * TOON_SWAP_PAIR JSON SwapPair ({ from, to, rate, ... })\n * TOON_SOCIALFI_PUBKEY optional: seed panel bind-queries before onboard surfaces it\n */\nexport async function main(env: NodeJS.ProcessEnv = process.env): Promise<number> {\n const baseUrl = env['TOON_DAEMON_URL'] ?? 'http://127.0.0.1:8787';\n\n const destination = env['TOON_SWAP_DEST'];\n const amount = env['TOON_SWAP_AMOUNT'];\n const swapPubkey = env['TOON_SWAP_PUBKEY'];\n const chainRecipient = env['TOON_CHAIN_RECIPIENT'];\n const pairRaw = env['TOON_SWAP_PAIR'];\n\n if (!destination || !amount || !swapPubkey || !chainRecipient || !pairRaw) {\n console.error(\n '[capstone] missing required env: TOON_SWAP_DEST, TOON_SWAP_AMOUNT, ' +\n 'TOON_SWAP_PUBKEY, TOON_CHAIN_RECIPIENT, TOON_SWAP_PAIR are all required ' +\n 'for the live DeFi leg. See the module header for the full env contract.'\n );\n return 2;\n }\n\n let pair: DeFiJourneyOpts['pair'];\n try {\n pair = JSON.parse(pairRaw) as DeFiJourneyOpts['pair'];\n } catch (e) {\n console.error(`[capstone] TOON_SWAP_PAIR is not valid JSON: ${String(e)}`);\n return 2;\n }\n\n const client = new ControlClient({ baseUrl });\n const socialFiPubkey = env['TOON_SOCIALFI_PUBKEY'];\n\n return runCapstoneDemo(client, {\n ...(socialFiPubkey ? { socialFi: { pubkey: socialFiPubkey } } : {}),\n deFi: { destination, amount, swapPubkey, chainRecipient, pair },\n });\n}\n\n// Run when invoked directly (tsx src/journey/demo.ts or node dist/journey/demo.js).\nconst invokedDirectly =\n typeof process !== 'undefined' &&\n Array.isArray(process.argv) &&\n /[/\\\\]journey[/\\\\]demo\\.(ts|js|mjs)$/.test(process.argv[1] ?? '');\n\nif (invokedDirectly) {\n main()\n .then((code) => process.exit(code))\n .catch((err) => {\n console.error('[capstone] fatal:', err instanceof Error ? err.message : err);\n process.exit(1);\n });\n}\n"],"mappings":"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","names":[]}
|
package/dist/mcp.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
APP_RESOURCE_URI,
|
|
5
5
|
TOOL_DEFINITIONS,
|
|
6
6
|
dispatchTool
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-57G7AAEG.js";
|
|
8
8
|
import {
|
|
9
9
|
ControlClient,
|
|
10
10
|
defaultConfigPath,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
readConfigFile,
|
|
13
13
|
spawnDaemonDetached,
|
|
14
14
|
waitForReady
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-UEP6PFZN.js";
|
|
16
16
|
import "./chunk-32QD72IL.js";
|
|
17
17
|
import "./chunk-DLYE6U2Z.js";
|
|
18
18
|
import "./chunk-LR7W2ISE.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toon-protocol/client-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.2",
|
|
4
4
|
"description": "Always-on local daemon + MCP server letting a Claude agent (Desktop or Code) act as a TOON Protocol client: pay-to-write publishing, free reads, channel/balance management, and swaps.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Jonathan Green",
|
|
@@ -48,9 +48,9 @@
|
|
|
48
48
|
"tsx": "^4.19.2",
|
|
49
49
|
"typescript": "^5.3.0",
|
|
50
50
|
"vitest": "^1.0.0",
|
|
51
|
-
"@toon-protocol/
|
|
52
|
-
"@toon-protocol/
|
|
53
|
-
"@toon-protocol/
|
|
51
|
+
"@toon-protocol/arweave": "0.1.1",
|
|
52
|
+
"@toon-protocol/client": "0.14.4",
|
|
53
|
+
"@toon-protocol/views": "0.8.2"
|
|
54
54
|
},
|
|
55
55
|
"engines": {
|
|
56
56
|
"node": ">=20"
|