Execute Swap

Slippage is an important concept in trading that can have a significant impact on your trading outcomes. It refers to the difference between the expected price of a trade and the actual price at which the trade is executed. Slippage can occur in various market conditions and for several reasons, and it’s crucial for traders to be aware of its potential effects.

Fibrous Finance uses slippage settings to prevent you from losing money; there is no need to increase your slippage when you spot an arbitrage opportunity.

Fibrous Finance is still in alpha version. Please make sure you have adjusted your slippage properly.

Usage on EVM Networks (Base, Scroll)

Here’s how to execute a swap on EVM-compatible networks like Base and Scroll:

import { BigNumber } from "@ethersproject/bignumber";
import { Router as FibrousRouter } from "fibrous-router-sdk";
import { parseUnits } from "ethers";
import { account } from "./account";

const RPC_URL = process.env.BASE_RPC_URL;
// Destination address for the swap
const destination = process.env.EVM_PUBLIC_KEY;
// Private key of the account that will be used to sign the transaction
const privateKey = process.env.EVM_PRIVATE_KEY;

const chainName = "base";
// Create a new router instance
const fibrous = new FibrousRouter();

// Create a new contract instance
const account0 = account(privateKey, RPC_URL);
const contractwallet = await fibrous.getContractWaccount(account0, chainName);
const provider = new ethers.JsonRpcProvider(RPC_URL);

const tokens = await fibrous.supportedTokens(chainName);
const inputToken = await fibrous.getToken(
  "0xfde4c96c8593536e31f229ea8f37b2ada2699bb2",
  "base",
);
if (!inputToken) {
  throw new Error("Input token not found");
}
const tokenInAddress = inputToken.address;
const tokenOutAddress = tokens["usdc"].address;
const tokenInDecimals = Number(inputToken.decimals);
const inputAmount = BigNumber.from(parseUnits("5", tokenInDecimals));

// Call the buildTransaction method in order to build the transaction
// slippage: The maximum acceptable slippage of the buyAmount amount.
const slippage = 1; // %1 slippage

const swapCall = await fibrous.buildTransaction(
  inputAmount,
  tokenInAddress,
  tokenOutAddress,
  slippage,
  destination,
  chainName,
);

const approveResponse = await fibrous.buildApproveEVM(
  inputAmount,
  tokenInAddress,
  account0,
  chainName,
);

if (approveResponse === true) {
  try {
    const feeData = await provider.getFeeData();
    if (!feeData.gasPrice) {
      console.log("gasPrice not found");
      return;
    }

    const tx = await contractwallet.swap(
      swapCall.route,
      swapCall.swap_parameters,
      {
        gasPrice: feeData.gasPrice * 2n,
      },
    );
    await tx.wait();
    console.log(`https://basescan.org/tx/${tx.hash}`);
  } catch (e) {
    console.error("Error swapping tokens: ", e);
  }
} else {
  console.error("Error approving tokens");
}

Usage on Starknet

For Starknet, the process is slightly different due to its unique architecture:

import { connect, disconnect } from '@argent/get-starknet'
import { Call } from "starknet";

const starknet = await connect({ showList: false })

await starknet.enable()

if (starknet.isConnected) {
  // Call the buildTransaction method in order to build the transaction
  // slippage: The maximum acceptable slippage of the buyAmount amount.
  const slippage = 1; // %1 slippage
  const receiverAddress = starknet.selectedAddress;

  const approveCall:Call = await fibrous.buildApproveStarknet(
    inputAmount,
    tokenInAddress,
  );

  const swapCall:Call = await fibrous.buildTransaction(
    inputAmount,
    tokenInAddress,
    tokenOutAddress,
    slippage,
    receiverAddress,
    "starknet",
  );

  await starknet.account.execute([approveCall,swapCall]);
}

Alternative Backend Usage on Starknet

If you’re implementing this on the backend for Starknet:

import { Account, Provider } from "starknet";
import { Call } from "starknet";

const provider = new Provider();
const PUBLIC_KEY = process.env.STARKNET_PUBLIC_KEY;
const PRIVATE_KEY = process.env.STARKNET_PRIVATE_KEY;
const RPC_URL = process.env.STARKNET_RPC_URL;
const DESTINATION = process.env.STARKNET_PUBLIC_KEY;
if (!DESTINATION || !PRIVATE_KEY || !RPC_URL || !PUBLIC_KEY) {
  throw new Error("Missing environment variables");
}

// https://www.starknetjs.com/docs/guides/connect_account
// If this account is based on a Cairo v2 contract (for example OpenZeppelin account 0.7.0)
const account = new Account(provider, PUBLIC_KEY, PRIVATE_KEY,"1");

// Call the buildTransaction method in order to build the transaction
// slippage: The maximum acceptable slippage of the buyAmount amount.
const slippage = 1; // %1 slippage
const receiverAddress = accountAddress;

const approveCall:Call = await fibrous.buildApproveStarknet(
  inputAmount,
  tokenInAddress,
);

const swapCall:Call = await fibrous.buildTransaction(
  inputAmount,
  tokenInAddress,
  tokenOutAddress,
  slippage,
  DESTINATION,
  "starknet",
);

await account.execute([approveToken, swapCall])

The swap call returns a transaction object with the following structure:

{
  contractAddress:ROUTER_ADDRESS,
  entrypoint: "swap",
  calldata: calldata,
}

Important Notes

  1. Always handle errors appropriately in production code
  2. Set a reasonable slippage value based on your trading strategy
  3. Make sure to have sufficient balance and approved tokens before executing swaps
  4. Monitor transaction status and implement proper error handling
  5. Consider implementing retry mechanisms for failed transactions
  6. Keep private keys secure and never expose them in your code