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 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: 5.0.0
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shll-skills",
3
- "version": "5.0.0",
3
+ "version": "5.1.0",
4
4
  "description": "SHLL DeFi Agent — CLI + MCP Server for BSC",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
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",