class GetMarketTrx(object): def __init__(self): config_file = os.getenv("HOME") + "/.python-bts/bts_client.json" fd_config = open(config_file) self.config_bts = json.load(fd_config)["client_default"] fd_config.close() config_bts = self.config_bts self.client = BTS(config_bts["user"], config_bts["password"], config_bts["host"], config_bts["port"]) self.market = BTSMarket(self.client) self.height = -1 def display_deal_trx(self, deal_trx): for trx in deal_trx: if trx["type"] == "bid": deal_type = "buy" else: deal_type = "sell" sys.stdout.write("\n%s %s %s %s %s at price %.4g %s/%s" % ( trx["timestamp"], trx["block"], deal_type, trx["volume"], trx["base"], trx["price"], trx["quote"], trx["base"])) def display_place_trx(self, place_trx): trx_id = "" for trx in place_trx: if trx_id == trx["trx_id"]: sys.stdout.write(".") continue trx_id = trx["trx_id"] if trx["type"] == "cover": sys.stdout.write("\n%s %s %s %s %s %s" % ( trx["timestamp"], trx["block"], trx["trx_id"], trx["type"], trx["amount"], trx["quote"])) elif trx["type"] == "add_collateral": sys.stdout.write("\n%s %s %s %s %s %s" % ( trx["timestamp"], trx["block"], trx["trx_id"], trx["type"], trx["amount"], trx["base"])) else: if trx["type"] == "bid": volume = trx["amount"] / trx["price"] else: volume = trx["amount"] order_type = trx["type"] if trx["cancel"]: order_type = "cancel " + trx["type"] if trx["price"]: price_str = "%.4g" % trx["price"] else: price_str = "unlimited" sys.stdout.write("\n%s %s %s %s %s %s at price %s %s/%s" % ( trx["timestamp"], trx["block"], trx["trx_id"], order_type, volume, trx["base"], price_str, trx["quote"], trx["base"])) def excute(self): client_info = self.client.get_info() height_now = int(client_info["blockchain_head_block_num"]) if self.height == -1: self.height = height_now - 1000 while self.height < height_now: self.height += 1 trxs = self.client.get_block_transactions(self.height) recs = self.market.get_order_deal_rec(self.height) self.display_deal_trx(recs) recs = self.market.get_order_place_rec(trxs) self.display_place_trx(recs) self.market.update_order_owner(recs)
class PublishMarket(object): def __init__(self): self.pusher = None self.order_book = {} self.order_book_brief = {} self.load_config() self.init_market() def load_config(self): config_file = os.getenv("HOME")+"/.python-bts/publish_market.json" fd_config = open(config_file) self.config = json.load(fd_config) fd_config.close() def init_market(self): config_file = os.getenv("HOME") + "/.python-bts/bts_client.json" fd_config = open(config_file) config_bts = json.load(fd_config)[self.config["bts_client"]] fd_config.close() self.bts_client = BTS(config_bts["user"], config_bts["password"], config_bts["host"], config_bts["port"]) self.market = BTSMarket(self.bts_client) client_info = self.bts_client.get_info() self.height = int(client_info["blockchain_head_block_num"]) def myPublish(self, topic, event): if self.pusher: self.pusher.publish(topic, event, c=topic) def publish_deal_trx(self, deal_trx): for trx in deal_trx: if trx["type"] == "bid": deal_type = "buy" else: deal_type = "sell" prefix = get_prefix(trx["quote"], trx["base"]) format_trx = [prefix, trx["block"], trx["timestamp"], deal_type, trx["price"], trx["volume"]] self.myPublish( u'bts.orderbook.%s.trx' % (format_trx[0]), format_trx[1:]) self.myPublish(u'bts.orderbook.trx', format_trx) print(format_trx) def publish_place_trx(self, place_trx): trx_id = "" for trx in place_trx: if trx_id == trx["trx_id"]: continue prefix = get_prefix(trx["quote"], trx["base"]) trx_id = trx["trx_id"] if trx["cancel"]: trx["type"] = "cancel " + trx["type"] format_trx = [prefix, trx["block"], trx["timestamp"], trx["type"], trx["price"], trx["amount"]] self.myPublish( u'bts.orderbook.%s.order' % (format_trx[0]), format_trx[1:]) self.myPublish(u'bts.orderbook.order', format_trx) print(format_trx) def publish_order_book(self): market_list = self.config["market_list"] for quote, base in market_list: prefix = get_prefix(quote, base) order_book = self.market.get_order_book( quote, base, cover=True) order_book["bids"] = order_book["bids"][:10] order_book["asks"] = order_book["asks"][:10] if (prefix not in self.order_book or self.order_book[prefix] != order_book): self.order_book[prefix] = order_book self.myPublish( u'bts.orderbook.%s' % prefix, order_book) self.publish_order_book_brief(quote, base, order_book) def publish_order_book_brief(self, quote, base, order_book): prefix = get_prefix(quote, base) order_book_brief = {"quote": quote, "base": base, "ask1": None, "bid1": None} if order_book["bids"]: order_book_brief["bid1"] = order_book["bids"][0][0] if order_book["asks"]: order_book_brief["ask1"] = order_book["asks"][0][0] if (prefix not in self.order_book_brief or self.order_book_brief[prefix] != order_book_brief): self.order_book_brief[prefix] = order_book_brief self.myPublish( u'bts.orderbook.%s.brief' % prefix, order_book_brief) def execute(self): client_info = self.bts_client.get_info() height_now = int(client_info["blockchain_head_block_num"]) if(self.height < height_now): time_stamp = client_info["blockchain_head_block_timestamp"] self.myPublish(u'bts.blockchain.info', {"height": height_now, "time_stamp": time_stamp}) self.publish_order_book() while self.height < height_now: self.height += 1 trxs = self.bts_client.get_block_transactions( self.height) recs = self.market.get_order_deal_rec(self.height) self.publish_deal_trx(recs) recs = self.market.get_order_place_rec(trxs) self.publish_place_trx(recs) self.market.update_order_owner(recs)
class DelegateWatch(object): def __init__(self): self.confirm = 2 self.load_config() self.init_bts() self.setup_log() self.init_watch() self.init_contact() def load_config(self): config_file = os.getenv("HOME")+"/.python-bts/delegate_watch.json" fd_config = open(config_file) self.config = json.load(fd_config)["delegate_watch"] fd_config.close() config_file = os.getenv("HOME")+"/.python-bts/bts_client.json" fd_config = open(config_file) self.config_bts = json.load(fd_config)[self.config["bts_client"]] fd_config.close() def init_bts(self): config_bts = self.config_bts self.bts_client = BTS(config_bts["user"], config_bts["password"], config_bts["host"], config_bts["port"]) self.delegate_num = int(self.bts_client.chain_info["delegate_num"]) self.period = float(self.bts_client.chain_info["block_interval"]) def setup_log(self): # Setting up Logger self.logger = logging.getLogger('bts') self.logger.setLevel(logging.INFO) formatter = logging.Formatter( '%(asctime)s[%(levelname)s]: %(message)s') fh = logging.handlers.RotatingFileHandler( "/tmp/bts_delegate_watch.log") fh.setFormatter(formatter) self.logger.addHandler(fh) def init_watch(self): client_info = self.bts_client.get_info() self.height = int(client_info["blockchain_head_block_num"]) self.round_left = int(client_info["blockchain_blocks_left_in_round"]) self.active_delegates = self.bts_client.list_active_delegates() self.active_offset = self.height for delegate in self.active_delegates: last_block_num = int( delegate["delegate_info"]["last_block_num_produced"]) if last_block_num == self.height: break self.active_offset -= 1 def init_contact(self): self.contact = {} mail_list = self.config["contact"] for mail in mail_list: if mail_list[mail]["enable"] == 0: continue for delegate in mail_list[mail]["delegates"]: if delegate not in self.contact: self.contact[delegate] = [mail] else: self.contact[delegate].append(mail) def process_missed_block(self, height): index = (height-self.active_offset) % self.delegate_num account = self.active_delegates[index]["name"] print("missed", height, account) self.logger.info("missed %s", account) self.active_offset -= 1 self.notify(account, height) return account def get_block_delegate(self, height): index = (height-self.active_offset) % self.delegate_num account = self.active_delegates[index]["name"] print("......", height, account) self.logger.info("%d %s", height, account) return account def check_missed_block(self, height): limit = height - self.height + 1 list_blocks = self.bts_client.list_blocks(height, limit) last_timestamp = -1 for block in reversed(list_blocks): timestamp = int(block["timestamp"][-2:]) block_num = int(block["block_num"]) if last_timestamp != -1: period = (timestamp - last_timestamp + 60) % 60 while period != self.period: period -= self.period self.process_missed_block(block_num) self.get_block_delegate(block_num) last_timestamp = timestamp def notify(self, account, height): if account not in self.contact: print("no contact") return print ("sent notify mail") sender = self.config["sender"] msg_from = "From: %s <%s>\n" % (self.config["name"], sender) msg_to = "" for receiver in self.contact[account]: msg_to = msg_to+"To: <%s>\n" % receiver msg_subject = "Subject: missed block attention for %s\n" % account msg_content = "you have missed block %d\n" % height message = msg_from+msg_to+msg_subject+msg_content print(message) smtpObj = smtplib.SMTP('localhost') smtpObj.sendmail(sender, self.contact[account], message) def execute(self): while True: try: client_info = self.bts_client.get_info() height = int( client_info["blockchain_head_block_num"]) - self.confirm if height > self.height: round_left = (int( client_info["blockchain_blocks_left_in_round"] ) + self.confirm - 1) % self.delegate_num + 1 if round_left > self.round_left: if self.round_left != 1: round_left = 1 height = self.height+self.round_left-1 else: self.active_delegates = \ self.bts_client.list_active_delegates() self.check_missed_block(height) self.height = height self.round_left = round_left except Exception as e: self.logger.exception(e) now = time.time() nexttime = int(now/self.period+1)*self.period - now time.sleep(nexttime+1)
class BTSOrderBook(object): def __init__(self): self.market_list = [ ["BOTSCNY", "BTS"], ["CNY", "BTS"], ["USD", "BTS"], ["GOLD", "BTS"], ["BTC", "BTS"], ["BDR.AAPL", "CNY"], ["NOTE", "BTS"]] self.init_done = False self.pusher = None self.order_book = {} self.deal_trx = {} self.place_trx = {} for quote, base in self.market_list: prefix = get_prefix(quote, base) self.order_book[prefix] = {} self.deal_trx[prefix] = [] self.place_trx[prefix] = [] self.init_market() self.execute() self.init_done = True def init_market(self): config_file = os.getenv("HOME") + "/.python-bts/bts_client.json" fd_config = open(config_file) config_bts = json.load(fd_config)["client_default"] fd_config.close() self.bts_client = BTS(config_bts["user"], config_bts["password"], config_bts["host"], config_bts["port"]) self.market = BTSMarket(self.bts_client) client_info = self.bts_client.get_info() self.height = int(client_info["blockchain_head_block_num"]) - 180 def myPublish(self, topic, event): if self.pusher and self.init_done: self.pusher.emit(topic, event, namespace="") def publish_deal_trx(self, deal_trx): for trx in deal_trx: if trx["type"] == "bid": deal_type = "buy" else: deal_type = "sell" prefix = get_prefix(trx["quote"], trx["base"]) format_trx = [prefix, trx["block"], trx["timestamp"], deal_type, trx["price"], trx["volume"]] self.myPublish( u'bts.orderbook.%s.trx' % (format_trx[0]), format_trx[1:]) self.myPublish(u'bts.orderbook.trx', format_trx) market = format_trx[0] if market not in self.deal_trx: self.deal_trx[market] = [] self.deal_trx[market].append(format_trx[1:]) print(format_trx) def publish_place_trx(self, place_trx): trx_id = "" for trx in place_trx: if trx_id == trx["trx_id"]: continue prefix = get_prefix(trx["quote"], trx["base"]) trx_id = trx["trx_id"] if trx["cancel"]: trx["type"] = "cancel " + trx["type"] format_trx = [prefix, trx["block"], trx["timestamp"], trx["type"], trx["price"], trx["amount"]] self.myPublish( u'bts.orderbook.%s.order' % (format_trx[0]), format_trx[1:]) self.myPublish(u'bts.orderbook.order', format_trx) market = format_trx[0] if market not in self.place_trx: self.place_trx[market] = [] self.place_trx[market].append(format_trx[1:]) print(format_trx) def publish_order_book(self): for quote, base in self.market_list: prefix = get_prefix(quote, base) order_book = self.market.get_order_book( quote, base) order_book["bids"] = order_book["bids"][:10] order_book["asks"] = order_book["asks"][:10] if (prefix not in self.order_book or self.order_book[prefix] != order_book): self.order_book[prefix] = order_book self.myPublish( u'bts.orderbook.%s' % prefix, order_book) def execute(self): client_info = self.bts_client.get_info() height_now = int(client_info["blockchain_head_block_num"]) if(self.height < height_now): time_stamp = client_info["blockchain_head_block_timestamp"] self.myPublish(u'bts.blockchain.info', {"height": height_now, "time_stamp": time_stamp}) self.publish_order_book() while self.height < height_now: self.height += 1 trxs = self.bts_client.get_block_transactions( self.height) recs = self.market.get_order_deal_rec(self.height) self.publish_deal_trx(recs) recs = self.market.get_order_place_rec(trxs) self.publish_place_trx(recs) self.market.update_order_owner(recs)
class BTSOrderBook(object): def __init__(self): self.market_list = [["BOTSCNY", "BTS"], ["CNY", "BTS"], ["USD", "BTS"], ["GOLD", "BTS"], ["BTC", "BTS"], ["BDR.AAPL", "CNY"], ["NOTE", "BTS"]] self.init_done = False self.pusher = None self.order_book = {} self.deal_trx = {} self.place_trx = {} for quote, base in self.market_list: prefix = get_prefix(quote, base) self.order_book[prefix] = {} self.deal_trx[prefix] = [] self.place_trx[prefix] = [] self.init_market() self.execute() self.init_done = True def init_market(self): config_file = os.getenv("HOME") + "/.python-bts/bts_client.json" fd_config = open(config_file) config_bts = json.load(fd_config)["client_default"] fd_config.close() self.bts_client = BTS(config_bts["user"], config_bts["password"], config_bts["host"], config_bts["port"]) self.market = BTSMarket(self.bts_client) client_info = self.bts_client.get_info() self.height = int(client_info["blockchain_head_block_num"]) - 180 def myPublish(self, topic, event): if self.pusher and self.init_done: self.pusher.emit(topic, event, namespace="") def publish_deal_trx(self, deal_trx): for trx in deal_trx: if trx["type"] == "bid": deal_type = "buy" else: deal_type = "sell" prefix = get_prefix(trx["quote"], trx["base"]) format_trx = [ prefix, trx["block"], trx["timestamp"], deal_type, trx["price"], trx["volume"] ] self.myPublish(u'bts.orderbook.%s.trx' % (format_trx[0]), format_trx[1:]) self.myPublish(u'bts.orderbook.trx', format_trx) market = format_trx[0] if market not in self.deal_trx: self.deal_trx[market] = [] self.deal_trx[market].append(format_trx[1:]) print(format_trx) def publish_place_trx(self, place_trx): trx_id = "" for trx in place_trx: if trx_id == trx["trx_id"]: continue prefix = get_prefix(trx["quote"], trx["base"]) trx_id = trx["trx_id"] if trx["cancel"]: trx["type"] = "cancel " + trx["type"] format_trx = [ prefix, trx["block"], trx["timestamp"], trx["type"], trx["price"], trx["amount"] ] self.myPublish(u'bts.orderbook.%s.order' % (format_trx[0]), format_trx[1:]) self.myPublish(u'bts.orderbook.order', format_trx) market = format_trx[0] if market not in self.place_trx: self.place_trx[market] = [] self.place_trx[market].append(format_trx[1:]) print(format_trx) def publish_order_book(self): for quote, base in self.market_list: prefix = get_prefix(quote, base) order_book = self.market.get_order_book(quote, base) order_book["bids"] = order_book["bids"][:10] order_book["asks"] = order_book["asks"][:10] if (prefix not in self.order_book or self.order_book[prefix] != order_book): self.order_book[prefix] = order_book self.myPublish(u'bts.orderbook.%s' % prefix, order_book) def execute(self): client_info = self.bts_client.get_info() height_now = int(client_info["blockchain_head_block_num"]) if (self.height < height_now): time_stamp = client_info["blockchain_head_block_timestamp"] self.myPublish(u'bts.blockchain.info', { "height": height_now, "time_stamp": time_stamp }) self.publish_order_book() while self.height < height_now: self.height += 1 trxs = self.bts_client.get_block_transactions(self.height) recs = self.market.get_order_deal_rec(self.height) self.publish_deal_trx(recs) recs = self.market.get_order_place_rec(trxs) self.publish_place_trx(recs) self.market.update_order_owner(recs)