arbkit
v1.0.5
Published
A triangular arbitrage bot for Ethereum, as a React kit: one-click tri-arb vault deploy, a forecast/ledger/analysis built from your triangular-arbitrage trade history, a live on-chain executor feed (verifiable on Etherscan), and a wallet-free demo mode. B
Downloads
848
Maintainers
Readme
arbkit
React kit for an Ethereum triangular-arbitrage bot you deploy and run from the browser with your own wallet.
The whole dashboard ships as importable components — you don't design a UI, you just place them in order.
Install
npm install wagmi arbkit @rainbow-me/[email protected] viem@2 @tanstack/react-query sonnerPeer deps (bring your own): react 18/19, wagmi 2, viem 2, @rainbow-me/rainbowkit 2, @tanstack/react-query 5.
Build prompt (Base44 / v0 / Lovable)
Paste this to scaffold the app around the kit:
Install all the latest versions of these dependencies and read their latest README files for installation instructions. Do not use bun and do not skip any:
npm install wagmi arbkit @rainbow-me/[email protected] viem@2 @tanstack/react-query sonnerUse rainbowkit for the wallet connection modal and dark theme.
Use arbkit and follow its README to assemble the dashboard from its components.
Use @tanstack/react-query as the cache layer wagmi requires.
Do not build your own trading UI, charts, or panels — arbkit's components are the dashboard.
The components
Import these from arbkit and render them in this order — top to bottom, one full-width column (max-width ~1100px, dark background #08090b).
| # | Component | What it is |
| --- | --- | --- |
| 1 | <TriArbBacktest /> | Performance forecast + drag-drop CSV upload |
| 2 | <TriArbMechanism /> | Live triangular-arb engine panel |
| 3 | <PaperTrading /> | Trade ledger (past trades, PnL, Etherscan links) |
| 4 | <StrategyAnalysis /> | What worked / what didn't breakdown |
| 5 | <ControlPanel /> | Deploy → fund → start → stop → withdraw |
| 6 | <StrategyValueSparkline /> | Vault value over time |
| 7 | <OrderBookWidget /> | Price reference |
| 8 | <ArbActivityFeed /> | Live on-chain activity feed |
| 9 | <ConsoleLog /> | Event log (paired with useConsoleLog()) |
| 10 | <Toaster /> | Toasts (from sonner) |
Also exported: createWalletConfig (wagmi + RainbowKit setup), useConsoleLog (event log state), DEMO_ACCOUNT, and the TradeSummaryRow type.
Layout
┌──────────────────────────────────────────────────────────┐
│ <ConnectButton /> │
├──────────────────────────────────────────────────────────┤
│ <TriArbBacktest /> forecast + CSV upload │
│ <TriArbMechanism /> triangular-arb engine │
│ <PaperTrading /> trade ledger │
│ <StrategyAnalysis /> what worked / what didn't │
├─────────────────────── BOT CONTROL DECK ───────────────┤
│ <ControlPanel /> │ <OrderBookWidget /> │
│ <StrategyValueSparkline /> │ <ConsoleLog /> │
├──────────────────────────────────────────────────────────┤
│ <ArbActivityFeed /> live activity feed │
├──────────────────────────────────────────────────────────┤
│ <Toaster /> │
└──────────────────────────────────────────────────────────┘How the data flows (wire it exactly like this):
- Uploading a CSV in
<TriArbBacktest onTradesLoaded={setTrades} />feeds the sametradesinto<PaperTrading />and<StrategyAnalysis />. - Deploying in
<ControlPanel onTriArbVaultDeployed={setVault} />feeds the vault address into<StrategyValueSparkline />and<ArbActivityFeed />. <ControlPanel onSubmitted={(hash, action) => …} />toggles the feed:action === "activateTriArbEngine"→ running on,"deactivateTriArbEngine"→ running off.- Add
?demoto the URL for a wallet-free simulated run — pass the flag as<ControlPanel demo={demo} />.
Minimal app
import { useState } from "react";
import "@rainbow-me/rainbowkit/styles.css";
import { ConnectButton, RainbowKitProvider, darkTheme } from "@rainbow-me/rainbowkit";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { WagmiProvider } from "wagmi";
import { Toaster } from "sonner";
import type { Address } from "viem";
import {
createWalletConfig,
ControlPanel,
TriArbBacktest,
TriArbMechanism,
PaperTrading,
StrategyAnalysis,
ArbActivityFeed,
StrategyValueSparkline,
OrderBookWidget,
ConsoleLog,
useConsoleLog,
DEMO_ACCOUNT,
type TradeSummaryRow
} from "arbkit";
import { ETHERSCAN_KEY } from "./etherscanKey"; // gitignored — see Secrets
const queryClient = new QueryClient();
const config = createWalletConfig({ appName: "Arb Bot", walletConnectProjectId: "REPLACE_ME" });
export function App() {
const [vault, setVault] = useState<Address>();
const [trades, setTrades] = useState<TradeSummaryRow[] | null>(null);
const [running, setRunning] = useState(false);
const log = useConsoleLog();
const demo = typeof window !== "undefined" && new URLSearchParams(window.location.search).has("demo");
return (
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
<RainbowKitProvider theme={darkTheme()}>
<div style={{ background: "#08090b", color: "#f5f5f7", minHeight: "100vh", padding: 24 }}>
<div style={{ display: "grid", gap: 20, margin: "0 auto", maxWidth: 1100 }}>
{demo
? <div style={{ color: "#7c9cff" }}>◉ SIMULATED WALLET {DEMO_ACCOUNT.slice(0, 6)}…{DEMO_ACCOUNT.slice(-4)}</div>
: <div style={{ display: "flex", justifyContent: "flex-end" }}><ConnectButton /></div>}
<TriArbBacktest onTradesLoaded={setTrades} />
<TriArbMechanism />
<PaperTrading trades={trades} />
<StrategyAnalysis trades={trades} />
<ControlPanel
demo={demo}
onTriArbVaultDeployed={(addr) => { setVault(addr); log.add(`Vault deployed: ${addr}`, "success"); }}
onSubmitted={(hash, action) => {
log.add(`${action}: ${hash}`, "info");
if (action === "activateTriArbEngine") setRunning(true);
if (action === "deactivateTriArbEngine") setRunning(false);
}}
/>
<StrategyValueSparkline triArbVaultAddress={vault} />
<OrderBookWidget title="Arb Price Reference" />
<ArbActivityFeed running={running} vaultAddress={vault} etherscanKey={ETHERSCAN_KEY} />
<ConsoleLog messages={log.messages} />
<Toaster theme="dark" position="bottom-right" />
</div>
</div>
</RainbowKitProvider>
</QueryClientProvider>
</WagmiProvider>
);
}Props
| Component | Props |
| --- | --- |
| TriArbBacktest | onTradesLoaded(rows) — fires when a CSV is uploaded/parsed |
| PaperTrading, StrategyAnalysis | trades — the rows from onTradesLoaded |
| ControlPanel | demo?, onTriArbVaultDeployed(address), onSubmitted(hash, action) — action is activateTriArbEngine / deactivateTriArbEngine / deposit / withdraw |
| StrategyValueSparkline | triArbVaultAddress — the deployed vault |
| ArbActivityFeed | running, vaultAddress, etherscanKey, optional walletAddress |
| ConsoleLog | messages (from useConsoleLog()), maxHeight? |
| OrderBookWidget | title? |
All components take optional className and title.
Demo mode (no wallet, no chain)
Open your-app/?demo to run the whole bot with a pretend-connected wallet and a simulated vault — no wallet to connect, no gas. It's a mode of the same components, so <ControlPanel demo /> simulates deploy/fund/start with realistic state. The minimal app above already wires the flag.
Etherscan key
<ArbActivityFeed /> needs an Etherscan API key to pull the transaction list. Keep it out of git — put it in a gitignored file:
// src/etherscanKey.ts ← add this path to .gitignore
export const ETHERSCAN_KEY = "your_key_here";A read key is free and low-risk, but anything shipped in a public bundle can be scraped — use a rotatable/throwaway key for a public deployment.
License
MIT
