diff --git a/web3.js/module.d.ts b/web3.js/module.d.ts index de248da5e7..4010a67277 100644 --- a/web3.js/module.d.ts +++ b/web3.js/module.d.ts @@ -271,6 +271,10 @@ declare module '@solana/web3.js' { getRecentBlockhashAndContext( commitment?: Commitment, ): Promise>; + getFeeCalculatorForBlockhash( + blockhash: Blockhash, + commitment?: Commitment, + ): Promise>; getRecentBlockhash( commitment?: Commitment, ): Promise; diff --git a/web3.js/module.flow.js b/web3.js/module.flow.js index cfd47f897f..b8e49bedbe 100644 --- a/web3.js/module.flow.js +++ b/web3.js/module.flow.js @@ -284,6 +284,10 @@ declare module '@solana/web3.js' { getRecentBlockhashAndContext( commitment: ?Commitment, ): Promise>; + getFeeCalculatorForBlockhash( + blockhash: Blockhash, + commitment: ?Commitment, + ): Promise>; getRecentBlockhash( commitment: ?Commitment, ): Promise; diff --git a/web3.js/src/connection.js b/web3.js/src/connection.js index c5b40de0c2..8a84cd9d20 100644 --- a/web3.js/src/connection.js +++ b/web3.js/src/connection.js @@ -783,6 +783,20 @@ const GetRecentBlockhashAndContextRpcResult = jsonRpcResultAndContext( }), ); +/** + * Expected JSON RPC response for the "getFeeCalculatorForBlockhash" message + */ +const GetFeeCalculatorRpcResult = jsonRpcResultAndContext( + struct.union([ + 'null', + struct({ + feeCalculator: struct({ + lamportsPerSignature: 'number', + }), + }), + ]), +); + /** * Expected JSON RPC response for the "requestAirdrop" message */ @@ -1506,6 +1520,31 @@ export class Connection { return res.result; } + /** + * Fetch the fee calculator for a recent blockhash from the cluster, return with context + */ + async getFeeCalculatorForBlockhash( + blockhash: Blockhash, + commitment: ?Commitment, + ): Promise> { + const args = this._argsWithCommitment([blockhash], commitment); + const unsafeRes = await this._rpcRequest( + 'getFeeCalculatorForBlockhash', + args, + ); + + const res = GetFeeCalculatorRpcResult(unsafeRes); + if (res.error) { + throw new Error('failed to get fee calculator: ' + res.error.message); + } + assert(typeof res.result !== 'undefined'); + const {context, value} = res.result; + return { + context, + value: value && value.feeCalculator, + }; + } + /** * Fetch a recent blockhash from the cluster * @return {Promise<{blockhash: Blockhash, feeCalculator: FeeCalculator}>} diff --git a/web3.js/test/connection.test.js b/web3.js/test/connection.test.js index 8a9f053578..c18f2e69cd 100644 --- a/web3.js/test/connection.test.js +++ b/web3.js/test/connection.test.js @@ -203,6 +203,7 @@ test('get program accounts', async () => { }, }, ]); + transaction = SystemProgram.assign({ accountPubkey: account1.publicKey, programId: programId.publicKey, @@ -213,8 +214,40 @@ test('get program accounts', async () => { skipPreflight: true, }); - mockGetRecentBlockhash('recent'); - const {feeCalculator} = await connection.getRecentBlockhash(); + mockRpc.push([ + url, + { + method: 'getFeeCalculatorForBlockhash', + params: [transaction.recentBlockhash, {commitment: 'recent'}], + }, + { + error: null, + result: { + context: { + slot: 11, + }, + value: { + feeCalculator: { + lamportsPerSignature: 42, + }, + }, + }, + }, + ]); + + if (transaction.recentBlockhash === null) { + expect(transaction.recentBlockhash).not.toBeNull(); + return; + } + + const feeCalculator = ( + await connection.getFeeCalculatorForBlockhash(transaction.recentBlockhash) + ).value; + + if (feeCalculator === null) { + expect(feeCalculator).not.toBeNull(); + return; + } mockRpc.push([ url, @@ -1077,6 +1110,43 @@ test('get recent blockhash', async () => { } }); +test('get fee calculator', async () => { + const connection = new Connection(url); + + mockGetRecentBlockhash('recent'); + const {blockhash} = await connection.getRecentBlockhash('recent'); + + mockRpc.push([ + url, + { + method: 'getFeeCalculatorForBlockhash', + params: [blockhash, {commitment: 'recent'}], + }, + { + error: null, + result: { + context: { + slot: 11, + }, + value: { + feeCalculator: { + lamportsPerSignature: 5000, + }, + }, + }, + }, + ]); + + const feeCalculator = ( + await connection.getFeeCalculatorForBlockhash(blockhash, 'recent') + ).value; + if (feeCalculator === null) { + expect(feeCalculator).not.toBeNull(); + return; + } + expect(feeCalculator.lamportsPerSignature).toEqual(5000); +}); + test('get block time', async () => { const connection = new Connection(url);