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. Old v2 Documentation (Deprecated)
  2. SDK

Cross-chain NFT Purchase Example

PreviousStaking ExampleNextKey Concepts

Last updated 11 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://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