fibermeter

Hosted live demo operations

This runbook describes a persistent product-testing environment where a user clicks Fund via Fiber, a real Fiber testnet invoice settles end to end, and the underlying channel can be inspected on a public block explorer without requiring terminal access during the payment flow.

It complements (does not replace) the turnkey simulated path (docker compose up) used for local development.


Settlement evidence

A Fiber payment is off-chain — an HTLC update inside a payment channel. It does not appear on any block explorer, by design. What is on-chain and publicly verifiable is the channel funding transaction. So the honest, checkable proof we surface is:

  1. The dashboard Overview shows the node’s open channel(s) with a CKB testnet explorer link to each channel’s on-chain funding tx (GET /api/fiber/live-proof).
  2. Clicking Fund via Fiber issues a real fibt1… invoice; the balance is credited only after the API’s /verify confirms Fiber settled it.

Together, these surfaces show that the deployment uses a funded CKB testnet channel and that FiberMeter moves the customer balance only after settlement.


Why the hosted environment needs one-time bootstrap

Going live needs two funded testnet nodes + an open channel. Funding comes from the CKB faucet (external, rate-limited) and a channel open needs on-chain confirmation. Local application startup cannot create faucet capacity or an on-chain channel automatically, so operators complete this bootstrap once and persist the node state.


Topology

┌─────────────── your droplet ───────────────┐
│  Docker:  postgres · api(live) · dashboard  │
│           · demo-service · autopay          │
│                                             │
│  Host:    fnn payee node  RPC :8237  ◄── api (issues invoices)
│           fnn payer node  RPC :8247  ◄── autopay (pays invoices)
└─────────────────────────────────────────────┘
        │                    │
        └─ public CKB testnet RPC (testnet.ckbapp.dev) ─┘

Requirements


One-time bootstrap

1. Prepare two node data dirs

Give each node its own directory, config, and CKB key. Use distinct ports so they can coexist and the containers can reach each:

Node Fiber P2P Fiber RPC data dir
payee 8238 8237 ./fiber-payee
payer 8248 8247 ./fiber-payer

In each config.yml, set chain: testnet, point ckb.rpc_url at a public testnet RPC (https://testnet.ckbapp.dev/), and set rpc.listening_addr to the port above. Keep RPC bound to 127.0.0.1 — it is dangerous to expose. (The repo’s fiber-payee/config.yml is a working reference.)

2. Start both nodes on the host

FIBER_SECRET_KEY_PASSWORD='password' ./fiber-payee/fnn -c ./fiber-payee/config.yml -d ./fiber-payee &
FIBER_SECRET_KEY_PASSWORD='password' ./fiber-payer/fnn -c ./fiber-payer/config.yml -d ./fiber-payer &

Confirm each responds:

curl -s -X POST http://127.0.0.1:8237 -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"node_info","params":[{}]}' | jq .result.node_id
curl -s -X POST http://127.0.0.1:8247 -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"node_info","params":[{}]}' | jq .result.node_id

3. Fund the payer node from the faucet

The payer funds the channel (its balance is what gets pushed to the payee on each top-up), so it needs on-chain CKB. Get the payer node’s CKB address (via ckb-cli / your wallet against the node’s ckb/key) and request testnet CKB at https://faucet.nervos.org/. Fund with enough for the channel + fees (e.g. 300+ CKB).

4. Peer the nodes and open a channel (payer → payee)

Use fnn-cli against each node — it tracks the current RPC parameter shapes across fnn versions, so prefer it over hand-rolled JSON:

# connect payer → payee (payee multiaddr = /ip4/127.0.0.1/tcp/8238/p2p/<payee node_id>)
./fiber-payer/fnn-cli --rpc http://127.0.0.1:8247 connect-peer <payee-multiaddr>

# open a funded channel from payer → payee (gives the payee inbound capacity to receive top-ups)
./fiber-payer/fnn-cli --rpc http://127.0.0.1:8247 open-channel --peer <payee-node-id> --funding-amount 20000000000

Wait until the channel is ChannelReady:

curl -s -X POST http://127.0.0.1:8247 -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"list_channels","params":[{}]}' | jq '.result.channels[].state'

Exact fnn-cli subcommand names/flags can differ by release — run ./fnn-cli --help. The RPC methods are connect_peer, open_channel, list_channels. This is the only manual, on-chain step; everything after is automated.

5. Start the app tier (live) with the auto-payer

docker compose -f docker-compose.yml -f docker-compose.live.yml up -d

This runs postgres + API in live mode (invoice creation/verification → payee :8237, preflight → payer :8247) + dashboard + demo-service + autopay (→ payer :8247). The API auto-migrates and seeds on boot.


Hosted user flow

  1. Open the dashboard, log in (demo@fibermeter.dev / password123).
  2. OverviewLive Fiber channel proof shows the channel with a CKB testnet explorer link. Click it — real funding tx on testnet. ✅
  3. Create a Payment Request for a customer → a real fibt1… invoice.
  4. Within a few seconds autopay settles it from the payer node; the request flips to Paid, the balance is credited, and the confirmation keeps the CKB Explorer proof link visible.
  5. Run the demo service / record usage → the live-funded balance is charged.

No terminal, no manual send_payment.


The auto-payer

scripts/autopay.mjs (npm: pnpm autopay) logs into the API, polls GET /api/payment-requests, and for each live + pending request calls send_payment on the payer node, then polls the API’s /verify until Fiber confirms. Config via env (see the file header): API_URL, API_EMAIL, API_PASSWORD, PAYER_RPC_URL, POLL_MS, MAX_PAYMENT_CKB. It never pays the same request twice.


Security & operations