Skip to main content
A delegate renews users’ VTXOs before batch expiry without holding their keys. Fulmine, Ark Labs’ wallet daemon, can run as a headless delegate.

What you’re running

Fulmine is a wallet daemon that doubles as delegate infrastructure: clients hand it presigned, tamper-proof settlement intents and it submits them in a batch swap before their VTXOs expire — fully self-custodial (see Settlement Intent Delegation for the model). The delegate service signs batch transactions with the wallet’s key, so a wallet must be created and unlocked before the Delegate API becomes ready. You do this once; after that, FULMINE_UNLOCKER_* auto-unlock keeps the delegate live across restarts. Fulmine has no flag to hide the Web UI; just ignore it. Fulmine listens on three ports:

Prerequisites

  • Docker — the quickest way to run Fulmine.
  • jq — used below to pipe the generated key straight into the next call.
  • The mainnet Arkade Service URL: https://arkade.computer.
Fulmine’s REST and gRPC interfaces are not authenticated. Do not expose them to the public internet — keep the daemon on a private network or behind a reverse proxy with its own access control.

Quickstart with Docker

1

Start Fulmine with delegation enabled

Set the password once as a shell variable — the rest of the quickstart reuses it, so there is nothing to retype. Use a strong value: at least 8 characters with a number and a special character.
This publishes the HTTP port (7001, for status lookups and the Web UI) and the delegate port (7002, the Delegate API). The gRPC port (7000) is intentionally left unpublished — it isn’t needed for a delegate-only deployment.
Telemetry is on unless you turn it off, so FULMINE_DISABLE_TELEMETRY=true is set explicitly here.
2

Create the wallet (one-time only)

Generate a mnemonic, create the wallet, then unlock it. The mnemonic never leaves your shell, so there is nothing to copy by hand. Auto-unlock handles every subsequent restart.
Both create and unlock return {} on success.
Back up $MNEMONIC before you go on — those 12 words are your wallet seed, and losing them means losing the delegate key.
When an unlocker is configured, Fulmine creates the wallet with the unlocker’s password and ignores whatever create sends — so the two must agree, or auto-unlock will fail on the next restart. Driving both from $FULMINE_PASSWORD keeps them in sync.
3

Verify the delegate is live

The Delegate API is served on port 7002 at /v1/... (no /api prefix):
A response with a pubkey means the delegate is ready for clients. Before the wallet is created and unlocked, this endpoint fails with service not ready instead.
delegateAddress is the delegate’s own offchain address, where clients pay your service fee. It is always present — including while FULMINE_DELEGATE_FEE is 0 — and is stable across restarts, which matters because clients build their intent proofs against it. The response repeats it under a deprecated delegatorAddress alias; prefer delegateAddress.

Essential environment variables

Fulmine is configured entirely through FULMINE_-prefixed environment variables — there are no CLI flags. These are the ones that matter for a headless delegate:
The env unlocker keeps the quickstart short, but the password is then visible to anyone who can run docker inspect on the container. In production prefer the file unlocker, which reads the password from a mounted file you can lock down with filesystem permissions. See the Fulmine repo for the full configuration.

How a wallet uses your delegate

Once your server is up, a client wallet uses it in three steps:
  1. Discover — the wallet calls GET /v1/delegate/info (port 7002) to read your delegate pubkey, fee, and address, then builds a delegated address with an operator + user + delegate spend path.
  2. Delegate — the wallet submits a presigned intent and forfeit transactions to POST /v1/delegate (port 7002). The intent is bound by a time window and signed with BIP322, so your server cannot alter or redirect the funds — only submit what was authorized.
  3. Renew — your server watches those VTXOs and submits the intent in a batch swap just before expiry. Status can be tracked via GET /api/v1/delegates on the HTTP port (7001), which accepts status (pending, completed, failed), limit, and offset query parameters.
The info endpoint is also exposed at /v1/delegator/info as a legacy alias, but /v1/delegate/info is preferred. For a complete client-side example of building the intent and forfeit transactions, see the TS-SDK delegate.js example.

Next Steps

VTXO Management

Automatic renewal and recovery from the client side

Settlement Intent Delegation

The delegation workflow and security model in depth

Fulmine Reference

The wallet daemon powering your delegate

Fulmine on GitHub

Source, releases, and full configuration