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.

239 lines (238 loc) 10.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getAxieIdsFromAccount = getAxieIdsFromAccount; exports.delegateAxie = delegateAxie; exports.batchDelegateAxies = batchDelegateAxies; exports.batchRevokeDelegations = batchRevokeDelegations; exports.revokeDelegation = revokeDelegation; const ethers_1 = require("ethers"); const contracts_1 = require("./contracts"); // Delegation context hash const ctxHash = "0xfa4914198408a3840a0a751c221614143f885428607953c71fa37ad0dd52f940"; async function approveAxieDelegation(signer) { const axieContract = (0, contracts_1.getAxieContract)(signer); const delegationContract = (0, contracts_1.getAxieDelegationContract)(signer); const delegationAddress = await delegationContract.getAddress(); // Check if already approved const isApproved = await axieContract.isApprovedForAll(await signer.getAddress(), delegationAddress); if (!isApproved) { console.log("Approving Axie delegation contract..."); const tx = await axieContract.setApprovalForAll(delegationAddress, true); await tx.wait(); console.log("✅ Delegation contract approved"); } } async function getAxieIdsFromAccount(address, provider) { // get axie contract const axieContract = (0, contracts_1.getAxieContract)(provider); // get axies balance for the address const axiesBalance = await axieContract.balanceOf(address); // get axie ids const axieIds = []; for (let i = 0; i < axiesBalance; i++) { try { const axieId = await axieContract.tokenOfOwnerByIndex(address, i); axieIds.push(Number(axieId)); } catch (error) { const errorMessage = error instanceof Error ? error.message : "Unknown error"; console.error(`Error fetching axie id at index ${i}: ${errorMessage}`); } } return axieIds; } async function delegateAxie(signer, tokenId, delegatee) { const axieContract = (0, contracts_1.getAxieContract)(signer); const delegationContract = (0, contracts_1.getAxieDelegationContract)(signer); // Format token ID const formattedTokenId = typeof tokenId === "string" ? tokenId : tokenId.toString(); try { // Check if context is already attached const context = await axieContract.contextOf(formattedTokenId); if (context === ctxHash) { console.log(`ℹ️ Context already attached for Axie ${formattedTokenId}`); } else { // If context exists but is different, we need to attach the correct one console.log(`Attaching context for Axie ${formattedTokenId}`); const tx1 = await axieContract.attachContext(ctxHash, formattedTokenId, "0x", { gasPrice: (0, ethers_1.parseUnits)("20", "gwei"), }); await tx1.wait(); console.log(`✅ Context attached for Axie ${formattedTokenId}`); } } catch (error) { // If error contains "execution reverted", context is already attached if (error instanceof Error && error.message.includes('execution reverted')) { console.log(`ℹ️ Context already attached for Axie ${formattedTokenId}`); } else { // If any other error, try to attach context try { console.log(`Attaching context for Axie ${formattedTokenId}`); const tx1 = await axieContract.attachContext(ctxHash, formattedTokenId, "0x", { gasPrice: (0, ethers_1.parseUnits)("20", "gwei"), }); await tx1.wait(); console.log(`✅ Context attached for Axie ${formattedTokenId}`); } catch (attachError) { if (attachError instanceof Error && attachError.message.includes('execution reverted')) { console.log(`ℹ️ Context already attached for Axie ${formattedTokenId}`); } else { throw attachError; } } } } // Calculate expiry timestamp (1 year from now) const oneYearFromNow = Math.floor(Date.now() / 1000) + (365 * 24 * 60 * 60); // Format the delegatee address const cleanDelegatee = delegatee.replace("ronin:", "0x").toLowerCase(); console.log(`Delegating Axie ${formattedTokenId} to ${cleanDelegatee}`); try { // Call delegate function with standard method call const tx2 = await delegationContract.delegate(formattedTokenId, cleanDelegatee, oneYearFromNow, 1, // permissionBitMap as uint64 { gasPrice: (0, ethers_1.parseUnits)("20", "gwei"), }); const receipt = await tx2.wait(); return receipt; } catch (error) { console.error("Delegation error:", error); throw error; } } async function batchDelegateAxies(signer, axieIds, delegatee) { const axieContract = (0, contracts_1.getAxieContract)(signer); const delegationContract = (0, contracts_1.getAxieDelegationContract)(signer); // Format token IDs and delegatee address const tokenIds = axieIds.map(id => { try { return BigInt(id.toString().replace(/[^0-9]/g, '')); } catch (e) { throw new Error(`Invalid Axie ID format: ${id}`); } }); // Format the delegatee address const formattedDelegatee = delegatee.replace("ronin:", "0x").toLowerCase(); // Check and attach contexts individually console.log(`Checking/attaching context for ${tokenIds.length} Axies`); for (const tokenId of tokenIds) { try { // Check if context is already attached const context = await axieContract.contextOf(tokenId.toString()); if (context === ctxHash) { console.log(`ℹ️ Context already attached for Axie ${tokenId}`); } else { console.log(`- Attaching context for Axie ${tokenId}`); const tx1 = await axieContract.attachContext(ctxHash, tokenId.toString(), "0x"); await tx1.wait(); console.log(`✅ Context attached for Axie ${tokenId}`); } } catch (error) { // If error contains "execution reverted", context is already attached if (error instanceof Error && error.message.includes('execution reverted')) { console.log(`ℹ️ Context already attached for Axie ${tokenId}`); } else { try { console.log(`- Attaching context for Axie ${tokenId}`); const tx1 = await axieContract.attachContext(ctxHash, tokenId.toString(), "0x"); await tx1.wait(); console.log(`✅ Context attached for Axie ${tokenId}`); } catch (attachError) { if (attachError instanceof Error && attachError.message.includes('execution reverted')) { console.log(`ℹ️ Context already attached for Axie ${tokenId}`); } else { console.log(`❌ Failed to attach context for Axie ${tokenId}`, attachError); throw attachError; } } } } } // Calculate expiry timestamp (1 year from now) const oneYearFromNow = BigInt(Math.floor(Date.now() / 1000) + (365 * 24 * 60 * 60)); const permissionBitMap = 1n; // Now do the bulk delegation console.log(`\nDelegating ${tokenIds.length} Axies to ${delegatee}`); try { const tx2 = await delegationContract.bulkDelegate(tokenIds, Array(tokenIds.length).fill(formattedDelegatee), Array(tokenIds.length).fill(oneYearFromNow), Array(tokenIds.length).fill(permissionBitMap)); const receipt = await tx2.wait(); return receipt; } catch (error) { // If bulk delegation fails, try individual delegations console.log("\n⚠️ Bulk delegation failed:", error); console.log("Falling back to individual delegations...\n"); for (const tokenId of tokenIds) { try { const tx = await delegationContract.delegate(tokenId, formattedDelegatee, oneYearFromNow, permissionBitMap); await tx.wait(); console.log(`✅ Successfully delegated Axie ${tokenId}`); } catch (err) { console.log(`❌ Failed to delegate Axie ${tokenId}`, err); } } } } async function batchRevokeDelegations(signer, axieIds) { const delegationContract = (0, contracts_1.getAxieDelegationContract)(signer); // Format token IDs - ensure they are clean numeric strings const tokenIds = axieIds.map(id => id.toString().replace(/[^0-9]/g, '')); // Then do the bulk revocation console.log(`\nRevoking delegations for ${tokenIds.length} Axies`); try { const tx2 = await delegationContract.bulkRevokeDelegations(tokenIds); const receipt = await tx2.wait(); return receipt; } catch (error) { console.log("\n⚠️ Bulk revocation failed:", error); console.log("Falling back to individual revocations...\n"); for (const tokenId of tokenIds) { try { const tx = await delegationContract.revokeDelegation(tokenId); await tx.wait(); console.log(`✅ Successfully revoked delegation for Axie ${tokenId}`); } catch (err) { console.log(`❌ Failed to revoke delegation for Axie ${tokenId}`, err); } } } } async function revokeDelegation(signer, tokenId) { // // First approve the delegation contract if needed // await approveAxieDelegation(signer); // const axieContract = getAxieContract(signer); const delegationContract = (0, contracts_1.getAxieDelegationContract)(signer); // // First request detachment // console.log(`Requesting detachment for Axie ${Number(tokenId)}...`); // const tx1 = await axieContract.requestDetachContext( // ctxHash, // Number(tokenId), // "0x", // { // gasPrice: parseUnits("20", "gwei"), // } // ); // await tx1.wait(); // Then revoke the delegation console.log(`Revoking delegation for Axie ${Number(tokenId)}`); const tx2 = await delegationContract.revokeDelegation(Number(tokenId), { gasPrice: (0, ethers_1.parseUnits)("20", "gwei"), }); const receipt = await tx2.wait(); return receipt; }