def run(self): try: while True: schedule.run_pending() time.sleep(1) if (self._max_job_invocation_count is not None) and \ (self._job_invocation_count >= self._max_job_invocation_count): Logger.printInfo('Max job invocation count reached. Exiting...') break except (KeyboardInterrupt, SystemExit): pass
def sanityChecks(analyzed_balance_map, queried_balance_map, expected_total_supply): total_supply = 0 for address in analyzed_balance_map.keys(): analyzed_balance = analyzed_balance_map[address] queried_balance = queried_balance_map.get(address, -1) if (analyzed_balance != queried_balance) or (queried_balance == -1): Logger.printError( "Balance mismatch for address: %s, analyzed_balance = %s, queried_balance = %s" % (address, analyzed_balance, queried_balance)) return False total_supply += int(queried_balance) Logger.printInfo('Expected total supply : %s' % (expected_total_supply)) Logger.printInfo('Sum of queried balances: %s' % (total_supply)) if total_supply != expected_total_supply: Logger.printError( 'Token total supply mismatch. expected = %s, calculated = %s' % (expected_total_supply, total_supply)) return False return True
def get(self): addresses = request.args.getlist(ApiKey.ADDRESS, None) nonce = request.args.get(ApiKey.NONCE, None) gas_price = request.args.get(ApiKey.GAS_PRICE, None) start_gas = request.args.get(ApiKey.START_GAS, None) if None in [addresses, nonce, gas_price, start_gas]: return HttpError( error_code=ApiErrorCode.QUERY_PARAM_MISSING, message= 'Query parameter missing! requires address, nonce, gas_price, and start_gas!' ).toJson() nonce = int(nonce) gas_price = int(gas_price) start_gas = int(start_gas) function_name = SupportedFunctionName.ADD_ACCOUNTS_TO_WHITELIST function_params = addresses key_info = KeyInfoManager.getKeyInfo(KeyAlias.WHITELIST_CONTROLLER) success, signed_tx = TransactionSigner.signTransaction( from_addr=key_info.address, nonce=nonce, gas_price=gas_price, start_gas=start_gas, smart_contract_name=SmartContractName.THETA_TOKEN_SALE, function_name=function_name, function_params=function_params, private_key=key_info.private_key) if not success: return HttpError( error_code=ApiErrorCode.TX_SIGNING_FAILURE, message='Failed to sign the transaction!').toJson() Logger.printInfo('Signed transaction - nonce: %s, function_name: %s, function_params: %s, signed_tx: %s'%\ (nonce, function_name, function_params, signed_tx)) return HttpSuccess({ApiKey.SIGNED_TX: signed_tx}).toJson()
def Export(self, start_height, end_height): Logger.printInfo("Start to extract events from height %s to %s..." % (start_height, end_height)) current_height = self.getProcessedHeight() if current_height >= start_height: Logger.printInfo("Already extracted up to height %s" % (current_height)) if current_height < end_height: Logger.printInfo("Continue from height %s..." % (current_height + 1)) else: current_height = start_height - 1 while current_height < end_height: from_height = current_height + 1 to_height = min( from_height + EthereumEventExtractor.HEIGHT_STEP - 1, end_height) self.export(from_height, to_height) current_height = to_height Logger.printInfo("Extracted events from height %s to %s" % (from_height, to_height))
def Query(self, addresses, target_height): num_addresses = len(addresses) Logger.printInfo("Total number of addresses: %s" % (num_addresses)) queried_balance_map = {} num_addresses_queried = 0 for address in addresses: balance = self.ethereum_rpc_service.GetTokenBalance( smart_contract_address=self.smart_contract_address, account_address=address, target_height=hex(target_height)) balance_str = str(balance) queried_balance_map[address] = balance_str num_addresses_queried += 1 if num_addresses_queried % 1000 == 0: Logger.printInfo("%s addresses queried." % (num_addresses_queried)) Logger.printInfo("%s addresses queried." % (num_addresses_queried)) return queried_balance_map
def exportTokenBalance(ethereum_rpc_url, smart_contract_address, expected_total_supply, genesis_height, target_height, balance_file_path): export_folder = "./data/events" if not os.path.exists(export_folder): os.makedirs(export_folder) Logger.printInfo('') Logger.printInfo('Start exporting Ethereum events...') eee = EthereumEventExtractor(ethereum_rpc_url, smart_contract_address, export_folder) eee.Export(genesis_height, target_height) Logger.printInfo('Ethereum events exported.') Logger.printInfo('') Logger.printInfo('Start extracting token holders...') eea = EthereumEventAnalyzer() analyzed_balance_map = eea.Analyze(export_folder, target_height) Logger.printInfo('Token holders extracted.') Logger.printInfo('') #with open(balance_file_path + '.analyzed', 'w') as balance_file: # json.dump(analyzed_balance_map, balance_file, indent=2) Logger.printInfo( 'Start querying the balance of each holder at block height %s, may take a while...' % (target_height)) token_holder_addresses = analyzed_balance_map.keys() tbe = TokenBalanceExtractor(ethereum_rpc_url, smart_contract_address) queried_balance_map = tbe.Query(token_holder_addresses, target_height) Logger.printInfo('Token holders balance retrieved.') Logger.printInfo('') #with open(balance_file_path + '.queried', 'w') as balance_file: # json.dump(queried_balance_map, balance_file, indent=2) Logger.printInfo('Start sanity checks...') if not sanityChecks(analyzed_balance_map, queried_balance_map, expected_total_supply): Logger.printError('Sanity checks failed.') exit(1) Logger.printInfo('Sanity checks all passed.') Logger.printInfo('') with open(balance_file_path, 'w') as balance_file: json.dump(queried_balance_map, balance_file, indent=2) Logger.printInfo('Token balances calculated and exported to: %s' % (balance_file_path)) Logger.printInfo('')
return False if KeyInfoManager.getKeyInfo(KeyAlias.EXCHANGE_RATE_CONTROLLER) == None: Logger.printError('%s key info not loaded!' % (KeyAlias.EXCHANGE_RATE_CONTROLLER)) return False success = TransactionSigner.initialize() if not success: return False return True app = Flask(__name__) api = Api(app) api.add_resource(WhitelistResource, '/whitelist/sign') api.add_resource(ExchangeRateResource, '/exchange_rate/sign') if __name__ == '__main__': path_to_config_file = '../config.json' path_to_key_info_json = '../data/key_info.json' success = initialize(path_to_config_file, path_to_key_info_json) if not success: exit(1) host = '0.0.0.0' port = ConfigManager.getConfig().getPort() Logger.printInfo('Running test server at %s:%s' % (host, port)) app.run(threaded=True, debug=True, host=host, port=port)