Last active
February 28, 2025 14:47
-
-
Save danmt/051adb0920e87369bae78beec68ed407 to your computer and use it in GitHub Desktop.
This method goes over the manual decodification of the Pool State of a Constant Product Liquidity Pool from Raydium.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { struct, u8 as u8Func } from "@solana/buffer-layout"; | |
import { | |
publicKey as publicKeyUtil, | |
u64 as u64Func, | |
} from "@solana/buffer-layout-utils"; | |
import { getAccount, getMint } from "@solana/spl-token"; | |
import { PublicKey } from "@solana/web3.js"; | |
import { config } from "./config"; | |
import { fetchToken } from "./fetch-token"; | |
// Define the layout structure with proper factory functions | |
const CPMM_POOL_STATE_LAYOUT = struct<PoolState>([ | |
u64Func("version"), | |
publicKeyUtil("ammConfig"), | |
publicKeyUtil("poolCreator"), | |
publicKeyUtil("token0Vault"), | |
publicKeyUtil("token1Vault"), | |
publicKeyUtil("lpMint"), | |
publicKeyUtil("token0Mint"), | |
publicKeyUtil("token1Mint"), | |
publicKeyUtil("token0Program"), | |
publicKeyUtil("token1Program"), | |
publicKeyUtil("observationKey"), | |
u8Func("authBump"), | |
u8Func("status"), | |
u8Func("lpMintDecimals"), | |
u8Func("mint0Decimals"), | |
u8Func("mint1Decimals"), | |
u64Func("lpSupply"), | |
u64Func("protocolFeesToken0"), | |
u64Func("protocolFeesToken1"), | |
u64Func("fundFeesToken0"), | |
u64Func("fundFeesToken1"), | |
u64Func("openTime"), | |
struct(Array(32).fill(u64Func()), "padding"), | |
]); | |
interface PoolState { | |
version: bigint; | |
ammConfig: PublicKey; | |
poolCreator: PublicKey; | |
token0Vault: PublicKey; | |
token1Vault: PublicKey; | |
lpMint: PublicKey; | |
token0Mint: PublicKey; | |
token1Mint: PublicKey; | |
token0Program: PublicKey; | |
token1Program: PublicKey; | |
observationKey: PublicKey; | |
authBump: number; | |
status: number; | |
lpMintDecimals: number; | |
mint0Decimals: number; | |
mint1Decimals: number; | |
lpSupply: bigint; | |
protocolFeesToken0: bigint; | |
protocolFeesToken1: bigint; | |
fundFeesToken0: bigint; | |
fundFeesToken1: bigint; | |
openTime: bigint; | |
padding: bigint[]; | |
} | |
export async function fetchRaydiumPoolData(poolId: string) { | |
try { | |
const { connection, mintPublicKey } = config; | |
const poolAccount = await connection.getAccountInfo(new PublicKey(poolId)); | |
if (!poolAccount) throw new Error("Pool account not found"); | |
const poolState = CPMM_POOL_STATE_LAYOUT.decode(poolAccount.data); | |
// Determine base/quote based on configBaseMint | |
const isToken0Base = mintPublicKey.equals(poolState.token0Mint); | |
const baseMint = isToken0Base ? poolState.token0Mint : poolState.token1Mint; | |
const quoteMint = isToken0Base | |
? poolState.token1Mint | |
: poolState.token0Mint; | |
const baseVault = isToken0Base | |
? poolState.token0Vault | |
: poolState.token1Vault; | |
const quoteVault = isToken0Base | |
? poolState.token1Vault | |
: poolState.token0Vault; | |
// Fetch token mint alongside its metadata when available | |
const baseToken = await fetchToken(baseMint); | |
const quoteToken = await fetchToken(quoteMint); | |
const baseTicker = baseToken.metadata | |
? baseToken.metadata.symbol || baseMint.toBase58().slice(0, 6) | |
: "Unknown"; | |
const quoteTicker = quoteToken.metadata | |
? quoteToken.metadata?.symbol || quoteMint.toBase58().slice(0, 6) | |
: "Unknown"; | |
const pair = `${baseTicker}/${quoteTicker}`; | |
const baseVaultAccount = await getAccount(connection, baseVault); | |
const quoteVaultAccount = await getAccount(connection, quoteVault); | |
const baseMintInfo = await getMint(connection, baseMint); | |
const quoteMintInfo = await getMint(connection, quoteMint); | |
const baseAmount = | |
Number(baseVaultAccount.amount) / 10 ** baseMintInfo.decimals; | |
const quoteAmount = | |
Number(quoteVaultAccount.amount) / 10 ** quoteMintInfo.decimals; | |
const priceSol = quoteAmount / baseAmount; // Quote per base (e.g., SOL/BANANA) | |
return { | |
pair, | |
priceSol, | |
baseMint: baseMintInfo, | |
quoteMint: quoteMintInfo, | |
baseAmount, | |
quoteAmount, | |
baseVault: baseVaultAccount, | |
quoteVault: quoteVaultAccount, | |
}; | |
} catch (error) { | |
console.warn( | |
`Failed to fetch Raydium CPMM pool data for ${poolId}:`, | |
error | |
); | |
return null; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment