API Documentation
A description of the TsunamiX contracts
Deployed Contracts
PositionRouter: 0xB5D1DDdFbb8697416EA2DC9ba943542e0c1CB206
OrderBook: 0x71E1db7DF70BD3c6f8F12aEEf53dD5068B14a555
RewardReader: 0x6599Ca48719B89B2e8f099E1383209C799A6bEe4
OrderBookReader: 0xf102D2037e5fDCdec7DA9A134DA678dF2E691EF3
GlpManager: 0xb64A055F0980b91385e0bA810Df40d4B61b9711b
RewardRouter: 0xCC8865447bFA08B11d9985E5109E392F8Ee645E4
PriceFeed: 0xA3387b96936B3CeD8d23FbA12ffCDaA0A78E38B5
Swap
To execute a swap:
Approve the Router contract for the token and amount you would like to swap
Call Router.swap with parameters:
_path: [tokenIn, tokenOut]
_amountIn: amount of tokenIn to swap
_minOut: minimum expected output amount
_receiver: address of the receiver of tokenOut
The function will revert if the amount of tokenOut sent to the receiver is less than _minOut
To get swap amounts before execution:
Call Reader.getMaxAmountIn with parameters:
_vault: address of the vault
_tokenIn: address of token that will be given
_tokenOut: address of token to be received
The max amount of tokenIn that can be swapped will be returned
Call Reader.getAmountOut with parameters:
_vault: address of the vault
_tokenIn: address of token that will be given
_tokenOut: address of token to be received
_amountIn: amount of tokenIn to swap
Two values will be returned, the first is the amount out after fees, and the second is the fee amount
The fee amount will be in terms of tokenOut
Tokens have a usdgAmount in the Vault contract used for some calculations, this amount is updated on minting of TLP, redemption of TLP and swaps based on the price of the token at the time. Due to price fluctuations this value may drift slightly from the actual USD value of the tokens in the pool, the usdgAmount is periodically updated to re-align values.
Query Available Amounts
The maximum sum of all position sizes is limited by the amount of tokens there are in the pool and any additional caps.
To calculate the available amount of liquidity for long positions:
indexToken: the address of the token to long
Available amount in tokens: Vault.poolAmounts(indexToken) - Vault.reservedAmounts(indexToken)
Available amount in USD: PositionRouter.maxGlobalLongSizes(indexToken) - Vault.guaranteedUsd(indexToken)
The available liquidity will be the lower of these two values
PositionRouter.maxGlobalLongSizes(indexToken) can be zero, in which case there is no additional cap, and available liquidity is based only on the available amount of tokens
To calculate the available amount of liquidity for short positions:
indexToken: the address of the token to short
collateralToken: the address of the stablecoin token to be used as collateral
Available amount in tokens: Vault.poolAmounts(collateralToken) - Vault.reservedAmounts(collateralToken)
Available amount in USD: PositionRouter.maxGlobalShortSizes(indexToken) - Vault.globalShortSizes(indexToken)
The available liquidity will be the lower of these two values
PositionRouter.maxGlobalShortSizes(indexToken) can be zero, in which case there is no additional cap, and available liquidity is based only on the available amount of tokens
Opening / Increasing a Position
To open or increase the size of an existing position:
Approve the PositionRouter as a Router plugin for your account
Router.approvePlugin(PositionRouter address)
Approve the Router contract for the token and amount you would deposit as collateral for the position
Call PositionRouter.createIncreasePosition with parameters:
_path: [collateralToken] or [tokenIn, collateralToken] if a swap is needed
_indexToken: the address of the token you want to long or short
_amountIn: the amount of tokenIn you want to deposit as collateral
_minOut: the min amount of collateralToken to swap for
_sizeDelta: the USD value of the change in position size
_isLong: whether to long or short
_acceptablePrice: the USD value of the max (for longs) or min (for shorts) index price acceptable when executing the request
_executionFee: can be set to PositionRouter.minExecutionFee
_referralCode: referral code for affiliate rewards and rebates
_callbackTarget: an optional callback contract, this contract will be called on request execution or cancellation
After this transaction is sent a keeper will execute the request, the request will either be executed or cancelled
If the position cannot be increased for reasons such as the _acceptablePrice not being fulfillable or there being insufficient liquidity then the request will be cancelled and funds will be sent back to the msg.sender that called PositionRouter.createIncreasePosition
_minOut can be zero if no swap is required
USD values for _sizeDelta and _price are multiplied by (10 ** 30), so for example to open a long position of size 1000 USD, the value 1000 * (10 ** 30) should be used
Note that if the position increase request is created with PositionRouter.createIncreasePositionETH then in case of cancellation the PositionRouter would send ETH to the receiver using receiver.send(amount)
, this has a limit of 2300 gas. If the receiver is a contract and the receive function invoked on the transfer requires more than 2300 gas, this call can fail which would cause the ETH to be left in the PositionRouter.
WETH and PositionRouter.createIncreasePosition should be used instead to avoid this issue.
Closing / Decreasing a Position
To close or decrease an existing position:
Call PositionRouter.createDecreasePosition with parameters:
_path: [collateralToken] or [collateralToken, tokenOut] if a swap is needed
_indexToken: the index token of the position
_collateralDelta: the amount of collateral in USD value to withdraw
_sizeDelta: the USD value of the change in position size
_isLong: whether the position is a long or short
_receiver: the address to receive the withdrawn tokens
_acceptablePrice: the USD value of the min (for longs) or max (for shorts) index price acceptable when executing the request
_minOut: the min output token amount
_executionFee: can be set to PositionRouter.minExecutionFee
_withdrawETH: only applicable if WETH will be withdrawn, the WETH will be unwrapped to ETH if this is set to true
_callbackTarget: an optional callback contract, this contract will be called on request execution or cancellation
After this transaction is sent a keeper will execute the request, the request will either be executed or cancelled
If the position cannot be decreased for reasons such as the _acceptablePrice not being fulfillable then the request will be cancelled and there will be no change to the position
_minOut can be zero if no swap is required
Note that if _withdrawETH
is true
then the position decrease request would send ETH to the receiver using receiver.send(amount)
, this has a limit of 2300 gas. If the receiver is a contract and the receive function invoked on the transfer requires more than 2300 gas, this call can fail which would cause the ETH to be left in the PositionRouter.
Set _withdrawETH
to false
instead to avoid this issue.
Positions List
A list of position details can be retrieved by calling Reader.getPositions with params:
_vault: the vault contract address
_account: the account of the user
_collateralTokens: an array of collateralTokens
_indexTokens: an array of indexTokens
_isLong: an array of whether the position is a long position
The returned positions will be in the order of the query, for example, given the following inputs:
_collateralTokens: [WBTC.address, WETH.address, USDC.address]
_indexTokens: [WBTC.address, WETH.address, WBTC.address]
_isLong: [true, true, false]
The position details would be returned for:
Long BTC position, positionIndex: 0
Long ETH position, positionIndex: 1
Short BTC position, positionIndex: 2
The returned array would be a list of values ordered by the positions:
size
position size in USD
value at: positionIndex * 9
collateral
position collateral in USD
value at: positionIndex * 9 + 1
averagePrice
average entry price of the position in USD
value at: positionIndex * 9 + 2
entryFundingRate
a snapshot of the cumulative funding rate at the time the position was entered
value at: positionIndex * 9 + 3
hasRealisedProfit
1 if the position has a positive realised profit, 0 otherwise
value at: positionIndex * 9 + 4
realisedPnl
the realised PnL for the position in USD
value at: positionIndex * 9 + 5
lastIncreasedTime
timestamp of the last time the position was increased
value at: positionIndex * 9 + 6
hasProfit
1 if the position is currently in profit, 0 otherwise
value at: positionIndex * 9 + 7
delta
amount of current profit or loss of the position in USD
value at: positionIndex * 9 + 8
Buying / Selling TLP
Buying and selling TLP can be done through the GlpRewardRouter.
To buy TLP, call mintAndStakeGlp with params:
_token: the token to buy TLP with
_amount: the amount of token to use for the purchase
_minUsdg: the minimum acceptable USD value of the TLP purchased
_minGlp: the minimum acceptable TLP amount
To sell TLP, call unstakeAndRedeemGlp with params:
_tokenOut: the token to sell TLP for
_glpAmount: the amount of TLP to sell
_minOut: the minimum acceptable amount of tokenOut to be received
_receiver: the address to send tokenOut to
Note that TLP can only be redeemed up to the reservedAmount, which is based on the amount of open interest, if the pool has been fully redeemed up to the reservedAmount then redeemers will need to wait for positions to close before further redemptions can be done, in this scenario the borrowing fee APR would be very high so liquidity providers will be incentivised to mint TLP and traders will be incentivised to close positions
TLP Price
The price of TLP can be retrieved using the getPrice(_maximise)
function of the GlpManager.
To get the price of TLP for buying TLP use
GlpManager.getPrice(true)
To get the price of TLP for selling TLP use
GlpManager.getPrice(false)
The price of TLP factors in the pending PnL of the open long and short positions.
If you are calculating the pending PnL for shorts manually please use the glpManager.shortsTracker.globalShortAveragePrices
value instead of the vault.globalShortAveragePrices
value.
Last updated