@routedock/routedock 0.2.0 → 0.3.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 (50) hide show
  1. package/README.md +305 -0
  2. package/dist/MppSessionHandler-1EL8QBAn.d.cts +215 -0
  3. package/dist/MppSessionHandler-Bq4S-JTE.d.ts +215 -0
  4. package/dist/{ProviderRegistry-C50nyhaF.d.ts → ProviderRegistry-CA_TdREG.d.ts} +2 -2
  5. package/dist/{ProviderRegistry-BJ9oJLVz.d.cts → ProviderRegistry-D-0rqK0N.d.cts} +2 -2
  6. package/dist/{RouteDockClient-B1roCa8h.d.cts → RouteDockClient-Bh86bVly.d.ts} +23 -9
  7. package/dist/{RouteDockClient-BbkqjhMG.d.ts → RouteDockClient-go9aopfF.d.cts} +23 -9
  8. package/dist/{SessionReconciler-Dscw43F3.d.ts → SessionReconciler-Bw-PoBVl.d.ts} +14 -5
  9. package/dist/{SessionReconciler-bi0z2qtN.d.cts → SessionReconciler-Cz2nuOlJ.d.cts} +14 -5
  10. package/dist/{SessionStore-DvkZv8-E.d.ts → SessionStore-B4-Hi4H8.d.cts} +34 -2
  11. package/dist/{SessionStore-BpK8vv0L.d.cts → SessionStore-BaYiegP0.d.ts} +34 -2
  12. package/dist/client.cjs +429 -117
  13. package/dist/client.d.cts +9 -8
  14. package/dist/client.d.ts +9 -8
  15. package/dist/client.js +421 -119
  16. package/dist/index.cjs +652 -220
  17. package/dist/index.d.cts +8 -8
  18. package/dist/index.d.ts +8 -8
  19. package/dist/index.js +643 -221
  20. package/dist/{types-DmhmfLzP.d.cts → logger-D8_Q2ytp.d.cts} +58 -1
  21. package/dist/{types-DmhmfLzP.d.ts → logger-D8_Q2ytp.d.ts} +58 -1
  22. package/dist/provider/fastify.cjs +306 -89
  23. package/dist/provider/fastify.d.cts +9 -4
  24. package/dist/provider/fastify.d.ts +9 -4
  25. package/dist/provider/fastify.js +305 -88
  26. package/dist/provider/hono.cjs +286 -82
  27. package/dist/provider/hono.d.cts +9 -7
  28. package/dist/provider/hono.d.ts +9 -7
  29. package/dist/provider/hono.js +282 -78
  30. package/dist/provider.cjs +326 -98
  31. package/dist/provider.d.cts +14 -10
  32. package/dist/provider.d.ts +14 -10
  33. package/dist/provider.js +318 -98
  34. package/dist/react.cjs +407 -117
  35. package/dist/react.d.cts +2 -2
  36. package/dist/react.d.ts +2 -2
  37. package/dist/react.js +408 -118
  38. package/dist/{routedockMiddleware-BlDsHuPl.d.ts → routedockMiddleware-57gUaEMf.d.ts} +9 -4
  39. package/dist/{routedockMiddleware-D97A5ptQ.d.cts → routedockMiddleware-DlyLrxp7.d.cts} +9 -4
  40. package/dist/schema.cjs +40 -0
  41. package/dist/schema.js +40 -0
  42. package/dist/{sign-Dpj2Mp7k.d.ts → sign-AKH67sft.d.cts} +1 -1
  43. package/dist/{sign-CUf3rhTx.d.cts → sign-BEq-OsSq.d.ts} +1 -1
  44. package/dist/testing.cjs +6 -4
  45. package/dist/testing.d.cts +32 -13
  46. package/dist/testing.d.ts +32 -13
  47. package/dist/testing.js +6 -4
  48. package/package.json +2 -2
  49. package/dist/MppSessionHandler-B4TyD7Xg.d.cts +0 -121
  50. package/dist/MppSessionHandler-CLB5SzgN.d.ts +0 -121
@@ -1,6 +1,6 @@
1
1
  import { RequestHandler } from 'express';
2
- import { P as PaymentMode, R as RouteDockManifest } from './types-DmhmfLzP.js';
3
- import { O as OrphanedSessionInfo, S as SeenTxStore } from './MppSessionHandler-CLB5SzgN.js';
2
+ import { P as PaymentMode, h as RouteDockManifest, g as RouteDockLogger } from './logger-D8_Q2ytp.js';
3
+ import { O as OrphanedSessionInfo, S as SeenTxStore } from './MppSessionHandler-Bq4S-JTE.js';
4
4
 
5
5
  interface RouteDockMiddlewareOptions {
6
6
  modes: PaymentMode[];
@@ -12,9 +12,9 @@ interface RouteDockMiddlewareOptions {
12
12
  channelFactory: string;
13
13
  };
14
14
  };
15
- asset: string;
15
+ asset?: string;
16
16
  /** Stellar Asset Contract address for the payment asset */
17
- assetContract: string;
17
+ assetContract?: string;
18
18
  payee: string;
19
19
  network: 'testnet' | 'mainnet';
20
20
  /** Private key (S...) of the server/payee account */
@@ -53,6 +53,11 @@ interface RouteDockMiddlewareOptions {
53
53
  * duplicate settlement on agent retries. Defaults to per-handler in-memory.
54
54
  */
55
55
  seenTxStore?: SeenTxStore;
56
+ /**
57
+ * Structured log sink for every adapter diagnostic (settlement errors,
58
+ * callback failures, orphaned sessions). Defaults to a console-backed logger.
59
+ */
60
+ logger?: RouteDockLogger;
56
61
  }
57
62
  declare function routedock(opts: RouteDockMiddlewareOptions): RequestHandler;
58
63
 
@@ -1,6 +1,6 @@
1
1
  import { RequestHandler } from 'express';
2
- import { P as PaymentMode, R as RouteDockManifest } from './types-DmhmfLzP.cjs';
3
- import { O as OrphanedSessionInfo, S as SeenTxStore } from './MppSessionHandler-B4TyD7Xg.cjs';
2
+ import { P as PaymentMode, h as RouteDockManifest, g as RouteDockLogger } from './logger-D8_Q2ytp.cjs';
3
+ import { O as OrphanedSessionInfo, S as SeenTxStore } from './MppSessionHandler-1EL8QBAn.cjs';
4
4
 
5
5
  interface RouteDockMiddlewareOptions {
6
6
  modes: PaymentMode[];
@@ -12,9 +12,9 @@ interface RouteDockMiddlewareOptions {
12
12
  channelFactory: string;
13
13
  };
14
14
  };
15
- asset: string;
15
+ asset?: string;
16
16
  /** Stellar Asset Contract address for the payment asset */
17
- assetContract: string;
17
+ assetContract?: string;
18
18
  payee: string;
19
19
  network: 'testnet' | 'mainnet';
20
20
  /** Private key (S...) of the server/payee account */
@@ -53,6 +53,11 @@ interface RouteDockMiddlewareOptions {
53
53
  * duplicate settlement on agent retries. Defaults to per-handler in-memory.
54
54
  */
55
55
  seenTxStore?: SeenTxStore;
56
+ /**
57
+ * Structured log sink for every adapter diagnostic (settlement errors,
58
+ * callback failures, orphaned sessions). Defaults to a console-backed logger.
59
+ */
60
+ logger?: RouteDockLogger;
56
61
  }
57
62
  declare function routedock(opts: RouteDockMiddlewareOptions): RequestHandler;
58
63
 
package/dist/schema.cjs CHANGED
@@ -81,6 +81,14 @@ var routedock_schema_default = {
81
81
  type: "string",
82
82
  description: "Stellar Asset Contract (SAC) address for the payment asset"
83
83
  },
84
+ assets: {
85
+ type: "array",
86
+ minItems: 1,
87
+ items: {
88
+ $ref: "#/definitions/AssetConfig"
89
+ },
90
+ description: "Payment assets accepted by this provider. Each asset can be scoped to specific modes and endpoints. When present, assets[0] must match the root-level asset and asset_contract."
91
+ },
84
92
  payee: {
85
93
  type: "string",
86
94
  description: "Stellar address (G...) that receives payments"
@@ -213,6 +221,38 @@ var routedock_schema_default = {
213
221
  enum: ["x402", "mpp-charge", "mpp-session", "mpp-session-ws"],
214
222
  description: "A supported RouteDock payment mode"
215
223
  },
224
+ AssetConfig: {
225
+ type: "object",
226
+ description: "Payment asset configuration with optional mode and endpoint scoping",
227
+ required: ["asset", "asset_contract"],
228
+ additionalProperties: false,
229
+ properties: {
230
+ asset: {
231
+ type: "string",
232
+ description: "Asset ticker symbol (e.g. 'USDC' or 'XLM')"
233
+ },
234
+ asset_contract: {
235
+ type: "string",
236
+ description: "Stellar Asset Contract (SAC) address for the payment asset"
237
+ },
238
+ modes: {
239
+ type: "array",
240
+ items: {
241
+ $ref: "#/definitions/PaymentMode"
242
+ },
243
+ uniqueItems: true,
244
+ description: "Optional: restrict this asset to specific payment modes. If omitted, available for all modes."
245
+ },
246
+ endpoints: {
247
+ type: "array",
248
+ items: {
249
+ type: "string"
250
+ },
251
+ uniqueItems: true,
252
+ description: "Optional: restrict this asset to specific endpoints (by name). If omitted, available for all endpoints."
253
+ }
254
+ }
255
+ },
216
256
  PricingConfig: {
217
257
  type: "object",
218
258
  description: "Per-request pricing for x402 or mpp-charge modes",
package/dist/schema.js CHANGED
@@ -77,6 +77,14 @@ var routedock_schema_default = {
77
77
  type: "string",
78
78
  description: "Stellar Asset Contract (SAC) address for the payment asset"
79
79
  },
80
+ assets: {
81
+ type: "array",
82
+ minItems: 1,
83
+ items: {
84
+ $ref: "#/definitions/AssetConfig"
85
+ },
86
+ description: "Payment assets accepted by this provider. Each asset can be scoped to specific modes and endpoints. When present, assets[0] must match the root-level asset and asset_contract."
87
+ },
80
88
  payee: {
81
89
  type: "string",
82
90
  description: "Stellar address (G...) that receives payments"
@@ -209,6 +217,38 @@ var routedock_schema_default = {
209
217
  enum: ["x402", "mpp-charge", "mpp-session", "mpp-session-ws"],
210
218
  description: "A supported RouteDock payment mode"
211
219
  },
220
+ AssetConfig: {
221
+ type: "object",
222
+ description: "Payment asset configuration with optional mode and endpoint scoping",
223
+ required: ["asset", "asset_contract"],
224
+ additionalProperties: false,
225
+ properties: {
226
+ asset: {
227
+ type: "string",
228
+ description: "Asset ticker symbol (e.g. 'USDC' or 'XLM')"
229
+ },
230
+ asset_contract: {
231
+ type: "string",
232
+ description: "Stellar Asset Contract (SAC) address for the payment asset"
233
+ },
234
+ modes: {
235
+ type: "array",
236
+ items: {
237
+ $ref: "#/definitions/PaymentMode"
238
+ },
239
+ uniqueItems: true,
240
+ description: "Optional: restrict this asset to specific payment modes. If omitted, available for all modes."
241
+ },
242
+ endpoints: {
243
+ type: "array",
244
+ items: {
245
+ type: "string"
246
+ },
247
+ uniqueItems: true,
248
+ description: "Optional: restrict this asset to specific endpoints (by name). If omitted, available for all endpoints."
249
+ }
250
+ }
251
+ },
212
252
  PricingConfig: {
213
253
  type: "object",
214
254
  description: "Per-request pricing for x402 or mpp-charge modes",
@@ -1,4 +1,4 @@
1
- import { R as RouteDockManifest } from './types-DmhmfLzP.js';
1
+ import { h as RouteDockManifest } from './logger-D8_Q2ytp.cjs';
2
2
 
3
3
  /**
4
4
  * Ed25519 manifest signing and verification.
@@ -1,4 +1,4 @@
1
- import { R as RouteDockManifest } from './types-DmhmfLzP.cjs';
1
+ import { h as RouteDockManifest } from './logger-D8_Q2ytp.js';
2
2
 
3
3
  /**
4
4
  * Ed25519 manifest signing and verification.
package/dist/testing.cjs CHANGED
@@ -3,6 +3,7 @@
3
3
  // src/testing/createMockRoutedockMiddleware.ts
4
4
  var DEFAULT_TX_HASH = "0000000000000000000000000000000000000000000000000000000000000000";
5
5
  var DEFAULT_CHANNEL_ID = "CCK4XOW3YKQUEZFONUTINKMSNW7SNMRQZURME5U3UP7E6WNGK7UHUCAH";
6
+ var DEFAULT_PAYER = "GAIRCEIRCEIRCEIRCEIRCEIRCEIRCEIRCEIRCEIRCEIRCEIRCEIRCF6M";
6
7
  function format7(scaled) {
7
8
  return (Number(scaled) / 1e7).toFixed(7);
8
9
  }
@@ -16,11 +17,12 @@ async function runMockSettlement(opts) {
16
17
  if ((opts.payment ?? "auto-pass") === "auto-fail") return null;
17
18
  const s = opts.synthetic ?? {};
18
19
  const txHash = s.txHash ?? DEFAULT_TX_HASH;
19
- if (mode === "mpp-session") {
20
+ const payer = s.payer === void 0 ? DEFAULT_PAYER : s.payer;
21
+ if (mode === "mpp-session" || mode === "mpp-session-ws") {
20
22
  const channelId = s.channelId ?? DEFAULT_CHANNEL_ID;
21
23
  const rate = toScaled(s.rate ?? "0.0001");
22
24
  const count = s.voucherCount ?? 3;
23
- if (opts.onSessionOpen) await opts.onSessionOpen(channelId);
25
+ if (opts.onSessionOpen) await opts.onSessionOpen(channelId, payer);
24
26
  const vouchers = [];
25
27
  for (let i = 1; i <= count; i++) {
26
28
  const cumulativeAmount = format7(rate * BigInt(i));
@@ -28,11 +30,11 @@ async function runMockSettlement(opts) {
28
30
  if (opts.onVoucher) await opts.onVoucher(channelId, i, cumulativeAmount, "0000000000000000000000000000000000000000000000000000000000000000");
29
31
  }
30
32
  const totalPaid = format7(rate * BigInt(count));
31
- if (opts.onSettled) await opts.onSettled(txHash, totalPaid, "mpp-session");
33
+ if (opts.onSettled) await opts.onSettled(txHash, totalPaid, mode, payer);
32
34
  return { mode, txHash, amount: totalPaid, channelId, vouchers };
33
35
  }
34
36
  const amount = s.amount ?? "0.001";
35
- if (opts.onSettled) await opts.onSettled(txHash, amount, mode);
37
+ if (opts.onSettled) await opts.onSettled(txHash, amount, mode, payer);
36
38
  return { mode, txHash, amount };
37
39
  }
38
40
  function createMockRoutedockMiddleware(opts = {}) {
@@ -1,19 +1,26 @@
1
1
  import { RequestHandler } from 'express';
2
- import { P as PaymentMode } from './types-DmhmfLzP.cjs';
2
+ import { P as PaymentMode } from './logger-D8_Q2ytp.cjs';
3
+ import { R as RouteDockMiddlewareOptions } from './routedockMiddleware-DlyLrxp7.cjs';
3
4
  import 'mppx';
5
+ import './MppSessionHandler-1EL8QBAn.cjs';
4
6
 
5
7
  /**
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.
8
+ * Loosen a production callback's return type so a plain sync test spy works,
9
+ * while keeping its exact parameter list (the real adapter's signature).
10
+ */
11
+ type TestCallback<F> = F extends (...args: infer A) => unknown ? (...args: A) => void | Promise<void> : never;
12
+ /**
13
+ * Provider settlement callbacks under test. Same parameter list as the real
14
+ * `RouteDockMiddlewareOptions` callbacks — including `payer` — but they accept
15
+ * sync or async fns so a plain test spy works without wrapping it in a Promise.
9
16
  */
10
17
  interface MockRoutedockCallbacks {
11
18
  /** 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>;
19
+ onSettled?: TestCallback<NonNullable<RouteDockMiddlewareOptions['onSettled']>>;
20
+ /** Called once when a synthetic session is opened (first voucher). */
21
+ onSessionOpen?: TestCallback<NonNullable<RouteDockMiddlewareOptions['onSessionOpen']>>;
22
+ /** Called for each synthetic voucher in a session (1-based index). */
23
+ onVoucher?: TestCallback<NonNullable<RouteDockMiddlewareOptions['onVoucher']>>;
17
24
  }
18
25
  /** Synthetic settlement values handed to the callbacks. All optional — sensible defaults per mode. */
19
26
  interface SyntheticPayment {
@@ -21,12 +28,19 @@ interface SyntheticPayment {
21
28
  txHash?: string;
22
29
  /** Settled amount (x402 / mpp-charge) passed to onSettled. Default: '0.001'. */
23
30
  amount?: string;
24
- /** Channel address (mpp-session) passed to onSessionOpen. Default: a fixed C... address. */
31
+ /** Channel address (session modes) passed to onSessionOpen. Default: a fixed C... address. */
25
32
  channelId?: string;
26
- /** Per-voucher rate (mpp-session), in decimal string. Default: '0.0001'. */
33
+ /** Per-voucher rate (session modes), in decimal string. Default: '0.0001'. */
27
34
  rate?: string;
28
- /** Number of vouchers to emit before close (mpp-session). Default: 3. */
35
+ /** Number of vouchers to emit before close (session modes). Default: 3. */
29
36
  voucherCount?: number;
37
+ /**
38
+ * Payer passed to onSettled (4th arg) and onSessionOpen (2nd arg). Default: a
39
+ * valid Stellar G... account. Pass `null` to exercise the address-unavailable
40
+ * path; `null` is passed through untouched (an explicit null is not replaced
41
+ * by the default).
42
+ */
43
+ payer?: string | null;
30
44
  }
31
45
  interface MockRoutedockOptions extends MockRoutedockCallbacks {
32
46
  /** Payment mode the synthetic payment uses. Default: 'x402'. */
@@ -87,7 +101,12 @@ declare function runMockSettlement(opts: MockRoutedockOptions): Promise<MockSett
87
101
  * app.get('/price', (_req, res) => res.json({ price: '42' }))
88
102
  *
89
103
  * await request(app).get('/price').expect(200)
90
- * expect(onSettled).toHaveBeenCalledWith(expect.any(String), '0.001', 'x402')
104
+ * expect(onSettled).toHaveBeenCalledWith(
105
+ * expect.any(String),
106
+ * '0.001',
107
+ * 'x402',
108
+ * expect.any(String), // payer
109
+ * )
91
110
  * ```
92
111
  */
93
112
  declare function createMockRoutedockMiddleware(opts?: MockRoutedockOptions): RequestHandler;
package/dist/testing.d.ts CHANGED
@@ -1,19 +1,26 @@
1
1
  import { RequestHandler } from 'express';
2
- import { P as PaymentMode } from './types-DmhmfLzP.js';
2
+ import { P as PaymentMode } from './logger-D8_Q2ytp.js';
3
+ import { R as RouteDockMiddlewareOptions } from './routedockMiddleware-57gUaEMf.js';
3
4
  import 'mppx';
5
+ import './MppSessionHandler-Bq4S-JTE.js';
4
6
 
5
7
  /**
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.
8
+ * Loosen a production callback's return type so a plain sync test spy works,
9
+ * while keeping its exact parameter list (the real adapter's signature).
10
+ */
11
+ type TestCallback<F> = F extends (...args: infer A) => unknown ? (...args: A) => void | Promise<void> : never;
12
+ /**
13
+ * Provider settlement callbacks under test. Same parameter list as the real
14
+ * `RouteDockMiddlewareOptions` callbacks — including `payer` — but they accept
15
+ * sync or async fns so a plain test spy works without wrapping it in a Promise.
9
16
  */
10
17
  interface MockRoutedockCallbacks {
11
18
  /** 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>;
19
+ onSettled?: TestCallback<NonNullable<RouteDockMiddlewareOptions['onSettled']>>;
20
+ /** Called once when a synthetic session is opened (first voucher). */
21
+ onSessionOpen?: TestCallback<NonNullable<RouteDockMiddlewareOptions['onSessionOpen']>>;
22
+ /** Called for each synthetic voucher in a session (1-based index). */
23
+ onVoucher?: TestCallback<NonNullable<RouteDockMiddlewareOptions['onVoucher']>>;
17
24
  }
18
25
  /** Synthetic settlement values handed to the callbacks. All optional — sensible defaults per mode. */
19
26
  interface SyntheticPayment {
@@ -21,12 +28,19 @@ interface SyntheticPayment {
21
28
  txHash?: string;
22
29
  /** Settled amount (x402 / mpp-charge) passed to onSettled. Default: '0.001'. */
23
30
  amount?: string;
24
- /** Channel address (mpp-session) passed to onSessionOpen. Default: a fixed C... address. */
31
+ /** Channel address (session modes) passed to onSessionOpen. Default: a fixed C... address. */
25
32
  channelId?: string;
26
- /** Per-voucher rate (mpp-session), in decimal string. Default: '0.0001'. */
33
+ /** Per-voucher rate (session modes), in decimal string. Default: '0.0001'. */
27
34
  rate?: string;
28
- /** Number of vouchers to emit before close (mpp-session). Default: 3. */
35
+ /** Number of vouchers to emit before close (session modes). Default: 3. */
29
36
  voucherCount?: number;
37
+ /**
38
+ * Payer passed to onSettled (4th arg) and onSessionOpen (2nd arg). Default: a
39
+ * valid Stellar G... account. Pass `null` to exercise the address-unavailable
40
+ * path; `null` is passed through untouched (an explicit null is not replaced
41
+ * by the default).
42
+ */
43
+ payer?: string | null;
30
44
  }
31
45
  interface MockRoutedockOptions extends MockRoutedockCallbacks {
32
46
  /** Payment mode the synthetic payment uses. Default: 'x402'. */
@@ -87,7 +101,12 @@ declare function runMockSettlement(opts: MockRoutedockOptions): Promise<MockSett
87
101
  * app.get('/price', (_req, res) => res.json({ price: '42' }))
88
102
  *
89
103
  * await request(app).get('/price').expect(200)
90
- * expect(onSettled).toHaveBeenCalledWith(expect.any(String), '0.001', 'x402')
104
+ * expect(onSettled).toHaveBeenCalledWith(
105
+ * expect.any(String),
106
+ * '0.001',
107
+ * 'x402',
108
+ * expect.any(String), // payer
109
+ * )
91
110
  * ```
92
111
  */
93
112
  declare function createMockRoutedockMiddleware(opts?: MockRoutedockOptions): RequestHandler;
package/dist/testing.js CHANGED
@@ -1,6 +1,7 @@
1
1
  // src/testing/createMockRoutedockMiddleware.ts
2
2
  var DEFAULT_TX_HASH = "0000000000000000000000000000000000000000000000000000000000000000";
3
3
  var DEFAULT_CHANNEL_ID = "CCK4XOW3YKQUEZFONUTINKMSNW7SNMRQZURME5U3UP7E6WNGK7UHUCAH";
4
+ var DEFAULT_PAYER = "GAIRCEIRCEIRCEIRCEIRCEIRCEIRCEIRCEIRCEIRCEIRCEIRCEIRCF6M";
4
5
  function format7(scaled) {
5
6
  return (Number(scaled) / 1e7).toFixed(7);
6
7
  }
@@ -14,11 +15,12 @@ async function runMockSettlement(opts) {
14
15
  if ((opts.payment ?? "auto-pass") === "auto-fail") return null;
15
16
  const s = opts.synthetic ?? {};
16
17
  const txHash = s.txHash ?? DEFAULT_TX_HASH;
17
- if (mode === "mpp-session") {
18
+ const payer = s.payer === void 0 ? DEFAULT_PAYER : s.payer;
19
+ if (mode === "mpp-session" || mode === "mpp-session-ws") {
18
20
  const channelId = s.channelId ?? DEFAULT_CHANNEL_ID;
19
21
  const rate = toScaled(s.rate ?? "0.0001");
20
22
  const count = s.voucherCount ?? 3;
21
- if (opts.onSessionOpen) await opts.onSessionOpen(channelId);
23
+ if (opts.onSessionOpen) await opts.onSessionOpen(channelId, payer);
22
24
  const vouchers = [];
23
25
  for (let i = 1; i <= count; i++) {
24
26
  const cumulativeAmount = format7(rate * BigInt(i));
@@ -26,11 +28,11 @@ async function runMockSettlement(opts) {
26
28
  if (opts.onVoucher) await opts.onVoucher(channelId, i, cumulativeAmount, "0000000000000000000000000000000000000000000000000000000000000000");
27
29
  }
28
30
  const totalPaid = format7(rate * BigInt(count));
29
- if (opts.onSettled) await opts.onSettled(txHash, totalPaid, "mpp-session");
31
+ if (opts.onSettled) await opts.onSettled(txHash, totalPaid, mode, payer);
30
32
  return { mode, txHash, amount: totalPaid, channelId, vouchers };
31
33
  }
32
34
  const amount = s.amount ?? "0.001";
33
- if (opts.onSettled) await opts.onSettled(txHash, amount, mode);
35
+ if (opts.onSettled) await opts.onSettled(txHash, amount, mode, payer);
34
36
  return { mode, txHash, amount };
35
37
  }
36
38
  function createMockRoutedockMiddleware(opts = {}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@routedock/routedock",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Unified payment execution layer for autonomous agents on Stellar",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -131,7 +131,7 @@
131
131
  "@x402/core": "^2.9.0",
132
132
  "@x402/stellar": "^2.9.0",
133
133
  "mppx": "^0.5.7",
134
- "@routedock/nulth-sdk": "0.2.0"
134
+ "@routedock/nulth-sdk": "0.2.1"
135
135
  },
136
136
  "peerDependencies": {
137
137
  "express": "^4.18.0",
@@ -1,121 +0,0 @@
1
- import { RequestHandler } from 'express';
2
- import { Store } from 'mppx';
3
- import { R as RouteDockManifest } from './types-DmhmfLzP.cjs';
4
-
5
- /**
6
- * Idempotency store for payment settlement.
7
- *
8
- * `x402Handler` and `MppChargeHandler` settle on every request carrying a
9
- * payment header. An agent that retries after a post-settlement network
10
- * timeout resends the *same* signed payment, which would settle a second time
11
- * and invoke `onSettled` twice — double-counting in billing.
12
- *
13
- * Before settling, a handler derives an idempotency key from the inbound
14
- * payment header(s) and checks this store. On a hit it replays the cached
15
- * settlement response and skips both the on-chain settle and `onSettled`.
16
- *
17
- * The default {@link InMemorySeenTxStore} is per-handler and per-process. For
18
- * multi-instance deployments, supply a shared implementation backed by Redis,
19
- * Supabase, etc.
20
- */
21
- /** Cached outcome of a settlement, replayed on a duplicate payment. */
22
- interface SettlementRecord {
23
- /** On-chain transaction hash (or settlement reference), if known. */
24
- txHash: string | null;
25
- /** Response headers to re-apply on a replay (e.g. `X-Payment-Response`). */
26
- headers?: Record<string, string>;
27
- }
28
- interface SeenTxStore {
29
- /** Returns the cached settlement for a key, or `undefined` if unseen. */
30
- get(key: string): Promise<SettlementRecord | undefined> | SettlementRecord | undefined;
31
- /** Records the settlement outcome for a key. */
32
- set(key: string, record: SettlementRecord): Promise<void> | void;
33
- }
34
- interface InMemorySeenTxStoreOptions {
35
- /** Maximum number of entries before FIFO eviction. Defaults to 10,000. */
36
- maxEntries?: number;
37
- /** Log a startup warning about non-durability. Defaults to true. */
38
- warn?: boolean;
39
- }
40
- /**
41
- * Default in-memory {@link SeenTxStore}. Bounded by `maxEntries` with FIFO
42
- * eviction so a long-running process cannot grow without limit.
43
- *
44
- * **Not durable.** On serverless/edge runtimes each request may land on a
45
- * fresh isolate with an empty cache, which causes duplicate settlements.
46
- * Supply a persistent implementation (Supabase, Redis, …) in production.
47
- */
48
- declare class InMemorySeenTxStore implements SeenTxStore {
49
- private readonly map;
50
- private readonly order;
51
- constructor(maxEntriesOrOptions?: number | InMemorySeenTxStoreOptions);
52
- private readonly maxEntries;
53
- get(key: string): SettlementRecord | undefined;
54
- set(key: string, record: SettlementRecord): void;
55
- }
56
- /**
57
- * Derive a collision-resistant idempotency key from the inbound
58
- * payment-bearing headers. Uses SHA-256 instead of 32-bit FNV-1a
59
- * (which has a 2^32 keyspace — birthday collisions become likely
60
- * well before the 10_000-entry default store is full).
61
- *
62
- * x402 clients send the signed payment in `payment-signature` / `x-payment`;
63
- * mppx clients send it in `authorization` (the `Payment` scheme). A retry
64
- * resends byte-identical headers, so hashing the first present one yields a
65
- * stable key. Returns `null` when no payment header is present (nothing to
66
- * dedupe — e.g. the initial 402 challenge request).
67
- */
68
- declare function paymentIdempotencyKey(getHeader: (name: string) => string | undefined): Promise<string | null>;
69
-
70
- /** Store shape extended with optional atomic update operation. */
71
- type ChannelStore = Store.Store & {
72
- update?: (key: string, fn: (prev: unknown) => unknown) => Promise<unknown>;
73
- };
74
- /** Expected payload shape for voucher cumulative amount entries. */
75
- interface VoucherStoreValue {
76
- amount: string;
77
- [key: string]: unknown;
78
- }
79
- /** Validates that a stored store value is an object containing a numeric string amount. */
80
- declare function isVoucherStoreValue(value: unknown): value is VoucherStoreValue;
81
- type Network = 'testnet' | 'mainnet';
82
- /** Why a live session was flagged as orphaned (never cleanly closed). */
83
- type OrphanReason = 'connection-closed' | 'idle-timeout';
84
- /** Latest signed state of an orphaned session, enough for the reconciler to settle. */
85
- interface OrphanedSessionInfo {
86
- /** Cumulative amount of the highest voucher seen (human-readable, 7 dp). */
87
- cumulativeAmount: string;
88
- /** Hex-encoded signature of the highest voucher seen. */
89
- lastSignature: string;
90
- /** Number of vouchers received before teardown. */
91
- voucherCount: number;
92
- /** What triggered the orphan flag. */
93
- reason: OrphanReason;
94
- }
95
- interface MppSessionHandlerOptions {
96
- payeeSecretKey: string;
97
- network: Network;
98
- channelFactory: string;
99
- rate: string;
100
- assetContract: string;
101
- manifest: RouteDockManifest;
102
- commitmentPublicKey: string;
103
- onSettled?: (txHash: string, totalPaid: string, mode: string, payer: string | null) => Promise<void>;
104
- onSessionOpen?: (channelId: string, payer: string | null) => Promise<void>;
105
- onVoucher?: (channelId: string, voucherIndex: number, cumulativeAmount: string, signature: string) => Promise<void>;
106
- onCallbackError?: (err: unknown, cb: string) => void;
107
- /**
108
- * Called when the client connection drops mid-session or the session goes
109
- * idle, before a clean close. Persist the session as `closing` so the
110
- * SessionReconciler can settle it with the latest signed voucher.
111
- */
112
- onOrphaned?: (channelId: string, info: OrphanedSessionInfo) => Promise<void>;
113
- /**
114
- * Flag the session orphaned after this many milliseconds with no voucher
115
- * activity. Disabled when unset.
116
- */
117
- idleTimeoutMs?: number;
118
- }
119
- declare function createMppSessionHandler(opts: MppSessionHandlerOptions): RequestHandler;
120
-
121
- export { type ChannelStore as C, InMemorySeenTxStore as I, type MppSessionHandlerOptions as M, type OrphanedSessionInfo as O, type SeenTxStore as S, type VoucherStoreValue as V, type SettlementRecord as a, type InMemorySeenTxStoreOptions as b, type OrphanReason as c, createMppSessionHandler as d, isVoucherStoreValue as i, paymentIdempotencyKey as p };