Skip to content

Instantly share code, notes, and snippets.

@rubpy
Created June 22, 2024 19:35
Show Gist options
  • Save rubpy/171fdd565569191b4fc7ba9555e4564f to your computer and use it in GitHub Desktop.
Save rubpy/171fdd565569191b4fc7ba9555e4564f to your computer and use it in GitHub Desktop.
Tracking changes in Pump.fun global state (initialVirtualTokenReserves, initialVirtualSolReserves, initialRealTokenReserves, tokenTotalSupply, feeBasisPoints).
import * as web3 from "@solana/web3.js";
import bs58 from "bs58";
//////////////////////////////////////////////////
function readBytes(buf: Buffer, offset: number, length: number): Buffer {
const end = offset + length;
if (buf.byteLength < end) throw new RangeError("range out of bounds");
return buf.subarray(offset, end);
}
function readBigUintLE(buf: Buffer, offset: number, length: number): bigint {
switch (length) {
case 1: return BigInt(buf.readUint8(offset));
case 2: return BigInt(buf.readUint16LE(offset));
case 4: return BigInt(buf.readUint32LE(offset));
case 8: return buf.readBigUint64LE(offset);
}
throw new Error(`unsupported data size (${length} bytes)`);
}
function readBoolean(buf: Buffer, offset: number, length: number): boolean {
const data = readBytes(buf, offset, length);
for (const b of data) {
if (b) return true;
}
return false;
}
function readPublicKey(buf: Buffer, offset: number): web3.PublicKey {
return new web3.PublicKey(readBytes(buf, offset, web3.PUBLIC_KEY_LENGTH));
}
//////////////////////////////////////////////////
const PUMP_PROGRAM_ID = new web3.PublicKey("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P");
interface PumpGlobalState {
initialized: boolean
authority: web3.PublicKey
feeRecipient: web3.PublicKey
initialVirtualTokenReserves: bigint
initialVirtualSolReserves: bigint
initialRealTokenReserves: bigint
tokenTotalSupply: bigint
feeBasisPoints: bigint
}
// Calculated as the first 8 bytes of: `sha256("account:Global")`.
const PUMP_GLOBAL_STATE_SIGNATURE = Uint8Array.from([0xa7, 0xe8, 0xe8, 0xb1, 0xc8, 0x6c, 0x72, 0x7f]);
const PUMP_GLOBAL_STATE_SIZE = 0x69;
const PUMP_GLOBAL_STATE_OFFSETS = {
INITIALIZED: 0x08,
AUTHORITY: 0x09,
FEE_RECIPIENT: 0x29,
INITIAL_VIRTUAL_TOKEN_RESERVES: 0x49,
INITIAL_VIRTUAL_SOL_RESERVES: 0x51,
INITIAL_REAL_TOKEN_RESERVES: 0x59,
TOKEN_TOTAL_SUPPLY: 0x61,
FEE_BASIS_POINTS: 0x69,
};
function decodePumpGlobalState(data: Buffer): PumpGlobalState {
const idlSignature = readBytes(data, 0, PUMP_GLOBAL_STATE_SIGNATURE.byteLength);
if (idlSignature.compare(PUMP_GLOBAL_STATE_SIGNATURE) !== 0) {
throw new Error("unexpected global state IDL signature");
}
return {
initialized: readBoolean(data, PUMP_GLOBAL_STATE_OFFSETS.INITIALIZED, 1),
authority: readPublicKey(data, PUMP_GLOBAL_STATE_OFFSETS.AUTHORITY),
feeRecipient: readPublicKey(data, PUMP_GLOBAL_STATE_OFFSETS.FEE_RECIPIENT),
initialVirtualTokenReserves: readBigUintLE(data, PUMP_GLOBAL_STATE_OFFSETS.INITIAL_VIRTUAL_TOKEN_RESERVES, 8),
initialVirtualSolReserves: readBigUintLE(data, PUMP_GLOBAL_STATE_OFFSETS.INITIAL_VIRTUAL_SOL_RESERVES, 8),
initialRealTokenReserves: readBigUintLE(data, PUMP_GLOBAL_STATE_OFFSETS.INITIAL_REAL_TOKEN_RESERVES, 8),
tokenTotalSupply: readBigUintLE(data, PUMP_GLOBAL_STATE_OFFSETS.TOKEN_TOTAL_SUPPLY, 8),
feeBasisPoints: readBigUintLE(data, PUMP_GLOBAL_STATE_OFFSETS.FEE_BASIS_POINTS, 8),
};
}
//////////////////////////////////////////////////
(async (rpcUrl: string) => {
const conn = new web3.Connection(rpcUrl, "confirmed");
conn.onProgramAccountChange(PUMP_PROGRAM_ID, (info: web3.KeyedAccountInfo, ctx: web3.Context) => {
let state: PumpGlobalState | null = null;
try {
state = decodePumpGlobalState(info.accountInfo.data);
} catch (e) {}
if (!state) return null;
console.log(ctx.slot, "|", info.accountId.toBase58());
console.dir(state);
console.log();
}, undefined, [
{ dataSize: PUMP_GLOBAL_STATE_SIGNATURE.byteLength + PUMP_GLOBAL_STATE_SIZE },
{ memcmp: { offset: 0, bytes: bs58.encode(PUMP_GLOBAL_STATE_SIGNATURE) } },
]);
//
// --- OUTPUT ---
//
// 273403135 | 4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf
// {
// initialized: true,
// authority: PublicKey [PublicKey(DCpJReAfonSrgohiQbTmKKbjbqVofspFRHz9yQikzooP)] {
// _bn: BN { negative: 0, words: [Array], length: 10, red: null }
// },
// feeRecipient: PublicKey [PublicKey(CebN5WGQ4jvEPvsVU4EoHEpgzq1VV7AbicfhtW4xC9iM)] {
// _bn: BN { negative: 0, words: [Array], length: 10, red: null }
// },
// initialVirtualTokenReserves: 1073000000000000n,
// initialVirtualSolReserves: 30000000000n,
// initialRealTokenReserves: 793100000000000n,
// tokenTotalSupply: 1000000000000000n,
// feeBasisPoints: 100n
// }
//
// --------------
//
})(process.env.SOL_RPC_URL || "https://mainnet.helius-rpc.com/?api-key=00000000-0000-0000-0000-000000000000");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment