Execute Swaps
Run exact-input swaps, exact-output swaps, and swaps with ERC-4337 accounts.
This guide explains how to run a basic exact-input swap, an exact-output swap, and a swap from an ERC-4337 smart account. You should already have a VeloraProtocolEvm instance.
Swaps spend tokens and gas on-chain. Before execution, approve the input token for the current Velora spender on the account's chain. The module does not submit approvals or reset allowances. See configuration for approval and fee prerequisites.
Basic exact-input swap
For beta.9 or later, carry an accepted output floor into swap(). This example allows at most 1% less output than the preview. Choose the tolerance for your application and obtain user approval before execution.
- Check the current spender allowance and obtain a quote.
- Review the recipient, input amount, output floor, and fee cap with the user.
- Execute the same request with
minAmountOutandswapMaxFee.
Use quoteSwap() to prepare the request:
const ETHEREUM_USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7'
const ETHEREUM_WETH = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'
const request = {
tokenIn: ETHEREUM_USDT,
tokenOut: ETHEREUM_WETH,
tokenInAmount: 1000000n,
to: await account.getAddress()
}
const quote = await swapProtocol.quoteSwap(request)
const minAmountOut = quote.tokenOutAmount * 9900n / 10000n
const maxFee = 200000000000000n // Exclusive cap in wei for this standard EVM account.After approval, pass the reviewed request and limits to swap():
const result = await swapProtocol.swap({
...request,
minAmountOut
}, { swapMaxFee: maxFee })
console.log('Swap transaction hash:', result.hash)
console.log('Total fee (account units):', result.fee)
console.log('Quoted input (base units):', result.tokenInAmount)
console.log('Quoted output (base units):', result.tokenOutAmount)Execution fetches a new rate and rejects a mismatched pair, mismatched input amount, invalid or non-positive amounts, or output below the floor before building the transaction. It then applies the transaction validation checks before fee estimation and sending; these checks do not decode the calldata. The returned token amounts are from that rate, not a settlement receipt. The earlier quote's route is not pinned.
Exact output swap
Preview an exact-output BUY request with quoteSwap() and review its input amount before execution:
const buyRequest = {
tokenIn: ETHEREUM_USDT,
tokenOut: ETHEREUM_WETH,
tokenOutAmount: 500000000000000000n, // 0.5 WETH (18 decimals)
to: await account.getAddress()
}
const buyQuote = await swapProtocol.quoteSwap(buyRequest)
console.log('Quoted input (base units):', buyQuote.tokenInAmount)
console.log('Quoted execution fee (account units):', buyQuote.fee)BUY fetches a new rate at execution and has no maximum input-amount option. Keep the input-token allowance within the spending budget you authorize; swapMaxFee and minAmountOut do not cap the input-token spend.
After reviewing and approving that budget, execute the request with the fee cap:
const result = await swapProtocol.swap(buyRequest, { swapMaxFee: maxFee })
console.log('Swap hash:', result.hash)
console.log('Quoted input (base units):', result.tokenInAmount)
console.log('Quoted output (base units):', result.tokenOutAmount)BUY validates the requested exact output and retains it in the transaction build. An optional minAmountOut also rejects an output below that floor.
Swap with ERC-4337
You can perform a user-operation-backed swap by constructing VeloraProtocolEvm with WalletAccountEvmErc4337 and passing paymaster options to swap():
import { WalletAccountEvmErc4337 } from '@tetherto/wdk-wallet-evm-erc-4337'
import VeloraProtocolEvm from '@tetherto/wdk-protocol-swap-velora-evm'
const aa = new WalletAccountEvmErc4337(seedPhrase, "0'/0/0", {
chainId: 1,
provider: 'https://ethereum-rpc.publicnode.com',
bundlerUrl: process.env.BUNDLER_URL,
paymasterUrl: process.env.PAYMASTER_URL,
paymasterAddress: process.env.PAYMASTER_ADDRESS,
safeModulesVersion: '0.3.0',
paymasterToken: {
address: '0xdAC17F958D2ee523a2206206994597C13D831ec7'
}
})
// Exclusive cap: 0.01 USDt with this six-decimal paymaster token.
const swapAA = new VeloraProtocolEvm(aa, { swapMaxFee: 10000n })
const result = await swapAA.swap({
tokenIn: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
tokenOut: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
tokenInAmount: 1000000n
}, {
paymasterToken: {
address: '0xdAC17F958D2ee523a2206206994597C13D831ec7'
},
swapMaxFee: 10000n
})
console.log('Swap hash:', result.hash)
console.log('Total fee (USDt base units):', result.fee)Token addresses must match the chain your account uses (for example, Ethereum USD₮ and Arbitrum USD₮0 use different contract addresses).
Next Steps
- Get swap quotes before sending
- Handle errors
- Get started if you still need setup