Dexterity Typescript SDK QuickStart
The QuickStart tutorial document below provides an overview of how to connect to and use Hxro’s Dexterity Protocol
Index:
What is the Hxro Dexterity Protocol?
Dexterity is a decentralized protocol that allows for the creation and exchange of financial instruments such as perpetual swaps and futures. The protocol provides an on-chain solution to trade and settle these instruments in a liquid, capital-efficient, and decentralized manner. It has a customizable fee model and a customizable risk engine to handle margining and liquidation of trades. It also supports combo products for trading contracts with arbitrary leg ratios. Dexterity relies on a few main components including the Decentralized Exchange (DEX) contract, the Asset Agnostic Order Book (AAOB), and the Instruments, in order to manage the accounting of orders, trades, and product metadata, to track the order book, and to implement the payoff functions of various financial instruments.
MPG ⇒ Market Product Group
An MPG is a group of Products that derive from the same Market (ie: BTC-USD)
Examples:
BTC/USD
BTCUSD-PERP (Perpetual Future)
BTCUSD-MAR2023 (Dated Futures)
ETH/USD
ETHUSD-PERP (Perpetual Future)
ETHUSD-MAR2023 (Dated Futures)
TRG ⇒ Trader Risk Group
Think of these as user/trader ‘accounts’ per MPG, where you can deposit capital and trade with those products on their respective MPG
The following walkthrough provides a step-by-step tutorial on how to create a TRG in the BTC-USD Market-Product-Group for your Wallet
Requirements:
Previous experience with TS
Create a Typescript project (Don’t know how? Read here)
Install Solana Web3.js in your project by running
npm i @solana/web3.js
Install the Dexterity SDK in your project by running
npm i @hxronetwork/dexterity-ts
Install the Anchor library in your project by running
npm i @project-serum/anchor
Install the base58 encoding library in your project by running
npm i bs58
Getting Started:
Importing dependencies:
Setting up an RPC
Set up an RPC to Solana Testnet using the clusterApiUrl()
method from @solana/web3.js
and set the cluster name to "testnet"
. Add the following code to your file:
Tip: Instead of using the clusterApiUrl()
you can pass in your own RPC URL (as a string) for a better connection to Solana since the public ones tend to be more highly saturated
Setting up a test wallet
To sign transactions and create the TRG account, set up your wallet with your private key. Replace the priv_key
variable with your own private key.
It is highly recommended that you create a new wallet to be used exclusively for testing purposes. This can be done via Phantom or any other Solana wallet, subsequently allowing you to retrieve the private key, and use it in your project. Once you have set up your wallet, you can then airdrop Testnet SOL to it from here.
Connecting to Dexterity
Getting the Manifest
Create an asynchronous function called CreateTRG()
in order to connect to Dexterity and obtain the manifest
. This is achieved by using the *getManifest(rpc, useCache, wallet)*
method, passing in your rpc
for *rpc*
, a boolean for *useCache*
(for this tutorial, false
is used), and your wallet
for *wallet*
If the file is ran, you should now see your Manifest
object printed out in the console.
Manifest Object Example Output
Selecting our MPG
This tutorial will focus solely on utilizing the BTC-USD MPG.
In the DexExample()
function, it is recommended to establish a constant for the BTC-USD MPG publickey.
Creating your TRG
To create a TRG for the BTC-USD MPG, use the createTrg(marketProductGroup)
from *manifest*
and pass in mpgPubkey
for ****marketProductGroup****
, then you can console.log
your result.
When the file is ran, you should see the following:
Nicely done! You just created your first TRG for the BTC-USD MPG. The following section provides an overview of how to use the TRG trader account to deposit capital into the account, trade products inside of the MPG, cancel positions, and more.
The following walkthrough provides a step-by-step guides on how to use TRGs to interact with Dexterity
Using TRG
Depositing into TRGs
Create a new file called **fundingTrg.ts**
where you will build your own function to deposit
and withdraw
from a TRG.
Copy and paste the code below into your new file:
To interact with dexterity and the products inside your MPG using TRG, a trader
instance is needed. To create one, use the trader
method from dexterity
and pass in your trgPubkey
and manifest
.
Next, create a viewAccount()
function that allows you to view the cash balance of your TRG account. This will help you to know how much is in the account and enable you to withdraw and deposit funds as needed. This is achieved by using the getNetCash()
method from your trader
instance:
Next, to obtain updated account information, connect to your trader account. To do this, use the connect
method from your trader instance. The connect
method allows you to pass in a function as the first argument to get a perpetual update stream, meaning that it will call your function perpetually. Alternatively, you can pass in a function as the second argument to get an account update only once. In this case, you are going to pass in your viewAccount()
function to only output your cash balance once when you call the account()
function.
To proceed, you will need Testnet Hxro, UXDC
💡 UXDC is an SPL token issued by Hxro Network that is used to test Dexterity Contracts on the Solana Testnet & Devnet
UXDC Faucet: https://uxdc-faucet-api-1srh.vercel.app/
After obtaining UXDC (remember to also have Testnet SOL for transaction fees), create a function to deposit and withdraw UXDC from your TRG
To use the deposit
and withdraw
methods from the trader
instance, pass in a Fractional
type from your dexterity
instance. To create a Fractional
, use **dexterity.Fractional.New(amount: number, exponent: number)**
❓ The Fractional
method from the dexterity
instance creates a new fractional value with a specified numerator and denominator. It is used to represent numbers with fractional values, such as decimals or percentages, and allows for precise calculations with those values.
Fractional
method from the dexterity
instance creates a new fractional value with a specified numerator and denominator. It is used to represent numbers with fractional values, such as decimals or percentages, and allows for precise calculations with those values.You can now run the code and observe that it deposited 5,000 UXDC from your wallet account to your TRG account. After that, you can comment out the deposit function and uncomment the withdraw function. Running the code again will withdraw the UXDC from your TRG account and transfer it back to your test wallet account.
Placing Limit Orders
Create a new file called **limitOrder.ts**
which will be used to build your own function to create and place limit orders
You can copy and paste the code below into your new file:
Moving forward, for simplification purposes, you will only use the 'BTCUSD-PERP'
perpetual product within your BTCUSD Market Product Group.
Create a trader
instance that can be used to interact and trade on Dexterity.
Create a function that handles updates on the TRG account and logs out the TRGs account cash balance (in USDC) to the console.
Call the connect()
method from trader
so updates are streamed.
You are currently iterating over a list of products obtained using the getProducts()
method from the trader
instance. The objective is to find the index of a particular product you are interested in. In this case, that is the BTCUSD-PERP product.
Now, set up a QUOTE_SIZE
constant that is needed to establish the order amount:
QUOTE_SIZE
: This constant represents the size of a contract. In this case, it is set to a value of 1.0000 contracts. Therefore, when a user enters a size of 1, they will receive one contract.
Then, set a constant for the price
of BTCUSD that will be used to set limit orders:
Note: As of the creation of this walkthrough, to place an order using Dexterity, the limit order price must be within 15% of the mark price, up or down.
Now, use the dexterity.Fractional.New
method to convert the price into a fractional value with zero decimal places.
Now, you can finally place an order! Using the newOrder()
method from the trader instance, pass in the following arguments:
productIndex: number
⇒ the index of the product for which we want to place an orderisBid: boolean
⇒ determines whether the order is a bid or an offerBid
= BuyAsk
= Sell
limitPrice: Fractional
⇒ the value at which the order will be filledmaxBaseQty: Fractional
⇒ the size of the order
Here is an example of a Long
:
Here is an example of a Short
:
Congratulations! You have just placed your first orders on Dexterity. The following section will show you how to view your account and TRGs open orders more extensively.
View Account Information and Open Orders
Create a new file called **accountTrg.ts**
where you will build your own function to view TRG account information and open orders.
You can copy and paste the code below into your new file:
Create a function that handles updates on the TRG account and logs them to the console.
Within the streamAccount()
function, call the getOpenOrders()
method of your trader
instance and pass in your PRODUCT_NAME
array. This returns all the Open Limit Orders of your TRG account.
Now that you have your orders
array, create a function called prettierOrders()
. This function formats the open orders inside your orders
array to make them more readable and prints them to the console.
index
: Index of the order in theorders
array.order.productName
: Name of the product for which the order was set (e.g. BTCUSD-PERP).order.price.m
: Price at which the limit order was placed.order.qty.m
: Size quantity for the order.order.isBid
: Boolean value indicating if the order was a "bid" or not. If not, it was an "ask."order.id
: Number ID of the order. This can be used to obtain more information about the order from Dexterity or even to cancel the order itself.
Call pretierorders()
to print out TRGs open orders. Then, print out TRG account information.
Next, call the streamAccount()
function within the trader.connect()
method.
Here is an example of what the output should look like if there are open orders in the target account:
BONUS: Cancel All Open Orders
Here you can see how to easily cancel all open limit orders when called
Last updated