x402-proxy 0.8.2 → 0.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -1
- package/dist/bin/cli.js +32 -15
- package/dist/openclaw/plugin.js +1 -1
- package/dist/{status-CJPUbh6Z.js → status-DjudJ6fD.js} +1 -1
- package/dist/{status-S3t-XV_M.js → status-DvSu8reM.js} +1 -1
- package/dist/{wallet-CeY5DPj-.js → wallet-BiX5_XFY.js} +23 -0
- package/dist/{wallet-CJBRFJw8.js → wallet-BkZ0DOJL.js} +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.8.4] - 2026-03-24
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- Servers returning Solana payment options with EVM-format `payTo` addresses (e.g. `0x...`) no longer crash with a base58 decode error - malformed options are filtered out and valid options are used instead
|
|
14
|
+
- When all payment options from a server have mismatched address formats, a clear error is shown instead of a cryptic codec failure
|
|
15
|
+
|
|
16
|
+
## [0.8.3] - 2026-03-24
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
- JSON response pretty-printing: non-streaming `application/json` responses auto-formatted with 2-space indent on TTY
|
|
20
|
+
- `--json` flag now works: forces JSON pretty-printing even when piped (non-TTY)
|
|
21
|
+
- Color-coded HTTP status lines: green for 2xx, yellow for 3xx, red for 4xx/5xx
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
- MPP streaming payment label unified from `MPP session:` to `Payment: ... MPP` to match non-streaming format
|
|
25
|
+
- MPP streaming status line now starts on a new line instead of appending to last JSON chunk
|
|
26
|
+
|
|
10
27
|
## [0.8.2] - 2026-03-24
|
|
11
28
|
|
|
12
29
|
### Fixed
|
|
@@ -219,7 +236,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
219
236
|
- `appendHistory` / `readHistory` / `calcSpend` - JSONL transaction history
|
|
220
237
|
- Re-exports from `@x402/fetch`, `@x402/svm`, `@x402/evm`
|
|
221
238
|
|
|
222
|
-
[Unreleased]: https://github.com/cascade-protocol/x402-proxy/compare/v0.8.
|
|
239
|
+
[Unreleased]: https://github.com/cascade-protocol/x402-proxy/compare/v0.8.4...HEAD
|
|
240
|
+
[0.8.4]: https://github.com/cascade-protocol/x402-proxy/compare/v0.8.3...v0.8.4
|
|
241
|
+
[0.8.3]: https://github.com/cascade-protocol/x402-proxy/compare/v0.8.2...v0.8.3
|
|
223
242
|
[0.8.2]: https://github.com/cascade-protocol/x402-proxy/compare/v0.8.1...v0.8.2
|
|
224
243
|
[0.8.1]: https://github.com/cascade-protocol/x402-proxy/compare/v0.8.0...v0.8.1
|
|
225
244
|
[0.8.0]: https://github.com/cascade-protocol/x402-proxy/compare/v0.7.1...v0.8.0
|
package/dist/bin/cli.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { a as getHistoryPath, c as loadConfig, i as getConfigDirShort, l as loadWalletFile, s as isConfigured, u as saveConfig } from "../derive-BR6N1ZjI.js";
|
|
3
|
-
import { _ as error, b as warn, c as resolveWallet, d as displayNetwork, f as formatAmount, g as dim, h as readHistory, l as appendHistory, m as formatUsdcValue, o as walletInfoCommand, p as formatTxLine, s as buildX402Client, u as calcSpend, v as info, y as isTTY } from "../wallet-
|
|
3
|
+
import { _ as error, b as warn, c as resolveWallet, d as displayNetwork, f as formatAmount, g as dim, h as readHistory, l as appendHistory, m as formatUsdcValue, o as walletInfoCommand, p as formatTxLine, s as buildX402Client, u as calcSpend, v as info, y as isTTY } from "../wallet-BiX5_XFY.js";
|
|
4
4
|
import { n as setupCommand } from "../setup-Di_b5Vp9.js";
|
|
5
|
-
import { n as statusCommand } from "../status-
|
|
5
|
+
import { n as statusCommand } from "../status-DvSu8reM.js";
|
|
6
6
|
import { buildApplication, buildCommand, buildRouteMap, run } from "@stricli/core";
|
|
7
7
|
import pc from "picocolors";
|
|
8
8
|
import { decodePaymentResponseHeader, wrapFetchWithPayment } from "@x402/fetch";
|
|
@@ -301,6 +301,9 @@ async function createMppProxyHandler(opts) {
|
|
|
301
301
|
|
|
302
302
|
//#endregion
|
|
303
303
|
//#region src/commands/fetch.ts
|
|
304
|
+
function isStreamingResponse(res) {
|
|
305
|
+
return (res.headers.get("content-type") ?? "").includes("text/event-stream");
|
|
306
|
+
}
|
|
304
307
|
const fetchCommand = buildCommand({
|
|
305
308
|
docs: {
|
|
306
309
|
brief: "Make a paid HTTP request (default command)",
|
|
@@ -395,7 +398,7 @@ Examples:
|
|
|
395
398
|
};
|
|
396
399
|
if (!url) {
|
|
397
400
|
if (isConfigured()) {
|
|
398
|
-
const { displayStatus } = await import("../status-
|
|
401
|
+
const { displayStatus } = await import("../status-DjudJ6fD.js");
|
|
399
402
|
await displayStatus();
|
|
400
403
|
console.log();
|
|
401
404
|
console.log(pc.dim(" Commands:"));
|
|
@@ -460,7 +463,7 @@ Examples:
|
|
|
460
463
|
verbose(`protocol: ${resolvedProtocol ?? "auto-detect"}, maxDeposit: ${maxDeposit}`);
|
|
461
464
|
let preferredNetwork = config?.defaultNetwork;
|
|
462
465
|
if (!preferredNetwork && wallet.evmAddress && wallet.solanaAddress) {
|
|
463
|
-
const { fetchAllBalances } = await import("../wallet-
|
|
466
|
+
const { fetchAllBalances } = await import("../wallet-BkZ0DOJL.js");
|
|
464
467
|
const balances = await fetchAllBalances(wallet.evmAddress, wallet.solanaAddress);
|
|
465
468
|
const evmUsdc = balances.evm ? Number(balances.evm.usdc) : 0;
|
|
466
469
|
const solUsdc = balances.sol ? Number(balances.sol.usdc) : 0;
|
|
@@ -527,7 +530,8 @@ Examples:
|
|
|
527
530
|
usedProtocol = "mpp";
|
|
528
531
|
const elapsedMs = Date.now() - startMs;
|
|
529
532
|
const spentAmount = mppPayment.amount ? Number(mppPayment.amount) : void 0;
|
|
530
|
-
if (
|
|
533
|
+
if (isTTY()) process.stderr.write("\n");
|
|
534
|
+
if (mppPayment && isTTY()) info(` Payment:${spentAmount != null ? ` ${formatAmount(spentAmount, "USDC")}` : ""} MPP (${displayNetwork(mppPayment.network)})`);
|
|
531
535
|
if (isTTY()) dim(` Streamed (${elapsedMs}ms)`);
|
|
532
536
|
if (mppPayment) {
|
|
533
537
|
const record = {
|
|
@@ -626,7 +630,7 @@ Examples:
|
|
|
626
630
|
const hasSolana = accepts.some((a) => a.network.startsWith("solana:"));
|
|
627
631
|
const hasMpp = detected.mpp;
|
|
628
632
|
const hasOther = accepts.some((a) => !a.network.startsWith("eip155:") && !a.network.startsWith("solana:"));
|
|
629
|
-
const { fetchAllBalances } = await import("../wallet-
|
|
633
|
+
const { fetchAllBalances } = await import("../wallet-BkZ0DOJL.js");
|
|
630
634
|
const balances = await fetchAllBalances(wallet.evmAddress, wallet.solanaAddress);
|
|
631
635
|
const evmUsdc = hasEvm && balances.evm ? Number(balances.evm.usdc) : 0;
|
|
632
636
|
const solUsdc = hasSolana && balances.sol ? Number(balances.sol.usdc) : 0;
|
|
@@ -688,7 +692,11 @@ Examples:
|
|
|
688
692
|
else if (x402Payment) info(` Payment: ${x402Payment.amount ? formatAmount(Number(x402Payment.amount) / 1e6, "USDC") : "? USDC"} (${displayNetwork(x402Payment.network ?? "unknown")})`);
|
|
689
693
|
if (txSig) dim(` Tx: ${txSig}`);
|
|
690
694
|
}
|
|
691
|
-
if (isTTY())
|
|
695
|
+
if (isTTY()) {
|
|
696
|
+
const statusText = ` ${response.status} ${response.statusText} (${elapsedMs}ms)`;
|
|
697
|
+
const colorFn = response.status < 300 ? pc.green : response.status < 400 ? pc.yellow : pc.red;
|
|
698
|
+
process.stderr.write(`${colorFn(statusText)}\n`);
|
|
699
|
+
}
|
|
692
700
|
if (x402Payment) {
|
|
693
701
|
const record = {
|
|
694
702
|
t: Date.now(),
|
|
@@ -719,7 +727,16 @@ Examples:
|
|
|
719
727
|
};
|
|
720
728
|
appendHistory(getHistoryPath(), record);
|
|
721
729
|
}
|
|
722
|
-
|
|
730
|
+
const shouldPrettyPrint = (response.headers.get("content-type") ?? "").includes("application/json") && (flags.json || isTTY()) && !isStreamingResponse(response);
|
|
731
|
+
if (response.body) if (shouldPrettyPrint) {
|
|
732
|
+
const text = await response.text();
|
|
733
|
+
try {
|
|
734
|
+
process.stdout.write(`${JSON.stringify(JSON.parse(text), null, 2)}\n`);
|
|
735
|
+
} catch {
|
|
736
|
+
process.stdout.write(text);
|
|
737
|
+
if (isTTY()) process.stdout.write("\n");
|
|
738
|
+
}
|
|
739
|
+
} else {
|
|
723
740
|
const reader = response.body.getReader();
|
|
724
741
|
try {
|
|
725
742
|
while (true) {
|
|
@@ -730,8 +747,8 @@ Examples:
|
|
|
730
747
|
} finally {
|
|
731
748
|
reader.releaseLock();
|
|
732
749
|
}
|
|
750
|
+
if (isTTY()) process.stdout.write("\n");
|
|
733
751
|
}
|
|
734
|
-
if (isTTY() && response.body) process.stdout.write("\n");
|
|
735
752
|
}
|
|
736
753
|
});
|
|
737
754
|
|
|
@@ -823,7 +840,7 @@ Add to your MCP client config (Claude, Cursor, etc.):
|
|
|
823
840
|
async function startX402Proxy() {
|
|
824
841
|
let preferredNetwork = config?.defaultNetwork;
|
|
825
842
|
if (!preferredNetwork && wallet.evmAddress && wallet.solanaAddress) {
|
|
826
|
-
const { fetchAllBalances } = await import("../wallet-
|
|
843
|
+
const { fetchAllBalances } = await import("../wallet-BkZ0DOJL.js");
|
|
827
844
|
const balances = await fetchAllBalances(wallet.evmAddress, wallet.solanaAddress);
|
|
828
845
|
const evmUsdc = balances.evm ? Number(balances.evm.usdc) : 0;
|
|
829
846
|
const solUsdc = balances.sol ? Number(balances.sol.usdc) : 0;
|
|
@@ -843,7 +860,7 @@ Add to your MCP client config (Claude, Cursor, etc.):
|
|
|
843
860
|
}
|
|
844
861
|
const remoteClient = new Client({
|
|
845
862
|
name: "x402-proxy",
|
|
846
|
-
version: "0.8.
|
|
863
|
+
version: "0.8.4"
|
|
847
864
|
});
|
|
848
865
|
const x402Mcp = new x402MCPClient(remoteClient, x402PaymentClient, {
|
|
849
866
|
autoPayment: true,
|
|
@@ -881,7 +898,7 @@ Add to your MCP client config (Claude, Cursor, etc.):
|
|
|
881
898
|
}
|
|
882
899
|
const localServer = new Server({
|
|
883
900
|
name: "x402-proxy",
|
|
884
|
-
version: "0.8.
|
|
901
|
+
version: "0.8.4"
|
|
885
902
|
}, { capabilities: {
|
|
886
903
|
tools: tools.length > 0 ? {} : void 0,
|
|
887
904
|
resources: remoteResources.length > 0 ? {} : void 0
|
|
@@ -976,7 +993,7 @@ Add to your MCP client config (Claude, Cursor, etc.):
|
|
|
976
993
|
}));
|
|
977
994
|
const remoteClient = new Client({
|
|
978
995
|
name: "x402-proxy",
|
|
979
|
-
version: "0.8.
|
|
996
|
+
version: "0.8.4"
|
|
980
997
|
});
|
|
981
998
|
await connectTransport(remoteClient);
|
|
982
999
|
const mppClient = McpClient.wrap(remoteClient, { methods: wrappedMethods });
|
|
@@ -991,7 +1008,7 @@ Add to your MCP client config (Claude, Cursor, etc.):
|
|
|
991
1008
|
}
|
|
992
1009
|
const localServer = new Server({
|
|
993
1010
|
name: "x402-proxy",
|
|
994
|
-
version: "0.8.
|
|
1011
|
+
version: "0.8.4"
|
|
995
1012
|
}, { capabilities: {
|
|
996
1013
|
tools: tools.length > 0 ? {} : void 0,
|
|
997
1014
|
resources: remoteResources.length > 0 ? {} : void 0
|
|
@@ -1203,7 +1220,7 @@ const routes = buildRouteMap({
|
|
|
1203
1220
|
});
|
|
1204
1221
|
const app = buildApplication(routes, {
|
|
1205
1222
|
name: "x402-proxy",
|
|
1206
|
-
versionInfo: { currentVersion: "0.8.
|
|
1223
|
+
versionInfo: { currentVersion: "0.8.4" },
|
|
1207
1224
|
scanner: { caseStyle: "allow-kebab-for-camel" }
|
|
1208
1225
|
});
|
|
1209
1226
|
|
package/dist/openclaw/plugin.js
CHANGED
|
@@ -726,7 +726,7 @@ function createWalletCommand(ctx) {
|
|
|
726
726
|
try {
|
|
727
727
|
const snap = await getWalletSnapshot(ctx.rpcUrl, walletAddress, ctx.historyPath);
|
|
728
728
|
const solscanUrl = `https://solscan.io/account/${walletAddress}`;
|
|
729
|
-
const lines = [`x402-proxy v0.8.
|
|
729
|
+
const lines = [`x402-proxy v0.8.4`];
|
|
730
730
|
const defaultModel = ctx.allModels[0];
|
|
731
731
|
if (defaultModel) lines.push("", `**Model** - ${defaultModel.name} (${defaultModel.provider})`);
|
|
732
732
|
lines.push("", `**[Wallet](${solscanUrl})**`, `\`${walletAddress}\``);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { a as getHistoryPath, c as loadConfig, i as getConfigDirShort } from "./derive-BR6N1ZjI.js";
|
|
3
|
-
import { c as resolveWallet, f as formatAmount, g as dim, h as readHistory, m as formatUsdcValue, n as fetchAllBalances, p as formatTxLine, t as balanceLine, u as calcSpend } from "./wallet-
|
|
3
|
+
import { c as resolveWallet, f as formatAmount, g as dim, h as readHistory, m as formatUsdcValue, n as fetchAllBalances, p as formatTxLine, t as balanceLine, u as calcSpend } from "./wallet-BiX5_XFY.js";
|
|
4
4
|
import { buildCommand } from "@stricli/core";
|
|
5
5
|
import pc from "picocolors";
|
|
6
6
|
|
|
@@ -236,6 +236,28 @@ function networkToCaipPrefix(name) {
|
|
|
236
236
|
default: return name;
|
|
237
237
|
}
|
|
238
238
|
}
|
|
239
|
+
/**
|
|
240
|
+
* Validate that payTo addresses match the network format.
|
|
241
|
+
* Filters out malformed entries (e.g. EVM hex address on a Solana network).
|
|
242
|
+
*/
|
|
243
|
+
function createAddressValidationPolicy() {
|
|
244
|
+
return (_version, reqs) => {
|
|
245
|
+
const malformed = [];
|
|
246
|
+
const valid = reqs.filter((r) => {
|
|
247
|
+
if (r.network.startsWith("solana:") && r.payTo.startsWith("0x")) {
|
|
248
|
+
malformed.push(`Solana option has EVM-format payTo (${r.payTo})`);
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
251
|
+
if (r.network.startsWith("eip155:") && !r.payTo.startsWith("0x")) {
|
|
252
|
+
malformed.push(`EVM option has non-EVM payTo (${r.payTo})`);
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
return true;
|
|
256
|
+
});
|
|
257
|
+
if (valid.length === 0 && malformed.length > 0) throw new Error(`Server returned only malformed payment options:\n ${malformed.join("\n ")}\nThe server's payTo addresses don't match the advertised networks.`);
|
|
258
|
+
return valid;
|
|
259
|
+
};
|
|
260
|
+
}
|
|
239
261
|
function createNetworkFilter(network) {
|
|
240
262
|
const prefix = networkToCaipPrefix(network);
|
|
241
263
|
return (_version, reqs) => {
|
|
@@ -269,6 +291,7 @@ async function buildX402Client(wallet, opts) {
|
|
|
269
291
|
const { createKeyPairSignerFromBytes } = await import("@solana/kit");
|
|
270
292
|
registerExactSvmScheme(client, { signer: await createKeyPairSignerFromBytes(wallet.solanaKey) });
|
|
271
293
|
}
|
|
294
|
+
client.registerPolicy(createAddressValidationPolicy());
|
|
272
295
|
if (opts?.network) client.registerPolicy(createNetworkFilter(opts.network));
|
|
273
296
|
const daily = opts?.spendLimitDaily;
|
|
274
297
|
const perTx = opts?.spendLimitPerTx;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as fetchTempoBalances, i as fetchSolanaBalances, n as fetchAllBalances, o as walletInfoCommand, r as fetchEvmBalances, t as balanceLine } from "./wallet-
|
|
2
|
+
import { a as fetchTempoBalances, i as fetchSolanaBalances, n as fetchAllBalances, o as walletInfoCommand, r as fetchEvmBalances, t as balanceLine } from "./wallet-BiX5_XFY.js";
|
|
3
3
|
|
|
4
4
|
export { fetchAllBalances };
|
package/package.json
CHANGED