Skip to content

Commit

Permalink
feat: agave v2 rpc: replace getRecentBlockhash with `getLatestBlock…
Browse files Browse the repository at this point in the history
…hash`
  • Loading branch information
buffalojoec committed Nov 1, 2024
1 parent f96e4d2 commit ea25c54
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 25 deletions.
69 changes: 48 additions & 21 deletions src/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ import RpcWebSocketClient from './rpc-websocket';
import {MS_PER_SLOT} from './timing';
import {
Transaction,
TransactionInstruction,
TransactionMessage,
TransactionStatus,
TransactionVersion,
VersionedTransaction,
Expand Down Expand Up @@ -2597,20 +2599,6 @@ const GetParsedTransactionRpcResult = jsonRpcResult(
),
);

/**
* Expected JSON RPC response for the "getRecentBlockhash" message
*
* @deprecated Deprecated since RPC v1.8.0. Please use {@link GetLatestBlockhashRpcResult} instead.
*/
const GetRecentBlockhashAndContextRpcResult = jsonRpcResultAndContext(
pick({
blockhash: string(),
feeCalculator: pick({
lamportsPerSignature: number(),
}),
}),
);

/**
* Expected JSON RPC response for the "getLatestBlockhash" message
*/
Expand Down Expand Up @@ -4565,13 +4553,52 @@ export class Connection {
feeCalculator: FeeCalculator;
}>
> {
const args = this._buildArgs([], commitment);
const unsafeRes = await this._rpcRequest('getRecentBlockhash', args);
const res = create(unsafeRes, GetRecentBlockhashAndContextRpcResult);
if ('error' in res) {
throw new SolanaJSONRPCError(res.error, 'failed to get recent blockhash');
}
return res.result;
// In order to serve the same response (with blockhash and fee calculator)
// as the now-removed `getRecentBlockhash` method, we'll have to make two
// calls.

// First get the latest blockhash from `getLatestBlockhash`.
const {
context,
value: {blockhash: latestBlockhash},
} = await this.getLatestBlockhashAndContext(commitment);

// Then, in order to obtain the fee calculator for this blockhash, build a
// mock transaction message:
// * Use the obtained blockhash.
// * Provide only one signer.
// * Declare zero write locks.
// * Request no additional CUs.
const defaultPubkey = PublicKey.default;
const mockedMessage = new TransactionMessage({
payerKey: defaultPubkey,
instructions: [
new TransactionInstruction({
programId: defaultPubkey,
keys: [{pubkey: defaultPubkey, isSigner: true, isWritable: false}],
}),
],
recentBlockhash: latestBlockhash,
}).compileToLegacyMessage();

// Then query the `getFeeForMessage` method to obtain a fee for the mocked
// message. This will give us a fee which equates to the cluster's lamports
// per signature for the given blockhash.
const feeForMessage = await this.getFeeForMessage(
mockedMessage,
commitment,
);
const lamportsPerSignature = feeForMessage.value;

return {
context,
value: {
blockhash: latestBlockhash,
feeCalculator: {
lamportsPerSignature: lamportsPerSignature ?? 5000,
},
},
};
}

/**
Expand Down
13 changes: 9 additions & 4 deletions test/mocks/rpc-http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,17 +160,22 @@ const recentBlockhash = async ({
}

await mockRpcResponse({
method: 'getRecentBlockhash',
method: 'getLatestBlockhash',
params,
value: {
blockhash,
feeCalculator: {
lamportsPerSignature: 42,
},
lastValidBlockHeight: 200,
},
withContext: true,
});

await mockRpcResponse({
method: 'getFeeForMessage',
params,
value: 5000,
withContext: true,
});

return await connection.getRecentBlockhash(commitment);
};

Expand Down

0 comments on commit ea25c54

Please sign in to comment.