Executing a Trade
This section demonstrates how to use a quote to construct and execute a trade on the Storyhunt V3 protocol.
Introduction
This section demonstrates how to use a quote to construct and execute a trade on the Storyhunt V3 protocol. The example involves trading between two ERC20 tokens, WIP and USDC, and allows configuring the input token, output token, input amount, and fee level.
The process includes:
Constructing a route from pool information
Building an unchecked trade
Executing the trade
At the end, you’ll be able to create and execute a trade programmatically between any two ERC20 tokens.
Constructing a Route from Pool Information
First, gather metadata from the relevant pool contract. This includes constant information about the pool and its current state:
async function getPoolInfo() {
const [fee, liquidity, slot0] = await Promise.all([
poolContract.fee(),
poolContract.liquidity(),
poolContract.slot0(),
]);
return {
fee,
liquidity,
sqrtPriceX96: slot0[0],
tick: slot0[1],
};
}
Key values:
fee: The fee taken from every swap in the pool, expressed as 1 per million (e.g., a value of 500 means 0.05%).
liquidity: The current liquidity available for trades at the current price.
sqrtPriceX96: The current price of the pool.
tick: The tick corresponding to the current pool price.
Next, construct a Pool
instance:
const poolInfo = await getPoolInfo();
const pool = new Pool(
CurrentConfig.tokens.in,
CurrentConfig.tokens.out,
CurrentConfig.tokens.poolFee,
poolInfo.sqrtPriceX96.toString(),
poolInfo.liquidity.toString(),
poolInfo.tick
);
Creating a Route
Using the Pool
instance, construct a Route
to represent a trade path:
import { Route } from '@storyhunt/v3-sdk';
const swapRoute = new Route(
[pool],
CurrentConfig.tokens.in,
CurrentConfig.tokens.out
);
The Route
object specifies that the input token will be traded for the output token over the specified pool.
Building an Unchecked Trade
Obtain a quote for the trade and construct an unchecked trade:
import { SwapQuoter } from '@storyhunt/v3-sdk';
import { CurrencyAmount, TradeType } from '@storyhunt/sdk-core';
const { calldata } = await SwapQuoter.quoteCallParameters(
swapRoute,
CurrencyAmount.fromRawAmount(
CurrentConfig.tokens.in,
fromReadableAmount(
CurrentConfig.tokens.amountIn,
CurrentConfig.tokens.in.decimals
)
),
TradeType.EXACT_INPUT,
{ useQuoterV2: true }
);
const quoteCallReturnData = await provider.call({
to: QUOTER_CONTRACT_ADDRESS,
data: calldata,
});
const amountOut = ethers.utils.defaultAbiCoder.decode(['uint256'], quoteCallReturnData);
const uncheckedTrade = Trade.createUncheckedTrade({
route: swapRoute,
inputAmount: CurrencyAmount.fromRawAmount(
CurrentConfig.tokens.in,
fromReadableAmount(
CurrentConfig.tokens.amountIn,
CurrentConfig.tokens.in.decimals
)
),
outputAmount: CurrencyAmount.fromRawAmount(
CurrentConfig.tokens.out,
JSBI.BigInt(amountOut)
),
tradeType: TradeType.EXACT_INPUT,
});
Executing the Trade
Approve the SwapRouter
contract to spend the input token:
const tokenApproval = await getTokenTransferApproval(CurrentConfig.tokens.in);
Set the swap options, including slippage tolerance and deadline:
import { SwapOptions } from '@storyhunt/v3-sdk';
import { Percent } from '@storyhunt/sdk-core';
const options: SwapOptions = {
slippageTolerance: new Percent(50, 10_000), // 0.50%
deadline: Math.floor(Date.now() / 1000) + 60 * 20, // 20 minutes from now
recipient: walletAddress,
};
Use the SwapRouter
to get the call parameters for the trade:
import { SwapRouter } from '@storyhunt/v3-sdk';
const methodParameters = SwapRouter.swapCallParameters([uncheckedTrade], options);
Construct and send the transaction:
const tx = {
data: methodParameters.calldata,
to: SWAP_ROUTER_ADDRESS,
value: methodParameters.value,
from: walletAddress,
maxFeePerGas: MAX_FEE_PER_GAS,
maxPriorityFeePerGas: MAX_PRIORITY_FEE_PER_GAS,
};
const res = await wallet.sendTransaction(tx);
Next Steps
With the ability to execute trades, you can now explore routing through multiple pools for optimal pricing and fees. Expand your implementation to include advanced routing features for more efficient swaps.