diff --git a/web3.js/module.d.ts b/web3.js/module.d.ts index bb755820b8..437ec38cf9 100644 --- a/web3.js/module.d.ts +++ b/web3.js/module.d.ts @@ -50,6 +50,11 @@ declare module '@solana/web3.js' { skipPreflight?: boolean; }; + export type ConfirmedSignaturesForAddress2Options = { + before?: TransactionSignature; + limit?: number; + }; + export type TokenAccountsFilter = | { mint: PublicKey; @@ -87,6 +92,13 @@ declare module '@solana/web3.js' { confirmations: number | null; }; + export type ConfirmedSignatureInfo = { + signature: string; + slot: number; + err: TransactionError | null; + memo: string | null; + }; + export type BlockhashAndFeeCalculator = { blockhash: Blockhash; feeCalculator: FeeCalculator; diff --git a/web3.js/module.flow.js b/web3.js/module.flow.js index 50aaed0119..8d2cc9b846 100644 --- a/web3.js/module.flow.js +++ b/web3.js/module.flow.js @@ -66,6 +66,11 @@ declare module '@solana/web3.js' { skipPreflight: ?boolean, }; + declare export type ConfirmedSignaturesForAddress2Options = { + before?: TransactionSignature, + limit?: number, + }; + declare export type TokenAccountsFilter = | { mint: PublicKey, @@ -103,6 +108,13 @@ declare module '@solana/web3.js' { confirmations: number | null, }; + declare export type ConfirmedSignatureInfo = { + signature: string, + slot: number, + err: TransactionError | null, + memo: string | null, + }; + declare export type BlockhashAndFeeCalculator = { blockhash: Blockhash, feeCalculator: FeeCalculator, diff --git a/web3.js/src/connection.js b/web3.js/src/connection.js index a4d2d294c4..b35f6d0c38 100644 --- a/web3.js/src/connection.js +++ b/web3.js/src/connection.js @@ -64,6 +64,20 @@ export type ConfirmOptions = { confirmations: ?number, }; +/** + * Options for getConfirmedSignaturesForAddress2 + * + * @typedef {Object} ConfirmedSignaturesForAddress2Options + * @property {TransactionSignature | undefined} before start searching backwards from this transaction signature. + * If not provided the search starts from the highest max confirmed block. + * @property {number | undefined} limit maximum transaction signatures to return (between 1 and 1,000, default: 1,000). + * + */ +export type ConfirmedSignaturesForAddress2Options = { + before?: TransactionSignature, + limit?: number, +}; + /** * RPC Response with extra contextual information * @@ -604,12 +618,27 @@ const GetAccountInfoAndContextRpcResult = jsonRpcResultAndContext( ); /** - * @private + * Expected JSON RPC response for the "getConfirmedSignaturesForAddress" message */ const GetConfirmedSignaturesForAddressRpcResult = jsonRpcResult( struct.array(['string']), ); +/** + * Expected JSON RPC response for the "getConfirmedSignaturesForAddress2" message + */ + +const GetConfirmedSignaturesForAddress2RpcResult = jsonRpcResult( + struct.array([ + struct({ + signature: 'string', + slot: 'number', + err: TransactionErrorResult, + memo: struct.union(['null', 'string']), + }), + ]), +); + /*** * Expected JSON RPC response for the "accountNotification" message */ @@ -1041,6 +1070,22 @@ export type SignatureStatus = { err: TransactionError | null, }; +/** + * A confirmed signature with its status + * + * @typedef {Object} ConfirmedSignatureInfo + * @property {string} signature the transaction signature + * @property {number} slot when the transaction was processed + * @property {TransactionError | null} err error, if any + * @property {string | null} memo memo associated with the transaction, if any + */ +export type ConfirmedSignatureInfo = { + signature: string, + slot: number, + err: TransactionError | null, + memo: string | null, +}; + /** * A connection to a fullnode JSON RPC endpoint */ @@ -1836,6 +1881,33 @@ export class Connection { return result.result; } + /** + * Returns confirmed signatures for transactions involving an + * address backwards in time from the provided signature or most recent confirmed block + * + * + * @param address queried address + * @param options + */ + async getConfirmedSignaturesForAddress2( + address: PublicKey, + options: ?ConfirmedSignaturesForAddress2Options, + ): Promise> { + const unsafeRes = await this._rpcRequest( + 'getConfirmedSignaturesForAddress2', + [address.toBase58(), options], + ); + const result = GetConfirmedSignaturesForAddress2RpcResult(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 */ diff --git a/web3.js/test/connection.test.js b/web3.js/test/connection.test.js index 714c1715f8..dc4854d880 100644 --- a/web3.js/test/connection.test.js +++ b/web3.js/test/connection.test.js @@ -756,6 +756,7 @@ test('get confirmed signatures for address', async () => { } } + // getConfirmedSignaturesForAddress tests... mockRpc.push([ url, { @@ -794,6 +795,38 @@ test('get confirmed signatures for address', async () => { badSlot + 1, ); expect(emptySignatures.length).toBe(0); + + // getConfirmedSignaturesForAddress2 tests... + mockRpc.push([ + url, + { + method: 'getConfirmedSignaturesForAddress2', + params: [address.toBase58(), {limit: 1}], + }, + { + error: null, + result: [ + { + signature: expectedSignature, + slot, + err: null, + memo: null, + }, + ], + }, + ]); + + const confirmedSignatures2 = await connection.getConfirmedSignaturesForAddress2( + address, + {limit: 1}, + ); + expect(confirmedSignatures2.length).toBe(1); + if (mockRpcEnabled) { + expect(confirmedSignatures2[0].signature).toBe(expectedSignature); + expect(confirmedSignatures2[0].slot).toBe(slot); + expect(confirmedSignatures2[0].err).toBeNull(); + expect(confirmedSignatures2[0].memo).toBeNull(); + } }); test('get confirmed transaction', async () => {