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,716 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MCP_VERSION
|
|
3
|
+
} from "./chunk-DZC5MTYY.js";
|
|
4
|
+
import {
|
|
5
|
+
err,
|
|
6
|
+
getBalance,
|
|
7
|
+
getBaseUrl,
|
|
8
|
+
getDepositLink,
|
|
9
|
+
log,
|
|
10
|
+
ok,
|
|
11
|
+
resultFromPromise,
|
|
12
|
+
resultFromThrowable,
|
|
13
|
+
safeFetch,
|
|
14
|
+
safeFetchJson,
|
|
15
|
+
safeParseResponse
|
|
16
|
+
} from "./chunk-PJFATGPH.js";
|
|
17
|
+
|
|
18
|
+
// src/shared/operations/check-endpoint.ts
|
|
19
|
+
import { x402Client, x402HTTPClient } from "@x402/core/client";
|
|
20
|
+
|
|
21
|
+
// src/shared/neverthrow/x402/index.ts
|
|
22
|
+
import { createSIWxPayload } from "@x402/extensions/sign-in-with-x";
|
|
23
|
+
var errorType = "x402";
|
|
24
|
+
var x402Ok = (value) => ok(value);
|
|
25
|
+
var x402Err = (cause, error) => err(errorType, cause, error);
|
|
26
|
+
var x402ResultFromPromise = (surface, promise, error) => resultFromPromise(errorType, surface, promise, error);
|
|
27
|
+
var x402ResultFromThrowable = (surface, fn, error) => resultFromThrowable(errorType, surface, fn, error);
|
|
28
|
+
var safeGetPaymentRequired = (surface, client, response) => {
|
|
29
|
+
return x402ResultFromPromise(
|
|
30
|
+
surface,
|
|
31
|
+
response.json().then(
|
|
32
|
+
(json) => client.getPaymentRequiredResponse(
|
|
33
|
+
(name) => response.headers.get(name),
|
|
34
|
+
json
|
|
35
|
+
),
|
|
36
|
+
() => client.getPaymentRequiredResponse((name) => response.headers.get(name))
|
|
37
|
+
),
|
|
38
|
+
(error) => ({
|
|
39
|
+
cause: "parse_payment_required",
|
|
40
|
+
message: error instanceof Error ? error.message : "Failed to parse payment required"
|
|
41
|
+
})
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
var safeCreatePaymentPayload = (surface, client, paymentRequired) => {
|
|
45
|
+
return x402ResultFromPromise(
|
|
46
|
+
surface,
|
|
47
|
+
client.createPaymentPayload(paymentRequired),
|
|
48
|
+
(error) => ({
|
|
49
|
+
cause: "create_payment_payload",
|
|
50
|
+
message: error instanceof Error ? error.message : "Failed to create payment payload"
|
|
51
|
+
})
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
var safeGetPaymentSettlement = (surface, client, response) => {
|
|
55
|
+
return x402ResultFromThrowable(
|
|
56
|
+
surface,
|
|
57
|
+
() => client.getPaymentSettleResponse((name) => response.headers.get(name)),
|
|
58
|
+
(error) => ({
|
|
59
|
+
cause: "get_payment_settlement",
|
|
60
|
+
message: error instanceof Error ? error.message : "Failed to get payment settlement"
|
|
61
|
+
})
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
var safeCreateSIWxPayload = (surface, serverInfo, signer) => {
|
|
65
|
+
return x402ResultFromPromise(
|
|
66
|
+
surface,
|
|
67
|
+
createSIWxPayload(serverInfo, signer),
|
|
68
|
+
(error) => ({
|
|
69
|
+
cause: "create_siwx_payload",
|
|
70
|
+
message: error instanceof Error ? error.message : "Failed to create SIWX payload"
|
|
71
|
+
})
|
|
72
|
+
);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// src/shared/neverthrow/mpp/index.ts
|
|
76
|
+
import { Challenge, Receipt } from "mpay";
|
|
77
|
+
var errorType2 = "mpp";
|
|
78
|
+
var mppOk = (value) => ok(value);
|
|
79
|
+
var mppErr = (surface, error) => err(errorType2, surface, error);
|
|
80
|
+
var mppResultFromPromise = (surface, promise, error) => resultFromPromise(errorType2, surface, promise, error);
|
|
81
|
+
var mppResultFromThrowable = (surface, fn, error) => resultFromThrowable(errorType2, surface, fn, error);
|
|
82
|
+
var safeGetMppChallenge = (surface, response) => {
|
|
83
|
+
return mppResultFromThrowable(
|
|
84
|
+
surface,
|
|
85
|
+
() => Challenge.fromResponse(response),
|
|
86
|
+
(error) => ({
|
|
87
|
+
cause: "parse_mpp_challenge",
|
|
88
|
+
message: error instanceof Error ? error.message : "Failed to parse MPP challenge from response"
|
|
89
|
+
})
|
|
90
|
+
);
|
|
91
|
+
};
|
|
92
|
+
var safeCreateMppCredential = (surface, mpayClient, response) => {
|
|
93
|
+
return mppResultFromPromise(
|
|
94
|
+
surface,
|
|
95
|
+
mpayClient.createCredential(response),
|
|
96
|
+
(error) => ({
|
|
97
|
+
cause: "create_mpp_credential",
|
|
98
|
+
message: error instanceof Error ? error.message : "Failed to create MPP credential"
|
|
99
|
+
})
|
|
100
|
+
);
|
|
101
|
+
};
|
|
102
|
+
var safeGetMppReceipt = (surface, response) => {
|
|
103
|
+
return mppResultFromThrowable(
|
|
104
|
+
surface,
|
|
105
|
+
() => Receipt.fromResponse(response),
|
|
106
|
+
(error) => ({
|
|
107
|
+
cause: "parse_mpp_receipt",
|
|
108
|
+
message: error instanceof Error ? error.message : "Failed to parse MPP receipt from response"
|
|
109
|
+
})
|
|
110
|
+
);
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
// src/shared/protocol.ts
|
|
114
|
+
function detectPaymentProtocols(response) {
|
|
115
|
+
const protocols = [];
|
|
116
|
+
const wwwAuth = response.headers.get("WWW-Authenticate");
|
|
117
|
+
if (wwwAuth?.startsWith("Payment")) {
|
|
118
|
+
protocols.push("mpp");
|
|
119
|
+
}
|
|
120
|
+
const paymentRequired = response.headers.get("payment-required");
|
|
121
|
+
if (paymentRequired) {
|
|
122
|
+
protocols.push("x402");
|
|
123
|
+
}
|
|
124
|
+
if (protocols.length === 0) {
|
|
125
|
+
protocols.push("x402");
|
|
126
|
+
}
|
|
127
|
+
return protocols;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// src/shared/openapi-cache.ts
|
|
131
|
+
var specCache = /* @__PURE__ */ new Map();
|
|
132
|
+
async function fetchOpenApiSpec(origin) {
|
|
133
|
+
const cached = specCache.get(origin);
|
|
134
|
+
if (cached) return cached;
|
|
135
|
+
const uniqueUrls = [
|
|
136
|
+
`${origin}/openapi.json`,
|
|
137
|
+
`${origin}/.well-known/openapi.json`,
|
|
138
|
+
`${origin}/.well-known/x402`,
|
|
139
|
+
`${origin}/.well-known/mpp`
|
|
140
|
+
];
|
|
141
|
+
for (const url of uniqueUrls) {
|
|
142
|
+
log.debug(`Fetching OpenAPI spec from: ${url}`);
|
|
143
|
+
const fetchResult = await safeFetch(
|
|
144
|
+
"fetchOpenApiSpec",
|
|
145
|
+
new Request(url, { headers: { Accept: "application/json" } })
|
|
146
|
+
);
|
|
147
|
+
if (fetchResult.isErr()) {
|
|
148
|
+
log.debug(`Failed to fetch OpenAPI spec from: ${url}`);
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
const response = fetchResult.value;
|
|
152
|
+
if (!response.ok) continue;
|
|
153
|
+
const jsonResult = await resultFromPromise(
|
|
154
|
+
"json",
|
|
155
|
+
"fetchOpenApiSpec",
|
|
156
|
+
response.json(),
|
|
157
|
+
() => ({
|
|
158
|
+
cause: "parse",
|
|
159
|
+
message: `Failed to parse JSON from: ${url}`
|
|
160
|
+
})
|
|
161
|
+
);
|
|
162
|
+
if (jsonResult.isErr()) {
|
|
163
|
+
log.debug(`Failed to fetch OpenAPI spec from: ${url}`);
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
const spec = jsonResult.value;
|
|
167
|
+
if (spec && typeof spec === "object" && spec.paths) {
|
|
168
|
+
specCache.set(origin, spec);
|
|
169
|
+
log.info(`Cached OpenAPI spec for origin: ${origin}`);
|
|
170
|
+
return spec;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
log.debug(`No OpenAPI spec found for origin: ${origin}`);
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
function resolveRef(spec, ref, seen) {
|
|
177
|
+
if (!ref.startsWith("#/")) return void 0;
|
|
178
|
+
if (seen.has(ref)) return { $circular: ref };
|
|
179
|
+
seen.add(ref);
|
|
180
|
+
const parts = ref.slice(2).split("/");
|
|
181
|
+
let current = spec;
|
|
182
|
+
for (const part of parts) {
|
|
183
|
+
if (current == null || typeof current !== "object" || Array.isArray(current))
|
|
184
|
+
return void 0;
|
|
185
|
+
const next = current[part];
|
|
186
|
+
if (next === void 0) return void 0;
|
|
187
|
+
current = next;
|
|
188
|
+
}
|
|
189
|
+
if (current != null && typeof current === "object" && !Array.isArray(current)) {
|
|
190
|
+
return resolveRefs(spec, current, seen);
|
|
191
|
+
}
|
|
192
|
+
return current;
|
|
193
|
+
}
|
|
194
|
+
function resolveRefs(spec, obj, seen, depth = 0) {
|
|
195
|
+
if (depth > 4) return obj;
|
|
196
|
+
const result = {};
|
|
197
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
198
|
+
if (key === "$ref" && typeof value === "string") {
|
|
199
|
+
const resolved = resolveRef(spec, value, seen);
|
|
200
|
+
if (resolved != null && typeof resolved === "object" && !Array.isArray(resolved)) {
|
|
201
|
+
Object.assign(result, resolved);
|
|
202
|
+
} else {
|
|
203
|
+
result[key] = value;
|
|
204
|
+
}
|
|
205
|
+
} else if (value != null && typeof value === "object" && !Array.isArray(value)) {
|
|
206
|
+
result[key] = resolveRefs(spec, value, seen, depth + 1);
|
|
207
|
+
} else if (Array.isArray(value)) {
|
|
208
|
+
result[key] = value.map((item) => {
|
|
209
|
+
if (item != null && typeof item === "object" && !Array.isArray(item)) {
|
|
210
|
+
return resolveRefs(spec, item, seen, depth + 1);
|
|
211
|
+
}
|
|
212
|
+
return item;
|
|
213
|
+
});
|
|
214
|
+
} else {
|
|
215
|
+
result[key] = value;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return result;
|
|
219
|
+
}
|
|
220
|
+
function extractPath(url, origin) {
|
|
221
|
+
if (url.startsWith(origin)) {
|
|
222
|
+
return url.slice(origin.length) || "/";
|
|
223
|
+
}
|
|
224
|
+
return URL.canParse(url) ? new URL(url).pathname : url;
|
|
225
|
+
}
|
|
226
|
+
async function getEndpointSchema(endpointUrl, method) {
|
|
227
|
+
if (!URL.canParse(endpointUrl)) return null;
|
|
228
|
+
const origin = new URL(endpointUrl).origin;
|
|
229
|
+
const spec = await fetchOpenApiSpec(origin);
|
|
230
|
+
if (!spec) return null;
|
|
231
|
+
const paths = spec.paths;
|
|
232
|
+
if (!paths) return null;
|
|
233
|
+
const path = extractPath(endpointUrl, origin);
|
|
234
|
+
const httpMethod = (method ?? "post").toLowerCase();
|
|
235
|
+
let pathEntry = paths[path];
|
|
236
|
+
if (!pathEntry) {
|
|
237
|
+
for (const [specPath, specEntry] of Object.entries(paths)) {
|
|
238
|
+
if (specEntry == null || typeof specEntry !== "object") continue;
|
|
239
|
+
const pattern = specPath.replace(/\{[^}]+\}/g, "[^/]+");
|
|
240
|
+
const regex = new RegExp(`^${pattern}$`);
|
|
241
|
+
if (regex.test(path)) {
|
|
242
|
+
pathEntry = specEntry;
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
if (!pathEntry) {
|
|
248
|
+
log.debug(`No OpenAPI path entry found for: ${path}`);
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
const operation = pathEntry[httpMethod];
|
|
252
|
+
if (!operation) {
|
|
253
|
+
log.debug(`No OpenAPI operation found for ${httpMethod.toUpperCase()} ${path}`);
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
const resolved = resolveRefs(spec, operation, /* @__PURE__ */ new Set());
|
|
257
|
+
return { path, method: httpMethod, ...resolved };
|
|
258
|
+
}
|
|
259
|
+
var indexCache = /* @__PURE__ */ new Map();
|
|
260
|
+
async function getOriginIndex(origin) {
|
|
261
|
+
const cached = indexCache.get(origin);
|
|
262
|
+
if (cached) return cached;
|
|
263
|
+
const spec = await fetchOpenApiSpec(origin);
|
|
264
|
+
if (!spec?.paths) return null;
|
|
265
|
+
const endpoints = [];
|
|
266
|
+
for (const [path, methods] of Object.entries(
|
|
267
|
+
spec.paths
|
|
268
|
+
)) {
|
|
269
|
+
for (const [method, operation] of Object.entries(methods)) {
|
|
270
|
+
if (typeof operation === "object" && operation !== null) {
|
|
271
|
+
const op = operation;
|
|
272
|
+
const paymentInfo = op["x-payment-info"];
|
|
273
|
+
const entry = {
|
|
274
|
+
path,
|
|
275
|
+
method: method.toUpperCase(),
|
|
276
|
+
summary: op.summary || op.description || ""
|
|
277
|
+
};
|
|
278
|
+
if (paymentInfo?.price != null) {
|
|
279
|
+
entry.price = `$${paymentInfo.price}`;
|
|
280
|
+
}
|
|
281
|
+
if (Array.isArray(paymentInfo?.protocols)) {
|
|
282
|
+
entry.protocols = paymentInfo.protocols;
|
|
283
|
+
}
|
|
284
|
+
endpoints.push(entry);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
indexCache.set(origin, endpoints);
|
|
289
|
+
return endpoints;
|
|
290
|
+
}
|
|
291
|
+
var OPENAPI_HTTP_METHODS = /* @__PURE__ */ new Set([
|
|
292
|
+
"get",
|
|
293
|
+
"post",
|
|
294
|
+
"put",
|
|
295
|
+
"delete",
|
|
296
|
+
"patch",
|
|
297
|
+
"head",
|
|
298
|
+
"options",
|
|
299
|
+
"trace"
|
|
300
|
+
]);
|
|
301
|
+
async function getSpecMethods(endpointUrl) {
|
|
302
|
+
if (!URL.canParse(endpointUrl)) return null;
|
|
303
|
+
const origin = new URL(endpointUrl).origin;
|
|
304
|
+
const spec = await fetchOpenApiSpec(origin);
|
|
305
|
+
if (!spec?.paths) return null;
|
|
306
|
+
const paths = spec.paths;
|
|
307
|
+
const path = extractPath(endpointUrl, origin);
|
|
308
|
+
let pathEntry = paths[path];
|
|
309
|
+
if (!pathEntry) {
|
|
310
|
+
for (const [specPath, specEntry] of Object.entries(paths)) {
|
|
311
|
+
if (specEntry == null || typeof specEntry !== "object") continue;
|
|
312
|
+
const pattern = specPath.replace(/\{[^}]+\}/g, "[^/]+");
|
|
313
|
+
const regex = new RegExp(`^${pattern}$`);
|
|
314
|
+
if (regex.test(path)) {
|
|
315
|
+
pathEntry = specEntry;
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
if (!pathEntry) return null;
|
|
321
|
+
return Object.keys(pathEntry).filter((k) => OPENAPI_HTTP_METHODS.has(k)).map((k) => k.toUpperCase());
|
|
322
|
+
}
|
|
323
|
+
function getIndexEntry(origin, path, method) {
|
|
324
|
+
const entries = indexCache.get(origin);
|
|
325
|
+
if (!entries) return void 0;
|
|
326
|
+
const m = method.toUpperCase();
|
|
327
|
+
return entries.find((e) => e.path === path && e.method === m);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// src/shared/token.ts
|
|
331
|
+
import { formatUnits } from "viem";
|
|
332
|
+
var tokenStringToNumber = (amount, decimals = 6) => {
|
|
333
|
+
return Number(formatUnits(BigInt(amount), decimals));
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
// src/server/lib/x402-extensions.ts
|
|
337
|
+
var getBazaarExtension = (extensions) => {
|
|
338
|
+
const { bazaar } = extensions ?? {};
|
|
339
|
+
if (!bazaar) {
|
|
340
|
+
return void 0;
|
|
341
|
+
}
|
|
342
|
+
return bazaar;
|
|
343
|
+
};
|
|
344
|
+
var getInputSchema = (extensions) => getBazaarExtension(extensions)?.schema.properties.input;
|
|
345
|
+
var getSiwxExtension = (extensions) => {
|
|
346
|
+
const siwx = extensions?.["sign-in-with-x"];
|
|
347
|
+
if (!siwx?.info) {
|
|
348
|
+
return void 0;
|
|
349
|
+
}
|
|
350
|
+
const chain = siwx.supportedChains?.find(
|
|
351
|
+
(c) => c.chainId.startsWith("eip155:")
|
|
352
|
+
);
|
|
353
|
+
return {
|
|
354
|
+
...siwx.info,
|
|
355
|
+
chainId: chain?.chainId ?? "eip155:8453",
|
|
356
|
+
type: chain?.type ?? "eip191",
|
|
357
|
+
signatureScheme: chain?.signatureScheme
|
|
358
|
+
};
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
// src/shared/operations/check-endpoint.ts
|
|
362
|
+
var SUPPORTED_METHODS = [
|
|
363
|
+
"GET",
|
|
364
|
+
"POST",
|
|
365
|
+
"PUT",
|
|
366
|
+
"DELETE",
|
|
367
|
+
"PATCH"
|
|
368
|
+
];
|
|
369
|
+
async function checkEndpoint({
|
|
370
|
+
surface,
|
|
371
|
+
url,
|
|
372
|
+
methods,
|
|
373
|
+
body,
|
|
374
|
+
headers = {},
|
|
375
|
+
includeMethodErrors = false,
|
|
376
|
+
probeAllMethods = false
|
|
377
|
+
}) {
|
|
378
|
+
let methodsToCheck;
|
|
379
|
+
if (methods) {
|
|
380
|
+
methodsToCheck = methods;
|
|
381
|
+
} else if (probeAllMethods) {
|
|
382
|
+
methodsToCheck = [...SUPPORTED_METHODS];
|
|
383
|
+
} else {
|
|
384
|
+
const specMethods = await getSpecMethods(url);
|
|
385
|
+
if (specMethods?.length) {
|
|
386
|
+
methodsToCheck = specMethods.filter(
|
|
387
|
+
(m) => SUPPORTED_METHODS.includes(m)
|
|
388
|
+
);
|
|
389
|
+
} else {
|
|
390
|
+
methodsToCheck = [...SUPPORTED_METHODS];
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
log.info("Checking endpoint", { url, methods: methodsToCheck });
|
|
394
|
+
const results = await Promise.all(
|
|
395
|
+
methodsToCheck.map(
|
|
396
|
+
(method) => probeMethod({ surface, method, url, body, headers, includeMethodErrors })
|
|
397
|
+
)
|
|
398
|
+
);
|
|
399
|
+
return {
|
|
400
|
+
url,
|
|
401
|
+
results: results.filter((r) => r !== null)
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
async function probeMethod({
|
|
405
|
+
surface,
|
|
406
|
+
method,
|
|
407
|
+
url,
|
|
408
|
+
body,
|
|
409
|
+
headers,
|
|
410
|
+
includeMethodErrors
|
|
411
|
+
}) {
|
|
412
|
+
const cachedSchemaResult = await resultFromPromise(
|
|
413
|
+
"openapi",
|
|
414
|
+
surface,
|
|
415
|
+
getEndpointSchema(url, method),
|
|
416
|
+
(e) => ({
|
|
417
|
+
cause: "cache_lookup",
|
|
418
|
+
message: e instanceof Error ? e.message : String(e)
|
|
419
|
+
})
|
|
420
|
+
);
|
|
421
|
+
if (cachedSchemaResult.isOk() && cachedSchemaResult.value) {
|
|
422
|
+
const cachedSchema = cachedSchemaResult.value;
|
|
423
|
+
const origin = new URL(url).origin;
|
|
424
|
+
const path = new URL(url).pathname || "/";
|
|
425
|
+
const indexEntry = getIndexEntry(origin, path, method);
|
|
426
|
+
return {
|
|
427
|
+
method,
|
|
428
|
+
source: "openapi",
|
|
429
|
+
requiresPayment: true,
|
|
430
|
+
schema: cachedSchema,
|
|
431
|
+
...indexEntry?.price ? { estimatedPrice: indexEntry.price } : {},
|
|
432
|
+
...indexEntry?.protocols ? { protocols: indexEntry.protocols } : {},
|
|
433
|
+
...indexEntry?.summary ? { summary: indexEntry.summary } : {}
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
if (cachedSchemaResult.isErr()) {
|
|
437
|
+
log.debug(
|
|
438
|
+
`Cache lookup failed for ${method} ${url}, falling back to 402 probe`
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
const request = buildProbeRequest(url, method, body, headers);
|
|
442
|
+
const responseResult = await safeFetch(surface, request);
|
|
443
|
+
if (responseResult.isErr()) {
|
|
444
|
+
log.debug(`${method} ${url} probe failed`, responseResult.error);
|
|
445
|
+
return null;
|
|
446
|
+
}
|
|
447
|
+
const response = responseResult.value;
|
|
448
|
+
if (!response.ok && response.status !== 402) {
|
|
449
|
+
if (includeMethodErrors && (response.status === 404 || response.status === 405)) {
|
|
450
|
+
return {
|
|
451
|
+
method,
|
|
452
|
+
source: "probe",
|
|
453
|
+
requiresPayment: false,
|
|
454
|
+
statusCode: response.status
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
log.debug(`${method} ${url} returned ${response.status} \u2014 skipping`);
|
|
458
|
+
return null;
|
|
459
|
+
}
|
|
460
|
+
if (response.status !== 402) {
|
|
461
|
+
return {
|
|
462
|
+
method,
|
|
463
|
+
source: "probe",
|
|
464
|
+
requiresPayment: false,
|
|
465
|
+
statusCode: response.status
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
const protocols = detectPaymentProtocols(response);
|
|
469
|
+
const paymentMethods = [];
|
|
470
|
+
if (protocols.includes("mpp")) {
|
|
471
|
+
const challengeResult = safeGetMppChallenge(surface, response);
|
|
472
|
+
if (challengeResult.isOk()) {
|
|
473
|
+
const challenge = challengeResult.value;
|
|
474
|
+
const currency = challenge.request.currency;
|
|
475
|
+
const amount = challenge.request.amount;
|
|
476
|
+
const decimals = challenge.request.decimals ?? 6;
|
|
477
|
+
let schema;
|
|
478
|
+
const endpointSchemaResult = await resultFromPromise(
|
|
479
|
+
"openapi",
|
|
480
|
+
surface,
|
|
481
|
+
getEndpointSchema(url, method),
|
|
482
|
+
(e) => ({
|
|
483
|
+
cause: "schema_fetch",
|
|
484
|
+
message: e instanceof Error ? e.message : String(e)
|
|
485
|
+
})
|
|
486
|
+
);
|
|
487
|
+
if (endpointSchemaResult.isOk() && endpointSchemaResult.value) {
|
|
488
|
+
schema = endpointSchemaResult.value;
|
|
489
|
+
} else if (endpointSchemaResult.isErr()) {
|
|
490
|
+
log.debug(`Failed to fetch OpenAPI schema for: ${url}`);
|
|
491
|
+
}
|
|
492
|
+
paymentMethods.push({
|
|
493
|
+
protocol: "mpp",
|
|
494
|
+
method: challenge.method,
|
|
495
|
+
intent: challenge.intent,
|
|
496
|
+
realm: challenge.realm,
|
|
497
|
+
...challenge.description ? { description: challenge.description } : {},
|
|
498
|
+
...amount ? { price: tokenStringToNumber(amount, decimals) } : {},
|
|
499
|
+
...currency ? { currency } : {},
|
|
500
|
+
...schema ? { schema } : {},
|
|
501
|
+
network: `tempo:${challenge.method}`
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
if (protocols.includes("x402")) {
|
|
506
|
+
const client = new x402HTTPClient(new x402Client());
|
|
507
|
+
const paymentRequiredResult = await safeGetPaymentRequired(
|
|
508
|
+
surface,
|
|
509
|
+
client,
|
|
510
|
+
response
|
|
511
|
+
);
|
|
512
|
+
if (paymentRequiredResult.isOk()) {
|
|
513
|
+
const { resource, extensions, accepts } = paymentRequiredResult.value;
|
|
514
|
+
for (const accept of accepts) {
|
|
515
|
+
paymentMethods.push({
|
|
516
|
+
protocol: "x402",
|
|
517
|
+
...resource,
|
|
518
|
+
schema: getInputSchema(extensions),
|
|
519
|
+
price: tokenStringToNumber(accept.amount),
|
|
520
|
+
network: accept.network,
|
|
521
|
+
asset: accept.asset
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
return {
|
|
527
|
+
method,
|
|
528
|
+
source: "probe",
|
|
529
|
+
requiresPayment: true,
|
|
530
|
+
statusCode: response.status,
|
|
531
|
+
protocols,
|
|
532
|
+
paymentMethods
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
function buildProbeRequest(url, method, body, headers) {
|
|
536
|
+
const supportsBody = ["POST", "PUT", "PATCH"].includes(method);
|
|
537
|
+
const requestBody = supportsBody && body ? typeof body === "string" ? body : JSON.stringify(body) : void 0;
|
|
538
|
+
return new Request(url, {
|
|
539
|
+
method,
|
|
540
|
+
body: requestBody,
|
|
541
|
+
headers: {
|
|
542
|
+
...requestBody ? { "Content-Type": "application/json" } : {},
|
|
543
|
+
...headers
|
|
544
|
+
}
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// src/shared/operations/discover.ts
|
|
549
|
+
async function fetchLlmsTxt(surface, origin) {
|
|
550
|
+
const llmsTxtUrl = `${origin}/llms.txt`;
|
|
551
|
+
log.debug(`Fetching llms.txt from: ${llmsTxtUrl}`);
|
|
552
|
+
const result = await safeFetch(
|
|
553
|
+
surface,
|
|
554
|
+
new Request(llmsTxtUrl, { headers: { Accept: "text/plain" } })
|
|
555
|
+
);
|
|
556
|
+
if (result.isErr()) return null;
|
|
557
|
+
const parseResult = await safeParseResponse(surface, result.value);
|
|
558
|
+
if (parseResult.isErr() || parseResult.value.type !== "text") return null;
|
|
559
|
+
return parseResult.value.data;
|
|
560
|
+
}
|
|
561
|
+
async function discoverResources(surface, url) {
|
|
562
|
+
const origin = URL.canParse(url) ? new URL(url).origin : url;
|
|
563
|
+
log.info(`Discovering resources for origin: ${origin}`);
|
|
564
|
+
const [spec, instructions] = await Promise.all([
|
|
565
|
+
fetchOpenApiSpec(origin),
|
|
566
|
+
fetchLlmsTxt(surface, origin)
|
|
567
|
+
]);
|
|
568
|
+
if (!spec?.paths) {
|
|
569
|
+
log.debug(
|
|
570
|
+
`No OpenAPI spec found for ${origin}. Tried: /openapi.json, /.well-known/openapi.json, /.well-known/x402, /.well-known/mpp`
|
|
571
|
+
);
|
|
572
|
+
return null;
|
|
573
|
+
}
|
|
574
|
+
const endpoints = await getOriginIndex(origin);
|
|
575
|
+
if (!endpoints || endpoints.length === 0) {
|
|
576
|
+
log.debug(`OpenAPI spec found for ${origin} but no endpoints extracted`);
|
|
577
|
+
return null;
|
|
578
|
+
}
|
|
579
|
+
log.info(`Found ${endpoints.length} endpoints for: ${origin}`);
|
|
580
|
+
return {
|
|
581
|
+
origin,
|
|
582
|
+
source: "openapi",
|
|
583
|
+
endpoints: endpoints.map(({ path, method, summary, price, protocols }) => ({
|
|
584
|
+
path,
|
|
585
|
+
method,
|
|
586
|
+
summary,
|
|
587
|
+
...price ? { price } : {},
|
|
588
|
+
...protocols ? { protocols } : {}
|
|
589
|
+
})),
|
|
590
|
+
...instructions ? { instructions } : {}
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// src/shared/operations/wallet-info.ts
|
|
595
|
+
import { formatUnits as formatUnits2 } from "viem";
|
|
596
|
+
|
|
597
|
+
// src/shared/tempo.ts
|
|
598
|
+
var TEMPO_RPC_URL = "https://eng:acard-melody-fashion-finish@rpc.mainnet.tempo.xyz";
|
|
599
|
+
var TEMPO_TOKEN_ADDRESS = "0x20c0000000000000000000000000000000000000";
|
|
600
|
+
|
|
601
|
+
// src/shared/tempo-balance.ts
|
|
602
|
+
import { tempo } from "viem/chains";
|
|
603
|
+
var MPPSCAN_BASE = "https://mppscan.com";
|
|
604
|
+
async function getTempoBalance({
|
|
605
|
+
address,
|
|
606
|
+
tokenAddress
|
|
607
|
+
}) {
|
|
608
|
+
const url = `${MPPSCAN_BASE}/api/balance/${address}`;
|
|
609
|
+
const res = await fetch(url, {
|
|
610
|
+
method: "GET",
|
|
611
|
+
headers: { accept: "application/json" }
|
|
612
|
+
});
|
|
613
|
+
if (!res.ok) {
|
|
614
|
+
throw new Error(`mppscan balance request failed: ${res.status}`);
|
|
615
|
+
}
|
|
616
|
+
const data = await res.json();
|
|
617
|
+
return {
|
|
618
|
+
chainId: tempo.id,
|
|
619
|
+
chainName: tempo.name,
|
|
620
|
+
balance: BigInt(data.balance),
|
|
621
|
+
tokenAddress
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
// src/shared/operations/wallet-info.ts
|
|
626
|
+
async function getWalletInfo(surface, address, flags) {
|
|
627
|
+
const [balanceResult, tempoResult] = await Promise.all([
|
|
628
|
+
getBalance({ address, flags, surface }),
|
|
629
|
+
getTempoBalance({ address, tokenAddress: TEMPO_TOKEN_ADDRESS }).then((r) => Number(formatUnits2(r.balance, 6))).catch((e) => {
|
|
630
|
+
log.info(`Failed to fetch Tempo balance: ${e}`);
|
|
631
|
+
return null;
|
|
632
|
+
})
|
|
633
|
+
]);
|
|
634
|
+
if (balanceResult.isErr()) {
|
|
635
|
+
return balanceResult;
|
|
636
|
+
}
|
|
637
|
+
const baseBalance = balanceResult.value.balance;
|
|
638
|
+
const tempoBalance = tempoResult ?? 0;
|
|
639
|
+
const totalBalance = baseBalance + tempoBalance;
|
|
640
|
+
const chains = [
|
|
641
|
+
{ chain: "Base", balance: baseBalance },
|
|
642
|
+
{ chain: "Tempo", balance: tempoBalance }
|
|
643
|
+
];
|
|
644
|
+
return ok({
|
|
645
|
+
address,
|
|
646
|
+
balance: totalBalance,
|
|
647
|
+
chains,
|
|
648
|
+
isNewWallet: totalBalance === 0,
|
|
649
|
+
depositLink: getDepositLink(address, flags),
|
|
650
|
+
...totalBalance < 2.5 && totalBalance > 0 ? { message: "Your balance is low. Consider topping it up" } : {}
|
|
651
|
+
});
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
// src/shared/operations/report-error.ts
|
|
655
|
+
import { z } from "zod";
|
|
656
|
+
async function submitErrorReport(surface, input, address, dev) {
|
|
657
|
+
const telemetryResult = await safeFetchJson(
|
|
658
|
+
surface,
|
|
659
|
+
new Request(`${getBaseUrl(dev)}/api/telemetry`, {
|
|
660
|
+
method: "POST",
|
|
661
|
+
headers: {
|
|
662
|
+
"Content-Type": "application/json"
|
|
663
|
+
},
|
|
664
|
+
body: JSON.stringify({
|
|
665
|
+
tool: input.tool,
|
|
666
|
+
summary: input.summary,
|
|
667
|
+
errorMessage: input.errorMessage,
|
|
668
|
+
resource: input.resource,
|
|
669
|
+
stack: input.stack,
|
|
670
|
+
fullReport: input.fullReport,
|
|
671
|
+
walletAddress: address,
|
|
672
|
+
mcpVersion: MCP_VERSION,
|
|
673
|
+
reportedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
674
|
+
})
|
|
675
|
+
}),
|
|
676
|
+
z.object({
|
|
677
|
+
reportId: z.string()
|
|
678
|
+
})
|
|
679
|
+
);
|
|
680
|
+
if (telemetryResult.isErr()) {
|
|
681
|
+
return telemetryResult;
|
|
682
|
+
}
|
|
683
|
+
const { reportId } = telemetryResult.value;
|
|
684
|
+
return ok({
|
|
685
|
+
submitted: true,
|
|
686
|
+
reportId,
|
|
687
|
+
message: "Error report submitted successfully. The agentcash team will investigate."
|
|
688
|
+
});
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
export {
|
|
692
|
+
TEMPO_RPC_URL,
|
|
693
|
+
x402Ok,
|
|
694
|
+
x402Err,
|
|
695
|
+
safeGetPaymentRequired,
|
|
696
|
+
safeCreatePaymentPayload,
|
|
697
|
+
safeGetPaymentSettlement,
|
|
698
|
+
safeCreateSIWxPayload,
|
|
699
|
+
mppOk,
|
|
700
|
+
mppErr,
|
|
701
|
+
safeGetMppChallenge,
|
|
702
|
+
safeCreateMppCredential,
|
|
703
|
+
safeGetMppReceipt,
|
|
704
|
+
detectPaymentProtocols,
|
|
705
|
+
tokenStringToNumber,
|
|
706
|
+
getTempoBalance,
|
|
707
|
+
getOriginIndex,
|
|
708
|
+
getInputSchema,
|
|
709
|
+
getSiwxExtension,
|
|
710
|
+
SUPPORTED_METHODS,
|
|
711
|
+
checkEndpoint,
|
|
712
|
+
discoverResources,
|
|
713
|
+
getWalletInfo,
|
|
714
|
+
submitErrorReport
|
|
715
|
+
};
|
|
716
|
+
//# sourceMappingURL=chunk-FM2E2QVT.js.map
|