From 6dabdf157a1909ade63ce7921c7cf322ca0c704e Mon Sep 17 00:00:00 2001 From: Rodrigo <95635797+poly-rodr@users.noreply.github.com> Date: Tue, 11 Apr 2023 12:18:21 -0300 Subject: [PATCH 1/2] feat/ adding support for all the possible tick sizes Adding support for: - `0.1` - `0.01` - already supported - `0.001` - `0.0001` ### Example ```python chain_id = MUMBAI client = ClobClient(host, key=key, chain_id=chain_id, creds=creds) # Create and sign a limit order buying 100 YES tokens for 0.0005 each order_args = OrderArgs( price=0.0005, size=20, side=BUY, token_id="16678291189211314787145083999015737376658799626183230671758641503291735614088", ) signed_order = client.create_order(order_args) resp = client.post_order(signed_order) print(resp) print("Done!") ``` --- examples/get_order.py | 4 +- examples/order.py | 6 +- py_clob_client/client.py | 15 +- py_clob_client/clob_types.py | 14 + py_clob_client/endpoints.py | 1 + py_clob_client/order_builder/builder.py | 43 +- setup.py | 2 +- tests/order_builder/test_builder.py | 633 ++++++++++++++++++++++-- tests/test_utilities.py | 512 ++++++++++++++++++- 9 files changed, 1173 insertions(+), 57 deletions(-) diff --git a/examples/get_order.py b/examples/get_order.py index 332f7d9..800773f 100644 --- a/examples/get_order.py +++ b/examples/get_order.py @@ -19,7 +19,9 @@ def main(): chain_id = MUMBAI client = ClobClient(host, key=key, chain_id=chain_id, creds=creds) - resp = client.get_order("0xf5667d8509bdc78ac43676fe2c980da1365c471ee92153820c89c488fc15d539") + resp = client.get_order( + "0xf5667d8509bdc78ac43676fe2c980da1365c471ee92153820c89c488fc15d539" + ) print(resp) print("Done!") diff --git a/examples/order.py b/examples/order.py index f5f7a1d..6f314d5 100644 --- a/examples/order.py +++ b/examples/order.py @@ -22,10 +22,10 @@ def main(): chain_id = MUMBAI client = ClobClient(host, key=key, chain_id=chain_id, creds=creds) - # Create and sign a limit order buying 100 YES tokens for 0.50c each + # Create and sign a limit order buying 100 YES tokens for 0.0005 each order_args = OrderArgs( - price=0.50, - size=100.0, + price=0.0005, + size=20, side=BUY, token_id="16678291189211314787145083999015737376658799626183230671758641503291735614088", ) diff --git a/py_clob_client/client.py b/py_clob_client/client.py index c1ca740..cb933ea 100644 --- a/py_clob_client/client.py +++ b/py_clob_client/client.py @@ -28,6 +28,7 @@ DROP_TRADE_NOTIFICATIONS, GET_BALANCE_ALLOWANCE, IS_ORDER_SCORING, + GET_TICK_SIZE, ) from .clob_types import ( ApiCreds, @@ -38,6 +39,7 @@ OrderBookSummary, BalanceAllowanceParams, OrderScoringParams, + TickSize, ) from .exceptions import PolyException from .http_helpers.helpers import ( @@ -90,6 +92,7 @@ def __init__( self.builder = OrderBuilder( self.signer, sig_type=signature_type, funder=funder ) + self.__tick_sizes = {} self.logger = logging.getLogger(self.__class__.__name__) def get_address(self): @@ -225,6 +228,15 @@ def get_price(self, token_id, side): """ return get("{}{}?token_id={}&side={}".format(self.host, PRICE, token_id, side)) + def get_tick_size(self, token_id: str) -> TickSize: + if token_id in self.__tick_sizes: + return self.__tick_sizes[token_id] + + result = get("{}{}?token_id={}".format(self.host, GET_TICK_SIZE, token_id)) + self.__tick_sizes[token_id] = result["minimum_tick_size"] + + return self.__tick_sizes[token_id] + def create_order(self, order_args: OrderArgs): """ Creates and signs an order @@ -232,7 +244,8 @@ def create_order(self, order_args: OrderArgs): """ self.assert_level_2_auth() - return self.builder.create_order(order_args) + tick_size = self.get_tick_size(order_args.token_id) + return self.builder.create_order(order_args, tick_size) def post_order(self, order, orderType: OrderType = OrderType.GTC): """ diff --git a/py_clob_client/clob_types.py b/py_clob_client/clob_types.py index 5eba231..ab69ffd 100644 --- a/py_clob_client/clob_types.py +++ b/py_clob_client/clob_types.py @@ -2,6 +2,7 @@ from typing import Any from dataclasses import dataclass, asdict from json import dumps +from typing import Literal from .constants import ZERO_ADDRESS @@ -132,3 +133,16 @@ class OrderType(enumerate): @dataclass class OrderScoringParams: orderId: str + + +TickSize = Literal["0.1", "0.01", "0.001", "0.0001"] + + +@dataclass +class RoundConfig: + price: float + size: float + amount: float + + +TickSizes: dict[str, TickSize] diff --git a/py_clob_client/endpoints.py b/py_clob_client/endpoints.py index c67b953..a576904 100644 --- a/py_clob_client/endpoints.py +++ b/py_clob_client/endpoints.py @@ -19,3 +19,4 @@ DROP_TRADE_NOTIFICATIONS = "/drop-trade-notifications" GET_BALANCE_ALLOWANCE = "/balance-allowance" IS_ORDER_SCORING = "/order-scoring" +GET_TICK_SIZE = "/tick-size" diff --git a/py_clob_client/order_builder/builder.py b/py_clob_client/order_builder/builder.py index beaa0b7..e161894 100644 --- a/py_clob_client/order_builder/builder.py +++ b/py_clob_client/order_builder/builder.py @@ -18,7 +18,15 @@ from .constants import BUY, SELL from ..signer import Signer -from ..clob_types import OrderArgs +from ..clob_types import OrderArgs, TickSize, RoundConfig +from typing import Tuple + +ROUNDING_CONFIG: Tuple[TickSize, RoundConfig] = { + "0.1": RoundConfig(price=1, size=2, amount=3), + "0.01": RoundConfig(price=2, size=2, amount=4), + "0.001": RoundConfig(price=3, size=2, amount=5), + "0.0001": RoundConfig(price=4, size=2, amount=6), +} class OrderBuilder: @@ -40,30 +48,32 @@ def __init__(self, signer: Signer, sig_type=None, funder=None): def _get_contract_config(self, chain_id: int): return get_contract_config(chain_id) - def get_order_amounts(self, side: str, size: float, price: float): - raw_price = round_normal(price, 2) + def get_order_amounts( + self, side: str, size: float, price: float, round_config: RoundConfig + ): + raw_price = round_normal(price, round_config.price) if side == BUY: - raw_taker_amt = round_down(size, 2) + raw_taker_amt = round_down(size, round_config.size) raw_maker_amt = raw_taker_amt * raw_price - if decimal_places(raw_maker_amt) > 4: - raw_maker_amt = round_up(raw_maker_amt, 8) - if decimal_places(raw_maker_amt) > 4: - raw_maker_amt = round_down(raw_maker_amt, 4) + if decimal_places(raw_maker_amt) > round_config.amount: + raw_maker_amt = round_up(raw_maker_amt, round_config.amount + 4) + if decimal_places(raw_maker_amt) > round_config.amount: + raw_maker_amt = round_down(raw_maker_amt, round_config.amount) maker_amount = to_token_decimals(raw_maker_amt) taker_amount = to_token_decimals(raw_taker_amt) return UtilsBuy, maker_amount, taker_amount elif side == SELL: - raw_maker_amt = round_down(size, 2) + raw_maker_amt = round_down(size, round_config.size) raw_taker_amt = raw_maker_amt * raw_price - if decimal_places(raw_taker_amt) > 4: - raw_taker_amt = round_up(raw_taker_amt, 8) - if decimal_places(raw_taker_amt) > 4: - raw_taker_amt = round_down(raw_taker_amt, 4) + if decimal_places(raw_taker_amt) > round_config.amount: + raw_taker_amt = round_up(raw_taker_amt, round_config.amount + 4) + if decimal_places(raw_taker_amt) > round_config.amount: + raw_taker_amt = round_down(raw_taker_amt, round_config.amount) maker_amount = to_token_decimals(raw_maker_amt) taker_amount = to_token_decimals(raw_taker_amt) @@ -72,12 +82,15 @@ def get_order_amounts(self, side: str, size: float, price: float): else: raise ValueError(f"order_args.side must be '{BUY}' or '{SELL}'") - def create_order(self, order_args: OrderArgs) -> SignedOrder: + def create_order(self, order_args: OrderArgs, tick_size: TickSize) -> SignedOrder: """ Creates and signs an order """ side, maker_amount, taker_amount = self.get_order_amounts( - order_args.side, order_args.size, order_args.price + order_args.side, + order_args.size, + order_args.price, + ROUNDING_CONFIG[tick_size], ) data = OrderData( diff --git a/setup.py b/setup.py index 3c1a75c..43d95b9 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name="py_clob_client", - version="0.5.0", + version="0.6.0", author="Polymarket Engineering", author_email="engineering@polymarket.com", maintainer="Polymarket Engineering", diff --git a/tests/order_builder/test_builder.py b/tests/order_builder/test_builder.py index 30736f6..6fcb675 100644 --- a/tests/order_builder/test_builder.py +++ b/tests/order_builder/test_builder.py @@ -5,8 +5,8 @@ from py_clob_client.order_builder.constants import BUY, SELL from py_clob_client.signer import Signer -from py_clob_client.order_builder.builder import OrderBuilder -from py_clob_client.order_builder.helpers import decimal_places +from py_clob_client.order_builder.builder import OrderBuilder, ROUNDING_CONFIG +from py_clob_client.order_builder.helpers import decimal_places, round_normal from py_order_utils.model import POLY_GNOSIS_SAFE, EOA # publicly known private key @@ -16,37 +16,181 @@ class TestOrderBuilder(TestCase): - def test_get_order_amounts_buy(self): + def test_get_order_amounts_buy_0_1(self): builder = OrderBuilder(signer) - delta = 0.01 + delta_price = 0.1 + delta_size = 0.01 + size = 0.01 + while size <= 1000: + price = 0.1 + while price <= 1: + side, maker, taker = builder.get_order_amounts( + BUY, size, price, ROUNDING_CONFIG["0.1"] + ) + self.assertEqual(side, 0) + self.assertEqual(decimal_places(maker), 0) + self.assertEqual(decimal_places(taker), 0) + self.assertGreaterEqual( + round_normal(maker / taker, 2), round_normal(price, 2) + ) + price = price + delta_price + + size = size + delta_size + + def test_get_order_amounts_buy_0_01(self): + builder = OrderBuilder(signer) + + delta_price = 0.01 + delta_size = 0.01 size = 0.01 while size <= 100: price = 0.01 while price <= 1: - side, maker, taker = builder.get_order_amounts(BUY, size, price) + side, maker, taker = builder.get_order_amounts( + BUY, size, price, ROUNDING_CONFIG["0.01"] + ) + self.assertEqual(side, 0) + self.assertEqual(decimal_places(maker), 0) + self.assertEqual(decimal_places(taker), 0) + self.assertGreaterEqual( + round_normal(maker / taker, 4), round_normal(price, 4) + ) + price = price + delta_price + + size = size + delta_size + + def test_get_order_amounts_buy_0_001(self): + builder = OrderBuilder(signer) + + delta_price = 0.001 + delta_size = 0.01 + size = 0.01 + while size <= 10: + price = 0.001 + while price <= 1: + side, maker, taker = builder.get_order_amounts( + BUY, size, price, ROUNDING_CONFIG["0.001"] + ) + self.assertEqual(side, 0) + self.assertEqual(decimal_places(maker), 0) + self.assertEqual(decimal_places(taker), 0) + self.assertGreaterEqual( + round_normal(maker / taker, 6), round_normal(price, 6) + ) + price = price + delta_price + + size = size + delta_size + + def test_get_order_amounts_buy_0_0001(self): + builder = OrderBuilder(signer) + + delta_price = 0.0001 + delta_size = 0.01 + size = 0.01 + while size <= 1: + price = 0.0001 + while price <= 1: + side, maker, taker = builder.get_order_amounts( + BUY, size, price, ROUNDING_CONFIG["0.0001"] + ) self.assertEqual(side, 0) self.assertEqual(decimal_places(maker), 0) self.assertEqual(decimal_places(taker), 0) - price = price + delta + self.assertGreaterEqual( + round_normal(maker / taker, 8), round_normal(price, 8) + ) + price = price + delta_price - size = size + delta + size = size + delta_size - def test_get_order_amounts_sell(self): + def test_get_order_amounts_sell_0_1(self): builder = OrderBuilder(signer) - delta = 0.01 + delta_price = 0.1 + delta_size = 0.01 + size = 0.01 + while size <= 1000: + price = 0.1 + while price <= 1: + side, maker, taker = builder.get_order_amounts( + SELL, size, price, ROUNDING_CONFIG["0.1"] + ) + self.assertEqual(side, 1) + self.assertEqual(decimal_places(maker), 0) + self.assertEqual(decimal_places(taker), 0) + self.assertGreaterEqual( + round_normal(taker / maker, 2), round_normal(price, 2) + ) + price = price + delta_price + + size = size + delta_size + + def test_get_order_amounts_sell_0_01(self): + builder = OrderBuilder(signer) + + delta_price = 0.01 + delta_size = 0.01 size = 0.01 while size <= 100: price = 0.01 while price <= 1: - side, maker, taker = builder.get_order_amounts(SELL, size, price) + side, maker, taker = builder.get_order_amounts( + SELL, size, price, ROUNDING_CONFIG["0.01"] + ) + self.assertEqual(side, 1) + self.assertEqual(decimal_places(maker), 0) + self.assertEqual(decimal_places(taker), 0) + self.assertGreaterEqual( + round_normal(taker / maker, 4), round_normal(price, 4) + ) + price = price + delta_price + + size = size + delta_size + + def test_get_order_amounts_sell_0_001(self): + builder = OrderBuilder(signer) + + delta_price = 0.001 + delta_size = 0.01 + size = 0.01 + while size <= 10: + price = 0.001 + while price <= 1: + side, maker, taker = builder.get_order_amounts( + SELL, size, price, ROUNDING_CONFIG["0.001"] + ) self.assertEqual(side, 1) self.assertEqual(decimal_places(maker), 0) self.assertEqual(decimal_places(taker), 0) - price = price + delta + self.assertGreaterEqual( + round_normal(taker / maker, 6), round_normal(price, 6) + ) + price = price + delta_price + + size = size + delta_size - size = size + delta + def test_get_order_amounts_sell_0_0001(self): + builder = OrderBuilder(signer) + + delta_price = 0.0001 + delta_size = 0.01 + size = 0.01 + while size <= 1: + price = 0.0001 + while price <= 1: + side, maker, taker = builder.get_order_amounts( + SELL, size, price, ROUNDING_CONFIG["0.0001"] + ) + self.assertEqual(side, 1) + self.assertEqual(decimal_places(maker), 0) + self.assertEqual(decimal_places(taker), 0) + self.assertGreaterEqual( + round_normal(taker / maker, 8), round_normal(price, 8) + ) + price = price + delta_price + + size = size + delta_size def test_create_order_decimal_accuracy(self): builder = OrderBuilder(signer) @@ -58,7 +202,8 @@ def test_create_order_decimal_accuracy(self): price=0.24, size=15, side=BUY, - ) + ), + tick_size="0.01", ) self.assertEqual( signed_order.order["makerAmount"], @@ -76,7 +221,8 @@ def test_create_order_decimal_accuracy(self): price=0.24, size=15, side=SELL, - ) + ), + tick_size="0.01", ) self.assertEqual( signed_order.order["makerAmount"], @@ -94,7 +240,8 @@ def test_create_order_decimal_accuracy(self): price=0.82, size=101, side=BUY, - ) + ), + tick_size="0.01", ) self.assertEqual( signed_order.order["makerAmount"], @@ -112,7 +259,8 @@ def test_create_order_decimal_accuracy(self): price=0.82, size=101, side=SELL, - ) + ), + tick_size="0.01", ) self.assertEqual( signed_order.order["makerAmount"], @@ -130,7 +278,8 @@ def test_create_order_decimal_accuracy(self): price=0.78, size=12.8205, side=BUY, - ) + ), + tick_size="0.01", ) self.assertEqual( signed_order.order["makerAmount"], @@ -148,7 +297,8 @@ def test_create_order_decimal_accuracy(self): price=0.78, size=12.8205, side=SELL, - ) + ), + tick_size="0.01", ) self.assertEqual( signed_order.order["makerAmount"], @@ -166,7 +316,8 @@ def test_create_order_decimal_accuracy(self): price=0.39, size=2435.89, side=SELL, - ) + ), + tick_size="0.01", ) self.assertEqual( signed_order.order["makerAmount"], @@ -184,7 +335,8 @@ def test_create_order_decimal_accuracy(self): price=0.43, size=19.1, side=SELL, - ) + ), + tick_size="0.01", ) self.assertEqual( signed_order.order["makerAmount"], @@ -202,7 +354,8 @@ def test_create_order_decimal_accuracy(self): price=0.58, size=18233.33, side=BUY, - ) + ), + tick_size="0.01", ) self.assertEqual( signed_order.order["makerAmount"], @@ -216,7 +369,76 @@ def test_create_order_decimal_accuracy(self): signed_order.order["makerAmount"] / signed_order.order["takerAmount"], 0.58 ) - def test_create_order_buy(self): + def test_create_order_buy_0_1(self): + builder = OrderBuilder(signer) + + signed_order = builder.create_order( + order_args=OrderArgs( + token_id="123", + price=0.5, + size=21.04, + side=BUY, + fee_rate_bps=111, + nonce=123, + expiration=50000, + ), + tick_size="0.1", + ) + + self.assertTrue(isinstance(signed_order.order["salt"], int)) + self.assertIsNotNone(signed_order) + self.assertEqual( + signed_order.order["maker"], + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + ) + self.assertEqual( + signed_order.order["signer"], + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + ) + self.assertEqual( + signed_order.order["taker"], + "0x0000000000000000000000000000000000000000", + ) + self.assertEqual( + signed_order.order["tokenId"], + 123, + ) + self.assertEqual( + signed_order.order["makerAmount"], + 10520000, + ) + self.assertEqual( + signed_order.order["takerAmount"], + 21040000, + ) + self.assertEqual( + signed_order.order["side"], + 0, + ) + self.assertEqual( + signed_order.order["expiration"], + 50000, + ) + self.assertEqual( + signed_order.order["nonce"], + 123, + ) + self.assertEqual( + signed_order.order["feeRateBps"], + 111, + ) + self.assertEqual( + signed_order.order["signatureType"], + EOA, + ) + self.assertIsNotNone(signed_order.signature) + self.assertEqual( + float(signed_order.order["makerAmount"]) + / float(signed_order.order["takerAmount"]), + 0.5, + ) + + def test_create_order_buy_0_01(self): builder = OrderBuilder(signer) signed_order = builder.create_order( @@ -228,7 +450,8 @@ def test_create_order_buy(self): fee_rate_bps=111, nonce=123, expiration=50000, - ) + ), + tick_size="0.01", ) self.assertTrue(isinstance(signed_order.order["salt"], int)) @@ -279,12 +502,219 @@ def test_create_order_buy(self): ) self.assertIsNotNone(signed_order.signature) self.assertEqual( - int(signed_order.order["makerAmount"]) - / int(signed_order.order["takerAmount"]), + float(signed_order.order["makerAmount"]) + / float(signed_order.order["takerAmount"]), 0.56, ) - def test_create_order_sell(self): + def test_create_order_buy_0_001(self): + builder = OrderBuilder(signer) + + signed_order = builder.create_order( + order_args=OrderArgs( + token_id="123", + price=0.056, + size=21.04, + side=BUY, + fee_rate_bps=111, + nonce=123, + expiration=50000, + ), + tick_size="0.001", + ) + + self.assertTrue(isinstance(signed_order.order["salt"], int)) + self.assertIsNotNone(signed_order) + self.assertEqual( + signed_order.order["maker"], + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + ) + self.assertEqual( + signed_order.order["signer"], + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + ) + self.assertEqual( + signed_order.order["taker"], + "0x0000000000000000000000000000000000000000", + ) + self.assertEqual( + signed_order.order["tokenId"], + 123, + ) + self.assertEqual( + signed_order.order["makerAmount"], + 1178240, + ) + self.assertEqual( + signed_order.order["takerAmount"], + 21040000, + ) + self.assertEqual( + signed_order.order["side"], + 0, + ) + self.assertEqual( + signed_order.order["expiration"], + 50000, + ) + self.assertEqual( + signed_order.order["nonce"], + 123, + ) + self.assertEqual( + signed_order.order["feeRateBps"], + 111, + ) + self.assertEqual( + signed_order.order["signatureType"], + EOA, + ) + self.assertIsNotNone(signed_order.signature) + self.assertEqual( + float(signed_order.order["makerAmount"]) + / float(signed_order.order["takerAmount"]), + 0.056, + ) + + def test_create_order_buy_0_001(self): + builder = OrderBuilder(signer) + + signed_order = builder.create_order( + order_args=OrderArgs( + token_id="123", + price=0.0056, + size=21.04, + side=BUY, + fee_rate_bps=111, + nonce=123, + expiration=50000, + ), + tick_size="0.0001", + ) + + self.assertTrue(isinstance(signed_order.order["salt"], int)) + self.assertIsNotNone(signed_order) + self.assertEqual( + signed_order.order["maker"], + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + ) + self.assertEqual( + signed_order.order["signer"], + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + ) + self.assertEqual( + signed_order.order["taker"], + "0x0000000000000000000000000000000000000000", + ) + self.assertEqual( + signed_order.order["tokenId"], + 123, + ) + self.assertEqual( + signed_order.order["makerAmount"], + 117824, + ) + self.assertEqual( + signed_order.order["takerAmount"], + 21040000, + ) + self.assertEqual( + signed_order.order["side"], + 0, + ) + self.assertEqual( + signed_order.order["expiration"], + 50000, + ) + self.assertEqual( + signed_order.order["nonce"], + 123, + ) + self.assertEqual( + signed_order.order["feeRateBps"], + 111, + ) + self.assertEqual( + signed_order.order["signatureType"], + EOA, + ) + self.assertIsNotNone(signed_order.signature) + self.assertEqual( + float(signed_order.order["makerAmount"]) + / float(signed_order.order["takerAmount"]), + 0.0056, + ) + + def test_create_order_sell_0_1(self): + builder = OrderBuilder(signer, sig_type=POLY_GNOSIS_SAFE) + + signed_order = builder.create_order( + order_args=OrderArgs( + token_id="123", + price=0.5, + size=21.04, + side=SELL, + fee_rate_bps=111, + nonce=123, + expiration=50000, + ), + tick_size="0.1", + ) + + self.assertTrue(isinstance(signed_order.order["salt"], int)) + self.assertIsNotNone(signed_order) + self.assertEqual( + signed_order.order["maker"], + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + ) + self.assertEqual( + signed_order.order["signer"], + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + ) + self.assertEqual( + signed_order.order["taker"], + "0x0000000000000000000000000000000000000000", + ) + self.assertEqual( + signed_order.order["tokenId"], + 123, + ) + self.assertEqual( + signed_order.order["makerAmount"], + 21040000, + ) + self.assertEqual( + signed_order.order["takerAmount"], + 10520000, + ) + self.assertEqual( + signed_order.order["side"], + 1, + ) + self.assertEqual( + signed_order.order["expiration"], + 50000, + ) + self.assertEqual( + signed_order.order["nonce"], + 123, + ) + self.assertEqual( + signed_order.order["feeRateBps"], + 111, + ) + self.assertEqual( + signed_order.order["signatureType"], + POLY_GNOSIS_SAFE, + ) + self.assertIsNotNone(signed_order.signature) + self.assertEqual( + float(signed_order.order["takerAmount"]) + / float(signed_order.order["makerAmount"]), + 0.5, + ) + + def test_create_order_sell_0_01(self): builder = OrderBuilder(signer, sig_type=POLY_GNOSIS_SAFE) signed_order = builder.create_order( @@ -296,7 +726,8 @@ def test_create_order_sell(self): fee_rate_bps=111, nonce=123, expiration=50000, - ) + ), + tick_size="0.01", ) self.assertTrue(isinstance(signed_order.order["salt"], int)) @@ -347,11 +778,149 @@ def test_create_order_sell(self): ) self.assertIsNotNone(signed_order.signature) self.assertEqual( - int(signed_order.order["takerAmount"]) - / int(signed_order.order["makerAmount"]), + float(signed_order.order["takerAmount"]) + / float(signed_order.order["makerAmount"]), 0.56, ) + def test_create_order_sell_0_001(self): + builder = OrderBuilder(signer, sig_type=POLY_GNOSIS_SAFE) + + signed_order = builder.create_order( + order_args=OrderArgs( + token_id="123", + price=0.056, + size=21.04, + side=SELL, + fee_rate_bps=111, + nonce=123, + expiration=50000, + ), + tick_size="0.001", + ) + + self.assertTrue(isinstance(signed_order.order["salt"], int)) + self.assertIsNotNone(signed_order) + self.assertEqual( + signed_order.order["maker"], + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + ) + self.assertEqual( + signed_order.order["signer"], + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + ) + self.assertEqual( + signed_order.order["taker"], + "0x0000000000000000000000000000000000000000", + ) + self.assertEqual( + signed_order.order["tokenId"], + 123, + ) + self.assertEqual( + signed_order.order["makerAmount"], + 21040000, + ) + self.assertEqual( + signed_order.order["takerAmount"], + 1178240, + ) + self.assertEqual( + signed_order.order["side"], + 1, + ) + self.assertEqual( + signed_order.order["expiration"], + 50000, + ) + self.assertEqual( + signed_order.order["nonce"], + 123, + ) + self.assertEqual( + signed_order.order["feeRateBps"], + 111, + ) + self.assertEqual( + signed_order.order["signatureType"], + POLY_GNOSIS_SAFE, + ) + self.assertIsNotNone(signed_order.signature) + self.assertEqual( + float(signed_order.order["takerAmount"]) + / float(signed_order.order["makerAmount"]), + 0.056, + ) + + def test_create_order_sell_0_0001(self): + builder = OrderBuilder(signer, sig_type=POLY_GNOSIS_SAFE) + + signed_order = builder.create_order( + order_args=OrderArgs( + token_id="123", + price=0.0056, + size=21.04, + side=SELL, + fee_rate_bps=111, + nonce=123, + expiration=50000, + ), + tick_size="0.0001", + ) + + self.assertTrue(isinstance(signed_order.order["salt"], int)) + self.assertIsNotNone(signed_order) + self.assertEqual( + signed_order.order["maker"], + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + ) + self.assertEqual( + signed_order.order["signer"], + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + ) + self.assertEqual( + signed_order.order["taker"], + "0x0000000000000000000000000000000000000000", + ) + self.assertEqual( + signed_order.order["tokenId"], + 123, + ) + self.assertEqual( + signed_order.order["makerAmount"], + 21040000, + ) + self.assertEqual( + signed_order.order["takerAmount"], + 117824, + ) + self.assertEqual( + signed_order.order["side"], + 1, + ) + self.assertEqual( + signed_order.order["expiration"], + 50000, + ) + self.assertEqual( + signed_order.order["nonce"], + 123, + ) + self.assertEqual( + signed_order.order["feeRateBps"], + 111, + ) + self.assertEqual( + signed_order.order["signatureType"], + POLY_GNOSIS_SAFE, + ) + self.assertIsNotNone(signed_order.signature) + self.assertEqual( + float(signed_order.order["takerAmount"]) + / float(signed_order.order["makerAmount"]), + 0.0056, + ) + def test_dict_order_buy(self): builder = OrderBuilder(signer) @@ -364,7 +933,8 @@ def test_dict_order_buy(self): fee_rate_bps=111, nonce=123, expiration=50000, - ) + ), + tick_size="0.01", ) self.assertIsNotNone(signed_order) @@ -431,7 +1001,8 @@ def test_dict_order_sell(self): fee_rate_bps=111, nonce=123, expiration=50000, - ) + ), + tick_size="0.01", ) self.assertIsNotNone(signed_order) diff --git a/tests/test_utilities.py b/tests/test_utilities.py index c49c26b..4d1c6de 100644 --- a/tests/test_utilities.py +++ b/tests/test_utilities.py @@ -151,7 +151,7 @@ def test_generate_orderbook_summary_hash(self): "7f81a35a09e1933a96b05edb51ac4be4a6163146", ) - def test_order_to_json(self): + def test_order_to_json_0_1(self): # publicly known private key private_key = ( "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" @@ -169,7 +169,8 @@ def test_order_to_json(self): price=0.5, size=100, side=BUY, - ) + ), + tick_size="0.1", ), owner=owner, orderType=OrderType.GTC, @@ -207,7 +208,8 @@ def test_order_to_json(self): price=0.5, size=100, side=SELL, - ) + ), + tick_size="0.1", ), owner=owner, orderType=OrderType.GTC, @@ -245,7 +247,8 @@ def test_order_to_json(self): price=0.5, size=100, side=BUY, - ) + ), + tick_size="0.1", ), owner=owner, orderType=OrderType.GTD, @@ -283,7 +286,8 @@ def test_order_to_json(self): price=0.5, size=100, side=SELL, - ) + ), + tick_size="0.1", ), owner=owner, orderType=OrderType.GTD, @@ -312,3 +316,501 @@ def test_order_to_json(self): self.assertEqual(json_order["order"]["side"], "SELL") self.assertEqual(json_order["order"]["signatureType"], 0) self.assertIsNotNone(json_order["order"]["signature"]) + + def test_order_to_json_0_01(self): + # publicly known private key + private_key = ( + "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" + ) + chain_id = MUMBAI + signer = Signer(private_key=private_key, chain_id=chain_id) + owner = "aaa-bbb-ccc" + builder = OrderBuilder(signer) + + # GTC BUY + json_order = order_to_json( + order=builder.create_order( + order_args=OrderArgs( + token_id="100", + price=0.05, + size=100, + side=BUY, + ), + tick_size="0.01", + ), + owner=owner, + orderType=OrderType.GTC, + ) + + self.assertIsNotNone(json_order) + self.assertEqual(json_order["orderType"], "GTC") + self.assertEqual(json_order["owner"], owner) + self.assertIsNotNone(json_order["order"]) + self.assertIsNotNone(json_order["order"]["salt"]) + self.assertEqual( + json_order["order"]["maker"], "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + ) + self.assertEqual( + json_order["order"]["signer"], "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + ) + self.assertEqual( + json_order["order"]["taker"], "0x0000000000000000000000000000000000000000" + ) + self.assertEqual(json_order["order"]["tokenId"], "100") + self.assertEqual(json_order["order"]["makerAmount"], "5000000") + self.assertEqual(json_order["order"]["takerAmount"], "100000000") + self.assertEqual(json_order["order"]["expiration"], "0") + self.assertEqual(json_order["order"]["nonce"], "0") + self.assertEqual(json_order["order"]["feeRateBps"], "0") + self.assertEqual(json_order["order"]["side"], "BUY") + self.assertEqual(json_order["order"]["signatureType"], 0) + self.assertIsNotNone(json_order["order"]["signature"]) + + # GTC SELL + json_order = order_to_json( + order=builder.create_order( + order_args=OrderArgs( + token_id="100", + price=0.05, + size=100, + side=SELL, + ), + tick_size="0.01", + ), + owner=owner, + orderType=OrderType.GTC, + ) + + self.assertIsNotNone(json_order) + self.assertEqual(json_order["orderType"], "GTC") + self.assertEqual(json_order["owner"], owner) + self.assertIsNotNone(json_order["order"]) + self.assertIsNotNone(json_order["order"]["salt"]) + self.assertEqual( + json_order["order"]["maker"], "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + ) + self.assertEqual( + json_order["order"]["signer"], "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + ) + self.assertEqual( + json_order["order"]["taker"], "0x0000000000000000000000000000000000000000" + ) + self.assertEqual(json_order["order"]["tokenId"], "100") + self.assertEqual(json_order["order"]["makerAmount"], "100000000") + self.assertEqual(json_order["order"]["takerAmount"], "5000000") + self.assertEqual(json_order["order"]["expiration"], "0") + self.assertEqual(json_order["order"]["nonce"], "0") + self.assertEqual(json_order["order"]["feeRateBps"], "0") + self.assertEqual(json_order["order"]["side"], "SELL") + self.assertEqual(json_order["order"]["signatureType"], 0) + self.assertIsNotNone(json_order["order"]["signature"]) + + # GTD BUY + json_order = order_to_json( + order=builder.create_order( + order_args=OrderArgs( + token_id="100", + price=0.05, + size=100, + side=BUY, + ), + tick_size="0.01", + ), + owner=owner, + orderType=OrderType.GTD, + ) + + self.assertIsNotNone(json_order) + self.assertEqual(json_order["orderType"], "GTD") + self.assertEqual(json_order["owner"], owner) + self.assertIsNotNone(json_order["order"]) + self.assertIsNotNone(json_order["order"]["salt"]) + self.assertEqual( + json_order["order"]["maker"], "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + ) + self.assertEqual( + json_order["order"]["signer"], "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + ) + self.assertEqual( + json_order["order"]["taker"], "0x0000000000000000000000000000000000000000" + ) + self.assertEqual(json_order["order"]["tokenId"], "100") + self.assertEqual(json_order["order"]["makerAmount"], "5000000") + self.assertEqual(json_order["order"]["takerAmount"], "100000000") + self.assertEqual(json_order["order"]["expiration"], "0") + self.assertEqual(json_order["order"]["nonce"], "0") + self.assertEqual(json_order["order"]["feeRateBps"], "0") + self.assertEqual(json_order["order"]["side"], "BUY") + self.assertEqual(json_order["order"]["signatureType"], 0) + self.assertIsNotNone(json_order["order"]["signature"]) + + # GTD SELL + json_order = order_to_json( + order=builder.create_order( + order_args=OrderArgs( + token_id="100", + price=0.05, + size=100, + side=SELL, + ), + tick_size="0.01", + ), + owner=owner, + orderType=OrderType.GTD, + ) + + self.assertIsNotNone(json_order) + self.assertEqual(json_order["orderType"], "GTD") + self.assertEqual(json_order["owner"], owner) + self.assertIsNotNone(json_order["order"]) + self.assertIsNotNone(json_order["order"]["salt"]) + self.assertEqual( + json_order["order"]["maker"], "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + ) + self.assertEqual( + json_order["order"]["signer"], "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + ) + self.assertEqual( + json_order["order"]["taker"], "0x0000000000000000000000000000000000000000" + ) + self.assertEqual(json_order["order"]["tokenId"], "100") + self.assertEqual(json_order["order"]["makerAmount"], "100000000") + self.assertEqual(json_order["order"]["takerAmount"], "5000000") + self.assertEqual(json_order["order"]["expiration"], "0") + self.assertEqual(json_order["order"]["nonce"], "0") + self.assertEqual(json_order["order"]["feeRateBps"], "0") + self.assertEqual(json_order["order"]["side"], "SELL") + self.assertEqual(json_order["order"]["signatureType"], 0) + self.assertIsNotNone(json_order["order"]["signature"]) + + def test_order_to_json_0_001(self): + # publicly known private key + private_key = ( + "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" + ) + chain_id = MUMBAI + signer = Signer(private_key=private_key, chain_id=chain_id) + owner = "aaa-bbb-ccc" + builder = OrderBuilder(signer) + + # GTC BUY + json_order = order_to_json( + order=builder.create_order( + order_args=OrderArgs( + token_id="100", + price=0.005, + size=100, + side=BUY, + ), + tick_size="0.001", + ), + owner=owner, + orderType=OrderType.GTC, + ) + + self.assertIsNotNone(json_order) + self.assertEqual(json_order["orderType"], "GTC") + self.assertEqual(json_order["owner"], owner) + self.assertIsNotNone(json_order["order"]) + self.assertIsNotNone(json_order["order"]["salt"]) + self.assertEqual( + json_order["order"]["maker"], "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + ) + self.assertEqual( + json_order["order"]["signer"], "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + ) + self.assertEqual( + json_order["order"]["taker"], "0x0000000000000000000000000000000000000000" + ) + self.assertEqual(json_order["order"]["tokenId"], "100") + self.assertEqual(json_order["order"]["makerAmount"], "500000") + self.assertEqual(json_order["order"]["takerAmount"], "100000000") + self.assertEqual(json_order["order"]["expiration"], "0") + self.assertEqual(json_order["order"]["nonce"], "0") + self.assertEqual(json_order["order"]["feeRateBps"], "0") + self.assertEqual(json_order["order"]["side"], "BUY") + self.assertEqual(json_order["order"]["signatureType"], 0) + self.assertIsNotNone(json_order["order"]["signature"]) + + # GTC SELL + json_order = order_to_json( + order=builder.create_order( + order_args=OrderArgs( + token_id="100", + price=0.005, + size=100, + side=SELL, + ), + tick_size="0.001", + ), + owner=owner, + orderType=OrderType.GTC, + ) + + self.assertIsNotNone(json_order) + self.assertEqual(json_order["orderType"], "GTC") + self.assertEqual(json_order["owner"], owner) + self.assertIsNotNone(json_order["order"]) + self.assertIsNotNone(json_order["order"]["salt"]) + self.assertEqual( + json_order["order"]["maker"], "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + ) + self.assertEqual( + json_order["order"]["signer"], "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + ) + self.assertEqual( + json_order["order"]["taker"], "0x0000000000000000000000000000000000000000" + ) + self.assertEqual(json_order["order"]["tokenId"], "100") + self.assertEqual(json_order["order"]["makerAmount"], "100000000") + self.assertEqual(json_order["order"]["takerAmount"], "500000") + self.assertEqual(json_order["order"]["expiration"], "0") + self.assertEqual(json_order["order"]["nonce"], "0") + self.assertEqual(json_order["order"]["feeRateBps"], "0") + self.assertEqual(json_order["order"]["side"], "SELL") + self.assertEqual(json_order["order"]["signatureType"], 0) + self.assertIsNotNone(json_order["order"]["signature"]) + + # GTD BUY + json_order = order_to_json( + order=builder.create_order( + order_args=OrderArgs( + token_id="100", + price=0.005, + size=100, + side=BUY, + ), + tick_size="0.001", + ), + owner=owner, + orderType=OrderType.GTD, + ) + + self.assertIsNotNone(json_order) + self.assertEqual(json_order["orderType"], "GTD") + self.assertEqual(json_order["owner"], owner) + self.assertIsNotNone(json_order["order"]) + self.assertIsNotNone(json_order["order"]["salt"]) + self.assertEqual( + json_order["order"]["maker"], "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + ) + self.assertEqual( + json_order["order"]["signer"], "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + ) + self.assertEqual( + json_order["order"]["taker"], "0x0000000000000000000000000000000000000000" + ) + self.assertEqual(json_order["order"]["tokenId"], "100") + self.assertEqual(json_order["order"]["makerAmount"], "500000") + self.assertEqual(json_order["order"]["takerAmount"], "100000000") + self.assertEqual(json_order["order"]["expiration"], "0") + self.assertEqual(json_order["order"]["nonce"], "0") + self.assertEqual(json_order["order"]["feeRateBps"], "0") + self.assertEqual(json_order["order"]["side"], "BUY") + self.assertEqual(json_order["order"]["signatureType"], 0) + self.assertIsNotNone(json_order["order"]["signature"]) + + # GTD SELL + json_order = order_to_json( + order=builder.create_order( + order_args=OrderArgs( + token_id="100", + price=0.005, + size=100, + side=SELL, + ), + tick_size="0.001", + ), + owner=owner, + orderType=OrderType.GTD, + ) + + self.assertIsNotNone(json_order) + self.assertEqual(json_order["orderType"], "GTD") + self.assertEqual(json_order["owner"], owner) + self.assertIsNotNone(json_order["order"]) + self.assertIsNotNone(json_order["order"]["salt"]) + self.assertEqual( + json_order["order"]["maker"], "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + ) + self.assertEqual( + json_order["order"]["signer"], "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + ) + self.assertEqual( + json_order["order"]["taker"], "0x0000000000000000000000000000000000000000" + ) + self.assertEqual(json_order["order"]["tokenId"], "100") + self.assertEqual(json_order["order"]["makerAmount"], "100000000") + self.assertEqual(json_order["order"]["takerAmount"], "500000") + self.assertEqual(json_order["order"]["expiration"], "0") + self.assertEqual(json_order["order"]["nonce"], "0") + self.assertEqual(json_order["order"]["feeRateBps"], "0") + self.assertEqual(json_order["order"]["side"], "SELL") + self.assertEqual(json_order["order"]["signatureType"], 0) + self.assertIsNotNone(json_order["order"]["signature"]) + + def test_order_to_json_0_0001(self): + # publicly known private key + private_key = ( + "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" + ) + chain_id = MUMBAI + signer = Signer(private_key=private_key, chain_id=chain_id) + owner = "aaa-bbb-ccc" + builder = OrderBuilder(signer) + + # GTC BUY + json_order = order_to_json( + order=builder.create_order( + order_args=OrderArgs( + token_id="100", + price=0.0005, + size=100, + side=BUY, + ), + tick_size="0.0001", + ), + owner=owner, + orderType=OrderType.GTC, + ) + + self.assertIsNotNone(json_order) + self.assertEqual(json_order["orderType"], "GTC") + self.assertEqual(json_order["owner"], owner) + self.assertIsNotNone(json_order["order"]) + self.assertIsNotNone(json_order["order"]["salt"]) + self.assertEqual( + json_order["order"]["maker"], "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + ) + self.assertEqual( + json_order["order"]["signer"], "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + ) + self.assertEqual( + json_order["order"]["taker"], "0x0000000000000000000000000000000000000000" + ) + self.assertEqual(json_order["order"]["tokenId"], "100") + self.assertEqual(json_order["order"]["makerAmount"], "50000") + self.assertEqual(json_order["order"]["takerAmount"], "100000000") + self.assertEqual(json_order["order"]["expiration"], "0") + self.assertEqual(json_order["order"]["nonce"], "0") + self.assertEqual(json_order["order"]["feeRateBps"], "0") + self.assertEqual(json_order["order"]["side"], "BUY") + self.assertEqual(json_order["order"]["signatureType"], 0) + self.assertIsNotNone(json_order["order"]["signature"]) + + # GTC SELL + json_order = order_to_json( + order=builder.create_order( + order_args=OrderArgs( + token_id="100", + price=0.0005, + size=100, + side=SELL, + ), + tick_size="0.0001", + ), + owner=owner, + orderType=OrderType.GTC, + ) + + self.assertIsNotNone(json_order) + self.assertEqual(json_order["orderType"], "GTC") + self.assertEqual(json_order["owner"], owner) + self.assertIsNotNone(json_order["order"]) + self.assertIsNotNone(json_order["order"]["salt"]) + self.assertEqual( + json_order["order"]["maker"], "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + ) + self.assertEqual( + json_order["order"]["signer"], "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + ) + self.assertEqual( + json_order["order"]["taker"], "0x0000000000000000000000000000000000000000" + ) + self.assertEqual(json_order["order"]["tokenId"], "100") + self.assertEqual(json_order["order"]["makerAmount"], "100000000") + self.assertEqual(json_order["order"]["takerAmount"], "50000") + self.assertEqual(json_order["order"]["expiration"], "0") + self.assertEqual(json_order["order"]["nonce"], "0") + self.assertEqual(json_order["order"]["feeRateBps"], "0") + self.assertEqual(json_order["order"]["side"], "SELL") + self.assertEqual(json_order["order"]["signatureType"], 0) + self.assertIsNotNone(json_order["order"]["signature"]) + + # GTD BUY + json_order = order_to_json( + order=builder.create_order( + order_args=OrderArgs( + token_id="100", + price=0.0005, + size=100, + side=BUY, + ), + tick_size="0.0001", + ), + owner=owner, + orderType=OrderType.GTD, + ) + + self.assertIsNotNone(json_order) + self.assertEqual(json_order["orderType"], "GTD") + self.assertEqual(json_order["owner"], owner) + self.assertIsNotNone(json_order["order"]) + self.assertIsNotNone(json_order["order"]["salt"]) + self.assertEqual( + json_order["order"]["maker"], "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + ) + self.assertEqual( + json_order["order"]["signer"], "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + ) + self.assertEqual( + json_order["order"]["taker"], "0x0000000000000000000000000000000000000000" + ) + self.assertEqual(json_order["order"]["tokenId"], "100") + self.assertEqual(json_order["order"]["makerAmount"], "50000") + self.assertEqual(json_order["order"]["takerAmount"], "100000000") + self.assertEqual(json_order["order"]["expiration"], "0") + self.assertEqual(json_order["order"]["nonce"], "0") + self.assertEqual(json_order["order"]["feeRateBps"], "0") + self.assertEqual(json_order["order"]["side"], "BUY") + self.assertEqual(json_order["order"]["signatureType"], 0) + self.assertIsNotNone(json_order["order"]["signature"]) + + # GTD SELL + json_order = order_to_json( + order=builder.create_order( + order_args=OrderArgs( + token_id="100", + price=0.0005, + size=100, + side=SELL, + ), + tick_size="0.0001", + ), + owner=owner, + orderType=OrderType.GTD, + ) + + self.assertIsNotNone(json_order) + self.assertEqual(json_order["orderType"], "GTD") + self.assertEqual(json_order["owner"], owner) + self.assertIsNotNone(json_order["order"]) + self.assertIsNotNone(json_order["order"]["salt"]) + self.assertEqual( + json_order["order"]["maker"], "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + ) + self.assertEqual( + json_order["order"]["signer"], "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + ) + self.assertEqual( + json_order["order"]["taker"], "0x0000000000000000000000000000000000000000" + ) + self.assertEqual(json_order["order"]["tokenId"], "100") + self.assertEqual(json_order["order"]["makerAmount"], "100000000") + self.assertEqual(json_order["order"]["takerAmount"], "50000") + self.assertEqual(json_order["order"]["expiration"], "0") + self.assertEqual(json_order["order"]["nonce"], "0") + self.assertEqual(json_order["order"]["feeRateBps"], "0") + self.assertEqual(json_order["order"]["side"], "SELL") + self.assertEqual(json_order["order"]["signatureType"], 0) + self.assertIsNotNone(json_order["order"]["signature"]) From 5b3c8da88f12c15e486f99db4d3235366cd33416 Mon Sep 17 00:00:00 2001 From: Rodrigo <95635797+poly-rodr@users.noreply.github.com> Date: Wed, 12 Apr 2023 15:15:41 -0300 Subject: [PATCH 2/2] converting tick size to an optional parameter --- py_clob_client/client.py | 21 +++++++++++++++++++-- py_clob_client/utilities.py | 7 +++++-- tests/test_utilities.py | 26 ++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/py_clob_client/client.py b/py_clob_client/client.py index cb933ea..bcef209 100644 --- a/py_clob_client/client.py +++ b/py_clob_client/client.py @@ -57,6 +57,7 @@ parse_raw_orderbook_summary, generate_orderbook_summary_hash, order_to_json, + is_tick_size_smaller, ) @@ -237,14 +238,30 @@ def get_tick_size(self, token_id: str) -> TickSize: return self.__tick_sizes[token_id] - def create_order(self, order_args: OrderArgs): + def __resolve_tick_size( + self, token_id: str, tick_size: TickSize = None + ) -> TickSize: + min_tick_size = self.get_tick_size(token_id) + if tick_size is not None: + if is_tick_size_smaller(tick_size, min_tick_size): + raise Exception( + "invalid tick size (" + + tick_size + + "), minimum for the market is " + + min_tick_size, + ) + else: + tick_size = min_tick_size + return tick_size + + def create_order(self, order_args: OrderArgs, tick_size: TickSize = None): """ Creates and signs an order Level 2 Auth required """ self.assert_level_2_auth() - tick_size = self.get_tick_size(order_args.token_id) + tick_size = self.__resolve_tick_size(order_args.token_id, tick_size) return self.builder.create_order(order_args, tick_size) def post_order(self, order, orderType: OrderType = OrderType.GTC): diff --git a/py_clob_client/utilities.py b/py_clob_client/utilities.py index 2275c1f..8648c18 100644 --- a/py_clob_client/utilities.py +++ b/py_clob_client/utilities.py @@ -1,7 +1,6 @@ import hashlib -import json -from .clob_types import OrderBookSummary, OrderSummary +from .clob_types import OrderBookSummary, OrderSummary, TickSize def parse_raw_orderbook_summary(raw_obs: any) -> OrderBookSummary: @@ -33,3 +32,7 @@ def generate_orderbook_summary_hash(orderbook: OrderBookSummary) -> str: def order_to_json(order, owner, orderType) -> dict: return {"order": order.dict(), "owner": owner, "orderType": orderType} + + +def is_tick_size_smaller(a: TickSize, b: TickSize) -> bool: + return float(a) < float(b) diff --git a/tests/test_utilities.py b/tests/test_utilities.py index 4d1c6de..a6240ad 100644 --- a/tests/test_utilities.py +++ b/tests/test_utilities.py @@ -9,6 +9,7 @@ parse_raw_orderbook_summary, generate_orderbook_summary_hash, order_to_json, + is_tick_size_smaller, ) @@ -814,3 +815,28 @@ def test_order_to_json_0_0001(self): self.assertEqual(json_order["order"]["side"], "SELL") self.assertEqual(json_order["order"]["signatureType"], 0) self.assertIsNotNone(json_order["order"]["signature"]) + + def test_is_tick_size_smaller(self): + # 0.1 + self.assertFalse(is_tick_size_smaller("0.1", "0.1")) + self.assertFalse(is_tick_size_smaller("0.1", "0.01")) + self.assertFalse(is_tick_size_smaller("0.1", "0.001")) + self.assertFalse(is_tick_size_smaller("0.1", "0.0001")) + + # 0.01 + self.assertTrue(is_tick_size_smaller("0.01", "0.1")) + self.assertFalse(is_tick_size_smaller("0.01", "0.01")) + self.assertFalse(is_tick_size_smaller("0.01", "0.001")) + self.assertFalse(is_tick_size_smaller("0.01", "0.0001")) + + # 0.001 + self.assertTrue(is_tick_size_smaller("0.001", "0.1")) + self.assertTrue(is_tick_size_smaller("0.001", "0.01")) + self.assertFalse(is_tick_size_smaller("0.001", "0.001")) + self.assertFalse(is_tick_size_smaller("0.001", "0.0001")) + + # 0.0001 + self.assertTrue(is_tick_size_smaller("0.0001", "0.1")) + self.assertTrue(is_tick_size_smaller("0.0001", "0.01")) + self.assertTrue(is_tick_size_smaller("0.0001", "0.001")) + self.assertFalse(is_tick_size_smaller("0.0001", "0.0001"))