mppx 0.13.4 → 0.13.6

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 (73) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/dist/Credential.d.ts +3 -0
  3. package/dist/Credential.js +9 -0
  4. package/dist/Errors.d.ts +63 -2
  5. package/dist/Errors.js +52 -2
  6. package/dist/Method.d.ts +10 -0
  7. package/dist/cli/cli.js +92 -92
  8. package/dist/cli/plugins/evm.js +2 -2
  9. package/dist/cli/plugins/index.js +12 -12
  10. package/dist/client/Mppx.d.ts +2 -0
  11. package/dist/client/Mppx.js +8 -10
  12. package/dist/client/internal/Fetch.js +107 -8
  13. package/dist/client/internal/MethodChallenge.d.ts +2 -0
  14. package/dist/client/internal/MethodChallenge.js +4 -0
  15. package/dist/client/internal/MethodResponse.d.ts +6 -0
  16. package/dist/client/internal/MethodResponse.js +16 -0
  17. package/dist/client/internal/protocols/Mcp.js +36 -5
  18. package/dist/evm/server/Charge.js +3 -1
  19. package/dist/internal/version.d.ts +2 -2
  20. package/dist/internal/version.js +1 -1
  21. package/dist/internal/warnOnce.d.ts +3 -0
  22. package/dist/internal/warnOnce.js +9 -0
  23. package/dist/server/Mppx.d.ts +5 -0
  24. package/dist/server/Mppx.js +45 -18
  25. package/dist/server/Transport.js +10 -0
  26. package/dist/stripe/server/Methods.js +4 -1
  27. package/dist/tempo/Attribution.d.ts +24 -9
  28. package/dist/tempo/Attribution.js +25 -5
  29. package/dist/tempo/client/Charge.d.ts +116 -10
  30. package/dist/tempo/client/Charge.js +117 -22
  31. package/dist/tempo/client/Methods.d.ts +88 -9
  32. package/dist/tempo/index.d.ts +1 -0
  33. package/dist/tempo/index.js +1 -0
  34. package/dist/tempo/internal/auto-swap.d.ts +10 -0
  35. package/dist/tempo/internal/auto-swap.js +35 -8
  36. package/dist/tempo/internal/fee-payer.d.ts +8 -0
  37. package/dist/tempo/internal/fee-payer.js +20 -8
  38. package/dist/tempo/legacy/session/Chain.js +8 -2
  39. package/dist/tempo/server/Charge.d.ts +11 -0
  40. package/dist/tempo/server/Charge.js +160 -29
  41. package/dist/tempo/server/Methods.js +28 -5
  42. package/dist/tempo/server/Relay.js +6 -22
  43. package/dist/tempo/server/Subscription.js +5 -1
  44. package/dist/tempo/server/internal/fallback-store.d.ts +9 -0
  45. package/dist/tempo/server/internal/fallback-store.js +13 -0
  46. package/dist/tempo/server/internal/html.gen.js +1 -1
  47. package/dist/tempo/server/internal/transport.d.ts +3 -0
  48. package/dist/tempo/server/internal/transport.js +5 -1
  49. package/dist/tempo/session/client/ChannelOps.d.ts +2 -0
  50. package/dist/tempo/session/client/ChannelStore.d.ts +12 -1
  51. package/dist/tempo/session/client/ChannelStore.js +47 -0
  52. package/dist/tempo/session/client/CredentialState.js +8 -3
  53. package/dist/tempo/session/client/Session.js +50 -33
  54. package/dist/tempo/session/client/SessionManager.js +186 -65
  55. package/dist/tempo/session/client/Transports.d.ts +6 -0
  56. package/dist/tempo/session/client/Transports.js +52 -7
  57. package/dist/tempo/session/precompile/Chain.d.ts +2 -0
  58. package/dist/tempo/session/precompile/Chain.js +8 -3
  59. package/dist/tempo/session/server/ChannelStore.d.ts +34 -0
  60. package/dist/tempo/session/server/ChannelStore.js +69 -9
  61. package/dist/tempo/session/server/CredentialVerification.d.ts +7 -1
  62. package/dist/tempo/session/server/CredentialVerification.js +220 -48
  63. package/dist/tempo/session/server/MeteredStream.d.ts +6 -5
  64. package/dist/tempo/session/server/MeteredStream.js +10 -26
  65. package/dist/tempo/session/server/Session.d.ts +29 -2
  66. package/dist/tempo/session/server/Session.js +124 -44
  67. package/dist/tempo/session/server/Settlement.d.ts +9 -0
  68. package/dist/tempo/session/server/Settlement.js +23 -3
  69. package/dist/tempo/session/server/Sse.d.ts +4 -3
  70. package/dist/tempo/session/server/Sse.js +3 -3
  71. package/dist/tempo/session/server/Ws.d.ts +9 -1
  72. package/dist/tempo/session/server/Ws.js +1 -0
  73. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,53 @@
1
1
  # mppx
2
2
 
3
+ ## 0.13.6
4
+
5
+ ### Patch Changes
6
+
7
+ - 82810df: Added `autoSwap.fallback` to Tempo charges. Setting `fallback: false` swaps only from `tokenIn`, as an allowlist, instead of also trying pathUSD and USDC afterwards.
8
+ - 82810df: Added OUSD to the default Tempo auto-swap currencies, after pathUSD and USDC.
9
+ - 0acc2bc: Fixed Tempo charge auto-swap finding no route for an access key whose authorization was not yet published. Balance and DEX quote reads no longer carry the client's account, which the node rejected with `KeyNotFound`.
10
+ - 7827823: Bounded session management POSTs to 30 seconds so stalled endpoints cannot hold funding waiters indefinitely. Timed-out payments report an unknown outcome and ignore late responses.
11
+
12
+ Persisted uncertain top-up state in the channel store after dispatched management requests timed out, failed, or were cancelled and blocked new deposits, including from replacement managers. Callers must reconcile the pending transaction against trusted chain state before clearing that state.
13
+
14
+ - 4de6876: Bounded payment authorization values to 64 KiB before scheme extraction and decoding.
15
+ - 80f9a76: Rechecked sponsored subscription and session transaction deadlines before signing and submission. Aligned validity-window rounding and rejected maximum windows below the required 15 seconds.
16
+ - 051510d: Fixed `compose()` dispatch for handlers without a static `scope`. Their challenges are scoped to the request's route, so dispatch now compares the credential's metadata with that scope merged in, instead of falling back to the first handler with the same method and intent.
17
+ - 626afc6: Fixed `compose()` dispatching every `tempo/session` credential to the first session handler. Dispatch compared the credential with each handler's route request, which lacks the `chainId` and `sessionProtocol` the session request hook adds, so no handler matched; sessions offered in several currencies rejected all but the first with a currency mismatch.
18
+ - f82decc: Sessions now read on-chain channel state concurrently with the stored channel when accepting a voucher, instead of after it. The forced on-chain refresh and error precedence are unchanged.
19
+ - 7055666: Fixed manual streaming charges to commit before stream.charge() resolved, retaining charges when subsequent work was canceled or failed.
20
+ - 3f95f89: Fixed the EVM CLI plugin to use the selected account when signing payments.
21
+ - 3b18cd0: Paid session requests make fewer store round trips. Validating a voucher credential right before broadcasting it no longer reads the stored channel, since broadcasting checks it again. With `voucherStateMaxAge`, a voucher is checked against the stored channel inside the store update that accepts it, without a separate read. The new `chargeOnAcceptance` option charges request-priced content in that same update instead of a second update when the response is delivered.
22
+ - 97eb961: Added `reusableChallenges` to `tempo.session()`. A session challenge then stays valid for later requests to the same route until it expires: it is bound to its route, currency, recipient and channel terms but not to the amount it quoted, and every request is charged its own price from the channel's accepted balance. Clients can send a voucher with a request instead of waiting for a `402`. Composed handlers with a stable binding are now also dispatched by the fields their route request defines, and with reusable challenges session SSE responses charge the verified route request's amount.
23
+ - 22e5b42: Limited automatic swaps to the missing balance and bounded spending independently of DEX quotes. Added an explicit maxAmountIn budget for non-parity token pairs; defaults assumed 1:1 token units plus slippage. Sponsored charge validation accepted partial acquisition up to the payment amount.
24
+ - 132a793: Stopped reusing cached relay receipts as new payment authorizations. Relay broadcasts now omit idempotency keys so reused credentials are rejected; applications should recover uncertain outcomes separately from executing protected operations.
25
+ - 78d0a04: Serialized session-manager top-ups and refreshed the active deposit before subsequent funding decisions, preventing concurrent automatic requests from exceeding the configured deposit limit.
26
+ - 9ad515a: Fixed Stripe-backed session offers to enforce the one-cent recording minimum before application offer policies.
27
+ - d4dddfc: Checked on-chain escrow during managed SSE and WebSocket streams and stopped delivery when escrow closed or checks failed.
28
+ - 13a9035: Added `voucherStateMaxAge` to `tempo.session()`. Vouchers within the deposit of on-chain state verified that recently are accepted without waiting for a fresh on-chain read, which finishes in the background and records a pending close for later vouchers. The verification time is persisted on the stored channel so every server instance can use it. The default `0` keeps reading on-chain state before every acceptance.
29
+
30
+ ## 0.13.5
31
+
32
+ ### Patch Changes
33
+
34
+ - 19315c7: Bounded automatic MCP JSON and SSE payment-challenge inspection to 1 MiB while preserving the original response stream for callers.
35
+ - 9da0e18: Removed retained native response bodies from manual payment event snapshots to prevent unbounded buffering while callers consume streams. Status and headers remained available; non-HTTP transport snapshots were unchanged.
36
+ - 68381a4: Fixed Tempo charge `validBefore` to cover a fractional challenge expiry, so charge transactions stay valid for as long as their challenge.
37
+ - ca6f04b: Exported `Attribution` from `mppx/tempo` so apps can encode, decode, and verify MPP attribution memos on TIP-20 transfers.
38
+ - b085cae: Exposed the verified payer as `payer` on payment success contexts and per-method `onPaymentSuccess` hooks. Tempo charge and EVM charge validation now report the recovered payer address as `payer`.
39
+ - 47beb31: Attached the original error as `cause` on `InternalPaymentError` so payment hooks can inspect unexpected failures, and added `CredentialReplayedError` (a `VerificationFailedError` subclass) for Tempo charge credentials whose payment already settled: replayed transaction hashes and proofs, claims held by a concurrent request, and settled transfers whose memo is bound to another challenge. The HTTP transport and session bootstrap answer it with a final 403 Problem Details response without a `WWW-Authenticate` challenge, so clients do not pay again; the problem type stays `verification-failed`.
40
+ - 7271a85: Recovered confirmed Tempo charges when a synchronous broadcast returned an RPC error after inclusion.
41
+ - 08fa745: Released Tempo charge transaction hash claims when settlement fails after a broadcast attempt, so retrying the same credential re-broadcasts and recovers the receipt instead of being rejected as a replay.
42
+ - 1e692c3: Added `Errors.PaymentOutcomeUnknownError` and emitted it through `payment.failed` when a paid retry returns a 5xx response, carrying the challenge, credential, and the transaction hash for push and unsponsored Tempo charges. The response is still returned and never retried; when `payment.failed` is observed, its body is first buffered up to 64 KiB within 2 seconds so the connection is released, and a cut-off body is marked with `Mppx-Body-Truncated: true`. A thrown paid retry now passes the same error to `payment.failed` with the original error as `cause`, and the original error is still thrown.
43
+ - 74533b0: Required at least 15 seconds of remaining validity before sponsoring and broadcasting transactions.
44
+ - 94162a5: Fixed session settlements failing the charged request when a lagging RPC replica reverted the settle while preparing it (such as `ChannelNotFound` right after an open); `settle()` now retries reverted preparations.
45
+ - 763a187: Shared default sponsor-budget storage across currency offers from tempo.charge and tempo.common, enforcing aggregate exposure limits without changing replay-store policy. Multi-process deployments still require a shared atomic store.
46
+ - 68381a4: Shared one in-flight signing between concurrent Tempo charge requests for the same challenge and signer.
47
+ - 61b4c10: Added `maxAmount` (display units, parsed with `decimals`) and `maxAtomicAmount` (base units) to the `tempo.charge()` client, matching the EVM charge client, plus a `currencies` allowlist that the caps require. Offers that exceed a cap or fail `currencies`, `expectedRecipients`, `expectedChainId`, or `allowedChainIds` are skipped during challenge selection and rejected before signing, and a `maxAmount` that would round is rejected.
48
+ - 29855e8: Bounded synchronous Tempo charge broadcasts by a configurable `confirmationTimeoutMs` deadline (default 30 seconds). The broadcast may use at most two thirds of it, which leaves time for recovery. When the broadcast outcome is unknown, such as a timeout, a lost connection, or an "already known" response, the receipt is now polled until the deadline instead of failing while the transaction is still pending. Polling stops early once an expiring transaction is past its `validBefore`, followed by one final receipt lookup. Definitive RPC rejections still fail immediately.
49
+ - 27213df: Added a one-time warning when Tempo `charge`, `session`, or `subscription` server methods fall back to an in-memory store, since replay protection backed by it only applies within a single instance.
50
+
3
51
  ## 0.13.4
4
52
 
5
53
  ### Patch Changes
@@ -24,6 +24,7 @@ export declare class InvalidCredentialEncodingError extends Error {
24
24
  }
25
25
  /**
26
26
  * Deserializes a Payment credential header value to a credential.
27
+ * Rejects values longer than 64 KiB before decoding.
27
28
  * Accepts the spec-compliant base64url `opaque` string shape and the legacy
28
29
  * object-shaped `opaque` form emitted by older mppx versions.
29
30
  *
@@ -106,6 +107,8 @@ export declare function serialize(credential: Credential): string;
106
107
  * Extracts the `Payment` scheme from an Authorization header value
107
108
  * that may contain multiple schemes (comma-separated per RFC 9110).
108
109
  *
110
+ * Values longer than 64 KiB are rejected before splitting.
111
+ *
109
112
  * @param header - The raw Authorization header value.
110
113
  * @returns The `Payment ...` scheme string, or `null` if not found.
111
114
  */
@@ -2,6 +2,8 @@ import { Base64 } from 'ox';
2
2
  import * as Challenge from './Challenge.js';
3
3
  import * as Constants from './Constants.js';
4
4
  import * as PaymentRequest from './PaymentRequest.js';
5
+ // Allow the echoed challenge and payment payload to expand during JSON/base64 encoding.
6
+ const maxAuthorizationLength = 64 * 1024;
5
7
  export class MissingAuthorizationHeaderError extends Error {
6
8
  name = 'MissingAuthorizationHeaderError';
7
9
  constructor(header = Constants.Headers.authorization) {
@@ -22,6 +24,7 @@ export class InvalidCredentialEncodingError extends Error {
22
24
  }
23
25
  /**
24
26
  * Deserializes a Payment credential header value to a credential.
27
+ * Rejects values longer than 64 KiB before decoding.
25
28
  * Accepts the spec-compliant base64url `opaque` string shape and the legacy
26
29
  * object-shaped `opaque` form emitted by older mppx versions.
27
30
  *
@@ -36,6 +39,8 @@ export class InvalidCredentialEncodingError extends Error {
36
39
  * ```
37
40
  */
38
41
  export function deserialize(value) {
42
+ if (value.length > maxAuthorizationLength)
43
+ throw new InvalidCredentialEncodingError();
39
44
  const prefixMatch = value.match(new RegExp(`^${Constants.Schemes.payment}\\s+(.+)$`, 'i'));
40
45
  if (!prefixMatch?.[1])
41
46
  throw new MissingPaymentSchemeError();
@@ -162,10 +167,14 @@ export function serialize(credential) {
162
167
  * Extracts the `Payment` scheme from an Authorization header value
163
168
  * that may contain multiple schemes (comma-separated per RFC 9110).
164
169
  *
170
+ * Values longer than 64 KiB are rejected before splitting.
171
+ *
165
172
  * @param header - The raw Authorization header value.
166
173
  * @returns The `Payment ...` scheme string, or `null` if not found.
167
174
  */
168
175
  export function extractPaymentScheme(header) {
176
+ if (header.length > maxAuthorizationLength)
177
+ return null;
169
178
  const schemes = header.split(',').map((s) => s.trim());
170
179
  return schemes.find((s) => new RegExp(`^${Constants.Schemes.payment}\\s+`, 'i').test(s)) ?? null;
171
180
  }
package/dist/Errors.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type * as Challenge from './Challenge.js';
1
2
  /** Default hint messages for payment errors. */
2
3
  export declare const Hints: {
3
4
  readonly paymentRequired: 'Use a supported wallet to pay for this resource using one of the supported payment methods returned in the WWW-Authenticate header. See https://mpp.dev/tools/wallet.md';
@@ -24,6 +25,8 @@ export declare abstract class PaymentError extends Error {
24
25
  }
25
26
  export declare namespace PaymentError {
26
27
  type Options = {
28
+ /** Underlying error. Never serialized into Problem Details. */
29
+ cause?: unknown;
27
30
  details?: Record<string, unknown> | undefined;
28
31
  };
29
32
  type ProblemDetails = {
@@ -82,7 +85,7 @@ export declare namespace InvalidChallengeError {
82
85
  * Payment proof is invalid or verification failed.
83
86
  */
84
87
  export declare class VerificationFailedError extends PaymentError {
85
- readonly name = "VerificationFailedError";
88
+ readonly name: string;
86
89
  readonly title = "Verification Failed";
87
90
  readonly type = "https://paymentauth.org/problems/verification-failed";
88
91
  constructor(options?: VerificationFailedError.Options);
@@ -95,15 +98,43 @@ export declare namespace VerificationFailedError {
95
98
  reason?: string;
96
99
  };
97
100
  }
101
+ /**
102
+ * The payment behind a credential is already used or bound elsewhere: the
103
+ * credential was consumed by an earlier request, is being settled by a
104
+ * concurrent one, or its settled transfer is bound to another challenge.
105
+ *
106
+ * Answered with 403 and no challenge (the payment was valid, but policy
107
+ * denies access), since a fresh 402 challenge would invite an auto-paying
108
+ * client to pay again. The problem type stays `verification-failed`.
109
+ */
110
+ export declare class CredentialReplayedError extends VerificationFailedError {
111
+ readonly name = "CredentialReplayedError";
112
+ readonly status = 403;
113
+ constructor(options?: CredentialReplayedError.Options);
114
+ }
115
+ export declare namespace CredentialReplayedError {
116
+ type Options = {
117
+ /** Reason the credential was rejected (e.g., "Transaction hash has already been used"). */
118
+ reason?: string;
119
+ };
120
+ }
98
121
  /**
99
122
  * Payment processing failed because of an unexpected internal error.
123
+ *
124
+ * The response stays generic; the original error is only available on `cause`.
100
125
  */
101
126
  export declare class InternalPaymentError extends PaymentError {
102
127
  readonly name = "InternalPaymentError";
103
128
  readonly title = "Internal Payment Error";
104
129
  readonly status = 500;
105
130
  readonly type = "https://paymentauth.org/problems/internal-payment-error";
106
- constructor();
131
+ constructor(options?: InternalPaymentError.Options);
132
+ }
133
+ export declare namespace InternalPaymentError {
134
+ type Options = {
135
+ /** Original error, for server-side hooks and logging. Never sent to clients. */
136
+ cause?: unknown;
137
+ };
107
138
  }
108
139
  /**
109
140
  * Payment requires additional action (e.g., 3DS authentication).
@@ -135,6 +166,36 @@ export declare namespace PaymentExpiredError {
135
166
  expires?: string;
136
167
  };
137
168
  }
169
+ /**
170
+ * A credential was sent, but the payment result could not be confirmed.
171
+ *
172
+ * Reconcile with `credential` (and `transactionHash` when the method can derive it)
173
+ * instead of retrying, which could pay twice.
174
+ */
175
+ export declare class PaymentOutcomeUnknownError extends PaymentError {
176
+ readonly name = "PaymentOutcomeUnknownError";
177
+ readonly title = "Payment Outcome Unknown";
178
+ readonly type = "https://paymentauth.org/problems/payment-outcome-unknown";
179
+ /** Challenge the credential paid for. */
180
+ readonly challenge: Challenge.Challenge;
181
+ /** Serialized credential sent with the paid request. */
182
+ readonly credential: string;
183
+ /** On-chain hash the payment will have if it settled, when derivable from the credential. */
184
+ readonly transactionHash: string | undefined;
185
+ constructor(options: PaymentOutcomeUnknownError.Options);
186
+ }
187
+ export declare namespace PaymentOutcomeUnknownError {
188
+ type Options = {
189
+ /** Error thrown by the paid request, when it failed without a response. */
190
+ cause?: unknown;
191
+ /** Challenge the credential paid for. */
192
+ challenge: Challenge.Challenge;
193
+ /** Serialized credential sent with the paid request. */
194
+ credential: string;
195
+ /** On-chain hash the payment will have if it settled. */
196
+ transactionHash?: string | undefined;
197
+ };
198
+ }
138
199
  /**
139
200
  * No credential was provided but payment is required.
140
201
  */
package/dist/Errors.js CHANGED
@@ -17,6 +17,13 @@ export class PaymentError extends Error {
17
17
  constructor(message, options = {}) {
18
18
  super(message);
19
19
  this.details = options.details;
20
+ // Defined manually (non-enumerable, like native `cause`) so consumers on pre-ES2022 libs still typecheck.
21
+ if (options.cause !== undefined)
22
+ Object.defineProperty(this, 'cause', {
23
+ configurable: true,
24
+ value: options.cause,
25
+ writable: true,
26
+ });
20
27
  }
21
28
  /** Converts the error to RFC 9457 Problem Details format. */
22
29
  toProblemDetails(challengeId) {
@@ -74,16 +81,35 @@ export class VerificationFailedError extends PaymentError {
74
81
  });
75
82
  }
76
83
  }
84
+ /**
85
+ * The payment behind a credential is already used or bound elsewhere: the
86
+ * credential was consumed by an earlier request, is being settled by a
87
+ * concurrent one, or its settled transfer is bound to another challenge.
88
+ *
89
+ * Answered with 403 and no challenge (the payment was valid, but policy
90
+ * denies access), since a fresh 402 challenge would invite an auto-paying
91
+ * client to pay again. The problem type stays `verification-failed`.
92
+ */
93
+ export class CredentialReplayedError extends VerificationFailedError {
94
+ name = 'CredentialReplayedError';
95
+ status = 403;
96
+ constructor(options = {}) {
97
+ const { reason = 'Credential has already been used' } = options;
98
+ super({ reason });
99
+ }
100
+ }
77
101
  /**
78
102
  * Payment processing failed because of an unexpected internal error.
103
+ *
104
+ * The response stays generic; the original error is only available on `cause`.
79
105
  */
80
106
  export class InternalPaymentError extends PaymentError {
81
107
  name = 'InternalPaymentError';
82
108
  title = 'Internal Payment Error';
83
109
  status = 500;
84
110
  type = 'https://paymentauth.org/problems/internal-payment-error';
85
- constructor() {
86
- super('An internal payment error occurred.');
111
+ constructor(options = {}) {
112
+ super('An internal payment error occurred.', { cause: options.cause });
87
113
  }
88
114
  }
89
115
  /**
@@ -110,6 +136,30 @@ export class PaymentExpiredError extends PaymentError {
110
136
  super(expires ? `Payment expired at ${expires}.` : 'Payment has expired.');
111
137
  }
112
138
  }
139
+ /**
140
+ * A credential was sent, but the payment result could not be confirmed.
141
+ *
142
+ * Reconcile with `credential` (and `transactionHash` when the method can derive it)
143
+ * instead of retrying, which could pay twice.
144
+ */
145
+ export class PaymentOutcomeUnknownError extends PaymentError {
146
+ name = 'PaymentOutcomeUnknownError';
147
+ title = 'Payment Outcome Unknown';
148
+ type = 'https://paymentauth.org/problems/payment-outcome-unknown';
149
+ /** Challenge the credential paid for. */
150
+ challenge;
151
+ /** Serialized credential sent with the paid request. */
152
+ credential;
153
+ /** On-chain hash the payment will have if it settled, when derivable from the credential. */
154
+ transactionHash;
155
+ constructor(options) {
156
+ const { cause, challenge, credential, transactionHash } = options;
157
+ super(`Payment outcome is unknown after sending a credential for challenge "${challenge.id}". Do not blindly retry.`, { cause });
158
+ this.challenge = challenge;
159
+ this.credential = credential;
160
+ this.transactionHash = transactionHash;
161
+ }
162
+ }
113
163
  /**
114
164
  * No credential was provided but payment is required.
115
165
  */
package/dist/Method.d.ts CHANGED
@@ -127,6 +127,14 @@ export type Validation<method extends Method = Method, details = unknown> = Read
127
127
  intent: method['intent'];
128
128
  /** The validated payment method, repeated for convenient dispatch. */
129
129
  method: method['name'];
130
+ /**
131
+ * Payer identity established by method-specific validation, when the method
132
+ * can determine one (for example, the Tempo address that sent the payment).
133
+ *
134
+ * Unlike `source`, this is derived from the verified credential payload.
135
+ * Its format is method-specific.
136
+ */
137
+ payer?: string | undefined;
130
138
  /**
131
139
  * The validated method request after the method's schema transforms.
132
140
  *
@@ -191,6 +199,8 @@ export type OnPaymentSuccessFn<method extends Method> = (parameters: {
191
199
  /** Challenge associated with the successful payment. */
192
200
  challenge?: DeepReadonly<Challenge.Challenge<z.output<method['schema']['request']>, method['intent'], method['name']>> | undefined;
193
201
  input?: globalThis.Request;
202
+ /** Payer identity verified by the method, when available. See {@link Validation.payer}. */
203
+ payer?: string | undefined;
194
204
  receipt: DeepReadonly<Receipt.Receipt>;
195
205
  /** Canonical payment request included in the challenge. */
196
206
  request: DeepReadonly<z.output<method['schema']['request']>>;