TL;DR

  • Agave 4.2 is rolling out across mainnet now, and the changes most likely to bite you aren't the headline features
  • Transaction v1 is the first thing to fix: once the gate activates, getBlock and getTransaction calls that haven't declared support for version 1 fail outright
  • Dragon's Mouth already carries the v1 transaction shape, so streaming customers need a client and protobuf bump rather than a rewrite
  • Slot times are already stepping down on mainnet, and the SDK's slot duration constant hasn't caught up yet
  •  Unchanged accounts no longer emit account updates, and block rewards carry a new reward type that closed-enum parsers will drop

View the Dragon's Mouth docs

If you run an indexer, a trading system, a wallet backend or anything that parses blocks or matches transactions to account updates, here's what to check.

Transaction v1 breaks calls that haven't opted in

SIMD-0296 raises the maximum transaction size from 1,232 bytes to 4,096 bytes, delivered through the new v1 transaction format defined in SIMD-0385. The headline framing is about bigger payloads. But what matters for your integration is what happens to your RPC calls when the first v1 transaction lands.

There's no degraded path here. If a transaction is legacy or v0, we can serve it as we always have. If it's v1 and your call hasn't declared support for version 1, the call fails. 

The fix:

  1. Upgrade your SDK so your decode path actually understands the v1 layout
  2. Confirm your deserialisation handles it
  3. Then set maxSupportedTransactionVersion to 1 on getBlock and getTransaction

Do those in that order. The parameter declares a ceiling on what your client can handle, not a request for a specific version, which means it's safe to set the moment your endpoint runs 4.2 and long before the gate activates. Setting it before your decode path is ready just moves the breakage one step earlier.

Streaming: bump your client and protobuf

Dragon's Mouth supports transaction v1 today. Your subscription requests, filters, tokens and endpoints don't change. What changes is the version of the client and protobuf you build against.

For Rust, the minimums are:

[dependencies]
yellowstone-grpc-client = "13.3.0"  # minimum: 12.0.0
yellowstone-grpc-proto = "12.6.0"   # minimum: 12.6.0, first proto carrying transaction v1

Declare both. yellowstone-grpc-client depends on yellowstone-grpc-proto, and only 12.0.0 and above will accept a 12.x proto. Newer is better here, so take 13.3.0 unless you have a reason not to.

For Go, there's no client we ship. You generate your own from the proto definitions, so regenerate against our latest protobuf and solana-storage-proto and you're current.

💡
Having looked at our crates.io download stats: a lot of people are running very old Dragon's Mouth and Jet builds. If you haven't touched your dependencies in a while, this is the release where that catches up with you.

Unchanged accounts no longer send account updates

The biggest behavioural shift in 4.2 shows up as missing data rather than new data. Validators now skip writing accounts that a transaction locked for writing, but didn't actually modify. Since Geyser account notifications are driven by the store path, an account that's write-locked but left untouched no longer produces an account update on your stream.

This is correctness-preserving. The account genuinely didn't change, so there was never a new state to deliver. Here’s the potential impact:

Transaction and account matching

If you correlate transactions with account updates, you can no longer assume that every writable account in a transaction produces a matching update. You'll see the account in the transaction's account keys, but if the transaction left it unmodified, no account update follows. Matching logic that waits for the full set will wait forever. An account update now confirms the account changed; it no longer tells you whether a transaction touched it. The fee payer is the exception: it always changes (it paid the fee), so it always emits an update.

Heartbeats and liveness checks

If any of your monitoring treats "an update arrived for this account" as a liveness signal, that signal just got less frequent. A hot account that's often locked but rarely modified will go quiet for longer stretches. That's expected behaviour on 4.2, not a fault in your stream.

Volume dashboards and alerting

Your account update rate steps down when the validators serving you upgrade. Re-baseline any alerts keyed to notification volume so the drop isn't paged as an incident. We don't have a precise percentage to give you because the reduction depends entirely on your subscription's traffic mix; accounts that are frequently write-locked without being modified see the largest drop.

The upside is real: less redundant data over the wire means less bandwidth, less deserialisation work and fewer no-op writes in your own storage layer. The stream is cleaner; the adjustment is on your side, where code may still expect the noise.

Block rewards carry a new reward type

This is the most underdetected change in the release because nothing about the data's shape changes. The reward objects in getBlock and blockSubscribe responses look exactly as they did on 4.1. What changes is the set of values: alongside fee, rent, staking and voting, stake accounts that finish deactivating now receive their final reward under a new deactivated stake reward type, starting at the first epoch boundary after upgrade.

Here's the failure mode. If your indexer parses rewardType as a closed enum of the four known values, the new value either throws or falls into a default branch you never look at. If you filter on rewardType == "staking" to build staking yield data, you drop the final reward of every deactivating stake account. Nothing errors or warns; the gap only shows up later as balances that don't reconcile.

Agave patched its own getInflationReward internally to handle the new classification, but external consumers parsing raw reward arrays are on their own. The fix is to treat rewardType as an open set, and if you aggregate staking rewards, decide explicitly whether deactivation payouts belong in your totals.

On our side, this is already handled. The Dragon's Mouth protobuf carries the new reward type value, so gRPC subscribers receive it cleanly typed rather than as an unknown enum value. The same applies whether you connect through a shared subscription, a dedicated node or Riptide. The audit you need to run is in your own deserialisation and filtering code, not in the stream.

jsonParsed loses two fields on confidential transfers

4.2 contains exactly one outright field removal in jsonParsed responses, and it's in Token-2022 confidential transfers. The parsed forms of the depositConfidentialTransfer and withdrawConfidentialTransfer instructions previously reported source and destination fields. Those labels were wrong: each instruction touches only one token account. 4.2 removes both fields and replaces them with a single account field. The mint field is unchanged.

If your code reads source or destination from either of these parsed instructions, it breaks the moment your RPC provider upgrades. The migration is mechanical: read account instead. Since the old fields were mislabelled anyway, chances are your handling of them deserves a second look regardless.

Token-2022 parsing gets broader and stricter

Alongside the removal, 4.2 expands what jsonParsed understands. The transaction parser moves to the Token-2022 3.x interface and gains parsed forms for several instructions that previously came back unparsed: permissioned burn (initialise, burn and burnChecked), unwrapLamports, confidentialBurn and batch, plus a permissionedBurnConfig extension on mint accounts.

There's also a subtle account-level change. On 4.1, a Token-2022 mint carrying an extension the node didn't recognise returned an empty extensions array in jsonParsed responses; the parser failed closed and dropped everything. On 4.2, mints with newer extensions parse properly, so accounts that returned an empty array yesterday return a populated one today. If your code treats a non-empty extensions array as a signal (or worse, assumes certain mints have no extensions because that's what the API told you), revisit that assumption.

Your upgrade checklist

Eight things to check, in order of likely damage:

  • Migrate confidential transfer parsing from source and destination to account, and re-test any Token-2022 code that reads the extensions array
  • Re-baseline volume alerts and remove any liveness checks built on account update frequency
  • Update transaction-to-account-update matching so a missing account update means "unchanged", not "still waiting"
  • Audit every place you parse or filter rewardType: handle the new deactivated stake value and decide whether it belongs in your staking aggregates
  • Check your indexing pipeline's headroom, and replace anything relying on a hardcoded 400ms slot duration
  • Go streaming: regenerate your client from our latest protobuf definitions and solana-storage-proto
  • Rust streaming: move to yellowstone-grpc-client 13.3.0 and yellowstone-grpc-proto 12.6.0, declaring both, then run cargo update
  • Upgrade your SDK, confirm your decode path handles the v1 transaction layout, then set maxSupportedTransactionVersion to 1 on getBlock and getTransaction, in that order

None of these require changes to your subscription requests, filters or connection setup. The stream and the RPC interface are the same.

FAQ

When does transaction v1 activate? The code ships in 4.2; activation is a separate, cluster-wide feature gate. Make the change now rather than waiting, because maxSupportedTransactionVersion declares a ceiling and costs you nothing to set early.

What are the minimum client versions for v1? For Rust, yellowstone-grpc-client 12.0.0 and yellowstone-grpc-proto 12.6.0, though we'd take 13.3.0 and 12.6.0. For Go, regenerate from our latest proto definitions and solana-storage-proto.

Do I need to change my Dragon's Mouth subscription for 4.2? No. Subscription requests, filters, tokens and endpoints are unchanged. The protobuf already includes the new reward type, so gRPC consumers receive correctly typed data. The changes you need to make are in how your code interprets what arrives.

Will I receive fewer account updates? Yes, if your subscriptions cover accounts that are frequently write-locked but not modified. The reduction is real but varies by workload, and it reflects genuinely redundant updates that no longer exist.

Does the new reward type affect getInflationReward? No. Agave adjusted that method internally to account for the new classification. The exposure is in getBlock, blockSubscribe and any Geyser or gRPC stream where you parse raw reward arrays yourself.

I've found something in my integration that behaves differently and isn't listed here. Where do I look? Start with the Dragon's Mouth docs and the Solana streaming overview. If you're still unsure, reach out and we'll dig into it with you.

Audit your parsers, loosen your enums, re-baseline your alerts, and your integration crosses the 4.2 upgrade without a blip. That's the kind of boring we aim for.

New to Triton? Get an endpoint