feat: add getLargestAccounts rpc api
This commit is contained in:
committed by
Michael Vines
parent
9c677c7d3d
commit
1b8fe71230
15
web3.js/module.d.ts
vendored
15
web3.js/module.d.ts
vendored
@ -48,6 +48,13 @@ declare module '@solana/web3.js' {
|
|||||||
|
|
||||||
export type Commitment = 'max' | 'recent' | 'root' | 'single';
|
export type Commitment = 'max' | 'recent' | 'root' | 'single';
|
||||||
|
|
||||||
|
export type LargestAccountsFilter = 'circulating' | 'nonCirculating';
|
||||||
|
|
||||||
|
export type GetLargestAccountsConfig = {
|
||||||
|
commitment?: Commitment;
|
||||||
|
filter?: LargestAccountsFilter;
|
||||||
|
};
|
||||||
|
|
||||||
export type SignatureStatusConfig = {
|
export type SignatureStatusConfig = {
|
||||||
searchTransactionHistory: boolean;
|
searchTransactionHistory: boolean;
|
||||||
};
|
};
|
||||||
@ -180,6 +187,11 @@ declare module '@solana/web3.js' {
|
|||||||
nonCirculatingAccounts: Array<PublicKey>;
|
nonCirculatingAccounts: Array<PublicKey>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type AccountBalancePair = {
|
||||||
|
address: PublicKey;
|
||||||
|
lamports: number;
|
||||||
|
};
|
||||||
|
|
||||||
export type VoteAccountStatus = {
|
export type VoteAccountStatus = {
|
||||||
current: Array<VoteAccountInfo>;
|
current: Array<VoteAccountInfo>;
|
||||||
delinquent: Array<VoteAccountInfo>;
|
delinquent: Array<VoteAccountInfo>;
|
||||||
@ -208,6 +220,9 @@ declare module '@solana/web3.js' {
|
|||||||
getBlockTime(slot: number): Promise<number | null>;
|
getBlockTime(slot: number): Promise<number | null>;
|
||||||
getMinimumLedgerSlot(): Promise<number>;
|
getMinimumLedgerSlot(): Promise<number>;
|
||||||
getSupply(commitment?: Commitment): Promise<RpcResponseAndContext<Supply>>;
|
getSupply(commitment?: Commitment): Promise<RpcResponseAndContext<Supply>>;
|
||||||
|
getLargestAccounts(
|
||||||
|
config?: GetLargestAccountsConfig,
|
||||||
|
): Promise<RpcResponseAndContext<Array<AccountBalancePair>>>;
|
||||||
getClusterNodes(): Promise<Array<ContactInfo>>;
|
getClusterNodes(): Promise<Array<ContactInfo>>;
|
||||||
getConfirmedBlock(slot: number): Promise<ConfirmedBlock>;
|
getConfirmedBlock(slot: number): Promise<ConfirmedBlock>;
|
||||||
getConfirmedTransaction(
|
getConfirmedTransaction(
|
||||||
|
@ -61,6 +61,13 @@ declare module '@solana/web3.js' {
|
|||||||
|
|
||||||
declare export type Commitment = 'max' | 'recent' | 'root' | 'single';
|
declare export type Commitment = 'max' | 'recent' | 'root' | 'single';
|
||||||
|
|
||||||
|
declare export type LargestAccountsFilter = 'circulating' | 'nonCirculating';
|
||||||
|
|
||||||
|
declare export type GetLargestAccountsConfig = {
|
||||||
|
commitment: ?Commitment,
|
||||||
|
filter: ?LargestAccountsFilter,
|
||||||
|
};
|
||||||
|
|
||||||
declare export type SignatureStatusConfig = {
|
declare export type SignatureStatusConfig = {
|
||||||
searchTransactionHistory: boolean,
|
searchTransactionHistory: boolean,
|
||||||
};
|
};
|
||||||
@ -193,6 +200,11 @@ declare module '@solana/web3.js' {
|
|||||||
nonCirculatingAccounts: Array<PublicKey>,
|
nonCirculatingAccounts: Array<PublicKey>,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
declare export type AccountBalancePair = {
|
||||||
|
address: PublicKey,
|
||||||
|
lamports: number,
|
||||||
|
};
|
||||||
|
|
||||||
declare export type VoteAccountStatus = {
|
declare export type VoteAccountStatus = {
|
||||||
current: Array<VoteAccountInfo>,
|
current: Array<VoteAccountInfo>,
|
||||||
delinquent: Array<VoteAccountInfo>,
|
delinquent: Array<VoteAccountInfo>,
|
||||||
@ -221,6 +233,9 @@ declare module '@solana/web3.js' {
|
|||||||
getBlockTime(slot: number): Promise<number | null>;
|
getBlockTime(slot: number): Promise<number | null>;
|
||||||
getMinimumLedgerSlot(): Promise<number>;
|
getMinimumLedgerSlot(): Promise<number>;
|
||||||
getSupply(commitment: ?Commitment): Promise<RpcResponseAndContext<Supply>>;
|
getSupply(commitment: ?Commitment): Promise<RpcResponseAndContext<Supply>>;
|
||||||
|
getLargestAccounts(
|
||||||
|
config: ?GetLargestAccountsConfig,
|
||||||
|
): Promise<RpcResponseAndContext<Array<AccountBalancePair>>>;
|
||||||
getClusterNodes(): Promise<Array<ContactInfo>>;
|
getClusterNodes(): Promise<Array<ContactInfo>>;
|
||||||
getConfirmedBlock(slot: number): Promise<ConfirmedBlock>;
|
getConfirmedBlock(slot: number): Promise<ConfirmedBlock>;
|
||||||
getConfirmedTransaction(
|
getConfirmedTransaction(
|
||||||
|
@ -100,6 +100,29 @@ function notificationResultAndContext(resultDescription: any) {
|
|||||||
*/
|
*/
|
||||||
export type Commitment = 'max' | 'recent' | 'root' | 'single';
|
export type Commitment = 'max' | 'recent' | 'root' | 'single';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter for largest accounts query
|
||||||
|
* <pre>
|
||||||
|
* 'circulating': Return the largest accounts that are part of the circulating supply
|
||||||
|
* 'nonCirculating': Return the largest accounts that are not part of the circulating supply
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @typedef {'circulating' | 'nonCirculating'} LargestAccountsFilter
|
||||||
|
*/
|
||||||
|
export type LargestAccountsFilter = 'circulating' | 'nonCirculating';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration object for changing `getLargestAccounts` query behavior
|
||||||
|
*
|
||||||
|
* @typedef {Object} GetLargestAccountsConfig
|
||||||
|
* @property {Commitment|undefined} commitment The level of commitment desired
|
||||||
|
* @property {LargestAccountsFilter|undefined} filter Filter largest accounts by whether they are part of the circulating supply
|
||||||
|
*/
|
||||||
|
type GetLargestAccountsConfig = {
|
||||||
|
commitment: ?Commitment,
|
||||||
|
filter: ?LargestAccountsFilter,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration object for changing query behavior
|
* Configuration object for changing query behavior
|
||||||
*
|
*
|
||||||
@ -431,6 +454,30 @@ const GetSupplyRpcResult = jsonRpcResultAndContext(
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pair of an account address and its balance
|
||||||
|
*
|
||||||
|
* @typedef {Object} AccountBalancePair
|
||||||
|
* @property {PublicKey} address
|
||||||
|
* @property {number} lamports
|
||||||
|
*/
|
||||||
|
type AccountBalancePair = {
|
||||||
|
address: PublicKey,
|
||||||
|
lamports: number,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expected JSON RPC response for the "getLargestAccounts" message
|
||||||
|
*/
|
||||||
|
const GetLargestAccountsRpcResult = jsonRpcResultAndContext(
|
||||||
|
struct.array([
|
||||||
|
struct({
|
||||||
|
lamports: 'number',
|
||||||
|
address: 'string',
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expected JSON RPC response for the "getVersion" message
|
* Expected JSON RPC response for the "getVersion" message
|
||||||
*/
|
*/
|
||||||
@ -1063,6 +1110,30 @@ export class Connection {
|
|||||||
return res.result;
|
return res.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the 20 largest accounts with their current balances
|
||||||
|
*/
|
||||||
|
async getLargestAccounts(
|
||||||
|
config: ?GetLargestAccountsConfig,
|
||||||
|
): Promise<RpcResponseAndContext<Array<AccountBalancePair>>> {
|
||||||
|
const arg = {
|
||||||
|
...config,
|
||||||
|
commitment: (config && config.commitment) || this.commitment,
|
||||||
|
};
|
||||||
|
const args = arg.filter || arg.commitment ? [arg] : [];
|
||||||
|
const unsafeRes = await this._rpcRequest('getLargestAccounts', args);
|
||||||
|
const res = GetLargestAccountsRpcResult(unsafeRes);
|
||||||
|
if (res.error) {
|
||||||
|
throw new Error('failed to get largest accounts: ' + res.error.message);
|
||||||
|
}
|
||||||
|
assert(typeof res.result !== 'undefined');
|
||||||
|
res.result.value = res.result.value.map(({address, lamports}) => ({
|
||||||
|
address: new PublicKey(address),
|
||||||
|
lamports,
|
||||||
|
}));
|
||||||
|
return res.result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch all the account info for the specified public key, return with context
|
* Fetch all the account info for the specified public key, return with context
|
||||||
*/
|
*/
|
||||||
|
@ -1141,6 +1141,33 @@ test('get supply', async () => {
|
|||||||
expect(supply.nonCirculatingAccounts.length).toBeGreaterThan(0);
|
expect(supply.nonCirculatingAccounts.length).toBeGreaterThan(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('get largest accounts', async () => {
|
||||||
|
const connection = new Connection(url);
|
||||||
|
|
||||||
|
mockRpc.push([
|
||||||
|
url,
|
||||||
|
{
|
||||||
|
method: 'getLargestAccounts',
|
||||||
|
params: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
error: null,
|
||||||
|
result: {
|
||||||
|
context: {
|
||||||
|
slot: 1,
|
||||||
|
},
|
||||||
|
value: new Array(20).fill(0).map(() => ({
|
||||||
|
address: new Account().publicKey.toBase58(),
|
||||||
|
lamports: 1000,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const largestAccounts = (await connection.getLargestAccounts()).value;
|
||||||
|
expect(largestAccounts.length).toEqual(20);
|
||||||
|
});
|
||||||
|
|
||||||
test('getVersion', async () => {
|
test('getVersion', async () => {
|
||||||
const connection = new Connection(url);
|
const connection = new Connection(url);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user