Construindo Transações em Python
As transações Solana agrupam uma ou mais instruções com um conjunto recente de blockhash e assinante. Em Python, você compõe instruções com solders, anexa assinantes, simula no Agave 4.1.1 RPC e depois envia com solana-py.
Receita
Cartão de receitas de referência rápida - pronto para copiar e colar.
from solders.keypair import Keypair
from solders.pubkey import Pubkey
from solders.hash import Hash
from solders.message import Message
from solders.transaction import VersionedTransaction
from solders.system_program import TransferParams, transfer
from solana.rpc.api import Client
client = Client("https://api.devnet.solana.com")
payer = Keypair()
blockhash = Hash.from_string(str(client.get_latest_blockhash().value.blockhash))
ix = transfer(TransferParams(from_pubkey=payer.pubkey(), to_pubkey=Pubkey.default(), lamports=1000))
msg = Message.new_with_blockhash([ix], payer.pubkey(), blockhash)
tx = VersionedTransaction(msg, [payer])
Quando fazer isso:
- Serviços de back-end que retransmitem transações assinadas pelo usuário ou de custódia.
- Bots que montam lotes atômicos com múltiplas instruções.
- Scripts que espelham transferências Solana CLI 3.0.10 com lógica customizada.
- Pipelines que adicionam instruções de orçamento de cálculo e taxas prioritárias.
Exemplo de trabalho
import asyncio
from solders.compute_budget import set_compute_unit_limit, set_compute_unit_price
from solders.keypair import Keypair
from solders.pubkey import Pubkey
from solders.hash import Hash
from solders.message import Message
from solders.transaction import VersionedTransaction
from solders.system_program import TransferParams, transfer
from solana.rpc.async_api import AsyncClient
from solana.rpc.types import TxOpts
RPC = "https://api.devnet.solana.com"
async def send_with_budget(dest: Pubkey, lamports: int, micro_lamports: int):
payer = Keypair()
async with AsyncClient(RPC) as client:
bh = await client.get_latest_blockhash()
blockhash = Hash.from_string(str(bh.value.blockhash))
ixs = [
set_compute_unit_limit(50_000),
set_compute_unit_price(micro_lamports),
transfer(TransferParams(from_pubkey=payer.pubkey(), to_pubkey=dest, lamports=lamports)),
]
msg = Message.new_with_blockhash(ixs, payer.pubkey(), blockhash)
tx = VersionedTransaction(msg, [payer])
sim = await client.simulate_transaction(tx)
if sim.value.err:
raise RuntimeError(f"simulation failed: {sim.value.err} logs={sim.value.logs}")
resp = await client.send_transaction(
tx,
opts=TxOpts(skip_preflight=True, preflight_commitment="confirmed"),
)
await client.confirm_transaction(resp.value, commitment="confirmed")
return resp.value
asyncio.run(send_with_budget(Pubkey.default(), 10_000, 5_000))
O que isso demonstra:
- As instruções do cálculo do orçamento precedem as instruções do programa.
- O Blockhash é obtido diretamente do RPC por tentativa de envio.
- A simulação valida metas da conta antes do envio.
- A pesquisa de confirmação aguarda o compromisso de
confirmed.
Aprofundamento
Como funciona
- Uma mensagem lista chaves de conta, blockhash recente e instruções compiladas.
- Os signatários devem cobrir todas as contas de signatários graváveis no cabeçalho da mensagem.
- Transações versionadas suportam tabelas de pesquisa de endereços (v0) para listas de contas grandes.
- RPC
sendTransactiontransmite para o líder; a confirmação é assíncrona.
Lista de verificação do conjunto de transações
| Etapa | API | Notas |
|---|---|---|
| 1. Instruções de construção | solders.*_program ajudantes | Ordem é importante para efeitos colaterais da CPI |
| 2. Buscar blockhash | get_latest_blockhash | Atualizar ao tentar novamente |
| 3. Criar mensagem | Message.new_with_blockhash | O pagador da taxa é o primeiro signatário |
| 4. Assine | VersionedTransaction(msg, signers) | Todos os signatários necessários presentes |
| 5. Simular | simulate_transaction | Inspecione logs em caso de erro |
| 6. Enviar | send_transaction | Ajuste skip_preflight por ambiente |
Notas Python
# Partial signing for multisig or remote signers
tx = VersionedTransaction(msg, []) # unsigned
tx.sign([local_signer], blockhash)
# ship bytes to cosigner, then merge signatures per your custody model
# Read confirmation status
status = client.get_signature_statuses([sig])
Pegadinhas
- Signatário ausente - a simulação retorna
MissingRequiredSignature. Correção: auditar sinalizadoresAccountMeta.is_signer. - Blockhash expirou -
BlockhashNotFound. Correção: reconstruir mensagem com novo blockhash. - Fundos insuficientes para aluguel - a criação de contas precisa de pagamentos além do valor da transferência. Correção: simular e financiar o pagador.
- Ordem de instrução - o cálculo do orçamento deve ser o primeiro. Correção: anexar instruções de orçamento.
- Assumindo finalidade síncrona -
send_transactionretorna uma assinatura, não uma confirmação. Correção: enqueteconfirm_transaction.
Alternativas
| Alternativa | Usar quando | Não use quando |
|---|---|---|
Solana CLI transfer | Operações manuais | Estratégias automatizadas |
@solana/kit na rota API | Carteira do navegador + assinatura do servidor | Pilha Python pura |
| Pacote Jito RPC | Bots MEV sensíveis à latência | Transferências simples |
| Serviço de assinatura remota | Trocas de custódia | Teste de desenvolvimento individual |
Perguntas frequentes
Transação legada versus transação versionada?
Prefira VersionedTransaction para novo código Python; ele se alinha com as transações v0 no Agave 4.x.
Quantas instruções por tx?
O limite prático é o tamanho da transação (~1232 bytes) e o orçamento da CU - simule para validar.
Posso misturar instruções de token SPL?
Sim - importe auxiliares SPL ou construa Instruction manualmente com o ID do programa Token.
Como diferenciar o pagador da taxa do signatário?
Passe a chave pública do pagador para Message.new_with_blockhash e inclua sua assinatura.
Tentativas novamente em caso de falha?
Atualize o blockhash, opcionalmente, aumente set_compute_unit_price, espera exponencial.
Transações nonce duráveis?
Suportado, mas raro em bots - use quando a rotatividade de blockhash for problemática.
Como depurar erros de programa?
Leia os logs simulate_transaction - eles correspondem à saída msg! na cadeia.
Segurança da rede principal?
Execute um teste no devnet e, em seguida, habilite limites de gastos em carteiras quentes.
Suporte ALT em Python?
Use APIs de mensagens v0 quando a lista de contas exceder os limites herdados - consulte a documentação RPC ALT.
Construção de transação AnchorPy?
AnchorPy pode construir txs a partir de IDL - ainda usa solders internas.
Relacionado
- solders & solana-py - Visão geral do SDK
- Taxas prioritárias - mercado de taxas
- Simulando Transações - teoria da simulação
- Trading e Bots - automaçã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.