import { BN, Program, Wallet, web3 } from "@project-serum/anchor"; import { SendTxRequest } from "@project-serum/anchor/dist/provider"; import { PublicKey, Signer, SystemProgram } from "@solana/web3.js"; import { CONSTRUCTION_ACCOUNT_SIZE, LIFETIME_CONSTRUCTION_ACCOUNT_MS, } from "../constants"; import { calculateRent } from "../solana-utils"; import { breakUpInstrDataArrays } from "./helpers"; export const prepareConstruction = ( program: Program, construction: PublicKey, initActionIdx: number[], initActionSplits: number[], authority: Signer | Wallet, amounts: BN[] ): SendTxRequest[] => { const signers = (authority as Signer).secretKey ? [authority as Signer] : []; const items = initActionSplits.map((split, i) => { return { idx: initActionIdx[i], split }; }); const createTxFn = (items: { idx: number; split: number }[]) => { const idxs = items.map((i) => i.idx); const splits = items.map((i) => i.split); return getAddInitInfosTx( program, idxs, splits, authority, construction, signers ); }; const addInitTxRequests = breakUpInstrDataArrays(items, createTxFn); return [ ...addInitTxRequests, getPrepareTx(program, construction, signers, amounts, authority), ]; }; const getPrepareTx = ( program: Program, construction: PublicKey, signers: Signer[], amounts: BN[], authority: Signer | Wallet ) => { return { tx: program.transaction.prepareConstruction(amounts, { accounts: { authority: authority.publicKey, construction: construction, rent: web3.SYSVAR_RENT_PUBKEY, }, signers, }), signers, }; }; export const getAddInitInfosTx = ( program: Program, initActionIdx: number[], initActionSplits: number[], authority: Wallet | Signer, construction: PublicKey, signers: Signer[] ): SendTxRequest => { return { tx: program.transaction.addInitInfo( initActionIdx, initActionSplits.map((i) => new BN(i)), { accounts: { authority: authority.publicKey, construction: construction, rent: web3.SYSVAR_RENT_PUBKEY, }, signers, } ), signers, }; }; export const createAndInitConstruction = async ( program: Program, authority: PublicKey, numbActions: number ): Promise<{ construction: Signer; tx: SendTxRequest }> => { const constructionSize = CONSTRUCTION_ACCOUNT_SIZE; const ConstructionAccount = web3.Keypair.generate(); const tx = program.transaction.initConstruction(numbActions, { accounts: { construction: ConstructionAccount.publicKey, authority, rent: web3.SYSVAR_RENT_PUBKEY, }, signers: [ConstructionAccount], instructions: [ await SystemProgram.createAccount({ fromPubkey: program.provider.wallet.publicKey, newAccountPubkey: ConstructionAccount.publicKey, space: constructionSize + 8, lamports: calculateRent( constructionSize + 8, LIFETIME_CONSTRUCTION_ACCOUNT_MS ), programId: program.programId, }), ], }); return { tx: { tx, signers: [ConstructionAccount] }, construction: ConstructionAccount, }; }; export const closeConstructionAccount = ( program: Program, construction: PublicKey, recipientSol: PublicKey, authority: Wallet | Signer ): SendTxRequest => { const signers = (authority as Signer).secretKey ? [authority as Signer] : []; const tx = program.transaction.closeConstruction({ accounts: { construction: { construction, authority: authority.publicKey, }, recipient: recipientSol, rent: web3.SYSVAR_RENT_PUBKEY, }, signers, }); return { tx, signers, }; };