import {AnchorProvider, BN, Program, Wallet} from '@coral-xyz/anchor'; import { AccountMeta, ComputeBudgetProgram, Connection, Keypair, PublicKey, Transaction, TransactionInstruction, VersionedTransaction, } from '@solana/web3.js'; import {u32} from "@metaplex-foundation/beet"; import * as base58 from 'bs58'; import nacl from 'tweetnacl'; import {Vault, IDL} from './types/vault'; import { AddWithdrawSupplyEventName, AddWithdrawSupplyEvent, CanceledWithdrawRequestEventName, CanceledWithdrawRequestEvent, ClaimWithdrawEventName, ClaimWithdrawEvent, CloseBatchEventName, CloseBatchEvent, CollectDepositFeeEventName, CollectDepositFeeEvent, CollectPerformanceFeeEventName, CollectPerformanceFeeEvent, CollectRevenueFeeEventName, CollectRevenueFeeEvent, CollectWithdrawFeeEventName, CollectWithdrawFeeEvent, ConcludeBatchEventName, ConcludeBatchEvent, DepositEventName, DepositEvent, OpenNewBatchEventName, OpenNewBatchEvent, ProcessUserBatchEventName, ProcessUserBatchEvent, RequestWithdrawEventName, RequestWithdrawEvent, TransferTempEventName, TransferTempEvent, WithdrawSupplyEventName, WithdrawSupplyEvent, } from "./types/vault-event-types"; import { ProgramStatusType, VaultStatusType, FeeReceiverDetail, UserStatusType } from "./types/vault-enums"; import {keccak256} from "ethereum-cryptography/keccak"; import { createAssociatedTokenAccountInstruction, getAssociatedTokenAddressSync } from "@solana/spl-token"; /// Prefix const PROGRAM_CONFIG_ACCOUNT_PREFIX: string = "CONFIG"; const VAULT_DETAIL_ACCOUNT_PREFIX: string = "VDAP"; const VAULT_DEPOSIT_TREASURE_ACCOUNT_PREFIX: string = "VDTAP"; const VAULT_WITHDRAW_TREASURE_ACCOUNT_PREFIX: string = "VWTAP"; const VAULT_TEMP_WITHDRAW_TREASURE_ACCOUNT_PREFIX: string = "VTWTAP"; const VAULT_DEPOSIT_FEE_DETAIL_ACCOUNT_PREFIX: string = "VDFDAP"; const VAULT_WITHDRAW_FEE_DETAIL_ACCOUNT_PREFIX: string = "VWFDAP"; const VAULT_PERFORMANCE_FEE_DETAIL_ACCOUNT_PREFIX: string = "VPFDAP"; const VAULT_REVENUE_FEE_DETAIL_ACCOUNT_PREFIX: string = "VRFDAP"; const VAULT_BATCH_DETAIL_ACCOUNT_PREFIX: string = "VBDAP"; const USER_DETAIL_ACCOUNT_PREFIX: string = "UDAP"; const USER_BATCH_DETAIL_ACCOUNT_PREFIX: string = "UBDAP"; const USER_DEPOSIT_DETAIL_ACCOUNT_PREFIX: string = "UDDAP"; const USER_WITHDRAW_DETAIL_ACCOUNT_PREFIX: string = "UWDAP"; export class VaultLib { program: Program; connection: Connection; constructor(programId: PublicKey, connection: Connection, wallet: Wallet) { this.connection = connection; const provider = new AnchorProvider(connection, wallet, AnchorProvider.defaultOptions()); this.program = new Program(IDL, programId, provider); } signTransaction(tx: Transaction, secretKey: string): Transaction { const keypair: Keypair = Keypair.fromSecretKey(base58.decode(secretKey)); const signature = nacl.sign.detached(tx.serializeMessage(), keypair.secretKey); tx.addSignature(keypair.publicKey, Buffer.from(signature)); return tx; } signVersionTransaction(tx: VersionedTransaction, secretKey: string): VersionedTransaction { const keypair: Keypair = Keypair.fromSecretKey(base58.decode(secretKey)); const signature = nacl.sign.detached(tx.message.serialize(), keypair.secretKey); tx.addSignature(keypair.publicKey, Buffer.from(signature)); return tx; } addSignatureInTransaction(tx: Transaction, signerAddress: PublicKey, signature: Buffer): Transaction { tx.addSignature(signerAddress, signature); return tx; } addSignatureInVersionTransaction(tx: VersionedTransaction, signerAddress: PublicKey, signature: Buffer): VersionedTransaction { tx.addSignature(signerAddress, signature); return tx; } async addFeePayerAndRecentBlockHashInTransaction(tx: Transaction, feePayer: PublicKey, units: number = 100000): Promise { tx.add(ComputeBudgetProgram.setComputeUnitLimit({units: units})); tx.feePayer = feePayer; tx.recentBlockhash = (await this.connection.getLatestBlockhash()).blockhash; return tx; } async isPdaAddressInitialize(pdaAddress: PublicKey): Promise { const pdaAccountInfo = await this.connection.getAccountInfo(pdaAddress); return pdaAccountInfo != null; } //// PDAs getProgramConfigAccountPdaAndBump(): [PublicKey, number] { return PublicKey.findProgramAddressSync([Buffer.from(PROGRAM_CONFIG_ACCOUNT_PREFIX)], this.program.programId); } getVaultDetailAccountPdaAndBump(vaultName: string): [PublicKey, number] { return PublicKey.findProgramAddressSync( [ Buffer.from(VAULT_DETAIL_ACCOUNT_PREFIX), Buffer.from(vaultName), ], this.program.programId ) } getVaultDepositTreasureAccountPdaAndBump(vaultDetail: PublicKey): [PublicKey, number] { return PublicKey.findProgramAddressSync( [ Buffer.from(VAULT_DEPOSIT_TREASURE_ACCOUNT_PREFIX), vaultDetail.toBuffer(), ], this.program.programId ) } getVaultWithdrawTreasureAccountPdaAndBump(vaultDetail: PublicKey): [PublicKey, number] { return PublicKey.findProgramAddressSync( [ Buffer.from(VAULT_WITHDRAW_TREASURE_ACCOUNT_PREFIX), vaultDetail.toBuffer(), ], this.program.programId ) } getVaultTempWithdrawTreasureAccountPdaAndBump(vaultDetail: PublicKey): [PublicKey, number] { return PublicKey.findProgramAddressSync( [ Buffer.from(VAULT_TEMP_WITHDRAW_TREASURE_ACCOUNT_PREFIX), vaultDetail.toBuffer(), ], this.program.programId ) } getVaultDepositFeeDetailAccountPdaAndBump(vaultDetail: PublicKey): [PublicKey, number] { return PublicKey.findProgramAddressSync( [ Buffer.from(VAULT_DEPOSIT_FEE_DETAIL_ACCOUNT_PREFIX), vaultDetail.toBuffer() ], this.program.programId ) } getVaultWithdrawFeeDetailAccountPdaAndBump(vaultDetail: PublicKey): [PublicKey, number] { return PublicKey.findProgramAddressSync( [ Buffer.from(VAULT_WITHDRAW_FEE_DETAIL_ACCOUNT_PREFIX), vaultDetail.toBuffer() ], this.program.programId ) } getVaultPerformanceFeeDetailAccountPdaAndBump(vaultDetail: PublicKey): [PublicKey, number] { return PublicKey.findProgramAddressSync( [ Buffer.from(VAULT_PERFORMANCE_FEE_DETAIL_ACCOUNT_PREFIX), vaultDetail.toBuffer() ], this.program.programId ) } getVaultRevenueFeeDetailAccountPdaAndBump(vaultDetail: PublicKey): [PublicKey, number] { return PublicKey.findProgramAddressSync( [ Buffer.from(VAULT_REVENUE_FEE_DETAIL_ACCOUNT_PREFIX), vaultDetail.toBuffer() ], this.program.programId ) } getVaultBatchDetailAccountPdaAndBump(vaultDetail: PublicKey, batchIndex: number): [PublicKey, number] { return PublicKey.findProgramAddressSync( [ Buffer.from(VAULT_BATCH_DETAIL_ACCOUNT_PREFIX), vaultDetail.toBuffer(), this.toU32Bytes(batchIndex) ], this.program.programId ) } getUserDetailAccountPdaAndBump(vaultDetail: PublicKey, user: PublicKey): [PublicKey, number] { return PublicKey.findProgramAddressSync( [ Buffer.from(USER_DETAIL_ACCOUNT_PREFIX), vaultDetail.toBuffer(), user.toBuffer(), ], this.program.programId ) } getUserBatchDetailAccountPdaAndBump(userDetail: PublicKey, batchIndex: number): [PublicKey, number] { return PublicKey.findProgramAddressSync( [ Buffer.from(USER_BATCH_DETAIL_ACCOUNT_PREFIX), userDetail.toBuffer(), this.toU32Bytes(batchIndex) ], this.program.programId ) } getUserDepositDetailAccountPdaAndBump(userDetail: PublicKey, depositIndex: number): [PublicKey, number] { return PublicKey.findProgramAddressSync( [ Buffer.from(USER_DEPOSIT_DETAIL_ACCOUNT_PREFIX), userDetail.toBuffer(), this.toU32Bytes(depositIndex) ], this.program.programId ) } getUserWithdrawDetailAccountPdaAndBump(userDetail: PublicKey, withdrawIndex: number): [PublicKey, number] { return PublicKey.findProgramAddressSync( [ Buffer.from(USER_WITHDRAW_DETAIL_ACCOUNT_PREFIX), userDetail.toBuffer(), this.toU32Bytes(withdrawIndex) ], this.program.programId ) } /// Get Account Data async getProgramConfigAccountData() { const [programConfigPda] = this.getProgramConfigAccountPdaAndBump(); return await this.program.account.programConfigAccount.fetch(programConfigPda); } async getVaultDetailAccountData(vaultName: string) { const [vaultDetailPda] = this.getVaultDetailAccountPdaAndBump(vaultName); return await this.program.account.vaultDetailAccount.fetch(vaultDetailPda); } async getVaultDepositFeeDetailAccountData(vaultName: string) { const [vaultDetailPda] = this.getVaultDetailAccountPdaAndBump(vaultName); const [vaultDepositFeeDetailPda] = this.getVaultDepositFeeDetailAccountPdaAndBump(vaultDetailPda); return await this.program.account.feeDetailAccount.fetch(vaultDepositFeeDetailPda); } async getVaultWithdrawFeeDetailAccountData(vaultName: string) { const [vaultDetailPda] = this.getVaultDetailAccountPdaAndBump(vaultName); const [vaultWithdrawFeeDetailPda] = this.getVaultWithdrawFeeDetailAccountPdaAndBump(vaultDetailPda); return await this.program.account.feeDetailAccount.fetch(vaultWithdrawFeeDetailPda); } async getVaultPerformanceFeeDetailAccountData(vaultName: string) { const [vaultDetailPda] = this.getVaultDetailAccountPdaAndBump(vaultName); const [vaultPerformanceFeeDetailPda] = this.getVaultPerformanceFeeDetailAccountPdaAndBump(vaultDetailPda); return await this.program.account.feeDetailAccount.fetch(vaultPerformanceFeeDetailPda); } async getVaultBatchDetailAccountData(vaultName: string, batchIndex: number) { const [vaultDetailPda] = this.getVaultDetailAccountPdaAndBump(vaultName); const [vaultBatchDetailPda] = this.getVaultBatchDetailAccountPdaAndBump(vaultDetailPda, batchIndex); return await this.program.account.vaultBatchDetailAccount.fetch(vaultBatchDetailPda); } async getUserDetailAccountData(vaultName: string, user: PublicKey) { const [vaultDetailPda] = this.getVaultDetailAccountPdaAndBump(vaultName); const [userDetailPda] = this.getUserDetailAccountPdaAndBump(vaultDetailPda, user); return await this.program.account.userDetailAccount.fetch(userDetailPda); } async getUserDepositDetailAccountData(vaultName: string, user: PublicKey, depositIndex: number) { const [vaultDetailPda] = this.getVaultDetailAccountPdaAndBump(vaultName); const [userDetailPda] = this.getUserDetailAccountPdaAndBump(vaultDetailPda, user); const [userDepositDetailPda] = this.getUserDepositDetailAccountPdaAndBump(userDetailPda, depositIndex); return await this.program.account.userDepositDetailAccount.fetch(userDepositDetailPda); } async getUserWithdrawDetailAccountData(vaultName: string, user: PublicKey, withdrawIndex: number) { const [vaultDetailPda] = this.getVaultDetailAccountPdaAndBump(vaultName); const [userDetailPda] = this.getUserDetailAccountPdaAndBump(vaultDetailPda, user); const [userWithdrawDetailPda] = this.getUserWithdrawDetailAccountPdaAndBump(userDetailPda, withdrawIndex); return await this.program.account.userWithdrawDetailAccount.fetch(userWithdrawDetailPda); } async getCurrentVaultBatchIndex(vaultName: string): Promise { const [vaultDetailPda] = this.getVaultDetailAccountPdaAndBump(vaultName); let index: number = 0; if (await this.isPdaAddressInitialize(vaultDetailPda)) { index = (await this.getVaultDetailAccountData(vaultName)).batchCount; } return index; } async getCurrentUserDepositIndex(vaultName: string, user: PublicKey): Promise { const [vaultDetailPda] = this.getVaultDetailAccountPdaAndBump(vaultName); const [userDetailPda] = this.getUserDetailAccountPdaAndBump(vaultDetailPda, user); let index: number = 0; if (await this.isPdaAddressInitialize(userDetailPda)) { index = (await this.getUserDetailAccountData(vaultName, user)).depositCount; } return index; } async getCurrentUserWithdrawIndex(vaultName: string, user: PublicKey): Promise { return (await this.getUserDetailAccountData(vaultName, user)).requestedWithdrawCount; } /// Transactions async createInitializeTransaction( feeAndRentPayer: PublicKey, mainSigningAuthority: PublicKey, systemProgram: PublicKey, rent: PublicKey ): Promise { const [programConfigPda] = this.getProgramConfigAccountPdaAndBump(); const tx: Transaction = new Transaction(); const initializeIx: TransactionInstruction = await this.program.methods .initialize({}) .accounts({ feeAndRentPayer: feeAndRentPayer, mainSigningAuthority: mainSigningAuthority, programConfig: programConfigPda, systemProgram: systemProgram, rent: rent, }) .instruction(); tx.add(initializeIx); return tx; } async createUpdateProgramStatusTransaction( mainSigningAuthority: PublicKey, programStatus: ProgramStatusType ): Promise { const [programConfigPda, programConfigBump] = this.getProgramConfigAccountPdaAndBump(); const tx: Transaction = new Transaction(); const updateProgramStatusIx: TransactionInstruction = await this.program.methods .updateProgramStatus({ programStatus: programStatus, programConfigBump: programConfigBump, }) .accounts({ mainSigningAuthority: mainSigningAuthority, programConfig: programConfigPda, }) .instruction(); tx.add(updateProgramStatusIx); return tx; } async createTransferProgramMainAuthorityTransaction( mainSigningAuthority: PublicKey, newMainSigningAuthority: PublicKey ): Promise { const [programConfigPda, programConfigBump] = this.getProgramConfigAccountPdaAndBump(); const tx: Transaction = new Transaction(); const transferProgramMainAuthorityIx = await this.program.methods .transferProgramMainAuthority({ newMainSigningAuthority: newMainSigningAuthority, programConfigBump: programConfigBump }) .accountsStrict({ mainSigningAuthority: mainSigningAuthority, programConfig: programConfigPda }) .instruction(); tx.add(transferProgramMainAuthorityIx); return tx; } async createAcceptProgramMainAuthorityTransaction( acceptingMainSigningAuthority: PublicKey ): Promise { const [programConfigPda, programConfigBump] = this.getProgramConfigAccountPdaAndBump(); const tx: Transaction = new Transaction(); const acceptProgramMainAuthorityIx = await this.program.methods .acceptProgramMainAuthority({ programConfigBump: programConfigBump }) .accountsStrict({ acceptingMainSigningAuthority: acceptingMainSigningAuthority, programConfig: programConfigPda }) .instruction(); tx.add(acceptProgramMainAuthorityIx); return tx; } async createCancelProgramMainAuthorityTransaction( mainSigningAuthority: PublicKey ): Promise { const [programConfigPda, programConfigBump] = this.getProgramConfigAccountPdaAndBump(); const tx: Transaction = new Transaction(); const cancelProgramMainAuthorityIx = await this.program.methods .cancelProgramMainAuthority({ programConfigBump: programConfigBump }) .accountsStrict({ mainSigningAuthority: mainSigningAuthority, programConfig: programConfigPda }) .instruction(); tx.add(cancelProgramMainAuthorityIx); return tx; } async createInitializeVaultTransaction( feeAndRentPayer: PublicKey, mainSigningAuthority: PublicKey, vaultName: string, owner: PublicKey, tokenMintAccount: PublicKey, operator: PublicKey, processTxFeeReceiver: PublicKey, depositReceiver: PublicKey, processTxFee: BN, withdrawAuthority: PublicKey, tokenProgram: PublicKey, associatedTokenProgram: PublicKey, systemProgram: PublicKey, rent: PublicKey ): Promise { const [programConfigPda, programConfigBump] = this.getProgramConfigAccountPdaAndBump(); const [vaultDetailPda] = this.getVaultDetailAccountPdaAndBump(vaultName); const tx: Transaction = new Transaction(); const [vaultDepositTreasurePda] = this.getVaultDepositTreasureAccountPdaAndBump(vaultDetailPda); const vaultDepositTreasureTokenAccount: PublicKey = getAssociatedTokenAddressSync( tokenMintAccount, vaultDepositTreasurePda, true, tokenProgram, associatedTokenProgram ); if (!await this.isPdaAddressInitialize(vaultDepositTreasureTokenAccount)) { const createVaultDepositTreasureTokenAccountIx: TransactionInstruction = createAssociatedTokenAccountInstruction( feeAndRentPayer, vaultDepositTreasureTokenAccount, vaultDepositTreasurePda, tokenMintAccount, tokenProgram, associatedTokenProgram ); tx.add(createVaultDepositTreasureTokenAccountIx); } const [vaultWithdrawTreasurePda] = this.getVaultWithdrawTreasureAccountPdaAndBump(vaultDetailPda); const vaultWithdrawTreasureTokenAccount: PublicKey = getAssociatedTokenAddressSync( tokenMintAccount, vaultWithdrawTreasurePda, true, tokenProgram, associatedTokenProgram ); if (!await this.isPdaAddressInitialize(vaultWithdrawTreasureTokenAccount)) { const createVaultWithdrawTreasureTokenAccountIx: TransactionInstruction = createAssociatedTokenAccountInstruction( feeAndRentPayer, vaultWithdrawTreasureTokenAccount, vaultWithdrawTreasurePda, tokenMintAccount, tokenProgram, associatedTokenProgram ); tx.add(createVaultWithdrawTreasureTokenAccountIx); } const [vaultTempWithdrawTreasurePda] = this.getVaultTempWithdrawTreasureAccountPdaAndBump(vaultDetailPda); const vaultTempWithdrawTreasureTokenAccount: PublicKey = getAssociatedTokenAddressSync( tokenMintAccount, vaultTempWithdrawTreasurePda, true, tokenProgram, associatedTokenProgram ); if (!await this.isPdaAddressInitialize(vaultTempWithdrawTreasureTokenAccount)) { const createVaultTempWithdrawTreasureTokenAccountIx: TransactionInstruction = createAssociatedTokenAccountInstruction( feeAndRentPayer, vaultTempWithdrawTreasureTokenAccount, vaultTempWithdrawTreasurePda, tokenMintAccount, tokenProgram, associatedTokenProgram ); tx.add(createVaultTempWithdrawTreasureTokenAccountIx); } const initializeVaultIx: TransactionInstruction = await this.program.methods .initializeVault({ name: vaultName, owner: owner, mint: tokenMintAccount, operator: operator, processTxFeeReceiver: processTxFeeReceiver, depositReceiver: depositReceiver, processTxFee: processTxFee, withdrawAuthority: withdrawAuthority, programConfigBump: programConfigBump }) .accounts({ feeAndRentPayer: feeAndRentPayer, mainSigningAuthority: mainSigningAuthority, programConfig: programConfigPda, vaultDetail: vaultDetailPda, systemProgram: systemProgram, rent: rent }) .instruction(); tx.add(initializeVaultIx); return tx; } async createUpdateVaultStatusTransaction( mainSigningAuthority: PublicKey, vaultName: string, owner: PublicKey, vaultStatus: VaultStatusType, withdrawAuthority: PublicKey ): Promise { const [programConfigPda, programConfigBump] = this.getProgramConfigAccountPdaAndBump(); const [vaultDetailPda, vaultDetailBump] = this.getVaultDetailAccountPdaAndBump(vaultName); const tx: Transaction = new Transaction(); const updateVaultStatusIx: TransactionInstruction = await this.program.methods .updateVaultStatus({ name: vaultName, owner: owner, vaultStatus: vaultStatus, withdrawAuthority: withdrawAuthority, programConfigBump: programConfigBump, vaultDetailBump: vaultDetailBump }) .accounts({ mainSigningAuthority: mainSigningAuthority, programConfig: programConfigPda, vaultDetail: vaultDetailPda, }) .instruction(); tx.add(updateVaultStatusIx); return tx; } async createUpdateVaultTransaction( owner: PublicKey, vaultName: string, operator: PublicKey, processTxFeeReceiver: PublicKey, depositReceiver: PublicKey, processTxFee: BN, ): Promise { const [programConfigPda] = this.getProgramConfigAccountPdaAndBump(); const [vaultDetailPda, vaultDetailBump] = this.getVaultDetailAccountPdaAndBump(vaultName); const tx: Transaction = new Transaction(); const updateVaultStatusIx: TransactionInstruction = await this.program.methods .updateVault({ name: vaultName, operator: operator, processTxFeeReceiver: processTxFeeReceiver, depositReceiver: depositReceiver, processTxFee: processTxFee, vaultDetailBump: vaultDetailBump }) .accounts({ owner: owner, vaultDetail: vaultDetailPda, }) .remainingAccounts([ // 0: Program Config { pubkey: programConfigPda, isSigner: false, isWritable: false } ]) .instruction(); tx.add(updateVaultStatusIx); return tx; } async createInitializeVaultDepositFeeTransaction( feeAndRentPayer: PublicKey, owner: PublicKey, vaultName: string, enable: boolean, basePoint: number, minimumClaimableFee: BN, receivers: FeeReceiverDetail[], tokenMintAccount: PublicKey, tokenProgram: PublicKey, associatedTokenProgram: PublicKey, systemProgram: PublicKey, rent: PublicKey, ): Promise { const [programConfigPda] = this.getProgramConfigAccountPdaAndBump(); const [vaultDetailPda, vaultDetailBump] = this.getVaultDetailAccountPdaAndBump(vaultName); const [vaultDepositFeeDetailPda] = this.getVaultDepositFeeDetailAccountPdaAndBump(vaultDetailPda); const tx: Transaction = new Transaction(); const vaultDepositFeeDetailTokenAccount: PublicKey = getAssociatedTokenAddressSync( tokenMintAccount, vaultDepositFeeDetailPda, true, tokenProgram, associatedTokenProgram ); if (!await this.isPdaAddressInitialize(vaultDepositFeeDetailTokenAccount)) { const createVaultDepositFeeDetailTokenAccountIx: TransactionInstruction = createAssociatedTokenAccountInstruction( feeAndRentPayer, vaultDepositFeeDetailTokenAccount, vaultDepositFeeDetailPda, tokenMintAccount, tokenProgram, associatedTokenProgram ); tx.add(createVaultDepositFeeDetailTokenAccountIx) } for (let i = 0; i < receivers.length; i++) { const depositFeeReceiverTokenAccount: PublicKey = getAssociatedTokenAddressSync( tokenMintAccount, receivers[i].receiver, true, tokenProgram, associatedTokenProgram ); if (!await this.isPdaAddressInitialize(depositFeeReceiverTokenAccount)) { const createReceiverTokenAccountIx: TransactionInstruction = createAssociatedTokenAccountInstruction( feeAndRentPayer, depositFeeReceiverTokenAccount, receivers[i].receiver, tokenMintAccount, tokenProgram, associatedTokenProgram ); tx.add(createReceiverTokenAccountIx); } } const initializeVaultDepositFeeIx: TransactionInstruction = await this.program.methods .initializeVaultDepositFee({ name: vaultName, enable: enable, basePoint: basePoint, minimumClaimableFee: minimumClaimableFee, receivers: receivers, vaultDetailBump: vaultDetailBump }) .accounts({ feeAndRentPayer: feeAndRentPayer, owner: owner, vaultDetail: vaultDetailPda, vaultDepositFeeDetail: vaultDepositFeeDetailPda, systemProgram: systemProgram, rent: rent }) .remainingAccounts([ // 0: Program Config { pubkey: programConfigPda, isSigner: false, isWritable: false } ]) .instruction(); tx.add(initializeVaultDepositFeeIx); return tx; } async createUpdateVaultDepositFeeTransaction( feeAndRentPayer: PublicKey, owner: PublicKey, vaultName: string, enable: boolean, basePoint: number, minimumClaimableFee: BN, receivers: FeeReceiverDetail[], tokenMintAccount: PublicKey, tokenProgram: PublicKey, associatedTokenProgram: PublicKey, systemProgram: PublicKey, rent: PublicKey, ): Promise { const [programConfigPda] = this.getProgramConfigAccountPdaAndBump(); const [vaultDetailPda, vaultDetailBump] = this.getVaultDetailAccountPdaAndBump(vaultName); const [vaultDepositFeeDetailPda, vaultDepositFeeDetailBump] = this.getVaultDepositFeeDetailAccountPdaAndBump(vaultDetailPda); const tx: Transaction = new Transaction(); for (let i = 0; i < receivers.length; i++) { const depositFeeReceiverTokenAccount: PublicKey = getAssociatedTokenAddressSync( tokenMintAccount, receivers[i].receiver, true, tokenProgram, associatedTokenProgram ); if (!await this.isPdaAddressInitialize(depositFeeReceiverTokenAccount)) { const createReceiverTokenAccountIx: TransactionInstruction = createAssociatedTokenAccountInstruction( feeAndRentPayer, depositFeeReceiverTokenAccount, receivers[i].receiver, tokenMintAccount, tokenProgram, associatedTokenProgram ); tx.add(createReceiverTokenAccountIx); } } const updateVaultDepositFeeIx: TransactionInstruction = await this.program.methods .updateVaultDepositFee({ name: vaultName, enable: enable, basePoint: basePoint, minimumClaimableFee: minimumClaimableFee, receivers: receivers, vaultDetailBump: vaultDetailBump, vaultDepositFeeDetailBump: vaultDepositFeeDetailBump }) .accounts({ feeAndRentPayer: feeAndRentPayer, owner: owner, vaultDetail: vaultDetailPda, vaultDepositFeeDetail: vaultDepositFeeDetailPda, systemProgram: systemProgram, rent: rent }) .remainingAccounts([ // 0: Program Config { pubkey: programConfigPda, isSigner: false, isWritable: false } ]) .instruction(); tx.add(updateVaultDepositFeeIx); return tx; } async createInitializeVaultWithdrawFeeTransaction( feeAndRentPayer: PublicKey, owner: PublicKey, vaultName: string, enable: boolean, basePoint: number, minimumClaimableFee: BN, receivers: FeeReceiverDetail[], tokenMintAccount: PublicKey, tokenProgram: PublicKey, associatedTokenProgram: PublicKey, systemProgram: PublicKey, rent: PublicKey, ): Promise { const [programConfigPda] = this.getProgramConfigAccountPdaAndBump(); const [vaultDetailPda, vaultDetailBump] = this.getVaultDetailAccountPdaAndBump(vaultName); const [vaultWithdrawFeeDetailPda] = this.getVaultWithdrawFeeDetailAccountPdaAndBump(vaultDetailPda); const tx: Transaction = new Transaction(); const vaultWithdrawFeeDetailTokenAccount: PublicKey = getAssociatedTokenAddressSync( tokenMintAccount, vaultWithdrawFeeDetailPda, true, tokenProgram, associatedTokenProgram ); if (!await this.isPdaAddressInitialize(vaultWithdrawFeeDetailTokenAccount)) { const createVaultWithdrawFeeDetailTokenAccountIx: TransactionInstruction = createAssociatedTokenAccountInstruction( feeAndRentPayer, vaultWithdrawFeeDetailTokenAccount, vaultWithdrawFeeDetailPda, tokenMintAccount, tokenProgram, associatedTokenProgram ); tx.add(createVaultWithdrawFeeDetailTokenAccountIx) } for (let i = 0; i < receivers.length; i++) { const withdrawFeeReceiverTokenAccount: PublicKey = getAssociatedTokenAddressSync( tokenMintAccount, receivers[i].receiver, true, tokenProgram, associatedTokenProgram ); if (!await this.isPdaAddressInitialize(withdrawFeeReceiverTokenAccount)) { const createReceiverTokenAccountIx: TransactionInstruction = createAssociatedTokenAccountInstruction( feeAndRentPayer, withdrawFeeReceiverTokenAccount, receivers[i].receiver, tokenMintAccount, tokenProgram, associatedTokenProgram ); tx.add(createReceiverTokenAccountIx); } } const initializeVaultWithdrawFeeIx: TransactionInstruction = await this.program.methods .initializeVaultWithdrawFee({ name: vaultName, enable: enable, basePoint: basePoint, minimumClaimableFee: minimumClaimableFee, receivers: receivers, vaultDetailBump: vaultDetailBump }) .accounts({ feeAndRentPayer: feeAndRentPayer, owner: owner, vaultDetail: vaultDetailPda, vaultWithdrawFeeDetail: vaultWithdrawFeeDetailPda, systemProgram: systemProgram, rent: rent }) .remainingAccounts([ // 0: Program Config { pubkey: programConfigPda, isSigner: false, isWritable: false } ]) .instruction(); tx.add(initializeVaultWithdrawFeeIx); return tx; } async createUpdateVaultWithdrawFeeTransaction( feeAndRentPayer: PublicKey, owner: PublicKey, vaultName: string, enable: boolean, basePoint: number, minimumClaimableFee: BN, receivers: FeeReceiverDetail[], tokenMintAccount: PublicKey, tokenProgram: PublicKey, associatedTokenProgram: PublicKey, systemProgram: PublicKey, rent: PublicKey, ): Promise { const [programConfigPda] = this.getProgramConfigAccountPdaAndBump(); const [vaultDetailPda, vaultDetailBump] = this.getVaultDetailAccountPdaAndBump(vaultName); const [vaultWithdrawFeeDetailPda, vaultWithdrawFeeDetailBump] = this.getVaultWithdrawFeeDetailAccountPdaAndBump(vaultDetailPda); const tx: Transaction = new Transaction(); for (let i = 0; i < receivers.length; i++) { const withdrawFeeReceiverTokenAccount: PublicKey = getAssociatedTokenAddressSync( tokenMintAccount, receivers[i].receiver, true, tokenProgram, associatedTokenProgram ); if (!await this.isPdaAddressInitialize(withdrawFeeReceiverTokenAccount)) { const createReceiverTokenAccountIx: TransactionInstruction = createAssociatedTokenAccountInstruction( feeAndRentPayer, withdrawFeeReceiverTokenAccount, receivers[i].receiver, tokenMintAccount, tokenProgram, associatedTokenProgram ); tx.add(createReceiverTokenAccountIx); } } const updateVaultWithdrawFeeIx: TransactionInstruction = await this.program.methods .updateVaultWithdrawFee({ name: vaultName, enable: enable, basePoint: basePoint, minimumClaimableFee: minimumClaimableFee, receivers: receivers, vaultDetailBump: vaultDetailBump, vaultWithdrawFeeDetailBump: vaultWithdrawFeeDetailBump }) .accounts({ feeAndRentPayer: feeAndRentPayer, owner: owner, vaultDetail: vaultDetailPda, vaultWithdrawFeeDetail: vaultWithdrawFeeDetailPda, systemProgram: systemProgram, rent: rent }) .remainingAccounts([ // 0: Program Config { pubkey: programConfigPda, isSigner: false, isWritable: false } ]) .instruction(); tx.add(updateVaultWithdrawFeeIx); return tx; } async createInitializeVaultPerformanceFeeTransaction( feeAndRentPayer: PublicKey, owner: PublicKey, vaultName: string, enable: boolean, basePoint: number, minimumClaimableFee: BN, receivers: FeeReceiverDetail[], tokenMintAccount: PublicKey, tokenProgram: PublicKey, associatedTokenProgram: PublicKey, systemProgram: PublicKey, rent: PublicKey, ): Promise { const [programConfigPda] = this.getProgramConfigAccountPdaAndBump(); const [vaultDetailPda, vaultDetailBump] = this.getVaultDetailAccountPdaAndBump(vaultName); const [vaultPerformanceFeeDetailPda] = this.getVaultPerformanceFeeDetailAccountPdaAndBump(vaultDetailPda); const tx: Transaction = new Transaction(); const vaultPerformanceFeeDetailTokenAccount: PublicKey = getAssociatedTokenAddressSync( tokenMintAccount, vaultPerformanceFeeDetailPda, true, tokenProgram, associatedTokenProgram ); if (!await this.isPdaAddressInitialize(vaultPerformanceFeeDetailTokenAccount)) { const createVaultPerformanceFeeDetailTokenAccountIx: TransactionInstruction = createAssociatedTokenAccountInstruction( feeAndRentPayer, vaultPerformanceFeeDetailTokenAccount, vaultPerformanceFeeDetailPda, tokenMintAccount, tokenProgram, associatedTokenProgram ); tx.add(createVaultPerformanceFeeDetailTokenAccountIx) } for (let i = 0; i < receivers.length; i++) { const performanceFeeReceiverTokenAccount: PublicKey = getAssociatedTokenAddressSync( tokenMintAccount, receivers[i].receiver, true, tokenProgram, associatedTokenProgram ); if (!await this.isPdaAddressInitialize(performanceFeeReceiverTokenAccount)) { const createReceiverTokenAccountIx: TransactionInstruction = createAssociatedTokenAccountInstruction( feeAndRentPayer, performanceFeeReceiverTokenAccount, receivers[i].receiver, tokenMintAccount, tokenProgram, associatedTokenProgram ); tx.add(createReceiverTokenAccountIx); } } const initializeVaultPerformanceFeeIx: TransactionInstruction = await this.program.methods .initializeVaultPerformanceFee({ name: vaultName, enable: enable, basePoint: basePoint, minimumClaimableFee: minimumClaimableFee, receivers: receivers, vaultDetailBump: vaultDetailBump }) .accounts({ feeAndRentPayer: feeAndRentPayer, owner: owner, vaultDetail: vaultDetailPda, vaultPerformanceFeeDetail: vaultPerformanceFeeDetailPda, systemProgram: systemProgram, rent: rent }) .remainingAccounts([ // 0: Program Config { pubkey: programConfigPda, isSigner: false, isWritable: false } ]) .instruction(); tx.add(initializeVaultPerformanceFeeIx); return tx; } async createUpdateVaultPerformanceFeeTransaction( feeAndRentPayer: PublicKey, owner: PublicKey, vaultName: string, enable: boolean, basePoint: number, minimumClaimableFee: BN, receivers: FeeReceiverDetail[], tokenMintAccount: PublicKey, tokenProgram: PublicKey, associatedTokenProgram: PublicKey, systemProgram: PublicKey, rent: PublicKey, ): Promise { const [programConfigPda] = this.getProgramConfigAccountPdaAndBump(); const [vaultDetailPda, vaultDetailBump] = this.getVaultDetailAccountPdaAndBump(vaultName); const [vaultPerformanceFeeDetailPda, vaultPerformanceFeeDetailBump] = this.getVaultPerformanceFeeDetailAccountPdaAndBump(vaultDetailPda); const tx: Transaction = new Transaction(); for (let i = 0; i < receivers.length; i++) { const performanceFeeReceiverTokenAccount: PublicKey = getAssociatedTokenAddressSync( tokenMintAccount, receivers[i].receiver, true, tokenProgram, associatedTokenProgram ); if (!await this.isPdaAddressInitialize(performanceFeeReceiverTokenAccount)) { const createReceiverTokenAccountIx: TransactionInstruction = createAssociatedTokenAccountInstruction( feeAndRentPayer, performanceFeeReceiverTokenAccount, receivers[i].receiver, tokenMintAccount, tokenProgram, associatedTokenProgram ); tx.add(createReceiverTokenAccountIx); } } const updateVaultPerformanceFeeIx: TransactionInstruction = await this.program.methods .updateVaultPerformanceFee({ name: vaultName, enable: enable, basePoint: basePoint, minimumClaimableFee: minimumClaimableFee, receivers: receivers, vaultDetailBump: vaultDetailBump, vaultPerformanceFeeDetailBump: vaultPerformanceFeeDetailBump }) .accounts({ feeAndRentPayer: feeAndRentPayer, owner: owner, vaultDetail: vaultDetailPda, vaultPerformanceFeeDetail: vaultPerformanceFeeDetailPda, systemProgram: systemProgram, rent: rent }) .remainingAccounts([ // 0: Program Config { pubkey: programConfigPda, isSigner: false, isWritable: false } ]) .instruction(); tx.add(updateVaultPerformanceFeeIx); return tx; } async createInitializeVaultRevenueFeeTransaction( feeAndRentPayer: PublicKey, owner: PublicKey, vaultName: string, enable: boolean, basePoint: number, minimumClaimableFee: BN, receivers: FeeReceiverDetail[], tokenMintAccount: PublicKey, tokenProgram: PublicKey, associatedTokenProgram: PublicKey, systemProgram: PublicKey, rent: PublicKey, ): Promise { const [programConfigPda] = this.getProgramConfigAccountPdaAndBump(); const [vaultDetailPda, vaultDetailBump] = this.getVaultDetailAccountPdaAndBump(vaultName); const [vaultRevenueFeeDetailPda] = this.getVaultRevenueFeeDetailAccountPdaAndBump(vaultDetailPda); const tx: Transaction = new Transaction(); const vaultRevenueFeeDetailTokenAccount: PublicKey = getAssociatedTokenAddressSync( tokenMintAccount, vaultRevenueFeeDetailPda, true, tokenProgram, associatedTokenProgram ); if (!await this.isPdaAddressInitialize(vaultRevenueFeeDetailTokenAccount)) { const createVaultRevenueFeeDetailTokenAccountIx: TransactionInstruction = createAssociatedTokenAccountInstruction( feeAndRentPayer, vaultRevenueFeeDetailTokenAccount, vaultRevenueFeeDetailPda, tokenMintAccount, tokenProgram, associatedTokenProgram ); tx.add(createVaultRevenueFeeDetailTokenAccountIx) } for (let i = 0; i < receivers.length; i++) { const revenueFeeReceiverTokenAccount: PublicKey = getAssociatedTokenAddressSync( tokenMintAccount, receivers[i].receiver, true, tokenProgram, associatedTokenProgram ); if (!await this.isPdaAddressInitialize(revenueFeeReceiverTokenAccount)) { const createReceiverTokenAccountIx: TransactionInstruction = createAssociatedTokenAccountInstruction( feeAndRentPayer, revenueFeeReceiverTokenAccount, receivers[i].receiver, tokenMintAccount, tokenProgram, associatedTokenProgram ); tx.add(createReceiverTokenAccountIx); } } const initializeVaultRevenueFeeIx: TransactionInstruction = await this.program.methods .initializeVaultRevenueFee({ name: vaultName, enable: enable, basePoint: basePoint, minimumClaimableFee: minimumClaimableFee, receivers: receivers, vaultDetailBump: vaultDetailBump }) .accounts({ feeAndRentPayer: feeAndRentPayer, owner: owner, vaultDetail: vaultDetailPda, vaultRevenueFeeDetail: vaultRevenueFeeDetailPda, systemProgram: systemProgram, rent: rent }) .remainingAccounts([ // 0: Program Config { pubkey: programConfigPda, isSigner: false, isWritable: false } ]) .instruction(); tx.add(initializeVaultRevenueFeeIx); return tx; } async createUpdateVaultRevenueFeeTransaction( feeAndRentPayer: PublicKey, owner: PublicKey, vaultName: string, enable: boolean, basePoint: number, minimumClaimableFee: BN, receivers: FeeReceiverDetail[], tokenMintAccount: PublicKey, tokenProgram: PublicKey, associatedTokenProgram: PublicKey, systemProgram: PublicKey, rent: PublicKey, ): Promise { const [programConfigPda] = this.getProgramConfigAccountPdaAndBump(); const [vaultDetailPda, vaultDetailBump] = this.getVaultDetailAccountPdaAndBump(vaultName); const [vaultRevenueFeeDetailPda, vaultRevenueFeeDetailBump] = this.getVaultRevenueFeeDetailAccountPdaAndBump(vaultDetailPda); const tx: Transaction = new Transaction(); for (let i = 0; i < receivers.length; i++) { const revenueFeeReceiverTokenAccount: PublicKey = getAssociatedTokenAddressSync( tokenMintAccount, receivers[i].receiver, true, tokenProgram, associatedTokenProgram ); if (!await this.isPdaAddressInitialize(revenueFeeReceiverTokenAccount)) { const createReceiverTokenAccountIx: TransactionInstruction = createAssociatedTokenAccountInstruction( feeAndRentPayer, revenueFeeReceiverTokenAccount, receivers[i].receiver, tokenMintAccount, tokenProgram, associatedTokenProgram ); tx.add(createReceiverTokenAccountIx); } } const updateVaultRevenueFeeIx: TransactionInstruction = await this.program.methods .updateVaultRevenueFee({ name: vaultName, enable: enable, basePoint: basePoint, minimumClaimableFee: minimumClaimableFee, receivers: receivers, vaultDetailBump: vaultDetailBump, vaultRevenueFeeDetailBump: vaultRevenueFeeDetailBump }) .accounts({ feeAndRentPayer: feeAndRentPayer, owner: owner, vaultDetail: vaultDetailPda, vaultRevenueFeeDetail: vaultRevenueFeeDetailPda, systemProgram: systemProgram, rent: rent }) .remainingAccounts([ // 0: Program Config { pubkey: programConfigPda, isSigner: false, isWritable: false } ]) .instruction(); tx.add(updateVaultRevenueFeeIx); return tx; } async createAddWithdrawSupplyTransaction( supplyProvider: PublicKey, vaultName: string, supply: BN, tokenMintAccount: PublicKey, tokenProgram: PublicKey, associatedTokenProgram: PublicKey, ): Promise { console.log("createAddWithdrawSupplyTransaction"); const [programConfigPda] = this.getProgramConfigAccountPdaAndBump(); const [vaultDetailPda, vaultDetailBump] = this.getVaultDetailAccountPdaAndBump(vaultName); const [vaultWithdrawTreasurePda] = this.getVaultWithdrawTreasureAccountPdaAndBump(vaultDetailPda); const vaultWithdrawTreasureTokenAccount: PublicKey = getAssociatedTokenAddressSync( tokenMintAccount, vaultWithdrawTreasurePda, true, tokenProgram, associatedTokenProgram ); console.log("vaultWithdrawTreasureTokenAccount: ", vaultWithdrawTreasureTokenAccount.toBase58()); const supplyProviderTokenAccount: PublicKey = getAssociatedTokenAddressSync( tokenMintAccount, supplyProvider, true, tokenProgram, associatedTokenProgram ); console.log("supplyProviderTokenAccount: ", supplyProviderTokenAccount.toBase58()); const tx: Transaction = new Transaction(); const addWithdrawSupplyIx: TransactionInstruction = await this.program.methods .addWithdrawSupply({ name: vaultName, supply: supply, vaultDetailBump: vaultDetailBump, }) .accounts({ supplyProvider: supplyProvider, vaultDetail: vaultDetailPda, tokenMintAccount: tokenMintAccount }) .remainingAccounts([ // 0: Program Config { pubkey: programConfigPda, isSigner: false, isWritable: false }, // 1: Token Program { pubkey: tokenProgram, isSigner: false, isWritable: false }, // 2: Vault Withdraw Treasure Token Program { pubkey: vaultWithdrawTreasureTokenAccount, isSigner: false, isWritable: true }, // 3: Supply Provider Token Account { pubkey: supplyProviderTokenAccount, isSigner: false, isWritable: true } ]) .instruction(); tx.add(addWithdrawSupplyIx); return tx; } async createWithdrawSupplyTransaction( feeAndRentPayer: PublicKey, withdrawAuthority: PublicKey, vaultName: string, supply: BN, withdrawReceiver: PublicKey, tokenMintAccount: PublicKey, tokenProgram: PublicKey, associatedTokenProgram: PublicKey, ): Promise { const [programConfigPda] = this.getProgramConfigAccountPdaAndBump(); const [vaultDetailPda, vaultDetailBump] = this.getVaultDetailAccountPdaAndBump(vaultName); const vaultDetailTokenAccount: PublicKey = getAssociatedTokenAddressSync( tokenMintAccount, vaultDetailPda, true, tokenProgram, associatedTokenProgram ); const withdrawReceiverTokenAccount: PublicKey = getAssociatedTokenAddressSync( tokenMintAccount, withdrawReceiver, true, tokenProgram, associatedTokenProgram ); const tx: Transaction = new Transaction(); if (!await this.isPdaAddressInitialize(withdrawReceiverTokenAccount)) { const createWithdrawReceiverTokenAccountIx: TransactionInstruction = createAssociatedTokenAccountInstruction( feeAndRentPayer, withdrawReceiverTokenAccount, withdrawReceiver, tokenMintAccount, tokenProgram, associatedTokenProgram ); tx.add(createWithdrawReceiverTokenAccountIx); } const withdrawSupplyIx: TransactionInstruction = await this.program.methods .withdrawSupply({ name: vaultName, supply: supply, withdrawReceiver: withdrawReceiver, vaultDetailBump: vaultDetailBump, }) .accounts({ withdrawAuthority: withdrawAuthority, vaultDetail: vaultDetailPda, tokenMintAccount: tokenMintAccount }) .remainingAccounts([ // 0: Program Config { pubkey: programConfigPda, isSigner: false, isWritable: false }, // 1: Token Program { pubkey: tokenProgram, isSigner: false, isWritable: false }, // 2: Vault Detail Token Program { pubkey: vaultDetailTokenAccount, isSigner: false, isWritable: true }, // 3: Withdraw Receiver Token Account { pubkey: withdrawReceiverTokenAccount, isSigner: false, isWritable: true } ]) .instruction(); tx.add(withdrawSupplyIx); return tx; } async createOpenNewBatchTransaction( feeAndRentPayer: PublicKey, operator: PublicKey, vaultName: string, batchIndex: number, sharePrice: BN, tokenMintAccount: PublicKey, tokenProgram: PublicKey, associatedTokenProgram: PublicKey, systemProgram: PublicKey, rent: PublicKey, ): Promise { const [programConfigPda] = this.getProgramConfigAccountPdaAndBump(); const [vaultDetailPda, vaultDetailBump] = this.getVaultDetailAccountPdaAndBump(vaultName); const [vaultBatchDetailPda] = this.getVaultBatchDetailAccountPdaAndBump(vaultDetailPda, batchIndex); const tx: Transaction = new Transaction(); const vaultBatchDetailTokenAccount: PublicKey = getAssociatedTokenAddressSync( tokenMintAccount, vaultBatchDetailPda, true, tokenProgram, associatedTokenProgram ); if (!await this.isPdaAddressInitialize(vaultBatchDetailTokenAccount)) { const createVaultBatchDetailTokenAccountIx: TransactionInstruction = createAssociatedTokenAccountInstruction( feeAndRentPayer, vaultBatchDetailTokenAccount, vaultBatchDetailPda, tokenMintAccount, tokenProgram, associatedTokenProgram ); tx.add(createVaultBatchDetailTokenAccountIx); } const openNewBatchIx: TransactionInstruction = await this.program.methods .openNewBatch({ name: vaultName, sharePrice: sharePrice, vaultDetailBump: vaultDetailBump, }) .accounts({ feeAndRentPayer: feeAndRentPayer, operator: operator, vaultDetail: vaultDetailPda, vaultBatchDetail: vaultBatchDetailPda, systemProgram: systemProgram, rent: rent }) .remainingAccounts([ // 0: Program Config { pubkey: programConfigPda, isSigner: false, isWritable: false }, ]) .instruction(); tx.add(openNewBatchIx); return tx; } async createDepositTransaction( feeAndRentPayer: PublicKey, operator: PublicKey, depositProvider: PublicKey, user: PublicKey, vaultName: string, batchIndex: number, depositIndex: number, depositAmount: BN, depositTxFeeReceiver: PublicKey, tokenMintAccount: PublicKey, tokenProgram: PublicKey, associatedTokenProgram: PublicKey, systemProgram: PublicKey, rent: PublicKey, ): Promise { const [programConfigPda] = this.getProgramConfigAccountPdaAndBump(); const [vaultDetailPda, vaultDetailBump] = this.getVaultDetailAccountPdaAndBump(vaultName); const [vaultBatchDetailPda, vaultBatchDetailBump] = this.getVaultBatchDetailAccountPdaAndBump(vaultDetailPda, batchIndex); const [userDetailPda] = this.getUserDetailAccountPdaAndBump(vaultDetailPda, user); const [userDepositDetailPda] = this.getUserDepositDetailAccountPdaAndBump(userDetailPda, depositIndex); const vaultBatchDetailTokenAccount = getAssociatedTokenAddressSync( tokenMintAccount, vaultBatchDetailPda, true, tokenProgram, associatedTokenProgram ); const depositProviderTokenAccount = getAssociatedTokenAddressSync( tokenMintAccount, depositProvider, true, tokenProgram, associatedTokenProgram ); const tx: Transaction = new Transaction(); const depositIx: TransactionInstruction = await this.program.methods .deposit({ name: vaultName, amount: depositAmount, batchIndex: batchIndex, depositIndex: depositIndex, vaultDetailBump: vaultDetailBump, vaultBatchDetailBump: vaultBatchDetailBump, }) .accounts({ feeAndRentPayer: feeAndRentPayer, operator: operator, depositProvider: depositProvider, user: user, vaultDetail: vaultDetailPda, vaultBatchDetail: vaultBatchDetailPda, userDetail: userDetailPda, userDepositDetail: userDepositDetailPda, tokenMintAccount: tokenMintAccount, systemProgram: systemProgram, rent: rent }) .remainingAccounts([ // 0: Program Config { pubkey: programConfigPda, isSigner: false, isWritable: false }, // 1: Token Program { pubkey: tokenProgram, isSigner: false, isWritable: false }, // 2: Vault Batch Detail Token Account { pubkey: vaultBatchDetailTokenAccount, isSigner: false, isWritable: true }, // 3: Deposit Provider Token Account { pubkey: depositProviderTokenAccount, isSigner: false, isWritable: true }, // 5: Deposit Tx Fee Receiver { pubkey: depositTxFeeReceiver, isSigner: false, isWritable: true }, ]) .instruction(); tx.add(depositIx); return tx; } async createCloseBatchTransaction( operator: PublicKey, vaultName: string, batchIndex: number, ): Promise { const [programConfigPda] = this.getProgramConfigAccountPdaAndBump(); const [vaultDetailPda, vaultDetailBump] = this.getVaultDetailAccountPdaAndBump(vaultName); const [vaultBatchDetailPda, vaultBatchDetailBump] = this.getVaultBatchDetailAccountPdaAndBump(vaultDetailPda, batchIndex); const tx: Transaction = new Transaction(); const closeBatchIx: TransactionInstruction = await this.program.methods .closeBatch({ name: vaultName, batchIndex: batchIndex, vaultDetailBump: vaultDetailBump, vaultBatchDetailBump: vaultBatchDetailBump, }) .accounts({ operator: operator, vaultDetail: vaultDetailPda, vaultBatchDetail: vaultBatchDetailPda, }) .remainingAccounts([ // 0: Program Config { pubkey: programConfigPda, isSigner: false, isWritable: false }, ]) .instruction(); tx.add(closeBatchIx); return tx; } async createUpdateUserStatusTransaction( operator: PublicKey, user: PublicKey, vaultName: string, userStatus: UserStatusType, ): Promise { const [programConfigPda] = this.getProgramConfigAccountPdaAndBump(); const [vaultDetailPda, vaultDetailBump] = this.getVaultDetailAccountPdaAndBump(vaultName); const [userDetailPda, userDetailBump] = this.getUserDetailAccountPdaAndBump(vaultDetailPda, user); const tx: Transaction = new Transaction(); const updateUserStatusIx: TransactionInstruction = await this.program.methods .updateUserStatus({ name: vaultName, userStatus: userStatus, vaultDetailBump: vaultDetailBump, userDetailBump: userDetailBump, }) .accounts({ operator: operator, user: user, vaultDetail: vaultDetailPda, userDetail: userDetailPda, }) .remainingAccounts([ // 0: Program Config { pubkey: programConfigPda, isSigner: false, isWritable: false }, ]) .instruction(); tx.add(updateUserStatusIx); return tx; } async createRequestWithdrawTransaction( feeAndRentPayer: PublicKey, operator: PublicKey, user: PublicKey, vaultName: string, batchIndex: number, withdrawIndex: number, withdrawAmount: BN, performanceFee: BN, systemProgram: PublicKey, rent: PublicKey, ): Promise { const [programConfigPda] = this.getProgramConfigAccountPdaAndBump(); const [vaultDetailPda, vaultDetailBump] = this.getVaultDetailAccountPdaAndBump(vaultName); const [vaultBatchDetailPda, vaultBatchDetailBump] = this.getVaultBatchDetailAccountPdaAndBump(vaultDetailPda, batchIndex); const [userDetailPda, userDetailBump] = this.getUserDetailAccountPdaAndBump(vaultDetailPda, user); const [userWithdrawDetailPda] = this.getUserWithdrawDetailAccountPdaAndBump(userDetailPda, withdrawIndex); const tx: Transaction = new Transaction(); const depositIx: TransactionInstruction = await this.program.methods .requestWithdraw({ name: vaultName, batchIndex: batchIndex, withdrawIndex: withdrawIndex, withdrawAmount: withdrawAmount, performanceFee: performanceFee, vaultDetailBump: vaultDetailBump, vaultBatchDetailBump: vaultBatchDetailBump, userDetailBump: userDetailBump }) .accounts({ feeAndRentPayer: feeAndRentPayer, operator: operator, user: user, vaultDetail: vaultDetailPda, vaultBatchDetail: vaultBatchDetailPda, userDetail: userDetailPda, userWithdrawDetail: userWithdrawDetailPda, systemProgram: systemProgram, rent: rent }) .remainingAccounts([ // 0: Program Config { pubkey: programConfigPda, isSigner: false, isWritable: false }, ]) .instruction(); tx.add(depositIx); return tx; } async createCanceledWithdrawTransaction( operator: PublicKey, user: PublicKey, vaultName: string, withdrawIndex: number, ): Promise { const [programConfigPda] = this.getProgramConfigAccountPdaAndBump(); const [vaultDetailPda, vaultDetailBump] = this.getVaultDetailAccountPdaAndBump(vaultName); const [userDetailPda, userDetailBump] = this.getUserDetailAccountPdaAndBump(vaultDetailPda, user); const [userWithdrawDetailPda, userWithdrawDetailBump] = this.getUserWithdrawDetailAccountPdaAndBump(userDetailPda, withdrawIndex); const tx: Transaction = new Transaction(); // const canceledWithdrawIx: TransactionInstruction = await this.program.methods // .canceledWithdraw({ // name: vaultName, // withdrawIndex: withdrawIndex, // vaultDetailBump: vaultDetailBump, // userDetailBump: userDetailBump, // userWithdrawDetailBump: userWithdrawDetailBump // }) // .accounts({ // operator: operator, // user: user, // vaultDetail: vaultDetailPda, // userDetail: userDetailPda, // userWithdrawDetail: userWithdrawDetailPda, // }) // .remainingAccounts([ // // 0: Program Config // { // pubkey: programConfigPda, // isSigner: false, // isWritable: false // }, // ]) // .instruction(); // // tx.add(canceledWithdrawIx); return tx; } async createProcessUserBatchTransaction( operator: PublicKey, user: PublicKey, vaultName: string, batchIndex: number, tokenMintAccount: PublicKey, tokenProgram: PublicKey, associatedTokenProgram: PublicKey, ): Promise { const [programConfigPda] = this.getProgramConfigAccountPdaAndBump(); const [vaultDetailPda, vaultDetailBump] = this.getVaultDetailAccountPdaAndBump(vaultName); const [vaultBatchDetailPda, vaultBatchDetailBump] = this.getVaultBatchDetailAccountPdaAndBump(vaultDetailPda, batchIndex); const [nextVaultBatchDetailPda, nextVaultBatchDetailBump] = this.getVaultBatchDetailAccountPdaAndBump(vaultDetailPda, batchIndex + 1); const [userDetailPda, userDetailBump] = this.getUserDetailAccountPdaAndBump(vaultDetailPda, user); const [userBatchDetailPda, userBatchDetailBump] = this.getUserBatchDetailAccountPdaAndBump(userDetailPda, batchIndex); const [vaultDepositTreasurePda] = this.getVaultDepositTreasureAccountPdaAndBump(vaultDetailPda); const vaultDepositTreasureTokenAccount = getAssociatedTokenAddressSync( tokenMintAccount, vaultDepositTreasurePda, true, tokenProgram, associatedTokenProgram ); const [vaultWithdrawTreasurePda] = this.getVaultWithdrawTreasureAccountPdaAndBump(vaultDetailPda); const vaultWithdrawTreasureTokenAccount = getAssociatedTokenAddressSync( tokenMintAccount, vaultWithdrawTreasurePda, true, tokenProgram, associatedTokenProgram ); const tx: Transaction = new Transaction(); const processUserBatchIx: TransactionInstruction = await this.program.methods .processUserBatch({ name: vaultName, batchIndex: batchIndex, vaultDetailBump: vaultDetailBump, vaultBatchDetailBump: vaultBatchDetailBump, nextVaultBatchDetailBump: nextVaultBatchDetailBump, userDetailBump: userDetailBump, userBatchDetailBump: userBatchDetailBump, }) .accounts({ operator: operator, user: user, vaultDetail: vaultDetailPda, vaultBatchDetail: vaultBatchDetailPda, nextVaultBatchDetail: nextVaultBatchDetailPda, userDetail: userDetailPda, userBatchDetail: userBatchDetailPda, tokenMintAccount: tokenMintAccount, }) .remainingAccounts([ // 0: Program Config { pubkey: programConfigPda, isSigner: false, isWritable: false }, // 1: Token Program { pubkey: tokenProgram, isSigner: false, isWritable: false }, // 2: Vault Withdraw Treasure { pubkey: vaultWithdrawTreasurePda, isSigner: false, isWritable: false }, // 3: Vault Withdraw Treasure Token Account { pubkey: vaultWithdrawTreasureTokenAccount, isSigner: false, isWritable: true }, // 4: Vault Deposit Treasure { pubkey: vaultDepositTreasurePda, isSigner: false, isWritable: false }, // 5: Vault Deposit Treasure Token Account { pubkey: vaultDepositTreasureTokenAccount, isSigner: false, isWritable: true }, ]) .instruction(); tx.add(processUserBatchIx); return tx; } async createConcludeBatchTransaction( feeAndRentPayer: PublicKey, operator: PublicKey, vaultName: string, batchIndex: number, tokenMintAccount: PublicKey, tokenProgram: PublicKey, associatedTokenProgram: PublicKey, ): Promise { const [programConfigPda] = this.getProgramConfigAccountPdaAndBump(); const [vaultDetailPda, vaultDetailBump] = this.getVaultDetailAccountPdaAndBump(vaultName); const [vaultBatchDetailPda, vaultBatchDetailBump] = this.getVaultBatchDetailAccountPdaAndBump(vaultDetailPda, batchIndex); const [vaultPerformanceFeeDetailPda, vaultPerformanceFeeDetailBump] = this.getVaultPerformanceFeeDetailAccountPdaAndBump(vaultDetailPda); const vaultPerformanceFeeDetailTokenAccount = getAssociatedTokenAddressSync( tokenMintAccount, vaultPerformanceFeeDetailPda, true, tokenProgram, associatedTokenProgram ); const [vaultRevenueFeeDetailPda, vaultRevenueFeeDetailBump] = this.getVaultRevenueFeeDetailAccountPdaAndBump(vaultDetailPda); const vaultRevenueFeeDetailTokenAccount = getAssociatedTokenAddressSync( tokenMintAccount, vaultRevenueFeeDetailPda, true, tokenProgram, associatedTokenProgram ); const [vaultWithdrawTreasurePda] = this.getVaultWithdrawTreasureAccountPdaAndBump(vaultDetailPda); const vaultWithdrawTreasureTokenAccount = getAssociatedTokenAddressSync( tokenMintAccount, vaultWithdrawTreasurePda, true, tokenProgram, associatedTokenProgram ); const [vaultDepositTreasurePda] = this.getVaultDepositTreasureAccountPdaAndBump(vaultDetailPda); const vaultDepositTreasureTokenAccount = getAssociatedTokenAddressSync( tokenMintAccount, vaultDepositTreasurePda, true, tokenProgram, associatedTokenProgram ); // Fetch vault detail to discover the deposit_receiver pubkey. const vaultDetailData = await this.getVaultDetailAccountData(vaultName); const depositReceiverTokenAccount = getAssociatedTokenAddressSync( tokenMintAccount, vaultDetailData.depositReceiver, true, tokenProgram, associatedTokenProgram ); const tx: Transaction = new Transaction(); // Ensure the deposit_receiver ATA exists — conclude_batch transfers tokens into it // but does not initialize it. feeAndRentPayer pays rent for the ATA creation. if (!await this.isPdaAddressInitialize(depositReceiverTokenAccount)) { const createDepositReceiverAtaIx: TransactionInstruction = createAssociatedTokenAccountInstruction( feeAndRentPayer, depositReceiverTokenAccount, vaultDetailData.depositReceiver, tokenMintAccount, tokenProgram, associatedTokenProgram ); tx.add(createDepositReceiverAtaIx); } const concludeBatchIx: TransactionInstruction = await this.program.methods .concludeBatch({ name: vaultName, batchIndex: batchIndex, vaultDetailBump: vaultDetailBump, vaultBatchDetailBump: vaultBatchDetailBump, vaultPerformanceFeeDetailBump: vaultPerformanceFeeDetailBump, vaultRevenueFeeDetailBump: vaultRevenueFeeDetailBump, }) .accounts({ operator: operator, vaultDetail: vaultDetailPda, vaultBatchDetail: vaultBatchDetailPda, vaultPerformanceFeeDetail: vaultPerformanceFeeDetailPda, vaultRevenueFeeDetail: vaultRevenueFeeDetailPda, tokenMintAccount: tokenMintAccount, }) .remainingAccounts([ // 0: Program Config { pubkey: programConfigPda, isSigner: false, isWritable: false }, // 1: Token Program { pubkey: tokenProgram, isSigner: false, isWritable: false }, // 2: Vault Withdraw Treasure { pubkey: vaultWithdrawTreasurePda, isSigner: false, isWritable: false }, // 3: Vault Withdraw Treasure Token Account { pubkey: vaultWithdrawTreasureTokenAccount, isSigner: false, isWritable: true }, // 4: Vault Performance Fee Token Account { pubkey: vaultPerformanceFeeDetailTokenAccount, isSigner: false, isWritable: true }, // 5: Vault Revenue Fee Token Account { pubkey: vaultRevenueFeeDetailTokenAccount, isSigner: false, isWritable: true }, // 6: Vault Deposit Treasure (PDA authority) { pubkey: vaultDepositTreasurePda, isSigner: false, isWritable: false }, // 7: Vault Deposit Treasure Token Account { pubkey: vaultDepositTreasureTokenAccount, isSigner: false, isWritable: true }, // 8: Deposit Receiver Token Account { pubkey: depositReceiverTokenAccount, isSigner: false, isWritable: true }, ]) .instruction(); tx.add(concludeBatchIx); return tx; } async createClaimWithdrawTransaction( operator: PublicKey, user: PublicKey, vaultName: string, batchIndex: number, withdrawIndex: number, tokenMintAccount: PublicKey, tokenProgram: PublicKey, associatedTokenProgram: PublicKey, ): Promise { const [programConfigPda] = this.getProgramConfigAccountPdaAndBump(); const [vaultDetailPda, vaultDetailBump] = this.getVaultDetailAccountPdaAndBump(vaultName); const [vaultBatchDetailPda, vaultBatchDetailBump] = this.getVaultBatchDetailAccountPdaAndBump(vaultDetailPda, batchIndex); const [userDetailPda, userDetailBump] = this.getUserDetailAccountPdaAndBump(vaultDetailPda, user); const [userBatchDetailPda, userBatchDetailBump] = this.getUserBatchDetailAccountPdaAndBump(userDetailPda, batchIndex); const [userWithdrawDetailPda, userWithdrawDetailBump] = this.getUserWithdrawDetailAccountPdaAndBump(userDetailPda, withdrawIndex); const [vaultWithdrawTreasurePda] = this.getVaultWithdrawTreasureAccountPdaAndBump(vaultDetailPda); const vaultWithdrawTreasureTokenAccount = getAssociatedTokenAddressSync( tokenMintAccount, vaultWithdrawTreasurePda, true, tokenProgram, associatedTokenProgram ); const userTokenAccount = getAssociatedTokenAddressSync( tokenMintAccount, user, true, tokenProgram, associatedTokenProgram ); const tx: Transaction = new Transaction(); const claimWithdrawIx: TransactionInstruction = await this.program.methods .claimWithdraw({ name: vaultName, batchIndex: batchIndex, withdrawIndex: withdrawIndex, vaultDetailBump: vaultDetailBump, vaultBatchDetailBump: vaultBatchDetailBump, userDetailBump: userDetailBump, userBatchDetailBump: userBatchDetailBump, userWithdrawDetailBump: userWithdrawDetailBump, }) .accounts({ operator: operator, user: user, vaultDetail: vaultDetailPda, vaultBatchDetail: vaultBatchDetailPda, userDetail: userDetailPda, userBatchDetail: userBatchDetailPda, userWithdrawDetail: userWithdrawDetailPda, tokenMintAccount: tokenMintAccount, }) .remainingAccounts([ // 0: Program Config { pubkey: programConfigPda, isSigner: false, isWritable: false }, // 1: Token Program { pubkey: tokenProgram, isSigner: false, isWritable: false }, // 2: Vault Withdraw Treasure { pubkey: vaultWithdrawTreasurePda, isSigner: false, isWritable: false }, // 3: Vault Withdraw Treasure Token Account { pubkey: vaultWithdrawTreasureTokenAccount, isSigner: false, isWritable: true }, // 4: User Token Account { pubkey: userTokenAccount, isSigner: false, isWritable: true }, ]) .instruction(); tx.add(claimWithdrawIx); return tx; } async createCollectDepositFeeTransaction( collector: PublicKey, vaultName: string, feeAmount: BN, tokenMintAccount: PublicKey, tokenProgram: PublicKey, associatedTokenProgram: PublicKey, ): Promise { const [programConfigPda] = this.getProgramConfigAccountPdaAndBump(); const [vaultDetailPda, vaultDetailBump] = this.getVaultDetailAccountPdaAndBump(vaultName); const [vaultDepositFeeDetailPda, vaultDepositFeeDetailBump] = this.getVaultDepositFeeDetailAccountPdaAndBump(vaultDetailPda); const vaultDepositFeeDetailTokenAccount = getAssociatedTokenAddressSync( tokenMintAccount, vaultDepositFeeDetailPda, true, tokenProgram, associatedTokenProgram ); const feeReceiverAccountMeta: AccountMeta[] = []; const vaultDepositFeeDetailData = await this.getVaultDepositFeeDetailAccountData(vaultName); for (let i = 0; i < vaultDepositFeeDetailData.receivers.length; i++) { const feeReceiverTokenAccount = getAssociatedTokenAddressSync( tokenMintAccount, vaultDepositFeeDetailData.receivers[i].receiver, true, tokenProgram, associatedTokenProgram ); feeReceiverAccountMeta.push({ pubkey: feeReceiverTokenAccount, isSigner: false, isWritable: true }); } const tx: Transaction = new Transaction(); const collectDepositFeeIx: TransactionInstruction = await this.program.methods .collectDepositFee({ name: vaultName, feeAmount: feeAmount, vaultDetailBump: vaultDetailBump, vaultDepositFeeDetailBump: vaultDepositFeeDetailBump, }) .accounts({ collector: collector, vaultDetail: vaultDetailPda, vaultDepositFeeDetail: vaultDepositFeeDetailPda, tokenMintAccount: tokenMintAccount, }) .remainingAccounts([ // 0: Program Config { pubkey: programConfigPda, isSigner: false, isWritable: false }, // 1: Token Program { pubkey: tokenProgram, isSigner: false, isWritable: false }, // 2: Vault Deposit Fee Detail Token Account { pubkey: vaultDepositFeeDetailTokenAccount, isSigner: false, isWritable: true }, ...feeReceiverAccountMeta ]) .instruction(); tx.add(collectDepositFeeIx); return tx; } async createCollectWithdrawFeeTransaction( collector: PublicKey, vaultName: string, feeAmount: BN, tokenMintAccount: PublicKey, tokenProgram: PublicKey, associatedTokenProgram: PublicKey, ): Promise { const [programConfigPda] = this.getProgramConfigAccountPdaAndBump(); const [vaultDetailPda, vaultDetailBump] = this.getVaultDetailAccountPdaAndBump(vaultName); const [vaultWithdrawFeeDetailPda, vaultWithdrawFeeDetailBump] = this.getVaultWithdrawFeeDetailAccountPdaAndBump(vaultDetailPda); const vaultWithdrawFeeDetailTokenAccount = getAssociatedTokenAddressSync( tokenMintAccount, vaultWithdrawFeeDetailPda, true, tokenProgram, associatedTokenProgram ); const feeReceiverAccountMeta: AccountMeta[] = []; const vaultWithdrawFeeDetailData = await this.getVaultWithdrawFeeDetailAccountData(vaultName); for (let i = 0; i < vaultWithdrawFeeDetailData.receivers.length; i++) { const feeReceiverTokenAccount = getAssociatedTokenAddressSync( tokenMintAccount, vaultWithdrawFeeDetailData.receivers[i].receiver, true, tokenProgram, associatedTokenProgram ); feeReceiverAccountMeta.push({ pubkey: feeReceiverTokenAccount, isSigner: false, isWritable: true }); } const tx: Transaction = new Transaction(); const collectWithdrawFeeIx: TransactionInstruction = await this.program.methods .collectWithdrawFee({ name: vaultName, feeAmount: feeAmount, vaultDetailBump: vaultDetailBump, vaultWithdrawFeeDetailBump: vaultWithdrawFeeDetailBump, }) .accounts({ collector: collector, vaultDetail: vaultDetailPda, vaultWithdrawFeeDetail: vaultWithdrawFeeDetailPda, tokenMintAccount: tokenMintAccount, }) .remainingAccounts([ // 0: Program Config { pubkey: programConfigPda, isSigner: false, isWritable: false }, // 1: Token Program { pubkey: tokenProgram, isSigner: false, isWritable: false }, // 2: Vault Withdraw Fee Detail Token Account { pubkey: vaultWithdrawFeeDetailTokenAccount, isSigner: false, isWritable: true }, ...feeReceiverAccountMeta ]) .instruction(); tx.add(collectWithdrawFeeIx); return tx; } async createCollectPerformanceFeeTransaction( collector: PublicKey, vaultName: string, feeAmount: BN, tokenMintAccount: PublicKey, tokenProgram: PublicKey, associatedTokenProgram: PublicKey, ): Promise { const [programConfigPda] = this.getProgramConfigAccountPdaAndBump(); const [vaultDetailPda, vaultDetailBump] = this.getVaultDetailAccountPdaAndBump(vaultName); const [vaultPerformanceFeeDetailPda, vaultPerformanceFeeDetailBump] = this.getVaultPerformanceFeeDetailAccountPdaAndBump(vaultDetailPda); const vaultPerformanceFeeDetailTokenAccount = getAssociatedTokenAddressSync( tokenMintAccount, vaultPerformanceFeeDetailPda, true, tokenProgram, associatedTokenProgram ); const feeReceiverAccountMeta: AccountMeta[] = []; const vaultPerformanceFeeDetailData = await this.getVaultPerformanceFeeDetailAccountData(vaultName); for (let i = 0; i < vaultPerformanceFeeDetailData.receivers.length; i++) { const feeReceiverTokenAccount = getAssociatedTokenAddressSync( tokenMintAccount, vaultPerformanceFeeDetailData.receivers[i].receiver, true, tokenProgram, associatedTokenProgram ); feeReceiverAccountMeta.push({ pubkey: feeReceiverTokenAccount, isSigner: false, isWritable: true }); } const tx: Transaction = new Transaction(); const collectPerformanceFeeIx: TransactionInstruction = await this.program.methods .collectPerformanceFee({ name: vaultName, feeAmount: feeAmount, vaultDetailBump: vaultDetailBump, vaultPerformanceFeeDetailBump: vaultPerformanceFeeDetailBump, }) .accounts({ collector: collector, vaultDetail: vaultDetailPda, vaultPerformanceFeeDetail: vaultPerformanceFeeDetailPda, tokenMintAccount: tokenMintAccount, }) .remainingAccounts([ // 0: Program Config { pubkey: programConfigPda, isSigner: false, isWritable: false }, // 1: Token Program { pubkey: tokenProgram, isSigner: false, isWritable: false }, // 2: Vault Performance Fee Detail Token Account { pubkey: vaultPerformanceFeeDetailTokenAccount, isSigner: false, isWritable: true }, ...feeReceiverAccountMeta ]) .instruction(); tx.add(collectPerformanceFeeIx); return tx; } // Events async removeEventListener(eventId: number) { await this.program.removeEventListener(eventId); } addAddWithdrawSupplyEventListener(callback: (event: AddWithdrawSupplyEvent) => void): number { return this.program.addEventListener(AddWithdrawSupplyEventName, callback); } addWithdrawSupplyEventListener(callback: (event: WithdrawSupplyEvent) => void): number { return this.program.addEventListener(WithdrawSupplyEventName, callback); } addOpenNewBatchEventListener(callback: (event: OpenNewBatchEvent) => void): number { return this.program.addEventListener(OpenNewBatchEventName, callback); } addDepositEventListener(callback: (event: DepositEvent) => void): number { return this.program.addEventListener(DepositEventName, callback); } addCloseBatchEventListener(callback: (event: CloseBatchEvent) => void): number { return this.program.addEventListener(CloseBatchEventName, callback); } addRequestWithdrawEventListener(callback: (event: RequestWithdrawEvent) => void): number { return this.program.addEventListener(RequestWithdrawEventName, callback); } addCollectDepositFeeEventListener(callback: (event: CollectDepositFeeEvent) => void): number { return this.program.addEventListener(CollectDepositFeeEventName, callback); } addCollectWithdrawFeeEventListener(callback: (event: CollectWithdrawFeeEvent) => void): number { return this.program.addEventListener(CollectWithdrawFeeEventName, callback); } addCollectPerformanceFeeEventListener(callback: (event: CollectPerformanceFeeEvent) => void): number { return this.program.addEventListener(CollectPerformanceFeeEventName, callback); } addCollectRevenueFeeEventListener(callback: (event: CollectRevenueFeeEvent) => void): number { return this.program.addEventListener(CollectRevenueFeeEventName, callback); } addCanceledWithdrawRequestEventListener(callback: (event: CanceledWithdrawRequestEvent) => void): number { return this.program.addEventListener(CanceledWithdrawRequestEventName, callback); } addProcessUserBatchEventListener(callback: (event: ProcessUserBatchEvent) => void): number { return this.program.addEventListener(ProcessUserBatchEventName, callback); } addConcludeBatchEventListener(callback: (event: ConcludeBatchEvent) => void): number { return this.program.addEventListener(ConcludeBatchEventName, callback); } addClaimWithdrawEventListener(callback: (event: ClaimWithdrawEvent) => void): number { return this.program.addEventListener(ClaimWithdrawEventName, callback); } addTransferTempEventListener(callback: (event: TransferTempEvent) => void): number { return this.program.addEventListener(TransferTempEventName, callback); } toU32Bytes(num: number): Uint8Array { const bytes = Buffer.alloc(4); u32.write(bytes, 0, num); return bytes; } }