mirror of
https://github.com/RoboSats/robosats.git
synced 2024-12-13 10:56:24 +00:00
Add mempool.space as fee estimator and remote read devfund pubkey (#1055)
This commit is contained in:
parent
f5d708f6a0
commit
3af8287da7
@ -9,7 +9,7 @@ from django.utils import timezone
|
||||
from api.lightning.node import LNNode
|
||||
from api.models import Currency, LNPayment, MarketTick, OnchainPayment, Order
|
||||
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
|
||||
|
||||
FEE = float(config("FEE"))
|
||||
@ -640,10 +640,7 @@ class Logics:
|
||||
): # Not enough onchain balance to commit for this swap.
|
||||
return False
|
||||
|
||||
suggested_mining_fee_rate = LNNode.estimate_fee(
|
||||
amount_sats=preliminary_amount,
|
||||
target_conf=config("SUGGESTED_TARGET_CONF", cast=int, default=2),
|
||||
)["mining_fee_rate"]
|
||||
suggested_mining_fee_rate = get_minning_fee("suggested", preliminary_amount)
|
||||
|
||||
# Hardcap mining fee suggested at 1000 sats/vbyte
|
||||
if suggested_mining_fee_rate > 1000:
|
||||
@ -795,10 +792,7 @@ class Logics:
|
||||
num_satoshis = cls.payout_amount(order, user)[1]["invoice_amount"]
|
||||
if mining_fee_rate:
|
||||
# not a valid mining fee
|
||||
min_mining_fee_rate = LNNode.estimate_fee(
|
||||
amount_sats=num_satoshis,
|
||||
target_conf=config("MINIMUM_TARGET_CONF", cast=int, default=24),
|
||||
)["mining_fee_rate"]
|
||||
min_mining_fee_rate = get_minning_fee("minimum", num_satoshis)
|
||||
|
||||
min_mining_fee_rate = max(2, min_mining_fee_rate)
|
||||
|
||||
|
10
api/tasks.py
10
api/tasks.py
@ -98,15 +98,9 @@ def send_devfund_donation(order_id, proceeds, reason):
|
||||
|
||||
from api.lightning.node import LNNode
|
||||
from api.models import LNPayment, Order
|
||||
from api.utils import get_devfund_pubkey
|
||||
|
||||
if config("NETWORK", cast=str) == "testnet":
|
||||
target_pubkey = (
|
||||
"03ecb271b3e2e36f2b91c92c65bab665e5165f8cdfdada1b5f46cfdd3248c87fd6"
|
||||
)
|
||||
else:
|
||||
target_pubkey = (
|
||||
"02187352cc4b1856b9604e0a79e1bc9b301be7e0c14acbbb8c29f7051d507127d7"
|
||||
)
|
||||
target_pubkey = get_devfund_pubkey(config("NETWORK", cast=str))
|
||||
|
||||
order = Order.objects.get(id=order_id)
|
||||
coordinator_alias = config("COORDINATOR_ALIAS", cast=str, default="NoAlias")
|
||||
|
90
api/utils.py
90
api/utils.py
@ -70,6 +70,96 @@ def validate_onchain_address(address):
|
||||
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 = {}
|
||||
|
||||
|
||||
|
4
devfund_pubkey.json
Normal file
4
devfund_pubkey.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"mainnet": "02187352cc4b1856b9604e0a79e1bc9b301be7e0c14acbbb8c29f7051d507127d7",
|
||||
"testnet": "03ecb271b3e2e36f2b91c92c65bab665e5165f8cdfdada1b5f46cfdd3248c87fd6"
|
||||
}
|
Loading…
Reference in New Issue
Block a user