safehands-pharos 1.4.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.
- package/README.md +174 -63
- package/dist/cli.d.ts +5 -5
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +126 -124
- package/dist/cli.js.map +1 -1
- package/dist/demo.d.ts +1 -1
- package/dist/demo.js +171 -171
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +73 -65
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +1 -1
- package/dist/init.js +65 -65
- package/dist/lib/constants.d.ts +303 -291
- package/dist/lib/constants.d.ts.map +1 -1
- package/dist/lib/constants.js +302 -292
- package/dist/lib/constants.js.map +1 -1
- package/dist/lib/dodoApi.d.ts +78 -78
- package/dist/lib/dodoApi.js +196 -196
- package/dist/lib/envLoader.d.ts +2 -0
- package/dist/lib/envLoader.d.ts.map +1 -0
- package/dist/lib/envLoader.js +44 -0
- package/dist/lib/envLoader.js.map +1 -0
- package/dist/lib/http.d.ts +14 -14
- package/dist/lib/http.js +118 -118
- package/dist/lib/pharosClient.d.ts +58 -58
- package/dist/lib/pharosClient.js +63 -63
- package/dist/lib/policy/actionPolicyEngine.d.ts +53 -53
- package/dist/lib/policy/actionPolicyEngine.js +212 -212
- package/dist/lib/riskEngine.d.ts +26 -26
- package/dist/lib/riskEngine.d.ts.map +1 -1
- package/dist/lib/riskEngine.js +288 -283
- package/dist/lib/riskEngine.js.map +1 -1
- package/dist/lib/signer/index.d.ts +24 -24
- package/dist/lib/signer/index.js +88 -88
- package/dist/lib/testDodoLive.d.ts +1 -1
- package/dist/lib/testDodoLive.js +104 -104
- package/dist/lib/testLiveSafehands.d.ts +1 -1
- package/dist/lib/testLiveSafehands.js +92 -92
- package/dist/lib/testRpcLive.d.ts +1 -1
- package/dist/lib/testRpcLive.js +88 -88
- package/dist/lib/testTools.js +397 -398
- package/dist/lib/testX402Live.d.ts +1 -1
- package/dist/lib/testX402Live.js +159 -159
- package/dist/lib/toolResponse.d.ts +25 -25
- package/dist/lib/toolResponse.js +53 -53
- package/dist/lib/wallet/index.d.ts +37 -37
- package/dist/lib/wallet/index.js +128 -128
- package/dist/scripts/checkDeploy.d.ts +1 -1
- package/dist/scripts/checkDeploy.js +24 -24
- package/dist/scripts/deployRegistry.d.ts +1 -1
- package/dist/scripts/deployRegistry.js +100 -100
- package/dist/scripts/testRegistry.d.ts +1 -1
- package/dist/scripts/testRegistry.js +43 -43
- package/dist/tools/approveToken.d.ts +45 -45
- package/dist/tools/approveToken.js +85 -85
- package/dist/tools/assessRisk.d.ts +79 -79
- package/dist/tools/assessRisk.js +104 -104
- package/dist/tools/checkAllowance.d.ts +43 -43
- package/dist/tools/checkAllowance.js +56 -56
- package/dist/tools/checkTokenSecurity.d.ts +46 -46
- package/dist/tools/checkTokenSecurity.js +95 -95
- package/dist/tools/createAgentWallet.d.ts +28 -26
- package/dist/tools/createAgentWallet.d.ts.map +1 -1
- package/dist/tools/createAgentWallet.js +82 -58
- package/dist/tools/createAgentWallet.js.map +1 -1
- package/dist/tools/estimateGas.d.ts +79 -79
- package/dist/tools/estimateGas.js +124 -124
- package/dist/tools/executeSwap.d.ts +61 -61
- package/dist/tools/executeSwap.js +141 -141
- package/dist/tools/explainRisk.d.ts +29 -29
- package/dist/tools/explainRisk.js +32 -32
- package/dist/tools/getAgentWallet.d.ts +21 -21
- package/dist/tools/getAgentWallet.js +27 -27
- package/dist/tools/getAgentWalletBalance.d.ts +11 -11
- package/dist/tools/getAgentWalletBalance.js +70 -70
- package/dist/tools/getExecutionHistory.d.ts +49 -49
- package/dist/tools/getExecutionHistory.js +154 -154
- package/dist/tools/getGasPrice.d.ts +43 -43
- package/dist/tools/getGasPrice.js +59 -59
- package/dist/tools/getPoolInfo.d.ts +75 -75
- package/dist/tools/getPoolInfo.js +137 -137
- package/dist/tools/getTokenPrice.d.ts +113 -113
- package/dist/tools/getTokenPrice.js +117 -117
- package/dist/tools/getTransactionStatus.d.ts +43 -43
- package/dist/tools/getTransactionStatus.js +59 -59
- package/dist/tools/getWalletBalance.d.ts +68 -68
- package/dist/tools/getWalletBalance.js +87 -87
- package/dist/tools/publishRiskScore.d.ts +63 -63
- package/dist/tools/publishRiskScore.js +88 -88
- package/dist/tools/queryRiskRegistry.d.ts +38 -38
- package/dist/tools/queryRiskRegistry.js +55 -55
- package/dist/tools/safehandsPreflightCheck.d.ts +77 -77
- package/dist/tools/safehandsPreflightCheck.js +47 -47
- package/dist/tools/safehandsRiskReport.d.ts +81 -81
- package/dist/tools/safehandsRiskReport.js +28 -28
- package/dist/tools/safehandsSafeExecute.d.ts +20 -20
- package/dist/tools/safehandsSafeExecute.js +81 -81
- package/dist/tools/safehandsWalletHealth.d.ts +14 -14
- package/dist/tools/safehandsWalletHealth.js +103 -103
- package/dist/tools/safehandsX402Preflight.d.ts +26 -26
- package/dist/tools/safehandsX402Preflight.js +65 -65
- package/dist/tools/sendPayment.d.ts +57 -57
- package/dist/tools/sendPayment.js +117 -117
- package/dist/tools/simulateTransaction.d.ts +60 -60
- package/dist/tools/simulateTransaction.js +83 -83
- package/dist/tools/tokenRegistryStatus.d.ts +26 -26
- package/dist/tools/tokenRegistryStatus.js +96 -96
- package/dist/tools/x402PayAndFetch.d.ts +81 -81
- package/dist/tools/x402PayAndFetch.js +152 -152
- package/dist/x402Server.d.ts +1 -1
- package/dist/x402Server.js +300 -252
- package/dist/x402Server.js.map +1 -1
- package/package.json +6 -16
- package/examples/dashboard/index.html +0 -337
- package/examples/pharos-skill-engine/SKILL.safehands.md +0 -85
- package/examples/pharos-skill-engine/assets/safehands/example-actions.json +0 -49
- package/examples/pharos-skill-engine/assets/safehands/policy-defaults.json +0 -11
- package/examples/pharos-skill-engine/references/safehands.md +0 -345
- package/examples/scenario-hack.ts +0 -38
- package/skill/SKILL.md +0 -133
- package/skill/assets/safehands/example-actions.json +0 -49
- package/skill/assets/safehands/policy-defaults.json +0 -11
- package/skill/references/safehands.md +0 -345
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "safehands-pharos",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Pharos Skill Engine-compatible transaction safety firewall for AI agents.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -14,11 +14,8 @@
|
|
|
14
14
|
"files": [
|
|
15
15
|
"dist",
|
|
16
16
|
"contracts",
|
|
17
|
-
"examples",
|
|
18
|
-
"skill",
|
|
19
17
|
"README.md",
|
|
20
18
|
".env.example",
|
|
21
|
-
"docs",
|
|
22
19
|
"LICENSE"
|
|
23
20
|
],
|
|
24
21
|
"scripts": {
|
|
@@ -26,12 +23,6 @@
|
|
|
26
23
|
"start": "node dist/index.js",
|
|
27
24
|
"dev": "tsx src/index.ts",
|
|
28
25
|
"x402-server": "tsx src/x402Server.ts",
|
|
29
|
-
"test:rpc": "tsx src/lib/testRpc.ts",
|
|
30
|
-
"test:rpc:live": "tsx src/lib/testRpcLive.ts",
|
|
31
|
-
"test:all": "tsx src/lib/testTools.ts",
|
|
32
|
-
"test:live:safehands": "tsx src/lib/testLiveSafehands.ts",
|
|
33
|
-
"test:x402:live": "tsx src/lib/testX402Live.ts",
|
|
34
|
-
"test:dodo:live": "tsx src/lib/testDodoLive.ts",
|
|
35
26
|
"demo": "tsx src/demo.ts"
|
|
36
27
|
},
|
|
37
28
|
"keywords": [
|
|
@@ -65,18 +56,17 @@
|
|
|
65
56
|
},
|
|
66
57
|
"dependencies": {
|
|
67
58
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
68
|
-
"@
|
|
69
|
-
"@x402/
|
|
70
|
-
"@x402/
|
|
71
|
-
"@x402/
|
|
72
|
-
"@x402/fetch": "^2.14.0",
|
|
59
|
+
"@x402/core": "^2.15.0",
|
|
60
|
+
"@x402/evm": "^2.15.0",
|
|
61
|
+
"@x402/express": "^2.15.0",
|
|
62
|
+
"@x402/fetch": "^2.15.0",
|
|
73
63
|
"express": "^5.2.1",
|
|
74
64
|
"viem": "^2.31.3",
|
|
75
65
|
"zod": "^3.25.67"
|
|
76
66
|
},
|
|
77
67
|
"devDependencies": {
|
|
68
|
+
"@types/express": "^5.0.6",
|
|
78
69
|
"@types/node": "^22.15.0",
|
|
79
|
-
"solc": "^0.8.28",
|
|
80
70
|
"tsx": "^4.20.3",
|
|
81
71
|
"typescript": "^5.8.3"
|
|
82
72
|
}
|
|
@@ -1,337 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>SafeHands Pharos | Threat Radar</title>
|
|
7
|
-
<style>
|
|
8
|
-
:root {
|
|
9
|
-
--bg-color: #0b0c10;
|
|
10
|
-
--surface-color: rgba(31, 40, 51, 0.7);
|
|
11
|
-
--border-color: rgba(69, 162, 158, 0.2);
|
|
12
|
-
--text-main: #c5c6c7;
|
|
13
|
-
--text-accent: #66fcf1;
|
|
14
|
-
--danger: #ff4b4b;
|
|
15
|
-
--success: #4caf50;
|
|
16
|
-
--warning: #ffc107;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
* {
|
|
20
|
-
margin: 0;
|
|
21
|
-
padding: 0;
|
|
22
|
-
box-sizing: border-box;
|
|
23
|
-
font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
body {
|
|
27
|
-
background-color: var(--bg-color);
|
|
28
|
-
color: var(--text-main);
|
|
29
|
-
min-height: 100vh;
|
|
30
|
-
background-image:
|
|
31
|
-
radial-gradient(circle at 15% 50%, rgba(102, 252, 241, 0.08) 0%, transparent 50%),
|
|
32
|
-
radial-gradient(circle at 85% 30%, rgba(255, 75, 75, 0.05) 0%, transparent 50%);
|
|
33
|
-
overflow-x: hidden;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
.container {
|
|
37
|
-
max-width: 1200px;
|
|
38
|
-
margin: 0 auto;
|
|
39
|
-
padding: 2rem;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
header {
|
|
43
|
-
display: flex;
|
|
44
|
-
justify-content: space-between;
|
|
45
|
-
align-items: center;
|
|
46
|
-
margin-bottom: 3rem;
|
|
47
|
-
border-bottom: 1px solid var(--border-color);
|
|
48
|
-
padding-bottom: 1.5rem;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
.logo {
|
|
52
|
-
font-size: 1.8rem;
|
|
53
|
-
font-weight: 800;
|
|
54
|
-
letter-spacing: -1px;
|
|
55
|
-
background: linear-gradient(90deg, #fff, var(--text-accent));
|
|
56
|
-
-webkit-background-clip: text;
|
|
57
|
-
-webkit-text-fill-color: transparent;
|
|
58
|
-
display: flex;
|
|
59
|
-
align-items: center;
|
|
60
|
-
gap: 10px;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
.badge {
|
|
64
|
-
background: rgba(102, 252, 241, 0.1);
|
|
65
|
-
color: var(--text-accent);
|
|
66
|
-
padding: 0.4rem 1rem;
|
|
67
|
-
border-radius: 50px;
|
|
68
|
-
font-size: 0.85rem;
|
|
69
|
-
font-weight: 600;
|
|
70
|
-
border: 1px solid rgba(102, 252, 241, 0.3);
|
|
71
|
-
box-shadow: 0 0 10px rgba(102, 252, 241, 0.1);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
.dashboard-grid {
|
|
75
|
-
display: grid;
|
|
76
|
-
grid-template-columns: 1fr 2fr;
|
|
77
|
-
gap: 2rem;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
.card {
|
|
81
|
-
background: var(--surface-color);
|
|
82
|
-
backdrop-filter: blur(16px);
|
|
83
|
-
border: 1px solid var(--border-color);
|
|
84
|
-
border-radius: 16px;
|
|
85
|
-
padding: 1.5rem;
|
|
86
|
-
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
|
87
|
-
transition: transform 0.3s ease, border-color 0.3s ease;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
.card:hover {
|
|
91
|
-
transform: translateY(-5px);
|
|
92
|
-
border-color: rgba(102, 252, 241, 0.4);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
.card-header {
|
|
96
|
-
font-size: 1.1rem;
|
|
97
|
-
font-weight: 600;
|
|
98
|
-
margin-bottom: 1.5rem;
|
|
99
|
-
color: #fff;
|
|
100
|
-
display: flex;
|
|
101
|
-
justify-content: space-between;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
.metric {
|
|
105
|
-
font-size: 3rem;
|
|
106
|
-
font-weight: 700;
|
|
107
|
-
color: var(--text-accent);
|
|
108
|
-
margin-bottom: 0.5rem;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
.metric-label {
|
|
112
|
-
font-size: 0.9rem;
|
|
113
|
-
color: #888;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/* Table Styles */
|
|
117
|
-
.table-container {
|
|
118
|
-
width: 100%;
|
|
119
|
-
overflow-x: auto;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
table {
|
|
123
|
-
width: 100%;
|
|
124
|
-
border-collapse: collapse;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
th {
|
|
128
|
-
text-align: left;
|
|
129
|
-
padding: 1rem;
|
|
130
|
-
font-size: 0.85rem;
|
|
131
|
-
text-transform: uppercase;
|
|
132
|
-
letter-spacing: 1px;
|
|
133
|
-
color: #888;
|
|
134
|
-
border-bottom: 1px solid var(--border-color);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
td {
|
|
138
|
-
padding: 1rem;
|
|
139
|
-
font-size: 0.95rem;
|
|
140
|
-
border-bottom: 1px solid rgba(255,255,255,0.05);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
tr:last-child td {
|
|
144
|
-
border-bottom: none;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
tr:hover td {
|
|
148
|
-
background: rgba(255, 255, 255, 0.02);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
.hash {
|
|
152
|
-
font-family: 'Courier New', Courier, monospace;
|
|
153
|
-
color: #888;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
.status {
|
|
157
|
-
padding: 0.3rem 0.8rem;
|
|
158
|
-
border-radius: 4px;
|
|
159
|
-
font-size: 0.8rem;
|
|
160
|
-
font-weight: 600;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
.status.blocked {
|
|
164
|
-
background: rgba(255, 75, 75, 0.1);
|
|
165
|
-
color: var(--danger);
|
|
166
|
-
border: 1px solid rgba(255, 75, 75, 0.3);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
.status.allowed {
|
|
170
|
-
background: rgba(76, 175, 80, 0.1);
|
|
171
|
-
color: var(--success);
|
|
172
|
-
border: 1px solid rgba(76, 175, 80, 0.3);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
.status.warn {
|
|
176
|
-
background: rgba(255, 193, 7, 0.1);
|
|
177
|
-
color: var(--warning);
|
|
178
|
-
border: 1px solid rgba(255, 193, 7, 0.3);
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
.live-indicator {
|
|
182
|
-
display: inline-block;
|
|
183
|
-
width: 8px;
|
|
184
|
-
height: 8px;
|
|
185
|
-
background-color: var(--danger);
|
|
186
|
-
border-radius: 50%;
|
|
187
|
-
margin-right: 8px;
|
|
188
|
-
box-shadow: 0 0 8px var(--danger);
|
|
189
|
-
animation: pulse 1.5s infinite;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
@keyframes pulse {
|
|
193
|
-
0% { transform: scale(0.95); opacity: 0.8; }
|
|
194
|
-
50% { transform: scale(1.2); opacity: 1; }
|
|
195
|
-
100% { transform: scale(0.95); opacity: 0.8; }
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
/* Pulse animation for new rows */
|
|
199
|
-
@keyframes highlightRow {
|
|
200
|
-
0% { background-color: rgba(255, 75, 75, 0.2); }
|
|
201
|
-
100% { background-color: transparent; }
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
.new-row {
|
|
205
|
-
animation: highlightRow 2s ease-out;
|
|
206
|
-
}
|
|
207
|
-
</style>
|
|
208
|
-
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700;800&display=swap" rel="stylesheet">
|
|
209
|
-
</head>
|
|
210
|
-
<body>
|
|
211
|
-
<div style="background: rgba(255, 193, 7, 0.12); border-bottom: 1px solid rgba(255, 193, 7, 0.4); padding: 0.6rem 2rem; font-size: 0.85rem; color: #ffc107; text-align: center; letter-spacing: 0.02em;">
|
|
212
|
-
⚠️ <strong>Demo visualization only.</strong> All data shown is simulated — this dashboard does not connect to a live MCP server or RiskRegistry contract.
|
|
213
|
-
</div>
|
|
214
|
-
<div class="container">
|
|
215
|
-
<header>
|
|
216
|
-
<div class="logo">
|
|
217
|
-
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
218
|
-
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path>
|
|
219
|
-
</svg>
|
|
220
|
-
SafeHands
|
|
221
|
-
</div>
|
|
222
|
-
<div class="badge">Pharos Atlantic Testnet (688689)</div>
|
|
223
|
-
</header>
|
|
224
|
-
|
|
225
|
-
<div class="dashboard-grid">
|
|
226
|
-
<div class="column-left">
|
|
227
|
-
<div class="card" style="margin-bottom: 2rem;">
|
|
228
|
-
<div class="card-header">Threats Blocked</div>
|
|
229
|
-
<div class="metric" id="threatCount">1,248</div>
|
|
230
|
-
<div class="metric-label">+12 in the last hour</div>
|
|
231
|
-
</div>
|
|
232
|
-
|
|
233
|
-
<div class="card">
|
|
234
|
-
<div class="card-header">Top Blocked Vectors</div>
|
|
235
|
-
<ul style="list-style: none; margin-top: 1rem;">
|
|
236
|
-
<li style="margin-bottom: 1rem; display: flex; justify-content: space-between;">
|
|
237
|
-
<span>Unlimited Approvals</span>
|
|
238
|
-
<span style="color: var(--danger);">68%</span>
|
|
239
|
-
</li>
|
|
240
|
-
<li style="margin-bottom: 1rem; display: flex; justify-content: space-between;">
|
|
241
|
-
<span>SSRF (Localhost) x402</span>
|
|
242
|
-
<span style="color: var(--warning);">22%</span>
|
|
243
|
-
</li>
|
|
244
|
-
<li style="display: flex; justify-content: space-between;">
|
|
245
|
-
<span>Mainnet Leakage</span>
|
|
246
|
-
<span style="color: #888;">10%</span>
|
|
247
|
-
</li>
|
|
248
|
-
</ul>
|
|
249
|
-
</div>
|
|
250
|
-
</div>
|
|
251
|
-
|
|
252
|
-
<div class="column-right">
|
|
253
|
-
<div class="card" style="height: 100%;">
|
|
254
|
-
<div class="card-header">
|
|
255
|
-
<div><span class="live-indicator"></span> Agent Preflight Log (Simulated)</div>
|
|
256
|
-
<span style="font-size: 0.8rem; color: #888;">Demo data — not live</span>
|
|
257
|
-
</div>
|
|
258
|
-
<div class="table-container">
|
|
259
|
-
<table>
|
|
260
|
-
<thead>
|
|
261
|
-
<tr>
|
|
262
|
-
<th>Action</th>
|
|
263
|
-
<th>Target / Details</th>
|
|
264
|
-
<th>Decision</th>
|
|
265
|
-
<th>Risk Reason</th>
|
|
266
|
-
</tr>
|
|
267
|
-
</thead>
|
|
268
|
-
<tbody id="logTable">
|
|
269
|
-
<!-- Populated by JS -->
|
|
270
|
-
</tbody>
|
|
271
|
-
</table>
|
|
272
|
-
</div>
|
|
273
|
-
</div>
|
|
274
|
-
</div>
|
|
275
|
-
</div>
|
|
276
|
-
</div>
|
|
277
|
-
|
|
278
|
-
<script>
|
|
279
|
-
const initialLogs = [
|
|
280
|
-
{ action: "approve_token", target: "0xBadActor...9812", decision: "BLOCK", reason: "Unlimited approval requested" },
|
|
281
|
-
{ action: "x402_pay", target: "http://127.0.0.1/admin", decision: "BLOCK", reason: "SSRF_BLOCKED (Localhost)" },
|
|
282
|
-
{ action: "send_payment", target: "0xAgentB...4411 (0.001 PHRS)", decision: "ALLOW", reason: "Low risk testnet payment" },
|
|
283
|
-
{ action: "execute_swap", target: "Unverified Token Pool", decision: "WARN", reason: "Custom Token Non-Registry" },
|
|
284
|
-
{ action: "approve_token", target: "0xSkillEngine...4321", decision: "ALLOW", reason: "Limited approval (50 USDC)" }
|
|
285
|
-
];
|
|
286
|
-
|
|
287
|
-
const logTable = document.getElementById('logTable');
|
|
288
|
-
|
|
289
|
-
function createRow(log, isNew = false) {
|
|
290
|
-
const tr = document.createElement('tr');
|
|
291
|
-
if (isNew) tr.classList.add('new-row');
|
|
292
|
-
|
|
293
|
-
let statusClass = 'allowed';
|
|
294
|
-
if (log.decision === 'BLOCK') statusClass = 'blocked';
|
|
295
|
-
if (log.decision === 'WARN') statusClass = 'warn';
|
|
296
|
-
|
|
297
|
-
tr.innerHTML = `
|
|
298
|
-
<td style="font-weight: 600;">${log.action}</td>
|
|
299
|
-
<td class="hash">${log.target}</td>
|
|
300
|
-
<td><span class="status ${statusClass}">${log.decision}</span></td>
|
|
301
|
-
<td style="color: #aaa; font-size: 0.85rem;">${log.reason}</td>
|
|
302
|
-
`;
|
|
303
|
-
return tr;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
// Init table
|
|
307
|
-
initialLogs.forEach(log => logTable.appendChild(createRow(log)));
|
|
308
|
-
|
|
309
|
-
// Simulate live incoming threats
|
|
310
|
-
const newThreats = [
|
|
311
|
-
{ action: "x402_pay", target: "http://192.168.1.1/config", decision: "BLOCK", reason: "SSRF_BLOCKED (Private IP)" },
|
|
312
|
-
{ action: "custom_call", target: "Mainnet Router (Chain 1)", decision: "BLOCK", reason: "Mainnet execution blocked" },
|
|
313
|
-
{ action: "send_payment", target: "0xUnknown...9999 (1000 PHRS)", decision: "BLOCK", reason: "Payment exceeds 0.01 limit" }
|
|
314
|
-
];
|
|
315
|
-
|
|
316
|
-
let count = parseInt(document.getElementById('threatCount').innerText.replace(',', ''));
|
|
317
|
-
|
|
318
|
-
let threatIndex = 0;
|
|
319
|
-
setInterval(() => {
|
|
320
|
-
if(threatIndex >= newThreats.length) threatIndex = 0; // loop for demo
|
|
321
|
-
|
|
322
|
-
const log = newThreats[threatIndex];
|
|
323
|
-
const row = createRow(log, true);
|
|
324
|
-
|
|
325
|
-
logTable.insertBefore(row, logTable.firstChild);
|
|
326
|
-
if(logTable.children.length > 6) {
|
|
327
|
-
logTable.removeChild(logTable.lastChild);
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
count++;
|
|
331
|
-
document.getElementById('threatCount').innerText = count.toLocaleString();
|
|
332
|
-
|
|
333
|
-
threatIndex++;
|
|
334
|
-
}, 4000); // New log every 4 seconds
|
|
335
|
-
</script>
|
|
336
|
-
</body>
|
|
337
|
-
</html>
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: safehands-guard
|
|
3
|
-
version: 1.0.0
|
|
4
|
-
description: Transaction Safety Firewall / Guardrail Skill for Pharos Skill Engine on Pharos Atlantic Testnet.
|
|
5
|
-
author: SZtch
|
|
6
|
-
chain: pharos-atlantic-testnet
|
|
7
|
-
tags: [pharos, skill-engine, guardrail, transaction-safety, x402, risk, ai-agent]
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
# SafeHands Guard
|
|
11
|
-
|
|
12
|
-
SafeHands Guard is a **Transaction Safety Firewall / Guardrail Skill** for Pharos Skill Engine. It checks whether an AI agent action, token approval, x402 payment, swap, wallet action, or token interaction is safe before execution on Pharos Atlantic Testnet.
|
|
13
|
-
|
|
14
|
-
Use this skill when the user wants to check whether an AI agent action, transaction, token approval, x402 payment, swap, wallet action, or token interaction is safe before execution on Pharos Atlantic Testnet.
|
|
15
|
-
|
|
16
|
-
SafeHands complements Pharos Skill Engine. It is not a replacement for Pharos Skill Engine and should not be used as a generic Web3 toolbox.
|
|
17
|
-
|
|
18
|
-
```text
|
|
19
|
-
User intent
|
|
20
|
-
→ SafeHands preflight
|
|
21
|
-
→ ALLOW / WARN / BLOCK / REQUIRE_CONFIRMATION
|
|
22
|
-
→ Pharos Skill Engine or MCP execution
|
|
23
|
-
→ SafeHands risk report
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
## When to use this skill
|
|
27
|
-
|
|
28
|
-
Use SafeHands when:
|
|
29
|
-
|
|
30
|
-
- The user or agent is about to send PHRS, approve tokens, swap assets, call a custom contract, publish risk data, or pay an x402 endpoint.
|
|
31
|
-
- The user asks if a token address is canonical, custom, non-registry, unknown, or invalid.
|
|
32
|
-
- The user asks why an action was blocked, warned, or requires confirmation.
|
|
33
|
-
- The agent needs a wallet readiness check before an on-chain or x402 action.
|
|
34
|
-
|
|
35
|
-
## When not to use this skill
|
|
36
|
-
|
|
37
|
-
Do not use SafeHands as the primary execution engine for generic Web3 tasks. If the user only wants to deploy a contract, write Solidity, or perform a normal Pharos Skill Engine tutorial flow, use the appropriate Pharos Skill Engine capability first and add SafeHands only as the preflight guardrail.
|
|
38
|
-
|
|
39
|
-
## Pharos Atlantic Testnet context
|
|
40
|
-
|
|
41
|
-
| Field | Value |
|
|
42
|
-
|---|---|
|
|
43
|
-
| Environment | `atlantic-testnet` |
|
|
44
|
-
| Chain ID | `688689` |
|
|
45
|
-
| Mainnet | `false` |
|
|
46
|
-
| Default write tools | disabled |
|
|
47
|
-
| Safety posture | testnet-only guardrail |
|
|
48
|
-
|
|
49
|
-
## Capability Index
|
|
50
|
-
|
|
51
|
-
| User wants to... | Capability | Reference |
|
|
52
|
-
|---|---|---|
|
|
53
|
-
| Check whether an on-chain action is safe before execution | SafeHands Preflight Check | references/safehands.md#safehands-preflight-check |
|
|
54
|
-
| Check whether an x402 paid endpoint is safe to pay | SafeHands x402 Preflight | references/safehands.md#safehands-x402-preflight |
|
|
55
|
-
| Check whether an agent wallet is ready to act | SafeHands Wallet Health | references/safehands.md#safehands-wallet-health |
|
|
56
|
-
| Check whether a token address is canonical or custom | Token Registry Status | references/safehands.md#token-registry-status |
|
|
57
|
-
| Explain why an action was blocked or warned | Explain Risk | references/safehands.md#explain-risk |
|
|
58
|
-
| Generate a human-readable safety report | SafeHands Risk Report | references/safehands.md#safehands-risk-report |
|
|
59
|
-
|
|
60
|
-
## Natural language examples
|
|
61
|
-
|
|
62
|
-
- "Check if this token approval is safe before execution."
|
|
63
|
-
- "Run SafeHands preflight before paying this x402 endpoint."
|
|
64
|
-
- "Explain why this action was blocked."
|
|
65
|
-
- "Check whether this token is canonical on Pharos Atlantic Testnet."
|
|
66
|
-
- "Tell me if this wallet is ready for x402 payment."
|
|
67
|
-
|
|
68
|
-
## Agent behavior guidelines
|
|
69
|
-
|
|
70
|
-
1. Always run `safehands_preflight_check` before any write action.
|
|
71
|
-
2. If `decision` is `BLOCK`, do not execute the action.
|
|
72
|
-
3. If `decision` is `WARN`, explain the risk and ask for user confirmation.
|
|
73
|
-
4. If `decision` is `REQUIRE_CONFIRMATION`, ask for explicit user approval.
|
|
74
|
-
5. If `decision` is `REQUIRE_FUNDING`, ask the user to fund the testnet wallet before continuing.
|
|
75
|
-
6. If `decision` is `REQUIRE_TOKEN_REVIEW`, ask the user to verify the exact token contract.
|
|
76
|
-
7. If `decision` is `ALLOW`, the action may continue through Pharos Skill Engine or MCP execution.
|
|
77
|
-
8. Never silently replace a user-provided token address.
|
|
78
|
-
9. Never request or reveal private keys in the conversation.
|
|
79
|
-
10. Treat SafeHands output as a safety decision, not a guarantee that external contracts are audited.
|
|
80
|
-
|
|
81
|
-
## Safety disclaimer
|
|
82
|
-
|
|
83
|
-
SafeHands is built for Pharos Atlantic Testnet hackathon workflows. It is not audited for mainnet production use. Write tools are disabled by default and require explicit configuration. Managed wallet storage is testnet-grade only.
|
|
84
|
-
|
|
85
|
-
For command templates, parameters, output parsing, and error handling, see [`references/safehands.md`](references/safehands.md).
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"safeApproval": {
|
|
3
|
-
"actionType": "approve_token",
|
|
4
|
-
"chainId": 688689,
|
|
5
|
-
"isMainnet": false,
|
|
6
|
-
"tokenAddress": "0xcfC8330f4BCAB529c625D12781b1C19466A9Fc8B",
|
|
7
|
-
"spender": "0x000000000000000000000000000000000000dEaD",
|
|
8
|
-
"approvalAmount": "1"
|
|
9
|
-
},
|
|
10
|
-
"blockedUnlimitedApproval": {
|
|
11
|
-
"actionType": "approve_token",
|
|
12
|
-
"chainId": 688689,
|
|
13
|
-
"isMainnet": false,
|
|
14
|
-
"tokenAddress": "0xcfC8330f4BCAB529c625D12781b1C19466A9Fc8B",
|
|
15
|
-
"spender": "0x000000000000000000000000000000000000dEaD",
|
|
16
|
-
"approvalAmount": "max"
|
|
17
|
-
},
|
|
18
|
-
"x402FreeEndpoint": {
|
|
19
|
-
"url": "https://example.com/health",
|
|
20
|
-
"paymentAmountUsdc": "0",
|
|
21
|
-
"probeEndpoint": false
|
|
22
|
-
},
|
|
23
|
-
"x402PaidEndpoint": {
|
|
24
|
-
"url": "https://example.com/assess-risk",
|
|
25
|
-
"paymentAmountUsdc": "0.001",
|
|
26
|
-
"probeEndpoint": false
|
|
27
|
-
},
|
|
28
|
-
"mainnetBlockedAction": {
|
|
29
|
-
"actionType": "send_payment",
|
|
30
|
-
"chainId": 1,
|
|
31
|
-
"isMainnet": true,
|
|
32
|
-
"recipient": "0x000000000000000000000000000000000000dEaD",
|
|
33
|
-
"amount": "0.001"
|
|
34
|
-
},
|
|
35
|
-
"chainIdMismatch": {
|
|
36
|
-
"actionType": "send_payment",
|
|
37
|
-
"chainId": 688688,
|
|
38
|
-
"isMainnet": false,
|
|
39
|
-
"recipient": "0x000000000000000000000000000000000000dEaD",
|
|
40
|
-
"amount": "0.001"
|
|
41
|
-
},
|
|
42
|
-
"customTokenWarning": {
|
|
43
|
-
"actionType": "execute_swap",
|
|
44
|
-
"chainId": 688689,
|
|
45
|
-
"isMainnet": false,
|
|
46
|
-
"tokenAddress": "0x000000000000000000000000000000000000dEaD",
|
|
47
|
-
"amount": "1"
|
|
48
|
-
}
|
|
49
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"environment": "atlantic-testnet",
|
|
3
|
-
"chainId": 688689,
|
|
4
|
-
"isMainnet": false,
|
|
5
|
-
"writeToolsEnabledByDefault": false,
|
|
6
|
-
"allowUnlimitedApprovalByDefault": false,
|
|
7
|
-
"maxTxAmountPHRS": "0.1",
|
|
8
|
-
"maxX402PaymentUSDC": "0.01",
|
|
9
|
-
"maxApprovalAmountUSDC": "10",
|
|
10
|
-
"maxDailySpendUSD": "10"
|
|
11
|
-
}
|