Esempio n. 1
0
    def on_md_publish(self, publish_msg):
        """" on_md_publish. """
        topic = publish_msg[0]
        raw_message = publish_msg[1]

        msg = JsonMessage(raw_message)

        if msg.type == 'W':  # Full Refresh
            self.on_md_full_refresh(msg)

        elif msg.type == 'X':  # Incremental
            self.on_md_incremental(msg)
Esempio n. 2
0
    def sendString(self, string_msg):
        if not self.isConnected() and self.reopen:
            self.connect()

        self.trade_in_socket.send_unicode("REQ," + self.connection_id + ',' +
                                          string_msg)

        response_message = self.trade_in_socket.recv()
        raw_resp_message_header = response_message[:3]
        raw_resp_message = response_message[4:].strip()

        rep_msg = None
        if raw_resp_message:
            try:
                rep_msg = JsonMessage(raw_resp_message)
            except Exception:
                pass

        if raw_resp_message_header == 'CLS' and rep_msg and not rep_msg.isErrorMessage(
        ):
            self.close()
            if self.reopen:
                self.connect()
            return rep_msg

        if raw_resp_message_header != 'REP':
            self.close()
            if self.reopen:
                self.connect()

            if rep_msg and rep_msg.isErrorMessage():
                raise TradeClientException(rep_msg.get('Description'),
                                           rep_msg.get('Detail'))
            raise TradeClientException('Invalid request: ' + raw_resp_message)

        if rep_msg and rep_msg.isUserResponse():
            if rep_msg.get("UserStatus") == 1:
                self.user_id = rep_msg.get("UserID")
                self.is_logged = True

                if self.trade_pub_socket:
                    self.trade_pub_socket.setsockopt(
                        zmq.SUBSCRIBE, '^' + str(self.user_id) + '$')

        return rep_msg
Esempio n. 3
0
    def on_md_publish(self, publish_msg):
        """" on_md_publish. """
        start = datetime.datetime.now()

        topic = publish_msg[0]
        raw_message = publish_msg[1]

        msg = JsonMessage(raw_message)

        if msg.type == 'W':  # Full Refresh
            self.on_md_full_refresh(msg)

        elif msg.type == 'X':  # Incremental
            self.on_md_incremental(msg)

        finish = datetime.datetime.now()
        self.application.log(
            "DEBUG", "PERF",
            str([(finish - start).total_seconds(),
                 "MarketDataSubscriber.on_md_publish", "1",
                 [topic, raw_message]]))
Esempio n. 4
0
    def on_message(self, raw_message):
        if self.honey_pot_connection:
            self.application.log('INFO', "HONEY_POT", raw_message)

        if self.trade_client is None or not self.trade_client.isConnected():
            return

        self.last_message_datetime.append(datetime.now())
        message_time_last_second = self.last_message_datetime[-1] - timedelta(
            seconds=1)
        for x in xrange(0, len(self.last_message_datetime)):
            if self.last_message_datetime[x] > message_time_last_second:
                self.last_message_datetime = self.last_message_datetime[x:]
                break
        if len(self.last_message_datetime
               ) > 15:  # higher than 15 messages per second
            self.application.log(
                "ERROR", "TOO_MANY_MESSAGES",
                "Exceed 15 messages per second. [ip=" + self.remote_ip + ",'" +
                raw_message + "']")
            self.write_message(
                '{"MsgType":"ERROR", "Description":"Too many messages per second", "Detail": "16 messages in the last second"}'
            )
            self.application.unregister_connection(self)
            self.trade_client.close()
            self.close()
            return

        try:
            req_msg = JsonMessage(raw_message)
        except InvalidMessageException as e:
            self.write_message(
                '{"MsgType":"ERROR", "Description":"Invalid message", "Detail": "'
                + str(e) + '"}')
            self.application.unregister_connection(self)
            self.trade_client.close()
            self.close()
            return

        req_msg.set('RemoteIP', self.remote_ip)

        if req_msg.isUserRequest():
            if req_msg.has('Password'):
                raw_message = raw_message.replace(req_msg.get('Password'), '*')
            if req_msg.has('NewPassword'):
                raw_message = raw_message.replace(req_msg.get('NewPassword'),
                                                  '*')
            self.application.log('IN', self.trade_client.connection_id,
                                 raw_message)

        if req_msg.isTestRequest() or req_msg.isHeartbeat():
            dt = datetime.now()
            response_msg = {
                'MsgType':
                '0',
                'TestReqID':
                req_msg.get('TestReqID'),
                'ServerTimestamp':
                int(mktime(dt.timetuple()) + dt.microsecond / 1000.0)
            }

            sendTime = req_msg.get('SendTime')
            if sendTime:
                response_msg['SendTime'] = sendTime

            self.write_message(str(json.dumps(response_msg, cls=JsonEncoder)))
            return

        if req_msg.isTradeHistoryRequest():  # Trade History request
            self.on_trade_history_request(req_msg)
            return

        if req_msg.isMarketDataRequest():  # Market Data Request
            self.on_market_data_request(req_msg)

            if not self.trade_client.isConnected():
                self.application.log('DEBUG', self.trade_client.connection_id,
                                     'not self.trade_client.isConnected()')
                self.application.unregister_connection(self)
                self.trade_client.close()
                self.close()
            return

        if req_msg.isSecurityStatusRequest():
            self.on_security_status_request(req_msg)
            return

        if req_msg.isDepositRequest():
            if not req_msg.get('DepositMethodID') and not req_msg.get(
                    'DepositID'):

                currency = req_msg.get('Currency')

                secret = uuid.uuid4().hex
                callback_url = self.application.options.callback_url + secret

                hot_wallet = self.get_broker_wallet('hot', currency)
                cold_wallet = self.get_broker_wallet('cold', currency)
                if not hot_wallet and not cold_wallet:
                    return

                if not hot_wallet and cold_wallet:
                    dest_wallet = cold_wallet
                elif hot_wallet and not cold_wallet:
                    dest_wallet = hot_wallet
                else:
                    # 62.5% of all deposits go to the cold wallet, and 37.5% go to the hot wallet
                    dest_wallet = hot_wallet
                    if secret[0] in ('0', '1', '2', '3', '4', '5', '6', '7',
                                     '8', '9'):
                        dest_wallet = cold_wallet

                if not dest_wallet:
                    return

                parameters = urllib.urlencode({
                    'method': 'create',
                    'address': dest_wallet,
                    'callback': callback_url,
                    'currency': currency
                })

                try:
                    url_payment_processor = self.application.options.url_payment_processor + '?' + parameters
                    self.application.log('DEBUG',
                                         self.trade_client.connection_id,
                                         "invoking..." + url_payment_processor)
                    response = urllib2.urlopen(url_payment_processor)
                    data = json.load(response)
                    self.application.log('DEBUG',
                                         self.trade_client.connection_id,
                                         str(data))

                    req_msg.set('InputAddress', data['input_address'])
                    req_msg.set('Destination', data['destination'])
                    req_msg.set('Secret', secret)
                except urllib2.HTTPError as e:
                    out_message = json.dumps({
                        'MsgType':
                        'ERROR',
                        'ReqID':
                        req_msg.get('DepositReqID'),
                        'Description':
                        'Blockchain.info is not available at this moment, please try again within few minutes',
                        'Detail':
                        str(e)
                    })
                    self.write_message(out_message)
                    return
                except Exception as e:
                    out_message = json.dumps({
                        'MsgType':
                        'ERROR',
                        'ReqID':
                        req_msg.get('DepositReqID'),
                        'Description':
                        'Error retrieving a new deposit address from Blockchain.info. Please, try again',
                        'Detail':
                        str(e)
                    })
                    self.write_message(out_message)
                    return

        try:
            resp_message = self.trade_client.sendMessage(req_msg)
            if resp_message:
                self.write_message(resp_message.raw_message)

            if resp_message and resp_message.isUserResponse():
                self.user_response = resp_message
                if self.is_user_logged():
                    self.application.log('LOGIN_OK',
                                         self.trade_client.connection_id,
                                         raw_message)
                    #TODO: Request open order list
                    #self.trade_client.

                else:
                    self.application.log('LOGIN_FAILED',
                                         self.trade_client.connection_id,
                                         raw_message)

            if not self.trade_client.isConnected():
                self.application.log('DEBUG', self.trade_client.connection_id,
                                     'not self.trade_client.isConnected()')
                self.application.unregister_connection(self)
                self.trade_client.close()
                self.close()
        except TradeClientException as e:
            exception_message = {
                'MsgType': 'ERROR',
                'Description': 'Invalid message',
                'Detail': str(e)
            }
            self.write_message(json.dumps(exception_message))
            self.application.unregister_connection(self)
            self.trade_client.close()
            self.close()
    def onMessage(self, payload, isBinary):
        if isBinary:
            print("Binary message received: {0} bytes".format(len(payload)))
            reactor.stop()
            return

        if self.factory.verbose:
            print 'rx:', payload

        msg = JsonMessage(payload.decode('utf8'))
        if msg.isHeartbeat():
            return

        if msg.isUserResponse():  # login response
            if msg.get('UserStatus') != 1:
                reactor.stop()
                raise RuntimeError('Wrong login')

            profile = msg.get('Profile')
            if profile['Type'] != 'BROKER':
                reactor.stop()
                raise RuntimeError('It is not a brokerage account')

            self.factory.broker_username = msg.get('Username')
            self.factory.broker_id = msg.get('UserID')
            self.factory.profile = profile
            return

        if msg.isWithdrawRefresh():
            if msg.get('BrokerID') != self.factory.broker_id:
                return  # received a message from a different broker

            msg.set('BrokerUsername', self.factory.broker_username)

            if msg.get('Status') == '1'\
              and (self.factory.methods[0] == '*' or msg.get('Method') in self.factory.methods) \
              and (self.factory.currencies[0] == '*' or  msg.get('Currency') in self.factory.currencies):
                withdraw_record = Withdraw.process_withdrawal_refresh_message(
                    self.factory.db_session, msg)
                if withdraw_record:
                    process_withdraw_message = MessageBuilder.processWithdraw(
                        action='PROGRESS',
                        withdrawId=msg.get('WithdrawID'),
                        data=msg.get('Data'),
                        percent_fee=msg.get('PercentFee'),
                        fixed_fee=msg.get('FixedFee'))

                    withdraw_record.process_req_id = process_withdraw_message[
                        'ProcessWithdrawReqID']

                    # sent a B6
                    self.sendJSON(process_withdraw_message)
                    self.factory.db_session.commit()

        if msg.isProcessWithdrawResponse():
            if not msg.get('Result'):
                return

            process_req_id = msg.get('ProcessWithdrawReqID')
            withdraw_record = Withdraw.get_withdraw_by_process_req_id(
                self.factory.db_session, process_req_id)

            should_transfer = False
            if withdraw_record:
                if withdraw_record.status == '1' and msg.get('Status') == '2'\
                  and (self.factory.methods[0] == '*' or withdraw_record.method  in self.factory.methods)\
                  and (self.factory.currencies[0] == '*' or  withdraw_record.currency in self.factory.currencies):

                    if withdraw_record.account_id not in self.factory.blocked_accounts:
                        should_transfer = True

                withdraw_record.status = msg.get('Status')
                withdraw_record.reason = msg.get('Reason')
                withdraw_record.reason_id = msg.get('ReasonID')

                self.factory.db_session.add(withdraw_record)
                self.factory.db_session.commit()

                if should_transfer:
                    self.factory.reactor.callLater(
                        0, partial(self.initiateTransfer, process_req_id))
Esempio n. 6
0
    def onMessage(self, payload, isBinary):
        if isBinary:
            print("Binary message received: {0} bytes".format(len(payload)))
            reactor.stop()
            return

        if self.factory.verbose:
            print 'rx:', payload

        msg = JsonMessage(payload.decode('utf8'))
        if msg.isHeartbeat():
            return

        if msg.isUserResponse():  # login response
            if msg.get('UserStatus') != 1:
                reactor.stop()
                raise RuntimeError('Wrong login')

            profile = msg.get('Profile')
            if profile['Type'] != 'BROKER':
                reactor.stop()
                raise RuntimeError('It is not a brokerage account')

            self.factory.broker_username = msg.get('Username')
            self.factory.broker_id = msg.get('UserID')
            self.factory.profile = profile
            return

        if msg.isVerifyCustomerRefresh():
            broker_id = msg.get('BrokerID')
            if broker_id != self.factory.broker_id:
                return  # received a message from a different broker

            verified = msg.get('Verified')
            if verified != 1:
                return

            user_id = msg.get('ClientID')
            username = msg.get('Username')
            verification_data = msg.get('VerificationData')
            if verification_data:
                verification_data = json.loads(verification_data)

            edentiti_status = get_verification_data(verification_data,
                                                    'edentiti_status')
            if edentiti_status == "IN_PROGRESS":
                return

            street_address = get_verification_data(verification_data,
                                                   'address')['street1']
            flat_number = ''
            if '/' in street_address:
                flat_number = street_address[:street_address.find('/')]
                street_address = street_address[street_address.find('/') + 1:]

            street_address_parts = street_address.split(" ")
            street_type = ""
            if len(street_address_parts) > 1:
                street_type = street_address_parts[-1]
                street_address = ' '.join(street_address_parts[:-1])

            street_address_parts = street_address.split(" ")
            street_number = ""
            if street_address_parts and street_address_parts[0].isdigit():
                street_number = street_address_parts[0]
                street_address = ' '.join(street_address_parts[1:])

            street_name = street_address

            try:
                res = self.factory.wsdl_client.registerUser(
                    customerId=self.factory.edentiti_customer_id,
                    password=self.factory.edentiti_password,
                    ruleId='default',
                    name={
                        'givenName':
                        get_verification_data(verification_data,
                                              'name')['first'],
                        'middleNames':
                        get_verification_data(verification_data,
                                              'name')['middle'],
                        'surname':
                        get_verification_data(verification_data,
                                              'name')['last']
                    },
                    currentResidentialAddress={
                        'country':
                        get_verification_data(verification_data,
                                              'address')['country_code'],
                        'flatNumber':
                        flat_number,
                        'postcode':
                        get_verification_data(verification_data,
                                              'address')['postal_code'],
                        'propertyName':
                        '',
                        'state':
                        get_verification_data(verification_data,
                                              'address')['state'],
                        'streetName':
                        street_name,
                        'streetNumber':
                        street_number,
                        'streetType':
                        street_type.upper(),
                        'suburb':
                        get_verification_data(verification_data,
                                              'address')['city']
                    },
                    homePhone=get_verification_data(verification_data,
                                                    'phone_number'),
                    dob=datetime.datetime.strptime(
                        get_verification_data(verification_data,
                                              'date_of_birth'), "%Y-%m-%d"))

                dt = datetime.datetime.now()
                createdAt = int(
                    mktime(dt.timetuple()) + dt.microsecond / 1000000.0)
                edentiti_verification_data = {
                    "service_provider": "edentiti",
                    "edentiti_status": res['return']['outcome'],
                    "id": res['return']['transactionId'],
                    "user_id": res['return']['userId'],
                    "status": res['return']['outcome'],
                    "created_at": createdAt,
                    "updated_at": createdAt
                }
                if res['return']['outcome'] == "IN_PROGRESS":
                    edentiti_verification_data["status"] = "progress"
                    verified = 2

                if edentiti_verification_data["status"] == "valid":
                    verified = 3

                self.sendJSON(
                    MessageBuilder.verifyCustomer(
                        user_id, verified,
                        json.dumps(edentiti_verification_data)))

            except Exception:
                pass
def run_application(options, instance_name):
    input_log_file_handler = logging.handlers.TimedRotatingFileHandler(
        os.path.expanduser(options.mailer_log), when='MIDNIGHT')
    input_log_file_handler.setFormatter(
        logging.Formatter(u"%(asctime)s - %(message)s"))

    mail_logger = logging.getLogger(instance_name)
    mail_logger.setLevel(logging.INFO)
    mail_logger.addHandler(input_log_file_handler)

    ch = logging.StreamHandler(sys.stdout)
    ch.setLevel(logging.DEBUG)
    ch.setFormatter(
        logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
    mail_logger.addHandler(ch)

    mail_logger.info('START')

    def log(command, key, value=None):
        log_msg = u'%s, %s, %s' % (command, key, value if value else None)
        mail_logger.info(unicode(log_msg))

    log('PARAM', 'BEGIN')
    log('PARAM', 'trade_in', options.trade_in)
    log('PARAM', 'trade_pub', options.trade_pub)
    log('PARAM', 'mailer_log', options.mailer_log)
    log('PARAM', 'mailchimp_apikey', options.mailchimp_apikey)
    log('PARAM', 'mandrill_apikey', options.mandrill_apikey)
    log('PARAM', 'mailer_username', options.mailer_username)
    log('PARAM', 'mailchimp_newsletter_list_id',
        options.mailchimp_newsletter_list_id)
    log('PARAM', 'END')

    context = zmq.Context()
    socket = context.socket(zmq.SUB)
    socket.connect(options.trade_pub)
    socket.setsockopt(zmq.SUBSCRIBE, "^EMAIL$")

    trade_in_socket = context.socket(zmq.REQ)
    trade_in_socket.connect(options.trade_in)

    application_trade_client = TradeClient(context, trade_in_socket)
    application_trade_client.connect()

    login_response = application_trade_client.sendJSON(
        MessageBuilder.login(8999999, options.mailer_username,
                             options.mailer_password))
    if login_response.get('UserStatus') != 1:
        raise RuntimeError("Invalid user id")

    brokers = {}
    broker_list, broker_list_columns = application_trade_client.getBrokerList(
        ['1'])
    for b in broker_list:
        brokers[b[0]] = {"params": b}

    broker_mandrill_column_index = None
    try:
        broker_mandrill_column_index = broker_list_columns.index(
            'MandrillApiKey')
    except ValueError:
        pass

    for broker_id, broker_data in brokers.iteritems():
        if broker_mandrill_column_index and broker_data['params'][
                broker_mandrill_column_index]:
            broker_data['MandrillApiKey'] = broker_data['params'][
                broker_mandrill_column_index]
        else:
            broker_data['MandrillApiKey'] = options.mandrill_apikey

    for broker_id, broker_data in brokers.iteritems():
        print broker_id, broker_data['MandrillApiKey']

    # [u'BrokerID', u'ShortName', u'BusinessName', u'Address', u'City', u'State',
    #  u'ZipCode', u'Country', u'PhoneNumber1', u'PhoneNumber2', u'Skype', u'Currencies',
    #  u'TosUrl', u'FeeStructure', u'TransactionFeeBuy', u'TransactionFeeSell', u'Status',
    #  u'ranking', u'Email', u'CountryCode', u'CryptoCurrencies', u'WithdrawStructure',
    #  u'SupportURL', u'SignupLabel', u'AcceptCustomersFrom', u'IsBrokerHub']

    mailchimp_api = mailchimp.Mailchimp(options.mailchimp_apikey)
    try:
        mailchimp_api.helper.ping()
    except mailchimp.Error:
        raise RuntimeError("Invalid MailChimp API key")

    mandrill_api = mandrill.Mandrill(options.mandrill_apikey)
    try:
        mandrill_api.users.ping()
    except mandrill.Error:
        raise RuntimeError("Invalid Mandrill API key")

    while True:
        try:
            raw_email_message = socket.recv()
            log('IN', 'TRADE_IN_PUB', raw_email_message)

            msg = JsonMessage(raw_email_message)

            if not msg.isEmail():
                log('ERROR', 'EXCEPTION',
                    'Received message is not an email message')
                continue

            try:
                broker_id = msg.get('BrokerID')
                sender =  brokers[broker_id]['params'][broker_list_columns.index('MailerFromName')]  + \
                          '<' + brokers[broker_id]['params'][broker_list_columns.index('MailerFromEmail')] + '>'
                body = ""
                msg_to = msg.get('To')
                subject = msg.get('Subject')
                language = msg.get('Language')
                content_type = 'plain'

                if msg.has('Template') and msg.get('Template'):
                    params = {}
                    if msg.has('Params') and msg.get('Params'):
                        params = json.loads(msg.get('Params'))

                    template_name = msg.get('Template')

                    if template_name == 'welcome':
                        # user signup .... let's register him on mailchimp newsletter
                        try:
                            mailchimp_api.lists.subscribe(
                                id=brokers[broker_id]['params']
                                [broker_list_columns.index('MailchimpListID')],
                                email={'email': params['email']},
                                merge_vars={
                                    'EMAIL': params['email'],
                                    'FNAME': params['username']
                                })

                        except mailchimp.ListAlreadySubscribedError:
                            log(
                                'ERROR', 'EXCEPTION', params['email'] +
                                ' mailchimp.ListAlreadySubscribedError')
                        except mailchimp.Error, e:
                            log('ERROR', 'EXCEPTION', str(e))

                    template_content = []
                    for k, v in params.iteritems():
                        template_content.append({'name': k, 'content': v})

                    for broker_column_key in broker_list_columns:
                        broker_column_value = brokers[broker_id]['params'][
                            broker_list_columns.index(broker_column_key)]
                        template_content.append({
                            'name':
                            'broker_' +
                            convertCamelCase2Underscore(broker_column_key),
                            'content':
                            broker_column_value
                        })

                    message = {
                        'from_email':
                        brokers[broker_id]['params'][broker_list_columns.index(
                            'MailerFromEmail')],
                        'from_name':
                        brokers[broker_id]['params'][broker_list_columns.index(
                            'MailerFromName')],
                        'to': [{
                            'email': msg_to,
                            'name': params['username'],
                            'type': 'to'
                        }],
                        'metadata': {
                            'website': 'www.blinktrade.com'
                        },
                        'global_merge_vars':
                        template_content
                    }

                    result = mandrill_api.messages.send_template(
                        template_name=(template_name + '-' +
                                       language.replace('_', '-')).lower(),
                        template_content=template_content,
                        message=message)

                    log('INFO', 'SUCCESS', str(result))
                    continue

                elif msg.has('RawData') and msg.get('RawData'):
                    body = msg.get('RawData')

                    log(
                        'DEBUG', 'EMAIL',
                        u'{"Sender":"%s","To":"%s","Subject":"%s", "Body":"%s" }'
                        % (sender, msg_to, subject, body))
                    send_email(sender, msg_to, subject, body, content_type)
                    log('IN', 'SENT', "")

                    log('INFO', 'SUCCESS', msg.get('EmailThreadID'))
            except Exception as ex:
                traceback.print_exc()
                log('ERROR', 'EXCEPTION', str(ex))
                time.sleep(1)

        except KeyboardInterrupt:
            mail_logger.info('END')
            break
Esempio n. 8
0
    def run(self):
        from pyblinktrade.message import JsonMessage, InvalidMessageException
        from market_data_publisher import MarketDataPublisher
        from execution import OrderMatcher
        from models import Order

        orders = self.db_session.query(Order).filter(
            Order.status.in_(("0", "1"))).order_by(Order.created)
        for order in orders:
            OrderMatcher.get(order.symbol).match(self.db_session, order,
                                                 self.order_matcher_disabled)

        while True:
            raw_message = self.input_socket.recv()

            msg_header = raw_message[:3]
            session_id = raw_message[4:20]
            json_raw_message = raw_message[21:].strip()

            try:
                msg = None
                if json_raw_message:
                    try:
                        msg = JsonMessage(json_raw_message)
                    except InvalidMessageException, e:
                        self.log('IN', 'TRADE_IN_REQ_ERROR', raw_message)
                        raise InvalidMessageError()

                    # never write passwords in the log file
                    if msg.has('Password'):
                        raw_message = raw_message.replace(
                            msg.get('Password'), '*')
                    if msg.has('NewPassword'):
                        raw_message = raw_message.replace(
                            msg.get('NewPassword'), '*')

                self.log('IN', 'TRADE_IN_REQ', raw_message)

                if msg:
                    if msg.isMarketDataRequest():  # Market Data Request
                        req_id = msg.get('MDReqID')
                        market_depth = msg.get('MarketDepth')
                        instruments = msg.get('Instruments')
                        entries = msg.get('MDEntryTypes')
                        transact_time = msg.get('TransactTime')

                        timestamp = None
                        if transact_time:
                            timestamp = transact_time
                        else:
                            trade_date = msg.get('TradeDate')
                            if not trade_date:
                                trade_date = time.strftime(
                                    "%Y%m%d", time.localtime())

                            self.log('OUT', 'TRADEDATE', trade_date)
                            timestamp = datetime.datetime.strptime(
                                trade_date, "%Y%m%d")

                        self.log('OUT', 'TIMESTAMP', timestamp)

                        if len(instruments) > 1:
                            raise InvalidMessageError()

                        instrument = instruments[0]

                        om = OrderMatcher.get(instrument)
                        response_message = MarketDataPublisher.generate_md_full_refresh(
                            self.db_session, instrument, market_depth, om,
                            entries, req_id, timestamp)
                        response_message = 'REP,' + json.dumps(
                            response_message, cls=JsonEncoder)
                    elif msg.isTradeHistoryRequest():

                        page = msg.get('Page', 0)
                        page_size = msg.get('PageSize', 100)
                        offset = page * page_size

                        columns = [
                            'TradeID', 'Market', 'Side', 'Price', 'Size',
                            'BuyerID', 'SellerID', 'BuyerUsername',
                            'SellerUsername', 'Created', 'OrderId',
                            'CounterOrderID'
                        ]

                        trade_list = MarketDataPublisher.generate_trade_history(
                            self.db_session, page_size, offset)

                        response_message = 'REP,' + json.dumps(
                            {
                                'MsgType': 'U33',  # TradeHistoryResponse
                                'TradeHistoryReqID': -1,
                                'Page': page,
                                'PageSize': page_size,
                                'Columns': columns,
                                'TradeHistoryGrp': trade_list
                            },
                            cls=JsonEncoder)

                    else:
                        response_message = self.session_manager.process_message(
                            msg_header, session_id, msg)
                else:
                    response_message = self.session_manager.process_message(
                        msg_header, session_id, msg)

            except TradeRuntimeError, e:
                self.db_session.rollback()
                self.session_manager.close_session(session_id)
                response_message = 'ERR,{"MsgType":"ERROR", "Description":"' + e.error_description.replace(
                    "'", "") + '", "Detail": ""}'
Esempio n. 9
0
    def on_message(self, raw_message):
        if not self.trade_client.isConnected():
            return

        try:
            req_msg = JsonMessage(raw_message)
        except InvalidMessageException as e:
            self.write_message(
                '{"MsgType":"ERROR", "Description":"Invalid message", "Detail": "'
                + str(e) + '"}')
            self.application.unregister_connection(self)
            self.trade_client.close()
            self.close()
            return

        req_msg.set('RemoteIP', self.remote_ip)

        if req_msg.isUserRequest():
            if req_msg.has('Password'):
                raw_message = raw_message.replace(req_msg.get('Password'), '*')
            if req_msg.has('NewPassword'):
                raw_message = raw_message.replace(req_msg.get('NewPassword'),
                                                  '*')
            self.application.log('IN', self.trade_client.connection_id,
                                 raw_message)

        if req_msg.isTestRequest() or req_msg.isHeartbeat():
            dt = datetime.now()
            response_msg = {
                'MsgType':
                '0',
                'TestReqID':
                req_msg.get('TestReqID'),
                'ServerTimestamp':
                int(mktime(dt.timetuple()) + dt.microsecond / 1000.0)
            }

            sendTime = req_msg.get('SendTime')
            if sendTime:
                response_msg['SendTime'] = sendTime

            self.write_message(str(json.dumps(response_msg, cls=JsonEncoder)))
            return

        if req_msg.isTradeHistoryRequest():  # Trade History request
            self.on_trade_history_request(req_msg)
            return

        if req_msg.isMarketDataRequest():  # Market Data Request
            self.on_market_data_request(req_msg)

            if not self.trade_client.isConnected():
                self.application.log('DEBUG', self.trade_client.connection_id,
                                     'not self.trade_client.isConnected()')
                self.application.unregister_connection(self)
                self.trade_client.close()
                self.close()
            return

        if req_msg.isSecurityStatusRequest():
            self.on_security_status_request(req_msg)
            return

        if req_msg.isNewOrderSingle():
            if self.last_order_datetime:
                order_time = datetime.now()
                order_time_less_one_second = order_time - timedelta(
                    milliseconds=200)  # max of 5 orders per second
                if self.last_order_datetime > order_time_less_one_second:
                    #self.application.log('ORDER_REJECT', self.trade_client.connection_id, raw_message )
                    reject_message = {
                        "MsgType": "8",
                        "OrderID": None,
                        "ExecID": None,
                        "ExecType": "8",
                        "OrdStatus": "8",
                        "CumQty": 0,
                        "Symbol": req_msg.get("Symbol"),
                        "OrderQty": req_msg.get("Qty"),
                        "LastShares": 0,
                        "LastPx": 0,
                        "Price": req_msg.get("Price"),
                        "TimeInForce": "1",
                        "LeavesQty": 0,
                        "ExecSide": req_msg.get("Side"),
                        "Side": req_msg.get("Side"),
                        "OrdType": req_msg.get("OrdType"),
                        "CxlQty": req_msg.get("Qty"),
                        "ClOrdID": req_msg.get("ClOrdID"),
                        "AvgPx": 0,
                        "OrdRejReason":
                        "Exceeded the maximum number of orders sent per second.",
                        "Volume": 0
                    }
                    #self.write_message(str(json.dumps(reject_message, cls=JsonEncoder)))
                    #return

            self.last_order_datetime = datetime.now()

        if req_msg.isDepositRequest():
            if not req_msg.get('DepositMethodID') and not req_msg.get(
                    'DepositID'):

                currency = req_msg.get('Currency')

                secret = uuid.uuid4().hex
                callback_url = self.application.options.callback_url + secret

                hot_wallet = self.get_broker_wallet('hot', currency)
                cold_wallet = self.get_broker_wallet('cold', currency)
                if not hot_wallet and not cold_wallet:
                    return

                if not hot_wallet and cold_wallet:
                    dest_wallet = cold_wallet
                elif hot_wallet and not cold_wallet:
                    dest_wallet = hot_wallet
                else:
                    # 62.5% of all deposits go to the cold wallet, and 37.5% go to the hot wallet
                    dest_wallet = hot_wallet
                    if secret[0] in ('0', '1', '2', '3', '4', '5', '6', '7',
                                     '8', '9'):
                        dest_wallet = cold_wallet

                if not dest_wallet:
                    return

                parameters = urllib.urlencode({
                    'method': 'create',
                    'address': dest_wallet,
                    'callback': callback_url,
                    'currency': currency
                })

                try:
                    url_payment_processor = self.application.options.url_payment_processor + '?' + parameters
                    self.application.log('DEBUG',
                                         self.trade_client.connection_id,
                                         "invoking..." + url_payment_processor)
                    response = urllib2.urlopen(url_payment_processor)
                    data = json.load(response)
                    self.application.log('DEBUG',
                                         self.trade_client.connection_id,
                                         str(data))

                    req_msg.set('InputAddress', data['input_address'])
                    req_msg.set('Destination', data['destination'])
                    req_msg.set('Secret', secret)
                except urllib2.HTTPError as e:
                    out_message = json.dumps({
                        'MsgType':
                        'ERROR',
                        'ReqID':
                        req_msg.get('DepositReqID'),
                        'Description':
                        'Blockchain.info is not available at this moment, please try again within few minutes',
                        'Detail':
                        str(e)
                    })
                    self.write_message(out_message)
                    return
                except Exception as e:
                    out_message = json.dumps({
                        'MsgType':
                        'ERROR',
                        'ReqID':
                        req_msg.get('DepositReqID'),
                        'Description':
                        'Error retrieving a new deposit address from Blockchain.info. Please, try again',
                        'Detail':
                        str(e)
                    })
                    self.write_message(out_message)
                    return

        try:
            resp_message = self.trade_client.sendMessage(req_msg)
            if resp_message:
                self.write_message(resp_message.raw_message)

            if resp_message and resp_message.isUserResponse():
                self.user_response = resp_message
                if self.is_user_logged():
                    self.application.log('LOGIN_OK',
                                         self.trade_client.connection_id,
                                         raw_message)
                    #TODO: Request open order list
                    #self.trade_client.

                else:
                    self.application.log('LOGIN_FAILED',
                                         self.trade_client.connection_id,
                                         raw_message)

            if not self.trade_client.isConnected():
                self.application.log('DEBUG', self.trade_client.connection_id,
                                     'not self.trade_client.isConnected()')
                self.application.unregister_connection(self)
                self.trade_client.close()
                self.close()
        except TradeClientException as e:
            exception_message = {
                'MsgType': 'ERROR',
                'Description': 'Invalid message',
                'Detail': str(e)
            }
            self.write_message(json.dumps(exception_message))
            self.application.unregister_connection(self)
            self.trade_client.close()
            self.close()