mppx 0.10.0 → 0.11.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.
@@ -0,0 +1,56 @@
1
+ import type * as Hex from 'ox/Hex';
2
+ import { type Address, type Client } from 'viem';
3
+ type Call = {
4
+ data?: Hex.Hex | undefined;
5
+ to?: Address | undefined;
6
+ value?: bigint | undefined;
7
+ };
8
+ type RouteCall = {
9
+ data: Hex.Hex;
10
+ to: Address;
11
+ };
12
+ type Route = {
13
+ calls: readonly [RouteCall, RouteCall];
14
+ settlementSender: Address;
15
+ transfers: readonly [{
16
+ amount: bigint;
17
+ memo: Hex.Hex;
18
+ recipient: Address;
19
+ }];
20
+ };
21
+ type Transfer = {
22
+ amount: bigint | string;
23
+ memo?: string | undefined;
24
+ recipient: Address;
25
+ };
26
+ /** Returns whether a first-party machine-token charge route is deployed on a chain. */
27
+ export declare function isSupported(chainId: number | undefined): boolean;
28
+ /** Returns whether a currency is the machine token for a supported chain. */
29
+ export declare function isMachineToken(parameters: {
30
+ chainId: number | undefined;
31
+ currency: Address;
32
+ }): boolean;
33
+ /** Resolves the canonical first-party settlement route for a compatible charge. */
34
+ export declare function getRoute(parameters: {
35
+ chainId: number | undefined;
36
+ currency: Address;
37
+ transfers: readonly Transfer[];
38
+ }): Route | undefined;
39
+ /** Builds and simulates the first-party settlement route. */
40
+ export declare function findRoute(client: Client, parameters: {
41
+ account: Address;
42
+ chainId: number;
43
+ currency: Address;
44
+ transfers: readonly Transfer[];
45
+ }): Promise<Route | undefined>;
46
+ /** Matches an exact first-party settlement route. */
47
+ export declare function matchRoute(parameters: {
48
+ calls: readonly Call[];
49
+ chainId: number | undefined;
50
+ currency: Address;
51
+ transfers: readonly Transfer[];
52
+ }): Route | undefined;
53
+ /** Returns the trusted sender that settles the configured charge route on a chain. */
54
+ export declare function getSettlementSender(chainId: number | undefined): Address | undefined;
55
+ export {};
56
+ //# sourceMappingURL=machine-token-charge.d.ts.map
@@ -0,0 +1,108 @@
1
+ import { decodeFunctionData, encodeFunctionData, isAddress, isAddressEqual, parseAbi, } from 'viem';
2
+ import { call, readContract } from 'viem/actions';
3
+ import { Abis, Actions } from 'viem/tempo';
4
+ import * as defaults from './defaults.js';
5
+ const machineTokenSwapperAbi = parseAbi([
6
+ 'function swapTo(address inputToken,uint256 amount,address targetToken,address recipient,bytes32 memo)',
7
+ ]);
8
+ function getDeployment(chainId) {
9
+ if (chainId === undefined)
10
+ return undefined;
11
+ return defaults.machineToken[chainId];
12
+ }
13
+ /** Returns whether a first-party machine-token charge route is deployed on a chain. */
14
+ export function isSupported(chainId) {
15
+ return !!getDeployment(chainId);
16
+ }
17
+ /** Returns whether a currency is the machine token for a supported chain. */
18
+ export function isMachineToken(parameters) {
19
+ const deployment = getDeployment(parameters.chainId);
20
+ return (!!deployment &&
21
+ isAddress(parameters.currency, { strict: false }) &&
22
+ isAddressEqual(parameters.currency, deployment.token));
23
+ }
24
+ /** Resolves the canonical first-party settlement route for a compatible charge. */
25
+ export function getRoute(parameters) {
26
+ const deployment = getDeployment(parameters.chainId);
27
+ const transfer = parameters.transfers.length === 1 ? parameters.transfers[0] : undefined;
28
+ if (!deployment || !transfer?.memo)
29
+ return undefined;
30
+ const amount = BigInt(transfer.amount);
31
+ const memo = transfer.memo;
32
+ return {
33
+ calls: [
34
+ {
35
+ data: encodeFunctionData({
36
+ abi: Abis.tip20,
37
+ functionName: 'approve',
38
+ args: [deployment.swap, amount],
39
+ }),
40
+ to: deployment.token,
41
+ },
42
+ {
43
+ data: encodeFunctionData({
44
+ abi: machineTokenSwapperAbi,
45
+ functionName: 'swapTo',
46
+ args: [deployment.token, amount, parameters.currency, transfer.recipient, memo],
47
+ }),
48
+ to: deployment.swap,
49
+ },
50
+ ],
51
+ settlementSender: deployment.swap,
52
+ transfers: [{ amount, memo, recipient: transfer.recipient }],
53
+ };
54
+ }
55
+ /** Builds and simulates the first-party settlement route. */
56
+ export async function findRoute(client, parameters) {
57
+ const route = getRoute(parameters);
58
+ if (!route)
59
+ return undefined;
60
+ try {
61
+ const balance = await readContract(client, Actions.token.getBalance.call(client, {
62
+ account: parameters.account,
63
+ token: route.calls[0].to,
64
+ }));
65
+ if (balance < route.transfers[0].amount)
66
+ return undefined;
67
+ await call(client, { account: parameters.account, calls: route.calls });
68
+ return route;
69
+ }
70
+ catch {
71
+ return undefined;
72
+ }
73
+ }
74
+ /** Matches an exact first-party settlement route. */
75
+ export function matchRoute(parameters) {
76
+ const transfer = parameters.transfers.length === 1 ? parameters.transfers[0] : undefined;
77
+ const swap = parameters.calls[1];
78
+ if (!transfer || parameters.calls.length !== 2 || !swap?.data)
79
+ return undefined;
80
+ try {
81
+ const decoded = decodeFunctionData({ abi: machineTokenSwapperAbi, data: swap.data });
82
+ const route = getRoute({
83
+ ...parameters,
84
+ transfers: [{ ...transfer, memo: transfer.memo ?? decoded.args[4] }],
85
+ });
86
+ if (!route)
87
+ return undefined;
88
+ if (parameters.calls.some((call, index) => {
89
+ const expected = route.calls[index];
90
+ return (!call.data ||
91
+ !call.to ||
92
+ !expected ||
93
+ (call.value ?? 0n) !== 0n ||
94
+ !isAddressEqual(call.to, expected.to) ||
95
+ call.data.toLowerCase() !== expected.data.toLowerCase());
96
+ }))
97
+ return undefined;
98
+ return route;
99
+ }
100
+ catch {
101
+ return undefined;
102
+ }
103
+ }
104
+ /** Returns the trusted sender that settles the configured charge route on a chain. */
105
+ export function getSettlementSender(chainId) {
106
+ return getDeployment(chainId)?.swap;
107
+ }
108
+ //# sourceMappingURL=machine-token-charge.js.map
@@ -45,6 +45,8 @@ export declare namespace charge {
45
45
  } | undefined;
46
46
  };
47
47
  type Parameters = {
48
+ /** Enables first-party machine-token funding through the canonical swapper. */
49
+ machineTokenEnabled?: boolean | undefined;
48
50
  /** Render payment page when Accept header is text/html (e.g. in browsers) */
49
51
  html?: boolean | Html.Config | undefined;
50
52
  /**
@@ -99,6 +101,7 @@ export declare namespace charge {
99
101
  * relay broadcasts pull credentials, while it recognizes a push
100
102
  * credential as already broadcast and returns its receipt without sending
101
103
  * it again.
104
+ *
102
105
  */
103
106
  relay?: RelayOptions | undefined;
104
107
  /**
@@ -15,6 +15,7 @@ import * as Charge_internal from '../internal/charge.js';
15
15
  import * as defaults from '../internal/defaults.js';
16
16
  import * as FeePayer from '../internal/fee-payer.js';
17
17
  import { resolveFeeToken } from '../internal/fee-token.js';
18
+ import * as MachineTokenCharge from '../internal/machine-token-charge.js';
18
19
  import * as Proof from '../internal/proof.js';
19
20
  import * as Selectors from '../internal/selectors.js';
20
21
  import * as Methods from '../Methods.js';
@@ -32,7 +33,7 @@ import * as SponsorBudget from './SponsorBudget.js';
32
33
  * ```
33
34
  */
34
35
  export function charge(parameters = {}) {
35
- const { amount, currency = defaults.resolveCurrency(parameters), decimals = defaults.decimals, description, externalId, feeToken: configuredFeeToken, feePayerPolicy, html, memo, relay, sponsorBudget, splits, supportedModes, validateSender, waitForConfirmation = true, } = parameters;
36
+ const { machineTokenEnabled, amount, currency = defaults.resolveCurrency(parameters), decimals = defaults.decimals, description, externalId, feeToken: configuredFeeToken, feePayerPolicy, html, relay, sponsorBudget, splits, supportedModes, validateSender, waitForConfirmation = true, } = parameters;
36
37
  const storeKeyPrefix = parameters.storeKeyPrefix ?? '';
37
38
  const rawStore = (parameters.store ?? Store.memory());
38
39
  const store = Store.from(rawStore, { keyPrefix: storeKeyPrefix });
@@ -83,36 +84,40 @@ export function charge(parameters = {}) {
83
84
  const supportedModes = methodDetails?.supportedModes;
84
85
  const currency = resolvedRequest.currency;
85
86
  const recipient = resolvedRequest.recipient;
86
- const memo = methodDetails?.memo;
87
+ const machineTokenEnabled = methodDetails?.machineTokenEnabled === true;
88
+ const settlementSender = machineTokenEnabled
89
+ ? MachineTokenCharge.getSettlementSender(chainId)
90
+ : undefined;
87
91
  const isZeroAmount = BigInt(amount) === 0n;
88
92
  Expires.assert(challenge.expires, challenge.id);
89
93
  if (isZeroAmount && payload.type !== 'proof')
90
94
  throw new MismatchError('Zero-amount challenges require a proof credential.', {});
91
95
  return {
92
96
  amount,
97
+ machineTokenEnabled,
93
98
  chainId,
94
99
  challenge,
95
100
  client: await getClient({ chainId }),
96
101
  currency,
97
102
  isZeroAmount,
98
- memo,
99
103
  methodDetails,
100
104
  payload,
101
105
  recipient,
102
106
  requestAllowsFeePayer: request.feePayer !== false,
103
107
  resolvedRequest,
108
+ settlementSenders: settlementSender ? [settlementSender] : [],
104
109
  supportedModes,
105
110
  };
106
111
  }
107
112
  async function validateHashCredential(credential, payload, context) {
108
- const { amount, chainId, challenge, client, currency, memo, methodDetails, recipient, supportedModes, } = context;
113
+ const { amount, chainId, challenge, client, currency, methodDetails, recipient, settlementSenders, supportedModes, } = context;
109
114
  if (supportedModes && !supportedModes.includes('push'))
110
115
  throw new MismatchError('Hash credentials are not supported for this challenge.', {});
111
116
  const source = parseHashCredentialSource({
112
117
  chainId: chainId ?? client.chain?.id,
113
118
  source: credential.source,
114
119
  });
115
- const transfers = getExpectedTransfers({ amount, memo, methodDetails, recipient });
120
+ const transfers = getExpectedTransfers({ amount, methodDetails, recipient });
116
121
  const receipt = await getTransactionReceipt(client, {
117
122
  hash: payload.hash,
118
123
  });
@@ -120,15 +125,15 @@ export function charge(parameters = {}) {
120
125
  const matchedLogs = await assertTransferLogs(receipt, {
121
126
  currency,
122
127
  sender,
128
+ settlementSenders,
123
129
  source,
124
130
  transfers,
125
131
  validateSender,
126
132
  });
127
- if (!memo)
128
- assertChallengeBoundMemo(matchedLogs, {
129
- challengeId: challenge.id,
130
- realm: challenge.realm,
131
- });
133
+ assertChallengeBoundMemo(matchedLogs, {
134
+ challengeId: challenge.id,
135
+ realm: challenge.realm,
136
+ });
132
137
  return { receipt: toReceipt(receipt), sender, transfers };
133
138
  }
134
139
  async function validateProofCredential(credential, payload, context) {
@@ -169,7 +174,7 @@ export function charge(parameters = {}) {
169
174
  return { sender: source.address };
170
175
  }
171
176
  async function validateTransactionCredential(credential, payload, request, context) {
172
- const { amount, chainId, challenge, client, currency, memo, methodDetails, recipient, requestAllowsFeePayer, supportedModes, } = context;
177
+ const { machineTokenEnabled, amount, chainId, challenge, client, currency, methodDetails, recipient, requestAllowsFeePayer, supportedModes, } = context;
173
178
  if (supportedModes && !supportedModes.includes('pull'))
174
179
  throw new MismatchError('Transaction credentials are not supported for this challenge.', {});
175
180
  const serializedTransaction = payload.signature;
@@ -181,25 +186,40 @@ export function charge(parameters = {}) {
181
186
  const isFeePayerTx = methodDetails?.feePayer === true &&
182
187
  requestAllowsFeePayer &&
183
188
  !!(Account.is(request.feePayer) ? request.feePayer : feePayer || remoteFeePayer);
184
- const transfers = getExpectedTransfers({ amount, memo, methodDetails, recipient });
185
- const matchedCalls = assertTransferCalls(transaction.calls ?? [], {
186
- currency,
187
- exactCount: isFeePayerTx,
188
- transfers,
189
- });
190
- if (!memo)
191
- assertChallengeBoundCallMemo(matchedCalls, {
192
- challengeId: challenge.id,
193
- realm: challenge.realm,
189
+ const transfers = getExpectedTransfers({ amount, methodDetails, recipient });
190
+ const machineTokenRoute = machineTokenEnabled
191
+ ? MachineTokenCharge.matchRoute({
192
+ calls: transaction.calls ?? [],
193
+ chainId: chainId ?? client.chain?.id,
194
+ currency,
195
+ transfers,
196
+ })
197
+ : undefined;
198
+ const matchedCalls = machineTokenRoute?.transfers ??
199
+ assertTransferCalls(transaction.calls ?? [], {
200
+ currency,
201
+ exactCount: isFeePayerTx,
202
+ transfers,
194
203
  });
204
+ assertChallengeBoundCallMemo(matchedCalls, {
205
+ challengeId: challenge.id,
206
+ realm: challenge.realm,
207
+ });
195
208
  if (isFeePayerTx) {
196
- FeePayer.validateCalls(transaction.calls, { amount, currency, recipient }, { currency, expectedTransfers: transfers });
209
+ if (!machineTokenRoute)
210
+ FeePayer.validateCalls(transaction.calls, { amount, currency, recipient }, { currency, expectedTransfers: transfers });
197
211
  FeePayer.assertAllowedFeeToken(transaction, FeePayer.defaultAllowedFeeTokens(chainId));
198
212
  }
199
213
  else {
200
214
  await viem_call(client, FeePayer.simulationTransaction(transaction, { feePayer: false }));
201
215
  }
202
- return { isFeePayerTx, serializedTransaction, transaction, transfers };
216
+ return {
217
+ isFeePayerTx,
218
+ serializedTransaction,
219
+ settlementSenders: machineTokenRoute ? [machineTokenRoute.settlementSender] : [],
220
+ transaction,
221
+ transfers,
222
+ };
203
223
  }
204
224
  async function validateCredential(credential, request, context) {
205
225
  switch (context.payload.type) {
@@ -217,7 +237,7 @@ export function charge(parameters = {}) {
217
237
  return { details: { mode: 'proof', sender }, type: 'proof' };
218
238
  }
219
239
  case 'transaction': {
220
- const { isFeePayerTx, serializedTransaction, transaction, transfers } = await validateTransactionCredential(credential, context.payload, request, context);
240
+ const { isFeePayerTx, serializedTransaction, settlementSenders, transaction, transfers } = await validateTransactionCredential(credential, context.payload, request, context);
221
241
  return {
222
242
  details: {
223
243
  mode: 'pull',
@@ -227,6 +247,7 @@ export function charge(parameters = {}) {
227
247
  },
228
248
  isFeePayerTx,
229
249
  serializedTransaction,
250
+ settlementSenders,
230
251
  transaction,
231
252
  transfers,
232
253
  type: 'transaction',
@@ -238,12 +259,12 @@ export function charge(parameters = {}) {
238
259
  canOffer: parameters.canOffer,
239
260
  onPaymentSuccess: parameters.onPaymentSuccess,
240
261
  defaults: {
262
+ machineTokenEnabled,
241
263
  amount,
242
264
  currency,
243
265
  decimals,
244
266
  description,
245
267
  externalId,
246
- memo,
247
268
  recipient,
248
269
  splits,
249
270
  supportedModes,
@@ -298,6 +319,13 @@ export function charge(parameters = {}) {
298
319
  })();
299
320
  if (client.chain?.id !== chainId)
300
321
  throw new Error(`Client not configured with chainId ${chainId}.`);
322
+ if (MachineTokenCharge.isMachineToken({
323
+ chainId,
324
+ currency: request.currency,
325
+ }))
326
+ throw new Error('MACH cannot be advertised as a charge currency. Advertise the settlement currency with `machineTokenEnabled: true`.');
327
+ if (request.machineTokenEnabled && !MachineTokenCharge.isSupported(chainId))
328
+ throw new Error(`Machine tokens are not supported on chainId ${chainId}.`);
301
329
  const resolvedFeePayer = (() => {
302
330
  if (request.feePayer === false)
303
331
  return credential ? false : undefined;
@@ -308,9 +336,9 @@ export function charge(parameters = {}) {
308
336
  })();
309
337
  return {
310
338
  ...request,
339
+ machineTokenEnabled: request.machineTokenEnabled || undefined,
311
340
  chainId,
312
341
  feePayer: resolvedFeePayer,
313
- memo: request.memo || undefined,
314
342
  };
315
343
  },
316
344
  async validate({ credential, request }) {
@@ -328,7 +356,7 @@ export function charge(parameters = {}) {
328
356
  },
329
357
  async broadcast({ credential, request }) {
330
358
  const context = await resolveCredentialContext({ credential, request });
331
- const { amount, chainId, challenge, client, currency, memo, methodDetails, recipient, requestAllowsFeePayer, } = context;
359
+ const { amount, chainId, challenge, client, currency, methodDetails, recipient, requestAllowsFeePayer, } = context;
332
360
  const validated = await validateCredential(credential, request, context);
333
361
  const feePayerAccount = methodDetails?.feePayer === true && requestAllowsFeePayer
334
362
  ? Account.is(request.feePayer)
@@ -362,7 +390,7 @@ export function charge(parameters = {}) {
362
390
  };
363
391
  }
364
392
  case 'transaction': {
365
- const { isFeePayerTx, serializedTransaction, transaction, transfers } = validated;
393
+ const { isFeePayerTx, serializedTransaction, settlementSenders, transaction, transfers } = validated;
366
394
  // Pre-broadcast dedup: catch exact byte-for-byte replays early.
367
395
  const hash = keccak256(serializedTransaction);
368
396
  if (!(await tryClaimHash(store, hash, replayExpires))) {
@@ -495,13 +523,13 @@ export function charge(parameters = {}) {
495
523
  const matchedLogs = await assertTransferLogs(receipt, {
496
524
  currency,
497
525
  sender: transaction.from,
526
+ settlementSenders,
498
527
  transfers,
499
528
  });
500
- if (!memo)
501
- assertChallengeBoundMemo(matchedLogs, {
502
- challengeId: challenge.id,
503
- realm: challenge.realm,
504
- });
529
+ assertChallengeBoundMemo(matchedLogs, {
530
+ challengeId: challenge.id,
531
+ realm: challenge.realm,
532
+ });
505
533
  if (receipt.transactionHash.toLowerCase() !== finalHash.toLowerCase())
506
534
  throw new VerificationFailedError({
507
535
  reason: 'Broadcast transaction hash does not match the signed transaction',
@@ -550,16 +578,16 @@ function chargeBinding(request) {
550
578
  // Exhaustively destructure so new charge request fields require an explicit binding decision.
551
579
  const { amount, currency, description, externalId, methodDetails, recipient, ...requestRest } = request;
552
580
  requestRest;
553
- const { chainId, feePayer, memo, splits, supportedModes, ...methodDetailsRest } = methodDetails ?? {};
581
+ const { chainId, feePayer, machineTokenEnabled, splits, supportedModes, ...methodDetailsRest } = methodDetails ?? {};
554
582
  methodDetailsRest;
555
583
  void feePayer;
556
584
  return {
585
+ machineTokenEnabled,
557
586
  amount,
558
587
  chainId,
559
588
  currency,
560
589
  description,
561
590
  externalId,
562
- memo,
563
591
  recipient,
564
592
  splits,
565
593
  supportedModes,
@@ -569,7 +597,6 @@ function getExpectedTransfers(parameters) {
569
597
  return Charge_internal.getTransfers({
570
598
  amount: parameters.amount,
571
599
  methodDetails: {
572
- memo: parameters.memo,
573
600
  splits: parameters.methodDetails?.splits,
574
601
  },
575
602
  recipient: parameters.recipient,
@@ -695,7 +722,9 @@ async function assertTransferLogs(receipt, parameters) {
695
722
  if (!(await isValidTransferSender({
696
723
  expectedSender: parameters.sender,
697
724
  sender: log.args.from,
725
+ settlementSenders: parameters.settlementSenders,
698
726
  source: parameters.source,
727
+ transactionSender: receipt.from,
699
728
  validateSender: parameters.validateSender,
700
729
  })))
701
730
  continue;
@@ -770,6 +799,9 @@ function isSameTransferLog(a, b) {
770
799
  async function isValidTransferSender(parameters) {
771
800
  if (TempoAddress.isEqual(parameters.sender, parameters.expectedSender))
772
801
  return true;
802
+ if (TempoAddress.isEqual(parameters.transactionSender, parameters.expectedSender) &&
803
+ parameters.settlementSenders?.some((sender) => TempoAddress.isEqual(parameters.sender, sender)))
804
+ return true;
773
805
  if (!parameters.validateSender)
774
806
  return false;
775
807
  return parameters.validateSender({
@@ -37,6 +37,7 @@ export declare function tempo<const parameters extends tempo.Parameters>(paramet
37
37
  }, import("zod/v4/core").$strip>], "type">;
38
38
  };
39
39
  request: import("zod/mini").ZodMiniPipe<import("zod/mini").ZodMiniObject<{
40
+ machineTokenEnabled: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniBoolean<boolean>>;
40
41
  amount: import("zod/mini").ZodMiniString<string>;
41
42
  chainId: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniNumber<number>>;
42
43
  currency: import("zod/mini").ZodMiniString<string>;
@@ -44,7 +45,7 @@ export declare function tempo<const parameters extends tempo.Parameters>(paramet
44
45
  description: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
45
46
  externalId: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
46
47
  feePayer: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniPipe<import("zod/mini").ZodMiniUnion<readonly [import("zod/mini").ZodMiniBoolean<boolean>, import("zod/mini").ZodMiniCustom<import("viem").Account, import("viem").Account>]>, import("zod/mini").ZodMiniTransform<boolean, boolean | import("viem").Account>>>;
47
- memo: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
48
+ memo: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniNever>;
48
49
  recipient: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
49
50
  splits: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniArray<import("zod/mini").ZodMiniObject<{
50
51
  amount: import("zod/mini").ZodMiniString<string>;
@@ -62,9 +63,9 @@ export declare function tempo<const parameters extends tempo.Parameters>(paramet
62
63
  recipient?: string | undefined;
63
64
  amount: string;
64
65
  methodDetails?: {
66
+ machineTokenEnabled?: boolean | undefined;
65
67
  chainId?: number | undefined;
66
68
  feePayer?: boolean | undefined;
67
- memo?: string | undefined;
68
69
  splits?: {
69
70
  memo?: string | undefined;
70
71
  recipient: `0x${string}`;
@@ -73,6 +74,7 @@ export declare function tempo<const parameters extends tempo.Parameters>(paramet
73
74
  supportedModes?: ("pull" | "push")[] | undefined;
74
75
  } | undefined;
75
76
  }, {
77
+ machineTokenEnabled?: boolean | undefined;
76
78
  amount: string;
77
79
  chainId?: number | undefined;
78
80
  currency: string;
@@ -80,7 +82,7 @@ export declare function tempo<const parameters extends tempo.Parameters>(paramet
80
82
  description?: string | undefined;
81
83
  externalId?: string | undefined;
82
84
  feePayer?: boolean | undefined;
83
- memo?: string | undefined;
85
+ memo?: undefined;
84
86
  recipient?: string | undefined;
85
87
  splits?: {
86
88
  amount: string;
@@ -181,7 +183,10 @@ export declare function tempo<const parameters extends tempo.Parameters>(paramet
181
183
  };
182
184
  }, session_.DeriveDefaults<parameters>, parameters["sse"] extends false | undefined ? undefined : import("./internal/transport.js").Sse, session_.Extensions, undefined>];
183
185
  export declare namespace tempo {
184
- type Parameters = charge_.Parameters & session_.Parameters;
186
+ type Parameters = Omit<charge_.Parameters, 'machineTokenEnabled'> & session_.Parameters & {
187
+ /** Enables MACH funding for compatible Tempo methods. Currently applies to `charge`. */
188
+ machineTokenEnabled?: boolean | undefined;
189
+ };
185
190
  /** Tempo API relay configuration for server-side charges. */
186
191
  type RelayOptions = charge_.RelayOptions;
187
192
  /** Stable failure codes returned by Tempo API's MPP relay. */
@@ -14,8 +14,11 @@ function createChargeMethod(parameters) {
14
14
  return tempo.charge(parameters);
15
15
  }
16
16
  function createSessionMethod(parameters) {
17
- // See `createChargeMethod()`: session receives the same shared parameter bag.
18
- return sessionServer(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 ?? {};
21
+ return sessionServer(sessionParameters);
19
22
  }
20
23
  /**
21
24
  * Creates the common Tempo `charge` and `session` methods from shared parameters.