Skip to content

Commit

Permalink
network: add singleton accessor classmethod, port trustedcoin to aiohttp
Browse files Browse the repository at this point in the history
  • Loading branch information
ysangkok committed Sep 7, 2018
1 parent 8f4b57f commit 52b877a
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 46 deletions.
11 changes: 3 additions & 8 deletions electrum/exchange_rate.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from .i18n import _
from .util import PrintError, ThreadJob, make_dir, aiosafe
from .util import make_aiohttp_session

from .network import Network

# See https://en.wikipedia.org/wiki/ISO_4217
CCY_PRECISIONS = {'BHD': 3, 'BIF': 0, 'BYR': 0, 'CLF': 4, 'CLP': 0,
Expand All @@ -27,8 +27,6 @@
'RWF': 0, 'TND': 3, 'UGX': 0, 'UYI': 0, 'VND': 0,
'VUV': 0, 'XAF': 0, 'XAU': 4, 'XOF': 0, 'XPF': 0}

PROXY = None

class ExchangeBase(PrintError):

def __init__(self, on_quotes, on_history):
Expand All @@ -40,14 +38,14 @@ def __init__(self, on_quotes, on_history):
async def get_raw(self, site, get_string):
# APIs must have https
url = ''.join(['https://', site, get_string])
async with make_aiohttp_session(PROXY) as session:
async with make_aiohttp_session(Network.get_instance().proxy) as session:
async with session.get(url) as response:
return await response.text()

async def get_json(self, site, get_string):
# APIs must have https
url = ''.join(['https://', site, get_string])
async with make_aiohttp_session(PROXY) as session:
async with make_aiohttp_session(Network.get_instance().proxy) as session:
async with session.get(url) as response:
return await response.json()

Expand Down Expand Up @@ -448,11 +446,8 @@ def __init__(self, config, network):
self.trigger.set()
self.set_exchange(self.config_exchange())
make_dir(self.cache_dir)
self.set_proxy('bogus', self.network.proxy)

def set_proxy(self, trigger_name, *args):
global PROXY
PROXY = args[0]
self.trigger.set()

def get_currencies(self, h):
Expand Down
9 changes: 3 additions & 6 deletions electrum/gui/kivy/uix/dialogs/crash_reporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,6 @@ def __init__(self, main_window, exctype, value, tb):
self.ids.crash_message.text = BaseCrashReporter.CRASH_MESSAGE
self.ids.request_help_message.text = BaseCrashReporter.REQUEST_HELP_MESSAGE
self.ids.describe_error_message.text = BaseCrashReporter.DESCRIBE_ERROR_MESSAGE
self.proxy = self.main_window.network.proxy
self.main_window.network.register_callback(self.set_proxy, ['proxy_set'])

def set_proxy(self, evt, proxy):
self.proxy = proxy

def show_contents(self):
details = CrashReportDetails(self.get_report_string())
Expand All @@ -121,7 +116,9 @@ def show_popup(self, title, content):

def send_report(self):
try:
response = json.loads(BaseCrashReporter.send_report(self, self.main_window.network.asyncio_loop, self.proxy, "/crash.json"))
loop = self.main_window.network.asyncio_loop
proxy = self.main_window.network.proxy
response = json.loads(BaseCrashReporter.send_report(self, loop, proxy, "/crash.json"))
except (ValueError, ClientError):
self.show_popup(_('Unable to send report'), _("Please check your network connection."))
else:
Expand Down
9 changes: 2 additions & 7 deletions electrum/gui/qt/exception_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,6 @@ def __init__(self, main_window, exctype, value, tb):
BaseCrashReporter.__init__(self, exctype, value, tb)
self.main_window = main_window

self.proxy = self.main_window.network.proxy
self.main_window.network.register_callback(self.set_proxy, ['proxy_set'])

QWidget.__init__(self)
self.setWindowTitle('Electrum - ' + _('An Error Occurred'))
self.setMinimumSize(600, 300)
Expand Down Expand Up @@ -92,12 +89,10 @@ def __init__(self, main_window, exctype, value, tb):
self.setLayout(main_box)
self.show()

def set_proxy(self, evt, proxy):
self.proxy = proxy

def send_report(self):
try:
response = BaseCrashReporter.send_report(self, self.main_window.network.asyncio_loop, self.proxy)
proxy = self.main_window.network.proxy
response = BaseCrashReporter.send_report(self, self.main_window.network.asyncio_loop, proxy)
except BaseException as e:
traceback.print_exc(file=sys.stderr)
self.main_window.show_critical(_('There was a problem with the automatic reporting:') + '\n' +
Expand Down
8 changes: 8 additions & 0 deletions electrum/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ def deserialize_server(server_str):
def serialize_server(host, port, protocol):
return str(':'.join([host, port, protocol]))

INSTANCE = None

class Network(PrintError):
"""The Network class manages a set of connections to remote electrum
servers, each connected socket is handled by an Interface() object.
Expand All @@ -173,6 +175,8 @@ class Network(PrintError):
verbosity_filter = 'n'

def __init__(self, config=None):
global INSTANCE
INSTANCE = self
if config is None:
config = {} # Do not use mutables as default values!
self.config = SimpleConfig(config) if isinstance(config, dict) else config
Expand Down Expand Up @@ -244,6 +248,10 @@ def __init__(self, config=None):
# just to not trigger a warning from switch_to_interface the first time we change default_server
self.server_info_job.set_result(1)

@staticmethod
def get_instance():
return INSTANCE

def with_interface_lock(func):
def func_wrapper(self, *args, **kwargs):
with self.interface_lock:
Expand Down
60 changes: 35 additions & 25 deletions electrum/plugins/trustedcoin/trustedcoin.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,9 @@
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

import asyncio
import socket
import os
import requests
import json
import base64
from urllib.parse import urljoin
Expand All @@ -38,8 +37,9 @@
from electrum.wallet import Multisig_Wallet, Deterministic_Wallet
from electrum.i18n import _
from electrum.plugin import BasePlugin, hook
from electrum.util import NotEnoughFunds
from electrum.util import NotEnoughFunds, make_aiohttp_session
from electrum.storage import STO_EV_USER_PW
from electrum.network import Network

# signing_xpub is hardcoded so that the wallet can be restored from seed, without TrustedCoin's server
def get_signing_xpub():
Expand Down Expand Up @@ -104,34 +104,44 @@ def __init__(self, user_agent=None, base_url='https://api.trustedcoin.com/2/'):
self.user_agent = user_agent

def send_request(self, method, relative_url, data=None):
kwargs = {'headers': {}}
if self.user_agent:
kwargs['headers']['user-agent'] = self.user_agent
if method == 'get' and data:
kwargs['params'] = data
elif method == 'post' and data:
kwargs['data'] = json.dumps(data)
kwargs['headers']['content-type'] = 'application/json'
print("send_req")
return asyncio.run_coroutine_threadsafe(self._send_request(method, relative_url, data), Network.get_instance().asyncio_loop).result()

async def handle_response(self, resp):
if resp.status != 200:
try:
r = await resp.json()
message = r['message']
except:
message = await resp.text()
raise TrustedCoinException(message, resp.status)
try:
return await resp.json()
except:
return await resp.text()

async def _send_request(self, method, relative_url, data):
url = urljoin(self.base_url, relative_url)
if self.debug:
print('%s %s %s' % (method, url, data))
headers = {}
if self.user_agent:
headers['user-agent'] = self.user_agent
try:
response = requests.request(method, url, **kwargs)
proxy = Network.get_instance().proxy
async with make_aiohttp_session(proxy) as session:
if method == 'get':
async with session.get(url, params=data, headers=headers) as resp:
return await self.handle_response(resp)
elif method == 'post':
async with session.post(url, json=data, headers=headers) as resp:
return await self.handle_response(resp)
else:
assert False
except TrustedCoinException:
raise
except Exception as e:
raise ErrorConnectingServer(e)
if self.debug:
print(response.text)
if response.status_code != 200:
message = str(response.text)
if response.headers.get('content-type') == 'application/json':
r = response.json()
if 'message' in r:
message = r['message']
raise TrustedCoinException(message, response.status_code)
if response.headers.get('content-type') == 'application/json':
return response.json()
else:
return response.text

def get_terms_of_service(self, billing_plan='electrum-per-tx-otp'):
"""
Expand Down

0 comments on commit 52b877a

Please sign in to comment.