npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

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

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 sonner

Peer 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 sonner

Use 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 same trades into <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 ?demo to 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