@toon-protocol/client-mcp 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/daemon.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  ClientRunner,
5
5
  registerRoutes,
6
6
  scaffoldFirstRun
7
- } from "./chunk-EY5GFEDH.js";
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-76CTU2A5.js";
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 mill peer, receive asset B + a signed
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 mill peer must be routed via
208
+ * against the open apex channel (the swap peer must be routed via
209
209
  * `apexChildPeers`).
210
210
  */
211
211
  interface SwapRequest {
212
- /** Mill peer ILP destination (e.g. `g.townhouse.mill`). */
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
- /** Mill's 64-char lowercase hex Nostr pubkey (NIP-59 gift-wrap recipient). */
217
- millPubkey: string;
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 mill announces pairs to a relay other than the town relay.
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 mill must be a child peer of this apex.
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 mill. */
246
+ /** Sender's payout address echoed by the swap peer. */
247
247
  recipient?: string;
248
- /** Mill's on-chain signer address. */
249
- millSignerAddress?: string;
250
- /** Mill-side claim id. */
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 mill FULFILLed. */
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 mill, if any (e.g. `F99`). */
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.townhouse.town`). */
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. `["dvm","mill"]`). */
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.townhouse.town`. */
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. `town`). */
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;
@@ -654,6 +654,12 @@ interface DaemonConfigFile {
654
654
  * override: `TOON_CLIENT_FAUCET_URL`.
655
655
  */
656
656
  faucetUrl?: string;
657
+ /**
658
+ * Faucet HTTP request timeout in milliseconds. When set it overrides the
659
+ * chain-aware default (fast 30s for evm/solana, 120s for the slow-settling
660
+ * mina faucet). Env override: `TOON_CLIENT_FAUCET_TIMEOUT_MS`.
661
+ */
662
+ faucetTimeoutMs?: number;
657
663
  /** Town relay WS URL for FREE reads. */
658
664
  relayUrl?: string;
659
665
  /**
@@ -698,9 +704,9 @@ interface DaemonConfigFile {
698
704
  */
699
705
  apexChains?: Partial<Record<SettlementChain, ApexNegotiationConfig>>;
700
706
  /**
701
- * Additional apex CHILD peers (last ILP segment, e.g. `["dvm","mill"]`)
707
+ * Additional apex CHILD peers (last ILP segment, e.g. `["store","swap"]`)
702
708
  * reachable via the SAME apex channel — used when publishing/swapping to
703
- * `g.townhouse.dvm` / `g.townhouse.mill`. The runner injects the apex
709
+ * `g.proxy.store` / `g.proxy.swap`. The runner injects the apex
704
710
  * negotiation under each and points it at the open apex channel (no extra
705
711
  * on-chain channel). The apex `peerId` itself is always handled.
706
712
  */
@@ -737,6 +743,12 @@ interface ResolvedDaemonConfig {
737
743
  proxyUrl?: string;
738
744
  /** Devnet faucet base URL, when configured. */
739
745
  faucetUrl?: string;
746
+ /**
747
+ * Explicit faucet HTTP request timeout (ms), when configured. Overrides the
748
+ * chain-aware default. When absent, {@link fundWallet} picks the per-chain
749
+ * default (longer for mina).
750
+ */
751
+ faucetTimeoutMs?: number;
740
752
  destination: string;
741
753
  /** Resolved default destination for relay-write publishes (falls back to `destination`). */
742
754
  publishDestination: string;
@@ -744,7 +756,7 @@ interface ResolvedDaemonConfig {
744
756
  storeDestination: string;
745
757
  feePerEvent: bigint;
746
758
  apex?: ApexNegotiationConfig;
747
- /** Apex child peers reached via the same apex channel (e.g. dvm, mill). */
759
+ /** Apex child peers reached via the same apex channel (e.g. store, swap). */
748
760
  apexChildPeers?: string[];
749
761
  /** The active settlement chain for paid writes. */
750
762
  chain: SettlementChain;
@@ -1004,7 +1016,7 @@ declare class ClientRunner {
1004
1016
  private discoverApexNegotiation;
1005
1017
  /** Inject the apex settlement negotiation directly into its ToonClient. */
1006
1018
  private injectApexNegotiation;
1007
- /** Route apex CHILD peers (dvm/mill) through the SAME apex payment channel. */
1019
+ /** Route apex CHILD peers (store/swap) through the SAME apex payment channel. */
1008
1020
  private routeChildPeersThroughApexChannel;
1009
1021
  private defaultApex;
1010
1022
  /** Whether any apex has finished bootstrapping. */
@@ -1053,7 +1065,7 @@ declare class ClientRunner {
1053
1065
  }>;
1054
1066
  /** List tracked channels across ALL apexes with nonce + cumulative amount. */
1055
1067
  getChannels(): ChannelsResponse;
1056
- /** Swap source→target asset against a mill peer via the selected apex. */
1068
+ /** Swap source→target asset against a swap peer via the selected apex. */
1057
1069
  swap(req: SwapRequest): Promise<SwapResponse>;
1058
1070
  /**
1059
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-EY5GFEDH.js";
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-PX3DOSEG.js";
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-76CTU2A5.js";
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: DVM upload (kind:1063) + media-embed read-back ──────────────
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: "dvm-upload",
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
- millPubkey: opts.millPubkey,
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 millPubkey = env["TOON_MILL_PUBKEY"];
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 || !millPubkey || !chainRecipient || !pairRaw) {
387
+ if (!destination || !amount || !swapPubkey || !chainRecipient || !pairRaw) {
388
388
  console.error(
389
- "[capstone] missing required env: TOON_SWAP_DEST, TOON_SWAP_AMOUNT, TOON_MILL_PUBKEY, TOON_CHAIN_RECIPIENT, TOON_SWAP_PAIR are all required for the live DeFi leg. See the module header for the full env contract."
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, millPubkey, chainRecipient, pair }
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-PX3DOSEG.js";
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-76CTU2A5.js";
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.7.0",
3
+ "version": "0.8.0",
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",
@@ -49,8 +49,8 @@
49
49
  "typescript": "^5.3.0",
50
50
  "vitest": "^1.0.0",
51
51
  "@toon-protocol/arweave": "0.1.1",
52
- "@toon-protocol/views": "0.7.0",
53
- "@toon-protocol/client": "0.14.2"
52
+ "@toon-protocol/client": "0.14.4",
53
+ "@toon-protocol/views": "0.8.0"
54
54
  },
55
55
  "engines": {
56
56
  "node": ">=20"