def test_datafeed_median_gas_price_strategy(): mock_etherchain_gas_price = 1000 mock_upvest_gas_price = 2000 mock_zoltu_gas_price = 4000 mock_rpc_gas_price = 42 def construct_mock_gas_strategy(gas_price) -> Callable: def _mock_gas_strategy(web3, tx=None): return gas_price return _mock_gas_strategy # In normal circumstances, all datafeeds in the strategy work, and the median is returned with patch('nucypher.utilities.datafeeds.UpvestGasPriceDatafeed.construct_gas_strategy', return_value=construct_mock_gas_strategy(mock_upvest_gas_price)): with patch('nucypher.utilities.datafeeds.EtherchainGasPriceDatafeed.construct_gas_strategy', return_value=construct_mock_gas_strategy(mock_etherchain_gas_price)): with patch('nucypher.utilities.datafeeds.ZoltuGasPriceDatafeed.construct_gas_strategy', return_value=construct_mock_gas_strategy(mock_zoltu_gas_price)): datafeed_median_gas_price_strategy = construct_datafeed_median_strategy() assert datafeed_median_gas_price_strategy("web3", "tx") == median([mock_etherchain_gas_price, mock_upvest_gas_price, mock_zoltu_gas_price]) # If, for example, Upvest fails, the median is computed using the other two feeds with patch('nucypher.utilities.datafeeds.UpvestGasPriceDatafeed._probe_feed', side_effect=Datafeed.DatafeedError): with patch('nucypher.utilities.datafeeds.EtherchainGasPriceDatafeed.construct_gas_strategy', return_value=construct_mock_gas_strategy(mock_etherchain_gas_price)): with patch('nucypher.utilities.datafeeds.ZoltuGasPriceDatafeed.construct_gas_strategy', return_value=construct_mock_gas_strategy(mock_zoltu_gas_price)): datafeed_median_gas_price_strategy = construct_datafeed_median_strategy() assert datafeed_median_gas_price_strategy("web3", "tx") == median([mock_etherchain_gas_price, mock_zoltu_gas_price]) # If only one feed works, then the return value corresponds to this feed with patch('nucypher.utilities.datafeeds.UpvestGasPriceDatafeed._probe_feed', side_effect=Datafeed.DatafeedError): with patch('nucypher.utilities.datafeeds.EtherchainGasPriceDatafeed._probe_feed', side_effect=Datafeed.DatafeedError): with patch('nucypher.utilities.datafeeds.ZoltuGasPriceDatafeed.construct_gas_strategy', return_value=construct_mock_gas_strategy(mock_zoltu_gas_price)): datafeed_median_gas_price_strategy = construct_datafeed_median_strategy() assert datafeed_median_gas_price_strategy("web3", "tx") == mock_zoltu_gas_price # If all feeds fail, we fallback to the rpc_gas_price_strategy with patch('nucypher.utilities.datafeeds.EtherchainGasPriceDatafeed._probe_feed', side_effect=Datafeed.DatafeedError): with patch('nucypher.utilities.datafeeds.UpvestGasPriceDatafeed._probe_feed', side_effect=Datafeed.DatafeedError): with patch('nucypher.utilities.datafeeds.ZoltuGasPriceDatafeed._probe_feed', side_effect=Datafeed.DatafeedError): with patch('nucypher.utilities.gas_strategies.rpc_gas_price_strategy', side_effect=construct_mock_gas_strategy(mock_rpc_gas_price)): datafeed_median_gas_price_strategy = construct_datafeed_median_strategy() assert datafeed_median_gas_price_strategy("web3", "tx") == mock_rpc_gas_price
def configure_gas_strategy(self, gas_strategy: Optional[Callable] = None ) -> None: if gas_strategy: reported_gas_strategy = f"fixed/{gas_strategy.name}" elif isinstance(self.client, InfuraClient): gas_strategy = construct_datafeed_median_strategy( speed=self.gas_strategy) reported_gas_strategy = f"datafeed/{self.gas_strategy}" else: reported_gas_strategy = f"web3/{self.gas_strategy}" gas_strategy = self.get_gas_strategy(self.gas_strategy) configuration_message = f"Using gas strategy '{reported_gas_strategy}'" if self.max_gas_price: __price = Web3.toWei(self.max_gas_price, 'gwei') # from gwei to wei gas_strategy = max_price_gas_strategy_wrapper( gas_strategy=gas_strategy, max_gas_price_wei=__price) configuration_message += f", with a max price of {self.max_gas_price} gwei." self.client.set_gas_strategy(gas_strategy=gas_strategy) gwei_gas_price = Web3.fromWei(self.client.gas_price_for_transaction(), 'gwei') self.log.info(configuration_message) self.log.debug( f"Gas strategy currently reports a gas price of {gwei_gas_price} gwei." )
def configure_gas_strategy(self, gas_strategy: Optional[Callable] = None ) -> None: if gas_strategy: reported_gas_strategy = f"fixed/{gas_strategy.name}" elif isinstance(self.client, InfuraClient): gas_strategy = construct_datafeed_median_strategy( speed=self.gas_strategy) reported_gas_strategy = f"datafeed/{self.gas_strategy}" else: reported_gas_strategy = f"web3/{self.gas_strategy}" gas_strategy = self.get_gas_strategy(self.gas_strategy) configuration_message = f"Using gas strategy '{reported_gas_strategy}'" if self.max_gas_price: __price = Web3.toWei(self.max_gas_price, 'gwei') # from gwei to wei gas_strategy = max_price_gas_strategy_wrapper( gas_strategy=gas_strategy, max_gas_price_wei=__price) configuration_message += f", with a max price of {self.max_gas_price} gwei." self.client.set_gas_strategy(gas_strategy=gas_strategy) # TODO: This line must not be called prior to establishing a connection # Move it down to a lower layer, near the client. # gwei_gas_price = Web3.fromWei(self.client.gas_price_for_transaction(), 'gwei') self.log.info(configuration_message)