
Agave 4.2:移行チェックリスト
Agave 4.2 の機能セットについては、リリース概要で解説しました。この記事では移行に焦点を当て、何が壊れるのか、フィーチャーゲートが有効になる前に統合を検証する方法を説明します。
これらの変更の多くは、エラーではなく誤ったデータや欠落したデータを返すため、例外ログには現れません。
有効化スケジュール
| 時期 | 内容 | ステータス |
| 2026年8月11日 | Anza がメインネットで 4.2 を推奨。バリデータのアップグレード開始 | 進行中 |
| ノードのアップグレード時 | アカウント更新の抑制と Token-2022 の jsonParsed に関する変更が有効化 | 完了 |
| アップグレード後、最初のエポック境界 | 報酬に DeactivatedStake rewardType 値が出現 | 完了 |
| エポック 1020 | スロット時間を 400ms から 350ms に短縮。200ms に向けた4段階のうち第1段階 | 完了 |
| エポック 1024 | スロット時間を 350ms から 300ms に短縮 | 予定(8月28日の見込み) |
| フィーチャーゲート、日付未定 | トランザクション v1(4,096バイトのトランザクション) | 保留中(日付は未発表のため、来週有効になる前提で準備してください) |
| 5つのフィーチャーゲート、日付未定 | Rent の削減。6,960 lamports/byte から段階的に 696 へ | 保留中 |
| Agave 4.3、2026年10月を予定 | Alpenglow コンセンサス | 将来のリリース |
Agave 4.2 の破壊的変更
トランザクション v1 により呼び出し全体が失敗します
SIMD-0296 と SIMD-0385 により、新しいトランザクション形式を通じて Solana のトランザクションサイズ上限が 4,096 バイトに引き上げられます。
容量が増えることで、ZK 証明や、より多くの経路を含む DEX ルートなど、より大きなオンチェーンワークロードを実行できます。
ただし、ブロック内に v1 トランザクションが1つでもあり、呼び出しで maxSupportedTransactionVersion: 1 が設定されていない場合、ブロック全体の getBlock が失敗します。
ほかのトランザクションも返されず、呼び出し全体がエラーになります。getTransaction と getTransactionsForAddress(transactionDetails = full を使用)も、v1 トランザクションが含まれると同様に失敗します。
修正方法:
- SDK を、v1 をデコードできるリリースへアップグレードしてください。各クライアントで順次サポートが追加されています。お使いの SDK でトランザクション v1 のサポートがまだリリースされていない場合は、リリースノートで transaction v1 または SIMD-0385 を確認してください。
- 主な JS クライアント:@solana/kit 8.0+、@solana/web3.js v3
- 主な Rust crate:solana-rpc-client-api 4.2+、solana-client 4.2+、solana-transaction 4.2+、solana-compute-budget 4.2+、その他の Anza crate。
- すべての getBlock、getTransaction、getTransactionsForAddress 呼び出しで
maxSupportedTransactionVersion: 1を設定してください(transactionDetails = fullを使用) - すべての Enhanced WebSockets transactionSubscribe サブスクリプションの options オブジェクトで
maxSupportedTransactionVersion: 1を設定してください(transactionDetailsをfullまたはaccountsに設定)。ドキュメントの例からコピーしたサブスクリプションでは0に設定されているため、1に引き上げてください
{
"jsonrpc": "2.0",
"id": "1",
"method": "getTransactionsForAddress",
"params": [
"Vote111111111111111111111111111111111111111",
{
"transactionDetails": "full",
"sortOrder": "desc",
"filters": {
"status": "succeeded"
},
"maxSupportedTransactionVersion": 1
}
]
}
このパラメータは、クライアントが処理できる最大バージョンを宣言します。現時点で設定しても安全であり、legacy および v0 トランザクションの返却方法は変わりません。
トランザクション v1 のコンピュートバジェットに関する問題
v1 トランザクションでは、コンピュート上限と優先手数料が ComputeBudget 命令ではなく transactionConfig オブジェクトに保存されます。これらの命令との照合によって手数料を検出する手数料ダッシュボードや優先手数料推定ツールは、エラーを出さず、すべての v1 トランザクションを支払額ゼロとして読み取ります。
修正方法:
代わりに、トランザクション設定の新しい priorityFee フィールドから値を読み取ってください。新しい priorityFee フィールドは、コンピュートユニットあたりの価格ではなく、lamports 単位の合計手数料を示す点に注意してください。
"message": {
"instructions": ["… no ComputeBudget instruction here …"],
"recentBlockhash": "...",
"transactionConfig": {
"computeUnitLimit": 200000,
"heapSize": null,
"loadedAccountsDataSizeLimit": 200000,
"priorityFee": 50000
}
}
変更されていないアカウントから更新が送信されなくなります
Agave 4.2 では、アカウントが実際に書き込まれた場合にのみアカウントイベントが送信されます。LaserStream の gRPC および WSS アカウントサブスクリプションでは、イベントが約80%減少します。
修正方法:
- トランザクションとアカウント更新を照合している場合、書き込み可能なすべてのアカウントからの更新を待つのをやめ、更新がない場合は「アカウントが変更されなかった」と扱ってください。常に手数料を支払うため、更新が保証されるのは手数料支払者だけです。
- 更新頻度をヘルスシグナルとして使用している場合、頻繁にロックされるもののほとんど変更されないアカウントについては、そのチェックを削除してください。更新のないアカウントも正常です。何も変更されなかったため、イベントが送信されなくなっただけです。
新しい rewardType 値
非アクティブ化が完了したステークアカウントは、getBlock と blockSubscribe の報酬配列で、新しい rewardType 値である DeactivatedStake として最終支払いを受け取るようになりました。報酬オブジェクトの構造は Agave 4.1 と同一のため、既知の報酬タイプのみを受け付けるパーサーは、エラーを出さずに DeactivatedStake の支払いをスキップします。
getInflationReward には影響しません。このリスクがあるのは、raw の報酬配列を独自に解析する場合だけです。
修正方法:
パーサーが受け付ける rewardType 値に DeactivatedStake を追加し、認識できない値はレコードを破棄せずにログへ記録してください。
{
"pubkey": "...",
"lamports": 10000000,
"postBalance": 50000000000,
"rewardType": "DeactivatedStake",
"commission": null,
"commissionBps": 500
}
Token-2022:1つのフィールドを削除し、解析対象を拡大
jsonParsed のレスポンスでは、depositConfidentialTransfer と withdrawConfidentialTransfer から source と destination が削除され、単一の account フィールドに置き換わります。従来のラベルは誤っていました。各命令が操作するトークンアカウントは1つだけです。
Token-2022 パーサーを更新し、新しいフィールドをサポートしてください。
{
"parsed": {
"type": "depositConfidentialTransfer",
"info": {
"account": "6XVfUq9jZQtBfqcm1Rz8fBhViyoyzWiEUAaWnQ9AmXeR",
"mint": "8fJ7bCZo2vZ3vAnyCBQgZuLYuTX1qPnKvsMKotk92B2J",
"amount": 42,
"decimals": 9,
"owner": "F7yLk3s2iZDPBBvSNbXAaKPBnQ9vXqSSSzYUCGeUFhXn"
}
}
}
Permissioned burn、unwrapLamports、confidentialBurn、バッチ操作は、raw バイトではなく解析済み JSON として返されるようになりました。
{
"parsed": {
"type": "unwrapLamports",
"info": {
"source": "9rr9Xh6PXPKcVqbCB1qxGDWRUJJAdguqcUqVuUqEjqQK",
"destination": "BhU2wDgmvvMNC1vTSU4aG7BvW26MoTMSDL63hcMqziGL",
"amount": "1000000",
"authority": "F7yLk3s2iZDPBBvSNbXAaKPBnQ9vXqSSSzYUCGeUFhXn"
}
}
}
これまでは、認識されていない拡張を含む mint では空の extensions 配列が返されていましたが、Agave 4.2 では配列に値が入ります。
コードで空の配列を「拡張なし」として扱っている場合は、今後そこに値が出現することを想定してください。
"extensions": [
{
"extension": "transferFeeConfig",
"state": {
"transferFeeConfigAuthority": "...",
"withdrawWithheldAuthority": "...",
"withheldAmount": 0,
"olderTransferFee": {...},
"newerTransferFee": {...}
}
},
{
"extension": "permissionedBurnConfig",
"state": {
"authority": "3nGhQzXCzoDDvW9pkg8fVLGDrJc23uwFz7qzW26MoTMS"
}
}
]
スロットタイミングの定数が古くなっています
メインネットでは、エポック 1020 からスロット時間が 350ms になっています。次の短縮では 300ms となり、エポック 1024(8月28日の見込み)に予定されています。最終目標は 200ms です。スロットから時刻への計算にハードコードされた 400ms の定数は、現在すでに 12.5% ずれており、各段階でさらにずれが広がります。
修正方法:
ブロックのタイムスタンプからタイミングを算出するか、設定可能にしてください。また、ブロックの到着が速くなってもインデクサーが処理に追いつけることを確認してください。
完了を確認する
対応が完了したことを検証するには、エージェント監査を実行し、依存関係を確認してください。
エージェント監査を実行する
以下のスキルをコーディングエージェントにコピーしてください。
Claude Code の場合は、.claude/skills/agave-42-readiness/SKILL.md として保存してください。
ほかのエージェントでは、タスクプロンプトとして貼り付けてください。
---
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展開折りたたむ
ストリームの依存関係を確認する
Rust:yellowstone-grpc-client 13.3.0 と yellowstone-grpc-proto 12.6.0 の両方を宣言し、その後 cargo update を実行してください。
Go:最新の Yellowstone proto から再生成し、solana-storage-proto を実行してください。
LaserStream SDK:JS 0.8.4、Rust 0.6.3、Go 0.2.0 以降には、v1 対応の proto が含まれています。どの経路でも、サブスクリプションやフィルターを変更する必要はありません。
質問
4.2 で統合の動作が変わり、この記事で解決しない場合は、Discord またはサポートからお問い合わせください。機能ごとの詳細は、4.2 の概要をご覧ください。
関連記事
Heliusを購読
Solana開発の最新情報や新しい記事の公開通知を受け取れます


