def set_fee(_w3: Web3, _fee: float): """ Set new fee for battery registraton :param Web3 _w3: Web3 instance :param float _fee: New fee to set :return: Status message :rtype: str """ data = utils.open_data_base(ACCOUNT_DB_NAME) actor = data['account'] tx = {'from': actor, 'gasPrice': utils.get_actual_gas_price(_w3)} mgmt_contract = utils.init_management_contract(_w3) utils.unlock_account(_w3, actor, data['password']) tx_hash = mgmt_contract.functions.setFee(_w3.toWei(_fee, 'ether')).transact(tx) receipt = web3.eth.wait_for_transaction_receipt(_w3, tx_hash, 120, 0.1) result = receipt.status if result == 1: return f"{bcolors.OKGREEN}Fee setting was successfull{bcolors.ENDC}" else: return f"{bcolors.FAIL}Fee setting failed{bcolors.ENDC}"
def transfer_battery_to_sc(w3: Web3, car_battery_id: str, sc_address: str): """ Transfer battery to service center :param Web3 w3: Web3 instance :param str car_battery_id: Car's battery id :param str sc_battery_id: Service centers's battery id return: Nothing rtype: None """ data = utils.open_data_base(MGMT_CONTRACT_DB_NAME) if data is None: return 'Cannot access management contract database' data = utils.open_data_base(ACCOUNT_DB_NAME) if data is None: return 'Cannot access account database' private_key = data['key'] battery_mgmt_contract_addr = utils.get_battery_managment_contract_addr(w3) battery_mgmt_contract = utils.init_battery_management_contract( w3, battery_mgmt_contract_addr) car_address = w3.eth.account.privateKeyToAccount(private_key).address gas_price = utils.get_actual_gas_price(w3) nonce = w3.eth.getTransactionCount(car_address) tx = {'gasPrice': gas_price, 'nonce': nonce, 'gas': 2204 * 68 + 21000} reg_tx = battery_mgmt_contract.functions.transfer( sc_address, decode_hex(car_battery_id)).buildTransaction(tx) sign_tx = w3.eth.account.signTransaction(reg_tx, private_key) tx_hash = w3.eth.sendRawTransaction(sign_tx.rawTransaction) receipt = web3.eth.wait_for_transaction_receipt(w3, tx_hash, 120, 0.1) if receipt.status != 1: sys.exit( f"{bcolors.FAIL}The car does not own this battery!{bcolors.ENDC}")
def register_car(_w3: Web3): """ Register new car :param Web3 _w3: Web3 instance """ data = utils.open_data_base(MGMT_CONTRACT_DB_NAME) if data is None: return f'{bcolors.FAIL}Cannot access management contract database{bcolors.ENDC}' data = CONFIG if data is None: return f'{bcolors.FAIL}Cannot access account database{bcolors.ENDC}' private_key = data['key'] mgmt_contract = utils.init_management_contract(_w3) car_address = _w3.eth.account.privateKeyToAccount(private_key).address registration_required_gas = 50000 gas_price = utils.get_actual_gas_price(_w3) if registration_required_gas * gas_price > _w3.eth.getBalance(car_address): return 'No enough funds to send transaction' nonce = _w3.eth.getTransactionCount(car_address) tx = {'gasPrice': gas_price, 'nonce': nonce} regTx = mgmt_contract.functions.registerCar().buildTransaction(tx) signTx = _w3.eth.account.signTransaction(regTx, private_key) txHash = _w3.eth.sendRawTransaction(signTx.rawTransaction) receipt = web3.eth.wait_for_transaction_receipt(_w3, txHash, 120, 0.1) if receipt.status == 1: return f'{bcolors.OKGREEN}Registered successfully{bcolors.ENDC}' else: return f'{bcolors.FAIL}Car registration failed{bcolors.ENDC}'
def register_scenter(_w3: Web3): """ Register new service center :param Web3 _w3: Web3 instance :return: Registration status message :rtype: str """ mgmt_contract = utils.init_management_contract(_w3) data = utils.open_data_base(ACCOUNT_DB_NAME) if data is None: sys.exit(f"{bcolors.FAIL}Cannot access account database{bcolors.ENDC}") actor = data['account'] tx = {'from': actor, 'gasPrice': utils.get_actual_gas_price(_w3)} if REGISTRATION_REQUIRED_GAS * tx['gasPrice'] > _w3.eth.getBalance(actor): sys.exit( f"{bcolors.FAIL}No enough funds to send transaction{bcolors.ENDC}") utils.unlock_account(_w3, actor, data['password']) try: tx_hash = mgmt_contract.functions.registerServiceCenter().transact(tx) except ValueError: sys.exit(f"{bcolors.FAIL}Already registered{bcolors.ENDC}") receipt = web3.eth.wait_for_transaction_receipt(_w3, tx_hash, 120, 0.1) if receipt.status == 1: return f"{bcolors.OKGREEN}Registered successfully{bcolors.ENDC}" else: return f"{bcolors.FAIL}Registration failed{bcolors.ENDC}"
def change_owner(_w3: Web3, _battery_id: str, _new_owner: str) -> str: """ Change the owner of battery :param Web3 _w3: Web3 instance :param str _battery_id: battery ID :param str _new_owner: New owner address :return: Status message :rtype: str """ data = utils.open_data_base(ACCOUNT_DB_NAME) actor = data['account'] tx = { 'from': actor, 'gasPrice': utils.get_actual_gas_price(_w3), 'gas': 2204 * 68 + 21000 } battery_mgmt_contract_addr = utils.get_battery_managment_contract_addr(_w3) battery_mgmt_contract = utils.init_battery_management_contract( _w3, battery_mgmt_contract_addr) utils.unlock_account(_w3, actor, data['password']) tx_hash = battery_mgmt_contract.functions.transfer( _new_owner, decode_hex(_battery_id)).transact(tx) receipt = web3.eth.wait_for_transaction_receipt(_w3, tx_hash, 120, 0.1) result = receipt.status if result == 1: return f"{bcolors.OKGREEN}Ownership change was successfull{bcolors.ENDC}" else: return f"{bcolors.FAIL}Ownership change failed{bcolors.ENDC}"
def main() -> None: w3 = Web3(Web3.HTTPProvider(URL)) # configure provider to work with PoA chains w3.middleware_onion.inject(geth_poa_middleware, layer=0) parser = create_parser() args = parser.parse_args() config = utils.open_data_base("account.json") if config is None: sys.exit(f"{bcolors.FAIL}Can't access account database{bcolors.ENDC}") actor = w3.toChecksumAddress(config['account']) gas_price = utils.get_actual_gas_price(w3) global TX_TEMPLATE TX_TEMPLATE = {'from': actor, 'gasPrice': gas_price} if args.new: print(utils.create_new_account(w3, args.new, ACCOUNT_DB_NAME)) elif args.reg: w3.geth.personal.unlockAccount(actor, config['password'], 300) result = register_vendor(w3, args.reg[0], w3.toWei(float(args.reg[1]), 'ether')) if isinstance(result, bytes): print( f'{bcolors.OKGREEN}Success{bcolors.ENDC}\nVendor ID: {bcolors.HEADER}{del_hex_prefix(w3.toHex(result))}{bcolors.ENDC}' ) else: sys.exit(result) elif args.bat: w3.geth.personal.unlockAccount(actor, config['password'], 300) if len(args.bat) == 1: result = register_battery(w3, int(args.bat[0])) else: result = register_battery(w3, int(args.bat[0]), Web3.toWei(float(args.bat[1]))) if isinstance(result, list): for bat_id in result: print( f'Created battery with id: {bcolors.HEADER}{bat_id[2:]}{bcolors.ENDC}' ) elif args.regfee: print( f'Vendor registration fee: {bcolors.HEADER}{get_fee(w3) * 1000}{bcolors.ENDC} eth' ) elif args.batfee: print( f'Battery registration fee: {bcolors.HEADER}{get_fee(w3)}{bcolors.ENDC} eth' ) elif args.deposit: print( f"Vendor deposit: {bcolors.HEADER}{get_deposit(w3)}{bcolors.ENDC} eth" ) elif args.owner: print(change_owner(w3, args.owner[0], args.owner[1])) else: sys.exit(f"{bcolors.FAIL}No parameters provided{bcolors.ENDC}")
def setup(_w3: Web3, _service_fee: float) -> Union[dict, None]: """ Deploy and initialize Management, BatteryManagement, ServiceProviderWallet and CurrencyToken contracts to the blockchain :param Web3 _w3: Web3 instance :params float _service_fee: Set fee for battery registration :return: Pairs of contract names and their addresses if setup successfull and None if not :rtype: dict/None """ service_fee = _w3.toWei(_service_fee, 'ether') data = utils.open_data_base(ACCOUNT_DB_NAME) if data is None: print("Can't access account database") return actor = data['account'] utils.unlock_account(_w3, actor, data['password']) tx_dict = {} for i in ['token', 'wallet']: tx_dict[i] = utils._deploy_contract(_w3, actor, CONTRACTS[i][0], CONTRACTS[i][1]) # wait for deployment transactions validation receipt_dict = utils._wait_for_validation(_w3, tx_dict) currency_token_contract_addr = receipt_dict['token'][1]['contractAddress'] service_provider_wallet_addr = receipt_dict['wallet'][1]['contractAddress'] if (receipt_dict['token'][1] is not None) and (receipt_dict['wallet'][1] is not None): currency_token_contract_addr = receipt_dict['token'][1]['contractAddress'] service_provider_wallet_addr = receipt_dict['wallet'][1]['contractAddress'] if service_provider_wallet_addr is not None: # deploy managment contract mgmt_contract_addr = utils._deploy_contract_and_wait(_w3, actor, CONTRACTS['mgmt'][0], CONTRACTS['mgmt'][1], service_provider_wallet_addr, service_fee) if mgmt_contract_addr is not None: utils._create_mgmt_contract_db(mgmt_contract_addr) # deploy battery managment battery_mgmt_contract_addr = utils._deploy_contract_and_wait(_w3, actor, CONTRACTS['battery'][0], CONTRACTS['battery'][1], mgmt_contract_addr, currency_token_contract_addr) if battery_mgmt_contract_addr is not None: compiled_contract = utils.compile_contracts(CONTRACTS['mgmt'][0]) mgmt_contract = utils.initialize_contract_factory(_w3, compiled_contract, CONTRACTS['mgmt'][0] + ':' + CONTRACTS['mgmt'][1], mgmt_contract_addr) tx_hash = mgmt_contract.functions.setBatteryManagementContract(battery_mgmt_contract_addr).transact({'from': actor, 'gasPrice': utils.get_actual_gas_price(_w3)}) receipt = web3.eth.wait_for_transaction_receipt(_w3, tx_hash, 120, 0.1) if receipt.status == 1: contract_addresses = { 'Management contract': mgmt_contract_addr, 'Wallet contract' : service_provider_wallet_addr, 'Currency contract:' : currency_token_contract_addr } return contract_addresses return None