shll-skills 6.0.4 → 6.0.5

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
@@ -1,4 +1,4 @@
1
- # SHLL Skills — AI Agent DeFi Toolkit on BSC
1
+ # SHLL Skills — AI Agent DeFi Toolkit on BSC
2
2
 
3
3
  [![Website](https://img.shields.io/badge/Website-shll.run-blue)](https://shll.run) [![Twitter](https://img.shields.io/badge/Twitter-@shllrun-1DA1F2)](https://twitter.com/shllrun) [![npm](https://img.shields.io/npm/v/shll-skills)](https://www.npmjs.com/package/shll-skills) [![ClawHub](https://img.shields.io/badge/ClawHub-shll--skills-orange)](https://clawhub.ai/kledx/shll-skills)
4
4
 
@@ -85,7 +85,7 @@ The server communicates via **stdio** using JSON-RPC 2.0. Send `tools/list` to d
85
85
  | `status` | Read | One-shot readiness overview with blockers, warnings, and next actions |
86
86
  | `history` | Read | Recent transactions + policy rejections |
87
87
  | `token_restriction` | Read | View token whitelist restriction status + whitelisted tokens |
88
- | `listings` | Read | Available agent templates for rent |
88
+ | `listings` | Read | Available agent templates for subscription |
89
89
  | `four_info` | Read | Query Four.meme bonding curve token info |
90
90
  | `swap` | Write | PancakeSwap V2/V3 auto-routing swap |
91
91
  | `wrap` | Write | BNB → WBNB in vault |
@@ -180,13 +180,13 @@ AI Agent -> CLI/MCP -> PolicyClient.validate() -> PolicyGuard (on-chain) -> vaul
180
180
  | | Owner Wallet | Operator Wallet (RUNNER_PRIVATE_KEY) |
181
181
  |---|---|---|
182
182
  | **Who holds it** | User (MetaMask/hardware) | AI agent |
183
- | **Use it for** | Rent or mint the agent, hold the Agent NFT, authorize operator | Pay gas and execute policy-limited actions |
183
+ | **Use it for** | Subscribe or mint the agent, hold the Agent NFT, authorize operator | Pay gas and execute policy-limited actions |
184
184
  | **Can trade** | — | ✅ Within PolicyGuard limits |
185
185
  | **Can withdraw vault** | ✅ | ❌ |
186
186
  | **Can transfer NFT** | ✅ | ❌ |
187
187
  | **Risk if leaked** | 🚨 Full vault access | ⚠️ Limited to policy-allowed trades |
188
188
 
189
- Do not use the operator wallet to mint or rent the agent. Do not hold the Agent NFT in the operator wallet. Keep only a small BNB balance there for gas.
189
+ Do not use the operator wallet to mint or subscribe to the agent. Do not hold the Agent NFT in the operator wallet. Keep only a small BNB balance there for gas.
190
190
 
191
191
  After setup, run `status` first. It returns a machine-friendly readiness object with:
192
192
  - `readiness.ready`
package/SKILL.md CHANGED
@@ -196,8 +196,8 @@ export SHLL_RPC="https://your-private-bsc-rpc.example.com"
196
196
  - Recommend the listing with `recommended=true` by default unless the user explicitly wants a specialized template.
197
197
  - Run `shll-run setup-guide -l <listingId> -d <days>`.
198
198
  - Send `setupUrl` plus the wallet-role explanation.
199
- - Explicitly warn: do not use the operator wallet to mint, rent, or hold the Agent NFT.
200
- - Explicitly warn: use the owner wallet in the browser for rental or mint and for operator authorization.
199
+ - Explicitly warn: do not use the operator wallet to mint, subscribe to, or hold the Agent NFT.
200
+ - Explicitly warn: use the owner wallet in the browser for subscription or mint and for operator authorization.
201
201
 
202
202
  4. User returns with token ID:
203
203
  - Run `shll-run status -k <tokenId>`.
@@ -314,7 +314,7 @@ When the user provides a token address:
314
314
  2. `NOT authorized for token-id`
315
315
  - Operator wallet is not authorized; use setup guide or set operator in console.
316
316
 
317
- 3. `rental has EXPIRED` or `operator authorization has EXPIRED`
317
+ 3. `subscription has EXPIRED` or `operator authorization has EXPIRED`
318
318
  - Renew subscription or authorization first.
319
319
 
320
320
  4. `status: error` with `errorCode: POLICY_REJECTED`
@@ -337,7 +337,7 @@ When the user provides a token address:
337
337
  1. Never describe `generate-wallet` as if it were the user's main wallet.
338
338
  2. Always call it the operator wallet or AI hot wallet.
339
339
  3. Always explain the dual-wallet model the first time setup is discussed.
340
- 4. Always warn that the operator wallet must not be used to mint, rent, or hold the Agent NFT.
340
+ 4. Always warn that the operator wallet must not be used to mint, subscribe to, or hold the Agent NFT.
341
341
  5. Do not ask the user to manually set `RUNNER_PRIVATE_KEY` in OpenClaw; AI should do it.
342
342
  6. After setup is complete and the user provides a token-id, run readiness checks automatically before asking the user what to do next.
343
343
  7. When multiple listings are available, recommend one by default and explain why.
@@ -855,8 +855,8 @@ async function checkAccess(rpcUrl, tokenId, existingPublicClient) {
855
855
  if (now > userExpires) {
856
856
  return {
857
857
  blocked: true,
858
- errorType: "rental_expired",
859
- message: `Agent token-id ${tokenId} rental has EXPIRED (expired at ${new Date(Number(userExpires) * 1e3).toISOString()}).`,
858
+ errorType: "subscription_expired",
859
+ message: `Agent token-id ${tokenId} subscription has EXPIRED (expired at ${new Date(Number(userExpires) * 1e3).toISOString()}).`,
860
860
  details: { expiredAt: new Date(Number(userExpires) * 1e3).toISOString(), action: "renew" }
861
861
  };
862
862
  }
@@ -885,7 +885,7 @@ async function checkAccess(rpcUrl, tokenId, existingPublicClient) {
885
885
  consoleUrl: agentConsoleUrl(tokenId),
886
886
  howToFix: [
887
887
  `1. Use 'setup_guide' command to generate an OperatorPermit for this wallet`,
888
- `2. Renter (${renter}) can call setOperator(${tokenId}, ${account.address}, <expiry>) on AgentNFA`,
888
+ `2. Subscriber (${renter}) can call setOperator(${tokenId}, ${account.address}, <expiry>) on AgentNFA`,
889
889
  `3. Go to ${agentConsoleUrl(tokenId)} to set operator`,
890
890
  `4. Use the correct RUNNER_PRIVATE_KEY for operator ${operator}`
891
891
  ]
@@ -1217,7 +1217,7 @@ async function ensureAccess(tokenId, rpcUrl, publicClient) {
1217
1217
  "ACCESS_DENIED",
1218
1218
  access.message || `Access denied for token_id ${tokenId.toString()}`,
1219
1219
  access.details,
1220
- "Check operator permissions and rental status"
1220
+ "Check operator permissions and subscription status"
1221
1221
  );
1222
1222
  }
1223
1223
  }
@@ -1330,7 +1330,7 @@ async function getPortfolio(tokenIdRaw, rpcUrl) {
1330
1330
  ]);
1331
1331
  const now = BigInt(Math.floor(Date.now() / 1e3));
1332
1332
  let accessStatus = "Active";
1333
- if (now > userExpires) accessStatus = "Rental Expired";
1333
+ if (now > userExpires) accessStatus = "Subscription Expired";
1334
1334
  else if (now > operatorExpires) accessStatus = "Operator Auth Expired";
1335
1335
  else if (operator.toLowerCase() !== account.address.toLowerCase()) accessStatus = "Operator Mismatch";
1336
1336
  return {
@@ -2102,14 +2102,14 @@ async function buildSetupGuide(listingId, days = 7) {
2102
2102
  walletModel: {
2103
2103
  type: "dual_wallet",
2104
2104
  ownerWallet: {
2105
- purpose: "Rent or mint the agent, own the Agent NFT, authorize the operator, and hold primary assets.",
2106
- useFor: ["renting or minting the agent", "holding ownership", "authorizing the operator"]
2105
+ purpose: "Subscribe or mint the agent, own the Agent NFT, authorize the operator, and hold primary assets.",
2106
+ useFor: ["subscribing to or minting the agent", "holding ownership", "authorizing the operator"]
2107
2107
  },
2108
2108
  operatorWallet: {
2109
2109
  purpose: "AI-only hot wallet used for gas and policy-limited execution.",
2110
2110
  useFor: ["paying gas", "executing policy-limited trades"],
2111
2111
  doNotUseFor: [
2112
- "minting or renting the agent",
2112
+ "minting or subscribing to the agent",
2113
2113
  "holding the Agent NFT",
2114
2114
  "using as your main asset wallet"
2115
2115
  ],
@@ -2117,8 +2117,8 @@ async function buildSetupGuide(listingId, days = 7) {
2117
2117
  }
2118
2118
  },
2119
2119
  criticalWarnings: [
2120
- "Do not use the operator wallet to mint, rent, or hold the Agent NFT.",
2121
- "Use your owner wallet in the browser to complete rental and operator authorization.",
2120
+ "Do not use the operator wallet to mint, subscribe to, or hold the Agent NFT.",
2121
+ "Use your owner wallet in the browser to complete subscription and operator authorization.",
2122
2122
  "Keep only a small BNB balance in the operator wallet for gas."
2123
2123
  ],
2124
2124
  listingSelection: {
@@ -2153,7 +2153,7 @@ function generateOperatorWallet() {
2153
2153
  securityModel: "dual_wallet",
2154
2154
  safeIfLeaked: "This is not the owner wallet. A leak does not grant unrestricted vault withdrawal because owner permissions stay on the owner wallet and PolicyGuard still limits operator actions.",
2155
2155
  doNotUseFor: [
2156
- "minting or renting the agent",
2156
+ "minting or subscribing to the agent",
2157
2157
  "holding the Agent NFT",
2158
2158
  "holding your main assets"
2159
2159
  ],
@@ -2299,7 +2299,7 @@ async function getStatusOverview(tokenIdRaw, rpcUrl) {
2299
2299
  const opBalance = runnerAccount ? await publicClient.getBalance({ address: runnerAccount.address }) : null;
2300
2300
  const access = await checkAccess(rpcUrl, tokenId, publicClient);
2301
2301
  const now = BigInt(Math.floor(Date.now() / 1e3));
2302
- const rentalActive = now <= userExpires;
2302
+ const subscriptionActive = now <= userExpires;
2303
2303
  const operatorAuthorizationActive = now <= operatorExpires;
2304
2304
  const runnerMatchesOperator = runnerAccount ? runnerAccount.address.toLowerCase() === operator.toLowerCase() : null;
2305
2305
  const blockers = [];
@@ -2309,9 +2309,9 @@ async function getStatusOverview(tokenIdRaw, rpcUrl) {
2309
2309
  blockers.push("Operator session key is not loaded.");
2310
2310
  nextActions.push("In OpenClaw, have AI set RUNNER_PRIVATE_KEY for the current session automatically.");
2311
2311
  }
2312
- if (!rentalActive) {
2313
- blockers.push(`Rental expired at ${new Date(Number(userExpires) * 1e3).toISOString()}.`);
2314
- nextActions.push("Use the owner wallet on shll.run to renew the rental before trading.");
2312
+ if (!subscriptionActive) {
2313
+ blockers.push(`Subscription expired at ${new Date(Number(userExpires) * 1e3).toISOString()}.`);
2314
+ nextActions.push("Use the owner wallet on shll.run to renew the subscription before trading.");
2315
2315
  }
2316
2316
  if (!operatorAuthorizationActive) {
2317
2317
  blockers.push(`Operator authorization expired at ${new Date(Number(operatorExpires) * 1e3).toISOString()}.`);
@@ -2335,7 +2335,7 @@ async function getStatusOverview(tokenIdRaw, rpcUrl) {
2335
2335
  if (blockers.length === 0 && bnbBalance > 0n) {
2336
2336
  nextActions.push("Agent is ready. You can ask AI to trade, lend, transfer, or rebalance from this token-id.");
2337
2337
  }
2338
- const readinessStage = !runnerAccount ? "needs_session_key" : !rentalActive ? "needs_rental" : !operatorAuthorizationActive || !runnerMatchesOperator ? "needs_operator_authorization" : opBalance !== null && opBalance < MIN_OPERATOR_GAS_WEI ? "needs_operator_gas" : bnbBalance === 0n ? "ready_but_unfunded" : "ready";
2338
+ const readinessStage = !runnerAccount ? "needs_session_key" : !subscriptionActive ? "needs_subscription" : !operatorAuthorizationActive || !runnerMatchesOperator ? "needs_operator_authorization" : opBalance !== null && opBalance < MIN_OPERATOR_GAS_WEI ? "needs_operator_gas" : bnbBalance === 0n ? "ready_but_unfunded" : "ready";
2339
2339
  let activityStats = { available: false };
2340
2340
  try {
2341
2341
  const res = await fetch(`${DEFAULT_INDEXER}/api/agents/${tokenIdRaw}/summary`, { signal: AbortSignal.timeout(5e3) });
@@ -2362,10 +2362,10 @@ async function getStatusOverview(tokenIdRaw, rpcUrl) {
2362
2362
  nextActions: dedupeStrings(nextActions)
2363
2363
  },
2364
2364
  walletModelReminder: {
2365
- ownerWallet: "Use your owner wallet to mint, rent, renew, and authorize the operator.",
2365
+ ownerWallet: "Use your owner wallet to mint, subscribe, renew, and authorize the operator.",
2366
2366
  operatorWallet: "Use RUNNER_PRIVATE_KEY only as the AI hot wallet for gas and policy-limited execution.",
2367
2367
  doNotUseOperatorWalletFor: [
2368
- "minting or renting the agent",
2368
+ "minting or subscribing to the agent",
2369
2369
  "holding the Agent NFT",
2370
2370
  "storing primary funds"
2371
2371
  ]
@@ -2384,8 +2384,8 @@ async function getStatusOverview(tokenIdRaw, rpcUrl) {
2384
2384
  recommendedMinGasBnb: "0.001"
2385
2385
  },
2386
2386
  access: {
2387
- rentalActive,
2388
- rentalExpiresAt: new Date(Number(userExpires) * 1e3).toISOString(),
2387
+ subscriptionActive,
2388
+ subscriptionExpiresAt: new Date(Number(userExpires) * 1e3).toISOString(),
2389
2389
  operatorAuthorizationActive,
2390
2390
  operatorAuthorizationExpiresAt: new Date(Number(operatorExpires) * 1e3).toISOString(),
2391
2391
  runnerMatchesOperator,
package/dist/index.js CHANGED
@@ -857,8 +857,8 @@ async function checkAccess(rpcUrl, tokenId, existingPublicClient) {
857
857
  if (now > userExpires) {
858
858
  return {
859
859
  blocked: true,
860
- errorType: "rental_expired",
861
- message: `Agent token-id ${tokenId} rental has EXPIRED (expired at ${new Date(Number(userExpires) * 1e3).toISOString()}).`,
860
+ errorType: "subscription_expired",
861
+ message: `Agent token-id ${tokenId} subscription has EXPIRED (expired at ${new Date(Number(userExpires) * 1e3).toISOString()}).`,
862
862
  details: { expiredAt: new Date(Number(userExpires) * 1e3).toISOString(), action: "renew" }
863
863
  };
864
864
  }
@@ -887,7 +887,7 @@ async function checkAccess(rpcUrl, tokenId, existingPublicClient) {
887
887
  consoleUrl: agentConsoleUrl(tokenId),
888
888
  howToFix: [
889
889
  `1. Use 'setup_guide' command to generate an OperatorPermit for this wallet`,
890
- `2. Renter (${renter}) can call setOperator(${tokenId}, ${account.address}, <expiry>) on AgentNFA`,
890
+ `2. Subscriber (${renter}) can call setOperator(${tokenId}, ${account.address}, <expiry>) on AgentNFA`,
891
891
  `3. Go to ${agentConsoleUrl(tokenId)} to set operator`,
892
892
  `4. Use the correct RUNNER_PRIVATE_KEY for operator ${operator}`
893
893
  ]
@@ -1238,7 +1238,7 @@ async function ensureAccess(tokenId, rpcUrl, publicClient) {
1238
1238
  "ACCESS_DENIED",
1239
1239
  access.message || `Access denied for token_id ${tokenId.toString()}`,
1240
1240
  access.details,
1241
- "Check operator permissions and rental status"
1241
+ "Check operator permissions and subscription status"
1242
1242
  );
1243
1243
  }
1244
1244
  }
@@ -1352,7 +1352,7 @@ async function getPortfolio(tokenIdRaw, rpcUrl) {
1352
1352
  ]);
1353
1353
  const now = BigInt(Math.floor(Date.now() / 1e3));
1354
1354
  let accessStatus = "Active";
1355
- if (now > userExpires) accessStatus = "Rental Expired";
1355
+ if (now > userExpires) accessStatus = "Subscription Expired";
1356
1356
  else if (now > operatorExpires) accessStatus = "Operator Auth Expired";
1357
1357
  else if (operator.toLowerCase() !== account.address.toLowerCase()) accessStatus = "Operator Mismatch";
1358
1358
  return {
@@ -2075,14 +2075,14 @@ async function buildSetupGuide(listingId, days = 7) {
2075
2075
  walletModel: {
2076
2076
  type: "dual_wallet",
2077
2077
  ownerWallet: {
2078
- purpose: "Rent or mint the agent, own the Agent NFT, authorize the operator, and hold primary assets.",
2079
- useFor: ["renting or minting the agent", "holding ownership", "authorizing the operator"]
2078
+ purpose: "Subscribe or mint the agent, own the Agent NFT, authorize the operator, and hold primary assets.",
2079
+ useFor: ["subscribing to or minting the agent", "holding ownership", "authorizing the operator"]
2080
2080
  },
2081
2081
  operatorWallet: {
2082
2082
  purpose: "AI-only hot wallet used for gas and policy-limited execution.",
2083
2083
  useFor: ["paying gas", "executing policy-limited trades"],
2084
2084
  doNotUseFor: [
2085
- "minting or renting the agent",
2085
+ "minting or subscribing to the agent",
2086
2086
  "holding the Agent NFT",
2087
2087
  "using as your main asset wallet"
2088
2088
  ],
@@ -2090,8 +2090,8 @@ async function buildSetupGuide(listingId, days = 7) {
2090
2090
  }
2091
2091
  },
2092
2092
  criticalWarnings: [
2093
- "Do not use the operator wallet to mint, rent, or hold the Agent NFT.",
2094
- "Use your owner wallet in the browser to complete rental and operator authorization.",
2093
+ "Do not use the operator wallet to mint, subscribe to, or hold the Agent NFT.",
2094
+ "Use your owner wallet in the browser to complete subscription and operator authorization.",
2095
2095
  "Keep only a small BNB balance in the operator wallet for gas."
2096
2096
  ],
2097
2097
  listingSelection: {
@@ -2126,7 +2126,7 @@ function generateOperatorWallet() {
2126
2126
  securityModel: "dual_wallet",
2127
2127
  safeIfLeaked: "This is not the owner wallet. A leak does not grant unrestricted vault withdrawal because owner permissions stay on the owner wallet and PolicyGuard still limits operator actions.",
2128
2128
  doNotUseFor: [
2129
- "minting or renting the agent",
2129
+ "minting or subscribing to the agent",
2130
2130
  "holding the Agent NFT",
2131
2131
  "holding your main assets"
2132
2132
  ],
@@ -2242,7 +2242,7 @@ async function getStatusOverview(tokenIdRaw, rpcUrl) {
2242
2242
  const opBalance = runnerAccount ? await publicClient.getBalance({ address: runnerAccount.address }) : null;
2243
2243
  const access = await checkAccess(rpcUrl, tokenId, publicClient);
2244
2244
  const now = BigInt(Math.floor(Date.now() / 1e3));
2245
- const rentalActive = now <= userExpires;
2245
+ const subscriptionActive = now <= userExpires;
2246
2246
  const operatorAuthorizationActive = now <= operatorExpires;
2247
2247
  const runnerMatchesOperator = runnerAccount ? runnerAccount.address.toLowerCase() === operator.toLowerCase() : null;
2248
2248
  const blockers = [];
@@ -2252,9 +2252,9 @@ async function getStatusOverview(tokenIdRaw, rpcUrl) {
2252
2252
  blockers.push("Operator session key is not loaded.");
2253
2253
  nextActions.push("In OpenClaw, have AI set RUNNER_PRIVATE_KEY for the current session automatically.");
2254
2254
  }
2255
- if (!rentalActive) {
2256
- blockers.push(`Rental expired at ${new Date(Number(userExpires) * 1e3).toISOString()}.`);
2257
- nextActions.push("Use the owner wallet on shll.run to renew the rental before trading.");
2255
+ if (!subscriptionActive) {
2256
+ blockers.push(`Subscription expired at ${new Date(Number(userExpires) * 1e3).toISOString()}.`);
2257
+ nextActions.push("Use the owner wallet on shll.run to renew the subscription before trading.");
2258
2258
  }
2259
2259
  if (!operatorAuthorizationActive) {
2260
2260
  blockers.push(`Operator authorization expired at ${new Date(Number(operatorExpires) * 1e3).toISOString()}.`);
@@ -2278,7 +2278,7 @@ async function getStatusOverview(tokenIdRaw, rpcUrl) {
2278
2278
  if (blockers.length === 0 && bnbBalance > 0n) {
2279
2279
  nextActions.push("Agent is ready. You can ask AI to trade, lend, transfer, or rebalance from this token-id.");
2280
2280
  }
2281
- const readinessStage = !runnerAccount ? "needs_session_key" : !rentalActive ? "needs_rental" : !operatorAuthorizationActive || !runnerMatchesOperator ? "needs_operator_authorization" : opBalance !== null && opBalance < MIN_OPERATOR_GAS_WEI ? "needs_operator_gas" : bnbBalance === 0n ? "ready_but_unfunded" : "ready";
2281
+ const readinessStage = !runnerAccount ? "needs_session_key" : !subscriptionActive ? "needs_subscription" : !operatorAuthorizationActive || !runnerMatchesOperator ? "needs_operator_authorization" : opBalance !== null && opBalance < MIN_OPERATOR_GAS_WEI ? "needs_operator_gas" : bnbBalance === 0n ? "ready_but_unfunded" : "ready";
2282
2282
  let activityStats = { available: false };
2283
2283
  try {
2284
2284
  const res = await fetch(`${DEFAULT_INDEXER}/api/agents/${tokenIdRaw}/summary`, { signal: AbortSignal.timeout(5e3) });
@@ -2305,10 +2305,10 @@ async function getStatusOverview(tokenIdRaw, rpcUrl) {
2305
2305
  nextActions: dedupeStrings(nextActions)
2306
2306
  },
2307
2307
  walletModelReminder: {
2308
- ownerWallet: "Use your owner wallet to mint, rent, renew, and authorize the operator.",
2308
+ ownerWallet: "Use your owner wallet to mint, subscribe, renew, and authorize the operator.",
2309
2309
  operatorWallet: "Use RUNNER_PRIVATE_KEY only as the AI hot wallet for gas and policy-limited execution.",
2310
2310
  doNotUseOperatorWalletFor: [
2311
- "minting or renting the agent",
2311
+ "minting or subscribing to the agent",
2312
2312
  "holding the Agent NFT",
2313
2313
  "storing primary funds"
2314
2314
  ]
@@ -2327,8 +2327,8 @@ async function getStatusOverview(tokenIdRaw, rpcUrl) {
2327
2327
  recommendedMinGasBnb: "0.001"
2328
2328
  },
2329
2329
  access: {
2330
- rentalActive,
2331
- rentalExpiresAt: new Date(Number(userExpires) * 1e3).toISOString(),
2330
+ subscriptionActive,
2331
+ subscriptionExpiresAt: new Date(Number(userExpires) * 1e3).toISOString(),
2332
2332
  operatorAuthorizationActive,
2333
2333
  operatorAuthorizationExpiresAt: new Date(Number(operatorExpires) * 1e3).toISOString(),
2334
2334
  runnerMatchesOperator,
@@ -2715,7 +2715,7 @@ function registerSetupCommands(program2) {
2715
2715
  process.exit(1);
2716
2716
  }
2717
2717
  });
2718
- const setupCmd = new import_commander7.Command("setup-guide").description("Print dual-wallet setup instructions for a specific template").option("-l, --listing <hex>", "Template listing ID").option("-d, --days <number>", "Number of days to rent", "7");
2718
+ const setupCmd = new import_commander7.Command("setup-guide").description("Print dual-wallet setup instructions for a specific template").option("-l, --listing <hex>", "Template listing ID").option("-d, --days <number>", "Number of days to subscribe", "7");
2719
2719
  setupCmd.action(async (opts) => {
2720
2720
  try {
2721
2721
  const result = await buildSetupGuide(opts.listing, parseInt(opts.days, 10));
@@ -2723,8 +2723,8 @@ function registerSetupCommands(program2) {
2723
2723
  ...result,
2724
2724
  steps: [
2725
2725
  { step: 1, action: `Open ${result.setupUrl}` },
2726
- { step: 2, action: "Use your owner wallet in the browser. Do not use the operator wallet for rental or mint." },
2727
- { step: 3, action: "Confirm the rental or mint transaction in the owner wallet." },
2726
+ { step: 2, action: "Use your owner wallet in the browser. Do not use the operator wallet for subscription or mint." },
2727
+ { step: 3, action: "Confirm the subscription or mint transaction in the owner wallet." },
2728
2728
  { step: 4, action: "Authorize the operator wallet for AI execution." },
2729
2729
  { step: 5, action: "Fund the vault with BNB or trading tokens. Do not use the operator wallet as the vault wallet." },
2730
2730
  { step: 6, action: "Send the token-id back to AI so it can automatically run readiness checks." }
package/dist/index.mjs CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  transferFromVault,
28
28
  unwrapWbnb,
29
29
  wrapBnb
30
- } from "./chunk-IKVUDAK6.mjs";
30
+ } from "./chunk-RUCWJDVB.mjs";
31
31
 
32
32
  // src/index.ts
33
33
  import { Command as Command9 } from "commander";
@@ -359,7 +359,7 @@ function registerSetupCommands(program2) {
359
359
  process.exit(1);
360
360
  }
361
361
  });
362
- const setupCmd = new Command7("setup-guide").description("Print dual-wallet setup instructions for a specific template").option("-l, --listing <hex>", "Template listing ID").option("-d, --days <number>", "Number of days to rent", "7");
362
+ const setupCmd = new Command7("setup-guide").description("Print dual-wallet setup instructions for a specific template").option("-l, --listing <hex>", "Template listing ID").option("-d, --days <number>", "Number of days to subscribe", "7");
363
363
  setupCmd.action(async (opts) => {
364
364
  try {
365
365
  const result = await buildSetupGuide(opts.listing, parseInt(opts.days, 10));
@@ -367,8 +367,8 @@ function registerSetupCommands(program2) {
367
367
  ...result,
368
368
  steps: [
369
369
  { step: 1, action: `Open ${result.setupUrl}` },
370
- { step: 2, action: "Use your owner wallet in the browser. Do not use the operator wallet for rental or mint." },
371
- { step: 3, action: "Confirm the rental or mint transaction in the owner wallet." },
370
+ { step: 2, action: "Use your owner wallet in the browser. Do not use the operator wallet for subscription or mint." },
371
+ { step: 3, action: "Confirm the subscription or mint transaction in the owner wallet." },
372
372
  { step: 4, action: "Authorize the operator wallet for AI execution." },
373
373
  { step: 5, action: "Fund the vault with BNB or trading tokens. Do not use the operator wallet as the vault wallet." },
374
374
  { step: 6, action: "Send the token-id back to AI so it can automatically run readiness checks." }
package/dist/mcp.js CHANGED
@@ -856,8 +856,8 @@ async function checkAccess(rpcUrl, tokenId, existingPublicClient) {
856
856
  if (now > userExpires) {
857
857
  return {
858
858
  blocked: true,
859
- errorType: "rental_expired",
860
- message: `Agent token-id ${tokenId} rental has EXPIRED (expired at ${new Date(Number(userExpires) * 1e3).toISOString()}).`,
859
+ errorType: "subscription_expired",
860
+ message: `Agent token-id ${tokenId} subscription has EXPIRED (expired at ${new Date(Number(userExpires) * 1e3).toISOString()}).`,
861
861
  details: { expiredAt: new Date(Number(userExpires) * 1e3).toISOString(), action: "renew" }
862
862
  };
863
863
  }
@@ -886,7 +886,7 @@ async function checkAccess(rpcUrl, tokenId, existingPublicClient) {
886
886
  consoleUrl: agentConsoleUrl(tokenId),
887
887
  howToFix: [
888
888
  `1. Use 'setup_guide' command to generate an OperatorPermit for this wallet`,
889
- `2. Renter (${renter}) can call setOperator(${tokenId}, ${account.address}, <expiry>) on AgentNFA`,
889
+ `2. Subscriber (${renter}) can call setOperator(${tokenId}, ${account.address}, <expiry>) on AgentNFA`,
890
890
  `3. Go to ${agentConsoleUrl(tokenId)} to set operator`,
891
891
  `4. Use the correct RUNNER_PRIVATE_KEY for operator ${operator}`
892
892
  ]
@@ -1218,7 +1218,7 @@ async function ensureAccess(tokenId, rpcUrl, publicClient) {
1218
1218
  "ACCESS_DENIED",
1219
1219
  access.message || `Access denied for token_id ${tokenId.toString()}`,
1220
1220
  access.details,
1221
- "Check operator permissions and rental status"
1221
+ "Check operator permissions and subscription status"
1222
1222
  );
1223
1223
  }
1224
1224
  }
@@ -1332,7 +1332,7 @@ async function getPortfolio(tokenIdRaw, rpcUrl) {
1332
1332
  ]);
1333
1333
  const now = BigInt(Math.floor(Date.now() / 1e3));
1334
1334
  let accessStatus = "Active";
1335
- if (now > userExpires) accessStatus = "Rental Expired";
1335
+ if (now > userExpires) accessStatus = "Subscription Expired";
1336
1336
  else if (now > operatorExpires) accessStatus = "Operator Auth Expired";
1337
1337
  else if (operator.toLowerCase() !== account.address.toLowerCase()) accessStatus = "Operator Mismatch";
1338
1338
  return {
@@ -2106,14 +2106,14 @@ async function buildSetupGuide(listingId, days = 7) {
2106
2106
  walletModel: {
2107
2107
  type: "dual_wallet",
2108
2108
  ownerWallet: {
2109
- purpose: "Rent or mint the agent, own the Agent NFT, authorize the operator, and hold primary assets.",
2110
- useFor: ["renting or minting the agent", "holding ownership", "authorizing the operator"]
2109
+ purpose: "Subscribe or mint the agent, own the Agent NFT, authorize the operator, and hold primary assets.",
2110
+ useFor: ["subscribing to or minting the agent", "holding ownership", "authorizing the operator"]
2111
2111
  },
2112
2112
  operatorWallet: {
2113
2113
  purpose: "AI-only hot wallet used for gas and policy-limited execution.",
2114
2114
  useFor: ["paying gas", "executing policy-limited trades"],
2115
2115
  doNotUseFor: [
2116
- "minting or renting the agent",
2116
+ "minting or subscribing to the agent",
2117
2117
  "holding the Agent NFT",
2118
2118
  "using as your main asset wallet"
2119
2119
  ],
@@ -2121,8 +2121,8 @@ async function buildSetupGuide(listingId, days = 7) {
2121
2121
  }
2122
2122
  },
2123
2123
  criticalWarnings: [
2124
- "Do not use the operator wallet to mint, rent, or hold the Agent NFT.",
2125
- "Use your owner wallet in the browser to complete rental and operator authorization.",
2124
+ "Do not use the operator wallet to mint, subscribe to, or hold the Agent NFT.",
2125
+ "Use your owner wallet in the browser to complete subscription and operator authorization.",
2126
2126
  "Keep only a small BNB balance in the operator wallet for gas."
2127
2127
  ],
2128
2128
  listingSelection: {
@@ -2157,7 +2157,7 @@ function generateOperatorWallet() {
2157
2157
  securityModel: "dual_wallet",
2158
2158
  safeIfLeaked: "This is not the owner wallet. A leak does not grant unrestricted vault withdrawal because owner permissions stay on the owner wallet and PolicyGuard still limits operator actions.",
2159
2159
  doNotUseFor: [
2160
- "minting or renting the agent",
2160
+ "minting or subscribing to the agent",
2161
2161
  "holding the Agent NFT",
2162
2162
  "holding your main assets"
2163
2163
  ],
@@ -2303,7 +2303,7 @@ async function getStatusOverview(tokenIdRaw, rpcUrl) {
2303
2303
  const opBalance = runnerAccount ? await publicClient.getBalance({ address: runnerAccount.address }) : null;
2304
2304
  const access = await checkAccess(rpcUrl, tokenId, publicClient);
2305
2305
  const now = BigInt(Math.floor(Date.now() / 1e3));
2306
- const rentalActive = now <= userExpires;
2306
+ const subscriptionActive = now <= userExpires;
2307
2307
  const operatorAuthorizationActive = now <= operatorExpires;
2308
2308
  const runnerMatchesOperator = runnerAccount ? runnerAccount.address.toLowerCase() === operator.toLowerCase() : null;
2309
2309
  const blockers = [];
@@ -2313,9 +2313,9 @@ async function getStatusOverview(tokenIdRaw, rpcUrl) {
2313
2313
  blockers.push("Operator session key is not loaded.");
2314
2314
  nextActions.push("In OpenClaw, have AI set RUNNER_PRIVATE_KEY for the current session automatically.");
2315
2315
  }
2316
- if (!rentalActive) {
2317
- blockers.push(`Rental expired at ${new Date(Number(userExpires) * 1e3).toISOString()}.`);
2318
- nextActions.push("Use the owner wallet on shll.run to renew the rental before trading.");
2316
+ if (!subscriptionActive) {
2317
+ blockers.push(`Subscription expired at ${new Date(Number(userExpires) * 1e3).toISOString()}.`);
2318
+ nextActions.push("Use the owner wallet on shll.run to renew the subscription before trading.");
2319
2319
  }
2320
2320
  if (!operatorAuthorizationActive) {
2321
2321
  blockers.push(`Operator authorization expired at ${new Date(Number(operatorExpires) * 1e3).toISOString()}.`);
@@ -2339,7 +2339,7 @@ async function getStatusOverview(tokenIdRaw, rpcUrl) {
2339
2339
  if (blockers.length === 0 && bnbBalance > 0n) {
2340
2340
  nextActions.push("Agent is ready. You can ask AI to trade, lend, transfer, or rebalance from this token-id.");
2341
2341
  }
2342
- const readinessStage = !runnerAccount ? "needs_session_key" : !rentalActive ? "needs_rental" : !operatorAuthorizationActive || !runnerMatchesOperator ? "needs_operator_authorization" : opBalance !== null && opBalance < MIN_OPERATOR_GAS_WEI ? "needs_operator_gas" : bnbBalance === 0n ? "ready_but_unfunded" : "ready";
2342
+ const readinessStage = !runnerAccount ? "needs_session_key" : !subscriptionActive ? "needs_subscription" : !operatorAuthorizationActive || !runnerMatchesOperator ? "needs_operator_authorization" : opBalance !== null && opBalance < MIN_OPERATOR_GAS_WEI ? "needs_operator_gas" : bnbBalance === 0n ? "ready_but_unfunded" : "ready";
2343
2343
  let activityStats = { available: false };
2344
2344
  try {
2345
2345
  const res = await fetch(`${DEFAULT_INDEXER}/api/agents/${tokenIdRaw}/summary`, { signal: AbortSignal.timeout(5e3) });
@@ -2366,10 +2366,10 @@ async function getStatusOverview(tokenIdRaw, rpcUrl) {
2366
2366
  nextActions: dedupeStrings(nextActions)
2367
2367
  },
2368
2368
  walletModelReminder: {
2369
- ownerWallet: "Use your owner wallet to mint, rent, renew, and authorize the operator.",
2369
+ ownerWallet: "Use your owner wallet to mint, subscribe, renew, and authorize the operator.",
2370
2370
  operatorWallet: "Use RUNNER_PRIVATE_KEY only as the AI hot wallet for gas and policy-limited execution.",
2371
2371
  doNotUseOperatorWalletFor: [
2372
- "minting or renting the agent",
2372
+ "minting or subscribing to the agent",
2373
2373
  "holding the Agent NFT",
2374
2374
  "storing primary funds"
2375
2375
  ]
@@ -2388,8 +2388,8 @@ async function getStatusOverview(tokenIdRaw, rpcUrl) {
2388
2388
  recommendedMinGasBnb: "0.001"
2389
2389
  },
2390
2390
  access: {
2391
- rentalActive,
2392
- rentalExpiresAt: new Date(Number(userExpires) * 1e3).toISOString(),
2391
+ subscriptionActive,
2392
+ subscriptionExpiresAt: new Date(Number(userExpires) * 1e3).toISOString(),
2393
2393
  operatorAuthorizationActive,
2394
2394
  operatorAuthorizationExpiresAt: new Date(Number(operatorExpires) * 1e3).toISOString(),
2395
2395
  runnerMatchesOperator,
@@ -2836,7 +2836,7 @@ function asToolResult7(payload) {
2836
2836
  function registerSetupTools(server2) {
2837
2837
  server2.tool(
2838
2838
  "listings",
2839
- "List all available agent templates for rent",
2839
+ "List all available agent templates for subscription",
2840
2840
  {},
2841
2841
  async () => {
2842
2842
  try {
@@ -2854,10 +2854,10 @@ function registerSetupTools(server2) {
2854
2854
  );
2855
2855
  server2.tool(
2856
2856
  "setup_guide",
2857
- "Generate step-by-step dual-wallet onboarding instructions. Owner wallet completes rental or mint; operator wallet is AI-only.",
2857
+ "Generate step-by-step dual-wallet onboarding instructions. Owner wallet completes subscription or mint; operator wallet is AI-only.",
2858
2858
  {
2859
2859
  listing_id: CommonSchemas.listingId.optional(),
2860
- days: import_zod7.z.number().int().min(7).default(7).describe("Number of days to rent")
2860
+ days: import_zod7.z.number().int().min(7).default(7).describe("Number of days to subscribe")
2861
2861
  },
2862
2862
  async ({ listing_id, days }) => {
2863
2863
  try {
@@ -2867,7 +2867,7 @@ function registerSetupTools(server2) {
2867
2867
  steps: [
2868
2868
  { step: 1, title: "Open SHLL Setup Page", action: `Open ${result.setupUrl}` },
2869
2869
  { step: 2, title: "Use Owner Wallet", action: "Use your main owner wallet in the browser. Do not use the operator wallet for this step." },
2870
- { step: 3, title: "Rent or Mint Agent", action: "Confirm the rental or mint transaction in the owner wallet." },
2870
+ { step: 3, title: "Subscribe or Mint Agent", action: "Confirm the subscription or mint transaction in the owner wallet." },
2871
2871
  { step: 4, title: "Authorize Operator", action: "Authorize the operator wallet for AI execution.", note: `Operator: ${result.operatorAddress}` },
2872
2872
  { step: 5, title: "Fund Vault", action: "Deposit BNB or tokens into the vault for trading. Do not store primary assets in the operator wallet." },
2873
2873
  { step: 6, title: "Return Token ID", action: "Send the token-id back to AI so it can automatically check operator gas, vault balance, and policy readiness." }
package/dist/mcp.mjs CHANGED
@@ -26,7 +26,7 @@ import {
26
26
  transferFromVault,
27
27
  unwrapWbnb,
28
28
  wrapBnb
29
- } from "./chunk-IKVUDAK6.mjs";
29
+ } from "./chunk-RUCWJDVB.mjs";
30
30
 
31
31
  // src/mcp.ts
32
32
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
@@ -389,7 +389,7 @@ function asToolResult7(payload) {
389
389
  function registerSetupTools(server2) {
390
390
  server2.tool(
391
391
  "listings",
392
- "List all available agent templates for rent",
392
+ "List all available agent templates for subscription",
393
393
  {},
394
394
  async () => {
395
395
  try {
@@ -407,10 +407,10 @@ function registerSetupTools(server2) {
407
407
  );
408
408
  server2.tool(
409
409
  "setup_guide",
410
- "Generate step-by-step dual-wallet onboarding instructions. Owner wallet completes rental or mint; operator wallet is AI-only.",
410
+ "Generate step-by-step dual-wallet onboarding instructions. Owner wallet completes subscription or mint; operator wallet is AI-only.",
411
411
  {
412
412
  listing_id: CommonSchemas.listingId.optional(),
413
- days: z6.number().int().min(7).default(7).describe("Number of days to rent")
413
+ days: z6.number().int().min(7).default(7).describe("Number of days to subscribe")
414
414
  },
415
415
  async ({ listing_id, days }) => {
416
416
  try {
@@ -420,7 +420,7 @@ function registerSetupTools(server2) {
420
420
  steps: [
421
421
  { step: 1, title: "Open SHLL Setup Page", action: `Open ${result.setupUrl}` },
422
422
  { step: 2, title: "Use Owner Wallet", action: "Use your main owner wallet in the browser. Do not use the operator wallet for this step." },
423
- { step: 3, title: "Rent or Mint Agent", action: "Confirm the rental or mint transaction in the owner wallet." },
423
+ { step: 3, title: "Subscribe or Mint Agent", action: "Confirm the subscription or mint transaction in the owner wallet." },
424
424
  { step: 4, title: "Authorize Operator", action: "Authorize the operator wallet for AI execution.", note: `Operator: ${result.operatorAddress}` },
425
425
  { step: 5, title: "Fund Vault", action: "Deposit BNB or tokens into the vault for trading. Do not store primary assets in the operator wallet." },
426
426
  { step: 6, title: "Return Token ID", action: "Send the token-id back to AI so it can automatically check operator gas, vault balance, and policy readiness." }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shll-skills",
3
- "version": "6.0.4",
3
+ "version": "6.0.5",
4
4
  "description": "SHLL DeFi Agent - CLI + MCP Server for BSC",
5
5
  "main": "dist/index.js",
6
6
  "bin": {