diff --git a/web3.js/src/connection.ts b/web3.js/src/connection.ts index 2e33c8e41..ed3d25131 100644 --- a/web3.js/src/connection.ts +++ b/web3.js/src/connection.ts @@ -931,13 +931,6 @@ const StakeActivationResult = pick({ inactive: number(), }); -/** - * Expected JSON RPC response for the "getConfirmedSignaturesForAddress" message - */ -const GetConfirmedSignaturesForAddressRpcResult = jsonRpcResult( - array(string()), -); - /** * Expected JSON RPC response for the "getConfirmedSignaturesForAddress2" message */ @@ -2596,6 +2589,7 @@ export class Connection { /** * 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. + * @deprecated Deprecated since v1.3. Use `Connection.getConfirmedSignaturesForAddress2()` instead. * * @param address queried address * @param startSlot start slot, inclusive @@ -2606,17 +2600,59 @@ export class Connection { startSlot: number, endSlot: number, ): Promise> { - const unsafeRes = await this._rpcRequest( - 'getConfirmedSignaturesForAddress', - [address.toBase58(), startSlot, endSlot], - ); - const res = create(unsafeRes, GetConfirmedSignaturesForAddressRpcResult); - if ('error' in res) { - throw new Error( - 'failed to get confirmed signatures for address: ' + res.error.message, - ); + let options: any = {}; + + let firstAvailableBlock = await this.getFirstAvailableBlock(); + while (!('until' in options)) { + startSlot--; + if (startSlot <= 0 || startSlot < firstAvailableBlock) { + break; + } + + try { + const block = await this.getConfirmedBlockSignatures(startSlot); + if (block.signatures.length > 0) { + options.until = block.signatures[ + block.signatures.length - 1 + ].toString(); + } + } catch (err) { + if (err.message.includes('skipped')) { + continue; + } else { + throw err; + } + } } - return res.result; + + let highestConfirmedRoot = await this.getSlot('finalized'); + while (!('before' in options)) { + endSlot++; + if (endSlot > highestConfirmedRoot) { + break; + } + + try { + const block = await this.getConfirmedBlockSignatures(endSlot); + if (block.signatures.length > 0) { + options.before = block.signatures[ + block.signatures.length - 1 + ].toString(); + } + } catch (err) { + if (err.message.includes('skipped')) { + continue; + } else { + throw err; + } + } + } + + const confirmedSignatureInfo = await this.getConfirmedSignaturesForAddress2( + address, + options, + ); + return confirmedSignatureInfo.map(info => info.signature); } /** diff --git a/web3.js/test/connection.test.ts b/web3.js/test/connection.test.ts index 1c9f0b1c3..45403e432 100644 --- a/web3.js/test/connection.test.ts +++ b/web3.js/test/connection.test.ts @@ -597,9 +597,50 @@ describe('Connection', () => { // getConfirmedSignaturesForAddress tests... await mockRpcResponse({ - method: 'getConfirmedSignaturesForAddress', - params: [address.toBase58(), slot, slot + 1], - value: [expectedSignature], + method: 'getFirstAvailableBlock', + params: [], + value: 0, + }); + const mockSignature = + '5SHZ9NwpnS9zYnauN7pnuborKf39zGMr11XpMC59VvRSeDJNcnYLecmdxXCVuBFPNQLdCBBjyZiNCL4KoHKr3tvz'; + await mockRpcResponse({ + method: 'getConfirmedBlock', + params: [slot, {transactionDetails: 'signatures', rewards: false}], + value: { + blockTime: 1614281964, + blockhash: 'H5nJ91eGag3B5ZSRHZ7zG5ZwXJ6ywCt2hyR8xCsV7xMo', + previousBlockhash: 'H5nJ91eGag3B5ZSRHZ7zG5ZwXJ6ywCt2hyR8xCsV7xMo', + parentSlot: 1, + signatures: [mockSignature], + }, + }); + await mockRpcResponse({ + method: 'getSlot', + params: [], + value: 123, + }); + await mockRpcResponse({ + method: 'getConfirmedBlock', + params: [slot + 2, {transactionDetails: 'signatures', rewards: false}], + value: { + blockTime: 1614281964, + blockhash: 'H5nJ91eGag3B5ZSRHZ7zG5ZwXJ6ywCt2hyR8xCsV7xMo', + previousBlockhash: 'H5nJ91eGag3B5ZSRHZ7zG5ZwXJ6ywCt2hyR8xCsV7xMo', + parentSlot: 1, + signatures: [mockSignature], + }, + }); + await mockRpcResponse({ + method: 'getConfirmedSignaturesForAddress2', + params: [address.toBase58(), {before: mockSignature}], + value: [ + { + signature: expectedSignature, + slot, + err: null, + memo: null, + }, + ], }); const confirmedSignatures = await connection.getConfirmedSignaturesForAddress( @@ -611,17 +652,17 @@ describe('Connection', () => { const badSlot = Number.MAX_SAFE_INTEGER - 1; await mockRpcResponse({ - method: 'getConfirmedSignaturesForAddress', - params: [address.toBase58(), badSlot, badSlot + 1], - value: [], + method: 'getConfirmedBlock', + params: [badSlot - 1, {transactionDetails: 'signatures', rewards: false}], + error: {message: 'Block not available for slot ' + badSlot}, }); - - const emptySignatures = await connection.getConfirmedSignaturesForAddress( - address, - badSlot, - badSlot + 1, - ); - expect(emptySignatures).to.have.length(0); + expect( + connection.getConfirmedSignaturesForAddress( + address, + badSlot, + badSlot + 1, + ), + ).to.be.rejected; // getConfirmedSignaturesForAddress2 tests... await mockRpcResponse({