x402-proxy 0.8.0 → 0.8.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/CHANGELOG.md CHANGED
@@ -7,6 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.8.2] - 2026-03-24
11
+
12
+ ### Fixed
13
+ - JSON request bodies sent without explicit `Content-Type` header now auto-detect as `application/json` instead of defaulting to `text/plain` - fixes servers rejecting JSON bodies on payment retry
14
+
15
+ ## [0.8.1] - 2026-03-24
16
+
17
+ ### Added
18
+ - Curl-style short flags: `-X` (method), `-H` (header), `-d` (body) for the `fetch` command
19
+ - `-H` preprocessing in CLI entry point to work around Stricli reserving `-H` for `--help-all`
20
+
21
+ ### Fixed
22
+ - SSE streaming resilience: swallow Node.js "terminated" errors when server closes connection after final event, so payment logging still completes
23
+ - Bumped `mppx` to ^0.4.9 (fixes 204-safe SSE receipt wrapping and idempotent voucher replay)
24
+
10
25
  ## [0.8.0] - 2026-03-21
11
26
 
12
27
  ### Added
@@ -204,7 +219,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
204
219
  - `appendHistory` / `readHistory` / `calcSpend` - JSONL transaction history
205
220
  - Re-exports from `@x402/fetch`, `@x402/svm`, `@x402/evm`
206
221
 
207
- [Unreleased]: https://github.com/cascade-protocol/x402-proxy/compare/v0.8.0...HEAD
222
+ [Unreleased]: https://github.com/cascade-protocol/x402-proxy/compare/v0.8.2...HEAD
223
+ [0.8.2]: https://github.com/cascade-protocol/x402-proxy/compare/v0.8.1...v0.8.2
224
+ [0.8.1]: https://github.com/cascade-protocol/x402-proxy/compare/v0.8.0...v0.8.1
208
225
  [0.8.0]: https://github.com/cascade-protocol/x402-proxy/compare/v0.7.1...v0.8.0
209
226
  [0.7.1]: https://github.com/cascade-protocol/x402-proxy/compare/v0.7.0...v0.7.1
210
227
  [0.7.0]: https://github.com/cascade-protocol/x402-proxy/compare/v0.6.0...v0.7.0
package/README.md CHANGED
@@ -40,10 +40,10 @@ Works like curl. Response body streams to stdout, payment info goes to stderr.
40
40
  # GET request
41
41
  $ npx x402-proxy https://twitter.surf.cascade.fyi/users/cascade_fyi
42
42
 
43
- # POST with body and headers
44
- $ npx x402-proxy --method POST \
45
- --header "Content-Type: application/json" \
46
- --body '{"url":"https://x402.org"}' \
43
+ # POST with body and headers (curl-style short flags: -X, -H, -d)
44
+ $ npx x402-proxy -X POST \
45
+ -H "Content-Type: application/json" \
46
+ -d '{"url":"https://x402.org"}' \
47
47
  https://web.surf.cascade.fyi/v1/crawl
48
48
 
49
49
  # Force a specific network
@@ -54,9 +54,8 @@ $ npx x402-proxy --verbose https://api.example.com/data
54
54
 
55
55
  # Use MPP protocol for streaming payments
56
56
  $ npx x402-proxy --protocol mpp \
57
- --method POST \
58
- --header "Content-Type: application/json" \
59
- --body '{"model":"minimax/minimax-m2.5","stream":true,"messages":[{"role":"user","content":"Hello"}]}' \
57
+ -X POST -H "Content-Type: application/json" \
58
+ -d '{"model":"minimax/minimax-m2.5","stream":true,"messages":[{"role":"user","content":"Hello"}]}' \
60
59
  https://inference.surf.cascade.fyi/v1/chat/completions
61
60
 
62
61
  # Pipe-safe
package/dist/bin/cli.js CHANGED
@@ -367,6 +367,10 @@ Examples:
367
367
  default: false
368
368
  }
369
369
  },
370
+ aliases: {
371
+ X: "method",
372
+ d: "body"
373
+ },
370
374
  positional: {
371
375
  kind: "tuple",
372
376
  parameters: [{
@@ -469,6 +473,10 @@ Examples:
469
473
  if (idx > 0) headers.set(h.slice(0, idx).trim(), h.slice(idx + 1).trim());
470
474
  }
471
475
  const method = flags.method || "GET";
476
+ if (flags.body && !headers.has("Content-Type")) {
477
+ const trimmed = flags.body.trimStart();
478
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) headers.set("Content-Type", "application/json");
479
+ }
472
480
  const init = {
473
481
  method,
474
482
  headers: Object.fromEntries(headers.entries())
@@ -497,7 +505,13 @@ Examples:
497
505
  verbose("opening SSE session...");
498
506
  const tokens = await mppHandler.sse(parsedUrl.toString(), init);
499
507
  verbose("SSE stream opened, reading tokens...");
500
- for await (const token of tokens) process.stdout.write(token);
508
+ try {
509
+ for await (const token of tokens) process.stdout.write(token);
510
+ } catch (streamErr) {
511
+ const msg = streamErr instanceof Error ? streamErr.message : String(streamErr);
512
+ verbose(`SSE stream error: ${msg}`);
513
+ if (!msg.includes("terminated")) throw streamErr;
514
+ }
501
515
  verbose("SSE stream complete");
502
516
  } finally {
503
517
  await closeMppSession(mppHandler);
@@ -829,7 +843,7 @@ Add to your MCP client config (Claude, Cursor, etc.):
829
843
  }
830
844
  const remoteClient = new Client({
831
845
  name: "x402-proxy",
832
- version: "0.8.0"
846
+ version: "0.8.2"
833
847
  });
834
848
  const x402Mcp = new x402MCPClient(remoteClient, x402PaymentClient, {
835
849
  autoPayment: true,
@@ -867,7 +881,7 @@ Add to your MCP client config (Claude, Cursor, etc.):
867
881
  }
868
882
  const localServer = new Server({
869
883
  name: "x402-proxy",
870
- version: "0.8.0"
884
+ version: "0.8.2"
871
885
  }, { capabilities: {
872
886
  tools: tools.length > 0 ? {} : void 0,
873
887
  resources: remoteResources.length > 0 ? {} : void 0
@@ -962,7 +976,7 @@ Add to your MCP client config (Claude, Cursor, etc.):
962
976
  }));
963
977
  const remoteClient = new Client({
964
978
  name: "x402-proxy",
965
- version: "0.8.0"
979
+ version: "0.8.2"
966
980
  });
967
981
  await connectTransport(remoteClient);
968
982
  const mppClient = McpClient.wrap(remoteClient, { methods: wrappedMethods });
@@ -977,7 +991,7 @@ Add to your MCP client config (Claude, Cursor, etc.):
977
991
  }
978
992
  const localServer = new Server({
979
993
  name: "x402-proxy",
980
- version: "0.8.0"
994
+ version: "0.8.2"
981
995
  }, { capabilities: {
982
996
  tools: tools.length > 0 ? {} : void 0,
983
997
  resources: remoteResources.length > 0 ? {} : void 0
@@ -1189,7 +1203,7 @@ const routes = buildRouteMap({
1189
1203
  });
1190
1204
  const app = buildApplication(routes, {
1191
1205
  name: "x402-proxy",
1192
- versionInfo: { currentVersion: "0.8.0" },
1206
+ versionInfo: { currentVersion: "0.8.2" },
1193
1207
  scanner: { caseStyle: "allow-kebab-for-camel" }
1194
1208
  });
1195
1209
 
@@ -1201,7 +1215,7 @@ function buildContext(process) {
1201
1215
 
1202
1216
  //#endregion
1203
1217
  //#region src/bin/cli.ts
1204
- await run(app, process.argv.slice(2), buildContext(process));
1218
+ await run(app, process.argv.slice(2).map((a) => a === "-H" ? "--header" : a), buildContext(process));
1205
1219
 
1206
1220
  //#endregion
1207
1221
  export { };
@@ -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.0`];
729
+ const lines = [`x402-proxy v0.8.2`];
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}\``);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "x402-proxy",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
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,
@@ -39,7 +39,7 @@
39
39
  "@x402/evm": "^2.6.0",
40
40
  "@x402/fetch": "^2.6.0",
41
41
  "@x402/mcp": "^2.6.0",
42
- "mppx": "^0.4.7",
42
+ "mppx": "^0.4.9",
43
43
  "@x402/svm": "^2.6.0",
44
44
  "ethers": "^6.0.0",
45
45
  "picocolors": "^1.1.1",