nanosolana 0.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 ADDED
@@ -0,0 +1,163 @@
1
+ <div align="center">
2
+
3
+ ```
4
+ ███╗ ██╗ █████╗ ███╗ ██╗ ██████╗ ███████╗ ██████╗ ██╗ █████╗ ███╗ ██╗ █████╗
5
+ ████╗ ██║██╔══██╗████╗ ██║██╔═══██╗██╔════╝██╔═══██╗██║ ██╔══██╗████╗ ██║██╔══██╗
6
+ ██╔██╗ ██║███████║██╔██╗ ██║██║ ██║███████╗██║ ██║██║ ███████║██╔██╗ ██║███████║
7
+ ██║╚██╗██║██╔══██║██║╚██╗██║██║ ██║╚════██║██║ ██║██║ ██╔══██║██║╚██╗██║██╔══██║
8
+ ██║ ╚████║██║ ██║██║ ╚████║╚██████╔╝███████║╚██████╔╝███████╗██║ ██║██║ ╚████║██║ ██║
9
+ ╚═╝ ╚═══╝╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝
10
+ ```
11
+
12
+ **The Open-Source Agentic Framework for Financial Intelligence on Solana**
13
+
14
+ [![License: MIT](https://img.shields.io/badge/License-MIT-14F195.svg)](LICENSE)
15
+ [![Solana](https://img.shields.io/badge/Solana-Native-9945FF.svg)](https://solana.com)
16
+ [![npm](https://img.shields.io/npm/v/nanosolana?color=14F195)](https://npmjs.com/package/nanosolana)
17
+
18
+ [Website](https://nanosolana.com) · [Hub](https://hub.nanosolana.com) · [Docs](https://docs.nanosolana.com) · [GitHub](https://github.com/x402agent/NanoSolana)
19
+
20
+ </div>
21
+
22
+ ## One-Shot Deploy
23
+
24
+ ```bash
25
+ npx nanosolana go
26
+ ```
27
+
28
+ That's it — one command handles API key setup, wallet creation, blockchain scan, on-chain NFT identity, OODA trading loop, and gateway.
29
+
30
+ ## Install
31
+
32
+ ```bash
33
+ npm install -g nanosolana
34
+ ```
35
+
36
+ Or step-by-step:
37
+
38
+ ```bash
39
+ nanosolana init # Configure API keys (encrypted at rest)
40
+ nanosolana birth # Create Solana wallet + mint Birth Certificate NFT + blockchain scan
41
+ nanosolana run # Start the OODA trading loop
42
+ ```
43
+
44
+ ## Architecture
45
+
46
+ ```
47
+ nano-core/
48
+ ├── src/
49
+ │ ├── ai/ → OpenRouter AI provider (multimodal: text, image, audio, video)
50
+ │ ├── cli/ → `nanosolana` CLI (25+ commands)
51
+ │ ├── config/ → AES-256-GCM encrypted vault & Zod-validated config
52
+ │ ├── gateway/ → HMAC-SHA256 authenticated WebSocket + HTTP server
53
+ │ ├── hub/ → NanoHub bridge for UI communication
54
+ │ ├── memory/ → ClawVault 3-tier epistemological memory engine
55
+ │ ├── network/ → Tailscale + tmux mesh networking
56
+ │ ├── nft/ → Metaplex gasless devnet birth certificate NFT
57
+ │ ├── onchain/ → Helius blockchain reader (DAS, Enhanced Tx, wallet scan)
58
+ │ ├── registry/ → On-chain agent identity (Metaplex NFT registration)
59
+ │ ├── nanobot/ → Interactive local web UI companion
60
+ │ ├── pet/ → TamaGOchi virtual pet engine (mood × risk)
61
+ │ ├── strategy/ → RSI + EMA + ATR auto-optimizer
62
+ │ ├── telegram/ → Persistent conversation store (200 msg/chat)
63
+ │ ├── trading/ → OODA trading engine + Jupiter swap execution
64
+ │ └── wallet/ → Solana Ed25519 wallet manager
65
+ ├── SOUL.md → Agent identity system prompt
66
+ └── extensions/ → 14+ plugins (Telegram, Discord, Nostr, etc.)
67
+ ```
68
+
69
+ ## Commands
70
+
71
+ | Command | Description |
72
+ |---------|-------------|
73
+ | `nanosolana go` | **One-shot: init + birth + scan + register + trade** |
74
+ | `nanosolana init` | Configure + encrypt API keys |
75
+ | `nanosolana birth` | Create wallet + mint Birth Certificate NFT + blockchain scan |
76
+ | `nanosolana run` | Start OODA trading loop |
77
+ | `nanosolana scan [address]` | **Blockchain data scan — SOL, tokens, NFTs, tx history** |
78
+ | `nanosolana register` | **Mint on-chain agent identity NFT (devnet)** |
79
+ | `nanosolana registry` | **Show on-chain agent identity** |
80
+ | `nanosolana nanobot` | **Launch interactive NanoBot web UI** |
81
+ | `nanosolana dvd` | Floating DVD screensaver 🦞 |
82
+ | `nanosolana lobster` | Animated Unicode lobster mascot |
83
+ | `nanosolana status` | Show agent + wallet + pet status |
84
+ | `nanosolana trade status` | Trading P&L and strategy state |
85
+ | `nanosolana trade signals` | Recent trading signals with confidence |
86
+ | `nanosolana wallet balance` | SOL + SPL token balances |
87
+ | `nanosolana pet status` | TamaGOchi pet mood and evolution |
88
+ | `nanosolana memory search` | Search ClawVault memory |
89
+ | `nanosolana gateway run` | Start WebSocket gateway |
90
+ | `nanosolana channels status` | Check channel connections |
91
+ | `nanosolana vault set <key> <val>` | Store encrypted secret |
92
+ | `nanosolana send <msg>` | One-shot message to nano bots |
93
+ | `nanosolana nodes` | List Tailscale mesh peers |
94
+ | `nanosolana doctor` | Run diagnostics |
95
+ | `nanosolana security audit` | Full security scan |
96
+
97
+ ## Required API Keys
98
+
99
+ | Key | Source | Required |
100
+ |-----|--------|----------|
101
+ | `OPENROUTER_API_KEY` | [openrouter.ai](https://openrouter.ai) | ✅ |
102
+ | `HELIUS_RPC_URL` | [helius.dev](https://helius.dev) | ✅ |
103
+ | `HELIUS_API_KEY` | [helius.dev](https://helius.dev) | ✅ |
104
+ | `HELIUS_WSS_URL` | [helius.dev](https://helius.dev) | Recommended |
105
+ | `BIRDEYE_API_KEY` | [birdeye.so](https://birdeye.so) | Recommended |
106
+ | `JUPITER_API_KEY` | [jup.ag](https://jup.ag) | For trading |
107
+
108
+ ## Security
109
+
110
+ - ✅ AES-256-GCM encrypted secrets vault
111
+ - ✅ HMAC-SHA256 gateway authentication
112
+ - ✅ Ed25519 wallet signatures
113
+ - ✅ Timing-safe token comparison
114
+ - ✅ Rate limiting (10 conn/min, 100 msg/min)
115
+ - ✅ File permissions enforced (0600/0700)
116
+ - ✅ Wallet private key never leaves the vault
117
+
118
+ ## Trading Engine (OODA)
119
+
120
+ 1. **Observe** — Real-time data from Helius RPC + Birdeye API
121
+ 2. **Orient** — AI analysis via OpenRouter (multimodal)
122
+ 3. **Decide** — Structured signals with confidence scoring
123
+ 4. **Act** — Jupiter swap execution with slippage protection
124
+ 5. **Learn** — ClawVault experience replay + contradiction detection
125
+
126
+ ## Blockchain Intelligence (Helius)
127
+
128
+ At agent birth, NanoSolana instantly reads the blockchain:
129
+
130
+ - **DAS API** — tokens, NFTs, compressed assets
131
+ - **Enhanced Transactions** — parsed tx history with descriptions
132
+ - **Priority Fees** — real-time fee estimation
133
+ - **Wallet Snapshot** — SOL balance, token prices, NFT inventory
134
+
135
+ ## On-Chain Identity
136
+
137
+ Every agent mints a **Metaplex NFT** on devnet as its on-chain identity:
138
+
139
+ - Agent public key
140
+ - NanoSolana version
141
+ - Registered skills
142
+ - SHA-256 fingerprint
143
+
144
+ ## TamaGOchi Pet
145
+
146
+ 🥚 Egg → 🐛 Larva → 🐣 Juvenile → 🦞 Adult → 👑 Alpha → 👻 Ghost
147
+
148
+ Pet mood affects risk tolerance. Feed to keep alive!
149
+
150
+ ## Chrome Extension
151
+
152
+ Manifest V3 browser extension for tab relay, wallet management, chat, and manual trades via the gateway.
153
+
154
+ ## Links
155
+
156
+ - **Website:** [nanosolana.com](https://nanosolana.com)
157
+ - **Hub:** [hub.nanosolana.com](https://hub.nanosolana.com)
158
+ - **Docs:** [docs.nanosolana.com](https://docs.nanosolana.com)
159
+ - **GitHub:** [github.com/x402agent/NanoSolana](https://github.com/x402agent/NanoSolana)
160
+
161
+ ## License
162
+
163
+ MIT — [NanoSolana Labs](https://nanosolana.com)
@@ -0,0 +1,11 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
8
+ export {
9
+ __require
10
+ };
11
+ //# sourceMappingURL=chunk-DGUM43GV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,303 @@
1
+ // src/memory/engine.ts
2
+ import { EventEmitter } from "eventemitter3";
3
+ import { randomUUID } from "crypto";
4
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
5
+ import { join } from "path";
6
+ import { homedir } from "os";
7
+ var MemoryEngine = class extends EventEmitter {
8
+ constructor(temporalDecayHours = 168, dbPath) {
9
+ super();
10
+ this.temporalDecayHours = temporalDecayHours;
11
+ this.dbPath = dbPath ?? join(homedir(), ".nanosolana", "memory");
12
+ this.ensureDbDir();
13
+ this.loadFromDisk();
14
+ }
15
+ memories = /* @__PURE__ */ new Map();
16
+ lessons = /* @__PURE__ */ new Map();
17
+ decayTimer = null;
18
+ persistTimer = null;
19
+ dbPath;
20
+ /**
21
+ * Store a new memory.
22
+ */
23
+ store(params) {
24
+ const memory = {
25
+ id: randomUUID(),
26
+ type: params.type,
27
+ content: params.content,
28
+ metadata: params.metadata ?? {},
29
+ confidence: 1,
30
+ importance: params.importance ?? 0.5,
31
+ accessCount: 0,
32
+ lastAccessedAt: Date.now(),
33
+ createdAt: Date.now(),
34
+ tags: params.tags ?? [],
35
+ linkedMemories: params.linkedMemories ?? []
36
+ };
37
+ this.memories.set(memory.id, memory);
38
+ this.emit("memoryCreated", memory);
39
+ return memory;
40
+ }
41
+ /**
42
+ * Record a trade outcome and learn from it.
43
+ */
44
+ recordTradeOutcome(params) {
45
+ const pnl = params.exitPrice - params.entryPrice;
46
+ const pnlPercent = params.entryPrice > 0 ? (params.exitPrice - params.entryPrice) / params.entryPrice * 100 : 0;
47
+ const wasCorrect = pnl > 0;
48
+ const memory = this.store({
49
+ type: "outcome",
50
+ content: `Trade ${params.tradeType} ${params.tokenSymbol}: ${wasCorrect ? "WIN" : "LOSS"} (${pnlPercent.toFixed(2)}%). Reasoning: ${params.reasoning}`,
51
+ metadata: {
52
+ signalId: params.signalId,
53
+ executionId: params.executionId,
54
+ tokenMint: params.tokenMint,
55
+ tokenSymbol: params.tokenSymbol,
56
+ tradeType: params.tradeType,
57
+ entryPrice: params.entryPrice,
58
+ exitPrice: params.exitPrice,
59
+ pnl,
60
+ pnlPercent,
61
+ reasoning: params.reasoning,
62
+ wasCorrect
63
+ },
64
+ tags: [
65
+ params.tradeType,
66
+ params.tokenSymbol,
67
+ wasCorrect ? "win" : "loss",
68
+ pnlPercent > 10 ? "big-win" : pnlPercent < -10 ? "big-loss" : "normal"
69
+ ],
70
+ importance: Math.abs(pnlPercent) > 5 ? 0.9 : 0.5
71
+ });
72
+ const lesson = this.learnFromOutcome(memory, wasCorrect, pnlPercent, params);
73
+ return { memory, lesson };
74
+ }
75
+ /**
76
+ * Learn a lesson from a trade outcome.
77
+ */
78
+ learnFromOutcome(memory, wasCorrect, pnlPercent, params) {
79
+ const similarOutcomes = this.searchByTags([params.tradeType, params.tokenSymbol], 10);
80
+ const recentWins = similarOutcomes.filter(
81
+ (m) => m.memory.metadata.wasCorrect === true
82
+ );
83
+ const recentLosses = similarOutcomes.filter(
84
+ (m) => m.memory.metadata.wasCorrect === false
85
+ );
86
+ const winRate = similarOutcomes.length > 0 ? recentWins.length / similarOutcomes.length : 0.5;
87
+ const patternKey = `${params.tradeType}:${params.tokenSymbol}`;
88
+ const existingLesson = this.lessons.get(patternKey);
89
+ if (existingLesson) {
90
+ existingLesson.occurrences++;
91
+ existingLesson.lastOccurrence = Date.now();
92
+ existingLesson.confidenceImpact = wasCorrect ? Math.min(1, existingLesson.confidenceImpact + 0.1) : Math.max(-1, existingLesson.confidenceImpact - 0.15);
93
+ if (!wasCorrect && recentLosses.length >= 3) {
94
+ existingLesson.adjustment = `STOP trading ${params.tokenSymbol} \u2014 ${recentLosses.length} consecutive losses. Win rate: ${(winRate * 100).toFixed(0)}%`;
95
+ }
96
+ this.lessons.set(patternKey, existingLesson);
97
+ this.emit("lessonLearned", existingLesson);
98
+ return existingLesson;
99
+ }
100
+ const lesson = {
101
+ id: randomUUID(),
102
+ pattern: `${params.tradeType} on ${params.tokenSymbol}`,
103
+ action: params.reasoning,
104
+ outcome: wasCorrect ? `Profit: +${pnlPercent.toFixed(2)}%` : `Loss: ${pnlPercent.toFixed(2)}%`,
105
+ adjustment: wasCorrect ? `Continue monitoring ${params.tokenSymbol} \u2014 strategy working` : `Reduce position size or avoid ${params.tokenSymbol} \u2014 reasoning "${params.reasoning}" led to loss`,
106
+ confidenceImpact: wasCorrect ? 0.1 : -0.15,
107
+ occurrences: 1,
108
+ lastOccurrence: Date.now()
109
+ };
110
+ this.lessons.set(patternKey, lesson);
111
+ this.emit("lessonLearned", lesson);
112
+ return lesson;
113
+ }
114
+ /**
115
+ * Search memories by content similarity (basic text match).
116
+ * In production, this would use vector embeddings.
117
+ */
118
+ search(query, limit = 10) {
119
+ const queryLower = query.toLowerCase();
120
+ const queryWords = queryLower.split(/\s+/);
121
+ const results = [];
122
+ for (const memory of this.memories.values()) {
123
+ const contentLower = memory.content.toLowerCase();
124
+ let matchScore = 0;
125
+ for (const word of queryWords) {
126
+ if (contentLower.includes(word)) {
127
+ matchScore += 1 / queryWords.length;
128
+ }
129
+ }
130
+ const relevance = matchScore * memory.confidence * (0.5 + memory.importance * 0.5);
131
+ if (relevance > 0) {
132
+ memory.accessCount++;
133
+ memory.lastAccessedAt = Date.now();
134
+ results.push({ memory, relevance });
135
+ }
136
+ }
137
+ return results.sort((a, b) => b.relevance - a.relevance).slice(0, limit);
138
+ }
139
+ /**
140
+ * Search memories by tags.
141
+ */
142
+ searchByTags(tags, limit = 10) {
143
+ const results = [];
144
+ for (const memory of this.memories.values()) {
145
+ const matchCount = tags.filter((t) => memory.tags.includes(t)).length;
146
+ if (matchCount > 0) {
147
+ const relevance = matchCount / tags.length * memory.confidence;
148
+ results.push({ memory, relevance });
149
+ }
150
+ }
151
+ return results.sort((a, b) => b.relevance - a.relevance).slice(0, limit);
152
+ }
153
+ /**
154
+ * Experience Replay — resurface past lessons for current context.
155
+ * Called before making trading decisions.
156
+ */
157
+ experienceReplay(context) {
158
+ const relevantLessons = [];
159
+ for (const lesson of this.lessons.values()) {
160
+ let relevant = false;
161
+ if (context.tokenSymbol && lesson.pattern.includes(context.tokenSymbol)) {
162
+ relevant = true;
163
+ }
164
+ if (context.tradeType && lesson.pattern.includes(context.tradeType)) {
165
+ relevant = true;
166
+ }
167
+ if (relevant) {
168
+ relevantLessons.push(lesson);
169
+ }
170
+ }
171
+ if (relevantLessons.length > 0) {
172
+ this.emit("replayTriggered", relevantLessons);
173
+ }
174
+ return relevantLessons;
175
+ }
176
+ /**
177
+ * Apply temporal decay to all memories.
178
+ * Older memories lose confidence unless they're important or frequently accessed.
179
+ */
180
+ applyDecay() {
181
+ const now = Date.now();
182
+ const decayWindowMs = this.temporalDecayHours * 60 * 60 * 1e3;
183
+ for (const [id, memory] of this.memories) {
184
+ const age = now - memory.createdAt;
185
+ const timeSinceAccess = now - memory.lastAccessedAt;
186
+ let decayRate = age / decayWindowMs;
187
+ if (memory.accessCount > 5) decayRate *= 0.5;
188
+ decayRate *= 1 - memory.importance * 0.7;
189
+ const newConfidence = Math.max(0.01, memory.confidence - decayRate * 0.01);
190
+ if (newConfidence !== memory.confidence) {
191
+ memory.confidence = newConfidence;
192
+ if (newConfidence < 0.1) {
193
+ this.emit("memoryDecayed", id);
194
+ }
195
+ }
196
+ }
197
+ for (const [id, memory] of this.memories) {
198
+ if (memory.confidence < 0.05 && memory.importance < 0.3) {
199
+ this.memories.delete(id);
200
+ }
201
+ }
202
+ }
203
+ /**
204
+ * Reinforce a memory — called when a past memory proves relevant again.
205
+ */
206
+ reinforce(id, boost = 0.2) {
207
+ const memory = this.memories.get(id);
208
+ if (!memory) return;
209
+ memory.confidence = Math.min(1, memory.confidence + boost);
210
+ memory.accessCount++;
211
+ memory.lastAccessedAt = Date.now();
212
+ this.emit("memoryReinforced", id, memory.confidence);
213
+ }
214
+ /**
215
+ * Start autonomous memory management.
216
+ */
217
+ startAutonomous(decayIntervalMs = 6e4, persistIntervalMs = 3e4) {
218
+ this.decayTimer = setInterval(() => this.applyDecay(), decayIntervalMs);
219
+ this.persistTimer = setInterval(() => this.persistToDisk(), persistIntervalMs);
220
+ }
221
+ /**
222
+ * Stop autonomous management.
223
+ */
224
+ stopAutonomous() {
225
+ if (this.decayTimer) {
226
+ clearInterval(this.decayTimer);
227
+ this.decayTimer = null;
228
+ }
229
+ if (this.persistTimer) {
230
+ clearInterval(this.persistTimer);
231
+ this.persistTimer = null;
232
+ }
233
+ this.persistToDisk();
234
+ }
235
+ /**
236
+ * Get memory stats.
237
+ */
238
+ getStats() {
239
+ let totalConfidence = 0;
240
+ let tradeWins = 0;
241
+ let totalTrades = 0;
242
+ for (const memory of this.memories.values()) {
243
+ totalConfidence += memory.confidence;
244
+ if (memory.type === "outcome") {
245
+ totalTrades++;
246
+ if (memory.metadata.wasCorrect) tradeWins++;
247
+ }
248
+ }
249
+ return {
250
+ totalMemories: this.memories.size,
251
+ totalLessons: this.lessons.size,
252
+ avgConfidence: this.memories.size > 0 ? totalConfidence / this.memories.size : 0,
253
+ tradeWinRate: totalTrades > 0 ? tradeWins / totalTrades : 0
254
+ };
255
+ }
256
+ /**
257
+ * Get all lessons.
258
+ */
259
+ getLessons() {
260
+ return [...this.lessons.values()];
261
+ }
262
+ // ── Persistence ────────────────────────────────────────────
263
+ ensureDbDir() {
264
+ if (!existsSync(this.dbPath)) {
265
+ mkdirSync(this.dbPath, { recursive: true, mode: 448 });
266
+ }
267
+ }
268
+ persistToDisk() {
269
+ try {
270
+ const memoriesFile = join(this.dbPath, "memories.json");
271
+ const lessonsFile = join(this.dbPath, "lessons.json");
272
+ const memoriesArr = [...this.memories.values()];
273
+ const lessonsArr = [...this.lessons.entries()];
274
+ writeFileSync(memoriesFile, JSON.stringify(memoriesArr, null, 2), { mode: 384 });
275
+ writeFileSync(lessonsFile, JSON.stringify(lessonsArr, null, 2), { mode: 384 });
276
+ } catch {
277
+ }
278
+ }
279
+ loadFromDisk() {
280
+ try {
281
+ const memoriesFile = join(this.dbPath, "memories.json");
282
+ const lessonsFile = join(this.dbPath, "lessons.json");
283
+ if (existsSync(memoriesFile)) {
284
+ const data = JSON.parse(readFileSync(memoriesFile, "utf8"));
285
+ for (const memory of data) {
286
+ this.memories.set(memory.id, memory);
287
+ }
288
+ }
289
+ if (existsSync(lessonsFile)) {
290
+ const data = JSON.parse(readFileSync(lessonsFile, "utf8"));
291
+ for (const [key, lesson] of data) {
292
+ this.lessons.set(key, lesson);
293
+ }
294
+ }
295
+ } catch {
296
+ }
297
+ }
298
+ };
299
+
300
+ export {
301
+ MemoryEngine
302
+ };
303
+ //# sourceMappingURL=chunk-FJ2L6IFK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/memory/engine.ts"],"sourcesContent":["/**\n * Nano Solana — Real-Time Memory Engine\n *\n * Adaptive memory system that learns from trading outcomes.\n * Features:\n * - Temporal decay (older memories fade)\n * - Experience replay (learn from mistakes)\n * - Semantic search via embeddings\n * - Trade outcome feedback loop\n *\n * The memory is \"sentient\" in the sense that it autonomously:\n * 1. Observes outcomes and correlates them with past decisions\n * 2. Adjusts confidence weights based on success/failure\n * 3. Surfaces relevant past experiences during decision-making\n * 4. Prunes low-value memories to stay focused\n */\n\nimport { EventEmitter } from \"eventemitter3\";\nimport { createHash, randomUUID } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\n\n// ── Types ────────────────────────────────────────────────────\n\nexport interface Memory {\n id: string;\n type: \"observation\" | \"decision\" | \"outcome\" | \"lesson\" | \"context\";\n content: string;\n embedding?: number[];\n metadata: Record<string, unknown>;\n confidence: number; // 0-1, decays over time\n importance: number; // 0-1, increased by relevance\n accessCount: number;\n lastAccessedAt: number;\n createdAt: number;\n tags: string[];\n linkedMemories: string[]; // IDs of related memories\n}\n\nexport interface TradeMemory extends Memory {\n type: \"outcome\";\n metadata: {\n signalId: string;\n executionId: string;\n tokenMint: string;\n tokenSymbol: string;\n tradeType: \"buy\" | \"sell\";\n entryPrice: number;\n exitPrice?: number;\n pnl?: number;\n pnlPercent?: number;\n holdDurationMs?: number;\n reasoning: string;\n wasCorrect?: boolean;\n };\n}\n\nexport interface Lesson {\n id: string;\n pattern: string; // What pattern was recognized\n action: string; // What the agent did\n outcome: string; // What happened\n adjustment: string; // What to do differently\n confidenceImpact: number; // How much to adjust confidence (-1 to 1)\n occurrences: number;\n lastOccurrence: number;\n}\n\nexport interface MemorySearchResult {\n memory: Memory;\n relevance: number;\n}\n\nexport interface MemoryEngineEvents {\n memoryCreated: (memory: Memory) => void;\n lessonLearned: (lesson: Lesson) => void;\n memoryDecayed: (id: string) => void;\n memoryReinforced: (id: string, newConfidence: number) => void;\n replayTriggered: (lessons: Lesson[]) => void;\n}\n\n// ── Memory Engine ────────────────────────────────────────────\n\nexport class MemoryEngine extends EventEmitter<MemoryEngineEvents> {\n private memories: Map<string, Memory> = new Map();\n private lessons: Map<string, Lesson> = new Map();\n private decayTimer: ReturnType<typeof setInterval> | null = null;\n private persistTimer: ReturnType<typeof setInterval> | null = null;\n private dbPath: string;\n\n constructor(\n private temporalDecayHours = 168, // 7 days\n dbPath?: string,\n ) {\n super();\n this.dbPath = dbPath ?? join(homedir(), \".nanosolana\", \"memory\");\n this.ensureDbDir();\n this.loadFromDisk();\n }\n\n /**\n * Store a new memory.\n */\n store(params: {\n type: Memory[\"type\"];\n content: string;\n metadata?: Record<string, unknown>;\n tags?: string[];\n importance?: number;\n linkedMemories?: string[];\n }): Memory {\n const memory: Memory = {\n id: randomUUID(),\n type: params.type,\n content: params.content,\n metadata: params.metadata ?? {},\n confidence: 1.0,\n importance: params.importance ?? 0.5,\n accessCount: 0,\n lastAccessedAt: Date.now(),\n createdAt: Date.now(),\n tags: params.tags ?? [],\n linkedMemories: params.linkedMemories ?? [],\n };\n\n this.memories.set(memory.id, memory);\n this.emit(\"memoryCreated\", memory);\n return memory;\n }\n\n /**\n * Record a trade outcome and learn from it.\n */\n recordTradeOutcome(params: {\n signalId: string;\n executionId: string;\n tokenMint: string;\n tokenSymbol: string;\n tradeType: \"buy\" | \"sell\";\n entryPrice: number;\n exitPrice: number;\n reasoning: string;\n }): { memory: Memory; lesson: Lesson | null } {\n const pnl = params.exitPrice - params.entryPrice;\n const pnlPercent = params.entryPrice > 0\n ? ((params.exitPrice - params.entryPrice) / params.entryPrice) * 100\n : 0;\n const wasCorrect = pnl > 0;\n\n // Store the outcome as a memory\n const memory = this.store({\n type: \"outcome\",\n content: `Trade ${params.tradeType} ${params.tokenSymbol}: ${wasCorrect ? \"WIN\" : \"LOSS\"} (${pnlPercent.toFixed(2)}%). Reasoning: ${params.reasoning}`,\n metadata: {\n signalId: params.signalId,\n executionId: params.executionId,\n tokenMint: params.tokenMint,\n tokenSymbol: params.tokenSymbol,\n tradeType: params.tradeType,\n entryPrice: params.entryPrice,\n exitPrice: params.exitPrice,\n pnl,\n pnlPercent,\n reasoning: params.reasoning,\n wasCorrect,\n },\n tags: [\n params.tradeType,\n params.tokenSymbol,\n wasCorrect ? \"win\" : \"loss\",\n pnlPercent > 10 ? \"big-win\" : pnlPercent < -10 ? \"big-loss\" : \"normal\",\n ],\n importance: Math.abs(pnlPercent) > 5 ? 0.9 : 0.5,\n });\n\n // Learn a lesson from the outcome\n const lesson = this.learnFromOutcome(memory, wasCorrect, pnlPercent, params);\n\n return { memory, lesson };\n }\n\n /**\n * Learn a lesson from a trade outcome.\n */\n private learnFromOutcome(\n memory: Memory,\n wasCorrect: boolean,\n pnlPercent: number,\n params: { tokenSymbol: string; tradeType: string; reasoning: string },\n ): Lesson | null {\n // Find similar past outcomes to identify patterns\n const similarOutcomes = this.searchByTags([params.tradeType, params.tokenSymbol], 10);\n const recentWins = similarOutcomes.filter(\n (m) => (m.memory.metadata as any).wasCorrect === true,\n );\n const recentLosses = similarOutcomes.filter(\n (m) => (m.memory.metadata as any).wasCorrect === false,\n );\n\n // Generate a pattern-based lesson\n const winRate = similarOutcomes.length > 0\n ? recentWins.length / similarOutcomes.length\n : 0.5;\n\n const patternKey = `${params.tradeType}:${params.tokenSymbol}`;\n const existingLesson = this.lessons.get(patternKey);\n\n if (existingLesson) {\n // Update existing lesson\n existingLesson.occurrences++;\n existingLesson.lastOccurrence = Date.now();\n existingLesson.confidenceImpact = wasCorrect\n ? Math.min(1, existingLesson.confidenceImpact + 0.1)\n : Math.max(-1, existingLesson.confidenceImpact - 0.15);\n\n if (!wasCorrect && recentLosses.length >= 3) {\n existingLesson.adjustment = `STOP trading ${params.tokenSymbol} — ${recentLosses.length} consecutive losses. Win rate: ${(winRate * 100).toFixed(0)}%`;\n }\n\n this.lessons.set(patternKey, existingLesson);\n this.emit(\"lessonLearned\", existingLesson);\n return existingLesson;\n }\n\n // Create new lesson\n const lesson: Lesson = {\n id: randomUUID(),\n pattern: `${params.tradeType} on ${params.tokenSymbol}`,\n action: params.reasoning,\n outcome: wasCorrect\n ? `Profit: +${pnlPercent.toFixed(2)}%`\n : `Loss: ${pnlPercent.toFixed(2)}%`,\n adjustment: wasCorrect\n ? `Continue monitoring ${params.tokenSymbol} — strategy working`\n : `Reduce position size or avoid ${params.tokenSymbol} — reasoning \"${params.reasoning}\" led to loss`,\n confidenceImpact: wasCorrect ? 0.1 : -0.15,\n occurrences: 1,\n lastOccurrence: Date.now(),\n };\n\n this.lessons.set(patternKey, lesson);\n this.emit(\"lessonLearned\", lesson);\n return lesson;\n }\n\n /**\n * Search memories by content similarity (basic text match).\n * In production, this would use vector embeddings.\n */\n search(query: string, limit = 10): MemorySearchResult[] {\n const queryLower = query.toLowerCase();\n const queryWords = queryLower.split(/\\s+/);\n\n const results: MemorySearchResult[] = [];\n\n for (const memory of this.memories.values()) {\n const contentLower = memory.content.toLowerCase();\n let matchScore = 0;\n\n for (const word of queryWords) {\n if (contentLower.includes(word)) {\n matchScore += 1 / queryWords.length;\n }\n }\n\n // Boost by confidence and importance\n const relevance = matchScore * memory.confidence * (0.5 + memory.importance * 0.5);\n\n if (relevance > 0) {\n // Mark as accessed\n memory.accessCount++;\n memory.lastAccessedAt = Date.now();\n\n results.push({ memory, relevance });\n }\n }\n\n return results\n .sort((a, b) => b.relevance - a.relevance)\n .slice(0, limit);\n }\n\n /**\n * Search memories by tags.\n */\n searchByTags(tags: string[], limit = 10): MemorySearchResult[] {\n const results: MemorySearchResult[] = [];\n\n for (const memory of this.memories.values()) {\n const matchCount = tags.filter((t) => memory.tags.includes(t)).length;\n if (matchCount > 0) {\n const relevance = (matchCount / tags.length) * memory.confidence;\n results.push({ memory, relevance });\n }\n }\n\n return results\n .sort((a, b) => b.relevance - a.relevance)\n .slice(0, limit);\n }\n\n /**\n * Experience Replay — resurface past lessons for current context.\n * Called before making trading decisions.\n */\n experienceReplay(context: {\n tokenSymbol?: string;\n tradeType?: string;\n marketCondition?: string;\n }): Lesson[] {\n const relevantLessons: Lesson[] = [];\n\n for (const lesson of this.lessons.values()) {\n let relevant = false;\n\n if (context.tokenSymbol && lesson.pattern.includes(context.tokenSymbol)) {\n relevant = true;\n }\n if (context.tradeType && lesson.pattern.includes(context.tradeType)) {\n relevant = true;\n }\n\n if (relevant) {\n relevantLessons.push(lesson);\n }\n }\n\n if (relevantLessons.length > 0) {\n this.emit(\"replayTriggered\", relevantLessons);\n }\n\n return relevantLessons;\n }\n\n /**\n * Apply temporal decay to all memories.\n * Older memories lose confidence unless they're important or frequently accessed.\n */\n applyDecay(): void {\n const now = Date.now();\n const decayWindowMs = this.temporalDecayHours * 60 * 60 * 1000;\n\n for (const [id, memory] of this.memories) {\n const age = now - memory.createdAt;\n const timeSinceAccess = now - memory.lastAccessedAt;\n\n // Base decay factor\n let decayRate = age / decayWindowMs;\n\n // Reduce decay for frequently accessed memories\n if (memory.accessCount > 5) decayRate *= 0.5;\n\n // Reduce decay for high-importance memories\n decayRate *= 1 - memory.importance * 0.7;\n\n // Apply decay\n const newConfidence = Math.max(0.01, memory.confidence - decayRate * 0.01);\n\n if (newConfidence !== memory.confidence) {\n memory.confidence = newConfidence;\n\n if (newConfidence < 0.1) {\n this.emit(\"memoryDecayed\", id);\n }\n }\n }\n\n // Prune very old, low-confidence memories (keep the store lean)\n for (const [id, memory] of this.memories) {\n if (memory.confidence < 0.05 && memory.importance < 0.3) {\n this.memories.delete(id);\n }\n }\n }\n\n /**\n * Reinforce a memory — called when a past memory proves relevant again.\n */\n reinforce(id: string, boost = 0.2): void {\n const memory = this.memories.get(id);\n if (!memory) return;\n\n memory.confidence = Math.min(1, memory.confidence + boost);\n memory.accessCount++;\n memory.lastAccessedAt = Date.now();\n\n this.emit(\"memoryReinforced\", id, memory.confidence);\n }\n\n /**\n * Start autonomous memory management.\n */\n startAutonomous(decayIntervalMs = 60000, persistIntervalMs = 30000): void {\n // Temporal decay\n this.decayTimer = setInterval(() => this.applyDecay(), decayIntervalMs);\n\n // Periodic persistence\n this.persistTimer = setInterval(() => this.persistToDisk(), persistIntervalMs);\n }\n\n /**\n * Stop autonomous management.\n */\n stopAutonomous(): void {\n if (this.decayTimer) {\n clearInterval(this.decayTimer);\n this.decayTimer = null;\n }\n if (this.persistTimer) {\n clearInterval(this.persistTimer);\n this.persistTimer = null;\n }\n this.persistToDisk(); // Final save\n }\n\n /**\n * Get memory stats.\n */\n getStats(): {\n totalMemories: number;\n totalLessons: number;\n avgConfidence: number;\n tradeWinRate: number;\n } {\n let totalConfidence = 0;\n let tradeWins = 0;\n let totalTrades = 0;\n\n for (const memory of this.memories.values()) {\n totalConfidence += memory.confidence;\n if (memory.type === \"outcome\") {\n totalTrades++;\n if ((memory.metadata as any).wasCorrect) tradeWins++;\n }\n }\n\n return {\n totalMemories: this.memories.size,\n totalLessons: this.lessons.size,\n avgConfidence: this.memories.size > 0 ? totalConfidence / this.memories.size : 0,\n tradeWinRate: totalTrades > 0 ? tradeWins / totalTrades : 0,\n };\n }\n\n /**\n * Get all lessons.\n */\n getLessons(): Lesson[] {\n return [...this.lessons.values()];\n }\n\n // ── Persistence ────────────────────────────────────────────\n\n private ensureDbDir(): void {\n if (!existsSync(this.dbPath)) {\n mkdirSync(this.dbPath, { recursive: true, mode: 0o700 });\n }\n }\n\n private persistToDisk(): void {\n try {\n const memoriesFile = join(this.dbPath, \"memories.json\");\n const lessonsFile = join(this.dbPath, \"lessons.json\");\n\n const memoriesArr = [...this.memories.values()];\n const lessonsArr = [...this.lessons.entries()];\n\n writeFileSync(memoriesFile, JSON.stringify(memoriesArr, null, 2), { mode: 0o600 });\n writeFileSync(lessonsFile, JSON.stringify(lessonsArr, null, 2), { mode: 0o600 });\n } catch {\n // Silent fail on persistence — memory is primarily in-RAM\n }\n }\n\n private loadFromDisk(): void {\n try {\n const memoriesFile = join(this.dbPath, \"memories.json\");\n const lessonsFile = join(this.dbPath, \"lessons.json\");\n\n if (existsSync(memoriesFile)) {\n const data = JSON.parse(readFileSync(memoriesFile, \"utf8\")) as Memory[];\n for (const memory of data) {\n this.memories.set(memory.id, memory);\n }\n }\n\n if (existsSync(lessonsFile)) {\n const data = JSON.parse(readFileSync(lessonsFile, \"utf8\")) as [string, Lesson][];\n for (const [key, lesson] of data) {\n this.lessons.set(key, lesson);\n }\n }\n } catch {\n // Fresh start if files are corrupted\n }\n }\n}\n"],"mappings":"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","names":[]}