diff --git a/.github/workflows/nigiri-infra.yml b/.github/workflows/nigiri-infra.yml index 5e6285d..8d5308a 100644 --- a/.github/workflows/nigiri-infra.yml +++ b/.github/workflows/nigiri-infra.yml @@ -32,6 +32,47 @@ jobs: uses: vulpemventures/nigiri-github-action@v1 with: use_liquid: false + - name: Wait for Bitcoin RPC + run: | + python3 - <<'PY' + import json + import time + import urllib.error + import urllib.request + + url = "http://localhost:18443" + password_mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm() + password_mgr.add_password(None, url, "admin1", "123") + opener = urllib.request.build_opener( + urllib.request.HTTPBasicAuthHandler(password_mgr) + ) + payload = json.dumps({ + "jsonrpc": "2.0", + "id": "ci-ready", + "method": "getblockchaininfo", + "params": [], + }).encode() + + deadline = time.time() + 120 + last_error = None + while time.time() < deadline: + try: + request = urllib.request.Request( + url, + data=payload, + headers={"content-type": "application/json"}, + ) + with opener.open(request, timeout=5) as response: + result = json.loads(response.read())["result"] + print("Bitcoin RPC ready:", result["chain"], result["blocks"]) + raise SystemExit(0) + except Exception as exc: + last_error = exc + print("Waiting for Bitcoin RPC:", exc) + time.sleep(2) + + raise SystemExit(f"Bitcoin RPC did not become ready: {last_error}") + PY - name: Run integration tests run: | pytest tests/integration/basics.py diff --git a/pyproject.toml b/pyproject.toml index 64fcf0a..bb92bb2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,5 +54,6 @@ test = [ "mock", "black", "pre-commit", - "bdkpython" -] \ No newline at end of file + "Werkzeug<3", + "bdkpython==0.32.1" +] diff --git a/requirements.txt b/requirements.txt index b236612..f3a2a8f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ embit>=0.6.1 -Flask>=2.1.1 +Flask>=2.1.1,<2.3 Flask-SQLAlchemy==2.5.1 sqlalchemy>=1.4.42,<2.0 psycopg2-binary diff --git a/src/cryptoadvance/spectrum/util_specter.py b/src/cryptoadvance/spectrum/util_specter.py index 462072d..4d4effa 100644 --- a/src/cryptoadvance/spectrum/util_specter.py +++ b/src/cryptoadvance/spectrum/util_specter.py @@ -295,7 +295,9 @@ def trace_call_after(cls, url, payload, timestamp): def __getattr__(self, method): def fn(*args, **kwargs): r = self.multi([(method, *args)], **kwargs)[0] - if r["error"] is not None: + # Bitcoin Core 30.0 omits the JSON-RPC "error" field from successful + # responses instead of returning "error": null. + if r.get("error") is not None: raise Exception( f"Request error for method {method}{args}: {r['error']['message']}", r, diff --git a/tests/integration/elsock_test.py b/tests/integration/elsock_test.py index 6788b7e..5b5dbde 100644 --- a/tests/integration/elsock_test.py +++ b/tests/integration/elsock_test.py @@ -35,7 +35,7 @@ def callback(something): port=50002, callback=callback, use_ssl=True, - call_timeout=1, + call_timeout=10, ) ts = elsock.ping() logger.info(f"First working ping in {ts} ms") @@ -80,7 +80,7 @@ def callback(something): logger.info(elsock._socket) ts = elsock.ping() logger.info(f"second working ping in {ts} ms") - assert ts < 1 + assert ts < 10 assert caplog.text.count("ElectrumSocket Status changed") == 9 assert (