def transfer_from_hot_wallet(self, ticker, quantity=None, destination="multisigcash"): contract = self.session.query( models.Contract).filter_by(ticker=ticker).one() if destination == "offlinecash" or not contract.multisig_wallet_address: address = contract.cold_wallet_address to_account = "offlinecash" else: address = contract.multisig_wallet_address to_account = "multisigcash" if quantity is None: try: online_cash = self.session.query(models.Positions).filter_by( username="******").filter_by(contract=contract).one() except NoResultFound: log.msg("No position in %s for onlinecash" % ticker) returnValue(None) else: # If we exceed the limit by 10%, so we're not always sending small amounts to the cold wallet if online_cash.position > contract.hot_wallet_limit * 1.1: quantity = online_cash.position - contract.hot_wallet_limit else: returnValue(None) log.msg("Transferring %d from hot to %s wallet at %s" % (quantity, destination, address)) result = yield self.send_to_address(ticker, address, quantity) txid = result['txid'] # Charge the fee to 'customer' fee = result['fee'] fee_uid = util.get_uid() note = "%s: %s" % (address, txid) # CREDIT online cash (decrease) fee_d1 = self.accountant.transfer_position('onlinecash', ticker, "credit", fee, note, fee_uid) # DEBIT the customer (decrease) fee_d2 = self.accountant.transfer_position('customer', ticker, "debit", fee, note, fee_uid) uid = util.get_uid() # CREDIT THE FROM ACCOUNT (decrease) d1 = self.accountant.transfer_position('onlinecash', ticker, 'credit', quantity, note, uid) # DEBIT THE TO ACCOUNT (increase) d2 = self.accountant.transfer_position(to_account, ticker, 'debit', quantity, note, uid) yield defer.gatherResults([d1, d2, fee_d1, fee_d2], consumeErrors=True) returnValue(txid)
def transfer_from_hot_wallet(self, ticker, quantity=None, destination="multisigcash"): contract = self.session.query(models.Contract).filter_by(ticker=ticker).one() if destination == "offlinecash" or not contract.multisig_wallet_address: address = contract.cold_wallet_address to_account = "offlinecash" else: address = contract.multisig_wallet_address to_account = "multisigcash" if quantity is None: try: online_cash = self.session.query(models.Positions).filter_by(username="******").filter_by(contract=contract).one() except NoResultFound: log.msg("No position in %s for onlinecash" % ticker) returnValue(None) else: # If we exceed the limit by 10%, so we're not always sending small amounts to the cold wallet if online_cash.position > contract.hot_wallet_limit * 1.1: quantity = online_cash.position - contract.hot_wallet_limit else: returnValue(None) log.msg("Transferring %d from hot to %s wallet at %s" % (quantity, destination, address)) result = yield self.send_to_address(ticker, address, quantity) txid = result['txid'] # Charge the fee to 'customer' fee = result['fee'] fee_uid = util.get_uid() note = "%s: %s" % (address, txid) # CREDIT online cash (decrease) fee_d1 = self.accountant.transfer_position('onlinecash', ticker, "credit", fee, note, fee_uid) # DEBIT the customer (decrease) fee_d2 = self.accountant.transfer_position('customer', ticker, "debit", fee, note, fee_uid) uid = util.get_uid() # CREDIT THE FROM ACCOUNT (decrease) d1=self.accountant.transfer_position('onlinecash', ticker, 'credit', quantity, note, uid) # DEBIT THE TO ACCOUNT (increase) d2=self.accountant.transfer_position(to_account, ticker, 'debit', quantity, note, uid) yield defer.gatherResults([d1, d2, fee_d1, fee_d2], consumeErrors=True) returnValue(txid)
def transfer_from_multisig_wallet(self, ticker, quantity, destination, multisig): contract = accounting.get_contract(self.session, ticker) if destination == "onlinecash": address = yield self.get_current_address("multisigcash", ticker) elif destination == "offlinecash": address = contract.cold_wallet_address else: raise NotImplementedError result = yield self.send_to_address(ticker, address, quantity, multisig=multisig) txid = result['txid'] fee = result['fee'] # Record fees fee_uid = util.get_uid() note = "%s: %s" % (address, txid) # CREDIT the from account fee_d1 = self.accountant.transfer_position('multisigcash', ticker, 'credit', fee, note, fee_uid) # DEBIT the customer account fee_d2 = self.accountant.transfer_position('customer', ticker, 'debit', fee, note, fee_uid) yield defer.gatherResults([fee_d1, fee_d2], consumeErrors=True) if destination == "offlinecash": # Record the transfer uid = util.get_uid() # CREDIT the from account d1 = self.accountant.transfer_position('multisigcash', ticker, 'credit', quantity, note, uid) # DEBIT the to account d2 = self.accountant.transfer_position('offlinecash', ticker, 'debit', quantity, note, uid) yield defer.gatherResults([d1, d2]) else: # If going to online cash the transfer will get recorded when the btc arrives pass returnValue(txid)
def on_trade_success(self, order, passive_order, price, quantity): uid = get_uid() self.accountant.post_transaction(order.username, { 'username': order.username, 'aggressive': True, 'contract': self.ticker, 'order': order.id, 'other_order': passive_order.id, 'side': OrderSide.name(order.side), 'quantity': quantity, 'price': price, 'timestamp': order.timestamp, 'uid': uid } ) self.accountant.post_transaction(passive_order.username, { 'username': passive_order.username, 'aggressive': False, 'contract': self.ticker, 'order': passive_order.id, 'other_order': order.id, 'side': OrderSide.name(passive_order.side), 'quantity': quantity, 'price': price, 'timestamp': order.timestamp, 'uid': uid } )
def transfer_from_multisig_wallet(self, ticker, quantity, destination, multisig): contract = accounting.get_contract(self.session, ticker) if destination == "onlinecash": address = yield self.get_current_address("multisigcash", ticker) elif destination == "offlinecash": address = contract.cold_wallet_address else: raise NotImplementedError result = yield self.send_to_address(ticker, address, quantity, multisig=multisig) txid = result['txid'] fee = result['fee'] # Record fees fee_uid = util.get_uid() note = "%s: %s" % (address, txid) # CREDIT the from account fee_d1 = self.accountant.transfer_position('multisigcash', ticker, 'credit', fee, note, fee_uid) # DEBIT the customer account fee_d2 = self.accountant.transfer_position('customer', ticker, 'debit', fee, note, fee_uid) yield defer.gatherResults([fee_d1, fee_d2], consumeErrors=True) if destination == "offlinecash": # Record the transfer uid = util.get_uid() # CREDIT the from account d1=self.accountant.transfer_position('multisigcash', ticker, 'credit', quantity, note, uid) # DEBIT the to account d2=self.accountant.transfer_position('offlinecash', ticker, 'debit', quantity, note, uid) yield defer.gatherResults([d1, d2]) else: # If going to online cash the transfer will get recorded when the btc arrives pass returnValue(txid)
def process_withdrawal(self, withdrawal_id, online=False, cancel=False, admin_username=None, multisig={}): # Mark a withdrawal as complete, send the money from the BTC wallet if online=True # and tell the accountant that the withdrawal has happened # If cancel=True, then return the money to the user log.msg("Processing withdrawal: %d online=%s cancel=%s" % (withdrawal_id, online, cancel)) try: withdrawal = self.session.query(models.Withdrawal).filter_by(id=withdrawal_id).one() except NoResultFound: log.err("No withdrawal found for id %d" % withdrawal_id) raise WITHDRAWAL_NOT_FOUND log.msg("Withdrawal found: %s" % withdrawal) if not withdrawal.pending: raise WITHDRAWAL_COMPLETE # Figure out what to do with this withdrawal, and send to address if an online withdrawal if cancel: txid = "cancel" to_user = withdrawal.username fee = None else: if online: # Actually process via the hot or warm wallet if withdrawal.contract.ticker in self.bitcoinrpc: if not multisig: to_user = "******" else: to_user = "******" result = yield self.send_to_address(withdrawal.contract.ticker, withdrawal.address, withdrawal.amount, multisig=multisig) txid = result['txid'] fee = result['fee'] else: raise NO_AUTOMATIC_WITHDRAWAL else: fee = None txid = "offline" to_user = "******" # Notify the accountant try: if admin_username is not None: note = "%s: %s (%s)" % (withdrawal.address, txid, admin_username) else: note = "%s: %s" % (withdrawal.address, txid) # If there was a fee if fee is not None: fee_uid = util.get_uid() fee_d1 = self.accountant.transfer_position(to_user, withdrawal.contract.ticker, 'credit', fee, note, fee_uid) fee_d2 = self.accountant.transfer_position('customer', withdrawal.contract.ticker, 'debit', fee, note, fee_uid) yield defer.gatherResults([fee_d1, fee_d2], consumeErrors=True) uid = util.get_uid() d1 = self.accountant.transfer_position('pendingwithdrawal', withdrawal.contract.ticker, 'debit', withdrawal.amount, note, uid) d2 = self.accountant.transfer_position(to_user, withdrawal.contract.ticker, 'credit', withdrawal.amount, note, uid) yield defer.gatherResults([d1, d2], consumeErrors=True) except Exception as e: log.err(e) self.alerts.send_alert(str(e), "Transfer position failed in process_withdrawal") raise e # Update the DB try: withdrawal.pending = False withdrawal.completed = datetime.utcnow() self.session.add(withdrawal) self.session.commit() except Exception as e: log.err("Exception when trying to mark withdrawal complete: %s" % e) self.session.rollback() raise e returnValue(txid)
def process_withdrawal(self, withdrawal_id, online=False, cancel=False, admin_username=None, multisig={}): # Mark a withdrawal as complete, send the money from the BTC wallet if online=True # and tell the accountant that the withdrawal has happened # If cancel=True, then return the money to the user log.msg("Processing withdrawal: %d online=%s cancel=%s" % (withdrawal_id, online, cancel)) try: withdrawal = self.session.query( models.Withdrawal).filter_by(id=withdrawal_id).one() except NoResultFound: log.err("No withdrawal found for id %d" % withdrawal_id) raise WITHDRAWAL_NOT_FOUND log.msg("Withdrawal found: %s" % withdrawal) if not withdrawal.pending: raise WITHDRAWAL_COMPLETE # Figure out what to do with this withdrawal, and send to address if an online withdrawal if cancel: txid = "cancel" to_user = withdrawal.username fee = None else: if online: # Actually process via the hot or warm wallet if withdrawal.contract.ticker in self.bitcoinrpc: if not multisig: to_user = "******" else: to_user = "******" result = yield self.send_to_address( withdrawal.contract.ticker, withdrawal.address, withdrawal.amount, multisig=multisig) txid = result['txid'] fee = result['fee'] else: raise NO_AUTOMATIC_WITHDRAWAL else: fee = None txid = "offline" to_user = "******" # Notify the accountant try: if admin_username is not None: note = "%s: %s (%s)" % (withdrawal.address, txid, admin_username) else: note = "%s: %s" % (withdrawal.address, txid) # If there was a fee if fee is not None: fee_uid = util.get_uid() fee_d1 = self.accountant.transfer_position( to_user, withdrawal.contract.ticker, 'credit', fee, note, fee_uid) fee_d2 = self.accountant.transfer_position( 'customer', withdrawal.contract.ticker, 'debit', fee, note, fee_uid) yield defer.gatherResults([fee_d1, fee_d2], consumeErrors=True) uid = util.get_uid() d1 = self.accountant.transfer_position('pendingwithdrawal', withdrawal.contract.ticker, 'debit', withdrawal.amount, note, uid) d2 = self.accountant.transfer_position(to_user, withdrawal.contract.ticker, 'credit', withdrawal.amount, note, uid) yield defer.gatherResults([d1, d2], consumeErrors=True) except Exception as e: log.err(e) self.alerts.send_alert( str(e), "Transfer position failed in process_withdrawal") raise e # Update the DB try: withdrawal.pending = False withdrawal.completed = datetime.utcnow() self.session.add(withdrawal) self.session.commit() except Exception as e: log.err("Exception when trying to mark withdrawal complete: %s" % e) self.session.rollback() raise e returnValue(txid)