import { BN } from '@project-serum/anchor'; import type { Wallet } from '@saberhq/solana-contrib'; import type { AccountMeta, Connection, PublicKey, Transaction } from '@solana/web3.js'; import { Keypair, SystemProgram } from '@solana/web3.js'; import { tryGetAccount } from '../../utils/tryGetAccount'; import { withFindOrInitAssociatedTokenAccount } from '../../utils/withFindOrInitAssociatedTokenAccount'; import { getIdentifier } from './accounts'; import { BLAZE_ADDRESS } from './constants'; import { claimPrizeInstruction, closeBlazeInstruction, initBlazeInstruction, initIdentifierInstruction, redeemEntrantsInstruction, resolveBlazeInstruction, updateBlazeInstruction } from './instruction'; import { findBlazeId, findIdentifierId } from './pda'; /** * Add init blaze identifier instructions to a transaction * @param transaction * @param connection * @param wallet * @returns Transaction, public key for the created blaze identifier */ export const withInitBlazeIdentifier = async ( transaction: Transaction, connection: Connection, wallet: Wallet ): Promise<[Transaction, PublicKey]> => { const [identifierId] = await findIdentifierId(); transaction.add( await initIdentifierInstruction(connection, wallet, { identifierId: identifierId }) ); return [transaction, identifierId]; }; export const withInitBlaze = async ( transaction: Transaction, connection: Connection, wallet: Wallet, params: { prizeMint: PublicKey; tokenMint?: PublicKey; tokenAccount?: PublicKey; treasury?: PublicKey; burnRate?: number; entrantFee: BN; maxEntrants: number; start: BN; end: BN; maxEntrantsPerWalletRate?: number; projectId: PublicKey; projectWallet: PublicKey; category?: string; } ): Promise<[Transaction, PublicKey, Keypair]> => { const [[identifierId], identifierData] = await Promise.all([ findIdentifierId(), tryGetAccount(() => getIdentifier(connection)) ]); const identifier = (identifierData?.parsed.count as BN) || new BN(1); if (!identifierData) { transaction.add( await initIdentifierInstruction(connection, wallet, { identifierId: identifierId }) ); } const [blazeId] = await findBlazeId(identifier); const [blazePrizeMintTokenAccount, userPrizeMintTokenAccount] = await Promise.all([ withFindOrInitAssociatedTokenAccount( transaction, connection, params.prizeMint, blazeId, wallet.publicKey, true ), withFindOrInitAssociatedTokenAccount( transaction, connection, params.prizeMint, wallet.publicKey, wallet.publicKey ) ]); const entrantsAccountDataSize = 8 + 4 + 4 + 32 * params.maxEntrants; const entrantsKeyPair = Keypair.generate(); const lamports = await connection.getMinimumBalanceForRentExemption( entrantsAccountDataSize, 'confirmed' ); transaction.add( SystemProgram.createAccount({ fromPubkey: wallet.publicKey, newAccountPubkey: entrantsKeyPair.publicKey, space: entrantsAccountDataSize, lamports, programId: BLAZE_ADDRESS }), await initBlazeInstruction(connection, wallet, { identifierId, blazeId, projectId: params.projectId, projectWallet: params.projectWallet, blazePrizeMintTokenAccount, userPrizeMintTokenAccount, entrants: entrantsKeyPair.publicKey, tokenMint: params.tokenMint, tokenAccount: params.tokenAccount, treasury: params.treasury, burnRate: params.burnRate, category: params.category, prizeMint: params.prizeMint, entrantFee: params.entrantFee, maxEntrants: params.maxEntrants, start: params.start, end: params.end, maxEntrantsPerWalletRate: params.maxEntrantsPerWalletRate }) ); return [transaction, blazeId, entrantsKeyPair]; }; export const withUpdateBlaze = async ( transaction: Transaction, connection: Connection, wallet: Wallet, params: { blazeId: PublicKey; projectId: PublicKey; tokenMint?: PublicKey; tokenAccount?: PublicKey; treasury?: PublicKey; burnRate?: number; entrantFee: BN; start: BN; end: BN; maxEntrantsPerWalletRate?: number; category?: string; } ): Promise => { transaction.add( await updateBlazeInstruction(connection, wallet, { blazeId: params.blazeId, projectId: params.projectId, tokenMint: params.tokenMint, tokenAccount: params.tokenAccount, treasury: params.treasury, burnRate: params.burnRate, entrantFee: params.entrantFee, start: params.start, end: params.end, maxEntrantsPerWalletRate: params.maxEntrantsPerWalletRate, category: params.category }) ); return transaction; }; export const withCloseBlaze = async ( transaction: Transaction, connection: Connection, wallet: Wallet, params: { blazeId: PublicKey; projectId: PublicKey; prizeMint: PublicKey; entrants: PublicKey; } ): Promise => { const [blazePrizeMintTokenAccount, userPrizeMintTokenAccount] = await Promise.all([ withFindOrInitAssociatedTokenAccount( transaction, connection, params.prizeMint, params.blazeId, wallet.publicKey, true ), withFindOrInitAssociatedTokenAccount( transaction, connection, params.prizeMint, wallet.publicKey, wallet.publicKey ) ]); transaction.add( await closeBlazeInstruction(connection, wallet, { blazeId: params.blazeId, projectId: params.projectId, entrants: params.entrants, blazePrizeMintTokenAccount, userPrizeMintTokenAccount }) ); return transaction; }; export const withRedeemEntrants = async ( transaction: Transaction, connection: Connection, wallet: Wallet, params: { quantity: number; blazeId: PublicKey; entrants: PublicKey; remainingAccountsForRedeem: AccountMeta[]; } ): Promise => { transaction.add(await redeemEntrantsInstruction(connection, wallet, params)); return transaction; }; export const withResolveBlaze = async ( transaction: Transaction, connection: Connection, wallet: Wallet, params: { blazeId: PublicKey; entrants: PublicKey; } ): Promise => { transaction.add( await resolveBlazeInstruction(connection, wallet, { blazeId: params.blazeId, entrants: params.entrants }) ); return transaction; }; export const withClaimPrize = async ( transaction: Transaction, connection: Connection, wallet: Wallet, params: { blazeId: PublicKey; prizeMint: PublicKey; } ): Promise => { const [blazePrizeMintTokenAccount, winnerPrizeMintTokenAccount] = await Promise.all([ withFindOrInitAssociatedTokenAccount( transaction, connection, params.prizeMint, params.blazeId, wallet.publicKey, true ), withFindOrInitAssociatedTokenAccount( transaction, connection, params.prizeMint, wallet.publicKey, wallet.publicKey ) ]); transaction.add( await claimPrizeInstruction(connection, wallet, { blazeId: params.blazeId, blazePrizeMintTokenAccount, winnerPrizeMintTokenAccount }) ); return transaction; };