mppx 0.8.9 → 0.8.12

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 (124) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/cli/validate/challenge.d.ts +2 -0
  3. package/dist/cli/validate/challenge.d.ts.map +1 -1
  4. package/dist/cli/validate/challenge.js +21 -9
  5. package/dist/cli/validate/challenge.js.map +1 -1
  6. package/dist/cli/validate/discovery.d.ts.map +1 -1
  7. package/dist/cli/validate/discovery.js +50 -19
  8. package/dist/cli/validate/discovery.js.map +1 -1
  9. package/dist/cli/validate/helpers.d.ts +1 -0
  10. package/dist/cli/validate/helpers.d.ts.map +1 -1
  11. package/dist/cli/validate/helpers.js +11 -0
  12. package/dist/cli/validate/helpers.js.map +1 -1
  13. package/dist/cli/validate/index.d.ts +1 -0
  14. package/dist/cli/validate/index.d.ts.map +1 -1
  15. package/dist/cli/validate/index.js +4 -0
  16. package/dist/cli/validate/index.js.map +1 -1
  17. package/dist/cli/validate/payment.d.ts +1 -0
  18. package/dist/cli/validate/payment.d.ts.map +1 -1
  19. package/dist/cli/validate/payment.js +2 -2
  20. package/dist/cli/validate/payment.js.map +1 -1
  21. package/dist/client/internal/Fetch.d.ts.map +1 -1
  22. package/dist/client/internal/Fetch.js +35 -6
  23. package/dist/client/internal/Fetch.js.map +1 -1
  24. package/dist/client/internal/MethodResponse.d.ts +23 -0
  25. package/dist/client/internal/MethodResponse.d.ts.map +1 -0
  26. package/dist/client/internal/MethodResponse.js +15 -0
  27. package/dist/client/internal/MethodResponse.js.map +1 -0
  28. package/dist/tempo/internal/fee-payer.d.ts +39 -2
  29. package/dist/tempo/internal/fee-payer.d.ts.map +1 -1
  30. package/dist/tempo/internal/fee-payer.js +45 -1
  31. package/dist/tempo/internal/fee-payer.js.map +1 -1
  32. package/dist/tempo/internal/fee-token.d.ts +8 -0
  33. package/dist/tempo/internal/fee-token.d.ts.map +1 -1
  34. package/dist/tempo/internal/fee-token.js +19 -6
  35. package/dist/tempo/internal/fee-token.js.map +1 -1
  36. package/dist/tempo/legacy/client/ChannelOps.d.ts +2 -0
  37. package/dist/tempo/legacy/client/ChannelOps.d.ts.map +1 -1
  38. package/dist/tempo/legacy/client/ChannelOps.js +4 -0
  39. package/dist/tempo/legacy/client/ChannelOps.js.map +1 -1
  40. package/dist/tempo/legacy/client/Session.d.ts.map +1 -1
  41. package/dist/tempo/legacy/client/Session.js +7 -0
  42. package/dist/tempo/legacy/client/Session.js.map +1 -1
  43. package/dist/tempo/legacy/session/Chain.d.ts.map +1 -1
  44. package/dist/tempo/legacy/session/Chain.js +53 -50
  45. package/dist/tempo/legacy/session/Chain.js.map +1 -1
  46. package/dist/tempo/server/Charge.d.ts +8 -0
  47. package/dist/tempo/server/Charge.d.ts.map +1 -1
  48. package/dist/tempo/server/Charge.js +49 -45
  49. package/dist/tempo/server/Charge.js.map +1 -1
  50. package/dist/tempo/server/Methods.d.ts +7 -0
  51. package/dist/tempo/server/Methods.d.ts.map +1 -1
  52. package/dist/tempo/server/Methods.js.map +1 -1
  53. package/dist/tempo/server/Subscription.d.ts.map +1 -1
  54. package/dist/tempo/server/Subscription.js +24 -16
  55. package/dist/tempo/server/Subscription.js.map +1 -1
  56. package/dist/tempo/server/internal/html.gen.d.ts +1 -1
  57. package/dist/tempo/server/internal/html.gen.d.ts.map +1 -1
  58. package/dist/tempo/server/internal/html.gen.js +1 -1
  59. package/dist/tempo/server/internal/html.gen.js.map +1 -1
  60. package/dist/tempo/session/client/Session.d.ts.map +1 -1
  61. package/dist/tempo/session/client/Session.js +53 -1
  62. package/dist/tempo/session/client/Session.js.map +1 -1
  63. package/dist/tempo/session/client/SessionManager.d.ts +3 -0
  64. package/dist/tempo/session/client/SessionManager.d.ts.map +1 -1
  65. package/dist/tempo/session/client/SessionManager.js +3 -0
  66. package/dist/tempo/session/client/SessionManager.js.map +1 -1
  67. package/dist/tempo/session/client/Transports.d.ts +30 -0
  68. package/dist/tempo/session/client/Transports.d.ts.map +1 -1
  69. package/dist/tempo/session/client/Transports.js +118 -19
  70. package/dist/tempo/session/client/Transports.js.map +1 -1
  71. package/dist/tempo/session/precompile/Chain.d.ts.map +1 -1
  72. package/dist/tempo/session/precompile/Chain.js +25 -19
  73. package/dist/tempo/session/precompile/Chain.js.map +1 -1
  74. package/dist/tempo/session/server/index.d.ts +2 -0
  75. package/dist/tempo/session/server/index.d.ts.map +1 -1
  76. package/dist/tempo/session/server/index.js +2 -0
  77. package/dist/tempo/session/server/index.js.map +1 -1
  78. package/dist/validation/core.d.ts +1 -0
  79. package/dist/validation/core.d.ts.map +1 -1
  80. package/dist/validation/core.js +5 -0
  81. package/dist/validation/core.js.map +1 -1
  82. package/dist/x402/Header.js +1 -1
  83. package/dist/x402/Header.js.map +1 -1
  84. package/package.json +1 -1
  85. package/src/cli/validate/challenge.ts +20 -8
  86. package/src/cli/validate/discovery.test.ts +128 -0
  87. package/src/cli/validate/discovery.ts +50 -15
  88. package/src/cli/validate/helpers.ts +10 -0
  89. package/src/cli/validate/index.ts +4 -0
  90. package/src/cli/validate/payment.ts +4 -1
  91. package/src/cli/validate.test.ts +23 -2
  92. package/src/client/Mppx.test-d.ts +3 -1
  93. package/src/client/internal/Fetch.test.ts +29 -0
  94. package/src/client/internal/Fetch.ts +51 -6
  95. package/src/client/internal/MethodResponse.ts +39 -0
  96. package/src/tempo/PublicExports.test-d.ts +5 -0
  97. package/src/tempo/internal/fee-payer.test.ts +93 -0
  98. package/src/tempo/internal/fee-payer.ts +64 -2
  99. package/src/tempo/internal/fee-token.test.ts +37 -0
  100. package/src/tempo/internal/fee-token.ts +26 -5
  101. package/src/tempo/legacy/client/ChannelOps.test.ts +21 -0
  102. package/src/tempo/legacy/client/ChannelOps.ts +7 -0
  103. package/src/tempo/legacy/client/Session.test.ts +102 -1
  104. package/src/tempo/legacy/client/Session.ts +10 -0
  105. package/src/tempo/legacy/session/Chain.test.ts +78 -2
  106. package/src/tempo/legacy/session/Chain.ts +56 -52
  107. package/src/tempo/server/Charge.test.ts +121 -6
  108. package/src/tempo/server/Charge.ts +61 -48
  109. package/src/tempo/server/Methods.ts +6 -0
  110. package/src/tempo/server/Subscription.test.ts +79 -4
  111. package/src/tempo/server/Subscription.ts +24 -16
  112. package/src/tempo/server/internal/html.gen.ts +1 -1
  113. package/src/tempo/session/client/Session.test.ts +83 -1
  114. package/src/tempo/session/client/Session.ts +73 -1
  115. package/src/tempo/session/client/SessionManager.test.ts +12 -1
  116. package/src/tempo/session/client/SessionManager.ts +5 -0
  117. package/src/tempo/session/client/Transports.test.ts +109 -0
  118. package/src/tempo/session/client/Transports.ts +153 -29
  119. package/src/tempo/session/precompile/Chain.test.ts +9 -0
  120. package/src/tempo/session/precompile/Chain.ts +28 -20
  121. package/src/tempo/session/server/Session.test.ts +23 -3
  122. package/src/tempo/session/server/index.ts +2 -0
  123. package/src/validation/core.ts +6 -0
  124. package/src/x402/Header.ts +1 -1
@@ -434,15 +434,10 @@ function parsePrecompileCredentialTransaction(parameters: {
434
434
  return { transaction, call: { ...call, data: call.data, to: call.to } }
435
435
  }
436
436
 
437
- async function simulateTempoTransaction(client: Client, transaction: Transaction.TransactionTempo) {
437
+ async function simulateTempoTransaction(client: Client, request: unknown) {
438
438
  // viem's public `call` type does not yet model Tempo's multi-call and
439
439
  // fee-payer fields together. Keep that compatibility cast in one place.
440
- await call(client, {
441
- ...transaction,
442
- account: transaction.from,
443
- calls: transaction.calls ?? [],
444
- feePayerSignature: undefined,
445
- } as never)
440
+ await call(client, request as never)
446
441
  }
447
442
 
448
443
  async function signTempoTransaction(client: Client, transaction: unknown): Promise<Hex> {
@@ -705,25 +700,38 @@ export async function sendCredentialTransaction(parameters: SendCredentialTransa
705
700
  assertSenderSigned(transaction)
706
701
 
707
702
  if (feePayer === true) {
703
+ // The transport owns hosted completion, so mppx can only preflight call
704
+ // execution as the sender. It intentionally omits fee fields here; the
705
+ // transport is responsible for validating its final sponsored envelope.
706
+ await simulateTempoTransaction(
707
+ client,
708
+ FeePayer.simulationTransaction(transaction, { feePayer: true }),
709
+ )
708
710
  const txHash = await sendTransaction(client, serializedTransaction)
709
711
  return waitForSuccessfulReceipt(client, txHash)
710
712
  }
711
713
 
712
- await simulateTempoTransaction(client, transaction)
713
-
714
- const sponsored = FeePayer.prepareSponsoredTransaction({
715
- account: feePayer,
716
- allowedFeeTokens,
717
- challengeExpires,
718
- chainId,
719
- details,
720
- policy: feePayerPolicy,
721
- transaction: {
722
- ...transaction,
723
- ...(allowedFeeTokens?.[0] ? { feeToken: transaction.feeToken ?? allowedFeeTokens[0] } : {}),
714
+ const sponsorshipTransaction = {
715
+ ...transaction,
716
+ ...(allowedFeeTokens?.[0] ? { feeToken: transaction.feeToken ?? allowedFeeTokens[0] } : {}),
717
+ }
718
+ const completed = await FeePayer.preflightSponsorship({
719
+ transaction: sponsorshipTransaction,
720
+ simulate: (request) => simulateTempoTransaction(client, request),
721
+ async complete() {
722
+ const sponsored = FeePayer.prepareSponsoredTransaction({
723
+ account: feePayer,
724
+ allowedFeeTokens,
725
+ challengeExpires,
726
+ chainId,
727
+ details,
728
+ policy: feePayerPolicy,
729
+ transaction: sponsorshipTransaction,
730
+ })
731
+ return { feePayer: feePayer.address, transaction: sponsored }
724
732
  },
725
733
  })
726
- const serialized = await signTempoTransaction(client, sponsored)
734
+ const serialized = await signTempoTransaction(client, completed.transaction)
727
735
  const receipt = await sendRawTransactionSync(client, {
728
736
  serializedTransaction: serialized as Transaction.TransactionSerializedTempo,
729
737
  })
@@ -2257,6 +2257,7 @@ describe('precompile server session unit guardrails', () => {
2257
2257
  action: SessionCredentialPayload['action']
2258
2258
  contentLength: string | null
2259
2259
  hasBody: boolean
2260
+ hasReceipt: boolean
2260
2261
  status: number
2261
2262
  }> = []
2262
2263
  const app = new Hono()
@@ -2271,6 +2272,7 @@ describe('precompile server session unit guardrails', () => {
2271
2272
  action: payload.action,
2272
2273
  contentLength: request.headers.get('content-length'),
2273
2274
  hasBody: request.body !== null,
2275
+ hasReceipt: response.headers.has(Constants.Headers.paymentReceipt),
2274
2276
  status: response.status,
2275
2277
  })
2276
2278
  return response
@@ -2302,9 +2304,27 @@ describe('precompile server session unit guardrails', () => {
2302
2304
  expect(closeReceipt?.spent).toBe('3')
2303
2305
  expect(managementPosts).toEqual(
2304
2306
  expect.arrayContaining([
2305
- { action: 'topUp', contentLength: '0', hasBody: true, status: 204 },
2306
- { action: 'voucher', contentLength: '0', hasBody: true, status: 204 },
2307
- { action: 'close', contentLength: '0', hasBody: true, status: 204 },
2307
+ {
2308
+ action: 'topUp',
2309
+ contentLength: '0',
2310
+ hasBody: true,
2311
+ hasReceipt: true,
2312
+ status: 204,
2313
+ },
2314
+ {
2315
+ action: 'voucher',
2316
+ contentLength: '0',
2317
+ hasBody: true,
2318
+ hasReceipt: true,
2319
+ status: 204,
2320
+ },
2321
+ {
2322
+ action: 'close',
2323
+ contentLength: '0',
2324
+ hasBody: true,
2325
+ hasReceipt: true,
2326
+ status: 204,
2327
+ },
2308
2328
  ]),
2309
2329
  )
2310
2330
  expect(managementPosts.every(({ status }) => status === 204)).toBe(true)
@@ -1,4 +1,6 @@
1
1
  export { charge, session, settle, settleBatch } from './Session.js'
2
+ /** SSE helpers and types for Tempo session streams. */
3
+ export * as Sse from './Sse.js'
2
4
  /** Server-side automatic settlement schedule. */
3
5
  export type {
4
6
  ResolveSessionChannelId,
@@ -25,6 +25,7 @@ export type ValidateOptions = {
25
25
  endpoint?: string | undefined
26
26
  body?: string | undefined
27
27
  query?: string[] | undefined
28
+ headers?: string[] | undefined
28
29
  verbose?: boolean | undefined
29
30
  yes?: boolean | undefined
30
31
  skipPayment?: boolean | undefined
@@ -92,12 +93,14 @@ export async function* validateStream(options: ValidateOptions): AsyncGenerator<
92
93
  yield { phase: 'endpoint', endpoint }
93
94
 
94
95
  let body: string | undefined
96
+ let bodyIsAutogenerated = false
95
97
  if (options.endpoint) {
96
98
  body = options.body
97
99
  } else {
98
100
  body = resolveBodyForEndpoint(options.body, endpoint.path)
99
101
  if (!body && discovery.doc) {
100
102
  body = extractRequestBodyFromDiscovery(discovery.doc, endpoint)
103
+ bodyIsAutogenerated = !!body
101
104
  }
102
105
  }
103
106
 
@@ -107,7 +110,9 @@ export async function* validateStream(options: ValidateOptions): AsyncGenerator<
107
110
  challenges: parsedChallenges,
108
111
  } = await validateChallenge(baseUrl, endpoint, verbose, {
109
112
  body,
113
+ bodyIsAutogenerated,
110
114
  query: options.query,
115
+ extraHeaders: options.headers,
111
116
  discoveryDoc: discovery.doc ?? undefined,
112
117
  })
113
118
  const effectiveBody = resolvedBody ?? body
@@ -156,6 +161,7 @@ export async function* validateStream(options: ValidateOptions): AsyncGenerator<
156
161
  const paymentResults = await validatePaymentFlow(baseUrl, endpoint, verbose, {
157
162
  body: effectiveBody,
158
163
  query: options.query,
164
+ extraHeaders: options.headers,
159
165
  yes: options.yes,
160
166
  silent: !onResults,
161
167
  interactive: options.interactive,
@@ -68,7 +68,7 @@ const parsePaymentRequiredEnvelope = (value: unknown): PaymentRequiredEnvelope =
68
68
 
69
69
  const resource = ResourceInfoSchema.parse(record.resource)
70
70
  const extensions =
71
- record.extensions === undefined ? undefined : ExtensionsSchema.parse(record.extensions)
71
+ record.extensions !== undefined ? ExtensionsSchema.safeParse(record.extensions).data : undefined
72
72
 
73
73
  return {
74
74
  accepts: record.accepts,