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.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 +

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.


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 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.

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 optional rpcUrl prop; the deprecated etherscanKey prop is ignored.
  • Explorer links open etherscan.io (or sepolia.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