traderclaw-cli 1.0.58 → 1.0.60
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.
|
@@ -768,7 +768,7 @@ function traderCronPrescriptiveJobs(agentId) {
|
|
|
768
768
|
schedule: "30 */2 * * *",
|
|
769
769
|
agentId,
|
|
770
770
|
message:
|
|
771
|
-
"CRON_JOB: portfolio_risk_audit —
|
|
771
|
+
"CRON_JOB: portfolio_risk_audit\n\nStep 1: Call solana_capital_status to get wallet balance and portfolio value.\n\nStep 2: Call solana_positions to get all open positions with entry prices and sizes.\n\nStep 3: For each open position, call solana_token_snapshot to get current price, 24h volume, and market cap.\n\nStep 4: Run concentration check — flag WARNING if any single position exceeds 30 percent of total portfolio value, CRITICAL if above 50 percent.\n\nStep 5: Run exposure check — flag WARNING if total exposure exceeds 50 percent of wallet balance, CRITICAL if above 75 percent.\n\nStep 6: Run drawdown check — CRITICAL if portfolio drawdown exceeds 25 percent from peak capital.\n\nStep 7: Calculate portfolio heat (sum of all position risk scores). Flag WARNING above 50 percent, CRITICAL above 75 percent.\n\nStep 8: Run liquidity check — WARNING if any position exceeds 2 percent of its pool depth.\n\nStep 9: Check solana_killswitch_status.\n\nStep 10: Write risk report via solana_memory_write with tag 'risk_audit'.\n\nFORMATTING RULES:\n- Every token reference MUST use SYMBOL (full_CA) format.\n- Do not execute trades. Do not ask questions.",
|
|
772
772
|
enabled: true,
|
|
773
773
|
},
|
|
774
774
|
{
|
|
@@ -776,15 +776,15 @@ function traderCronPrescriptiveJobs(agentId) {
|
|
|
776
776
|
schedule: "0 */3 * * *",
|
|
777
777
|
agentId,
|
|
778
778
|
message:
|
|
779
|
-
"CRON_JOB: source_reputation_recalc
|
|
779
|
+
"CRON_JOB: source_reputation_recalc\n\nStep 1: Call solana_alpha_sources to get per-source performance stats (signal count, conversion rate, avg score).\n\nStep 2: Call solana_alpha_history to get recent signal history with scores and source identifiers.\n\nStep 3: Call solana_trades to get recent trade outcomes. Cross-reference each trade back to its originating signal source.\n\nStep 4: For each source, calculate: win rate (trades that hit TP vs SL), average PnL per trade, signal-to-trade conversion rate.\n\nStep 5: Assign tier rankings:\n- TIER-1 (LOCK): Win rate above 60% AND 5+ trades AND positive avg PnL\n- TIER-2 (CONDITIONAL): Win rate 30-60% OR fewer than 5 trades\n- TIER-3 (BLACKLIST): Win rate below 30% with 5+ trades\n\nStep 6: Write scorecard to memory using solana_memory_write with tag 'source_reputation'.\n\nFORMATTING RULES:\n- Every token reference MUST use SYMBOL (full_CA) format.\n- Do not execute trades. Do not ask questions.",
|
|
780
780
|
enabled: true,
|
|
781
781
|
},
|
|
782
782
|
{
|
|
783
|
-
id: "meta-rotation
|
|
783
|
+
id: "meta-rotation",
|
|
784
784
|
schedule: "30 */3 * * *",
|
|
785
785
|
agentId,
|
|
786
786
|
message:
|
|
787
|
-
"CRON_JOB: meta_rotation_analysis
|
|
787
|
+
"CRON_JOB: meta_rotation_analysis\n\nStep 0: Call x_search_tweets with queries: 'solana memecoin', 'pump fun gem', 'sol alpha'. Note which token names and narratives appear most frequently in the last 3 hours. Use this social signal to validate or challenge the on-chain data in the following steps.\n\nStep 1: Call solana_scan_launches to get recent token launches (last 3-6 hours).\n\nStep 2: Categorize each token by narrative cluster: AI/Agents, Animal Memes, Political, Celebrity/IP, DeFi, Gaming, Culture/Humor, Other.\n\nStep 3: For each cluster, aggregate: token count, total volume, average market cap.\n\nStep 4: Call solana_memory_search for 'meta_rotation' to compare with prior scan.\n\nStep 5: Classify each narrative: GAINING, SATURATED, COOLING, DORMANT.\n\nStep 6: Write rotation report via solana_memory_write with tag 'meta_rotation'.\n\nFORMATTING RULES:\n- Every token reference MUST use SYMBOL (full_CA) format.\n- Do not execute trades. Do not ask questions.",
|
|
788
788
|
enabled: true,
|
|
789
789
|
},
|
|
790
790
|
{
|
|
@@ -800,7 +800,7 @@ function traderCronPrescriptiveJobs(agentId) {
|
|
|
800
800
|
schedule: "15 * * * *",
|
|
801
801
|
agentId,
|
|
802
802
|
message:
|
|
803
|
-
"CRON_JOB: subscription_cleanup
|
|
803
|
+
"CRON_JOB: subscription_cleanup\n\nStep 1: Call solana_positions to get all open positions and extract their contract addresses.\n\nStep 2: Call solana_bitquery_subscriptions to list all active Bitquery subscriptions. If this call returns an AUTH_SCOPE_MISSING error, log the error to memory and stop gracefully — do not retry or error out.\n\nStep 3: For each active subscription, check if the associated token CA still has an open position. Build two lists: 'matched' (has position) and 'orphaned' (no position).\n\nStep 4: Unsubscribe orphans via solana_bitquery_unsubscribe.\n\nStep 5: Reopen subscriptions nearing 24h expiry via solana_bitquery_subscription_reopen.\n\nStep 6: Write summary via solana_memory_write with tag 'subscription_cleanup'.\n\nFORMATTING RULES:\n- Every token reference MUST use SYMBOL (full_CA) format.\n- Do not execute trades. Do not ask questions.",
|
|
804
804
|
enabled: true,
|
|
805
805
|
},
|
|
806
806
|
{
|
package/bin/openclaw-trader.mjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { createInterface } from "readline";
|
|
4
4
|
import { readFileSync, writeFileSync, mkdirSync, appendFileSync, existsSync } from "fs";
|
|
5
5
|
import { dirname, join } from "path";
|
|
6
|
-
import { fileURLToPath } from "url";
|
|
6
|
+
import { fileURLToPath, pathToFileURL } from "url";
|
|
7
7
|
import { homedir } from "os";
|
|
8
8
|
import { randomUUID, createPrivateKey, sign as cryptoSign } from "crypto";
|
|
9
9
|
import { execFile, execSync } from "child_process";
|
|
@@ -665,6 +665,7 @@ async function cmdSetup(args) {
|
|
|
665
665
|
let writeGatewayEnvFlag = false;
|
|
666
666
|
let noEnsureGatewayPersistent = false;
|
|
667
667
|
let signupRecoverySecret = undefined;
|
|
668
|
+
let forwardTelegramRecipientArg = "";
|
|
668
669
|
|
|
669
670
|
for (let i = 0; i < args.length; i++) {
|
|
670
671
|
if ((args[i] === "--api-key" || args[i] === "-k") && args[i + 1]) {
|
|
@@ -703,6 +704,14 @@ async function cmdSetup(args) {
|
|
|
703
704
|
if (args[i] === "--no-ensure-gateway-persistent") {
|
|
704
705
|
noEnsureGatewayPersistent = true;
|
|
705
706
|
}
|
|
707
|
+
if (
|
|
708
|
+
(args[i] === "--telegram-recipient" ||
|
|
709
|
+
args[i] === "--forward-telegram-chat-id" ||
|
|
710
|
+
args[i] === "--telegram-chat-id") &&
|
|
711
|
+
args[i + 1]
|
|
712
|
+
) {
|
|
713
|
+
forwardTelegramRecipientArg = args[++i];
|
|
714
|
+
}
|
|
706
715
|
}
|
|
707
716
|
const runtimeWalletPrivateKey = getRuntimeWalletPrivateKey(walletPrivateKey);
|
|
708
717
|
|
|
@@ -970,6 +979,49 @@ async function cmdSetup(args) {
|
|
|
970
979
|
}
|
|
971
980
|
}
|
|
972
981
|
|
|
982
|
+
let forwardTelegramRecipient = forwardTelegramRecipientArg.trim();
|
|
983
|
+
print("\nTelegram delivery (optional)...\n");
|
|
984
|
+
printInfo(" Enter your Telegram @username or numeric chat id so agent replies can be routed to you.");
|
|
985
|
+
printInfo(
|
|
986
|
+
" Usernames resolve when plugin config telegramBotToken is set, or TELEGRAM_BOT_TOKEN / OPENCLAW_TELEGRAM_BOT_TOKEN is set for this prompt.",
|
|
987
|
+
);
|
|
988
|
+
printInfo(" Private chats: message your bot once first.\n");
|
|
989
|
+
if (!forwardTelegramRecipient) {
|
|
990
|
+
forwardTelegramRecipient = await prompt("Telegram @username or chat id (optional, Enter to skip)", "");
|
|
991
|
+
}
|
|
992
|
+
forwardTelegramRecipient = forwardTelegramRecipient.trim();
|
|
993
|
+
|
|
994
|
+
if (forwardTelegramRecipient) {
|
|
995
|
+
const botToken = String(
|
|
996
|
+
prevPlugin?.telegramBotToken ||
|
|
997
|
+
process.env.TELEGRAM_BOT_TOKEN ||
|
|
998
|
+
process.env.OPENCLAW_TELEGRAM_BOT_TOKEN ||
|
|
999
|
+
"",
|
|
1000
|
+
).trim();
|
|
1001
|
+
try {
|
|
1002
|
+
const { looksLikeTelegramChatId, resolveTelegramRecipientToChatId } = await import(
|
|
1003
|
+
pathToFileURL(join(PLUGIN_ROOT, "dist", "src", "telegram-resolve.js")).href,
|
|
1004
|
+
);
|
|
1005
|
+
if (looksLikeTelegramChatId(forwardTelegramRecipient)) {
|
|
1006
|
+
pluginConfig.forwardTelegramRecipient = forwardTelegramRecipient;
|
|
1007
|
+
printSuccess(` Saved Telegram chat id`);
|
|
1008
|
+
} else if (botToken) {
|
|
1009
|
+
const id = await resolveTelegramRecipientToChatId({ botToken, raw: forwardTelegramRecipient });
|
|
1010
|
+
pluginConfig.forwardTelegramRecipient = id;
|
|
1011
|
+
printSuccess(` Resolved @${forwardTelegramRecipient.replace(/^@/, "")} → chat id ${id}`);
|
|
1012
|
+
} else {
|
|
1013
|
+
pluginConfig.forwardTelegramRecipient = forwardTelegramRecipient;
|
|
1014
|
+
printInfo(
|
|
1015
|
+
" Saved as-is; set plugin telegramBotToken or gateway TELEGRAM_BOT_TOKEN to resolve @username on first run.",
|
|
1016
|
+
);
|
|
1017
|
+
}
|
|
1018
|
+
} catch (err) {
|
|
1019
|
+
printWarn(` Telegram resolve failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1020
|
+
printInfo(" Saving your username anyway — fix token or use numeric chat id.");
|
|
1021
|
+
pluginConfig.forwardTelegramRecipient = forwardTelegramRecipient;
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
|
|
973
1025
|
print("\nWriting configuration...\n");
|
|
974
1026
|
|
|
975
1027
|
const existingConfig = readConfig();
|
|
@@ -1178,6 +1230,7 @@ async function cmdSetup(args) {
|
|
|
1178
1230
|
Wallet PrivKey:${lastSeenWalletPrivateKey ? (createdNewWallet || showWalletPrivateKey ? " " + lastSeenWalletPrivateKey : " " + maskKey(lastSeenWalletPrivateKey)) : " not saved"}
|
|
1179
1231
|
Gateway URL: ${gatewayBaseUrl || "not set"}
|
|
1180
1232
|
Gateway Token: ${gatewayToken ? maskKey(gatewayToken) : "not set"}
|
|
1233
|
+
Telegram fwd: ${pluginConfig.forwardTelegramRecipient || "(not set)"}
|
|
1181
1234
|
API Key: ${showApiKey ? apiKey : maskKey(apiKey)}
|
|
1182
1235
|
Session: Active (tier: ${sessionTokens.session?.tier || "?"})
|
|
1183
1236
|
Config: ${CONFIG_FILE}
|
|
@@ -3154,6 +3207,7 @@ Setup options:
|
|
|
3154
3207
|
--wallet-private-key Optional base58 private key for wallet proof flow (runtime only, never saved)
|
|
3155
3208
|
--gateway-base-url, -g Gateway public HTTPS URL for orchestrator callbacks
|
|
3156
3209
|
--gateway-token, -t Gateway bearer token (defaults to API key)
|
|
3210
|
+
--telegram-recipient Telegram @username or chat id (aliases: --forward-telegram-chat-id, --telegram-chat-id)
|
|
3157
3211
|
--skip-gateway-registration Skip gateway URL registration with orchestrator
|
|
3158
3212
|
--show-api-key Extra hint after signup (full key is always shown once; confirm with API_KEY_STORED)
|
|
3159
3213
|
--show-wallet-private-key Reveal full wallet private key in setup output
|
|
@@ -3186,6 +3240,7 @@ Examples:
|
|
|
3186
3240
|
traderclaw setup --signup --user-id my_agent_001
|
|
3187
3241
|
traderclaw setup --api-key oc_xxx --url https://api.traderclaw.ai
|
|
3188
3242
|
traderclaw setup --gateway-base-url https://gateway.myhost.ts.net
|
|
3243
|
+
traderclaw setup --telegram-recipient @myusername
|
|
3189
3244
|
traderclaw login
|
|
3190
3245
|
traderclaw login --force-reauth --wallet-private-key <base58_key>
|
|
3191
3246
|
traderclaw logout
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "traderclaw-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.60",
|
|
4
4
|
"description": "Global TraderClaw CLI (install --wizard, setup, precheck). Installs solana-traderclaw as a dependency for OpenClaw plugin files.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"node": ">=22"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"solana-traderclaw": "^1.0.
|
|
20
|
+
"solana-traderclaw": "^1.0.60"
|
|
21
21
|
},
|
|
22
22
|
"keywords": [
|
|
23
23
|
"traderclaw",
|