chore: update Connection to non-deprecated endpoints (#22800)

* chore: remove usage of `getConfirmedTransaction`

* chore: use `getBlock` instead of `getConfirmedBlock`

* chore: add `getLatestBlockhash` and test
This commit is contained in:
Jon Cinque
2022-01-28 00:43:01 +01:00
committed by GitHub
parent 350207b05f
commit fa51e5b704
3 changed files with 310 additions and 52 deletions

View File

@ -504,8 +504,15 @@ export type TokenBalance = {
/** /**
* Metadata for a parsed confirmed transaction on the ledger * Metadata for a parsed confirmed transaction on the ledger
*
* @deprecated Deprecated since Solana v1.8.0. Please use {@link ParsedTransactionMeta} instead.
*/ */
export type ParsedConfirmedTransactionMeta = { export type ParsedConfirmedTransactionMeta = ParsedTransactionMeta;
/**
* Metadata for a parsed transaction on the ledger
*/
export type ParsedTransactionMeta = {
/** The fee charged for processing the transaction */ /** The fee charged for processing the transaction */
fee: number; fee: number;
/** An array of cross program invoked parsed instructions */ /** An array of cross program invoked parsed instructions */
@ -644,14 +651,21 @@ export type ParsedTransaction = {
/** /**
* A parsed and confirmed transaction on the ledger * A parsed and confirmed transaction on the ledger
*
* @deprecated Deprecated since Solana v1.8.0. Please use {@link ParsedTransactionWithMeta} instead.
*/ */
export type ParsedConfirmedTransaction = { export type ParsedConfirmedTransaction = ParsedTransactionWithMeta;
/**
* A parsed transaction on the ledger with meta
*/
export type ParsedTransactionWithMeta = {
/** The slot during which the transaction was processed */ /** The slot during which the transaction was processed */
slot: number; slot: number;
/** The details of the transaction */ /** The details of the transaction */
transaction: ParsedTransaction; transaction: ParsedTransaction;
/** Metadata produced from the transaction */ /** Metadata produced from the transaction */
meta: ParsedConfirmedTransactionMeta | null; meta: ParsedTransactionMeta | null;
/** The unix timestamp of when the transaction was processed */ /** The unix timestamp of when the transaction was processed */
blockTime?: number | null; blockTime?: number | null;
}; };
@ -720,9 +734,9 @@ export type ConfirmedBlock = {
}; };
/** /**
* A ConfirmedBlock on the ledger with signatures only * A Block on the ledger with signatures only
*/ */
export type ConfirmedBlockSignatures = { export type BlockSignatures = {
/** Blockhash of this block */ /** Blockhash of this block */
blockhash: Blockhash; blockhash: Blockhash;
/** Blockhash of this block's parent */ /** Blockhash of this block's parent */
@ -1494,8 +1508,41 @@ const ParsedConfirmedTransactionMetaResult = pick({
postTokenBalances: optional(nullable(array(TokenBalanceResult))), postTokenBalances: optional(nullable(array(TokenBalanceResult))),
}); });
/**
* Expected JSON RPC response for the "getBlock" message
*/
const GetBlockRpcResult = jsonRpcResult(
nullable(
pick({
blockhash: string(),
previousBlockhash: string(),
parentSlot: number(),
transactions: array(
pick({
transaction: ConfirmedTransactionResult,
meta: nullable(ConfirmedTransactionMetaResult),
}),
),
rewards: optional(
array(
pick({
pubkey: string(),
lamports: number(),
postBalance: nullable(number()),
rewardType: nullable(string()),
}),
),
),
blockTime: nullable(number()),
blockHeight: nullable(number()),
}),
),
);
/** /**
* Expected JSON RPC response for the "getConfirmedBlock" message * Expected JSON RPC response for the "getConfirmedBlock" message
*
* @deprecated Deprecated since Solana v1.8.0. Please use {@link GetBlockRpcResult} instead.
*/ */
const GetConfirmedBlockRpcResult = jsonRpcResult( const GetConfirmedBlockRpcResult = jsonRpcResult(
nullable( nullable(
@ -1525,9 +1572,9 @@ const GetConfirmedBlockRpcResult = jsonRpcResult(
); );
/** /**
* Expected JSON RPC response for the "getConfirmedBlockSignatures" message * Expected JSON RPC response for the "getBlock" message
*/ */
const GetConfirmedBlockSignaturesRpcResult = jsonRpcResult( const GetBlockSignaturesRpcResult = jsonRpcResult(
nullable( nullable(
pick({ pick({
blockhash: string(), blockhash: string(),
@ -1540,9 +1587,9 @@ const GetConfirmedBlockSignaturesRpcResult = jsonRpcResult(
); );
/** /**
* Expected JSON RPC response for the "getConfirmedTransaction" message * Expected JSON RPC response for the "getTransaction" message
*/ */
const GetConfirmedTransactionRpcResult = jsonRpcResult( const GetTransactionRpcResult = jsonRpcResult(
nullable( nullable(
pick({ pick({
slot: number(), slot: number(),
@ -1554,9 +1601,9 @@ const GetConfirmedTransactionRpcResult = jsonRpcResult(
); );
/** /**
* Expected JSON RPC response for the "getConfirmedTransaction" message * Expected parsed JSON RPC response for the "getTransaction" message
*/ */
const GetParsedConfirmedTransactionRpcResult = jsonRpcResult( const GetParsedTransactionRpcResult = jsonRpcResult(
nullable( nullable(
pick({ pick({
slot: number(), slot: number(),
@ -1569,6 +1616,8 @@ const GetParsedConfirmedTransactionRpcResult = jsonRpcResult(
/** /**
* Expected JSON RPC response for the "getRecentBlockhash" message * Expected JSON RPC response for the "getRecentBlockhash" message
*
* @deprecated Deprecated since Solana v1.8.0. Please use {@link GetLatestBlockhashRpcResult} instead.
*/ */
const GetRecentBlockhashAndContextRpcResult = jsonRpcResultAndContext( const GetRecentBlockhashAndContextRpcResult = jsonRpcResultAndContext(
pick({ pick({
@ -1579,6 +1628,16 @@ const GetRecentBlockhashAndContextRpcResult = jsonRpcResultAndContext(
}), }),
); );
/**
* Expected JSON RPC response for the "getLatestBlockhash" message
*/
const GetLatestBlockhashRpcResult = jsonRpcResultAndContext(
pick({
blockhash: string(),
lastValidBlockHeight: number(),
}),
);
const PerfSampleResult = pick({ const PerfSampleResult = pick({
slot: number(), slot: number(),
numTransactions: number(), numTransactions: number(),
@ -2962,6 +3021,8 @@ export class Connection {
/** /**
* Fetch a recent blockhash from the cluster, return with context * Fetch a recent blockhash from the cluster, return with context
* @return {Promise<RpcResponseAndContext<{blockhash: Blockhash, feeCalculator: FeeCalculator}>>} * @return {Promise<RpcResponseAndContext<{blockhash: Blockhash, feeCalculator: FeeCalculator}>>}
*
* @deprecated Deprecated since Solana v1.8.0. Please use {@link getLatestBlockhash} instead.
*/ */
async getRecentBlockhashAndContext( async getRecentBlockhashAndContext(
commitment?: Commitment, commitment?: Commitment,
@ -3001,6 +3062,8 @@ export class Connection {
/** /**
* Fetch the fee calculator for a recent blockhash from the cluster, return with context * Fetch the fee calculator for a recent blockhash from the cluster, return with context
*
* @deprecated Deprecated since Solana v1.8.0. Please use {@link getFeeForMessage} instead.
*/ */
async getFeeCalculatorForBlockhash( async getFeeCalculatorForBlockhash(
blockhash: Blockhash, blockhash: Blockhash,
@ -3047,6 +3110,8 @@ export class Connection {
/** /**
* Fetch a recent blockhash from the cluster * Fetch a recent blockhash from the cluster
* @return {Promise<{blockhash: Blockhash, feeCalculator: FeeCalculator}>} * @return {Promise<{blockhash: Blockhash, feeCalculator: FeeCalculator}>}
*
* @deprecated Deprecated since Solana v1.8.0. Please use {@link getLatestBlockhash} instead.
*/ */
async getRecentBlockhash( async getRecentBlockhash(
commitment?: Commitment, commitment?: Commitment,
@ -3059,6 +3124,39 @@ export class Connection {
} }
} }
/**
* Fetch the latest blockhash from the cluster
* @return {Promise<{blockhash: Blockhash, lastValidBlockHeight: number}>}
*/
async getLatestBlockhash(
commitment?: Commitment,
): Promise<{blockhash: Blockhash; lastValidBlockHeight: number}> {
try {
const res = await this.getLatestBlockhashAndContext(commitment);
return res.value;
} catch (e) {
throw new Error('failed to get recent blockhash: ' + e);
}
}
/**
* Fetch the latest blockhash from the cluster
* @return {Promise<{blockhash: Blockhash, lastValidBlockHeight: number}>}
*/
async getLatestBlockhashAndContext(
commitment?: Commitment,
): Promise<
RpcResponseAndContext<{blockhash: Blockhash; lastValidBlockHeight: number}>
> {
const args = this._buildArgs([], commitment);
const unsafeRes = await this._rpcRequest('getLatestBlockhash', args);
const res = create(unsafeRes, GetLatestBlockhashRpcResult);
if ('error' in res) {
throw new Error('failed to get latest blockhash: ' + res.error.message);
}
return res.result;
}
/** /**
* Fetch the node version * Fetch the node version
*/ */
@ -3094,8 +3192,8 @@ export class Connection {
[slot], [slot],
opts && opts.commitment, opts && opts.commitment,
); );
const unsafeRes = await this._rpcRequest('getConfirmedBlock', args); const unsafeRes = await this._rpcRequest('getBlock', args);
const res = create(unsafeRes, GetConfirmedBlockRpcResult); const res = create(unsafeRes, GetBlockRpcResult);
if ('error' in res) { if ('error' in res) {
throw new Error('failed to get confirmed block: ' + res.error.message); throw new Error('failed to get confirmed block: ' + res.error.message);
@ -3120,7 +3218,7 @@ export class Connection {
} }
/** /**
* Fetch a processed transaction from the cluster. * Fetch a confirmed or finalized transaction from the cluster.
*/ */
async getTransaction( async getTransaction(
signature: string, signature: string,
@ -3130,12 +3228,10 @@ export class Connection {
[signature], [signature],
opts && opts.commitment, opts && opts.commitment,
); );
const unsafeRes = await this._rpcRequest('getConfirmedTransaction', args); const unsafeRes = await this._rpcRequest('getTransaction', args);
const res = create(unsafeRes, GetConfirmedTransactionRpcResult); const res = create(unsafeRes, GetTransactionRpcResult);
if ('error' in res) { if ('error' in res) {
throw new Error( throw new Error('failed to get transaction: ' + res.error.message);
'failed to get confirmed transaction: ' + res.error.message,
);
} }
const result = res.result; const result = res.result;
@ -3150,6 +3246,57 @@ export class Connection {
}; };
} }
/**
* Fetch parsed transaction details for a confirmed or finalized transaction
*/
async getParsedTransaction(
signature: TransactionSignature,
commitment?: Finality,
): Promise<ParsedConfirmedTransaction | null> {
const args = this._buildArgsAtLeastConfirmed(
[signature],
commitment,
'jsonParsed',
);
const unsafeRes = await this._rpcRequest('getTransaction', args);
const res = create(unsafeRes, GetParsedTransactionRpcResult);
if ('error' in res) {
throw new Error('failed to get transaction: ' + res.error.message);
}
return res.result;
}
/**
* Fetch parsed transaction details for a batch of confirmed transactions
*/
async getParsedTransactions(
signatures: TransactionSignature[],
commitment?: Finality,
): Promise<(ParsedConfirmedTransaction | null)[]> {
const batch = signatures.map(signature => {
const args = this._buildArgsAtLeastConfirmed(
[signature],
commitment,
'jsonParsed',
);
return {
methodName: 'getTransaction',
args,
};
});
const unsafeRes = await this._rpcBatchRequest(batch);
const res = unsafeRes.map((unsafeRes: any) => {
const res = create(unsafeRes, GetParsedTransactionRpcResult);
if ('error' in res) {
throw new Error('failed to get transactions: ' + res.error.message);
}
return res.result;
});
return res;
}
/** /**
* Fetch a list of Transactions and transaction statuses from the cluster * Fetch a list of Transactions and transaction statuses from the cluster
* for a confirmed block. * for a confirmed block.
@ -3160,14 +3307,36 @@ export class Connection {
slot: number, slot: number,
commitment?: Finality, commitment?: Finality,
): Promise<ConfirmedBlock> { ): Promise<ConfirmedBlock> {
const result = await this.getBlock(slot, {commitment}); const args = this._buildArgsAtLeastConfirmed([slot], commitment);
const unsafeRes = await this._rpcRequest('getConfirmedBlock', args);
const res = create(unsafeRes, GetConfirmedBlockRpcResult);
if ('error' in res) {
throw new Error('failed to get confirmed block: ' + res.error.message);
}
const result = res.result;
if (!result) { if (!result) {
throw new Error('Confirmed block ' + slot + ' not found'); throw new Error('Confirmed block ' + slot + ' not found');
} }
return { const block = {
...result, ...result,
transactions: result.transactions.map(({transaction, meta}) => { transactions: result.transactions.map(({transaction, meta}) => {
const message = new Message(transaction.message);
return {
meta,
transaction: {
...transaction,
message,
},
};
}),
};
return {
...block,
transactions: block.transactions.map(({transaction, meta}) => {
return { return {
meta, meta,
transaction: Transaction.populate( transaction: Transaction.populate(
@ -3191,7 +3360,7 @@ export class Connection {
endSlot !== undefined ? [startSlot, endSlot] : [startSlot], endSlot !== undefined ? [startSlot, endSlot] : [startSlot],
commitment, commitment,
); );
const unsafeRes = await this._rpcRequest('getConfirmedBlocks', args); const unsafeRes = await this._rpcRequest('getBlocks', args);
const res = create(unsafeRes, jsonRpcResult(array(number()))); const res = create(unsafeRes, jsonRpcResult(array(number())));
if ('error' in res) { if ('error' in res) {
throw new Error('failed to get blocks: ' + res.error.message); throw new Error('failed to get blocks: ' + res.error.message);
@ -3199,13 +3368,43 @@ export class Connection {
return res.result; return res.result;
} }
/**
* Fetch a list of Signatures from the cluster for a block, excluding rewards
*/
async getBlockSignatures(
slot: number,
commitment?: Finality,
): Promise<BlockSignatures> {
const args = this._buildArgsAtLeastConfirmed(
[slot],
commitment,
undefined,
{
transactionDetails: 'signatures',
rewards: false,
},
);
const unsafeRes = await this._rpcRequest('getBlock', args);
const res = create(unsafeRes, GetBlockSignaturesRpcResult);
if ('error' in res) {
throw new Error('failed to get block: ' + res.error.message);
}
const result = res.result;
if (!result) {
throw new Error('Block ' + slot + ' not found');
}
return result;
}
/** /**
* Fetch a list of Signatures from the cluster for a confirmed block, excluding rewards * Fetch a list of Signatures from the cluster for a confirmed block, excluding rewards
*
* @deprecated Deprecated since Solana v1.8.0. Please use {@link getBlockSignatures} instead.
*/ */
async getConfirmedBlockSignatures( async getConfirmedBlockSignatures(
slot: number, slot: number,
commitment?: Finality, commitment?: Finality,
): Promise<ConfirmedBlockSignatures> { ): Promise<BlockSignatures> {
const args = this._buildArgsAtLeastConfirmed( const args = this._buildArgsAtLeastConfirmed(
[slot], [slot],
commitment, commitment,
@ -3216,7 +3415,7 @@ export class Connection {
}, },
); );
const unsafeRes = await this._rpcRequest('getConfirmedBlock', args); const unsafeRes = await this._rpcRequest('getConfirmedBlock', args);
const res = create(unsafeRes, GetConfirmedBlockSignaturesRpcResult); const res = create(unsafeRes, GetBlockSignaturesRpcResult);
if ('error' in res) { if ('error' in res) {
throw new Error('failed to get confirmed block: ' + res.error.message); throw new Error('failed to get confirmed block: ' + res.error.message);
} }
@ -3229,14 +3428,25 @@ export class Connection {
/** /**
* Fetch a transaction details for a confirmed transaction * Fetch a transaction details for a confirmed transaction
*
* @deprecated Deprecated since Solana v1.8.0. Please use {@link getTransaction} instead.
*/ */
async getConfirmedTransaction( async getConfirmedTransaction(
signature: TransactionSignature, signature: TransactionSignature,
commitment?: Finality, commitment?: Finality,
): Promise<ConfirmedTransaction | null> { ): Promise<ConfirmedTransaction | null> {
const result = await this.getTransaction(signature, {commitment}); const args = this._buildArgsAtLeastConfirmed([signature], commitment);
const unsafeRes = await this._rpcRequest('getConfirmedTransaction', args);
const res = create(unsafeRes, GetTransactionRpcResult);
if ('error' in res) {
throw new Error('failed to get transaction: ' + res.error.message);
}
const result = res.result;
if (!result) return result; if (!result) return result;
const {message, signatures} = result.transaction;
const message = new Message(result.transaction.message);
const signatures = result.transaction.signatures;
return { return {
...result, ...result,
transaction: Transaction.populate(message, signatures), transaction: Transaction.populate(message, signatures),
@ -3245,6 +3455,8 @@ export class Connection {
/** /**
* Fetch parsed transaction details for a confirmed transaction * Fetch parsed transaction details for a confirmed transaction
*
* @deprecated Deprecated since Solana v1.8.0. Please use {@link getParsedTransaction} instead.
*/ */
async getParsedConfirmedTransaction( async getParsedConfirmedTransaction(
signature: TransactionSignature, signature: TransactionSignature,
@ -3256,7 +3468,7 @@ export class Connection {
'jsonParsed', 'jsonParsed',
); );
const unsafeRes = await this._rpcRequest('getConfirmedTransaction', args); const unsafeRes = await this._rpcRequest('getConfirmedTransaction', args);
const res = create(unsafeRes, GetParsedConfirmedTransactionRpcResult); const res = create(unsafeRes, GetParsedTransactionRpcResult);
if ('error' in res) { if ('error' in res) {
throw new Error( throw new Error(
'failed to get confirmed transaction: ' + res.error.message, 'failed to get confirmed transaction: ' + res.error.message,
@ -3267,6 +3479,8 @@ export class Connection {
/** /**
* Fetch parsed transaction details for a batch of confirmed transactions * Fetch parsed transaction details for a batch of confirmed transactions
*
* @deprecated Deprecated since Solana v1.8.0. Please use {@link getParsedTransactions} instead.
*/ */
async getParsedConfirmedTransactions( async getParsedConfirmedTransactions(
signatures: TransactionSignature[], signatures: TransactionSignature[],
@ -3286,7 +3500,7 @@ export class Connection {
const unsafeRes = await this._rpcBatchRequest(batch); const unsafeRes = await this._rpcBatchRequest(batch);
const res = unsafeRes.map((unsafeRes: any) => { const res = unsafeRes.map((unsafeRes: any) => {
const res = create(unsafeRes, GetParsedConfirmedTransactionRpcResult); const res = create(unsafeRes, GetParsedTransactionRpcResult);
if ('error' in res) { if ('error' in res) {
throw new Error( throw new Error(
'failed to get confirmed transactions: ' + res.error.message, 'failed to get confirmed transactions: ' + res.error.message,

View File

@ -1501,9 +1501,10 @@ describe('Connection', () => {
} }
await mockRpcResponse({ await mockRpcResponse({
method: 'getConfirmedBlock', method: 'getBlock',
params: [1], params: [1],
value: { value: {
blockHeight: 0,
blockTime: 1614281964, blockTime: 1614281964,
blockhash: '57zQNBZBEiHsCZFqsaY6h176ioXy5MsSLmcvHkEyaLGy', blockhash: '57zQNBZBEiHsCZFqsaY6h176ioXy5MsSLmcvHkEyaLGy',
previousBlockhash: 'H5nJ91eGag3B5ZSRHZ7zG5ZwXJ6ywCt2hyR8xCsV7xMo', previousBlockhash: 'H5nJ91eGag3B5ZSRHZ7zG5ZwXJ6ywCt2hyR8xCsV7xMo',
@ -1552,18 +1553,18 @@ describe('Connection', () => {
// Find a block that has a transaction, usually Block 1 // Find a block that has a transaction, usually Block 1
let slot = 0; let slot = 0;
let confirmedTransaction: string | undefined; let transaction: string | undefined;
while (!confirmedTransaction) { while (!transaction) {
slot++; slot++;
const block = await connection.getBlock(slot); const block = await connection.getBlock(slot);
if (block && block.transactions.length > 0) { if (block && block.transactions.length > 0) {
confirmedTransaction = block.transactions[0].transaction.signatures[0]; transaction = block.transactions[0].transaction.signatures[0];
} }
} }
await mockRpcResponse({ await mockRpcResponse({
method: 'getConfirmedTransaction', method: 'getTransaction',
params: [confirmedTransaction], params: [transaction],
value: { value: {
slot, slot,
transaction: { transaction: {
@ -1604,7 +1605,7 @@ describe('Connection', () => {
}, },
}); });
const result = await connection.getTransaction(confirmedTransaction); const result = await connection.getTransaction(transaction);
if (!result) { if (!result) {
expect(result).to.be.ok; expect(result).to.be.ok;
@ -1612,7 +1613,7 @@ describe('Connection', () => {
} }
const resultSignature = result.transaction.signatures[0]; const resultSignature = result.transaction.signatures[0];
expect(resultSignature).to.eq(confirmedTransaction); expect(resultSignature).to.eq(transaction);
const newAddress = Keypair.generate().publicKey; const newAddress = Keypair.generate().publicKey;
const recentSignature = await helpers.airdrop({ const recentSignature = await helpers.airdrop({
@ -1622,7 +1623,7 @@ describe('Connection', () => {
}); });
await mockRpcResponse({ await mockRpcResponse({
method: 'getConfirmedTransaction', method: 'getTransaction',
params: [recentSignature], params: [recentSignature],
value: null, value: null,
}); });
@ -1896,9 +1897,10 @@ describe('Connection', () => {
} }
await mockRpcResponse({ await mockRpcResponse({
method: 'getConfirmedBlock', method: 'getBlock',
params: [0], params: [0],
value: { value: {
blockHeight: 0,
blockTime: 1614281964, blockTime: 1614281964,
blockhash: 'H5nJ91eGag3B5ZSRHZ7zG5ZwXJ6ywCt2hyR8xCsV7xMo', blockhash: 'H5nJ91eGag3B5ZSRHZ7zG5ZwXJ6ywCt2hyR8xCsV7xMo',
previousBlockhash: 'H5nJ91eGag3B5ZSRHZ7zG5ZwXJ6ywCt2hyR8xCsV7xMo', previousBlockhash: 'H5nJ91eGag3B5ZSRHZ7zG5ZwXJ6ywCt2hyR8xCsV7xMo',
@ -1921,9 +1923,10 @@ describe('Connection', () => {
expect(block0.parentSlot).to.eq(0); expect(block0.parentSlot).to.eq(0);
await mockRpcResponse({ await mockRpcResponse({
method: 'getConfirmedBlock', method: 'getBlock',
params: [1], params: [1],
value: { value: {
blockHeight: 0,
blockTime: 1614281964, blockTime: 1614281964,
blockhash: '57zQNBZBEiHsCZFqsaY6h176ioXy5MsSLmcvHkEyaLGy', blockhash: '57zQNBZBEiHsCZFqsaY6h176ioXy5MsSLmcvHkEyaLGy',
previousBlockhash: 'H5nJ91eGag3B5ZSRHZ7zG5ZwXJ6ywCt2hyR8xCsV7xMo', previousBlockhash: 'H5nJ91eGag3B5ZSRHZ7zG5ZwXJ6ywCt2hyR8xCsV7xMo',
@ -1985,7 +1988,7 @@ describe('Connection', () => {
} }
await mockRpcResponse({ await mockRpcResponse({
method: 'getConfirmedBlock', method: 'getBlock',
params: [Number.MAX_SAFE_INTEGER], params: [Number.MAX_SAFE_INTEGER],
error: { error: {
message: `Block not available for slot ${Number.MAX_SAFE_INTEGER}`, message: `Block not available for slot ${Number.MAX_SAFE_INTEGER}`,
@ -2109,7 +2112,7 @@ describe('Connection', () => {
it('get blocks between two slots', async () => { it('get blocks between two slots', async () => {
await mockRpcResponse({ await mockRpcResponse({
method: 'getConfirmedBlocks', method: 'getBlocks',
params: [0, 10], params: [0, 10],
value: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], value: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
}); });
@ -2129,7 +2132,7 @@ describe('Connection', () => {
it('get blocks from starting slot', async () => { it('get blocks from starting slot', async () => {
await mockRpcResponse({ await mockRpcResponse({
method: 'getConfirmedBlocks', method: 'getBlocks',
params: [0], params: [0],
value: [ value: [
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
@ -2155,7 +2158,7 @@ describe('Connection', () => {
expect(blocks).to.contain(latestSlot); expect(blocks).to.contain(latestSlot);
}); });
it('get confirmed block signatures', async () => { it('get block signatures', async () => {
await mockRpcResponse({ await mockRpcResponse({
method: 'getSlot', method: 'getSlot',
params: [], params: [],
@ -2167,7 +2170,7 @@ describe('Connection', () => {
} }
await mockRpcResponse({ await mockRpcResponse({
method: 'getConfirmedBlock', method: 'getBlock',
params: [ params: [
0, 0,
{ {
@ -2176,6 +2179,7 @@ describe('Connection', () => {
}, },
], ],
value: { value: {
blockHeight: 0,
blockTime: 1614281964, blockTime: 1614281964,
blockhash: 'H5nJ91eGag3B5ZSRHZ7zG5ZwXJ6ywCt2hyR8xCsV7xMo', blockhash: 'H5nJ91eGag3B5ZSRHZ7zG5ZwXJ6ywCt2hyR8xCsV7xMo',
previousBlockhash: 'H5nJ91eGag3B5ZSRHZ7zG5ZwXJ6ywCt2hyR8xCsV7xMo', previousBlockhash: 'H5nJ91eGag3B5ZSRHZ7zG5ZwXJ6ywCt2hyR8xCsV7xMo',
@ -2185,7 +2189,7 @@ describe('Connection', () => {
}); });
// Block 0 never has any transactions in test validator // Block 0 never has any transactions in test validator
const block0 = await connection.getConfirmedBlockSignatures(0); const block0 = await connection.getBlockSignatures(0);
const blockhash0 = block0.blockhash; const blockhash0 = block0.blockhash;
expect(block0.signatures).to.have.length(0); expect(block0.signatures).to.have.length(0);
expect(blockhash0).not.to.be.null; expect(blockhash0).not.to.be.null;
@ -2194,7 +2198,7 @@ describe('Connection', () => {
expect(block0).to.not.have.property('rewards'); expect(block0).to.not.have.property('rewards');
await mockRpcResponse({ await mockRpcResponse({
method: 'getConfirmedBlock', method: 'getBlock',
params: [ params: [
1, 1,
{ {
@ -2203,6 +2207,7 @@ describe('Connection', () => {
}, },
], ],
value: { value: {
blockHeight: 1,
blockTime: 1614281964, blockTime: 1614281964,
blockhash: '57zQNBZBEiHsCZFqsaY6h176ioXy5MsSLmcvHkEyaLGy', blockhash: '57zQNBZBEiHsCZFqsaY6h176ioXy5MsSLmcvHkEyaLGy',
previousBlockhash: 'H5nJ91eGag3B5ZSRHZ7zG5ZwXJ6ywCt2hyR8xCsV7xMo', previousBlockhash: 'H5nJ91eGag3B5ZSRHZ7zG5ZwXJ6ywCt2hyR8xCsV7xMo',
@ -2217,7 +2222,7 @@ describe('Connection', () => {
// Find a block that has a transaction, usually Block 1 // Find a block that has a transaction, usually Block 1
let x = 1; let x = 1;
while (x < 10) { while (x < 10) {
const block1 = await connection.getConfirmedBlockSignatures(x); const block1 = await connection.getBlockSignatures(x);
if (block1.signatures.length >= 1) { if (block1.signatures.length >= 1) {
expect(block1.previousBlockhash).to.eq(blockhash0); expect(block1.previousBlockhash).to.eq(blockhash0);
expect(block1.blockhash).not.to.be.null; expect(block1.blockhash).not.to.be.null;
@ -2230,14 +2235,14 @@ describe('Connection', () => {
} }
await mockRpcResponse({ await mockRpcResponse({
method: 'getConfirmedBlock', method: 'getBlock',
params: [Number.MAX_SAFE_INTEGER], params: [Number.MAX_SAFE_INTEGER],
error: { error: {
message: `Block not available for slot ${Number.MAX_SAFE_INTEGER}`, message: `Block not available for slot ${Number.MAX_SAFE_INTEGER}`,
}, },
}); });
await expect( await expect(
connection.getConfirmedBlockSignatures(Number.MAX_SAFE_INTEGER), connection.getBlockSignatures(Number.MAX_SAFE_INTEGER),
).to.be.rejectedWith( ).to.be.rejectedWith(
`Block not available for slot ${Number.MAX_SAFE_INTEGER}`, `Block not available for slot ${Number.MAX_SAFE_INTEGER}`,
); );
@ -2255,6 +2260,18 @@ describe('Connection', () => {
} }
}); });
it('get latest blockhash', async () => {
const commitments: Commitment[] = ['processed', 'confirmed', 'finalized'];
for (const commitment of commitments) {
const {blockhash, lastValidBlockHeight} = await helpers.latestBlockhash({
connection,
commitment,
});
expect(bs58.decode(blockhash)).to.have.length(32);
expect(lastValidBlockHeight).to.be.at.least(0);
}
});
it('get fee calculator', async () => { it('get fee calculator', async () => {
const {blockhash} = await helpers.recentBlockhash({connection}); const {blockhash} = await helpers.recentBlockhash({connection});
await mockRpcResponse({ await mockRpcResponse({
@ -2282,7 +2299,7 @@ describe('Connection', () => {
const accountFrom = Keypair.generate(); const accountFrom = Keypair.generate();
const accountTo = Keypair.generate(); const accountTo = Keypair.generate();
const {blockhash} = await helpers.recentBlockhash({connection}); const {blockhash} = await helpers.latestBlockhash({connection});
const transaction = new Transaction({ const transaction = new Transaction({
feePayer: accountFrom.publicKey, feePayer: accountFrom.publicKey,
@ -2972,7 +2989,7 @@ describe('Connection', () => {
}); });
const recentBlockhash = await ( const recentBlockhash = await (
await helpers.recentBlockhash({connection}) await helpers.latestBlockhash({connection})
).blockhash; ).blockhash;
const message = new Message({ const message = new Message({
accountKeys: [ accountKeys: [

View File

@ -104,6 +104,32 @@ export const mockRpcResponse = async ({
); );
}; };
const latestBlockhash = async ({
connection,
commitment,
}: {
connection: Connection;
commitment?: Commitment;
}) => {
const blockhash = uniqueBlockhash();
const params = [];
if (commitment) {
params.push({commitment});
}
await mockRpcResponse({
method: 'getLatestBlockhash',
params,
value: {
blockhash,
lastValidBlockHeight: 3090,
},
withContext: true,
});
return await connection.getLatestBlockhash(commitment);
};
const recentBlockhash = async ({ const recentBlockhash = async ({
connection, connection,
commitment, commitment,
@ -145,7 +171,7 @@ const processTransaction = async ({
commitment: Commitment; commitment: Commitment;
err?: any; err?: any;
}) => { }) => {
const blockhash = (await recentBlockhash({connection})).blockhash; const blockhash = (await latestBlockhash({connection})).blockhash;
transaction.recentBlockhash = blockhash; transaction.recentBlockhash = blockhash;
transaction.sign(...signers); transaction.sign(...signers);
@ -211,4 +237,5 @@ export const helpers = {
airdrop, airdrop,
processTransaction, processTransaction,
recentBlockhash, recentBlockhash,
latestBlockhash,
}; };