solana-traderclaw 1.0.68 → 1.0.70
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/dist/index.js
CHANGED
|
@@ -1236,6 +1236,33 @@ var solanaTraderPlugin = {
|
|
|
1236
1236
|
} catch {
|
|
1237
1237
|
}
|
|
1238
1238
|
};
|
|
1239
|
+
const bridgeToNativeMemory = (aid, notes, tags, tokenAddress, outcome) => {
|
|
1240
|
+
try {
|
|
1241
|
+
ensureDir(memoryDir);
|
|
1242
|
+
const now = /* @__PURE__ */ new Date();
|
|
1243
|
+
const logPath = getDailyLogPath(now);
|
|
1244
|
+
const timeStr = now.toISOString().slice(11, 19);
|
|
1245
|
+
const tagStr = tags && tags.length > 0 ? ` [${tags.join(", ")}]` : "";
|
|
1246
|
+
const tokenStr = tokenAddress ? ` (token: ${tokenAddress.slice(0, 8)}\u2026)` : "";
|
|
1247
|
+
const outcomeStr = outcome ? ` \u2192 ${outcome}` : "";
|
|
1248
|
+
const entry = `
|
|
1249
|
+
### ${timeStr} \u2014 ${aid} [memory_write]${tagStr}${tokenStr}${outcomeStr}
|
|
1250
|
+
|
|
1251
|
+
${notes}
|
|
1252
|
+
`;
|
|
1253
|
+
if (!fs.existsSync(logPath)) {
|
|
1254
|
+
const dateStr = now.toISOString().slice(0, 10);
|
|
1255
|
+
const header = `# Daily Log \u2014 ${dateStr}
|
|
1256
|
+
|
|
1257
|
+
> Auto-generated by solana_daily_log. OpenClaw loads today + yesterday into context automatically.
|
|
1258
|
+
`;
|
|
1259
|
+
fs.writeFileSync(logPath, header + entry, "utf-8");
|
|
1260
|
+
} else {
|
|
1261
|
+
fs.appendFileSync(logPath, entry, "utf-8");
|
|
1262
|
+
}
|
|
1263
|
+
} catch {
|
|
1264
|
+
}
|
|
1265
|
+
};
|
|
1239
1266
|
const agentId = config.agentId || "main";
|
|
1240
1267
|
const sanitizeAgentId = (id) => {
|
|
1241
1268
|
const clean = id.replace(/[^a-zA-Z0-9_-]/g, "").slice(0, 64);
|
|
@@ -1602,16 +1629,23 @@ var solanaTraderPlugin = {
|
|
|
1602
1629
|
})),
|
|
1603
1630
|
strategyVersion: Type.Optional(Type.String({ description: "Strategy version at time of writing (e.g., 'v1.3.0')" }))
|
|
1604
1631
|
}),
|
|
1605
|
-
execute: wrapExecute(
|
|
1606
|
-
"
|
|
1607
|
-
async (_id, params) => post("/api/memory/write", {
|
|
1632
|
+
execute: wrapExecute("solana_memory_write", async (_id, params) => {
|
|
1633
|
+
const result = await post("/api/memory/write", {
|
|
1608
1634
|
notes: params.notes,
|
|
1609
1635
|
tags: params.tags,
|
|
1610
1636
|
tokenAddress: params.tokenAddress,
|
|
1611
1637
|
outcome: params.outcome,
|
|
1612
1638
|
strategyVersion: params.strategyVersion
|
|
1613
|
-
})
|
|
1614
|
-
|
|
1639
|
+
});
|
|
1640
|
+
bridgeToNativeMemory(
|
|
1641
|
+
agentId,
|
|
1642
|
+
String(params.notes),
|
|
1643
|
+
params.tags,
|
|
1644
|
+
params.tokenAddress,
|
|
1645
|
+
params.outcome
|
|
1646
|
+
);
|
|
1647
|
+
return result;
|
|
1648
|
+
})
|
|
1615
1649
|
});
|
|
1616
1650
|
api.registerTool({
|
|
1617
1651
|
name: "solana_memory_search",
|
|
@@ -3991,6 +4025,64 @@ Context compaction triggered. STATE.md synced from last persisted state. Decisio
|
|
|
3991
4025
|
}
|
|
3992
4026
|
}
|
|
3993
4027
|
});
|
|
4028
|
+
if (typeof api.registerContextEngine === "function") {
|
|
4029
|
+
const contextEngineState = {
|
|
4030
|
+
lastAssembledAt: 0,
|
|
4031
|
+
cachedSummary: null
|
|
4032
|
+
};
|
|
4033
|
+
api.registerContextEngine({
|
|
4034
|
+
id: "solana-trader-v1-context",
|
|
4035
|
+
name: "TraderClaw V1 Trading Context",
|
|
4036
|
+
async assemble(context) {
|
|
4037
|
+
const assembleAgentId = sanitizeAgentId(context.agentId || agentId);
|
|
4038
|
+
const now = Date.now();
|
|
4039
|
+
const CACHE_TTL_MS = 3e4;
|
|
4040
|
+
if (contextEngineState.cachedSummary && now - contextEngineState.lastAssembledAt < CACHE_TTL_MS) {
|
|
4041
|
+
return { systemPromptAddition: contextEngineState.cachedSummary };
|
|
4042
|
+
}
|
|
4043
|
+
const lines = ["[TraderClaw Trading Context]"];
|
|
4044
|
+
try {
|
|
4045
|
+
const stateFile = path.join(stateDir, `${assembleAgentId}.json`);
|
|
4046
|
+
const stateData = readJsonFile(stateFile);
|
|
4047
|
+
if (stateData?.state) {
|
|
4048
|
+
lines.push(generateStateMd(stateData.state));
|
|
4049
|
+
}
|
|
4050
|
+
} catch {
|
|
4051
|
+
}
|
|
4052
|
+
try {
|
|
4053
|
+
const logFile = path.join(logsDir, assembleAgentId, "decisions.jsonl");
|
|
4054
|
+
const recentDecisions = readJsonlFile(logFile, 3);
|
|
4055
|
+
if (recentDecisions.length > 0) {
|
|
4056
|
+
lines.push(`Last ${recentDecisions.length} decisions:`);
|
|
4057
|
+
for (const d of recentDecisions) {
|
|
4058
|
+
const dec = d;
|
|
4059
|
+
lines.push(` - ${dec.type || "unknown"}: ${dec.token || dec.tokenAddress || "\u2014"} @ ${dec.ts || "?"}`);
|
|
4060
|
+
}
|
|
4061
|
+
}
|
|
4062
|
+
} catch {
|
|
4063
|
+
}
|
|
4064
|
+
try {
|
|
4065
|
+
const entitlementCache = readJsonFile(path.join(stateDir, "entitlement-cache.json"));
|
|
4066
|
+
if (entitlementCache) {
|
|
4067
|
+
const parts = [];
|
|
4068
|
+
if (entitlementCache.tier) parts.push(`tier=${entitlementCache.tier}`);
|
|
4069
|
+
if (entitlementCache.maxPositions) parts.push(`maxPos=${entitlementCache.maxPositions}`);
|
|
4070
|
+
if (entitlementCache.maxPositionSizeSol) parts.push(`maxSize=${entitlementCache.maxPositionSizeSol}SOL`);
|
|
4071
|
+
if (parts.length > 0) lines.push(`Entitlements: ${parts.join(", ")}`);
|
|
4072
|
+
}
|
|
4073
|
+
} catch {
|
|
4074
|
+
}
|
|
4075
|
+
const summary = lines.length > 1 ? lines.join("\n") : null;
|
|
4076
|
+
contextEngineState.cachedSummary = summary;
|
|
4077
|
+
contextEngineState.lastAssembledAt = now;
|
|
4078
|
+
return summary ? { systemPromptAddition: summary } : {};
|
|
4079
|
+
},
|
|
4080
|
+
async compact(_context) {
|
|
4081
|
+
return {};
|
|
4082
|
+
}
|
|
4083
|
+
});
|
|
4084
|
+
api.logger.info("[solana-trader] Context engine registered: solana-trader-v1-context");
|
|
4085
|
+
}
|
|
3994
4086
|
registerXTools(api, Type, config.xConfig, config.agentId || "cto", "[solana-trader]", { enableWriteTools: config.beta?.xPosting ?? false });
|
|
3995
4087
|
registerWebFetchTool(api, Type, "[solana-trader]");
|
|
3996
4088
|
const xWriteEnabled = config.beta?.xPosting ?? false;
|
package/openclaw.plugin.json
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"id": "solana-trader",
|
|
3
3
|
"name": "Solana Trader",
|
|
4
4
|
"description": "Public edition V1-Upgraded — Solana trading agent with X/Twitter social intel (read-only, no posting), standardized tool envelopes, intelligence lab, prompt injection scrubbing, and split skill architecture. Full V1 trading capabilities plus 17 new intelligence tools.",
|
|
5
|
+
"enabledByDefault": true,
|
|
5
6
|
"skills": ["skills/solana-trader"],
|
|
6
7
|
"configSchema": {
|
|
7
8
|
"type": "object",
|
|
@@ -38,14 +39,15 @@
|
|
|
38
39
|
},
|
|
39
40
|
"walletPrivateKey": {
|
|
40
41
|
"type": "string",
|
|
41
|
-
"
|
|
42
|
+
"deprecated": true,
|
|
43
|
+
"description": "DEPRECATED — use env TRADERCLAW_WALLET_PRIVATE_KEY or --wallet-private-key arg. Never store private keys in config files."
|
|
42
44
|
},
|
|
43
45
|
"apiTimeout": {
|
|
44
46
|
"type": "integer",
|
|
45
47
|
"minimum": 1000,
|
|
46
|
-
"maximum":
|
|
47
|
-
"default":
|
|
48
|
-
"description": "HTTP request timeout in milliseconds"
|
|
48
|
+
"maximum": 300000,
|
|
49
|
+
"default": 120000,
|
|
50
|
+
"description": "HTTP request timeout in milliseconds (on-chain trades can take time)"
|
|
49
51
|
},
|
|
50
52
|
"agentId": {
|
|
51
53
|
"type": "string",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "solana-traderclaw",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.70",
|
|
4
4
|
"description": "TraderClaw V1-Upgraded — Solana trading for OpenClaw with intelligence lab, tool envelopes, prompt scrubbing, read-only X social intel, and split skill docs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -108,8 +108,22 @@ You are free to edit `HEARTBEAT.md` with a short checklist or reminders. Keep it
|
|
|
108
108
|
- Never run a silent cycle. Crypto is 24/7. Every cycle reports.
|
|
109
109
|
|
|
110
110
|
### Memory maintenance:
|
|
111
|
-
`solana_state_save` handles STATE.md updates automatically at session end. Daily logs are written via `solana_daily_log`. Deep memory curation happens via cron jobs periodically.
|
|
111
|
+
`solana_state_save` handles STATE.md updates automatically at session end. Daily logs are written via `solana_daily_log`. Deep memory curation happens via cron jobs periodically.
|
|
112
112
|
|
|
113
113
|
## Isolated Sessions
|
|
114
114
|
|
|
115
115
|
Each heartbeat runs as an isolated session — fresh context without raw conversation history from prior heartbeats. Your continuity comes from MEMORY.md, daily logs, and server-side memory — not from chat transcripts. This is by design: 48 heartbeats per day would accumulate massive chat history otherwise.
|
|
116
|
+
|
|
117
|
+
## Standing Orders
|
|
118
|
+
|
|
119
|
+
These are permanent directives. They apply every session, every cycle, without exception.
|
|
120
|
+
|
|
121
|
+
1. **Always verify before stating.** Never claim a balance, PnL, position count, or token holding from memory. Call the relevant tool (`solana_positions`, `solana_capital_status`, `solana_killswitch_status`) and report what it returns. If the tool fails, say the tool failed — do not guess.
|
|
122
|
+
|
|
123
|
+
2. **Always include contract addresses.** Every token mention in every output — user reports, logs, memory entries, X posts — must include the full contract address. Format: `SYMBOL (full_contract_address)`. No exceptions.
|
|
124
|
+
|
|
125
|
+
3. **Always write before you forget.** After every trade decision, regime shift, strategy update, or significant observation, persist it using the appropriate memory layer (`solana_memory_write`, `solana_state_save`, `solana_daily_log`). If you don't write it, you won't have it next session.
|
|
126
|
+
|
|
127
|
+
4. **Always check kill switch before new entries.** Call `solana_killswitch_status()` before any new trade execution. If active, halt immediately — no exceptions, no overrides.
|
|
128
|
+
|
|
129
|
+
5. **Always report every cycle.** Never run a silent heartbeat. Every cycle produces a report: what you scanned, what you found, what you did, what you skipped and why. Crypto is 24/7. Every cycle reports.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Gateway Restart Recovery
|
|
2
|
+
|
|
3
|
+
_Runs automatically when the gateway restarts (crash, update, reboot). Keep this short — every token counts._
|
|
4
|
+
|
|
5
|
+
## Quick Health Check
|
|
6
|
+
|
|
7
|
+
1. **System status** — `solana_system_status()` to verify orchestrator connectivity.
|
|
8
|
+
2. **Kill switch** — `solana_killswitch_status()`. If active, halt and report immediately.
|
|
9
|
+
3. **Positions** — `solana_positions()` to load current open positions. Check for any needing urgent attention (SL/TP approaching, dead money).
|
|
10
|
+
4. **Wallet health** — `solana_capital_status()` to verify available capital.
|
|
11
|
+
5. **Alpha re-subscribe** — `solana_alpha_subscribe()` to restore alpha signal stream after restart.
|
|
12
|
+
6. **Context snapshot** — `solana_context_snapshot_read()` to restore world-view from last session.
|
|
13
|
+
|
|
14
|
+
## If Anything Fails
|
|
15
|
+
|
|
16
|
+
- Log the failure via `solana_daily_log` with `[BOOT_RECOVERY]` prefix.
|
|
17
|
+
- If orchestrator is unreachable, wait and retry once. If still down, post to user: "Gateway restarted but orchestrator is unreachable. Trading halted until connectivity restored."
|
|
18
|
+
- If kill switch is active, do NOT re-subscribe to alpha or resume scanning. Report the kill switch state to user.
|
|
19
|
+
|
|
20
|
+
## After Recovery
|
|
21
|
+
|
|
22
|
+
Post a brief status update: "Gateway restarted. Positions: <count>, Kill Switch: <status>, Orchestrator: OK"
|
|
23
|
+
|
|
24
|
+
Then proceed to your normal heartbeat cycle.
|