mppx 0.8.19 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/README.md +0 -6
- package/dist/Challenge.d.ts +7 -0
- package/dist/Challenge.js +32 -6
- package/dist/Constants.d.ts +1 -0
- package/dist/Constants.js +1 -0
- package/dist/Credential.d.ts +11 -5
- package/dist/Credential.js +8 -8
- package/dist/Errors.d.ts +10 -0
- package/dist/Errors.js +12 -0
- package/dist/Html.js +1 -1
- package/dist/Mcp.d.ts +9 -1
- package/dist/Mcp.js +18 -0
- package/dist/Method.d.ts +7 -0
- package/dist/cli/THIRD-PARTY-LICENSES.txt +1 -1
- package/dist/cli/cli.d.ts +2 -2
- package/dist/cli/cli.js +134 -134
- package/dist/cli/plugins/index.js +13 -13
- package/dist/cli/sessions/Manager.js +4 -6
- package/dist/cli/sessions/commands.d.ts +1 -1
- package/dist/cli/sessions/store.js +13 -19
- package/dist/cli/validate/index.d.ts +2 -2
- package/dist/client/Mppx.d.ts +39 -2
- package/dist/client/Mppx.js +102 -46
- package/dist/client/Transport.js +1 -1
- package/dist/client/internal/protocols/Mcp.js +2 -1
- package/dist/client/internal/protocols/Mpp.d.ts +1 -1
- package/dist/client/internal/protocols/Mpp.js +5 -3
- package/dist/client/internal/protocols/Protocol.d.ts +3 -1
- package/dist/client/internal/protocols/Shared.js +5 -1
- package/dist/integrations/x402/Evm.d.ts +29 -0
- package/dist/integrations/x402/Evm.js +150 -0
- package/dist/integrations/x402/Negotiator.d.ts +36 -0
- package/dist/integrations/x402/Negotiator.js +165 -0
- package/dist/mcp/client/McpClient.js +22 -10
- package/dist/mcp/internal/Credential.d.ts +9 -0
- package/dist/mcp/internal/Credential.js +16 -0
- package/dist/mcp/server/Transport.d.ts +2 -2
- package/dist/mcp/server/Transport.js +11 -6
- package/dist/middlewares/express.js +5 -12
- package/dist/middlewares/internal/express.d.ts +8 -0
- package/dist/middlewares/internal/express.js +24 -0
- package/dist/middlewares/internal/node.d.ts +10 -0
- package/dist/middlewares/internal/node.js +34 -0
- package/dist/proxy/Proxy.js +15 -9
- package/dist/server/Mppx.d.ts +8 -0
- package/dist/server/Mppx.js +92 -20
- package/dist/server/Transport.d.ts +8 -2
- package/dist/server/Transport.js +14 -18
- package/dist/server/internal/SecretKey.d.ts +3 -0
- package/dist/server/internal/SecretKey.js +9 -0
- package/dist/server/internal/html/serviceWorker.client.d.ts +1 -1
- package/dist/server/internal/html/serviceWorker.client.js +2 -2
- package/dist/server/internal/html/serviceWorker.gen.d.ts +1 -1
- package/dist/server/internal/html/serviceWorker.gen.js +1 -1
- package/dist/stripe/Methods.d.ts +6 -0
- package/dist/stripe/Methods.js +3 -1
- package/dist/stripe/client/Charge.d.ts +6 -0
- package/dist/stripe/client/Methods.d.ts +6 -0
- package/dist/stripe/internal/payment-intent.d.ts +7 -0
- package/dist/stripe/internal/payment-intent.js +6 -0
- package/dist/stripe/server/Charge.d.ts +6 -0
- package/dist/stripe/server/Charge.js +8 -3
- package/dist/stripe/server/Methods.js +62 -7
- package/dist/stripe/server/internal/html.gen.d.ts +1 -1
- package/dist/stripe/server/internal/html.gen.js +1 -1
- package/dist/tempo/Methods.d.ts +0 -10
- package/dist/tempo/Methods.js +3 -12
- package/dist/tempo/Tokens.d.ts +13 -0
- package/dist/tempo/Tokens.js +13 -0
- package/dist/tempo/client/Charge.d.ts +1 -4
- package/dist/tempo/client/Charge.js +20 -13
- package/dist/tempo/client/Methods.d.ts +0 -10
- package/dist/tempo/index.d.ts +1 -0
- package/dist/tempo/index.js +1 -0
- package/dist/tempo/internal/account.d.ts +15 -6
- package/dist/tempo/internal/account.js +17 -26
- package/dist/tempo/internal/defaults.d.ts +0 -11
- package/dist/tempo/internal/defaults.js +0 -11
- package/dist/tempo/internal/fee-payer.d.ts +22 -4
- package/dist/tempo/internal/fee-payer.js +12 -31
- package/dist/tempo/internal/fee-token.d.ts +2 -0
- package/dist/tempo/internal/fee-token.js +7 -0
- package/dist/tempo/internal/remote-fee-payer.d.ts +12 -0
- package/dist/tempo/internal/remote-fee-payer.js +17 -0
- package/dist/tempo/legacy/client/Session.d.ts +0 -7
- package/dist/tempo/server/Charge.d.ts +0 -3
- package/dist/tempo/server/Charge.js +26 -68
- package/dist/tempo/server/Methods.d.ts +4 -18
- package/dist/tempo/server/Methods.js +4 -8
- package/dist/tempo/server/internal/html.gen.d.ts +1 -1
- package/dist/tempo/server/internal/html.gen.js +1 -1
- package/dist/tempo/session/client/ChannelOps.d.ts +0 -14
- package/dist/tempo/session/client/ChannelOps.js +0 -22
- package/dist/tempo/session/client/ChannelStore.d.ts +5 -0
- package/dist/tempo/session/client/ChannelStore.js +2 -2
- package/dist/tempo/session/client/CredentialState.d.ts +2 -12
- package/dist/tempo/session/client/CredentialState.js +75 -73
- package/dist/tempo/session/client/Session.d.ts +2 -9
- package/dist/tempo/session/client/Session.js +71 -176
- package/dist/tempo/session/client/SessionManager.js +7 -27
- package/dist/tempo/session/precompile/Chain.d.ts +0 -4
- package/dist/tempo/session/precompile/Chain.js +1 -29
- package/dist/tempo/session/precompile/Protocol.d.ts +0 -13
- package/dist/tempo/session/precompile/Voucher.d.ts +1 -3
- package/dist/tempo/session/precompile/Voucher.js +12 -6
- package/dist/tempo/session/server/ChannelStore.d.ts +0 -6
- package/dist/tempo/session/server/ChannelStore.js +4 -11
- package/dist/tempo/session/server/CredentialVerification.d.ts +7 -9
- package/dist/tempo/session/server/CredentialVerification.js +118 -184
- package/dist/tempo/session/server/RequestState.d.ts +0 -17
- package/dist/tempo/session/server/RequestState.js +15 -59
- package/dist/tempo/session/server/Session.d.ts +0 -9
- package/dist/tempo/session/server/Session.js +13 -39
- package/dist/tempo/session/server/Settlement.d.ts +0 -7
- package/dist/tempo/session/server/Settlement.js +16 -50
- package/dist/viem/Client.d.ts +7 -2
- package/dist/viem/Client.js +17 -5
- package/dist/x402/Types.d.ts +2 -0
- package/dist/x402/Types.js +2 -0
- package/dist/x402/mcp.d.ts +20 -0
- package/dist/x402/mcp.js +154 -0
- package/dist/x402/middlewares/express.d.ts +23 -0
- package/dist/x402/middlewares/express.js +49 -0
- package/dist/x402/middlewares/hono.d.ts +13 -0
- package/dist/x402/middlewares/hono.js +36 -0
- package/dist/x402/middlewares/next.d.ts +17 -0
- package/dist/x402/middlewares/next.js +58 -0
- package/package.json +41 -1
- package/dist/tempo/internal/machine-token-charge.d.ts +0 -51
- package/dist/tempo/internal/machine-token-charge.js +0 -113
- package/dist/tempo/internal/machine-token-session.d.ts +0 -88
- package/dist/tempo/internal/machine-token-session.js +0 -173
- package/dist/tempo/internal/signature-envelope.d.ts +0 -14
- package/dist/tempo/internal/signature-envelope.js +0 -28
|
@@ -3,10 +3,9 @@ import * as Constants from '../../../Constants.js';
|
|
|
3
3
|
import { VerificationFailedError } from '../../../Errors.js';
|
|
4
4
|
import * as Methods from '../../Methods.js';
|
|
5
5
|
import { captureRequestBodyProbe, isSessionContentRequest, } from '../../server/internal/request-body.js';
|
|
6
|
-
import { tip20ChannelEscrow
|
|
7
|
-
import * as Voucher from '../precompile/Voucher.js';
|
|
6
|
+
import { tip20ChannelEscrow } from '../precompile/Protocol.js';
|
|
8
7
|
import * as ChannelStore from './ChannelStore.js';
|
|
9
|
-
import { requireSessionCredentialAction
|
|
8
|
+
import { requireSessionCredentialAction } from './CredentialVerification.js';
|
|
10
9
|
import { resolveCredentialFeePayer, resolveRequestFeePayer, } from './Settlement.js';
|
|
11
10
|
/** Normalizes a session channel ID hint when one is present. */
|
|
12
11
|
export function normalizeSessionChannelId(value) {
|
|
@@ -30,27 +29,6 @@ function normalizeResolvedSessionChannelId(value) {
|
|
|
30
29
|
return undefined;
|
|
31
30
|
return ChannelStore.normalizeChannelId(value);
|
|
32
31
|
}
|
|
33
|
-
/** Returns a close credential's channel once its voucher signature verifies. */
|
|
34
|
-
async function verifiedCloseCredentialChannel(credential, store) {
|
|
35
|
-
try {
|
|
36
|
-
const payload = requireSessionCredentialPayload(credential?.payload);
|
|
37
|
-
if (payload.action !== 'close')
|
|
38
|
-
return undefined;
|
|
39
|
-
const channelId = payload.channelId;
|
|
40
|
-
const channel = await store.getChannel(channelId);
|
|
41
|
-
if (!channel || !ChannelStore.isPrecompileState(channel))
|
|
42
|
-
return undefined;
|
|
43
|
-
const verified = Voucher.verifyVoucher(channel.escrowContract, channel.chainId, {
|
|
44
|
-
channelId,
|
|
45
|
-
cumulativeAmount: uint96(BigInt(payload.cumulativeAmount)),
|
|
46
|
-
signature: payload.signature,
|
|
47
|
-
}, channel.authorizedSigner);
|
|
48
|
-
return verified ? { channelId, channel } : undefined;
|
|
49
|
-
}
|
|
50
|
-
catch {
|
|
51
|
-
return undefined;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
32
|
/** Resolves the channel ID used to build server-side session bootstrap hints. */
|
|
55
33
|
export async function resolveSessionChannelId(parameters) {
|
|
56
34
|
const { capturedRequest, credential, request, resolveChannelId, source, store } = parameters;
|
|
@@ -69,10 +47,10 @@ export async function resolveSessionChannelId(parameters) {
|
|
|
69
47
|
}
|
|
70
48
|
/** Builds server bootstrap hints for a reusable precompile session channel. */
|
|
71
49
|
export async function resolveSessionSnapshot(parameters) {
|
|
72
|
-
const { amount, channelId, expected,
|
|
50
|
+
const { amount, channelId, expected, store } = parameters;
|
|
73
51
|
if (!channelId)
|
|
74
52
|
return undefined;
|
|
75
|
-
const channel =
|
|
53
|
+
const channel = await store.getChannel(ChannelStore.normalizeChannelId(channelId));
|
|
76
54
|
if (!channel || !ChannelStore.isPrecompileState(channel))
|
|
77
55
|
return undefined;
|
|
78
56
|
if (channel.finalized)
|
|
@@ -83,18 +61,8 @@ export async function resolveSessionSnapshot(parameters) {
|
|
|
83
61
|
return undefined;
|
|
84
62
|
if (channel.highestVoucher.cumulativeAmount !== channel.highestVoucherAmount)
|
|
85
63
|
return undefined;
|
|
86
|
-
if (expected && !matchesSnapshotPaymentFields(channel, expected))
|
|
87
|
-
|
|
88
|
-
// transient RPC error during the route check) must omit the hint rather
|
|
89
|
-
// than fail challenge issuance or bootstrap preflight.
|
|
90
|
-
let matched = false;
|
|
91
|
-
try {
|
|
92
|
-
matched = (await matchPaymentFields?.(channel, expected)) ?? false;
|
|
93
|
-
}
|
|
94
|
-
catch { }
|
|
95
|
-
if (!matched)
|
|
96
|
-
return undefined;
|
|
97
|
-
}
|
|
64
|
+
if (expected && !matchesSnapshotPaymentFields(channel, expected))
|
|
65
|
+
return undefined;
|
|
98
66
|
const requiredCumulative = channel.spent + amount;
|
|
99
67
|
return {
|
|
100
68
|
acceptedCumulative: channel.highestVoucherAmount.toString(),
|
|
@@ -149,7 +117,6 @@ function isCanonicalSessionMethodDetails(value) {
|
|
|
149
117
|
(value.feePayer === undefined || typeof value.feePayer === 'boolean') &&
|
|
150
118
|
(value.feeToken === undefined ||
|
|
151
119
|
(typeof value.feeToken === 'string' && isAddress(value.feeToken, { strict: false }))) &&
|
|
152
|
-
(value.machineTokenEnabled === undefined || typeof value.machineTokenEnabled === 'boolean') &&
|
|
153
120
|
(value.minVoucherDelta === undefined || typeof value.minVoucherDelta === 'string') &&
|
|
154
121
|
(value.operator === undefined ||
|
|
155
122
|
(typeof value.operator === 'string' && isAddress(value.operator, { strict: false }))) &&
|
|
@@ -191,7 +158,7 @@ export async function resolveRequestChainId(parameters) {
|
|
|
191
158
|
}
|
|
192
159
|
/** Resolves request-time TIP-1034 details and server bootstrap hints for a challenge. */
|
|
193
160
|
export async function resolveSessionPaymentRequest(parameters) {
|
|
194
|
-
const { capturedRequest, credential, decimals, defaultFeePayer, getClient,
|
|
161
|
+
const { capturedRequest, credential, decimals, defaultFeePayer, getClient, parameterChainId, parameterEscrowContract, parameterFeePayer, request, resolveChannelId, source, store, } = parameters;
|
|
195
162
|
const chainId = await resolveRequestChainId({
|
|
196
163
|
getClient,
|
|
197
164
|
parameterChainId,
|
|
@@ -205,24 +172,16 @@ export async function resolveSessionPaymentRequest(parameters) {
|
|
|
205
172
|
const escrowContract = resolveRequestEscrowContract(request.escrowContract, parameterEscrowContract);
|
|
206
173
|
const operator = resolveRequestOperator(request.operator);
|
|
207
174
|
const requestAmount = parseUnits(request.amount, decimals);
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
capturedRequest,
|
|
217
|
-
credential,
|
|
218
|
-
request,
|
|
219
|
-
resolveChannelId,
|
|
220
|
-
source,
|
|
221
|
-
store,
|
|
222
|
-
}));
|
|
175
|
+
const channelId = await resolveSessionChannelId({
|
|
176
|
+
capturedRequest,
|
|
177
|
+
credential,
|
|
178
|
+
request,
|
|
179
|
+
resolveChannelId,
|
|
180
|
+
source,
|
|
181
|
+
store,
|
|
182
|
+
});
|
|
223
183
|
const sessionSnapshot = await resolveSessionSnapshot({
|
|
224
184
|
amount: capturedRequest && !isSessionContentRequest(capturedRequest) ? 0n : requestAmount,
|
|
225
|
-
channel: verifiedClose?.channel,
|
|
226
185
|
channelId,
|
|
227
186
|
expected: {
|
|
228
187
|
chainId,
|
|
@@ -230,9 +189,6 @@ export async function resolveSessionPaymentRequest(parameters) {
|
|
|
230
189
|
escrowContract,
|
|
231
190
|
recipient: readChallengeAddress(request.recipient, 'recipient'),
|
|
232
191
|
},
|
|
233
|
-
matchPaymentFields: matchSnapshotPaymentFields && (verifiedClose || request.machineTokenEnabled)
|
|
234
|
-
? (channel, expected) => matchSnapshotPaymentFields(channel, expected, verifiedClose ? { action: 'close' } : undefined)
|
|
235
|
-
: undefined,
|
|
236
192
|
store,
|
|
237
193
|
});
|
|
238
194
|
const { operator: _operator, ...requestWithoutOperator } = request;
|
|
@@ -36,7 +36,6 @@ export declare function session<const parameters extends session.Parameters>(p?:
|
|
|
36
36
|
credential: {
|
|
37
37
|
payload: import("zod/mini").ZodMiniDiscriminatedUnion<[import("zod/mini").ZodMiniObject<{
|
|
38
38
|
action: import("zod/mini").ZodMiniLiteral<"open">;
|
|
39
|
-
authorizationSignature: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
40
39
|
authorizedSigner: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
41
40
|
channelId: import("zod/mini").ZodMiniString<string>;
|
|
42
41
|
cumulativeAmount: import("zod/mini").ZodMiniString<string>;
|
|
@@ -53,18 +52,15 @@ export declare function session<const parameters extends session.Parameters>(p?:
|
|
|
53
52
|
type: import("zod/mini").ZodMiniLiteral<"transaction">;
|
|
54
53
|
}, import("zod/v4/core").$strip>, import("zod/mini").ZodMiniObject<{
|
|
55
54
|
action: import("zod/mini").ZodMiniLiteral<"voucher">;
|
|
56
|
-
authorizationSignature: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
57
55
|
channelId: import("zod/mini").ZodMiniString<string>;
|
|
58
56
|
cumulativeAmount: import("zod/mini").ZodMiniString<string>;
|
|
59
57
|
descriptor: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniCustom<import("../precompile/Protocol.js").ChannelDescriptor, import("../precompile/Protocol.js").ChannelDescriptor>>;
|
|
60
58
|
signature: import("zod/mini").ZodMiniString<string>;
|
|
61
59
|
}, import("zod/v4/core").$strip>, import("zod/mini").ZodMiniObject<{
|
|
62
60
|
action: import("zod/mini").ZodMiniLiteral<"close">;
|
|
63
|
-
authorizationSignature: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
64
61
|
channelId: import("zod/mini").ZodMiniString<string>;
|
|
65
62
|
cumulativeAmount: import("zod/mini").ZodMiniString<string>;
|
|
66
63
|
descriptor: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniCustom<import("../precompile/Protocol.js").ChannelDescriptor, import("../precompile/Protocol.js").ChannelDescriptor>>;
|
|
67
|
-
refundSignature: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
68
64
|
signature: import("zod/mini").ZodMiniString<string>;
|
|
69
65
|
}, import("zod/v4/core").$strip>], "action">;
|
|
70
66
|
};
|
|
@@ -77,7 +73,6 @@ export declare function session<const parameters extends session.Parameters>(p?:
|
|
|
77
73
|
escrowContract: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
78
74
|
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>>>;
|
|
79
75
|
feeToken: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
80
|
-
machineTokenEnabled: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniBoolean<boolean>>;
|
|
81
76
|
minVoucherDelta: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
82
77
|
operator: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
83
78
|
recipient: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
@@ -101,7 +96,6 @@ export declare function session<const parameters extends session.Parameters>(p?:
|
|
|
101
96
|
chainId?: number | undefined;
|
|
102
97
|
feePayer?: boolean | undefined;
|
|
103
98
|
feeToken?: string | undefined;
|
|
104
|
-
machineTokenEnabled?: boolean | undefined;
|
|
105
99
|
operator?: string | undefined;
|
|
106
100
|
sessionProtocol?: "v1" | "v2" | undefined;
|
|
107
101
|
sessionSnapshot?: import("../Snapshot.js").SessionSnapshot | undefined;
|
|
@@ -115,7 +109,6 @@ export declare function session<const parameters extends session.Parameters>(p?:
|
|
|
115
109
|
escrowContract?: string | undefined;
|
|
116
110
|
feePayer?: boolean | undefined;
|
|
117
111
|
feeToken?: string | undefined;
|
|
118
|
-
machineTokenEnabled?: boolean | undefined;
|
|
119
112
|
minVoucherDelta?: string | undefined;
|
|
120
113
|
operator?: string | undefined;
|
|
121
114
|
recipient?: string | undefined;
|
|
@@ -185,8 +178,6 @@ export declare namespace session {
|
|
|
185
178
|
settlementSchedule?: SettlementSchedule | undefined;
|
|
186
179
|
/** Optional fee token for management and server-driven settle/close transactions. */
|
|
187
180
|
feeToken?: Address | undefined;
|
|
188
|
-
/** Enables first-party machine-token funding when the configured deployment is available. */
|
|
189
|
-
machineTokenEnabled?: boolean | undefined;
|
|
190
181
|
} & Account.resolve.Parameters & Client.getResolver.Parameters & Defaults & Method.ComposableHooks<typeof Methods.session>;
|
|
191
182
|
/** Defaults derived from `session()` parameters for handler type inference. */
|
|
192
183
|
type DeriveDefaults<parameters extends Parameters> = types.DeriveDefaults<parameters, Defaults, {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* and one-shot settlement. Each incoming request carries a session credential
|
|
6
6
|
* with a cumulative voucher that the server validates and records.
|
|
7
7
|
*/
|
|
8
|
-
import { isAddress
|
|
8
|
+
import { isAddress } from 'viem';
|
|
9
9
|
import { tempo as tempo_chain } from 'viem/chains';
|
|
10
10
|
import * as Challenge from '../../../Challenge.js';
|
|
11
11
|
import * as Constants from '../../../Constants.js';
|
|
@@ -16,7 +16,6 @@ import * as Store from '../../../Store.js';
|
|
|
16
16
|
import * as Client from '../../../viem/Client.js';
|
|
17
17
|
import * as Account from '../../internal/account.js';
|
|
18
18
|
import * as defaults from '../../internal/defaults.js';
|
|
19
|
-
import * as MachineTokenSession from '../../internal/machine-token-session.js';
|
|
20
19
|
import * as Methods from '../../Methods.js';
|
|
21
20
|
import * as ChargeServer from '../../server/Charge.js';
|
|
22
21
|
import * as Transport from '../../server/internal/transport.js';
|
|
@@ -130,10 +129,13 @@ async function verifyBootstrapCredential(parameters) {
|
|
|
130
129
|
});
|
|
131
130
|
Expires.assert(credential.challenge.expires, credential.challenge.id);
|
|
132
131
|
assertBootstrapChallengeMatches(challenge, credential.challenge);
|
|
132
|
+
const payload = Methods.charge.schema.credential.payload.safeParse(credential.payload);
|
|
133
|
+
if (!payload.success)
|
|
134
|
+
throw new Errors.InvalidPayloadError();
|
|
133
135
|
return charge.verify({
|
|
134
136
|
credential: {
|
|
135
137
|
...credential,
|
|
136
|
-
payload:
|
|
138
|
+
payload: payload.data,
|
|
137
139
|
},
|
|
138
140
|
request: rawRequest,
|
|
139
141
|
});
|
|
@@ -160,7 +162,7 @@ async function handleBootstrapPreflight(parameters) {
|
|
|
160
162
|
});
|
|
161
163
|
}
|
|
162
164
|
catch (error) {
|
|
163
|
-
return respondBootstrapChallenge(challenge, error instanceof Errors.PaymentError ? error : new Errors.
|
|
165
|
+
return respondBootstrapChallenge(challenge, error instanceof Errors.PaymentError ? error : new Errors.InternalPaymentError());
|
|
164
166
|
}
|
|
165
167
|
const channelId = await resolveSessionChannelId({
|
|
166
168
|
capturedRequest: parameters.capturedRequest,
|
|
@@ -179,9 +181,6 @@ async function handleBootstrapPreflight(parameters) {
|
|
|
179
181
|
escrowContract: resolveBootstrapEscrowContract(parameters.paymentRequest, parameters.parameterEscrowContract),
|
|
180
182
|
recipient: readBootstrapAddress(request.recipient, 'recipient'),
|
|
181
183
|
},
|
|
182
|
-
matchPaymentFields: parameters.paymentRequest.machineTokenEnabled
|
|
183
|
-
? parameters.matchSnapshotPaymentFields
|
|
184
|
-
: undefined,
|
|
185
184
|
store: parameters.store,
|
|
186
185
|
});
|
|
187
186
|
const headers = new Headers({ 'Cache-Control': 'no-store' });
|
|
@@ -194,33 +193,19 @@ async function handleBootstrapPreflight(parameters) {
|
|
|
194
193
|
/** Creates a server-side TIP20EscrowChannel precompile session payment method. */
|
|
195
194
|
export function session(p) {
|
|
196
195
|
const parameters = p;
|
|
197
|
-
const { amount, channelStateTtl = 5_000, currency = defaults.resolveCurrency(parameters), decimals = defaults.decimals,
|
|
196
|
+
const { amount, channelStateTtl = 5_000, currency = defaults.resolveCurrency(parameters), decimals = defaults.decimals, operator, store: rawStore = Store.memory(), suggestedDeposit, unitType, } = parameters;
|
|
198
197
|
const settlementSchedule = resolveSettlementSchedule(parameters.settlementSchedule, decimals);
|
|
199
198
|
const onSessionSettlement = parameters.onSessionSettlement;
|
|
200
199
|
const store = ChannelStore.fromStore(rawStore);
|
|
201
200
|
const lastOnChainVerified = new Map();
|
|
202
|
-
const { account, feePayer,
|
|
203
|
-
const configuredFeePayer = feePayer ??
|
|
204
|
-
const settlementFeePayer = feePayer ?? (feePayerUrl ? true : undefined);
|
|
201
|
+
const { account, feePayer, remoteFeePayer, recipient } = Account.resolve(parameters);
|
|
202
|
+
const configuredFeePayer = feePayer ?? (remoteFeePayer || parameters.feePayer === true ? true : undefined);
|
|
205
203
|
const getClient = Client.getResolver({
|
|
206
204
|
chain: tempo_chain,
|
|
207
|
-
|
|
205
|
+
remoteFeePayer,
|
|
208
206
|
getClient: parameters.getClient,
|
|
209
207
|
rpcUrl: defaults.rpcUrl,
|
|
210
208
|
});
|
|
211
|
-
const matchSnapshotPaymentFields = async (channel, expected, options) => {
|
|
212
|
-
if (channel.chainId !== expected.chainId ||
|
|
213
|
-
!isAddressEqual(channel.escrowContract, expected.escrowContract) ||
|
|
214
|
-
!isAddressEqual(expected.escrowContract, tip20ChannelEscrow))
|
|
215
|
-
return false;
|
|
216
|
-
return !!(await MachineTokenSession.matchRoute(await getClient({ chainId: expected.chainId }), {
|
|
217
|
-
active: options?.action !== 'close',
|
|
218
|
-
chainId: expected.chainId,
|
|
219
|
-
descriptor: channel.descriptor,
|
|
220
|
-
merchant: expected.recipient,
|
|
221
|
-
targetToken: expected.currency,
|
|
222
|
-
}));
|
|
223
|
-
};
|
|
224
209
|
const settleScheduled = async (channel) => {
|
|
225
210
|
if (!isSettlementDue(channel, settlementSchedule))
|
|
226
211
|
return undefined;
|
|
@@ -228,7 +213,7 @@ export function session(p) {
|
|
|
228
213
|
account,
|
|
229
214
|
channel,
|
|
230
215
|
client: await getClient({ chainId: channel.chainId }),
|
|
231
|
-
...(
|
|
216
|
+
...(configuredFeePayer ? { feePayer: configuredFeePayer } : {}),
|
|
232
217
|
feePayerPolicy: parameters.feePayerPolicy,
|
|
233
218
|
feeToken: parameters.feeToken,
|
|
234
219
|
onSessionSettlement,
|
|
@@ -350,7 +335,6 @@ export function session(p) {
|
|
|
350
335
|
amount,
|
|
351
336
|
currency,
|
|
352
337
|
decimals,
|
|
353
|
-
machineTokenEnabled,
|
|
354
338
|
operator,
|
|
355
339
|
recipient,
|
|
356
340
|
suggestedDeposit,
|
|
@@ -371,7 +355,6 @@ export function session(p) {
|
|
|
371
355
|
defaultRecipient: recipient,
|
|
372
356
|
expires,
|
|
373
357
|
getClient,
|
|
374
|
-
matchSnapshotPaymentFields,
|
|
375
358
|
parameterChainId: parameters.chainId,
|
|
376
359
|
parameterEscrowContract: parameters.escrowContract,
|
|
377
360
|
paymentRequest: options,
|
|
@@ -389,25 +372,16 @@ export function session(p) {
|
|
|
389
372
|
decimals,
|
|
390
373
|
defaultFeePayer: feePayer,
|
|
391
374
|
getClient,
|
|
392
|
-
matchSnapshotPaymentFields,
|
|
393
375
|
parameterChainId: parameters.chainId,
|
|
394
376
|
parameterEscrowContract: parameters.escrowContract,
|
|
395
|
-
parameterFeePayer:
|
|
377
|
+
parameterFeePayer: configuredFeePayer,
|
|
396
378
|
request,
|
|
397
379
|
resolveChannelId: parameters.resolveChannelId,
|
|
398
380
|
store,
|
|
399
381
|
});
|
|
400
|
-
// Only advertise the capability when this logical session can use a
|
|
401
|
-
// configured unified router on the canonical escrow.
|
|
402
|
-
const { machineTokenEnabled: requestedMachineTokenEnabled, ...requestWithoutMachineToken } = resolvedRequest;
|
|
403
|
-
const machineSessionSupported = MachineTokenSession.isSupported(resolvedRequest.chainId) &&
|
|
404
|
-
isAddressEqual(resolvedRequest.escrowContract, tip20ChannelEscrow);
|
|
405
382
|
return {
|
|
406
|
-
...
|
|
383
|
+
...resolvedRequest,
|
|
407
384
|
feeToken: parameters.feeToken,
|
|
408
|
-
...(requestedMachineTokenEnabled && machineSessionSupported
|
|
409
|
-
? { machineTokenEnabled: true }
|
|
410
|
-
: {}),
|
|
411
385
|
sessionProtocol: Constants.SessionProtocols.v2,
|
|
412
386
|
};
|
|
413
387
|
},
|
|
@@ -198,13 +198,6 @@ export declare function getClientAccount(client: {
|
|
|
198
198
|
}): viem_Account | undefined;
|
|
199
199
|
/** Validates that the transaction sender is the channel payee or nonzero operator. */
|
|
200
200
|
export declare function assertSettlementSender(parameters: SettlementSenderParameters): void;
|
|
201
|
-
/**
|
|
202
|
-
* Assembles transaction options for settle/close transactions. Machine
|
|
203
|
-
* channels pin PathUSD (or an explicit override); direct channels leave the
|
|
204
|
-
* fee token unset so balance-aware selection can pick a funded candidate.
|
|
205
|
-
* The rail comes from the caller so fee pinning always matches dispatch.
|
|
206
|
-
*/
|
|
207
|
-
export declare function resolveChannelTransactionOptions(channel: Pick<ChannelStore.StoredPrecompileChannel, 'chainId' | 'token'>, options: SettlementTransactionOptions | undefined, account: viem_Account | undefined, machineRouter: Address | undefined): Chain.ChannelTransactionOptions | undefined;
|
|
208
201
|
/** Applies automatic settlement when the server-owned schedule is due. */
|
|
209
202
|
export declare function maybeSettleScheduled(parameters: MaybeSettleScheduledParameters): Promise<Hex | undefined>;
|
|
210
203
|
/** Settles the highest accepted voucher for a precompile-backed session channel. */
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { isAddress, isAddressEqual, parseUnits, zeroAddress, } from 'viem';
|
|
2
2
|
import { BadRequestError, ChannelClosedError, ChannelNotFoundError, InsufficientBalanceError, VerificationFailedError, } from '../../../Errors.js';
|
|
3
|
-
import * as MachineTokenSession from '../../internal/machine-token-session.js';
|
|
4
3
|
import { isSessionContentRequest } from '../../server/internal/request-body.js';
|
|
5
4
|
import * as Chain from '../precompile/Chain.js';
|
|
6
5
|
import { readSettledReceiptFields } from '../precompile/Chain.js';
|
|
@@ -183,30 +182,6 @@ export function assertSettlementSender(parameters) {
|
|
|
183
182
|
' If using an access key, pass a Tempo access-key account whose address is the payee/operator wallet, not the raw delegated key address.',
|
|
184
183
|
});
|
|
185
184
|
}
|
|
186
|
-
/**
|
|
187
|
-
* Assembles transaction options for settle/close transactions. Machine
|
|
188
|
-
* channels pin PathUSD (or an explicit override); direct channels leave the
|
|
189
|
-
* fee token unset so balance-aware selection can pick a funded candidate.
|
|
190
|
-
* The rail comes from the caller so fee pinning always matches dispatch.
|
|
191
|
-
*/
|
|
192
|
-
export function resolveChannelTransactionOptions(channel, options, account, machineRouter) {
|
|
193
|
-
if (!account)
|
|
194
|
-
return undefined;
|
|
195
|
-
const feeToken = options?.feeToken ??
|
|
196
|
-
(machineRouter
|
|
197
|
-
? MachineTokenSession.resolveFeeToken({
|
|
198
|
-
chainId: channel.chainId,
|
|
199
|
-
paymentToken: channel.token,
|
|
200
|
-
})
|
|
201
|
-
: undefined);
|
|
202
|
-
return {
|
|
203
|
-
account,
|
|
204
|
-
...(options?.feePayer ? { feePayer: options.feePayer } : {}),
|
|
205
|
-
...(options?.feePayerPolicy ? { feePayerPolicy: options.feePayerPolicy } : {}),
|
|
206
|
-
...(feeToken ? { feeToken } : {}),
|
|
207
|
-
candidateFeeTokens: options?.candidateFeeTokens ?? [feeToken ?? channel.token],
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
185
|
/** Applies automatic settlement when the server-owned schedule is due. */
|
|
211
186
|
export async function maybeSettleScheduled(parameters) {
|
|
212
187
|
const { channel, schedule, store } = parameters;
|
|
@@ -237,32 +212,23 @@ export async function settle(store_, client, channelId_, options) {
|
|
|
237
212
|
throw new VerificationFailedError({ reason: 'no voucher to settle' });
|
|
238
213
|
const escrow = options?.escrowContract ?? channel.escrowContract;
|
|
239
214
|
const account = options?.account ?? getClientAccount(client);
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
channelId,
|
|
248
|
-
operator: channel.operator,
|
|
249
|
-
payee: channel.payee,
|
|
250
|
-
sender: account?.address,
|
|
251
|
-
});
|
|
215
|
+
assertSettlementSender({
|
|
216
|
+
operation: 'settle',
|
|
217
|
+
channelId,
|
|
218
|
+
operator: channel.operator,
|
|
219
|
+
payee: channel.payee,
|
|
220
|
+
sender: account?.address,
|
|
221
|
+
});
|
|
252
222
|
const amount = uint96(channel.highestVoucher.cumulativeAmount);
|
|
253
|
-
const
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
}
|
|
263
|
-
else {
|
|
264
|
-
txHash = await Chain.settleOnChain(client, channel.descriptor, amount, channel.highestVoucher.signature, escrow, transactionOptions);
|
|
265
|
-
}
|
|
223
|
+
const txHash = await Chain.settleOnChain(client, channel.descriptor, amount, channel.highestVoucher.signature, escrow, account
|
|
224
|
+
? {
|
|
225
|
+
account,
|
|
226
|
+
...(options?.feePayer ? { feePayer: options.feePayer } : {}),
|
|
227
|
+
...(options?.feePayerPolicy ? { feePayerPolicy: options.feePayerPolicy } : {}),
|
|
228
|
+
...(options?.feeToken ? { feeToken: options.feeToken } : {}),
|
|
229
|
+
candidateFeeTokens: options?.candidateFeeTokens ?? [channel.token],
|
|
230
|
+
}
|
|
231
|
+
: undefined);
|
|
266
232
|
const receipt = await Chain.waitForSuccessfulReceipt(client, txHash);
|
|
267
233
|
const settled = readSettledReceiptFields(Chain.getChannelEvent(receipt, 'Settled', channelId));
|
|
268
234
|
const { newSettled } = settled;
|
package/dist/viem/Client.d.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { type Chain, type Client } from 'viem';
|
|
2
2
|
import type { MaybePromise } from '../internal/types.js';
|
|
3
|
+
import * as RemoteFeePayer from '../tempo/internal/remote-fee-payer.js';
|
|
4
|
+
/** Creates an HTTP transport for a configured remote fee-payer service. */
|
|
5
|
+
export declare function remoteFeePayerTransport(config: RemoteFeePayer.Config, options?: {
|
|
6
|
+
retryCount?: number | undefined;
|
|
7
|
+
}): import("viem").HttpTransport<undefined, false>;
|
|
3
8
|
export declare function getResolver(parameters: getResolver.Parameters & {
|
|
4
9
|
/** Default chain to use if not provided. */
|
|
5
10
|
chain?: Chain | undefined;
|
|
6
|
-
/**
|
|
7
|
-
|
|
11
|
+
/** Remote fee-payer configuration. When set, the transport is wrapped with `withFeePayer`. */
|
|
12
|
+
remoteFeePayer?: RemoteFeePayer.Config | undefined;
|
|
8
13
|
/** RPC URLs keyed by chain ID. */
|
|
9
14
|
rpcUrl?: ({
|
|
10
15
|
[chainId: number]: string;
|
package/dist/viem/Client.js
CHANGED
|
@@ -1,28 +1,38 @@
|
|
|
1
1
|
import { createClient, createTransport, custom, http } from 'viem';
|
|
2
2
|
import { withFeePayer } from 'viem/tempo';
|
|
3
3
|
import { tempo as tempoMainnetChain, tempoModerato } from 'viem/tempo/chains';
|
|
4
|
+
import * as RemoteFeePayer from '../tempo/internal/remote-fee-payer.js';
|
|
4
5
|
const knownTempoChains = {
|
|
5
6
|
[tempoMainnetChain.id]: tempoMainnetChain,
|
|
6
7
|
[tempoModerato.id]: tempoModerato,
|
|
7
8
|
};
|
|
9
|
+
/** Creates an HTTP transport for a configured remote fee-payer service. */
|
|
10
|
+
export function remoteFeePayerTransport(config, options = {}) {
|
|
11
|
+
return http(config.url, {
|
|
12
|
+
fetchOptions: { headers: RemoteFeePayer.resolveHeaders(config) },
|
|
13
|
+
...options,
|
|
14
|
+
});
|
|
15
|
+
}
|
|
8
16
|
export function getResolver(parameters) {
|
|
9
|
-
const { chain,
|
|
17
|
+
const { chain, getClient, remoteFeePayer, rpcUrl } = parameters;
|
|
10
18
|
if (getClient) {
|
|
11
19
|
// When a default chain with serializers is provided (e.g. Tempo chain config),
|
|
12
20
|
// ensure user-provided clients inherit those serializers. Without this, clients
|
|
13
21
|
// created without the Tempo chain config will use the default viem serializer,
|
|
14
22
|
// causing errors like "maxFeePerGas is not a valid Legacy Transaction attribute".
|
|
15
|
-
if (!chain?.serializers && !
|
|
23
|
+
if (!chain?.serializers && !remoteFeePayer)
|
|
16
24
|
return getClient;
|
|
17
25
|
return async (params) => {
|
|
18
26
|
const client = await getClient(params);
|
|
19
27
|
let resolvedClient = client;
|
|
20
28
|
// Wrap the client's transport with `withFeePayer` when a fee payer URL is provided.
|
|
21
|
-
if (
|
|
29
|
+
if (remoteFeePayer && client.transport.key !== 'feePayer') {
|
|
22
30
|
const request = client.request.bind(client);
|
|
23
31
|
// The supplied client already owns retries. Keep the relay middleware retry-free so
|
|
24
32
|
// failures are not retried once per nested transport layer.
|
|
25
|
-
const feePayerTransport = withFeePayer(custom({ request: (args) => request(args) }, { retryCount: 0 }),
|
|
33
|
+
const feePayerTransport = withFeePayer(custom({ request: (args) => request(args) }, { retryCount: 0 }), remoteFeePayerTransport(remoteFeePayer, {
|
|
34
|
+
retryCount: client.transport.retryCount,
|
|
35
|
+
}))({
|
|
26
36
|
account: client.account,
|
|
27
37
|
chain: client.chain,
|
|
28
38
|
pollingInterval: client.pollingInterval,
|
|
@@ -56,7 +66,9 @@ export function getResolver(parameters) {
|
|
|
56
66
|
const url = rpcUrl[resolvedChainId];
|
|
57
67
|
if (!url)
|
|
58
68
|
throw new Error(`No \`rpcUrl\` configured for \`chainId\` (${resolvedChainId}).`);
|
|
59
|
-
const transport =
|
|
69
|
+
const transport = remoteFeePayer
|
|
70
|
+
? withFeePayer(http(url), remoteFeePayerTransport(remoteFeePayer))
|
|
71
|
+
: http(url);
|
|
60
72
|
return createClient({
|
|
61
73
|
chain: (knownTempoChains[resolvedChainId] ?? { ...chain, id: resolvedChainId }),
|
|
62
74
|
transport,
|
package/dist/x402/Types.d.ts
CHANGED
|
@@ -26,6 +26,8 @@ export type EvmNetwork = `${typeof evmNetworkPrefix}${number}`;
|
|
|
26
26
|
export declare const paymentRequiredHeader = "PAYMENT-REQUIRED";
|
|
27
27
|
/** HTTP header carrying a base64-encoded x402 payment payload. */
|
|
28
28
|
export declare const paymentSignatureHeader = "PAYMENT-SIGNATURE";
|
|
29
|
+
/** Legacy HTTP header carrying an x402 v1 payment payload. */
|
|
30
|
+
export declare const legacyPaymentSignatureHeader = "X-PAYMENT";
|
|
29
31
|
/** HTTP header carrying a base64-encoded x402 settlement response. */
|
|
30
32
|
export declare const paymentResponseHeader = "PAYMENT-RESPONSE";
|
|
31
33
|
/** Describes the protected resource in x402 v2 payment-required responses. */
|
package/dist/x402/Types.js
CHANGED
|
@@ -14,6 +14,8 @@ export const syntheticChallengeIdPrefix = 'x402:';
|
|
|
14
14
|
export const paymentRequiredHeader = 'PAYMENT-REQUIRED';
|
|
15
15
|
/** HTTP header carrying a base64-encoded x402 payment payload. */
|
|
16
16
|
export const paymentSignatureHeader = 'PAYMENT-SIGNATURE';
|
|
17
|
+
/** Legacy HTTP header carrying an x402 v1 payment payload. */
|
|
18
|
+
export const legacyPaymentSignatureHeader = 'X-PAYMENT';
|
|
17
19
|
/** HTTP header carrying a base64-encoded x402 settlement response. */
|
|
18
20
|
export const paymentResponseHeader = 'PAYMENT-RESPONSE';
|
|
19
21
|
const nonEmptyString = z.string().check(z.minLength(1));
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { x402ResourceServer } from '@x402/core/server';
|
|
2
|
+
import { type MCPToolCallback, type PaymentWrappedHandler, type PaymentWrapperConfig } from '@x402/mcp';
|
|
3
|
+
import * as Negotiator from '../integrations/x402/Negotiator.js';
|
|
4
|
+
type ToolResource = NonNullable<PaymentWrapperConfig['resource']> & {
|
|
5
|
+
url: `mcp://tool/${string}`;
|
|
6
|
+
};
|
|
7
|
+
/** Configuration for {@link mpp}. A canonical MCP tool URL is required as its identity. */
|
|
8
|
+
export type Config = Omit<PaymentWrapperConfig, 'resource'> & Pick<Negotiator.Config, 'realm' | 'secretKey'> & {
|
|
9
|
+
resource: ToolResource;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Creates an MCP tool wrapper that accepts both MPP and x402 payment metadata.
|
|
13
|
+
*
|
|
14
|
+
* Existing x402 credentials and lifecycle hooks continue through `@x402/mcp`.
|
|
15
|
+
* MPP credentials reuse the same x402 requirements, verifier, and facilitator;
|
|
16
|
+
* x402-only hooks in `PaymentWrapperConfig.hooks` therefore run only on x402 calls.
|
|
17
|
+
*/
|
|
18
|
+
export declare function mpp(resourceServer: x402ResourceServer, config: Config): <arguments_ extends Record<string, unknown>>(handler: PaymentWrappedHandler<arguments_>) => MCPToolCallback<arguments_>;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=mcp.d.ts.map
|