fix: update ConfirmedBlock handling to match solana upstream
This commit is contained in:
parent
77745a278d
commit
a461d5f25f
|
@ -71,6 +71,13 @@ declare module '@solana/web3.js' {
|
|||
rpc: string | null,
|
||||
};
|
||||
|
||||
declare export type ConfirmedBlock = {
|
||||
blockhash: Blockhash,
|
||||
previousBlockhash: Blockhash,
|
||||
parentSlot: number,
|
||||
transactions: Array<[Transaction, SignatureSuccess | TransactionError | null]>,
|
||||
};
|
||||
|
||||
declare export type KeyedAccountInfo = {
|
||||
accountId: PublicKey,
|
||||
accountInfo: AccountInfo,
|
||||
|
@ -136,6 +143,7 @@ declare module '@solana/web3.js' {
|
|||
): Promise<RpcResponseAndContext<number>>;
|
||||
getBalance(publicKey: PublicKey, commitment: ?Commitment): Promise<number>;
|
||||
getClusterNodes(): Promise<Array<ContactInfo>>;
|
||||
getConfirmedBlock(): Promise<ConfirmedBlock>;
|
||||
getVoteAccounts(commitment: ?Commitment): Promise<VoteAccountStatus>;
|
||||
confirmTransactionAndContext(
|
||||
signature: TransactionSignature,
|
||||
|
|
|
@ -186,6 +186,22 @@ const Version = struct({
|
|||
'solana-core': 'string',
|
||||
});
|
||||
|
||||
/**
|
||||
* A ConfirmedBlock on the ledger
|
||||
*
|
||||
* @typedef {Object} ConfirmedBlock
|
||||
* @property {Blockhash} blockhash Blockhash of this block
|
||||
* @property {Blockhash} previousBlockhash Blockhash of this block's parent
|
||||
* @property {number} parentSlot Slot index of this block's parent
|
||||
* @property {Array<Array<object>>} transactions Vector of transactions paired with statuses
|
||||
*/
|
||||
type ConfirmedBlock = {
|
||||
blockhash: Blockhash,
|
||||
previousBlockhash: Blockhash,
|
||||
parentSlot: number,
|
||||
transactions: Array<[Transaction, GetSignatureStatusRpcResult]>,
|
||||
};
|
||||
|
||||
function createRpcRequest(url): RpcRequest {
|
||||
const server = jayson(async (request, callback) => {
|
||||
const options = {
|
||||
|
@ -412,37 +428,48 @@ const GetMinimumBalanceForRentExemptionRpcResult = jsonRpcResult('number');
|
|||
* Expected JSON RPC response for the "getConfirmedBlock" message
|
||||
*/
|
||||
export const GetConfirmedBlockRpcResult = jsonRpcResult(
|
||||
struct.list([
|
||||
struct.tuple([
|
||||
struct({
|
||||
signatures: struct.list([struct.list(['number'])]),
|
||||
message: struct({
|
||||
account_keys: struct.list([struct.list(['number'])]),
|
||||
header: struct({
|
||||
num_required_signatures: 'number',
|
||||
num_readonly_signed_accounts: 'number',
|
||||
num_readonly_unsigned_accounts: 'number',
|
||||
}),
|
||||
instructions: struct.list([
|
||||
struct.union([
|
||||
struct.list(['number']),
|
||||
struct({
|
||||
accounts: struct.list([
|
||||
struct.union([struct.list(['number']), 'number']),
|
||||
]),
|
||||
data: struct.list([
|
||||
struct.union([struct.list(['number']), 'number']),
|
||||
]),
|
||||
program_id_index: 'number',
|
||||
}),
|
||||
struct({
|
||||
blockhash: struct.list(['number']),
|
||||
previousBlockhash: struct.list(['number']),
|
||||
parentSlot: 'number',
|
||||
transactions: struct.list([
|
||||
struct.tuple([
|
||||
struct({
|
||||
signatures: struct.list([struct.list(['number'])]),
|
||||
message: struct({
|
||||
accountKeys: struct.list([struct.list(['number'])]),
|
||||
header: struct({
|
||||
numRequiredSignatures: 'number',
|
||||
numReadonlySignedAccounts: 'number',
|
||||
numReadonlyUnsignedAccounts: 'number',
|
||||
}),
|
||||
instructions: struct.list([
|
||||
struct.union([
|
||||
struct.list(['number']),
|
||||
struct({
|
||||
accounts: struct.list([
|
||||
struct.union([struct.list(['number']), 'number']),
|
||||
]),
|
||||
data: struct.list([
|
||||
struct.union([struct.list(['number']), 'number']),
|
||||
]),
|
||||
programIdIndex: 'number',
|
||||
}),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
recent_blockhash: struct.list(['number']),
|
||||
recentBlockhash: struct.list(['number']),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
struct.union([struct({Ok: 'null'}), struct({Err: 'object'})]),
|
||||
struct.union([
|
||||
'null',
|
||||
struct({
|
||||
status: GetSignatureStatusRpcResult,
|
||||
fee: 'number',
|
||||
}),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
}),
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -1055,20 +1082,23 @@ export class Connection {
|
|||
* Fetch a list of Transactions and transaction statuses from the cluster
|
||||
* for a confirmed block
|
||||
*/
|
||||
async getConfirmedBlock(
|
||||
slot: number,
|
||||
): Promise<
|
||||
Array<[Transaction, SignatureSuccess] | [Transaction, TransactionError]>,
|
||||
> {
|
||||
async getConfirmedBlock(slot: number): Promise<ConfirmedBlock> {
|
||||
const unsafeRes = await this._rpcRequest('getConfirmedBlock', [slot]);
|
||||
const result = GetConfirmedBlockRpcResult(unsafeRes);
|
||||
if (result.error) {
|
||||
throw new Error(result.error.message);
|
||||
}
|
||||
assert(typeof result.result !== 'undefined');
|
||||
return result.result.map(result => {
|
||||
return [Transaction.fromRpcResult(result[0]), result[1]];
|
||||
});
|
||||
return {
|
||||
blockhash: new PublicKey(result.result.blockhash).toString(),
|
||||
previousBlockhash: new PublicKey(
|
||||
result.result.previousBlockhash,
|
||||
).toString(),
|
||||
parentSlot: result.result.parentSlot,
|
||||
transactions: result.result.transactions.map(result => {
|
||||
return [Transaction.fromRpcResult(result[0]), result[1]];
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -504,19 +504,19 @@ export class Transaction {
|
|||
*/
|
||||
static fromRpcResult(rpcResult: any): Transaction {
|
||||
const signatures = rpcResult.signatures.slice(1);
|
||||
const accounts = rpcResult.message.account_keys.slice(1);
|
||||
const accounts = rpcResult.message.accountKeys.slice(1);
|
||||
const instructions = rpcResult.message.instructions.slice(1).map(ix => {
|
||||
ix.accounts.shift();
|
||||
ix.data.shift();
|
||||
return ix;
|
||||
});
|
||||
const recentBlockhash = rpcResult.message.recent_blockhash;
|
||||
const recentBlockhash = rpcResult.message.recentBlockhash;
|
||||
const numRequiredSignatures =
|
||||
rpcResult.message.header.num_required_signatures;
|
||||
rpcResult.message.header.numRequiredSignatures;
|
||||
const numReadonlySignedAccounts =
|
||||
rpcResult.message.header.num_readonly_signed_accounts;
|
||||
rpcResult.message.header.numReadonlySignedAccounts;
|
||||
const numReadonlyUnsignedAccounts =
|
||||
rpcResult.message.header.num_readonly_unsigned_accounts;
|
||||
rpcResult.message.header.numReadonlyUnsignedAccounts;
|
||||
return Transaction._populate(
|
||||
signatures,
|
||||
accounts,
|
||||
|
|
|
@ -426,12 +426,26 @@ test('get confirmed block', async () => {
|
|||
}
|
||||
const connection = new Connection(url);
|
||||
|
||||
// These test cases need to be updated when upstream solana RPC api is fleshed out
|
||||
const zeroTransactions = await connection.getConfirmedBlock(0);
|
||||
expect(zeroTransactions.length).toBe(0);
|
||||
// Block 0 never has any transactions in automation localnet
|
||||
const block0 = await connection.getConfirmedBlock(0);
|
||||
const blockhash0 = block0.blockhash;
|
||||
expect(block0.transactions.length).toBe(0);
|
||||
expect(blockhash0).not.toBeNull();
|
||||
expect(block0.previousBlockhash).not.toBeNull();
|
||||
expect(block0.parentSlot).toBe(0);
|
||||
|
||||
const oneTransaction = await connection.getConfirmedBlock(1);
|
||||
expect(oneTransaction.length).toBe(1);
|
||||
// Find a block that has a transaction, usually Block 1
|
||||
let x = 1;
|
||||
while (x < 10) {
|
||||
const block1 = await connection.getConfirmedBlock(x);
|
||||
if (block1.transactions.length >= 1) {
|
||||
expect(block1.previousBlockhash).toBe(blockhash0);
|
||||
expect(block1.blockhash).not.toBeNull();
|
||||
expect(block1.parentSlot).toBe(0);
|
||||
break;
|
||||
}
|
||||
x++;
|
||||
}
|
||||
});
|
||||
|
||||
test('get recent blockhash', async () => {
|
||||
|
|
|
@ -105,7 +105,7 @@ test('transaction from rpc result', () => {
|
|||
const rawBlockhash = new PublicKey(0).toBuffer();
|
||||
const rpcResult = {
|
||||
message: {
|
||||
account_keys: [
|
||||
accountKeys: [
|
||||
[5],
|
||||
new PublicKey(1).toBuffer(),
|
||||
new PublicKey(2).toBuffer(),
|
||||
|
@ -114,19 +114,19 @@ test('transaction from rpc result', () => {
|
|||
new PublicKey(5).toBuffer(),
|
||||
],
|
||||
header: {
|
||||
num_readonly_signed_accounts: 0,
|
||||
num_readonly_unsigned_accounts: 3,
|
||||
num_required_signatures: 2,
|
||||
num_ReadonlySignedAccounts: 0,
|
||||
numReadonlyUnsignedAccounts: 3,
|
||||
numRequiredSignatures: 2,
|
||||
},
|
||||
instructions: [
|
||||
[1],
|
||||
{
|
||||
accounts: [[3], 1, 2, 3],
|
||||
data: [[1], 0],
|
||||
program_id_index: 4,
|
||||
programIdIndex: 4,
|
||||
},
|
||||
],
|
||||
recent_blockhash: rawBlockhash,
|
||||
recentBlockhash: rawBlockhash,
|
||||
},
|
||||
signatures: [[2], Array(64).fill(1), Array(64).fill(2)],
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue