NUEVO: Helius adquiere Light Protocol
lista de verificación para la migración a Solana Agave 4.2
Blog/Actualizaciones

Agave 4.2: lista de verificación para la migración

Producto @ HeliusKiryl Miranovich en XKiryl Miranovich en LinkedIn
5 min de lectura

Explicamos el conjunto de funciones de Agave 4.2 en nuestro resumen de la versión. Esta publicación aborda la migración: qué deja de funcionar y cómo verificar tu integración antes de que se active la función.

La mayoría de estos cambios devuelve datos incorrectos o ausentes en lugar de errores, por lo que no aparecerán en tus registros de excepciones.

Cronograma de activación

CuándoQuéEstado
11 de agosto de 2026Anza recomienda la versión 4.2 para mainnet; comienzan las actualizaciones de validadoresEn curso
A medida que se actualizan los nodosEntran en vigor la supresión de actualizaciones de cuentas y los cambios de Token-2022 en jsonParsedListo
Primer límite de época tras la actualizaciónAparece el valor DeactivatedStake rewardType en las recompensasListo
Época 1020La duración de los slots baja de 400 ms a 350 ms, el primero de cuatro pasos hacia los 200 msListo
Época 1024La duración de los slots baja de 350 ms a 300 msProgramado (previsto para el 28 de agosto)
Activación de función, fecha por determinarTransacción v1 (transacciones de 4096 bytes)Pendiente (no hay una fecha anunciada, así que prepárate como si se activara la próxima semana)
Cinco activaciones de funciones, fechas por determinarReducción de la renta, de 6960 lamports/byte hasta 696Pendiente
Agave 4.3, prevista para octubre de 2026Consenso AlpenglowVersión futura

Cambios incompatibles de Agave 4.2

Una transacción v1 hace que falle toda la llamada

SIMD-0296 y SIMD-0385 elevan a 4096 bytes el límite de tamaño de las transacciones de Solana mediante un nuevo formato de transacción.

El espacio adicional permite a los desarrolladores ejecutar cargas de trabajo on-chain más grandes, como pruebas ZK o rutas de DEX con más tramos. 

El inconveniente: una sola transacción v1 en un bloque hace que getBlock falle para todo el bloque si la llamada no establece maxSupportedTransactionVersion: 1.

Las demás transacciones tampoco se devuelven; falla toda la llamada. getTransaction y getTransactionsForAddress (con transactionDetails = full) fallan de la misma manera ante cualquier transacción v1. 

Cómo solucionarlo:

  • Actualiza tu SDK a una versión que decodifique v1. La compatibilidad está llegando a los distintos clientes. Si tu SDK aún no es compatible con transacciones v1, consulta sus notas de la versión para buscar transaction v1 o SIMD-0385.
    • Clientes JS populares: @solana/kit 8.0+, @solana/web3.js v3
    • Crates populares de Rust: solana-rpc-client-api 4.2+, solana-client 4.2+, solana-transaction 4.2+, solana-compute-budget 4.2+, otros crates de Anza.
  • Establece maxSupportedTransactionVersion: 1 en cada llamada a getBlock, getTransaction y getTransactionsForAddress (con transactionDetails = full)
  • Establece maxSupportedTransactionVersion: 1 en el objeto de opciones de cada suscripción transactionSubscribe de Enhanced WebSockets (con transactionDetails establecido en full o accounts). Las suscripciones copiadas de los ejemplos de la documentación lo tienen establecido en 0; cámbialo a 1
Código
{
  "jsonrpc": "2.0",
  "id": "1",
  "method": "getTransactionsForAddress",
  "params": [
    "Vote111111111111111111111111111111111111111",
    {
      "transactionDetails": "full",
      "sortOrder": "desc",
      "filters": {
        "status": "succeeded"
      },
      "maxSupportedTransactionVersion": 1
    }
  ]
}

El parámetro declara la versión más alta que admite tu cliente. Puedes establecerlo hoy sin riesgos y no cambia cómo se devuelven las transacciones heredadas y v0.

Fallos del presupuesto de cómputo en transacciones v1

Una transacción v1 almacena su límite de cómputo y su tarifa de prioridad en el objeto transactionConfig en lugar de hacerlo en instrucciones ComputeBudget. Los paneles de tarifas y los estimadores de tarifas de prioridad que detectan las tarifas mediante la coincidencia de esas instrucciones interpretan que todas las transacciones v1 pagan cero, sin mostrar ningún error.

Cómo solucionarlo:

En su lugar, lee los valores del nuevo campo priorityFee en la configuración de la transacción. Ten en cuenta que el nuevo campo priorityFee indica una tarifa total en lamports (no un precio por unidad de cómputo).

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

Las cuentas sin cambios dejan de emitir actualizaciones

Agave 4.2 solo emite eventos de cuenta cuando realmente se escribe en una cuenta. Para las suscripciones de cuentas mediante gRPC y WSS de LaserStream, esto implica aproximadamente un 80 % menos de eventos.

Cómo solucionarlo:

  1. Si relacionas transacciones con actualizaciones de cuentas, deja de esperar una actualización de cada cuenta escribible; interpreta la ausencia de una actualización como "la cuenta no cambió". Solo se garantiza que se actualice el pagador de la tarifa, ya que siempre paga la tarifa.
  2. Si usas la frecuencia de actualización como señal de estado, elimina esa comprobación para las cuentas que suelen estar bloqueadas pero rara vez cambian. Una cuenta inactiva está en buen estado; dejó de emitir porque nada cambió.

Un nuevo valor de rewardType

Las cuentas de staking que terminan de desactivarse ahora reciben su pago final con un nuevo valor rewardType, DeactivatedStake, en los arrays de recompensas getBlock e blockSubscribe. La estructura del objeto de recompensa es idéntica a la de Agave 4.1, por lo que un parser que solo acepte los tipos de recompensa que ya conoce omitirá los pagos DeactivatedStake sin mostrar ningún error.

getInflationReward no se ve afectado; el riesgo solo existe cuando analizas directamente los arrays de recompensas sin procesar.

Cómo solucionarlo:

Agrega DeactivatedStake a los valores rewardType que acepta tu parser y registra cualquier valor que no reconozcas en lugar de descartar el registro.

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

Token-2022: se elimina un campo y se amplía el análisis

En las respuestas jsonParsed, depositConfidentialTransfer e withdrawConfidentialTransfer pierden los campos de origen y destino en favor de un único campo de cuenta. Las etiquetas anteriores eran incorrectas; cada instrucción afecta a una cuenta de tokens.

La solución es actualizar los parsers de Token-2022 para que admitan el nuevo campo.

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

La quema con permisos, unwrapLamports, confidentialBurn y las operaciones por lotes ahora se devuelven como JSON analizado en lugar de bytes sin procesar. 

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

Antes, los mints con extensiones no reconocidas devolvían un array extensions vacío; en Agave 4.2, el array contiene datos.

Si tu código interpreta un array vacío como "sin extensiones", espera que comiencen a aparecer valores allí.

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

Las constantes de temporización de slots están desactualizadas

Mainnet usa slots de 350 ms desde la época 1020. La próxima reducción, a 300 ms, está programada para la época 1024 (prevista para el 28 de agosto), con un objetivo de 200 ms. Las constantes de 400 ms codificadas directamente en los cálculos de slots a tiempo tienen hoy un desfase del 12,5 % y se desviarán más con cada paso. 

Cómo solucionarlo:

Calcula los tiempos a partir de las marcas de tiempo de los bloques o permite configurarlos, y asegúrate de que tu indexador pueda seguir el ritmo cuando los bloques comiencen a llegar más rápido.

Verifica que hayas terminado

Para verificar que hayas terminado, ejecuta la auditoría del agente y confirma tus dependencias.

Ejecuta la auditoría del agente

Copia la siguiente habilidad en tu agente de programación. 

Para Claude Code, guárdala como .claude/skills/agave-42-readiness/SKILL.md.

Para otros agentes, pégala como prompt de tarea.

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
ExpandirContraer

Confirma las dependencias de streaming

Rust: yellowstone-grpc-client 13.3.0 e yellowstone-grpc-proto 12.6.0, ambas declaradas, y luego cargo update. 

Go: vuelve a generar desde los protos más recientes de Yellowstone y solana-storage-proto. 

LaserStream SDK: JS 0.8.4, Rust 0.6.3 y Go 0.2.0 o versiones posteriores incluyen el proto compatible con v1. Tus suscripciones y filtros no necesitan cambios en ninguna ruta.

Preguntas

Si tu integración se comporta de forma distinta en la versión 4.2 y esta publicación no lo explica, contáctanos en Discord o mediante soporte. Para ver el desglose por función, consulta el resumen de la versión 4.2.

Suscríbete a Helius

Mantente al día con las novedades del desarrollo en Solana y recibe actualizaciones cuando publiquemos