feat: add method to return a confirmed block with signatures only

This commit is contained in:
Tyera Eulberg 2021-04-14 00:56:08 -06:00 committed by Tyera Eulberg
parent 4ac17b1ee3
commit f37c05adeb
2 changed files with 140 additions and 0 deletions

View File

@ -583,6 +583,22 @@ export type ConfirmedBlock = {
blockTime: number | null;
};
/**
* A ConfirmedBlock on the ledger with signatures only
*/
export type ConfirmedBlockSignatures = {
/** Blockhash of this block */
blockhash: Blockhash;
/** Blockhash of this block's parent */
previousBlockhash: Blockhash;
/** Slot index of this block's parent */
parentSlot: number;
/** Vector of signatures */
signatures: Array<string>;
/** The unix timestamp of when the block was processed */
blockTime: number | null;
};
/**
* A performance sample
*/
@ -1231,6 +1247,21 @@ const GetConfirmedBlockRpcResult = jsonRpcResult(
),
);
/**
* Expected JSON RPC response for the "getConfirmedBlockSignatures" message
*/
const GetConfirmedBlockSignaturesRpcResult = jsonRpcResult(
nullable(
pick({
blockhash: string(),
previousBlockhash: string(),
parentSlot: number(),
signatures: array(string()),
blockTime: nullable(number()),
}),
),
);
/**
* Expected JSON RPC response for the "getConfirmedTransaction" message
*/
@ -2477,6 +2508,27 @@ export class Connection {
return result;
}
/**
* Fetch a list of Signatures from the cluster for a confirmed block, excluding rewards
*/
async getConfirmedBlockSignatures(
slot: number,
): Promise<ConfirmedBlockSignatures> {
const unsafeRes = await this._rpcRequest('getConfirmedBlock', [
slot,
{transactionDetails: 'signatures', rewards: false},
]);
const res = create(unsafeRes, GetConfirmedBlockSignaturesRpcResult);
if ('error' in res) {
throw new Error('failed to get confirmed block: ' + res.error.message);
}
const result = res.result;
if (!result) {
throw new Error('Confirmed block ' + slot + ' not found');
}
return result;
}
/**
* Fetch a transaction details for a confirmed transaction
*/

View File

@ -1288,6 +1288,94 @@ describe('Connection', () => {
);
});
it('get confirmed block signatures', async () => {
await mockRpcResponse({
method: 'getSlot',
params: [],
value: 1,
});
while ((await connection.getSlot()) <= 0) {
continue;
}
await mockRpcResponse({
method: 'getConfirmedBlock',
params: [
0,
{
transactionDetails: 'signatures',
rewards: false,
},
],
value: {
blockTime: 1614281964,
blockhash: 'H5nJ91eGag3B5ZSRHZ7zG5ZwXJ6ywCt2hyR8xCsV7xMo',
previousBlockhash: 'H5nJ91eGag3B5ZSRHZ7zG5ZwXJ6ywCt2hyR8xCsV7xMo',
parentSlot: 0,
signatures: [],
},
});
// Block 0 never has any transactions in test validator
const block0 = await connection.getConfirmedBlockSignatures(0);
const blockhash0 = block0.blockhash;
expect(block0.signatures).to.have.length(0);
expect(blockhash0).not.to.be.null;
expect(block0.previousBlockhash).not.to.be.null;
expect(block0.parentSlot).to.eq(0);
expect(block0).to.not.have.property('rewards');
await mockRpcResponse({
method: 'getConfirmedBlock',
params: [
1,
{
transactionDetails: 'signatures',
rewards: false,
},
],
value: {
blockTime: 1614281964,
blockhash: '57zQNBZBEiHsCZFqsaY6h176ioXy5MsSLmcvHkEyaLGy',
previousBlockhash: 'H5nJ91eGag3B5ZSRHZ7zG5ZwXJ6ywCt2hyR8xCsV7xMo',
parentSlot: 0,
signatures: [
'w2Zeq8YkpyB463DttvfzARD7k9ZxGEwbsEw4boEK7jDp3pfoxZbTdLFSsEPhzXhpCcjGi2kHtHFobgX49MMhbWt',
'4oCEqwGrMdBeMxpzuWiukCYqSfV4DsSKXSiVVCh1iJ6pS772X7y219JZP3mgqBz5PhsvprpKyhzChjYc3VSBQXzG',
],
},
});
// Find a block that has a transaction, usually Block 1
let x = 1;
while (x < 10) {
const block1 = await connection.getConfirmedBlockSignatures(x);
if (block1.signatures.length >= 1) {
expect(block1.previousBlockhash).to.eq(blockhash0);
expect(block1.blockhash).not.to.be.null;
expect(block1.parentSlot).to.eq(0);
expect(block1.signatures[0]).not.to.be.null;
expect(block1).to.not.have.property('rewards');
break;
}
x++;
}
await mockRpcResponse({
method: 'getConfirmedBlock',
params: [Number.MAX_SAFE_INTEGER],
error: {
message: `Block not available for slot ${Number.MAX_SAFE_INTEGER}`,
},
});
await expect(
connection.getConfirmedBlockSignatures(Number.MAX_SAFE_INTEGER),
).to.be.rejectedWith(
`Block not available for slot ${Number.MAX_SAFE_INTEGER}`,
);
});
it('get recent blockhash', async () => {
const commitments: Commitment[] = ['processed', 'confirmed', 'finalized'];
for (const commitment of commitments) {