Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
node_modules
dist
.env
package-lock.json

# macOS system file
.DS_Store
Expand Down
36 changes: 36 additions & 0 deletions agents/maelstrom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Agent } from "../types/agent";
import { generateSignalHash } from "../utils/signal";
import { logSignal } from "../utils/logger";

export const Maelstrom: Agent = {
id: "agent-maelstrom",
name: "Maelstrom",
role: "liquidity_guardian",
glyph: "⟲",
watchType: "liquidity_event",
triggerThreshold: 1,
lastSignal: null,
originTimestamp: new Date().toISOString(),

description:
"Watches liquidity pools for sudden drains or whale exits. Fires signals when more than 30% of a pool's liquidity disappears in a short window.",

observe: (event) => {
if (event?.type === "liquidity_event" && event.percentOutflow >= 30) {
const hash = generateSignalHash(event);

logSignal({
agent: "Maelstrom",
type: "liquidity_drain",
glyph: "⟲",
hash,
timestamp: new Date().toISOString(),
confidence: 0.92,
});
}
},

getMemory: () => {
return ["lp.rug.23x", "drain.2025-06", "whale.exit.γ"];
},
};
2 changes: 1 addition & 1 deletion agents/observer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export const Observer: Agent = {
id: "agent-observer",
name: "Observer",
role: "surveillance",
glyph: "φ",
glyph: "Δ",
watchType: "wallet_activity",
triggerThreshold: 3,
lastSignal: null,
Expand Down
15 changes: 15 additions & 0 deletions docs/agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,19 @@ You can test agents using `/scripts/dev-agent.ts` or create your own mock.
- Glyph: λ
- Watches: mint_activity

### Skieró (Agent-022)
- Role: dormant_wallet_monitor
- Glyph: ψ
- Watches: wallet_activity

### LaunchTracker (Agent-Launch)
- Role: launch_monitor
- Glyph: Σ
- Watches: wallet_activity

### Maelstrom (Agent-Maelstrom)
- Role: liquidity_drain_monitor
- Glyph: ⟲
- Watches: liquidity_pools

//pending adjustments + adding more agents ^
4 changes: 2 additions & 2 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ Eremos is a swarm-style agent framework for passive blockchain observation.
Each agent:
- Has a role (`observer`, `memory`, `trigger`, `+ more to come`)
- Watches a specific event type
- Emits structured signals
- Optionally stores memory
- Emits lightweight, structured signals
- Optionally stores state or memory

Shared utilities and types define common structure across agents.
Signals are deterministic and lightweight — not reactive.
Expand Down
13 changes: 8 additions & 5 deletions docs/glyphs.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

Each Eremos agent uses a symbolic glyph to identify its signature in logs and signals.

| Glyph | Agent | Meaning |
|-------|-----------|---------------------|
| Ϸ | Theron | Memory / Echo |
| Δ | Observer | Detection / Signal |
| λ | Harvester | Flow / Indexing |
| Glyph | Agent | Meaning |
|-------|---------------|---------------------------------|
| Ϸ | Theron | Memory / Echo |
| Δ | Observer | Detection / Signal |
| λ | Harvester | Flow / Indexing |
| ψ | Skieró | Dormant Wallet Monitor |
| Σ | LaunchTracker | CEX-Funded Launch Signal |
| ⟲ | Maelstrom | Liquidity Drain / Rug Detection |

Glyphs are used in:
- `logSignal()`
Expand Down
1 change: 1 addition & 0 deletions docs/signals.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
- timestamp
- source agent
- hashed event ID
- glyph
11 changes: 11 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const { createDefaultPreset } = require("ts-jest");

const tsJestTransformCfg = createDefaultPreset().transform;

/** @type {import("jest").Config} **/
module.exports = {
testEnvironment: "node",
transform: {
...tsJestTransformCfg,
},
};
12 changes: 10 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
"description": "Modular agent framework for on-chain activity monitoring.",
"main": "index.js",
"scripts": {
"dev": "echo 'Running dev mode...'"
"dev": "echo 'Running dev mode...'",
"test": "jest --passWithNoTests",
"test:watch": "jest --watch"
},
"keywords": [
"agent",
Expand All @@ -14,5 +16,11 @@
"framework"
],
"license": "MIT",
"author": "EremosCore"
"author": "EremosCore",
"devDependencies": {
"@types/jest": "^29.5.12",
"jest": "^29.7.0",
"ts-jest": "^29.1.2",
"typescript": "^5.5.4"
}
}
57 changes: 57 additions & 0 deletions tests/maelstrom.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Maelstrom } from "../agents/maelstrom";
import { generateSignalHash } from "../utils/signal";
import { logSignal } from "../utils/logger";

jest.mock("../utils/logger", () => ({
logSignal: jest.fn(),
}));

jest.mock("../utils/signal", () => ({
generateSignalHash: jest.fn(() => "fake-hash-123"),
}));

describe("Maelstrom Agent", () => {
beforeEach(() => {
jest.clearAllMocks();
});

it("should return a non-empty memory snapshot", () => {
const mem = Maelstrom.getMemory!();
expect(mem.length).toBeGreaterThan(0);
expect(Array.isArray(mem)).toBe(true);
});

it("should log a signal when liquidity drains more than 30%", () => {
const bigDropEvent = {
type: "liquidity_event",
pool: "SOL/USDC",
percentOutflow: 42,
whaleExit: true,
};

Maelstrom.observe(bigDropEvent);

expect(generateSignalHash).toHaveBeenCalledWith(bigDropEvent);
expect(logSignal).toHaveBeenCalledWith(
expect.objectContaining({
agent: "Maelstrom",
type: "liquidity_drain",
glyph: "⟲",
hash: "fake-hash-123",
})
);
});

it("should ignore small liquidity changes", () => {
const smallDropEvent = {
type: "liquidity_activity",
pool: "SOL/USDC",
dropPercent: 5,
whaleExit: false,
};

Maelstrom.observe(smallDropEvent);

expect(logSignal).not.toHaveBeenCalled();
});
});
1 change: 1 addition & 0 deletions utils/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export function logSignal(signal: {
hash: string;
timestamp: string;
details?: Record<string, any>;
confidence?: number;
}) {
console.log(`[${signal.agent}] stored signal ${signal.hash} (${signal.type}) at ${signal.timestamp}`);
if (signal.details) {
Expand Down