def api_qr_generate(address): """ Generate a QR image. Subject to IP throttling. :param address: valid receiving address :return: """ from funding.factory import cache qr = QrCodeGenerator() if not qr.exists(address): # create a new QR code ip = get_ip() cache_key = 'qr_ip_%s' % ip hit = cache.get(cache_key) if hit and ip not in ['127.0.0.1', 'localhost']: return Response('Wait a bit before generating a new QR', 403) throttling_seconds = 3 cache.set(cache_key, {'wow': 'kek'}, throttling_seconds) created = qr.create(address) if not created: raise Exception('Could not create QR code') return send_from_directory('static/qr', '%s.png' % address)
def fetch_stats(purge=False): from funding.factory import db_session from funding.orm.orm import Proposal, User, Comment from funding.factory import cache cache_key = 'funding_stats' data = cache.get(cache_key) if data and not purge: return data categories = settings.FUNDING_CATEGORIES statuses = settings.FUNDING_STATUSES.keys() for cat in categories: q = db_session.query(Proposal) q = q.filter(Proposal.category == cat) res = q.count() data.setdefault('cats', {}) data['cats'][cat] = res for status in statuses: q = db_session.query(Proposal) q = q.filter(Proposal.status == status) res = q.count() data.setdefault('statuses', {}) data['statuses'][status] = res data.setdefault('users', {}) data['users']['count'] = db_session.query(User.id).count() cache.set(cache_key, data=data, expiry=300) return data
def fetch_prices(): if hasattr(g, 'funding_prices') and g.coin_prices: return g.coin_prices from funding.factory import cache cache_key = 'funding_prices' data = cache.get(cache_key) if data: return data data = {'coin-btc': coin_btc_value(), 'btc-usd': price_cmc_btc_usd()} cache.set(cache_key, data=data, expiry=7200) g.coin_prices = data return data
def spends(self): from funding.bin.utils import Summary, coin_to_usd from funding.factory import cache, db_session rtn = {'sum': 0.0, 'txs': [], 'pct': 0.0} cache_key = 'coin_spends_pid_%d' % self.id data = cache.get(cache_key) if not data: from funding.bin.daemon import Daemon try: data = Daemon().get_transfers_out(proposal=self) if not isinstance(data, dict): print('error; get_transfers_out; %d' % self.id) return rtn cache.set(cache_key, data=data, expiry=60) except: print('error; get_transfers_out; %d' % self.id) return rtn data['remaining_pct'] = 0.0 prices = Summary.fetch_prices() for tx in data['txs']: if prices: tx['amount_usd'] = coin_to_usd(amt=tx['amount_human'], btc_per_coin=prices['coin-btc'], usd_per_btc=prices['btc-usd']) tx['datetime'] = datetime.fromtimestamp(tx['timestamp']) if data.get('sum', 0.0): data['pct'] = 100 / float(self.funds_target / data.get('sum', 0.0)) data['spent'] = data['sum'] else: data['pct'] = 0.0 data['spent'] = 0.0 cache_key_in = 'coin_balance_pid_%d' % self.id data_in = cache.get(cache_key_in) if data_in and data['spent']: data['remaining_pct'] = 100 / float(data_in['sum'] / data['spent']) return data
def balance(self): """This property retrieves the current funding status of this proposal. It uses Redis cache to not spam the daemon too much. Returns a nice dictionary containing all relevant proposal funding info""" from funding.bin.utils import Summary, coin_to_usd from funding.factory import cache, db_session rtn = {'sum': 0.0, 'txs': [], 'pct': 0.0, 'available': 0.0} cache_key = 'coin_balance_pid_%d' % self.id data = cache.get(cache_key) if not data: from funding.bin.daemon import Daemon try: data = Daemon().get_transfers_in(index=self.id, proposal_id=self.id) if not isinstance(data, dict): print('error; get_transfers_in; %d' % self.id) return rtn cache.set(cache_key, data=data, expiry=300) except: print('error; get_transfers_in; %d' % self.id) return rtn prices = Summary.fetch_prices() for tx in data['txs']: if prices: tx['amount_usd'] = coin_to_usd(amt=tx['amount_human'], btc_per_coin=prices['coin-btc'], usd_per_btc=prices['btc-usd']) tx['datetime'] = datetime.fromtimestamp(tx['timestamp']) if data.get('sum', 0.0): data['pct'] = 100 / float(self.funds_target / data.get('sum', 0.0)) data['available'] = data['sum'] else: data['pct'] = 0.0 data['available'] = 0.0 if data['pct'] != self.funds_progress: self.funds_progress = data['pct'] db_session.commit() db_session.flush() if data['available']: data['remaining_pct'] = 100 / float( data['sum'] / data['available']) else: data['remaining_pct'] = 0.0 return data
def api_wow_supply(): from funding.factory import cache cache_key = 'wow_supply' hit = cache.get(cache_key) if hit: return float(hit.get('data', -1)) try: resp = requests.get('http://explorer.wowne.ro/api/emission', headers={'User-Agent': 'WFS'}) resp.raise_for_status() blob = resp.json() assert 'data' in blob assert 'coinbase' in blob['data'] except: return Exception('error fetching circulating supply') supply = blob['data'].get('coinbase') / 100000000000 cache.set(cache_key, {'data': supply}, 120) return supply
def donate(): return "devfund page currently not working :D" data_default = {'sum': 0, 'txs': []} cache_key = 'devfund_txs_in' data = cache.get(cache_key) if not data: daemon = Daemon(url=settings.RPC_LOCATION_DEVFUND, username=settings.RPC_USERNAME_DEVFUND, password=settings.RPC_PASSWORD_DEVFUND) txs_in = daemon.get_transfers_in_simple() if not txs_in['txs']: cache.set(cache_key, data=data_default, expiry=60) else: txs_in['txs'] = txs_in['txs'][:50] # truncate to last 50 cache.set(cache_key, data=txs_in, expiry=60) else: for tx in data['txs']: tx['datetime'] = dateutil_parse(tx['datetime']) txs_in = data return make_response(render_template('donate.html', txs_in=txs_in))