1.3.33 • Published 1 month ago

@shogun-sdk/money-legos v1.3.33

Weekly downloads
-
License
ISC
Repository
github
Last release
1 month ago

@shogun-sdk/money-legos

Legos SDK for building with Shogun's money legos. This package allows you to purchase NFTs on Bera Chain using any token from any blockchain.

Overview

The Shogun Money Legos SDK provides a comprehensive set of tools for interacting with Shogun's cross-chain infrastructure. It enables:

  1. Cross-chain NFT Purchases: Buy NFTs on Bera Chain using tokens from any supported blockchain
  2. Cross-chain Token Swaps: Swap tokens between different EVM chains and Solana
  3. Balance Checking: Check token balances across multiple chains
  4. Transaction Signing: Sign and execute transactions on various blockchains

The SDK is built with TypeScript and provides a type-safe API for interacting with Shogun's services.

Installation

npm install @shogun-sdk/money-legos
# or
yarn add @shogun-sdk/money-legos
# or
pnpm add @shogun-sdk/money-legos

Configuration

The SDK requires an API key for authentication. You can obtain this from the Shogun dashboard.

RPC URLs

The SDK provides multiple ways to configure RPC URLs:

1. Using the Initialization Function (Recommended)

You can explicitly set RPC URLs using the initialization function:

import { init } from '@shogun-sdk/money-legos';

// Initialize the SDK with custom RPC URLs
init({
  rpcUrls: {
    1: ['https://your-ethereum-rpc-url'],
    8453: ['https://your-base-rpc-url'],
    42161: ['https://your-arbitrum-rpc-url'],
    56: ['https://your-bsc-rpc-url'],
    80094: ['https://your-berachain-rpc-url'],
    7565164: ['https://your-solana-rpc-url'],
    146: ['https://your-sonic-rpc-url'],
  }
});

// Now use the SDK as usual
import { LegoClient } from '@shogun-sdk/money-legos';
const legoClient = new LegoClient({ apiKey: 'YOUR_API_KEY' });

This approach is recommended for Next.js applications and gives you the most control over RPC URLs.

2. Using Environment Variables

The SDK can also use environment variables for RPC URLs. You can configure them as follows:

For Node.js applications:

Create a .env file in your project root:

RPC_URL_1=https://your-ethereum-rpc-url
RPC_URL_8453=https://your-base-rpc-url
RPC_URL_42161=https://your-arbitrum-rpc-url
RPC_URL_56=https://your-bsc-rpc-url
RPC_URL_80094=https://your-berachain-rpc-url
RPC_URL_7565164=https://your-solana-rpc-url
RPC_URL_146=https://your-sonic-rpc-url

Then load the environment variables using dotenv:

import 'dotenv/config';
// Your application code
For React/Vite applications:

For Vite applications, you'll need to use a plugin like vite-plugin-env-compatible to expose environment variables to the client. Create a .env file in your project root:

RPC_URL_1=https://your-ethereum-rpc-url
RPC_URL_8453=https://your-base-rpc-url
RPC_URL_42161=https://your-arbitrum-rpc-url
RPC_URL_56=https://your-bsc-rpc-url
RPC_URL_80094=https://your-berachain-rpc-url
RPC_URL_7565164=https://your-solana-rpc-url
RPC_URL_146=https://your-sonic-rpc-url

Then configure your Vite application to expose these variables:

// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import envCompatible from 'vite-plugin-env-compatible';

export default defineConfig({
  plugins: [
    react(),
    envCompatible({
      prefix: 'RPC_URL_',
    }),
  ],
});
For Next.js applications:

Next.js has a specific way of handling environment variables. Variables prefixed with NEXT_PUBLIC_ are exposed to the browser. Create a .env.local file in your project root:

NEXT_PUBLIC_RPC_URL_1=https://your-ethereum-rpc-url
NEXT_PUBLIC_RPC_URL_8453=https://your-base-rpc-url
NEXT_PUBLIC_RPC_URL_42161=https://your-arbitrum-rpc-url
NEXT_PUBLIC_RPC_URL_56=https://your-bsc-rpc-url
NEXT_PUBLIC_RPC_URL_80094=https://your-berachain-rpc-url
NEXT_PUBLIC_RPC_URL_7565164=https://your-solana-rpc-url
NEXT_PUBLIC_RPC_URL_146=https://your-sonic-rpc-url

For server-side code, you can use regular environment variables without the NEXT_PUBLIC_ prefix:

RPC_URL_1=https://your-server-side-ethereum-rpc-url
RPC_URL_8453=https://your-server-side-base-rpc-url
# ... and so on

Fallback RPCs

If no environment variables or custom RPC URLs are provided, the SDK will use public RPC endpoints as fallbacks. However, for production applications, it's recommended to use your own RPC endpoints for better reliability and performance.

Configuration

import { LegoClient, OneShotClient, ShogunBalancesApiClient } from '@shogun-sdk/money-legos';

// Initialize the Lego client for NFT purchases
const legoClient = new LegoClient({ 
  apiKey: 'YOUR_API_KEY', // Get this from Shogun dashboard
});

// Initialize the OneShot client for cross-chain swaps
const oneShotClient = new OneShotClient(
  'YOUR_API_KEY', // Get this from Shogun dashboard
  'SHOGUN_API_URL' // API endpoint
);

// Initialize the Balances client for checking token balances
const balancesClient = new ShogunBalancesApiClient('YOUR_API_KEY');

Supported Chains

The SDK supports multiple blockchain networks:

import { 
  ETHEREUM_CHAIN_ID, 
  BASE_CHAIN_ID, 
  ARBITRUM_CHAIN_ID, 
  BSC_CHAIN_ID, 
  BERA_CHAIN_ID, 
  SOLANA_CHAIN_ID, 
  SONIC_CHAIN_ID 
} from '@shogun-sdk/money-legos';

// Chain IDs
console.log(ETHEREUM_CHAIN_ID); // 1
console.log(BASE_CHAIN_ID); // 8453
console.log(ARBITRUM_CHAIN_ID); // 42161
console.log(BSC_CHAIN_ID); // 56
console.log(BERA_CHAIN_ID); // 80094
console.log(SOLANA_CHAIN_ID); // 7565164
console.log(SONIC_CHAIN_ID); // 146


// List of all supported chains
import { getSupportedChains , CHAIN_MAP } from '@shogun-sdk/money-legos';

Quick Start

1. Install the package

npm install @shogun-sdk/money-legos
# or
yarn add @shogun-sdk/money-legos

2. Initialize the SDK with RPC URLs (Recommended)

import { init } from '@shogun-sdk/money-legos';

// Initialize with your RPC URLs
init({
  rpcUrls: {
    1: ['https://your-ethereum-rpc-url'],
    8453: ['https://your-base-rpc-url'],
    // Add other chains as needed
  }
});

3. Initialize the Lego Client

import { LegoClient } from '@shogun-sdk/money-legos';

// Create a new client instance
const legoClient = new LegoClient({ 
  apiKey: 'YOUR_API_KEY', // Get this from Shogun dashboard
});

4. Basic Usage Example

// Example: Purchase an NFT using ETH
async function purchaseNFT() {
  try {
    const result = await legoClient.MagicEden.SwapForNFT({
      items: [{ 
        address: '0x7E0b0363804C6C79AAb9aB51850bF8F3D561f868', // NFT contract address
        tokenId: '42' // The NFT token ID you want to purchase
      }],
      token: { 
        address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // WETH address
        decimals: 18, 
        chainId: 1  // Ethereum mainnet
      },
      userAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e' // Your wallet address
    });

    if (result.status) {
      console.log('Success! Transaction steps:', result.data.steps);
      // Execute the transaction steps...
    } else {
      console.error('Failed to fetch data:', result.error);
    }
  } catch (error) {
    console.error('Error:', error);
  }
}

Using with Viem Client

Here's a complete example of how to execute transactions using Viem:

import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { base } from "viem/chains";
import { LegoClient } from '@shogun-sdk/money-legos';

async function setupBuyNftWithViem() {
  // 1. Initialize the Lego client
  const legoClient = new LegoClient({
    apiKey: "your api key here",
  });

  // 2. Set up your wallet
  const account = privateKeyToAccount("0x..."); // Your private key
  const client = createWalletClient({
    chain: base,
    transport: http(),
    account,
  });

  try {
    // 3. Fetch the purchase data
    const { data } = await legoClient.MagicEden.SwapForNFT({
      token: {
        address: "0x0000000000000000000000000000000000000000", // ETH
        decimals: 18,
        chainId: 8453, // Base chain
      },
      items: [
        {
          address: "0x72d876d9cdf4001b836f8e47254d0551eda2eebb", // NFT contract
          tokenId: "32", // NFT ID
        },
      ],
      userAddress: account.address,
    });
    
    if (!data) {
      console.error("No data returned from MagicEden.SwapForNFT");
      return;
    }
    
    // 4. Execute each transaction step
    const { steps } = data;
    for (const step of steps) {
      console.log(`Executing step: ${step.description || 'Unknown step'}`);
      
      const txHash = await client.sendTransaction({
        to: step.to as `0x${string}`,
        data: step.data as `0x${string}`,
        value: BigInt(step.value),
        chainId: step.chainId,
        gas: BigInt(step.gas),
        maxFeePerGas: BigInt(step.maxFeePerGas),
        maxPriorityFeePerGas: BigInt(step.maxPriorityFeePerGas),
      });
      
      console.log(`Transaction successful! Hash: ${txHash}`);
    }
  } catch (error) {
    console.error("Error during NFT purchase:", error);
  }
}

Transaction Signing Examples

EVM Transaction Signing

Here's how to sign and execute EVM transactions using the OneShot client:

import { OneShotClient, QuoteTypes } from '@shogun-sdk/money-legos';
import { createWalletClient, http, getPublicClient } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { mainnet } from 'viem/chains';

// Initialize the OneShot client
const oneShotClient = new OneShotClient(
  'YOUR_API_KEY',
  'SHOGUN_API_URL'
);

// Set up your wallet
const account = privateKeyToAccount('0x...'); // Your private key
const walletClient = createWalletClient({
  account,
  chain: mainnet,
  transport: http()
});

// Function to handle EVM transactions
const handleEVMTransaction = async (quote: QuoteTypes, signer: any, chain: any): Promise<{ hash: string; swapPlacementTimestamp: number; swapExecutionTimestamp: number } | null> => {
  try {
    if (Array.isArray(quote.calldatas) || !signer) return null;
    
    const provider = getPublicClient({ chain });
    const estimatedGas = await provider.estimateGas({
      to: quote.calldatas.to as `0x${string}`,
      data: quote.calldatas.data as `0x${string}`,
      value: BigInt(quote.calldatas?.value ?? 0),
      account: signer.account,
    });

    // Increase estimated gas by 20%
    const gas = BigInt(Math.ceil(Number(estimatedGas) * 1.2));

    const hash = await signer.sendTransaction({
      to: quote.calldatas.to as `0x${string}`,
      data: quote.calldatas.data as `0x${string}`,
      value: BigInt(quote.calldatas?.value ?? 0),
      account: signer.account,
      gas,
      chain,
    });
    
    const swapPlacementTimestamp = Date.now();

    const tx = await provider.waitForTransactionReceipt({
      hash,
      retryCount: 5,
      confirmations: 1,
    });
    
    const swapExecutionTimestamp = Date.now();

    if (tx.status !== 'success') {
      throw new Error(`EVM transaction failed: ${tx.status}`);
    }

    return { hash, swapPlacementTimestamp, swapExecutionTimestamp };
  } catch (error) {
    throw error;
  }
};

// Example usage
async function performEVMTransaction() {
  try {
    // Get a quote for a cross-chain swap
    const quote = await oneShotClient.fetchQuote({
      srcChain: 1, // Ethereum mainnet
      destChain: 8453, // Base chain
      srcToken: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // WETH
      destToken: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', // WBTC
      amount: '1000000000000000000', // 1 ETH (in wei)
      senderAddress: account.address,
      slippage: 0.5, // 0.5% slippage tolerance
    });

    if (!quote.status) {
      console.error('Failed to get quote:', quote.error);
      return;
    }

    // Execute the transaction
    const result = await handleEVMTransaction(quote.data, walletClient, mainnet);
    console.log('Transaction result:', result);
  } catch (error) {
    console.error('Error performing transaction:', error);
  }
}

Solana Transaction Signing

Here's how to sign and execute Solana transactions:

import { OneShotClient, QuoteTypes } from '@shogun-sdk/money-legos';
import { VersionedTransaction } from '@solana/web3.js';
import bs58 from 'bs58';
import {
  sendTransactionUsingJito,
  sendBundleUsingJito,
  isValidSolanaSignature,
  checkTransactionConfirmation,
  confirmTransaction,
} from '@shogun-sdk/money-legos';

// Initialize the OneShot client
const oneShotClient = new OneShotClient(
  'YOUR_API_KEY',
  'SHOGUN_API_URL'
);

// Function to handle Solana transactions
const handleSolanaTransaction = async (
  quote: QuoteTypes,
  address: string,
  client: YourWalletSigner
): Promise<{ transactionHash: string; swapPlacementTimestamp: number; swapExecutionTimestamp: number } | null> => {
  if (!Array.isArray(quote.calldatas)) return null;
  
  const transactions = await Promise.all(
    quote.calldatas.map(async (calldata) => {
      const messageBuffer = Buffer.from(calldata.data, 'base64');
      return VersionedTransaction.deserialize(messageBuffer);
    }),
  );

  const signedTransactions = await client.signAllTransactions!(
    transactions,
    address,
  );
  if (!signedTransactions) {
    throw new Error('Failed to sign transactions');
  }

  const base58Transactions = signedTransactions.map((tx) => bs58.encode(tx.serialize()));

  if (quote.calldatas.length === 1) {
    return handleSingleSolanaTransaction(base58Transactions[0]);
  } else {
    return handleSolanaBundleTransaction(base58Transactions, transactions[0]);
  }
};

// Function to handle a single Solana transaction
const handleSingleSolanaTransaction = async (base58Transaction: string): Promise<{ transactionHash: string; swapPlacementTimestamp: number; swapExecutionTimestamp: number }> => {
  const transactionHash = await sendTransactionUsingJito(base58Transaction);

  const confirmation = await confirmTransaction(transactionHash, {
    maxRetries: 50,
    commitment: 'confirmed',
    checkInterval: 200,
  });
  if (!confirmation.success) {
    throw new Error(`Transaction failed: ${confirmation.error}`);
  }

  return { transactionHash };
};

// Function to handle a bundle of Solana transactions
const handleSolanaBundleTransaction = async (
  base58Transactions: string[],
  firstTransaction: VersionedTransaction,
): Promise<{ transactionHash: string; swapPlacementTimestamp: number; swapExecutionTimestamp: number }> => {
  // Get the signature from the first transaction
  const transactionSignature = firstTransaction?.signatures?.[0];
  if (!transactionSignature) {
    throw new Error('Missing or invalid transaction signature');
  }
  // Convert signature to hash
  const transactionHash = bs58.encode(transactionSignature);
  if (!isValidSolanaSignature(transactionHash)) {
    throw new Error('Invalid transaction signature format');
  }

  // Send the bundle to Jito
  const bundleID = await sendBundleUsingJito(base58Transactions);
  const swapPlacementTimestamp = Date.now();

  // Wait for confirmation
  const confirmed = await checkTransactionConfirmation(transactionHash);
  const swapExecutionTimestamp = Date.now();

  if (!confirmed) {
    throw new Error('Bundle transaction failed to confirm');
  }

  return { transactionHash, swapPlacementTimestamp, swapExecutionTimestamp };
};

// Example usage
async function performSolanaTransaction() {
  try {
    // Get a quote for a cross-chain swap
    const quote = await oneShotClient.fetchQuote({
      srcChain: 7565164, // Solana
      destChain: 1, // Ethereum mainnet
      srcToken: 'So11111111111111111111111111111111111111112', // SOL
      destToken: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // WETH
      amount: '1000000000', // 1 SOL (in lamports)
      senderAddress: 'your_solana_address',
      slippage: 0.5, // 0.5% slippage tolerance
    });

    if (!quote.status) {
      console.error('Failed to get quote:', quote.error);
      return;
    }

    // Execute the transaction
    const result = await handleSolanaTransaction(
      quote.data,
      'your_solana_address',
      yourTurnkeyClient
    );
    console.log('Transaction result:', result);
  } catch (error) {
    console.error('Error performing transaction:', error);
  }
}

Common Use Cases

1. Purchasing Multiple NFTs in One Transaction

const result = await legoClient.MagicEden.SwapForNFT({
  items: [
    { address: '0x7E0b0363804C6C79AAb9aB51850bF8F3D561f868', tokenId: '42' },
    { address: '0x7E0b0363804C6C79AAb9aB51850bF8F3D561f868', tokenId: '43' }
  ],
  token: { 
    address: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', // WBTC
    decimals: 8, 
    chainId: 1 
  },
  userAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e'
});

2. Purchasing with Different Tokens

// Using USDC
const usdcResult = await legoClient.MagicEden.SwapForNFT({
  items: [{ address: '0x...', tokenId: '1' }],
  token: { 
    address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
    decimals: 6, 
    chainId: 1 
  },
  userAddress: '0x...'
});

// Using DAI
const daiResult = await legoClient.MagicEden.SwapForNFT({
  items: [{ address: '0x...', tokenId: '1' }],
  token: { 
    address: '0x6B175474E89094C44Da98b954EedeAC495271d0F', // DAI
    decimals: 18, 
    chainId: 1 
  },
  userAddress: '0x...'
});

3. Checking Token Balances

import { ShogunBalancesApiClient } from '@shogun-sdk/money-legos';

// Initialize the balances client
const balancesClient = new ShogunBalancesApiClient('YOUR_API_KEY');

// Check EVM wallet balances
const evmBalances = await balancesClient.getEvmWalletBalance('0x742d35Cc6634C0532925a3b844Bc454e4438f44e');
console.log('EVM Balances:', evmBalances);

// Check Solana token balances
const solanaBalances = await balancesClient.getSolanaTokenBalances('your_solana_address');
console.log('Solana Balances:', solanaBalances);

// Get token price in USD
const tokenPrice = await balancesClient.getTokenUSDPrice(
  '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // WETH
  1 // Ethereum mainnet
);
console.log('Token Price:', tokenPrice);

// Get token information
const tokenInfo = await balancesClient.getTokenInfo(
  '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // WETH
  1 // Ethereum mainnet
);
console.log('Token Info:', tokenInfo);

Error Handling

Here's a comprehensive example of error handling:

async function purchaseNFTWithErrorHandling() {
  try {
    const result = await legoClient.MagicEden.SwapForNFT({
      items: [{ address: '0x123...', tokenId: '1' }],
      token: { address: '0xabc...', decimals: 18, chainId: 1 },
      userAddress: '0xdef...'
    });
    
    if (!result.status) {
      // Handle specific error cases
      switch (result.error) {
        case 'INSUFFICIENT_BALANCE':
          console.error('Not enough tokens to complete the purchase');
          break;
        case 'INVALID_NFT':
          console.error('The NFT you\'re trying to purchase doesn\'t exist');
          break;
        case 'PRICE_CHANGED':
          console.error('The price has changed, please try again');
          break;
        default:
          console.error(`Failed to fetch data: ${result.error}`);
      }
      return;
    }

    // Success case
    console.log('Purchase data fetched successfully:', result.data);
    
    // Execute transactions...
    
  } catch (error) {
    // Handle unexpected errors
    if (error instanceof Error) {
      console.error('Unexpected error:', error.message);
      console.error('Stack trace:', error.stack);
    } else {
      console.error('Unknown error occurred:', error);
    }
  }
}

API Reference

LegoClient

Constructor

new LegoClient(config: LegoClientConfig)

Parameters:

  • config.apiKey (string): Your API key for authentication
  • config.baseUrl (string, optional): Custom API base URL

Methods

MagicEden.SwapForNFT(props: FetchLegoProps): Promise<LegoResult>

Fetches Lego data for purchasing NFTs.

Parameters:

  • props.items (NFTItem[]): Array of NFT items to purchase
  • props.token (Token): Token to use for the purchase
  • props.userAddress (string): Address of the user making the purchase

Returns: A promise that resolves to a LegoResult object containing:

  • status (boolean): Whether the request was successful
  • error (string): Error message if any
  • data (ResponseData | null): The result data if successful
  • isLoading (boolean): Whether the request is in progress
  • refetch (function): Function to refetch the data with the same parameters

OneShotClient

Constructor

new OneShotClient(apiKey: string, baseUrl: string)

Methods

fetchQuote(params: QuoteParams): Promise<QuoteResponse>

Fetches a quote for a cross-chain swap.

Parameters:

  • params.srcChain (number): Source chain ID
  • params.destChain (number): Destination chain ID
  • params.srcToken (string): Source token address
  • params.destToken (string): Destination token address
  • params.amount (string): Amount to swap
  • params.senderAddress (string): Address of the sender
  • params.slippage (number): Slippage tolerance in percentage

Returns: A promise that resolves to a QuoteResponse object containing:

  • status (boolean): Whether the request was successful
  • error (string): Error message if any
  • data (QuoteTypes | null): The quote data if successful

ShogunBalancesApiClient

Constructor

const balancesClient = new ShogunBalancesApiClient(apiKey: string)

Methods

getEvmWalletBalance(address: string): Promise<EvmBalances>

Gets the token balances for an EVM wallet.

Parameters:

  • address (string): The wallet address

Returns: A promise that resolves to an EvmBalances object containing token balances.

getSolanaTokenBalances(address: string): Promise<SolanaBalances>

Gets the token balances for a Solana wallet.

Parameters:

  • address (string): The wallet address

Returns: A promise that resolves to a SolanaBalances object containing token balances.

getTokenUSDPrice(tokenAddress: string, chainId: number): Promise<TokenPrice>

Gets the USD price for a token.

Parameters:

  • tokenAddress (string): The token address
  • chainId (number): The chain ID

Returns: A promise that resolves to a TokenPrice object containing the token price.

Types

interface NFTItem {
  address: string;  // NFT contract address
  tokenId: string;  // NFT token ID
}

interface Token {
  address: string;  // Token contract address
  decimals: number; // Token decimals (e.g., 18 for ETH)
  chainId: number;  // Chain ID (e.g., 1 for Ethereum mainnet)
}

interface ResponseData {
  steps: Step[];    // Array of transaction steps
  details: Details; // Transaction details
  fees: Fees;      // Fee information
}

Best Practices

  1. Always Check Response Status
const result = await legoClient.MagicEden.SwapForNFT({...});
if (!result.status) {
  // Handle error
  return;
}
  1. Use TypeScript for Better Type Safety
import { LegoClient, NFTItem, Token } from '@shogun-sdk/money-legos';

const items: NFTItem[] = [...];
const token: Token = {...};
  1. Implement Proper Error Handling
try {
  const result = await legoClient.MagicEden.SwapForNFT({...});
  // Handle success
} catch (error) {
  // Handle errors
}
  1. Keep API Keys Secure
// Use environment variables
const legoClient = new LegoClient({
  apiKey: process.env.SHOGUN_API_KEY,
});

Troubleshooting

Common issues and their solutions:

  1. API Key Issues

    • Ensure your API key is valid and active
    • Check if you've exceeded your API rate limits
    • Verify the API key format
  2. Transaction Failures

    • Check if you have sufficient balance
    • Verify gas settings
    • Ensure you're on the correct network
  3. Invalid NFT Data

    • Verify the NFT contract address
    • Check if the token ID exists
    • Ensure the NFT is available for purchase

Support

If you encounter any issues or need help:

1.3.33

1 month ago

1.3.32

1 month ago

1.3.31

2 months ago

1.3.3

2 months ago

1.3.2

2 months ago

1.3.1

2 months ago

1.3.0

2 months ago

1.2.453

2 months ago

1.2.452

2 months ago

1.2.451

2 months ago

1.2.45

2 months ago

1.2.44

2 months ago

1.2.42-beta

2 months ago

1.2.41

2 months ago

1.2.40

2 months ago

1.2.38-avax

2 months ago

1.2.37-avax

2 months ago

1.2.36-avax

2 months ago

1.2.35-avax

2 months ago

1.2.34-avax

2 months ago

1.2.33-avax

2 months ago

1.2.32-avax

3 months ago

1.2.32

3 months ago

1.2.31

3 months ago

1.2.30

3 months ago

1.2.29

3 months ago

1.2.28-avax-rpc-2

3 months ago

1.2.28-avax-rpc-1

3 months ago

1.2.27-avax-rpc-3

3 months ago

1.2.27-rpc-3

3 months ago

1.2.27-rpc-2

3 months ago

1.2.27-rpc

3 months ago

1.2.26

3 months ago

1.2.26-avax

3 months ago

1.2.25

3 months ago

1.2.24

3 months ago

1.2.23

3 months ago

1.2.22

3 months ago

1.2.21

3 months ago

1.2.2

3 months ago

1.2.1

3 months ago

1.2.0

3 months ago

1.1.59

3 months ago

1.1.58

3 months ago

1.1.57

4 months ago

1.1.56

4 months ago

1.1.55

4 months ago

1.1.54

4 months ago

1.1.53

4 months ago

1.1.52

4 months ago