def post(self): command_request = self.request.POST.get("command") trans = Transaction() trans.command = command_request trans.datetimestemp = datetime.now() trans.put()
def get(self): # path = os.path.join(os.path.dirname(__file__), 'sensorside.html') query_command = Transaction.gql( "WHERE datetimestemp>:dt ORDER BY datetimestemp DESC", dt=(datetime.now() - timedelta(hours=1)) ) last_command = query_command.fetch(limit=1)[0] jsonStr = json.dumps( [{"last_command": last_command.command}, {"datetimestemp": str(last_command.datetimestemp)}] ) self.response.headers["Content-Type"] = "application/json" self.response.out.write(jsonStr)
def post(self): books = [] args = calculate_parser.parse_args() req = request.json['books'] user = Customer.query.filter(Customer.email == args['email']).first() if not user: user = Customer(name=args['name'], email=args['email'], phone_number=args['phone']) db.session.add(user) db.session.commit() for book in req: book = Books.query.get(book) assert book, abort(404, message=f"Book with Id <{book}> not found") books.append(book) currency_id = book.currency_id trans = Transaction.create_transaction(customer_id=user.id, currency_id=currency_id, books=books) return trans, 201
def scan(self): self.block_info = self.rpc.get_block_height() self.newest_height = self.block_info.current_height self.highest_height = self.block_info.highest_height # 延迟扫 SCAN_DELAY_NUMBER 个块 need_to_height = self.newest_height - self.SCAN_DELAY_NUMBER self.logger.info('起始扫块高度:{} 最新高度:{} 需要同步:{}'.format( self.current_scan_height, self.newest_height, need_to_height - self.current_scan_height)) while self.current_scan_height < need_to_height: self.logger.info('当前已扫块高度:{} 最新高度:{} 需要同步:{} 节点最高高度:{}'.format( self.current_scan_height, self.newest_height, need_to_height - self.current_scan_height, self.highest_height)) for height in range(self.current_scan_height, need_to_height, self.SCAN_HEIGHT_NUMBER): # 分批处理, 一次处理 SCAN_HEIGHT_NUMBER 或 剩余要处理的块 block_batch = min(self.SCAN_HEIGHT_NUMBER, need_to_height - self.current_scan_height) blocks = self.rpc.get_block_by_number([ digit.int_to_hex(height) for height in range(height, height + block_batch) ]) save_tx_count = 0 with runtime.app.app_context(): # 一次处理一批 session = db.session() try: for block in blocks: if block is None: return block_height = digit.hex_to_int(block['number']) block_hash = block['hash'] block_timestamp = digit.hex_to_int( block['timestamp']) block_time = datetime.fromtimestamp( block_timestamp) session.begin(subtransactions=True) db_block = Block(height=block_height, block_hash=block_hash, block_time=block_time) session.add(db_block) session.commit() for transaction in block.get('transactions', []): tx = EthereumResolver.resolver_transaction( transaction) if tx.sender in runtime.project_address: # 提现的暂时不要 continue if tx.receiver in runtime.project_address: receipt_raw_tx = self.rpc.get_transaction_receipt( tx.tx_hash) if tx.contract: coin = runtime.coins.get(tx.contract) else: coin = runtime.coins.get( self.COIN_NAME) if coin is None: continue if receipt_raw_tx: receipt_tx = EthereumResolver.resolver_receipt( receipt_raw_tx) else: self.logger.error( '请求 {} receipt 错误, 重新处理') raise tx.status = receipt_tx.status # session.begin(subtransactions=True) # db_tx = Transaction(block_id=db_block.id, coin_id=coin['coin_id'], # tx_hash=tx.tx_hash, height=db_block.height, # block_time=block_timestamp, # amount=tx.value, sender=tx.sender, receiver=tx.receiver, # gas=tx.gas, gas_price=tx.gas_price, # is_send=SendEnum.NOT_PUSH.value, # fee=receipt_tx.gas_used * tx.gas_price, # contract=tx.contract, status=receipt_tx.status, # type=TxTypeEnum.DEPOSIT.value) Transaction.add_transaction_or_update( block_id=db_block.id, coin_id=coin['coin_id'], tx_hash=tx.tx_hash, height=db_block.height, block_time=block_timestamp, amount=tx.value, sender=tx.sender, receiver=tx.receiver, gas=tx.gas, gas_price=tx.gas_price, is_send=SendEnum.NOT_PUSH.value, fee=receipt_tx.gas_used * tx.gas_price, contract=tx.contract, status=receipt_tx.status, type=TxTypeEnum.DEPOSIT.value, session=session, commit=False) save_tx_count += 1 # session.add(db_tx) # session.commit() # 添加推送信息 session.query(SyncConfig).filter( SyncConfig.id == self.config_id).update({ 'synced_height': height + block_batch, 'highest_height': self.highest_height }) self.current_scan_height = height + block_batch session.commit() self.logger.info("本次同步高度为:{} -- {}, 保存交易: {} 笔".format( height, height + block_batch, save_tx_count)) except Exception as e: self.logger.error('同步块出现异常, 事务回滚. {}'.format(e)) session.rollback() return self.logger.info("扫链结束, 本次同步")
def render(self): self.logger.info('开始补充手续费进程') for pid, p in self.project_addresses.items(): project_address = p['address'] for ck, coin in runtime.coins.items(): if coin['coin_name'] == self.COIN_NAME: self.logger.warning('币种名称为: {}, 不需要补充手续费!'.format( coin['coin_name'])) continue contract = coin['contract'] offset, count = 0, self.BALANCE_QUERY_NUMBER for s in range(0, len(project_address), count): addresses = project_address[offset:count] balances = self.rpc.get_balance(addresses, contract) balances_sum = sum([ digit.hex_to_int(balance) for balance in balances if balance ]) if not balances_sum: self.logger.info("本 {} 个地址无额外, 不需要补充手续费".format( len(addresses))) continue for idx, balance in enumerate(balances): balance_int = hex_to_int(balance) if not balance_int: continue balance_eth_int = hex_to_int( self.rpc.get_balance(address=addresses[idx])) if hasattr(config, 'GAS'): gas = config.GAS else: gas = self.rpc.get_smart_fee(contract=contract) if hasattr(config, 'GAS_PRICE'): gas_price = config.GAS_PRICE else: gas_price = self.rpc.gas_price() if gas is None: self.logger.info("未找到合适 gas . {}".format(gas)) continue if gas_price is None: self.logger.info( "未找到合适 gas_price . {}".format(gas_price)) continue gas, gas_price = hex_to_int(gas), hex_to_int(gas_price) fee = gas * gas_price if balance_eth_int > fee: self.logger.info("地址: {} 手续费足够, 不需要补充手续费".format( addresses[idx])) continue render_amount = int(config.COLLECTION_MIN_ETH * 1e18) tx_hash = self.rpc.send_transaction( sender=config.RENDER_ADDRESS, receiver=addresses[idx], value=render_amount, passphrase=p['passphrase'], gas=gas, gas_price=gas_price, contract=contract) if not tx_hash: self.logger.error("给地址: {} 补充手续费失败".format( addresses[idx])) continue self.logger.info("给地址: {} 补充手续费成功".format( addresses[idx])) with runtime.app.app_context(): saved = Transaction.add_transaction( coin_id=coin['coin_id'], tx_hash=tx_hash, block_time=datetime.now().timestamp(), sender=config.RENDER_ADDRESS, receiver=addresses[idx], amount=render_amount, status=TxStatusEnum.UNKNOWN.value, type=TxTypeEnum.RENDER.value, block_id=-1, height=-1, gas=gas, gas_price=gas_price, contract=contract) self.logger.info('结束补充手续费进程')
def collection(self): self.logger.info('开始归集进程') for pid, p in self.project_addresses.items(): project_address = p['address'] for ck, coin in runtime.coins.items(): contract = coin['contract'] offset, count = 0, self.BALANCE_QUERY_NUMBER for s in range(0, len(project_address), count): addresses = project_address[offset:count] balances = self.rpc.get_balance(addresses, contract) balances_sum = sum([ digit.hex_to_int(balance) for balance in balances if balance ]) if not balances_sum: self.logger.info("本 {} 个地址不需要归集".format( len(addresses))) continue for idx, balance in enumerate(balances): balance_int = hex_to_int(balance) if not balance_int: continue if hasattr(config, 'GAS'): gas = config.GAS else: gas = self.rpc.get_smart_fee(contract=contract) if hasattr(config, 'GAS_PRICE'): gas_price = config.GAS_PRICE else: gas_price = self.rpc.gas_price() if gas is None: self.logger.info("未找到合适 gas . {}".format(gas)) continue if gas_price is None: self.logger.info( "未找到合适 gas_price . {}".format(gas_price)) continue gas, gas_price = hex_to_int(gas), hex_to_int(gas_price) fee = gas * gas_price if coin['symbol'] == 'ETH': send_value = max( balance_int - max(int(config.COLLECTION_MIN_ETH * 1e18), fee), 0) else: send_value = balance_int if send_value <= 0: self.logger.info("地址 {} 需要归集金额低于 0".format( addresses[idx])) continue tx_hash = self.rpc.send_transaction( sender=addresses[idx], receiver=config.COLLECTION_ADDRESS, value=send_value, passphrase=p['passphrase'], gas=gas, gas_price=gas_price, contract=contract) with runtime.app.app_context(): saved = Transaction.add_transaction( coin_id=coin['coin_id'], tx_hash=tx_hash, block_time=datetime.now().timestamp(), sender=addresses[idx], receiver=config.COLLECTION_ADDRESS, amount=send_value, status=TxStatusEnum.UNKNOWN.value, type=TxTypeEnum.COLLECTION.value, block_id=-1, height=-1, gas=gas, gas_price=gas_price, contract=contract) offset += count self.logger.info("结束归集进程")
def get_tx_by_tx_hash(tx_hash: str): rpc = RpcConfig.get_rpc() if rpc is None: return ResponseObject.error(**out_data_missing) chain_info = rpc.get_block_height() tx = Transaction.get_tx_coin_by_tx_hash(tx_hash=tx_hash) if tx: return ResponseObject.success( data={ "sender": tx.Transaction.sender, "receiver": tx.Transaction.receiver, "txHash": tx.Transaction.tx_hash, "value": safe_math.divided(tx.Transaction.amount, safe_math.e_calc( tx.Coin.decimal)).to_eng_string(), "blockHeight": tx.Transaction.height, "blockTime": tx.Transaction.block_time, "contract": tx.Transaction.contract, "isValid": True if tx.Transaction.status == 1 else False, "confirmNumber": chain_info.highest_height - tx.Transaction.height if tx.Transaction.height > 0 else 0 }) else: tx_origin, receipt_origin = rpc.get_transaction_by_hash(tx_hash) if tx_origin and receipt_origin: tx, receipt = EthereumResolver.resolver_transaction( tx_origin), EthereumResolver.resolver_receipt(receipt_origin) block_info = rpc.get_block_by_number(int_to_hex(tx.block_height), False) if not block_info: return ResponseObject.error(**rpc_block_not_found) block = EthereumResolver.resolver_block(block_info, False) if tx.contract is not None: coin = Coin.get_erc20_usdt_coin() else: coin = Coin.get_coin(name='Ethereum') if coin is None: return ResponseObject.error(**coin_missing) return ResponseObject.success( data={ "sender": tx.sender, "receiver": tx.receiver, "txHash": tx.tx_hash, "value": safe_math.divided(tx.value, safe_math.e_calc( coin.decimal)).to_eng_string(), "blockHeight": tx.block_height, "blockTime": block.timestamp, "contract": tx.contract, "isValid": True if receipt.status == 1 else False, "confirmNumber": chain_info.highest_height - tx.block_height }) return ResponseObject.error(**tx_miss)