Docs
Version 2 (v2)
Quote

Quote v2 API

Quote API computes the best path to swap tokens at the best rate using our Navigator.

With a straightforward API call, you can get the transaction data that will execute the swap without hassle.

💡
Quote API requires authentication.

Changes since v1

  • We don't do gas estimation from now on. This will have similar effect as setting skipGasEstimation=true on v1.
  • slippageNumerator and slippageDenominator now combined into a single slippage field. This is going to be same as fixing slippageDenominator to 10000.
  • Referrer fee has been implemented. You can now set referrerFeeToken, referrerFee, and referrerFeeTo fields to receive referrer fee.
  • payWithSCNR field has been added. With this, you can choose whether to make the from to pay the Swapscanner fee with SCNR instead of the output token. 20% discount will be applied to the Swapscanner fee if payWithSCNR is set to true.
  • Preconditions that were previously blocking the swapTx from being returned are now returned as errors field. swapTx will always be returned.
  • Response body schema has been drastically changed. Please refer to the Response Body section for more details.

Endpoint

https://api.swapscanner.io/v2/quote

Request Message Schema

{
  "domain": {
    "name": "Swapscanner Navigator",
    "version": "v2",
    "chainId": "8217",
    "verifyingContract": "0x8888888888888888888888888888888888888888",
    "salt": "0xYourSaltHere"
  },
  "primaryType": "QuoteRequestV2",
  "types": {
    "EIP712Domain": [
      { "name": "name", "type": "string" },
      { "name": "version", "type": "string" },
      { "name": "chainId", "type": "uint256" },
      { "name": "verifyingContract", "type": "address" },
      { "name": "salt", "type": "bytes32" }
    ],
    "QuoteRequestV2": [
      { "name": "issuedAt", "type": "uint256" },

      { "name": "slippage", "type": "uint16" },
      { "name": "from", "type": "address" },
      { "name": "to", "type": "address" },
      { "name": "tokenInAddress", "type": "address" },
      { "name": "tokenOutAddress", "type": "address" },
      { "name": "amount", "type": "uint256" },

      { "name": "referrerFeeToken", "type": "uint8" },
      { "name": "referrerFee", "type": "uint16" },
      { "name": "referrerFeeTo", "type": "address" },

      { "name": "payWithSCNR", "type": "bool" }
    ]
  }
}
💡
Every address must be lowercased, without the checksum.

Security Related Fields

  • issuedAt - UNIX timestamp (in seconds) when you issued the request. issuedAt and salt will together work as a countermeasure for replay attacks.

    Your computer and the Swapscanner API server could be a clock difference, resulting in the message expiring earlier than expected. In such case, try subtracting 1~2 seconds from your current timestamp. However, do not subtract too much since we have TTL.

Trading Related Fields

  • slippage - slippage that the from wallet would like to allow in BPS (basis points). (e.g. for slippage allowance of 1%, set slippage to 100)

  • from - The address of the wallet (or contract) that would like to perform a swap. Token tokenInAddress will be transferred from this address.

  • to - The address of the wallet (or contract) that would like to receive the swapped token. Token tokenOutAddress will be transferred to this address. In most cases, this should be the same as from address.

  • tokenInAddress - Address of the token that the from wallet would like to provide.

  • tokenOutAddress - Address of the token that the from wallet would like to receive.

  • amount - amount of tokenInAddress that the from wallet would like to provide. Must be numerated with the decimals of the tokenInAddress. (e.g. 1 KLAY = 1000000000000000000)

Referrer Fee Related Fields

  • referrerFeeToken - the token that the referrer would like to receive as a fee (0: same as Swapscanner fee (preferrably stablecoin but can be tokenOut), 1: tokenIn, 2: tokenOut). Set to 0 if you don't want to receive referrer fee.

  • referrerFee - the fee that the referrer would like to receive in BPS (basis points) (e.g. for 0.1% fee, set referrerFee to 10). Set to 0 if you don't want to receive referrer fee.

  • referrerFeeTo - the address that the referrer would like to receive the fee. Set to zero address if you don't want to receive referrer fee.

Swapscanner Fee Related Fields

  • payWithSCNR - whether to make from account to pay the Swapscanner fee with SCNR or not.

Example Message

{
  issuedAt: Math.floor(Date.now() / 1000),
  slippage: '10', // 0.1%
  from: '0x[ADDRESS_TO_ACCOUNT_WHO_WILL_SEND_SWAP_TX_AND_PAY_INPUT_TOKEN]'.toLowerCase(),
  to: '0x[ADDRESS_TO_ACCOUNT_WHO_WILL_RECEIVE_OUTPUT_TOKEN]'.toLowerCase(),
  tokenInAddress: '0x[INPUT_TOKEN_ADDRESS]'.toLowerCase(),
  tokenOutAddress: '0x[OUTPUT_TOKEN_ADDRESS]'.toLowerCase(),
  amount: '1000000',
  referrerFeeToken: '1', // collect from input token
  referrerFee: '10', // 0.10%
  referrerFeeTo: '0x[REFERRER_FEE_TO_ADDRESS]'.toLowerCase()
}

Response Codes

  • 200: OK
  • 400: Bad Request
    • used_salt: the salt given is already used once and not fresh anymore.
    • bad_signature: signature is invalid and Swapscanner API was unable to recover signer address.
    • bttf: acronym of “Back to the Future”. Happens when the issuedAt is greater than the current server timestamp.
    • signature_expired: the request was generated too long ago.
  • 403: Forbidden
    • bad_referrer: the referrer address is not authorized.
    • invalid_signature: the referrer address does not match with the recovered one.
  • 429: Too Many Requests
    • rate_limited: the request is rejected due to rate limiting.
  • 503: Service Unavailable
    • quote_under_maintenance: system is under the maintenance mode and will be back online shortly.

Response Body

{
  // input contains the information about the input token
  "input": {
    // address of the input token
    "address": "0x[INPUT_TOKEN_ADDRESS]",
    // balance of the input token in the `from` account
    "balance": "146362196",
    // amount of the input token that the `from` account would like to provide
    "amount": "10000000000"
  },

  // output contains the information about the output token
  "output": {
    // address of the output token
    "address": "0x[OUTPUT_TOKEN_ADDRESS]",
    // balance of the output token in the `to` account
    "balance": "2592272957307052821882"
  },

  // quote contains the information about the swap
  "quote": {
    // priceImpact is the price impact of the swap
    "priceImpact": 0.005615815216666306,

    // output contains the information about the output token
    "output": {
      // recipient is the address that will receive the output token
      "recipient": "0x[SWAP_RECIPIENT_ADDRESS]",
      // estimatedAmountDeductingFee is the estimated amount of the output token that the `to` account will receive after deducting the fee
      "estimatedAmountDeductingFee": "50020321161059352407537",
      // minimumAmount is the guaranteed minimum amount of the output token that the `to` account will receive.
      // This is approximately equal to deducting the slippage allowance from the `estimatedAmountDeductingFee`.
      "minimumAmount": "49520117949448758883461"
    },

    // fees contains the information about the fees that the `from` account will be paying, or
    // being deducted before and/or after the swap.
    "fees": [
      // Note that referrer desired to receive 0.10% of the input token as a fee, but the actual
      // fee being taken here is 0.0999996% of the input token. This can happen due to precision loss.
      {
        "type": "referrer",
        "fee": { "address": "0x[INPUT_TOKEN_ADDRESS]", "amount": "9999960" },
        "recipient": "0x[REFERRER_FEE_TO_ADDRESS]"
      },
      // Swapscanner fee depends on our fee schedule.
      {
        "type": "swapscanner",
        "fee": {
          // address can be either SCNR or the output token
          "address": "0x[SWAPSCANNER_FEE_TOKEN_ADDRESS]",
          "amount": "9038554652517578627"
        }
      }
    ],

    "routing": [
      {
        "path": [
          {
            "token": "0x22e3ac1e6595b64266e0b062e01fae31d9cdd578",
            "subPaths": [{ "exchange": "KokonutSwap", "fraction": 0.0526315788 }]
          },
          {
            "token": "0x4fa62f1f404188ce860c8f0041d6ac3765a72e67",
            "subPaths": [{ "exchange": "KokonutSwap", "fraction": 0.0526315788 }]
          },
          {
            "token": "0x[OUTPUT_TOKEN_ADDRESS]",
            "subPaths": [{ "exchange": "KokonutSwap", "fraction": 0.0526315788 }]
          }
        ]
      },
      {
        "path": [
          {
            "token": "0xcee8faf64bb97a73bb51e115aa89c17ffa8dd167",
            "subPaths": [{ "exchange": "KLAYswap", "fraction": 0.8421052636 }]
          },
          {
            "token": "0x[OUTPUT_TOKEN_ADDRESS]",
            "subPaths": [
              { "exchange": "ClaimSwap", "fraction": 0.0526315788 },
              { "exchange": "KLAYswap", "fraction": 0.5263157892 },
              { "exchange": "KLAYswap", "fraction": 0.2631578956 }
            ]
          }
        ]
      },
      {
        "path": [
          {
            "token": "0xcee8faf64bb97a73bb51e115aa89c17ffa8dd167",
            "subPaths": [{ "exchange": "KLAYswap", "fraction": 0.0526315788 }]
          },
          {
            "token": "0xba9725eaccf07044625f1d232ef682216f5371c2",
            "subPaths": [{ "exchange": "KLAYswap", "fraction": 0.0526315788 }]
          },
          {
            "token": "0x[OUTPUT_TOKEN_ADDRESS]",
            "subPaths": [{ "exchange": "KLAYswap", "fraction": 0.0526315788 }]
          }
        ]
      },
      {
        "path": [
          {
            "token": "0xcee8faf64bb97a73bb51e115aa89c17ffa8dd167",
            "subPaths": [{ "exchange": "KLAYswap", "fraction": 0.0526315788 }]
          },
          {
            "token": "0xba9725eaccf07044625f1d232ef682216f5371c2",
            "subPaths": [{ "exchange": "KLAYswap", "fraction": 0.0526315788 }]
          },
          {
            "token": "0x34d21b1e550d73cee41151c77f3c73359527a396",
            "subPaths": [{ "exchange": "KLAYswap", "fraction": 0.0526315788 }]
          },
          {
            "token": "0x[OUTPUT_TOKEN_ADDRESS]",
            "subPaths": [{ "exchange": "KLAYswap", "fraction": 0.0526315788 }]
          }
        ]
      }
    ],

    // errors contains the information about the errors that the Swapscanner encountered while
    // computing the quote. Following errors must be addressed before the swap can be performed.
    // Although you can still perform the swap without addressing the errors, the swap may revert.
    "errors": [
      // Some of the errors require manual intervention.
      { "message": "insufficient_input_token_balance" },
      // Some of the errors can be resolved by performing a transaction. In this case, we add
      // `tx` field to the error object.
      {
        "message": "insufficient_input_token_allowance",
        "tx": {
          "type": "approve",
          "txs": {
            "eth": {
              "from": "0x[SWAP_INITIATOR_ADDRESS]",
              "to": "0x[INPUT_TOKEN_ADDRESS]",
              "data": "0x[DATA_TO_ALLOW_SWAPSCANNER_NAEP_TO_SPEND_UINT256_MAX_OF_INPUT_TOKEN]",
              "value": "0x0",
              "type": "0x2",
              "maxPriorityFeePerGas": "0xba43b7400",
              "maxFeePerGas": "0xba43b7400"
            },
            "klay": {
              "from": "0x[SWAP_INITIATOR_ADDRESS]",
              "to": "0x[INPUT_TOKEN_ADDRESS]",
              "data": "0x[DATA_TO_ALLOW_SWAPSCANNER_NAEP_TO_SPEND_UINT256_MAX_OF_INPUT_TOKEN]",
              "value": "0x0",
              "type": "SMART_CONTRACT_EXECUTION",
              "gasPrice": "0xba43b7400"
            },
            "klip": {
              "bappName": "Swapscanner",
              "from": "0x[SWAP_INITIATOR_ADDRESS]",
              "to": "0x[INPUT_TOKEN_ADDRESS]",
              "value": "0",
              "abi": "{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}",
              "params": "[\"0x[SWAPSCANNER_NAEP_ROUTER_ADDRESS]\",\"[UINT256_MAX]\"]"
            }
          }
        }
      }
    ],

    // swapTx contains the information about the transaction that will perform the swap
    "swapTx": {
      "type": "swap",
      "txs": {
        // eth is the transaction data can be used with Metamask-like Ethereum standard wallets
        "eth": {
          "from": "0x[SWAP_INITIATOR_ADDRESS]",
          "to": "0x[SWAPSCANNER_NAEP_ROUTER_ADDRESS]",
          "data": "0x[DATA_TO_PERFORM_SWAP]",
          "value": "0x[INPUT_AMOUNT_IF_INPUT_TOKEN_IS_NATIVE_TOKEN]",
          "type": "0x2",
          "maxPriorityFeePerGas": "0xba43b7400",
          "maxFeePerGas": "0xba43b7400"
        },
        // klay is the transaction data can be used with Kaikas-like Klaytn standard wallets
        "klay": {
          "from": "0x[SWAP_INITIATOR_ADDRESS]",
          "to": "0x[SWAPSCANNER_NAEP_ROUTER_ADDRESS]",
          "data": "0x[DATA_TO_PERFORM_SWAP]",
          "value": "0x[INPUT_AMOUNT_IF_INPUT_TOKEN_IS_NATIVE_TOKEN]",
          "type": "SMART_CONTRACT_EXECUTION",
          "gasPrice": "0xba43b7400"
        },
        // klip is the transaction data can be used with Klip API
        "klip": {
          "bappName": "Swapscanner",
          "from": "0x[SWAP_INITIATOR_ADDRESS]",
          "to": "0x[SWAPSCANNER_NAEP_ROUTER_ADDRESS]",
          "value": "[INPUT_AMOUNT_IF_INPUT_TOKEN_IS_NATIVE_TOKEN]",
          "abi": "{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"swap_3e3c58e6\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}",
          "params": "[\"0x[DATA_TO_PERFORM_SWAP]\",\"0x[DATA_TO_PERFORM_SWAP]\"]"
        }
      }
    }
  }
}

Errors

  • insufficient_input_token_allowance: the from account has not approved the Swapscanner NAEP to spend the input token. The tx field will be present in the error object, which contains the transaction data that will approve the Swapscanner NAEP to spend the input token.

  • insufficient_scnr_fee_allowance: the from account has not approved the Swapscanner NAEP to spend the SCNR. The tx field will be present in the error object, which contains the transaction data that will approve the Swapscanner NAEP to spend the SCNR. This can only be present when payWithSCNR is set to true.

  • insufficient_input_token_balance: the from account does not have sufficient balance of the input token.

  • insufficient_scnr_balance: the from account does not have sufficient balance of the SCNR. This can only be present when payWithSCNR is set to true.

Swap Tx

Return Data

The swapTx will return following data to the caller:

returns (address outputToken, uint256 outputAmount)

Which means outputAmount amount of outputToken has been transferred to the to address.

Event

Following event will be emitted when the swap is performed:

event Swap(
  address indexed sender,
  address recipient,
  address indexed inputToken,
  address indexed outputToken,
  uint256 inputAmount,
  uint256 outputAmount
);

Which means sender has paid inputAmount amount of inputToken, and recipient received outputAmount amount of outputToken.

Fee

There could be two distinct fees that the from account will be paying. One is the Swapscanner fee and the other is the referrer fee. Referrer is a caller of the quote API.

Swapscanner Fee

Swapscanner fee is the fee that the Swapscanner will be charging for providing the best quote. The fee is calculated based on our fee schedule.

There are two ways to pay the Swapscanner fee:

Pay with SCNR

If payWithSCNR is set to true, corresponding amount of SCNR (calculated based on realtime pricing data) will be deducted from from account's balance.

Sufficient amount of SCNR must be present in the from account's balance, and the from account must have approved the Swapscanner NAEP to spend the SCNR.

Discounts of 20% will be applied to the Swapscanner fee if payWithSCNR is set to true.

Pay with Token

If payWithSCNR is set to false, the Swapscanner fee will be automatically deducted from the output token amount.

Referrer Fee

Referrer fee is the fee that the referrer (caller of the quote API) can charge to the from account.

Referrer fee will be disabled if any of the following conditions are met:

  • referrerFeeToken is set to 0.
  • referrerFee is set to 0.
  • referrerFeeTo is set to zero address.

Referrer Fee Token

Referrer can choose which token to receive as a fee. There are three options:

  • 0: referrer fee is disabled.
  • 1: the input token amount (tokenIn) will be deducted before the swap and sent to the referrer as a fee.
  • 2: the output token amount (tokenOut) will be deducted after the swap and sent to the referrer as a fee.