import { PublicKey } from '@solana/web3.js'; import { AccountNotFoundError } from '../errors'; import { SolAmount } from './Amount'; import { createSerializerFromSolitaType, deserializeAccount, SolitaType, } from './Serializer'; export type AccountInfo = { readonly executable: boolean; readonly owner: PublicKey; readonly lamports: SolAmount; readonly rentEpoch?: number; }; export type Account = AccountInfo & { readonly publicKey: PublicKey; readonly data: T; }; export type MaybeAccount = | (Account & { readonly exists: true }) | { readonly publicKey: PublicKey; readonly exists: false }; export type UnparsedAccount = Account; export type UnparsedMaybeAccount = MaybeAccount; export type AccountParsingFunction = { (unparsedAccount: UnparsedAccount): Account; (unparsedAccount: UnparsedMaybeAccount): MaybeAccount; }; export type AccountParsingAndAssertingFunction = ( unparsedAccount: UnparsedAccount | UnparsedMaybeAccount, solution?: string ) => Account; export function getAccountParsingFunction( parser: SolitaType ): AccountParsingFunction { function parse(account: UnparsedAccount): Account; function parse(account: UnparsedMaybeAccount): MaybeAccount; function parse( account: UnparsedAccount | UnparsedMaybeAccount ): Account | MaybeAccount { if ('exists' in account && !account.exists) { return account; } const serializer = createSerializerFromSolitaType(parser); return deserializeAccount(account, serializer); } return parse; } export function getAccountParsingAndAssertingFunction( parser: SolitaType ): AccountParsingAndAssertingFunction { const parse = getAccountParsingFunction(parser); return ( unparsedAccount: UnparsedAccount | UnparsedMaybeAccount, solution?: string ) => { if ('exists' in unparsedAccount) { assertAccountExists(unparsedAccount, parser.name, solution); } return parse(unparsedAccount); }; } export function assertAccountExists( account: MaybeAccount, name?: string, solution?: string ): asserts account is Account & { exists: true } { if (!account.exists) { throw new AccountNotFoundError(account.publicKey, name, { solution }); } } export const toAccountInfo = (account: UnparsedAccount): AccountInfo => { const { executable, owner, lamports, rentEpoch } = account; return { executable, owner, lamports, rentEpoch }; };