Bot Integration
This guide shows how to process trade signals through Evix with slippage protection — a common pattern for automated trading bots.
Full Example
import { createPublicClient, createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { base } from "viem/chains";
import { EvixClient } from "@inductiv/evix-sdk";
const account = privateKeyToAccount("0x...");
const publicClient = createPublicClient({
chain: base,
transport: http(),
});
const walletClient = createWalletClient({
account,
chain: base,
transport: http(),
});
const evix = new EvixClient({
chainId: base.id,
contractAddress: "0x...",
publicClient,
walletClient,
});
// Define a trade signal type
type TradeSignal = {
tokenIn: `0x${string}`;
tokenOut: `0x${string}`;
amountIn: bigint;
maxSlippageBps: bigint;
};
async function executeSignal(signal: TradeSignal) {
const deadline = BigInt(Math.floor(Date.now() / 1000) + 30);
// Simulate to get expected output
const expectedOut = await evix.simulateSwap({
tokenIn: signal.tokenIn,
tokenOut: signal.tokenOut,
amountIn: signal.amountIn,
deadline,
minAmountOut: 0n,
recipient: account.address,
});
const minOut =
expectedOut - (expectedOut * signal.maxSlippageBps) / 10_000n;
console.log(
`Signal: ${signal.amountIn} in -> expected ${expectedOut} out (min: ${minOut})`
);
const result = await evix.swap({
tokenIn: signal.tokenIn,
tokenOut: signal.tokenOut,
amountIn: signal.amountIn,
deadline,
minAmountOut: minOut,
recipient: account.address,
});
console.log(`Executed: ${result.transactionHash}`);
return result;
}
// Process signals from a queue
async function main() {
const signals: TradeSignal[] = [
{
tokenIn: "0x..." as `0x${string}`,
tokenOut: "0x..." as `0x${string}`,
amountIn: 500_000n,
maxSlippageBps: 30n, // 0.3%
},
];
for (const signal of signals) {
try {
await executeSignal(signal);
} catch (err) {
console.error("Signal execution failed:", err);
}
}
}
main().catch(console.error);
Key Patterns
Tight Deadlines
For bot integrations, use short deadlines (15–60 seconds). Stale transactions that land late can result in unfavorable execution.
// 30-second deadline for latency-sensitive bots
const deadline = BigInt(Math.floor(Date.now() / 1000) + 30);
Per-Signal Slippage
Each signal carries its own maxSlippageBps, allowing you to differentiate between:
- Aggressive signals (low slippage, tight tolerance)
- Opportunistic signals (higher slippage, more flexibility)
Error Isolation
Wrap each signal execution in a try/catch to prevent a single failure from halting the queue:
for (const signal of signals) {
try {
await executeSignal(signal);
} catch (err) {
// Log and continue — don't let one bad signal halt the pipeline
console.error("Signal execution failed:", err);
}
}
Simulation as Gating
Use the simulation result to gate execution. If the simulated output is below a profitability threshold, skip the signal:
const expectedOut = await evix.simulateSwap(params);
if (expectedOut < signal.minProfitableOutput) {
console.log("Skipping: output below profitability threshold");
return;
}
Considerations
| Concern | Recommendation |
|---|---|
| Deadline | 15–60s for bots, shorter is better |
| Slippage | 10–50 bps for stable pairs, higher for volatile |
| Error handling | Isolate per-signal, log failures, continue processing |
| Simulation | Always simulate first — it catches stale pairs, bad amounts, and reverts |
| Concurrency | Process signals sequentially per account to avoid nonce conflicts |