LogoLogo
  • Xave Finance
  • Contract Reference
  • Deployment Addresses
    • Avalanche (C-Chain)
    • Polygon (POS) Mainnet
    • Ethereum Mainnet
    • Apothem Testnet
    • Sepolia Testnet
  • Developer Guides
    • Executing FX Trades
    • Adding / Removing Liquidity
  • Contract API
    • Assimilators
      • API Reference
    • FXPool
      • API Reference
  • Other API Reference
    • Pairs and Tickers
Powered by GitBook
On this page
  • Executing a Trade via the Balancer Smart Order Router
  • Executing a Trade via the Balancer API
  • Sample Batch Swap Walkthrough
  1. Developer Guides

Executing FX Trades

PreviousDeveloper GuidesNextAdding / Removing Liquidity

Last updated 1 year ago

Preparing a swap transaction on an FXPool is no different from preparing a swap transaction via the Balancer router (Xave FXPools are exposed via Balancer's Smart Order Router).

Please refer to Deployment Addresses to access FXPool parameters (such as poolId) when interacting with the Balancer SOR and/or API. However, if you deployed your pool via the self service functionality, you will have to note the contract address of your deployment to fetch your FXPool's parameters

Executing a Trade via the Balancer Smart Order Router

Please see the Balancer docs for instructions on how to trade on Xave via the Balancer router and API

Executing a Trade via the Balancer API

You may also execute trades and interact with the Balancer Smart Order Router via API

Sample Batch Swap Walkthrough

Batch Swaps

import VaultABI from '../path/to/abi/Vault.json'

const vaultContract = useContract('0xBA12222222228d8Ba445958a75a0704d566BF2C8, VaultABI)

Sort the addresses of the tokens to be swapped. Token ordering is very important in the Balancer Vault; each pool stores its tokens sorted numerically. Because of this, we will need to sort our own token lists when interacting with pools.

// Token addresses (checksum format)
const tokenIn = '0xDC3326e71D45186F113a2F448984CA0e8D201995'.toLowerCase(); // XSGD
const tokenOut  = '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174'.toLowerCase(); // USDC

const sortedTokenAddresses = [tokenIn, tokenOut].sort()

Determine the swap kind and scale it to the correct decimal.

// // SwapKind is an Enum. This example handles a GIVEN_IN swap.
// https://github.com/balancer-labs/balancer-v2-monorepo/blob/0328ed575c1b36fb0ad61ab8ce848083543070b9/pkg/vault/contracts/interfaces/IVault.sol#L497
// 0 = GIVEN_IN, 1 = GIVEN_OUT
const swap_kind = 0;
const decimals = swapType === 0 ? tokenIn.decimals : tokenOut.decimals

Define swap settings. Here, we're specifying that the sender/recipient for the tokens going into/out of the trade are both the account that we initialized the script with. Note that with this granularity, it is possible to make a swap that sends the tokens to a different address.

We specify that {to/from}InternalBalance are both False. This will be the default use case for most users; however, you may have a use case that would benefit from Internal Balances.

// Some code
const funds = {
      sender: account,
      recipient: account,
      fromInternalBalance: false,
      toInternalBalance: false
}
const swapSteps = [
        {
            poolId: '0x726e324c29a1e49309672b244bdc4ff62a270407000200000000000000000702',
            assetInIndex: sortedTokenAddresses.indexOf(tokenIn),
            assetOutIndex: sortedTokenAddresses.indexOf(tokenOut),
            amount: 1,
            userData: '0x'
        }
    ]

const deadlineBN = parseUnits(`${new Date().getTime() + deadline * 1000}`)
const deltas = await vaultContract.callStatic.queryBatchSwap(swapType, swaps, tokenAddresses, funds)

Calculate amountOut with slippage. We are also scaling our limits to account for the token-specific decimals.

const amountOutWithSlippage = (Number(estimatedAmountOut) - Number(estimatedAmountOut) * slippage) * -1
    const limits = tokenAddresses.map(address => {
      if (isSameAddress(address, [tokenIn.address])) {
        return numberToBigNumber(Number(amountIn), tokenIn.decimals)
      } else if (isSameAddress(address, [tokenOut.address])) {
        return numberToBigNumber(amountOutWithSlippage, tokenOut.decimals)
      } else {
        return parseUnits('0')
      }
    })

Finally, call the batchSwap

const tx = await vaultContract.batchSwap(HaloSwapType.SwapExactIn, swaps, tokenAddresses, funds, limits, deadlineBN)

Initialize the Balancer Vault Contract. Refer to the for the correct vault address.

Define swap steps. In this swap step, we assume that the pool contains both tokens. The deadline for a transaction is the time (in ) after which it will no longer attempt to make a trade.

Call to preview the input/output amount for the swap

Unix timestamp
queryBatchSwap
Use the Smart Order Router | Balancer
Logo
Using the API | Balancer
Logo
deployed addresses