Farbeam
Docs / Alerts and webhooks

Beamline fields

A rule reads the fields of one event. There are 17: 15 for transfer rows and 2 for liquidity samples. The list is also returned as data.fields from Validate a rule. Field names ignore case.

#All fields

FieldTypeValuesNull case
chaintextethereum, base, bnb, arbitrum, solanaNever
tokentextCurated symbol, or ETH, or SOLNever
token_addresstextContract or mint addressnull on native rows
kindtexttoken or nativeNever
fromtextSender addressNever
totextRecipient addressNever
from_labeltextName from the label setnull when not labeled
to_labeltextName from the label setnull when not labeled
from_typetextLabel typenull when not labeled
to_typetextLabel typenull when not labeled
txtextTransaction hash or signatureNever
usdnumberValue at index time, at least 100,000Never
amountnumberToken units after decimalsNever
blocknumberBlock number or slotNever
sampledbooleantrue on Solana rowsNever
liquidity_usdnumberLiquidity sample in USDLiquidity rules only
change_pctnumberLiquidity change in percent over the sample windowLiquidity rules only

A null text field compares as the empty string. to_type != "exchange" is true on a row with no label.

#Liquidity rules

A rule that names liquidity_usd or change_pct, or holds the text "liquidity", is a liquidity rule. It runs on liquidity samples and never on transfers. Every other rule runs on transfers and never on samples.

FactValue
TokensCurated tokens, except stablecoins and wrapped native assets: symbols that begin with USD, DAI, FDUSD, wSOL, WETH, WBNB or WMATIC
ChainsAll seven, for the tokens that remain
Sample intervalAbout 5 minutes, and only while an enabled liquidity rule exists
Change windowUp to 12 samples, so about one hour. window_minutes in the event gives the real span.
SourceToken report market logic on DexScreener pools, with outlier pools left out
Other fields on the eventchain, token, token_address, and kind set to liquidity
Payload typeliquidity.matched

The samples are held in memory, so a restart empties the window. The first sample after a restart can fire nothing. change_pct then measures a shorter span. Validate a rule tests stored transfers only, so a liquidity rule shows matched: 0 there. That result says nothing about the rule.

Numbers can be negative, so change_pct <= -30 is valid.

#Notes by field

#chain

Rows exist only for ethereum, base, bnb, arbitrum and solana. A rule naming optimism or polygon is valid and never matches, because those chains have no index. See chain coverage.

#token

The symbol. Symbols repeat across chains. token == "USDC" matches on all chains. Use token_address or add chain to narrow it.

ChainTokens in rows
ethereumUSDC, USDT, WETH, WBTC, DAI, ETH
baseUSDC, WETH, USDbC, cbBTC, DAI
bnbUSDT, USDC, WBNB, BTCB, ETH
arbitrumUSDC, USDT, WETH, WBTC
solanaUSDC, USDT, wSOL, JUP, BONK, WIF, JTO, PYTH, RAY, JitoSOL, mSOL, SOL

ETH means two things. With kind == "native" it is native ETH on Ethereum. With chain == "bnb" it is a bridged token.

#token_address

Case does not matter. On native rows, it reads as an empty string, so token_address == "" selects them. Use kind == "native" for clarity.

#kind

native covers ETH on Ethereum and SOL on Solana. Everything else is token.

#from, to

EVM addresses are stored in lowercase, and comparison ignores case, so you can paste a checksummed address. startswith works for vanity prefixes.

On Solana, these fields come from balance changes. They hold the owners with the largest decrease and largest increase in that transaction. See the data model.

#from_label, to_label

Names can be corrected in later releases, so a rule on an exact name can stop matching. For stable logic, use from_type and to_type, or match the address. contains is useful for groups of wallets:

Beamline
to_label contains "binance"

#from_type, to_type

Values: exchange, dex, bridge, lending, staking, token, issuer, launchpad, infrastructure. The list is small and hand-curated, so to_type == "exchange" finds only the exchange wallets it knows. See labels.

The Null address label has type infrastructure. Match mints and burns on the label:

Beamline
from_label == "Null address"

#usd

Set at index time from a CoinGecko price. Stored rows are at or above $100,000, so a lower bound below that has no effect, and an upper bound below that matches nothing. Use suffixes: usd >= 2.5m.

#amount

Token units after decimals, as a double. It is useful for assets with a volatile price, where you care about units:

Beamline
token == "WETH" and amount >= 1000

#block

Rarely useful in a live rule, because block numbers differ by chain. It works in POST /rules/validate to look at a range of stored rows.

#sampled

true on Solana rows only. Read sampling. Add not sampled to keep Solana out of an alert.

#tx

The full hash. It matches at most a few rows, so it is useful only for testing against stored rows.

#Fields that are not available

You might expectWhy it is absentWhat to do
ts, time of dayRules read a single row with no time logicFilter in your receiver with data.ts
Price, price changeRows hold a USD value, not a priceCall Asset prices in your receiver
Wallet balanceNot on the rowCall Wallet overview in your receiver
Token report statusNot on the rowCall Token report in your receiver
Sums and counts over timeRules have no stateKeep state in your receiver

These are the limits of the language today. Your receiver can add any of these, using the same public API.

#Check a field

Send a rule to the validate endpoint and read sample to see real rows with all fields.

curl -s -X POST "https://farbeamlabs.com/api/v1/rules/validate" \
  -H "content-type: application/json" \
  -d '{"expression":"to_type == \"exchange\" and usd >= 500k"}'
const res = await fetch("https://farbeamlabs.com/api/v1/rules/validate", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({ expression: 'to_type == "exchange" and usd >= 500k' }),
});
const { data } = await res.json();
console.log(data.tested, data.matched, data.sample[0], data.fields);
import requests

res = requests.post(
    "https://farbeamlabs.com/api/v1/rules/validate",
    json={"expression": 'to_type == "exchange" and usd >= 500k'},
    timeout=30,
)
data = res.json()["data"]
print(data["tested"], data["matched"], data["fields"])