Análise de dados
Os fluxos de trabalho analíticos extraem dados Solana de snapshots RPC, exportações de indexadores ou APIs de provedores para pandas ou Polars para agregação, junções e visualização. Python é a cola padrão entre dados da cadeia do Agave 4.1.1 e notebooks, painéis e relatórios em lote.
Receita
Cartão de receitas de referência rápida - pronto para copiar e colar.
import polars as pl
df = pl.DataFrame(
{
"signature": [],
"slot": [],
"fee_lamports": [],
"success": [],
}
)
summary = df.group_by("success").agg(pl.col("fee_lamports").mean())
Quando fazer isso:
- Análise exploratória em Jupyter em amostras de transações.
- Métricas diárias de tesouraria ou protocolo (volume, taxas, assinantes únicos).
- Participar de eventos on-chain com CRM off-chain ou dados de produtos.
- Construção de conjuntos de treinamento para monitoramento e detecção de anomalias.
Exemplo de trabalho
import asyncio
import polars as pl
from solders.pubkey import Pubkey
from solana.rpc.async_api import AsyncClient
PROGRAM = Pubkey.from_string("<PROGRAM_ID>")
RPC = "https://api.devnet.solana.com"
async def collect_signatures(limit: int = 200):
async with AsyncClient(RPC) as client:
resp = await client.get_signatures_for_address(PROGRAM, limit=limit)
rows = [
{
"signature": str(item.signature),
"slot": item.slot,
"err": item.err is not None,
"block_time": item.block_time,
}
for item in resp.value
]
return pl.DataFrame(rows)
async def enrich_with_fees(df: pl.DataFrame):
async with AsyncClient(RPC) as client:
fees = []
for sig in df["signature"].to_list():
tx = await client.get_transaction(sig, max_supported_transaction_version=0)
meta = tx.value.transaction.meta if tx.value else None
fees.append(meta.fee if meta else None)
return df.with_columns(pl.Series("fee_lamports", fees))
async def main():
df = await collect_signatures()
df = await enrich_with_fees(df)
print(df.group_by("err").agg(pl.len(), pl.col("fee_lamports").mean()))
asyncio.run(main())
O que isso demonstra: O histórico de assinatura semeia um quadro Polars sem grandes profundidades.
- O enriquecimento por transação busca campos de metataxa.
- Agrupar por agrega médias de taxas de sucesso versus falha.
- O Async RPC é adequado para scripts de enriquecimento em lote.
Aprofundamento
Como funciona
- Extrair: RPC (
getSignaturesForAddress,getTransaction), exportações Geyser ou tabelas de armazém. - Normalizar: esquemas estáveis (assinatura, slot, program_id, instrução_index, quantidade).
- Transformar: pandas/Polars para junções, funções de janela, reamostragem por slot/tempo.
- Carregar: Parquet para armazenamento de objetos, DuckDB, BigQuery ou ferramentas de painel.
Compensações de fontes de dados
| Fonte | Frescura | Volume | Acesso Python |
|---|---|---|---|
| Paginação RPC | Em tempo real | Baixo/médio | solana-py assíncio |
| API indexadora | Minutos | Alto | httpx + polares |
| Plugin Geyser | Transmissão | Muito alto | Consumidor gRPC (geralmente Rust) -> Parquet |
| Conjuntos de dados públicos | Diariamente | Histórico | read_parquet |
Notas Python
# Prefer Polars for large scans
df = pl.scan_parquet("s3://bucket/txs/*.parquet").filter(pl.col("slot") > 250_000_000).collect()
# Integer amounts only
df = df.with_columns((pl.col("amount_raw") / 10**decimals).alias("amount")) # watch float policy
# pandas interop
pdf = df.to_pandas()
Pegadinhas
- Preenchimento de RPC em escala - lento e com taxa limitada. Correção: exportação em massa do indexador ou do provedor.
- Quantidades de tokens flutuantes - perda de precisão em casas da moeda de 9 decimais. Correção: mantenha strings/números inteiros u64 brutos em quadros.
- Loops
getTransactionilimitados - caro. Correção: assinaturas em lote; armazenar em cache as respostas ao Parquet. - Desvio de esquema entre versões do programa - quebra junções. Correção: coluna de versão do mapa IDL/discriminador.
- Confusão de fuso horário em
block_time- Segundos Unix UTC. Correção: conversãodatetimeexplícita em Polars.
Alternativas
| Alternativa | Usar quando | Não use quando |
|---|---|---|
| dbt + armazém | Métricas de toda a organização | Espiada rápida do caderno |
| Indexador em Rust | Streaming em subsegundos | Equipe exclusiva de analistas |
| Flipside / Dune SQL | Painéis padrão | Layouts de conta personalizados |
@solana/kit no navegador | Visualizações específicas do usuário | História em escala de TB |
Perguntas frequentes
pandas ou polares?
Polares para grandes varreduras locais; pandas é adequado para amostras pequenas e gráficos matplotlib.
Como obter todos os txs do programa?
Prefira um indexador; O RPC getSignaturesForAddress no ID do programa está incompleto para instruções internas.
Decodificar eventos anchor?
Analise logs com layout de evento IDL ou use um indexador que emita eventos estruturados.
Armazenar bruto ou analisado?
Armazene bytes brutos + colunas analisadas para reprodução quando os layouts mudarem.
Qualidade dos dados Devnet?
Trate apenas como teste - as distribuições diferem da rede principal.
Agendamento?
Airflow/Prefect cron com partições Parquet idempotentes por data de slot.
PII?
Os endereços da carteira podem ser confidenciais – classifique os conjuntos de dados de acordo.
Análise gráfica?
Exporte listas de bordas para NetworkX a partir de quadros de transferência.
Painéis em tempo real?
Transmita via websockets para um buffer; microlote para Polars a cada N segundos.
Controle de custos?
Cache de respostas RPC; desduplicar assinaturas antes de getTransaction.
Relacionado
- Leitura de dados da cadeia - Leituras RPC e DAS
- Construindo um indexador - pipelines de produção
- Paginação e Eficiência - Lote RPC
- Python para práticas recomendadas de Solana - higiene do serviço
Versões Stack: Esta página foi escrita para Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, anchor-lang 0.32.1, Rust 1.91.1, @solana/kit 7.0.0, Surfpool 0.12.0 e LiteSVM 0.6.x.