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.
Files changed (151) hide show
  1. package/README.md +147 -0
  2. package/dist/bin.d.ts +9 -0
  3. package/dist/bin.d.ts.map +1 -0
  4. package/dist/bin.js +14 -0
  5. package/dist/bin.js.map +1 -0
  6. package/dist/cli.d.ts +319 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +25 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/commands/config.d.ts +35 -0
  11. package/dist/commands/config.d.ts.map +1 -0
  12. package/dist/commands/config.js +145 -0
  13. package/dist/commands/config.js.map +1 -0
  14. package/dist/commands/query.d.ts +51 -0
  15. package/dist/commands/query.d.ts.map +1 -0
  16. package/dist/commands/query.js +364 -0
  17. package/dist/commands/query.js.map +1 -0
  18. package/dist/commands/token.d.ts +55 -0
  19. package/dist/commands/token.d.ts.map +1 -0
  20. package/dist/commands/token.js +650 -0
  21. package/dist/commands/token.js.map +1 -0
  22. package/dist/commands/tools.d.ts +54 -0
  23. package/dist/commands/tools.d.ts.map +1 -0
  24. package/dist/commands/tools.js +499 -0
  25. package/dist/commands/tools.js.map +1 -0
  26. package/dist/commands/trade.d.ts +63 -0
  27. package/dist/commands/trade.d.ts.map +1 -0
  28. package/dist/commands/trade.js +933 -0
  29. package/dist/commands/trade.js.map +1 -0
  30. package/dist/commands/transfer.d.ts +51 -0
  31. package/dist/commands/transfer.d.ts.map +1 -0
  32. package/dist/commands/transfer.js +728 -0
  33. package/dist/commands/transfer.js.map +1 -0
  34. package/dist/commands/wallet.d.ts +111 -0
  35. package/dist/commands/wallet.d.ts.map +1 -0
  36. package/dist/commands/wallet.js +716 -0
  37. package/dist/commands/wallet.js.map +1 -0
  38. package/dist/contracts/erc20.d.ts +72 -0
  39. package/dist/contracts/erc20.d.ts.map +1 -0
  40. package/dist/contracts/erc20.js +55 -0
  41. package/dist/contracts/erc20.js.map +1 -0
  42. package/dist/contracts/fourmemeMmRouter.d.ts +68 -0
  43. package/dist/contracts/fourmemeMmRouter.d.ts.map +1 -0
  44. package/dist/contracts/fourmemeMmRouter.js +48 -0
  45. package/dist/contracts/fourmemeMmRouter.js.map +1 -0
  46. package/dist/contracts/pancakeRouter.d.ts +73 -0
  47. package/dist/contracts/pancakeRouter.d.ts.map +1 -0
  48. package/dist/contracts/pancakeRouter.js +50 -0
  49. package/dist/contracts/pancakeRouter.js.map +1 -0
  50. package/dist/contracts/tokenManager2.d.ts +193 -0
  51. package/dist/contracts/tokenManager2.d.ts.map +1 -0
  52. package/dist/contracts/tokenManager2.js +108 -0
  53. package/dist/contracts/tokenManager2.js.map +1 -0
  54. package/dist/contracts/tokenManagerHelper3.d.ts +118 -0
  55. package/dist/contracts/tokenManagerHelper3.d.ts.map +1 -0
  56. package/dist/contracts/tokenManagerHelper3.js +66 -0
  57. package/dist/contracts/tokenManagerHelper3.js.map +1 -0
  58. package/dist/datastore/cache.d.ts +20 -0
  59. package/dist/datastore/cache.d.ts.map +1 -0
  60. package/dist/datastore/cache.js +45 -0
  61. package/dist/datastore/cache.js.map +1 -0
  62. package/dist/datastore/index.d.ts +85 -0
  63. package/dist/datastore/index.d.ts.map +1 -0
  64. package/dist/datastore/index.js +341 -0
  65. package/dist/datastore/index.js.map +1 -0
  66. package/dist/datastore/paths.d.ts +17 -0
  67. package/dist/datastore/paths.d.ts.map +1 -0
  68. package/dist/datastore/paths.js +39 -0
  69. package/dist/datastore/paths.js.map +1 -0
  70. package/dist/datastore/types.d.ts +105 -0
  71. package/dist/datastore/types.d.ts.map +1 -0
  72. package/dist/datastore/types.js +8 -0
  73. package/dist/datastore/types.js.map +1 -0
  74. package/dist/fourmeme/auth.d.ts +22 -0
  75. package/dist/fourmeme/auth.d.ts.map +1 -0
  76. package/dist/fourmeme/auth.js +78 -0
  77. package/dist/fourmeme/auth.js.map +1 -0
  78. package/dist/fourmeme/create.d.ts +31 -0
  79. package/dist/fourmeme/create.d.ts.map +1 -0
  80. package/dist/fourmeme/create.js +111 -0
  81. package/dist/fourmeme/create.js.map +1 -0
  82. package/dist/fourmeme/upload.d.ts +16 -0
  83. package/dist/fourmeme/upload.d.ts.map +1 -0
  84. package/dist/fourmeme/upload.js +52 -0
  85. package/dist/fourmeme/upload.js.map +1 -0
  86. package/dist/lib/bundle.d.ts +51 -0
  87. package/dist/lib/bundle.d.ts.map +1 -0
  88. package/dist/lib/bundle.js +95 -0
  89. package/dist/lib/bundle.js.map +1 -0
  90. package/dist/lib/config.d.ts +58 -0
  91. package/dist/lib/config.d.ts.map +1 -0
  92. package/dist/lib/config.js +183 -0
  93. package/dist/lib/config.js.map +1 -0
  94. package/dist/lib/const.d.ts +165 -0
  95. package/dist/lib/const.d.ts.map +1 -0
  96. package/dist/lib/const.js +98 -0
  97. package/dist/lib/const.js.map +1 -0
  98. package/dist/lib/env.d.ts +14 -0
  99. package/dist/lib/env.d.ts.map +1 -0
  100. package/dist/lib/env.js +18 -0
  101. package/dist/lib/env.js.map +1 -0
  102. package/dist/lib/guards.d.ts +44 -0
  103. package/dist/lib/guards.d.ts.map +1 -0
  104. package/dist/lib/guards.js +65 -0
  105. package/dist/lib/guards.js.map +1 -0
  106. package/dist/lib/identify.d.ts +85 -0
  107. package/dist/lib/identify.d.ts.map +1 -0
  108. package/dist/lib/identify.js +88 -0
  109. package/dist/lib/identify.js.map +1 -0
  110. package/dist/lib/pricing.d.ts +62 -0
  111. package/dist/lib/pricing.d.ts.map +1 -0
  112. package/dist/lib/pricing.js +302 -0
  113. package/dist/lib/pricing.js.map +1 -0
  114. package/dist/lib/routing.d.ts +57 -0
  115. package/dist/lib/routing.d.ts.map +1 -0
  116. package/dist/lib/routing.js +67 -0
  117. package/dist/lib/routing.js.map +1 -0
  118. package/dist/lib/slippage.d.ts +29 -0
  119. package/dist/lib/slippage.d.ts.map +1 -0
  120. package/dist/lib/slippage.js +110 -0
  121. package/dist/lib/slippage.js.map +1 -0
  122. package/dist/lib/tracker.d.ts +68 -0
  123. package/dist/lib/tracker.d.ts.map +1 -0
  124. package/dist/lib/tracker.js +155 -0
  125. package/dist/lib/tracker.js.map +1 -0
  126. package/dist/lib/viem.d.ts +12 -0
  127. package/dist/lib/viem.d.ts.map +1 -0
  128. package/dist/lib/viem.js +44 -0
  129. package/dist/lib/viem.js.map +1 -0
  130. package/dist/lib/wallet-rows.d.ts +30 -0
  131. package/dist/lib/wallet-rows.d.ts.map +1 -0
  132. package/dist/lib/wallet-rows.js +9 -0
  133. package/dist/lib/wallet-rows.js.map +1 -0
  134. package/dist/lib/walletClient.d.ts +16 -0
  135. package/dist/lib/walletClient.d.ts.map +1 -0
  136. package/dist/lib/walletClient.js +26 -0
  137. package/dist/lib/walletClient.js.map +1 -0
  138. package/dist/wallets/groups/encrypt.d.ts +26 -0
  139. package/dist/wallets/groups/encrypt.d.ts.map +1 -0
  140. package/dist/wallets/groups/encrypt.js +52 -0
  141. package/dist/wallets/groups/encrypt.js.map +1 -0
  142. package/dist/wallets/groups/generate.d.ts +19 -0
  143. package/dist/wallets/groups/generate.d.ts.map +1 -0
  144. package/dist/wallets/groups/generate.js +36 -0
  145. package/dist/wallets/groups/generate.js.map +1 -0
  146. package/dist/wallets/groups/store.d.ts +107 -0
  147. package/dist/wallets/groups/store.d.ts.map +1 -0
  148. package/dist/wallets/groups/store.js +254 -0
  149. package/dist/wallets/groups/store.js.map +1 -0
  150. package/package.json +50 -0
  151. package/skills/SKILL.md +187 -0
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Token pricing.
3
+ *
4
+ * Dual-path:
5
+ * 1. Bonding curve (liquidityAdded=false) → read on-chain
6
+ * TokenManagerHelper3.getTokenInfo.lastPrice directly. No network round-trip
7
+ * to a third-party pricing API.
8
+ * 2. Graduated (liquidityAdded=true) → query GeckoTerminal
9
+ * (`/api/v2/networks/bsc/tokens/{address}`) for PancakeSwap-derived price.
10
+ *
11
+ * BNB→USD conversion uses CoinGecko's free simple-price endpoint, cached for
12
+ * 60 seconds in DataStore's global/bnb-price.json.
13
+ *
14
+ * All price outputs are in BNB per token (float). The raw on-chain lastPrice
15
+ * is BNB-wei per smallest-token-unit (18 decimals); for meme tokens the price
16
+ * is tiny (well below 1e-6 BNB), so converting via Number() is safe in
17
+ * practice. If Week 3 bot code cares about sub-wei precision we'll switch to
18
+ * BigInt-to-string formatting.
19
+ */
20
+ import type { Address, PublicClient } from 'viem';
21
+ import type { TradingPathKind } from '../datastore/types.js';
22
+ /**
23
+ * Where the price value came from (freshness axis).
24
+ *
25
+ * - `live` → just fetched from Helper3 or GeckoTerminal this invocation
26
+ * - `cache` → served from DataStore pool-info within TTL
27
+ * - `stale` → cache hit beyond TTL but upstream fetch failed (best-effort)
28
+ */
29
+ export type PriceOrigin = 'live' | 'cache' | 'stale';
30
+ export type TokenPrice = {
31
+ ca: Address;
32
+ priceBnb: number;
33
+ priceUsd: number;
34
+ /** Trading path: bonding-curve / pancake (static token property) */
35
+ path: TradingPathKind;
36
+ /** Freshness of this value */
37
+ origin: PriceOrigin;
38
+ /** Unix ms */
39
+ updatedAt: number;
40
+ liquidityAdded: boolean;
41
+ };
42
+ /**
43
+ * Get the current price of a Four.meme token.
44
+ *
45
+ * Cache-through: checks DataStore pool-info first; on miss or expiry,
46
+ * fetches live and writes back. Network failures are surfaced via
47
+ * throwing, but we fall back to cache if the fresh fetch fails and a stale
48
+ * value exists.
49
+ */
50
+ export declare function getTokenPrice(client: PublicClient, ca: Address, options?: {
51
+ fetchImpl?: typeof fetch | undefined;
52
+ }): Promise<TokenPrice>;
53
+ /**
54
+ * Get BNB → USD price with 60s cache.
55
+ *
56
+ * Primary source: on-chain PancakeSwap WBNB/USDT pair reserves (no external
57
+ * API dependency — uses the same viem client that's already working for RPC).
58
+ *
59
+ * Fallback: CoinGecko simple/price endpoint (may fail in restricted networks).
60
+ */
61
+ export declare function getBnbUsdPrice(clientOrFetch?: PublicClient | typeof fetch | undefined): Promise<number>;
62
+ //# sourceMappingURL=pricing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing.d.ts","sourceRoot":"","sources":["../../src/lib/pricing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,MAAM,CAAA;AAwBjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAE5D;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAA;AAEpD,MAAM,MAAM,UAAU,GAAG;IACvB,EAAE,EAAE,OAAO,CAAA;IACX,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,oEAAoE;IACpE,IAAI,EAAE,eAAe,CAAA;IACrB,8BAA8B;IAC9B,MAAM,EAAE,WAAW,CAAA;IACnB,cAAc;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,cAAc,EAAE,OAAO,CAAA;CACxB,CAAA;AAcD;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,YAAY,EACpB,EAAE,EAAE,OAAO,EACX,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,OAAO,KAAK,GAAG,SAAS,CAAA;CAAO,GACrD,OAAO,CAAC,UAAU,CAAC,CAmJrB;AAuCD;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,aAAa,CAAC,EAAE,YAAY,GAAG,OAAO,KAAK,GAAG,SAAS,GACtD,OAAO,CAAC,MAAM,CAAC,CA0DjB"}
@@ -0,0 +1,302 @@
1
+ /**
2
+ * Token pricing.
3
+ *
4
+ * Dual-path:
5
+ * 1. Bonding curve (liquidityAdded=false) → read on-chain
6
+ * TokenManagerHelper3.getTokenInfo.lastPrice directly. No network round-trip
7
+ * to a third-party pricing API.
8
+ * 2. Graduated (liquidityAdded=true) → query GeckoTerminal
9
+ * (`/api/v2/networks/bsc/tokens/{address}`) for PancakeSwap-derived price.
10
+ *
11
+ * BNB→USD conversion uses CoinGecko's free simple-price endpoint, cached for
12
+ * 60 seconds in DataStore's global/bnb-price.json.
13
+ *
14
+ * All price outputs are in BNB per token (float). The raw on-chain lastPrice
15
+ * is BNB-wei per smallest-token-unit (18 decimals); for meme tokens the price
16
+ * is tiny (well below 1e-6 BNB), so converting via Number() is safe in
17
+ * practice. If Week 3 bot code cares about sub-wei precision we'll switch to
18
+ * BigInt-to-string formatting.
19
+ */
20
+ import { TOKEN_MANAGER_HELPER3, PANCAKE_V2_FACTORY, WBNB } from './const.js';
21
+ import { tokenManagerHelper3Abi } from '../contracts/tokenManagerHelper3.js';
22
+ import { getDataStore } from '../datastore/index.js';
23
+ import { loadConfig } from './config.js';
24
+ // PancakeFactory getPair — to resolve LP pair address for graduated tokens
25
+ const pancakeFactoryAbi = [
26
+ {
27
+ type: 'function',
28
+ name: 'getPair',
29
+ stateMutability: 'view',
30
+ inputs: [
31
+ { name: 'tokenA', type: 'address' },
32
+ { name: 'tokenB', type: 'address' },
33
+ ],
34
+ outputs: [{ name: 'pair', type: 'address' }],
35
+ },
36
+ ];
37
+ // ============================================================
38
+ // Constants
39
+ // ============================================================
40
+ const BNB_DECIMALS = 18;
41
+ const POOL_CACHE_TTL_MS = 30_000;
42
+ const BNB_PRICE_TTL_MS = 60_000;
43
+ // ============================================================
44
+ // Public API
45
+ // ============================================================
46
+ /**
47
+ * Get the current price of a Four.meme token.
48
+ *
49
+ * Cache-through: checks DataStore pool-info first; on miss or expiry,
50
+ * fetches live and writes back. Network failures are surfaced via
51
+ * throwing, but we fall back to cache if the fresh fetch fails and a stale
52
+ * value exists.
53
+ */
54
+ export async function getTokenPrice(client, ca, options = {}) {
55
+ const ds = getDataStore();
56
+ // Check cached pool-info first
57
+ const cached = ds.getPoolInfo(ca);
58
+ const now = Date.now();
59
+ if (cached && now - cached.updatedAt < POOL_CACHE_TTL_MS) {
60
+ return {
61
+ ca,
62
+ priceBnb: cached.priceBnb,
63
+ priceUsd: cached.priceUsd,
64
+ path: cached.path,
65
+ origin: 'cache',
66
+ updatedAt: cached.updatedAt,
67
+ liquidityAdded: cached.path === 'pancake',
68
+ };
69
+ }
70
+ // Hit Helper3 to learn graduation status + on-chain lastPrice
71
+ let info;
72
+ try {
73
+ info = await client.readContract({
74
+ address: TOKEN_MANAGER_HELPER3,
75
+ abi: tokenManagerHelper3Abi,
76
+ functionName: 'getTokenInfo',
77
+ args: [ca],
78
+ });
79
+ }
80
+ catch (err) {
81
+ if (cached) {
82
+ // Fresh fetch failed — return the stale cache we have
83
+ return {
84
+ ca,
85
+ priceBnb: cached.priceBnb,
86
+ priceUsd: cached.priceUsd,
87
+ path: cached.path,
88
+ origin: 'stale',
89
+ updatedAt: cached.updatedAt,
90
+ liquidityAdded: cached.path === 'pancake',
91
+ };
92
+ }
93
+ throw new Error(`pricing.getTokenPrice(${ca}): Helper3 read failed${err instanceof Error ? `: ${err.message}` : ''}`);
94
+ }
95
+ const version = info[0];
96
+ const lastPrice = info[3];
97
+ const liquidityAdded = info[11];
98
+ if (version === 0n) {
99
+ throw new Error(`pricing.getTokenPrice(${ca}): token not found on Four.meme`);
100
+ }
101
+ // ---- Branch 1: bonding curve ----
102
+ if (!liquidityAdded) {
103
+ const priceBnb = Number(lastPrice) / 10 ** BNB_DECIMALS;
104
+ const bnbUsd = await getBnbUsdPrice(client).catch(() => 0);
105
+ const priceUsd = priceBnb * bnbUsd;
106
+ ds.savePoolInfo({
107
+ ca,
108
+ pairAddress: '',
109
+ path: 'bonding-curve',
110
+ priceBnb,
111
+ priceUsd,
112
+ graduationProgress: null,
113
+ updatedAt: now,
114
+ });
115
+ return {
116
+ ca,
117
+ priceBnb,
118
+ priceUsd,
119
+ path: 'bonding-curve',
120
+ origin: 'live',
121
+ updatedAt: now,
122
+ liquidityAdded: false,
123
+ };
124
+ }
125
+ // ---- Branch 2: graduated → GeckoTerminal ----
126
+ const gecko = await fetchGeckoTerminalPrice(ca, options.fetchImpl).catch(() => null);
127
+ if (!gecko) {
128
+ if (cached) {
129
+ return {
130
+ ca,
131
+ priceBnb: cached.priceBnb,
132
+ priceUsd: cached.priceUsd,
133
+ path: cached.path,
134
+ origin: 'stale',
135
+ updatedAt: cached.updatedAt,
136
+ liquidityAdded: true,
137
+ };
138
+ }
139
+ throw new Error(`pricing.getTokenPrice(${ca}): token has graduated but GeckoTerminal fetch failed`);
140
+ }
141
+ const bnbUsd = await getBnbUsdPrice(client).catch(() => 0);
142
+ const priceUsd = gecko.priceUsd;
143
+ // Convert USD → BNB when we know the BNB price
144
+ const priceBnb = bnbUsd > 0 ? priceUsd / bnbUsd : 0;
145
+ // Resolve PancakeSwap LP pair address so `query kline` can auto-resolve it
146
+ let pairAddress = '';
147
+ try {
148
+ const pair = await client.readContract({
149
+ address: PANCAKE_V2_FACTORY,
150
+ abi: pancakeFactoryAbi,
151
+ functionName: 'getPair',
152
+ args: [ca, WBNB],
153
+ });
154
+ if (pair && pair !== '0x0000000000000000000000000000000000000000') {
155
+ pairAddress = pair;
156
+ }
157
+ }
158
+ catch {
159
+ // Factory query failed — pairAddress stays empty, kline needs --pool
160
+ }
161
+ ds.savePoolInfo({
162
+ ca,
163
+ pairAddress,
164
+ path: 'pancake',
165
+ priceBnb,
166
+ priceUsd,
167
+ graduationProgress: null,
168
+ updatedAt: now,
169
+ });
170
+ return {
171
+ ca,
172
+ priceBnb,
173
+ priceUsd,
174
+ path: 'pancake',
175
+ origin: 'live',
176
+ updatedAt: now,
177
+ liquidityAdded: true,
178
+ };
179
+ }
180
+ // ============================================================
181
+ // BNB / USD price (CoinGecko)
182
+ // ============================================================
183
+ /**
184
+ * Get BNB → USD price with 60s cache.
185
+ *
186
+ * We use CoinGecko's public `simple/price` endpoint (no auth). If it fails
187
+ * or is rate-limited, we return the cached value if present, else 0 (so the
188
+ * rest of the pipeline still returns a priceBnb but priceUsd will be 0).
189
+ */
190
+ // PancakeSwap WBNB/USDT pair — used for on-chain BNB/USD pricing
191
+ // This avoids depending on external APIs (CoinGecko/GeckoTerminal) that
192
+ // may be unreachable from certain environments (e.g. WSL2 TLS issues).
193
+ const PANCAKE_WBNB_USDT_PAIR = '0x16b9a82891338f9ba80e2d6970fdda79d1eb0dae';
194
+ const pairReservesAbi = [
195
+ {
196
+ type: 'function',
197
+ name: 'getReserves',
198
+ stateMutability: 'view',
199
+ inputs: [],
200
+ outputs: [
201
+ { name: 'reserve0', type: 'uint112' },
202
+ { name: 'reserve1', type: 'uint112' },
203
+ { name: 'blockTimestampLast', type: 'uint32' },
204
+ ],
205
+ },
206
+ {
207
+ type: 'function',
208
+ name: 'token0',
209
+ stateMutability: 'view',
210
+ inputs: [],
211
+ outputs: [{ name: '', type: 'address' }],
212
+ },
213
+ ];
214
+ /**
215
+ * Get BNB → USD price with 60s cache.
216
+ *
217
+ * Primary source: on-chain PancakeSwap WBNB/USDT pair reserves (no external
218
+ * API dependency — uses the same viem client that's already working for RPC).
219
+ *
220
+ * Fallback: CoinGecko simple/price endpoint (may fail in restricted networks).
221
+ */
222
+ export async function getBnbUsdPrice(clientOrFetch) {
223
+ const ds = getDataStore();
224
+ const cached = ds.getBnbPrice();
225
+ const now = Date.now();
226
+ if (cached && now - cached.updatedAt < BNB_PRICE_TTL_MS) {
227
+ return cached.priceUsd;
228
+ }
229
+ // Try on-chain first: read PancakeSwap WBNB/USDT reserves
230
+ if (clientOrFetch && typeof clientOrFetch === 'object' && 'readContract' in clientOrFetch) {
231
+ const client = clientOrFetch;
232
+ try {
233
+ const token0 = await client.readContract({
234
+ address: PANCAKE_WBNB_USDT_PAIR,
235
+ abi: pairReservesAbi,
236
+ functionName: 'token0',
237
+ });
238
+ const [reserve0, reserve1] = await client.readContract({
239
+ address: PANCAKE_WBNB_USDT_PAIR,
240
+ abi: pairReservesAbi,
241
+ functionName: 'getReserves',
242
+ });
243
+ // Determine which reserve is WBNB and which is USDT
244
+ const wbnbLower = WBNB.toLowerCase();
245
+ const isToken0Wbnb = token0.toLowerCase() === wbnbLower;
246
+ const wbnbReserve = isToken0Wbnb ? reserve0 : reserve1;
247
+ const usdtReserve = isToken0Wbnb ? reserve1 : reserve0;
248
+ // WBNB = 18 decimals, USDT = 18 decimals on BSC
249
+ if (wbnbReserve > 0n) {
250
+ const price = Number(usdtReserve) / Number(wbnbReserve);
251
+ if (price > 0) {
252
+ ds.saveBnbPrice(price);
253
+ return price;
254
+ }
255
+ }
256
+ }
257
+ catch {
258
+ // On-chain query failed — try API fallback
259
+ }
260
+ }
261
+ // Fallback: CoinGecko API
262
+ try {
263
+ const fetchFn = (typeof clientOrFetch === 'function' ? clientOrFetch : globalThis.fetch);
264
+ const res = await fetchFn('https://api.coingecko.com/api/v3/simple/price?ids=binancecoin&vs_currencies=usd');
265
+ if (!res.ok)
266
+ return cached?.priceUsd ?? 0;
267
+ const json = (await res.json());
268
+ const price = json.binancecoin?.usd;
269
+ if (typeof price === 'number' && price > 0) {
270
+ ds.saveBnbPrice(price);
271
+ return price;
272
+ }
273
+ }
274
+ catch {
275
+ // API also failed
276
+ }
277
+ return cached?.priceUsd ?? 0;
278
+ }
279
+ async function fetchGeckoTerminalPrice(ca, fetchImpl) {
280
+ const fetchFn = fetchImpl ?? globalThis.fetch;
281
+ const config = loadConfig();
282
+ const url = `${config.geckoTerminalUrl}/networks/bsc/tokens/${ca}`;
283
+ try {
284
+ const res = await fetchFn(url, {
285
+ headers: { accept: 'application/json' },
286
+ });
287
+ if (!res.ok)
288
+ return null;
289
+ const json = (await res.json());
290
+ const raw = json.data?.attributes?.price_usd;
291
+ if (!raw)
292
+ return null;
293
+ const priceUsd = Number.parseFloat(raw);
294
+ if (!Number.isFinite(priceUsd) || priceUsd <= 0)
295
+ return null;
296
+ return { priceUsd };
297
+ }
298
+ catch {
299
+ return null;
300
+ }
301
+ }
302
+ //# sourceMappingURL=pricing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing.js","sourceRoot":"","sources":["../../src/lib/pricing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Trading path resolution.
3
+ *
4
+ * Every trade / tools command MUST call `resolveTradingPath(client, ca)`
5
+ * before any on-chain write. The result tells the caller which contract
6
+ * interface to use (bonding-curve TokenManager2 vs graduated PancakeSwap
7
+ * router) AND exposes the raw Helper3.getTokenInfo result so downstream
8
+ * code can reuse fields (launchTime, offers, funds, etc.) without firing
9
+ * another RPC call.
10
+ *
11
+ * This is the single source of truth for routing — do NOT hardcode
12
+ * TOKEN_MANAGER_V2 anywhere else.
13
+ */
14
+ import type { Address, PublicClient, ReadContractReturnType } from 'viem';
15
+ import { tokenManagerHelper3Abi } from '../contracts/tokenManagerHelper3.js';
16
+ /** The raw tuple that Helper3.getTokenInfo returns */
17
+ export type GetTokenInfoResult = ReadContractReturnType<typeof tokenManagerHelper3Abi, 'getTokenInfo'>;
18
+ export type BondingCurvePath = {
19
+ path: 'bonding-curve';
20
+ /** The V1 or V2 TokenManager that owns this token — use this, not a hardcoded address */
21
+ router: Address;
22
+ version: 1 | 2;
23
+ /** Quote token (address(0) = BNB) */
24
+ quote: Address;
25
+ };
26
+ export type PancakePath = {
27
+ path: 'pancake';
28
+ /** PancakeSwap V2 router on BSC mainnet */
29
+ router: Address;
30
+ /** LP pair address if known (0x0 for now; Week 3 will resolve from factory) */
31
+ pairAddress: Address | '0x0000000000000000000000000000000000000000';
32
+ /** Quote token — always BNB for Four.meme graduated tokens */
33
+ quote: Address;
34
+ };
35
+ export type TradingPath = BondingCurvePath | PancakePath;
36
+ /**
37
+ * Full result of a routing call: the chosen path PLUS the raw Helper3 info
38
+ * tuple the caller can reuse. Downstream code reads:
39
+ * - `rawInfo[6]` launchTime (for tradeable check)
40
+ * - `rawInfo[7]` offers
41
+ * - `rawInfo[8]` maxOffers
42
+ * - `rawInfo[9]` funds
43
+ * - `rawInfo[10]` maxFunds
44
+ */
45
+ export type ResolveResult = {
46
+ tradingPath: TradingPath;
47
+ rawInfo: GetTokenInfoResult;
48
+ };
49
+ /**
50
+ * Inspect a token's on-chain state and pick the correct trading path.
51
+ *
52
+ * Throws on a malformed / unknown token (version 0). Callers should wrap
53
+ * this in the command's error handler so the agent gets a structured error
54
+ * instead of a viem revert trace.
55
+ */
56
+ export declare function resolveTradingPath(client: PublicClient, ca: Address): Promise<ResolveResult>;
57
+ //# sourceMappingURL=routing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../../src/lib/routing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,MAAM,CAAA;AAEzE,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAA;AAM5E,sDAAsD;AACtD,MAAM,MAAM,kBAAkB,GAAG,sBAAsB,CACrD,OAAO,sBAAsB,EAC7B,cAAc,CACf,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,eAAe,CAAA;IACrB,yFAAyF;IACzF,MAAM,EAAE,OAAO,CAAA;IACf,OAAO,EAAE,CAAC,GAAG,CAAC,CAAA;IACd,qCAAqC;IACrC,KAAK,EAAE,OAAO,CAAA;CACf,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,SAAS,CAAA;IACf,2CAA2C;IAC3C,MAAM,EAAE,OAAO,CAAA;IACf,+EAA+E;IAC/E,WAAW,EAAE,OAAO,GAAG,4CAA4C,CAAA;IACnE,8DAA8D;IAC9D,KAAK,EAAE,OAAO,CAAA;CACf,CAAA;AAED,MAAM,MAAM,WAAW,GAAG,gBAAgB,GAAG,WAAW,CAAA;AAExD;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,WAAW,EAAE,WAAW,CAAA;IACxB,OAAO,EAAE,kBAAkB,CAAA;CAC5B,CAAA;AAMD;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,YAAY,EACpB,EAAE,EAAE,OAAO,GACV,OAAO,CAAC,aAAa,CAAC,CAgDxB"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Trading path resolution.
3
+ *
4
+ * Every trade / tools command MUST call `resolveTradingPath(client, ca)`
5
+ * before any on-chain write. The result tells the caller which contract
6
+ * interface to use (bonding-curve TokenManager2 vs graduated PancakeSwap
7
+ * router) AND exposes the raw Helper3.getTokenInfo result so downstream
8
+ * code can reuse fields (launchTime, offers, funds, etc.) without firing
9
+ * another RPC call.
10
+ *
11
+ * This is the single source of truth for routing — do NOT hardcode
12
+ * TOKEN_MANAGER_V2 anywhere else.
13
+ */
14
+ import { PANCAKE_V2_ROUTER, TOKEN_MANAGER_HELPER3 } from './const.js';
15
+ import { tokenManagerHelper3Abi } from '../contracts/tokenManagerHelper3.js';
16
+ // ============================================================
17
+ // Public API
18
+ // ============================================================
19
+ /**
20
+ * Inspect a token's on-chain state and pick the correct trading path.
21
+ *
22
+ * Throws on a malformed / unknown token (version 0). Callers should wrap
23
+ * this in the command's error handler so the agent gets a structured error
24
+ * instead of a viem revert trace.
25
+ */
26
+ export async function resolveTradingPath(client, ca) {
27
+ let info;
28
+ try {
29
+ info = await client.readContract({
30
+ address: TOKEN_MANAGER_HELPER3,
31
+ abi: tokenManagerHelper3Abi,
32
+ functionName: 'getTokenInfo',
33
+ args: [ca],
34
+ });
35
+ }
36
+ catch (err) {
37
+ throw new Error(`resolveTradingPath(${ca}): Helper3 read failed${err instanceof Error ? `: ${err.message}` : ''}`);
38
+ }
39
+ const version = info[0];
40
+ const tokenManager = info[1];
41
+ const quote = info[2];
42
+ const liquidityAdded = info[11];
43
+ if (version === 0n) {
44
+ throw new Error(`resolveTradingPath(${ca}): token not registered with Four.meme TokenManager`);
45
+ }
46
+ let tradingPath;
47
+ if (liquidityAdded) {
48
+ tradingPath = {
49
+ path: 'pancake',
50
+ router: PANCAKE_V2_ROUTER,
51
+ // Pair lookup is Week 3 — Router uses factory.getPair at tx build time
52
+ pairAddress: '0x0000000000000000000000000000000000000000',
53
+ quote,
54
+ };
55
+ }
56
+ else {
57
+ const normalized = version === 1n ? 1 : 2;
58
+ tradingPath = {
59
+ path: 'bonding-curve',
60
+ router: tokenManager,
61
+ version: normalized,
62
+ quote,
63
+ };
64
+ }
65
+ return { tradingPath, rawInfo: info };
66
+ }
67
+ //# sourceMappingURL=routing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing.js","sourceRoot":"","sources":["../../src/lib/routing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AACrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAA;AA+C5E,+DAA+D;AAC/D,aAAa;AACb,+DAA+D;AAE/D;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,MAAoB,EACpB,EAAW;IAEX,IAAI,IAAwB,CAAA;IAC5B,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC;YAC/B,OAAO,EAAE,qBAAqB;YAC9B,GAAG,EAAE,sBAAsB;YAC3B,YAAY,EAAE,cAAc;YAC5B,IAAI,EAAE,CAAC,EAAE,CAAC;SACX,CAAC,CAAA;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,sBAAsB,EAAE,yBACtB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAC9C,EAAE,CACH,CAAA;IACH,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;IACvB,MAAM,YAAY,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;IAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;IACrB,MAAM,cAAc,GAAG,IAAI,CAAC,EAAE,CAAC,CAAA;IAE/B,IAAI,OAAO,KAAK,EAAE,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CACb,sBAAsB,EAAE,qDAAqD,CAC9E,CAAA;IACH,CAAC;IAED,IAAI,WAAwB,CAAA;IAC5B,IAAI,cAAc,EAAE,CAAC;QACnB,WAAW,GAAG;YACZ,IAAI,EAAE,SAAS;YACf,MAAM,EAAE,iBAAiB;YACzB,uEAAuE;YACvE,WAAW,EAAE,4CAA4C;YACzD,KAAK;SACN,CAAA;IACH,CAAC;SAAM,CAAC;QACN,MAAM,UAAU,GAAU,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAChD,WAAW,GAAG;YACZ,IAAI,EAAE,eAAe;YACrB,MAAM,EAAE,YAAY;YACpB,OAAO,EAAE,UAAU;YACnB,KAAK;SACN,CAAA;IACH,CAAC;IAED,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;AACvC,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Slippage calculation helpers for Router calls.
3
+ *
4
+ * Two paths:
5
+ * - Bonding curve: uses Helper3.tryBuy to estimate output
6
+ * - PancakeSwap (graduated): uses PancakeRouter.getAmountsOut
7
+ *
8
+ * Without proper minimums, passing 0n makes every tx fully sandwichable.
9
+ */
10
+ import type { Address, PublicClient } from 'viem';
11
+ /**
12
+ * Compute slippage-protected minimums for volume (buy+sell round-trip).
13
+ *
14
+ * Tries bonding-curve estimation first (tryBuy). If that fails (token has
15
+ * graduated), falls back to PancakeSwap getAmountsOut. If both fail,
16
+ * returns 0n (no protection — last resort).
17
+ */
18
+ export declare function computeVolumeSlippage(client: PublicClient, token: Address, bnbWei: bigint, slippageBps: number): Promise<{
19
+ minTokenOut: bigint;
20
+ minBnbBack: bigint;
21
+ }>;
22
+ /**
23
+ * Compute minTokenOut for a turnover (buy-only, no sell leg).
24
+ * Same dual-path logic as computeVolumeSlippage but only the buy side.
25
+ */
26
+ export declare function computeTurnoverSlippage(client: PublicClient, token: Address, bnbWei: bigint, slippageBps: number): Promise<{
27
+ minTokenOut: bigint;
28
+ }>;
29
+ //# sourceMappingURL=slippage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slippage.d.ts","sourceRoot":"","sources":["../../src/lib/slippage.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,MAAM,CAAA;AAkBjD;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CA4CtD;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CA6BlC"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Slippage calculation helpers for Router calls.
3
+ *
4
+ * Two paths:
5
+ * - Bonding curve: uses Helper3.tryBuy to estimate output
6
+ * - PancakeSwap (graduated): uses PancakeRouter.getAmountsOut
7
+ *
8
+ * Without proper minimums, passing 0n makes every tx fully sandwichable.
9
+ */
10
+ import { TOKEN_MANAGER_HELPER3, PANCAKE_V2_ROUTER, WBNB } from './const.js';
11
+ import { tokenManagerHelper3Abi } from '../contracts/tokenManagerHelper3.js';
12
+ // PancakeSwap getAmountsOut ABI (just what we need)
13
+ const pancakeGetAmountsOutAbi = [
14
+ {
15
+ type: 'function',
16
+ name: 'getAmountsOut',
17
+ stateMutability: 'view',
18
+ inputs: [
19
+ { name: 'amountIn', type: 'uint256' },
20
+ { name: 'path', type: 'address[]' },
21
+ ],
22
+ outputs: [{ name: 'amounts', type: 'uint256[]' }],
23
+ },
24
+ ];
25
+ /**
26
+ * Compute slippage-protected minimums for volume (buy+sell round-trip).
27
+ *
28
+ * Tries bonding-curve estimation first (tryBuy). If that fails (token has
29
+ * graduated), falls back to PancakeSwap getAmountsOut. If both fail,
30
+ * returns 0n (no protection — last resort).
31
+ */
32
+ export async function computeVolumeSlippage(client, token, bnbWei, slippageBps) {
33
+ const slipBig = BigInt(slippageBps);
34
+ // --- Try bonding curve first ---
35
+ let minTokenOut = 0n;
36
+ let usedPancake = false;
37
+ try {
38
+ const result = await client.readContract({
39
+ address: TOKEN_MANAGER_HELPER3,
40
+ abi: tokenManagerHelper3Abi,
41
+ functionName: 'tryBuy',
42
+ args: [token, 0n, bnbWei],
43
+ });
44
+ const estimatedTokens = result[2];
45
+ minTokenOut = (estimatedTokens * (10000n - slipBig)) / 10000n;
46
+ }
47
+ catch {
48
+ // tryBuy failed — token is likely graduated. Try PancakeSwap.
49
+ try {
50
+ const amounts = await client.readContract({
51
+ address: PANCAKE_V2_ROUTER,
52
+ abi: pancakeGetAmountsOutAbi,
53
+ functionName: 'getAmountsOut',
54
+ args: [bnbWei, [WBNB, token]],
55
+ });
56
+ if (amounts.length >= 2) {
57
+ const estimatedTokens = amounts[1];
58
+ minTokenOut = (estimatedTokens * (10000n - slipBig)) / 10000n;
59
+ usedPancake = true;
60
+ }
61
+ }
62
+ catch {
63
+ // Both paths failed — throw so callers refuse to send an unprotected tx
64
+ throw new Error('Slippage estimation failed: neither bonding-curve tryBuy nor PancakeSwap getAmountsOut returned a quote. Refusing to send tx with 0 slippage protection.');
65
+ }
66
+ }
67
+ // For the sell leg: estimate how much BNB we'd get back after a round-trip.
68
+ // Bonding curve: ~2.5% round-trip fee. PancakeSwap: ~0.5% LP fee × 2 = 1%.
69
+ const estimatedFeeBps = usedPancake ? 150n : 250n;
70
+ const totalDiscountBps = slipBig + estimatedFeeBps;
71
+ const effectiveBps = totalDiscountBps > 10000n ? 10000n : totalDiscountBps;
72
+ const minBnbBack = (bnbWei * (10000n - effectiveBps)) / 10000n;
73
+ return { minTokenOut, minBnbBack };
74
+ }
75
+ /**
76
+ * Compute minTokenOut for a turnover (buy-only, no sell leg).
77
+ * Same dual-path logic as computeVolumeSlippage but only the buy side.
78
+ */
79
+ export async function computeTurnoverSlippage(client, token, bnbWei, slippageBps) {
80
+ const slipBig = BigInt(slippageBps);
81
+ // Try bonding curve
82
+ try {
83
+ const result = await client.readContract({
84
+ address: TOKEN_MANAGER_HELPER3,
85
+ abi: tokenManagerHelper3Abi,
86
+ functionName: 'tryBuy',
87
+ args: [token, 0n, bnbWei],
88
+ });
89
+ return { minTokenOut: (result[2] * (10000n - slipBig)) / 10000n };
90
+ }
91
+ catch {
92
+ // Fallback: PancakeSwap
93
+ try {
94
+ const amounts = await client.readContract({
95
+ address: PANCAKE_V2_ROUTER,
96
+ abi: pancakeGetAmountsOutAbi,
97
+ functionName: 'getAmountsOut',
98
+ args: [bnbWei, [WBNB, token]],
99
+ });
100
+ if (amounts.length >= 2) {
101
+ return { minTokenOut: (amounts[1] * (10000n - slipBig)) / 10000n };
102
+ }
103
+ }
104
+ catch {
105
+ // both failed
106
+ }
107
+ throw new Error('Slippage estimation failed: neither bonding-curve tryBuy nor PancakeSwap getAmountsOut returned a quote. Refusing to send tx with 0 slippage protection.');
108
+ }
109
+ }
110
+ //# sourceMappingURL=slippage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slippage.js","sourceRoot":"","sources":["../../src/lib/slippage.ts"],"names":[],"mappings":"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"}