import { calculateOutcome } from "./calculate.js"; /** * Verify that SDK outcome calculation matches expected on-chain verification * * This helper is primarily used in tests to ensure SDK and on-chain logic remain aligned. * It compares the SDK's calculateOutcome result against the expected outcome that the * on-chain program would verify. * * On-chain reference: programs/pit/src/instructions/mark_extreme.rs:205-241 * * @param priceInCents - Price in cents * @param strikes - Strike prices in cents * @param expectedHighOutcome - Expected High pool outcome (or null to skip) * @param expectedLowOutcome - Expected Low pool outcome (or null to skip) * @returns True if SDK matches expected outcomes * * @example * ```typescript * // Verify High Pool outcome=1 requires price >= strikes[0] * const strikes = [14000, 15000, 16000]; * assert(verifyOutcomeAlignment(14000, strikes, 1, null)); // price >= 140 * assert(!verifyOutcomeAlignment(13999, strikes, 1, null)); // price < 140 * * // Verify Low Pool outcome=1 requires price < strikes[0] * const lowStrikes = [16000, 15000, 14000]; // descending * assert(verifyOutcomeAlignment(15999, lowStrikes, null, 1)); // price < 160 * assert(!verifyOutcomeAlignment(16000, lowStrikes, null, 1)); // price >= 160 * ``` */ export function verifyOutcomeAlignment( priceInCents: number, strikes: [number, number, number], expectedHighOutcome: number | null = null, expectedLowOutcome: number | null = null ): boolean { const result = calculateOutcome(priceInCents, strikes); if (expectedHighOutcome !== null && result.highOutcome !== expectedHighOutcome) { return false; } if (expectedLowOutcome !== null && result.lowOutcome !== expectedLowOutcome) { return false; } return true; } /** * Get the required strike price for a given outcome and pool type * * This matches the on-chain verification logic in mark_extreme.rs where * the program checks if the price satisfies the claimed outcome. * * @param poolType - "high" or "low" * @param outcome - Outcome number (0-3) * @param strikes - Strike prices in cents * @returns Required strike price for verification * * @example * ```typescript * const highStrikes = [14000, 15000, 16000]; * getRequiredStrike("high", 1, highStrikes); // Returns 14000 (must be >= s0) * getRequiredStrike("high", 2, highStrikes); // Returns 15000 (must be >= s1) * * const lowStrikes = [16000, 15000, 14000]; * getRequiredStrike("low", 1, lowStrikes); // Returns 16000 (must be < s0) * getRequiredStrike("low", 3, lowStrikes); // Returns 14000 (must be < s2) * ``` */ export function getRequiredStrike( poolType: "high" | "low", outcome: number, strikes: [number, number, number] ): number | null { if (outcome === 0) { return null; // Outcome 0 has no strike requirement } // Both High and Low use outcome-1 as strike index // High: outcome 1 → strikes[0], outcome 2 → strikes[1], outcome 3 → strikes[2] // Low: outcome 1 → strikes[0], outcome 2 → strikes[1], outcome 3 → strikes[2] const strikeIndex = outcome - 1; return strikes[strikeIndex]; }