Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add isBlockhashValid method to web3.js #25888

Closed
wants to merge 16 commits into from
Closed
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
37 changes: 37 additions & 0 deletions web3.js/src/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1042,6 +1042,16 @@ const BlockProductionResponseStruct = jsonRpcResultAndContext(
}),
);

/**
* Configuration object for changing `isBlockhashValid` query behavior
*/
export type IsBlockhashValidConfig = {
/** The level of commitment desired */
commitment?: Commitment;
/** The minimum slot that the request can be evaluated at */
minContextSlot?: number;
};

/**
* A performance sample
*/
Expand Down Expand Up @@ -3547,6 +3557,33 @@ export class Connection {
return res.result;
}

/**
* Check whether a blockhash is still valid or not
*/
async isBlockhashValid(
blockhash: string,
config?: IsBlockhashValidConfig,
): Promise<RpcResponseAndContext<boolean>> {
const {commitment, config: configWithoutCommitment} =
extractCommitmentFromConfig(config);
const args = this._buildArgs(
[blockhash],
commitment,
'jsonParsed',
configWithoutCommitment,
);

const unsafeRes = await this._rpcRequest('isBlockhashValid', args);
const res = create(unsafeRes, jsonRpcResultAndContext(boolean()));
if ('error' in res) {
throw new SolanaJSONRPCError(
res.error,
'Could not determine if blockhash `' + blockhash + '` was valid',
);
}
return res.result;
}

/**
* Fetch the node version
*/
Expand Down
62 changes: 62 additions & 0 deletions web3.js/test/connection.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3087,6 +3087,68 @@ describe('Connection', function () {
}
});

describe('is blockhash valid', () => {
it('is blockhash valid - blockhash only (mock)', async () => {
const {blockhash} = await helpers.recentBlockhash({connection});

await mockRpcResponse({
method: 'isBlockhashValid',
params: [blockhash],
value: true,
withContext: true,
});

const isValid = await connection.isBlockhashValid(blockhash);
expect(isValid.value).to.be.true;
});

it('is blockhash valid - blockhash and min slot (mock)', async () => {
const {blockhash} = await helpers.recentBlockhash({connection});

await mockRpcResponse({
method: 'isBlockhashValid',
params: [blockhash, {minContextSlot: 2}],
value: true,
withContext: true,
});

const isValid = await connection.isBlockhashValid(blockhash, {
minContextSlot: 2,
});
expect(isValid.value).to.be.true;
});

if (process.env.TEST_LIVE) {
it('is blockhash valid - blockhash only (live)', async () => {
const {blockhash} = await helpers.recentBlockhash({connection});
const isValid = await connection.isBlockhashValid(blockhash);
expect(isValid.value).to.be.true;
});

it('is blockhash valid - blockhash only and min slot (live)', async () => {
const blockhash = await connection.getLatestBlockhashAndContext(
'processed',
);

const isValid = await connection.isBlockhashValid(
blockhash.value.blockhash,
{
commitment: 'finalized',
minContextSlot: blockhash.context.slot,
},
);
expect(isValid.value).to.be.false;
});

it('is blockhash valid - junk blockhash (live)', async () => {
const isValid = await connection.isBlockhashValid(
'57zQNBZBEiHsCZFqsaY6h176ioXy5MsSLmcvHkEyaLGy',
);
expect(isValid.value).to.be.false;
});
}
});

it('get minimum ledger slot', async () => {
await mockRpcResponse({
method: 'minimumLedgerSlot',
Expand Down