PhotonBolt Docs

Photon Faucet Repo Guide

This document explains what this repository does, how the HTML pages are connected to the backend, and where the faucet, RGB wallet, registry, and settlement logic live.

Prism backend reference: RGBits Prism Server v10

Prism capabilities and UTXO model: RGBits Prism Server Capabilities

1. Repo purpose

This repo is not only a Bitcoin regtest faucet. It is a single Node.js service that also exposes RGB wallet helper APIs, an RGB asset registry, transfer inspection endpoints, and a watchdog-driven settlement flow for PhotonBolt regtest development.

The entrypoint is server.js. It serves static files from public/, talks to Bitcoin Core over RPC, talks to one or two RGB node APIs over HTTP, stores RGB wallet state in PostgreSQL, and stores basic faucet cooldown history in data/claims.json.

2. HTML pages and what they do

Page Frontend file Main API calls Purpose
/ public/index.html + public/app.js GET /api/status, POST /api/claim Main regtest faucet page for sending BTC to a bcrt1... address.
/asset-registry.html public/asset-registry.html + public/asset-registry.js GET /api/rgb/registry Lists known RGB assets from PostgreSQL and lets the user copy/import contract IDs.
/asset-transactions.html?assetId=... public/asset-transactions.html + public/asset-transactions.js GET /api/rgb/registry/transfers Shows transfer history for one asset by combining registry data with RGB node transfer data.

3. How the main homepage works

  • public/index.html is a static shell with a status rail, faucet form, workflow notes, and a recent activity table.
  • public/app.js calls /api/status on load to populate network, balance, chain height, cooldown, and allowed amounts.
  • The amount chips are local UI state only until submit; the chosen amount is posted as amountBtc.
  • Submitting the form sends JSON to POST /api/claim.
  • If the claim succeeds, the page stores the txid and address in browser localStorage under photonbolt_faucet_recent_activity.
  • The “Recent Activity” table is therefore browser-local, not a shared server activity feed.
  • The paste button uses the Clipboard API, and Ctrl+Enter submits the form.

4. Backend request flow

  1. The HTTP server is created in server.js using Node’s built-in http module.
  2. Requests are routed manually by pathname, not by Express or another framework.
  3. Static files are served from public/; / resolves to /index.html.
  4. GET /api/status calls Bitcoin Core RPC methods such as getblockchaininfo, getwalletinfo, and getbalance.
  5. POST /api/claim validates the address, enforces a cooldown, sends BTC with sendtoaddress, then mines blocks with generatetoaddress.
  6. Most RGB endpoints first resolve a wallet key from the x-photon-wallet-key header and upsert that wallet into PostgreSQL.

5. Storage model

There are two distinct storage layers in this repo.

  • data/claims.json: a lightweight file store for faucet cooldown records by IP and address.
  • PostgreSQL via db.js: the persistent store for wallets, wallet assets, RGB invoices, transfers, consignments, and transfer events.

The most important PostgreSQL tables are:

  • wallets: one row per logical wallet key.
  • wallet_assets: assets visible to each wallet.
  • wallet_asset_balances: derived settled/future/spendable balances.
  • rgb_invoices: invoices generated or tracked by the backend.
  • rgb_transfers: incoming and outgoing transfer rows.
  • consignment_records: proxy/consignment delivery tracking.
  • transfer_events: append-only event log for important workflow steps.
  • asset_registry: public-facing RGB asset catalog used by the registry pages.

6. RGB endpoints in plain language

  • /api/rgb/invoice: creates a normal RGB invoice and records it in PostgreSQL.
  • /api/rgb/ln-invoice: creates an RGB-over-Lightning invoice on the user account ref.
  • /api/rgb/invoice/register: registers a browser-provided blinding secret/recipient pairing.
  • /api/rgb/balance: syncs a wallet asset from the RGB node, refreshes transfers, and returns derived balance numbers.
  • /api/rgb/transfers: returns wallet-scoped transfer history for one asset.
  • /api/rgb/send: decodes an invoice, sends RGB assets, syncs transfer rows, and returns the matched transfer.
  • /api/rgb/pay-lightning: pays an RGB Lightning invoice and starts the async settlement pipeline.
  • /api/rgb/refresh: forces the node to refresh transfers and re-derives balances.
  • /api/rgb/settlement-status: polling endpoint for non-terminal settlement states so UIs can update without WebSockets.
  • /api/rgb/registry and /api/rgb/registry/transfers: public asset catalog and transfer history used by the HTML pages.

7. Settlement pipeline

The repo contains a multi-stage settlement flow for RGB Lightning transfers. The enum added in db/migrations/003_settlement_pipeline.sql tracks these phases:

  • INITIATED: the backend created a pending transfer record before touching the node.
  • PAYMENT_SUCCESS: the Lightning payment succeeded and a preimage/payment hash exists.
  • CONSIGNMENT_UPLOADED: the consignment was uploaded to the proxy.
  • SETTLED: the receiver validated the asset and the transfer reached a terminal success state.

A background watchdog in server.js runs two jobs: one confirms sender-side ACKs from the proxy, and the other forces receiver-side refresh/reconciliation until incoming transfers settle or fail validation.

8. Same-node wallets

A normal RGB Lightning payment should only be used when the sender wallet and receiver wallet resolve to different RGB node account refs. If both wallets resolve to the same node, the backend will treat that as a same-node wallet pair rather than a real Lightning route.

The reason is simple: the receiver invoice is created on the same node that the sender would use for payment, so the payment becomes a self-transfer at the node level. That is the wrong place to force Lightning semantics.

  • Different sender and receiver node refs: use normal /api/rgb/pay-lightning.
  • Same sender and receiver node ref: switch to an internal same-node wallet transfer path.

The planned same-node flow is:

  1. Receiver creates the invoice as usual.
  2. Backend stores the invoice with the receiver wallet and node account ref.
  3. Sender pastes the invoice into the send flow.
  4. Backend resolves sender wallet, receiver wallet, and both node refs.
  5. If both node refs match, backend does not call /sendpayment.
  6. Backend creates linked outgoing and incoming transfer rows in PostgreSQL.
  7. Backend records settlement events and recalculates both wallet balances.
  8. UI shows the result as an internal same-node transfer, not as a true Lightning payment.

This design is preferred over adding a middle relay node because it avoids introducing a synthetic two-leg payment that can partially succeed and leave the system holding funds between hops.

9. RGB Asset Issuance

The recommended product model for user-created RGB assets in PhotonBolt is a backend-driven issuance flow. The wallet should provide the UI and approval flow, while the backend performs the actual RGB issuance on an issuer-capable node and records the result in PostgreSQL.

This matches the current architecture better than direct issuance from the browser extension because the backend already owns wallet-scoped RGB runtime operations, invoice storage, transfer storage, and registry persistence.

RGB asset issuance requires Bitcoin UTXOs. The issuing wallet must have BTC available for fees and at least one usable issuance-ready UTXO or seal output before the backend can create the asset.

The planned issuance flow is:

  1. User opens an Issue Asset screen in the wallet.
  2. User enters asset metadata such as name, ticker, precision, supply, and optional visibility settings.
  3. Wallet calls a backend issuance API using x-photon-wallet-key.
  4. Backend validates the request and checks whether the wallet has enough BTC and issuance-ready UTXO state.
  5. Backend routes the request to an issuer-capable RGB node, ideally the dedicated issuer node for the first version.
  6. Backend creates the RGB asset and receives the resulting contract id and issuance metadata.
  7. Backend stores the issuance workflow state in PostgreSQL.
  8. Backend inserts or updates the public asset_registry row if the asset is meant to be visible in the registry.
  9. Backend imports the newly issued asset into the issuing wallet’s wallet_assets view.
  10. Wallet shows a success screen with the contract id, registry state, and import status.

The backend work should include:

  • POST /api/rgb/issue-asset to create a new fungible RGB asset.
  • GET /api/rgb/issue-asset/:id to inspect issuance status.
  • Optional GET /api/rgb/my-issued-assets for wallet history.
  • A dedicated workflow table such as rgb_asset_issuances separate from the public asset_registry.
  • Funding and UTXO readiness checks before issuance starts.

The wallet UI should include:

  • An Issue Asset form with name, ticker, precision, supply, description, and visibility controls.
  • A funding-readiness panel showing whether the wallet can issue immediately.
  • A review-and-confirm step before submission.
  • A success screen with contract id copy, import confirmation, and optional registry link.
  • A future My Issued Assets view for issuance history.

For the first version, the cleanest implementation is to issue through the dedicated issuer node and record the user wallet as the logical issuer in database metadata and registry fields such as issuer_ref. A later version can support true per-user issuer runtimes if the backend ownership model changes.

10. Preview Faucet Steps

The preview site at photonbolt.xyz/preview should link directly into the live PhotonBolt faucet stack rather than placeholder tools. These step pages document the actual user flow from the preview UI into the public faucet, registry, and RGB faucet.

11. RGB Issuance to Primary Channel Bootstrap

A newly issued asset and a Lightning-ready asset are not the same thing. PhotonBolt now has a dedicated design contract for the optional flow that reserves part of a new asset’s supply for liquidity, commits Bitcoin to the first channel, and marks the asset as LIGHTNING_READY only after the primary RGB Lightning channel is actually usable.

  • Registry-only and Lightning-ready are separate lifecycle states.
  • The full issued supply lands in the requesting wallet first.
  • A user-selected percentage can be reserved for channel liquidity after issuance.
  • BTC funding can happen during issuance or later.
  • Channel bootstrap failure does not invalidate the asset; it leaves a retryable state.

Read the full spec in /rgb-issuance-primary-channel-bootstrap.html.

For the channel-role explanation, see Primary Channel vs Parallel Channel.

12. Important files to read first

  • server.js: all routing, RPC calls, RGB orchestration, static serving, and watchdog logic.
  • db.js: PostgreSQL pool and wallet/asset upsert helpers.
  • public/index.html and public/app.js: faucet UI.
  • public/asset-registry.html and public/asset-registry.js: public asset registry UI.
  • public/asset-transactions.html and public/asset-transactions.js: asset transfer inspection UI.
  • db/migrations/001_rgb_wallets.sql, 002_asset_registry.sql, and 003_settlement_pipeline.sql: schema foundation.
  • README.md: operational basics for running and deploying the faucet.

13. Mental model

The simplest way to think about this repo is: one Node process exposes a public faucet UI, a public RGB asset browser, and several wallet-scoped RGB APIs; Bitcoin Core handles BTC, RGB nodes handle asset operations, PostgreSQL stores durable wallet state, and a watchdog reconciles delayed settlement work in the background.