From 7917a7413cbcee5d7a8d5395b074d665e3d8dd31 Mon Sep 17 00:00:00 2001 From: TaprootFreak <142087526+TaprootFreak@users.noreply.github.com> Date: Thu, 13 Nov 2025 11:53:53 +0100 Subject: [PATCH 01/11] README.md aktualisieren Do not merge this state into PRD! --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 48d4ead2..88fc4cec 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ # lightning.space API API for lightning.space custodial service + +Do not merge this state into PRD! From 538fb2b7adef35889282fe48b390400d631cb38e Mon Sep 17 00:00:00 2001 From: bernd2022 <104787072+bernd2022@users.noreply.github.com> Date: Fri, 14 Nov 2025 14:26:46 +0100 Subject: [PATCH 02/11] [DEV-4458] Update infrastructure (#87) * [DEV-4458] Update infrastructure * [DEV-4458] Changes after review * [DEV-4458] Change because of renaming compose file * [DEV-4458] Add second volume again --- infrastructure/README.md | 17 +- .../config/bitcoin/dev-bitcoin.conf | 12 +- .../config/bitcoin/prd-bitcoin.conf | 1 + .../config/boltz/backend/dev-boltz.conf | 150 ++++++++++++++++++ .../config/boltz/backend/prd-boltz.conf | 150 ++++++++++++++++++ .../docker/dev-docker-compose-boltz.yml | 93 +++++++++++ ...e.yml => dev-docker-compose-lightning.yml} | 89 +++++++---- .../docker/dev-docker-compose-nginx.yml | 24 +++ .../docker/prd-docker-compose-boltz.yml | 93 +++++++++++ ...e.yml => prd-docker-compose-lightning.yml} | 85 ++++++---- .../docker/prd-docker-compose-nginx.yml | 24 +++ infrastructure/config/lightning/dev-lnd.conf | 4 + infrastructure/config/lightning/prd-pwd.txt | 1 + infrastructure/config/lnbits/dev.env | 6 +- infrastructure/config/lnbits/prd.env | 2 +- infrastructure/config/nginx/dev-default.conf | 71 +++++++++ infrastructure/config/nginx/prd-default.conf | 71 +++++++++ infrastructure/config/taproot/dev-tapd.conf | 10 +- .../config/thunderhub/dev-accounts.yml | 2 +- infrastructure/config/thunderhub/dev.env | 2 +- infrastructure/scripts/dev-docker-compose.sh | 7 - .../scripts/dev-runBackup-exclude-file.txt | 3 - ...rd-docker-compose.sh => docker-compose.sh} | 2 +- ...de-file.txt => runBackup-exclude-file.txt} | 0 infrastructure/scripts/setupEnv.sh | 21 +-- 25 files changed, 843 insertions(+), 97 deletions(-) create mode 100644 infrastructure/config/boltz/backend/dev-boltz.conf create mode 100644 infrastructure/config/boltz/backend/prd-boltz.conf create mode 100644 infrastructure/config/docker/dev-docker-compose-boltz.yml rename infrastructure/config/docker/{dev-docker-compose.yml => dev-docker-compose-lightning.yml} (58%) create mode 100644 infrastructure/config/docker/dev-docker-compose-nginx.yml create mode 100644 infrastructure/config/docker/prd-docker-compose-boltz.yml rename infrastructure/config/docker/{prd-docker-compose.yml => prd-docker-compose-lightning.yml} (62%) create mode 100644 infrastructure/config/docker/prd-docker-compose-nginx.yml create mode 100644 infrastructure/config/lightning/prd-pwd.txt delete mode 100644 infrastructure/scripts/dev-docker-compose.sh delete mode 100644 infrastructure/scripts/dev-runBackup-exclude-file.txt rename infrastructure/scripts/{prd-docker-compose.sh => docker-compose.sh} (71%) rename infrastructure/scripts/{prd-runBackup-exclude-file.txt => runBackup-exclude-file.txt} (100%) diff --git a/infrastructure/README.md b/infrastructure/README.md index 2a570978..337ab128 100644 --- a/infrastructure/README.md +++ b/infrastructure/README.md @@ -14,8 +14,11 @@ 1. Execute script: `sudo ./setupDocker.sh` 1. Copy script `infrastructure/scripts/setupEnv.sh` to virtual machine `~/setupEnv.sh` 1. Execute script: `./setupEnv.sh` -1. Copy script `infrastructure/scripts/{env}-docker-compose.sh` to virtual machine `~/docker-compose.sh` -1. Copy file `infrastructure/config/docker/{env}-docker-compose.yml` to virtual machine `~/docker-compose.yml` +1. Create docker network `docker network create lightning-network` +1. Copy script `infrastructure/scripts/docker-compose.sh` to virtual machine `~/docker-compose.sh` +1. Copy file `infrastructure/config/docker/{env}-docker-compose-lightning.yml` to virtual machine `~/docker-compose-lightning.yml` +1. Copy file `infrastructure/config/docker/{env}-docker-compose-nginx.yml` to virtual machine `~/docker-compose-nginx.yml` +1. Copy file `infrastructure/config/docker/{env}-docker-compose-boltz.yml` to virtual machine `~/docker-compose-boltz.yml` 1. Execute Docker Compose (see [below](#docker-compose)) after all other setup steps are done: 1. [Bitcoin Node Setup](#bitcoin-node-setup-bitcoind) 1. [Lightning Node Setup](#lightning-node-setup-lnd) @@ -23,6 +26,7 @@ 1. [LNbits Setup](#lnbits-setup) 1. [ThunderHub Setup](#thunderhub-setup) 1. [NGINX Setup](#nginx-setup) + 1. [Boltz Setup](#boltz-setup) # Bitcoin Node Setup (bitcoind) @@ -59,6 +63,15 @@ 1. Copy content of config file `infrastructure/config/nginx/{env}-default.conf` to virtual machine `~/volumes/nginx/default.conf` +# Boltz Setup + +1. Copy content of config file `infrastructure/config/boltz/backend/{env}-boltz.conf` to virtual machine `~/volumes/boltz/backend/boltz.conf` +1. `boltz.conf`: Replace + 1. `[POSTGRES_DATABASE]` / `[POSTGRES_USERNAME]` / `[POSTGRES_PASSWORD]` + 1. `[RPC_USER]` / `[RPC_PASSWORD]` + 1. `[WALLET_NAME]` + 1. `[PROVIDER_ENDPOINT]` + # Docker Compose The complete Bitcoin Blockchain data is loaded after the very first startup of the bitcoin node. Therefore it is recommended to copy already available blockchain data to the `~/volumes/bitcoin/...` directory. diff --git a/infrastructure/config/bitcoin/dev-bitcoin.conf b/infrastructure/config/bitcoin/dev-bitcoin.conf index 3018e8cc..870156b3 100644 --- a/infrastructure/config/bitcoin/dev-bitcoin.conf +++ b/infrastructure/config/bitcoin/dev-bitcoin.conf @@ -1,16 +1,14 @@ -testnet=1 server=1 rest=1 +txindex=1 rpcallowip=0.0.0.0/0 +rpcbind=0.0.0.0 +rpcport=8332 rpcauth=[RPC-AUTH] -zmqpubrawblock=tcp://0.0.0.0:28332 -zmqpubrawtx=tcp://0.0.0.0:28333 - -[test] wallet=[WALLET] addresstype=p2sh-segwit -rpcbind=0.0.0.0 -rpcport=18332 +zmqpubrawblock=tcp://0.0.0.0:28332 +zmqpubrawtx=tcp://0.0.0.0:28333 diff --git a/infrastructure/config/bitcoin/prd-bitcoin.conf b/infrastructure/config/bitcoin/prd-bitcoin.conf index a93bdbcf..870156b3 100644 --- a/infrastructure/config/bitcoin/prd-bitcoin.conf +++ b/infrastructure/config/bitcoin/prd-bitcoin.conf @@ -1,5 +1,6 @@ server=1 rest=1 +txindex=1 rpcallowip=0.0.0.0/0 rpcbind=0.0.0.0 diff --git a/infrastructure/config/boltz/backend/dev-boltz.conf b/infrastructure/config/boltz/backend/dev-boltz.conf new file mode 100644 index 00000000..5c1d50ad --- /dev/null +++ b/infrastructure/config/boltz/backend/dev-boltz.conf @@ -0,0 +1,150 @@ +# Boltz Backend Configuration - Mainnet +# Integration with existing Lightning.space infrastructure + +# Network Configuration - MUST be at top level before any sections! +network = "mainnet" + +loglevel = "debug" + +[api] +host = "0.0.0.0" +port = 9001 +allowedCors = ["*"] + +[grpc] +host = "0.0.0.0" +port = 9000 + +# Sidecar Configuration (Rust component) +[sidecar] + [sidecar.grpc] + host = "0.0.0.0" + port = 9003 + certificates = "/root/.boltz/sidecar/certificates" + + [sidecar.ws] + host = "0.0.0.0" + port = 9004 + + [sidecar.api] + host = "0.0.0.0" + port = 9005 + +# PostgreSQL Database +[postgres] +host = "postgres" +port = 5432 +database = "[POSTGRES_DATABASE]" +username = "[POSTGRES_USERNAME]" +password = "[POSTGRES_PASSWORD]" + +# Redis Cache (optional but recommended) +[cache] +redisEndpoint = "redis://redis:6379" + +# Bitcoin/Lightning Configuration +[[currencies]] +symbol = "BTC" +network = "bitcoinMainnet" + +# Wallet balances - adjusted for testing +minWalletBalance = 100_000 # 0.001 BTC (100k sats) +minChannelBalance = 100_000 # 0.001 BTC (100k sats) + +# Swap limits +maxSwapAmount = 10_000_000 # 0.1 BTC maximum +minSwapAmount = 2_500 # 2,500 sats minimum (currency level - for all BTC swaps) +maxZeroConfAmount = 0 # Disable 0-conf for security + + # Bitcoin Core Configuration + [currencies.chain] + host = "bitcoind" + port = 8332 + + # RPC Authentication + user = "[RPC_USER]" + password = "[RPC_PASSWORD]" + + # ZMQ endpoints for blockchain notifications + zmqpubrawtx = "tcp://bitcoind:28333" + zmqpubrawblock = "tcp://bitcoind:28332" + + # Bitcoin wallet name + wallet = "[WALLET_NAME]" + + # LND Configuration + [currencies.lnd] + host = "lnd" + port = 10009 # gRPC port (not REST 8080!) + + # Credentials - mounted from Docker volumes + certpath = "/root/.lnd/tls.cert" + macaroonpath = "/root/.lnd/data/chain/bitcoin/mainnet/admin.macaroon" + +# Swap Pair Configuration: BTC/BTC (Lightning <-> OnChain) +[[pairs]] +base = "BTC" +quote = "BTC" +rate = 1 # 1:1 exchange rate + +# Fee configuration (in percent) +fee = 0.5 # 0.5% service fee +swapInFee = 0.25 # 0.25% for submarine swaps (chain -> lightning) + +# Swap amount limits (in satoshis) +maxSwapAmount = 10_000_000 # 0.1 BTC +minSwapAmount = 2_500 # 2,500 sats (pair level) + + # Submarine Swap specific settings (Chain -> Lightning) + [pairs.submarineSwap] + minSwapAmount = 10_000 # Minimum for submarine swaps (needs high limit due to on-chain fees) + + # Reverse Swap specific settings (Lightning -> Chain) + [pairs.reverseSwap] + minSwapAmount = 2_500 # Minimum for reverse swaps (lower fees, no input tx) + + # Timeout configuration (in minutes!) + [pairs.timeoutDelta] + chain = 1440 # Chain swap timeout (~24 hours = 144 blocks) + reverse = 1440 # ~24 hours for reverse swaps (lightning -> chain) + swapMinimal = 1440 # Minimum timeout for submarine swaps (~24 hours = 144 blocks) + swapMaximal = 2880 # Maximum timeout (~48 hours = 288 blocks) + swapTaproot = 10080 # 1 week for taproot swaps (10080 blocks) + +# Swap Pair Configuration: BTC/RBTC (Lightning BTC <-> RSK RBTC) +[[pairs]] +base = "BTC" +quote = "RBTC" +rate = 1 # 1:1 peg between BTC and RBTC + +# Fee configuration (in percent) +fee = 0.25 +swapInFee = 0.1 + +# Swap amount limits (in satoshis) +maxSwapAmount = 10_000_000 # 0.1 BTC/RBTC +minSwapAmount = 2_500 # 2,500 sats minimum (Rootstock has lower fees) + + [pairs.timeoutDelta] + chain = 1440 # Chain swap timeout (~24 hours) + reverse = 1440 # Reverse swap timeout (Lightning -> RBTC) + swapMinimal = 1440 # Minimum timeout + swapMaximal = 2880 # Maximum timeout + swapTaproot = 10080 + +# RSK (Rootstock) Configuration +[rsk] +networkName = "RSK Mainnet" +providerEndpoint = "[PROVIDER_ENDPOINT]" + + [[rsk.contracts]] + etherSwap = "0x3d9cc5780CA1db78760ad3D35458509178A85A4A" + erc20Swap = "0x7d5a2187CC8EF75f8822daB0E8C9a2DB147BA045" + + [[rsk.tokens]] + symbol = "RBTC" + + maxSwapAmount = 10_000_000 + minSwapAmount = 2_500 + + minWalletBalance = 10_000 diff --git a/infrastructure/config/boltz/backend/prd-boltz.conf b/infrastructure/config/boltz/backend/prd-boltz.conf new file mode 100644 index 00000000..5c1d50ad --- /dev/null +++ b/infrastructure/config/boltz/backend/prd-boltz.conf @@ -0,0 +1,150 @@ +# Boltz Backend Configuration - Mainnet +# Integration with existing Lightning.space infrastructure + +# Network Configuration - MUST be at top level before any sections! +network = "mainnet" + +loglevel = "debug" + +[api] +host = "0.0.0.0" +port = 9001 +allowedCors = ["*"] + +[grpc] +host = "0.0.0.0" +port = 9000 + +# Sidecar Configuration (Rust component) +[sidecar] + [sidecar.grpc] + host = "0.0.0.0" + port = 9003 + certificates = "/root/.boltz/sidecar/certificates" + + [sidecar.ws] + host = "0.0.0.0" + port = 9004 + + [sidecar.api] + host = "0.0.0.0" + port = 9005 + +# PostgreSQL Database +[postgres] +host = "postgres" +port = 5432 +database = "[POSTGRES_DATABASE]" +username = "[POSTGRES_USERNAME]" +password = "[POSTGRES_PASSWORD]" + +# Redis Cache (optional but recommended) +[cache] +redisEndpoint = "redis://redis:6379" + +# Bitcoin/Lightning Configuration +[[currencies]] +symbol = "BTC" +network = "bitcoinMainnet" + +# Wallet balances - adjusted for testing +minWalletBalance = 100_000 # 0.001 BTC (100k sats) +minChannelBalance = 100_000 # 0.001 BTC (100k sats) + +# Swap limits +maxSwapAmount = 10_000_000 # 0.1 BTC maximum +minSwapAmount = 2_500 # 2,500 sats minimum (currency level - for all BTC swaps) +maxZeroConfAmount = 0 # Disable 0-conf for security + + # Bitcoin Core Configuration + [currencies.chain] + host = "bitcoind" + port = 8332 + + # RPC Authentication + user = "[RPC_USER]" + password = "[RPC_PASSWORD]" + + # ZMQ endpoints for blockchain notifications + zmqpubrawtx = "tcp://bitcoind:28333" + zmqpubrawblock = "tcp://bitcoind:28332" + + # Bitcoin wallet name + wallet = "[WALLET_NAME]" + + # LND Configuration + [currencies.lnd] + host = "lnd" + port = 10009 # gRPC port (not REST 8080!) + + # Credentials - mounted from Docker volumes + certpath = "/root/.lnd/tls.cert" + macaroonpath = "/root/.lnd/data/chain/bitcoin/mainnet/admin.macaroon" + +# Swap Pair Configuration: BTC/BTC (Lightning <-> OnChain) +[[pairs]] +base = "BTC" +quote = "BTC" +rate = 1 # 1:1 exchange rate + +# Fee configuration (in percent) +fee = 0.5 # 0.5% service fee +swapInFee = 0.25 # 0.25% for submarine swaps (chain -> lightning) + +# Swap amount limits (in satoshis) +maxSwapAmount = 10_000_000 # 0.1 BTC +minSwapAmount = 2_500 # 2,500 sats (pair level) + + # Submarine Swap specific settings (Chain -> Lightning) + [pairs.submarineSwap] + minSwapAmount = 10_000 # Minimum for submarine swaps (needs high limit due to on-chain fees) + + # Reverse Swap specific settings (Lightning -> Chain) + [pairs.reverseSwap] + minSwapAmount = 2_500 # Minimum for reverse swaps (lower fees, no input tx) + + # Timeout configuration (in minutes!) + [pairs.timeoutDelta] + chain = 1440 # Chain swap timeout (~24 hours = 144 blocks) + reverse = 1440 # ~24 hours for reverse swaps (lightning -> chain) + swapMinimal = 1440 # Minimum timeout for submarine swaps (~24 hours = 144 blocks) + swapMaximal = 2880 # Maximum timeout (~48 hours = 288 blocks) + swapTaproot = 10080 # 1 week for taproot swaps (10080 blocks) + +# Swap Pair Configuration: BTC/RBTC (Lightning BTC <-> RSK RBTC) +[[pairs]] +base = "BTC" +quote = "RBTC" +rate = 1 # 1:1 peg between BTC and RBTC + +# Fee configuration (in percent) +fee = 0.25 +swapInFee = 0.1 + +# Swap amount limits (in satoshis) +maxSwapAmount = 10_000_000 # 0.1 BTC/RBTC +minSwapAmount = 2_500 # 2,500 sats minimum (Rootstock has lower fees) + + [pairs.timeoutDelta] + chain = 1440 # Chain swap timeout (~24 hours) + reverse = 1440 # Reverse swap timeout (Lightning -> RBTC) + swapMinimal = 1440 # Minimum timeout + swapMaximal = 2880 # Maximum timeout + swapTaproot = 10080 + +# RSK (Rootstock) Configuration +[rsk] +networkName = "RSK Mainnet" +providerEndpoint = "[PROVIDER_ENDPOINT]" + + [[rsk.contracts]] + etherSwap = "0x3d9cc5780CA1db78760ad3D35458509178A85A4A" + erc20Swap = "0x7d5a2187CC8EF75f8822daB0E8C9a2DB147BA045" + + [[rsk.tokens]] + symbol = "RBTC" + + maxSwapAmount = 10_000_000 + minSwapAmount = 2_500 + + minWalletBalance = 10_000 diff --git a/infrastructure/config/docker/dev-docker-compose-boltz.yml b/infrastructure/config/docker/dev-docker-compose-boltz.yml new file mode 100644 index 00000000..896d49be --- /dev/null +++ b/infrastructure/config/docker/dev-docker-compose-boltz.yml @@ -0,0 +1,93 @@ +name: 'boltz' + +services: + postgres: + image: postgres:17 + cpus: 0.5 + shm_size: '1gb' + restart: unless-stopped + networks: + - shared + volumes: + - ./volumes/boltz/postgres:/var/lib/postgresql/data + ports: + - '5432:5432' + healthcheck: + test: ['CMD-SHELL', 'pg_isready -U [POSTGRES_USERNAME]'] + interval: 30s + timeout: 5s + retries: 5 + logging: + driver: 'json-file' + options: + max-size: '100m' + max-file: '3' + environment: + - POSTGRES_DB=[POSTGRES_DATABASE] + - POSTGRES_USER=[POSTGRES_USERNAME] + - POSTGRES_PASSWORD=[POSTGRES_PASSWORD] + command: postgres -c max_connections=100 + + redis: + image: redis:alpine + restart: unless-stopped + networks: + - shared + volumes: + - ./volumes/boltz/redis/data:/data + ports: + - '6379:6379' + logging: + driver: 'json-file' + options: + max-size: '100m' + max-file: '3' + command: redis-server + + backend: + image: dfxswiss/boltz-backend:dev + restart: unless-stopped + networks: + - shared + depends_on: + - postgres + volumes: + - ./volumes/lightning:/root/.lnd + - ./volumes/boltz/backend/data:/root/.boltz + - ./volumes/boltz/backend/boltz.conf:/root/.boltz/boltz.conf + ports: + - '9000:9000' + - '9001:9001' + - '9004:9004' + logging: + driver: 'json-file' + options: + max-size: '100m' + max-file: '3' + environment: + - NODE_EXTRA_CA_CERTS=/root/.lnd/tls.cert + webapp: + image: dfxswiss/boltz-webapp:dev + restart: unless-stopped + networks: + - shared + depends_on: + - backend + volumes: + - ./volumes/lightning:/root/.lnd + + ports: + - '444:444' + logging: + driver: 'json-file' + options: + max-size: '100m' + max-file: '3' + environment: + - VITE_API_URL=http://backend:9000 + - VITE_RSK_LOG_SCAN_ENDPOINT=[VITE_RSK_LOG_SCAN_ENDPOINT] + +networks: + shared: + external: true + name: lightning-network diff --git a/infrastructure/config/docker/dev-docker-compose.yml b/infrastructure/config/docker/dev-docker-compose-lightning.yml similarity index 58% rename from infrastructure/config/docker/dev-docker-compose.yml rename to infrastructure/config/docker/dev-docker-compose-lightning.yml index ccb23537..57a97ab6 100644 --- a/infrastructure/config/docker/dev-docker-compose.yml +++ b/infrastructure/config/docker/dev-docker-compose-lightning.yml @@ -1,31 +1,36 @@ -version: '3.7' -name: 'bitcoin-lightning' +name: 'lightning' services: bitcoind: image: lightninglabs/bitcoin-core - restart: always + restart: unless-stopped + networks: + - shared volumes: - ./volumes/bitcoin:/home/bitcoin/.bitcoin - - ./volumes/bitcoin/bitcoin.conf:/home/bitcoin/.bitcoin/bitcoin.conf - - ./volumes/bitcoin/wallets:/home/bitcoin/.bitcoin/testnet3/wallets ports: - - '18332:18332' + - '8332:8332' healthcheck: - test: curl --fail http://localhost:18332/rest/chaininfo.json || exit 1 + test: curl --fail http://localhost:8332/rest/chaininfo.json || exit 1 start_period: 120s interval: 30s timeout: 60s retries: 10 + logging: + driver: 'json-file' + options: + max-size: '100m' + max-file: '3' command: > bitcoind -conf=/home/bitcoin/.bitcoin/bitcoin.conf lnd: - image: lightninglabs/lnd:v0.17.3-beta - restart: always + image: lightninglabs/lnd:v0.19.3-beta + restart: unless-stopped + networks: + - shared volumes: - ./volumes/lightning:/root/.lnd - - ./volumes/lightning/lnd.conf:/root/.lnd/lnd.conf ports: - '8080:8080' healthcheck: @@ -34,15 +39,22 @@ services: interval: 30s timeout: 60s retries: 10 + logging: + driver: 'json-file' + options: + max-size: '100m' + max-file: '3' depends_on: bitcoind: condition: service_healthy command: > - lnd --configfile=/root/.lnd/lnd.conf --bitcoin.testnet + lnd --configfile=/root/.lnd/lnd.conf --bitcoin.mainnet tapd: - image: polarlightning/tapd:0.3.2-alpha - restart: always + image: polarlightning/tapd:0.3.3-alpha + restart: unless-stopped + networks: + - shared volumes: - ./volumes/lightning:/home/tap/.lnd - ./volumes/taproot:/home/tap/.tapd @@ -52,12 +64,19 @@ services: depends_on: lnd: condition: service_healthy + logging: + driver: 'json-file' + options: + max-size: '100m' + max-file: '3' command: > tapd --configfile=/home/tap/tapd.conf lnbits: - image: lnbitsdocker/lnbits-legend:0.11.3 - restart: always + image: lnbits/lnbits:0.12.8 + restart: unless-stopped + networks: + - shared volumes: - ./volumes/lightning:/app/.lnd - ./volumes/lnbits/data:/app/data @@ -70,6 +89,11 @@ services: interval: 60s timeout: 30s retries: 10 + logging: + driver: 'json-file' + options: + max-size: '100m' + max-file: '3' depends_on: lnd: condition: service_healthy @@ -78,20 +102,29 @@ services: lnbitsapi: image: dfxswiss/lnbitsapi:latest - restart: always + restart: unless-stopped + networks: + - shared volumes: - ./volumes/lnbitsapi/data:/home/node/data - ./volumes/lnbits/data:/home/node/data/sqlite3 - ./volumes/lnbitsapi/.env:/home/node/.env ports: - '5001:5001' + logging: + driver: 'json-file' + options: + max-size: '100m' + max-file: '3' depends_on: lnbits: condition: service_healthy thunderhub: - image: apotdevin/thunderhub:v0.13.30 - restart: always + image: apotdevin/thunderhub:v0.13.31 + restart: unless-stopped + networks: + - shared volumes: - ./volumes/lightning:/app/.lnd - ./volumes/thunderhub/.env:/app/.env @@ -101,15 +134,13 @@ services: depends_on: lnd: condition: service_healthy + logging: + driver: 'json-file' + options: + max-size: '100m' + max-file: '3' - nginx: - image: nginx:1.25.3-perl - restart: always - volumes: - - ./volumes/lightning:/app/.lnd - - ./volumes/nginx/default.conf:/etc/nginx/conf.d/default.conf - ports: - - '443:443' - depends_on: - - lnbits - - thunderhub +networks: + shared: + external: true + name: lightning-network diff --git a/infrastructure/config/docker/dev-docker-compose-nginx.yml b/infrastructure/config/docker/dev-docker-compose-nginx.yml new file mode 100644 index 00000000..eee1fc0f --- /dev/null +++ b/infrastructure/config/docker/dev-docker-compose-nginx.yml @@ -0,0 +1,24 @@ +name: 'network' + +services: + nginx: + image: nginx:1.25.5-perl + restart: unless-stopped + networks: + - shared + volumes: + - ./volumes/lightning:/app/.lnd + - ./volumes/nginx/default.conf:/etc/nginx/conf.d/default.conf + ports: + - '443:443' + - '9006:9006' + logging: + driver: 'json-file' + options: + max-size: '100m' + max-file: '3' + +networks: + shared: + external: true + name: lightning-network diff --git a/infrastructure/config/docker/prd-docker-compose-boltz.yml b/infrastructure/config/docker/prd-docker-compose-boltz.yml new file mode 100644 index 00000000..896d49be --- /dev/null +++ b/infrastructure/config/docker/prd-docker-compose-boltz.yml @@ -0,0 +1,93 @@ +name: 'boltz' + +services: + postgres: + image: postgres:17 + cpus: 0.5 + shm_size: '1gb' + restart: unless-stopped + networks: + - shared + volumes: + - ./volumes/boltz/postgres:/var/lib/postgresql/data + ports: + - '5432:5432' + healthcheck: + test: ['CMD-SHELL', 'pg_isready -U [POSTGRES_USERNAME]'] + interval: 30s + timeout: 5s + retries: 5 + logging: + driver: 'json-file' + options: + max-size: '100m' + max-file: '3' + environment: + - POSTGRES_DB=[POSTGRES_DATABASE] + - POSTGRES_USER=[POSTGRES_USERNAME] + - POSTGRES_PASSWORD=[POSTGRES_PASSWORD] + command: postgres -c max_connections=100 + + redis: + image: redis:alpine + restart: unless-stopped + networks: + - shared + volumes: + - ./volumes/boltz/redis/data:/data + ports: + - '6379:6379' + logging: + driver: 'json-file' + options: + max-size: '100m' + max-file: '3' + command: redis-server + + backend: + image: dfxswiss/boltz-backend:dev + restart: unless-stopped + networks: + - shared + depends_on: + - postgres + volumes: + - ./volumes/lightning:/root/.lnd + - ./volumes/boltz/backend/data:/root/.boltz + - ./volumes/boltz/backend/boltz.conf:/root/.boltz/boltz.conf + ports: + - '9000:9000' + - '9001:9001' + - '9004:9004' + logging: + driver: 'json-file' + options: + max-size: '100m' + max-file: '3' + environment: + - NODE_EXTRA_CA_CERTS=/root/.lnd/tls.cert + webapp: + image: dfxswiss/boltz-webapp:dev + restart: unless-stopped + networks: + - shared + depends_on: + - backend + volumes: + - ./volumes/lightning:/root/.lnd + + ports: + - '444:444' + logging: + driver: 'json-file' + options: + max-size: '100m' + max-file: '3' + environment: + - VITE_API_URL=http://backend:9000 + - VITE_RSK_LOG_SCAN_ENDPOINT=[VITE_RSK_LOG_SCAN_ENDPOINT] + +networks: + shared: + external: true + name: lightning-network diff --git a/infrastructure/config/docker/prd-docker-compose.yml b/infrastructure/config/docker/prd-docker-compose-lightning.yml similarity index 62% rename from infrastructure/config/docker/prd-docker-compose.yml rename to infrastructure/config/docker/prd-docker-compose-lightning.yml index db0e62b3..27b6179d 100644 --- a/infrastructure/config/docker/prd-docker-compose.yml +++ b/infrastructure/config/docker/prd-docker-compose-lightning.yml @@ -1,14 +1,13 @@ -version: '3.7' -name: 'bitcoin-lightning' +name: 'lightning' services: bitcoind: image: lightninglabs/bitcoin-core - restart: always + restart: unless-stopped + networks: + - shared volumes: - ./volumes/bitcoin:/home/bitcoin/.bitcoin - - ./volumes/bitcoin/bitcoin.conf:/home/bitcoin/.bitcoin/bitcoin.conf - - ./volumes/bitcoin/wallets:/home/bitcoin/.bitcoin/wallets ports: - '8332:8332' healthcheck: @@ -17,15 +16,21 @@ services: interval: 30s timeout: 60s retries: 10 + logging: + driver: 'json-file' + options: + max-size: '100m' + max-file: '3' command: > bitcoind -conf=/home/bitcoin/.bitcoin/bitcoin.conf lnd: - image: lightninglabs/lnd:v0.17.3-beta - restart: always + image: lightninglabs/lnd:v0.19.3-beta + restart: unless-stopped + networks: + - shared volumes: - ./volumes/lightning:/root/.lnd - - ./volumes/lightning/lnd.conf:/root/.lnd/lnd.conf ports: - '8080:8080' - '9735:9735' @@ -35,6 +40,11 @@ services: interval: 30s timeout: 60s retries: 10 + logging: + driver: 'json-file' + options: + max-size: '100m' + max-file: '3' depends_on: bitcoind: condition: service_healthy @@ -42,8 +52,10 @@ services: lnd --configfile=/root/.lnd/lnd.conf --bitcoin.mainnet tapd: - image: polarlightning/tapd:0.3.2-alpha - restart: always + image: polarlightning/tapd:0.3.3-alpha + restart: unless-stopped + networks: + - shared volumes: - ./volumes/lightning:/home/tap/.lnd - ./volumes/taproot:/home/tap/.tapd @@ -54,12 +66,19 @@ services: depends_on: lnd: condition: service_healthy + logging: + driver: 'json-file' + options: + max-size: '100m' + max-file: '3' command: > - tapd --configfile=/home/tap/tapd.conf --profile=localhost:6060 + tapd --configfile=/home/tap/tapd.conf lnbits: - image: lnbitsdocker/lnbits-legend:0.11.3 - restart: always + image: lnbits/lnbits:0.12.8 + restart: unless-stopped + networks: + - shared volumes: - ./volumes/lightning:/app/.lnd - ./volumes/lnbits/data:/app/data @@ -72,6 +91,11 @@ services: interval: 60s timeout: 30s retries: 10 + logging: + driver: 'json-file' + options: + max-size: '100m' + max-file: '3' depends_on: lnd: condition: service_healthy @@ -80,20 +104,29 @@ services: lnbitsapi: image: dfxswiss/lnbitsapi:main - restart: always + restart: unless-stopped + networks: + - shared volumes: - ./volumes/lnbitsapi/data:/home/node/data - ./volumes/lnbits/data:/home/node/data/sqlite3 - ./volumes/lnbitsapi/.env:/home/node/.env ports: - '5001:5001' + logging: + driver: 'json-file' + options: + max-size: '100m' + max-file: '3' depends_on: lnbits: condition: service_healthy thunderhub: - image: apotdevin/thunderhub:v0.13.30 - restart: always + image: apotdevin/thunderhub:v0.13.31 + restart: unless-stopped + networks: + - shared volumes: - ./volumes/lightning:/app/.lnd - ./volumes/thunderhub/.env:/app/.env @@ -103,15 +136,13 @@ services: depends_on: lnd: condition: service_healthy + logging: + driver: 'json-file' + options: + max-size: '100m' + max-file: '3' - nginx: - image: nginx:1.25.3-perl - restart: always - volumes: - - ./volumes/lightning:/app/.lnd - - ./volumes/nginx/default.conf:/etc/nginx/conf.d/default.conf - ports: - - '443:443' - depends_on: - - lnbits - - thunderhub +networks: + shared: + external: true + name: lightning-network diff --git a/infrastructure/config/docker/prd-docker-compose-nginx.yml b/infrastructure/config/docker/prd-docker-compose-nginx.yml new file mode 100644 index 00000000..eee1fc0f --- /dev/null +++ b/infrastructure/config/docker/prd-docker-compose-nginx.yml @@ -0,0 +1,24 @@ +name: 'network' + +services: + nginx: + image: nginx:1.25.5-perl + restart: unless-stopped + networks: + - shared + volumes: + - ./volumes/lightning:/app/.lnd + - ./volumes/nginx/default.conf:/etc/nginx/conf.d/default.conf + ports: + - '443:443' + - '9006:9006' + logging: + driver: 'json-file' + options: + max-size: '100m' + max-file: '3' + +networks: + shared: + external: true + name: lightning-network diff --git a/infrastructure/config/lightning/dev-lnd.conf b/infrastructure/config/lightning/dev-lnd.conf index b16b6186..fb2cbece 100644 --- a/infrastructure/config/lightning/dev-lnd.conf +++ b/infrastructure/config/lightning/dev-lnd.conf @@ -2,6 +2,7 @@ debuglevel=debug rpclisten=0.0.0.0:10009 restlisten=0.0.0.0:8080 + nolisten=true maxpendingchannels=0 @@ -35,3 +36,6 @@ bitcoind.rpcpass=[RPC-PASSWORD] bitcoind.zmqpubrawblock=tcp://bitcoind:28332 bitcoind.zmqpubrawtx=tcp://bitcoind:28333 + +[protocol] +protocol.wumbo-channels=true diff --git a/infrastructure/config/lightning/prd-pwd.txt b/infrastructure/config/lightning/prd-pwd.txt new file mode 100644 index 00000000..979878ab --- /dev/null +++ b/infrastructure/config/lightning/prd-pwd.txt @@ -0,0 +1 @@ +[PASSWORD] \ No newline at end of file diff --git a/infrastructure/config/lnbits/dev.env b/infrastructure/config/lnbits/dev.env index 058131bf..4490e20b 100644 --- a/infrastructure/config/lnbits/dev.env +++ b/infrastructure/config/lnbits/dev.env @@ -29,15 +29,15 @@ LNBITS_SITE_DESCRIPTION="Lightning custodial service brought to you by lightning LNBITS_THEME_OPTIONS="classic, bitcoin, flamingo, freedom, mint, autumn, monochrome, salvador, cyber" LNBITS_BACKEND_WALLET_CLASS=LndWallet -LIGHTNING_INVOICE_EXPIRY=600 +LIGHTNING_INVOICE_EXPIRY=86400 # LndWallet LND_GRPC_ENDPOINT=lnd LND_GRPC_PORT=10009 LND_GRPC_CERT="/app/.lnd/tls.cert" -LND_GRPC_MACAROON="/app/.lnd/data/chain/bitcoin/testnet/admin.macaroon" +LND_GRPC_MACAROON="/app/.lnd/data/chain/bitcoin/mainnet/admin.macaroon" # LndRestWallet LND_REST_ENDPOINT=lnd:8080/ LND_REST_CERT="/app/.lnd/tls.cert" -LND_REST_MACAROON="/app/.lnd/data/chain/bitcoin/testnet/admin.macaroon" +LND_REST_MACAROON="/app/.lnd/data/chain/bitcoin/mainnet/admin.macaroon" diff --git a/infrastructure/config/lnbits/prd.env b/infrastructure/config/lnbits/prd.env index eea19c7c..4490e20b 100644 --- a/infrastructure/config/lnbits/prd.env +++ b/infrastructure/config/lnbits/prd.env @@ -29,7 +29,7 @@ LNBITS_SITE_DESCRIPTION="Lightning custodial service brought to you by lightning LNBITS_THEME_OPTIONS="classic, bitcoin, flamingo, freedom, mint, autumn, monochrome, salvador, cyber" LNBITS_BACKEND_WALLET_CLASS=LndWallet -LIGHTNING_INVOICE_EXPIRY=600 +LIGHTNING_INVOICE_EXPIRY=86400 # LndWallet LND_GRPC_ENDPOINT=lnd diff --git a/infrastructure/config/nginx/dev-default.conf b/infrastructure/config/nginx/dev-default.conf index 9513c5f7..4c649184 100644 --- a/infrastructure/config/nginx/dev-default.conf +++ b/infrastructure/config/nginx/dev-default.conf @@ -1,3 +1,8 @@ +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} + server { listen 443 ssl; listen [::]:443 ssl; @@ -11,3 +16,69 @@ server { proxy_pass http://thunderhub:3000; } } + +server { + listen 9006 ssl; + listen [::]:9006 ssl; + + ssl_certificate /app/.lnd/tls.cert; + ssl_certificate_key /app/.lnd/tls.key; + + add_header 'Access-Control-Allow-Origin' '*' always; + add_header 'Access-Control-Allow-Headers' '*' always; + add_header 'Access-Control-Allow-Methods' 'GET, PATCH, POST, DELETE, OPTIONS' always; + add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;" always; + + if ($request_method = OPTIONS) { + return 200; + } + + location /v2/ws { + proxy_pass http://backend:9004/; + + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $remote_addr; + } + + location /streamswapstatus { + proxy_pass http://backend:9005; + + proxy_http_version 1.1; + proxy_set_header Connection ''; + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 24h; + proxy_set_header X-Forwarded-For $remote_addr; + keepalive_timeout 3600; + + chunked_transfer_encoding off; + } + + location ~ ^/v2/swap/[^/]+/stats/[^/]+/[^/]+$ { + proxy_pass http://backend:9005; + } + + location ~ ^/v2/swap/rescue { + proxy_pass http://backend:9005; + } + + location ~ ^/v2/swap/restore { + proxy_pass http://backend:9005; + } + + location /v2/lightning/ { + proxy_pass http://backend:9005; + } + location ~ ^/v2/quote { + proxy_pass http://backend:9005; + } + + location / { + proxy_pass http://backend:9001; + + proxy_hide_header Content-Security-Policy; + } +} diff --git a/infrastructure/config/nginx/prd-default.conf b/infrastructure/config/nginx/prd-default.conf index 9d42f734..3fddd710 100644 --- a/infrastructure/config/nginx/prd-default.conf +++ b/infrastructure/config/nginx/prd-default.conf @@ -1,3 +1,8 @@ +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} + server { listen 443 ssl; listen [::]:443 ssl; @@ -11,3 +16,69 @@ server { proxy_pass http://thunderhub:4000; } } + +server { + listen 9006 ssl; + listen [::]:9006 ssl; + + ssl_certificate /app/.lnd/tls.cert; + ssl_certificate_key /app/.lnd/tls.key; + + add_header 'Access-Control-Allow-Origin' '*' always; + add_header 'Access-Control-Allow-Headers' '*' always; + add_header 'Access-Control-Allow-Methods' 'GET, PATCH, POST, DELETE, OPTIONS' always; + add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;" always; + + if ($request_method = OPTIONS) { + return 200; + } + + location /v2/ws { + proxy_pass http://backend:9004/; + + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $remote_addr; + } + + location /streamswapstatus { + proxy_pass http://backend:9005; + + proxy_http_version 1.1; + proxy_set_header Connection ''; + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 24h; + proxy_set_header X-Forwarded-For $remote_addr; + keepalive_timeout 3600; + + chunked_transfer_encoding off; + } + + location ~ ^/v2/swap/[^/]+/stats/[^/]+/[^/]+$ { + proxy_pass http://backend:9005; + } + + location ~ ^/v2/swap/rescue { + proxy_pass http://backend:9005; + } + + location ~ ^/v2/swap/restore { + proxy_pass http://backend:9005; + } + + location /v2/lightning/ { + proxy_pass http://backend:9005; + } + location ~ ^/v2/quote { + proxy_pass http://backend:9005; + } + + location / { + proxy_pass http://backend:9001; + + proxy_hide_header Content-Security-Policy; + } +} diff --git a/infrastructure/config/taproot/dev-tapd.conf b/infrastructure/config/taproot/dev-tapd.conf index ab3d5846..24e51638 100644 --- a/infrastructure/config/taproot/dev-tapd.conf +++ b/infrastructure/config/taproot/dev-tapd.conf @@ -1,9 +1,9 @@ -debuglevel=trace -network=testnet +debuglevel=info +network=mainnet lnd.host=lnd:10009 -lnd.macaroonpath=/home/tap/.lnd/data/chain/bitcoin/testnet/admin.macaroon +lnd.macaroonpath=/home/tap/.lnd/data/chain/bitcoin/mainnet/admin.macaroon lnd.tlspath=/home/tap/.lnd/tls.cert -rpclisten=127.0.0.1:10029 -restlisten=127.0.0.1:8089 +rpclisten=0.0.0.0:10029 +restlisten=0.0.0.0:8089 diff --git a/infrastructure/config/thunderhub/dev-accounts.yml b/infrastructure/config/thunderhub/dev-accounts.yml index a8f448f6..f666deca 100644 --- a/infrastructure/config/thunderhub/dev-accounts.yml +++ b/infrastructure/config/thunderhub/dev-accounts.yml @@ -1,6 +1,6 @@ accounts: - name: [NAME] serverUrl: lnd:10009 - macaroonPath: /app/.lnd/data/chain/bitcoin/testnet/admin.macaroon + macaroonPath: /app/.lnd/data/chain/bitcoin/mainnet/admin.macaroon certificatePath: /app/.lnd/tls.cert password: [PASSWORD] diff --git a/infrastructure/config/thunderhub/dev.env b/infrastructure/config/thunderhub/dev.env index d8c8c479..52d50e92 100644 --- a/infrastructure/config/thunderhub/dev.env +++ b/infrastructure/config/thunderhub/dev.env @@ -10,7 +10,7 @@ ACCOUNT_CONFIG_PATH='/app/accounts.yml' SSO_SERVER_URL='lnd:10009' SSO_CERT_PATH="/app/.lnd/tls.cert" -SSO_MACAROON_PATH="/app/.lnd/data/chain/bitcoin/testnet" +SSO_MACAROON_PATH="/app/.lnd/data/chain/bitcoin/mainnet" TLS_KEY_PATH="/app/.lnd/tls.key" TLS_CERT_PATH="/app/.lnd/tls.cert" diff --git a/infrastructure/scripts/dev-docker-compose.sh b/infrastructure/scripts/dev-docker-compose.sh deleted file mode 100644 index e599aadf..00000000 --- a/infrastructure/scripts/dev-docker-compose.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/bash - -cat << EOF > .env -MACAROON=$(xxd -ps -u -c 1000 volumes/lightning/data/chain/bitcoin/testnet/admin.macaroon) -EOF - -docker compose up -d diff --git a/infrastructure/scripts/dev-runBackup-exclude-file.txt b/infrastructure/scripts/dev-runBackup-exclude-file.txt deleted file mode 100644 index b071109e..00000000 --- a/infrastructure/scripts/dev-runBackup-exclude-file.txt +++ /dev/null @@ -1,3 +0,0 @@ -./volumes/bitcoin/testnet3/blocks -./volumes/bitcoin/testnet3/chainstate -./volumes/bitcoin/testnet3/indexes diff --git a/infrastructure/scripts/prd-docker-compose.sh b/infrastructure/scripts/docker-compose.sh similarity index 71% rename from infrastructure/scripts/prd-docker-compose.sh rename to infrastructure/scripts/docker-compose.sh index 9beb6d0f..40209a4e 100644 --- a/infrastructure/scripts/prd-docker-compose.sh +++ b/infrastructure/scripts/docker-compose.sh @@ -4,4 +4,4 @@ cat << EOF > .env MACAROON=$(xxd -ps -u -c 1000 volumes/lightning/data/chain/bitcoin/mainnet/admin.macaroon) EOF -docker compose up -d +docker compose -f docker-compose-lightning.yml up -d diff --git a/infrastructure/scripts/prd-runBackup-exclude-file.txt b/infrastructure/scripts/runBackup-exclude-file.txt similarity index 100% rename from infrastructure/scripts/prd-runBackup-exclude-file.txt rename to infrastructure/scripts/runBackup-exclude-file.txt diff --git a/infrastructure/scripts/setupEnv.sh b/infrastructure/scripts/setupEnv.sh index a73a0b82..ad9fe81c 100644 --- a/infrastructure/scripts/setupEnv.sh +++ b/infrastructure/scripts/setupEnv.sh @@ -2,18 +2,19 @@ cd ~ mkdir backup -mkdir volumes -cd ~/volumes -mkdir bitcoin -mkdir lightning -mkdir taproot -mkdir lnbits -mkdir lnbitsapi -mkdir thunderhub -mkdir nginx +mkdir -p volumes/bitcoin +mkdir -p volumes/lightning +mkdir -p volumes/taproot +mkdir -p volumes/lnbits +mkdir -p volumes/lnbitsapi +mkdir -p volumes/thunderhub +mkdir -p volumes/nginx -cd ~ +mkdir -p volumes/boltz/postgres +mkdir -p volumes/boltz/redis +mkdir -p volumes/boltz/backend +mkdir -p volumes/boltz/webapp sudo apt install wget sudo apt install iputils-ping From dfc9abe4961377d006c61bfd80a8fface480298d Mon Sep 17 00:00:00 2001 From: bernd2022 <104787072+bernd2022@users.noreply.github.com> Date: Tue, 18 Nov 2025 11:53:39 +0100 Subject: [PATCH 03/11] [DEV-4476] Citrea monitoring (#88) * [DEV-4476] Citrea monitoring * [DEV-4476] Changed env to EVM_WALLET_SEED --- .../1763453659323-addCitreaMonitoring.js | 14 +++++ src/config/config.ts | 9 +++- .../blockchain/blockchain.module.ts | 2 + .../blockchain/citrea/citrea-client.ts | 27 ++++++++++ .../blockchain/citrea/citrea.module.ts | 12 +++++ .../blockchain/citrea/citrea.service.ts | 26 ++++++++++ .../blockchain/rootstock/rootstock-client.ts | 2 +- .../blockchain/shared/evm/evm-client.ts | 2 +- src/shared/enums/blockchain.enum.ts | 1 + .../entities/monitoring-balance.entity.ts | 26 +++++++--- .../monitoring/services/monitoring.service.ts | 51 ++++++------------- 11 files changed, 126 insertions(+), 46 deletions(-) create mode 100644 migration/1763453659323-addCitreaMonitoring.js create mode 100644 src/integration/blockchain/citrea/citrea-client.ts create mode 100644 src/integration/blockchain/citrea/citrea.module.ts create mode 100644 src/integration/blockchain/citrea/citrea.service.ts diff --git a/migration/1763453659323-addCitreaMonitoring.js b/migration/1763453659323-addCitreaMonitoring.js new file mode 100644 index 00000000..eb9ff70d --- /dev/null +++ b/migration/1763453659323-addCitreaMonitoring.js @@ -0,0 +1,14 @@ +const { MigrationInterface, QueryRunner } = require("typeorm"); + +module.exports = class addCitreaMonitoring1763453659323 { + name = 'addCitreaMonitoring1763453659323' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "monitoring_balance" ADD "citreaBalance" float NOT NULL CONSTRAINT "DF_98f1eabfa79a178eacdc47fe777" DEFAULT 0`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "monitoring_balance" DROP CONSTRAINT "DF_98f1eabfa79a178eacdc47fe777"`); + await queryRunner.query(`ALTER TABLE "monitoring_balance" DROP COLUMN "citreaBalance"`); + } +} diff --git a/src/config/config.ts b/src/config/config.ts index d839ad44..a04b0b52 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -152,8 +152,15 @@ export class Configuration { gatewayUrl: process.env.ROOTSTOCK_GATEWAY_URL ?? '', apiKey: process.env.ALCHEMY_API_KEY ?? '', chainId: +(process.env.ROOTSTOCK_CHAIN_ID ?? -1), - walletSeed: process.env.ROOTSTOCK_WALLET_SEED ?? '', }, + citrea: { + gatewayUrl: process.env.CITREA_GATEWAY_URL ?? '', + chainId: +(process.env.CITREA_CHAIN_ID ?? -1), + }, + }; + + evm = { + walletSeed: process.env.EVM_WALLET_SEED ?? '', }; alchemy = { diff --git a/src/integration/blockchain/blockchain.module.ts b/src/integration/blockchain/blockchain.module.ts index 826d4cd6..5f57e745 100644 --- a/src/integration/blockchain/blockchain.module.ts +++ b/src/integration/blockchain/blockchain.module.ts @@ -2,6 +2,7 @@ import { Module } from '@nestjs/common'; import { ArbitrumModule } from './arbitrum/arbitrum.module'; import { BaseModule } from './base/base.module'; import { BitcoinModule } from './bitcoin/bitcoin.module'; +import { CitreaModule } from './citrea/citrea.module'; import { EthereumModule } from './ethereum/ethereum.module'; import { LightningModule } from './lightning/lightning.module'; import { OptimismModule } from './optimism/optimism.module'; @@ -21,6 +22,7 @@ import { UmaModule } from './uma/uma.module'; PolygonModule, BaseModule, RootstockModule, + CitreaModule, ], controllers: [], providers: [CryptoService], diff --git a/src/integration/blockchain/citrea/citrea-client.ts b/src/integration/blockchain/citrea/citrea-client.ts new file mode 100644 index 00000000..a4025473 --- /dev/null +++ b/src/integration/blockchain/citrea/citrea-client.ts @@ -0,0 +1,27 @@ +import { Config } from 'src/config/config'; +import { EvmUtil } from 'src/subdomains/evm/evm.util'; +import { AssetTransferEntity } from 'src/subdomains/master-data/asset/entities/asset-transfer.entity'; +import { LightningHelper } from '../lightning/lightning-helper'; +import { EvmTokenBalance } from '../shared/evm/dto/evm-token-balance.dto'; +import { EvmClient, EvmClientParams } from '../shared/evm/evm-client'; + +export class CitreaClient extends EvmClient { + constructor(private readonly params: EvmClientParams) { + super(params); + } + + async getNativeCoinBalance(): Promise { + const walletAddress = EvmUtil.createWallet({ seed: Config.evm.walletSeed, index: 0 }).address; + + const balance = await this.provider.getBalance(walletAddress); + return LightningHelper.btcToSat(EvmUtil.fromWeiAmount(balance.toString())); + } + + async getTokenBalance(_asset: AssetTransferEntity): Promise { + throw new Error('Method not implemented.'); + } + + async getTokenBalances(_assets: AssetTransferEntity[]): Promise { + throw new Error('Method not implemented.'); + } +} diff --git a/src/integration/blockchain/citrea/citrea.module.ts b/src/integration/blockchain/citrea/citrea.module.ts new file mode 100644 index 00000000..a5672f25 --- /dev/null +++ b/src/integration/blockchain/citrea/citrea.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; +import { SharedModule } from 'src/shared/shared.module'; +import { AlchemyModule } from 'src/subdomains/alchemy/alchemy.module'; +import { EvmRegistryModule } from '../shared/evm/registry/evm-registry.module'; +import { CitreaService } from './citrea.service'; + +@Module({ + imports: [SharedModule, EvmRegistryModule, AlchemyModule], + providers: [CitreaService], + exports: [], +}) +export class CitreaModule {} diff --git a/src/integration/blockchain/citrea/citrea.service.ts b/src/integration/blockchain/citrea/citrea.service.ts new file mode 100644 index 00000000..debe0c16 --- /dev/null +++ b/src/integration/blockchain/citrea/citrea.service.ts @@ -0,0 +1,26 @@ +import { Injectable } from '@nestjs/common'; +import { GetConfig } from 'src/config/config'; +import { Blockchain } from 'src/shared/enums/blockchain.enum'; +import { HttpService } from 'src/shared/services/http.service'; +import { AlchemyService } from 'src/subdomains/alchemy/services/alchemy.service'; +import { EvmService } from '../shared/evm/evm.service'; +import { CitreaClient } from './citrea-client'; + +@Injectable() +export class CitreaService extends EvmService { + constructor(http: HttpService, alchemyService: AlchemyService) { + const { gatewayUrl, chainId } = GetConfig().blockchain.citrea; + + super(CitreaClient, { + http: http, + alchemyService, + gatewayUrl, + apiKey: '', + chainId, + }); + } + + get blockchain(): Blockchain { + return Blockchain.CITREA; + } +} diff --git a/src/integration/blockchain/rootstock/rootstock-client.ts b/src/integration/blockchain/rootstock/rootstock-client.ts index 88fbee3d..0a551e00 100644 --- a/src/integration/blockchain/rootstock/rootstock-client.ts +++ b/src/integration/blockchain/rootstock/rootstock-client.ts @@ -16,7 +16,7 @@ export class RootstockClient extends EvmClient { const url = `${this.params.gatewayUrl}/${this.params.apiKey ?? ''}`; - const walletAddress = EvmUtil.createWallet({ seed: Config.blockchain.rootstock.walletSeed, index: 0 }).address; + const walletAddress = EvmUtil.createWallet({ seed: Config.evm.walletSeed, index: 0 }).address; const balanceResult = await http .post<{ result: number }>(url, { diff --git a/src/integration/blockchain/shared/evm/evm-client.ts b/src/integration/blockchain/shared/evm/evm-client.ts index cd3c9033..222cf6e1 100644 --- a/src/integration/blockchain/shared/evm/evm-client.ts +++ b/src/integration/blockchain/shared/evm/evm-client.ts @@ -21,7 +21,7 @@ export abstract class EvmClient { private readonly alchemyService: AlchemyService; private readonly chainId: number; - private readonly provider: ethers.providers.JsonRpcProvider; + protected readonly provider: ethers.providers.JsonRpcProvider; private readonly tokens = new AsyncCache(); constructor(params: EvmClientParams) { diff --git a/src/shared/enums/blockchain.enum.ts b/src/shared/enums/blockchain.enum.ts index d227756d..32455de9 100644 --- a/src/shared/enums/blockchain.enum.ts +++ b/src/shared/enums/blockchain.enum.ts @@ -7,4 +7,5 @@ export enum Blockchain { POLYGON = 'polygon', BASE = 'base', ROOTSTOCK = 'rootstock', + CITREA = 'citrea', } diff --git a/src/subdomains/monitoring/entities/monitoring-balance.entity.ts b/src/subdomains/monitoring/entities/monitoring-balance.entity.ts index e39d38dc..b8b289cb 100644 --- a/src/subdomains/monitoring/entities/monitoring-balance.entity.ts +++ b/src/subdomains/monitoring/entities/monitoring-balance.entity.ts @@ -5,6 +5,14 @@ import { Price } from 'src/subdomains/support/dto/price.dto'; import { LightningWalletTotalBalanceDto } from 'src/subdomains/user/application/dto/lightning-wallet.dto'; import { Column, Entity, ManyToOne } from 'typeorm'; +export interface MonitoringBlockchainBalance { + onchainBalance: number; + lndOnchainBalance: number; + lightningBalance: number; + rootstockBalance: number; + citreaBalance: number; +} + @Entity('monitoring_balance') export class MonitoringBalanceEntity extends IEntity { @ManyToOne(() => AssetAccountEntity, { eager: true }) @@ -22,6 +30,9 @@ export class MonitoringBalanceEntity extends IEntity { @Column({ type: 'float', default: 0 }) rootstockBalance: number; + @Column({ type: 'float', default: 0 }) + citreaBalance: number; + @Column({ type: 'float', default: 0 }) customerBalance: number; @@ -37,10 +48,7 @@ export class MonitoringBalanceEntity extends IEntity { // --- FACTORY METHODS --- // static createAsBtcEntity( - onchainBalance: number, - lndOnchainBalance: number, - lightningBalance: number, - rootstockBalance: number, + blockchainBalance: MonitoringBlockchainBalance, internalBalance: LightningWalletTotalBalanceDto, customerBalance: LightningWalletTotalBalanceDto, chfPrice: Price, @@ -48,10 +56,11 @@ export class MonitoringBalanceEntity extends IEntity { const entity = new MonitoringBalanceEntity(); entity.asset = { id: customerBalance.assetId } as AssetAccountEntity; - entity.onchainBalance = onchainBalance; - entity.lndOnchainBalance = lndOnchainBalance; - entity.lightningBalance = lightningBalance; - entity.rootstockBalance = rootstockBalance; + entity.onchainBalance = blockchainBalance.onchainBalance; + entity.lndOnchainBalance = blockchainBalance.lndOnchainBalance; + entity.lightningBalance = blockchainBalance.lightningBalance; + entity.rootstockBalance = blockchainBalance.rootstockBalance; + entity.citreaBalance = blockchainBalance.citreaBalance; entity.customerBalance = customerBalance.totalBalance; entity.ldsBalance = @@ -59,6 +68,7 @@ export class MonitoringBalanceEntity extends IEntity { entity.lndOnchainBalance + entity.lightningBalance + entity.rootstockBalance + + entity.citreaBalance + internalBalance.totalBalance - entity.customerBalance; diff --git a/src/subdomains/monitoring/services/monitoring.service.ts b/src/subdomains/monitoring/services/monitoring.service.ts index 0cad920b..7776175b 100644 --- a/src/subdomains/monitoring/services/monitoring.service.ts +++ b/src/subdomains/monitoring/services/monitoring.service.ts @@ -1,6 +1,7 @@ import { Injectable, InternalServerErrorException, OnModuleInit } from '@nestjs/common'; import { BitcoinClient } from 'src/integration/blockchain/bitcoin/bitcoin-client'; import { BitcoinService } from 'src/integration/blockchain/bitcoin/bitcoin.service'; +import { CitreaClient } from 'src/integration/blockchain/citrea/citrea-client'; import { LndChannelDto } from 'src/integration/blockchain/lightning/dto/lnd.dto'; import { LightningClient } from 'src/integration/blockchain/lightning/lightning-client'; import { LightningService } from 'src/integration/blockchain/lightning/services/lightning.service'; @@ -12,7 +13,7 @@ import { QueueHandler } from 'src/shared/utils/queue-handler'; import { AssetService } from 'src/subdomains/master-data/asset/services/asset.service'; import { CoinGeckoService } from 'src/subdomains/pricing/services/coingecko.service'; import { LightningWalletTotalBalanceDto } from 'src/subdomains/user/application/dto/lightning-wallet.dto'; -import { MonitoringBalanceEntity } from '../entities/monitoring-balance.entity'; +import { MonitoringBalanceEntity, MonitoringBlockchainBalance } from '../entities/monitoring-balance.entity'; import { MonitoringBalanceRepository } from '../repositories/monitoring-balance.repository'; import { MonitoringRepository } from '../repositories/monitoring.repository'; @@ -23,6 +24,7 @@ export class MonitoringService implements OnModuleInit { private readonly bitcoinClient: BitcoinClient; private readonly lightningClient: LightningClient; private rootstockClient: RootstockClient; + private citreaClient: CitreaClient; private readonly processBalancesQueue: QueueHandler; @@ -43,6 +45,7 @@ export class MonitoringService implements OnModuleInit { onModuleInit() { this.rootstockClient = this.evmRegistryService.getClient(Blockchain.ROOTSTOCK) as RootstockClient; + this.citreaClient = this.evmRegistryService.getClient(Blockchain.CITREA) as CitreaClient; } // --- LIGHTNING --- // @@ -66,10 +69,7 @@ export class MonitoringService implements OnModuleInit { customerBalances: LightningWalletTotalBalanceDto[], ): Promise { try { - const onchainBalance = await this.getOnchainBalance(); - const lndOnchainBalance = await this.getLndOnchainBalance(); - const lightningBalance = await this.getLightningBalance(); - const rootstockBalance = await this.getRootstockBalance(); + const blockchainBalance = await this.getBlockchainBalances(); const btcAccountAsset = await this.assetService.getBtcAccountAssetOrThrow(); const btcAccountAssetId = btcAccountAsset.id; @@ -86,14 +86,7 @@ export class MonitoringService implements OnModuleInit { const customerFiatBalances = customerBalances.filter((b) => b.assetId !== btcAccountAssetId); - await this.processBtcBalance( - onchainBalance, - lndOnchainBalance, - lightningBalance, - rootstockBalance, - internalBtcBalance, - customerBtcBalance, - ); + await this.processBtcBalance(blockchainBalance, internalBtcBalance, customerBtcBalance); await this.processFiatBalances(customerFiatBalances); } catch (e) { this.logger.error('Error while processing balances', e); @@ -119,10 +112,7 @@ export class MonitoringService implements OnModuleInit { } private async processBtcBalance( - onchainBalance: number, - lndOnchainBalance: number, - lightningBalance: number, - rootstockBalance: number, + blockchainBalance: MonitoringBlockchainBalance, internalBtcBalance: LightningWalletTotalBalanceDto, customerBtcBalance: LightningWalletTotalBalanceDto, ) { @@ -130,10 +120,7 @@ export class MonitoringService implements OnModuleInit { if (!chfPrice.isValid) throw new InternalServerErrorException(`Invalid price from BTC to CHF`); const btcMonitoringEntity = MonitoringBalanceEntity.createAsBtcEntity( - onchainBalance, - lndOnchainBalance, - lightningBalance, - rootstockBalance, + blockchainBalance, internalBtcBalance, customerBtcBalance, chfPrice, @@ -169,20 +156,14 @@ export class MonitoringService implements OnModuleInit { return balance; } - private async getOnchainBalance(): Promise { - return this.bitcoinClient.getWalletBalance(); - } - - private async getLndOnchainBalance(): Promise { - return this.lightningClient.getLndConfirmedWalletBalance(); - } - - private async getLightningBalance(): Promise { - return this.lightningClient.getLndLightningBalance(); - } - - private async getRootstockBalance(): Promise { - return this.rootstockClient.getNativeCoinBalance(); + private async getBlockchainBalances(): Promise { + return { + onchainBalance: await this.bitcoinClient.getWalletBalance(), + lndOnchainBalance: await this.lightningClient.getLndConfirmedWalletBalance(), + lightningBalance: await this.lightningClient.getLndLightningBalance(), + rootstockBalance: await this.rootstockClient.getNativeCoinBalance(), + citreaBalance: await this.citreaClient.getNativeCoinBalance(), + }; } private async getChannels(): Promise { From 6d2e586b28aeb36a85c793a67589f0e177084f3b Mon Sep 17 00:00:00 2001 From: bernd2022 <104787072+bernd2022@users.noreply.github.com> Date: Mon, 24 Nov 2025 10:52:20 +0100 Subject: [PATCH 04/11] [DEV-4498] Boltz ERC-20 swaps (#89) --- .../config/boltz/backend/dev-boltz.conf | 149 +++++++++++++++--- .../config/boltz/backend/prd-boltz.conf | 149 +++++++++++++++--- 2 files changed, 246 insertions(+), 52 deletions(-) diff --git a/infrastructure/config/boltz/backend/dev-boltz.conf b/infrastructure/config/boltz/backend/dev-boltz.conf index 5c1d50ad..99ba8764 100644 --- a/infrastructure/config/boltz/backend/dev-boltz.conf +++ b/infrastructure/config/boltz/backend/dev-boltz.conf @@ -49,7 +49,7 @@ network = "bitcoinMainnet" # Wallet balances - adjusted for testing minWalletBalance = 100_000 # 0.001 BTC (100k sats) -minChannelBalance = 100_000 # 0.001 BTC (100k sats) +minChannelBalance = 100_000 # 0.001 BTC (100k sats) # Swap limits maxSwapAmount = 10_000_000 # 0.1 BTC maximum @@ -85,15 +85,13 @@ maxZeroConfAmount = 0 # Disable 0-conf for security [[pairs]] base = "BTC" quote = "BTC" -rate = 1 # 1:1 exchange rate - -# Fee configuration (in percent) -fee = 0.5 # 0.5% service fee -swapInFee = 0.25 # 0.25% for submarine swaps (chain -> lightning) +rate = 1 +fee = 0.5 # 0.5% service fee +swapInFee = 0.25 # 0.25% for submarine swaps (chain -> lightning) # Swap amount limits (in satoshis) -maxSwapAmount = 10_000_000 # 0.1 BTC -minSwapAmount = 2_500 # 2,500 sats (pair level) +maxSwapAmount = 10_000_000 # 0.1 BTC +minSwapAmount = 2_500 # 2,500 sats (pair level) # Submarine Swap specific settings (Chain -> Lightning) [pairs.submarineSwap] @@ -115,36 +113,135 @@ minSwapAmount = 2_500 # 2,500 sats (pair level) [[pairs]] base = "BTC" quote = "RBTC" -rate = 1 # 1:1 peg between BTC and RBTC - -# Fee configuration (in percent) +rate = 1 fee = 0.25 swapInFee = 0.1 # Swap amount limits (in satoshis) -maxSwapAmount = 10_000_000 # 0.1 BTC/RBTC -minSwapAmount = 2_500 # 2,500 sats minimum (Rootstock has lower fees) +maxSwapAmount = 10_000_000 # 0.1 BTC/RBTC +minSwapAmount = 2_500 # 2,500 sats minimum (Rootstock has lower fees) + + [pairs.timeoutDelta] + chain = 1440 # Chain swap timeout (~24 hours = 144 blocks) + reverse = 1440 # ~24 hours for reverse swaps (lightning -> chain) + swapMinimal = 1440 # Minimum timeout for submarine swaps (~24 hours = 144 blocks) + swapMaximal = 2880 # Maximum timeout (~48 hours = 288 blocks) + swapTaproot = 10080 # 1 week for taproot swaps (10080 blocks) + +[[pairs]] +base = "BTC" +quote = "cBTC" +rate = 1 +fee = 0.25 +swapInFee = 0.1 + +maxSwapAmount = 10_000_000 # 0.1 BTC/cBTC +minSwapAmount = 2_500 # 2,500 sats minimum (Citrea Testnet has low fees) + + [pairs.timeoutDelta] + chain = 60 # Chain swap timeout (~1 hour, due to fast 2s blocks) + reverse = 180 # Reverse swap timeout (Lightning -> cBTC) - increased for CLTV requirements + swapMinimal = 1440 # Minimum timeout (~13.3 hours) - minimum for Lightning CLTV (80 blocks × 10 min) + swapMaximal = 2880 # Maximum timeout (~16.7 hours) - allows 100 Bitcoin blocks CLTV + swapTaproot = 10080 # Taproot timeout (~16.7 hours) + +[[pairs]] +base = "USDT_ETH" +quote = "USDT_CITREA" +rate = 1 +fee = 0.25 +swapInFee = 0.1 + +maxSwapAmount = 1_000_000_000 # 1000 USDT_ETH/USDT_CITREA +minSwapAmount = 1_000_000 # 1 USDT_ETH/USDT_CITREA + + [pairs.timeoutDelta] + chain = 1440 # Chain swap timeout (~24 hours = 144 blocks) + reverse = 1440 # ~24 hours for reverse swaps (lightning -> chain) + swapMinimal = 1440 # Minimum timeout for submarine swaps (~24 hours = 144 blocks) + swapMaximal = 2880 # Maximum timeout (~48 hours = 288 blocks) + swapTaproot = 10080 # 1 week for taproot swaps (10080 blocks) + +[[pairs]] +base = "USDT_POLYGON" +quote = "USDT_CITREA" +rate = 1 +fee = 0.25 +swapInFee = 0.1 + +maxSwapAmount = 1_000_000_000 # 1000 USDT_POLYGON/USDT_CITREA +minSwapAmount = 1_000_000 # 1 USDT_POLYGON/USDT_CITREA [pairs.timeoutDelta] - chain = 1440 # Chain swap timeout (~24 hours) - reverse = 1440 # Reverse swap timeout (Lightning -> RBTC) - swapMinimal = 1440 # Minimum timeout - swapMaximal = 2880 # Maximum timeout - swapTaproot = 10080 + chain = 1440 # Chain swap timeout (~24 hours = 144 blocks) + reverse = 1440 # ~24 hours for reverse swaps (lightning -> chain) + swapMinimal = 1440 # Minimum timeout for submarine swaps (~24 hours = 144 blocks) + swapMaximal = 2880 # Maximum timeout (~48 hours = 288 blocks) + swapTaproot = 10080 # 1 week for taproot swaps (10080 blocks) # RSK (Rootstock) Configuration [rsk] networkName = "RSK Mainnet" providerEndpoint = "[PROVIDER_ENDPOINT]" - [[rsk.contracts]] - etherSwap = "0x3d9cc5780CA1db78760ad3D35458509178A85A4A" - erc20Swap = "0x7d5a2187CC8EF75f8822daB0E8C9a2DB147BA045" + [[rsk.contracts]] + etherSwap = "0x3d9cc5780CA1db78760ad3D35458509178A85A4A" + erc20Swap = "0x7d5a2187CC8EF75f8822daB0E8C9a2DB147BA045" + + [[rsk.tokens]] + symbol = "RBTC" + + minWalletBalance = 10_000 + +# ETH (Ethereum) Configuration +[ethereum] +networkName = "Ethereum Mainnet" +providerEndpoint = "[PROVIDER_ENDPOINT]" + + [[ethereum.contracts]] + etherSwap = "0x9ADfB0F1B783486289Fc23f3A3Ad2927cebb17e4" + erc20Swap = "0x2E21F58Da58c391F110467c7484EdfA849C1CB9B" + + [[ethereum.tokens]] + symbol = "USDT_ETH" + decimals = 6 + contractAddress = "0xdAC17F958D2ee523a2206206994597C13D831ec7" + + minWalletBalance = 1_000_000 # 1 USDT_ETH + +# POL (Polygon) Configuration +[polygon] +networkName = "Polygon Mainnet" +providerEndpoint = "[PROVIDER_ENDPOINT]" + + [[polygon.contracts]] + etherSwap = "0x9ADfB0F1B783486289Fc23f3A3Ad2927cebb17e4" + erc20Swap = "0x2E21F58Da58c391F110467c7484EdfA849C1CB9B" + + [[polygon.tokens]] + symbol = "USDT_POLYGON" + decimals = 6 + contractAddress = "0xc2132D05D31c914a87C6611C10748AEb04B58e8F" + + minWalletBalance = 1_000_000 # 1 USDT_POLYGON + +# Citrea Testnet Configuration +[citrea] +networkName = "Citrea Testnet" +providerEndpoint = "https://dev.rpc.testnet.juiceswap.com" + + [[citrea.contracts]] + etherSwap = "0xd02731fD8c5FDD53B613A699234FAd5EE8851B65" + erc20Swap = "0xf2e019a371e5Fd32dB2fC564Ad9eAE9E433133cc" + + [[citrea.tokens]] + symbol = "cBTC" - [[rsk.tokens]] - symbol = "RBTC" + minWalletBalance = 100_000 - maxSwapAmount = 10_000_000 - minSwapAmount = 2_500 + [[citrea.tokens]] + symbol = "USDT_CITREA" + decimals = 6 + contractAddress = "0x1Dd3057888944ff1f914626aB4BD47Dc8b6285Fe" - minWalletBalance = 10_000 + minWalletBalance = 1_000_000 # 1 USDT_CITREA diff --git a/infrastructure/config/boltz/backend/prd-boltz.conf b/infrastructure/config/boltz/backend/prd-boltz.conf index 5c1d50ad..99ba8764 100644 --- a/infrastructure/config/boltz/backend/prd-boltz.conf +++ b/infrastructure/config/boltz/backend/prd-boltz.conf @@ -49,7 +49,7 @@ network = "bitcoinMainnet" # Wallet balances - adjusted for testing minWalletBalance = 100_000 # 0.001 BTC (100k sats) -minChannelBalance = 100_000 # 0.001 BTC (100k sats) +minChannelBalance = 100_000 # 0.001 BTC (100k sats) # Swap limits maxSwapAmount = 10_000_000 # 0.1 BTC maximum @@ -85,15 +85,13 @@ maxZeroConfAmount = 0 # Disable 0-conf for security [[pairs]] base = "BTC" quote = "BTC" -rate = 1 # 1:1 exchange rate - -# Fee configuration (in percent) -fee = 0.5 # 0.5% service fee -swapInFee = 0.25 # 0.25% for submarine swaps (chain -> lightning) +rate = 1 +fee = 0.5 # 0.5% service fee +swapInFee = 0.25 # 0.25% for submarine swaps (chain -> lightning) # Swap amount limits (in satoshis) -maxSwapAmount = 10_000_000 # 0.1 BTC -minSwapAmount = 2_500 # 2,500 sats (pair level) +maxSwapAmount = 10_000_000 # 0.1 BTC +minSwapAmount = 2_500 # 2,500 sats (pair level) # Submarine Swap specific settings (Chain -> Lightning) [pairs.submarineSwap] @@ -115,36 +113,135 @@ minSwapAmount = 2_500 # 2,500 sats (pair level) [[pairs]] base = "BTC" quote = "RBTC" -rate = 1 # 1:1 peg between BTC and RBTC - -# Fee configuration (in percent) +rate = 1 fee = 0.25 swapInFee = 0.1 # Swap amount limits (in satoshis) -maxSwapAmount = 10_000_000 # 0.1 BTC/RBTC -minSwapAmount = 2_500 # 2,500 sats minimum (Rootstock has lower fees) +maxSwapAmount = 10_000_000 # 0.1 BTC/RBTC +minSwapAmount = 2_500 # 2,500 sats minimum (Rootstock has lower fees) + + [pairs.timeoutDelta] + chain = 1440 # Chain swap timeout (~24 hours = 144 blocks) + reverse = 1440 # ~24 hours for reverse swaps (lightning -> chain) + swapMinimal = 1440 # Minimum timeout for submarine swaps (~24 hours = 144 blocks) + swapMaximal = 2880 # Maximum timeout (~48 hours = 288 blocks) + swapTaproot = 10080 # 1 week for taproot swaps (10080 blocks) + +[[pairs]] +base = "BTC" +quote = "cBTC" +rate = 1 +fee = 0.25 +swapInFee = 0.1 + +maxSwapAmount = 10_000_000 # 0.1 BTC/cBTC +minSwapAmount = 2_500 # 2,500 sats minimum (Citrea Testnet has low fees) + + [pairs.timeoutDelta] + chain = 60 # Chain swap timeout (~1 hour, due to fast 2s blocks) + reverse = 180 # Reverse swap timeout (Lightning -> cBTC) - increased for CLTV requirements + swapMinimal = 1440 # Minimum timeout (~13.3 hours) - minimum for Lightning CLTV (80 blocks × 10 min) + swapMaximal = 2880 # Maximum timeout (~16.7 hours) - allows 100 Bitcoin blocks CLTV + swapTaproot = 10080 # Taproot timeout (~16.7 hours) + +[[pairs]] +base = "USDT_ETH" +quote = "USDT_CITREA" +rate = 1 +fee = 0.25 +swapInFee = 0.1 + +maxSwapAmount = 1_000_000_000 # 1000 USDT_ETH/USDT_CITREA +minSwapAmount = 1_000_000 # 1 USDT_ETH/USDT_CITREA + + [pairs.timeoutDelta] + chain = 1440 # Chain swap timeout (~24 hours = 144 blocks) + reverse = 1440 # ~24 hours for reverse swaps (lightning -> chain) + swapMinimal = 1440 # Minimum timeout for submarine swaps (~24 hours = 144 blocks) + swapMaximal = 2880 # Maximum timeout (~48 hours = 288 blocks) + swapTaproot = 10080 # 1 week for taproot swaps (10080 blocks) + +[[pairs]] +base = "USDT_POLYGON" +quote = "USDT_CITREA" +rate = 1 +fee = 0.25 +swapInFee = 0.1 + +maxSwapAmount = 1_000_000_000 # 1000 USDT_POLYGON/USDT_CITREA +minSwapAmount = 1_000_000 # 1 USDT_POLYGON/USDT_CITREA [pairs.timeoutDelta] - chain = 1440 # Chain swap timeout (~24 hours) - reverse = 1440 # Reverse swap timeout (Lightning -> RBTC) - swapMinimal = 1440 # Minimum timeout - swapMaximal = 2880 # Maximum timeout - swapTaproot = 10080 + chain = 1440 # Chain swap timeout (~24 hours = 144 blocks) + reverse = 1440 # ~24 hours for reverse swaps (lightning -> chain) + swapMinimal = 1440 # Minimum timeout for submarine swaps (~24 hours = 144 blocks) + swapMaximal = 2880 # Maximum timeout (~48 hours = 288 blocks) + swapTaproot = 10080 # 1 week for taproot swaps (10080 blocks) # RSK (Rootstock) Configuration [rsk] networkName = "RSK Mainnet" providerEndpoint = "[PROVIDER_ENDPOINT]" - [[rsk.contracts]] - etherSwap = "0x3d9cc5780CA1db78760ad3D35458509178A85A4A" - erc20Swap = "0x7d5a2187CC8EF75f8822daB0E8C9a2DB147BA045" + [[rsk.contracts]] + etherSwap = "0x3d9cc5780CA1db78760ad3D35458509178A85A4A" + erc20Swap = "0x7d5a2187CC8EF75f8822daB0E8C9a2DB147BA045" + + [[rsk.tokens]] + symbol = "RBTC" + + minWalletBalance = 10_000 + +# ETH (Ethereum) Configuration +[ethereum] +networkName = "Ethereum Mainnet" +providerEndpoint = "[PROVIDER_ENDPOINT]" + + [[ethereum.contracts]] + etherSwap = "0x9ADfB0F1B783486289Fc23f3A3Ad2927cebb17e4" + erc20Swap = "0x2E21F58Da58c391F110467c7484EdfA849C1CB9B" + + [[ethereum.tokens]] + symbol = "USDT_ETH" + decimals = 6 + contractAddress = "0xdAC17F958D2ee523a2206206994597C13D831ec7" + + minWalletBalance = 1_000_000 # 1 USDT_ETH + +# POL (Polygon) Configuration +[polygon] +networkName = "Polygon Mainnet" +providerEndpoint = "[PROVIDER_ENDPOINT]" + + [[polygon.contracts]] + etherSwap = "0x9ADfB0F1B783486289Fc23f3A3Ad2927cebb17e4" + erc20Swap = "0x2E21F58Da58c391F110467c7484EdfA849C1CB9B" + + [[polygon.tokens]] + symbol = "USDT_POLYGON" + decimals = 6 + contractAddress = "0xc2132D05D31c914a87C6611C10748AEb04B58e8F" + + minWalletBalance = 1_000_000 # 1 USDT_POLYGON + +# Citrea Testnet Configuration +[citrea] +networkName = "Citrea Testnet" +providerEndpoint = "https://dev.rpc.testnet.juiceswap.com" + + [[citrea.contracts]] + etherSwap = "0xd02731fD8c5FDD53B613A699234FAd5EE8851B65" + erc20Swap = "0xf2e019a371e5Fd32dB2fC564Ad9eAE9E433133cc" + + [[citrea.tokens]] + symbol = "cBTC" - [[rsk.tokens]] - symbol = "RBTC" + minWalletBalance = 100_000 - maxSwapAmount = 10_000_000 - minSwapAmount = 2_500 + [[citrea.tokens]] + symbol = "USDT_CITREA" + decimals = 6 + contractAddress = "0x1Dd3057888944ff1f914626aB4BD47Dc8b6285Fe" - minWalletBalance = 10_000 + minWalletBalance = 1_000_000 # 1 USDT_CITREA From 3d4dc253997078afc152b22fb7352950562d95b8 Mon Sep 17 00:00:00 2001 From: bernd2022 Date: Mon, 24 Nov 2025 15:31:10 +0100 Subject: [PATCH 05/11] [NO-TASK] added swap/deferredClaimSymbols --- infrastructure/config/boltz/backend/dev-boltz.conf | 3 +++ infrastructure/config/boltz/backend/prd-boltz.conf | 3 +++ 2 files changed, 6 insertions(+) diff --git a/infrastructure/config/boltz/backend/dev-boltz.conf b/infrastructure/config/boltz/backend/dev-boltz.conf index 99ba8764..9d45819c 100644 --- a/infrastructure/config/boltz/backend/dev-boltz.conf +++ b/infrastructure/config/boltz/backend/dev-boltz.conf @@ -42,6 +42,9 @@ password = "[POSTGRES_PASSWORD]" [cache] redisEndpoint = "redis://redis:6379" +[swap] +deferredClaimSymbols = ["cBTC"] + # Bitcoin/Lightning Configuration [[currencies]] symbol = "BTC" diff --git a/infrastructure/config/boltz/backend/prd-boltz.conf b/infrastructure/config/boltz/backend/prd-boltz.conf index 99ba8764..9d45819c 100644 --- a/infrastructure/config/boltz/backend/prd-boltz.conf +++ b/infrastructure/config/boltz/backend/prd-boltz.conf @@ -42,6 +42,9 @@ password = "[POSTGRES_PASSWORD]" [cache] redisEndpoint = "redis://redis:6379" +[swap] +deferredClaimSymbols = ["cBTC"] + # Bitcoin/Lightning Configuration [[currencies]] symbol = "BTC" From 3f6613f8a1c8b1f44214af634547e2f28a126aba Mon Sep 17 00:00:00 2001 From: TaprootFreak <142087526+TaprootFreak@users.noreply.github.com> Date: Mon, 24 Nov 2025 16:23:21 +0100 Subject: [PATCH 06/11] Add L-BTC to deferred claim symbols in backend configs Added L-BTC to deferredClaimSymbols array in both dev and prod configurations to enable server-side automatic claiming for L-BTC swaps. --- infrastructure/config/boltz/backend/dev-boltz.conf | 2 +- infrastructure/config/boltz/backend/prd-boltz.conf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/infrastructure/config/boltz/backend/dev-boltz.conf b/infrastructure/config/boltz/backend/dev-boltz.conf index 9d45819c..bcc66e64 100644 --- a/infrastructure/config/boltz/backend/dev-boltz.conf +++ b/infrastructure/config/boltz/backend/dev-boltz.conf @@ -43,7 +43,7 @@ password = "[POSTGRES_PASSWORD]" redisEndpoint = "redis://redis:6379" [swap] -deferredClaimSymbols = ["cBTC"] +deferredClaimSymbols = ["L-BTC", "cBTC"] # Bitcoin/Lightning Configuration [[currencies]] diff --git a/infrastructure/config/boltz/backend/prd-boltz.conf b/infrastructure/config/boltz/backend/prd-boltz.conf index 9d45819c..bcc66e64 100644 --- a/infrastructure/config/boltz/backend/prd-boltz.conf +++ b/infrastructure/config/boltz/backend/prd-boltz.conf @@ -43,7 +43,7 @@ password = "[POSTGRES_PASSWORD]" redisEndpoint = "redis://redis:6379" [swap] -deferredClaimSymbols = ["cBTC"] +deferredClaimSymbols = ["L-BTC", "cBTC"] # Bitcoin/Lightning Configuration [[currencies]] From ccd146cc613c4756b12e4303d7d2ce5519a08eca Mon Sep 17 00:00:00 2001 From: TaprootFreak <142087526+TaprootFreak@users.noreply.github.com> Date: Mon, 24 Nov 2025 16:24:43 +0100 Subject: [PATCH 07/11] Revert: Remove L-BTC from deferredClaimSymbols Only cBTC should be in the deferred claim symbols list. --- infrastructure/config/boltz/backend/dev-boltz.conf | 2 +- infrastructure/config/boltz/backend/prd-boltz.conf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/infrastructure/config/boltz/backend/dev-boltz.conf b/infrastructure/config/boltz/backend/dev-boltz.conf index bcc66e64..9d45819c 100644 --- a/infrastructure/config/boltz/backend/dev-boltz.conf +++ b/infrastructure/config/boltz/backend/dev-boltz.conf @@ -43,7 +43,7 @@ password = "[POSTGRES_PASSWORD]" redisEndpoint = "redis://redis:6379" [swap] -deferredClaimSymbols = ["L-BTC", "cBTC"] +deferredClaimSymbols = ["cBTC"] # Bitcoin/Lightning Configuration [[currencies]] diff --git a/infrastructure/config/boltz/backend/prd-boltz.conf b/infrastructure/config/boltz/backend/prd-boltz.conf index bcc66e64..9d45819c 100644 --- a/infrastructure/config/boltz/backend/prd-boltz.conf +++ b/infrastructure/config/boltz/backend/prd-boltz.conf @@ -43,7 +43,7 @@ password = "[POSTGRES_PASSWORD]" redisEndpoint = "redis://redis:6379" [swap] -deferredClaimSymbols = ["L-BTC", "cBTC"] +deferredClaimSymbols = ["cBTC"] # Bitcoin/Lightning Configuration [[currencies]] From 75491e9ef783dcb87902b69e8758619833c44dff Mon Sep 17 00:00:00 2001 From: Danswar <48102227+Danswar@users.noreply.github.com> Date: Wed, 17 Dec 2025 11:23:23 -0300 Subject: [PATCH 08/11] [NO-TASK]: Rewrite request to Boltz claim server (#90) * [NO-TASK]: Rewrite request to Boltz claim server * Rename path --- src/config/config.ts | 4 ++++ src/main.ts | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/config/config.ts b/src/config/config.ts index a04b0b52..2aa15754 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -187,6 +187,10 @@ export class Configuration { apiUrl: process.env.SWAP_API_URL, }; + boltzClaim = { + apiUrl: process.env.BOLTZ_CLAIM_API_URL, + }; + // --- GETTERS --- // get baseUrl(): string { return this.environment === Environment.LOC diff --git a/src/main.ts b/src/main.ts index b22ac0f5..2ff72bdb 100644 --- a/src/main.ts +++ b/src/main.ts @@ -60,6 +60,25 @@ async function bootstrap() { server.on('upgrade', forwardProxy.upgrade); } + // --- REWRITE BOLTZ CLAIM URL --- // + if (Config.boltzClaim.apiUrl) { + const rewriteUrl = `/${Config.version}/claim`; + const forwardProxy = createProxyMiddleware({ + target: Config.boltzClaim.apiUrl, + changeOrigin: true, + toProxy: true, + secure: false, + pathRewrite: { [rewriteUrl]: '' }, + on: { + proxyReq(proxyReq, req: Request) { + if (req.ip) proxyReq.setHeader('X-Forwarded-For', req.ip.split(':')[0]); + fixRequestBody(proxyReq, req); + }, + }, + }); + app.use(rewriteUrl, forwardProxy); + } + // --- SWAGGER --- // const swaggerOptions = new DocumentBuilder() .setTitle('lightning.space API') From 966e35be5642a51d1ed99d3d05438eaff654567e Mon Sep 17 00:00:00 2001 From: David May Date: Wed, 17 Dec 2025 15:31:31 +0100 Subject: [PATCH 09/11] [NO-TASK] Refactoring & docker compose update --- .../docker/dev-docker-compose-boltz.yml | 22 +++++++++++++++++++ src/config/config.ts | 5 +---- src/main.ts | 10 ++------- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/infrastructure/config/docker/dev-docker-compose-boltz.yml b/infrastructure/config/docker/dev-docker-compose-boltz.yml index 896d49be..e2180adf 100644 --- a/infrastructure/config/docker/dev-docker-compose-boltz.yml +++ b/infrastructure/config/docker/dev-docker-compose-boltz.yml @@ -66,6 +66,7 @@ services: max-file: '3' environment: - NODE_EXTRA_CA_CERTS=/root/.lnd/tls.cert + webapp: image: dfxswiss/boltz-webapp:dev restart: unless-stopped @@ -87,6 +88,27 @@ services: - VITE_API_URL=http://backend:9000 - VITE_RSK_LOG_SCAN_ENDPOINT=[VITE_RSK_LOG_SCAN_ENDPOINT] + claim: + image: dfxswiss/boltz-claim:dev + restart: unless-stopped + networks: + - shared + depends_on: + - postgres + ports: + - '3001:3001' + logging: + driver: 'json-file' + options: + max-size: '100m' + max-file: '3' + environment: + - PORT=3001 + - PONDER_PROFILE=mainnet + - DATABASE_URL=postgresql://[POSTGRES_USERNAME]:[POSTGRES_PASSWORD]@postgres:5432/boltz_claim + - SIGNER_PRIVATE_KEY=[SIGNER_PRIVATE_KEY] + - RPC_PROVIDER_URL=https://rpc.testnet.juiceswap.com/ + networks: shared: external: true diff --git a/src/config/config.ts b/src/config/config.ts index 2aa15754..2fa61ba2 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -185,10 +185,7 @@ export class Configuration { swap = { apiUrl: process.env.SWAP_API_URL, - }; - - boltzClaim = { - apiUrl: process.env.BOLTZ_CLAIM_API_URL, + claimApiUrl: process.env.SWAP_CLAIM_API_URL, }; // --- GETTERS --- // diff --git a/src/main.ts b/src/main.ts index 2ff72bdb..f545b062 100644 --- a/src/main.ts +++ b/src/main.ts @@ -61,20 +61,14 @@ async function bootstrap() { } // --- REWRITE BOLTZ CLAIM URL --- // - if (Config.boltzClaim.apiUrl) { + if (Config.swap.claimApiUrl) { const rewriteUrl = `/${Config.version}/claim`; const forwardProxy = createProxyMiddleware({ - target: Config.boltzClaim.apiUrl, + target: Config.swap.claimApiUrl, changeOrigin: true, toProxy: true, secure: false, pathRewrite: { [rewriteUrl]: '' }, - on: { - proxyReq(proxyReq, req: Request) { - if (req.ip) proxyReq.setHeader('X-Forwarded-For', req.ip.split(':')[0]); - fixRequestBody(proxyReq, req); - }, - }, }); app.use(rewriteUrl, forwardProxy); } From 7f8a266c5e6d892388853b8ba6f85c40d6a3afd3 Mon Sep 17 00:00:00 2001 From: Danswar <48102227+Danswar@users.noreply.github.com> Date: Wed, 17 Dec 2025 13:46:43 -0300 Subject: [PATCH 10/11] fix: add fixRequestBody to Boltz claim proxy for POST requests (#91) --- src/main.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main.ts b/src/main.ts index f545b062..307ecc5b 100644 --- a/src/main.ts +++ b/src/main.ts @@ -69,6 +69,11 @@ async function bootstrap() { toProxy: true, secure: false, pathRewrite: { [rewriteUrl]: '' }, + on: { + proxyReq(proxyReq, req: Request) { + fixRequestBody(proxyReq, req); + }, + }, }); app.use(rewriteUrl, forwardProxy); } From a41f411fdbbe0809fcfa255768a8d82a58727ca5 Mon Sep 17 00:00:00 2001 From: David May Date: Thu, 18 Dec 2025 10:27:32 +0100 Subject: [PATCH 11/11] Fixed docker compose --- infrastructure/config/docker/dev-docker-compose-boltz.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infrastructure/config/docker/dev-docker-compose-boltz.yml b/infrastructure/config/docker/dev-docker-compose-boltz.yml index e2180adf..c6c7683f 100644 --- a/infrastructure/config/docker/dev-docker-compose-boltz.yml +++ b/infrastructure/config/docker/dev-docker-compose-boltz.yml @@ -89,7 +89,7 @@ services: - VITE_RSK_LOG_SCAN_ENDPOINT=[VITE_RSK_LOG_SCAN_ENDPOINT] claim: - image: dfxswiss/boltz-claim:dev + image: dfxswiss/boltz-claim:beta restart: unless-stopped networks: - shared