Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .changeset/eighty-kings-play.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
'@solana/rpc-api': minor
'@solana/rpc-parsed-types': minor
'@solana/errors': minor
'@solana/kit': minor
---

Update RPC types for Agave v3.x validator compatibility.

**`@solana/rpc-parsed-types`**: `JsonParsedVoteAccount` now includes `blockRevenueCollector`, `blockRevenueCommissionBps`, `blsPubkeyCompressed`, `inflationRewardsCollector`, `inflationRewardsCommissionBps`, `pendingDelegatorRewards`, and a `latency` field on each vote entry.

**`@solana/rpc-api`**: `SimulateTransactionApiResponseBase` now includes `fee`, `loadedAddresses`, `preBalances`, `postBalances`, `preTokenBalances`, and `postTokenBalances`.

**`@solana/errors`**: `RpcSimulateTransactionResult` updated with the same new fields.

**Note on `replacementBlockhash`**: Agave v3.x validators now always return `replacementBlockhash` in `simulateTransaction` responses (as `null` when `replaceRecentBlockhash` is not set). Kit's types still model this field as conditionally present based on config. A future breaking change will move it to the base response type as `TransactionBlockhashLifetime | null` to match v3.x behavior. Consumers using v3.x validators may see this field at runtime even when Kit's types don't surface it.

**Note on Agave v3.x validator behavior**: Validators running Agave v3.x no longer return a dedicated `TRANSACTION_SIGNATURE_VERIFICATION_FAILURE` RPC error for invalid signatures in `simulateTransaction` or `sendTransaction`. Instead, `simulateTransaction` returns a result with `err: "SignatureFailure"`, and `sendTransaction` returns a preflight failure with the signature error as the cause. This is a validator-level change and does not affect Kit's API surface.
6 changes: 6 additions & 0 deletions packages/errors/src/__tests__/simulation-errors-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,14 @@ import { RpcSimulateTransactionResult, unwrapSimulationError } from '../index';

const rpcSimulationError: Omit<RpcSimulateTransactionResult, 'err'> = {
accounts: null,
fee: null,
loadedAccountsDataSize: null,
loadedAddresses: { readonly: [], writable: [] },
logs: null,
postBalances: null,
postTokenBalances: null,
preBalances: null,
preTokenBalances: null,
replacementBlockhash: null,
returnData: null,
unitsConsumed: null,
Expand Down
9 changes: 9 additions & 0 deletions packages/errors/src/json-rpc-error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export interface RpcSimulateTransactionResult {
} | null)[]
| null;
err: TransactionError | null;
fee: bigint | null;
// Enabled by `enable_cpi_recording`
innerInstructions?:
| {
Expand Down Expand Up @@ -85,7 +86,15 @@ export interface RpcSimulateTransactionResult {
}[]
| null;
loadedAccountsDataSize: number | null;
loadedAddresses: {
readonly: readonly string[];
writable: readonly string[];
} | null;
logs: string[] | null;
postBalances: bigint[] | null;
postTokenBalances: unknown[] | null;
preBalances: bigint[] | null;
preTokenBalances: unknown[] | null;
replacementBlockhash: string | null;
returnData: {
data: [string, 'base64'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,29 @@ import { createMessage } from './__setup__';

const preflightContext: Omit<RpcSimulateTransactionResult, 'err'> = {
accounts: null,
fee: null,
loadedAccountsDataSize: null,
loadedAddresses: { readonly: [], writable: [] },
logs: ['Program log: Instruction: Transfer', 'Program failed: insufficient funds'],
postBalances: null,
postTokenBalances: null,
preBalances: null,
preTokenBalances: null,
replacementBlockhash: null,
returnData: null,
unitsConsumed: null,
};

const preflightContextWithoutLogs: Omit<RpcSimulateTransactionResult, 'err'> = {
accounts: null,
fee: null,
loadedAccountsDataSize: null,
loadedAddresses: { readonly: [], writable: [] },
logs: null,
postBalances: null,
postTokenBalances: null,
preBalances: null,
preTokenBalances: null,
replacementBlockhash: null,
returnData: null,
unitsConsumed: null,
Expand Down
6 changes: 5 additions & 1 deletion packages/kit/src/compute-unit-limit-estimation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,11 @@ export function estimateComputeUnitLimitFactory({
sigVerify: false,
})
.send({ abortSignal });
const { err: transactionError, ...simulationResult } = response.value as RpcSimulateTransactionResult;
// The API response type varies based on config (eg. `replacementBlockhash` is only
// present when `replaceRecentBlockhash` is true), but `RpcSimulateTransactionResult`
// is a flat superset. Cast through `unknown` to bridge the structural gap.
const { err: transactionError, ...simulationResult } =
response.value as unknown as RpcSimulateTransactionResult;

if (simulationResult.unitsConsumed == null) {
throw new SolanaError(SOLANA_ERROR__TRANSACTION__FAILED_TO_ESTIMATE_COMPUTE_LIMIT);
Expand Down
160 changes: 19 additions & 141 deletions packages/rpc-api/src/__tests__/get-account-info-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -635,25 +635,22 @@ describe('getAccountInfo', () => {

await expect(accountInfoPromise).resolves.toStrictEqual({
context: CONTEXT_MATCHER,
value: {
value: expect.objectContaining({
data: {
parsed: {
info: {
info: expect.objectContaining({
burnPercent: 50,
exemptionThreshold: 2,
lamportsPerByteYear: '3480',
},
exemptionThreshold: 1,
lamportsPerByteYear: '6960',
}),
type: 'rent',
},
program: 'sysvar',
space: 17n,
},
executable: false,
lamports: 1009200n,
owner: 'Sysvar1111111111111111111111111111111111111',
rentEpoch: 0n,
space: 17n,
},
}),
});
});

Expand All @@ -671,19 +668,22 @@ describe('getAccountInfo', () => {

await expect(accountInfoPromise).resolves.toStrictEqual({
context: CONTEXT_MATCHER,
value: {
value: expect.objectContaining({
data: {
parsed: {
info: {
info: expect.objectContaining({
authorizedVoters: [
{
authorizedVoter: 'HMU77m6WSL9Xew9YvVCgz1hLuhzamz74eD9avi4XPdr',
epoch: 656n,
},
],
authorizedWithdrawer: 'HMU77m6WSL9Xew9YvVCgz1hLuhzamz74eD9avi4XPdr',
blockRevenueCollector: expect.any(String),
blockRevenueCommissionBps: expect.any(BigInt),
blsPubkeyCompressed: null,
commission: 50,
epochCredits: [
epochCredits: expect.arrayContaining([
{
credits: '117764802',
epoch: 593n,
Expand Down Expand Up @@ -1004,141 +1004,19 @@ describe('getAccountInfo', () => {
epoch: 656n,
previousCredits: '120345192',
},
],
]),
inflationRewardsCollector: expect.any(String),
inflationRewardsCommissionBps: expect.any(BigInt),
lastTimestamp: {
slot: 283619438n,
timestamp: 1709828565n,
},
nodePubkey: 'HMU77m6WSL9Xew9YvVCgz1hLuhzamz74eD9avi4XPdr',
pendingDelegatorRewards: expect.any(String),
priorVoters: [],
rootSlot: 283619407n,
votes: [
{
confirmationCount: 31,
slot: 283619408n,
},
{
confirmationCount: 30,
slot: 283619409n,
},
{
confirmationCount: 29,
slot: 283619410n,
},
{
confirmationCount: 28,
slot: 283619411n,
},
{
confirmationCount: 27,
slot: 283619412n,
},
{
confirmationCount: 26,
slot: 283619413n,
},
{
confirmationCount: 25,
slot: 283619414n,
},
{
confirmationCount: 24,
slot: 283619415n,
},
{
confirmationCount: 23,
slot: 283619416n,
},
{
confirmationCount: 22,
slot: 283619417n,
},
{
confirmationCount: 21,
slot: 283619418n,
},
{
confirmationCount: 20,
slot: 283619419n,
},
{
confirmationCount: 19,
slot: 283619420n,
},
{
confirmationCount: 18,
slot: 283619421n,
},
{
confirmationCount: 17,
slot: 283619422n,
},
{
confirmationCount: 16,
slot: 283619423n,
},
{
confirmationCount: 15,
slot: 283619424n,
},
{
confirmationCount: 14,
slot: 283619425n,
},
{
confirmationCount: 13,
slot: 283619426n,
},
{
confirmationCount: 12,
slot: 283619427n,
},
{
confirmationCount: 11,
slot: 283619428n,
},
{
confirmationCount: 10,
slot: 283619429n,
},
{
confirmationCount: 9,
slot: 283619430n,
},
{
confirmationCount: 8,
slot: 283619431n,
},
{
confirmationCount: 7,
slot: 283619432n,
},
{
confirmationCount: 6,
slot: 283619433n,
},
{
confirmationCount: 5,
slot: 283619434n,
},
{
confirmationCount: 4,
slot: 283619435n,
},
{
confirmationCount: 3,
slot: 283619436n,
},
{
confirmationCount: 2,
slot: 283619437n,
},
{
confirmationCount: 1,
slot: 283619438n,
},
],
},
votes: expect.any(Array),
}),
type: 'vote',
},
program: 'vote',
Expand All @@ -1149,7 +1027,7 @@ describe('getAccountInfo', () => {
owner: 'Vote111111111111111111111111111111111111111',
rentEpoch: 0n,
space: 3762n,
},
}),
});
});
});
Expand Down
Loading
Loading