x402-proxy 0.8.3 → 0.8.5

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 CHANGED
@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.8.5] - 2026-03-24
11
+
12
+ ### Fixed
13
+ - OpenClaw plugin: models now appear in `openclaw models` list - replaced invalid `models` field on `registerProvider()` with a `catalog` hook returning `ProviderCatalogResult`, which is required by OpenClaw's provider discovery filter
14
+
15
+ ## [0.8.4] - 2026-03-24
16
+
17
+ ### Fixed
18
+ - 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
19
+ - When all payment options from a server have mismatched address formats, a clear error is shown instead of a cryptic codec failure
20
+
10
21
  ## [0.8.3] - 2026-03-24
11
22
 
12
23
  ### Added
@@ -230,7 +241,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
230
241
  - `appendHistory` / `readHistory` / `calcSpend` - JSONL transaction history
231
242
  - Re-exports from `@x402/fetch`, `@x402/svm`, `@x402/evm`
232
243
 
233
- [Unreleased]: https://github.com/cascade-protocol/x402-proxy/compare/v0.8.3...HEAD
244
+ [Unreleased]: https://github.com/cascade-protocol/x402-proxy/compare/v0.8.4...HEAD
245
+ [0.8.5]: https://github.com/cascade-protocol/x402-proxy/compare/v0.8.4...v0.8.5
246
+ [0.8.4]: https://github.com/cascade-protocol/x402-proxy/compare/v0.8.3...v0.8.4
234
247
  [0.8.3]: https://github.com/cascade-protocol/x402-proxy/compare/v0.8.2...v0.8.3
235
248
  [0.8.2]: https://github.com/cascade-protocol/x402-proxy/compare/v0.8.1...v0.8.2
236
249
  [0.8.1]: https://github.com/cascade-protocol/x402-proxy/compare/v0.8.0...v0.8.1
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-CeY5DPj-.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-BiX5_XFY.js";
4
4
  import { n as setupCommand } from "../setup-Di_b5Vp9.js";
5
- import { n as statusCommand } from "../status-S3t-XV_M.js";
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";
@@ -398,7 +398,7 @@ Examples:
398
398
  };
399
399
  if (!url) {
400
400
  if (isConfigured()) {
401
- const { displayStatus } = await import("../status-CJPUbh6Z.js");
401
+ const { displayStatus } = await import("../status-DjudJ6fD.js");
402
402
  await displayStatus();
403
403
  console.log();
404
404
  console.log(pc.dim(" Commands:"));
@@ -463,7 +463,7 @@ Examples:
463
463
  verbose(`protocol: ${resolvedProtocol ?? "auto-detect"}, maxDeposit: ${maxDeposit}`);
464
464
  let preferredNetwork = config?.defaultNetwork;
465
465
  if (!preferredNetwork && wallet.evmAddress && wallet.solanaAddress) {
466
- const { fetchAllBalances } = await import("../wallet-CJBRFJw8.js");
466
+ const { fetchAllBalances } = await import("../wallet-BkZ0DOJL.js");
467
467
  const balances = await fetchAllBalances(wallet.evmAddress, wallet.solanaAddress);
468
468
  const evmUsdc = balances.evm ? Number(balances.evm.usdc) : 0;
469
469
  const solUsdc = balances.sol ? Number(balances.sol.usdc) : 0;
@@ -630,7 +630,7 @@ Examples:
630
630
  const hasSolana = accepts.some((a) => a.network.startsWith("solana:"));
631
631
  const hasMpp = detected.mpp;
632
632
  const hasOther = accepts.some((a) => !a.network.startsWith("eip155:") && !a.network.startsWith("solana:"));
633
- const { fetchAllBalances } = await import("../wallet-CJBRFJw8.js");
633
+ const { fetchAllBalances } = await import("../wallet-BkZ0DOJL.js");
634
634
  const balances = await fetchAllBalances(wallet.evmAddress, wallet.solanaAddress);
635
635
  const evmUsdc = hasEvm && balances.evm ? Number(balances.evm.usdc) : 0;
636
636
  const solUsdc = hasSolana && balances.sol ? Number(balances.sol.usdc) : 0;
@@ -840,7 +840,7 @@ Add to your MCP client config (Claude, Cursor, etc.):
840
840
  async function startX402Proxy() {
841
841
  let preferredNetwork = config?.defaultNetwork;
842
842
  if (!preferredNetwork && wallet.evmAddress && wallet.solanaAddress) {
843
- const { fetchAllBalances } = await import("../wallet-CJBRFJw8.js");
843
+ const { fetchAllBalances } = await import("../wallet-BkZ0DOJL.js");
844
844
  const balances = await fetchAllBalances(wallet.evmAddress, wallet.solanaAddress);
845
845
  const evmUsdc = balances.evm ? Number(balances.evm.usdc) : 0;
846
846
  const solUsdc = balances.sol ? Number(balances.sol.usdc) : 0;
@@ -860,7 +860,7 @@ Add to your MCP client config (Claude, Cursor, etc.):
860
860
  }
861
861
  const remoteClient = new Client({
862
862
  name: "x402-proxy",
863
- version: "0.8.3"
863
+ version: "0.8.5"
864
864
  });
865
865
  const x402Mcp = new x402MCPClient(remoteClient, x402PaymentClient, {
866
866
  autoPayment: true,
@@ -898,7 +898,7 @@ Add to your MCP client config (Claude, Cursor, etc.):
898
898
  }
899
899
  const localServer = new Server({
900
900
  name: "x402-proxy",
901
- version: "0.8.3"
901
+ version: "0.8.5"
902
902
  }, { capabilities: {
903
903
  tools: tools.length > 0 ? {} : void 0,
904
904
  resources: remoteResources.length > 0 ? {} : void 0
@@ -993,7 +993,7 @@ Add to your MCP client config (Claude, Cursor, etc.):
993
993
  }));
994
994
  const remoteClient = new Client({
995
995
  name: "x402-proxy",
996
- version: "0.8.3"
996
+ version: "0.8.5"
997
997
  });
998
998
  await connectTransport(remoteClient);
999
999
  const mppClient = McpClient.wrap(remoteClient, { methods: wrappedMethods });
@@ -1008,7 +1008,7 @@ Add to your MCP client config (Claude, Cursor, etc.):
1008
1008
  }
1009
1009
  const localServer = new Server({
1010
1010
  name: "x402-proxy",
1011
- version: "0.8.3"
1011
+ version: "0.8.5"
1012
1012
  }, { capabilities: {
1013
1013
  tools: tools.length > 0 ? {} : void 0,
1014
1014
  resources: remoteResources.length > 0 ? {} : void 0
@@ -1220,7 +1220,7 @@ const routes = buildRouteMap({
1220
1220
  });
1221
1221
  const app = buildApplication(routes, {
1222
1222
  name: "x402-proxy",
1223
- versionInfo: { currentVersion: "0.8.3" },
1223
+ versionInfo: { currentVersion: "0.8.5" },
1224
1224
  scanner: { caseStyle: "allow-kebab-for-camel" }
1225
1225
  });
1226
1226
 
@@ -17,6 +17,14 @@ type ModelEntry = {
17
17
  };
18
18
  //#endregion
19
19
  //#region src/openclaw/plugin.d.ts
20
+ type ProviderCatalogResult = {
21
+ provider: {
22
+ baseUrl: string;
23
+ api?: string;
24
+ authHeader?: boolean;
25
+ models: Array<Omit<ModelEntry, "provider">>;
26
+ };
27
+ } | null;
20
28
  type OpenClawPluginApi = {
21
29
  pluginConfig?: Record<string, unknown>;
22
30
  logger: {
@@ -27,13 +35,9 @@ type OpenClawPluginApi = {
27
35
  id: string;
28
36
  label: string;
29
37
  auth: unknown[];
30
- models: {
31
- baseUrl: string;
32
- api: string;
33
- authHeader: boolean;
34
- models: Array<Omit<ModelEntry, "provider"> & {
35
- input: Array<"text" | "image">;
36
- }>;
38
+ catalog: {
39
+ order?: "simple" | "profile" | "paired" | "late";
40
+ run: (ctx: unknown) => Promise<ProviderCatalogResult>;
37
41
  };
38
42
  }) => void;
39
43
  registerTool: (tool: unknown) => void;
@@ -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.3`];
729
+ const lines = [`x402-proxy v0.8.5`];
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}\``);
@@ -1026,11 +1026,14 @@ function register(api) {
1026
1026
  id: name,
1027
1027
  label: `${name} (x402)`,
1028
1028
  auth: [],
1029
- models: {
1030
- baseUrl: prov.baseUrl,
1031
- api: "openai-completions",
1032
- authHeader: false,
1033
- models: prov.models
1029
+ catalog: {
1030
+ order: "simple",
1031
+ run: async () => ({ provider: {
1032
+ baseUrl: prov.baseUrl,
1033
+ api: "openai-completions",
1034
+ authHeader: false,
1035
+ models: prov.models
1036
+ } })
1034
1037
  }
1035
1038
  });
1036
1039
  api.logger.info(`x402-proxy: ${Object.keys(raw).join(", ")} - ${allModels.length} models, ${upstreamOrigins.length} x402 endpoints`);
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import { n as statusCommand, t as displayStatus } from "./status-S3t-XV_M.js";
2
+ import { n as statusCommand, t as displayStatus } from "./status-DvSu8reM.js";
3
3
 
4
4
  export { displayStatus };
@@ -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-CeY5DPj-.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-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-CeY5DPj-.js";
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "x402-proxy",
3
- "version": "0.8.3",
3
+ "version": "0.8.5",
4
4
  "description": "curl for x402 paid APIs. Auto-pays any endpoint on Base, Solana, and Tempo. Also works as an OpenClaw plugin.",
5
5
  "type": "module",
6
6
  "sideEffects": false,