feat: update getSignatureStatus

This commit is contained in:
Justin Starry 2020-03-23 23:01:12 +08:00 committed by Michael Vines
parent ac8660b2e9
commit 1c31e527e2
7 changed files with 152 additions and 26 deletions

11
web3.js/module.d.ts vendored
View File

@ -48,6 +48,11 @@ declare module '@solana/web3.js' {
export type SignatureStatusResult = SignatureSuccess | TransactionError;
export type SignatureStatus = {
slot: number;
status: SignatureSuccess | TransactionError;
};
export type BlockhashAndFeeCalculator = {
blockhash: Blockhash;
feeCalculator: FeeCalculator;
@ -183,7 +188,11 @@ declare module '@solana/web3.js' {
getSignatureStatus(
signature: TransactionSignature,
commitment?: Commitment,
): Promise<SignatureSuccess | TransactionError | null>;
): Promise<SignatureStatus | null>;
getSignatureStatusBatch(
signatures: Array<TransactionSignature>,
commitment?: Commitment,
): Promise<Array<SignatureStatus | null>>;
getTransactionCount(commitment?: Commitment): Promise<number>;
getTotalSupply(commitment?: Commitment): Promise<number>;
getVersion(): Promise<Version>;

View File

@ -63,6 +63,11 @@ declare module '@solana/web3.js' {
| SignatureSuccess
| TransactionError;
declare export type SignatureStatus = {
slot: number,
status: SignatureSuccess | TransactionError,
};
declare export type BlockhashAndFeeCalculator = {
blockhash: Blockhash,
feeCalculator: FeeCalculator,
@ -198,7 +203,11 @@ declare module '@solana/web3.js' {
getSignatureStatus(
signature: TransactionSignature,
commitment: ?Commitment,
): Promise<SignatureSuccess | TransactionError | null>;
): Promise<SignatureStatus | null>;
getSignatureStatusBatch(
signatures: Array<TransactionSignature>,
commitment: ?Commitment,
): Promise<Array<SignatureStatus | null>>;
getTransactionCount(commitment: ?Commitment): Promise<number>;
getTotalSupply(commitment: ?Commitment): Promise<number>;
getVersion(): Promise<Version>;

View File

@ -452,7 +452,15 @@ const GetVoteAccounts = jsonRpcResult(
* Expected JSON RPC response for the "getSignatureStatus" message
*/
const GetSignatureStatusRpcResult = jsonRpcResult(
struct.union(['null', SignatureStatusResult]),
struct.array([
struct.union([
'null',
struct({
slot: 'number',
status: SignatureStatusResult,
}),
]),
]),
);
/**
@ -660,6 +668,18 @@ export type TransactionError = {|
Err: Object,
|};
/**
* Signature status
*
* @typedef {Object} SignatureStatus
* @property {number} slot when the transaction was processed
* @property {SignatureStatus | TransactionError} status
*/
export type SignatureStatus = {
slot: number,
status: SignatureSuccess | TransactionError,
};
/**
* A connection to a fullnode JSON RPC endpoint
*/
@ -944,8 +964,20 @@ export class Connection {
async getSignatureStatus(
signature: TransactionSignature,
commitment: ?Commitment,
): Promise<SignatureSuccess | TransactionError | null> {
const args = this._argsWithCommitment([signature], commitment);
): Promise<SignatureStatus | null> {
const res = await this.getSignatureStatusBatch([signature], commitment);
assert(res.length === 1);
return res[0];
}
/**
* Fetch the current status of a signature
*/
async getSignatureStatusBatch(
signatures: Array<TransactionSignature>,
commitment: ?Commitment,
): Promise<Array<SignatureStatus | null>> {
const args = this._argsWithCommitment([signatures], commitment);
const unsafeRes = await this._rpcRequest('getSignatureStatus', args);
const res = GetSignatureStatusRpcResult(unsafeRes);
if (res.error) {

View File

@ -39,7 +39,7 @@ export async function sendAndConfirmRawTransaction(
}
}
if (status && 'Ok' in status) {
if (status && status.status && 'Ok' in status.status) {
return signature;
}

View File

@ -65,7 +65,7 @@ async function _sendAndConfirmTransaction(
await sleep((500 * DEFAULT_TICKS_PER_SLOT) / NUM_TICKS_PER_SECOND);
}
if (status && 'Ok' in status) {
if (status && 'Ok' in status.status) {
break;
}
if (--sendRetries <= 0) {
@ -77,7 +77,7 @@ async function _sendAndConfirmTransaction(
);
}
if (status && status.Err && !('AccountInUse' in status.Err)) {
if (status && status.status.Err && !('AccountInUse' in status.status.Err)) {
throw new Error(
`Transaction ${signature} failed (${JSON.stringify(status)})`,
);

View File

@ -100,13 +100,20 @@ test('get program accounts', async () => {
{
method: 'getSignatureStatus',
params: [
'3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
[
'3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
],
{commitment: 'recent'},
],
},
{
error: null,
result: {Ok: null},
result: [
{
slot: 0,
status: {Ok: null},
},
],
},
]);
let transaction = SystemProgram.assign({
@ -131,13 +138,20 @@ test('get program accounts', async () => {
{
method: 'getSignatureStatus',
params: [
'3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
[
'3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
],
{commitment: 'recent'},
],
},
{
error: null,
result: {Ok: null},
result: [
{
slot: 0,
status: {Ok: null},
},
],
},
]);
transaction = SystemProgram.assign({
@ -471,7 +485,7 @@ test('confirm transaction - error', async () => {
url,
{
method: 'getSignatureStatus',
params: [badTransactionSignature],
params: [[badTransactionSignature]],
},
errorResponse,
]);
@ -1011,18 +1025,64 @@ test('transaction', async () => {
{
method: 'getSignatureStatus',
params: [
'3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
[
'3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
],
{commitment: 'recent'},
],
},
{
error: null,
result: {Ok: null},
result: [
{
slot: 0,
status: {Ok: null},
},
],
},
]);
await expect(connection.getSignatureStatus(signature)).resolves.toEqual({
Ok: null,
});
const response = await connection.getSignatureStatus(signature);
if (response !== null) {
expect(typeof response.slot).toEqual('number');
expect(response.status).toEqual({Ok: null});
} else {
expect(response).not.toBeNull();
}
const unprocessedSignature =
'8WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk';
mockRpc.push([
url,
{
method: 'getSignatureStatus',
params: [
[
'3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
unprocessedSignature,
],
{commitment: 'recent'},
],
},
{
error: null,
result: [
{
slot: 0,
status: {Ok: null},
},
null,
],
},
]);
const responses = await connection.getSignatureStatusBatch([
signature,
unprocessedSignature,
]);
expect(responses.length).toEqual(2);
expect(responses[0]).toEqual(response);
expect(responses[1]).toBeNull();
mockRpc.push([
url,
@ -1120,9 +1180,14 @@ test('multi-instruction transaction', async () => {
expect(++i).toBeLessThan(10);
await sleep(500);
}
await expect(connection.getSignatureStatus(signature)).resolves.toEqual({
Ok: null,
});
const response = await connection.getSignatureStatus(signature);
if (response !== null) {
expect(typeof response.slot).toEqual('number');
expect(response.status).toEqual({Ok: null});
} else {
expect(response).not.toBeNull();
}
// accountFrom may have less than LAMPORTS_PER_SOL due to transaction fees
expect(await connection.getBalance(accountFrom.publicKey)).toBeGreaterThan(0);

View File

@ -148,18 +148,29 @@ test('transaction-payer', async () => {
{
method: 'getSignatureStatus',
params: [
'3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
[
'3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
],
{commitment: 'recent'},
],
},
{
error: null,
result: {Ok: null},
result: [
{
slot: 0,
status: {Ok: null},
},
],
},
]);
await expect(connection.getSignatureStatus(signature)).resolves.toEqual({
Ok: null,
});
const response = await connection.getSignatureStatus(signature);
if (response !== null) {
expect(typeof response.slot).toEqual('number');
expect(response.status).toEqual({Ok: null});
} else {
expect(response).not.toBeNull();
}
mockRpc.push([
url,