Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

setup(
name="cryptoadvance.spectrum",
version="0.2.0",
version="0.2.1",
license="MIT license",
url="https://github.com/cryptoadvance/spectrum",
description="Electrum adaptor for Specter-Desktop",
Expand Down
30 changes: 24 additions & 6 deletions src/cryptoadvance/specterext/spectrum/bridge_rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@
from cryptoadvance.specter.helpers import is_ip_private
from cryptoadvance.specter.specter_error import SpecterError, handle_exception
from cryptoadvance.specter.rpc import BitcoinRPC
from cryptoadvance.specter.rpc import RpcError as SpecterRpcError
from cryptoadvance.spectrum.spectrum import RPCError as SpectrumRpcError
from cryptoadvance.specter.specter_error import BrokenCoreConnectionException

from cryptoadvance.spectrum.spectrum import RPCError, Spectrum
from cryptoadvance.spectrum.spectrum import Spectrum

from flask import has_app_context

Expand Down Expand Up @@ -76,11 +78,27 @@ def multi(self, calls: list, **kwargs):

# Spectrum uses a DB and access to it needs an app-context. In order to keep that implementation
# detail within spectrum, we're establishing a context as needed.
if not has_app_context() and self._app is not None:
with self._app.app_context():
return [self.spectrum.jsonrpc(item,wallet_name=self.wallet_name) for item in payload]
else:
return [self.spectrum.jsonrpc(item,wallet_name=self.wallet_name) for item in payload]
try:
if not has_app_context() and self._app is not None:
with self._app.app_context():
result = [self.spectrum.jsonrpc(item,wallet_name=self.wallet_name, catch_exceptions=False) for item in payload]
else:
result = [self.spectrum.jsonrpc(item,wallet_name=self.wallet_name, catch_exceptions=False) for item in payload]
return result

except ValueError as ve:
mock_response = object()
mock_response.status_code = 500
mock_response.text =ve
raise SpecterRpcError(
f"Request error: {ve}", mock_response
)
except SpectrumRpcError as se:
mock_response = object()
mock_response.status_code = se.code
mock_response.text =se.message
raise SpecterRpcError(se.message, mock_response)


def __repr__(self) -> str:
return f"<BridgeRPC {self.spectrum}>"
10 changes: 5 additions & 5 deletions src/cryptoadvance/spectrum/elsock.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import time
import threading
import sys
from .util import SpectrumException, handle_exception
from .util import FlaskThread, SpectrumException, handle_exception

# TODO: normal handling of ctrl+C interrupt

Expand All @@ -33,16 +33,16 @@ def __init__(self, host="127.0.0.1", port=50001, use_ssl=False, callback=None, t
self._requests = []
self._notifications = []
logger.info("Starting ElectrumSocket Threads ...")
self._recv_thread = threading.Thread(target=self.recv_loop)
self._recv_thread = FlaskThread(target=self.recv_loop)
self._recv_thread.daemon = True
self._recv_thread.start()
self._write_thread = threading.Thread(target=self.write_loop)
self._write_thread = FlaskThread(target=self.write_loop)
self._write_thread.daemon = True
self._write_thread.start()
self._ping_thread = threading.Thread(target=self.ping_loop)
self._ping_thread = FlaskThread(target=self.ping_loop)
self._ping_thread.daemon = True
self._ping_thread.start()
self._notify_thread = threading.Thread(target=self.notify_loop)
self._notify_thread = FlaskThread(target=self.notify_loop)
self._notify_thread.daemon = True
self._notify_thread.start()
logger.info("Finished starting ElectrumSocket Threads")
Expand Down
7 changes: 5 additions & 2 deletions src/cryptoadvance/spectrum/spectrum.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from decimal import Decimal
import json
import logging
import math
Expand Down Expand Up @@ -316,7 +315,7 @@ def get_wallet(self, wallet_name):
raise RPCError(f"Requested wallet {wallet_name} does not exist or is not loaded", -18)
return w

def jsonrpc(self, obj, wallet_name=None):
def jsonrpc(self, obj, wallet_name=None, catch_exceptions=True):
method = obj.get("method")
id = obj.get("id", 0)
params = obj.get("params", [])
Expand Down Expand Up @@ -345,9 +344,13 @@ def jsonrpc(self, obj, wallet_name=None):
else:
res = m(*args, **kwargs)
except RPCError as e:
if not catch_exceptions:
raise e
logger.error(f"FAIL method: {method} wallet: {wallet_name} args: {args} kwargs: {kwargs} exc {e}")
return dict(result=None, error=e.to_dict(), id=id)
except Exception as e:
if not catch_exceptions:
raise e
logger.error(f"FAIL method: {method} wallet: {wallet_name} args: {args} kwargs: {kwargs} exc {e}")
handle_exception(e)
return dict(result=None, error={"code": -500, "message": str(e)}, id=id)
Expand Down
12 changes: 4 additions & 8 deletions src/cryptoadvance/spectrum/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,13 @@ def sat_to_btc(sat):
If we do it, also have a look at:
https://github.com/relativisticelectron/specter-desktop/pull/3
'''
if not isinstance(sat, Decimal):
sat = Decimal(sat)
sat = sat or Decimal(0) # if None is passed
return Decimal(round(sat * Decimal(1e-8), 8))
sat = sat or 0 # if None is passed
return round(sat * 1e-8, 8)


def btc_to_sat(btc):
if not isinstance(btc, Decimal):
btc = Decimal(btc)
btc = btc or Decimal(0) # if None is passed
return round(btc * Decimal(1e8))
btc = btc or 0 # if None is passed
return round(btc * 1e8)

class SpectrumException(Exception):
pass
Expand Down
6 changes: 6 additions & 0 deletions tests/test_spectrum_rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ def test_root(caplog,client):
assert result.status_code == 200
assert json.loads(result.data)["error"]["message"] == "Method not found (None)"

def test_unknownmethod(caplog, client):
caplog.set_level(logging.INFO)
caplog.set_level(logging.DEBUG, logger="cryptoadvance.spectrum")
result = client.post("/", json={"method":"unknownmethod"})
assert result.status_code == 200

def test_getmininginfo(caplog,client):
caplog.set_level(logging.INFO)
caplog.set_level(logging.DEBUG, logger="cryptoadvance.spectrum")
Expand Down
22 changes: 22 additions & 0 deletions utils/release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ case $key in
SET="yes"
shift
;;
commit)
COMMIT="yes"
shift
;;
tag)
TAG="yes"
shift
Expand Down Expand Up @@ -176,6 +180,9 @@ function main() {
if [[ -n "$SET" ]]; then
set
fi
if [[ -n "$COMMIT" ]]; then
commit
fi
if [[ -n "$TAG" ]]; then
tag
fi
Expand All @@ -196,6 +203,21 @@ function set() {
cat setup.py | grep version
}

function commit() {
if ! git status --porcelain | grep setup.py ; then
echo "setup.py has not been modified!"
exit 1
fi
if [[ $(git status --porcelain | wc -l) -ne 1 ]]; then
echo "setup.py needs to be the only change!"
exit 1
fi
echo " --> adding setup.py"
git add setup.py
echo " --> committing"
git commit -m "version $new_version"
}

function build() {
echo " --> Building the package for version $new_version"
python3 -m pip install --upgrade build
Expand Down