9
9
from time import sleep
10
10
11
11
from web3 import Web3
12
+ from web3 .types import Wei
12
13
13
14
from uniswap import Uniswap
14
15
from uniswap .constants import ETH_ADDRESS
15
- from uniswap .exceptions import InsufficientBalance
16
+ from uniswap .fee import FeeTier
17
+ from uniswap .exceptions import InsufficientBalance ,InvalidFeeTier
16
18
from uniswap .tokens import get_tokens
17
19
from uniswap .util import (
18
20
_str_to_addr ,
@@ -75,11 +77,11 @@ def test_assets(client: Uniswap):
75
77
("USDC" ,10_000 * ONE_USDC ),
76
78
]:
77
79
token_addr = tokens [token_name ]
78
- price = client .get_price_output (_str_to_addr (ETH_ADDRESS ),token_addr ,amount )
80
+ price = client .get_price_output (_str_to_addr (ETH_ADDRESS ),token_addr ,amount , fee = FeeTier . TIER_3000 )
79
81
logger .info (f"Cost of{ amount } { token_name } :{ price } " )
80
82
logger .info ("Buying..." )
81
83
82
- txid = client .make_trade_output (tokens ["ETH" ],token_addr ,amount )
84
+ txid = client .make_trade_output (tokens ["ETH" ],token_addr ,amount , fee = FeeTier . TIER_3000 )
83
85
tx = client .w3 .eth .wait_for_transaction_receipt (txid ,timeout = RECEIPT_TIMEOUT )
84
86
assert tx ["status" ]== 1 ,f"Transaction failed:{ tx } "
85
87
@@ -159,47 +161,47 @@ def test_get_fee_taker(self, client: Uniswap):
159
161
160
162
# ------ Market --------------------------------------------------------------------
161
163
@pytest .mark .parametrize (
162
- "token0, token1, qty, kwargs " ,
164
+ "token0, token1, qty" ,
163
165
[
164
- ("ETH" ,"UNI" ,ONE_ETH , {} ),
165
- ("UNI" ,"ETH" ,ONE_ETH , {} ),
166
- ("ETH" ,"DAI" ,ONE_ETH , {} ),
167
- ("DAI" ,"ETH" ,ONE_ETH , {} ),
168
- ("ETH" ,"UNI" ,2 * ONE_ETH , {} ),
169
- ("UNI" ,"ETH" ,2 * ONE_ETH , {} ),
170
- ("WETH" ,"DAI" ,ONE_ETH , {} ),
171
- ("DAI" ,"WETH" ,ONE_ETH , {} ),
172
- ("DAI" ,"USDC" ,ONE_ETH , { "fee" : 500 } ),
166
+ ("ETH" ,"UNI" ,ONE_ETH ),
167
+ ("UNI" ,"ETH" ,ONE_ETH ),
168
+ ("ETH" ,"DAI" ,ONE_ETH ),
169
+ ("DAI" ,"ETH" ,ONE_ETH ),
170
+ ("ETH" ,"UNI" ,2 * ONE_ETH ),
171
+ ("UNI" ,"ETH" ,2 * ONE_ETH ),
172
+ ("WETH" ,"DAI" ,ONE_ETH ),
173
+ ("DAI" ,"WETH" ,ONE_ETH ),
174
+ ("DAI" ,"USDC" ,ONE_ETH ),
173
175
],
174
176
)
175
- def test_get_price_input (self ,client ,tokens ,token0 ,token1 ,qty , kwargs ):
177
+ def test_get_price_input (self ,client : Uniswap ,tokens ,token0 ,token1 ,qty ):
176
178
token0 ,token1 = tokens [token0 ],tokens [token1 ]
177
179
if client .version == 1 and ETH_ADDRESS not in [token0 ,token1 ]:
178
180
pytest .skip ("Not supported in this version of Uniswap" )
179
- r = client .get_price_input (token0 ,token1 ,qty ,** kwargs )
181
+ r = client .get_price_input (token0 ,token1 ,qty ,fee = FeeTier . TIER_3000 )
180
182
assert r
181
183
182
184
@pytest .mark .parametrize (
183
- "token0, token1, qty, kwargs " ,
185
+ "token0, token1, qty" ,
184
186
[
185
- ("ETH" ,"UNI" ,ONE_ETH , {} ),
186
- ("UNI" ,"ETH" ,ONE_ETH // 100 , {} ),
187
- ("ETH" ,"DAI" ,ONE_ETH , {} ),
188
- ("DAI" ,"ETH" ,ONE_ETH , {} ),
189
- ("ETH" ,"UNI" ,2 * ONE_ETH , {} ),
190
- ("WETH" ,"DAI" ,ONE_ETH , {} ),
191
- ("DAI" ,"WETH" ,ONE_ETH , {} ),
192
- ("DAI" ,"USDC" ,ONE_USDC , { "fee" : 500 } ),
187
+ ("ETH" ,"UNI" ,ONE_ETH ),
188
+ ("UNI" ,"ETH" ,ONE_ETH // 100 ),
189
+ ("ETH" ,"DAI" ,ONE_ETH ),
190
+ ("DAI" ,"ETH" ,ONE_ETH ),
191
+ ("ETH" ,"UNI" ,2 * ONE_ETH ),
192
+ ("WETH" ,"DAI" ,ONE_ETH ),
193
+ ("DAI" ,"WETH" ,ONE_ETH ),
194
+ ("DAI" ,"USDC" ,ONE_USDC ),
193
195
],
194
196
)
195
- def test_get_price_output (self ,client ,tokens ,token0 ,token1 ,qty , kwargs ):
197
+ def test_get_price_output (self ,client : Uniswap ,tokens ,token0 ,token1 ,qty ):
196
198
token0 ,token1 = tokens [token0 ],tokens [token1 ]
197
199
if client .version == 1 and ETH_ADDRESS not in [token0 ,token1 ]:
198
200
pytest .skip ("Not supported in this version of Uniswap" )
199
- r = client .get_price_output (token0 ,token1 ,qty ,** kwargs )
201
+ r = client .get_price_output (token0 ,token1 ,qty ,fee = FeeTier . TIER_3000 )
200
202
assert r
201
203
202
- @pytest .mark .parametrize ("token0, token1, fee" , [("DAI" ,"USDC" ,500 )])
204
+ @pytest .mark .parametrize ("token0, token1, fee" , [("DAI" ,"USDC" ,FeeTier . TIER_3000 )])
203
205
def test_get_raw_price (self ,client :Uniswap ,tokens ,token0 ,token1 ,fee ):
204
206
token0 ,token1 = tokens [token0 ],tokens [token1 ]
205
207
if client .version == 1 :
@@ -210,7 +212,7 @@ def test_get_raw_price(self, client: Uniswap, tokens, token0, token1, fee):
210
212
@pytest .mark .parametrize (
211
213
"token0, token1, kwargs" ,
212
214
[
213
- ("WETH" ,"DAI" , {"fee" :500 }),
215
+ ("WETH" ,"DAI" , {"fee" :FeeTier . TIER_3000 }),
214
216
],
215
217
)
216
218
def test_get_pool_instance (self ,client ,tokens ,token0 ,token1 ,kwargs ):
@@ -223,7 +225,7 @@ def test_get_pool_instance(self, client, tokens, token0, token1, kwargs):
223
225
@pytest .mark .parametrize (
224
226
"token0, token1, kwargs" ,
225
227
[
226
- ("WETH" ,"DAI" , {"fee" :500 }),
228
+ ("WETH" ,"DAI" , {"fee" :FeeTier . TIER_3000 }),
227
229
],
228
230
)
229
231
def test_get_pool_immutables (self ,client ,tokens ,token0 ,token1 ,kwargs ):
@@ -238,7 +240,7 @@ def test_get_pool_immutables(self, client, tokens, token0, token1, kwargs):
238
240
@pytest .mark .parametrize (
239
241
"token0, token1, kwargs" ,
240
242
[
241
- ("WETH" ,"DAI" , {"fee" :500 }),
243
+ ("WETH" ,"DAI" , {"fee" :FeeTier . TIER_3000 }),
242
244
],
243
245
)
244
246
def test_get_pool_state (self ,client ,tokens ,token0 ,token1 ,kwargs ):
@@ -253,7 +255,7 @@ def test_get_pool_state(self, client, tokens, token0, token1, kwargs):
253
255
@pytest .mark .parametrize (
254
256
"amount0, amount1, token0, token1, kwargs" ,
255
257
[
256
- (1 ,10 ,"WETH" ,"DAI" , {"fee" :500 }),
258
+ (1 ,10 ,"WETH" ,"DAI" , {"fee" :FeeTier . TIER_3000 }),
257
259
],
258
260
)
259
261
def test_mint_position (
@@ -308,7 +310,7 @@ def test_get_exchange_rate(
308
310
@pytest .mark .parametrize (
309
311
"token0, token1, amount0, amount1, qty, fee" ,
310
312
[
311
- ("DAI" ,"USDC" ,ONE_ETH ,ONE_USDC ,ONE_ETH ,3000 ),
313
+ ("DAI" ,"USDC" ,ONE_ETH ,ONE_USDC ,ONE_ETH ,FeeTier . TIER_3000 ),
312
314
],
313
315
)
314
316
def test_v3_deploy_pool_with_liquidity (
@@ -325,14 +327,14 @@ def test_v3_deploy_pool_with_liquidity(
325
327
print (pool .address )
326
328
# Ensuring client has sufficient balance of both tokens
327
329
eth_to_dai = client .make_trade (
328
- tokens ["ETH" ],tokens [token0 ],qty ,client .address
330
+ tokens ["ETH" ],tokens [token0 ],qty ,client .address , fee = fee ,
329
331
)
330
332
eth_to_dai_tx = client .w3 .eth .wait_for_transaction_receipt (
331
333
eth_to_dai ,timeout = RECEIPT_TIMEOUT
332
334
)
333
335
assert eth_to_dai_tx ["status" ]
334
336
dai_to_usdc = client .make_trade (
335
- tokens [token0 ],tokens [token1 ],qty * 10 ,client .address
337
+ tokens [token0 ],tokens [token1 ],qty * 10 ,client .address , fee = fee ,
336
338
)
337
339
dai_to_usdc_tx = client .w3 .eth .wait_for_transaction_receipt (
338
340
dai_to_usdc ,timeout = RECEIPT_TIMEOUT
@@ -381,7 +383,7 @@ def test_get_tvl_in_pool_on_chain(self, client: Uniswap, tokens, token0, token1)
381
383
if client .version != 3 :
382
384
pytest .skip ("Not supported in this version of Uniswap" )
383
385
384
- pool = client .get_pool_instance (tokens [token0 ],tokens [token1 ])
386
+ pool = client .get_pool_instance (tokens [token0 ],tokens [token1 ], fee = FeeTier . TIER_3000 )
385
387
tvl_0 ,tvl_1 = client .get_tvl_in_pool (pool )
386
388
assert tvl_0 > 0
387
389
assert tvl_1 > 0
@@ -452,7 +454,7 @@ def test_make_trade(
452
454
with expectation ():
453
455
bal_in_before = client .get_token_balance (input_token )
454
456
455
- txid = client .make_trade (input_token ,output_token ,qty ,recipient )
457
+ txid = client .make_trade (input_token ,output_token ,qty ,recipient , fee = FeeTier . TIER_3000 )
456
458
tx = web3 .eth .wait_for_transaction_receipt (txid ,timeout = RECEIPT_TIMEOUT )
457
459
assert tx ["status" ],f"Transaction failed with status{ tx ['status' ]} :{ tx } "
458
460
@@ -474,13 +476,6 @@ def test_make_trade(
474
476
# ("ETH", "UNI", int(0.000001 * ONE_ETH), ZERO_ADDRESS),
475
477
# ("UNI", "ETH", int(0.000001 * ONE_ETH), ZERO_ADDRESS),
476
478
# ("DAI", "UNI", int(0.000001 * ONE_ETH), ZERO_ADDRESS),
477
- (
478
- "DAI" ,
479
- "ETH" ,
480
- 10 * ONE_ETH ,
481
- None ,
482
- lambda :pytest .raises (InsufficientBalance ),
483
- ),
484
479
("DAI" ,"DAI" ,ONE_USDC ,None ,lambda :pytest .raises (ValueError )),
485
480
],
486
481
)
@@ -504,11 +499,45 @@ def test_make_trade_output(
504
499
with expectation ():
505
500
balance_before = client .get_token_balance (output_token )
506
501
507
- r = client .make_trade_output (input_token ,output_token ,qty ,recipient )
502
+ r = client .make_trade_output (input_token ,output_token ,qty ,recipient , fee = FeeTier . TIER_3000 )
508
503
tx = web3 .eth .wait_for_transaction_receipt (r ,timeout = RECEIPT_TIMEOUT )
509
504
assert tx ["status" ]
510
505
511
- # TODO: Checks for ETH, taking gas into account
506
+ ## TODO: Checks for ETH, taking gas into account
512
507
balance_after = client .get_token_balance (output_token )
513
508
if output_token != tokens ["ETH" ]:
514
509
assert balance_before + qty == balance_after
510
+
511
+ def test_fee_required_for_uniswap_v3 (
512
+ self ,
513
+ client :Uniswap ,
514
+ tokens ,
515
+ )-> None :
516
+ if client .version != 3 :
517
+ pytest .skip ("Not supported in this version of Uniswap" )
518
+ with pytest .raises (InvalidFeeTier ):
519
+ client .get_price_input (tokens ["ETH" ],tokens ["UNI" ],ONE_ETH ,fee = None )
520
+ with pytest .raises (InvalidFeeTier ):
521
+ client .get_price_output (tokens ["ETH" ],tokens ["UNI" ],ONE_ETH ,fee = None )
522
+ with pytest .raises (InvalidFeeTier ):
523
+ client ._get_eth_token_output_price (tokens ["UNI" ],ONE_ETH ,fee = None )
524
+ with pytest .raises (InvalidFeeTier ):
525
+ client ._get_token_eth_output_price (tokens ["UNI" ],Wei (ONE_ETH ),fee = None )
526
+ with pytest .raises (InvalidFeeTier ):
527
+ client ._get_token_token_output_price (
528
+ tokens ["UNI" ],tokens ["ETH" ],ONE_ETH ,fee = None
529
+ )
530
+ with pytest .raises (InvalidFeeTier ):
531
+ client .make_trade (tokens ["ETH" ],tokens ["UNI" ],ONE_ETH ,fee = None )
532
+ with pytest .raises (InvalidFeeTier ):
533
+ client .make_trade_output (tokens ["ETH" ],tokens ["UNI" ],ONE_ETH ,fee = None )
534
+ # NOTE: (rudiemeant@gmail.com): Since in 0.7.1 we're breaking the
535
+ # backwards-compatibility with 0.7.0, we should check
536
+ # that clients now get an error when trying to call methods
537
+ # without explicitly specifying a fee tier.
538
+ with pytest .raises (InvalidFeeTier ):
539
+ client .get_pool_instance (tokens ["ETH" ],tokens ["UNI" ],fee = None )# type: ignore[arg-type]
540
+ with pytest .raises (InvalidFeeTier ):
541
+ client .create_pool_instance (tokens ["ETH" ],tokens ["UNI" ],fee = None )# type: ignore[arg-type]
542
+ with pytest .raises (InvalidFeeTier ):
543
+ client .get_raw_price (tokens ["ETH" ],tokens ["UNI" ],fee = None )