Squid Dev Documentation
  • Getting Started
    • Overview
    • Get an Integrator ID
    • Integrator Quickstart
  • Widget Integration
    • Add A Widget
      • Swap widget
        • Getting Started
        • Installing the Widget
        • React Installation
        • NextJS Installation
        • Vite Installation
        • Iframe Installation
        • Customization Guide
          • Default User Settings
          • Configuring Content
          • Default Chains and Tokens
          • Configuration Types
          • Collect Fees
        • Information for Integrators
        • Set default chains and tokens via URL
        • Errors
    • Upgrade Your Widget
  • API & SDK Integration
    • API
      • Swap & Bridge Example
      • Staking Example
      • Cross-chain NFT Purchase Example
      • Get Route Status
    • SDK
      • Cross-chain Swap Example
      • Staking Example
      • Cross-chain NFT Purchase Example
      • Get Route Status
    • Key Concepts
      • Route Request Parameters
      • Get a route
      • Execute the route
      • 🪝Hooks
        • How do hooks work
        • Build a preHook
        • Build a postHook
        • Using the full ERC20 or Native balance in a call
        • ❗Transfer the remainder to the user
        • Get a route and execute as normal
      • Express
      • Track status
      • Types
      • Collect Fees
      • Get supported tokens and chains
    • Coral: Intent Swaps
      • Integrating Coral
    • NEW: Bitcoin and Solana
  • Adding Tokens
    • Whitelist a Token
    • Interchain Token(ITS) Listings
      • How To List
    • Circle's EURC Integration Guide
  • Migration
    • Squid v2 vs Squid v1
    • v1 -> v2 Migration
  • Additional Resources
    • Contracts
    • Squid v1 Docs
      • SDK
        • Installing our SDK
        • Get supported tokens and chains
          • Example chains response
          • Example tokens response
        • Set your transfer parameters
        • Get a route
          • Understanding the route response
        • Execute your swap or call
        • Get Route Status
        • Contract calls
          • Code example
          • Creating a ContractCall object
          • Contract call types
          • Approving ERC20s in our multicall
          • Transferring the remainder to a user
        • Collect Fees
          • Fee collector contract addresses
        • Working example!
      • API
        • integratorId
        • API playground
        • Base URLs
        • Get supported tokens and chains
        • Get a route
        • Checking the status of a transaction
        • Error codes
          • V2 API
      • Cosmos
        • Installing our SDK
        • Get supported tokens and chains
          • Example chains response
          • Example tokens response
        • Set your transfer parameters
        • Get a route
          • Cosmos route response
        • Execute your swap or call on Cosmos
        • Get Route Status
        • Cosmos custom calls
        • Working cosmos example!
        • Fallback Addresses
    • Additional Dev Resources
      • Choose How To Integrate Squid
      • Squid x Tenderly
      • Testnet or Mainnet?
      • Understanding Gas Payments
      • Supported Chains and Tokens
      • Request a new supported token
      • Liquidity Sources
        • axlASSET Liquidity
      • Integrator type specific docs
        • DEXs
        • Aggregators
        • NFTs
      • Setting up an EVM signer
      • Setting up Cosmos signer
      • Contract addresses
      • SDK easter eggs
        • Setting toAmount
        • getAllBalances
        • Advanced set up
        • Manually approve a route
        • Manually approve an ERC20
      • Whitelist a token
      • Security & Audits
        • Security
        • Audits
        • Axelar
      • Get an integrator-id
    • Architecture
      • FAQ
      • Liquidity model
      • Architecture
      • General message passing (GMP)
      • Transaction times and fees
      • Fallback behaviour on failed transactions
      • Axelar
    • Brand Assets
      • "Powered by Squid" Policy
    • Audits & Security
    • Contact
  • Changelog
    • SDK
      • v1.3
      • v1.2
    • API
      • v1.9
      • v1.8
      • v1.7
      • v1.6
  • Old v2 Documentation (Deprecated)
    • Whitelist a Token
    • Interchain Token(ITS) Listings
      • How To List
    • Add A Widget
      • Swap widget
        • Getting Started
        • Installing the Widget
        • React Installation
        • NextJS Installation
        • Iframe Installation
        • Customization Guide
          • Default User Settings
          • Theme Customization
          • Configuring Content
          • Default Chains and Tokens
          • Configuration Types
          • Collect fees
        • Information for Integrators
        • Set default chains and tokens via URL
        • Errors
      • Stake widget
        • Installing the Widget
        • Configuration
        • Importing The widget
    • Quick Start
    • API
      • Swap & Bridge Example
      • Staking Example
      • Cross-chain NFT Purchase Example
    • SDK
      • Cross-chain Swap Example
      • Staking Example
      • Cross-chain NFT Purchase Example
    • Key Concepts
      • Route Request Parameters
      • Get a route
      • Execute the route
      • 🪝Hooks
        • How do hooks work
        • Build a preHook
        • Build a postHook
        • Using the full ERC20 or Native balance in a call
        • ❗Transfer the remainder to the user
        • Add your hooks to a route request, or widget
        • Get a route and execute as normal
      • Boost
      • Track status
      • Types
      • Collect Fees
      • Get supported tokens and chains
Powered by GitBook
On this page
  1. API & SDK Integration
  2. SDK

Cross-chain NFT Purchase Example

PreviousStaking ExampleNextGet Route Status

Last updated 2 months ago

This example walks you through how to implement the SDK to purchase an NFT on any chain.

Download the full example .

import { Squid } from "@0xsquid/sdk";
import { ethers } from "ethers";

// Environment
// add to a file named ".env" to prevent them being uploaded to github
import * as dotenv from "dotenv";
dotenv.config();
const avaxRpcEndpoint = process.env.AVAX_RPC_ENDPOINT;
const privateKey = process.env.PRIVATE_KEY;

// ABIs
import erc1155Abi from "../abi/erc1155Abi";
import erc20Abi from "../abi/erc20Abi";
import treasureMarketplaceAbi from "../abi/treasureMarketplaceAbi";

// Squid call types for multicall
const SquidCallType = {
  DEFAULT: 0,
  FULL_TOKEN_BALANCE: 1,
  FULL_NATIVE_BALANCE: 2,
  COLLECT_TOKEN_BALANCE: 3,
};

// addresses and IDs
const avalancheId = 43114;
const arbitrumId = 42161;
const nativeToken = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
const squidMulticall = "0x4fd39C9E151e50580779bd04B1f7eCc310079fd3";
const magicToken = "0x539bdE0d7Dbd336b79148AA742883198BBF60342";
const treasureAddress = "0x09986b4e255b3c548041a30a2ee312fe176731c2"; // treasure contract
const moonrockNftAddress = "0xc5295c6a183f29b7c962df076819d44e0076860e";
const moonrockOwner = "0xa5c53eb116EC0CE355D8be38b0EB424ce520A4db";

// amount of AVAX to send (currently 0.05 AVAX)
const amount = "30000000000000000";

const getSDK = () => {
  const squid = new Squid({
    baseUrl: "https://v2.api.squidrouter.com",
    integratorId: process.env.INTEGRATOR_ID,
  });
  return squid;
};

(async () => {
  // set up your RPC provider and signer
  const provider = new ethers.JsonRpcProvider(avaxRpcEndpoint);
  const signer = new ethers.Wallet(privateKey, provider);
  console.log("Signer address: ", signer.address);

  // instantiate the SDK
  const squid = getSDK();
  // init the SDK
  await squid.init();
  console.log("Squid inited");

  // Generate the encoded data to approve the Treasure contract to spend Magic
  const erc20ContractInterface = new ethers.Interface(erc20Abi);
  const approveEncodeData = erc20ContractInterface.encodeFunctionData(
    "approve",
    [treasureAddress, "0"]
  );

  // Generate the encoded data to buy the NFT on Treasure
  // This example buys a MoonRock NFT on Treasure on mainnet
  // https://trove.treasure.lol/collection/smol-treasures/1
  const treasureMarketplaceInterface = new ethers.Interface(
    treasureMarketplaceAbi
  );
  const _buyItemParams = {
    nftAddress: moonrockNftAddress,
    tokenId: 1,
    owner: moonrockOwner,
    quantity: 1,
    maxPricePerItem: "990000000000000000",
    paymentToken: magicToken,
    usinEth: false,
  };
  const buyMoonRockNftEncodeData =
    treasureMarketplaceInterface.encodeFunctionData("buyItems", [
      [_buyItemParams],
    ]);

  // Generate the encoded data to transfer the NFT to signer's address
  const erc1155Interface = new ethers.Interface(erc1155Abi);
  const transferNftEncodeData = erc1155Interface.encodeFunctionData(
    "safeTransferFrom",
    [squidMulticall, signer.address, 1, 1, 0x00]
  );

  // Generate the encoded data to send any remaining Magic back to signer's address
  const transferMagicEncodeData = erc20ContractInterface.encodeFunctionData(
    "transfer",
    [signer.address, "0"]
  );

  const { route, requestId } = await squid.getRoute({
    toAddress: signer.address,
    fromChain: avalancheId,
    fromToken: nativeToken,
    fromAmount: amount,
    toChain: arbitrumId,
    toToken: magicToken,
    slippage: 1,   //optional, Squid will dynamically calculate if removed
    // enableExpress: false, // default is true on all chains except Ethereum
    postHook: [
      description: "Buy Milady 2039 on Ethereum"
      {
        callType: SquidCallType.FULL_TOKEN_BALANCE,
        target: magicToken,
        value: "0",
        callData: approveEncodeData,
        payload: {
          tokenAddress: magicToken,
          inputPos: 1,
        },
        estimatedGas: "50000",
      },
      {
        callType: SquidCallType.DEFAULT,
        target: treasureAddress,
        value: "0",
        callData: buyMoonRockNftEncodeData,
        payload: {
          tokenAddress: "1",
          inputPos: 1,
        },
        estimatedGas: "80000",
      },
      {
        callType: SquidCallType.DEFAULT,
        target: moonrockNftAddress,
        value: "0",
        callData: transferNftEncodeData,
        payload: {
          tokenAddress: "0x",
          inputPos: 1,
        },
        estimatedGas: "50000",
      },
      {
        callType: SquidCallType.FULL_TOKEN_BALANCE, // transfer any remaining MAGIC to the user's account
        target: magicToken,
        value: "0",
        callData: transferMagicEncodeData,
        payload: {
          tokenAddress: magicToken,
          inputPos: 1,
        },
        estimatedGas: "50000",
      },
    ],
  });

  const tx = (await squid.executeRoute({
    signer,
    route,
  })) as unknown as ethers.TransactionResponse;
  const txReceipt = await tx.wait();

  const axelarScanLink = "https://axelarscan.io/gmp/" + txReceipt.hash;
  console.log(
    "Finished! Please check Axelarscan for more details: ",
    axelarScanLink,
    "\n"
  );

  console.log(
    "Track status via API call to: https://api.squidrouter.com/v1/status?transactionId=" +
      txReceipt.hash,
    "\n"
  );

  // It's best to wait a few seconds before checking the status
  await new Promise((resolve) => setTimeout(resolve, 5000));

  const status = await squid.getStatus({
    transactionId: txReceipt.hash,
  });

  console.log("Status: ", status);
})();
here