shll-skills 5.0.0 → 5.1.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 +29 -1
- package/SKILL.md +44 -1
- package/dist/mcp.js +90 -0
- package/dist/mcp.mjs +90 -0
- package/package.json +1 -1
- package/src/mcp.ts +101 -0
package/README.md
CHANGED
|
@@ -65,18 +65,32 @@ RUNNER_PRIVATE_KEY=0x... shll-mcp
|
|
|
65
65
|
|
|
66
66
|
The server communicates via **stdio** using JSON-RPC 2.0. Send `tools/list` to discover all available tools.
|
|
67
67
|
|
|
68
|
-
### Available MCP Tools
|
|
68
|
+
### Available MCP Tools (22 total)
|
|
69
69
|
|
|
70
70
|
| Tool | Type | Description |
|
|
71
71
|
|------|------|-------------|
|
|
72
72
|
| `portfolio` | Read | Vault holdings + token balances |
|
|
73
73
|
| `balance` | Read | Operator wallet gas balance |
|
|
74
74
|
| `price` | Read | Real-time token price (DexScreener) |
|
|
75
|
+
| `search` | Read | Search token by name/symbol on BSC |
|
|
76
|
+
| `tokens` | Read | List known token symbols + addresses |
|
|
75
77
|
| `lending_info` | Read | Venus Protocol supply balances + APY |
|
|
78
|
+
| `policies` | Read | View active on-chain policies + config |
|
|
79
|
+
| `status` | Read | One-shot security overview (vault, operator, policies, activity) |
|
|
80
|
+
| `history` | Read | Recent transactions + policy rejections |
|
|
81
|
+
| `my_agents` | Read | List agents where current operator is authorized |
|
|
82
|
+
| `listings` | Read | Available agent templates for rent |
|
|
76
83
|
| `swap` | Write | PancakeSwap V2/V3 auto-routing swap |
|
|
84
|
+
| `wrap` | Write | BNB → WBNB in vault |
|
|
85
|
+
| `unwrap` | Write | WBNB → BNB in vault |
|
|
77
86
|
| `lend` | Write | Supply tokens to Venus for yield |
|
|
78
87
|
| `redeem` | Write | Withdraw from Venus |
|
|
79
88
|
| `transfer` | Write | Send BNB or ERC20 from vault |
|
|
89
|
+
| `config` | Write | Configure risk parameters (spending limits, cooldown) |
|
|
90
|
+
| `setup_guide` | Info | Generate dual-wallet onboarding URL + steps |
|
|
91
|
+
| `generate_wallet` | Info | Create new operator wallet (address + key) |
|
|
92
|
+
| `execute_calldata` | Write | Execute raw calldata from any source through PolicyGuard |
|
|
93
|
+
| `execute_calldata_batch` | Write | Execute multiple calldata actions atomically through PolicyGuard |
|
|
80
94
|
|
|
81
95
|
---
|
|
82
96
|
|
|
@@ -169,6 +183,20 @@ AI Agent -> CLI/MCP -> PolicyClient.validate() -> PolicyGuard (on-chain) -> vaul
|
|
|
169
183
|
- npm: [shll-skills](https://www.npmjs.com/package/shll-skills)
|
|
170
184
|
- GitHub: [kledx/shll-skills](https://github.com/kledx/shll-skills)
|
|
171
185
|
|
|
186
|
+
## 🧩 Multi-Skill Compatibility
|
|
187
|
+
|
|
188
|
+
SHLL can coexist with other DeFi skills (OKX DEX API, Bitget Wallet, etc.). Key architectural differences:
|
|
189
|
+
|
|
190
|
+
| | **SHLL** | **OKX DEX API** | **Bitget Wallet** |
|
|
191
|
+
|---|---|---|---|
|
|
192
|
+
| **Wallet** | Smart contract vault (AgentNFA) | User EOA | Bitget custody |
|
|
193
|
+
| **Execution** | On-chain via PolicyGuard | Calldata only (user signs) | HMAC API |
|
|
194
|
+
| **Safety** | On-chain policy enforcement | User approval | API key perms |
|
|
195
|
+
| **AI autonomy** | Execute within policy limits | Cannot execute | Full API access |
|
|
196
|
+
| **Risk if key leaked** | Policy-limited trades only | N/A | Full API access |
|
|
197
|
+
|
|
198
|
+
**SHLL is the only skill with on-chain policy enforcement.** Even if the AI hallucinates, the smart contract rejects unsafe operations.
|
|
199
|
+
|
|
172
200
|
## License
|
|
173
201
|
|
|
174
202
|
MIT
|
package/SKILL.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: shll-run
|
|
3
3
|
description: Execute DeFi transactions on BSC via SHLL AgentNFA. The AI handles all commands — users only need to chat.
|
|
4
|
-
version:
|
|
4
|
+
version: 6.0.0
|
|
5
5
|
author: SHLL Team
|
|
6
6
|
website: https://shll.run
|
|
7
7
|
twitter: https://twitter.com/shllrun
|
|
@@ -26,6 +26,7 @@ These rules are **non-negotiable**. Violating any of them is a critical failure.
|
|
|
26
26
|
4. **One agent per conversation.** Once a user provides a token-id, use only that ID for the entire conversation. If they want to switch, they must explicitly say so.
|
|
27
27
|
5. **Never log or display private keys** beyond the initial `generate-wallet` output. If the user asks you to repeat it, remind them to check their saved copy.
|
|
28
28
|
6. **Do not infer trading intent.** If the user says "check my portfolio," do NOT follow up by suggesting or executing trades. Only trade when the user explicitly asks.
|
|
29
|
+
7. **Multi-skill coexistence.** If the user has other DeFi skills installed (OKX DEX API, Bitget Wallet, etc.), **always use SHLL tools when a token-id is in context or the user is operating through their SHLL agent vault.** Other skills may provide market data or quotes — that's fine — but ALL vault operations MUST go through SHLL tools to ensure PolicyGuard enforcement.
|
|
29
30
|
|
|
30
31
|
---
|
|
31
32
|
|
|
@@ -229,6 +230,48 @@ All commands output JSON:
|
|
|
229
230
|
- Rejected by policy: `{"status":"rejected", "reason":"Exceeds per-tx limit"}`
|
|
230
231
|
- Error: `{"status":"error", "message":"..."}`
|
|
231
232
|
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## 🧩 MULTI-SKILL COMPATIBILITY: How SHLL Differs from Other DeFi Skills
|
|
236
|
+
|
|
237
|
+
If the user has multiple DeFi skills installed, understand the architectural differences:
|
|
238
|
+
|
|
239
|
+
| | **SHLL** | **OKX DEX API** | **Bitget Wallet Skill** |
|
|
240
|
+
|---|---|---|---|
|
|
241
|
+
| **Wallet model** | Smart contract vault (AgentNFA) | User's EOA wallet | Bitget API custody |
|
|
242
|
+
| **Execution** | On-chain via PolicyGuard | Generates calldata → user signs | HMAC API call → Bitget backend |
|
|
243
|
+
| **Safety** | On-chain policy enforcement (spending limits, cooldowns, DEX whitelist) | User approval only | API key permissions |
|
|
244
|
+
| **Fund location** | On-chain vault (isolated per agent) | User's wallet directly | Bitget platform |
|
|
245
|
+
| **AI autonomy** | Can execute within policy limits | Cannot execute (calldata only) | Can execute via API |
|
|
246
|
+
| **Risk if key leaked** | Limited to policy-allowed trades | N/A (no key) | Full API access |
|
|
247
|
+
|
|
248
|
+
**Key distinction:** SHLL is the only skill with **on-chain policy enforcement**. Even if the AI makes a mistake, the smart contract rejects operations that violate spending limits or cooldowns. Other skills rely on the user or platform to gatekeep.
|
|
249
|
+
|
|
250
|
+
**Routing rule:** When the user's intent involves their SHLL agent vault (identified by token-id), ALWAYS use SHLL tools. It's fine to use other skills for price quotes, market research, or operations outside SHLL.
|
|
251
|
+
|
|
252
|
+
### Cross-Skill Execution Pattern
|
|
253
|
+
|
|
254
|
+
If another skill provides **calldata** (e.g. OKX DEX API returns a swap route), you can execute it through SHLL's safety layer:
|
|
255
|
+
|
|
256
|
+
1. **Get calldata from other skill** → e.g., OKX returns `{to: "0xDEX...", data: "0xABC...", value: "100000..."}`
|
|
257
|
+
2. **Execute via SHLL** → use `execute_calldata` tool with the target, data, and value
|
|
258
|
+
3. **PolicyGuard validates** → spending limits, cooldowns, whitelists enforced
|
|
259
|
+
4. **Vault executes** → transaction runs from the agent vault
|
|
260
|
+
|
|
261
|
+
Example flow:
|
|
262
|
+
```
|
|
263
|
+
User: "Use OKX to find the best swap route for 0.5 BNB to USDT, then execute it"
|
|
264
|
+
|
|
265
|
+
Step 1: Call OKX DEX API skill → get calldata
|
|
266
|
+
Step 2: Call SHLL execute_calldata(token_id, target, data, value) → PolicyGuard validated execution
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
**This pattern gives you the best of both worlds:** superior routing from specialized DEX aggregators + SHLL's on-chain policy enforcement.
|
|
270
|
+
|
|
271
|
+
For multi-step transactions (e.g. approve + swap), use `execute_calldata_batch` to execute atomically.
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
232
275
|
## LINKS
|
|
233
276
|
- Website: https://shll.run
|
|
234
277
|
- Twitter: @shllrun
|
package/dist/mcp.js
CHANGED
|
@@ -1314,6 +1314,96 @@ server.tool(
|
|
|
1314
1314
|
};
|
|
1315
1315
|
}
|
|
1316
1316
|
);
|
|
1317
|
+
server.tool(
|
|
1318
|
+
"execute_calldata",
|
|
1319
|
+
"Execute raw calldata through PolicyGuard safety layer. Use this to execute transactions from other DeFi skills (OKX DEX API, Bitget, 1inch, etc.) with SHLL on-chain policy enforcement. All actions are validated against spending limits, cooldowns, and whitelists before execution.",
|
|
1320
|
+
{
|
|
1321
|
+
token_id: import_zod.z.string().describe("Agent NFA Token ID"),
|
|
1322
|
+
target: import_zod.z.string().describe("Target contract address (0x...)"),
|
|
1323
|
+
data: import_zod.z.string().describe("Transaction calldata hex string"),
|
|
1324
|
+
value: import_zod.z.string().default("0").describe("Native BNB value in wei (default: 0)")
|
|
1325
|
+
},
|
|
1326
|
+
async ({ token_id, target, data, value }) => {
|
|
1327
|
+
const { policyClient } = createClients();
|
|
1328
|
+
const tokenId = BigInt(token_id);
|
|
1329
|
+
const action = {
|
|
1330
|
+
target,
|
|
1331
|
+
value: BigInt(value),
|
|
1332
|
+
data
|
|
1333
|
+
};
|
|
1334
|
+
const sim = await policyClient.validate(tokenId, action);
|
|
1335
|
+
if (!sim.ok) {
|
|
1336
|
+
return {
|
|
1337
|
+
content: [{
|
|
1338
|
+
type: "text",
|
|
1339
|
+
text: JSON.stringify({
|
|
1340
|
+
status: "rejected",
|
|
1341
|
+
reason: sim.reason,
|
|
1342
|
+
note: "PolicyGuard rejected this calldata. The target contract or operation may not be whitelisted, or it exceeds spending/cooldown limits."
|
|
1343
|
+
})
|
|
1344
|
+
}]
|
|
1345
|
+
};
|
|
1346
|
+
}
|
|
1347
|
+
const result = await policyClient.execute(tokenId, action, true);
|
|
1348
|
+
return {
|
|
1349
|
+
content: [{
|
|
1350
|
+
type: "text",
|
|
1351
|
+
text: JSON.stringify({
|
|
1352
|
+
status: "success",
|
|
1353
|
+
hash: result.hash,
|
|
1354
|
+
note: "Calldata executed through PolicyGuard. Transaction validated against all on-chain policies."
|
|
1355
|
+
})
|
|
1356
|
+
}]
|
|
1357
|
+
};
|
|
1358
|
+
}
|
|
1359
|
+
);
|
|
1360
|
+
server.tool(
|
|
1361
|
+
"execute_calldata_batch",
|
|
1362
|
+
"Execute multiple raw calldata actions atomically through PolicyGuard. Useful for approve+swap patterns from external DEX aggregators.",
|
|
1363
|
+
{
|
|
1364
|
+
token_id: import_zod.z.string().describe("Agent NFA Token ID"),
|
|
1365
|
+
actions: import_zod.z.array(import_zod.z.object({
|
|
1366
|
+
target: import_zod.z.string().describe("Target contract address"),
|
|
1367
|
+
data: import_zod.z.string().describe("Calldata hex"),
|
|
1368
|
+
value: import_zod.z.string().default("0").describe("BNB value in wei")
|
|
1369
|
+
})).describe("Array of actions to execute atomically")
|
|
1370
|
+
},
|
|
1371
|
+
async ({ token_id, actions: rawActions }) => {
|
|
1372
|
+
const { policyClient } = createClients();
|
|
1373
|
+
const tokenId = BigInt(token_id);
|
|
1374
|
+
const actions = rawActions.map((a) => ({
|
|
1375
|
+
target: a.target,
|
|
1376
|
+
value: BigInt(a.value || "0"),
|
|
1377
|
+
data: a.data
|
|
1378
|
+
}));
|
|
1379
|
+
for (let i = 0; i < actions.length; i++) {
|
|
1380
|
+
const sim = await policyClient.validate(tokenId, actions[i]);
|
|
1381
|
+
if (!sim.ok) {
|
|
1382
|
+
return {
|
|
1383
|
+
content: [{
|
|
1384
|
+
type: "text",
|
|
1385
|
+
text: JSON.stringify({
|
|
1386
|
+
status: "rejected",
|
|
1387
|
+
failedActionIndex: i,
|
|
1388
|
+
reason: sim.reason
|
|
1389
|
+
})
|
|
1390
|
+
}]
|
|
1391
|
+
};
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
const result = actions.length === 1 ? await policyClient.execute(tokenId, actions[0], true) : await policyClient.executeBatch(tokenId, actions, true);
|
|
1395
|
+
return {
|
|
1396
|
+
content: [{
|
|
1397
|
+
type: "text",
|
|
1398
|
+
text: JSON.stringify({
|
|
1399
|
+
status: "success",
|
|
1400
|
+
hash: result.hash,
|
|
1401
|
+
actionsExecuted: actions.length
|
|
1402
|
+
})
|
|
1403
|
+
}]
|
|
1404
|
+
};
|
|
1405
|
+
}
|
|
1406
|
+
);
|
|
1317
1407
|
server.tool(
|
|
1318
1408
|
"generate_wallet",
|
|
1319
1409
|
"Generate a new operator wallet (address + private key) for AI to use. This is a HOT wallet for trading only.",
|
package/dist/mcp.mjs
CHANGED
|
@@ -825,6 +825,96 @@ server.tool(
|
|
|
825
825
|
};
|
|
826
826
|
}
|
|
827
827
|
);
|
|
828
|
+
server.tool(
|
|
829
|
+
"execute_calldata",
|
|
830
|
+
"Execute raw calldata through PolicyGuard safety layer. Use this to execute transactions from other DeFi skills (OKX DEX API, Bitget, 1inch, etc.) with SHLL on-chain policy enforcement. All actions are validated against spending limits, cooldowns, and whitelists before execution.",
|
|
831
|
+
{
|
|
832
|
+
token_id: z.string().describe("Agent NFA Token ID"),
|
|
833
|
+
target: z.string().describe("Target contract address (0x...)"),
|
|
834
|
+
data: z.string().describe("Transaction calldata hex string"),
|
|
835
|
+
value: z.string().default("0").describe("Native BNB value in wei (default: 0)")
|
|
836
|
+
},
|
|
837
|
+
async ({ token_id, target, data, value }) => {
|
|
838
|
+
const { policyClient } = createClients();
|
|
839
|
+
const tokenId = BigInt(token_id);
|
|
840
|
+
const action = {
|
|
841
|
+
target,
|
|
842
|
+
value: BigInt(value),
|
|
843
|
+
data
|
|
844
|
+
};
|
|
845
|
+
const sim = await policyClient.validate(tokenId, action);
|
|
846
|
+
if (!sim.ok) {
|
|
847
|
+
return {
|
|
848
|
+
content: [{
|
|
849
|
+
type: "text",
|
|
850
|
+
text: JSON.stringify({
|
|
851
|
+
status: "rejected",
|
|
852
|
+
reason: sim.reason,
|
|
853
|
+
note: "PolicyGuard rejected this calldata. The target contract or operation may not be whitelisted, or it exceeds spending/cooldown limits."
|
|
854
|
+
})
|
|
855
|
+
}]
|
|
856
|
+
};
|
|
857
|
+
}
|
|
858
|
+
const result = await policyClient.execute(tokenId, action, true);
|
|
859
|
+
return {
|
|
860
|
+
content: [{
|
|
861
|
+
type: "text",
|
|
862
|
+
text: JSON.stringify({
|
|
863
|
+
status: "success",
|
|
864
|
+
hash: result.hash,
|
|
865
|
+
note: "Calldata executed through PolicyGuard. Transaction validated against all on-chain policies."
|
|
866
|
+
})
|
|
867
|
+
}]
|
|
868
|
+
};
|
|
869
|
+
}
|
|
870
|
+
);
|
|
871
|
+
server.tool(
|
|
872
|
+
"execute_calldata_batch",
|
|
873
|
+
"Execute multiple raw calldata actions atomically through PolicyGuard. Useful for approve+swap patterns from external DEX aggregators.",
|
|
874
|
+
{
|
|
875
|
+
token_id: z.string().describe("Agent NFA Token ID"),
|
|
876
|
+
actions: z.array(z.object({
|
|
877
|
+
target: z.string().describe("Target contract address"),
|
|
878
|
+
data: z.string().describe("Calldata hex"),
|
|
879
|
+
value: z.string().default("0").describe("BNB value in wei")
|
|
880
|
+
})).describe("Array of actions to execute atomically")
|
|
881
|
+
},
|
|
882
|
+
async ({ token_id, actions: rawActions }) => {
|
|
883
|
+
const { policyClient } = createClients();
|
|
884
|
+
const tokenId = BigInt(token_id);
|
|
885
|
+
const actions = rawActions.map((a) => ({
|
|
886
|
+
target: a.target,
|
|
887
|
+
value: BigInt(a.value || "0"),
|
|
888
|
+
data: a.data
|
|
889
|
+
}));
|
|
890
|
+
for (let i = 0; i < actions.length; i++) {
|
|
891
|
+
const sim = await policyClient.validate(tokenId, actions[i]);
|
|
892
|
+
if (!sim.ok) {
|
|
893
|
+
return {
|
|
894
|
+
content: [{
|
|
895
|
+
type: "text",
|
|
896
|
+
text: JSON.stringify({
|
|
897
|
+
status: "rejected",
|
|
898
|
+
failedActionIndex: i,
|
|
899
|
+
reason: sim.reason
|
|
900
|
+
})
|
|
901
|
+
}]
|
|
902
|
+
};
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
const result = actions.length === 1 ? await policyClient.execute(tokenId, actions[0], true) : await policyClient.executeBatch(tokenId, actions, true);
|
|
906
|
+
return {
|
|
907
|
+
content: [{
|
|
908
|
+
type: "text",
|
|
909
|
+
text: JSON.stringify({
|
|
910
|
+
status: "success",
|
|
911
|
+
hash: result.hash,
|
|
912
|
+
actionsExecuted: actions.length
|
|
913
|
+
})
|
|
914
|
+
}]
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
);
|
|
828
918
|
server.tool(
|
|
829
919
|
"generate_wallet",
|
|
830
920
|
"Generate a new operator wallet (address + private key) for AI to use. This is a HOT wallet for trading only.",
|
package/package.json
CHANGED
package/src/mcp.ts
CHANGED
|
@@ -968,6 +968,107 @@ server.tool(
|
|
|
968
968
|
}
|
|
969
969
|
);
|
|
970
970
|
|
|
971
|
+
// ── Tool: execute_calldata ──────────────────────────────
|
|
972
|
+
// Universal safety execution layer: accepts calldata from ANY source
|
|
973
|
+
// (OKX DEX API, Bitget, 1inch, etc.) and routes through PolicyGuard
|
|
974
|
+
server.tool(
|
|
975
|
+
"execute_calldata",
|
|
976
|
+
"Execute raw calldata through PolicyGuard safety layer. Use this to execute transactions from other DeFi skills (OKX DEX API, Bitget, 1inch, etc.) with SHLL on-chain policy enforcement. All actions are validated against spending limits, cooldowns, and whitelists before execution.",
|
|
977
|
+
{
|
|
978
|
+
token_id: z.string().describe("Agent NFA Token ID"),
|
|
979
|
+
target: z.string().describe("Target contract address (0x...)"),
|
|
980
|
+
data: z.string().describe("Transaction calldata hex string"),
|
|
981
|
+
value: z.string().default("0").describe("Native BNB value in wei (default: 0)"),
|
|
982
|
+
},
|
|
983
|
+
async ({ token_id, target, data, value }) => {
|
|
984
|
+
const { policyClient } = createClients();
|
|
985
|
+
const tokenId = BigInt(token_id);
|
|
986
|
+
const action: Action = {
|
|
987
|
+
target: target as Address,
|
|
988
|
+
value: BigInt(value),
|
|
989
|
+
data: data as Hex,
|
|
990
|
+
};
|
|
991
|
+
|
|
992
|
+
// Validate through PolicyGuard (spending limits, cooldowns, whitelists)
|
|
993
|
+
const sim = await policyClient.validate(tokenId, action);
|
|
994
|
+
if (!sim.ok) {
|
|
995
|
+
return {
|
|
996
|
+
content: [{
|
|
997
|
+
type: "text" as const, text: JSON.stringify({
|
|
998
|
+
status: "rejected",
|
|
999
|
+
reason: sim.reason,
|
|
1000
|
+
note: "PolicyGuard rejected this calldata. The target contract or operation may not be whitelisted, or it exceeds spending/cooldown limits.",
|
|
1001
|
+
})
|
|
1002
|
+
}]
|
|
1003
|
+
};
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
const result = await policyClient.execute(tokenId, action, true);
|
|
1007
|
+
return {
|
|
1008
|
+
content: [{
|
|
1009
|
+
type: "text" as const, text: JSON.stringify({
|
|
1010
|
+
status: "success",
|
|
1011
|
+
hash: result.hash,
|
|
1012
|
+
note: "Calldata executed through PolicyGuard. Transaction validated against all on-chain policies.",
|
|
1013
|
+
})
|
|
1014
|
+
}]
|
|
1015
|
+
};
|
|
1016
|
+
}
|
|
1017
|
+
);
|
|
1018
|
+
|
|
1019
|
+
// ── Tool: execute_calldata_batch ─────────────────────────
|
|
1020
|
+
server.tool(
|
|
1021
|
+
"execute_calldata_batch",
|
|
1022
|
+
"Execute multiple raw calldata actions atomically through PolicyGuard. Useful for approve+swap patterns from external DEX aggregators.",
|
|
1023
|
+
{
|
|
1024
|
+
token_id: z.string().describe("Agent NFA Token ID"),
|
|
1025
|
+
actions: z.array(z.object({
|
|
1026
|
+
target: z.string().describe("Target contract address"),
|
|
1027
|
+
data: z.string().describe("Calldata hex"),
|
|
1028
|
+
value: z.string().default("0").describe("BNB value in wei"),
|
|
1029
|
+
})).describe("Array of actions to execute atomically"),
|
|
1030
|
+
},
|
|
1031
|
+
async ({ token_id, actions: rawActions }) => {
|
|
1032
|
+
const { policyClient } = createClients();
|
|
1033
|
+
const tokenId = BigInt(token_id);
|
|
1034
|
+
const actions: Action[] = rawActions.map(a => ({
|
|
1035
|
+
target: a.target as Address,
|
|
1036
|
+
value: BigInt(a.value || "0"),
|
|
1037
|
+
data: a.data as Hex,
|
|
1038
|
+
}));
|
|
1039
|
+
|
|
1040
|
+
// Validate all actions
|
|
1041
|
+
for (let i = 0; i < actions.length; i++) {
|
|
1042
|
+
const sim = await policyClient.validate(tokenId, actions[i]);
|
|
1043
|
+
if (!sim.ok) {
|
|
1044
|
+
return {
|
|
1045
|
+
content: [{
|
|
1046
|
+
type: "text" as const, text: JSON.stringify({
|
|
1047
|
+
status: "rejected",
|
|
1048
|
+
failedActionIndex: i,
|
|
1049
|
+
reason: sim.reason,
|
|
1050
|
+
})
|
|
1051
|
+
}]
|
|
1052
|
+
};
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
const result = actions.length === 1
|
|
1057
|
+
? await policyClient.execute(tokenId, actions[0], true)
|
|
1058
|
+
: await policyClient.executeBatch(tokenId, actions, true);
|
|
1059
|
+
|
|
1060
|
+
return {
|
|
1061
|
+
content: [{
|
|
1062
|
+
type: "text" as const, text: JSON.stringify({
|
|
1063
|
+
status: "success",
|
|
1064
|
+
hash: result.hash,
|
|
1065
|
+
actionsExecuted: actions.length,
|
|
1066
|
+
})
|
|
1067
|
+
}]
|
|
1068
|
+
};
|
|
1069
|
+
}
|
|
1070
|
+
);
|
|
1071
|
+
|
|
971
1072
|
// ── Tool: generate_wallet ───────────────────────────────
|
|
972
1073
|
server.tool(
|
|
973
1074
|
"generate_wallet",
|