feat: add Boltz/Lightning.space adapter for Citrea cBTC liquidity#3266
Draft
TaprootFreak wants to merge 12 commits intodevelopfrom
Draft
feat: add Boltz/Lightning.space adapter for Citrea cBTC liquidity#3266TaprootFreak wants to merge 12 commits intodevelopfrom
TaprootFreak wants to merge 12 commits intodevelopfrom
Conversation
Integrate Lightning.space (Boltz) as an additional liquidity source for Citrea/cBTC, enabling flexible BTC → cBTC reverse swaps for amounts smaller than the fixed 10 BTC Clementine Bridge.
Use invoice.settled as success status for reverse swaps (not transaction.claimed which is for submarine swaps). Add complete SwapUpdateEvent enum matching boltz-backend. Simplify createReverseSwap params since EVM chains don't need preimageHash/claimPublicKey.
BTC onchain -> cBTC onchain is a Chain Swap (not a Reverse Swap which is Lightning -> onchain). Switch to POST /v2/swap/chain with preimageHash, claimAddress, userLockAmount. Use correct final events: transaction.claimed for success.
Previously the Boltz adapter created a chain swap but never sent BTC to the lockup address and never called helpMeClaim, leaving swaps stuck at swap.created. This implements the full flow: - Fix API URL (lightning.space/v1) and endpoint paths (/swap/v2/...) - Add getChainPairs() for pairHash and helpMeClaim() for server-side claiming - Send BTC to lockup address via BitcoinService after swap creation - Add state machine (btc_sent → claiming → done) in checkDepositCompletion - Store preimage/preimageHash in correlation data for claiming
❌ Security: 1 critical vulnerabilities |
…from response The helpMeClaim endpoint expects preimageHash with 0x prefix (verified against JuiceSwap frontend's prefix0x() call). Also use the actual lockup amount from the Boltz response instead of the requested amount for defensive correctness.
The outputAmount was incorrectly set to userLockAmountSats (BTC sent) instead of claimAmountSats (cBTC received after Boltz fees). Now stores swap.claimDetails.amount in correlation data and uses it for the final outputAmount calculation.
return-await is required inside try-catch blocks per @typescript-eslint/return-await rule.
Creates Boltz deposit action and wires it as onFail fallback for Clementine (Action 236). Activates Rule 320 (Citrea cBTC) with thresholds: minimal=0, optimal=0.1, maximal=0.5. Strategy: Clementine stays primary (fee-free, 10 BTC fixed). When it fails (e.g. balance < 10 BTC), Boltz handles flexible amounts as fallback.
Generate secp256k1 key pair and send compressed public key as refundPublicKey in createChainSwap request. Store private key in correlation data for potential refund signing if swap fails.
Without this status, a failed lockup would leave the swap polling indefinitely. Verified against JuiceSwap bapp which includes lockupFailed in its swapStatusFailed list.
Fetch dynamic min/max limits from Boltz chain pairs API and reject orders where the amount falls outside the allowed range. Prevents invalid swap creation and allows the order to retry later.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
What changed
src/config/config.tslightning.space/v1src/integration/blockchain/boltz/boltz-client.ts/swap/v2/...,/claim/...), addgetChainPairs(),helpMeClaim(), addpairHash/referralId/refundPublicKeytocreateChainSwap()src/integration/blockchain/boltz/boltz.service.tssrc/integration/blockchain/boltz/boltz.module.tssrc/integration/blockchain/blockchain.module.tssrc/subdomains/core/liquidity-management/adapters/actions/boltz.adapter.tsBitcoinService/BitcoinFeeService, generate secp256k1 refund keys, send BTC to lockup, state machine (btc_sent→claiming→ done), store preimage + refundPrivateKey for claiming/refundssrc/subdomains/core/liquidity-management/enums/index.tsBOLTZenum valuesrc/subdomains/core/liquidity-management/factories/liquidity-action-integration.factory.tssrc/subdomains/core/liquidity-management/liquidity-management.module.tsmigration/1772100000000-AddBoltzLiquidityAction.jsFlow
Migration (auto-runs on deploy)
migration/1772100000000-AddBoltzLiquidityAction.jsperforms:INSERT INTO liquidity_management_action (system, command, tag) VALUES ('Boltz', 'deposit', 'cBTC')UPDATE liquidity_management_action SET onFailId = <boltz_id> WHERE id = 236(Clementine)UPDATE liquidity_management_rule SET status = 'Active', minimal = 0, optimal = 0.1, maximal = 0.5, reactivationTime = 10 WHERE id = 320Strategy: Clementine (Action 236) stays primary — fee-free but requires 10 BTC. When Clementine fails (e.g. balance < 10 BTC), the pipeline follows
onFailto Boltz, which handles any amount within pair limits (with fees).Rollback via
down()reverts all three steps.Test plan
npx tsc --noEmitpassesnpx eslint— 0 errors, 0 warnings in changed files