Skip to content

feat: Add hybrid fee estimation using mempool.space oracle for RBF#235

Merged
macterra merged 6 commits intomainfrom
234-hybrid-fee-estimation
Mar 18, 2026
Merged

feat: Add hybrid fee estimation using mempool.space oracle for RBF#235
macterra merged 6 commits intomainfrom
234-hybrid-fee-estimation

Conversation

@macterra
Copy link
Copy Markdown
Collaborator

@macterra macterra commented Mar 18, 2026

Summary

  • Adds getHybridFeeRateSatPerVb() in satoshi-mediator: takes Math.max(localEstimate, oracleEstimate) so a thin-mempool estimateSmartFee can't produce a stalling under-fee
  • Oracle URL configurable via ARCHON_SAT_FEE_ORACLE_URL; defaults to https://mempool.space/api/v1/fees/recommended for mainnet, empty (disabled) for testnet4/signet
  • Oracle has a 5s timeout and fails silently — if unavailable, falls back to local estimate only
  • RBF bump now passes the hybrid rate explicitly to walletBumpFee, so Bitcoin Core's internal estimate isn't used a second time for the bump amount
  • feeConf block target maps to fastestFee (≤1), halfHourFee (≤3), or hourFee (>3) from the oracle response

Test plan

  • Verify RBF bump uses oracle rate when oracle > local estimate
  • Verify fallback to local estimate when ARCHON_SAT_FEE_ORACLE_URL is empty
  • Verify oracle timeout/failure is logged as warning and local estimate is used

Closes #234

🤖 Generated with Claude Code

macterra and others added 3 commits March 18, 2026 15:25
Use Math.max(localEstimate, oracleEstimate) so estimateSmartFee with a
thin mempool doesn't produce an under-fee that stalls transactions.
Oracle URL is configurable via ARCHON_SAT_FEE_ORACLE_URL (defaults to
mempool.space for mainnet, empty/disabled for testnet/signet).

Closes #234

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously getHybridFeeRateSatPerVb() was only used in RBF bumps.
The initial walletAnchor call used conf_target which falls back to
Bitcoin Core's thin-mempool estimateSmartFee, producing too-low fees.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
>= caused RBF to wait 2 blocks instead of feeConf blocks.
Change to > so it fires after exactly feeConf missed blocks.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@macterra macterra requested a review from Copilot March 18, 2026 19:47
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a hybrid fee estimation strategy to the Satoshi mediator to improve anchoring and RBF bump behavior when local estimatesmartfee underestimates fees (e.g., thin mempool), with optional integration to a mempool.space-style fee oracle.

Changes:

  • Introduces getHybridFeeRateSatPerVb() (max of local estimateSmartFee and external oracle recommendation) and uses it for both anchoring and RBF bumping.
  • Fixes the RBF timing off-by-one by changing the bump trigger condition from >= to >.
  • Adds ARCHON_SAT_FEE_ORACLE_URL wiring/documentation and propagates the env var through sample env + docker-compose files.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
services/mediators/satoshi/src/satoshi-mediator.ts Use hybrid fee rate for anchor + RBF bump; fix RBF block trigger condition; plumb feeRate into wallet API calls.
services/mediators/satoshi/src/config.ts Add feeOracleUrl config field sourced from ARCHON_SAT_FEE_ORACLE_URL.
services/mediators/satoshi/README.md Document new fee oracle env var.
sample.env Add per-network *_FEE_ORACLE_URL defaults (mainnet set, testnet4/signet empty).
docker-compose.btc-testnet4.yml Pass fee oracle env var through to satoshi mediator container.
docker-compose.btc-signet.yml Pass fee oracle env var through to satoshi mediator container.
docker-compose.btc-mainnet.yml Pass fee oracle env var through to satoshi mediator container.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread services/mediators/satoshi/src/satoshi-mediator.ts Outdated
Comment thread services/mediators/satoshi/src/config.ts Outdated
macterra and others added 3 commits March 18, 2026 16:24
Re-queues a dropped operation by CID directly into the gatekeeper DB,
allowing the mediator to re-anchor it on-chain and restore the
confirmation chain for affected DID versions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Wrap estimateSmartFee in try/catch, fall back to feeFallback on error
- Default feeOracleUrl to mempool.space only on BTC:mainnet; empty for
  testnet4/signet to avoid mainnet fee rates on test networks

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Defaults to empty (disabled). Set ARCHON_SAT_FEE_ORACLE_URL explicitly
in .env to enable (sample.env provides the mempool.space URL).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@macterra macterra merged commit ad90d3c into main Mar 18, 2026
13 checks passed
@macterra macterra deleted the 234-hybrid-fee-estimation branch March 18, 2026 20:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RBF off-by-one: fee bump delayed by extra block

2 participants