import { decodeAccount, getAddressEncoder, getBase64Decoder, getBase64Encoder, lamports as toLamports, type Account, type Address, type Base64EncodedBytes, type Decoder, type EncodedAccount, } from "@solana/kit"; import { ADAPTOR_ADD_RECEIPT_DISCRIMINATOR, getAdaptorAddReceiptDecoder, getRequestWithdrawVaultReceiptDecoder, getStrategyInitReceiptDecoder, REQUEST_WITHDRAW_VAULT_RECEIPT_DISCRIMINATOR, STRATEGY_INIT_RECEIPT_DISCRIMINATOR, VOLTR_VAULT_PROGRAM_ADDRESS, type AdaptorAddReceipt, type RequestWithdrawVaultReceipt, type StrategyInitReceipt, } from "../generated"; import type { GetProgramAccountsRpc } from "./rpc"; const VAULT_FIELD_OFFSET = 8n; const DISCRIMINATOR_OFFSET = 0n; const base64Decoder = getBase64Decoder(); const base64Encoder = getBase64Encoder(); const addressEncoder = getAddressEncoder(); function bytesToBase64(bytes: Uint8Array): string { return base64Decoder.decode(bytes); } function base64ToBytes(base64: string): Uint8Array { return base64Encoder.encode(base64) as Uint8Array; } async function fetchAndDecodeAccountsByVault( rpc: GetProgramAccountsRpc, vault: Address, discriminator: Uint8Array, decoder: Decoder, ): Promise[]> { const results = await rpc .getProgramAccounts(VOLTR_VAULT_PROGRAM_ADDRESS, { encoding: "base64", filters: [ { memcmp: { offset: DISCRIMINATOR_OFFSET, bytes: bytesToBase64(discriminator) as Base64EncodedBytes, encoding: "base64", }, }, { memcmp: { offset: VAULT_FIELD_OFFSET, bytes: bytesToBase64( addressEncoder.encode(vault) as Uint8Array, ) as Base64EncodedBytes, encoding: "base64", }, }, ], }) .send(); return results.map(({ pubkey, account }) => { const [data] = account.data; const encoded: EncodedAccount = { address: pubkey, data: base64ToBytes(data), executable: account.executable, lamports: toLamports(BigInt(account.lamports)), programAddress: account.owner, space: BigInt(account.space), }; return decodeAccount(encoded, decoder); }); } export async function fetchAllStrategyInitReceiptAccountsOfVault( rpc: GetProgramAccountsRpc, vault: Address, ): Promise[]> { return fetchAndDecodeAccountsByVault( rpc, vault, STRATEGY_INIT_RECEIPT_DISCRIMINATOR, getStrategyInitReceiptDecoder(), ); } export async function fetchAllRequestWithdrawVaultReceiptsOfVault( rpc: GetProgramAccountsRpc, vault: Address, ): Promise[]> { return fetchAndDecodeAccountsByVault( rpc, vault, REQUEST_WITHDRAW_VAULT_RECEIPT_DISCRIMINATOR, getRequestWithdrawVaultReceiptDecoder(), ); } export async function fetchAllAdaptorAddReceiptAccountsOfVault( rpc: GetProgramAccountsRpc, vault: Address, ): Promise[]> { return fetchAndDecodeAccountsByVault( rpc, vault, ADAPTOR_ADD_RECEIPT_DISCRIMINATOR, getAdaptorAddReceiptDecoder(), ); }