import { Connection , PublicKey } from '@solana/web3.js' ; import bs58 from 'bs58' ; import { ProgramAccountWithType } from '../core/accounts' ; import { Schema } from 'borsh' ; import { getErrorMessage } from '../tools/script' ; import { ProgramAccount } from '../tools/sdk/runtime' ; import { deserializeBorsh } from '../tools/borsh' ; import { WalletNotConnectedError , WalletSigner } from '../tools/walletAdapter' ; export class RpcContext { programId : PublicKey ; programVersion : number ; wallet : WalletSigner ; connection : Connection ; endpoint : string ; constructor ( programId , programVersion , wallet , connection , endpoint ) { this . programId = programId ; this . wallet = wallet ; this . connection = connection ; this . endpoint = endpoint ; this . programVersion = programVersion ; } get walletPubkey ( ) { if ( ! this . wallet ?. publicKey ) { throw new WalletNotConnectedError ( ) ; } return this . wallet . publicKey ; } get programIdBase58 ( ) { return this . programId . toBase58 ( ) ; } } export class MemcmpFilter { offset : number ; bytes : Buffer ; constructor ( offset , bytes ) { this . offset = offset ; this . bytes = bytes ; } isMatch ( buffer ) { if ( this . offset + this . bytes . length > buffer . length ) { return false ; } for ( let i = 0 ; i < this . bytes . length ; i ++ ) { if ( this . bytes [ i ] !== buffer [ this . offset + i ] ) return false ; } return true ; } } export const pubkeyFilter = ( offset , pubkey ) => ( ! pubkey ? undefined : new MemcmpFilter ( offset , pubkey . toBuffer ( ) ) ) ; export const booleanFilter = ( offset , value ) => new MemcmpFilter ( offset , Buffer . from ( value ? [ 1 ] : [ 0 ] ) ) ; export async function getBorshProgramAccounts < TAccount extends ProgramAccountWithType > ( connection , programId , getSchema , accountFactory , filters = [ ] , accountType ? ) { accountType = accountType ?? new accountFactory ( { } ) . accountType ; const programAccounts = await connection . getProgramAccounts ( programId , { commitment : connection . commitment , filters : [ { memcmp : { offset : 0 , bytes : bs58 . encode ( [ accountType ] ) , } , } , ... filters . map ( f => ( { memcmp : { offset : f . offset , bytes : bs58 . encode ( f . bytes ) } , } ) ) , ] , } ) ; let accounts = [ ] ; for ( let rawAccount of programAccounts ) { try { const data = rawAccount . account . data ; const accountType = data [ 0 ] ; const account = { pubkey : new PublicKey ( rawAccount . pubkey ) , account : deserializeBorsh ( getSchema ( accountType ) , accountFactory , data ) , owner : rawAccount . account . owner , } ; accounts . push ( account ) ; } catch ( ex ) { console . info ( `Can't deserialize ${ accountFactory . name } @ ${ rawAccount . pubkey }.` , getErrorMessage ( ex ) ) ; } } return accounts ; }