UNPKG

axie-tools

Version:

TypeScript library and CLI tool for interacting with Axie Infinity marketplace and NFTs on Ronin network. Features marketplace operations (buy/sell/delist), batch transfers, and wallet information.

468 lines (467 loc) • 25.9 kB
#!/usr/bin/env node "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const prompts_1 = require("@inquirer/prompts"); const ethers_1 = require("ethers"); const axie_1 = require("./lib/axie"); const access_token_1 = require("./lib/marketplace/access-token"); const transfers_1 = require("./lib/transfers"); const utils_1 = require("./lib/utils"); const approve_1 = require("./lib/marketplace/approve"); const settle_order_1 = __importDefault(require("./lib/marketplace/settle-order")); const cancel_order_1 = __importDefault(require("./lib/marketplace/cancel-order")); const create_order_1 = __importDefault(require("./lib/marketplace/create-order")); const atia_1 = require("./lib/atia"); const delegation_1 = require("./lib/atia/delegation"); const graphql_1 = require("./lib/atia/graphql"); require("dotenv/config"); async function main() { // Check for PRIVATE_KEY before the main loop let privateKey = process.env.PRIVATE_KEY; if (!privateKey) { privateKey = await (0, prompts_1.password)({ message: "šŸ” Enter your private key:", validate: (value) => { if (!value) return false; // Private keys are 32 bytes (64 characters) + optional "0x" prefix return (0, ethers_1.isHexString)(value, 32) || (0, ethers_1.isHexString)(`0x${value}`, 32); }, }); // Ensure "0x" prefix privateKey = privateKey.startsWith("0x") ? privateKey : `0x${privateKey}`; } // Initialize provider with a reliable RPC endpoint const provider = new ethers_1.JsonRpcProvider("https://api.roninchain.com/rpc"); // Initialize wallet with the previously obtained private key const wallet = new ethers_1.Wallet(privateKey, provider); const address = await wallet.getAddress(); while (true) { try { const action = await (0, prompts_1.select)({ message: "What would you like to do?", choices: [ { name: "Get account info", value: "account" }, { name: "Refresh access token", value: "refresh-token" }, { name: "Approve WETH", value: "approve-weth" }, { name: "Approve marketplace", value: "approve-marketplace" }, { name: "Buy axie", value: "buy" }, { name: "Delist axie", value: "delist" }, { name: "Delist multiple axies", value: "delist-all" }, { name: "List axie", value: "list" }, { name: "List multiple axies", value: "list-all" }, { name: "Transfer axie", value: "transfer" }, { name: "Transfer multiple axies", value: "transfer-all" }, { name: "Delegate axie", value: "delegate-axie" }, { name: "Revoke axie delegation", value: "revoke-delegation-axie" }, { name: "Delegate multiple axies", value: "batch-delegate" }, { name: "Revoke multiple delegations", value: "batch-revoke" }, { name: "Check Atia blessing status", value: "check-blessing" }, { name: "Pray for Atia blessing", value: "pray-blessing" }, { name: "Create Atia Blessing delegation", value: "delegate" }, { name: "List Atia Blessing delegations", value: "list-delegations" }, { name: "Revoke Atia Blessing delegation", value: "revoke-delegation" }, ], }); switch (action) { case "account": { const info = await (0, utils_1.getAccountInfo)(address, provider); console.log(`šŸ“¬ Address: ${info.address}`); console.log("šŸ’° RON Balance:", info.ronBalance); console.log("šŸ’° WETH Balance:", info.wethBalance); console.log("šŸ’° USDC Balance:", info.usdcBalance); console.log("šŸ›’ Marketplace WETH allowance:", info.allowance !== 0n ? "āœ… Granted" : "āŒ Not granted"); console.log("šŸ” Marketplace approval for Axies:", info.isApprovedForAll ? "āœ… Approved" : "āŒ Not approved"); console.log(`🐾 Number of Axies: ${info.axieIds.length}`); if (info.axieIds.length > 0) { console.log(`šŸ†” Axie IDs: ${info.axieIds.join(", ")}`); } break; } case "refresh-token": { let refreshTokenValue = process.env.MARKETPLACE_REFRESH_TOKEN; if (!refreshTokenValue) { refreshTokenValue = await (0, prompts_1.input)({ message: "Enter refresh token", validate: (value) => value.length > 0, }); } const result = await (0, access_token_1.refreshToken)(refreshTokenValue); console.log("New access token:", result.newAccessToken); console.log("New refresh token:", result.newRefreshToken); process.env.MARKETPLACE_ACCESS_TOKEN = result.newAccessToken; process.env.MARKETPLACE_REFRESH_TOKEN = result.newRefreshToken; break; } case "approve-weth": { await (0, approve_1.approveWETH)(wallet); break; } case "approve-marketplace": { await (0, approve_1.approveMarketplaceContract)(wallet); break; } case "buy": { const token = await (0, utils_1.ensureMarketplaceToken)(); const axieId = await (0, utils_1.getAxieId)(); if (!axieId) break; await (0, approve_1.approveWETH)(wallet); const receipt = await (0, settle_order_1.default)(axieId, wallet, token); if (receipt) { console.log("šŸš€ Transaction successful! Hash:", receipt.hash); console.log(`šŸ”— View transaction: https://app.roninchain.com/tx/${receipt.hash}`); } break; } case "list": { const axieId = await (0, utils_1.getAxieId)(); if (!axieId) break; const token = await (0, utils_1.ensureMarketplaceToken)(); const basePrice = await (0, prompts_1.input)({ message: "Enter base price in ETH", validate: (value) => (0, ethers_1.parseEther)(value) > 0n, }); await (0, approve_1.approveMarketplaceContract)(wallet); const currentBlock = await provider.getBlock("latest"); const startedAt = currentBlock?.timestamp ?? Math.floor(Date.now() / 1000); const expiredAt = startedAt + 15634800; // ~6 months const orderData = { address, axieId: axieId.toString(), basePrice: (0, ethers_1.parseEther)(basePrice).toString(), endedPrice: "0", startedAt, endedAt: 0, expiredAt, }; const result = await (0, create_order_1.default)(orderData, token, wallet); if (result === null || result.errors || !result.data) { console.error("āŒ Error:", result?.errors?.[0]?.message || "Unknown error"); break; } console.log(`āœ… Listed Axie ${axieId}! Current price in USD: ${result.data.createOrder.currentPriceUsd}`); break; } case "list-all": { const token = await (0, utils_1.ensureMarketplaceToken)(); const basePrice = await (0, prompts_1.input)({ message: "Enter base price in ETH (for all Axies)", validate: (value) => (0, ethers_1.parseEther)(value) > 0n, }); await (0, approve_1.approveMarketplaceContract)(wallet); let axieIds = await (0, axie_1.getAxieIdsFromAccount)(address, provider); if (axieIds.length > 100) { console.log("āš ļø Warning: Can only list up to 100 Axies at once, only listing the first 100"); axieIds = axieIds.slice(0, 100); } const currentBlock = await provider.getBlock("latest"); const startedAt = currentBlock?.timestamp ?? Math.floor(Date.now() / 1000); const expiredAt = startedAt + 15634800; // ~6 months for (const axieId of axieIds) { const orderData = { address, axieId: axieId.toString(), basePrice: (0, ethers_1.parseEther)(basePrice).toString(), endedPrice: "0", startedAt, endedAt: 0, expiredAt, }; const result = await (0, create_order_1.default)(orderData, token, wallet); if (result === null || result.errors || !result.data) { console.error(`āŒ Error listing Axie ${axieId}:`, result?.errors?.[0]?.message || "Unknown error"); continue; } console.log(`āœ… Listed Axie ${axieId}! Current price in USD: ${result.data.createOrder.currentPriceUsd}`); } break; } case "delist": { const axieId = await (0, utils_1.getAxieId)(); if (!axieId) break; const receipt = await (0, cancel_order_1.default)(axieId, wallet); if (receipt) { console.log("āœ… Axie delisted! Transaction hash:", receipt.hash); console.log(`šŸ”— View transaction: https://app.roninchain.com/tx/${receipt.hash}`); } break; } case "delist-all": { const axieIdsInput = await (0, prompts_1.input)({ message: "Enter comma-separated Axie IDs to delist (e.g. 123, 456, 789)", validate: (value) => { const ids = value.split(",").map(id => id.trim()); return ids.length > 0 && ids.every(id => !Number.isNaN(Number(id))); }, }); let axieIds = axieIdsInput.split(",").map(id => id.trim()); if (axieIds.length > 100) { console.log("āš ļø Warning: Can only delist up to 100 Axies at once, only delisting the first 100"); axieIds = axieIds.slice(0, 100); } const receipt = await (0, transfers_1.batchTransferAxies)(wallet, await wallet.getAddress(), axieIds); if (receipt) { console.log("āœ… Axies delisted! Transaction hash:", receipt.hash); console.log(`šŸ”— View transaction: https://app.roninchain.com/tx/${receipt.hash}`); } else { console.log("āŒ Error delisting Axies"); } break; } case "transfer": { const axieId = await (0, utils_1.getAxieId)(); if (!axieId) break; const address = await (0, prompts_1.input)({ message: "Enter recipient address", validate: (value) => value.length > 0, }); const receipt = await (0, transfers_1.transferAxie)(wallet, address, axieId); if (receipt) { console.log("āœ… Axie transferred! Transaction hash:", receipt.hash); } break; } case "transfer-all": { const axieIdsInput = await (0, prompts_1.input)({ message: "Enter comma-separated Axie IDs (e.g. 123, 456, 789)", validate: (value) => { const ids = value.split(",").map(id => id.trim()); return ids.length > 0 && ids.every(id => !Number.isNaN(Number(id))); }, }); let axieIds = axieIdsInput.split(",").map(id => id.trim()); if (axieIds.length > 100) { console.log("āš ļø Warning: Can only transfer up to 100 Axies at once, only transferring the first 100"); axieIds = axieIds.slice(0, 100); } const address = await (0, prompts_1.input)({ message: "Enter recipient address", validate: (value) => value.length > 0, }); const receipt = await (0, transfers_1.batchTransferAxies)(wallet, address, axieIds); if (receipt) { console.log("āœ… Axies transferred! Transaction hash:", receipt.hash); } break; } case "delegate-axie": { const axieId = await (0, utils_1.getAxieId)(); if (!axieId) break; const address = await (0, prompts_1.input)({ message: "Enter delegatee address", validate: (value) => value.length > 0, }); const receipt = await (0, axie_1.delegateAxie)(wallet, axieId, address); if (receipt) { console.log("āœ… Axie delegated! Transaction hash:", receipt.hash); console.log(`šŸ”— View transaction: https://app.roninchain.com/tx/${receipt.hash}`); } break; } case "revoke-delegation-axie": { const axieId = await (0, utils_1.getAxieId)(); if (!axieId) break; console.log("šŸ”„ Starting delegation revocation process (this requires multiple transactions)..."); const receipt = await (0, axie_1.revokeDelegation)(wallet, axieId); if (receipt) { console.log("āœ… Axie delegation fully revoked! Final transaction hash:", receipt.hash); console.log(`šŸ”— View transaction: https://app.roninchain.com/tx/${receipt.hash}`); } break; } case "batch-delegate": { const axieIdsInput = await (0, prompts_1.input)({ message: "Enter comma-separated Axie IDs to delegate (e.g. 123, 456, 789)", validate: (value) => { const ids = value.split(",").map(id => id.trim()); return ids.length > 0 && ids.every(id => !Number.isNaN(Number(id))); }, }); let axieIds = axieIdsInput.split(",").map(id => id.trim()); if (axieIds.length === 0) { console.log("āŒ No Axie IDs provided"); break; } if (axieIds.length > 100) { console.log("āš ļø Warning: Can only delegate up to 100 Axies at once, only delegating the first 100"); axieIds = axieIds.slice(0, 100); } const address = await (0, prompts_1.input)({ message: "Enter delegatee address", validate: (value) => value.length > 0, }); console.log("\nšŸ”„ Starting batch delegation process..."); try { const receipt = await (0, axie_1.batchDelegateAxies)(wallet, axieIds, address); if (receipt) { console.log("\nāœ… Batch operation completed! Final transaction hash:", receipt.hash); console.log(`šŸ”— View transaction: https://app.roninchain.com/tx/${receipt.hash}`); } } catch (error) { console.log("\nāŒ Some operations failed. Check the logs above for details."); } break; } case "batch-revoke": { const axieIdsInput = await (0, prompts_1.input)({ message: "Enter comma-separated Axie IDs to revoke delegation (e.g. 123, 456, 789)", validate: (value) => { const ids = value.split(",").map(id => id.trim()); return ids.length > 0 && ids.every(id => !Number.isNaN(Number(id))); }, }); let axieIds = axieIdsInput.split(",").map(id => id.trim()); if (axieIds.length === 0) { console.log("āŒ No Axie IDs provided"); break; } if (axieIds.length > 100) { console.log("āš ļø Warning: Can only revoke up to 100 Axies at once, only revoking the first 100"); axieIds = axieIds.slice(0, 100); } console.log("\nšŸ”„ Starting batch revocation process..."); console.log("This will:"); console.log("1. Check and approve delegation contract if needed"); console.log("2. Request detachment for each Axie"); console.log("3. Perform the revocation\n"); try { const receipt = await (0, axie_1.batchRevokeDelegations)(wallet, axieIds); if (receipt) { console.log("\nāœ… Batch operation completed! Final transaction hash:", receipt.hash); console.log(`šŸ”— View transaction: https://app.roninchain.com/tx/${receipt.hash}`); } } catch (error) { console.log("\nāŒ Some operations failed. Check the logs above for details."); } break; } case "check-blessing": { const address = await (0, prompts_1.input)({ message: "Enter address to check blessing status (press Enter to use your address)", validate: () => true, }); const targetAddress = address || wallet.address; const { status, streak } = await (0, atia_1.isActivated)(targetAddress, provider); if (status) { console.log(`āœ… Address ${targetAddress.slice(-4)} has already prayed today (Current streak: ${streak})`); } else { console.log(`āŒ Address ${targetAddress.slice(-4)} has not prayed today (Current streak: ${streak})`); } break; } case "pray-blessing": { const token = await (0, utils_1.ensureMarketplaceToken)(); await (0, atia_1.checkBlessings)(wallet, token); break; } case "delegate": { const token = await (0, utils_1.ensureMarketplaceToken)(); if (!token) { console.log("āŒ No marketplace token available. Please refresh token first."); break; } const toAddress = await (0, prompts_1.input)({ message: "Enter delegatee address:", validate: (value) => (0, ethers_1.isAddress)(value), }); const percentage = await (0, prompts_1.input)({ message: "Enter delegator slips percentage (default: 100):", validate: (value) => { if (value === "") return true; const num = Number.parseInt(value); return !Number.isNaN(num) && num > 0 && num <= 100; }, default: "100" }); const delegatedAt = Math.floor(Date.now() / 1000); console.log("\nšŸ”„ Creating delegation signature..."); const { message, signature } = await (0, delegation_1.signDelegation)(wallet, toAddress, delegatedAt, Number.parseInt(percentage)); console.log("āœ… Signature created!"); console.log("\nšŸ“ Message:", message); console.log("āœļø Signature:", signature); console.log("\nšŸ”„ Submitting delegation..."); const success = await (0, graphql_1.delegateAtiaBlessing)(token, signature, wallet.address, toAddress, delegatedAt, Number.parseInt(percentage)); if (success) { console.log("āœ… Delegation submitted successfully!"); } else { console.log("āŒ Failed to submit delegation"); } break; } case "revoke-delegation": { const token = await (0, utils_1.ensureMarketplaceToken)(); if (!token) { console.log("āŒ No marketplace token available. Please refresh token first."); break; } const toAddress = await (0, prompts_1.input)({ message: "Enter delegatee address to revoke:", validate: (value) => (0, ethers_1.isAddress)(value), }); console.log("\nšŸ”„ Revoking delegation..."); const success = await (0, graphql_1.revokeAtiaBlessingDelegation)(token, wallet.address, // userAddress toAddress, wallet.address // fromAddress ); if (success) { console.log("āœ… Delegation revoked successfully!"); } else { console.log("āŒ Failed to revoke delegation"); } break; } case "list-delegations": { const token = await (0, utils_1.ensureMarketplaceToken)(); if (!token) { console.log("āŒ No marketplace token available. Please refresh token first."); break; } console.log("\nšŸ“‹ Checking delegations..."); const delegations = await (0, graphql_1.getAtiaBlessingDelegations)(token, wallet.address); if (delegations.length === 0) { console.log("ā„¹ļø No delegations found"); break; } console.log("\nšŸ“‹ Delegations:"); for (const delegation of delegations) { const fromName = delegation.fromProfile?.name || delegation.fromAddress.slice(-4); const toName = delegation.toProfile?.name || delegation.toAddress.slice(-4); console.log(`\nšŸ”„ From: ${fromName} (${delegation.fromAddress})`); console.log(` To: ${toName} (${delegation.toAddress})`); console.log(` Percentage: ${delegation.delegatorSlipsPercent}%`); console.log(` Last Prayed: ${delegation.lastPrayedAt ? new Date(delegation.lastPrayedAt).toLocaleString() : 'Never'}`); console.log(` Delegated At: ${new Date(delegation.delegatedAt * 1000).toLocaleString()}`); } break; } } } catch (error) { if (error instanceof Error) { console.error("āŒ Error:", error.message); } else { console.error("āŒ Error:", error); } } finally { await (0, utils_1.askToContinue)(); } } } main();