agentcash 0.3.0 → 0.3.2
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 +480 -3191
- package/dist/esm/{chunk-4YIIYCPO.js → chunk-BTIVASGJ.js} +5 -10
- package/dist/esm/{chunk-4YIIYCPO.js.map → chunk-BTIVASGJ.js.map} +1 -1
- package/dist/esm/chunk-E3MKYUQQ.js +575 -0
- package/dist/esm/chunk-E3MKYUQQ.js.map +1 -0
- package/dist/esm/{chunk-J3LUL7DB.js → chunk-ISR6DJ53.js} +1 -6
- package/dist/esm/{chunk-J3LUL7DB.js.map → chunk-ISR6DJ53.js.map} +1 -1
- package/dist/esm/{chunk-3MUBKDR7.js → chunk-KPEJO3KV.js} +1 -6
- package/dist/esm/{chunk-3MUBKDR7.js.map → chunk-KPEJO3KV.js.map} +1 -1
- package/dist/esm/{chunk-2OAFWAAC.js → chunk-VX2WPSZV.js} +29 -97
- package/dist/esm/chunk-VX2WPSZV.js.map +1 -0
- package/dist/esm/chunk-VZL5QWWM.js +363 -0
- package/dist/esm/chunk-VZL5QWWM.js.map +1 -0
- package/dist/esm/{chunk-FYIUFEVS.js → chunk-XXKBL2AC.js} +1 -6
- package/dist/esm/{chunk-FYIUFEVS.js.map → chunk-XXKBL2AC.js.map} +1 -1
- package/dist/esm/chunk-ZVDFFTHM.js +22 -0
- package/dist/esm/chunk-ZVDFFTHM.js.map +1 -0
- package/dist/esm/cli-context-JTXXAIO4.js +9 -0
- package/dist/esm/{commands-WQ5AY36Z.js → commands-IANPQPZS.js} +14 -35
- package/dist/esm/commands-IANPQPZS.js.map +1 -0
- package/dist/esm/{fund-JSFGMI3R.js → fund-H6QAHY62.js} +5 -9
- package/dist/esm/{fund-JSFGMI3R.js.map → fund-H6QAHY62.js.map} +1 -1
- package/dist/esm/index.js +11 -15
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/{install-B4HDFMEM.js → install-KLEATNEC.js} +9 -25
- package/dist/esm/install-KLEATNEC.js.map +1 -0
- package/dist/esm/{server-SKKWDRW7.js → server-XNUVCZTJ.js} +35 -142
- package/dist/esm/server-XNUVCZTJ.js.map +1 -0
- package/dist/esm/shared/operations/index.d.ts +7 -7
- package/dist/esm/shared/operations/index.js +4 -5
- package/package.json +5 -3
- package/dist/esm/chunk-2OAFWAAC.js.map +0 -1
- package/dist/esm/chunk-A2KI7TKE.js +0 -59
- package/dist/esm/chunk-A2KI7TKE.js.map +0 -1
- package/dist/esm/chunk-JVUT4TKE.js +0 -197
- package/dist/esm/chunk-JVUT4TKE.js.map +0 -1
- package/dist/esm/chunk-VTLIFNZN.js +0 -46015
- package/dist/esm/chunk-VTLIFNZN.js.map +0 -1
- package/dist/esm/chunk-YOLNSINZ.js +0 -57
- package/dist/esm/chunk-YOLNSINZ.js.map +0 -1
- package/dist/esm/cli-context-2MKOXVXU.js +0 -10
- package/dist/esm/commands-WQ5AY36Z.js.map +0 -1
- package/dist/esm/install-B4HDFMEM.js.map +0 -1
- package/dist/esm/server-SKKWDRW7.js.map +0 -1
- /package/dist/esm/{cli-context-2MKOXVXU.js.map → cli-context-JTXXAIO4.js.map} +0 -0
|
@@ -1,23 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
redeemInviteCode
|
|
3
|
-
} from "./chunk-JVUT4TKE.js";
|
|
4
1
|
import {
|
|
5
2
|
DEFAULT_NETWORK,
|
|
6
3
|
getChainName,
|
|
7
|
-
|
|
8
|
-
} from "./chunk-
|
|
4
|
+
redeemInviteCode
|
|
5
|
+
} from "./chunk-VZL5QWWM.js";
|
|
9
6
|
import {
|
|
10
|
-
|
|
11
|
-
} from "./chunk-
|
|
7
|
+
getDepositLink
|
|
8
|
+
} from "./chunk-VX2WPSZV.js";
|
|
12
9
|
|
|
13
10
|
// src/cli/lib/deposit.ts
|
|
14
|
-
init_esm_shims();
|
|
15
11
|
import chalk from "chalk";
|
|
16
12
|
import { select, text, log, spinner as spinner2 } from "@clack/prompts";
|
|
17
13
|
import open from "open";
|
|
18
14
|
|
|
19
15
|
// src/cli/lib/wait.ts
|
|
20
|
-
init_esm_shims();
|
|
21
16
|
import { spinner } from "@clack/prompts";
|
|
22
17
|
var wait = async ({ startText, stopText, ms }) => {
|
|
23
18
|
const { start: startSpinner, stop: stopSpinner } = spinner();
|
|
@@ -116,4 +111,4 @@ export {
|
|
|
116
111
|
wait,
|
|
117
112
|
promptDeposit
|
|
118
113
|
};
|
|
119
|
-
//# sourceMappingURL=chunk-
|
|
114
|
+
//# sourceMappingURL=chunk-BTIVASGJ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/lib/deposit.ts","../../src/cli/lib/wait.ts"],"sourcesContent":["import chalk from 'chalk';\nimport { select, text, log, spinner } from '@clack/prompts';\nimport open from 'open';\n\nimport { DEFAULT_NETWORK, getChainName } from '../../shared/networks';\nimport { wait } from './wait';\nimport { getDepositLink } from '../../shared/utils';\nimport { redeemInviteCode } from '../../shared/redeem-invite';\n\nimport type { GlobalFlags } from '@/types';\nimport type { Address } from 'viem';\n\ninterface PromptDepositProps {\n address: Address;\n flags: GlobalFlags;\n surface: string;\n}\n\nexport const promptDeposit = async (\n props: PromptDepositProps\n): Promise<void> => {\n const { address, flags, surface } = props;\n\n const depositLink = getDepositLink(address, flags);\n\n const depositChoice =\n flags.yes || surface === 'guided'\n ? 'manual'\n : await select({\n message: chalk.bold('How would you like to deposit?'),\n initialValue: 'guided' as string | undefined,\n options: [\n {\n label: 'Guided - Recommended',\n value: 'guided',\n hint: 'Online portal in agentcash',\n },\n {\n label: 'Manual',\n value: 'manual',\n hint: 'Print deposit instructions',\n },\n {\n label: 'Redeem Invite Code',\n value: 'invite',\n hint: 'Enter an invite code for starter money',\n },\n {\n label: 'Skip',\n value: undefined,\n hint: 'Skip deposit process - functionality limited',\n },\n ],\n });\n\n if (depositChoice === 'guided') {\n await wait({\n startText: 'Opening deposit page...',\n stopText: `Opening ${chalk.underline.hex('#2563eb')(depositLink)}`,\n ms: 1000,\n });\n\n await open(depositLink);\n } else if (depositChoice === 'manual') {\n log.step(chalk.bold('Account Information'));\n\n log.message(`Address: ${address}`);\n log.message(`Network: ${getChainName(DEFAULT_NETWORK)}`);\n\n log.step(chalk.bold('Online Portal'));\n log.message(`${chalk.underline(depositLink)}`);\n } else if (depositChoice === 'invite') {\n const code = await text({\n message: 'Enter your invite code',\n placeholder: 'MRT-XXXXX',\n validate: value => {\n if (!value || value.trim().length === 0) {\n return 'Please enter an invite code';\n }\n },\n });\n\n if (typeof code !== 'string') {\n return promptDeposit({ address, flags, surface });\n }\n\n const s = spinner();\n s.start('Redeeming invite code...');\n\n const redeemResult = await redeemInviteCode({\n code,\n dev: flags.dev,\n address,\n surface: 'redeemInvite',\n });\n\n if (redeemResult.isErr()) {\n s.stop('Invite code redemption failed');\n log.error('Failed to redeem invite code');\n return promptDeposit({ address, flags, surface });\n }\n\n s.stop('Invite code redeemed successfully!');\n\n const { amount, txHash } = redeemResult.value;\n\n await wait({\n startText: 'Processing...',\n stopText: chalk.green(\n `${chalk.bold(amount)} USDC has been sent to your wallet!`\n ),\n ms: 1500,\n });\n\n log.success(chalk.bold(`Your wallet has been funded with ${amount} USDC`));\n\n if (txHash) {\n log.info(chalk.dim(`Transaction: https://basescan.org/tx/${txHash}`));\n }\n\n return;\n }\n};\n","import { spinner } from '@clack/prompts';\n\ninterface WaitProps {\n startText: string;\n stopText: string;\n ms: number;\n}\n\nexport const wait = async ({ startText, stopText, ms }: WaitProps) => {\n const { start: startSpinner, stop: stopSpinner } = spinner();\n startSpinner(startText);\n await new Promise(resolve => setTimeout(resolve, ms));\n stopSpinner(stopText);\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../src/cli/lib/deposit.ts","../../src/cli/lib/wait.ts"],"sourcesContent":["import chalk from 'chalk';\nimport { select, text, log, spinner } from '@clack/prompts';\nimport open from 'open';\n\nimport { DEFAULT_NETWORK, getChainName } from '../../shared/networks';\nimport { wait } from './wait';\nimport { getDepositLink } from '../../shared/utils';\nimport { redeemInviteCode } from '../../shared/redeem-invite';\n\nimport type { GlobalFlags } from '@/types';\nimport type { Address } from 'viem';\n\ninterface PromptDepositProps {\n address: Address;\n flags: GlobalFlags;\n surface: string;\n}\n\nexport const promptDeposit = async (\n props: PromptDepositProps\n): Promise<void> => {\n const { address, flags, surface } = props;\n\n const depositLink = getDepositLink(address, flags);\n\n const depositChoice =\n flags.yes || surface === 'guided'\n ? 'manual'\n : await select({\n message: chalk.bold('How would you like to deposit?'),\n initialValue: 'guided' as string | undefined,\n options: [\n {\n label: 'Guided - Recommended',\n value: 'guided',\n hint: 'Online portal in agentcash',\n },\n {\n label: 'Manual',\n value: 'manual',\n hint: 'Print deposit instructions',\n },\n {\n label: 'Redeem Invite Code',\n value: 'invite',\n hint: 'Enter an invite code for starter money',\n },\n {\n label: 'Skip',\n value: undefined,\n hint: 'Skip deposit process - functionality limited',\n },\n ],\n });\n\n if (depositChoice === 'guided') {\n await wait({\n startText: 'Opening deposit page...',\n stopText: `Opening ${chalk.underline.hex('#2563eb')(depositLink)}`,\n ms: 1000,\n });\n\n await open(depositLink);\n } else if (depositChoice === 'manual') {\n log.step(chalk.bold('Account Information'));\n\n log.message(`Address: ${address}`);\n log.message(`Network: ${getChainName(DEFAULT_NETWORK)}`);\n\n log.step(chalk.bold('Online Portal'));\n log.message(`${chalk.underline(depositLink)}`);\n } else if (depositChoice === 'invite') {\n const code = await text({\n message: 'Enter your invite code',\n placeholder: 'MRT-XXXXX',\n validate: value => {\n if (!value || value.trim().length === 0) {\n return 'Please enter an invite code';\n }\n },\n });\n\n if (typeof code !== 'string') {\n return promptDeposit({ address, flags, surface });\n }\n\n const s = spinner();\n s.start('Redeeming invite code...');\n\n const redeemResult = await redeemInviteCode({\n code,\n dev: flags.dev,\n address,\n surface: 'redeemInvite',\n });\n\n if (redeemResult.isErr()) {\n s.stop('Invite code redemption failed');\n log.error('Failed to redeem invite code');\n return promptDeposit({ address, flags, surface });\n }\n\n s.stop('Invite code redeemed successfully!');\n\n const { amount, txHash } = redeemResult.value;\n\n await wait({\n startText: 'Processing...',\n stopText: chalk.green(\n `${chalk.bold(amount)} USDC has been sent to your wallet!`\n ),\n ms: 1500,\n });\n\n log.success(chalk.bold(`Your wallet has been funded with ${amount} USDC`));\n\n if (txHash) {\n log.info(chalk.dim(`Transaction: https://basescan.org/tx/${txHash}`));\n }\n\n return;\n }\n};\n","import { spinner } from '@clack/prompts';\n\ninterface WaitProps {\n startText: string;\n stopText: string;\n ms: number;\n}\n\nexport const wait = async ({ startText, stopText, ms }: WaitProps) => {\n const { start: startSpinner, stop: stopSpinner } = spinner();\n startSpinner(startText);\n await new Promise(resolve => setTimeout(resolve, ms));\n stopSpinner(stopText);\n};\n"],"mappings":";;;;;;;;;;AAAA,OAAO,WAAW;AAClB,SAAS,QAAQ,MAAM,KAAK,WAAAA,gBAAe;AAC3C,OAAO,UAAU;;;ACFjB,SAAS,eAAe;AAQjB,IAAM,OAAO,OAAO,EAAE,WAAW,UAAU,GAAG,MAAiB;AACpE,QAAM,EAAE,OAAO,cAAc,MAAM,YAAY,IAAI,QAAQ;AAC3D,eAAa,SAAS;AACtB,QAAM,IAAI,QAAQ,aAAW,WAAW,SAAS,EAAE,CAAC;AACpD,cAAY,QAAQ;AACtB;;;ADKO,IAAM,gBAAgB,OAC3B,UACkB;AAClB,QAAM,EAAE,SAAS,OAAO,QAAQ,IAAI;AAEpC,QAAM,cAAc,eAAe,SAAS,KAAK;AAEjD,QAAM,gBACJ,MAAM,OAAO,YAAY,WACrB,WACA,MAAM,OAAO;AAAA,IACX,SAAS,MAAM,KAAK,gCAAgC;AAAA,IACpD,cAAc;AAAA,IACd,SAAS;AAAA,MACP;AAAA,QACE,OAAO;AAAA,QACP,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,MACA;AAAA,QACE,OAAO;AAAA,QACP,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,MACA;AAAA,QACE,OAAO;AAAA,QACP,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,MACA;AAAA,QACE,OAAO;AAAA,QACP,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF,CAAC;AAEP,MAAI,kBAAkB,UAAU;AAC9B,UAAM,KAAK;AAAA,MACT,WAAW;AAAA,MACX,UAAU,WAAW,MAAM,UAAU,IAAI,SAAS,EAAE,WAAW,CAAC;AAAA,MAChE,IAAI;AAAA,IACN,CAAC;AAED,UAAM,KAAK,WAAW;AAAA,EACxB,WAAW,kBAAkB,UAAU;AACrC,QAAI,KAAK,MAAM,KAAK,qBAAqB,CAAC;AAE1C,QAAI,QAAQ,YAAY,OAAO,EAAE;AACjC,QAAI,QAAQ,YAAY,aAAa,eAAe,CAAC,EAAE;AAEvD,QAAI,KAAK,MAAM,KAAK,eAAe,CAAC;AACpC,QAAI,QAAQ,GAAG,MAAM,UAAU,WAAW,CAAC,EAAE;AAAA,EAC/C,WAAW,kBAAkB,UAAU;AACrC,UAAM,OAAO,MAAM,KAAK;AAAA,MACtB,SAAS;AAAA,MACT,aAAa;AAAA,MACb,UAAU,WAAS;AACjB,YAAI,CAAC,SAAS,MAAM,KAAK,EAAE,WAAW,GAAG;AACvC,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,CAAC;AAED,QAAI,OAAO,SAAS,UAAU;AAC5B,aAAO,cAAc,EAAE,SAAS,OAAO,QAAQ,CAAC;AAAA,IAClD;AAEA,UAAM,IAAIC,SAAQ;AAClB,MAAE,MAAM,0BAA0B;AAElC,UAAM,eAAe,MAAM,iBAAiB;AAAA,MAC1C;AAAA,MACA,KAAK,MAAM;AAAA,MACX;AAAA,MACA,SAAS;AAAA,IACX,CAAC;AAED,QAAI,aAAa,MAAM,GAAG;AACxB,QAAE,KAAK,+BAA+B;AACtC,UAAI,MAAM,8BAA8B;AACxC,aAAO,cAAc,EAAE,SAAS,OAAO,QAAQ,CAAC;AAAA,IAClD;AAEA,MAAE,KAAK,oCAAoC;AAE3C,UAAM,EAAE,QAAQ,OAAO,IAAI,aAAa;AAExC,UAAM,KAAK;AAAA,MACT,WAAW;AAAA,MACX,UAAU,MAAM;AAAA,QACd,GAAG,MAAM,KAAK,MAAM,CAAC;AAAA,MACvB;AAAA,MACA,IAAI;AAAA,IACN,CAAC;AAED,QAAI,QAAQ,MAAM,KAAK,oCAAoC,MAAM,OAAO,CAAC;AAEzE,QAAI,QAAQ;AACV,UAAI,KAAK,MAAM,IAAI,wCAAwC,MAAM,EAAE,CAAC;AAAA,IACtE;AAEA;AAAA,EACF;AACF;","names":["spinner","spinner"]}
|
|
@@ -0,0 +1,575 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MCP_VERSION
|
|
3
|
+
} from "./chunk-ZVDFFTHM.js";
|
|
4
|
+
import {
|
|
5
|
+
err,
|
|
6
|
+
fetchErr,
|
|
7
|
+
fetchOk,
|
|
8
|
+
getBalance,
|
|
9
|
+
getBaseUrl,
|
|
10
|
+
getDepositLink,
|
|
11
|
+
log,
|
|
12
|
+
ok,
|
|
13
|
+
resultFromPromise,
|
|
14
|
+
resultFromThrowable,
|
|
15
|
+
safeFetch,
|
|
16
|
+
safeFetchJson,
|
|
17
|
+
safeParseResponse
|
|
18
|
+
} from "./chunk-VX2WPSZV.js";
|
|
19
|
+
|
|
20
|
+
// src/shared/openapi-cache.ts
|
|
21
|
+
var specCache = /* @__PURE__ */ new Map();
|
|
22
|
+
async function fetchOpenApiSpec(origin) {
|
|
23
|
+
const cached = specCache.get(origin);
|
|
24
|
+
if (cached) return cached;
|
|
25
|
+
const uniqueUrls = [
|
|
26
|
+
`${origin}/openapi.json`,
|
|
27
|
+
`${origin}/.well-known/openapi.json`,
|
|
28
|
+
`${origin}/.well-known/x402`,
|
|
29
|
+
`${origin}/.well-known/mpp`
|
|
30
|
+
];
|
|
31
|
+
for (const url of uniqueUrls) {
|
|
32
|
+
log.debug(`Fetching OpenAPI spec from: ${url}`);
|
|
33
|
+
const fetchResult = await safeFetch(
|
|
34
|
+
"fetchOpenApiSpec",
|
|
35
|
+
new Request(url, { headers: { Accept: "application/json" } })
|
|
36
|
+
);
|
|
37
|
+
if (fetchResult.isErr()) {
|
|
38
|
+
log.debug(`Failed to fetch OpenAPI spec from: ${url}`);
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const response = fetchResult.value;
|
|
42
|
+
if (!response.ok) continue;
|
|
43
|
+
const jsonResult = await resultFromPromise(
|
|
44
|
+
"json",
|
|
45
|
+
"fetchOpenApiSpec",
|
|
46
|
+
response.json(),
|
|
47
|
+
() => ({
|
|
48
|
+
cause: "parse",
|
|
49
|
+
message: `Failed to parse JSON from: ${url}`
|
|
50
|
+
})
|
|
51
|
+
);
|
|
52
|
+
if (jsonResult.isErr()) {
|
|
53
|
+
log.debug(`Failed to fetch OpenAPI spec from: ${url}`);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
const spec = jsonResult.value;
|
|
57
|
+
if (spec && typeof spec === "object" && spec.paths) {
|
|
58
|
+
specCache.set(origin, spec);
|
|
59
|
+
log.info(`Cached OpenAPI spec for origin: ${origin}`);
|
|
60
|
+
return spec;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
log.debug(`No OpenAPI spec found for origin: ${origin}`);
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
function resolveRef(spec, ref, seen) {
|
|
67
|
+
if (!ref.startsWith("#/")) return void 0;
|
|
68
|
+
if (seen.has(ref)) return { $circular: ref };
|
|
69
|
+
seen.add(ref);
|
|
70
|
+
const parts = ref.slice(2).split("/");
|
|
71
|
+
let current = spec;
|
|
72
|
+
for (const part of parts) {
|
|
73
|
+
if (current == null || typeof current !== "object" || Array.isArray(current))
|
|
74
|
+
return void 0;
|
|
75
|
+
const next = current[part];
|
|
76
|
+
if (next === void 0) return void 0;
|
|
77
|
+
current = next;
|
|
78
|
+
}
|
|
79
|
+
if (current != null && typeof current === "object" && !Array.isArray(current)) {
|
|
80
|
+
return resolveRefs(spec, current, seen);
|
|
81
|
+
}
|
|
82
|
+
return current;
|
|
83
|
+
}
|
|
84
|
+
function resolveRefs(spec, obj, seen, depth = 0) {
|
|
85
|
+
if (depth > 4) return obj;
|
|
86
|
+
const result = {};
|
|
87
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
88
|
+
if (key === "$ref" && typeof value === "string") {
|
|
89
|
+
const resolved = resolveRef(spec, value, seen);
|
|
90
|
+
if (resolved != null && typeof resolved === "object" && !Array.isArray(resolved)) {
|
|
91
|
+
Object.assign(result, resolved);
|
|
92
|
+
} else {
|
|
93
|
+
result[key] = value;
|
|
94
|
+
}
|
|
95
|
+
} else if (value != null && typeof value === "object" && !Array.isArray(value)) {
|
|
96
|
+
result[key] = resolveRefs(spec, value, seen, depth + 1);
|
|
97
|
+
} else if (Array.isArray(value)) {
|
|
98
|
+
result[key] = value.map((item) => {
|
|
99
|
+
if (item != null && typeof item === "object" && !Array.isArray(item)) {
|
|
100
|
+
return resolveRefs(spec, item, seen, depth + 1);
|
|
101
|
+
}
|
|
102
|
+
return item;
|
|
103
|
+
});
|
|
104
|
+
} else {
|
|
105
|
+
result[key] = value;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
function extractPath(url, origin) {
|
|
111
|
+
if (url.startsWith(origin)) {
|
|
112
|
+
return url.slice(origin.length) || "/";
|
|
113
|
+
}
|
|
114
|
+
return URL.canParse(url) ? new URL(url).pathname : url;
|
|
115
|
+
}
|
|
116
|
+
async function getEndpointSchema(endpointUrl, method) {
|
|
117
|
+
if (!URL.canParse(endpointUrl)) return null;
|
|
118
|
+
const origin = new URL(endpointUrl).origin;
|
|
119
|
+
const spec = await fetchOpenApiSpec(origin);
|
|
120
|
+
if (!spec) return null;
|
|
121
|
+
const paths = spec.paths;
|
|
122
|
+
if (!paths) return null;
|
|
123
|
+
const path = extractPath(endpointUrl, origin);
|
|
124
|
+
const httpMethod = (method ?? "post").toLowerCase();
|
|
125
|
+
let pathEntry = paths[path];
|
|
126
|
+
if (!pathEntry) {
|
|
127
|
+
for (const [specPath, specEntry] of Object.entries(paths)) {
|
|
128
|
+
if (specEntry == null || typeof specEntry !== "object") continue;
|
|
129
|
+
const pattern = specPath.replace(/\{[^}]+\}/g, "[^/]+");
|
|
130
|
+
const regex = new RegExp(`^${pattern}$`);
|
|
131
|
+
if (regex.test(path)) {
|
|
132
|
+
pathEntry = specEntry;
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (!pathEntry) {
|
|
138
|
+
log.debug(`No OpenAPI path entry found for: ${path}`);
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
const operation = pathEntry[httpMethod];
|
|
142
|
+
if (!operation) {
|
|
143
|
+
const resolved2 = resolveRefs(spec, pathEntry, /* @__PURE__ */ new Set());
|
|
144
|
+
return { path, ...resolved2 };
|
|
145
|
+
}
|
|
146
|
+
const resolved = resolveRefs(spec, operation, /* @__PURE__ */ new Set());
|
|
147
|
+
return { path, method: httpMethod, ...resolved };
|
|
148
|
+
}
|
|
149
|
+
var indexCache = /* @__PURE__ */ new Map();
|
|
150
|
+
async function getOriginIndex(origin) {
|
|
151
|
+
const cached = indexCache.get(origin);
|
|
152
|
+
if (cached) return cached;
|
|
153
|
+
const spec = await fetchOpenApiSpec(origin);
|
|
154
|
+
if (!spec?.paths) return null;
|
|
155
|
+
const endpoints = [];
|
|
156
|
+
for (const [path, methods] of Object.entries(
|
|
157
|
+
spec.paths
|
|
158
|
+
)) {
|
|
159
|
+
for (const [method, operation] of Object.entries(methods)) {
|
|
160
|
+
if (typeof operation === "object" && operation !== null) {
|
|
161
|
+
const op = operation;
|
|
162
|
+
const paymentInfo = op["x-payment-info"];
|
|
163
|
+
const entry = {
|
|
164
|
+
path,
|
|
165
|
+
method: method.toUpperCase(),
|
|
166
|
+
summary: op.summary || op.description || ""
|
|
167
|
+
};
|
|
168
|
+
if (paymentInfo?.price != null) {
|
|
169
|
+
entry.price = `$${paymentInfo.price}`;
|
|
170
|
+
}
|
|
171
|
+
if (Array.isArray(paymentInfo?.protocols)) {
|
|
172
|
+
entry.protocols = paymentInfo.protocols;
|
|
173
|
+
}
|
|
174
|
+
endpoints.push(entry);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
indexCache.set(origin, endpoints);
|
|
179
|
+
return endpoints;
|
|
180
|
+
}
|
|
181
|
+
function getIndexEntry(origin, path, method) {
|
|
182
|
+
const entries = indexCache.get(origin);
|
|
183
|
+
if (!entries) return void 0;
|
|
184
|
+
const m = method.toUpperCase();
|
|
185
|
+
return entries.find((e) => e.path === path && e.method === m);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// src/shared/operations/discover.ts
|
|
189
|
+
var ERROR_TYPE = "discovery";
|
|
190
|
+
async function fetchLlmsTxt(surface, origin) {
|
|
191
|
+
const llmsTxtUrl = `${origin}/llms.txt`;
|
|
192
|
+
log.debug(`Fetching llms.txt from: ${llmsTxtUrl}`);
|
|
193
|
+
const result = await safeFetch(
|
|
194
|
+
surface,
|
|
195
|
+
new Request(llmsTxtUrl, { headers: { Accept: "text/plain" } })
|
|
196
|
+
);
|
|
197
|
+
if (result.isErr()) return null;
|
|
198
|
+
const parseResult = await safeParseResponse(surface, result.value);
|
|
199
|
+
if (parseResult.isErr() || parseResult.value.type !== "text") return null;
|
|
200
|
+
return parseResult.value.data;
|
|
201
|
+
}
|
|
202
|
+
async function discoverResources(surface, url) {
|
|
203
|
+
const origin = URL.canParse(url) ? new URL(url).origin : url;
|
|
204
|
+
log.info(`Discovering resources for origin: ${origin}`);
|
|
205
|
+
const [spec, instructions] = await Promise.all([
|
|
206
|
+
fetchOpenApiSpec(origin),
|
|
207
|
+
fetchLlmsTxt(surface, origin)
|
|
208
|
+
]);
|
|
209
|
+
if (!spec?.paths) {
|
|
210
|
+
return err(ERROR_TYPE, surface, {
|
|
211
|
+
cause: "not_found",
|
|
212
|
+
message: `No OpenAPI spec found for ${origin}. Tried: /openapi.json, /.well-known/openapi.json, /.well-known/x402, /.well-known/mpp`,
|
|
213
|
+
origin
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
const endpoints = await getOriginIndex(origin);
|
|
217
|
+
if (!endpoints || endpoints.length === 0) {
|
|
218
|
+
return err(ERROR_TYPE, surface, {
|
|
219
|
+
cause: "not_found",
|
|
220
|
+
message: `OpenAPI spec found for ${origin} but no endpoints extracted`,
|
|
221
|
+
origin
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
log.info(`Found ${endpoints.length} endpoints for: ${origin}`);
|
|
225
|
+
return ok({
|
|
226
|
+
found: true,
|
|
227
|
+
origin,
|
|
228
|
+
source: "openapi",
|
|
229
|
+
endpoints: endpoints.map(({ path, summary, price }) => ({
|
|
230
|
+
path,
|
|
231
|
+
summary,
|
|
232
|
+
...price ? { price } : {}
|
|
233
|
+
})),
|
|
234
|
+
...instructions ? { instructions } : {}
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// src/shared/neverthrow/x402/index.ts
|
|
239
|
+
import { createSIWxPayload } from "@x402/extensions/sign-in-with-x";
|
|
240
|
+
var errorType = "x402";
|
|
241
|
+
var x402Ok = (value) => ok(value);
|
|
242
|
+
var x402Err = (cause, error) => err(errorType, cause, error);
|
|
243
|
+
var x402ResultFromPromise = (surface, promise, error) => resultFromPromise(errorType, surface, promise, error);
|
|
244
|
+
var x402ResultFromThrowable = (surface, fn, error) => resultFromThrowable(errorType, surface, fn, error);
|
|
245
|
+
var safeGetPaymentRequired = (surface, client, response) => {
|
|
246
|
+
return x402ResultFromPromise(
|
|
247
|
+
surface,
|
|
248
|
+
response.json().then(
|
|
249
|
+
(json) => client.getPaymentRequiredResponse(
|
|
250
|
+
(name) => response.headers.get(name),
|
|
251
|
+
json
|
|
252
|
+
),
|
|
253
|
+
() => client.getPaymentRequiredResponse((name) => response.headers.get(name))
|
|
254
|
+
),
|
|
255
|
+
(error) => ({
|
|
256
|
+
cause: "parse_payment_required",
|
|
257
|
+
message: error instanceof Error ? error.message : "Failed to parse payment required"
|
|
258
|
+
})
|
|
259
|
+
);
|
|
260
|
+
};
|
|
261
|
+
var safeCreatePaymentPayload = (surface, client, paymentRequired) => {
|
|
262
|
+
return x402ResultFromPromise(
|
|
263
|
+
surface,
|
|
264
|
+
client.createPaymentPayload(paymentRequired),
|
|
265
|
+
(error) => ({
|
|
266
|
+
cause: "create_payment_payload",
|
|
267
|
+
message: error instanceof Error ? error.message : "Failed to create payment payload"
|
|
268
|
+
})
|
|
269
|
+
);
|
|
270
|
+
};
|
|
271
|
+
var safeGetPaymentSettlement = (surface, client, response) => {
|
|
272
|
+
return x402ResultFromThrowable(
|
|
273
|
+
surface,
|
|
274
|
+
() => client.getPaymentSettleResponse((name) => response.headers.get(name)),
|
|
275
|
+
(error) => ({
|
|
276
|
+
cause: "get_payment_settlement",
|
|
277
|
+
message: error instanceof Error ? error.message : "Failed to get payment settlement"
|
|
278
|
+
})
|
|
279
|
+
);
|
|
280
|
+
};
|
|
281
|
+
var safeCreateSIWxPayload = (surface, serverInfo, signer) => {
|
|
282
|
+
return x402ResultFromPromise(
|
|
283
|
+
surface,
|
|
284
|
+
createSIWxPayload(serverInfo, signer),
|
|
285
|
+
(error) => ({
|
|
286
|
+
cause: "create_siwx_payload",
|
|
287
|
+
message: error instanceof Error ? error.message : "Failed to create SIWX payload"
|
|
288
|
+
})
|
|
289
|
+
);
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
// src/shared/operations/fetch-with-payment.ts
|
|
293
|
+
function createFetchWithPayment(surface, client) {
|
|
294
|
+
return async (request) => {
|
|
295
|
+
const clonedRequest = request.clone();
|
|
296
|
+
const probeResult = await safeFetch(surface, request);
|
|
297
|
+
if (probeResult.isErr()) {
|
|
298
|
+
return fetchErr(surface, probeResult.error);
|
|
299
|
+
}
|
|
300
|
+
if (probeResult.value.status !== 402) {
|
|
301
|
+
return probeResult.andThen(
|
|
302
|
+
(response2) => fetchOk({
|
|
303
|
+
response: response2,
|
|
304
|
+
paymentPayload: void 0
|
|
305
|
+
})
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
const response = probeResult.value;
|
|
309
|
+
const paymentRequiredResult = await safeGetPaymentRequired(
|
|
310
|
+
surface,
|
|
311
|
+
client,
|
|
312
|
+
response
|
|
313
|
+
);
|
|
314
|
+
if (paymentRequiredResult.isErr()) {
|
|
315
|
+
return paymentRequiredResult;
|
|
316
|
+
}
|
|
317
|
+
const paymentRequired = paymentRequiredResult.value;
|
|
318
|
+
const paymentPayloadResult = await safeCreatePaymentPayload(
|
|
319
|
+
surface,
|
|
320
|
+
client,
|
|
321
|
+
paymentRequired
|
|
322
|
+
);
|
|
323
|
+
if (paymentPayloadResult.isErr()) {
|
|
324
|
+
return paymentPayloadResult;
|
|
325
|
+
}
|
|
326
|
+
const paymentPayload = paymentPayloadResult.value;
|
|
327
|
+
const paymentHeaders = client.encodePaymentSignatureHeader(paymentPayload);
|
|
328
|
+
if (clonedRequest.headers.has("PAYMENT-SIGNATURE") || clonedRequest.headers.has("X-PAYMENT")) {
|
|
329
|
+
return x402Err(surface, {
|
|
330
|
+
cause: "payment_already_attempted",
|
|
331
|
+
message: "Payment already attempted"
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
for (const [key, value] of Object.entries(paymentHeaders)) {
|
|
335
|
+
clonedRequest.headers.set(key, value);
|
|
336
|
+
}
|
|
337
|
+
clonedRequest.headers.set(
|
|
338
|
+
"Access-Control-Expose-Headers",
|
|
339
|
+
"PAYMENT-RESPONSE,X-PAYMENT-RESPONSE"
|
|
340
|
+
);
|
|
341
|
+
return await safeFetch(surface, clonedRequest).andThen(
|
|
342
|
+
(response2) => x402Ok({
|
|
343
|
+
response: response2,
|
|
344
|
+
paymentPayload
|
|
345
|
+
})
|
|
346
|
+
);
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// src/shared/operations/wallet-info.ts
|
|
351
|
+
import { formatUnits } from "viem";
|
|
352
|
+
|
|
353
|
+
// src/shared/tempo.ts
|
|
354
|
+
import { createPublicClient, defineChain, http } from "viem";
|
|
355
|
+
var TEMPO_CHAIN_ID = Number(process.env.TEMPO_CHAIN_ID ?? 42431);
|
|
356
|
+
var TEMPO_RPC_URL = process.env.TEMPO_RPC_URL ?? "https://tempo-moderato.g.alchemy.com/v2/GCnF4KF-qMTaDYNxAOMSC";
|
|
357
|
+
var TEMPO_CHAIN_NAME = process.env.TEMPO_CHAIN_NAME ?? "Tempo";
|
|
358
|
+
var TEMPO_TOKEN_ADDRESS = process.env.TEMPO_TOKEN_ADDRESS ?? "0x20c0000000000000000000000000000000000001";
|
|
359
|
+
function getTempoChainId() {
|
|
360
|
+
return TEMPO_CHAIN_ID;
|
|
361
|
+
}
|
|
362
|
+
function getTempoRpcUrl() {
|
|
363
|
+
return TEMPO_RPC_URL;
|
|
364
|
+
}
|
|
365
|
+
function getTempoChainName() {
|
|
366
|
+
return TEMPO_CHAIN_NAME;
|
|
367
|
+
}
|
|
368
|
+
function getTempoTokenAddress() {
|
|
369
|
+
return TEMPO_TOKEN_ADDRESS;
|
|
370
|
+
}
|
|
371
|
+
var tempoChain = defineChain({
|
|
372
|
+
id: TEMPO_CHAIN_ID,
|
|
373
|
+
name: TEMPO_CHAIN_NAME,
|
|
374
|
+
nativeCurrency: { name: "TEMPO", symbol: "TEMPO", decimals: 18 },
|
|
375
|
+
rpcUrls: {
|
|
376
|
+
default: { http: [TEMPO_RPC_URL] }
|
|
377
|
+
}
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
// src/shared/tempo-balance.ts
|
|
381
|
+
var MPPSCAN_BASE = "https://mppscan.com";
|
|
382
|
+
async function getTempoBalance({
|
|
383
|
+
address,
|
|
384
|
+
tokenAddress
|
|
385
|
+
}) {
|
|
386
|
+
const url = `${MPPSCAN_BASE}/api/balance/${address}`;
|
|
387
|
+
const res = await fetch(url, {
|
|
388
|
+
method: "GET",
|
|
389
|
+
headers: { accept: "application/json" }
|
|
390
|
+
});
|
|
391
|
+
if (!res.ok) {
|
|
392
|
+
throw new Error(`mppscan balance request failed: ${res.status}`);
|
|
393
|
+
}
|
|
394
|
+
const data = await res.json();
|
|
395
|
+
return {
|
|
396
|
+
chainId: getTempoChainId(),
|
|
397
|
+
chainName: getTempoChainName(),
|
|
398
|
+
balance: BigInt(data.balance),
|
|
399
|
+
tokenAddress
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// src/shared/operations/wallet-info.ts
|
|
404
|
+
async function getWalletInfo(surface, address, flags) {
|
|
405
|
+
const [balanceResult, tempoResult] = await Promise.all([
|
|
406
|
+
getBalance({ address, flags, surface }),
|
|
407
|
+
getTempoBalance({ address, tokenAddress: getTempoTokenAddress() }).then((r) => Number(formatUnits(r.balance, 6))).catch((e) => {
|
|
408
|
+
log.info(`Failed to fetch Tempo balance: ${e}`);
|
|
409
|
+
return null;
|
|
410
|
+
})
|
|
411
|
+
]);
|
|
412
|
+
if (balanceResult.isErr()) {
|
|
413
|
+
return balanceResult;
|
|
414
|
+
}
|
|
415
|
+
const baseBalance = balanceResult.value.balance;
|
|
416
|
+
const tempoBalance = tempoResult ?? 0;
|
|
417
|
+
const totalBalance = baseBalance + tempoBalance;
|
|
418
|
+
const chains = [
|
|
419
|
+
{ chain: "Base", balance: baseBalance },
|
|
420
|
+
{ chain: "Tempo", balance: tempoBalance }
|
|
421
|
+
];
|
|
422
|
+
return ok({
|
|
423
|
+
address,
|
|
424
|
+
balance: totalBalance,
|
|
425
|
+
chains,
|
|
426
|
+
isNewWallet: totalBalance === 0,
|
|
427
|
+
depositLink: getDepositLink(address, flags),
|
|
428
|
+
...totalBalance < 2.5 && totalBalance > 0 ? { message: "Your balance is low. Consider topping it up" } : {}
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// src/shared/operations/check-endpoint.ts
|
|
433
|
+
import { x402Client, x402HTTPClient } from "@x402/core/client";
|
|
434
|
+
|
|
435
|
+
// src/shared/token.ts
|
|
436
|
+
import { formatUnits as formatUnits2 } from "viem";
|
|
437
|
+
var tokenStringToNumber = (amount, decimals = 6) => {
|
|
438
|
+
return Number(formatUnits2(BigInt(amount), decimals));
|
|
439
|
+
};
|
|
440
|
+
|
|
441
|
+
// src/server/lib/x402-extensions.ts
|
|
442
|
+
var getBazaarExtension = (extensions) => {
|
|
443
|
+
const { bazaar } = extensions ?? {};
|
|
444
|
+
if (!bazaar) {
|
|
445
|
+
return void 0;
|
|
446
|
+
}
|
|
447
|
+
return bazaar;
|
|
448
|
+
};
|
|
449
|
+
var getInputSchema = (extensions) => getBazaarExtension(extensions)?.schema.properties.input;
|
|
450
|
+
var getSiwxExtension = (extensions) => {
|
|
451
|
+
const siwx = extensions?.["sign-in-with-x"];
|
|
452
|
+
if (!siwx?.info) {
|
|
453
|
+
return void 0;
|
|
454
|
+
}
|
|
455
|
+
const chain = siwx.supportedChains?.find(
|
|
456
|
+
(c) => c.chainId.startsWith("eip155:")
|
|
457
|
+
);
|
|
458
|
+
return {
|
|
459
|
+
...siwx.info,
|
|
460
|
+
chainId: chain?.chainId ?? "eip155:8453",
|
|
461
|
+
type: chain?.type ?? "eip191",
|
|
462
|
+
signatureScheme: chain?.signatureScheme
|
|
463
|
+
};
|
|
464
|
+
};
|
|
465
|
+
|
|
466
|
+
// src/shared/operations/check-endpoint.ts
|
|
467
|
+
async function checkEndpoint(surface, request) {
|
|
468
|
+
log.info("Checking endpoint", request.url);
|
|
469
|
+
const responseResult = await safeFetch(surface, request);
|
|
470
|
+
if (responseResult.isErr()) {
|
|
471
|
+
return responseResult;
|
|
472
|
+
}
|
|
473
|
+
const response = responseResult.value;
|
|
474
|
+
if (!response.ok && response.status !== 402) {
|
|
475
|
+
return responseResult;
|
|
476
|
+
}
|
|
477
|
+
if (response.status !== 402) {
|
|
478
|
+
const parseResponseResult = await safeParseResponse(surface, response);
|
|
479
|
+
if (parseResponseResult.isErr()) {
|
|
480
|
+
return parseResponseResult;
|
|
481
|
+
}
|
|
482
|
+
return ok({
|
|
483
|
+
requiresPayment: false,
|
|
484
|
+
statusCode: response.status,
|
|
485
|
+
parsedResponse: parseResponseResult.value
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
const client = new x402HTTPClient(new x402Client());
|
|
489
|
+
const paymentRequiredResult = await safeGetPaymentRequired(
|
|
490
|
+
surface,
|
|
491
|
+
client,
|
|
492
|
+
response
|
|
493
|
+
);
|
|
494
|
+
if (paymentRequiredResult.isErr()) {
|
|
495
|
+
return paymentRequiredResult;
|
|
496
|
+
}
|
|
497
|
+
const { resource, extensions, accepts } = paymentRequiredResult.value;
|
|
498
|
+
const routeDetails = {
|
|
499
|
+
...resource,
|
|
500
|
+
schema: getInputSchema(extensions),
|
|
501
|
+
paymentMethods: accepts.map((accept) => ({
|
|
502
|
+
price: tokenStringToNumber(accept.amount),
|
|
503
|
+
network: accept.network,
|
|
504
|
+
asset: accept.asset
|
|
505
|
+
}))
|
|
506
|
+
};
|
|
507
|
+
return ok({
|
|
508
|
+
requiresPayment: true,
|
|
509
|
+
statusCode: response.status,
|
|
510
|
+
routeDetails
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// src/shared/operations/report-error.ts
|
|
515
|
+
import { z } from "zod";
|
|
516
|
+
async function submitErrorReport(surface, input, address, dev) {
|
|
517
|
+
const telemetryResult = await safeFetchJson(
|
|
518
|
+
surface,
|
|
519
|
+
new Request(`${getBaseUrl(dev)}/api/telemetry`, {
|
|
520
|
+
method: "POST",
|
|
521
|
+
headers: {
|
|
522
|
+
"Content-Type": "application/json"
|
|
523
|
+
},
|
|
524
|
+
body: JSON.stringify({
|
|
525
|
+
tool: input.tool,
|
|
526
|
+
summary: input.summary,
|
|
527
|
+
errorMessage: input.errorMessage,
|
|
528
|
+
resource: input.resource,
|
|
529
|
+
stack: input.stack,
|
|
530
|
+
fullReport: input.fullReport,
|
|
531
|
+
walletAddress: address,
|
|
532
|
+
mcpVersion: MCP_VERSION,
|
|
533
|
+
reportedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
534
|
+
})
|
|
535
|
+
}),
|
|
536
|
+
z.object({
|
|
537
|
+
reportId: z.string()
|
|
538
|
+
})
|
|
539
|
+
);
|
|
540
|
+
if (telemetryResult.isErr()) {
|
|
541
|
+
return telemetryResult;
|
|
542
|
+
}
|
|
543
|
+
const { reportId } = telemetryResult.value;
|
|
544
|
+
return ok({
|
|
545
|
+
submitted: true,
|
|
546
|
+
reportId,
|
|
547
|
+
message: "Error report submitted successfully. The agentcash team will investigate."
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
export {
|
|
552
|
+
tokenStringToNumber,
|
|
553
|
+
x402Ok,
|
|
554
|
+
x402Err,
|
|
555
|
+
safeGetPaymentRequired,
|
|
556
|
+
safeCreatePaymentPayload,
|
|
557
|
+
safeGetPaymentSettlement,
|
|
558
|
+
safeCreateSIWxPayload,
|
|
559
|
+
fetchOpenApiSpec,
|
|
560
|
+
getEndpointSchema,
|
|
561
|
+
getOriginIndex,
|
|
562
|
+
getIndexEntry,
|
|
563
|
+
discoverResources,
|
|
564
|
+
createFetchWithPayment,
|
|
565
|
+
getTempoChainId,
|
|
566
|
+
getTempoRpcUrl,
|
|
567
|
+
getTempoTokenAddress,
|
|
568
|
+
getTempoBalance,
|
|
569
|
+
getWalletInfo,
|
|
570
|
+
getInputSchema,
|
|
571
|
+
getSiwxExtension,
|
|
572
|
+
checkEndpoint,
|
|
573
|
+
submitErrorReport
|
|
574
|
+
};
|
|
575
|
+
//# sourceMappingURL=chunk-E3MKYUQQ.js.map
|