@true402.dev/openclaw-swap-guard 1.0.2 → 1.0.3

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
@@ -36,7 +36,7 @@ export TRUE402_PAYER_PRIVATE_KEY=0x…
36
36
 
37
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
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.
39
+ Spending is bounded twice: **at most $0.02 per check** (`maxAmountUsd`) and **at most 50 paid checks per UTC day** (`maxPaidChecksPerDay`) — at most $1.00 a day by default. The day's count is kept in `$OPENCLAW_STATE_DIR/true402-swap-guard/spend.json` (default `~/.openclaw/…`), so restarting OpenClaw does not reset it; if that file cannot be written, no payment is made. Past the limit only free checks run, and the guard logs a warning. The limit is per machine: several OpenClaw installs with their own state directories each have their own.
40
40
 
41
41
  ## Settings
42
42
 
@@ -54,7 +54,9 @@ All optional, under the plugin's config (`true402-swap-guard`):
54
54
 
55
55
  ## What is sent
56
56
 
57
- Only the token address and its chain, to `true402.dev`. Nothing about your wallet, your prompts or the trade itself.
57
+ A **free check** sends only the token address and its chain to `true402.dev` — nothing about your wallet, your prompts or the trade.
58
+
59
+ A **paid check** also sends a signed USDC payment authorization. That necessarily reveals the paying wallet's **address** to true402, and the payment is settled on Base, where it is public. That is why the wallet should be a dedicated, low-balance one. The private key itself never leaves your machine.
58
60
 
59
61
  ## License
60
62
 
package/dist/index.js CHANGED
@@ -267,6 +267,11 @@ function clean(s, max = 160) {
267
267
  return t.length > max ? `${t.slice(0, max - 1)}\u2026` : t;
268
268
  }
269
269
 
270
+ // src/check.ts
271
+ import { mkdirSync, readFileSync, writeFileSync } from "fs";
272
+ import { homedir } from "os";
273
+ import { dirname, join } from "path";
274
+
270
275
  // src/x402.ts
271
276
  import { randomBytes } from "crypto";
272
277
  import { createPublicClient, http, getAddress } from "viem";
@@ -274,7 +279,7 @@ import { privateKeyToAccount } from "viem/accounts";
274
279
  import { base } from "viem/chains";
275
280
 
276
281
  // src/client.ts
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" };
282
+ var CLIENT = { id: "openclaw-guard", version: "1.0.3", package: "@true402.dev/openclaw-swap-guard", install: "openclaw plugins install @true402.dev/openclaw-swap-guard" };
278
283
 
279
284
  // src/x402.ts
280
285
  var USDC_ABI = [
@@ -447,6 +452,22 @@ async function payStall(path, payload, opts) {
447
452
  }
448
453
 
449
454
  // src/check.ts
455
+ function fileSpendStore(path = join(process.env.OPENCLAW_STATE_DIR || join(homedir(), ".openclaw"), "true402-swap-guard", "spend.json")) {
456
+ return {
457
+ read() {
458
+ try {
459
+ const v = JSON.parse(readFileSync(path, "utf8"));
460
+ return { day: typeof v.day === "string" ? v.day : "", count: typeof v.count === "number" && v.count >= 0 ? v.count : 0 };
461
+ } catch {
462
+ return { day: "", count: 0 };
463
+ }
464
+ },
465
+ write(v) {
466
+ mkdirSync(dirname(path), { recursive: true });
467
+ writeFileSync(path, JSON.stringify(v), { mode: 384 });
468
+ }
469
+ };
470
+ }
450
471
  var DEFAULT_MAX_PER_CHECK_USD = 0.02;
451
472
  var DEFAULT_MAX_PAID_CHECKS_PER_DAY = 50;
452
473
  var NOT_A_TOKEN = /* @__PURE__ */ new Set(["not_a_contract", "mint_unreadable", "mint_not_initialized"]);
@@ -495,8 +516,7 @@ function createChecker(cfg = {}) {
495
516
  const perCheck = cfg.maxAmountUsd ?? DEFAULT_MAX_PER_CHECK_USD;
496
517
  const perDay = cfg.maxPaidChecksPerDay ?? DEFAULT_MAX_PAID_CHECKS_PER_DAY;
497
518
  const now = cfg.now ?? Date.now;
498
- let day = "";
499
- let paidToday = 0;
519
+ const store = cfg.spendStore ?? fileSpendStore();
500
520
  async function free(path, token) {
501
521
  const res = await fetch(`${baseUrl}${path}`, {
502
522
  method: "POST",
@@ -516,9 +536,14 @@ function createChecker(cfg = {}) {
516
536
  if (body !== null) return toVerdict(body);
517
537
  if (!cfg.payerPrivateKey) throw new Error("the free daily checks are used up \u2014 set TRUE402_PAYER_PRIVATE_KEY to pay per check");
518
538
  const today = new Date(now()).toISOString().slice(0, 10);
519
- if (today !== day) [day, paidToday] = [today, 0];
539
+ const saved = store.read();
540
+ const paidToday = saved.day === today ? saved.count : 0;
520
541
  if (paidToday >= perDay) throw new Error(`the daily limit of ${perDay} paid checks is reached (maxPaidChecksPerDay)`);
521
- paidToday++;
542
+ try {
543
+ store.write({ day: today, count: paidToday + 1 });
544
+ } catch {
545
+ throw new Error("could not record the paid-check count, so no payment was made");
546
+ }
522
547
  return toVerdict(await payStall(path, { token: t.token }, { payerPrivateKey: cfg.payerPrivateKey, baseUrl, maxAmountUsd: perCheck }));
523
548
  };
524
549
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@true402.dev/openclaw-swap-guard",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
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",