Plan: Bitcoin HTTP Adapter For Your Regtest Server

You wrote "RegNet", but based on your current stack this is regtest. The clean solution is to add a browser-safe HTTP adapter that fronts your existing regtest services and replaces the public blockchain APIs currently used by the web wallet.

Current Local Stack

Component Current Value Best Use In Adapter
bitcoind RPC 127.0.0.1:18443 Broadcast, fee estimation, raw transaction lookup fallback
electrs 127.0.0.1:50001 plain TCP, dev-index.photonbolt.xyz:50002 TLS Address history and UTXO lookups
rgb-proxy-server 127.0.0.1:3000/json-rpc, public via dev-proxy.photonbolt.xyz RGB only, not Bitcoin UTXO/history/broadcast

How To Handle Fees, History, UTXOs, Broadcast On Regtest

Fees

  • Use bitcoind RPC, not electrs, as the primary source.
  • Call estimatesmartfee for multiple confirmation targets, for example 1, 3, and 6 blocks.
  • If estimatesmartfee is not useful on regtest because of low mempool activity, fall back to fallbackfee=0.0002 from your Bitcoin config.
  • Return a mempool.space-compatible JSON shape so the web wallet needs minimal frontend change.

Broadcast

  • Use sendrawtransaction on bitcoind.
  • The adapter should accept raw tx hex via HTTP POST.
  • Return plain txid text or JSON, depending on how closely you want to mimic mempool.
  • This is the safest way to replace public broadcast APIs for regtest.

Address History

  • Use electrs, not bitcoind RPC, for address history.
  • Electrs works by scripthash, not by address directly.
  • The adapter should:
    1. parse the Bitcoin address,
    2. derive its scriptPubKey,
    3. compute the Electrum scripthash,
    4. call blockchain.scripthash.get_history.
  • For richer tx details, follow with blockchain.transaction.get per txid.

UTXOs

  • Use electrs method blockchain.scripthash.listunspent.
  • This gives the UTXOs for the address-derived scripthash.
  • It is a better fit than trying to do address-index-like queries against bitcoind.
  • Transform the response into the same shape your web wallet currently expects from public APIs.
Bottom line: for regtest, use electrs for history and UTXOs, and use bitcoind RPC for fees and broadcast. That matches the strengths of each component in your current stack.

Recommended HTTP API Shape

The easiest migration path is to make your adapter look like the public APIs your frontend already uses.

HTTP Endpoint Backend Source Why
GET /api/v1/fees/recommended bitcoind estimatesmartfee Replaces mempool fee API
GET /api/address/:address electrs get_history plus optional tx lookups Lets frontend check whether the address has history
GET /api/address/:address/utxo electrs listunspent Direct replacement for UTXO lookup
GET /api/address/:address/txs electrs get_history + transaction.get Replaces activity/history feed
POST /api/tx bitcoind sendrawtransaction Replaces public broadcast endpoint
GET /api/health bitcoind + electrs checks Operational safety

Response Shapes To Mimic

Fees

{
  "fastestFee": 2,
  "halfHourFee": 2,
  "hourFee": 1,
  "minimumFee": 1
}

UTXO List

[
  {
    "txid": "....",
    "vout": 0,
    "value": 5000000000,
    "status": {
      "confirmed": true,
      "block_height": 123,
      "block_hash": "....",
      "block_time": 1710000000
    }
  }
]

Address Summary

{
  "address": "bcrt1....",
  "chain_stats": {
    "funded_txo_count": 2,
    "funded_txo_sum": 5000001000,
    "spent_txo_count": 1,
    "spent_txo_sum": 1000,
    "tx_count": 3
  },
  "mempool_stats": {
    "funded_txo_count": 0,
    "funded_txo_sum": 0,
    "spent_txo_count": 0,
    "spent_txo_sum": 0,
    "tx_count": 0
  }
}

Implementation Plan

  1. Create a small adapter service, preferably FastAPI or Node/Express, running locally on a new port such as 127.0.0.1:9001.
  2. Add an Electrum client inside that service which can talk to local electrs on 127.0.0.1:50001.
  3. Add a bitcoind RPC client inside that service using your existing regtest RPC credentials.
  4. Implement the HTTP endpoints listed above.
  5. Return mempool-style JSON shapes so the frontend refactor stays small.
  6. Expose the adapter through Nginx, for example on dev-api.photonbolt.xyz.
  7. Update the web wallet to use the adapter base URL instead of public mempool/blockstream URLs when the Photon profile is selected.

Nginx Plan

server {
    listen 80;
    server_name dev-api.photonbolt.xyz;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name dev-api.photonbolt.xyz;

    location / {
        proxy_pass http://127.0.0.1:9001;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Add the new hostname to Certbot once the DNS record exists, the same way the other Photon dev subdomains were configured.

Frontend Change Plan

Current Frontend Function Current Source New Source When Photon Profile Is Selected
fetchLiveFees mempool.space dev-api.photonbolt.xyz/api/v1/fees/recommended
checkAddressHistory mempool.space or blockstream.info dev-api.photonbolt.xyz/api/address/:address
fetchUTXOsFromBlockchain mempool.space or blockstream.info dev-api.photonbolt.xyz/api/address/:address/utxo
fetchBtcActivities mempool.space dev-api.photonbolt.xyz/api/address/:address/txs
broadcastTransaction mempool.space or blockstream.info dev-api.photonbolt.xyz/api/tx

Recommended Order Of Work

  1. Build the adapter with just /health, /fees/recommended, /address/:address/utxo, and /tx.
  2. Then add /address/:address and /address/:address/txs.
  3. Add the Nginx vhost and TLS certificate.
  4. Add a Photon backend profile in the web wallet.
  5. Switch only the selected profile to the new adapter; keep the current public profile unchanged.
Important practical note: regtest addresses are not visible to public explorers. That is why history and UTXO queries must come from your own electrs-backed adapter, not from any external API.