PageSourceSearch

https://mysol.ink/pumpfun_devnet_charts/solana_lite_manager_v3.js

js mysol.ink collected 2026-09-24 15:03:14 UTC 16,041 bytes, 388 lines download raw bytes

1/*
2   [PEŁNE KOMPENDIUM SYSTEMU SDK128]
3   MODUŁ: solana_lite_manager_v3.js
4   LOGIKA: Lekki manager Solana (Browser-Lite) bazujący na MASTER LOGIC z SDK128.
5   CEL: Zgodność 1:1 z price_pool_chartSDK128.js i utilsSDK128.js.
6*/
7
8const PUMP_PROGRAM_ID = new solanaWeb3.PublicKey("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P");
9const PUMP_AMM_PROGRAM_ID = new solanaWeb3.PublicKey("pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA");
10const WSOL_MINT = new solanaWeb3.PublicKey("So11111111111111111111111111111111111111112");
11const ASSOCIATED_TOKEN_PROGRAM_ID = new solanaWeb3.PublicKey("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL");
12const TOKEN_PROGRAM_ID = new solanaWeb3.PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
13
14const METADATA_PROGRAM_ID = new solanaWeb3.PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s");
15
16class SolanaLiteManagerV3 {
17    constructor(rpcUrl) {
18        this.connection = new solanaWeb3.Connection(rpcUrl, 'confirmed');
19    }
20
21    logUI(msg, type = 'info') {
22        console.log(`[LiteManager] ${msg}`);
23        if (window.onLiteLog) window.onLiteLog(msg, type);
24    }
25
26    async getMintMetadata(mint) {
27        try {
28            const pubkey = new solanaWeb3.PublicKey(mint);
29            const info = await this.connection.getParsedAccountInfo(pubkey);
30            let decimals = 6;
31            if (info.value && info.value.data.parsed) {
32                decimals = info.value.data.parsed.info.decimals;
33            }
34            
35            const meta = await this.getTokenMetadata(mint);
36            return { decimals, name: meta.name, symbol: meta.symbol };
37        } catch (e) {
38            return { decimals: 6, name: "Unknown", symbol: "???" };
39        }
40    }
41
42    async getTokenMetadata(mint) {
43        /* [MASTER LOGIC SYNC: utilsSDK128.js] */
44        try {
45            this.logUI(`Fetching metadata for: ${mint}...`);
46            const mintPk = new solanaWeb3.PublicKey(mint);
47            const mintInfo = await this.connection.getAccountInfo(mintPk);
48            if (!mintInfo) {
49                this.logUI(`Mint account not found!`, 'error');
50                return { name: "N/A", symbol: "N/A" };
51            }
52
53            // 1. Token-2022 Extensions Brute-force
54            if (mintInfo.owner.toBase58() === "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb") {
55                this.logUI(`Token-2022 detected, checking extensions...`);
56                for (let i = 165; i < mintInfo.data.length - 8; i++) {
57                    if (mintInfo.data[i] === 0x13 && mintInfo.data[i+1] === 0x00) {
58                        try {
59                            const view = new DataView(mintInfo.data.buffer, mintInfo.data.byteOffset + i + 2, 2);
60                            const length = view.getUint16(0, true);
61                            if (i + 4 + length <= mintInfo.data.length) {
62                                const metadataBuffer = mintInfo.data.slice(i + 4, i + 4 + length);
63                                let mOffset = 64; 
64                                const nView = new DataView(metadataBuffer.buffer, metadataBuffer.byteOffset + mOffset, 4);
65                                const nameLen = nView.getUint32(0, true);
66                                const name = new TextDecoder().decode(metadataBuffer.slice(mOffset + 4, mOffset + 4 + nameLen)).replace(/[\x00-\x1F\x7F-\x9F]/g, "").trim();
67                                mOffset += 4 + nameLen;
68                                const sView = new DataView(metadataBuffer.buffer, metadataBuffer.byteOffset + mOffset, 4);
69                                const symbolLen = sView.getUint32(0, true);
70                                const symbol = new TextDecoder().decode(metadataBuffer.slice(mOffset + 4, mOffset + 4 + symbolLen)).replace(/[\x00-\x1F\x7F-\x9F]/g, "").trim();
71                                if (name || symbol) {
72                                    this.logUI(`Found Token-2022 Metadata: ${name} (${symbol})`, 'success');
73                                    return { name: name || "Unknown", symbol: symbol || "???" };
74                                }
75                            }
76                        } catch (err) {
77                            this.logUI(`Token-2022 Parse Error: ${err.message}`, 'error');
78                        }
79                    }
80                }
81            }
82
83            // 2. Metaplex Metadata V1
84            this.logUI(`Checking Metaplex Metadata PDA...`);
85            const [pda] = solanaWeb3.PublicKey.findProgramAddressSync(
86                [new TextEncoder().encode("metadata"), METADATA_PROGRAM_ID.toBuffer(), mintPk.toBuffer()],
87                METADATA_PROGRAM_ID
88            );
89            
90            this.logUI(`PDA derived: ${pda.toBase58()}`);
91            const pdaInfo = await this.connection.getAccountInfo(pda);
92            if (pdaInfo) {
93                this.logUI(`Metaplex Metadata found! Decoding...`, 'success');
94                // Name at 69, Symbol at 105 (Metaplex V1 layout with 4-byte prefixes)
95                const name = new TextDecoder().decode(pdaInfo.data.slice(69, 101)).replace(/[\x00-\x1F\x7F-\x9F]/g, "").trim();
96                const symbol = new TextDecoder().decode(pdaInfo.data.slice(105, 115)).replace(/[\x00-\x1F\x7F-\x9F]/g, "").trim();
97                this.logUI(`Decoded: ${name} / ${symbol}`, 'success');
98                return { name: name || "Unknown", symbol: symbol || "???" };
99            } else {
100                this.logUI(`Metaplex Metadata PDA not found.`, 'warn');
101            }
102            
103            return { name: "Unknown", symbol: "???" };
104        } catch (e) {
105            this.logUI(`Metadata Error: ${e.message}`, 'error');
106            console.error(e);
107            return { name: "Unknown", symbol: "???" };
108        }
109    }
110
111    async getMintSupply(mint) {
112        try {
113            const mintPk = new solanaWeb3.PublicKey(mint);
114            // Use getParsedAccountInfo as it's often cached better by RPCs than raw getAccountInfo
115            const info = await this.connection.getParsedAccountInfo(mintPk);
116            if (info.value && info.value.data.parsed) {
117                return BigInt(info.value.data.parsed.info.supply);
118            }
119            // Fallback to raw if parsing failed
120            if (info.value) {
121                return this.readBigUInt64LE(info.value.data, 36);
122            }
123        } catch (e) {
124            console.error("Error fetching mint supply:", e);
125        }
126        return 0n;
127    }
128
129    // --- PDA DERIVATION (MATCHING SDK128) ---
130
131    getBondingCurvePda(mint) {
132        const mintPk = new solanaWeb3.PublicKey(mint);
133        return solanaWeb3.PublicKey.findProgramAddressSync(
134            [new TextEncoder().encode('bonding-curve'), mintPk.toBytes()],
135            PUMP_PROGRAM_ID
136        )[0];
137    }
138
139    getBondingCurveV2Pda(mint) {
140        const mintPk = new solanaWeb3.PublicKey(mint);
141        return solanaWeb3.PublicKey.findProgramAddressSync(
142            [new TextEncoder().encode('bonding-curve-v2'), mintPk.toBytes()],
143            PUMP_PROGRAM_ID
144        )[0];
145    }
146
147    getAuthorityPda(mint) {
148        const mintPk = new solanaWeb3.PublicKey(mint);
149        return solanaWeb3.PublicKey.findProgramAddressSync(
150            [new TextEncoder().encode('pool-authority'), mintPk.toBytes()],
151            PUMP_PROGRAM_ID
152        )[0];
153    }
154
155    getPoolV1Pda(mint) {
156        const mintPk = new solanaWeb3.PublicKey(mint);
157        const authority = this.getAuthorityPda(mint);
158        // Canonical Pump.fun AMM Pool (V1) - Correct Seeds from SDK
159        const index_buf = new Uint8Array(2);
160        // index 0 LE
161        index_buf[0] = 0;
162        index_buf[1] = 0;
163
164        return solanaWeb3.PublicKey.findProgramAddressSync(
165            [
166                new TextEncoder().encode('pool'),
167                index_buf,
168                authority.toBuffer(),
169                mintPk.toBuffer(),
170                WSOL_MINT.toBuffer()
171            ],
172            PUMP_AMM_PROGRAM_ID
173        )[0];
174    }
175
176    getPoolV2Pda(mint) {
177        const mintPk = new solanaWeb3.PublicKey(mint);
178        // Alternative Pump.fun AMM Pool (V2)
179        return solanaWeb3.PublicKey.findProgramAddressSync(
180            [new TextEncoder().encode('pool-v2'), mintPk.toBytes()],
181            PUMP_AMM_PROGRAM_ID
182        )[0];
183    }
184
185    getAta(mint, owner, programId = TOKEN_PROGRAM_ID) {
186        const mintPk = new solanaWeb3.PublicKey(mint);
187        const ownerPk = new solanaWeb3.PublicKey(owner);
188        const progPk = new solanaWeb3.PublicKey(programId);
189        return solanaWeb3.PublicKey.findProgramAddressSync(
190            [ownerPk.toBytes(), progPk.toBytes(), mintPk.toBytes()],
191            ASSOCIATED_TOKEN_PROGRAM_ID
192        )[0];
193    }
194
195    // --- DATA DECODING (MATCHING SDK128) ---
196
197    decodeBondingCurve(data) {
198        // Offset 8 for discriminator
199        const virtualTokenReserves = this.readBigUInt64LE(data, 8);
200        const virtualSolReserves = this.readBigUInt64LE(data, 16);
201        const realTokenReserves = this.readBigUInt64LE(data, 24);
202        const realSolReserves = this.readBigUInt64LE(data, 32);
203        const tokenTotalSupply = this.readBigUInt64LE(data, 40);
204        const complete = data[48] !== 0;
205
206        return {
207            virtualTokenReserves,
208            virtualSolReserves,
209            realTokenReserves,
210            realSolReserves,
211            tokenTotalSupply,
212            complete
213        };
214    }
215
216    decodeTokenAmount(data) {
217        // SPL Token Account balance is at offset 64 (8 bytes)
218        return this.readBigUInt64LE(data, 64);
219    }
220
221    readBigUInt64LE(buffer, offset) {
222        const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
223        return view.getBigUint64(offset, true);
224    }
225
226    // --- PRICE CALCULATION (MATCHING price_pool_chartSDK128.js) ---
227
228    calculatePrice(phase, data, decimals = 6) {
229        if (phase === 'CURVE') {
230            const vS = Number(data.virtualSolReserves) / 1e9;
231            const vT = Number(data.virtualTokenReserves) / Math.pow(10, decimals);
232            return vT > 0 ? vS / vT : 0;
233        } else if (phase === 'AMM') {
234            const bNum = Number(data.baseAmount) / Math.pow(10, decimals);
235            const qNum = Number(data.quoteAmount) / 1e9;
236            return bNum > 0 ? qNum / bNum : 0;
237        }
238        return 0;
239    }
240
241    async fetchFullAmmState(mint, silent = false) {
242        const mintPk = new solanaWeb3.PublicKey(mint);
243        const poolPda = this.getPoolV1Pda(mint);
244        
245        let tokenProgram = TOKEN_PROGRAM_ID;
246        try {
247            const mInfo = await this.connection.getAccountInfo(mintPk);
248            if (mInfo) tokenProgram = mInfo.owner;
249        } catch (e) {}
250
251        const poolBaseAta = this.getAta(mint, poolPda, tokenProgram);
252        const poolQuoteAta = this.getAta(WSOL_MINT, poolPda, TOKEN_PROGRAM_ID);
253
254        try {
255            const [baseInfo, quoteInfo, mintInfo] = await Promise.all([
256                this.connection.getAccountInfo(poolBaseAta),
257                this.connection.getAccountInfo(poolQuoteAta),
258                this.connection.getAccountInfo(mintPk)
259            ]);
260            
261            let totalSupply = 0n;
262            if (mintInfo) {
263                // Supply is at offset 36 (8 bytes)
264                totalSupply = this.readBigUInt64LE(mintInfo.data, 36);
265            }
266
267            if (baseInfo && quoteInfo) {
268                const baseAmount = this.decodeTokenAmount(baseInfo.data);
269                const quoteAmount = this.decodeTokenAmount(quoteInfo.data);
270                return {
271                    poolPda,
272                    baseAmount,
273                    quoteAmount,
274                    poolBaseAta,
275                    poolQuoteAta,
276                    tokenProgram,
277                    totalSupply
278                };
279            }
280        } catch (e) {
281            if (!silent) console.error("Error fetching AMM state:", e);
282        }
283        return null;
284    }
285
286    // --- PHASE DETECTION (MATCHING detectTokenPhase in utilsSDK128.js) ---
287
288    async detectTokenPhase(mint) {
289        const logUI = (msg, type = 'info') => {
290            console.log(`[LiteManager] ${msg}`);
291            if (window.onLiteLog) window.onLiteLog(msg, type);
292        };
293
294        logUI(`=== Phase Detection for: ${mint} ===`);
295        const mintPk = new solanaWeb3.PublicKey(mint);
296        
297        let tokenProgram = TOKEN_PROGRAM_ID;
298        try {
299            const mInfo = await this.connection.getAccountInfo(mintPk);
300            if (mInfo) {
301                tokenProgram = mInfo.owner;
302                logUI(`Mint Owner: ${tokenProgram.toBase58()}`);
303            }
304        } catch (e) {
305            logUI(`Warning: Could not fetch mint info (RPC?), defaulting to Tokenkeg...`);
306        }
307
308        // --- PHASE SEQUENCE ---
309        
310        // 1. Sprawdź Bonding Curve V1
311        const bcPda = this.getBondingCurvePda(mint);
312        logUI(`Checking BC V1: ${bcPda.toBase58()}`);
313        try {
314            const bcInfo = await this.connection.getAccountInfo(bcPda);
315            if (bcInfo) {
316                const decoded = this.decodeBondingCurve(bcInfo.data);
317                if (!decoded.complete) {
318                    logUI(`Phase: CURVE (V1) Found!`, 'success');
319                    return { phase: 'CURVE', data: decoded, pda: bcPda, tokenProgram, version: 'V1' };
320                }
321                logUI(`BC V1 Complete...`);
322            }
323        } catch (e) {}
324
325        // 2. Sprawdź Bonding Curve V2
326        const bcV2Pda = this.getBondingCurveV2Pda(mint);
327        logUI(`Checking BC V2: ${bcV2Pda.toBase58()}`);
328        try {
329            const bcV2Info = await this.connection.getAccountInfo(bcV2Pda);
330            if (bcV2Info) {
331                const decoded = this.decodeBondingCurve(bcV2Info.data);
332                if (!decoded.complete) {
333                    logUI(`Phase: CURVE (V2) Found!`, 'success');
334                    return { phase: 'CURVE', data: decoded, pda: bcV2Pda, tokenProgram, version: 'V2' };
335                }
336                logUI(`BC V2 Complete...`);
337            }
338        } catch (e) {}
339
340        // 3. Sprawdź AMM V1 (Canonical)
341        const poolV1Pda = this.getPoolV1Pda(mint);
342        logUI(`Checking AMM V1 (Canonical): ${poolV1Pda.toBase58()}`);
343        try {
344            const poolV1State = await this.fetchFullAmmState(mint, true);
345            if (poolV1State) {
346                logUI(`Phase: AMM (V1) Found!`, 'success');
347                return { phase: 'AMM', data: poolV1State, pda: poolV1Pda, tokenProgram, version: 'V1' };
348            }
349        } catch (e) {}
350
351        // 4. Sprawdź AMM V2 (Pool-V2)
352        const poolV2Pda = this.getPoolV2Pda(mint);
353        logUI(`Checking AMM V2 (Pool-V2): ${poolV2Pda.toBase58()}`);
354        try {
355            const poolV2Info = await this.connection.getAccountInfo(poolV2Pda);
356            if (poolV2Info) {
357                logUI(`Phase: AMM (V2) Found!`, 'success');
358                // Dla V2 spróbuj też pobrać balansy jeśli ATA istnieją
359                const poolV2State = await this.fetchFullAmmState(mint, true);
360                return { phase: 'AMM', data: poolV2State || { poolPda: poolV2Pda }, pda: poolV2Pda, tokenProgram, version: 'V2' };
361            }
362        } catch (e) {}
363
364        logUI(`No active phase found (UNKNOWN). Check if RPC supports Token-2022 Accounts.`, 'error');
365        return { phase: 'UNKNOWN' };
366    }
367
368    subscribeToAccount(pubkey, callback) {
369        return this.connection.onAccountChange(
370            new solanaWeb3.PublicKey(pubkey),
371            (info) => callback(info),
372            'confirmed'
373        );
374    }
375
376    async getSolPrice() {
377        try {
378            const url = `/api/sol-price`;
379            const resp = await fetch(url);
380            const data = await resp.json();
381            // Jupiter V3 ticker structure: { MINT: { usdPrice: N, ... } }
382            return data["So11111111111111111111111111111111111111112"].usdPrice;
383        } catch (e) {
384            console.warn("SOL Price fetch error:", e);
385            return null;
386        }
387    }
388}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.