Team Shyft
· January 22, 2026
A comprehensive guide on tracking Bonding Curve transactions on pump fun with gRPC

Since the emergence of decentralized finance (Defi), understanding bonding curves and their valuation has become crucial for anyone and everyone involved in liquidity pools and tokenomics. Bonding curves are mathematical functions that illustrates the relationship between a token’s price and its circulating supply, enabling automated market-making and liquidity provision within the Defi protocols.
Pumpfun, a platform on the Solana blockchain, allows users to create and trade meme coins using a bonding curve model. This model adjusts token prices dynamically based on demand, ensuring a fair and transparent trading experience. When a token’s market cap reaches $69,000 or its pool value hits 86 SOL, Pumpfun automatically adds liquidity to Raydium, a decentralized exchange (DEX), to enhance trading efficiency.
In this tutorial, we will explore how to use gRPC to stream bonding curve transactions on Pumpfun.
To get started, you’ll need a few essentials:
1. Authentication: Shyft API Key, gRPC Endpoint, and gRPC Token
2. Server-Side Backend (e.g., Node.js) to Receive gRPC Data
Since gRPC services are not supported in web browsers, you’ll need a backend application to handle the gRPC data. For this example, we use Node.js, but other server-side languages such as C#, Go, Java, Kotlin, Python, or PHP can also be used.
In this article, we will look at streaming Bonding Curve trading transactions on Pumpfun using gRPC. We will be covering the following topics,
For comprehensive guidance on streaming real-time updates from Pumpfun on Solana, please consult our article: How to Stream Real-Time Pumpfun Updates on Solana.
To get started, you will need to clone the Git repository containing the code. Follow these steps:
git clone followed by the repository URL. For example:$ git clone https://github.com/Shyft-to/solana-defi.git
In your terminal, navigate to the folder containing the code by running cd grpc-moonshot, then install all dependencies by executing npm install.
cd grpc-pump-curveBondingnpm install
All the code related to this article is available on our GitHub here. You are welcome to clone it and follow along.
To begin streaming data from Pumpfun using gRPC, you need to establish the client service. This involves two essential pieces of information: the gRPC URL and the gRPC Access Token. The access token is a security credential, usually a long alphanumeric string, while the URL corresponds to your region-specific gRPC endpoint. With these details, you can configure the client service and start streaming data from Pumpfun.
const client = new Client('Your Region specific Shyft gRPC URL','Shyft gRPC Access Token',undefined);
Now we can proceed to obtain our data from the blockchain.
To stream data from Pumpfun, it’s not enough to establish a connection. We would need to fetch the bonding curve transaction details, which include the Contract Address of the Bonding Curve, and the Pool token details, we use the wallet token API to fetch the necessary data. To retrieve data, we would be making use of memcmp to filter our pumpfun transaction. Our code structures will look like this:
const req: SubscribeRequest = {
"slots": {}, "accounts": { "raydium": { "account": [], "filters": [], "owner": [pumpfun] } }, "transactions": {}, "blocks": {}, "blocksMeta": { "block": [] }, "accountsDataSlice": [], "commitment": CommitmentLevel.PROCESSED, entry: {}, transactionsStatus: {}}
Our raw transaction should be presented in a comprehensive and detailed format to ensure clarity and accessibility
{ filters: [ 'pumpfun' ], account: { account: { pubkey: <Buffer 94 3c 0a 59 44 07 80 77 53 51 c6 e0 fd 26 20 83 ef ad cb d5 d2 fc 5c 22 84 9d 19 8b 0b 1e e7 a6>, lamports: '1232028', owner: <Buffer 01 56 e0 f6 93 66 5a cf 44 db 15 68 bf 17 5b aa 51 89 cb 97 f5 d2 ff 3b 65 5d 2b b6 fd 6d 18 b0>, executable: false, rentEpoch: '18446744073709551615', data: <Buffer 17 b7 f8 37 60 d8 ac 60 a4 86 a2 47 e3 cf 03 00 6c ac 23 fc 06 00 00 00 a4 ee 8f fb 51 d1 02 00 6c 00 00 00 00 00 00 00 00 80 c6 a4 7e 8d 03 00 00>, writeVersion: '1455967774790', txnSignature: undefined }, slot: '292282145', isStartup: false }, slot: undefined, transaction: undefined, block: undefined, ping: undefined, pong: undefined, blockMeta: undefined, entry: undefined}
To retrieve our pool details, we will utilize Shyft’s DeFi API. This process involves making a request to the API endpoint designed for fetching pool information.
var myHeaders = new Headers();export const api = "api"myHeaders.append("x-api-key", api);var requestOptions:any = { method: 'GET', headers: myHeaders, redirect: 'follow'};export async function getTokenBalance(address){ const info = await fetch(`https://api.shyft.to/sol/v1/wallet/all_tokens?network=mainnet-beta&wallet=${address}`, requestOptions) const infoJson = await info.json(); const result = infoJson?.result[0]; const ca = result?.address const name = result?.info?.name const symbol = result?.info.symbolconst balance = result?.balance; return { name, symbol, ca, balance };}
This is how our result should be presented:
{ name: 'Key Opinion Loser', symbol: 'KOL', ca: 'KoL17ZJJ8ccwM2zxvpvDuVD9YpMW4KumAsaRFB9JCKe', balance: 0}
Our output is currently in a Buffer format, which is not very user-friendly. To make this data more accessible and easier to understand, we need to decode and trim it into a more readable text format.
import base58 from "bs58";import { struct, bool, u64, Layout } from "@coral-xyz/borsh";export const structure = struct([ u64("discriminator"), u64("virtualTokenReserves"), u64("virtualSolReserves"), u64("realTokenReserves"), u64("realSolReserves"), u64("tokenTotalSupply"), bool("complete"), ]);export function decodeTransact(data){ const output = base58.encode(Buffer.from(data,'base64')) return output;}export function bondingCurveData(buffer: Buffer) { let value = structure.decode(buffer); const discriminator = BigInt(value.discriminator); const virtualTokenReserves = BigInt(value.virtualTokenReserves); const virtualSolReserves = BigInt(value.virtualSolReserves); const realTokenReserves = BigInt(value.realTokenReserves); const realSolReserves = BigInt(value.realSolReserves); const tokenTotalSupply = BigInt(value.tokenTotalSupply); const complete = value.complete; return { discriminator, virtualTokenReserves, virtualSolReserves, realTokenReserves, realSolReserves, tokenTotalSupply, complete }; }
We decode the pumpfun account data by defining its struct
import { LIQUIDITY_STATE_LAYOUT_V4 } from "@raydium-io/raydium-sdk";import { bondingCurveData, decodeTransact } from "./decodeTransaction";export function tOutPut(data) { if (!data || !data.account || !data.account.account) { throw new Error("Invalid data format"); } const dataTx = data.account.account; const signature = dataTx.txnSignature ? decodeTransact(dataTx.txnSignature) : null; const pubKey = dataTx.pubkey ? decodeTransact(dataTx.pubkey) : null; const owner = dataTx.owner ? decodeTransact(dataTx.owner) : null; let poolstate = null; try { poolstate = bondingCurveData(dataTx.data); } catch (error) { console.error("Failed to decode pool state:", error); } return { signature, pubKey, owner, poolstate };}
Here is the result we aim to achieve in our console output.
{ signature: '3PfY1M74yoKerd38LV7ZYQejVBxiYGCW2BmhfEr2UGGt5eAWQGRkdFJUniqvr6yyZMVCsYxMTJQmymXT9ECEFR3J', pubKey: 'LjCVC9PKfX5WzWTbD6T1tHbHW4EDCuk3cdE53BTwXxa', owner: '6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P', poolstate: { discriminator: 6966180631402821399n, virtualTokenReserves: 925163590557167n, virtualSolReserves: 34793847131n, realTokenReserves: 645263590557167n, realSolReserves: 4793847131n, tokenTotalSupply: 1000000000000000n, complete: false }}
Our code becomes much simpler as we leverage memcmp to retrieve the Bonding Curve completion on Pumpfun. This approach allows us to streamline our process significantly. By focusing solely on filtering our transactions, we can efficiently isolate the relevant data needed for our analysis. This optimization not only reduces complexity but also improves performance, making it easier to work with the specific transaction details we require.
const req: SubscribeRequest = { "slots": {}, "accounts": { "raydium": { "account": [], "filters": [ { "memcmp": { "offset": structure.offsetOf('complete').toString(), "bytes" : Uint8Array.from([1]) } } ], "owner": [pumpfun] } }, "transactions": {}, "blocks": {}, "blocksMeta": { "block": [] }, "accountsDataSlice": [], "commitment": CommitmentLevel.PROCESSED, entry: {}, transactionsStatus: {}}
We should anticipate receiving the following output from the API request.
{ signature: null, pubKey: '3ZEsfmh28PAfxyqJjHppcqzkEQbhKgtxCPg6WQG21ZKg', owner: '6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P', poolstate: { discriminator: 6966180631402821399n, virtualTokenReserves: 0n, virtualSolReserves: 0n, realTokenReserves: 0n, realSolReserves: 0n, tokenTotalSupply: 1000000000000000n, complete: true }}
To proceed, we should enhance our stream.on function to include the functionality for retrieving the pool details.
stream.on("data", async (data) => { try{ const result = await tOutPut(data); const tokenInfo = await getTokenBalance(result.pubKey); console.log( ` CA : ${tokenInfo.ca} Name : ${tokenInfo.name} (${tokenInfo.symbol}) POOL DETAILS : 0 ${tokenInfo.symbol} 0 SOL BONDING CURVE STATUS : COMPLETE ` )}catch(error){ if(error){ console.log(error) }}});
We want to ensure that our console output is formatted in a clear and informative manner.
CA : 7FhLiAXYaJX1HbpJPqASucasxdRYRUbvR25QVXfxua3G Name : VibeAI (VAI) POOL DETAILS : 0 VAI 0 SOL BONDING CURVE STATUS : COMPLETED CA : 4iBqSNn9i3PqNv1shXVHjEWkD7MvoaZmcCFpTJSwNqep Name : Its Over Cat (OVER) POOL DETAILS : 0 OVER 0 SOL BONDING CURVE STATUS : COMPLETED
We’re excited to unveil new solution for streaming data on the Solana blockchain: gRPC. This technology streamlines the process of accessing on-chain data, enabling developers to concentrate on creating powerful applications that leverage the Solana blockchain. gRPC simplifies the code base and reduces latency, making data transmission faster and more efficient. Traditionally, streaming data on Solana with dedicated nodes has been complex and resource-intensive, often requiring a more elaborate code base. However, gRPC simplifies this process, allowing developers to build even the most sophisticated projects with ease.
Join Medium for free to get updates from this writer.
Key benefits of using gRPC for Solana blockchain development include:
For additional support, join our Discord Server or follow us on Twitter for the latest updates. Our team is here to assist you in leveraging this innovative technology.
You can find all the code related to this article on our GitHub repository. Feel free to clone it and follow along. For more insights into data streaming on Solana, explore our other articles: Streaming Real-Time Data on Solana, Real-Time Data Streaming with gRPC: Accounts, Transactions, Blocks, How to Stream Real-Time Pump.fun Updates on Solana, and Tracking New Pools on Raydium.

In this article we will explore streaming and parsing pump swap AMM transactions using gRPC ...
January 24, 2026

In this article, we will explore how to fetch parsed pump fun’s newly introduced pump AMM data ...
January 23, 2026

In this article, we will see how we can stream real-time Raydium liquidity pool v4 transactions and parse them using Shy...
January 22, 2026
Get in touch with our discord community and keep up with the latest feature
releases. Get help from our developers who are always here to help you take off.