mppx 0.11.0 → 0.13.1

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 (126) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/README.md +22 -1
  3. package/dist/Method.d.ts +7 -1
  4. package/dist/Method.js +7 -2
  5. package/dist/Receipt.d.ts +2 -0
  6. package/dist/Receipt.js +2 -0
  7. package/dist/cli/agent.d.ts +3 -0
  8. package/dist/cli/agent.js +20 -0
  9. package/dist/cli/cli.d.ts +9 -1
  10. package/dist/cli/cli.js +134 -136
  11. package/dist/cli/plugins/index.js +12 -14
  12. package/dist/cli/plugins/tempo.js +9 -2
  13. package/dist/cli/utils.d.ts +11 -1
  14. package/dist/cli/utils.js +15 -2
  15. package/dist/cli/validate/challenge.d.ts +2 -0
  16. package/dist/cli/validate/challenge.js +19 -4
  17. package/dist/cli/validate/discovery.d.ts +1 -0
  18. package/dist/cli/validate/discovery.js +10 -1
  19. package/dist/cli/validate/payment.js +63 -24
  20. package/dist/client/Methods.d.ts +0 -2
  21. package/dist/client/Methods.js +0 -2
  22. package/dist/client/Mppx.js +1 -0
  23. package/dist/client/index.d.ts +1 -1
  24. package/dist/client/index.js +1 -1
  25. package/dist/client/internal/Fetch.d.ts +2 -0
  26. package/dist/client/internal/Fetch.js +8 -2
  27. package/dist/client/internal/MethodChallenge.d.ts +1 -0
  28. package/dist/evm/Types.js +1 -1
  29. package/dist/evm/server/Charge.js +5 -0
  30. package/dist/evm/server/Methods.d.ts +164 -3
  31. package/dist/evm/server/Methods.js +50 -2
  32. package/dist/integrations/x402/Evm.js +4 -3
  33. package/dist/internal/HeaderCodec.d.ts +2 -2
  34. package/dist/internal/version.d.ts +2 -2
  35. package/dist/internal/version.js +1 -1
  36. package/dist/mcp/client/McpClient.js +4 -7
  37. package/dist/middlewares/elysia.d.ts +11 -8
  38. package/dist/middlewares/elysia.js +67 -14
  39. package/dist/middlewares/express.js +13 -6
  40. package/dist/middlewares/hono.js +4 -4
  41. package/dist/middlewares/nextjs.js +9 -5
  42. package/dist/proxy/internal/Headers.js +65 -0
  43. package/dist/proxy/services/stripe.js +1 -0
  44. package/dist/server/Mppx.d.ts +18 -2
  45. package/dist/server/Mppx.js +204 -92
  46. package/dist/server/NodeListener.js +71 -6
  47. package/dist/server/Request.d.ts +11 -1
  48. package/dist/server/Request.js +132 -13
  49. package/dist/server/Transport.d.ts +14 -1
  50. package/dist/server/Transport.js +1 -0
  51. package/dist/server/internal/html/compose.main.gen.d.ts +1 -1
  52. package/dist/server/internal/html/serviceWorker.gen.d.ts +1 -1
  53. package/dist/stripe/server/Methods.d.ts +10 -3
  54. package/dist/stripe/server/Methods.js +19 -6
  55. package/dist/stripe/server/internal/html.gen.d.ts +1 -1
  56. package/dist/stripe/server/internal/html.gen.js +1 -1
  57. package/dist/tempo/Methods.d.ts +1 -0
  58. package/dist/tempo/Methods.js +1 -0
  59. package/dist/tempo/client/Charge.js +17 -13
  60. package/dist/tempo/client/Methods.d.ts +1 -5
  61. package/dist/tempo/client/Methods.js +10 -5
  62. package/dist/tempo/client/ResolveAccount.d.ts +3 -0
  63. package/dist/tempo/client/index.d.ts +0 -3
  64. package/dist/tempo/client/index.js +0 -2
  65. package/dist/tempo/internal/currencies.d.ts +19 -0
  66. package/dist/tempo/internal/currencies.js +41 -0
  67. package/dist/tempo/internal/defaults.d.ts +5 -3
  68. package/dist/tempo/internal/defaults.js +6 -2
  69. package/dist/tempo/internal/fee-payer.d.ts +11 -7
  70. package/dist/tempo/internal/fee-payer.js +30 -11
  71. package/dist/tempo/internal/machine-token-charge.d.ts +23 -0
  72. package/dist/tempo/internal/machine-token-charge.js +2 -1
  73. package/dist/tempo/legacy/index.d.ts +1 -3
  74. package/dist/tempo/legacy/index.js +1 -3
  75. package/dist/tempo/server/Charge.d.ts +12 -1
  76. package/dist/tempo/server/Charge.js +109 -78
  77. package/dist/tempo/server/Methods.d.ts +5048 -40
  78. package/dist/tempo/server/Methods.js +104 -13
  79. package/dist/tempo/server/Subscription.d.ts +1 -1
  80. package/dist/tempo/server/Subscription.js +31 -4
  81. package/dist/tempo/server/internal/html.gen.d.ts +1 -1
  82. package/dist/tempo/server/internal/html.gen.js +1 -1
  83. package/dist/tempo/server/internal/transport.js +28 -11
  84. package/dist/tempo/session/client/ChannelOps.js +5 -0
  85. package/dist/tempo/session/client/Session.d.ts +1 -0
  86. package/dist/tempo/session/client/Session.js +7 -4
  87. package/dist/tempo/session/client/SessionManager.js +3 -0
  88. package/dist/tempo/session/client/Transports.d.ts +8 -1
  89. package/dist/tempo/session/client/Transports.js +12 -3
  90. package/dist/tempo/session/precompile/Chain.js +16 -1
  91. package/dist/tempo/session/precompile/Protocol.d.ts +2 -0
  92. package/dist/tempo/session/precompile/Voucher.d.ts +16 -0
  93. package/dist/tempo/session/precompile/Voucher.js +48 -0
  94. package/dist/tempo/session/server/ChannelStore.d.ts +22 -2
  95. package/dist/tempo/session/server/ChannelStore.js +37 -7
  96. package/dist/tempo/session/server/CredentialVerification.d.ts +6 -1
  97. package/dist/tempo/session/server/CredentialVerification.js +56 -19
  98. package/dist/tempo/session/server/MeteredStream.d.ts +3 -2
  99. package/dist/tempo/session/server/MeteredStream.js +85 -29
  100. package/dist/tempo/session/server/RequestState.d.ts +6 -0
  101. package/dist/tempo/session/server/RequestState.js +11 -4
  102. package/dist/tempo/session/server/Session.d.ts +2 -1
  103. package/dist/tempo/session/server/Session.js +10 -2
  104. package/dist/tempo/session/server/Settlement.d.ts +23 -0
  105. package/dist/tempo/session/server/Settlement.js +105 -25
  106. package/dist/tempo/session/server/Sse.d.ts +3 -1
  107. package/dist/tempo/session/server/Sse.js +105 -32
  108. package/dist/tempo/session/server/Transports.d.ts +24 -19
  109. package/dist/tempo/session/server/Transports.js +169 -58
  110. package/dist/tempo/session/server/Ws.d.ts +5 -1
  111. package/dist/tempo/session/server/Ws.js +75 -20
  112. package/dist/tempo/subscription/KeyAuthorization.d.ts +70 -8
  113. package/dist/tempo/subscription/Store.d.ts +2 -0
  114. package/dist/tempo/subscription/Store.js +3 -0
  115. package/dist/validation/core.js +2 -1
  116. package/dist/x402/server/EvmCharge.d.ts +3 -1
  117. package/dist/x402/server/EvmCharge.js +14 -1
  118. package/package.json +8 -8
  119. package/dist/tempo/legacy/client/ChannelOps.d.ts +0 -69
  120. package/dist/tempo/legacy/client/ChannelOps.js +0 -168
  121. package/dist/tempo/legacy/client/Session.d.ts +0 -185
  122. package/dist/tempo/legacy/client/Session.js +0 -279
  123. package/dist/tempo/legacy/client/SessionManager.d.ts +0 -100
  124. package/dist/tempo/legacy/client/SessionManager.js +0 -706
  125. package/dist/tempo/legacy/client/index.d.ts +0 -7
  126. package/dist/tempo/legacy/client/index.js +0 -5
@@ -1,3 +1,6 @@
1
+ import * as Store from '../../Store.js';
2
+ import * as Currencies from '../internal/currencies.js';
3
+ import * as ChannelStore from '../session/server/ChannelStore.js';
1
4
  import { charge as sessionCharge_, session as session_, settle as settle_, settleBatch as settleBatch_, } from '../session/server/Session.js';
2
5
  import * as Ws_ from '../session/server/Ws.js';
3
6
  import { charge as charge_ } from './Charge.js';
@@ -11,18 +14,28 @@ function createChargeMethod(parameters) {
11
14
  // `tempo()` accepts the intersection of charge/session parameters, then
12
15
  // forwards only the fields each method understands. Preserve the inferred
13
16
  // parameter type so configured request defaults remain visible to handlers.
14
- return tempo.charge(parameters);
17
+ return charge_(parameters);
15
18
  }
16
19
  function createSessionMethod(parameters) {
17
- // Machine-token funding is configured at the Tempo family level, but only
18
- // charge implements it today. Keep it out of session configuration until
19
- // session routing has its own complete lifecycle support.
20
- const { machineTokenEnabled: _machineTokenEnabled, ...sessionParameters } = parameters ?? {};
20
+ // These options apply only to charge, even when configured at the family level.
21
+ const { allowedFeeTokens: _allowedFeeTokens, machineTokenEnabled: _machineTokenEnabled, ...sessionParameters } = parameters ?? {};
21
22
  return sessionServer(sessionParameters);
22
23
  }
23
24
  /**
24
25
  * Creates the common Tempo `charge` and `session` methods from shared parameters.
25
26
  *
27
+ * Mainnet accepts OUSD first, then USDC.e. Testnet accepts OUSD first, then pathUSD.
28
+ * Use `currencies`
29
+ * for an ordered list of addresses/token definitions, including a one-element
30
+ * list for a single asset. Each currency creates charge and session offers; list
31
+ * order is presentation order, not a requirement on the client's choice.
32
+ * Chain-indexed definitions (including `tokens.tempo` from `viem/tokens`) are
33
+ * filtered to USD tokens deployed on `chainId`. Duplicates are removed by address.
34
+ * Explicit lists replace the defaults; an empty resolved list throws.
35
+ *
36
+ * The chain defaults to Tempo mainnet (Moderato with `testnet: true`). Set
37
+ * `chainId` explicitly when using a custom client for another network.
38
+ *
26
39
  * When configured, `relay` applies to the `charge` method. Session vouchers
27
40
  * remain local state transitions and session relay delegation will be added
28
41
  * with its action-specific lifecycle support.
@@ -32,22 +45,41 @@ function createSessionMethod(parameters) {
32
45
  * import { Mppx, tempo } from 'mppx/server'
33
46
  *
34
47
  * const mppx = Mppx.create({
35
- * methods: [tempo.common({ currency: '0x...', recipient: '0x...' })],
48
+ * methods: [tempo.common({ recipient: '0x...' })],
36
49
  * })
37
50
  * ```
38
51
  */
39
52
  export function tempo(parameters) {
40
- return [createChargeMethod(parameters), createSessionMethod(parameters)];
53
+ if (parameters?.currency !== undefined) {
54
+ if (parameters.currencies !== undefined)
55
+ throw new Error('Specify either `currency` or `currencies`, not both.');
56
+ return [createChargeMethod(parameters), createSessionMethod(parameters)];
57
+ }
58
+ const { currencies: _currencies, ...shared } = parameters ?? {};
59
+ const [first, ...rest] = Currencies.resolve(parameters ?? {});
60
+ const sessions = sessionOffers(parameters);
61
+ function createMethods(currency, index) {
62
+ const configured = { ...shared, ...currency };
63
+ return [createChargeMethod(configured), sessions[index]];
64
+ }
65
+ return [
66
+ ...createMethods(first, 0),
67
+ ...rest.flatMap((currency, index) => createMethods(currency, index + 1)),
68
+ ];
41
69
  }
42
70
  (function (tempo) {
43
- /** Creates a Tempo `charge` method for one-time TIP-20 token transfers. */
44
- tempo.charge = charge_;
71
+ /** Creates ordered Tempo charge offers: OUSD first, then the network fallback. */
72
+ tempo.charge = chargeOffers;
45
73
  /** Creates the common Tempo `charge` and `session` methods from shared parameters. */
46
74
  tempo.common = tempo;
47
- /** Creates a TIP-1034 Tempo `session` method for session-based TIP-20 token payments. */
48
- tempo.session = sessionServer;
49
- /** Creates a Tempo `subscription` method for recurring TIP-20 token payments. */
50
- tempo.subscription = subscription_;
75
+ /** Creates ordered TIP-1034 session offers with shared storage and settlement helpers. */
76
+ tempo.session = Object.assign(sessionOffers, {
77
+ charge: sessionCharge_,
78
+ settle: settle_,
79
+ settleBatch: settleBatch_,
80
+ });
81
+ /** Creates ordered subscription offers. Existing subscriptions retain their authorized currency. */
82
+ tempo.subscription = subscriptionOffers;
51
83
  /** Renews an overdue Tempo subscription outside of the HTTP request path. */
52
84
  tempo.renewSubscription = renewSubscription_;
53
85
  /** One-shot settle: reads highest voucher from storage and submits on-chain. */
@@ -57,4 +89,63 @@ export function tempo(parameters) {
57
89
  /** Experimental websocket helpers for Tempo sessions. */
58
90
  tempo.Ws = Ws_;
59
91
  })(tempo || (tempo = {}));
92
+ /** Resolves the public factory configuration while preserving explicit legacy currencies. */
93
+ function resolveCurrencies(parameters) {
94
+ if (parameters.currency !== undefined && parameters.currencies !== undefined)
95
+ throw new Error('Specify either `currency` or `currencies`, not both.');
96
+ return Currencies.resolve({
97
+ ...parameters,
98
+ ...(parameters.currency === undefined ? {} : { currencies: [parameters.currency] }),
99
+ });
100
+ }
101
+ /** Creates OUSD-first charge offers, with explicit currency lists replacing the defaults. */
102
+ function chargeOffers(parameters) {
103
+ const { currencies: _currencies, ...shared } = parameters ?? {};
104
+ const [first, ...rest] = resolveCurrencies(parameters ?? {});
105
+ function create(currency) {
106
+ const configured = { ...shared, ...currency };
107
+ return charge_(configured);
108
+ }
109
+ return [create(first), ...rest.map(create)];
110
+ }
111
+ /** Creates OUSD-first session offers with shared storage and currency-aware settlement helpers. */
112
+ function sessionOffers(parameters) {
113
+ const { currencies: _currencies, ...shared } = parameters ?? {};
114
+ const [first, ...rest] = resolveCurrencies(parameters ?? {});
115
+ const store = parameters?.store ?? Store.memory();
116
+ const settlements = new Map();
117
+ const key = (chainId, currency) => `${chainId}:${currency.toLowerCase()}`;
118
+ const settleScheduled = (channel) => {
119
+ const settle = settlements.get(key(channel.chainId, channel.token));
120
+ if (!settle)
121
+ throw new Error('Channel currency is not configured for this session handler.');
122
+ return settle(channel);
123
+ };
124
+ const extensions = {
125
+ settleScheduled,
126
+ serveWebSocket: (options) => Ws_.serve({
127
+ ...options,
128
+ store: ChannelStore.fromStore(store),
129
+ onChargeCommitted: settleScheduled,
130
+ }),
131
+ };
132
+ function create(currency) {
133
+ const configured = { ...shared, ...currency, store };
134
+ const method = session_(configured);
135
+ settlements.set(key(currency.chainId, currency.currency), method.extensions.settleScheduled);
136
+ return { ...method, extensions };
137
+ }
138
+ return [create(first), ...rest.map(create)];
139
+ }
140
+ /** Offers currencies for new subscriptions; stored subscriptions retain their authorized currency. */
141
+ function subscriptionOffers(parameters) {
142
+ const { currencies: _currencies, ...shared } = parameters;
143
+ const [first, ...rest] = resolveCurrencies(parameters);
144
+ const store = parameters.store ?? Store.memory();
145
+ function create(currency) {
146
+ const configured = { ...shared, ...currency, store };
147
+ return subscription_(configured);
148
+ }
149
+ return [create(first), ...rest.map(create)];
150
+ }
60
151
  //# sourceMappingURL=Methods.js.map
@@ -68,7 +68,7 @@ export declare function subscription<const parameters extends subscription.Param
68
68
  amount: string;
69
69
  subscriptionExpires: string;
70
70
  methodDetails?: {
71
- accessKey?: import("zod").output<import("zod/mini").ZodMiniObject<{
71
+ accessKey?: import("zod").infer<import("zod/mini").ZodMiniObject<{
72
72
  accessKeyAddress: import("zod/mini").ZodMiniPipe<import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniTransform<`0x${string}`, string>>;
73
73
  keyType: import("zod/mini").ZodMiniEnum<{
74
74
  p256: "p256";
@@ -12,6 +12,7 @@ import * as Attribution from '../Attribution.js';
12
12
  import * as Account from '../internal/account.js';
13
13
  import * as defaults from '../internal/defaults.js';
14
14
  import * as FeePayer from '../internal/fee-payer.js';
15
+ import { resolveFeeToken } from '../internal/fee-token.js';
15
16
  import * as Proof from '../internal/proof.js';
16
17
  import * as Methods from '../Methods.js';
17
18
  import { assertSubscriptionTiming, toSubscriptionPeriodSeconds, verifySubscriptionKeyAuthorization, } from '../subscription/KeyAuthorization.js';
@@ -246,6 +247,7 @@ export function subscription(p) {
246
247
  });
247
248
  }
248
249
  if (activation.status === 'inFlight') {
250
+ await store.releaseCredential(credential.challenge.id);
249
251
  throw new VerificationFailedError({
250
252
  reason: 'subscription activation is already in flight',
251
253
  });
@@ -283,8 +285,13 @@ export function subscription(p) {
283
285
  if (!renewal) {
284
286
  throw new VerificationFailedError({ reason: 'subscription renewal failed' });
285
287
  }
286
- if (renewal.status === 'charged' || renewal.status === 'inFlight') {
288
+ if (renewal.status === 'charged')
287
289
  return renewal.receipt;
290
+ if (renewal.status === 'inFlight') {
291
+ await store.releaseCredential(credential.challenge.id);
292
+ throw new VerificationFailedError({
293
+ reason: 'subscription renewal is already in flight',
294
+ });
288
295
  }
289
296
  await parameters.hooks?.renewed?.({
290
297
  periodIndex,
@@ -306,6 +313,7 @@ export function subscription(p) {
306
313
  }
307
314
  // Access-key provisioning can cost around 4M gas.
308
315
  const defaultFeePayerPolicy = {
316
+ allowKeyAuthorization: true,
309
317
  maxGas: 5000000n,
310
318
  maxTotalFee: 200000000000000000n,
311
319
  };
@@ -688,6 +696,17 @@ async function submitSubscriptionPayment(parameters) {
688
696
  ...baseTransaction,
689
697
  nonceKey: 'expiring',
690
698
  });
699
+ const resolvedChainId = chainId ?? client.chain.id;
700
+ const allowedFeeTokens = FeePayer.defaultAllowedFeeTokens(resolvedChainId);
701
+ const feeToken = allowedFeeTokens.length === 1
702
+ ? allowedFeeTokens[0]
703
+ : await resolveFeeToken({
704
+ account: feePayer.address,
705
+ allowedTokens: allowedFeeTokens,
706
+ candidateTokens: allowedFeeTokens,
707
+ client,
708
+ });
709
+ delete prepared.feeToken;
691
710
  prepared.gas = (prepared.gas ?? 0n) + 5000n;
692
711
  prepared.feePayer = true;
693
712
  const userSerialized = await signTransaction(client, prepared);
@@ -698,16 +717,24 @@ async function submitSubscriptionPayment(parameters) {
698
717
  async complete() {
699
718
  const sponsored = FeePayer.prepareSponsoredTransaction({
700
719
  account: feePayer,
701
- chainId: chainId ?? client.chain.id,
720
+ allowedFeeTokens,
721
+ chainId: resolvedChainId,
702
722
  details: {
703
723
  amount: String(request.amount),
704
724
  currency: String(request.currency),
705
725
  recipient: String(request.recipient),
706
726
  },
707
727
  ...(feePayerPolicy ? { policy: feePayerPolicy } : {}),
708
- transaction: userTransaction,
728
+ transaction: {
729
+ ...userTransaction,
730
+ ...(feeToken ? { feeToken } : {}),
731
+ },
709
732
  });
710
- return { feePayer: feePayer.address, transaction: sponsored };
733
+ return {
734
+ feePayer: feePayer.address,
735
+ feeToken: sponsored.feeToken,
736
+ transaction: sponsored,
737
+ };
711
738
  },
712
739
  });
713
740
  return await signTransaction(client, completed.transaction);