web3.js: deprecate getTotalSupply and getConfirmedSignaturesForAddress (#16534)

* feat: add method to return a confirmed block with signatures only

* fix: deprecate getConfirmedSignaturesForAddress

* fix: deprecate getTotalSupply
This commit is contained in:
Tyera Eulberg
2021-04-15 21:52:08 -06:00
committed by GitHub
parent 974e6dd2c1
commit 59268b8629
2 changed files with 259 additions and 35 deletions

View File

@ -583,6 +583,22 @@ export type ConfirmedBlock = {
blockTime: number | null; blockTime: number | null;
}; };
/**
* A ConfirmedBlock on the ledger with signatures only
*/
export type ConfirmedBlockSignatures = {
/** Blockhash of this block */
blockhash: Blockhash;
/** Blockhash of this block's parent */
previousBlockhash: Blockhash;
/** Slot index of this block's parent */
parentSlot: number;
/** Vector of signatures */
signatures: Array<string>;
/** The unix timestamp of when the block was processed */
blockTime: number | null;
};
/** /**
* A performance sample * A performance sample
*/ */
@ -915,13 +931,6 @@ const StakeActivationResult = pick({
inactive: number(), inactive: number(),
}); });
/**
* Expected JSON RPC response for the "getConfirmedSignaturesForAddress" message
*/
const GetConfirmedSignaturesForAddressRpcResult = jsonRpcResult(
array(string()),
);
/** /**
* Expected JSON RPC response for the "getConfirmedSignaturesForAddress2" message * Expected JSON RPC response for the "getConfirmedSignaturesForAddress2" message
*/ */
@ -1231,6 +1240,21 @@ const GetConfirmedBlockRpcResult = jsonRpcResult(
), ),
); );
/**
* Expected JSON RPC response for the "getConfirmedBlockSignatures" message
*/
const GetConfirmedBlockSignaturesRpcResult = jsonRpcResult(
nullable(
pick({
blockhash: string(),
previousBlockhash: string(),
parentSlot: number(),
signatures: array(string()),
blockTime: nullable(number()),
}),
),
);
/** /**
* Expected JSON RPC response for the "getConfirmedTransaction" message * Expected JSON RPC response for the "getConfirmedTransaction" message
*/ */
@ -2284,15 +2308,16 @@ export class Connection {
/** /**
* Fetch the current total currency supply of the cluster in lamports * Fetch the current total currency supply of the cluster in lamports
* @deprecated Deprecated since v1.2.8. Use `Connection.getSupply()` instead.
*/ */
async getTotalSupply(commitment?: Commitment): Promise<number> { async getTotalSupply(commitment?: Commitment): Promise<number> {
const args = this._buildArgs([], commitment); const args = this._buildArgs([], commitment);
const unsafeRes = await this._rpcRequest('getTotalSupply', args); const unsafeRes = await this._rpcRequest('getSupply', args);
const res = create(unsafeRes, jsonRpcResult(number())); const res = create(unsafeRes, GetSupplyRpcResult);
if ('error' in res) { if ('error' in res) {
throw new Error('failed to get total supply: ' + res.error.message); throw new Error('failed to get total supply: ' + res.error.message);
} }
return res.result; return res.result.value.total;
} }
/** /**
@ -2477,6 +2502,27 @@ export class Connection {
return result; return result;
} }
/**
* Fetch a list of Signatures from the cluster for a confirmed block, excluding rewards
*/
async getConfirmedBlockSignatures(
slot: number,
): Promise<ConfirmedBlockSignatures> {
const unsafeRes = await this._rpcRequest('getConfirmedBlock', [
slot,
{transactionDetails: 'signatures', rewards: false},
]);
const res = create(unsafeRes, GetConfirmedBlockSignaturesRpcResult);
if ('error' in res) {
throw new Error('failed to get confirmed block: ' + res.error.message);
}
const result = res.result;
if (!result) {
throw new Error('Confirmed block ' + slot + ' not found');
}
return result;
}
/** /**
* Fetch a transaction details for a confirmed transaction * Fetch a transaction details for a confirmed transaction
*/ */
@ -2544,6 +2590,7 @@ export class Connection {
/** /**
* Fetch a list of all the confirmed signatures for transactions involving an address * 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. * 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 address queried address
* @param startSlot start slot, inclusive * @param startSlot start slot, inclusive
@ -2554,17 +2601,59 @@ export class Connection {
startSlot: number, startSlot: number,
endSlot: number, endSlot: number,
): Promise<Array<TransactionSignature>> { ): Promise<Array<TransactionSignature>> {
const unsafeRes = await this._rpcRequest( let options: any = {};
'getConfirmedSignaturesForAddress',
[address.toBase58(), startSlot, endSlot], let firstAvailableBlock = await this.getFirstAvailableBlock();
); while (!('until' in options)) {
const res = create(unsafeRes, GetConfirmedSignaturesForAddressRpcResult); startSlot--;
if ('error' in res) { if (startSlot <= 0 || startSlot < firstAvailableBlock) {
throw new Error( break;
'failed to get confirmed signatures for address: ' + res.error.message, }
);
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);
} }
/** /**

View File

@ -492,9 +492,15 @@ describe('Connection', () => {
it('get total supply', async () => { it('get total supply', async () => {
await mockRpcResponse({ await mockRpcResponse({
method: 'getTotalSupply', method: 'getSupply',
params: [], params: [],
value: 1000000, value: {
total: 1000000,
circulating: 100000,
nonCirculating: 900000,
nonCirculatingAccounts: [new Account().publicKey.toBase58()],
},
withContext: true,
}); });
const count = await connection.getTotalSupply(); const count = await connection.getTotalSupply();
@ -597,9 +603,50 @@ describe('Connection', () => {
// getConfirmedSignaturesForAddress tests... // getConfirmedSignaturesForAddress tests...
await mockRpcResponse({ await mockRpcResponse({
method: 'getConfirmedSignaturesForAddress', method: 'getFirstAvailableBlock',
params: [address.toBase58(), slot, slot + 1], params: [],
value: [expectedSignature], 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( const confirmedSignatures = await connection.getConfirmedSignaturesForAddress(
@ -611,17 +658,17 @@ describe('Connection', () => {
const badSlot = Number.MAX_SAFE_INTEGER - 1; const badSlot = Number.MAX_SAFE_INTEGER - 1;
await mockRpcResponse({ await mockRpcResponse({
method: 'getConfirmedSignaturesForAddress', method: 'getConfirmedBlock',
params: [address.toBase58(), badSlot, badSlot + 1], params: [badSlot - 1, {transactionDetails: 'signatures', rewards: false}],
value: [], error: {message: 'Block not available for slot ' + badSlot},
}); });
expect(
const emptySignatures = await connection.getConfirmedSignaturesForAddress( connection.getConfirmedSignaturesForAddress(
address, address,
badSlot, badSlot,
badSlot + 1, badSlot + 1,
); ),
expect(emptySignatures).to.have.length(0); ).to.be.rejected;
// getConfirmedSignaturesForAddress2 tests... // getConfirmedSignaturesForAddress2 tests...
await mockRpcResponse({ await mockRpcResponse({
@ -1288,6 +1335,94 @@ describe('Connection', () => {
); );
}); });
it('get confirmed block signatures', async () => {
await mockRpcResponse({
method: 'getSlot',
params: [],
value: 1,
});
while ((await connection.getSlot()) <= 0) {
continue;
}
await mockRpcResponse({
method: 'getConfirmedBlock',
params: [
0,
{
transactionDetails: 'signatures',
rewards: false,
},
],
value: {
blockTime: 1614281964,
blockhash: 'H5nJ91eGag3B5ZSRHZ7zG5ZwXJ6ywCt2hyR8xCsV7xMo',
previousBlockhash: 'H5nJ91eGag3B5ZSRHZ7zG5ZwXJ6ywCt2hyR8xCsV7xMo',
parentSlot: 0,
signatures: [],
},
});
// Block 0 never has any transactions in test validator
const block0 = await connection.getConfirmedBlockSignatures(0);
const blockhash0 = block0.blockhash;
expect(block0.signatures).to.have.length(0);
expect(blockhash0).not.to.be.null;
expect(block0.previousBlockhash).not.to.be.null;
expect(block0.parentSlot).to.eq(0);
expect(block0).to.not.have.property('rewards');
await mockRpcResponse({
method: 'getConfirmedBlock',
params: [
1,
{
transactionDetails: 'signatures',
rewards: false,
},
],
value: {
blockTime: 1614281964,
blockhash: '57zQNBZBEiHsCZFqsaY6h176ioXy5MsSLmcvHkEyaLGy',
previousBlockhash: 'H5nJ91eGag3B5ZSRHZ7zG5ZwXJ6ywCt2hyR8xCsV7xMo',
parentSlot: 0,
signatures: [
'w2Zeq8YkpyB463DttvfzARD7k9ZxGEwbsEw4boEK7jDp3pfoxZbTdLFSsEPhzXhpCcjGi2kHtHFobgX49MMhbWt',
'4oCEqwGrMdBeMxpzuWiukCYqSfV4DsSKXSiVVCh1iJ6pS772X7y219JZP3mgqBz5PhsvprpKyhzChjYc3VSBQXzG',
],
},
});
// Find a block that has a transaction, usually Block 1
let x = 1;
while (x < 10) {
const block1 = await connection.getConfirmedBlockSignatures(x);
if (block1.signatures.length >= 1) {
expect(block1.previousBlockhash).to.eq(blockhash0);
expect(block1.blockhash).not.to.be.null;
expect(block1.parentSlot).to.eq(0);
expect(block1.signatures[0]).not.to.be.null;
expect(block1).to.not.have.property('rewards');
break;
}
x++;
}
await mockRpcResponse({
method: 'getConfirmedBlock',
params: [Number.MAX_SAFE_INTEGER],
error: {
message: `Block not available for slot ${Number.MAX_SAFE_INTEGER}`,
},
});
await expect(
connection.getConfirmedBlockSignatures(Number.MAX_SAFE_INTEGER),
).to.be.rejectedWith(
`Block not available for slot ${Number.MAX_SAFE_INTEGER}`,
);
});
it('get recent blockhash', async () => { it('get recent blockhash', async () => {
const commitments: Commitment[] = ['processed', 'confirmed', 'finalized']; const commitments: Commitment[] = ['processed', 'confirmed', 'finalized'];
for (const commitment of commitments) { for (const commitment of commitments) {