feat: add token methods (#11303)
This commit is contained in:
46
web3.js/flow-typed/npm/@solana/spl-token_vx.x.x.js
vendored
Normal file
46
web3.js/flow-typed/npm/@solana/spl-token_vx.x.x.js
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
// flow-typed signature: 069c76ac6f0b539483367fd95c435241
|
||||
// flow-typed version: <<STUB>>/@solana/spl-token_v0.0.4/flow_v0.130.0
|
||||
|
||||
/**
|
||||
* This is an autogenerated libdef stub for:
|
||||
*
|
||||
* '@solana/spl-token'
|
||||
*
|
||||
* Fill this stub out by replacing all the `any` types.
|
||||
*
|
||||
* Once filled out, we encourage you to share your work with the
|
||||
* community by sending a pull request to:
|
||||
* https://github.com/flowtype/flow-typed
|
||||
*/
|
||||
|
||||
declare module '@solana/spl-token' {
|
||||
declare module.exports: any;
|
||||
}
|
||||
|
||||
/**
|
||||
* We include stubs for each file inside this npm package in case you need to
|
||||
* require those files directly. Feel free to delete any files that aren't
|
||||
* needed.
|
||||
*/
|
||||
declare module '@solana/spl-token/lib/index.cjs' {
|
||||
declare module.exports: any;
|
||||
}
|
||||
|
||||
declare module '@solana/spl-token/lib/index.esm' {
|
||||
declare module.exports: any;
|
||||
}
|
||||
|
||||
declare module '@solana/spl-token/module.flow' {
|
||||
declare module.exports: any;
|
||||
}
|
||||
|
||||
// Filename aliases
|
||||
declare module '@solana/spl-token/lib/index.cjs.js' {
|
||||
declare module.exports: $Exports<'@solana/spl-token/lib/index.cjs'>;
|
||||
}
|
||||
declare module '@solana/spl-token/lib/index.esm.js' {
|
||||
declare module.exports: $Exports<'@solana/spl-token/lib/index.esm'>;
|
||||
}
|
||||
declare module '@solana/spl-token/module.flow.js' {
|
||||
declare module.exports: $Exports<'@solana/spl-token/module.flow'>;
|
||||
}
|
40
web3.js/module.d.ts
vendored
40
web3.js/module.d.ts
vendored
@ -50,6 +50,14 @@ declare module '@solana/web3.js' {
|
||||
skipPreflight?: boolean;
|
||||
};
|
||||
|
||||
export type TokenAccountsFilter =
|
||||
| {
|
||||
mint: PublicKey;
|
||||
}
|
||||
| {
|
||||
programId: PublicKey;
|
||||
};
|
||||
|
||||
export type RpcResponseAndContext<T> = {
|
||||
context: Context;
|
||||
value: T;
|
||||
@ -150,6 +158,23 @@ declare module '@solana/web3.js' {
|
||||
root: number;
|
||||
};
|
||||
|
||||
export type TokenAccountInfo = {
|
||||
mint: PublicKey;
|
||||
owner: PublicKey;
|
||||
amount: number;
|
||||
delegate: null | PublicKey;
|
||||
delegatedAmount: number;
|
||||
isInitialized: boolean;
|
||||
isNative: boolean;
|
||||
};
|
||||
|
||||
export type TokenAccount = {
|
||||
executable: boolean;
|
||||
owner: PublicKey;
|
||||
lamports: number;
|
||||
data: TokenAccountInfo;
|
||||
};
|
||||
|
||||
export type AccountChangeCallback = (
|
||||
accountInfo: AccountInfo,
|
||||
context: Context,
|
||||
@ -239,6 +264,21 @@ declare module '@solana/web3.js' {
|
||||
getMinimumLedgerSlot(): Promise<number>;
|
||||
getFirstAvailableBlock(): Promise<number>;
|
||||
getSupply(commitment?: Commitment): Promise<RpcResponseAndContext<Supply>>;
|
||||
getTokenSupply(
|
||||
tokenMintAddress: PublicKey,
|
||||
commitment?: Commitment,
|
||||
): Promise<RpcResponseAndContext<number>>;
|
||||
getTokenAccountBalance(
|
||||
tokenAddress: PublicKey,
|
||||
commitment?: Commitment,
|
||||
): Promise<RpcResponseAndContext<number>>;
|
||||
getTokenAccountsByOwner(
|
||||
ownerAddress: PublicKey,
|
||||
filter: TokenAccountsFilter,
|
||||
commitment?: Commitment,
|
||||
): Promise<
|
||||
RpcResponseAndContext<Array<{pubkey: PublicKey; account: TokenAccount}>>
|
||||
>;
|
||||
getLargestAccounts(
|
||||
config?: GetLargestAccountsConfig,
|
||||
): Promise<RpcResponseAndContext<Array<AccountBalancePair>>>;
|
||||
|
@ -66,6 +66,14 @@ declare module '@solana/web3.js' {
|
||||
skipPreflight: ?boolean,
|
||||
};
|
||||
|
||||
declare export type TokenAccountsFilter =
|
||||
| {
|
||||
mint: PublicKey,
|
||||
}
|
||||
| {
|
||||
programId: PublicKey,
|
||||
};
|
||||
|
||||
declare export type RpcResponseAndContext<T> = {
|
||||
context: Context,
|
||||
value: T,
|
||||
@ -166,6 +174,23 @@ declare module '@solana/web3.js' {
|
||||
root: number,
|
||||
};
|
||||
|
||||
declare export type TokenAccountInfo = {
|
||||
mint: PublicKey,
|
||||
owner: PublicKey,
|
||||
amount: number,
|
||||
delegate: null | PublicKey,
|
||||
delegatedAmount: number,
|
||||
isInitialized: boolean,
|
||||
isNative: boolean,
|
||||
};
|
||||
|
||||
declare export type TokenAccount = {
|
||||
executable: boolean,
|
||||
owner: PublicKey,
|
||||
lamports: number,
|
||||
data: TokenAccountInfo,
|
||||
};
|
||||
|
||||
declare type AccountChangeCallback = (
|
||||
accountInfo: AccountInfo,
|
||||
context: Context,
|
||||
@ -255,6 +280,21 @@ declare module '@solana/web3.js' {
|
||||
getMinimumLedgerSlot(): Promise<number>;
|
||||
getFirstAvailableBlock(): Promise<number>;
|
||||
getSupply(commitment: ?Commitment): Promise<RpcResponseAndContext<Supply>>;
|
||||
getTokenSupply(
|
||||
tokenMintAddress: PublicKey,
|
||||
commitment: ?Commitment,
|
||||
): Promise<RpcResponseAndContext<number>>;
|
||||
getTokenAccountBalance(
|
||||
tokenAddress: PublicKey,
|
||||
commitment: ?Commitment,
|
||||
): Promise<RpcResponseAndContext<number>>;
|
||||
getTokenAccountsByOwner(
|
||||
ownerAddress: PublicKey,
|
||||
filter: TokenAccountsFilter,
|
||||
commitment: ?Commitment,
|
||||
): Promise<
|
||||
RpcResponseAndContext<Array<{pubkey: PublicKey, account: TokenAccount}>>,
|
||||
>;
|
||||
getLargestAccounts(
|
||||
config: ?GetLargestAccountsConfig,
|
||||
): Promise<RpcResponseAndContext<Array<AccountBalancePair>>>;
|
||||
|
75
web3.js/package-lock.json
generated
75
web3.js/package-lock.json
generated
@ -4742,6 +4742,44 @@
|
||||
"@sinonjs/commons": "^1.7.0"
|
||||
}
|
||||
},
|
||||
"@solana/spl-token": {
|
||||
"version": "0.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.0.4.tgz",
|
||||
"integrity": "sha512-zYoZ6iYMKxGYbouunEkWdf6vWRJyEPOkAjvlNVjww9oPKMkIeM9VzgGtjZ/kKMelao1QEohH4JN9qXO4+LwfRA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.10.5",
|
||||
"@solana/web3.js": "^0.63.2",
|
||||
"bn.js": "^5.0.0",
|
||||
"buffer-layout": "^1.2.0",
|
||||
"dotenv": "8.2.0",
|
||||
"json-to-pretty-yaml": "^1.2.2",
|
||||
"mkdirp-promise": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"@solana/web3.js": {
|
||||
"version": "0.63.2",
|
||||
"resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-0.63.2.tgz",
|
||||
"integrity": "sha512-4jd8U1U/eFTEemr+jCzQCDepKnkttV4dxWsjMloifb82x1d6KgCzP+Jd6D9kr8f1MFj2i/AnG++97tlHAGTOkA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.3.1",
|
||||
"bn.js": "^5.0.0",
|
||||
"bs58": "^4.0.1",
|
||||
"buffer": "^5.4.3",
|
||||
"buffer-layout": "^1.2.0",
|
||||
"crypto-hash": "^1.2.2",
|
||||
"esdoc-inject-style-plugin": "^1.0.0",
|
||||
"jayson": "^3.0.1",
|
||||
"mz": "^2.7.0",
|
||||
"node-fetch": "^2.2.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"rpc-websockets": "^5.0.8",
|
||||
"superstruct": "^0.8.3",
|
||||
"tweetnacl": "^1.0.0",
|
||||
"ws": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"@szmarczak/http-timer": {
|
||||
"version": "4.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.5.tgz",
|
||||
@ -8274,6 +8312,12 @@
|
||||
"is-obj": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"dotenv": {
|
||||
"version": "8.2.0",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
|
||||
"integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==",
|
||||
"dev": true
|
||||
},
|
||||
"duplexer2": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
|
||||
@ -14170,6 +14214,16 @@
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
|
||||
},
|
||||
"json-to-pretty-yaml": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/json-to-pretty-yaml/-/json-to-pretty-yaml-1.2.2.tgz",
|
||||
"integrity": "sha1-9M0L0KXo/h3yWq9boRiwmf2ZLVs=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"remedial": "^1.0.7",
|
||||
"remove-trailing-spaces": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"json5": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
|
||||
@ -15150,6 +15204,15 @@
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
},
|
||||
"mkdirp-promise": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz",
|
||||
"integrity": "sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mkdirp": "*"
|
||||
}
|
||||
},
|
||||
"modify-values": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz",
|
||||
@ -20096,12 +20159,24 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"remedial": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/remedial/-/remedial-1.0.8.tgz",
|
||||
"integrity": "sha512-/62tYiOe6DzS5BqVsNpH/nkGlX45C/Sp6V+NtiN6JQNS1Viay7cWkazmRkrQrdFj2eshDe96SIQNIoMxqhzBOg==",
|
||||
"dev": true
|
||||
},
|
||||
"remove-trailing-separator": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
|
||||
"integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
|
||||
"dev": true
|
||||
},
|
||||
"remove-trailing-spaces": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/remove-trailing-spaces/-/remove-trailing-spaces-1.0.7.tgz",
|
||||
"integrity": "sha512-wjM17CJ2kk0SgoGyJ7ZMzRRCuTq+V8YhMwpZ5XEWX0uaked2OUq6utvHXGNBQrfkUzUUABFMyxlKn+85hMv4dg==",
|
||||
"dev": true
|
||||
},
|
||||
"repeat-element": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
|
||||
|
@ -97,6 +97,7 @@
|
||||
"@babel/preset-flow": "^7.0.0",
|
||||
"@commitlint/config-conventional": "^9.0.1",
|
||||
"@commitlint/travis-cli": "^9.0.1",
|
||||
"@solana/spl-token": "^0.0.4",
|
||||
"@typescript-eslint/eslint-plugin": "^2.18.0",
|
||||
"@typescript-eslint/parser": "^2.18.0",
|
||||
"acorn": "^7.0.0",
|
||||
|
@ -24,6 +24,14 @@ export const BLOCKHASH_CACHE_TIMEOUT_MS = 30 * 1000;
|
||||
|
||||
type RpcRequest = (methodName: string, args: Array<any>) => any;
|
||||
|
||||
type TokenAccountsFilter =
|
||||
| {
|
||||
mint: PublicKey,
|
||||
}
|
||||
| {
|
||||
programId: PublicKey,
|
||||
};
|
||||
|
||||
/**
|
||||
* Extra contextual information for RPC responses
|
||||
*
|
||||
@ -500,6 +508,77 @@ const GetSupplyRpcResult = jsonRpcResultAndContext(
|
||||
}),
|
||||
);
|
||||
|
||||
/**
|
||||
* Information describing a token account
|
||||
*/
|
||||
type TokenAccountInfo = {|
|
||||
mint: PublicKey,
|
||||
owner: PublicKey,
|
||||
amount: number,
|
||||
delegate: null | PublicKey,
|
||||
delegatedAmount: number,
|
||||
isInitialized: boolean,
|
||||
isNative: boolean,
|
||||
|};
|
||||
|
||||
/**
|
||||
* Information describing an account with token account data
|
||||
*
|
||||
* @typedef {Object} TokenAccount
|
||||
* @property {number} lamports Number of lamports assigned to the account
|
||||
* @property {PublicKey} owner Identifier of the program that owns the account
|
||||
* @property {TokenAccountInfo} data Token account data
|
||||
* @property {boolean} executable `true` if this account's data contains a loaded program
|
||||
*/
|
||||
type TokenAccount = {
|
||||
executable: boolean,
|
||||
owner: PublicKey,
|
||||
lamports: number,
|
||||
data: TokenAccountInfo,
|
||||
};
|
||||
|
||||
const TokenAccountResult = struct({
|
||||
token: struct({
|
||||
account: struct({
|
||||
mint: 'string',
|
||||
owner: 'string',
|
||||
amount: 'number',
|
||||
delegate: struct.union(['string', 'null']),
|
||||
delegatedAmount: 'number',
|
||||
isInitialized: 'boolean',
|
||||
isNative: 'boolean',
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
/**
|
||||
* Expected JSON RPC response for the "getTokenAccountBalance" message
|
||||
*/
|
||||
const GetTokenAccountBalance = jsonRpcResultAndContext('number');
|
||||
|
||||
/**
|
||||
* Expected JSON RPC response for the "getTokenSupply" message
|
||||
*/
|
||||
const GetTokenSupplyRpcResult = jsonRpcResultAndContext('number');
|
||||
|
||||
/**
|
||||
* Expected JSON RPC response for the "getTokenAccountsByOwner" message
|
||||
*/
|
||||
const GetTokenAccountsByOwner = jsonRpcResultAndContext(
|
||||
struct.array([
|
||||
struct({
|
||||
pubkey: 'string',
|
||||
account: struct({
|
||||
executable: 'boolean',
|
||||
owner: 'string',
|
||||
lamports: 'number',
|
||||
data: TokenAccountResult,
|
||||
rentEpoch: 'number?',
|
||||
}),
|
||||
}),
|
||||
]),
|
||||
);
|
||||
|
||||
/**
|
||||
* Pair of an account address and its balance
|
||||
*
|
||||
@ -541,7 +620,7 @@ const AccountInfoResult = struct({
|
||||
executable: 'boolean',
|
||||
owner: 'string',
|
||||
lamports: 'number',
|
||||
data: 'string',
|
||||
data: 'any',
|
||||
rentEpoch: 'number?',
|
||||
});
|
||||
|
||||
@ -1185,6 +1264,109 @@ export class Connection {
|
||||
return res.result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the current supply of a token mint
|
||||
*/
|
||||
async getTokenSupply(
|
||||
tokenMintAddress: PublicKey,
|
||||
commitment: ?Commitment,
|
||||
): Promise<RpcResponseAndContext<number>> {
|
||||
const args = this._argsWithCommitment(
|
||||
[tokenMintAddress.toBase58()],
|
||||
commitment,
|
||||
);
|
||||
const unsafeRes = await this._rpcRequest('getTokenSupply', args);
|
||||
const res = GetTokenSupplyRpcResult(unsafeRes);
|
||||
if (res.error) {
|
||||
throw new Error('failed to get token supply: ' + res.error.message);
|
||||
}
|
||||
assert(typeof res.result !== 'undefined');
|
||||
return res.result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the current balance of a token account
|
||||
*/
|
||||
async getTokenAccountBalance(
|
||||
tokenAddress: PublicKey,
|
||||
commitment: ?Commitment,
|
||||
): Promise<RpcResponseAndContext<number>> {
|
||||
const args = this._argsWithCommitment(
|
||||
[tokenAddress.toBase58()],
|
||||
commitment,
|
||||
);
|
||||
const unsafeRes = await this._rpcRequest('getTokenAccountBalance', args);
|
||||
const res = GetTokenAccountBalance(unsafeRes);
|
||||
if (res.error) {
|
||||
throw new Error(
|
||||
'failed to get token account balance: ' + res.error.message,
|
||||
);
|
||||
}
|
||||
assert(typeof res.result !== 'undefined');
|
||||
return res.result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch all the token accounts owned by the specified account
|
||||
*
|
||||
* @return {Promise<RpcResponseAndContext<Array<{pubkey: PublicKey, account: TokenAccount}>>>}
|
||||
*/
|
||||
async getTokenAccountsByOwner(
|
||||
ownerAddress: PublicKey,
|
||||
filter: TokenAccountsFilter,
|
||||
commitment: ?Commitment,
|
||||
): Promise<
|
||||
RpcResponseAndContext<Array<{pubkey: PublicKey, account: TokenAccount}>>,
|
||||
> {
|
||||
let _args = [ownerAddress.toBase58()];
|
||||
|
||||
// Strip flow types to make flow happy
|
||||
((filter: any) => {
|
||||
if ('mint' in filter) {
|
||||
_args.push({mint: filter.mint.toBase58()});
|
||||
} else {
|
||||
_args.push({programId: filter.programId.toBase58()});
|
||||
}
|
||||
})(filter);
|
||||
|
||||
const args = this._argsWithCommitment(_args, commitment);
|
||||
const unsafeRes = await this._rpcRequest('getTokenAccountsByOwner', args);
|
||||
const res = GetTokenAccountsByOwner(unsafeRes);
|
||||
if (res.error) {
|
||||
throw new Error(
|
||||
'failed to get token accounts owned by account ' +
|
||||
ownerAddress.toBase58() +
|
||||
': ' +
|
||||
res.error.message,
|
||||
);
|
||||
}
|
||||
|
||||
const {result} = res;
|
||||
const {context, value} = result;
|
||||
assert(typeof result !== 'undefined');
|
||||
|
||||
return {
|
||||
context,
|
||||
value: value.map(result => {
|
||||
const data = result.account.data.token.account;
|
||||
return {
|
||||
pubkey: new PublicKey(result.pubkey),
|
||||
account: {
|
||||
executable: result.account.executable,
|
||||
owner: new PublicKey(result.account.owner),
|
||||
lamports: result.account.lamports,
|
||||
data: {
|
||||
...data,
|
||||
mint: new PublicKey(data.mint),
|
||||
owner: new PublicKey(data.owner),
|
||||
delegate: data.delegate ? new PublicKey(data.delegate) : null,
|
||||
},
|
||||
},
|
||||
};
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the 20 largest accounts with their current balances
|
||||
*/
|
||||
|
@ -1,5 +1,6 @@
|
||||
// @flow
|
||||
import bs58 from 'bs58';
|
||||
import {Token, u64} from '@solana/spl-token';
|
||||
|
||||
import {
|
||||
Account,
|
||||
@ -1261,6 +1262,129 @@ test('get supply', async () => {
|
||||
expect(supply.nonCirculatingAccounts.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
const TOKEN_PROGRAM_ID = new PublicKey(
|
||||
'TokenSVp5gheXUvJ6jGWGeCsgPKgnE3YgdGKRVCMY9o',
|
||||
);
|
||||
|
||||
test('token methods', async () => {
|
||||
if (mockRpcEnabled) {
|
||||
console.log('non-live test skipped');
|
||||
return;
|
||||
}
|
||||
|
||||
const connection = new Connection(url);
|
||||
const payerAccount = new Account();
|
||||
await connection.confirmTransaction(
|
||||
await connection.requestAirdrop(payerAccount.publicKey, 100000000000),
|
||||
0,
|
||||
);
|
||||
|
||||
const mintOwner = new Account();
|
||||
const accountOwner = new Account();
|
||||
const [token, tokenAccount] = await Token.createMint(
|
||||
connection,
|
||||
payerAccount,
|
||||
mintOwner.publicKey,
|
||||
accountOwner.publicKey,
|
||||
new u64(10000),
|
||||
2,
|
||||
TOKEN_PROGRAM_ID,
|
||||
false,
|
||||
);
|
||||
|
||||
await Token.createMint(
|
||||
connection,
|
||||
payerAccount,
|
||||
mintOwner.publicKey,
|
||||
accountOwner.publicKey,
|
||||
new u64(10000),
|
||||
2,
|
||||
TOKEN_PROGRAM_ID,
|
||||
false,
|
||||
);
|
||||
|
||||
const tokenAccountDest = await token.createAccount(accountOwner.publicKey);
|
||||
await token.transfer(
|
||||
tokenAccount,
|
||||
tokenAccountDest,
|
||||
accountOwner,
|
||||
[],
|
||||
new u64(1),
|
||||
);
|
||||
|
||||
const supply = (await connection.getTokenSupply(token.publicKey, 'recent'))
|
||||
.value;
|
||||
expect(supply).toEqual(10000);
|
||||
|
||||
const newAccount = new Account();
|
||||
await expect(
|
||||
connection.getTokenSupply(newAccount.publicKey, 'recent'),
|
||||
).rejects.toThrow();
|
||||
|
||||
const balance = (
|
||||
await connection.getTokenAccountBalance(tokenAccount, 'recent')
|
||||
).value;
|
||||
expect(balance).toEqual(9999);
|
||||
|
||||
await expect(
|
||||
connection.getTokenAccountBalance(newAccount.publicKey, 'recent'),
|
||||
).rejects.toThrow();
|
||||
|
||||
const accountsWithMintFilter = (
|
||||
await connection.getTokenAccountsByOwner(
|
||||
accountOwner.publicKey,
|
||||
{mint: token.publicKey},
|
||||
'recent',
|
||||
)
|
||||
).value;
|
||||
expect(accountsWithMintFilter.length).toEqual(2);
|
||||
for (const {account} of accountsWithMintFilter) {
|
||||
expect(account.data.mint.toBase58()).toEqual(token.publicKey.toBase58());
|
||||
expect(account.data.owner.toBase58()).toEqual(
|
||||
accountOwner.publicKey.toBase58(),
|
||||
);
|
||||
}
|
||||
|
||||
const accountsWithProgramFilter = (
|
||||
await connection.getTokenAccountsByOwner(
|
||||
accountOwner.publicKey,
|
||||
{programId: TOKEN_PROGRAM_ID},
|
||||
'recent',
|
||||
)
|
||||
).value;
|
||||
expect(accountsWithProgramFilter.length).toEqual(3);
|
||||
for (const {account} of accountsWithProgramFilter) {
|
||||
expect(account.data.owner.toBase58()).toEqual(
|
||||
accountOwner.publicKey.toBase58(),
|
||||
);
|
||||
}
|
||||
|
||||
const noAccounts = (
|
||||
await connection.getTokenAccountsByOwner(
|
||||
newAccount.publicKey,
|
||||
{mint: token.publicKey},
|
||||
'recent',
|
||||
)
|
||||
).value;
|
||||
expect(noAccounts.length).toEqual(0);
|
||||
|
||||
await expect(
|
||||
connection.getTokenAccountsByOwner(
|
||||
accountOwner.publicKey,
|
||||
{mint: newAccount.publicKey},
|
||||
'recent',
|
||||
),
|
||||
).rejects.toThrow();
|
||||
|
||||
await expect(
|
||||
connection.getTokenAccountsByOwner(
|
||||
accountOwner.publicKey,
|
||||
{programId: newAccount.publicKey},
|
||||
'recent',
|
||||
),
|
||||
).rejects.toThrow();
|
||||
});
|
||||
|
||||
test('get largest accounts', async () => {
|
||||
const connection = new Connection(url);
|
||||
|
||||
|
Reference in New Issue
Block a user