Fulmine is a Bitcoin wallet daemon built on Arkade. It can be used as a general-purpose Arkade wallet or as an infrastructure node for Arkade-native services β such as serving VHTLCs or acting as a delegate for automated VTXO refresh.
The easiest way to run fulmine is using Docker. Make sure you have Docker installed on your machine.
docker run -d \
--name fulmine \
-p 7000:7000 \
-p 7001:7001 \
-v fulmine-data:/app/data \
ghcr.io/arklabshq/fulmine:latestOnce the container is running, you can access the web UI at http://localhost:7001.
To view logs:
docker logs -f fulmineTo stop the container:
docker stop fulmineTo update to the latest version:
docker pull ghcr.io/arklabshq/fulmine:latest
docker stop fulmine && docker rm fulmine
docker run -d \
--name fulmine \
-p 7000:7000 \
-p 7001:7001 \
-v fulmine-data:/app/data \
ghcr.io/arklabshq/fulmine:latestAlternatively, you can download the latest release from the releases page for your platform. After downloading:
- Extract the binary
- Make it executable (on Linux/macOS):
chmod +x fulmine - Run the binary:
./fulmine
The following environment variables can be configured:
| Variable | Description | Default |
|---|---|---|
FULMINE_DATADIR |
Directory to store wallet data | /app/data in Docker, ~/.fulmine otherwise |
FULMINE_HTTP_PORT |
HTTP port for the web UI and REST API | 7001 |
FULMINE_GRPC_PORT |
gRPC port for service communication | 7000 |
FULMINE_ARK_SERVER |
URL of the Ark server to connect to | It pre-fills with the default Ark server |
FULMINE_ESPLORA_URL |
URL of the Esplora server to connect to | It pre-fills with the default Esplora server |
FULMINE_UNLOCKER_TYPE |
Type of unlocker to use for auto-unlock (file or env) |
Not set by default (no auto-unlock) |
FULMINE_UNLOCKER_FILE_PATH |
Path to the file containing the wallet password (when using file unlocker) |
Not set by default |
FULMINE_UNLOCKER_PASSWORD |
Password string to use for unlocking (when using env unlocker) |
Not set by default |
FULMINE_BOLTZ_URL |
URL of the custom Boltz backend to connect to for swaps | Not set by default |
FULMINE_BOLTZ_WS_URL |
URL of the custom Boltz WebSocket backend to connect to for swap events | Not set by default |
FULMINE_DISABLE_TELEMETRY |
Opt out of telemetry logs | False by default |
When using Docker, you can set these variables using the -e flag:
docker run -d \
--name fulmine \
-p 7001:7001 \
-e FULMINE_HTTP_PORT=7001 \
-e FULMINE_ARK_SERVER="https://server.example.com" \
-e FULMINE_ESPLORA_URL="https://mempool.space/api" \
-e FULMINE_UNLOCKER_TYPE="file" \
-e FULMINE_UNLOCKER_FILE_PATH="/app/password.txt" \
-v fulmine-data:/app/data \
-v /path/to/password.txt:/app/password.txt \
ghcr.io/arklabshq/fulmine:latestFulmine supports automatic wallet unlocking on startup, which is useful for unattended operation or when running as a service. Two methods are available:
-
File-based unlocker: Reads the wallet password from a file
FULMINE_UNLOCKER_TYPE=file FULMINE_UNLOCKER_FILE_PATH=/path/to/password/file -
Environment-based unlocker: Uses a password directly from an environment variable
FULMINE_UNLOCKER_TYPE=env FULMINE_UNLOCKER_PASSWORD=your_wallet_password
- For file-based unlocking, use appropriate file permissions (chmod 600)
- For environment-based unlocking, be cautious about environment variable visibility
- Consider using Docker secrets or similar tools in production environments
IMPORTANT: The REST API and gRPC interfaces are currently not protected by authentication. This is a known limitation and is being tracked in issue #98.
DO NOT expose these interfaces over the public internet until authentication is implemented. The interfaces should only be accessed from trusted networks or localhost.
While the wallet seed is encrypted using AES-256 with a password that the user set, the API endpoints themselves are not protected.
Fulmine provides three main interfaces:
- Web UI - Available at http://localhost:7001 by default
- REST API - Available at http://localhost:7001/api
- gRPC Service - Available at
localhost:7000
Before using any wallet-dependent features, you need to set up and unlock your wallet.
-
Generate Seed
curl -X GET http://localhost:7001/api/v1/wallet/genseed
-
Create Wallet
Password must:
- Be 8 chars or longer
- Have at least one number
- Have at least one special char
Private key supported formats:
- 64 chars hexadecimal
- Nostr nsec (NIP-19)
curl -X POST http://localhost:7001/api/v1/wallet/create \ -H "Content-Type: application/json" \ -d '{"privateKey": "<hex or nsec>", "password": "<strong password>", "serverUrl": "https://server.example.com"}' -
Unlock Wallet
curl -X POST http://localhost:7001/api/v1/wallet/unlock \ -H "Content-Type: application/json" \ -d '{"password": "<strong password>"}' -
Lock Wallet
curl -X POST http://localhost:7001/api/v1/wallet/lock \ -H "Content-Type: application/json" -
Get Wallet Status
curl -X GET http://localhost:7001/api/v1/wallet/status
-
Get Arkade Address
curl -X GET http://localhost:7001/api/v1/address
-
Get Onboard Address
curl -X GET http://localhost:7001/api/v1/onboard
-
Send funds offchain
curl -X POST http://localhost:7001/api/v1/send/offchain \ -H "Content-Type: application/json" \ -d '{"address": "<ark address>", "amount": <amount in sats>}' -
Send funds onchain
curl -X POST http://localhost:7001/api/v1/send/onchain \ -H "Content-Type: application/json" \ -d '{"address": "<bitcoin address>", "amount": <amount in sats>}'
Note: Wallet setup is not required to use the Notification API.
Fulmine can track off-chain addresses on behalf of external services and deliver notifications whenever funds are received or spent.
-
Subscribe to Addresses
Ask Fulmine to watch one or more off-chain addresses.
curl -X POST http://localhost:7001/api/v1/subscribe \ -H "Content-Type: application/json" \ -d '{"addresses": ["<ark address>", "<ark address>"]}' -
Unsubscribe from Addresses
Stop watching one or more addresses.
curl -X POST http://localhost:7001/api/v1/unsubscribe \ -H "Content-Type: application/json" \ -d '{"addresses": ["<ark address>"]}' -
Stream Notifications
Open a server-sent event stream to receive real-time notifications for all subscribed addresses. Each event contains the affected addresses, newly received VTXOs (
newVtxos), and spent VTXOs (spentVtxos).curl -X GET http://localhost:7001/api/v1/notifications
Note: Wallet setup is required before using the VHTLC APIs.
Virtual Hash Time-Locked Contracts (VHTLCs) are Arkade-native HTLCs that live off-chain. They enable atomic swaps and conditional payments without touching the base layer.
-
Create VHTLC
Computes a VHTLC address from:
- a preimage hash
- sender or receiver pubkeys. The missing key (depending on whether fulmine has to fund or claim the VHTLC) is added by fulmine using one of its internal wallet.
- optional locktimes, if not provided fulmine uses the following default values:
refundLocktime: 24hrs. This is the offchain (absolute) locktime the sender must wait to refund the VHTLC offchain (can be expressed in blocks only on regtest)unilateralClaimDelay: 8 mins. This is the locktime the receiver has to wait to claim the VHTLC after it's been unrolled onchainunilateralRefundDelay: 16 mins. This is the locktime sender and Boltz have to wait to refund the VHTLC collaboratively after it's been unrolled onchainunilateralRefundWithoutEeceiverDelay: 32 mins. This is the locktime the sender has to wait to refund alone the VHTLC after it's been unrolled onchain
curl -X POST http://localhost:7001/api/v1/vhtlc \ -H "Content-Type: application/json" \ -d '{ "preimageHash": "<hex preimage hash>", "senderPubkey": "<hex sender pubkey>", "receiverPubkey": "<hex receiver pubkey>", "refundLocktime": 1024, "unilateralClaimDelay": {"type": "LOCKTIME_TYPE_SECONDS", "value": 2048}, "unilateralRefundDelay": {"type": "LOCKTIME_TYPE_SECONDS", "value": 4096}, "unilateralRefundWithoutEeceiverDelay": {"type": "LOCKTIME_TYPE_SECONDS", "value": 8192} }'Returns: VHTLC
id,address,claimPubkey,refundPubkey,serverPubkey,swapTree, and the resolved locktime values.
ThevhtlcIdis the sha256 hash of preimage hash + sender ec pubkey + receiver ec pubkey. -
List VHTLCs
Returns VHTLCs by their
vhtlcIds.curl -X GET "http://localhost:7001/api/v1/vhtlcs?vhtlcIds=id1,id2" -
ListVHTLC
Returns a VHTLC by its
vhtlcId.curl -X GET "http://localhost:7001/api/v1/vhtlc?vhtlcId=id1" -
Claim VHTLC
Claims a VHTLC by revealing the preimage. Moves the funds into a regular VTXO.
curl -X POST http://localhost:7001/api/v1/vhtlc/claim \ -H "Content-Type: application/json" \ -d '{"vhtlcId": "<vhtlc id>", "preimage": "<hex preimage>"}'Returns:
{ "claimTxid": "<txid>" } -
Settle VHTLC
Settles a VHTLC via either the claim path (reveal preimage) or the collaborative refund path (delegate params).
Claim path:
curl -X POST http://localhost:7001/api/v1/vhtlc/settle \ -H "Content-Type: application/json" \ -d '{"vhtlcId": "<vhtlc id>", "claim": {"preimage": "<hex preimage>"}}'Refund path:
curl -X POST http://localhost:7001/api/v1/vhtlc/settle \ -H "Content-Type: application/json" \ -d '{ "vhtlcId": "<vhtlc id>", "refund": { "delegateParams": { "signedIntentProof": "<base64>", "intentMessage": "<json string>", "partialForfeitTx": "<base64 psbt>" } } }'Returns:
{ "commitmentTxid": "<txid>" } -
Refund VHTLC Without Receiver
Unilaterally refunds a VHTLC after the timeout has expired, without requiring the receiver's cooperation.
curl -X POST http://localhost:7001/api/v1/vhtlc/refundWithoutReceiver \ -H "Content-Type: application/json" \ -d '{"vhtlcId": "<vhtlc id>"}'Returns:
{ "refundTxid": "<txid>" }
Note: Wallet setup is not required to use the Delegator API.
Fulmine can act as a delegate: it monitors VTXO expiry on behalf of clients and automatically refreshes them before they expire. Clients submit a signed intent and pre-signed forfeit transactions; Fulmine handles the rest.
-
Get Delegate Info
Returns the delegate's pubkey (to include in VTXO scripts), service fee, and fee address.
curl -X GET http://localhost:7001/api/v1/delegator/info
Returns:
{ "pubkey": "<hex>", "fee": "<amount>", "delegatorAddress": "<ark address>" } -
Delegate
Submit a delegation request. The
intent.messageis a stringified JSON describing the VTXOs to refresh. Theintent.proofis a partially signed PSBT (base64).forfeitTxsare partially signed forfeit transactions (base64), one per VTXO input.curl -X POST http://localhost:7001/api/v1/delegate \ -H "Content-Type: application/json" \ -d '{ "intent": { "message": "{\"vtxos\": [...]}", "proof": "<base64 psbt>" }, "forfeitTxs": ["<base64 psbt>"], "rejectReplace": false }' -
List Delegates
Returns delegate tasks filtered by status, paginated.
curl -X GET "http://localhost:7001/api/v1/delegates?status=<pending|completed|failed>&limit=10&offset=0"
Note: Replace http://localhost:7001 with the appropriate host and port where your Fulmine is running.
For more detailed information about request and response structures, please refer to the proto files in the api-spec/protobuf/fulmine/v1/ directory.
To get started with fulmine development you need Go 1.26.1 or higher and Node.js 18.17.1 or higher.
git clone https://github.com/ArkLabsHQ/fulmine.git
cd fulmine
go mod download
make runNow navigate to http://localhost:7001/ to see the web UI.
Run all unit tests:
make testRun integration tests:
make build-test-env
make setup-test-env
make integrationtest
make down-test-envWe welcome contributions to fulmine! Here's how you can help:
- Fork the repository and create your branch from
main - Install dependencies:
go mod download - Make your changes and ensure tests pass:
make test4. Run the linter to ensure code quality:make lint - Submit a pull request
For major changes, please open an issue first to discuss what you would like to change.
The Makefile contains several useful commands for development:
make run: Run in development modemake build: Build the binary for your platformmake test: Run unit testsmake lint: Lint the codebasemake proto: Generate protobuf stubs (requires Docker)
If you encounter any issues or have questions, please file an issue on our GitHub Issues page.
We take the security of Ark seriously. If you discover a security vulnerability, we appreciate your responsible disclosure.
Currently, we do not have an official bug bounty program. However, we value the efforts of security researchers and will consider offering appropriate compensation for significant, responsibly disclosed vulnerabilities.
This project is licensed under the MIT License - see the LICENSE file for details.
