feat: add parsed account data APIs
This commit is contained in:
parent
b36e60738e
commit
c7a2fbe7eb
|
@ -1,6 +1,7 @@
|
|||
declare module 'superstruct' {
|
||||
declare type StructFunc = {
|
||||
(any): any,
|
||||
object(schema: any): any;
|
||||
union(schema: any): any;
|
||||
array(schema: any): any;
|
||||
literal(schema: any): any;
|
||||
|
|
|
@ -104,16 +104,16 @@ declare module '@solana/web3.js' {
|
|||
feeCalculator: FeeCalculator;
|
||||
};
|
||||
|
||||
export type PublicKeyAndAccount = {
|
||||
export type PublicKeyAndAccount<T> = {
|
||||
pubkey: PublicKey;
|
||||
account: AccountInfo;
|
||||
account: AccountInfo<T>;
|
||||
};
|
||||
|
||||
export type AccountInfo = {
|
||||
export type AccountInfo<T> = {
|
||||
executable: boolean;
|
||||
owner: PublicKey;
|
||||
lamports: number;
|
||||
data: Buffer;
|
||||
data: T;
|
||||
rentEpoch?: number;
|
||||
};
|
||||
|
||||
|
@ -181,9 +181,14 @@ declare module '@solana/web3.js' {
|
|||
meta: ConfirmedTransactionMeta | null;
|
||||
};
|
||||
|
||||
export type ParsedAccountData = {
|
||||
program: string;
|
||||
parsed: any;
|
||||
};
|
||||
|
||||
export type KeyedAccountInfo = {
|
||||
accountId: PublicKey;
|
||||
accountInfo: AccountInfo;
|
||||
accountInfo: AccountInfo<Buffer>;
|
||||
};
|
||||
|
||||
export type Version = {
|
||||
|
@ -210,7 +215,7 @@ declare module '@solana/web3.js' {
|
|||
};
|
||||
|
||||
export type AccountChangeCallback = (
|
||||
accountInfo: AccountInfo,
|
||||
accountInfo: AccountInfo<Buffer>,
|
||||
context: Context,
|
||||
) => void;
|
||||
export type ProgramAccountChangeCallback = (
|
||||
|
@ -280,15 +285,25 @@ declare module '@solana/web3.js' {
|
|||
getAccountInfoAndContext(
|
||||
publicKey: PublicKey,
|
||||
commitment?: Commitment,
|
||||
): Promise<RpcResponseAndContext<AccountInfo | null>>;
|
||||
): Promise<RpcResponseAndContext<AccountInfo<Buffer> | null>>;
|
||||
getAccountInfo(
|
||||
publicKey: PublicKey,
|
||||
commitment?: Commitment,
|
||||
): Promise<AccountInfo | null>;
|
||||
): Promise<AccountInfo<Buffer> | null>;
|
||||
getParsedAccountInfo(
|
||||
publicKey: PublicKey,
|
||||
commitment?: Commitment,
|
||||
): Promise<
|
||||
RpcResponseAndContext<AccountInfo<Buffer | ParsedAccountData> | null>
|
||||
>;
|
||||
getProgramAccounts(
|
||||
programId: PublicKey,
|
||||
commitment?: Commitment,
|
||||
): Promise<Array<PublicKeyAndAccount>>;
|
||||
): Promise<Array<PublicKeyAndAccount<Buffer>>>;
|
||||
getParsedProgramAccounts(
|
||||
programId: PublicKey,
|
||||
commitment?: Commitment,
|
||||
): Promise<Array<PublicKeyAndAccount<Buffer | ParsedAccountData>>>;
|
||||
getBalanceAndContext(
|
||||
publicKey: PublicKey,
|
||||
commitment?: Commitment,
|
||||
|
@ -311,7 +326,18 @@ declare module '@solana/web3.js' {
|
|||
filter: TokenAccountsFilter,
|
||||
commitment?: Commitment,
|
||||
): Promise<
|
||||
RpcResponseAndContext<Array<{pubkey: PublicKey; account: AccountInfo}>>
|
||||
RpcResponseAndContext<
|
||||
Array<{pubkey: PublicKey; account: AccountInfo<Buffer>}>
|
||||
>
|
||||
>;
|
||||
getParsedTokenAccountsByOwner(
|
||||
ownerAddress: PublicKey,
|
||||
filter: TokenAccountsFilter,
|
||||
commitment?: Commitment,
|
||||
): Promise<
|
||||
RpcResponseAndContext<
|
||||
Array<{pubkey: PublicKey; account: AccountInfo<ParsedAccountData>}>
|
||||
>
|
||||
>;
|
||||
getLargestAccounts(
|
||||
config?: GetLargestAccountsConfig,
|
||||
|
|
|
@ -125,16 +125,16 @@ declare module '@solana/web3.js' {
|
|||
feeCalculator: FeeCalculator,
|
||||
};
|
||||
|
||||
declare export type PublicKeyAndAccount = {
|
||||
declare export type PublicKeyAndAccount<T> = {
|
||||
pubkey: PublicKey,
|
||||
account: AccountInfo,
|
||||
account: AccountInfo<T>,
|
||||
};
|
||||
|
||||
declare export type AccountInfo = {
|
||||
declare export type AccountInfo<T> = {
|
||||
executable: boolean,
|
||||
owner: PublicKey,
|
||||
lamports: number,
|
||||
data: Buffer,
|
||||
data: T,
|
||||
rentEpoch: number | null,
|
||||
};
|
||||
|
||||
|
@ -169,6 +169,11 @@ declare module '@solana/web3.js' {
|
|||
meta: ConfirmedTransactionMeta | null,
|
||||
};
|
||||
|
||||
declare export type ParsedAccountData = {
|
||||
program: string,
|
||||
parsed: any,
|
||||
};
|
||||
|
||||
declare export type ParsedMessageAccount = {
|
||||
pubkey: PublicKey,
|
||||
signer: boolean,
|
||||
|
@ -204,7 +209,7 @@ declare module '@solana/web3.js' {
|
|||
|
||||
declare export type KeyedAccountInfo = {
|
||||
accountId: PublicKey,
|
||||
accountInfo: AccountInfo,
|
||||
accountInfo: AccountInfo<Buffer>,
|
||||
};
|
||||
|
||||
declare export type Version = {
|
||||
|
@ -231,7 +236,7 @@ declare module '@solana/web3.js' {
|
|||
};
|
||||
|
||||
declare type AccountChangeCallback = (
|
||||
accountInfo: AccountInfo,
|
||||
accountInfo: AccountInfo<Buffer>,
|
||||
context: Context,
|
||||
) => void;
|
||||
declare type ProgramAccountChangeCallback = (
|
||||
|
@ -301,15 +306,25 @@ declare module '@solana/web3.js' {
|
|||
getAccountInfoAndContext(
|
||||
publicKey: PublicKey,
|
||||
commitment: ?Commitment,
|
||||
): Promise<RpcResponseAndContext<AccountInfo | null>>;
|
||||
): Promise<RpcResponseAndContext<AccountInfo<Buffer> | null>>;
|
||||
getAccountInfo(
|
||||
publicKey: PublicKey,
|
||||
commitment: ?Commitment,
|
||||
): Promise<AccountInfo | null>;
|
||||
): Promise<AccountInfo<Buffer> | null>;
|
||||
getParsedAccountInfo(
|
||||
publicKey: PublicKey,
|
||||
commitment: ?Commitment,
|
||||
): Promise<
|
||||
RpcResponseAndContext<AccountInfo<Buffer | ParsedAccountData> | null>,
|
||||
>;
|
||||
getProgramAccounts(
|
||||
programId: PublicKey,
|
||||
commitment: ?Commitment,
|
||||
): Promise<Array<PublicKeyAndAccount>>;
|
||||
): Promise<Array<PublicKeyAndAccount<Buffer>>>;
|
||||
getParsedProgramAccounts(
|
||||
programId: PublicKey,
|
||||
commitment: ?Commitment,
|
||||
): Promise<Array<PublicKeyAndAccount<Buffer | ParsedAccountData>>>;
|
||||
getBalanceAndContext(
|
||||
publicKey: PublicKey,
|
||||
commitment: ?Commitment,
|
||||
|
@ -332,7 +347,9 @@ declare module '@solana/web3.js' {
|
|||
filter: TokenAccountsFilter,
|
||||
commitment: ?Commitment,
|
||||
): Promise<
|
||||
RpcResponseAndContext<Array<{pubkey: PublicKey, account: AccountInfo}>>,
|
||||
RpcResponseAndContext<
|
||||
Array<{pubkey: PublicKey, account: AccountInfo<Buffer>}>,
|
||||
>,
|
||||
>;
|
||||
getLargestAccounts(
|
||||
config: ?GetLargestAccountsConfig,
|
||||
|
|
|
@ -25,12 +25,12 @@ 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
|
||||
|
@ -634,13 +634,34 @@ const GetTokenSupplyRpcResult = jsonRpcResultAndContext(TokenAmountResult);
|
|||
*/
|
||||
const GetTokenAccountsByOwner = jsonRpcResultAndContext(
|
||||
struct.array([
|
||||
struct({
|
||||
struct.object({
|
||||
pubkey: 'string',
|
||||
account: struct({
|
||||
account: struct.object({
|
||||
executable: 'boolean',
|
||||
owner: 'string',
|
||||
lamports: 'number',
|
||||
data: 'any',
|
||||
data: 'string',
|
||||
rentEpoch: 'number?',
|
||||
}),
|
||||
}),
|
||||
]),
|
||||
);
|
||||
|
||||
/**
|
||||
* Expected JSON RPC response for the "getTokenAccountsByOwner" message with parsed data
|
||||
*/
|
||||
const GetParsedTokenAccountsByOwner = jsonRpcResultAndContext(
|
||||
struct.array([
|
||||
struct.object({
|
||||
pubkey: 'string',
|
||||
account: struct.object({
|
||||
executable: 'boolean',
|
||||
owner: 'string',
|
||||
lamports: 'number',
|
||||
data: struct.object({
|
||||
program: 'string',
|
||||
parsed: 'any',
|
||||
}),
|
||||
rentEpoch: 'number?',
|
||||
}),
|
||||
}),
|
||||
|
@ -692,6 +713,23 @@ const AccountInfoResult = struct({
|
|||
rentEpoch: 'number?',
|
||||
});
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
const ParsedAccountInfoResult = struct.object({
|
||||
executable: 'boolean',
|
||||
owner: 'string',
|
||||
lamports: 'number',
|
||||
data: struct.union([
|
||||
'string',
|
||||
struct.object({
|
||||
program: 'string',
|
||||
parsed: 'any',
|
||||
}),
|
||||
]),
|
||||
rentEpoch: 'number?',
|
||||
});
|
||||
|
||||
/**
|
||||
* Expected JSON RPC response for the "getAccountInfo" message
|
||||
*/
|
||||
|
@ -699,6 +737,13 @@ const GetAccountInfoAndContextRpcResult = jsonRpcResultAndContext(
|
|||
struct.union(['null', AccountInfoResult]),
|
||||
);
|
||||
|
||||
/**
|
||||
* Expected JSON RPC response for the "getAccountInfo" message with jsonParsed param
|
||||
*/
|
||||
const GetParsedAccountInfoResult = jsonRpcResultAndContext(
|
||||
struct.union(['null', ParsedAccountInfoResult]),
|
||||
);
|
||||
|
||||
/**
|
||||
* Expected JSON RPC response for the "getConfirmedSignaturesForAddress" message
|
||||
*/
|
||||
|
@ -737,6 +782,14 @@ const ProgramAccountInfoResult = struct({
|
|||
account: AccountInfoResult,
|
||||
});
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
const ParsedProgramAccountInfoResult = struct({
|
||||
pubkey: 'string',
|
||||
account: ParsedAccountInfoResult,
|
||||
});
|
||||
|
||||
/***
|
||||
* Expected JSON RPC response for the "programNotification" message
|
||||
*/
|
||||
|
@ -785,6 +838,13 @@ const GetProgramAccountsRpcResult = jsonRpcResult(
|
|||
struct.array([ProgramAccountInfoResult]),
|
||||
);
|
||||
|
||||
/**
|
||||
* Expected JSON RPC response for the "getProgramAccounts" message
|
||||
*/
|
||||
const GetParsedProgramAccountsRpcResult = jsonRpcResult(
|
||||
struct.array([ParsedProgramAccountInfoResult]),
|
||||
);
|
||||
|
||||
/**
|
||||
* Expected JSON RPC response for the "getSlot" message
|
||||
*/
|
||||
|
@ -1051,20 +1111,32 @@ type SlotInfo = {
|
|||
root: number,
|
||||
};
|
||||
|
||||
/**
|
||||
* Parsed account data
|
||||
*
|
||||
* @typedef {Object} ParsedAccountData
|
||||
* @property {string} program Name of the program that owns this account
|
||||
* @property {any} parsed Parsed account data
|
||||
*/
|
||||
type ParsedAccountData = {
|
||||
program: string,
|
||||
parsed: any,
|
||||
};
|
||||
|
||||
/**
|
||||
* Information describing an account
|
||||
*
|
||||
* @typedef {Object} AccountInfo
|
||||
* @property {number} lamports Number of lamports assigned to the account
|
||||
* @property {PublicKey} owner Identifier of the program that owns the account
|
||||
* @property {?Buffer} data Optional data assigned to the account
|
||||
* @property {T} data Optional data assigned to the account
|
||||
* @property {boolean} executable `true` if this account's data contains a loaded program
|
||||
*/
|
||||
type AccountInfo = {
|
||||
type AccountInfo<T> = {
|
||||
executable: boolean,
|
||||
owner: PublicKey,
|
||||
lamports: number,
|
||||
data: Buffer,
|
||||
data: T,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1072,18 +1144,18 @@ type AccountInfo = {
|
|||
*
|
||||
* @typedef {Object} KeyedAccountInfo
|
||||
* @property {PublicKey} accountId
|
||||
* @property {AccountInfo} accountInfo
|
||||
* @property {AccountInfo<Buffer>} accountInfo
|
||||
*/
|
||||
type KeyedAccountInfo = {
|
||||
accountId: PublicKey,
|
||||
accountInfo: AccountInfo,
|
||||
accountInfo: AccountInfo<Buffer>,
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback function for account change notifications
|
||||
*/
|
||||
export type AccountChangeCallback = (
|
||||
accountInfo: AccountInfo,
|
||||
accountInfo: AccountInfo<Buffer>,
|
||||
context: Context,
|
||||
) => void;
|
||||
|
||||
|
@ -1450,25 +1522,23 @@ export class Connection {
|
|||
/**
|
||||
* Fetch all the token accounts owned by the specified account
|
||||
*
|
||||
* @return {Promise<RpcResponseAndContext<Array<{pubkey: PublicKey, account: AccountInfo}>>>}
|
||||
* @return {Promise<RpcResponseAndContext<Array<{pubkey: PublicKey, account: AccountInfo<Buffer>}>>>}
|
||||
*/
|
||||
async getTokenAccountsByOwner(
|
||||
ownerAddress: PublicKey,
|
||||
filter: TokenAccountsFilter,
|
||||
commitment: ?Commitment,
|
||||
): Promise<
|
||||
RpcResponseAndContext<Array<{pubkey: PublicKey, account: AccountInfo}>>,
|
||||
RpcResponseAndContext<
|
||||
Array<{pubkey: PublicKey, account: AccountInfo<Buffer>}>,
|
||||
>,
|
||||
> {
|
||||
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);
|
||||
if (filter.mint) {
|
||||
_args.push({mint: filter.mint.toBase58()});
|
||||
} else {
|
||||
_args.push({programId: filter.programId.toBase58()});
|
||||
}
|
||||
|
||||
const args = this._argsWithCommitment(_args, commitment);
|
||||
const unsafeRes = await this._rpcRequest('getTokenAccountsByOwner', args);
|
||||
|
@ -1489,7 +1559,7 @@ export class Connection {
|
|||
return {
|
||||
context,
|
||||
value: value.map(result => ({
|
||||
pubkey: result.pubkey,
|
||||
pubkey: new PublicKey(result.pubkey),
|
||||
account: {
|
||||
executable: result.account.executable,
|
||||
owner: new PublicKey(result.account.owner),
|
||||
|
@ -1500,6 +1570,57 @@ export class Connection {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch parsed token accounts owned by the specified account
|
||||
*
|
||||
* @return {Promise<RpcResponseAndContext<Array<{pubkey: PublicKey, account: AccountInfo<ParsedAccountData>}>>>}
|
||||
*/
|
||||
async getParsedTokenAccountsByOwner(
|
||||
ownerAddress: PublicKey,
|
||||
filter: TokenAccountsFilter,
|
||||
commitment: ?Commitment,
|
||||
): Promise<
|
||||
RpcResponseAndContext<
|
||||
Array<{pubkey: PublicKey, account: AccountInfo<ParsedAccountData>}>,
|
||||
>,
|
||||
> {
|
||||
let _args = [ownerAddress.toBase58()];
|
||||
if (filter.mint) {
|
||||
_args.push({mint: filter.mint.toBase58()});
|
||||
} else {
|
||||
_args.push({programId: filter.programId.toBase58()});
|
||||
}
|
||||
|
||||
const args = this._argsWithCommitment(_args, commitment, 'jsonParsed');
|
||||
const unsafeRes = await this._rpcRequest('getTokenAccountsByOwner', args);
|
||||
const res = GetParsedTokenAccountsByOwner(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 => ({
|
||||
pubkey: new PublicKey(result.pubkey),
|
||||
account: {
|
||||
executable: result.account.executable,
|
||||
owner: new PublicKey(result.account.owner),
|
||||
lamports: result.account.lamports,
|
||||
data: result.account.data,
|
||||
},
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the 20 largest accounts with their current balances
|
||||
*/
|
||||
|
@ -1530,7 +1651,7 @@ export class Connection {
|
|||
async getAccountInfoAndContext(
|
||||
publicKey: PublicKey,
|
||||
commitment: ?Commitment,
|
||||
): Promise<RpcResponseAndContext<AccountInfo | null>> {
|
||||
): Promise<RpcResponseAndContext<AccountInfo<Buffer> | null>> {
|
||||
const args = this._argsWithCommitment([publicKey.toBase58()], commitment);
|
||||
const unsafeRes = await this._rpcRequest('getAccountInfo', args);
|
||||
const res = GetAccountInfoAndContextRpcResult(unsafeRes);
|
||||
|
@ -1563,13 +1684,64 @@ export class Connection {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch parsed account info for the specified public key
|
||||
*/
|
||||
async getParsedAccountInfo(
|
||||
publicKey: PublicKey,
|
||||
commitment: ?Commitment,
|
||||
): Promise<
|
||||
RpcResponseAndContext<AccountInfo<Buffer | ParsedAccountData> | null>,
|
||||
> {
|
||||
const args = this._argsWithCommitment(
|
||||
[publicKey.toBase58()],
|
||||
commitment,
|
||||
'jsonParsed',
|
||||
);
|
||||
const unsafeRes = await this._rpcRequest('getAccountInfo', args);
|
||||
const res = GetParsedAccountInfoResult(unsafeRes);
|
||||
if (res.error) {
|
||||
throw new Error(
|
||||
'failed to get info about account ' +
|
||||
publicKey.toBase58() +
|
||||
': ' +
|
||||
res.error.message,
|
||||
);
|
||||
}
|
||||
assert(typeof res.result !== 'undefined');
|
||||
|
||||
let value = null;
|
||||
if (res.result.value) {
|
||||
const {executable, owner, lamports, data: resultData} = res.result.value;
|
||||
|
||||
let data = resultData;
|
||||
if (!data.program) {
|
||||
data = bs58.decode(data);
|
||||
}
|
||||
|
||||
value = {
|
||||
executable,
|
||||
owner: new PublicKey(owner),
|
||||
lamports,
|
||||
data,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
context: {
|
||||
slot: res.result.context.slot,
|
||||
},
|
||||
value,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch all the account info for the specified public key
|
||||
*/
|
||||
async getAccountInfo(
|
||||
publicKey: PublicKey,
|
||||
commitment: ?Commitment,
|
||||
): Promise<AccountInfo | null> {
|
||||
): Promise<AccountInfo<Buffer> | null> {
|
||||
return await this.getAccountInfoAndContext(publicKey, commitment)
|
||||
.then(x => x.value)
|
||||
.catch(e => {
|
||||
|
@ -1582,12 +1754,12 @@ export class Connection {
|
|||
/**
|
||||
* Fetch all the accounts owned by the specified program id
|
||||
*
|
||||
* @return {Promise<Array<{pubkey: PublicKey, account: AccountInfo}>>}
|
||||
* @return {Promise<Array<{pubkey: PublicKey, account: AccountInfo<Buffer>}>>}
|
||||
*/
|
||||
async getProgramAccounts(
|
||||
programId: PublicKey,
|
||||
commitment: ?Commitment,
|
||||
): Promise<Array<{pubkey: PublicKey, account: AccountInfo}>> {
|
||||
): Promise<Array<{pubkey: PublicKey, account: AccountInfo<Buffer>}>> {
|
||||
const args = this._argsWithCommitment([programId.toBase58()], commitment);
|
||||
const unsafeRes = await this._rpcRequest('getProgramAccounts', args);
|
||||
const res = GetProgramAccountsRpcResult(unsafeRes);
|
||||
|
@ -1605,7 +1777,7 @@ export class Connection {
|
|||
|
||||
return result.map(result => {
|
||||
return {
|
||||
pubkey: result.pubkey,
|
||||
pubkey: new PublicKey(result.pubkey),
|
||||
account: {
|
||||
executable: result.account.executable,
|
||||
owner: new PublicKey(result.account.owner),
|
||||
|
@ -1616,6 +1788,59 @@ export class Connection {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch and parse all the accounts owned by the specified program id
|
||||
*
|
||||
* @return {Promise<Array<{pubkey: PublicKey, account: AccountInfo<Buffer | ParsedAccountData>}>>}
|
||||
*/
|
||||
async getParsedProgramAccounts(
|
||||
programId: PublicKey,
|
||||
commitment: ?Commitment,
|
||||
): Promise<
|
||||
Array<{
|
||||
pubkey: PublicKey,
|
||||
account: AccountInfo<Buffer | ParsedAccountData>,
|
||||
}>,
|
||||
> {
|
||||
const args = this._argsWithCommitment(
|
||||
[programId.toBase58()],
|
||||
commitment,
|
||||
'jsonParsed',
|
||||
);
|
||||
const unsafeRes = await this._rpcRequest('getProgramAccounts', args);
|
||||
const res = GetParsedProgramAccountsRpcResult(unsafeRes);
|
||||
if (res.error) {
|
||||
throw new Error(
|
||||
'failed to get accounts owned by program ' +
|
||||
programId.toBase58() +
|
||||
': ' +
|
||||
res.error.message,
|
||||
);
|
||||
}
|
||||
|
||||
const {result} = res;
|
||||
assert(typeof result !== 'undefined');
|
||||
|
||||
return result.map(result => {
|
||||
const resultData = result.account.data;
|
||||
|
||||
let data = resultData;
|
||||
if (!data.program) {
|
||||
data = bs58.decode(data);
|
||||
}
|
||||
|
||||
return {
|
||||
pubkey: new PublicKey(result.pubkey),
|
||||
account: {
|
||||
executable: result.account.executable,
|
||||
owner: new PublicKey(result.account.owner),
|
||||
lamports: result.account.lamports,
|
||||
data,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm the transaction identified by the specified signature
|
||||
*/
|
||||
|
@ -2625,10 +2850,21 @@ export class Connection {
|
|||
}
|
||||
}
|
||||
|
||||
_argsWithCommitment(args: Array<any>, override: ?Commitment): Array<any> {
|
||||
_argsWithCommitment(
|
||||
args: Array<any>,
|
||||
override: ?Commitment,
|
||||
encoding?: 'jsonParsed',
|
||||
): Array<any> {
|
||||
const commitment = override || this._commitment;
|
||||
if (commitment) {
|
||||
args.push({commitment});
|
||||
if (commitment || encoding) {
|
||||
let options: any = {};
|
||||
if (encoding) {
|
||||
options.encoding = encoding;
|
||||
}
|
||||
if (commitment) {
|
||||
options.commitment = commitment;
|
||||
}
|
||||
args.push(options);
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
|
|
@ -77,6 +77,12 @@ test('get account info - not found', async () => {
|
|||
]);
|
||||
|
||||
expect(await connection.getAccountInfo(account.publicKey)).toBeNull();
|
||||
|
||||
if (!mockRpcEnabled) {
|
||||
expect(
|
||||
(await connection.getParsedAccountInfo(account.publicKey)).value,
|
||||
).toBeNull();
|
||||
}
|
||||
});
|
||||
|
||||
test('get program accounts', async () => {
|
||||
|
@ -282,20 +288,39 @@ test('get program accounts', async () => {
|
|||
expect(programAccounts.length).toBe(2);
|
||||
|
||||
programAccounts.forEach(function (element) {
|
||||
expect([
|
||||
account0.publicKey.toBase58(),
|
||||
account1.publicKey.toBase58(),
|
||||
]).toEqual(expect.arrayContaining([element.pubkey]));
|
||||
if (element.pubkey == account0.publicKey) {
|
||||
if (element.pubkey.equals(account0.publicKey)) {
|
||||
expect(element.account.lamports).toBe(
|
||||
LAMPORTS_PER_SOL - feeCalculator.lamportsPerSignature,
|
||||
);
|
||||
} else {
|
||||
} else if (element.pubkey.equals(account1.publicKey)) {
|
||||
expect(element.account.lamports).toBe(
|
||||
0.5 * LAMPORTS_PER_SOL - feeCalculator.lamportsPerSignature,
|
||||
);
|
||||
} else {
|
||||
expect(element.pubkey.equals(account1.publicKey)).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
if (!mockRpcEnabled) {
|
||||
const programAccounts = await connection.getParsedProgramAccounts(
|
||||
programId.publicKey,
|
||||
);
|
||||
expect(programAccounts.length).toBe(2);
|
||||
|
||||
programAccounts.forEach(function (element) {
|
||||
if (element.pubkey.equals(account0.publicKey)) {
|
||||
expect(element.account.lamports).toBe(
|
||||
LAMPORTS_PER_SOL - feeCalculator.lamportsPerSignature,
|
||||
);
|
||||
} else if (element.pubkey.equals(account1.publicKey)) {
|
||||
expect(element.account.lamports).toBe(
|
||||
0.5 * LAMPORTS_PER_SOL - feeCalculator.lamportsPerSignature,
|
||||
);
|
||||
} else {
|
||||
expect(element.pubkey.equals(account1.publicKey)).toBe(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
test('validatorExit', async () => {
|
||||
|
@ -1410,6 +1435,55 @@ describe('token methods', () => {
|
|||
).rejects.toThrow();
|
||||
});
|
||||
|
||||
test('get parsed token account info', async () => {
|
||||
const accountInfo = (
|
||||
await connection.getParsedAccountInfo(testTokenAccount)
|
||||
).value;
|
||||
if (accountInfo) {
|
||||
const data = accountInfo.data;
|
||||
if (data instanceof Buffer) {
|
||||
expect(data instanceof Buffer).toBe(false);
|
||||
} else {
|
||||
expect(data.program).toEqual('spl-token');
|
||||
expect(data.parsed).toBeTruthy();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('get parsed token program accounts', async () => {
|
||||
const tokenAccounts = await connection.getParsedProgramAccounts(
|
||||
TOKEN_PROGRAM_ID,
|
||||
);
|
||||
tokenAccounts.forEach(({account}) => {
|
||||
expect(account.owner.equals(TOKEN_PROGRAM_ID)).toBe(true);
|
||||
const data = account.data;
|
||||
if (data instanceof Buffer) {
|
||||
expect(data instanceof Buffer).toBe(false);
|
||||
} else {
|
||||
expect(data.parsed).toBeTruthy();
|
||||
expect(data.program).toEqual('spl-token');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('get parsed token accounts by owner', async () => {
|
||||
const tokenAccounts = (
|
||||
await connection.getParsedTokenAccountsByOwner(testOwner.publicKey, {
|
||||
mint: testToken.publicKey,
|
||||
})
|
||||
).value;
|
||||
tokenAccounts.forEach(({account}) => {
|
||||
expect(account.owner.equals(TOKEN_PROGRAM_ID)).toBe(true);
|
||||
const data = account.data;
|
||||
if (data instanceof Buffer) {
|
||||
expect(data instanceof Buffer).toBe(false);
|
||||
} else {
|
||||
expect(data.parsed).toBeTruthy();
|
||||
expect(data.program).toEqual('spl-token');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('get token accounts by owner', async () => {
|
||||
const accountsWithMintFilter = (
|
||||
await connection.getTokenAccountsByOwner(testOwner.publicKey, {
|
||||
|
@ -1611,6 +1685,45 @@ test('request airdrop', async () => {
|
|||
expect(accountInfo.lamports).toBe(minimumAmount + 42);
|
||||
expect(accountInfo.data).toHaveLength(0);
|
||||
expect(accountInfo.owner).toEqual(SystemProgram.programId);
|
||||
|
||||
mockRpc.push([
|
||||
url,
|
||||
{
|
||||
method: 'getAccountInfo',
|
||||
params: [
|
||||
account.publicKey.toBase58(),
|
||||
{commitment: 'recent', encoding: 'jsonParsed'},
|
||||
],
|
||||
},
|
||||
{
|
||||
error: null,
|
||||
result: {
|
||||
context: {
|
||||
slot: 11,
|
||||
},
|
||||
value: {
|
||||
owner: '11111111111111111111111111111111',
|
||||
lamports: minimumAmount + 42,
|
||||
data: '',
|
||||
executable: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const parsedAccountInfo = (
|
||||
await connection.getParsedAccountInfo(account.publicKey)
|
||||
).value;
|
||||
if (parsedAccountInfo === null) {
|
||||
expect(parsedAccountInfo).not.toBeNull();
|
||||
return;
|
||||
} else if (parsedAccountInfo.data.parsed) {
|
||||
expect(parsedAccountInfo.data.parsed).not.toBeTruthy();
|
||||
return;
|
||||
}
|
||||
expect(parsedAccountInfo.lamports).toBe(minimumAmount + 42);
|
||||
expect(parsedAccountInfo.data).toHaveLength(0);
|
||||
expect(parsedAccountInfo.owner).toEqual(SystemProgram.programId);
|
||||
});
|
||||
|
||||
test('transaction failure', async () => {
|
||||
|
|
Loading…
Reference in New Issue