def sync_wallet_for_user(app_user): wallet = ThreeFoldWallet.create_key(app_user).get() if not wallet: return now_ = now() next_unlock_timestamp = 0 for token in wallet.tokens: for t in ThreeFoldTransaction.list_with_amount_left_by_token( app_user, token): for unlock_timestamp in t.unlock_timestamps: if unlock_timestamp > now_: if not next_unlock_timestamp: next_unlock_timestamp = unlock_timestamp elif next_unlock_timestamp > unlock_timestamp: next_unlock_timestamp = unlock_timestamp wallet.next_unlock_timestamp = next_unlock_timestamp wallet.put() for token in wallet.tokens: deferred.defer(sync_payment_asset, app_user, get_asset_id_from_token(app_user, token), _countdown=5)
def get_all_balances(app_user): transactions = ThreeFoldTransaction.list_with_amount_left(app_user) token_types = set(map(lambda transaction: transaction.token, transactions)) results = [] for token in token_types: transactions_per_token = [ trans for trans in transactions if trans.token == token ] results.append( _get_balance_from_transactions(transactions_per_token, token)) return results
def _save_transaction_to_backlog(transaction_id, backlog_type): return # Temporarily disabled if backlog_type not in ('tierion', 'git'): raise Exception('Invalid backlog_type') cfg = get_config(NAMESPACE) if not (cfg.ledger.url or cfg.ledger.secret): if DEBUG: logging.warn('Transaction backlog is not filled in, doing nothing') return raise Exception('Backlog config is not filled in') transaction = ThreeFoldTransaction.get_by_id(transaction_id) if not transaction: raise BusinessException('ThreeFoldTransaction with id %s not found!' % transaction_id) data = { 'id': transaction.id, 'timestamp': transaction.timestamp, 'amount': transaction.amount } if transaction.from_user: data['from'] = hmac.new(cfg.ledger.secret.encode(), transaction.from_user.email(), hashlib.sha1).hexdigest() if transaction.to_user: data['to'] = hmac.new(cfg.ledger.secret.encode(), transaction.to_user.email(), hashlib.sha1).hexdigest() headers = {'Authorization': cfg.ledger.secret} url = cfg.ledger.url + '/transactions/%s' % backlog_type result = urlfetch.fetch(url, json.dumps(data), urlfetch.POST, headers, deadline=30) if result.status_code not in (200, 201): logging.info('Status:%s Content: %s', result.status_code, result.content) raise Exception('Failed to add transaction to backlog')
def get_balance(app_user, token): # type: (users.User, unicode) -> WalletBalanceTO transactions = ThreeFoldTransaction.list_with_amount_left_by_token( app_user, token) return _get_balance_from_transactions(transactions, token)
def trans(keys): bh = ThreeFoldBlockHeight.get_block_height() if not bh.updating: logging.debug('Blockheight already syncing') return pt_key = keys.pop() if len(keys) == 0: deferred.defer(_sync_transactions, _countdown=1, _transactional=True) else: deferred.defer(_migrate_pending_transactions, keys, _transactional=True) pt = pt_key.get() if not pt: logging.debug('Pending transaction not found') return pt.synced = True height = bh.height + 1 funding_transactions_to_put = [] if pt.from_user: funding_transactions_keys = list_transactions_with_amount_left( pt.from_user, pt.token) funding_transactions = ndb.get_multi(funding_transactions_keys) amount_left = pt.amount for ft in funding_transactions: funding_transactions_to_put.append(ft) spendable_amount = get_spendable_amount_of_transaction(ft) if (amount_left - spendable_amount) >= 0: amount_left -= spendable_amount ft.amount_left -= spendable_amount if ft.amount_left == 0: ft.fully_spent = True else: ft.amount_left -= amount_left break else: logging.debug('Insufficient funds') pt.synced_status = ThreeFoldPendingTransaction.STATUS_FAILED pt.put() return # not enough money ... ndb.put_multi(funding_transactions_to_put) else: logging.info("Genesis payout to %s at height %s", pt.to_user, height) pt.synced_status = ThreeFoldPendingTransaction.STATUS_CONFIRMED pt.put() bh.timestamp = now() bh.height = height bh.put() new_transaction = ThreeFoldTransaction.create_new() new_transaction.timestamp = now() new_transaction.height = height new_transaction.unlock_timestamps = pt.unlock_timestamps new_transaction.unlock_amounts = pt.unlock_amounts new_transaction.token = pt.token new_transaction.token_type = pt.token_type new_transaction.amount = pt.amount new_transaction.amount_left = pt.amount new_transaction.fully_spent = False new_transaction.app_users = [] if pt.from_user: new_transaction.app_users.append(pt.from_user) deferred.defer(sync_payment_asset, pt.from_user, get_asset_id_from_token(pt.from_user, pt.token), _countdown=5, _transactional=True) if pt.to_user: new_transaction.app_users.append(pt.to_user) deferred.defer(sync_payment_asset, pt.to_user, get_asset_id_from_token(pt.to_user, pt.token), _countdown=5, _transactional=True) new_transaction.from_user = pt.from_user new_transaction.to_user = pt.to_user new_transaction.put() key = ThreeFoldWallet.create_key(pt.to_user) wallet = key.get() if not wallet: wallet = ThreeFoldWallet(key=key, tokens=[]) wallet.put() if pt.token not in wallet.tokens: wallet.tokens.append(pt.token) wallet.put() deferred.defer(_save_transaction_to_backlog, new_transaction.id, 'git', _transactional=True) deferred.defer(_save_transaction_to_backlog, new_transaction.id, 'tierion', _transactional=True)
def list_transactions_with_amount_left(app_user, token): return [ t.key for t in ThreeFoldTransaction.list_with_amount_left_by_token( app_user, token) ]
def get_transactions(app_user, token): return ThreeFoldTransaction.list_by_user(app_user, token)