feat: add getTokenLargestAccounts method
This commit is contained in:
committed by
Justin Starry
parent
177c9c3aec
commit
e1dc05fae0
11
web3.js/module.d.ts
vendored
11
web3.js/module.d.ts
vendored
@ -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(
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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,
|
||||
|
Reference in New Issue
Block a user