Omahub
← All plugins
I

Bitfinex Bitcoin Ticker

by ismyhc

Live Bitcoin price in the bar, streamed from Bitfinex, with a 24h sparkline panel

Security review

No obvious issues detected

Deterministic scan — not a security guarantee

None
Risk level
None
Analyzed commit
f912280
Scanned
1 month ago

No potentially dangerous behavior detected in the analyzed commit.

Automated analysis only — not a security guarantee.

AI advisory review

No obvious issues detected

Language-model assessment · ~deepseek/deepseek-v4-flash-latest — advisory only

Low
AI risk level
Low
Recommendation
install
Model
~deepseek/deepseek-v4-flash-latest
Analyzed commit
f912280
Reviewed
1 month ago

This is a straightforward Bitcoin ticker widget that fetches public data from Bitfinex via REST and optional WebSocket. The code is transparent, well-documented, and performs no dangerous operations beyond network requests to the expected endpoints. No obfuscation, credential handling, or system modifications are present.

  • Network access to Bitfinex endpoints is required, but this is clearly documented and limited to public unauthenticated APIs.
  • The optional WebSocket module (qt6-websockets) is only used if installed; the fallback polling works without it.
How this check works

This review combines the deterministic scan (the rule-based results above) with an independent look at the plugin's code by a language model. The model reads a trimmed sample of the repository's files, the manifest, and the README, then gives a plain-language risk level and a recommendation: install (no notable danger), review (look closer first), or avoid (clearly dangerous).

It runs on the same analyzed commit as the deterministic scan and is strictly advisory — it is not a security guarantee and never blocks a plugin by itself. A human moderator still reviews plugins before they are listed.

AI advisory only — automated analysis, not a security guarantee.

Install
$ omarchy plugin add https://github.com/ismyhc/omarchy-bitfinex-ticker --enable
Widgets #bar #system

Bitfinex Bitcoin Ticker

A live Bitcoin price in the Omarchy bar, streamed over a WebSocket from the public Bitfinex v2 API — no polling, no API key, no account.

The bar pill and the detail panel

The pill is the price alone, in the theme foreground, so it reads as part of the bar rather than as a coloured badge. Clicking it opens a panel with the 24h change, a sparkline, and the rest of the ticker.

Defaults to Bitcoin, and quotes it in your locale's currency.

Requirements

Omarchy with the Quickshell-based omarchy-shell. Nothing else — no extra packages, no API key, no account.

Install

omarchy plugin add https://github.com/ismyhc/omarchy-bitfinex-ticker.git
omarchy plugin enable io.github.ismyhc.bitfinex-ticker

Plugins land disabled so you can read the code before it runs; enable puts the widget in the bar. To move it:

omarchy bar move io.github.ismyhc.bitfinex-ticker --section right

That is the whole install. The price should appear within a second or two.

Optional: live streaming

Out of the box the price is polled from Bitfinex's REST ticker every 10 seconds. Install Qt's WebSocket QML module and the widget switches itself to the live websocket stream instead, updating as trades happen:

omarchy pkg add qt6-websockets
omarchy restart shell

Nothing else changes, and nothing needs configuring — the widget detects the module at load. It is 441 KiB from Arch's extra repo and depends on nothing Omarchy does not already have. The panel's header says which source is in use (Bitfinex · live or Bitfinex · 10s poll), and polling resumes on its own whenever the stream drops, so a reconnect or a suspend never leaves the price frozen.

Remove

omarchy plugin remove io.github.ismyhc.bitfinex-ticker

That deletes ~/.config/omarchy/plugins/io.github.ismyhc.bitfinex-ticker/ and drops the widget from your bar layout. Nothing else is touched: the plugin writes only its own entry in ~/.config/omarchy/shell.json, keeps no state elsewhere on disk, and installs no services, timers, or system packages. If you installed qt6-websockets for this, it stays — remove it with omarchy pkg drop qt6-websockets if nothing else needs it.

Currency

currency defaults to auto, which reads your desktop locale: an en_US session streams tBTCUSD and shows $68,292, a de_DE one streams tBTCEUR and shows 58.659 €. Grouping, decimal separator, and symbol placement all follow the locale.

Bitfinex only quotes BTC against USD, EUR, GBP and JPY. A locale on any other currency falls back to USD rather than subscribing to a pair that does not exist. Set currency explicitly to override, or symbol to name a Bitfinex pair directly.

Other assets

base takes any asset Bitfinex lists, so "base": "ETH" gives you tETHUSD. Change icon to match — the default ₿ is Bitcoin's. For a pair the base/currency mapping does not cover, set symbol to the exact Bitfinex pair (e.g. "symbol": "tSOL:USD"), which overrides both.

allowMultiple is on, so several entries with different assets can sit in the bar at once.

Interactions

Gesture Action
left click open the detail panel
right click bring the 24h change into the bar beside the price, tinted by direction (persisted)
middle click force a reconnect and refetch the history

The panel

  • the price at display size, with the 24h move in percent and absolute terms
  • a 24h sparkline — 96 fifteen-minute closes over REST, right edge tracking the live ticker — with the day's open drawn as a dotted reference
  • bid, ask, 24h high/low, spread, and volume

History is fetched when the panel opens and refreshed once a minute while it stays open; the ticker websocket channel carries no history of its own.

Settings

Set inline on the widget's entry in ~/.config/omarchy/shell.json:

{
  "id": "io.github.ismyhc.bitfinex-ticker",
  "currency": "auto",
  "compact": false
}
Key Default Meaning
currency auto auto (locale), or USD / EUR / GBP / JPY
base BTC base asset, e.g. ETH
symbol — explicit Bitfinex pair; overrides currency and base
icon ₿ glyph before the price (nerd font)
decimals -1 price decimals; -1 picks by magnitude
showChange false also show the 24h change in the bar
showCurrency true show the currency symbol
compact false 68.3k instead of 68,292
pollSeconds 10 seconds between REST reads while not streaming (min 5)
upColor #2ea043 tint for a positive 24h change
downColor theme urgent tint for a negative 24h change

Themes carry no green role, so the up colour is a plain default; the down colour rides the theme's urgent (its red). Both accept any QML colour string.

Vertical bars always use the compact form — a grouped six-figure price does not fit 28px.

IPC

omarchy-shell io.github.ismyhc.bitfinex-ticker price          # last price on stdout
omarchy-shell io.github.ismyhc.bitfinex-ticker toggle         # open/close the panel
omarchy-shell io.github.ismyhc.bitfinex-ticker refresh        # reconnect + refetch history
omarchy-shell io.github.ismyhc.bitfinex-ticker toggleChange   # show/hide the 24h change

Network access

The plugin talks to two Bitfinex endpoints and nothing else:

Endpoint When
https://api-pub.bitfinex.com/v2/ticker/<pair> every pollSeconds while not streaming
wss://api-pub.bitfinex.com/ws/2 continuously, when qt6-websockets is installed
https://api-pub.bitfinex.com/v2/candles/... on panel open, then once a minute while it is open

All three are public and unauthenticated. Nothing is sent but the pair being watched, no credentials are stored or read, and no other host is contacted.

Files

File Role
manifest.json plugin declaration, defaults, settings schema
BarWidget.qml the pill: currency resolution, formatting, gestures, IPC
Panel.qml detail popup
Sparkline.qml the 24h canvas
Feed.qml ticker state, REST polling, and the candle history
Stream.qml the optional WebSocket
Format.js locale-aware number, currency, and pair formatting

Stream.qml is deliberately separate: it is the only file that imports QtWebSockets, so a missing qt6-websockets fails one Loader instead of the widget's own import. Feed.qml imports nothing but QtQuick — the fallback cannot depend on the thing it is a fallback for.

Both sources produce the same value. /v2/ticker returns the identical 10-field array the stream pushes, so one applyTicker handles both and the widget never has to know where a price came from.

Notes for anyone hacking on this

  • manifest.json defaults win. barWidget.defaults are merged into the widget's settings before it sees them, so those values — not the QML fallbacks in BarWidget.qml — are what an entry without the key resolves to. Keep the two in step.
  • Candle order. /v2/candles/...?limit=96 returns the newest 96, newest-first. Adding sort=1 does not sort that window ascending — it makes limit select the oldest 96 candles Bitfinex holds, which for tBTCUSD is March 2013 at $93. Fetch newest-first and reverse client-side.
  • The fallback is not just for missing packages. Polling runs whenever the stream is not carrying the price — including the first connect and every reconnect gap — so the two paths are exercised together on every machine, not only on ones without the module.
  • Half-dead sockets. Bitfinex sends [CHAN_ID, "hb"] roughly every 15s when the book is quiet. Wi-Fi handoff and resume-from-suspend can kill the connection without a close frame, so a 45s silence forces a reconnect; otherwise the price silently freezes. Reconnects back off 1s → 30s.
  • baseline is taken. It is a final property on Item, so a custom one will not bind — Sparkline.qml calls its day-open line reference.
  • Developing against a symlink. Symlinking a working copy into ~/.config/omarchy/plugins/ works for discovery, but inotifywait -r does not follow it, so edits will not hot-reload — run omarchy-shell shell rescanPlugins, or omarchy restart shell for changes the reload does not pick up. Point omarchy plugin validate at the real directory; it rejects symlinks.

Licence

MIT — see LICENSE.

Not affiliated with Bitfinex. Market data is provided as-is by their public API; do not trade off a status bar.