Skip to content

Commit 9d34a25

Browse files
committed
Use new quote API for cowswap oracle
- markets API was deprecated
1 parent 13a4365 commit 9d34a25

File tree

4 files changed

+57
-16
lines changed

4 files changed

+57
-16
lines changed

gnosis/eth/oracles/cowswap.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,14 @@ def get_price(
5656
result = self.api.get_estimated_amount(
5757
token_address_1, token_address_2, OrderKind.SELL, 10**token_1_decimals
5858
)
59-
if "amount" in result:
59+
if "buyAmount" in result:
6060
# Decimals needs to be adjusted
6161
token_2_decimals = get_decimals(token_address_2, self.ethereum_client)
62-
return float(result["amount"]) / 10**token_2_decimals
62+
return (
63+
float(result["buyAmount"])
64+
/ result["sellAmount"]
65+
* 10 ** (token_1_decimals - token_2_decimals)
66+
)
6367

6468
exception = None
6569
except IOError as exc:

gnosis/eth/tests/oracles/test_cowswap.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ def test_get_price(self):
5555
)
5656
self.assertAlmostEqual(price, 1.0, delta=0.5)
5757

58-
with mock.patch.object(Session, "get", side_effect=IOError("Connection Error")):
58+
with mock.patch.object(
59+
Session, "post", side_effect=IOError("Connection Error")
60+
):
5961
with self.assertRaisesMessage(
6062
CannotGetPriceFromOracle,
6163
f"Cannot get price from CowSwap "

gnosis/protocol/gnosis_protocol_api.py

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from gnosis.eth import EthereumNetwork, EthereumNetworkNotSupported
1111
from gnosis.eth.eip712 import eip712_encode_hash
1212

13+
from ..eth.constants import NULL_ADDRESS
1314
from .order import Order, OrderKind
1415

1516

@@ -27,8 +28,8 @@ class TradeResponse(TypedDict):
2728

2829

2930
class AmountResponse(TypedDict):
30-
amount: str
31-
token: AnyAddress
31+
sellAmount: int
32+
buyAmount: int
3233

3334

3435
class ErrorResponse(TypedDict):
@@ -77,13 +78,15 @@ def weth_address(self) -> ChecksumAddress:
7778
else: # XDAI
7879
return ChecksumAddress("0x6A023CCd1ff6F2045C3309768eAd9E68F978f6e1")
7980

80-
def get_fee(self, order: Order, from_address: ChecksumAddress) -> int:
81+
def get_quote(
82+
self, order: Order, from_address: ChecksumAddress
83+
) -> Union[Dict[str, Any], ErrorResponse]:
8184
url = self.base_url + "quote"
8285
data_json = {
8386
"sellToken": order.sellToken.lower(),
8487
"buyToken": order.buyToken.lower(),
8588
"sellAmountBeforeFee": str(order.sellAmount),
86-
"validTo": order.validTo,
89+
# "validTo": order.validTo,
8790
"appData": HexBytes(order.appData).hex()
8891
if isinstance(order.appData, bytes)
8992
else order.appData,
@@ -96,10 +99,20 @@ def get_fee(self, order: Order, from_address: ChecksumAddress) -> int:
9699
}
97100
r = self.http_session.post(url, json=data_json)
98101
if r.ok:
99-
return int(r.json()["quote"]["feeAmount"])
102+
return r.json()
100103
else:
101104
return ErrorResponse(r.json())
102105

106+
def get_fee(
107+
self, order: Order, from_address: ChecksumAddress
108+
) -> Union[int, ErrorResponse]:
109+
quote = self.get_quote(order, from_address)
110+
111+
if "quote" in quote:
112+
return int(quote["quote"]["feeAmount"])
113+
else:
114+
return quote
115+
103116
def place_order(
104117
self, order: Order, private_key: HexStr
105118
) -> Union[HexStr, ErrorResponse]:
@@ -193,14 +206,36 @@ def get_estimated_amount(
193206
base_token: ChecksumAddress,
194207
quote_token: ChecksumAddress,
195208
kind: OrderKind,
196-
amount: int,
209+
amount_wei: int,
197210
) -> Union[AmountResponse, ErrorResponse]:
198211
"""
199-
The estimated amount in quote token for either buying or selling amount of baseToken.
212+
213+
:param base_token:
214+
:param quote_token:
215+
:param kind:
216+
:param amount_wei:
217+
:return: Both `sellAmount` and `buyAmount` as they can be adjusted by CowSwap API
200218
"""
201-
url = self.base_url + f"markets/{base_token}-{quote_token}/{kind.name}/{amount}"
202-
r = self.http_session.get(url)
203-
if r.ok:
204-
return AmountResponse(r.json())
219+
order = Order(
220+
sellToken=base_token,
221+
buyToken=quote_token,
222+
receiver=NULL_ADDRESS,
223+
sellAmount=amount_wei * 10 if kind == OrderKind.SELL else 0,
224+
buyAmount=amount_wei * 10 if kind == OrderKind.BUY else 0,
225+
validTo=0, # Valid for 1 hour
226+
appData="0x0000000000000000000000000000000000000000000000000000000000000000",
227+
feeAmount=0,
228+
kind=kind.name.lower(), # `sell` or `buy`
229+
partiallyFillable=False,
230+
sellTokenBalance="erc20", # `erc20`, `external` or `internal`
231+
buyTokenBalance="erc20", # `erc20` or `internal`
232+
)
233+
234+
quote = self.get_quote(order, NULL_ADDRESS)
235+
if "quote" in quote:
236+
return {
237+
"buyAmount": int(quote["quote"]["buyAmount"]),
238+
"sellAmount": int(quote["quote"]["sellAmount"]),
239+
}
205240
else:
206-
return ErrorResponse(r.json())
241+
return quote

gnosis/protocol/tests/test_gnosis_protocol_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def test_get_estimated_amount(self):
6363
OrderKind.SELL,
6464
int(1e18),
6565
)
66-
amount = int(response["amount"]) / 1e18
66+
amount = float(response["buyAmount"]) / response["sellAmount"]
6767
self.assertGreater(amount, 0)
6868
self.assertLess(amount, 1)
6969

0 commit comments

Comments
 (0)