Skip to main content
glnc

COMMAND

Webhook alerts on wallet conditions

glnc alert watches a wallet and POSTs a structured envelope to a webhook URL when a condition crosses its edge. The condition language is a small expression DSL over balance.<chain> and balance.<symbol> values. Every fire is SSRF-validated before the network call leaves your process.

Synopsis

glnc alert <address> --on <condition> --webhook <url> [--interval N] [--once] [--dry-run]
glnc alert vitalik.eth \
--on "balance.eth < 300" \
--webhook https://hooks.slack.com/services/XXX \
--interval 60

Conditions

Conditions are expressions over balance values. balance.eth resolves to the native ETH balance in whole units; balance.usdc resolves to USDC balance in whole units. Comparison operators (<, <=,>, >=, ==, !=) and boolean combinators (and, or, not) are supported.

glnc alert 0x... --on "balance.eth < 300 and balance.usdc > 10000" --webhook ...
parsed condition: AND(LT(balance.eth, 300), GT(balance.usdc, 10000))
watching every 120s

Alerts are edge-triggered. State persists in ~/.glnc/alerts.json, so a condition that is already true when the alert starts does not fire until it goes false then true again.

Webhook security

glnc alert POSTs to a URL you supply. To prevent the CLI from being weaponised as an SSRF tool against the operator's own infrastructure (cloud-VM IMDS, internal admin panels), each webhook URL is validated before every fire:

Webhook validation rules.
FlagDescription
Scheme allowlisthttp: and https: only. No file:, gopher:, data:.
IPv4 blocks0/8, 10/8, 127/8, 169.254/16 (IMDS), 172.16/12, 192.168/16, 100.64/10 (CGNAT), 224/4 (multicast), TEST-NET, 198.18/15.
IPv6 blocks::, ::1, fc00::/7, fe80::/10, ff00::/8. IPv4-mapped, IPv4-compatible, 6to4, NAT64 all rejected when the embedded IPv4 is blocked.
DNS resolutionHostnames are resolved before each fire; any A or AAAA record in a blocked range aborts the fire.
RedirectsUnderlying fetch uses redirect: error. Any 30x aborts the fire.
No retries on validation failureA blocked URL is not retried; the alert envelope still records the rejection.

There is a documented residual TOCTOU window between DNS resolution and the underlying connect (DNS rebinding). For a CLI alert tool with a 10-second per-attempt timeout and an operator-supplied URL, this is an accepted trade-off.

Modes

--once evaluates the condition exactly once and exits. --dry-run evaluates and prints what would be sent without firing the webhook. Combine them to preview a payload before deploying.

glnc alert 0x... --on "balance.eth < 300" --webhook https://... --dry-run
evaluating once...
condition: balance.eth(229.58) < 300 → true
would POST: { "schema": "glnc.alert/v1", ... }
--dry-run: webhook NOT fired

Flags

Flags accepted by glnc alert.
FlagDescription
--on <expr>Condition expression. Required.
--webhook <url>http:// or https:// webhook URL. Required.
--interval <N>Poll interval in seconds. Default 120. Minimum 30.
--onceEvaluate the condition once and exit.
--dry-runEvaluate without firing the webhook.
--jsonEmit NDJSON envelopes for each evaluation plus a final stop event.