Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 2a5c791

Browse filesBrowse files
committed
test: fixed tests
1 parent cdadaf3 commit 2a5c791
Copy full SHA for 2a5c791

File tree

Expand file treeCollapse file tree

3 files changed

+75
-30
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+75
-30
lines changed

‎pyproject.toml

Copy file name to clipboardExpand all lines: pyproject.toml
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ Sphinx = "*"
3939
sphinx-book-theme = "*"
4040
sphinx-click = "*"
4141

42+
[tool.pytest.ini_options]
43+
log_cli = false # to print logs during tests, set to true
44+
#log_level = "NOTSET"
45+
4246
[build-system]
4347
requires = ["poetry>=0.12"]
4448
build-backend = "poetry.masonry.api"

‎tests/test_uniswap.py

Copy file name to clipboardExpand all lines: tests/test_uniswap.py
+19-3Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919

2020
logger = logging.getLogger(__name__)
21+
logging.basicConfig(level=logging.INFO)
2122

2223
ENV_UNISWAP_VERSION = os.getenv("UNISWAP_VERSION", None)
2324
if ENV_UNISWAP_VERSION:
@@ -38,7 +39,11 @@ class GanacheInstance:
3839
@pytest.fixture(scope="module", params=UNISWAP_VERSIONS)
3940
def client(request, web3: Web3, ganache: GanacheInstance):
4041
return Uniswap(
41-
ganache.eth_address, ganache.eth_privkey, web3=web3, version=request.param
42+
ganache.eth_address,
43+
ganache.eth_privkey,
44+
web3=web3,
45+
version=request.param,
46+
use_estimate_gas=False, # see note in _build_and_send_tx
4247
)
4348

4449

@@ -80,11 +85,22 @@ def ganache() -> Generator[GanacheInstance, None, None]:
8085
)
8186

8287
port = 10999
88+
defaultGasPrice = 1000_000_000_000 # 1000 gwei
8389
p = subprocess.Popen(
84-
f"ganache --port {port} -s test --networkId 1 --fork {os.environ['PROVIDER']}",
90+
f"""ganache
91+
--port {port}
92+
--wallet.seed test
93+
--chain.networkId 1
94+
--chain.chainId 1
95+
--fork.url {os.environ['PROVIDER']}
96+
--miner.defaultGasPrice {defaultGasPrice}
97+
--miner.legacyInstamine true
98+
""".replace(
99+
"\n", " "
100+
),
85101
shell=True,
86102
)
87-
# Address #1 when ganache is run with `-s test`, it starts with 100 ETH
103+
# Address #1 when ganache is run with `--wallet.seed test`, it starts with 1000 ETH
88104
eth_address = "0x94e3361495bD110114ac0b6e35Ed75E77E6a6cFA"
89105
eth_privkey = "0x6f1313062db38875fb01ee52682cbf6a8420e92bfbc578c5d4fdc0a32c50266f"
90106
sleep(3)

‎uniswap/uniswap.py

Copy file name to clipboardExpand all lines: uniswap/uniswap.py
+52-27Lines changed: 52 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,16 @@ class Uniswap:
4545
Wrapper around Uniswap contracts.
4646
"""
4747

48+
address: AddressLike
49+
version: int
50+
51+
w3: Web3
52+
netid: int
53+
netname: str
54+
55+
default_slippage: float
56+
use_estimate_gas: bool
57+
4858
def __init__(
4959
self,
5060
address: Union[AddressLike, str, None],
@@ -53,6 +63,8 @@ def __init__(
5363
web3: Web3 = None,
5464
version: int = 1,
5565
default_slippage: float = 0.01,
66+
use_estimate_gas: bool = True,
67+
# use_eip1559: bool = True,
5668
factory_contract_addr: str = None,
5769
router_contract_addr: str = None,
5870
) -> None:
@@ -66,7 +78,7 @@ def __init__(
6678
:param factory_contract_addr: Can be optionally set to override the address of the factory contract.
6779
:param router_contract_addr: Can be optionally set to override the address of the router contract (v2 only).
6880
"""
69-
self.address: AddressLike = _str_to_addr(
81+
self.address = _str_to_addr(
7082
address or "0x0000000000000000000000000000000000000000"
7183
)
7284
self.private_key = (
@@ -78,22 +90,23 @@ def __init__(
7890

7991
# TODO: Write tests for slippage
8092
self.default_slippage = default_slippage
93+
self.use_estimate_gas = use_estimate_gas
8194

8295
if web3:
8396
self.w3 = web3
8497
else:
8598
# Initialize web3. Extra provider for testing.
86-
self.provider = provider or os.environ["PROVIDER"]
87-
self.w3 = Web3(
88-
Web3.HTTPProvider(self.provider, request_kwargs={"timeout": 60})
89-
)
90-
91-
netid = int(self.w3.net.version)
92-
if netid in _netid_to_name:
93-
self.network = _netid_to_name[netid]
99+
if not provider:
100+
provider = os.environ["PROVIDER"]
101+
self.w3 = Web3(Web3.HTTPProvider(provider, request_kwargs={"timeout": 60}))
102+
103+
# Cache netid to avoid extra RPC calls
104+
self.netid = int(self.w3.net.version)
105+
if self.netid in _netid_to_name:
106+
self.netname = _netid_to_name[self.netid]
94107
else:
95-
raise Exception(f"Unknown netid: {netid}")
96-
logger.info(f"Using {self.w3} ('{self.network}')")
108+
raise Exception(f"Unknown netid: {self.netid}")
109+
logger.info(f"Using {self.w3} ('{self.netname}', netid: {self.netid})")
97110

98111
self.last_nonce: Nonce = self.w3.eth.get_transaction_count(self.address)
99112

@@ -102,14 +115,14 @@ def __init__(
102115
# max_approval_check checks that current approval is above a reasonable number
103116
# The program cannot check for max_approval each time because it decreases
104117
# with each trade.
105-
self.max_approval_hex = f"0x{64 * 'f'}"
106-
self.max_approval_int = int(self.max_approval_hex, 16)
107-
self.max_approval_check_hex = f"0x{15 * '0'}{49 * 'f'}"
108-
self.max_approval_check_int = int(self.max_approval_check_hex, 16)
118+
max_approval_hex = f"0x{64 * 'f'}"
119+
self.max_approval_int = int(max_approval_hex, 16)
120+
max_approval_check_hex = f"0x{15 * '0'}{49 * 'f'}"
121+
self.max_approval_check_int = int(max_approval_check_hex, 16)
109122

110123
if self.version == 1:
111124
if factory_contract_addr is None:
112-
factory_contract_addr = _factory_contract_addresses_v1[self.network]
125+
factory_contract_addr = _factory_contract_addresses_v1[self.netname]
113126

114127
self.factory_contract = _load_contract(
115128
self.w3,
@@ -118,11 +131,11 @@ def __init__(
118131
)
119132
elif self.version == 2:
120133
if router_contract_addr is None:
121-
router_contract_addr = _router_contract_addresses_v2[self.network]
134+
router_contract_addr = _router_contract_addresses_v2[self.netname]
122135
self.router_address: AddressLike = _str_to_addr(router_contract_addr)
123136

124137
if factory_contract_addr is None:
125-
factory_contract_addr = _factory_contract_addresses_v2[self.network]
138+
factory_contract_addr = _factory_contract_addresses_v2[self.netname]
126139
self.factory_contract = _load_contract(
127140
self.w3,
128141
abi_name="uniswap-v2/factory",
@@ -1085,8 +1098,19 @@ def _build_and_send_tx(
10851098
if not tx_params:
10861099
tx_params = self._get_tx_params()
10871100
transaction = function.buildTransaction(tx_params)
1088-
# Uniswap3 uses 20% margin for transactions
1089-
transaction["gas"] = Wei(int(self.w3.eth.estimate_gas(transaction) * 1.2))
1101+
1102+
if "gas" not in tx_params:
1103+
# `use_estimate_gas` needs to be True for networks like Arbitrum (can't assume 250000 gas),
1104+
# but it breaks tests for unknown reasons because estimateGas takes forever on some tx's.
1105+
# Maybe an issue with ganache? (got GC warnings once...)
1106+
if self.use_estimate_gas:
1107+
# The Uniswap V3 UI uses 20% margin for transactions
1108+
transaction["gas"] = Wei(
1109+
int(self.w3.eth.estimate_gas(transaction) * 1.2)
1110+
)
1111+
else:
1112+
transaction["gas"] = Wei(250000)
1113+
10901114
signed_txn = self.w3.eth.account.sign_transaction(
10911115
transaction, private_key=self.private_key
10921116
)
@@ -1098,15 +1122,18 @@ def _build_and_send_tx(
10981122
logger.debug(f"nonce: {tx_params['nonce']}")
10991123
self.last_nonce = Nonce(tx_params["nonce"] + 1)
11001124

1101-
def _get_tx_params(self, value: Wei = Wei(0)) -> TxParams:
1125+
def _get_tx_params(self, value: Wei = Wei(0), gas: Wei = None) -> TxParams:
11021126
"""Get generic transaction parameters."""
1103-
return {
1127+
params: TxParams = {
11041128
"from": _addr_to_str(self.address),
11051129
"value": value,
11061130
"nonce": max(
11071131
self.last_nonce, self.w3.eth.get_transaction_count(self.address)
11081132
),
11091133
}
1134+
if gas:
1135+
params["gas"] = gas
1136+
return params
11101137

11111138
# ------ Price Calculation Utils ---------------------------------------------------
11121139
def _calculate_max_input_token(
@@ -1255,14 +1282,12 @@ def _get_token_addresses(self) -> Dict[str, ChecksumAddress]:
12551282
Returns a dict with addresses for tokens for the current net.
12561283
Used in testing.
12571284
"""
1258-
netid = int(self.w3.net.version)
1259-
netname = _netid_to_name[netid]
1260-
if netname == "mainnet":
1285+
if self.netname == "mainnet":
12611286
return tokens
1262-
elif netname == "rinkeby":
1287+
elif self.netname == "rinkeby":
12631288
return tokens_rinkeby
12641289
else:
1265-
raise Exception(f"Unknown net '{netname}'")
1290+
raise Exception(f"Unknown net '{self.netname}'")
12661291

12671292
# ---- Old v1 utils ----
12681293

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.