@routedock/routedock 0.1.2 → 0.2.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.
Files changed (74) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +227 -4
  3. package/dist/MppSessionHandler-B4TyD7Xg.d.cts +121 -0
  4. package/dist/MppSessionHandler-CLB5SzgN.d.ts +121 -0
  5. package/dist/ProviderRegistry-BJ9oJLVz.d.cts +142 -0
  6. package/dist/ProviderRegistry-C50nyhaF.d.ts +142 -0
  7. package/dist/RouteDockClient-B1roCa8h.d.cts +455 -0
  8. package/dist/RouteDockClient-BbkqjhMG.d.ts +455 -0
  9. package/dist/SessionReconciler-Dscw43F3.d.ts +125 -0
  10. package/dist/SessionReconciler-bi0z2qtN.d.cts +125 -0
  11. package/dist/SessionStore-BpK8vv0L.d.cts +111 -0
  12. package/dist/SessionStore-DvkZv8-E.d.ts +111 -0
  13. package/dist/client.cjs +2419 -202
  14. package/dist/client.d.cts +50 -81
  15. package/dist/client.d.ts +50 -81
  16. package/dist/client.js +2373 -203
  17. package/dist/index.cjs +3080 -298
  18. package/dist/index.d.cts +12 -3
  19. package/dist/index.d.ts +12 -3
  20. package/dist/index.js +3026 -298
  21. package/dist/provider/fastify.cjs +882 -0
  22. package/dist/provider/fastify.d.cts +35 -0
  23. package/dist/provider/fastify.d.ts +35 -0
  24. package/dist/provider/fastify.js +880 -0
  25. package/dist/provider/hono.cjs +948 -0
  26. package/dist/provider/hono.d.cts +99 -0
  27. package/dist/provider/hono.d.ts +99 -0
  28. package/dist/provider/hono.js +938 -0
  29. package/dist/provider.cjs +827 -97
  30. package/dist/provider.d.cts +32 -25
  31. package/dist/provider.d.ts +32 -25
  32. package/dist/provider.js +810 -99
  33. package/dist/react.cjs +2641 -0
  34. package/dist/react.d.cts +107 -0
  35. package/dist/react.d.ts +107 -0
  36. package/dist/react.js +2634 -0
  37. package/dist/routedockMiddleware-BlDsHuPl.d.ts +59 -0
  38. package/dist/routedockMiddleware-D97A5ptQ.d.cts +59 -0
  39. package/dist/schema.cjs +364 -0
  40. package/dist/schema.d.cts +3 -0
  41. package/dist/schema.d.ts +3 -0
  42. package/dist/schema.js +359 -0
  43. package/dist/sign-CUf3rhTx.d.cts +53 -0
  44. package/dist/sign-Dpj2Mp7k.d.ts +53 -0
  45. package/dist/testing.cjs +57 -0
  46. package/dist/testing.d.cts +95 -0
  47. package/dist/testing.d.ts +95 -0
  48. package/dist/testing.js +54 -0
  49. package/dist/types-DmhmfLzP.d.cts +410 -0
  50. package/dist/types-DmhmfLzP.d.ts +410 -0
  51. package/package.json +143 -23
  52. package/PUBLISH_CHECKLIST.md +0 -70
  53. package/dist/SessionStore-CCVO0PHM.d.cts +0 -152
  54. package/dist/SessionStore-CCVO0PHM.d.ts +0 -152
  55. package/dist/routedockMiddleware-B7WTB3LT.d.cts +0 -53
  56. package/dist/routedockMiddleware-DRgdrycG.d.ts +0 -53
  57. package/src/client/ModeRouter.ts +0 -104
  58. package/src/client/MppChargeClient.ts +0 -44
  59. package/src/client/MppSessionClient.ts +0 -144
  60. package/src/client/RouteDockClient.ts +0 -124
  61. package/src/client/index.ts +0 -8
  62. package/src/client/x402Client.ts +0 -84
  63. package/src/index.ts +0 -9
  64. package/src/provider/MppChargeHandler.ts +0 -90
  65. package/src/provider/MppSessionHandler.ts +0 -157
  66. package/src/provider/index.ts +0 -7
  67. package/src/provider/routedockMiddleware.ts +0 -154
  68. package/src/provider/x402Handler.ts +0 -164
  69. package/src/schemas/routedock.schema.json +0 -159
  70. package/src/store/SessionStore.ts +0 -90
  71. package/src/tests/smoke.test.ts +0 -228
  72. package/src/types.ts +0 -165
  73. package/tsconfig.json +0 -14
  74. package/tsup.config.ts +0 -15
@@ -0,0 +1,95 @@
1
+ import { RequestHandler } from 'express';
2
+ import { P as PaymentMode } from './types-DmhmfLzP.js';
3
+ import 'mppx';
4
+
5
+ /**
6
+ * Provider settlement callbacks under test. Same shape as the real
7
+ * `RouteDockMiddlewareOptions` callbacks, but accept sync or async fns so a
8
+ * plain test spy works without wrapping it in a Promise.
9
+ */
10
+ interface MockRoutedockCallbacks {
11
+ /** Called after each (synthetic) on-chain settlement. */
12
+ onSettled?: (txHash: string, amount: string, mode: string) => void | Promise<void>;
13
+ /** Called once when a synthetic mpp-session is opened (first voucher). */
14
+ onSessionOpen?: (channelId: string) => void | Promise<void>;
15
+ /** Called for each synthetic voucher in an mpp-session (1-based index). */
16
+ onVoucher?: (channelId: string, voucherIndex: number, cumulativeAmount: string, signature: string) => void | Promise<void>;
17
+ }
18
+ /** Synthetic settlement values handed to the callbacks. All optional — sensible defaults per mode. */
19
+ interface SyntheticPayment {
20
+ /** On-chain tx hash passed to onSettled. Default: a fixed 64-hex string. */
21
+ txHash?: string;
22
+ /** Settled amount (x402 / mpp-charge) passed to onSettled. Default: '0.001'. */
23
+ amount?: string;
24
+ /** Channel address (mpp-session) passed to onSessionOpen. Default: a fixed C... address. */
25
+ channelId?: string;
26
+ /** Per-voucher rate (mpp-session), in decimal string. Default: '0.0001'. */
27
+ rate?: string;
28
+ /** Number of vouchers to emit before close (mpp-session). Default: 3. */
29
+ voucherCount?: number;
30
+ }
31
+ interface MockRoutedockOptions extends MockRoutedockCallbacks {
32
+ /** Payment mode the synthetic payment uses. Default: 'x402'. */
33
+ mode?: PaymentMode;
34
+ /**
35
+ * 'auto-pass' (default): synthesize a successful settlement, invoke the
36
+ * configured callbacks with synthetic data, then call the route handler.
37
+ * 'auto-fail': respond with `failStatus` and skip both callbacks and handler.
38
+ */
39
+ payment?: 'auto-pass' | 'auto-fail';
40
+ /** Override the synthetic data handed to callbacks. */
41
+ synthetic?: SyntheticPayment;
42
+ /** HTTP status used on 'auto-fail'. Default: 402. */
43
+ failStatus?: number;
44
+ }
45
+ /** Synthetic settlement record attached to `req.routedock` for assertions. */
46
+ interface MockSettlementRecord {
47
+ mode: PaymentMode;
48
+ txHash: string;
49
+ amount: string;
50
+ channelId?: string;
51
+ vouchers?: Array<{
52
+ index: number;
53
+ cumulativeAmount: string;
54
+ }>;
55
+ }
56
+ /**
57
+ * Drive a provider's settlement callbacks with synthetic data, with no Express
58
+ * request involved. Useful for unit-testing an `onSettled` (e.g. a Supabase
59
+ * write) in complete isolation. Returns the synthetic settlement record.
60
+ *
61
+ * Honors `payment: 'auto-fail'` by invoking no callbacks and returning null.
62
+ */
63
+ declare function runMockSettlement(opts: MockRoutedockOptions): Promise<MockSettlementRecord | null>;
64
+ /**
65
+ * Express middleware that mocks RouteDock payment verification — the testing
66
+ * counterpart to `routedock()`. Drop it in front of a route to drive that
67
+ * route's settlement callbacks with synthetic data, without any on-chain
68
+ * settlement, facilitator, or wallet. Think `msw` for RouteDock providers.
69
+ *
70
+ * On `payment: 'auto-pass'` (default) it invokes the configured callbacks with
71
+ * synthetic data and then calls the next handler (your route). On
72
+ * `payment: 'auto-fail'` it responds with `failStatus` (402 by default) and
73
+ * skips both the callbacks and the route handler — exactly as a real payment
74
+ * rejection would.
75
+ *
76
+ * The synthetic settlement is attached to `req.routedock` for assertions.
77
+ *
78
+ * @example
79
+ * ```ts
80
+ * import express from 'express'
81
+ * import request from 'supertest'
82
+ * import { createMockRoutedockMiddleware } from '@routedock/routedock/testing'
83
+ *
84
+ * const onSettled = vi.fn()
85
+ * const app = express()
86
+ * app.use('/price', createMockRoutedockMiddleware({ mode: 'x402', payment: 'auto-pass', onSettled }))
87
+ * app.get('/price', (_req, res) => res.json({ price: '42' }))
88
+ *
89
+ * await request(app).get('/price').expect(200)
90
+ * expect(onSettled).toHaveBeenCalledWith(expect.any(String), '0.001', 'x402')
91
+ * ```
92
+ */
93
+ declare function createMockRoutedockMiddleware(opts?: MockRoutedockOptions): RequestHandler;
94
+
95
+ export { type MockRoutedockCallbacks, type MockRoutedockOptions, type MockSettlementRecord, type SyntheticPayment, createMockRoutedockMiddleware, runMockSettlement };
@@ -0,0 +1,54 @@
1
+ // src/testing/createMockRoutedockMiddleware.ts
2
+ var DEFAULT_TX_HASH = "0000000000000000000000000000000000000000000000000000000000000000";
3
+ var DEFAULT_CHANNEL_ID = "CCK4XOW3YKQUEZFONUTINKMSNW7SNMRQZURME5U3UP7E6WNGK7UHUCAH";
4
+ function format7(scaled) {
5
+ return (Number(scaled) / 1e7).toFixed(7);
6
+ }
7
+ function toScaled(decimal) {
8
+ const [whole, frac = ""] = decimal.split(".");
9
+ const fracPadded = (frac + "0000000").slice(0, 7);
10
+ return BigInt(whole + fracPadded);
11
+ }
12
+ async function runMockSettlement(opts) {
13
+ const mode = opts.mode ?? "x402";
14
+ if ((opts.payment ?? "auto-pass") === "auto-fail") return null;
15
+ const s = opts.synthetic ?? {};
16
+ const txHash = s.txHash ?? DEFAULT_TX_HASH;
17
+ if (mode === "mpp-session") {
18
+ const channelId = s.channelId ?? DEFAULT_CHANNEL_ID;
19
+ const rate = toScaled(s.rate ?? "0.0001");
20
+ const count = s.voucherCount ?? 3;
21
+ if (opts.onSessionOpen) await opts.onSessionOpen(channelId);
22
+ const vouchers = [];
23
+ for (let i = 1; i <= count; i++) {
24
+ const cumulativeAmount = format7(rate * BigInt(i));
25
+ vouchers.push({ index: i, cumulativeAmount });
26
+ if (opts.onVoucher) await opts.onVoucher(channelId, i, cumulativeAmount, "0000000000000000000000000000000000000000000000000000000000000000");
27
+ }
28
+ const totalPaid = format7(rate * BigInt(count));
29
+ if (opts.onSettled) await opts.onSettled(txHash, totalPaid, "mpp-session");
30
+ return { mode, txHash, amount: totalPaid, channelId, vouchers };
31
+ }
32
+ const amount = s.amount ?? "0.001";
33
+ if (opts.onSettled) await opts.onSettled(txHash, amount, mode);
34
+ return { mode, txHash, amount };
35
+ }
36
+ function createMockRoutedockMiddleware(opts = {}) {
37
+ const payment = opts.payment ?? "auto-pass";
38
+ const failStatus = opts.failStatus ?? 402;
39
+ return (req, res, next) => {
40
+ if (payment === "auto-fail") {
41
+ res.status(failStatus).json({
42
+ error: "payment required",
43
+ detail: "mock routedock middleware: payment=auto-fail"
44
+ });
45
+ return;
46
+ }
47
+ void runMockSettlement(opts).then((record) => {
48
+ if (record) req.routedock = record;
49
+ next();
50
+ }).catch((err) => next(err));
51
+ };
52
+ }
53
+
54
+ export { createMockRoutedockMiddleware, runMockSettlement };
@@ -0,0 +1,410 @@
1
+ import { Store } from 'mppx';
2
+
3
+ /**
4
+ * TypeScript types for the RouteDock manifest format.
5
+ * Derived from packages/sdk/src/schemas/routedock.schema.json (draft-07).
6
+ *
7
+ * Section 5 of ROUTEDOCK_MASTER.md is the canonical specification.
8
+ */
9
+
10
+ type PaymentMode = 'x402' | 'mpp-charge' | 'mpp-session' | 'mpp-session-ws';
11
+ /**
12
+ * Agent custody mode — declared in routedock.json when provider accepts ZK vault payers.
13
+ * `nulth` = Nulth proof-authorized account (the ZK-account primitive; formerly "covenant-zk").
14
+ */
15
+ type VaultMode = 'local-key' | 'agent-vault' | 'nulth';
16
+ /** Per-request pricing config — used by x402 and mpp-charge modes */
17
+ interface PricingConfig {
18
+ /** Cost per request in the payment asset, e.g. "0.001" */
19
+ amount: string;
20
+ per: 'request';
21
+ /** x402 facilitator URL (OpenZeppelin Channels). Required for x402 mode. */
22
+ facilitator?: string;
23
+ /**
24
+ * Optional per-mode payee override (Stellar G... address). When set, payments
25
+ * for this mode are directed here instead of the top-level manifest `payee`,
26
+ * enabling treasury separation by settlement type (e.g. x402 → facilitator
27
+ * hot wallet, mpp-charge → direct-settlement account). Falls back to the
28
+ * top-level `payee` when omitted.
29
+ */
30
+ payee?: string;
31
+ }
32
+ /** Per-voucher pricing config — used by mpp-session (one-way-channel) mode */
33
+ interface SessionPricingConfig {
34
+ /** Cost per voucher, e.g. "0.0001" */
35
+ rate: string;
36
+ per: 'voucher';
37
+ /** Stable Soroban factory address (C...) used to deploy a per-session channel */
38
+ channel_factory: string;
39
+ /** Minimum initial deposit to open a channel, e.g. "0.10" */
40
+ min_deposit: string;
41
+ /**
42
+ * Ledgers the server has to settle before the funder can reclaim.
43
+ * Default: 17280 (~24h). Do NOT reduce in production — this is a
44
+ * security parameter the server depends on to settle first.
45
+ */
46
+ refund_waiting_period_ledgers: number;
47
+ }
48
+ /** SLA configuration */
49
+ interface SLAConfig {
50
+ uptime_30d_percent: number;
51
+ p95_latency_ms: number;
52
+ maintenance_windows?: {
53
+ cron: string;
54
+ duration_minutes: number;
55
+ }[];
56
+ }
57
+ /** Endpoint descriptor */
58
+ interface EndpointDescriptor {
59
+ method: string;
60
+ path: string;
61
+ /**
62
+ * Whether this endpoint is retained only for backwards compatibility.
63
+ * The SDK logs a `[RouteDock] WARNING:` line before paying a deprecated
64
+ * endpoint.
65
+ */
66
+ deprecated?: boolean;
67
+ /**
68
+ * ISO 8601 timestamp after which callers should stop using this endpoint.
69
+ * The SDK refuses to pay (`RouteDockManifestSunsetError`) once it has passed.
70
+ */
71
+ sunset_at?: string;
72
+ headers?: Record<string, string>;
73
+ request_schema?: unknown;
74
+ response_schema?: unknown;
75
+ rate_limit?: {
76
+ requests: number;
77
+ window_seconds: number;
78
+ };
79
+ }
80
+ /** Full RouteDock discovery manifest — served at /.well-known/routedock.json */
81
+ interface RouteDockManifest {
82
+ /** Manifest schema version (major.minor), e.g. "1.0", "1.1", "2.0" */
83
+ routedock: string;
84
+ /**
85
+ * Minimum SDK client version (major.minor) required to use this manifest.
86
+ * Clients below this version must refuse to pay.
87
+ */
88
+ min_client_version?: string;
89
+ /**
90
+ * Payment modes still listed in `modes` for backwards compatibility
91
+ * but deprecated for new integrations.
92
+ */
93
+ deprecated_modes?: PaymentMode[];
94
+ /** ISO 8601 timestamp after which this manifest version is no longer supported. */
95
+ sunset_at?: string;
96
+ /** Human-readable provider name */
97
+ name: string;
98
+ /** Human-readable description of the provider's data or service */
99
+ description: string;
100
+ /** Payment modes supported by this provider */
101
+ modes: PaymentMode[];
102
+ /** Stellar network this provider operates on */
103
+ network: 'testnet' | 'mainnet';
104
+ /** Asset ticker symbol, e.g. "USDC" */
105
+ asset: string;
106
+ /** Stellar Asset Contract (SAC) address for the payment asset */
107
+ asset_contract: string;
108
+ /**
109
+ * Stellar address (G...) that receives payments. Used as the default
110
+ * recipient for all modes. Individual per-request modes (x402, mpp-charge)
111
+ * may override this via `pricing.<mode>.payee` for treasury separation.
112
+ * Note: mpp-session settlements always land in the server signer's account
113
+ * (the channel pays out to the closer), so they cannot be redirected by a
114
+ * manifest field and always use this top-level `payee` for discovery display.
115
+ */
116
+ payee: string;
117
+ /** Pricing configuration per supported payment mode */
118
+ pricing: {
119
+ x402?: PricingConfig;
120
+ 'mpp-charge'?: PricingConfig;
121
+ 'mpp-session'?: SessionPricingConfig;
122
+ /**
123
+ * WebSocket transport variant of mpp-session. The channel is opened and the
124
+ * first voucher negotiated over HTTP exactly like mpp-session, then the
125
+ * connection upgrades to WebSocket for push-based streaming (OpenAI-style
126
+ * inference providers). Same SessionPricingConfig shape — only the
127
+ * streaming transport differs.
128
+ */
129
+ 'mpp-session-ws'?: SessionPricingConfig;
130
+ };
131
+ /** Service Level Agreement for the provider */
132
+ sla?: SLAConfig;
133
+ /** Map of endpoint name to endpoint descriptors */
134
+ endpoints: Record<string, EndpointDescriptor>;
135
+ /** Capability tags indexed with trigram search in the provider registry */
136
+ tags: string[];
137
+ /**
138
+ * Optional vault custody mode declared by the provider.
139
+ * When set to `nulth`, the provider accepts payers using Nulth smart accounts.
140
+ */
141
+ vault?: VaultMode;
142
+ /**
143
+ * Optional Nulth smart account address (C...) that this provider is linked to.
144
+ * Used by the client to verify the nulth_account before sending proofs.
145
+ */
146
+ nulth_account?: string;
147
+ /** Optional protocol features this provider supports */
148
+ capabilities?: {
149
+ /** Supported streaming transports */
150
+ streaming?: ('sse' | 'websocket')[];
151
+ /** Whether webhook callbacks are supported */
152
+ webhooks?: boolean;
153
+ /** Whether idempotency keys are supported */
154
+ idempotency_keys?: boolean;
155
+ /** Supported content types for request/response */
156
+ content_types?: string[];
157
+ };
158
+ /**
159
+ * IATA airport codes or UN/LOCODE identifiers for regions where this provider
160
+ * has infrastructure (e.g. ["IAD", "AMS"]). Used by agents to select the
161
+ * nearest provider and reduce mpp-session round-trip latency.
162
+ */
163
+ regions?: string[];
164
+ /**
165
+ * Provider-declared p50 latency in milliseconds per region code.
166
+ * Keys must be a subset of `regions`. Agents can use these hints to
167
+ * rank providers by expected round-trip cost before opening a session.
168
+ * Example: { "IAD": 14, "AMS": 22 }
169
+ */
170
+ latency_hints?: Record<string, number>;
171
+ /**
172
+ * Base64 Ed25519 signature of the payee keypair over the SHA-256 digest of
173
+ * this manifest with the `signature` field omitted. Clients must verify this
174
+ * before trusting any routing field (payee, endpoints, pricing).
175
+ */
176
+ signature?: string;
177
+ /** Canonical manifest-signature format. Version 2 signs nested fields recursively. */
178
+ signature_version?: '2';
179
+ /** Optional hierarchical categories from a published taxonomy (e.g. "data/price/crypto") */
180
+ categories?: string[];
181
+ }
182
+ /** Result returned by client.pay() for any payment mode */
183
+ interface PaymentResult {
184
+ /** Parsed response body from the provider */
185
+ data: unknown;
186
+ /** On-chain Stellar transaction hash, or null for session voucher calls */
187
+ txHash: string | null;
188
+ /** Payment mode that was used for this call */
189
+ mode: PaymentMode;
190
+ /** Amount paid in the payment asset (decimal string) */
191
+ amount: string;
192
+ /** Unix timestamp (ms) when the payment completed */
193
+ timestamp: number;
194
+ }
195
+ /** Result returned by client.preflight() — summary of trustline status and provider capabilities */
196
+ interface PreflightResult {
197
+ /** Whether the trustline exists on-chain for the payer */
198
+ hasTrustline: boolean;
199
+ /** Payment asset ticker, e.g. "USDC" */
200
+ asset: string;
201
+ /** Payment modes supported by this provider */
202
+ modes: PaymentMode[];
203
+ /** Regions where this provider has infrastructure */
204
+ regions?: string[];
205
+ /** Provider-declared p50 latency in milliseconds per region code */
206
+ latency_hints?: Record<string, number>;
207
+ /** Optional protocol features supported by this provider */
208
+ capabilities?: RouteDockManifest['capabilities'];
209
+ }
210
+ /** Result returned by client.estimateCost() — the expected charge without submitting any transaction */
211
+ interface EstimateCostResult {
212
+ /** Expected charge in the payment asset (decimal string, e.g. "0.001") */
213
+ amount: string;
214
+ /** Payment asset ticker, e.g. "USDC" */
215
+ asset: string;
216
+ /** Payment mode that would be used */
217
+ mode: PaymentMode;
218
+ /** Full manifest — available for approval-gate / budget-routing decisions */
219
+ manifest: RouteDockManifest;
220
+ /** Regions where this provider has infrastructure */
221
+ regions?: string[];
222
+ /** Provider-declared p50 latency in milliseconds per region code */
223
+ latency_hints?: Record<string, number>;
224
+ /** Optional protocol features supported by this provider */
225
+ capabilities?: RouteDockManifest['capabilities'];
226
+ }
227
+ /** Result returned by session.close() */
228
+ interface SessionCloseResult {
229
+ /** On-chain transaction hash for the channel close */
230
+ closeTxHash: string;
231
+ /** Total amount settled across all vouchers (decimal string) */
232
+ totalPaid: string;
233
+ /** Number of vouchers issued during the session */
234
+ vouchersIssued: number;
235
+ }
236
+ /**
237
+ * Live session statistics returned by {@link SessionHandle.stats}.
238
+ * Read at any point during the session — no need to close it first.
239
+ */
240
+ interface SessionStats {
241
+ /** Number of vouchers issued so far in this session */
242
+ vouchersIssued: number;
243
+ /**
244
+ * Cumulative amount authorized across all signed vouchers so far, in
245
+ * payment-asset decimal units (e.g. "0.0001"). Matches the units of
246
+ * {@link SessionCloseResult.totalPaid}, so a per-session sub-cap can be
247
+ * enforced by comparing against it mid-stream.
248
+ */
249
+ currentCumulative: string;
250
+ /** Stellar channel contract address (C...) */
251
+ channelId: string;
252
+ /**
253
+ * Transaction hash of the on-chain channel-open call, or null for a
254
+ * pre-deployed channel (no open transaction was issued).
255
+ */
256
+ openTxHash: string | null;
257
+ }
258
+ /** Default wall-clock lifetime of a session before it auto-closes (1h). */
259
+ declare const DEFAULT_MAX_SESSION_DURATION_MS = 3600000;
260
+ /** Options accepted by client.openSession() */
261
+ interface SessionOptions {
262
+ /**
263
+ * Session payment mode. Defaults to 'mpp-session' (SSE-style one HTTP
264
+ * request per voucher). Set to 'mpp-session-ws' to negotiate the channel
265
+ * and first voucher over HTTP and then upgrade the connection to WebSocket
266
+ * for push-based streaming. Requires the provider's manifest to advertise
267
+ * the selected mode.
268
+ */
269
+ mode?: 'mpp-session' | 'mpp-session-ws';
270
+ /**
271
+ * Maximum wall-clock lifetime of the session in milliseconds. When the
272
+ * timer fires, the session emits 'session:timeout' and auto-closes so an
273
+ * orphaned channel cannot keep collateral locked on-chain indefinitely.
274
+ * Defaults to {@link DEFAULT_MAX_SESSION_DURATION_MS} (1h). Pass 0 or
275
+ * Infinity to disable the guard (not recommended).
276
+ */
277
+ maxDurationMs?: number;
278
+ /**
279
+ * Optional persistent store for the client-side cumulative baseline.
280
+ *
281
+ * Every challenge is validated against what this client has already signed,
282
+ * so without a store a session refuses a challenge that reports a non-zero
283
+ * cumulative — it cannot tell how much a channel already owes from an earlier
284
+ * session (e.g. across an agent restart that skipped `close()`). Supply a
285
+ * store to resume such a channel, or close it first.
286
+ */
287
+ store?: Store.Store;
288
+ }
289
+ /**
290
+ * Lifecycle events emitted by a SessionHandle.
291
+ *
292
+ * - 'session:timeout' — the maxDurationMs budget elapsed; auto-close started.
293
+ * - 'session:close-failed' — that auto-close rejected. The channel may still
294
+ * hold collateral, so the caller should retry close() or fall back to
295
+ * requestRefund().
296
+ */
297
+ type SessionEvent = 'session:timeout' | 'session:close-failed';
298
+ /** Payload delivered with the 'session:timeout' event. */
299
+ interface SessionTimeoutPayload {
300
+ /** The wall-clock budget (ms) that elapsed before auto-close was triggered. */
301
+ maxDurationMs: number;
302
+ }
303
+ /** Payload delivered with the 'session:close-failed' event. */
304
+ interface SessionCloseFailedPayload {
305
+ /** The wall-clock budget (ms) that elapsed before auto-close was triggered. */
306
+ maxDurationMs: number;
307
+ /**
308
+ * The rejection thrown by the failed auto-close. Typed `unknown` because the
309
+ * close path wraps transport, RPC, and channel-state failures, and a rejection
310
+ * is not guaranteed to be an Error.
311
+ */
312
+ error: unknown;
313
+ }
314
+ /**
315
+ * Maps each lifecycle event to the payload its listener receives, so on() can
316
+ * narrow the callback argument per event.
317
+ */
318
+ interface SessionEventPayloadMap {
319
+ 'session:timeout': SessionTimeoutPayload;
320
+ 'session:close-failed': SessionCloseFailedPayload;
321
+ }
322
+ /**
323
+ * Options for SessionHandle.stream().
324
+ */
325
+ interface StreamOptions {
326
+ /**
327
+ * Maximum number of voucher requests outstanding at once before backpressure
328
+ * is applied. Default: 1 (strictly sequential — safe for all providers).
329
+ * Increase only when the provider explicitly advertises support for concurrent
330
+ * vouchers; out-of-order sequence numbers will cause payment failures otherwise.
331
+ */
332
+ concurrency?: number;
333
+ }
334
+ /** Handle for a live MPP session returned by client.openSession() */
335
+ interface SessionHandle {
336
+ /** Stellar channel contract address (C...) */
337
+ channelId: string;
338
+ /**
339
+ * Transaction hash of the on-chain channel-open call, or null.
340
+ * The one-way-channel contract is deployed and funded before the agent
341
+ * runs, so openSession() performs no on-chain open and has no hash to
342
+ * report — it returns null rather than a non-transaction identifier.
343
+ */
344
+ openTxHash: string | null;
345
+ /**
346
+ * Async generator of streamed data.
347
+ *
348
+ * mpp-session: each iteration sends a voucher over HTTP and yields the
349
+ * parsed response body. With default concurrency (1) the next voucher is not
350
+ * issued until the provider returns HTTP 200 for the previous one.
351
+ *
352
+ * mpp-session-ws: opens the channel and negotiates the first voucher over
353
+ * HTTP, upgrades the connection to WebSocket, and yields each server frame
354
+ * (JSON frames parsed, raw strings yielded as-is). The stream ends when the
355
+ * server closes the socket with a normal close code.
356
+ *
357
+ * Once close() has been called (manually or by the maxDurationMs lifetime
358
+ * guard), the next next() on an mpp-session iterator rejects with a
359
+ * RouteDockChannelStateError whose message is "session closed" instead of
360
+ * signing another voucher. Pipelined streams (concurrency > 1) stop refilling
361
+ * their in-flight window the same way.
362
+ * UNAUDITED: uses stellar-experimental/one-way-channel contract.
363
+ */
364
+ stream(options?: StreamOptions): AsyncIterable<unknown>;
365
+ /**
366
+ * Snapshot of live session statistics (vouchers issued, cumulative amount
367
+ * authorized, channel identity). Values are updated synchronously on every
368
+ * stream() yield, so callers can log spend or enforce a per-session sub-cap
369
+ * without terminating the session.
370
+ */
371
+ stats(): SessionStats;
372
+ /** Close the channel on-chain with the highest signed voucher */
373
+ close(): Promise<SessionCloseResult>;
374
+ /** Request refund from the channel contract (initiates dispute) */
375
+ requestRefund(): Promise<string>;
376
+ /** Server-side counter-mechanism to settle with latest voucher before refund window expires */
377
+ settleWithLatestVoucher(): Promise<string>;
378
+ /** Get the current dispute status of the channel */
379
+ getDisputeStatus(): Promise<DisputeStatus>;
380
+ /**
381
+ * Subscribe to a session lifecycle event (e.g. 'session:timeout').
382
+ * Returns an unsubscribe function. Throwing inside the listener is caught;
383
+ * a rejected promise it returns is swallowed the same way.
384
+ */
385
+ on<E extends SessionEvent>(event: E, listener: (payload: SessionEventPayloadMap[E]) => void): () => void;
386
+ }
387
+ /**
388
+ * Durable session state stored in Supabase (sessions table).
389
+ * cumulative_amount is a decimal string to avoid float precision loss.
390
+ * The monotonic invariant is enforced both here and at the DB level via trigger.
391
+ */
392
+ interface SessionState {
393
+ channel_id: string;
394
+ payee: string;
395
+ payer: string;
396
+ channel_contract: string;
397
+ network: 'testnet' | 'mainnet';
398
+ /** Monotonically increasing cumulative amount — stored as string to preserve precision */
399
+ cumulative_amount: string;
400
+ last_signature: string;
401
+ status: 'open' | 'closing' | 'closed';
402
+ opened_at: string;
403
+ updated_at: string;
404
+ settlement_tx_hash: string | null;
405
+ }
406
+
407
+ /** Dispute status of a channel */
408
+ type DisputeStatus = 'open' | 'in-refund-window' | 'refundable' | 'settled';
409
+
410
+ export { DEFAULT_MAX_SESSION_DURATION_MS as D, type EndpointDescriptor as E, type PaymentMode as P, type RouteDockManifest as R, type SLAConfig as S, type VaultMode as V, type DisputeStatus as a, type EstimateCostResult as b, type PaymentResult as c, type PreflightResult as d, type PricingConfig as e, type SessionCloseFailedPayload as f, type SessionCloseResult as g, type SessionEvent as h, type SessionEventPayloadMap as i, type SessionHandle as j, type SessionOptions as k, type SessionPricingConfig as l, type SessionState as m, type SessionStats as n, type SessionTimeoutPayload as o, type StreamOptions as p };