shll-skills 5.0.1 → 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 +3 -1
- package/SKILL.md +22 -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,7 +65,7 @@ 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
|
|------|------|-------------|
|
|
@@ -89,6 +89,8 @@ The server communicates via **stdio** using JSON-RPC 2.0. Send `tools/list` to d
|
|
|
89
89
|
| `config` | Write | Configure risk parameters (spending limits, cooldown) |
|
|
90
90
|
| `setup_guide` | Info | Generate dual-wallet onboarding URL + steps |
|
|
91
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 |
|
|
92
94
|
|
|
93
95
|
---
|
|
94
96
|
|
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
|
|
@@ -249,6 +249,27 @@ If the user has multiple DeFi skills installed, understand the architectural dif
|
|
|
249
249
|
|
|
250
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
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
|
+
|
|
252
273
|
---
|
|
253
274
|
|
|
254
275
|
## LINKS
|
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",
|