feat: add getParsedConfirmedTransaction API
This commit is contained in:
parent
5a63c9d535
commit
b36e60738e
36
web3.js/module.d.ts
vendored
36
web3.js/module.d.ts
vendored
@ -148,6 +148,39 @@ declare module '@solana/web3.js' {
|
||||
meta: ConfirmedTransactionMeta | null;
|
||||
};
|
||||
|
||||
export type ParsedMessageAccount = {
|
||||
pubkey: PublicKey;
|
||||
signer: boolean;
|
||||
writable: boolean;
|
||||
};
|
||||
|
||||
export type ParsedInstruction = {
|
||||
programId: PublicKey;
|
||||
program: string;
|
||||
parsed: string;
|
||||
};
|
||||
|
||||
export type PartiallyDecodedInstruction = {
|
||||
programId: PublicKey;
|
||||
accounts: Array<PublicKey>;
|
||||
data: string;
|
||||
};
|
||||
|
||||
export type ParsedTransaction = {
|
||||
signatures: Array<string>;
|
||||
message: {
|
||||
accountKeys: ParsedMessageAccount[];
|
||||
instructions: (ParsedInstruction | PartiallyDecodedInstruction)[];
|
||||
recentBlockhash: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type ParsedConfirmedTransaction = {
|
||||
slot: number;
|
||||
transaction: ParsedTransaction;
|
||||
meta: ConfirmedTransactionMeta | null;
|
||||
};
|
||||
|
||||
export type KeyedAccountInfo = {
|
||||
accountId: PublicKey;
|
||||
accountInfo: AccountInfo;
|
||||
@ -288,6 +321,9 @@ declare module '@solana/web3.js' {
|
||||
getConfirmedTransaction(
|
||||
signature: TransactionSignature,
|
||||
): Promise<ConfirmedTransaction | null>;
|
||||
getParsedConfirmedTransaction(
|
||||
signature: TransactionSignature,
|
||||
): Promise<ParsedConfirmedTransaction | null>;
|
||||
getConfirmedSignaturesForAddress(
|
||||
address: PublicKey,
|
||||
startSlot: number,
|
||||
|
@ -169,6 +169,39 @@ declare module '@solana/web3.js' {
|
||||
meta: ConfirmedTransactionMeta | null,
|
||||
};
|
||||
|
||||
declare export type ParsedMessageAccount = {
|
||||
pubkey: PublicKey,
|
||||
signer: boolean,
|
||||
writable: boolean,
|
||||
};
|
||||
|
||||
declare export type ParsedInstruction = {|
|
||||
programId: PublicKey,
|
||||
program: string,
|
||||
parsed: string,
|
||||
|};
|
||||
|
||||
declare export type PartiallyDecodedInstruction = {|
|
||||
programId: PublicKey,
|
||||
accounts: Array<PublicKey>,
|
||||
data: string,
|
||||
|};
|
||||
|
||||
declare export type ParsedTransaction = {
|
||||
signatures: Array<string>,
|
||||
message: {
|
||||
accountKeys: ParsedMessageAccount[],
|
||||
instructions: (ParsedInstruction | PartiallyDecodedInstruction)[],
|
||||
recentBlockhash: string,
|
||||
},
|
||||
};
|
||||
|
||||
declare export type ParsedConfirmedTransaction = {
|
||||
slot: number,
|
||||
transaction: ParsedTransaction,
|
||||
meta: ConfirmedTransactionMeta | null,
|
||||
};
|
||||
|
||||
declare export type KeyedAccountInfo = {
|
||||
accountId: PublicKey,
|
||||
accountInfo: AccountInfo,
|
||||
@ -309,6 +342,9 @@ declare module '@solana/web3.js' {
|
||||
getConfirmedTransaction(
|
||||
signature: TransactionSignature,
|
||||
): Promise<ConfirmedTransaction | null>;
|
||||
getParsedConfirmedTransaction(
|
||||
signature: TransactionSignature,
|
||||
): Promise<ParsedConfirmedTransaction | null>;
|
||||
getConfirmedSignaturesForAddress(
|
||||
address: PublicKey,
|
||||
startSlot: number,
|
||||
|
37
web3.js/package-lock.json
generated
37
web3.js/package-lock.json
generated
@ -4743,24 +4743,23 @@
|
||||
}
|
||||
},
|
||||
"@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==",
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.0.5.tgz",
|
||||
"integrity": "sha512-OXW/zHzMQqVGcSNrNt8sRaHlKT5vjdcUcmUHi8d4ssG8ChbZVA2lkJK10XDXlcnMIiSTindpEjiFmooYc9K3uQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.10.5",
|
||||
"@solana/web3.js": "^0.63.2",
|
||||
"@solana/web3.js": "^0.64.0",
|
||||
"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==",
|
||||
"version": "0.64.2",
|
||||
"resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-0.64.2.tgz",
|
||||
"integrity": "sha512-aGRG1rn8fLerE4NscRL6rq0nSyYAK9K+TGRZxb6ue7Ontufa6wO1kxum4zJs17+xT0zVf8wABUtCMgP4W7FxpA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.3.1",
|
||||
@ -14214,16 +14213,6 @@
|
||||
"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",
|
||||
@ -20159,24 +20148,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"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,7 +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",
|
||||
"@solana/spl-token": "^0.0.5",
|
||||
"@typescript-eslint/eslint-plugin": "^2.18.0",
|
||||
"@typescript-eslint/parser": "^2.18.0",
|
||||
"acorn": "^7.0.0",
|
||||
|
@ -49,7 +49,7 @@ type Context = {
|
||||
* @property {boolean | undefined} skipPreflight disable transaction verification step
|
||||
*/
|
||||
export type SendOptions = {
|
||||
skipPreflight: ?boolean,
|
||||
skipPreflight?: boolean,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -60,8 +60,8 @@ export type SendOptions = {
|
||||
* @property {number | undefined} confirmations desired number of cluster confirmations
|
||||
*/
|
||||
export type ConfirmOptions = {
|
||||
skipPreflight: ?boolean,
|
||||
confirmations: ?number,
|
||||
skipPreflight?: boolean,
|
||||
confirmations?: number,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -378,6 +378,88 @@ type ConfirmedTransaction = {
|
||||
meta: ConfirmedTransactionMeta | null,
|
||||
};
|
||||
|
||||
/**
|
||||
* A partially decoded transaction instruction
|
||||
*
|
||||
* @typedef {Object} ParsedMessageAccount
|
||||
* @property {PublicKey} pubkey Public key of the account
|
||||
* @property {PublicKey} accounts Indicates if the account signed the transaction
|
||||
* @property {string} data Raw base-58 instruction data
|
||||
*/
|
||||
type PartiallyDecodedInstruction = {|
|
||||
programId: PublicKey,
|
||||
accounts: Array<PublicKey>,
|
||||
data: string,
|
||||
|};
|
||||
|
||||
/**
|
||||
* A parsed transaction message account
|
||||
*
|
||||
* @typedef {Object} ParsedMessageAccount
|
||||
* @property {PublicKey} pubkey Public key of the account
|
||||
* @property {boolean} signer Indicates if the account signed the transaction
|
||||
* @property {boolean} writable Indicates if the account is writable for this transaction
|
||||
*/
|
||||
type ParsedMessageAccount = {
|
||||
pubkey: PublicKey,
|
||||
signer: boolean,
|
||||
writable: boolean,
|
||||
};
|
||||
|
||||
/**
|
||||
* A parsed transaction instruction
|
||||
*
|
||||
* @typedef {Object} ParsedInstruction
|
||||
* @property {string} program Name of the program for this instruction
|
||||
* @property {PublicKey} programId ID of the program for this instruction
|
||||
* @property {any} parsed Parsed instruction info
|
||||
*/
|
||||
type ParsedInstruction = {|
|
||||
program: string,
|
||||
programId: PublicKey,
|
||||
parsed: any,
|
||||
|};
|
||||
|
||||
/**
|
||||
* A parsed transaction message
|
||||
*
|
||||
* @typedef {Object} ParsedMessage
|
||||
* @property {Array<ParsedMessageAccount>} accountKeys Accounts used in the instructions
|
||||
* @property {Array<ParsedInstruction | PartiallyDecodedInstruction>} instructions The atomically executed instructions for the transaction
|
||||
* @property {string} recentBlockhash Recent blockhash
|
||||
*/
|
||||
type ParsedMessage = {
|
||||
accountKeys: ParsedMessageAccount[],
|
||||
instructions: (ParsedInstruction | PartiallyDecodedInstruction)[],
|
||||
recentBlockhash: string,
|
||||
};
|
||||
|
||||
/**
|
||||
* A parsed transaction
|
||||
*
|
||||
* @typedef {Object} ParsedTransaction
|
||||
* @property {Array<string>} signatures Signatures for the transaction
|
||||
* @property {ParsedMessage} message Message of the transaction
|
||||
*/
|
||||
type ParsedTransaction = {
|
||||
signatures: Array<string>,
|
||||
message: ParsedMessage,
|
||||
};
|
||||
|
||||
/**
|
||||
* A parsed and confirmed transaction on the ledger
|
||||
*
|
||||
* @typedef {Object} ParsedConfirmedTransaction
|
||||
* @property {number} slot The slot during which the transaction was processed
|
||||
* @property {ParsedTransaction} transaction The details of the transaction
|
||||
* @property {ConfirmedTransactionMeta|null} meta Metadata produced from the transaction
|
||||
*/
|
||||
type ParsedConfirmedTransaction = {
|
||||
slot: number,
|
||||
transaction: ParsedTransaction,
|
||||
meta: ConfirmedTransactionMeta | null,
|
||||
};
|
||||
|
||||
/**
|
||||
* A ConfirmedBlock on the ledger
|
||||
*
|
||||
@ -807,13 +889,41 @@ const ConfirmedTransactionResult = struct({
|
||||
numReadonlySignedAccounts: 'number',
|
||||
numReadonlyUnsignedAccounts: 'number',
|
||||
}),
|
||||
instructions: struct.array([
|
||||
struct({
|
||||
accounts: struct.array(['number']),
|
||||
data: 'string',
|
||||
programIdIndex: 'number',
|
||||
}),
|
||||
]),
|
||||
recentBlockhash: 'string',
|
||||
}),
|
||||
});
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
const ParsedConfirmedTransactionResult = struct({
|
||||
signatures: struct.array(['string']),
|
||||
message: struct({
|
||||
accountKeys: struct.array([
|
||||
struct({
|
||||
pubkey: 'string',
|
||||
signer: 'boolean',
|
||||
writable: 'boolean',
|
||||
}),
|
||||
]),
|
||||
instructions: struct.array([
|
||||
struct.union([
|
||||
struct.array(['number']),
|
||||
struct({
|
||||
accounts: struct.array(['number']),
|
||||
accounts: struct.array(['string']),
|
||||
data: 'string',
|
||||
programIdIndex: 'number',
|
||||
programId: 'string',
|
||||
}),
|
||||
struct({
|
||||
parsed: 'any',
|
||||
program: 'string',
|
||||
programId: 'string',
|
||||
}),
|
||||
]),
|
||||
]),
|
||||
@ -877,6 +987,20 @@ const GetConfirmedTransactionRpcResult = jsonRpcResult(
|
||||
]),
|
||||
);
|
||||
|
||||
/**
|
||||
* Expected JSON RPC response for the "getConfirmedTransaction" message
|
||||
*/
|
||||
const GetParsedConfirmedTransactionRpcResult = jsonRpcResult(
|
||||
struct.union([
|
||||
'null',
|
||||
struct.pick({
|
||||
slot: 'number',
|
||||
transaction: ParsedConfirmedTransactionResult,
|
||||
meta: ConfirmedTransactionMetaResult,
|
||||
}),
|
||||
]),
|
||||
);
|
||||
|
||||
/**
|
||||
* Expected JSON RPC response for the "getRecentBlockhash" message
|
||||
*/
|
||||
@ -1853,6 +1977,56 @@ export class Connection {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch parsed transaction details for a confirmed transaction
|
||||
*/
|
||||
async getParsedConfirmedTransaction(
|
||||
signature: TransactionSignature,
|
||||
): Promise<ParsedConfirmedTransaction | null> {
|
||||
const unsafeRes = await this._rpcRequest('getConfirmedTransaction', [
|
||||
signature,
|
||||
'jsonParsed',
|
||||
]);
|
||||
const {result, error} = GetParsedConfirmedTransactionRpcResult(unsafeRes);
|
||||
if (error) {
|
||||
throw new Error('failed to get confirmed transaction: ' + error.message);
|
||||
}
|
||||
assert(typeof result !== 'undefined');
|
||||
if (result === null) return result;
|
||||
|
||||
const {
|
||||
accountKeys,
|
||||
instructions,
|
||||
recentBlockhash,
|
||||
} = result.transaction.message;
|
||||
return {
|
||||
slot: result.slot,
|
||||
meta: result.meta,
|
||||
transaction: {
|
||||
signatures: result.transaction.signatures,
|
||||
message: {
|
||||
accountKeys: accountKeys.map(accountKey => ({
|
||||
pubkey: new PublicKey(accountKey.pubkey),
|
||||
signer: accountKey.signer,
|
||||
writable: accountKey.writable,
|
||||
})),
|
||||
instructions: instructions.map(ix => {
|
||||
let mapped: any = {programId: new PublicKey(ix.programId)};
|
||||
if ('accounts' in ix) {
|
||||
mapped.accounts = ix.accounts.map(key => new PublicKey(key));
|
||||
}
|
||||
|
||||
return {
|
||||
...ix,
|
||||
...mapped,
|
||||
};
|
||||
}),
|
||||
recentBlockhash,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
@ -1,5 +1,6 @@
|
||||
// @flow
|
||||
|
||||
import bs58 from 'bs58';
|
||||
import fs from 'mz/fs';
|
||||
|
||||
import {
|
||||
@ -77,7 +78,29 @@ test('load BPF Rust program', async () => {
|
||||
programId: program.publicKey,
|
||||
});
|
||||
await sendAndConfirmTransaction(connection, transaction, [from], {
|
||||
confirmations: 1,
|
||||
skipPreflight: true,
|
||||
});
|
||||
|
||||
if (transaction.signature === null) {
|
||||
expect(transaction.signature).not.toBeNull();
|
||||
return;
|
||||
}
|
||||
|
||||
const confirmedSignature = bs58.encode(transaction.signature);
|
||||
const parsedTx = await connection.getParsedConfirmedTransaction(
|
||||
confirmedSignature,
|
||||
);
|
||||
if (parsedTx === null) {
|
||||
expect(parsedTx).not.toBeNull();
|
||||
return;
|
||||
}
|
||||
const {signatures, message} = parsedTx.transaction;
|
||||
expect(signatures[0]).toEqual(confirmedSignature);
|
||||
const ix = message.instructions[0];
|
||||
if (ix.parsed) {
|
||||
expect('parsed' in ix).toBe(false);
|
||||
} else {
|
||||
expect(ix.programId.equals(program.publicKey)).toBe(true);
|
||||
expect(ix.data).toEqual('');
|
||||
}
|
||||
});
|
||||
|
@ -16,6 +16,7 @@ import {mockGetRecentBlockhash} from './mockrpc/get-recent-blockhash';
|
||||
import {url} from './url';
|
||||
import {sleep} from '../src/util/sleep';
|
||||
import {BLOCKHASH_CACHE_TIMEOUT_MS} from '../src/connection';
|
||||
import type {TransactionSignature} from '../src/transaction';
|
||||
import type {SignatureStatus, TransactionError} from '../src/connection';
|
||||
import {mockConfirmTransaction} from './mockrpc/confirm-transaction';
|
||||
|
||||
@ -1299,116 +1300,150 @@ const TOKEN_PROGRAM_ID = new PublicKey(
|
||||
'TokenSVp5gheXUvJ6jGWGeCsgPKgnE3YgdGKRVCMY9o',
|
||||
);
|
||||
|
||||
test('token methods', async () => {
|
||||
describe('token methods', () => {
|
||||
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 newAccount = new Account().publicKey;
|
||||
|
||||
const mintOwner = new Account();
|
||||
const accountOwner = new Account();
|
||||
const [token, tokenAccount] = await Token.createMint(
|
||||
connection,
|
||||
payerAccount,
|
||||
mintOwner.publicKey,
|
||||
accountOwner.publicKey,
|
||||
new u64(11111),
|
||||
2,
|
||||
TOKEN_PROGRAM_ID,
|
||||
false,
|
||||
);
|
||||
let testToken: Token;
|
||||
let testTokenAccount: PublicKey;
|
||||
let testSignature: TransactionSignature;
|
||||
let testOwner: Account;
|
||||
|
||||
await Token.createMint(
|
||||
connection,
|
||||
payerAccount,
|
||||
mintOwner.publicKey,
|
||||
accountOwner.publicKey,
|
||||
new u64(10000),
|
||||
2,
|
||||
TOKEN_PROGRAM_ID,
|
||||
false,
|
||||
);
|
||||
// Setup token mints and accounts for token tests
|
||||
beforeAll(async () => {
|
||||
const payerAccount = new Account();
|
||||
await connection.confirmTransaction(
|
||||
await connection.requestAirdrop(payerAccount.publicKey, 100000000000),
|
||||
0,
|
||||
);
|
||||
|
||||
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.uiAmount).toEqual(111.11);
|
||||
expect(supply.decimals).toEqual(2);
|
||||
expect(supply.amount).toEqual('11111');
|
||||
|
||||
const newAccount = new Account();
|
||||
await expect(
|
||||
connection.getTokenSupply(newAccount.publicKey, 'recent'),
|
||||
).rejects.toThrow();
|
||||
|
||||
const balance = (
|
||||
await connection.getTokenAccountBalance(tokenAccount, 'recent')
|
||||
).value;
|
||||
expect(balance.amount).toEqual('11110');
|
||||
expect(balance.decimals).toEqual(2);
|
||||
expect(balance.uiAmount).toEqual(111.1);
|
||||
|
||||
await expect(
|
||||
connection.getTokenAccountBalance(newAccount.publicKey, 'recent'),
|
||||
).rejects.toThrow();
|
||||
|
||||
const accountsWithMintFilter = (
|
||||
await connection.getTokenAccountsByOwner(
|
||||
const mintOwner = new Account();
|
||||
const accountOwner = new Account();
|
||||
const [token, tokenAccount] = await Token.createMint(
|
||||
connection,
|
||||
payerAccount,
|
||||
mintOwner.publicKey,
|
||||
accountOwner.publicKey,
|
||||
{mint: token.publicKey},
|
||||
'recent',
|
||||
)
|
||||
).value;
|
||||
expect(accountsWithMintFilter.length).toEqual(2);
|
||||
new u64(11111),
|
||||
2,
|
||||
TOKEN_PROGRAM_ID,
|
||||
false,
|
||||
);
|
||||
|
||||
const accountsWithProgramFilter = (
|
||||
await connection.getTokenAccountsByOwner(
|
||||
await Token.createMint(
|
||||
connection,
|
||||
payerAccount,
|
||||
mintOwner.publicKey,
|
||||
accountOwner.publicKey,
|
||||
{programId: TOKEN_PROGRAM_ID},
|
||||
'recent',
|
||||
)
|
||||
).value;
|
||||
expect(accountsWithProgramFilter.length).toEqual(3);
|
||||
new u64(10000),
|
||||
2,
|
||||
TOKEN_PROGRAM_ID,
|
||||
false,
|
||||
);
|
||||
|
||||
const noAccounts = (
|
||||
await connection.getTokenAccountsByOwner(
|
||||
newAccount.publicKey,
|
||||
{mint: token.publicKey},
|
||||
'recent',
|
||||
)
|
||||
).value;
|
||||
expect(noAccounts.length).toEqual(0);
|
||||
const tokenAccountDest = await token.createAccount(accountOwner.publicKey);
|
||||
testSignature = await token.transfer(
|
||||
tokenAccount,
|
||||
tokenAccountDest,
|
||||
accountOwner,
|
||||
[],
|
||||
new u64(1),
|
||||
);
|
||||
|
||||
await expect(
|
||||
connection.getTokenAccountsByOwner(
|
||||
accountOwner.publicKey,
|
||||
{mint: newAccount.publicKey},
|
||||
'recent',
|
||||
),
|
||||
).rejects.toThrow();
|
||||
await connection.confirmTransaction(testSignature);
|
||||
|
||||
await expect(
|
||||
connection.getTokenAccountsByOwner(
|
||||
accountOwner.publicKey,
|
||||
{programId: newAccount.publicKey},
|
||||
'recent',
|
||||
),
|
||||
).rejects.toThrow();
|
||||
testOwner = accountOwner;
|
||||
testToken = token;
|
||||
testTokenAccount = tokenAccount;
|
||||
});
|
||||
|
||||
test('get token supply', async () => {
|
||||
const supply = (await connection.getTokenSupply(testToken.publicKey)).value;
|
||||
expect(supply.uiAmount).toEqual(111.11);
|
||||
expect(supply.decimals).toEqual(2);
|
||||
expect(supply.amount).toEqual('11111');
|
||||
|
||||
await expect(connection.getTokenSupply(newAccount)).rejects.toThrow();
|
||||
});
|
||||
|
||||
test('get confirmed token transaction', async () => {
|
||||
const parsedTx = await connection.getParsedConfirmedTransaction(
|
||||
testSignature,
|
||||
);
|
||||
if (parsedTx === null) {
|
||||
expect(parsedTx).not.toBeNull();
|
||||
return;
|
||||
}
|
||||
const {signatures, message} = parsedTx.transaction;
|
||||
expect(signatures[0]).toEqual(testSignature);
|
||||
const ix = message.instructions[0];
|
||||
if (ix.parsed) {
|
||||
expect(ix.program).toEqual('spl-token');
|
||||
expect(ix.programId.equals(TOKEN_PROGRAM_ID)).toBe(true);
|
||||
} else {
|
||||
expect('parsed' in ix).toBe(true);
|
||||
}
|
||||
|
||||
const missingSignature =
|
||||
'45pGoC4Rr3fJ1TKrsiRkhHRbdUeX7633XAGVec6XzVdpRbzQgHhe6ZC6Uq164MPWtiqMg7wCkC6Wy3jy2BqsDEKf';
|
||||
const nullResponse = await connection.getParsedConfirmedTransaction(
|
||||
missingSignature,
|
||||
);
|
||||
|
||||
expect(nullResponse).toBeNull();
|
||||
});
|
||||
|
||||
test('get token account balance', async () => {
|
||||
const balance = (await connection.getTokenAccountBalance(testTokenAccount))
|
||||
.value;
|
||||
expect(balance.amount).toEqual('11110');
|
||||
expect(balance.decimals).toEqual(2);
|
||||
expect(balance.uiAmount).toEqual(111.1);
|
||||
|
||||
await expect(
|
||||
connection.getTokenAccountBalance(newAccount),
|
||||
).rejects.toThrow();
|
||||
});
|
||||
|
||||
test('get token accounts by owner', async () => {
|
||||
const accountsWithMintFilter = (
|
||||
await connection.getTokenAccountsByOwner(testOwner.publicKey, {
|
||||
mint: testToken.publicKey,
|
||||
})
|
||||
).value;
|
||||
expect(accountsWithMintFilter.length).toEqual(2);
|
||||
|
||||
const accountsWithProgramFilter = (
|
||||
await connection.getTokenAccountsByOwner(testOwner.publicKey, {
|
||||
programId: TOKEN_PROGRAM_ID,
|
||||
})
|
||||
).value;
|
||||
expect(accountsWithProgramFilter.length).toEqual(3);
|
||||
|
||||
const noAccounts = (
|
||||
await connection.getTokenAccountsByOwner(newAccount, {
|
||||
mint: testToken.publicKey,
|
||||
})
|
||||
).value;
|
||||
expect(noAccounts.length).toEqual(0);
|
||||
|
||||
await expect(
|
||||
connection.getTokenAccountsByOwner(testOwner.publicKey, {
|
||||
mint: newAccount,
|
||||
}),
|
||||
).rejects.toThrow();
|
||||
|
||||
await expect(
|
||||
connection.getTokenAccountsByOwner(testOwner.publicKey, {
|
||||
programId: newAccount,
|
||||
}),
|
||||
).rejects.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
test('get largest accounts', async () => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user