@true402.dev/openclaw-swap-guard 1.0.1 → 1.0.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/README.md CHANGED
@@ -28,13 +28,15 @@ It recognises buys in shell commands the way trading skills run them (`--token-o
28
28
 
29
29
  No setup is needed for a few checks a day: the guard uses true402's free daily allowance.
30
30
 
31
- For more, give it a **separate, low-balance** Base wallet holding a little USDC (gas is sponsored):
31
+ For more, give it a **dedicated, low-balance** Base wallet holding a little USDC (gas is sponsored):
32
32
 
33
33
  ```bash
34
- export TRUE402_PAYER_PRIVATE_KEY=0x… # or PAYER_PRIVATE_KEY
34
+ export TRUE402_PAYER_PRIVATE_KEY=0x…
35
35
  ```
36
36
 
37
- Each check then pays the exact quoted price over [x402](https://x402.org) — no account, no API key. The key is read from the environment, never from OpenClaw's config file, and is never sent anywhere: it signs a USDC authorization locally. The guard **refuses to sign more than $0.25** for a single check.
37
+ Only this dedicated variable is read — never a generic `PAYER_PRIVATE_KEY` another tool may have set. Each check then pays the exact quoted price over [x402](https://x402.org), no account and no API key. The key stays on your machine (it authorizes each USDC payment locally) and is never written to OpenClaw's config.
38
+
39
+ Spending is bounded twice: **at most $0.02 per check** (`maxAmountUsd`) and **at most 50 paid checks a day** (`maxPaidChecksPerDay`) — so never more than $1.00 a day by default. Past the daily limit, only free checks run, and the guard logs a warning.
38
40
 
39
41
  ## Settings
40
42
 
@@ -47,7 +49,8 @@ All optional, under the plugin's config (`true402-swap-guard`):
47
49
  | `onUnchecked` | `allow` | `ask` or `block` when a token could not be checked |
48
50
  | `allowTokens` | `[]` | Token addresses never checked |
49
51
  | `timeoutMs` | `15000` | Give up on a free check after this long (then it is "unchecked"). A paid check is never abandoned once paid — you get the answer you paid for |
50
- | `maxAmountUsd` | `0.25` | Never sign a single check payment above this |
52
+ | `maxAmountUsd` | `0.02` | Never pay more than this for one check |
53
+ | `maxPaidChecksPerDay` | `50` | Paid checks per UTC day; after that only free checks run |
51
54
 
52
55
  ## What is sent
53
56
 
package/dist/index.js CHANGED
@@ -274,7 +274,7 @@ import { privateKeyToAccount } from "viem/accounts";
274
274
  import { base } from "viem/chains";
275
275
 
276
276
  // src/client.ts
277
- var CLIENT = { id: "openclaw-guard", version: "1.0.1", package: "@true402.dev/openclaw-swap-guard", install: "openclaw plugins install @true402.dev/openclaw-swap-guard" };
277
+ var CLIENT = { id: "openclaw-guard", version: "1.0.2", package: "@true402.dev/openclaw-swap-guard", install: "openclaw plugins install @true402.dev/openclaw-swap-guard" };
278
278
 
279
279
  // src/x402.ts
280
280
  var USDC_ABI = [
@@ -447,6 +447,8 @@ async function payStall(path, payload, opts) {
447
447
  }
448
448
 
449
449
  // src/check.ts
450
+ var DEFAULT_MAX_PER_CHECK_USD = 0.02;
451
+ var DEFAULT_MAX_PAID_CHECKS_PER_DAY = 50;
450
452
  var NOT_A_TOKEN = /* @__PURE__ */ new Set(["not_a_contract", "mint_unreadable", "mint_not_initialized"]);
451
453
  var SOL_NEVER_SELLABLE = /* @__PURE__ */ new Set(["non_transferable", "permanent_delegate"]);
452
454
  var SOL_SELL_BLOCKABLE = /* @__PURE__ */ new Set(["freeze_authority_active", "pausable", "transfer_hook", "default_frozen"]);
@@ -490,6 +492,11 @@ function strings(v) {
490
492
  function createChecker(cfg = {}) {
491
493
  const baseUrl = cfg.baseUrl ?? "https://true402.dev/api";
492
494
  const timeoutMs = cfg.timeoutMs ?? 15e3;
495
+ const perCheck = cfg.maxAmountUsd ?? DEFAULT_MAX_PER_CHECK_USD;
496
+ const perDay = cfg.maxPaidChecksPerDay ?? DEFAULT_MAX_PAID_CHECKS_PER_DAY;
497
+ const now = cfg.now ?? Date.now;
498
+ let day = "";
499
+ let paidToday = 0;
493
500
  async function free(path, token) {
494
501
  const res = await fetch(`${baseUrl}${path}`, {
495
502
  method: "POST",
@@ -507,8 +514,12 @@ function createChecker(cfg = {}) {
507
514
  const toVerdict = (body2) => t.chain === "solana" ? solanaVerdict(body2) : evmVerdict(body2, t.chain);
508
515
  const body = await free(path, t.token);
509
516
  if (body !== null) return toVerdict(body);
510
- if (!cfg.payerPrivateKey) throw new Error("the free daily checks are used up \u2014 set PAYER_PRIVATE_KEY to pay per check");
511
- return toVerdict(await payStall(path, { token: t.token }, { payerPrivateKey: cfg.payerPrivateKey, baseUrl, maxAmountUsd: cfg.maxAmountUsd }));
517
+ if (!cfg.payerPrivateKey) throw new Error("the free daily checks are used up \u2014 set TRUE402_PAYER_PRIVATE_KEY to pay per check");
518
+ const today = new Date(now()).toISOString().slice(0, 10);
519
+ if (today !== day) [day, paidToday] = [today, 0];
520
+ if (paidToday >= perDay) throw new Error(`the daily limit of ${perDay} paid checks is reached (maxPaidChecksPerDay)`);
521
+ paidToday++;
522
+ return toVerdict(await payStall(path, { token: t.token }, { payerPrivateKey: cfg.payerPrivateKey, baseUrl, maxAmountUsd: perCheck }));
512
523
  };
513
524
  }
514
525
 
@@ -524,7 +535,8 @@ function readConfig(raw) {
524
535
  onUnchecked: pick(c.onUnchecked, ["allow", "ask", "block"]),
525
536
  allowTokens: Array.isArray(c.allowTokens) ? c.allowTokens.filter((x) => typeof x === "string") : void 0,
526
537
  timeoutMs: num(c.timeoutMs),
527
- maxAmountUsd: num(c.maxAmountUsd)
538
+ maxAmountUsd: num(c.maxAmountUsd),
539
+ maxPaidChecksPerDay: num(c.maxPaidChecksPerDay)
528
540
  };
529
541
  }
530
542
  var index_default = definePluginEntry({
@@ -533,7 +545,7 @@ var index_default = definePluginEntry({
533
545
  description: "Blocks token buys when true402 finds a honeypot or a rug in progress (Base, Ethereum, BSC, Solana).",
534
546
  register(api) {
535
547
  const cfg = readConfig(api.pluginConfig);
536
- const payerPrivateKey = process.env.TRUE402_PAYER_PRIVATE_KEY || process.env.PAYER_PRIVATE_KEY || void 0;
548
+ const payerPrivateKey = process.env.TRUE402_PAYER_PRIVATE_KEY || void 0;
537
549
  const warn = (m) => api.logger?.warn ? api.logger.warn(m) : console.warn(m);
538
550
  const guard = createGuard(createChecker({ ...cfg, payerPrivateKey }), { ...cfg, warn });
539
551
  api.on("before_tool_call", (event, ctx) => guard(event.toolName, event.params ?? {}, ctx?.abortSignal), { priority: 60 });
@@ -15,7 +15,8 @@
15
15
  "onUnchecked": { "type": "string", "enum": ["allow", "ask", "block"], "description": "When a token could not be checked (API unreachable, free checks used up): allow (default), ask, or block." },
16
16
  "allowTokens": { "type": "array", "items": { "type": "string" }, "description": "Token addresses never checked." },
17
17
  "timeoutMs": { "type": "number", "description": "Give up on one check after this many ms (default 15000)." },
18
- "maxAmountUsd": { "type": "number", "description": "Never sign a single check payment above this, in USDC (default 0.25)." }
18
+ "maxAmountUsd": { "type": "number", "description": "Never pay more than this for one check, in USDC (default 0.02)." },
19
+ "maxPaidChecksPerDay": { "type": "number", "description": "At most this many paid checks per day; beyond it only free checks run (default 50)." }
19
20
  }
20
21
  }
21
22
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@true402.dev/openclaw-swap-guard",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "OpenClaw plugin: before any tool call that buys a token, check it with true402 (executed buy/sell honeypot simulation) and block honeypots and rugs. Base, Ethereum, BSC, Solana. Free daily checks; pay-per-check over x402.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",