NOVO: Helius adquire a Light Protocol
checklist de migração para o Solana Agave 4.2
Blog/Atualizações

Agave 4.2: checklist de migração

Produto na HeliusKiryl Miranovich no XKiryl Miranovich no LinkedIn
5 min de leitura

Apresentamos o conjunto de recursos do Agave 4.2 em nossa visão geral da versão. Este post aborda a migração: o que deixa de funcionar e como verificar sua integração antes da ativação do gate de recurso.

A maioria dessas alterações retorna dados incorretos ou ausentes em vez de erros. Por isso, elas não aparecerão nos seus logs de exceções.

Cronograma de ativação

QuandoO quêStatus
11 de ago. de 2026A Anza recomenda a versão 4.2 para a mainnet; começam as atualizações dos validadoresEm andamento
Conforme os nós são atualizadosA supressão de atualizações de contas e as alterações do Token-2022 em jsonParsed entram em vigorConcluído
Primeiro limite de época após a atualizaçãoO valor DeactivatedStake rewardType aparece nas recompensasConcluído
Época 1020A duração dos slots cai de 400 ms para 350 ms, a primeira de quatro etapas rumo a 200 msConcluído
Época 1024A duração dos slots cai de 350 ms para 300 msAgendado (previsto para 28 de ago.)
Gate de recurso, data a definirTransação v1 (transações de 4.096 bytes)Pendente (nenhuma data anunciada; prepare-se como se a ativação fosse ocorrer na próxima semana)
Cinco gates de recursos, datas a definirRedução do aluguel, de 6.960 lamports/byte até 696Pendente
Agave 4.3, previsto para out. de 2026Consenso AlpenglowVersão futura

Alterações incompatíveis do Agave 4.2

Uma transação v1 faz a chamada inteira falhar

A SIMD-0296 e a SIMD-0385 aumentam o limite de tamanho das transações da Solana para 4.096 bytes por meio de um novo formato de transação.

O espaço adicional permite que os desenvolvedores executem cargas de trabalho on-chain maiores, como provas ZK ou rotas de DEX com mais etapas. 

O problema: uma única transação v1 em um bloco faz getBlock falhar para o bloco inteiro se a chamada não definir maxSupportedTransactionVersion: 1.

As outras transações também não são retornadas; a chamada inteira gera um erro. getTransaction e getTransactionsForAddress (com transactionDetails = full) falham da mesma forma diante de qualquer transação v1. 

Como corrigir:

  • Atualize seu SDK para uma versão que decodifique a v1. O suporte está sendo implementado nos diferentes clientes. Se o seu SDK ainda não lançou suporte a transações v1, acompanhe as notas de versão em busca de transaction v1 ou SIMD-0385.
    • Clientes JS populares: @solana/kit 8.0+, @solana/web3.js v3
    • Crates Rust populares: solana-rpc-client-api 4.2+, solana-client 4.2+, solana-transaction 4.2+, solana-compute-budget 4.2+, outros crates da Anza.
  • Defina maxSupportedTransactionVersion: 1 em todas as chamadas getBlock, getTransaction e getTransactionsForAddress (com transactionDetails = full)
  • Defina maxSupportedTransactionVersion: 1 no objeto de opções de todas as assinaturas transactionSubscribe do Enhanced WebSockets (com transactionDetails definido como full ou accounts). As assinaturas copiadas dos exemplos da documentação têm esse valor definido como 0; altere-o para 1
Código
{
  "jsonrpc": "2.0",
  "id": "1",
  "method": "getTransactionsForAddress",
  "params": [
    "Vote111111111111111111111111111111111111111",
    {
      "transactionDetails": "full",
      "sortOrder": "desc",
      "filters": {
        "status": "succeeded"
      },
      "maxSupportedTransactionVersion": 1
    }
  ]
}

O parâmetro declara a versão mais recente que o seu cliente processa. É seguro defini-lo agora, sem alterar a forma como transações legadas e v0 são retornadas.

Falhas no orçamento computacional de transações v1

Uma transação v1 armazena seu limite computacional e sua taxa de prioridade no objeto transactionConfig, em vez de usar instruções ComputeBudget. Painéis de taxas e estimadores de taxas de prioridade que detectam taxas procurando correspondências com essas instruções interpretam todas as transações v1 como se pagassem zero, sem gerar erros.

Como corrigir:

Em vez disso, leia os valores do novo campo priorityFee na configuração da transação. Observe que o novo campo priorityFee informa a taxa total em lamports, não o preço por unidade computacional.

Código
"message": {
  "instructions": ["… no ComputeBudget instruction here …"],
  "recentBlockhash": "...",
  "transactionConfig": {
    "computeUnitLimit": 200000,
    "heapSize": null,
    "loadedAccountsDataSizeLimit": 200000,
    "priorityFee": 50000
  }
}

Contas inalteradas deixam de emitir atualizações

O Agave 4.2 só emite eventos de conta quando uma conta é realmente gravada. Para assinaturas de contas gRPC e WSS do LaserStream, isso representa cerca de 80% menos eventos.

Como corrigir:

  1. Se você associa transações a atualizações de contas, pare de esperar uma atualização de cada conta gravável; trate a ausência de atualização como "a conta não mudou". Somente o pagador da taxa tem atualização garantida, pois ele sempre paga a taxa.
  2. Se você usa a frequência de atualizações como sinal de integridade, remova essa verificação para contas que são bloqueadas com frequência, mas raramente alteradas. Uma conta sem atividade está íntegra; ela deixou de emitir porque nada mudou.

Um novo valor de rewardType

As contas de staking que concluem a desativação agora recebem o pagamento final sob um novo valor de rewardType, DeactivatedStake, nos arrays de recompensas de getBlock e blockSubscribe. O formato do objeto de recompensa é idêntico ao do Agave 4.1. Portanto, um parser que aceite somente os tipos de recompensa já conhecidos ignorará os pagamentos DeactivatedStake sem gerar erros.

getInflationReward não é afetado; o risco só existe quando você mesmo analisa arrays de recompensas brutos.

Como corrigir:

Adicione DeactivatedStake aos valores de rewardType aceitos pelo seu parser e registre qualquer valor não reconhecido em vez de descartar o registro.

Código
{
  "pubkey": "...",
  "lamports": 10000000,
  "postBalance": 50000000000,
  "rewardType": "DeactivatedStake",
  "commission": null,
  "commissionBps": 500
}

Token-2022: um campo removido, análise expandida

Nas respostas de jsonParsed, depositConfidentialTransfer e withdrawConfidentialTransfer perdem os campos de origem e destino em favor de um único campo de conta. Os rótulos antigos estavam incorretos; cada instrução afeta uma conta de token.

A correção é atualizar os parsers do Token-2022 para que ofereçam suporte ao novo campo.

Código
{
  "parsed": {
    "type": "depositConfidentialTransfer",
    "info": {
      "account": "6XVfUq9jZQtBfqcm1Rz8fBhViyoyzWiEUAaWnQ9AmXeR",
      "mint": "8fJ7bCZo2vZ3vAnyCBQgZuLYuTX1qPnKvsMKotk92B2J",
      "amount": 42,
      "decimals": 9,
      "owner": "F7yLk3s2iZDPBBvSNbXAaKPBnQ9vXqSSSzYUCGeUFhXn"
    }
  }
}

A queima com permissão, unwrapLamports, confidentialBurn e as operações em lote agora são retornadas como JSON analisado, em vez de bytes brutos. 

Código
{
  "parsed": {
    "type": "unwrapLamports",
    "info": {
      "source": "9rr9Xh6PXPKcVqbCB1qxGDWRUJJAdguqcUqVuUqEjqQK",
      "destination": "BhU2wDgmvvMNC1vTSU4aG7BvW26MoTMSDL63hcMqziGL",
      "amount": "1000000",
      "authority": "F7yLk3s2iZDPBBvSNbXAaKPBnQ9vXqSSSzYUCGeUFhXn"
    }
  }
}

Mints contendo extensões anteriormente não reconhecidas costumavam retornar um array extensions vazio; no Agave 4.2, o array é preenchido.

Se o seu código trata um array vazio como "sem extensões", espere que valores comecem a aparecer nele.

Código
"extensions": [
  {
    "extension": "transferFeeConfig",
    "state": {
      "transferFeeConfigAuthority": "...",
      "withdrawWithheldAuthority": "...",
      "withheldAmount": 0,
      "olderTransferFee": {...},
      "newerTransferFee": {...}
    }
  },
  {
    "extension": "permissionedBurnConfig",
    "state": {
      "authority": "3nGhQzXCzoDDvW9pkg8fVLGDrJc23uwFz7qzW26MoTMS"
    }
  }
]

As constantes de duração dos slots estão desatualizadas

A mainnet opera com slots de 350 ms desde a época 1020. A próxima redução, para 300 ms, está agendada para a época 1024 (prevista para 28 de ago.), e a meta é chegar a 200 ms. Constantes fixas de 400 ms em cálculos de conversão de slots em tempo apresentam hoje uma diferença de 12,5%, que aumentará a cada etapa. 

Como corrigir:

Calcule a duração com base nos timestamps dos blocos ou torne-a configurável. Também garanta que seu indexador consiga acompanhar o ritmo quando os blocos começarem a chegar mais rápido.

Verifique se está tudo pronto

Para verificar se está tudo pronto, execute a auditoria do agente e confirme suas dependências.

Execute a auditoria do agente

Copie a skill abaixo para seu agente de programação. 

No Claude Code, salve-a como .claude/skills/agave-42-readiness/SKILL.md.

Para outros agentes, cole-a como um prompt de tarefa.

Prompt
---
name: agave-42-readiness
description: Audit this repository for Solana Agave 4.2 breaking changes. Use when asked to check Agave 4.2 readiness, migrate for transaction v1, or audit Solana RPC/streaming integration code.
---

# Agave 4.2 Readiness Audit

Audit the repository for the five Agave 4.2 breaking changes below. For each, locate the relevant code, judge whether it is affected, and report file:line with a verdict of PASS, FAIL, or NEEDS REVIEW. Do not modify code unless asked to fix findings.

## Check 1: Transaction v1 opt-in (highest priority)
Find every `getBlock`, `getTransaction`, and `getTransactionsForAddress` (with `transactionDetails = full`) call, plus every Enhanced WebSockets `transactionSubscribe` subscription. Search all languages, raw JSON-RPC request bodies (`"method": "getBlock"`, `"method": "transactionSubscribe"`), and SDK wrappers (`connection.getBlock`, `connection.getParsedTransaction`, `rpc_client.get_block`, `client.GetTransaction`, and similar).
- FAIL if `maxSupportedTransactionVersion` is absent or set to 0. Once the v1 feature gate activates, these calls fail on v1 transactions with JSON-RPC error code -32015: `"Transaction version (1) is not supported by the requesting client. Please use \"maxSupportedTransactionVersion\" in your request."` Also grep for `-32015` in logs and error handlers; hits mean the project has already been failing on versioned transactions.
- Also FAIL if the project deserializes raw transaction bytes (custom indexer, signer, relayer) and the decoder does not handle the v1 layout: version byte 0x81 (decimal 129, vs 0x80 for v0), signatures at the END of the transaction instead of the front, compute budget carried in a header config mask instead of instructions.
- Correct fix order: upgrade the Solana SDK to a v1-capable version (JS: @solana/kit 8.0+ or @solana/web3.js v3), then set `maxSupportedTransactionVersion: 1`. Flag if the parameter is set but the installed SDK version predates v1 support.
- Also FAIL if priority fee or compute budget extraction scans for ComputeBudget program instructions (`ComputeBudget111111111111111111111111111111`, `setComputeUnitPrice`, `setComputeUnitLimit`). A v1 transaction contains no such instructions; its values live in a `transactionConfig` object in the message. Scanning code reads every v1 transaction as paying zero priority fee.
- Units trap, FAIL even when the code reads `transactionConfig`: legacy/v0 `setComputeUnitPrice` is **micro-lamports per compute unit**; v1 `priorityFee` is a **total in lamports**. Code that ports the old `price × computeUnitLimit ÷ 1e6` math onto the new field misreports fees. `priorityFee` needs no multiplication. Null fields mean the sender did not set them.

Example v1 message:
```
"message": {
  "instructions": ["… no ComputeBudget instruction here …"],
  "recentBlockhash": "...",
  "transactionConfig": {
    "computeUnitLimit": 200000,
    "heapSize": null,
    "loadedAccountsDataSizeLimit": 200000,
    "priorityFee": 50000
  }
}
```
`"priorityFee": 50000` = this transaction pays 50,000 lamports total. Legacy and v0 messages omit `transactionConfig` entirely, so its presence (or `"version": 1` on the enclosing transaction) identifies v1.

## Check 2: rewardType parsed as a closed enum
Find code reading `rewardType` from `getBlock`, `blockSubscribe`, or Geyser/gRPC reward arrays. Search for the existing values too (`"Fee"`, `"Rent"`, `"Staking"`, `"Voting"` in JSON paths; `RewardType::` in Rust; reward-type enums in generated gRPC code).
- 4.2 adds the value `DeactivatedStake` — same capitalized casing as the existing JSON values (`"Staking"`, not `"staking"`). A reward entry looks like:
```
{
  "pubkey": "...",
  "lamports": 10000000,
  "postBalance": 50000000000,
  "rewardType": "DeactivatedStake",
  "commission": null
}
```
- FAIL if unknown values throw, or fall into a match/switch arm or if/else chain that drops the record without logging: a Rust `match` without a logging wildcard arm, a TS `switch` whose `default` is silent, a lookup table where a missing key skips the entry. Closed parsers lose every deactivating stake account's final payout with no error.
- FAIL if a deserialization enum (serde, protobuf mapping, Zod/io-ts schema) rejects unknown reward-type strings; the whole reward array or block record errors out, not just one entry.
- PASS requires unknown values to be preserved or logged. If the project aggregates staking yield by filtering `rewardType == "Staking"`, add a NEEDS REVIEW noting the team must decide whether `DeactivatedStake` payouts belong in totals; they are final payouts, not recurring yield.

## Check 3: Transaction-to-account-update matching
Find logic that correlates transactions with account update notifications. Search for `accountSubscribe`, Yellowstone/LaserStream `SubscribeRequest` account filters, and code that builds a pending set of a transaction's writable accounts and waits to check them off as updates arrive.
- FAIL if it assumes every writable account in a transaction produces an update. On 4.2, an account that was write-locked but not modified emits nothing; logic awaiting the full set hangs forever. Typical patterns: a countdown/completion latch over `message.accountKeys` writable entries, a timeout that treats a missing update as an error, a reconciler that re-fetches "late" accounts. The fee payer is the only account guaranteed to update.
- The correct interpretation of a missing update is "this account did not change"; its pre-transaction state is still current.
- Also FAIL liveness or health checks that treat update frequency as a signal, and flag alert thresholds calibrated to pre-4.2 volume; account-subscription event counts drop roughly 80% on 4.2.

## Check 4: Token-2022 jsonParsed changes
Find parsers reading Token-2022 `jsonParsed` output: instruction types `depositConfidentialTransfer` and `withdrawConfidentialTransfer`, and mint-account `extensions` arrays.
- FAIL if confidential-transfer parsers read `source` or `destination`; 4.2 replaces both with a single `account` field. New shape:
```
"info": {
  "account": "...",   // was source + destination
  "mint": "...",
  "amount": 42,
  "decimals": 9,
  "owner": "..."      // multisig: "multisigOwner" + "signers" array instead
}
```
- New instruction types now come back parsed instead of raw: `unwrapLamports`, `confidentialBurn`, permissioned burn, and batch operations. FAIL if code assumes these arrive as raw base64/base58 data, and flag `unwrapLamports` parsers that require `info.amount` or treat it as a number: it is a **string** and is **omitted entirely** when the instruction unwraps the full balance.
- Extensions array: on 4.1, one unrecognized extension type on a mint made the node return `"extensions": []`, hiding every extension including known ones. On 4.2 the full array returns, each entry as `{"extension": "<name>", "state": {...}}`, with still-undecodable ones as `{"extension": "unparseableExtension"}`. FAIL if code treats an empty array as proof of no extensions, or throws on extension names it does not recognize (`scaledUiAmountConfig`, `pausableConfig`, `permissionedBurnConfig`, `unparseableExtension`, and future values).

## Check 5: Slot timing and streaming dependencies
- FAIL on hardcoded slot-duration constants: `400`, `0.4`, `400_000` microseconds, `MS_PER_SLOT`, `SLOT_DURATION`, `DEFAULT_MS_PER_SLOT`, or slot-to-time math like `slots * 400`. Mainnet is 350ms, cutting to 300ms on Aug 28, 2026, stepping toward 200ms. Constants inherited from an SDK count as hardcoded. PASS requires timing derived from block timestamps (e.g. `getBlockTime` deltas over a few thousand slots) or a config value with a documented update path.
- Also flag capacity assumptions keyed to block rate: batch sizes, poll intervals, and queue depths sized for 400ms blocks fall behind as slots shorten.
- In Cargo.toml/Cargo.lock: FAIL if `yellowstone-grpc-client` < 13.3.0 or `yellowstone-grpc-proto` < 12.6.0 (first proto carrying transaction v1). Recommend client 13.3.0, proto 12.6.0, both declared.
- For Go gRPC clients: flag if generated protos predate transaction v1; regenerate from latest Yellowstone protos and solana-storage-proto.
- If the project uses the Helius LaserStream SDK (package names `helius-laserstream`, `laserstream` in dependencies): FAIL if below JS 0.8.4, Rust 0.6.3, or Go 0.2.0 (first releases with the v1-capable proto).

## Report format
Output a table: check, verdict, file:line references, one-line remediation. End with an overall verdict (READY / NOT READY) and the ordered fix list. Full migration guide: https://www.helius.dev/blog/agave-4-2-migration-checklist
ExpandirRecolher

Confirme as dependências de streams

Rust: yellowstone-grpc-client 13.3.0 e yellowstone-grpc-proto 12.6.0, ambos declarados, e depois cargo update. 

Go: gere novamente a partir dos protos mais recentes do Yellowstone e de solana-storage-proto. 

LaserStream SDK: JS 0.8.4, Rust 0.6.3 e Go 0.2.0 ou versões posteriores incluem o proto compatível com v1. Suas assinaturas e seus filtros não precisam de alterações em nenhum caminho.

Dúvidas

Se sua integração se comportar de forma diferente na versão 4.2 e este post não explicar o motivo, entre em contato pelo Discord ou pelo suporte. Para uma análise detalhada por recurso, leia a visão geral da versão 4.2.

Assine a Helius

Acompanhe as novidades mais recentes do desenvolvimento Solana e receba atualizações quando publicarmos