Skip to content

Commit 2b63283

Browse files
committed
Add Exchange SC wrapper
1 parent b581d16 commit 2b63283

File tree

1 file changed

+305
-0
lines changed

1 file changed

+305
-0
lines changed

sdk/contracts/ExchangeWrapper.py

Lines changed: 305 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
1+
import sys
2+
3+
from sdk.contracts.base_wrapper import BaseWrapper
4+
from sdk.registry import Registry
5+
6+
from web3 import Web3
7+
8+
9+
# TODO: test when other called SC wrappers will be written and callable
10+
class Exchange(BaseWrapper):
11+
"""
12+
Contract that allows to exchange StableToken for GoldToken and vice versa
13+
using a Constant Product Market Maker Model
14+
15+
Attributes:
16+
web3: Web3
17+
Web3 object
18+
registry: Registry
19+
Registry object
20+
address: str
21+
Contract's address
22+
abi: list
23+
Contract's ABI
24+
wallet: Wallet
25+
Wallet object to sign transactions
26+
"""
27+
28+
def __init__(self, web3: Web3, registry: Registry, address: str, abi: list, wallet: 'Wallet' = None):
29+
super().__init__(web3, registry, wallet=wallet)
30+
self.web3 = web3
31+
self.address = address
32+
self._contract = self.web3.eth.contract(self.address, abi=abi)
33+
self.__wallet = wallet
34+
35+
def spread(self) -> int:
36+
"""
37+
Query spread parameter
38+
39+
Returns:
40+
int
41+
Current spread charged on exchanges
42+
"""
43+
return self._contract.functions.spread().call()
44+
45+
def reserve_fraction(self) -> int:
46+
"""
47+
Query reserve fraction parameter
48+
49+
Returns:
50+
int
51+
Current fraction to commit to the gold bucket
52+
"""
53+
return self._contract.functions.reserveFraction().call()
54+
55+
def update_frequency(self) -> int:
56+
"""
57+
Query update frequency parameter
58+
59+
Returns:
60+
int
61+
The time period that needs to elapse between bucket
62+
updates
63+
"""
64+
return self._contract.functions.updateFrequency().call()
65+
66+
def minimum_reports(self) -> int:
67+
"""
68+
Query minimum reports parameter
69+
70+
Returns:
71+
int
72+
The minimum number of fresh reports that need to be
73+
present in the oracle to update buckets
74+
commit to the gold bucket
75+
"""
76+
return self._contract.functions.minimumReports().call()
77+
78+
def last_bucket_update(self) -> int:
79+
"""
80+
Query last bucket update
81+
82+
Returns:
83+
int
84+
The timestamp of the last time exchange buckets were updated.
85+
"""
86+
return self._contract.functions.lastBucketUpdate().call()
87+
88+
def get_buy_token_amount(self, sell_amount: int, sell_gold: bool) -> int:
89+
"""
90+
Returns the amount of buyToken a user would get for sellAmount of sellToken
91+
92+
Prameters:
93+
sell_amount: int
94+
The amount of sellToken the user is selling to the exchange
95+
sell_gold: bool
96+
`true` if gold is the sell token
97+
Returns:
98+
bool
99+
The corresponding buyToken amount
100+
"""
101+
if sell_amount == 0:
102+
return 0
103+
104+
return self._contract.functions.getBuyTokenAmount(sell_amount, sell_gold).call()
105+
106+
def get_sell_token_amount(self, buy_amount: int, sell_gold: bool) -> int:
107+
"""
108+
Returns the amount of sellToken a user would need to exchange to receive buyAmount of
109+
buyToken
110+
111+
Parameters:
112+
buy_amount: int
113+
The amount of buyToken the user would like to purchase
114+
sell_gold: bool
115+
`true` if gold is the sell token
116+
Returns:
117+
int
118+
The corresponding sellToken amount
119+
"""
120+
if buy_amount == 0:
121+
return 0
122+
123+
return self._contract.functions.getSellTokenAmount(buy_amount, sell_gold).call()
124+
125+
def get_buy_and_sell_buckets(self, sell_gold: bool) -> list:
126+
"""
127+
Returns the buy token and sell token bucket sizes, in order. The ratio of
128+
the two also represents the exchange rate between the two.
129+
130+
Parameters:
131+
sell_gold: bool
132+
`true` if gold is the sell token
133+
Returns: list
134+
"""
135+
return self._contract.functions.getBuyAndSellBuckets(sell_gold).call()
136+
137+
def exchange(self, sell_amount: int, min_buy_amount: int, sell_gold: bool) -> str:
138+
"""
139+
Exchanges sellAmount of sellToken in exchange for at least minBuyAmount of buyToken
140+
Requires the sellAmount to have been approved to the exchange
141+
142+
Parameters:
143+
sell_amount: int
144+
The amount of sellToken the user is selling to the exchange
145+
min_buy_amount: int
146+
The minimum amount of buyToken the user has to receive for this
147+
transaction to succeed
148+
sell_gold: bool
149+
`true` if gold is the sell token
150+
Returns:
151+
str
152+
Transaction hash
153+
"""
154+
func_call = self._contract.functions.exchange(sell_amount, min_buy_amount, sell_gold)
155+
156+
return self.__wallet.send_transaction(func_call)
157+
158+
def sell_gold(self, amount: int, min_usd_amount: int) -> str:
159+
"""
160+
Exchanges amount of CELO in exchange for at least minUsdAmount of cUsd
161+
Requires the amount to have been approved to the exchange
162+
163+
Parameters:
164+
amount: int
165+
The amount of CELO the user is selling to the exchange
166+
min_usd_amount: int
167+
The minimum amount of cUsd the user has to receive for this
168+
transaction to succeed
169+
Returns:
170+
str
171+
Transaction hash
172+
"""
173+
return self.exchange(amount, min_usd_amount, True)
174+
175+
def sell_dollar(self, amount: int, min_gold_amount: int) -> str:
176+
"""
177+
Exchanges amount of cUsd in exchange for at least minGoldAmount of CELO
178+
Requires the amount to have been approved to the exchange
179+
180+
Parameters:
181+
amount: int
182+
The amount of cUsd the user is selling to the exchange
183+
min_gold_amount: int
184+
The minimum amount of CELO the user has to receive for this
185+
transaction to succeed
186+
Returns:
187+
str
188+
Transaction hash
189+
"""
190+
return self.exchange(amount, min_gold_amount, False)
191+
192+
def quote_usd_sell(self, sell_amount: int) -> int:
193+
"""
194+
Returns the amount of CELO a user would get for sellAmount of cUsd
195+
196+
Parameters:
197+
sell_amount: int
198+
The amount of cUsd the user is selling to the exchange
199+
Returns:
200+
int
201+
The corresponding CELO amount
202+
"""
203+
return self.get_buy_token_amount(sell_amount, False)
204+
205+
def quote_gold_sell(self, sell_amount: int) -> int:
206+
"""
207+
Returns the amount of cUsd a user would get for sellAmount of CELO
208+
209+
Parameters:
210+
sell_amount: int
211+
The amount of CELO the user is selling to the exchange
212+
Returns:
213+
int
214+
The corresponding cUsd amount
215+
"""
216+
return self.get_buy_token_amount(sell_amount, True)
217+
218+
def quote_usd_buy(self, buy_amount: int) -> int:
219+
"""
220+
Returns the amount of CELO a user would need to exchange to receive buyAmount of
221+
cUsd
222+
223+
Parameters:
224+
buy_amount: int
225+
The amount of cUsd the user would like to purchase
226+
Returns:
227+
int
228+
The corresponding CELO amount
229+
"""
230+
return self.get_sell_token_amount(buy_amount, False)
231+
232+
def quote_gold_buy(self, buy_amount: int) -> int:
233+
"""
234+
Returns the amount of cUsd a user would need to exchange to receive buyAmount of
235+
CELO
236+
237+
Parameters:
238+
buy_amount: int
239+
The amount of CELO the user would like to purchase
240+
Returns:
241+
int
242+
The corresponding cUsd amount
243+
"""
244+
return self.get_sell_token_amount(buy_amount, True)
245+
246+
def get_config(self) -> dict:
247+
"""
248+
Returns the current configuration of the exchange contract
249+
"""
250+
spread = self.spread()
251+
reserve_fraction = self.reserve_fraction()
252+
update_frequency = self.update_frequency()
253+
minimum_reports = self.minimum_reports()
254+
last_bucket_update = self.last_bucket_update()
255+
256+
return {
257+
'spread': spread,
258+
'reserve_fraction': reserve_fraction,
259+
'update_frequency': update_frequency,
260+
'minimum_reports': minimum_reports,
261+
'last_bucket_update': last_bucket_update
262+
}
263+
264+
def get_exchange_rate(self, buy_amount: int, sell_gold: bool) -> float:
265+
"""
266+
Returns the exchange rate estimated at buyAmount
267+
268+
Parameters:
269+
buy_amount: int
270+
The amount of buyToken in wei to estimate the exchange rate at
271+
sell_gold: bool
272+
`true` if gold is the sell token
273+
Returns:
274+
float
275+
The exchange rate (number of sellTokens received for one buyToken)
276+
"""
277+
taker_amount = self.get_buy_token_amount(buy_amount, sell_gold)
278+
279+
return buy_amount / taker_amount
280+
281+
def get_usd_exchange_rate(self, buy_amount: int) -> float:
282+
"""
283+
Returns the exchange rate for cUsd estimated at the buyAmount
284+
285+
Parameters:
286+
buy_amount: int
287+
The amount of cUsd in wei to estimate the exchange rate at
288+
Returns:
289+
float
290+
The exchange rate (number of CELO received for one cUsd)
291+
"""
292+
return self.get_exchange_rate(buy_amount, False)
293+
294+
def get_gold_exchange_rate(self, buy_amount: int) -> float:
295+
"""
296+
Returns the exchange rate for CELO estimated at the buyAmount
297+
298+
Parameters:
299+
buy_amount: int
300+
The amount of CELO in wei to estimate the exchange rate at
301+
Returns:
302+
float
303+
The exchange rate (number of CELO received for one cUsd)
304+
"""
305+
return self.get_exchange_rate(buy_amount, True)

0 commit comments

Comments
 (0)