20 minutos de leitura
fromSlot Parâmetros para a reprodução histórica e outrosA partir de julho de 2025, Quicknode o fromSlot parâmetro que permite aos clientes reproduzir dados de até 3000 intervalos recentes — cerca de 20 minutos —, proporcionando maior flexibilidade aos clientes que possam enfrentar instabilidade na rede ou necessitem de preenchimento de dados durante a recuperação.
Este guia foi atualizado para refletir esta nova funcionalidade, bem como para utilizar Solana , as versões atuais do Node.js e outras ferramentas mais recentes.
Visão geral
In this guide, we'll learn about how to use Solana gRPC (Yellowstone-compatible Geyser gRPC) to monitor real-time on-chain activity. Specifically, we'll create a TypeScript application that tracks new token mints from the Pump.fun program on Solana's mainnet. This project will demonstrate how to leverage Solana gRPC's low-latency data access capabilities to build responsive and efficient monitoring tools.
Prefere um formato visual? Acompanhe o vídeo para aprender a monitorizar os dados Solana utilizando Solana gRPC 9 minutos.
O que irá fazer
- Saiba mais sobre o Geyser egRPC Solana
- Utilize o TypeScript egRPC Solana gRPC monitorizar as novas emissões da Pump.fun na Solana
- Ser capaz de aplicar esta lógica a outros programas
Eis como ficará o programa:

O que vai precisar
- Noções básicas sobre Solana
- Node.js (v20 ou posterior)
- Uma Quicknode num plano Scale ou Business (gRPC Solana gRPC ) ou num plano Build/Accelerate com o gRPC Solana gRPC
- Um editor de código à sua escolha (por exemplo, o VS Code)
O que é o Geyser?
Geyser is a plugin system for Solana validators that provides low-latency access to blockchain data without overloading validators with intensive RPC requests (e.g., getProgramAccounts). Em vez de consultar diretamente o validador, os plugins do Geyser transmitem informações em tempo real sobre contas, transações, slots e blocos para o repositório de dados externo da sua escolha, por exemplo, uma base de dados relacional, uma base de dados NoSQL ou plataformas de streaming como o Kafka. Esta abordagem reduz significativamente a carga sobre os validadores, ao mesmo tempo que melhora a eficiência do acesso aos dados.
The key advantage of Geyser plugins is their ability to scale with high-volume Solana applications. By routing data queries to external stores, developers can implement optimized access patterns like caching and indexing, which is particularly valuable for applications requiring frequent access to large datasets or historical information. This separation allows validators to focus on their primary role of processing transactions while ensuring developers have the comprehensive, real-time data access they need.
O que é Solana gRPC?
Solana gRPC gRPC Geyser gRPC Quicknode, Yellowstone — interoperável com o ecossistema de código aberto Yellowstone gRPC. Este serviço utiliza gRPC, a estrutura de alto desempenho da Google que combina o Protocol Buffers para serialização com o HTTP/2 para transporte, permitindo uma comunicação rápida e segura em termos de tipos entre sistemas distribuídos.
Solana gRPC a transmissão em tempo real de:
- Atualizações da conta
- Transações
- Entradas
- Bloquear notificações
- Notificações de slots
Em comparação com as implementações tradicionais do WebSocket, Solana gRPC menor latência e maior estabilidade. Inclui também operações unárias para recuperações rápidas e pontuais de dados. A combinação da eficiência gRPC com a segurança de tipos torna Solana gRPC adequado para serviços baseados na nuvem e atualizações de bases de dados. Solana gRPC incluído nos planos Scale e Business. Nos planos Build e Accelerate, continua disponível através do gRPC Solana gRPC .
Vamos vergRPC Solana gRPC ação, escrevendo um script para monitorizar novas emissões da Pump.fun na Solana.
Se utilizar Solana gRPC Node.js para grandes volumes de dados, é possível sobrecarregar uma única CPU. Se estiver a desenvolver sistemas que necessitem de processar todas as transações de programas com elevado volume de tráfego ou de monitorizar vários programas em simultâneo, considere as seguintes alternativas de alto desempenho:
-
Utilização de múltiplas threads. O Node.js dispõe de dois módulos:
agrupamento(multiprocessos, uma thread por processo) etrabalhador(um único processo, várias threads). Qualquer uma destas opções resolverá o problema da sobrecarga de um único núcleo por parte do nó, masagrupamentoé mais simples, uma vez que cada processo está isolado em termos de memória. Divida asgRPC Solana entre várias instâncias deagrupamentooutrabalhadorpara distribuir a carga. -
Utilizar Solana gRPC Rust (ver também o guiaSolana gRPC Rust»)
-
Utilização Solana gRPC Go (ver também o guiaSolana gRPC Go»).
Criar um novo projeto
Vamos começar por criar um novo projeto em TypeScript:
-
Crie um novo diretório para o seu projeto e aceda a ele:
mkdir pump-fun-monitor && cd pump-fun-monitor -
Inicializar um novo projeto Node.js:
npm init -y
Em seguida, ative os módulos ES6 no seu package.json ficheiro, adicionando o seguinte:
{
...existing package.json content...
"type": "module"
}
-
Instale as dependências necessárias:
npm install tsxgrpc solana -
Guarde o ficheiro IDL do programa que pretende monitorizar. Neste caso, vamos obter o ficheiro IDL do programa Pump.fun.
curl -o program.jsonsdk
Agora já estás pronto para começares a escrever o teu programa!
Escrever o guião
Vamos criar o nosso programa para monitorizar as emissões do Pump.fun utilizandogRPC Solana . Vamos dividir este processo em várias etapas:
Passo 1: Definir interfaces
Vamos utilizar principalmente as interfaces do grpc pacote, pelo que não precisamos de definir muitos deles aqui. Crie um novo ficheiro chamado lib/interfaces.ts e adicione o seguinte código:
export interface CompiledInstruction {
programIdIndex: number;
accounts: Uint8Array;
data: Uint8Array;
}
export interface MintInformation {
mint: string;
transaction: string;
slot: number;
}
Passo 2: Criar uma função para obterendpoint seuendpointgRPC Solana
gRPC Solana gRPC uma porta diferente da do endpoint RPC habitual. Esta função irá converter endpoint seu endpoint Quicknode endpoint endpoint gRPC Solana endpoint endpoint token.
Crie um novo ficheiro chamado quicknode.ts e adicione o seguinte código:
// Convert the RPC endpoint to a Solana gRPC endpoint and token
export const getYellowstoneEndpointAndToken = (rpcEndpoint: string) => {
// Convert endpoint to URL object
const url = new URL(rpcEndpoint);
const YELLOWSTONE_PORT = 443;
// Solana gRPC endpoint is the same as the RPC endpoint, but with port 443 and no pathname
const yellowstoneEndpoint = `${url.protocol}//${url.hostname}:${YELLOWSTONE_PORT}`;
// The token is the pathname of the RPC endpoint, but without the leading slash
const yellowstoneToken = url.pathname.replace(/\//g, "");
return { yellowstoneEndpoint, yellowstoneToken };
};
Passo 3: Criar funções auxiliares
gRPC Solana gRPC as assinaturas das transações e os endereços dos tokens como Uint8Array. Temos de os converter para base58 para que fiquem legíveis. Crie um novo ficheiro chamado lib/helpers.ts e adicione o seguinte código:
import { getBase58Decoder } from "@solana/kit";
export const bufferToBase58 = (buffer: Uint8Array): string => {
return getBase58Decoder().decode(buffer);
};
Next, we'll add a function to get the explorer URL for an address or transaction. Modern terminal apps support clicking links, so it will allow us to see each mint as it's created:
export const getExplorerUrl = (address: string, type: "address" | "tx") => {
return `https://explorer.solana.com/${type}/${address}`;
};
A seguir, vamos adicionar uma função para obter o discriminador de um manipulador de instruções a partir do IDL de um programa. Podemos utilizar isto mais tarde para identificar as instruções que chamaram esse manipulador de instruções.
export const getInstructionHandlerDiscriminator = (
programIdl: any,
instructionName: string
) => {
const instruction = programIdl.instructions.find(
(instruction: any) => instruction.name === instructionName
);
const discriminatorBytes = instruction.discriminator;
return Buffer.from(discriminatorBytes);
};
A seguir, vamos adicionar uma função para obter os nomes e os índices das contas utilizadas num gestor de instruções. Podemos utilizar esta função mais tarde para filtrar as transações, de modo a incluir apenas as instruções destinadas a um determinado gestor de instruções.
export const getAccountsFromIdl = (
programIdl: any,
instructionName: string
): Array<{ name: string; index: number }> => {
const instruction = programIdl.instructions.find(
(instruction: any) => instruction.name === instructionName
);
if (!instruction) {
throw new Error(`Instruction '${instructionName}' not found in IDL`);
}
return instruction.accounts.map((account: any, index: number) => ({
name: account.name,
index: index,
}));
};
Passo 4: Criar constantes
Há algumas coisas que não mudam com tanta frequência, por isso vamos defini-las. Crie um novo ficheiro chamado lib/constants.ts e adicione o seguinte código:
// Set by Solana
export const SOLANA_SLOT_TIME_MS = 400;
// Set by Quicknode
export const MAX_SLOTS_TO_REPLAY = 3000;
// Set by the late 18th century French scientists
export const SECONDS = 1000;
// Set by ancient Babylonians
export const MINUTES = SECONDS * 60;
export const MAX_TIME_TO_REPLAY_MS = MAX_SLOTS_TO_REPLAY * SOLANA_SLOT_TIME_MS;
export const MAX_TIME_TO_REPLAY_MINUTES = MAX_TIME_TO_REPLAY_MS / 1000 / 60;
Passo 5: CriargRPC nossogRPC Solana
Crie um novo ficheiro chamado yellowstone.ts. Vamos tornar isto o mais genérico possível, para que possa reutilizá-lo em vários projetos. Comece por importar as dependências relevantes — o grpc cliente, gRPC e os nossos auxiliares, interfaces e constantes.
import Client, {
CommitmentLevel,
SubscribeRequest,
SubscribeUpdate,
SubscribeUpdateTransaction,
} from "@triton-one/yellowstone-grpc";
import { ClientDuplexStream } from "@grpc/grpc-js";
import { bufferToBase58, getExplorerUrl } from "./helpers";
import { CompiledInstruction, MintInformation } from "./interfaces";
import {
MAX_SLOTS_TO_REPLAY,
MAX_TIME_TO_REPLAY_MINUTES,
SOLANA_SLOT_TIME_MS,
} from "./constants";
Vamos criar algumas funções úteis.gRPC Solana devolve,gRPC , o slot como uma cadeia de caracteres, por isso vamos corrigir isso:
export const getCurrentSlot = async (
yellowstoneClient: Client
): Promise<number> => {
const currentSlotString = await yellowstoneClient.getSlot();
return Number(currentSlotString);
};
Criar um pedido de subscrição
Esta função irá criar um SubscreverSolicitar que irá monitorizar os IDs dos programas indicados e as contas necessárias.
Queremos ser o mais específicos possível com os nossos filtros, para que possamos reduzir a quantidade de dados que recebemos do servidor:
accountInclude: incluir transações que utilizam qualquer conta da matriz.excluir conta: excluir transações que utilizam qualquer conta da matriz.conta obrigatória: incluir apenas as transações que utilizam todos contas da matriz.
Preferimos utilizar conta obrigatória uma vez que é mais específico do que accountInclude e excluir conta.
export const createSubscribeRequest = (
includedAccounts: Array<string>,
excludedAccounts: Array<string>,
requiredAccounts: Array<string>,
fromSlot: number | null = null
): SubscribeRequest => {
// See https://github.com/rpcpool/yellowstone-grpc?tab=readme-ov-file#filters-for-streamed-data for full list of filters.
const request: SubscribeRequest = {
commitment: CommitmentLevel.CONFIRMED,
accounts: {},
slots: {},
transactions: {
// We can have multiple filters here, but for this demo, we'll only have one.
// When we get events, we can check which filter was matched.
// https://github.com/rpcpool/yellowstone-grpc?tab=readme-ov-file#transactions
pumpFun: {
vote: false,
failed: false,
accountInclude: includedAccounts,
accountExclude: excludedAccounts,
accountRequired: requiredAccounts,
},
},
transactionsStatus: {},
entry: {},
blocks: {},
blocksMeta: {},
accountsDataSlice: [],
ping: undefined,
};
if (fromSlot) {
// Solana gRPC expects the slot as a string, so let's fix that.
request.fromSlot = String(fromSlot);
}
return request;
};
Vamos também criar uma função para enviar o pedido de subscrição para ogRPC Solana — vamos criar o fluxo daqui a pouco.
export const sendSubscribeRequest = (
stream: ClientDuplexStream<SubscribeRequest, SubscribeUpdate>,
request: SubscribeRequest
): Promise<void> => {
return new Promise<void>((resolve, reject) => {
stream.write(request, (error: Error | null) => {
if (error) {
reject(error);
} else {
resolve();
}
});
});
};
Adicionar alguns filtros do lado do cliente
A maior parte da nossa filtragem é feita através Solana gRPC, mas este não filtra diretamente as transações por gestor de instruções, por isso vamos adicionar uma verificação adicional do lado do cliente:
// Solana gRPC doesn't directly filter by instruction handler so we have to
// do it client-side.
export const checkInstructionMatchesInstructionHandlers = (
instruction: CompiledInstruction,
instructionHandlerDiscriminators: Array<Uint8Array>
): boolean => {
return (
instruction?.data &&
instructionHandlerDiscriminators.some((instructionHandlerDiscriminator) =>
Buffer.from(instructionHandlerDiscriminator).equals(
instruction.data.slice(0, 8)
)
)
);
};
Vamos também criar uma função para criar um objeto bem organizado com pares de nome/morada, para que possamos obter as moradas que esta instrução
utilizou para nomes de contas específicos (como o hortelã registo de cada novo token no Pump.fun) e apresentá-los numa tabela bem organizada.
export const getAccountsByName = (
accountsToInclude: Array<{ name: string; index: number }>,
instruction: CompiledInstruction,
accountKeys: Array<Uint8Array>
): Record<string, string> => {
return accountsToInclude.reduce<Record<string, string>>(
(accumulator, account) => {
const accountIndex = instruction.accounts[account.index];
const address = bufferToBase58(accountKeys[accountIndex]);
accumulator[account.name] = address;
return accumulator;
},
{}
);
};
Pronto! Agora vamos começar a tratar das atualizações que recebemos do Solana gRPC, utilizando as funções que acabámos de criar.
Cria uma função para transformar o `SubscribeUpdate` em informações sobre a moeda «mint» bem formatadas
Vamos criar uma função que irá converter um SubscreverAtualizar dogRPC da Solana gRPC um MintInformation — um objeto simples que contém o endereço de emissão, a assinatura da transação e o número do slot.
export const getMintInfoFromUpdate = (
update: SubscribeUpdate,
instructionHandlerDiscriminators: Array<Uint8Array>,
accountsToInclude: Array<{ name: string; index: number }>
): null | MintInformation => {
// Check the filter name that was matched
// (Solana gRPC also sends other things like 'ping' updates, but we don't care about those)
if (!update.filters.includes("pumpFun")) {
return null;
}
// These should never happen in this demo,
// since our filter's matches will include the right properties.
// but let's satisfy the type checker.
const transaction = update.transaction?.transaction;
const message = transaction?.transaction?.message;
const slot = update.transaction?.slot;
if (!transaction || !message || !slot) {
return null;
}
// Find the instruction that matches our target instruction handler
const instruction =
message.instructions.find((instruction) =>
checkInstructionMatchesInstructionHandlers(
instruction,
instructionHandlerDiscriminators
)
) || null;
if (!instruction) {
return null;
}
// Make a nice Object of account value/address pairs, so we can get the address
// values this instruction used for each account name.
const accountsByName = getAccountsByName(
accountsToInclude,
instruction,
message.accountKeys
);
const base58TransactionSignature = bufferToBase58(transaction.signature);
return {
mint: getExplorerUrl(accountsByName.mint, "address"),
transaction: getExplorerUrl(base58TransactionSignature, "tx"),
slot: Number(slot),
};
};
Ligar o fluxo às nossas funções
Agora estamos prontos para ligar o fluxo às nossas funções. Sempre que o fluxo enviar uma atualização, vamos chamar obterInformaçõesSobreMintA partirDaAtualização para obter as informações do Mint e imprimi-las na consola.
Abrir yellowstone.ts e adicione o seguinte código:
export const handleStreamEvents = (
stream: ClientDuplexStream<SubscribeRequest, SubscribeUpdate>,
instructionDiscriminators: Array<Uint8Array>,
accountsToInclude: Array<{ name: string; index: number }>
): Promise<void> => {
return new Promise<void>((resolve, reject) => {
stream.on("data", (update: SubscribeUpdate) => {
const mintInfo = getMintInfoFromUpdate(
update,
instructionDiscriminators,
accountsToInclude
);
if (mintInfo) {
console.log("💊 New Pump.fun Mint Detected!");
console.table(mintInfo);
console.log("\n");
}
});
stream.on("error", (error: Error) => {
console.error("Stream error:", error);
reject(error);
stream.end();
});
stream.on("end", () => {
console.log("Stream ended");
resolve();
});
stream.on("close", () => {
console.log("Stream closed");
resolve();
});
});
};
É tudo yellowstone.ts!
Passo 6: Escolher os nossos filtros e juntar tudo
Agora estamos prontos para criar o script principal. Aqui, vamos definir vários valores para as transações que pretendemos monitorizar, vamos estabelecer ligação aogRPC Solana e, em seguida, chamar as funções que acabámos de criar para monitorizar a transação.
Vamos tentar ser o mais específicos possível com os nossos filtros, para que possamos reduzir a quantidade de dados que recebemos do servidor, utilizar menos créditos da API e tornar o nosso script mais eficiente. Poderíamos simplesmente incluir PROGRAM_ID para obter todas as transações que envolvem o programa, mas como estamos apenas à procura de um subconjunto de instruções (neste caso, criar (instruções), poderíamos analisar o IDL e identificar quaisquer contas adicionais que possam ter sido apenas passadas para o criar manipulador de instruções. Uma vez que o Autoridade de Emissão de Tokens da Pump.fun é utilizado em todos os criar gestor de instruções; assim, ao exigir ambas as contas, podemos reduzir a quantidade de dados que recebemos e tornar o nosso script mais eficiente.
Também vamos querer indicar o endereço específico utilizado para «mint». Solana utilizam matrizes, e não contas com nome, pelo que precisamos de obter o índice da conta que queremos monitorizar a partir do IDL do programa, tal como fizemos anteriormente. Pode incluir outras contas que queira monitorizar (pode obter o respetivo índice a partir do IDL do seu programa).
Crie um novo ficheiro chamado monitor-program.ts e adicione o seguinte código:
import {
createSubscribeRequest,
handleStreamEvents,
sendSubscribeRequest,
getSlotFromTimeAgo,
} from "./lib/yellowstone";
import { getYellowstoneEndpointAndToken } from "./lib/quicknode";
import { env } from "node:process";
import { MINUTES } from "./lib/constants";
import Client from "@triton-one/yellowstone-grpc";
import {
getInstructionHandlerDiscriminator,
getAccountsFromIdl,
} from "./lib/helpers";
import programIdl from "./program.json";
// We're watching the pump.fun program
const PROGRAM_ID = programIdl.address;
// We're watching the create() instruction handler
const PUMP_FUN_CREATE_INSTRUCTION_HANDLER_DISCRIMINATOR =
getInstructionHandlerDiscriminator(programIdl, "create");
const PUMP_FUN_MINT_AUTHORITY = "TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM";
// The program and required accounts to watch via Solana gRPC
// See https://github.com/rpcpool/yellowstone-grpc?tab=readme-ov-file#filters-for-streamed-data for full list of filters.
const requiredAccounts: Array<string> = [PROGRAM_ID, PUMP_FUN_MINT_AUTHORITY];
// After we get the events from Solana gRPC, we'll filter them by the instruction handler (onchain function) being invoked
const instructionDiscriminators: Array<Uint8Array> = [
PUMP_FUN_CREATE_INSTRUCTION_HANDLER_DISCRIMINATOR,
];
// Get account information from the IDL for the create instruction
// This will include all accounts used in the create instruction with their names and indices
const ACCOUNTS_TO_INCLUDE = getAccountsFromIdl(programIdl, "create");
const rpcEndpoint = env["QUICKNODE_SOLANA_MAINNET_ENDPOINT"];
if (!rpcEndpoint) {
throw new Error(
"QUICKNODE_SOLANA_MAINNET_ENDPOINT environment variable is required"
);
}
const { yellowstoneEndpoint, yellowstoneToken } =
getYellowstoneEndpointAndToken(rpcEndpoint);
const yellowstoneClient = new Client(yellowstoneEndpoint, yellowstoneToken, {
grpcDefaultCompressionAlgorithm: 0, // 0 = gzip, 1 = zstd
});
await yellowstoneClient.connect();
// Somewhat confusingly, we need to call `subscribe` on the client to get a stream
// and then make a subscribe request to the stream.
const stream = await yellowstoneClient.subscribe();
// We'll use this later in the guide
const fromSlot = null;
// Create subscribe request with fromSlot parameter
const request = createSubscribeRequest([], [], requiredAccounts, fromSlot);
await sendSubscribeRequest(stream, request);
console.log(
"🔌 Geyser connection established - watching new Pump.fun token mints...\n"
);
await handleStreamEvents(
stream,
instructionDiscriminators,
ACCOUNTS_TO_INCLUDE
);
Adicione o seuendpoint Quicknode endpoint um .env ficheiro
Antes de executar o script, obter endpoint seu endpoint do Quicknode e adicione-o a um novo ficheiro chamado .env, substituindo o endpoint seu próprio:
QUICKNODE"mainnet"
.env Adicione o ficheiro ao seu repositório!Não te comprometas com o teu .env ficheiro para o seu repositório, uma vez que contémendpoint seuendpoint Quicknode . Isto representa um risco de segurança, pois permite que qualquer pessoa aceda endpoint seu endpoint o utilize sem a sua autorização. Adicione-o ao seu .gitignore ficheiro para evitar isso.
Executar o script
Agora estamos prontos para executar o script. No seu terminal, execute o seguinte comando:
npx tsx --env-file=.env monitor-program.ts
Deve ver o seguinte resultado:
npx tsx --env-file=.env monitor-program.ts
🔌 Geyser connection established - watching new Pump.fun token mints...
💊 New Pump.fun Mint Detected!
┌─────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ (index) │ Values │
├─────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ mint │ 'https://explorer.solana.com/address/G8XYfdnujEiwivG8LZuj5NKppUkx6nn6Wo72A1Ckpump' │
│ transaction │ 'https://explorer.solana.com/tx/2sSHoWvNNuHVMJMPLeramPNKj8VJvtjhG6hLrci4FmnYG6xmPEqRiKHAWY15wcTGMxqhgnLi8DRBPWEM3r5bSAut' │
│ slot │ 358713246 │
└─────────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
💊 New Pump.fun Mint Detected!
┌─────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ (index) │ Values │
├─────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ mint │ 'https://explorer.solana.com/address/EjrHSwxfZ3mCbLnnuXg4xYuHuzvMCbB5S4ptVzxAfonq' │
│ transaction │ 'https://explorer.solana.com/tx/2rR47UGUcv5EY5hTij8eVshZPHqLV2mUVJdZYr4kxm25EQwLdumqt3v9RfLMfGBM7ENVpRGbdD1b3Q7L4mo3W9TX' │
│ slot │ 358713253 │
└─────────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
💊 New Pump.fun Mint Detected!
┌─────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ (index) │ Values │
├─────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ mint │ 'https://explorer.solana.com/address/8prBRtMZvYpppiUfcKbmteQx8gHqn8XicDZAPfPRpump' │
│ transaction │ 'https://explorer.solana.com/tx/5cS6buykKeFaE9bNDzoo8PvKixew4cV14hJMMLYSwuvQm5xWrxr2uRf2Hf3ZRrwizKbc8GsytmbxbpaXhHgYaZYJ' │
│ slot │ 358713276 │
└─────────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Pode clicar no endereço de emissão para ver as informações de emissão no Solana :

Tem algum problema? O código completo está disponível no repositório GitHub do monitor pump.fun.
Repetição histórica com o fromSlot
Por vezes, queremos retomar a partir de um determinado momento no passado — para clientes que possam ter perdido mensagens ou que necessitem de recuperação de dados durante o processo de recuperação. Também podemos retomar a partir de qualquer momento nos últimos 3000 intervalos (20 minutos).
Normalmente, guardamos o número da ranhura mais recente à medida que surgem novas ranhuras e definimos fromSlot a esse número no pedido de subscrição aquando da recuperação.
Para esta demonstração, vamos simplesmente escolher um intervalo de tempo de há algum tempo atrás — abrir yellowstone.ts e adicione a seguinte função:
// Allow us to get the slot from a given time in the past
export const getSlotFromTimeAgo = async (
yellowstoneClient: Client,
timeAgo: number
) => {
const now = Date.now();
const fromTime = now - timeAgo;
const slotsAgo = Math.ceil(timeAgo / SOLANA_SLOT_TIME_MS);
if (slotsAgo > MAX_SLOTS_TO_REPLAY) {
throw new Error(
`From time ${new Date(
fromTime
).toISOString()} is too far in the past. Maximum time to replay is ${MAX_TIME_TO_REPLAY_MINUTES} minutes.`
);
}
const currentSlot = await getCurrentSlot(yellowstoneClient);
const fromSlot = currentSlot - slotsAgo;
return fromSlot;
};
Depois, em monitor-program.ts, podemos definir fromSlot para a ranhura há 5 minutos:
// Typically, we would record the most recent slot when each event is recieved,
// and then replay from that slot if we need to recover.
// For this demo, let's get the last 5 minutes of transactions
const fromSlot = await getSlotFromTimeAgo(yellowstoneClient, 5 * MINUTES);
Execute novamente o script e deverá ver uma série de dados históricos antes de chegar ao tempo real. Pode clicar em qualquer uma das emissões ou transações para ver os detalhes no Solana , incluindo o tempo decorrido.
Conclusão
Neste guia, explorámos como utilizargRPC Solana gRPC monitorizar Solana em tempo real. Centrámo-nos no acompanhamento da emissão de novos tokens pelo programa Pump.fun, mas os princípios que abordámos podem ser utilizados para monitorizar qualquer Solana ou conta Solana .
As you continue to build on Solana, consider how you can leverage Solana gRPC to create more responsive and efficient applications. Whether you're building a trading bot, an analytics dashboard, or a complex DeFi application, low latency real time data access can give you a significant edge.
Recursos
- GitHub: Monitor Pump.fun
- Documentação: Solana gRPC
- Solana gRPC add-on
- Solana : Plug-ins Geyser para Solana
- GitHub: gRPC Yellowstone
- GitHub: Geyser Park - Lista não oficial de plugins do Geyser
Vamos entrar em contacto!
Adoraríamos saber como está a utilizar Solana gRPC. Envie-nos a sua experiência, perguntas ou comentários através do Twitter ou do Discord.
