DeFiPy 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,28 @@
1
+ Metadata-Version: 2.1
2
+ Name: DeFiPy
3
+ Version: 0.0.1
4
+ Summary: DeFi for Python
5
+ Home-page: http://github.com/icmoore/defipy
6
+ Author: icmoore
7
+ Author-email: utiliwire@gmail.com
8
+ License: MIT
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE.txt
11
+
12
+ # defipy
13
+ Python package for DeFi modelling
14
+ * Currently in Beta (version 0.0.1) until fully tested and analyzed
15
+
16
+ ## Install
17
+ To install package:
18
+ ```
19
+ > git clone https://github.com/icmoore/defipy
20
+ > pip install .
21
+ ```
22
+ or
23
+ ```
24
+ > pip install DeFiPy
25
+ ```
26
+
27
+ ## DeFi Overview
28
+ * Python for DeFi analytics
@@ -0,0 +1,18 @@
1
+ LICENSE.txt
2
+ README.md
3
+ setup.cfg
4
+ setup.py
5
+ DeFiPy.egg-info/PKG-INFO
6
+ DeFiPy.egg-info/SOURCES.txt
7
+ DeFiPy.egg-info/dependency_links.txt
8
+ DeFiPy.egg-info/not-zip-safe
9
+ DeFiPy.egg-info/top_level.txt
10
+ python/prod/cst/exchg/StableswapExchange.py
11
+ python/prod/cst/exchg/StableswapPoolMath.py
12
+ python/prod/cst/exchg/__init__.py
13
+ python/prod/cst/factory/StableswapFactory.py
14
+ python/prod/cst/factory/__init__.py
15
+ python/prod/erc/ERC20.py
16
+ python/prod/erc/__init__.py
17
+ python/prod/group/StableswapERC20Group.py
18
+ python/prod/group/__init__.py
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,2 @@
1
+ defipy
2
+ python
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Ian Moore
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
DeFiPy-0.0.1/PKG-INFO ADDED
@@ -0,0 +1,28 @@
1
+ Metadata-Version: 2.1
2
+ Name: DeFiPy
3
+ Version: 0.0.1
4
+ Summary: DeFi for Python
5
+ Home-page: http://github.com/icmoore/defipy
6
+ Author: icmoore
7
+ Author-email: utiliwire@gmail.com
8
+ License: MIT
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE.txt
11
+
12
+ # defipy
13
+ Python package for DeFi modelling
14
+ * Currently in Beta (version 0.0.1) until fully tested and analyzed
15
+
16
+ ## Install
17
+ To install package:
18
+ ```
19
+ > git clone https://github.com/icmoore/defipy
20
+ > pip install .
21
+ ```
22
+ or
23
+ ```
24
+ > pip install DeFiPy
25
+ ```
26
+
27
+ ## DeFi Overview
28
+ * Python for DeFi analytics
DeFiPy-0.0.1/README.md ADDED
@@ -0,0 +1,17 @@
1
+ # defipy
2
+ Python package for DeFi modelling
3
+ * Currently in Beta (version 0.0.1) until fully tested and analyzed
4
+
5
+ ## Install
6
+ To install package:
7
+ ```
8
+ > git clone https://github.com/icmoore/defipy
9
+ > pip install .
10
+ ```
11
+ or
12
+ ```
13
+ > pip install DeFiPy
14
+ ```
15
+
16
+ ## DeFi Overview
17
+ * Python for DeFi analytics
@@ -0,0 +1,489 @@
1
+ # StableswapExchange.py
2
+ # Author: Ian Moore ( imoore@syscoin.org )
3
+ # Date: Oct 2023
4
+
5
+ from decimal import Decimal
6
+ from python.prod.group import StableswapERC20Group
7
+ from python.prod.cst.factory import StableswapFactory
8
+ from python.prod.cst.exchg.StableswapPoolMath import StableswapPoolMath
9
+
10
+ import math
11
+
12
+ GWEI_PRECISION = 18
13
+ GWEI_SWAP_FEE = 1000000
14
+ MINIMUM_LIQUIDITY = 1e-15
15
+ EXIT_FEE = 0
16
+
17
+ class StableswapExchange():
18
+
19
+ def __init__(self, creator: StableswapFactory, tkn_group : StableswapERC20Group, symbol: str, addr : str) -> None:
20
+ self.factory = creator
21
+ self.tkn_group = tkn_group
22
+ self.name = tkn_group.get_name()
23
+ self.symbol = symbol
24
+ self.addr = addr
25
+ self.tkn_reserves = {}
26
+ self.tkn_decimals = {}
27
+ self.tkn_fees = {}
28
+ self.collected_fees = {}
29
+ self.liquidity_providers = {}
30
+ self.total_supply = 0
31
+ self.last_liquidity_deposit = 0
32
+ self.math_pool = None
33
+ self.joined = False
34
+
35
+ def info(self):
36
+ if(self.total_supply == 0):
37
+ print(f"Stableswap Exchange: {self.name} ({self.symbol})")
38
+ print(f"Coins: {self.tkn_group.get_coins_str()}")
39
+ print(f"Liquidity: {self.total_supply} \n")
40
+ else:
41
+ reserve_str = " | ".join([f'{tkn_nm} = {self.tkn_reserves[tkn_nm]:.2f}' for tkn_nm in self.tkn_reserves])
42
+ print(f"Stableswap Exchange: {self.name} ({self.symbol})")
43
+ print(f"Coins: {self.tkn_group.get_coins_str()}")
44
+ print(f"Reserves: {reserve_str}")
45
+ print(f"Liquidity: {self.total_supply} \n")
46
+
47
+ def join_pool(self, tkn_group : StableswapERC20Group, ampl_coeff : float, to: str):
48
+
49
+ """ join_pool
50
+
51
+ Initialize a Stableswap pool, and add liquidity for all asset deposit
52
+
53
+ Parameters
54
+ -------
55
+ tkn_group : StableswapERC20Group
56
+ Group of ERC20 objects
57
+ amt_shares_in : float
58
+ Amount of pool shares in
59
+ to : str
60
+ User name/address
61
+ """
62
+
63
+ if(not self.joined):
64
+ self.tkn_group = tkn_group
65
+ self.tkn_reserves = tkn_group.get_balances().copy()
66
+ self.tkn_decimals = tkn_group.get_decimals().copy()
67
+
68
+ decimal_amts = list(self.tkn_group.get_decimal_amts().values())
69
+ rates = list(self.tkn_group.get_rates().values())
70
+
71
+ self.math_pool = StableswapPoolMath(A = ampl_coeff, D = decimal_amts, n = len(rates),
72
+ rates = rates, fee = GWEI_SWAP_FEE)
73
+ amt_liquidity_in = self._dec2amt(self.math_pool.tokens, GWEI_PRECISION)
74
+
75
+ if self.total_supply == 0:
76
+ self._mint('init_account', MINIMUM_LIQUIDITY)
77
+ amt_liquidity_in = amt_liquidity_in - MINIMUM_LIQUIDITY
78
+
79
+ self._mint(to, amt_liquidity_in)
80
+ self.joined = True
81
+ else:
82
+ assert not self.joined, 'Stableswap V1: POOL ALREADY JOINED'
83
+
84
+ def swap(self, amt_tkn_in, tkn_in, tkn_out, to):
85
+
86
+ """ swap
87
+
88
+ Swap output token given input token
89
+
90
+ Parameters
91
+ -------
92
+ amt_tkn_in : float
93
+ Amount of input token requested for swaping
94
+ tkn_in : ERC20
95
+ Input token
96
+ tkn_out : ERC20
97
+ Output token
98
+ to : str
99
+ User name/address
100
+ """
101
+
102
+ assert self.tkn_group.get_token(tkn_in.token_name) and self.tkn_group.get_token(tkn_out.token_name), "Stableswap: TOKEN NOT PART OF GROUP"
103
+ amount_out = self.get_amount_out(amt_tkn_in, tkn_in, tkn_out)
104
+ assert amount_out['tkn_out_amt'] <= tkn_out.token_total, 'Stableswap V1: INSUFFICIENT_OUTPUT_AMOUNT'
105
+
106
+ self._swap_math_pool(amt_tkn_in, tkn_in, tkn_out)
107
+ self.tkn_group.get_token(tkn_in.token_name).deposit(to, amt_tkn_in)
108
+ self._swap(amount_out['tkn_out_amt'], amount_out['tkn_in_fee'], tkn_out, tkn_in, to)
109
+ self._tally_fees(tkn_in, amount_out['tkn_in_fee'])
110
+
111
+ return amount_out
112
+
113
+ def add_liquidity(self, tkn_amt_in, tkn_in, to):
114
+
115
+ """ add_liquidity
116
+
117
+ Add token amounts for LP token
118
+
119
+ Parameters
120
+ -------
121
+ Parameters
122
+ -------
123
+ amt_shares_in : float
124
+ Amount of pool shares coming in
125
+ tkn_in : ERC20
126
+ Input token
127
+ to : str
128
+ User name/address
129
+ """
130
+
131
+ assert self.tkn_group.get_token(tkn_in.token_name), 'Stableswap V1: TOKEN NOT PART OF GROUP'
132
+
133
+ tkn_amts_in = [len(self.tkn_reserves)]*5
134
+
135
+ tkn_in_index = self._get_tkn_index(tkn_in.token_name)
136
+ dec_tkn_in = self.tkn_decimals[tkn_in.token_name]
137
+ tkn_in_dec = self._amt2dec(tkn_amt_in, dec_tkn_in)
138
+
139
+ tkn_amts_in[tkn_in_index] = tkn_in_dec
140
+ out = self.math_pool.add_liquidity(tkn_amts_in)
141
+ liquidity_amt_in = self._dec2amt(out, GWEI_PRECISION)
142
+
143
+ self.tkn_group.get_token(tkn_in.token_name).deposit(to, tkn_amt_in)
144
+ self.mint(liquidity_amt_in, tkn_amt_in, tkn_in, to)
145
+ self._tally_fees(tkn_in, 0)
146
+
147
+ return {'liquidity_amt_in': liquidity_amt_in, 'tkn_in_nm': tkn_in.token_name}
148
+
149
+ def remove_liquidity(self, liquidity_amt_out, tkn_out, to):
150
+
151
+ """ remove_liquidity
152
+
153
+ Remove liquidity from specified token in the pool based on lp amount
154
+
155
+ Parameters
156
+ -------
157
+ to : str
158
+ receiving user address
159
+ liquidity_amt_out : float
160
+ lp amount to removed
161
+ tkn_out : ERC20
162
+ Output token
163
+ """
164
+
165
+ assert self.tkn_group.get_token(tkn_out.token_name), 'Stableswap V1: TOKEN NOT PART OF GROUP'
166
+
167
+ total_liquidity = self.liquidity_providers[to]
168
+ if liquidity_amt_out >= total_liquidity:
169
+ liquidity_amt_out = total_liquidity
170
+
171
+ tkn_out_index = self._get_tkn_index(tkn_out.token_name)
172
+ dec_tkn_out = self.tkn_decimals[tkn_out.token_name]
173
+ liquidity_out_dec = self._amt2dec(liquidity_amt_out, GWEI_PRECISION)
174
+
175
+ dout, fee = self.math_pool.calc_withdraw_one_coin(liquidity_out_dec, tkn_out_index, True)
176
+ tkn_amt_out_min = self._dec2amt(dout, dec_tkn_out)
177
+
178
+ assert tkn_amt_out_min <= self.tkn_reserves[tkn_out.token_name], 'Stableswap V1: INSUFFICIENT TKN AMOUNT'
179
+
180
+ tkn_out_dec, tkn_out_fee_dec = self.math_pool.remove_liquidity_one_coin(liquidity_out_dec, tkn_out_index, True)
181
+ tkn_out_amt = self._dec2amt(tkn_out_dec, dec_tkn_out)
182
+ tkn_out_fee = self._dec2amt(tkn_out_fee_dec, dec_tkn_out)
183
+
184
+ self.burn(liquidity_amt_out, tkn_out_amt, tkn_out, to)
185
+ self._tally_fees(tkn_out, tkn_out_fee)
186
+
187
+ return {'tkn_out_amt': tkn_out_amt, 'tkn_out_nm': tkn_out.token_name, 'tkn_out_fee':tkn_out_fee}
188
+
189
+
190
+ def burn(self, liquidity_out, tkn_out_amt, tkn_out, _from):
191
+
192
+ """ burn
193
+
194
+ Burn liquidity from token based on amount of liquidity and amount of token
195
+
196
+ Parameters
197
+ -------
198
+ liquidity_out : float
199
+ Amount of liquidity requested for burn
200
+ amt_tkn_out : float
201
+ Amount of token requested for burn
202
+ tkn_out : ERC20
203
+ Output token
204
+ _from : str
205
+ User name/address
206
+ """
207
+
208
+ assert self.tkn_group.get_token(tkn_out.token_name), 'Stableswap V1: TOKEN NOT PART OF GROUP'
209
+
210
+ self._burn(_from, liquidity_out)
211
+ self.tkn_group.get_token(tkn_out.token_name).transfer(_from, tkn_out_amt)
212
+ new_balance = self.tkn_group.get_token(tkn_out.token_name).token_total
213
+ self._update(new_balance, tkn_out.token_name)
214
+
215
+ def _burn(self, _from, liquidity_out):
216
+
217
+ """ burn
218
+
219
+ Burn liquidity from token based on amount of liquidity
220
+
221
+ Parameters
222
+ -------
223
+ liquidity_out : float
224
+ Amount of liquidity requested for burn
225
+ _from : str
226
+ User name/address
227
+ """
228
+
229
+ exit_fee = liquidity_out * EXIT_FEE
230
+ available_liquidity = self.liquidity_providers.get(_from)
231
+ self.liquidity_providers[_from] = available_liquidity - liquidity_out - exit_fee
232
+ self.total_supply -= liquidity_out - exit_fee
233
+
234
+ def _swap(self, amt_swap, amt_fee, tkn_out, tkn_in, to):
235
+
236
+ """ _swap
237
+
238
+ Swap output token given input token
239
+
240
+ Parameters
241
+ -------
242
+ amt_out : float
243
+ Amount of input token requested for swaping
244
+ tkn_in : ERC20
245
+ Input token
246
+ tkn_out : ERC20
247
+ Output token
248
+ to : str
249
+ User name/address
250
+ """
251
+
252
+ self.tkn_group.get_token(tkn_out.token_name).transfer(to, amt_swap)
253
+ new_tkn_balances = self.tkn_group.get_balances()
254
+
255
+ res_balance_in = self.tkn_reserves[tkn_in.token_name]
256
+ res_balance_out = self.tkn_reserves[tkn_out.token_name]
257
+
258
+ new_balance_in = new_tkn_balances[tkn_in.token_name]
259
+ new_balance_out = new_tkn_balances[tkn_out.token_name]
260
+
261
+ if new_balance_in > res_balance_in - amt_swap:
262
+ amount_in = new_balance_in - res_balance_in
263
+ else:
264
+ amount_in = 0
265
+
266
+ assert amount_in > 0, 'Stableswap V1: INSUFFICIENT_INPUT_AMOUNT'
267
+
268
+ res_balance_in_adjusted = res_balance_in + amount_in
269
+ res_balance_out_adjusted = res_balance_out - amt_swap
270
+
271
+ lside = round(math.ceil(res_balance_in_adjusted * res_balance_out_adjusted), 8)
272
+ rside = round(math.ceil(new_balance_in * new_balance_out), 8)
273
+
274
+ assert lside == rside , 'Stableswap V1: LP BALANCES NOT ALIGNED TO TKN BALANCES'
275
+
276
+ self._update(new_balance_in, tkn_in.token_name)
277
+ self._update(new_balance_out, tkn_out.token_name)
278
+ self._tally_fees(tkn_in, amt_fee)
279
+
280
+
281
+ def _swap_math_pool(self, amt_tkn_in, tkn_in, tkn_out):
282
+
283
+ """ swap_math_pool
284
+
285
+ Given some amount of an asset, quotes an equivalent amount of the other asset
286
+
287
+ Parameters
288
+ -------
289
+ amt_tkn_in : float
290
+ Amount of token requested for quote
291
+ tkn_in : ERC20
292
+ Input token
293
+ tkn_out : ERC20
294
+ Output token
295
+ """
296
+
297
+ assert self.tkn_group.get_token(tkn_in.token_name), 'Stableswap V1: TOKEN NOT PART OF GROUP'
298
+
299
+ ind_tkn_in = self._get_tkn_index(tkn_in.token_name)
300
+ ind_tkn_out = self._get_tkn_index(tkn_out.token_name)
301
+
302
+ dec_tkn_in = self.tkn_decimals[tkn_in.token_name]
303
+ dec_tkn_out = self.tkn_decimals[tkn_out.token_name]
304
+
305
+ dx_tkn_in_dec = self._amt2dec(amt_tkn_in, dec_tkn_in)
306
+ out = self.math_pool.exchange(ind_tkn_in, ind_tkn_out, dx_tkn_in_dec)
307
+
308
+ tkn_out_amt = self._dec2amt(out[0], dec_tkn_out)
309
+ tkn_in_fee = self._dec2amt(out[1], dec_tkn_out)
310
+
311
+ return {'tkn_out_amt': tkn_out_amt, 'tkn_in_nm': tkn_in.token_name, 'tkn_in_fee': tkn_in_fee}
312
+
313
+ def get_amount_out(self, amt_tkn_in, tkn_in, tkn_out):
314
+
315
+ """ get_amount_out
316
+
317
+ Given some amount of an asset, quotes an equivalent amount of the other asset
318
+
319
+ Parameters
320
+ -------
321
+ amt_tkn_in : float
322
+ Amount of token requested for quote
323
+ tkn_in : ERC20
324
+ Input token
325
+ tkn_out : ERC20
326
+ Output token
327
+ """
328
+
329
+ assert self.tkn_group.get_token(tkn_in.token_name), 'Stableswap V1: TOKEN NOT PART OF GROUP'
330
+
331
+ ind_tkn_in = self._get_tkn_index(tkn_in.token_name)
332
+ ind_tkn_out = self._get_tkn_index(tkn_out.token_name)
333
+
334
+ dec_tkn_in = self.tkn_decimals[tkn_in.token_name]
335
+ dec_tkn_out = self.tkn_decimals[tkn_out.token_name]
336
+
337
+ dx_tkn_in_dec = self._amt2dec(amt_tkn_in, dec_tkn_in)
338
+ out = self.math_pool.get_amount_out(ind_tkn_in, ind_tkn_out, dx_tkn_in_dec)
339
+
340
+ tkn_out_amt = self._dec2amt(out[0], dec_tkn_out)
341
+ tkn_in_fee = self._dec2amt(out[1], dec_tkn_out)
342
+
343
+ return {'tkn_out_amt': tkn_out_amt, 'tkn_in_nm': tkn_in.token_name, 'tkn_in_fee': tkn_in_fee}
344
+
345
+
346
+ def mint(self, new_liquidity, amt_tkn_in, tkn_in, to):
347
+
348
+ """ mint
349
+
350
+ Update reserve amount for specific token in the pool
351
+
352
+ Parameters
353
+ -------
354
+ new_shares : float
355
+ Amount of new pool shares requested for minting
356
+ amt_tkn_in : float
357
+ Input token
358
+ tkn_in : ERC20
359
+ Output token
360
+ to : str
361
+ User name/address
362
+ """
363
+
364
+ tkn_balance = self.tkn_group.get_token(tkn_in.token_name).token_total
365
+ _amt_tkn_in = tkn_balance - self.tkn_reserves[tkn_in.token_name]
366
+
367
+ assert round(_amt_tkn_in,5) == round(amt_tkn_in,5), 'Stableswap V1: MINT ERROR'
368
+
369
+ new_balance = tkn_in.token_total
370
+ self._update(new_balance, tkn_in.token_name)
371
+ self._mint(to, new_liquidity)
372
+
373
+ def _tally_fees(self, tkn, fee):
374
+
375
+
376
+ """ _tally_fees
377
+
378
+ Tally fee from swap and record last collected fee
379
+
380
+ Parameters
381
+ -------
382
+ tkn : ERC20
383
+ Token where fees are being collected for
384
+ fee : float
385
+ Fee being collected
386
+ """
387
+
388
+ if tkn.token_name not in self.tkn_fees:
389
+ self.tkn_fees[tkn.token_name] = 0
390
+
391
+ self.tkn_fees[tkn.token_name] += fee
392
+
393
+ def _mint(self, to, value):
394
+
395
+ """ _mint
396
+
397
+ Update reserve amount for specific token in the pool
398
+
399
+ Parameters
400
+ -------
401
+ value : float
402
+ Amount of new pool shares requested for minting
403
+ to : str
404
+ User name/address
405
+ """
406
+
407
+ if self.liquidity_providers.get(to):
408
+ self.liquidity_providers[to] += value
409
+ else:
410
+ self.liquidity_providers[to] = value
411
+
412
+ self.last_liquidity_deposit = value
413
+ self.total_supply += value
414
+
415
+ def _update(self, new_balance, tkn_nm):
416
+
417
+ """ _update
418
+
419
+ Update reserve amounts specified token
420
+
421
+ Parameters
422
+ -------
423
+ new_balance : float
424
+ New reserve amount of token
425
+ tkn_nm : ERC20
426
+ Name of token being updated
427
+ """
428
+
429
+ self.tkn_reserves[tkn_nm] = new_balance
430
+
431
+ def _get_tkn_index(self, tkn_nm):
432
+ return list(self.tkn_reserves.keys()).index(tkn_nm)
433
+
434
+ def _amt2dec(self, tkn_amt, decimal):
435
+ return int(Decimal(str(tkn_amt))*Decimal(str(10**decimal)))
436
+
437
+ def _dec2amt(self, dec_amt, decimal):
438
+ return float(Decimal(str(dec_amt))/Decimal(str(10**decimal)))
439
+
440
+ def get_math_pool(self):
441
+ return self.math_pool
442
+
443
+ def get_reserve_decimal_amts(self):
444
+ decimal_amts = {}
445
+ token_decimals = self.tkn_group.get_decimals()
446
+ for tkn_nm in token_decimals:
447
+ tkn_amt = self.tkn_reserves[tkn_nm]
448
+ decimal_amts[tkn.token_name] = self._amt2dec(tkn_amt, tkn.token_decimal)
449
+ return decimal_amts
450
+
451
+
452
+ def get_price(self, base_tkn, opp_tkn, fee = False):
453
+
454
+ """ get_price
455
+
456
+ Get price of select token in the exchange pair
457
+
458
+ Parameters
459
+ -------
460
+ base_tkn : float
461
+ Base token request for price quote
462
+ opp_tkn : ERC20
463
+ Denomination token of price quote
464
+ """
465
+
466
+ assert self.tkn_group.get_token(base_tkn.token_name), 'Stableswap V1: TOKEN NOT PART OF GROUP'
467
+
468
+ base_tkn_index = self._get_tkn_index(base_tkn.token_name)
469
+ opp_tkn_index = self._get_tkn_index(opp_tkn.token_name)
470
+
471
+ return self.math_pool.dydx(base_tkn_index, opp_tkn_index, use_fee=fee)
472
+
473
+ def get_reserve(self, token):
474
+
475
+ """ get_reserve
476
+
477
+ Get reserve amount of select token in the pool
478
+
479
+ Parameters
480
+ -------
481
+ token : ERC20
482
+ ERC20 token
483
+ """
484
+
485
+ return self.tkn_reserves[token.token_name]
486
+
487
+
488
+
489
+