axie-ronin-ethers-js-tools
Version:
A set of functions that make it easier for developers to interact with their Axies on the Ronin network and the maketplace.
322 lines (321 loc) • 17.2 kB
JavaScript
#!/usr/bin/env node
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
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 dotenv = __importStar(require("dotenv"));
const ethers_1 = require("ethers");
const axie_1 = require("./lib/axie");
const access_token_1 = require("./lib/marketplace/access-token");
const buy_order_1 = __importDefault(require("./lib/marketplace/buy-order"));
const cancel_order_1 = __importDefault(require("./lib/marketplace/cancel-order"));
const create_order_1 = __importDefault(require("./lib/marketplace/create-order"));
const transfers_1 = require("./lib/transfers");
const contracts_1 = require("./lib/contracts");
const contracts_2 = require("@roninbuilders/contracts");
const utils_1 = require("./lib/utils");
dotenv.config();
async function ensureMarketplaceToken() {
if (!process.env.MARKETPLACE_ACCESS_TOKEN) {
const token = await (0, prompts_1.input)({
message: '🔑 Enter your Marketplace access token:',
validate: (value) => value !== undefined && value !== ''
});
process.env.MARKETPLACE_ACCESS_TOKEN = token;
}
return process.env.MARKETPLACE_ACCESS_TOKEN;
}
async function main() {
// Ask for Skymavis API key at startup if not in env (optional)
let skyMavisApiKey = process.env.SKYMAVIS_DAPP_KEY;
if (!skyMavisApiKey) {
const shouldProvideKey = await (0, prompts_1.confirm)({
message: '🔑 Would you like to provide a Skymavis DApp API key? (Recommended for better rate limits)',
default: false
});
if (shouldProvideKey) {
skyMavisApiKey = await (0, prompts_1.input)({
message: '🔑 Enter your Skymavis DApp API key:',
validate: (value) => value !== undefined && value !== ''
});
}
}
// 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 ethers_1.ethers.utils.isHexString(value, 32) || ethers_1.ethers.utils.isHexString(`0x${value}`, 32);
}
});
// Ensure "0x" prefix
privateKey = privateKey.startsWith('0x') ? privateKey : `0x${privateKey}`;
}
while (true) {
// Initialize provider with the API key from above
const provider = new ethers_1.ethers.providers.JsonRpcProvider(skyMavisApiKey
? `https://api-gateway.skymavis.com/rpc?apikey=${skyMavisApiKey}`
: "https://api.roninchain.com/rpc");
// Initialize wallet with the previously obtained private key
const wallet = new ethers_1.ethers.Wallet(privateKey, provider);
const address = await wallet.getAddress();
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 all axies', value: 'delist-all' },
{ name: 'List axie', value: 'list' },
{ name: 'List all axies', value: 'list-all' },
{ name: 'Transfer axie', value: 'transfer' },
{ name: 'Transfer all axies', value: 'transfer-all' },
]
});
switch (action) {
case 'account': {
const axieIds = await (0, axie_1.getAxieIdsFromAccount)(address, provider);
console.log(`📬 Address: ${address}`);
const wethContract = (0, contracts_1.getWETHContract)(wallet);
// Get RON balance
const balance = await provider.getBalance(address);
const balanceInEther = ethers_1.utils.formatEther(balance);
console.log('💰 RON Balance:', balanceInEther);
// Get WETH balance
const wethBalance = await wethContract.balanceOf(address);
const wethBalanceInEther = ethers_1.utils.formatEther(wethBalance);
console.log('💰 WETH Balance:', wethBalanceInEther);
// WETH allowance
const allowance = await wethContract.allowance(address, contracts_2.MARKETPLACE_GATEWAY_V2.address);
console.log('🛒 Marketplace WETH allowance:', !allowance.eq(0) ? '✅ Granted' : '❌ Not granted');
// get axie contract
const axieContract = (0, contracts_1.getAxieContract)(provider);
// check if marketplace is approved for axies
const isApprovedForAll = await axieContract.isApprovedForAll(address, contracts_2.MARKETPLACE_GATEWAY_V2.address);
console.log('🔐 Marketplace approval for Axies:', isApprovedForAll ? '✅ Approved' : '❌ Not approved');
console.log(`🐾 Number of Axies: ${axieIds.length}`);
if (axieIds.length > 0) {
console.log(`🆔 Axie IDs: ${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': {
const wethContract = (0, contracts_1.getWETHContract)(wallet);
const amountToApprove = '115792089237316195423570985008687907853269984665640564039457584007913129639935';
const address = await wallet.getAddress();
console.log(`Approving Marketplace (${contracts_2.MARKETPLACE_GATEWAY_V2.address}) to spend ${amountToApprove} WETH for the address ${address}`);
const txApproveWETH = await wethContract.approve(contracts_2.MARKETPLACE_GATEWAY_V2.address, amountToApprove, {
gasPrice: ethers_1.utils.parseUnits('20', 'gwei')
});
const txApproveReceipt = await txApproveWETH.wait();
console.log('✅ WETH approved! Transaction hash:', txApproveReceipt.transactionHash);
break;
}
case 'approve-marketplace': {
const axieContract = (0, contracts_1.getAxieContract)(wallet);
const address = await wallet.getAddress();
console.log(`Approving Marketplace (${contracts_2.MARKETPLACE_GATEWAY_V2.address}) to handle Axies for ${address}`);
const tx = await axieContract.setApprovalForAll(contracts_2.MARKETPLACE_GATEWAY_V2.address, true, {
gasPrice: ethers_1.utils.parseUnits('20', 'gwei')
});
const receipt = await tx.wait();
console.log('✅ Marketplace approved! Transaction hash:', receipt.transactionHash);
break;
}
case 'buy': {
const token = await ensureMarketplaceToken();
const axieId = await (0, utils_1.getAxieId)();
if (!axieId)
break;
const receipt = await (0, buy_order_1.default)(axieId, wallet, token, process.env.SKYMAVIS_DAPP_KEY // This can be undefined
);
if (receipt) {
console.log('🚀 Transaction successful! Hash:', receipt.transactionHash);
console.log('🔗 View transaction: https://app.roninchain.com/tx/' + receipt.transactionHash);
}
break;
}
case 'delist': {
const axieId = await (0, utils_1.getAxieId)();
if (!axieId)
break;
const receipt = await (0, cancel_order_1.default)(axieId, wallet, process.env.SKYMAVIS_DAPP_KEY // This can be undefined
);
if (receipt) {
console.log('Transaction hash:', receipt.transactionHash);
}
break;
}
case 'delist-all': {
const fromAddress = await wallet.getAddress();
let axieIds = await (0, axie_1.getAxieIdsFromAccount)(fromAddress, provider);
if (axieIds.length > 100) {
console.log('⚠️ Warning: Can only transfer up to 100 Axies at once, only delisting the first 100');
axieIds = axieIds.slice(0, 100);
}
const receipt = await (0, transfers_1.batchTransferAxies)(wallet, fromAddress, axieIds);
if (receipt) {
console.log('✅ Axies delisted! Transaction hash:', receipt.transactionHash);
}
break;
}
case 'list': {
const axieId = await (0, utils_1.getAxieId)();
if (!axieId)
break;
const token = await ensureMarketplaceToken();
const basePrice = await (0, prompts_1.input)({
message: 'Enter base price in ETH',
validate: (value) => ethers_1.utils.parseEther(value).gt(0)
});
const address = await wallet.getAddress();
const currentBlock = await provider.getBlock('latest');
const startedAt = currentBlock.timestamp;
const expiredAt = startedAt + 15634800; // ~6 months
const orderData = {
address,
axieId: axieId.toString(),
basePrice: ethers_1.ethers.utils.parseEther(basePrice).toString(),
endedPrice: '0',
startedAt,
endedAt: 0,
expiredAt,
};
const result = await (0, create_order_1.default)(orderData, token, wallet, process.env.SKYMAVIS_DAPP_KEY // This can be undefined
);
if (result === null || result.errors || !result.data) {
console.error('❌ Error:', result?.errors?.[0]?.message || 'Unknown error');
break;
}
console.log('✅ Order created! Order hash:', result.data.createOrder);
break;
}
case 'list-all': {
const token = await ensureMarketplaceToken();
const basePrice = await (0, prompts_1.input)({
message: 'Enter base price in ETH (for all Axies)',
validate: (value) => ethers_1.utils.parseEther(value).gt(0)
});
const address = await wallet.getAddress();
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;
const expiredAt = startedAt + 15634800; // ~6 months
for (const axieId of axieIds) {
const orderData = {
address,
axieId: axieId.toString(),
basePrice: ethers_1.ethers.utils.parseEther(basePrice).toString(),
endedPrice: '0',
startedAt,
endedAt: 0,
expiredAt,
};
const result = await (0, create_order_1.default)(orderData, token, wallet, process.env.SKYMAVIS_DAPP_KEY);
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}! Order hash:`, result.data.createOrder);
}
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.transactionHash);
}
break;
}
case 'transfer-all': {
const address = await (0, prompts_1.input)({
message: 'Enter recipient address',
validate: (value) => value.length > 0
});
const fromAddress = await wallet.getAddress();
let axieIds = await (0, axie_1.getAxieIdsFromAccount)(fromAddress, provider);
if (axieIds.length > 100) {
console.log('⚠️ Warning: Can only transfer up to 100 Axies at once, only transfering the first 100');
axieIds = axieIds.slice(0, 100);
}
const receipt = await (0, transfers_1.batchTransferAxies)(wallet, address, axieIds);
if (receipt) {
console.log('✅ Axies transferred! Transaction hash:', receipt.transactionHash);
}
break;
}
}
}
catch (error) {
if (error instanceof Error) {
console.error('❌ Error:', error.message);
}
else {
console.error('❌ Error:', error);
}
}
finally {
await (0, utils_1.askToContinue)();
}
}
}
main();