electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit 3bac924303b4b4ae2e1009f11544c4afe7b99849
parent 9b7a62c36afe96eb05380eec541d2bfa2b699fa0
Author: ThomasV <thomasv@gitorious>
Date:   Sun, 12 Apr 2015 12:52:26 +0200

remove coinbase plugin

Diffstat:
Dplugins/coinbase_buyback.py | 320-------------------------------------------------------------------------------
1 file changed, 0 insertions(+), 320 deletions(-)

diff --git a/plugins/coinbase_buyback.py b/plugins/coinbase_buyback.py @@ -1,320 +0,0 @@ -import PyQt4 -import sys - -import PyQt4.QtCore as QtCore -import base64 -import urllib -import re -import time -import os -import httplib -import datetime -import json -import string - -from urllib import urlencode - -from PyQt4.QtGui import * -from PyQt4.QtCore import * -try: - from PyQt4.QtWebKit import QWebView - loaded_qweb = True -except ImportError as e: - loaded_qweb = False - -from electrum.plugins import BasePlugin, hook -from electrum.i18n import _, set_language -from electrum.util import user_dir -from electrum.util import format_satoshis -from electrum_gui.qt import ElectrumGui - -SATOSHIS_PER_BTC = float(100000000) -COINBASE_ENDPOINT = 'https://coinbase.com' -SCOPE = 'buy' -REDIRECT_URI = 'urn:ietf:wg:oauth:2.0:oob' -TOKEN_URI = 'https://coinbase.com/oauth/token' -CLIENT_ID = '0a930a48b5a6ea10fb9f7a9fec3d093a6c9062ef8a7eeab20681274feabdab06' -CLIENT_SECRET = 'f515989e8819f1822b3ac7a7ef7e57f755c9b12aee8f22de6b340a99fd0fd617' -# Expiry is stored in RFC3339 UTC format -EXPIRY_FORMAT = '%Y-%m-%dT%H:%M:%SZ' - -class Plugin(BasePlugin): - - def fullname(self): return 'Coinbase BuyBack' - - def description(self): return 'After sending bitcoin, prompt the user with the option to rebuy them via Coinbase.\n\nMarcell Ortutay, 1FNGQvm29tKM7y3niq63RKi7Qbg7oZ3jrB' - - def __init__(self, gui, name): - BasePlugin.__init__(self, gui, name) - self._is_available = self._init() - - def _init(self): - return loaded_qweb - - @hook - def init_qt(self, gui): - self.gui = gui - - def is_available(self): - return self._is_available - - def enable(self): - return BasePlugin.enable(self) - - @hook - def receive_tx(self, tx, wallet): - domain = wallet.get_account_addresses(None) - is_relevant, is_send, v, fee = tx.get_value(domain, wallet.prevout_values) - if isinstance(self.gui, ElectrumGui): - try: - web = propose_rebuy_qt(abs(v)) - except OAuth2Exception as e: - rm_local_oauth_credentials() - # TODO(ortutay): android flow - - -def propose_rebuy_qt(amount): - web = QWebView() - box = QMessageBox() - box.setFixedSize(200, 200) - - credentials = read_local_oauth_credentials() - questionText = _('Rebuy ') + format_satoshis(amount) + _(' BTC?') - if credentials: - credentials.refresh() - if credentials and not credentials.invalid: - credentials.store_locally() - totalPrice = get_coinbase_total_price(credentials, amount) - questionText += _('\n(Price: ') + totalPrice + _(')') - - if not question(box, questionText): - return - - if credentials: - do_buy(credentials, amount) - else: - do_oauth_flow(web, amount) - return web - -def do_buy(credentials, amount): - conn = httplib.HTTPSConnection('coinbase.com') - credentials.authorize(conn) - params = { - 'qty': float(amount)/SATOSHIS_PER_BTC, - 'agree_btc_amount_varies': False - } - resp = conn.auth_request('POST', '/api/v1/buys', urlencode(params), None) - - if resp.status != 200: - message(_('Error, could not buy bitcoin')) - return - content = json.loads(resp.read()) - if content['success']: - message(_('Success!\n') + content['transfer']['description']) - else: - if content['errors']: - message(_('Error: ') + string.join(content['errors'], '\n')) - else: - message(_('Error, could not buy bitcoin')) - -def get_coinbase_total_price(credentials, amount): - conn = httplib.HTTPSConnection('coinbase.com') - params={'qty': amount/SATOSHIS_PER_BTC} - conn.request('GET', '/api/v1/prices/buy?' + urlencode(params)) - resp = conn.getresponse() - if resp.status != 200: - return 'unavailable' - content = json.loads(resp.read()) - return '$' + content['total']['amount'] - -def do_oauth_flow(web, amount): - # QT expects un-escaped URL - auth_uri = step1_get_authorize_url() - web.load(QUrl(auth_uri)) - web.setFixedSize(500, 700) - web.show() - web.titleChanged.connect(lambda(title): complete_oauth_flow(title, web, amount) if re.search('^[a-z0-9]+$', title) else False) - -def complete_oauth_flow(token, web, amount): - web.close() - credentials = step2_exchange(str(token)) - credentials.store_locally() - do_buy(credentials, amount) - -def token_path(): - dir = user_dir() + '/coinbase_buyback' - if not os.access(dir, os.F_OK): - os.mkdir(dir) - return dir + '/token' - -def read_local_oauth_credentials(): - if not os.access(token_path(), os.F_OK): - return None - f = open(token_path(), 'r') - data = f.read() - f.close() - try: - credentials = Credentials.from_json(data) - return credentials - except Exception as e: - return None - -def rm_local_oauth_credentials(): - os.remove(token_path()) - -def step1_get_authorize_url(): - return ('https://coinbase.com/oauth/authorize' - + '?scope=' + SCOPE - + '&redirect_uri=' + REDIRECT_URI - + '&response_type=code' - + '&client_id=' + CLIENT_ID - + '&access_type=offline') - -def step2_exchange(code): - body = urllib.urlencode({ - 'grant_type': 'authorization_code', - 'client_id': CLIENT_ID, - 'client_secret': CLIENT_SECRET, - 'code': code, - 'redirect_uri': REDIRECT_URI, - 'scope': SCOPE, - }) - headers = { - 'content-type': 'application/x-www-form-urlencoded', - } - - conn = httplib.HTTPSConnection('coinbase.com') - conn.request('POST', TOKEN_URI, body, headers) - resp = conn.getresponse() - if resp.status == 200: - d = json.loads(resp.read()) - access_token = d['access_token'] - refresh_token = d.get('refresh_token', None) - token_expiry = None - if 'expires_in' in d: - token_expiry = datetime.datetime.utcnow() + datetime.timedelta( - seconds=int(d['expires_in'])) - return Credentials(access_token, refresh_token, token_expiry) - else: - raise OAuth2Exception(content) - -class OAuth2Exception(Exception): - """An error related to OAuth2""" - -class Credentials(object): - def __init__(self, access_token, refresh_token, token_expiry): - self.access_token = access_token - self.refresh_token = refresh_token - self.token_expiry = token_expiry - - # Indicates a failed refresh - self.invalid = False - - def to_json(self): - token_expiry = self.token_expiry - if (token_expiry and isinstance(token_expiry, datetime.datetime)): - token_expiry = token_expiry.strftime(EXPIRY_FORMAT) - - d = { - 'access_token': self.access_token, - 'refresh_token': self.refresh_token, - 'token_expiry': token_expiry, - } - return json.dumps(d) - - def store_locally(self): - f = open(token_path(), 'w') - f.write(self.to_json()) - f.close() - - @classmethod - def from_json(cls, s): - data = json.loads(s) - if ('token_expiry' in data - and not isinstance(data['token_expiry'], datetime.datetime)): - try: - data['token_expiry'] = datetime.datetime.strptime( - data['token_expiry'], EXPIRY_FORMAT) - except: - data['token_expiry'] = None - retval = Credentials( - data['access_token'], - data['refresh_token'], - data['token_expiry']) - return retval - - def apply(self, headers): - headers['Authorization'] = 'Bearer ' + self.access_token - - def authorize(self, conn): - request_orig = conn.request - - def new_request(method, uri, params, headers): - if headers == None: - headers = {} - self.apply(headers) - request_orig(method, uri, params, headers) - resp = conn.getresponse() - if resp.status == 401: - # Refresh and try again - self._refresh(request_orig) - self.store_locally() - self.apply(headers) - request_orig(method, uri, params, headers) - return conn.getresponse() - else: - return resp - - conn.auth_request = new_request - return conn - - def refresh(self): - try: - self._refresh() - except OAuth2Exception as e: - rm_local_oauth_credentials() - self.invalid = True - raise e - - def _refresh(self): - conn = httplib.HTTPSConnection('coinbase.com') - body = urllib.urlencode({ - 'grant_type': 'refresh_token', - 'refresh_token': self.refresh_token, - 'client_id': CLIENT_ID, - 'client_secret': CLIENT_SECRET, - }) - headers = { - 'content-type': 'application/x-www-form-urlencoded', - } - conn.request('POST', TOKEN_URI, body, headers) - resp = conn.getresponse() - if resp.status == 200: - d = json.loads(resp.read()) - self.token_response = d - self.access_token = d['access_token'] - self.refresh_token = d.get('refresh_token', self.refresh_token) - if 'expires_in' in d: - self.token_expiry = datetime.timedelta( - seconds=int(d['expires_in'])) + datetime.datetime.utcnow() - else: - raise OAuth2Exception('Refresh failed, ' + content) - -def message(msg): - box = QMessageBox() - box.setFixedSize(200, 200) - return QMessageBox.information(box, _('Message'), msg) - -def question(widget, msg): - return (QMessageBox.question( - widget, _('Message'), msg, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) - == QMessageBox.Yes) - -def main(): - app = QApplication(sys.argv) - print sys.argv[1] - propose_rebuy_qt(int(sys.argv[1])) - sys.exit(app.exec_()) - -if __name__ == "__main__": - main()