feat: add filters to getProgramAccounts and getParsedProgramAccounts (#16448)
* feat: add filters to getProgramAccounts and getParsedProgramAccounts * fix: documentation edits * fix: make connection interface match existing interface
This commit is contained in:
parent
c63a208488
commit
7e3db1dedb
|
@ -1368,6 +1368,63 @@ export type StakeActivationData = {
|
|||
inactive: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* Data slice argument for getProgramAccounts
|
||||
*/
|
||||
export type DataSlice = {
|
||||
/** offset of data slice */
|
||||
offset: number;
|
||||
/** length of data slice */
|
||||
length: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* Memory comparison filter for getProgramAccounts
|
||||
*/
|
||||
export type MemcmpFilter = {
|
||||
memcmp: {
|
||||
/** offset into program account data to start comparison */
|
||||
offset: number;
|
||||
/** data to match, as base-58 encoded string and limited to less than 129 bytes */
|
||||
bytes: string;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Data size comparison filter for getProgramAccounts
|
||||
*/
|
||||
export type DataSizeFilter = {
|
||||
/** Size of data for program account data length comparison */
|
||||
dataSize: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* A filter object for getProgramAccounts
|
||||
*/
|
||||
export type GetProgramAccountsFilter = MemcmpFilter | DataSizeFilter;
|
||||
|
||||
/**
|
||||
* Configuration object for getProgramAccounts requests
|
||||
*/
|
||||
export type GetProgramAccountsConfig = {
|
||||
/** Optional commitment level */
|
||||
commitment?: Commitment;
|
||||
/** Optional encoding for account data (default base64) */
|
||||
encoding?: 'base64' | 'jsonParsed';
|
||||
/** Optional data slice to limit the returned account data */
|
||||
dataSlice?: DataSlice;
|
||||
/** Optional array of filters to apply to accounts */
|
||||
filters?: GetProgramAccountsFilter[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Configuration object for getParsedProgramAccounts
|
||||
*/
|
||||
export type GetParsedProgramAccountsConfig = Exclude<
|
||||
GetProgramAccountsConfig,
|
||||
'encoding' | 'dataSlice'
|
||||
>;
|
||||
|
||||
/**
|
||||
* Information describing an account
|
||||
*/
|
||||
|
@ -2080,9 +2137,34 @@ export class Connection {
|
|||
*/
|
||||
async getProgramAccounts(
|
||||
programId: PublicKey,
|
||||
commitment?: Commitment,
|
||||
configOrCommitment?: GetProgramAccountsConfig | Commitment,
|
||||
): Promise<Array<{pubkey: PublicKey; account: AccountInfo<Buffer>}>> {
|
||||
const args = this._buildArgs([programId.toBase58()], commitment, 'base64');
|
||||
const extra: Pick<GetProgramAccountsConfig, 'dataSlice' | 'filters'> = {};
|
||||
|
||||
let commitment;
|
||||
let encoding;
|
||||
if (configOrCommitment) {
|
||||
if (typeof configOrCommitment === 'string') {
|
||||
commitment = configOrCommitment;
|
||||
} else {
|
||||
commitment = configOrCommitment.commitment;
|
||||
encoding = configOrCommitment.encoding;
|
||||
|
||||
if (configOrCommitment.dataSlice) {
|
||||
extra.dataSlice = configOrCommitment.dataSlice;
|
||||
}
|
||||
if (configOrCommitment.filters) {
|
||||
extra.filters = configOrCommitment.filters;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const args = this._buildArgs(
|
||||
[programId.toBase58()],
|
||||
commitment,
|
||||
encoding || 'base64',
|
||||
extra,
|
||||
);
|
||||
const unsafeRes = await this._rpcRequest('getProgramAccounts', args);
|
||||
const res = create(unsafeRes, jsonRpcResult(array(KeyedAccountInfoResult)));
|
||||
if ('error' in res) {
|
||||
|
@ -2103,17 +2185,33 @@ export class Connection {
|
|||
*/
|
||||
async getParsedProgramAccounts(
|
||||
programId: PublicKey,
|
||||
commitment?: Commitment,
|
||||
configOrCommitment?: GetParsedProgramAccountsConfig | Commitment,
|
||||
): Promise<
|
||||
Array<{
|
||||
pubkey: PublicKey;
|
||||
account: AccountInfo<Buffer | ParsedAccountData>;
|
||||
}>
|
||||
> {
|
||||
const extra: Pick<GetParsedProgramAccountsConfig, 'filters'> = {};
|
||||
|
||||
let commitment;
|
||||
if (configOrCommitment) {
|
||||
if (typeof configOrCommitment === 'string') {
|
||||
commitment = configOrCommitment;
|
||||
} else {
|
||||
commitment = configOrCommitment.commitment;
|
||||
|
||||
if (configOrCommitment.filters) {
|
||||
extra.filters = configOrCommitment.filters;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const args = this._buildArgs(
|
||||
[programId.toBase58()],
|
||||
commitment,
|
||||
'jsonParsed',
|
||||
extra,
|
||||
);
|
||||
const unsafeRes = await this._rpcRequest('getProgramAccounts', args);
|
||||
const res = create(
|
||||
|
|
|
@ -163,6 +163,59 @@ describe('Connection', () => {
|
|||
const feeCalculator = (await helpers.recentBlockhash({connection}))
|
||||
.feeCalculator;
|
||||
|
||||
{
|
||||
await mockRpcResponse({
|
||||
method: 'getProgramAccounts',
|
||||
params: [
|
||||
programId.publicKey.toBase58(),
|
||||
{commitment: 'confirmed', encoding: 'base64'},
|
||||
],
|
||||
value: [
|
||||
{
|
||||
account: {
|
||||
data: ['', 'base64'],
|
||||
executable: false,
|
||||
lamports: LAMPORTS_PER_SOL - feeCalculator.lamportsPerSignature,
|
||||
owner: programId.publicKey.toBase58(),
|
||||
rentEpoch: 20,
|
||||
},
|
||||
pubkey: account0.publicKey.toBase58(),
|
||||
},
|
||||
{
|
||||
account: {
|
||||
data: ['', 'base64'],
|
||||
executable: false,
|
||||
lamports:
|
||||
0.5 * LAMPORTS_PER_SOL - feeCalculator.lamportsPerSignature,
|
||||
owner: programId.publicKey.toBase58(),
|
||||
rentEpoch: 20,
|
||||
},
|
||||
pubkey: account1.publicKey.toBase58(),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const programAccounts = await connection.getProgramAccounts(
|
||||
programId.publicKey,
|
||||
{
|
||||
commitment: 'confirmed',
|
||||
},
|
||||
);
|
||||
expect(programAccounts).to.have.length(2);
|
||||
programAccounts.forEach(function (keyedAccount) {
|
||||
if (keyedAccount.pubkey.equals(account0.publicKey)) {
|
||||
expect(keyedAccount.account.lamports).to.eq(
|
||||
LAMPORTS_PER_SOL - feeCalculator.lamportsPerSignature,
|
||||
);
|
||||
} else {
|
||||
expect(keyedAccount.pubkey).to.eql(account1.publicKey);
|
||||
expect(keyedAccount.account.lamports).to.eq(
|
||||
0.5 * LAMPORTS_PER_SOL - feeCalculator.lamportsPerSignature,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
await mockRpcResponse({
|
||||
method: 'getProgramAccounts',
|
||||
|
@ -214,6 +267,95 @@ describe('Connection', () => {
|
|||
});
|
||||
}
|
||||
|
||||
{
|
||||
await mockRpcResponse({
|
||||
method: 'getProgramAccounts',
|
||||
params: [
|
||||
programId.publicKey.toBase58(),
|
||||
{
|
||||
commitment: 'confirmed',
|
||||
encoding: 'base64',
|
||||
filters: [
|
||||
{
|
||||
dataSize: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
value: [
|
||||
{
|
||||
account: {
|
||||
data: ['', 'base64'],
|
||||
executable: false,
|
||||
lamports: LAMPORTS_PER_SOL - feeCalculator.lamportsPerSignature,
|
||||
owner: programId.publicKey.toBase58(),
|
||||
rentEpoch: 20,
|
||||
},
|
||||
pubkey: account0.publicKey.toBase58(),
|
||||
},
|
||||
{
|
||||
account: {
|
||||
data: ['', 'base64'],
|
||||
executable: false,
|
||||
lamports:
|
||||
0.5 * LAMPORTS_PER_SOL - feeCalculator.lamportsPerSignature,
|
||||
owner: programId.publicKey.toBase58(),
|
||||
rentEpoch: 20,
|
||||
},
|
||||
pubkey: account1.publicKey.toBase58(),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const programAccountsDoMatchFilter = await connection.getProgramAccounts(
|
||||
programId.publicKey,
|
||||
{
|
||||
commitment: 'confirmed',
|
||||
encoding: 'base64',
|
||||
filters: [{dataSize: 0}],
|
||||
},
|
||||
);
|
||||
expect(programAccountsDoMatchFilter).to.have.length(2);
|
||||
}
|
||||
|
||||
{
|
||||
await mockRpcResponse({
|
||||
method: 'getProgramAccounts',
|
||||
params: [
|
||||
programId.publicKey.toBase58(),
|
||||
{
|
||||
commitment: 'confirmed',
|
||||
encoding: 'base64',
|
||||
filters: [
|
||||
{
|
||||
memcmp: {
|
||||
offset: 0,
|
||||
bytes: 'XzdZ3w',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
value: [],
|
||||
});
|
||||
|
||||
const programAccountsDontMatchFilter = await connection.getProgramAccounts(
|
||||
programId.publicKey,
|
||||
{
|
||||
commitment: 'confirmed',
|
||||
filters: [
|
||||
{
|
||||
memcmp: {
|
||||
offset: 0,
|
||||
bytes: 'XzdZ3w',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
);
|
||||
expect(programAccountsDontMatchFilter).to.have.length(0);
|
||||
}
|
||||
|
||||
{
|
||||
await mockRpcResponse({
|
||||
method: 'getProgramAccounts',
|
||||
|
@ -248,7 +390,9 @@ describe('Connection', () => {
|
|||
|
||||
const programAccounts = await connection.getParsedProgramAccounts(
|
||||
programId.publicKey,
|
||||
'confirmed',
|
||||
{
|
||||
commitment: 'confirmed',
|
||||
},
|
||||
);
|
||||
expect(programAccounts).to.have.length(2);
|
||||
|
||||
|
@ -265,6 +409,94 @@ describe('Connection', () => {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
await mockRpcResponse({
|
||||
method: 'getProgramAccounts',
|
||||
params: [
|
||||
programId.publicKey.toBase58(),
|
||||
{
|
||||
commitment: 'confirmed',
|
||||
encoding: 'jsonParsed',
|
||||
filters: [
|
||||
{
|
||||
dataSize: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
value: [],
|
||||
});
|
||||
|
||||
const programAccountsDontMatchFilter = await connection.getParsedProgramAccounts(
|
||||
programId.publicKey,
|
||||
{
|
||||
commitment: 'confirmed',
|
||||
filters: [{dataSize: 2}],
|
||||
},
|
||||
);
|
||||
expect(programAccountsDontMatchFilter).to.have.length(0);
|
||||
}
|
||||
|
||||
{
|
||||
await mockRpcResponse({
|
||||
method: 'getProgramAccounts',
|
||||
params: [
|
||||
programId.publicKey.toBase58(),
|
||||
{
|
||||
commitment: 'confirmed',
|
||||
encoding: 'jsonParsed',
|
||||
filters: [
|
||||
{
|
||||
memcmp: {
|
||||
offset: 0,
|
||||
bytes: '',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
value: [
|
||||
{
|
||||
account: {
|
||||
data: ['', 'base64'],
|
||||
executable: false,
|
||||
lamports: LAMPORTS_PER_SOL - feeCalculator.lamportsPerSignature,
|
||||
owner: programId.publicKey.toBase58(),
|
||||
rentEpoch: 20,
|
||||
},
|
||||
pubkey: account0.publicKey.toBase58(),
|
||||
},
|
||||
{
|
||||
account: {
|
||||
data: ['', 'base64'],
|
||||
executable: false,
|
||||
lamports:
|
||||
0.5 * LAMPORTS_PER_SOL - feeCalculator.lamportsPerSignature,
|
||||
owner: programId.publicKey.toBase58(),
|
||||
rentEpoch: 20,
|
||||
},
|
||||
pubkey: account1.publicKey.toBase58(),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const programAccountsDoMatchFilter = await connection.getParsedProgramAccounts(
|
||||
programId.publicKey,
|
||||
{
|
||||
commitment: 'confirmed',
|
||||
filters: [
|
||||
{
|
||||
memcmp: {
|
||||
offset: 0,
|
||||
bytes: '',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
);
|
||||
expect(programAccountsDoMatchFilter).to.have.length(2);
|
||||
}
|
||||
});
|
||||
|
||||
it('get balance', async () => {
|
||||
|
|
Loading…
Reference in New Issue