specter-desktop/tests/test_specter.py
Kim Neunert 556ec5f961
Releasing procedure with pip (#69)
* automate pip-packages-gen + upload for gittags
release documentation
proper package including and  static + templates

* Change import- and start  logic, removed cli.py

* project-renaming to cryptoadvance.specter
propoer packaging
include proper dependencies

* Adding requirements.txt

* Specify maintainers and thanks to contributors

* Removing test-url for pip-uload. This is now live!
2020-02-20 13:00:53 +01:00

132 lines
5.9 KiB
Python

import json
import logging
import shutil
import pytest
from cryptoadvance.specter.rpc import RpcError
from cryptoadvance.specter.logic import (Device, DeviceManager, Specter, Wallet, WalletManager,
alias)
def test_alias():
assert alias("wurst 1") == "wurst_1"
assert alias("wurst_1") == "wurst_1"
assert alias("Wurst$ 1") == "wurst_1"
def test_specter(specter_regtest_configured,caplog):
caplog.set_level(logging.DEBUG)
specter_regtest_configured.check()
assert specter_regtest_configured.wallets is not None
assert specter_regtest_configured.devices is not None
assert specter_regtest_configured.config['rpc']['host'] != "None"
logging.debug("out {}".format(specter_regtest_configured.test_rpc() ))
json_return = json.loads(specter_regtest_configured.test_rpc()["out"] )
# that might only work if your chain is fresh
# assert json_return['blocks'] == 100
assert json_return['chain'] == 'regtest'
def test_DeviceManager(empty_data_folder):
# A DeviceManager manages devices, specifically the persistence
# of them via json-files in an empty data folder
dm = DeviceManager(data_folder=empty_data_folder)
# initialisation will load from the folder but i's empty, yet
assert len(dm) == 0
# a device has a name, a type and a list of keys
a_key = {
"derivation": "m/48h/1h/0h/2h",
"original": "Vpub5n9kKePTPPGtw3RddeJWJe29epEyBBcoHbbPi5HhpoG2kTVsSCUzsad33RJUt3LktEUUPPofcZczuudnwR7ZgkAkT6N2K2Z7wdyjYrVAkXM",
"fingerprint": "08686ac6",
"type": "wsh",
"xpub": "tpubDFHpKypXq4kwUrqLotPs6fCic5bFqTRGMBaTi9s5YwwGymE8FLGwB2kDXALxqvNwFxB1dLWYBmmeFVjmUSdt2AsaQuPmkyPLBKRZW8BGCiL"
}
# the DeviceManager doesn't care so much about the content of a key
# so this is a minimal valid "key":
another_key = {
'original': 'blub'
}
dm.add("some_name","the_type",[a_key,another_key])
assert dm.get_by_alias('some_name')['name'] == 'some_name'
assert dm.get_by_alias('some_name')['type'] == 'the_type'
assert dm.get_by_alias('some_name')['keys'][0]['fingerprint'] == '08686ac6'
# Now it has a length of 1
assert len(dm) == 1
# and is iterable
assert [the_type['type'] for the_type in dm] == ['the_type']
# The DeviceManager will return Device-Types (subclass of dict)
assert type(dm['some_name']) == Device
# A device is mainly a Domain-Object which assumes an underlying
# json-file which can be found in the "fullpath"-key
# It derives from a dict
# It needs a DeviceManager to be injected and can't reasonable
# be created on your own.
some_device = dm['some_name']
assert some_device['fullpath'] == empty_data_folder + '/some_name.json'
# keys can be added and removed. It will instantly update the underlying json
# TBD: more explanational tests
def test_WalletManager(bitcoin_regtest, devices_filled_data_folder, device_manager):
wm = WalletManager(devices_filled_data_folder,bitcoin_regtest.get_cli(),"regtest")
# A wallet-creation needs a device
device = device_manager.get_by_alias('trezor')
assert device != None
key = {
"derivation": "m/84h/1h/0h",
"original": "vpub5Y35MNUT8sUR2SnRCU9A9S6z1JDACMTuNnM8WHXvuS7hCwuVuoRAWJGpi66Yo8evGPiecN26oLqx19xf57mqVQjiYb9hbb4QzbNmFfsS9ko",
"fingerprint": "1ef4e492",
"type": "wpkh",
"xpub": "tpubDC5EUwdy9WWpzqMWKNhVmXdMgMbi4ywxkdysRdNr1MdM4SCfVLbNtsFvzY6WKSuzsaVAitj6FmP6TugPuNT6yKZDLsHrSwMd816TnqX7kuc"
}
# Lets's create a wallet with the WalletManager
wm.create_simple('a_test_wallet','wpkh',key,device)
# The wallet-name gets its filename and therfore its alias
wallet = wm.get_by_alias('a_test_wallet')
assert wallet != None
assert wallet.getbalances()['trusted'] == 0
assert wallet.getbalances()['untrusted_pending'] == 0
# this is a sum of both
assert wallet.getfullbalance() == 0
address = wallet.getnewaddress()
# newly minted coins need 100 blocks to get spendable
wallet.cli.generatetoaddress(1, address)
# let's mine another 100 blocks to get these coins spendable
random_address = "mruae2834buqxk77oaVpephnA5ZAxNNJ1r"
wallet.cli.generatetoaddress(100, random_address)
# a balance has properties which are caching the result from last call
assert wallet.fullbalance == 0
assert wallet.getfullbalance() == 50
assert wallet.fullbalance == 50
assert wallet.getbalance() == 50
# Lets's spend something and create a PSBT to a random address
psbt = wallet.createpsbt(random_address,10, True, 10)
# the most relevant stuff of the above object:
assert len(psbt['tx']['vin']) == 1 # 1 input
assert psbt['tx']['vin'][0]['txid'] == "730b41bd1e77b65770bfec73304da5c34cc1bad100394e6f5cc020bb5dbe65fd"
assert len(psbt['tx']['vout']) == 2 # 2 outputs
# Now let's send some money to this wallet (creating 10 more potential inputs)
for i in range(0,4): # 40 coins as a whole
bitcoin_regtest.testcoin_faucet(address,10)
assert wallet.getfullbalance() == 90
assert wallet.getbalances()['untrusted_pending'] == 40
assert wallet.getbalances()['trusted'] == 50
# Even though the Bitcoin-API doesn't support spending more than 'trusted'
try:
wallet.cli.walletcreatefundedpsbt(
[], # inputs (choose yourself)
[{random_address: 60}], # output
0, # locktime
{}, # options
True # replaceable
)
assert False # excpected an exception
except RpcError as rpce:
assert rpce.error_msg == "Insufficient funds"
pass
# But wallet.createpsbt supports it (by explicitely specifying inputs)!
psbt = wallet.createpsbt(random_address, 60, True, 10)
assert len(psbt['tx']['vin']) == 3
assert psbt['tx']['vin'][2]['txid'] == '730b41bd1e77b65770bfec73304da5c34cc1bad100394e6f5cc020bb5dbe65fd'