def __init__( self, jsonrpc_client: JSONRPCClient, user_deposit_address: UserDepositAddress, contract_manager: ContractManager, proxy_manager: "ProxyManager", ) -> None: if not is_binary_address(user_deposit_address): raise ValueError("Expected binary address format for token nework") check_address_has_code( client=jsonrpc_client, address=Address(user_deposit_address), contract_name=CONTRACT_USER_DEPOSIT, expected_code=decode_hex( contract_manager.get_runtime_hexcode(CONTRACT_USER_DEPOSIT)), ) self.client = jsonrpc_client self.address = user_deposit_address self.node_address = self.client.address self.contract_manager = contract_manager self.gas_measurements = gas_measurements( self.contract_manager.contracts_version) self.proxy_manager = proxy_manager self.proxy = jsonrpc_client.new_contract_proxy( abi=self.contract_manager.get_contract_abi(CONTRACT_USER_DEPOSIT), contract_address=Address(user_deposit_address), ) self.deposit_lock = RLock()
def token_network(self, address: TokenNetworkAddress) -> TokenNetwork: if not is_binary_address(address): raise ValueError("address must be a valid address") with self._token_network_creation_lock: if address not in self.address_to_token_network: metadata = TokenNetworkMetadata( deployed_at=None, abi=self.contract_manager.get_contract_abi( CONTRACT_TOKEN_NETWORK), gas_measurements=gas_measurements( self.contract_manager.contracts_version), runtime_bytecode=EVMBytecode( decode_hex( self.contract_manager.get_runtime_hexcode( CONTRACT_TOKEN_NETWORK))), address=Address(address), token_network_registry_address=None, filters_start_at=self.metadata.filters_start_at, ) self.address_to_token_network[address] = TokenNetwork( jsonrpc_client=self.client, contract_manager=self.contract_manager, proxy_manager=self, metadata=metadata, ) return self.address_to_token_network[address]
def get_required_gas_estimate(raiden: "RaidenService", channels_to_open: int = 0) -> int: gas_estimate = _get_required_gas_estimate_for_state(raiden) measurements = gas_measurements(raiden.contract_manager.contracts_version) gas_estimate += _get_required_gas_estimate(gas_measurements=measurements, new_channels=channels_to_open) return gas_estimate
def token_network_registry( self, address: TokenNetworkRegistryAddress) -> TokenNetworkRegistry: with self._token_network_registry_creation_lock: if address not in self.address_to_token_network_registry: metadata = SmartContractMetadata( deployed_at=self.metadata. token_network_registry_deployed_at, address=Address(address), abi=self.contract_manager.get_contract_abi( CONTRACT_TOKEN_NETWORK_REGISTRY), runtime_bytecode=EVMBytecode( decode_hex( self.contract_manager.get_runtime_hexcode( CONTRACT_TOKEN_NETWORK_REGISTRY))), gas_measurements=gas_measurements( self.contract_manager.contracts_version), filters_start_at=self.metadata.filters_start_at, ) self.address_to_token_network_registry[ address] = TokenNetworkRegistry(rpc_client=self.client, metadata=metadata, proxy_manager=self) return self.address_to_token_network_registry[address]
def calc_claim_cost_rdn(web3: Web3, rdn_per_eth: float) -> TokenAmount: web3.eth.setGasPriceStrategy(rpc_gas_price_strategy) claim_cost_gas = gas_measurements()["OneToN.claim"] claim_cost_eth = claim_cost_gas * web3.eth.generateGasPrice( ) * GAS_COST_SAFETY_MARGIN claim_cost_rdn = TokenAmount(int(claim_cost_eth / rdn_per_eth)) return claim_cost_rdn
def test_gas_json_has_enough_fields(version: Optional[str]) -> None: """ Check is gas.json contains enough fields """ doc = gas_measurements(version) keys = { "CustomToken.mint", "CustomToken.approve", "CustomToken.transfer", "CustomToken.transferFrom", "MonitoringService.claimReward", "MonitoringService.monitor", "OneToN.claim", "OneToN.bulkClaim 1 ious", "OneToN.bulkClaim 6 ious", "SecretRegistry.registerSecret", "ServiceRegistry.deposit", "ServiceRegistry.setURL", "TokenNetwork DEPLOYMENT", "TokenNetwork.closeChannel", "TokenNetwork.openChannel", "TokenNetwork.setTotalDeposit", "TokenNetwork.setTotalWithdraw", "TokenNetwork.settleChannel", "TokenNetwork.unlock 1 locks", "TokenNetwork.unlock 6 locks", "TokenNetwork.updateNonClosingBalanceProof", "TokenNetworkRegistry DEPLOYMENT", "TokenNetworkRegistry createERC20TokenNetwork", "UserDeposit.deposit", "UserDeposit.deposit (increase balance)", "UserDeposit.planWithdraw", "UserDeposit.withdraw", } assert set(doc.keys()) == keys
def calc_claim_cost_rdn(web3: Web3, rdn_per_eth: float) -> TokenAmount: web3.eth.setGasPriceStrategy(rpc_gas_price_strategy) claim_cost_gas = gas_measurements()["OneToN.claim"] gas_price = web3.eth.generateGasPrice() assert gas_price is not None, "Could not generate gas price" claim_cost_eth = claim_cost_gas * gas_price * GAS_COST_SAFETY_MARGIN return TokenAmount(int(claim_cost_eth / rdn_per_eth))
def get_approximate_registration_cost(web3: Web3) -> int: gas_costs = gas_measurements() gas_cost = ( gas_costs["CustomToken.approve"] + gas_costs["ServiceRegistry.deposit"] + gas_costs["ServiceRegistry.setURL"] ) gas_price = web3.eth.generate_gas_price() assert gas_price is not None, "No gas price strategy set" return gas_cost * gas_price
def get_required_gas_estimate(raiden: "RaidenService", channels_to_open: int = 0) -> int: num_opening_channels = 0 num_opened_channels = 0 num_closing_channels = 0 num_closed_channels = 0 num_settling_channels = 0 num_settled_channels = 0 # Only use the token networks that have been instantiated. Instantiating # the token networks here has a very high performance impact for a registry # with lots of tokens. # # The lock is being acquired to prevent chnages to the dictionary while # iterating over it. with raiden.proxy_manager.token_network_creation_lock: num_opening_channels = sum( token_network.opening_channels_count for token_network in raiden.proxy_manager.address_to_token_network.values()) chain_state = views.state_from_raiden(raiden) registry_address = raiden.default_registry.address token_addresses = views.get_token_identifiers(chain_state, registry_address) for token_address in token_addresses: num_opened_channels += len( views.get_channelstate_open(chain_state, registry_address, token_address)) num_closing_channels += len( views.get_channelstate_closing(chain_state, registry_address, token_address)) num_closed_channels += len( views.get_channelstate_closed(chain_state, registry_address, token_address)) num_settling_channels += len( views.get_channelstate_settling(chain_state, registry_address, token_address)) num_settled_channels += len( views.get_channelstate_settled(chain_state, registry_address, token_address)) return _get_required_gas_estimate( gas_measurements=gas_measurements( raiden.contract_manager.contracts_version), opening_channels=num_opening_channels + channels_to_open, opened_channels=num_opened_channels, closing_channels=num_closing_channels, closed_channels=num_closed_channels, settling_channels=num_settling_channels, settled_channels=num_settled_channels, )
def check_gas_reserve(web3: Web3, private_key: str) -> None: """ Check periodically for gas reserve in the account """ gas_price = web3.eth.gasPrice gas_limit = gas_measurements()["MonitoringService.monitor"] estimated_required_balance = gas_limit * gas_price * DEFAULT_GAS_BUFFER_FACTOR estimated_required_balance_eth = Web3.fromWei(estimated_required_balance, "ether") current_balance = web3.eth.getBalance(private_key_to_address(private_key)) if current_balance < estimated_required_balance: log.error( "Your account's balance is below the estimated gas reserve of " f"{estimated_required_balance_eth} Eth. You will be be unable " "to perform on-chain transactions and cannot monitor any channels. " "Please add funds to your account as soon as possible.")
def _get_required_gas_estimate_for_state(raiden: "RaidenService") -> int: num_opening_channels = 0 num_opened_channels = 0 num_closing_channels = 0 num_closed_channels = 0 num_settling_channels = 0 num_settled_channels = 0 # Only use the token networks that have been instantiated. Instantiating # the token networks here can have a high performance impacet for a token # network registry with lots of registeres tokens. with raiden.proxy_manager.token_network_creation_lock: num_opening_channels = sum( token_network.opening_channels_count for token_network in raiden.proxy_manager.address_to_token_network.values()) chain_state = views.state_from_raiden(raiden) registry_address = raiden.default_registry.address token_addresses = views.get_token_identifiers(chain_state, registry_address) for token_address in token_addresses: num_opened_channels += len( views.get_channelstate_open(chain_state, registry_address, token_address)) num_closing_channels += len( views.get_channelstate_closing(chain_state, registry_address, token_address)) num_closed_channels += len( views.get_channelstate_closed(chain_state, registry_address, token_address)) num_settling_channels += len( views.get_channelstate_settling(chain_state, registry_address, token_address)) num_settled_channels += len( views.get_channelstate_settled(chain_state, registry_address, token_address)) return _get_required_gas_estimate( gas_measurements=gas_measurements( raiden.contract_manager.contracts_version), opening_channels=num_opening_channels, opened_channels=num_opened_channels, closing_channels=num_closing_channels, closed_channels=num_closed_channels, settling_channels=num_settling_channels, settled_channels=num_settled_channels, )
def _get_required_gas_estimate_for_state(raiden: "RaidenService") -> int: chain_state = views.state_from_raiden(raiden) registry_address = raiden.default_registry.address token_addresses = views.get_token_identifiers(chain_state, registry_address) measurements = gas_measurements(raiden.contract_manager.contracts_version) gas_estimate = 0 for token_address in token_addresses: token_network_address = views.get_token_network_address_by_token_address( chain_state=chain_state, token_network_registry_address=registry_address, token_address=token_address, ) if token_network_address is None: continue num_opening_channels = raiden.proxy_manager.token_network( token_network_address).opening_channels_count num_opened_channels = len( views.get_channelstate_open(chain_state, registry_address, token_address)) num_closing_channels = len( views.get_channelstate_closing(chain_state, registry_address, token_address)) num_closed_channels = len( views.get_channelstate_closed(chain_state, registry_address, token_address)) num_settling_channels = len( views.get_channelstate_settling(chain_state, registry_address, token_address)) num_settled_channels = len( views.get_channelstate_settled(chain_state, registry_address, token_address)) gas_estimate += _get_required_gas_estimate( gas_measurements=measurements, opening_channels=num_opening_channels, opened_channels=num_opened_channels, closing_channels=num_closing_channels, closed_channels=num_closed_channels, settling_channels=num_settling_channels, settled_channels=num_settled_channels, ) return gas_estimate
def token_network_from_registry( self, token_network_registry_address: TokenNetworkRegistryAddress, token_address: TokenAddress, block_identifier: BlockSpecification = "latest", ) -> TokenNetwork: token_network_registry = self.token_network_registry( token_network_registry_address) token_network_address = token_network_registry.get_token_network( token_address=token_address, block_identifier=block_identifier) if token_network_address is None: raise ValueError( f"{to_checksum_address(token_network_registry_address)} does not " f"have the token {to_checksum_address(token_address)} " f"registered.") with self._token_network_creation_lock: if token_network_address not in self.address_to_token_network: metadata = TokenNetworkMetadata( deployed_at=None, address=Address(token_network_address), abi=self.contract_manager.get_contract_abi( CONTRACT_TOKEN_NETWORK), gas_measurements=gas_measurements( self.contract_manager.contracts_version), runtime_bytecode=EVMBytecode( decode_hex( self.contract_manager.get_runtime_hexcode( CONTRACT_TOKEN_NETWORK))), token_network_registry_address= token_network_registry_address, filters_start_at=token_network_registry.metadata. filters_start_at, ) self.address_to_token_network[ token_network_address] = TokenNetwork( jsonrpc_client=self.client, contract_manager=self.contract_manager, proxy_manager=self, metadata=metadata, ) return self.address_to_token_network[token_network_address]
def __init__( self, jsonrpc_client: JSONRPCClient, user_deposit_address: UserDepositAddress, contract_manager: ContractManager, proxy_manager: "ProxyManager", block_identifier: BlockIdentifier, ) -> None: if not is_binary_address(user_deposit_address): raise ValueError("Expected binary address format for token nework") check_address_has_code_handle_pruned_block( client=jsonrpc_client, address=Address(user_deposit_address), contract_name=CONTRACT_USER_DEPOSIT, expected_code=decode_hex( contract_manager.get_runtime_hexcode(CONTRACT_USER_DEPOSIT)), given_block_identifier=block_identifier, ) self.client = jsonrpc_client self.address = user_deposit_address self.node_address = self.client.address self.contract_manager = contract_manager self.gas_measurements = gas_measurements( self.contract_manager.contracts_version) self.proxy_manager = proxy_manager self.proxy = jsonrpc_client.new_contract_proxy( abi=self.contract_manager.get_contract_abi(CONTRACT_USER_DEPOSIT), contract_address=Address(user_deposit_address), ) # Keeps track of the current in-flight deposits, to avoid sending # unecessary transactions. self._inflight_deposits: Dict[Address, InflightDeposit] = dict() # Don't allow concurrent withdraw_plan and withdraw calls. # This simplifies the precondition checks. self._withdraw_lock = Lock()