safehands-pharos 1.3.0 → 1.5.0

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.
Files changed (118) hide show
  1. package/.env.example +64 -26
  2. package/README.md +444 -445
  3. package/dist/cli.d.ts +1 -1
  4. package/dist/cli.d.ts.map +1 -1
  5. package/dist/cli.js +36 -8
  6. package/dist/cli.js.map +1 -1
  7. package/dist/index.d.ts +1 -1
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +208 -147
  10. package/dist/index.js.map +1 -1
  11. package/dist/lib/auditLog.d.ts +9 -0
  12. package/dist/lib/auditLog.d.ts.map +1 -0
  13. package/dist/lib/auditLog.js +30 -0
  14. package/dist/lib/auditLog.js.map +1 -0
  15. package/dist/lib/constants.d.ts +12 -0
  16. package/dist/lib/constants.d.ts.map +1 -1
  17. package/dist/lib/constants.js +10 -0
  18. package/dist/lib/constants.js.map +1 -1
  19. package/dist/lib/dodoApi.d.ts +8 -0
  20. package/dist/lib/dodoApi.d.ts.map +1 -1
  21. package/dist/lib/dodoApi.js +22 -4
  22. package/dist/lib/dodoApi.js.map +1 -1
  23. package/dist/lib/envLoader.d.ts +2 -0
  24. package/dist/lib/envLoader.d.ts.map +1 -0
  25. package/dist/lib/envLoader.js +44 -0
  26. package/dist/lib/envLoader.js.map +1 -0
  27. package/dist/lib/pharosClient.d.ts.map +1 -1
  28. package/dist/lib/pharosClient.js +13 -3
  29. package/dist/lib/pharosClient.js.map +1 -1
  30. package/dist/lib/riskEngine.d.ts.map +1 -1
  31. package/dist/lib/riskEngine.js +50 -45
  32. package/dist/lib/riskEngine.js.map +1 -1
  33. package/dist/lib/signer/index.d.ts.map +1 -1
  34. package/dist/lib/signer/index.js +3 -4
  35. package/dist/lib/signer/index.js.map +1 -1
  36. package/dist/lib/spendAccumulator.d.ts +10 -0
  37. package/dist/lib/spendAccumulator.d.ts.map +1 -0
  38. package/dist/lib/spendAccumulator.js +54 -0
  39. package/dist/lib/spendAccumulator.js.map +1 -0
  40. package/dist/lib/testRpc.d.ts +1 -1
  41. package/dist/lib/testRpc.js +29 -29
  42. package/dist/lib/testTools.d.ts +1 -1
  43. package/dist/lib/testTools.js +4 -5
  44. package/dist/lib/wallet/index.d.ts +19 -0
  45. package/dist/lib/wallet/index.d.ts.map +1 -1
  46. package/dist/lib/wallet/index.js +65 -7
  47. package/dist/lib/wallet/index.js.map +1 -1
  48. package/dist/tools/approveToken.d.ts +0 -1
  49. package/dist/tools/approveToken.d.ts.map +1 -1
  50. package/dist/tools/approveToken.js +3 -1
  51. package/dist/tools/approveToken.js.map +1 -1
  52. package/dist/tools/assessRisk.d.ts.map +1 -1
  53. package/dist/tools/assessRisk.js +18 -7
  54. package/dist/tools/assessRisk.js.map +1 -1
  55. package/dist/tools/checkAllowance.d.ts +9 -2
  56. package/dist/tools/checkAllowance.d.ts.map +1 -1
  57. package/dist/tools/checkAllowance.js +20 -6
  58. package/dist/tools/checkAllowance.js.map +1 -1
  59. package/dist/tools/checkTokenSecurity.d.ts.map +1 -1
  60. package/dist/tools/checkTokenSecurity.js +7 -0
  61. package/dist/tools/checkTokenSecurity.js.map +1 -1
  62. package/dist/tools/createAgentWallet.d.ts +2 -0
  63. package/dist/tools/createAgentWallet.d.ts.map +1 -1
  64. package/dist/tools/createAgentWallet.js +30 -7
  65. package/dist/tools/createAgentWallet.js.map +1 -1
  66. package/dist/tools/executeSwap.d.ts +3 -1
  67. package/dist/tools/executeSwap.d.ts.map +1 -1
  68. package/dist/tools/executeSwap.js +13 -1
  69. package/dist/tools/executeSwap.js.map +1 -1
  70. package/dist/tools/getExecutionHistory.d.ts +15 -17
  71. package/dist/tools/getExecutionHistory.d.ts.map +1 -1
  72. package/dist/tools/getExecutionHistory.js +125 -64
  73. package/dist/tools/getExecutionHistory.js.map +1 -1
  74. package/dist/tools/getTransactionStatus.d.ts +5 -19
  75. package/dist/tools/getTransactionStatus.d.ts.map +1 -1
  76. package/dist/tools/getTransactionStatus.js +10 -18
  77. package/dist/tools/getTransactionStatus.js.map +1 -1
  78. package/dist/tools/publishRiskScore.d.ts.map +1 -1
  79. package/dist/tools/publishRiskScore.js +3 -0
  80. package/dist/tools/publishRiskScore.js.map +1 -1
  81. package/dist/tools/queryRiskRegistry.d.ts +3 -13
  82. package/dist/tools/queryRiskRegistry.d.ts.map +1 -1
  83. package/dist/tools/queryRiskRegistry.js +6 -11
  84. package/dist/tools/queryRiskRegistry.js.map +1 -1
  85. package/dist/tools/safehandsSafeExecute.d.ts.map +1 -1
  86. package/dist/tools/safehandsSafeExecute.js +12 -6
  87. package/dist/tools/safehandsSafeExecute.js.map +1 -1
  88. package/dist/tools/sendPayment.d.ts +0 -1
  89. package/dist/tools/sendPayment.d.ts.map +1 -1
  90. package/dist/tools/sendPayment.js +10 -1
  91. package/dist/tools/sendPayment.js.map +1 -1
  92. package/dist/tools/simulateTransaction.d.ts +2 -23
  93. package/dist/tools/simulateTransaction.d.ts.map +1 -1
  94. package/dist/tools/simulateTransaction.js +10 -15
  95. package/dist/tools/simulateTransaction.js.map +1 -1
  96. package/dist/tools/x402PayAndFetch.d.ts.map +1 -1
  97. package/dist/tools/x402PayAndFetch.js +4 -1
  98. package/dist/tools/x402PayAndFetch.js.map +1 -1
  99. package/dist/x402Server.js +51 -3
  100. package/dist/x402Server.js.map +1 -1
  101. package/package.json +73 -84
  102. package/.agents/skill/safehands/SKILL.md +0 -212
  103. package/.agents/skill/safehands/assets/networks.json +0 -24
  104. package/.agents/skill/safehands/assets/tokens.json +0 -66
  105. package/.agents/wallets.json +0 -20
  106. package/docs/reports/OFFICIAL_DOCS_ALIGNMENT_REPORT.md +0 -137
  107. package/docs/reports/final_audit_report.md +0 -307
  108. package/docs/reports/live_verification_report.md +0 -147
  109. package/docs/reports/pharos_skill_engine_alignment_report.md +0 -85
  110. package/examples/pharos-skill-engine/SKILL.safehands.md +0 -85
  111. package/examples/pharos-skill-engine/assets/safehands/example-actions.json +0 -49
  112. package/examples/pharos-skill-engine/assets/safehands/policy-defaults.json +0 -11
  113. package/examples/pharos-skill-engine/references/safehands.md +0 -345
  114. package/examples/scenario-hack.ts +0 -38
  115. package/skill/SKILL.md +0 -133
  116. package/skill/assets/safehands/example-actions.json +0 -49
  117. package/skill/assets/safehands/policy-defaults.json +0 -11
  118. package/skill/references/safehands.md +0 -345
package/README.md CHANGED
@@ -1,445 +1,444 @@
1
- <p align="center">
2
- <img src="https://img.shields.io/badge/TypeScript-3178C6?style=for-the-badge&logo=typescript&logoColor=white" />
3
- <img src="https://img.shields.io/badge/MCP_Skill-000000?style=for-the-badge" />
4
- <img src="https://img.shields.io/badge/Pharos_Atlantic-688689-blueviolet?style=for-the-badge" />
5
- <img src="https://img.shields.io/badge/Tools-27-orange?style=for-the-badge" />
6
- <img src="https://img.shields.io/badge/Testnet_Only-SAFE-blue?style=for-the-badge" />
7
- </p>
8
-
9
- # SafeHands-Pharos: Transaction Safety Firewall for AI Agents
10
-
11
- SafeHands-Pharos is a **Pharos Skill Engine-compatible MCP package** that protects AI agents before they execute payments, token approvals, swaps, x402 paid requests, or contract interactions.
12
-
13
- Before an AI agent sends a payment, approves tokens, swaps assets, publishes risk data, or pays an x402 resource, SafeHands runs a policy-based preflight check and returns a deterministic decision:
14
-
15
- ```text
16
- ALLOW | WARN | BLOCK | REQUIRE_CONFIRMATION | REQUIRE_FUNDING | REQUIRE_TOKEN_REVIEW
17
- ```
18
-
19
- Every decision includes a risk level, human-readable reasons, required next actions, environment metadata, and structured JSON that agents can parse.
20
-
21
- > **Testnet scope:** SafeHands targets **Pharos Atlantic Testnet only**. It is not audited for mainnet and should not be used with mainnet funds.
22
-
23
- ---
24
-
25
- ## Why AI Agents Need Transaction Safety Middleware
26
-
27
- Autonomous agents can now hold wallets, call APIs, pay x402 resources, approve tokens, and interact on-chain. Generic Web3 tools usually answer: "Can this transaction be sent?" SafeHands answers a more important question first:
28
-
29
- > **Should this action be allowed at all?**
30
-
31
- Common agent-execution risks:
32
-
33
- | Risk | What can go wrong | SafeHands guardrail |
34
- |---|---|---|
35
- | Unlimited approval | Agent approves a malicious spender forever | Blocks unlimited approval by default |
36
- | Wrong chain | Agent signs on mainnet or the wrong testnet | Blocks mainnet and chain ID mismatch |
37
- | Risky x402 URL | Agent pays or fetches SSRF-sensitive endpoints | Blocks localhost/private IPs by default |
38
- | Overspending | Agent pays above configured limits | Blocks payments above limits |
39
- | Unknown token | Agent swaps/approves unverified token | Warns or requires token review |
40
- | Missing signer | Agent tries write action without safe signer | Returns structured signer error |
41
-
42
- ---
43
-
44
- ## What SafeHands Is, and What It Is Not
45
-
46
- SafeHands is a **Transaction Safety Firewall / Guardrail Skill** for Pharos agents. SafeHands is a guardrail layer before execution, not a generic Web3 toolbox.
47
-
48
- It is **not** a generic Web3 toolbox and does not replace Pharos Skill Engine. It complements the Skill Engine by adding a safety layer before execution:
49
-
50
- ```text
51
- User intent
52
- SafeHands preflight
53
- → ALLOW / WARN / BLOCK
54
- Pharos Skill Engine or MCP execution if safe
55
- SafeHands risk report
56
- ```
57
-
58
- ### Difference from Reputation Systems
59
-
60
- SafeHands is also different from pure reputation systems:
61
-
62
- | System type | Main question |
63
- |---|---|
64
- | Agent reputation, such as AgentLeash-style trust systems | "Can I trust this agent?" |
65
- | SafeHands | "Can I trust this action right now?" |
66
-
67
- SafeHands can use reputation signals, but its core purpose is **action-level risk gating**.
68
-
69
- ---
70
-
71
- ## Pharos Atlantic Testnet Context
72
-
73
- Default project configuration:
74
-
75
- | Item | Value |
76
- |---|---|
77
- | Environment | `atlantic-testnet` |
78
- | Chain ID | `688689` |
79
- | RPC URL | `https://atlantic.dplabs-internal.com` |
80
- | Explorer | `https://atlantic.pharosscan.xyz/` |
81
- | Mainnet support | `false` |
82
- | RiskRegistry | `0x61962a6c812ee9f57b207e1ea47c19ae70bb7141` |
83
- | Primary Pharos Skill Engine USDC | `0xE0BE08c77f415F577A1B3A9aD7a1Df1479564ec8` |
84
- | Alternate Circle-referenced USDC | `0xcfC8330f4BCAB529c625D12781b1C19466A9Fc8B` |
85
-
86
- The project treats router and pool addresses that are not directly verified from official docs as **project-configured**, not universal canonical values.
87
-
88
- ### 🧠 Smart Liquidity Fallback
89
- Testnet liquidity is often fragmented or missing. SafeHands includes a **Smart Fallback Engine** within its DODO API integration.
90
- If an AI agent requests a swap to the primary `USDC` token and the routing engine returns `NO_ROUTE_AVAILABLE`, SafeHands will automatically and silently retry the route query using the `Alternate Circle-referenced USDC` address. This prevents unnecessary transaction failures during live agent demos.
91
-
92
- ---
93
-
94
- ## Official Pharos Skill Engine Alignment
95
-
96
- - SafeHands follows the official `SKILL.md` + `references` + `assets` structure (found in the `skill/` package directory).
97
- - SafeHands complements Pharos Skill Engine by adding preflight safety checks before write actions.
98
- - Pharos Skill Engine provides general on-chain capabilities.
99
- - SafeHands answers: "Is this action safe to execute?"
100
- - Default network remains Pharos Atlantic Testnet.
101
- - No mainnet readiness is claimed.
102
-
103
- ---
104
-
105
- ## Supported Usage Modes
106
-
107
- SafeHands supports three usage modes:
108
-
109
- 1. **Pharos Skill Engine (Recommended for Agents):** Install directly into your AI agent project via GitHub:
110
- ```bash
111
- npx skills add SZtch/safehands-pharos
112
- ```
113
- 2. **MCP server usage:** Run directly as a standard MCP server for Claude Desktop, Anvita Flow, etc.
114
- 3. **npm/npx CLI usage:** Run manually in the terminal for testing and CI checks.
115
-
116
- ---
117
-
118
- ## Quick Start
119
-
120
- ```bash
121
- npm install
122
- npm run build
123
- npm run test:all
124
- npm run demo
125
- ```
126
-
127
- Run as MCP server:
128
-
129
- ```bash
130
- npx safehands-pharos
131
- ```
132
-
133
- Show CLI help:
134
-
135
- ```bash
136
- npx safehands-pharos --help
137
- ```
138
-
139
- Run deterministic demo:
140
-
141
- ```bash
142
- npx safehands-pharos --demo
143
- ```
144
-
145
- Run a Skill Engine-compatible CLI call:
146
-
147
- ```bash
148
- npx safehands-pharos skill safehands_preflight_check --input-json '{"actionType":"approve_token","chainId":688689,"isMainnet":false,"approvalAmount":"max","spender":"0x0000000000000000000000000000000000000001"}'
149
- ```
150
-
151
- The CLI returns the standard response envelope:
152
-
153
- ```json
154
- {
155
- "success": true,
156
- "data": {
157
- "decision": "BLOCK",
158
- "riskLevel": "HIGH",
159
- "safeToExecute": false,
160
- "reasons": ["Unlimited approval requested."],
161
- "requiredActions": ["Use a limited approval amount."],
162
- "environment": "atlantic-testnet",
163
- "chainId": 688689,
164
- "isMainnet": false
165
- },
166
- "error": null,
167
- "timestamp": "2026-06-12T00:00:00.000Z"
168
- }
169
- ```
170
-
171
- ---
172
-
173
- ## Environment Setup
174
-
175
- Copy `.env.example` if you need local configuration:
176
-
177
- ```bash
178
- cp .env.example .env
179
- ```
180
-
181
- Safe defaults:
182
-
183
- ```env
184
- WALLET_MODE=none
185
- WRITE_TOOLS_ENABLED=false
186
- ALLOW_UNLIMITED_APPROVAL=false
187
- ALLOW_LOCAL_X402_FETCH=false
188
- ```
189
-
190
- Read-only and preflight tools do not require a private key. Write tools require `WRITE_TOOLS_ENABLED=true` and a safe signer source.
191
-
192
- ### 💾 Agent Wallet Backups
193
- By default, testnet wallets created via `create_agent_wallet` are strictly **In-Memory** and will not persist after the MCP server restarts.
194
- To enable persistent local storage for your AI agent wallets, set the following environment variable:
195
- ```env
196
- WALLET_STORE_PATH=./.agents/wallets.json
197
- ```
198
- This will securely XOR-obfuscate and save the agent's private key to your local `.agents` folder (which is explicitly ignored by Git to prevent accidental leakage).
199
-
200
- ---
201
-
202
- ## MCP Tools: 27 Total
203
-
204
- SafeHands currently exposes **27 MCP tools**:
205
-
206
- - 17 legacy/core Web3 safety/execution tools
207
- - 3 managed testnet wallet tools
208
- - 7 branded SafeHands guardrail tools
209
-
210
- ### Branded SafeHands Guardrail Tools
211
-
212
- | Tool | Purpose |
213
- |---|---|
214
- | `safehands_preflight_check` | Policy-based ALLOW/WARN/BLOCK check before execution |
215
- | `safehands_safe_execute` | Guarded wrapper around payment, approval, swap, and x402 execution |
216
- | `safehands_wallet_health` | Checks whether an agent wallet is ready to act |
217
- | `safehands_x402_preflight` | Checks URL, payment amount, token, signer, and x402 safety before paying |
218
- | `safehands_risk_report` | Generates a human-readable risk report for demos and judges |
219
- | `explain_risk` | Converts policy results into plain-English explanations |
220
- | `token_registry_status` | Classifies token addresses as canonical, test, custom, unknown, or invalid |
221
-
222
- ### Core Safety and Execution Tools
223
-
224
- | Tool | Type | Purpose |
225
- |---|---|---|
226
- | `assess_risk` | Read / optional write | 5-dimension risk score |
227
- | `check_token_security` | Read | GoPlus token security profile |
228
- | `simulate_transaction` | Read | Dry-run transaction simulation |
229
- | `estimate_gas` | Read | Gas estimate and sufficiency check |
230
- | `execute_swap` | Write | FaroSwap/DODO swap with guardrails |
231
- | `send_payment` | Write | Native PHRS payment |
232
- | `approve_token` | Write | ERC-20 approval with unlimited-approval guard |
233
- | `get_token_price` | Read | Token price data |
234
- | `get_pool_info` | Read | DODO/FaroSwap pool and route info |
235
- | `get_gas_price` | Read | Current gas price |
236
- | `get_wallet_balance` | Read | Wallet balances |
237
- | `check_allowance` | Read | ERC-20 allowance check |
238
- | `get_transaction_status` | Read | Transaction status by hash |
239
- | `get_execution_history` | Read | Wallet transaction history |
240
- | `publish_risk_score` | Write | Publish score to RiskRegistry |
241
- | `query_risk_registry` | Read | Query on-chain risk score |
242
- | `x402_pay_and_fetch` | Write when HTTP 402 | Fetch x402 resources and pay only after a payment challenge |
243
-
244
- ### Managed Testnet Wallet Tools
245
-
246
- | Tool | Purpose |
247
- |---|---|
248
- | `create_agent_wallet` | Explicitly create a managed testnet wallet |
249
- | `get_agent_wallet` | Return public wallet metadata, never private key |
250
- | `get_agent_wallet_balance` | Check managed wallet balances |
251
-
252
- ---
253
-
254
- ## Policy Engine Behavior
255
-
256
- The reusable policy engine lives at:
257
-
258
- ```text
259
- src/lib/policy/actionPolicyEngine.ts
260
- ```
261
-
262
- Supported action types:
263
-
264
- ```text
265
- send_payment
266
- approve_token
267
- execute_swap
268
- x402_pay_and_fetch
269
- publish_risk_score
270
- custom_contract_call
271
- ```
272
-
273
- Key guardrails:
274
-
275
- - Block mainnet actions.
276
- - Block chain ID mismatch.
277
- - Block unlimited approvals by default.
278
- - Block SSRF-sensitive x402 URLs.
279
- - Block payment above configured limits.
280
- - Block x402 payment above `MAX_X402_PAYMENT_USDC`.
281
- - Block approvals above `MAX_APPROVAL_AMOUNT_USDC` unless consciously configured.
282
- - Warn when a token is custom, non-registry, or token-security provider is unavailable.
283
- - Require confirmation for medium-risk actions.
284
- - Allow low-risk Pharos Atlantic Testnet actions.
285
-
286
- ---
287
-
288
- ## x402 Behavior
289
-
290
- SafeHands has both x402 client and server behavior:
291
-
292
- ### Free endpoints
293
-
294
- - `GET /supported`
295
- - `GET /health`
296
-
297
- These do **not** require a user private key.
298
-
299
- ### Paid endpoints
300
-
301
- - `GET /assess-risk`
302
- - `GET /check-token-security`
303
- - `GET /simulate-transaction`
304
-
305
- Expected demo price: `0.001 USDC`.
306
-
307
- Client flow:
308
-
309
- 1. Fetch normally first.
310
- 2. If HTTP 200, return `paymentExecuted=false`.
311
- 3. If HTTP 402, run SafeHands x402 preflight.
312
- 4. Request signer only after HTTP 402.
313
- 5. Do not log or return signed payment payloads.
314
-
315
- ---
316
-
317
- ## Using SafeHands with Pharos Skill Engine
318
-
319
- SafeHands includes a Pharos Skill Engine adapter under:
320
-
321
- > **Note:** The canonical publishable Skill package is in `skill/`. The `examples/pharos-skill-engine/` folder is retained as an integration example.
322
-
323
- ```text
324
- examples/pharos-skill-engine/
325
- ├── SKILL.safehands.md
326
- ├── references/
327
- │ └── safehands.md
328
- └── assets/
329
- └── safehands/
330
- ├── policy-defaults.json
331
- └── example-actions.json
332
- ```
333
-
334
- The reference files teach the Skill Engine how to call SafeHands through terminal commands such as:
335
-
336
- ```bash
337
- npx safehands-pharos skill safehands_preflight_check --input-json '<json>'
338
- npx safehands-pharos skill safehands_x402_preflight --input-json '<json>'
339
- npx safehands-pharos skill safehands_wallet_health --input-json '{}'
340
- npx safehands-pharos skill token_registry_status --input-json '{"tokenAddress":"0xE0BE08c77f415F577A1B3A9aD7a1Df1479564ec8"}'
341
- ```
342
-
343
- Use SafeHands before Pharos Skill Engine performs write actions. SafeHands complements the Skill Engine and should not be treated as a replacement.
344
-
345
- ---
346
-
347
- ## Security Guardrails
348
-
349
- SafeHands defaults to defensive behavior:
350
-
351
- - `WRITE_TOOLS_ENABLED=false` by default.
352
- - `WALLET_MODE=none` by default.
353
- - No wallet is created on install, import, or startup.
354
- - Managed wallets are created only through `create_agent_wallet`.
355
- - Private keys are never returned in MCP or CLI responses.
356
- - Private keys and payment proofs are not logged.
357
- - Unlimited approvals are blocked unless explicitly allowed.
358
- - SSRF-sensitive x402 URLs are blocked unless local testing is explicitly enabled.
359
- - Mainnet actions are blocked.
360
- - External API failures return structured errors rather than crashing tool calls.
361
-
362
- ---
363
-
364
- ## Demo
365
-
366
- Run:
367
-
368
- ```bash
369
- npm run demo
370
- ```
371
-
372
- or:
373
-
374
- ```bash
375
- npx safehands-pharos --demo
376
- ```
377
-
378
- The default demo is deterministic and non-destructive. It shows wallet health, allowed preflight, blocked approval, token registry status, x402 preflight, free x402 endpoint behavior, paid x402 without signer, SSRF blocking, write-tool blocking, and a human-readable risk explanation.
379
-
380
- ---
381
-
382
- ## Real Testnet Verification
383
-
384
- SafeHands includes live verification commands that test against real Pharos Atlantic Testnet infrastructure:
385
-
386
- | Command | What it does | Requires |
387
- |---------|-------------|----------|
388
- | `npm run test:rpc:live` | Reads chain ID, block number, optional wallet balance from live RPC | Network access |
389
- | `npm run test:live:safehands` | Runs 7 CLI safety checks against built dist (no broadcast) | Built dist |
390
- | `npm run test:x402:live` | Tests x402 free/paid endpoint behavior locally | Nothing |
391
- | `npm run test:dodo:live` | Tests DODO API route if `DODO_API_KEY` set; skips cleanly if not | `DODO_API_KEY` (optional) |
392
-
393
- **Important distinctions:**
394
-
395
- 1. **Live RPC checks** (`test:rpc`, `test:rpc:live`) connect to the real Pharos Atlantic Testnet RPC and read chain ID + block number.
396
- 2. **Live CLI checks** (`test:live:safehands`) run real CLI invocations against built dist, testing policy decisions deterministically.
397
- 3. **x402 behavior checks** (`test:x402:live`) use a **local test server** labeled `LOCAL_X402_SERVER_DOCS_BEHAVIOR_TEST`. They do not connect to a remote Pharos x402 endpoint.
398
- 4. **DODO checks** (`test:dodo:live`) performs live read-only DODO/FaroSwap checks when `DODO_API_KEY` is configured. The public API key can be provided through an environment variable. The key is not required for the normal deterministic demo. A missing key results in a clean skip. A live API pass does not automatically make router addresses docs-verified.
399
- 5. **Smoke tests** (`test:all`) are deterministic and do not require network connectivity (except DODO/RPC-dependent tools, which degrade gracefully).
400
- 6. **Address verification statuses** (DOCS_VERIFIED, DOCS_DEMO_NON_OFFICIAL, PROJECT_CONFIGURED) are sourced from `docs/reports/OFFICIAL_DOCS_ALIGNMENT_REPORT.md`.
401
- 7. **No real transactions are broadcast by default.** Write tools require explicit `WRITE_TOOLS_ENABLED=true`.
402
-
403
- ---
404
-
405
- ## Tests and Validation
406
-
407
- ```bash
408
- npm ci
409
- npm run build
410
- npx tsc -p tsconfig.all.json --pretty false
411
- npm run test:all # 43-point smoke test suite
412
- npm audit --omit=dev --audit-level=high
413
- npm pack --dry-run
414
- ```
415
-
416
- Live verification (requires network):
417
-
418
- ```bash
419
- npm run test:rpc # Basic RPC connectivity
420
- npm run test:rpc:live # Full live RPC verification with structured output
421
- npm run test:live:safehands # 7 CLI safety checks (read-only)
422
- npm run test:x402:live # x402 behavior checks (local server)
423
- npm run test:dodo:live # DODO API check (requires DODO_API_KEY, skips if missing)
424
- ```
425
-
426
- `test:rpc` and `test:rpc:live` depend on DNS/network access to Pharos RPC and may fail in restricted environments. This should be reported honestly as a provider/network limitation, not hidden.
427
-
428
- ---
429
-
430
- ## Known Limitations and TODOs
431
-
432
- - Testnet-only, not audited for mainnet use.
433
- - Managed wallet storage is testnet-grade unless a real KMS/Vault is integrated.
434
- - DODO/FaroSwap router addresses are project-configured unless official docs confirm them.
435
- - GoPlus/DODO/FaroSwap availability depends on external services and API limits.
436
- - `npm audit` for production dependencies is clean; full dev audit may report dev-only dependency issues depending on upstream packages.
437
- - Formal unit tests with mocked RPC/DODO/GoPlus providers would improve long-term maintainability.
438
-
439
- ---
440
-
441
- ## Hackathon Summary
442
-
443
- **Project name:** SafeHands-Pharos: Transaction Safety Firewall for AI Agents
444
-
445
- **Short description:** SafeHands-Pharos is a Pharos Skill Engine-compatible MCP package that protects AI agents before they execute payments, token approvals, swaps, or x402 paid requests by returning ALLOW, WARN, or BLOCK decisions with human-readable risk explanations.
1
+ # SafeHands-Pharos — Transaction Safety Firewall for AI Agents
2
+
3
+ > **Most Pharos skills let an agent *do* things — check balances, swap, pay, deploy.**
4
+ > **SafeHands is the one that decides whether the agent *should*.**
5
+
6
+ ```bash
7
+ npx safehands-pharos skill safehands_preflight_check --input-json \
8
+ '{"actionType":"approve_token","chainId":688689,"tokenAddress":"0xE0BE08c77f415F577A1B3A9aD7a1Df1479564ec8","spenderAddress":"0x000000000000000000000000000000000000dEaD","approvalAmount":"max"}'
9
+ ```
10
+
11
+ Sample output:
12
+
13
+ ```json
14
+ {
15
+ "success": true,
16
+ "data": {
17
+ "decision": "BLOCK",
18
+ "riskLevel": "HIGH",
19
+ "safeToExecute": false,
20
+ "reasons": [
21
+ "Unlimited approval requested."
22
+ ],
23
+ "requiredActions": [
24
+ "Use a limited approval amount."
25
+ ],
26
+ "checks": [
27
+ { "name": "mainnet_guard", "status": "pass", "message": "Action is not targeting mainnet." },
28
+ { "name": "chain_id", "status": "pass", "message": "Chain ID is Pharos Atlantic Testnet (688689)." },
29
+ { "name": "environment", "status": "pass", "message": "Environment is atlantic-testnet." },
30
+ { "name": "approval_amount", "status": "fail", "message": "Unlimited approval is blocked by default." }
31
+ ],
32
+ "environment": "atlantic-testnet",
33
+ "chainId": 688689,
34
+ "isMainnet": false,
35
+ "tokenRegistry": {
36
+ "symbol": "USDC",
37
+ "status": "SKILL_ENGINE_CANONICAL_TOKEN",
38
+ "verificationStatus": "DOCS_VERIFIED_FROM_PHAROS_SKILL_ENGINE"
39
+ },
40
+ "source": "safehands_preflight_check"
41
+ },
42
+ "error": null,
43
+ "timestamp": "2026-06-14T00:00:00.000Z"
44
+ }
45
+ ```
46
+
47
+ That's the whole idea: **before** an agent approves a token, swaps, sends a payment,
48
+ or pays an x402 resource, SafeHands runs a policy check and returns `ALLOW`, `WARN`,
49
+ or `BLOCK` — with a plain-English reason. If `BLOCK`, the agent stops. No transaction,
50
+ no loss.
51
+
52
+ **Live preflight examples:** see [DEMO.md](DEMO.md) — real ALLOW and BLOCK outputs.
53
+
54
+ <p align="center">
55
+ <img src="https://img.shields.io/badge/TypeScript-3178C6?style=for-the-badge&logo=typescript&logoColor=white" />
56
+ <img src="https://img.shields.io/badge/MCP_Skill-000000?style=for-the-badge" />
57
+ <img src="https://img.shields.io/badge/Pharos_Atlantic-688689-blueviolet?style=for-the-badge" />
58
+ <img src="https://img.shields.io/badge/Tools-27-orange?style=for-the-badge" />
59
+ <img src="https://img.shields.io/badge/Testnet_Only-SAFE-blue?style=for-the-badge" />
60
+ </p>
61
+
62
+ > **Testnet only.** SafeHands targets Pharos Atlantic Testnet (Chain ID 688689). Not audited for mainnet use.
63
+
64
+ ---
65
+
66
+ ## Why AI Agents Need This
67
+
68
+ Generic Web3 tools answer: *"Can this transaction be sent?"*
69
+ SafeHands answers: **"Should this action be allowed at all?"**
70
+
71
+ | Risk | What goes wrong without SafeHands | SafeHands guardrail |
72
+ |------|----------------------------------|---------------------|
73
+ | Unlimited approval | Agent approves malicious spender forever | Blocked by default |
74
+ | Wrong chain | Agent signs on mainnet by mistake | Blocked |
75
+ | Risky x402 URL | Agent pays a localhost / private IP | Blocked (SSRF guard) |
76
+ | Overspending | Agent drains wallet in one session | Daily cap enforced |
77
+ | Unknown token | Agent swaps unverified contract | Warns, requires review |
78
+ | Missing signer | Agent attempts write without wallet | Structured error returned |
79
+
80
+ SafeHands is a **Pharos Skill Engine-compatible MCP package** — a composable guardrail layer that any agent can add in front of any action, without modifying existing skill logic.
81
+
82
+ ---
83
+
84
+ ## Getting Started
85
+
86
+ ### Step 1 Try it now (no setup, no wallet)
87
+
88
+ ```bash
89
+ npx safehands-pharos --demo
90
+ ```
91
+
92
+ Runs 10 live safety checks in your terminal: ALLOW/BLOCK decisions, wallet health, token registry, x402 preflight, risk report. No config, no private key, no transactions.
93
+
94
+ ---
95
+
96
+ ### Step 2 Connect to your AI agent
97
+
98
+ Pick **one** depending on how you use AI agents:
99
+
100
+ #### Claude Desktop
101
+
102
+ Add to your `claude_desktop_config.json`, then restart Claude Desktop:
103
+
104
+ ```json
105
+ {
106
+ "mcpServers": {
107
+ "safehands": {
108
+ "command": "npx",
109
+ "args": ["safehands-pharos"]
110
+ }
111
+ }
112
+ }
113
+ ```
114
+
115
+ All 27 SafeHands tools appear automatically in every Claude conversation.
116
+
117
+ #### Anvita Flow
118
+
119
+ Add as an MCP server in Anvita Flow settings:
120
+
121
+ ```json
122
+ { "command": "npx", "args": ["safehands-pharos"] }
123
+ ```
124
+
125
+ #### Terminal / scripts (CLI)
126
+
127
+ Call any tool directly without connecting to an AI client:
128
+
129
+ ```bash
130
+ npx safehands-pharos skill safehands_preflight_check \
131
+ '{"actionType":"send_payment","chainId":688689,"amount":"0.001","recipient":"0x1234567890123456789012345678901234567890"}'
132
+ ```
133
+
134
+ ---
135
+
136
+ ### Step 3 — (Optional) Enable write operations
137
+
138
+ By default, SafeHands is **read-only**: preflight checks, risk scoring, token registry, wallet health. No private key needed.
139
+
140
+ To unlock swaps, payments, and approvals, run the setup wizard:
141
+
142
+ ```bash
143
+ npx safehands-pharos init
144
+ ```
145
+
146
+ Or set manually in a `.env` file in your working directory:
147
+
148
+ ```env
149
+ WALLET_MODE=env # env | managed-testnet
150
+ PRIVATE_KEY=0x... # testnet key only — never mainnet
151
+ WRITE_TOOLS_ENABLED=true
152
+ MAX_TX_AMOUNT_PHRS=0.1 # per-transaction cap
153
+ MAX_DAILY_SPEND_USD=10 # daily spend cap
154
+ ```
155
+
156
+ ---
157
+
158
+ ## Calling Tools from the CLI
159
+
160
+ ```bash
161
+ # Short form (recommended)
162
+ npx safehands-pharos skill <tool> '<json>'
163
+
164
+ # With flag
165
+ npx safehands-pharos skill <tool> -i '<json>'
166
+
167
+ # Explicit flag
168
+ npx safehands-pharos skill <tool> --input-json '<json>'
169
+ ```
170
+
171
+ Examples:
172
+
173
+ ```bash
174
+ # Preflight check before a swap
175
+ npx safehands-pharos skill safehands_preflight_check \
176
+ '{"actionType":"execute_swap","tokenIn":"PHRS","tokenOut":"USDC","amount":"0.01","chainId":688689,"isMainnet":false}'
177
+
178
+ # Check wallet balance
179
+ npx safehands-pharos skill get_wallet_balance \
180
+ '{"walletAddress":"0xYourWallet"}'
181
+
182
+ # Assess risk score
183
+ npx safehands-pharos skill assess_risk \
184
+ '{"action":"swap","tokenIn":"PHRS","tokenOut":"USDC","amount":"0.01","walletAddress":"0xYourWallet"}'
185
+
186
+ # Classify a token address
187
+ npx safehands-pharos skill token_registry_status \
188
+ '{"tokenAddress":"0xE0BE08c77f415F577A1B3A9aD7a1Df1479564ec8"}'
189
+ ```
190
+
191
+ ---
192
+
193
+ ## All 27 Tools
194
+
195
+ All tools return the same response envelope:
196
+
197
+ ```json
198
+ {
199
+ "success": true,
200
+ "data": { ... },
201
+ "error": null,
202
+ "timestamp": "2026-06-13T00:00:00.000Z"
203
+ }
204
+ ```
205
+
206
+ On failure: `success: false`, `data: null`, `error: { code, message, retryable }`.
207
+
208
+ ### SafeHands Guardrail Tools
209
+
210
+ | Tool | What it does | CLI |
211
+ |------|-------------|-----|
212
+ | `safehands_preflight_check` | ALLOW / WARN / BLOCK before any action | ✓ |
213
+ | `safehands_safe_execute` | Preflight + execute in one call | ✓ |
214
+ | `safehands_wallet_health` | Wallet, signer, gas, x402 readiness | ✓ |
215
+ | `safehands_x402_preflight` | URL safety + payment check before x402 | |
216
+ | `safehands_risk_report` | Human-readable risk summary | |
217
+ | `explain_risk` | Translate ALLOW/WARN/BLOCK into plain English | |
218
+ | `token_registry_status` | Canonical / custom / unknown token check | |
219
+
220
+ ### Safety & Analysis Tools
221
+
222
+ | Tool | What it does | CLI |
223
+ |------|-------------|-----|
224
+ | `assess_risk` | 5-dimension risk score (0–100) | |
225
+ | `check_token_security` | GoPlus token security profile | ✓ |
226
+ | `simulate_transaction` | Dry-run before broadcasting | |
227
+ | `estimate_gas` | Gas estimate + sufficiency check | |
228
+ | `check_allowance` | ERC-20 allowance check | MCP |
229
+
230
+ ### Market & Chain Data
231
+
232
+ | Tool | What it does | CLI |
233
+ |------|-------------|-----|
234
+ | `get_wallet_balance` | PHRS / USDC / USDT balances | |
235
+ | `get_token_price` | Token price via DODO | |
236
+ | `get_gas_price` | Current network gas price | MCP |
237
+ | `get_pool_info` | FaroSwap / DODO pool info | MCP |
238
+ | `get_transaction_status` | TX status by hash | ✓ |
239
+ | `get_execution_history` | Wallet transfer history (ERC-20 + native) | MCP |
240
+
241
+ ### Write Tools *(require `WRITE_TOOLS_ENABLED=true`)*
242
+
243
+ | Tool | What it does | CLI |
244
+ |------|-------------|-----|
245
+ | `execute_swap` | Swap tokens via FaroSwap / DODO | MCP |
246
+ | `send_payment` | Send native PHRS | MCP |
247
+ | `approve_token` | ERC-20 approval (unlimited blocked by default) | MCP |
248
+ | `publish_risk_score` | Publish risk score to RiskRegistry contract | MCP |
249
+ | `x402_pay_and_fetch` | Fetch x402 resource, pay only after HTTP 402 | MCP |
250
+
251
+ ### Risk Registry
252
+
253
+ | Tool | What it does | CLI |
254
+ |------|-------------|-----|
255
+ | `query_risk_registry` | Read on-chain risk score | ✓ |
256
+
257
+ ### Managed Wallet Tools
258
+
259
+ | Tool | What it does | CLI |
260
+ |------|-------------|-----|
261
+ | `create_agent_wallet` | Create testnet wallet (AES-256-GCM encrypted) | ✓ |
262
+ | `get_agent_wallet` | Wallet address + metadata (no private key) | ✓ |
263
+ | `get_agent_wallet_balance` | Managed wallet balances | ✓ |
264
+
265
+ > **CLI** = callable via `npx safehands-pharos skill <tool> '<json>'`
266
+ > **MCP** = available via Claude Desktop / Anvita Flow only
267
+
268
+ ---
269
+
270
+ ## Configuration
271
+
272
+ If you cloned the repo, copy the example file:
273
+
274
+ ```bash
275
+ cp .env.example .env # then edit .env with your settings
276
+ ```
277
+
278
+ If you installed via `npx` or `npm install`, create a `.env` in your working directory with these settings:
279
+
280
+ ```env
281
+ # Wallet mode
282
+ WALLET_MODE=none # none | env | managed-testnet
283
+ PRIVATE_KEY= # required when WALLET_MODE=env
284
+ WALLET_STORE_PATH= # optional: persist managed wallets to disk
285
+
286
+ # Write gates (all off by default)
287
+ WRITE_TOOLS_ENABLED=false
288
+ ALLOW_UNLIMITED_APPROVAL=false
289
+
290
+ # Spend limits
291
+ MAX_TX_AMOUNT_PHRS=0.1 # max PHRS per transaction
292
+ MAX_DAILY_SPEND_USD=10 # daily cap across all wallets
293
+ PHRS_USD_PRICE=1.0 # used for daily spend accounting
294
+
295
+ # DODO API (required for swaps and price data)
296
+ DODO_API_KEY=
297
+ ```
298
+
299
+ ### Wallet modes explained
300
+
301
+ | Mode | How it works |
302
+ |------|-------------|
303
+ | `none` | No signer — read-only tools only (safe default) |
304
+ | `env` | Reads `PRIVATE_KEY` from `.env` |
305
+ | `managed-testnet` | Uses wallet created via `create_agent_wallet` |
306
+
307
+ ### Persistent managed wallets
308
+
309
+ By default, wallets created with `create_agent_wallet` are in-memory and lost on restart. To persist them:
310
+
311
+ ```env
312
+ WALLET_STORE_PATH=./.agents/wallets.json
313
+ WALLET_ENCRYPTION_KEY=your-strong-secret
314
+ ```
315
+
316
+ Private keys are AES-256-GCM encrypted on disk. The `.agents/` folder is gitignored.
317
+
318
+ ---
319
+
320
+ ## Security Defaults
321
+
322
+ SafeHands ships safe by default — nothing is enabled without explicit opt-in:
323
+
324
+ - `WRITE_TOOLS_ENABLED=false` — no on-chain writes without opt-in
325
+ - `WALLET_MODE=none` — no signer loaded on startup
326
+ - Unlimited token approvals blocked
327
+ - Mainnet actions blocked
328
+ - SSRF-sensitive x402 URLs blocked
329
+ - Private keys never returned in responses or logs
330
+ - Daily spend cap enforced in-memory per wallet
331
+
332
+ ---
333
+
334
+ ## x402 Support
335
+
336
+ SafeHands acts as both an x402 client and server.
337
+
338
+ **Client** (`x402_pay_and_fetch`): Fetches a resource normally first. If the server returns HTTP 402, SafeHands runs a preflight check, requests the signer, pays, and retries — all in one tool call. Payment proofs are never logged.
339
+
340
+ **Server** (`npm run x402-server`): Exposes paid endpoints. A live instance runs at:
341
+
342
+ ```
343
+ https://safehands-pharos-production.up.railway.app
344
+ ```
345
+
346
+ | Endpoint | Type | Price |
347
+ |----------|------|-------|
348
+ | `GET /supported` | Free | — |
349
+ | `GET /health` | Free | — |
350
+ | `GET /assess-risk` | Paid | 0.001 USDC |
351
+ | `GET /check-token-security` | Paid | 0.001 USDC |
352
+ | `GET /simulate-transaction` | Paid | 0.001 USDC |
353
+
354
+ ---
355
+
356
+ ## Examples
357
+
358
+ **Prompt-injection attack scenario** SafeHands blocking an unlimited token approval triggered by a simulated prompt-injection attack:
359
+
360
+ ```bash
361
+ npx safehands-pharos skill safehands_preflight_check \
362
+ '{"actionType":"approve_token","chainId":688689,"approvalAmount":"max","spender":"0xBadActor12300000000000000000000000000000"}'
363
+ ```
364
+
365
+ Expected output: `BLOCK` — `"Unlimited approval is blocked by default."`
366
+
367
+ **Live server** — the SafeHands x402 server runs at:
368
+
369
+ ```
370
+ https://safehands-pharos-production.up.railway.app
371
+ ```
372
+
373
+ Hit `/preflight?actionType=send_payment&amount=0.001&chainId=688689&recipient=0x1234...` for a live ALLOW/WARN/BLOCK response with no setup required.
374
+
375
+ ---
376
+
377
+ ## Network Info
378
+
379
+ | Item | Value |
380
+ |------|-------|
381
+ | Chain ID | `688689` |
382
+ | RPC | `https://atlantic.dplabs-internal.com` |
383
+ | Explorer | `https://atlantic.pharosscan.xyz` |
384
+ | USDC | `0xE0BE08c77f415F577A1B3A9aD7a1Df1479564ec8` |
385
+ | RiskRegistry | `0x61962a6c812ee9f57b207e1ea47c19ae70bb7141` |
386
+
387
+ **Proof of life — live on-chain tx:**
388
+
389
+ | What | Value |
390
+ |------|-------|
391
+ | Action | `publish_risk_score` RiskRegistry |
392
+ | Tx Hash | [`0x6a58f636...fdefc`](https://atlantic.pharosscan.xyz/tx/0x6a58f636814458c09304db3d7c4f5f48e764f6439649fbb786cddb32c77fdefc) |
393
+ | Block | `24168297` |
394
+ | Gas Used | `140,187` |
395
+
396
+ ---
397
+
398
+ ## Testing
399
+
400
+ ```bash
401
+ npm run build # compile TypeScript
402
+ npm run demo # run 10 live safety checks in terminal (no wallet needed)
403
+ npm run dev # run MCP server in dev mode (tsx, no build step)
404
+ ```
405
+
406
+ For manual testing, use the CLI directly after building:
407
+
408
+ ```bash
409
+ # Build first
410
+ npm run build
411
+
412
+ # Then call any tool
413
+ node dist/index.js skill safehands_preflight_check \
414
+ '{"actionType":"approve_token","chainId":688689,"approvalAmount":"max"}'
415
+ ```
416
+
417
+ ---
418
+
419
+ ## Known Limitations
420
+
421
+ - Testnet-only not audited for mainnet
422
+ - Managed wallet encryption is AES-256-GCM but not KMS/Vault grade
423
+ - `get_token_price` and swap routing require a DODO API key
424
+ - GoPlus token security does not support Pharos testnet (Chain 688689) — `check_token_security` returns a clear error
425
+ - DODO reverse routes (e.g. USDT → PHRS) have no liquidity on testnet
426
+ - x402 client and server are implemented with the official `@x402/fetch` and `@x402/evm` SDKs and verified against a local x402-compatible server. They have not yet been verified against live third-party x402 endpoints on Pharos.
427
+
428
+ ---
429
+
430
+ ## Roadmap
431
+
432
+ SafeHands is designed to grow from a single-project guardrail into **shared safety infrastructure** for the Pharos agent economy.
433
+
434
+ **Near-term**
435
+ - **Per-agent spend limits** — a `set_spend_limits` / `get_spend_limits` tool pair so each agent carries its own policy instead of a shared global cap. Stored in the existing AES-256-GCM encrypted wallet store.
436
+ - **x402 live endpoint verification** validate SafeHands's x402 preflight against production third-party x402 endpoints on Pharos as they become available.
437
+
438
+ **Medium-term**
439
+ - **Community risk registry** — as more agents publish scores to the on-chain RiskRegistry (`0x61962a6c812ee9f57b207e1ea47c19ae70bb7141`), `query_risk_registry` becomes shared reputation infrastructure. A malicious contract blocked by one agent is flagged for all agents across the ecosystem.
440
+ - **Cross-chain x402 guardrails** — SafeHands's x402 preflight logic is protocol-level, not Pharos-specific. The same guardrail pattern can protect agents making x402 payments on AgentCash (Base / Solana) or any other compatible network.
441
+
442
+ **Long-term**
443
+ - **Mainnet support** — currently testnet-only by design. Mainnet requires a full re-audit of every safety check, formal verification of the RiskRegistry contract, and KMS/Vault-grade key management before it can be trusted with real funds.
444
+ - **Standardized guardrail interface** — a community spec so any Pharos skill can expose a `preflight(action) → ALLOW | WARN | BLOCK` interface and compose with SafeHands, rather than each skill reinventing safety logic independently.