arbkit
v1.5.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). Built on wagmi + RainbowKit +
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.
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), 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.
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,
type TradeSummaryRow
} from "arbkit";
const queryClient = new QueryClient();
// Injected wallet only (MetaMask / Chrome). No WalletConnect project ID needed.
const config = createWalletConfig({ appName: "Arb Bot" });
export function App() {
const [vault, setVault] = useState<Address>();
const [trades, setTrades] = useState<TradeSummaryRow[] | null>(null);
const [running, setRunning] = useState(false);
const log = useConsoleLog();
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 }}>
<div style={{ display: "flex", justifyContent: "flex-end" }}><ConnectButton /></div>
<TriArbBacktest onTradesLoaded={setTrades} />
<TriArbMechanism />
<PaperTrading trades={trades} />
<StrategyAnalysis trades={trades} />
<ControlPanel
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} />
<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 | onTriArbVaultDeployed(address), onSubmitted(hash, action) — action is activateTriArbEngine / deactivateTriArbEngine / deposit / withdraw |
| StrategyValueSparkline | triArbVaultAddress — the deployed vault |
| ArbActivityFeed | running, vaultAddress, optional rpcUrl |
| ConsoleLog | messages (from useConsoleLog()), maxHeight? |
| OrderBookWidget | title? |
All components take optional className and title.
No API keys needed
This kit needs no WalletConnect project ID and no Etherscan API key. Do not scaffold walletConfig project-id placeholders or an etherscanKey file.
- Wallet: injected only (MetaMask / Chrome).
createWalletConfig({ appName })takes no project ID. - Live feed:
<ArbActivityFeed />scans blocks over a public JSON-RPC endpoint (eth_getBlockReceipts), not the Etherscan API. Override the endpoint with the optionalrpcUrlprop; the deprecatedetherscanKeyprop is ignored. - Explorer links open
etherscan.io(orsepolia.etherscan.io) directly — no key involved.
The React app holds no secrets and no strategy. Vault forwarding config and the trading engine live on your own arbkit-server (a small private Next.js app); the kit talks to it over an authenticated URL.
Configuration
None. Install the package and the components work — the vault contract and its
config are served by the built-in server. (Optional, for a private server:
serverUrl / serverToken props on ControlPanel, or VITE_ARBKIT_SERVER_URL /
VITE_ARBKIT_SERVER_TOKEN in your app's environment.)
License
MIT
