import { PublicKey, TransactionInstruction, SystemProgram, SYSVAR_RENT_PUBKEY, } from "@solana/web3.js"; import BN from "bn.js"; import { ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID } from "@solana/spl-token"; import type { PitProgram } from "../program.js"; import { WSOL_MINT, TOKEN_2022_PROGRAM_ID } from "../constants.js"; import { getMarketAddress, getWsolVaultAddress, getRegistryAddress } from "../accounts/pda.js"; /** * Parameters for creating an initialize_market instruction * * This merged instruction creates a complete market with both High and Low pools * in a single transaction. */ interface InitializeMarketParams { /** Week number for this market (unique identifier) */ weekNumber: number; /** Unix timestamp when the market ends */ endTimestamp: BN; /** Total subsidy in lamports (SOL to seed liquidity, split 50/50 between pools) */ totalSubsidy: BN; /** Operator's public key (must match hardcoded OPERATOR) */ operator: PublicKey; /** Pyth price update account for SOL/USD */ priceUpdate: PublicKey; /** Initial q_vector for High pool [S0, S1, S2, S3] - values in WAD format (10^18) */ highQVector: [BN, BN, BN, BN]; /** Initial q_vector for Low pool [S0, S1, S2, S3] - values in WAD format (10^18) */ lowQVector: [BN, BN, BN, BN]; /** * All 12 mint accounts in order: * - [0-2]: High pool HIT mints (strike 0, 1, 2) * - [3-5]: High pool MISS mints (strike 0, 1, 2) * - [6-8]: Low pool HIT mints (strike 0, 1, 2) * - [9-11]: Low pool MISS mints (strike 0, 1, 2) */ mints: PublicKey[]; /** wSOL mint address (usually WSOL_MINT constant) */ wsolMint?: PublicKey; } /** * Create an initialize_market instruction * * This instruction is operator-only. It creates a complete market with both * High and Low pools, initializes all 12 token mints with metadata, transfers * the subsidy, and registers the market in the global registry. * * Strikes are automatically calculated on-chain from the current Pyth SOL/USD price. * * @param program - Anchor Program instance * @param params - Initialize market parameters * @returns Promise resolving to TransactionInstruction * * @example * ```typescript * import { createProgram, createInitializeMarketInstruction, createZeroQVector, getAllMintAddresses } from "@pit-protocol/sdk"; * * const program = createProgram(provider); * * // First, create 12 Token-2022 mints with MetadataPointer extension * const mints = getAllMintAddresses(2604); * * // Get Pyth price update account * const priceUpdate = SOL_USD_PRICE_FEED_ACCOUNT; * * // Create the instruction * const ix = await createInitializeMarketInstruction(program, { * weekNumber: 2604, * endTimestamp: new BN(Math.floor(Date.now() / 1000) + 7 * 24 * 60 * 60), * totalSubsidy: new BN(10 * LAMPORTS_PER_SOL), * operator: operatorKeypair.publicKey, * priceUpdate, * highQVector: createZeroQVector(), * lowQVector: createZeroQVector(), * mints, * }); * * const tx = new Transaction().add(ix); * await sendAndConfirmTransaction(connection, tx, [operatorKeypair]); * ``` */ export async function createInitializeMarketInstruction( program: PitProgram, params: InitializeMarketParams ): Promise { const { weekNumber, endTimestamp, totalSubsidy, operator, priceUpdate, highQVector, lowQVector, mints, wsolMint = WSOL_MINT, } = params; // Validate mints count if (mints.length !== 12) { throw new Error(`Expected 12 mints, got ${mints.length}`); } const marketState = getMarketAddress(weekNumber); const wsolVault = getWsolVaultAddress(marketState, wsolMint); const registry = getRegistryAddress(); // Convert q_vectors to array format expected by Anchor const highQVectorArg = highQVector.map((q) => q); const lowQVectorArg = lowQVector.map((q) => q); return await program.methods .initializeMarket(weekNumber, endTimestamp, totalSubsidy, highQVectorArg, lowQVectorArg) .accountsPartial({ marketState, operator, wsolMint, wsolVault, registry, priceUpdate, systemProgram: SystemProgram.programId, tokenProgram: TOKEN_PROGRAM_ID, associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, token2022Program: TOKEN_2022_PROGRAM_ID, rent: SYSVAR_RENT_PUBKEY, }) .remainingAccounts( mints.map((mint) => ({ pubkey: mint, isSigner: false, isWritable: true, })) ) .instruction(); } /** * Helper to create zero q_vector (equal probability for all outcomes). * All outcomes start at 25% probability. */ export function createZeroQVector(): [BN, BN, BN, BN] { return [new BN(0), new BN(0), new BN(0), new BN(0)]; }