UNPKG

eatthepie

Version:

Command line app for interacting with Eat The Pie, the world lottery on World Chain.

235 lines (209 loc) • 6.22 kB
import inquirer from "inquirer"; import chalk from "chalk"; import { loadConfig } from "../utils/config.js"; import { createPublicClient } from "../utils/ethereum.js"; import { getDetailedGameInfo } from "../services/gameService.js"; import { formatDifficulty } from "../utils/display.js"; import { formatEther } from "viem"; /** * Game status mapping */ const GAME_STATUS = { 0: "šŸŽ® In Play", 1: "šŸŽ² Drawing", 2: "āœ… Completed", }; /** * Prize tier labels */ const PRIZE_TIERS = ["šŸ† Jackpot", "🄈 3 in-a-row", "šŸ„‰ 2 in-a-row"]; /** * Validation messages */ const VALIDATION = { GAME_NUMBER: "āš ļø Please enter a valid game number", }; /** * Display defaults */ const DISPLAY = { NOT_AVAILABLE: "ā“", }; /** * Error messages that require special handling */ const ERROR_MESSAGES = { GAME_NOT_STARTED: "Game ID exceeds current game", }; /** * Error response messages */ const ERROR_RESPONSES = { GAME_NOT_STARTED: "āš ļø Game number you entered exceeds the current active game.", }; /** * Handles displaying detailed information about a specific game */ async function gameInfoHandler() { try { console.log(chalk.cyan("\nšŸ” Loading game information...")); const config = await loadConfig(); const publicClient = createPublicClient(config); // Get game number from user const gameNumber = await promptForGameNumber(); // Get and display game information const gameInfo = await getDetailedGameInfo( publicClient, config.contractAddress, gameNumber ); displayGameInformation(gameNumber, gameInfo, config.network); } catch (error) { handleError(error); } } /** * Prompts the user for a game number * @returns {Promise<number>} The selected game number */ async function promptForGameNumber() { const { gameNumber } = await inquirer.prompt([ { type: "number", name: "gameNumber", message: "šŸŽ® Enter the past game number you want to view:", validate: (input) => input > 0 || VALIDATION.GAME_NUMBER, }, ]); return gameNumber; } /** * Displays all game information * @param {number} gameNumber - The game number * @param {Object} gameInfo - The detailed game information * @param {string} network - The network name */ function displayGameInformation(gameNumber, gameInfo, network) { const status = GAME_STATUS[Number(gameInfo.status)]; const areNumbersSet = gameInfo.winningNumbers[0] !== 0n; console.log(chalk.yellow(`\nšŸŽ² Game ${gameNumber} Information:`)); // Display basic game info displayBasicInfo(gameInfo, status, network); // Display block information displayBlockInfo(gameInfo, status); // Display winning information displayWinningInfo(gameInfo, status, areNumbersSet, network); } /** * Displays basic game information * @param {Object} gameInfo - The game information * @param {string} status - The game status * @param {string} network - The network name */ function displayBasicInfo(gameInfo, status, network) { console.log(chalk.cyan("šŸ“Š Status:"), status); console.log( chalk.cyan("šŸ’° Prize Pool:"), formatEther(gameInfo.prizePool), network === "worldchain" ? "WLD" : "ETH" ); console.log( chalk.cyan("šŸŽÆ Difficulty:"), formatDifficulty(gameInfo.difficulty) ); } /** * Displays block-related information * @param {Object} gameInfo - The game information * @param {string} status - The game status */ function displayBlockInfo(gameInfo, status) { const isInPlay = status === "šŸŽ® In Play"; console.log( chalk.cyan("šŸ“” Draw Initiated Block:"), isInPlay ? DISPLAY.NOT_AVAILABLE : gameInfo.drawInitiatedBlock.toString() ); console.log( chalk.cyan("šŸŽ² Witnet Randomness Value:"), isInPlay || !gameInfo.randomValue ? DISPLAY.NOT_AVAILABLE : gameInfo.randomValue.toString() ); } /** * Displays winning-related information * @param {Object} gameInfo - The game information * @param {string} status - The game status * @param {boolean} areNumbersSet - Whether the winning numbers have been set * @param {string} network - The network name */ function displayWinningInfo(gameInfo, status, areNumbersSet, network) { console.log( chalk.cyan("šŸŽÆ Winning Numbers:"), areNumbersSet ? gameInfo.winningNumbers.join(", ") : DISPLAY.NOT_AVAILABLE ); console.log( chalk.cyan("šŸ‘„ Number of Winners:"), areNumbersSet ? `${gameInfo.numberOfWinners.toString()} (šŸ†: ${ gameInfo.goldWinners }, 🄈: ${gameInfo.silverWinners}, šŸ„‰: ${gameInfo.bronzeWinners})` : DISPLAY.NOT_AVAILABLE ); displayPayouts(gameInfo, status, network); } /** * Formats and displays payout information * @param {Object} gameInfo - The game information * @param {string} status - The game status * @param {string} network - The network name */ function displayPayouts(gameInfo, status, network) { console.log( chalk.cyan("šŸ’ø Payouts:"), status === "āœ… Completed" ? formatPayouts(gameInfo.payouts, network) : DISPLAY.NOT_AVAILABLE ); } /** * Formats payout information into a readable string * @param {bigint[]} payouts - Array of payout amounts * @param {string} network - The network name * @returns {string} Formatted payout string */ function formatPayouts(payouts, network) { return payouts .map((payout, index) => { return `${PRIZE_TIERS[index]}: ${formatEther(payout)} ${ network === "worldchain" ? "WLD" : "ETH" }`; }) .join(", "); } /** * Handles errors that occur during the game info display * @param {Error} error - The error to handle */ function handleError(error) { if (error.message.includes(ERROR_MESSAGES.GAME_NOT_STARTED)) { console.log(chalk.yellow(ERROR_RESPONSES.GAME_NOT_STARTED)); } else { console.error( chalk.red("\nāŒ Error:"), error.shortMessage || error.message ); console.error( chalk.red( "\nāš ļø Make sure your settings are correct.\nšŸ”§ Run 'config' to view them and 'setup' to reset them." ) ); process.exit(1); } } export default { command: "game-info", describe: "šŸŽ² Get game information", handler: gameInfoHandler, };