feat: add getConfirmedTransaction and getConfirmedSignaturesForAddress
This commit is contained in:
committed by
Michael Vines
parent
7f182d22cd
commit
ae53742e1a
19
web3.js/module.d.ts
vendored
19
web3.js/module.d.ts
vendored
@ -98,6 +98,17 @@ declare module '@solana/web3.js' {
|
|||||||
}>;
|
}>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ConfirmedTransaction = {
|
||||||
|
slot: number;
|
||||||
|
transaction: Transaction;
|
||||||
|
meta: {
|
||||||
|
fee: number;
|
||||||
|
preBalances: Array<number>;
|
||||||
|
postBalances: Array<number>;
|
||||||
|
err: TransactionError | null;
|
||||||
|
} | null;
|
||||||
|
};
|
||||||
|
|
||||||
export type KeyedAccountInfo = {
|
export type KeyedAccountInfo = {
|
||||||
accountId: PublicKey;
|
accountId: PublicKey;
|
||||||
accountInfo: AccountInfo;
|
accountInfo: AccountInfo;
|
||||||
@ -184,6 +195,14 @@ declare module '@solana/web3.js' {
|
|||||||
getBalance(publicKey: PublicKey, commitment?: Commitment): Promise<number>;
|
getBalance(publicKey: PublicKey, commitment?: Commitment): Promise<number>;
|
||||||
getClusterNodes(): Promise<Array<ContactInfo>>;
|
getClusterNodes(): Promise<Array<ContactInfo>>;
|
||||||
getConfirmedBlock(slot: number): Promise<ConfirmedBlock>;
|
getConfirmedBlock(slot: number): Promise<ConfirmedBlock>;
|
||||||
|
getConfirmedTransaction(
|
||||||
|
signature: TransactionSignature,
|
||||||
|
): Promise<ConfirmedTransaction | null>;
|
||||||
|
getConfirmedSignaturesForAddress(
|
||||||
|
address: PublicKey,
|
||||||
|
startSlot: number,
|
||||||
|
endSlot: number,
|
||||||
|
): Promise<Array<TransactionSignature>>;
|
||||||
getVoteAccounts(commitment?: Commitment): Promise<VoteAccountStatus>;
|
getVoteAccounts(commitment?: Commitment): Promise<VoteAccountStatus>;
|
||||||
confirmTransactionAndContext(
|
confirmTransactionAndContext(
|
||||||
signature: TransactionSignature,
|
signature: TransactionSignature,
|
||||||
|
@ -111,6 +111,17 @@ declare module '@solana/web3.js' {
|
|||||||
}>,
|
}>,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
declare export type ConfirmedTransaction = {
|
||||||
|
slot: number,
|
||||||
|
transaction: Transaction,
|
||||||
|
meta: {
|
||||||
|
fee: number,
|
||||||
|
preBalances: Array<number>,
|
||||||
|
postBalances: Array<number>,
|
||||||
|
err: TransactionError | null,
|
||||||
|
} | null,
|
||||||
|
};
|
||||||
|
|
||||||
declare export type KeyedAccountInfo = {
|
declare export type KeyedAccountInfo = {
|
||||||
accountId: PublicKey,
|
accountId: PublicKey,
|
||||||
accountInfo: AccountInfo,
|
accountInfo: AccountInfo,
|
||||||
@ -197,6 +208,14 @@ declare module '@solana/web3.js' {
|
|||||||
getBalance(publicKey: PublicKey, commitment: ?Commitment): Promise<number>;
|
getBalance(publicKey: PublicKey, commitment: ?Commitment): Promise<number>;
|
||||||
getClusterNodes(): Promise<Array<ContactInfo>>;
|
getClusterNodes(): Promise<Array<ContactInfo>>;
|
||||||
getConfirmedBlock(slot: number): Promise<ConfirmedBlock>;
|
getConfirmedBlock(slot: number): Promise<ConfirmedBlock>;
|
||||||
|
getConfirmedTransaction(
|
||||||
|
signature: TransactionSignature,
|
||||||
|
): Promise<ConfirmedTransaction | null>;
|
||||||
|
getConfirmedSignaturesForAddress(
|
||||||
|
address: PublicKey,
|
||||||
|
startSlot: number,
|
||||||
|
endSlot: number,
|
||||||
|
): Promise<Array<TransactionSignature>>;
|
||||||
getVoteAccounts(commitment: ?Commitment): Promise<VoteAccountStatus>;
|
getVoteAccounts(commitment: ?Commitment): Promise<VoteAccountStatus>;
|
||||||
confirmTransactionAndContext(
|
confirmTransactionAndContext(
|
||||||
signature: TransactionSignature,
|
signature: TransactionSignature,
|
||||||
|
@ -233,6 +233,25 @@ const Version = struct({
|
|||||||
'solana-core': 'string',
|
'solana-core': 'string',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A confirmed transaction on the ledger
|
||||||
|
*
|
||||||
|
* @typedef {Object} ConfirmedTransaction
|
||||||
|
* @property {number} slot The slot during which the transaction was processed
|
||||||
|
* @property {Transaction} transaction The details of the transaction
|
||||||
|
* @property {object} meta Slot index of this block's parent
|
||||||
|
*/
|
||||||
|
type ConfirmedTransaction = {
|
||||||
|
slot: number,
|
||||||
|
transaction: Transaction,
|
||||||
|
meta: {
|
||||||
|
fee: number,
|
||||||
|
err: TransactionError | null,
|
||||||
|
preBalances: Array<number>,
|
||||||
|
postBalances: Array<number>,
|
||||||
|
} | null,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A ConfirmedBlock on the ledger
|
* A ConfirmedBlock on the ledger
|
||||||
*
|
*
|
||||||
@ -357,6 +376,13 @@ const GetAccountInfoAndContextRpcResult = jsonRpcResultAndContext(
|
|||||||
struct.union(['null', AccountInfoResult]),
|
struct.union(['null', AccountInfoResult]),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
const GetConfirmedSignaturesForAddressRpcResult = jsonRpcResult(
|
||||||
|
struct.array(['string']),
|
||||||
|
);
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Expected JSON RPC response for the "accountNotification" message
|
* Expected JSON RPC response for the "accountNotification" message
|
||||||
*/
|
*/
|
||||||
@ -519,6 +545,45 @@ const GetTotalSupplyRpcResult = jsonRpcResult('number');
|
|||||||
*/
|
*/
|
||||||
const GetMinimumBalanceForRentExemptionRpcResult = jsonRpcResult('number');
|
const GetMinimumBalanceForRentExemptionRpcResult = jsonRpcResult('number');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
const ConfirmedTransactionResult = struct({
|
||||||
|
signatures: struct.array(['string']),
|
||||||
|
message: struct({
|
||||||
|
accountKeys: struct.array(['string']),
|
||||||
|
header: struct({
|
||||||
|
numRequiredSignatures: 'number',
|
||||||
|
numReadonlySignedAccounts: 'number',
|
||||||
|
numReadonlyUnsignedAccounts: 'number',
|
||||||
|
}),
|
||||||
|
instructions: struct.array([
|
||||||
|
struct.union([
|
||||||
|
struct.array(['number']),
|
||||||
|
struct({
|
||||||
|
accounts: struct.array(['number']),
|
||||||
|
data: 'string',
|
||||||
|
programIdIndex: 'number',
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
recentBlockhash: 'string',
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
const ConfirmedTransactionMetaResult = struct.union([
|
||||||
|
'null',
|
||||||
|
struct.pick({
|
||||||
|
err: TransactionErrorResult,
|
||||||
|
fee: 'number',
|
||||||
|
preBalances: struct.array(['number']),
|
||||||
|
postBalances: struct.array(['number']),
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expected JSON RPC response for the "getConfirmedBlock" message
|
* Expected JSON RPC response for the "getConfirmedBlock" message
|
||||||
*/
|
*/
|
||||||
@ -531,37 +596,8 @@ export const GetConfirmedBlockRpcResult = jsonRpcResult(
|
|||||||
parentSlot: 'number',
|
parentSlot: 'number',
|
||||||
transactions: struct.array([
|
transactions: struct.array([
|
||||||
struct({
|
struct({
|
||||||
transaction: struct({
|
transaction: ConfirmedTransactionResult,
|
||||||
signatures: struct.array(['string']),
|
meta: ConfirmedTransactionMetaResult,
|
||||||
message: struct({
|
|
||||||
accountKeys: struct.array(['string']),
|
|
||||||
header: struct({
|
|
||||||
numRequiredSignatures: 'number',
|
|
||||||
numReadonlySignedAccounts: 'number',
|
|
||||||
numReadonlyUnsignedAccounts: 'number',
|
|
||||||
}),
|
|
||||||
instructions: struct.array([
|
|
||||||
struct.union([
|
|
||||||
struct.array(['number']),
|
|
||||||
struct({
|
|
||||||
accounts: struct.array(['number']),
|
|
||||||
data: 'string',
|
|
||||||
programIdIndex: 'number',
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
]),
|
|
||||||
recentBlockhash: 'string',
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
meta: struct.union([
|
|
||||||
'null',
|
|
||||||
struct.pick({
|
|
||||||
err: TransactionErrorResult,
|
|
||||||
fee: 'number',
|
|
||||||
preBalances: struct.array(['number']),
|
|
||||||
postBalances: struct.array(['number']),
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
rewards: struct.union([
|
rewards: struct.union([
|
||||||
@ -577,6 +613,20 @@ export const GetConfirmedBlockRpcResult = jsonRpcResult(
|
|||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expected JSON RPC response for the "getConfirmedTransaction" message
|
||||||
|
*/
|
||||||
|
const GetConfirmedTransactionRpcResult = jsonRpcResult(
|
||||||
|
struct.union([
|
||||||
|
'null',
|
||||||
|
struct({
|
||||||
|
slot: 'number',
|
||||||
|
transaction: ConfirmedTransactionResult,
|
||||||
|
meta: ConfirmedTransactionMetaResult,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expected JSON RPC response for the "getRecentBlockhash" message
|
* Expected JSON RPC response for the "getRecentBlockhash" message
|
||||||
*/
|
*/
|
||||||
@ -1266,6 +1316,59 @@ export class Connection {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch a transaction details for a confirmed transaction
|
||||||
|
*/
|
||||||
|
async getConfirmedTransaction(
|
||||||
|
signature: TransactionSignature,
|
||||||
|
): Promise<ConfirmedTransaction | null> {
|
||||||
|
const unsafeRes = await this._rpcRequest('getConfirmedTransaction', [
|
||||||
|
signature,
|
||||||
|
]);
|
||||||
|
const {result, error} = GetConfirmedTransactionRpcResult(unsafeRes);
|
||||||
|
if (error) {
|
||||||
|
throw new Error('failed to get confirmed transaction: ' + error.message);
|
||||||
|
}
|
||||||
|
assert(typeof result !== 'undefined');
|
||||||
|
if (result === null) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
slot: result.slot,
|
||||||
|
transaction: Transaction.fromRpcResult(result.transaction),
|
||||||
|
meta: result.meta,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch a list of all the confirmed signatures for transactions involving an address
|
||||||
|
* within a specified slot range. Max range allowed is 10,000 slots.
|
||||||
|
*
|
||||||
|
* @param address queried address
|
||||||
|
* @param startSlot start slot, inclusive
|
||||||
|
* @param endSlot end slot, inclusive
|
||||||
|
*/
|
||||||
|
async getConfirmedSignaturesForAddress(
|
||||||
|
address: PublicKey,
|
||||||
|
startSlot: number,
|
||||||
|
endSlot: number,
|
||||||
|
): Promise<Array<TransactionSignature>> {
|
||||||
|
const unsafeRes = await this._rpcRequest(
|
||||||
|
'getConfirmedSignaturesForAddress',
|
||||||
|
[address.toBase58(), startSlot, endSlot],
|
||||||
|
);
|
||||||
|
const result = GetConfirmedSignaturesForAddressRpcResult(unsafeRes);
|
||||||
|
if (result.error) {
|
||||||
|
throw new Error(
|
||||||
|
'failed to get confirmed signatures for address: ' +
|
||||||
|
result.error.message,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
assert(typeof result.result !== 'undefined');
|
||||||
|
return result.result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch the contents of a Nonce account from the cluster, return with context
|
* Fetch the contents of a Nonce account from the cluster, return with context
|
||||||
*/
|
*/
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
// @flow
|
// @flow
|
||||||
|
import bs58 from 'bs58';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Account,
|
Account,
|
||||||
Connection,
|
Connection,
|
||||||
SystemProgram,
|
SystemProgram,
|
||||||
sendAndConfirmTransaction,
|
sendAndConfirmTransaction,
|
||||||
LAMPORTS_PER_SOL,
|
LAMPORTS_PER_SOL,
|
||||||
|
PublicKey,
|
||||||
} from '../src';
|
} from '../src';
|
||||||
import {DEFAULT_TICKS_PER_SLOT, NUM_TICKS_PER_SECOND} from '../src/timing';
|
import {DEFAULT_TICKS_PER_SLOT, NUM_TICKS_PER_SECOND} from '../src/timing';
|
||||||
import {mockRpc, mockRpcEnabled} from './__mocks__/node-fetch';
|
import {mockRpc, mockRpcEnabled} from './__mocks__/node-fetch';
|
||||||
@ -570,6 +573,331 @@ test('get minimum balance for rent exemption', async () => {
|
|||||||
expect(count).toBeGreaterThanOrEqual(0);
|
expect(count).toBeGreaterThanOrEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('get confirmed signatures for address', async () => {
|
||||||
|
const connection = new Connection(url);
|
||||||
|
|
||||||
|
mockRpc.push([
|
||||||
|
url,
|
||||||
|
{
|
||||||
|
method: 'getSlot',
|
||||||
|
params: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
error: null,
|
||||||
|
result: 1,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
while ((await connection.getSlot()) <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
mockRpc.push([
|
||||||
|
url,
|
||||||
|
{
|
||||||
|
method: 'getConfirmedBlock',
|
||||||
|
params: [1],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
error: null,
|
||||||
|
result: {
|
||||||
|
blockhash: '57zQNBZBEiHsCZFqsaY6h176ioXy5MsSLmcvHkEyaLGy',
|
||||||
|
previousBlockhash: 'H5nJ91eGag3B5ZSRHZ7zG5ZwXJ6ywCt2hyR8xCsV7xMo',
|
||||||
|
parentSlot: 0,
|
||||||
|
transactions: [
|
||||||
|
{
|
||||||
|
meta: {
|
||||||
|
fee: 10000,
|
||||||
|
postBalances: [499260347380, 15298080, 1, 1, 1],
|
||||||
|
preBalances: [499260357380, 15298080, 1, 1, 1],
|
||||||
|
status: {Ok: null},
|
||||||
|
err: null,
|
||||||
|
},
|
||||||
|
transaction: {
|
||||||
|
message: {
|
||||||
|
accountKeys: [
|
||||||
|
'va12u4o9DipLEB2z4fuoHszroq1U9NcAB9aooFDPJSf',
|
||||||
|
'57zQNBZBEiHsCZFqsaY6h176ioXy5MsSLmcvHkEyaLGy',
|
||||||
|
'SysvarS1otHashes111111111111111111111111111',
|
||||||
|
'SysvarC1ock11111111111111111111111111111111',
|
||||||
|
'Vote111111111111111111111111111111111111111',
|
||||||
|
],
|
||||||
|
header: {
|
||||||
|
numReadonlySignedAccounts: 0,
|
||||||
|
numReadonlyUnsignedAccounts: 3,
|
||||||
|
numRequiredSignatures: 2,
|
||||||
|
},
|
||||||
|
instructions: [
|
||||||
|
{
|
||||||
|
accounts: [1, 2, 3],
|
||||||
|
data:
|
||||||
|
'37u9WtQpcm6ULa3VtWDFAWoQc1hUvybPrA3dtx99tgHvvcE7pKRZjuGmn7VX2tC3JmYDYGG7',
|
||||||
|
programIdIndex: 4,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
recentBlockhash: 'GeyAFFRY3WGpmam2hbgrKw4rbU2RKzfVLm5QLSeZwTZE',
|
||||||
|
},
|
||||||
|
signatures: [
|
||||||
|
'w2Zeq8YkpyB463DttvfzARD7k9ZxGEwbsEw4boEK7jDp3pfoxZbTdLFSsEPhzXhpCcjGi2kHtHFobgX49MMhbWt',
|
||||||
|
'4oCEqwGrMdBeMxpzuWiukCYqSfV4DsSKXSiVVCh1iJ6pS772X7y219JZP3mgqBz5PhsvprpKyhzChjYc3VSBQXzG',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Find a block that has a transaction, usually Block 1
|
||||||
|
let slot = 0;
|
||||||
|
let address: ?PublicKey;
|
||||||
|
let expectedSignature: ?string;
|
||||||
|
while (!address || !expectedSignature) {
|
||||||
|
slot++;
|
||||||
|
const block = await connection.getConfirmedBlock(slot);
|
||||||
|
if (block.transactions.length > 0) {
|
||||||
|
const {
|
||||||
|
signature,
|
||||||
|
publicKey,
|
||||||
|
} = block.transactions[0].transaction.signatures[0];
|
||||||
|
if (signature) {
|
||||||
|
address = publicKey;
|
||||||
|
expectedSignature = bs58.encode(signature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mockRpc.push([
|
||||||
|
url,
|
||||||
|
{
|
||||||
|
method: 'getConfirmedSignaturesForAddress',
|
||||||
|
params: [address.toBase58(), slot, slot + 1],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
error: null,
|
||||||
|
result: [expectedSignature],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const confirmedSignatures = await connection.getConfirmedSignaturesForAddress(
|
||||||
|
address,
|
||||||
|
slot,
|
||||||
|
slot + 1,
|
||||||
|
);
|
||||||
|
expect(confirmedSignatures.includes(expectedSignature)).toBe(true);
|
||||||
|
|
||||||
|
const badSlot = Number.MAX_SAFE_INTEGER - 1;
|
||||||
|
mockRpc.push([
|
||||||
|
url,
|
||||||
|
{
|
||||||
|
method: 'getConfirmedSignaturesForAddress',
|
||||||
|
params: [address.toBase58(), badSlot, badSlot + 1],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
error: null,
|
||||||
|
result: [],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const emptySignatures = await connection.getConfirmedSignaturesForAddress(
|
||||||
|
address,
|
||||||
|
badSlot,
|
||||||
|
badSlot + 1,
|
||||||
|
);
|
||||||
|
expect(emptySignatures.length).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('get confirmed transaction', async () => {
|
||||||
|
const connection = new Connection(url);
|
||||||
|
|
||||||
|
mockRpc.push([
|
||||||
|
url,
|
||||||
|
{
|
||||||
|
method: 'getSlot',
|
||||||
|
params: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
error: null,
|
||||||
|
result: 1,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
while ((await connection.getSlot()) <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
mockRpc.push([
|
||||||
|
url,
|
||||||
|
{
|
||||||
|
method: 'getConfirmedBlock',
|
||||||
|
params: [1],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
error: null,
|
||||||
|
result: {
|
||||||
|
blockhash: '57zQNBZBEiHsCZFqsaY6h176ioXy5MsSLmcvHkEyaLGy',
|
||||||
|
previousBlockhash: 'H5nJ91eGag3B5ZSRHZ7zG5ZwXJ6ywCt2hyR8xCsV7xMo',
|
||||||
|
parentSlot: 0,
|
||||||
|
transactions: [
|
||||||
|
{
|
||||||
|
meta: {
|
||||||
|
fee: 10000,
|
||||||
|
postBalances: [499260347380, 15298080, 1, 1, 1],
|
||||||
|
preBalances: [499260357380, 15298080, 1, 1, 1],
|
||||||
|
status: {Ok: null},
|
||||||
|
err: null,
|
||||||
|
},
|
||||||
|
transaction: {
|
||||||
|
message: {
|
||||||
|
accountKeys: [
|
||||||
|
'va12u4o9DipLEB2z4fuoHszroq1U9NcAB9aooFDPJSf',
|
||||||
|
'57zQNBZBEiHsCZFqsaY6h176ioXy5MsSLmcvHkEyaLGy',
|
||||||
|
'SysvarS1otHashes111111111111111111111111111',
|
||||||
|
'SysvarC1ock11111111111111111111111111111111',
|
||||||
|
'Vote111111111111111111111111111111111111111',
|
||||||
|
],
|
||||||
|
header: {
|
||||||
|
numReadonlySignedAccounts: 0,
|
||||||
|
numReadonlyUnsignedAccounts: 3,
|
||||||
|
numRequiredSignatures: 2,
|
||||||
|
},
|
||||||
|
instructions: [
|
||||||
|
{
|
||||||
|
accounts: [1, 2, 3],
|
||||||
|
data:
|
||||||
|
'37u9WtQpcm6ULa3VtWDFAWoQc1hUvybPrA3dtx99tgHvvcE7pKRZjuGmn7VX2tC3JmYDYGG7',
|
||||||
|
programIdIndex: 4,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
recentBlockhash: 'GeyAFFRY3WGpmam2hbgrKw4rbU2RKzfVLm5QLSeZwTZE',
|
||||||
|
},
|
||||||
|
signatures: [
|
||||||
|
'w2Zeq8YkpyB463DttvfzARD7k9ZxGEwbsEw4boEK7jDp3pfoxZbTdLFSsEPhzXhpCcjGi2kHtHFobgX49MMhbWt',
|
||||||
|
'4oCEqwGrMdBeMxpzuWiukCYqSfV4DsSKXSiVVCh1iJ6pS772X7y219JZP3mgqBz5PhsvprpKyhzChjYc3VSBQXzG',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Find a block that has a transaction, usually Block 1
|
||||||
|
let slot = 0;
|
||||||
|
let confirmedTransaction: ?string;
|
||||||
|
while (!confirmedTransaction) {
|
||||||
|
slot++;
|
||||||
|
const block = await connection.getConfirmedBlock(slot);
|
||||||
|
for (const tx of block.transactions) {
|
||||||
|
if (tx.transaction.signature) {
|
||||||
|
confirmedTransaction = bs58.encode(tx.transaction.signature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mockRpc.push([
|
||||||
|
url,
|
||||||
|
{
|
||||||
|
method: 'getConfirmedTransaction',
|
||||||
|
params: [confirmedTransaction],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
error: null,
|
||||||
|
result: {
|
||||||
|
slot,
|
||||||
|
transaction: {
|
||||||
|
message: {
|
||||||
|
accountKeys: [
|
||||||
|
'va12u4o9DipLEB2z4fuoHszroq1U9NcAB9aooFDPJSf',
|
||||||
|
'57zQNBZBEiHsCZFqsaY6h176ioXy5MsSLmcvHkEyaLGy',
|
||||||
|
'SysvarS1otHashes111111111111111111111111111',
|
||||||
|
'SysvarC1ock11111111111111111111111111111111',
|
||||||
|
'Vote111111111111111111111111111111111111111',
|
||||||
|
],
|
||||||
|
header: {
|
||||||
|
numReadonlySignedAccounts: 0,
|
||||||
|
numReadonlyUnsignedAccounts: 3,
|
||||||
|
numRequiredSignatures: 2,
|
||||||
|
},
|
||||||
|
instructions: [
|
||||||
|
{
|
||||||
|
accounts: [1, 2, 3],
|
||||||
|
data:
|
||||||
|
'37u9WtQpcm6ULa3VtWDFAWoQc1hUvybPrA3dtx99tgHvvcE7pKRZjuGmn7VX2tC3JmYDYGG7',
|
||||||
|
programIdIndex: 4,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
recentBlockhash: 'GeyAFFRY3WGpmam2hbgrKw4rbU2RKzfVLm5QLSeZwTZE',
|
||||||
|
},
|
||||||
|
signatures: [
|
||||||
|
'w2Zeq8YkpyB463DttvfzARD7k9ZxGEwbsEw4boEK7jDp3pfoxZbTdLFSsEPhzXhpCcjGi2kHtHFobgX49MMhbWt',
|
||||||
|
'4oCEqwGrMdBeMxpzuWiukCYqSfV4DsSKXSiVVCh1iJ6pS772X7y219JZP3mgqBz5PhsvprpKyhzChjYc3VSBQXzG',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
fee: 10000,
|
||||||
|
postBalances: [499260347380, 15298080, 1, 1, 1],
|
||||||
|
preBalances: [499260357380, 15298080, 1, 1, 1],
|
||||||
|
status: {Ok: null},
|
||||||
|
err: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const result = await connection.getConfirmedTransaction(confirmedTransaction);
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
expect(result).toBeDefined();
|
||||||
|
expect(result).not.toBeNull();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.transaction.signature === null) {
|
||||||
|
expect(result.transaction.signature).not.toBeNull();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const resultSignature = bs58.encode(result.transaction.signature);
|
||||||
|
expect(resultSignature).toEqual(confirmedTransaction);
|
||||||
|
|
||||||
|
const newAddress = new Account().publicKey;
|
||||||
|
mockRpc.push([
|
||||||
|
url,
|
||||||
|
{
|
||||||
|
method: 'requestAirdrop',
|
||||||
|
params: [newAddress.toBase58(), 1, {commitment: 'recent'}],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
error: null,
|
||||||
|
result:
|
||||||
|
'1WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const recentSignature = await connection.requestAirdrop(
|
||||||
|
newAddress,
|
||||||
|
1,
|
||||||
|
'recent',
|
||||||
|
);
|
||||||
|
mockRpc.push([
|
||||||
|
url,
|
||||||
|
{
|
||||||
|
method: 'getConfirmedTransaction',
|
||||||
|
params: [recentSignature],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
error: null,
|
||||||
|
result: null,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const nullResponse = await connection.getConfirmedTransaction(
|
||||||
|
recentSignature,
|
||||||
|
);
|
||||||
|
expect(nullResponse).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
test('get confirmed block', async () => {
|
test('get confirmed block', async () => {
|
||||||
const connection = new Connection(url);
|
const connection = new Connection(url);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user