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 * as bs58 from 'bs58';
|
||||
import { deserializeBorsh, ParsedAccount } from '@oyster/common';
|
||||
|
||||
import { ParsedAccount } from '@oyster/common';
|
||||
import { GOVERNANCE_SCHEMA } from './serialisation';
|
||||
import {
|
||||
GovernanceAccount,
|
||||
|
@ -9,14 +9,14 @@ import {
|
|||
Realm,
|
||||
} from './accounts';
|
||||
|
||||
import { MemcmpFilter, RpcContext } from './core/api';
|
||||
import { getBorshProgramAccounts, MemcmpFilter, RpcContext } from './core/api';
|
||||
|
||||
export async function getRealms(rpcContext: RpcContext) {
|
||||
return getGovernanceAccountsImpl<Realm>(
|
||||
return getBorshProgramAccounts<Realm>(
|
||||
rpcContext.programId,
|
||||
GOVERNANCE_SCHEMA,
|
||||
rpcContext.endpoint,
|
||||
Realm,
|
||||
GovernanceAccountType.Realm,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -28,23 +28,25 @@ export async function getGovernanceAccounts<TAccount extends GovernanceAccount>(
|
|||
filters: MemcmpFilter[] = [],
|
||||
) {
|
||||
if (accountTypes.length === 1) {
|
||||
return getGovernanceAccountsImpl<TAccount>(
|
||||
return getBorshProgramAccounts<TAccount>(
|
||||
programId,
|
||||
GOVERNANCE_SCHEMA,
|
||||
endpoint,
|
||||
accountClass,
|
||||
accountTypes[0],
|
||||
accountClass as any,
|
||||
filters,
|
||||
accountTypes[0],
|
||||
);
|
||||
}
|
||||
|
||||
const all = await Promise.all(
|
||||
accountTypes.map(at =>
|
||||
getGovernanceAccountsImpl<TAccount>(
|
||||
getBorshProgramAccounts<TAccount>(
|
||||
programId,
|
||||
GOVERNANCE_SCHEMA,
|
||||
endpoint,
|
||||
accountClass,
|
||||
at,
|
||||
accountClass as any,
|
||||
filters,
|
||||
at,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -54,66 +56,3 @@ export async function getGovernanceAccounts<TAccount extends GovernanceAccount>(
|
|||
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 bs58 from 'bs58';
|
||||
import { MemcmpFilter, pubkeyFilter } from '../core/api';
|
||||
|
||||
import {
|
||||
ChatMessage,
|
||||
GovernanceChatAccount,
|
||||
GovernanceChatAccountClass,
|
||||
GovernanceChatAccountType,
|
||||
governanceChatProgramId,
|
||||
} from './accounts';
|
||||
import { deserializeBorsh, ParsedAccount } from '@oyster/common';
|
||||
getBorshProgramAccounts,
|
||||
MemcmpFilter,
|
||||
pubkeyFilter,
|
||||
} from '../core/api';
|
||||
import { ChatMessage, governanceChatProgramId } from './accounts';
|
||||
|
||||
import { GOVERNANCE_CHAT_SCHEMA } from './serialisation';
|
||||
|
||||
export function getGovernanceChatMessages(
|
||||
endpoint: string,
|
||||
proposal: PublicKey,
|
||||
) {
|
||||
return getGovernanceChatAccounts<ChatMessage>(
|
||||
return getBorshProgramAccounts<ChatMessage>(
|
||||
governanceChatProgramId,
|
||||
GOVERNANCE_CHAT_SCHEMA,
|
||||
endpoint,
|
||||
ChatMessage,
|
||||
GovernanceChatAccountType.ChatMessage,
|
||||
[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 { 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 {
|
||||
publicKey: PublicKey;
|
||||
|
@ -63,3 +67,71 @@ export const pubkeyFilter = (
|
|||
offset: number,
|
||||
pubkey: PublicKey | undefined | null,
|
||||
) => (!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