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
- "solana_memory_write",
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;
@@ -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
- "description": "Solana wallet private key in base58 (only needed for re-auth when wallet already exists on account)"
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": 120000,
47
- "default": 30000,
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.68",
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. `solana_memory_trim` runs daily at 03:00 UTC via `memory_trim` cron — compacts state, prunes old daily logs, trims stale decision/bulletin entries while preserving all critical data (positions, rules, identity, strategy weights, permanent learnings).
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.