mirror of
https://github.com/cryptoadvance/specter-desktop.git
synced 2026-08-13 12:33:29 +02:00
211 lines
7.3 KiB
Python
211 lines
7.3 KiB
Python
import base64
|
|
import json
|
|
import logging
|
|
from numbers import Number
|
|
import jwt
|
|
import pytest
|
|
import datetime
|
|
import random
|
|
|
|
from flask import current_app as app
|
|
from cryptoadvance.specter.managers.device_manager import DeviceManager
|
|
from cryptoadvance.specter.specter import Specter
|
|
from cryptoadvance.specter.specter_error import SpecterError
|
|
from cryptoadvance.specter.util.wallet_importer import WalletImporter
|
|
from cryptoadvance.specter.user import User
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def create_registered_jwt_token(specter, username):
|
|
user = specter.user_manager.get_user_by_username(username)
|
|
jwt_token_id = User.generate_token_id()
|
|
jwt_token_life = 3600
|
|
jwt_token = User.generate_jwt_token(
|
|
username, jwt_token_id, "test token", jwt_token_life
|
|
)
|
|
user.add_jwt_token(jwt_token_id, jwt_token, "test token", jwt_token_life)
|
|
return jwt_token
|
|
|
|
|
|
def almost_equal(a: Number, b: Number, precision: float = 0.01) -> bool:
|
|
"""
|
|
Checks if a and b are not very different.
|
|
Default precision is 1%
|
|
"""
|
|
if a == b:
|
|
return True
|
|
diff = 2 * (a - b) / (a + b)
|
|
return (diff < precision) and (diff > -precision)
|
|
|
|
|
|
def test_rr_psbt_get(client, specter_regtest_configured, bitcoin_regtest, caplog):
|
|
create_a_simple_wallet(specter_regtest_configured, bitcoin_regtest)
|
|
assert (
|
|
specter_regtest_configured.config["testing"]["allow_threading_for_testing"]
|
|
== False
|
|
) # Tests fail with threading
|
|
caplog.set_level(logging.DEBUG)
|
|
""" testing the registration """
|
|
# Unauthorized
|
|
result = client.get("/api/v1alpha/wallets/some_wallet/psbt", follow_redirects=True)
|
|
assert result.status_code == 401
|
|
assert json.loads(result.data)["message"].startswith(
|
|
"The server could not verify that you are authorized to access the URL requested."
|
|
)
|
|
|
|
# Wrong token
|
|
headers = {"Authorization": "Bearer " + "sometoken"}
|
|
result = client.get(
|
|
"/api/v1alpha/wallets/a_simple_wallet/psbt",
|
|
follow_redirects=True,
|
|
headers=headers,
|
|
)
|
|
assert result.status_code == 401
|
|
assert json.loads(result.data)["message"].startswith(
|
|
"The server could not verify that you are authorized to access the URL requested."
|
|
)
|
|
|
|
# Admin but not authorized (admin is NOT allowed to read everything)
|
|
headers = {
|
|
"Authorization": "Bearer "
|
|
+ create_registered_jwt_token(specter_regtest_configured, "admin")
|
|
}
|
|
result = client.get(
|
|
"/api/v1alpha/wallets/a_simple_wallet/psbt",
|
|
follow_redirects=True,
|
|
headers=headers,
|
|
)
|
|
assert result.status_code == 403
|
|
assert (
|
|
json.loads(result.data)["message"]
|
|
== "The wallet does not belong to the user in the request."
|
|
)
|
|
|
|
# Proper authorized (the wallet is owned by someuser)
|
|
headers = {
|
|
"Authorization": "Bearer "
|
|
+ create_registered_jwt_token(specter_regtest_configured, "someuser")
|
|
}
|
|
result = client.get(
|
|
"/api/v1alpha/wallets/a_simple_wallet/psbt",
|
|
follow_redirects=True,
|
|
headers=headers,
|
|
)
|
|
assert result.status_code == 200
|
|
data = json.loads(result.data)
|
|
assert data["result"] == {}
|
|
|
|
|
|
def test_rr_psbt_post(specter_regtest_configured, bitcoin_regtest, client, caplog):
|
|
create_a_simple_wallet(specter_regtest_configured, bitcoin_regtest)
|
|
caplog.set_level(logging.DEBUG)
|
|
""" testing the registration """
|
|
|
|
headers = {
|
|
"Authorization": "Bearer "
|
|
+ create_registered_jwt_token(specter_regtest_configured, "someuser"),
|
|
"Content-type": "application/json",
|
|
}
|
|
|
|
result = client.get(
|
|
"/api/v1alpha/wallets/a_simple_wallet/",
|
|
follow_redirects=True,
|
|
headers=headers,
|
|
)
|
|
# Why the heck does this fail?
|
|
# assert json.loads(result.data)["a_simple_wallet"]["info"]["balance"] > 0
|
|
|
|
result = client.post(
|
|
"/api/v1alpha/wallets/some_wallet/psbt",
|
|
data=dict(address="someaddress", amount=0.5),
|
|
follow_redirects=True,
|
|
)
|
|
assert result.status_code == 401
|
|
assert json.loads(result.data)["message"].startswith(
|
|
"The server could not verify that you are authorized to access the URL requested."
|
|
)
|
|
|
|
result = client.post(
|
|
"/api/v1alpha/wallets/a_simple_wallet/psbt",
|
|
data="""
|
|
{
|
|
"recipients" : [
|
|
{
|
|
"address": "bcrt1qgc6h85z43g3ss2dl5zdrzrp3ef6av4neqcqhh8",
|
|
"amount": 0.1,
|
|
"unit": "btc",
|
|
"label": "someLabel"
|
|
},
|
|
{
|
|
"address": "bcrt1q3kfetuxpxvujasww6xas94nawklvpz0e52uw8a",
|
|
"amount": 111211,
|
|
"unit": "sat",
|
|
"label": "someOtherLabel"
|
|
}
|
|
],
|
|
"rbf_tx_id": "",
|
|
"subtract_from": "0",
|
|
"fee_rate": "64",
|
|
"rbf": true
|
|
}
|
|
""",
|
|
follow_redirects=True,
|
|
headers=headers,
|
|
)
|
|
print(result.data)
|
|
assert result.status_code == 200
|
|
data = json.loads(result.data)
|
|
assert "bcrt1qgc6h85z43g3ss2dl5zdrzrp3ef6av4neqcqhh8" in data["result"]["address"]
|
|
assert "bcrt1q3kfetuxpxvujasww6xas94nawklvpz0e52uw8a" in data["result"]["address"]
|
|
assert 0.1 in data["result"]["amount"]
|
|
assert 0.00111211 in data["result"]["amount"]
|
|
assert data["result"]["tx"]
|
|
assert data["result"]["inputs"]
|
|
assert data["result"]["outputs"]
|
|
assert almost_equal(data["result"]["fee_rate"], 64)
|
|
assert data["result"]["tx_full_size"]
|
|
assert data["result"]["base64"]
|
|
assert data["result"]["time"]
|
|
assert data["result"]["sigs_count"] == 0
|
|
|
|
|
|
def create_a_simple_wallet(specter: Specter, bitcoin_regtest):
|
|
"""ToDo: Could potentially do this with a fixture but this is only relevant for this file only"""
|
|
payload = jwt.decode(
|
|
User.generate_jwt_token(
|
|
"someuser", "tokenid", "tokendescription", random.randrange(100, 200)
|
|
),
|
|
app.config["SECRET_KEY"],
|
|
algorithms=["HS256"],
|
|
)
|
|
username = payload["username"]
|
|
someuser = specter.user_manager.get_user_by_username(username)
|
|
wm = someuser.wallet_manager
|
|
assert not wm.working_folder is None
|
|
# Create a Wallet
|
|
wallet_json = '{"label": "a_simple_wallet", "blockheight": 0, "descriptor": "wpkh([1ef4e492/84h/1h/0h]tpubDC5EUwdy9WWpzqMWKNhVmXdMgMbi4ywxkdysRdNr1MdM4SCfVLbNtsFvzY6WKSuzsaVAitj6FmP6TugPuNT6yKZDLsHrSwMd816TnqX7kuc/0/*)#xp8lv5nr", "devices": [{"type": "trezor", "label": "trezor"}]} '
|
|
dm = someuser.device_manager
|
|
wallet_importer = WalletImporter(wallet_json, specter, device_manager=dm)
|
|
wallet_importer.create_nonexisting_signers(
|
|
dm,
|
|
{"unknown_cosigner_0_name": "trezor", "unknown_cosigner_0_type": "trezor"},
|
|
)
|
|
wallet = wallet_importer.create_wallet(wm)
|
|
try:
|
|
# fund it with some coins
|
|
bitcoin_regtest.testcoin_faucet(address=wallet.getnewaddress())
|
|
# make sure it's confirmed
|
|
bitcoin_regtest.mine()
|
|
# Realize that the wallet has funds:
|
|
wallet.update()
|
|
except SpecterError as se:
|
|
if str(se).startswith("Timeout"):
|
|
pytest.fail(
|
|
"We got a Bitcoin-RPC timeout while setting up the test, minting some coins. Test Error! Check cpu/mem utilastion and btc/elem logs!"
|
|
)
|
|
return
|
|
else:
|
|
raise se
|
|
|
|
assert wallet.fullbalance >= 20
|