Add mempool.space as fee estimator and remote read devfund pubkey (#1055)

This commit is contained in:
Reckless_Satoshi 2024-01-08 14:13:37 +00:00 committed by GitHub
parent f5d708f6a0
commit 3af8287da7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 99 additions and 17 deletions

View File

@ -9,7 +9,7 @@ from django.utils import timezone
from api.lightning.node import LNNode from api.lightning.node import LNNode
from api.models import Currency, LNPayment, MarketTick, OnchainPayment, Order from api.models import Currency, LNPayment, MarketTick, OnchainPayment, Order
from api.tasks import send_devfund_donation, send_notification from api.tasks import send_devfund_donation, send_notification
from api.utils import validate_onchain_address from api.utils import get_minning_fee, validate_onchain_address
from chat.models import Message from chat.models import Message
FEE = float(config("FEE")) FEE = float(config("FEE"))
@ -640,10 +640,7 @@ class Logics:
): # Not enough onchain balance to commit for this swap. ): # Not enough onchain balance to commit for this swap.
return False return False
suggested_mining_fee_rate = LNNode.estimate_fee( suggested_mining_fee_rate = get_minning_fee("suggested", preliminary_amount)
amount_sats=preliminary_amount,
target_conf=config("SUGGESTED_TARGET_CONF", cast=int, default=2),
)["mining_fee_rate"]
# Hardcap mining fee suggested at 1000 sats/vbyte # Hardcap mining fee suggested at 1000 sats/vbyte
if suggested_mining_fee_rate > 1000: if suggested_mining_fee_rate > 1000:
@ -795,10 +792,7 @@ class Logics:
num_satoshis = cls.payout_amount(order, user)[1]["invoice_amount"] num_satoshis = cls.payout_amount(order, user)[1]["invoice_amount"]
if mining_fee_rate: if mining_fee_rate:
# not a valid mining fee # not a valid mining fee
min_mining_fee_rate = LNNode.estimate_fee( min_mining_fee_rate = get_minning_fee("minimum", num_satoshis)
amount_sats=num_satoshis,
target_conf=config("MINIMUM_TARGET_CONF", cast=int, default=24),
)["mining_fee_rate"]
min_mining_fee_rate = max(2, min_mining_fee_rate) min_mining_fee_rate = max(2, min_mining_fee_rate)

View File

@ -98,15 +98,9 @@ def send_devfund_donation(order_id, proceeds, reason):
from api.lightning.node import LNNode from api.lightning.node import LNNode
from api.models import LNPayment, Order from api.models import LNPayment, Order
from api.utils import get_devfund_pubkey
if config("NETWORK", cast=str) == "testnet": target_pubkey = get_devfund_pubkey(config("NETWORK", cast=str))
target_pubkey = (
"03ecb271b3e2e36f2b91c92c65bab665e5165f8cdfdada1b5f46cfdd3248c87fd6"
)
else:
target_pubkey = (
"02187352cc4b1856b9604e0a79e1bc9b301be7e0c14acbbb8c29f7051d507127d7"
)
order = Order.objects.get(id=order_id) order = Order.objects.get(id=order_id)
coordinator_alias = config("COORDINATOR_ALIAS", cast=str, default="NoAlias") coordinator_alias = config("COORDINATOR_ALIAS", cast=str, default="NoAlias")

View File

@ -70,6 +70,96 @@ def validate_onchain_address(address):
return True, None return True, None
mining_fee = {}
@ring.dict(mining_fee, expire=60) # keeps in cache for 60 seconds
def get_minning_fee(priority: str, preliminary_amount: int) -> int:
"""
priority: (str) 'suggested' | 'minimum'
Fetches suggested and minimum mining fee rates from mempool.space
uses LND/CLN fee estimator as fallback.
mempool.space response object:
{
fastestFee: 1,
halfHourFee: 1,
hourFee: 1,
economyFee: 1,
minimumFee: 1
}
Where 'suggested' is 'fastestFee' and 'minimum' is 'economyFee'
"""
from api.lightning.node import LNNode
session = get_session()
mempool_url = (
"http://mempoolhqx4isw62xs7abwphsq7ldayuidyx2v2oethdhhj6mlo2r6ad.onion"
if USE_TOR
else "https://mempool.space"
)
api_path = "/api/v1/fees/recommended"
try:
response = session.get(mempool_url + api_path)
response.raise_for_status() # Raises stored HTTPError, if one occurred
data = response.json()
if priority == "suggested":
value = data.get("fastestFee")
elif priority == "minimum":
value = data.get("economyFee")
else:
raise Exception(
"an error occurred",
"unexpected value for mining fee priority",
priority,
)
except Exception:
# Fetch mining fee from LND/CLN instance
if priority == "suggested":
target_conf = config("SUGGESTED_TARGET_CONF", cast=int, default=2)
if priority == "minimum":
target_conf = config("MINIMUM_TARGET_CONF", cast=int, default=24)
value = LNNode.estimate_fee(
amount_sats=preliminary_amount,
target_conf=target_conf,
)["mining_fee_rate"]
return value
devfund_pubkey = {}
@ring.dict(devfund_pubkey, expire=3600) # keeps in cache for 3600 seconds
def get_devfund_pubkey(network: str) -> str:
"""
network: (str) "mainnet" | "testnet";
Fetches devfund pubkey from `main` branch in the repository
fallback to hardcoded pubkey
"""
session = get_session()
url = "https://raw.githubusercontent.com/RoboSats/robosats/main/devfund_pubkey.json"
# hardcoded fallback
mainnet = "02187352cc4b1856b9604e0a79e1bc9b301be7e0c14acbbb8c29f7051d507127d7"
testnet = "03ecb271b3e2e36f2b91c92c65bab665e5165f8cdfdada1b5f46cfdd3248c87fd6"
try:
response = session.get(url)
response.raise_for_status() # Raises stored HTTPError, if one occurred
value = response.json().get(network)
if len(value) == 66:
return value
except Exception as e:
print(e)
return mainnet if network == "mainnet" else testnet
market_cache = {} market_cache = {}

4
devfund_pubkey.json Normal file
View File

@ -0,0 +1,4 @@
{
"mainnet": "02187352cc4b1856b9604e0a79e1bc9b301be7e0c14acbbb8c29f7051d507127d7",
"testnet": "03ecb271b3e2e36f2b91c92c65bab665e5165f8cdfdada1b5f46cfdd3248c87fd6"
}