import { createWalletClient, createPublicClient, custom, http, erc20Abi, defineChain } from "viem";
const ROUTE = "https://partners.route.fun";
const ETH = "0x0000000000000000000000000000000000000000";
const robinhood = defineChain({
id: 4663,
name: "Robinhood Chain",
nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
rpcUrls: { default: { http: [process.env.ROBINHOOD_RPC_URL!] } },
});
// Backend: your key never leaves the server.
export async function buildSwap(p: { tokenIn: string; tokenOut: string; amount: bigint; user: `0x${string}` }) {
const params = new URLSearchParams({
in: p.tokenIn,
out: p.tokenOut,
amount: p.amount.toString(),
recipient: p.user,
slippageBps: "50",
});
const res = await fetch(`${ROUTE}/quote?${params}`, {
headers: { authorization: `Bearer ${process.env.ROUTE_API_KEY}` },
});
const q = await res.json();
if (!res.ok || !q.ok) throw new Error(q.error ?? `Route returned ${res.status}`);
return q;
}
// Client: approve if needed, then send the transaction from buildSwap().
export async function executeSwap(q: any, wallet: ReturnType<typeof createWalletClient>, account: `0x${string}`) {
const pub = createPublicClient({ chain: robinhood, transport: http() });
const amountIn = BigInt(q.amountIn);
if (q.tokenIn !== ETH) {
const allowance = await pub.readContract({
address: q.tokenIn, abi: erc20Abi, functionName: "allowance", args: [account, q.swap.spender],
});
if (allowance < amountIn) {
const approval = await wallet.writeContract({
account, chain: robinhood, address: q.tokenIn, abi: erc20Abi,
functionName: "approve", args: [q.swap.spender, amountIn],
});
await pub.waitForTransactionReceipt({ hash: approval });
// The approval took time. Ask buildSwap() again before sending.
}
}
const hash = await wallet.sendTransaction({
account, chain: robinhood, to: q.tx.to, data: q.tx.data, value: BigInt(q.tx.value),
});
return pub.waitForTransactionReceipt({ hash });
}