feat: add getTokenLargestAccounts method

This commit is contained in:
Justin Starry 2020-08-11 17:28:07 +08:00 committed by Justin Starry
parent 177c9c3aec
commit e1dc05fae0
4 changed files with 104 additions and 2 deletions

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

@ -215,6 +215,13 @@ declare module '@solana/web3.js' {
amount: string;
};
export type TokenAccountBalancePair = {
address: PublicKey;
amount: string;
decimals: number;
uiAmount: number;
};
export type AccountChangeCallback = (
accountInfo: AccountInfo<Buffer>,
context: Context,
@ -343,6 +350,10 @@ declare module '@solana/web3.js' {
getLargestAccounts(
config?: GetLargestAccountsConfig,
): Promise<RpcResponseAndContext<Array<AccountBalancePair>>>;
getTokenLargestAccounts(
mintAddress: PublicKey,
commitment?: Commitment,
): Promise<RpcResponseAndContext<Array<TokenAccountBalancePair>>>;
getClusterNodes(): Promise<Array<ContactInfo>>;
getConfirmedBlock(slot: number): Promise<ConfirmedBlock>;
getConfirmedTransaction(

View File

@ -237,6 +237,13 @@ declare module '@solana/web3.js' {
amount: string,
};
declare export type TokenAccountBalancePair = {
address: PublicKey,
amount: string,
decimals: number,
uiAmount: number,
};
declare type AccountChangeCallback = (
accountInfo: AccountInfo<Buffer>,
context: Context,
@ -356,6 +363,10 @@ declare module '@solana/web3.js' {
getLargestAccounts(
config: ?GetLargestAccountsConfig,
): Promise<RpcResponseAndContext<Array<AccountBalancePair>>>;
getTokenLargestAccounts(
mintAddress: PublicKey,
commitment: ?Commitment,
): Promise<RpcResponseAndContext<Array<TokenAccountBalancePair>>>;
getClusterNodes(): Promise<Array<ContactInfo>>;
getConfirmedBlock(slot: number): Promise<ConfirmedBlock>;
getConfirmedTransaction(

View File

@ -616,21 +616,60 @@ const GetSupplyRpcResult = jsonRpcResultAndContext(
}),
);
/**
* Token amount object which returns a token amount in different formats
* for various client use cases.
*
* @typedef {Object} TokenAmount
* @property {string} amount Raw amount of tokens as string ignoring decimals
* @property {number} decimals Number of decimals configured for token's mint
* @property {number} uiAmount Token account as float, accounts for decimals
*/
type TokenAmount = {
amount: string,
decimals: 2,
decimals: number,
uiAmount: number,
};
/**
* Expected JSON RPC structure for token amounts
*/
const TokenAmountResult = struct({
const TokenAmountResult = struct.object({
amount: 'string',
uiAmount: 'number',
decimals: 'number',
});
/**
* Token address and balance.
*
* @typedef {Object} TokenAccountBalancePair
* @property {PublicKey} address Address of the token account
* @property {string} amount Raw amount of tokens as string ignoring decimals
* @property {number} decimals Number of decimals configured for token's mint
* @property {number} uiAmount Token account as float, accounts for decimals
*/
type TokenAccountBalancePair = {
address: PublicKey,
amount: string,
decimals: number,
uiAmount: number,
};
/**
* Expected JSON RPC response for the "getTokenLargestAccounts" message
*/
const GetTokenLargestAccountsResult = jsonRpcResultAndContext(
struct.array([
struct.pick({
address: 'string',
amount: 'string',
uiAmount: 'number',
decimals: 'number',
}),
]),
);
/**
* Expected JSON RPC response for the "getTokenAccountBalance" message
*/
@ -1653,6 +1692,30 @@ export class Connection {
return res.result;
}
/**
* Fetch the 20 largest token accounts with their current balances
* for a given mint.
*/
async getTokenLargestAccounts(
mintAddress: PublicKey,
commitment: ?Commitment,
): Promise<RpcResponseAndContext<Array<TokenAccountBalancePair>>> {
const args = this._buildArgs([mintAddress.toBase58()], commitment);
const unsafeRes = await this._rpcRequest('getTokenLargestAccounts', args);
const res = GetTokenLargestAccountsResult(unsafeRes);
if (res.error) {
throw new Error(
'failed to get token largest accounts: ' + res.error.message,
);
}
assert(typeof res.result !== 'undefined');
res.result.value = res.result.value.map(pair => ({
...pair,
address: new PublicKey(pair.address),
}));
return res.result;
}
/**
* Fetch all the account info for the specified public key, return with context
*/

View File

@ -1399,6 +1399,23 @@ describe('token methods', () => {
await expect(connection.getTokenSupply(newAccount)).rejects.toThrow();
});
test('get token largest accounts', async () => {
const largestAccounts = (
await connection.getTokenLargestAccounts(testToken.publicKey)
).value;
expect(largestAccounts.length).toEqual(2);
const largestAccount = largestAccounts[0];
expect(largestAccount.address.equals(testTokenAccount)).toBe(true);
expect(largestAccount.amount).toEqual('11110');
expect(largestAccount.decimals).toEqual(2);
expect(largestAccount.uiAmount).toEqual(111.1);
await expect(
connection.getTokenLargestAccounts(newAccount),
).rejects.toThrow();
});
test('get confirmed token transaction', async () => {
const parsedTx = await connection.getParsedConfirmedTransaction(
testSignature,