About
fbd is a Fistbump full node written in Swift, built by eskimo.
Read the whitepaper, browse the block explorer, or view the source code.
Download
Download pre-built releases for the node, wallet, and other software from fistbump.org.
Build from source
$git clone https://github.com/fistbump-org/fbd.git
$cd fbdmacOS
$./install/macos.shLinux
$./install/linux.shWindows
$powershell -ExecutionPolicy Bypass -File install\windows.ps1macOS, Linux, Windows. Each script installs dependencies, builds, and installs fbd and fbdctl.
Configuration
$fbd --network main --host 0.0.0.0 --log-level debug --index-tx| Flag | Description | Default |
|---|---|---|
--network, -n | main, testnet, regtest, simnet | main |
--datadir, -d | Data directory | ~/.fbd (macOS/Linux), %LOCALAPPDATA%\fbd (Windows) |
--host | P2P listen address | 127.0.0.1 |
--port, -p | P2P port | network default |
--max-outbound | Max outbound peers | 8 |
--max-inbound | Max inbound peers | 64 |
--seeds | Additional seed peers | |
--nodes | Connect only to these peers | |
--agent | User agent suffix | |
--rpc-host | RPC listen address | 127.0.0.1 |
--rpc-port | RPC port | network default |
--api-key | RPC API key | auto-generated |
--no-auth | Disable RPC auth | false |
--ns-host | DNS listen address | 127.0.0.1 |
--ns-port | DNS port | network default |
--miner-address | Coinbase payout address | |
--miner-threads | CPU miner threads (0 = auto, max = cores - 1) | 0 |
--log-level | trace, debug, info, warning, error | info |
--index-tx | Transaction index for historical lookups | false |
--index-address | Address index for lookups by address | false |
--index-auctions | Auction index for bid history | false |
Config file
<datadir>/fbd.conf — CLI flags override config values.
network = main
host = 0.0.0.0
nodes = 1.2.3.4:32867, 5.6.7.8:32867
log-level = debug
index-tx = trueNetworks
| Network | P2P | Brontide | RPC | DNS | HRP |
|---|---|---|---|---|---|
| main | 32867 | 32868 | 32869 | 32870 | fb |
| testnet | 42867 | 42868 | 42869 | 42870 | ft |
| regtest | 52867 | 52868 | 52869 | 52870 | fr |
| simnet | 62867 | 62868 | 62869 | 62870 | fs |
RPC
fbdctl
$fbdctl getblockcount{
"result": 318614,
"error": null
}curl
$curl -s http://127.0.0.1:32869/ \
-X POST \
-u "x:YOUR_API_KEY" \
-d '{"method":"getblockcount","params":[],"id":1}'{
"result": 318614,
"error": null,
"id": 1
}curl returns standard JSON-RPC with an extra id field.
Examples below show the result value only.
Auth
A random key is generated on startup at <datadir>/.cookie. fbdctl reads it automatically.
--api-key mykey— set a fixed key on bothfbdandfbdctl--no-auth— disable auth entirely
HTTP Basic auth: username x, password is the key.
Wallets
Wallet commands require --wallet <name>. Auto-selected if only one wallet exists.
$fbdctl --wallet main getbalanceMethods tagged wallet required need this flag.
Subdomains
Fistbump supports on-chain subdomains — names like example.fistbump that are registered and resolved entirely on the blockchain. Subdomains go through the same auction process as top-level names.
Enabling subdomains
A name owner must explicitly opt in by setting the auctionSubdomains flag via sendupdate:
$fbdctl sendupdate fistbump '{"records":[]}' --flags 1Once enabled, this flag is permanent — it cannot be revoked and persists through name expiration and re-registration.
auctionSubdomains. You must remove all delegation and SUB records before enabling subdomain auctions, and you cannot add them after enabling.
Registering a subdomain
Once the parent has auctionSubdomains enabled, anyone can open an auction for a subdomain:
$fbdctl sendopen example.fistbumpThe node automatically detects the parent name, verifies that subdomains are allowed, and includes the parentHash (SHA3-256 of the parent name) in the covenant. Bidding and registration follow the same auction flow as top-level names.
Payment splitting
When a subdomain is registered, the winning bid is split:
- 50% — burned (same as top-level names)
- 25% — paid to ancestor name owners (split equally up the chain)
- 25% — dev fund
Name rules
- Each label: 1–63 bytes, lowercase ASCII, hyphens allowed (not leading/trailing)
- Total name: 1–253 bytes (including dots)
- Punycode labels (e.g.
xn--5p9h) are valid - Subdomains can themselves enable
auctionSubdomainsfor deeper nesting
Inline subdomain records (SUB)
As an alternative to subdomain auctions, name owners can define subdomains directly in their resource data using SUB records. A SUB record contains a single label and a set of nested records:
$fbdctl sendupdate fistbump '{"records":[{"type":"SUB","name":"www","records":[{"type":"A","address":"1.2.3.4"}]}]}'This creates a www.fistbump subdomain that resolves to 1.2.3.4, without any auction. The owner retains full control and can update or remove SUB records at any time. SUB records and auctionSubdomains are mutually exclusive — you cannot use inline subdomains and subdomain auctions on the same name.
DNS resolution
The built-in DNS server resolves subdomains using progressive lookup: it first tries the full name (example.fistbump), then strips the leftmost label to check the parent. If the parent has a matching SUB record, those nested records are returned. If the subdomain exists as its own on-chain name with resource records, those are returned directly. If neither exists, the parent's NS records are returned as a referral.
DANE / TLSA
TLSA records are stored on-chain with port and protocol fields. The DNS server synthesizes standard DANE owner names:
$dig @127.0.0.1 -p 32870 TLSA _443._tcp.fistbumpThis works for both top-level names and subdomains.
Querying subdomain info
$fbdctl getnameinfo example.fistbump{
"name": "example.fistbump",
"parentHash": "b9c3...",
"flags": 0,
"auctionSubdomains": false,
...
}Records
Resource data passed to sendupdate, sendregister, and sendmany is a JSON object with a records array. Each record has a type field and type-specific fields.
$fbdctl --wallet main sendupdate myname '{"records":[...]}'A
IPv4 address.
{"type": "A", "address": "1.2.3.4"}AAAA
IPv6 address.
{"type": "AAAA", "address": "2001:db8::1"}CNAME
Canonical name (alias).
{"type": "CNAME", "target": "alias.example.com."}NS
Nameserver delegation (without glue).
{"type": "NS", "ns": "ns1.example.com."}GLUE4
Nameserver with an IPv4 glue address.
{"type": "GLUE4", "ns": "ns1.example.com.", "address": "1.2.3.4"}GLUE6
Nameserver with an IPv6 glue address.
{"type": "GLUE6", "ns": "ns1.example.com.", "address": "2001:db8::1"}SYNTH4
Synthetic nameserver from an IPv4 address. The NS name is generated automatically at serve time.
{"type": "SYNTH4", "address": "1.2.3.4"}SYNTH6
Synthetic nameserver from an IPv6 address. The NS name is generated automatically at serve time.
{"type": "SYNTH6", "address": "2001:db8::1"}MX
Mail exchange. preference is the priority (lower = higher priority, 0–65535).
{"type": "MX", "preference": 10, "exchange": "mail.example.com."}TXT
Text record. txt is an array of strings (each max 255 bytes).
{"type": "TXT", "txt": ["v=spf1 include:_spf.example.com -all"]}DS
DNSSEC delegation signer. algorithm: 8 (RSA/SHA-256), 13 (ECDSA P-256), 14 (ECDSA P-384), 15 (Ed25519), 16 (Ed448). digestType: 1 (SHA-1), 2 (SHA-256), 4 (SHA-384). digest is hex-encoded.
{"type": "DS", "keyTag": 12345, "algorithm": 13,
"digestType": 2, "digest": "a1b2c3..."}TLSA
DANE certificate association. protocol: 6 (TCP), 17 (UDP), 132 (SCTP). usage: 0 (PKIX-TA), 1 (PKIX-EE), 2 (DANE-TA), 3 (DANE-EE). selector: 0 (full cert), 1 (SubjectPublicKeyInfo). matchingType: 0 (exact), 1 (SHA-256), 2 (SHA-512). certificate is hex-encoded.
{"type": "TLSA", "port": 443, "protocol": 6,
"usage": 3, "selector": 1, "matchingType": 1,
"certificate": "30820122..."}The DNS server synthesizes the standard DANE owner name (_443._tcp.myname) at serve time from the port and protocol fields.
CAA
Certification authority authorization. flags: 0 or 128. tag: issue, issuewild, or iodef.
{"type": "CAA", "flags": 0, "tag": "issue", "value": "letsencrypt.org"}WALLET
Fistbump payment address. Associates a receive address with the name for on-chain payments.
{"type": "WALLET", "address": "fb1q..."}SUB
Inline subdomain records. name is a single label (1–63 bytes). records is a nested array of records. See Subdomains for details.
{"type": "SUB", "name": "www",
"records": [{"type": "A", "address": "1.2.3.4"}]}Example
A complete sendupdate setting an A record, mail exchange, TXT for SPF, and a TLSA record:
$fbdctl --wallet main sendupdate myname '{
"records": [
{"type": "A", "address": "1.2.3.4"},
{"type": "MX", "preference": 10, "exchange": "mail.example.com."},
{"type": "TXT", "txt": ["v=spf1 include:_spf.example.com -all"]},
{"type": "TLSA", "port": 443, "protocol": 6, "usage": 3,
"selector": 1, "matchingType": 1, "certificate": "30820122..."}
]
}'The same records can be set in a batch with sendmany:
$fbdctl --wallet main sendmany update myname '{"records":[{"type":"A","address":"1.2.3.4"}]}'ns, target, exchange) use DNS format: labels 1–63 bytes, alphanumeric plus hyphens, no leading or trailing hyphens. Trailing dot is optional. Names with auctionSubdomains enabled cannot use delegation records (NS, DS, GLUE4, GLUE6, SYNTH4, SYNTH6).
Browser Extension
The Fistbump browser extension exposes a window.fistbump API to web pages, letting dApps connect to the user's wallet, send transactions, and sign messages. It communicates with the Fistbump desktop wallet via Chrome native messaging — no HTTP, no localhost ports.
Available for Chrome, Chromium, Brave, Edge, Arc, Vivaldi, and Firefox. Requires the Fistbump desktop wallet to be installed.
Install
Load the extension in developer mode:
Chrome / Chromium-based browsers
- Open
chrome://extensions - Toggle Developer mode on (top-right)
- Click Load unpacked and select the extension directory
Firefox
- Open
about:debugging#/runtime/this-firefox - Click Load Temporary Add-on
- Select
manifest.jsonfrom the extension directory
The Fistbump icon appears in the toolbar. Clicking it opens a popup showing the extension version and a live indicator for whether the wallet is running.
API
All methods are available on window.fistbump and return promises. You can detect the extension with window.fistbump.isFistbump.
connect
Request wallet access and get the user's address. The first call from a new origin shows a confirmation modal in the wallet. Subsequent calls from the same origin skip the prompt.
// connect to the wallet
const result = await window.fistbump.connect();
// → { address: "fb1...", origin: "https://example.com" }isConnected
Check whether the current origin is already approved, without prompting the user.
const connected = await window.fistbump.isConnected();
// → true or falsesendTx
Build, sign, and broadcast a transaction. The to field accepts a raw fb1… address or a Fistbump name — the wallet resolves names automatically. A review modal shows the recipient, fee, and total before signing.
// send by name
const tx = await window.fistbump.sendTx({ to: 'eskimo', amount: 1.5 });
// → { txid: "a1b2c3..." }
// send by address
const tx = await window.fistbump.sendTx({ to: 'fb1q...', amount: 0.25 });
// → { txid: "d4e5f6..." }signMessage
Sign an arbitrary message. Without a name option, signs with the wallet's receive address. With name, signs with the key that owns that Fistbump name — the wallet verifies ownership before showing the review modal.
// sign with wallet address
const sig = await window.fistbump.signMessage('hello');
// → { signature: "...", address: "fb1..." }
// sign as a Fistbump name
const sig = await window.fistbump.signMessage('hello', { name: 'eskimo' });
// → { signature: "...", name: "eskimo" }How it works
The extension uses a four-layer message flow to reach the desktop wallet:
| Layer | Component | Transport |
|---|---|---|
| 1 | dApp calls window.fistbump | postMessage |
| 2 | Content script relays to service worker | chrome.runtime.sendMessage |
| 3 | Service worker connects to native host | chrome.runtime.connectNative |
| 4 | Bridge forwards to wallet over local socket | Unix socket / named pipe |
If the wallet isn't running, the bridge launches it automatically and waits for the socket to come up before forwarding the request.
Security
- The extension's only permission is
nativeMessaging— it cannot read page data or make network requests - The wallet has no HTTP listener — there is no localhost surface for other processes to reach
- The local socket (
~/.fistbump/extension.sock) is created with mode0600— only the current user can connect - Chrome verifies the extension's stable ID before spawning the native host — other extensions cannot impersonate it
sendTxandsignMessagealways show a review modal, even for previously approved origins- Name signing verifies wallet ownership via
getnameinfo+validateaddressbefore prompting - Approved origins are stored in
~/.fistbump/settings.jsonand can be revoked via the wallet