From 7ce182d06e5996a9023e5498bbfc7486a3df091e Mon Sep 17 00:00:00 2001 From: Ibad Ur Rahman Date: Mon, 28 Aug 2023 14:53:23 +0500 Subject: [PATCH] Doc change (#3) * fixing the examples and cancel order * documenting --- CHANGES.md | 17 ++++ examples/1.initialization.py | 3 +- examples/10.1.socket_readonly.py | 2 +- examples/10.sockets.py | 2 +- examples/11.sub_accounts.py | 2 +- examples/12.open_order_event.py | 6 +- examples/14.web_sockets.py | 14 ++- examples/15.get_funding_history.py | 2 +- .../16.listening_events_using_sub_account.py | 5 +- examples/17.1.get_orders_readonly.py | 2 +- examples/17.get_orders.py | 2 +- examples/18.dms_api.py | 2 +- examples/19.Generate_readonly_token.py | 2 +- examples/2.user_info.py | 2 +- examples/3.balance.py | 12 ++- examples/4.placing_orders.py | 8 +- examples/5.adjusting_leverage.py | 17 +--- examples/6.adjusting_margin.py | 14 ++- examples/7.cancelling_orders.py | 7 +- examples/8.exchange_data.py | 2 +- examples/9.user_data.py | 2 +- src/bluefin_v2_client/client.py | 88 ++++++++++++----- src/bluefin_v2_client/constants.py | 4 +- src/bluefin_v2_client/contracts.py | 8 +- src/bluefin_v2_client/rpc.py | 98 +++++++------------ src/bluefin_v2_client/utilities.py | 11 ++- 26 files changed, 185 insertions(+), 149 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 94211d9..8e59055 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -76,3 +76,20 @@ hash=hashlib.blake2b(intent,digest_size=32) #then we finally sign the hash ``` +## Margin Bank: +1. When you insert money to margin bank we give it in BASE6 but when we see balance it is in base9. internally the functions are implemented that way. +2. We expect you to give the arguments directly in DECIMALS. + + +## Making Direct Contract Calls: +1. for making contract calls. The one interacting with our contracts are implemented internally in `client.py` +2. we have exposed some generic functions through which you can make direct contract calls yourself + 1. `def rpc_unsafe_moveCall(url,params, function_name: str, function_library: str, userAddress ,packageId, gasBudget=100000000 ):` + 2. `def rpc_sui_executeTransactionBlock(url, txBytes, signature):` + 3. The first one is used to serialise the contract calls you are going to make. + 4. for second one you need to sign the result of first call with your signer and then make call along with serialised call and signature. + 5. internally all our contract calls to packages uses these functions. for more information have a look at `rpc.py` +3. For making calls to SUI functions + 1. For that we have exposed `def rpc_call_sui_function(url, params, method="suix_getCoins"):` + 2. Here you can specify the params and the name of the sui function you are calling. + 3. internally we use these calls to get the chain balance, usdc coins. diff --git a/examples/1.initialization.py b/examples/1.initialization.py index f1c301b..e878ef7 100644 --- a/examples/1.initialization.py +++ b/examples/1.initialization.py @@ -1,8 +1,7 @@ import os import sys -print(os.getcwd()) -sys.path.append(os.getcwd() + "/src/") +# sys.path.append(os.getcwd() + "/src/") from config import TEST_ACCT_KEY, TEST_NETWORK diff --git a/examples/10.1.socket_readonly.py b/examples/10.1.socket_readonly.py index 5e543b2..375e7dc 100644 --- a/examples/10.1.socket_readonly.py +++ b/examples/10.1.socket_readonly.py @@ -1,6 +1,6 @@ import sys, os -sys.path.append(os.getcwd() + "/src/") +# sys.path.append(os.getcwd() + "/src/") import time from config import TEST_ACCT_KEY, TEST_NETWORK diff --git a/examples/10.sockets.py b/examples/10.sockets.py index 8a7029d..05fb66d 100644 --- a/examples/10.sockets.py +++ b/examples/10.sockets.py @@ -1,6 +1,6 @@ import sys, os -sys.path.append(os.getcwd() + "/src/") +# sys.path.append(os.getcwd() + "/src/") import time from config import TEST_ACCT_KEY, TEST_NETWORK diff --git a/examples/11.sub_accounts.py b/examples/11.sub_accounts.py index 00d6d91..aa9c558 100644 --- a/examples/11.sub_accounts.py +++ b/examples/11.sub_accounts.py @@ -1,6 +1,6 @@ import sys, os -sys.path.append(os.getcwd() + "/src/") +# sys.path.append(os.getcwd() + "/src/") from config import TEST_ACCT_KEY, TEST_SUB_ACCT_KEY, TEST_NETWORK from bluefin_v2_client import ( BluefinClient, diff --git a/examples/12.open_order_event.py b/examples/12.open_order_event.py index d884e3f..a753fc1 100644 --- a/examples/12.open_order_event.py +++ b/examples/12.open_order_event.py @@ -32,11 +32,11 @@ async def place_limit_order(client: BluefinClient): # creates a LIMIT order to be signed signature_request = OrderSignatureRequest( symbol=MARKET_SYMBOLS.ETH, # market symbol - price=1300000000000, # price at which you want to place order - quantity=10000000, # quantity + price=1300, # price at which you want to place order + quantity=0.01, # quantity side=ORDER_SIDE.SELL, orderType=ORDER_TYPE.LIMIT, - leverage=1000000000, + leverage=user_leverage, ) # create signed order diff --git a/examples/14.web_sockets.py b/examples/14.web_sockets.py index a6f6440..4c86fec 100644 --- a/examples/14.web_sockets.py +++ b/examples/14.web_sockets.py @@ -1,6 +1,6 @@ import sys, os -sys.path.append(os.getcwd() + "/src/") +# sys.path.append(os.getcwd() + "/src/") import time from config import TEST_ACCT_KEY, TEST_NETWORK from bluefin_v2_client import ( @@ -33,7 +33,7 @@ def on_error(ws, error): def on_close(ws): # unsubscribe from global events - status = client.webSocketClient.unsubscribe_global_updates_by_symbol( + status = client.ws_client.unsubscribe_global_updates_by_symbol( MARKET_SYMBOLS.ETH ) print("Unsubscribed from global ETH events: {}".format(status)) @@ -42,21 +42,19 @@ def on_close(ws): def on_open(ws): # subscribe to global event updates for ETH market - status = client.webSocketClient.subscribe_global_updates_by_symbol( - MARKET_SYMBOLS.ETH - ) + status = client.ws_client.subscribe_global_updates_by_symbol(MARKET_SYMBOLS.ETH) print("Subscribed to global ETH events: {}".format(status)) # SOCKET_EVENTS contains all events that can be listened to print("Listening to Exchange Health updates") - client.webSocketClient.listen(SOCKET_EVENTS.EXCHANGE_HEALTH.value, callback) + client.ws_client.listen(SOCKET_EVENTS.EXCHANGE_HEALTH.value, callback) # logs event name and data for all markets and users that are subscribed. # helpful for debugging # client.socket.listen("default",callback) print("Making socket connection to Bluefin exchange") - client.webSocketClient.initialize_socket( + client.ws_client.initialize_socket( on_open=on_open, on_error=on_error, on_close=on_close ) @@ -65,7 +63,7 @@ def on_open(ws): while not event_received and time.time() < end_time: time.sleep(1) - client.webSocketClient.stop() + client.ws_client.stop() await client.close_connections() diff --git a/examples/15.get_funding_history.py b/examples/15.get_funding_history.py index f93ff7e..b820419 100644 --- a/examples/15.get_funding_history.py +++ b/examples/15.get_funding_history.py @@ -1,6 +1,6 @@ import sys, os -sys.path.append(os.getcwd() + "/src/") +# sys.path.append(os.getcwd() + "/src/") from config import TEST_ACCT_KEY, TEST_NETWORK from bluefin_v2_client import ( BluefinClient, diff --git a/examples/16.listening_events_using_sub_account.py b/examples/16.listening_events_using_sub_account.py index 6c64587..85829e7 100644 --- a/examples/16.listening_events_using_sub_account.py +++ b/examples/16.listening_events_using_sub_account.py @@ -4,6 +4,9 @@ has no position of its own. So when placing orders or listening to position updates the sub account must specify the parent address whose position its listening. """ +import os, sys + +# sys.path.append(os.getcwd() + "/src/") import time, sys from config import TEST_ACCT_KEY, TEST_NETWORK, TEST_SUB_ACCT_KEY from bluefin_v2_client import ( @@ -35,7 +38,7 @@ async def main(): # # whitelist sub account status = await clientParent.update_sub_account( - MARKET_SYMBOLS.ETH, clientChild.get_public_address(), True + clientChild.get_public_address(), True ) print("Sub account created: {}\n".format(status)) diff --git a/examples/17.1.get_orders_readonly.py b/examples/17.1.get_orders_readonly.py index 1a8329b..0791900 100644 --- a/examples/17.1.get_orders_readonly.py +++ b/examples/17.1.get_orders_readonly.py @@ -6,7 +6,7 @@ import sys, os -sys.path.append(os.getcwd() + "/src/") +# sys.path.append(os.getcwd() + "/src/") from config import TEST_ACCT_KEY, TEST_NETWORK from bluefin_v2_client import ( BluefinClient, diff --git a/examples/17.get_orders.py b/examples/17.get_orders.py index 5882c7e..67e00f8 100644 --- a/examples/17.get_orders.py +++ b/examples/17.get_orders.py @@ -5,7 +5,7 @@ """ import sys, os -sys.path.append(os.getcwd() + "/src/") +# sys.path.append(os.getcwd() + "/src/") from config import TEST_ACCT_KEY, TEST_NETWORK from bluefin_v2_client import ( BluefinClient, diff --git a/examples/18.dms_api.py b/examples/18.dms_api.py index cac6217..20dc10b 100644 --- a/examples/18.dms_api.py +++ b/examples/18.dms_api.py @@ -2,7 +2,7 @@ import sys, os -sys.path.append(os.getcwd() + "/src/") +# sys.path.append(os.getcwd() + "/src/") from config import TEST_ACCT_KEY, TEST_SUB_ACCT_KEY, TEST_NETWORK from bluefin_v2_client import ( BluefinClient, diff --git a/examples/19.Generate_readonly_token.py b/examples/19.Generate_readonly_token.py index 6ec3d94..eea55c4 100644 --- a/examples/19.Generate_readonly_token.py +++ b/examples/19.Generate_readonly_token.py @@ -1,6 +1,6 @@ import sys, os -sys.path.append(os.getcwd() + "/src/") +# sys.path.append(os.getcwd() + "/src/") from config import TEST_ACCT_KEY, TEST_NETWORK from bluefin_v2_client import BluefinClient, Networks from pprint import pprint diff --git a/examples/2.user_info.py b/examples/2.user_info.py index 6af62bd..b7424e6 100644 --- a/examples/2.user_info.py +++ b/examples/2.user_info.py @@ -1,6 +1,6 @@ import sys, os -sys.path.append(os.getcwd() + "/src/") +# sys.path.append(os.getcwd() + "/src/") from config import TEST_ACCT_KEY, TEST_NETWORK from bluefin_v2_client import BluefinClient, Networks, MARKET_SYMBOLS from pprint import pprint diff --git a/examples/3.balance.py b/examples/3.balance.py index 9867a33..bae01da 100644 --- a/examples/3.balance.py +++ b/examples/3.balance.py @@ -1,6 +1,6 @@ import sys, os -sys.path.append(os.getcwd() + "/src/") +# sys.path.append(os.getcwd() + "/src/") from config import TEST_ACCT_KEY, TEST_NETWORK from bluefin_v2_client import BluefinClient, Networks @@ -32,18 +32,24 @@ async def main(): # deposit usdc to margin bank # must have native chain tokens to pay for gas fee - print("USDC deposited:", await client.deposit_margin_to_bank(10)) + usdc_coins = client.get_usdc_coins() + ## we expect that you have some coins in your usdc, + coin_obj_id = usdc_coins["data"][1]["coinObjectId"] + print("USDC deposited:", await client.deposit_margin_to_bank(5000, coin_obj_id)) # check margin bank balance resp = await client.get_margin_bank_balance() print("Margin bank balance:", resp) # withdraw margin bank balance - print("USDC Withdrawn:", await client.withdraw_margin_from_bank(resp)) + print("USDC Withdrawn:", await client.withdraw_margin_from_bank(10)) # check margin bank balance print("Margin bank balance:", await client.get_margin_bank_balance()) + print("Withdraw all", await client.withdraw_all_margin_from_bank()) + + print("Margin bank balance:", await client.get_margin_bank_balance()) await client.close_connections() diff --git a/examples/4.placing_orders.py b/examples/4.placing_orders.py index 11d6292..02619cb 100644 --- a/examples/4.placing_orders.py +++ b/examples/4.placing_orders.py @@ -1,6 +1,6 @@ import sys, os -sys.path.append(os.getcwd() + "/src/") +# sys.path.append(os.getcwd() + "/src/") from config import TEST_ACCT_KEY, TEST_NETWORK from bluefin_v2_client import ( BluefinClient, @@ -49,12 +49,11 @@ async def place_market_order(client: BluefinClient): symbol=MARKET_SYMBOLS.ETH, price=0, quantity=1, - leverage=1, + leverage=user_leverage, side=ORDER_SIDE.BUY, reduceOnly=False, postOnly=False, orderbookOnly=True, - maker="0xa3c3504d90c428274beaa89f1238a769ea1d1c3516c31c0f4157f33787367af0", expiration=1700530261000, salt=1668690862116, orderType=ORDER_TYPE.MARKET, @@ -83,9 +82,8 @@ async def main(): await client.init(True) - # await place_limit_order(client) - await client await place_limit_order(client) + await place_market_order(client) await client.close_connections() diff --git a/examples/5.adjusting_leverage.py b/examples/5.adjusting_leverage.py index 9bf7dfc..427df79 100644 --- a/examples/5.adjusting_leverage.py +++ b/examples/5.adjusting_leverage.py @@ -1,6 +1,6 @@ import sys, os -sys.path.append(os.getcwd() + "/src/") +# sys.path.append(os.getcwd() + "/src/") from config import TEST_ACCT_KEY, TEST_NETWORK from bluefin_v2_client import BluefinClient, Networks, MARKET_SYMBOLS @@ -15,27 +15,18 @@ async def main(): TEST_ACCT_KEY, # private key of wallet ) - await client.init(True, symbol=MARKET_SYMBOLS.BTC) + await client.init(True) print("Leverage on BTC market:", await client.get_user_leverage(MARKET_SYMBOLS.BTC)) # we have a position on BTC so this will perform on-chain leverage update # must have native chain tokens to pay for gas fee - await client.adjust_leverage(MARKET_SYMBOLS.BTC, 6) + await client.adjust_leverage(MARKET_SYMBOLS.BTC, 2) print("Leverage on BTC market:", await client.get_user_leverage(MARKET_SYMBOLS.BTC)) - # initialize client - client = BluefinClient( - True, # agree to terms and conditions - Networks[TEST_NETWORK], # network to connect with - TEST_ACCT_KEY, # private key of wallet - ) - - await client.init(True, symbol=MARKET_SYMBOLS.ETH) - print("Leverage on ETH market:", await client.get_user_leverage(MARKET_SYMBOLS.ETH)) # since we don't have a position on-chain, it will perform off-chain leverage adjustment - await client.adjust_leverage(MARKET_SYMBOLS.ETH, 7) + await client.adjust_leverage(MARKET_SYMBOLS.ETH, 8) print("Leverage on ETH market:", await client.get_user_leverage(MARKET_SYMBOLS.ETH)) diff --git a/examples/6.adjusting_margin.py b/examples/6.adjusting_margin.py index a42daba..2d75243 100644 --- a/examples/6.adjusting_margin.py +++ b/examples/6.adjusting_margin.py @@ -1,6 +1,6 @@ import sys, os -sys.path.append(os.getcwd() + "/src/") +# sys.path.append(os.getcwd() + "/src/") from config import TEST_ACCT_KEY, TEST_NETWORK from bluefin_v2_client import BluefinClient, Networks, MARKET_SYMBOLS, ADJUST_MARGIN @@ -14,8 +14,6 @@ OrderSignatureRequest, ) -TEST_NETWORK = "SUI_STAGING" - async def place_limit_order(client: BluefinClient): # default leverage of account is set to 3 on Bluefin @@ -91,7 +89,10 @@ async def main(): # adding 100$ from our margin bank into our BTC position on-chain # must have native chain tokens to pay for gas fee - await client.adjust_margin(MARKET_SYMBOLS.ETH, ADJUST_MARGIN.ADD, 100) + print( + "Adjusting Margin", + await client.adjust_margin(MARKET_SYMBOLS.ETH, ADJUST_MARGIN.ADD, 100), + ) # get updated position margin. Note it can take a few seconds to show updates # to on-chain positions on exchange as off-chain infrastructure waits for blockchain @@ -100,7 +101,10 @@ async def main(): print("Current margin in position:", position["margin"]) # removing 100$ from margin - await client.adjust_margin(MARKET_SYMBOLS.ETH, ADJUST_MARGIN.REMOVE, 100) + print( + "Adjusting margin", + await client.adjust_margin(MARKET_SYMBOLS.ETH, ADJUST_MARGIN.REMOVE, 100), + ) position = await client.get_user_position({"symbol": MARKET_SYMBOLS.ETH}) print("Current margin in position:", int(position["margin"])) diff --git a/examples/7.cancelling_orders.py b/examples/7.cancelling_orders.py index 8451761..6e26967 100644 --- a/examples/7.cancelling_orders.py +++ b/examples/7.cancelling_orders.py @@ -1,6 +1,6 @@ import sys, os, random -sys.path.append(os.getcwd() + "/src/") +# sys.path.append(os.getcwd() + "/src/") import time from config import TEST_ACCT_KEY, TEST_NETWORK @@ -23,15 +23,16 @@ async def main(): # client.create_order_to_sign() await client.adjust_leverage(MARKET_SYMBOLS.ETH, 1) + user_leverage = await client.get_user_leverage(MARKET_SYMBOLS.ETH) # creates a LIMIT order to be signed order = OrderSignatureRequest( symbol=MARKET_SYMBOLS.ETH, # market symbol - price=1636.8, # price at which you want to place order + price=2905, # price at which you want to place order quantity=0.01, # quantity side=ORDER_SIDE.BUY, orderType=ORDER_TYPE.LIMIT, - leverage=1, + leverage=user_leverage, salt=random.randint(0, 100000000), expiration=int(time.time() + (30 * 24 * 60 * 60)) * 1000, ) diff --git a/examples/8.exchange_data.py b/examples/8.exchange_data.py index 6008176..58d41da 100644 --- a/examples/8.exchange_data.py +++ b/examples/8.exchange_data.py @@ -1,6 +1,6 @@ import sys, os -sys.path.append(os.getcwd() + "/src/") +# sys.path.append(os.getcwd() + "/src/") from config import TEST_ACCT_KEY, TEST_NETWORK from bluefin_v2_client import ( diff --git a/examples/9.user_data.py b/examples/9.user_data.py index 5540e76..38023a5 100644 --- a/examples/9.user_data.py +++ b/examples/9.user_data.py @@ -1,6 +1,6 @@ import sys, os -sys.path.append(os.getcwd() + "/src/") +# sys.path.append(os.getcwd() + "/src/") from config import TEST_ACCT_KEY, TEST_NETWORK from bluefin_v2_client import BluefinClient, Networks, MARKET_SYMBOLS, ORDER_STATUS diff --git a/src/bluefin_v2_client/client.py b/src/bluefin_v2_client/client.py index 4b11c4a..f14d1c7 100644 --- a/src/bluefin_v2_client/client.py +++ b/src/bluefin_v2_client/client.py @@ -5,11 +5,11 @@ from .contracts import Contracts from .order_signer import OrderSigner from .onboarding_signer import OnboardingSigner -from .constants import TIME, SERVICE_URLS +from .constants import TIME, SERVICE_URLS, CONTRACTS_BASE_NUM from .sockets_lib import Sockets from .websocket_client import WebsocketClient from .signer import Signer -from .utilities import default_value +from .utilities import * from .rpc import * from .account import * from .interfaces import * @@ -106,7 +106,7 @@ async def authorize_signed_hash(self, signed_hash: str): }, ) - def create_order_to_sign(self, params: OrderSignatureRequest): + def create_order_to_sign(self, params: OrderSignatureRequest) -> Order: """ Creates order signature request for an order. Inputs: @@ -192,7 +192,11 @@ def create_signed_cancel_order( Returns: OrderSignatureResponse: generated cancel signature """ - order_to_sign = self.create_order_to_sign(params) + sui_params = deepcopy(params) + sui_params["price"] = self._to_sui_base(params["price"]) + sui_params["quantity"] = self._to_sui_base(params["quantity"]) + sui_params["leverage"] = self._to_sui_base(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) return self.create_signed_cancel_orders( params["symbol"], hash_val.hex(), parentAddress @@ -331,7 +335,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(self._to_sui_base(amount))) + callArgs.append(str(toSuiBase(amount, base=CONTRACTS_BASE_NUM))) callArgs.append(coin_id) txBytes = rpc_unsafe_moveCall( self.url, @@ -344,9 +348,12 @@ async def deposit_margin_to_bank(self, amount: int, coin_id: str) -> bool: signature = self.contract_signer.sign_tx(txBytes, self.account) res = rpc_sui_executeTransactionBlock(self.url, txBytes, signature) - return res + if res["result"]["effects"]["status"]["status"] == "success": + return True + else: + return False - async def withdraw_margin_from_bank(self, amount): + async def withdraw_margin_from_bank(self, amount: Union[float, int]) -> bool: """ Withdraws given amount of usdc from margin bank if possible @@ -360,7 +367,11 @@ async def withdraw_margin_from_bank(self, amount): bank_id = self.contracts.get_bank_id() account_address = self.account.getUserAddress() - callArgs = [bank_id, account_address, str(amount)] + callArgs = [ + bank_id, + account_address, + str(toSuiBase(amount, base=CONTRACTS_BASE_NUM)), + ] txBytes = rpc_unsafe_moveCall( self.url, callArgs, @@ -372,9 +383,20 @@ async def withdraw_margin_from_bank(self, amount): signature = self.contract_signer.sign_tx(txBytes, self.account) res = rpc_sui_executeTransactionBlock(self.url, txBytes, signature) - return res + if res["result"]["effects"]["status"]["status"] == "success": + return True + else: + return False async def withdraw_all_margin_from_bank(self): + """ + Withdraws everything of usdc from margin bank + + Inputs: + No input Required + Returns: + Boolean: true if amount is successfully withdrawn, false otherwise + """ bank_id = self.contracts.get_bank_id() account_address = self.account.getUserAddress() @@ -389,7 +411,11 @@ async def withdraw_all_margin_from_bank(self): ) signature = self.contract_signer.sign_tx(txBytes, self.account) res = rpc_sui_executeTransactionBlock(self.url, txBytes, signature) - return res + + if res["result"]["effects"]["status"]["status"] == "success": + return True + else: + return False async def adjust_leverage(self, symbol, leverage, parentAddress: str = ""): """ @@ -411,6 +437,7 @@ 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)) @@ -418,7 +445,7 @@ async def adjust_leverage(self, symbol, leverage, parentAddress: str = ""): callArgs.append(self.contracts.get_sub_account_id()) callArgs.append(account_address) callArgs.append(str(self._to_sui_base(leverage))) - callArgs.append(self.contracts.get_price_oracle_object_id(symbol.value)) + callArgs.append(self.contracts.get_price_oracle_object_id(symbol)) txBytes = rpc_unsafe_moveCall( self.url, callArgs, @@ -429,19 +456,22 @@ async def adjust_leverage(self, symbol, leverage, parentAddress: str = ""): ) signature = self.contract_signer.sign_tx(txBytes, self.account) result = rpc_sui_executeTransactionBlock(self.url, txBytes, signature) - return result - else: - await self.apis.post( - SERVICE_URLS["USER"]["ADJUST_LEVERAGE"], - { - "symbol": symbol.value, - "address": account_address, - "leverage": toDapiBase(leverage), - "marginType": MARGIN_TYPE.ISOLATED.value, - }, - auth_required=True, - ) - return True + if result["result"]["effects"]["status"]["status"] == "success": + return True + else: + return False + + res = await self.apis.post( + SERVICE_URLS["USER"]["ADJUST_LEVERAGE"], + { + "symbol": symbol.value, + "address": account_address, + "leverage": toDapiBase(leverage), + "marginType": MARGIN_TYPE.ISOLATED.value, + }, + auth_required=True, + ) + return res async def adjust_margin( self, @@ -476,7 +506,7 @@ async def adjust_margin( callArgs.append(self.contracts.get_sub_account_id()) callArgs.append(self.account.getUserAddress()) - callArgs.append(str(amount)) + callArgs.append(str(toSuiBase(amount))) callArgs.append(self.contracts.get_price_oracle_object_id(symbol)) if operation == ADJUST_MARGIN.ADD: txBytes = rpc_unsafe_moveCall( @@ -500,7 +530,10 @@ async def adjust_margin( signature = self.contract_signer.sign_tx(txBytes, self.account) result = rpc_sui_executeTransactionBlock(self.url, txBytes, signature) - return True + if result["result"]["effects"]["status"]["status"] == "success": + return True + else: + return False async def update_sub_account(self, sub_account_address: str, status: bool) -> bool: """ @@ -549,6 +582,9 @@ async def get_native_chain_token_balance(self) -> float: raise (Exception(f"Failed to get balance, error: {e}")) def get_usdc_coins(self): + """ + Returns the list of the usdc coins owned by user + """ try: callArgs = [] callArgs.append(self.account.getUserAddress()) diff --git a/src/bluefin_v2_client/constants.py b/src/bluefin_v2_client/constants.py index af29f9b..aef6c21 100644 --- a/src/bluefin_v2_client/constants.py +++ b/src/bluefin_v2_client/constants.py @@ -13,7 +13,7 @@ "socketURL": "wss://dapi.api.sui-prod.bluefin.io", "dmsURL": "https://dapi.api.sui-prod.bluefin.io", "webSocketURL": "wss://notifications.api.sui-prod.bluefin.io", - "onboardingUrl": "https://trade.bluefin.io", + "onboardingUrl": "https://trade-sui.bluefin.exchange", }, } @@ -64,4 +64,6 @@ }, } +SUI_BASE_NUM = 1000000000 DAPI_BASE_NUM = 1000000000000000000 +CONTRACTS_BASE_NUM = 1000000 diff --git a/src/bluefin_v2_client/contracts.py b/src/bluefin_v2_client/contracts.py index 0ddc310..652b7ec 100644 --- a/src/bluefin_v2_client/contracts.py +++ b/src/bluefin_v2_client/contracts.py @@ -11,7 +11,9 @@ def __init__(self): def set_contract_addresses(self, contracts_info): self.contract_info = contracts_info - self.contracts_global_info = contracts_info[_DEFAULT_MARKET]["Deployment"] + self.contracts_global_info = contracts_info["auxiliaryContractsAddresses"][ + "objects" + ] def get_sub_account_id(self): return self.contracts_global_info["SubAccounts"]["id"] @@ -29,7 +31,7 @@ def get_currency_type(self): return self.contracts_global_info["Currency"]["dataType"] def get_price_oracle_object_id(self, market: MARKET_SYMBOLS): - return self.contract_info[market]["objects"]["PriceOracle"]["id"] + return self.contract_info[market.value]["PriceOracle"]["id"] def get_perpetual_id(self, market: MARKET_SYMBOLS): - return self.contract_info[market]["objects"]["Perpetual"]["id"] + return self.contract_info[market.value]["Perpetual"]["id"] diff --git a/src/bluefin_v2_client/rpc.py b/src/bluefin_v2_client/rpc.py index 7ff4752..1d6fa4f 100644 --- a/src/bluefin_v2_client/rpc.py +++ b/src/bluefin_v2_client/rpc.py @@ -11,6 +11,21 @@ def rpc_unsafe_moveCall( packageId, gasBudget=100000000, ): + """ + Does the RPC call to SUI chain + Input: + url: url of the node + params: a list of arguments to be passed to function + function_name: name of the function to call on sui + function_library: name of the library/module in which the function exists + userAddress: Address of the signer + packageId: package id in which the module exists + gasBudget(optional): gasBudget defaults to 100000000 + + Output: + Returns the request form serialised in bytes ready to be signed. + + """ base_dict = {} base_dict["jsonrpc"] = "2.0" base_dict["id"] = 1689764924887 @@ -34,6 +49,18 @@ def rpc_unsafe_moveCall( def rpc_sui_executeTransactionBlock(url, txBytes, signature): + """ + Execute the SUI call on sui chain + Input: + url: url of the node + txBytes: the call in serialised form + signature: txBytes signed by signer + + Output: + result of transaction + + + """ base_dict = {} base_dict["jsonrpc"] = "2.0" base_dict["id"] = 5 @@ -59,6 +86,13 @@ def rpc_sui_executeTransactionBlock(url, txBytes, signature): def rpc_call_sui_function(url, params, method="suix_getCoins"): + """ + for calling sui functions: + Input: + url: url of node + params: arguments of function + method(optional): the name of method in sui we want to call. defaults to suix_getCoins + """ base_dict = {} base_dict["jsonrpc"] = "2.0" base_dict["id"] = 1 @@ -70,67 +104,3 @@ def rpc_call_sui_function(url, params, method="suix_getCoins"): response = requests.request("POST", url, headers=headers, data=payload) result = json.loads(response.text) return result["result"] - - -""" - -payload = json.dumps({ - "jsonrpc": "2.0", - "id": 5, - "method": "sui_executeTransactionBlock", - "params": [ - "AAADAQGPzuAZV5krLKJWD1WUXOjk7Guz2vki2pBMZJ6CXkRf1XLGgQAAAAAAAQAgH/qFdX+Vzs7ShiLTDkGkUsiFFt9TRQyxkTgS3YKNWWgAEOgDAAAAAAAAAAAAAAAAAAABAF82iNaL7Cly31h0P767ErFoKbQb8bxQeNNRAJDvbPWOC21hcmdpbl9iYW5rEndpdGhkcmF3X2Zyb21fYmFuawADAQAAAQEAAQIAH/qFdX+Vzs7ShiLTDkGkUsiFFt9TRQyxkTgS3YKNWWgBWiybg/9fRf7zXUmsdBU3umIFeucEZNWeMGzlLttPf86tHg8AAAAAACA3qZfzxP1+yVILtVkJ6LdfZvkF7gK877AJco9Xook9Th/6hXV/lc7O0oYi0w5BpFLIhRbfU0UMsZE4Et2CjVlo6AMAAAAAAAAA4fUFAAAAAAA=", - [ - "ANyIBWjL6U9T6qBoWWTc18qzVViytirDmwX+dOEqd77dibe0tgLcziDZpe3XoTRVbBJGUV9TIHCN2C21aNvUTA/JFlIyQTT87zRFBPBubLG+G22kP5UDgk3kIg8JPeUiBw==" - ], - { - "showInput": True, - "showEffects": True, - "showEvents": True, - "showObjectChanges": True - }, - "WaitForLocalExecution" - ] -}) -headers = { - 'Content-Type': 'application/json' -} - -response = requests.request("POST", url, headers=headers, data=payload) - -print(response.text) - - -""" - - -""" -url = "https://fullnode.testnet.sui.io:443" - -payload = json.dumps({ - "jsonrpc": "2.0", - "id": 1689764924887, - "method": "unsafe_moveCall", - "params": [ - "0x1ffa85757f95ceced28622d30e41a452c88516df53450cb1913812dd828d5968", - "0x5f3688d68bec2972df58743fbebb12b16829b41bf1bc5078d3510090ef6cf58e", - "margin_bank", - "withdraw_from_bank", - [], - [ - "0x8fcee01957992b2ca2560f55945ce8e4ec6bb3daf922da904c649e825e445fd5", - "0x1ffa85757f95ceced28622d30e41a452c88516df53450cb1913812dd828d5968", - "1000" - ], - "0x5a2c9b83ff5f45fef35d49ac741537ba62057ae70464d59e306ce52edb4f7fce", - "100000000" - ] -}) -headers = { - 'Content-Type': 'application/json' -} - -response = requests.request("POST", url, headers=headers, data=payload) - -print(response.text) -""" diff --git a/src/bluefin_v2_client/utilities.py b/src/bluefin_v2_client/utilities.py index 2f89d7f..5f3a3d5 100644 --- a/src/bluefin_v2_client/utilities.py +++ b/src/bluefin_v2_client/utilities.py @@ -6,7 +6,7 @@ import bip_utils import hashlib from typing import Union -from .constants import SUI_BASE_NUM, DAPI_BASE_NUM +from .constants import SUI_BASE_NUM, DAPI_BASE_NUM, CONTRACTS_BASE_NUM def toDapiBase(number: Union[int, float]) -> int: @@ -17,6 +17,15 @@ def fromDapiBase(number: Union[int, float], dtype=int) -> int: return dtype(number / DAPI_BASE_NUM) +def toSuiBase(number: Union[int, float], base=SUI_BASE_NUM) -> int: + return int(number * base) + + +def fromSuiBase(number: Union[str, int], base=SUI_BASE_NUM) -> float: + number = float(number) + return number / float(base) + + def numberToHex(num, pad=32): # converting number to Hexadecimal format hexNum = hex(num)