2021-11-17 10:53:32 -06:00
|
|
|
import hashlib
|
2023-02-01 16:54:07 +01:00
|
|
|
import json
|
2023-07-26 14:18:14 +02:00
|
|
|
import os
|
2022-06-27 00:11:46 +02:00
|
|
|
import random
|
|
|
|
import string
|
2023-08-30 12:01:32 +02:00
|
|
|
import time
|
|
|
|
from subprocess import PIPE, Popen, TimeoutExpired
|
2023-07-26 14:18:14 +02:00
|
|
|
from typing import Tuple
|
2022-08-03 14:10:32 +02:00
|
|
|
|
2023-09-12 12:02:01 +02:00
|
|
|
import psycopg2
|
2023-08-30 12:01:32 +02:00
|
|
|
from loguru import logger
|
2023-09-12 12:02:01 +02:00
|
|
|
from sqlalchemy.engine.url import make_url
|
2023-08-30 12:01:32 +02:00
|
|
|
|
2023-09-12 12:02:01 +02:00
|
|
|
from lnbits import core
|
|
|
|
from lnbits.db import DB_TYPE, POSTGRES
|
2023-06-27 16:11:00 +02:00
|
|
|
from lnbits.wallets import get_wallet_class, set_wallet_class
|
2021-11-17 10:53:32 -06:00
|
|
|
|
2022-06-01 14:53:05 +02:00
|
|
|
|
2023-02-01 16:54:07 +01:00
|
|
|
def get_random_string(N: int = 10):
|
2022-06-27 00:11:46 +02:00
|
|
|
return "".join(
|
|
|
|
random.SystemRandom().choice(string.ascii_uppercase + string.digits)
|
2023-01-24 11:04:19 +00:00
|
|
|
for _ in range(N)
|
2022-06-27 00:11:46 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
async def get_random_invoice_data():
|
|
|
|
return {"out": False, "amount": 10, "memo": f"test_memo_{get_random_string(10)}"}
|
Boltz.exchange Extension (#922)
* initial commit and still draft, ready for review
* forgot to uncomment this line
* fee estimation and blockheight
* resolve conversation with michael, to use mempool websockets instead of boltz status event
* Update lnbits/extensions/boltz/boltz.py
Co-authored-by: michael1011 <me@michael1011.at>
* add status to swaps, add sorting and data into listing
* add swap status checks, change urls to docker test setup, dynamic minimum and maximum limits
* fix docker hosts for development
* add api endpoints to _api_docs
* add wallet name and id, to list and status information
* fix status_update for reverse_swaps
* chore: format with black
* more blackformatting and refactoring create_swap()
* fix variable bug
* check if swap is already refunded
* use create_task instead of ensure_future
* add mempool and boltz urls depending on DEBUG .env
* raise exception in mempool fails
* fix onchain txs, sending funds to wrong address and add a refund address for normal swaps beforehand
* add status to swaps, add sorting and data into listing
* add swap status checks, change urls to docker test setup, dynamic minimum and maximum limits
* add wallet name and id, to list and status information
* fix status_update for reverse_swaps
* chore: format with black
* use create_task instead of ensure_future
* add mempool and boltz urls depending on DEBUG .env
* fix onchain txs, sending funds to wrong address and add a refund address for normal swaps beforehand
* black formatting
* add some logging with loguru, and remove function duplication
* cleanup readme
* updates/suggestions from calle
Co-authored-by: calle <93376500+callebtc@users.noreply.github.com>
* remove unused comments
* Update API Endpoints
Co-authored-by: calle <93376500+callebtc@users.noreply.github.com>
* un-factor get_boltz_pairs
* added a explaination for the onchain tx
* remove unused template file
* rename api endpoints
* fix isort and prettier
* more verbose logging!!
* add boltz to mock_data.zip
* new mockdata
* remove comment
* better readme
* fix mempool urls
* change /refund /check /status to post requests
* first step in tests2
* add first tests
* change refund,check,status to post requests
* next try on tests
* overall code improvements
* just testing tests
* throw http exceptions in views_api
* require admincheck for refund,check,status and added fastapi documentation for those
* added more tests
* black
* many code improvements
* adding tests
* temp fix test
* fix race condition when pay_invoice fails
* test are working
* add boltz env variables
* add startup check, bugfixes, improvements
* improve on status checking
* remove check_invoice_status
* more fixes and tests
* testing testing testing
* make tests run again inside regtest
* fix bad error :O
* fix postgres boolean bug and add swap test
* Update README.md
Update README.md
Update README.md
Update README.md
* some mypy
* blacked
* the missing commit?
* fix api_docs readme link
* better refunding error catching
fix
* check swaps now also shows pending reverse swap, ui improvements, tooltips
* add backend check for boltz limits
fixup
* many improvements, startup check for swaps working, reverse needs more testing
* little last fixes
* remove unused logic
* fastapi documentation
fixup
* formatting and remove unused tests
* fix test
* fix swapstatus model
* Update lnbits/extensions/boltz/tasks.py
Co-authored-by: calle <93376500+callebtc@users.noreply.github.com>
* Update lnbits/extensions/boltz/views_api.py
Co-authored-by: calle <93376500+callebtc@users.noreply.github.com>
* balance check msg, format
* fix mypy data override
* fix swapstatus, remove can refund column
* Update lnbits/extensions/boltz/README.md
Co-authored-by: michael1011 <me@michael1011.at>
* empty lines
* fix error message when swap is not found
* remove preimage_hash from database
* fix api_docs html
fix api_docs html
* catch boltz network exceptions better
* formatting
* check for timeout on swap at get request
Co-authored-by: michael1011 <me@michael1011.at>
Co-authored-by: fusion44 <some.fusion@gmail.com>
Co-authored-by: calle <93376500+callebtc@users.noreply.github.com>
2022-08-30 12:51:17 +02:00
|
|
|
|
|
|
|
|
2023-06-15 12:36:28 +02:00
|
|
|
set_wallet_class()
|
2022-10-05 11:15:11 +02:00
|
|
|
WALLET = get_wallet_class()
|
|
|
|
is_fake: bool = WALLET.__class__.__name__ == "FakeWallet"
|
Boltz.exchange Extension (#922)
* initial commit and still draft, ready for review
* forgot to uncomment this line
* fee estimation and blockheight
* resolve conversation with michael, to use mempool websockets instead of boltz status event
* Update lnbits/extensions/boltz/boltz.py
Co-authored-by: michael1011 <me@michael1011.at>
* add status to swaps, add sorting and data into listing
* add swap status checks, change urls to docker test setup, dynamic minimum and maximum limits
* fix docker hosts for development
* add api endpoints to _api_docs
* add wallet name and id, to list and status information
* fix status_update for reverse_swaps
* chore: format with black
* more blackformatting and refactoring create_swap()
* fix variable bug
* check if swap is already refunded
* use create_task instead of ensure_future
* add mempool and boltz urls depending on DEBUG .env
* raise exception in mempool fails
* fix onchain txs, sending funds to wrong address and add a refund address for normal swaps beforehand
* add status to swaps, add sorting and data into listing
* add swap status checks, change urls to docker test setup, dynamic minimum and maximum limits
* add wallet name and id, to list and status information
* fix status_update for reverse_swaps
* chore: format with black
* use create_task instead of ensure_future
* add mempool and boltz urls depending on DEBUG .env
* fix onchain txs, sending funds to wrong address and add a refund address for normal swaps beforehand
* black formatting
* add some logging with loguru, and remove function duplication
* cleanup readme
* updates/suggestions from calle
Co-authored-by: calle <93376500+callebtc@users.noreply.github.com>
* remove unused comments
* Update API Endpoints
Co-authored-by: calle <93376500+callebtc@users.noreply.github.com>
* un-factor get_boltz_pairs
* added a explaination for the onchain tx
* remove unused template file
* rename api endpoints
* fix isort and prettier
* more verbose logging!!
* add boltz to mock_data.zip
* new mockdata
* remove comment
* better readme
* fix mempool urls
* change /refund /check /status to post requests
* first step in tests2
* add first tests
* change refund,check,status to post requests
* next try on tests
* overall code improvements
* just testing tests
* throw http exceptions in views_api
* require admincheck for refund,check,status and added fastapi documentation for those
* added more tests
* black
* many code improvements
* adding tests
* temp fix test
* fix race condition when pay_invoice fails
* test are working
* add boltz env variables
* add startup check, bugfixes, improvements
* improve on status checking
* remove check_invoice_status
* more fixes and tests
* testing testing testing
* make tests run again inside regtest
* fix bad error :O
* fix postgres boolean bug and add swap test
* Update README.md
Update README.md
Update README.md
Update README.md
* some mypy
* blacked
* the missing commit?
* fix api_docs readme link
* better refunding error catching
fix
* check swaps now also shows pending reverse swap, ui improvements, tooltips
* add backend check for boltz limits
fixup
* many improvements, startup check for swaps working, reverse needs more testing
* little last fixes
* remove unused logic
* fastapi documentation
fixup
* formatting and remove unused tests
* fix test
* fix swapstatus model
* Update lnbits/extensions/boltz/tasks.py
Co-authored-by: calle <93376500+callebtc@users.noreply.github.com>
* Update lnbits/extensions/boltz/views_api.py
Co-authored-by: calle <93376500+callebtc@users.noreply.github.com>
* balance check msg, format
* fix mypy data override
* fix swapstatus, remove can refund column
* Update lnbits/extensions/boltz/README.md
Co-authored-by: michael1011 <me@michael1011.at>
* empty lines
* fix error message when swap is not found
* remove preimage_hash from database
* fix api_docs html
fix api_docs html
* catch boltz network exceptions better
* formatting
* check for timeout on swap at get request
Co-authored-by: michael1011 <me@michael1011.at>
Co-authored-by: fusion44 <some.fusion@gmail.com>
Co-authored-by: calle <93376500+callebtc@users.noreply.github.com>
2022-08-30 12:51:17 +02:00
|
|
|
is_regtest: bool = not is_fake
|
2023-02-01 16:54:07 +01:00
|
|
|
|
|
|
|
|
2023-08-30 12:01:32 +02:00
|
|
|
docker_lightning_cli = [
|
|
|
|
"docker",
|
|
|
|
"exec",
|
|
|
|
"lnbits-legend-lnd-1-1",
|
|
|
|
"lncli",
|
|
|
|
"--network",
|
|
|
|
"regtest",
|
|
|
|
"--rpcserver=lnd-1",
|
|
|
|
]
|
|
|
|
|
|
|
|
docker_bitcoin_cli = [
|
|
|
|
"docker",
|
|
|
|
"exec",
|
|
|
|
"lnbits-legend-bitcoind-1-1" "bitcoin-cli",
|
|
|
|
"-rpcuser=lnbits",
|
|
|
|
"-rpcpassword=lnbits",
|
|
|
|
"-regtest",
|
|
|
|
]
|
|
|
|
|
|
|
|
|
2023-09-25 15:04:44 +02:00
|
|
|
docker_lightning_unconnected_cli = [
|
|
|
|
"docker",
|
|
|
|
"exec",
|
|
|
|
"lnbits-legend-lnd-2-1",
|
|
|
|
"lncli",
|
|
|
|
"--network",
|
|
|
|
"regtest",
|
|
|
|
"--rpcserver=lnd-2",
|
|
|
|
]
|
|
|
|
|
|
|
|
|
2023-08-30 12:01:32 +02:00
|
|
|
def run_cmd(cmd: list) -> str:
|
|
|
|
timeout = 20
|
|
|
|
process = Popen(cmd, stdout=PIPE, stderr=PIPE)
|
|
|
|
|
|
|
|
def process_communication(comm):
|
|
|
|
stdout, stderr = comm
|
|
|
|
output = stdout.decode("utf-8").strip()
|
|
|
|
error = stderr.decode("utf-8").strip()
|
|
|
|
return output, error
|
|
|
|
|
|
|
|
try:
|
|
|
|
now = time.time()
|
|
|
|
output, error = process_communication(process.communicate(timeout=timeout))
|
|
|
|
took = time.time() - now
|
|
|
|
logger.debug(f"ran command output: {output}, error: {error}, took: {took}s")
|
|
|
|
return output
|
|
|
|
except TimeoutExpired:
|
|
|
|
process.kill()
|
|
|
|
output, error = process_communication(process.communicate())
|
|
|
|
logger.error(f"timeout command: {cmd}, output: {output}, error: {error}")
|
|
|
|
raise
|
|
|
|
|
|
|
|
|
|
|
|
def run_cmd_json(cmd: list) -> dict:
|
|
|
|
output = run_cmd(cmd)
|
|
|
|
try:
|
|
|
|
return json.loads(output) if output else {}
|
|
|
|
except json.decoder.JSONDecodeError:
|
|
|
|
logger.error(f"failed to decode json from cmd `{cmd}`: {output}")
|
|
|
|
raise
|
2023-02-01 16:54:07 +01:00
|
|
|
|
|
|
|
|
2023-07-26 14:18:14 +02:00
|
|
|
def get_hold_invoice(sats: int) -> Tuple[str, dict]:
|
|
|
|
preimage = os.urandom(32)
|
|
|
|
preimage_hash = hashlib.sha256(preimage).hexdigest()
|
2023-08-30 12:01:32 +02:00
|
|
|
cmd = docker_lightning_cli.copy()
|
|
|
|
cmd.extend(["addholdinvoice", preimage_hash, str(sats)])
|
|
|
|
json = run_cmd_json(cmd)
|
2023-07-26 14:18:14 +02:00
|
|
|
return preimage.hex(), json
|
|
|
|
|
|
|
|
|
2023-08-30 12:01:32 +02:00
|
|
|
def settle_invoice(preimage: str) -> str:
|
|
|
|
cmd = docker_lightning_cli.copy()
|
|
|
|
cmd.extend(["settleinvoice", preimage])
|
|
|
|
return run_cmd(cmd)
|
2023-07-26 14:18:14 +02:00
|
|
|
|
|
|
|
|
2023-08-30 12:01:32 +02:00
|
|
|
def cancel_invoice(preimage_hash: str) -> str:
|
|
|
|
cmd = docker_lightning_cli.copy()
|
|
|
|
cmd.extend(["cancelinvoice", preimage_hash])
|
|
|
|
return run_cmd(cmd)
|
2023-07-26 14:18:14 +02:00
|
|
|
|
|
|
|
|
2023-06-15 12:36:28 +02:00
|
|
|
def get_real_invoice(sats: int) -> dict:
|
2023-08-30 12:01:32 +02:00
|
|
|
cmd = docker_lightning_cli.copy()
|
|
|
|
cmd.extend(["addinvoice", str(sats)])
|
|
|
|
return run_cmd_json(cmd)
|
2023-02-01 16:54:07 +01:00
|
|
|
|
|
|
|
|
2023-08-30 12:01:32 +02:00
|
|
|
def pay_real_invoice(invoice: str) -> str:
|
|
|
|
cmd = docker_lightning_cli.copy()
|
|
|
|
cmd.extend(["payinvoice", "--force", invoice])
|
|
|
|
return run_cmd(cmd)
|
2023-02-01 16:54:07 +01:00
|
|
|
|
|
|
|
|
|
|
|
def mine_blocks(blocks: int = 1) -> str:
|
2023-08-30 12:01:32 +02:00
|
|
|
cmd = docker_bitcoin_cli.copy()
|
|
|
|
cmd.extend(["-generate", str(blocks)])
|
|
|
|
return run_cmd(cmd)
|
2023-02-01 16:54:07 +01:00
|
|
|
|
|
|
|
|
2023-09-25 15:04:44 +02:00
|
|
|
def get_unconnected_node_uri() -> str:
|
|
|
|
cmd = docker_lightning_unconnected_cli.copy()
|
|
|
|
cmd.append("getinfo")
|
|
|
|
info = run_cmd_json(cmd)
|
|
|
|
pubkey = info["identity_pubkey"]
|
|
|
|
return f"{pubkey}@lnd-2:9735"
|
|
|
|
|
|
|
|
|
2023-02-01 16:54:07 +01:00
|
|
|
def create_onchain_address(address_type: str = "bech32") -> str:
|
2023-08-30 12:01:32 +02:00
|
|
|
cmd = docker_bitcoin_cli.copy()
|
|
|
|
cmd.extend(["getnewaddress", address_type])
|
|
|
|
return run_cmd(cmd)
|
2023-02-01 16:54:07 +01:00
|
|
|
|
|
|
|
|
|
|
|
def pay_onchain(address: str, sats: int) -> str:
|
|
|
|
btc = sats * 0.00000001
|
2023-08-30 12:01:32 +02:00
|
|
|
cmd = docker_bitcoin_cli.copy()
|
|
|
|
cmd.extend(["sendtoaddress", address, str(btc)])
|
|
|
|
return run_cmd(cmd)
|
2023-09-12 12:02:01 +02:00
|
|
|
|
|
|
|
|
|
|
|
def clean_database(settings):
|
|
|
|
if DB_TYPE == POSTGRES:
|
|
|
|
db_url = make_url(settings.lnbits_database_url)
|
|
|
|
|
|
|
|
conn = psycopg2.connect(settings.lnbits_database_url)
|
|
|
|
conn.autocommit = True
|
|
|
|
with conn.cursor() as cur:
|
|
|
|
try:
|
|
|
|
cur.execute("DROP DATABASE lnbits_test")
|
|
|
|
except psycopg2.errors.InvalidCatalogName:
|
|
|
|
pass
|
|
|
|
cur.execute("CREATE DATABASE lnbits_test")
|
|
|
|
|
|
|
|
db_url.database = "lnbits_test"
|
|
|
|
settings.lnbits_database_url = str(db_url)
|
|
|
|
|
|
|
|
core.db.__init__("database")
|
|
|
|
|
|
|
|
conn.close()
|
|
|
|
else:
|
|
|
|
# FIXME: do this once mock data is removed from test data folder
|
|
|
|
# os.remove(settings.lnbits_data_folder + "/database.sqlite3")
|
|
|
|
pass
|