Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Negative Risk #66

Merged
merged 11 commits into from
Dec 7, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 28 additions & 12 deletions py_clob_client/client.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import logging

from .order_builder.builder import OrderBuilder
from .clob_types import ApiCreds, OrderType

from .headers.headers import create_level_1_headers, create_level_2_headers
from .signer import Signer

Expand Down Expand Up @@ -47,7 +45,10 @@
BalanceAllowanceParams,
OrderScoringParams,
TickSize,
CreateOrderOptions,
OrdersScoringParams,
OrderType,
PartialCreateOrderOptions,
)
from .exceptions import PolyException
from .http_helpers.helpers import (
Expand All @@ -60,7 +61,7 @@
add_order_scoring_params_to_url,
add_orders_scoring_params_to_url,
)
from py_order_utils.config import get_contract_config

from .constants import L0, L1, L1_AUTH_UNAVAILABLE, L2, L2_AUTH_UNAVAILABLE
from .utilities import (
parse_raw_orderbook_summary,
Expand Down Expand Up @@ -96,8 +97,7 @@ def __init__(
self.signer = Signer(key, chain_id) if key else None
self.creds = creds
self.mode = self._get_client_mode()
if chain_id:
self.contract_config = get_contract_config(chain_id)

if self.signer:
self.builder = OrderBuilder(
self.signer, sig_type=signature_type, funder=funder
Expand Down Expand Up @@ -263,15 +263,29 @@ def __resolve_tick_size(
tick_size = min_tick_size
return tick_size

def create_order(self, order_args: OrderArgs, tick_size: TickSize = None):
def create_order(
self, order_args: OrderArgs, options: PartialCreateOrderOptions = None
):
"""
Creates and signs an order
Level 2 Auth required
Level 1 Auth required
"""
self.assert_level_2_auth()
self.assert_level_1_auth()

tick_size = self.__resolve_tick_size(order_args.token_id, tick_size)
return self.builder.create_order(order_args, tick_size)
# add resolve_order_options, or similar
tick_size = self.__resolve_tick_size(
order_args.token_id,
options.tick_size if options else None,
)
neg_risk = options.neg_risk if options else False

return self.builder.create_order(
order_args,
CreateOrderOptions(
tick_size=tick_size,
neg_risk=neg_risk,
),
)

def post_order(self, order, orderType: OrderType = OrderType.GTC):
"""
Expand All @@ -286,11 +300,13 @@ def post_order(self, order, orderType: OrderType = OrderType.GTC):
)
return post("{}{}".format(self.host, POST_ORDER), headers=headers, data=body)

def create_and_post_order(self, order_args: OrderArgs):
def create_and_post_order(
self, order_args: OrderArgs, options: PartialCreateOrderOptions = None
):
"""
Utility function to create and publish an order
"""
ord = self.create_order(order_args)
ord = self.create_order(order_args, options)
return self.post_order(ord)

def cancel(self, order_id):
Expand Down
35 changes: 33 additions & 2 deletions py_clob_client/clob_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from typing import Any
from dataclasses import dataclass, asdict
from json import dumps
from typing import Literal
from typing import Literal, Optional

from .constants import ZERO_ADDRESS

Expand Down Expand Up @@ -143,11 +143,42 @@ class OrdersScoringParams:
TickSize = Literal["0.1", "0.01", "0.001", "0.0001"]


@dataclass
class CreateOrderOptions:
tick_size: TickSize
neg_risk: bool = False


@dataclass
class PartialCreateOrderOptions:
tick_size: Optional[TickSize] = None
neg_risk: bool = False


@dataclass
class RoundConfig:
price: float
size: float
amount: float


TickSizes: dict[str, TickSize]
@dataclass
class ContractConfig:
"""
Contract Configuration
"""

exchange: str
"""
The exchange contract responsible for matching orders
"""

collateral: str
"""
The ERC20 token used as collateral for the exchange's markets
"""

conditional_tokens: str
"""
The ERC1155 conditional tokens contract
"""
42 changes: 42 additions & 0 deletions py_clob_client/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from .clob_types import ContractConfig


def get_contract_config(chainID: int, neg_risk: bool = False) -> ContractConfig:
"""
Get the contract configuration for the chain
"""

CONFIG = {
137: ContractConfig(
exchange="0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E",
collateral="0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
conditional_tokens="0x4D97DCd97eC945f40cF65F87097ACe5EA0476045",
),
80001: ContractConfig(
exchange="0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E",
collateral="0x2E8DCfE708D44ae2e406a1c02DFE2Fa13012f961",
conditional_tokens="0x7D8610E9567d2a6C9FBf66a5A13E9Ba8bb120d43",
),
}

NEG_RISK_CONFIG = {
137: ContractConfig(
exchange="0xC5d563A36AE78145C45a50134d48A1215220f80a",
collateral="0x2791bca1f2de4661ed88a30c99a7a9449aa84174",
conditional_tokens="0x4D97DCd97eC945f40cF65F87097ACe5EA0476045",
),
80001: ContractConfig(
exchange="0x87d1A0DdB4C63a6301916F02090A51a7241571e4",
collateral="0x2e8dcfe708d44ae2e406a1c02dfe2fa13012f961",
conditional_tokens="0x7D8610E9567d2a6C9FBf66a5A13E9Ba8bb120d43",
),
}

if neg_risk:
config = NEG_RISK_CONFIG.get(chainID)
else:
config = CONFIG.get(chainID)
if config is None:
raise Exception("Invalid chainID: ${}".format(chainID))

return config
40 changes: 22 additions & 18 deletions py_clob_client/order_builder/builder.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from py_order_utils.builders import OrderBuilder as UtilsOrderBuild
from py_order_utils.builders import OrderBuilder as UtilsOrderBuilder
from py_order_utils.signer import Signer as UtilsSigner
from py_order_utils.model import (
EOA,
OrderData,
SignedOrder,
BUY as UtilsBuy,
SELL as UtilsSell,
)
from py_order_utils.config import get_contract_config

from .helpers import (
to_token_decimals,
Expand All @@ -16,12 +16,11 @@
round_up,
)
from .constants import BUY, SELL

from ..config import get_contract_config
from ..signer import Signer
from ..clob_types import OrderArgs, TickSize, RoundConfig
from typing import Tuple
from ..clob_types import OrderArgs, CreateOrderOptions, TickSize, RoundConfig

ROUNDING_CONFIG: Tuple[TickSize, RoundConfig] = {
ROUNDING_CONFIG: dict[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),
Expand All @@ -40,13 +39,6 @@ def __init__(self, signer: Signer, sig_type=None, funder=None):
# Used for Polymarket proxy wallets and other smart contract wallets
# Defaults to the address of the signer
self.funder = funder if funder is not None else self.signer.address()
self.contract_config = self._get_contract_config(self.signer.get_chain_id())
self.order_builder = UtilsOrderBuild(
self.contract_config.exchange, self.signer.get_chain_id(), self.signer
)

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, round_config: RoundConfig
Expand Down Expand Up @@ -82,23 +74,25 @@ def get_order_amounts(
else:
raise ValueError(f"order_args.side must be '{BUY}' or '{SELL}'")

def create_order(self, order_args: OrderArgs, tick_size: TickSize) -> SignedOrder:
def create_order(
self, order_args: OrderArgs, options: CreateOrderOptions
) -> SignedOrder:
"""
Creates and signs an order
"""
side, maker_amount, taker_amount = self.get_order_amounts(
order_args.side,
order_args.size,
order_args.price,
ROUNDING_CONFIG[tick_size],
ROUNDING_CONFIG[options.tick_size],
)

data = OrderData(
maker=self.funder,
taker=order_args.taker,
tokenId=order_args.token_id,
makerAmount=maker_amount,
takerAmount=taker_amount,
makerAmount=str(maker_amount),
takerAmount=str(taker_amount),
side=side,
feeRateBps=str(order_args.fee_rate_bps),
nonce=str(order_args.nonce),
Expand All @@ -107,4 +101,14 @@ def create_order(self, order_args: OrderArgs, tick_size: TickSize) -> SignedOrde
signatureType=self.sig_type,
)

return self.order_builder.build_signed_order(data)
contract_config = get_contract_config(
self.signer.get_chain_id(), options.neg_risk
)

order_builder = UtilsOrderBuilder(
contract_config.exchange,
self.signer.get_chain_id(),
UtilsSigner(key=self.signer.private_key),
)

return order_builder.build_signed_order(data)
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setuptools.setup(
name="py_clob_client",
version="0.11.0",
version="0.12.0",
author="Polymarket Engineering",
author_email="[email protected]",
maintainer="Polymarket Engineering",
Expand Down
Loading
Loading