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.
@@ -24,18 +24,23 @@ export type PreparedPayment<methods extends readonly Method.AnyClient[] = readon
24
24
  /** Attaches a credential using the protocol that produced the selected challenge. */
25
25
  setCredential: (request: Transport.RequestOf<transport>, credential: string) => Transport.RequestOf<transport>;
26
26
  }>;
27
- /** A payment challenge prepared together with the exact HTTP request that produced it. */
28
- export type PreparedRequest<methods extends readonly Method.AnyClient[]> = Readonly<PreparedPayment<methods, Transport.Transport<RequestInit, Response>> & {
29
- /** Exact request that returned the selected payment challenge. */
27
+ /** An HTTP request prepared together with its response and optional payment. */
28
+ export type PreparedRequest<methods extends readonly Method.AnyClient[], requirePayment extends boolean = false> = Readonly<{
29
+ /** Exact request that produced {@link response}. */
30
30
  request: Request;
31
- /** Payment-required response returned for {@link request}. */
31
+ /** Response returned for {@link request}. */
32
32
  response: Response;
33
- /** Redirects followed before receiving the payment challenge. */
33
+ /** Redirects followed before receiving {@link response}. */
34
34
  redirects: readonly PreparedRequest.Redirect[];
35
- /** Creates and sends a credential to the prepared request without following redirects. */
36
- pay: (context?: AnyContextFor<methods> | undefined) => Promise<Response>;
35
+ /** Selected payment when the response requires payment. */
36
+ payment: requirePayment extends true ? PreparedRequest.Payment<methods> : PreparedRequest.Payment<methods> | undefined;
37
37
  }>;
38
38
  export declare namespace PreparedRequest {
39
+ /** A request-bound payment that can be inspected or paid. */
40
+ type Payment<methods extends readonly Method.AnyClient[]> = Readonly<PreparedPayment<methods, Transport.Transport<RequestInit, Response>> & {
41
+ /** Creates and sends a credential to the prepared request without following redirects. */
42
+ pay: (context?: AnyContextFor<methods> | undefined) => Promise<Response>;
43
+ }>;
39
44
  /** A redirect followed while discovering a payment challenge. */
40
45
  type Redirect = Readonly<{
41
46
  from: string;
@@ -70,11 +75,17 @@ export type Mppx<methods extends Methods = Methods, transport extends Transport.
70
75
  */
71
76
  preparePayment: (response: Transport.ResponseOf<transport>, options?: preparePayment.Options<FlattenMethods<methods>, transport> | undefined) => Promise<PreparedPayment<FlattenMethods<methods>, transport>>;
72
77
  /**
73
- * Follows safe pre-payment redirects and prepares the challenge with the exact request that
74
- * produced it. Credential-bearing requests never follow redirects. Requires a runtime that
75
- * exposes manual redirect responses; browsers return opaque redirects and are not supported.
78
+ * Follows safe pre-payment redirects and returns the response with its exact request. When the
79
+ * response requires payment, prepares its selected challenge without creating a credential.
80
+ * Credential-bearing requests never follow redirects. Requires a runtime that exposes manual
81
+ * redirect responses; browsers return opaque redirects and are not supported.
76
82
  */
77
- prepareRequest: transport extends Transport.Transport<RequestInit, Response> ? (input: RequestInfo | URL, init?: RequestInit | undefined, options?: prepareRequest.Options<FlattenMethods<methods>> | undefined) => Promise<PreparedRequest<FlattenMethods<methods>>> : never;
83
+ prepareRequest: transport extends Transport.Transport<RequestInit, Response> ? {
84
+ <const requirePayment extends boolean>(input: RequestInfo | URL, init: RequestInit | undefined, options: prepareRequest.Options<FlattenMethods<methods>, requirePayment> & {
85
+ requirePayment: requirePayment;
86
+ }): Promise<PreparedRequest<FlattenMethods<methods>, requirePayment>>;
87
+ (input: RequestInfo | URL, init?: RequestInit | undefined, options?: prepareRequest.Options<FlattenMethods<methods>> | undefined): Promise<PreparedRequest<FlattenMethods<methods>>>;
88
+ } : never;
78
89
  /** Creates a credential from a payment-required response by routing to the correct method. */
79
90
  createCredential: (response: Transport.ResponseOf<transport>, context?: AnyContextFor<FlattenMethods<methods>> | undefined, options?: createCredential.Options<FlattenMethods<methods>, transport> | undefined) => Promise<string>;
80
91
  /** Register a client event handler by canonical event name. */
@@ -116,9 +127,11 @@ export declare namespace preparePayment {
116
127
  }
117
128
  export declare namespace prepareRequest {
118
129
  /** Options for preparing a request-bound payment. */
119
- type Options<methods extends readonly Method.AnyClient[] = readonly Method.AnyClient[]> = Omit<preparePayment.Options<methods, Transport.Transport<RequestInit, Response>>, 'request'> & {
130
+ type Options<methods extends readonly Method.AnyClient[] = readonly Method.AnyClient[], requirePayment extends boolean = false> = Omit<preparePayment.Options<methods, Transport.Transport<RequestInit, Response>>, 'request'> & {
120
131
  /** Maximum redirects followed before rejecting the request. @default 20 */
121
132
  maxRedirects?: number | undefined;
133
+ /** Throw when the response does not require payment. @default false */
134
+ requirePayment?: requirePayment | undefined;
122
135
  };
123
136
  }
124
137
  export declare namespace createCredential {
@@ -148,7 +148,7 @@ export function create(config) {
148
148
  }
149
149
  }
150
150
  async function prepareRequest(input, init, options) {
151
- const { maxRedirects = 20, ...paymentOptions } = options ?? {};
151
+ const { maxRedirects = 20, requirePayment = false, ...paymentOptions } = options ?? {};
152
152
  const preparedHttp = await prepareHttpRequest({
153
153
  acceptPayment: acceptPayment.header,
154
154
  acceptPaymentPolicy,
@@ -159,8 +159,16 @@ export function create(config) {
159
159
  signer: attestationSigner,
160
160
  });
161
161
  const requestInit = requestToInit(preparedHttp.replayRequest, preparedHttp.body);
162
- if (!(await transport.isPaymentRequired(preparedHttp.response, requestInit)))
163
- throw new Error('Response does not require payment.');
162
+ if (!(await transport.isPaymentRequired(preparedHttp.response, requestInit))) {
163
+ if (requirePayment)
164
+ throw new Error('Response does not require payment.');
165
+ return Object.freeze({
166
+ payment: undefined,
167
+ request: preparedHttp.request,
168
+ response: preparedHttp.response,
169
+ redirects: preparedHttp.redirects,
170
+ });
171
+ }
164
172
  const payment = (await preparePayment(preparedHttp.response, {
165
173
  ...paymentOptions,
166
174
  request: requestInit,
@@ -176,12 +184,9 @@ export function create(config) {
176
184
  });
177
185
  return payment.createCredential(context);
178
186
  });
179
- return Object.freeze({
187
+ const preparedPayment = Object.freeze({
180
188
  ...payment,
181
189
  createCredential: createRequestCredential,
182
- request: preparedHttp.request,
183
- response: preparedHttp.response,
184
- redirects: preparedHttp.redirects,
185
190
  async pay(context) {
186
191
  const credential = await createRequestCredential(context);
187
192
  const paidInit = payment.setCredential(requestToInit(preparedHttp.replayRequest, preparedHttp.body), credential);
@@ -191,6 +196,12 @@ export function create(config) {
191
196
  });
192
197
  },
193
198
  });
199
+ return Object.freeze({
200
+ payment: preparedPayment,
201
+ request: preparedHttp.request,
202
+ response: preparedHttp.response,
203
+ redirects: preparedHttp.redirects,
204
+ });
194
205
  }
195
206
  return {
196
207
  fetch,
@@ -17,8 +17,6 @@ export function x402() {
17
17
  if (!header)
18
18
  return [];
19
19
  const paymentRequired = x402_Header.decodePaymentRequiredEnvelope(header);
20
- if (response.url && paymentRequired.resource.url !== response.url)
21
- throw new Error('x402 payment-required resource does not match response URL.');
22
20
  return paymentRequired.accepts.flatMap((rawAccepted, index) => {
23
21
  const parsed = x402_Types.PaymentRequirementsSchema.safeParse(rawAccepted);
24
22
  if (!parsed.success)
@@ -1,5 +1,5 @@
1
1
  /** Current mppx package version. */
2
- export declare const version = "0.10.0";
2
+ export declare const version = "0.11.0";
3
3
  /** Canonical SDK identifier for this mppx release. */
4
- export declare const sdkIdentifier = "mppx/0.10.0";
4
+ export declare const sdkIdentifier = "mppx/0.11.0";
5
5
  //# sourceMappingURL=version.d.ts.map
@@ -1,6 +1,6 @@
1
1
  // Generated by scripts/sync-version.ts.
2
2
  /** Current mppx package version. */
3
- export const version = '0.10.0';
3
+ export const version = '0.11.0';
4
4
  /** Canonical SDK identifier for this mppx release. */
5
5
  export const sdkIdentifier = `mppx/${version}`;
6
6
  //# sourceMappingURL=version.js.map
@@ -121,13 +121,21 @@ export function stripe(parameters) {
121
121
  }));
122
122
  }
123
123
  function makeTempoSession(params) {
124
- const { recipient, ...rest } = params;
124
+ const { recipient, onSessionSettlement, ...rest } = params;
125
125
  return tempoSession({
126
126
  currency: tempoCurrency,
127
127
  recipient,
128
128
  ...(!livemode && { testnet: true }),
129
129
  ...(hostedTempoFeePayer && { feePayer: hostedTempoFeePayer }),
130
130
  ...rest,
131
+ async onSessionSettlement(context) {
132
+ await tempoPaymentHandler({
133
+ intent: 'session',
134
+ receipt: { reference: context.txHash },
135
+ request: { amount: context.delta.toString() },
136
+ });
137
+ await onSessionSettlement?.(context);
138
+ },
131
139
  });
132
140
  }
133
141
  function makeBaseCharge(params) {
@@ -283,7 +291,7 @@ function customRails(additional) {
283
291
  }
284
292
  function createPaymentSuccessHandler(client, network, connect, metadata) {
285
293
  return (params) => {
286
- const { challenge, receipt, request, requestInput } = params;
294
+ const { challenge, intent, receipt, request, requestInput } = params;
287
295
  if (receipt?.reference && request?.amount) {
288
296
  const paymentIntentOptionsInput = requestInput?.paymentIntentOptions;
289
297
  const paymentIntentOptions = typeof paymentIntentOptionsInput === 'function' ? undefined : paymentIntentOptionsInput;
@@ -300,7 +308,7 @@ function createPaymentSuccessHandler(client, network, connect, metadata) {
300
308
  reference: receipt.reference,
301
309
  amount: String(request.amount),
302
310
  ...(connect && { connect }),
303
- analyticsMetadata: buildAnalytics({ challenge }),
311
+ analyticsMetadata: buildAnalytics({ challenge, intent }),
304
312
  ...(Object.keys(resolvedPaymentIntentOptions).length > 0 && {
305
313
  paymentIntentOptions: resolvedPaymentIntentOptions,
306
314
  }),
@@ -2,5 +2,6 @@ import type * as Challenge from '../../../Challenge.js';
2
2
  /** Builds Stripe metadata used to identify and analyze MPP payments. */
3
3
  export declare function buildAnalytics(parameters: {
4
4
  challenge?: Pick<Challenge.Challenge, 'id' | 'intent'> | undefined;
5
+ intent?: string | undefined;
5
6
  }): Record<string, string>;
6
7
  //# sourceMappingURL=analytics.d.ts.map
@@ -2,13 +2,13 @@ import { sdkIdentifier } from '../../../internal/version.js';
2
2
  import { machinePaymentMetadata } from '../../internal/constants.js';
3
3
  /** Builds Stripe metadata used to identify and analyze MPP payments. */
4
4
  export function buildAnalytics(parameters) {
5
- const { challenge } = parameters;
5
+ const { challenge, intent = challenge?.intent } = parameters;
6
6
  const metadata = {
7
7
  ...machinePaymentMetadata,
8
8
  mpp_sdk: sdkIdentifier,
9
+ ...(intent && { mpp_intent: intent }),
9
10
  ...(challenge && {
10
11
  mpp_challenge_id: challenge.id,
11
- mpp_intent: challenge.intent,
12
12
  }),
13
13
  };
14
14
  return Object.fromEntries(Object.entries(metadata).map(([key, value]) => [key, [...value].slice(0, 500).join('')]));
@@ -13,9 +13,9 @@ export function recordCryptoPayment(client, parameters) {
13
13
  const { network, reference, amount, connect, analyticsMetadata, paymentIntentOptions } = parameters;
14
14
  const { customer, hooks, metadata, receipt_email } = paymentIntentOptions ?? {};
15
15
  const { stripeNetworkName, tokenDecimals } = NETWORK_CONFIG[network];
16
- const amountCents = Math.round(Number(amount) / 10 ** (tokenDecimals - 2));
16
+ const amountCents = Number(BigInt(amount) / 10n ** BigInt(tokenDecimals - 2));
17
17
  if (amountCents < 1) {
18
- console.warn(`[stripe] skipping PI recording: ${amount} raw units on ${network} rounds to ${amountCents} cents (below Stripe minimum)`);
18
+ console.warn(`[stripe] skipping PI recording: ${amount} raw units on ${network} floors to ${amountCents} cents (below Stripe minimum)`);
19
19
  return Promise.resolve();
20
20
  }
21
21
  const requiredParams = {
@@ -35,6 +35,7 @@ export declare const charge: {
35
35
  }, z.core.$strip>], "type">;
36
36
  };
37
37
  request: z.ZodMiniPipe<z.ZodMiniObject<{
38
+ machineTokenEnabled: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
38
39
  amount: z.ZodMiniString<string>;
39
40
  chainId: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
40
41
  currency: z.ZodMiniString<string>;
@@ -42,7 +43,7 @@ export declare const charge: {
42
43
  description: z.ZodMiniOptional<z.ZodMiniString<string>>;
43
44
  externalId: z.ZodMiniOptional<z.ZodMiniString<string>>;
44
45
  feePayer: z.ZodMiniOptional<z.ZodMiniPipe<z.ZodMiniUnion<readonly [z.ZodMiniBoolean<boolean>, z.ZodMiniCustom<Account, Account>]>, z.ZodMiniTransform<boolean, boolean | Account>>>;
45
- memo: z.ZodMiniOptional<z.ZodMiniString<string>>;
46
+ memo: z.ZodMiniOptional<z.ZodMiniNever>;
46
47
  recipient: z.ZodMiniOptional<z.ZodMiniString<string>>;
47
48
  splits: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniObject<{
48
49
  amount: z.ZodMiniString<string>;
@@ -60,9 +61,9 @@ export declare const charge: {
60
61
  recipient?: string | undefined;
61
62
  amount: string;
62
63
  methodDetails?: {
64
+ machineTokenEnabled?: boolean | undefined;
63
65
  chainId?: number | undefined;
64
66
  feePayer?: boolean | undefined;
65
- memo?: string | undefined;
66
67
  splits?: {
67
68
  memo?: string | undefined;
68
69
  recipient: `0x${string}`;
@@ -71,6 +72,7 @@ export declare const charge: {
71
72
  supportedModes?: ("pull" | "push")[] | undefined;
72
73
  } | undefined;
73
74
  }, {
75
+ machineTokenEnabled?: boolean | undefined;
74
76
  amount: string;
75
77
  chainId?: number | undefined;
76
78
  currency: string;
@@ -78,7 +80,7 @@ export declare const charge: {
78
80
  description?: string | undefined;
79
81
  externalId?: string | undefined;
80
82
  feePayer?: boolean | undefined;
81
- memo?: string | undefined;
83
+ memo?: undefined;
82
84
  recipient?: string | undefined;
83
85
  splits?: {
84
86
  amount: string;
@@ -82,6 +82,7 @@ export const charge = Method.from({
82
82
  },
83
83
  request: z.pipe(z
84
84
  .object({
85
+ machineTokenEnabled: z.optional(z.boolean()),
85
86
  amount: z.amount(),
86
87
  chainId: z.optional(z.number()),
87
88
  currency: z.string(),
@@ -89,7 +90,7 @@ export const charge = Method.from({
89
90
  description: z.optional(z.string()),
90
91
  externalId: z.optional(z.string()),
91
92
  feePayer: z.optional(z.pipe(z.union([z.boolean(), z.custom()]), z.transform((v) => (typeof v === 'object' ? true : v)))),
92
- memo: z.optional(z.hash()),
93
+ memo: z.optional(z.never()),
93
94
  recipient: z.optional(z.string()),
94
95
  splits: z.optional(z.array(split).check(z.minLength(1), z.maxLength(10))),
95
96
  supportedModes: z.optional(z.array(z.enum(chargeModes)).check(z.minLength(1))),
@@ -101,19 +102,19 @@ export const charge = Method.from({
101
102
  const splitTotal = splits.reduce((sum, split) => sum + parseUnits(split.amount, decimals), 0n);
102
103
  return (splits.every((split) => parseUnits(split.amount, decimals) > 0n) &&
103
104
  splitTotal < totalAmount);
104
- }, 'Invalid splits')), z.transform(({ amount, chainId, decimals, feePayer, memo, splits, supportedModes, ...rest }) => ({
105
+ }, 'Invalid splits')), z.transform(({ machineTokenEnabled, amount, chainId, decimals, feePayer, memo: _memo, splits, supportedModes, ...rest }) => ({
105
106
  ...rest,
106
107
  amount: parseUnits(amount, decimals).toString(),
107
- ...(chainId !== undefined ||
108
+ ...(machineTokenEnabled !== undefined ||
109
+ chainId !== undefined ||
108
110
  feePayer !== undefined ||
109
- memo !== undefined ||
110
111
  splits !== undefined ||
111
112
  supportedModes !== undefined
112
113
  ? {
113
114
  methodDetails: {
115
+ ...(machineTokenEnabled !== undefined && { machineTokenEnabled }),
114
116
  ...(chainId !== undefined && { chainId }),
115
117
  ...(feePayer !== undefined && { feePayer }),
116
- ...(memo !== undefined && { memo }),
117
118
  ...(splits !== undefined && {
118
119
  splits: splits.map((split) => ({
119
120
  ...split,
@@ -1,4 +1,4 @@
1
- import { type Address } from 'viem';
1
+ import type { Address } from 'viem';
2
2
  import * as Method from '../../Method.js';
3
3
  import * as Account from '../../viem/Account.js';
4
4
  import * as Client from '../../viem/Client.js';
@@ -42,6 +42,7 @@ export declare function charge(parameters?: charge.Parameters): Method.Client<{
42
42
  }, z.core.$strip>], "type">;
43
43
  };
44
44
  request: z.ZodMiniPipe<z.ZodMiniObject<{
45
+ machineTokenEnabled: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
45
46
  amount: z.ZodMiniString<string>;
46
47
  chainId: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
47
48
  currency: z.ZodMiniString<string>;
@@ -49,7 +50,7 @@ export declare function charge(parameters?: charge.Parameters): Method.Client<{
49
50
  description: z.ZodMiniOptional<z.ZodMiniString<string>>;
50
51
  externalId: z.ZodMiniOptional<z.ZodMiniString<string>>;
51
52
  feePayer: z.ZodMiniOptional<z.ZodMiniPipe<z.ZodMiniUnion<readonly [z.ZodMiniBoolean<boolean>, z.ZodMiniCustom<import("viem").Account, import("viem").Account>]>, z.ZodMiniTransform<boolean, boolean | import("viem").Account>>>;
52
- memo: z.ZodMiniOptional<z.ZodMiniString<string>>;
53
+ memo: z.ZodMiniOptional<z.ZodMiniNever>;
53
54
  recipient: z.ZodMiniOptional<z.ZodMiniString<string>>;
54
55
  splits: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniObject<{
55
56
  amount: z.ZodMiniString<string>;
@@ -67,9 +68,9 @@ export declare function charge(parameters?: charge.Parameters): Method.Client<{
67
68
  recipient?: string | undefined;
68
69
  amount: string;
69
70
  methodDetails?: {
71
+ machineTokenEnabled?: boolean | undefined;
70
72
  chainId?: number | undefined;
71
73
  feePayer?: boolean | undefined;
72
- memo?: string | undefined;
73
74
  splits?: {
74
75
  memo?: string | undefined;
75
76
  recipient: `0x${string}`;
@@ -78,6 +79,7 @@ export declare function charge(parameters?: charge.Parameters): Method.Client<{
78
79
  supportedModes?: ("pull" | "push")[] | undefined;
79
80
  } | undefined;
80
81
  }, {
82
+ machineTokenEnabled?: boolean | undefined;
81
83
  amount: string;
82
84
  chainId?: number | undefined;
83
85
  currency: string;
@@ -85,7 +87,7 @@ export declare function charge(parameters?: charge.Parameters): Method.Client<{
85
87
  description?: string | undefined;
86
88
  externalId?: string | undefined;
87
89
  feePayer?: boolean | undefined;
88
- memo?: string | undefined;
90
+ memo?: undefined;
89
91
  recipient?: string | undefined;
90
92
  splits?: {
91
93
  amount: string;
@@ -1,4 +1,3 @@
1
- import { isAddressEqual } from 'viem';
2
1
  import { prepareTransactionRequest, sendCallsSync, sendTransactionSync, signTypedData, signTransaction, } from 'viem/actions';
3
2
  import { Actions } from 'viem/tempo';
4
3
  import { tempo as tempo_chain } from 'viem/tempo/chains';
@@ -12,9 +11,9 @@ import * as AutoSwap from '../internal/auto-swap.js';
12
11
  import * as Charge_internal from '../internal/charge.js';
13
12
  import * as defaults from '../internal/defaults.js';
14
13
  import { defaultFeeTokens, resolveFeeToken } from '../internal/fee-token.js';
14
+ import * as MachineTokenCharge from '../internal/machine-token-charge.js';
15
15
  import * as Proof from '../internal/proof.js';
16
16
  import * as Methods from '../Methods.js';
17
- import { mach } from '../Tokens.js';
18
17
  const chargeContextSchema = z.object({
19
18
  account: z.optional(z.custom()),
20
19
  autoSwap: z.optional(z.custom()),
@@ -98,9 +97,12 @@ export function charge(parameters = {}) {
98
97
  });
99
98
  }
100
99
  const currency = request.currency;
101
- const memo = methodDetails?.memo
102
- ? methodDetails.memo
103
- : Attribution.encode({ challengeId: challenge.id, clientId, serverId: challenge.realm });
100
+ const isMachineTokenCurrency = MachineTokenCharge.isMachineToken({ chainId, currency });
101
+ const memo = Attribution.encode({
102
+ challengeId: challenge.id,
103
+ clientId,
104
+ serverId: challenge.realm,
105
+ });
104
106
  const transfers = Charge_internal.getTransfers({
105
107
  amount,
106
108
  methodDetails: {
@@ -116,14 +118,66 @@ export function charge(parameters = {}) {
116
118
  token: currency,
117
119
  }));
118
120
  const autoSwap = AutoSwap.resolve(context?.autoSwap ?? parameters.autoSwap, AutoSwap.defaultCurrencies);
119
- const account = (await parameters.resolveAccount?.({
121
+ const machineTokenEnabled = methodDetails?.machineTokenEnabled === true;
122
+ const resolveAccount = async (calls) => (await parameters.resolveAccount?.({
120
123
  account: defaultAccount,
121
124
  chainId,
122
125
  operation: {
123
126
  kind: 'executeCalls',
124
- ...(autoSwap ? {} : { calls: transferCalls }),
127
+ ...(calls ? { calls } : {}),
125
128
  },
126
129
  })) ?? defaultAccount;
130
+ const machineTokenCandidate = machineTokenEnabled
131
+ ? MachineTokenCharge.getRoute({ chainId, currency, transfers })
132
+ : undefined;
133
+ let account = defaultAccount;
134
+ let machineTokenRoute;
135
+ if (machineTokenCandidate) {
136
+ const machineTokenAccount = await (async () => {
137
+ try {
138
+ return await resolveAccount(machineTokenCandidate.calls);
139
+ }
140
+ catch {
141
+ // A machine-token route is optional. A scoped account that cannot
142
+ // execute it may still be able to satisfy the direct payment.
143
+ return undefined;
144
+ }
145
+ })();
146
+ if (machineTokenAccount) {
147
+ machineTokenRoute = await MachineTokenCharge.findRoute(client, {
148
+ account: machineTokenAccount.address,
149
+ chainId,
150
+ currency,
151
+ transfers,
152
+ });
153
+ if (machineTokenRoute)
154
+ account = machineTokenAccount;
155
+ }
156
+ }
157
+ let swapCalls;
158
+ if (!machineTokenRoute) {
159
+ account = await resolveAccount(autoSwap ? undefined : transferCalls);
160
+ swapCalls = autoSwap
161
+ ? await AutoSwap.findCalls(client, {
162
+ account: account.address,
163
+ amountOut: BigInt(amount),
164
+ tokenOut: currency,
165
+ tokenIn: autoSwap.tokenIn,
166
+ slippage: autoSwap.slippage,
167
+ })
168
+ : undefined;
169
+ }
170
+ const calls = machineTokenRoute?.calls ?? [...(swapCalls ?? []), ...transferCalls];
171
+ const allowedFeeTokens = defaultFeeTokens(chainId);
172
+ const feeToken = machineTokenRoute || isMachineTokenCurrency
173
+ ? await resolveFeeToken({
174
+ account: account.address,
175
+ allowedTokens: allowedFeeTokens,
176
+ candidateTokens: allowedFeeTokens,
177
+ client,
178
+ prioritizeCandidates: true,
179
+ })
180
+ : undefined;
127
181
  const mode = (() => {
128
182
  const explicitMode = context?.mode ?? parameters.mode;
129
183
  if (explicitMode) {
@@ -136,27 +190,6 @@ export function charge(parameters = {}) {
136
190
  return preferredMode;
137
191
  return supportedModes[0];
138
192
  })();
139
- const swapCalls = autoSwap
140
- ? await AutoSwap.findCalls(client, {
141
- account: account.address,
142
- amountOut: BigInt(amount),
143
- tokenOut: currency,
144
- tokenIn: autoSwap.tokenIn,
145
- slippage: autoSwap.slippage,
146
- })
147
- : undefined;
148
- const calls = [...(swapCalls ?? []), ...transferCalls];
149
- const machAddress = mach.addresses[chainId];
150
- const allowedFeeTokens = defaultFeeTokens(chainId);
151
- const feeToken = machAddress && isAddressEqual(currency, machAddress)
152
- ? await resolveFeeToken({
153
- account: account.address,
154
- allowedTokens: allowedFeeTokens,
155
- candidateTokens: allowedFeeTokens,
156
- client,
157
- prioritizeCandidates: true,
158
- })
159
- : undefined;
160
193
  const validBefore = (() => {
161
194
  const defaultExpiry = Math.floor(Date.now() / 1000) + 25;
162
195
  if (!challenge.expires)
@@ -37,6 +37,7 @@ export declare function tempo(parameters?: tempo.Parameters): readonly [import("
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(parameters?: tempo.Parameters): readonly [import("
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(parameters?: tempo.Parameters): readonly [import("
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(parameters?: tempo.Parameters): readonly [import("
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(parameters?: tempo.Parameters): readonly [import("
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;
@@ -3,5 +3,6 @@ export * as Methods from './Methods.js';
3
3
  export * as Session from './session/index.js';
4
4
  export * as SessionLegacy from './legacy/index.js';
5
5
  export * as Subscription from './subscription/index.js';
6
- export { mach } from './Tokens.js';
6
+ /** Canonical first-party machine-token deployments by Tempo chain ID. */
7
+ export { machineToken as machineTokenDeployments } from './internal/defaults.js';
7
8
  //# sourceMappingURL=index.d.ts.map
@@ -3,5 +3,6 @@ export * as Methods from './Methods.js';
3
3
  export * as Session from './session/index.js';
4
4
  export * as SessionLegacy from './legacy/index.js';
5
5
  export * as Subscription from './subscription/index.js';
6
- export { mach } from './Tokens.js';
6
+ /** Canonical first-party machine-token deployments by Tempo chain ID. */
7
+ export { machineToken as machineTokenDeployments } from './internal/defaults.js';
7
8
  //# sourceMappingURL=index.js.map
@@ -16,6 +16,17 @@ export declare const currency: {
16
16
  readonly 4217: "0x20C000000000000000000000b9537d11c60E8b50";
17
17
  readonly 42431: "0x20c0000000000000000000000000000000000000";
18
18
  };
19
+ /** Immutable canonical first-party machine-token deployments used by charge routes. */
20
+ export declare const machineToken: Readonly<{
21
+ readonly 4217: Readonly<{
22
+ swap: "0xF72E5107c32C655ffA7539a3C8e97B7C3cE16A3F";
23
+ token: "0x20c000000000000000000000f37de3740ADec032";
24
+ }>;
25
+ readonly 42431: Readonly<{
26
+ swap: "0xd05f8EdFBB54Da0d765C9fE9b2B3f7d2E3a8C466";
27
+ token: "0x20c000000000000000000000f37de3740ADec032";
28
+ }>;
29
+ }>;
19
30
  /**
20
31
  * Default token decimals for TIP-20 stablecoins (e.g. pathUSD, USDC).
21
32
  *
@@ -14,6 +14,17 @@ export const currency = {
14
14
  [chainId.mainnet]: tokens.usdc,
15
15
  [chainId.testnet]: tokens.pathUsd,
16
16
  };
17
+ /** Immutable canonical first-party machine-token deployments used by charge routes. */
18
+ export const machineToken = Object.freeze({
19
+ [chainId.mainnet]: Object.freeze({
20
+ swap: '0xF72E5107c32C655ffA7539a3C8e97B7C3cE16A3F',
21
+ token: '0x20c000000000000000000000f37de3740ADec032',
22
+ }),
23
+ [chainId.testnet]: Object.freeze({
24
+ swap: '0xd05f8EdFBB54Da0d765C9fE9b2B3f7d2E3a8C466',
25
+ token: '0x20c000000000000000000000f37de3740ADec032',
26
+ }),
27
+ });
17
28
  /**
18
29
  * Default token decimals for TIP-20 stablecoins (e.g. pathUSD, USDC).
19
30
  *