Beispiel #1
0
    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)
Beispiel #2
0
    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)
Beispiel #3
0
    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)
Beispiel #4
0
    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
                                         }
        )
Beispiel #5
0
    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)
Beispiel #6
0
    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)
Beispiel #7
0
    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)