Change Log
2023-09-06
- Python SDK v0.8 release
- Network class was moved from
pyinjective.constant
topyinjective.core.network
- Configuration to use secure or insecure channels has been moved into the Network class
- The Composer can be created now by the AsyncClient, taking markets and tokens from the chain information instead of using the local configuration files
- Changed the cookies management logic. All cookies management is done now by Network
- Network class was moved from
2023-08-28
- Added IP rate limits documentation
Introduction
Welcome to Injective's documentation!
Here you can find a comprehensive overview of our protocol, as well as tutorials, guides and general resources for developers and API traders.
If you would like to ask any questions or be a part of our community, please join our Discord Group or Telegram Group. We have a dedicated channel in our Discord group for questions related to the API.
Clients
Python Client
Dependencies
Ubuntu
sudo apt install python3.X-dev autoconf automake build-essential libffi-dev libtool pkg-config
Fedora
sudo dnf install python3-devel autoconf automake gcc gcc-c++ libffi-devel libtool make pkgconfig
macOS
brew install autoconf automake libtool
Installation
Install injective-py from PyPI using pip
.
pip install injective-py
Reference
Markets and Tokens information
Example - Traditional Composer instantiation
from pyinjective.composer import Composer
from pyinjective.transaction import Transaction
from pyinjective.core.network import Network
network = Network.testnet()
composer = Composer(network=network.string())
Python SDK traditionally relied on local configuration files to get the list of available markets and tokens in each network (mainnet, testnet and devnet).
Since version 0.8 the SDK is able also to get the markets and tokens information directly from the chain data (through the Indexer process). The benefit of this approach is that it is not necessary to update the SDK version when a new market is created in the chain or a new token added.
- To use the markets and tokens information from the local configuration files, create the Composer instance in the traditional way
Example - Get the composer instance through the AsyncClient
from pyinjective.composer import Composer as ProtoMsgComposer
from pyinjective.async_client import AsyncClient
from pyinjective.transaction import Transaction
from pyinjective.core.network import Network
network = Network.testnet()
client = AsyncClient(network)
composer = await client.composer()
- To get the markets and tokens information directly from the chain, create the Composer instance through the AsyncClient
Golang Client
1. Create your own client repo and go.mod file
go mod init foo
2. Import SDK into go.mod
module foo
go 1.18
require ( github.com/InjectiveLabs/sdk-go v1.39.4 )
Consult the sdk-go repository to find the latest release and replace the version in your go.mod file. Version v1.39.4 is only an example and must be replaced with the newest release
3. Download the package
Download the package using go mod download
go mod download github.com/InjectiveLabs/sdk-go
Reference
Typescript Client
Installation
Install the @injectivelabs/sdk-ts
npm package using yarn
yarn add @injectivelabs/sdk-ts
Reference
For other languages
Currently Injective provides SDKs only for Go, Python and TypeScript. To interact with the nodes using a different language please connect directly using the gRPC proto objects. The compiled proto files for C++, C# and Rust can be found in InjectiveLabs/injective-proto
Overview
Injective is a DeFi focused layer-1 blockchain built for the next generation of decentralized derivatives exchanges. The Injective Chain is a Tendermint-based IBC-compatible blockchain which supports a decentralized orderbook-based DEX protocol and a trustless ERC-20 token bridge to the Ethereum blockchain.
It is the first decentralized exchange focused layer-1 blockchain for perpetual swaps, futures, and spot trading that unlocks the full potential of decentralized derivatives and borderless DeFi. Every component of the protocol has been built to be fully trustless, censorship-resistant, publicly verifiable, and front-running resistant.
By providing the unrestricted and unprecedented ability to express diverse views in decentralized financial markets, we strive to empower individuals with the ability to more efficiently allocate capital in our society.
Architecture Overview
Injective enables traders to create and trade on arbitrary spot and derivative markets. The entire process includes on-chain limit orderbook management, on-chain trade execution, on-chain order matching, on-chain transaction settlement, and on-chain trading incentive distribution through the logic codified by the Injective Chain's exchange module.
Architecturally there are two main services that traders should concern themselves with:
- The Injective Chain node (the Chain API)
- The Injective Exchange API
The trading lifecycle is as follows:
- First, traders cryptographically sign a transaction containing one or more order messages (e.g.
MsgBatchCreateDerivativeLimitOrders
,MsgCreateSpotMarketOrder
,MsgCancelDerivativeLimitOrder
, etc. ). - Then the transaction is broadcasted to an Injective Chain node.
- The transaction is then added to the mempool and becomes included in a block. More details on this process can be found here.
- The handler for each respective message is run. During handler execution, order cancel and liquidation messages are processed immediately, whereas order creation messages are added to a queue.
- At the end of the block, the batch auction process for order matching begins.
- First, the queued market orders are executed against the resting orderbook (which does NOT include the new orders from the current block) and are cleared at a uniform clearing price.
- Second, the queued limit orders are matched against each other and the resting orderbook to result in an uncrossed orderbook. Limit orders created in that block are cleared at a uniform clearing price while resting limit orders created in previous blocks are cleared at an equal or better price than their limit order price.
- The funds are settled accordingly, with positions being created for derivative trades and assets being swapped for spot trades.
- Events containing the trade and settlement information are emitted by the Chain.
- The Injective Exchange API backend indexes the events and pushes updates to all subscribed traders.
Key Differences To CEX
- All information is public which includes things like untriggered Stop/Take orders or pending orders in the mempool.
- The data stored on-chain is minimal for performance reasons and reflects only the current state; exchange dApps provide additional historical data as well as a user interface for traders through the Injective Exchange API backend.
- Usually a DEX has front-running issues, but those are mitigated at Injective through fast block times and FBA (Frequent Batch Auction).
- The order of execution is different. Any new exchange action is a new transaction and is not executed immediately. Instead, it is added to a queue (mempool) and executed once the block is committed. At the time of the block commit, all included transactions happen more or less instantly. Firstly, code that is inside the handler is executed in the transaction sequence which is decided by the miner. This is not a problem since the sequence does not affect matching prices due to FBA and thus fairness is guaranteed.
To summarize the sequence of state changes on the Injective Chain:
- Mempool: A queue of pending transactions.
- BeginBlocker: Code that is executed at the beginning of every block. We use it for certain maintenance tasks (details can be found in the exchange module documentation).
- Handler: Code that is executed when a transaction is included in a block.
- EndBlocker: Code that is executed at the end of every block. We use it to match orders, calculate changes in funds, and update positions.
Comparison to CEX
Centralized Exchange (CEX) | Decentralized Exchange (DEX) |
---|---|
Exchange Gateway | Injective Chain Handler |
Exchange Matching Engine | Injective Chain EndBlocker |
Exchange Trade Report | Injective Chain EndBlocker |
Co-location | Injective Node (Decentralized Validators) |
Frequent Batch Auction (FBA)
The goal is to further prevent any Front-Running in a decentralized setting. Most DEX's suffer from this as all information is public and traders can collude with miners or pay high gas fees enabling them to front-run any trades. We mitigate this by combining fast block times with a Frequent Batch Auction:
In any given block:
- Calculate one uniform clearing price for all market orders and execute them. For an example for the market order matching in FBA fashion, look here.
- Limit orders are combined with the resting orderbook and orders are matched as long as there is still negative spread. The limit orders are all matched at one uniform clearing price. For an example for the limit order matching in FBA fashion, look here.
Trading Fees and Gas
If you are a trader on existing centralized exchanges, you will be familiar with the concept of trading fees. Traders are charged a fee for each successful trade. However, for a DEX, there are additional gas costs that must be paid to the network. And luckily, the gas fee from trading on Injective is very minimal.
- If you are a trader using a DEX UI, you don't need to worry about gas costs because the exchange dApp will pay them for you. However, you will pay trading fees in full.
- If you are using the API, then you will need to pay the gas costs.
- The gas costs are currently minimal, 20K transactions will cost about 1 INJ.
- You can set the fee_recipient to your own wallet address to save 40% of all trading fees.
Note: trading from bank balances, which automatically uses the default subaccount 0, will cost roughly 15% more gas than trading from other subaccounts. API traders can use other subaccounts to trade to avoid the extra gas fees—read here for more information.
Mark Price Margin Requirement
Quantity = 2 BTC, InitialMarginRatio = 0.05
MarkPrice = $45,000, EntryPrice = $43,000
Margin ≥ 2 * 0.05 * $45,000 = $4,500
MarginLong ≥ max(2 * (0.05 * $45,000 - ($45,000 - $43,000)), $4,500)
MarginLong ≥ max($500, $4,500) = $4,500
MarginShort ≥ max(2 * (0.05 * $45,000 - ($43,000 - $45,000)), $4,500)
MarginShort ≥ max($8,500, $4,500) = $8,500
So in this case if the trader wanted to create a short position with
an entry price which essentially starts at a loss of $2,000 as
unrealized PNL, he would need to post at a minimum $8,500 as margin,
rather than the usual required $4,500.
You might be familiar with margin requirements on Centralized Exchanges. When creating a new position, it must fulfill the following requirement:
Margin >= InitialMarginRatio * Quantity * EntryPrice
For example in a market with maximally 20x leverage, your initial margin must be at least 0.05 of the order's notional (entryPrice * quantity
). On Injective additionally the margin must also fulfill the following mark price requirement:
Margin >= Quantity * (InitialMarginRatio * MarkPrice - PNL)
where PNL
is the expected profit and loss of the position if it was closed at the MarkPrice.
Liquidations
Long Position:
Quantity = 1 BTC, MaintenanceMarginRatio = 0.05
EntryPrice = $50,000, Margin = $5,000
Now the MarkPrice drops down to $47,300, which is below the liquidation price of $47,368.42 (when margin = $2,368.42, maintenance ratio ≈ .04999998).
The position is auto-closed via reduce-only order:
Sell order:
Quantity = 1 BTC, Price = $0, Margin = $0
Assuming it gets matched with a clearing price of 47,100:
Liquidation Payout = Position Margin + PNL = $5,000 - $2,900 = $2,100
Liquidator Profit = $2,100 * 0.5 = $1,050
Insurance Fund Profit = $2,100 * 0.5 = $1,050
When your position falls below the maintenance margin ratio, the position can and likely will be liquidated by anyone running the liquidator bot. You will loose your entire position and all funds remaining in the position. On-chain, a reduce-only market order of the same size as the position is automatically created. The market order will have a worst price defined as Infinity or 0, implying it will be matched at whatever prices are available in the order book.
One key difference is that the payout from executing the reduce-only market order will not go towards the position owner. Instead, half of the remaining funds are transferred to the liquidator bot and the other half is transferred to the insurance fund.
If the payout in the position was negative, i.e., the position's negative PNL was greater than its margin, then the insurance fund will cover the missing funds.
Note: liquidations are executed immediately in a block before any other order matching occurs.
Fee Discounts
Fee discounts are enabled by looking at the past trailing 30 day window. As long as you meet both conditions for a tier (volume traded AND staked amount), you will receive the respective discounts.
- Note that there is a caching mechanism in place which can take up to one day before being updated with a new tier.
- Negative maker fee markets are not eligible for discounts.
Funding Rate
The hourly funding rate on perpetual markets determines the percentage that traders on one side have to pay to the other side each hour. If the rate is positive, longs pay shorts. If the rate is negative, shorts pay longs. The further trade prices deviate from the mark price within the hour, the higher the funding rate will be up to a maximum of 0.0625% (1.5% per day).
Closing a Position
Suppose you have an open position:
- Direction = Long
- Margin = $5,000
- EntryPrice = $50,000
- Quantity = 0.5 BTC
You create a new vanilla order for
- Direction = Sell
- Margin = $10,000
- Price = $35,000
- Quantity = 0.75 BTC
which is fully matched. First, the position is fully closed:
- OrderMarginUsedForClosing = OrderMargin * CloseQuantity / OrderQuantity
- OrderMarginUsedForClosing = $10,000 * 0.5 / 0.75 = $6,667
The proportional closing order margin is then used for the payout:
- Payout = PNL + PositionMargin + OrderMarginUsedForClosing
- Payout = ($35,000-$50,000) * 0.5 + $5,000 + $6,667 = $4,167
And a new position is opened in the opposite direction:
- Direction = Short
- Margin = $3,333
- Price = $35,000
- Quantity = 0.25 BTC
There are two ways to close a position:
Closing via Reduce-Only Order
When you close a position via a reduce-only order, no additional margin is used from the order. All reduce-only orders have a margin of zero. In addition, reduce-only orders are only used to close positions, not to open new ones.
Closing via Vanilla Order
You can also close a position via vanilla orders. When a sell vanilla order is getting matched while you have an open Long position, the position will be closed at the price of the sell order. Depending on the size of the order and position, the position may be either
- partially closed
- fully closed
- or fully closed with subsequent opening of a new position in the opposite direction.
Note that how the margin inside the order is used depends on which of the three scenarios you are in. If you close a position via vanilla order, the margin is only used to cover PNL payouts, not to go into the position. If the order subsequently opens a new position in the opposite direction (scenario 3), the remaining proportional margin will go towards the new position.
Trading Rewards
Assume you have a trading rewards campaign with 100 INJ as rewards:
Reward Tokens: 100 INJ
Trader Reward Points = 100
Total Reward Points = 1,000
Trader Rewards = Trader Reward Points / Total Reward Points * Reward Tokens
Trader Rewards = 100 / 1,000 * 100 INJ = 10 INJ
During a given campaign, the exchange will record each trader's cumulative trading reward points obtained from trading fees (with boosts applied, if applicable) from all eligible markets. At the end of each campaign each trader will receive a pro-rata percentage of the trading rewards pool based off their trading rewards points from that campaign epoch. Those rewards will be automatically deposited into the trader's respective wallets, it's not necessary to manually withdraw them.
Reduce-Only Order Precedence
Imagine a trader has the following position:
- LONG:
1 BTC
with EntryPrice of $59,000
And the following SELL orders:
Buy Price | Quantity | Order Type |
---|---|---|
$66,500 | 0.2 BTC | Vanilla |
$65,500 | 0.1 BTC | Reduce-only |
$65,400 | 0.1 BTC | Vanilla |
$64,500 | 0.3 BTC | Vanilla |
$63,500 | 0.1 BTC | Reduce-only |
This has some implications when placing new orders.
Upon placing a reduce-only order
- If any reduce-only orders would be invalid after executing all of the trader's other limit sell orders that have better prices in the same direction.
In our example, consider a new reduce-only order of 0.4 BTC
at $64,600
.
Sell Price | Quantity | Order Type |
---|---|---|
$66,500 | 0.2 BTC | Vanilla |
$65,500 | 0.1 BTC | Reduce-only |
$65,400 | 0.1 BTC | Vanilla |
$64,600 | 0.4 BTC | Reduce-only |
$64,500 | 0.3 BTC | Vanilla |
$63,500 | 0.1 BTC | Reduce-only |
This is perfectly valid and no further action is required. If the buy price hit $65,500 and all limit sell orders less than or equal to that price were filled, then the long position would be closed. If the price hit $66,500 and the vanilla sell order was filled, then the trader would open a 0.2 BTC short position. But what if the reduce-only order was for 0.5 BTC
instead?
Sell Price | Quantity | Order Type |
---|---|---|
$66,500 | 0.2 BTC | Vanilla |
$65,500 | 0.1 BTC | Reduce-only |
$65,400 | 0.1 BTC | Vanilla |
$64,600 | 0.4 BTC | Reduce-only |
$64,500 | 0.3 BTC | Vanilla |
$63,500 | 0.1 BTC | Reduce-only |
If the orders are getting matched, once the last vanilla order of 0.1 BTC at $65,400 is filled, the position will have been reduced to 1 BTC - 0.1 BTC - 0.3 BTC - 0.5 BTC - 0.1 BTC = 0 BTC
. The next reduce-only order of 0.1 BTC at $65,500 will thus be invalid.
To prevent that, we automatically cancel all reduce-only orders at a price where the cumulative sum of orders up to and including the reduce-only order would add up to more than the trader’s current long amount. Another way to think about it: we find the reduce-only order with the highest price such that all orders (vanilla and reduce-only) including and below that price add up in quantity to less than the long quantity. All reduce-only orders above that price will be canceled so that no reduce-only orders exist when the position is closed or short. The same concept applies to reduce-only orders on short positions, but we look for the lowest price instead of the highest on buy orders so that no reduce-only orders exist when the position is closed or long.
Upon placing a vanilla limit order
- We check if any reduce-only limit orders would be invalidated if all the orders up to and including the new vanilla limit order were filled.
In our example, consider a new vanilla order of 0.4 BTC
at $64,600
.
Sell Price | Quantity | Order Type |
---|---|---|
$66,500 | 0.2 BTC | Vanilla |
$65,500 | 0.1 BTC | Reduce-only |
$65,400 | 0.1 BTC | Vanilla |
$64,600 | 0.4 BTC | Vanilla |
$64,500 | 0.3 BTC | Vanilla |
$63,500 | 0.1 BTC | Reduce-only |
Again this perfectly valid and no further action is required because all order quantities up to the highest priced reduce-only order add up to ≤ the long position quantity. But what if the order was for 0.5 BTC
instead?
Sell Price | Quantity | Order Type |
---|---|---|
$66,500 | 0.2 BTC | Vanilla |
$65,500 | 0.1 BTC | Reduce-only |
$65,400 | 0.1 BTC | Vanilla |
$64,600 | 0.5 BTC | Vanilla |
$64,500 | 0.3 BTC | Vanilla |
$63,500 | 0.1 BTC | Reduce-only |
If the orders are getting matched, once the last reduce-only order of $65,500 is reached, the position will have been reduced to 1 BTC - 0.1 BTC - 0.3 BTC - 0.5 BTC - 0.1 BTC = 0 BTC
. A reduce-only order of 0.1 BTC after that will thus be invalid.
To prevent this, we automatically cancel the existing 0.1 BTC reduce-only order. In other words, new vanilla limit orders can invalidate and auto-cancel existing reduce-only limit orders if the reduce-only order becomes invalid at its price.
Rate Limits
The public mainnet and testnet nodes have a request rate limit associated to the requester IP address. The limits are:
- 20 requests/second for the "chain" group
- 50 requests/second for the "indexer" group
Each endpoint's section in this document clarifies which group the endpoint belongs to. When the limit is reached the server will respond sending an error response with code 429.
Market and Limit Order Examples
Adding a Spot Market Buy Order
Maker Fee = -0.01%
Taker Fee = 0.1%
Market Buy Order:
Quantity = 1,000 INJ
Worst Price = 5 USDT
→ The account's available balance is decremented by 5,000 USDT + Taker Fee = 5,005 USDT
.
Upon matching with a resting sell order with price of 4 USDT
the new account balances are calculated as:
Trading Fee = 1,000 * 4 * 0.001 = 4 USDT
Credit Amount = 1,000 INJ
Debit Amount = 1,000 * 4 + 4 = 4,004 USDT
Clearing Refund = 5,005 - 4,004 = 1,001 USDT
Adding a Spot Market Sell Order
Maker Fee = -0.01%
Taker Fee = 0.1%
Market Sell Order:
Quantity = 1,000 INJ
Worst Price = 3 USDT
→ The account's available balance is decremented by 1,000 INJ
.
Upon matching with a resting sell order with price of 4 USDT
the new account balances are calculated as:
Trading Fee = 1,000 * 4 * 0.001 = 4 USDT
Debit Amount = 1,000 INJ
Credit Amount = 1,000 * 4 - 4 = 3,996 USDT
Clearing Refund = 0
Adding a Spot Limit Buy Order
Maker Fee = -0.01%
Taker Fee = 0.1%
We initially assume taker fees for the limit order in case the limit order is matched immediately. With price and quantity of:
Quantity = 1,000 INJ
Price = 5 USDT
→ The account's available balance is decremented by 5,000 USDT + Taker Fee = 5,005 USDT
.
After the order is submitted:
- If Matched Immediately: the limit order is filled and no fees are refunded since taker fees were previously deducted from the account's available balance. However, if Post-Only was selected, then the order will not be matched and will be rejected, with the trading fees being refunded. Assuming a clearing price of 4 USDT and a non Post-Only order:
Trading Fee = 1,000 * 4 * 0.001 = 4 USDT
Credit Amount = 5,000 - 4,000 = 1,000 INJ
Debit Amount = 1,000 * 4 + 4 = 4,004 USDT
Clearing Refund = 5,005 - 4,004 = 1,001 USDT
Unmatched Fee Refund = 0 USDT
- If Entirely Unmatched, the order becomes a resting limit order and we refund the taker fee:
Fee Refund = 1,000 * 5 * (0.001) = 5 USDT
- If Filled Later by Market Order, a maker fee will be charged, or a rebate will be credited. Since the order is filled by Market Order, the clearing price will be the price set in the limit order:
Trading Fee Rebate = 1,000 * 5 * -0.0001 = 0.5 USDT
Credit Amount = 1,000 INJ + 0.5 USDT
Debit Amount (in quote asset) = 1,000 * 5 = 5,000 USDT
If Partially Matched Immediately: the portion of the limit order that is filled immediately is charged taker fees with the rest being charged/credited maker fees/rebates. Assuming half the order is matched at a clearing price of 4 USDT and half the order is filled by Market Order at 5 USDT:
- Portion Immediately Filled:
Taker Trading Fee = 500 * 4 * 0.001 = 2 USDT
Credit Amount = 500 INJ
Debit Amount (Including Fees) = 500 * 4 + 2 = 2,002 USDT
Clearing Refund = (quantity of order filled * limit price) - (quantity of order filled * clearing price) + (proportional difference between limit fees and clearing fees)= (500 * 5) - (500 * 4) + ((500 * 5) * 0.001 - (500 * 4) * 0.001) = 500.5 USDT
Unmatched Fee Refund = quantity of order unfilled * limit price * taker fee rate = 500 * 5 * 0.001 = 2.5 USDT
- Rest of Order Filled Later by Market Order:
Maker Trading Fee Rebate = 500 * 5 * -0.0001 = 0.25 USDT
Credit Amount = 500 INJ
Debit Amount = 500 * 5 = 2,500 USDT
Clearing Refund = 0 USDT
- In Total:
Net Trading Fee = 2 - 0.25 = 1.75 USDT
Credit Amount (Including Maker Fee Rebates) = 1000 INJ + 0.25 USDT
Debit Amount (Including Taker Fees) = 4,502 USDT
- Portion Immediately Filled:
Adding a Spot Limit Sell Order
Maker Fee = -0.01%
Taker Fee = 0.1%
We initially assume taker fees for the limit order in case the limit order is matched immediately. With price and quantity of:
Quantity = 1,000 INJ
Price = 3 USDT
→ The account's available balance is decremented by 1,000 INJ
.
After the order is submitted:
- If Matched Immediately: the limit order is filled and taker fees are deducted, unless Post-Only is selected, in which case the order will not be matched and will be rejected with no trading fees being charged. Assuming a clearing price of 4 USDT:
Trading Fee = 1,000 * 4 * 0.001 = 4 USDT
Credit Amount = 1,000 * 4 - 4 = 3,996 USDT
Debit Amount = 1,000 INJ
Clearing Refund = 0 ETH
Fee Refund/Rebate = 0 USDT
- If Filled Later by Market Order, a maker fee rebate will be credited. Since the order is filled by Market Order, the clearing price will be the price set in the limit order:
Maker Trading Rebate = 1,000 * 3 * 0.0001 = 0.3 USDT
Credit Amount (in quote asset) = 1,000 * 3 + 0.3 = 3,000.3 USDT
Debit Amount (in base asset) = 1,000 INJ
- If Partially Matched Immediately: the portion of the limit order that is filled immediately is charged taker fees with the rest being charged maker fees. Similar logic to a spot limit buy order applies.
Derivative Market Order Payouts
The payouts for derivative market orders work the same way as for derivative limit orders, with the one difference being they are cancelled if not immediately matched. See spot market and derivative limit orders as reference.
Adding a Derivative Limit Buy Order
Quantity = 1,000 INJ
,Price = 5 USDT
,Margin = 1,000 USDT
TakerFeeRate = 0.001
MakerFeeRate = -0.0001
→ The account's available balance is decremented by Margin + Taker Fee = 1000 + 5000 * 0.001 = 1005 USDT
.
After creation:
If Unmatched, the order becomes a resting limit order (maker) and we refund the taker fee on vanilla orders (reduce-only orders don't pay upfront fees):
Fee Refund = 5 USDT
If Matched:
Assuming:
- a clearing price of 4 USDT
an existing
SHORT
position:Position Quantity = 600 INJ
Position Entry Price = 4.5 USDT
Position Margin = 400 USDT
Would result in:
1. Closing existing position with proportional order margin for closing:
CloseExecutionMargin = ExecutionMargin * CloseQuantity / OrderQuantity = 1000 * 600 / 1000 = 600 USDT
- Where
CloseExecutionMargin = Portion of margin used to close position
- And
ExecutionMargin = Margin supplied in new order
- Where
ClosingPayout = PNL + PositionMargin * CloseQuantity / PositionQuantity + CloseExecutionMargin
Short PNL = CloseQuantity * (EntryPrice - FillPrice) = 600 * (4.5 - 4) = 300 USDT
ClosingPayout = 300 + 400 * 600 / 600 + 600 = 1300 USDT
2. Opening new position in opposite direction:
a new
LONG
position:Position Quantity = 400 INJ
Position Entry Price = 4 USDT
NewPositionMargin = ExecutionMargin - CloseExecutionMargin = 1000 - 600 = 400 USDT
3. Refunding margin difference from order price vs. clearing price:
- Since the order was placed with 5x leverage at a price of 5 USDT, some margin is refunded with the new clearing price to maintain the 5x leverage.
Margin Refund = NewPositionMargin - NewPositionMarginRequired = 400 - 400 * 4 / 5 = 80 USDT
4. Refunding fee difference from order price vs. clearing price:
PriceDelta = Price - ClearingPrice = 5 - 4 = 1 USDT
ClearingFeeRefund = FillQuantity * PriceDelta * TakerFeeRate = 1000 * 1 * 0.001 = 1 USDT
- In the case of matching a sell order, this would have been a charge, not a refund
Market Order Matching
Existing Orderbook
Sells | Buys | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
New Orders
- 1x market buy order for 0.2 BTC with worst price 64,360
- 1x market buy order for 0.4 BTC with worst price 66,000
- 1x market sell order for 0.1 BTC with worst price 60,000
- 1x market sell order for 0.2 BTC with worst price 61,000
- 1x market sell order for 0.3 BTC with worst price 69,000
Resulting Orderbook
Sells | Buys | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
Market Buys: Matching the highest priced market buy order first for 0.4 BTC. Now for the second market buy order only 0.1 BTC is left at matchable price, meaning the other 0.1 BTC in the order will be cancelled. Both orders will be matched with the single resting limit order at a price of 64,360 for a total quantity of 0.5 BTC.
Market Sells: Matching the first two market sell orders for at a matching price of (64,210*0.1 + 64,205*0.2) / 0.3 = 64,206.67
for a total quantity of 0.3 BTC. The resting limit orders are both matched at their specified price points of 64,210 and 64,205. Since the last market sell order of 69,000 cannot be fulfilled, it is cancelled.
Limit Order Matching
Existing Orderbook
Sells | Buys | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
New Orders
Sells | Buys | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
Matching Orders
All new orders are incorporated into the existing orderbook. In our case this results in a negative spread:
Sells | Buys | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
As long as negative spread exists, orders are matched against each other. The first buy order is fully matched:
Sells | Buys | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
Now the second buy order can still be fully matched:
Sells | Buys | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
This is the end of the matching, since no more negative spread exists (64,220 > 62,210
).
All orders will be matched with a uniform clearing price within the range of the last sell order price and the last buy order price.
- Last sell order price: 64,220
- Last buy order price: 64,360
- 64,220 >= Clearing price >= 64,360
Step 1: Check if clearing price range is out of bounds regarding the resting orderbook mid price.
- Resting orderbook mid price: (64,250+64,210)/2 = 64,230
- Is within range of clearing price ✅ (if not, a clearing price of either last buy or last sell price would be used)
Step 2: Check if clearing price range is out of bounds regarding the mark price.
- Let's assume mark price is 64,300
- Is within range of clearing price ✅ (if not, a clearing price of either last buy or last sell price would be used)
Step 3: Set clearing price = mid price or mark price for spot or perpetual markets, respectively, or in the case where these prices are out of bounds, use last buy or last sell price.
Resources
Here you can find a comprehensive overview of the exchange ecosystem on Injective, guides and general resources for developers and API traders.
Coin denoms and market IDs for testnet and mainnet can be found here under denoms_testnet.ini and denoms_mainnet.ini, respectively. This information can also be found on the Injective testnet explorer and mainnet explorer under the Markets tab and Assets tab.
Explorer
A Web interface that allows you to search for information on the Injective Chain
Faucet
A web-based service that provides free tokens to users on testnet and allows them to experiment on the Injective Chain.
Status
Monitor the uptime of all public services.
Message Broadcaster
In the examples included in this documentation you will see all the steps required to interact with the chain, from deriving a public key from a private key, creating messages to query the chain or creating orders, to creating and broadcasting transactions to the chain. Before going to the examples of all the possible actions it is important to state that you can avoid implementing yourself all the steps to create and configure correctly a transaction. If you are not interested in defining all the low level aspects you can use the component called MsgBroadcasterWithPk. To use the broadcaster you just need to create an instance of MsgBroadcasterWithPk, and once all the messages to be included in the transaction have been created, use the broadcast method, passing the messages as a parameter. The broadcaster will take care of: - Calculate the gas fee to pay for the transaction - Create the transaction and configure it - Sign the transaction - Broadcast it to the chain
Broadcaster for standard account
Calculate gas fee simulating the transaction
Example - Calculate gas fee simulating the transaction:
import asyncio
from pyinjective.composer import Composer as ProtoMsgComposer
from pyinjective.core.broadcaster import MsgBroadcasterWithPk
from pyinjective.core.network import Network
from pyinjective.wallet import PrivateKey
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
composer = ProtoMsgComposer(network=network.string())
private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3"
message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
network=network,
private_key=private_key_in_hexa,
use_secure_connection=True
)
priv_key = PrivateKey.from_hex(private_key_in_hexa)
pub_key = priv_key.to_public_key()
address = pub_key.to_address()
subaccount_id = address.get_subaccount_id(index=0)
# prepare trade info
fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
spot_market_id_create = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
spot_orders_to_create = [
composer.SpotOrder(
market_id=spot_market_id_create,
subaccount_id=subaccount_id,
fee_recipient=fee_recipient,
price=3,
quantity=55,
is_buy=True,
is_po=False
),
composer.SpotOrder(
market_id=spot_market_id_create,
subaccount_id=subaccount_id,
fee_recipient=fee_recipient,
price=300,
quantity=55,
is_buy=False,
is_po=False
),
]
# prepare tx msg
msg = composer.MsgBatchUpdateOrders(
sender=address.to_acc_bech32(),
spot_orders_to_create=spot_orders_to_create,
)
# broadcast the transaction
result = await message_broadcaster.broadcast([msg])
print("---Transaction Response---")
print(result)
if __name__ == "__main__":
asyncio.get_event_loop().run_until_complete(main())
For the broadcaster to calculate the gas fee running the simulation, create an instance of MsgBroadcasterWithPk
with the message new_using_simulation
.
This is the most common broadcaster configuration. Unless you are using grantee accounts (delegated accounts with authz) you should use this one.
Calculate gas fee without simulation
Example - Calculate gas fee without simulation:
import asyncio
from pyinjective.composer import Composer as ProtoMsgComposer
from pyinjective.core.broadcaster import MsgBroadcasterWithPk
from pyinjective.core.network import Network
from pyinjective.wallet import PrivateKey
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
composer = ProtoMsgComposer(network=network.string())
private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3"
message_broadcaster = MsgBroadcasterWithPk.new_without_simulation(
network=network,
private_key=private_key_in_hexa,
use_secure_connection=True
)
priv_key = PrivateKey.from_hex(private_key_in_hexa)
pub_key = priv_key.to_public_key()
address = pub_key.to_address()
subaccount_id = address.get_subaccount_id(index=0)
# prepare trade info
fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
spot_market_id_create = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
spot_orders_to_create = [
composer.SpotOrder(
market_id=spot_market_id_create,
subaccount_id=subaccount_id,
fee_recipient=fee_recipient,
price=3,
quantity=55,
is_buy=True,
is_po=False
),
composer.SpotOrder(
market_id=spot_market_id_create,
subaccount_id=subaccount_id,
fee_recipient=fee_recipient,
price=300,
quantity=55,
is_buy=False,
is_po=False
),
]
# prepare tx msg
msg = composer.MsgBatchUpdateOrders(
sender=address.to_acc_bech32(),
spot_orders_to_create=spot_orders_to_create,
)
# broadcast the transaction
result = await message_broadcaster.broadcast([msg])
print("---Transaction Response---")
print(result)
if __name__ == "__main__":
asyncio.get_event_loop().run_until_complete(main())
For the broadcaster to calculate the gas fee based on the messages included without running the simulation, create an instance of MsgBroadcasterWithPk
with the message new_without_simulation
.
Broadcaster for grantee account
This is the required broadcaster configuration when operating with grantee accounts. The broadcaster will take care of creating the MsgExec
message, so that the user keeps passing the same messages to the broadcast
method that are passed when using the standard broadcaster with non-grantee accounts.
Calculate gas fee simulating the transaction
Example - Calculate gas fee simulating the transaction:
import asyncio
from pyinjective.composer import Composer as ProtoMsgComposer
from pyinjective.async_client import AsyncClient
from pyinjective.core.broadcaster import MsgBroadcasterWithPk
from pyinjective.core.network import Network
from pyinjective.wallet import PrivateKey, Address
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
composer = ProtoMsgComposer(network=network.string())
# initialize grpc client
client = AsyncClient(network)
await client.sync_timeout_height()
# load account
private_key_in_hexa = "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e"
priv_key = PrivateKey.from_hex(private_key_in_hexa)
pub_key = priv_key.to_public_key()
address = pub_key.to_address()
message_broadcaster = MsgBroadcasterWithPk.new_for_grantee_account_using_simulation(
network=network,
grantee_private_key=private_key_in_hexa,
use_secure_connection=True
)
# prepare tx msg
market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
granter_inj_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
granter_address = Address.from_acc_bech32(granter_inj_address)
granter_subaccount_id = granter_address.get_subaccount_id(index=0)
msg = composer.MsgCreateSpotLimitOrder(
sender=granter_inj_address,
market_id=market_id,
subaccount_id=granter_subaccount_id,
fee_recipient=address.to_acc_bech32(),
price=7.523,
quantity=0.01,
is_buy=True,
is_po=False
)
# broadcast the transaction
result = await message_broadcaster.broadcast([msg])
print("---Transaction Response---")
print(result)
if __name__ == "__main__":
asyncio.get_event_loop().run_until_complete(main())
For the broadcaster to calculate the gas fee running the simulation, create an instance of MsgBroadcasterWithPk
with the message new_for_grantee_account_using_simulation
.
Calculate gas fee without simulation
Example - Calculate gas fee without simulation:
import asyncio
from pyinjective.composer import Composer as ProtoMsgComposer
from pyinjective.async_client import AsyncClient
from pyinjective.core.broadcaster import MsgBroadcasterWithPk
from pyinjective.core.network import Network
from pyinjective.wallet import PrivateKey, Address
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
composer = ProtoMsgComposer(network=network.string())
# initialize grpc client
client = AsyncClient(network)
await client.sync_timeout_height()
# load account
private_key_in_hexa = "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e"
priv_key = PrivateKey.from_hex(private_key_in_hexa)
pub_key = priv_key.to_public_key()
address = pub_key.to_address()
message_broadcaster = MsgBroadcasterWithPk.new_for_grantee_account_without_simulation(
network=network,
grantee_private_key=private_key_in_hexa,
use_secure_connection=True
)
# prepare tx msg
market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
granter_inj_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
granter_address = Address.from_acc_bech32(granter_inj_address)
granter_subaccount_id = granter_address.get_subaccount_id(index=0)
msg = composer.MsgCreateSpotLimitOrder(
sender=granter_inj_address,
market_id=market_id,
subaccount_id=granter_subaccount_id,
fee_recipient=address.to_acc_bech32(),
price=7.523,
quantity=0.01,
is_buy=True,
is_po=False
)
# broadcast the transaction
result = await message_broadcaster.broadcast([msg])
print("---Transaction Response---")
print(result)
if __name__ == "__main__":
asyncio.get_event_loop().run_until_complete(main())
For the broadcaster to calculate the gas fee based on the messages included without running the simulation, create an instance of MsgBroadcasterWithPk
with the message new_for_grantee_account_without_simulation
.
NOTE:
There an important consideration when using the Transaction Broadcaster calculating the gas cost without simulation to send a MsgBatchUpdateOrders message.
The logic that estimates the gas cost for the MsgBatchUpdateOrders correclty calculates the gas required for each order action (creation or cancelation) it includes. But there is no easy way to calculate the gas cost when canceling all orders for a market id using one of the following parameters: spot_market_ids_to_cancel_all
, derivative_market_ids_to_cancel_all
or binary_options_market_ids_to_cancel_all
. The complexity is related to the fact that the gas cost depends on the number of orders to be cancelled.
By default the estimation logic calculates a gas cost considering the number of orders to cancel for each market id is 20.
To improve the gas cost calculation when using the MsgBatchUpdateOrders message to cancel all orders for one or more markets you can change the number of estimated orders to cancel per market running the following command:
BatchUpdateOrdersGasLimitEstimator.AVERAGE_CANCEL_ALL_AFFECTED_ORDERS = 30
Indexer API
The Indexer API is read-only whereas the Chain API is write and also includes a limited set of API requests to read data. The Chain API reads query the blockchain state from the node directly as opposed to the Indexer API which reconstructs state from events emitted by chain.
On a high-level the end-user trading applications and Injective Products use the Indexer API to read data and the Chain API to write data to the blockchain. Even though it’s possible to develop trading applications using the Chain API only, the Indexer API includes more methods, streaming support, gRPC, and also allows you to fetch historical data (the Chain API queries the blockchain state which doesn’t include historical records).
- InjectiveAccountsRPC
InjectiveAccountsRPC defines the gRPC API of the Exchange Accounts provider.
SubaccountsList
Get a list of subaccounts for a specific address.
IP rate limit group: indexer
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
client = AsyncClient(network)
account_address = "inj1clw20s2uxeyxtam6f7m84vgae92s9eh7vygagt"
subacc_list = await client.get_subaccount_list(account_address)
print(subacc_list)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
panic(err)
}
ctx := context.Background()
accountAddress := "inj1clw20s2uxeyxtam6f7m84vgae92s9eh7vygagt"
res, err := exchangeClient.GetSubaccountsList(ctx, accountAddress)
if err != nil {
fmt.Println(err)
}
str, _ := json.MarshalIndent(res, "", " ")
fmt.Print(string(str))
}
import { IndexerGrpcAccountApi } from "@injectivelabs/sdk-ts";
import { getNetworkEndpoints, Network } from "@injectivelabs/networks";
(async () => {
const endpoints = getNetworkEndpoints(Network.TestnetK8s);
const indexerGrpcAccountApi = new IndexerGrpcAccountApi(endpoints.indexer);
const injectiveAddress = "inj10y4mpwgqr4c63m7t8spxhf8rgcy2dz5vt3mvk9";
const subaccountsList = await indexerGrpcAccountApi.fetchSubaccountsList(
injectiveAddress
);
console.log(subaccountsList);
})();
Parameter | Type | Description | Required |
---|---|---|---|
account_address | String | The Injective Chain address | Yes |
Response Parameters
Response Example:
subaccounts: "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001"
subaccounts: "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000002"
{
"subaccounts": [
"0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001",
"0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000002"
]
}
[
'0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001',
'0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000002',
'0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000000'
]
Parameter | Type | Description |
---|---|---|
subaccounts | String Array | List of subaccounts, including default and all funded accounts |
SubaccountHistory
Get the subaccount's transfer history.
IP rate limit group: indexer
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
network = Network.testnet()
client = AsyncClient(network)
subaccount = "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
denom = "inj"
transfer_types = ["withdraw", "deposit"]
skip = 1
limit = 15
end_time = 1665118340224
subacc_history = await client.get_subaccount_history(
subaccount_id=subaccount,
denom=denom,
transfer_types=transfer_types,
skip=skip,
limit=limit,
end_time=end_time
)
print(subacc_history)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
accountPB "github.com/InjectiveLabs/sdk-go/exchange/accounts_rpc/pb"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
panic(err)
}
ctx := context.Background()
denom := "inj"
subaccountId := "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
transferTypes := []string{"deposit"}
skip := uint64(0)
limit := int32(10)
req := accountPB.SubaccountHistoryRequest{
Denom: denom,
SubaccountId: subaccountId,
TransferTypes: transferTypes,
Skip: skip,
Limit: limit,
}
res, err := exchangeClient.GetSubaccountHistory(ctx, req)
if err != nil {
fmt.Println(err)
}
str, _ := json.MarshalIndent(res, "", " ")
fmt.Print(string(str))
}
import { PaginationOption, IndexerGrpcAccountApi } from '@injectivelabs/sdk-ts'
import { getNetworkEndpoints, Network } from '@injectivelabs/networks'
(async () => {
const endpoints = getNetworkEndpoints(Network.TestnetK8s)
const indexerGrpcAccountApi = new IndexerGrpcAccountApi(endpoints.indexer)
const subaccountId = '0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000'
const denom = 'inj'
const pagination = {} as PaginationOption
const subaccountHistory = await indexerGrpcAccountApi.fetchSubaccountHistory({
subaccountId,
denom,
pagination /* optional param */
})
console.log(subaccountHistory)
})();
Parameter | Type | Description | Required |
---|---|---|---|
subaccount_id | String | Filter by subaccount ID | Yes |
denom | String | Filter by denom | No |
transfer_types | String Array | Filter by transfer types. Valid options: [“internal”, “external”, withdraw”, “deposit”] | No |
skip | Integer | Skip the last n transfers, you can use this to fetch all transfers since the API caps at 100. Note: The end_time filter takes precedence over skip; any skips will use the filtered results from end_time | No |
limit | Integer | Max number of items to be returned | No |
end_time | Integer | Upper bound (inclusive) of account transfer history executed_at unix timestamp | No |
Response Parameters
Response Example:
transfers {
transfer_type: "deposit"
src_account_address: "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku"
dst_subaccount_id: "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
amount {
denom: "inj"
amount: "2000000000000000000"
}
executed_at: 1665117493543
}
transfers {
transfer_type: "deposit"
src_account_address: "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku"
dst_subaccount_id: "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
amount {
denom: "inj"
amount: "15000000000000000000"
}
executed_at: 1660313668990
}
paging {
total: 3
}
{
"transfers": [
{
"transfer_type": "deposit",
"src_account_address": "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
"dst_subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"amount": {
"denom": "inj",
"amount": "50000000000000000000"
},
"executed_at": 1651492257605
},
{
"transfer_type": "deposit",
"src_account_address": "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
"dst_subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"amount": {
"denom": "inj",
"amount": "1000000000000000000"
},
"executed_at": 1652453978939
}
],
"paging": [
{
"total": 3
}
]
}
{
transfers: [
{
transferType: 'withdraw',
srcSubaccountId: '0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000',
srcSubaccountAddress: '',
dstSubaccountId: '',
dstSubaccountAddress: 'inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku',
executedAt: 1676518649359,
amount: {
amount: '10000000000000000000',
denom: 'inj',
}
},
{
transferType: 'deposit',
srcSubaccountId: '',
srcSubaccountAddress: 'inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku',
dstSubaccountId: '0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000',
dstSubaccountAddress: '',
executedAt: 1676518457766,
amount: {
amount: '10000000000000000000',
denom: 'inj',
}
}
...
],
pagination: { total: 15, from: 0, to: 0, countBySubaccount: '0' }
}
Parameter | Type | Description |
---|---|---|
transfers | SubaccountBalanceTransfer | List of subaccount transfers |
paging | Paging | Pagination of results |
SubaccountBalanceTransfer
Parameter | Type | Description |
---|---|---|
amount | CosmosCoin | CosmosCoin |
dst_account_address | String | Account address of the receiving side |
executed_at | Integer | Timestamp of the transfer in UNIX millis |
src_subaccount_id | String | Subaccount ID of the sending side |
transfer_type | String | Type of the subaccount balance transfer. Valid options: ["internal", "external", "withdraw", "deposit"] |
CosmosCoin
Parameter | Type | Description |
---|---|---|
amount | String | Coin amount |
denom | String | Coin denominator |
Paging
Parameter | Type | Description |
---|---|---|
total | Integer | Total number of available records |
SubaccountBalance
Get the balance of a subaccount for a specific denom.
IP rate limit group: indexer
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
client = AsyncClient(network)
subaccount_id = "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
denom = "inj"
balance = await client.get_subaccount_balance(
subaccount_id=subaccount_id,
denom=denom
)
print(balance)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
panic(err)
}
ctx := context.Background()
subaccountId := "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
denom := "inj"
res, err := exchangeClient.GetSubaccountBalance(ctx, subaccountId, denom)
if err != nil {
fmt.Println(err)
}
str, _ := json.MarshalIndent(res, "", " ")
fmt.Print(string(str))
}
import { IndexerGrpcAccountApi } from "@injectivelabs/sdk-ts";
import { getNetworkEndpoints, Network } from "@injectivelabs/networks";
(async () => {
const endpoints = getNetworkEndpoints(Network.TestnetK8s);
const indexerGrpcAccountApi = new IndexerGrpcAccountApi(endpoints.indexer);
const subaccountId =
"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000";
const denom = "inj";
const subaccountBalance = await indexerGrpcAccountApi.fetchSubaccountBalance(
subaccountId,
denom
);
console.log(subaccountBalance);
})();
Parameter | Type | Description | Required |
---|---|---|---|
subaccount_id | String | Filter by subaccount ID | Yes |
denom | String | Filter by denom | Yes |
Response Parameters
Response Example:
balance {
subaccount_id: "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
account_address: "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku"
denom: "inj"
deposit {
total_balance: "1492235700000000000000"
available_balance: "1492235700000000000000"
}
}
{
"balance": {
"subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"account_address": "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
"denom": "inj",
"deposit": {
"total_balance": "1492235700000000000000",
"available_balance": "1492235700000000000000"
}
}
}
{
subaccountId: '0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000',
accountAddress: 'inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku',
denom: 'inj',
deposit: { totalBalance: '334000000000000000000', availableBalance: '0' }
}
Parameter | Type | Description |
---|---|---|
balance | SubaccountBalance | SubaccountBalance object |
SubaccountBalance
Parameter | Type | Description |
---|---|---|
denom | String | Coin denom on the chain |
deposit | SubaccountDeposit | SubaccountDeposit object |
subaccount_id | String | ID of the subaccount |
account_address | String | The Injective Chain address that owns the subaccount |
SubaccountDeposit
Parameter | Type | Description |
---|---|---|
available_balance | String | The available balance for a denom (taking active orders into account) |
total_balance | String | The total balance for a denom (balance if all active orders were cancelled) |
SubaccountBalancesList
List the subaccount's balances for all denoms.
IP rate limit group: indexer
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
network = Network.testnet()
client = AsyncClient(network)
subaccount = "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
denoms = ["inj", "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"]
subacc_balances_list = await client.get_subaccount_balances_list(
subaccount_id=subaccount,
denoms=denoms
)
print(subacc_balances_list)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
panic(err)
}
ctx := context.Background()
subaccountId := "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
res, err := exchangeClient.GetSubaccountBalancesList(ctx, subaccountId)
if err != nil {
fmt.Println(err)
}
str, _ := json.MarshalIndent(res, "", " ")
fmt.Print(string(str))
}
import { IndexerGrpcAccountApi } from "@injectivelabs/sdk-ts";
import { getNetworkEndpoints, Network } from "@injectivelabs/networks";
(async () => {
const endpoints = getNetworkEndpoints(Network.TestnetK8s);
const indexerGrpcAccountApi = new IndexerGrpcAccountApi(endpoints.indexer);
const subaccountId =
"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000";
const subaccountBalanceList =
await indexerGrpcAccountApi.fetchSubaccountBalancesList(subaccountId);
console.log(subaccountBalanceList);
})();
Parameter | Type | Description | Required |
---|---|---|---|
subaccount_id | String | ID of subaccount to get balance info from | Yes |
denoms | String Array | Filter balances by denoms. If not set, the balances of all the denoms for the subaccount are provided | No |
Response Parameters
Response Example:
balances {
subaccount_id: "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
account_address: "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku"
denom: "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"
deposit {
total_balance: "115310339308.284511627876066473"
available_balance: "115236639078.284511627876066473"
}
}
balances {
subaccount_id: "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
account_address: "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku"
denom: "inj"
deposit {
total_balance: "1492235700000000000000"
available_balance: "1492235700000000000000"
}
}
{
"balances": [
{
"subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"account_address": "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
"denom": "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7",
"deposit": {
"total_balance": "200501904612800.13082016560359584",
"available_balance": "200358014975479.130820165603595295"
}
},
{
"subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"account_address": "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
"denom": "inj",
"deposit": {
"total_balance": "53790000010000000003",
"available_balance": "52790000010000000003"
}
},
{
"subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"account_address": "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
"denom": "ibc/C4CFF46FD6DE35CA4CF4CE031E643C8FDC9BA4B99AE598E9B0ED98FE3A2319F9",
"deposit": {
"total_balance": "1000000",
"available_balance": "1000000"
}
}
]
}
[
{
subaccountId: '0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000',
accountAddress: 'inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku',
denom: 'peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5',
deposit: {
totalBalance: '63522890505.651888522157767422',
availableBalance: '0.332888522157767422'
}
},
{
subaccountId: '0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000',
accountAddress: 'inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku',
denom: 'inj',
deposit: { totalBalance: '334000000000000000000', availableBalance: '0' }
},
{
subaccountId: '0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000',
accountAddress: 'inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku',
denom: 'peggy0x44C21afAaF20c270EBbF5914Cfc3b5022173FEB7',
deposit: { totalBalance: '0', availableBalance: '0' }
}
]
Parameter | Type | Description |
---|---|---|
balances | SubaccountBalance Array | Array of SubaccountBalance objects |
SubaccountBalance
Parameter | Type | Description |
---|---|---|
account_address | String | The Injective Chain address, owner of subaccount |
denom | String | Coin denom on the chain |
deposit | SubaccountDeposit | SubaccountDeposit object |
subaccount_id | String | ID of subaccount associated with returned balances |
SubaccountDeposit
Parameter | Type | Description |
---|---|---|
available_balance | String | The available balance for a denom |
total_balance | String | The total balance for a denom |
SubaccountOrderSummary
Get a summary of the subaccount's active/unfilled orders.
IP rate limit group: indexer
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
network = Network.testnet()
client = AsyncClient(network)
subaccount = "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
# order_direction = "buy"
# market_id = "0xe112199d9ee44ceb2697ea0edd1cd422223c105f3ed2bdf85223d3ca59f5909a"
subacc_order_summary = await client.get_subaccount_order_summary(
subaccount_id=subaccount,
# order_direction=order_direction,
# market_id=market_id
)
print(subacc_order_summary)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
accountPB "github.com/InjectiveLabs/sdk-go/exchange/accounts_rpc/pb"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
panic(err)
}
ctx := context.Background()
marketId := "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0"
subaccountId := "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
orderDirection := "buy"
req := accountPB.SubaccountOrderSummaryRequest{
MarketId: marketId,
SubaccountId: subaccountId,
OrderDirection: orderDirection,
}
res, err := exchangeClient.GetSubaccountOrderSummary(ctx, req)
if err != nil {
fmt.Println(err)
}
fmt.Println("spot orders:", res.SpotOrdersTotal)
fmt.Println("derivative orders:", res.DerivativeOrdersTotal)
}
import { IndexerGrpcAccountApi } from "@injectivelabs/sdk-ts";
import { getNetworkEndpoints, Network } from "@injectivelabs/networks";
(async () => {
const endpoints = getNetworkEndpoints(Network.TestnetK8s);
const indexerGrpcAccountApi = new IndexerGrpcAccountApi(endpoints.indexer);
const subaccountId =
"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000";
const marketId =
"0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0";
const orderDirection = "buy";
const orderSummary = await indexerGrpcAccountApi.fetchSubaccountOrderSummary({
subaccountId,
marketId,
orderDirection,
});
console.log(orderSummary);
})();
Parameter | Type | Description | Required |
---|---|---|---|
subaccount_id | String | ID of the subaccount we want to get the summary from | Yes |
market_id | String | Limit the order summary to a specific market | No |
order_direction | String | Filter by the direction of the orders. Valid options: "buy", "sell" | No |
Response Parameters
Response Example:
spot_orders_total: 1
derivative_orders_total: 7
spot orders: 1
derivative orders: 7
{
"spotOrdersTotal": 1,
"derivativeOrdersTotal": 7
}
Parameter | Type | Description |
---|---|---|
derivative_orders_total | Integer | Total count of subaccount's active derivative orders in a given market and direction |
spot_orders_total | Integer | Total count of subaccount's active spot orders in a given market and direction |
StreamSubaccountBalance
Stream the subaccount's balance for all denoms.
IP rate limit group: indexer
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
network = Network.testnet()
client = AsyncClient(network)
subaccount_id = "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001"
denoms = ["inj", "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"]
subaccount = await client.stream_subaccount_balance(subaccount_id)
async for balance in subaccount:
print("Subaccount balance Update:\n")
print(balance)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
panic(err)
}
ctx := context.Background()
subaccountId := "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
stream, err := exchangeClient.StreamSubaccountBalance(ctx, subaccountId)
if err != nil {
panic(err)
}
for {
select {
case <-ctx.Done():
return
default:
res, err := stream.Recv()
if err != nil {
fmt.Println(err)
return
}
str, _ := json.MarshalIndent(res, "", " ")
fmt.Print(string(str))
}
}
}
import {
IndexerGrpcAccountStream,
BalanceStreamCallback,
} from "@injectivelabs/sdk-ts";
import { getNetworkEndpoints, Network } from "@injectivelabs/networks";
(async () => {
const endpoints = getNetworkEndpoints(Network.TestnetK8s);
const indexerGrpcAccountStream = new IndexerGrpcAccountStream(
endpoints.indexer
);
const subaccountId =
"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000";
const streamFn = indexerGrpcAccountStream.streamSubaccountBalance.bind(
indexerGrpcAccountStream
);
const callback: BalanceStreamCallback = (subaccountBalance) => {
console.log(subaccountBalance);
};
const streamFnArgs = {
subaccountId,
callback,
};
streamFn(streamFnArgs);
})();
Parameter | Type | Description | Required |
---|---|---|---|
subaccount_id | String | Filter by subaccount ID | Yes |
denoms | String Array | Filter balances by denoms. If not set, the balances of all the denoms for the subaccount are provided | No |
Response Parameters
Streaming Response Example:
Subaccount balance Update:
balance {
subaccount_id: "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001"
account_address: "inj1clw20s2uxeyxtam6f7m84vgae92s9eh7vygagt"
denom: "inj"
deposit {
available_balance: "9980001000000000000"
}
}
timestamp: 1675902606000
Subaccount balance Update:
balance {
subaccount_id: "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001"
account_address: "inj1clw20s2uxeyxtam6f7m84vgae92s9eh7vygagt"
denom: "inj"
deposit {
available_balance: "9990001000000000000"
}
}
timestamp: 1675902946000
Subaccount balance Update:
balance {
subaccount_id: "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001"
account_address: "inj1clw20s2uxeyxtam6f7m84vgae92s9eh7vygagt"
denom: "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"
deposit {
total_balance: "199999859.1576"
available_balance: "199989859.1576"
}
}
timestamp: 1675902946000
{
"balance": {
"subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"account_address": "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
"denom": "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7",
"deposit": {
"total_balance": "200503979400874.28368413692326264",
"available_balance": "200360046875708.283684136923262095"
}
},
"timestamp": 1653037703000
}{
"balance": {
"subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"account_address": "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
"denom": "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7",
"deposit": {
"total_balance": "200503560511302.28368413692326264",
"available_balance": "200359627986136.283684136923262095"
}
},
"timestamp": 1653037744000
}
{
"balance": {
"subaccountId": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"accountAddress": "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
"denom": "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7",
"deposit": {
"totalBalance": "200493439765890.695319283887814576",
"availableBalance": "200493414240390.695319283887814031"
}
},
"timestamp": 1654234765000
}
{
"balance": {
"subaccountId": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"accountAddress": "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
"denom": "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7",
"deposit": {
"totalBalance": "200493847328858.695319283887814576",
"availableBalance": "200493821803358.695319283887814031"
}
},
"timestamp": 1654234804000
}
Parameter | Type | Description |
---|---|---|
balance | SubaccountBalance | SubaccountBalance object |
timestamp | Integer | Operation timestamp in UNIX millis |
SubaccountBalance
Parameter | Type | Description |
---|---|---|
denom | String | Coin denom on the chain |
deposit | SubaccountDeposit | SubaccountDeposit object |
subaccount_id | String | ID of the subaccount to get balance from |
account_address | String | The Injective Chain address that owns the subaccount |
SubaccountDeposit
Parameter | Type | Description |
---|---|---|
available_balance | String | The available balance for a denom (taking active orders into account) |
total_balance | String | The total balance for a denom (balance if all active orders were cancelled) |
OrderStates
Get orders with an order hash. This request will return market orders and limit orders in all states [booked, partial_filled, filled, canceled]. For filled and canceled orders, there is a TTL of 3 minutes. Should your order be filled or canceled you will still be able to fetch it for 3 minutes.
IP rate limit group: indexer
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
network = Network.testnet()
client = AsyncClient(network)
spot_order_hashes = ["0xce0d9b701f77cd6ddfda5dd3a4fe7b2d53ba83e5d6c054fb2e9e886200b7b7bb", "0x2e2245b5431638d76c6e0cc6268970418a1b1b7df60a8e94b8cf37eae6105542"]
derivative_order_hashes = ["0x82113f3998999bdc3892feaab2c4e53ba06c5fe887a2d5f9763397240f24da50", "0xbb1f036001378cecb5fff1cc69303919985b5bf058c32f37d5aaf9b804c07a06"]
orders = await client.get_order_states(spot_order_hashes=spot_order_hashes, derivative_order_hashes=derivative_order_hashes)
print(orders)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
accountPB "github.com/InjectiveLabs/sdk-go/exchange/accounts_rpc/pb"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
panic(err)
}
ctx := context.Background()
spotOrderHashes := []string{"0xb7b556d6eab10c4c185a660be44757a8a6715fb16db39708f2f76d9ce5ae8617"}
derivativeOrderHashes := []string{"0x4228f9a56a5bb50de4ceadc64df694c77e7752d58b71a7c557a27ec10e1a094e"}
req := accountPB.OrderStatesRequest{
SpotOrderHashes: spotOrderHashes,
DerivativeOrderHashes: derivativeOrderHashes,
}
res, err := exchangeClient.GetOrderStates(ctx, req)
if err != nil {
fmt.Println(err)
}
str, _ := json.MarshalIndent(res, "", " ")
fmt.Print(string(str))
}
import { IndexerGrpcAccountApi } from "@injectivelabs/sdk-ts";
import { getNetworkEndpoints, Network } from "@injectivelabs/networks";
(async () => {
const endpoints = getNetworkEndpoints(Network.TestnetK8s);
const indexerGrpcAccountApi = new IndexerGrpcAccountApi(endpoints.indexer);
const spotOrderHashes = [
"0xce0d9b701f77cd6ddfda5dd3a4fe7b2d53ba83e5d6c054fb2e9e886200b7b7bb",
];
const derivativeOrderHashes = [
"0x82113f3998999bdc3892feaab2c4e53ba06c5fe887a2d5f9763397240f24da50",
];
const orderStates = await indexerGrpcAccountApi.fetchOrderStates({
spotOrderHashes,
derivativeOrderHashes,
});
console.log(orderStates);
})();
Parameter | Type | Description | Required |
---|---|---|---|
spot_order_hashes | String Array | Array with the order hashes you want to fetch in spot markets | No |
derivative_order_hashes | String Array | Array with the order hashes you want to fetch in derivative markets | No |
Response Parameters
Response Example:
spot_order_states {
order_hash: "0xa848395a768ee06af360e2e35bac6f598fdc52e8d0c34a588d32cd9108f3571f"
subaccount_id: "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
market_id: "0x0511ddc4e6586f3bfe1acb2dd905f8b8a82c97e1edaef654b12ca7e6031ca0fa"
order_type: "buy"
order_side: "buy"
state: "booked"
quantity_filled: "0"
quantity_remaining: "2000000"
created_at: 1652701438661
updated_at: 1652701438661
}
spot_order_states {
order_hash: "0x163861fba3d911631e18354a03e7357bc6358cd2042535e8ad11dc6c29f8c558"
subaccount_id: "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
market_id: "0x0511ddc4e6586f3bfe1acb2dd905f8b8a82c97e1edaef654b12ca7e6031ca0fa"
order_type: "buy"
order_side: "buy"
state: "booked"
quantity_filled: "0"
quantity_remaining: "2000000"
created_at: 1652693332688
updated_at: 1652693332688
}
derivative_order_states {
order_hash: "0x962af5e492a2ce4575616dbcf687a063ef9c4b33a047a9fb86794804923337c8"
subaccount_id: "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
market_id: "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"
order_type: "sell"
order_side: "sell"
state: "booked"
quantity_filled: "1"
quantity_remaining: "0"
created_at: 1652786114544
updated_at: 1652786114544
}
{
"spot_order_states": [
{
"order_hash": "0xb7b556d6eab10c4c185a660be44757a8a6715fb16db39708f2f76d9ce5ae8617",
"subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"market_id": "0x0511ddc4e6586f3bfe1acb2dd905f8b8a82c97e1edaef654b12ca7e6031ca0fa",
"order_type": "limit",
"order_side": "buy",
"state": "booked",
"quantity_filled": "0",
"quantity_remaining": "1000000",
"created_at": 1654080262300,
"updated_at": 1654080262300
}
],
"derivative_order_states": [
{
"order_hash": "0x4228f9a56a5bb50de4ceadc64df694c77e7752d58b71a7c557a27ec10e1a094e",
"subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"market_id": "0x1c79dac019f73e4060494ab1b4fcba734350656d6fc4d474f6a238c13c6f9ced",
"order_type": "limit",
"order_side": "buy",
"state": "booked",
"quantity_filled": "0",
"quantity_remaining": "1",
"created_at": 1654235059957,
"updated_at": 1654235059957
}
]
}
{
"spotOrderStates": [
{
"orderHash": "0xb7b556d6eab10c4c185a660be44757a8a6715fb16db39708f2f76d9ce5ae8617",
"subaccountId": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"marketId": "0x0511ddc4e6586f3bfe1acb2dd905f8b8a82c97e1edaef654b12ca7e6031ca0fa",
"orderType": "limit",
"orderSide": "buy",
"state": "booked",
"quantityFilled": "0",
"quantityRemaining": "1000000",
"createdAt": 1654080262300,
"updatedAt": 1654080262300
}
],
"derivativeOrderStates": [
{
"orderHash": "0x4228f9a56a5bb50de4ceadc64df694c77e7752d58b71a7c557a27ec10e1a094e",
"subaccountId": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"marketId": "0x1c79dac019f73e4060494ab1b4fcba734350656d6fc4d474f6a238c13c6f9ced",
"orderType": "limit",
"orderSide": "buy",
"state": "booked",
"quantityFilled": "0",
"quantityRemaining": "1",
"createdAt": 1654235059957,
"updatedAt": 1654235059957
}
]
}
Parameter | Type | Description |
---|---|---|
spot_order_states | OrderStateRecord Array | Array of OrderStateRecord objects |
derivative_order_states | OrderStateRecord Array | Array of OrderStateRecord objects |
SpotOrderStates
Parameter | Type | Description |
---|---|---|
order_hash | String | Hash of the order |
subaccount_id | String | The subaccount ID that posted the order |
market_id | String | The market ID of the order |
order_type | String | The order type. Should be one of: ["buy", "sell", "stop_buy", "stop_sell", "take_buy", "take_sell", "buy_po", "sell_po"]. If execution_type (market or limit) is needed, use the OrdersHistory request in Spot/DerivativeExchangeRPC instead |
order_side | String | The order side. Should be one of: ["buy", "sell"] |
state | String | The order state. Should be one of: ["booked", "partial_filled", "filled", "canceled"] |
quantity_filled | String | The quantity that has been filled for the order |
quantity_remaining | String | The quantity that hasn't been filled for the order |
created_at | String | The UNIX timestamp of the order when it was first created |
updated_at | String | The UNIX timestamp of the order when it was last updated |
DerivativeOrderStates
Parameter | Type | Description |
---|---|---|
order_hash | String | Hash of the order |
subaccount_id | String | The subaccount ID that posted the order |
market_id | String | The market ID of the order |
order_type | String | The order type. Should be one of: ["buy", "sell", "stop_buy", "stop_sell", "take_buy", "take_sell", "buy_po", "sell_po"]. If execution_type (market or limit) is needed, use the OrdersHistory request in Spot/DerivativeExchangeRPC instead |
order_side | String | The order side. Should be one of: ["buy", "sell"] |
state | String | The order state. Should be one of: ["booked", "partial_filled", "filled", "canceled"] |
quantity_filled | String | The quantity that has been filled for the order |
quantity_remaining | String | The quantity that hasn't been filled for the order |
created_at | String | The UNIX timestamp of the order when it was first created |
updated_at | String | The UNIX timestamp of the order when it was last updated |
Portfolio
Get an overview of your portfolio.
IP rate limit group: indexer
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
network = Network.testnet()
client = AsyncClient(network)
account_address = "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku"
portfolio = await client.get_portfolio(account_address=account_address)
print(portfolio)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
panic(err)
}
ctx := context.Background()
accountAddress := "inj10y4mpwgqr4c63m7t8spxhf8rgcy2dz5vt3mvk9"
res, err := exchangeClient.GetPortfolio(ctx, accountAddress)
if err != nil {
fmt.Println(err)
}
str, _ := json.MarshalIndent(res, "", " ")
fmt.Print(string(str))
}
import { IndexerGrpcAccountApi } from "@injectivelabs/sdk-ts";
import { getNetworkEndpoints, Network } from "@injectivelabs/networks";
(async () => {
const endpoints = getNetworkEndpoints(Network.TestnetK8s);
const indexerGrpcAccountApi = new IndexerGrpcAccountApi(endpoints.indexer);
const injectiveAddress = "inj10y4mpwgqr4c63m7t8spxhf8rgcy2dz5vt3mvk9";
const portfolio = await indexerGrpcAccountApi.fetchPortfolio(
injectiveAddress
);
console.log(portfolio);
})();
Parameter | Type | Description | Required |
---|---|---|---|
account_address | String | The Injective Chain address | Yes |
Response Parameters
Response Example:
portfolio {
portfolio_value: "121771.765274665073374624"
available_balance: "120622.8032988109636363"
locked_balance: "1476.0573145189379903"
unrealized_pnl: "-327.095338664828251976"
subaccounts {
subaccount_id: "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
available_balance: "120622.8032988109636363"
locked_balance: "1476.0573145189379903"
unrealized_pnl: "-327.095338664828251976"
}
}
{
"portfolio": {
"portfolio_value": "16961.63886335580191347385",
"available_balance": "10127.8309908372442029",
"locked_balance": "8192.6038127728038576",
"unrealized_pnl": "-1358.79594025424614702615",
"subaccounts": [
{
"subaccount_id": "0x792bb0b9001d71a8efcb3c026ba4e34608a68a8c000000000000000000000000",
"available_balance": "10127.8309908372442029",
"locked_balance": "8192.6038127728038576",
"unrealized_pnl": "-1358.79594025424614702615"
}
]
}
}
{
"portfolioValue": "18140.93939739028541677385",
"availableBalance": "10100.5755146800551762",
"lockedBalance": "8190.6761262577118576",
"unrealizedPnl": "-150.31224354748161702615",
"subaccountsList": [
{
"subaccountId": "0x792bb0b9001d71a8efcb3c026ba4e34608a68a8c000000000000000000000000",
"availableBalance": "10100.5755146800551762",
"lockedBalance": "8190.6761262577118576",
"unrealizedPnl": "-150.31224354748161702615"
}
]
}
Parameter | Type | Description |
---|---|---|
portfolio_value | String | The total value (in USD) of your portfolio including bank balance, subaccounts' balance, unrealized profit & loss as well as margin in open positions |
available_balance | String | The total available balance (in USD) in all subaccounts |
locked_balance | String | The amount of margin in open orders and positions (in USD) |
unrealized_pnl | String | The approximate unrealized profit and loss across all positions (based on mark prices, in USD) |
subaccounts | SubaccountPortfolio Array | List of all subaccounts' portfolios |
SubaccountPortfolio
Parameter | Type | Description |
---|---|---|
subaccount_id | String | The ID of this subaccount |
available_balance | String | The subaccount's available balance (in USD) |
locked_balance | String | The subaccount's locked balance (in USD) |
unrealized_pnl | String | The Subaccount's total unrealized PnL value (in USD) |
Rewards
Get the rewards for Trade & Earn, the request will fetch all addresses for the latest epoch (-1) by default.
IP rate limit group: indexer
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
network = Network.testnet()
client = AsyncClient(network)
# account_address = "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku"
epoch = -1
rewards = await client.get_rewards(
# account_address=account_address,
epoch=epoch)
print(rewards)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
accountPB "github.com/InjectiveLabs/sdk-go/exchange/accounts_rpc/pb"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
panic(err)
}
ctx := context.Background()
accountAddress := "inj1rwv4zn3jptsqs7l8lpa3uvzhs57y8duemete9e"
epoch := int64(2)
req := accountPB.RewardsRequest{
Epoch: epoch,
AccountAddress: accountAddress,
}
res, err := exchangeClient.GetRewards(ctx, req)
if err != nil {
fmt.Println(err)
}
fmt.Println(res)
}
import { IndexerGrpcAccountApi } from "@injectivelabs/sdk-ts";
import { getNetworkEndpoints, Network } from "@injectivelabs/networks";
(async () => {
const endpoints = getNetworkEndpoints(Network.TestnetK8s);
const indexerGrpcAccountApi = new IndexerGrpcAccountApi(endpoints.indexer);
const injectiveAddress = "inj10y4mpwgqr4c63m7t8spxhf8rgcy2dz5vt3mvk9";
const epoch = -1; // current epoch
const tradingRewards = await indexerGrpcAccountApi.fetchRewards(
{
address: injectiveAddress,
epoch,
}
);
console.log(tradingRewards);
})();
Parameter | Type | Description | Required |
---|---|---|---|
account_address | String | The Injective Chain address to fetch rewards amount for | No |
epoch | Integer | The rewards distribution epoch number. Use -1 for the latest epoch | No |
Response Parameters
Response Example:
rewards {
account_address: "inj1qra8c03h70y36j85dpvtj05juxe9z7acuvz6vg"
rewards {
denom: "inj"
amount: "1954269574440758128"
}
distributed_at: 1672218001897
}
rewards {
account_address: "inj1q4sww3amkmwhym54aaey5v8wemkh9v80jp8e3z"
rewards {
denom: "inj"
amount: "8497057876433151133"
}
distributed_at: 1672218001897
}
rewards {
account_address: "inj1pqsujjk66dsf40v2lfrry46m2fym44thgn5qqh"
rewards {
denom: "inj"
amount: "41401176734199333"
}
distributed_at: 1672218001897
}
...
{
"rewards": [
{
"account_address": "inj1rwv4zn3jptsqs7l8lpa3uvzhs57y8duemete9e",
"rewards": [
{
"denom": "inj",
"amount": "755104058929571177652"
}
],
"distributed_at": 1642582800716
}
]
}
[
{
"accountAddress": "inj1rwv4zn3jptsqs7l8lpa3uvzhs57y8duemete9e",
"rewards": [
{
"denom": "inj",
"amount": "755104058929571177652"
}
],
"distributedAt": 1642582800716
}
]
Parameter | Type | Description |
---|---|---|
rewards | Reward Array | List of trading rewards |
Reward
Parameter | Type | Description |
---|---|---|
account_address | String | The Injective Chain address |
rewards | Coin Array | List of rewards by denom and amount |
distributed_at | Integer | Timestamp of the transfer in UNIX millis |
Coin
Parameter | Type | Description |
---|---|---|
denom | String | Denom of the reward |
amount | String | Amount of denom in reward |
- InjectiveSpotExchangeRPC
InjectiveSpotExchangeRPC defines the gRPC API of the Spot Exchange provider.
Market
Get details of a single spot market.
IP rate limit group: indexer
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
network = Network.testnet()
client = AsyncClient(network)
market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
market = await client.get_spot_market(market_id=market_id)
print(market)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
fmt.Println(err)
}
ctx := context.Background()
marketId := "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0"
res, err := exchangeClient.GetSpotMarket(ctx, marketId)
if err != nil {
fmt.Println(err)
}
str, _ := json.MarshalIndent(res, "", " ")
fmt.Print(string(str))
}
import { IndexerGrpcSpotApi } from "@injectivelabs/sdk-ts";
import { getNetworkEndpoints, Network } from "@injectivelabs/networks";
(async () => {
const endpoints = getNetworkEndpoints(Network.TestnetK8s);
const indexerGrpcSpotApi = new IndexerGrpcSpotApi(endpoints.indexer);
const marketId =
"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe";
const market = await indexerGrpcSpotApi.fetchMarket(marketId);
console.log(market);
})();
Parameter | Type | Description | Required |
---|---|---|---|
market_id | String | MarketId of the market we want to fetch | Yes |
Response Parameters
Response Example:
market {
market_id: "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
market_status: "active"
ticker: "INJ/USDT"
base_denom: "inj"
base_token_meta {
name: "Injective Protocol"
address: "0xe28b3B32B6c345A34Ff64674606124Dd5Aceca30"
symbol: "INJ"
logo: "https://static.alchemyapi.io/images/assets/7226.png"
decimals: 18
updated_at: 1658129632873
}
quote_denom: "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"
quote_token_meta {
name: "Testnet Tether USDT"
address: "0x0000000000000000000000000000000000000000"
symbol: "USDT"
logo: "https://static.alchemyapi.io/images/assets/825.png"
decimals: 6
updated_at: 1675929393340
}
maker_fee_rate: "-0.0001"
taker_fee_rate: "0.001"
service_provider_fee: "0.4"
min_price_tick_size: "0.000000000000001"
min_quantity_tick_size: "1000000000000000"
}
{
"market": {
"market_id": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
"market_status": "active",
"ticker": "INJ/USDT",
"base_denom": "inj",
"base_token_meta": {
"name": "Injective Protocol",
"address": "0xe28b3B32B6c345A34Ff64674606124Dd5Aceca30",
"symbol": "INJ",
"logo": "https://static.alchemyapi.io/images/assets/7226.png",
"decimals": 18,
"updated_at": 1650978921934
},
"quote_denom": "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7",
"maker_fee_rate": "0.001",
"taker_fee_rate": "0.002",
"service_provider_fee": "0.4",
"min_price_tick_size": "0.000000000000001",
"min_quantity_tick_size": "1000000000000000"
}
}
{
"market": {
"marketId": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
"marketStatus": "active",
"ticker": "INJ/USDT",
"baseDenom": "inj",
"baseTokenMeta": {
"name": "Injective Protocol",
"address": "0xe28b3B32B6c345A34Ff64674606124Dd5Aceca30",
"symbol": "INJ",
"logo": "https://static.alchemyapi.io/images/assets/7226.png",
"decimals": 18,
"updatedAt": 1650978921934
},
"quoteDenom": "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7",
"makerFeeRate": "0.001",
"takerFeeRate": "0.002",
"serviceProviderFee": "0.4",
"minPriceTickSize": "0.000000000000001",
"minQuantityTickSize": "1000000000000000"
}
}
Parameter | Type | Description |
---|---|---|
market | SpotMarketInfo | Info about particular spot market |
SpotMarketInfo
Parameter | Type | Description |
---|---|---|
base_denom | String | Coin denom of the base asset |
market_id | String | ID of the spot market of interest |
market_status | String | The status of the market (Should be one of: ["active", "paused", "suspended", "demolished", "expired"]) |
min_quantity_tick_size | String | Defines the minimum required tick size for the order's quantity |
quote_token_meta | TokenMeta | Token metadata for quote asset, only for Ethereum-based assets |
service_provider_fee | String | Percentage of the transaction fee shared with the service provider |
base_token_meta | TokenMeta | Token metadata for base asset, only for Ethereum-based assets |
maker_fee_rate | String | Defines the fee percentage makers pay (or receive, if negative) in quote asset when trading |
min_price_tick_size | String | Defines the minimum required tick size for the order's price |
quote_denom | String | Coin denom of the quote asset |
taker_fee_rate | String | Defines the fee percentage takers pay (in the quote asset) when trading |
ticker | String | A name of the pair in format AAA/BBB, where AAA is base asset, BBB is quote asset |
TokenMeta
Parameter | Type | Description |
---|---|---|
address | String | Token's Ethereum contract address |
decimals | Integer | Token decimals |
logo | String | URL to the logo image |
name | String | Token full name |
symbol | String | Token symbol short name |
updatedAt | Integer | Token metadata fetched timestamp in UNIX millis |
Markets
Get a list of spot markets.
IP rate limit group: indexer
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
network = Network.testnet()
client = AsyncClient(network)
market_status = "active"
base_denom = "inj"
quote_denom = "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"
market = await client.get_spot_markets(
market_status=market_status,
base_denom=base_denom,
quote_denom=quote_denom
)
print(market)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
spotExchangePB "github.com/InjectiveLabs/sdk-go/exchange/spot_exchange_rpc/pb"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
fmt.Println(err)
}
ctx := context.Background()
marketStatus := "active"
quoteDenom := "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7"
req := spotExchangePB.MarketsRequest{
MarketStatus: marketStatus,
QuoteDenom: quoteDenom,
}
res, err := exchangeClient.GetSpotMarkets(ctx, req)
if err != nil {
fmt.Println(err)
}
str, _ := json.MarshalIndent(res, "", " ")
fmt.Print(string(str))
}
import { IndexerGrpcSpotApi } from "@injectivelabs/sdk-ts";
import { getNetworkEndpoints, Network } from "@injectivelabs/networks";
(async () => {
const endpoints = getNetworkEndpoints(Network.TestnetK8s);
const indexerGrpcSpotApi = new IndexerGrpcSpotApi(endpoints.indexer);
const marketStatus = "active";
const quoteDenom = "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7";
const markets = await indexerGrpcSpotApi.fetchMarkets({
marketStatus,
quoteDenom,
});
console.log(markets);
})();
Parameter | Type | Description | Required |
---|---|---|---|
base_denom | String | Filter by the Coin denomination of the base currency | No |
market_status | String | Filter by status of the market (Should be one of: ["active", "paused", "suspended", "demolished", "expired"]) | No |
quote_denom | String | Filter by the Coin denomination of the quote currency | No |
Response Parameters
Response Example:
markets {
market_id: "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
market_status: "active"
ticker: "INJ/USDT"
base_denom: "inj"
base_token_meta {
name: "Injective Protocol"
address: "0xe28b3B32B6c345A34Ff64674606124Dd5Aceca30"
symbol: "INJ"
logo: "https://static.alchemyapi.io/images/assets/7226.png"
decimals: 18
updated_at: 1658129632873
}
quote_denom: "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"
quote_token_meta {
name: "Testnet Tether USDT"
address: "0x0000000000000000000000000000000000000000"
symbol: "USDT"
logo: "https://static.alchemyapi.io/images/assets/825.png"
decimals: 6
updated_at: 1675929959325
}
maker_fee_rate: "-0.0001"
taker_fee_rate: "0.001"
service_provider_fee: "0.4"
min_price_tick_size: "0.000000000000001"
min_quantity_tick_size: "1000000000000000"
}
{
"markets": [
{
"market_id": "0x01edfab47f124748dc89998eb33144af734484ba07099014594321729a0ca16b",
"market_status": "active",
"ticker": "AAVE/USDT",
"base_denom": "peggy0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9",
"base_token_meta": {
"name": "Aave",
"address": "0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9",
"symbol": "AAVE",
"logo": "https://static.alchemyapi.io/images/assets/7278.png",
"decimals": 18,
"updated_at": 1650978921846
},
"quote_denom": "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7",
"maker_fee_rate": "0.001",
"taker_fee_rate": "0.002",
"service_provider_fee": "0.4",
"min_price_tick_size": "0.000000000000001",
"min_quantity_tick_size": "1000000000000000"
},
{
"market_id": "0xe8bf0467208c24209c1cf0fd64833fa43eb6e8035869f9d043dbff815ab76d01",
"market_status": "active",
"ticker": "UNI/USDT",
"base_denom": "peggy0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984",
"base_token_meta": {
"name": "Uniswap",
"address": "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984",
"symbol": "UNI",
"logo": "https://static.alchemyapi.io/images/assets/7083.png",
"decimals": 18,
"updated_at": 1650978922133
},
"quote_denom": "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7",
"maker_fee_rate": "0.001",
"taker_fee_rate": "0.002",
"service_provider_fee": "0.4",
"min_price_tick_size": "0.000000000000001",
"min_quantity_tick_size": "1000000000000000"
}
]
}
[
{
"marketId": "0x01edfab47f124748dc89998eb33144af734484ba07099014594321729a0ca16b",
"marketStatus": "active",
"ticker": "AAVE/USDT",
"baseDenom": "peggy0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9",
"baseTokenMeta": {
"name": "Aave",
"address": "0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9",
"symbol": "AAVE",
"logo": "https://static.alchemyapi.io/images/assets/7278.png",
"decimals": 18,
"updatedAt": 1650978921846
},
"quoteDenom": "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7",
"makerFeeRate": "0.001",
"takerFeeRate": "0.002",
"serviceProviderFee": "0.4",
"minPriceTickSize": "0.000000000000001",
"minQuantityTickSize": "1000000000000000"
},
{
"marketId": "0x0511ddc4e6586f3bfe1acb2dd905f8b8a82c97e1edaef654b12ca7e6031ca0fa",
"marketStatus": "active",
"ticker": "ATOM/USDT",
"baseDenom": "ibc/C4CFF46FD6DE35CA4CF4CE031E643C8FDC9BA4B99AE598E9B0ED98FE3A2319F9",
"baseTokenMeta": {
"name": "Cosmos",
"address": "0x8D983cb9388EaC77af0474fA441C4815500Cb7BB",
"symbol": "ATOM",
"logo": "https://s2.coinmarketcap.com/static/img/coins/64x64/3794.png",
"decimals": 6,
"updatedAt": 1650978921848
},
"quoteDenom": "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7",
"makerFeeRate": "0.001",
"takerFeeRate": "0.001",
"serviceProviderFee": "0.4",
"minPriceTickSize": "0.01",
"minQuantityTickSize": "10000"
},
{
"marketId": "0xe8bf0467208c24209c1cf0fd64833fa43eb6e8035869f9d043dbff815ab76d01",
"marketStatus": "active",
"ticker": "UNI/USDT",
"baseDenom": "peggy0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984",
"baseTokenMeta": {
"name": "Uniswap",
"address": "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984",
"symbol": "UNI",
"logo": "https://static.alchemyapi.io/images/assets/7083.png",
"decimals": 18,
"updatedAt": 1650978922133
},
"quoteDenom": "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7",
"makerFeeRate": "0.001",
"takerFeeRate": "0.002",
"serviceProviderFee": "0.4",
"minPriceTickSize": "0.000000000000001",
"minQuantityTickSize": "1000000000000000"
}
]
Parameter | Type | Description |
---|---|---|
markets | SpotMarketInfo Array | List of spot markets |
SpotMarketInfo
Parameter | Type | Description |
---|---|---|
base_denom | String | Coin denom of the base asset |
market_id | String | ID of the spot market of interest |
market_status | String | The status of the market (Should be one of: ["active", "paused", "suspended", "demolished", "expired"]) |
min_quantity_tick_size | String | Defines the minimum required tick size for the order's quantity |
quote_token_meta | TokenMeta | Token metadata for quote asset, only for Ethereum-based assets |
service_provider_fee | String | Percentage of the transaction fee shared with the service provider |
base_token_meta | TokenMeta | Token metadata for base asset, only for Ethereum-based assets |
maker_fee_rate | String | Defines the fee percentage makers pay (or receive, if negative) in quote asset when trading |
min_price_tick_size | String | Defines the minimum required tick size for the order's price |
quote_denom | String | Coin denom of the quote asset |
taker_fee_rate | String | Defines the fee percentage takers pay (in the quote asset) when trading |
ticker | String | A name of the pair in format AAA/BBB, where AAA is base asset, BBB is quote asset |
TokenMeta
Parameter | Type | Description |
---|---|---|
address | String | Token's Ethereum contract address |
decimals | Integer | Token decimals |
logo | String | URL to the logo image |
name | String | Token full name |
symbol | String | Token symbol short name |
updatedAt | Integer | Token metadata fetched timestamp in UNIX millis |
StreamMarkets
Stream live updates of spot markets.
IP rate limit group: indexer
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
client = AsyncClient(network)
markets = await client.stream_spot_markets()
async for market in markets:
print(market)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
fmt.Println(err)
}
ctx := context.Background()
marketIds := []string{"0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0"}
stream, err := exchangeClient.StreamSpotMarket(ctx, marketIds)
if err != nil {
fmt.Println(err)
}
for {
select {
case <-ctx.Done():
return
default:
res, err := stream.Recv()
if err != nil {
fmt.Println(err)
return
}
str, _ := json.MarshalIndent(res, "", " ")
fmt.Print(string(str))
}
}
}
import {
IndexerGrpcSpotStream,
MarketsStreamCallback,
} from "@injectivelabs/sdk-ts";
import { getNetworkEndpoints, Network } from "@injectivelabs/networks";
(async () => {
const endpoints = getNetworkEndpoints(Network.TestnetK8s);
const indexerGrpcSpotStream = new IndexerGrpcSpotStream(endpoints.indexer);
const marketIds = [
"0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
]; /* optional param */
const streamFn = indexerGrpcSpotStream.streamSpotMarket.bind(
indexerGrpcSpotStream
);
const callback: MarketsStreamCallback = (markets) => {
console.log(markets);
};
const streamFnArgs = {
marketIds,
callback,
};
streamFn(streamFnArgs);
})();
Parameter | Type | Description | Required |
---|---|---|---|
market_ids | String Array | List of market IDs for updates streaming, empty means 'ALL' spot markets | No |
Response Parameters
Streaming Response Example:
market: {
market_id: "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
market_status: "active",
ticker: "INJ/USDT",
base_denom: "inj",
base_token_meta: {
name: "Injective Protocol",
address: "0xe28b3B32B6c345A34Ff64674606124Dd5Aceca30",
symbol: "INJ",
logo: "https://static.alchemyapi.io/images/assets/7226.png",
decimals: 18,
updated_at: 1632535055751
},
quote_denom: "peggy0x69efCB62D98f4a6ff5a0b0CFaa4AAbB122e85e08",
quote_token_meta: {
name: "Tether",
address: "0x69efCB62D98f4a6ff5a0b0CFaa4AAbB122e85e08",
symbol: "USDT",
logo: "https://static.alchemyapi.io/images/assets/825.png",
decimals: 6,
updated_at: 1632535055759
},
maker_fee_rate: "0.001",
taker_fee_rate: "0.002",
service_provider_fee: "0.4",
min_price_tick_size: "0.000000000000001",
min_quantity_tick_size: "1000000000000000"
},
operation_type: "update",
timestamp: 1632535055790
{
"market": {
"market_id": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
"market_status": "active",
"ticker": "INJ/USDT",
"base_denom": "inj",
"base_token_meta": {
"name": "Injective Protocol",
"address": "0xe28b3B32B6c345A34Ff64674606124Dd5Aceca30",
"symbol": "INJ",
"logo": "https://static.alchemyapi.io/images/assets/7226.png",
"decimals": 18,
"updated_at": 1632535055751
},
"quote_denom": "peggy0x69efCB62D98f4a6ff5a0b0CFaa4AAbB122e85e08",
"quote_token_meta": {
"name": "Tether",
"address": "0x69efCB62D98f4a6ff5a0b0CFaa4AAbB122e85e08",
"symbol": "USDT",
"logo": "https://static.alchemyapi.io/images/assets/825.png",
"decimals": 6,
"updated_at": 1632535055759
},
"maker_fee_rate": "0.001",
"taker_fee_rate": "0.002",
"service_provider_fee": "0.4",
"min_price_tick_size": "0.000000000000001",
"min_quantity_tick_size": "1000000000000000"
},
"operation_type": "update",
"timestamp": 1632535055790
}
{
"market": {
"marketId": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
"marketStatus": "active",
"ticker": "INJ/USDT",
"baseDenom": "inj",
"baseTokenMeta": {
"name": "Injective Protocol",
"address": "0xe28b3B32B6c345A34Ff64674606124Dd5Aceca30",
"symbol": "INJ",
"logo": "https://static.alchemyapi.io/images/assets/7226.png",
"decimals": 18,
"updatedAt": 1632535055751
},
"quoteDenom": "peggy0x69efCB62D98f4a6ff5a0b0CFaa4AAbB122e85e08",
"quoteTokenMeta": {
"name": "Tether",
"address": "0x69efCB62D98f4a6ff5a0b0CFaa4AAbB122e85e08",
"symbol": "USDT",
"logo": "https://static.alchemyapi.io/images/assets/825.png",
"decimals": 6,
"updatedAt": 1632535055759
},
"makerFeeRate": "0.001",
"takerFeeRate": "0.002",
"serviceProviderRate": "0.4",
"minPriceTickSize": "0.000000000000001",
"minQuantityTickSize": "1000000000000000"
},
"operationType": "update",
"timestamp": 1632535055790
}
}
Parameter | Type | Description |
---|---|---|
market | SpotMarketInfo | Info about particular spot market |
operation_type | String | Update type (Should be one of: ["insert", "replace", "update", "invalidate"]) |
timestamp | Integer | Operation timestamp in UNIX millis |
SpotMarketInfo
Parameter | Type | Description |
---|---|---|
base_denom | String | Coin denom of the base asset |
market_id | String | ID of the spot market of interest |
market_status | String | The status of the market (Should be one of: ["active", "paused", "suspended", "demolished", "expired"]) |
min_quantity_tick_size | String | Defines the minimum required tick size for the order's quantity |
quote_token_meta | TokenMeta | Token metadata for quote asset, only for Ethereum-based assets |
service_provider_fee | String | Percentage of the transaction fee shared with the service provider |
base_token_meta | TokenMeta | Token metadata for base asset, only for Ethereum-based assets |
maker_fee_rate | String | Defines the fee percentage makers pay (or receive, if negative) in quote asset when trading |
min_price_tick_size | String | Defines the minimum required tick size for the order's price |
quote_denom | String | Coin denom of the quote asset |
taker_fee_rate | String | Defines the fee percentage takers pay (in the quote asset) when trading |
ticker | String | A name of the pair in format AAA/BBB, where AAA is base asset, BBB is quote asset |
TokenMeta
Parameter | Type | Description |
---|---|---|
address | String | Token's Ethereum contract address |
decimals | Integer | Token decimals |
logo | String | URL to the logo image |
name | String | Token full name |
symbol | String | Token symbol short name |
updatedAt | Integer | Token metadata fetched timestamp in UNIX millis |
OrdersHistory
List history of orders (all states) for a spot market.
IP rate limit group: indexer
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
network = Network.testnet()
client = AsyncClient(network)
market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
subaccount_id = "0xbdaedec95d563fb05240d6e01821008454c24c36000000000000000000000000"
skip = 10
limit = 3
order_types = ["buy_po"]
orders = await client.get_historical_spot_orders(
market_id=market_id,
subaccount_id=subaccount_id,
skip=skip,
limit=limit,
order_types=order_types
)
print(orders)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
Parameter | Type | Description | Required |
---|---|---|---|
market_id | String | Filter by market ID | Yes |
subaccount_id | String | Filter by subaccount ID | No |
skip | Integer | Skip the first n items from the results. This can be used to fetch all trades since the API caps at 100 | No |
limit | Integer | Maximum number of items to be returned. 1 <= n <= 100 | No |
direction | String | Filter by order direction (Should be one of: ["buy", "sell"]) | No |
start_time | Integer | Search for orders where createdAt >= startTime, time in milliseconds | No |
end_time | Integer | Search for orders where createdAt <= startTime, time in milliseconds | No |
state | String | The order state (Should be one of: ["booked", "partial_filled", "filled", "canceled"]) | No |
execution_types | String Array | The execution of the order (Should be one of: ["limit", "market"]) | No |
order_types | String Array | The order type (Should be one of: ["buy", "sell", "stop_buy", "stop_sell", "take_buy", "take_sell", "buy_po", "sell_po"]) | No |
Response Parameters
Response Example:
orders {
order_hash: "0x5421e66dee390cbc734c2aaa3e9cf4b6917a3c9cf496c2e1ba3661e9cebcce56"
market_id: "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
subaccount_id: "0xbdaedec95d563fb05240d6e01821008454c24c36000000000000000000000000"
execution_type: "limit"
order_type: "buy_po"
price: "0.000000000000001"
trigger_price: "0"
quantity: "1000000000000000"
filled_quantity: "0"
state: "canceled"
created_at: 1669998526840
updated_at: 1670919394668
direction: "buy"
}
orders {
order_hash: "0xf4d33d0eb3ee93a79df7e1c330b729dc56ab18b423be8d82c972f9dd2498fb3c"
market_id: "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
subaccount_id: "0xbdaedec95d563fb05240d6e01821008454c24c36000000000000000000000000"
execution_type: "limit"
order_type: "buy_po"
price: "0.000000000000001"
trigger_price: "0"
quantity: "1000000000000000"
filled_quantity: "0"
state: "canceled"
created_at: 1669998526840
updated_at: 1670919410587
direction: "buy"
}
orders {
order_hash: "0x3fedb6c07b56155e4e7752dd3f24dfbf58a6cfc1370b9cd2973e79e31d29b17a"
market_id: "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
subaccount_id: "0xbdaedec95d563fb05240d6e01821008454c24c36000000000000000000000000"
execution_type: "limit"
order_type: "buy_po"
price: "0.000000000000001"
trigger_price: "0"
quantity: "1000000000000000"
filled_quantity: "0"
state: "canceled"
created_at: 1669998524140
updated_at: 1670919410587
direction: "buy"
}
paging {
total: 1000
}
Parameter | Type | Description |
---|---|---|
orders | SpotOrderHistory Array | List of prior spot orders |
paging | Paging | Pagination of results |
SpotOrderHistory
Parameter | Type | Description |
---|---|---|
order_hash | String | Hash of the order |
quantity | String | Quantity of the order |
is_active | Boolean | Indicates if the order is active |
state | String | Order state (Should be one of: ["booked", "partial_filled", "filled", "canceled"]) |
trigger_price | String | Trigger price used by stop/take orders |
market_id | String | ID of the spot market |
created_at | Integer | Order created timestamp in UNIX millis |
updated_at | Integer | Order updated timestamp in UNIX millis |
price | String | Price of the order |
subaccount_id | String | ID of the subaccount that the order belongs to |
order_type | String | Order type (Should be one of: ["buy", "sell", "stop_buy", "stop_sell", "take_buy", "take_sell", "buy_po", "sell_po"]) |
execution_type | String | The type of the order (Should be one of: ["limit", "market"]) |
filled_quantity | String | The amount of the quantity filled |
direction | String | The direction of the order (Should be one of: ["buy", "sell"]) |
Paging
Parameter | Type | Description |
---|---|---|
total | Integer | Total number of available records |
StreamOrdersHistory
Stream order updates for spot markets. If no parameters are given, updates to all subaccounts in all spot markets will be streamed.
IP rate limit group: indexer
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
network = Network.testnet()
client = AsyncClient(network)
market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
order_side = "buy"
subaccount_id = "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000"
orders = await client.stream_historical_spot_orders(
market_id=market_id,
order_side=order_side
)
async for order in orders:
print(order)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
import {
TradeDirection,
PaginationOption,
IndexerGrpcSpotApi,
TradeExecutionType,
} from '@injectivelabs/sdk-ts'
import { getNetworkEndpoints, Network } from '@injectivelabs/networks'
import { OrderSide } from '@injectivelabs/ts-types';
(async () => {
const endpoints = getNetworkEndpoints(Network.TestnetK8s)
const indexerGrpcSpotApi = new IndexerGrpcSpotApi(endpoints.indexer)
const marketIds = ['0x...'] /* optional param */
const executionTypes = [TradeExecutionType.Market] /* optional param */
const orderTypes = [OrderSide.Buy]; /* optional param */
const direction = TradeDirection.Buy /* optional param */
const subaccountId = '0x...' /* optional param */
const paginationOption = {} as PaginationOption /* optional param */
const orderHistory = await indexerGrpcSpotApi.fetchOrderHistory({
marketIds,
executionTypes,
orderTypes,
direction,
subaccountId,
pagination: paginationOption,
});
console.log(orderHistory)
})();
Parameter | Type | Description | Required |
---|---|---|---|
market_id | String | Filter by market ID | Yes |
subaccount_id | String | Filter by subaccount ID | No |
direction | String | Filter by direction (Should be one of: ["buy", "sell"]) | No |
state | String | Filter by state (Should be one of: ["booked", "partial_filled", "filled", "canceled"]) | No |
order_types | String Array | Filter by order type (Should be one of: ["buy", "sell", "stop_buy", "stop_sell", "take_buy", "take_sell", "buy_po", "sell_po"]) | No |
execution_types | String Array | Filter by execution type (Should be one of: ["limit", "market"]) | No |
Response Parameters
Streaming Response Example:
order {
order_hash: "0xe34ada890ab627fb904d8dd50411a4ca64d1f6cb56c7305a2833772b36ae5660"
market_id: "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
is_active: true
subaccount_id: "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000"
execution_type: "limit"
order_type: "buy_po"
price: "0.000000000001849"
trigger_price: "0"
quantity: "10817000000000000000"
filled_quantity: "0"
state: "booked"
created_at: 1665486460484
updated_at: 1665486460484
direction: "buy"
}
operation_type: "insert"
timestamp: 1665486462000
Parameter | Type | Description |
---|---|---|
order | SpotOrderHistory | Updated Order |
operation_type | String | Order update type (Should be one of: ["insert", "replace", "update", "invalidate"]) |
timestamp | Integer | Operation timestamp in UNIX millis |
SpotOrderHistory
Parameter | Type | Description |
---|---|---|
order_hash | String | Hash of the order |
quantity | String | Quantity of the order |
is_active | Boolean | Indicates if the order is active |
state | String | Order state (Should be one of: ["booked", "partial_filled", "filled", "canceled"]) |
trigger_price | String | Trigger price used by stop/take orders |
market_id | String | Spot Market ID |
created_at | Integer | Order created timestamp in UNIX millis |
updated_at | Integer | Order updated timestamp in UNIX millis |
price | String | Price of the order |
subaccount_id | String | ID of the subaccount that this order belongs to |
order_type | String | Order type (Should be one of: ["buy", "sell", "stop_buy", "stop_sell", "take_buy", "take_sell", "buy_po", "sell_po"]) |
execution_type | String | Execution type of the order (Should be one of: ["limit", "market"]) |
filled_quantity | String | The amount of order quantity filled |
direction | String | The direction of the order (Should be one of: ["buy", "sell"]) |
Trades
Get trade history for a spot market. The default request returns all spot trades from all markets.
IP rate limit group: indexer
*Trade execution types
"market"
for market orders"limitFill"
for a resting limit order getting filled by a market order"limitMatchRestingOrder"
for a resting limit order getting matched with another new limit order"limitMatchNewOrder"
for a new limit order getting matched immediately
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
network = Network.testnet()
client = AsyncClient(network)
market_ids = ["0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"]
execution_side = "taker"
direction = "buy"
subaccount_id = "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001"
execution_types = ["limitMatchNewOrder", "market"]
orders = await client.get_spot_trades(
market_ids=market_ids,
execution_side=execution_side,
direction=direction,
subaccount_id=subaccount_id,
execution_types=execution_types
)
print(orders)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
spotExchangePB "github.com/InjectiveLabs/sdk-go/exchange/spot_exchange_rpc/pb"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
panic(err)
}
ctx := context.Background()
marketId := "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0"
subaccountId := "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
req := spotExchangePB.TradesRequest{
MarketId: marketId,
SubaccountId: subaccountId,
}
res, err := exchangeClient.GetSpotTrades(ctx, req)
if err != nil {
panic(err)
}
str, _ := json.MarshalIndent(res, "", " ")
fmt.Print(string(str))
}
import {
TradeDirection,
PaginationOption,
TradeExecutionType,
IndexerGrpcSpotApi,
} from "@injectivelabs/sdk-ts";
import { getNetworkEndpoints, Network } from "@injectivelabs/networks";
(async () => {
const endpoints = getNetworkEndpoints(Network.TestnetK8s);
const indexerGrpcSpotApi = new IndexerGrpcSpotApi(endpoints.indexer);
const marketId = "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce";
const executionTypes = [TradeExecutionType.Market];
const direction = TradeDirection.Buy;
const subaccountId = "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000";
const paginationOption = {} as PaginationOption;
const trades = await indexerGrpcSpotApi.fetchTrades({
marketId,
executionTypes,
direction,
subaccountId,
pagination: paginationOption,
});
console.log(trades);
})();
Parameter | Type | Description | Required |
---|---|---|---|
market_id | String | Filter by a single market ID | No |
market_ids | String Array | Filter by multiple market IDs | No |
subaccount_id | String | Filter by a single subaccount ID | No |
subaccount_ids | String Array | Filter by multiple subaccount IDs | No |
direction | String | Filter by the direction of the trade (Should be one of: ["buy", "sell"]) | No |
execution_side | String | Filter by the execution side of the trade (Should be one of: ["maker", "taker"]) | No |
execution_types | String Array | Filter by the *trade execution type (Should be one of: ["market", "limitFill", "limitMatchRestingOrder", "limitMatchNewOrder"]) | No |
skip | Integer | Skip the first n items from the results. This can be used to fetch all trades since the API caps at 100 | No |
limit | Integer | Maximum number of items to be returned. 1 <= n <= 100 | No |
start_time | Integer | startTime <= trade execution timestamp <= endTime | No |
end_time | Integer | startTime <= trade execution timestamp <= endTime | No |
Response Parameters
Response Example:
trades {
order_hash: "0x250acb226cd0f888fa18a9923eaa3a484d2157b60925c74164aaa3beb8ea0d4a"
subaccount_id: "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001"
market_id: "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
trade_execution_type: "market"
trade_direction: "buy"
price {
price: "0.000000000007523"
quantity: "100000000000000000"
timestamp: 1675908341371
}
fee: "451.38"
executed_at: 1675908341371
fee_recipient: "inj1clw20s2uxeyxtam6f7m84vgae92s9eh7vygagt"
trade_id: "7962343_1_0"
execution_side: "taker"
}
trades {
order_hash: "0xf437ef4da3d143ffa8c8faf0964d10cece38fb9213fd9f26dd089bf874b22745"
subaccount_id: "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001"
market_id: "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
trade_execution_type: "limitMatchNewOrder"
trade_direction: "buy"
price {
price: "0.000000000007523"
quantity: "10000000000000000"
timestamp: 1675902943256
}
fee: "45.138"
executed_at: 1675902943256
fee_recipient: "inj1clw20s2uxeyxtam6f7m84vgae92s9eh7vygagt"
trade_id: "7960022_3_0"
execution_side: "taker"
}
trades {
order_hash: "0x80ba741245dc1d78e97897f7d423c1f663fb4b368b0b95ab73b6f1756a656056"
subaccount_id: "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001"
market_id: "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
trade_execution_type: "limitMatchNewOrder"
trade_direction: "buy"
price {
price: "0.000000000007523"
quantity: "10000000000000000"
timestamp: 1675902280096
}
fee: "45.138"
executed_at: 1675902280096
fee_recipient: "inj1clw20s2uxeyxtam6f7m84vgae92s9eh7vygagt"
trade_id: "7959737_3_0"
execution_side: "taker"
}
paging {
total: 3
}
{
"trades": [
{
"order_hash": "0xdc7cb11c1ad1edd129848da46b3c02f3a6860bc1478b8ba0620f7c18bae0eefe",
"subaccount_id": "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000",
"market_id": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
"trade_execution_type": "limitFill",
"position_delta": {
"trade_direction": "sell",
"execution_price": "42536400000",
"execution_quantity": "0.02",
"execution_margin": "850728000"
},
"payout": "850728000",
"fee": "425364",
"executed_at": 1652793510591,
"fee_recipient": "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r"
},
{
"order_hash": "0x5e871a3dfb977acdd6727b6a4fa8156750b89078ad425406ffb2a9d06898ebf5",
"subaccount_id": "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000",
"market_id": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
"trade_execution_type": "limitMatchRestingOrder",
"position_delta": {
"trade_direction": "buy",
"execution_price": "40128736026.409431766475",
"execution_quantity": "0.02",
"execution_margin": "833072000"
},
"payout": "0",
"fee": "401287.36026409431766475",
"executed_at": 1652775275064,
"fee_recipient": "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r"
}
]
}
[
{
"orderHash": "0xf7b0741b6e6ca6121f7747f662348674efc12e544746caf2d6cd045d6782dcb9",
"subaccountId": "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000",
"marketId": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
"tradeExecutionType": "limitMatchRestingOrder",
"tradeDirection": "buy",
"price": {
"price": "0.000000000001880078",
"quantity": "32000000000000000000",
"timestamp": 1653642433329
},
"fee": "60162.496",
"executedAt": 1653642433329,
"feeRecipient": "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r"
},
{
"orderHash": "0x6f0be3232ffd084c0377302177c9fcf5caafea412c6c8d2daa352c91bd3c1c3c",
"subaccountId": "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000",
"marketId": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
"tradeExecutionType": "limitMatchRestingOrder",
"tradeDirection": "buy",
"price": {
"price": "0.0000000000018405",
"quantity": "26000000000000000000",
"timestamp": 1653631819163
},
"fee": "47853",
"executedAt": 1653631819163,
"feeRecipient": "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r"
}
]
Parameter | Type | Description |
---|---|---|
trades | SpotTrade Array | Trades of a particular spot market |
paging | Paging | Pagination of results |
SpotTrade
Parameter | Type | Description |
---|---|---|
trade_direction | String | Direction of the trade(Should be one of: ["buy", "sell"]) |
trade_execution_type | String | Execution type of the trade (Should be one of: ["market", "limitFill", "limitMatchRestingOrder", "limitMatchNewOrder"]) |
fee | String | The fee associated with the trade (quote asset denom) |
market_id | String | The ID of the market that this trade is in |
order_hash | String | The order hash |
price | PriceLevel | Price level at which trade has been executed |
subaccount_id | String | The subaccountId that executed the trade |
executed_at | Integer | Timestamp of trade execution (on chain) in UNIX millis |
fee_recipient | String | The address that received 40% of the fees |
trade_id | String | Unique identifier to differentiate between trades |
execution_side | String | Execution side of trade (Should be one of: ["maker", "taker"]) |
PriceLevel
Parameter | Type | Description |
---|---|---|
price | String | Price number of the price level |
quantity | String | Quantity of the price level |
timestamp | Integer | Price level last updated timestamp in UNIX millis |
Paging
Parameter | Type | Description |
---|---|---|
total | Integer | Total number of records available |
StreamTrades
Stream newly executed trades of spot markets. The default request streams trades from all spot markets.
IP rate limit group: indexer
*Trade execution types
"market"
for market orders"limitFill"
for a resting limit order getting filled by a market order"limitMatchRestingOrder"
for a resting limit order getting matched with another new limit order"limitMatchNewOrder"
for a new limit order getting matched immediately
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
network = Network.testnet()
client = AsyncClient(network)
market_ids = [
"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
"0x7a57e705bb4e09c88aecfc295569481dbf2fe1d5efe364651fbe72385938e9b0"
]
execution_side = "maker"
direction = "sell"
subaccount_id = "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001"
execution_types = ["limitMatchRestingOrder"]
trades = await client.stream_spot_trades(
market_ids=market_ids,
execution_side=execution_side,
direction=direction,
subaccount_id=subaccount_id,
execution_types=execution_types
)
async for trade in trades:
print(trade)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
spotExchangePB "github.com/InjectiveLabs/sdk-go/exchange/spot_exchange_rpc/pb"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
fmt.Println(err)
}
ctx := context.Background()
marketId := "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0"
subaccountId := "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
req := spotExchangePB.StreamTradesRequest{
MarketId: marketId,
SubaccountId: subaccountId,
}
stream, err := exchangeClient.StreamSpotTrades(ctx, req)
if err != nil {
fmt.Println(err)
}
for {
select {
case <-ctx.Done():
return
default:
res, err := stream.Recv()
if err != nil {
fmt.Println(err)
return
}
str, _ := json.MarshalIndent(res, "", " ")
fmt.Print(string(str))
}
}
}
import {
TradeDirection,
PaginationOption,
IndexerGrpcSpotStream,
SpotTradesStreamCallback,
} from "@injectivelabs/sdk-ts";
import { getNetworkEndpoints, Network } from "@injectivelabs/networks";
(async () => {
const endpoints = getNetworkEndpoints(Network.TestnetK8s);
const indexerGrpcSpotStream = new IndexerGrpcSpotStream(endpoints.indexer);
const marketIds = [
"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
];
const subaccountId =
"0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001";
const direction = TradeDirection.Buy;
const pagination = {} as PaginationOption;
const streamFn = indexerGrpcSpotStream.streamSpotTrades.bind(
indexerGrpcSpotStream
);
const callback: SpotTradesStreamCallback = (trades) => {
console.log(trades);
};
const streamFnArgs = {
marketIds,
subaccountId,
direction,
pagination,
callback,
};
streamFn(streamFnArgs);
})();
Parameter | Type | Description | Required |
---|---|---|---|
market_id | String | Filter by a single market ID | No |
market_ids | String Array | Filter by multiple market IDs | No |
subaccount_id | String | Filter by a single subaccount ID | No |
subaccount_ids | String Array | Filter by multiple subaccount IDs | No |
direction | String | Filter by the direction of the trade (Should be one of: ["buy", "sell"]) | No |
execution_side | String | Filter by the execution side of the trade (Should be one of: ["maker", "taker"]) | No |
execution_types | String Array | Filter by the *trade execution type (Should be one of: ["market", "limitFill", "limitMatchRestingOrder", "limitMatchNewOrder"]) | No |
Response Parameters
Streaming Response Example:
trade {
order_hash: "0x03b7ac1869cbdead911b2953cd6a0eae119312783b5fbee9db65ad2a53c5ce6d"
subaccount_id: "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001"
market_id: "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
trade_execution_type: "limitMatchRestingOrder"
trade_direction: "sell"
price {
price: "0.000000000007523"
quantity: "10000000000000000"
timestamp: 1676015144404
}
fee: "-7.523"
executed_at: 1676015144404
fee_recipient: "inj1clw20s2uxeyxtam6f7m84vgae92s9eh7vygagt"
trade_id: "8007760_1_0"
execution_side: "maker"
}
operation_type: "insert"
timestamp: 1676015190000
trade {
order_hash: "0x03b7ac1869cbdead911b2953cd6a0eae119312783b5fbee9db65ad2a53c5ce6d"
subaccount_id: "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001"
market_id: "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
trade_execution_type: "limitMatchRestingOrder"
trade_direction: "sell"
price {
price: "0.000000000007523"
quantity: "10000000000000000"
timestamp: 1676015256701
}
fee: "-7.523"
executed_at: 1676015256701
fee_recipient: "inj1clw20s2uxeyxtam6f7m84vgae92s9eh7vygagt"
trade_id: "8007808_1_0"
execution_side: "maker"
}
operation_type: "insert"
timestamp: 1676015260000
{
"trade": {
"order_hash": "0x88e34872af0147f57c8c5a093c3a6a8a97358615bccf975b4a06dfb5162daeaf",
"subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"market_id": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
"trade_execution_type": "market",
"trade_direction": "sell",
"price": {
"price": "0.000000000001654",
"quantity": "1000000000000000000",
"timestamp": 1653042087046
},
"fee": "3308",
"executed_at": 1653042087046,
"fee_recipient": "inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8"
},
"operation_type": "insert",
"timestamp": 1653042089000
}{
"trade": {
"order_hash": "0xb5d651a01faa90ec53b0fa34f00f3ecdfe169f9fc35be8114ee113eea9257c30",
"subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"market_id": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
"trade_execution_type": "market",
"trade_direction": "sell",
"price": {
"price": "0.000000000001654",
"quantity": "2000000000000000000",
"timestamp": 1653042093023
},
"fee": "6616",
"executed_at": 1653042093023,
"fee_recipient": "inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8"
},
"operation_type": "insert",
"timestamp": 1653042098000
}
{
"trade": {
"orderHash": "0xedf6203fce7e3391052ddd8244385b267ddbe81aebd90724cde09c0c1b4af73b",
"subaccountId": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"marketId": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
"tradeExecutionType": "market",
"tradeDirection": "sell",
"price": {
"price": "0.000000000003",
"quantity": "1000000000000000000",
"timestamp": 1654080019844
},
"fee": "6000",
"executedAt": 1654080019844,
"feeRecipient": "inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8"
},
"operationType": "insert",
"timestamp": 1654080026000
}
{
"trade": {
"orderHash": "0xac596cc795ba91dc8f10b6d251e211679f908be04f8becca566210fab20bfd2f",
"subaccountId": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"marketId": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
"tradeExecutionType": "market",
"tradeDirection": "sell",
"price": {
"price": "0.000000000003",
"quantity": "49000000000000000000",
"timestamp": 1654080025588
},
"fee": "294000",
"executedAt": 1654080025588,
"feeRecipient": "inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8"
},
"operationType": "insert",
"timestamp": 1654080028000
}
Parameter | Type | Description |
---|---|---|
trade | SpotTrade | New spot market trade |
operation_type | String | Trade operation type (Should be one of: ["insert", "invalidate"]) |
timestamp | Integer | Timestamp the new trade is written into the database in UNIX millis |
SpotTrade
Parameter | Type | Description |
---|---|---|
trade_direction | String | Direction of the trade(Should be one of: ["buy", "sell"]) |
trade_execution_type | String | Execution type of the trade (Should be one of: ["market", "limitFill", "limitMatchRestingOrder", "limitMatchNewOrder"]) |
fee | String | The fee associated with the trade (quote asset denom) |
market_id | String | The ID of the market that this trade is in |
order_hash | String | The order hash |
price | PriceLevel | Price level at which trade has been executed |
subaccount_id | String | The subaccountId that executed the trade |
executed_at | Integer | Timestamp of trade execution (on chain) in UNIX millis |
fee_recipient | String | The address that received 40% of the fees |
trade_id | String | Unique identifier to differentiate between trades |
execution_side | String | Execution side of trade (Should be one of: ["maker", "taker"]) |
PriceLevel
Parameter | Type | Description |
---|---|---|
price | String | Price number of the price level |
quantity | String | Quantity of the price level |
timestamp | Integer | Price level last updated timestamp in UNIX millis |
[DEPRECATED] Orderbook
Get the orderbook of a spot market.
Deprecation warning
This API will be removed on April 5, 2023 on testnet and on April 22, 2023 on mainnet. Please use the new api OrderbookV2 instead.
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
client = AsyncClient(network)
market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
orderbook = await client.get_spot_orderbook(market_id=market_id)
print(orderbook)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
fmt.Println(err)
}
ctx := context.Background()
marketId := "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0"
res, err := exchangeClient.GetSpotOrderbook(ctx, marketId)
if err != nil {
fmt.Println(err)
}
str, _ := json.MarshalIndent(res, "", " ")
fmt.Print(string(str))
}
import { getNetworkInfo, Network } from "@injectivelabs/networks";
import { protoObjectToJson, ExchangeClient } from "@injectivelabs/sdk-ts";
(async () => {
const network = getNetworkInfo(Network.Testnet);
const marketId = "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0";
const exchangeClient = new ExchangeClient.ExchangeGrpcClient(
network.exchangeApi
);
const market = await exchangeClient.spotApi.fetchSpotOrderbook(marketId);
console.log(protoObjectToJson(market, {}));
})();
Parameter | Type | Description | Required |
---|---|---|---|
market_id | String | Market ID of the spot market to get orderbook from | Yes |
Response Parameters
Response Example:
orderbook {
buys {
price: "0.000000000007"
quantity: "1000000000000000000"
timestamp: 1669998494728
}
buys {
price: "0.000000000001"
quantity: "10000000000000000"
timestamp: 1675882430039
}
buys {
price: "0.000000000000001"
quantity: "11553000000000000000"
timestamp: 1675904400063
}
sells {
price: "0.000000000007523"
quantity: "70000000000000000"
timestamp: 1675904636889
}
sells {
price: "0.000000000007525"
quantity: "10000000000000000"
timestamp: 1676058445306
}
sells {
price: "0.000000000007526"
quantity: "20000000000000000"
timestamp: 1676015247335
}
sells {
price: "0.000000000008"
quantity: "10000000000000000"
timestamp: 1676015125593
}
}
{
"orderbook": {
"buys": [
{
"price": "0.000000000001654",
"quantity": "27000000000000000000",
"timestamp": 1652395260912
},
{
"price": "0.000000000001608",
"quantity": "38000000000000000000",
"timestamp": 1652351094680
},
],
"sells": [
{
"price": "0.000000000002305",
"quantity": "28000000000000000000",
"timestamp": 1652774849587
},
{
"price": "0.00000000000231",
"quantity": "10000000000000000000",
"timestamp": 1652774849587
},
{
"price": "0.000000000002313",
"quantity": "20000000000000000000",
"timestamp": 1652774849587
},
{
"price": "0.0000000003",
"quantity": "220000000000000000000",
"timestamp": 1652264026293
}
]
}
}
{
"orderbook": {
"buysList": [
{
"price": "0.000000000002375",
"quantity": "4000000000000000000",
"timestamp": 1653968629289
},
{
"price": "0.000000000002349",
"quantity": "14000000000000000000",
"timestamp": 1653968629289
},
{
"price": "0.000000000002336",
"quantity": "34000000000000000000",
"timestamp": 1653968629289
},
{
"price": "0.000000000001",
"quantity": "4000000000000000000",
"timestamp": 1653930539754
}
],
"sellsList": [
{
"price": "0.0000000000025",
"quantity": "1000000000000000000",
"timestamp": 1654080089976
}
]
}
}
Parameter | Type | Description |
---|---|---|
orderbook | SpotLimitOrderbook | Orderbook of a particular spot market |
SpotLimitOrderbook
Parameter | Type | Description |
---|---|---|
buys | PriceLevel Array | List of price levels for buys |
sells | PriceLevel Array | List of price levels for sells |
PriceLevel
Parameter | Type | Description |
---|---|---|
price | String | Price number of the price level |
quantity | String | Quantity of the price level |
timestamp | Integer | Price level last updated timestamp in UNIX millis |
[DEPRECATED] Orderbooks
Get the orderbooks for one or more spot markets.
Deprecation warning
This API will be removed on April 5, 2023 on testnet and on April 22, 2023 on mainnet. Please use the new api OrderbookV2 instead.
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
network = Network.testnet()
client = AsyncClient(network)
market_ids = [
"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
"0x7a57e705bb4e09c88aecfc295569481dbf2fe1d5efe364651fbe72385938e9b0"
]
orderbooks = await client.get_spot_orderbooks(market_ids=market_ids)
print(orderbooks)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
fmt.Println(err)
}
ctx := context.Background()
marketIds := []string{"0x26413a70c9b78a495023e5ab8003c9cf963ef963f6755f8b57255feb5744bf31", "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0"}
res, err := exchangeClient.GetSpotOrderbooks(ctx, marketIds)
if err != nil {
fmt.Println(err)
}
str, _ := json.MarshalIndent(res, "", " ")
fmt.Print(string(str))
}
import { getNetworkInfo, Network } from "@injectivelabs/networks";
import { protoObjectToJson } from "@injectivelabs/sdk-ts";
import { ExchangeGrpcClient } from "@injectivelabs/sdk-ts/dist/client/exchange/ExchangeGrpcClient";
(async () => {
const network = getNetworkInfo(Network.TestnetK8s);
const marketIds = ["0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0", "0x0511ddc4e6586f3bfe1acb2dd905f8b8a82c97e1edaef654b12ca7e6031ca0fa"];
const exchangeClient = new ExchangeGrpcClient(
network.exchangeApi
);
const market = await exchangeClient.spot.fetchOrderbooks(marketIds);
console.log(protoObjectToJson(market));
})();
Parameter | Type | Description | Required |
---|---|---|---|
market_ids | String Array | Filter by one or more market IDs | Yes |
Response Parameters
Response Example:
orderbooks {
market_id: "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
orderbook {
buys {
price: "0.000000000006057"
quantity: "38000000000000000000"
timestamp: 1652395483345
}
buys {
price: "0.000000000005643"
quantity: "8000000000000000000"
timestamp: 1652340918434
}
sells {
price: "0.000000000008102"
quantity: "50000000000000000000"
timestamp: 1652773614923
}
sells {
price: "0.000000000008108"
quantity: "48000000000000000000"
timestamp: 1652774630240
orderbooks {
market_id: "0x7a57e705bb4e09c88aecfc295569481dbf2fe1d5efe364651fbe72385938e9b0"
orderbook {
buys {
price: "0.000000000001654"
quantity: "27000000000000000000"
timestamp: 1652395260912
}
buys {
price: "0.000000000001608"
quantity: "38000000000000000000"
timestamp: 1652351094680
sells {
price: "0.00000000002792"
quantity: "30000000000000000"
timestamp: 1652263504751
}
sells {
price: "0.0000000003"
quantity: "220000000000000000000"
timestamp: 1652264026293
}
}
}
{
"orderbooks": [
{
"market_id": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
"orderbook": {
"buys": [
{
"price": "0.000000000001654",
"quantity": "27000000000000000000",
"timestamp": 1652395260912
},
{
"price": "0.000000000000001",
"quantity": "62000000000000000",
"timestamp": 1649838645114
}
],
"sells": [
{
"price": "0.00000000002792",
"quantity": "30000000000000000",
"timestamp": 1652263504751
},
{
"price": "0.0000000003",
"quantity": "220000000000000000000",
"timestamp": 1652264026293
}
]
}
},
{
"market_id": "0x26413a70c9b78a495023e5ab8003c9cf963ef963f6755f8b57255feb5744bf31",
"orderbook": {
"buys": [
{
"price": "0.000000000006057",
"quantity": "38000000000000000000",
"timestamp": 1652395483345
},
{
"price": "0.000000000005643",
"quantity": "8000000000000000000",
"timestamp": 1652340012497
},
{
"price": "0.000000000005374",
"quantity": "46000000000000000000",
"timestamp": 1652340012497
}
],
"sells": [
{
"price": "0.000000000014033",
"quantity": "48000000000000000000",
"timestamp": 1650976706210
},
{
"price": "0.000000000014036",
"quantity": "48000000000000000000",
"timestamp": 1650974855789
},
{
"price": "0.000000000014094",
"quantity": "44000000000000000000",
"timestamp": 1650976917202
}
]
}
}
]
}
{
"orderbooksList": [
{
"marketId": "0x0511ddc4e6586f3bfe1acb2dd905f8b8a82c97e1edaef654b12ca7e6031ca0fa",
"orderbook": {
"buysList": [
{
"price": "22",
"quantity": "1000000",
"timestamp": 1654080262300
}
],
"sellsList": [
{
"price": "23",
"quantity": "10000",
"timestamp": 1654080273783
}
]
}
},
{
"marketId": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
"orderbook": {
"buysList": [
{
"price": "0.000000000002375",
"quantity": "4000000000000000000",
"timestamp": 1653968629289
},
{
"price": "0.000000000002349",
"quantity": "14000000000000000000",
"timestamp": 1653968629289
},
{
"price": "0.000000000002336",
"quantity": "34000000000000000000",
"timestamp": 1653968629289
},
{
"price": "0.000000000001",
"quantity": "4000000000000000000",
"timestamp": 1653930539754
}
],
"sellsList": [
{
"price": "0.0000000000025",
"quantity": "1000000000000000000",
"timestamp": 1654080089976
}
]
}
}
]
}
Parameter | Type | Description |
---|---|---|
orderbooks | SingleSpotLimitOrderbook Array | List of spot market orderbooks with market IDs |
SingleSpotLimitOrderbook
Parameter | Type | Description |
---|---|---|
market_id | String | ID of spot market |
orderbook | SpotLimitOrderBook | Orderbook of the market |
SpotLimitOrderbook
Parameter | Type | Description |
---|---|---|
buys | PriceLevel Array | List of price levels for buys |
sells | PriceLevel Array | List of price levels for sells |
PriceLevel
Parameter | Type | Description |
---|---|---|
price | String | Price number of the price level |
quantity | String | Quantity of the price level |
timestamp | Integer | Price level last updated timestamp in UNIX millis |
[DEPRECATED] StreamOrderbooks
Stream orderbook updates for an array of spot markets.
Deprecation warning
This API will be removed on April 5, 2023 on testnet and on April 22, 2023 on mainnet. Please use the new api OrderbookV2 instead.
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
client = AsyncClient(network)
market_ids = [
"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
"0x7a57e705bb4e09c88aecfc295569481dbf2fe1d5efe364651fbe72385938e9b0"
]
orderbook = await client.stream_spot_orderbooks(market_ids=market_ids)
async for orders in orderbook:
print(orders)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
fmt.Println(err)
}
ctx := context.Background()
marketIds := []string{"0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0"}
stream, err := exchangeClient.StreamSpotOrderbook(ctx, marketIds)
if err != nil {
fmt.Println(err)
}
for {
select {
case <-ctx.Done():
return
default:
res, err := stream.Recv()
if err != nil {
fmt.Println(err)
return
}
str, _ := json.MarshalIndent(res, "", " ")
fmt.Print(string(str))
}
}
}
import { getNetworkInfo, Network } from "@injectivelabs/networks";
import { protoObjectToJson } from "@injectivelabs/sdk-ts";
import { ExchangeGrpcStreamClient } from "@injectivelabs/sdk-ts/dist/client/exchange/ExchangeGrpcStreamClient";;
(async () => {
const network = getNetworkInfo(Network.TestnetK8s);
const marketIds = ["0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0"];
const exchangeClient = new ExchangeGrpcStreamClient(
network.exchangeApi
);
await exchangeClient.spot.streamSpotOrderbook(
{
marketIds,
callback: (streamSpotOrderbook) => {
console.log(protoObjectToJson(streamSpotOrderbook));
},
onEndCallback: (status) => {
console.log("Stream has ended with status: " + status);
},
});
})();
Parameter | Type | Description | Required |
---|---|---|---|
market_ids | String Array | List of market IDs for orderbook streaming; empty means all spot markets | Yes |
Response Parameters
Streaming Response Example:
orderbook {
buys {
price: "0.000000000007"
quantity: "1000000000000000000"
timestamp: 1669998494728
}
buys {
price: "0.000000000001"
quantity: "10000000000000000"
timestamp: 1675882430039
}
buys {
price: "0.000000000000001"
quantity: "11553000000000000000"
timestamp: 1675904400063
}
sells {
price: "0.000000000007523"
quantity: "40000000000000000"
timestamp: 1675904636889
}
sells {
price: "0.000000000007525"
quantity: "10000000000000000"
timestamp: 1676064156831
}
sells {
price: "0.000000000007526"
quantity: "40000000000000000"
timestamp: 1676015247335
}
sells {
price: "0.000000000008"
quantity: "10000000000000000"
timestamp: 1676015125593
}
}
operation_type: "update"
timestamp: 1676089310000
market_id: "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
orderbook {
buys {
price: "0.000000000007"
quantity: "1000000000000000000"
timestamp: 1669998494728
}
buys {
price: "0.000000000001"
quantity: "10000000000000000"
timestamp: 1675882430039
}
buys {
price: "0.000000000000001"
quantity: "11553000000000000000"
timestamp: 1675904400063
}
sells {
price: "0.000000000007523"
quantity: "40000000000000000"
timestamp: 1675904636889
}
sells {
price: "0.000000000007525"
quantity: "10000000000000000"
timestamp: 1676089482358
}
sells {
price: "0.000000000007526"
quantity: "50000000000000000"
timestamp: 1676015247335
}
sells {
price: "0.000000000008"
quantity: "10000000000000000"
timestamp: 1676015125593
}
}
operation_type: "update"
timestamp: 1676089487000
market_id: "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
{
"orderbook": {
"buys": [
{
"price": "0.000000000002349",
"quantity": "14000000000000000000",
"timestamp": 1653968629289
},
{
"price": "0.000000000002336",
"quantity": "34000000000000000000",
"timestamp": 1653968629289
},
{
"price": "0.000000000002328",
"quantity": "12000000000000000000",
"timestamp": 1653968629289
},
{
"price": "0.000000000001",
"quantity": "4000000000000000000",
"timestamp": 1653930539754
}
],
"sells": [
{
"price": "0.000000000003",
"quantity": "1000000000000000000",
"timestamp": 1654080771385
}
]
},
"operation_type": "update",
"timestamp": 1654080908000,
"market_id": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0"
}
{
"orderbook": {
"buysList": [
{
"price": "0.000000000002375",
"quantity": "4000000000000000000",
"timestamp": 1653968629289
},
{
"price": "0.0000000000015",
"quantity": "46000000000000000000",
"timestamp": 1652340323984
},
{
"price": "0.000000000001",
"quantity": "4000000000000000000",
"timestamp": 1653930539754
}
],
"sellsList": []
},
"operationType": "update",
"timestamp": 1654080598000,
"marketId": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0"
}
Parameter | Type | Description |
---|---|---|
orderbook | SpotLimitOrderbook | Orderbook of a Spot Market |
operation_type | String | Order update type (Should be one of: ["insert", "replace", "update", "invalidate"]) |
timestamp | Integer | Operation timestamp in UNIX millis |
market_id | String | ID of the market the orderbook belongs to |
SpotLimitOrderbook
Parameter | Type | Description |
---|---|---|
buys | PriceLevel Array | List of price levels for buys |
sells | PriceLevel Array | List of price levels for sells |
PriceLevel
Parameter | Type | Description |
---|---|---|
price | String | Price number of the price level |
quantity | String | Quantity of the price level |
timestamp | Integer | Price level last updated timestamp in UNIX millis |
OrderbooksV2
Get an orderbook snapshot for one or more spot markets.
IP rate limit group: indexer
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
client = AsyncClient(network)
market_ids = [
"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
"0x7a57e705bb4e09c88aecfc295569481dbf2fe1d5efe364651fbe72385938e9b0"
]
orderbooks = await client.get_spot_orderbooksV2(market_ids=market_ids)
print(orderbooks)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
import { IndexerGrpcSpotApi } from "@injectivelabs/sdk-ts";
import { getNetworkEndpoints, Network } from "@injectivelabs/networks";
(async () => {
const endpoints = getNetworkEndpoints(Network.TestnetK8s);
const indexerGrpcSpotApi = new IndexerGrpcSpotApi(endpoints.indexer);
const marketId =
"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe";
const orderbook = await indexerGrpcSpotApi.fetchOrderbookV2(marketId);
console.log(orderbook);
})();
Parameter | Type | Description | Required |
---|---|---|---|
market_ids | String Array | List of IDs of markets to get orderbook snapshots from | Yes |
Response Parameters
Response Example:
orderbooks {
market_id: "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
orderbook {
buys {
price: "0.000000000006057"
quantity: "38000000000000000000"
timestamp: 1652395483345
}
buys {
price: "0.000000000005643"
quantity: "8000000000000000000"
timestamp: 1652340918434
}
sells {
price: "0.000000000008102"
quantity: "50000000000000000000"
timestamp: 1652773614923
}
sells {
price: "0.000000000008108"
quantity: "48000000000000000000"
timestamp: 1652774630240
sequence: 512
orderbooks {
market_id: "0x7a57e705bb4e09c88aecfc295569481dbf2fe1d5efe364651fbe72385938e9b0"
orderbook {
buys {
price: "0.000000000001654"
quantity: "27000000000000000000"
timestamp: 1652395260912
}
buys {
price: "0.000000000001608"
quantity: "38000000000000000000"
timestamp: 1652351094680
sells {
price: "0.00000000002792"
quantity: "30000000000000000"
timestamp: 1652263504751
}
sells {
price: "0.0000000003"
quantity: "220000000000000000000"
timestamp: 1652264026293
}
sequence: 711
}
}
{
sequence: 359910,
buys: [
{
price: '0.000000000003783',
quantity: '800000000000000000',
timestamp: 1680706007368
},
{
price: '0.00000000000373',
quantity: '8000000000000000000',
timestamp: 1680203525200
},
{
price: '0.000000000003541',
quantity: '10000000000000000000',
timestamp: 1680203525200
},
{
price: '0.00000000000354',
quantity: '6000000000000000000',
timestamp: 1680203525200
},
{
price: '0.000000000003391',
quantity: '18000000000000000000',
timestamp: 1680203525200
},
{
price: '0.000000000003',
quantity: '220000000000000000000',
timestamp: 1680367499208
},
{
price: '0.000000000002968',
quantity: '20000000000000000000',
timestamp: 1680203525200
},
{
price: '0.00000000000292',
quantity: '2900000000000000000',
timestamp: 1680203520210
},
{
price: '0.000000000002917',
quantity: '2000000000000000000',
timestamp: 1680001507406
},
{
price: '0.000000000002911',
quantity: '30000000000000000000',
timestamp: 1678692509153
},
{
price: '0.000000000002899',
quantity: '2000000000000000000',
timestamp: 1679572500545
},
{
price: '0.000000000002894',
quantity: '4000000000000000000',
timestamp: 1678692509153
},
{
price: '0.000000000002878',
quantity: '18000000000000000000',
timestamp: 1679572532055
},
{
price: '0.000000000002865',
quantity: '18000000000000000000',
timestamp: 1679572500545
},
{
price: '0.000000000002859',
quantity: '16000000000000000000',
timestamp: 1679572500545
},
{
price: '0.000000000002834',
quantity: '30000000000000000000',
timestamp: 1680203525200
},
{
price: '0.000000000002803',
quantity: '10000000000000000000',
timestamp: 1679572500545
},
{
price: '0.000000000002712',
quantity: '6000000000000000000',
timestamp: 1678692509153
},
{
price: '0.000000000002696',
quantity: '14000000000000000000',
timestamp: 1680203525200
},
{
price: '0.000000000002646',
quantity: '8000000000000000000',
timestamp: 1678692509153
},
{
price: '0.000000000002639',
quantity: '16000000000000000000',
timestamp: 1679572532055
},
{
price: '0.000000000002638',
quantity: '10000000000000000000',
timestamp: 1678692509153
},
{
price: '0.000000000002591',
quantity: '8000000000000000000',
timestamp: 1679572500545
},
{
price: '0.000000000002585',
quantity: '14000000000000000000',
timestamp: 1678692509153
},
{
price: '0.000000000002544',
quantity: '24000000000000000000',
timestamp: 1679572500545
},
{
price: '0.000000000002437',
quantity: '26000000000000000000',
timestamp: 1679572500545
},
{
price: '0.000000000002307',
quantity: '6000000000000000000',
timestamp: 1680001507406
},
{
price: '0.000000000002',
quantity: '1010000000000000000',
timestamp: 1680441737475
},
{
price: '0.000000000001969',
quantity: '1000000000000000000',
timestamp: 1678692502214
},
{
price: '0.000000000001949',
quantity: '12000000000000000000',
timestamp: 1677967315144
},
{
price: '0.00000000000188',
quantity: '30000000000000000000',
timestamp: 1677967315144
},
{
price: '0.000000000001823',
quantity: '10000000000000000000',
timestamp: 1678393343584
},
{
price: '0.000000000001811',
quantity: '28000000000000000000',
timestamp: 1678393343584
},
{
price: '0.00000000000169',
quantity: '4000000000000000000',
timestamp: 1678393343584
},
{
price: '0.00000000000167',
quantity: '14000000000000000000',
timestamp: 1678393343584
},
{
price: '0.0000000000015',
quantity: '1000000000000000',
timestamp: 1678876747101
},
{
price: '0.0000000000012',
quantity: '1000000000000000000',
timestamp: 1679447160553
},
{
price: '0.000000000001',
quantity: '11000000000000000',
timestamp: 1678876209661
},
{
price: '0.000000000000524',
quantity: '20000000000000000',
timestamp: 1680590417443
},
{
price: '0.000000000000001',
quantity: '17158000000000000000',
timestamp: 1680184521138
}
],
sells: [
{
price: '0.000000000006546',
quantity: '24000000000000000000',
timestamp: 1680770944037
},
{
price: '0.000000000006782',
quantity: '6000000000000000000',
timestamp: 1680770944037
},
{
price: '0.00000000000712',
quantity: '8000000000000000000',
timestamp: 1680770944037
},
{
price: '0.000000000007261',
quantity: '2000000000000000000',
timestamp: 1680771009040
},
{
price: '0.000000000007344',
quantity: '4000000000000000000',
timestamp: 1680771009040
},
{
price: '0.000000000007709',
quantity: '26000000000000000000',
timestamp: 1680771009040
},
{
price: '0.000000000007759',
quantity: '12000000000000000000',
timestamp: 1680771009040
},
{
price: '0.000000000007854',
quantity: '18000000000000000000',
timestamp: 1680770944037
},
{
price: '0.000000000008686',
quantity: '4000000000000000000',
timestamp: 1680770944037
},
{
price: '0.000000000008897',
quantity: '20000000000000000000',
timestamp: 1680771009040
},
{
price: '0.000000000008995',
quantity: '26000000000000000000',
timestamp: 1680766793814
},
{
price: '0.000000000009005',
quantity: '12000000000000000000',
timestamp: 1680766384883
},
{
price: '0.00000000000908',
quantity: '14000000000000000000',
timestamp: 1680766001957
},
{
price: '0.000000000009235',
quantity: '30000000000000000000',
timestamp: 1680763023661
},
{
price: '0.000000000009474',
quantity: '22000000000000000000',
timestamp: 1680734525680
},
{
price: '0.000000000009476',
quantity: '30000000000000000000',
timestamp: 1680718692037
},
{
price: '0.000000000009486',
quantity: '18000000000000000000',
timestamp: 1680738421510
},
{
price: '0.000000000009502',
quantity: '24000000000000000000',
timestamp: 1680719211313
},
{
price: '0.000000000009513',
quantity: '28000000000000000000',
timestamp: 1680731204023
},
{
price: '0.000000000009536',
quantity: '28000000000000000000',
timestamp: 1680741128906
},
{
price: '0.000000000009588',
quantity: '30000000000000000000',
timestamp: 1680720423137
},
{
price: '0.000000000009607',
quantity: '28000000000000000000',
timestamp: 1680735930195
},
{
price: '0.000000000009612',
quantity: '48000000000000000000',
timestamp: 1680728873346
},
{
price: '0.000000000009762',
quantity: '26000000000000000000',
timestamp: 1680561287193
},
{
price: '0.000000000009797',
quantity: '30000000000000000000',
timestamp: 1680541713262
},
{
price: '0.000000000009809',
quantity: '20000000000000000000',
timestamp: 1680539044375
},
{
price: '0.000000000009813',
quantity: '30000000000000000000',
timestamp: 1680544680029
},
{
price: '0.000000000009816',
quantity: '16000000000000000000',
timestamp: 1680562550057
},
{
price: '0.000000000009828',
quantity: '50000000000000000000',
timestamp: 1680552590986
},
{
price: '0.000000000009845',
quantity: '28000000000000000000',
timestamp: 1680548015586
},
{
price: '0.000000000009894',
quantity: '30000000000000000000',
timestamp: 1680564367217
},
{
price: '0.000000000009912',
quantity: '24000000000000000000',
timestamp: 1680565055834
},
{
price: '0.000000000009951',
quantity: '24000000000000000000',
timestamp: 1680580625008
},
{
price: '0.00000000002792',
quantity: '30000000000000000',
timestamp: 1680590417443
},
{
price: '0.0000000003',
quantity: '220000000000000000000',
timestamp: 1680367499208
}
]
}
Parameter | Type | Description |
---|---|---|
orderbooks | SingleSpotLimitOrderbookV2 Array | List of spot market orderbooks with market IDs |
SingleSpotLimitOrderbookV2
Parameter | Type | Description |
---|---|---|
market_id | String | ID of spot market |
orderbook | SpotLimitOrderBookV2 | Orderbook of the market |
SpotLimitOrderbookV2
Parameter | Type | Description |
---|---|---|
buys | PriceLevel Array | List of price levels for buys |
sells | PriceLevel Array | List of price levels for sells |
sequence | Integer | Sequence number of the orderbook; increments by 1 each update |
PriceLevel
Parameter | Type | Description |
---|---|---|
price | String | Price number of the price level |
quantity | String | Quantity of the price level |
timestamp | Integer | Price level last updated timestamp in UNIX millis |
StreamOrderbooksV2
Stream orderbook snapshot updates for one or more spot markets.
IP rate limit group: indexer
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
client = AsyncClient(network)
market_ids = ["0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"]
orderbooks = await client.stream_spot_orderbook_snapshot(market_ids=market_ids)
async for orderbook in orderbooks:
print(orderbook)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
import {
IndexerGrpcSpotStream,
SpotOrderbookV2StreamCallback,
} from "@injectivelabs/sdk-ts";
import { getNetworkEndpoints, Network } from "@injectivelabs/networks";
(async () => {
const endpoints = getNetworkEndpoints(Network.TestnetK8s);
const indexerGrpcSpotStream = new IndexerGrpcSpotStream(endpoints.indexer);
const marketIds = [
"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
];
const streamFn = indexerGrpcSpotStream.streamSpotOrderbookV2.bind(
indexerGrpcSpotStream
);
const callback: SpotOrderbookV2StreamCallback = (orderbooks) => {
console.log(orderbooks);
};
const streamFnArgs = {
marketIds,
callback,
};
streamFn(streamFnArgs);
})();
Parameter | Type | Description | Required |
---|---|---|---|
market_ids | String Array | List of market IDs for orderbook streaming; empty means all spot markets | Yes |
Response Parameters
Streaming Response Example:
orderbook {
buys {
price: "0.000000000007"
quantity: "1000000000000000000"
timestamp: 1675904400063
}
buys {
price: "0.000000000001"
quantity: "10000000000000000"
timestamp: 1675882430039
}
buys {
price: "0.000000000000001"
quantity: "17983000000000000000"
timestamp: 1675880932648
}
sells {
price: "0.000000000007523"
quantity: "20000000000000000"
timestamp: 1676610722671
}
sells {
price: "0.000000000007525"
quantity: "10000000000000000"
timestamp: 1676015247335
}
sells {
price: "0.000000000007526"
quantity: "50000000000000000"
timestamp: 1676089482358
}
sells {
price: "0.000000000008"
quantity: "10000000000000000"
timestamp: 1675904636889
}
sequence: 713
}
operation_type: "update"
timestamp: 1676610727000
market_id: "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
{
orderbook: {
sells: [{
price: "0.000000000008",
quantity: "10000000000000000",
timestamp: 1675904636889,
}],
buys: [{
price: "0.000000000001",
quantity: "10000000000000000",
timestamp: 1675882430039,
}],
sequence: 713
}
operationType: "update"
timestamp: 1676610727000
marketId: "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
}
Parameter | Type | Description |
---|---|---|
orderbook | SpotLimitOrderbookV2 | Orderbook of a Spot Market |
operation_type | String | Order update type (Should be one of: ["insert", "replace", "update", "invalidate"]) |
timestamp | Integer | Operation timestamp in UNIX millis |
market_id | String | ID of the market the orderbook belongs to |
SpotLimitOrderbookV2
Parameter | Type | Description |
---|---|---|
buys | PriceLevel Array | List of price levels for buys |
sells | PriceLevel Array | List of price levels for sells |
sequence | Integer | Sequence number of the orderbook; increments by 1 each update |
PriceLevel
Parameter | Type | Description |
---|---|---|
price | String | Price number of the price level |
quantity | String | Quantity of the price level |
timestamp | Integer | Price level last updated timestamp in UNIX millis |
StreamOrderbookUpdate
Stream incremental orderbook updates for one or more spot markets. This stream should be started prior to obtaining orderbook snapshots so that no incremental updates are omitted between obtaining a snapshot and starting the update stream.
IP rate limit group: indexer
Request Parameters
Request Example:
import asyncio
import logging
from decimal import *
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
class PriceLevel:
def __init__(self, price: Decimal, quantity: Decimal, timestamp: int):
self.price = price
self.quantity = quantity
self.timestamp = timestamp
def __str__(self) -> str:
return "price: {} | quantity: {} | timestamp: {}".format(self.price, self.quantity, self.timestamp)
class Orderbook:
def __init__(self, market_id: str):
self.market_id = market_id
self.sequence = -1
self.levels = {"buys": {}, "sells": {}}
async def load_orderbook_snapshot(async_client: AsyncClient, orderbook: Orderbook):
# load the snapshot
res = await async_client.get_spot_orderbooksV2(market_ids=[orderbook.market_id])
for snapshot in res.orderbooks:
if snapshot.market_id != orderbook.market_id:
raise Exception("unexpected snapshot")
orderbook.sequence = int(snapshot.orderbook.sequence)
for buy in snapshot.orderbook.buys:
orderbook.levels["buys"][buy.price] = PriceLevel(
price=Decimal(buy.price),
quantity=Decimal(buy.quantity),
timestamp=buy.timestamp,
)
for sell in snapshot.orderbook.sells:
orderbook.levels["sells"][sell.price] = PriceLevel(
price=Decimal(sell.price),
quantity=Decimal(sell.quantity),
timestamp=sell.timestamp,
)
break
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
async_client = AsyncClient(network)
market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
orderbook = Orderbook(market_id=market_id)
# start getting price levels updates
stream = await async_client.stream_spot_orderbook_update(market_ids=[market_id])
first_update = None
async for update in stream:
first_update = update.orderbook_level_updates
break
# load the snapshot once we are already receiving updates, so we don't miss any
await load_orderbook_snapshot(async_client=async_client, orderbook=orderbook)
# start consuming updates again to process them
apply_orderbook_update(orderbook, first_update)
async for update in stream:
apply_orderbook_update(orderbook, update.orderbook_level_updates)
def apply_orderbook_update(orderbook: Orderbook, updates):
# discard updates older than the snapshot
if updates.sequence <= orderbook.sequence:
return
print(" * * * * * * * * * * * * * * * * * * *")
# ensure we have not missed any update
if updates.sequence > (orderbook.sequence + 1):
raise Exception("missing orderbook update events from stream, must restart: {} vs {}".format(
updates.sequence, (orderbook.sequence + 1)))
print("updating orderbook with updates at sequence {}".format(updates.sequence))
# update orderbook
orderbook.sequence = updates.sequence
for direction, levels in {"buys": updates.buys, "sells": updates.sells}.items():
for level in levels:
if level.is_active:
# upsert level
orderbook.levels[direction][level.price] = PriceLevel(
price=Decimal(level.price),
quantity=Decimal(level.quantity),
timestamp=level.timestamp)
else:
if level.price in orderbook.levels[direction]:
del orderbook.levels[direction][level.price]
# sort the level numerically
buys = sorted(orderbook.levels["buys"].values(), key=lambda x: x.price, reverse=True)
sells = sorted(orderbook.levels["sells"].values(), key=lambda x: x.price, reverse=True)
# lowest sell price should be higher than the highest buy price
if len(buys) > 0 and len(sells) > 0:
highest_buy = buys[0].price
lowest_sell = sells[-1].price
print("Max buy: {} - Min sell: {}".format(highest_buy, lowest_sell))
if highest_buy >= lowest_sell:
raise Exception("crossed orderbook, must restart")
# for the example, print the list of buys and sells orders.
print("sells")
for k in sells:
print(k)
print("=========")
print("buys")
for k in buys:
print(k)
print("====================================")
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.run(main())
import {
IndexerGrpcSpotStream,
SpotOrderbookUpdateStreamCallback,
} from "@injectivelabs/sdk-ts";
import { getNetworkEndpoints, Network } from "@injectivelabs/networks";
(async () => {
const endpoints = getNetworkEndpoints(Network.TestnetK8s);
const indexerGrpcSpotStream = new IndexerGrpcSpotStream(endpoints.indexer);
const marketIds = [
"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
];
const streamFn = indexerGrpcSpotStream.streamSpotOrderbookUpdate.bind(
indexerGrpcSpotStream
);
const callback: SpotOrderbookUpdateStreamCallback = (orderbooks) => {
console.log(orderbooks);
};
const streamFnArgs = {
marketIds,
callback,
};
streamFn(streamFnArgs);
})();
Parameter | Type | Description | Required |
---|---|---|---|
market_ids | String Array | List of market IDs for orderbook streaming; empty means all spot markets | Yes |
Response Parameters
Streaming Response Example:
* * * * * * * * * * * * * * * * * * *
updating orderbook with updates at sequence 724
Max buy: 7.523E-12 - Min sell: 7.525E-12
sells
price: 8E-12 | quantity: 10000000000000000 | timestamp: 1675904636889
price: 7.526E-12 | quantity: 50000000000000000 | timestamp: 1676089482358
price: 7.525E-12 | quantity: 10000000000000000 | timestamp: 1676015247335
=========
buys
price: 7.523E-12 | quantity: 30000000000000000 | timestamp: 1676616192052
price: 7E-12 | quantity: 1000000000000000000 | timestamp: 1675904400063
price: 1E-12 | quantity: 10000000000000000 | timestamp: 1675882430039
price: 1E-15 | quantity: 17983000000000000000 | timestamp: 1675880932648
====================================
* * * * * * * * * * * * * * * * * * *
updating orderbook with updates at sequence 725
Max buy: 7.523E-12 - Min sell: 7.525E-12
sells
price: 8E-12 | quantity: 10000000000000000 | timestamp: 1675904636889
price: 7.526E-12 | quantity: 50000000000000000 | timestamp: 1676089482358
price: 7.525E-12 | quantity: 10000000000000000 | timestamp: 1676015247335
=========
buys
price: 7.523E-12 | quantity: 40000000000000000 | timestamp: 1676616222476
price: 7E-12 | quantity: 1000000000000000000 | timestamp: 1675904400063
price: 1E-12 | quantity: 10000000000000000 | timestamp: 1675882430039
price: 1E-15 | quantity: 17983000000000000000 | timestamp: 1675880932648
====================================
{
orderbook: {
sells: [{
price: "0.000000000008",
quantity: "10000000000000000",
timestamp: 1675904636889,
}],
buys: [{
price: "0.000000000001",
quantity: "10000000000000000",
timestamp: 1675882430039,
}],
sequence: 713
}
operationType: "update"
timestamp: 1676610727000
marketId: "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
}
Parameter | Type | Description |
---|---|---|
orderbook_level_updates | OrderbookLevelUpdates | Orderbook level updates of a spot market |
operation_type | String | Order update type (Should be one of: ["insert", "replace", "update", "invalidate"]) |
timestamp | Integer | Operation timestamp in UNIX millis |
market_id | String | ID of the market the orderbook belongs to |
OrderbookLevelUpdates
Parameter | Type | Description |
---|---|---|
market_id | String | ID of the market the orderbook belongs to |
sequence | Integer | Orderbook update sequence number; increments by 1 each update |
buys | PriceLevelUpdate Array | List of buy level updates |
sells | PriceLevelUpdate Array | List of sell level updates |
updated_at | Integer | Timestamp of the updates in UNIX millis |
PriceLevelUpdate
Parameter | Type | Description |
---|---|---|
price | String | Price number of the price level |
quantity | String | Quantity of the price level |
is_active | Boolean | Price level status |
timestamp | Integer | Price level last updated timestamp in UNIX millis |
SubaccountOrdersList
Get orders of a subaccount.
IP rate limit group: indexer
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
client = AsyncClient(network)
subaccount_id = "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001"
market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
skip = 10
limit = 10
orders = await client.get_spot_subaccount_orders(
subaccount_id=subaccount_id,
market_id=market_id,
skip=skip,
limit=limit
)
print(orders)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
spotExchangePB "github.com/InjectiveLabs/sdk-go/exchange/spot_exchange_rpc/pb"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
fmt.Println(err)
}
ctx := context.Background()
marketId := "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0"
subaccountId := "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
skip := uint64(0)
limit := int32(2)
req := spotExchangePB.SubaccountOrdersListRequest{
MarketId: marketId,
SubaccountId: subaccountId,
Skip: skip,
Limit: limit,
}
res, err := exchangeClient.GetSubaccountSpotOrdersList(ctx, req)
if err != nil {
fmt.Println(err)
}
str, _ := json.MarshalIndent(res, "", " ")
fmt.Print(string(str))
}
import { PaginationOption, IndexerGrpcSpotApi } from "@injectivelabs/sdk-ts";
import { getNetworkEndpoints, Network } from "@injectivelabs/networks";
(async () => {
const endpoints = getNetworkEndpoints(Network.TestnetK8s);
const indexerGrpcSpotApi = new IndexerGrpcSpotApi(endpoints.indexer);
const marketId =
"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe";
const subaccountId =
"0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001";
const pagination = {} as PaginationOption;
const orders = await indexerGrpcSpotApi.fetchSubaccountOrdersList({
marketId,
subaccountId,
pagination,
});
console.log(orders);
})();
Parameter | Type | Description | Required |
---|---|---|---|
subaccount_id | String | Filter by subaccount ID | Yes |
market_id | String | Filter by market ID | No |
skip | Integer | Skip the first n items from the results. This can be used to fetch all trades since the API caps at 100 | No |
limit | Integer | Maximum number of items to be returned. 1 <= n <= 100 | No |
Response Parameters
Response Example:
orders {
order_hash: "0x982d82c58a3e96680915636c9a5fe6b25af8581ceec19087f611a96e1d73b79e"
order_side: "sell"
market_id: "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
subaccount_id: "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001"
price: "0.000000000008"
quantity: "10000000000000000"
unfilled_quantity: "10000000000000000"
trigger_price: "0"
fee_recipient: "inj1clw20s2uxeyxtam6f7m84vgae92s9eh7vygagt"
state: "booked"
created_at: 1675904636889
updated_at: 1675904636889
}
orders {
order_hash: "0x2c497f2a6e62fc4a3db39f6483d2dac797b9345d1033738ee316136611c7951c"
order_side: "buy"
market_id: "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
subaccount_id: "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001"
price: "0.000000000007"
quantity: "1000000000000000000"
unfilled_quantity: "1000000000000000000"
trigger_price: "0"
fee_recipient: "inj1clw20s2uxeyxtam6f7m84vgae92s9eh7vygagt"
state: "booked"
created_at: 1675904400063
updated_at: 1675904400063
}
orders {
order_hash: "0xd567b9d5b3dde5d37980f8aa7110be94163d016978ca5614a373d0ad5326a96b"
order_side: "buy"
market_id: "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
subaccount_id: "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001"
price: "0.000000000001"
quantity: "10000000000000000"
unfilled_quantity: "10000000000000000"
trigger_price: "0"
fee_recipient: "inj1clw20s2uxeyxtam6f7m84vgae92s9eh7vygagt"
state: "booked"
created_at: 1675882430039
updated_at: 1675882430039
}
paging {
total: 13
from: 11
to: 13
}
{
"orders": [
{
"order_hash": "0x5e970df47eb5a65a5f907e3a2912067dde416eca8609c838e08c0dbebfbefaa5",
"order_side": "sell",
"market_id": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
"subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"price": "0.000000000005",
"quantity": "1000000000000000000",
"unfilled_quantity": "1000000000000000000",
"trigger_price": "0",
"fee_recipient": "inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8",
"state": "booked",
"created_at": 1652809317404,
"updated_at": 1652809317404
},
{
"order_hash": "0x318418b546563a75c11dc656ee0fb41608e2893b0de859cf2b9e2d65996b6f9c",
"order_side": "buy",
"market_id": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
"subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"price": "0.000000000001",
"quantity": "1000000000000000000",
"unfilled_quantity": "1000000000000000000",
"trigger_price": "0",
"fee_recipient": "inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8",
"state": "booked",
"created_at": 1652809253308,
"updated_at": 1652809253308
}
]
}
[
{
"orderHash": "0x2f63441ddea8003bb29c28949d4a3f3b1e40fb423154164a7b579fbefa2e4f8d",
"orderSide": "sell",
"marketId": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
"subaccountId": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"price": "0.000000000003",
"quantity": "1000000000000000000",
"unfilledQuantity": "1000000000000000000",
"triggerPrice": "0",
"feeRecipient": "inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8",
"state": "booked",
"createdAt": 1654080771385,
"updatedAt": 1654080771385
},
{
"orderHash": "0xb5b7f863c0f94f31668670d9ac74df6c31dc37b5d3b73e7ac43a200da58fbaeb",
"orderSide": "buy",
"marketId": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
"subaccountId": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"price": "0.000000000001",
"quantity": "1500000000000000000",
"unfilledQuantity": "1500000000000000000",
"triggerPrice": "0",
"feeRecipient": "inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8",
"state": "booked",
"createdAt": 1654079407709,
"updatedAt": 1654079407709
},
{
"orderHash": "0x9bfdda8da0008059844bff8e2cfa0399d5a71abaadc2a3b659c4c2c0db654fb6",
"orderSide": "buy",
"marketId": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
"subaccountId": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"price": "0.000000000001",
"quantity": "2000000000000000000",
"unfilledQuantity": "2000000000000000000",
"triggerPrice": "0",
"feeRecipient": "inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8",
"state": "booked",
"createdAt": 1654079382459,
"updatedAt": 1654079382459
},
{
"orderHash": "0xc2d56db71c54e5d0814746ebb966d63bb6c0b5f3462e97b2d607028881144b3b",
"orderSide": "buy",
"marketId": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
"subaccountId": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"price": "0.000000000002",
"quantity": "2000000000000000000",
"unfilledQuantity": "2000000000000000000",
"triggerPrice": "0",
"feeRecipient": "inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8",
"state": "booked",
"createdAt": 1654079341993,
"updatedAt": 1654079341993
},
{
"orderHash": "0xd3f1e94393fc026a6a5b709b52b5ad0057e771b2b2768f4d7aebd03c5dfa383f",
"orderSide": "buy",
"marketId": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
"subaccountId": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"price": "0.000000000002",
"quantity": "1000000000000000000",
"unfilledQuantity": "1000000000000000000",
"triggerPrice": "0",
"feeRecipient": "inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8",
"state": "booked",
"createdAt": 1654079259156,
"updatedAt": 1654079259156
}
]
Parameter | Type | Description |
---|---|---|
orders | SpotLimitOrder Array | List of spot market orders |
paging | Paging | Pagination of results |
SpotLimitOrder
Parameter | Type | Description |
---|---|---|
state | String | State of the order (Should be one of: ["booked", "partial_filled", "filled", "canceled"]) |
subaccount_id | String | The subaccount ID the order belongs to |
unfilled_quantity | String | The amount of the quantity remaining unfilled |
market_id | String | ID of the market the order belongs to |
order_hash | String | Hash of the order |
order_side | String | The side of the order (Should be one of: ["buy", "sell", "stop_buy", "stop_sell", "take_buy", "take_sell"]) |
fee_recipient | String | The address that receives fees if the order is executed |
price | String | The price of the order |
quantity | String | The quantity of the order |
trigger_price | String | The price that triggers stop and take orders. If no price is set, the default is 0 |
created_at | Integer | Order committed timestamp in UNIX millis |
updated_at | Integer | Order updated timestamp in UNIX millis |
Paging
Parameter | Type | Description |
---|---|---|
total | Integer | Total number of available records |
from | Integer | Lower bound of indices of records returned |
to | integer | Upper bound of indices of records returned |
SubaccountTradesList
Get trades of a subaccount.
IP rate limit group: indexer
*Trade execution types
"market"
for market orders"limitFill"
for a resting limit order getting filled by a market order"limitMatchRestingOrder"
for a resting limit order getting matched with another new limit order"limitMatchNewOrder"
for a new limit order getting matched immediately
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
client = AsyncClient(network)
subaccount_id = "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
execution_type = "market"
direction = "buy"
skip = 2
limit = 3
trades = await client.get_spot_subaccount_trades(
subaccount_id=subaccount_id,
market_id=market_id,
execution_type=execution_type,
direction=direction,
skip=skip,
limit=limit
)
print(trades)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
spotExchangePB "github.com/InjectiveLabs/sdk-go/exchange/spot_exchange_rpc/pb"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
fmt.Println(err)
}
ctx := context.Background()
marketId := "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0"
subaccountId := "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000"
skip := uint64(0)
limit := int32(2)
req := spotExchangePB.SubaccountTradesListRequest{
MarketId: marketId,
SubaccountId: subaccountId,
Skip: skip,
Limit: limit,
}
res, err := exchangeClient.GetSubaccountSpotTradesList(ctx, req)
if err != nil {
fmt.Println(err)
}
str, _ := json.MarshalIndent(res, "", " ")
fmt.Print(string(str))
}
import {
TradeDirection,
TradeExecutionType,
PaginationOption,
IndexerGrpcSpotApi,
} from "@injectivelabs/sdk-ts";
import { getNetworkEndpoints, Network } from "@injectivelabs/networks";
(async () => {
const endpoints = getNetworkEndpoints(Network.TestnetK8s);
const indexerGrpcSpotApi = new IndexerGrpcSpotApi(endpoints.indexer);
const marketId =
"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"; /* optional param */
const subaccountId =
"0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001"; /* optional param */
const executionType = TradeExecutionType.LimitFill; /* optional param */
const direction = TradeDirection.Sell; /* optional param */
const pagination = {} as PaginationOption; /* optional param */
const subaccountTrades = await indexerGrpcSpotApi.fetchSubaccountTradesList({
marketId,
subaccountId,
executionType,
direction,
pagination,
});
console.log(subaccountTrades);
})();
Parameter | Type | Description | Required |
---|---|---|---|
subaccount_id | String | Filter by subaccount ID | Yes |
market_id | String | Filter by market ID | No |
direction | String | Filter by the direction of the trades (Should be one of: ["buy", "sell"]) | No |
execution_type | String | Filter by the *execution type of the trades (Should be one of: ["market", "limitFill", "limitMatchRestingOrder", "limitMatchNewOrder"]) | No |
skip | Integer | Skip the first n items from the results. This can be used to fetch all trades since the API caps at 100 | No |
limit | Integer | Maximum number of items to be returned. 1 <= n <= 100 | No |
Response Parameters
Response Example:
trades {
order_hash: "0x5ff08b7fe885b62aaaadb0c8b8877d9031d39fd67a1b94bc19da34e3be48238f"
subaccount_id: "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
market_id: "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
trade_execution_type: "market"
trade_direction: "buy"
price {
price: "0.000000000055"
quantity: "182000000000000000"
timestamp: 1673343614891
}
fee: "10010"
executed_at: 1673343614891
fee_recipient: "inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8"
trade_id: "6858954_5ff08b7fe885b62aaaadb0c8b8877d9031d39fd67a1b94bc19da34e3be48238f"
execution_side: "taker"
}
trades {
order_hash: "0x38d614f920c8ab577eb7ab8ed1f1c452e4aeba9b69885ec1e8b308052957174d"
subaccount_id: "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
market_id: "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
trade_execution_type: "market"
trade_direction: "buy"
price {
price: "0.000000000055"
quantity: "1544000000000000000"
timestamp: 1673343521906
}
fee: "84920"
executed_at: 1673343521906
fee_recipient: "inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8"
trade_id: "6858914_38d614f920c8ab577eb7ab8ed1f1c452e4aeba9b69885ec1e8b308052957174d"
execution_side: "taker"
}
trades {
order_hash: "0xfe1a82268e2147ba359092a751fd4e3ee375d1887bf1fa00de5ece88764bd7f5"
subaccount_id: "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
market_id: "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
trade_execution_type: "market"
trade_direction: "buy"
price {
price: "0.000000000055"
quantity: "1816000000000000000"
timestamp: 1673343487116
}
fee: "99880"
executed_at: 1673343487116
fee_recipient: "inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8"
trade_id: "6858899_fe1a82268e2147ba359092a751fd4e3ee375d1887bf1fa00de5ece88764bd7f5"
execution_side: "taker"
}
{
"trades": [
{
"order_hash": "0xbf5cf18a5e73c61d465a60ca550c5fbe0ed37b9ca0a49f7bd1de012e983fe55e",
"subaccount_id": "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000",
"market_id": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
"trade_execution_type": "limitFill",
"trade_direction": "sell",
"price": {
"price": "0.000000000002305",
"quantity": "1000000000000000000",
"timestamp": 1652809734211
},
"fee": "2305",
"executed_at": 1652809734211,
"fee_recipient": "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r"
},
{
"order_hash": "0xfd474dc696dc291bca8ca1b371653994fd846a303c08d26ccc17a7b60939d256",
"subaccount_id": "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000",
"market_id": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
"trade_execution_type": "limitFill",
"trade_direction": "sell",
"price": {
"price": "0.000000000002318",
"quantity": "4000000000000000000",
"timestamp": 1652773190338
},
"fee": "9272",
"executed_at": 1652773190338,
"fee_recipient": "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r"
}
]
}
[
{
"orderHash": "0xa6e42876bc57db846a06e1efbf481c99696fc8e50797d6535dde70545240839c",
"subaccountId": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"marketId": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
"tradeExecutionType": "market",
"tradeDirection": "buy",
"price": {
"price": "0.0000000000025",
"quantity": "1000000000000000000",
"timestamp": 1654080596036
},
"fee": "5000",
"executedAt": 1654080596036,
"feeRecipient": "inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8"
},
{
"orderHash": "0x78b04557c96b82cfb49bb31955c4f990e4cf1bd2a976d683defdf676d427632f",
"subaccountId": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"marketId": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
"tradeExecutionType": "market",
"tradeDirection": "buy",
"price": {
"price": "0.0000000003",
"quantity": "55000000000000000000",
"timestamp": 1653935308434
},
"fee": "33000000",
"executedAt": 1653935308434,
"feeRecipient": "inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8"
},
{
"orderHash": "0x6ad25de6dac78159fe66a02bded6bc9609ad67a3ad7b50c9809ce22c5855d571",
"subaccountId": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"marketId": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
"tradeExecutionType": "limitMatchNewOrder",
"tradeDirection": "buy",
"price": {
"price": "0.0000000000054255",
"quantity": "10000000000000000",
"timestamp": 1652097626589
},
"fee": "108.51",
"executedAt": 1652097626589,
"feeRecipient": "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
}
]
Parameter | Type | Description |
---|---|---|
trades | SpotTrade Array | List of spot market trades |
SpotTrade
Parameter | Type | Description |
---|---|---|
trade_direction | String | The direction the trade (Should be one of: ["buy", "sell"]) |
trade_execution_type | String | The execution type of the trade (Should be one of: ["market", "limitFill", "limitMatchRestingOrder", "limitMatchNewOrder"]) |
fee | String | The fee associated with the trade (quote asset denom) |
market_id | String | The ID of the market that this trade is in |
order_hash | String | The order hash |
price | PriceLevel | Price level at which trade has been executed |
subaccount_id | String | Filter by the subaccount ID |
executed_at | Integer | Timestamp of trade execution (on chain) in UNIX millis |
fee_recipient | String | Address that received fees from the order |
trade_id | String | A unique string that helps differentiate between trades |
execution_side | String | Trade's execution side (Should be one of: ["maker", "taker"]) |
PriceLevel
Parameter | Type | Description |
---|---|---|
price | String | Price number of the price level |
quantity | String | Quantity of the price level |
timestamp | Integer | Price level last updated timestamp in UNIX millis |
- InjectiveDerivativeExchangeRPC
InjectiveDerivativeExchangeRPC defines the gRPC API of the Derivative Exchange provider.
Market
Get details of a single derivative market.
IP rate limit group: indexer
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
client = AsyncClient(network)
market_id = "0x141e3c92ed55107067ceb60ee412b86256cedef67b1227d6367b4cdf30c55a74"
market = await client.get_derivative_market(market_id=market_id)
print(market)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
panic(err)
}
ctx := context.Background()
marketId := "0x141e3c92ed55107067ceb60ee412b86256cedef67b1227d6367b4cdf30c55a74"
res, err := exchangeClient.GetDerivativeMarket(ctx, marketId)
if err != nil {
panic(err)
}
str, _ := json.MarshalIndent(res, "", " ")
fmt.Print(string(str))
}
import { IndexerGrpcDerivativesApi } from '@injectivelabs/sdk-ts'
import { getNetworkEndpoints, Network } from '@injectivelabs/networks'
const endpoints = getNetworkEndpoints(Network.TestnetK8s)
const indexerGrpcDerivativesApi = new IndexerGrpcDerivativesApi(endpoints.indexer)
const marketId = '0x...'
const market = await indexerGrpcDerivativesApi.fetchMarket(marketId)
console.log(market)
Parameter | Type | Description | Required |
---|---|---|---|
market_id | String | ID of the market to fetch | Yes |
Response Parameters
Response Example:
market {
market_id: "0x90e662193fa29a3a7e6c07be4407c94833e762d9ee82136a2cc712d6b87d7de3"
market_status: "active"
ticker: "BTC/USDT PERP"
oracle_base: "BTC"
oracle_quote: "USDT"
oracle_type: "bandibc"
oracle_scale_factor: 6
initial_margin_ratio: "0.095"
maintenance_margin_ratio: "0.05"
quote_denom: "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"
quote_token_meta {
name: "Testnet Tether USDT"
address: "0x0000000000000000000000000000000000000000"
symbol: "USDT"
logo: "https://static.alchemyapi.io/images/assets/825.png"
decimals: 6
updated_at: 1676338338818
}
maker_fee_rate: "-0.0001"
taker_fee_rate: "0.001"
service_provider_fee: "0.4"
is_perpetual: true
min_price_tick_size: "100000"
min_quantity_tick_size: "0.0001"
perpetual_market_info {
hourly_funding_rate_cap: "0.000625"
hourly_interest_rate: "0.00000416666"
next_funding_timestamp: 1676340000
funding_interval: 3600
}
perpetual_market_funding {
cumulative_funding: "779109108.57624692966427974"
cumulative_price: "295.860245725710572515"
last_timestamp: 1676294229
}
}
{
"market": {
"market_id": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
"market_status": "active",
"ticker": "BTC/USDT PERP",
"oracle_base": "BTC",
"oracle_quote": "USDT",
"oracle_type": "bandibc",
"oracle_scale_factor": 6,
"initial_margin_ratio": "0.095",
"maintenance_margin_ratio": "0.05",
"quote_denom": "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7",
"quote_token_meta": {
"name": "Tether",
"address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"symbol": "USDT",
"logo": "https://static.alchemyapi.io/images/assets/825.png",
"decimals": 6,
"updated_at": 1650978923435
},
"maker_fee_rate": "0.0005",
"taker_fee_rate": "0.0012",
"service_provider_fee": "0.4",
"is_perpetual": true,
"min_price_tick_size": "100000",
"min_quantity_tick_size": "0.0001",
"perpetual_market_info": {
"hourly_funding_rate_cap": "0.000625",
"hourly_interest_rate": "0.00000416666",
"next_funding_timestamp": 1652864400,
"funding_interval": 3600
},
"perpetual_market_funding": {
"cumulative_funding": "7246105747.050586213851272386",
"cumulative_price": "31.114148427047982579",
"last_timestamp": 1652793510
}
}
}
{
"market": {
"marketId": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
"marketStatus": "active",
"ticker": "BTC/USDT PERP",
"oracleBase": "BTC",
"oracleQuote": "USDT",
"oracleType": "bandibc",
"oracleScaleFactor": 6,
"initialMarginRatio": "0.095",
"maintenanceMarginRatio": "0.05",
"quoteDenom": "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7",
"quoteTokenMeta": {
"name": "Tether",
"address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"symbol": "USDT",
"logo": "https://static.alchemyapi.io/images/assets/825.png",
"decimals": 6,
"updatedAt": 1650978923435
},
"makerFeeRate": "0.0005",
"takerFeeRate": "0.0012",
"serviceProviderFee": "0.4",
"isPerpetual": true,
"minPriceTickSize": "100000",
"minQuantityTickSize": "0.0001",
"perpetualMarketInfo": {
"hourlyFundingRateCap": "0.000625",
"hourlyInterestRate": "0.00000416666",
"nextFundingTimestamp": 1654246800,
"fundingInterval": 3600
},
"perpetualMarketFunding": {
"cumulativeFunding": "8239865636.851083559033030036",
"cumulativePrice": "-3.875827592425613503",
"lastTimestamp": 1654243770
}
}
}
Parameter | Type | Description |
---|---|---|
market | DerivativeMarketInfo | Info about a particular derivative market |
DerivativeMarketInfo
Parameter | Type | Description |
---|---|---|
oracle_quote | String | Oracle quote currency |
oracle_type | String | Oracle Type |
quote_denom | String | Coin denom used for the quote asset |
is_perpetual | Boolean | True if the market is a perpetual swap market |
maker_fee_rate | String | Defines the fee percentage makers pay (or receive, if negative) in quote asset when trading |
min_price_tick_size | String | Defines the minimum required tick size for the order's price |
min_quantity_tick_size | String | Defines the minimum required tick size for the order's quantity |
oracle_scale_factor | Integer | Scaling multiple to scale oracle prices to the correct number of decimals |
taker_fee_rate | String | Defines the fee percentage takers pay (in quote asset) when trading |
expiry_futures_market_info | ExpiryFuturesMarketInfo | Info about expiry futures market |
initial_margin_ratio | String | The initial margin ratio of the derivative market |
market_status | String | The status of the market (Should be one of: ["active", "paused", "suspended", "demolished", "expired"]) |
service_provider_fee | String | Percentage of the transaction fee shared with the service provider |
oracle_base | String | Oracle base currency |
perpetual_market_funding | PerpetualMarketFunding | PerpetualMarketFunding object |
perpetual_market_info | PerpetualMarketInfo | Information about the perpetual market |
ticker | String | The name of the pair in format AAA/BBB, where AAA is the base asset and BBB is the quote asset |
maintenance_margin_ratio | String | The maintenance margin ratio of the derivative market |
market_id | String | The market ID |
quoteTokenMeta | TokenMeta | Token metadata for quote asset, only for Ethereum-based assets |
ExpiryFuturesMarketInfo
Parameter | Type | Description |
---|---|---|
expiration_timestamp | Integer | Defines the expiration time for a time expiry futures market in UNIX seconds |
settlement_price | String | Defines the settlement price for a time expiry futures market |
PerpetualMarketFunding
Parameter | Type | Description |
---|---|---|
cumulative_funding | String | Defines the cumulative funding of a perpetual market |
cumulative_price | String | Defines the cumulative price for the current hour up to the last timestamp |
last_timestamp | Integer | Defines the last funding timestamp in UNIX seconds |
PerpetualMarketInfo
Parameter | Type | Description |
---|---|---|
hourly_funding_rate_cap | String | Defines the default maximum absolute value of the hourly funding rate |
hourly_interest_rate | String | Defines the hourly interest rate of the perpetual market |
next_funding_timestamp | Integer | Defines the next funding timestamp in UNIX seconds |
funding_interval | Integer | Defines the funding interval in seconds |
TokenMeta
Parameter | Type | Description |
---|---|---|
address | String | Token's Ethereum contract address |
decimals | Integer | Token decimals |
logo | String | URL to the logo image |
name | String | Token full name |
symbol | String | Token symbol short name |
updatedAt | Integer | Token metadata fetched timestamp in UNIX millis |
Markets
Get a list of one or more derivative markets.
IP rate limit group: indexer
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
client = AsyncClient(network)
market_status = "active"
quote_denom = "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"
market = await client.get_derivative_markets(
market_status=market_status,
quote_denom=quote_denom
)
print(market)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
derivativeExchangePB "github.com/InjectiveLabs/sdk-go/exchange/derivative_exchange_rpc/pb"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
panic(err)
}
ctx := context.Background()
marketStatus := "active"
quoteDenom := "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7"
req := derivativeExchangePB.MarketsRequest{
MarketStatus: marketStatus,
QuoteDenom: quoteDenom,
}
res, err := exchangeClient.GetDerivativeMarkets(ctx, req)
if err != nil {
panic(err)
}
str, _ := json.MarshalIndent(res, "", " ")
fmt.Print(string(str))
}
import { IndexerGrpcDerivativesApi } from '@injectivelabs/sdk-ts'
import { getNetworkEndpoints, Network } from '@injectivelabs/networks'
const endpoints = getNetworkEndpoints(Network.TestnetK8s)
const indexerGrpcDerivativesApi = new IndexerGrpcDerivativesApi(endpoints.indexer)
const markets = await indexerGrpcDerivativesApi.fetchMarkets()
console.log(markets)
Parameter | Type | Description | Required |
---|---|---|---|
market_status | String | Filter by market status (Should be one of: ["active", "paused", "suspended", "demolished", "expired"]) | No |
quote_denom | String | Filter by the Coin denomination of the quote currency | No |
Response Parameters
Response Example:
markets {
market_id: "0xe112199d9ee44ceb2697ea0edd1cd422223c105f3ed2bdf85223d3ca59f5909a"
market_status: "active"
ticker: "INJ/USDT PERP"
oracle_base: "INJ"
oracle_quote: "USDT"
oracle_type: "bandibc"
oracle_scale_factor: 6
initial_margin_ratio: "0.095"
maintenance_margin_ratio: "0.05"
quote_denom: "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"
quote_token_meta {
name: "Testnet Tether USDT"
address: "0x0000000000000000000000000000000000000000"
symbol: "USDT"
logo: "https://static.alchemyapi.io/images/assets/825.png"
decimals: 6
updated_at: 1676339989721
}
maker_fee_rate: "-0.0001"
taker_fee_rate: "0.001"
service_provider_fee: "0.4"
is_perpetual: true
min_price_tick_size: "100000"
min_quantity_tick_size: "0.0001"
perpetual_market_info {
hourly_funding_rate_cap: "0.000625"
hourly_interest_rate: "0.00000416666"
next_funding_timestamp: 1676340000
funding_interval: 3600
}
perpetual_market_funding {
cumulative_funding: "30750.538513128695953648"
cumulative_price: "793.433131392911165592"
last_timestamp: 1674712474
}
}
...
markets {
market_id: "0x3bb58218cd90efcce9ea9e317d137dcd4ce8485c6be346250dbf8cd60d9c9e2d"
market_status: "active"
ticker: "Frontrunner Futures 4: Expires 7.7.2023"
oracle_base: "FRNT"
oracle_quote: "USDT"
oracle_type: "pricefeed"
oracle_scale_factor: 6
initial_margin_ratio: "0.999999999999999999"
maintenance_margin_ratio: "0.1"
quote_denom: "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"
quote_token_meta {
name: "Testnet Tether USDT"
address: "0x0000000000000000000000000000000000000000"
symbol: "USDT"
logo: "https://static.alchemyapi.io/images/assets/825.png"
decimals: 6
updated_at: 1676339989721
}
maker_fee_rate: "0.005"
taker_fee_rate: "0.012"
service_provider_fee: "0.4"
min_price_tick_size: "0.000000000000001"
min_quantity_tick_size: "0.0001"
expiry_futures_market_info {
expiration_timestamp: 1688747341
settlement_price: "0"
}
}
{
"markets": [
{
"market_id": "0x1c79dac019f73e4060494ab1b4fcba734350656d6fc4d474f6a238c13c6f9ced",
"market_status": "active",
"ticker": "BNB/USDT PERP",
"oracle_base": "BNB",
"oracle_quote": "USDT",
"oracle_type": "bandibc",
"oracle_scale_factor": 6,
"initial_margin_ratio": "0.095",
"maintenance_margin_ratio": "0.05",
"quote_denom": "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7",
"quote_token_meta": {
"name": "Tether",
"address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"symbol": "USDT",
"logo": "https://static.alchemyapi.io/images/assets/825.png",
"decimals": 6,
"updated_at": 1650978923353
},
"maker_fee_rate": "0.0005",
"taker_fee_rate": "0.0012",
"service_provider_fee": "0.4",
"is_perpetual": true,
"min_price_tick_size": "10000",
"min_quantity_tick_size": "0.01",
"perpetual_market_info": {
"hourly_funding_rate_cap": "0.000625",
"hourly_interest_rate": "0.00000416666",
"next_funding_timestamp": 1652864400,
"funding_interval": 3600
},
"perpetual_market_funding": {
"cumulative_funding": "48248742.484852568471323698",
"cumulative_price": "5.691379282523162906",
"last_timestamp": 1652775374
}
},
{
"market_id": "0xfb5f14852bd01af901291dd2aa65e997b3a831f957124a7fe7aa40d218ff71ae",
"market_status": "active",
"ticker": "XAG/USDT PERP",
"oracle_base": "XAG",
"oracle_quote": "USDT",
"oracle_type": "bandibc",
"oracle_scale_factor": 6,
"initial_margin_ratio": "0.8",
"maintenance_margin_ratio": "0.4",
"quote_denom": "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7",
"quote_token_meta": {
"name": "Tether",
"address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"symbol": "USDT",
"logo": "https://static.alchemyapi.io/images/assets/825.png",
"decimals": 6,
"updated_at": 1650978923534
},
"maker_fee_rate": "0.003",
"taker_fee_rate": "0.005",
"service_provider_fee": "0.4",
"is_perpetual": true,
"min_price_tick_size": "10000",
"min_quantity_tick_size": "0.01",
"perpetual_market_info": {
"hourly_funding_rate_cap": "0.000625",
"hourly_interest_rate": "0.00000416666",
"next_funding_timestamp": 1652864400,
"funding_interval": 3600
},
"perpetual_market_funding": {
"cumulative_funding": "1099659.417190990913058692",
"cumulative_price": "-4.427475055338306767",
"last_timestamp": 1652775322
}
}
]
}
[
{
"marketId": "0x1c79dac019f73e4060494ab1b4fcba734350656d6fc4d474f6a238c13c6f9ced",
"marketStatus": "active",
"ticker": "BNB/USDT PERP",
"oracleBase": "BNB",
"oracleQuote": "USDT",
"oracleType": "bandibc",
"oracleScaleFactor": 6,
"initialMarginRatio": "0.095",
"maintenanceMarginRatio": "0.05",
"quoteDenom": "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7",
"quoteTokenMeta": {
"name": "Tether",
"address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"symbol": "USDT",
"logo": "https://static.alchemyapi.io/images/assets/825.png",
"decimals": 6,
"updatedAt": 1650978923353
},
"makerFeeRate": "0.0005",
"takerFeeRate": "0.0012",
"serviceProviderFee": "0.4",
"isPerpetual": true,
"minPriceTickSize": "10000",
"minQuantityTickSize": "0.01",
"perpetualMarketInfo": {
"hourlyFundingRateCap": "0.000625",
"hourlyInterestRate": "0.00000416666",
"nextFundingTimestamp": 1654246800,
"fundingInterval": 3600
},
"perpetualMarketFunding": {
"cumulativeFunding": "56890491.178246679699729639",
"cumulativePrice": "7.082760891515203314",
"lastTimestamp": 1654245985
}
},
{
"marketId": "0x00030df39180df04a873cb4aadc50d4135640af5c858ab637dbd4d31b147478c",
"marketStatus": "active",
"ticker": "Frontrunner Futures: Expires 5.21.2023",
"oracleBase": "FRNT",
"oracleQuote": "USDT",
"oracleType": "pricefeed",
"oracleScaleFactor": 6,
"initialMarginRatio": "0.999999999999999999",
"maintenanceMarginRatio": "0.1",
"quoteDenom": "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7",
"quoteTokenMeta": {
"name": "Tether",
"address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"symbol": "USDT",
"logo": "https://static.alchemyapi.io/images/assets/825.png",
"decimals": 6,
"updatedAt": 1653064108501
},
"makerFeeRate": "0.005",
"takerFeeRate": "0.012",
"serviceProviderFee": "0.4",
"isPerpetual": false,
"minPriceTickSize": "0.000000000000001",
"minQuantityTickSize": "0.0001",
"expiryFuturesMarketInfo": {
"expirationTimestamp": 1684600043,
"settlementPrice": "0"
}
}
]
Parameter | Type | Description |
---|---|---|
markets | DerivativeMarketInfo Array | List of derivative markets and associated info |
DerivativeMarketInfo
Parameter | Type | Description |
---|---|---|
oracle_quote | String | Oracle quote currency |
oracle_type | String | Oracle Type |
quote_denom | String | Coin denom used for the quote asset |
is_perpetual | Boolean | True if the market is a perpetual swap market |
maker_fee_rate | String | Defines the fee percentage makers pay (or receive, if negative) in quote asset when trading |
min_price_tick_size | String | Defines the minimum required tick size for the order's price |
min_quantity_tick_size | String | Defines the minimum required tick size for the order's quantity |
oracle_scale_factor | Integer | Scaling multiple to scale oracle prices to the correct number of decimals |
taker_fee_rate | String | Defines the fee percentage takers pay (in quote asset) when trading |
expiry_futures_market_info | ExpiryFuturesMarketInfo | Info about expiry futures market |
initial_margin_ratio | String | The initial margin ratio of the derivative market |
market_status | String | The status of the market (Should be one of: ["active", "paused", "suspended", "demolished", "expired"]) |
service_provider_fee | String | Percentage of the transaction fee shared with the service provider |
oracle_base | String | Oracle base currency |
perpetual_market_funding | PerpetualMarketFunding | PerpetualMarketFunding object |
perpetual_market_info | PerpetualMarketInfo | Information about the perpetual market |
ticker | String | The name of the pair in format AAA/BBB, where AAA is the base asset and BBB is the quote asset |
maintenance_margin_ratio | String | The maintenance margin ratio of the derivative market |
market_id | String | The market ID |
quoteTokenMeta | TokenMeta | Token metadata for quote asset, only for Ethereum-based assets |
ExpiryFuturesMarketInfo
Parameter | Type | Description |
---|---|---|
expiration_timestamp | Integer | Defines the expiration time for a time expiry futures market in UNIX seconds |
settlement_price | String | Defines the settlement price for a time expiry futures market |
PerpetualMarketFunding
Parameter | Type | Description |
---|---|---|
cumulative_funding | String | Defines the cumulative funding of a perpetual market |
cumulative_price | String | Defines the cumulative price for the current hour up to the last timestamp |
last_timestamp | Integer | Defines the last funding timestamp in UNIX seconds |
PerpetualMarketInfo
Parameter | Type | Description |
---|---|---|
hourly_funding_rate_cap | String | Defines the default maximum absolute value of the hourly funding rate |
hourly_interest_rate | String | Defines the hourly interest rate of the perpetual market |
next_funding_timestamp | Integer | Defines the next funding timestamp in UNIX seconds |
funding_interval | Integer | Defines the funding interval in seconds |
TokenMeta
Parameter | Type | Description |
---|---|---|
address | String | Token's Ethereum contract address |
decimals | Integer | Token decimals |
logo | String | URL to the logo image |
name | String | Token full name |
symbol | String | Token symbol short name |
updatedAt | Integer | Token metadata fetched timestamp in UNIX millis |
StreamMarkets
Stream live updates of derivative markets.
IP rate limit group: indexer
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
client = AsyncClient(network)
markets = await client.stream_derivative_markets()
async for market in markets:
print(market)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
panic(err)
}
ctx := context.Background()
marketIds := []string{"0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"}
stream, err := exchangeClient.StreamDerivativeMarket(ctx, marketIds)
if err != nil {
panic(err)
}
for {
select {
case <-ctx.Done():
return
default:
res, err := stream.Recv()
if err != nil {
panic(err)
return
}
str, _ := json.MarshalIndent(res, "", " ")
fmt.Print(string(str))
}
}
}
import {
IndexerGrpcDerivativesStream
} from '@injectivelabs/sdk-ts'
import { getNetworkEndpoints, Network } from '@injectivelabs/networks'
const endpoints = getNetworkEndpoints(Network.TestnetK8s)
const indexerGrpcDerivativesStream = new IndexerGrpcDerivativesStream(endpoints.indexer)
const marketIds = ['0x...'] /* optional param */
const streamFn = indexerGrpcDerivativesStream.streamDerivativeMarket.bind(indexerGrpcDerivativesStream)
const callback = (markets) => {
console.log(markets)
}
const streamFnArgs = {
marketIds,
callback
}
streamFn(streamFnArgs)
Parameter | Type | Description | Required |
---|---|---|---|
market_ids | String Array | List of market IDs for updates streaming, empty means 'ALL' derivative markets | No |
Response Parameters
Streaming Response Example:
market {
market_id: "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"
market_status: "active"
ticker: "BTC/USDT PERP"
oracle_base: "BTC"
oracle_quote: "USDT"
oracle_type: "bandibc"
oracle_scale_factor: 6
initial_margin_ratio: "0.095"
maintenance_margin_ratio: "0.05"
quote_denom: "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7"
quote_token_meta {
name: "Tether"
address: "0xdAC17F958D2ee523a2206206994597C13D831ec7"
symbol: "USDT"
logo: "https://static.alchemyapi.io/images/assets/825.png"
decimals: 6
updated_at: 1650978923435
}
maker_fee_rate: "0.0005"
taker_fee_rate: "0.0012"
service_provider_fee: "0.4"
is_perpetual: true
min_price_tick_size: "100000"
min_quantity_tick_size: "0.0001"
perpetual_market_info {
hourly_funding_rate_cap: "0.000625"
hourly_interest_rate: "0.00000416666"
next_funding_timestamp: 1652796000
funding_interval: 3600
}
perpetual_market_funding {
cumulative_funding: "7234678245.415396885076050889"
cumulative_price: "6.214149999812187743"
last_timestamp: 1652775381
}
}
operation_type: "update"
timestamp: 1652792406000
{
"market": {
"market_id": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
"market_status": "active",
"ticker": "BTC/USDT PERP",
"oracle_base": "BTC",
"oracle_quote": "USDT",
"oracle_type": "bandibc",
"oracle_scale_factor": 6,
"initial_margin_ratio": "0.095",
"maintenance_margin_ratio": "0.05",
"quote_denom": "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7",
"quote_token_meta": {
"name": "Tether",
"address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"symbol": "USDT",
"logo": "https://static.alchemyapi.io/images/assets/825.png",
"decimals": 6,
"updated_at": 1650978923435
},
"maker_fee_rate": "0.0005",
"taker_fee_rate": "0.0012",
"service_provider_fee": "0.4",
"is_perpetual": true,
"min_price_tick_size": "100000",
"min_quantity_tick_size": "0.0001",
"perpetual_market_info": {
"hourly_funding_rate_cap": "0.000625",
"hourly_interest_rate": "0.00000416666",
"next_funding_timestamp": 1653040800,
"funding_interval": 3600
},
"perpetual_market_funding": {
"cumulative_funding": "7356035675.459202347630388315",
"cumulative_price": "3.723976370878870887",
"last_timestamp": 1653038971
}
},
"operation_type": "update",
"timestamp": 1653038974000
}
{
"market": {
"marketId": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
"marketStatus": "active",
"ticker": "BTC/USDT PERP",
"oracleBase": "BTC",
"oracleQuote": "USDT",
"oracleType": "bandibc",
"oracleScaleFactor": 6,
"initialMarginRatio": "0.095",
"maintenanceMarginRatio": "0.05",
"quoteDenom": "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7",
"quoteTokenMeta": {
"name": "Tether",
"address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"symbol": "USDT",
"logo": "https://static.alchemyapi.io/images/assets/825.png",
"decimals": 6,
"updatedAt": 1650978923435
},
"makerFeeRate": "0.0005",
"takerFeeRate": "0.0012",
"serviceProviderFee": "0.4",
"isPerpetual": true,
"minPriceTickSize": "100000",
"minQuantityTickSize": "0.0001",
"perpetualMarketInfo": {
"hourlyFundingRateCap": "0.000625",
"hourlyInterestRate": "0.00000416666",
"nextFundingTimestamp": 1654246800,
"fundingInterval": 3600
},
"perpetualMarketFunding": {
"cumulativeFunding": "8239865636.851083559033030036",
"cumulativePrice": "7.15770685160786651",
"lastTimestamp": 1654246073
}
},
"operationType": "update",
"timestamp": 1654246076000
}
Parameter | Type | Description |
---|---|---|
market | DerivativeMarketInfo | Info about a particular derivative market |
operation_type | String | Update type (Should be one of: ["insert", "delete", "replace", "update", "invalidate"]) |
timestamp | Integer | Operation timestamp in UNIX millis |
DerivativeMarketInfo
Parameter | Type | Description |
---|---|---|
oracle_quote | String | Oracle quote currency |
oracle_type | String | Oracle Type |
quote_denom | String | Coin denom used for the quote asset |
is_perpetual | Boolean | True if the market is a perpetual swap market |
maker_fee_rate | String | Defines the fee percentage makers pay (or receive, if negative) in quote asset when trading |
min_price_tick_size | String | Defines the minimum required tick size for the order's price |
min_quantity_tick_size | String | Defines the minimum required tick size for the order's quantity |
oracle_scale_factor | Integer | Scaling multiple to scale oracle prices to the correct number of decimals |
taker_fee_rate | String | Defines the fee percentage takers pay (in quote asset) when trading |
expiry_futures_market_info | ExpiryFuturesMarketInfo | Info about expiry futures market |
initial_margin_ratio | String | The initial margin ratio of the derivative market |
market_status | String | The status of the market (Should be one of: ["active", "paused", "suspended", "demolished", "expired"]) |
service_provider_fee | String | Percentage of the transaction fee shared with the service provider |
oracle_base | String | Oracle base currency |
perpetual_market_funding | PerpetualMarketFunding | PerpetualMarketFunding object |
perpetual_market_info | PerpetualMarketInfo | Information about the perpetual market |
ticker | String | The name of the pair in format AAA/BBB, where AAA is the base asset and BBB is the quote asset |
maintenance_margin_ratio | String | The maintenance margin ratio of the derivative market |
market_id | String | The market ID |
quoteTokenMeta | TokenMeta | Token metadata for quote asset, only for Ethereum-based assets |
ExpiryFuturesMarketInfo
Parameter | Type | Description |
---|---|---|
expiration_timestamp | Integer | Defines the expiration time for a time expiry futures market in UNIX seconds |
settlement_price | String | Defines the settlement price for a time expiry futures market |
PerpetualMarketFunding
Parameter | Type | Description |
---|---|---|
cumulative_funding | String | Defines the cumulative funding of a perpetual market |
cumulative_price | String | Defines the cumulative price for the current hour up to the last timestamp |
last_timestamp | Integer | Defines the last funding timestamp in UNIX seconds |
PerpetualMarketInfo
Parameter | Type | Description |
---|---|---|
hourly_funding_rate_cap | String | Defines the default maximum absolute value of the hourly funding rate |
hourly_interest_rate | String | Defines the hourly interest rate of the perpetual market |
next_funding_timestamp | Integer | Defines the next funding timestamp in UNIX seconds |
funding_interval | Integer | Defines the funding interval in seconds |
TokenMeta
Parameter | Type | Description |
---|---|---|
address | String | Token's Ethereum contract address |
decimals | Integer | Token decimals |
logo | String | URL to the logo image |
name | String | Token full name |
symbol | String | Token symbol short name |
updatedAt | Integer | Token metadata fetched timestamp in UNIX millis |
OrdersHistory
Lists historical orders posted from a subaccount
IP rate limit group: indexer
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
client = AsyncClient(network)
market_id = "0x141e3c92ed55107067ceb60ee412b86256cedef67b1227d6367b4cdf30c55a74"
subaccount_id = "0x295639d56c987f0e24d21bb167872b3542a6e05a000000000000000000000000"
is_conditional = "false"
skip = 10
limit = 3
orders = await client.get_historical_derivative_orders(
market_id=market_id,
subaccount_id=subaccount_id,
skip=skip,
limit=limit,
is_conditional=is_conditional,
)
print(orders)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
Parameter | Type | Description | Required |
---|---|---|---|
market_id | String | Filter by a single market ID | Yes |
market_ids | String Array | Filter by multiple market IDs | No |
subaccount_id | String | Filter by subaccount ID | No |
skip | Integer | Skip the first n items from the results. This can be used to fetch all results since the API caps at 100 | No |
limit | Integer | Maximum number of items to be returned. 1 <= n <= 100 | No |
direction | String | Filter by order direction (Should be one of: ["buy", "sell"]) | No |
is_conditional | String | Search for conditional/non-conditional orders(Should be one of: ["true", "false"]) | No |
start_time | Integer | Search for orders where createdAt >= startTime, time in milliseconds | No |
end_time | Integer | Search for orders where createdAt <= startTime, time in milliseconds | No |
state | String | The order state (Should be one of: ["booked", "partial_filled", "filled", "canceled"]) | No |
execution_types | String Array | The execution of the order (Should be one of: ["limit", "market"]) | No |
order_type | String | The order type (Should be one of: ["buy", "sell", "stop_buy", "stop_sell", "take_buy", "take_sell", "buy_po", "sell_po"]) | No |
order_types | String Array | The order types to be included (Should be one of: ["buy", "sell", "stop_buy", "stop_sell", "take_buy", "take_sell", "buy_po", "sell_po"]) | No |
Response Parameters
Response Example:
orders {
order_hash: "0x06a9b81441b4fd38bc9da9b928007286b340407481f41398daab291cde2bd6dc"
market_id: "0x90e662193fa29a3a7e6c07be4407c94833e762d9ee82136a2cc712d6b87d7de3"
subaccount_id: "0x295639d56c987f0e24d21bb167872b3542a6e05a000000000000000000000000"
execution_type: "limit"
order_type: "sell"
price: "21805600000"
trigger_price: "0"
quantity: "0.001"
filled_quantity: "0.001"
state: "filled"
created_at: 1676269001530
updated_at: 1676269001530
direction: "sell"
margin: "21800000"
}
orders {
order_hash: "0x1b4ebdd127ecda4a0b392907e872ef960c9a2e76eb4e68a0ab5c1d631f540b85"
market_id: "0x90e662193fa29a3a7e6c07be4407c94833e762d9ee82136a2cc712d6b87d7de3"
subaccount_id: "0x295639d56c987f0e24d21bb167872b3542a6e05a000000000000000000000000"
execution_type: "limit"
order_type: "sell"
price: "21805600000"
trigger_price: "0"
quantity: "0.001"
filled_quantity: "0.001"
state: "filled"
created_at: 1676268938604
updated_at: 1676268938604
direction: "sell"
margin: "21800000"
}
orders {
order_hash: "0x10c4cd0c744c08d38920d063ad5f811b97fd9f5d59224814ad9a02bdffb4c0bd"
market_id: "0x90e662193fa29a3a7e6c07be4407c94833e762d9ee82136a2cc712d6b87d7de3"
subaccount_id: "0x295639d56c987f0e24d21bb167872b3542a6e05a000000000000000000000000"
execution_type: "limit"
order_type: "sell"
price: "21876100000"
trigger_price: "0"
quantity: "0.001"
filled_quantity: "0"
state: "canceled"
created_at: 1676268856766
updated_at: 1676268924613
direction: "sell"
margin: "21900000"
}
paging {
total: 32
}
Parameter | Type | Description |
---|---|---|
orders | DerivativeOrderHistory Array | list of historical derivative orders |
paging | Paging | Pagination of results |
DerivativeOrderHistory
Parameter | Type | Description |
---|---|---|
order_hash | String | Hash of the order |
quantity | String | Quantity of the order |
state | String | Order state (Should be one of: ["booked", "partial_filled", "filled", "canceled"]) |
trigger_price | String | The price that triggers stop/take orders |
market_id | String | Derivative market ID |
created_at | Integer | Order created timestamp in UNIX millis |
updated_at | Integer | Order updated timestamp in UNIX millis |
price | String | Price of the order |
subaccount_id | String | The subaccountId that this order belongs to |
order_type | String | Order type (Should be one of: ["buy", "sell", "stop_buy", "stop_sell", "take_buy", "take_sell", "buy_po", "sell_po"]) |
execution_type | String | The type of the order (Should be one of: ["limit", "market"]) |
filled_quantity | String | The amount of the quantity filled |
direction | String | The direction of the order (Should be one of: ["buy", "sell"]) |
margin | String | The margin of the order |
Paging
Parameter | Type | Description |
---|---|---|
total | Integer | Total number of available records |
StreamOrdersHistory
Stream order updates of a derivative market.
IP rate limit group: indexer
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
client = AsyncClient(network)
market_id = "0x141e3c92ed55107067ceb60ee412b86256cedef67b1227d6367b4cdf30c55a74"
order_side = "sell"
subaccount_id = "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000"
orders = await client.stream_historical_derivative_orders(
market_id=market_id
)
async for order in orders:
print(order)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
import {
TradeDirection,
PaginationOption,
DerivativeOrderSide,
TradeExecutionType,
IndexerGrpcDerivativesApi
} from '@injectivelabs/sdk-ts'
import { getNetworkEndpoints, Network } from '@injectivelabs/networks'
const endpoints = getNetworkEndpoints(Network.TestnetK8s)
const indexerGrpcDerivativesApi = new IndexerGrpcDerivativesApi(endpoints.indexer)
const marketIds = ['0x...'] /* optional param */
const executionTypes = [TradeExecutionType.Market] /* optional param */
const orderTypes = DerivativeOrderSide.StopBuy /* optional param */
const direction = TradeDirection.Buy /* optional param */
const subaccountId = '0x...' /* optional param */
const paginationOption = {...} as PaginationOption /* optional param */
const orderHistory = await indexerGrpcDerivativesApi.fetchOrderHistory({
marketIds,
executionTypes,
orderTypes,
direction,
subaccountId,
paginationOption
})
console.log(orderHistory)
Parameter | Type | Description | Required |
---|---|---|---|
market_id | String | Filter by market ID | Yes |
subaccount_id | String | Filter by subaccount ID | No |
direction | String | Filter by direction (Should be one of: ["buy", "sell"]) | No |
state | String | Filter by state (Should be one of: ["booked", "partial_filled", "filled", "canceled"]) | No |
order_types | String Array | Filter by order type (Should be one of: ["buy", "sell", "stop_buy", "stop_sell", "take_buy", "take_sell", "buy_po", "sell_po"]) | No |
execution_types | String Array | Filter by execution type (Should be one of: ["limit", "market"]) | No |
Response Parameters
Streaming Response Example:
order {
order_hash: "0xfb526d72b85e9ffb4426c37bf332403fb6fb48709fb5d7ca3be7b8232cd10292"
market_id: "0x90e662193fa29a3a7e6c07be4407c94833e762d9ee82136a2cc712d6b87d7de3"
is_active: true
subaccount_id: "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000"
execution_type: "limit"
order_type: "sell_po"
price: "274310000"
trigger_price: "0"
quantity: "144"
filled_quantity: "0"
state: "booked"
created_at: 1665487076373
updated_at: 1665487076373
direction: "sell"
margin: "3950170000"
}
operation_type: "insert"
timestamp: 1665487078000
Parameter | Type | Description |
---|---|---|
order | DerivativeOrderHistory | Updated order |
operation_type | String | Order update type (Should be one of: ["insert", "replace", "update", "invalidate"]) |
timestamp | Integer | Operation timestamp in UNIX millis |
DerivativeOrderHistory
Parameter | Type | Description |
---|---|---|
order_hash | String | Hash of the order |
quantity | String | Quantity of the order |
state | String | Order state (Should be one of: ["booked", "partial_filled", "filled", "canceled"]) |
trigger_price | String | The price that triggers stop/take orders |
market_id | String | Derivative market ID |
created_at | Integer | Order created timestamp in UNIX millis |
updated_at | Integer | Order updated timestamp in UNIX millis |
price | String | Price of the order |
subaccount_id | String | The subaccountId that this order belongs to |
order_type | String | Order type (Should be one of: ["buy", "sell", "stop_buy", "stop_sell", "take_buy", "take_sell", "buy_po", "sell_po"]) |
execution_type | String | The type of the order (Should be one of: ["limit", "market"]) |
filled_quantity | String | The amount of the quantity filled |
direction | String | The direction of the order (Should be one of: ["buy", "sell"]) |
margin | String | The margin of the order |
Trades
Get trades of a derivative market.
IP rate limit group: indexer
*Trade execution types
"market"
for market orders"limitFill"
for a resting limit order getting filled by a market order"limitMatchRestingOrder"
for a resting limit order getting matched with another new limit order"limitMatchNewOrder"
for a new limit order getting matched immediately
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
client = AsyncClient(network)
market_id = "0x141e3c92ed55107067ceb60ee412b86256cedef67b1227d6367b4cdf30c55a74"
subaccount_id = "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000"
trades = await client.get_derivative_trades(
market_id=market_id,
subaccount_id=subaccount_id
)
print(trades)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
derivativeExchangePB "github.com/InjectiveLabs/sdk-go/exchange/derivative_exchange_rpc/pb"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
fmt.Println(err)
}
ctx := context.Background()
marketId := "0x141e3c92ed55107067ceb60ee412b86256cedef67b1227d6367b4cdf30c55a74"
subaccountId := "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000"
req := derivativeExchangePB.TradesRequest{
MarketId: marketId,
SubaccountId: subaccountId,
}
res, err := exchangeClient.GetDerivativeTrades(ctx, req)
if err != nil {
fmt.Println(err)
}
fmt.Println(res)
}
import {
TradeDirection,
PaginationOption,
TradeExecutionType,
IndexerGrpcDerivativesApi
} from '@injectivelabs/sdk-ts'
import { getNetworkEndpoints, Network } from '@injectivelabs/networks'
const endpoints = getNetworkEndpoints(Network.TestnetK8s)
const indexerGrpcDerivativesApi = new IndexerGrpcDerivativesApi(endpoints.indexer)
const marketId = '0x...' /* optional param */
const executionTypes = [TradeExecutionType.Market] /* optional param */
const direction = TradeDirection.Buy /* optional param */
const subaccountId = '0x...'/* optional param */
const paginationOption = {...} as PaginationOption /* optional param */
const trades = await indexerGrpcDerivativesApi.fetchTrades({
marketId,
executionTypes,
direction,
subaccountId,
paginationOption
})
console.log(trades)
Parameter | Type | Description | Required |
---|---|---|---|
market_id | String | Filter by a single market ID | No |
market_ids | String Array | Filter by multiple market IDs | No |
subaccount_id | String | Filter by a single subaccount ID | No |
subaccount_ids | String Array | Filter by multiple subaccount IDs | No |
direction | String | Filter by the direction of the trade (Should be one of: ["buy", "sell"]) | No |
execution_side | String | Filter by the execution side of the trade (Should be one of: ["maker", "taker"]) | No |
execution_types | String Array | Filter by the *trade execution type (Should be one of: ["market", "limitFill", "limitMatchRestingOrder", "limitMatchNewOrder"]) | No |
skip | Integer | Skip the first n items from the results. This can be used to fetch all trades since the API caps at 100 | No |
limit | Integer | Maximum number of items to be returned. 1 <= n <= 100 | No |
start_time | Integer | startTime <= trade execution timestamp <= endTime | No |
end_time | Integer | startTime <= trade execution timestamp <= endTime | No |
Response Parameters
Response Example:
trades {
order_hash: "0xab1d5fbc7c578d2e92f98d18fbeb7199539f84fe62dd474cce87737f0e0a8737"
subaccount_id: "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000"
market_id: "0x90e662193fa29a3a7e6c07be4407c94833e762d9ee82136a2cc712d6b87d7de3"
trade_execution_type: "limitMatchNewOrder"
position_delta {
trade_direction: "sell"
execution_price: "25111000000"
execution_quantity: "0.0001"
execution_margin: "2400000"
}
payout: "0"
fee: "2511.1"
executed_at: 1671745977284
fee_recipient: "inj1cd0d4l9w9rpvugj8upwx0pt054v2fwtr563eh0"
trade_id: "6205591_ab1d5fbc7c578d2e92f98d18fbeb7199539f84fe62dd474cce87737f0e0a8737"
execution_side: "taker"
}
paging {
total: 1
}
{
"trades": [
{
"order_hash": "0x96453bfbda21b4bd53b3b2b85d510f2fec8a56893e9a142d9f7d32484647bccf",
"subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"market_id": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
"trade_execution_type": "market",
"trade_direction": "buy",
"price": {
"price": "0.000000000002305",
"quantity": "1000000000000000000",
"timestamp": 1652809734211
},
"fee": "4610",
"executed_at": 1652809734211,
"fee_recipient": "inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8"
},
{
"order_hash": "0x2d374994918a86f45f9eca46efbc64d866b9ea1d0c49b5aa0c4a114be3570d05",
"subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"market_id": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
"trade_execution_type": "market",
"trade_direction": "sell",
"price": {
"price": "0.000000000001654",
"quantity": "1000000000000000000",
"timestamp": 1652809465316
},
"fee": "3308",
"executed_at": 1652809465316,
"fee_recipient": "inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8"
},
{
"order_hash": "0x832e8544a047a108a45f712d9cbff8ec1349296e65a3cdc312b374849335ae45",
"subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
"market_id": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
"trade_execution_type": "limitFill",
"trade_direction": "sell",
"price": {
"price": "0.00000000002792",
"quantity": "10000000000000000",
"timestamp": 1650974383413
},
"fee": "279.2",
"executed_at": 1650974383413,
"fee_recipient": "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
}
]
}
[
{
"orderHash": "0x3da3c53a00c28787d614c533b70d0c8c954dfa54a31ce930e58c23ee88e3ea09",
"subaccountId": "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000",
"marketId": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
"tradeExecutionType": "limitMatchRestingOrder",
"isLiquidation": false,
"positionDelta": {
"tradeDirection": "buy",
"executionPrice": "39406400000",
"executionQuantity": "0.02",
"executionMargin": "841900000"
},
"payout": "856231180.396992742528328042",
"fee": "394064",
"executedAt": 1654246304825,
"feeRecipient": "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r"
},
{
"orderHash": "0x0dfc926924befc45d36a6178501143085a05e2dfb45330a05f57ed16a1b27a82",
"subaccountId": "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000",
"marketId": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
"tradeExecutionType": "limitMatchRestingOrder",
"isLiquidation": false,
"positionDelta": {
"tradeDirection": "buy",
"executionPrice": "39406400000",
"executionQuantity": "0.07",
"executionMargin": "2912938000"
},
"payout": "2996809131.389474598849148143",
"fee": "1379224",
"executedAt": 1654246304825,
"feeRecipient": "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r"
},
{
"orderHash": "0xcae7168f316a60deaa832eaea99f0ac25a276efbc35913adc74fa64698925422",
"subaccountId": "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000",
"marketId": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
"tradeExecutionType": "limitMatchRestingOrder",
"isLiquidation": false,
"positionDelta": {
"tradeDirection": "buy",
"executionPrice": "40128736026.409431766475",
"executionQuantity": "0.05",
"executionMargin": "2014460000"
},
"payout": "1990739547.202719429741148872",
"fee": "1003218.400660235794161875",
"executedAt": 1654246213333,
"feeRecipient": "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r"
},
{
"orderHash": "0x11736cd550f7d53db11e89d0ae240a1d5a10aa78b00013a760b32964be15dd6d",
"subaccountId": "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000",
"marketId": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
"tradeExecutionType": "limitMatchRestingOrder",
"isLiquidation": false,
"positionDelta": {
"tradeDirection": "buy",
"executionPrice": "40128736026.409431766475",
"executionQuantity": "0.02",
"executionMargin": "804982000"
},
"payout": "796295818.881087771896459548",
"fee": "401287.36026409431766475",
"executedAt": 1654246213333,
"feeRecipient": "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r"
}
]
Parameter | Type | Description |
---|---|---|
trades | DerivativeTrade Array | List of trades of derivative markets |
paging | Paging | Pagination of results |
DerivativeTrade
Parameter | Type | Description |
---|---|---|
executed_at | Integer | Timestamp of trade execution (on chain) in UNIX millis |
position_delta | PositionDelta | Position delta from the trade |
subaccount_id | String | ID of subaccount that executed the trade |
trade_execution_type | String | *Execution type of the trade (Should be one of: ["market", "limitFill", "limitMatchRestingOrder", "limitMatchNewOrder"]) |
fee | String | The fee associated with the trade |
is_liquidation | Boolean | True if the trade is a liquidation |
market_id | String | The market ID |
order_hash | String | The order hash |
payout | String | The payout associated with the trade |
fee_recipient | String | The address that received 40% of the fees |
trade_id | String | Unique identifier to differentiate between trades |
execution_side | String | Execution side of trade (Should be one of: ["maker", "taker"]) |
PositionDelta
Parameter | Type | Description |
---|---|---|
execution_price | String | Execution price of the trade |
execution_quantity | String | Execution quantity of the trade |
trade_direction | String | The direction the trade (Should be one of: ["buy", "sell"]) |
execution_margin | String | Execution margin of the trade |
Paging
Parameter | Type | Description |
---|---|---|
total | Integer | Total number of records available |
StreamTrades
Stream newly executed trades of a derivative market. The default request streams trades from all derivative markets.
IP rate limit group: indexer
*Trade execution types
"market"
for market orders"limitFill"
for a resting limit order getting filled by a market order"limitMatchRestingOrder"
for a resting limit order getting matched with another new limit order"limitMatchNewOrder"
for a new limit order getting matched immediately
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
client = AsyncClient(network)
market_ids = [
"0x90e662193fa29a3a7e6c07be4407c94833e762d9ee82136a2cc712d6b87d7de3",
"0xd5e4b12b19ecf176e4e14b42944731c27677819d2ed93be4104ad7025529c7ff"
]
subaccount_id = "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000"
trades = await client.stream_derivative_trades(
market_id=market_ids[0],
subaccount_id=subaccount_id
)
async for trade in trades:
print(trade)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
derivativeExchangePB "github.com/InjectiveLabs/sdk-go/exchange/derivative_exchange_rpc/pb"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
panic(err)
}
ctx := context.Background()
marketId := "0x141e3c92ed55107067ceb60ee412b86256cedef67b1227d6367b4cdf30c55a74"
subaccountId := "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000"
req := derivativeExchangePB.StreamTradesRequest{
MarketId: marketId,
SubaccountId: subaccountId,
}
stream, err := exchangeClient.StreamDerivativeTrades(ctx, req)
if err != nil {
panic(err)
}
for {
select {
case <-ctx.Done():
return
default:
res, err := stream.Recv()
if err != nil {
panic(err)
return
}
str, _ := json.MarshalIndent(res, "", " ")
fmt.Print(string(str))
}
}
}
import {getNetworkInfo, Network} from "@injectivelabs/networks";
import {protoObjectToJson, TradeDirection, TradeExecutionSide} from "@injectivelabs/sdk-ts";
import { ExchangeGrpcStreamClient } from "@injectivelabs/sdk-ts/dist/client/exchange/ExchangeGrpcStreamClient";;
(async () => {
const network = getNetworkInfo(Network.TestnetK8s);
const marketIds = ["0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"];
const subaccountIds = ["0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000"];
const executionSide = TradeExecutionSide.Maker;
const direction = TradeDirection.Buy;
const pagination = {
skip: 0,
limit: 10,
key: ""
};
const exchangeClient = new ExchangeGrpcStreamClient(
network.exchangeApi
);
await exchangeClient.derivatives.streamDerivativeTrades(
{
marketIds: marketIds,
subaccountIds: subaccountIds,
executionSide: executionSide,
direction: direction,
pagination: pagination,
callback: (streamDerivativeTrades) => {
console.log(protoObjectToJson(streamDerivativeTrades));
},
onEndCallback: (status) => {
console.log("Stream has ended with status: " + status);
},
});
})();
Parameter | Type | Description | Required |
---|---|---|---|
market_id | String | Filter by a single market ID | No |
market_ids | String Array | Filter by multiple market IDs | No |
subaccount_id | String | Filter by a single subaccount ID | No |
subaccount_ids | String Array | Filter by multiple subaccount IDs | No |
direction | String | Filter by the direction of the trade (Should be one of: ["buy", "sell"]) | No |
execution_side | String | Filter by the execution side of the trade (Should be one of: ["maker", "taker"]) | No |
execution_types | String Array | Filter by the *trade execution type (Should be one of: ["market", "limitFill", "limitMatchRestingOrder", "limitMatchNewOrder"]) | No |
Response Parameters
Streaming Response Example:
trade {
order_hash: "0xab1d5fbc7c578d2e92f98d18fbeb7199539f84fe62dd474cce87737f0e0a8737"
subaccount_id: "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000"
market_id: "0x90e662193fa29a3a7e6c07be4407c94833e762d9ee82136a2cc712d6b87d7de3"
trade_execution_type: "limitMatchNewOrder"
position_delta {
trade_direction: "sell"
execution_price: "25111000000"
execution_quantity: "0.0001"
execution_margin: "2400000"
}
payout: "0"
fee: "2511.1"
executed_at: 1671745977284
fee_recipient: "inj1cd0d4l9w9rpvugj8upwx0pt054v2fwtr563eh0"
trade_id: "6205591_ab1d5fbc7c578d2e92f98d18fbeb7199539f84fe62dd474cce87737f0e0a8737"
execution_side: "taker"
}
operation_type: "insert"
timestamp: 1652793013000
{
"trade": {
"order_hash": "0x0403d2e51d73aa1cb46004b16d76279afece9ad14e3784eb93aa6370de466f81",
"subaccount_id": "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000",
"market_id": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
"trade_execution_type": "limitMatchRestingOrder",
"position_delta": {
"trade_direction": "sell",
"execution_price": "40249100000",
"execution_quantity": "0.06",
"execution_margin": "2388462000"
},
"payout": "0",
"fee": "1207473",
"executed_at": 1653040243183,
"fee_recipient": "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r"
},
"operation_type": "insert",
"timestamp": 1653040246000
}{
"trade": {
"order_hash": "0x728d69975e4057d1801f1a7031d0ccf7242abacbf73320da55abab677efc2a7e",
"subaccount_id": "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000",
"market_id": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
"trade_execution_type": "limitMatchRestingOrder",
"position_delta": {
"trade_direction": "sell",
"execution_price": "40249100000",
"execution_quantity": "0.02",
"execution_margin": "779300000"
},
"payout": "0",
"fee": "402491",
"executed_at": 1653040243183,
"fee_recipient": "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r"
},
"operation_type": "insert",
"timestamp": 1653040246000
}
{
"trade": {
"orderHash": "0xc133f2be809052e24c05132014fc685a0c691e2ac1eacfccc0f52749b20bbfda",
"subaccountId": "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000",
"marketId": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
"tradeExecutionType": "limitMatchRestingOrder",
"isLiquidation": false,
"positionDelta": {
"tradeDirection": "buy",
"executionPrice": "39687300000",
"executionQuantity": "0.01",
"executionMargin": "397675000"
},
"payout": "413013107.353824969334409788",
"fee": "198436.5",
"executedAt": 1654246489592,
"feeRecipient": "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r"
},
"operationType": "insert",
"timestamp": 1654246493000
}
{
"trade": {
"orderHash": "0xb59e0591c9a6b8edc95c3b1ee21cb37541164e96acbb3253b68fb0a9675a854d",
"subaccountId": "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000",
"marketId": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
"tradeExecutionType": "limitMatchRestingOrder",
"isLiquidation": false,
"positionDelta": {
"tradeDirection": "buy",
"executionPrice": "39687300000",
"executionQuantity": "0.05",
"executionMargin": "1996400000"
},
"payout": "2065065536.76912484667204894",
"fee": "992182.5",
"executedAt": 1654246489592,
"feeRecipient": "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r"
},
"operationType": "insert",
"timestamp": 1654246493000
}
{
"trade": {
"orderHash": "0x15e0e47533e55b7fe9d8a16053d0d5419b70a8cafac0820cf367f24ecae73eb9",
"subaccountId": "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000",
"marketId": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
"tradeExecutionType": "limitMatchRestingOrder",
"isLiquidation": false,
"positionDelta": {
"tradeDirection": "buy",
"executionPrice": "39687300000",
"executionQuantity": "0.03",
"executionMargin": "1190619000"
},
"payout": "1239039322.061474908003229364",
"fee": "595309.5",
"executedAt": 1654246489592,
"feeRecipient": "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r"
},
"operationType": "insert",
"timestamp": 1654246493000
}
Parameter | Type | Description |
---|---|---|
trade | DerivativeTrade | New derivative market trade |
operation_type | String | Trade operation type (Should be one of: ["insert", "invalidate"]) |
timestamp | Integer | Timestamp the new trade is written into the database in UNIX millis |
DerivativeTrade
Parameter | Type | Description |
---|---|---|
executed_at | Integer | Timestamp of trade execution (on chain) in UNIX millis |
position_delta | PositionDelta | Position delta from the trade |
subaccount_id | String | ID of subaccount that executed the trade |
trade_execution_type | String | *Execution type of the trade (Should be one of: ["market", "limitFill", "limitMatchRestingOrder", "limitMatchNewOrder"]) |
fee | String | The fee associated with the trade |
is_liquidation | Boolean | True if the trade is a liquidation |
market_id | String | The market ID |
order_hash | String | The order hash |
payout | String | The payout associated with the trade |
fee_recipient | String | The address that received 40% of the fees |
trade_id | String | Unique identifier to differentiate between trades |
execution_side | String | Execution side of trade (Should be one of: ["maker", "taker"]) |
PositionDelta
Parameter | Type | Description |
---|---|---|
execution_price | String | Execution price of the trade |
execution_quantity | String | Execution quantity of the trade |
trade_direction | String | The direction the trade (Should be one of: ["buy", "sell"]) |
execution_margin | String | Execution margin of the trade |
Positions
Get the positions of a market.
IP rate limit group: indexer
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
client = AsyncClient(network)
market_ids = [
"0x90e662193fa29a3a7e6c07be4407c94833e762d9ee82136a2cc712d6b87d7de3",
"0xe112199d9ee44ceb2697ea0edd1cd422223c105f3ed2bdf85223d3ca59f5909a"
]
subaccount_id = "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000"
direction = "short"
subaccount_total_positions = False
skip = 4
limit = 4
positions = await client.get_derivative_positions(
market_ids=market_ids,
# subaccount_id=subaccount_id,
direction=direction,
subaccount_total_positions=subaccount_total_positions,
skip=skip,
limit=limit
)
print(positions)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
derivativeExchangePB "github.com/InjectiveLabs/sdk-go/exchange/derivative_exchange_rpc/pb"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
panic(err)
}
ctx := context.Background()
marketId := "0x141e3c92ed55107067ceb60ee412b86256cedef67b1227d6367b4cdf30c55a74"
skip := uint64(0)
limit := int32(2)
req := derivativeExchangePB.PositionsRequest{
MarketId: marketId,
Skip: skip,
Limit: limit,
}
res, err := exchangeClient.GetDerivativePositions(ctx, req)
if err != nil {
panic(err)
}
str, _ := json.MarshalIndent(res, "", " ")
fmt.Print(string(str))
}
import { getNetworkInfo, Network } from "@injectivelabs/networks";
import { protoObjectToJson } from "@injectivelabs/sdk-ts";
import { ExchangeGrpcClient } from "@injectivelabs/sdk-ts/dist/client/exchange/ExchangeGrpcClient";
(async () => {
const network = getNetworkInfo(Network.TestnetK8s);
const marketId = "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce";
const subaccountId = "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000";
const pagination = {
skip: 0,
limit: 10,
key: ""
};
const exchangeClient = new ExchangeGrpcClient(
network.exchangeApi
);
const positions = await exchangeClient.derivatives.fetchPositions(
{
marketId: marketId,
subaccountId: subaccountId,
pagination: pagination,
});
console.log(protoObjectToJson(positions));
})();
Parameter | Type | Description | Required |
---|---|---|---|
market_id | String | Filter by a single market ID | No |
market_ids | String Array | Filter by multiple market IDs | No |
subaccount_id | String | Filter by subaccount ID | No |
direction | String | Filter by direction of position (Should be one of: ["long", "short"]) | |
subaccount_total_positions | Boolean | Choose to return subaccount total positions (Should be one of: [True, False]) | |
skip | Integer | Skip the first n items from the results. This can be used to fetch all results since the API caps at 100 | No |
limit | Integer | Maximum number of items to be returned. 1 <= n <= 100 | No |
start_time | Integer | startTime <= position timestamp <= endTime | No |
end_time | Integer | startTime <= position timestamp <= endTime | No |
Response Parameters
Response Example:
positions {
ticker: "BTC/USDT PERP"
market_id: "0x90e662193fa29a3a7e6c07be4407c94833e762d9ee82136a2cc712d6b87d7de3"
subaccount_id: "0xea98e3aa091a6676194df40ac089e40ab4604bf9000000000000000000000000"
direction: "short"
quantity: "0.01"
entry_price: "18000000000"
margin: "186042357.839476"
liquidation_price: "34861176937.092952"
mark_price: "16835930000"
aggregate_reduce_only_quantity: "0"
updated_at: 1676412001911
created_at: -62135596800000
}
positions {
ticker: "BTC/USDT PERP"
market_id: "0x90e662193fa29a3a7e6c07be4407c94833e762d9ee82136a2cc712d6b87d7de3"
subaccount_id: "0xf0876e4b3afb41594c7fa7e79c37f638e9fc17bc000000000000000000000000"
direction: "short"
quantity: "0.3396"
entry_price: "18542170276.197423020607578062"
margin: "6166391787.817873"
liquidation_price: "34952360798.739463"
mark_price: "16835930000"
aggregate_reduce_only_quantity: "0"
updated_at: 1676412001911
created_at: -62135596800000
}
positions {
ticker: "INJ/USDT PERP"
market_id: "0xe112199d9ee44ceb2697ea0edd1cd422223c105f3ed2bdf85223d3ca59f5909a"
subaccount_id: "0x2da57011081e05273fe34560d7556ce79bc9ef2e000000000000000000000000"
direction: "short"
quantity: "2"
entry_price: "1000000"
margin: "2060353.334536"
liquidation_price: "1933501.587874"
mark_price: "1368087.992"
aggregate_reduce_only_quantity: "0"
updated_at: 1676412001911
created_at: -62135596800000
}
positions {
ticker: "INJ/USDT PERP"
market_id: "0xe112199d9ee44ceb2697ea0edd1cd422223c105f3ed2bdf85223d3ca59f5909a"
subaccount_id: "0x5bd0718082df50745334433ff9aff9c29d60733c000000000000000000000000"
direction: "short"
quantity: "5.8823"
entry_price: "1725484.929364364279278514"
margin: "3192502.681895"
liquidation_price: "2160205.018913"
mark_price: "1368087.992"
aggregate_reduce_only_quantity: "0"
updated_at: 1676412001911
created_at: -62135596800000
}
paging {
total: 13
from: 5
to: 8
}
{
"positions": [
{
"ticker": "BTC/USDT PERP",
"market_id": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
"subaccount_id": "0x306db78bc90ddf11bd917358f48942ccb48f4dc6000000000000000000000000",
"direction": "short",
"quantity": "0.01",
"entry_price": "35187550000",
"margin": "143194359.84865",
"liquidation_price": "47149510461.77619",
"mark_price": "40128736026.4094317665",
"aggregate_reduce_only_quantity": "0"
},
{
"ticker": "BTC/USDT PERP",
"market_id": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
"subaccount_id": "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000",
"direction": "long",
"quantity": "0.5501",
"entry_price": "38000115954.863590915583488073",
"margin": "20888477638.841827",
"liquidation_price": "29441820.010972",
"mark_price": "40128736026.4094317665",
"aggregate_reduce_only_quantity": "0"
}
]
}
{
"positionsList": [
{
"ticker": "BTC/USDT PERP",
"marketId": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
"subaccountId": "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000",
"direction": "short",
"quantity": "1.6321",
"entryPrice": "40673269578.764267860566718788",
"margin": "65479686044.860453741141489314",
"liquidationPrice": "76945874187.425265",
"markPrice": "40128736026.4094317665",
"aggregateReduceOnlyQuantity": "0"
}
]
}
Parameter | Type | Description |
---|---|---|
positions | DerivativePosition Array | List of derivative positions |
paging | Paging | Pagination of results |
DerivativePosition
Parameter | Type | Description |
---|---|---|
direction | String | Direction of the position (Should be one of: ["long", "short"]) |
market_id | String | ID of the market the position is in |
subaccount_id | String | The subaccount ID the position belongs to |
ticker | String | Ticker of the derivative market |
aggregate_reduce_only_quantity | String | Aggregate quantity of the reduce-only orders associated with the position |
entry_price | String | Entry price of the position |
liquidation_price | String | Liquidation price of the position |
margin | String | Margin of the position |
mark_price | String | Oracle price of the base asset |
quantity | String | Quantity of the position |
updated_at | Integer | Position updated timestamp in UNIX millis |
created_at | Integer | Position created timestamp in UNIX millis. Currently not supported (value will be inaccurate). |
Paging
Parameter | Type | Description |
---|---|---|
total | Integer | Total number of available records |
StreamPositions
Stream position updates for a specific market.
IP rate limit group: indexer
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
client = AsyncClient(network)
market_id = "0x141e3c92ed55107067ceb60ee412b86256cedef67b1227d6367b4cdf30c55a74"
subaccount_id = "0xea98e3aa091a6676194df40ac089e40ab4604bf9000000000000000000000000"
positions = await client.stream_derivative_positions(
market_id=market_id,
subaccount_id=subaccount_id
)
async for position in positions:
print(position)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
derivativeExchangePB "github.com/InjectiveLabs/sdk-go/exchange/derivative_exchange_rpc/pb"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
panic(err)
}
ctx := context.Background()
marketId := "0x141e3c92ed55107067ceb60ee412b86256cedef67b1227d6367b4cdf30c55a74"
req := derivativeExchangePB.StreamPositionsRequest{
MarketId: marketId,
}
stream, err := exchangeClient.StreamDerivativePositions(ctx, req)
if err != nil {
panic(err)
}
for {
select {
case <-ctx.Done():
return
default:
res, err := stream.Recv()
if err != nil {
panic(err)
return
}
str, _ := json.MarshalIndent(res, "", " ")
fmt.Print(string(str))
}
}
}
import { getNetworkInfo, Network } from "@injectivelabs/networks";
import { protoObjectToJson } from "@injectivelabs/sdk-ts";
import { ExchangeGrpcStreamClient } from "@injectivelabs/sdk-ts/dist/client/exchange/ExchangeGrpcStreamClient";;
(async () => {
const network = getNetworkInfo(Network.TestnetK8s);
const marketId = "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce";
const subaccountId = "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000";
const exchangeClient = new ExchangeGrpcStreamClient(
network.exchangeApi
);
await exchangeClient.derivatives.streamDerivativePositions(
{
marketId,
subaccountId,
callback: (streamDerivativePositions) => {
console.log(protoObjectToJson(streamDerivativePositions));
},
onEndCallback: (status) => {
console.log("Stream has ended with status: " + status);
},
});
})();
Parameter | Type | Description | Required |
---|---|---|---|
market_id | String | ID of the market to stream position data from | No |
market_ids | String Array | IDs of the markets to stream position data from | No |
subaccount_ids | String Array | Subaccount IDs of the traders to stream positions from | No |
subaccount_id | String | Subaccount ID of the trader to stream positions from | No |
Response Parameters
Streaming Response Example:
positions {
ticker: "BTC/USDT PERP"
market_id: "0x90e662193fa29a3a7e6c07be4407c94833e762d9ee82136a2cc712d6b87d7de3"
subaccount_id: "0xea98e3aa091a6676194df40ac089e40ab4604bf9000000000000000000000000"
direction: "short"
quantity: "0.01"
entry_price: "18000000000"
margin: "186042357.839476"
liquidation_price: "34861176937.092952"
mark_price: "16835930000"
aggregate_reduce_only_quantity: "0"
updated_at: 1676412001911
created_at: -62135596800000
}
timestamp: 1652793296000
{
"position": {
"ticker": "BTC/USDT PERP",
"market_id": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
"subaccount_id": "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000",
"direction": "short",
"quantity": "0.4499",
"entry_price": "40187334829.308997167725462798",
"margin": "17648170480.844939276952101173",
"liquidation_price": "75632579558.528471",
"mark_price": "40128736026.4094317665",
"aggregate_reduce_only_quantity": "0"
},
"timestamp": 1653039418000
}{
"position": {
"ticker": "BTC/USDT PERP",
"market_id": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
"subaccount_id": "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000",
"direction": "short",
"quantity": "0.4499",
"entry_price": "40415133266.89312760388339505",
"margin": "17780087110.130349528796488556",
"liquidation_price": "76128781140.582706",
"mark_price": "40128736026.4094317665",
"aggregate_reduce_only_quantity": "0"
},
"timestamp": 1653039464000
}{
"position": {
"ticker": "BTC/USDT PERP",
"market_id": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
"subaccount_id": "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000",
"direction": "short",
"quantity": "0.4499",
"entry_price": "40306914705.252255649316986606",
"margin": "17654816331.908168110936068341",
"liquidation_price": "75760533574.235878",
"mark_price": "40128736026.4094317665",
"aggregate_reduce_only_quantity": "0"
},
"timestamp": 1653039501000
}
{
"position": {
"ticker": "BTC/USDT PERP",
"marketId": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
"subaccountId": "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000",
"direction": "short",
"quantity": "1.6321",
"entryPrice": "40555935751.758890674529114982",
"margin": "65283896141.678537523412631302",
"liquidationPrice": "76719878206.648298",
"markPrice": "40128736026.4094317665",
"aggregateReduceOnlyQuantity": "0"
},
"timestamp": 1654246646000
}
{
"position": {
"ticker": "BTC/USDT PERP",
"marketId": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
"subaccountId": "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000",
"direction": "short",
"quantity": "1.6321",
"entryPrice": "40489113688.030524225816723708",
"margin": "65069810777.851918748331744252",
"liquidationPrice": "76531312698.56045",
"markPrice": "40128736026.4094317665",
"aggregateReduceOnlyQuantity": "0"
},
"timestamp": 1654246687000
}
Parameter | Type | Description |
---|---|---|
position | DerivativePosition | Updated derivative position |
timestamp | Integer | Timestamp of update in UNIX millis |
DerivativePosition
Parameter | Type | Description |
---|---|---|
direction | String | Direction of the position (Should be one of: ["long", "short"]) |
market_id | String | ID of the market the position is in |
subaccount_id | String | The subaccount ID the position belongs to |
ticker | String | Ticker of the derivative market |
aggregate_reduce_only_quantity | String | Aggregate quantity of the reduce-only orders associated with the position |
entry_price | String | Entry price of the position |
liquidation_price | String | Liquidation price of the position |
margin | String | Margin of the position |
mark_price | String | Oracle price of the base asset |
quantity | String | Quantity of the position |
updated_at | Integer | Position updated timestamp in UNIX millis |
created_at | Integer | Position created timestamp in UNIX millis. Currently not supported (value will be inaccurate). |
[DEPRECATED] Orderbook
Get the orderbook of a derivative market.
Deprecation warning
This API will be removed on April 5, 2023 on testnet and on April 22, 2023 on mainnet. Please use the new api OrderbookV2 instead.
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
client = AsyncClient(network)
market_id = "0x141e3c92ed55107067ceb60ee412b86256cedef67b1227d6367b4cdf30c55a74"
market = await client.get_derivative_orderbook(market_id=market_id)
print(market)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
panic(err)
}
ctx := context.Background()
marketId := "0x141e3c92ed55107067ceb60ee412b86256cedef67b1227d6367b4cdf30c55a74"
res, err := exchangeClient.GetDerivativeOrderbook(ctx, marketId)
if err != nil {
panic(err)
}
str, _ := json.MarshalIndent(res, "", " ")
fmt.Print(string(str))
}
import { getNetworkInfo, Network } from "@injectivelabs/networks";
import { protoObjectToJson } from "@injectivelabs/sdk-ts";
import { ExchangeGrpcClient } from "@injectivelabs/sdk-ts/dist/client/exchange/ExchangeGrpcClient";
(async () => {
const network = getNetworkInfo(Network.TestnetK8s);
const marketId = "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce";
const exchangeClient = new ExchangeGrpcClient(
network.exchangeApi
);
const orderbook = await exchangeClient.derivatives.fetchOrderbook(marketId);
console.log(protoObjectToJson(orderbook));
})();
Parameter | Type | Description | Required |
---|---|---|---|
market_id | String | ID of the market to fetch orderbook from | Yes |
Response Parameters
Response Example:
orderbook {
buys {
price: "5000000000"
quantity: "0.0097"
timestamp: 1657561054917
}
buys {
price: "1000000000"
quantity: "0.001"
timestamp: 1661607737731
}
sells {
price: "21623000000"
quantity: "0.0027"
timestamp: 1676294145312
}
sells {
price: "50000000000"
quantity: "0.1"
timestamp: 1676326399734
}
sells {
price: "65111000000"
quantity: "0.0449"
timestamp: 1668424687130
}
sells {
price: "70000000000"
quantity: "0.0001"
timestamp: 1671787246665
}
sells {
price: "100000000000"
quantity: "0.0037"
timestamp: 1675291786816
}
sells {
price: "101000000000"
quantity: "0.0007"
timestamp: 1675291761230
}
}
{
"orderbook": {
"buys": [
{
"price": "37640700000",
"quantity": "0.1399",
"timestamp": 1650974417291
},
{
"price": "37520300000",
"quantity": "0.16",
"timestamp": 1651491945818
},
{
"price": "37399900000",
"quantity": "0.15",
"timestamp": 1651491945818
},
{
"price": "30000000000",
"quantity": "1",
"timestamp": 1649838645114
}
],
"sells": [
{
"price": "50000000000",
"quantity": "0.01",
"timestamp": 1652457633995
}
]
}
}
{
"orderbook": {
"buysList": [
{
"price": "39165600000",
"quantity": "0.07",
"timestamp": 1654245802262
},
{
"price": "39085300000",
"quantity": "0.07",
"timestamp": 1654245802262
},
{
"price": "25000000000",
"quantity": "0.1",
"timestamp": 1653932262361
}
],
"sellsList": [
{
"price": "39446500000",
"quantity": "0.07",
"timestamp": 1654246681580
},
{
"price": "40449700000",
"quantity": "0.08",
"timestamp": 1654246681580
},
{
"price": "43058100000",
"quantity": "0.0577",
"timestamp": 1654245756032
},
{
"price": "50000000000",
"quantity": "0.012",
"timestamp": 1653932262361
}
]
}
}
Parameter | Type | Description |
---|---|---|
orderbook | DerivativeLimitOrderbook | Orderbook of a particular derivative market |
DerivativeLimitOrderbook
Parameter | Type | Description |
---|---|---|
buys | PriceLevel Array | List of price levels for buys |
sells | PriceLevel Array | List of price levels for sells |
PriceLevel
Parameter | Type | Description |
---|---|---|
quantity | String | Quantity of the price level |
timestamp | Integer | Price level last updated timestamp in UNIX millis |
price | String | Price number of the price level |
[DEPRECATED] Orderbooks
Get the orderbook for an array of derivative markets.
Deprecation warning
This API will be removed on April 5, 2023 on testnet and on April 22, 2023 on mainnet. Please use the new api OrderbookV2 instead.
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
client = AsyncClient(network)
market_ids = [
"0x90e662193fa29a3a7e6c07be4407c94833e762d9ee82136a2cc712d6b87d7de3",
"0xd5e4b12b19ecf176e4e14b42944731c27677819d2ed93be4104ad7025529c7ff"
]
markets = await client.get_derivative_orderbooks(market_ids=market_ids)
print(markets)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
panic(err)
}
ctx := context.Background()
marketIds := []string{"0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce", "0x1f73e21972972c69c03fb105a5864592ac2b47996ffea3c500d1ea2d20138717"}
res, err := exchangeClient.GetDerivativeOrderbooks(ctx, marketIds)
if err != nil {
panic(err)
}
str, _ := json.MarshalIndent(res, "", " ")
fmt.Print(string(str))
}
import { getNetworkInfo, Network } from "@injectivelabs/networks";
import { protoObjectToJson } from "@injectivelabs/sdk-ts";
import { ExchangeGrpcClient } from "@injectivelabs/sdk-ts/dist/client/exchange/ExchangeGrpcClient";
(async () => {
const network = getNetworkInfo(Network.TestnetK8s);
const marketIds = ["0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"];
const exchangeClient = new ExchangeGrpcClient(
network.exchangeApi
);
const market = await exchangeClient.derivatives.fetchOrderbooks(marketIds);
console.log(protoObjectToJson(market));
})();
Parameter | Type | Description | Required |
---|---|---|---|
market_ids | String Array | List of IDs of markets to get orderbooks from | Yes |
Response Parameters
Response Example:
orderbooks {
market_id: "0x90e662193fa29a3a7e6c07be4407c94833e762d9ee82136a2cc712d6b87d7de3"
orderbook {
buys {
price: "5000000000"
quantity: "0.0097"
timestamp: 1657561054917
}
buys {
price: "1000000000"
quantity: "0.001"
timestamp: 1661607737731
}
sells {
price: "21623000000"
quantity: "0.0027"
timestamp: 1676326399734
}
sells {
price: "50000000000"
quantity: "0.1"
timestamp: 1676294145312
}
}
}
orderbooks {
market_id: "0xd5e4b12b19ecf176e4e14b42944731c27677819d2ed93be4104ad7025529c7ff"
orderbook {
buys {
price: "10000000"
quantity: "2"
timestamp: 1670437854869
}
buys {
price: "1000000"
quantity: "1"
timestamp: 1667908624847
}
}
}
{
"orderbooks": [
{
"market_id": "0x1f73e21972972c69c03fb105a5864592ac2b47996ffea3c500d1ea2d20138717",
"orderbook": {}
},
{
"market_id": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
"orderbook": {
"buys": [
{
"price": "37640700000",
"quantity": "0.1399",
"timestamp": 1652792829016
},
{
"price": "37520300000",
"quantity": "0.16",
"timestamp": 1652786114544
},
{
"price": "35000000000",
"quantity": "3",
"timestamp": 1649838645114
},
{
"price": "31000000000",
"quantity": "0.01",
"timestamp": 1649838645114
},
{
"price": "30000000000",
"quantity": "1",
"timestamp": 1649838645114
}
],
"sells": [
{
"price": "50000000000",
"quantity": "0.01",
"timestamp": 1652457633995
}
]
}
}
]
}
{
"orderbooksList": [
{
"marketId": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
"orderbook": {
"buysList": [
{
"price": "39767500000",
"quantity": "0.05",
"timestamp": 1654246733424
},
{
"price": "39687300000",
"quantity": "0.08",
"timestamp": 1654246733424
},
{
"price": "25000000000",
"quantity": "0.1",
"timestamp": 1653932262361
}
],
"sellsList": [
{
"price": "40249100000",
"quantity": "0.05",
"timestamp": 1654246769016
},
{
"price": "43539600000",
"quantity": "0.17",
"timestamp": 1654245756032
},
{
"price": "50000000000",
"quantity": "0.012",
"timestamp": 1653932262361
}
]
}
}
]
}
Parameter | Type | Description |
---|---|---|
orderbooks | SingleDerivativeLimitOrderbook Array | List of derivative market orderbooks |
SingleDerivativeLimitOrderbook
Parameter | Type | Description |
---|---|---|
market_id | String | ID of the market that the orderbook belongs to |
orderbook | DerivativeLimitOrderbook | Orderbook of the market |
DerivativeLimitOrderbook
Parameter | Type | Description |
---|---|---|
buys | PriceLevel Array | List of price levels for buys |
sells | PriceLevel Array | List of price levels for sells |
PriceLevel
Parameter | Type | Description |
---|---|---|
quantity | String | Quantity of the price level |
timestamp | Integer | Price level last updated timestamp in UNIX millis |
price | String | Price number of the price level |
[DEPRECATED] StreamOrderbooks
Stream orderbook updates for an array of derivative markets.
Deprecation warning
This API will be removed on April 5, 2023 on testnet and on April 22, 2023 on mainnet. Please use the new api OrderbookV2 instead.
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
client = AsyncClient(network)
market_id = "0x141e3c92ed55107067ceb60ee412b86256cedef67b1227d6367b4cdf30c55a74"
markets = await client.stream_derivative_orderbook(market_id=market_id)
async for market in markets:
print(market)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/InjectiveLabs/sdk-go/client/common"
exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
)
func main() {
// network := common.LoadNetwork("mainnet", "lb")
network := common.LoadNetwork("testnet", "k8s")
exchangeClient, err := exchangeclient.NewExchangeClient(network.ExchangeGrpcEndpoint, common.OptionTLSCert(network.ExchangeTlsCert))
if err != nil {
panic(err)
}
ctx := context.Background()
marketIds := []string{"0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"}
stream, err := exchangeClient.StreamDerivativeOrderbook(ctx, marketIds)
if err != nil {
panic(err)
}
for {
select {
case <-ctx.Done():
return
default:
res, err := stream.Recv()
if err != nil {
panic(err)
return
}
str, _ := json.MarshalIndent(res, "", " ")
fmt.Print(string(str))
}
}
}
import { getNetworkInfo, Network } from "@injectivelabs/networks";
import { protoObjectToJson } from "@injectivelabs/sdk-ts";
import { ExchangeGrpcStreamClient } from "@injectivelabs/sdk-ts/dist/client/exchange/ExchangeGrpcStreamClient";;
(async () => {
const network = getNetworkInfo(Network.TestnetK8s);
const marketIds = ["0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"];
const exchangeClient = new ExchangeGrpcStreamClient(
network.exchangeApi
);
await exchangeClient.derivatives.streamDerivativeOrderbook(
{
marketIds,
callback: (streamOrderbook) => {
console.log(protoObjectToJson(streamOrderbook));
},
onEndCallback: (status) => {
console.log("Stream has ended with status: " + status);
},
});
})();
Parameter | Type | Description | Required |
---|---|---|---|
market_ids | String Array | List of market IDs for orderbook streaming, empty means 'ALL' derivative markets | Yes |
Response Parameters
Streaming Response Example:
orderbook {
buys {
price: "37640700000"
quantity: "0.1399"
timestamp: 1652792829016
}
buys {
price: "37520300000"
quantity: "0.16"
timestamp: 1652786114544
}
buys {
price: "35179900000"
quantity: "0.01"
timestamp: 1650974417291
}
sells {
price: "50000000000"
quantity: "0.01"
timestamp: 1652457633995
}
}
operation_type: "update"
timestamp: 1652793515000
market_id: "0x90e662193fa29a3a7e6c07be4407c94833e762d9ee82136a2cc712d6b87d7de3"
{
"orderbook": {
"buys": [
{
"price": "40289200000",
"quantity": "0.02",
"timestamp": 1653039106493
},
{
"price": "30000000000",
"quantity": "1",
"timestamp": 1649838645114
}
],
"sells": [
{
"price": "40971400000",
"quantity": "0.01",
"timestamp": 1653039061717
},
{
"price": "41212200000",
"quantity": "0.08",
"timestamp": 1653038883873
},
{
"price": "50000000000",
"quantity": "0.01",
"timestamp": 1652457633995
}
]
},
"operation_type": "update",
"timestamp": 1653039112000,
"market_id": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"
}{
"orderbook": {
"buys": [
{
"price": "39286000000",
"quantity": "0.02",
"timestamp": 1653038931674
},
{
"price": "30000000000",
"quantity": "1",
"timestamp": 1649838645114
}
],
"sells": [
{
"price": "39767500000",
"quantity": "0.01",
"timestamp": 1653039143024
},
{
"price": "40168800000",
"quantity": "0.02",
"timestamp": 1653039143024
},
{
"price": "50000000000",
"quantity": "0.01",
"timestamp": 1652457633995
}
]
},
"operation_type": "update",
"timestamp": 1653039145000,
"market_id": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"
}{
"orderbook": {
"buys": [
{
"price": "40249100000",
"quantity": "0.03",
"timestamp": 1653039193813
},
{
"price": "50000000000",
"quantity": "0.01",
"timestamp": 1652457633995
}
]
},
"operation_type": "update",
"timestamp": 1653039198000,
"market_id": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"
}
{
"orderbook": {
"buysList": [
{
"price": "39767500000",
"quantity": "0.05",
"timestamp": 1654246733424
},
{
"price": "39687300000",
"quantity": "0.08",
"timestamp": 1654246733424
},
{
"price": "25000000000",
"quantity": "0.1",
"timestamp": 1653932262361
}
],
"sellsList": [
{
"price": "40530000000",
"quantity": "0.01",
"timestamp": 1654246681580
},
{
"price": "43539600000",
"quantity": "0.17",
"timestamp": 1654245756032
},
{
"price": "50000000000",
"quantity": "0.012",
"timestamp": 1653932262361
}
]
},
"operationType": "update",
"timestamp": 1654246904000,
"marketId": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"
}
Parameter | Type | Description |
---|---|---|
operation_type | String | Order update type (Should be one of: ["insert", "delete", "replace", "update", "invalidate"]) |
orderbook | DerivativeLimitOrderbook | Orderbook of a Derivative Market |
timestamp | Integer | Orderbook update timestamp in UNIX millis |
market_id | String | ID of the market the orderbook belongs to |
DerivativeLimitOrderbook
Parameter | Type | Description |
---|---|---|
buys | PriceLevel Array | List of price levels for buys |
sells | PriceLevel Array | List of price levels for sells |
PriceLevel
Parameter | Type | Description |
---|---|---|
quantity | String | Quantity of the price level |
timestamp | Integer | Price level last updated timestamp in UNIX millis |
price | String | Price number of the price level |
OrderbooksV2
Get an orderbook snapshot for one or more derivative markets.
IP rate limit group: indexer
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
client = AsyncClient(network)
market_ids = [
"0x90e662193fa29a3a7e6c07be4407c94833e762d9ee82136a2cc712d6b87d7de3",
"0xd5e4b12b19ecf176e4e14b42944731c27677819d2ed93be4104ad7025529c7ff"
]
orderbooks = await client.get_derivative_orderbooksV2(market_ids=market_ids)
print(orderbooks)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
Parameter | Type | Description | Required |
---|---|---|---|
market_ids | String Array | List of IDs of markets to get orderbook snapshots from | Yes |
Response Parameters
Response Example:
orderbooks {
market_id: "0x90e662193fa29a3a7e6c07be4407c94833e762d9ee82136a2cc712d6b87d7de3"
orderbook {
buys {
price: "5000000000"
quantity: "0.0097"
timestamp: 1676383776468
}
buys {
price: "1000000000"
quantity: "0.001"
timestamp: 1661607737731
}
sells {
price: "50000000000"
quantity: "0.1"
timestamp: 1676326399734
}
sells {
price: "65111000000"
quantity: "0.0449"
timestamp: 1675291786816
}
sells {
price: "70000000000"
quantity: "0.0001"
timestamp: 1671787246665
}
sells {
price: "100000000000"
quantity: "0.0037"
timestamp: 1675291786816
}
sells {
price: "101000000000"
quantity: "0.0007"
timestamp: 1675291761230
}
sequence: 582
}
}
orderbooks {
market_id: "0xd5e4b12b19ecf176e4e14b42944731c27677819d2ed93be4104ad7025529c7ff"
orderbook {
buys {
price: "930000000"
quantity: "0.01"
timestamp: 1676014824244
}
buys {
price: "900000000"
quantity: "0.4999"
timestamp: 1670444208954
}
buys {
price: "10000000"
quantity: "2"
timestamp: 1670437854869
}
buys {
price: "1000000"
quantity: "1"
timestamp: 1667908624847
}
sequence: 148
}
}
Parameter | Type | Description |
---|---|---|
orderbooks | SingleDerivativeLimitOrderbookV2 Array | List of derivative market orderbooks |
SingleDerivativeLimitOrderbookV2
Parameter | Type | Description |
---|---|---|
market_id | String | ID of the market that the orderbook belongs to |
orderbook | DerivativeLimitOrderbookV2 | Orderbook of the market |
DerivativeLimitOrderbookV2
Parameter | Type | Description |
---|---|---|
buys | PriceLevel Array | List of price levels for buys |
sells | PriceLevel Array | List of price levels for sells |
sequence | Integer | Sequence number of the orderbook; increments by 1 each update |
PriceLevel
Parameter | Type | Description |
---|---|---|
quantity | String | Quantity of the price level |
timestamp | Integer | Price level last updated timestamp in UNIX millis |
price | String | Price number of the price level |
StreamOrderbooksV2
Stream orderbook snapshot updates for one or more derivative markets
IP rate limit group: indexer
Request Parameters
Request Example:
import asyncio
import logging
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network
async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
client = AsyncClient(network)
market_ids = ["0x90e662193fa29a3a7e6c07be4407c94833e762d9ee82136a2cc712d6b87d7de3"]
orderbooks = await client.stream_derivative_orderbook_snapshot(market_ids=market_ids)
async for orderbook in orderbooks:
print(orderbook)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
import { IndexerGrpcDerivativesStream } from '@injectivelabs/sdk-ts'
import { getNetworkEndpoints, Network } from '@injectivelabs/networks'
const endpoints = getNetworkEndpoints(Network.TestnetK8s)
const indexerGrpcDerivativesStream = new IndexerGrpcDerivativesStream(endpoints.indexer)
const marketIds = ['0x...']
const streamFn = indexerGrpcDerivativesStream.streamDerivativeOrderbookV2.bind(indexerGrpcDerivativesStream)
const callback = (orderbooks) => {
console.log(orderbooks)
}
const streamFnArgs = {
marketIds,
callback
}
streamFn(streamFnArgs)
Parameter | Type | Description | Required |
---|---|---|---|
market_ids | String Array | List of market IDs for orderbook streaming; empty means all spot markets | Yes |
Response Parameters
Streaming Response Example:
orderbook {
buys {
price: "10000000000"
quantity: "0.0002"
timestamp: 1676621246197
}
buys {
price: "5000000000"
quantity: "0.0097"
timestamp: 1676383776468
}
buys {
price: "1000000000"
quantity: "0.001"
timestamp: 1661607737731
}
sells {
price: "50000000000"
quantity: "0.1"
timestamp: 1676326399734
}
sells {
price: "65111000000"
quantity: "0.0449"
timestamp: 1675291786816
}
sells {
price: "70000000000"
quantity: "0.0001"
timestamp: 1671787246665
}
sells {
price: "100000000000"
quantity: "0.0037"
timestamp: 1675291786816
}
sells {
price: "101000000000"
quantity: "0.0007"
timestamp: 1675291761230
}
sequence: 584
}
operation_type: "update"
timestamp: 1676621249000
market_id: "0x90e662193fa29a3a7e6c07be4407c94833e762d9ee82136a2cc712d6b87d7de3"
{
orderbook: {
sells: [{
price: "0.000000000008",
quantity: "10000000000000000",
timestamp: 1675904636889,
}],
buys: [{
price: "0.000000000001",
quantity: "10000000000000000",
timestamp: 1675882430039,
}],
sequence: 713,
timestamp: "343432244"
}
operationType: "update"
timestamp: 1676610727000
marketId: "