Feature: Spectrum addition (#1952)

* add spectrum

* rc3 of spectrum

* spectrum rc4

* missing __init__.py

* changes for rc6

* make cli-arguments work in electron

* update spectrum to remove simplejson

* Bugfix devices not shown

* additional checks for wallet_import

* nodes template magic to improve extensibility

* smaller bugfixes

* update spectrum

* keep python 3.9 in pre-commit-yaml

* specter_added_to_flask_app callback added

* useful logger + avoid writing to config with no node alias

* Using FlaskThread

* remove overriding chain property in node.py

* nodes_by_chain method added to node mananger

* icons for spectrum setup

* keep external_node and fix test

* bump spectrum version

* more visibility

* deactivate checker_threads for testing

Co-authored-by: k9ert <kim@swanbitcoin.com>
Co-authored-by: Manolis Mandrapilias <70536101+moneymanolis@users.noreply.github.com>
Co-authored-by: moneymanolis <moneymanolis@protonmail.com>
This commit is contained in:
k9ert 2022-11-30 04:13:16 -08:00 committed by GitHub
parent bf4413587a
commit 9df0b77f8c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 475 additions and 71 deletions

View file

@ -33,3 +33,4 @@ pytimeparse==1.1.8
cryptoadvance-liquidissuer==0.2.4
specterext-exfund==0.1.7
specterext-faucet==0.1.2
cryptoadvance.spectrum==0.2.0

View file

@ -1,5 +1,5 @@
#
# This file is autogenerated by pip-compile with python 3.9
# This file is autogenerated by pip-compile with python 3.10
# To update, run:
#
# pip-compile --generate-hashes requirements.in
@ -12,28 +12,14 @@ apscheduler==3.9.1 \
--hash=sha256:65e6574b6395498d371d045f2a8a7e4f7d50c6ad21ef7313d15b1c7cf20df1e3 \
--hash=sha256:ddc25a0ddd899de44d7f451f4375fb971887e65af51e41e5dcf681f59b8b2c9a
# via flask-apscheduler
attrs==22.1.0 \
--hash=sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6 \
--hash=sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c
# via pytest
babel==2.10.3 \
--hash=sha256:7614553711ee97490f732126dc077f8d0ae084ebc6a96e23db1482afabdb2c51 \
--hash=sha256:ff56f4892c1c4bf0d814575ea23471c230d544203c7748e8c68f0089478d48eb
# via flask-babel
backports-zoneinfo==0.2.1 ; python_version < "3.10" \
--hash=sha256:17746bd546106fa389c51dbea67c8b7c8f0d14b5526a579ca6ccf5ed72c526cf \
--hash=sha256:1b13e654a55cd45672cb54ed12148cd33628f672548f373963b0bff67b217328 \
--hash=sha256:1c5742112073a563c81f786e77514969acb58649bcdf6cdf0b4ed31a348d4546 \
--hash=sha256:4a0f800587060bf8880f954dbef70de6c11bbe59c673c3d818921f042f9954a6 \
--hash=sha256:5c144945a7752ca544b4b78c8c41544cdfaf9786f25fe5ffb10e838e19a27570 \
--hash=sha256:7b0a64cda4145548fed9efc10322770f929b944ce5cee6c0dfe0c87bf4c0c8c9 \
--hash=sha256:8439c030a11780786a2002261569bdf362264f605dfa4d65090b64b05c9f79a7 \
--hash=sha256:8961c0f32cd0336fb8e8ead11a1f8cd99ec07145ec2931122faaac1c8f7fd987 \
--hash=sha256:89a48c0d158a3cc3f654da4c2de1ceba85263fafb861b98b59040a5086259722 \
--hash=sha256:a76b38c52400b762e48131494ba26be363491ac4f9a04c1b7e92483d169f6582 \
--hash=sha256:da6013fd84a690242c310d77ddb8441a559e9cb3d3d59ebac9aca1a57b2e18bc \
--hash=sha256:e55b384612d93be96506932a786bbcde5a2db7a9e6a4bb4bffe8b733f5b9036b \
--hash=sha256:e81b76cace8eda1fca50e345242ba977f9be6ae3945af8d46326d776b4cf78d1 \
--hash=sha256:e8236383a20872c0cdf5a62b554b27538db7fa1bbec52429d8d106effbaeca08 \
--hash=sha256:f04e857b59d9d1ccc39ce2da1021d196e47234873820cbeaad210724b1ee28ac \
--hash=sha256:fadbfe37f74051d024037f223b8e001611eac868b5c5b06144ef4d8b799862f2
# via -r requirements.in
base58==2.1.1 \
--hash=sha256:11a36f4d3ce51dfc1043f3218591ac4eb1ceb172919cebe05b52a5bcc8d245c2 \
--hash=sha256:c5d0cb3f5b6e81e8e35da5754388ddcc6d0d14b6c6a132cb93d69ed580a7278c
@ -137,6 +123,10 @@ cryptoadvance-liquidissuer==0.2.4 \
--hash=sha256:5a2c531801854c5a4a46daf184877e22f731cdb42d2cfb840785bda7371ba6fb \
--hash=sha256:9e468f3e35ecc566b3f74a2263677cf26632548abb194521dba15ad37acd1e9b
# via -r requirements.in
cryptoadvance-spectrum==0.2.0 \
--hash=sha256:4ff8ec591ed86ddedc3049f3c37ed5ca4c02ce444c3ca8098c7a6d8de8ae57c2 \
--hash=sha256:8cc4ef940c635075bff9755e60d55a0259010f4d44f961ad9d257180a4bc073b
# via -r requirements.in
cryptography==3.4.7 \
--hash=sha256:0f1212a66329c80d68aeeb39b8a16d54ef57071bf22ff4e521657b27372e327d \
--hash=sha256:1e056c28420c072c5e3cb36e2b23ee55e260cb04eee08f702e0edfec3fb51959 \
@ -165,18 +155,26 @@ ecdsa==0.18.0 \
# hwi
embit==0.6.1 \
--hash=sha256:16a84c6668dc9ffc907594457a46f7142cee379646bc009a5a9b77b0d2cb4e12
# via -r requirements.in
# via
# -r requirements.in
# cryptoadvance-spectrum
exceptiongroup==1.0.0 \
--hash=sha256:2ac84b496be68464a2da60da518af3785fff8b7ec0d090a581604bc870bdee41 \
--hash=sha256:affbabf13fb6e98988c38d9c5650e701569fe3c1de3233cfb61c5f33774690ad
# via pytest
flask==2.1.1 \
--hash=sha256:8a4cf32d904cf5621db9f0c9fbcd7efabf3003f22a04e4d0ce790c7137ec5264 \
--hash=sha256:a8c9bd3e558ec99646d177a9739c41df1ded0629480b4c8d2975412f3c9519c8
# via
# -r requirements.in
# cryptoadvance-spectrum
# flask-apscheduler
# flask-babel
# flask-cors
# flask-httpauth
# flask-login
# flask-restful
# flask-sqlalchemy
# flask-wtf
flask-apscheduler==1.12.3 \
--hash=sha256:d60948d1f2be9eb4772f68c3308ba3f973755219d13947266f89292ad6df63fc
@ -201,10 +199,82 @@ flask-restful==0.3.9 \
--hash=sha256:4970c49b6488e46c520b325f54833374dc2b98e211f1b272bd4b0c516232afe2 \
--hash=sha256:ccec650b835d48192138c85329ae03735e6ced58e9b2d9c2146d6c84c06fa53e
# via -r requirements.in
flask-sqlalchemy==2.5.1 \
--hash=sha256:2bda44b43e7cacb15d4e05ff3cc1f8bc97936cc464623424102bfc2c35e95912 \
--hash=sha256:f12c3d4cc5cc7fdcc148b9527ea05671718c3ea45d50c7e732cceb33f574b390
# via cryptoadvance-spectrum
flask-wtf==0.15.1 \
--hash=sha256:6ff7af73458f182180906a37a783e290bdc8a3817fe4ad17227563137ca285bf \
--hash=sha256:ff177185f891302dc253437fe63081e7a46a4e99aca61dfe086fb23e54fff2dc
# via -r requirements.in
greenlet==1.1.3.post0 \
--hash=sha256:0120a879aa2b1ac5118bce959ea2492ba18783f65ea15821680a256dfad04754 \
--hash=sha256:025b8de2273d2809f027d347aa2541651d2e15d593bbce0d5f502ca438c54136 \
--hash=sha256:05ae7383f968bba4211b1fbfc90158f8e3da86804878442b4fb6c16ccbcaa519 \
--hash=sha256:0914f02fcaa8f84f13b2df4a81645d9e82de21ed95633765dd5cc4d3af9d7403 \
--hash=sha256:0971d37ae0eaf42344e8610d340aa0ad3d06cd2eee381891a10fe771879791f9 \
--hash=sha256:0a954002064ee919b444b19c1185e8cce307a1f20600f47d6f4b6d336972c809 \
--hash=sha256:0aa1845944e62f358d63fcc911ad3b415f585612946b8edc824825929b40e59e \
--hash=sha256:104f29dd822be678ef6b16bf0035dcd43206a8a48668a6cae4d2fe9c7a7abdeb \
--hash=sha256:11fc7692d95cc7a6a8447bb160d98671ab291e0a8ea90572d582d57361360f05 \
--hash=sha256:17a69967561269b691747e7f436d75a4def47e5efcbc3c573180fc828e176d80 \
--hash=sha256:2794eef1b04b5ba8948c72cc606aab62ac4b0c538b14806d9c0d88afd0576d6b \
--hash=sha256:2c6e942ca9835c0b97814d14f78da453241837419e0d26f7403058e8db3e38f8 \
--hash=sha256:2ccdc818cc106cc238ff7eba0d71b9c77be868fdca31d6c3b1347a54c9b187b2 \
--hash=sha256:325f272eb997916b4a3fc1fea7313a8adb760934c2140ce13a2117e1b0a8095d \
--hash=sha256:39464518a2abe9c505a727af7c0b4efff2cf242aa168be5f0daa47649f4d7ca8 \
--hash=sha256:3a24f3213579dc8459e485e333330a921f579543a5214dbc935bc0763474ece3 \
--hash=sha256:3aeac044c324c1a4027dca0cde550bd83a0c0fbff7ef2c98df9e718a5086c194 \
--hash=sha256:3c22998bfef3fcc1b15694818fc9b1b87c6cc8398198b96b6d355a7bcb8c934e \
--hash=sha256:467b73ce5dcd89e381292fb4314aede9b12906c18fab903f995b86034d96d5c8 \
--hash=sha256:4a8b58232f5b72973350c2b917ea3df0bebd07c3c82a0a0e34775fc2c1f857e9 \
--hash=sha256:4f74aa0092602da2069df0bc6553919a15169d77bcdab52a21f8c5242898f519 \
--hash=sha256:5662492df0588a51d5690f6578f3bbbd803e7f8d99a99f3bf6128a401be9c269 \
--hash=sha256:5c2d21c2b768d8c86ad935e404cc78c30d53dea009609c3ef3a9d49970c864b5 \
--hash=sha256:5edf75e7fcfa9725064ae0d8407c849456553a181ebefedb7606bac19aa1478b \
--hash=sha256:60839ab4ea7de6139a3be35b77e22e0398c270020050458b3d25db4c7c394df5 \
--hash=sha256:62723e7eb85fa52e536e516ee2ac91433c7bb60d51099293671815ff49ed1c21 \
--hash=sha256:64e10f303ea354500c927da5b59c3802196a07468332d292aef9ddaca08d03dd \
--hash=sha256:66aa4e9a726b70bcbfcc446b7ba89c8cec40f405e51422c39f42dfa206a96a05 \
--hash=sha256:695d0d8b5ae42c800f1763c9fce9d7b94ae3b878919379150ee5ba458a460d57 \
--hash=sha256:70048d7b2c07c5eadf8393e6398595591df5f59a2f26abc2f81abca09610492f \
--hash=sha256:7afa706510ab079fd6d039cc6e369d4535a48e202d042c32e2097f030a16450f \
--hash=sha256:7cf37343e43404699d58808e51f347f57efd3010cc7cee134cdb9141bd1ad9ea \
--hash=sha256:8149a6865b14c33be7ae760bcdb73548bb01e8e47ae15e013bf7ef9290ca309a \
--hash=sha256:814f26b864ed2230d3a7efe0336f5766ad012f94aad6ba43a7c54ca88dd77cba \
--hash=sha256:82a38d7d2077128a017094aff334e67e26194f46bd709f9dcdacbf3835d47ef5 \
--hash=sha256:83a7a6560df073ec9de2b7cb685b199dfd12519bc0020c62db9d1bb522f989fa \
--hash=sha256:8415239c68b2ec9de10a5adf1130ee9cb0ebd3e19573c55ba160ff0ca809e012 \
--hash=sha256:88720794390002b0c8fa29e9602b395093a9a766b229a847e8d88349e418b28a \
--hash=sha256:890f633dc8cb307761ec566bc0b4e350a93ddd77dc172839be122be12bae3e10 \
--hash=sha256:8926a78192b8b73c936f3e87929931455a6a6c6c385448a07b9f7d1072c19ff3 \
--hash=sha256:8c0581077cf2734569f3e500fab09c0ff6a2ab99b1afcacbad09b3c2843ae743 \
--hash=sha256:8fda1139d87ce5f7bd80e80e54f9f2c6fe2f47983f1a6f128c47bf310197deb6 \
--hash=sha256:91a84faf718e6f8b888ca63d0b2d6d185c8e2a198d2a7322d75c303e7097c8b7 \
--hash=sha256:924df1e7e5db27d19b1359dc7d052a917529c95ba5b8b62f4af611176da7c8ad \
--hash=sha256:949c9061b8c6d3e6e439466a9be1e787208dec6246f4ec5fffe9677b4c19fcc3 \
--hash=sha256:9649891ab4153f217f319914455ccf0b86986b55fc0573ce803eb998ad7d6854 \
--hash=sha256:96656c5f7c95fc02c36d4f6ef32f4e94bb0b6b36e6a002c21c39785a4eec5f5d \
--hash=sha256:a812df7282a8fc717eafd487fccc5ba40ea83bb5b13eb3c90c446d88dbdfd2be \
--hash=sha256:a8d24eb5cb67996fb84633fdc96dbc04f2d8b12bfcb20ab3222d6be271616b67 \
--hash=sha256:bef49c07fcb411c942da6ee7d7ea37430f830c482bf6e4b72d92fd506dd3a427 \
--hash=sha256:bffba15cff4802ff493d6edcf20d7f94ab1c2aee7cfc1e1c7627c05f1102eee8 \
--hash=sha256:c0643250dd0756f4960633f5359884f609a234d4066686754e834073d84e9b51 \
--hash=sha256:c6f90234e4438062d6d09f7d667f79edcc7c5e354ba3a145ff98176f974b8132 \
--hash=sha256:c8c9301e3274276d3d20ab6335aa7c5d9e5da2009cccb01127bddb5c951f8870 \
--hash=sha256:c8ece5d1a99a2adcb38f69af2f07d96fb615415d32820108cd340361f590d128 \
--hash=sha256:cb863057bed786f6622982fb8b2c122c68e6e9eddccaa9fa98fd937e45ee6c4f \
--hash=sha256:ccbe7129a282ec5797df0451ca1802f11578be018a32979131065565da89b392 \
--hash=sha256:d25cdedd72aa2271b984af54294e9527306966ec18963fd032cc851a725ddc1b \
--hash=sha256:d75afcbb214d429dacdf75e03a1d6d6c5bd1fa9c35e360df8ea5b6270fb2211c \
--hash=sha256:d7815e1519a8361c5ea2a7a5864945906f8e386fa1bc26797b4d443ab11a4589 \
--hash=sha256:eb6ac495dccb1520667cfea50d89e26f9ffb49fa28496dea2b95720d8b45eb54 \
--hash=sha256:ec615d2912b9ad807afd3be80bf32711c0ff9c2b00aa004a45fd5d5dde7853d9 \
--hash=sha256:f5e09dc5c6e1796969fd4b775ea1417d70e49a5df29aaa8e5d10675d9e11872c \
--hash=sha256:f6661b58412879a2aa099abb26d3c93e91dedaba55a6394d1fb1512a77e85de9 \
--hash=sha256:f7d20c3267385236b4ce54575cc8e9f43e7673fc761b069c820097092e318e3b \
--hash=sha256:fe7c51f8a2ab616cb34bc33d810c887e89117771028e1e3d3b77ca25ddeace04
# via sqlalchemy
gunicorn==20.1.0 \
--hash=sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e \
--hash=sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8
@ -258,9 +328,11 @@ idna==3.4 \
importlib-metadata==4.8.1 \
--hash=sha256:b618b6d2d5ffa2f16add5697cf57a46c76a56229b0ed1c438322e4e95645bd15 \
--hash=sha256:f284b3e11256ad1e5d03ab86bb2ccd6f5339688ff17a4d797a0fe7df326f23b1
# via
# -r requirements.in
# flask
# via -r requirements.in
iniconfig==1.1.1 \
--hash=sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3 \
--hash=sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32
# via pytest
itsdangerous==2.1.2 \
--hash=sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44 \
--hash=sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a
@ -333,10 +405,18 @@ noiseprotocol==0.3.1 \
--hash=sha256:2e1a603a38439636cf0ffd8b3e8b12cee27d368a28b41be7dbe568b2abb23111 \
--hash=sha256:b092a871b60f6a8f07f17950dc9f7098c8fe7d715b049bd4c24ee3752b90d645
# via bitbox02
packaging==21.3 \
--hash=sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb \
--hash=sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522
# via pytest
pgpy==0.5.4 \
--hash=sha256:bdd3da1e006fc8e81cc02232969924d6e8c98a4af1621a925d99bba09164183b \
--hash=sha256:c29ad9b2bcba6575c3773410894e77a7552b6a3de184fd99b4da3995986f26a9
# via -r requirements.in
pluggy==1.0.0 \
--hash=sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159 \
--hash=sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3
# via pytest
protobuf==3.20.2 \
--hash=sha256:03d76b7bd42ac4a6e109742a4edf81ffe26ffd87c5993126d894fe48a120396a \
--hash=sha256:09e25909c4297d71d97612f04f41cea8fa8510096864f2835ad2f3b3df5a5559 \
@ -397,6 +477,79 @@ psutil==5.9.0 \
--hash=sha256:ef216cc9feb60634bda2f341a9559ac594e2eeaadd0ba187a4c2eb5b5d40b91c \
--hash=sha256:ff0d41f8b3e9ebb6b6110057e40019a432e96aae2008951121ba4e56040b84f3
# via -r requirements.in
psycopg2-binary==2.9.5 \
--hash=sha256:00475004e5ed3e3bf5e056d66e5dcdf41a0dc62efcd57997acd9135c40a08a50 \
--hash=sha256:01ad49d68dd8c5362e4bfb4158f2896dc6e0c02e87b8a3770fc003459f1a4425 \
--hash=sha256:024030b13bdcbd53d8a93891a2cf07719715724fc9fee40243f3bd78b4264b8f \
--hash=sha256:02551647542f2bf89073d129c73c05a25c372fc0a49aa50e0de65c3c143d8bd0 \
--hash=sha256:043a9fd45a03858ff72364b4b75090679bd875ee44df9c0613dc862ca6b98460 \
--hash=sha256:05b3d479425e047c848b9782cd7aac9c6727ce23181eb9647baf64ffdfc3da41 \
--hash=sha256:0775d6252ccb22b15da3b5d7adbbf8cfe284916b14b6dc0ff503a23edb01ee85 \
--hash=sha256:1764546ffeaed4f9428707be61d68972eb5ede81239b46a45843e0071104d0dd \
--hash=sha256:1e491e6489a6cb1d079df8eaa15957c277fdedb102b6a68cfbf40c4994412fd0 \
--hash=sha256:212757ffcecb3e1a5338d4e6761bf9c04f750e7d027117e74aa3cd8a75bb6fbd \
--hash=sha256:215d6bf7e66732a514f47614f828d8c0aaac9a648c46a831955cb103473c7147 \
--hash=sha256:25382c7d174c679ce6927c16b6fbb68b10e56ee44b1acb40671e02d29f2fce7c \
--hash=sha256:2abccab84d057723d2ca8f99ff7b619285d40da6814d50366f61f0fc385c3903 \
--hash=sha256:2d964eb24c8b021623df1c93c626671420c6efadbdb8655cb2bd5e0c6fa422ba \
--hash=sha256:2ec46ed947801652c9643e0b1dc334cfb2781232e375ba97312c2fc256597632 \
--hash=sha256:2ef892cabdccefe577088a79580301f09f2a713eb239f4f9f62b2b29cafb0577 \
--hash=sha256:33e632d0885b95a8b97165899006c40e9ecdc634a529dca7b991eb7de4ece41c \
--hash=sha256:3520d7af1ebc838cc6084a3281145d5cd5bdd43fdef139e6db5af01b92596cb7 \
--hash=sha256:3d790f84201c3698d1bfb404c917f36e40531577a6dda02e45ba29b64d539867 \
--hash=sha256:3fc33295cfccad697a97a76dec3f1e94ad848b7b163c3228c1636977966b51e2 \
--hash=sha256:422e3d43b47ac20141bc84b3d342eead8d8099a62881a501e97d15f6addabfe9 \
--hash=sha256:426c2ae999135d64e6a18849a7d1ad0e1bd007277e4a8f4752eaa40a96b550ff \
--hash=sha256:46512486be6fbceef51d7660dec017394ba3e170299d1dc30928cbedebbf103a \
--hash=sha256:46850a640df62ae940e34a163f72e26aca1f88e2da79148e1862faaac985c302 \
--hash=sha256:484405b883630f3e74ed32041a87456c5e0e63a8e3429aa93e8714c366d62bd1 \
--hash=sha256:4e7904d1920c0c89105c0517dc7e3f5c20fb4e56ba9cdef13048db76947f1d79 \
--hash=sha256:56b2957a145f816726b109ee3d4e6822c23f919a7d91af5a94593723ed667835 \
--hash=sha256:5c6527c8efa5226a9e787507652dd5ba97b62d29b53c371a85cd13f957fe4d42 \
--hash=sha256:5cbc554ba47ecca8cd3396ddaca85e1ecfe3e48dd57dc5e415e59551affe568e \
--hash=sha256:5d28ecdf191db558d0c07d0f16524ee9d67896edf2b7990eea800abeb23ebd61 \
--hash=sha256:5fc447058d083b8c6ac076fc26b446d44f0145308465d745fba93a28c14c9e32 \
--hash=sha256:63e318dbe52709ed10d516a356f22a635e07a2e34c68145484ed96a19b0c4c68 \
--hash=sha256:68d81a2fe184030aa0c5c11e518292e15d342a667184d91e30644c9d533e53e1 \
--hash=sha256:6e63814ec71db9bdb42905c925639f319c80e7909fb76c3b84edc79dadef8d60 \
--hash=sha256:6f8a9bcab7b6db2e3dbf65b214dfc795b4c6b3bb3af922901b6a67f7cb47d5f8 \
--hash=sha256:70831e03bd53702c941da1a1ad36c17d825a24fbb26857b40913d58df82ec18b \
--hash=sha256:74eddec4537ab1f701a1647214734bc52cee2794df748f6ae5908e00771f180a \
--hash=sha256:7b3751857da3e224f5629400736a7b11e940b5da5f95fa631d86219a1beaafec \
--hash=sha256:7cf1d44e710ca3a9ce952bda2855830fe9f9017ed6259e01fcd71ea6287565f5 \
--hash=sha256:7d07f552d1e412f4b4e64ce386d4c777a41da3b33f7098b6219012ba534fb2c2 \
--hash=sha256:7d88db096fa19d94f433420eaaf9f3c45382da2dd014b93e4bf3215639047c16 \
--hash=sha256:7ee3095d02d6f38bd7d9a5358fcc9ea78fcdb7176921528dd709cc63f40184f5 \
--hash=sha256:902844f9c4fb19b17dfa84d9e2ca053d4a4ba265723d62ea5c9c26b38e0aa1e6 \
--hash=sha256:937880290775033a743f4836aa253087b85e62784b63fd099ee725d567a48aa1 \
--hash=sha256:95076399ec3b27a8f7fa1cc9a83417b1c920d55cf7a97f718a94efbb96c7f503 \
--hash=sha256:9c38d3869238e9d3409239bc05bc27d6b7c99c2a460ea337d2814b35fb4fea1b \
--hash=sha256:9e32cedc389bcb76d9f24ea8a012b3cb8385ee362ea437e1d012ffaed106c17d \
--hash=sha256:9ffdc51001136b699f9563b1c74cc1f8c07f66ef7219beb6417a4c8aaa896c28 \
--hash=sha256:a0adef094c49f242122bb145c3c8af442070dc0e4312db17e49058c1702606d4 \
--hash=sha256:a36a0e791805aa136e9cbd0ffa040d09adec8610453ee8a753f23481a0057af5 \
--hash=sha256:a7e518a0911c50f60313cb9e74a169a65b5d293770db4770ebf004245f24b5c5 \
--hash=sha256:af0516e1711995cb08dc19bbd05bec7dbdebf4185f68870595156718d237df3e \
--hash=sha256:b8104f709590fff72af801e916817560dbe1698028cd0afe5a52d75ceb1fce5f \
--hash=sha256:b911dfb727e247340d36ae20c4b9259e4a64013ab9888ccb3cbba69b77fd9636 \
--hash=sha256:b9a794cef1d9c1772b94a72eec6da144c18e18041d294a9ab47669bc77a80c1d \
--hash=sha256:b9c33d4aef08dfecbd1736ceab8b7b3c4358bf10a0121483e5cd60d3d308cc64 \
--hash=sha256:b9d38a4656e4e715d637abdf7296e98d6267df0cc0a8e9a016f8ba07e4aa3eeb \
--hash=sha256:bcda1c84a1c533c528356da5490d464a139b6e84eb77cc0b432e38c5c6dd7882 \
--hash=sha256:bef7e3f9dc6f0c13afdd671008534be5744e0e682fb851584c8c3a025ec09720 \
--hash=sha256:c15ba5982c177bc4b23a7940c7e4394197e2d6a424a2d282e7c236b66da6d896 \
--hash=sha256:c5254cbd4f4855e11cebf678c1a848a3042d455a22a4ce61349c36aafd4c2267 \
--hash=sha256:c5682a45df7d9642eff590abc73157c887a68f016df0a8ad722dcc0f888f56d7 \
--hash=sha256:c5e65c6ac0ae4bf5bef1667029f81010b6017795dcb817ba5c7b8a8d61fab76f \
--hash=sha256:d4c7b3a31502184e856df1f7bbb2c3735a05a8ce0ade34c5277e1577738a5c91 \
--hash=sha256:d892bfa1d023c3781a3cab8dd5af76b626c483484d782e8bd047c180db590e4c \
--hash=sha256:dbc332beaf8492b5731229a881807cd7b91b50dbbbaf7fe2faf46942eda64a24 \
--hash=sha256:dc85b3777068ed30aff8242be2813038a929f2084f69e43ef869daddae50f6ee \
--hash=sha256:e59137cdb970249ae60be2a49774c6dfb015bd0403f05af1fe61862e9626642d \
--hash=sha256:e67b3c26e9b6d37b370c83aa790bbc121775c57bfb096c2e77eacca25fd0233b \
--hash=sha256:e72c91bda9880f097c8aa3601a2c0de6c708763ba8128006151f496ca9065935 \
--hash=sha256:f95b8aca2703d6a30249f83f4fe6a9abf2e627aa892a5caaab2267d56be7ab69
# via cryptoadvance-spectrum
pyaes==1.6.1 \
--hash=sha256:02c1b1405c38d3c370b085fb952dd8bea3fadcee6411ad99f312cc129c536d8f
# via hwi
@ -416,6 +569,10 @@ pyopenssl==20.0.1 \
--hash=sha256:4c231c759543ba02560fcd2480c48dcec4dae34c9da7d3747c508227e0624b51 \
--hash=sha256:818ae18e06922c066f777a33f1fca45786d85edfe71cd043de6379337a7f274b
# via -r requirements.in
pyparsing==3.0.9 \
--hash=sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb \
--hash=sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc
# via packaging
pyserial==3.5 \
--hash=sha256:3c77e014170dfffbd816e6ffc205e9842efb10be9f58ec16d3e8675b4925cddb \
--hash=sha256:c4451db6ba391ca6ca299fb3ec7bae67a5c55dde170964c7a14ceefec02f2cf0
@ -425,6 +582,10 @@ pysocks==1.7.1 \
--hash=sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5 \
--hash=sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0
# via -r requirements.in
pytest==7.2.0 \
--hash=sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71 \
--hash=sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59
# via cryptoadvance-spectrum
python-dateutil==2.8.2 \
--hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \
--hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9
@ -452,7 +613,9 @@ pytz-deprecation-shim==0.1.0.post0 \
requests==2.26.0 \
--hash=sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24 \
--hash=sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7
# via -r requirements.in
# via
# -r requirements.in
# cryptoadvance-spectrum
semver==2.13.0 \
--hash=sha256:ced8b23dceb22134307c1b8abfa523da14198793d9787ac838e70e29e77458d4 \
--hash=sha256:fa0fe2722ee1c3f57eac478820c3a5ae2f624af8264cbdf9000c980ff7f75e3f
@ -475,9 +638,56 @@ specterext-exfund==0.1.7 \
specterext-faucet==0.1.2 \
--hash=sha256:86db78a6c41688152cfeec14efafd6d06c97e6edd9735461ee897495f90cb2e8
# via -r requirements.in
sqlalchemy==1.4.42 \
--hash=sha256:04f2598c70ea4a29b12d429a80fad3a5202d56dce19dd4916cc46a965a5ca2e9 \
--hash=sha256:0501f74dd2745ec38f44c3a3900fb38b9db1ce21586b691482a19134062bf049 \
--hash=sha256:0ee377eb5c878f7cefd633ab23c09e99d97c449dd999df639600f49b74725b80 \
--hash=sha256:11b2ec26c5d2eefbc3e6dca4ec3d3d95028be62320b96d687b6e740424f83b7d \
--hash=sha256:15d878929c30e41fb3d757a5853b680a561974a0168cd33a750be4ab93181628 \
--hash=sha256:177e41914c476ed1e1b77fd05966ea88c094053e17a85303c4ce007f88eff363 \
--hash=sha256:1811a0b19a08af7750c0b69e38dec3d46e47c4ec1d74b6184d69f12e1c99a5e0 \
--hash=sha256:1d0c23ecf7b3bc81e29459c34a3f4c68ca538de01254e24718a7926810dc39a6 \
--hash=sha256:22459fc1718785d8a86171bbe7f01b5c9d7297301ac150f508d06e62a2b4e8d2 \
--hash=sha256:28e881266a172a4d3c5929182fde6bb6fba22ac93f137d5380cc78a11a9dd124 \
--hash=sha256:2e56dfed0cc3e57b2f5c35719d64f4682ef26836b81067ee6cfad062290fd9e2 \
--hash=sha256:2fd49af453e590884d9cdad3586415922a8e9bb669d874ee1dc55d2bc425aacd \
--hash=sha256:3ab7c158f98de6cb4f1faab2d12973b330c2878d0c6b689a8ca424c02d66e1b3 \
--hash=sha256:4948b6c5f4e56693bbeff52f574279e4ff972ea3353f45967a14c30fb7ae2beb \
--hash=sha256:4e1c5f8182b4f89628d782a183d44db51b5af84abd6ce17ebb9804355c88a7b5 \
--hash=sha256:5ce6929417d5dce5ad1d3f147db81735a4a0573b8fb36e3f95500a06eaddd93e \
--hash=sha256:5ede1495174e69e273fad68ad45b6d25c135c1ce67723e40f6cf536cb515e20b \
--hash=sha256:5f966b64c852592469a7eb759615bbd351571340b8b344f1d3fa2478b5a4c934 \
--hash=sha256:6045b3089195bc008aee5c273ec3ba9a93f6a55bc1b288841bd4cfac729b6516 \
--hash=sha256:6c9d004eb78c71dd4d3ce625b80c96a827d2e67af9c0d32b1c1e75992a7916cc \
--hash=sha256:6e39e97102f8e26c6c8550cb368c724028c575ec8bc71afbbf8faaffe2b2092a \
--hash=sha256:723e3b9374c1ce1b53564c863d1a6b2f1dc4e97b1c178d9b643b191d8b1be738 \
--hash=sha256:876eb185911c8b95342b50a8c4435e1c625944b698a5b4a978ad2ffe74502908 \
--hash=sha256:9256563506e040daddccaa948d055e006e971771768df3bb01feeb4386c242b0 \
--hash=sha256:934472bb7d8666727746a75670a1f8d91a9cae8c464bba79da30a0f6faccd9e1 \
--hash=sha256:97ff50cd85bb907c2a14afb50157d0d5486a4b4639976b4a3346f34b6d1b5272 \
--hash=sha256:9b01d9cd2f9096f688c71a3d0f33f3cd0af8549014e66a7a7dee6fc214a7277d \
--hash=sha256:9e3a65ce9ed250b2f096f7b559fe3ee92e6605fab3099b661f0397a9ac7c8d95 \
--hash=sha256:a7dd5b7b34a8ba8d181402d824b87c5cee8963cb2e23aa03dbfe8b1f1e417cde \
--hash=sha256:a85723c00a636eed863adb11f1e8aaa36ad1c10089537823b4540948a8429798 \
--hash=sha256:b42c59ffd2d625b28cdb2ae4cde8488543d428cba17ff672a543062f7caee525 \
--hash=sha256:bd448b262544b47a2766c34c0364de830f7fb0772d9959c1c42ad61d91ab6565 \
--hash=sha256:ca9389a00f639383c93ed00333ed763812f80b5ae9e772ea32f627043f8c9c88 \
--hash=sha256:df76e9c60879fdc785a34a82bf1e8691716ffac32e7790d31a98d7dec6e81545 \
--hash=sha256:e12c6949bae10f1012ab5c0ea52ab8db99adcb8c7b717938252137cdf694c775 \
--hash=sha256:e4ef8cb3c5b326f839bfeb6af5f406ba02ad69a78c7aac0fbeeba994ad9bb48a \
--hash=sha256:e7e740453f0149437c101ea4fdc7eea2689938c5760d7dcc436c863a12f1f565 \
--hash=sha256:effc89e606165ca55f04f3f24b86d3e1c605e534bf1a96e4e077ce1b027d0b71 \
--hash=sha256:f0f574465b78f29f533976c06b913e54ab4980b9931b69aa9d306afff13a9471 \
--hash=sha256:fa5b7eb2051e857bf83bade0641628efe5a88de189390725d3e6033a1fff4257 \
--hash=sha256:fdb94a3d1ba77ff2ef11912192c066f01e68416f554c194d769391638c8ad09a
# via flask-sqlalchemy
stem==1.8.0 \
--hash=sha256:a0b48ea6224e95f22aa34c0bc3415f0eb4667ddeae3dfb5e32a6920c185568c2
# via -r requirements.in
tomli==2.0.1 \
--hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \
--hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f
# via pytest
typing-extensions==3.10.0.2 \
--hash=sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e \
--hash=sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7 \

View file

@ -179,6 +179,7 @@ class BaseConfig(object):
"cryptoadvance.specterext.exfund.service",
"cryptoadvance.specterext.faucet.service",
"cryptoadvance.specterext.electrum.service",
"cryptoadvance.specterext.spectrum.service",
]
# This is just a placeholder in order to be aware that you cannot set this

View file

@ -128,6 +128,10 @@ class NodeManager:
"""Returns a list of the names (not the aliases) of the nodes"""
return [node.name for node in self.nodes.values()]
def nodes_by_chain(self, chain: str) -> list:
"""Returns a list of nodes for a given blockchain"""
return [node for node in self.nodes.values() if node.chain == chain]
def switch_node(self, node_alias: str):
# This will throw an error if the node doesn't exist
logger.debug(f"Switching from {self._active_node} to {node_alias}.")

View file

@ -3,10 +3,8 @@ import os
import sys
import pathlib
import sys
import threading
import traceback
from typing import Dict
from typing import Dict
from flask_babel import lazy_gettext as _
from flask import copy_current_request_context
from cryptoadvance.specter.rpc import BitcoinRPC
@ -120,7 +118,7 @@ class WalletManager:
if "pytest" in sys.modules:
if self.allow_threading_for_testing:
logger.info("Using threads in updating the wallet manager.")
t = threading.Thread(
t = FlaskThread(
target=self._update,
args=(wallets_update_list,),
)
@ -131,7 +129,7 @@ class WalletManager:
else:
if use_threading:
logger.info("Using threads in updating the wallet manager.")
t = threading.Thread(
t = FlaskThread(
target=self._update,
args=(wallets_update_list,),
)

View file

@ -632,10 +632,6 @@ class Node(AbstractNode):
except Exception as e:
return False
@property
def chain(self):
return self.info["chain"]
@property
def asset_labels(self):
if not self.is_liquid:

View file

@ -21,7 +21,7 @@ from werkzeug.middleware.proxy_fix import ProxyFix
from werkzeug.wrappers import Response
from .hwi_server import hwi_server
from .services.callbacks import after_serverpy_init_app
from .services.callbacks import after_serverpy_init_app, specter_added_to_flask_app
from .specter import Specter
from .util.specter_migrator import SpecterMigrator
@ -180,6 +180,9 @@ def init_app(app: SpecterFlask, hwibridge=False, specter=None):
app.login = login
# Attach specter instance so child views (e.g. hwi) can access it
app.specter = specter
# Executing callback specter_added_to_flask_app
app.logger.info("Executing callback specter_added_to_flask_app ...")
specter.service_manager.execute_ext_callbacks(specter_added_to_flask_app)
if specter.config["auth"].get("method") == "none":
app.logger.info("Login disabled")
app.config["LOGIN_DISABLED"] = True

View file

@ -52,3 +52,8 @@ specter_persistence_callback = "specter_persistence_callback"
Will get called before every request via the Flask's @app.before_request
"""
flask_before_request = "flask_before_request"
"""
Will get called right after having access to app.specter
"""
specter_added_to_flask_app = "specter_added_to_flask_app"

View file

@ -110,7 +110,9 @@ class Specter:
# Migrating from Specter 1.3.1 and lower (prior to the node manager)
self.migrate_old_node_format()
logger.info("Instantiate NodeManager")
logger.info(
f"Instantiate NodeManager with node alias: {self.active_node_alias}."
)
self.node_manager = NodeManager(
proxy_url=self.proxy_url,
only_tor=self.only_tor,
@ -119,7 +121,9 @@ class Specter:
internal_bitcoind_version=self._internal_bitcoind_version,
data_folder=os.path.join(self.data_folder, "nodes"),
)
logger.debug(
f"This is the active node in the node manager: {self.node_manager.active_node}"
)
self.torbrowser_path = os.path.join(
self.data_folder, f"tor-binaries/tor{get_tor_daemon_suffix()}"
)
@ -299,8 +303,10 @@ class Specter:
# mark
def update_active_node(self, node_alias):
"""update the current active node to use"""
self.node_manager.switch_node(
node_alias
) # If the node alias doesn't exist, this throws an exception preventing incorrectly updating the config.
self.config_manager.update_active_node(node_alias)
self.node_manager.switch_node(node_alias)
self.check()
def update_setup_status(self, software_name, stage):

View file

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<g>
<path style="fill:#FBD971;" d="M512,256c0,141.383-114.617,256-256,256S0,397.383,0,256S114.617,0,256,0S512,114.617,512,256"/>
<g>
<path style="fill:#FFFFFF;" d="M414.897,176.473c0,29.255-23.711,52.966-52.966,52.966s-52.966-23.711-52.966-52.966
s23.711-52.966,52.966-52.966S414.897,147.219,414.897,176.473"/>
<path style="fill:#FFFFFF;" d="M203.034,176.473c0,29.255-23.711,52.966-52.966,52.966c-29.255,0-52.965-23.711-52.965-52.966
s23.711-52.966,52.965-52.966C179.324,123.508,203.034,147.219,203.034,176.473"/>
</g>
<path style="fill:#F29C1F;" d="M344.285,362.319c-2.798,0-5.561-1.324-7.265-3.805c-35.981-52.056-107.599-65.121-159.656-29.149
c-3.999,2.763-9.516,1.757-12.279-2.242c-2.772-4.017-1.766-9.516,2.242-12.288c60.072-41.499,142.689-26.43,184.205,33.633
c2.781,4.017,1.765,9.516-2.242,12.288C347.772,361.807,346.015,362.319,344.285,362.319"/>
<g>
<path d="M176.552,202.956c0,14.627-11.855,26.483-26.483,26.483c-14.627,0-26.483-11.855-26.483-26.483
s11.855-26.483,26.483-26.483C164.696,176.473,176.552,188.329,176.552,202.956"/>
<path d="M388.414,202.956c0,14.627-11.855,26.483-26.483,26.483c-14.627,0-26.483-11.855-26.483-26.483
s11.855-26.483,26.483-26.483C376.558,176.473,388.414,188.329,388.414,202.956"/>
</g>
<g>
<path style="fill:#F29C1F;" d="M187.517,112.616c-2.26,0-4.52-0.865-6.241-2.586c-8.333-8.333-19.421-12.924-31.206-12.924
c-11.785,0-22.872,4.59-31.206,12.924c-3.452,3.452-9.039,3.452-12.482,0c-3.452-3.443-3.452-9.031,0-12.482
c11.67-11.67,27.18-18.097,43.688-18.097s32.018,6.426,43.688,18.097c3.452,3.452,3.452,9.039,0,12.482
C192.037,111.751,189.777,112.616,187.517,112.616"/>
<path style="fill:#F29C1F;" d="M399.379,112.616c-2.26,0-4.52-0.865-6.241-2.586c-8.333-8.333-19.421-12.924-31.206-12.924
c-11.785,0-22.872,4.59-31.206,12.924c-3.452,3.452-9.039,3.452-12.482,0c-3.452-3.443-3.452-9.031,0-12.482
c11.67-11.67,27.18-18.097,43.688-18.097s32.018,6.426,43.688,18.097c3.452,3.452,3.452,9.039,0,12.482
C403.899,111.751,401.639,112.616,399.379,112.616"/>
</g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 496 496" style="enable-background:new 0 0 496 496;" xml:space="preserve">
<path style="fill:#CAD9DD;" d="M480,445.6c0,17.6-17.6,34.4-34.4,34.4H50.4C33.6,480,16,462.4,16,445.6V50.4
C16,33.6,33.6,16,50.4,16h395.2c16.8,0,34.4,17.6,34.4,34.4V445.6z"/>
<path style="fill:#B6CCD1;" d="M19.2,48.8C19.2,32,33.6,16,50.4,16h395.2c16.8,0,34.4,17.6,34.4,34.4v395.2
c0,17.6-16,30.4-32.8,30.4"/>
<path style="fill:#9EC1C6;" d="M24,72.8v385.6c0,10.4,13.6,21.6,26.4,21.6h14.4c-2.4-8-0.8-8.8-0.8-12V72.8c0-6.4,2.4-8.8,8.8-8.8
H468c3.2,0,4-1.6,12,0.8V50.4c0-12.8-11.2-26.4-21.6-26.4H72.8C44.8,24,24,44.8,24,72.8z"/>
<path style="fill:#2F4745;" d="M445.6,496H50.4C22.4,496,0,473.6,0,445.6V50.4C0,22.4,22.4,0,50.4,0h395.2c28,0,50.4,22.4,50.4,50.4
v395.2C496,473.6,473.6,496,445.6,496z M456,52c0-6.4-5.6-12-12-12H52c-6.4,0-12,5.6-12,12v392.8c0,5.6,5.6,11.2,12,11.2h392
c6.4,0,12-5.6,12-12V52z"/>
<path style="opacity:0.2;fill:#616F70;enable-background:new ;" d="M346.4,324.8l-48-48l48-48c7.2-7.2,10.4-16,10.4-25.6
c0-8.8-3.2-18.4-10.4-25.6c-14.4-13.6-36.8-13.6-50.4,0l-48,48l-48-48c-13.6-13.6-36.8-13.6-50.4,0c-13.6,13.6-13.6,36.8,0,50.4
l48,48l-48,48c-13.6,13.6-13.6,36.8,0,50.4s36.8,13.6,50.4,0l48-48l48,48c7.2,7.2,16,10.4,25.6,10.4c8.8,0,18.4-3.2,25.6-10.4
C360,361.6,360,338.4,346.4,324.8z"/>
<path style="fill:#EF0770;" d="M346.4,297.6l-48-48l48-48c7.2-7.2,10.4-16,10.4-25.6c0-8.8-3.2-18.4-10.4-25.6
c-14.4-13.6-36.8-13.6-50.4,0l-48,48l-48-48c-13.6-13.6-36.8-13.6-50.4,0c-13.6,13.6-13.6,36.8,0,50.4l48,48l-48,48
c-13.6,13.6-13.6,36.8,0,50.4s36.8,13.6,50.4,0l48-48l48,48c7.2,7.2,16,10.4,25.6,10.4c8.8,0,18.4-3.2,25.6-10.4
C360,334.4,360,312,346.4,297.6z"/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -1,5 +1,5 @@
import logging
import threading
from .flask import FlaskThread
import time
logger = logging.getLogger(__name__)
@ -29,7 +29,7 @@ class Checker:
if not self.running:
self.running = True
self.error_counter = 0
self.thread = threading.Thread(target=self.loop)
self.thread = FlaskThread(target=self.loop)
self.thread.daemon = True
self.thread.start()
logger.info(f"Checker {self.desc} started with period {self.period}")
@ -59,7 +59,7 @@ class Checker:
)
except Exception as e:
if self.error_counter < 5:
logger.error(e)
logger.exception(e)
self.error_counter = self.error_counter + 1
if self.error_counter == 4:
logger.error("The above Error-Message is now suppressed!")

View file

@ -30,7 +30,7 @@ class SpecterMigration_0002(SpecterMigration):
def description(self) -> str:
return """Node-class migration:
We introduced the Spectrum Node on an extension. With that, we made the choice of
the Node to be instantiated much more flexible. The node.json get a member called
the Node to be instantiated much more flexible. The node.json gets an attribute called
python_class which is the fully qualified package name of the class the NodeManager
should instantiate.
This migrates all the node.json files to the new format.
@ -38,19 +38,23 @@ class SpecterMigration_0002(SpecterMigration):
* Iterate over all nodes in ~/.specter/nodes/*.json
* load each node.json and adds the correct python_class
* stores it again
In order to reverse this migration, you do need to reverese the addition of the
In order to reverse this migration, you do need to reverse the addition of the
python_class like this:
sudo apt-get install moreutils jq
cd ~/.specter/nodes
# adding the external_node key again:
for file in `ls *.json`; do jq '. | select(.python_class=="cryptoadvance.specter.internal_node.InternalNode") + {"external_node":false} , . | select(.python_class=="cryptoadvance.specter.node.Node") + {"external_node":true}' $file | sponge $file ; done
# remove python_class key
for file in `ls *.json`; do jq 'del(.python_class)' $file | sponge $file ; done
cd ..
jq 'del(.migration_executions[] | select(.migration_id == 2))' migration_data.json | sponge migration_data.json
"""
# In an early iteration of the migration, the key "external_node" has been deleted as well.
# However, this breaks backwards compatibility. So in order to keep that (for some time),
# we don't delete that key (see below)
# If we do at some point in time (and we should), this rollback procedure might be helpful:
# adding the external_node key again:
# for file in `ls *.json`; do jq '. | select(.python_class=="cryptoadvance.specter.internal_node.InternalNode") + {"external_node":false} , . | select(.python_class=="cryptoadvance.specter.node.Node") + {"external_node":true}' $file | sponge $file ; done
def execute(self):
node_folder = os.path.join(self.data_folder, "nodes")
@ -77,9 +81,11 @@ class SpecterMigration_0002(SpecterMigration):
nodes_files[node_alias][
"python_class"
] = "cryptoadvance.specter.internal_node.InternalNode"
if nodes_files[node_alias].get("external_node"):
logger.info(f"Deleting external_node key of {node_alias} in node.json")
del nodes_files[node_alias]["external_node"]
# As described above, the "external_node" attribute is not deleted for backwards compatibility
# This code might come in handy, for a future migration which is doing that.
# if nodes_files[node_alias].get("external_node"):
# logger.info(f"Deleting external_node key of {node_alias} in node.json")
# del nodes_files[node_alias]["external_node"]
write_json_file(
nodes_files[node_alias], nodes_files[node_alias]["fullpath"]

View file

@ -550,7 +550,9 @@ def specter_regtest_configured(bitcoin_regtest, devices_filled_data_folder, node
"allow_threading_for_testing": False,
},
}
specter = Specter(data_folder=devices_filled_data_folder, config=config)
specter = Specter(
data_folder=devices_filled_data_folder, config=config, checker_threads=False
)
assert specter.chain == "regtest"
# Create a User
someuser = specter.user_manager.add_user(
@ -666,7 +668,7 @@ def app(specter_regtest_configured) -> SpecterFlask:
@pytest.fixture
def app_no_node(empty_data_folder) -> SpecterFlask:
specter = Specter(data_folder=empty_data_folder)
specter = Specter(data_folder=empty_data_folder, checker_threads=False)
app = create_app(config="cryptoadvance.specter.config.TestConfig")
app.app_context().push()
app.config["TESTING"] = True

View file

@ -5,6 +5,7 @@
"""
import os
import pytest
import traceback
import threading
@ -37,20 +38,22 @@ def pytest_exception_interact(node, call, report):
"""Making more clever investigations in case of Exceptions"""
if should_intercept(call):
print()
print("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
print("IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII")
print(
f"intercepting: {call.excinfo.value.__class__.__name__} while {report.when}"
)
print_exception(node, call, report)
print_threaddump(node, call, report)
print_debug_logs(node, call, report)
print("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
print_directory_content(node, call, report)
print("IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII")
yield
def print_exception(node, call, report):
"""prints a stacktrace of the intercepted Exception"""
print("XXXXXXXXXXXXXXXXXX_EXCEPTION_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
print(f"XXXXXXXXXXXXXXXXXX_EXCEPTION_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
traceback.print_exception(call.excinfo.value)
print("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
@ -67,7 +70,6 @@ def print_threaddump(node, call, report):
def print_debug_logs(node, call, report):
"""prints the debug-logs of all the Regtest instances"""
print(node)
if isinstance(call.excinfo.value, BrokenCoreConnectionException):
print("XXXXXXXXXXXXXXXXXX_DEBUG.LOG_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
regtests = []
@ -82,3 +84,14 @@ def print_debug_logs(node, call, report):
)
print(regtest.get_debug_log())
print("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
def print_directory_content(node, call, report):
if str(call.excinfo.value).startswith(
"[Errno 39]"
): # [Errno 39] Directory not empty: '/tmp/specter_home_tmp_vzn6u1rv'
folder = str(call.excinfo.value).split(":")[1][2:-1]
print("XXXXXXXXX_DIR_CONTENT_OF_{folder}_XXXXXXXXXXXXXXXXXXXXXXXXXXX")
for file in os.listdir(folder):
print(file)
print("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")

View file

@ -26,7 +26,9 @@ def specter_testnet_configured(bitcoin_regtest, devices_filled_data_folder):
"method": "rpcpasswordaspin",
},
}
specter = Specter(data_folder=devices_filled_data_folder, config=config)
specter = Specter(
data_folder=devices_filled_data_folder, config=config, checker_threads=False
)
specter.check()
assert specter.chain == "test"

View file

@ -20,11 +20,13 @@ def test_checker(caplog):
callback_mock.side_effect = Exception("someException")
checker.start()
time.sleep(
0.8
2
) # If the above assumptions are failing, you might want to increase this
checker.stop()
assert "someException" in caplog.text
# should output 5 times
assert caplog.text.count("someException") < 10
assert caplog.text.count("[ ERROR] someException") == 5
# But should also show stacktrace 5 times
assert caplog.text.count("Exception: someException") == 5
assert "The above Error-Message is now suppressed" in caplog.text
assert caplog.text.count("The above Error-Message is now suppressed") == 1

34
tests/test_fail.py Normal file
View file

@ -0,0 +1,34 @@
""" The tests in this file are built to intentionally fail in order to test the
functionality in the conf_visibility pytest plugin
Therefore, the tests are skipped
"""
import os
import pytest
import threading
import time
from cryptoadvance.specter.persistence import write_json_file
def thread_function(empty_data_folder):
fname = os.path.join(empty_data_folder, "some.file")
for i in range(0, 100000):
try:
with open(fname, "w") as f:
f.write("muh")
except FileNotFoundError as e:
print("---------------------\nFileNotFound Error for i = " + str(i))
raise e
@pytest.mark.skip
def test_fail(empty_data_folder):
print(empty_data_folder)
t = threading.Thread(
target=thread_function,
args=(empty_data_folder,),
)
t.start()
time.sleep(0.08)

View file

@ -10,7 +10,7 @@ from cryptoadvance.specter.user import *
def test_token_endpoints(client, empty_data_folder, caplog):
specter = Specter(data_folder=empty_data_folder)
specter = Specter(data_folder=empty_data_folder, checker_threads=False)
user = User.from_json(
user_dict={
"id": "someuser",

View file

@ -57,6 +57,8 @@ def test_ServiceManager_get_service_x_dirs(caplog):
def test_ServiceManager_get_service_packages(caplog):
caplog.set_level(logging.DEBUG)
packages = ServiceManager.get_service_packages()
assert "cryptoadvance.specterext.electrum.service" in packages
assert "cryptoadvance.specterext.electrum.devices.electrum" in packages
assert "cryptoadvance.specterext.swan.service" in packages
assert "cryptoadvance.specterext.electrum.service" in packages
assert "cryptoadvance.specterext.electrum.devices.electrum" in packages

View file

@ -8,7 +8,7 @@ def test_create_user(empty_data_folder):
Should add a new User to the `users` list, generate a user_secret, and write
the new User to json storage.
"""
specter = Specter(data_folder=empty_data_folder)
specter = Specter(data_folder=empty_data_folder, checker_threads=False)
user_manager = UserManager(specter=specter)
password = "somepassword"

View file

@ -372,7 +372,7 @@ def test_both_Storages_in_parallel(empty_data_folder, user1, user2):
}
class TestService(Service):
class MyTestService(Service):
id = "test_service"
@classmethod
@ -385,7 +385,7 @@ class TestService(Service):
def test_Service_reserve_address(empty_data_folder, caplog):
wallet_mock = MagicMock()
TestService.reserve_address(wallet_mock, "a", "someLabel")
MyTestService.reserve_address(wallet_mock, "a", "someLabel")
assert wallet_mock.associate_address_with_service.assert_called_once
@ -393,7 +393,7 @@ def test_reserve_addresses_with_mocks(empty_data_folder, caplog):
caplog.set_level(logging.DEBUG)
specter_mock = MagicMock()
specter_mock.data_folder = empty_data_folder
s = TestService(True, specter_mock)
s = MyTestService(True, specter_mock)
wallet_mock = MagicMock()
# We assume that we haven't yet reserved any addresses:
@ -419,7 +419,7 @@ def test_reserve_addresses_with_mocks(empty_data_folder, caplog):
def test_reserve_addresses_with_an_actual_wallet(wallet):
specter_mock = MagicMock()
test_service = TestService(True, specter_mock)
test_service = MyTestService(True, specter_mock)
# Reserve first address
test_service.reserve_address(
wallet, "bcrt1qcatuhg0gll3h7py4cmn53rjjn9xlsqfwj3zcej", "reserved_for_john_nash"

View file

@ -83,7 +83,9 @@ def test_abandon_purged_tx(
"method": "rpcpasswordaspin",
},
}
specter = Specter(data_folder=devices_filled_data_folder, config=config)
specter = Specter(
data_folder=devices_filled_data_folder, config=config, checker_threads=False
)
specter.check()
assert specter.info["mempool_info"]["maxmempool"] == 5 * 1000 * 1000 # 5MB

View file

@ -19,7 +19,7 @@ def test_generate_user_secret_on_decrypt_user_secret(empty_data_folder):
Should generate a user_secret if one does not yet exist when decrypt_user_secret
is called (happens during the login flow).
"""
specter = Specter(data_folder=empty_data_folder)
specter = Specter(data_folder=empty_data_folder, checker_threads=False)
password = "somepassword"
user = User.from_json(
@ -50,7 +50,7 @@ def test_generate_user_secret_on_set_password(empty_data_folder):
Should generate a user_secret if one does not yet exist when the User's password
is changed via set_password.
"""
specter = Specter(data_folder=empty_data_folder)
specter = Specter(data_folder=empty_data_folder, checker_threads=False)
password = "somepassword"
user = User.from_json(
@ -85,7 +85,7 @@ def test_reencrypt_user_secret_on_set_password(empty_data_folder):
"""
Should re-encrypt the user_secret when the user changes their password.
"""
specter = Specter(data_folder=empty_data_folder)
specter = Specter(data_folder=empty_data_folder, checker_threads=False)
password = "somepassword"
user = User.from_json(
@ -122,7 +122,7 @@ def test_reencrypt_user_secret_on_iterations_increase(empty_data_folder):
"""
Should re-encrypt the user_secret when the User.encryption_iterations is increased
"""
specter = Specter(data_folder=empty_data_folder)
specter = Specter(data_folder=empty_data_folder, checker_threads=False)
password = "somepassword"
user = User.from_json(

View file

@ -16,7 +16,7 @@ def test_underlying_requests(empty_data_folder):
"""This test might fail on MacOS
see #1512
"""
specter_mock = Specter(data_folder=empty_data_folder)
specter_mock = Specter(data_folder=empty_data_folder, checker_threads=False)
requests_session = specter_mock.requests_session()
currency = "eur"
price = requests_session.get(
@ -27,7 +27,7 @@ def test_underlying_requests(empty_data_folder):
def test_failsafe_request_get(empty_data_folder):
specter_mock = Specter(data_folder=empty_data_folder)
specter_mock = Specter(data_folder=empty_data_folder, checker_threads=False)
requests_session = specter_mock.requests_session()
currency = "notExisting"
url = "https://www.bitstamp.net/api/v2/ticker/btc{}".format(currency)

View file

@ -455,7 +455,9 @@ def specter_regtest_configured(bitcoin_regtest, devices_filled_data_folder):
"method": "rpcpasswordaspin",
},
}
specter = Specter(data_folder=devices_filled_data_folder, config=config)
specter = Specter(
data_folder=devices_filled_data_folder, config=config, checker_threads=False
)
assert specter.chain == "regtest"
# Create a User
someuser = specter.user_manager.add_user(
@ -529,7 +531,7 @@ def app(specter_regtest_configured) -> SpecterFlask:
@pytest.fixture
def app_no_node(empty_data_folder) -> SpecterFlask:
specter = Specter(data_folder=empty_data_folder)
specter = Specter(data_folder=empty_data_folder, checker_threads=False)
app = create_app(config="cryptoadvance.specter.config.TestConfig")
app.app_context().push()
app.config["TESTING"] = True