Platform
Farbeam is one Node process with one SQLite file. It polls seven chains, stores large transfers for 7 days, answers lookups over a public REST API, and matches new transfers against alert rules. This page explains how those parts connect and where each one stops.
The numbers on this page come from the source code and from calls to the running API at 2026-11-04T19:20:48Z. Check the current state on the status page.
#Data flow
| Stage | Input | What happens | Output | Kept for |
|---|---|---|---|---|
| Chain poller | JSON-RPC head, logs and blocks | One loop per chain reads the head, fees and new transfers | Chain state, transfer events | Chain state in memory |
| Price refresh | CoinGecko simple/price | Runs every 60 seconds | USD price per asset | In memory |
| Valuation filter | Transfer amount and price | Rows below $100,000 are dropped. Assets with no price are dropped | Stored transfer | 7 days |
| Label join | Address and the label set | Adds from_label, to_label, from_type, to_type by address, with no chain check | Enriched event | Labels ship with the code |
| Live stream | New transfer or block event | Pushed to open SSE connections | transfer and block events | Not kept, no replay |
| Alert engine | New transfer event, or a liquidity sample every 5 minutes | Each enabled rule runs against the event, then waits for its cooldown | Queued delivery | Log kept 14 days |
| API and tools | HTTP request | Reads the store or calls a public source through a cache | JSON | Cache TTLs below |
| Status sampler | Chain state | Writes one health sample per chain per 5 minutes | /status/history | 30 days |
Two kinds of data use this flow. Index data, such as transfers, comes from the store and was collected earlier. Lookup data, such as a wallet balance or a token report, is read from public sources when you ask for it.
#Chain pollers
Each chain has its own loop, so a failure on one chain does not stop another. After a failed poll the next poll waits for twice the normal interval, capped at 60 seconds. EVM chains use free public endpoints from dRPC, 1RPC, Nodies, BlockRazor, Arbitrum and PublicNode, tried in order. Solana uses Helius when it is configured, with PublicNode as the other endpoint. Background polling on Solana prefers the public endpoint, and the keyed endpoint has a daily credit budget.
| Chain | Poll target | Large-transfer index | Token scope | Blocks between polls (measured median) | Coverage note |
|---|---|---|---|---|---|
| Ethereum | 12 s | Yes, tokens and native ETH | USDC, USDT, WETH, WBTC, DAI | 1 | Token logs cover gaps. Native ETH reads only the head block |
| Base | 16 s | Yes, tokens only | USDC, WETH, USDbC, cbBTC, DAI | 9 | Inside the scan window |
| BNB Chain | 16 s | Yes, tokens only | USDT, USDC, WBNB, BTCB, ETH | 38.5 | Inside the scan window, with little margin |
| Arbitrum One | 16 s | Yes, tokens only | USDC, USDT, WETH, WBTC | 59 | Cursor catches up, up to 200 blocks per poll |
| OP Mainnet | 30 s | No | Lookups only | 15 | Head, fees and lookups |
| Polygon PoS | 30 s | No | Lookups only | 20 | Head, fees and lookups |
| Solana | 30 s | Sampled, plus a wallet watch list | USDC, USDT, wSOL, SOL, JUP, BONK, WIF, JTO, PYTH, RAY, JitoSOL, mSOL | 148 slots | One finalized block per poll, about 0.7% of slots |
#EVM log scan
An EVM poll asks for ERC-20 Transfer logs of the curated tokens from the last scanned block to the head. One poll reads at most 200 blocks. If the chain moved further, the next poll continues from the cursor, so no block is skipped unless the reader falls more than 2,000 blocks behind. Native ETH transfers are read from the latest block of each poll, and Farbeam checks the receipt, so a reverted call is not stored.
The scan position lives in memory. After a process restart the scan starts again at the head. Transfers that happened during the restart are not backfilled.
#Native ETH
Native ETH is read from the head block body on Ethereum only. It covers the top-level value of each transaction. It does not cover internal transfers from contracts, and it does not read receipts, so a reverted transaction with a large value can appear. When two blocks pass between polls, the block that was not the head is not read for native ETH.
#Solana sampling
Solana is too busy to read in full with this design. It has two partial readers, and every Solana event has sampled: true from either one.
- Sampled blocks. Each poll reads one finalized block. In the sample there were 148 slots between reads, or about 32 seconds.
- Wallet watch list. About every 2 minutes, the service reads recent transactions of the Solana exchange wallets in the label set, 7 addresses at this time. It reads up to 20 signatures and at most 6 transactions per wallet in each pass, on the public endpoint. A busy wallet can do more than that between passes, so this reader also misses transfers.
GET /statusreports the list and its counters underwatch_list.
For each successful transaction, the poller sums balance changes per owner and mint. The largest decrease becomes from, the largest increase becomes to, and the amount is the smaller of the two. SOL uses the same method on lamport balances. This finds large balance changes. It is not a decoded transfer list, and it misses most of Solana by design. Do not sum Solana rows and call the result a volume. See sampling.
#Valuation and timestamps
usd is the amount times the CoinGecko price at the moment of indexing. The value does not change later. On EVM log events, ts is estimated from the head block time and a configured block time, so it can be off by some seconds. Exact times come from transaction lookup.
#Chain health
GET /status reports one state per chain. These rules come directly from the poller.
| State | Rule |
|---|---|
starting | No poll has succeeded since the process started |
ok | None of the rules below apply |
degraded | 2 or more failed polls in a row, or head lag above the larger of 3 poll intervals and 90 seconds |
down | No good poll for longer than the larger of 6 poll intervals and 180 seconds |
#Store
The store is one SQLite file in WAL mode. This design is simple to run and has limits: one process, one writer, no replicas and no archive.
| Data | Kept for | Notes |
|---|---|---|
| Transfers of $100,000 or more | 7 days | Rows older than 7 days are deleted by an hourly job |
| Status samples | 30 days | One per chain per 5 minutes |
| Delivery log | 14 days | The payload is removed after a delivery succeeds or finally fails |
| Recent blocks | Up to 25 per chain | In memory, lost on restart |
| Rate-limit counters | One minute | In memory, IP addresses are hashed |
| Last good lookup copies | Refreshed on each success, removed after 7 days | Used only when every source fails, marked stale: true |
| Accounts, API key hashes, sessions | Sessions 7 days, accounts until removed | See Security |
The transfer uid is unique, so a repeated poll cannot store the same event twice. See indexing for the row format.
#API
The Data API has about 40 documented endpoints. It costs nothing to read, and reading needs no sign-up. Limits use fixed one-minute windows, plus a daily limit per key. See rate limits.
Lookups go through one upstream client with timeouts, an in-memory cache and single-flight, so equal requests share one outbound call. The cache times are short enough that you should expect different numbers between calls.
| Data | Source | Cache |
|---|---|---|
| Prices | CoinGecko | 60 s |
| Wallet balances | Public RPC, Helius DAS on Solana when it is configured | 30 s |
| Wallet activity | Public RPC eth_getLogs | 60 s |
| Token market data | DexScreener | 60 s |
| Token security fields | GoPlus | 5 min |
| Solana mint, supply, largest accounts | Solana RPC | 5 min |
| RugCheck score | RugCheck | 5 min |
| Token symbol, name, decimals | Direct eth_call | 24 h |
| Chain TVL, stablecoin supply | DefiLlama | 10 min |
| DEX volume | DefiLlama | 15 min |
| Trending pools | GeckoTerminal | 5 min |
When a source fails, the service does not fill the gap with a guess. A token check reads unknown, and a wallet chain reads ok: false. If every source fails for a wallet, token report, stablecoin or DEX call, the API returns the last saved copy with stale: true and its as_of time. With no saved copy it returns 502 upstream_unavailable with the source name. The full list is on data sources.
#Tools
The browser tools are thin clients over the same API. They hold no extra data, so anything you see in a tool is also available as JSON.
| Tool | API call | Cost | Main limit |
|---|---|---|---|
| Wallet explorer | GET /wallets/{address} | 3 | EVM balances cover the native asset and curated tokens only |
| Token report | GET /tokens/{chain}/{address} | 3 | Reads public fields, gives no composite score |
| Transaction lookup | GET /tx/{chain}/{hash} | 2 | At most 60 decoded token transfers on EVM |
| Gas and fees | GET /gas | 1 | Execution fee data only, no L1 data fee |
| Rule tester | POST /rules/validate | 1 | Tests the last 2,000 stored transfers |
| Live transfers | GET /api/live | 0 | No replay after a disconnect |
| Playground | Any public endpoint | Varies | Uses your rate limit |
| Console | Account, key and rule endpoints | Varies | Needs sign-in with a Solana wallet. EVM wallet sign-in is Planned |
Market pages show aggregator data with the source named: stablecoins and DEX volume from DefiLlama, trending pools from GeckoTerminal.
#Alert engine
The engine subscribes to new transfer events. Each enabled rule is a compiled Beamline expression, and it runs once per new event. After a rule fires, it waits for its cooldown, 300 seconds by default, and matches in that time are dropped. A match writes a delivery row to SQLite. A worker runs every 3 seconds and sends up to 20 due deliveries per pass, so pending deliveries survive a restart.
A rule that names liquidity_usd or change_pct watches liquidity samples instead of transfers. While such a rule exists, the engine samples DexScreener liquidity of curated tokens every 5 minutes, skipping stablecoins and wrapped native assets.
The engine sees only what the index stores. A rule cannot match a transfer below $100,000, or a token outside the curated list. See Alerts for the delivery guarantees.
#Accounts
Reading data needs no account. An API key, a rule and the console need sign-in with a Solana wallet. The wallet signs a text message, which sends no transaction and costs nothing. The server then sets a session cookie for 7 days. See Security for how sessions and key hashes are stored.
#Status
Status shows measured state from this service: chain head, lag, RPC latency and the result of each outbound source. The service does not publish an uptime percentage. It stores samples and shows them.
#Not built yet
These items do not exist today. The list is here so you do not plan around them.
| Item | State |
|---|---|
| Email delivery | Planned |
| EVM wallet sign-in | Planned |
| Wallet clustering and an attribution graph | Planned |
| Flow graphs | Planned |
| Paid plans, billing, SLA | Planned |
| Team accounts and SSO | Planned |
| Official SDK packages | Planned |
| History beyond 7 days and data exports | Planned |
| GraphQL and WebSockets | Planned |
| Testnets and NFT data | Planned |
The roadmap gives more detail. Items on it have no dates.