Blockend
HomeLive Demo
BlockEnd Labs
BlockEnd Labs
  • About BlockEnd
    • Overview
    • 🎯Thesis
    • 🧭Compass
    • 🌊LEX Protocol
  • ⚡Compass Widgets
    • Widget Pro
      • Install Widget Pro
      • Customise Widget Pro
    • Widget Lite
  • 👨‍💻Compass API
    • API Reference
      • Getting Started
      • Authentication
      • Fetching Quotes
      • Create Transaction
      • Get Raw Transaction To Execute
      • Check Transaction Status
      • Gasless Swaps
      • Type Definations
      • Get Supported Chains & Tokens
    • Quick Swap API
    • SDK
      • Getting Started
      • Configuration
      • Core Methods
        • getQuotes
        • Create Transaction
        • getNextTxn
        • Check Status
        • pollTransactionStatus
        • executeQuote
        • executeTransaction
      • Gasless Transactions
      • Tokens and Chains
    • Supported Chains
    • Liquidity Sources
  • Code Examples
    • EVM Swaps
    • EVM to SOL Bridge
    • SOLANA Swaps
    • Solana to EVM Bridge
  • Resources
    • Brand Assets
  • Troubleshooting
    • React issues
    • Next js issues
Powered by GitBook
On this page
  • Overview
  • Handling Gasless Transactions
  • Waiting for Transaction Fulfilment
  • Example TypeScript Code for Gasless Swap

Was this helpful?

  1. Compass API
  2. API Reference

Gasless Swaps

Overview

To enable gasless transactions in your swap process, you can add the gasless=true flag to the quotes request. This ensures that only transactions that can be executed without the user paying for gas are returned.

Key Flags

  1. gasless=true: When set to true, this parameter ensures that all returned transactions (including both token approvals and swaps) can be executed without the end-user paying for gas fees. The gas costs will be covered by the protocol, creating a seamless user experience without requiring native tokens for transaction fees

  2. gaslessSwap=true: When set to true, this parameter guarantees that swap transactions will be executed without the end-user paying for gas fees. Unlike the gasless parameter, this option specifically focuses on making the swap operation gasless, while token approval transactions may or may not require gas payment depending on the specific tokens involved in the swap.

Workflow

  1. Quote Request:

    • Include the gasless=true flag to get gasless (approval + swap) transaction quotes.

    • Include gaslessSwap=true to get gasless transaction for swaps, but approvals may or may not require gas.

  2. /createTx and /nextTx Calls:

    • Once you've received the quotes, make the /createTx and /nextTx calls as usual. The process for these calls remains the same.


Handling Gasless Transactions

Response from /nextTx and /createTx

  • The response from both endpoints will contain a gasless field.

    • gasless: false: The transaction requires user gas. The user must sign and submit the transaction via RPC.

    • gasless: true: The transaction is gasless, and you should make a /submit call with the signed transaction data.

Gasless Transaction Process

For gasless transactions, the process differs slightly:

  1. Transaction Data:

    • The transaction data for gasless transactions is different from standard transactions. It only needs to be signed by the user, not submitted to the network via RPC.

  2. Signing the Transaction:

    • The user must sign the transaction using the provided txnData (example signing process shared in the code snippet below).

  3. Submit the Transaction:

    • Once signed, the transaction must be submitted to Blockend via the /submit API.

    Request Body for /submit

    {
      "routeId": "string",
      "stepId": "string",
      "signedTxn": "string"
    }

    Response Example from /submit

    {
      "status": "success",
      "data": {
        "routeId": "01JN23TP2QNH3A8ESJJEQ5A2NM",
        "stepId": "01JN23TP2QQTXZQ93HM30WRWJ5",
        "status": "in-progress"
      }
    }

    status: success: The signed transaction has been successfully submitted. status: in-progress: The transaction is still being processed. Wait for it to complete.


Waiting for Transaction Fulfilment

You can use the normal status check endpoint to monitor the status of the transaction. The key difference is that the txnHash field is not required, as the actual transaction hash is generated by Blockend.

Request Body for /status

{
  "routeId": "string",
  "stepId": "string"
}

The response will be similar to the one from a regular transaction, but the transaction hash is managed by Blockend.


Example TypeScript Code for Gasless Swap

import { ethers } from 'ethers';

const baseRpcUrl = "https://base.drpc.org";
const evmProvider = new ethers.providers.JsonRpcProvider(baseRpcUrl);
const evmSigner = new ethers.Wallet(EVM_PRIVATE_KEY, evmProvider);

const BASE_URL = "https://api2.blockend.com/v1";
const FETCH_OPTIONS = {
  headers: {
    'content-type': 'application/json',
    'x-api-key': '<api-key>',
  }
};

async function main() {
  const baseQuote = {
    fromChainId: "8453",
    fromAssetAddress: "0x4f9fd6be4a90f2620860d680c0d4d5fb53d1a825", // Example asset
    toAssetAddress: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913", // Example asset
    inputAmountDisplay: "1",
    userWalletAddress: evmSigner.address,
    // gasless: true, // gasless for both swaps and approvals
    gaslessSwap: true,  // gasless for swaps (approvals may or may not be gasless)
  };

  const quoteReq = baseQuote;
  const urlParams = Object.entries(quoteReq).map(([key, value]) => `${key}=${value}`).join('&');
  const fetchQuoteReq = await fetch(`${BASE_URL}/quotes?${urlParams}`, FETCH_OPTIONS);
  const fetchQuoteRes = await fetchQuoteReq.json();
  console.log("quotes fetched");
  const quotes = fetchQuoteRes.data.quotes;

  const providerQuote = quotes[0];
  if (!providerQuote) throw new Error("Quote not found");

  const createdTxnReq = await fetch(`${BASE_URL}/createTx?routeId=${providerQuote.routeId}`, FETCH_OPTIONS);
  const createdTxnRes = await createdTxnReq.json();
  console.log("Transaction created");
  const createdTxn = createdTxnRes.data;

  let stepId = "";
  for (const step of createdTxn.steps) {
    stepId = step.stepId;
    const nextTxnReq = await fetch(`${BASE_URL}/nextTx?routeId=${providerQuote.routeId}&stepId=${step.stepId}`, FETCH_OPTIONS);
    const nextTxnRes = await nextTxnReq.json();
    const nextTxn = nextTxnRes.data;

    const txnData = nextTxn.txnData;
    if (!txnData) throw new Error("txnData not found");
    const txnEvm = txnData.txnEvm;
    if (!txnEvm) throw new Error("txnEvm not found");

    if (txnData.gasless || txnData.txnType === "sign-typed") {
      console.log("Executing gasless transaction...");
      const signedTxn = await evmSigner._signTypedData(txnEvm.domain, txnEvm.types, txnEvm.message);
      const submitReq = await fetch(`${BASE_URL}/submit?routeId=${providerQuote.routeId}&stepId=${step.stepId}`, {
        ...FETCH_OPTIONS,
        method: "POST",
        body: JSON.stringify({
          routeId: providerQuote.routeId,
          stepId: step.stepId,
          signedTxn: signedTxn,
        })
      });

      const submitResText = await submitReq.text();
      console.log("Transaction submitted:", submitResText);
    } else {
      console.log("Executing regular transaction...");
      const txn = await evmSigner.sendTransaction(txnEvm);
      const statusCheckRes = await getStatus(providerQuote.routeId, step.stepId, txn.hash);
      console.log("Transaction status:", statusCheckRes);
    }
  }

  const statusCheckRes = await getStatus(providerQuote.routeId, stepId);
  console.log("Final transaction status:", statusCheckRes);
}

async function getStatus(routeId: string, stepId: string, txnHash?: string) {
  const statusCheckReq = await fetch(`${BASE_URL}/status?routeId=${routeId}&stepId=${stepId}&txnHash=${txnHash}`, FETCH_OPTIONS);
  const statusCheckRes = await statusCheckReq.json();
  const status = statusCheckRes.data;

  if (status.status !== "in-progress") {
    return status;
  }

  await sleep(3 * 1000);
  return getStatus(routeId, stepId, txnHash);
}

main().catch(console.error).finally(() => process.exit(0));

PreviousCheck Transaction StatusNextType Definations

Last updated 2 months ago

Was this helpful?

👨‍💻