diff --git a/pyproject.toml b/pyproject.toml index b830e93..482148b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "bluefin_v2_client" -version = "2.1.0" +version = "2.1.1" description = "Library to interact with Bluefin exchange protocol including its off-chain api-gateway and on-chain contracts" readme = "README.md" requires-python = ">=3.8" diff --git a/src/bluefin_v2_client/client.py b/src/bluefin_v2_client/client.py index c0f872b..f37de47 100644 --- a/src/bluefin_v2_client/client.py +++ b/src/bluefin_v2_client/client.py @@ -5,7 +5,7 @@ from .contracts import Contracts from .order_signer import OrderSigner from .onboarding_signer import OnboardingSigner -from .constants import TIME, SERVICE_URLS, CONTRACTS_BASE_NUM +from .constants import TIME, SERVICE_URLS from .sockets_lib import Sockets from .websocket_client import WebsocketClient from .signer import Signer @@ -15,10 +15,14 @@ from .interfaces import * from .enumerations import * -_SUI_BASE_NUM = 1000000000 +DEAULT_EXCHANGE_LEVERAGE = 3 class BluefinClient: + """ + A class to represent a client for interacting with bluefin offchain and onchain APIs. + """ + def __init__(self, are_terms_accepted, network, private_key=""): self.are_terms_accepted = are_terms_accepted self.network = network @@ -153,9 +157,9 @@ def create_signed_order(self, req: OrderSignatureRequest) -> OrderSignatureRespo OrderSignatureResponse: order raw info and generated signature """ sui_params = deepcopy(req) - sui_params["price"] = toDapiBase(req["price"]) - sui_params["quantity"] = toDapiBase(req["quantity"]) - sui_params["leverage"] = toDapiBase(req["leverage"]) + sui_params["price"] = to1e18(req["price"]) + sui_params["quantity"] = to1e18(req["quantity"]) + sui_params["leverage"] = to1e18(req["leverage"]) order = self.create_order_to_sign(sui_params) symbol = sui_params["symbol"].value @@ -193,9 +197,9 @@ def create_signed_cancel_order( OrderSignatureResponse: generated cancel signature """ sui_params = deepcopy(params) - sui_params["price"] = toDapiBase(params["price"]) - sui_params["quantity"] = toDapiBase(params["quantity"]) - sui_params["leverage"] = toDapiBase(params["leverage"]) + sui_params["price"] = to1e18(params["price"]) + sui_params["quantity"] = to1e18(params["quantity"]) + sui_params["leverage"] = to1e18(params["leverage"]) order_to_sign = self.create_order_to_sign(sui_params) hash_val = self.order_signer.get_order_hash(order_to_sign, withBufferHex=False) @@ -313,7 +317,7 @@ async def post_signed_order(self, params: PlaceOrderRequest): ), "postOnly": default_value(params, "postOnly", False), "cancelOnRevert": default_value(params, "cancelOnRevert", False), - "clientId": "bluefin-python-client: {}".format( + "clientId": "bluefin-v2-client-python: {}".format( default_value(params, "clientId", "bluefin-python-client") ), }, @@ -336,7 +340,7 @@ async def deposit_margin_to_bank(self, amount: int, coin_id: str) -> bool: callArgs = [] callArgs.append(self.contracts.get_bank_id()) callArgs.append(self.account.getUserAddress()) - callArgs.append(str(toSuiBase(amount, base=CONTRACTS_BASE_NUM))) + callArgs.append(str(toUsdcBase(amount))) callArgs.append(coin_id) txBytes = rpc_unsafe_moveCall( self.url, @@ -371,7 +375,7 @@ async def withdraw_margin_from_bank(self, amount: Union[float, int]) -> bool: callArgs = [ bank_id, account_address, - str(toSuiBase(amount, base=CONTRACTS_BASE_NUM)), + str(toUsdcBase(amount)), ] txBytes = rpc_unsafe_moveCall( self.url, @@ -438,14 +442,13 @@ async def adjust_leverage(self, symbol, leverage, parentAddress: str = ""): account_address = self.account.address if parentAddress == "" else parentAddress # implies user has an open position on-chain, perform on-chain leverage update - open_position = True if user_position != {}: callArgs = [] callArgs.append(self.contracts.get_perpetual_id(symbol)) callArgs.append(self.contracts.get_bank_id()) callArgs.append(self.contracts.get_sub_account_id()) callArgs.append(account_address) - callArgs.append(str(toDapiBase(leverage))) + callArgs.append(str(to1e18(leverage))) callArgs.append(self.contracts.get_price_oracle_object_id(symbol)) txBytes = rpc_unsafe_moveCall( self.url, @@ -467,7 +470,7 @@ async def adjust_leverage(self, symbol, leverage, parentAddress: str = ""): { "symbol": symbol.value, "address": account_address, - "leverage": toDapiBase(leverage), + "leverage": to1e18(leverage), "marginType": MARGIN_TYPE.ISOLATED.value, }, auth_required=True, @@ -507,7 +510,7 @@ async def adjust_margin( callArgs.append(self.contracts.get_sub_account_id()) callArgs.append(self.account.getUserAddress()) - callArgs.append(str(toDapiBase(amount))) + callArgs.append(str(to1e18(amount))) callArgs.append(self.contracts.get_price_oracle_object_id(symbol)) if operation == ADJUST_MARGIN.ADD: txBytes = rpc_unsafe_moveCall( @@ -578,7 +581,7 @@ async def get_native_chain_token_balance(self) -> float: result = rpc_call_sui_function( self.url, callArgs, method="suix_getBalance" )["totalBalance"] - return self._from_sui_base(result) + return fromSuiBase(result) except Exception as e: raise (Exception(f"Failed to get balance, error: {e}")) @@ -606,7 +609,7 @@ async def get_usdc_balance(self) -> float: result = rpc_call_sui_function( self.url, callArgs, method="suix_getBalance" )["totalBalance"] - return self._from_sui_base(result) + return fromSuiBase(result) except Exception as e: raise (Exception("Failed to get balance, Exception: {}".format(e))) @@ -625,7 +628,7 @@ async def get_margin_bank_balance(self) -> float: self.url, call_args, method="suix_getDynamicFieldObject" ) - balance = fromDapiBase( + balance = from1e18( result["data"]["content"]["fields"]["value"]["fields"]["balance"] ) return balance @@ -894,10 +897,9 @@ async def get_user_leverage(self, symbol: MARKET_SYMBOLS, parentAddress: str = " for i in account_data_by_market: if symbol.value == i["symbol"]: - return fromDapiBase(int(i["selectedLeverage"])) - # default leverage on system is 3 + return from1e18(int(i["selectedLeverage"])) # todo fetch from exchange info route - return 3 + return DEAULT_EXCHANGE_LEVERAGE async def get_cancel_on_disconnect_timer( self, params: GetCancelOnDisconnectTimerRequest = None @@ -952,10 +954,3 @@ async def close_connections(self): # close aio http connection await self.apis.close_session() await self.dms_api.close_session() - - def _from_sui_base(self, number: Union[str, int]) -> float: - number = float(number) - return number / float(_SUI_BASE_NUM) - - def _to_sui_base(self, number: Union[int, float]) -> int: - return int(number * _SUI_BASE_NUM) diff --git a/src/bluefin_v2_client/constants.py b/src/bluefin_v2_client/constants.py index 1f95172..83346c0 100644 --- a/src/bluefin_v2_client/constants.py +++ b/src/bluefin_v2_client/constants.py @@ -63,7 +63,3 @@ "ORDERS_HASH": "/orders/hash", }, } - -SUI_BASE_NUM = 1000000000 -DAPI_BASE_NUM = 1000000000000000000 -CONTRACTS_BASE_NUM = 1000000 diff --git a/src/bluefin_v2_client/utilities.py b/src/bluefin_v2_client/utilities.py index 5f3a3d5..fcb59bd 100644 --- a/src/bluefin_v2_client/utilities.py +++ b/src/bluefin_v2_client/utilities.py @@ -3,33 +3,46 @@ # from web3 import Web3 import time +from typing import Union import bip_utils import hashlib -from typing import Union -from .constants import SUI_BASE_NUM, DAPI_BASE_NUM, CONTRACTS_BASE_NUM -def toDapiBase(number: Union[int, float]) -> int: - return int(number * DAPI_BASE_NUM) +BASE_1E18 = 1000000000000000000 +BASE_1E6 = 1000000 # 1e6 for USDC token +BASE_1E9 = 1000000000 -def fromDapiBase(number: Union[int, float], dtype=int) -> int: - return dtype(number / DAPI_BASE_NUM) +def to1e18(number: Union[int, float]) -> int: + """Takes in a number and multiples it by 1e18""" + return int(number * BASE_1E18) -def toSuiBase(number: Union[int, float], base=SUI_BASE_NUM) -> int: - return int(number * base) +def from1e18(number: Union[str, int]) -> float: + """Takes in a number and divides it by 1e18""" + number = float(number) + return number / float(BASE_1E18) -def fromSuiBase(number: Union[str, int], base=SUI_BASE_NUM) -> float: +def fromSuiBase(number: Union[str, int]) -> float: + """Takes in a number and divides it by 1e9""" number = float(number) - return number / float(base) + return number / float(BASE_1E9) + + +def toUsdcBase(number: Union[int, float]) -> int: + """Converts a number to usdc contract onchain representation i.e. multiply it by 1e6""" + return int(number * BASE_1E6) + + +def fromUsdcBase(number: Union[str, int]) -> float: + """Converts a usdc quantity to number i.e. divide it by 1e6""" + number = float(number) + return number / float(BASE_1E6) def numberToHex(num, pad=32): - # converting number to Hexadecimal format hexNum = hex(num) - # padding it with zero to make the size 32 bytes padHex = hexNum[2:].zfill(pad) return padHex