agentcash 0.3.4 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/run-server.cjs +93839 -93640
- package/dist/esm/{chunk-FJSHGCIM.js → chunk-DZC5MTYY.js} +2 -2
- package/dist/esm/{chunk-GCS3RSLB.js → chunk-EVE4PTLY.js} +6 -6
- package/dist/esm/chunk-EVE4PTLY.js.map +1 -0
- package/dist/esm/chunk-FM2E2QVT.js +716 -0
- package/dist/esm/chunk-FM2E2QVT.js.map +1 -0
- package/dist/esm/{chunk-MOO4ZEGR.js → chunk-PCCYUD6X.js} +3 -3
- package/dist/esm/{chunk-KD2ZZXT7.js → chunk-PJFATGPH.js} +43 -2
- package/dist/esm/chunk-PJFATGPH.js.map +1 -0
- package/dist/esm/chunk-QCFNW6VN.js +22 -0
- package/dist/esm/chunk-QCFNW6VN.js.map +1 -0
- package/dist/esm/chunk-VVTMCXSK.js +309 -0
- package/dist/esm/chunk-VVTMCXSK.js.map +1 -0
- package/dist/esm/{commands-DUIGMEXV.js → commands-DE2RIAL5.js} +60 -111
- package/dist/esm/commands-DE2RIAL5.js.map +1 -0
- package/dist/esm/{fund-Y2STNDHA.js → fund-IALSHTLH.js} +4 -5
- package/dist/esm/{fund-Y2STNDHA.js.map → fund-IALSHTLH.js.map} +1 -1
- package/dist/esm/index.js +19 -13
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/{install-GFY4JNNJ.js → install-Q4KN5XCP.js} +6 -8
- package/dist/esm/{install-GFY4JNNJ.js.map → install-Q4KN5XCP.js.map} +1 -1
- package/dist/esm/lib.d.ts +68 -3
- package/dist/esm/lib.js +6 -2
- package/dist/esm/{server-7D6YY3KG.js → server-WCNK52XR.js} +153 -531
- package/dist/esm/server-WCNK52XR.js.map +1 -0
- package/dist/esm/shared/operations/index.d.ts +12 -53
- package/dist/esm/shared/operations/index.js +6 -7
- package/package.json +3 -3
- package/dist/esm/chunk-CZBCIWYU.js +0 -48
- package/dist/esm/chunk-CZBCIWYU.js.map +0 -1
- package/dist/esm/chunk-GCS3RSLB.js.map +0 -1
- package/dist/esm/chunk-GIYROB7O.js +0 -210
- package/dist/esm/chunk-GIYROB7O.js.map +0 -1
- package/dist/esm/chunk-KD2ZZXT7.js.map +0 -1
- package/dist/esm/chunk-NQNMVKGY.js +0 -382
- package/dist/esm/chunk-NQNMVKGY.js.map +0 -1
- package/dist/esm/chunk-XXKBL2AC.js +0 -31
- package/dist/esm/chunk-XXKBL2AC.js.map +0 -1
- package/dist/esm/commands-DUIGMEXV.js.map +0 -1
- package/dist/esm/lib-DIhoN8bW.d.ts +0 -115
- package/dist/esm/server-7D6YY3KG.js.map +0 -1
- /package/dist/esm/{chunk-FJSHGCIM.js.map → chunk-DZC5MTYY.js.map} +0 -0
- /package/dist/esm/{chunk-MOO4ZEGR.js.map → chunk-PCCYUD6X.js.map} +0 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import {
|
|
2
|
+
detectPaymentProtocols,
|
|
3
|
+
getTempoBalance,
|
|
4
|
+
mppErr,
|
|
5
|
+
mppOk,
|
|
6
|
+
safeCreateMppCredential,
|
|
7
|
+
safeCreatePaymentPayload,
|
|
8
|
+
safeGetMppChallenge,
|
|
9
|
+
safeGetMppReceipt,
|
|
10
|
+
safeGetPaymentRequired,
|
|
11
|
+
safeGetPaymentSettlement,
|
|
12
|
+
tokenStringToNumber,
|
|
13
|
+
x402Err,
|
|
14
|
+
x402Ok
|
|
15
|
+
} from "./chunk-FM2E2QVT.js";
|
|
16
|
+
import {
|
|
17
|
+
fetchErr,
|
|
18
|
+
fetchOk,
|
|
19
|
+
getBalance,
|
|
20
|
+
log,
|
|
21
|
+
resultFromPromise,
|
|
22
|
+
safeFetch
|
|
23
|
+
} from "./chunk-PJFATGPH.js";
|
|
24
|
+
|
|
25
|
+
// src/server/tools/lib/request.ts
|
|
26
|
+
import z from "zod";
|
|
27
|
+
var requestSchema = z.object({
|
|
28
|
+
url: z.url().describe("The endpoint URL"),
|
|
29
|
+
method: z.enum(["GET", "POST", "PUT", "DELETE", "PATCH"]).optional().describe("HTTP method. Defaults to GET for fetch operations."),
|
|
30
|
+
body: z.unknown().optional().describe("Request body for POST/PUT/PATCH methods"),
|
|
31
|
+
headers: z.record(z.string(), z.string()).optional().describe("Additional headers to include").default({})
|
|
32
|
+
});
|
|
33
|
+
var buildRequest = ({
|
|
34
|
+
input,
|
|
35
|
+
address,
|
|
36
|
+
sessionId,
|
|
37
|
+
provider
|
|
38
|
+
}) => {
|
|
39
|
+
return new Request(input.url, {
|
|
40
|
+
method: input.method ?? "GET",
|
|
41
|
+
body: input.body ? typeof input.body === "string" ? input.body : JSON.stringify(input.body) : void 0,
|
|
42
|
+
headers: {
|
|
43
|
+
...input.body ? { "Content-Type": "application/json" } : {},
|
|
44
|
+
...input.headers,
|
|
45
|
+
...address ? { "X-Wallet-Address": address, "X-Client-ID": provider } : {},
|
|
46
|
+
...sessionId ? { "X-Session-ID": sessionId } : {}
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// src/shared/operations/fetch-with-payment.ts
|
|
52
|
+
import { formatUnits } from "viem";
|
|
53
|
+
function createFetchWithPayment(options) {
|
|
54
|
+
const { surface, clients, paymentMethod, beforePayment } = options;
|
|
55
|
+
return async (request) => {
|
|
56
|
+
const clonedRequest = request.clone();
|
|
57
|
+
const fallbackRequest = request.clone();
|
|
58
|
+
const probeResult = await safeFetch(surface, request);
|
|
59
|
+
if (probeResult.isErr()) {
|
|
60
|
+
return fetchErr(surface, probeResult.error);
|
|
61
|
+
}
|
|
62
|
+
if (probeResult.value.status !== 402) {
|
|
63
|
+
return probeResult.andThen(
|
|
64
|
+
(response2) => fetchOk({ response: response2, paymentInfo: null })
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
const response = probeResult.value;
|
|
68
|
+
if (paymentMethod !== "auto") {
|
|
69
|
+
if (paymentMethod === "mpp") {
|
|
70
|
+
return handleMppPayment(surface, response, clonedRequest, options);
|
|
71
|
+
}
|
|
72
|
+
return handleX402Payment(
|
|
73
|
+
surface,
|
|
74
|
+
response,
|
|
75
|
+
clonedRequest,
|
|
76
|
+
clients.x402,
|
|
77
|
+
beforePayment
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
const available = detectPaymentProtocols(response);
|
|
81
|
+
let preferred;
|
|
82
|
+
if (available.length === 1) {
|
|
83
|
+
preferred = available[0];
|
|
84
|
+
} else {
|
|
85
|
+
preferred = await pickByBalance(surface, response, options);
|
|
86
|
+
}
|
|
87
|
+
const fallback = available.length > 1 ? preferred === "mpp" ? "x402" : "mpp" : null;
|
|
88
|
+
const result = preferred === "mpp" ? await handleMppPayment(surface, response, clonedRequest, options) : await handleX402Payment(
|
|
89
|
+
surface,
|
|
90
|
+
response,
|
|
91
|
+
clonedRequest,
|
|
92
|
+
clients.x402,
|
|
93
|
+
beforePayment
|
|
94
|
+
);
|
|
95
|
+
if (result.isErr() && fallback) {
|
|
96
|
+
return fallback === "mpp" ? handleMppPayment(surface, response, fallbackRequest, options) : handleX402Payment(
|
|
97
|
+
surface,
|
|
98
|
+
response,
|
|
99
|
+
fallbackRequest,
|
|
100
|
+
clients.x402,
|
|
101
|
+
beforePayment
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
return result;
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
async function pickByBalance(surface, response, options) {
|
|
108
|
+
const { account, flags } = options;
|
|
109
|
+
const x402BalanceResult = await resultFromPromise(
|
|
110
|
+
"balance",
|
|
111
|
+
surface,
|
|
112
|
+
getBalance({
|
|
113
|
+
address: account.address,
|
|
114
|
+
flags,
|
|
115
|
+
surface
|
|
116
|
+
}).then((r) => r.isOk() ? r.value.balance : 0),
|
|
117
|
+
() => ({
|
|
118
|
+
cause: "x402_balance",
|
|
119
|
+
message: "Failed to get x402 balance"
|
|
120
|
+
})
|
|
121
|
+
);
|
|
122
|
+
if (x402BalanceResult.isErr()) {
|
|
123
|
+
log.debug("Balance comparison failed, defaulting to mpp");
|
|
124
|
+
return "mpp";
|
|
125
|
+
}
|
|
126
|
+
const x402Balance = x402BalanceResult.value;
|
|
127
|
+
let mppBalance = 0;
|
|
128
|
+
const challengeResult = safeGetMppChallenge(surface, response);
|
|
129
|
+
if (challengeResult.isOk()) {
|
|
130
|
+
const currency = challengeResult.value.request.currency;
|
|
131
|
+
const decimals = challengeResult.value.request.decimals ?? 6;
|
|
132
|
+
if (currency) {
|
|
133
|
+
const tempoResult = await resultFromPromise(
|
|
134
|
+
"tempo",
|
|
135
|
+
surface,
|
|
136
|
+
getTempoBalance({
|
|
137
|
+
address: account.address,
|
|
138
|
+
tokenAddress: currency
|
|
139
|
+
}),
|
|
140
|
+
() => ({
|
|
141
|
+
cause: "tempo_balance",
|
|
142
|
+
message: "Tempo balance check failed"
|
|
143
|
+
})
|
|
144
|
+
);
|
|
145
|
+
if (tempoResult.isOk()) {
|
|
146
|
+
mppBalance = Number(formatUnits(tempoResult.value.balance, decimals));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
log.info(`Protocol selection \u2014 x402: $${x402Balance}, mpp: $${mppBalance}`);
|
|
151
|
+
return x402Balance >= mppBalance ? "x402" : "mpp";
|
|
152
|
+
}
|
|
153
|
+
async function handleX402Payment(surface, response, clonedRequest, client, beforePayment) {
|
|
154
|
+
const paymentRequiredResult = await safeGetPaymentRequired(
|
|
155
|
+
surface,
|
|
156
|
+
client,
|
|
157
|
+
response
|
|
158
|
+
);
|
|
159
|
+
if (paymentRequiredResult.isErr()) {
|
|
160
|
+
return paymentRequiredResult;
|
|
161
|
+
}
|
|
162
|
+
const paymentRequired = paymentRequiredResult.value;
|
|
163
|
+
if (beforePayment) {
|
|
164
|
+
const accept = paymentRequired.accepts[0];
|
|
165
|
+
if (accept) {
|
|
166
|
+
const amount = tokenStringToNumber(accept.amount);
|
|
167
|
+
const hookResult = await resultFromPromise(
|
|
168
|
+
"x402",
|
|
169
|
+
surface,
|
|
170
|
+
beforePayment({
|
|
171
|
+
protocol: "x402",
|
|
172
|
+
amount,
|
|
173
|
+
currency: "USDC",
|
|
174
|
+
network: accept.network
|
|
175
|
+
}),
|
|
176
|
+
(e) => ({
|
|
177
|
+
cause: "payment_already_attempted",
|
|
178
|
+
message: e instanceof Error ? e.message : "Before-payment hook failed"
|
|
179
|
+
})
|
|
180
|
+
);
|
|
181
|
+
if (hookResult.isErr()) {
|
|
182
|
+
return x402Err(surface, hookResult.error);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const paymentPayloadResult = await safeCreatePaymentPayload(
|
|
187
|
+
surface,
|
|
188
|
+
client,
|
|
189
|
+
paymentRequired
|
|
190
|
+
);
|
|
191
|
+
if (paymentPayloadResult.isErr()) {
|
|
192
|
+
return paymentPayloadResult;
|
|
193
|
+
}
|
|
194
|
+
const paymentPayload = paymentPayloadResult.value;
|
|
195
|
+
const paymentHeaders = client.encodePaymentSignatureHeader(paymentPayload);
|
|
196
|
+
if (clonedRequest.headers.has("PAYMENT-SIGNATURE") || clonedRequest.headers.has("X-PAYMENT")) {
|
|
197
|
+
return x402Err(surface, {
|
|
198
|
+
cause: "payment_already_attempted",
|
|
199
|
+
message: "Payment already attempted"
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
for (const [key, value] of Object.entries(paymentHeaders)) {
|
|
203
|
+
clonedRequest.headers.set(key, value);
|
|
204
|
+
}
|
|
205
|
+
clonedRequest.headers.set(
|
|
206
|
+
"Access-Control-Expose-Headers",
|
|
207
|
+
"PAYMENT-RESPONSE,X-PAYMENT-RESPONSE"
|
|
208
|
+
);
|
|
209
|
+
return await safeFetch(surface, clonedRequest).andThen((paidResponse) => {
|
|
210
|
+
const settlementResult = safeGetPaymentSettlement(
|
|
211
|
+
surface,
|
|
212
|
+
client,
|
|
213
|
+
paidResponse
|
|
214
|
+
);
|
|
215
|
+
return x402Ok({
|
|
216
|
+
response: paidResponse,
|
|
217
|
+
paymentInfo: {
|
|
218
|
+
protocol: "x402",
|
|
219
|
+
price: tokenStringToNumber(
|
|
220
|
+
paymentPayload.accepted.amount
|
|
221
|
+
).toLocaleString("en-US", {
|
|
222
|
+
style: "currency",
|
|
223
|
+
currency: "USD"
|
|
224
|
+
}),
|
|
225
|
+
...settlementResult.isOk() ? {
|
|
226
|
+
payment: {
|
|
227
|
+
success: settlementResult.value.success,
|
|
228
|
+
transactionHash: settlementResult.value.transaction
|
|
229
|
+
}
|
|
230
|
+
} : {}
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
async function handleMppPayment(surface, response, clonedRequest, options) {
|
|
236
|
+
const { clients, beforePayment } = options;
|
|
237
|
+
const mpayClient = clients.mpp;
|
|
238
|
+
if (clonedRequest.headers.has("Authorization")) {
|
|
239
|
+
return mppErr(surface, {
|
|
240
|
+
cause: "mpp_payment_already_attempted",
|
|
241
|
+
message: "MPP payment already attempted"
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
const challengeResult = safeGetMppChallenge(surface, response);
|
|
245
|
+
if (challengeResult.isErr()) {
|
|
246
|
+
return challengeResult;
|
|
247
|
+
}
|
|
248
|
+
const challenge = challengeResult.value;
|
|
249
|
+
const amount = challenge.request.amount;
|
|
250
|
+
const decimals = challenge.request.decimals ?? 6;
|
|
251
|
+
const currency = challenge.request.currency;
|
|
252
|
+
if (beforePayment && amount && currency) {
|
|
253
|
+
const numericAmount = Number(formatUnits(BigInt(amount), decimals));
|
|
254
|
+
const hookResult = await resultFromPromise(
|
|
255
|
+
"mpp",
|
|
256
|
+
surface,
|
|
257
|
+
beforePayment({
|
|
258
|
+
protocol: "mpp",
|
|
259
|
+
amount: numericAmount,
|
|
260
|
+
currency,
|
|
261
|
+
network: `tempo:${challenge.method}`
|
|
262
|
+
}),
|
|
263
|
+
(e) => ({
|
|
264
|
+
cause: "mpp_payment_already_attempted",
|
|
265
|
+
message: e instanceof Error ? e.message : "Before-payment hook failed"
|
|
266
|
+
})
|
|
267
|
+
);
|
|
268
|
+
if (hookResult.isErr()) {
|
|
269
|
+
return mppErr(surface, hookResult.error);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
const credentialResult = await safeCreateMppCredential(
|
|
273
|
+
surface,
|
|
274
|
+
mpayClient,
|
|
275
|
+
response
|
|
276
|
+
);
|
|
277
|
+
if (credentialResult.isErr()) {
|
|
278
|
+
return credentialResult;
|
|
279
|
+
}
|
|
280
|
+
const credential = credentialResult.value;
|
|
281
|
+
clonedRequest.headers.set("Authorization", credential);
|
|
282
|
+
return await safeFetch(surface, clonedRequest).andThen((paidResponse) => {
|
|
283
|
+
const receiptResult = safeGetMppReceipt(surface, paidResponse);
|
|
284
|
+
const priceDisplay = amount ? Number(formatUnits(BigInt(amount), decimals)).toLocaleString("en-US", {
|
|
285
|
+
style: "currency",
|
|
286
|
+
currency: "USD"
|
|
287
|
+
}) : void 0;
|
|
288
|
+
return mppOk({
|
|
289
|
+
response: paidResponse,
|
|
290
|
+
paymentInfo: {
|
|
291
|
+
protocol: "mpp",
|
|
292
|
+
...priceDisplay ? { price: priceDisplay } : {},
|
|
293
|
+
...receiptResult.isOk() ? {
|
|
294
|
+
payment: {
|
|
295
|
+
success: true,
|
|
296
|
+
transactionHash: receiptResult.value.reference
|
|
297
|
+
}
|
|
298
|
+
} : {}
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
export {
|
|
305
|
+
requestSchema,
|
|
306
|
+
buildRequest,
|
|
307
|
+
createFetchWithPayment
|
|
308
|
+
};
|
|
309
|
+
//# sourceMappingURL=chunk-VVTMCXSK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/server/tools/lib/request.ts","../../src/shared/operations/fetch-with-payment.ts"],"sourcesContent":["import z from 'zod';\n\nimport type { Address } from 'viem';\n\nexport const requestSchema = z.object({\n url: z.url().describe('The endpoint URL'),\n method: z\n .enum(['GET', 'POST', 'PUT', 'DELETE', 'PATCH'])\n .optional()\n .describe('HTTP method. Defaults to GET for fetch operations.'),\n body: z\n .unknown()\n .optional()\n .describe('Request body for POST/PUT/PATCH methods'),\n headers: z\n .record(z.string(), z.string())\n .optional()\n .describe('Additional headers to include')\n .default({}),\n});\n\ninterface BuildRequestProps {\n input: z.infer<typeof requestSchema>;\n address?: Address;\n sessionId?: string;\n provider?: string;\n}\n\nexport const buildRequest = ({\n input,\n address,\n sessionId,\n provider,\n}: BuildRequestProps) => {\n return new Request(input.url, {\n method: input.method ?? 'GET',\n body: input.body\n ? typeof input.body === 'string'\n ? input.body\n : JSON.stringify(input.body)\n : undefined,\n headers: {\n ...(input.body ? { 'Content-Type': 'application/json' } : {}),\n ...input.headers,\n ...(address\n ? { 'X-Wallet-Address': address, 'X-Client-ID': provider }\n : {}),\n ...(sessionId ? { 'X-Session-ID': sessionId } : {}),\n },\n });\n};\n","import { formatUnits } from 'viem';\n\nimport type { x402HTTPClient } from '@x402/core/client';\nimport type { Mpay } from 'mpay/client';\nimport type { Address } from 'viem';\nimport type { GlobalFlags } from '@/types';\n\nimport { resultFromPromise } from '@agentcash/neverthrow';\n\nimport { fetchErr, fetchOk, safeFetch } from '@/shared/neverthrow/fetch';\nimport {\n safeCreatePaymentPayload,\n safeGetPaymentRequired,\n safeGetPaymentSettlement,\n x402Err,\n x402Ok,\n} from '@/shared/neverthrow/x402';\nimport {\n safeGetMppChallenge,\n safeCreateMppCredential,\n safeGetMppReceipt,\n mppErr,\n mppOk,\n} from '@/shared/neverthrow/mpp';\n\nimport { log } from '@/shared/log';\nimport { detectPaymentProtocols } from '@/shared/protocol';\nimport { tokenStringToNumber } from '@/shared/token';\nimport { getBalance } from '@/shared/balance';\nimport { getTempoBalance } from '@/shared/tempo-balance';\n\n/**\n * Hook called before a payment is executed.\n * Throw to abort. Return to proceed.\n * Matches existing checkBalance/checkTempoBalance throw-to-abort behavior.\n */\nexport type BeforePaymentHook = (ctx: {\n protocol: 'x402' | 'mpp';\n amount: number;\n currency: string;\n network: string;\n}) => Promise<void>;\n\nexport interface PaymentClients {\n x402: x402HTTPClient;\n mpp: ReturnType<typeof Mpay.create>;\n}\n\nexport interface PaymentInfo {\n protocol: 'x402' | 'mpp';\n price?: string;\n payment?: {\n success: boolean;\n transactionHash?: string;\n };\n}\n\nexport interface FetchWithPaymentResult {\n response: Response;\n paymentInfo: PaymentInfo | null;\n}\n\nexport interface FetchWithPaymentOptions {\n surface: string;\n clients: PaymentClients;\n paymentMethod: 'x402' | 'mpp' | 'auto';\n account: { address: Address };\n flags: GlobalFlags;\n beforePayment?: BeforePaymentHook;\n}\n\n/**\n * Create a fetch function with automatic dual-protocol payment handling.\n *\n * 1. Makes initial request\n * 2. If 402 response, detects protocol(s)\n * 3. Calls beforePayment hook (for balance checks)\n * 4. Creates payment credential/payload\n * 5. Retries request with payment headers\n */\nexport function createFetchWithPayment(options: FetchWithPaymentOptions) {\n const { surface, clients, paymentMethod, beforePayment } = options;\n\n return async (request: Request) => {\n const clonedRequest = request.clone();\n const fallbackRequest = request.clone();\n\n const probeResult = await safeFetch(surface, request);\n\n if (probeResult.isErr()) {\n return fetchErr(surface, probeResult.error);\n }\n\n // Not a 402 response — return as-is\n if (probeResult.value.status !== 402) {\n return probeResult.andThen(response =>\n fetchOk<FetchWithPaymentResult>({ response, paymentInfo: null })\n );\n }\n\n const response = probeResult.value;\n\n // User explicitly chose a protocol — use that, no fallback\n if (paymentMethod !== 'auto') {\n if (paymentMethod === 'mpp') {\n return handleMppPayment(surface, response, clonedRequest, options);\n }\n return handleX402Payment(\n surface,\n response,\n clonedRequest,\n clients.x402,\n beforePayment\n );\n }\n\n // Auto: detect available protocols, pick by higher balance\n const available = detectPaymentProtocols(response);\n\n let preferred: 'x402' | 'mpp';\n\n if (available.length === 1) {\n preferred = available[0]!;\n } else {\n // Both protocols available — pick by balance\n preferred = await pickByBalance(surface, response, options);\n }\n\n const fallback =\n available.length > 1 ? (preferred === 'mpp' ? 'x402' : 'mpp') : null;\n\n const result =\n preferred === 'mpp'\n ? await handleMppPayment(surface, response, clonedRequest, options)\n : await handleX402Payment(\n surface,\n response,\n clonedRequest,\n clients.x402,\n beforePayment\n );\n\n if (result.isErr() && fallback) {\n // Preferred failed — try fallback with a fresh request clone\n return fallback === 'mpp'\n ? handleMppPayment(surface, response, fallbackRequest, options)\n : handleX402Payment(\n surface,\n response,\n fallbackRequest,\n clients.x402,\n beforePayment\n );\n }\n\n return result;\n };\n}\n\n/**\n * Pick the preferred protocol by comparing wallet balances.\n * Falls back to 'mpp' if both balances fail to fetch.\n */\nasync function pickByBalance(\n surface: string,\n response: Response,\n options: FetchWithPaymentOptions\n): Promise<'x402' | 'mpp'> {\n const { account, flags } = options;\n\n // Get x402 (USDC on Base) balance\n const x402BalanceResult = await resultFromPromise(\n 'balance',\n surface,\n getBalance({\n address: account.address,\n flags,\n surface,\n }).then(r => (r.isOk() ? r.value.balance : 0)),\n () => ({\n cause: 'x402_balance' as const,\n message: 'Failed to get x402 balance',\n })\n );\n\n if (x402BalanceResult.isErr()) {\n log.debug('Balance comparison failed, defaulting to mpp');\n return 'mpp';\n }\n\n const x402Balance = x402BalanceResult.value;\n\n // Get MPP (Tempo) balance — need token address from the challenge\n let mppBalance = 0;\n const challengeResult = safeGetMppChallenge(surface, response);\n if (challengeResult.isOk()) {\n const currency = challengeResult.value.request.currency as\n | string\n | undefined;\n const decimals =\n (challengeResult.value.request.decimals as number | undefined) ?? 6;\n if (currency) {\n const tempoResult = await resultFromPromise(\n 'tempo',\n surface,\n getTempoBalance({\n address: account.address,\n tokenAddress: currency as Address,\n }),\n () => ({\n cause: 'tempo_balance' as const,\n message: 'Tempo balance check failed',\n })\n );\n if (tempoResult.isOk()) {\n mppBalance = Number(formatUnits(tempoResult.value.balance, decimals));\n }\n }\n }\n\n log.info(`Protocol selection — x402: $${x402Balance}, mpp: $${mppBalance}`);\n return x402Balance >= mppBalance ? 'x402' : 'mpp';\n}\n\nasync function handleX402Payment(\n surface: string,\n response: Response,\n clonedRequest: Request,\n client: x402HTTPClient,\n beforePayment?: BeforePaymentHook\n) {\n const paymentRequiredResult = await safeGetPaymentRequired(\n surface,\n client,\n response\n );\n\n if (paymentRequiredResult.isErr()) {\n return paymentRequiredResult;\n }\n\n const paymentRequired = paymentRequiredResult.value;\n\n // Call beforePayment hook (e.g. balance check) before signing\n if (beforePayment) {\n const accept = paymentRequired.accepts[0];\n if (accept) {\n const amount = tokenStringToNumber(accept.amount);\n const hookResult = await resultFromPromise(\n 'x402',\n surface,\n beforePayment({\n protocol: 'x402',\n amount,\n currency: 'USDC',\n network: accept.network,\n }),\n e => ({\n cause: 'payment_already_attempted' as const,\n message:\n e instanceof Error ? e.message : 'Before-payment hook failed',\n })\n );\n if (hookResult.isErr()) {\n return x402Err(surface, hookResult.error);\n }\n }\n }\n\n const paymentPayloadResult = await safeCreatePaymentPayload(\n surface,\n client,\n paymentRequired\n );\n\n if (paymentPayloadResult.isErr()) {\n return paymentPayloadResult;\n }\n\n const paymentPayload = paymentPayloadResult.value;\n\n // Encode payment header\n const paymentHeaders = client.encodePaymentSignatureHeader(paymentPayload);\n\n // Check if this is already a retry to prevent infinite loops\n if (\n clonedRequest.headers.has('PAYMENT-SIGNATURE') ||\n clonedRequest.headers.has('X-PAYMENT')\n ) {\n return x402Err(surface, {\n cause: 'payment_already_attempted',\n message: 'Payment already attempted',\n });\n }\n\n // Add payment headers to cloned request\n for (const [key, value] of Object.entries(paymentHeaders)) {\n clonedRequest.headers.set(key, value);\n }\n clonedRequest.headers.set(\n 'Access-Control-Expose-Headers',\n 'PAYMENT-RESPONSE,X-PAYMENT-RESPONSE'\n );\n\n // Retry the request with payment\n return await safeFetch(surface, clonedRequest).andThen(paidResponse => {\n const settlementResult = safeGetPaymentSettlement(\n surface,\n client,\n paidResponse\n );\n\n return x402Ok<FetchWithPaymentResult>({\n response: paidResponse,\n paymentInfo: {\n protocol: 'x402',\n price: tokenStringToNumber(\n paymentPayload.accepted.amount\n ).toLocaleString('en-US', {\n style: 'currency',\n currency: 'USD',\n }),\n ...(settlementResult.isOk()\n ? {\n payment: {\n success: settlementResult.value.success,\n transactionHash: settlementResult.value.transaction,\n },\n }\n : {}),\n },\n });\n });\n}\n\nasync function handleMppPayment(\n surface: string,\n response: Response,\n clonedRequest: Request,\n options: FetchWithPaymentOptions\n) {\n const { clients, beforePayment } = options;\n const mpayClient = clients.mpp;\n\n // Prevent retry loops\n if (clonedRequest.headers.has('Authorization')) {\n return mppErr(surface, {\n cause: 'mpp_payment_already_attempted',\n message: 'MPP payment already attempted',\n });\n }\n\n // Parse the challenge from the WWW-Authenticate header\n const challengeResult = safeGetMppChallenge(surface, response);\n\n if (challengeResult.isErr()) {\n return challengeResult;\n }\n\n const challenge = challengeResult.value;\n\n // Extract payment info from challenge request\n const amount = challenge.request.amount as string | undefined;\n const decimals = (challenge.request.decimals as number | undefined) ?? 6;\n const currency = challenge.request.currency as string | undefined;\n\n // Call beforePayment hook (e.g. balance check)\n if (beforePayment && amount && currency) {\n const numericAmount = Number(formatUnits(BigInt(amount), decimals));\n const hookResult = await resultFromPromise(\n 'mpp',\n surface,\n beforePayment({\n protocol: 'mpp',\n amount: numericAmount,\n currency,\n network: `tempo:${challenge.method}`,\n }),\n e => ({\n cause: 'mpp_payment_already_attempted' as const,\n message: e instanceof Error ? e.message : 'Before-payment hook failed',\n })\n );\n if (hookResult.isErr()) {\n return mppErr(surface, hookResult.error);\n }\n }\n\n // Create credential (signs transaction on Tempo)\n const credentialResult = await safeCreateMppCredential(\n surface,\n mpayClient,\n response\n );\n\n if (credentialResult.isErr()) {\n return credentialResult;\n }\n\n const credential = credentialResult.value;\n\n // Set Authorization header on cloned request\n clonedRequest.headers.set('Authorization', credential);\n\n // Retry the fetch with the credential\n return await safeFetch(surface, clonedRequest).andThen(paidResponse => {\n // Parse the receipt for transaction hash\n const receiptResult = safeGetMppReceipt(surface, paidResponse);\n\n const priceDisplay = amount\n ? Number(formatUnits(BigInt(amount), decimals)).toLocaleString('en-US', {\n style: 'currency',\n currency: 'USD',\n })\n : undefined;\n\n return mppOk<FetchWithPaymentResult>({\n response: paidResponse,\n paymentInfo: {\n protocol: 'mpp',\n ...(priceDisplay ? { price: priceDisplay } : {}),\n ...(receiptResult.isOk()\n ? {\n payment: {\n success: true,\n transactionHash: receiptResult.value.reference,\n },\n }\n : {}),\n },\n });\n });\n}\n"],"mappings":"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","names":["response"]}
|
|
@@ -1,35 +1,34 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildRequest,
|
|
3
|
-
requestSchema
|
|
4
|
-
} from "./chunk-XXKBL2AC.js";
|
|
5
|
-
import {
|
|
6
3
|
createFetchWithPayment,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} from "./chunk-GIYROB7O.js";
|
|
4
|
+
requestSchema
|
|
5
|
+
} from "./chunk-VVTMCXSK.js";
|
|
10
6
|
import {
|
|
7
|
+
TEMPO_RPC_URL,
|
|
11
8
|
checkEndpoint,
|
|
12
9
|
discoverResources,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
} from "./chunk-
|
|
16
|
-
import "./chunk-
|
|
10
|
+
getWalletInfo,
|
|
11
|
+
submitErrorReport
|
|
12
|
+
} from "./chunk-FM2E2QVT.js";
|
|
13
|
+
import "./chunk-DZC5MTYY.js";
|
|
17
14
|
import {
|
|
18
15
|
DEFAULT_NETWORK,
|
|
19
16
|
getWallet,
|
|
20
17
|
redeemInviteCode,
|
|
21
|
-
safeParseJson
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
safeParseJson,
|
|
19
|
+
toJsonObject
|
|
20
|
+
} from "./chunk-EVE4PTLY.js";
|
|
24
21
|
import {
|
|
25
22
|
safeParseResponse
|
|
26
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-PJFATGPH.js";
|
|
27
24
|
import "./chunk-ISR6DJ53.js";
|
|
28
25
|
|
|
29
26
|
// src/cli/commands/fetch.ts
|
|
30
27
|
import { randomBytes } from "crypto";
|
|
31
28
|
import { x402Client, x402HTTPClient } from "@x402/core/client";
|
|
32
29
|
import { ExactEvmScheme } from "@x402/evm/exact/client";
|
|
30
|
+
import { Mpay, tempo as tempoMethod } from "mpay/client";
|
|
31
|
+
import { tempo } from "viem/chains";
|
|
33
32
|
|
|
34
33
|
// src/cli/output/types.ts
|
|
35
34
|
var errorCodeToExitCode = {
|
|
@@ -233,7 +232,7 @@ function parseRequestInput(surface, args, flags) {
|
|
|
233
232
|
}
|
|
234
233
|
const inputResult = requestSchema.safeParse({
|
|
235
234
|
url: args.url,
|
|
236
|
-
method: args.method
|
|
235
|
+
method: args.method,
|
|
237
236
|
body: parsedBody,
|
|
238
237
|
headers: parsedHeaders ?? {}
|
|
239
238
|
});
|
|
@@ -262,20 +261,34 @@ async function fetchCommand(args, flags) {
|
|
|
262
261
|
{ network: DEFAULT_NETWORK, client: new ExactEvmScheme(account) }
|
|
263
262
|
]
|
|
264
263
|
});
|
|
265
|
-
const
|
|
264
|
+
const x402HttpClient = new x402HTTPClient(coreClient);
|
|
265
|
+
const mpayClient = Mpay.create({
|
|
266
|
+
methods: [
|
|
267
|
+
tempoMethod({
|
|
268
|
+
account,
|
|
269
|
+
rpcUrl: { [tempo.id]: TEMPO_RPC_URL }
|
|
270
|
+
})
|
|
271
|
+
]
|
|
272
|
+
});
|
|
266
273
|
const provider = flags.provider ?? account.address;
|
|
274
|
+
const paymentMethod = args.paymentMethod ?? "auto";
|
|
267
275
|
const request = buildRequest({
|
|
268
276
|
input,
|
|
269
277
|
address: account.address,
|
|
270
278
|
sessionId,
|
|
271
279
|
provider
|
|
272
280
|
});
|
|
273
|
-
const
|
|
274
|
-
|
|
281
|
+
const fetchResult = await createFetchWithPayment({
|
|
282
|
+
surface: SURFACE,
|
|
283
|
+
clients: { x402: x402HttpClient, mpp: mpayClient },
|
|
284
|
+
paymentMethod,
|
|
285
|
+
account,
|
|
286
|
+
flags
|
|
287
|
+
})(request);
|
|
275
288
|
if (fetchResult.isErr()) {
|
|
276
289
|
return outputAndExit(fromNeverthrowError(fetchResult), flags);
|
|
277
290
|
}
|
|
278
|
-
const { response,
|
|
291
|
+
const { response, paymentInfo } = fetchResult.value;
|
|
279
292
|
if (!response.ok) {
|
|
280
293
|
const parseResult = await safeParseResponse(SURFACE, response);
|
|
281
294
|
const details = { statusCode: response.status };
|
|
@@ -304,23 +317,11 @@ async function fetchCommand(args, flags) {
|
|
|
304
317
|
if (parseResponseResult.isErr()) {
|
|
305
318
|
return outputAndExit(fromNeverthrowError(parseResponseResult), flags);
|
|
306
319
|
}
|
|
307
|
-
const settlementResult = safeGetPaymentSettlement(SURFACE, client, response);
|
|
308
320
|
const data = parseResponseResult.value.type === "json" ? parseResponseResult.value.data : parseResponseResult.value.type === "text" ? parseResponseResult.value.data : { type: parseResponseResult.value.type };
|
|
309
|
-
const metadata =
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
).toLocaleString("en-US", {
|
|
314
|
-
style: "currency",
|
|
315
|
-
currency: "USD"
|
|
316
|
-
})
|
|
317
|
-
} : {},
|
|
318
|
-
...settlementResult.isOk() ? {
|
|
319
|
-
payment: {
|
|
320
|
-
success: settlementResult.value.success,
|
|
321
|
-
transactionHash: settlementResult.value.transaction
|
|
322
|
-
}
|
|
323
|
-
} : {}
|
|
321
|
+
const metadata = paymentInfo ? {
|
|
322
|
+
protocol: paymentInfo.protocol,
|
|
323
|
+
...paymentInfo.price ? { price: paymentInfo.price } : {},
|
|
324
|
+
...paymentInfo.payment ? { payment: paymentInfo.payment } : {}
|
|
324
325
|
} : void 0;
|
|
325
326
|
outputAndExit(successResponse(data, metadata), flags);
|
|
326
327
|
}
|
|
@@ -332,96 +333,44 @@ async function checkCommand(args, flags) {
|
|
|
332
333
|
const { account } = await getWalletOrExit(flags);
|
|
333
334
|
const sessionId = randomBytes2(16).toString("hex");
|
|
334
335
|
const input = parseRequestInput(SURFACE2, args, flags);
|
|
335
|
-
const
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
336
|
+
const result = await checkEndpoint({
|
|
337
|
+
surface: SURFACE2,
|
|
338
|
+
url: input.url,
|
|
339
|
+
methods: input.method ? [input.method] : void 0,
|
|
340
|
+
body: input.body,
|
|
341
|
+
headers: {
|
|
342
|
+
...input.headers ?? {},
|
|
343
|
+
"X-Wallet-Address": account.address,
|
|
344
|
+
"X-Session-ID": sessionId
|
|
345
|
+
},
|
|
346
|
+
includeMethodErrors: !!input.method
|
|
339
347
|
});
|
|
340
|
-
|
|
341
|
-
if (result.isErr()) {
|
|
342
|
-
return outputAndExit(fromNeverthrowError(result), flags);
|
|
343
|
-
}
|
|
344
|
-
const value = result.value;
|
|
345
|
-
if (value instanceof Response) {
|
|
346
|
-
const response = value;
|
|
347
|
-
const parseResult = await safeParseResponse(SURFACE2, response);
|
|
348
|
-
const details = { statusCode: response.status };
|
|
349
|
-
if (parseResult.isOk()) {
|
|
350
|
-
const { type } = parseResult.value;
|
|
351
|
-
if (type === "json") {
|
|
352
|
-
details.body = parseResult.value.data;
|
|
353
|
-
} else if (type === "text") {
|
|
354
|
-
details.body = parseResult.value.data;
|
|
355
|
-
} else {
|
|
356
|
-
details.bodyType = type;
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
return outputAndExit(
|
|
360
|
-
errorResponse({
|
|
361
|
-
code: "HTTP_ERROR",
|
|
362
|
-
message: `HTTP ${response.status}: ${response.statusText}`,
|
|
363
|
-
surface: SURFACE2,
|
|
364
|
-
cause: "http",
|
|
365
|
-
details
|
|
366
|
-
}),
|
|
367
|
-
flags
|
|
368
|
-
);
|
|
369
|
-
}
|
|
370
|
-
if ("requiresPayment" in value && value.requiresPayment) {
|
|
371
|
-
return outputAndExit(
|
|
372
|
-
successResponse({
|
|
373
|
-
requiresPayment: true,
|
|
374
|
-
statusCode: value.statusCode,
|
|
375
|
-
routeDetails: value.routeDetails
|
|
376
|
-
}),
|
|
377
|
-
flags
|
|
378
|
-
);
|
|
379
|
-
}
|
|
380
|
-
if ("parsedResponse" in value) {
|
|
381
|
-
const { parsedResponse } = value;
|
|
382
|
-
const data = parsedResponse.type === "json" ? parsedResponse.data : parsedResponse.type === "text" ? parsedResponse.data : { type: parsedResponse.type };
|
|
383
|
-
return outputAndExit(
|
|
384
|
-
successResponse({
|
|
385
|
-
requiresPayment: false,
|
|
386
|
-
statusCode: value.statusCode,
|
|
387
|
-
data
|
|
388
|
-
}),
|
|
389
|
-
flags
|
|
390
|
-
);
|
|
391
|
-
}
|
|
392
|
-
return outputAndExit(
|
|
393
|
-
errorResponse({
|
|
394
|
-
code: "GENERAL_ERROR",
|
|
395
|
-
message: "Unexpected response format",
|
|
396
|
-
surface: SURFACE2,
|
|
397
|
-
cause: "unknown"
|
|
398
|
-
}),
|
|
399
|
-
flags
|
|
400
|
-
);
|
|
348
|
+
return outputAndExit(successResponse(toJsonObject(result)), flags);
|
|
401
349
|
}
|
|
402
350
|
|
|
403
351
|
// src/cli/commands/discover.ts
|
|
404
352
|
async function discoverCommand(args, flags) {
|
|
405
353
|
const result = await discoverResources("cli:discover", args.url);
|
|
406
|
-
if (result
|
|
354
|
+
if (result) {
|
|
407
355
|
return outputAndExit(
|
|
408
356
|
successResponse({
|
|
409
357
|
found: true,
|
|
410
|
-
origin: result.
|
|
411
|
-
source: result.
|
|
412
|
-
endpoints: result.
|
|
413
|
-
...result.
|
|
358
|
+
origin: result.origin,
|
|
359
|
+
source: result.source,
|
|
360
|
+
endpoints: result.endpoints.map((e) => ({ ...e })),
|
|
361
|
+
...result.instructions ? { instructions: result.instructions } : {}
|
|
414
362
|
}),
|
|
415
363
|
flags
|
|
416
364
|
);
|
|
417
365
|
}
|
|
366
|
+
const origin = URL.canParse(args.url) ? new URL(args.url).origin : args.url;
|
|
418
367
|
return outputAndExit(
|
|
419
368
|
errorResponse({
|
|
420
369
|
code: "GENERAL_ERROR",
|
|
421
|
-
message:
|
|
422
|
-
surface:
|
|
423
|
-
cause:
|
|
424
|
-
details: { origin
|
|
370
|
+
message: `No OpenAPI spec found for ${origin}. Tried: /openapi.json, /.well-known/openapi.json, /.well-known/x402, /.well-known/mpp`,
|
|
371
|
+
surface: "cli:discover",
|
|
372
|
+
cause: "not_found",
|
|
373
|
+
details: { origin }
|
|
425
374
|
}),
|
|
426
375
|
flags
|
|
427
376
|
);
|
|
@@ -503,7 +452,7 @@ async function reportErrorCommand(args, flags) {
|
|
|
503
452
|
|
|
504
453
|
// src/cli/commands/server.ts
|
|
505
454
|
async function serverCommand(flags) {
|
|
506
|
-
const { startServer } = await import("./server-
|
|
455
|
+
const { startServer } = await import("./server-WCNK52XR.js");
|
|
507
456
|
await startServer(flags);
|
|
508
457
|
}
|
|
509
458
|
export {
|
|
@@ -515,4 +464,4 @@ export {
|
|
|
515
464
|
walletInfoCommand,
|
|
516
465
|
walletRedeemCommand
|
|
517
466
|
};
|
|
518
|
-
//# sourceMappingURL=commands-
|
|
467
|
+
//# sourceMappingURL=commands-DE2RIAL5.js.map
|