# Axie tools

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

You only need Node.js. Install it from [here](https://nodejs.org/en/download/prebuilt-binaries/)

> [!TIP]
> Use the npx command to test this tool with an interactive CLI.

```shell
npx axie-tools
```

This will present an interactive menu with the following options:

- Get account info
- Refresh access token
- Approve WETH
- Approve marketplace
- Buy axie
- List axie for sale
- List all axies for sale
- Delist axie from sale
- Delist all axies from sale
- Transfer axie
- Transfer all axies
- Check Atia blessing status
- Pray for Atia blessing
- Create Atia Blessing delegation
- List Atia Blessing delegations
- Revoke Atia Blessing delegation

The CLI will guide you through the inputs for each action.

> [!TIP]
> You can create an .env (see .env.example) file to avoid entering values every time you use the CLI.

![CLIScreenshot](./examples/CLIScreenshot.png)

## Using axie tools library in your nodejs projects

```shell
npm install axie-tools ethers@6.13.4 dotenv
```

Create a .env file with the following values:

```shell
# Get from Ronin wallet: Manage wallet > Show private key
PRIVATE_KEY="<your private key, copy from ronin wallet: manage wallet > show private key>"
# Get from app.axie: Browser > Developer Tools > Application > Local storage > https://app.axieinfinity.com > accessToken
MARKETPLACE_ACCESS_TOKEN="<your marketplace access token, log in to the marketplace and copy from the developer console>"
```

### Examples

- Buy axie: [complete example code](https://github.com/alexx855/axie-tools/tree/main/examples/buy.js)
- List axie for sale on the marketplace: [complete example code](https://github.com/alexx855/axie-tools/tree/main/examples/list-for-sale.js)
- Delist axie from the marketplace: [complete example code](https://github.com/alexx855/axie-tools/tree/main/examples/delist-from-sale.js)
- Delegate an Axie:
```javascript
import { Wallet, JsonRpcProvider } from "ethers";
import { delegateAxie } from "axie-tools";

async function delegateMyAxie() {
  const provider = new JsonRpcProvider("https://api.roninchain.com/rpc");
  const wallet = new Wallet("YOUR_PRIVATE_KEY", provider);
  
  const axieId = "11964920"; // The Axie ID to delegate
  const delegatee = "0x4C16558656f85d73394864aB4F333600197fBcD9"; // Address to delegate to (can be ronin: format)
  
  const receipt = await delegateAxie(wallet, axieId, delegatee);
  console.log(`✅ Axie delegated! Transaction: https://app.roninchain.com/tx/${receipt.hash}`);
}
```

- Batch delegate multiple Axies:
```javascript
import { Wallet, JsonRpcProvider } from "ethers";
import { batchDelegateAxies } from "axie-tools";

async function batchDelegateMyAxies() {
  const provider = new JsonRpcProvider("https://api.roninchain.com/rpc");
  const wallet = new Wallet("YOUR_PRIVATE_KEY", provider);
  
  const axieIds = ["11964920", "11964921", "11964922"]; // Up to 100 Axie IDs
  const delegatee = "0x4C16558656f85d73394864aB4F333600197fBcD9"; 
  
  const receipt = await batchDelegateAxies(wallet, axieIds, delegatee);
  console.log(`✅ Axies delegated! Transaction: https://app.roninchain.com/tx/${receipt.hash}`);
}
```

- Revoke an Axie delegation (multi-step process):
```javascript
import { Wallet, JsonRpcProvider } from "ethers";
import { revokeDelegation } from "axie-tools";

async function revokeDelegationForAxie() {
  const provider = new JsonRpcProvider("https://api.roninchain.com/rpc");
  const wallet = new Wallet("YOUR_PRIVATE_KEY", provider);
  
  const axieId = "11964920"; // The Axie ID to revoke delegation for
  
  console.log("Starting delegation revocation process...");
  // This will handle all required steps: request detachment, execute detachment, and revoke
  const receipt = await revokeDelegation(wallet, axieId);
  console.log(`✅ Delegation fully revoked! Transaction: https://app.roninchain.com/tx/${receipt.hash}`);
}
```

- Batch revoke multiple Axie delegations (multi-step process):
```javascript
import { Wallet, JsonRpcProvider } from "ethers";
import { batchRevokeDelegations } from "axie-tools";

async function batchRevokeMyDelegations() {
  const provider = new JsonRpcProvider("https://api.roninchain.com/rpc");
  const wallet = new Wallet("YOUR_PRIVATE_KEY", provider);
  
  const axieIds = ["11964920", "11964921", "11964922"]; // Up to 100 Axie IDs
  
  console.log("Starting batch delegation revocation process...");
  // This will handle all required steps for each Axie
  const receipt = await batchRevokeDelegations(wallet, axieIds);
  console.log(`✅ All delegations fully revoked! Transaction: https://app.roninchain.com/tx/${receipt.hash}`);
}
```

- Batch transfer multiple Axies:
```javascript
import { Wallet, JsonRpcProvider } from "ethers";
import { batchTransferAxies } from "axie-tools";

async function transferMultipleAxies() {
  const provider = new JsonRpcProvider("https://api.roninchain.com/rpc");
  const wallet = new Wallet("YOUR_PRIVATE_KEY", provider);
  
  const axieIds = ["123456", "123457", "123458"]; // List of Axie IDs to transfer
  const recipientAddress = "ronin:123..."; // Can use ronin: format
  
  const receipt = await batchTransferAxies(wallet, recipientAddress, axieIds);
  console.log(`✅ All Axies transferred! Transaction: https://app.roninchain.com/tx/${receipt.hash}`);
}
```

- Batch delist multiple Axies:
```javascript
import { Wallet, JsonRpcProvider } from "ethers";
import { batchTransferAxies } from "axie-tools";

async function batchDelistAxies() {
  const provider = new JsonRpcProvider("https://api.roninchain.com/rpc");
  const wallet = new Wallet("YOUR_PRIVATE_KEY", provider);
  
  const axieIds = ["123456", "123457", "123458"]; // List of Axie IDs to delist
  const receipt = await batchTransferAxies(wallet, wallet.address, axieIds);
  console.log(`✅ All Axies delisted! Transaction: https://app.roninchain.com/tx/${receipt.hash}`);
}
```

- Refresh your marketplace access token:
```javascript
import { refreshToken } from "axie-tools";

async function refreshMyToken() {
  // You need a valid refresh token to get a new access token
  const refreshTokenValue = "your-refresh-token-here";
  
  try {
    const result = await refreshToken(refreshTokenValue);
    console.log("New access token:", resuleshTokenValue);
    console.log("New access token:", result.newAccessToken);
    console.log("New refresh token:", result.newRefreshToken);
    
    // Save these tokens for future use
    // The refresh token also changes, so make sure to save both!
    return result;
  } catch (error) {
    console.error("Failed to refresh token:", error);
  }
}
```

- Pray for Atia's Blessing using marketplace delegations: Use `checkBlessings()` from `lib/atia.ts`
- Pray for Atia's Blessing without access token:
```javascript
import { Wallet, JsonRpcProvider } from "ethers";
import { activateStreak, isActivated } from "axie-tools";

async function prayForAddresses() {
  const provider = new JsonRpcProvider("https://api.roninchain.com/rpc");
  const wallet = new Wallet("YOUR_PRIVATE_KEY", provider);
  
  // List of addresses to pray for (max 5)
  const addresses = [
    "0x...", // Address 1
    "0x...", // Address 2
    wallet.address // Include self
  ];

  for (const address of addresses) {
    // Check if already prayed
    const { status, streak } = await isActivated(address, provider);
    if (status) {
      console.log(`Already prayed for ${address} (streak: ${streak})`);
      continue;
    }

    // Pray for address
    const result = await activateStreak(wallet, address);
    if (result.status) {
      console.log(`Successfully prayed for ${address} (new streak: ${result.streak})`);
    }
  }
}
```

### How to get marketplace access token

> [!NOTE]
> Get your access token by logging into <https://app.axieinfinity.com/> and accessing Developer Tools > Application > Local storage > https://app.axieinfinity.com > accessToken

![ConsoleScreenshot](./examples/accessTokenConsoleScreenshot.png)

### Considerations

- You need RON tokens to pay for the gas fees of the onchain transactions.
- All scripts use WETH for the marketplace transactions, you need to have WETH in your wallet to buy axies.
- Listing is offchain, you will need to approve the marketplace contract to use your axies first, you can do this with the `approveMarketplaceContract` function or manually in the marketplace website the first time you list an axie.
- Buying is onchain, you need to have approve WETH allowance, you can do this with the `approveWETH` function or manually in the marketplace website the first time you buy and axie.
- Cancel listing is onchain.
- Atia's Blessing delegations require a valid marketplace access token.
- If you get a "Signer is not maker" error, make sure the access token is correct.

### Contributing

Feel free to open an issue or a pull request if you have any error, questions or suggestions.
