mirror of https://github.com/certusone/oyster.git
chore: unify account fetching api
This commit is contained in:
parent
cb137c1e8b
commit
fe7bda34d8
|
@ -1,6 +1,6 @@
|
||||||
import { PublicKey } from '@solana/web3.js';
|
import { PublicKey } from '@solana/web3.js';
|
||||||
import * as bs58 from 'bs58';
|
|
||||||
import { deserializeBorsh, ParsedAccount } from '@oyster/common';
|
import { ParsedAccount } from '@oyster/common';
|
||||||
import { GOVERNANCE_SCHEMA } from './serialisation';
|
import { GOVERNANCE_SCHEMA } from './serialisation';
|
||||||
import {
|
import {
|
||||||
GovernanceAccount,
|
GovernanceAccount,
|
||||||
|
@ -9,14 +9,14 @@ import {
|
||||||
Realm,
|
Realm,
|
||||||
} from './accounts';
|
} from './accounts';
|
||||||
|
|
||||||
import { MemcmpFilter, RpcContext } from './core/api';
|
import { getBorshProgramAccounts, MemcmpFilter, RpcContext } from './core/api';
|
||||||
|
|
||||||
export async function getRealms(rpcContext: RpcContext) {
|
export async function getRealms(rpcContext: RpcContext) {
|
||||||
return getGovernanceAccountsImpl<Realm>(
|
return getBorshProgramAccounts<Realm>(
|
||||||
rpcContext.programId,
|
rpcContext.programId,
|
||||||
|
GOVERNANCE_SCHEMA,
|
||||||
rpcContext.endpoint,
|
rpcContext.endpoint,
|
||||||
Realm,
|
Realm,
|
||||||
GovernanceAccountType.Realm,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,23 +28,25 @@ export async function getGovernanceAccounts<TAccount extends GovernanceAccount>(
|
||||||
filters: MemcmpFilter[] = [],
|
filters: MemcmpFilter[] = [],
|
||||||
) {
|
) {
|
||||||
if (accountTypes.length === 1) {
|
if (accountTypes.length === 1) {
|
||||||
return getGovernanceAccountsImpl<TAccount>(
|
return getBorshProgramAccounts<TAccount>(
|
||||||
programId,
|
programId,
|
||||||
|
GOVERNANCE_SCHEMA,
|
||||||
endpoint,
|
endpoint,
|
||||||
accountClass,
|
accountClass as any,
|
||||||
accountTypes[0],
|
|
||||||
filters,
|
filters,
|
||||||
|
accountTypes[0],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const all = await Promise.all(
|
const all = await Promise.all(
|
||||||
accountTypes.map(at =>
|
accountTypes.map(at =>
|
||||||
getGovernanceAccountsImpl<TAccount>(
|
getBorshProgramAccounts<TAccount>(
|
||||||
programId,
|
programId,
|
||||||
|
GOVERNANCE_SCHEMA,
|
||||||
endpoint,
|
endpoint,
|
||||||
accountClass,
|
accountClass as any,
|
||||||
at,
|
|
||||||
filters,
|
filters,
|
||||||
|
at,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -54,66 +56,3 @@ export async function getGovernanceAccounts<TAccount extends GovernanceAccount>(
|
||||||
ParsedAccount<TAccount>
|
ParsedAccount<TAccount>
|
||||||
>;
|
>;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getGovernanceAccountsImpl<TAccount extends GovernanceAccount>(
|
|
||||||
programId: PublicKey,
|
|
||||||
endpoint: string,
|
|
||||||
accountClass: GovernanceAccountClass,
|
|
||||||
accountType: GovernanceAccountType,
|
|
||||||
filters: MemcmpFilter[] = [],
|
|
||||||
) {
|
|
||||||
let getProgramAccounts = await fetch(endpoint, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
jsonrpc: '2.0',
|
|
||||||
id: 1,
|
|
||||||
method: 'getProgramAccounts',
|
|
||||||
params: [
|
|
||||||
programId.toBase58(),
|
|
||||||
{
|
|
||||||
commitment: 'single',
|
|
||||||
encoding: 'base64',
|
|
||||||
filters: [
|
|
||||||
{
|
|
||||||
memcmp: {
|
|
||||||
offset: 0,
|
|
||||||
bytes: bs58.encode([accountType]),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
...filters.map(f => ({
|
|
||||||
memcmp: { offset: f.offset, bytes: bs58.encode(f.bytes) },
|
|
||||||
})),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
const rawAccounts = (await getProgramAccounts.json())['result'];
|
|
||||||
let accounts: Record<string, ParsedAccount<TAccount>> = {};
|
|
||||||
|
|
||||||
for (let rawAccount of rawAccounts) {
|
|
||||||
try {
|
|
||||||
const account = {
|
|
||||||
pubkey: new PublicKey(rawAccount.pubkey),
|
|
||||||
account: {
|
|
||||||
...rawAccount.account,
|
|
||||||
data: [], // There is no need to keep the raw data around once we deserialize it into TAccount
|
|
||||||
},
|
|
||||||
info: deserializeBorsh(
|
|
||||||
GOVERNANCE_SCHEMA,
|
|
||||||
accountClass,
|
|
||||||
Buffer.from(rawAccount.account.data[0], 'base64'),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
accounts[account.pubkey.toBase58()] = account;
|
|
||||||
} catch (ex) {
|
|
||||||
console.error(`Can't deserialize ${accountClass}`, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return accounts;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,90 +1,23 @@
|
||||||
import { PublicKey } from '@solana/web3.js';
|
import { PublicKey } from '@solana/web3.js';
|
||||||
import bs58 from 'bs58';
|
|
||||||
import { MemcmpFilter, pubkeyFilter } from '../core/api';
|
|
||||||
import {
|
import {
|
||||||
ChatMessage,
|
getBorshProgramAccounts,
|
||||||
GovernanceChatAccount,
|
MemcmpFilter,
|
||||||
GovernanceChatAccountClass,
|
pubkeyFilter,
|
||||||
GovernanceChatAccountType,
|
} from '../core/api';
|
||||||
governanceChatProgramId,
|
import { ChatMessage, governanceChatProgramId } from './accounts';
|
||||||
} from './accounts';
|
|
||||||
import { deserializeBorsh, ParsedAccount } from '@oyster/common';
|
|
||||||
import { GOVERNANCE_CHAT_SCHEMA } from './serialisation';
|
import { GOVERNANCE_CHAT_SCHEMA } from './serialisation';
|
||||||
|
|
||||||
export function getGovernanceChatMessages(
|
export function getGovernanceChatMessages(
|
||||||
endpoint: string,
|
endpoint: string,
|
||||||
proposal: PublicKey,
|
proposal: PublicKey,
|
||||||
) {
|
) {
|
||||||
return getGovernanceChatAccounts<ChatMessage>(
|
return getBorshProgramAccounts<ChatMessage>(
|
||||||
governanceChatProgramId,
|
governanceChatProgramId,
|
||||||
|
GOVERNANCE_CHAT_SCHEMA,
|
||||||
endpoint,
|
endpoint,
|
||||||
ChatMessage,
|
ChatMessage,
|
||||||
GovernanceChatAccountType.ChatMessage,
|
|
||||||
[pubkeyFilter(1, proposal) as MemcmpFilter],
|
[pubkeyFilter(1, proposal) as MemcmpFilter],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getGovernanceChatAccounts<
|
|
||||||
TAccount extends GovernanceChatAccount
|
|
||||||
>(
|
|
||||||
programId: PublicKey,
|
|
||||||
endpoint: string,
|
|
||||||
accountClass: GovernanceChatAccountClass,
|
|
||||||
accountType: GovernanceChatAccountType,
|
|
||||||
filters: MemcmpFilter[] = [],
|
|
||||||
) {
|
|
||||||
let getProgramAccounts = await fetch(endpoint, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
jsonrpc: '2.0',
|
|
||||||
id: 1,
|
|
||||||
method: 'getProgramAccounts',
|
|
||||||
params: [
|
|
||||||
programId.toBase58(),
|
|
||||||
{
|
|
||||||
commitment: 'single',
|
|
||||||
encoding: 'base64',
|
|
||||||
filters: [
|
|
||||||
{
|
|
||||||
memcmp: {
|
|
||||||
offset: 0,
|
|
||||||
bytes: bs58.encode([accountType]),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
...filters.map(f => ({
|
|
||||||
memcmp: { offset: f.offset, bytes: bs58.encode(f.bytes) },
|
|
||||||
})),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
const rawAccounts = (await getProgramAccounts.json())['result'];
|
|
||||||
let accounts: Record<string, ParsedAccount<TAccount>> = {};
|
|
||||||
|
|
||||||
for (let rawAccount of rawAccounts) {
|
|
||||||
try {
|
|
||||||
const account = {
|
|
||||||
pubkey: new PublicKey(rawAccount.pubkey),
|
|
||||||
account: {
|
|
||||||
...rawAccount.account,
|
|
||||||
data: [], // There is no need to keep the raw data around once we deserialize it into TAccount
|
|
||||||
},
|
|
||||||
info: deserializeBorsh(
|
|
||||||
GOVERNANCE_CHAT_SCHEMA,
|
|
||||||
accountClass,
|
|
||||||
Buffer.from(rawAccount.account.data[0], 'base64'),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
accounts[account.pubkey.toBase58()] = account;
|
|
||||||
} catch (ex) {
|
|
||||||
console.error(`Can't deserialize ${accountClass}`, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return accounts;
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
// Interface for accounts with type field
|
||||||
|
export interface ProgramAccountWithType {
|
||||||
|
accountType: number;
|
||||||
|
}
|
|
@ -1,5 +1,9 @@
|
||||||
import { Connection, PublicKey } from '@solana/web3.js';
|
import { Connection, PublicKey } from '@solana/web3.js';
|
||||||
import { WalletNotConnectedError } from '../errors';
|
import { WalletNotConnectedError } from '../errors';
|
||||||
|
import bs58 from 'bs58';
|
||||||
|
import { deserializeBorsh, ParsedAccount } from '@oyster/common';
|
||||||
|
import { ProgramAccountWithType } from '../core/accounts';
|
||||||
|
import { Schema } from 'borsh';
|
||||||
|
|
||||||
export interface IWallet {
|
export interface IWallet {
|
||||||
publicKey: PublicKey;
|
publicKey: PublicKey;
|
||||||
|
@ -63,3 +67,71 @@ export const pubkeyFilter = (
|
||||||
offset: number,
|
offset: number,
|
||||||
pubkey: PublicKey | undefined | null,
|
pubkey: PublicKey | undefined | null,
|
||||||
) => (!pubkey ? undefined : new MemcmpFilter(offset, pubkey.toBuffer()));
|
) => (!pubkey ? undefined : new MemcmpFilter(offset, pubkey.toBuffer()));
|
||||||
|
|
||||||
|
export async function getBorshProgramAccounts<
|
||||||
|
TAccount extends ProgramAccountWithType
|
||||||
|
>(
|
||||||
|
programId: PublicKey,
|
||||||
|
borshSchema: Schema,
|
||||||
|
endpoint: string,
|
||||||
|
accountFactory: new (args: any) => TAccount,
|
||||||
|
filters: MemcmpFilter[] = [],
|
||||||
|
accountType?: number,
|
||||||
|
) {
|
||||||
|
accountType = accountType ?? new accountFactory({}).accountType;
|
||||||
|
|
||||||
|
let getProgramAccounts = await fetch(endpoint, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
id: 1,
|
||||||
|
method: 'getProgramAccounts',
|
||||||
|
params: [
|
||||||
|
programId.toBase58(),
|
||||||
|
{
|
||||||
|
commitment: 'single',
|
||||||
|
encoding: 'base64',
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
memcmp: {
|
||||||
|
offset: 0,
|
||||||
|
bytes: bs58.encode([accountType]),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...filters.map(f => ({
|
||||||
|
memcmp: { offset: f.offset, bytes: bs58.encode(f.bytes) },
|
||||||
|
})),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
const rawAccounts = (await getProgramAccounts.json())['result'];
|
||||||
|
let accounts: { [pubKey: string]: ParsedAccount<TAccount> } = {};
|
||||||
|
|
||||||
|
for (let rawAccount of rawAccounts) {
|
||||||
|
try {
|
||||||
|
const account = {
|
||||||
|
pubkey: new PublicKey(rawAccount.pubkey),
|
||||||
|
account: {
|
||||||
|
...rawAccount.account,
|
||||||
|
data: [], // There is no need to keep the raw data around once we deserialize it into TAccount
|
||||||
|
},
|
||||||
|
info: deserializeBorsh(
|
||||||
|
borshSchema,
|
||||||
|
accountFactory,
|
||||||
|
Buffer.from(rawAccount.account.data[0], 'base64'),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
accounts[account.pubkey.toBase58()] = account;
|
||||||
|
} catch (ex) {
|
||||||
|
console.error(`Can't deserialize ${accountFactory}`, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return accounts;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue