fourmm 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 +147 -0
- package/dist/bin.d.ts +9 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +14 -0
- package/dist/bin.js.map +1 -0
- package/dist/cli.d.ts +319 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +25 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/config.d.ts +35 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +145 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/query.d.ts +51 -0
- package/dist/commands/query.d.ts.map +1 -0
- package/dist/commands/query.js +364 -0
- package/dist/commands/query.js.map +1 -0
- package/dist/commands/token.d.ts +55 -0
- package/dist/commands/token.d.ts.map +1 -0
- package/dist/commands/token.js +650 -0
- package/dist/commands/token.js.map +1 -0
- package/dist/commands/tools.d.ts +54 -0
- package/dist/commands/tools.d.ts.map +1 -0
- package/dist/commands/tools.js +499 -0
- package/dist/commands/tools.js.map +1 -0
- package/dist/commands/trade.d.ts +63 -0
- package/dist/commands/trade.d.ts.map +1 -0
- package/dist/commands/trade.js +933 -0
- package/dist/commands/trade.js.map +1 -0
- package/dist/commands/transfer.d.ts +51 -0
- package/dist/commands/transfer.d.ts.map +1 -0
- package/dist/commands/transfer.js +728 -0
- package/dist/commands/transfer.js.map +1 -0
- package/dist/commands/wallet.d.ts +111 -0
- package/dist/commands/wallet.d.ts.map +1 -0
- package/dist/commands/wallet.js +716 -0
- package/dist/commands/wallet.js.map +1 -0
- package/dist/contracts/erc20.d.ts +72 -0
- package/dist/contracts/erc20.d.ts.map +1 -0
- package/dist/contracts/erc20.js +55 -0
- package/dist/contracts/erc20.js.map +1 -0
- package/dist/contracts/fourmemeMmRouter.d.ts +68 -0
- package/dist/contracts/fourmemeMmRouter.d.ts.map +1 -0
- package/dist/contracts/fourmemeMmRouter.js +48 -0
- package/dist/contracts/fourmemeMmRouter.js.map +1 -0
- package/dist/contracts/pancakeRouter.d.ts +73 -0
- package/dist/contracts/pancakeRouter.d.ts.map +1 -0
- package/dist/contracts/pancakeRouter.js +50 -0
- package/dist/contracts/pancakeRouter.js.map +1 -0
- package/dist/contracts/tokenManager2.d.ts +193 -0
- package/dist/contracts/tokenManager2.d.ts.map +1 -0
- package/dist/contracts/tokenManager2.js +108 -0
- package/dist/contracts/tokenManager2.js.map +1 -0
- package/dist/contracts/tokenManagerHelper3.d.ts +118 -0
- package/dist/contracts/tokenManagerHelper3.d.ts.map +1 -0
- package/dist/contracts/tokenManagerHelper3.js +66 -0
- package/dist/contracts/tokenManagerHelper3.js.map +1 -0
- package/dist/datastore/cache.d.ts +20 -0
- package/dist/datastore/cache.d.ts.map +1 -0
- package/dist/datastore/cache.js +45 -0
- package/dist/datastore/cache.js.map +1 -0
- package/dist/datastore/index.d.ts +85 -0
- package/dist/datastore/index.d.ts.map +1 -0
- package/dist/datastore/index.js +341 -0
- package/dist/datastore/index.js.map +1 -0
- package/dist/datastore/paths.d.ts +17 -0
- package/dist/datastore/paths.d.ts.map +1 -0
- package/dist/datastore/paths.js +39 -0
- package/dist/datastore/paths.js.map +1 -0
- package/dist/datastore/types.d.ts +105 -0
- package/dist/datastore/types.d.ts.map +1 -0
- package/dist/datastore/types.js +8 -0
- package/dist/datastore/types.js.map +1 -0
- package/dist/fourmeme/auth.d.ts +22 -0
- package/dist/fourmeme/auth.d.ts.map +1 -0
- package/dist/fourmeme/auth.js +78 -0
- package/dist/fourmeme/auth.js.map +1 -0
- package/dist/fourmeme/create.d.ts +31 -0
- package/dist/fourmeme/create.d.ts.map +1 -0
- package/dist/fourmeme/create.js +111 -0
- package/dist/fourmeme/create.js.map +1 -0
- package/dist/fourmeme/upload.d.ts +16 -0
- package/dist/fourmeme/upload.d.ts.map +1 -0
- package/dist/fourmeme/upload.js +52 -0
- package/dist/fourmeme/upload.js.map +1 -0
- package/dist/lib/bundle.d.ts +51 -0
- package/dist/lib/bundle.d.ts.map +1 -0
- package/dist/lib/bundle.js +95 -0
- package/dist/lib/bundle.js.map +1 -0
- package/dist/lib/config.d.ts +58 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +183 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/const.d.ts +165 -0
- package/dist/lib/const.d.ts.map +1 -0
- package/dist/lib/const.js +98 -0
- package/dist/lib/const.js.map +1 -0
- package/dist/lib/env.d.ts +14 -0
- package/dist/lib/env.d.ts.map +1 -0
- package/dist/lib/env.js +18 -0
- package/dist/lib/env.js.map +1 -0
- package/dist/lib/guards.d.ts +44 -0
- package/dist/lib/guards.d.ts.map +1 -0
- package/dist/lib/guards.js +65 -0
- package/dist/lib/guards.js.map +1 -0
- package/dist/lib/identify.d.ts +85 -0
- package/dist/lib/identify.d.ts.map +1 -0
- package/dist/lib/identify.js +88 -0
- package/dist/lib/identify.js.map +1 -0
- package/dist/lib/pricing.d.ts +62 -0
- package/dist/lib/pricing.d.ts.map +1 -0
- package/dist/lib/pricing.js +302 -0
- package/dist/lib/pricing.js.map +1 -0
- package/dist/lib/routing.d.ts +57 -0
- package/dist/lib/routing.d.ts.map +1 -0
- package/dist/lib/routing.js +67 -0
- package/dist/lib/routing.js.map +1 -0
- package/dist/lib/slippage.d.ts +29 -0
- package/dist/lib/slippage.d.ts.map +1 -0
- package/dist/lib/slippage.js +110 -0
- package/dist/lib/slippage.js.map +1 -0
- package/dist/lib/tracker.d.ts +68 -0
- package/dist/lib/tracker.d.ts.map +1 -0
- package/dist/lib/tracker.js +155 -0
- package/dist/lib/tracker.js.map +1 -0
- package/dist/lib/viem.d.ts +12 -0
- package/dist/lib/viem.d.ts.map +1 -0
- package/dist/lib/viem.js +44 -0
- package/dist/lib/viem.js.map +1 -0
- package/dist/lib/wallet-rows.d.ts +30 -0
- package/dist/lib/wallet-rows.d.ts.map +1 -0
- package/dist/lib/wallet-rows.js +9 -0
- package/dist/lib/wallet-rows.js.map +1 -0
- package/dist/lib/walletClient.d.ts +16 -0
- package/dist/lib/walletClient.d.ts.map +1 -0
- package/dist/lib/walletClient.js +26 -0
- package/dist/lib/walletClient.js.map +1 -0
- package/dist/wallets/groups/encrypt.d.ts +26 -0
- package/dist/wallets/groups/encrypt.d.ts.map +1 -0
- package/dist/wallets/groups/encrypt.js +52 -0
- package/dist/wallets/groups/encrypt.js.map +1 -0
- package/dist/wallets/groups/generate.d.ts +19 -0
- package/dist/wallets/groups/generate.d.ts.map +1 -0
- package/dist/wallets/groups/generate.js +36 -0
- package/dist/wallets/groups/generate.js.map +1 -0
- package/dist/wallets/groups/store.d.ts +107 -0
- package/dist/wallets/groups/store.d.ts.map +1 -0
- package/dist/wallets/groups/store.js +254 -0
- package/dist/wallets/groups/store.js.map +1 -0
- package/package.json +50 -0
- package/skills/SKILL.md +187 -0
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DataStore — local JSON store at ~/.fourmm/data/.
|
|
3
|
+
*
|
|
4
|
+
* Responsibilities:
|
|
5
|
+
* - Persist token metadata, pool info, transaction history, holdings, balances
|
|
6
|
+
* - Atomic writes (write .tmp, rename) to avoid half-written files
|
|
7
|
+
* - Memory cache per key with TTL (default 30s)
|
|
8
|
+
*
|
|
9
|
+
* What it does NOT do:
|
|
10
|
+
* - Cross-process locking. CLI is single-process; parallel invocations
|
|
11
|
+
* can race on writes. If Week 3 Router daemons need parallel writes we
|
|
12
|
+
* add a lockfile then.
|
|
13
|
+
* - Pretty printing control / schema migration (we'll version if needed).
|
|
14
|
+
*
|
|
15
|
+
* Public surface is a class with a singleton accessor so tests can inject
|
|
16
|
+
* a fresh instance. Paths come from datastore/paths.ts which reads HOME
|
|
17
|
+
* lazily, so redirecting HOME per test works.
|
|
18
|
+
*/
|
|
19
|
+
import fs from 'node:fs';
|
|
20
|
+
import path from 'node:path';
|
|
21
|
+
import { MemoryCache } from './cache.js';
|
|
22
|
+
import { balancesPath, bnbPricePath, globalDir, groupDir, holdingsPath, poolInfoPath, tokenDir, tokenInfoPath, tokensRoot, transactionsPath, } from './paths.js';
|
|
23
|
+
// Re-export types so consumers only need one import path
|
|
24
|
+
export * from './types.js';
|
|
25
|
+
export { MemoryCache } from './cache.js';
|
|
26
|
+
// ============================================================
|
|
27
|
+
// Internal helpers
|
|
28
|
+
// ============================================================
|
|
29
|
+
function atomicWriteJson(filePath, data) {
|
|
30
|
+
const dir = path.dirname(filePath);
|
|
31
|
+
if (!fs.existsSync(dir)) {
|
|
32
|
+
fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
33
|
+
}
|
|
34
|
+
const tmpPath = `${filePath}.tmp`;
|
|
35
|
+
fs.writeFileSync(tmpPath, JSON.stringify(data, null, 2), {
|
|
36
|
+
encoding: 'utf-8',
|
|
37
|
+
mode: 0o600,
|
|
38
|
+
});
|
|
39
|
+
fs.renameSync(tmpPath, filePath);
|
|
40
|
+
}
|
|
41
|
+
function readJson(filePath) {
|
|
42
|
+
if (!fs.existsSync(filePath))
|
|
43
|
+
return null;
|
|
44
|
+
try {
|
|
45
|
+
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
46
|
+
return JSON.parse(raw);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// Corrupt file: let the caller decide whether to rewrite or error
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function validateCa(ca) {
|
|
54
|
+
if (!ca || ca.includes('/') || ca.includes('\\') || ca.includes('..')) {
|
|
55
|
+
throw new Error(`Invalid CA: "${ca}"`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// ============================================================
|
|
59
|
+
// DataStore
|
|
60
|
+
// ============================================================
|
|
61
|
+
export class DataStore {
|
|
62
|
+
cache;
|
|
63
|
+
constructor(ttlMs = 30_000) {
|
|
64
|
+
this.cache = new MemoryCache(ttlMs);
|
|
65
|
+
}
|
|
66
|
+
// ----- token-info.json -----
|
|
67
|
+
getTokenInfo(ca) {
|
|
68
|
+
validateCa(ca);
|
|
69
|
+
const key = `token:${ca}`;
|
|
70
|
+
const cached = this.cache.get(key);
|
|
71
|
+
if (cached)
|
|
72
|
+
return cached;
|
|
73
|
+
const data = readJson(tokenInfoPath(ca));
|
|
74
|
+
if (data)
|
|
75
|
+
this.cache.set(key, data);
|
|
76
|
+
return data;
|
|
77
|
+
}
|
|
78
|
+
saveTokenInfo(info) {
|
|
79
|
+
validateCa(info.ca);
|
|
80
|
+
atomicWriteJson(tokenInfoPath(info.ca), info);
|
|
81
|
+
this.cache.set(`token:${info.ca}`, info);
|
|
82
|
+
}
|
|
83
|
+
// ----- pool-info.json -----
|
|
84
|
+
getPoolInfo(ca) {
|
|
85
|
+
validateCa(ca);
|
|
86
|
+
const key = `pool:${ca}`;
|
|
87
|
+
const cached = this.cache.get(key);
|
|
88
|
+
if (cached)
|
|
89
|
+
return cached;
|
|
90
|
+
const data = readJson(poolInfoPath(ca));
|
|
91
|
+
if (data)
|
|
92
|
+
this.cache.set(key, data);
|
|
93
|
+
return data;
|
|
94
|
+
}
|
|
95
|
+
savePoolInfo(info) {
|
|
96
|
+
validateCa(info.ca);
|
|
97
|
+
atomicWriteJson(poolInfoPath(info.ca), info);
|
|
98
|
+
this.cache.set(`pool:${info.ca}`, info);
|
|
99
|
+
}
|
|
100
|
+
// ----- transactions.json -----
|
|
101
|
+
getTransactions(ca, groupId) {
|
|
102
|
+
validateCa(ca);
|
|
103
|
+
return readJson(transactionsPath(ca, groupId));
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Append a transaction to the group's history, deduped by txHash.
|
|
107
|
+
* Always reads fresh from disk (no cache) to avoid losing a concurrent append.
|
|
108
|
+
*/
|
|
109
|
+
appendTransaction(ca, groupId, tx) {
|
|
110
|
+
validateCa(ca);
|
|
111
|
+
const file = transactionsPath(ca, groupId);
|
|
112
|
+
let current = readJson(file);
|
|
113
|
+
if (!current) {
|
|
114
|
+
current = {
|
|
115
|
+
ca,
|
|
116
|
+
groupId,
|
|
117
|
+
transactions: [],
|
|
118
|
+
updatedAt: Date.now(),
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
// Dedupe by txHash
|
|
122
|
+
if (current.transactions.some((t) => t.txHash === tx.txHash)) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
current.transactions.push(tx);
|
|
126
|
+
current.updatedAt = Date.now();
|
|
127
|
+
atomicWriteJson(file, current);
|
|
128
|
+
}
|
|
129
|
+
// ----- holdings.json -----
|
|
130
|
+
getHoldings(ca, groupId) {
|
|
131
|
+
validateCa(ca);
|
|
132
|
+
const key = `holdings:${ca}:${groupId}`;
|
|
133
|
+
const cached = this.cache.get(key);
|
|
134
|
+
if (cached)
|
|
135
|
+
return cached;
|
|
136
|
+
const data = readJson(holdingsPath(ca, groupId));
|
|
137
|
+
if (data)
|
|
138
|
+
this.cache.set(key, data);
|
|
139
|
+
return data;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Upsert a single wallet's holding.
|
|
143
|
+
* Merges with existing (by walletAddress); creates the file if missing.
|
|
144
|
+
*/
|
|
145
|
+
updateHolding(ca, groupId, wallet, patch) {
|
|
146
|
+
validateCa(ca);
|
|
147
|
+
const file = holdingsPath(ca, groupId);
|
|
148
|
+
let current = readJson(file);
|
|
149
|
+
if (!current) {
|
|
150
|
+
current = { ca, groupId, wallets: [], updatedAt: Date.now() };
|
|
151
|
+
}
|
|
152
|
+
const idx = current.wallets.findIndex((w) => w.walletAddress === wallet);
|
|
153
|
+
if (idx === -1) {
|
|
154
|
+
const blank = {
|
|
155
|
+
walletAddress: wallet,
|
|
156
|
+
tokenBalance: 0,
|
|
157
|
+
avgBuyPrice: 0,
|
|
158
|
+
totalBought: 0,
|
|
159
|
+
totalSold: 0,
|
|
160
|
+
totalCostBnb: 0,
|
|
161
|
+
totalRevenueBnb: 0,
|
|
162
|
+
realizedPnl: 0,
|
|
163
|
+
...patch,
|
|
164
|
+
};
|
|
165
|
+
current.wallets.push(blank);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
current.wallets[idx] = { ...current.wallets[idx], ...patch };
|
|
169
|
+
}
|
|
170
|
+
current.updatedAt = Date.now();
|
|
171
|
+
atomicWriteJson(file, current);
|
|
172
|
+
this.cache.set(`holdings:${ca}:${groupId}`, current);
|
|
173
|
+
}
|
|
174
|
+
// ----- balances.json -----
|
|
175
|
+
getBalances(ca, groupId) {
|
|
176
|
+
validateCa(ca);
|
|
177
|
+
const key = `balances:${ca}:${groupId}`;
|
|
178
|
+
const cached = this.cache.get(key);
|
|
179
|
+
if (cached)
|
|
180
|
+
return cached;
|
|
181
|
+
const data = readJson(balancesPath(ca, groupId));
|
|
182
|
+
if (data)
|
|
183
|
+
this.cache.set(key, data);
|
|
184
|
+
return data;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Partial upsert of a single wallet's balance.
|
|
188
|
+
*
|
|
189
|
+
* IMPORTANT: patch semantics — any field you DON'T pass keeps its previous
|
|
190
|
+
* value. This avoids the bug where a BNB-only refresh would clobber a
|
|
191
|
+
* stored tokenBalance. `updatedAt` is always bumped to now.
|
|
192
|
+
*
|
|
193
|
+
* If the wallet has no existing row, missing fields default to 0.
|
|
194
|
+
*/
|
|
195
|
+
updateBalance(ca, groupId, walletAddress, patch) {
|
|
196
|
+
validateCa(ca);
|
|
197
|
+
const file = balancesPath(ca, groupId);
|
|
198
|
+
let current = readJson(file);
|
|
199
|
+
if (!current) {
|
|
200
|
+
current = { ca, groupId, balances: [], updatedAt: Date.now() };
|
|
201
|
+
}
|
|
202
|
+
const idx = current.balances.findIndex((b) => b.walletAddress === walletAddress);
|
|
203
|
+
const now = Date.now();
|
|
204
|
+
const base = idx >= 0
|
|
205
|
+
? current.balances[idx]
|
|
206
|
+
: {
|
|
207
|
+
walletAddress,
|
|
208
|
+
bnbBalance: 0,
|
|
209
|
+
tokenBalance: 0,
|
|
210
|
+
updatedAt: now,
|
|
211
|
+
};
|
|
212
|
+
const merged = {
|
|
213
|
+
...base,
|
|
214
|
+
...patch,
|
|
215
|
+
walletAddress,
|
|
216
|
+
updatedAt: now,
|
|
217
|
+
};
|
|
218
|
+
if (idx === -1)
|
|
219
|
+
current.balances.push(merged);
|
|
220
|
+
else
|
|
221
|
+
current.balances[idx] = merged;
|
|
222
|
+
current.updatedAt = now;
|
|
223
|
+
atomicWriteJson(file, current);
|
|
224
|
+
this.cache.set(`balances:${ca}:${groupId}`, current);
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Batch variant: apply a list of patches in one file write.
|
|
228
|
+
* Each patch must include `walletAddress` so we know which row to merge.
|
|
229
|
+
*/
|
|
230
|
+
updateBalancesBatch(ca, groupId, patches) {
|
|
231
|
+
if (patches.length === 0)
|
|
232
|
+
return;
|
|
233
|
+
validateCa(ca);
|
|
234
|
+
const file = balancesPath(ca, groupId);
|
|
235
|
+
let current = readJson(file);
|
|
236
|
+
if (!current) {
|
|
237
|
+
current = { ca, groupId, balances: [], updatedAt: Date.now() };
|
|
238
|
+
}
|
|
239
|
+
const now = Date.now();
|
|
240
|
+
const byAddr = new Map(current.balances.map((b) => [b.walletAddress, b]));
|
|
241
|
+
for (const patch of patches) {
|
|
242
|
+
const base = byAddr.get(patch.walletAddress) ?? {
|
|
243
|
+
walletAddress: patch.walletAddress,
|
|
244
|
+
bnbBalance: 0,
|
|
245
|
+
tokenBalance: 0,
|
|
246
|
+
updatedAt: now,
|
|
247
|
+
};
|
|
248
|
+
byAddr.set(patch.walletAddress, {
|
|
249
|
+
...base,
|
|
250
|
+
...patch,
|
|
251
|
+
walletAddress: patch.walletAddress,
|
|
252
|
+
updatedAt: now,
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
current.balances = Array.from(byAddr.values());
|
|
256
|
+
current.updatedAt = now;
|
|
257
|
+
atomicWriteJson(file, current);
|
|
258
|
+
this.cache.set(`balances:${ca}:${groupId}`, current);
|
|
259
|
+
}
|
|
260
|
+
// ----- global/bnb-price.json -----
|
|
261
|
+
getBnbPrice() {
|
|
262
|
+
const cached = this.cache.get('global:bnb-price');
|
|
263
|
+
if (cached)
|
|
264
|
+
return cached;
|
|
265
|
+
const data = readJson(bnbPricePath());
|
|
266
|
+
if (data)
|
|
267
|
+
this.cache.set('global:bnb-price', data);
|
|
268
|
+
return data;
|
|
269
|
+
}
|
|
270
|
+
saveBnbPrice(priceUsd) {
|
|
271
|
+
const file = { priceUsd, updatedAt: Date.now() };
|
|
272
|
+
if (!fs.existsSync(globalDir())) {
|
|
273
|
+
fs.mkdirSync(globalDir(), { recursive: true, mode: 0o700 });
|
|
274
|
+
}
|
|
275
|
+
atomicWriteJson(bnbPricePath(), file);
|
|
276
|
+
this.cache.set('global:bnb-price', file);
|
|
277
|
+
}
|
|
278
|
+
// ----- Directory listing -----
|
|
279
|
+
/**
|
|
280
|
+
* List all token CA directories we have data for.
|
|
281
|
+
*
|
|
282
|
+
* Excludes `NATIVE_BNB` (the sentinel CA used for BNB transfer history) so
|
|
283
|
+
* callers iterating "for each known token" don't hit version=0 reverts on
|
|
284
|
+
* the zero address.
|
|
285
|
+
*/
|
|
286
|
+
listTokens() {
|
|
287
|
+
const root = tokensRoot();
|
|
288
|
+
if (!fs.existsSync(root))
|
|
289
|
+
return [];
|
|
290
|
+
const NATIVE_BNB = '0x0000000000000000000000000000000000000000';
|
|
291
|
+
return fs
|
|
292
|
+
.readdirSync(root, { withFileTypes: true })
|
|
293
|
+
.filter((d) => d.isDirectory())
|
|
294
|
+
.map((d) => d.name)
|
|
295
|
+
.filter((addr) => addr.toLowerCase() !== NATIVE_BNB);
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* List the groups that have native BNB transfer history.
|
|
299
|
+
* Separate from `listTokens` so downstream monitor/PnL code can treat
|
|
300
|
+
* BNB history distinctly from token holdings.
|
|
301
|
+
*/
|
|
302
|
+
listNativeBnbGroups() {
|
|
303
|
+
const NATIVE_BNB = '0x0000000000000000000000000000000000000000';
|
|
304
|
+
return this.listGroups(NATIVE_BNB);
|
|
305
|
+
}
|
|
306
|
+
listGroups(ca) {
|
|
307
|
+
validateCa(ca);
|
|
308
|
+
const groupsRoot = path.join(tokenDir(ca), 'groups');
|
|
309
|
+
if (!fs.existsSync(groupsRoot))
|
|
310
|
+
return [];
|
|
311
|
+
return fs
|
|
312
|
+
.readdirSync(groupsRoot, { withFileTypes: true })
|
|
313
|
+
.filter((d) => d.isDirectory())
|
|
314
|
+
.map((d) => Number.parseInt(d.name, 10))
|
|
315
|
+
.filter((n) => Number.isInteger(n))
|
|
316
|
+
.sort((a, b) => a - b);
|
|
317
|
+
}
|
|
318
|
+
/** Ensure the group directory exists (useful before running a session) */
|
|
319
|
+
ensureGroupDir(ca, groupId) {
|
|
320
|
+
validateCa(ca);
|
|
321
|
+
const dir = groupDir(ca, groupId);
|
|
322
|
+
if (!fs.existsSync(dir)) {
|
|
323
|
+
fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
// ============================================================
|
|
328
|
+
// Singleton
|
|
329
|
+
// ============================================================
|
|
330
|
+
let _instance = null;
|
|
331
|
+
/** Get the global DataStore. Tests that need isolation should use `new DataStore()`. */
|
|
332
|
+
export function getDataStore() {
|
|
333
|
+
if (!_instance)
|
|
334
|
+
_instance = new DataStore();
|
|
335
|
+
return _instance;
|
|
336
|
+
}
|
|
337
|
+
/** Reset the singleton (test helper) */
|
|
338
|
+
export function resetDataStore() {
|
|
339
|
+
_instance = null;
|
|
340
|
+
}
|
|
341
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/datastore/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DataStore path construction.
|
|
3
|
+
*
|
|
4
|
+
* All functions are lazy (read HOME on each call) so tests can redirect
|
|
5
|
+
* without resetting modules. Lives under ~/.fourmm/data/.
|
|
6
|
+
*/
|
|
7
|
+
export declare function tokensRoot(): string;
|
|
8
|
+
export declare function tokenDir(ca: string): string;
|
|
9
|
+
export declare function tokenInfoPath(ca: string): string;
|
|
10
|
+
export declare function poolInfoPath(ca: string): string;
|
|
11
|
+
export declare function groupDir(ca: string, groupId: number): string;
|
|
12
|
+
export declare function transactionsPath(ca: string, groupId: number): string;
|
|
13
|
+
export declare function holdingsPath(ca: string, groupId: number): string;
|
|
14
|
+
export declare function balancesPath(ca: string, groupId: number): string;
|
|
15
|
+
export declare function globalDir(): string;
|
|
16
|
+
export declare function bnbPricePath(): string;
|
|
17
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/datastore/paths.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,wBAAgB,YAAY,IAAI,MAAM,CAErC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DataStore path construction.
|
|
3
|
+
*
|
|
4
|
+
* All functions are lazy (read HOME on each call) so tests can redirect
|
|
5
|
+
* without resetting modules. Lives under ~/.fourmm/data/.
|
|
6
|
+
*/
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import { dataDir } from '../lib/config.js';
|
|
9
|
+
export function tokensRoot() {
|
|
10
|
+
return path.join(dataDir(), 'tokens');
|
|
11
|
+
}
|
|
12
|
+
export function tokenDir(ca) {
|
|
13
|
+
return path.join(tokensRoot(), ca);
|
|
14
|
+
}
|
|
15
|
+
export function tokenInfoPath(ca) {
|
|
16
|
+
return path.join(tokenDir(ca), 'token-info.json');
|
|
17
|
+
}
|
|
18
|
+
export function poolInfoPath(ca) {
|
|
19
|
+
return path.join(tokenDir(ca), 'pool-info.json');
|
|
20
|
+
}
|
|
21
|
+
export function groupDir(ca, groupId) {
|
|
22
|
+
return path.join(tokenDir(ca), 'groups', String(groupId));
|
|
23
|
+
}
|
|
24
|
+
export function transactionsPath(ca, groupId) {
|
|
25
|
+
return path.join(groupDir(ca, groupId), 'transactions.json');
|
|
26
|
+
}
|
|
27
|
+
export function holdingsPath(ca, groupId) {
|
|
28
|
+
return path.join(groupDir(ca, groupId), 'holdings.json');
|
|
29
|
+
}
|
|
30
|
+
export function balancesPath(ca, groupId) {
|
|
31
|
+
return path.join(groupDir(ca, groupId), 'balances.json');
|
|
32
|
+
}
|
|
33
|
+
export function globalDir() {
|
|
34
|
+
return path.join(dataDir(), 'global');
|
|
35
|
+
}
|
|
36
|
+
export function bnbPricePath() {
|
|
37
|
+
return path.join(globalDir(), 'bnb-price.json');
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/datastore/paths.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAE1C,MAAM,UAAU,UAAU;IACxB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAA;AACvC,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,EAAU;IACjC,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,EAAE,CAAC,CAAA;AACpC,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,EAAU;IACtC,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,iBAAiB,CAAC,CAAA;AACnD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,EAAU;IACrC,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,gBAAgB,CAAC,CAAA;AAClD,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,EAAU,EAAE,OAAe;IAClD,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAA;AAC3D,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,EAAU,EAAE,OAAe;IAC1D,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,mBAAmB,CAAC,CAAA;AAC9D,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,EAAU,EAAE,OAAe;IACtD,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,eAAe,CAAC,CAAA;AAC1D,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,EAAU,EAAE,OAAe;IACtD,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,eAAe,CAAC,CAAA;AAC1D,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAA;AACvC,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,gBAAgB,CAAC,CAAA;AACjD,CAAC"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DataStore type definitions.
|
|
3
|
+
*
|
|
4
|
+
* File formats for ~/.fourmm/data/. Each type corresponds to a JSON file on
|
|
5
|
+
* disk. All timestamps are Unix milliseconds unless otherwise noted.
|
|
6
|
+
*/
|
|
7
|
+
import type { Address, Hash, Hex } from 'viem';
|
|
8
|
+
export type TokenVariant = 'standard' | 'anti-sniper-fee' | 'tax-token' | 'x-mode';
|
|
9
|
+
export type TokenInfoFile = {
|
|
10
|
+
ca: Address;
|
|
11
|
+
symbol: string;
|
|
12
|
+
name: string;
|
|
13
|
+
decimals: number;
|
|
14
|
+
creatorAddress: Address | '';
|
|
15
|
+
/** Four.meme internal version (1 or 2) */
|
|
16
|
+
version: 1 | 2;
|
|
17
|
+
/** Variant detected from template / feeSetting */
|
|
18
|
+
variant: TokenVariant;
|
|
19
|
+
/** Address of the TokenManager that owns this token (V1 or V2) */
|
|
20
|
+
tokenManager: Address;
|
|
21
|
+
/** Quote token — 0x0000... for BNB, else BEP20 address */
|
|
22
|
+
quote: Address;
|
|
23
|
+
/** Bonding curve top-pair or PancakeSwap LP after graduation */
|
|
24
|
+
pairAddress: Address | '';
|
|
25
|
+
/** Set once the bonding curve has graduated */
|
|
26
|
+
liquidityAdded: boolean;
|
|
27
|
+
/** Last update (Unix ms) */
|
|
28
|
+
updatedAt: number;
|
|
29
|
+
};
|
|
30
|
+
/** Trading path a token is currently on */
|
|
31
|
+
export type TradingPathKind = 'bonding-curve' | 'pancake';
|
|
32
|
+
export type PoolInfoFile = {
|
|
33
|
+
ca: Address;
|
|
34
|
+
pairAddress: Address | '';
|
|
35
|
+
/** Which trading path this data describes */
|
|
36
|
+
path: TradingPathKind;
|
|
37
|
+
/** BNB-denominated price (float) */
|
|
38
|
+
priceBnb: number;
|
|
39
|
+
/** USD price (may be 0 when BNB→USD oracle unavailable) */
|
|
40
|
+
priceUsd: number;
|
|
41
|
+
/** Bonding curve progress 0..1 (null after graduation) */
|
|
42
|
+
graduationProgress: number | null;
|
|
43
|
+
updatedAt: number;
|
|
44
|
+
};
|
|
45
|
+
export type TxType = 'buy' | 'sell' | 'transfer_in' | 'transfer_out' | 'turnover' | 'volume';
|
|
46
|
+
export type TransactionRecord = {
|
|
47
|
+
txHash: Hash;
|
|
48
|
+
txType: TxType;
|
|
49
|
+
/** Wallet that signed / was the primary subject */
|
|
50
|
+
walletAddress: Address;
|
|
51
|
+
tokenCA: Address;
|
|
52
|
+
/** Signed BNB delta: positive for buy, negative for sell */
|
|
53
|
+
amountBnb: number;
|
|
54
|
+
/** Signed token delta */
|
|
55
|
+
amountToken: number;
|
|
56
|
+
/** Derived execution price (BNB per token) */
|
|
57
|
+
pricePerToken: number;
|
|
58
|
+
/** Gas fee (BNB) */
|
|
59
|
+
fee: number;
|
|
60
|
+
blockNumber: number;
|
|
61
|
+
/** Block timestamp (Unix seconds) */
|
|
62
|
+
blockTime: number;
|
|
63
|
+
status: 'confirmed' | 'failed' | 'pending';
|
|
64
|
+
};
|
|
65
|
+
export type TransactionsFile = {
|
|
66
|
+
ca: Address;
|
|
67
|
+
groupId: number;
|
|
68
|
+
transactions: TransactionRecord[];
|
|
69
|
+
updatedAt: number;
|
|
70
|
+
};
|
|
71
|
+
export type WalletHolding = {
|
|
72
|
+
walletAddress: Address;
|
|
73
|
+
tokenBalance: number;
|
|
74
|
+
avgBuyPrice: number;
|
|
75
|
+
totalBought: number;
|
|
76
|
+
totalSold: number;
|
|
77
|
+
totalCostBnb: number;
|
|
78
|
+
totalRevenueBnb: number;
|
|
79
|
+
realizedPnl: number;
|
|
80
|
+
};
|
|
81
|
+
export type HoldingsFile = {
|
|
82
|
+
ca: Address;
|
|
83
|
+
groupId: number;
|
|
84
|
+
wallets: WalletHolding[];
|
|
85
|
+
updatedAt: number;
|
|
86
|
+
};
|
|
87
|
+
export type WalletBalance = {
|
|
88
|
+
walletAddress: Address;
|
|
89
|
+
bnbBalance: number;
|
|
90
|
+
tokenBalance: number;
|
|
91
|
+
updatedAt: number;
|
|
92
|
+
};
|
|
93
|
+
export type BalancesFile = {
|
|
94
|
+
ca: Address;
|
|
95
|
+
groupId: number;
|
|
96
|
+
balances: WalletBalance[];
|
|
97
|
+
updatedAt: number;
|
|
98
|
+
};
|
|
99
|
+
export type BnbPriceFile = {
|
|
100
|
+
priceUsd: number;
|
|
101
|
+
updatedAt: number;
|
|
102
|
+
};
|
|
103
|
+
/** Hex-encoded raw transaction input data (kept for audit / replay) */
|
|
104
|
+
export type RawTxData = Hex;
|
|
105
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/datastore/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/datastore/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Four.meme REST API authentication.
|
|
3
|
+
*
|
|
4
|
+
* Flow:
|
|
5
|
+
* 1. POST /v1/private/user/nonce/generate → get nonce
|
|
6
|
+
* 2. Sign message "You are sign in Meme {nonce}" with wallet private key
|
|
7
|
+
* 3. POST /v1/private/user/login/dex → get access_token
|
|
8
|
+
*
|
|
9
|
+
* The access_token is used for subsequent API calls (upload, create).
|
|
10
|
+
*/
|
|
11
|
+
import type { Hex } from 'viem';
|
|
12
|
+
export type AuthResult = {
|
|
13
|
+
accessToken: string;
|
|
14
|
+
walletAddress: string;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Authenticate with Four.meme and return an access token.
|
|
18
|
+
*/
|
|
19
|
+
export declare function authenticateFourmeme(privateKey: Hex, options?: {
|
|
20
|
+
fetchImpl?: typeof fetch | undefined;
|
|
21
|
+
}): Promise<AuthResult>;
|
|
22
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/fourmeme/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,MAAM,CAAA;AAI/B,MAAM,MAAM,UAAU,GAAG;IACvB,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;CACtB,CAAA;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,GAAG,EACf,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,OAAO,KAAK,GAAG,SAAS,CAAA;CAAO,GACrD,OAAO,CAAC,UAAU,CAAC,CAuErB"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Four.meme REST API authentication.
|
|
3
|
+
*
|
|
4
|
+
* Flow:
|
|
5
|
+
* 1. POST /v1/private/user/nonce/generate → get nonce
|
|
6
|
+
* 2. Sign message "You are sign in Meme {nonce}" with wallet private key
|
|
7
|
+
* 3. POST /v1/private/user/login/dex → get access_token
|
|
8
|
+
*
|
|
9
|
+
* The access_token is used for subsequent API calls (upload, create).
|
|
10
|
+
*/
|
|
11
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
12
|
+
import { loadConfig } from '../lib/config.js';
|
|
13
|
+
/**
|
|
14
|
+
* Authenticate with Four.meme and return an access token.
|
|
15
|
+
*/
|
|
16
|
+
export async function authenticateFourmeme(privateKey, options = {}) {
|
|
17
|
+
const fetchFn = options.fetchImpl ?? globalThis.fetch;
|
|
18
|
+
const config = loadConfig();
|
|
19
|
+
const apiBase = config.fourmemeApiUrl;
|
|
20
|
+
const account = privateKeyToAccount(privateKey);
|
|
21
|
+
const walletAddress = account.address;
|
|
22
|
+
// Step 1: Get nonce
|
|
23
|
+
const nonceRes = await fetchFn(`${apiBase}/v1/private/user/nonce/generate`, {
|
|
24
|
+
method: 'POST',
|
|
25
|
+
headers: { 'Content-Type': 'application/json' },
|
|
26
|
+
body: JSON.stringify({
|
|
27
|
+
accountAddress: walletAddress,
|
|
28
|
+
verifyType: 'LOGIN',
|
|
29
|
+
networkCode: 'BSC',
|
|
30
|
+
}),
|
|
31
|
+
});
|
|
32
|
+
if (!nonceRes.ok) {
|
|
33
|
+
throw new Error(`Four.meme nonce/generate failed: HTTP ${nonceRes.status}`);
|
|
34
|
+
}
|
|
35
|
+
const nonceJson = (await nonceRes.json());
|
|
36
|
+
if (nonceJson.code !== 0 || !nonceJson.data) {
|
|
37
|
+
throw new Error(`Four.meme nonce/generate error: ${JSON.stringify(nonceJson)}`);
|
|
38
|
+
}
|
|
39
|
+
const nonce = nonceJson.data;
|
|
40
|
+
// Step 2: Sign the nonce message
|
|
41
|
+
const message = `You are sign in Meme ${nonce}`;
|
|
42
|
+
const signature = await account.signMessage({ message });
|
|
43
|
+
// Step 3: Login (nested verifyInfo format per API docs 02-02-2026)
|
|
44
|
+
const loginRes = await fetchFn(`${apiBase}/v1/private/user/login/dex`, {
|
|
45
|
+
method: 'POST',
|
|
46
|
+
headers: { 'Content-Type': 'application/json' },
|
|
47
|
+
body: JSON.stringify({
|
|
48
|
+
region: 'WEB',
|
|
49
|
+
langType: 'EN',
|
|
50
|
+
loginIp: '',
|
|
51
|
+
inviteCode: '',
|
|
52
|
+
verifyInfo: {
|
|
53
|
+
address: walletAddress,
|
|
54
|
+
networkCode: 'BSC',
|
|
55
|
+
signature,
|
|
56
|
+
verifyType: 'LOGIN',
|
|
57
|
+
},
|
|
58
|
+
walletName: 'MetaMask',
|
|
59
|
+
}),
|
|
60
|
+
});
|
|
61
|
+
if (!loginRes.ok) {
|
|
62
|
+
const body = await loginRes.text().catch(() => '');
|
|
63
|
+
throw new Error(`Four.meme login/dex failed: HTTP ${loginRes.status} ${body}`);
|
|
64
|
+
}
|
|
65
|
+
const loginJson = (await loginRes.json());
|
|
66
|
+
if (loginJson.code !== 0) {
|
|
67
|
+
throw new Error(`Four.meme login error: ${JSON.stringify(loginJson)}`);
|
|
68
|
+
}
|
|
69
|
+
// API may return token as a plain string or as an object with access_token
|
|
70
|
+
const accessToken = typeof loginJson.data === 'string'
|
|
71
|
+
? loginJson.data
|
|
72
|
+
: (loginJson.data.access_token ?? loginJson.data.accessToken ?? '');
|
|
73
|
+
if (!accessToken) {
|
|
74
|
+
throw new Error('Four.meme login succeeded but no access_token returned');
|
|
75
|
+
}
|
|
76
|
+
return { accessToken, walletAddress };
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/fourmeme/auth.ts"],"names":[],"mappings":"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"}
|