mirror of https://github.com/nucypher/nucypher.git
Introduce equivalence classes for gas speed names
parent
1b5de0a266
commit
71ad8c2c31
|
@ -14,12 +14,14 @@
|
|||
You should have received a copy of the GNU Affero General Public License
|
||||
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from difflib import get_close_matches
|
||||
from typing import Optional
|
||||
|
||||
import requests
|
||||
from constant_sorrow.constants import SLOW, MEDIUM, FAST, FASTEST
|
||||
from web3 import Web3
|
||||
from web3.gas_strategies.rpc import rpc_gas_price_strategy
|
||||
from web3.types import Wei, TxParams
|
||||
|
||||
|
||||
|
@ -54,6 +56,13 @@ class EthereumGasPriceDatafeed(Datafeed):
|
|||
_speed_names = NotImplemented
|
||||
_default_speed = NotImplemented
|
||||
|
||||
_speed_equivalence_classes = {
|
||||
SLOW: ('slow', 'safeLow', 'low'),
|
||||
MEDIUM: ('medium', 'standard', 'average'),
|
||||
FAST: ('fast', 'high'),
|
||||
FASTEST: ('fastest', )
|
||||
}
|
||||
|
||||
@abstractmethod
|
||||
def _parse_gas_prices(self):
|
||||
return NotImplementedError
|
||||
|
@ -72,6 +81,22 @@ class EthereumGasPriceDatafeed(Datafeed):
|
|||
return gas_price
|
||||
return gas_price_strategy
|
||||
|
||||
@classmethod
|
||||
def get_canonical_speed(cls, speed: str):
|
||||
for canonical_speed, speed_names in cls._speed_equivalence_classes.items():
|
||||
if speed.lower() in map(str.lower, speed_names):
|
||||
return canonical_speed
|
||||
else:
|
||||
all_speed_names = [name for names in cls._speed_equivalence_classes.values() for name in names]
|
||||
suggestion = get_close_matches(speed, all_speed_names, n=1)
|
||||
if not suggestion:
|
||||
message = f"'{speed}' is not a valid speed name."
|
||||
else:
|
||||
suggestion = suggestion.pop()
|
||||
message = f"'{speed}' is not a valid speed name. Did you mean '{suggestion}'?"
|
||||
raise LookupError(message)
|
||||
|
||||
|
||||
|
||||
class EtherchainGasPriceDatafeed(EthereumGasPriceDatafeed):
|
||||
"""Gas price datafeed from Etherchain"""
|
||||
|
|
|
@ -18,14 +18,15 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
|||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from constant_sorrow.constants import SLOW, MEDIUM, FAST, FASTEST
|
||||
from requests.exceptions import ConnectionError
|
||||
from web3 import Web3
|
||||
|
||||
from nucypher.utilities.datafeeds import (
|
||||
EtherchainGasPriceDatafeed,
|
||||
Datafeed,
|
||||
UpvestGasPriceDatafeed
|
||||
)
|
||||
UpvestGasPriceDatafeed,
|
||||
EthereumGasPriceDatafeed)
|
||||
from nucypher.utilities.gas_strategies import datafeed_fallback_gas_price_strategy
|
||||
|
||||
etherchain_json = {
|
||||
|
@ -76,6 +77,41 @@ def test_probe_datafeed(mocker):
|
|||
assert feed._raw_data == json
|
||||
|
||||
|
||||
def test_canonical_speed_names():
|
||||
# Valid speed names, grouped in equivalence classes
|
||||
speed_equivalence_classes = {
|
||||
SLOW: ('slow', 'SLOW', 'Slow',
|
||||
'safeLow', 'safelow', 'SafeLow', 'SAFELOW',
|
||||
'low', 'LOW', 'Low'),
|
||||
MEDIUM: ('medium', 'MEDIUM', 'Medium',
|
||||
'standard', 'STANDARD', 'Standard',
|
||||
'average', 'AVERAGE', 'Average'),
|
||||
FAST: ('fast', 'FAST', 'Fast',
|
||||
'high', 'HIGH', 'High'),
|
||||
FASTEST: ('fastest', 'FASTEST', 'Fastest')
|
||||
}
|
||||
|
||||
for canonical_speed, equivalence_class in speed_equivalence_classes.items():
|
||||
for speed_name in equivalence_class:
|
||||
assert canonical_speed == EthereumGasPriceDatafeed.get_canonical_speed(speed_name)
|
||||
|
||||
# Invalid speed names, but that are somewhat similar to a valid one so we can give a suggestion
|
||||
similarities = (
|
||||
('hihg', 'high'),
|
||||
('zlow', 'low'),
|
||||
)
|
||||
|
||||
for wrong_name, suggestion in similarities:
|
||||
message = f"'{wrong_name}' is not a valid speed name. Did you mean '{suggestion}'?"
|
||||
with pytest.raises(LookupError, match=message):
|
||||
EthereumGasPriceDatafeed.get_canonical_speed(wrong_name)
|
||||
|
||||
# Utterly wrong speed names. Shame on you.
|
||||
wrong_name = "🙈"
|
||||
with pytest.raises(LookupError, match=f"'{wrong_name}' is not a valid speed name."):
|
||||
EthereumGasPriceDatafeed.get_canonical_speed(wrong_name)
|
||||
|
||||
|
||||
def test_etherchain():
|
||||
feed = EtherchainGasPriceDatafeed()
|
||||
|
||||
|
|
Loading…
Reference in New Issue