@kurox_real/plugin-rugshield-402 1.0.0 → 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
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Autonomous Pre-Swap Honeypot Detection & Tax Verification Plugin for ElizaOS Agents on Base**
4
4
 
5
- Gated by the **x402 Payment Protocol** ($0.005 USDC per scan on Base Mainnet).
5
+ Gated by the **x402 Payment Protocol** ($0.010 USDC per scan on Base Mainnet).
6
6
 
7
7
  ## Overview
8
8
  This plugin provides the `PRE_SWAP_RISK_CHECK` action for ElizaOS agents. Before an agent swaps any token on Base (Aerodrome, Uniswap v3), it automatically queries the RugShield 402 engine to:
package/dist/index.d.ts CHANGED
@@ -8,8 +8,8 @@ export interface ElizaAction {
8
8
  }
9
9
  /**
10
10
  * ElizaOS Action: PRE_SWAP_RISK_CHECK
11
- * Automatically intercepts swap requests and calls RugShield 402 on Base
12
- * to protect the agent's wallet from honeypots, malicious taxes, and liquidity drains.
11
+ * Automatically intercepts swap requests and calls RugShield 402 (Base or Solana)
12
+ * using @x402/fetch auto-signing when X402_PRIVATE_KEY is available, or free preview otherwise.
13
13
  */
14
14
  export declare const preSwapRiskCheckAction: ElizaAction;
15
15
  export declare const rugshieldPlugin: {
package/dist/index.js CHANGED
@@ -1,7 +1,55 @@
1
+ import { x402Client, wrapFetchWithPayment } from "@x402/fetch";
2
+ import { ExactEvmScheme } from "@x402/evm/exact/client";
3
+ import { privateKeyToAccount } from "viem/accounts";
4
+ const EXPECTED_MERCHANT = "0x80e0ae84679b7f11be171daadd492fbecf628cd6";
5
+ const BASE_USDC = "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913";
6
+ const MAX_PER_CALL_MICRO_USDC = 50000n;
7
+ function readSetting(runtime, keys) {
8
+ for (const key of keys) {
9
+ const rt = typeof runtime?.getSetting === "function" ? runtime.getSetting(key) : undefined;
10
+ if (typeof rt === "string" && rt.trim())
11
+ return rt.trim();
12
+ const env = typeof process !== "undefined" ? process.env?.[key] : undefined;
13
+ if (typeof env === "string" && env.trim())
14
+ return env.trim();
15
+ }
16
+ return undefined;
17
+ }
18
+ function resolvePrivateKey(runtime, explicitKey) {
19
+ const candidates = [
20
+ explicitKey,
21
+ readSetting(runtime, ["X402_PRIVATE_KEY", "RUGSHIELD_PRIVATE_KEY", "EVM_PRIVATE_KEY", "BASE_PRIVATE_KEY"]),
22
+ ];
23
+ for (const raw of candidates) {
24
+ if (typeof raw !== "string")
25
+ continue;
26
+ const cleaned = raw.trim().replace(/^0x/i, "");
27
+ if (/^[a-fA-F0-9]{64}$/.test(cleaned))
28
+ return `0x${cleaned}`;
29
+ }
30
+ return undefined;
31
+ }
32
+ function createPayingFetch(privateKey, baseFetch = fetch) {
33
+ const account = privateKeyToAccount(privateKey);
34
+ const client = new x402Client();
35
+ client.register("eip155:8453", new ExactEvmScheme(account));
36
+ client.onBeforePaymentCreation(async (context) => {
37
+ const req = context.selectedRequirements;
38
+ if (req.network !== "eip155:8453")
39
+ throw new Error(`Rejected network ${req.network}`);
40
+ if (req.asset.toLowerCase() !== BASE_USDC)
41
+ throw new Error(`Rejected asset ${req.asset}`);
42
+ if (req.payTo.toLowerCase() !== EXPECTED_MERCHANT)
43
+ throw new Error(`Rejected payTo ${req.payTo}`);
44
+ if (BigInt(req.amount) > MAX_PER_CALL_MICRO_USDC)
45
+ throw new Error(`Rejected amount ${req.amount}`);
46
+ });
47
+ return wrapFetchWithPayment(baseFetch, client);
48
+ }
1
49
  /**
2
50
  * ElizaOS Action: PRE_SWAP_RISK_CHECK
3
- * Automatically intercepts swap requests and calls RugShield 402 on Base
4
- * to protect the agent's wallet from honeypots, malicious taxes, and liquidity drains.
51
+ * Automatically intercepts swap requests and calls RugShield 402 (Base or Solana)
52
+ * using @x402/fetch auto-signing when X402_PRIVATE_KEY is available, or free preview otherwise.
5
53
  */
6
54
  export const preSwapRiskCheckAction = {
7
55
  name: "PRE_SWAP_RISK_CHECK",
@@ -10,54 +58,80 @@ export const preSwapRiskCheckAction = {
10
58
  "VERIFY_TOKEN_SAFETY",
11
59
  "SIMULATE_TOKEN_TAX",
12
60
  "AUDIT_BASE_TOKEN",
13
- "RUGSHIELD_CHECK"
61
+ "RUGSHIELD_CHECK",
14
62
  ],
15
- description: "MANDATORY check before executing DEX swaps on Base. Queries RugShield 402 to detect honeypots, high buy/sell taxes, and drained liquidity. Cost: 0.005 USDC on Base.",
63
+ description: "MANDATORY check before executing DEX swaps on Base or Solana. Uses @x402/fetch when X402_PRIVATE_KEY is configured ($0.010 USDC/call) to detect honeypots, buy/sell taxes, and drained liquidity.",
16
64
  validate: async (_runtime, message) => {
17
65
  const text = message.content?.text || "";
18
- // Matches 0x addresses on Base
19
- return /0x[a-fA-F0-9]{40}/i.test(text);
66
+ return /0x[a-fA-F0-9]{40}|[1-9A-HJ-NP-Za-km-z]{32,44}/i.test(text);
20
67
  },
21
- handler: async (runtime, message, _state, _options, callback) => {
68
+ handler: async (runtime, message, _state, options, callback) => {
22
69
  const text = message.content?.text || "";
23
- const match = text.match(/0x[a-fA-F0-9]{40}/i);
24
- if (!match)
70
+ const evmMatch = text.match(/0x[a-fA-F0-9]{40}/i);
71
+ const solMatch = !evmMatch ? text.match(/\b[1-9A-HJ-NP-Za-km-z]{32,44}\b/) : null;
72
+ const tokenAddress = options?.tokenAddress || evmMatch?.[0] || solMatch?.[0];
73
+ if (!tokenAddress)
25
74
  return false;
26
- const tokenAddress = match[0];
27
- const endpoint = process.env.RUGSHIELD_URL || "https://rugshield-402.onrender.com";
75
+ const chain = tokenAddress.startsWith("0x") ? "base" : "solana";
76
+ const endpoint = (options?.hostUrl ||
77
+ readSetting(runtime, ["RUGSHIELD_URL"]) ||
78
+ "https://rugshield-402.onrender.com").replace(/\/$/, "");
79
+ const baseFetch = options?.customFetch ?? fetch;
80
+ const privateKey = resolvePrivateKey(runtime, options?.privateKey);
81
+ const paymentHeader = options?.paymentHeader || readSetting(runtime, ["RUGSHIELD_PAYMENT_HEADER", "PAYMENT_SIGNATURE"]);
82
+ const usePreview = !privateKey && !paymentHeader && options?.useFreePreview !== false;
28
83
  try {
29
- const response = await fetch(`${endpoint}/v1/scan`, {
84
+ const headers = { "Content-Type": "application/json" };
85
+ if (paymentHeader && !privateKey && !usePreview) {
86
+ headers["PAYMENT-SIGNATURE"] = paymentHeader;
87
+ headers["X-PAYMENT"] = paymentHeader;
88
+ }
89
+ const caller = privateKey && !usePreview ? createPayingFetch(privateKey, baseFetch) : baseFetch;
90
+ const targetUrl = `${endpoint}${usePreview ? "/v1/scan/preview" : "/v1/scan"}`;
91
+ const response = await caller(targetUrl, {
30
92
  method: "POST",
31
- headers: { "Content-Type": "application/json" },
93
+ headers,
32
94
  body: JSON.stringify({
33
95
  token_address: tokenAddress,
34
- chain_id: 8453,
35
- simulate_sell: true
36
- })
96
+ chain,
97
+ chain_id: chain === "base" ? 8453 : undefined,
98
+ simulate_sell: true,
99
+ }),
37
100
  });
38
101
  if (response.status === 402) {
39
- const challenge = await response.json();
102
+ const challenge = await response.json().catch(() => ({}));
103
+ const payTo = challenge?.accepts?.[0]?.payTo ||
104
+ challenge?.payTo ||
105
+ "0x80E0Ae84679b7f11bE171DaADd492FBECf628cd6";
40
106
  if (callback) {
41
107
  callback({
42
- text: `RugShield 402 payment required ($0.005 USDC on Base). PayTo: ${challenge.payTo}`,
108
+ text: `RugShield 402 payment required ($0.010 USDC on Base). Set X402_PRIVATE_KEY (Base USDC, 0 ETH gas) for automatic x402 signing. PayTo: ${payTo}`,
43
109
  action: "X402_PAYMENT_REQUIRED",
44
- challenge
110
+ challenge,
45
111
  });
46
112
  }
47
113
  return false;
48
114
  }
115
+ if (!response.ok) {
116
+ throw new Error(`HTTP ${response.status}`);
117
+ }
49
118
  const report = await response.json();
50
- const isSafe = report.recommendation === "SAFE_TO_SWAP";
119
+ const isSafe = report.recommendation === "SAFE_TO_SWAP" && report.is_honeypot === false;
51
120
  if (callback) {
121
+ const modeNote = usePreview
122
+ ? `\n• Mode: Free Preview (set X402_PRIVATE_KEY for full swap simulation)`
123
+ : `\n• Mode: Paid x402 Verification`;
52
124
  callback({
53
- text: `RugShield Security Report for ${report.symbol} (${tokenAddress}):\n` +
54
- `• Recommendation: ${report.recommendation}\n` +
55
- `• Honeypot: ${report.is_honeypot ? "YES (DO NOT BUY)" : "NO"}\n` +
56
- `• Buy Tax: ${report.buy_tax_bps / 100}%\n` +
57
- `• Sell Tax: ${report.sell_tax_bps / 100}%\n` +
58
- `• Pool Liquidity: $${report.liquidity_usd.toLocaleString()}\n` +
59
- `• Risk Score: ${report.risk_score}`,
60
- report
125
+ text: `RugShield Security Report for ${report.symbol ?? tokenAddress} (${tokenAddress}):\n` +
126
+ `• Chain: ${chain}\n` +
127
+ `• Recommendation: ${report.recommendation ?? "UNVERIFIED"}\n` +
128
+ `• Honeypot: ${report.is_honeypot === true ? "YES (DO NOT BUY)" : report.is_honeypot === false ? "NO" : "UNVERIFIED (paid /v1/scan required)"}\n` +
129
+ `• Buy Tax: ${typeof report.buy_tax_bps === "number" ? report.buy_tax_bps / 100 + "%" : "UNVERIFIED"}\n` +
130
+ `• Sell Tax: ${typeof report.sell_tax_bps === "number" ? report.sell_tax_bps / 100 + "%" : "UNVERIFIED"}\n` +
131
+ `• Pool Liquidity: ${typeof report.liquidity_usd === "number" ? "$" + report.liquidity_usd.toLocaleString() : "Unavailable"}\n` +
132
+ `• Risk Score: ${report.risk_score ?? "N/A"}` +
133
+ modeNote,
134
+ report,
61
135
  });
62
136
  }
63
137
  return isSafe;
@@ -71,14 +145,20 @@ export const preSwapRiskCheckAction = {
71
145
  },
72
146
  examples: [
73
147
  [
74
- { user: "{{user1}}", content: { text: "Swap 0.05 ETH for 0x4ed4E862860beD51a9570b96d89aF5E1B0Efefed on Base" } },
75
- { user: "{{agent}}", content: { text: "Running pre-swap risk check via RugShield 402...", action: "PRE_SWAP_RISK_CHECK" } }
76
- ]
77
- ]
148
+ {
149
+ user: "{{user1}}",
150
+ content: { text: "Swap 0.05 ETH for 0x4ed4E862860beD51a9570b96d89aF5E1B0Efefed on Base" },
151
+ },
152
+ {
153
+ user: "{{agent}}",
154
+ content: { text: "Running pre-swap risk check via RugShield 402...", action: "PRE_SWAP_RISK_CHECK" },
155
+ },
156
+ ],
157
+ ],
78
158
  };
79
159
  export const rugshieldPlugin = {
80
160
  name: "plugin-rugshield-402",
81
- description: "RugShield 402 DEX Honeypot & Tax Protection Plugin for ElizaOS Agents on Base",
82
- actions: [preSwapRiskCheckAction]
161
+ description: "RugShield 402 DEX Honeypot & Tax Protection Plugin for ElizaOS Agents (Base & Solana)",
162
+ actions: [preSwapRiskCheckAction],
83
163
  };
84
164
  export default rugshieldPlugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kurox_real/plugin-rugshield-402",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "RugShield 402 DEX honeypot detection, buy/sell tax simulation, and pool liquidity verification action for ElizaOS agents on Base (x402 gated).",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -43,7 +43,11 @@
43
43
  "url": "https://github.com/ak10082247-max/rugshield-402.git",
44
44
  "directory": "plugins/eliza-rugshield"
45
45
  },
46
- "dependencies": {},
46
+ "dependencies": {
47
+ "@x402/evm": "^2.31.0",
48
+ "@x402/fetch": "^2.31.0",
49
+ "viem": "^2.57.4"
50
+ },
47
51
  "devDependencies": {
48
52
  "typescript": "^5.7.2"
49
53
  }