NAV
Python Golang

Change Log

2024-08-06

2024-07-30

2024-03-08

2024-01-25

2024-01-02

2023-09-06

2023-08-28

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

InjectiveLabs/sdk-python

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 is added.



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()

By default the AsyncClient and the Composer will only initialize the tokens that are part of an active market. In order to let them use any of the tokens available in the chain, the user has to execute the initialize_tokens_from_chain_denoms in the AsyncClient before the creation of the Composer.

Example - Initialize with all tokens from the chain

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)
await client.initialize_tokens_from_chain_denoms()
composer = await client.composer()

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

Markets and Tokens information

Example - Traditional ChainClient instantiation

package main

import (
    "fmt"
    "github.com/InjectiveLabs/sdk-go/client"
    "os"

    "github.com/InjectiveLabs/sdk-go/client/common"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    // initialize grpc client
    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )
    if err != nil {
        fmt.Println(err)
    }
    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        fmt.Println(err)
    }

}

Go 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 1.49 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 is added.













































Example - Get markets and tokens from Indexer (ExchangeClient)

package main

import (
    "context"
    "github.com/InjectiveLabs/sdk-go/client"
    "github.com/InjectiveLabs/sdk-go/client/core"
    exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
    "os"

    "github.com/InjectiveLabs/sdk-go/client/common"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    // initialize grpc client
    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )
    if err != nil {
        panic(err)
    }
    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketsAssistant, err := core.NewMarketsAssistantUsingExchangeClient(ctx, exchangeClient)
    if err != nil {
        panic(err)
    }
}




















































Example - MarketsAssistant with all tokens

package main

import (
    "context"
    "github.com/InjectiveLabs/sdk-go/client"
    "github.com/InjectiveLabs/sdk-go/client/core"
    exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
    "os"

    "github.com/InjectiveLabs/sdk-go/client/common"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    // initialize grpc client
    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )
    if err != nil {
        panic(err)
    }
    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketsAssistant, err := core.NewMarketsAssistantWithAllTokens(ctx, exchangeClient, chainClient)
    if err != nil {
        panic(err)
    }
}

By default the MarketsAssistant will only initialize the tokens that are part of an active market. In order to let it use any of the tokens available in the chain, the user has to create the MarketsAssistant instance using the function NewMarketsAssistantWithAllTokens.

The MarketsAssistant instance can be used with the following ChainClient functions:

Reference

InjectiveLabs/sdk-go.

Typescript Client

Installation

Install the @injectivelabs/sdk-ts npm package using yarn

yarn add @injectivelabs/sdk-ts

Reference

To see Typescript examples please check the Typescript SDK documentation page listed above

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:

  1. The Injective Chain node (the Chain API)
  2. The Injective Exchange API

The trading lifecycle is as follows:

  1. First, traders cryptographically sign a transaction containing one or more order messages (e.g. MsgBatchCreateDerivativeLimitOrders, MsgCreateSpotMarketOrder, MsgCancelDerivativeLimitOrder, etc. ).
  2. Then the transaction is broadcasted to an Injective Chain node.
  3. The transaction is then added to the mempool and becomes included in a block. More details on this process can be found here.
  4. 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.
  5. 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.
  6. The funds are settled accordingly, with positions being created for derivative trades and assets being swapped for spot trades.
  7. Events containing the trade and settlement information are emitted by the Chain.
  8. The Injective Exchange API backend indexes the events and pushes updates to all subscribed traders.

Key Differences To CEX

To summarize the sequence of state changes on the Injective Chain:

  1. Mempool: A queue of pending transactions.
  2. 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).
  3. Handler: Code that is executed when a transaction is included in a block.
  4. 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:

  1. 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.
  2. 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.

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:

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:

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.

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

  1. partially closed
  2. fully closed
  3. 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:

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:

We check 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.5 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:

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.

Order types

Market and Limit Order Examples

Adding a Spot Market Buy Order

→ 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:

Adding a Spot Market Sell Order

→ 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:

Adding a Spot Limit Buy Order

→ The account's available balance is decremented by 5,000 USDT + Taker Fee = 5,005 USDT.

After the order is submitted:

Adding a Spot Limit Sell Order

→ The account's available balance is decremented by 1,000 INJ.

After the order is submitted:

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

→ 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):

If Matched:

Assuming:

Would result in:

1. Closing existing position with proportional order margin for closing:

2. Opening new position in opposite direction:

3. Refunding margin difference from order price vs. clearing price:

4. Refunding fee difference from order price vs. clearing price:

Market Order Matching

Existing Orderbook

Sells Buys
PriceQuantity
$64,3900.3 BTC
$64,3700.2 BTC
$64,3600.5 BTC
PriceQuantity
$64,2100.1 BTC
$64,2050.4 BTC
$64,2000.2 BTC

New Orders

Resulting Orderbook

Sells Buys
PriceQuantity
$64,3900.3 BTC
$64,3700.2 BTC
PriceQuantity
$64,2050.2 BTC
$64,2000.2 BTC

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
PriceQuantity
$64,3900.3 BTC
$64,3700.2 BTC
$64,2500.5 BTC
PriceQuantity
$64,2100.1 BTC
$64,2050.3 BTC
$64,2000.2 BTC

New Orders

Sells Buys
PriceQuantity
$64,2200.4 BTC
$64,1800.2 BTC
PriceQuantity
$64,3700.4 BTC
$64,3600.2 BTC

Matching Orders

All new orders are incorporated into the existing orderbook. In our case this results in a negative spread:

Sells Buys
PriceQuantity
$64,3900.3 BTC
$64,3700.2 BTC
$64,2500.5 BTC
$64,2200.4 BTC
$64,1800.2 BTC
PriceQuantity
$64,3700.4 BTC
$64,3600.1 BTC
$64,2100.1 BTC
$64,2050.3 BTC
$64,2000.2 BTC

As long as negative spread exists, orders are matched against each other. The first buy order is fully matched:

Sells Buys
PriceQuantity
$64,3900.3 BTC
$64,3700.2 BTC
$64,2500.4 BTC
$64,2200.2 BTC
PriceQuantity
$64,3600.1 BTC
$64,2100.1 BTC
$64,2050.3 BTC
$64,2000.2 BTC

Now the second buy order can still be fully matched:

Sells Buys
PriceQuantity
$64,3900.3 BTC
$64,3700.2 BTC
$64,2500.4 BTC
$64,2200.1 BTC
PriceQuantity
$64,2100.1 BTC
$64,2050.3 BTC
$64,2000.2 BTC

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.

Step 1: Check if clearing price range is out of bounds regarding the resting orderbook mid price.

Step 2: Check if clearing price range is out of bounds regarding the mark price.

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 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

Explorer Mainnet

Explorer Testnet

Faucet

A web-based service that provides free tokens to users on testnet and allows them to experiment on the Injective Chain.

Faucet

Status

Monitor the uptime of all public services.

Testnet Status

Mainnet Status

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
import os
import uuid
from decimal import Decimal

import dotenv

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:
    dotenv.load_dotenv()
    private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()
    composer = ProtoMsgComposer(network=network.string())

    message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
        network=network,
        private_key=private_key_in_hexa,
    )

    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.spot_order(
            market_id=spot_market_id_create,
            subaccount_id=subaccount_id,
            fee_recipient=fee_recipient,
            price=Decimal("3"),
            quantity=Decimal("55"),
            order_type="BUY",
            cid=(str(uuid.uuid4())),
        ),
        composer.spot_order(
            market_id=spot_market_id_create,
            subaccount_id=subaccount_id,
            fee_recipient=fee_recipient,
            price=Decimal("300"),
            quantity=Decimal("55"),
            order_type="SELL",
            cid=str(uuid.uuid4()),
        ),
    ]

    # prepare tx msg
    msg = composer.msg_batch_update_orders(
        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
import os
import uuid
from decimal import Decimal

import dotenv

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:
    dotenv.load_dotenv()
    private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()
    composer = ProtoMsgComposer(network=network.string())

    message_broadcaster = MsgBroadcasterWithPk.new_without_simulation(
        network=network,
        private_key=private_key_in_hexa,
    )

    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.spot_order(
            market_id=spot_market_id_create,
            subaccount_id=subaccount_id,
            fee_recipient=fee_recipient,
            price=Decimal("3"),
            quantity=Decimal("55"),
            order_type="BUY",
            cid=str(uuid.uuid4()),
        ),
        composer.spot_order(
            market_id=spot_market_id_create,
            subaccount_id=subaccount_id,
            fee_recipient=fee_recipient,
            price=Decimal("300"),
            quantity=Decimal("55"),
            order_type="SELL",
            cid=str(uuid.uuid4()),
        ),
    ]

    # prepare tx msg
    msg = composer.msg_batch_update_orders(
        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
import os
import uuid
from decimal import Decimal

import dotenv

from pyinjective.async_client import AsyncClient
from pyinjective.composer import Composer as ProtoMsgComposer
from pyinjective.core.broadcaster import MsgBroadcasterWithPk
from pyinjective.core.network import Network
from pyinjective.wallet import Address, PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    private_key_in_hexa = os.getenv("INJECTIVE_GRANTEE_PRIVATE_KEY")
    granter_inj_address = os.getenv("INJECTIVE_GRANTER_PUBLIC_ADDRESS")

    # 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
    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,
    )

    # prepare tx msg
    market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"

    granter_address = Address.from_acc_bech32(granter_inj_address)
    granter_subaccount_id = granter_address.get_subaccount_id(index=0)

    msg = composer.msg_create_spot_limit_order(
        market_id=market_id,
        sender=granter_inj_address,
        subaccount_id=granter_subaccount_id,
        fee_recipient=address.to_acc_bech32(),
        price=Decimal("7.523"),
        quantity=Decimal("0.01"),
        order_type="BUY",
        cid=str(uuid.uuid4()),
    )

    # 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
import os
import uuid
from decimal import Decimal

import dotenv

from pyinjective.async_client import AsyncClient
from pyinjective.composer import Composer as ProtoMsgComposer
from pyinjective.core.broadcaster import MsgBroadcasterWithPk
from pyinjective.core.network import Network
from pyinjective.wallet import Address, PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    private_key_in_hexa = os.getenv("INJECTIVE_GRANTEE_PRIVATE_KEY")
    granter_inj_address = os.getenv("INJECTIVE_GRANTER_PUBLIC_ADDRESS")

    # 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
    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,
    )

    # prepare tx msg
    market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
    granter_address = Address.from_acc_bech32(granter_inj_address)
    granter_subaccount_id = granter_address.get_subaccount_id(index=0)

    msg = composer.msg_create_spot_limit_order(
        market_id=market_id,
        sender=granter_inj_address,
        subaccount_id=granter_subaccount_id,
        fee_recipient=address.to_acc_bech32(),
        price=Decimal("7.523"),
        quantity=Decimal("0.01"),
        order_type="BUY",
        cid=str(uuid.uuid4()),
    )

    # 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

Fine-tunning gas fee local estimation

As mentioned before the gas estimation without using simulation is implemented by using fixed values as gas cost for certain messages and actions. Since the real gas cost can differ at some point from the estimator calculations, the Python SDK allows the developer to fine-tune certain gas cost values in order to improve the gas cost estimation. In the next tables you can find the global values used for gas estimation calculations, that can be modified in your application:

Module Global Variable Description
pyinjective.core.gas_limit_estimator SPOT_ORDER_CREATION_GAS_LIMIT The gas cost associated to the creation of one spot order
pyinjective.core.gas_limit_estimator DERIVATIVE_ORDER_CREATION_GAS_LIMIT The gas cost associated to the creation of one derivative order
pyinjective.core.gas_limit_estimator SPOT_ORDER_CANCELATION_GAS_LIMIT The gas cost associated to the cancellation of one spot order
pyinjective.core.gas_limit_estimator DERIVATIVE_ORDER_CANCELATION_GAS_LIMIT The gas cost associated to the cancellation of one derivative order
pyinjective.core.gas_limit_estimator SPOT_POST_ONLY_ORDER_MULTIPLIER Multiplier to increase the gas cost for post only spot orders (in addition to the normal spot order cost)
pyinjective.core.gas_limit_estimator DERIVATIVE_POST_ONLY_ORDER_MULTIPLIER Multiplier to increase the gas cost for post only derivative orders (in addition to the normal derivative order cost)
Class Global Variable Description
MessageBasedTransactionFeeCalculator TRANSACTION_GAS_LIMIT The gas cost associated to the TX processing
GasLimitEstimator GENERAL_MESSAGE_GAS_LIMIT Generic base gas cost for any message
GasLimitEstimator BASIC_REFERENCE_GAS_LIMIT Base gas cost for messages not related to orders. Each type of message will calculate its cost multiplying this reference cost by a multiplier
DefaultGasLimitEstimator DEFAULT_GAS_LIMIT The gas cost for all messages for which there is no especial estimator implemented
BatchUpdateOrdersGasLimitEstimator CANCEL_ALL_SPOT_MARKET_GAS_LIMIT This is an estimation of the gas cost per spot order cancel when cancelling all orders for a spot market
BatchUpdateOrdersGasLimitEstimator CANCEL_ALL_DERIVATIVE_MARKET_GAS_LIMIT This is an estimation of the gas cost per derivative order cancel when cancelling all orders for a derivative market
BatchUpdateOrdersGasLimitEstimator MESSAGE_GAS_LIMIT Estimation of the general gas amount required for a MsgBatchUpdateOrders (not for particular actions, but for the general message processing)
BatchUpdateOrdersGasLimitEstimator AVERAGE_CANCEL_ALL_AFFECTED_ORDERS This global represents the expected number of orders to be cancelled when executing a "cancel all orders for a market" action
ExecGasLimitEstimator DEFAULT_GAS_LIMIT Estimation of the general gas amount required for a MsgExec (for the general message processing)
GenericExchangeGasLimitEstimator BASIC_REFERENCE_GAS_LIMIT Base gas cost for messages not related to orders. Each type of message will calculate its cost multiplying this reference cost by a multiplier

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

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    account_address = "inj1clw20s2uxeyxtam6f7m84vgae92s9eh7vygagt"
    subacc_list = await client.fetch_subaccounts_list(account_address)
    print(subacc_list)


if __name__ == "__main__":
    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("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    accountAddress := "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku"
    res, err := exchangeClient.GetSubaccountsList(ctx, accountAddress)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
account_addressStringInjective address of the account to query for subaccountsYes

Response Parameters

Response Example:

{
   "subaccounts":[
      "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001",
      "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000002",
      "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000000"
   ]
}
{
 "subaccounts": [
  "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001",
  "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000002"
 ]
}
ParameterTypeDescription
subaccountsString ArraySubaccounts list

SubaccountHistory

Get the subaccount's transfer history.

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
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
    pagination = PaginationOption(skip=skip, limit=limit, end_time=end_time)
    subacc_history = await client.fetch_subaccount_history(
        subaccount_id=subaccount,
        denom=denom,
        transfer_types=transfer_types,
        pagination=pagination,
    )
    print(subacc_history)


if __name__ == "__main__":
    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("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    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))
}
ParameterTypeDescriptionRequired
subaccount_idStringID of the subaccount to get the history fromYes
denomStringFilter by token denomNo
transfer_typesString ArrayFilter by transfer types. Valid options: internal, external, withdraw, depositNo
skipIntegerSkip the first N items from the resultNo
limitIntegerMaximum number of items to be returnedNo
end_timeIntegerUpper bound (inclusive) of account transfer history executed_at unix timestampNo

Response Parameters

Response Example:

{
   "transfers":[
      {
         "transferType":"deposit",
         "srcAccountAddress":"inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
         "dstSubaccountId":"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
         "amount":{
            "denom":"inj",
            "amount":"2000000000000000000"
         },
         "executedAt":"1665117493543",
         "srcSubaccountId":"",
         "dstAccountAddress":""
      },
      {
         "transferType":"deposit",
         "srcAccountAddress":"inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
         "dstSubaccountId":"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
         "amount":{
            "denom":"inj",
            "amount":"15000000000000000000"
         },
         "executedAt":"1660313668990",
         "srcSubaccountId":"",
         "dstAccountAddress":""
      }
   ],
   "paging":{
      "total":"3",
      "from":0,
      "to":0,
      "countBySubaccount":"0",
      "next":[

      ]
   }
}

{
 "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
  }
 ]
}
ParameterTypeDescription
transfersSubaccountBalanceTransfer ArrayTransfers list
pagingPagingPagination details


SubaccountBalanceTransfer

ParameterTypeDescription
transfer_typeStringType of subaccount balance transfer
src_subaccount_idStringSubaccount ID of the sending side
src_account_addressStringAccount address of the sending side
dst_subaccount_idStringSubaccount ID of the receiving side
dst_account_addressStringAccount address of the receiving side
amountCosmosCoinTransfer amount
executed_atIntegerTransfer timestamp (in milliseconds)


CosmosCoin

ParameterTypeDescription
denomStringToken denom
amountStringToken amount


Paging

ParameterTypeDescription
totalIntegerTotal number of available records
fromIntegerRecord index start
toIntegerRecord index end
count_by_subaccountIntegerCount entries by subaccount
nextString ArrayList of tokens to navigate to the next pages

SubaccountBalance

Get the balance of a subaccount for a specific denom.

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    subaccount_id = "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
    denom = "inj"
    balance = await client.fetch_subaccount_balance(subaccount_id=subaccount_id, denom=denom)
    print(balance)


if __name__ == "__main__":
    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")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    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))
}
ParameterTypeDescriptionRequired
subaccount_idStringID of the subaccount to get the balances fromYes
denomStringFilter by token denomYes

Response Parameters

Response Example:

{
   "balance":{
      "subaccountId":"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
      "accountAddress":"inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
      "denom":"inj",
      "deposit":{
         "totalBalance":"0",
         "availableBalance":"0"
      }
   }
}
{
 "balance": {
  "subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
  "account_address": "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
  "denom": "inj",
  "deposit": {
   "total_balance": "1492235700000000000000",
   "available_balance": "1492235700000000000000"
  }
 }
}
ParameterTypeDescription
balanceSubaccountBalanceBalance details


SubaccountBalance

ParameterTypeDescription
subaccount_idStringSubaccount ID
account_addressStringInjective address of the account the subaccount belongs to
denomStringToken denom
depositSubaccountDepositDeposit details


SubaccountDeposit

ParameterTypeDescription
total_balanceStringTotal balance
available_balanceStringAvailable balance

SubaccountBalancesList

List the subaccount's balances for all denoms.

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio

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.fetch_subaccount_balances_list(subaccount_id=subaccount, denoms=denoms)
    print(subacc_balances_list)


if __name__ == "__main__":
    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("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    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))
}
ParameterTypeDescriptionRequired
subaccount_idStringID of the subaccount to get the balances fromYes
denomsStringFilter balances by denoms. If not set, the balances of all the denoms for the subaccount are providedNo

Response Parameters

Response Example:

{
   "balances":[
      {
         "subaccountId":"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
         "accountAddress":"inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
         "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
         "deposit":{
            "totalBalance":"131721505.337958346262317217",
            "availableBalance":"0.337958346262317217"
         }
      },
      {
         "subaccountId":"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
         "accountAddress":"inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
         "denom":"inj",
         "deposit":{
            "totalBalance":"0",
            "availableBalance":"0"
         }
      }
   ]
}
{
 "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"
   }
  }
 ]
}
ParameterTypeDescription
balancesSubaccountBalance ArrayList of subaccount balances


SubaccountBalance

ParameterTypeDescription
subaccount_idStringSubaccount ID
account_addressStringInjective address of the account the subaccount belongs to
denomStringToken denom
depositSubaccountDepositDeposit details


SubaccountDeposit

ParameterTypeDescription
total_balanceStringTotal balance
available_balanceStringAvailable balance

SubaccountOrderSummary

Get a summary of the subaccount's active/unfilled orders.

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio

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 = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    subacc_order_summary = await client.fetch_subaccount_order_summary(
        subaccount_id=subaccount, order_direction=order_direction, market_id=market_id
    )
    print(subacc_order_summary)


if __name__ == "__main__":
    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("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    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)
}
ParameterTypeDescriptionRequired
subaccount_idStringID of the subaccount to get the summary fromYes
market_idStringLimit the order summary to a specific marketNo
order_directionStringFilter by the direction of the orders. Valid options: buy, sellNo

Response Parameters

Response Example:

{
   "derivativeOrdersTotal":"1",
   "spotOrdersTotal":"0"
}
spot orders: 1
derivative orders: 7
ParameterTypeDescription
spot_orders_totalIntegerTotal count of subaccount's spot orders in given market and direction
derivative_orders_totalIntegerTotal count of subaccount's derivative orders in given market and direction

StreamSubaccountBalance

Stream the subaccount's balance for all denoms.

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio
from typing import Any, Dict

from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def balance_event_processor(event: Dict[str, Any]):
    print(event)


def stream_error_processor(exception: RpcError):
    print(f"There was an error listening to balance updates ({exception})")


def stream_closed_processor():
    print("The balance updates stream has been closed")


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    subaccount_id = "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001"
    denoms = ["inj", "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"]
    task = asyncio.get_event_loop().create_task(
        client.listen_subaccount_balance_updates(
            subaccount_id=subaccount_id,
            callback=balance_event_processor,
            on_end_callback=stream_closed_processor,
            on_status_callback=stream_error_processor,
            denoms=denoms,
        )
    )

    await asyncio.sleep(delay=60)
    task.cancel()


if __name__ == "__main__":
    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", "k8s")
    network := common.LoadNetwork("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    subaccountId := "0x1b99514e320ae0087be7f87b1e3057853c43b799000000000000000000000000"
    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))
        }
    }
}
ParameterTypeDescriptionRequired
subaccount_idStringID of the subaccount to get the balances fromYes
denomsString ArrayFilter balances by denoms. If not set, the balances of all the denoms for the subaccount are providedNo

Response Parameters

Streaming Response Example:

{
  "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
}
{
 "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
}
ParameterTypeDescription
balanceSubaccountBalanceSubaccount balance
timestampIntegerOperation timestamp in Unix milliseconds


SubaccountBalance

ParameterTypeDescription
subaccount_idStringSubaccount ID
account_addressStringInjective address of the account the subaccount belongs to
denomStringToken denom
depositSubaccountDepositDeposit details


SubaccountDeposit

ParameterTypeDescription
total_balanceStringTotal balance
available_balanceStringAvailable balance

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

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.fetch_order_states(
        spot_order_hashes=spot_order_hashes, derivative_order_hashes=derivative_order_hashes
    )
    print(orders)


if __name__ == "__main__":
    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("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    spotOrderHashes := []string{"0x0b156df549747187210ca5381f0291f179d76d613d0bae1a3c4fd2e3c0504b7c"}
    derivativeOrderHashes := []string{"0x82113f3998999bdc3892feaab2c4e53ba06c5fe887a2d5f9763397240f24da50"}

    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))
}
ParameterTypeDescriptionRequired
spot_order_hashesString ArrayArray with the order hashes you want to fetch in spot marketsNo
derivative_order_hashesString ArrayArray with the order hashes you want to fetch in derivative marketsNo

Response Parameters

Response Example:

{
  "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
    }
  ]
}
{
 "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
  }
 ]
}
ParameterTypeDescription
spot_order_statesOrderStateRecord ArrayList of the spot order state records
derivative_order_statesOrderStateRecord ArrayList of the derivative order state records


OrderStateRecord

ParameterTypeDescription
order_hashStringHash of the order
subaccount_idStringThe subaccountId that this order belongs to
market_idStringThe Market ID of the order
order_typeStringThe type of the order
order_sideStringThe side of the order
stateStringThe order state. Should be one of: booked, partial_filled, filled, canceled
quantity_filledStringThe filled quantity of the order
quantity_remainingStringThe unfilled quantity of the order
created_atIntegerOrder committed timestamp in UNIX milliseconds
updated_atIntegerOrder updated timestamp in UNIX milliseconds
priceStringOrder price
marginStringMargin for derivative order

Portfolio

Get an overview of your portfolio.

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio

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.fetch_portfolio(account_address=account_address)
    print(portfolio)


if __name__ == "__main__":
    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("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    accountAddress := "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku"
    res, err := exchangeClient.GetPortfolio(ctx, accountAddress)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
account_addressStringThe Injective addressYes

Response Parameters

Response Example:

{
   "portfolio":{
      "portfolioValue":"6229.040631548905238875",
      "availableBalance":"92.4500010811984646",
      "lockedBalance":"13218.3573583009093604",
      "unrealizedPnl":"-7081.766727833202586125",
      "subaccounts":[
         {
            "subaccountId":"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000002",
            "availableBalance":"0",
            "lockedBalance":"0",
            "unrealizedPnl":"0"
         },
         {
            "subaccountId":"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000006",
            "availableBalance":"0",
            "lockedBalance":"0",
            "unrealizedPnl":"0"
         },
         {
            "subaccountId":"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000008",
            "availableBalance":"0",
            "lockedBalance":"0",
            "unrealizedPnl":"0"
         },
         {
            "subaccountId":"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000009",
            "availableBalance":"0",
            "lockedBalance":"0",
            "unrealizedPnl":"0"
         },
         {
            "subaccountId":"0xaf79152ac5df276d9a8e1e2e22822f971347490200000061746f6d2d75736474",
            "availableBalance":"0.00000066622556",
            "lockedBalance":"0",
            "unrealizedPnl":"0"
         },
         {
            "subaccountId":"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
            "availableBalance":"0.0000003382963046",
            "lockedBalance":"13218.3573583009093604",
            "unrealizedPnl":"-7081.766727833202586125"
         },
         {
            "subaccountId":"0xaf79152ac5df276d9a8e1e2e22822f971347490200000000696e6a2d75736474",
            "availableBalance":"0.0000000766766",
            "lockedBalance":"0",
            "unrealizedPnl":"0"
         },
         {
            "subaccountId":"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000001",
            "availableBalance":"92.45",
            "lockedBalance":"0",
            "unrealizedPnl":"0"
         },
         {
            "subaccountId":"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000003",
            "availableBalance":"0",
            "lockedBalance":"0",
            "unrealizedPnl":"0"
         },
         {
            "subaccountId":"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000007",
            "availableBalance":"0",
            "lockedBalance":"0",
            "unrealizedPnl":"0"
         },
         {
            "subaccountId":"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000004",
            "availableBalance":"0",
            "lockedBalance":"0",
            "unrealizedPnl":"0"
         },
         {
            "subaccountId":"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000005",
            "availableBalance":"0",
            "lockedBalance":"0",
            "unrealizedPnl":"0"
         }
      ]
   }
}
{
 "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"
   }
  ]
 }
}
ParameterTypeDescription
portfolioAccountPortfolioPortfolio details


AccountPortfolio

ParameterTypeDescription
portfolio_valueStringThe account's portfolio value in USD
available_balanceStringThe account's available balance value in USD
locked_balanceStringThe account's locked balance value in USD
unrealized_pnlStringThe account's total unrealized PnL value in USD
subaccountsSubaccountPortfolio ArrayList of all subaccounts' portfolio


SubaccountPortfolio

ParameterTypeDescription
subaccount_idStringThe subaccount ID
available_balanceStringThe subaccount's available balance value in USD
locked_balanceStringThe subaccount's locked balance value in USD
unrealized_pnlStringThe 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

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.fetch_rewards(account_address=account_address, epoch=epoch)
    print(rewards)


if __name__ == "__main__":
    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("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    accountAddress := "inj1rwv4zn3jptsqs7l8lpa3uvzhs57y8duemete9e"
    epoch := int64(1)

    req := accountPB.RewardsRequest{
        Epoch:          epoch,
        AccountAddress: accountAddress,
    }

    res, err := exchangeClient.GetRewards(ctx, &req)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
epochIntegerThe distribution epoch sequence number. -1 for latestNo
account_addressStringAccount address for the rewards distributionNo

Response Parameters

Response Example:

{
   "rewards":[
      {
         "accountAddress":"inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
         "rewards":[
            {
               "denom":"inj",
               "amount":"11169382212463849"
            }
         ],
         "distributedAt":"1672218001897"
      }
   ]
}
{
 "rewards": [
  {
   "account_address": "inj1rwv4zn3jptsqs7l8lpa3uvzhs57y8duemete9e",
   "rewards": [
    {
     "denom": "inj",
     "amount": "755104058929571177652"
    }
   ],
   "distributed_at": 1642582800716
  }
 ]
}
ParameterTypeDescription
rewardsReward ArrayThe trading rewards distributed


Reward

ParameterTypeDescription
account_addressStringAccount Injective address
rewardsCoin ArrayReward coins distributed
distributed_atIntegerRewards distribution timestamp in UNIX milliseconds


Coin

ParameterTypeDescription
denomStringToken denom
amountStringToken amount

- 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

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.fetch_spot_market(market_id=market_id)
    print(market)


if __name__ == "__main__":
    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", "k8s")
    network := common.LoadNetwork("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(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))
}
Parameter Type Description Required
market_id String MarketId of the market we want to fetch Yes

Response Parameters

Response Example:

{
   "market":{
      "marketId":"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
      "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":"1683119359318"
      },
      "quoteDenom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
      "quoteTokenMeta":{
         "name":"Testnet Tether USDT",
         "address":"0x0000000000000000000000000000000000000000",
         "symbol":"USDT",
         "logo":"https://static.alchemyapi.io/images/assets/825.png",
         "decimals":6,
         "updatedAt":"1683119359320"
      },
      "makerFeeRate":"-0.0001",
      "takerFeeRate":"0.001",
      "serviceProviderFee":"0.4",
      "minPriceTickSize":"0.000000000000001",
      "minQuantityTickSize":"1000000000000000",
      "minNotional": "1000000"
   }
}
{
 "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",
  "min_notional": "1000000"
 }
}
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
min_notional String Defines the minimum required notional for an order to be accepted

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

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.fetch_spot_markets(
        market_statuses=[market_status], base_denom=base_denom, quote_denom=quote_denom
    )
    print(market)


if __name__ == "__main__":
    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", "k8s")
    network := common.LoadNetwork("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(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))
}
Parameter Type Description Required
market_statuses String Array Filter by status of the market (Should be any of: ["active", "paused", "suspended", "demolished", "expired"]) No
base_denom String Filter by the Coin denomination of the base currency No
quote_denom String Filter by the Coin denomination of the quote currency No

Response Parameters

Response Example:

{
   "markets":[
      {
         "marketId":"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
         "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":"1683119359318"
         },
         "quoteDenom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
         "quoteTokenMeta":{
            "name":"Testnet Tether USDT",
            "address":"0x0000000000000000000000000000000000000000",
            "symbol":"USDT",
            "logo":"https://static.alchemyapi.io/images/assets/825.png",
            "decimals":6,
            "updatedAt":"1683119359320"
         },
         "makerFeeRate":"-0.0001",
         "takerFeeRate":"0.001",
         "serviceProviderFee":"0.4",
         "minPriceTickSize":"0.000000000000001",
         "minQuantityTickSize":"1000000000000000",
         "minNotional":"1000000"
      }
   ]
}
{
 "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",
   "min_notional": "1000000"
  }
 ]
}
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
min_notional String Defines the minimum required notional for an order to be accepted

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
from typing import Any, Dict

from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def market_event_processor(event: Dict[str, Any]):
    print(event)


def stream_error_processor(exception: RpcError):
    print(f"There was an error listening to spot markets updates ({exception})")


def stream_closed_processor():
    print("The spot markets updates stream has been closed")


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.mainnet()
    client = AsyncClient(network)

    task = asyncio.get_event_loop().create_task(
        client.listen_spot_markets_updates(
            callback=market_event_processor,
            on_end_callback=stream_closed_processor,
            on_status_callback=stream_error_processor,
        )
    )

    await asyncio.sleep(delay=60)
    task.cancel()


if __name__ == "__main__":
    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", "k8s")
    network := common.LoadNetwork("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketIds := []string{"0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0"}
    stream, err := exchangeClient.StreamSpotMarket(ctx, marketIds)
    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))
        }
    }
}
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":{
      "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",
      "minNotional":"0"
   },
   "operationType":"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",
  "min_notional": "0",
},
  "operation_type": "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
min_notional String Defines the minimum required notional for an order to be accepted

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

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    market_ids = ["0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"]
    subaccount_id = "0xbdaedec95d563fb05240d6e01821008454c24c36000000000000000000000000"
    skip = 10
    limit = 3
    order_types = ["buy_po"]
    pagination = PaginationOption(skip=skip, limit=limit)
    orders = await client.fetch_spot_orders_history(
        subaccount_id=subaccount_id,
        market_ids=market_ids,
        order_types=order_types,
        pagination=pagination,
    )
    print(orders)


if __name__ == "__main__":
    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("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketId := "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
    subaccountId := "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
    skip := uint64(0)
    limit := int32(10)
    orderTypes := []string{"buy_po"}

    req := spotExchangePB.OrdersHistoryRequest{
        SubaccountId: subaccountId,
        MarketId:     marketId,
        Skip:         skip,
        Limit:        limit,
        OrderTypes:   orderTypes,
    }

    res, err := exchangeClient.GetHistoricalSpotOrders(ctx, &req)
    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
Parameter Type Description Required
subaccount_id String Filter by subaccount ID No
market_ids String Array Filter by multiple market IDs 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
direction String Filter by order direction (Should be one of: ["buy", "sell"]) 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
trade_id String Filter by the trade's trade id No
active_markets_only Bool Return only orders for active markets No
cid String Filter by the custom client order id of the trade's order No
pagination PaginationOption Pagination configuration No

Response Parameters

Response Example:

{
   "orders":[
      {
         "orderHash":"0x4e6629ce45597a3dc3941c5382cc7bc542d52fbcc6b03c4fd604c94a9bec0cc1",
         "marketId":"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
         "subaccountId":"0xbdaedec95d563fb05240d6e01821008454c24c36000000000000000000000000",
         "executionType":"limit",
         "orderType":"buy_po",
         "price":"0.000000000000001",
         "triggerPrice":"0",
         "quantity":"1000000000000000",
         "filledQuantity":"1000000000000000",
         "state":"filled",
         "createdAt":"1668264339149",
         "updatedAt":"1682667017745",
         "direction":"buy",
         "txHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
         "isActive":false,
         "cid":""
      },
      {
         "orderHash":"0x347de654c8484fe36473c3569382ff27d25e95c660fd055163b7193607867a8b",
         "marketId":"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
         "subaccountId":"0xbdaedec95d563fb05240d6e01821008454c24c36000000000000000000000000",
         "executionType":"limit",
         "orderType":"buy_po",
         "price":"0.000000000000001",
         "triggerPrice":"0",
         "quantity":"1000000000000000",
         "filledQuantity":"1000000000000000",
         "state":"filled",
         "createdAt":"1668264339149",
         "updatedAt":"1682667017745",
         "direction":"buy",
         "txHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
         "isActive":false,
         "cid":""
      },
      {
         "orderHash":"0x2141d52714f5c9328170cc674de8ecf876463b1999bea4124d1de595152b718f",
         "marketId":"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
         "subaccountId":"0xbdaedec95d563fb05240d6e01821008454c24c36000000000000000000000000",
         "executionType":"limit",
         "orderType":"buy_po",
         "price":"0.000000000000001",
         "triggerPrice":"0",
         "quantity":"1000000000000000",
         "filledQuantity":"1000000000000000",
         "state":"filled",
         "createdAt":"1668264339149",
         "updatedAt":"1682667017745",
         "direction":"buy",
         "txHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
         "isActive":false,
         "cid":""
      }
   ],
   "paging":{
      "total":"1000",
      "from":0,
      "to":0,
      "countBySubaccount":"0",
      "next":[

      ]
   }
}
{
 "orders": [
  {
   "order_hash": "0x47a3858df766691a6124255a959ac17c79588fa36e52bed6d8aea2d927bb6a60",
   "market_id": "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
   "subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
   "execution_type": "limit",
   "order_type": "buy_po",
   "price": "0.000000000007789",
   "trigger_price": "0",
   "quantity": "12000000000000000000",
   "filled_quantity": "12000000000000000000",
   "state": "filled",
   "created_at": 1681812187591,
   "updated_at": 1681886620984,
   "direction": "buy"
  },
  {
   "order_hash": "0x4a0f7bec21c2861ec390510f461ab94a6e4425453e113ba41d67c5e79a45538b",
   "market_id": "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
   "subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
   "execution_type": "limit",
   "order_type": "buy_po",
   "price": "0.000000000007692",
   "trigger_price": "0",
   "quantity": "14000000000000000000",
   "filled_quantity": "14000000000000000000",
   "state": "filled",
   "created_at": 1681812187591,
   "updated_at": 1681886620984,
   "direction": "buy"
  },
  {
   "order_hash": "0x447b593a3c1683b64bd6ac4e60aa6ff22078951312eb3bfacf0b8b163eb015e4",
   "market_id": "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
   "subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
   "execution_type": "limit",
   "order_type": "buy_po",
   "price": "0.000000000005787",
   "trigger_price": "0",
   "quantity": "18000000000000000000",
   "filled_quantity": "18000000000000000000",
   "state": "filled",
   "created_at": 1681812187591,
   "updated_at": 1681886620984,
   "direction": "buy"
  },
  {
   "order_hash": "0x77d1c86d0b04b3347ace0f4a7f708adbb160d54701891d0c212a8c28bb10f77f",
   "market_id": "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
   "subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
   "execution_type": "limit",
   "order_type": "buy_po",
   "price": "0.000000000005457",
   "trigger_price": "0",
   "quantity": "8000000000000000000",
   "filled_quantity": "8000000000000000000",
   "state": "filled",
   "created_at": 1681812187591,
   "updated_at": 1681886620984,
   "direction": "buy"
  },
  {
   "order_hash": "0x76899c13fa3e591b1e2cbadfc2c84db5a7f4f97e42cee2451a6a90d04b100642",
   "market_id": "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
   "subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
   "execution_type": "limit",
   "order_type": "buy_po",
   "price": "0.000000000007134",
   "trigger_price": "0",
   "quantity": "4000000000000000000",
   "filled_quantity": "4000000000000000000",
   "state": "filled",
   "created_at": 1681812187591,
   "updated_at": 1681886620984,
   "direction": "buy"
  },
  {
   "order_hash": "0xf353711353a98ac3aceee62a4d7fed30e0c65cf38adfa898c455be5e5c671445",
   "market_id": "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
   "subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
   "execution_type": "limit",
   "order_type": "buy_po",
   "price": "0.000000000006138",
   "trigger_price": "0",
   "quantity": "2000000000000000000",
   "filled_quantity": "2000000000000000000",
   "state": "filled",
   "created_at": 1681812187591,
   "updated_at": 1681886620984,
   "direction": "buy"
  },
  {
   "order_hash": "0xb599db2124630b350e0ca2ea3453ece84e7721334e1009b451fa21d072a6cf8f",
   "market_id": "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
   "subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
   "execution_type": "limit",
   "order_type": "buy_po",
   "price": "0.000000000005667",
   "trigger_price": "0",
   "quantity": "22000000000000000000",
   "filled_quantity": "22000000000000000000",
   "state": "filled",
   "created_at": 1681812187591,
   "updated_at": 1681886620984,
   "direction": "buy"
  },
  {
   "order_hash": "0x1c28300cfebfef73c26e32d396162e45089e34a5ba0c627cc8b6e3fb1d9861ad",
   "market_id": "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
   "subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
   "execution_type": "limit",
   "order_type": "buy_po",
   "price": "0.000000000006263",
   "trigger_price": "0",
   "quantity": "20000000000000000000",
   "filled_quantity": "20000000000000000000",
   "state": "filled",
   "created_at": 1681812187591,
   "updated_at": 1681886620984,
   "direction": "buy"
  },
  {
   "order_hash": "0x7a2b9753c94c67f5e79e2f9dcd8af8a619d55d2f9ba1a134a22c5ef154b76e7f",
   "market_id": "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
   "subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
   "execution_type": "limit",
   "order_type": "buy_po",
   "price": "0.000000000007683",
   "trigger_price": "0",
   "quantity": "16000000000000000000",
   "filled_quantity": "16000000000000000000",
   "state": "filled",
   "created_at": 1681812187591,
   "updated_at": 1681886620984,
   "direction": "buy"
  },
  {
   "order_hash": "0x4984a08abefd29ba6bc914b11182251e18c0235842916955a4ffdc8ff149d188",
   "market_id": "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
   "subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
   "execution_type": "limit",
   "order_type": "buy_po",
   "price": "0.000000000007668",
   "trigger_price": "0",
   "quantity": "6000000000000000000",
   "filled_quantity": "6000000000000000000",
   "state": "filled",
   "created_at": 1681812187591,
   "updated_at": 1681886620984,
   "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
market_id String ID of the spot market
is_active Boolean Indicates if the order is active
subaccount_id String ID of the subaccount that the order belongs to
execution_type String The type of the order (Should be one of: ["limit", "market"])
order_type String Order type (Should be one of: ["buy", "sell", "stop_buy", "stop_sell", "take_buy", "take_sell", "buy_po", "sell_po"])
price String Price of the order
trigger_price String Trigger price used by stop/take orders
quantity String Quantity of the order
filled_quantity String The amount of the quantity filled
state String Order state (Should be one of: ["booked", "partial_filled", "filled", "canceled"])
created_at Integer Order created timestamp in UNIX millis
updated_at Integer Order updated timestamp in UNIX millis
direction String The direction of the order (Should be one of: ["buy", "sell"])
tx_hash String Transaction hash in which the order was created (not all orders have this value)
cid String Identifier for the order specified by the user (up to 36 characters, like a UUID)

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
from typing import Any, Dict

from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def order_event_processor(event: Dict[str, Any]):
    print(event)


def stream_error_processor(exception: RpcError):
    print(f"There was an error listening to spot orders history updates ({exception})")


def stream_closed_processor():
    print("The spot orders history updates stream has been closed")


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
    order_direction = "buy"

    task = asyncio.get_event_loop().create_task(
        client.listen_spot_orders_history_updates(
            callback=order_event_processor,
            on_end_callback=stream_closed_processor,
            on_status_callback=stream_error_processor,
            market_id=market_id,
            direction=order_direction,
        )
    )

    await asyncio.sleep(delay=60)
    task.cancel()


if __name__ == "__main__":
    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("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketId := "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
    subaccountId := "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000"
    direction := "buy"

    req := spotExchangePB.StreamOrdersHistoryRequest{
        MarketId:     marketId,
        SubaccountId: subaccountId,
        Direction:    direction,
    }
    stream, err := exchangeClient.StreamHistoricalSpotOrders(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))
        }
    }
}
Parameter Type Description Required
market_id String Filter by market ID No
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
callback Function Function receiving one parameter (a stream event JSON dictionary) to process each new event Yes
on_end_callback Function Function with the logic to execute when the stream connection is interrupted No
on_status_callback Function Function receiving one parameter (the exception) with the logic to execute when an exception happens No

Response Parameters

Streaming Response Example:

{
   "order":{
      "orderHash":"0xff6a1ce6339911bb6f0765e17e70144ae62834e65e551e910018203d62bc6d12",
      "marketId":"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
      "subaccountId":"0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000004",
      "executionType":"limit",
      "orderType":"buy_po",
      "price":"0.000000000019028",
      "triggerPrice":"0",
      "quantity":"67129093000000000000000",
      "filledQuantity":"0",
      "state":"canceled",
      "createdAt":"1702044186286",
      "updatedAt":"1702044188683",
      "direction":"buy",
      "txHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
      "isActive":false,
      "cid":""
   },
   "operationType":"update",
   "timestamp":"1702044191000"
}
{
 "order": {
  "order_hash": "0xf8a90ee4cfb4c938035b791d3b3561e8991803793b4b5590164b2ecbfa247f3d",
  "market_id": "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
  "subaccount_id": "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000004",
  "execution_type": "limit",
  "order_type": "buy_po",
  "price": "0.000000000007438",
  "trigger_price": "0",
  "quantity": "76848283000000000000000",
  "filled_quantity": "0",
  "state": "canceled",
  "created_at": 1696621893030,
  "updated_at": 1696621895445,
  "direction": "buy"
 },
 "operation_type": "update",
 "timestamp": 1696621898000
}{
 "order": {
  "order_hash": "0xfd6bf489944cb181ee94057b80ffdfc113a17d48d0455c8d10e4deadf341bdfd",
  "market_id": "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
  "subaccount_id": "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000004",
  "execution_type": "limit",
  "order_type": "buy_po",
  "price": "0.000000000007478",
  "trigger_price": "0",
  "quantity": "76437220000000000000000",
  "filled_quantity": "0",
  "state": "canceled",
  "created_at": 1696621893030,
  "updated_at": 1696621895445,
  "direction": "buy"
 },
 "operation_type": "update",
 "timestamp": 1696621898000
}
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
market_id String ID of the spot market
is_active Boolean Indicates if the order is active
subaccount_id String ID of the subaccount that the order belongs to
execution_type String The type of the order (Should be one of: ["limit", "market"])
order_type String Order type (Should be one of: ["buy", "sell", "stop_buy", "stop_sell", "take_buy", "take_sell", "buy_po", "sell_po"])
price String Price of the order
trigger_price String Trigger price used by stop/take orders
quantity String Quantity of the order
filled_quantity String The amount of the quantity filled
state String Order state (Should be one of: ["booked", "partial_filled", "filled", "canceled"])
created_at Integer Order created timestamp in UNIX millis
updated_at Integer Order updated timestamp in UNIX millis
direction String The direction of the order (Should be one of: ["buy", "sell"])
tx_hash String Transaction hash in which the order was created (not all orders have this value)
cid String Identifier for the order specified by the user (up to 36 characters, like a UUID)

TradesV2

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

  1. "market" for market orders
  2. "limitFill" for a resting limit order getting filled by a market order
  3. "limitMatchRestingOrder" for a resting limit order getting matched with another new limit order
  4. "limitMatchNewOrder" for a new limit order getting matched immediately

Request Parameters

Request Example:

import asyncio

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_ids = ["0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001"]
    execution_types = ["limitMatchNewOrder", "market"]
    orders = await client.fetch_spot_trades(
        market_ids=market_ids,
        subaccount_ids=subaccount_ids,
        execution_side=execution_side,
        direction=direction,
        execution_types=execution_types,
    )
    print(orders)


if __name__ == "__main__":
    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("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketId := "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0"
    subaccountId := "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"

    req := spotExchangePB.TradesV2Request{
        MarketId:     marketId,
        SubaccountId: subaccountId,
    }

    res, err := exchangeClient.GetSpotTradesV2(ctx, &req)
    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
Parameter Type Description Required
market_ids String Array Filter by multiple market IDs No
subaccount_ids String Array Filter by multiple subaccount IDs No
execution_side String Filter by the execution side of the trade (Should be one of: ["maker", "taker"]) No
direction String Filter by the direction of the trade (Should be one of: ["buy", "sell"]) No
execution_types String Array Filter by the *trade execution type (Should be one of: ["market", "limitFill", "limitMatchRestingOrder", "limitMatchNewOrder"]) No
trade_id String Filter by the trade id of the trade No
account_address String Filter by the account address No
cid String Filter by the custom client order id of the trade's order No
pagination PaginationOption Pagination configuration No

Response Parameters

Response Example:

{
   "trades":[
      {
         "orderHash":"0x952bb14a7a377697d724c60d6077ef3dfe894c98f854970fab187247be832b6f",
         "subaccountId":"0x101411266c6e2b610b4a0324d2bfb2ef0ca6e1dd000000000000000000000000",
         "marketId":"0x01edfab47f124748dc89998eb33144af734484ba07099014594321729a0ca16b",
         "tradeExecutionType":"limitMatchRestingOrder",
         "tradeDirection":"buy",
         "price":{
            "price":"0.00000000001",
            "quantity":"1000000000000000000",
            "timestamp":"1701961116630"
         },
         "fee":"-600",
         "executedAt":"1701961116630",
         "feeRecipient":"inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
         "tradeId":"1321_0",
         "executionSide":"maker",
         "cid":"96866b8b-02dd-4288-97d3-e5254e4888b3"
      },
      {
         "orderHash":"0x85a824c31f59cf68235b48666c4821334813f2b80db937f02d192f1e3fc74368",
         "subaccountId":"0x3db1f84431dfe4df617f9eb2d04edf432beb9826000000000000000000000000",
         "marketId":"0x01edfab47f124748dc89998eb33144af734484ba07099014594321729a0ca16b",
         "tradeExecutionType":"limitMatchNewOrder",
         "tradeDirection":"sell",
         "price":{
            "price":"0.00000000001",
            "quantity":"1000000000000000000",
            "timestamp":"1701961116630"
         },
         "fee":"10000",
         "executedAt":"1701961116630",
         "feeRecipient":"inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
         "tradeId":"1321_1",
         "executionSide":"taker",
         "cid":"spot_AAVE/USDT"
      },
      {
         "orderHash":"0xffabb2d12a745d79eb12c7ef0eb59c729aaa4387a141f858153c8b8f58168b2e",
         "subaccountId":"0x101411266c6e2b610b4a0324d2bfb2ef0ca6e1dd000000000000000000000000",
         "marketId":"0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
         "tradeExecutionType":"limitMatchRestingOrder",
         "tradeDirection":"buy",
         "price":{
            "price":"0.00000000001",
            "quantity":"2000000000000000000",
            "timestamp":"1701960607140"
         },
         "fee":"-2400",
         "executedAt":"1701960607140",
         "feeRecipient":"inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
         "tradeId":"646_0",
         "executionSide":"maker",
         "cid":"ec581735-f801-4bf3-9101-282b301bf5cd"
      },
      {
         "orderHash":"0xa19e24eef9877ec4980b8d259c1d21fa1dafcd50691e6f853e84af74fb23c05c",
         "subaccountId":"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
         "marketId":"0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
         "tradeExecutionType":"limitMatchNewOrder",
         "tradeDirection":"sell",
         "price":{
            "price":"0.00000000001",
            "quantity":"2000000000000000000",
            "timestamp":"1701960607140"
         },
         "fee":"40000",
         "executedAt":"1701960607140",
         "feeRecipient":"inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8",
         "tradeId":"646_1",
         "executionSide":"taker",
         "cid":""
      },
      {
         "orderHash":"0xffabb2d12a745d79eb12c7ef0eb59c729aaa4387a141f858153c8b8f58168b2e",
         "subaccountId":"0x101411266c6e2b610b4a0324d2bfb2ef0ca6e1dd000000000000000000000000",
         "marketId":"0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
         "tradeExecutionType":"limitMatchRestingOrder",
         "tradeDirection":"buy",
         "price":{
            "price":"0.00000000001",
            "quantity":"8000000000000000000",
            "timestamp":"1701960594997"
         },
         "fee":"-9600",
         "executedAt":"1701960594997",
         "feeRecipient":"inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
         "tradeId":"630_0",
         "executionSide":"maker",
         "cid":"ec581735-f801-4bf3-9101-282b301bf5cd"
      },
      {
         "orderHash":"0x87b786072190a2f38e9057987be7bdcb4e2274a6c16fdb9670e5c2ded765140f",
         "subaccountId":"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
         "marketId":"0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
         "tradeExecutionType":"limitMatchNewOrder",
         "tradeDirection":"sell",
         "price":{
            "price":"0.00000000001",
            "quantity":"8000000000000000000",
            "timestamp":"1701960594997"
         },
         "fee":"160000",
         "executedAt":"1701960594997",
         "feeRecipient":"inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8",
         "tradeId":"630_1",
         "executionSide":"taker",
         "cid":""
      }
   ],
   "paging":{
      "total":"6",
      "from":1,
      "to":6,
      "countBySubaccount":"0",
      "next":[

      ]
   }
}

{
 "trades": [
  {
   "order_hash": "0xffabb2d12a745d79eb12c7ef0eb59c729aaa4387a141f858153c8b8f58168b2e",
   "subaccount_id": "0x101411266c6e2b610b4a0324d2bfb2ef0ca6e1dd000000000000000000000000",
   "market_id": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
   "trade_execution_type": "limitMatchRestingOrder",
   "trade_direction": "buy",
   "price": {
    "price": "0.00000000001",
    "quantity": "2000000000000000000",
    "timestamp": 1701960607140
   },
   "fee": "-2400",
   "executed_at": 1701960607140,
   "fee_recipient": "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
   "trade_id": "646_0",
   "execution_side": "maker",
   "cid": "ec581735-f801-4bf3-9101-282b301bf5cd"
  },
  {
   "order_hash": "0xa19e24eef9877ec4980b8d259c1d21fa1dafcd50691e6f853e84af74fb23c05c",
   "subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
   "market_id": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
   "trade_execution_type": "limitMatchNewOrder",
   "trade_direction": "sell",
   "price": {
    "price": "0.00000000001",
    "quantity": "2000000000000000000",
    "timestamp": 1701960607140
   },
   "fee": "40000",
   "executed_at": 1701960607140,
   "fee_recipient": "inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8",
   "trade_id": "646_1",
   "execution_side": "taker"
  },
  {
   "order_hash": "0xffabb2d12a745d79eb12c7ef0eb59c729aaa4387a141f858153c8b8f58168b2e",
   "subaccount_id": "0x101411266c6e2b610b4a0324d2bfb2ef0ca6e1dd000000000000000000000000",
   "market_id": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
   "trade_execution_type": "limitMatchRestingOrder",
   "trade_direction": "buy",
   "price": {
    "price": "0.00000000001",
    "quantity": "8000000000000000000",
    "timestamp": 1701960594997
   },
   "fee": "-9600",
   "executed_at": 1701960594997,
   "fee_recipient": "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
   "trade_id": "630_0",
   "execution_side": "maker",
   "cid": "ec581735-f801-4bf3-9101-282b301bf5cd"
  },
  {
   "order_hash": "0x87b786072190a2f38e9057987be7bdcb4e2274a6c16fdb9670e5c2ded765140f",
   "subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
   "market_id": "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
   "trade_execution_type": "limitMatchNewOrder",
   "trade_direction": "sell",
   "price": {
    "price": "0.00000000001",
    "quantity": "8000000000000000000",
    "timestamp": 1701960594997
   },
   "fee": "160000",
   "executed_at": 1701960594997,
   "fee_recipient": "inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8",
   "trade_id": "630_1",
   "execution_side": "taker"
  }
 ],
 "paging": {
  "total": 4,
  "from": 1,
  "to": 4
 }
}

Parameter Type Description
trades SpotTrade Array Trades of a particular spot market
paging Paging Pagination of results

SpotTrade

Parameter Type Description
order_hash String The order hash
subaccount_id String The subaccountId that executed the trade
market_id String The ID of the market that this trade is in
trade_execution_type String Execution type of the trade (Should be one of: ["market", "limitFill", "limitMatchRestingOrder", "limitMatchNewOrder"])
trade_direction String Direction of the trade(Should be one of: ["buy", "sell"])
price PriceLevel Price level at which trade has been executed
fee String The fee associated with the trade (quote asset denom)
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"])
cid String Identifier for the order specified by the user (up to 36 characters, like a UUID)

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

StreamTradesV2

Stream newly executed trades of spot markets. The default request streams trades from all spot markets.

IP rate limit group: indexer

*Trade execution types

  1. "market" for market orders
  2. "limitFill" for a resting limit order getting filled by a market order
  3. "limitMatchRestingOrder" for a resting limit order getting matched with another new limit order
  4. "limitMatchNewOrder" for a new limit order getting matched immediately

Request Parameters

Request Example:

import asyncio
from typing import Any, Dict

from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def trade_event_processor(event: Dict[str, Any]):
    print(event)


def stream_error_processor(exception: RpcError):
    print(f"There was an error listening to spot trades updates ({exception})")


def stream_closed_processor():
    print("The spot trades updates stream has been closed")


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"]

    task = asyncio.get_event_loop().create_task(
        client.listen_spot_trades_updates(
            callback=trade_event_processor,
            on_end_callback=stream_closed_processor,
            on_status_callback=stream_error_processor,
            market_ids=market_ids,
            subaccount_ids=[subaccount_id],
            execution_side=execution_side,
            direction=direction,
            execution_types=execution_types,
        )
    )

    await asyncio.sleep(delay=60)
    task.cancel()


if __name__ == "__main__":
    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("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketId := "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0"
    subaccountId := "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000"

    req := spotExchangePB.StreamTradesV2Request{
        MarketId:     marketId,
        SubaccountId: subaccountId,
    }
    stream, err := exchangeClient.StreamSpotTradesV2(ctx, &req)
    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))
        }
    }
}
Parameter Type Description Required
market_ids String Array Filter by multiple market IDs No
subaccount_ids String Array Filter by multiple subaccount IDs No
execution_side String Filter by the execution side of the trade (Should be one of: ["maker", "taker"]) No
direction String Filter by the direction of the trade (Should be one of: ["buy", "sell"]) No
execution_types String Array Filter by the *trade execution type (Should be one of: ["market", "limitFill", "limitMatchRestingOrder", "limitMatchNewOrder"]) No
trade_id String Filter by the trade's trade id No
account_address String Filter by the account address No
cid String Filter by the custom client order id of the trade's order No
pagination PaginationOption Pagination configuration No
callback Function Function receiving one parameter (a stream event JSON dictionary) to process each new event Yes
on_end_callback Function Function with the logic to execute when the stream connection is interrupted No
on_status_callback Function Function receiving one parameter (the exception) with the logic to execute when an exception happens No

Response Parameters

Streaming Response Example:

{
   "trade":{
      "orderHash":"0xa7f4a7d85136d97108d271caadd93bf697ff965790e0e1558617b953cced4adc",
      "subaccountId":"0x3db1f84431dfe4df617f9eb2d04edf432beb9826000000000000000000000000",
      "marketId":"0x01edfab47f124748dc89998eb33144af734484ba07099014594321729a0ca16b",
      "tradeExecutionType":"limitMatchNewOrder",
      "tradeDirection":"sell",
      "price":{
         "price":"0.00000000001",
         "quantity":"1000000000000000000",
         "timestamp":"1701978102242"
      },
      "fee":"10000",
      "executedAt":"1701978102242",
      "feeRecipient":"inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
      "tradeId":"22868_1",
      "executionSide":"taker",
      "cid":"96866b8b-02dd-4288-97d3-e5254e4999d4"
   },
   "operationType":"insert",
   "timestamp":"1701978103000"
}
{
   "trade":{
      "orderHash":"0x952bb14a7a377697d724c60d6077ef3dfe894c98f854970fab187247be832b6f",
      "subaccountId":"0x101411266c6e2b610b4a0324d2bfb2ef0ca6e1dd000000000000000000000000",
      "marketId":"0x01edfab47f124748dc89998eb33144af734484ba07099014594321729a0ca16b",
      "tradeExecutionType":"limitMatchRestingOrder",
      "tradeDirection":"buy",
      "price":{
         "price":"0.00000000001",
         "quantity":"1000000000000000000",
         "timestamp":"1701978102242"
      },
      "fee":"-600",
      "executedAt":"1701978102242",
      "feeRecipient":"inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
      "tradeId":"22868_0",
      "executionSide":"maker",
      "cid":"96866b8b-02dd-4288-97d3-e5254e4888b3"
   },
   "operationType":"insert",
   "timestamp":"1701978103000"
}
{
 "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
}
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
order_hash String The order hash
subaccount_id String The subaccountId that executed the trade
market_id String The ID of the market that this trade is in
trade_execution_type String Execution type of the trade (Should be one of: ["market", "limitFill", "limitMatchRestingOrder", "limitMatchNewOrder"])
trade_direction String Direction of the trade(Should be one of: ["buy", "sell"])
price PriceLevel Price level at which trade has been executed
fee String The fee associated with the trade (quote asset denom)
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"])
cid String Identifier for the order specified by the user (up to 36 characters, like a UUID)

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

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.fetch_spot_orderbooks_v2(market_ids=market_ids)
    print(orderbooks)


if __name__ == "__main__":
    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", "k8s")
    network := common.LoadNetwork("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketIds := []string{"0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0"}
    res, err := exchangeClient.GetSpotOrderbooksV2(ctx, marketIds)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
Parameter Type Description Required
market_ids String Array List of IDs of markets to get orderbook snapshots from Yes

Response Parameters

Response Example:

{
   "orderbooks":[
      {
         "marketId":"0x7a57e705bb4e09c88aecfc295569481dbf2fe1d5efe364651fbe72385938e9b0",
         "orderbook":{
            "sells":[
               {
                  "price":"0.000000000005",
                  "quantity":"27767884000000000000000",
                  "timestamp":"1694702425539"
               },
               {
                  "price":"0.0000000000045",
                  "quantity":"3519999000000000000000000",
                  "timestamp":"1694424758707"
               }
            ],
            "timestamp":"-62135596800000",
            "buys":[

            ],
            "sequence":"0"
         }
      },
      {
         "marketId":"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
         "orderbook":{
            "buys":[
               {
                  "price":"0.000000000073489",
                  "quantity":"129000000000000000",
                  "timestamp":"1702042963690"
               },
               {
                  "price":"0.000000000064261",
                  "quantity":"1292000000000000000",
                  "timestamp":"1702039612697"
               }
            ],
            "sells":[
               {
                  "price":"0.000000000085",
                  "quantity":"6693248000000000000000",
                  "timestamp":"1702044317059"
               },
               {
                  "price":"0.000000000085768",
                  "quantity":"581000000000000000",
                  "timestamp":"1701944786578"
               }
            ],
            "sequence":"6916386",
            "timestamp":"1702044336800"
         }
      }
   ]
}

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
from typing import Any, Dict

from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def orderbook_event_processor(event: Dict[str, Any]):
    print(event)


def stream_error_processor(exception: RpcError):
    print(f"There was an error listening to spot orderbook snapshots ({exception})")


def stream_closed_processor():
    print("The spot orderbook snapshots stream has been closed")


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    market_ids = [
        "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
        "0x7a57e705bb4e09c88aecfc295569481dbf2fe1d5efe364651fbe72385938e9b0",
    ]

    task = asyncio.get_event_loop().create_task(
        client.listen_spot_orderbook_snapshots(
            market_ids=market_ids,
            callback=orderbook_event_processor,
            on_end_callback=stream_closed_processor,
            on_status_callback=stream_error_processor,
        )
    )

    await asyncio.sleep(delay=60)
    task.cancel()


if __name__ == "__main__":
    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"
)

func main() {
    network := common.LoadNetwork("devnet-1", "")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketIds := []string{"0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0"}
    stream, err := exchangeClient.StreamSpotOrderbookV2(ctx, marketIds)
    if err != nil {
        panic(err)
    }

    for {
        select {
        case <-ctx.Done():
            return
        default:
            res, err := stream.Recv()
            if err != nil {
                fmt.Println(err)
                return
            }
            fmt.Println(res.MarketId, res.Orderbook, len(res.Orderbook.Sells), len(res.Orderbook.Buys))
        }
    }
}
Parameter Type Description Required
market_ids String Array List of market IDs for orderbook streaming; empty means all spot markets Yes
callback Function Function receiving one parameter (a stream event JSON dictionary) to process each new event Yes
on_end_callback Function Function with the logic to execute when the stream connection is interrupted No
on_status_callback Function Function receiving one parameter (the exception) with the logic to execute when an exception happens No

Response Parameters

Streaming Response Example:

{
   "orderbook":{
      "buys":[
         {
            "price":"0.000000000073489",
            "quantity":"129000000000000000",
            "timestamp":"1702042963690"
         },
         {
            "price":"0.000000000064261",
            "quantity":"1292000000000000000",
            "timestamp":"1702039612697"
         }
      ],
      "sells":[
         {
            "price":"0.000000000085",
            "quantity":"6681507000000000000000",
            "timestamp":"1702044411262"
         },
         {
            "price":"0.000000000085768",
            "quantity":"581000000000000000",
            "timestamp":"1701944786578"
         }
      ],
      "sequence":"6916434",
      "timestamp":"1702044439698"
   },
   "operationType":"update",
   "timestamp":"1702044441000",
   "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
from decimal import Decimal
from typing import Any, Dict

from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


def stream_error_processor(exception: RpcError):
    print(f"There was an error listening to spot orderbook updates ({exception})")


def stream_closed_processor():
    print("The spot orderbook updates stream has been closed")


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.fetch_spot_orderbooks_v2(market_ids=[orderbook.market_id])
    for snapshot in res["orderbooks"]:
        if snapshot["marketId"] != 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=int(buy["timestamp"]),
            )
        for sell in snapshot["orderbook"]["sells"]:
            orderbook.levels["sells"][sell["price"]] = PriceLevel(
                price=Decimal(sell["price"]),
                quantity=Decimal(sell["quantity"]),
                timestamp=int(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)
    updates_queue = asyncio.Queue()
    tasks = []

    async def queue_event(event: Dict[str, Any]):
        await updates_queue.put(event)

    # start getting price levels updates
    task = asyncio.get_event_loop().create_task(
        async_client.listen_spot_orderbook_updates(
            market_ids=[market_id],
            callback=queue_event,
            on_end_callback=stream_closed_processor,
            on_status_callback=stream_error_processor,
        )
    )
    tasks.append(task)

    # 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)

    task = asyncio.get_event_loop().create_task(
        apply_orderbook_update(orderbook=orderbook, updates_queue=updates_queue)
    )
    tasks.append(task)

    await asyncio.sleep(delay=60)
    for task in tasks:
        task.cancel()


async def apply_orderbook_update(orderbook: Orderbook, updates_queue: asyncio.Queue):
    while True:
        updates = await updates_queue.get()
        update = updates["orderbookLevelUpdates"]

        # discard updates older than the snapshot
        if int(update["sequence"]) <= orderbook.sequence:
            return

        print(" * * * * * * * * * * * * * * * * * * *")

        # ensure we have not missed any update
        if int(update["sequence"]) > (orderbook.sequence + 1):
            raise Exception(
                "missing orderbook update events from stream, must restart: {} vs {}".format(
                    update["sequence"], (orderbook.sequence + 1)
                )
            )

        print("updating orderbook with updates at sequence {}".format(update["sequence"]))

        # update orderbook
        orderbook.sequence = int(update["sequence"])
        for direction, levels in {"buys": update["buys"], "sells": update["sells"]}.items():
            for level in levels:
                if level["isActive"]:
                    # 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__":
    asyncio.run(main())
package main

import (
    "context"
    "fmt"
    "io"
    "os"
    "sort"

    "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"
    "github.com/shopspring/decimal"
)

type MapOrderbook struct {
    Sequence uint64
    Levels   map[bool]map[string]*spotExchangePB.PriceLevel
}

func main() {
    network := common.LoadNetwork("devnet-1", "")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        fmt.Println(err)
        panic(err)
    }

    ctx := context.Background()
    marketIds := []string{"0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0"}
    stream, err := exchangeClient.StreamSpotOrderbookUpdate(ctx, marketIds)
    if err != nil {
        fmt.Println(err)
        panic(err)
    }

    updatesCh := make(chan *spotExchangePB.OrderbookLevelUpdates, 100000)
    receiving := make(chan struct{})
    var receivingClosed bool

    // stream orderbook price levels
    go func() {
        for {
            select {
            case <-ctx.Done():
                return
            default:
                res, err := stream.Recv()
                if err == io.EOF {
                    fmt.Println("change stream needs to be restarted")
                    os.Exit(0)
                }
                if err != nil {
                    panic(err) // rester on errors
                }
                u := res.OrderbookLevelUpdates
                if !receivingClosed {
                    fmt.Println("receiving updates from stream")
                    close(receiving)
                    receivingClosed = true
                }
                updatesCh <- u
            }
        }
    }()

    // ensure we are receiving updates before getting the orderbook snapshot,
    // we will skip past updates later.
    fmt.Println("waiting for streaming updates")
    <-receiving

    // prepare orderbooks map
    orderbooks := map[string]*MapOrderbook{}
    res, err := exchangeClient.GetSpotOrderbooksV2(ctx, marketIds)
    if err != nil {
        panic(err)
    }
    for _, ob := range res.Orderbooks {
        // init inner maps not ready
        _, ok := orderbooks[ob.MarketId]
        if !ok {
            orderbook := &MapOrderbook{
                Sequence: ob.Orderbook.Sequence,
                Levels:   map[bool]map[string]*spotExchangePB.PriceLevel{},
            }
            orderbook.Levels[true] = map[string]*spotExchangePB.PriceLevel{}
            orderbook.Levels[false] = map[string]*spotExchangePB.PriceLevel{}
            orderbooks[ob.MarketId] = orderbook
        }

        for _, level := range ob.Orderbook.Buys {
            orderbooks[ob.MarketId].Levels[true][level.Price] = level
        }
        for _, level := range ob.Orderbook.Sells {
            orderbooks[ob.MarketId].Levels[false][level.Price] = level
        }
    }

    // continuously consume level updates and maintain orderbook
    skippedPastEvents := false
    for {
        updates := <-updatesCh

        // validate orderbook
        orderbook, ok := orderbooks[updates.MarketId]
        if !ok {
            fmt.Println("updates channel closed, must restart")
            return // closed
        }

        // skip if update sequence <= orderbook sequence until it's ready to consume
        if !skippedPastEvents {
            if orderbook.Sequence >= updates.Sequence {
                continue
            }
            skippedPastEvents = true
        }

        // panic if update sequence > orderbook sequence + 1
        if updates.Sequence > orderbook.Sequence+1 {
            fmt.Printf("skipping levels: update sequence %d vs orderbook sequence %d\n", updates.Sequence, orderbook.Sequence)
            panic("missing orderbook update events from stream, must restart")
        }

        // update orderbook map
        orderbook.Sequence = updates.Sequence
        for isBuy, update := range map[bool][]*spotExchangePB.PriceLevelUpdate{
            true:  updates.Buys,
            false: updates.Sells,
        } {
            for _, level := range update {
                if level.IsActive {
                    // upsert
                    orderbook.Levels[isBuy][level.Price] = &spotExchangePB.PriceLevel{
                        Price:     level.Price,
                        Quantity:  level.Quantity,
                        Timestamp: level.Timestamp,
                    }
                } else {
                    // remove inactive level
                    delete(orderbook.Levels[isBuy], level.Price)
                }
            }
        }

        // construct orderbook arrays
        sells, buys := maintainOrderbook(orderbook.Levels)
        fmt.Println("after", orderbook.Sequence, len(sells), len(buys))

        if len(sells) > 0 && len(buys) > 0 {
            // assert orderbook
            topBuyPrice := decimal.RequireFromString(buys[0].Price)
            lowestSellPrice := decimal.RequireFromString(sells[0].Price)
            if topBuyPrice.GreaterThanOrEqual(lowestSellPrice) {
                panic(fmt.Errorf("crossed orderbook, must restart: buy %s >= %s sell", topBuyPrice, lowestSellPrice))
            }
        }

        res, _ = exchangeClient.GetSpotOrderbooksV2(ctx, marketIds)
        fmt.Println("query", res.Orderbooks[0].Orderbook.Sequence, len(res.Orderbooks[0].Orderbook.Sells), len(res.Orderbooks[0].Orderbook.Buys))

        // print orderbook
        fmt.Println(" [SELLS] ========")
        for _, s := range sells {
            fmt.Println(s)
        }
        fmt.Println(" [BUYS] ========")
        for _, b := range buys {
            fmt.Println(b)
        }
        fmt.Println("=======================================================")
    }
}

func maintainOrderbook(orderbook map[bool]map[string]*spotExchangePB.PriceLevel) (buys, sells []*spotExchangePB.PriceLevel) {
    for _, v := range orderbook[false] {
        sells = append(sells, v)
    }
    for _, v := range orderbook[true] {
        buys = append(buys, v)
    }

    sort.Slice(sells, func(i, j int) bool {
        return decimal.RequireFromString(sells[i].Price).LessThan(decimal.RequireFromString(sells[j].Price))
    })

    sort.Slice(buys, func(i, j int) bool {
        return decimal.RequireFromString(buys[i].Price).GreaterThan(decimal.RequireFromString(buys[j].Price))
    })

    return sells, buys
}
Parameter Type Description Required
market_ids String Array List of market IDs for orderbook streaming; empty means all spot markets Yes
callback Function Function receiving one parameter (a stream event JSON dictionary) to process each new event Yes
on_end_callback Function Function with the logic to execute when the stream connection is interrupted No
on_status_callback Function Function receiving one parameter (the exception) with the logic to execute when an exception happens No

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
====================================

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

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
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
    pagination = PaginationOption(skip=skip, limit=limit)
    orders = await client.fetch_spot_subaccount_orders_list(
        subaccount_id=subaccount_id, market_id=market_id, pagination=pagination
    )
    print(orders)


if __name__ == "__main__":
    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", "k8s")
    network := common.LoadNetwork("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketId := "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0"
    subaccountId := "0x0b46e339708ea4d87bd2fcc61614e109ac374bbe000000000000000000000000"
    skip := uint64(0)
    limit := int32(10)

    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))
}
Parameter Type Description Required
subaccount_id String Filter by subaccount ID Yes
market_id String Filter by market ID No
pagination PaginationOption Pagination configuration No

Response Parameters

Response Example:

{
   "orders":[
      {
         "orderHash":"0x3414f6f1a37a864166b19930680eb62a99798b5e406c2d14ed1ee66ab9958503",
         "orderSide":"buy",
         "marketId":"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
         "subaccountId":"0xbdaedec95d563fb05240d6e01821008454c24c36000000000000000000000000",
         "price":"0.000000000003",
         "quantity":"55000000000000000000",
         "unfilledQuantity":"55000000000000000000",
         "triggerPrice":"0",
         "feeRecipient":"inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
         "state":"booked",
         "createdAt":"1701808096494",
         "updatedAt":"1701808096494",
         "txHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
         "cid":"670c52ec-f68f-456c-8aeb-e271071a43ac"
      },
      {
         "orderHash":"0xb7b6d54d1e01e1eb0005e34e08a96b715b557eeee7c5f3a439636f98ddd66b91",
         "orderSide":"buy",
         "marketId":"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
         "subaccountId":"0xbdaedec95d563fb05240d6e01821008454c24c36000000000000000000000000",
         "price":"0.000000000003",
         "quantity":"55000000000000000000",
         "unfilledQuantity":"55000000000000000000",
         "triggerPrice":"0",
         "feeRecipient":"inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
         "state":"booked",
         "createdAt":"1701808058512",
         "updatedAt":"1701808058512",
         "txHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
         "cid":"bba97476-e7f4-4313-874b-7ef115daccb4"
      }
   ],
   "paging":{
      "total":"53",
      "from":1,
      "to":2,
      "countBySubaccount":"0",
      "next":[

      ]
   }
}
{
 "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
  }
 ]
}
Parameter Type Description
orders SpotLimitOrder Array List of spot market orders
paging Paging Pagination of results

SpotLimitOrder

Parameter Type Description
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"])
market_id String ID of the market the order belongs to
subaccount_id String The subaccount ID the order belongs to
price String The price of the order
quantity String The quantity of the order
unfilled_quantity String The amount of the quantity remaining unfilled
trigger_price String The price that triggers stop and take orders. If no price is set, the default is 0
fee_recipient String The address that receives fees if the order is executed
state String State of the order (Should be one of: ["booked", "partial_filled", "filled", "canceled"])
created_at Integer Order committed timestamp in UNIX millis
updated_at Integer Order updated timestamp in UNIX millis
tx_hash String Transaction hash in which the order was created (not all orders have this value)
cid String Identifier for the order specified by the user (up to 36 characters, like a UUID)

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

  1. "market" for market orders
  2. "limitFill" for a resting limit order getting filled by a market order
  3. "limitMatchRestingOrder" for a resting limit order getting matched with another new limit order
  4. "limitMatchNewOrder" for a new limit order getting matched immediately

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
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
    pagination = PaginationOption(skip=skip, limit=limit)
    trades = await client.fetch_spot_subaccount_trades_list(
        subaccount_id=subaccount_id,
        market_id=market_id,
        execution_type=execution_type,
        direction=direction,
        pagination=pagination,
    )
    print(trades)


if __name__ == "__main__":
    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", "k8s")
    network := common.LoadNetwork("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketId := "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0"
    subaccountId := "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000"
    skip := uint64(0)
    limit := int32(10)

    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))
}
Parameter Type Description Required
subaccount_id String Filter by subaccount ID Yes
market_id String Filter by market ID No
execution_type String Filter by the *execution type of the trades (Should be one of: ["market", "limitFill", "limitMatchRestingOrder", "limitMatchNewOrder"]) No
direction String Filter by the direction of the trades (Should be one of: ["buy", "sell"]) No
pagination PaginationOption Pagination configuration No

Response Parameters

Response Example:

{
   "trades":[
      {
         "orderHash":"0x6dfd01151a5b3cfb3a61777335f0d8d324a479b9006fd9642f52b402aec53d4f",
         "subaccountId":"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
         "marketId":"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
         "tradeExecutionType":"market",
         "tradeDirection":"buy",
         "price":{
            "price":"0.000000000015589",
            "quantity":"1000000000000000",
            "timestamp":"1700675201676"
         },
         "fee":"10.9123",
         "executedAt":"1700675201676",
         "feeRecipient":"inj1zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3t5qxqh",
         "tradeId":"18740619_240_0",
         "executionSide":"taker",
         "cid":""
      },
      {
         "orderHash":"0x6a6cd0afb038322b67a88cd827e2800483e3571c5e82663df37a33770fa0a8d1",
         "subaccountId":"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
         "marketId":"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
         "tradeExecutionType":"market",
         "tradeDirection":"buy",
         "price":{
            "price":"0.000000000015742",
            "quantity":"1000000000000000",
            "timestamp":"1700232025894"
         },
         "fee":"11.0194",
         "executedAt":"1700232025894",
         "feeRecipient":"inj1zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3t5qxqh",
         "tradeId":"18529043_240_0",
         "executionSide":"taker",
         "cid":""
      },
      {
         "orderHash":"0xa3049ebaa97ac3755c09bd53ea30e86b98aef40bf037cb9d91dedfc1fd4b7735",
         "subaccountId":"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
         "marketId":"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
         "tradeExecutionType":"limitMatchNewOrder",
         "tradeDirection":"buy",
         "price":{
            "price":"0.000000000015874",
            "quantity":"21000000000000000000",
            "timestamp":"1700221121919"
         },
         "fee":"233347.8",
         "executedAt":"1700221121919",
         "feeRecipient":"inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8",
         "tradeId":"18523837_243_0",
         "executionSide":"taker",
         "cid":""
      }
   ]
}
{
 "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"
  }
 ]
}

Parameter Type Description
trades SpotTrade Array List of spot market trades

SpotTrade

Parameter Type Description
order_hash String The order hash
subaccount_id String The subaccountId that executed the trade
market_id String The ID of the market that this trade is in
trade_execution_type String Execution type of the trade (Should be one of: ["market", "limitFill", "limitMatchRestingOrder", "limitMatchNewOrder"])
trade_direction String Direction of the trade(Should be one of: ["buy", "sell"])
price PriceLevel Price level at which trade has been executed
fee String The fee associated with the trade (quote asset denom)
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"])
cid String Identifier for the order specified by the user (up to 36 characters, like a UUID)

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

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 = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    market = await client.fetch_derivative_market(market_id=market_id)
    print(market)


if __name__ == "__main__":
    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", "k8s")
    network := common.LoadNetwork("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketId := "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"
    res, err := exchangeClient.GetDerivativeMarket(ctx, marketId)
    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
Parameter Type Description Required
market_id String ID of the market to fetch Yes

Response Parameters

Response Example:

{
   "market":{
      "marketId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
      "marketStatus":"active",
      "ticker":"INJ/USDT PERP",
      "oracleBase":"0x2d9315a88f3019f8efa88dfe9c0f0843712da0bac814461e27733f6b83eb51b3",
      "oracleQuote":"0x1fc18861232290221461220bd4e2acd1dcdfbc89c84092c93c18bdc7756c1588",
      "oracleType":"pyth",
      "oracleScaleFactor":6,
      "initialMarginRatio":"0.05",
      "maintenanceMarginRatio":"0.02",
      "quoteDenom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
      "quoteTokenMeta":{
         "name":"Testnet Tether USDT",
         "address":"0x0000000000000000000000000000000000000000",
         "symbol":"USDT",
         "logo":"https://static.alchemyapi.io/images/assets/825.png",
         "decimals":6,
         "updatedAt":"1698247516758"
      },
      "makerFeeRate":"-0.0001",
      "takerFeeRate":"0.001",
      "serviceProviderFee":"0.4",
      "isPerpetual":true,
      "minPriceTickSize":"100",
      "minQuantityTickSize":"0.0001",
      "perpetualMarketInfo":{
         "hourlyFundingRateCap":"0.000625",
         "hourlyInterestRate":"0.00000416666",
         "nextFundingTimestamp":"1701990000",
         "fundingInterval":"3600"
      },
      "perpetualMarketFunding":{
         "cumulativeFunding":"-156010.283874921534910863",
         "cumulativePrice":"566.477789213654772072",
         "lastTimestamp":"1701906508"
      },
      "min_notional":"1000000"
   }
}
{
 "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
  },
  "min_notional": "1000000"
 }
}
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
min_notional String Defines the minimum required notional for an order to be accepted

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

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_statuses = ["active"]
    quote_denom = "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"
    market = await client.fetch_derivative_markets(market_statuses=market_statuses, quote_denom=quote_denom)
    print(market)


if __name__ == "__main__":
    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", "k8s")
    network := common.LoadNetwork("mainnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    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))
}
Parameter Type Description Required
market_statuses String Array Filter by market status (Should be any of: ["active", "paused", "suspended", "demolished", "expired"]) No
quote_denom String Filter by the Coin denomination of the quote currency No

Response Parameters

Response Example:

[
  {
    "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
    },
    "min_notional": "1000000",
  },
  {
    "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"
    },
    "min_notional": "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
   },
   "min_notional": "1000000"
  },
  {
   "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
   },
   "min_notional": "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
min_notional String Defines the minimum required notional for an order to be accepted

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
from typing import Any, Dict

from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def market_event_processor(event: Dict[str, Any]):
    print(event)


def stream_error_processor(exception: RpcError):
    print(f"There was an error listening to derivative markets updates ({exception})")


def stream_closed_processor():
    print("The derivative markets updates stream has been closed")


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)

    task = asyncio.get_event_loop().create_task(
        client.listen_derivative_market_updates(
            callback=market_event_processor,
            on_end_callback=stream_closed_processor,
            on_status_callback=stream_error_processor,
        )
    )

    await asyncio.sleep(delay=60)
    task.cancel()


if __name__ == "__main__":
    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", "k8s")
    network := common.LoadNetwork("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    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))
        }
    }
}
Parameter Type Description Required
market_ids String Array List of market IDs for updates streaming, empty means 'ALL' derivative markets No
callback Function Function receiving one parameter (a stream event JSON dictionary) to process each new event Yes
on_end_callback Function Function with the logic to execute when the stream connection is interrupted No
on_status_callback Function Function receiving one parameter (the exception) with the logic to execute when an exception happens No

Response Parameters

Streaming Response Example:

{
  "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
    },
    "min_notional": "1000000"
  },
  "operationType": "update",
  "timestamp": 1654246076000
}
{
 "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
  },
  "min_notional": "0"
 },
 "operation_type": "update",
 "timestamp": 1653038974000
}
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
min_notional String Defines the minimum required notional for an order to be accepted

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

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    market_ids = ["0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"]
    subaccount_id = "0x295639d56c987f0e24d21bb167872b3542a6e05a000000000000000000000000"
    is_conditional = "false"
    skip = 10
    limit = 3
    pagination = PaginationOption(skip=skip, limit=limit)
    orders = await client.fetch_derivative_orders_history(
        subaccount_id=subaccount_id,
        market_ids=market_ids,
        is_conditional=is_conditional,
        pagination=pagination,
    )
    print(orders)


if __name__ == "__main__":
    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("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketId := "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    subaccountId := "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
    skip := uint64(0)
    limit := int32(10)
    isConditional := "false"

    req := derivativeExchangePB.OrdersHistoryRequest{
        SubaccountId:  subaccountId,
        MarketId:      marketId,
        Skip:          skip,
        Limit:         limit,
        IsConditional: isConditional,
    }

    res, err := exchangeClient.GetHistoricalDerivativeOrders(ctx, &req)
    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
Parameter Type Description Required
subaccount_id String Filter by subaccount ID No
market_ids String Array Filter by multiple market IDs No
order_types String Array The order types to be included (Should be any of: ["buy", "sell", "stop_buy", "stop_sell", "take_buy", "take_sell", "buy_po", "sell_po"]) 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
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
trade_id String Filter by the trade's trade id No
active_markets_only Bool Return only orders for active markets No
cid String Filter by the custom client order id of the trade's order No
pagination PaginationOption Pagination configuration No

Response Parameters

Response Example:

{
   "orders":[
      {
         "orderHash":"0x3c98f1e38781ce8780f8f5ffe3a78cf3dbfa4d96f54d774a4847f46e9e89d6dc",
         "marketId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
         "subaccountId":"0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000005",
         "executionType":"limit",
         "orderType":"buy_po",
         "price":"13097700",
         "triggerPrice":"0",
         "quantity":"110660.5284",
         "filledQuantity":"0",
         "state":"canceled",
         "createdAt":"1701995288222",
         "updatedAt":"1702002966962",
         "direction":"buy",
         "margin":"724699201412.34",
         "txHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
         "isActive":false,
         "isReduceOnly":false,
         "isConditional":false,
         "triggerAt":"0",
         "placedOrderHash":"",
         "cid":""
      },
      {
         "orderHash":"0xc7c34746158b1e21bbdfa8edce0876fa00810f7b6f2236c302945c8e6b9eeb38",
         "marketId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
         "subaccountId":"0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000005",
         "executionType":"limit",
         "orderType":"buy_po",
         "price":"13064100",
         "triggerPrice":"0",
         "quantity":"110945.1399",
         "filledQuantity":"0",
         "state":"canceled",
         "createdAt":"1701995288222",
         "updatedAt":"1702002966962",
         "direction":"buy",
         "margin":"724699201083.795",
         "txHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
         "isActive":false,
         "isReduceOnly":false,
         "isConditional":false,
         "triggerAt":"0",
         "placedOrderHash":"",
         "cid":""
      },
      {
         "orderHash":"0x4478897d21c94df929c7d12c33d71973027ced1899ff253199b6e46124e680c1",
         "marketId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
         "subaccountId":"0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000005",
         "executionType":"limit",
         "orderType":"buy_po",
         "price":"13030500",
         "triggerPrice":"0",
         "quantity":"111231.2193",
         "filledQuantity":"0",
         "state":"canceled",
         "createdAt":"1701995288222",
         "updatedAt":"1702002966962",
         "direction":"buy",
         "margin":"724699201544.325",
         "txHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
         "isActive":false,
         "isReduceOnly":false,
         "isConditional":false,
         "triggerAt":"0",
         "placedOrderHash":"",
         "cid":""
      }
   ],
   "paging":{
      "total":"1000",
      "from":0,
      "to":0,
      "countBySubaccount":"0",
      "next":[

      ]
   }
}
{
 "orders": [
  {
   "order_hash": "0x17da6aa0ba9c192da6c9d5a043b4c36a91af5117636cb1f6e69654fc6cfc1bee",
   "market_id": "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
   "subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
   "execution_type": "market",
   "order_type": "sell",
   "price": "6494113.703056872037914692",
   "trigger_price": "0",
   "quantity": "2110",
   "filled_quantity": "2110",
   "state": "filled",
   "created_at": 1692857306725,
   "updated_at": 1692857306725,
   "direction": "sell",
   "margin": "0"
  },
  {
   "order_hash": "0xeac94983c5e1a47885e5959af073c475e4ec6ec343c1e1d441af1ba65f8aa5ee",
   "market_id": "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
   "subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
   "execution_type": "limit",
   "order_type": "buy",
   "price": "8111100",
   "trigger_price": "0",
   "quantity": "10",
   "filled_quantity": "10",
   "state": "filled",
   "created_at": 1688738648747,
   "updated_at": 1688738648747,
   "direction": "buy",
   "margin": "82614000"
  },
  {
   "order_hash": "0x41a5c6f8c8c8ff3f37e443617dda589f46f1678ef1a22e2ab2b6ca54e0788210",
   "market_id": "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
   "subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
   "execution_type": "market",
   "order_type": "buy",
   "price": "8261400",
   "trigger_price": "0",
   "quantity": "100",
   "filled_quantity": "100",
   "state": "filled",
   "created_at": 1688591280030,
   "updated_at": 1688591280030,
   "direction": "buy",
   "margin": "274917218.543"
  },
  {
   "order_hash": "0x2f667629cd06ac9fd6e54aa2544ad63cd43efc29418d0e1e12df9ba783c9a7ab",
   "market_id": "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
   "subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
   "execution_type": "market",
   "order_type": "buy",
   "price": "7166668.98546",
   "trigger_price": "0",
   "quantity": "2000",
   "filled_quantity": "2000",
   "state": "filled",
   "created_at": 1687507605674,
   "updated_at": 1687507605674,
   "direction": "buy",
   "margin": "4814400000"
  },
  {
   "order_hash": "0x4c42bca7b65f18bf96e75be03a53f73854da15e8030c38e63d1531307f8cd40c",
   "market_id": "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
   "subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
   "execution_type": "market",
   "order_type": "sell",
   "price": "7123287.02926",
   "trigger_price": "0",
   "quantity": "1000",
   "filled_quantity": "1000",
   "state": "filled",
   "created_at": 1687507547684,
   "updated_at": 1687507547684,
   "direction": "sell",
   "margin": "0"
  },
  {
   "order_hash": "0x70c66ce3e92aa616d3dbdbcd565c37a3d42b2b5a0951a8bebe9ddaca9852d547",
   "market_id": "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
   "subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
   "execution_type": "market",
   "order_type": "buy",
   "price": "7162504.91532",
   "trigger_price": "0",
   "quantity": "1000",
   "filled_quantity": "1000",
   "state": "filled",
   "created_at": 1687507348068,
   "updated_at": 1687507348068,
   "direction": "buy",
   "margin": "7212200000"
  }
 ],
 "paging": {
  "total": 6
 }
}

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
market_id String Derivative market ID
is_active Boolean Indicates if the order is active
subaccount_id String The subaccountId that this order belongs to
execution_type String The type of the order (Should be one of: ["limit", "market"])
order_type String Order type (Should be one of: ["buy", "sell", "stop_buy", "stop_sell", "take_buy", "take_sell", "buy_po", "sell_po"])
price String Price of the order
trigger_price String The price that triggers stop/take orders
quantity String Quantity of the order
filled_quantity String The amount of the quantity filled
state String Order state (Should be one of: ["booked", "partial_filled", "filled", "canceled"])
created_at Integer Order created timestamp in UNIX millis
updated_at Integer Order updated timestamp in UNIX millis
is_reduce_only Boolean Indicates if the order is reduce-only
direction String The direction of the order (Should be one of: ["buy", "sell"])
is_conditional Boolean Indicates if the order is conditional
trigger_at Integer Trigger timestamp in UNIX millis
placed_order_hash String Hash of order placed upon conditional order trigger
margin String The margin of the order
tx_hash String Transaction hash in which the order was created (not all orders have this value)
cid String Identifier for the order specified by the user (up to 36 characters, like a UUID)

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
from typing import Any, Dict

from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def order_event_processor(event: Dict[str, Any]):
    print(event)


def stream_error_processor(exception: RpcError):
    print(f"There was an error listening to derivative orders history updates ({exception})")


def stream_closed_processor():
    print("The derivative orders history updates stream has been closed")


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"

    task = asyncio.get_event_loop().create_task(
        client.listen_derivative_orders_history_updates(
            callback=order_event_processor,
            on_end_callback=stream_closed_processor,
            on_status_callback=stream_error_processor,
            market_id=market_id,
        )
    )

    await asyncio.sleep(delay=60)
    task.cancel()


if __name__ == "__main__":
    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("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketId := "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    subaccountId := "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000"
    direction := "buy"

    req := derivativeExchangePB.StreamOrdersHistoryRequest{
        MarketId:     marketId,
        SubaccountId: subaccountId,
        Direction:    direction,
    }
    stream, err := exchangeClient.StreamHistoricalDerivativeOrders(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))
        }
    }
}
Parameter Type Description Required
subaccount_id String Filter by subaccount ID No
market_id String Filter by market ID 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
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
execution_types String Array Filter by execution type (Should be one of: ["limit", "market"]) No
callback Function Function receiving one parameter (a stream event JSON dictionary) to process each new event Yes
on_end_callback Function Function with the logic to execute when the stream connection is interrupted No
on_status_callback Function Function receiving one parameter (the exception) with the logic to execute when an exception happens No

Response Parameters

Streaming Response Example:

{
   "order":{
      "order_hash":"0x4aeb72ac2ae5811126a0c384e05ce68745316add0e705c39e73f68c76431515e",
      "market_id":"0x141e3c92ed55107067ceb60ee412b86256cedef67b1227d6367b4cdf30c55a74",
      "is_active":true,
      "subaccount_id":"0x7619f89a2172c6705aac7482f3adbf0601ea140e000000000000000000000000",
      "execution_type":"limit",
      "order_type":"sell_po",
      "price":"27953000000",
      "trigger_price":"0",
      "quantity":"0.0344",
      "filled_quantity":"0",
      "state":"booked",
      "created_at":1696617269292,
      "updated_at":1696617269292,
      "direction":"sell",
      "margin":"320527734"
   },
   "operation_type":"insert",
   "timestamp":1696617272000
}
{
   "order":{
      "order_hash":"0x24d82da3530ce5d2d392c9563d29b79c3a25e058dd6d79e0d8f651703256eb78",
      "market_id":"0x141e3c92ed55107067ceb60ee412b86256cedef67b1227d6367b4cdf30c55a74",
      "subaccount_id":"0x6590d14d9e9c1d964f8c83bddc8a092f4a2d1284000000000000000000000000",
      "execution_type":"limit",
      "order_type":"buy_po",
      "price":"27912000000",
      "trigger_price":"0",
      "quantity":"0.0344",
      "filled_quantity":"0",
      "state":"canceled",
      "created_at":1696617207873,
      "updated_at":1696617269292,
      "direction":"buy",
      "margin":"320057600"
   },
   "operation_type":"update",
   "timestamp":1696617272000
}
{
   "order":{
      "order_hash":"0x4aeb72ac2ae5811126a0c384e05ce68745316add0e705c39e73f68c76431515e",
      "market_id":"0x141e3c92ed55107067ceb60ee412b86256cedef67b1227d6367b4cdf30c55a74",
      "is_active":true,
      "subaccount_id":"0x7619f89a2172c6705aac7482f3adbf0601ea140e000000000000000000000000",
      "execution_type":"limit",
      "order_type":"sell_po",
      "price":"27953000000",
      "trigger_price":"0",
      "quantity":"0.0344",
      "filled_quantity":"0",
      "state":"booked",
      "created_at":1696617269292,
      "updated_at":1696617269292,
      "direction":"sell",
      "margin":"320527734"
   },
   "operation_type":"insert",
   "timestamp":1696617272000
}
{
   "order":{
      "order_hash":"0x24d82da3530ce5d2d392c9563d29b79c3a25e058dd6d79e0d8f651703256eb78",
      "market_id":"0x141e3c92ed55107067ceb60ee412b86256cedef67b1227d6367b4cdf30c55a74",
      "subaccount_id":"0x6590d14d9e9c1d964f8c83bddc8a092f4a2d1284000000000000000000000000",
      "execution_type":"limit",
      "order_type":"buy_po",
      "price":"27912000000",
      "trigger_price":"0",
      "quantity":"0.0344",
      "filled_quantity":"0",
      "state":"canceled",
      "created_at":1696617207873,
      "updated_at":1696617269292,
      "direction":"buy",
      "margin":"320057600"
   },
   "operation_type":"update",
   "timestamp":1696617272000
}
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
market_id String Derivative market ID
is_active Boolean Indicates if the order is active
subaccount_id String The subaccountId that this order belongs to
execution_type String The type of the order (Should be one of: ["limit", "market"])
order_type String Order type (Should be one of: ["buy", "sell", "stop_buy", "stop_sell", "take_buy", "take_sell", "buy_po", "sell_po"])
price String Price of the order
trigger_price String The price that triggers stop/take orders
quantity String Quantity of the order
filled_quantity String The amount of the quantity filled
state String Order state (Should be one of: ["booked", "partial_filled", "filled", "canceled"])
created_at Integer Order created timestamp in UNIX millis
updated_at Integer Order updated timestamp in UNIX millis
is_reduce_only Boolean Indicates if the order is reduce-only
direction String The direction of the order (Should be one of: ["buy", "sell"])
is_conditional Boolean Indicates if the order is conditional
trigger_at Integer Trigger timestamp in UNIX millis
placed_order_hash String Hash of order placed upon conditional order trigger
margin String The margin of the order
tx_hash String Transaction hash in which the order was created (not all orders have this value)
cid String Identifier for the order specified by the user (up to 36 characters, like a UUID)

TradesV2

Get trades of a derivative market. The difference between Trades and TradesV2 is that the latter returns a trade_id compatible witht the one used for trade events in chain stream.

IP rate limit group: indexer

*Trade execution types

  1. "market" for market orders
  2. "limitFill" for a resting limit order getting filled by a market order
  3. "limitMatchRestingOrder" for a resting limit order getting matched with another new limit order
  4. "limitMatchNewOrder" for a new limit order getting matched immediately

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    market_ids = ["0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"]
    subaccount_ids = ["0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000"]
    skip = 0
    limit = 4
    pagination = PaginationOption(skip=skip, limit=limit)
    trades = await client.fetch_derivative_trades(
        market_ids=market_ids, subaccount_ids=subaccount_ids, pagination=pagination
    )
    print(trades)


if __name__ == "__main__":
    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("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketId := "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"
    subaccountId := "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000"

    req := derivativeExchangePB.TradesV2Request{
        MarketId:     marketId,
        SubaccountId: subaccountId,
    }

    res, err := exchangeClient.GetDerivativeTradesV2(ctx, &req)
    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
Parameter Type Description Required
market_ids String Array Filter by multiple market IDs No
subaccount_ids String Array Filter by multiple subaccount IDs No
execution_side String Filter by the execution side of the trade (Should be one of: ["maker", "taker"]) No
direction String Filter by the direction of the trade (Should be one of: ["buy", "sell"]) No
execution_types String Array Filter by the *trade execution type (Should be any of: ["market", "limitFill", "limitMatchRestingOrder", "limitMatchNewOrder"]) No
trade_id String Filter by the trade id of the trade No
account_address String Filter by the account address No
cid String Filter by the custom client order id of the trade's order No
pagination PaginationOption Pagination configuration No

Response Parameters

Response Example:

{
   "trades":[
      {
         "orderHash":"0xc246b6a43d826667047f752a76e508511d0aa4f73aba1c3b95527037ccbcb50c",
         "subaccountId":"0x101411266c6e2b610b4a0324d2bfb2ef0ca6e1dd000000000000000000000000",
         "marketId":"0x56d0c0293c4415e2d48fc2c8503a56a0c7389247396a2ef9b0a48c01f0646705",
         "tradeExecutionType":"limitMatchRestingOrder",
         "positionDelta":{
            "tradeDirection":"buy",
            "executionPrice":"10000000",
            "executionQuantity":"1",
            "executionMargin":"10000000"
         },
         "payout":"0",
         "fee":"-60000",
         "executedAt":"1701978102242",
         "feeRecipient":"inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
         "tradeId":"22868_2",
         "executionSide":"maker",
         "cid":"49fb387d-aad3-4f03-85c5-e6c06c5ea685",
         "isLiquidation":false
      },
      {
         "orderHash":"0x836e778ae11cee6cd31619ca7329121419471be7ea1bd2fafbae3a8d411a04c7",
         "subaccountId":"0x101411266c6e2b610b4a0324d2bfb2ef0ca6e1dd000000000000000000000000",
         "marketId":"0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4",
         "tradeExecutionType":"limitMatchRestingOrder",
         "positionDelta":{
            "tradeDirection":"buy",
            "executionPrice":"10000000",
            "executionQuantity":"1",
            "executionMargin":"10000000"
         },
         "payout":"0",
         "fee":"-600",
         "executedAt":"1701978102242",
         "feeRecipient":"inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
         "tradeId":"22868_4",
         "executionSide":"maker",
         "cid":"9a74f3ce-ea31-491e-9e64-e48541a8f7fd",
         "isLiquidation":false
      },
      {
         "orderHash":"0x404577bc40896028733f7740d4efc6f6695fb9194f43dd545fb8923cbb01efd6",
         "subaccountId":"0x3db1f84431dfe4df617f9eb2d04edf432beb9826000000000000000000000000",
         "marketId":"0x56d0c0293c4415e2d48fc2c8503a56a0c7389247396a2ef9b0a48c01f0646705",
         "tradeExecutionType":"limitMatchNewOrder",
         "positionDelta":{
            "tradeDirection":"sell",
            "executionPrice":"10000000",
            "executionQuantity":"1",
            "executionMargin":"10000000"
         },
         "payout":"0",
         "fee":"5000000",
         "executedAt":"1701978102242",
         "feeRecipient":"inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
         "tradeId":"22868_3",
         "executionSide":"taker",
         "cid":"derivative_ATOM/USDT",
         "isLiquidation":false
      },
      {
         "orderHash":"0x3fde93ceabc67a13372c237f5271784c0bbe97801ef12e883cfbde4c13e16300",
         "subaccountId":"0x3db1f84431dfe4df617f9eb2d04edf432beb9826000000000000000000000000",
         "marketId":"0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4",
         "tradeExecutionType":"limitMatchNewOrder",
         "positionDelta":{
            "tradeDirection":"sell",
            "executionPrice":"10000000",
            "executionQuantity":"1",
            "executionMargin":"9000000"
         },
         "payout":"0",
         "fee":"10000",
         "executedAt":"1701978102242",
         "feeRecipient":"inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
         "tradeId":"22868_5",
         "executionSide":"taker",
         "cid":"derivative_INJ/USDT",
         "isLiquidation":false
      },
      {
         "orderHash":"0xc246b6a43d826667047f752a76e508511d0aa4f73aba1c3b95527037ccbcb50c",
         "subaccountId":"0x101411266c6e2b610b4a0324d2bfb2ef0ca6e1dd000000000000000000000000",
         "marketId":"0x56d0c0293c4415e2d48fc2c8503a56a0c7389247396a2ef9b0a48c01f0646705",
         "tradeExecutionType":"limitMatchRestingOrder",
         "positionDelta":{
            "tradeDirection":"buy",
            "executionPrice":"10000000",
            "executionQuantity":"1",
            "executionMargin":"10000000"
         },
         "payout":"0",
         "fee":"-60000",
         "executedAt":"1701961116630",
         "feeRecipient":"inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
         "tradeId":"1321_2",
         "executionSide":"maker",
         "cid":"49fb387d-aad3-4f03-85c5-e6c06c5ea685",
         "isLiquidation":false
      },
      {
         "orderHash":"0x836e778ae11cee6cd31619ca7329121419471be7ea1bd2fafbae3a8d411a04c7",
         "subaccountId":"0x101411266c6e2b610b4a0324d2bfb2ef0ca6e1dd000000000000000000000000",
         "marketId":"0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4",
         "tradeExecutionType":"limitMatchRestingOrder",
         "positionDelta":{
            "tradeDirection":"buy",
            "executionPrice":"10000000",
            "executionQuantity":"1",
            "executionMargin":"10000000"
         },
         "payout":"0",
         "fee":"-600",
         "executedAt":"1701961116630",
         "feeRecipient":"inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
         "tradeId":"1321_4",
         "executionSide":"maker",
         "cid":"9a74f3ce-ea31-491e-9e64-e48541a8f7fd",
         "isLiquidation":false
      },
      {
         "orderHash":"0xf6ae77b0a1e267b7f0b8618f3f226c39ba702a09fb3bdb650b0c28197d36d91d",
         "subaccountId":"0x3db1f84431dfe4df617f9eb2d04edf432beb9826000000000000000000000000",
         "marketId":"0x56d0c0293c4415e2d48fc2c8503a56a0c7389247396a2ef9b0a48c01f0646705",
         "tradeExecutionType":"limitMatchNewOrder",
         "positionDelta":{
            "tradeDirection":"sell",
            "executionPrice":"10000000",
            "executionQuantity":"1",
            "executionMargin":"10000000"
         },
         "payout":"0",
         "fee":"5000000",
         "executedAt":"1701961116630",
         "feeRecipient":"inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
         "tradeId":"1321_3",
         "executionSide":"taker",
         "cid":"49fb387d-aad3-4f03-85c5-e6c06c5ea685",
         "isLiquidation":false
      },
      {
         "orderHash":"0x01ba4dd3b30bc946a31f5fe1aba9918e95d3dc8cf31a6c4b2d793068eae529e8",
         "subaccountId":"0x3db1f84431dfe4df617f9eb2d04edf432beb9826000000000000000000000000",
         "marketId":"0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4",
         "tradeExecutionType":"limitMatchNewOrder",
         "positionDelta":{
            "tradeDirection":"sell",
            "executionPrice":"10000000",
            "executionQuantity":"1",
            "executionMargin":"9000000"
         },
         "payout":"0",
         "fee":"10000",
         "executedAt":"1701961116630",
         "feeRecipient":"inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
         "tradeId":"1321_5",
         "executionSide":"taker",
         "cid":"9a74f3ce-ea31-491e-9e64-e48541a8f7fd",
         "isLiquidation":false
      }
   ],
   "paging":{
      "total":"8",
      "from":1,
      "to":8,
      "countBySubaccount":"0",
      "next":[

      ]
   }
}
{
 "trades": [
  {
   "order_hash": "0x836e778ae11cee6cd31619ca7329121419471be7ea1bd2fafbae3a8d411a04c7",
   "subaccount_id": "0x101411266c6e2b610b4a0324d2bfb2ef0ca6e1dd000000000000000000000000",
   "market_id": "0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4",
   "trade_execution_type": "limitMatchRestingOrder",
   "position_delta": {
    "trade_direction": "buy",
    "execution_price": "10000000",
    "execution_quantity": "1",
    "execution_margin": "10000000"
   },
   "payout": "0",
   "fee": "-600",
   "executed_at": 1701978102242,
   "fee_recipient": "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
   "trade_id": "22868_4",
   "execution_side": "maker",
   "cid": "9a74f3ce-ea31-491e-9e64-e48541a8f7fd"
  },
  {
   "order_hash": "0x3fde93ceabc67a13372c237f5271784c0bbe97801ef12e883cfbde4c13e16300",
   "subaccount_id": "0x3db1f84431dfe4df617f9eb2d04edf432beb9826000000000000000000000000",
   "market_id": "0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4",
   "trade_execution_type": "limitMatchNewOrder",
   "position_delta": {
    "trade_direction": "sell",
    "execution_price": "10000000",
    "execution_quantity": "1",
    "execution_margin": "9000000"
   },
   "payout": "0",
   "fee": "10000",
   "executed_at": 1701978102242,
   "fee_recipient": "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
   "trade_id": "22868_5",
   "execution_side": "taker",
   "cid": "9a74f3ce-ea31-491e-9e64-e48541a8f7fd"
  },
  {
   "order_hash": "0x836e778ae11cee6cd31619ca7329121419471be7ea1bd2fafbae3a8d411a04c7",
   "subaccount_id": "0x101411266c6e2b610b4a0324d2bfb2ef0ca6e1dd000000000000000000000000",
   "market_id": "0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4",
   "trade_execution_type": "limitMatchRestingOrder",
   "position_delta": {
    "trade_direction": "buy",
    "execution_price": "10000000",
    "execution_quantity": "1",
    "execution_margin": "10000000"
   },
   "payout": "0",
   "fee": "-600",
   "executed_at": 1701961116630,
   "fee_recipient": "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
   "trade_id": "1321_4",
   "execution_side": "maker",
   "cid": "9a74f3ce-ea31-491e-9e64-e48541a8f7fd"
  },
  {
   "order_hash": "0x01ba4dd3b30bc946a31f5fe1aba9918e95d3dc8cf31a6c4b2d793068eae529e8",
   "subaccount_id": "0x3db1f84431dfe4df617f9eb2d04edf432beb9826000000000000000000000000",
   "market_id": "0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4",
   "trade_execution_type": "limitMatchNewOrder",
   "position_delta": {
    "trade_direction": "sell",
    "execution_price": "10000000",
    "execution_quantity": "1",
    "execution_margin": "9000000"
   },
   "payout": "0",
   "fee": "10000",
   "executed_at": 1701961116630,
   "fee_recipient": "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
   "trade_id": "1321_5",
   "execution_side": "taker",
   "cid": "9a74f3ce-ea31-491e-9e64-e48541a8f7fd"
  }
 ],
 "paging": {
  "total": 4,
  "from": 1,
  "to": 4
 }
}

Parameter Type Description
trades DerivativeTrade Array List of trades of derivative markets
paging Paging Pagination of results

DerivativeTrade

Parameter Type Description
order_hash String The order hash
subaccount_id String ID of subaccount that executed the trade
market_id String The market ID
trade_execution_type String *Execution type of the trade (Should be one of: ["market", "limitFill", "limitMatchRestingOrder", "limitMatchNewOrder"])
is_liquidation Boolean True if the trade is a liquidation
position_delta PositionDelta Position delta from the trade
payout String The payout associated with the trade
fee String The fee associated with 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"])
cid String Custom client order id

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

StreamTradesV2

Stream newly executed trades of a derivative market. The default request streams trades from all derivative markets. The difference between StreamTrades and StreamTradesV2 is that the latter returns a trade_id compatible witht the one used for trade events in chain stream.

IP rate limit group: indexer

*Trade execution types

  1. "market" for market orders
  2. "limitFill" for a resting limit order getting filled by a market order
  3. "limitMatchRestingOrder" for a resting limit order getting matched with another new limit order
  4. "limitMatchNewOrder" for a new limit order getting matched immediately

Request Parameters

Request Example:

import asyncio
from typing import Any, Dict

from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def market_event_processor(event: Dict[str, Any]):
    print(event)


def stream_error_processor(exception: RpcError):
    print(f"There was an error listening to derivative trades updates ({exception})")


def stream_closed_processor():
    print("The derivative trades updates stream has been closed")


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    market_ids = [
        "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
        "0x70bc8d7feab38b23d5fdfb12b9c3726e400c265edbcbf449b6c80c31d63d3a02",
    ]
    subaccount_ids = ["0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000"]

    task = asyncio.get_event_loop().create_task(
        client.listen_derivative_trades_updates(
            callback=market_event_processor,
            on_end_callback=stream_closed_processor,
            on_status_callback=stream_error_processor,
            market_ids=market_ids,
            subaccount_ids=subaccount_ids,
        )
    )

    await asyncio.sleep(delay=60)
    task.cancel()


if __name__ == "__main__":
    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("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketId := "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"
    subaccountId := "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000"

    req := derivativeExchangePB.StreamTradesV2Request{
        MarketId:     marketId,
        SubaccountId: subaccountId,
    }
    stream, err := exchangeClient.StreamDerivativeV2Trades(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))
        }
    }
}
Parameter Type Description Required
market_ids String Array Filter by multiple market IDs No
execution_side String Filter by the execution side of the trade (Should be one of: ["maker", "taker"]) No
direction String Filter by the direction of the trade (Should be one of: ["buy", "sell"]) No
subaccount_ids String Array Filter by multiple subaccount IDs No
execution_types String Array Filter by the *trade execution type (Should be one of: ["market", "limitFill", "limitMatchRestingOrder", "limitMatchNewOrder"]) No
trade_id String Filter by the trade's trade id No
account_address String Filter by the account address No
cid String Filter by the custom client order id of the trade's order No
pagination PaginationOption Pagination configuration No
callback Function Function receiving one parameter (a stream event JSON dictionary) to process each new event Yes
on_end_callback Function Function with the logic to execute when the stream connection is interrupted No
on_status_callback Function Function receiving one parameter (the exception) with the logic to execute when an exception happens No

Response Parameters

Streaming Response Example:

{
   "trade":{
      "orderHash":"0x01e6b3df831734c88c84522f9834b3656b3afde6891ac671742dd269be776510",
      "subaccountId":"0x3db1f84431dfe4df617f9eb2d04edf432beb9826000000000000000000000000",
      "marketId":"0x56d0c0293c4415e2d48fc2c8503a56a0c7389247396a2ef9b0a48c01f0646705",
      "tradeExecutionType":"limitMatchNewOrder",
      "positionDelta":{
         "tradeDirection":"sell",
         "executionPrice":"10000000",
         "executionQuantity":"1",
         "executionMargin":"10000000"
      },
      "payout":"0",
      "fee":"5000000",
      "executedAt":"1701979920875",
      "feeRecipient":"inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
      "tradeId":"25116_3",
      "executionSide":"taker",
      "cid":"derivative_ATOM/USDT",
      "isLiquidation":false
   },
   "operationType":"insert",
   "timestamp":"1701979922000"
}
{
   "trade":{
      "orderHash":"0xc246b6a43d826667047f752a76e508511d0aa4f73aba1c3b95527037ccbcb50c",
      "subaccountId":"0x101411266c6e2b610b4a0324d2bfb2ef0ca6e1dd000000000000000000000000",
      "marketId":"0x56d0c0293c4415e2d48fc2c8503a56a0c7389247396a2ef9b0a48c01f0646705",
      "tradeExecutionType":"limitMatchRestingOrder",
      "positionDelta":{
         "tradeDirection":"buy",
         "executionPrice":"10000000",
         "executionQuantity":"1",
         "executionMargin":"10000000"
      },
      "payout":"0",
      "fee":"-60000",
      "executedAt":"1701979920875",
      "feeRecipient":"inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
      "tradeId":"25116_2",
      "executionSide":"maker",
      "cid":"49fb387d-aad3-4f03-85c5-e6c06c5ea685",
      "isLiquidation":false
   },
   "operationType":"insert",
   "timestamp":"1701979922000"
}
{
   "trade":{
      "orderHash":"0xa0446c80b66dd6ab75b32e51e4e04929ae92df9fa7a64fe2d21ed9be536bb6d5",
      "subaccountId":"0x3db1f84431dfe4df617f9eb2d04edf432beb9826000000000000000000000000",
      "marketId":"0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4",
      "tradeExecutionType":"limitMatchNewOrder",
      "positionDelta":{
         "tradeDirection":"sell",
         "executionPrice":"10000000",
         "executionQuantity":"1",
         "executionMargin":"9000000"
      },
      "payout":"0",
      "fee":"10000",
      "executedAt":"1701979920875",
      "feeRecipient":"inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
      "tradeId":"25116_5",
      "executionSide":"taker",
      "cid":"derivative_INJ/USDT",
      "isLiquidation":false
   },
   "operationType":"insert",
   "timestamp":"1701979922000"
}
{
   "trade":{
      "orderHash":"0x836e778ae11cee6cd31619ca7329121419471be7ea1bd2fafbae3a8d411a04c7",
      "subaccountId":"0x101411266c6e2b610b4a0324d2bfb2ef0ca6e1dd000000000000000000000000",
      "marketId":"0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4",
      "tradeExecutionType":"limitMatchRestingOrder",
      "positionDelta":{
         "tradeDirection":"buy",
         "executionPrice":"10000000",
         "executionQuantity":"1",
         "executionMargin":"10000000"
      },
      "payout":"0",
      "fee":"-600",
      "executedAt":"1701979920875",
      "feeRecipient":"inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
      "tradeId":"25116_4",
      "executionSide":"maker",
      "cid":"9a74f3ce-ea31-491e-9e64-e48541a8f7fd",
      "isLiquidation":false
   },
   "operationType":"insert",
   "timestamp":"1701979922000"
}
{
 "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
}
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
order_hash String The order hash
subaccount_id String ID of subaccount that executed the trade
market_id String The market ID
trade_execution_type String *Execution type of the trade (Should be one of: ["market", "limitFill", "limitMatchRestingOrder", "limitMatchNewOrder"])
is_liquidation Boolean True if the trade is a liquidation
position_delta PositionDelta Position delta from the trade
payout String The payout associated with the trade
fee String The fee associated with 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"])
cid String Custom client order id

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

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    market_ids = [
        "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
        "0xd97d0da6f6c11710ef06315971250e4e9aed4b7d4cd02059c9477ec8cf243782",
    ]
    subaccount_id = "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000"
    direction = "short"
    subaccount_total_positions = False
    skip = 4
    limit = 4
    pagination = PaginationOption(skip=skip, limit=limit)
    positions = await client.fetch_derivative_positions_v2(
        market_ids=market_ids,
        subaccount_id=subaccount_id,
        direction=direction,
        subaccount_total_positions=subaccount_total_positions,
        pagination=pagination,
    )
    print(positions)


if __name__ == "__main__":
    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", "k8s")
    network := common.LoadNetwork("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketId := "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    subaccountId := "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000"
    skip := uint64(0)
    limit := int32(10)

    req := derivativeExchangePB.PositionsV2Request{
        MarketId:     marketId,
        SubaccountId: subaccountId,
        Skip:         skip,
        Limit:        limit,
    }

    res, err := exchangeClient.GetDerivativePositionsV2(ctx, &req)
    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
Parameter Type Description Required
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"]) No
subaccount_total_positions Boolean Choose to return subaccount total positions (Should be one of: [True, False]) No
pagination PaginationOption Pagination configuration No

Response Parameters

Response Example:

{
   "positions":[
      {
         "ticker":"INJ/USDT PERP",
         "marketId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
         "subaccountId":"0x0000007c60fab7a70c2ae0ebe437f3726b05e7eb000000000000000000000000",
         "direction":"short",
         "quantity":"0.087829315829932072",
         "entryPrice":"26453271.813315285838444221",
         "margin":"1156906.224974",
         "liquidationPrice":"38848511.946759",
         "markPrice":"35561999.99",
         "updatedAt":"1703793600379"
      },
      {
         "ticker":"INJ/USDT PERP",
         "marketId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
         "subaccountId":"0x0000040f1111c5c3d2037940658ee770bb37e0a2000000000000000000000000",
         "direction":"long",
         "quantity":"0.000068500966722584",
         "entryPrice":"12293600",
         "margin":"440.389918",
         "liquidationPrice":"5984327.380009",
         "markPrice":"35561999.99",
         "updatedAt":"1703793600379"
      },
      {
         "ticker":"INJ/USDT PERP",
         "marketId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
         "subaccountId":"0x00509ed903475672121d6a1fb2c646eef4da6c44000000000000000000000000",
         "direction":"short",
         "quantity":"0.022151816236313182",
         "entryPrice":"15980281.340438795311756833",
         "margin":"172782.601001",
         "liquidationPrice":"23313932.022168",
         "markPrice":"35561999.99",
         "updatedAt":"1703793600379"
      },
   ],
   "paging":{
      "total":"1166",
      "from":0,
      "to":0,
      "countBySubaccount":"0",
      "next":[

      ]
   }
}
{
 "positions": [
  {
   "ticker": "INJ/USDT PERP",
   "market_id": "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
   "subaccount_id": "0x0000007c60fab7a70c2ae0ebe437f3726b05e7eb000000000000000000000000",
   "direction": "short",
   "quantity": "0.087829315829932072",
   "entry_price": "26453271.813315285838444221",
   "margin": "1156893.718782",
   "liquidation_price": "38848372.346758",
   "mark_price": "35294291.44",
   "updated_at": 1703790001819
  },
  {
   "ticker": "INJ/USDT PERP",
   "market_id": "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
   "subaccount_id": "0x0000040f1111c5c3d2037940658ee770bb37e0a2000000000000000000000000",
   "direction": "long",
   "quantity": "0.000068500966722584",
   "entry_price": "12293600",
   "margin": "440.399672",
   "liquidation_price": "5984182.081895",
   "mark_price": "35294291.44",
   "updated_at": 1703790001819
  },
  {
   "ticker": "INJ/USDT PERP",
   "market_id": "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
   "subaccount_id": "0x00509ed903475672121d6a1fb2c646eef4da6c44000000000000000000000000",
   "direction": "short",
   "quantity": "0.022151816236313182",
   "entry_price": "15980281.340438795311756833",
   "margin": "172779.44676",
   "liquidation_price": "23313792.422186",
   "mark_price": "35294291.44",
   "updated_at": 1703790001819
  },
  {
   "ticker": "INJ/USDT PERP",
   "market_id": "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
   "subaccount_id": "0x00606da8ef76ca9c36616fa576d1c053bb0f7eb2000000000000000000000000",
   "direction": "short",
   "quantity": "0.041121486263975195",
   "entry_price": "15980281.340438795311756842",
   "margin": "320624.783065",
   "liquidation_price": "23311073.361647",
   "mark_price": "35294291.44",
   "updated_at": 1703790001819
  },
  {
   "ticker": "INJ/USDT PERP",
   "market_id": "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
   "subaccount_id": "0x00cd2929594559000670af009e2f5ef15fefa6cf000000000000000000000000",
   "direction": "long",
   "quantity": "0.000050211853307914",
   "entry_price": "12293600",
   "margin": "322.774915",
   "liquidation_price": "5985039.457698",
   "mark_price": "35294291.44",
   "updated_at": 1703790001819
  },
  {
   "ticker": "INJ/USDT PERP",
   "market_id": "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
   "subaccount_id": "0x00cf63fab44e827a4fb12142d6e0d8e82099701a000000000000000000000000",
   "direction": "long",
   "quantity": "0.000058171926973086",
   "entry_price": "12293600",
   "margin": "374.127106",
   "liquidation_price": "5981833.667338",
   "mark_price": "35294291.44",
   "updated_at": 1703790001819
  },
  {
   "ticker": "INJ/USDT PERP",
   "market_id": "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
   "subaccount_id": "0x010d36443f440708892e79dcbb6c1350c4c76662000000000000000000000000",
   "direction": "long",
   "quantity": "0.00008708028566368",
   "entry_price": "12293600",
   "margin": "559.983294",
   "liquidation_price": "5982596.709155",
   "mark_price": "35294291.44",
   "updated_at": 1703790001819
  },
  {
   "ticker": "INJ/USDT PERP",
   "market_id": "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
   "subaccount_id": "0x0154fc01caf0e4c82b7ea6c9be719c260e940ef3000000000000000000000000",
   "direction": "short",
   "quantity": "0.005684726095134712",
   "entry_price": "19468749.344033524349659551",
   "margin": "54688.034814",
   "liquidation_price": "28518548.958621",
   "mark_price": "35294291.44",
   "updated_at": 1703790001819
  },
  {
   "ticker": "INJ/USDT PERP",
   "market_id": "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
   "subaccount_id": "0x0198b3d3691bcc1718dcda4277bb27c68fd19a6f000000000000000000000000",
   "direction": "short",
   "quantity": "1.950155851194068459",
   "entry_price": "34111005.753742189227540816",
   "margin": "33194528.351493",
   "liquidation_price": "50129882.732098",
   "mark_price": "35294291.44",
   "updated_at": 1703790001819
  },
  {
   "ticker": "INJ/USDT PERP",
   "market_id": "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
   "subaccount_id": "0x021a86b9858f6e4150a724d444e94d10cb75c1b1000000000000000000000000",
   "direction": "short",
   "quantity": "0.077749303393590607",
   "entry_price": "15980281.340438795311756851",
   "margin": "605813.214778",
   "liquidation_price": "23306040.184987",
   "mark_price": "35294291.44",
   "updated_at": 1703790001819
  }
 ],
 "paging": {
  "total": 1153
 }
}
Parameter Type Description
positions DerivativePosition Array List of derivative positions
paging Paging Pagination of results

DerivativePosition

Parameter Type Description
ticker String Ticker of the derivative market
market_id String ID of the market the position is in
subaccount_id String The subaccount ID the position belongs to
direction String Direction of the position (Should be one of: ["long", "short"])
quantity String Quantity of the position
entry_price String Entry price of the position
margin String Margin of the position
liquidation_price String Liquidation price of the position
mark_price String Oracle price of the base asset
updated_at Integer Position updated timestamp in UNIX millis

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
from typing import Any, Dict

from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def positions_event_processor(event: Dict[str, Any]):
    print(event)


def stream_error_processor(exception: RpcError):
    print(f"There was an error listening to derivative positions updates ({exception})")


def stream_closed_processor():
    print("The derivative positions updates stream has been closed")


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    market_ids = ["0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"]
    subaccount_ids = ["0xea98e3aa091a6676194df40ac089e40ab4604bf9000000000000000000000000"]

    task = asyncio.get_event_loop().create_task(
        client.listen_derivative_positions_updates(
            callback=positions_event_processor,
            on_end_callback=stream_closed_processor,
            on_status_callback=stream_error_processor,
            market_ids=market_ids,
            subaccount_ids=subaccount_ids,
        )
    )

    await asyncio.sleep(delay=60)
    task.cancel()


if __name__ == "__main__":
    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("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketId := "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"
    subaccountId := "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000"

    req := derivativeExchangePB.StreamPositionsRequest{
        MarketId:     marketId,
        SubaccountId: subaccountId,
    }
    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))
        }
    }
}
Parameter Type Description Required
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
callback Function Function receiving one parameter (a stream event JSON dictionary) to process each new event Yes
on_end_callback Function Function with the logic to execute when the stream connection is interrupted No
on_status_callback Function Function receiving one parameter (the exception) with the logic to execute when an exception happens No

Response Parameters

Streaming Response Example:

{
  "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
}
{
 "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
}
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).

LiquidablePositions

Gets all the liquidable positions

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    skip = 10
    limit = 3
    pagination = PaginationOption(skip=skip, limit=limit)
    positions = await client.fetch_derivative_liquidable_positions(
        market_id=market_id,
        pagination=pagination,
    )
    print(positions)


if __name__ == "__main__":
    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("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    //marketId := "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    skip := uint64(0)
    limit := int32(10)

    req := derivativeExchangePB.LiquidablePositionsRequest{
        //MarketId: marketId,
        Skip:  skip,
        Limit: limit,
    }

    res, err := exchangeClient.GetDerivativeLiquidablePositions(ctx, &req)
    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
Parameter Type Description Required
market_id String ID of the market to query liquidable positions for Yes
skip Integer Skip the first n cosmwasm contracts. This can be used to fetch all results since the API caps at 100 No
limit Integer Max number of items to be returned, defaults to 100 No

Response Parameters

Streaming Response Example:

{
   "positions":[
      {
         "ticker":"INJ/USDT PERP",
         "marketId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
         "subaccountId":"0x0a5d67f3616a9e7b53c301b508e9384c6321be47000000000000000000000000",
         "direction":"short",
         "quantity":"0.00966730135521481",
         "entryPrice":"15980281.340438795311756819",
         "margin":"75611.273514",
         "liquidationPrice":"23334925.188149",
         "markPrice":"39291123.99",
         "aggregateReduceOnlyQuantity":"0",
         "updatedAt":"1705525203015",
         "createdAt":"-62135596800000"
      },
      {
         "ticker":"INJ/USDT PERP",
         "marketId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
         "subaccountId":"0x0c812012cf492aa422fb888e172fbd6e19df517b000000000000000000000000",
         "direction":"short",
         "quantity":"0.066327809378915175",
         "entryPrice":"16031762.538045163086357667",
         "margin":"520412.029703",
         "liquidationPrice":"23409630.791347",
         "markPrice":"39291123.99",
         "aggregateReduceOnlyQuantity":"0",
         "updatedAt":"1705525203015",
         "createdAt":"-62135596800000"
      },
      {
         "ticker":"INJ/USDT PERP",
         "marketId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
         "subaccountId":"0x0d750ad3404b6f23579706e44111e8dd774fd1fa000000000000000000000000",
         "direction":"short",
         "quantity":"0.000080602003464734",
         "entryPrice":"16031762.53804516308635803",
         "margin":"632.408209",
         "liquidationPrice":"23409630.592378",
         "markPrice":"39291123.99",
         "aggregateReduceOnlyQuantity":"0",
         "updatedAt":"1705525203015",
         "createdAt":"-62135596800000"
      }
   ]
}
{
 "positions": [
  {
   "ticker": "SOL/USDT PERP",
   "market_id": "0x95698a9d8ba11660f44d7001d8c6fb191552ece5d9141a05c5d9128711cdc2e0",
   "subaccount_id": "0x0ddbe7ea40134ae14ed6a5d104d8783c80663edb000000000000000000000000",
   "direction": "short",
   "quantity": "135965",
   "entry_price": "24074541.242231456624866694",
   "margin": "922840147876.471312471775929175",
   "liquidation_price": "29392264.1007154944460271",
   "mark_price": "102769181.99",
   "aggregate_reduce_only_quantity": "0",
   "updated_at": 1703361600801,
   "created_at": -62135596800000
  },
  {
   "ticker": "SOL/USDT PERP",
   "market_id": "0x95698a9d8ba11660f44d7001d8c6fb191552ece5d9141a05c5d9128711cdc2e0",
   "subaccount_id": "0x16aef18dbaa341952f1af1795cb49960f68dfee3000000000000000000000000",
   "direction": "short",
   "quantity": "34.99",
   "entry_price": "25000000",
   "margin": "963925977.452838924992513061",
   "liquidation_price": "50046298.3288514793340278",
   "mark_price": "102769181.99",
   "aggregate_reduce_only_quantity": "0",
   "updated_at": 1703361600801,
   "created_at": -62135596800000
  },
  {
   "ticker": "SOL/USDT PERP",
   "market_id": "0x95698a9d8ba11660f44d7001d8c6fb191552ece5d9141a05c5d9128711cdc2e0",
   "subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
   "direction": "short",
   "quantity": "160",
   "entry_price": "24375243.283322806982741737",
   "margin": "3774845657.765183864053125849",
   "liquidation_price": "45683836.8041478153648322",
   "mark_price": "102769181.99",
   "aggregate_reduce_only_quantity": "0",
   "updated_at": 1703361600801,
   "created_at": -62135596800000
  },
  {
   "ticker": "SOL/USDT PERP",
   "market_id": "0x95698a9d8ba11660f44d7001d8c6fb191552ece5d9141a05c5d9128711cdc2e0",
   "subaccount_id": "0xce4c01573f2a5f4db5d184b666ecfccb9313cc65000000000000000000000000",
   "direction": "short",
   "quantity": "8",
   "entry_price": "17700000",
   "margin": "141673770.450618846533455704",
   "liquidation_price": "33723067.9107879579206495",
   "mark_price": "102769181.99",
   "aggregate_reduce_only_quantity": "0",
   "updated_at": 1703361600801,
   "created_at": -62135596800000
  },
  {
   "ticker": "INJ/USDT PERP",
   "market_id": "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
   "subaccount_id": "0x0000007c60fab7a70c2ae0ebe437f3726b05e7eb000000000000000000000000",
   "direction": "short",
   "quantity": "0.087829315829932072",
   "entry_price": "26453271.813315285838444221",
   "margin": "1154483.475338511428917818",
   "liquidation_price": "38821468.0751518485185464",
   "mark_price": "40421744.55",
   "aggregate_reduce_only_quantity": "0",
   "updated_at": 1703361600801,
   "created_at": -62135596800000
  },
  {
   "ticker": "INJ/USDT PERP",
   "market_id": "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
   "subaccount_id": "0x00509ed903475672121d6a1fb2c646eef4da6c44000000000000000000000000",
   "direction": "short",
   "quantity": "0.022151816236313182",
   "entry_price": "15980281.340438795311756833",
   "margin": "172410.019375666543049786",
   "liquidation_price": "23297442.3538099336017081",
   "mark_price": "40421744.55",
   "aggregate_reduce_only_quantity": "0",
   "updated_at": 1703361600801,
   "created_at": -62135596800000
  },
  {
   "ticker": "INJ/USDT PERP",
   "market_id": "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
   "subaccount_id": "0x00606da8ef76ca9c36616fa576d1c053bb0f7eb2000000000000000000000000",
   "direction": "short",
   "quantity": "0.041121486263975195",
   "entry_price": "15980281.340438795311756842",
   "margin": "320053.045217395063737578",
   "liquidation_price": "23297442.3538099336017082",
   "mark_price": "40421744.55",
   "aggregate_reduce_only_quantity": "0",
   "updated_at": 1703361600801,
   "created_at": -62135596800000
  },
  {
   "ticker": "INJ/USDT PERP",
   "market_id": "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
   "subaccount_id": "0x0154fc01caf0e4c82b7ea6c9be719c260e940ef3000000000000000000000000",
   "direction": "short",
   "quantity": "0.005684726095134712",
   "entry_price": "19468749.344033524349659551",
   "margin": "54563.593706555517738922",
   "liquidation_price": "28497087.7512237107551938",
   "mark_price": "40421744.55",
   "aggregate_reduce_only_quantity": "0",
   "updated_at": 1703361600801,
   "created_at": -62135596800000
  },
  {
   "ticker": "INJ/USDT PERP",
   "market_id": "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
   "subaccount_id": "0x021a86b9858f6e4150a724d444e94d10cb75c1b1000000000000000000000000",
   "direction": "short",
   "quantity": "0.077749303393590607",
   "entry_price": "15980281.340438795311756851",
   "margin": "605131.369885566651321656",
   "liquidation_price": "23297442.3538099336017081",
   "mark_price": "40421744.55",
   "aggregate_reduce_only_quantity": "0",
   "updated_at": 1703361600801,
   "created_at": -62135596800000
  },
  {
   "ticker": "INJ/USDT PERP",
   "market_id": "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
   "subaccount_id": "0x03ca8d57285836857dddf42cbb896448015246e7000000000000000000000000",
   "direction": "short",
   "quantity": "3.933956815705317214",
   "entry_price": "20294270.597312410912417203",
   "margin": "39442957.950528509629919537",
   "liquidation_price": "29726031.3451969744796065",
   "mark_price": "40421744.55",
   "aggregate_reduce_only_quantity": "0",
   "updated_at": 1703361600801,
   "created_at": -62135596800000
  }
 ]
}

Parameter Type Description
positions DerivativePosition Array List of liquidable lpositions

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).

OrderbooksV2

Get an orderbook snapshot for one or more derivative markets.

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio

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 = [
        "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
        "0xd5e4b12b19ecf176e4e14b42944731c27677819d2ed93be4104ad7025529c7ff",
    ]
    orderbooks = await client.fetch_derivative_orderbooks_v2(market_ids=market_ids)
    print(orderbooks)


if __name__ == "__main__":
    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", "k8s")
    network := common.LoadNetwork("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketIds := []string{"0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"}
    res, err := exchangeClient.GetDerivativeOrderbooksV2(ctx, marketIds)
    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
Parameter Type Description Required
market_ids String Array List of IDs of markets to get orderbook snapshots from Yes

Response Parameters

Response Example:

{
   "orderbooks":[
      {
         "marketId":"0xd5e4b12b19ecf176e4e14b42944731c27677819d2ed93be4104ad7025529c7ff",
         "orderbook":{
            "sequence":"4099",
            "timestamp":"1681978300931",
            "buys":[

            ],
            "sells":[

            ]
         }
      },
      {
         "marketId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
         "orderbook":{
            "buys":[
               {
                  "price":"13400000",
                  "quantity":"683.3032",
                  "timestamp":"1702002966962"
               },
               {
                  "price":"13366500",
                  "quantity":"108438.1403",
                  "timestamp":"1702002966962"
               }
            ],
            "sells":[
               {
                  "price":"18390200",
                  "quantity":"78815.8042",
                  "timestamp":"1702002966962"
               }
            ],
            "sequence":"1919116",
            "timestamp":"1702003451726"
         }
      }
   ]
}
{
 "orderbooks": [
  {
   "market_id": "0x2e94326a421c3f66c15a3b663c7b1ab7fb6a5298b3a57759ecf07f0036793fc9",
   "orderbook": {
    "buys": [
     {
      "price": "25100000000",
      "quantity": "0.46",
      "timestamp": 1701558751779
     },
     {
      "price": "25000000000",
      "quantity": "99.51",
      "timestamp": 1702216325243
     },
     {
      "price": "24192180000",
      "quantity": "0.05",
      "timestamp": 1681812143213
     },
     {
      "price": "24000180000",
      "quantity": "3",
      "timestamp": 1681811751044
     },
     {
      "price": "21295940000",
      "quantity": "1",
      "timestamp": 1681811119316
     },
     {
      "price": "20160150000",
      "quantity": "1",
      "timestamp": 1681812143213
     },
     {
      "price": "20000000000",
      "quantity": "200",
      "timestamp": 1699699685300
     },
     {
      "price": "19894890000",
      "quantity": "1",
      "timestamp": 1681811751044
     },
     {
      "price": "19764860000",
      "quantity": "4",
      "timestamp": 1681810803871
     },
     {
      "price": "18900140000",
      "quantity": "3",
      "timestamp": 1681812143213
     },
     {
      "price": "18439160000",
      "quantity": "10",
      "timestamp": 1681812143213
     },
     {
      "price": "15000000000",
      "quantity": "400",
      "timestamp": 1699699705568
     },
     {
      "price": "10000000000",
      "quantity": "1000",
      "timestamp": 1699699744160
     }
    ],
    "sells": [
     {
      "price": "50501180000",
      "quantity": "4",
      "timestamp": 1681811955314
     },
     {
      "price": "50198770000",
      "quantity": "2.48",
      "timestamp": 1681811955314
     }
    ],
    "timestamp": -62135596800000
   }
  }
 ]
}

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
from typing import Any, Dict

from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def orderbook_event_processor(event: Dict[str, Any]):
    print(event)


def stream_error_processor(exception: RpcError):
    print(f"There was an error listening to derivative orderbook snapshots ({exception})")


def stream_closed_processor():
    print("The derivative orderbook snapshots stream has been closed")


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    market_ids = ["0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"]

    task = asyncio.get_event_loop().create_task(
        client.listen_derivative_orderbook_snapshots(
            market_ids=market_ids,
            callback=orderbook_event_processor,
            on_end_callback=stream_closed_processor,
            on_status_callback=stream_error_processor,
        )
    )

    await asyncio.sleep(delay=60)
    task.cancel()


if __name__ == "__main__":
    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"
)

func main() {
    network := common.LoadNetwork("devnet-1", "")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketIds := []string{"0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"}
    stream, err := exchangeClient.StreamDerivativeOrderbookV2(ctx, marketIds)
    if err != nil {
        panic(err)
    }

    for {
        select {
        case <-ctx.Done():
            return
        default:
            res, err := stream.Recv()
            if err != nil {
                fmt.Println(err)
                return
            }
            fmt.Println(res.MarketId, len(res.Orderbook.Sells), len(res.Orderbook.Buys))
        }
    }
}
Parameter Type Description Required
market_ids String Array List of market IDs for orderbook streaming; empty means all spot markets Yes
callback Function Function receiving one parameter (a stream event JSON dictionary) to process each new event Yes
on_end_callback Function Function with the logic to execute when the stream connection is interrupted No
on_status_callback Function Function receiving one parameter (the exception) with the logic to execute when an exception happens No

Response Parameters

Streaming Response Example:

{
   "orderbook":{
      "buys":[
         {
            "price":"13400000",
            "quantity":"683.3032",
            "timestamp":"1702002966962"
         },
         ...
      ],
      "sells":[
         {
            "price":"18390200",
            "quantity":"78815.8042",
            "timestamp":"1702002966962"
         },
         ...
      ],
      "sequence":"1919121",
      "timestamp":"1702003627697"
   },
   "operationType":"update",
   "timestamp":"1702003629000",
   "marketId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
}

Parameter Type Description
orderbook DerivativeLimitOrderbookV2 Orderbook of a Derivative 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

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
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 derivative 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
from decimal import Decimal
from typing import Any, Dict

from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


def stream_error_processor(exception: RpcError):
    print(f"There was an error listening to derivative orderbook updates ({exception})")


def stream_closed_processor():
    print("The derivative orderbook updates stream has been closed")


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.fetch_derivative_orderbooks_v2(market_ids=[orderbook.market_id])
    for snapshot in res["orderbooks"]:
        if snapshot["marketId"] != 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=int(buy["timestamp"]),
            )
        for sell in snapshot["orderbook"]["sells"]:
            orderbook.levels["sells"][sell["price"]] = PriceLevel(
                price=Decimal(sell["price"]),
                quantity=Decimal(sell["quantity"]),
                timestamp=int(sell["timestamp"]),
            )
        break


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    async_client = AsyncClient(network)

    market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    orderbook = Orderbook(market_id=market_id)
    updates_queue = asyncio.Queue()
    tasks = []

    async def queue_event(event: Dict[str, Any]):
        await updates_queue.put(event)

    # start getting price levels updates
    task = asyncio.get_event_loop().create_task(
        async_client.listen_derivative_orderbook_updates(
            market_ids=[market_id],
            callback=queue_event,
            on_end_callback=stream_closed_processor,
            on_status_callback=stream_error_processor,
        )
    )
    tasks.append(task)

    # 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)

    task = asyncio.get_event_loop().create_task(
        apply_orderbook_update(orderbook=orderbook, updates_queue=updates_queue)
    )
    tasks.append(task)

    await asyncio.sleep(delay=60)
    for task in tasks:
        task.cancel()


async def apply_orderbook_update(orderbook: Orderbook, updates_queue: asyncio.Queue):
    while True:
        updates = await updates_queue.get()
        update = updates["orderbookLevelUpdates"]

        # discard updates older than the snapshot
        if int(update["sequence"]) <= orderbook.sequence:
            return

        print(" * * * * * * * * * * * * * * * * * * *")

        # ensure we have not missed any update
        if int(update["sequence"]) > (orderbook.sequence + 1):
            raise Exception(
                "missing orderbook update events from stream, must restart: {} vs {}".format(
                    update["sequence"], (orderbook.sequence + 1)
                )
            )

        print("updating orderbook with updates at sequence {}".format(update["sequence"]))

        # update orderbook
        orderbook.sequence = int(update["sequence"])
        for direction, levels in {"buys": update["buys"], "sells": update["sells"]}.items():
            for level in levels:
                if level["isActive"]:
                    # 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__":
    asyncio.run(main())
package main

import (
    "context"
    "fmt"
    "sort"

    "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"
    "github.com/shopspring/decimal"
)

type MapOrderbook struct {
    Sequence uint64
    Levels   map[bool]map[string]*derivativeExchangePB.PriceLevel
}

func main() {
    network := common.LoadNetwork("devnet-1", "")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        fmt.Println(err)
        panic(err)
    }

    ctx := context.Background()
    marketIds := []string{"0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"}
    stream, err := exchangeClient.StreamDerivativeOrderbookUpdate(ctx, marketIds)
    if err != nil {
        fmt.Println(err)
        panic(err)
    }

    updatesCh := make(chan *derivativeExchangePB.OrderbookLevelUpdates, 100000)
    receiving := make(chan struct{})
    var receivingClosed bool

    // stream orderbook price levels
    go func() {
        defer close(updatesCh)
        for {
            select {
            case <-ctx.Done():
                return
            default:
                res, err := stream.Recv()
                if err != nil {
                    fmt.Println(err)
                    return
                }
                u := res.OrderbookLevelUpdates
                if !receivingClosed {
                    fmt.Println("receiving updates from stream")
                    close(receiving)
                    receivingClosed = true
                }
                updatesCh <- u
            }
        }
    }()

    // ensure we are receiving updates before getting orderbook
    fmt.Println("waiting for streaming updates")
    <-receiving

    // prepare orderbooks map
    orderbooks := map[string]*MapOrderbook{}
    res, err := exchangeClient.GetDerivativeOrderbooksV2(ctx, marketIds)
    if err != nil {
        panic(err)
    }
    for _, ob := range res.Orderbooks {
        // init inner maps not ready
        _, ok := orderbooks[ob.MarketId]
        if !ok {
            orderbook := &MapOrderbook{
                Sequence: ob.Orderbook.Sequence,
                Levels:   make(map[bool]map[string]*derivativeExchangePB.PriceLevel),
            }
            orderbook.Levels[true] = make(map[string]*derivativeExchangePB.PriceLevel)
            orderbook.Levels[false] = make(map[string]*derivativeExchangePB.PriceLevel)
            orderbooks[ob.MarketId] = orderbook
        }

        for _, level := range ob.Orderbook.Buys {
            orderbooks[ob.MarketId].Levels[true][level.Price] = level
        }
        for _, level := range ob.Orderbook.Sells {
            orderbooks[ob.MarketId].Levels[false][level.Price] = level
        }
    }

    // continuously consume level updates and maintain orderbook
    skippedPastEvents := false
    for {
        updates, ok := <-updatesCh
        if !ok {
            fmt.Println("updates channel closed, must restart")
            return // closed
        }

        // validate orderbook
        orderbook, ok := orderbooks[updates.MarketId]
        if !ok {
            panic("level update doesn't belong to any orderbooks")
        }

        // skip if update sequence <= orderbook sequence until it's ready to consume
        if !skippedPastEvents {
            if orderbook.Sequence >= updates.Sequence {
                continue
            }
            skippedPastEvents = true
        }

        // panic if update sequence > orderbook sequence + 1
        if updates.Sequence > orderbook.Sequence+1 {
            fmt.Printf("skipping levels: update sequence %d vs orderbook sequence %d\n", updates.Sequence, orderbook.Sequence)
            panic("missing orderbook update events from stream, must restart")
        }

        // update orderbook map
        orderbook.Sequence = updates.Sequence
        for isBuy, update := range map[bool][]*derivativeExchangePB.PriceLevelUpdate{
            true:  updates.Buys,
            false: updates.Sells,
        } {
            for _, level := range update {
                if level.IsActive {
                    // upsert
                    orderbook.Levels[isBuy][level.Price] = &derivativeExchangePB.PriceLevel{
                        Price:     level.Price,
                        Quantity:  level.Quantity,
                        Timestamp: level.Timestamp,
                    }
                } else {
                    // remove inactive level
                    delete(orderbook.Levels[isBuy], level.Price)
                }
            }
        }

        // construct orderbook arrays
        sells, buys := maintainOrderbook(orderbook.Levels)
        fmt.Println("after", orderbook.Sequence, len(sells), len(buys))

        if len(sells) > 0 && len(buys) > 0 {
            // assert orderbook
            topBuyPrice := decimal.RequireFromString(buys[0].Price)
            lowestSellPrice := decimal.RequireFromString(sells[0].Price)
            if topBuyPrice.GreaterThanOrEqual(lowestSellPrice) {
                panic(fmt.Errorf("crossed orderbook, must restart: buy %s >= %s sell", topBuyPrice, lowestSellPrice))
            }
        }

        res, _ = exchangeClient.GetDerivativeOrderbooksV2(ctx, marketIds)
        fmt.Println("query", res.Orderbooks[0].Orderbook.Sequence, len(res.Orderbooks[0].Orderbook.Sells), len(res.Orderbooks[0].Orderbook.Buys))

        // print orderbook
        fmt.Println(" [SELLS] ========")
        for _, s := range sells {
            fmt.Println(s)
        }
        fmt.Println(" [BUYS] ========")
        for _, b := range buys {
            fmt.Println(b)
        }
        fmt.Println("=======================================================")
    }
}

func maintainOrderbook(orderbook map[bool]map[string]*derivativeExchangePB.PriceLevel) (buys, sells []*derivativeExchangePB.PriceLevel) {
    for _, v := range orderbook[false] {
        sells = append(sells, v)
    }
    for _, v := range orderbook[true] {
        buys = append(buys, v)
    }

    sort.Slice(sells, func(i, j int) bool {
        return decimal.RequireFromString(sells[i].Price).LessThan(decimal.RequireFromString(sells[j].Price))
    })
    sort.Slice(buys, func(i, j int) bool {
        return decimal.RequireFromString(buys[i].Price).GreaterThan(decimal.RequireFromString(buys[j].Price))
    })

    return sells, buys
}
Parameter Type Description Required
market_ids String Array List of market IDs for orderbook streaming; empty means all derivative markets Yes
callback Function Function receiving one parameter (a stream event JSON dictionary) to process each new event Yes
on_end_callback Function Function with the logic to execute when the stream connection is interrupted No
on_status_callback Function Function receiving one parameter (the exception) with the logic to execute when an exception happens No

Response Parameters

Streaming Response Example:

* * * * * * * * * * * * * * * * * * *
updating orderbook with updates at sequence 589
Max buy: 10000000000 - Min sell: 50000000000
sells
price: 101000000000 | quantity: 0.0007 | timestamp: 1675291761230
price: 100000000000 | quantity: 0.0037 | timestamp: 1675291786816
price: 70000000000 | quantity: 0.0001 | timestamp: 1671787246665
price: 65111000000 | quantity: 0.0449 | timestamp: 1675291786816
price: 50000000000 | quantity: 0.1 | timestamp: 1676326399734
=========
buys
price: 10000000000 | quantity: 0.0004 | timestamp: 1676622014694
price: 5000000000 | quantity: 0.0097 | timestamp: 1676383776468
price: 1000000000 | quantity: 0.0013 | timestamp: 1676622213616
====================================
* * * * * * * * * * * * * * * * * * *
updating orderbook with updates at sequence 590
Max buy: 10000000000 - Min sell: 50000000000
sells
price: 101000000000 | quantity: 0.0007 | timestamp: 1675291761230
price: 100000000000 | quantity: 0.0037 | timestamp: 1675291786816
price: 70000000000 | quantity: 0.0001 | timestamp: 1671787246665
price: 65111000000 | quantity: 0.0449 | timestamp: 1675291786816
price: 50000000000 | quantity: 0.1 | timestamp: 1676326399734
=========
buys
price: 10000000000 | quantity: 0.0004 | timestamp: 1676622014694
price: 5000000000 | quantity: 0.0097 | timestamp: 1676383776468
price: 1000000000 | quantity: 0.0014 | timestamp: 1676622220695
====================================

Parameter Type Description
orderbook_level_updates OrderbookLevelUpdates Orderbook level updates of a derivative 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 the derivative orders of a specific subaccount.

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
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 = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    skip = 1
    limit = 2
    pagination = PaginationOption(skip=skip, limit=limit)
    orders = await client.fetch_subaccount_orders_list(
        subaccount_id=subaccount_id, market_id=market_id, pagination=pagination
    )
    print(orders)


if __name__ == "__main__":
    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", "k8s")
    network := common.LoadNetwork("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketId := "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"
    subaccountId := "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
    skip := uint64(0)
    limit := int32(10)

    req := derivativeExchangePB.SubaccountOrdersListRequest{
        MarketId:     marketId,
        SubaccountId: subaccountId,
        Skip:         skip,
        Limit:        limit,
    }

    res, err := exchangeClient.GetSubaccountDerivativeOrdersList(ctx, &req)
    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
Parameter Type Description Required
subaccount_id String Filter by subaccount ID Yes
market_id String Filter by market ID No
pagination PaginationOption Pagination configuration No

Response Parameters

Response Example:

{
   "orders":[
      {
         "orderHash":"0x0a3db65baf5d253b10e6f42e606a95503f72e920176b94e31ee802acde53ec84",
         "orderSide":"buy",
         "marketId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
         "subaccountId":"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
         "margin":"10107500",
         "price":"10107500",
         "quantity":"1",
         "unfilledQuantity":"1",
         "triggerPrice":"0",
         "feeRecipient":"inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8",
         "state":"booked",
         "createdAt":"1699794939298",
         "updatedAt":"1699794939298",
         "orderType":"buy",
         "txHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
         "isReduceOnly":false,
         "orderNumber":"0",
         "isConditional":false,
         "triggerAt":"0",
         "placedOrderHash":"",
         "executionType":"",
         "cid":""
      }
   ],
   "paging":{
      "total":"2",
      "from":2,
      "to":2,
      "countBySubaccount":"0",
      "next":[

      ]
   }
}
{
 "orders": [
  {
   "order_hash": "0x8af0b619d31acda68d04b8a14e1488eee3c28792ded6fbb7393a489a4a8dbb58",
   "order_side": "buy",
   "market_id": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
   "subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
   "margin": "36000000000",
   "price": "36000000000",
   "quantity": "1",
   "unfilled_quantity": "1",
   "trigger_price": "0",
   "fee_recipient": "inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8",
   "state": "booked",
   "created_at": 1652792829016,
   "updated_at": 1652792829016
  },
  {
   "order_hash": "0x457aadf92c40e5b2c4c7e6c3176872e72f36e11e7d4e718222b94a08a35ab071",
   "order_side": "buy",
   "market_id": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
   "subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
   "margin": "155000000",
   "price": "31000000000",
   "quantity": "0.01",
   "unfilled_quantity": "0.01",
   "trigger_price": "0",
   "fee_recipient": "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
   "state": "booked",
   "created_at": 1652701438661,
   "updated_at": 1652701438661
  }
 ]
}
Parameter Type Description
orders DerivativeLimitOrder Array List of derivative orders
paging Paging Pagination of results

DerivativeLimitOrder

Parameter Type Description
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"])
market_id String The market ID
subaccount_id String The subaccount ID this order belongs to
is_reduce_only Boolean True if the order is a reduce-only order
margin String Margin of the order
price String Price of the order
quantity String Quantity of the order
unfilled_quantity String The amount of the quantity remaining unfilled
trigger_price String The price that triggers stop/take orders
fee_recipient String Fee recipient address
state String Order state (Should be one of: ["booked", "partial_filled", "filled", "canceled"])
created_at Integer Order created timestamp in UNIX millis
updated_at Integer Order updated timestamp in UNIX millis
order_number Integer Order number of subaccount
order_type String Order type (Should be one of: ["buy", "sell", "stop_buy", "stop_sell", "take_buy", "take_sell", "buy_po", "sell_po"])
is_conditional Boolean If the order is conditional
trigger_at Integer Trigger timestamp, only exists for conditional orders
placed_order_hash String OrderHash of order that is triggered by this conditional order
execution_type String Execution type of conditional order
tx_hash String Transaction hash in which the order was created (not all orders have this value)
cid String Identifier for the order specified by the user (up to 36 characters, like a UUID)

SubaccountTradesList

Get the derivative trades for a specific subaccount.

IP rate limit group: indexer

*Trade execution types

  1. "market" for market orders
  2. "limitFill" for a resting limit order getting filled by a market order
  3. "limitMatchRestingOrder" for a resting limit order getting matched with another new limit order
  4. "limitMatchNewOrder" for a new limit order getting matched immediately

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
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 = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    execution_type = "market"
    direction = "sell"
    skip = 10
    limit = 2
    pagination = PaginationOption(skip=skip, limit=limit)
    trades = await client.fetch_derivative_subaccount_trades_list(
        subaccount_id=subaccount_id,
        market_id=market_id,
        execution_type=execution_type,
        direction=direction,
        pagination=pagination,
    )
    print(trades)


if __name__ == "__main__":
    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", "k8s")
    network := common.LoadNetwork("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketId := "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"
    subaccountId := "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
    skip := uint64(0)
    limit := int32(10)

    req := derivativeExchangePB.SubaccountTradesListRequest{
        MarketId:     marketId,
        SubaccountId: subaccountId,
        Skip:         skip,
        Limit:        limit,
    }

    res, err := exchangeClient.GetSubaccountDerivativeTradesList(ctx, &req)
    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
Parameter Type Description Required
subaccount_id String Subaccount ID of trader to get trades from Yes
market_id String Filter by Market ID No
execution_type String Filter by the *execution type of the trades (Should be one of: ["market", "limitFill", "limitMatchRestingOrder", "limitMatchNewOrder"]) No
direction String Filter by the direction of the trades (Should be one of: ["buy", "sell"]) No
pagination PaginationOption Pagination configuration No

Response Parameters

Response Example:

{
   "trades":[
      {
         "orderHash":"0x19da3923ce9141a9cfdb644d4ac72e0650e0e938c244ca9a55d100011fedc25e",
         "subaccountId":"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
         "marketId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
         "tradeExecutionType":"market",
         "positionDelta":{
            "tradeDirection":"sell",
            "executionPrice":"16945600",
            "executionQuantity":"4",
            "executionMargin":"67443600"
         },
         "payout":"0",
         "fee":"47447.68",
         "executedAt":"1699795360671",
         "feeRecipient":"inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8",
         "tradeId":"18321280_201_0",
         "executionSide":"taker",
         "isLiquidation":false,
         "cid":""
      },
      {
         "orderHash":"0xe9c8a307d353d09f11f616c9b3ee7be890512ceca9da7d8e3a62411607afc9af",
         "subaccountId":"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
         "marketId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
         "tradeExecutionType":"limitFill",
         "positionDelta":{
            "tradeDirection":"buy",
            "executionPrice":"16945600",
            "executionQuantity":"4",
            "executionMargin":"67782400"
         },
         "payout":"68143885.714285714285714287",
         "fee":"-4066.944",
         "executedAt":"1699795360671",
         "feeRecipient":"inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8",
         "tradeId":"18321280_202_0",
         "executionSide":"maker",
         "isLiquidation":false,
         "cid":""
      }
   ]
}
{
 "trades": [
  {
   "order_hash": "0xb131b0a095a8e72ad2fe0897001dbf6277f7ee9b8da868a9eedf9814e181da82",
   "subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
   "market_id": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
   "trade_execution_type": "market",
   "position_delta": {
    "trade_direction": "buy",
    "execution_price": "42710340000",
    "execution_quantity": "0.15",
    "execution_margin": "0"
   },
   "payout": "1105814219.16406340684465003",
   "fee": "7687861.2",
   "executed_at": 1652793510591,
   "fee_recipient": "inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8"
  },
  {
   "order_hash": "0xa049d9b5950b5a4a3a1560503ab22e191ad3f03d211629359cbdc844e8a05d91",
   "subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
   "market_id": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
   "trade_execution_type": "market",
   "position_delta": {
    "trade_direction": "sell",
    "execution_price": "38221371000",
    "execution_quantity": "1",
    "execution_margin": "37732000000"
   },
   "payout": "0",
   "fee": "45865645.2",
   "executed_at": 1651491831613,
   "fee_recipient": "inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8"
  }
 ]
}

Parameter Type Description
trades DerivativeTrade Array List of derivative market trades

DerivativeTrade

Parameter Type Description
order_hash String The order hash
subaccount_id String ID of subaccount that executed the trade
market_id String The market ID
trade_execution_type String *Execution type of the trade (Should be one of: ["market", "limitFill", "limitMatchRestingOrder", "limitMatchNewOrder"])
is_liquidation Boolean True if the trade is a liquidation
position_delta PositionDelta Position delta from the trade
payout String The payout associated with the trade
fee String The fee associated with 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"])
cid String Custom client order id

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

FundingPayments

Get the funding payments for a subaccount.

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    market_ids = ["0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"]
    subaccount_id = "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000"
    skip = 0
    limit = 3
    end_time = 1676426400125
    pagination = PaginationOption(skip=skip, limit=limit, end_time=end_time)
    funding_payments = await client.fetch_funding_payments(
        market_ids=market_ids, subaccount_id=subaccount_id, pagination=pagination
    )
    print(funding_payments)


if __name__ == "__main__":
    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", "k8s")
    network := common.LoadNetwork("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketId := "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"
    subaccountId := "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"

    req := derivativeExchangePB.FundingPaymentsRequest{
        MarketId:     marketId,
        SubaccountId: subaccountId,
    }

    res, err := exchangeClient.GetDerivativeFundingPayments(ctx, &req)
    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
Parameter Type Description Required
market_ids String Array Filter by multiple market IDs No
subaccount_id String Subaccount ID of the trader we want to get the positions from No
pagination PaginationOption Pagination configuration No

Response Parameters

Response Example:

{
   "payments":[
      {
         "marketId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
         "subaccountId":"0x00509ed903475672121d6a1fb2c646eef4da6c44000000000000000000000000",
         "amount":"1.628605",
         "timestamp":"1702000801389"
      },
      {
         "marketId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
         "subaccountId":"0x0000040f1111c5c3d2037940658ee770bb37e0a2000000000000000000000000",
         "amount":"-0.005036",
         "timestamp":"1702000801389"
      },
      {
         "marketId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
         "subaccountId":"0x0000007c60fab7a70c2ae0ebe437f3726b05e7eb000000000000000000000000",
         "amount":"-0.006378",
         "timestamp":"1702000801389"
      }
   ],
   "paging":{
      "total":"1000",
      "from":0,
      "to":0,
      "countBySubaccount":"0",
      "next":[

      ]
   }
}
{
 "payments": [
  {
   "market_id": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
   "subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
   "amount": "9904406.085347",
   "timestamp": 1652511601035
  },
  {
   "market_id": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
   "subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
   "amount": "5811676.298013",
   "timestamp": 1652508000824
  },
  {
   "market_id": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
   "subaccount_id": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
   "amount": "6834858.744846",
   "timestamp": 1652504401219
  }
 ]
}

Parameter Type Description
payments FundingPayment Array List of funding payments
paging Paging Pagination of results

FundingPayment

Parameter Type Description
market_id String The market ID
subaccount_id String The subaccount ID
amount String The amount of the funding payment
timestamp Integer Operation timestamp in UNIX millis

Paging

Parameter Type Description
total Integer Total number of records available

FundingRates

Get the historical funding rates for a specific market.

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    skip = 0
    limit = 3
    end_time = 1675717201465
    pagination = PaginationOption(skip=skip, limit=limit, end_time=end_time)
    funding_rates = await client.fetch_funding_rates(market_id=market_id, pagination=pagination)
    print(funding_rates)


if __name__ == "__main__":
    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", "k8s")
    network := common.LoadNetwork("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketId := "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"

    req := derivativeExchangePB.FundingRatesRequest{
        MarketId: marketId,
    }

    res, err := exchangeClient.GetDerivativeFundingRates(ctx, &req)
    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
Parameter Type Description Required
market_id String ID of the market to get funding rates for Yes
pagination PaginationOption Pagination configuration No

Response Parameters

Response Example:

{
   "fundingRates":[
      {
         "marketId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
         "rate":"0.000004",
         "timestamp":"1702000801389"
      },
      {
         "marketId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
         "rate":"0.000004",
         "timestamp":"1701997200816"
      },
      {
         "marketId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
         "rate":"0.000004",
         "timestamp":"1701993600737"
      }
   ],
   "paging":{
      "total":"5571",
      "from":0,
      "to":0,
      "countBySubaccount":"0",
      "next":[

      ]
   }
}
{
 "funding_rates": [
  {
   "market_id": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
   "rate": "0.000142",
   "timestamp": 1652508000824
  },
  {
   "market_id": "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
   "rate": "0.000167",
   "timestamp": 1652504401219
  }
 ]
}
Parameter Type Description
funding_rates FundingRate Array List of funding rates
paging Paging Pagination of results

FundingRate

Parameter Type Description
market_id String The derivative market ID
rate String Value of the funding rate
timestamp Integer Timestamp of funding rate in UNIX millis

Paging

Parameter Type Description
total Integer Total number of records available

BinaryOptionsMarket

Get details of a single binary options market.

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    market_id = "0x175513943b8677368d138e57bcd6bef53170a0da192e7eaa8c2cd4509b54f8db"
    market = await client.fetch_binary_options_market(market_id=market_id)
    print(market)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
Parameter Type Description Required
market_id String ID of the binary options market to fetch Yes

Response Parameters

Response Example:

{
  "market": {
    "marketId": "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
    "marketStatus": "active",
    "ticker": "INJ/USDT BO",
    "oracleSymbol": "inj",
    "oracleProvider": "BANDIBC",
    "oracleType": "provider",
    "oracleScaleFactor": 6,
    "expirationTimestamp": "2343242423",
    "settlementTimestamp": "2342342323",
    "quoteDenom": "USDT",
    "quoteTokenMeta": {
      "name": "Tether",
      "address": '0xdAC17F958D2ee523a2206206994597C13D831ec7',
      "symbol": "USDT",
      "logo": "https://static.alchemyapi.io/images/assets/7278.png",
      "decimals": 18;
      "updatedAt": "1650978921846"
    },
    "makerFeeRate": "0.001",
    "takerFeeRate": "0.002",
    "serviceProviderFee": "0.4",
    "minPriceTickSize": "0.000000000000001",
    "minQuantityTickSize": "1000000000000000",
    "settlementPrice": "1",
    "min_notional": "0"
  }
}

Parameter Type Description
market BinaryOptionsMarketInfo Info about a particular binary options market

BinaryOptionsMarketInfo

Parameter Type Description
market_id String The market ID
market_status String The status of the market (Should be one of: ["active", "paused", "suspended", "demolished", "expired"])
ticker String The name of the binary options market
oracle_symbol String Oracle symbol
oracle_provider String Oracle provider
oracle_type String Oracle Type
oracle_scale_factor Integer Scaling multiple to scale oracle prices to the correct number of decimals
expiration_timestamp Integer Defines the expiration time for the market in UNIX seconds
settlement_timestamp Integer Defines the settlement time for the market in UNIX seconds
quote_denom String Coin denom used for the quote asset
quoteTokenMeta TokenMeta Token metadata for quote 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
taker_fee_rate String Defines the fee percentage takers pay (in quote asset) when trading
service_provider_fee String Percentage of the transaction fee shared with the service provider
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
settlement_price String Defines the settlement price of the market
min_notional String Defines the minimum required notional for an order to be accepted

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

BinaryOptionsMarkets

Get a list of binary options markets.

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio

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"
    quote_denom = "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7"
    market = await client.fetch_binary_options_markets(market_status=market_status, quote_denom=quote_denom)

    print(market)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
Parameter Type Description Required
market_status String Filter by the 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
pagination PaginationOption Pagination configuration No

Response Parameters

Response Example:

{
   "markets":[
      {
         "marketId":"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
         "marketStatus":"active",
         "ticker":"INJ/USDT BO",
         "oracleSymbol":"inj",
         "oracleProvider":"BANDIBC",
         "oracleType":"provider",
         "oracleScaleFactor":6,
         "expirationTimestamp":"2343242423",
         "settlementTimestamp":"2342342323",
         "quoteDenom":"USDT",
         "quoteTokenMeta":{
            "name":"Tether",
            "address":"0xdAC17F958D2ee523a2206206994597C13D831ec7",
            "symbol":"USDT",
            "logo":"https://static.alchemyapi.io/images/assets/7278.png",
            "decimals":18;"updatedAt":"1650978921846"
         },
         "makerFeeRate":"0.001",
         "takerFeeRate":"0.002",
         "serviceProviderFee":"0.4",
         "minPriceTickSize":"0.000000000000001",
         "minQuantityTickSize":"1000000000000000",
         "settlementPrice":"1",
         "min_notional":"0",
      }
   ],
   "paging":{
      "total":"5"
      "from":"1"
      "to":"3"
      "countBySubaccount":"4"
   }
}

Parameter Type Description
market BinaryOptionsMarketInfo Array List of binary options markets and associated info
paging Paging Pagination of results

BinaryOptionsMarketInfo

Parameter Type Description
market_id String The market ID
market_status String The status of the market (Should be one of: ["active", "paused", "suspended", "demolished", "expired"])
ticker String The name of the binary options market
oracle_symbol String Oracle symbol
oracle_provider String Oracle provider
oracle_type String Oracle Type
oracle_scale_factor Integer Scaling multiple to scale oracle prices to the correct number of decimals
expiration_timestamp Integer Defines the expiration time for the market in UNIX seconds
settlement_timestamp Integer Defines the settlement time for the market in UNIX seconds
quote_denom String Coin denom used for the quote asset
quoteTokenMeta TokenMeta Token metadata for quote 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
taker_fee_rate String Defines the fee percentage takers pay (in quote asset) when trading
service_provider_fee String Percentage of the transaction fee shared with the service provider
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
settlement_price String Defines the settlement price of the market
min_notional String Defines the minimum required notional for an order to be accepted

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

Paging

Parameter Type Description
total Integer Total number of available records

- InjectiveOracleRPC

InjectiveOracleRPC defines the gRPC API of the Exchange Oracle provider.

OracleList

Get a list of all oracles.

IP rate limit group: indexer

Request Example:

import asyncio

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)
    oracle_list = await client.fetch_oracle_list()
    print(oracle_list)


if __name__ == "__main__":
    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")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    res, err := exchangeClient.GetOracleList(ctx)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}

Response Parameters

Response Example:

{
   "oracles":[
      {
         "symbol":"BTC",
         "oracleType":"bandibc",
         "price":"16835.93",
         "baseSymbol":"",
         "quoteSymbol":""
      },
      {
         "symbol":"ETH",
         "oracleType":"bandibc",
         "price":"1251.335",
         "baseSymbol":"",
         "quoteSymbol":""
      },
      {
         "symbol":"INJ",
         "oracleType":"bandibc",
         "price":"1.368087992",
         "baseSymbol":"",
         "quoteSymbol":""
      },
      {
         "symbol":"USDT",
         "oracleType":"bandibc",
         "price":"0.999785552",
         "baseSymbol":"",
         "quoteSymbol":""
      },
      {
         "symbol":"FRNT/USDT",
         "baseSymbol":"FRNT",
         "quoteSymbol":"USDT",
         "oracleType":"pricefeed",
         "price":"0.5"
      },
      {
         "symbol":"0xb327d9cf0ecd793a175fa70ac8d2dc109d4462758e556962c4a87b02ec4f3f15",
         "baseSymbol":"0xb327d9cf0ecd793a175fa70ac8d2dc109d4462758e556962c4a87b02ec4f3f15",
         "quoteSymbol":"0xb327d9cf0ecd793a175fa70ac8d2dc109d4462758e556962c4a87b02ec4f3f15",
         "oracleType":"pyth",
         "price":"7.33638432"
      },
      {
         "symbol":"0xecf553770d9b10965f8fb64771e93f5690a182edc32be4a3236e0caaa6e0581a",
         "baseSymbol":"0xecf553770d9b10965f8fb64771e93f5690a182edc32be4a3236e0caaa6e0581a",
         "quoteSymbol":"0xecf553770d9b10965f8fb64771e93f5690a182edc32be4a3236e0caaa6e0581a",
         "oracleType":"pyth",
         "price":"225.28704062"
      }
   ]
}
{
 "oracles": [
  {
   "symbol": "ANC",
   "oracle_type": "bandibc",
   "price": "2.212642692"
  },
  {
   "symbol": "ATOM",
   "oracle_type": "bandibc",
   "price": "24.706861402"
  },
  {
   "symbol": "ZRX",
   "oracle_type": "coinbase",
   "price": "0.9797"
  }
 ]
}
Parameter Type Description
oracles Oracle Array List of oracles

Oracle

Parameter Type Description
symbol String The symbol of the oracle asset
base_symbol String Oracle base currency
quote_symbol String Oracle quote currency. If no quote symbol is returned, USD is the default.
oracle_base String Oracle base currency
price String The price of the asset

Price

Get the oracle price of an asset.

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio

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 = (await client.all_derivative_markets())[
        "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    ]

    base_symbol = market.oracle_base
    quote_symbol = market.oracle_quote
    oracle_type = market.oracle_type

    oracle_prices = await client.fetch_oracle_price(
        base_symbol=base_symbol,
        quote_symbol=quote_symbol,
        oracle_type=oracle_type,
    )
    print(oracle_prices)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"

    "github.com/InjectiveLabs/sdk-go/client/common"
    exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketsAssistant, err := chainclient.NewMarketsAssistantInitializedFromChain(ctx, exchangeClient)
    market := marketsAssistant.AllDerivativeMarkets()["0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"]

    baseSymbol := market.OracleBase
    quoteSymbol := market.OracleQuote
    oracleType := market.OracleType
    oracleScaleFactor := uint32(0)
    res, err := exchangeClient.GetPrice(ctx, baseSymbol, quoteSymbol, oracleType, oracleScaleFactor)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
Parameter Type Description Required
base_symbol String Oracle base currency Yes
quote_symbol String Oracle quote currency Yes
oracle_type String The oracle provider Yes
oracle_scale_factor Integer Oracle scale factor for the quote asset Yes

Response Parameters

Response Example:

{ "price": '1.368087992' }
{
 "price": "40128736026.4094317665"
}
Parameter Type Description
price String The price of the oracle asset

StreamPrices

Stream new price changes for a specified oracle. If no oracles are provided, all price changes are streamed.

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio
from typing import Any, Dict

from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def price_event_processor(event: Dict[str, Any]):
    print(event)


def stream_error_processor(exception: RpcError):
    print(f"There was an error listening to oracle prices updates ({exception})")


def stream_closed_processor():
    print("The oracle prices updates stream has been closed")


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    market = (await client.all_derivative_markets())[
        "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    ]

    base_symbol = market.oracle_base
    quote_symbol = market.oracle_quote
    oracle_type = market.oracle_type

    task = asyncio.get_event_loop().create_task(
        client.listen_oracle_prices_updates(
            callback=price_event_processor,
            on_end_callback=stream_closed_processor,
            on_status_callback=stream_error_processor,
            base_symbol=base_symbol,
            quote_symbol=quote_symbol,
            oracle_type=oracle_type,
        )
    )

    await asyncio.sleep(delay=60)
    task.cancel()


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"

    "github.com/InjectiveLabs/sdk-go/client/common"
    exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketsAssistant, err := chainclient.NewMarketsAssistantInitializedFromChain(ctx, exchangeClient)
    market := marketsAssistant.AllDerivativeMarkets()["0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"]

    baseSymbol := market.OracleBase
    quoteSymbol := market.OracleQuote
    oracleType := market.OracleType
    stream, err := exchangeClient.StreamPrices(ctx, baseSymbol, quoteSymbol, oracleType)
    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))
        }
    }
}
Parameter Type Description Required
base_symbol String Oracle base currency No
quote_symbol String Oracle quote currency No
oracle_type String The oracle provider No
callback Function Function receiving one parameter (a stream event JSON dictionary) to process each new event Yes
on_end_callback Function Function with the logic to execute when the stream connection is interrupted No
on_status_callback Function Function receiving one parameter (the exception) with the logic to execute when an exception happens No

Response Parameters

Streaming Response Example:

{
   "price":"1.3683814386627584",
   "timestamp":"1702043286264"
}
{
 "price": "40128.7360264094317665",
 "timestamp": 1653038843915
}
Parameter Type Description
price String The price of the oracle asset
timestamp Integer Operation timestamp in UNIX millis.

- InjectiveInsuranceRPC

InjectiveInsuranceRPC defines the gRPC API of the Insurance Exchange provider.

InsuranceFunds

List all the insurance funds.

IP rate limit group: indexer

Request Example:

import asyncio

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)
    insurance_funds = await client.fetch_insurance_funds()
    print(insurance_funds)


if __name__ == "__main__":
    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"
    insurancePB "github.com/InjectiveLabs/sdk-go/exchange/insurance_rpc/pb"
)

func main() {
    // network := common.LoadNetwork("mainnet", "k8s")
    network := common.LoadNetwork("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    req := insurancePB.FundsRequest{}

    res, err := exchangeClient.GetInsuranceFunds(ctx, &req)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}

Response Parameters

Response Example:

{
   "funds":[
      {
         "marketTicker":"BTC/USDT PERP",
         "marketId":"0x90e662193fa29a3a7e6c07be4407c94833e762d9ee82136a2cc712d6b87d7de3",
         "depositDenom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
         "poolTokenDenom":"share1",
         "redemptionNoticePeriodDuration":"1209600",
         "balance":"3825059708",
         "totalShare":"1000000000000000000",
         "oracleBase":"BTC",
         "oracleQuote":"USDT",
         "oracleType":"bandibc",
         "expiry":"0"
      },
      {
         "marketTicker":"ETH/USDT PERP",
         "marketId":"0xd5e4b12b19ecf176e4e14b42944731c27677819d2ed93be4104ad7025529c7ff",
         "depositDenom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
         "poolTokenDenom":"share2",
         "redemptionNoticePeriodDuration":"1209600",
         "balance":"723501080000",
         "totalShare":"7235010800000000000",
         "oracleBase":"ETH",
         "oracleQuote":"USDT",
         "oracleType":"bandibc",
         "expiry":"0"
      }
   ]
}
{
 "funds": [
  {
   "market_ticker": "OSMO/UST PERP",
   "market_id": "0x8c7fd5e6a7f49d840512a43d95389a78e60ebaf0cde1af86b26a785eb23b3be5",
   "deposit_denom": "ibc/B448C0CA358B958301D328CCDC5D5AD642FC30A6D3AE106FF721DB315F3DDE5C",
   "pool_token_denom": "share19",
   "redemption_notice_period_duration": 1209600,
   "balance": "1000000",
   "total_share": "1000000000000000000",
   "oracle_base": "OSMO",
   "oracle_quote": "UST",
   "oracle_type": "bandibc"
  }
 ]
}
Parameter Type Description
funds InsuranceFund Array List of all insurance funds, including default and all funded accounts

InsuranceFund

Parameter Type Description
oracle_type String The oracle provider
pool_token_denom String Denom of the pool token for the given fund
total_share String Total number of shares in the fund
balance String The total balance of the fund
oracle_base String Oracle base currency
market_id String ID of the derivative market
market_ticker String Ticker of the derivative market
oracle_quote String Oracle quote currency
redemption_notice_period_duration Integer The minimum notice period duration that must pass after an underwriter sends a redemption request before underwriter can claim tokens
deposit_denom String Denom of the coin used to underwrite the insurance fund
expiry Integer Insurance fund expiry time, if any (usually 0 for perp markets)
deposit_token_meta TokenMeta Token metadata for the deposit asset, only for Ethereum-based assets

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

Redemptions

Get a list of redemptions. If no parameters are provided, redemptions for all pools and addresses will be returned.

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio

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)
    redeemer = "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku"
    redemption_denom = "share4"
    status = "disbursed"
    insurance_redemptions = await client.fetch_redemptions(address=redeemer, denom=redemption_denom, status=status)
    print(insurance_redemptions)


if __name__ == "__main__":
    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"
    insurancePB "github.com/InjectiveLabs/sdk-go/exchange/insurance_rpc/pb"
)

func main() {
    // network := common.LoadNetwork("mainnet", "k8s")
    network := common.LoadNetwork("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    req := insurancePB.RedemptionsRequest{}

    res, err := exchangeClient.GetRedemptions(ctx, &req)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
Parameter Type Description Required
address String Filter by address of the redeemer No
denom String Filter by denom of the insurance pool token No
status String Filter by redemption status (Should be one of: ["disbursed", "pending"]) No

Response Parameters

Response Example:

{
   "redemptionSchedules":[
      {
         "redemptionId":"1",
         "status":"disbursed",
         "redeemer":"inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
         "claimableRedemptionTime":"1674798129093000",
         "redemptionAmount":"500000000000000000",
         "redemptionDenom":"share4",
         "requestedAt":"1673588529093000",
         "disbursedAmount":"5000000",
         "disbursedDenom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
         "disbursedAt":"1674798130965000"
      },
      {
         "redemptionId":"2",
         "status":"disbursed",
         "redeemer":"inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
         "claimableRedemptionTime":"1674798342397000",
         "redemptionAmount":"2000000000000000000",
         "redemptionDenom":"share4",
         "requestedAt":"1673588742397000",
         "disbursedAmount":"20000000",
         "disbursedDenom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
         "disbursedAt":"1674798343097000"
      }
   ]
}
{
 "redemption_schedules": [
  {
   "redemption_id": 1,
   "status": "pending",
   "redeemer": "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
   "claimable_redemption_time": 1654247935923000,
   "redemption_amount": "1000000000000000000",
   "redemption_denom": "share19",
   "requested_at": 1653038335923000
  }
 ]
}
Parameter Type Description
redemption_schedules RedemptionSchedule Array List of redemption schedules

RedemptionSchedule

Parameter Type Description
claimable_redemption_time Integer Claimable redemption time in seconds
redeemer String Account address of the redeemer
redemption_denom String Pool token denom being redeemed
requested_at Integer Redemption request time in unix milliseconds
status String Status of the redemption (Should be one of: ["disbursed", "pending"])
redemption_amount String Amount of pool tokens being redeemed
redemption_id Integer ID of the redemption
disbursed_amount String Amount of quote tokens disbursed
disbursed_at Integer Redemption disbursement time in unix milliseconds
disbursed_denom String Denom of the quote tokens disbursed

- InjectiveAuctionRPC

InjectiveAuctionRPC defines the gRPC API of the Auction provider.

Auction

Get the details of a specific auction.

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio

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)
    bid_round = 31
    auction = await client.fetch_auction(round=bid_round)
    print(auction)


if __name__ == "__main__":
    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("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    round := int64(35)
    res, err := exchangeClient.GetAuction(ctx, round)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
roundIntegerThe auction round number, -1 for latestYes

Response Parameters

Response Example:

{
   "auction":{
      "winner":"inj1uyk56r3xdcf60jwrmn7p9rgla9dc4gam56ajrq",
      "basket":[
         {
            "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
            "amount":"2322098"
         }
      ],
      "winningBidAmount":"2000000000000000000",
      "round":"31",
      "endTimestamp":"1676013187000",
      "updatedAt":"1677075140258"
   },
   "bids":[
      {
         "bidder":"inj1pdxq82m20fzkjn2th2mm5jp7t5ex6j6klf9cs5",
         "amount":"1000000000000000000",
         "timestamp":"1675426622603"
      },
      {
         "bidder":"inj1tu9xwxms5dvz3782tjal0fy5rput78p3k5sfv6",
         "amount":"1010000000000000000",
         "timestamp":"1675427580363"
      },
      {
         "bidder":"inj1sdkt803zwq2tpej0k2a0z58hwyrnerzfsxj356",
         "amount":"1030000000000000000",
         "timestamp":"1675482275821"
      },
      {
         "bidder":"inj1uyk56r3xdcf60jwrmn7p9rgla9dc4gam56ajrq",
         "amount":"2000000000000000000",
         "timestamp":"1675595586380"
      }
   ]
}
{
 "auction": {
  "basket": [
   {
    "denom": "ibc/B448C0CA358B958301D328CCDC5D5AD642FC30A6D3AE106FF721DB315F3DDE5C",
    "amount": "20541163349"
   },
   {
    "denom": "peggy0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
    "amount": "3736040925000000"
   },
   {
    "denom": "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7",
    "amount": "383119139180"
   }
  ],
  "round": 13534,
  "end_timestamp": 1650635285000,
  "updated_at": 1650978958302
 }
}
ParameterTypeDescription
auctionAuctionAuction details
bidsBid ArrayAuction's bids


Auction

ParameterTypeDescription
winnerStringAccount Injective address
basketCoin ArrayCoins in the basket
winning_bid_amountStringAmount of the highest bid (in INJ)
roundIntegerThe auction round number
end_timestampIntegerAuction end timestamp in UNIX milliseconds
updated_atIntegerThe timestamp of the last update in UNIX milliseconds


Bid

ParameterTypeDescription
bidderStringBidder account Injective address
amountStringThe bid amount
timestampIntegerBid timestamp in UNIX millis


Coin

ParameterTypeDescription
denomStringToken denom
amountStringToken amount

Auctions

Get the details of previous auctions.

IP rate limit group: indexer

Request Example:

import asyncio

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)
    auctions = await client.fetch_auctions()
    print(auctions)


if __name__ == "__main__":
    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("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    res, err := exchangeClient.GetAuctions(ctx)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}

No parameters

Response Parameters

Response Example:

{
   "auctions":[
      {
         "basket":[
            {
               "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
               "amount":"188940000"
            }
         ],
         "round":"1",
         "endTimestamp":"1657869187000",
         "updatedAt":"1658131202118",
         "winner":"",
         "winningBidAmount":""
      },
      {
         "basket":[
            {
               "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
               "amount":"219025410"
            }
         ],
         "round":"2",
         "endTimestamp":"1658473987000",
         "updatedAt":"1658134858904",
         "winner":"",
         "winningBidAmount":""
      },
      ...
      {
         "winner":"inj1rk9fguz9zjwtqm3t6e9fzp7n9dd7jfhaw9dcc4",
         "basket":[
            {
               "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
               "amount":"1066722260002"
            }
         ],
         "winningBidAmount":"3007530000000000000000",
         "round":"73",
         "endTimestamp":"1701414787000",
         "updatedAt":"1700809987278"
      },
      {
         "basket":[
            {
               "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
               "amount":"1137356301548"
            },
            {
               "denom":"peggy0xf9152067989BDc8783fF586624124C05A529A5D1",
               "amount":"128519416"
            }
         ],
         "round":"74",
         "endTimestamp":"1702019587000",
         "updatedAt":"1701414788278",
         "winner":"",
         "winningBidAmount":""
      }
   ]
}
{
 "auctions": [
  {
   "basket": [
    {
     "denom": "ibc/B448C0CA358B958301D328CCDC5D5AD642FC30A6D3AE106FF721DB315F3DDE5C",
     "amount": "20541163349"
    },
    {
     "denom": "peggy0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
     "amount": "3736040925000000"
    },
    {
     "denom": "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7",
     "amount": "383119139180"
    }
   ],
   "round": 13435,
   "end_timestamp": 1650575885000,
   "updated_at": 1650978931464
  },
  {
   "basket": [
    {
     "denom": "ibc/B448C0CA358B958301D328CCDC5D5AD642FC30A6D3AE106FF721DB315F3DDE5C",
     "amount": "20541163349"
    },
    {
     "denom": "peggy0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
     "amount": "3736040925000000"
    },
    {
     "denom": "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7",
     "amount": "383119139180"
    }
   ],
   "round": 13436,
   "end_timestamp": 1650576485000,
   "updated_at": 1650978931847
  }
 ]
}
ParameterTypeDescription
auctionsAuction ArrayList of auctions


ParameterTypeDescription
winnerStringAccount Injective address
basketCoin ArrayCoins in the basket
winning_bid_amountStringAmount of the highest bid (in INJ)
roundIntegerThe auction round number
end_timestampIntegerAuction end timestamp in UNIX milliseconds
updated_atIntegerThe timestamp of the last update in UNIX milliseconds


Coin

ParameterTypeDescription
denomStringToken denom
amountStringToken amount

StreamBids

Stream live updates for auction bids.

IP rate limit group: indexer

Request Example:

import asyncio
from typing import Any, Dict

from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def bid_event_processor(event: Dict[str, Any]):
    print(event)


def stream_error_processor(exception: RpcError):
    print(f"There was an error listening to bids updates ({exception})")


def stream_closed_processor():
    print("The bids updates stream has been closed")


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)

    task = asyncio.get_event_loop().create_task(
        client.listen_bids_updates(
            callback=bid_event_processor,
            on_end_callback=stream_closed_processor,
            on_status_callback=stream_error_processor,
        )
    )

    await asyncio.sleep(delay=60)
    task.cancel()


if __name__ == "__main__":
    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("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    stream, err := exchangeClient.StreamBids(ctx)
    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))
        }
    }
}

No parameters

Response Parameters

Response Example:

{
  "bidder": "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
  "bidAmount": "1000000000000000000",
  "round": 19532,
  "timestamp": 1654233511715
}
{
  "bidder": "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
  "bidAmount": "3000000000000000000",
  "round": 19532,
  "timestamp": 1654233530633
}
{
 "bidder": "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
 "bid_amount": "1000000000000000000",
 "round": 17539,
 "timestamp": 1653038036697
}{
 "bidder": "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
 "bid_amount": "2000000000000000000",
 "round": 17539,
 "timestamp": 1653038046359
}
ParameterTypeDescription
bidderStringThe bidder Injective address
bid_amountStringThe bid amount (in INJ)
roundIntegerThe auction round number
timestampIntegerBid timestamp in UNIX milliseconds

- InjectiveExplorerRPC

InjectiveExplorerRPC defines the gRPC API of the Explorer provider.

GetTxByHash

Get the details for a specific transaction.

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.composer import Composer
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    composer = Composer(network=network.string())
    tx_hash = "0F3EBEC1882E1EEAC5B7BDD836E976250F1CD072B79485877CEACCB92ACDDF52"
    transaction_response = await client.fetch_tx_by_tx_hash(tx_hash=tx_hash)
    print(transaction_response)

    transaction_messages = composer.unpack_transaction_messages(transaction_data=transaction_response["data"])
    print(transaction_messages)
    first_message = transaction_messages[0]
    print(first_message)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client/common"
    explorerclient "github.com/InjectiveLabs/sdk-go/client/explorer"
)

func main() {
    network := common.LoadNetwork("mainnet", "sentry")
    explorerClient, err := explorerclient.NewExplorerClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    hash := "E5DCF04CC670A0567F58683409F7DAFC49754278DAAD507FE6EB40DFBFD71830"
    res, err := explorerClient.GetTxByTxHash(ctx, hash)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
Parameter Type Description Required
tx_hash String The transaction hash Yes

Response Parameters

Response Example:

{
   "s":"ok",
   "data":{
      "blockNumber":"5024371",
      "blockTimestamp":"2022-11-14 13:16:18.946 +0000 UTC",
      "hash":"0x0f3ebec1882e1eeac5b7bdd836e976250f1cd072b79485877ceaccb92acddf52",
      "data":"CoQBCjwvaW5qZWN0aXZlLmV4Y2hhbmdlLnYxYmV0YTEuTXNnQ3JlYXRlQmluYXJ5T3B0aW9uc0xpbWl0T3JkZXISRApCMHhmMWQ5MWZiNWI5MGRjYjU3MzczODVlNGIyZDUxMWY3YWZjMmE0MGRkMDNiZWRkMjdjYmM4Nzc3MmIwZjZlMzgy",
      "gasWanted":"123364",
      "gasUsed":"120511",
      "gasFee":{
         "amount":[
            {
               "denom":"inj",
               "amount":"61682000000000"
            }
         ],
         "gasLimit":"123364",
         "payer":"inj174mewc3hc96t7cngep545eju9ksdcfvx6d3jqq",
         "granter":""
      },
      "txType":"injective",
      "messages":"W3sidHlwZSI6Ii9pbmplY3RpdmUuZXhjaGFuZ2UudjFiZXRhMS5Nc2dDcmVhdGVCaW5hcnlPcHRpb25zTGltaXRPcmRlciIsInZhbHVlIjp7Im9yZGVyIjp7Im9yZGVyX3R5cGUiOiJTRUxMIiwibWFyZ2luIjoiOTk5OTk5NDAwMDAuMDAwMDAwMDAwMDAwMDAwMDAwIiwidHJpZ2dlcl9wcmljZSI6IjAuMDAwMDAwMDAwMDAwMDAwMDAwIiwibWFya2V0X2lkIjoiMHhjMGM5ODU4MWJhZjkzNzQwZTBkNTdhYWUyZTM2YWVjMjYyODUyMzQxYTY4MTgxYzkzODhjOWZiYmU3NTY3ZmYxIiwib3JkZXJfaW5mbyI6eyJmZWVfcmVjaXBpZW50IjoiaW5qMTc0bWV3YzNoYzk2dDdjbmdlcDU0NWVqdTlrc2RjZnZ4NmQzanFxIiwicHJpY2UiOiI1MzAwMDAuMDAwMDAwMDAwMDAwMDAwMDAwIiwicXVhbnRpdHkiOiIxMDAwMDAuMDAwMDAwMDAwMDAwMDAwMDAwIiwic3ViYWNjb3VudF9pZCI6IjB4ZjU3Nzk3NjIzN2MxNzRiZjYyNjhjODY5NWE2NjVjMmRhMGRjMjU4NjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMSJ9fSwic2VuZGVyIjoiaW5qMTc0bWV3YzNoYzk2dDdjbmdlcDU0NWVqdTlrc2RjZnZ4NmQzanFxIn19XQ==",
      "signatures":[
         {
            "pubkey":"injvalcons174mewc3hc96t7cngep545eju9ksdcfvxechtd9",
            "address":"inj174mewc3hc96t7cngep545eju9ksdcfvx6d3jqq",
            "sequence":"283962",
            "signature":"pqXQlPRK8aMEZg2GyW0aotlYcz82iX+FDYNtgkq/9P1e59QYcdyGT/DNV4INLQVXkMwNHUcbKti0dEurzQT6Tw=="
         }
      ],
      "txNumber":"635946",
      "blockUnixTimestamp":"1668431778946",
      "logs":"W3siZXZlbnRzIjpbeyJhdHRyaWJ1dGVzIjpbeyJrZXkiOiJhY3Rpb24iLCJ2YWx1ZSI6Ii9pbmplY3RpdmUuZXhjaGFuZ2UudjFiZXRhMS5Nc2dDcmVhdGVCaW5hcnlPcHRpb25zTGltaXRPcmRlciJ9XSwidHlwZSI6Im1lc3NhZ2UifV19XQ==",
      "id":"",
      "code":0,
      "info":"",
      "codespace":"",
      "events":[

      ],
      "memo":"",
      "errorLog":"",
      "claimIds":[

      ]
   },
   "errmsg":""
}

[
   {
      "type":"/injective.exchange.v1beta1.MsgCreateBinaryOptionsLimitOrder",
      "value":{
         "sender":"inj174mewc3hc96t7cngep545eju9ksdcfvx6d3jqq",
         "order":{
            "marketId":"0xc0c98581baf93740e0d57aae2e36aec262852341a68181c9388c9fbbe7567ff1",
            "orderInfo":{
               "subaccountId":"0xf577976237c174bf6268c8695a665c2da0dc2586000000000000000000000001",
               "feeRecipient":"inj174mewc3hc96t7cngep545eju9ksdcfvx6d3jqq",
               "price":"530000.000000000000000000",
               "quantity":"100000.000000000000000000",
               "cid":""
            },
            "orderType":"SELL",
            "margin":"99999940000.000000000000000000",
            "triggerPrice":"0.000000000000000000"
         }
      }
   }
]

{
   "type":"/injective.exchange.v1beta1.MsgCreateBinaryOptionsLimitOrder",
   "value":{
      "sender":"inj174mewc3hc96t7cngep545eju9ksdcfvx6d3jqq",
      "order":{
         "marketId":"0xc0c98581baf93740e0d57aae2e36aec262852341a68181c9388c9fbbe7567ff1",
         "orderInfo":{
            "subaccountId":"0xf577976237c174bf6268c8695a665c2da0dc2586000000000000000000000001",
            "feeRecipient":"inj174mewc3hc96t7cngep545eju9ksdcfvx6d3jqq",
            "price":"530000.000000000000000000",
            "quantity":"100000.000000000000000000",
            "cid":""
         },
         "orderType":"SELL",
         "margin":"99999940000.000000000000000000",
         "triggerPrice":"0.000000000000000000"
      }
   }
}
{
 "block_number": 4362066,
 "block_timestamp": "2022-04-25 09:27:48.303 +0000 UTC",
 "hash": "0x4893b36b1b2d7a0a94973cda1a6eaabf32c43e9c51b629bbdee6a46891c8a63c",
 "data": "CnsKMy9pbmplY3RpdmUuZXhjaGFuZ2UudjFiZXRhMS5Nc2dDcmVhdGVTcG90TGltaXRPcmRlchJECkIweDIzNGU3YTAzMzlmOTUzZGEyNDMxMTFlOTlhNDg2NTZiOGI5ODM5NGY3ZGJiNTNkZTNlY2QwYWZmMGQ0NTI4ZmI=",
 "gas_wanted": 121770,
 "gas_used": 115359,
 "gas_fee": {
  "amount": [
   {
    "denom": "inj",
    "amount": "60885000000000"
   }
  ],
  "gas_limit": 121770,
  "payer": "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
 },
 "tx_type": "injective",
 "messages": "[{\"type\":\"/injective.exchange.v1beta1.MsgCreateSpotLimitOrder\",\"value\":{\"order\":{\"market_id\":\"0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0\",\"order_info\":{\"fee_recipient\":\"inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r\",\"price\":\"0.000000000007523000\",\"quantity\":\"10000000000000000.000000000000000000\",\"subaccount_id\":\"0xbdaedec95d563fb05240d6e01821008454c24c36000000000000000000000000\"},\"order_type\":\"BUY_PO\",\"trigger_price\":\"0.000000000000000000\"},\"sender\":\"inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r\"}}]",
 "signatures": [
  {
   "pubkey": "injvalcons1hkhdaj2a2clmq5jq6mspsggqs32vynpkflpeux",
   "address": "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
   "sequence": 1114,
   "signature": "Ylj8HMq6g0iwSEtMVm8xKwP6m2p9w2H/K/AeKlIeBzltKONBP2oPkdWYcQKkGimbozlxIZm4AYi3x0JGwNps+g=="
  }
 ]
}
Parameter Type Description
s String Status of the response
errmsg String Error message, if any
data TxDetailData Tx detail information

TxDetailData

Parameter Type Description
block_number Integer The block at which the transaction was executed
block_timestamp String The timestamp of the block (yyyy-MM-dd HH:mm:ss.SSS ZZZZ zzz, e.g. 2022-11-14 13:16:18.946 +0000 UTC)
hash String The transaction hash
data bytes The raw data in bytes
gas_wanted Integer The gas wanted for this transaction
gas_used Integer The gas used for this transaction
gas_fee GasFee Gas fee information
tx_type String The transaction type
messages String The messages included in this transaction
signatures Signatures Array List of signatures
tx_number Integer Monotonic index of the tx in database
block_unix_timestamp Integer The timestamp of the block in UNIX millis

GasFee

Parameter Type Description
amount CosmosCoin Array List of coins with denom and amount
gas_limit Integer The gas limit for the transaction
payer String The Injective Chain address paying the gas fee
granter String Address of granter of the tx

CosmosCoin

Parameter Type Description
denom String Coin denom
amount String Coin amount

Signatures

Parameter Type Description
pubkey String The public key of the block proposer
address String The transaction sender address
sequence Integer The sequence number of the sender's address
signature String The signature

AccountTxs

Get the details for a specific transaction.

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.composer import Composer
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    composer = Composer(network=network.string())
    address = "inj1phd706jqzd9wznkk5hgsfkrc8jqxv0kmlj0kex"
    message_type = "cosmos.bank.v1beta1.MsgSend"
    limit = 2
    pagination = PaginationOption(limit=limit)
    transactions_response = await client.fetch_account_txs(
        address=address,
        message_type=message_type,
        pagination=pagination,
    )
    print(transactions_response)
    first_transaction_messages = composer.unpack_transaction_messages(transaction_data=transactions_response["data"][0])
    print(first_transaction_messages)
    first_message = first_transaction_messages[0]
    print(first_message)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    explorerPB "github.com/InjectiveLabs/sdk-go/exchange/explorer_rpc/pb"

    "github.com/InjectiveLabs/sdk-go/client/common"
    explorerclient "github.com/InjectiveLabs/sdk-go/client/explorer"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    explorerClient, err := explorerclient.NewExplorerClient(network)
    if err != nil {
        panic(err)
    }

    address := "inj1akxycslq8cjt0uffw4rjmfm3echchptu52a2dq"
    after := uint64(14112176)

    req := explorerPB.GetAccountTxsRequest{
        After:   after,
        Address: address,
    }

    ctx := context.Background()
    res, err := explorerClient.GetAccountTxs(ctx, &req)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
Parameter Type Description Required
address String The Injective Chain address Yes
before Integer Filter transactions before a given block height No
after Integer Filter transactions after a given block height No
message_type String Filter by message type No
module String Filter by module No
from_number Integer Filter from transaction number No
to_number Integer Filter to transaction number No
status String Filter by transaction status No
pagination PaginationOption Pagination configuration No

Response Parameters

Response Example:

{
   "paging":{
      "total":"5000",
      "from":221428,
      "to":221429,
      "countBySubaccount":"0",
      "next":[

      ]
   },
   "data":[
      {
         "blockNumber":"18138926",
         "blockTimestamp":"2023-11-07 23:19:55.371 +0000 UTC",
         "hash":"0x3790ade2bea6c8605851ec89fa968adf2a2037a5ecac11ca95e99260508a3b7e",
         "data":"EiYKJC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmRSZXNwb25zZQ==",
         "gasWanted":"400000",
         "gasUsed":"93696",
         "gasFee":{
            "amount":[
               {
                  "denom":"inj",
                  "amount":"200000000000000"
               }
            ],
            "gasLimit":"400000",
            "payer":"inj1phd706jqzd9wznkk5hgsfkrc8jqxv0kmlj0kex",
            "granter":""
         },
         "txType":"injective-web3",
         "messages":"W3sidHlwZSI6Ii9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQiLCJ2YWx1ZSI6eyJmcm9tX2FkZHJlc3MiOiJpbmoxcGhkNzA2anF6ZDl3em5razVoZ3Nma3JjOGpxeHYwa21sajBrZXgiLCJ0b19hZGRyZXNzIjoiaW5qMWQ2cXg4M25oeDNhM2d4N2U2NTR4NHN1OGh1cjVzODN1ODRoMnhjIiwiYW1vdW50IjpbeyJkZW5vbSI6ImZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3dldGgiLCJhbW91bnQiOiIxMDAwMDAwMDAwMDAwMDAwMDAifV19fV0=",
         "signatures":[
            {
               "pubkey":"02c33c539e2aea9f97137e8168f6e22f57b829876823fa04b878a2b7c2010465d9",
               "address":"inj1phd706jqzd9wznkk5hgsfkrc8jqxv0kmlj0kex",
               "sequence":"223460",
               "signature":"gFXPJ5QENzq9SUHshE8g++aRLIlRCRVcOsYq+EOr3T4QgAAs5bVHf8NhugBjJP9B+AfQjQNNneHXPF9dEp4Uehs="
            }
         ],
         "txNumber":"221429",
         "blockUnixTimestamp":"1699399195371",
         "logs":"W3sibXNnX2luZGV4IjowLCJldmVudHMiOlt7InR5cGUiOiJtZXNzYWdlIiwiYXR0cmlidXRlcyI6W3sia2V5IjoiYWN0aW9uIiwidmFsdWUiOiIvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kIn0seyJrZXkiOiJzZW5kZXIiLCJ2YWx1ZSI6ImluajFwaGQ3MDZqcXpkOXd6bmtrNWhnc2ZrcmM4anF4djBrbWxqMGtleCJ9LHsia2V5IjoibW9kdWxlIiwidmFsdWUiOiJiYW5rIn1dfSx7InR5cGUiOiJjb2luX3NwZW50IiwiYXR0cmlidXRlcyI6W3sia2V5Ijoic3BlbmRlciIsInZhbHVlIjoiaW5qMXBoZDcwNmpxemQ5d3pua2s1aGdzZmtyYzhqcXh2MGttbGowa2V4In0seyJrZXkiOiJhbW91bnQiLCJ2YWx1ZSI6IjEwMDAwMDAwMDAwMDAwMDAwMGZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3dldGgifV19LHsidHlwZSI6ImNvaW5fcmVjZWl2ZWQiLCJhdHRyaWJ1dGVzIjpbeyJrZXkiOiJyZWNlaXZlciIsInZhbHVlIjoiaW5qMWQ2cXg4M25oeDNhM2d4N2U2NTR4NHN1OGh1cjVzODN1ODRoMnhjIn0seyJrZXkiOiJhbW91bnQiLCJ2YWx1ZSI6IjEwMDAwMDAwMDAwMDAwMDAwMGZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3dldGgifV19LHsidHlwZSI6InRyYW5zZmVyIiwiYXR0cmlidXRlcyI6W3sia2V5IjoicmVjaXBpZW50IiwidmFsdWUiOiJpbmoxZDZxeDgzbmh4M2EzZ3g3ZTY1NHg0c3U4aHVyNXM4M3U4NGgyeGMifSx7ImtleSI6InNlbmRlciIsInZhbHVlIjoiaW5qMXBoZDcwNmpxemQ5d3pua2s1aGdzZmtyYzhqcXh2MGttbGowa2V4In0seyJrZXkiOiJhbW91bnQiLCJ2YWx1ZSI6IjEwMDAwMDAwMDAwMDAwMDAwMGZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3dldGgifV19LHsidHlwZSI6Im1lc3NhZ2UiLCJhdHRyaWJ1dGVzIjpbeyJrZXkiOiJzZW5kZXIiLCJ2YWx1ZSI6ImluajFwaGQ3MDZqcXpkOXd6bmtrNWhnc2ZrcmM4anF4djBrbWxqMGtleCJ9XX1dfV0=",
         "id":"",
         "code":0,
         "info":"",
         "codespace":"",
         "events":[

         ],
         "memo":"",
         "errorLog":"",
         "claimIds":[

         ]
      },
      {
         "blockNumber":"18138918",
         "blockTimestamp":"2023-11-07 23:19:38.275 +0000 UTC",
         "hash":"0xd1f313b090b8698223086c081f71d9590716b83390ae18bc7e6b84b9eb7c7500",
         "data":"EiYKJC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmRSZXNwb25zZQ==",
         "gasWanted":"400000",
         "gasUsed":"93775",
         "gasFee":{
            "amount":[
               {
                  "denom":"inj",
                  "amount":"200000000000000"
               }
            ],
            "gasLimit":"400000",
            "payer":"inj1phd706jqzd9wznkk5hgsfkrc8jqxv0kmlj0kex",
            "granter":""
         },
         "txType":"injective-web3",
         "messages":"W3sidHlwZSI6Ii9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQiLCJ2YWx1ZSI6eyJmcm9tX2FkZHJlc3MiOiJpbmoxcGhkNzA2anF6ZDl3em5razVoZ3Nma3JjOGpxeHYwa21sajBrZXgiLCJ0b19hZGRyZXNzIjoiaW5qMWQ2cXg4M25oeDNhM2d4N2U2NTR4NHN1OGh1cjVzODN1ODRoMnhjIiwiYW1vdW50IjpbeyJkZW5vbSI6ImZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2F0b20iLCJhbW91bnQiOiIxMDAwMDAwMDAwMDAwMDAwMDAwIn1dfX1d",
         "signatures":[
            {
               "pubkey":"02c33c539e2aea9f97137e8168f6e22f57b829876823fa04b878a2b7c2010465d9",
               "address":"inj1phd706jqzd9wznkk5hgsfkrc8jqxv0kmlj0kex",
               "sequence":"223459",
               "signature":"3Xunour/wXJksgpgkAXC55UwSbUYYt1jpA2zgsMNbHpGucHhSJad13i+HtCXUQY5APABaKKgRC+KAD9UvlPV0Rs="
            }
         ],
         "txNumber":"221428",
         "blockUnixTimestamp":"1699399178275",
         "logs":"W3sibXNnX2luZGV4IjowLCJldmVudHMiOlt7InR5cGUiOiJtZXNzYWdlIiwiYXR0cmlidXRlcyI6W3sia2V5IjoiYWN0aW9uIiwidmFsdWUiOiIvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kIn0seyJrZXkiOiJzZW5kZXIiLCJ2YWx1ZSI6ImluajFwaGQ3MDZqcXpkOXd6bmtrNWhnc2ZrcmM4anF4djBrbWxqMGtleCJ9LHsia2V5IjoibW9kdWxlIiwidmFsdWUiOiJiYW5rIn1dfSx7InR5cGUiOiJjb2luX3NwZW50IiwiYXR0cmlidXRlcyI6W3sia2V5Ijoic3BlbmRlciIsInZhbHVlIjoiaW5qMXBoZDcwNmpxemQ5d3pua2s1aGdzZmtyYzhqcXh2MGttbGowa2V4In0seyJrZXkiOiJhbW91bnQiLCJ2YWx1ZSI6IjEwMDAwMDAwMDAwMDAwMDAwMDBmYWN0b3J5L2luajE3dnl0ZHdxY3pxejcyajY1c2F1a3Bscmt0ZDRneWZtZTVhZ2Y2Yy9hdG9tIn1dfSx7InR5cGUiOiJjb2luX3JlY2VpdmVkIiwiYXR0cmlidXRlcyI6W3sia2V5IjoicmVjZWl2ZXIiLCJ2YWx1ZSI6ImluajFkNnF4ODNuaHgzYTNneDdlNjU0eDRzdThodXI1czgzdTg0aDJ4YyJ9LHsia2V5IjoiYW1vdW50IiwidmFsdWUiOiIxMDAwMDAwMDAwMDAwMDAwMDAwZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvYXRvbSJ9XX0seyJ0eXBlIjoidHJhbnNmZXIiLCJhdHRyaWJ1dGVzIjpbeyJrZXkiOiJyZWNpcGllbnQiLCJ2YWx1ZSI6ImluajFkNnF4ODNuaHgzYTNneDdlNjU0eDRzdThodXI1czgzdTg0aDJ4YyJ9LHsia2V5Ijoic2VuZGVyIiwidmFsdWUiOiJpbmoxcGhkNzA2anF6ZDl3em5razVoZ3Nma3JjOGpxeHYwa21sajBrZXgifSx7ImtleSI6ImFtb3VudCIsInZhbHVlIjoiMTAwMDAwMDAwMDAwMDAwMDAwMGZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2F0b20ifV19LHsidHlwZSI6Im1lc3NhZ2UiLCJhdHRyaWJ1dGVzIjpbeyJrZXkiOiJzZW5kZXIiLCJ2YWx1ZSI6ImluajFwaGQ3MDZqcXpkOXd6bmtrNWhnc2ZrcmM4anF4djBrbWxqMGtleCJ9XX1dfV0=",
         "id":"",
         "code":0,
         "info":"",
         "codespace":"",
         "events":[

         ],
         "memo":"",
         "errorLog":"",
         "claimIds":[

         ]
      }
   ]
}

[
   {
      "type":"/cosmos.bank.v1beta1.MsgSend",
      "value":{
         "fromAddress":"inj1phd706jqzd9wznkk5hgsfkrc8jqxv0kmlj0kex",
         "toAddress":"inj1d6qx83nhx3a3gx7e654x4su8hur5s83u84h2xc",
         "amount":[
            {
               "denom":"factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/weth",
               "amount":"100000000000000000"
            }
         ]
      }
   }
]

{
   "type":"/cosmos.bank.v1beta1.MsgSend",
   "value":{
      "fromAddress":"inj1phd706jqzd9wznkk5hgsfkrc8jqxv0kmlj0kex",
      "toAddress":"inj1d6qx83nhx3a3gx7e654x4su8hur5s83u84h2xc",
      "amount":[
         {
            "denom":"factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/weth",
            "amount":"100000000000000000"
         }
      ]
   }
}
{
 "paging": {
  "total": 100000,
  "from": 5968747,
  "to": 5968675
 },
 "data": [
  {
   "block_number": 5968747,
   "block_timestamp": "2022-05-30 16:01:23.09 +0000 UTC",
   "hash": "0x1d5e86c296c70aa2c97b0d31d83a84fb5b7296ccc2e9887868c17a0c1c7a458f",
   "data": "CoEBCjkvaW5qZWN0aXZlLmV4Y2hhbmdlLnYxYmV0YTEuTXNnQ3JlYXRlRGVyaXZhdGl2ZUxpbWl0T3JkZXISRApCMHhmYjEwMDdmYTZiODlmOWQwZDgyODU1MWZmOThhZDRkOTgxYWZkNWQ2NzUzYzljMmU1YTNiNWZiZjYyM2YxMjgw",
   "gas_wanted": 200000,
   "gas_used": 122413,
   "gas_fee": {
    "amount": [
     {
      "denom": "inj",
      "amount": "100000000000000"
     }
    ],
    "gas_limit": 200000,
    "payer": "inj1q4j3pkrl8jy07uf84t3l2srt345fppeeyagscf"
   },
   "tx_type": "injective-web3",
   "messages": "[{\"type\":\"/injective.exchange.v1beta1.MsgCreateDerivativeLimitOrder\",\"value\":{\"order\":{\"margin\":\"2000000.000000000000000000\",\"market_id\":\"0x9b9980167ecc3645ff1a5517886652d94a0825e54a77d2057cbbe3ebee015963\",\"order_info\":{\"fee_recipient\":\"inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8\",\"price\":\"1000000.000000000000000000\",\"quantity\":\"2.000000000000000000\",\"subaccount_id\":\"0x056510d87f3c88ff7127aae3f5406b8d68908739000000000000000000000000\"},\"order_type\":\"BUY\",\"trigger_price\":\"0.000000000000000000\"},\"sender\":\"inj1q4j3pkrl8jy07uf84t3l2srt345fppeeyagscf\"}}]",
   "signatures": [
    {
     "pubkey": "injvalcons1q4j3pkrl8jy07uf84t3l2srt345fppee8gwf4v",
     "address": "inj1q4j3pkrl8jy07uf84t3l2srt345fppeeyagscf",
     "sequence": 2,
     "signature": "kUm97awCT/j5RrHR3pIUvU/pOp+qYC2RnYm3tyPpdLdwFIXAFHCzX94htDc0LQxFKT7by08VCOyifTpZJJ9UaRs="
    }
   ]
  },
  {
   "block_number": 5968725,
   "block_timestamp": "2022-05-30 16:00:40.386 +0000 UTC",
   "hash": "0x8d8a0995b99c7641f8e0cc0c7e779325a4c4f5c3a738d1878ee2970c9f7e6f36",
   "data": "CoEBCjkvaW5qZWN0aXZlLmV4Y2hhbmdlLnYxYmV0YTEuTXNnQ3JlYXRlRGVyaXZhdGl2ZUxpbWl0T3JkZXISRApCMHgxZDE4Yzc4ZGYwMTAzZTg4NGZmZjdiZGU5OGIyMjgxNDQ3NDFmODA5NWE2NDY2OGZlNzc2MTEwNmQ1NDNkYWI1",
   "gas_wanted": 200000,
   "gas_used": 122263,
   "gas_fee": {
    "amount": [
     {
      "denom": "inj",
      "amount": "100000000000000"
     }
    ],
    "gas_limit": 200000,
    "payer": "inj1q4j3pkrl8jy07uf84t3l2srt345fppeeyagscf"
   },
   "tx_type": "injective-web3",
   "messages": "[{\"type\":\"/injective.exchange.v1beta1.MsgCreateDerivativeLimitOrder\",\"value\":{\"order\":{\"margin\":\"3000000.000000000000000000\",\"market_id\":\"0x9b9980167ecc3645ff1a5517886652d94a0825e54a77d2057cbbe3ebee015963\",\"order_info\":{\"fee_recipient\":\"inj1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8dkncm8\",\"price\":\"3000000.000000000000000000\",\"quantity\":\"1.000000000000000000\",\"subaccount_id\":\"0x056510d87f3c88ff7127aae3f5406b8d68908739000000000000000000000000\"},\"order_type\":\"BUY\",\"trigger_price\":\"0.000000000000000000\"},\"sender\":\"inj1q4j3pkrl8jy07uf84t3l2srt345fppeeyagscf\"}}]",
   "signatures": [
    {
     "pubkey": "injvalcons1q4j3pkrl8jy07uf84t3l2srt345fppee8gwf4v",
     "address": "inj1q4j3pkrl8jy07uf84t3l2srt345fppeeyagscf",
     "sequence": 1,
     "signature": "2iFB8tsuNHcSdvYufaL/8JJ0J0D6JOwbjzRJwJueHlpgkfRbWrXU3mBYqkP324U8scBs7jNP2Wa/90KUVi1BLRw="
    }
   ]
  },
  {
   "block_number": 5968715,
   "block_timestamp": "2022-05-30 16:00:19.878 +0000 UTC",
   "hash": "0x1d584573d1df6135bb13238943b805c30c075bca9068f6fe756ba433e36bb978",
   "data": "CigKJi9pbmplY3RpdmUuZXhjaGFuZ2UudjFiZXRhMS5Nc2dEZXBvc2l0",
   "gas_wanted": 200000,
   "gas_used": 119686,
   "gas_fee": {
    "amount": [
     {
      "denom": "inj",
      "amount": "100000000000000"
     }
    ],
    "gas_limit": 200000,
    "payer": "inj1q4j3pkrl8jy07uf84t3l2srt345fppeeyagscf"
   },
   "tx_type": "injective-web3",
   "messages": "[{\"type\":\"/injective.exchange.v1beta1.MsgDeposit\",\"value\":{\"amount\":{\"amount\":\"2000000000\",\"denom\":\"peggy0xdAC17F958D2ee523a2206206994597C13D831ec7\"},\"sender\":\"inj1q4j3pkrl8jy07uf84t3l2srt345fppeeyagscf\",\"subaccount_id\":\"0x056510d87f3c88ff7127aae3f5406b8d68908739000000000000000000000000\"}}]",
   "signatures": [
    {
     "pubkey": "injvalcons1q4j3pkrl8jy07uf84t3l2srt345fppee8gwf4v",
     "address": "inj1q4j3pkrl8jy07uf84t3l2srt345fppeeyagscf",
     "signature": "QYBDtZd3hc5/blM3DEk2MU64DsexOVQxMhDjbC+m5W4S1VM18DxbqN4fWfyr756jQNDAiAxAugXIaBgyDykfkRw="
    }
   ]
  },
  {
   "block_number": 5968675,
   "block_timestamp": "2022-05-30 15:59:00.706 +0000 UTC",
   "hash": "0x5f420c9e78f81e33614943834ae3913273b09b3e4b9ae6661bca0b695d6d2fde",
   "data": "Ch4KHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQKHgocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZA==",
   "gas_wanted": 400000,
   "gas_used": 126714,
   "gas_fee": {
    "amount": [
     {
      "denom": "inj",
      "amount": "200000000000000"
     }
    ],
    "gas_limit": 400000,
    "payer": "inj1pmau7c2ll72l0p58vdchzd39dvacfln50n7e9r"
   },
   "tx_type": "injective-web3",
   "messages": "[{\"type\":\"/cosmos.bank.v1beta1.MsgSend\",\"value\":{\"amount\":[{\"amount\":\"10000000000000000000\",\"denom\":\"inj\"}],\"from_address\":\"inj1pmau7c2ll72l0p58vdchzd39dvacfln50n7e9r\",\"to_address\":\"inj1q4j3pkrl8jy07uf84t3l2srt345fppeeyagscf\"}},{\"type\":\"/cosmos.bank.v1beta1.MsgSend\",\"value\":{\"amount\":[{\"amount\":\"10000000000\",\"denom\":\"peggy0xdAC17F958D2ee523a2206206994597C13D831ec7\"}],\"from_address\":\"inj1pmau7c2ll72l0p58vdchzd39dvacfln50n7e9r\",\"to_address\":\"inj1q4j3pkrl8jy07uf84t3l2srt345fppeeyagscf\"}}]",
   "signatures": [
    {
     "pubkey": "injvalcons1pmau7c2ll72l0p58vdchzd39dvacfln5vxcqgx",
     "address": "inj1pmau7c2ll72l0p58vdchzd39dvacfln50n7e9r",
     "sequence": 49,
     "signature": "4gw7HI6wT/+yuCs0TeB+qh63puimW7MSGnVOmX/ywKggKIgjRIXAzJHlT8c7graA0dXXxJX1Hn5yjuMDsBHQChw="
    }
   ]
  }
 ]
}
Parameter Type Description
data TxDetailData Array TxDetailData object
paging Paging Pagination of results

Paging

Parameter Type Description
total Integer Total number of records available

Data

Parameter Type Description
block_number Integer The block at which the transaction was executed
block_timestamp String The timestamp of the block (yyyy-MM-dd HH:mm:ss.SSS ZZZZ zzz, e.g. 2022-11-14 13:16:18.946 +0000 UTC)
hash String The transaction hash
data bytes The raw data in bytes
gas_wanted Integer The gas wanted for this transaction
gas_used Integer The gas used for this transaction
gas_fee GasFee GasFee object
tx_type String The transaction type
messages String The messages included in this transaction
signatures Signatures Array List of signatures
tx_number Integer Monotonic index of the tx in database
block_unix_timestamp Integer The timestamp of the block in UNIX millis

GasFee

Parameter Type Description
amount CosmosCoin Array List of coins with denom and amount
gas_limit Integer The gas limit for the transaction
payer String The Injective Chain address paying the gas fee
granter String Address of granter of the tx

CosmosCoin

Parameter Type Description
denom String Coin denom
amount String Coin amount

Signatures

Parameter Type Description
pubkey String The public key of the block proposer
address String The transaction sender address
sequence Integer The sequence number of the sender's address
signature String The signature

Blocks

Get data for blocks.

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    limit = 2
    pagination = PaginationOption(limit=limit)
    blocks = await client.fetch_blocks(pagination=pagination)
    print(blocks)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client/common"
    explorerclient "github.com/InjectiveLabs/sdk-go/client/explorer"
)

func main() {
    network := common.LoadNetwork("mainnet", "lb")
    explorerClient, err := explorerclient.NewExplorerClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    res, err := explorerClient.GetBlocks(ctx)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
Parameter Type Description Required
before Integer Filter transactions before a given block height No
after Integer Filter transactions after a given block height No
pagination PaginationOption Pagination configuration No

Response Parameters

Response Example:

{
   "paging":{
      "total":"19388338",
      "from":19388337,
      "to":19388338,
      "countBySubaccount":"0",
      "next":[

      ]
   },
   "data":[
      {
         "height":"19388338",
         "proposer":"injvalcons1xml3ew93xmjtuf5zwpcl9jzznphte30hvdre9a",
         "moniker":"InjectiveNode2",
         "blockHash":"0x349ba348107a78e27a21aa86f7b6a7eab3cda33067872234eef5e6967fa0964c",
         "parentHash":"0x3cdbdc7eee0767651785b5ac978af2fe2162caab8596da651c3c6403284902d7",
         "timestamp":"2023-12-08 12:35:08.059 +0000 UTC",
         "numPreCommits":"0",
         "numTxs":"0",
         "txs":[

         ]
      },
      {
         "height":"19388337",
         "proposer":"injvalcons1e0rj6fuy9yn5fwm9x4vw69xyuv7kzjm8rvw5r3",
         "moniker":"InjectiveNode3",
         "blockHash":"0x275aaa7206b6272b50a7d697d2ed432a2ab51aca3bcf3a0da3009521a29b1e07",
         "parentHash":"0x44b8faece543cba46e1391e918b4f397e99461092c178149185275fff30d40bc",
         "numTxs":"1",
         "timestamp":"2023-12-08 12:35:06.749 +0000 UTC",
         "numPreCommits":"0",
         "txs":[

         ]
      }
   ]
}
{
 "paging": {
  "from": 6002843,
  "to": 6002844
 },
 "data": [
  {
   "height": 6002844,
   "proposer": "injvalcons1qmrj7lnzraref92lzuhrv6m7sxey248fzxmfnf",
   "moniker": "InjectiveNode3",
   "block_hash": "0x138f577b66db53405fd2e642223d563558dd5af85cae0c7f6bb4d5fbfa53c310",
   "parent_hash": "0x4012fcb077810c5e5d70ad2a1fbb5874dd66c194f243800db2c02b6ffcac0f4d",
   "timestamp": "2022-05-31 10:27:13.325 +0000 UTC"
  },
  {
   "height": 6002843,
   "proposer": "injvalcons1uq5z4v9jhxr3a3k5k94nxa6l8hzzqs5fcstvaa",
   "moniker": "InjectiveNode1",
   "block_hash": "0x5b04a48a7d757585af7acd28f97cd75a377e6b5e8dd807322a2b74f467a292a6",
   "parent_hash": "0x82e4d22cf5ed64aa9bce69bcb9933295d0730a3dbfafdc3f0970949934435d70",
   "timestamp": "2022-05-31 10:27:11.395 +0000 UTC"
  }
 ]
}
Parameter Type Description
data BlockInfo Block data
paging Paging Pagination of results

Paging

Parameter Type Description
total Integer Total number of records available

BlockInfo

Parameter Type Description
height Integer The block height
proposer String The block proposer
moniker String The validator moniker
block_hash String The hash of the block
parent_hash String The parent hash of the block
timestamp String The timestamp of the block (yyyy-MM-dd HH:mm:ss.SSS ZZZZ zzz, e.g. 2022-11-14 13:16:18.946 +0000 UTC)

Block

Get detailed data for a single block.

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio

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)
    block_height = "5825046"
    block = await client.fetch_block(block_id=block_height)
    print(block)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client/common"
    explorerclient "github.com/InjectiveLabs/sdk-go/client/explorer"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    explorerClient, err := explorerclient.NewExplorerClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    blockHeight := "5825046"
    res, err := explorerClient.GetBlock(ctx, blockHeight)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
Parameter Type Description Required
block_id String Block height Yes

Response Parameters

Response Example:

{
   "s":"ok",
   "data":{
      "height":"5825046",
      "proposer":"injvalcons1xml3ew93xmjtuf5zwpcl9jzznphte30hvdre9a",
      "moniker":"InjectiveNode2",
      "blockHash":"0x5982527aa7bc62d663256d505ab396e699954e46ada71a11de2a75f6e514d073",
      "parentHash":"0x439caaef7ed0c6d9c2bdd7ffcd8c7303a4eb6a7c33d7db189f85f9b3a496fbc6",
      "numTxs":"2",
      "txs":[
         {
            "blockNumber":"5825046",
            "blockTimestamp":"2022-12-11 22:06:49.182 +0000 UTC",
            "hash":"0xbe8c8ca9a41196adf59b88fe9efd78e7532e04169152e779be3dc14ba7c360d9",
            "messages":"bnVsbA==",
            "txNumber":"994979",
            "txMsgTypes":"WyIvaW5qZWN0aXZlLmV4Y2hhbmdlLnYxYmV0YTEuTXNnQ3JlYXRlQmluYXJ5T3B0aW9uc0xpbWl0T3JkZXIiXQ==",
            "id":"",
            "codespace":"",
            "errorLog":"",
            "code":0,
            "logs":"",
            "claimIds":[

            ]
         },
         {
            "blockNumber":"5825046",
            "blockTimestamp":"2022-12-11 22:06:49.182 +0000 UTC",
            "hash":"0xe46713fbedc907278b6bd22165946d8673169c1a0360383e5e31abf219290c6a",
            "messages":"bnVsbA==",
            "txNumber":"994978",
            "txMsgTypes":"WyIvaWJjLmNvcmUuY2xpZW50LnYxLk1zZ1VwZGF0ZUNsaWVudCIsIi9pYmMuY29yZS5jaGFubmVsLnYxLk1zZ1JlY3ZQYWNrZXQiXQ==",
            "id":"",
            "codespace":"",
            "errorLog":"",
            "code":0,
            "logs":"",
            "claimIds":[

            ]
         }
      ],
      "timestamp":"2022-12-11 22:06:49.182 +0000 UTC",
      "numPreCommits":"0",
      "totalTxs":"0"
   },
   "errmsg":""
}
{
 "height": 5825046,
 "proposer": "injvalcons1qmrj7lnzraref92lzuhrv6m7sxey248fzxmfnf",
 "moniker": "InjectiveNode3",
 "block_hash": "0x06453296122c4db605b68aac9e2848ea778b8fb2cdbdeb77281515722a1457cf",
 "parent_hash": "0x14cba82aa61d5ee2ddcecf8e1f0a7f0286c5ac1fe3f8c3dafa1729121152793d",
 "timestamp": "2022-05-27 10:21:51.168 +0000 UTC"
}
Parameter Type Description
s String Status of the response
errmsg String Error message, if any
data BlockDetailInfo Detailed info on the block

BlockDetailInfo

Parameter Type Description
height Integer The block height
proposer String The block proposer
moniker String The block proposer's moniker
block_hash String The hash of the block
parent_hash String The parent hash of the block
num_txs Integer Number of transactions in the block
txs TxData Array List of transactions
timestamp String The timestamp of the block (yyyy-MM-dd HH:mm:ss.SSS ZZZZ zzz, e.g. 2022-11-14 13:16:18.946 +0000 UTC)

TxData

Parameter Type Description
block_number String The block number
block_timestamp String The timestamp of the block (yyyy-MM-dd HH:mm:ss.SSS ZZZZ zzz, e.g. 2022-11-14 13:16:18.946 +0000 UTC)
hash String Transaction hash
messages bytes Messages byte data of the transaction
tx_number Integer Transaction number

Txs

Get the transactions.

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    limit = 2
    pagination = PaginationOption(limit=limit)
    txs = await client.fetch_txs(pagination=pagination)
    print(txs)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    explorerPB "github.com/InjectiveLabs/sdk-go/exchange/explorer_rpc/pb"

    "github.com/InjectiveLabs/sdk-go/client/common"
    explorerclient "github.com/InjectiveLabs/sdk-go/client/explorer"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    explorerClient, err := explorerclient.NewExplorerClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    before := uint64(7158400)

    req := explorerPB.GetTxsRequest{
        Before: before,
    }

    res, err := explorerClient.GetTxs(ctx, &req)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
Parameter Type Description Required
before Integer Filter transactions before a given block height No
after Integer Filter transactions after a given block height No
message_type String Filter by message type No
module String Filter by module No
from_number Integer Filter from transaction number No
to_number Integer Filter to transaction number No
status String Filter by transaction status No
pagination PaginationOption Pagination configuration No

Response Parameters

Response Example:

{
   "paging":{
      "total":"17748338",
      "from":17748337,
      "to":17748338,
      "countBySubaccount":"0",
      "next":[

      ]
   },
   "data":[
      {
         "blockNumber":"19388410",
         "blockTimestamp":"2023-12-08 12:37:42.632 +0000 UTC",
         "hash":"0xe9e2bd81acb24a6d04ab3eb50e5188858a63b8ec05b694c8731b2be8dc34b2d0",
         "messages":"W3sidHlwZSI6Ii9jb3Ntd2FzbS53YXNtLnYxLk1zZ0V4ZWN1dGVDb250cmFjdCIsInZhbHVlIjp7InNlbmRlciI6ImluajFmdXc4OTMyNmQ0NzlrbjR2aGd6dnRhYWY3bTJoeDltZ25nZnFhMyIsImNvbnRyYWN0IjoiaW5qMTNnOWhwbnRjdHpnaGU5Mjkzc2xlMjhxNGU0ZTVtMGdzM2hwcDBoIiwibXNnIjp7InBvc3RfZGF0YSI6eyJkYXRhIjoiQ3RFREN2MEJDZ0lJQ3hETjhTd1lscHpNcXdZaUlPMFUvUTdFSFF1VEVUSHoxcmhtK0g3MUdJdkhsTXRwRUhOVlZQTDZHbUpHS2lCdDlWcmszekdtdGI0UVY2Z3hiVmlvOUJlT3VzenRmWUhtSUlOYzRxbTFyeklnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQTZJQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQVFpQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUZJVW44bHVMWERzaHVYd2FBcm8wcjllYUNocCtRSmFJQThyemk3UXFtRng1eW8rR2tOKzk3RjIvRUZZNEVRVGVGQjdYSTFKWTg0TFlndHZjSFJwWHpFM016Z3RNUkpDQ2tBVWNraTd4K2dBMUlyNlpINnNWTWRDSWVndU9Cdm5ONVFoZVpYbU9FTWhyZG54eHl6bXpLbks0cEVuRUFFSEgvMTVnZE1HQXRIZ3BiV0N3VGtYSG5vT0dvb0JDa01LRkovSmJpMXc3SWJsOEdnSzZOSy9YbWdvYWZrQ0VpSUtJTlprU09wWUtNbldoNytFamlQWDJ5eG52d1VIRVlrdXROSjV4bU5qTmRyVEdJQ0FtcWJxcitNQkVrTUtGSi9KYmkxdzdJYmw4R2dLNk5LL1htZ29hZmtDRWlJS0lOWmtTT3BZS01uV2g3K0VqaVBYMnl4bnZ3VUhFWWt1dE5KNXhtTmpOZHJUR0lDQW1xYnFyK01CRWdBPSJ9fSwiZnVuZHMiOltdfX1d",
         "txNumber":"17748338",
         "txMsgTypes":"WyIvY29zbXdhc20ud2FzbS52MS5Nc2dFeGVjdXRlQ29udHJhY3QiXQ==",
         "logs":"W3sibXNnX2luZGV4IjowLCJldmVudHMiOlt7InR5cGUiOiJtZXNzYWdlIiwiYXR0cmlidXRlcyI6W3sia2V5IjoiYWN0aW9uIiwidmFsdWUiOiIvY29zbXdhc20ud2FzbS52MS5Nc2dFeGVjdXRlQ29udHJhY3QifSx7ImtleSI6InNlbmRlciIsInZhbHVlIjoiaW5qMWZ1dzg5MzI2ZDQ3OWtuNHZoZ3p2dGFhZjdtMmh4OW1nbmdmcWEzIn0seyJrZXkiOiJtb2R1bGUiLCJ2YWx1ZSI6Indhc20ifV19LHsidHlwZSI6ImV4ZWN1dGUiLCJhdHRyaWJ1dGVzIjpbeyJrZXkiOiJfY29udHJhY3RfYWRkcmVzcyIsInZhbHVlIjoiaW5qMTNnOWhwbnRjdHpnaGU5Mjkzc2xlMjhxNGU0ZTVtMGdzM2hwcDBoIn1dfSx7InR5cGUiOiJ3YXNtIiwiYXR0cmlidXRlcyI6W3sia2V5IjoiX2NvbnRyYWN0X2FkZHJlc3MiLCJ2YWx1ZSI6ImluajEzZzlocG50Y3R6Z2hlOTI5M3NsZTI4cTRlNGU1bTBnczNocHAwaCJ9LHsia2V5IjoibWV0aG9kIiwidmFsdWUiOiJwb3N0ZGF0YSJ9XX1dfV0=",
         "id":"",
         "codespace":"",
         "errorLog":"",
         "code":0,
         "claimIds":[

         ]
      },
      {
         "blockNumber":"19388408",
         "blockTimestamp":"2023-12-08 12:37:38.713 +0000 UTC",
         "hash":"0xd9197814915db8cfcc38743d1680764530da238304899723f5b37b49500304d3",
         "messages":"W3sidHlwZSI6Ii9jb3Ntd2FzbS53YXNtLnYxLk1zZ0V4ZWN1dGVDb250cmFjdCIsInZhbHVlIjp7InNlbmRlciI6ImluajFkZWVqYzY2dmhjcWVuNXFqdTJlZGxjOHdqczN4OTJzaHYza2F0cyIsImNvbnRyYWN0IjoiaW5qMThybGZscDM3MzVoMjVqbWp4OTdkMjJjNzJzeGsyNjBhbWRqeGx1IiwibXNnIjp7InVwZGF0ZV9wcmljZV9mZWVkcyI6eyJkYXRhIjpbIlVFNUJWUUVBQUFBQW9BRUFBQUFBQVFDK3FzR3JqcjdzeXVmS3l3VDN6dllvcXRyVzc3cXZlSFFIbDl3V3hhU3RMRVJaS1liS2Q2UE45clNReW5OU1ZkbGVIdkRJaWh2d2lrYnhCY2o2bkxSb0FXVnpEaEVBQUFBQUFCcmhBZnJ0ckZoUjR5dWJJN1g1UVJxTUs2eEtyajdVM1h1QkhkR25McVNxY1FBQUFBQUNhNVRJQVVGVlYxWUFBQUFBQUFiYjlqUUFBQ2NRNmRhVWViTjRsM25SWmtyZlZVayt6Z0poQ3VrT0FGVUEvbVVQQTJmVXArK1lGYVdUNmhYVFpaUHdaRHFxOEJTYnNFdm1lcmhSM3MwQUFBQUJ0TXJCaHdBQUFBQUFNdFZtLy8vLytBQUFBQUJsY3c0UkFBQUFBR1Z6RGc4QUFBQUJzU2Q5cUFBQUFBQUFPNEpiQ21Gbzh0UGlWbTl5WkFkVUxNUUROZzRVNmV1ZXhHMklqdVlia1VTdlo2ZWhIbStQTlpXNXIxSTZFeHFURGFZNWJTREtpSWYyZHZBRWN6NXAwcEdTTEJzQm0yRHhZZVFKTkRXaTZ5U3VFTXp1MGViL0M4SHR6NjJwbkZDd00vUEFzcVFXM3UxRC9GUDAwcDBMRldKL1FSQjRMQ1pnK09Bb09DM2FTODFBUElqajU0TkpEdm9aMC9vTU5ucTlhdE5qV2dQWUhvaERDNUpZaWtzM3ZCM1MrMzNwK0daM1VVcC8yK3pKTjVCUVBTQTJQbFpCZXpuMEFseG8yM1IvcjQ3bCt4czJ2YnNXajFxa0FGVUFIOEdJWVNNaWtDSVVZU0lMMU9LczBkemZ2SW5JUUpMSlBCaTl4M1ZzRllnQUFBQUFCZllLTndBQUFBQUFBRlloLy8vLytBQUFBQUJsY3c0UkFBQUFBR1Z6RGc4QUFBQUFCZllYY3dBQUFBQUFBR05wQ24wRnd6c1lTem54aEtYc2JhQWhDd2phYTVhTHU4bVhKL2xtQWlJV050d2lnc1BWd09KN0hKb0VZWkpXb0ZxTTVoRVZvdmtDWWF5NG5jMFFqK2N3WkJHWmdGbmlYTGdEVjU3dEZHeE0rWWFMTkE5YWpTV2lLb0sxemVxUjN2TGpLMkIxSVgweHYwQVVTL0FVWURIYmREcDFYRzJyM1dveExzZlV4QVgrMnJ0UEVYN0syWEZkNFlHSUpvc21laXIxSThBZ3owUlp6c2JMZlo1ZHdwWWs1bStrRUVFN0l3SHllYXI0UTlub2orLzI0OVVBZmpuMEFseG8yM1IvcjQ3bCt4czJ2YnNXajFxa0FGVUErY0FYSzZFTitrMFpDSTJVOWI5aDA3Vk5XOWRJT2pJcW1DNFRjKzZPb3hzQUFBUDVhSU9ib1FBQUFBQmF1WVlwLy8vLytBQUFBQUJsY3c0UkFBQUFBR1Z6RGc4QUFBUDBZWjdLWUFBQUFBQlBSM1dlQ2dOdE94cWZPdFZOTXNwdm1NT0NZclB4MnBOSkpxVVJvdVYzalZKejdjNXY3QktTeVNxVWJtOVVUUkFOcHkrc05abnE1NVprUUVuaExTU20wckZIeXNZV0s4Rm13NVN4TFJjQUlUNXRQTnpaam5wWGR1aDJPK20vVmcwdG5RL1kxTXJ4N29sRC9GUDAwcDBMRldKL1FSQjRMQ1pnK09Bb09DM2FTODFBUElqajU0TkpEdm9aMC9vTU5ucTlhdE5qV2dQWUhvaERDNUpZaWtzM3ZCM1MrMzNwK0daM1VVcC8yK3pKTjVCUVBTQTJQbFpCZXpuMEFseG8yM1IvcjQ3bCt4czJ2YnNXajFxa0FGVUFOL1FOS0pnVm5vOHVVcms4dDQ5SHpEZ3BveDVTV3JsMXhKekZ4ZGtYWTNnQUFBQUFCdm5jR0FBQUFBQUFBT0lvLy8vLytBQUFBQUJsY3c0UkFBQUFBR1Z6RGc4QUFBQUFCdkZFWlFBQUFBQUFBUGxKQ21GaEpCK0ZMMlJka3Q0RzVNd1VZNTE4anlMQ0xEMUZTaGNUSnV0V1hSUjEwaEJFVit1N0RkNThUV1FncnlPQXpsMnQyaE1IM1dpbXFNNkZGOVkwbytGblh1K3dCcnE5ZXhWelpIRU1UcTJvM3doZjJ5bVY0aVZhbDhnNzI5MjdONGlRQkl4QnRJVDhuVkRxUERuQ3RJcVVlUEY1alpydTBPM2RZeVpxUjQwT2RGK3VtVkplUnNnZ0FEV0FlaXIxSThBZ3owUlp6c2JMZlo1ZHdwWWs1bStrRUVFN0l3SHllYXI0UTlub2orLzI0OVVBZmpuMEFseG8yM1IvcjQ3bCt4czJ2YnNXajFxa0FGVUFNS0dSV1BXbFRBcmZqN2RXQmljMFB5S2h2SVVyaWRWcjRhek54ZHY1YlE0QUFBQUFBQjcwMkFBQUFBQUFBQUJ6Ly8vLy9RQUFBQUJsY3c0UkFBQUFBR1Z6RGc4QUFBQUFBQjczV0FBQUFBQUFBQUI5Q3ZNTTI2VVlPVlBBRVBnZmMwOU0zYkthcklVdEhqVDhidU5HQms4MTQrQ1VQOGZMTjR3Vkd5dkJETzQzNC9GbnF3MENqNUhTZisrbmdhSTFLUlUvMVZaSnN5MFE2TER0eFpuRnpMK1NqVXlyd3RmV3J1V1ZkQnJBVDFFMDFYdmtnL094QlpKQnRJVDhuVkRxUERuQ3RJcVVlUEY1alpydTBPM2RZeVpxUjQwT2RGK3VtVkplUnNnZ0FEV0FlaXIxSThBZ3owUlp6c2JMZlo1ZHdwWWs1bStrRUVFN0l3SHllYXI0UTlub2orLzI0OVVBZmpuMEFseG8yM1IvcjQ3bCt4czJ2YnNXajFxa0FGVUF3YkVuYWZaak41alVXdC9XSy94d0VVZzVJeTRwU2JBZnM5UDVKOUpnWVZRQUFBQUFBQUdsT3dBQUFBQUFBQUFLLy8vLyt3QUFBQUJsY3c0UkFBQUFBR1Z6RGc4QUFBQUFBQUdsTVFBQUFBQUFBQUFLQ2lnRHd3eUo5TDRjaFNBSzZnRVZsckxkaUVQdmJhQ1owd09WUGpHNEpSeEpwMHBBY1BnbFo3YnVFQXdDd2tvN1JDVUxHRElPQ0k5aWg4ZlA4eTNzcnI0ekp6UkYycmI0MXZlM3pYeU9iRXJNVEZ1UGkvRmhtR3M5Mlh5NEV4eXZleVRrY056Mnc3OHFRMTIrckN6R0F3ejdwTjNNbnJyUVRQR0tGUnVjUU5FekF1WjBOaXVaUjd4dk8xdC9hdE5qV2dQWUhvaERDNUpZaWtzM3ZCM1MrMzNwK0daM1VVcC8yK3pKTjVCUVBTQTJQbFpCZXpuMEFseG8yM1IvcjQ3bCt4czJ2YnNXajFxa0FGVUFNaHVrMWdqNmRicDIxdGM5cW5GYXZMM3JuYm9DSlg4Rm9iV1JlTFNmV1pzQUFBQUFBQ1JIWndBQUFBQUFBQUp4Ly8vLyt3QUFBQUJsY3c0UkFBQUFBR1Z6RGc4QUFBQUFBQ1JTZndBQUFBQUFBQUgwQ3VXM0tTaW95T0dIQ0FCK3Nsc2ZKWldESWVtN0pmNlVueElLd3hRMWkrNzUwQ1lPTFFpbEJ5SnRHR3VqVGllbzlubXo4dVJsSkx1b3hEVm11eFUvMVZaSnN5MFE2TER0eFpuRnpMK1NqVXlyd3RmV3J1V1ZkQnJBVDFFMDFYdmtnL094QlpKQnRJVDhuVkRxUERuQ3RJcVVlUEY1alpydTBPM2RZeVpxUjQwT2RGK3VtVkplUnNnZ0FEV0FlaXIxSThBZ3owUlp6c2JMZlo1ZHdwWWs1bStrRUVFN0l3SHllYXI0UTlub2orLzI0OVVBZmpuMEFseG8yM1IvcjQ3bCt4czJ2YnNXajFxa0FGVUFJS2s0OVV0bzhmTHZHT29ES1BiZEIwZjQ2aEZJYlNLd0llZzZrQXZvbDNZQUFBQUFBQUl6blFBQUFBQUFBQUFJLy8vLy9RQUFBQUJsY3c0UkFBQUFBR1Z6RGc4QUFBQUFBQUl6L1FBQUFBQUFBQUFJQ2hwOEhiS1JRdnRrWUJKdzMxR1lPdjJPTUFURXU4bVhKL2xtQWlJV050d2lnc1BWd09KN0hKb0VZWkpXb0ZxTTVoRVZvdmtDWWF5NG5jMFFqK2N3WkJHWmdGbmlYTGdEVjU3dEZHeE0rWWFMTkE5YWpTV2lLb0sxemVxUjN2TGpLMkIxSVgweHYwQVVTL0FVWURIYmREcDFYRzJyM1dveExzZlV4QVgrMnJ0UEVYN0syWEZkNFlHSUpvc21laXIxSThBZ3owUlp6c2JMZlo1ZHdwWWs1bStrRUVFN0l3SHllYXI0UTlub2orLzI0OVVBZmpuMEFseG8yM1IvcjQ3bCt4czJ2YnNXajFxa0FGVUF2TDNDZFZ2WFNpQmwrZE1vUEN1S3k5aVk1SE85dVFwblpMUGIxR2ZGYnMwQUFBQUFBQUhyUUFBQUFBQUFBQUFLLy8vLyt3QUFBQUJsY3c0UkFBQUFBR1Z6RGc4QUFBQUFBQUhyVFFBQUFBQUFBQUFKQ3BySEprTUViNFk1R1EwQ0R5bktnZkxyODBYNzRXOGM3dG1FWGE3RG43WHk0SjlSeVZiYngyWElBQWRBSzRnTVlCTWNLVTNmZ0VUdEE5L0U1S1kvTWRLVERFNVhvS25ULzdaYkxZUGdxd3F1aEQ4WFNRVEVxZU1JYm9hUWRkblVMTVkzd2hiMnc3OHFRMTIrckN6R0F3ejdwTjNNbnJyUVRQR0tGUnVjUU5FekF1WjBOaXVaUjd4dk8xdC9hdE5qV2dQWUhvaERDNUpZaWtzM3ZCM1MrMzNwK0daM1VVcC8yK3pKTjVCUVBTQTJQbFpCZXpuMEFseG8yM1IvcjQ3bCt4czJ2YnNXajFxa0FGVUF5b0M2YmNNdUNOQnZHcWlHQVI3dEhYZkhlK25yZGh6QkRYSzMwS0w5VjZZQUFBQTNFZDZLc2dBQUFBQUZlOGp5Ly8vLytBQUFBQUJsY3c0UkFBQUFBR1Z6RGc4QUFBQTNBN29GWUFBQUFBQUZjbnJyQ2p3UmZsTzI3N1JXaTkxaXBEMEhIbWFzL3M0WWVEME5YNlo3Qnk3cDVhV1UzOC84ZEFsNVZFTUVsM2djeC96Mjl2ditDL2tjd05zSnlYTVFHY1Z5Z1JvOUdRcXp0cFl6MmxpRVBzcFhOR0F3dkhhekRvVkJIWHhMQ2dBT1VrWTVwUGYvc3QxQURuekVwd0hvYTlVQ29DZGhGbE5TN0d3NVhmR0tGUnVjUU5FekF1WjBOaXVaUjd4dk8xdC9hdE5qV2dQWUhvaERDNUpZaWtzM3ZCM1MrMzNwK0daM1VVcC8yK3pKTjVCUVBTQTJQbFpCZXpuMEFseG8yM1IvcjQ3bCt4czJ2YnNXajFxa0FGVUFZU0p0T2I3cUdkTTA4WHd2Njg0bjRTWkcyRVoxa2s2N0Fybk5ycWFISitNQUFBQUFQUkNMYXdBQUFBQUFDT3I4Ly8vLytBQUFBQUJsY3c0UkFBQUFBR1Z6RGc4QUFBQUFQR01hYmdBQUFBQUFDY0xZQ3I0dEhHVk9sNkh0dnpwVFlTMGNjaTdLTk5FYmxWRXlJU1lMTVpSemxhOEI2VnhOQ3FKbHZYUExZM0p3ckw4RG1NS2czNXJMVk14TWF4TE5EdkZOOHBTK2VzRjZrKy96SVc3WkxKY2l1MzE0N1NpcmpSbm42MHhhRlJYVkZWVVJycWlML1U0ZXlDTXIrWTdvRndFQ3RzS0F6OTdWNzQ4QlB6QnVtd3Fkc2d1Rnl1Q3ZJWldGTzNaVWlEMXp1dE1XYjBpYW9zK2o5SmVLeDhZRTZvQnVFRWlrRUVFN0l3SHllYXI0UTlub2orLzI0OVVBZmpuMEFseG8yM1IvcjQ3bCt4czJ2YnNXajFxa0FGVUFMWk1WcUk4d0dmanZxSTMrbkE4SVEzRXRvTHJJRkVZZUozTS9hNFByVWJNQUFBQUFkT2pNaXdBQUFBQUFKUDRCLy8vLytBQUFBQUJsY3c0UkFBQUFBR1Z6RGc4QUFBQUFjNlN1L0FBQUFBQUFJdXIzQ2hsMVJhT3BEV2k2S1VCbkozS1kwUUJ5WE5hdVlsNXV5YWpsQ0IwNlVxS29YM2h4VUFhbmdmWi83Wk1vWDlvdStEc2x5MW9hWkV3Z1ZqcVAvS3ZVeUh2QzhEcElDVU16aTNxakRab0c0ZjNoclJrQ1NjZmtiWGFybXNpOGZOVi9RUHJYN3U0eHYwQVVTL0FVWURIYmREcDFYRzJyM1dveExzZlV4QVgrMnJ0UEVYN0syWEZkNFlHSUpvc21laXIxSThBZ3owUlp6c2JMZlo1ZHdwWWs1bStrRUVFN0l3SHllYXI0UTlub2orLzI0OVVBZmpuMEFseG8yM1IvcjQ3bCt4czJ2YnNXajFxa0FGVUE3WUx2djYzZ0VJUC9xUFpHWk1ocTg1S0N5ZkNFaDNCbXJuSzJOZWQzR1BBQUFBQUFBQUE4V2dBQUFBQUFBQUJDLy8vLzlnQUFBQUJsY3c0UEFBQUFBR1Z6RGc0QUFBQUFBQUE4RkFBQUFBQUFBQUE2Q2lNOHhBaUtQUzByN2xOQnFGUVdvQUIySHN5cDArTm9vcmxKT3hJZzlMYmJOZEdMNHZUUzNZaTF6TUczOGVjSk1NM05zL1Q3OEkvS1JDajBUc3c1dWlZNlpncDROSmROMnJjSXBxekNsNVZNVkNnYUxBVHVienR3blNReDI5UDdBWU80T2RCbVhtSkF5TWg5YytwT01vWnY0dFo3ZEt3dnB5M2FTODFBUElqajU0TkpEdm9aMC9vTU5ucTlhdE5qV2dQWUhvaERDNUpZaWtzM3ZCM1MrMzNwK0daM1VVcC8yK3pKTjVCUVBTQTJQbFpCZXpuMEFseG8yM1IvcjQ3bCt4czJ2YnNXajFxa0FGVUFRZk5pV1hIS0x0SW1QbmhYUCtYT0krRTlKVmp0UHk1SHF3K0UrNTU2NXlJQUFBQUFCZlhnL3dBQUFBQUFBSFV0Ly8vLytBQUFBQUJsY3c0UkFBQUFBR1Z6RGc4QUFBQUFCZlhsakFBQUFBQUFBR3NYQ2tYVS94MUtZdEczb2VvUzVuQUlOV0tyUlBDc1R0NmVodjcxNXBSS25VZzJTTWNqbEVWdU91aklJUm5nZFpXSjlGVi9FV2hBMjdmaGZrT1pEeTZqQzUxTzlYT3cwTTByc0VlYUtWNzQ0NWFGM3doZjJ5bVY0aVZhbDhnNzI5MjdONGlRQkl4QnRJVDhuVkRxUERuQ3RJcVVlUEY1alpydTBPM2RZeVpxUjQwT2RGK3VtVkplUnNnZ0FEV0FlaXIxSThBZ3owUlp6c2JMZlo1ZHdwWWs1bStrRUVFN0l3SHllYXI0UTlub2orLzI0OVVBZmpuMEFseG8yM1IvcjQ3bCt4czJ2YnNXajFxayJdfX0sImZ1bmRzIjpbeyJkZW5vbSI6ImluaiIsImFtb3VudCI6IjE0In1dfX1d",
         "txNumber":"17748337",
         "txMsgTypes":"WyIvY29zbXdhc20ud2FzbS52MS5Nc2dFeGVjdXRlQ29udHJhY3QiXQ==",
         "logs":"W3sibXNnX2luZGV4IjowLCJldmVudHMiOlt7InR5cGUiOiJtZXNzYWdlIiwiYXR0cmlidXRlcyI6W3sia2V5IjoiYWN0aW9uIiwidmFsdWUiOiIvY29zbXdhc20ud2FzbS52MS5Nc2dFeGVjdXRlQ29udHJhY3QifSx7ImtleSI6InNlbmRlciIsInZhbHVlIjoiaW5qMWRlZWpjNjZ2aGNxZW41cWp1MmVkbGM4d2pzM3g5MnNodjNrYXRzIn0seyJrZXkiOiJtb2R1bGUiLCJ2YWx1ZSI6Indhc20ifV19LHsidHlwZSI6ImNvaW5fc3BlbnQiLCJhdHRyaWJ1dGVzIjpbeyJrZXkiOiJzcGVuZGVyIiwidmFsdWUiOiJpbmoxZGVlamM2NnZoY3FlbjVxanUyZWRsYzh3anMzeDkyc2h2M2thdHMifSx7ImtleSI6ImFtb3VudCIsInZhbHVlIjoiMTRpbmoifV19LHsidHlwZSI6ImNvaW5fcmVjZWl2ZWQiLCJhdHRyaWJ1dGVzIjpbeyJrZXkiOiJyZWNlaXZlciIsInZhbHVlIjoiaW5qMThybGZscDM3MzVoMjVqbWp4OTdkMjJjNzJzeGsyNjBhbWRqeGx1In0seyJrZXkiOiJhbW91bnQiLCJ2YWx1ZSI6IjE0aW5qIn1dfSx7InR5cGUiOiJ0cmFuc2ZlciIsImF0dHJpYnV0ZXMiOlt7ImtleSI6InJlY2lwaWVudCIsInZhbHVlIjoiaW5qMThybGZscDM3MzVoMjVqbWp4OTdkMjJjNzJzeGsyNjBhbWRqeGx1In0seyJrZXkiOiJzZW5kZXIiLCJ2YWx1ZSI6ImluajFkZWVqYzY2dmhjcWVuNXFqdTJlZGxjOHdqczN4OTJzaHYza2F0cyJ9LHsia2V5IjoiYW1vdW50IiwidmFsdWUiOiIxNGluaiJ9XX0seyJ0eXBlIjoiZXhlY3V0ZSIsImF0dHJpYnV0ZXMiOlt7ImtleSI6Il9jb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJpbmoxOHJsZmxwMzczNWgyNWptang5N2QyMmM3MnN4azI2MGFtZGp4bHUifV19LHsidHlwZSI6Indhc20iLCJhdHRyaWJ1dGVzIjpbeyJrZXkiOiJfY29udHJhY3RfYWRkcmVzcyIsInZhbHVlIjoiaW5qMThybGZscDM3MzVoMjVqbWp4OTdkMjJjNzJzeGsyNjBhbWRqeGx1In0seyJrZXkiOiJhY3Rpb24iLCJ2YWx1ZSI6InVwZGF0ZV9wcmljZV9mZWVkcyJ9LHsia2V5IjoibnVtX2F0dGVzdGF0aW9ucyIsInZhbHVlIjoiMTQifSx7ImtleSI6Im51bV91cGRhdGVkIiwidmFsdWUiOiIxNCJ9XX0seyJ0eXBlIjoiaW5qZWN0aXZlLm9yYWNsZS52MWJldGExLkV2ZW50U2V0UHl0aFByaWNlcyIsImF0dHJpYnV0ZXMiOlt7ImtleSI6InByaWNlcyIsInZhbHVlIjoiW3tcInByaWNlX2lkXCI6XCIweGZlNjUwZjAzNjdkNGE3ZWY5ODE1YTU5M2VhMTVkMzY1OTNmMDY0M2FhYWYwMTQ5YmIwNGJlNjdhYjg1MWRlY2RcIixcImVtYV9wcmljZVwiOlwiNzIuNjcxMjI2MDAwMDAwMDAwMDAwXCIsXCJlbWFfY29uZlwiOlwiMC4wMzg5OTk5NTAwMDAwMDAwMDBcIixcImNvbmZcIjpcIjAuMDMzMzE0MzAwMDAwMDAwMDAwXCIsXCJwdWJsaXNoX3RpbWVcIjpcIjE3MDIwMzkwNTdcIixcInByaWNlX3N0YXRlXCI6e1wicHJpY2VcIjpcIjczLjI4MTUzOTkxMDAwMDAwMDAwMFwiLFwiY3VtdWxhdGl2ZV9wcmljZVwiOlwiNTk1NjAyMjQ3LjEzNjEzNTY0MDAwMDAwMDAwMFwiLFwidGltZXN0YW1wXCI6XCIxNzAyMDM5MDU4XCJ9fSx7XCJwcmljZV9pZFwiOlwiMHgxZmMxODg2MTIzMjI5MDIyMTQ2MTIyMGJkNGUyYWNkMWRjZGZiYzg5Yzg0MDkyYzkzYzE4YmRjNzc1NmMxNTg4XCIsXCJlbWFfcHJpY2VcIjpcIjEuMDAwMTM5MzkwMDAwMDAwMDAwXCIsXCJlbWFfY29uZlwiOlwiMC4wMDAyNTQ0OTAwMDAwMDAwMDBcIixcImNvbmZcIjpcIjAuMDAwMjIwNDkwMDAwMDAwMDAwXCIsXCJwdWJsaXNoX3RpbWVcIjpcIjE3MDIwMzkwNTdcIixcInByaWNlX3N0YXRlXCI6e1wicHJpY2VcIjpcIjEuMDAwMTA1NTEwMDAwMDAwMDAwXCIsXCJjdW11bGF0aXZlX3ByaWNlXCI6XCIyMzIyNzc5Ni40NzU2MjQ3MzAwMDAwMDAwMDBcIixcInRpbWVzdGFtcFwiOlwiMTcwMjAzOTA1OFwifX0se1wicHJpY2VfaWRcIjpcIjB4ZjljMDE3MmJhMTBkZmE0ZDE5MDg4ZDk0ZjViZjYxZDNiNTRkNWJkNzQ4M2EzMjJhOTgyZTEzNzNlZThlYTMxYlwiLFwiZW1hX3ByaWNlXCI6XCI0MzQ4MS40NDcwMDAwMDAwMDAwMDAwMDBcIixcImVtYV9jb25mXCI6XCIxMy4zMDA4MzIzMDAwMDAwMDAwMDBcIixcImNvbmZcIjpcIjE1LjIyMTA3OTQ1MDAwMDAwMDAwMFwiLFwicHVibGlzaF90aW1lXCI6XCIxNzAyMDM5MDU3XCIsXCJwcmljZV9zdGF0ZVwiOntcInByaWNlXCI6XCI0MzY5Ny4zNTE5NTU1MzAwMDAwMDAwMDBcIixcImN1bXVsYXRpdmVfcHJpY2VcIjpcIjY4MzMwNjY2NjY4NC45NjIwNDczMjAwMDAwMDAwMDBcIixcInRpbWVzdGFtcFwiOlwiMTcwMjAzOTA1OFwifX0se1wicHJpY2VfaWRcIjpcIjB4MzdmNDBkMjg5ODE1OWU4ZjJlNTJiOTNjYjc4ZjQ3Y2MzODI5YTMxZTUyNWFiOTc1YzQ5Y2M1YzVkOTE3NjM3OFwiLFwiZW1hX3ByaWNlXCI6XCIxLjE2NDc0OTgxMDAwMDAwMDAwMFwiLFwiZW1hX2NvbmZcIjpcIjAuMDAwNjM4MTcwMDAwMDAwMDAwXCIsXCJjb25mXCI6XCIwLjAwMDU3ODk2MDAwMDAwMDAwMFwiLFwicHVibGlzaF90aW1lXCI6XCIxNzAyMDM5MDU3XCIsXCJwcmljZV9zdGF0ZVwiOntcInByaWNlXCI6XCIxLjE3MDM4MTA0MDAwMDAwMDAwMFwiLFwiY3VtdWxhdGl2ZV9wcmljZVwiOlwiMjQxNzYzMTkuNDE3NDMwMDgwMDAwMDAwMDAwXCIsXCJ0aW1lc3RhbXBcIjpcIjE3MDIwMzkwNThcIn19LHtcInByaWNlX2lkXCI6XCIweDMwYTE5MTU4ZjVhNTRjMGFkZjhmYjc1NjA2MjczNDNmMjJhMWJjODUyYjg5ZDU2YmUxYWNjZGM1ZGJmOTZkMGVcIixcImVtYV9wcmljZVwiOlwiMjAyOS40MDAwMDAwMDAwMDAwMDAwMDBcIixcImVtYV9jb25mXCI6XCIwLjEyNTAwMDAwMDAwMDAwMDAwMFwiLFwiY29uZlwiOlwiMC4xMTUwMDAwMDAwMDAwMDAwMDBcIixcInB1Ymxpc2hfdGltZVwiOlwiMTcwMjAzOTA1N1wiLFwicHJpY2Vfc3RhdGVcIjp7XCJwcmljZVwiOlwiMjAyOC43NjAwMDAwMDAwMDAwMDAwMDBcIixcImN1bXVsYXRpdmVfcHJpY2VcIjpcIjQzNzQ1MDU5NjM4LjQyMDAwMDAwMDAwMDAwMDAwMFwiLFwidGltZXN0YW1wXCI6XCIxNzAyMDM5MDU4XCJ9fSx7XCJwcmljZV9pZFwiOlwiMHhjMWIxMjc2OWY2NjMzNzk4ZDQ1YWRmZDYyYmZjNzAxMTQ4MzkyMzJlMjk0OWIwMWZiM2QzZjkyN2QyNjA2MTU0XCIsXCJlbWFfcHJpY2VcIjpcIjEuMDc4MjUwMDAwMDAwMDAwMDAwXCIsXCJlbWFfY29uZlwiOlwiMC4wMDAxMDAwMDAwMDAwMDAwMDBcIixcImNvbmZcIjpcIjAuMDAwMTAwMDAwMDAwMDAwMDAwXCIsXCJwdWJsaXNoX3RpbWVcIjpcIjE3MDIwMzkwNTdcIixcInByaWNlX3N0YXRlXCI6e1wicHJpY2VcIjpcIjEuMDc4MzUwMDAwMDAwMDAwMDAwXCIsXCJjdW11bGF0aXZlX3ByaWNlXCI6XCIyNDIzNzczMS4wNzEwMTAwMDAwMDAwMDAwMDBcIixcInRpbWVzdGFtcFwiOlwiMTcwMjAzOTA1OFwifX0se1wicHJpY2VfaWRcIjpcIjB4MzIxYmE0ZDYwOGZhNzViYTc2ZDZkNzNkYWE3MTVhYmNiZGViOWRiYTAyMjU3ZjA1YTFiNTkxNzhiNDlmNTk5YlwiLFwiZW1hX3ByaWNlXCI6XCIyMy44MDQxNTAwMDAwMDAwMDAwMDBcIixcImVtYV9jb25mXCI6XCIwLjAwNTAwMDAwMDAwMDAwMDAwMFwiLFwiY29uZlwiOlwiMC4wMDYyNTAwMDAwMDAwMDAwMDBcIixcInB1Ymxpc2hfdGltZVwiOlwiMTcwMjAzOTA1N1wiLFwicHJpY2Vfc3RhdGVcIjp7XCJwcmljZVwiOlwiMjMuNzc1NzUwMDAwMDAwMDAwMDAwXCIsXCJjdW11bGF0aXZlX3ByaWNlXCI6XCI1MjkwNjUwMTUuNTE0ODEwMDAwMDAwMDAwMDAwXCIsXCJ0aW1lc3RhbXBcIjpcIjE3MDIwMzkwNThcIn19LHtcInByaWNlX2lkXCI6XCIweDIwYTkzOGY1NGI2OGYxZjJlZjE4ZWEwMzI4ZjZkZDA3NDdmOGVhMTE0ODZkMjJiMDIxZTgzYTkwMGJlODk3NzZcIixcImVtYV9wcmljZVwiOlwiMTQ0LjM4MTAwMDAwMDAwMDAwMDAwMFwiLFwiZW1hX2NvbmZcIjpcIjAuMDA4MDAwMDAwMDAwMDAwMDAwXCIsXCJjb25mXCI6XCIwLjAwODAwMDAwMDAwMDAwMDAwMFwiLFwicHVibGlzaF90aW1lXCI6XCIxNzAyMDM5MDU3XCIsXCJwcmljZV9zdGF0ZVwiOntcInByaWNlXCI6XCIxNDQuMjg1MDAwMDAwMDAwMDAwMDAwXCIsXCJjdW11bGF0aXZlX3ByaWNlXCI6XCIzMTQ4MTY5NTYzLjY5MjAwMDAwMDAwMDAwMDAwMFwiLFwidGltZXN0YW1wXCI6XCIxNzAyMDM5MDU4XCJ9fSx7XCJwcmljZV9pZFwiOlwiMHhiY2JkYzI3NTViZDc0YTIwNjVmOWQzMjgzYzJiOGFjYmQ4OThlNDczYmRiOTBhNjc2NGIzZGJkNDY3YzU2ZWNkXCIsXCJlbWFfcHJpY2VcIjpcIjEuMjU3NzMwMDAwMDAwMDAwMDAwXCIsXCJlbWFfY29uZlwiOlwiMC4wMDAwOTAwMDAwMDAwMDAwMDBcIixcImNvbmZcIjpcIjAuMDAwMTAwMDAwMDAwMDAwMDAwXCIsXCJwdWJsaXNoX3RpbWVcIjpcIjE3MDIwMzkwNTdcIixcInByaWNlX3N0YXRlXCI6e1wicHJpY2VcIjpcIjEuMjU3NjAwMDAwMDAwMDAwMDAwXCIsXCJjdW11bGF0aXZlX3ByaWNlXCI6XCIyNzk5MTIyNS43NTQ3MDAwMDAwMDAwMDAwMDBcIixcInRpbWVzdGFtcFwiOlwiMTcwMjAzOTA1OFwifX0se1wicHJpY2VfaWRcIjpcIjB4Y2E4MGJhNmRjMzJlMDhkMDZmMWFhODg2MDExZWVkMWQ3N2M3N2JlOWViNzYxY2MxMGQ3MmI3ZDBhMmZkNTdhNlwiLFwiZW1hX3ByaWNlXCI6XCIyMzYyLjg1NzI0MDAwMDAwMDAwMDAwMFwiLFwiZW1hX2NvbmZcIjpcIjAuOTEzODg2NTEwMDAwMDAwMDAwXCIsXCJjb25mXCI6XCIwLjkxOTk4NDUwMDAwMDAwMDAwMFwiLFwicHVibGlzaF90aW1lXCI6XCIxNzAyMDM5MDU3XCIsXCJwcmljZV9zdGF0ZVwiOntcInByaWNlXCI6XCIyMzY1LjIyOTk4NDUwMDAwMDAwMDAwMFwiLFwiY3VtdWxhdGl2ZV9wcmljZVwiOlwiNDE3OTY4MDExMjEuNzk4MDYyMjEwMDAwMDAwMDAwXCIsXCJ0aW1lc3RhbXBcIjpcIjE3MDIwMzkwNThcIn19LHtcInByaWNlX2lkXCI6XCIweDYxMjI2ZDM5YmVlYTE5ZDMzNGYxN2MyZmViY2UyN2UxMjY0NmQ4NDY3NTkyNGViYjAyYjljZGFlYTY4NzI3ZTNcIixcImVtYV9wcmljZVwiOlwiMTAuMTMxMjc3OTAwMDAwMDAwMDAwXCIsXCJlbWFfY29uZlwiOlwiMC4wMDYzOTcwNDAwMDAwMDAwMDBcIixcImNvbmZcIjpcIjAuMDA1ODQ0NDQwMDAwMDAwMDAwXCIsXCJwdWJsaXNoX3RpbWVcIjpcIjE3MDIwMzkwNTdcIixcInByaWNlX3N0YXRlXCI6e1wicHJpY2VcIjpcIjEwLjI0NDk0NDQzMDAwMDAwMDAwMFwiLFwiY3VtdWxhdGl2ZV9wcmljZVwiOlwiMjEzODk1OTI4Ljc1Nzk5NTcyMDAwMDAwMDAwMFwiLFwidGltZXN0YW1wXCI6XCIxNzAyMDM5MDU4XCJ9fSx7XCJwcmljZV9pZFwiOlwiMHgyZDkzMTVhODhmMzAxOWY4ZWZhODhkZmU5YzBmMDg0MzcxMmRhMGJhYzgxNDQ2MWUyNzczM2Y2YjgzZWI1MWIzXCIsXCJlbWFfcHJpY2VcIjpcIjE5LjQwMTcyNTQwMDAwMDAwMDAwMFwiLFwiZW1hX2NvbmZcIjpcIjAuMDIyODgzNzUwMDAwMDAwMDAwXCIsXCJjb25mXCI6XCIwLjAyNDI0MzIxMDAwMDAwMDAwMFwiLFwicHVibGlzaF90aW1lXCI6XCIxNzAyMDM5MDU3XCIsXCJwcmljZV9zdGF0ZVwiOntcInByaWNlXCI6XCIxOS42MTQxMzc3MTAwMDAwMDAwMDBcIixcImN1bXVsYXRpdmVfcHJpY2VcIjpcIjE5Njk2NjI1Ni4xNTc4MjA0ODAwMDAwMDAwMDBcIixcInRpbWVzdGFtcFwiOlwiMTcwMjAzOTA1OFwifX0se1wicHJpY2VfaWRcIjpcIjB4ZWQ4MmVmYmZhZGUwMTA4M2ZmYThmNjQ2NjRjODZhZjM5MjgyYzlmMDg0ODc3MDY2YWU3MmI2MzVlNzc3MThmMFwiLFwiZW1hX3ByaWNlXCI6XCIwLjAwMDAwMTUzODAwMDAwMDAwMFwiLFwiZW1hX2NvbmZcIjpcIjAuMDAwMDAwMDA1ODAwMDAwMDAwXCIsXCJjb25mXCI6XCIwLjAwMDAwMDAwNjYwMDAwMDAwMFwiLFwicHVibGlzaF90aW1lXCI6XCIxNzAyMDM5MDU1XCIsXCJwcmljZV9zdGF0ZVwiOntcInByaWNlXCI6XCIwLjAwMDAwMTU0NTAwMDAwMDAwMFwiLFwiY3VtdWxhdGl2ZV9wcmljZVwiOlwiMjAuOTYzNzUwNDQyMjAwMDAwMDAwXCIsXCJ0aW1lc3RhbXBcIjpcIjE3MDIwMzkwNThcIn19LHtcInByaWNlX2lkXCI6XCIweDQxZjM2MjU5NzFjYTJlZDIyNjNlNzg1NzNmZTVjZTIzZTEzZDI1NThlZDNmMmU0N2FiMGY4NGZiOWU3YWU3MjJcIixcImVtYV9wcmljZVwiOlwiMS4wMDAwMTE2NDAwMDAwMDAwMDBcIixcImVtYV9jb25mXCI6XCIwLjAwMDI3NDE1MDAwMDAwMDAwMFwiLFwiY29uZlwiOlwiMC4wMDAyOTk5NzAwMDAwMDAwMDBcIixcInB1Ymxpc2hfdGltZVwiOlwiMTcwMjAzOTA1N1wiLFwicHJpY2Vfc3RhdGVcIjp7XCJwcmljZVwiOlwiMC45OTk5OTk5OTAwMDAwMDAwMDBcIixcImN1bXVsYXRpdmVfcHJpY2VcIjpcIjIzMjIyMDc2Ljg1MzYxNTM4MDAwMDAwMDAwMFwiLFwidGltZXN0YW1wXCI6XCIxNzAyMDM5MDU4XCJ9fV0ifV19XX1d",
         "id":"",
         "codespace":"",
         "errorLog":"",
         "code":0,
         "claimIds":[

         ]
      }
   ]
}
}
{
 "paging": {
  "total": 100000,
  "from": 6007200,
  "to": 6001687
 },
 "data": [
  {
   "block_number": 6007200,
   "block_timestamp": "2022-05-31 12:48:34.886 +0000 UTC",
   "hash": "0xaaf6e69819ade1b9bdc128ec84d35a0d928c46082007522f1ac80b999f62adfd",
   "data": "CjQKMi9pbmplY3RpdmUub3JhY2xlLnYxYmV0YTEuTXNnUmVsYXlDb2luYmFzZU1lc3NhZ2Vz",
   "gas_wanted": 784680,
   "gas_used": 538379,
   "gas_fee": {
    "amount": [
     {
      "denom": "inj",
      "amount": "392340000000000"
     }
    ],
    "gas_limit": 784680,
    "payer": "inj128jwakuw3wrq6ye7m4p64wrzc5rfl8tvwzc6s8"
   },
   "tx_type": "injective",
   "messages": "[{\"type\":\"/injective.oracle.v1beta1.MsgRelayCoinbaseMessages\",\"value\":{\"messages\":[\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYpYORAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1rce1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnByaWNlcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCVEMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYpYORAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHT/28gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnByaWNlcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANFVEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYpYORAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf0IgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnByaWNlcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANYVFoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYpX2mAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPQRQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnByaWNlcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANEQUkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYpYORAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACk3wgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnByaWNlcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANSRVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYpYORAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGaOoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnByaWNlcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANaUlgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYpYORAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGHVEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnByaWNlcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCQVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYpYORAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAh82gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnByaWNlcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANLTkMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYpYORAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwiJgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnByaWNlcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARMSU5LAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYpYORAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPA/6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnByaWNlcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARDT01QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYpYORAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABXleAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnByaWNlcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANVTkkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYpYORAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACWcIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnByaWNlcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANHUlQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYpYORAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv2/QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnByaWNlcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANTTlgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\"],\"sender\":\"inj128jwakuw3wrq6ye7m4p64wrzc5rfl8tvwzc6s8\",\"signatures\":[\"zCWD1dTt0tIGMPwd/8ff81HrG6nloxk6EVb1r7SOgO+c3NDRFoTqRGbQ4PwuDYAXzrTIznkiax808YeqbltB+wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc\",\"/kefMAblMcZEff6jiTRbYl0nmhSGVkCGeKBznKhQ5sldNytKBgWV7WQxGS9vbRXk/PSOgt6wHJ7ZRxdHw3LogwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAb\",\"FdnISEwJs5jBx4PQFO4snJLjc7KSZ46hWzeruHnqFcoMN9ojanwnk/vKO13rKVqUWZb7l4Oak9hWJ/rYXLi86wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAb\",\"0dWYExhIsaEL2/7xD1z2tPFbmxtXE9SRnOF/FCLsvMkenMopwQxK82oe+qK2Ts2pXVE7oFO6IyMQWCLIeVIcrQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc\",\"+UhX91gBZchuBZ21gdg6toGJEU4egivkRT5lEoh+AReN7ClIDhEKvKp/nVhEa5+zzIXY/5KCWOcGZlJ/Pfx8zgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc\",\"e1ho1uftysZdxNIg+701zAanvZxtEjSnfXynDWW7x6Wo79/mBs+KUpHzUfhlYxp8mgoOZbGCp3k5l83/4lhYwwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAb\",\"n8MD/MYj6B4u0YMiGrJOYdlQ3U6tfbOxBRptWgr6x/aLj2eKbcE5gmg6gGVas9WBvjquKAhQR8U5MhYkLbqYbwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAb\",\"txgWSFuq4x8o44kvl4I1GCryAa6gUzPTWAKWLxfp6HtzIWVoFDsiz1dFDngfaIBPo+lmvak1lEBES+I9Ai2O6wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAb\",\"BrWea8Hrzn6hd2rEZ6MYMcxUw7+a3xomj554oY4okaW8YaDFHl+Qjx83rYN/hV++I016oofLLpSQ7Un/t2gGVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAb\",\"A8Ls0YNqqj8DHofRIhkpG+KgM1qitVYyx72/8qPhi9kymmzEnWNaAnsNqBvBGvXka1e5u9bCFTmdx3lHpVe3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc\",\"QCnXDJR/47TZ9OJ0jEUxdPgp2tvbJvNUMkupmY0qE6rbrdMbbihu0oRn8q3TAzfELimrj3HuXqmi4dHjCfulVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAb\",\"oE3BN/deGTEqyXcfx+jmTjzp3uY9YPo3x8m678U6zKPTkE3eR1tnQ5tmwOOfejm7h5XzFWpnSdFylVKLBNqU1wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc\",\"+QU+45qb2cZL3jtmCtmXpUl1kROnRF0f4XiQ5sU+liRoqY/LKJDfKoy/ufqmApjGzYNuB6ccmKS2fLduARDZ0wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc\"]}}]",
   "signatures": [
    {
     "pubkey": "injvalcons128jwakuw3wrq6ye7m4p64wrzc5rfl8tvdh7raz",
     "address": "inj128jwakuw3wrq6ye7m4p64wrzc5rfl8tvwzc6s8",
     "sequence": 54715,
     "signature": "DDzBCEVmF9uNCt0kH9BSBcWYNs/D4ePWAPil/JU8FaMInn5ENSGNZ2qzPQPtnPxl63Z6pIMkeGFlxIlZo4COuAE="
    }
   ]
  },
  {
   "block_number": 6007111,
   "block_timestamp": "2022-05-31 12:45:41.945 +0000 UTC",
   "hash": "0x57d2c0dd087206f9772efdb6901b66c604d75c023d89a5c9614893e6157d1df1",
   "data": "CjQKMi9pbmplY3RpdmUub3JhY2xlLnYxYmV0YTEuTXNnUmVsYXlDb2luYmFzZU1lc3NhZ2Vz",
   "gas_wanted": 710127,
   "gas_used": 488677,
   "gas_fee": {
    "amount": [
     {
      "denom": "inj",
      "amount": "355063500000000"
     }
    ],
    "gas_limit": 710127,
    "payer": "inj128jwakuw3wrq6ye7m4p64wrzc5rfl8tvwzc6s8"
   },
   "tx_type": "injective",
   "messages": "[{\"type\":\"/injective.oracle.v1beta1.MsgRelayCoinbaseMessages\",\"value\":{\"messages\":[\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYpYNkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1oqt4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnByaWNlcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCVEMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYpYNkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHTk7UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnByaWNlcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANFVEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYpYNkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfqXgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnByaWNlcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANYVFoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYpX2mAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPQRQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnByaWNlcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANEQUkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYpYNkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAClLSgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnByaWNlcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANSRVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYpYNkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGaNIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnByaWNlcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANaUlgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYpYNVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGFSQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnByaWNlcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCQVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYpYNkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhyTgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnByaWNlcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANLTkMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYpYNkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwTgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnByaWNlcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARMSU5LAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYpYNkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO84PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnByaWNlcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARDT01QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYpYNkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABXW0gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnByaWNlcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANVTkkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYpYNkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACWDIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnByaWNlcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANHUlQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYpYNkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvrwgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnByaWNlcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANTTlgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\"],\"sender\":\"inj128jwakuw3wrq6ye7m4p64wrzc5rfl8tvwzc6s8\",\"signatures\":[\"YL231HABMdVXctipqLhc638wBgdTFpwOZAdAgPgefAjXC8Vvl65gXzw9cNRJOY0kA4vCt0g8FiF9YqdOw1jnbQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc\",\"kGtm079wAMRGGjJPT/WuLvd4M5LNTcjkIoTDI8SW6j6wwFhUYblYscAvJsqdtNxKzUB/s93g48nbfYbV+HRlrQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc\",\"LXYjHiXRC5HTKlylmfF+diCBzrAOY74yrKPNNqnN8RS+d+TKT/hx8CLGQt3QuLxlWnNg7BwucO+/TfhMauyp0wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAb\",\"0dWYExhIsaEL2/7xD1z2tPFbmxtXE9SRnOF/FCLsvMkenMopwQxK82oe+qK2Ts2pXVE7oFO6IyMQWCLIeVIcrQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc\",\"kkHcQL/fE+b4cXcTpxwL6gCiEHSx6vFapLVJ6pD+VQ5fv+FUZDj20fgMhigsA3cKa0TRhqB4VW/yeBeYeo+dtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc\",\"NgCe7fZDDgiHYKzTQGCmRvcCBO6hAtK+Lray3inBoJ2U5X102+9+hrW0843QToBG1LYHZ9kQ81DzkMNe6lKmLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAb\",\"RGiVY4JdjfVmXcIu5qcwhFwTTDl/Vi8etEMA3wGCisPqmG5x1/ibcTBqwu+bRftdaS1tR1EndDW+wsVvyJ27tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAb\",\"wvgniA1t3o6E/2t9OsqWKZq9vDlmOD8KR8/m3rjUnupQpv1fQ/b84T/FsFRezSZrfD1FUGUJZU4OpI90cvsN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc\",\"/Eks8pFIMrD64hlAwpNVmns4AwCVgsjty7ckBiKrau6ZPtmm7JyW0PcaAuvHtT+y2NE0F6I9h2fPzOIi+VCXLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc\",\"Ielef8mF/3IUz3VMl1uvbcgqs1i4jvgHPviwF5S6gkFDSa/YfPUp022c9+Q3pW7tidxaqWQbbayOUI9XrFBoNwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc\",\"1EDj3Pq/bh07CAE7EYReXiZgMH/tEFkar112JmsK83tWaCBuw6iRvZ43GqMvmnn5vU66axYg58UdxAcrkexfRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAb\",\"V1yoJNEvPhwT6BQ3HlpZsEaJgy/SHrb9cfMi9gg3GpbfkDvDx0qhrgkMPyd/YSCk+0Vpfyc9p15GbM4KfjwPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc\",\"iUoHMZwEx1gIjM8p8fejb6YAwMw+xzDshdnlr9mdosrP6qDjxOXqzcX644Nk8J2qG5Jd3QPgrSfbYP5fz9CggQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAb\"]}}]",
   "signatures": [
    {
     "pubkey": "injvalcons128jwakuw3wrq6ye7m4p64wrzc5rfl8tvdh7raz",
     "address": "inj128jwakuw3wrq6ye7m4p64wrzc5rfl8tvwzc6s8",
     "sequence": 54714,
     "signature": "HetA8jXHA1wsAF4HhO5DkQL+qZNkYnZP6IRlYANqz+ZByTFXbJ9suv1qZFMtHxANMkThjsNHfoNR3FyLCH+z9AA="
    }
   ]
  }
 ]
}
Parameter Type Description
data TxData Array Transactions data
paging Paging Pagination of results

Paging

Parameter Type Description
total Integer Total number of records available

TxData

Parameter Type Description
block_number Integer The block at which the transaction was executed
block_timestamp String The timestamp of the block (yyyy-MM-dd HH:mm:ss.SSS ZZZZ zzz, e.g. 2022-11-14 13:16:18.946 +0000 UTC)
hash String The transaction hash
messages bytes The raw data in bytes
tx_number Integer The transaction number
error_log String Logged errors, if any

StreamTxs

Stream transactions.

IP rate limit group: indexer

Request Example:

import asyncio
from typing import Any, Dict

from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def tx_event_processor(event: Dict[str, Any]):
    print(event)


def stream_error_processor(exception: RpcError):
    print(f"There was an error listening to txs updates ({exception})")


def stream_closed_processor():
    print("The txs updates stream has been closed")


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)

    task = asyncio.get_event_loop().create_task(
        client.listen_txs_updates(
            callback=tx_event_processor,
            on_end_callback=stream_closed_processor,
            on_status_callback=stream_error_processor,
        )
    )

    await asyncio.sleep(delay=60)
    task.cancel()


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client/common"
    explorerclient "github.com/InjectiveLabs/sdk-go/client/explorer"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    explorerClient, err := explorerclient.NewExplorerClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    stream, err := explorerClient.StreamTxs(ctx)
    if err != nil {
        panic(err)
    }

    for {
        select {
        case <-ctx.Done():
            return
        default:
            res, err := stream.Recv()
            if err != nil {
                panic(err)
            }
            str, _ := json.MarshalIndent(res, "", " ")
            fmt.Print(string(str))
        }
    }
}
Parameter Type Description Required
callback Function Function receiving one parameter (a stream event JSON dictionary) to process each new event Yes
on_end_callback Function Function with the logic to execute when the stream connection is interrupted No
on_status_callback Function Function receiving one parameter (the exception) with the logic to execute when an exception happens No

Response Parameters

Response Example:

{
   "blockNumber":"19388455",
   "blockTimestamp":"2023-12-08 12:39:19.596 +0000 UTC",
   "hash":"0xf4f17301c06df63160b60a071985fc0e0093a53e4027a2086fc51b0a46b6b43c",
   "messages":"[{\"type\":\"/cosmos.authz.v1beta1.MsgExec\",\"value\":{\"grantee\":\"inj12shqy72r0apr4d9ft9x6z59t5yfjj4jv9n79l6\",\"msgs\":[{\"@type\":\"/injective.exchange.v1beta1.MsgBatchUpdateOrders\",\"sender\":\"inj15uad884tqeq9r76x3fvktmjge2r6kek55c2zpa\",\"subaccount_id\":\"\",\"spot_market_ids_to_cancel_all\":[],\"derivative_market_ids_to_cancel_all\":[],\"spot_orders_to_cancel\":[],\"derivative_orders_to_cancel\":[],\"spot_orders_to_create\":[],\"derivative_orders_to_create\":[{\"market_id\":\"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6\",\"order_info\":{\"subaccount_id\":\"0xa73ad39eab064051fb468a5965ee48ca87ab66d4000000000000000000000004\",\"fee_recipient\":\"inj15uad884tqeq9r76x3fvktmjge2r6kek55c2zpa\",\"price\":\"18495900.000000000000000000\",\"quantity\":\"60.000000000000000000\",\"cid\":\"HBOTSIJUT60bfedf775353d7bf700310e7cd\"},\"order_type\":\"SELL\",\"margin\":\"0.000000000000000000\",\"trigger_price\":\"0.000000000000000000\"}],\"binary_options_orders_to_cancel\":[],\"binary_options_market_ids_to_cancel_all\":[],\"binary_options_orders_to_create\":[]}]}}]",
   "txNumber":"17748407",
   "id":"",
   "codespace":"",
   "errorLog":"",
   "code":0,
   "claimIds":[

   ]
}
{
 "block_number": 6129344,
 "block_timestamp": "2022-06-03 06:48:33.883 +0000 UTC",
 "hash": "0x8cbfc9c361abea5b59c95ed8096cd55d9b41af68e0fd81fab049f9e9aaace206",
 "data": "CnwKNC9pbmplY3RpdmUuZXhjaGFuZ2UudjFiZXRhMS5Nc2dDcmVhdGVTcG90TWFya2V0T3JkZXISRApCMHgzNGVjMGEyNTQzYWM5NmZlZmM2NWE0ZmQyMDUyOWE5MWQ4MzRiYzgwMzEwMzQ3M2FhYTlmYWY2YWMyMjVmYzNm",
 "gas_wanted": 129946,
 "gas_used": 101840,
 "gas_fee": {
  "amount": [
   {
    "denom": "inj",
    "amount": "64973000000000"
   }
  ],
  "gas_limit": 129946,
  "payer": "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r"
 },
 "tx_type": "injective",
 "messages": "[{\"type\":\"/injective.exchange.v1beta1.MsgCreateSpotMarketOrder\",\"value\":{\"order\":{\"market_id\":\"0x8b1a4d3e8f6b559e30e40922ee3662dd78edf7042330d4d620d188699d1a9715\",\"order_info\":{\"fee_recipient\":\"inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r\",\"price\":\"0.984400000000000000\",\"quantity\":\"23000000.000000000000000000\",\"subaccount_id\":\"0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000\"},\"order_type\":\"BUY\",\"trigger_price\":null},\"sender\":\"inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r\"}}]",
 "signatures": [
  {
   "pubkey": "injvalcons1cml96vmptgw99syqrrz8az79xer2pcgpvgp7ex",
   "address": "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r",
   "sequence": 2087458,
   "signature": "UWKbIKeR4a2Ws1zE5vno5Q71WLIiUzB4dGhJzLuUtLQWV09PcP/a40L0nzw0hnMEhSqJUeDk9oj0PVr6c0ZMZQE="
  }
 ]
}{
 "block_number": 6129345,
 "block_timestamp": "2022-06-03 06:48:35.803 +0000 UTC",
 "hash": "0x13177ab51add513cfae7586886954c6bc818c18d8523a4c29475d66114917cb3",
 "data": "CnwKNC9pbmplY3RpdmUuZXhjaGFuZ2UudjFiZXRhMS5Nc2dDcmVhdGVTcG90TWFya2V0T3JkZXISRApCMHhmY2MyNmRjYzc0OTQwMWRjZTA0NmNkM2M5M2QwNzczMzZkOGI1MDhiYTk0N2MxMzA4MjlhMzllNThjYzA1YzI2",
 "gas_wanted": 130489,
 "gas_used": 102202,
 "gas_fee": {
  "amount": [
   {
    "denom": "inj",
    "amount": "65244500000000"
   }
  ],
  "gas_limit": 130489,
  "payer": "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r"
 },
 "tx_type": "injective",
 "messages": "[{\"type\":\"/injective.exchange.v1beta1.MsgCreateSpotMarketOrder\",\"value\":{\"order\":{\"market_id\":\"0xbe9d4a0a768c7e8efb6740be76af955928f93c247e0b3a1a106184c6cf3216a7\",\"order_info\":{\"fee_recipient\":\"inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r\",\"price\":\"0.000000000071480000\",\"quantity\":\"240000000000000000000.000000000000000000\",\"subaccount_id\":\"0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000\"},\"order_type\":\"BUY\",\"trigger_price\":null},\"sender\":\"inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r\"}}]",
 "signatures": [
  {
   "pubkey": "injvalcons1cml96vmptgw99syqrrz8az79xer2pcgpvgp7ex",
   "address": "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r",
   "sequence": 2087459,
   "signature": "yXQON133B3lJlVNkFwf0pvZof6GCoeKoIhMkKHe3sndfgf2aWs4DwlOVlbEZTY4X++x+PU6sZNngHACiuGqPmAE="
  }
 ]
}
Parameter Type Description
block_number Integer The block at which the transaction was executed
block_timestamp String The timestamp of the block (yyyy-MM-dd HH:mm:ss.SSS ZZZZ zzz, e.g. 2022-11-14 13:16:18.946 +0000 UTC)
hash String The transaction hash
messages bytes The raw data in bytes
tx_number Integer The transaction number
error_log String Logged errors, if any

StreamBlocks

Stream blocks.

IP rate limit group: indexer

Request Example:

import asyncio
from typing import Any, Dict

from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def block_event_processor(event: Dict[str, Any]):
    print(event)


def stream_error_processor(exception: RpcError):
    print(f"There was an error listening to blocks updates ({exception})")


def stream_closed_processor():
    print("The blocks updates stream has been closed")


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)

    task = asyncio.get_event_loop().create_task(
        client.listen_blocks_updates(
            callback=block_event_processor,
            on_end_callback=stream_closed_processor,
            on_status_callback=stream_error_processor,
        )
    )

    await asyncio.sleep(delay=60)
    task.cancel()


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client/common"
    explorerclient "github.com/InjectiveLabs/sdk-go/client/explorer"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    explorerClient, err := explorerclient.NewExplorerClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    stream, err := explorerClient.StreamBlocks(ctx)
    if err != nil {
        panic(err)
    }

    for {
        select {
        case <-ctx.Done():
            return
        default:
            res, err := stream.Recv()
            if err != nil {
                panic(err)
            }
            str, _ := json.MarshalIndent(res, "", " ")
            fmt.Print(string(str))
        }
    }
}
Parameter Type Description Required
callback Function Function receiving one parameter (a stream event JSON dictionary) to process each new event Yes
on_end_callback Function Function with the logic to execute when the stream connection is interrupted No
on_status_callback Function Function receiving one parameter (the exception) with the logic to execute when an exception happens No

Response Parameters

Response Example:

{
   "height":"19388498",
   "proposer":"injvalcons1xml3ew93xmjtuf5zwpcl9jzznphte30hvdre9a",
   "moniker":"InjectiveNode2",
   "blockHash":"0xf12fd7ce5a00a4bab5028f6b6e94e014d31074b8f4a45d03731ab640533c71b7",
   "parentHash":"0x601b7b2c202e8142535b1a76ec095a05e91c2507cbb462d59c0fd251fd769255",
   "numTxs":"2",
   "timestamp":"2023-12-08 12:40:51.641 +0000 UTC",
   "numPreCommits":"0",
   "txs":[

   ]
}
{
   "height":"19388499",
   "proposer":"injvalcons1xwg7xkmpqp8q804c37sa4dzyfwgnh4a74ll9pz",
   "moniker":"InjectiveNode0",
   "blockHash":"0x36bc946dba7fd81ea9b8dac4a70ca20ff4bc8e59b6ed2005e397d6ab0d3655d7",
   "parentHash":"0xf37f966ec5d8275c74f25fbb3c39e7f58b30ca36dff5592cde44dd251b943fd8",
   "numTxs":"3",
   "timestamp":"2023-12-08 12:40:53.945 +0000 UTC",
   "numPreCommits":"0",
   "txs":[

   ]
}
{
   "height":"19388500",
   "proposer":"injvalcons18x63wcw5hjxlf535lgn4qy20yer7mm0qedu0la",
   "moniker":"InjectiveNode1",
   "blockHash":"0x1da9e10a726da84a5f7b53e25a598165a5ac44b573b7a3a7a1044242f9de2c83",
   "parentHash":"0xad1f884d19fac8c6abc8b1e896e34a84583c49dc3ff66070c477a5af71bf54a2",
   "numTxs":"2",
   "timestamp":"2023-12-08 12:40:56.463 +0000 UTC",
   "numPreCommits":"0",
   "txs":[

   ]
}
{
 "height": 6009287,
 "proposer": "injvalcons1aju53n6la4xzemws8gqnvr9v8hsjdea706jq7f",
 "moniker": "InjectiveNode2",
 "block_hash": "0x9ad53714c72b66d4c347814a0b14975160cda0f22e48df1e59cf1f4e9c083526",
 "parent_hash": "0x3a8aa6a5f7b9c3647442a0a7f43586c30b66b216ff3e29c373e9b02cbb81f51b",
 "timestamp": "2022-05-31 13:56:17.644 +0000 UTC"
}{
 "height": 6009288,
 "proposer": "injvalcons1qmrj7lnzraref92lzuhrv6m7sxey248fzxmfnf",
 "moniker": "InjectiveNode3",
 "block_hash": "0x1869065635c1b726d973ea154c49736dbcf3159975b4ef6236a85128ee0ad69a",
 "parent_hash": "0xb9054fd1f6ca37ba8d2507636685ceb548a6dc224c4658f6ec4e118ef803a6e8",
 "timestamp": "2022-05-31 13:56:19.657 +0000 UTC"
}
Parameter Type Description
height Integer The block height
proposer String The block proposer
moniker String The block proposer's moniker
block_hash String The block hash
parent_hash String The parent hash
num_txs Integer The number of transactions in the block
timestamp String The block's timestamp (yyyy-MM-dd HH:mm:ss.SSS ZZZZ zzz, e.g. 2022-11-14 13:16:18.946 +0000 UTC)

PeggyDeposits

Get info on peggy deposits. By default, deposits for all senders and receivers will be fetched.

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio

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)
    receiver = "inj1phd706jqzd9wznkk5hgsfkrc8jqxv0kmlj0kex"
    peggy_deposits = await client.fetch_peggy_deposit_txs(receiver=receiver)
    print(peggy_deposits)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    explorerPB "github.com/InjectiveLabs/sdk-go/exchange/explorer_rpc/pb"

    "github.com/InjectiveLabs/sdk-go/client/common"
    explorerclient "github.com/InjectiveLabs/sdk-go/client/explorer"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    explorerClient, err := explorerclient.NewExplorerClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    receiver := "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku"

    req := explorerPB.GetPeggyDepositTxsRequest{
        Receiver: receiver,
    }

    res, err := explorerClient.GetPeggyDeposits(ctx, &req)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
Parameter Type Description Required
sender String Filter by sender address No
receiver String Filter by receiver address No
pagination PaginationOption Pagination configuration No

Response Parameters

Response Example:

{
   "field":[
      {
         "sender":"0x197E6c3f19951eA0bA90Ddf465bcC79790cDD12d",
         "receiver":"inj1r9lxc0cej502pw5smh6xt0x8j7gvm5fdrj6xhk",
         "eventNonce":"624",
         "eventHeight":"10122722",
         "amount":"500000000000000000",
         "denom":"0xAD1794307245443B3Cb55d88e79EEE4d8a548C03",
         "orchestratorAddress":"inj1c8rpu79mr70hqsgzutdd6rhvzhej9vntm6fqku",
         "state":"Completed",
         "claimType":1,
         "txHashes":[
            "0x028a43ad2089cad45a8855143508f7381787d7f17cc19e3cda1bc2300c1d043f"
         ],
         "createdAt":"2023-11-28 16:55:54.841 +0000 UTC",
         "updatedAt":"2023-11-28 16:56:07.944 +0000 UTC"
      },
      {
         "sender":"0x197E6c3f19951eA0bA90Ddf465bcC79790cDD12d",
         "receiver":"inj1r9lxc0cej502pw5smh6xt0x8j7gvm5fdrj6xhk",
         "eventNonce":"622",
         "eventHeight":"10094898",
         "amount":"550000000000000000",
         "denom":"0xAD1794307245443B3Cb55d88e79EEE4d8a548C03",
         "orchestratorAddress":"inj1c8rpu79mr70hqsgzutdd6rhvzhej9vntm6fqku",
         "state":"Completed",
         "claimType":1,
         "txHashes":[
            "0xa528a522ce00b0f44add4a634ec92417c483fc045aa6b3f1cfceb685cdcf13a7"
         ],
         "createdAt":"2023-11-23 18:09:52.228 +0000 UTC",
         "updatedAt":"2023-11-23 18:10:31.294 +0000 UTC"
      }
   ]
}
{
 "field": [
  {
   "sender": "0xbdAEdEc95d563Fb05240d6e01821008454c24C36",
   "receiver": "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
   "event_nonce": 201,
   "event_height": 31544480,
   "amount": "1000000000000000000",
   "denom": "0x36B3D7ACe7201E28040eFf30e815290D7b37ffaD",
   "orchestrator_address": "inj1ultw9r29l8nxy5u6thcgusjn95vsy2caecl0ps",
   "state": "Completed",
   "claim_type": 1,
   "tx_hashes": [
    "0x8de1bf0f32966d2edf09378bc0e1d292f8ae34c45ae0b37a847867753a4b37a6"
   ],
   "created_at": "2022-06-01 07:25:47.077 +0000 UTC",
   "updated_at": "2022-06-01 07:32:01.671 +0000 UTC"
  },
  {
   "sender": "0xbdAEdEc95d563Fb05240d6e01821008454c24C36",
   "receiver": "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
   "event_nonce": 200,
   "event_height": 31396037,
   "amount": "1000000000000000000",
   "denom": "0x36B3D7ACe7201E28040eFf30e815290D7b37ffaD",
   "orchestrator_address": "inj1ultw9r29l8nxy5u6thcgusjn95vsy2caecl0ps",
   "state": "Completed",
   "claim_type": 1,
   "tx_hashes": [
    "0x377c52c94f8cab6e91d4b56a5e65710c1452acc4b10bc26d111ceeab9e30a67f"
   ],
   "created_at": "2022-06-01 07:17:52.285 +0000 UTC",
   "updated_at": "2022-06-01 07:31:57.848 +0000 UTC"
  },
  {
   "sender": "0xAF79152AC5dF276D9A8e1E2E22822f9713474902",
   "receiver": "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
   "event_nonce": 2,
   "event_height": 29335363,
   "amount": "50000000000000000000",
   "denom": "0xA3a9029B8120e2F09B194Df4A249A24dB461E573",
   "orchestrator_address": "inj1hs9q5xuvzunl77uv0mf0amsfa79uzhsrzak00a",
   "state": "InjectiveConfirming",
   "tx_hashes": [
    "0x97d223982ffef0a0550d75c8dfdb8fd661b8be28744d3f5b23cb8c1b328d1b3b"
   ],
   "created_at": "2022-05-18 21:03:34.991 +0000 UTC",
   "updated_at": "0001-01-01 00:00:00 +0000 UTC"
  }
 ]
}
Parameter Type Description
field PeggyDepositTx Array List of peggy deposits

PeggyDepositTx

Parameter Type Description
sender String The sender address
receiver String The receiver address
event_nonce Integer The event nonce
event_height Integer The event height
amount String The deposited amount
denom Integer The token denom
orchestrator_address String The orchestrator address
state String Transaction state
claim_type Integer Claim type of the deposit, always equal to 1
tx_hashes String Array List of transaction hashes
created_at Integer The timestamp of the tx creation (yyyy-MM-dd HH:mm:ss.SSS ZZZZ zzz, e.g. 2022-11-14 13:16:18.946 +0000 UTC)
updated_at String The timestamp of the tx update (yyyy-MM-dd HH:mm:ss.SSS ZZZZ zzz, e.g. 2022-11-14 13:16:18.946 +0000 UTC)

PeggyWithdrawals

Get info on peggy withdrawals.

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    sender = "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku"
    limit = 2
    pagination = PaginationOption(limit=limit)
    peggy_deposits = await client.fetch_peggy_withdrawal_txs(sender=sender, pagination=pagination)
    print(peggy_deposits)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    explorerPB "github.com/InjectiveLabs/sdk-go/exchange/explorer_rpc/pb"

    "github.com/InjectiveLabs/sdk-go/client/common"
    explorerclient "github.com/InjectiveLabs/sdk-go/client/explorer"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    explorerClient, err := explorerclient.NewExplorerClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    sender := "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku"

    req := explorerPB.GetPeggyWithdrawalTxsRequest{
        Sender: sender,
    }

    res, err := explorerClient.GetPeggyWithdrawals(ctx, &req)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
Parameter Type Description Required
sender String Filter by sender address No
receiver String Filter by receiver address No
pagination PaginationOption Pagination configuration No

Response Parameters

Response Example:

{
   "field":[
      {
         "sender":"inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
         "receiver":"0xAF79152AC5dF276D9A8e1E2E22822f9713474902",
         "amount":"1424956871765382404",
         "denom":"inj",
         "bridgeFee":"575043128234617596",
         "outgoingTxId":"1136",
         "batchTimeout":"10125614",
         "batchNonce":"1600",
         "orchestratorAddress":"inj1c8rpu79mr70hqsgzutdd6rhvzhej9vntm6fqku",
         "state":"Cancelled",
         "txHashes":[
            "0x0d9a7e280898b4452a4cd283c0447ea36d9f09f223d9812f64bbd694851dec8c",
            "0x9a456aa20d613c2cd646cbfff0b77c49e746757c24352e967578cd6e86ad62e1",
            "0x6ad03f12df86ead8efe52b1aecc35a4527c548283a901c71d6ca731a5bcf0a71",
            "0x8cb343b8ec48de5b30c9825156e29ab649570f15a8d1b4a4c850d736d99a670e",
            "0x9830d597d9ef2e60fa0c161cb0f39528e3d589c52bf365bf6971369025ce55ee",
            "0xa955975323aac3a3ad52adc45379a6ce19ec4d91f661265521a55139b2a6ad8d",
            "0x15dfa29c3f0e888b808b488c02f4596bbd6d30d566ddcf12fb80f658e6e2bc50",
            "0x016df0af7326ea14160f8f6d233578c9dfdecc9568b5b464deb80584ea00d652",
            "0xcf07704ba6ddf1ee4cdda30c594098ec7d4826fffc4a32891f76d1f632de5f61",
            "0xc6198363885fda70ec365020a99df9ba9b0a6dc880d7b83e956e7441c1cd8824",
            "0x25081d4593dc0f31c7e7465d2fbdb4f68289cd64b47968f532038085f9013ace",
            "0x684b59d4cd779d1333b9f2cfa5db1a28ed5ba6a9be3b96fa63aa0cf6577ade0e"
         ],
         "createdAt":"2023-11-09 07:37:31.258 +0000 UTC",
         "updatedAt":"2023-11-28 16:59:17.646 +0000 UTC",
         "eventNonce":"0",
         "eventHeight":"0",
         "claimType":0
      },
      {
         "sender":"inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
         "receiver":"0xAF79152AC5dF276D9A8e1E2E22822f9713474902",
         "amount":"19254843517138599106",
         "denom":"inj",
         "bridgeFee":"745156482861400894",
         "outgoingTxId":"912",
         "batchTimeout":"10125613",
         "batchNonce":"1598",
         "orchestratorAddress":"inj1qu62yv9xutqgeqms7gzvdnay5j5lph2j2e4q5h",
         "state":"Cancelled",
         "txHashes":[
            "0x1fc11c1db466716ad08237ec13128dead7a5edc2324a2d10eede9c45fd1789bc",
            "0x747b809a56f1e2f9065378df6f46a9e2d725f04ccf505608756aa41a73551235",
            "0x06db2f347054b394a70326314c04c2421757960a5b23724ec40cd84cc27ce44c",
            "0x3c36a54a326ad9eb37ccfb2b8d8db72f3d2b5bdbc8d3693bf202ce98b315bdd8",
            "0x7a2df716dae67e1fe9acbb336beda22882e92dc60836d19396305f9f03d34530",
            "0xe31b3b5cabdae870a4c93d15cadfa6ac173e7d60ee2f021f4a047d4523bf7481",
            "0x9d8d67e82d9f54477ca31e339643fc18b655fb24a9ebaa122400f49c5737df5e",
            "0xa9039fee3b119f27fb0e733d8cfe2f9e96af51802a6a4088af3a5cabb1fb6de8",
            "0x77d86350929b7cf6f4fe0094365bb71e9dc36a3e089a6af961cf05a153b54ade",
            "0x3846355740bcfa46d7ac9092e9065df0a7f232f2736ac05a09fff69ee32314f2",
            "0x86771d5fef383f8e256196d50ab62843aba63f3d23d3190f99cb882bcdaa45c9",
            "0x27c712e45ec0458c9a39cf031d3d5de2d1ba1ef8833528062508a1ef0a02e64b",
            "0x534fe5777662f31d098f6a5da2a73efc553a8fa81010da319162b7673062a90c",
            "0xaafcd570b535ecc063573a94e9dd58dfcfcb0f30853945aa79e64fccc5907688",
            "0x58258c46c3a674051e8c74c75ebe234942f85dacbeaba57c95ead9fa41b6d3a8",
            "0xa434119dd2e647db048cfad61f3b97feef6008c38e68d7c574a6153b41dd49fe"
         ],
         "createdAt":"2023-10-27 16:18:16.23 +0000 UTC",
         "updatedAt":"2023-11-28 16:59:04.777 +0000 UTC",
         "eventNonce":"0",
         "eventHeight":"0",
         "claimType":0
      }
   ]
}
{
 "field": [
  {
   "sender": "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
   "receiver": "0xAF79152AC5dF276D9A8e1E2E22822f9713474902",
   "amount": "5000000000000000000",
   "denom": "inj",
   "bridge_fee": "2000000000000000000",
   "outgoing_tx_id": 113,
   "state": "InjectiveConfirming",
   "tx_hashes": [
    "0x391ab87558318bd7ff2ccb9d68ed309ad073fa64c8395a493d6c347ff572af38"
   ],
   "created_at": "2022-05-13 16:14:16.912 +0000 UTC",
   "updated_at": "0001-01-01 00:00:00 +0000 UTC"
  },
  {
   "sender": "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
   "receiver": "0xAF79152AC5dF276D9A8e1E2E22822f9713474902",
   "amount": "23000000000000000000",
   "denom": "inj",
   "bridge_fee": "3546099290780142080",
   "outgoing_tx_id": 110,
   "state": "InjectiveConfirming",
   "tx_hashes": [
    "0x088975b8a12119944a254f0e4d7659df4c2b9c85c2c110305393f83be4f7f6ed"
   ],
   "created_at": "2022-05-11 10:32:20.19 +0000 UTC",
   "updated_at": "0001-01-01 00:00:00 +0000 UTC"
  }
 ]
}
Parameter Type Description
field PeggyWithdrawalTx Array List of peggy withdrawals

PeggyWithdrawalTx

Parameter Type Description
sender String The sender address
receiver String The receiver address
amount String The amount withdrawn
denom Integer The token denom
bridge_fee String The bridge fee
outgoing_tx_id Integer The tx nonce
batch_timeout Integer The timestamp after which batch request will be discarded if not processed already
BatchNonce Integer An auto incremented unique ID representing the Withdrawal Batches
orchestrator_address String Address that created batch request
event_nonce Integer The event nonce of WithdrawalClaim event emitted by Ethereum chain upon batch withdrawal
event_height Integer The block height of WithdrawalClaim event emitted by Ethereum chain upon batch withdrawal
state String Transaction state
claim_type Integer Claim type of the transaction, always equal to 2
tx_hashes String Array List of transaction hashes
created_at Integer The timestamp of the tx creation (yyyy-MM-dd HH:mm:ss.SSS ZZZZ zzz, e.g. 2022-11-14 13:16:18.946 +0000 UTC)
updated_at String The timestamp of the tx update (yyyy-MM-dd HH:mm:ss.SSS ZZZZ zzz, e.g. 2022-11-14 13:16:18.946 +0000 UTC)

IBCTransfers

Get data on IBC transfers.

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    sender = "inj1cll5cv3ezgal30gagkhnq2um6zf6qrmhw4r6c8"
    receiver = "cosmos1usr9g5a4s2qrwl63sdjtrs2qd4a7huh622pg82"
    src_channel = "channel-2"
    src_port = "transfer"
    destination_channel = "channel-30"
    dest_port = "transfer"
    limit = 1
    skip = 10
    pagination = PaginationOption(limit=limit, skip=skip)
    ibc_transfers = await client.fetch_ibc_transfer_txs(
        sender=sender,
        receiver=receiver,
        src_channel=src_channel,
        src_port=src_port,
        dest_channel=destination_channel,
        dest_port=dest_port,
        pagination=pagination,
    )
    print(ibc_transfers)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    explorerPB "github.com/InjectiveLabs/sdk-go/exchange/explorer_rpc/pb"

    "github.com/InjectiveLabs/sdk-go/client/common"
    explorerclient "github.com/InjectiveLabs/sdk-go/client/explorer"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    explorerClient, err := explorerclient.NewExplorerClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    receiver := "inj1ddcp5ftqmntudn4m6heg2adud6hn58urnwlmkh"

    req := explorerPB.GetIBCTransferTxsRequest{
        Receiver: receiver,
    }

    res, err := explorerClient.GetIBCTransfers(ctx, &req)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
Parameter Type Description Required
sender String Filter transfers based on sender address No
receiver String Filter transfers based on receiver address No
src_channel String Filter transfers based on source channel No
src_port String Filter transfers based on source port No
dest_channel String Filter transfers based on destination channel No
dest_port String Filter transfers based on destination port No
pagination PaginationOption Pagination configuration No

Response Parameters

Response Example:

{
   "field":[
      {
         "sender":"inj14nendtsz0c40n7xtzwkjmdc8dkuz835jdydxhn",
         "receiver":"nois1mvuupgre7pjx3k5tm5729frkn9nvju6pgsxawc47pgamctypdzlsm7hg90",
         "sourcePort":"transfer",
         "sourceChannel":"channel-74",
         "destinationPort":"transfer",
         "destinationChannel":"channel-33",
         "amount":"1000000",
         "denom":"transfer/channel-74/unois",
         "timeoutHeight":"0-0",
         "timeoutTimestamp":"1702124625185146392",
         "packetSequence":"20509",
         "dataHex":"N2IyMjYxNmQ2Zjc1NmU3NDIyM2EyMjMxMzAzMDMwMzAzMDMwMjIyYzIyNjQ2NTZlNmY2ZDIyM2EyMjc0NzI2MTZlNzM2NjY1NzIyZjYzNjg2MTZlNmU2NTZjMmQzNzM0MmY3NTZlNmY2OTczMjIyYzIyNzI2NTYzNjU2OTc2NjU3MjIyM2EyMjZlNmY2OTczMzE2ZDc2NzU3NTcwNjc3MjY1Mzc3MDZhNzgzMzZiMzU3NDZkMzUzNzMyMzk2NjcyNmI2ZTM5NmU3NjZhNzUzNjcwNjc3Mzc4NjE3NzYzMzQzNzcwNjc2MTZkNjM3NDc5NzA2NDdhNmM3MzZkMzc2ODY3MzkzMDIyMmMyMjczNjU2ZTY0NjU3MjIyM2EyMjY5NmU2YTMxMzQ2ZTY1NmU2NDc0NzM3YTMwNjMzNDMwNmUzNzc4NzQ3YTc3NmI2YTZkNjQ2MzM4NjQ2Yjc1N2EzODMzMzU2YTY0Nzk2NDc4Njg2ZTIyN2Q=",
         "state":"Completed",
         "txHashes":[
            "0x3bf678143df5202cb9646e3d449978d385aff8d7b7e8cd5b1e1442163816d609",
            "0x5abaf2ac5afd669c5cf5b8e22eceb211f6a334510dc58a5766d66848eede9407"
         ],
         "createdAt":"2023-12-08 12:23:45.185 +0000 UTC",
         "updatedAt":"2023-12-08 12:23:58.769 +0000 UTC"
      }
   ]
}
{
 "field": [
  {
   "sender": "terra1nrgj0e5l98y07zuenvnpa76x8e5dmm4cdkppws",
   "receiver": "inj1ddcp5ftqmntudn4m6heg2adud6hn58urnwlmkh",
   "source_port": "transfer",
   "source_channel": "channel-17",
   "destination_port": "transfer",
   "destination_channel": "channel-4",
   "amount": "10000000000",
   "denom": "uusd",
   "timeout_height": "5-7072846",
   "timeout_timestamp": 1648784773000000000,
   "packet_sequence": 1892,
   "data_hex": "N2IyMjYxNmQ2Zjc1NmU3NDIyM2EyMjMxMzAzMDMwMzAzMDMwMzAzMDMwMzAyMjJjMjI2NDY1NmU2ZjZkMjIzYTIyNzU3NTczNjQyMjJjMjI3MjY1NjM2NTY5NzY2NTcyMjIzYTIyNjk2ZTZhMzE2NDY0NjM3MDM1NjY3NDcxNmQ2ZTc0NzU2NDZlMzQ2ZDM2Njg2NTY3MzI2MTY0NzU2NDM2Njg2ZTM1Mzg3NTcyNmU3NzZjNmQ2YjY4MjIyYzIyNzM2NTZlNjQ2NTcyMjIzYTIyNzQ2NTcyNzI2MTMxNmU3MjY3NmEzMDY1MzU2YzM5Mzg3OTMwMzc3YTc1NjU2ZTc2NmU3MDYxMzczNjc4Mzg2NTM1NjQ2ZDZkMzQ2MzY0NmI3MDcwNzc3MzIyN2Q=",
   "state": "Completed",
   "tx_hashes": [
    "0xf52d55dd6b68d78d137d4e5526a450d74689d3cba7f69640acd41b68ee26cd15"
   ],
   "created_at": "2022-04-01 03:45:39.338 +0000 UTC",
   "updated_at": "2022-04-01 03:45:39.338 +0000 UTC"
  },
  {
   "sender": "terra1nrgj0e5l98y07zuenvnpa76x8e5dmm4cdkppws",
   "receiver": "inj1ddcp5ftqmntudn4m6heg2adud6hn58urnwlmkh",
   "source_port": "transfer",
   "source_channel": "channel-17",
   "destination_port": "transfer",
   "destination_channel": "channel-4",
   "amount": "200000000",
   "denom": "uluna",
   "timeout_height": "5-6753065",
   "timeout_timestamp": 1646665141000000000,
   "packet_sequence": 1516,
   "data_hex": "N2IyMjYxNmQ2Zjc1NmU3NDIyM2EyMjMyMzAzMDMwMzAzMDMwMzAzMDIyMmMyMjY0NjU2ZTZmNmQyMjNhMjI3NTZjNzU2ZTYxMjIyYzIyNzI2NTYzNjU2OTc2NjU3MjIyM2EyMjY5NmU2YTMxNjQ2NDYzNzAzNTY2NzQ3MTZkNmU3NDc1NjQ2ZTM0NmQzNjY4NjU2NzMyNjE2NDc1NjQzNjY4NmUzNTM4NzU3MjZlNzc2YzZkNmI2ODIyMmMyMjczNjU2ZTY0NjU3MjIyM2EyMjc0NjU3MjcyNjEzMTZlNzI2NzZhMzA2NTM1NmMzOTM4NzkzMDM3N2E3NTY1NmU3NjZlNzA2MTM3MzY3ODM4NjUzNTY0NmQ2ZDM0NjM2NDZiNzA3MDc3NzMyMjdk",
   "state": "Completed",
   "tx_hashes": [
    "0xe5782979f08f7f939b6ed6f4687b70542295ef91f3de84a3e10c4044230f8474"
   ],
   "created_at": "2022-03-07 14:58:31.905 +0000 UTC",
   "updated_at": "2022-03-07 14:58:31.905 +0000 UTC"
  }
 ]
}
Parameter Type Description
field IBCTransferTx Array List of IBC transfers

IBCTransferTx

Parameter Type Description
sender String Sender address
receiver String Receiver address
source_channel String Source channel
source_port String Source port
destination_channel String Destination channel
destination_port String Destination port
amount String Transfer amount
denom String Token denom
timeout_height Integer Timeout height relative to the current block height. Timeout disabled if set to 0
timeout_timestamp Integer Timeout timestamp (in nanoseconds) relative to the current block timestamp
packet_sequence String Corresponds to the order of sends and receives, where a Packet with an earlier sequence number must be sent and received before a Packet with a later sequence number
data_hex String IBC request data in hex format
state String Transaction state
tx_hashes String Array List of transaction hashes
created_at Integer The timestamp of the tx creation (yyyy-MM-dd HH:mm:ss.SSS ZZZZ zzz, e.g. 2022-11-14 13:16:18.946 +0000 UTC)
updated_at String The timestamp of the tx update (yyyy-MM-dd HH:mm:ss.SSS ZZZZ zzz, e.g. 2022-11-14 13:16:18.946 +0000 UTC)

GetWasmCodes

List all cosmwasm code on injective chain. Results are paginated.

IP rate limit group: indexer

Request Example:

package main

import (
    "context"
    "encoding/json"
    "fmt"

    explorerPB "github.com/InjectiveLabs/sdk-go/exchange/explorer_rpc/pb"

    "github.com/InjectiveLabs/sdk-go/client/common"
    explorerclient "github.com/InjectiveLabs/sdk-go/client/explorer"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    explorerClient, err := explorerclient.NewExplorerClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    req := explorerPB.GetWasmCodesRequest{
        Limit: 10,
    }

    res, err := explorerClient.GetWasmCodes(ctx, &req)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}

Response Example:

{
 "paging": {
  "total": 501,
  "from": 497,
  "to": 501
 },
 "data": [
  {
   "code_id": 501,
   "tx_hash": "0x6f218f72f68b3c90e578c1b1fad735f8016fc9b3618664ceb301234f2725d218",
   "checksum": {
    "algorithm": "sha256",
    "hash": "0x4f6e56bbbe7ebec55f7e9d49c4a6e534f57ba3402c0282c1c3ec1aac83753ccf"
   },
   "created_at": 1677495117914,
   "permission": {
    "access_type": 3
   },
   "creator": "inj13dyu3ukelncq95s7dqhg6crqvjursramcazkka",
   "code_number": 515
  },
  {
   "code_id": 500,
   "tx_hash": "0x9a8035a3cd85651b7266f813f3dd909772a7cec5ca0b4f9266832d50c85921b8",
   "checksum": {
    "algorithm": "sha256",
    "hash": "0xdcaa8a03707966ebfedbb927f755fabf9e7f095663f4b9f45a5b437a8276ea0f"
   },
   "created_at": 1677495084552,
   "permission": {
    "access_type": 3
   },
   "creator": "inj13dyu3ukelncq95s7dqhg6crqvjursramcazkka",
   "code_number": 514
  },
  {
   "code_id": 499,
   "tx_hash": "0x3809b1b61e218144c4f50e0a61b6ae89f8942cbe7cadfe67e23127c70949a3f1",
   "checksum": {
    "algorithm": "sha256",
    "hash": "0xdbef810fdc577f4e983620b16eccafdf359e924af0752a13820bf679b260ffe1"
   },
   "created_at": 1677495060759,
   "permission": {
    "access_type": 3
   },
   "creator": "inj13dyu3ukelncq95s7dqhg6crqvjursramcazkka",
   "code_number": 513
  },
  {
   "code_id": 498,
   "tx_hash": "0x9c5a44981506fe7658fa38b2bd63ddd20717842433ce75eba60cb2d7ca548b54",
   "checksum": {
    "algorithm": "sha256",
    "hash": "0xe17581873943e1fe3671bfca9a3360398be10a28245fc0d5c55403f64808019c"
   },
   "created_at": 1677495034788,
   "permission": {
    "access_type": 3
   },
   "creator": "inj13dyu3ukelncq95s7dqhg6crqvjursramcazkka",
   "code_number": 512
  },
  {
   "code_id": 497,
   "tx_hash": "0xeaa3d642a049d0b09920bacf7989a2371ecf43ec20bb5d6dbb3b54326cec63e7",
   "checksum": {
    "algorithm": "sha256",
    "hash": "0x1a1278f43c03e9ed12ba9c1995bae8ea1554cf67a38e9eedd97e9cd61a3e411d"
   },
   "created_at": 1677495006505,
   "permission": {
    "access_type": 3
   },
   "creator": "inj13dyu3ukelncq95s7dqhg6crqvjursramcazkka",
   "code_number": 511
  }
 ]
}

Request Parameters

Parameter Type Description Required
limit Integer Limit number of codes to return No
from_number Integer List all codes whose number (code_id) is not lower than from_number No
to_number Integer List all codes whose number (code_id) is not greater than to_number No

Response Parameters

Parameter Type Description
paging Paging Pagination of results
data WasmCode Array List of WasmCodes, after applying filters

Paging

Parameter Type Description
total Integer Total number of records available

WasmCode

Parameter Type Description
code_id Integer ID of stored wasm code, sorted in descending order
tx_hash String Tx hash of store code transaction
checksum Checksum Checksum of the cosmwasm code
created_at Integer Block time when the code is stored, in millisecond
contract_type String Contract type of the wasm code
version String Version of the wasm code
permission ContractPermission Describes instantiation permissions
code_schema String Code schema preview (to be supported)
code_view String Code repo preview, may contain schema folder (to be supported)
instantiates Integer Number of contract instantiations from this code
creator String Creator of this code
code_number Integer Monotonic order of the code stored
proposal_id Integer ID of the proposal that store this code

ContractPermission

Parameter Type Description
access_type Integer Access type of instantiation
address Integer Account address

Checksum

Parameter Type Description
algorithm String Hash function algorithm
hash String Hash of the cosmwasm bytecode

GetWasmCodeByID

Get cosmwasm code by its code ID

IP rate limit group: indexer

Request Example:

package main

import (
    "context"
    "encoding/json"
    "fmt"

    explorerPB "github.com/InjectiveLabs/sdk-go/exchange/explorer_rpc/pb"

    "github.com/InjectiveLabs/sdk-go/client/common"
    explorerclient "github.com/InjectiveLabs/sdk-go/client/explorer"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    explorerClient, err := explorerclient.NewExplorerClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    req := explorerPB.GetWasmCodeByIDRequest{
        CodeId: 10,
    }

    res, err := explorerClient.GetWasmCodeByID(ctx, &req)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}

Response Example:

{
 "code_id": 10,
 "tx_hash": "0x476b1988ba0ea020a337b92f46afefde8af2ac9e72934a1b9882673b3926388c",
 "checksum": {
  "algorithm": "sha256",
  "hash": "0xdba30bcea6d5997c00a7922b475e42f172e72b8ef6ad522c09bc1868bc6caff4"
 },
 "created_at": 1658305428842,
 "instantiates": 4,
 "creator": "inj10hpqmlskky8azz5qca20xau2ppf3x23jsh9k8r",
 "code_number": 10
}

Request Parameters

Parameter Type Description Required
code_id Integer ID of the code Yes

Response Parameters

Parameter Type Description
code_id Integer ID of stored wasm code, sorted in descending order
tx_hash String Tx hash of store code transaction
checksum Checksum Checksum of the cosmwasm code
created_at Integer Block time when the code is stored, in millisecond
contract_type String Contract type of the wasm code
version String Version of the wasm code
permission ContractPermission Describes instantiation permissions
code_schema String Code schema preview (to be supported)
code_view String Code repo preview, may contain schema folder (to be supported)
instantiates Integer Number of contract instantiations from this code
creator String Creator of this code
code_number Integer Monotonic order of the code stored
proposal_id Integer ID of the proposal that store this code

ContractPermission

Parameter Type Description
access_type Integer Access type of instantiation
address Integer Account address

Checksum

Parameter Type Description
algorithm String Hash function algorithm
hash String Hash of the cosmwasm bytecode

GetWasmContracts

Get cosmwasm instantiated contracts on injective-chain. Results are paginated.

IP rate limit group: indexer

Request Example:

package main

import (
    "context"
    "encoding/json"
    "fmt"

    explorerPB "github.com/InjectiveLabs/sdk-go/exchange/explorer_rpc/pb"

    "github.com/InjectiveLabs/sdk-go/client/common"
    explorerclient "github.com/InjectiveLabs/sdk-go/client/explorer"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    explorerClient, err := explorerclient.NewExplorerClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    req := explorerPB.GetWasmContractsRequest{}

    res, err := explorerClient.GetWasmContracts(ctx, &req)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}

Response Example:

{
 "paging": {
  "total": 529,
  "from": 1,
  "to": 5
 },
 "data": [
  {
   "label": "Instantiation",
   "address": "inj138nnvqqx4t49n6u8r7d8g6h2ek3kpztk3s4svy",
   "tx_hash": "0xdc1c7dc4bb47710b22894def0c4fa12d2d86d9d3d6e3ed3a348d83e9052ea7c2",
   "creator": "inj1rhsl5eld5qg7qe2w2nretw6s6xnwdpaju3rp5j",
   "instantiated_at": 1677520960574,
   "init_message": "{\"app_components\":[],\"name\":\"First Aoo\",\"primitive_contract\":\"inj1hsrl44l3gm5p52r26nx89g9tpptacuy755y6yd\"}",
   "last_executed_at": 1677520960574,
   "code_id": 481,
   "admin": "inj1rhsl5eld5qg7qe2w2nretw6s6xnwdpaju3rp5j",
   "contract_number": 529,
   "version": "0.1.0",
   "type": "crates.io:andromeda-app-contract"
  },
  {
   "label": "CounterTestInstance",
   "address": "inj1xd48d9fs7rmh9rhf36fj69mw8yxplnq66m3gxq",
   "tx_hash": "0x05f44c2dd194a41a7e4606d350d85bd49cf59597dbb63681eaf97e51416a2df2",
   "creator": "inj1kpps36y8c5qm9axr5w3v3ukqtth99pq40ga84e",
   "executes": 1,
   "instantiated_at": 1677252138256,
   "init_message": "{\"count\":99}",
   "last_executed_at": 1677255965387,
   "code_id": 476,
   "contract_number": 528,
   "version": "0.1.0",
   "type": "crates.io:cw-counter"
  },
  {
   "label": "Wormhole Wrapped CW20",
   "address": "inj1m4g54lg2mhhm7a4h3ms5xlyecafhe4macgsuen",
   "tx_hash": "0xce9b5b713da1b1b0e48d1b5451769ba80ca905145a90c704d01221986083c2d8",
   "creator": "inj1q0e70vhrv063eah90mu97sazhywmeegp7myvnh",
   "instantiated_at": 1677179269211,
   "init_message": "{\"name\":\"QAT\",\"symbol\":\"QAT\",\"asset_chain\":2,\"asset_address\":\"AAAAAAAAAAAAAAAAGQLhj+sSNNANiA8frKXI106FAek=\",\"decimals\":8,\"mint\":null,\"init_hook\":{\"msg\":\"eyJyZWdpc3Rlcl9hc3NldF9ob29rIjp7ImNoYWluIjoyLCJ0b2tlbl9hZGRyZXNzIjp7ImJ5dGVzIjpbMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMjUsMiwyMjUsMTQzLDIzNSwxOCw1MiwyMDgsMTMsMTM2LDE1LDMxLDE3MiwxNjUsMjAwLDIxNSw3OCwxMzMsMSwyMzNdfX19\",\"contract_addr\":\"inj1q0e70vhrv063eah90mu97sazhywmeegp7myvnh\"}}",
   "last_executed_at": 1677179269211,
   "code_id": 14,
   "admin": "inj1q0e70vhrv063eah90mu97sazhywmeegp7myvnh",
   "contract_number": 527,
   "version": "0.1.0",
   "type": "crates.io:cw20-base",
   "cw20_metadata": {
    "token_info": {
     "name": "QAT (Wormhole)",
     "symbol": "QAT",
     "decimals": 8,
     "total_supply": "0"
    }
   }
  },
  {
   "label": "xAccount Registry",
   "address": "inj1s4alfevl7u84v7c3klh2flv6fw95s3q08eje53",
   "tx_hash": "0xad817a8a4fcef1c36f8c5535b5598a4bc2ddc069f8a60634438dae90a242efed",
   "creator": "inj1dc6rrxhfjaxexzdcrec5w3ryl4jn6x5t7t9j3z",
   "instantiated_at": 1677176719385,
   "init_message": "{\"wormhole_id_here\":19,\"wormhole_core_contract\":\"inj1xx3aupmgv3ce537c0yce8zzd3sz567syuyedpg\",\"factory_code_id\":474,\"x_account_code_id\":475,\"vm_id_here\":1}",
   "last_executed_at": 1677176719385,
   "code_id": 473,
   "admin": "inj1dc6rrxhfjaxexzdcrec5w3ryl4jn6x5t7t9j3z",
   "contract_number": 526
  },
  {
   "label": "xAccount Deployer",
   "address": "inj1a0s058avjct43t7cwn7rfvmxt2p37v29xladv8",
   "tx_hash": "0xad817a8a4fcef1c36f8c5535b5598a4bc2ddc069f8a60634438dae90a242efed",
   "creator": "inj1s4alfevl7u84v7c3klh2flv6fw95s3q08eje53",
   "instantiated_at": 1677176719385,
   "init_message": "{\"x_account_registry\":\"inj1s4alfevl7u84v7c3klh2flv6fw95s3q08eje53\",\"commanders\":[{\"wormhole_id\":19,\"address_byte_length\":20,\"address\":\"AAAAAAAAAAAAAAAAQjjjD/fOAVOq8xb1O7rhomqGArc=\"}]}",
   "last_executed_at": 1677176719385,
   "code_id": 475,
   "admin": "inj1gguwxrlhecq482hnzm6nhwhp5f4gvq4hmxpn7p",
   "contract_number": 525
  }
 ]
}

Request Parameters

Parameter Type Description Required
limit Integer Max number of items to be returned, defaults to 100 No
code_id Integer Contract's code ID to be filtered No
from_number Integer List all contracts whose number is not lower than from_number No
to_number Integer List all contracts whose number is not greater than to_number No
assets_only Boolean Filter only CW20 contracts No
skip Integer Skip the first n cosmwasm contracts. This can be used to fetch all results since the API caps at 100 No

Response Parameters

Parameter Type Description
paging Paging Pagination of results
data WasmContract Array List of WasmContracts after filtering

Paging

Parameter Type Description
total Integer Total number of records available

WasmContract

Parameter Type Description
label String General name of the contract
address String Address of the contract
tx_hash String Hash of the instantiate transaction
creator String Address of the contract creator
executes Integer Number of times call to execute contract
instantiated_at Integer Block timestamp that contract was instantiated, in UNIX millis
init_message String Init message when this contract was instantiated
last_executed_at Integer Block timestamp that contract was last called, in UNIX millis
funds ContractFund Array List of contract funds
code_id Integer Code ID of the contract
admin String Admin of the contract
current_migrate_message String Latest migrate message of the contract
contract_number Integer Monotonic contract number in database
version String Contract version
type String Contract type
cw20_metadata Cw20Metadata Metadata of the CW20 contract
proposal_id Integer ID of the proposal that instantiates this contract

ContractFund

Parameter Type Description
denom String Denominator
amount String Amount of denom

Cw20Metadata

Parameter Type Description
token_info Cw20TokenInfo CW20 token info structure
marketing_info Cw20MarketingInfo Marketing info structure

Cw20TokenInfo

Parameter Type Description
name String General name of the token
symbol String Symbol of the token
decimals Integer Decimal places of token

Cw20MarketingInfo

Parameter Type Description
project String Project information
description String Token's description
logo String Logo (url/embedded)
marketing Bytes Array Address that can update the contract's marketing info

GetWasmContractByAddress

Get cosmwasm contract by its address

IP rate limit group: indexer

Request Example:

package main

import (
    "context"
    "encoding/json"
    "fmt"

    explorerPB "github.com/InjectiveLabs/sdk-go/exchange/explorer_rpc/pb"

    "github.com/InjectiveLabs/sdk-go/client/common"
    explorerclient "github.com/InjectiveLabs/sdk-go/client/explorer"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    explorerClient, err := explorerclient.NewExplorerClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    req := explorerPB.GetWasmContractByAddressRequest{
        ContractAddress: "inj1ru9nhdjtjtz8u8wrwxmcl9zsns4fh2838yr5ga",
    }
    res, err := explorerClient.GetWasmContractByAddress(ctx, &req)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}

Response Example:

{
 "label": "xAccount Registry",
 "address": "inj1ru9nhdjtjtz8u8wrwxmcl9zsns4fh2838yr5ga",
 "tx_hash": "0x7dbc4177ef6253b6cfb33c0345e023eec3a6603aa615fa836271d2f3743e33fb",
 "creator": "inj1dc6rrxhfjaxexzdcrec5w3ryl4jn6x5t7t9j3z",
 "executes": 6,
 "instantiated_at": 1676450262441,
 "init_message": "{\"wormhole_id_here\":19,\"wormhole_core_contract\":\"inj1xx3aupmgv3ce537c0yce8zzd3sz567syuyedpg\",\"factory_code_id\":422,\"x_account_code_id\":421,\"vm_id_here\":1}",
 "last_executed_at": 1676464935254,
 "code_id": 420,
 "admin": "inj1dc6rrxhfjaxexzdcrec5w3ryl4jn6x5t7t9j3z",
 "contract_number": 430
}

Request Parameters

Parameter Type Description Required
contract_address String Contract address Yes

Response Parameters

Parameter Type Description
label String General name of the contract
address String Address of the contract
tx_hash String Hash of the instantiate transaction
creator String Address of the contract creator
executes Integer Number of times call to execute contract
instantiated_at Integer Block timestamp that contract was instantiated, in UNIX millis
init_message String Init message when this contract was instantiated
last_executed_at Integer Block timestamp that contract was last called, in UNIX millis
funds ContractFund Array List of contract funds
code_id Integer Code ID of the contract
admin String Admin of the contract
current_migrate_message String Latest migrate message of the contract
contract_number Integer Monotonic contract number in database
version String Contract version
type String Contract type
cw20_metadata Cw20Metadata Metadata of the CW20 contract
proposal_id Integer ID of the proposal that instantiates this contract

ContractFund

Parameter Type Description
denom String Denominator
amount String Amount of denom

Cw20Metadata

Parameter Type Description
token_info Cw20TokenInfo CW20 token info structure
marketing_info Cw20MarketingInfo Marketing info structure

Cw20TokenInfo

Parameter Type Description
name String General name of the token
symbol String Symbol of the token
decimals Integer Decimal places of token

Cw20MarketingInfo

Parameter Type Description
project String Project information
description String Token's description
logo String Logo (url/embedded)
marketing Bytes Array Address that can update the contract's marketing info

GetCw20Balance

Get CW20 balances of an injective account across all instantiated CW20 contracts

IP rate limit group: indexer

Request Example:

package main

import (
    "context"
    "encoding/json"
    "fmt"

    explorerPB "github.com/InjectiveLabs/sdk-go/exchange/explorer_rpc/pb"

    "github.com/InjectiveLabs/sdk-go/client/common"
    explorerclient "github.com/InjectiveLabs/sdk-go/client/explorer"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    explorerClient, err := explorerclient.NewExplorerClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    req := explorerPB.GetCw20BalanceRequest{
        Address: "inj1dc6rrxhfjaxexzdcrec5w3ryl4jn6x5t7t9j3z",
    }
    res, err := explorerClient.GetCW20Balance(ctx, &req)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}

Response Example:

{
 "field": [
  {
   "contract_address": "inj1v6p2u2pgk9qdcf3ussudszjetqwjaj6l89ce0k",
   "account": "inj1dc6rrxhfjaxexzdcrec5w3ryl4jn6x5t7t9j3z",
   "balance": "10000000000000000",
   "updated_at": 1666153787458,
   "cw20_metadata": {
    "token_info": {
     "name": "test coin",
     "symbol": "TEST",
     "decimals": 6,
     "total_supply": "10000000000000000"
    },
    "marketing_info": {
     "marketing": "bnVsbA=="
    }
   }
  }
 ]
}

Request Parameters

Parameter Type Description Required
address String Address to list balance of Yes
limit Integer Limit number of balances to return No

Response Parameters

Parameter Type Description
Parameter WasmCw20Balance Array CW20 balance array

WasmCw20Balance

Parameter Type Description
contract_address String Address of CW20 contract
account String Account address
balance String Account balance
updated_at Integer Update timestamp in UNIX millis
cw20_metadata Cw20Metadata Metadata of the CW20 contract

Cw20Metadata

Parameter Type Description
token_info Cw20TokenInfo CW20 token info
marketing_info Cw20MarketingInfo Marketing info

Cw20TokenInfo

Parameter Type Description
name String General name of the token
symbol String Symbol of the token
decimals Integer Decimal places of token

Cw20MarketingInfo

Parameter Type Description
project String Project information
description String Token's description
logo String Logo (url/embedded)
marketing Bytes Array Address that can update the contract's marketing info

- InjectiveMetaRPC

InjectiveMetaRPC defines the gRPC API of the Exchange Meta provider.

Ping

Get the server health.

IP rate limit group: indexer

Request Example:

import asyncio

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)
    resp = await client.fetch_ping()
    print("Health OK?", resp)


if __name__ == "__main__":
    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"
    metaPB "github.com/InjectiveLabs/sdk-go/exchange/meta_rpc/pb"
)

func main() {
    // network := common.LoadNetwork("mainnet", "k8s")
    network := common.LoadNetwork("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    req := metaPB.PingRequest{}

    res, err := exchangeClient.Ping(ctx, &req)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}

Response Example:

Health OK?
Health OK?{}

Version

Get the server version.

IP rate limit group: indexer

Request Example:

import asyncio

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)
    resp = await client.fetch_version()
    print("Version:", resp)


if __name__ == "__main__":
    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"
    metaPB "github.com/InjectiveLabs/sdk-go/exchange/meta_rpc/pb"
)

func main() {
    // network := common.LoadNetwork("mainnet", "k8s")
    network := common.LoadNetwork("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    req := metaPB.VersionRequest{}

    res, err := exchangeClient.GetVersion(ctx, &req)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}

Response Parameters

Response Example:

{
   "version":"v1.12.46-rc1",
   "build":{
      "BuildDate":"20231110-0736",
      "GitCommit":"2b326fe",
      "GoVersion":"go1.20.5",
      "GoArch":"amd64"
   }
}
{
 "version": "dev",
 "build": {
  "BuildDate": "20220426-0810",
  "GitCommit": "4f3bc09",
  "GoArch": "amd64",
  "GoVersion": "go1.17.3"
 }
}
Parameter Type Description
version String injective-exchange code version
build VersionResponse.BuildEntry Array Additional build meta info

VersionResponse.BuildEntry

Parameter Type Description
key String Name
value String Description

Info

Get the server information.

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio
import time

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)
    resp = await client.fetch_info()
    print("[!] Info:")
    print(resp)
    latency = int(time.time() * 1000) - int(resp["timestamp"])
    print(f"Server Latency: {latency}ms")


if __name__ == "__main__":
    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"
    metaPB "github.com/InjectiveLabs/sdk-go/exchange/meta_rpc/pb"
)

func main() {
    // network := common.LoadNetwork("mainnet", "k8s")
    network := common.LoadNetwork("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    req := metaPB.InfoRequest{}

    res, err := exchangeClient.GetInfo(ctx, &req)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
Parameter Type Description Required
timestamp Integer Your current system UNIX timestamp in millis No, if using our async_client implementation, otherwise yes

Response Parameters

Response Example:

{
   "timestamp":"1702040535291",
   "serverTime":"1702040536394",
   "version":"v1.12.46-guilds-rc5",
   "build":{
      "BuildDate":"20231113-1523",
      "GitCommit":"78a9ea2",
      "GoVersion":"go1.20.5",
      "GoArch":"amd64"
   },
   "region":""
}
Parameter Type Description
timestamp Integer The original timestamp (from your system) of the request in UNIX millis
server_time Integer UNIX time on the server in millis
version String injective-exchange code version
build VersionResponse.BuildEntry Array Additional build meta info

VersionResponse.BuildEntry

Parameter Type Description
key String Name
value String Description

StreamKeepAlive

Subscribe to a stream and gracefully disconnect and connect to another sentry node if the primary becomes unavailable.

IP rate limit group: indexer

Request Example:

import asyncio
from typing import Any, Dict

from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


def stream_error_processor(exception: RpcError):
    print(f"There was an error listening to keepalive updates ({exception})")


def stream_closed_processor():
    print("The keepalive stream has been closed")


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    tasks = []

    async def keepalive_event_processor(event: Dict[str, Any]):
        print("Server announce:", event)
        for task in tasks:
            task.cancel()
        print("Cancelled all tasks")

    market_task = asyncio.get_event_loop().create_task(get_markets(client))
    tasks.append(market_task)
    keepalive_task = asyncio.get_event_loop().create_task(
        client.listen_keepalive(
            callback=keepalive_event_processor,
            on_end_callback=stream_closed_processor,
            on_status_callback=stream_error_processor,
        )
    )

    try:
        await asyncio.gather(market_task, keepalive_task)
    except asyncio.CancelledError:
        print("main(): get_markets is cancelled now")


async def get_markets(client):
    async def print_market_updates(event: Dict[str, Any]):
        print(event)

    await client.listen_spot_markets_updates(
        callback=print_market_updates,
        on_end_callback=stream_closed_processor,
        on_status_callback=stream_error_processor,
    )


if __name__ == "__main__":
    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", "k8s")
    network := common.LoadNetwork("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    stream, err := exchangeClient.StreamKeepalive(ctx)
    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))
        }
    }
}
Parameter Type Description Required
callback Function Function receiving one parameter (a stream event JSON dictionary) to process each new event Yes
on_end_callback Function Function with the logic to execute when the stream connection is interrupted No
on_status_callback Function Function receiving one parameter (the exception) with the logic to execute when an exception happens No

Response Parameters

Response Example:

event: "shutdown",
timestamp: 1636236225847,

"Cancelled all tasks"
Parameter Type Description
event String Server event
new_endpoint String New connection endpoint for the gRPC API
timestamp Integer Operation timestamp in UNIX millis

- InjectivePortfolioRPC

InjectivePortfolioRPC defines the gRPC API of the Exchange Portfolio provider.

AccountPortfolio

Get details about an account's portfolio.

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio

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"
    portfolio = await client.fetch_account_portfolio_balances(account_address=account_address)
    print(portfolio)


if __name__ == "__main__":
    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() {
    // select network: local, testnet, mainnet
    network := common.LoadNetwork("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    accountAddress := "inj1clw20s2uxeyxtam6f7m84vgae92s9eh7vygagt"
    res, err := exchangeClient.GetAccountPortfolioBalances(ctx, accountAddress)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
Parameter Type Description Required
account_address String Address of the account to get portfolio for Yes

Response Parameters

Response Example:

{
   "portfolio":{
      "accountAddress":"inj1clw20s2uxeyxtam6f7m84vgae92s9eh7vygagt",
      "bankBalances":[
         {
            "denom":"factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/atom",
            "amount":"10000000000"
         },
         {
            "denom":"factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/usdc",
            "amount":"10000000000"
         },
         {
            "denom":"factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/weth",
            "amount":"5000000000"
         },
         {
            "denom":"inj",
            "amount":"9699395972014420000000"
         },
         {
            "denom":"peggy0x44C21afAaF20c270EBbF5914Cfc3b5022173FEB7",
            "amount":"100000000000000000000"
         },
         {
            "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
            "amount":"18689670208"
         }
      ],
      "subaccounts":[
         {
            "subaccountId":"0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001",
            "denom":"inj",
            "deposit":{
               "totalBalance":"11010001000000000000",
               "availableBalance":"11010001000000000000"
            }
         },
         {
            "subaccountId":"0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001",
            "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
            "deposit":{
               "totalBalance":"298666021.6838251182660625",
               "availableBalance":"298666021.6838251182660625"
            }
         },
         {
            "subaccountId":"0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000002",
            "denom":"inj",
            "deposit":{
               "totalBalance":"1000000000000",
               "availableBalance":"1000000000000"
            }
         },
         {
            "subaccountId":"0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000000",
            "denom":"inj",
            "deposit":{
               "totalBalance":"0.458458",
               "availableBalance":"0.458458"
            }
         },
         {
            "subaccountId":"0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000000",
            "denom":"peggy0x44C21afAaF20c270EBbF5914Cfc3b5022173FEB7",
            "deposit":{
               "totalBalance":"0",
               "availableBalance":"0"
            }
         },
         {
            "subaccountId":"0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000000",
            "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
            "deposit":{
               "totalBalance":"0.170858923182467801",
               "availableBalance":"0.170858923182467801"
            }
         }
      ]
   }
}
{
 "portfolio": {
  "account_address": "inj1clw20s2uxeyxtam6f7m84vgae92s9eh7vygagt",
  "bank_balances": [
   {
    "denom": "factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/atom",
    "amount": "10000000000"
   },
   {
    "denom": "factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/usdc",
    "amount": "10000000000"
   },
   {
    "denom": "factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/weth",
    "amount": "5000000000"
   },
   {
    "denom": "inj",
    "amount": "9699395972014420000000"
   },
   {
    "denom": "peggy0x44C21afAaF20c270EBbF5914Cfc3b5022173FEB7",
    "amount": "100000000000000000000"
   },
   {
    "denom": "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
    "amount": "18689670208"
   }
  ],
  "subaccounts": [
   {
    "subaccount_id": "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000000",
    "denom": "peggy0x44C21afAaF20c270EBbF5914Cfc3b5022173FEB7",
    "deposit": {
     "total_balance": "0",
     "available_balance": "0"
    }
   },
   {
    "subaccount_id": "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000000",
    "denom": "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
    "deposit": {
     "total_balance": "0.170858923182467801",
     "available_balance": "0.170858923182467801"
    }
   },
   {
    "subaccount_id": "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000000",
    "denom": "inj",
    "deposit": {
     "total_balance": "0.458458",
     "available_balance": "0.458458"
    }
   },
   {
    "subaccount_id": "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001",
    "denom": "inj",
    "deposit": {
     "total_balance": "11010001000000000000",
     "available_balance": "11010001000000000000"
    }
   },
   {
    "subaccount_id": "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001",
    "denom": "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
    "deposit": {
     "total_balance": "298666021.6838251182660625",
     "available_balance": "298666021.6838251182660625"
    }
   },
   {
    "subaccount_id": "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000002",
    "denom": "inj",
    "deposit": {
     "total_balance": "1000000000000",
     "available_balance": "1000000000000"
    }
   }
  ]
 }
}

Parameter Type Description
portfolio Portfolio The portfolio of the account

PortfolioBalances

Parameter Type Description
account_address String The account's portfolio address
bank_balances Coin Array Account available bank balances
subaccounts SubaccountBalanceV2 Subaccounts list

Coin

Parameter Type Description
denom String Denom of the coin
amount String Amount of the coin

SubaccountBalanceV2

Parameter Type Description
subaccount_id String Related subaccount ID
denom String Coin denom on the chain
deposit SubaccountDeposit Subaccount's total balanace and available balances

SubaccountDeposit

Parameter Type Description
total_balance String All balances (in specific denom) that this subaccount has
available_balance String Available balance (in specific denom), the balance that is not used by current orders

StreamAccountPortfolio

Get continuous updates on account's portfolio.

IP rate limit group: indexer

Request Parameters

Request Example:

import asyncio
from typing import Any, Dict

from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def account_portfolio_event_processor(event: Dict[str, Any]):
    print(event)


def stream_error_processor(exception: RpcError):
    print(f"There was an error listening to account portfolio updates ({exception})")


def stream_closed_processor():
    print("The account portfolio updates stream has been closed")


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    account_address = "inj1clw20s2uxeyxtam6f7m84vgae92s9eh7vygagt"

    task = asyncio.get_event_loop().create_task(
        client.listen_account_portfolio_updates(
            account_address=account_address,
            callback=account_portfolio_event_processor,
            on_end_callback=stream_closed_processor,
            on_status_callback=stream_error_processor,
        )
    )

    await asyncio.sleep(delay=60)
    task.cancel()


if __name__ == "__main__":
    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() {
    // select network: local, testnet, mainnet
    network := common.LoadNetwork("testnet", "lb")
    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    stream, err := exchangeClient.StreamAccountPortfolio(ctx, "inj1clw20s2uxeyxtam6f7m84vgae92s9eh7vygagt", "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001", "total_balances")
    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))
        }
    }
}
Parameter Type Description Required
account_address String The account's portfolio address Yes
subaccount_id String Related subaccount ID No
callback Function Function receiving one parameter (a stream event JSON dictionary) to process each new event Yes
on_end_callback Function Function with the logic to execute when the stream connection is interrupted No
on_status_callback Function Function receiving one parameter (the exception) with the logic to execute when an exception happens No

Response Parameters

Response Example:

{
 "type": "total_balances",
 "denom": "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
 "amount": "302686408.8456",
 "subaccountId": "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001",
 "timestamp": "342423423"
}
{
 "type": "total_balances",
 "denom": "inj",
 "amount": "11040001000000000000",
 "subaccount_id": "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001",
 "timestamp": "342432343"
}
{
 "type": "total_balances",
 "denom": "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
 "amount": "302686408.8456",
 "subaccount_id": "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001"
}{
 "type": "total_balances",
 "denom": "inj",
 "amount": "11040001000000000000",
 "subaccount_id": "0xc7dca7c15c364865f77a4fb67ab11dc95502e6fe000000000000000000000001"
}
Parameter Type Description
type String Type of portfolio document (should be one of ["bank", "total_balance", "available_balance"])
denom String Denom of portfolio entry
amount String Amount of portfolio entry
subaccount_id String Subaccount id of portfolio entry

Chain 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 as the Chain API queries the blockchain state which doesn’t include historical records.

- Account

Includes all messages related to accounts and transfers.

MsgDeposit

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())
    subaccount_id = address.get_subaccount_id(index=0)

    # prepare tx msg
    msg = composer.msg_deposit(
        sender=address.to_acc_bech32(), subaccount_id=subaccount_id, amount=0.000001, denom="INJ"
    )

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "fmt"
    "os"
    "time"

    "cosmossdk.io/math"

    "github.com/InjectiveLabs/sdk-go/client"

    "github.com/InjectiveLabs/sdk-go/client/common"

    sdktypes "github.com/cosmos/cosmos-sdk/types"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )
    if err != nil {
        panic(err)
    }
    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    msg := &exchangetypes.MsgDeposit{
        Sender:       senderAddress.String(),
        SubaccountId: "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
        Amount: sdktypes.Coin{
            Denom: "inj", Amount: math.NewInt(1000000000000000000), // 1 INJ
        },
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    err = chainClient.QueueBroadcastMsg(msg)

    if err != nil {
        fmt.Println(err)
    }

    time.Sleep(time.Second * 5)

    gasFee, err := chainClient.GetGasFee()

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("gas fee:", gasFee, "INJ")
}
ParameterTypeDescriptionRequired
senderStringThe address doing the depositYes
subaccount_idStringSubaccount ID to deposit funds into. If empty, the coin will be deposited to the sender's default subaccount address.No
amountCoinThe token amount to depositYes


Coin

ParameterTypeDescriptionRequired
denomStringThe token denomYes
amountStringThe amount of tokensYes

Response Parameters

Response Example:

txhash: "49CA54DA708B5F58E401B661A8A6B590447AFCFCD192D95AE2DAFDBEB00DCD33"
raw_log: "[]"

gas wanted: 105793
gas fee: 0.0000528965 INJ
DEBU[0001] broadcastTx with nonce 3491                   fn=func1 src="client/chain/chain.go:598"
DEBU[0002] msg batch committed successfully at height 5212649  fn=func1 src="client/chain/chain.go:619" txHash=8B3F45BB7247C0BFC916B4D9177601E512BBAEF8FA60E5B61D5CC815910D059F
DEBU[0002] nonce incremented to 3492                     fn=func1 src="client/chain/chain.go:623"
DEBU[0002] gas wanted:  132099                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.0000660495 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgWithdraw

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())
    subaccount_id = address.get_subaccount_id(index=0)

    # prepare tx msg
    msg = composer.msg_withdraw(sender=address.to_acc_bech32(), subaccount_id=subaccount_id, amount=1, denom="USDT")

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "fmt"
    "os"
    "time"

    "cosmossdk.io/math"

    "github.com/InjectiveLabs/sdk-go/client"
    "github.com/InjectiveLabs/sdk-go/client/common"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
    sdktypes "github.com/cosmos/cosmos-sdk/types"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    msg := &exchangetypes.MsgWithdraw{
        Sender:       senderAddress.String(),
        SubaccountId: "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
        Amount: sdktypes.Coin{
            Denom: "inj", Amount: math.NewInt(1000000000000000000), // 1 INJ
        },
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    err = chainClient.QueueBroadcastMsg(msg)

    if err != nil {
        fmt.Println(err)
    }

    time.Sleep(time.Second * 5)

    gasFee, err := chainClient.GetGasFee()

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("gas fee:", gasFee, "INJ")
}
ParameterTypeDescriptionRequired
senderStringThe address doing the withdrawYes
subaccount_idStringSubaccount ID to withdraw funds fromYes
amountCoinThe token amount to depositYes


Coin

ParameterTypeDescriptionRequired
denomStringThe token denomYes
amountStringThe amount of tokensYes

Response Parameters

Response Example:

txhash: "30724652FB970C8C08B0179D134AC519795068885541B08C6BB0AE3E8F0E59CE"
raw_log: "[]"

gas wanted: 111105
gas fee: 0.0000555525 INJ
DEBU[0001] broadcastTx with nonce 3504                   fn=func1 src="client/chain/chain.go:598"
DEBU[0004] msg batch committed successfully at height 5214520  fn=func1 src="client/chain/chain.go:619" txHash=B73529AE8EE92B931B5E52102DE67251B71B492421D718644A79ED826BD6B451
DEBU[0004] nonce incremented to 3505                     fn=func1 src="client/chain/chain.go:623"
DEBU[0004] gas wanted:  129606                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.000064803 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgSubaccountTransfer

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os
from decimal import Decimal

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())
    subaccount_id = address.get_subaccount_id(index=0)
    dest_subaccount_id = address.get_subaccount_id(index=1)

    # prepare tx msg
    msg = composer.msg_subaccount_transfer(
        sender=address.to_acc_bech32(),
        source_subaccount_id=subaccount_id,
        destination_subaccount_id=dest_subaccount_id,
        amount=Decimal(100),
        denom="INJ",
    )

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "fmt"
    "os"
    "time"

    "cosmossdk.io/math"

    "github.com/InjectiveLabs/sdk-go/client"
    "github.com/InjectiveLabs/sdk-go/client/common"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
    sdktypes "github.com/cosmos/cosmos-sdk/types"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    msg := &exchangetypes.MsgSubaccountTransfer{
        Sender:                  senderAddress.String(),
        SourceSubaccountId:      "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
        DestinationSubaccountId: "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000001",
        Amount: sdktypes.Coin{
            Denom: "inj", Amount: math.NewInt(1000000000000000000), // 1 INJ
        },
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    err = chainClient.QueueBroadcastMsg(msg)

    if err != nil {
        fmt.Println(err)
    }

    time.Sleep(time.Second * 5)

    gasFee, err := chainClient.GetGasFee()

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("gas fee:", gasFee, "INJ")
}
ParameterTypeDescriptionRequired
senderStringThe sender's addressYes
source_subaccount_idStringSubaccount ID from where the funds are deductedYes
destination_subaccount_idStringSubaccount ID the funds are deposited intoYes
amountCoinThe transfer token amountYes


Coin

ParameterTypeDescriptionRequired
denomStringThe token denomYes
amountStringThe amount of tokensYes

Response Parameters

Response Example:

txhash: "2E37F37501D025D09FADEB8A64DD47362292DE47D81514723BB061410409C956"
raw_log: "[]"

gas wanted: 97883
gas fee: 0.0000489415 INJ
DEBU[0001] broadcastTx with nonce 3506                   fn=func1 src="client/chain/chain.go:598"
DEBU[0003] msg batch committed successfully at height 5214566  fn=func1 src="client/chain/chain.go:619" txHash=11181E2B0ACD1B0358CA19D52EF05D191B24F4E91B7548E94F3B7AC5841ABD8F
DEBU[0003] nonce incremented to 3507                     fn=func1 src="client/chain/chain.go:623"
DEBU[0003] gas wanted:  122103                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.0000610515 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgExternalTransfer

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os
from decimal import Decimal

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())
    subaccount_id = address.get_subaccount_id(index=0)
    dest_subaccount_id = "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"

    # prepare tx msg
    msg = composer.msg_external_transfer(
        sender=address.to_acc_bech32(),
        source_subaccount_id=subaccount_id,
        destination_subaccount_id=dest_subaccount_id,
        amount=Decimal(100),
        denom="INJ",
    )

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "fmt"
    "os"
    "time"

    "cosmossdk.io/math"

    "github.com/InjectiveLabs/sdk-go/client"
    "github.com/InjectiveLabs/sdk-go/client/common"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
    sdktypes "github.com/cosmos/cosmos-sdk/types"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    msg := &exchangetypes.MsgExternalTransfer{
        Sender:                  senderAddress.String(),
        SourceSubaccountId:      "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
        DestinationSubaccountId: "0xbdaedec95d563fb05240d6e01821008454c24c36000000000000000000000000",
        Amount: sdktypes.Coin{
            Denom: "inj", Amount: math.NewInt(1000000000000000000), // 1 INJ
        },
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    err = chainClient.QueueBroadcastMsg(msg)

    if err != nil {
        fmt.Println(err)
    }

    time.Sleep(time.Second * 5)

    gasFee, err := chainClient.GetGasFee()

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("gas fee:", gasFee, "INJ")
}
ParameterTypeDescriptionRequired
senderStringThe sender's addressYes
source_subaccount_idStringSubaccount ID from where the funds are deductedYes
destination_subaccount_idStringSubaccount ID the funds are deposited intoYes
amountCoinThe transfer token amountYes


Coin

ParameterTypeDescriptionRequired
denomStringThe token denomYes
amountStringThe amount of tokensYes

Response Parameters

Response Example:

txhash: "6790503C993094B50A7E0CBAD4B27E1ABFE24060509CB189DCC408A0AD99F894"
raw_log: "[]"

gas wanted: 99159
gas fee: 0.0000495795 INJ
DEBU[0002] broadcastTx with nonce 3658                   fn=func1 src="client/chain/chain.go:607"
DEBU[0005] msg batch committed successfully at height 6556107  fn=func1 src="client/chain/chain.go:628" txHash=BD185F427DD1987969605695779C48FD4BEECC7AEC9C51ED5E0BF1747A471F4E
DEBU[0005] nonce incremented to 3659                     fn=func1 src="client/chain/chain.go:632"
DEBU[0005] gas wanted:  122397                           fn=func1 src="client/chain/chain.go:633"
gas fee: 0.0000611985 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgSendToEth

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv
import requests
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    # prepare msg
    asset = "injective-protocol"
    coingecko_endpoint = f"https://api.coingecko.com/api/v3/simple/price?ids={asset}&vs_currencies=usd"
    token_price = requests.get(coingecko_endpoint).json()[asset]["usd"]
    minimum_bridge_fee_usd = 10
    bridge_fee = minimum_bridge_fee_usd / token_price

    # prepare tx msg
    msg = composer.MsgSendToEth(
        sender=address.to_acc_bech32(),
        denom="INJ",
        eth_dest="0xaf79152ac5df276d9a8e1e2e22822f9713474902",
        amount=23,
        bridge_fee=bridge_fee,
    )

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "fmt"
    "os"
    "time"

    "cosmossdk.io/math"

    "github.com/InjectiveLabs/sdk-go/client"
    "github.com/InjectiveLabs/sdk-go/client/common"

    peggytypes "github.com/InjectiveLabs/sdk-go/chain/peggy/types"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
    sdktypes "github.com/cosmos/cosmos-sdk/types"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ethDest := "0xaf79152ac5df276d9a8e1e2e22822f9713474902"

    amount := sdktypes.Coin{
        Denom: "inj", Amount: math.NewInt(5000000000000000000), // 5 INJ
    }
    bridgeFee := sdktypes.Coin{
        Denom: "inj", Amount: math.NewInt(2000000000000000000), // 2 INJ
    }

    msg := &peggytypes.MsgSendToEth{
        Sender:    senderAddress.String(),
        Amount:    amount,
        EthDest:   ethDest,
        BridgeFee: bridgeFee,
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    err = chainClient.QueueBroadcastMsg(msg)

    if err != nil {
        fmt.Println(err)
    }

    time.Sleep(time.Second * 5)

    gasFee, err := chainClient.GetGasFee()

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("gas fee:", gasFee, "INJ")
}
ParameterTypeDescriptionRequired
senderStringThe sender's addressYes
eth_destStringDestination Ethereum addressYes
amountCoinThe coin to send across the bridge (note the restriction that this is a single coin, not a set of coins)Yes
bridge_feeCoinThe fee paid for the bridge, distinct from the fee paid to the chain to actually send this message in the first place. So a successful send has two layers of fees for the userYes


Coin

ParameterTypeDescriptionRequired
denomStringThe token denomYes
amountStringThe amount of tokensYes

Response Parameters

Response Example:

txhash: "5529016817553230024B45B44ABEB0538DC0AF9EEE0DEAD467B91C85BCCCAC87"
raw_log: "[]"

gas wanted: 125732
gas fee: 0.000062866 INJ
DEBU[0001] broadcastTx with nonce 3515                   fn=func1 src="client/chain/chain.go:598"
DEBU[0004] msg batch committed successfully at height 5215066  fn=func1 src="client/chain/chain.go:619" txHash=391AB87558318BD7FF2CCB9D68ED309AD073FA64C8395A493D6C347FF572AF38
DEBU[0004] nonce incremented to 3516                     fn=func1 src="client/chain/chain.go:623"
DEBU[0004] gas wanted:  161907                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.0000809535 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

SendToInjective

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import json
import os

import dotenv

from pyinjective.core.network import Network
from pyinjective.sendtocosmos import Peggo


async def main() -> None:
    dotenv.load_dotenv()
    private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: testnet, mainnet
    network = Network.testnet()
    peggo_composer = Peggo(network=network.string())

    ethereum_endpoint = "https://eth-goerli.g.alchemy.com/v2/q-7JVv4mTfsNh1y_djKkKn3maRBGILLL"

    maxFeePerGas_Gwei = 4
    maxPriorityFeePerGas_Gwei = 4

    token_contract = "0xBe8d71D26525440A03311cc7fa372262c5354A3c"
    receiver = "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku"
    amount = 1

    data = (
        '{"@type": "/injective.exchange.v1beta1.MsgDeposit",'
        '"sender": "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",'
        '"subaccountId": "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",'
        '"amount": {"denom": "inj","amount": "1000000000000000000"}}'
    )

    with open("../pyinjective/Peggo_ABI.json") as pego_file:
        peggo_data = pego_file.read()
    peggo_abi = json.loads(peggo_data)

    peggo_composer.sendToInjective(
        ethereum_endpoint=ethereum_endpoint,
        private_key=private_key,
        token_contract=token_contract,
        receiver=receiver,
        amount=amount,
        maxFeePerGas=maxFeePerGas_Gwei,
        maxPriorityFeePerGas=maxPriorityFeePerGas_Gwei,
        data=data,
        peggo_abi=peggo_abi,
    )


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
ParameterTypeDescriptionRequired
ethereum_endpointStringThe ethereum endpoint, you can get one from providers like Infura and AlchemyYes
private_keyStringPrivate key of the account to be used to sign the transactionYes
token_contractStringThe token contract, you can find the contract for the token you want to transfer on etherscanYes
receiverStringThe Injective Chain address to receive the fundsYes
amountFloatThe amount to transferYes
maxFeePerGasIntegerThe maxFeePerGas in GweiYes
maxPriorityFeePerGasIntegerThe maxPriorityFeePerGas in GweiYes
peggo_abiStringPeggo contract ABI|Yes
dataStringThe body of the message to send to Injective chain to do the depositYes
decimalsIntegerNumber of decimals in Injective chain of the token being transferred (default: 18)No

Response Parameters

Response Example:

Transferred 1 0x36b3d7ace7201e28040eff30e815290d7b37ffad from 0xbdAEdEc95d563Fb05240d6e01821008454c24C36 to inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku

Transaction hash: 0xb538abc7c2f893a2fe24c7a8ea606ff48d980a754499f1bec89b862c2bcb9ea7

GetTx

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    tx_hash = "D265527E3171C47D01D7EC9B839A95F8F794D4E683F26F5564025961C96EFDDA"
    tx_logs = await client.fetch_tx(hash=tx_hash)
    print(tx_logs)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "fmt"
    "os"
    "time"

    "github.com/InjectiveLabs/sdk-go/client"
    "github.com/InjectiveLabs/sdk-go/client/common"

    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
)

func main() {
    // network := common.LoadNetwork("mainnet", "k8s")
    network := common.LoadNetwork("mainnet", "lb")
    tmRPC, err := rpchttp.New(network.TmEndpoint, "/websocket")

    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmRPC)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    timeOutCtx, cancelFn := context.WithTimeout(ctx, 30*time.Second)
    defer cancelFn()

    resp, err := chainClient.GetTx(timeOutCtx, "A2B2B971C690AE7977451D24D6F450AECE6BCCB271E91E32C2563342DDA5254B")
    if err != nil {
        panic(err)
    }

    fmt.Println(resp.TxResponse)
}
ParameterTypeDescriptionRequired
hashStringThe TX hash to query, encoded as a hex stringYes

Response Example:

{
   "tx":{
      "body":{
         "messages":[
            "OrderedDict("[
               "(""@type",
               "/cosmos.authz.v1beta1.MsgExec"")",
               "(""grantee",
               "inj1v4sm2qehqzmnf32d7syyyspetzyaydyj4r4yv7"")",
               "(""msgs",
               [
                  "OrderedDict("[
                     "(""@type",
                     "/injective.exchange.v1beta1.MsgCreateSpotMarketOrder"")",
                     "(""sender",
                     "inj1v4sm2qehqzmnf32d7syyyspetzyaydyj4r4yv7"")",
                     "(""order",
                     {
                        "marketId":"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
                        "orderInfo":{
                           "subaccountId":"0x6561b5033700b734c54df4084240395889d23492000000000000000000000000",
                           "feeRecipient":"inj1v4sm2qehqzmnf32d7syyyspetzyaydyj4r4yv7",
                           "price":"10194000",
                           "quantity":"175000000000000000000000000000000000",
                           "cid":""
                        },
                        "orderType":"SELL",
                        "triggerPrice":"0"
                     }")"
                  ]")"
               ]")"
            ]")"
         ],
         "timeoutHeight":"17518637",
         "memo":"",
         "extensionOptions":[

         ],
         "nonCriticalExtensionOptions":[

         ]
      },
      "authInfo":{
         "signerInfos":[
            {
               "publicKey":"OrderedDict("[
                  "(""@type",
                  "/injective.crypto.v1beta1.ethsecp256k1.PubKey"")",
                  "(""key",
                  "AmHqvENFf9E5s9vQFLQbcbHv4OIKTEWXVO4f7PZS9YOz"")"
               ]")",
               "modeInfo":{
                  "single":{
                     "mode":"SIGN_MODE_DIRECT"
                  }
               },
               "sequence":"211255"
            }
         ],
         "fee":{
            "amount":[
               {
                  "denom":"inj",
                  "amount":"52378500000000"
               }
            ],
            "gasLimit":"104757",
            "payer":"",
            "granter":""
         }
      },
      "signatures":[
         "Hn4Ugl50quZLQv/btmpWGMDr4F4RX5eeaGMIbc5VzC06a0sH3yRLvcNPyAcODcVjMQ1jbIRM01SYkvu2By+xJw=="
      ]
   },
   "txResponse":{
      "height":"17518608",
      "txhash":"D265527E3171C47D01D7EC9B839A95F8F794D4E683F26F5564025961C96EFDDA",
      "data":"126F0A252F636F736D6F732E617574687A2E763162657461312E4D736745786563526573706F6E736512460A440A42307834316630316536623266646433623463303631663834323235666165653033333536646238643137656265373631356661393232663132363861666434316136",
      "rawLog":"[{\"msg_index\":0,\"events\":[{\"type\":\"message\",\"attributes\":[{\"key\":\"action\",\"value\":\"/cosmos.authz.v1beta1.MsgExec\"},{\"key\":\"sender\",\"value\":\"inj1v4sm2qehqzmnf32d7syyyspetzyaydyj4r4yv7\"},{\"key\":\"module\",\"value\":\"authz\"}]},{\"type\":\"coin_spent\",\"attributes\":[{\"key\":\"spender\",\"value\":\"inj1v4sm2qehqzmnf32d7syyyspetzyaydyj4r4yv7\"},{\"key\":\"amount\",\"value\":\"175000000000000000inj\"},{\"key\":\"authz_msg_index\",\"value\":\"0\"}]},{\"type\":\"coin_received\",\"attributes\":[{\"key\":\"receiver\",\"value\":\"inj14vnmw2wee3xtrsqfvpcqg35jg9v7j2vdpzx0kk\"},{\"key\":\"amount\",\"value\":\"175000000000000000inj\"},{\"key\":\"authz_msg_index\",\"value\":\"0\"}]},{\"type\":\"transfer\",\"attributes\":[{\"key\":\"recipient\",\"value\":\"inj14vnmw2wee3xtrsqfvpcqg35jg9v7j2vdpzx0kk\"},{\"key\":\"sender\",\"value\":\"inj1v4sm2qehqzmnf32d7syyyspetzyaydyj4r4yv7\"},{\"key\":\"amount\",\"value\":\"175000000000000000inj\"},{\"key\":\"authz_msg_index\",\"value\":\"0\"}]},{\"type\":\"message\",\"attributes\":[{\"key\":\"sender\",\"value\":\"inj1v4sm2qehqzmnf32d7syyyspetzyaydyj4r4yv7\"},{\"key\":\"authz_msg_index\",\"value\":\"0\"}]}]}]",
      "logs":[
         {
            "events":[
               {
                  "type":"message",
                  "attributes":[
                     {
                        "key":"action",
                        "value":"/cosmos.authz.v1beta1.MsgExec"
                     },
                     {
                        "key":"sender",
                        "value":"inj1v4sm2qehqzmnf32d7syyyspetzyaydyj4r4yv7"
                     },
                     {
                        "key":"module",
                        "value":"authz"
                     }
                  ]
               },
               {
                  "type":"coin_spent",
                  "attributes":[
                     {
                        "key":"spender",
                        "value":"inj1v4sm2qehqzmnf32d7syyyspetzyaydyj4r4yv7"
                     },
                     {
                        "key":"amount",
                        "value":"175000000000000000inj"
                     },
                     {
                        "key":"authz_msg_index",
                        "value":"0"
                     }
                  ]
               },
               {
                  "type":"coin_received",
                  "attributes":[
                     {
                        "key":"receiver",
                        "value":"inj14vnmw2wee3xtrsqfvpcqg35jg9v7j2vdpzx0kk"
                     },
                     {
                        "key":"amount",
                        "value":"175000000000000000inj"
                     },
                     {
                        "key":"authz_msg_index",
                        "value":"0"
                     }
                  ]
               },
               {
                  "type":"transfer",
                  "attributes":[
                     {
                        "key":"recipient",
                        "value":"inj14vnmw2wee3xtrsqfvpcqg35jg9v7j2vdpzx0kk"
                     },
                     {
                        "key":"sender",
                        "value":"inj1v4sm2qehqzmnf32d7syyyspetzyaydyj4r4yv7"
                     },
                     {
                        "key":"amount",
                        "value":"175000000000000000inj"
                     },
                     {
                        "key":"authz_msg_index",
                        "value":"0"
                     }
                  ]
               },
               {
                  "type":"message",
                  "attributes":[
                     {
                        "key":"sender",
                        "value":"inj1v4sm2qehqzmnf32d7syyyspetzyaydyj4r4yv7"
                     },
                     {
                        "key":"authz_msg_index",
                        "value":"0"
                     }
                  ]
               }
            ],
            "msgIndex":0,
            "log":""
         }
      ],
      "gasWanted":"104757",
      "gasUsed":"102564",
      "tx":"OrderedDict("[
         "(""@type",
         "/cosmos.tx.v1beta1.Tx"")",
         "(""body",
         {
            "messages":[
               "OrderedDict("[
                  "(""@type",
                  "/cosmos.authz.v1beta1.MsgExec"")",
                  "(""grantee",
                  "inj1v4sm2qehqzmnf32d7syyyspetzyaydyj4r4yv7"")",
                  "(""msgs",
                  [
                     "OrderedDict("[
                        "(""@type",
                        "/injective.exchange.v1beta1.MsgCreateSpotMarketOrder"")",
                        "(""sender",
                        "inj1v4sm2qehqzmnf32d7syyyspetzyaydyj4r4yv7"")",
                        "(""order",
                        {
                           "marketId":"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
                           "orderInfo":{
                              "subaccountId":"0x6561b5033700b734c54df4084240395889d23492000000000000000000000000",
                              "feeRecipient":"inj1v4sm2qehqzmnf32d7syyyspetzyaydyj4r4yv7",
                              "price":"10194000",
                              "quantity":"175000000000000000000000000000000000",
                              "cid":""
                           },
                           "orderType":"SELL",
                           "triggerPrice":"0"
                        }")"
                     ]")"
                  ]")"
               ]")"
            ],
            "timeoutHeight":"17518637",
            "memo":"",
            "extensionOptions":[

            ],
            "nonCriticalExtensionOptions":[

            ]
         }")",
         "(""authInfo",
         {
            "signerInfos":[
               {
                  "publicKey":"OrderedDict("[
                     "(""@type",
                     "/injective.crypto.v1beta1.ethsecp256k1.PubKey"")",
                     "(""key",
                     "AmHqvENFf9E5s9vQFLQbcbHv4OIKTEWXVO4f7PZS9YOz"")"
                  ]")",
                  "modeInfo":{
                     "single":{
                        "mode":"SIGN_MODE_DIRECT"
                     }
                  },
                  "sequence":"211255"
               }
            ],
            "fee":{
               "amount":[
                  {
                     "denom":"inj",
                     "amount":"52378500000000"
                  }
               ],
               "gasLimit":"104757",
               "payer":"",
               "granter":""
            }
         }")",
         "(""signatures",
         [
            "Hn4Ugl50quZLQv/btmpWGMDr4F4RX5eeaGMIbc5VzC06a0sH3yRLvcNPyAcODcVjMQ1jbIRM01SYkvu2By+xJw=="
         ]")"
      ]")",
      "timestamp":"2023-10-23T18:48:19Z",
      "events":[
         {
            "type":"coin_spent",
            "attributes":[
               {
                  "key":"spender",
                  "value":"inj1v4sm2qehqzmnf32d7syyyspetzyaydyj4r4yv7",
                  "index":true
               },
               {
                  "key":"amount",
                  "value":"52378500000000inj",
                  "index":true
               }
            ]
         },
         {
            "type":"coin_received",
            "attributes":[
               {
                  "key":"receiver",
                  "value":"inj17xpfvakm2amg962yls6f84z3kell8c5l6s5ye9",
                  "index":true
               },
               {
                  "key":"amount",
                  "value":"52378500000000inj",
                  "index":true
               }
            ]
         },
         {
            "type":"transfer",
            "attributes":[
               {
                  "key":"recipient",
                  "value":"inj17xpfvakm2amg962yls6f84z3kell8c5l6s5ye9",
                  "index":true
               },
               {
                  "key":"sender",
                  "value":"inj1v4sm2qehqzmnf32d7syyyspetzyaydyj4r4yv7",
                  "index":true
               },
               {
                  "key":"amount",
                  "value":"52378500000000inj",
                  "index":true
               }
            ]
         },
         {
            "type":"message",
            "attributes":[
               {
                  "key":"sender",
                  "value":"inj1v4sm2qehqzmnf32d7syyyspetzyaydyj4r4yv7",
                  "index":true
               }
            ]
         },
         {
            "type":"tx",
            "attributes":[
               {
                  "key":"fee",
                  "value":"52378500000000inj",
                  "index":true
               },
               {
                  "key":"fee_payer",
                  "value":"inj1v4sm2qehqzmnf32d7syyyspetzyaydyj4r4yv7",
                  "index":true
               }
            ]
         },
         {
            "type":"tx",
            "attributes":[
               {
                  "key":"acc_seq",
                  "value":"inj1v4sm2qehqzmnf32d7syyyspetzyaydyj4r4yv7/211255",
                  "index":true
               }
            ]
         },
         {
            "type":"tx",
            "attributes":[
               {
                  "key":"signature",
                  "value":"Hn4Ugl50quZLQv/btmpWGMDr4F4RX5eeaGMIbc5VzC06a0sH3yRLvcNPyAcODcVjMQ1jbIRM01SYkvu2By+xJw==",
                  "index":true
               }
            ]
         },
         {
            "type":"message",
            "attributes":[
               {
                  "key":"action",
                  "value":"/cosmos.authz.v1beta1.MsgExec",
                  "index":true
               },
               {
                  "key":"sender",
                  "value":"inj1v4sm2qehqzmnf32d7syyyspetzyaydyj4r4yv7",
                  "index":true
               },
               {
                  "key":"module",
                  "value":"authz",
                  "index":true
               }
            ]
         },
         {
            "type":"coin_spent",
            "attributes":[
               {
                  "key":"spender",
                  "value":"inj1v4sm2qehqzmnf32d7syyyspetzyaydyj4r4yv7",
                  "index":true
               },
               {
                  "key":"amount",
                  "value":"175000000000000000inj",
                  "index":true
               },
               {
                  "key":"authz_msg_index",
                  "value":"0",
                  "index":true
               }
            ]
         },
         {
            "type":"coin_received",
            "attributes":[
               {
                  "key":"receiver",
                  "value":"inj14vnmw2wee3xtrsqfvpcqg35jg9v7j2vdpzx0kk",
                  "index":true
               },
               {
                  "key":"amount",
                  "value":"175000000000000000inj",
                  "index":true
               },
               {
                  "key":"authz_msg_index",
                  "value":"0",
                  "index":true
               }
            ]
         },
         {
            "type":"transfer",
            "attributes":[
               {
                  "key":"recipient",
                  "value":"inj14vnmw2wee3xtrsqfvpcqg35jg9v7j2vdpzx0kk",
                  "index":true
               },
               {
                  "key":"sender",
                  "value":"inj1v4sm2qehqzmnf32d7syyyspetzyaydyj4r4yv7",
                  "index":true
               },
               {
                  "key":"amount",
                  "value":"175000000000000000inj",
                  "index":true
               },
               {
                  "key":"authz_msg_index",
                  "value":"0",
                  "index":true
               }
            ]
         },
         {
            "type":"message",
            "attributes":[
               {
                  "key":"sender",
                  "value":"inj1v4sm2qehqzmnf32d7syyyspetzyaydyj4r4yv7",
                  "index":true
               },
               {
                  "key":"authz_msg_index",
                  "value":"0",
                  "index":true
               }
            ]
         }
      ],
      "codespace":"",
      "code":0,
      "info":""
   }
}
code: 0
codespace: ""
data: 0AC1010A302F696E6A6563746976652E65786368616E67652E763162657461312E4D736742617463685570646174654F7264657273128C011202010122423078396638313937363932323364333439646462313738333335303831396437396235373736323363623361613163633462346534326361643638666264393462362242307834656239333035636565663365616264663762653734313338343931633966373738663439613131613164643733613930623761666366323731353263633935
events:
- attributes:
  - index: true
    key: YWNjX3NlcQ==
    value: aW5qMWFzNGpydGE4ODV6M3puMzdhMnozeGs5Y2RkdDhkeXptZnZ3ZW13LzEwODczMTIy
  type: tx
- attributes:
  - index: true
    key: c2lnbmF0dXJl
    value: eWtDcmVOVjdEaHF1Z1k5d2gvc25EWFF4VUtibC9ZK3h3Nmw5d3ZhU28zcExSYU9rVlR2b3VuaERmRy9ZYzl0SEplYVd6L1d2am1OekU2MmFJNHBrSHdFPQ==
  type: tx
- attributes:
  - index: true
    key: c3BlbmRlcg==
    value: aW5qMWFzNGpydGE4ODV6M3puMzdhMnozeGs5Y2RkdDhkeXptZnZ3ZW13
  - index: true
    key: YW1vdW50
    value: MzY5ODAxMDAwMDAwMDAwaW5q
  type: coin_spent
- attributes:
  - index: true
    key: cmVjZWl2ZXI=
    value: aW5qMTd4cGZ2YWttMmFtZzk2MnlsczZmODR6M2tlbGw4YzVsNnM1eWU5
  - index: true
    key: YW1vdW50
    value: MzY5ODAxMDAwMDAwMDAwaW5q
  type: coin_received
- attributes:
  - index: true
    key: cmVjaXBpZW50
    value: aW5qMTd4cGZ2YWttMmFtZzk2MnlsczZmODR6M2tlbGw4YzVsNnM1eWU5
  - index: true
    key: c2VuZGVy
    value: aW5qMWFzNGpydGE4ODV6M3puMzdhMnozeGs5Y2RkdDhkeXptZnZ3ZW13
  - index: true
    key: YW1vdW50
    value: MzY5ODAxMDAwMDAwMDAwaW5q
  type: transfer
- attributes:
  - index: true
    key: c2VuZGVy
    value: aW5qMWFzNGpydGE4ODV6M3puMzdhMnozeGs5Y2RkdDhkeXptZnZ3ZW13
  type: message
- attributes:
  - index: true
    key: ZmVl
    value: MzY5ODAxMDAwMDAwMDAwaW5q
  - index: true
    key: ZmVlX3BheWVy
    value: aW5qMWFzNGpydGE4ODV6M3puMzdhMnozeGs5Y2RkdDhkeXptZnZ3ZW13
  type: tx
- attributes:
  - index: true
    key: YWN0aW9u
    value: L2luamVjdGl2ZS5leGNoYW5nZS52MWJldGExLk1zZ0JhdGNoVXBkYXRlT3JkZXJz
  type: message
- attributes:
  - index: true
    key: aXNMaW1pdENhbmNlbA==
    value: dHJ1ZQ==
  - index: true
    key: bGltaXRfb3JkZXI=
    value: eyJvcmRlcl9pbmZvIjp7InN1YmFjY291bnRfaWQiOiIweGVjMmIyMWFmYTczZDA1MTE0ZTNlZWE4NTEzNThiODZiNTY3NjkwNWIwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDEiLCJmZWVfcmVjaXBpZW50IjoiaW5qMWFzNGpydGE4ODV6M3puMzdhMnozeGs5Y2RkdDhkeXptZnZ3ZW13IiwicHJpY2UiOiI3NzM1MDAwLjAwMDAwMDAwMDAwMDAwMDAwMCIsInF1YW50aXR5IjoiNjQ2LjU2OTAwMDAwMDAwMDAwMDAwMCJ9LCJvcmRlcl90eXBlIjoiU0VMTF9QTyIsIm1hcmdpbiI6IjAuMDAwMDAwMDAwMDAwMDAwMDAwIiwiZmlsbGFibGUiOiI2NDYuNTY5MDAwMDAwMDAwMDAwMDAwIiwidHJpZ2dlcl9wcmljZSI6bnVsbCwib3JkZXJfaGFzaCI6ImhTZUNBOEU1a0krdmEzZUdLMnhWUGJxSlZybzNSUzlPRkJCVHhxMXhtVDg9In0=
  - index: true
    key: bWFya2V0X2lk
    value: IjB4OWI5OTgwMTY3ZWNjMzY0NWZmMWE1NTE3ODg2NjUyZDk0YTA4MjVlNTRhNzdkMjA1N2NiYmUzZWJlZTAxNTk2MyI=
  - index: true
    key: bWFya2V0X29yZGVyX2NhbmNlbA==
    value: bnVsbA==
  type: injective.exchange.v1beta1.EventCancelDerivativeOrder
- attributes:
  - index: true
    key: aXNMaW1pdENhbmNlbA==
    value: dHJ1ZQ==
  - index: true
    key: bGltaXRfb3JkZXI=
    value: eyJvcmRlcl9pbmZvIjp7InN1YmFjY291bnRfaWQiOiIweGVjMmIyMWFmYTczZDA1MTE0ZTNlZWE4NTEzNThiODZiNTY3NjkwNWIwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDEiLCJmZWVfcmVjaXBpZW50IjoiaW5qMWFzNGpydGE4ODV6M3puMzdhMnozeGs5Y2RkdDhkeXptZnZ3ZW13IiwicHJpY2UiOiI3NjY0MDAwLjAwMDAwMDAwMDAwMDAwMDAwMCIsInF1YW50aXR5IjoiNjQ2LjU2OTAwMDAwMDAwMDAwMDAwMCJ9LCJvcmRlcl90eXBlIjoiQlVZX1BPIiwibWFyZ2luIjoiOTkxMDYwOTYzLjIwMDAwMDAwMDAwMDAwMDAwMCIsImZpbGxhYmxlIjoiNjQ2LjU2OTAwMDAwMDAwMDAwMDAwMCIsInRyaWdnZXJfcHJpY2UiOm51bGwsIm9yZGVyX2hhc2giOiJnYllhaEVIdFhLY0J3RkgvazU4ZmxQdVZlUWRzcGlabjA5NWZia3E0a0dNPSJ9
  - index: true
    key: bWFya2V0X2lk
    value: IjB4OWI5OTgwMTY3ZWNjMzY0NWZmMWE1NTE3ODg2NjUyZDk0YTA4MjVlNTRhNzdkMjA1N2NiYmUzZWJlZTAxNTk2MyI=
  - index: true
    key: bWFya2V0X29yZGVyX2NhbmNlbA==
    value: bnVsbA==
  type: injective.exchange.v1beta1.EventCancelDerivativeOrder
- attributes:
  - index: true
    key: YnV5X29yZGVycw==
    value: W10=
  - index: true
    key: bWFya2V0X2lk
    value: IjB4OWI5OTgwMTY3ZWNjMzY0NWZmMWE1NTE3ODg2NjUyZDk0YTA4MjVlNTRhNzdkMjA1N2NiYmUzZWJlZTAxNTk2MyI=
  - index: true
    key: c2VsbF9vcmRlcnM=
    value: W3sib3JkZXJfaW5mbyI6eyJzdWJhY2NvdW50X2lkIjoiMHhlYzJiMjFhZmE3M2QwNTExNGUzZWVhODUxMzU4Yjg2YjU2NzY5MDViMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAxIiwiZmVlX3JlY2lwaWVudCI6ImluajFhczRqcnRhODg1ejN6bjM3YTJ6M3hrOWNkZHQ4ZHl6bWZ2d2VtdyIsInByaWNlIjoiNzczNzAwMC4wMDAwMDAwMDAwMDAwMDAwMDAiLCJxdWFudGl0eSI6IjY0Ni4zMzcwMDAwMDAwMDAwMDAwMDAifSwib3JkZXJfdHlwZSI6IlNFTExfUE8iLCJtYXJnaW4iOiIwLjAwMDAwMDAwMDAwMDAwMDAwMCIsImZpbGxhYmxlIjoiNjQ2LjMzNzAwMDAwMDAwMDAwMDAwMCIsInRyaWdnZXJfcHJpY2UiOm51bGwsIm9yZGVyX2hhc2giOiJuNEdYYVNJOU5KM2JGNE0xQ0JuWG0xZDJJOHM2b2N4TFRrTEsxbys5bExZPSJ9XQ==
  type: injective.exchange.v1beta1.EventNewDerivativeOrders
- attributes:
  - index: true
    key: YnV5X29yZGVycw==
    value: W3sib3JkZXJfaW5mbyI6eyJzdWJhY2NvdW50X2lkIjoiMHhlYzJiMjFhZmE3M2QwNTExNGUzZWVhODUxMzU4Yjg2YjU2NzY5MDViMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAxIiwiZmVlX3JlY2lwaWVudCI6ImluajFhczRqcnRhODg1ejN6bjM3YTJ6M3hrOWNkZHQ4ZHl6bWZ2d2VtdyIsInByaWNlIjoiNzY2NjAwMC4wMDAwMDAwMDAwMDAwMDAwMDAiLCJxdWFudGl0eSI6IjY0Ni4zMzcwMDAwMDAwMDAwMDAwMDAifSwib3JkZXJfdHlwZSI6IkJVWV9QTyIsIm1hcmdpbiI6Ijk5MDk2Mzg4OC40MDAwMDAwMDAwMDAwMDAwMDAiLCJmaWxsYWJsZSI6IjY0Ni4zMzcwMDAwMDAwMDAwMDAwMDAiLCJ0cmlnZ2VyX3ByaWNlIjpudWxsLCJvcmRlcl9oYXNoIjoiVHJrd1hPN3o2cjMzdm5RVGhKSEo5M2owbWhHaDNYT3BDM3I4OG5GU3pKVT0ifV0=
  - index: true
    key: bWFya2V0X2lk
    value: IjB4OWI5OTgwMTY3ZWNjMzY0NWZmMWE1NTE3ODg2NjUyZDk0YTA4MjVlNTRhNzdkMjA1N2NiYmUzZWJlZTAxNTk2MyI=
  - index: true
    key: c2VsbF9vcmRlcnM=
    value: W10=
  type: injective.exchange.v1beta1.EventNewDerivativeOrders
gas_used: "261983"
gas_wanted: "369801"
height: "32442284"
info: ""
logs:
- events:
  - attributes:
    - key: isLimitCancel
      value: "true"
    - key: limit_order
      value: '{"order_info":{"subaccount_id":"0xec2b21afa73d05114e3eea851358b86b5676905b000000000000000000000001","fee_recipient":"inj1as4jrta885z3zn37a2z3xk9cddt8dyzmfvwemw","price":"7735000.000000000000000000","quantity":"646.569000000000000000"},"order_type":"SELL_PO","margin":"0.000000000000000000","fillable":"646.569000000000000000","trigger_price":null,"order_hash":"hSeCA8E5kI+va3eGK2xVPbqJVro3RS9OFBBTxq1xmT8="}'
    - key: market_id
      value: '"0x9b9980167ecc3645ff1a5517886652d94a0825e54a77d2057cbbe3ebee015963"'
    - key: market_order_cancel
      value: "null"
    - key: isLimitCancel
      value: "true"
    - key: limit_order
      value: '{"order_info":{"subaccount_id":"0xec2b21afa73d05114e3eea851358b86b5676905b000000000000000000000001","fee_recipient":"inj1as4jrta885z3zn37a2z3xk9cddt8dyzmfvwemw","price":"7664000.000000000000000000","quantity":"646.569000000000000000"},"order_type":"BUY_PO","margin":"991060963.200000000000000000","fillable":"646.569000000000000000","trigger_price":null,"order_hash":"gbYahEHtXKcBwFH/k58flPuVeQdspiZn095fbkq4kGM="}'
    - key: market_id
      value: '"0x9b9980167ecc3645ff1a5517886652d94a0825e54a77d2057cbbe3ebee015963"'
    - key: market_order_cancel
      value: "null"
    type: injective.exchange.v1beta1.EventCancelDerivativeOrder
  - attributes:
    - key: buy_orders
      value: '[]'
    - key: market_id
      value: '"0x9b9980167ecc3645ff1a5517886652d94a0825e54a77d2057cbbe3ebee015963"'
    - key: sell_orders
      value: '[{"order_info":{"subaccount_id":"0xec2b21afa73d05114e3eea851358b86b5676905b000000000000000000000001","fee_recipient":"inj1as4jrta885z3zn37a2z3xk9cddt8dyzmfvwemw","price":"7737000.000000000000000000","quantity":"646.337000000000000000"},"order_type":"SELL_PO","margin":"0.000000000000000000","fillable":"646.337000000000000000","trigger_price":null,"order_hash":"n4GXaSI9NJ3bF4M1CBnXm1d2I8s6ocxLTkLK1o+9lLY="}]'
    - key: buy_orders
      value: '[{"order_info":{"subaccount_id":"0xec2b21afa73d05114e3eea851358b86b5676905b000000000000000000000001","fee_recipient":"inj1as4jrta885z3zn37a2z3xk9cddt8dyzmfvwemw","price":"7666000.000000000000000000","quantity":"646.337000000000000000"},"order_type":"BUY_PO","margin":"990963888.400000000000000000","fillable":"646.337000000000000000","trigger_price":null,"order_hash":"TrkwXO7z6r33vnQThJHJ93j0mhGh3XOpC3r88nFSzJU="}]'
    - key: market_id
      value: '"0x9b9980167ecc3645ff1a5517886652d94a0825e54a77d2057cbbe3ebee015963"'
    - key: sell_orders
      value: '[]'
    type: injective.exchange.v1beta1.EventNewDerivativeOrders
  - attributes:
    - key: action
      value: /injective.exchange.v1beta1.MsgBatchUpdateOrders
    type: message
  log: ""
  msg_index: 0
raw_log: '[{"events":[{"type":"injective.exchange.v1beta1.EventCancelDerivativeOrder","attributes":[{"key":"isLimitCancel","value":"true"},{"key":"limit_order","value":"{\"order_info\":{\"subaccount_id\":\"0xec2b21afa73d05114e3eea851358b86b5676905b000000000000000000000001\",\"fee_recipient\":\"inj1as4jrta885z3zn37a2z3xk9cddt8dyzmfvwemw\",\"price\":\"7735000.000000000000000000\",\"quantity\":\"646.569000000000000000\"},\"order_type\":\"SELL_PO\",\"margin\":\"0.000000000000000000\",\"fillable\":\"646.569000000000000000\",\"trigger_price\":null,\"order_hash\":\"hSeCA8E5kI+va3eGK2xVPbqJVro3RS9OFBBTxq1xmT8=\"}"},{"key":"market_id","value":"\"0x9b9980167ecc3645ff1a5517886652d94a0825e54a77d2057cbbe3ebee015963\""},{"key":"market_order_cancel","value":"null"},{"key":"isLimitCancel","value":"true"},{"key":"limit_order","value":"{\"order_info\":{\"subaccount_id\":\"0xec2b21afa73d05114e3eea851358b86b5676905b000000000000000000000001\",\"fee_recipient\":\"inj1as4jrta885z3zn37a2z3xk9cddt8dyzmfvwemw\",\"price\":\"7664000.000000000000000000\",\"quantity\":\"646.569000000000000000\"},\"order_type\":\"BUY_PO\",\"margin\":\"991060963.200000000000000000\",\"fillable\":\"646.569000000000000000\",\"trigger_price\":null,\"order_hash\":\"gbYahEHtXKcBwFH/k58flPuVeQdspiZn095fbkq4kGM=\"}"},{"key":"market_id","value":"\"0x9b9980167ecc3645ff1a5517886652d94a0825e54a77d2057cbbe3ebee015963\""},{"key":"market_order_cancel","value":"null"}]},{"type":"injective.exchange.v1beta1.EventNewDerivativeOrders","attributes":[{"key":"buy_orders","value":"[]"},{"key":"market_id","value":"\"0x9b9980167ecc3645ff1a5517886652d94a0825e54a77d2057cbbe3ebee015963\""},{"key":"sell_orders","value":"[{\"order_info\":{\"subaccount_id\":\"0xec2b21afa73d05114e3eea851358b86b5676905b000000000000000000000001\",\"fee_recipient\":\"inj1as4jrta885z3zn37a2z3xk9cddt8dyzmfvwemw\",\"price\":\"7737000.000000000000000000\",\"quantity\":\"646.337000000000000000\"},\"order_type\":\"SELL_PO\",\"margin\":\"0.000000000000000000\",\"fillable\":\"646.337000000000000000\",\"trigger_price\":null,\"order_hash\":\"n4GXaSI9NJ3bF4M1CBnXm1d2I8s6ocxLTkLK1o+9lLY=\"}]"},{"key":"buy_orders","value":"[{\"order_info\":{\"subaccount_id\":\"0xec2b21afa73d05114e3eea851358b86b5676905b000000000000000000000001\",\"fee_recipient\":\"inj1as4jrta885z3zn37a2z3xk9cddt8dyzmfvwemw\",\"price\":\"7666000.000000000000000000\",\"quantity\":\"646.337000000000000000\"},\"order_type\":\"BUY_PO\",\"margin\":\"990963888.400000000000000000\",\"fillable\":\"646.337000000000000000\",\"trigger_price\":null,\"order_hash\":\"TrkwXO7z6r33vnQThJHJ93j0mhGh3XOpC3r88nFSzJU=\"}]"},{"key":"market_id","value":"\"0x9b9980167ecc3645ff1a5517886652d94a0825e54a77d2057cbbe3ebee015963\""},{"key":"sell_orders","value":"[]"}]},{"type":"message","attributes":[{"key":"action","value":"/injective.exchange.v1beta1.MsgBatchUpdateOrders"}]}]}]'
timestamp: "2023-05-02T03:04:55Z"
tx:
  '@type': /cosmos.tx.v1beta1.Tx
  auth_info:
    fee:
      amount:
      - amount: "369801000000000"
        denom: inj
      gas_limit: "369801"
      granter: ""
      payer: ""
    signer_infos:
    - mode_info:
        single:
          mode: SIGN_MODE_DIRECT
      public_key:
        '@type': /injective.crypto.v1beta1.ethsecp256k1.PubKey
        key: An8DQ7/twFqvUuJxd5rCIkl04BfQocYS2T/A2pnYbFOJ
      sequence: "10873122"
  body:
    extension_options: []
    memo: ""
    messages:
    - '@type': /injective.exchange.v1beta1.MsgBatchUpdateOrders
      binary_options_market_ids_to_cancel_all: []
      binary_options_orders_to_cancel: []
      binary_options_orders_to_create: []
      derivative_market_ids_to_cancel_all: []
      derivative_orders_to_cancel:
      - market_id: 0x9b9980167ecc3645ff1a5517886652d94a0825e54a77d2057cbbe3ebee015963
        order_hash: 0x85278203c139908faf6b77862b6c553dba8956ba37452f4e141053c6ad71993f
        order_mask: 0
        subaccount_id: 0xec2b21afa73d05114e3eea851358b86b5676905b000000000000000000000001
      - market_id: 0x9b9980167ecc3645ff1a5517886652d94a0825e54a77d2057cbbe3ebee015963
        order_hash: 0x81b61a8441ed5ca701c051ff939f1f94fb9579076ca62667d3de5f6e4ab89063
        order_mask: 0
        subaccount_id: 0xec2b21afa73d05114e3eea851358b86b5676905b000000000000000000000001
      derivative_orders_to_create:
      - margin: "0.000000000000000000"
        market_id: 0x9b9980167ecc3645ff1a5517886652d94a0825e54a77d2057cbbe3ebee015963
        order_info:
          fee_recipient: inj1as4jrta885z3zn37a2z3xk9cddt8dyzmfvwemw
          price: "7737000.000000000000000000"
          quantity: "646.337000000000000000"
          subaccount_id: 0xec2b21afa73d05114e3eea851358b86b5676905b000000000000000000000001
        order_type: SELL_PO
        trigger_price: null
      - margin: "990963888.400000000000000000"
        market_id: 0x9b9980167ecc3645ff1a5517886652d94a0825e54a77d2057cbbe3ebee015963
        order_info:
          fee_recipient: inj1as4jrta885z3zn37a2z3xk9cddt8dyzmfvwemw
          price: "7666000.000000000000000000"
          quantity: "646.337000000000000000"
          subaccount_id: 0xec2b21afa73d05114e3eea851358b86b5676905b000000000000000000000001
        order_type: BUY_PO
        trigger_price: null
      sender: inj1as4jrta885z3zn37a2z3xk9cddt8dyzmfvwemw
      spot_market_ids_to_cancel_all: []
      spot_orders_to_cancel: []
      spot_orders_to_create: []
      subaccount_id: ""
    non_critical_extension_options: []
    timeout_height: "0"
  signatures:
  - ykCreNV7DhqugY9wh/snDXQxUKbl/Y+xw6l9wvaSo3pLRaOkVTvounhDfG/Yc9tHJeaWz/WvjmNzE62aI4pkHwE=
txhash: A2B2B971C690AE7977451D24D6F450AECE6BCCB271E91E32C2563342DDA5254B
ParameterTypeDescription
txTxTransaction details
tx_resposneTxResponseTransaction details


Tx

ParameterTypeDescription
bodyTxBodyBody is the processable content of the transaction
auth_infoAuthInfoAuthorization related content of the transaction (specifically signers, signer modes and fee)
signaturesBytes Array ArrayList of signatures that matches the length and order of AuthInfo's signer_infos to allow connecting signature meta information like public key and signing mode by position


TxBody

ParameterTypeDescription
messagesAny ArrayList of messages to be executed. The required signers of those messages define the number and order of elements in AuthInfo's signer_infos and Tx's signatures. Each required signer address is added to the list only the first time it occurs. By convention, the first required signer (usually from the first message) is referred to as the primary signer and pays the fee for the whole transaction
memoStringMemo is any arbitrary note/comment to be added to the transaction
timeout_heightIntegerThe block height after which this transaction will not be processed by the chain
extension_optionsAny ArrayThese are arbitrary options that can be added by chains when the default options are not sufficient. If any of these are present and can't be handled, the transaction will be rejected
non_critical_extension_optionsAny ArrayThese are arbitrary options that can be added by chains when the default options are not sufficient. If any of these are present and can't be handled, they will be ignored


AuthInfo

ParameterTypeDescription
signer_infosSignerInfo ArrayDefines the signing modes for the required signers. The number and order of elements must match the required signers from TxBody's messages. The first element is the primary signer and the one which pays the fee
feeFeeFee is the fee and gas limit for the transaction. The first signer is the primary signer and the one which pays the fee. The fee can be calculated based on the cost of evaluating the body and doing signature verification of the signers. This can be estimated via simulation
tipTipTip is the optional tip used for transactions fees paid in another denom (this field is ignored if the chain didn't enable tips, i.e. didn't add the `TipDecorator` in its posthandler)


SignerInfo

ParameterTypeDescription
public_keyAnyPublic key of the signer. It is optional for accounts that already exist in state. If unset, the verifier can use the required signer address for this position and lookup the public key
mode_infoModeInfoDescribes the signing mode of the signer and is a nested structure to support nested multisig pubkey's
sequenceIntegerThe sequence of the account, which describes the number of committed transactions signed by a given address. It is used to prevent replay attacks


ModeInfo

ParameterTypeDescription
sumSigning modeTypes that are valid to be assigned to Sum: *ModeInfo_Single_, *ModeInfo_Multi_


Fee

ParameterTypeDescription
amountCoin ArrayAmount of coins to be paid as a fee
gas_limitIntegerMaximum gas that can be used in transaction processing before an out of gas error occurs
payerStringIf unset, the first signer is responsible for paying the fees. If set, the specified account must pay the fees. The payer must be a tx signer (and thus have signed this field in AuthInfo). Setting this field does *not* change the ordering of required signers for the transaction
granterStringIf set, the fee payer (either the first signer or the value of the payer field) requests that a fee grant be used to pay fees instead of the fee payer's own balance. If an appropriate fee grant does not exist or the chain does not support fee grants, this will fail


Coin

ParameterTypeDescriptionRequired
denomStringThe token denomYes
amountStringThe amount of tokensYes


Tip

ParameterTypeDescription
amountCoin ArrayAmount of coins to be paid as a tip
tipperStringAddress of the account paying for the tip


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

StreamEventOrderFail

IP rate limit group: chain

Request Example:

import asyncio
import base64
import json

import websockets

from pyinjective.core.network import Network


async def main() -> None:
    network = Network.mainnet()
    event_filter = (
        "tm.event='Tx' AND message.sender='inj1rwv4zn3jptsqs7l8lpa3uvzhs57y8duemete9e' "
        "AND message.action='/injective.exchange.v1beta1.MsgBatchUpdateOrders' "
        "AND injective.exchange.v1beta1.EventOrderFail.flags EXISTS"
    )
    query = json.dumps(
        {
            "jsonrpc": "2.0",
            "method": "subscribe",
            "id": "0",
            "params": {"query": event_filter},
        }
    )

    async with websockets.connect(network.tm_websocket_endpoint) as ws:
        await ws.send(query)
        while True:
            res = await ws.recv()
            res = json.loads(res)
            result = res["result"]
            if result == {}:
                continue

            failed_order_hashes = json.loads(result["events"]["injective.exchange.v1beta1.EventOrderFail.hashes"][0])
            failed_order_codes = json.loads(result["events"]["injective.exchange.v1beta1.EventOrderFail.flags"][0])

            dict = {}
            for i, order_hash in enumerate(failed_order_hashes):
                hash = "0x" + base64.b64decode(order_hash).hex()
                dict[hash] = failed_order_codes[i]

            print(dict)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
)

func main() {
    network := common.LoadNetwork("mainnet", "lb")

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        "",
        nil,
    )
    if err != nil {
        panic(err)
    }

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    failEventCh := make(chan map[string]uint, 10000)
    go chainClient.StreamEventOrderFail("inj1rwv4zn3jptsqs7l8lpa3uvzhs57y8duemete9e", failEventCh)
    for {
        e := <-failEventCh
        fmt.Println(e)
    }
}

Response Parameters

Response Example:

{'0x7d6d0d2118488dcaccd57193372e536881f34132241f01c1721ed6aedffec419': 36}
map[0x9db0f6e90d63b151ab0d64f0c6d83f747969f353d8c39a68cca65d046907e92a:59 0xdf7e05e66ab7a47e7a8a1751d4b9360fd80058cd5186162cee6fe124c57ece82:36]

- Auction

Includes the message for placing bids in auctions.

MsgBid

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    # prepare tx msg
    msg = composer.MsgBid(sender=address.to_acc_bech32(), round=16250, bid_amount=1)

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "fmt"
    "os"
    "time"

    "cosmossdk.io/math"

    "github.com/InjectiveLabs/sdk-go/client"
    "github.com/InjectiveLabs/sdk-go/client/common"

    auctiontypes "github.com/InjectiveLabs/sdk-go/chain/auction/types"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
    sdktypes "github.com/cosmos/cosmos-sdk/types"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    round := uint64(9355)
    bidAmount := sdktypes.Coin{
        Denom: "inj", Amount: math.NewInt(1000000000000000000), // 1 INJ
    }

    msg := &auctiontypes.MsgBid{
        Sender:    senderAddress.String(),
        Round:     round,
        BidAmount: bidAmount,
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    err = chainClient.QueueBroadcastMsg(msg)

    if err != nil {
        fmt.Println(err)
    }

    time.Sleep(time.Second * 5)

    gasFee, err := chainClient.GetGasFee()

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("gas fee:", gasFee, "INJ")
}
ParameterTypeDescriptionRequired
senderStringThe sender Injective addressYes
bid_amountCoinBid amount in INJ tokensYes
roundIntegerThe current auction roundYes


Coin

ParameterTypeDescriptionRequired
denomStringThe token denomYes
amountStringThe amount of tokensYes

Response Parameters

Response Example:

txhash: "F18B1E6E39FAEA646F487C223DAE161482B1A12FC00C20D04A43826B8DD3E40F"
raw_log: "[]"

gas wanted: 105842
gas fee: 0.000052921 INJ
DEBU[0001] broadcastTx with nonce 3508                   fn=func1 src="client/chain/chain.go:598"
DEBU[0002] msg batch committed successfully at height 5214789  fn=func1 src="client/chain/chain.go:619" txHash=BD49BD58A263A92465A93FD0E10C5076DA8334A45A60E29A66C2E5961998AB5F
DEBU[0002] nonce incremented to 3509                     fn=func1 src="client/chain/chain.go:623"
DEBU[0002] gas wanted:  152112                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.000076056 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

- Authz

Includes all messages and queries related to the Authz module. Authz is an implementation of the Cosmos SDK module, that allows granting arbitrary privileges from one account (the granter) to another account (the grantee). Authorizations must be granted for a particular Msg service method one by one using an implementation of the Authorization interface.

MsgGrant

There are two types of authorization, Generic and Typed. Generic authorization will grant permissions to the grantee to execute exchange-related messages in all markets, typed authorization restricts the privileges to specified markets. Typed authorization is generally more safe since even if the grantee's key is compromised the attacker will only be able to send orders in specified markets - thus prevents them from launching bogus markets on-chain and executing orders on behalf of the granter.

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")
    grantee_public_address = os.getenv("INJECTIVE_GRANTEE_PUBLIC_ADDRESS")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())
    # subaccount_id = address.get_subaccount_id(index=0)
    # market_ids = ["0x0511ddc4e6586f3bfe1acb2dd905f8b8a82c97e1edaef654b12ca7e6031ca0fa"]

    # prepare tx msg

    # GENERIC AUTHZ
    msg = composer.MsgGrantGeneric(
        granter=address.to_acc_bech32(),
        grantee=grantee_public_address,
        msg_type="/injective.exchange.v1beta1.MsgCreateSpotLimitOrder",
        expire_in=31536000,  # 1 year
    )

    # TYPED AUTHZ
    # msg = composer.MsgGrantTyped(
    #     granter = "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku",
    #     grantee = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
    #     msg_type = "CreateSpotLimitOrderAuthz",
    #     expire_in=31536000, # 1 year
    #     subaccount_id=subaccount_id,
    #     market_ids=market_ids
    # )

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "fmt"
    "os"
    "time"

    "github.com/InjectiveLabs/sdk-go/client"

    "github.com/InjectiveLabs/sdk-go/client/common"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    granter := senderAddress.String()
    grantee := "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
    expireIn := time.Now().AddDate(1, 0, 0) // years months days

    // GENERIC AUTHZ
    // msgtype := "/injective.exchange.v1beta1.MsgCreateSpotLimitOrder"
    // msg := chainClient.BuildGenericAuthz(granter, grantee, msgtype, expireIn)

    // TYPED AUTHZ
    msg := chainClient.BuildExchangeAuthz(
        granter,
        grantee,
        chainclient.CreateSpotLimitOrderAuthz,
        chainClient.DefaultSubaccount(senderAddress).String(),
        []string{"0xe0dc13205fb8b23111d8555a6402681965223135d368eeeb964681f9ff12eb2a"},
        expireIn,
    )

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    err = chainClient.QueueBroadcastMsg(msg)

    if err != nil {
        fmt.Println(err)
    }

    time.Sleep(time.Second * 5)

    gasFee, err := chainClient.GetGasFee()

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("gas fee:", gasFee, "INJ")
}
Parameter Type Description Required
granter String The INJ address authorizing a grantee Yes
grantee String The INJ address being authorized by the granter Yes
msg_type String The message type being authorized by the granter Yes
expire_in Integer The expiration time for the authorization Yes

Typed Authorization Messages

  1. CreateSpotLimitOrderAuthz

  2. CreateSpotMarketOrderAuthz

  3. BatchCreateSpotLimitOrdersAuthz

  4. CancelSpotOrderAuthz

  5. BatchCancelSpotOrdersAuthz

  6. CreateDerivativeLimitOrderAuthz

  7. CreateDerivativeMarketOrderAuthz

  8. BatchCreateDerivativeLimitOrdersAuthz

  9. CancelDerivativeOrderAuthz

  10. BatchCancelDerivativeOrdersAuthz

  11. BatchUpdateOrdersAuthz

Response Parameters

Response Example:

txhash: "ACD8E18DF357E28821B2931C4138971F805967485AE48FED2A808112F630D7E9"
raw_log: "[]"

gas wanted: 96103
gas fee: 0.0000480515 INJ
DEBU[0001] broadcastTx with nonce 3509                   fn=func1 src="client/chain/chain.go:598"
DEBU[0003] msg batch committed successfully at height 5214837  fn=func1 src="client/chain/chain.go:619" txHash=1F1FD519002B85C68CAE5593FDDB11FD749F918D5BBCA5F10E8AF6CFF0C5090A
DEBU[0003] nonce incremented to 3510                     fn=func1 src="client/chain/chain.go:623"
DEBU[0003] gas wanted:  117873                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.0000589365 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgExec

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os
import uuid
from decimal import Decimal

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import Address, PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_GRANTEE_PRIVATE_KEY")
    granter_inj_address = os.getenv("INJECTIVE_GRANTER_PUBLIC_ADDRESS")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    # prepare tx msg
    market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
    grantee = address.to_acc_bech32()

    granter_address = Address.from_acc_bech32(granter_inj_address)
    granter_subaccount_id = granter_address.get_subaccount_id(index=0)
    msg0 = composer.msg_create_spot_limit_order(
        sender=granter_inj_address,
        market_id=market_id,
        subaccount_id=granter_subaccount_id,
        fee_recipient=grantee,
        price=Decimal("7.523"),
        quantity=Decimal("0.01"),
        order_type="BUY",
        cid=str(uuid.uuid4()),
    )

    msg = composer.MsgExec(grantee=grantee, msgs=[msg0])

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    sim_res_msgs = sim_res["result"]["msgResponses"]
    data = sim_res_msgs[0]
    unpacked_msg_res = composer.unpack_msg_exec_response(
        underlying_msg_type=msg0.__class__.__name__, msg_exec_response=data
    )
    print("simulation msg response")
    print(unpacked_msg_res)

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "fmt"
    "os"
    "time"

    exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"

    "github.com/InjectiveLabs/sdk-go/client"
    "github.com/InjectiveLabs/sdk-go/client/common"
    "github.com/shopspring/decimal"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
    codectypes "github.com/cosmos/cosmos-sdk/codec/types"
    sdk "github.com/cosmos/cosmos-sdk/types"
    authztypes "github.com/cosmos/cosmos-sdk/x/authz"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    granterAddress, _, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketsAssistant, err := chainclient.NewMarketsAssistantInitializedFromChain(ctx, exchangeClient)
    if err != nil {
        panic(err)
    }

    txFactory := chainclient.NewTxFactory(clientCtx)
    txFactory = txFactory.WithGasPrices(client.DefaultGasPriceWithDenom)
    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionTxFactory(&txFactory),
    )

    if err != nil {
        panic(err)
    }

    // note that we use grantee keyring to send the msg on behalf of granter here
    // sender, subaccount are from granter
    granter := granterAddress.String()
    grantee := "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
    defaultSubaccountID := chainClient.DefaultSubaccount(granterAddress)

    marketId := "0x0511ddc4e6586f3bfe1acb2dd905f8b8a82c97e1edaef654b12ca7e6031ca0fa"

    amount := decimal.NewFromFloat(2)
    price := decimal.NewFromFloat(22.55)
    order := chainClient.CreateSpotOrder(
        defaultSubaccountID,
        &chainclient.SpotOrderData{
            OrderType:    exchangetypes.OrderType_BUY,
            Quantity:     amount,
            Price:        price,
            FeeRecipient: senderAddress.String(),
            MarketId:     marketId,
        },
        marketsAssistant,
    )

    // manually pack msg into Any type
    msg0 := exchangetypes.MsgCreateSpotLimitOrder{
        Sender: granter,
        Order:  *order,
    }
    msg0Bytes, _ := msg0.Marshal()
    msg0Any := &codectypes.Any{}
    msg0Any.TypeUrl = sdk.MsgTypeURL(&msg0)
    msg0Any.Value = msg0Bytes
    msg := &authztypes.MsgExec{
        Grantee: grantee,
        Msgs:    []*codectypes.Any{msg0Any},
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    err = chainClient.QueueBroadcastMsg(msg)

    if err != nil {
        fmt.Println(err)
    }

    time.Sleep(time.Second * 5)

    gasFee, err := chainClient.GetGasFee()

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("gas fee:", gasFee, "INJ")
}
Parameter Type Description Required
grantee String The INJ address of the grantee Yes
msgs Array The messages to be executed on behalf of the granter Yes

Response Parameters

Response Example:

---Simulation Response---
[results: "\nB0x7bd1785363eb01c0c9e1642d71645f75d198e70419b303c9e48e39af3e428bcf"
]
---Transaction Response---
txhash: "D8F84A91C189430E2219DBA72BFA64FD567240EAEFFE4296202A1D31835E2EE1"
raw_log: "[]"

gas wanted: 107030
gas fee: 0.000053515 INJ
DEBU[0002] broadcastTx with nonce 1313                   fn=func1 src="client/chain/chain.go:598"
DEBU[0004] msg batch committed successfully at height 5214956  fn=func1 src="client/chain/chain.go:619" txHash=6968428F68F3F1380D9A059C964F0C39C943EBBCCD758E8541270DC3B4037A02
DEBU[0004] nonce incremented to 1314                     fn=func1 src="client/chain/chain.go:623"
DEBU[0004] gas wanted:  133972                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.000066986 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgRevoke

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")
    grantee_public_address = os.getenv("INJECTIVE_GRANTEE_PUBLIC_ADDRESS")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    # prepare tx msg
    msg = composer.MsgRevoke(
        granter=address.to_acc_bech32(),
        grantee=grantee_public_address,
        msg_type="/injective.exchange.v1beta1.MsgCreateSpotLimitOrder",
    )

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "fmt"
    "os"
    "time"

    "github.com/InjectiveLabs/sdk-go/client"
    "github.com/InjectiveLabs/sdk-go/client/common"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
    authztypes "github.com/cosmos/cosmos-sdk/x/authz"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    grantee := "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
    msgType := "/injective.exchange.v1beta1.MsgCreateSpotLimitOrder"

    msg := &authztypes.MsgRevoke{
        Granter:    senderAddress.String(),
        Grantee:    grantee,
        MsgTypeUrl: msgType,
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    err = chainClient.QueueBroadcastMsg(msg)

    if err != nil {
        fmt.Println(err)
    }

    time.Sleep(time.Second * 5)

    gasFee, err := chainClient.GetGasFee()

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("gas fee:", gasFee, "INJ")
}
Parameter Type Description Required
granter String The INJ address unauthorizing a grantee Yes
grantee String The INJ address being unauthorized by the granter Yes
msg_type String The message type being unauthorized by the granter Yes

Response Example:

txhash: "7E89656E1ED2E2A934B0A1D4DD1D4B228C15A50FDAEA0B97A67E9E27E1B22627"
raw_log: "[]"

gas wanted: 86490
gas fee: 0.000043245 INJ
DEBU[0001] broadcastTx with nonce 3511                   fn=func1 src="client/chain/chain.go:598"
DEBU[0003] msg batch committed successfully at height 5214972  fn=func1 src="client/chain/chain.go:619" txHash=CB15AC2B2722E5CFAA61234B3668043BA1333DAC728B875A77946EEE11FE48C2
DEBU[0003] nonce incremented to 3512                     fn=func1 src="client/chain/chain.go:623"
DEBU[0003] gas wanted:  103153                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.0000515765 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

Grants

Get the details of an authorization between a granter and a grantee.

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    dotenv.load_dotenv()
    granter = os.getenv("INJECTIVE_GRANTER_PUBLIC_ADDRESS")
    grantee = os.getenv("INJECTIVE_GRANTEE_PUBLIC_ADDRESS")

    network = Network.testnet()
    client = AsyncClient(network)
    msg_type_url = "/injective.exchange.v1beta1.MsgCreateDerivativeLimitOrder"
    authorizations = await client.fetch_grants(granter=granter, grantee=grantee, msg_type_url=msg_type_url)
    print(authorizations)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
    authztypes "github.com/cosmos/cosmos-sdk/x/authz"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    granter := "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku"
    grantee := "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
    msg_type_url := "/injective.exchange.v1beta1.MsgCreateSpotLimitOrder"

    req := authztypes.QueryGrantsRequest{
        Granter:    granter,
        Grantee:    grantee,
        MsgTypeUrl: msg_type_url,
    }

    ctx := context.Background()

    res, err := chainClient.GetAuthzGrants(ctx, req)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
Parameter Type Description Required
granter String The account owner Yes
grantee String The authorized account Yes
msg_type_url Integer The authorized message type No

Response Parameters

Response Example:

{
   "grants":[
      {
         "authorization":"OrderedDict("[
            "(""@type",
            "/cosmos.authz.v1beta1.GenericAuthorization"")",
            "(""msg",
            "/injective.exchange.v1beta1.MsgCreateSpotLimitOrder"")"
         ]")",
         "expiration":"2024-12-07T02:26:01Z"
      }
   ]
}
Parameter Type Description
grants Grants Grants object

Grants

Parameter Type Description
authorization Authorization Authorization object
expiration Expiration Expiration object

Authorization

Parameter Type Description
type_url String The authorization type
value String The authorized message

Expiration

Parameter Type Description
seconds String The expiration time for an authorization

- Bank

Bank module.

MsgSend

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    # prepare tx msg
    msg = composer.MsgSend(
        from_address=address.to_acc_bech32(),
        to_address="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
        amount=0.000000000000000001,
        denom="INJ",
    )

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "fmt"
    "os"
    "time"

    "cosmossdk.io/math"

    "github.com/InjectiveLabs/sdk-go/client"

    "github.com/InjectiveLabs/sdk-go/client/common"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
    sdktypes "github.com/cosmos/cosmos-sdk/types"
    banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    // initialize grpc client
    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )
    if err != nil {
        panic(err)
    }
    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    // prepare tx msg
    msg := &banktypes.MsgSend{
        FromAddress: senderAddress.String(),
        ToAddress:   "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
        Amount: []sdktypes.Coin{{
            Denom: "inj", Amount: math.NewInt(1000000000000000000)}, // 1 INJ
        },
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    err = chainClient.QueueBroadcastMsg(msg)

    if err != nil {
        fmt.Println(err)
    }

    time.Sleep(time.Second * 5)

    gasFee, err := chainClient.GetGasFee()

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("gas fee:", gasFee, "INJ")
}
Parameter Type Description Required
from_address String The Injective Chain address of the sender Yes
to_address String The Injective Chain address of the receiver Yes
amount Integer The amount of tokens to send Yes
denom String The token denom Yes

Response Parameters

Response Example:

txhash: "52F3AF222FB064E7505FB14D79D703120EBDF8C945B7920F02FE2BB6666F1D50"
raw_log: "[]"

gas wanted: 97455
gas fee: 0.0000487275 INJ
DEBU[0001] broadcastTx with nonce 3490                   fn=func1 src="client/chain/chain.go:598"
DEBU[0004] msg batch committed successfully at height 5212593  fn=func1 src="client/chain/chain.go:619" txHash=AD30AE73838AA342072DCC61897AA75548D613D032A3EC9BDD0A5A064C456002
DEBU[0004] nonce incremented to 3491                     fn=func1 src="client/chain/chain.go:623"
DEBU[0004] gas wanted:  119871                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.0000599355 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgMultiSend

IP rate limit group: chain

Request Parameters

Request Example:

package main

import (
    "fmt"
    "os"
    "time"

    "cosmossdk.io/math"

    "github.com/InjectiveLabs/sdk-go/client"
    "github.com/InjectiveLabs/sdk-go/client/common"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
    sdktypes "github.com/cosmos/cosmos-sdk/types"
    banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    // initialize grpc client

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    // prepare tx msg

    msg := &banktypes.MsgMultiSend{
        Inputs: []banktypes.Input{
            {
                Address: senderAddress.String(),
                Coins: []sdktypes.Coin{{
                    Denom: "inj", Amount: math.NewInt(1000000000000000000)}, // 1 INJ
                },
            },
            {
                Address: senderAddress.String(),
                Coins: []sdktypes.Coin{{
                    Denom: "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", Amount: math.NewInt(1000000)}, // 1 USDT
                },
            },
        },
        Outputs: []banktypes.Output{
            {
                Address: "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
                Coins: []sdktypes.Coin{{
                    Denom: "inj", Amount: math.NewInt(1000000000000000000)}, // 1 INJ
                },
            },
            {
                Address: "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
                Coins: []sdktypes.Coin{{
                    Denom: "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", Amount: math.NewInt(1000000)}, // 1 USDT
                },
            },
        },
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    err = chainClient.QueueBroadcastMsg(msg)

    if err != nil {
        fmt.Println(err)
    }

    time.Sleep(time.Second * 5)

    gasFee, err := chainClient.GetGasFee()

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("gas fee:", gasFee, "INJ")
}
Parameter Type Description Required
Inputs Input Inputs Yes
Outputs Output Outputs Yes

Input

Parameter Type Description Required
address String The Injective Chain address of the sender Yes
amount Integer The amount of tokens to send Yes
denom String The token denom Yes

Output

Parameter Type Description Required
address String The Injective Chain address of the receiver Yes
amount Integer The amount of tokens to send Yes
denom String The token denom Yes

Response Example:


DEBU[0001] broadcastTx with nonce 30                     fn=func1 src="client/chain/chain.go:630"
DEBU[0003] msg batch committed successfully at height 1620903  fn=func1 src="client/chain/chain.go:651" txHash=643F2C0F7FC679609AFE87FC4F3B0F2E81769F75628375BD6F3D27D4C286B240
DEBU[0003] nonce incremented to 31                       fn=func1 src="client/chain/chain.go:655"
DEBU[0003] gas wanted:  152844                           fn=func1 src="client/chain/chain.go:656"
gas fee: 0.000076422 INJ

QueryAllBalances

Get the bank balance for all denoms.

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    address = "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r"
    all_bank_balances = await client.fetch_bank_balances(address=address)
    print(all_bank_balances)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    address := "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku"
    ctx := context.Background()

    res, err := chainClient.GetBankBalances(ctx, address)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
Parameter Type Description Required
address String The Injective Chain address Yes

Response Parameters

Response Example:

{
   "balances":[
      {
         "denom":"factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/atom",
         "amount":"10000000000"
      },
      {
         "denom":"factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/usdc",
         "amount":"10000000000"
      },
      {
         "denom":"factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/weth",
         "amount":"5000000000"
      },
      {
         "denom":"factory/inj1aetmaq5pswvfg6nhvgd4lt94qmg23ka3ljgxlm/SHURIKEN",
         "amount":"115700000"
      },
      {
         "denom":"factory/inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r/test",
         "amount":"1000000"
      },
      {
         "denom":"inj",
         "amount":"760662316753211286487"
      },
      {
         "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
         "amount":"9996297948"
      }
   ],
   "pagination":{
      "total":"7",
      "nextKey":""
   }
}
{
 "balances": [
  {
   "denom": "ibc/B448C0CA358B958301D328CCDC5D5AD642FC30A6D3AE106FF721DB315F3DDE5C",
   "amount": "829149863837"
  },
  {
   "denom": "inj",
   "amount": "51142210518226357537"
  },
  {
   "denom": "peggy0x36B3D7ACe7201E28040eFf30e815290D7b37ffaD",
   "amount": "4000000000000000000"
  },
  {
   "denom": "share26",
   "amount": "1000000000000000000"
  }
 ],
 "pagination": {
  "total": 4
 }
}
Parameter Type Description
balances Balances Balances object
pagination Pagination Pagination object

Balances

Parameter Type Description
denom String Token denom
amount String Token amount

Pagination

Parameter Type Description
total Integer Total denoms

QueryBalance

Get the bank balance for a specific denom.

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    address = "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r"
    denom = "inj"
    bank_balance = await client.fetch_bank_balance(address=address, denom=denom)
    print(bank_balance)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    address := "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku"
    denom := "inj"
    ctx := context.Background()

    res, err := chainClient.GetBankBalance(ctx, address, denom)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
Parameter Type Description Required
address String The Injective Chain address Yes
denom String The token denom Yes

Response Parameters

Response Example:

{
   "balance":{
      "denom":"inj",
      "amount":"760662316753211286487"
   }
}
{
 "balance": {
  "denom": "inj",
  "amount": "51142210518226357537"
 }
}
Parameter Type Description
balance Balance Balance object

Balance

Parameter Type Description
denom String Token denom
amount String Token amount

SpendableBalances

Get the bank spendable balances for a specific address.

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    address = "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r"
    spendable_balances = await client.fetch_spendable_balances(address=address)
    print(spendable_balances)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"
    "github.com/cosmos/cosmos-sdk/types/query"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    address := "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku"
    pagination := query.PageRequest{Limit: 10}
    ctx := context.Background()

    res, err := chainClient.GetBankSpendableBalances(ctx, address, &pagination)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
Parameter Type Description Required
address String Address to query spendable balances for Yes
pagination Paging Pagination of results No

Response Parameters

Response Example:

{
   "balances":[
      {
         "denom":"factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/atom",
         "amount":"10000000000"
      },
      {
         "denom":"factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/usdc",
         "amount":"10000000000"
      },
      {
         "denom":"factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/weth",
         "amount":"5000000000"
      },
      {
         "denom":"factory/inj1aetmaq5pswvfg6nhvgd4lt94qmg23ka3ljgxlm/SHURIKEN",
         "amount":"109950000"
      },
      {
         "denom":"factory/inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r/AAA",
         "amount":"3000000000"
      },
      {
         "denom":"factory/inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r/ANK",
         "amount":"999989999000010"
      },
      {
         "denom":"factory/inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r/APE",
         "amount":"999999899000038"
      },
      {
         "denom":"factory/inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r/aaaa",
         "amount":"900000928000028"
      },
      {
         "denom":"factory/inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r/test",
         "amount":"1000000"
      },
      {
         "denom":"inj",
         "amount":"682717353413490977815"
      },
      {
         "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
         "amount":"9996297948"
      }
   ],
   "pagination":{
      "total":"11",
      "nextKey":""
   }
}
{
 "balances": [
  {
   "denom": "factory/inj17d34nrgnq5sj24qd6rk4jrnak628wfqxjx9uhz/lpinj1zd8zg8xeerlsrsfzxhpe3xgncrp0txetqye9cl",
   "amount": "2000000000000000000"
  },
  {
   "denom": "factory/inj17gkuet8f6pssxd8nycm3qr9d9y699rupv6397z/mitotest1",
   "amount": "249999999999999999998"
  },
  {
   "denom": "factory/inj17gkuet8f6pssxd8nycm3qr9d9y699rupv6397z/projx",
   "amount": "27877970000000000000"
  },
  {
   "denom": "factory/inj17gkuet8f6pssxd8nycm3qr9d9y699rupv6397z/stinj",
   "amount": "103927830000000000000"
  },
  {
   "denom": "factory/inj17q7ds0yh7hhtusff7gz8a5kx2uwxruttlxur96/lpinj1vd0mf8a39xwr9hav2g7e8lmur07utjrjv025kd",
   "amount": "29670048440098478542"
  },
  {
   "denom": "factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/aave",
   "amount": "110000000000"
  },
  {
   "denom": "factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/atom",
   "amount": "20672215991"
  },
  {
   "denom": "factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/crv",
   "amount": "110000000000"
  },
  {
   "denom": "factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/cvx",
   "amount": "110000000000"
  },
  {
   "denom": "factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/shib",
   "amount": "110000000000"
  }
 ],
 "pagination": {
  "next_key": "ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvdGlh"
 }
}

Parameter Type Description
balances Coin Array Balance object
pagination PageResponse Pagination of results

Coin

Parameter Type Description
denom String Token denom
amount String Token amount

SpendableBalancesByDenom

Get the bank spendable balances for a specific address and denom.

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    address = "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r"
    denom = "inj"
    spendable_balances = await client.fetch_spendable_balances_by_denom(address=address, denom=denom)
    print(spendable_balances)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    address := "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku"
    denom := "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"
    ctx := context.Background()

    res, err := chainClient.GetBankSpendableBalancesByDenom(ctx, address, denom)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
Parameter Type Description Required
address String Address to query spendable balances for Yes
denom String The token denom Yes

Response Parameters

Response Example:

{
   "balance":{
      "denom":"inj",
      "amount":"682717353413490977815"
   }
}
{
 "balance": {
  "denom": "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
  "amount": "172767664766"
 }
}

Parameter Type Description
balance Coin Balance object

Coin

Parameter Type Description
denom String Token denom
amount String Token amount

TotalSupply

Get the total supply for all tokens

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    total_supply = await client.fetch_total_supply(
        pagination=PaginationOption(limit=10),
    )
    print(total_supply)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"
    "github.com/cosmos/cosmos-sdk/types/query"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    pagination := query.PageRequest{Limit: 10}
    ctx := context.Background()

    res, err := chainClient.GetBankTotalSupply(ctx, &pagination)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
Parameter Type Description Required
pagination Paging Pagination of results No

Response Parameters

Response Example:

{
   "supply":[
      {
         "denom":"factory/inj104y00apw6uu26gthl7cafztdy67hhmwksekdem/position",
         "amount":"64120252107"
      },
      {
         "denom":"factory/inj106rseec0xmv5k06aaf8jsnr57ajw76rxa3gpwm/position",
         "amount":"192927104"
      },
      {
         "denom":"factory/inj107aqkjc3t5r3l9j4n9lgrma5tm3jav8qgppz6m/position",
         "amount":"1921200000000000000000"
      },
      {
         "denom":"factory/inj107skcseta3egagj822d3qdgusx7a7ua7sepmcf/position",
         "amount":"52973849072"
      },
      {
         "denom":"factory/inj107srzqksjtdevlpw888vuyrnqmlpjuv64ytm85/position",
         "amount":"777131899999"
      },
      {
         "denom":"factory/inj108t3mlej0dph8er6ca2lq5cs9pdgzva5mqsn5p/position",
         "amount":"5556700000000000000"
      },
      {
         "denom":"factory/inj109rcepnmg7ewjcc4my3448jm3h0yjdwcl6kmnl/position",
         "amount":"642300000000"
      },
      {
         "denom":"factory/inj10ajd3f46mp755wmhgke8w4vcegfjndwfzymf82/position",
         "amount":"725247250499"
      },
      {
         "denom":"factory/inj10fz2cj00ee80y76pdzg06dxfamat8nfpr9vl5s/position",
         "amount":"4067730000000000000000"
      },
      {
         "denom":"factory/inj10hmmvlqq6rrlf2c2v982d6xqsns4m3sy086r27/position",
         "amount":"761148481800"
      }
   ],
   "pagination":{
      "nextKey":"ZmFjdG9yeS9pbmoxMG52MjB4ZTR4MzI1c3E1NTdkZGNtc3lsYTd6YWo2cG5zc3JmdzkvcG9zaXRpb24=",
      "total":"0"
   }
}
{
 "supply": [
  {
   "denom": "factory/inj104y00apw6uu26gthl7cafztdy67hhmwksekdem/position",
   "amount": "64120252107"
  },
  {
   "denom": "factory/inj106rseec0xmv5k06aaf8jsnr57ajw76rxa3gpwm/position",
   "amount": "192927104"
  },
  {
   "denom": "factory/inj107aqkjc3t5r3l9j4n9lgrma5tm3jav8qgppz6m/position",
   "amount": "1921200000000000000000"
  },
  {
   "denom": "factory/inj107skcseta3egagj822d3qdgusx7a7ua7sepmcf/position",
   "amount": "52973849072"
  },
  {
   "denom": "factory/inj107srzqksjtdevlpw888vuyrnqmlpjuv64ytm85/position",
   "amount": "777131899999"
  },
  {
   "denom": "factory/inj108t3mlej0dph8er6ca2lq5cs9pdgzva5mqsn5p/position",
   "amount": "5556700000000000000"
  },
  {
   "denom": "factory/inj109rcepnmg7ewjcc4my3448jm3h0yjdwcl6kmnl/position",
   "amount": "642300000000"
  },
  {
   "denom": "factory/inj10ajd3f46mp755wmhgke8w4vcegfjndwfzymf82/position",
   "amount": "725247250499"
  },
  {
   "denom": "factory/inj10fz2cj00ee80y76pdzg06dxfamat8nfpr9vl5s/position",
   "amount": "4067730000000000000000"
  },
  {
   "denom": "factory/inj10hmmvlqq6rrlf2c2v982d6xqsns4m3sy086r27/position",
   "amount": "761148481800"
  }
 ],
 "pagination": {
  "next_key": "ZmFjdG9yeS9pbmoxMG52MjB4ZTR4MzI1c3E1NTdkZGNtc3lsYTd6YWo2cG5zc3JmdzkvcG9zaXRpb24="
 }
}

Parameter Type Description
supply Coin Array Array of supply for each token
pagination PageResponse Pagination of results

Coin

Parameter Type Description
denom String Token denom
amount String Token amount

SupplyOf

Queries the supply of a single token

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    supply_of = await client.fetch_supply_of(denom="inj")
    print(supply_of)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    denom := "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"
    ctx := context.Background()

    res, err := chainClient.GetBankSupplyOf(ctx, denom)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
Parameter Type Description Required
denom String Token denom Yes

Response Parameters

Response Example:

{'amount': {'denom': 'inj', 'amount': '926435158902805147647209906101604'}}
{
 "amount": {
  "denom": "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
  "amount": "999999965050607001998"
 }
}

Parameter Type Description
amount Coin Supply for the token

Coin

Parameter Type Description
denom String Token denom
amount String Token amount

DenomMetadata

Queries the metadata of a single token

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    denom = "factory/inj107aqkjc3t5r3l9j4n9lgrma5tm3jav8qgppz6m/position"
    metadata = await client.fetch_denom_metadata(denom=denom)
    print(metadata)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    denom := "factory/inj107aqkjc3t5r3l9j4n9lgrma5tm3jav8qgppz6m/position"
    ctx := context.Background()

    res, err := chainClient.GetDenomMetadata(ctx, denom)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
Parameter Type Description Required
denom String Token denom Yes

Response Parameters

Response Example:

{
   "metadata":{
      "denomUnits":[
         {
            "denom":"factory/inj107aqkjc3t5r3l9j4n9lgrma5tm3jav8qgppz6m/position",
            "exponent":0,
            "aliases":[

            ]
         }
      ],
      "base":"factory/inj107aqkjc3t5r3l9j4n9lgrma5tm3jav8qgppz6m/position",
      "description":"",
      "display":"",
      "name":"",
      "symbol":"",
      "uri":"",
      "uriHash":""
   }
}
{
 "metadata": {
  "denom_units": [
   {
    "denom": "factory/inj107aqkjc3t5r3l9j4n9lgrma5tm3jav8qgppz6m/position"
   }
  ],
  "base": "factory/inj107aqkjc3t5r3l9j4n9lgrma5tm3jav8qgppz6m/position"
 }
}

Parameter Type Description
metadata Metadata Token information

Metadata

Parameter Type Description
description String Token description
denom_units DenomUnit Array DenomUnits
base String Token denom
display String Token display name
name String Token name
symbol String Token symbol
uri String In general a URI to a document with additional information
uri_hash String SHA256 hash of a document pointed by URI

DenomsMetadata

Queries the metadata of all tokens

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    denoms = await client.fetch_denoms_metadata(
        pagination=PaginationOption(limit=10),
    )
    print(denoms)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"
    "github.com/cosmos/cosmos-sdk/types/query"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    pagination := query.PageRequest{Limit: 10}
    ctx := context.Background()

    res, err := chainClient.GetDenomsMetadata(ctx, &pagination)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
Parameter Type Description Required
pagination Paging Pagination of results No

Response Parameters

Response Example:

{
   "metadatas":[
      {
         "denomUnits":[
            {
               "denom":"factory/inj104y00apw6uu26gthl7cafztdy67hhmwksekdem/position",
               "exponent":0,
               "aliases":[

               ]
            }
         ],
         "base":"factory/inj104y00apw6uu26gthl7cafztdy67hhmwksekdem/position",
         "description":"",
         "display":"",
         "name":"",
         "symbol":"",
         "uri":"",
         "uriHash":""
      },
      {
         "denomUnits":[
            {
               "denom":"factory/inj106rseec0xmv5k06aaf8jsnr57ajw76rxa3gpwm/position",
               "exponent":0,
               "aliases":[

               ]
            }
         ],
         "base":"factory/inj106rseec0xmv5k06aaf8jsnr57ajw76rxa3gpwm/position",
         "description":"",
         "display":"",
         "name":"",
         "symbol":"",
         "uri":"",
         "uriHash":""
      },
      {
         "denomUnits":[
            {
               "denom":"factory/inj107aqkjc3t5r3l9j4n9lgrma5tm3jav8qgppz6m/position",
               "exponent":0,
               "aliases":[

               ]
            }
         ],
         "base":"factory/inj107aqkjc3t5r3l9j4n9lgrma5tm3jav8qgppz6m/position",
         "description":"",
         "display":"",
         "name":"",
         "symbol":"",
         "uri":"",
         "uriHash":""
      },
      {
         "denomUnits":[
            {
               "denom":"factory/inj107skcseta3egagj822d3qdgusx7a7ua7sepmcf/position",
               "exponent":0,
               "aliases":[

               ]
            }
         ],
         "base":"factory/inj107skcseta3egagj822d3qdgusx7a7ua7sepmcf/position",
         "description":"",
         "display":"",
         "name":"",
         "symbol":"",
         "uri":"",
         "uriHash":""
      },
      {
         "denomUnits":[
            {
               "denom":"factory/inj107srzqksjtdevlpw888vuyrnqmlpjuv64ytm85/position",
               "exponent":0,
               "aliases":[

               ]
            }
         ],
         "base":"factory/inj107srzqksjtdevlpw888vuyrnqmlpjuv64ytm85/position",
         "description":"",
         "display":"",
         "name":"",
         "symbol":"",
         "uri":"",
         "uriHash":""
      },
      {
         "denomUnits":[
            {
               "denom":"factory/inj108t3mlej0dph8er6ca2lq5cs9pdgzva5mqsn5p/position",
               "exponent":0,
               "aliases":[

               ]
            }
         ],
         "base":"factory/inj108t3mlej0dph8er6ca2lq5cs9pdgzva5mqsn5p/position",
         "description":"",
         "display":"",
         "name":"",
         "symbol":"",
         "uri":"",
         "uriHash":""
      },
      {
         "denomUnits":[
            {
               "denom":"factory/inj109rcepnmg7ewjcc4my3448jm3h0yjdwcl6kmnl/position",
               "exponent":0,
               "aliases":[

               ]
            }
         ],
         "base":"factory/inj109rcepnmg7ewjcc4my3448jm3h0yjdwcl6kmnl/position",
         "description":"",
         "display":"",
         "name":"",
         "symbol":"",
         "uri":"",
         "uriHash":""
      },
      {
         "denomUnits":[
            {
               "denom":"factory/inj10ajd3f46mp755wmhgke8w4vcegfjndwfzymf82/position",
               "exponent":0,
               "aliases":[

               ]
            }
         ],
         "base":"factory/inj10ajd3f46mp755wmhgke8w4vcegfjndwfzymf82/position",
         "description":"",
         "display":"",
         "name":"",
         "symbol":"",
         "uri":"",
         "uriHash":""
      },
      {
         "denomUnits":[
            {
               "denom":"factory/inj10fz2cj00ee80y76pdzg06dxfamat8nfpr9vl5s/position",
               "exponent":0,
               "aliases":[

               ]
            }
         ],
         "base":"factory/inj10fz2cj00ee80y76pdzg06dxfamat8nfpr9vl5s/position",
         "description":"",
         "display":"",
         "name":"",
         "symbol":"",
         "uri":"",
         "uriHash":""
      },
      {
         "denomUnits":[
            {
               "denom":"factory/inj10hmmvlqq6rrlf2c2v982d6xqsns4m3sy086r27/position",
               "exponent":0,
               "aliases":[

               ]
            }
         ],
         "base":"factory/inj10hmmvlqq6rrlf2c2v982d6xqsns4m3sy086r27/position",
         "description":"",
         "display":"",
         "name":"",
         "symbol":"",
         "uri":"",
         "uriHash":""
      }
   ],
   "pagination":{
      "nextKey":"ZmFjdG9yeS9pbmoxMGptcDZzZ2g0Y2M2enQzZThndzA1d2F2dmVqZ3I1cHc2bThqNzUvYWs=",
      "total":"0"
   }
}
{
 "metadatas": [
  {
   "denom_units": [
    {
     "denom": "factory/inj104y00apw6uu26gthl7cafztdy67hhmwksekdem/position"
    }
   ],
   "base": "factory/inj104y00apw6uu26gthl7cafztdy67hhmwksekdem/position"
  },
  {
   "denom_units": [
    {
     "denom": "factory/inj106rseec0xmv5k06aaf8jsnr57ajw76rxa3gpwm/position"
    }
   ],
   "base": "factory/inj106rseec0xmv5k06aaf8jsnr57ajw76rxa3gpwm/position"
  },
  {
   "denom_units": [
    {
     "denom": "factory/inj107aqkjc3t5r3l9j4n9lgrma5tm3jav8qgppz6m/position"
    }
   ],
   "base": "factory/inj107aqkjc3t5r3l9j4n9lgrma5tm3jav8qgppz6m/position"
  },
  {
   "denom_units": [
    {
     "denom": "factory/inj107skcseta3egagj822d3qdgusx7a7ua7sepmcf/position"
    }
   ],
   "base": "factory/inj107skcseta3egagj822d3qdgusx7a7ua7sepmcf/position"
  },
  {
   "denom_units": [
    {
     "denom": "factory/inj107srzqksjtdevlpw888vuyrnqmlpjuv64ytm85/position"
    }
   ],
   "base": "factory/inj107srzqksjtdevlpw888vuyrnqmlpjuv64ytm85/position"
  },
  {
   "denom_units": [
    {
     "denom": "factory/inj108t3mlej0dph8er6ca2lq5cs9pdgzva5mqsn5p/position"
    }
   ],
   "base": "factory/inj108t3mlej0dph8er6ca2lq5cs9pdgzva5mqsn5p/position"
  },
  {
   "denom_units": [
    {
     "denom": "factory/inj109rcepnmg7ewjcc4my3448jm3h0yjdwcl6kmnl/position"
    }
   ],
   "base": "factory/inj109rcepnmg7ewjcc4my3448jm3h0yjdwcl6kmnl/position"
  },
  {
   "denom_units": [
    {
     "denom": "factory/inj10ajd3f46mp755wmhgke8w4vcegfjndwfzymf82/position"
    }
   ],
   "base": "factory/inj10ajd3f46mp755wmhgke8w4vcegfjndwfzymf82/position"
  },
  {
   "denom_units": [
    {
     "denom": "factory/inj10fz2cj00ee80y76pdzg06dxfamat8nfpr9vl5s/position"
    }
   ],
   "base": "factory/inj10fz2cj00ee80y76pdzg06dxfamat8nfpr9vl5s/position"
  },
  {
   "denom_units": [
    {
     "denom": "factory/inj10hmmvlqq6rrlf2c2v982d6xqsns4m3sy086r27/position"
    }
   ],
   "base": "factory/inj10hmmvlqq6rrlf2c2v982d6xqsns4m3sy086r27/position"
  }
 ],
 "pagination": {
  "next_key": "ZmFjdG9yeS9pbmoxMGptcDZzZ2g0Y2M2enQzZThndzA1d2F2dmVqZ3I1cHc2bThqNzUvYWs="
 }
}
Parameter Type Description
metadatas Metadata Array Tokens information
pagination Pagination Pagination object

Metadata

Parameter Type Description
description String Token description
denom_units DenomUnit Array DenomUnits
base String Token denom
display String Token display name
name String Token name
symbol String Token symbol
uri String In general a URI to a document with additional information
uri_hash String SHA256 hash of a document pointed by URI

DenomsOwners

Queries for all account addresses that own a particular token

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    denom = "inj"
    owners = await client.fetch_denom_owners(
        denom=denom,
        pagination=PaginationOption(limit=10),
    )
    print(owners)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
    "github.com/cosmos/cosmos-sdk/types/query"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    denom := "factory/inj107aqkjc3t5r3l9j4n9lgrma5tm3jav8qgppz6m/position"
    pagination := query.PageRequest{Limit: 10}
    ctx := context.Background()

    res, err := chainClient.GetDenomOwners(ctx, denom, &pagination)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
Parameter Type Description Required
denom String Token denom Yes
pagination Paging Pagination of results No

Response Parameters

Response Example:

{
   "denomOwners":[
      {
         "address":"inj1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqe2hm49",
         "balance":{
            "denom":"inj",
            "amount":"420000000000000010003"
         }
      },
      {
         "address":"inj1qqqqqqqpa95pcsnxa3927hlym6t8quhwlgkmqt",
         "balance":{
            "denom":"inj",
            "amount":"10000000000000000"
         }
      },
      {
         "address":"inj1qqqqqqzw4rg692t320252whr7gjp4k86lun8hp",
         "balance":{
            "denom":"inj",
            "amount":"143805431033925108"
         }
      },
      {
         "address":"inj1qqqqqqr0g47qlr6kqveans58w2raj25j095pad",
         "balance":{
            "denom":"inj",
            "amount":"199999568185205399700"
         }
      },
      {
         "address":"inj1qqqqqq4ze7h25mf9w8h8h02h807yj2fxzl27m8",
         "balance":{
            "denom":"inj",
            "amount":"10000"
         }
      },
      {
         "address":"inj1qqqqqqhn9sygdmn966q9n77mwmhk56vkkae2d3",
         "balance":{
            "denom":"inj",
            "amount":"260838118080821668174"
         }
      },
      {
         "address":"inj1qqqqqr5pwtzk2n8tswusllscjagw3w9k3dyceg",
         "balance":{
            "denom":"inj",
            "amount":"826945326095056784"
         }
      },
      {
         "address":"inj1qqqqqrk35e4y5r3aklpeelkkr9hkxq4k4y55c9",
         "balance":{
            "denom":"inj",
            "amount":"49800000000000000"
         }
      },
      {
         "address":"inj1qqqqqyyfzemqpsjjtrdzn5hzept7c95f8zyhmn",
         "balance":{
            "denom":"inj",
            "amount":"599500010155805818137328"
         }
      },
      {
         "address":"inj1qqqqqy2thegwe8473jk5u6th93uc488n4ltucm",
         "balance":{
            "denom":"inj",
            "amount":"40027858757349727870"
         }
      }
   ],
   "pagination":{
      "nextKey":"FAAAADLLRNDsOnihjI3alQcdNB0a",
      "total":"0"
   }
}
{
 "denom_owners": [
  {
   "address": "inj15e2qkdv5kf0w79f34t0c0w3j7arhxe4gy6juwf",
   "balance": {
    "denom": "factory/inj107aqkjc3t5r3l9j4n9lgrma5tm3jav8qgppz6m/position",
    "amount": "1921200000000000000000"
   }
  }
 ],
 "pagination": {}
}
Parameter Type Description
denom_owners DenomOwner Array Token owners
pagination Pagination Pagination object

DenomOwner

Parameter Type Description
address String Account address
balance Coin Token amount

Coin

Parameter Type Description
denom String Token denom
amount String Token amount

SendEnabled

This query only returns denominations that have specific SendEnabled settings. Any denomination that does not have a specific setting will use the default params.default_send_enabled, and will not be returned by this query.

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    denom = "inj"
    enabled = await client.fetch_send_enabled(
        denoms=[denom],
        pagination=PaginationOption(limit=10),
    )
    print(enabled)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
    "github.com/cosmos/cosmos-sdk/types/query"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    denoms := []string{"factory/inj107aqkjc3t5r3l9j4n9lgrma5tm3jav8qgppz6m/position"}
    pagination := query.PageRequest{Limit: 10}
    ctx := context.Background()

    res, err := chainClient.GetBankSendEnabled(ctx, denoms, &pagination)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
Parameter Type Description Required
denom String Array Token denoms No
pagination Paging Pagination of results No

Response Parameters

Response Example:

Parameter Type Description
send_enabled SendEnabled Array SendEnabled information
pagination Pagination Pagination object

SendEnabled

Parameter Type Description
denom String Token denom
enabled Bool True or False

- Chain Stream

Chain Stream is a gRPC service that allows clients to receive low-latency updates from the Injective Chain. This API is exposed directly from a dedicated server running on a chain node and provides the fastest way to receive events data (like trades, orders, balances, etc.). Under the hood, a stream message is computed by the chain node immediately after the event is emitted and is sent to the client via a gRPC stream once the block is committed.

Stream Request

Its possible to specify multiple filters to customize the stream. A filter can be specified with a list of values, generally MarketIds, SubaccountIds and Accounts address. A filter can also be omitted, in this case the stream will return all the events for the specified type. In addition each filter supports a * wildcard to match all possible values.

import asyncio
from typing import Any, Dict

from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.composer import Composer
from pyinjective.core.network import Network


async def chain_stream_event_processor(event: Dict[str, Any]):
    print(event)


def stream_error_processor(exception: RpcError):
    print(f"There was an error listening to chain stream updates ({exception})")


def stream_closed_processor():
    print("The chain stream updates stream has been closed")


async def main() -> None:
    network = Network.testnet()

    client = AsyncClient(network)
    composer = Composer(network=network.string())

    subaccount_id = "0xbdaedec95d563fb05240d6e01821008454c24c36000000000000000000000000"

    inj_usdt_market = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
    inj_usdt_perp_market = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"

    bank_balances_filter = composer.chain_stream_bank_balances_filter(
        accounts=["inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"]
    )
    subaccount_deposits_filter = composer.chain_stream_subaccount_deposits_filter(subaccount_ids=[subaccount_id])
    spot_trades_filter = composer.chain_stream_trades_filter(subaccount_ids=["*"], market_ids=[inj_usdt_market])
    derivative_trades_filter = composer.chain_stream_trades_filter(
        subaccount_ids=["*"], market_ids=[inj_usdt_perp_market]
    )
    spot_orders_filter = composer.chain_stream_orders_filter(
        subaccount_ids=[subaccount_id], market_ids=[inj_usdt_market]
    )
    derivative_orders_filter = composer.chain_stream_orders_filter(
        subaccount_ids=[subaccount_id], market_ids=[inj_usdt_perp_market]
    )
    spot_orderbooks_filter = composer.chain_stream_orderbooks_filter(market_ids=[inj_usdt_market])
    derivative_orderbooks_filter = composer.chain_stream_orderbooks_filter(market_ids=[inj_usdt_perp_market])
    positions_filter = composer.chain_stream_positions_filter(
        subaccount_ids=[subaccount_id], market_ids=[inj_usdt_perp_market]
    )
    oracle_price_filter = composer.chain_stream_oracle_price_filter(symbols=["INJ", "USDT"])

    task = asyncio.get_event_loop().create_task(
        client.listen_chain_stream_updates(
            callback=chain_stream_event_processor,
            on_end_callback=stream_closed_processor,
            on_status_callback=stream_error_processor,
            bank_balances_filter=bank_balances_filter,
            subaccount_deposits_filter=subaccount_deposits_filter,
            spot_trades_filter=spot_trades_filter,
            derivative_trades_filter=derivative_trades_filter,
            spot_orders_filter=spot_orders_filter,
            derivative_orders_filter=derivative_orders_filter,
            spot_orderbooks_filter=spot_orderbooks_filter,
            derivative_orderbooks_filter=derivative_orderbooks_filter,
            positions_filter=positions_filter,
            oracle_price_filter=oracle_price_filter,
        )
    )

    await asyncio.sleep(delay=60)
    task.cancel()


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    chainStreamModule "github.com/InjectiveLabs/sdk-go/chain/stream/types"
    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        "",
        nil,
    )
    if err != nil {
        panic(err)
    }
    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    subaccountId := "0xbdaedec95d563fb05240d6e01821008454c24c36000000000000000000000000"

    injUsdtMarket := "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
    injUsdtPerpMarket := "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"

    req := chainStreamModule.StreamRequest{
        BankBalancesFilter: &chainStreamModule.BankBalancesFilter{
            Accounts: []string{"*"},
        },
        SpotOrdersFilter: &chainStreamModule.OrdersFilter{
            MarketIds:     []string{injUsdtMarket},
            SubaccountIds: []string{subaccountId},
        },
        DerivativeOrdersFilter: &chainStreamModule.OrdersFilter{
            MarketIds:     []string{injUsdtPerpMarket},
            SubaccountIds: []string{subaccountId},
        },
        SpotTradesFilter: &chainStreamModule.TradesFilter{
            MarketIds:     []string{injUsdtMarket},
            SubaccountIds: []string{"*"},
        },
        SubaccountDepositsFilter: &chainStreamModule.SubaccountDepositsFilter{
            SubaccountIds: []string{subaccountId},
        },
        DerivativeOrderbooksFilter: &chainStreamModule.OrderbookFilter{
            MarketIds: []string{injUsdtPerpMarket},
        },
        SpotOrderbooksFilter: &chainStreamModule.OrderbookFilter{
            MarketIds: []string{injUsdtMarket},
        },
        PositionsFilter: &chainStreamModule.PositionsFilter{
            SubaccountIds: []string{subaccountId},
            MarketIds:     []string{injUsdtPerpMarket},
        },
        DerivativeTradesFilter: &chainStreamModule.TradesFilter{
            SubaccountIds: []string{"*"},
            MarketIds:     []string{injUsdtPerpMarket},
        },
        OraclePriceFilter: &chainStreamModule.OraclePriceFilter{
            Symbol: []string{"INJ", "USDT"},
        },
    }

    ctx := context.Background()

    stream, err := chainClient.ChainStream(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))
        }
    }
}

Request parameters

Parameter Type Description Required
BankBalancesFilter BankBalancesFilter Filter for bank balances events No
SpotOrdersFilter OrdersFilter Filter for spot orders events No
DerivativeOrdersFilter OrdersFilter Filter for derivative orders events No
SpotTradesFilter TradesFilter Filter for spot trades events No
SubaccountDepositsFilter SubaccountDepositsFilter Filter for subaccount deposits events No
DerivativeOrderbooksFilter OrderbookFilter Filter for derivative order books events No
SpotOrderbooksFilter OrderbookFilter Filter for spot order books events No
PositionsFilter PositionsFilter Filter for positions events No
DerivativeTradesFilter TradesFilter Filter for derivative trades events No
OraclePriceFilter OraclePriceFilter Filter for oracle price events No

BankBalancesFilter

Structure for filtering bank balances.

Parameter Type Description Required
Accounts String Array List of account addresses. No

SubaccountDepositsFilter

Structure for filtering subaccount deposits.

Parameter Type Description Required
SubaccountIds String Array List of subaccount IDs. No

TradesFilter

Structure for filtering trades.

Parameter Type Description Required
SubaccountIds String Array List of subaccount IDs. No
MarketIds String Array List of market IDs. No

OrdersFilter

Structure for filtering orders.

Parameter Type Description Required
SubaccountIds String Array List of subaccount IDs. No
MarketIds String Array List of market IDs. No

OrderbookFilter

Structure for filtering orderbook.

Parameter Type Description Required
MarketIds String Array List of market IDs. No

PositionsFilter

Structure for filtering positions.

Parameter Type Description Required
SubaccountIds String Array List of subaccount IDs. No
MarketIds String Array List of market IDs. No

OraclePriceFilter

Structure for filtering oracle prices.

Parameter Type Description Required
Symbol String Array List of symbols. No

StreamResponse

The stream response is a stream of events that are sent to the client. Each message contains a list of events that are filtered by the request parameters and it's identified by the block height.

Response parameters

Response structure for the data stream.

Parameter Type Description Required
BlockHeight Integer The current block height.
BlockTime Integer The current block timestamp
BankBalances BankBalance Array List of bank balances.
SubaccountDeposits SubaccountDeposits Array List of subaccount deposits.
SpotTrades SpotTrade Array List of spot trades.
DerivativeTrades DerivativeTrade Array List of derivative trades.
SpotOrders SpotOrder Array List of spot orders.
DerivativeOrders DerivativeOrder Array List of derivative orders.
SpotOrderbookUpdates OrderbookUpdate Array List of spot orderbook updates.
DerivativeOrderbookUpdates OrderbookUpdate Array List of derivative orderbook updates.
Positions Position Array List of positions.
OraclePrices OraclePrice Array List of oracle prices.

BankBalance

Structure for bank balances.

Parameter Type Description Required
Account String The account name.
Balances Coins The list of available balances.

SubaccountDeposits

Structure for subaccount deposits.

Parameter Type Description Required
SubaccountId String The subaccount ID.
Deposits Deposit Array List of deposits.

SpotTrade

Structure for spot trades.

Parameter Type Description Required
MarketId String The market ID.
IsBuy bool True if it is a buy, False if it is a sell.
ExecutionType String The execution type.
Quantity Dec The quantity of the trade.
Price Dec The price of the trade.
SubaccountId String The subaccount ID that executed the trade.
Fee Dec The fee of the trade.
OrderHash String The hash of the order.
FeeRecipientAddress String The fee recipient address.
Cid String Identifier for the order specified by the user
TradeId String Unique identifier to differentiate between trades

DerivativeTrade

Structure for derivative trades.

Parameter Type Description Required
MarketId String The market ID.
IsBuy bool True if it is a buy, False if it is a sell.
ExecutionType String The execution type.
SubaccountId String The subaccount ID that executed the trade.
PositionDelta PositionDelta The position delta.
Payout Dec The payout of the trade.
Fee Dec The fee of the trade.
OrderHash String The hash of the order.
FeeRecipientAddress String The fee recipient address.
Cid String Identifier for the order specified by the user
TradeId String Unique identifier to differentiate between trades

SpotOrder

Structure for spot orders.

Parameter Type Description Required
MarketId String The market ID.
Order SpotLimitOrder The spot order.

DerivativeOrder

Structure for derivative orders.

Parameter Type Description Required
MarketId String The market ID.
Order DerivativeLimitOrder The derivative order.
IsMarket bool True if it is a market order, False if it is a limit order.

OrderbookUpdate

Structure for orderbook updates.

Parameter Type Description Required
Seq Integer The sequence number.
Orderbook Orderbook The updated orderbook.

Position

Structure for positions.

Parameter Type Description Required
MarketId String The market ID.
SubaccountId String The subaccount ID.
IsLong bool True if it is a long position, False if it is short.
Quantity Dec The quantity of the position.
EntryPrice Dec The entry price of the position.
Margin Dec The margin of the position.
CumulativeFundingEntry Dec The cumulative funding entry of the position.

OraclePrice

Structure for oracle prices.

Parameter Type Description Required
Symbol String The symbol of the price. Yes
Price Dec The oracle price. Yes
Type String The price type.

SubaccountDeposit

Structure for subaccount deposits.

Parameter Type Description Required
Denom String The denomination of the deposit.
Deposit Deposit The deposit details.

Deposit

Structure for deposit details.

Parameter Type Description Required
AvailableBalance Dec The available balance in the deposit.
TotalBalance Dec The total balance in the deposit.

SpotLimitOrder

Structure for spot limit orders.

Parameter Type Description Required
OrderInfo OrderInfo Information about the order.
OrderType OrderType The order type.
Fillable Dec The remaining fillable quantity.
TriggerPrice Dec (optional) The trigger price for stop/take orders.
OrderHash []byte (optional) The hash of the order.

DerivativeLimitOrder

Structure for derivative limit orders.

Parameter Type Description Required
OrderInfo OrderInfo Information about the order.
OrderType OrderType The order type.
Margin Dec The margin used by the order.
Fillable Dec The remaining fillable quantity.
TriggerPrice Dec (optional) The trigger price for stop/take orders.
OrderHash []byte (optional) The hash of the order.

OrderInfo

Structure for order information.

Parameter Type Description Required
SubaccountId String The subaccount ID of the order creator.
FeeRecipient String The fee recipient address for the order.
Price Dec The price of the order.
Quantity Dec The quantity of the order.
Cid String Identifier for the order specified by the user

OrderType

Any of the possible order types

Orderbook

Structure for the orderbook.

Parameter Type Description Required
MarketId String The market ID.
BuyLevels Level Array List of buy levels.
SellLevels Level Array List of sell levels.

Level

Structure for the orderbook levels.

Parameter Type Description Required
P Dec The price of the level.
Q Dec The quantity of the level.

- Chain Exchange

Includes all the messages and queries related to exchange accounts, orders and trades

SubaccountDeposits

Retrieves a subaccount's deposits

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective import PrivateKey
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    subaccount_id = address.get_subaccount_id(index=0)

    deposits = await client.fetch_subaccount_deposits(subaccount_id=subaccount_id)
    print(deposits)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    subaccountId := chainClient.Subaccount(senderAddress, 0)
    ctx := context.Background()

    res, err := chainClient.FetchSubaccountDeposits(ctx, subaccountId.Hex())
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
subaccount_idStringThe subaccount IDNo
subaccountSubaccountThe subaccount infoNo


Subaccount

ParameterTypeDescriptionRequired
traderStringThe subaccount trader addressNo
subaccount_nonceIntegerThe subaccount nonce numberNo

Response Parameters

Response Example:

{
   "deposits":{
      "factory/inj17gkuet8f6pssxd8nycm3qr9d9y699rupv6397z/demo":{
         "availableBalance":"0",
         "totalBalance":"0"
      },
      "factory/inj17gkuet8f6pssxd8nycm3qr9d9y699rupv6397z/stinj":{
         "availableBalance":"0",
         "totalBalance":"0"
      },
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/Talis-3":{
         "availableBalance":"0",
         "totalBalance":"0"
      },
      "inj":{
         "availableBalance":"0",
         "totalBalance":"22458000000000000000000000000000000000"
      },
      "peggy0x44C21afAaF20c270EBbF5914Cfc3b5022173FEB7":{
         "availableBalance":"0",
         "totalBalance":"0"
      },
      "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5":{
         "availableBalance":"342932031115126491",
         "totalBalance":"324904824830342932031115126449"
      },
      "factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/atom":{
         "availableBalance":"0",
         "totalBalance":"0"
      }
   }
}
ParameterTypeDescription
depositsMap String to DepositMap with the token denom as key, and a deposit information as value


Deposit

ParameterTypeDescription
available_balanceDecimalDeposit available balance
total_balanceDecimalDeposit total balance

SubaccountDeposit

Retrieves a subaccount's deposit

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective import PrivateKey
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    subaccount_id = address.get_subaccount_id(index=0)

    deposit = await client.fetch_subaccount_deposit(subaccount_id=subaccount_id, denom="inj")
    print(deposit)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    subaccountId := chainClient.Subaccount(senderAddress, 0)
    denom := "inj"
    ctx := context.Background()

    res, err := chainClient.FetchSubaccountDeposit(ctx, subaccountId.Hex(), denom)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
subaccount_idStringThe subaccount IDYes
denomStringThe token denomYes

Response Parameters

Response Example:

{
   "deposits":{
      "availableBalance":"0",
      "totalBalance":"22458000000000000000000000000000000000"
   }
}
ParameterTypeDescription
depositsDepositThe subaccount's deposits for the specified token


Deposit

ParameterTypeDescription
available_balanceDecimalDeposit available balance
total_balanceDecimalDeposit total balance

ExchangeBalances

Retrieves the balances for all accounts registered in the exchange module

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    # initialize grpc client
    client = AsyncClient(network)

    balances = await client.fetch_exchange_balances()
    print(balances)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    res, err := chainClient.FetchExchangeBalances(ctx)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}

No parameters

Response Parameters

Response Example:

{
   "balances":{
      "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
      "deposits":{
         "availableBalance":"0",
         "totalBalance":"0"
      },
      "subaccountId":"0x0000000001e9681c4266ec4aaf5fe4de967072ee000000000000000000000000"
   }
}
ParameterTypeDescription
depositsDepositThe subaccount's deposits for the specified token


Balance

ParameterTypeDescription
subaccount_idStringThe subaccount ID
denomStringThe token denom
depositsDepositThe token deposit details


Deposit

ParameterTypeDescription
available_balanceDecimalDeposit available balance
total_balanceDecimalDeposit total balance

AggregateVolume

Retrieves the aggregate volumes for the specified account or subaccount

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective import PrivateKey
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()

    subaccount_id = address.get_subaccount_id(index=0)

    volume = await client.fetch_aggregate_volume(account=address.to_acc_bech32())
    print(volume)

    volume = await client.fetch_aggregate_volume(account=subaccount_id)
    print(volume)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    subaccountId := chainClient.Subaccount(senderAddress, 0)

    res, err := chainClient.FetchAggregateVolume(ctx, senderAddress.String())
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

    res, err = chainClient.FetchAggregateVolume(ctx, subaccountId.Hex())
    if err != nil {
        fmt.Println(err)
    }

    str, _ = json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
accountStringAccount address or subaccount idYes

Response Parameters

Response Example:

{
   "aggregateVolumes":[
      {
         "marketId":"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
         "volume":{
            "makerVolume":"1689236673987000000000000000000",
            "takerVolume":"501627449819312000000000000000"
         }
      },
      {
         "marketId":"0x141e3c92ed55107067ceb60ee412b86256cedef67b1227d6367b4cdf30c55a74",
         "volume":{
            "makerVolume":"67687000000000000000000000000",
            "takerVolume":"5387728000000000000000000000"
         }
      },
      {
         "marketId":"0x14f82598b92674598af196770a45e1b808a4ef3aa86eb9ca09aff1aeab33ac46",
         "volume":{
            "makerVolume":"10648800000000000000000000",
            "takerVolume":"21548000000000000000000000"
         }
      }
   ]
}
ParameterTypeDescription
aggregated_volumesMarketVolume ArrayVolume information. If an address is specified, then the aggregate_volumes will aggregate the volumes across all subaccounts for the address


MarketVolume

ParameterTypeDescription
market_idStringThe market ID
volumeVolumeRecordThe volume for a particular market


VolumeRecord

ParameterTypeDescription
maker_volumeDecimalThe maker volume
taker_volumeDecimalThe taker volume

AggregateVolumes

Retrieves the aggregate volumes for specified accounts

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective import PrivateKey
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()

    volume = await client.fetch_aggregate_volumes(
        accounts=[address.to_acc_bech32()],
        market_ids=["0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"],
    )
    print(volume)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    accounts := []string{senderAddress.String()}
    marketIds := []string{"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"}

    res, err := chainClient.FetchAggregateVolumes(ctx, accounts, marketIds)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
accountsString ArrayList of account addresses and/or subaccount IDs to query forNo
market_idsString ArrayList of market IDs to query forNo

Response Parameters

Response Example:

{
   "aggregateAccountVolumes":[
      {
         "account":"inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
         "marketVolumes":[
            {
               "marketId":"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
               "volume":{
                  "makerVolume":"1689236673987000000000000000000",
                  "takerVolume":"501627449819312000000000000000"
               }
            }
         ]
      }
   ],
   "aggregateMarketVolumes":[
      {
         "marketId":"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
         "volume":{
            "makerVolume":"3070484904498656000000000000000000",
            "takerVolume":"3073070717217233353000000000000000"
         }
      }
   ]
}
ParameterTypeDescription
aggregated_account_volumesAggregateAccountVolumeRecord ArrayThe aggregate volume records for the accounts specified
aggregated_market_volumesMarketVolume ArrayThe aggregate volumes for the markets specified


AggregateAccountVolumeRecord

ParameterTypeDescription
accountStringAccount the volume belongs to
market_volumesMarketVolume ArrayThe aggregate volumes for each market


MarketVolume

ParameterTypeDescription
market_idStringThe market ID
volumeVolumeRecordThe volume for a particular market


VolumeRecord

ParameterTypeDescription
maker_volumeDecimalThe maker volume
taker_volumeDecimalThe taker volume

AggregateMarketVolume

Retrieves the aggregate volume for the specified market

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"

    volume = await client.fetch_aggregate_market_volume(market_id=market_id)
    print(volume)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    marketId := "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"

    res, err := chainClient.FetchAggregateMarketVolume(ctx, marketId)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
market_idStringThe market IDYes

Response Parameters

Response Example:

{
   "volume":{
      "makerVolume":"3070574313724656000000000000000000",
      "takerVolume":"3073160126443233353000000000000000"
   }
}
ParameterTypeDescription
volumeVolumeRecordThe aggregated market volume information


VolumeRecord

ParameterTypeDescription
maker_volumeDecimalThe maker volume
taker_volumeDecimalThe taker volume

AggregateMarketVolumes

Retrieves the aggregate market volumes for specified markets

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    volume = await client.fetch_aggregate_market_volumes(
        market_ids=["0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"],
    )
    print(volume)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    marketIds := []string{"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"}

    res, err := chainClient.FetchAggregateMarketVolumes(ctx, marketIds)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
market_idsString ArrayList of market IDs to query volume forNo

Response Parameters

Response Example:

{
   "volumes":[
      {
         "marketId":"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
         "volume":{
            "makerVolume":"3070590556798408000000000000000000",
            "takerVolume":"3073176369516985353000000000000000"
         }
      }
   ]
}
ParameterTypeDescription
volumesMarketVolume ArrayThe markets volume information


MarketVolume

ParameterTypeDescription
market_idStringThe market ID
volumeVolumeRecordThe volume for a particular market


VolumeRecord

ParameterTypeDescription
maker_volumeDecimalThe maker volume
taker_volumeDecimalThe taker volume

DenomDecimal

Retrieves the number of decimals used for a denom

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    deposits = await client.fetch_denom_decimal(denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5")
    print(deposits)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    denom := "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"

    res, err := chainClient.FetchDenomDecimal(ctx, denom)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
denomStringThe asset denomYes

Response Parameters

Response Example:

{
   "decimal":"6"
}
ParameterTypeDescription
decimalIntegerNumber of decimals used for the asset

DenomDecimals

Retrieves the denom decimals for multiple denoms

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    deposits = await client.fetch_denom_decimals(denoms=["inj", "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"])
    print(deposits)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    denoms := []string{"inj", "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"}

    res, err := chainClient.FetchDenomDecimals(ctx, denoms)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
denomsString ArrayList of asset denomsNo

Response Parameters

Response Example:

{
   "denomDecimals":[
      {
         "denom":"inj",
         "decimals":"0"
      },
      {
         "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
         "decimals":"6"
      }
   ]
}
ParameterTypeDescription
denom_decimalsDenomDecimals ArrayList of decimals for the queried denoms


DenomDecimals

ParameterTypeDescription
denomStringThe asset denom
decimalsIntegerNumber of decimals

SubaccountOrders

Retrieves subaccount's orders

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective import PrivateKey
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    subaccount_id = address.get_subaccount_id(index=0)

    orders = await client.fetch_chain_subaccount_orders(
        subaccount_id=subaccount_id,
        market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
    )
    print(orders)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    marketId := "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
    subaccountId := chainClient.Subaccount(senderAddress, 0)

    res, err := chainClient.FetchChainSubaccountOrders(ctx, subaccountId.Hex(), marketId)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
subaccount_idStringThe subaccount IDYes
market_idStringMarket ID to request forYes

Response Parameters

Response Example:

{
   "buyOrders":[

   ],
   "sellOrders":[

   ]
}
ParameterTypeDescription
buy_ordersSubaccountOrderData ArrayBuy orders info
sell_ordersSubaccountOrderData ArraySell orders info


SubaccountOrderData

ParameterTypeDescription
orderSubaccountOrderOrder info
order_hashBytesOrder hash


SubaccountOrder

ParameterTypeDescription
priceDecimalOrder price
quantityDecimalThe amount of the order quantity remaining fillable
is_reduce_onlyBooleanTrue if the order is a reduce only order
cidStringThe client order ID provided by the creator

SubaccountTradeNonce

Retrieves a subaccount's trade nonce

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective import PrivateKey
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    subaccount_id = address.get_subaccount_id(index=0)

    nonce = await client.fetch_subaccount_trade_nonce(
        subaccount_id=subaccount_id,
    )
    print(nonce)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    subaccountId := chainClient.Subaccount(senderAddress, 0)

    res, err := chainClient.FetchSubaccountTradeNonce(ctx, subaccountId.Hex())
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
subaccount_idStringThe subaccount ID to query forYes

Response Parameters

Response Example:

{
   "nonce":30226
}
ParameterTypeDescription
nonceIntegerThe nonce number

SubaccountOrderMetadata

Retrieves subaccount's order metadata

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective import PrivateKey
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    subaccount_id = address.get_subaccount_id(index=0)

    metadata = await client.fetch_subaccount_order_metadata(
        subaccount_id=subaccount_id,
    )
    print(metadata)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    subaccountId := chainClient.Subaccount(senderAddress, 0)

    res, err := chainClient.FetchSubaccountOrderMetadata(ctx, subaccountId.Hex())
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
subaccount_idStringThe subaccount ID to query forYes

Response Parameters

Response Example:

{
   "metadata":[
      {
         "metadata":{
            "aggregateReduceOnlyQuantity":"0",
            "aggregateVanillaQuantity":"0",
            "vanillaLimitOrderCount":0,
            "reduceOnlyLimitOrderCount":0,
            "vanillaConditionalOrderCount":0,
            "reduceOnlyConditionalOrderCount":0
         },
         "marketId":"0x141e3c92ed55107067ceb60ee412b86256cedef67b1227d6367b4cdf30c55a74",
         "isBuy":true
      },
      {
         "metadata":{
            "aggregateReduceOnlyQuantity":"0",
            "aggregateVanillaQuantity":"0",
            "vanillaLimitOrderCount":0,
            "reduceOnlyLimitOrderCount":0,
            "vanillaConditionalOrderCount":0,
            "reduceOnlyConditionalOrderCount":0
         },
         "marketId":"0x141e3c92ed55107067ceb60ee412b86256cedef67b1227d6367b4cdf30c55a74",
         "isBuy":false
      }
   ]
}
ParameterTypeDescription
metadataSubaccountOrderbookMetadataWithMarket ArrayList of subaccount's orderbook metadata information


SubaccountOrderbookMetadataWithMarket

ParameterTypeDescription
metadataSubaccountOrderbookMetadataOrderbook metadata
market_idStringThe orderbook's market ID
is_buyBooleanTrue for buy. False for sell


SubaccountOrderbookMetadata

ParameterTypeDescription
vanilla_limit_order_countIntegerNumber of vanilla limit orders
reduce_only_limit_order_countIntegerNumber of reduce only limit orders
aggregate_reduce_only_quantityDecimalAggregate fillable quantity of the subaccount's reduce-only limit orders in the given direction
aggregate_vanilla_quantityDecimalAggregate fillable quantity of the subaccount's vanilla limit orders in the given direction
vanilla_conditional_order_countIntegerNumber of vanilla conditional orders
reduce_only_conditional_order_countIntegerNumber of reduce only conditional orders

TradeRewardPoints

Retrieves the account and total trade rewards points

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective import PrivateKey
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    points = await client.fetch_trade_reward_points(
        accounts=[address.to_acc_bech32()],
    )
    print(points)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    accounts := []string{senderAddress.String()}

    res, err := chainClient.FetchTradeRewardPoints(ctx, accounts)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
accountsString ListList of account addresses to query forNo
pending_pool_timestampIntegerRewards pool timestampNo

Response Parameters

Response Example:

{
   "accountTradeRewardPoints":[
      "0"
   ]
}
ParameterTypeDescription
account_trade_reward_pointsDecimalNumber of points

PendingTradeRewardPoints

Retrieves the pending account and total trade rewards points

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective import PrivateKey
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    points = await client.fetch_pending_trade_reward_points(
        accounts=[address.to_acc_bech32()],
    )
    print(points)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    accounts := []string{senderAddress.String()}

    res, err := chainClient.FetchPendingTradeRewardPoints(ctx, accounts)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
accountsString ListList of account addresses to query forNo
pending_pool_timestampIntegerRewards pool timestampNo

Response Parameters

Response Example:

{
   "accountTradeRewardPoints":[
      "0"
   ]
}
ParameterTypeDescription
account_trade_reward_pointsDecimalNumber of points

TradeRewardCampaign

Retrieves the trade reward campaign

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective import PrivateKey
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    campaign = await client.fetch_trade_reward_campaign()
    print(campaign)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    res, err := chainClient.FetchTradeRewardCampaign(ctx)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}

No parameters

Response Parameters

Response Example:

{
   "totalTradeRewardPoints":"22845565536709999999999999999855",
   "tradingRewardPoolCampaignSchedule":[

   ],
   "pendingTradingRewardPoolCampaignSchedule":[

   ],
   "pendingTotalTradeRewardPoints":[

   ]
}
ParameterTypeDescription
trading_reward_campaign_infoTradingRewardCampaignInfoCampaign information
trading_reward_pool_campaign_scheduleCampaignRewardPool ArrayCampaign schedules
total_trade_reward_pointsDecimalTrade reward points
pending_trading_reward_pool_campaign_scheduleCampaignRewardPool ArrayPending campaigns schedules
pending_total_trade_reward_pointsDecimal ArrayPending campaigns points


TradingRewardCampaignInfo

ParameterTypeDescription
campaign_duration_secondsIntegerCampaign duration in seconds
quote_denomsString ArrayThe trading fee quote denoms which will be counted for the rewards
trading_reward_boost_infoTradingRewardCampaignBoostInfoBoost information
disqualified_market_idsString ArrayList of disqualified marked IDs


CampaignRewardPool

ParameterTypeDescription
start_timestampIntegerCampaign start timestamp in seconds
max_campaign_rewardsDecimal ArrayMaximum reward amounts to be disbursed at the end of the campaign


TradingRewardCampaignBoostInfo

ParameterTypeDescription
boosted_spot_market_idsString ArrayList of spot market IDs
spot_market_multipliersPointsMultiplier ArrayList of boost information for each spot market
boosted_derivative_market_idsString ArrayList of derivative market IDs
derivative_market_multipliersPointsMultiplier ArrayList of bood information for each derivative market


PointsMultiplier

ParameterTypeDescription
maker_points_multiplierDecimalMultiplier for maker trades
taker_points_multiplierDecimalMultiplier for taker trades

FeeDiscountAccountInfo

Retrieves the account's fee discount info

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective import PrivateKey
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    fee_discount = await client.fetch_fee_discount_account_info(
        account=address.to_acc_bech32(),
    )
    print(fee_discount)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    res, err := chainClient.FetchFeeDiscountAccountInfo(ctx, senderAddress.String())
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
accountStringAccount address to query forYes

Response Parameters

Response Example:

{
   "accountInfo":{
      "makerDiscountRate":"0",
      "takerDiscountRate":"0",
      "stakedAmount":"1008990017144791",
      "volume":"63626657729000000000000000000"
   },
   "tierLevel":"0"
}
ParameterTypeDescription
tier_levelIntegerFee discount tier
account_infoFeeDiscountTierInfoFee discount tier info
account_ttlFeeDiscountTierTTLFee discount tier TTL


FeeDiscountTierInfo

ParameterTypeDescription
maker_discount_rateDecimalMaker trades' discount rate
taker_discount_rateDecimalTaker trades' discount rate
staked_amountDecimalStaked smount to reach this discount tier
volumeDecimalVolume to reach this discount tier


FeeDiscountTierTTL

ParameterTypeDescription
tierIntegerTier number
ttl_timestampDecimalTier TTL

FeeDiscountSchedule

Retrieves the fee discount schedule

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    schedule = await client.fetch_fee_discount_schedule()
    print(schedule)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    res, err := chainClient.FetchFeeDiscountSchedule(ctx)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}

No parameters

Response Parameters

Response Example:

{
   "feeDiscountSchedule":{
      "bucketCount":"28",
      "bucketDuration":"86400",
      "quoteDenoms":[
         "peggy0xf9152067989BDc8783fF586624124C05A529A5D1",
         "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"
      ],
      "tierInfos":[
         {
            "makerDiscountRate":"75000000000000000",
            "takerDiscountRate":"75000000000000000",
            "stakedAmount":"25000000000000000000",
            "volume":"50000000000000000000000000"
         },
         {
            "makerDiscountRate":"125000000000000000",
            "takerDiscountRate":"125000000000000000",
            "stakedAmount":"100000000000000000000",
            "volume":"100000000000000000000000000"
         },
         {
            "makerDiscountRate":"200000000000000000",
            "takerDiscountRate":"200000000000000000",
            "stakedAmount":"250000000000000000000",
            "volume":"200000000000000000000000000"
         },
         {
            "makerDiscountRate":"300000000000000000",
            "takerDiscountRate":"300000000000000000",
            "stakedAmount":"750000000000000000000",
            "volume":"500000000000000000000000000"
         },
         {
            "makerDiscountRate":"400000000000000000",
            "takerDiscountRate":"400000000000000000",
            "stakedAmount":"2000000000000000000000",
            "volume":"1500000000000000000000000000"
         },
         {
            "makerDiscountRate":"500000000000000000",
            "takerDiscountRate":"500000000000000000",
            "stakedAmount":"5000000000000000000000",
            "volume":"3500000000000000000000000000"
         },
         {
            "makerDiscountRate":"600000000000000000",
            "takerDiscountRate":"600000000000000000",
            "stakedAmount":"12500000000000000000000",
            "volume":"8000000000000000000000000000"
         },
         {
            "makerDiscountRate":"700000000000000000",
            "takerDiscountRate":"700000000000000000",
            "stakedAmount":"30000000000000000000000",
            "volume":"20000000000000000000000000000"
         },
         {
            "makerDiscountRate":"800000000000000000",
            "takerDiscountRate":"800000000000000000",
            "stakedAmount":"750000000000000000000000",
            "volume":"30000000000000000000000000000"
         }
      ],
      "disqualifiedMarketIds":[
         "0x8b1a4d3e8f6b559e30e40922ee3662dd78edf7042330d4d620d188699d1a9715"
      ]
   }
}
ParameterTypeDescription
fee_discount_scheduleFeeDiscountScheduleFee discount schedule


FeeDiscountSchedule

ParameterTypeDescription
bucket_countIntegerBucket count
bucket_durationIntegerDuration in seconds
quote_denomsString ArrayThe trading fee quote denoms which will be counted for the fee paid contribution
tier_infosFeeDiscountTierInfo ArrayThe fee discount tiers
disqualified_market_idsString ArrayThe marketIDs which are disqualified from contributing to the fee paid amount


FeeDiscountTierInfo

ParameterTypeDescription
maker_discount_rateDecimalMaker trades' discount rate
taker_discount_rateDecimalTaker trades' discount rate
staked_amountDecimalStaked smount to reach this discount tier
volumeDecimalVolume to reach this discount tier

BalanceMismatches

Retrieves mismatches between available vs. total balance

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    mismatches = await client.fetch_balance_mismatches(dust_factor=1)
    print(mismatches)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    res, err := chainClient.FetchBalanceMismatches(ctx, 1)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
dust_factorIntegerDifference treshold to query withYes

Response Parameters

Response Example:

{
   "balanceMismatches":[
      {
         "subaccountId":"0x05fa91c2776ac40473285b75e3d795870b94e5e2000000000000000000000000",
         "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
         "available":"870155637577815628",
         "total":"870155637577800218",
         "balanceHold":"0",
         "expectedTotal":"870155637577815628",
         "difference":"15410"
      },
      {
         "subaccountId":"0x0ec17dde18a517442b7d580f53d8dc705af13ea8000000000000000000000000",
         "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
         "available":"933130554975740524",
         "total":"933130554975739895",
         "balanceHold":"0",
         "expectedTotal":"933130554975740524",
         "difference":"629"
      },
      {
         "subaccountId":"0x16aef18dbaa341952f1af1795cb49960f68dfee3000000000000000000000000",
         "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
         "available":"761588657963815176",
         "total":"75225000761588657963815176",
         "balanceHold":"0",
         "expectedTotal":"761588657963815176",
         "difference":"-75225000000000000000000000"
      },
      {
         "subaccountId":"0x2968698c6b9ed6d44b667a0b1f312a3b5d94ded7000000000000000000000000",
         "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
         "available":"219272509577750671",
         "total":"79887563548606272509577750670",
         "balanceHold":"79887563548387000000000000000",
         "expectedTotal":"79887563548606272509577750671",
         "difference":"1"
      },
      {
         "subaccountId":"0x48237ce2f2d88aebef5eec7b7a228e4b13fd6eb5000000000000000000000002",
         "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
         "available":"4207036229489676145196048627",
         "total":"4207036229489676145196048624",
         "balanceHold":"0",
         "expectedTotal":"4207036229489676145196048627",
         "difference":"3"
      },
      {
         "subaccountId":"0x643de64bde8ae72b8f0acfe88abd444df6b723fd000000000000000000000000",
         "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
         "available":"436283710291691073",
         "total":"436283710291693025",
         "balanceHold":"0",
         "expectedTotal":"436283710291691073",
         "difference":"-1952"
      },
      {
         "subaccountId":"0x6590d14d9e9c1d964f8c83bddc8a092f4a2d1284000000000000000000000000",
         "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
         "available":"546950183781755834",
         "total":"546950183781756580",
         "balanceHold":"0",
         "expectedTotal":"546950183781755834",
         "difference":"-746"
      },
      {
         "subaccountId":"0x7619f89a2172c6705aac7482f3adbf0601ea140e000000000000000000000000",
         "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
         "available":"42406272780554925",
         "total":"42406272780556044",
         "balanceHold":"0",
         "expectedTotal":"42406272780554925",
         "difference":"-1119"
      },
      {
         "subaccountId":"0x8efbdeee271d02e1931a015233b4c1e84631a8f1000000000000000000000000",
         "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
         "available":"703396215678687048",
         "total":"703396215678689667",
         "balanceHold":"0",
         "expectedTotal":"703396215678687048",
         "difference":"-2619"
      },
      {
         "subaccountId":"0xbb4afcb3b0e2a95d91f0eaaf9acefefa00d70a6e000000000000000000000000",
         "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
         "available":"893202463407432010",
         "total":"893202463407432298",
         "balanceHold":"0",
         "expectedTotal":"893202463407432010",
         "difference":"-288"
      },
      {
         "subaccountId":"0xbdaedec95d563fb05240d6e01821008454c24c36000000000000000000000000",
         "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
         "available":"342932031115126491",
         "total":"324904900060342932031115126449",
         "balanceHold":"324904900060000000000000000000",
         "expectedTotal":"324904900060342932031115126491",
         "difference":"42"
      },
      {
         "subaccountId":"0xc877ce74d053ada17c0c41d1203b19b44ac4d790000000000000000000000000",
         "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
         "available":"770209411929225026",
         "total":"770209411929224682",
         "balanceHold":"0",
         "expectedTotal":"770209411929225026",
         "difference":"344"
      },
      {
         "subaccountId":"0xfc48d223d93b6da8817ae50deb15c98babaa67ae000000000000000000000000",
         "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
         "available":"841670909697500242",
         "total":"841670909697500243",
         "balanceHold":"0",
         "expectedTotal":"841670909697500242",
         "difference":"-1"
      }
   ]
}
ParameterTypeDescription
balance_mismatchesBalanceMismatch ArrayList of balance mismatches


BalanceMismatch

ParameterTypeDescription
subaccount_idStringThe subaccount ID the balance belongs to
denomStringThe token denom
availableDecimalThe available balance
totalDecimalThe total balance
balance_holdDecimalThe balance on hold
expected_totalDecimalThe expected total balance
differenceDecimalBalance difference

BalanceWithBalanceHolds

Retrieves available and total balances with balance holds

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    balance = await client.fetch_balance_with_balance_holds()
    print(balance)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    res, err := chainClient.FetchBalanceWithBalanceHolds(ctx)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}

No parameters

Response Parameters

Response Example:

{
   "balanceWithBalanceHolds":[
      {
         "subaccountId":"0x0000000001e9681c4266ec4aaf5fe4de967072ee000000000000000000000000",
         "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
         "available":"0",
         "total":"0",
         "balanceHold":"0"
      },
      {
         "subaccountId":"0x00000002f32c0886ee65d68059fbdb76ef6a6996000000000000000000000000",
         "denom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
         "available":"361169802053915059",
         "total":"361169802053915059",
         "balanceHold":"0"
      }
   ]
}
ParameterTypeDescription
balance_with_balance_holdsBalanceWithMarginHold ArrayList of balances with hold


BalanceWithMarginHold

ParameterTypeDescription
subaccount_idStringThe subaccount ID the balance belongs to
denomStringThe token denom
availableDecimalThe available balance
totalDecimalThe total balance
balance_holdDecimalThe balance on hold

FeeDiscountTierStatistics

Retrieves fee discount tier stats

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    statistics = await client.fetch_fee_discount_tier_statistics()
    print(statistics)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    res, err := chainClient.FetchFeeDiscountTierStatistics(ctx)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}

No parameters

Response Parameters

Response Example:

{
   "statistics":[
      {
         "count":"104",
         "tier":"0"
      },
      {
         "tier":"1",
         "count":"0"
      },
      {
         "tier":"2",
         "count":"1"
      },
      {
         "tier":"3",
         "count":"1"
      },
      {
         "tier":"4",
         "count":"0"
      },
      {
         "tier":"5",
         "count":"0"
      },
      {
         "tier":"6",
         "count":"0"
      },
      {
         "tier":"7",
         "count":"0"
      },
      {
         "tier":"8",
         "count":"0"
      }
   ]
}
ParameterTypeDescription
statisticsTierStatistic ArrayList of tier statistics


TierStatistic

ParameterTypeDescription
tierIntegerTier number
countIntegerThe tier count

MitoVaultInfos

Retrieves market making pool info

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    infos = await client.fetch_mito_vault_infos()
    print(infos)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    res, err := chainClient.FetchMitoVaultInfos(ctx)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}

No parameters

Response Parameters

Response Example:

{
   "masterAddresses":[
      "inj1qg5ega6dykkxc307y25pecuufrjkxkag6xhp6y"
   ],
   "spotAddresses":[
      "inj1wddvh8vnn6rmyhp59qvr5jmpu3nllkgsyzr4m6"
   ],
   "derivativeAddresses":[

   ],
   "cw20Addresses":[

   ]
}
ParameterTypeDescription
master_addressesString ArrayList of master addresses
derivative_addressesString ArrayList of derivative addresses
spot_addressesString ArrayList of spot addresses
cw20_addressesString ArrayList of cw20 contract addresses

QueryMarketIDFromVault

Returns the market ID for a given vault subaccount ID

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    market_id = await client.fetch_market_id_from_vault(vault_address="inj1qg5ega6dykkxc307y25pecuufrjkxkag6xhp6y")
    print(market_id)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    vaultAddress := "inj1qg5ega6dykkxc307y25pecuufrjkxkag6xhp6y"

    res, err := chainClient.FetchMarketIDFromVault(ctx, vaultAddress)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
vault_addressStringThe vault address to query forYes

Response Parameters

Response Example:


ParameterTypeDescription
market_idStringThe vault's market ID

HistoricalTradeRecords

Retrieves historical trade records for a given market ID

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    records = await client.fetch_historical_trade_records(
        market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
    )
    print(records)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    marketId := "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"

    res, err := chainClient.FetchHistoricalTradeRecords(ctx, marketId)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
market_idStringThe market ID to query forYes

Response Parameters

Response Example:

{
   "tradeRecords":[
      {
         "marketId":"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
         "latestTradeRecords":[
            {
               "timestamp":"1709641326",
               "price":"42249000",
               "quantity":"15368000000000000000000000000000000000"
            },
            {
               "timestamp":"1709641446",
               "price":"42080000",
               "quantity":"15415000000000000000000000000000000000"
            }
         ]
      }
   ]
}
ParameterTypeDescription
trade_recordsTradeRecords ArrayList of trade records


TradeRecords

ParameterTypeDescription
market_idStringThe market ID
latest_trade_recordsTradeRecord ArrayList of trade records


TradeRecord

ParameterTypeDescription
timestampIntegerTrade timestamp
priceDecimalTrade price
quantityDecimalTrade quantity

IsOptedOutOfRewards

Retrieves if the account is opted out of rewards

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective import PrivateKey
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    is_opted_out = await client.fetch_is_opted_out_of_rewards(
        account=address.to_acc_bech32(),
    )
    print(is_opted_out)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    res, err := chainClient.FetchIsOptedOutOfRewards(ctx, senderAddress.String())
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
accountStringThe account's address to query forYes

Response Parameters

Response Example:

{
   "isOptedOut":true
}
ParameterTypeDescription
is_opted_outBooleanOpted out state for the account

OptedOutOfRewardsAccounts

Retrieves all accounts opted out of rewards

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    opted_out = await client.fetch_opted_out_of_rewards_accounts()
    print(opted_out)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    res, err := chainClient.FetchOptedOutOfRewardsAccounts(ctx)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}

No parameters

Response Parameters

Response Example:

{
   "accounts":[
      "inj1qqqqpgj4strcnlgzsaae2tey7dhk6enu8fc5zd",
      "inj1fwpyx9k4x5yzm63wmrpg4ekngmv2qjd0yddqaq",
      "inj1tz65vxc7a4acf6gd3fhq23mrquvjhgrtwwr7fz",
      "inj1wefqjmt5xkn7t769kl4kay2ncvx7we0nnephl2",
      "inj1n47c74gv6jwnzzsmqhd7h5msdnx2gncpjk4yh4",
      "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
      "inj1clw20s2uxeyxtam6f7m84vgae92s9eh7vygagt"
   ]
}
ParameterTypeDescription
accountsString ArrayList of opted out accounts

MarketVolatility

Computes the volatility for spot and derivative markets trading history

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
    trade_grouping_sec = 10
    max_age = 0
    include_raw_history = True
    include_metadata = True
    volatility = await client.fetch_market_volatility(
        market_id=market_id,
        trade_grouping_sec=trade_grouping_sec,
        max_age=max_age,
        include_raw_history=include_raw_history,
        include_metadata=include_metadata,
    )
    print(volatility)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/chain/exchange/types"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    marketId := "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
    tradeHistoryOptions := types.TradeHistoryOptions{
        TradeGroupingSec:  10,
        MaxAge:            0,
        IncludeRawHistory: true,
        IncludeMetadata:   true,
    }

    res, err := chainClient.FetchMarketVolatility(ctx, marketId, &tradeHistoryOptions)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
market_idStringThe market ID to query forYes
trade_history_optionsTradeHistoryOptionsExtra query optionsNo


TradeHistoryOptions

ParameterTypeDescription
trade_grouping_secInteger0 means use the chain's default grouping
max_ageIntegerRestricts the trade records oldest age in seconds from the current block time to consider. A value of 0 means use all the records present on the chain
include_raw_historyBooleanIf True, the raw underlying data used for the computation is included in the response
include_metadataBooleanIf True, metadata on the computation is included in the response

Response Parameters

Response Example:

{
   "volatility":"0",
   "historyMetadata":{
      "groupCount":2,
      "recordsSampleSize":2,
      "mean":"42109967",
      "twap":"42080000",
      "firstTimestamp":"1709644088",
      "lastTimestamp":"1709644207",
      "minPrice":"42080000",
      "maxPrice":"42110000",
      "medianPrice":"42095000"
   },
   "rawHistory":[
      {
         "timestamp":"1709644088",
         "price":"42110000",
         "quantity":"15330000000000000000000000000000000000"
      },
      {
         "timestamp":"1709644207",
         "price":"42080000",
         "quantity":"17000000000000000000000000000000000"
      }
   ]
}
ParameterTypeDescription
volatilityDecimalMarket's volatility
history_metadataMetadataStatisticsMarket's volatility
raw_historyTradeRecord ArrayList of trade records


MetadataStatistics

ParameterTypeDescription
group_countIntegerRefers to the number of groups used. Equals records_sample_size if no grouping is used
records_sample_sizeIntegerRefers to the total number of records used
meanDecimalRefers to the arithmetic mean. For trades, the mean is the VWAP computed over the grouped trade records ∑ (price * quantity) / ∑ quantity For oracle prices, the mean is computed over the price records ∑ (price) / prices_count
twapDecimalRefers to the time-weighted average price which equals ∑ (price_i * ∆t_i) / ∑ ∆t_i where ∆t_i = t_i - t_{i-1}
first_timestampIntegerThe timestamp of the oldest record considered
last_timestampIntegerThe timestamp of the youngest record considered
min_priceDecimalRefers to the smallest individual raw price considered
max_priceDecimalRefers to the largest individual raw price considered
median_priceDecimalRefers to the median individual raw price considered


TradeRecord

ParameterTypeDescription
timestampIntegerTrade timestamp
priceDecimalTrade price
quantityDecimalTrade quantity

MarketAtomicExecutionFeeMultiplier

Retrieves the atomic execution fee multiplier

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    multiplier = await client.fetch_market_atomic_execution_fee_multiplier(
        market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
    )
    print(multiplier)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    marketId := "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"

    res, err := chainClient.FetchMarketAtomicExecutionFeeMultiplier(ctx, marketId)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
market_idStringThe market ID to query forYes

Response Parameters

Response Example:

{
   "multiplier":"2000000000000000000"
}
ParameterTypeDescription
multiplierDecimalThe multiplier value

MsgRewardsOptOut

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    # prepare tx msg
    msg = composer.msg_rewards_opt_out(sender=address.to_acc_bech32())

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "fmt"
    "os"
    "time"

    "github.com/InjectiveLabs/sdk-go/client"
    "github.com/InjectiveLabs/sdk-go/client/common"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    msg := &exchangetypes.MsgRewardsOptOut{
        Sender: senderAddress.String(),
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    err = chainClient.QueueBroadcastMsg(msg)

    if err != nil {
        fmt.Println(err)
    }

    time.Sleep(time.Second * 5)

    gasFee, err := chainClient.GetGasFee()

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("gas fee:", gasFee, "INJ")
}
ParameterTypeDescriptionRequired
senderStringThe sender's addressYes

Response Parameters

Response Example:

ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgAuthorizeStakeGrants

Message to grant stakes to grantees.

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os
from decimal import Decimal

import dotenv

from pyinjective.async_client import AsyncClient
from pyinjective.core.broadcaster import MsgBroadcasterWithPk
from pyinjective.core.network import Network
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    await client.initialize_tokens_from_chain_denoms()
    composer = await client.composer()
    await client.sync_timeout_height()

    message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
        network=network,
        private_key=configured_private_key,
    )

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    # prepare tx msg
    grant_authorization = composer.create_grant_authorization(
        grantee="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
        amount=Decimal("1"),
    )
    message = composer.msg_authorize_stake_grants(sender=address.to_acc_bech32(), grants=[grant_authorization])

    # broadcast the transaction
    result = await message_broadcaster.broadcast([message])
    print("---Transaction Response---")
    print(result)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "encoding/json"
    "fmt"
    "os"

    "cosmossdk.io/math"

    "github.com/InjectiveLabs/sdk-go/client"

    "github.com/InjectiveLabs/sdk-go/client/common"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    grantAuthorization := &exchangetypes.GrantAuthorization{
        Grantee: "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
        Amount:  math.NewIntWithDecimal(1, 18),
    }

    msg := &exchangetypes.MsgAuthorizeStakeGrants{
        Sender: senderAddress.String(),
        Grants: []*exchangetypes.GrantAuthorization{grantAuthorization},
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    response, err := chainClient.AsyncBroadcastMsg(msg)

    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(response, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
senderStringInjective address of the stake granterYes
grantsGrantAuthorization ArrayList of grants assigned to the granteesYes


GrantAuthorization

ParameterTypeDescription
granteeStringGrantee's Injective address
amountIntegerAmount of stake granted (INJ in chain format)

Response Parameters

Response Example:

txhash: "5AF048ADCE6AF753256F03AF2404A5B78C4C3E7E42A91F0B5C9994372E8AC2FE"
raw_log: "[]"

gas wanted: 106585
gas fee: 0.0000532925 INJ
DEBU[0001] broadcastTx with nonce 3503                   fn=func1 src="client/chain/chain.go:598"
DEBU[0002] msg batch committed successfully at height 5214406  fn=func1 src="client/chain/chain.go:619"
txHash=31FDA89C3122322C0559B5766CDF892FD0AA12469017CF8BF88B53441464ECC4
DEBU[0002] nonce incremented to 3504                     fn=func1 src="client/chain/chain.go:623"
DEBU[0002] gas wanted:  133614                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.000066807 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgActivateStakeGrant

Message for grantees to claim stake grants.

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective.async_client import AsyncClient
from pyinjective.core.broadcaster import MsgBroadcasterWithPk
from pyinjective.core.network import Network
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    await client.initialize_tokens_from_chain_denoms()
    composer = await client.composer()
    await client.sync_timeout_height()

    message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
        network=network,
        private_key=configured_private_key,
    )

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    # prepare tx msg
    message = composer.msg_activate_stake_grant(
        sender=address.to_acc_bech32(), granter="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
    )

    # broadcast the transaction
    result = await message_broadcaster.broadcast([message])
    print("---Transaction Response---")
    print(result)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"

    "github.com/InjectiveLabs/sdk-go/client/common"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    msg := &exchangetypes.MsgActivateStakeGrant{
        Sender:  senderAddress.String(),
        Granter: "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    response, err := chainClient.AsyncBroadcastMsg(msg)

    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(response, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
senderStringInjective address of the stake granteeYes
granterStringInjective address of the stake granterYes


GrantAuthorization

ParameterTypeDescription
granteeStringGrantee's Injective address
amountIntegerAmount of stake granted (INJ in chain format)

Response Parameters

Response Example:

txhash: "5AF048ADCE6AF753256F03AF2404A5B78C4C3E7E42A91F0B5C9994372E8AC2FE"
raw_log: "[]"

gas wanted: 106585
gas fee: 0.0000532925 INJ
DEBU[0001] broadcastTx with nonce 3503                   fn=func1 src="client/chain/chain.go:598"
DEBU[0002] msg batch committed successfully at height 5214406  fn=func1 src="client/chain/chain.go:619"
txHash=31FDA89C3122322C0559B5766CDF892FD0AA12469017CF8BF88B53441464ECC4
DEBU[0002] nonce incremented to 3504                     fn=func1 src="client/chain/chain.go:623"
DEBU[0002] gas wanted:  133614                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.000066807 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

- Chain Exchange for Derivatives

Includes all messages related to derivative markets.

DerivativeMidPriceAndTOB

Retrieves a derivative market's mid-price

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    prices = await client.fetch_derivative_mid_price_and_tob(
        market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
    )
    print(prices)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    marketId := "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"

    res, err := chainClient.FetchDerivativeMidPriceAndTOB(ctx, marketId)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
market_idStringMarket ID to request forYes

Response Parameters

Response Example:

{
   "midPrice":"36928150000000000000000000",
   "bestBuyPrice":"36891200000000000000000000",
   "bestSellPrice":"36965100000000000000000000"
}
ParameterTypeDescription
mid_priceDecimalMarket's mid price
best_buy_priceDecimalMarket's bet bid price
best_sell_priceDecimalMarket's bet ask price

DerivativeOrderbook

Retrieves a derivative market's orderbook by marketID

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    pagination = PaginationOption(limit=2)

    orderbook = await client.fetch_chain_derivative_orderbook(
        market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
        pagination=pagination,
    )
    print(orderbook)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "cosmossdk.io/math"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    marketId := "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
    limit := uint64(2)
    limitCumulativeNotional := math.LegacyDec{}

    res, err := chainClient.FetchChainDerivativeOrderbook(ctx, marketId, limit, limitCumulativeNotional)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
market_idStringMarket ID to request forYes
limitIntegerMax number of order book entries to return per sideNo
limit_cumulative_notionalDecimalLimit the number of entries to return per side based on the cumulative notionalNo

Response Parameters

Response Example:

{
   "buysPriceLevel":[
      {
         "p":"36891200000000000000000000",
         "q":"3253632000000000000000"
      },
      {
         "p":"36860900000000000000000000",
         "q":"500000000000000000"
      }
   ],
   "sellsPriceLevel":[
      {
         "p":"36965100000000000000000000",
         "q":"60344815000000000000000"
      },
      {
         "p":"37057500000000000000000000",
         "q":"60194349800000000000000"
      }
   ]
}
ParameterTypeDescription
buys_price_levelLevel ArrayBid side entries
sells_price_levelLevel ArrayAsk side entries


Level

ParameterTypeDescription
pDecimalPrice
qDecimalQuantity

TraderDerivativeOrders

Retrieves a trader's derivative orders

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective import PrivateKey
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    subaccount_id = address.get_subaccount_id(index=0)

    orders = await client.fetch_chain_trader_derivative_orders(
        market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
        subaccount_id=subaccount_id,
    )
    print(orders)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    marketId := "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    subaccountId := chainClient.Subaccount(senderAddress, 0)

    res, err := chainClient.FetchChainTraderDerivativeOrders(ctx, marketId, subaccountId.Hex())
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
market_idStringMarket ID to request forYes
subaccount_idStringTrader's subaccount IDYes

Response Parameters

Response Example:

{
   "orders":[

   ]
}
ParameterTypeDescription
ordersTrimmedDerivativeLimitOrder ArrayOrders info


TrimmedDerivativeLimitOrder

ParameterTypeDescription
priceDecimalOrder price
quantityDecimalOrder quantity
marginDecimalOrder margin
fillableDecimalThe remaining fillable amount of the order
is_buyBooleanTrue if the order is a buy order
order_hashStringThe order hash
cidStringThe client order ID provided by the creator

AccountAddressDerivativeOrders

Retrieves all account address' derivative orders

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective import PrivateKey
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    orders = await client.fetch_chain_account_address_derivative_orders(
        market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
        account_address=address.to_acc_bech32(),
    )
    print(orders)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    marketId := "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"

    res, err := chainClient.FetchChainAccountAddressDerivativeOrders(ctx, marketId, senderAddress.String())
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
market_idStringMarket ID to request forYes
account_addressStringTrader's account addressYes

Response Parameters

Response Example:

{
   "orders":[

   ]
}
ParameterTypeDescription
ordersTrimmedDerivativeLimitOrder ArrayOrders info


TrimmedDerivativeLimitOrder

ParameterTypeDescription
priceDecimalOrder price
quantityDecimalOrder quantity
marginDecimalOrder margin
fillableDecimalThe remaining fillable amount of the order
is_buyBooleanTrue if the order is a buy order
order_hashStringThe order hash
cidStringThe client order ID provided by the creator

DerivativeOrdersByHashes

Retrieves a trader's derivative orders

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective import PrivateKey
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    subaccount_id = address.get_subaccount_id(index=0)

    orders = await client.fetch_chain_derivative_orders_by_hashes(
        market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
        subaccount_id=subaccount_id,
        order_hashes=["0x57a01cd26f1e2080860af3264e865d7c9c034a701e30946d01c1dc7a303cf2c1"],
    )
    print(orders)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    marketId := "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    subaccountId := chainClient.Subaccount(senderAddress, 0)
    orderHashes := []string{"0x57a01cd26f1e2080860af3264e865d7c9c034a701e30946d01c1dc7a303cf2c1"}

    res, err := chainClient.FetchChainDerivativeOrdersByHashes(ctx, marketId, subaccountId.Hex(), orderHashes)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
market_idStringMarket ID to request forYes
subaccount_idStringTrader's subaccount IDYes
order_hashesString ArrayList of order hashes to retrieve information forYes

Response Parameters

Response Example:

{
   "orders":[

   ]
}
ParameterTypeDescription
ordersTrimmedDerivativeLimitOrder ArrayOrders info


TrimmedDerivativeLimitOrder

ParameterTypeDescription
priceDecimalOrder price
quantityDecimalOrder quantity
marginDecimalOrder margin
fillableDecimalThe remaining fillable amount of the order
is_buyBooleanTrue if the order is a buy order
order_hashStringThe order hash
cidStringThe client order ID provided by the creator

TraderDerivativeTransientOrders

Retrieves a trader's transient derivative orders

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective import PrivateKey
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    subaccount_id = address.get_subaccount_id(index=0)

    orders = await client.fetch_chain_trader_derivative_transient_orders(
        market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
        subaccount_id=subaccount_id,
    )
    print(orders)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    marketId := "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    subaccountId := chainClient.Subaccount(senderAddress, 0)

    res, err := chainClient.FetchChainTraderDerivativeTransientOrders(ctx, marketId, subaccountId.Hex())
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
market_idStringMarket ID to request forYes
subaccount_idStringTrader's subaccount IDYes

Response Parameters

Response Example:

{
   "orders":[

   ]
}
ParameterTypeDescription
ordersTrimmedDerivativeLimitOrder ArrayOrders info


TrimmedDerivativeLimitOrder

ParameterTypeDescription
priceDecimalOrder price
quantityDecimalOrder quantity
marginDecimalOrder margin
fillableDecimalThe remaining fillable amount of the order
is_buyBooleanTrue if the order is a buy order
order_hashStringThe order hash
cidStringThe client order ID provided by the creator

DerivativeMarkets

Retrieves a list of derivative markets

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    derivative_markets = await client.fetch_chain_derivative_markets(
        status="Active",
        market_ids=["0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"],
    )
    print(derivative_markets)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    status := "Active"
    marketIds := []string{"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"}
    withMidPriceAndTob := true

    res, err := chainClient.FetchChainDerivativeMarkets(ctx, status, marketIds, withMidPriceAndTob)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
statusStringMarket statusNo
market_idsString ArrayList of market IDsNo
with_mid_price_and_tobBooleanFlag to activate/deactivate the inclusion of the markets mid price and top of the book buy and sell ordersNo

Response Parameters

Response Example:

{
   "markets":[
      {
         "market":{
            "ticker":"INJ/USDT PERP",
            "oracleBase":"0x2d9315a88f3019f8efa88dfe9c0f0843712da0bac814461e27733f6b83eb51b3",
            "oracleQuote":"0x1fc18861232290221461220bd4e2acd1dcdfbc89c84092c93c18bdc7756c1588",
            "oracleType":"Pyth",
            "oracleScaleFactor":6,
            "quoteDenom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
            "marketId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
            "initialMarginRatio":"50000000000000000",
            "maintenanceMarginRatio":"20000000000000000",
            "makerFeeRate":"-100000000000000",
            "takerFeeRate":"1000000000000000",
            "relayerFeeShareRate":"400000000000000000",
            "isPerpetual":true,
            "status":"Active",
            "minPriceTickSize":"100000000000000000000",
            "minQuantityTickSize":"100000000000000"
         },
         "perpetualInfo":{
            "marketInfo":{
               "marketId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
               "hourlyFundingRateCap":"625000000000000",
               "hourlyInterestRate":"4166660000000",
               "nextFundingTimestamp":"1709546400",
               "fundingInterval":"3600"
            },
            "fundingInfo":{
               "cumulativeFunding":"-44519773449439313111470",
               "cumulativePrice":"0",
               "lastTimestamp":"1709542800"
            }
         },
         "markPrice":"39829277195482383939000000"
      }
   ]
}
ParameterTypeDescription
marketsFullDerivativeMarket ArrayMarkets information


FullDerivativeMarket

ParameterTypeDescription
marketDerivativeMarketMarket basic information
infoPerpetualMarketState or ExpiryFuturesMarketInfoSpecific information for the perpetual or expiry futures market
mark_priceDecimalThe market mark price
mid_price_and_tobMidPriceAndTOBThe mid price for this market and the best ask and bid orders


DerivativeMarket

ParameterTypeDescription
tickerStringName of the pair in format AAA/BBB, where AAA is base asset, BBB is quote asset
oracle_baseStringOracle base token
oracle_quoteStringOracle quote token
oracle_typeOracleTypeThe oracle type
oracle_scale_factorIntegerThe oracle number of scale decimals
quote_denomStringCoin denom used for the quote asset
market_idStringThe market ID
initial_margin_ratioDecimalThe max initial margin ratio a position is allowed to have in the market
maintenance_margin_ratioDecimalThe max maintenance margin ratio a position is allowed to have in the market
maker_fee_rateDecimalFee percentage makers pay when trading
taker_fee_rateDecimalFee percentage takers pay when trading
relayer_fee_share_rateDecimalPercentage of the transaction fee shared with the relayer in a derivative market
is_perpetualBooleanTrue if the market is a perpetual market. False if the market is an expiry futures market
statusMarketStatusStatus of the market
min_price_tick_sizeDecimalMinimum tick size that the price required for orders in the market
min_quantity_tick_sizeDecimalMinimum tick size of the quantity required for orders in the market
min_notionalDecimalMinimum notional (in quote asset) required for orders in the market
adminStringCurrent market admin's address
admin_permissionsIntegerLevel of admin permissions (the permission number is a result of adding up all individual permissions numbers)


OracleType

CodeName
0Unspecified
1Band
2PriceFeed
3Coinbase
4Chainlink
5Razor
6Dia
7API3
8Uma
9Pyth
10BandIBC
11Provider


MarketStatus

CodeName
0Unspecified
1Active
2Paused
3Demolished
4Expired


PerpetualMarketState

ParameterTypeDescription
market_infoPerpetualMarketInfoPerpetual market information
funding_infoPerpetualMarketFundingMarket funding information


PerpetualMarketInfo

ParameterTypeDescription
market_idStringThe market ID
hourly_funding_rate_capDecimalMaximum absolute value of the hourly funding rate
hourly_interest_rateDecimalThe hourly interest rate
next_funding_timestampIntegerThe next funding timestamp in seconds
funding_intervalIntegerThe next funding interval in seconds


PerpetualMarketFunding

ParameterTypeDescription
cumulative_fundingDecimalThe market's cumulative funding
cumulative_priceDecimalThe cumulative price for the current hour up to the last timestamp
last_timestampIntegerLast funding timestamp in seconds


ExpiryFuturesMarketInfo

ParameterTypeDescription
market_idStringThe market ID
expiration_timestampIntegerThe market's expiration time in seconds
twap_start_timestampIntegerDefines the start time of the TWAP calculation window
expiration_twap_start_price_cumulativeDecimalDefines the cumulative price for the start of the TWAP window
settlement_priceDecimalThe settlement price


AdminPermission

CodeName
1Ticker Permission
2Min Price Tick Size Permission
4Min Quantity Tick Size Permission
8Min Notional Permission
16Initial Margin Ratio Permission
32Maintenance Margin Ratio Permission
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    marketId := "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"

    res, err := chainClient.FetchChainDerivativeMarket(ctx, marketId)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
market_idStringThe marke ID to query forYes

Response Parameters

Response Example:

{
   "market":{
      "market":{
         "ticker":"INJ/USDT PERP",
         "oracleBase":"0x2d9315a88f3019f8efa88dfe9c0f0843712da0bac814461e27733f6b83eb51b3",
         "oracleQuote":"0x1fc18861232290221461220bd4e2acd1dcdfbc89c84092c93c18bdc7756c1588",
         "oracleType":"Pyth",
         "oracleScaleFactor":6,
         "quoteDenom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
         "marketId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
         "initialMarginRatio":"50000000000000000",
         "maintenanceMarginRatio":"20000000000000000",
         "makerFeeRate":"-100000000000000",
         "takerFeeRate":"1000000000000000",
         "relayerFeeShareRate":"400000000000000000",
         "isPerpetual":true,
         "status":"Active",
         "minPriceTickSize":"100000000000000000000",
         "minQuantityTickSize":"100000000000000"
      },
      "perpetualInfo":{
         "marketInfo":{
            "marketId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
            "hourlyFundingRateCap":"625000000000000",
            "hourlyInterestRate":"4166660000000",
            "nextFundingTimestamp":"1709553600",
            "fundingInterval":"3600"
         },
         "fundingInfo":{
            "cumulativeFunding":"-44192284639015238855564",
            "cumulativePrice":"0",
            "lastTimestamp":"1709550000"
         }
      },
      "markPrice":"39011901904676818317000000"
   }
}
ParameterTypeDescription
marketFullDerivativeMarketMarket information


FullDerivativeMarket

ParameterTypeDescription
marketDerivativeMarketMarket basic information
infoPerpetualMarketState or ExpiryFuturesMarketInfoSpecific information for the perpetual or expiry futures market
mark_priceDecimalThe market mark price
mid_price_and_tobMidPriceAndTOBThe mid price for this market and the best ask and bid orders


DerivativeMarket

ParameterTypeDescription
tickerStringName of the pair in format AAA/BBB, where AAA is base asset, BBB is quote asset
oracle_baseStringOracle base token
oracle_quoteStringOracle quote token
oracle_typeOracleTypeThe oracle type
oracle_scale_factorIntegerThe oracle number of scale decimals
quote_denomStringCoin denom used for the quote asset
market_idStringThe market ID
initial_margin_ratioDecimalThe max initial margin ratio a position is allowed to have in the market
maintenance_margin_ratioDecimalThe max maintenance margin ratio a position is allowed to have in the market
maker_fee_rateDecimalFee percentage makers pay when trading
taker_fee_rateDecimalFee percentage takers pay when trading
relayer_fee_share_rateDecimalPercentage of the transaction fee shared with the relayer in a derivative market
is_perpetualBooleanTrue if the market is a perpetual market. False if the market is an expiry futures market
statusMarketStatusStatus of the market
min_price_tick_sizeDecimalMinimum tick size that the price required for orders in the market
min_quantity_tick_sizeDecimalMinimum tick size of the quantity required for orders in the market
min_notionalDecimalMinimum notional (in quote asset) required for orders in the market
adminStringCurrent market admin's address
admin_permissionsIntegerLevel of admin permissions (the permission number is a result of adding up all individual permissions numbers)


OracleType

CodeName
0Unspecified
1Band
2PriceFeed
3Coinbase
4Chainlink
5Razor
6Dia
7API3
8Uma
9Pyth
10BandIBC
11Provider


MarketStatus

CodeName
0Unspecified
1Active
2Paused
3Demolished
4Expired


PerpetualMarketState

ParameterTypeDescription
market_infoPerpetualMarketInfoPerpetual market information
funding_infoPerpetualMarketFundingMarket funding information


PerpetualMarketInfo

ParameterTypeDescription
market_idStringThe market ID
hourly_funding_rate_capDecimalMaximum absolute value of the hourly funding rate
hourly_interest_rateDecimalThe hourly interest rate
next_funding_timestampIntegerThe next funding timestamp in seconds
funding_intervalIntegerThe next funding interval in seconds


PerpetualMarketFunding

ParameterTypeDescription
cumulative_fundingDecimalThe market's cumulative funding
cumulative_priceDecimalThe cumulative price for the current hour up to the last timestamp
last_timestampIntegerLast funding timestamp in seconds


ExpiryFuturesMarketInfo

ParameterTypeDescription
market_idStringThe market ID
expiration_timestampIntegerThe market's expiration time in seconds
twap_start_timestampIntegerDefines the start time of the TWAP calculation window
expiration_twap_start_price_cumulativeDecimalDefines the cumulative price for the start of the TWAP window
settlement_priceDecimalThe settlement price


AdminPermission

CodeName
1Ticker Permission
2Min Price Tick Size Permission
4Min Quantity Tick Size Permission
8Min Notional Permission
16Initial Margin Ratio Permission
32Maintenance Margin Ratio Permission
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    marketId := "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"

    res, err := chainClient.FetchDerivativeMarketAddress(ctx, marketId)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
market_idStringThe marke ID to query forYes

Response Parameters

Response Example:

{
   "address":"inj1zlh5sqevkfphtwnu9cul8p89vseme2eqt0snn9",
   "subaccountId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20000000000000000000000000"
}
ParameterTypeDescription
addressStringThe market's address
subaccount_idStringThe market's subaccount ID

Positions

Retrieves the entire exchange module's positions

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    positions = await client.fetch_chain_positions()
    print(positions)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    res, err := chainClient.FetchChainPositions(ctx)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}

No parameters

Response Parameters

Response Example:

{
   "state":[
      {
         "subaccountId":"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
         "marketId":"0x0f03542809143c7e5d3c22f56bc6e51eb2c8bab5009161b58f6f468432dfa196",
         "position":{
            "isLong":true,
            "quantity":"258750000000000000000",
            "entryPrice":"24100496718773416724721614",
            "margin":"6777476791762608353694085318",
            "cumulativeFundingEntry":"50154448152800501378128"
         }
      },
      {
         "subaccountId":"0xd28d1e9bc2d5a00e5e17f82fa6d4a7b0f4f034de000000000000000000000000",
         "marketId":"0x0f03542809143c7e5d3c22f56bc6e51eb2c8bab5009161b58f6f468432dfa196",
         "position":{
            "quantity":"258750000000000000000",
            "entryPrice":"23962425204761235933835394",
            "margin":"6044298532028028581333461495",
            "cumulativeFundingEntry":"50154448152800501378128",
            "isLong":false
         }
      }
   ]
}
ParameterTypeDescription
stateDerivativePosition ArrayList of derivative positions


DerivativePosition

ParameterTypeDescription
subaccount_idStringSubaccount ID the position belongs to
market_idStringID of the position's market
positionPositionPosition information


Position

ParameterTypeDescription
is_longBooleanTrue if the position is long. False if the position is short
quantityDecimalThe position's amount
entry_priceDecimalThe order execution price when the position was created
marginDecimalThe position's current margin amount
cumulative_funding_entryDecimalThe cummulative funding

SubaccountPositions

Retrieves subaccount's positions

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective import PrivateKey
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    subaccount_id = address.get_subaccount_id(index=0)

    positions = await client.fetch_chain_subaccount_positions(
        subaccount_id=subaccount_id,
    )
    print(positions)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    subaccountId := chainClient.Subaccount(senderAddress, 0)

    res, err := chainClient.FetchChainSubaccountPositions(ctx, subaccountId.Hex())
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
subaccount_idStringThe subaccount ID to query forYes

Response Parameters

Response Example:

{
   "state":[
      {
         "subaccountId":"0xbdaedec95d563fb05240d6e01821008454c24c36000000000000000000000000",
         "marketId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
         "position":{
            "quantity":"3340193358036765108",
            "entryPrice":"36571100000000000000000000",
            "margin":"122195236794397342072018650",
            "cumulativeFundingEntry":"-252598128590449182271444",
            "isLong":false
         }
      },
      {
         "subaccountId":"0xbdaedec95d563fb05240d6e01821008454c24c36000000000000000000000000",
         "marketId":"0x95698a9d8ba11660f44d7001d8c6fb191552ece5d9141a05c5d9128711cdc2e0",
         "position":{
            "isLong":true,
            "quantity":"135686990000000000000000",
            "entryPrice":"22530000000000000000000000",
            "margin":"636295890792648990477285777577",
            "cumulativeFundingEntry":"547604913674998202455064"
         }
      },
      {
         "subaccountId":"0xbdaedec95d563fb05240d6e01821008454c24c36000000000000000000000000",
         "marketId":"0xba9c96a1a9cc226cfe6bd9bca3a433e396569d1955393f38f2ee728cfda7ec58",
         "position":{
            "quantity":"49610000000000000000",
            "entryPrice":"132668911285488007767214817",
            "margin":"6506890715472807452489590330",
            "cumulativeFundingEntry":"1853558761901071670120617",
            "isLong":false
         }
      },
      {
         "subaccountId":"0xbdaedec95d563fb05240d6e01821008454c24c36000000000000000000000000",
         "marketId":"0xd97d0da6f6c11710ef06315971250e4e9aed4b7d4cd02059c9477ec8cf243782",
         "position":{
            "quantity":"1000000000000000000",
            "entryPrice":"10700000000000000000000000",
            "margin":"10646500000000000000000000",
            "cumulativeFundingEntry":"452362068840099307543671",
            "isLong":false
         }
      },
      {
         "subaccountId":"0xbdaedec95d563fb05240d6e01821008454c24c36000000000000000000000000",
         "marketId":"0xe185b08a7ccd830a94060edd5e457d30f429aa6f0757f75a8b93aa611780cfac",
         "position":{
            "quantity":"71000000000000000000",
            "entryPrice":"1282490277777777777777778",
            "margin":"87823626715436695150716328",
            "cumulativeFundingEntry":"4419299319189937712262",
            "isLong":false
         }
      }
   ]
}
ParameterTypeDescription
stateDerivativePosition ArrayList of derivative positions


DerivativePosition

ParameterTypeDescription
subaccount_idStringSubaccount ID the position belongs to
market_idStringID of the position's market
positionPositionPosition information


Position

ParameterTypeDescription
is_longBooleanTrue if the position is long. False if the position is short
quantityDecimalThe position's amount
entry_priceDecimalThe order execution price when the position was created
marginDecimalThe position's current margin amount
cumulative_funding_entryDecimalThe cummulative funding

SubaccountPositionInMarket

Retrieves subaccount's position in market

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective import PrivateKey
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    subaccount_id = address.get_subaccount_id(index=0)

    position = await client.fetch_chain_subaccount_position_in_market(
        subaccount_id=subaccount_id,
        market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
    )
    print(position)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    subaccountId := chainClient.Subaccount(senderAddress, 0)
    marketId := "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"

    res, err := chainClient.FetchChainSubaccountPositionInMarket(ctx, subaccountId.Hex(), marketId)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
subaccount_idStringThe subaccount ID to query forYes
market_idStringThe market ID to query forYes

Response Parameters

Response Example:

{
   "state":{
      "quantity":"3340193358036765108",
      "entryPrice":"36571100000000000000000000",
      "margin":"122195236794397342072018650",
      "cumulativeFundingEntry":"-252598128590449182271444",
      "isLong":false
   }
}
ParameterTypeDescription
statePositionPosition information


Position

ParameterTypeDescription
is_longBooleanTrue if the position is long. False if the position is short
quantityDecimalThe position's amount
entry_priceDecimalThe order execution price when the position was created
marginDecimalThe position's current margin amount
cumulative_funding_entryDecimalThe cummulative funding

SubaccountEffectivePositionInMarket

Retrieves subaccount's position in market

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective import PrivateKey
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    subaccount_id = address.get_subaccount_id(index=0)

    position = await client.fetch_chain_subaccount_effective_position_in_market(
        subaccount_id=subaccount_id,
        market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
    )
    print(position)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    subaccountId := chainClient.Subaccount(senderAddress, 0)
    marketId := "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"

    res, err := chainClient.FetchChainSubaccountEffectivePositionInMarket(ctx, subaccountId.Hex(), marketId)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
subaccount_idStringThe subaccount ID to query forYes
market_idStringThe market ID to query forYes

Response Parameters

Response Example:

{
   "state":{
      "quantity":"3340193358036765108",
      "entryPrice":"36571100000000000000000000",
      "effectiveMargin":"115186707927789961723454140",
      "isLong":false
   }
}
ParameterTypeDescription
stateEffectivePositionEffective position information


EffectivePosition

ParameterTypeDescription
is_effective_position_longBooleanTrue if the position is long. False if the position is short
quantityDecimalThe position's amount
entry_priceDecimalThe order execution price when the position was created
effective_marginDecimalThe position's current margin amount

PerpetualMarketInfo

Retrieves perpetual market's info

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    market_info = await client.fetch_chain_perpetual_market_info(
        market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
    )
    print(market_info)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    marketId := "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"

    res, err := chainClient.FetchChainPerpetualMarketInfo(ctx, marketId)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
market_idStringThe market ID to query forYes

Response Parameters

Response Example:

{
   "info":{
      "marketId":"0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
      "hourlyFundingRateCap":"625000000000000",
      "hourlyInterestRate":"4166660000000",
      "nextFundingTimestamp":"1709560800",
      "fundingInterval":"3600"
   }
}
ParameterTypeDescription
infoPerpetualMarketInfoPerpetual market information


PerpetualMarketInfo

ParameterTypeDescription
market_idStringThe market ID
hourly_funding_rate_capDecimalMaximum absolute value of the hourly funding rate
hourly_interest_rateDecimalThe hourly interest rate
next_funding_timestampIntegerThe next funding timestamp in seconds
funding_intervalIntegerThe next funding interval in seconds

ExpiryFuturesMarketInfo

Retrieves expiry market's info

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    market_info = await client.fetch_chain_expiry_futures_market_info(
        market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
    )
    print(market_info)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    marketId := "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"

    res, err := chainClient.FetchChainExpiryFuturesMarketInfo(ctx, marketId)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
market_idStringThe market ID to query forYes

Response Parameters

Response Example:


ParameterTypeDescription
infoExpiryFuturesMarketInfoExpiry futures market information


ExpiryFuturesMarketInfo

ParameterTypeDescription
market_idStringThe market ID
expiration_timestampIntegerThe market's expiration time in seconds
twap_start_timestampIntegerDefines the start time of the TWAP calculation window
expiration_twap_start_price_cumulativeDecimalDefines the cumulative price for the start of the TWAP window
settlement_priceDecimalThe settlement price

PerpetualMarketFunding

Retrieves perpetual market funding

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    funding = await client.fetch_chain_perpetual_market_funding(
        market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
    )
    print(funding)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    marketId := "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"

    res, err := chainClient.FetchChainPerpetualMarketFunding(ctx, marketId)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
market_idStringThe market ID to query forYes

Response Parameters

Response Example:

{
   "state":{
      "cumulativeFunding":"-43868182364823854683390",
      "cumulativePrice":"0",
      "lastTimestamp":"1709557200"
   }
}
ParameterTypeDescription
statePerpetualMarketFundingMarket funding information


PerpetualMarketFunding

ParameterTypeDescription
cumulative_fundingDecimalThe market's cumulative funding
cumulative_priceDecimalThe cumulative price for the current hour up to the last timestamp
last_timestampIntegerLast funding timestamp in seconds

TraderDerivativeConditionalOrders

Retrieves a trader's derivative conditional orders

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective import PrivateKey
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    subaccount_id = address.get_subaccount_id(index=0)

    orders = await client.fetch_trader_derivative_conditional_orders(
        subaccount_id=subaccount_id,
        market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
    )
    print(orders)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    marketId := "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    subaccountId := chainClient.Subaccount(senderAddress, 0)

    res, err := chainClient.FetchTraderDerivativeConditionalOrders(ctx, subaccountId.Hex(), marketId)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
subaccount_idStringTrader subaccount IDNo
market_idStringThe market ID to query forNo

Response Parameters

Response Example:

{
   "orders":[

   ]
}
ParameterTypeDescription
ordersTrimmedDerivativeConditionalOrder ArrayList of conditional orders


TrimmedDerivativeConditionalOrder

ParameterTypeDescription
priceDecimalThe order price
quantityDecimalThe order quantity
marginDecimalThe order margin
trigger_priceOracleTypePrice to trigger the order
is_buyBooleanTrue if the order is a buy order. False otherwise.
is_limitBooleanTrue if the order is a limit order. False otherwise.
order_hashStringThe order hash
cidStringThe client order ID provided by the creator

MsgInstantPerpetualMarketLaunch

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os
from decimal import Decimal

import dotenv

from pyinjective.async_client import AsyncClient
from pyinjective.core.broadcaster import MsgBroadcasterWithPk
from pyinjective.core.network import Network
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    await client.initialize_tokens_from_chain_denoms()
    composer = await client.composer()
    await client.sync_timeout_height()

    message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
        network=network,
        private_key=configured_private_key,
    )

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    # prepare tx msg
    message = composer.msg_instant_perpetual_market_launch(
        sender=address.to_acc_bech32(),
        ticker="INJ/USDC PERP",
        quote_denom="USDC",
        oracle_base="INJ",
        oracle_quote="USDC",
        oracle_scale_factor=6,
        oracle_type="Band",
        maker_fee_rate=Decimal("-0.0001"),
        taker_fee_rate=Decimal("0.001"),
        initial_margin_ratio=Decimal("0.33"),
        maintenance_margin_ratio=Decimal("0.095"),
        min_price_tick_size=Decimal("0.001"),
        min_quantity_tick_size=Decimal("0.01"),
        min_notional=Decimal("1"),
    )

    # broadcast the transaction
    result = await message_broadcaster.broadcast([message])
    print("---Transaction Response---")
    print(result)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "cosmossdk.io/math"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    oracletypes "github.com/InjectiveLabs/sdk-go/chain/oracle/types"
    exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )
    if err != nil {
        panic(err)
    }

    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketsAssistant, err := chainclient.NewMarketsAssistantInitializedFromChain(ctx, exchangeClient)
    if err != nil {
        panic(err)
    }

    quoteToken := marketsAssistant.AllTokens()["USDC"]
    minPriceTickSize := math.LegacyMustNewDecFromStr("0.01")
    minQuantityTickSize := math.LegacyMustNewDecFromStr("0.001")

    chainMinPriceTickSize := minPriceTickSize.Mul(math.LegacyNewDecFromIntWithPrec(math.NewInt(1), int64(quoteToken.Decimals)))
    chainMinQuantityTickSize := minQuantityTickSize

    msg := &exchangetypes.MsgInstantPerpetualMarketLaunch{
        Sender:                 senderAddress.String(),
        Ticker:                 "INJ/USDC PERP",
        QuoteDenom:             quoteToken.Denom,
        OracleBase:             "INJ",
        OracleQuote:            "USDC",
        OracleScaleFactor:      6,
        OracleType:             oracletypes.OracleType_Band,
        MakerFeeRate:           math.LegacyMustNewDecFromStr("-0.0001"),
        TakerFeeRate:           math.LegacyMustNewDecFromStr("0.001"),
        InitialMarginRatio:     math.LegacyMustNewDecFromStr("0.33"),
        MaintenanceMarginRatio: math.LegacyMustNewDecFromStr("0.095"),
        MinPriceTickSize:       chainMinPriceTickSize,
        MinQuantityTickSize:    chainMinQuantityTickSize,
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    response, err := chainClient.AsyncBroadcastMsg(msg)

    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(response, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
senderStringThe market launch requestor addressYes
tickerStringTicker for the perpetual marketYes
quote_denomStringQuote tocken denomYes
oracle_baseStringOracle base currencyYes
oracle_quoteStringOracle quote currencyYes
oracle_scale_factorIntegerScale factor for oracle pricesYes
oracle_typeOracleTypeThe oracle typeYes
maker_fee_rateDecimalDefines the trade fee rate for makers on the perpetual marketYes
taker_fee_rateDecimalDefines the trade fee rate for takers on the perpetual marketYes
initial_margin_ratioDecimalDefines the initial margin ratio for the perpetual marketYes
maintenance_margin_ratioDecimalDefines the maintenance margin ratio for the perpetual marketYes
min_price_tick_sizeDecimalDefines the minimum tick size of the order's priceYes
min_quantity_tick_sizeDecimalDefines the minimum tick size of the order's quantityYes
min_notionalDecimalDefines the minimum notional (in quote asset) required for orders in the marketYes


OracleType

CodeName
0Unspecified
1Band
2PriceFeed
3Coinbase
4Chainlink
5Razor
6Dia
7API3
8Uma
9Pyth
10BandIBC
11Provider

Response Parameters

Response Example:


ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgInstantExpiryFuturesMarketLaunch

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os
from decimal import Decimal

import dotenv

from pyinjective.async_client import AsyncClient
from pyinjective.core.broadcaster import MsgBroadcasterWithPk
from pyinjective.core.network import Network
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    await client.initialize_tokens_from_chain_denoms()
    composer = await client.composer()
    await client.sync_timeout_height()

    message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
        network=network,
        private_key=configured_private_key,
    )

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    # prepare tx msg
    message = composer.msg_instant_expiry_futures_market_launch(
        sender=address.to_acc_bech32(),
        ticker="INJ/USDC FUT",
        quote_denom="USDC",
        oracle_base="INJ",
        oracle_quote="USDC",
        oracle_scale_factor=6,
        oracle_type="Band",
        expiry=2000000000,
        maker_fee_rate=Decimal("-0.0001"),
        taker_fee_rate=Decimal("0.001"),
        initial_margin_ratio=Decimal("0.33"),
        maintenance_margin_ratio=Decimal("0.095"),
        min_price_tick_size=Decimal("0.001"),
        min_quantity_tick_size=Decimal("0.01"),
        min_notional=Decimal("1"),
    )

    # broadcast the transaction
    result = await message_broadcaster.broadcast([message])
    print("---Transaction Response---")
    print(result)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "cosmossdk.io/math"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    oracletypes "github.com/InjectiveLabs/sdk-go/chain/oracle/types"
    exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )
    if err != nil {
        panic(err)
    }

    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketsAssistant, err := chainclient.NewMarketsAssistantInitializedFromChain(ctx, exchangeClient)
    if err != nil {
        panic(err)
    }

    quoteToken := marketsAssistant.AllTokens()["USDC"]
    minPriceTickSize := math.LegacyMustNewDecFromStr("0.01")
    minQuantityTickSize := math.LegacyMustNewDecFromStr("0.001")

    chainMinPriceTickSize := minPriceTickSize.Mul(math.LegacyNewDecFromIntWithPrec(math.NewInt(1), int64(quoteToken.Decimals)))
    chainMinQuantityTickSize := minQuantityTickSize

    msg := &exchangetypes.MsgInstantExpiryFuturesMarketLaunch{
        Sender:                 senderAddress.String(),
        Ticker:                 "INJ/USDC FUT",
        QuoteDenom:             quoteToken.Denom,
        OracleBase:             "INJ",
        OracleQuote:            "USDC",
        OracleScaleFactor:      6,
        OracleType:             oracletypes.OracleType_Band,
        Expiry:                 2000000000,
        MakerFeeRate:           math.LegacyMustNewDecFromStr("-0.0001"),
        TakerFeeRate:           math.LegacyMustNewDecFromStr("0.001"),
        InitialMarginRatio:     math.LegacyMustNewDecFromStr("0.33"),
        MaintenanceMarginRatio: math.LegacyMustNewDecFromStr("0.095"),
        MinPriceTickSize:       chainMinPriceTickSize,
        MinQuantityTickSize:    chainMinQuantityTickSize,
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    response, err := chainClient.AsyncBroadcastMsg(msg)

    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(response, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
senderStringThe market launch requestor addressYes
tickerStringTicker for the expiry futures marketYes
quote_denomStringQuote tocken denomYes
oracle_baseStringOracle base currencyYes
oracle_quoteStringOracle quote currencyYes
oracle_typeOracleTypeThe oracle typeYes
oracle_scale_factorIntegerScale factor for oracle pricesYes
expiryIntegerExpiration time of the marketYes
maker_fee_rateDecimalDefines the trade fee rate for makers on the perpetual marketYes
taker_fee_rateDecimalDefines the trade fee rate for takers on the perpetual marketYes
initial_margin_ratioDecimalDefines the initial margin ratio for the perpetual marketYes
maintenance_margin_ratioDecimalDefines the maintenance margin ratio for the perpetual marketYes
min_price_tick_sizeDecimalDefines the minimum tick size of the order's priceYes
min_quantity_tick_sizeDecimalDefines the minimum tick size of the order's quantityYes
min_notionalDecimalDefines the minimum notional (in quote asset) required for orders in the marketYes


OracleType

CodeName
0Unspecified
1Band
2PriceFeed
3Coinbase
4Chainlink
5Razor
6Dia
7API3
8Uma
9Pyth
10BandIBC
11Provider

Response Parameters

Response Example:


ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgCreateDerivativeLimitOrder

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os
import uuid
from decimal import Decimal

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())
    subaccount_id = address.get_subaccount_id(index=0)

    # prepare trade info
    market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"

    # prepare tx msg
    msg = composer.msg_create_derivative_limit_order(
        sender=address.to_acc_bech32(),
        market_id=market_id,
        subaccount_id=subaccount_id,
        fee_recipient=fee_recipient,
        price=Decimal(50000),
        quantity=Decimal(0.1),
        margin=composer.calculate_margin(
            quantity=Decimal(0.1), price=Decimal(50000), leverage=Decimal(1), is_reduce_only=False
        ),
        order_type="SELL",
        cid=str(uuid.uuid4()),
    )

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    sim_res_msg = sim_res["result"]["msgResponses"]
    print("---Simulation Response---")
    print(sim_res_msg)

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print("---Transaction Response---")
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "fmt"
    "os"
    "time"

    exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
    "github.com/google/uuid"

    "github.com/InjectiveLabs/sdk-go/client/common"
    "github.com/shopspring/decimal"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketsAssistant, err := chainclient.NewMarketsAssistantInitializedFromChain(ctx, exchangeClient)
    if err != nil {
        panic(err)
    }

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    defaultSubaccountID := chainClient.DefaultSubaccount(senderAddress)

    marketId := "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"
    amount := decimal.NewFromFloat(0.001)
    price := decimal.RequireFromString("31000") //31,000
    leverage := decimal.RequireFromString("2.5")

    order := chainClient.CreateDerivativeOrder(
        defaultSubaccountID,
        &chainclient.DerivativeOrderData{
            OrderType:    exchangetypes.OrderType_BUY, //BUY SELL BUY_PO SELL_PO
            Quantity:     amount,
            Price:        price,
            Leverage:     leverage,
            FeeRecipient: senderAddress.String(),
            MarketId:     marketId,
            IsReduceOnly: true,
            Cid:          uuid.NewString(),
        },
        marketsAssistant,
    )

    msg := new(exchangetypes.MsgCreateDerivativeLimitOrder)
    msg.Sender = senderAddress.String()
    msg.Order = exchangetypes.DerivativeOrder(*order)

    simRes, err := chainClient.SimulateMsg(clientCtx, msg)

    if err != nil {
        panic(err)
    }

    msgCreateDerivativeLimitOrderResponse := exchangetypes.MsgCreateDerivativeLimitOrderResponse{}
    err = msgCreateDerivativeLimitOrderResponse.Unmarshal(simRes.Result.MsgResponses[0].Value)

    if err != nil {
        panic(err)
    }

    fmt.Println("simulated order hash", msgCreateDerivativeLimitOrderResponse.OrderHash)

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    err = chainClient.QueueBroadcastMsg(msg)

    if err != nil {
        fmt.Println(err)
    }

    time.Sleep(time.Second * 5)

    gasFee, err := chainClient.GetGasFee()

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("gas fee:", gasFee, "INJ")
}
ParameterTypeDescriptionRequired
senderStringThe message sender's addressYes
orderDerivativeOrderOrder's parametersYes


DerivativeOrder

ParameterTypeDescriptionRequired
market_idStringThe unique ID of the marketYes
order_infoOrderInfoOrder's informationYes
order_typeOrderTypeThe order typeYes
marginDecimalThe margin amount used by the orderYes
trigger_priceDecimalThe trigger price used by stop/take ordersNo


OrderInfo

ParameterTypeDescriptionRequired
subaccount_idStringSubaccount ID that created the orderYes
fee_recipientStringAddress that will receive fees for the orderNo
priceDecimalPrice of the orderYes
quantityDecimalQuantity of the orderYes
cidStringClient order ID. An optional identifier for the order set by the creatorNo


OrderType

CodeName
0UNSPECIFIED
1BUY
2SELL
3STOP_BUY
4STOP_SELL
5TAKE_BUY
6TAKE_SELL
7BUY_PO
8SELL_PO
9BUY_ATOMIC
10SELL_ATOMIC

Response Parameters

Response Example:

---Simulation Response---
[order_hash: "0x224e7312eb28955507142e9f761c5ba90165e05688583bffe9281dbe8f3e3083"
]
---Transaction Response---
txhash: "34138C7F4EB05EEBFC7AD81CE187BE13BF12348CB7973388007BE7505F257B14"
raw_log: "[]"

gas wanted: 124365
gas fee: 0.0000621825 INJ
simulated order hash 0x25233ede1fee09310d549241647edcf94cf5378749593b55c27148a80ce655c1
DEBU[0001] broadcastTx with nonce 3495                   fn=func1 src="client/chain/chain.go:598"
DEBU[0003] msg batch committed successfully at height 5213085  fn=func1 src="client/chain/chain.go:619" txHash=47644A4BD75A97BF4B0D436821F564976C60C272DD25F966DA88216C2229A32A
DEBU[0003] nonce incremented to 3496                     fn=func1 src="client/chain/chain.go:623"
DEBU[0003] gas wanted:  171439                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.0000857195 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgCreateDerivativeMarketOrder

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os
import uuid
from decimal import Decimal

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())
    subaccount_id = address.get_subaccount_id(index=0)

    # prepare trade info
    market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"

    # prepare tx msg
    msg = composer.msg_create_derivative_market_order(
        sender=address.to_acc_bech32(),
        market_id=market_id,
        subaccount_id=subaccount_id,
        fee_recipient=fee_recipient,
        price=Decimal(50000),
        quantity=Decimal(0.1),
        margin=composer.calculate_margin(
            quantity=Decimal(0.1), price=Decimal(50000), leverage=Decimal(1), is_reduce_only=False
        ),
        order_type="BUY",
        cid=str(uuid.uuid4()),
    )

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    sim_res_msg = sim_res["result"]["msgResponses"]
    print("---Simulation Response---")
    print(sim_res_msg)

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print("---Transaction Response---")
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "fmt"
    "os"
    "time"

    exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
    "github.com/google/uuid"

    "github.com/InjectiveLabs/sdk-go/client/common"
    "github.com/shopspring/decimal"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        fmt.Println(err)
        return
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketsAssistant, err := chainclient.NewMarketsAssistantInitializedFromChain(ctx, exchangeClient)
    if err != nil {
        panic(err)
    }

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    defaultSubaccountID := chainClient.DefaultSubaccount(senderAddress)

    marketId := "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"
    amount := decimal.NewFromFloat(0.01)
    price := decimal.RequireFromString("33000") //33,000
    leverage := decimal.RequireFromString("2.5")

    order := chainClient.CreateDerivativeOrder(
        defaultSubaccountID,
        &chainclient.DerivativeOrderData{
            OrderType:    exchangetypes.OrderType_SELL, //BUY SELL
            Quantity:     amount,
            Price:        price,
            Leverage:     leverage,
            FeeRecipient: senderAddress.String(),
            MarketId:     marketId,
            IsReduceOnly: true,
            Cid:          uuid.NewString(),
        },
        marketsAssistant,
    )

    msg := new(exchangetypes.MsgCreateDerivativeMarketOrder)
    msg.Sender = senderAddress.String()
    msg.Order = exchangetypes.DerivativeOrder(*order)

    simRes, err := chainClient.SimulateMsg(clientCtx, msg)

    if err != nil {
        panic(err)
    }

    msgCreateDerivativeMarketOrderResponse := exchangetypes.MsgCreateDerivativeMarketOrderResponse{}
    err = msgCreateDerivativeMarketOrderResponse.Unmarshal(simRes.Result.MsgResponses[0].Value)

    if err != nil {
        panic(err)
    }

    fmt.Println("simulated order hash", msgCreateDerivativeMarketOrderResponse.OrderHash)

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    err = chainClient.QueueBroadcastMsg(msg)

    if err != nil {
        fmt.Println(err)
        return
    }

    time.Sleep(time.Second * 5)

    gasFee, err := chainClient.GetGasFee()

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("gas fee:", gasFee, "INJ")
}
ParameterTypeDescriptionRequired
senderStringThe message sender's addressYes
orderDerivativeOrderOrder's parametersYes


DerivativeOrder

ParameterTypeDescriptionRequired
market_idStringThe unique ID of the marketYes
order_infoOrderInfoOrder's informationYes
order_typeOrderTypeThe order typeYes
marginDecimalThe margin amount used by the orderYes
trigger_priceDecimalThe trigger price used by stop/take ordersNo


OrderInfo

ParameterTypeDescriptionRequired
subaccount_idStringSubaccount ID that created the orderYes
fee_recipientStringAddress that will receive fees for the orderNo
priceDecimalPrice of the orderYes
quantityDecimalQuantity of the orderYes
cidStringClient order ID. An optional identifier for the order set by the creatorNo


OrderType

CodeName
0UNSPECIFIED
1BUY
2SELL
3STOP_BUY
4STOP_SELL
5TAKE_BUY
6TAKE_SELL
7BUY_PO
8SELL_PO
9BUY_ATOMIC
10SELL_ATOMIC

Response Parameters

Response Example:

---Simulation Response---
[order_hash: "0xcd0e33273d3a5688ef35cf3d857bd37df4a6b7a0698fdc46d77bbaeb79ffbbe4"
]
---Transaction Response---
txhash: "A4B30567DE6AB33F076858B6ED99BE757C084A2A217CEC98054DCEA5B8A0875D"
raw_log: "[]"

gas wanted: 110924
gas fee: 0.000055462 INJ
simulated order hash 0x2df7d24f919f833138b50f0b01ac200ec2e7bdc679fb144d152487fc23d6cfd0
DEBU[0001] broadcastTx with nonce 3496                   fn=func1 src="client/chain/chain.go:598"
DEBU[0003] msg batch committed successfully at height 5213175  fn=func1 src="client/chain/chain.go:619" txHash=613A5264D460E9AA34ADD89987994A15A9AE5BF62BA8FFD53E3AA490F5AE0A6E
DEBU[0003] nonce incremented to 3497                     fn=func1 src="client/chain/chain.go:623"
DEBU[0003] gas wanted:  139962                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.000069981 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgCancelDerivativeOrder

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())
    subaccount_id = address.get_subaccount_id(index=0)

    # prepare trade info
    market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    order_hash = "0x667ee6f37f6d06bf473f4e1434e92ac98ff43c785405e2a511a0843daeca2de9"

    # prepare tx msg
    msg = composer.msg_cancel_derivative_order(
        sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, order_hash=order_hash
    )

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "fmt"
    "os"
    "time"

    "github.com/InjectiveLabs/sdk-go/client"

    "github.com/InjectiveLabs/sdk-go/client/common"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    msg := &exchangetypes.MsgCancelDerivativeOrder{
        Sender:       senderAddress.String(),
        MarketId:     "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
        SubaccountId: "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
        OrderHash:    "0x8cf97e586c0d84cd7864ccc8916b886557120d84fc97a21ae193b67882835ec5",
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    err = chainClient.QueueBroadcastMsg(msg)

    if err != nil {
        fmt.Println(err)
    }

    time.Sleep(time.Second * 5)

    gasFee, err := chainClient.GetGasFee()

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("gas fee:", gasFee, "INJ")
}
ParameterTypeDescriptionRequired
senderStringThe message sender's addressYes
market_idStringThe unique ID of the order's marketYes
subaccount_idStringThe subaccount ID the order belongs toYes
order_hashStringThe order hash (either order_hash or cid have to be provided)No
order_maskOrderMaskThe order mask that specifies the order typeNo
cidStringThe client order ID provided by the creator (either order_hash or cid have to be provided)No


OrderMask

CodeName
0OrderMask_UNUSED
1OrderMask_ANY
2OrderMask_REGULAR
4OrderMask_CONDITIONAL
8OrderMask_BUY_OR_HIGHER
16OrderMask_SELL_OR_LOWER
32OrderMask_MARKET
64OrderMask_LIMIT

Response Parameters

Response Example:

---Simulation Response---
[success: true
success: false
]
---Transaction Response---
txhash: "862F4ABD2A75BD15B9BCEDB914653743F11CDB19583FB9018EB5A78B8D4ED264"
raw_log: "[]"

gas wanted: 118158
gas fee: 0.000059079 INJ
DEBU[0001] broadcastTx with nonce 3497                   fn=func1 src="client/chain/chain.go:598"
DEBU[0003] msg batch committed successfully at height 5213261  fn=func1 src="client/chain/chain.go:619" txHash=71016DBB5723031C8DBF6B05A498DE5390BC91FE226E23E3F70497B584E6EB3B
DEBU[0003] nonce incremented to 3498                     fn=func1 src="client/chain/chain.go:623"
DEBU[0003] gas wanted:  141373                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.0000706865 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgBatchUpdateOrders

MsgBatchUpdateOrders allows for the atomic cancellation and creation of spot and derivative limit orders, along with a new order cancellation mode. Upon execution, order cancellations (if any) occur first, followed by order creations (if any).

Users can cancel all limit orders in a given spot or derivative market for a given subaccountID by specifying the associated marketID in the SpotMarketIdsToCancelAll and DerivativeMarketIdsToCancelAll. Users can also cancel individual limit orders in SpotOrdersToCancel or DerivativeOrdersToCancel, but must ensure that marketIDs in these individual order cancellations are not already provided in the SpotMarketIdsToCancelAll or DerivativeMarketIdsToCancelAll.

Further note that if no marketIDs are provided in the SpotMarketIdsToCancelAll or DerivativeMarketIdsToCancelAll, then the SubaccountID in the Msg should be left empty.

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os
import uuid
from decimal import Decimal

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())
    subaccount_id = address.get_subaccount_id(index=0)

    # prepare trade info
    fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"

    derivative_market_id_create = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    spot_market_id_create = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"

    derivative_market_id_cancel = "0xd5e4b12b19ecf176e4e14b42944731c27677819d2ed93be4104ad7025529c7ff"
    derivative_market_id_cancel_2 = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    spot_market_id_cancel = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
    spot_market_id_cancel_2 = "0x7a57e705bb4e09c88aecfc295569481dbf2fe1d5efe364651fbe72385938e9b0"

    derivative_orders_to_cancel = [
        composer.order_data(
            market_id=derivative_market_id_cancel,
            subaccount_id=subaccount_id,
            order_hash="0x48690013c382d5dbaff9989db04629a16a5818d7524e027d517ccc89fd068103",
        ),
        composer.order_data(
            market_id=derivative_market_id_cancel_2,
            subaccount_id=subaccount_id,
            order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5",
        ),
    ]

    spot_orders_to_cancel = [
        composer.order_data(
            market_id=spot_market_id_cancel,
            subaccount_id=subaccount_id,
            cid="0e5c3ad5-2cc4-4a2a-bbe5-b12697739163",
        ),
        composer.order_data(
            market_id=spot_market_id_cancel_2,
            subaccount_id=subaccount_id,
            order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2",
        ),
    ]

    derivative_orders_to_create = [
        composer.derivative_order(
            market_id=derivative_market_id_create,
            subaccount_id=subaccount_id,
            fee_recipient=fee_recipient,
            price=Decimal(25000),
            quantity=Decimal(0.1),
            margin=composer.calculate_margin(
                quantity=Decimal(0.1), price=Decimal(25000), leverage=Decimal(1), is_reduce_only=False
            ),
            order_type="BUY",
            cid=str(uuid.uuid4()),
        ),
        composer.derivative_order(
            market_id=derivative_market_id_create,
            subaccount_id=subaccount_id,
            fee_recipient=fee_recipient,
            price=Decimal(50000),
            quantity=Decimal(0.01),
            margin=composer.calculate_margin(
                quantity=Decimal(0.01), price=Decimal(50000), leverage=Decimal(1), is_reduce_only=False
            ),
            order_type="SELL",
            cid=str(uuid.uuid4()),
        ),
    ]

    spot_orders_to_create = [
        composer.spot_order(
            market_id=spot_market_id_create,
            subaccount_id=subaccount_id,
            fee_recipient=fee_recipient,
            price=Decimal("3"),
            quantity=Decimal("55"),
            order_type="BUY",
            cid=str(uuid.uuid4()),
        ),
        composer.spot_order(
            market_id=spot_market_id_create,
            subaccount_id=subaccount_id,
            fee_recipient=fee_recipient,
            price=Decimal("300"),
            quantity=Decimal("55"),
            order_type="SELL",
            cid=str(uuid.uuid4()),
        ),
    ]

    # prepare tx msg
    msg = composer.msg_batch_update_orders(
        sender=address.to_acc_bech32(),
        derivative_orders_to_create=derivative_orders_to_create,
        spot_orders_to_create=spot_orders_to_create,
        derivative_orders_to_cancel=derivative_orders_to_cancel,
        spot_orders_to_cancel=spot_orders_to_cancel,
    )

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    sim_res_msg = sim_res["result"]["msgResponses"]
    print("---Simulation Response---")
    print(sim_res_msg)

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print("---Transaction Response---")
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "fmt"
    "os"
    "time"

    exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
    "github.com/google/uuid"

    "github.com/InjectiveLabs/sdk-go/client"
    "github.com/InjectiveLabs/sdk-go/client/common"
    "github.com/shopspring/decimal"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        fmt.Println(err)
        return
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketsAssistant, err := chainclient.NewMarketsAssistantInitializedFromChain(ctx, exchangeClient)
    if err != nil {
        panic(err)
    }

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        fmt.Println(err)
        return
    }

    defaultSubaccountID := chainClient.DefaultSubaccount(senderAddress)

    smarketId := "0x0511ddc4e6586f3bfe1acb2dd905f8b8a82c97e1edaef654b12ca7e6031ca0fa"
    samount := decimal.NewFromFloat(2)
    sprice := decimal.NewFromFloat(22.5)
    smarketIds := []string{"0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0"}

    spot_order := chainClient.CreateSpotOrder(
        defaultSubaccountID,
        &chainclient.SpotOrderData{
            OrderType:    exchangetypes.OrderType_BUY, //BUY SELL BUY_PO SELL_PO
            Quantity:     samount,
            Price:        sprice,
            FeeRecipient: senderAddress.String(),
            MarketId:     smarketId,
            Cid:          uuid.NewString(),
        },
        marketsAssistant,
    )

    dmarketId := "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"
    damount := decimal.NewFromFloat(0.01)
    dprice := decimal.RequireFromString("31000") //31,000
    dleverage := decimal.RequireFromString("2")
    dmarketIds := []string{"0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"}

    derivative_order := chainClient.CreateDerivativeOrder(
        defaultSubaccountID,
        &chainclient.DerivativeOrderData{
            OrderType:    exchangetypes.OrderType_BUY, //BUY SELL BUY_PO SELL_PO
            Quantity:     damount,
            Price:        dprice,
            Leverage:     dleverage,
            FeeRecipient: senderAddress.String(),
            MarketId:     dmarketId,
            IsReduceOnly: false,
            Cid:          uuid.NewString(),
        },
        marketsAssistant,
    )

    msg := new(exchangetypes.MsgBatchUpdateOrders)
    msg.Sender = senderAddress.String()
    msg.SubaccountId = defaultSubaccountID.Hex()
    msg.SpotOrdersToCreate = []*exchangetypes.SpotOrder{spot_order}
    msg.DerivativeOrdersToCreate = []*exchangetypes.DerivativeOrder{derivative_order}
    msg.SpotMarketIdsToCancelAll = smarketIds
    msg.DerivativeMarketIdsToCancelAll = dmarketIds

    simRes, err := chainClient.SimulateMsg(clientCtx, msg)

    if err != nil {
        fmt.Println(err)
        return
    }

    MsgBatchUpdateOrdersResponse := exchangetypes.MsgBatchUpdateOrdersResponse{}
    MsgBatchUpdateOrdersResponse.Unmarshal(simRes.Result.MsgResponses[0].Value)

    fmt.Println("simulated spot order hashes", MsgBatchUpdateOrdersResponse.SpotOrderHashes)

    fmt.Println("simulated derivative order hashes", MsgBatchUpdateOrdersResponse.DerivativeOrderHashes)

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    err = chainClient.QueueBroadcastMsg(msg)

    if err != nil {
        fmt.Println(err)
        return
    }

    time.Sleep(time.Second * 5)

    gasFee, err := chainClient.GetGasFee()

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("gas fee:", gasFee, "INJ")
}
ParameterTypeDescriptionRequired
senderStringThe message sender's addressYes
subaccount_idStringThe subaccount ID is only used for the spot_market_ids_to_cancel_all and derivative_market_ids_to_cancel_allNo
spot_market_ids_to_cancel_allString ArrayList of unique market IDs to cancel all subaccount_id ordersNo
derivative_market_ids_to_cancel_allString ArrayList of unique market IDs to cancel all subaccount_id ordersNo
spot_orders_to_cancelOrderData ArrayList of spot orders to be cancelledNo
derivative_orders_to_cancelOrderData ArrayList of derivative orders to be cancelledNo
spot_orders_to_createSpotOrder ArrayList of spot orders to be createdNo
derivative_orders_to_createDerivativeOrder ArrayList of derivative orders to be createdNo
binary_options_orders_to_cancelOrderData ArrayList of binary options orders to be cancelledNo
binary_options_market_ids_to_cancel_allString ArrayList of unique market IDs to cancel all subaccount_id ordersNo
binary_options_orders_to_createDerivativeOrder ArrayList of binary options orders to be createdNo


OrderData

ParameterTypeDescriptionRequired
market_idStringThe order's market IDYes
subaccount_idStringSubaccount ID that created the orderYes
order_hashStringThe order hash (either the order_hash or the cid should be provided)No
order_maskOrderMaskThe order mask that specifies the order typeNo
cidStringThe order's client order ID (either the order_hash or the cid should be provided)No


SpotOrder

ParameterTypeDescriptionRequired
market_idStringThe unique ID of the marketYes
order_infoOrderInfoOrder's informationYes
order_typeOrderTypeThe order typeYes
trigger_priceDecimalThe trigger price used by stop/take ordersNo


DerivativeOrder

ParameterTypeDescriptionRequired
market_idStringThe unique ID of the marketYes
order_infoOrderInfoOrder's informationYes
order_typeOrderTypeThe order typeYes
marginDecimalThe margin amount used by the orderYes
trigger_priceDecimalThe trigger price used by stop/take ordersNo


OrderMask

CodeName
0OrderMask_UNUSED
1OrderMask_ANY
2OrderMask_REGULAR
4OrderMask_CONDITIONAL
8OrderMask_BUY_OR_HIGHER
16OrderMask_SELL_OR_LOWER
32OrderMask_MARKET
64OrderMask_LIMIT


OrderInfo

ParameterTypeDescriptionRequired
subaccount_idStringSubaccount ID that created the orderYes
fee_recipientStringAddress that will receive fees for the orderNo
priceDecimalPrice of the orderYes
quantityDecimalQuantity of the orderYes
cidStringClient order ID. An optional identifier for the order set by the creatorNo


OrderType

CodeName
0UNSPECIFIED
1BUY
2SELL
3STOP_BUY
4STOP_SELL
5TAKE_BUY
6TAKE_SELL
7BUY_PO
8SELL_PO
9BUY_ATOMIC
10SELL_ATOMIC

Response Parameters

Response Example:

---Simulation Response---
[spot_cancel_success: false
spot_cancel_success: false
derivative_cancel_success: false
derivative_cancel_success: false
spot_order_hashes: "0x3f5b5de6ec72b250c58e0a83408dbc1990cee369999036e3469e19b80fa9002e"
spot_order_hashes: "0x7d8580354e120b038967a180f73bc3aba0f49db9b6d2cb5c4cec85e8cab3e218"
derivative_order_hashes: "0x920a4ea4144c46d1e1084ca5807e4f5608639ce00f97139d5b44e628d487e15e"
derivative_order_hashes: "0x11d75d0c2ce8a07f352523be2e3456212c623397d0fc1a2f688b97a15c04372c"
]
---Transaction Response---
txhash: "4E29226884DCA22E127471588F39E0BB03D314E1AA27ECD810D24C4078D52DED"
raw_log: "[]"

gas wanted: 271213
gas fee: 0.0001356065 INJ
simulated spot order hashes [0xd9f30c7e700202615c2775d630b9fb276572d883fa480b6394abbddcb79c8109]
simulated derivative order hashes [0xb2bea3b15c204699a9ee945ca49650001560518d1e54266adac580aa061fedd4]
DEBU[0001] broadcastTx with nonce 3507                   fn=func1 src="client/chain/chain.go:598"
DEBU[0003] msg batch committed successfully at height 5214679  fn=func1 src="client/chain/chain.go:619" txHash=CF53E0B31B9E28E0D6D8F763ECEC2D91E38481321EA24AC86F6A8774C658AF44
DEBU[0003] nonce incremented to 3508                     fn=func1 src="client/chain/chain.go:623"
DEBU[0003] gas wanted:  659092                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.000329546 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgLiquidatePosition

This message is sent to the chain when a particular position has reached the liquidation price, to liquidate that position.

To detect the liquidable positions please use the Indexer endpoint called LiquidablePositions

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os
import uuid
from decimal import Decimal

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())
    subaccount_id = address.get_subaccount_id(index=0)

    # prepare trade info
    market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
    cid = str(uuid.uuid4())

    order = composer.derivative_order(
        market_id=market_id,
        subaccount_id=subaccount_id,
        fee_recipient=fee_recipient,
        price=Decimal(39.01),  # This should be the liquidation price
        quantity=Decimal(0.147),
        margin=composer.calculate_margin(
            quantity=Decimal(0.147), price=Decimal(39.01), leverage=Decimal(1), is_reduce_only=False
        ),
        order_type="SELL",
        cid=cid,
    )

    # prepare tx msg
    msg = composer.msg_liquidate_position(
        sender=address.to_acc_bech32(),
        subaccount_id="0x156df4d5bc8e7dd9191433e54bd6a11eeb390921000000000000000000000000",
        market_id=market_id,
        order=order,
    )

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    sim_res_msg = sim_res["result"]["msgResponses"]
    print("---Simulation Response---")
    print(sim_res_msg)

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print("---Transaction Response---")
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))
    print(f"\n\ncid: {cid}")


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
    "github.com/google/uuid"

    "github.com/InjectiveLabs/sdk-go/client/common"
    "github.com/shopspring/decimal"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketsAssistant, err := chainclient.NewMarketsAssistantInitializedFromChain(ctx, exchangeClient)
    if err != nil {
        panic(err)
    }

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    defaultSubaccountID := chainClient.DefaultSubaccount(senderAddress)

    marketId := "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    amount := decimal.NewFromFloat(0.147)
    price := decimal.RequireFromString("39.01")
    leverage := decimal.RequireFromString("1")

    order := chainClient.CreateDerivativeOrder(
        defaultSubaccountID,
        &chainclient.DerivativeOrderData{
            OrderType:    exchangetypes.OrderType_SELL,
            Quantity:     amount,
            Price:        price,
            Leverage:     leverage,
            FeeRecipient: senderAddress.String(),
            MarketId:     marketId,
            Cid:          uuid.NewString(),
        },
        marketsAssistant,
    )

    msg := &exchangetypes.MsgLiquidatePosition{
        Sender:       senderAddress.String(),
        SubaccountId: "0x156df4d5bc8e7dd9191433e54bd6a11eeb390921000000000000000000000000",
        MarketId:     marketId,
        Order:        order,
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    response, err := chainClient.AsyncBroadcastMsg(msg)

    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(response, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
senderStringThe message sender's addressYes
subaccount_idStringThe subaccount ID to create the orderYes
market_idStringThe order's unique market IDYes
orderDerivativeOrderOrder's parametersYes


DerivativeOrder

ParameterTypeDescriptionRequired
market_idStringThe unique ID of the marketYes
order_infoOrderInfoOrder's informationYes
order_typeOrderTypeThe order typeYes
marginDecimalThe margin amount used by the orderYes
trigger_priceDecimalThe trigger price used by stop/take ordersNo


OrderInfo

ParameterTypeDescriptionRequired
subaccount_idStringSubaccount ID that created the orderYes
fee_recipientStringAddress that will receive fees for the orderNo
priceDecimalPrice of the orderYes
quantityDecimalQuantity of the orderYes
cidStringClient order ID. An optional identifier for the order set by the creatorNo


OrderType

CodeName
0UNSPECIFIED
1BUY
2SELL
3STOP_BUY
4STOP_SELL
5TAKE_BUY
6TAKE_SELL
7BUY_PO
8SELL_PO
9BUY_ATOMIC
10SELL_ATOMIC

<!-- MARKDOWN-AUTO-DOCS:END -->|

Response Parameters

Response Example:

ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgIncreasePositionMargin

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os
from decimal import Decimal

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())
    subaccount_id = address.get_subaccount_id(index=0)

    # prepare trade info
    market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"

    # prepare tx msg
    msg = composer.msg_increase_position_margin(
        sender=address.to_acc_bech32(),
        market_id=market_id,
        source_subaccount_id=subaccount_id,
        destination_subaccount_id=subaccount_id,
        amount=Decimal(2),
    )

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "fmt"
    "os"
    "time"

    "cosmossdk.io/math"

    "github.com/InjectiveLabs/sdk-go/client"

    "github.com/InjectiveLabs/sdk-go/client/common"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    msg := &exchangetypes.MsgIncreasePositionMargin{
        Sender:                  senderAddress.String(),
        MarketId:                "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
        SourceSubaccountId:      "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
        DestinationSubaccountId: "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
        Amount:                  math.LegacyMustNewDecFromStr("100000000"), //100 USDT
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    err = chainClient.QueueBroadcastMsg(msg)

    if err != nil {
        fmt.Println(err)
    }

    time.Sleep(time.Second * 5)

    gasFee, err := chainClient.GetGasFee()

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("gas fee:", gasFee, "INJ")
}
ParameterTypeDescriptionRequired
senderStringThe sender's addressYes
source_subaccount_idStringSubaccount ID from where the funds are deductedYes
destination_subaccount_idStringSubaccount ID the funds are deposited intoYes
market_idStringThe position's unique market IDYes
amountDecimalThe amount of margin to add to the positionYes

Response Parameters

Response Example:

txhash: "5AF048ADCE6AF753256F03AF2404A5B78C4C3E7E42A91F0B5C9994372E8AC2FE"
raw_log: "[]"

gas wanted: 106585
gas fee: 0.0000532925 INJ
DEBU[0001] broadcastTx with nonce 3503                   fn=func1 src="client/chain/chain.go:598"
DEBU[0002] msg batch committed successfully at height 5214406  fn=func1 src="client/chain/chain.go:619"
txHash=31FDA89C3122322C0559B5766CDF892FD0AA12469017CF8BF88B53441464ECC4
DEBU[0002] nonce incremented to 3504                     fn=func1 src="client/chain/chain.go:623"
DEBU[0002] gas wanted:  133614                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.000066807 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgDecreasePositionMargin

Message to reduce the margin assigned to a particular position

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os
from decimal import Decimal

import dotenv

from pyinjective.async_client import AsyncClient
from pyinjective.core.broadcaster import MsgBroadcasterWithPk
from pyinjective.core.network import Network
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
        network=network,
        private_key=configured_private_key,
    )

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())
    subaccount_id = address.get_subaccount_id(index=0)

    # prepare trade info
    market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"

    # prepare tx msg
    msg = composer.msg_decrease_position_margin(
        sender=address.to_acc_bech32(),
        market_id=market_id,
        source_subaccount_id=subaccount_id,
        destination_subaccount_id=subaccount_id,
        amount=Decimal(2),
    )

    # 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())
package main

import (
    "encoding/json"
    "fmt"
    "os"

    "cosmossdk.io/math"

    "github.com/InjectiveLabs/sdk-go/client"

    "github.com/InjectiveLabs/sdk-go/client/common"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    defaultSubaccountID := chainClient.DefaultSubaccount(senderAddress)

    msg := &exchangetypes.MsgDecreasePositionMargin{
        Sender:                  senderAddress.String(),
        MarketId:                "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
        SourceSubaccountId:      defaultSubaccountID.String(),
        DestinationSubaccountId: defaultSubaccountID.String(),
        Amount:                  math.LegacyMustNewDecFromStr("100000000"), //100 USDT
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    response, err := chainClient.AsyncBroadcastMsg(msg)

    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(response, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
senderStringThe sender's addressYes
source_subaccount_idStringSubaccount ID the position belongs toYes
destination_subaccount_idStringSubaccount ID the funds are deposited intoYes
market_idStringThe position's unique market IDYes
amountDecimalThe amount of margin to remove from the positionYes

Response Parameters

Response Example:

txhash: "5AF048ADCE6AF753256F03AF2404A5B78C4C3E7E42A91F0B5C9994372E8AC2FE"
raw_log: "[]"

gas wanted: 106585
gas fee: 0.0000532925 INJ
DEBU[0001] broadcastTx with nonce 3503                   fn=func1 src="client/chain/chain.go:598"
DEBU[0002] msg batch committed successfully at height 5214406  fn=func1 src="client/chain/chain.go:619"
txHash=31FDA89C3122322C0559B5766CDF892FD0AA12469017CF8BF88B53441464ECC4
DEBU[0002] nonce incremented to 3504                     fn=func1 src="client/chain/chain.go:623"
DEBU[0002] gas wanted:  133614                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.000066807 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgUpdateDerivativeMarket

Modifies certain market fields. It can only be sent by the market's admin.

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os
from decimal import Decimal

import dotenv

from pyinjective.async_client import AsyncClient
from pyinjective.core.broadcaster import MsgBroadcasterWithPk
from pyinjective.core.network import Network
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    await client.initialize_tokens_from_chain_denoms()
    composer = await client.composer()
    await client.sync_timeout_height()

    message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
        network=network,
        private_key=configured_private_key,
    )

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    # prepare tx msg
    message = composer.msg_update_derivative_market(
        admin=address.to_acc_bech32(),
        market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
        new_ticker="INJ/USDT PERP 2",
        new_min_price_tick_size=Decimal("1"),
        new_min_quantity_tick_size=Decimal("1"),
        new_min_notional=Decimal("2"),
        new_initial_margin_ratio=Decimal("0.40"),
        new_maintenance_margin_ratio=Decimal("0.085"),
    )

    # broadcast the transaction
    result = await message_broadcaster.broadcast([message])
    print("---Transaction Response---")
    print(result)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "cosmossdk.io/math"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )
    if err != nil {
        panic(err)
    }

    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketsAssistant, err := chainclient.NewMarketsAssistantInitializedFromChain(ctx, exchangeClient)
    if err != nil {
        panic(err)
    }

    quoteToken := marketsAssistant.AllTokens()["USDT"]
    minPriceTickSize := math.LegacyMustNewDecFromStr("0.1")
    minQuantityTickSize := math.LegacyMustNewDecFromStr("0.1")
    minNotional := math.LegacyMustNewDecFromStr("2")

    chainMinPriceTickSize := minPriceTickSize.Mul(math.LegacyNewDecFromIntWithPrec(math.NewInt(1), int64(quoteToken.Decimals)))
    chainMinQuantityTickSize := minQuantityTickSize
    chainMinNotional := minNotional.Mul(math.LegacyNewDecFromIntWithPrec(math.NewInt(1), int64(quoteToken.Decimals)))

    msg := &exchangetypes.MsgUpdateDerivativeMarket{
        Admin:                     senderAddress.String(),
        MarketId:                  "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
        NewTicker:                 "INJ/USDT PERP 2",
        NewMinPriceTickSize:       chainMinPriceTickSize,
        NewMinQuantityTickSize:    chainMinQuantityTickSize,
        NewMinNotional:            chainMinNotional,
        NewInitialMarginRatio:     math.LegacyMustNewDecFromStr("0.4"),
        NewMaintenanceMarginRatio: math.LegacyMustNewDecFromStr("0.085"),
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    response, err := chainClient.AsyncBroadcastMsg(msg)

    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(response, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
adminStringThe market's admin address (has to be the message broadcaster)Yes
market_idStringThe market's unique IDYes
new_tickerStringNew ticker for the perpetual marketNo
new_min_price_tick_sizeDecimalDefines the minimum tick size of the order's priceNo
new_min_quantity_tick_sizeDecimalDefines the minimum tick size of the order's quantityNo
new_min_notionalDecimalDefines the minimum notional (in quote asset) required for orders in the marketNo
new_initial_margin_ratioDecimalDefines the initial margin ratio for the perpetual marketNo
new_maintenance_margin_ratioDecimalDefines the maintenance margin ratio for the perpetual marketNo

Response Parameters

Response Example:

txhash: "5AF048ADCE6AF753256F03AF2404A5B78C4C3E7E42A91F0B5C9994372E8AC2FE"
raw_log: "[]"

gas wanted: 106585
gas fee: 0.0000532925 INJ
DEBU[0001] broadcastTx with nonce 3503                   fn=func1 src="client/chain/chain.go:598"
DEBU[0002] msg batch committed successfully at height 5214406  fn=func1 src="client/chain/chain.go:619"
txHash=31FDA89C3122322C0559B5766CDF892FD0AA12469017CF8BF88B53441464ECC4
DEBU[0002] nonce incremented to 3504                     fn=func1 src="client/chain/chain.go:623"
DEBU[0002] gas wanted:  133614                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.000066807 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

LocalOrderHashComputation

This function computes order hashes locally for SpotOrder and DerivativeOrder. For more information, see the note below.

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os
import uuid
from decimal import Decimal

import dotenv

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.orderhash import OrderHashManager
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())
    subaccount_id = address.get_subaccount_id(index=0)
    subaccount_id_2 = address.get_subaccount_id(index=1)

    order_hash_manager = OrderHashManager(address=address, network=network, subaccount_indexes=[0, 1, 2, 7])

    # prepare trade info
    spot_market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
    deriv_market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"

    spot_orders = [
        composer.spot_order(
            market_id=spot_market_id,
            subaccount_id=subaccount_id,
            fee_recipient=fee_recipient,
            price=Decimal("0.524"),
            quantity=Decimal("0.01"),
            order_type="BUY",
            cid=str(uuid.uuid4()),
        ),
        composer.spot_order(
            market_id=spot_market_id,
            subaccount_id=subaccount_id,
            fee_recipient=fee_recipient,
            price=Decimal("27.92"),
            quantity=Decimal("0.01"),
            order_type="SELL",
            cid=str(uuid.uuid4()),
        ),
    ]

    derivative_orders = [
        composer.derivative_order(
            market_id=deriv_market_id,
            subaccount_id=subaccount_id,
            fee_recipient=fee_recipient,
            price=Decimal(10500),
            quantity=Decimal(0.01),
            margin=composer.calculate_margin(
                quantity=Decimal(0.01), price=Decimal(10500), leverage=Decimal(2), is_reduce_only=False
            ),
            order_type="BUY",
            cid=str(uuid.uuid4()),
        ),
        composer.derivative_order(
            market_id=deriv_market_id,
            subaccount_id=subaccount_id,
            fee_recipient=fee_recipient,
            price=Decimal(65111),
            quantity=Decimal(0.01),
            margin=composer.calculate_margin(
                quantity=Decimal(0.01), price=Decimal(65111), leverage=Decimal(2), is_reduce_only=False
            ),
            order_type="SELL",
            cid=str(uuid.uuid4()),
        ),
    ]

    # prepare tx msg
    spot_msg = composer.msg_batch_create_spot_limit_orders(sender=address.to_acc_bech32(), orders=spot_orders)

    deriv_msg = composer.msg_batch_create_derivative_limit_orders(
        sender=address.to_acc_bech32(), orders=derivative_orders
    )

    # compute order hashes
    order_hashes = order_hash_manager.compute_order_hashes(
        spot_orders=spot_orders, derivative_orders=derivative_orders, subaccount_index=0
    )

    print("computed spot order hashes", order_hashes.spot)
    print("computed derivative order hashes", order_hashes.derivative)

    # build tx 1
    tx = (
        Transaction()
        .with_messages(spot_msg, deriv_msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    gas_price = GAS_PRICE
    base_gas = 85000
    gas_limit = base_gas + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))

    # compute order hashes
    order_hashes = order_hash_manager.compute_order_hashes(
        spot_orders=spot_orders, derivative_orders=derivative_orders, subaccount_index=0
    )

    print("computed spot order hashes", order_hashes.spot)
    print("computed derivative order hashes", order_hashes.derivative)

    # build tx 2
    tx = (
        Transaction()
        .with_messages(spot_msg, deriv_msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    gas_price = GAS_PRICE
    base_gas = 85000
    gas_limit = base_gas + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))

    spot_orders = [
        composer.spot_order(
            market_id=spot_market_id,
            subaccount_id=subaccount_id_2,
            fee_recipient=fee_recipient,
            price=Decimal("1.524"),
            quantity=Decimal("0.01"),
            order_type="BUY_PO",
            cid=str(uuid.uuid4()),
        ),
        composer.spot_order(
            market_id=spot_market_id,
            subaccount_id=subaccount_id_2,
            fee_recipient=fee_recipient,
            price=Decimal("27.92"),
            quantity=Decimal("0.01"),
            order_type="SELL_PO",
            cid=str(uuid.uuid4()),
        ),
    ]

    derivative_orders = [
        composer.derivative_order(
            market_id=deriv_market_id,
            subaccount_id=subaccount_id_2,
            fee_recipient=fee_recipient,
            price=Decimal(25111),
            quantity=Decimal(0.01),
            margin=composer.calculate_margin(
                quantity=Decimal(0.01), price=Decimal(25111), leverage=Decimal("1.5"), is_reduce_only=False
            ),
            order_type="BUY",
            cid=str(uuid.uuid4()),
        ),
        composer.derivative_order(
            market_id=deriv_market_id,
            subaccount_id=subaccount_id_2,
            fee_recipient=fee_recipient,
            price=Decimal(65111),
            quantity=Decimal(0.01),
            margin=composer.calculate_margin(
                quantity=Decimal(0.01), price=Decimal(25111), leverage=Decimal(2), is_reduce_only=False
            ),
            order_type="SELL",
            cid=str(uuid.uuid4()),
        ),
    ]

    # prepare tx msg
    spot_msg = composer.msg_batch_create_spot_limit_orders(sender=address.to_acc_bech32(), orders=spot_orders)

    deriv_msg = composer.msg_batch_create_derivative_limit_orders(
        sender=address.to_acc_bech32(), orders=derivative_orders
    )

    # compute order hashes
    order_hashes = order_hash_manager.compute_order_hashes(
        spot_orders=spot_orders, derivative_orders=derivative_orders, subaccount_index=1
    )

    print("computed spot order hashes", order_hashes.spot)
    print("computed derivative order hashes", order_hashes.derivative)

    # build tx 3
    tx = (
        Transaction()
        .with_messages(spot_msg, deriv_msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    gas_price = GAS_PRICE
    base_gas = 85000
    gas_limit = base_gas + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "fmt"
    "os"
    "time"

    exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
    "github.com/google/uuid"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
    "github.com/shopspring/decimal"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )
    if err != nil {
        panic(err)
    }

    // initialize grpc client
    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketsAssistant, err := chainclient.NewMarketsAssistantInitializedFromChain(ctx, exchangeClient)
    if err != nil {
        panic(err)
    }

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    // prepare tx msg
    defaultSubaccountID := chainClient.Subaccount(senderAddress, 1)

    spotOrder := chainClient.CreateSpotOrder(
        defaultSubaccountID,
        &chainclient.SpotOrderData{
            OrderType:    exchangetypes.OrderType_BUY,
            Quantity:     decimal.NewFromFloat(2),
            Price:        decimal.NewFromFloat(22.55),
            FeeRecipient: senderAddress.String(),
            MarketId:     "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
            Cid:          uuid.NewString(),
        },
        marketsAssistant,
    )

    derivativeOrder := chainClient.CreateDerivativeOrder(
        defaultSubaccountID,
        &chainclient.DerivativeOrderData{
            OrderType:    exchangetypes.OrderType_BUY,
            Quantity:     decimal.NewFromFloat(2),
            Price:        decimal.RequireFromString("31"),
            Leverage:     decimal.RequireFromString("2.5"),
            FeeRecipient: senderAddress.String(),
            MarketId:     "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
            Cid:          uuid.NewString(),
        },
        marketsAssistant,
    )

    msg := new(exchangetypes.MsgBatchCreateSpotLimitOrders)
    msg.Sender = senderAddress.String()
    msg.Orders = []exchangetypes.SpotOrder{*spotOrder}

    msg1 := new(exchangetypes.MsgBatchCreateDerivativeLimitOrders)
    msg1.Sender = senderAddress.String()
    msg1.Orders = []exchangetypes.DerivativeOrder{*derivativeOrder, *derivativeOrder}

    // compute local order hashes
    orderHashes, err := chainClient.ComputeOrderHashes(msg.Orders, msg1.Orders, defaultSubaccountID)

    if err != nil {
        fmt.Println(err)
    }

    fmt.Println("computed spot order hashes: ", orderHashes.Spot)
    fmt.Println("computed derivative order hashes: ", orderHashes.Derivative)

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    err = chainClient.QueueBroadcastMsg(msg, msg1)

    if err != nil {
        fmt.Println(err)
    }

    time.Sleep(time.Second * 5)

    gasFee, err := chainClient.GetGasFee()

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("gas fee:", gasFee, "INJ")
}

Response Parameters

Response Example:

computed spot order hashes ['0xa2d59cca00bade680a552f02deeb43464df21c73649191d64c6436313b311cba', '0xab78219e6c494373262a310d73660198c7a4c91196c0f6bb8808c81d8fb54a11']
computed derivative order hashes ['0x38d432c011f4a62c6b109615718b26332e7400a86f5e6f44e74a8833b7eed992', '0x66a921d83e6931513df9076c91a920e5e943837e2b836ad370b5cf53a1ed742c']
txhash: "604757CD9024FFF2DDCFEED6FC070E435AC09A829DB2E81AD4AD65B33E987A8B"
raw_log: "[]"

gas wanted: 196604
gas fee: 0.000098302 INJ
computed spot order hashes:  [0x0103ca50d0d033e6b8528acf28a3beb3fd8bac20949fc1ba60a2da06c53ad94f]
computed derivative order hashes:  [0x15334a7a0f1c2f98b9369f79b9a62a1f357d3e63b46a8895a4cec0ca375ddbbb 0xc26c8f74f56eade275e518f73597dd8954041bfbae3951ed4d7efeb0d060edbd]
DEBU[0001] broadcastTx with nonce 3488                   fn=func1 src="client/chain/chain.go:598"
DEBU[0003] msg batch committed successfully at height 5212331  fn=func1 src="client/chain/chain.go:619" txHash=19D8D81BB1DF59889E00EAA600A01079BA719F00A4A43CCC1B56580A1BBD6455
DEBU[0003] nonce incremented to 3489                     fn=func1 src="client/chain/chain.go:623"
DEBU[0003] gas wanted:  271044                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.000135522 INJ

Note on LocalOrderHashComputation for HFTs/API Traders

LocalOrderHashComputation returns a locally computed transaction hash for spot and derivative orders, which is useful when the user needs the transaction hash faster than orders can be streamed through StreamOrdersHistory (there is extra latency since the order must be included by a block, and the block must be indexed by the Indexer). While the hash can also be obtained through transaction simulation, the process adds a layer of latency and can only be used for one transaction per block (simulation relies on a nonce based on the state machine which does not change until the transaction is included in a block).

On Injective, subaccount nonces are used to calculate order hashes. The subaccount nonce is incremented with each order so that order hashes remain unique.

For strategies employing high frequency trading, order hashes should be calculated locally before transactions are broadcasted. This is possible as long as the subaccount nonce is cached/tracked locally instead of queried from the chain. Similarly, the account sequence (like nonce on Ethereum) should be cached if more than one transaction per block is desired. The LocalOrderHashComputation implementation can be found here. Refer to the above API example for usage.

There are two caveats to be mindful of when taking this approach:

1. Gas must be manually calculated instead of fetched from simulation

  class GasLimitConstant:
      base = 65e3
      extra = 20e3
      derivative_order = 45e3
      derivative_cancel = 55e3

2. In the event a transaction fails, the account sequence and subaccount nonce must both be refreshed

  res = await self.client.broadcast_tx_sync_mode(tx_raw_bytes)
  if res.code == 32:
      await client.fetch_account(address.to_acc_bech32())

- Chain Exchange for Spot

Includes all messages related to spot markets.

SpotMarkets

Retrieves a list of spot markets

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    spot_markets = await client.fetch_chain_spot_markets(
        status="Active",
        market_ids=["0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"],
    )
    print(spot_markets)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    status := "Active"
    marketIds := []string{"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"}

    res, err := chainClient.FetchChainSpotMarkets(ctx, status, marketIds)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
statusStringMarket statusNo
market_idsString ArrayList of market IDsNo

Response Parameters

Response Example:

{
   "markets":[
      {
         "ticker":"INJ/USDT",
         "baseDenom":"inj",
         "quoteDenom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
         "makerFeeRate":"-100000000000000",
         "takerFeeRate":"1000000000000000",
         "relayerFeeShareRate":"400000000000000000",
         "marketId":"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
         "status":"Active",
         "minPriceTickSize":"1000",
         "minQuantityTickSize":"1000000000000000000000000000000000"
      }
   ]
}
ParameterTypeDescription
marketsSpotMarket ArrayList of markets


SpotMarket

ParameterTypeDescription
tickerStringName of the pair in format AAA/BBB, where AAA is base asset, BBB is quote asset
base_denomStringCoin denom used for the base asset
quote_denomStringCoin denom used for the quote asset
maker_fee_rateDecimalFee percentage makers pay when trading
taker_fee_rateDecimalFee percentage takers pay when trading
relayer_fee_share_rateDecimalPercentage of the transaction fee shared with the relayer in a derivative market
market_idStringThe market ID
statusMarketStatusStatus of the market
min_price_tick_sizeDecimalMinimum tick size that the price required for orders in the market
min_quantity_tick_sizeDecimalMinimum tick size of the quantity required for orders in the market
min_notionalDecimalMinimum notional (in quote asset) required for orders in the market
adminStringCurrent market admin's address
admin_permissionsIntegerLevel of admin permissions (the permission number is a result of adding up all individual permissions numbers)


MarketStatus

CodeName
0Unspecified
1Active
2Paused
3Demolished
4Expired


AdminPermission

CodeName
1Ticker Permission
2Min Price Tick Size Permission
4Min Quantity Tick Size Permission
8Min Notional Permission
16Initial Margin Ratio Permission
32Maintenance Margin Ratio Permission
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    marketId := "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"

    res, err := chainClient.FetchChainSpotMarket(ctx, marketId)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
market_idStringThe market IDYes

Response Parameters

Response Example:

{
   "market":{
      "ticker":"INJ/USDT",
      "baseDenom":"inj",
      "quoteDenom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
      "makerFeeRate":"-100000000000000",
      "takerFeeRate":"1000000000000000",
      "relayerFeeShareRate":"400000000000000000",
      "marketId":"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
      "status":"Active",
      "minPriceTickSize":"1000",
      "minQuantityTickSize":"1000000000000000000000000000000000"
   }
}
ParameterTypeDescription
marketSpotMarketMarket information


SpotMarket

ParameterTypeDescription
tickerStringName of the pair in format AAA/BBB, where AAA is base asset, BBB is quote asset
base_denomStringCoin denom used for the base asset
quote_denomStringCoin denom used for the quote asset
maker_fee_rateDecimalFee percentage makers pay when trading
taker_fee_rateDecimalFee percentage takers pay when trading
relayer_fee_share_rateDecimalPercentage of the transaction fee shared with the relayer in a derivative market
market_idStringThe market ID
statusMarketStatusStatus of the market
min_price_tick_sizeDecimalMinimum tick size that the price required for orders in the market
min_quantity_tick_sizeDecimalMinimum tick size of the quantity required for orders in the market
min_notionalDecimalMinimum notional (in quote asset) required for orders in the market
adminStringCurrent market admin's address
admin_permissionsIntegerLevel of admin permissions (the permission number is a result of adding up all individual permissions numbers)


MarketStatus

CodeName
0Unspecified
1Active
2Paused
3Demolished
4Expired


AdminPermission

CodeName
1Ticker Permission
2Min Price Tick Size Permission
4Min Quantity Tick Size Permission
8Min Notional Permission
16Initial Margin Ratio Permission
32Maintenance Margin Ratio Permission
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    status := "Active"
    marketIds := []string{"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"}
    withMidPriceAndTob := true

    res, err := chainClient.FetchChainFullSpotMarkets(ctx, status, marketIds, withMidPriceAndTob)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
statusStringStatus of the marketNo
market_idsString ArrayList of market IDsNo
with_mid_price_and_tobBooleanFlag to activate/deactivate the inclusion of the markets mid price and top of the book buy and sell ordersNo

Response Parameters

Response Example:

{
   "markets":[
      {
         "market":{
            "ticker":"INJ/USDT",
            "baseDenom":"inj",
            "quoteDenom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
            "makerFeeRate":"-100000000000000",
            "takerFeeRate":"1000000000000000",
            "relayerFeeShareRate":"400000000000000000",
            "marketId":"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
            "status":"Active",
            "minPriceTickSize":"1000",
            "minQuantityTickSize":"1000000000000000000000000000000000"
         },
         "midPriceAndTob":{
            "midPrice":"42494500",
            "bestBuyPrice":"42490000",
            "bestSellPrice":"42499000"
         }
      }
   ]
}
ParameterTypeDescription
marketsFullSpotMarket ArrayMarkets information


FullSpotMarket

ParameterTypeDescription
marketSpotMarketMarket basic information
mid_price_and_tobMidPriceAndTOBThe mid price for this market and the best ask and bid orders


SpotMarket

ParameterTypeDescription
tickerStringName of the pair in format AAA/BBB, where AAA is base asset, BBB is quote asset
base_denomStringCoin denom used for the base asset
quote_denomStringCoin denom used for the quote asset
maker_fee_rateDecimalFee percentage makers pay when trading
taker_fee_rateDecimalFee percentage takers pay when trading
relayer_fee_share_rateDecimalPercentage of the transaction fee shared with the relayer in a derivative market
market_idStringThe market ID
statusMarketStatusStatus of the market
min_price_tick_sizeDecimalMinimum tick size that the price required for orders in the market
min_quantity_tick_sizeDecimalMinimum tick size of the quantity required for orders in the market
min_notionalDecimalMinimum notional (in quote asset) required for orders in the market
adminStringCurrent market admin's address
admin_permissionsIntegerLevel of admin permissions (the permission number is a result of adding up all individual permissions numbers)


MarketStatus

CodeName
0Unspecified
1Active
2Paused
3Demolished
4Expired


MidPriceAndTOB

ParameterTypeDescription
mid_priceDecimalMarket's mid price
best_buy_priceDecimalMarket's best buy price
best_sell_priceDecimalMarket's best sell price


AdminPermission

CodeName
1Ticker Permission
2Min Price Tick Size Permission
4Min Quantity Tick Size Permission
8Min Notional Permission
16Initial Margin Ratio Permission
32Maintenance Margin Ratio Permission
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    marketId := "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
    withMidPriceAndTob := true

    res, err := chainClient.FetchChainFullSpotMarket(ctx, marketId, withMidPriceAndTob)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
market_idStringMarket ID to request forYes
with_mid_price_and_tobBooleanFlag to activate/deactivate the inclusion of the markets mid price and top of the book buy and sell ordersNo

Response Parameters

Response Example:

{
   "market":{
      "market":{
         "ticker":"INJ/USDT",
         "baseDenom":"inj",
         "quoteDenom":"peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5",
         "makerFeeRate":"-100000000000000",
         "takerFeeRate":"1000000000000000",
         "relayerFeeShareRate":"400000000000000000",
         "marketId":"0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
         "status":"Active",
         "minPriceTickSize":"1000",
         "minQuantityTickSize":"1000000000000000000000000000000000"
      },
      "midPriceAndTob":{
         "midPrice":"42473500",
         "bestBuyPrice":"42336000",
         "bestSellPrice":"42611000"
      }
   }
}
ParameterTypeDescription
marketFullSpotMarketMarkets information


FullSpotMarket

ParameterTypeDescription
marketSpotMarketMarket basic information
mid_price_and_tobMidPriceAndTOBThe mid price for this market and the best ask and bid orders


SpotMarket

ParameterTypeDescription
tickerStringName of the pair in format AAA/BBB, where AAA is base asset, BBB is quote asset
base_denomStringCoin denom used for the base asset
quote_denomStringCoin denom used for the quote asset
maker_fee_rateDecimalFee percentage makers pay when trading
taker_fee_rateDecimalFee percentage takers pay when trading
relayer_fee_share_rateDecimalPercentage of the transaction fee shared with the relayer in a derivative market
market_idStringThe market ID
statusMarketStatusStatus of the market
min_price_tick_sizeDecimalMinimum tick size that the price required for orders in the market
min_quantity_tick_sizeDecimalMinimum tick size of the quantity required for orders in the market
min_notionalDecimalMinimum notional (in quote asset) required for orders in the market
adminStringCurrent market admin's address
admin_permissionsIntegerLevel of admin permissions (the permission number is a result of adding up all individual permissions numbers)


MarketStatus

CodeName
0Unspecified
1Active
2Paused
3Demolished
4Expired


MidPriceAndTOB

ParameterTypeDescription
mid_priceDecimalMarket's mid price
best_buy_priceDecimalMarket's best buy price
best_sell_priceDecimalMarket's best sell price


AdminPermission

CodeName
1Ticker Permission
2Min Price Tick Size Permission
4Min Quantity Tick Size Permission
8Min Notional Permission
16Initial Margin Ratio Permission
32Maintenance Margin Ratio Permission
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "cosmossdk.io/math"

    "os"

    "github.com/InjectiveLabs/sdk-go/chain/exchange/types"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    marketId := "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
    limit := uint64(2)
    orderSide := types.OrderSide_Buy
    limitCumulativeNotional := math.LegacyDec{}
    limitCumulativeQuantity := math.LegacyDec{}

    res, err := chainClient.FetchChainSpotOrderbook(ctx, marketId, limit, orderSide, limitCumulativeNotional, limitCumulativeQuantity)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
market_idStringMarket ID to request forYes
limitIntegerMax number of order book entries to return per sideNo
order_sideOrderSideSpecifies the side of the order book to return entries fromNo
limit_cumulative_notionalDecimalLimit the number of entries to return per side based on the cumulative notionalNo
limit_cumulative_quantityDecimalLimit the number of entries to return per side based on the cumulative quantityNo


OrderSide

CodeName
0Side_Unspecified
1Buy
2Sell

Response Parameters

Response Example:

{
   "buysPriceLevel":[
      {
         "p":"43260000",
         "q":"142000000000000000000000000000000000000"
      },
      {
         "p":"43208000",
         "q":"25554192000000000000000000000000000000000"
      }
   ],
   "sellsPriceLevel":[

   ]
}
ParameterTypeDescription
buys_price_levelLevel ArrayBid side entries
sells_price_levelLevel ArrayAsk side entries


Level

ParameterTypeDescription
pDecimalPrice
qDecimalQuantity

TraderSpotOrders

Retrieves a trader's spot orders

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective import PrivateKey
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    subaccount_id = address.get_subaccount_id(index=0)

    orders = await client.fetch_chain_trader_spot_orders(
        market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
        subaccount_id=subaccount_id,
    )
    print(orders)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    marketId := "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
    subaccountId := chainClient.Subaccount(senderAddress, 0)

    res, err := chainClient.FetchChainTraderSpotOrders(ctx, marketId, subaccountId.Hex())
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
market_idStringMarket ID to request forYes
subaccount_idStringTrader's subaccount IDYes

Response Parameters

Response Example:

{
   "orders":[
      {
         "price":"7523000",
         "quantity":"10000000000000000000000000000000000",
         "fillable":"10000000000000000000000000000000000",
         "isBuy":true,
         "orderHash":"0xee405938e1924d20cce9d91e47476af0b40774843906b653ba4c439654fb9a8b"
      },
      {
         "price":"3000000",
         "quantity":"55000000000000000000000000000000000000",
         "fillable":"55000000000000000000000000000000000000",
         "isBuy":true,
         "orderHash":"0x57a01cd26f1e2080860af3264e865d7c9c034a701e30946d01c1dc7a303cf2c1"
      },
      {
         "price":"3000000",
         "quantity":"55000000000000000000000000000000000000",
         "fillable":"55000000000000000000000000000000000000",
         "isBuy":true,
         "orderHash":"0x079d65de81f03229d0fac69fb8ee0bfe0f043783099ad4cb28f1b30115736a02"
      },
      {
         "price":"300000000",
         "quantity":"55000000000000000000000000000000000000",
         "fillable":"22458000000000000000000000000000000000",
         "orderHash":"0x6e53d070e13be855d230de48849017b2390c2294afc3681bd3624370d153a7cc",
         "isBuy":false
      }
   ]
}
ParameterTypeDescription
ordersTrimmedSpotLimitOrder ArrayOrders info


TrimmedSpotLimitOrder

ParameterTypeDescription
priceDecimalOrder price
quantityDecimalOrder quantity
fillableDecimalThe remaining fillable amount of the order
is_buyBooleanTrue if the order is a buy order
order_hashStringThe order hash
cidStringThe client order ID provided by the creator

AccountAddressSpotOrders

Retrieves all account address spot orders

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective import PrivateKey
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    orders = await client.fetch_chain_account_address_spot_orders(
        market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
        account_address=address.to_acc_bech32(),
    )
    print(orders)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    marketId := "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"

    res, err := chainClient.FetchChainAccountAddressSpotOrders(ctx, marketId, senderAddress.String())
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
market_idStringMarket ID to request forYes
account_addressStringTrader's account addressYes

Response Parameters

Response Example:

{
   "orders":[
      {
         "price":"3000000",
         "quantity":"55000000000000000000000000000000000000",
         "fillable":"55000000000000000000000000000000000000",
         "isBuy":true,
         "orderHash":"0xda7a606d542962da77f13b0f8373c24ce4511e421de8e4602a3e5f2b85b7623c"
      },
      {
         "price":"3000000",
         "quantity":"55000000000000000000000000000000000000",
         "fillable":"55000000000000000000000000000000000000",
         "isBuy":true,
         "orderHash":"0x9c7c77da10b73d63c72875a175c4a7cb7313dbbeb9a3380bc1bf930cce883b1b"
      },
      {
         "price":"7523000",
         "quantity":"10000000000000000000000000000000000",
         "fillable":"10000000000000000000000000000000000",
         "isBuy":true,
         "orderHash":"0xee405938e1924d20cce9d91e47476af0b40774843906b653ba4c439654fb9a8b"
      },
      {
         "price":"3000000",
         "quantity":"55000000000000000000000000000000000000",
         "fillable":"55000000000000000000000000000000000000",
         "isBuy":true,
         "orderHash":"0x57a01cd26f1e2080860af3264e865d7c9c034a701e30946d01c1dc7a303cf2c1"
      },
      {
         "price":"3000000",
         "quantity":"55000000000000000000000000000000000000",
         "fillable":"55000000000000000000000000000000000000",
         "isBuy":true,
         "orderHash":"0x079d65de81f03229d0fac69fb8ee0bfe0f043783099ad4cb28f1b30115736a02"
      },
      {
         "price":"300000000",
         "quantity":"55000000000000000000000000000000000000",
         "fillable":"22458000000000000000000000000000000000",
         "orderHash":"0x6e53d070e13be855d230de48849017b2390c2294afc3681bd3624370d153a7cc",
         "isBuy":false
      },
      {
         "price":"300000000",
         "quantity":"55000000000000000000000000000000000000",
         "fillable":"55000000000000000000000000000000000000",
         "orderHash":"0xcb38413ecf5517faac19a4753726813b68374525d70e8ca3058bb20504a98e10",
         "isBuy":false
      }
   ]
}
ParameterTypeDescription
ordersTrimmedSpotLimitOrder ArrayOrders info


TrimmedSpotLimitOrder

ParameterTypeDescription
priceDecimalOrder price
quantityDecimalOrder quantity
fillableDecimalThe remaining fillable amount of the order
is_buyBooleanTrue if the order is a buy order
order_hashStringThe order hash
cidStringThe client order ID provided by the creator

SpotOrdersByHashes

Retrieves spot orders corresponding to specified order hashes for a given subaccount ID and market ID

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective import PrivateKey
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    subaccount_id = address.get_subaccount_id(index=0)

    orders = await client.fetch_chain_spot_orders_by_hashes(
        market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
        subaccount_id=subaccount_id,
        order_hashes=["0x57a01cd26f1e2080860af3264e865d7c9c034a701e30946d01c1dc7a303cf2c1"],
    )
    print(orders)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    marketId := "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
    subaccountId := chainClient.Subaccount(senderAddress, 0)
    orderHashes := []string{"0x57a01cd26f1e2080860af3264e865d7c9c034a701e30946d01c1dc7a303cf2c1"}

    res, err := chainClient.FetchChainSpotOrdersByHashes(ctx, marketId, subaccountId.Hex(), orderHashes)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
market_idStringMarket ID to request forYes
subaccount_idStringTrader's subaccount IDYes
order_hashesString ArrayList of order hashes to retrieve information forYes

Response Parameters

Response Example:

{
   "orders":[
      {
         "price":"3000000",
         "quantity":"55000000000000000000000000000000000000",
         "fillable":"55000000000000000000000000000000000000",
         "isBuy":true,
         "orderHash":"0x57a01cd26f1e2080860af3264e865d7c9c034a701e30946d01c1dc7a303cf2c1"
      }
   ]
}
ParameterTypeDescription
ordersTrimmedSpotLimitOrder ArrayOrders info


TrimmedSpotLimitOrder

ParameterTypeDescription
priceDecimalOrder price
quantityDecimalOrder quantity
fillableDecimalThe remaining fillable amount of the order
is_buyBooleanTrue if the order is a buy order
order_hashStringThe order hash
cidStringThe client order ID provided by the creator

TraderSpotTransientOrders

Retrieves a trader's transient spot orders

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective import PrivateKey
from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    subaccount_id = address.get_subaccount_id(index=0)

    orders = await client.fetch_chain_trader_spot_transient_orders(
        market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
        subaccount_id=subaccount_id,
    )
    print(orders)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    marketId := "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
    subaccountId := chainClient.Subaccount(senderAddress, 0)

    res, err := chainClient.FetchChainTraderSpotTransientOrders(ctx, marketId, subaccountId.Hex())
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
market_idStringMarket ID to request forYes
subaccount_idStringTrader's subaccount IDYes

Response Parameters

Response Example:

{
   "orders":[

   ]
}
ParameterTypeDescription
ordersTrimmedSpotLimitOrder ArrayOrders info


TrimmedSpotLimitOrder

ParameterTypeDescription
priceDecimalOrder price
quantityDecimalOrder quantity
fillableDecimalThe remaining fillable amount of the order
is_buyBooleanTrue if the order is a buy order
order_hashStringThe order hash
cidStringThe client order ID provided by the creator

SpotMidPriceAndTOB

Retrieves a spot market's mid-price

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    prices = await client.fetch_spot_mid_price_and_tob(
        market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
    )
    print(prices)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    marketId := "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"

    res, err := chainClient.FetchSpotMidPriceAndTOB(ctx, marketId)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
market_idStringMarket ID to request forYes

Response Parameters

Response Example:

{
   "midPrice":"44723500",
   "bestBuyPrice":"44538000",
   "bestSellPrice":"44909000"
}
ParameterTypeDescription
mid_priceDecimalMarket's mid price
best_buy_priceDecimalMarket's bet bid price
best_sell_priceDecimalMarket's bet ask price

MsgInstantSpotMarketLaunch

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os
from decimal import Decimal

import dotenv

from pyinjective.async_client import AsyncClient
from pyinjective.core.broadcaster import MsgBroadcasterWithPk
from pyinjective.core.network import Network
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    await client.initialize_tokens_from_chain_denoms()
    composer = await client.composer()
    await client.sync_timeout_height()

    message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
        network=network,
        private_key=configured_private_key,
    )

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    # prepare tx msg
    message = composer.msg_instant_spot_market_launch(
        sender=address.to_acc_bech32(),
        ticker="INJ/USDC",
        base_denom="INJ",
        quote_denom="USDC",
        min_price_tick_size=Decimal("0.001"),
        min_quantity_tick_size=Decimal("0.01"),
        min_notional=Decimal("1"),
    )

    # broadcast the transaction
    result = await message_broadcaster.broadcast([message])
    print("---Transaction Response---")
    print(result)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "cosmossdk.io/math"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )
    if err != nil {
        panic(err)
    }

    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketsAssistant, err := chainclient.NewMarketsAssistantInitializedFromChain(ctx, exchangeClient)
    if err != nil {
        panic(err)
    }

    baseToken := marketsAssistant.AllTokens()["INJ"]
    quoteToken := marketsAssistant.AllTokens()["USDC"]
    minPriceTickSize := math.LegacyMustNewDecFromStr("0.01")
    minQuantityTickSize := math.LegacyMustNewDecFromStr("0.001")
    minNotional := math.LegacyMustNewDecFromStr("1")

    chainMinPriceTickSize := minPriceTickSize.Mul(math.LegacyNewDecFromIntWithPrec(math.NewInt(1), int64(quoteToken.Decimals)))
    chainMinPriceTickSize = chainMinPriceTickSize.Quo(math.LegacyNewDecFromIntWithPrec(math.NewInt(1), int64(baseToken.Decimals)))

    chainMinQuantityTickSize := minQuantityTickSize.Mul(math.LegacyNewDecFromIntWithPrec(math.NewInt(1), int64(baseToken.Decimals)))
    chainMinNotional := minNotional.Mul(math.LegacyNewDecFromIntWithPrec(math.NewInt(1), int64(quoteToken.Decimals)))

    msg := &exchangetypes.MsgInstantSpotMarketLaunch{
        Sender:              senderAddress.String(),
        Ticker:              "INJ/USDC",
        BaseDenom:           baseToken.Denom,
        QuoteDenom:          quoteToken.Denom,
        MinPriceTickSize:    chainMinPriceTickSize,
        MinQuantityTickSize: chainMinQuantityTickSize,
        MinNotional:         chainMinNotional,
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    response, err := chainClient.AsyncBroadcastMsg(msg)

    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(response, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
senderStringThe market launch requestor addressYes
tickerStringTicker for the spot marketYes
base_denomStringBase tocken denomYes
quote_denomStringQuote tocken denomYes
min_price_tick_sizeDecimalDefines the minimum tick size of the order's priceYes
min_quantity_tick_sizeDecimalDefines the minimum tick size of the order's quantityYes
min_notionalDecimalDefines the minimum notional (in quote asset) required for orders in the marketYes

Response Parameters

Response Example:


ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgCreateSpotLimitOrder

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os
import uuid
from decimal import Decimal

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())
    subaccount_id = address.get_subaccount_id(index=0)

    # prepare trade info
    market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
    fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
    cid = str(uuid.uuid4())

    # prepare tx msg
    msg = composer.msg_create_spot_limit_order(
        sender=address.to_acc_bech32(),
        market_id=market_id,
        subaccount_id=subaccount_id,
        fee_recipient=fee_recipient,
        price=Decimal("7.523"),
        quantity=Decimal("0.01"),
        order_type="BUY",
        cid=cid,
    )

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    sim_res_msg = sim_res["result"]["msgResponses"]
    print("---Simulation Response---")
    print(sim_res_msg)

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print("---Transaction Response---")
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))
    print(f"\n\ncid: {cid}")


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "fmt"
    "os"
    "time"

    exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
    "github.com/google/uuid"

    "github.com/InjectiveLabs/sdk-go/client"
    "github.com/InjectiveLabs/sdk-go/client/common"
    "github.com/shopspring/decimal"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("mainnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )
    if err != nil {
        fmt.Println(err)
        return
    }
    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketsAssistant, err := chainclient.NewMarketsAssistantInitializedFromChain(ctx, exchangeClient)
    if err != nil {
        panic(err)
    }

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    defaultSubaccountID := chainClient.DefaultSubaccount(senderAddress)

    marketId := "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0"

    amount := decimal.NewFromFloat(2)
    price := decimal.NewFromFloat(22.55)

    order := chainClient.CreateSpotOrder(
        defaultSubaccountID,
        &chainclient.SpotOrderData{
            OrderType:    exchangetypes.OrderType_BUY, //BUY SELL BUY_PO SELL_PO
            Quantity:     amount,
            Price:        price,
            FeeRecipient: senderAddress.String(),
            MarketId:     marketId,
            Cid:          uuid.NewString(),
        },
        marketsAssistant,
    )

    msg := new(exchangetypes.MsgCreateSpotLimitOrder)
    msg.Sender = senderAddress.String()
    msg.Order = exchangetypes.SpotOrder(*order)

    simRes, err := chainClient.SimulateMsg(clientCtx, msg)

    if err != nil {
        fmt.Println(err)
        return
    }

    msgCreateSpotLimitOrderResponse := exchangetypes.MsgCreateSpotLimitOrderResponse{}
    err = msgCreateSpotLimitOrderResponse.Unmarshal(simRes.Result.MsgResponses[0].Value)

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("simulated order hash: ", msgCreateSpotLimitOrderResponse.OrderHash)

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    err = chainClient.QueueBroadcastMsg(msg)

    if err != nil {
        fmt.Println(err)
        return
    }

    time.Sleep(time.Second * 5)

    gasFee, err := chainClient.GetGasFee()

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("gas fee:", gasFee, "INJ")
}
ParameterTypeDescriptionRequired
senderStringThe message sender's addressYes
orderSpotOrderOrder's parametersYes


SpotOrder

ParameterTypeDescriptionRequired
market_idStringThe unique ID of the marketYes
order_infoOrderInfoOrder's informationYes
order_typeOrderTypeThe order typeYes
trigger_priceDecimalThe trigger price used by stop/take ordersNo


OrderInfo

ParameterTypeDescriptionRequired
subaccount_idStringSubaccount ID that created the orderYes
fee_recipientStringAddress that will receive fees for the orderNo
priceDecimalPrice of the orderYes
quantityDecimalQuantity of the orderYes
cidStringClient order ID. An optional identifier for the order set by the creatorNo


OrderType

CodeName
0UNSPECIFIED
1BUY
2SELL
3STOP_BUY
4STOP_SELL
5TAKE_BUY
6TAKE_SELL
7BUY_PO
8SELL_PO
9BUY_ATOMIC
10SELL_ATOMIC

Response Parameters

Response Example:

---Simulation Response---
[order_hash: "0xee49d8060469fd6824d65a0f7099b02fe23fcb7302dd21800905cf0cd285bd82"
]
---Transaction Response---
txhash: "C56626C351E66EBAF085E84DF6422E84043DD6A1B81316367FE3976D762000FE"
raw_log: "[]"

gas wanted: 104011
gas fee: 0.0000520055 INJ
simulated order hash:  0x73d8e846abdfffd3d42ff2c190a650829a5af52b3337287319b4f2c54eb7ce80
DEBU[0001] broadcastTx with nonce 3492                   fn=func1 src="client/chain/chain.go:598"
DEBU[0003] msg batch committed successfully at height 5212740  fn=func1 src="client/chain/chain.go:619" txHash=B62F7CC6DE3297EC4376C239AF93DB33193A89FA99FAC27C9E25AD5579B9BAD7
DEBU[0003] nonce incremented to 3493                     fn=func1 src="client/chain/chain.go:623"
DEBU[0003] gas wanted:  129912                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.000064956 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgCreateSpotMarketOrder

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os
import uuid
from decimal import Decimal

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())
    subaccount_id = address.get_subaccount_id(index=0)

    # prepare trade info
    market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
    fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"

    # prepare tx msg
    msg = composer.msg_create_spot_market_order(
        market_id=market_id,
        sender=address.to_acc_bech32(),
        subaccount_id=subaccount_id,
        fee_recipient=fee_recipient,
        price=Decimal("10.522"),
        quantity=Decimal("0.01"),
        order_type="BUY",
        cid=str(uuid.uuid4()),
    )

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    sim_res_msg = sim_res["result"]["msgResponses"]
    print("---Simulation Response---")
    print(sim_res_msg)

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print("---Transaction Response---")
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "fmt"
    "os"
    "time"

    exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
    "github.com/google/uuid"

    "github.com/InjectiveLabs/sdk-go/client"
    "github.com/InjectiveLabs/sdk-go/client/common"
    "github.com/shopspring/decimal"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketsAssistant, err := chainclient.NewMarketsAssistantInitializedFromChain(ctx, exchangeClient)
    if err != nil {
        panic(err)
    }

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    defaultSubaccountID := chainClient.DefaultSubaccount(senderAddress)

    marketId := "0x0511ddc4e6586f3bfe1acb2dd905f8b8a82c97e1edaef654b12ca7e6031ca0fa"
    amount := decimal.NewFromFloat(0.1)
    price := decimal.NewFromFloat(22)

    order := chainClient.CreateSpotOrder(
        defaultSubaccountID,
        &chainclient.SpotOrderData{
            OrderType:    exchangetypes.OrderType_SELL, //BUY SELL
            Quantity:     amount,
            Price:        price,
            FeeRecipient: senderAddress.String(),
            MarketId:     marketId,
            Cid:          uuid.NewString(),
        },
        marketsAssistant,
    )

    msg := new(exchangetypes.MsgCreateSpotMarketOrder)
    msg.Sender = senderAddress.String()
    msg.Order = exchangetypes.SpotOrder(*order)

    simRes, err := chainClient.SimulateMsg(clientCtx, msg)
    if err != nil {
        fmt.Println(err)
        return
    }

    msgCreateSpotMarketOrderResponse := exchangetypes.MsgCreateSpotMarketOrderResponse{}
    err = msgCreateSpotMarketOrderResponse.Unmarshal(simRes.Result.MsgResponses[0].Value)

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("simulated order hash", msgCreateSpotMarketOrderResponse.OrderHash)

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    err = chainClient.QueueBroadcastMsg(msg)

    if err != nil {
        fmt.Println(err)
        return
    }

    time.Sleep(time.Second * 5)

    gasFee, err := chainClient.GetGasFee()

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("gas fee:", gasFee, "INJ")
}
ParameterTypeDescriptionRequired
senderStringThe message sender's addressYes
orderSpotOrderOrder's parametersYes


SpotOrder

ParameterTypeDescriptionRequired
market_idStringThe unique ID of the marketYes
order_infoOrderInfoOrder's informationYes
order_typeOrderTypeThe order typeYes
trigger_priceDecimalThe trigger price used by stop/take ordersNo


OrderInfo

ParameterTypeDescriptionRequired
subaccount_idStringSubaccount ID that created the orderYes
fee_recipientStringAddress that will receive fees for the orderNo
priceDecimalPrice of the orderYes
quantityDecimalQuantity of the orderYes
cidStringClient order ID. An optional identifier for the order set by the creatorNo


OrderType

CodeName
0UNSPECIFIED
1BUY
2SELL
3STOP_BUY
4STOP_SELL
5TAKE_BUY
6TAKE_SELL
7BUY_PO
8SELL_PO
9BUY_ATOMIC
10SELL_ATOMIC

Response Parameters

Response Example:

---Simulation Response---
[order_hash: "0x7c6552c5f5ffd3adc2cb5fe9f2bc1eed4741952f698c84e9dc73c6f45b6af8b4"
]
---Transaction Response---
txhash: "9BBD3666A052FA11AF572F4D788C3C7D8B44F60CF0F0375EE40B84DA2408114A"
raw_log: "[]"

gas wanted: 104352
gas fee: 0.000052176 INJ
simulated order hash 0xfa9038ef2e59035a8f3368438aa4533fce90d8bbd3bee6c37e4cc06e8d1d0e6a
DEBU[0001] broadcastTx with nonce 3493                   fn=func1 src="client/chain/chain.go:598"
DEBU[0004] msg batch committed successfully at height 5212834  fn=func1 src="client/chain/chain.go:619" txHash=14ABC252192D7286429730F9A29AB1BA67608B5EA7ACD7AD4D8F174C9B3852B3
DEBU[0004] nonce incremented to 3494                     fn=func1 src="client/chain/chain.go:623"
DEBU[0004] gas wanted:  130596                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.000065298 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgCancelSpotOrder

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())
    subaccount_id = address.get_subaccount_id(index=0)

    # prepare trade info
    market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
    order_hash = "0x52888d397d5ae821869c8acde5823dfd8018802d2ef642d3aa639e5308173fcf"

    # prepare tx msg
    msg = composer.msg_cancel_spot_order(
        sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, order_hash=order_hash
    )

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "fmt"
    "os"
    "time"

    "github.com/InjectiveLabs/sdk-go/client"

    "github.com/InjectiveLabs/sdk-go/client/common"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    msg := &exchangetypes.MsgCancelSpotOrder{
        Sender:       senderAddress.String(),
        MarketId:     "0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0",
        SubaccountId: "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
        OrderHash:    "0xc1dd07efb7cf3a90c3d09da958fa22d96a5787eba3dbec56b63902c482accbd4",
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    err = chainClient.QueueBroadcastMsg(msg)

    if err != nil {
        fmt.Println(err)
    }

    time.Sleep(time.Second * 5)

    gasFee, err := chainClient.GetGasFee()

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("gas fee:", gasFee, "INJ")
}
ParameterTypeDescriptionRequired
senderStringThe message sender's addressYes
market_idStringThe unique ID of the order's marketYes
subaccount_idStringThe subaccount ID the order belongs toYes
order_hashStringThe order hash (either order_hash or cid have to be provided)No
cidStringThe client order ID provided by the creator (either order_hash or cid have to be provided)No

Response Parameters

Response Example:

txhash: "3ABF365B8D90D44749AFF74FC510D792581202F98ABB406219B72E71315A64D4"
raw_log: "[]"

gas wanted: 102720
gas fee: 0.00005136 INJ
DEBU[0001] broadcastTx with nonce 3494                   fn=func1 src="client/chain/chain.go:598"
DEBU[0002] msg batch committed successfully at height 5212920  fn=func1 src="client/chain/chain.go:619" txHash=14C2CB0592C5E950587D2041E97E337452A28F2A11220CC3E66624E5BAA73245
DEBU[0002] nonce incremented to 3495                     fn=func1 src="client/chain/chain.go:623"
DEBU[0002] gas wanted:  127363                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.0000636815 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgBatchUpdateOrders

MsgBatchUpdateOrders allows for the atomic cancellation and creation of spot and derivative limit orders, along with a new order cancellation mode. Upon execution, order cancellations (if any) occur first, followed by order creations (if any).

Users can cancel all limit orders in a given spot or derivative market for a given subaccountID by specifying the associated marketID in the SpotMarketIdsToCancelAll and DerivativeMarketIdsToCancelAll. Users can also cancel individual limit orders in SpotOrdersToCancel or DerivativeOrdersToCancel, but must ensure that marketIDs in these individual order cancellations are not already provided in the SpotMarketIdsToCancelAll or DerivativeMarketIdsToCancelAll.

Further note that if no marketIDs are provided in the SpotMarketIdsToCancelAll or DerivativeMarketIdsToCancelAll, then the SubaccountID in the Msg should be left empty.

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os
import uuid
from decimal import Decimal

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())
    subaccount_id = address.get_subaccount_id(index=0)

    # prepare trade info
    fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"

    derivative_market_id_create = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    spot_market_id_create = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"

    derivative_market_id_cancel = "0xd5e4b12b19ecf176e4e14b42944731c27677819d2ed93be4104ad7025529c7ff"
    derivative_market_id_cancel_2 = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    spot_market_id_cancel = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
    spot_market_id_cancel_2 = "0x7a57e705bb4e09c88aecfc295569481dbf2fe1d5efe364651fbe72385938e9b0"

    derivative_orders_to_cancel = [
        composer.order_data(
            market_id=derivative_market_id_cancel,
            subaccount_id=subaccount_id,
            order_hash="0x48690013c382d5dbaff9989db04629a16a5818d7524e027d517ccc89fd068103",
        ),
        composer.order_data(
            market_id=derivative_market_id_cancel_2,
            subaccount_id=subaccount_id,
            order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5",
        ),
    ]

    spot_orders_to_cancel = [
        composer.order_data(
            market_id=spot_market_id_cancel,
            subaccount_id=subaccount_id,
            cid="0e5c3ad5-2cc4-4a2a-bbe5-b12697739163",
        ),
        composer.order_data(
            market_id=spot_market_id_cancel_2,
            subaccount_id=subaccount_id,
            order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2",
        ),
    ]

    derivative_orders_to_create = [
        composer.derivative_order(
            market_id=derivative_market_id_create,
            subaccount_id=subaccount_id,
            fee_recipient=fee_recipient,
            price=Decimal(25000),
            quantity=Decimal(0.1),
            margin=composer.calculate_margin(
                quantity=Decimal(0.1), price=Decimal(25000), leverage=Decimal(1), is_reduce_only=False
            ),
            order_type="BUY",
            cid=str(uuid.uuid4()),
        ),
        composer.derivative_order(
            market_id=derivative_market_id_create,
            subaccount_id=subaccount_id,
            fee_recipient=fee_recipient,
            price=Decimal(50000),
            quantity=Decimal(0.01),
            margin=composer.calculate_margin(
                quantity=Decimal(0.01), price=Decimal(50000), leverage=Decimal(1), is_reduce_only=False
            ),
            order_type="SELL",
            cid=str(uuid.uuid4()),
        ),
    ]

    spot_orders_to_create = [
        composer.spot_order(
            market_id=spot_market_id_create,
            subaccount_id=subaccount_id,
            fee_recipient=fee_recipient,
            price=Decimal("3"),
            quantity=Decimal("55"),
            order_type="BUY",
            cid=str(uuid.uuid4()),
        ),
        composer.spot_order(
            market_id=spot_market_id_create,
            subaccount_id=subaccount_id,
            fee_recipient=fee_recipient,
            price=Decimal("300"),
            quantity=Decimal("55"),
            order_type="SELL",
            cid=str(uuid.uuid4()),
        ),
    ]

    # prepare tx msg
    msg = composer.msg_batch_update_orders(
        sender=address.to_acc_bech32(),
        derivative_orders_to_create=derivative_orders_to_create,
        spot_orders_to_create=spot_orders_to_create,
        derivative_orders_to_cancel=derivative_orders_to_cancel,
        spot_orders_to_cancel=spot_orders_to_cancel,
    )

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    sim_res_msg = sim_res["result"]["msgResponses"]
    print("---Simulation Response---")
    print(sim_res_msg)

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print("---Transaction Response---")
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "fmt"
    "os"
    "time"

    exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
    "github.com/google/uuid"

    "github.com/InjectiveLabs/sdk-go/client"
    "github.com/InjectiveLabs/sdk-go/client/common"
    "github.com/shopspring/decimal"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        fmt.Println(err)
        return
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketsAssistant, err := chainclient.NewMarketsAssistantInitializedFromChain(ctx, exchangeClient)
    if err != nil {
        panic(err)
    }

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        fmt.Println(err)
        return
    }

    defaultSubaccountID := chainClient.DefaultSubaccount(senderAddress)

    smarketId := "0x0511ddc4e6586f3bfe1acb2dd905f8b8a82c97e1edaef654b12ca7e6031ca0fa"
    samount := decimal.NewFromFloat(2)
    sprice := decimal.NewFromFloat(22.5)
    smarketIds := []string{"0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0"}

    spot_order := chainClient.CreateSpotOrder(
        defaultSubaccountID,
        &chainclient.SpotOrderData{
            OrderType:    exchangetypes.OrderType_BUY, //BUY SELL BUY_PO SELL_PO
            Quantity:     samount,
            Price:        sprice,
            FeeRecipient: senderAddress.String(),
            MarketId:     smarketId,
            Cid:          uuid.NewString(),
        },
        marketsAssistant,
    )

    dmarketId := "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"
    damount := decimal.NewFromFloat(0.01)
    dprice := decimal.RequireFromString("31000") //31,000
    dleverage := decimal.RequireFromString("2")
    dmarketIds := []string{"0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"}

    derivative_order := chainClient.CreateDerivativeOrder(
        defaultSubaccountID,
        &chainclient.DerivativeOrderData{
            OrderType:    exchangetypes.OrderType_BUY, //BUY SELL BUY_PO SELL_PO
            Quantity:     damount,
            Price:        dprice,
            Leverage:     dleverage,
            FeeRecipient: senderAddress.String(),
            MarketId:     dmarketId,
            IsReduceOnly: false,
            Cid:          uuid.NewString(),
        },
        marketsAssistant,
    )

    msg := new(exchangetypes.MsgBatchUpdateOrders)
    msg.Sender = senderAddress.String()
    msg.SubaccountId = defaultSubaccountID.Hex()
    msg.SpotOrdersToCreate = []*exchangetypes.SpotOrder{spot_order}
    msg.DerivativeOrdersToCreate = []*exchangetypes.DerivativeOrder{derivative_order}
    msg.SpotMarketIdsToCancelAll = smarketIds
    msg.DerivativeMarketIdsToCancelAll = dmarketIds

    simRes, err := chainClient.SimulateMsg(clientCtx, msg)

    if err != nil {
        fmt.Println(err)
        return
    }

    MsgBatchUpdateOrdersResponse := exchangetypes.MsgBatchUpdateOrdersResponse{}
    MsgBatchUpdateOrdersResponse.Unmarshal(simRes.Result.MsgResponses[0].Value)

    fmt.Println("simulated spot order hashes", MsgBatchUpdateOrdersResponse.SpotOrderHashes)

    fmt.Println("simulated derivative order hashes", MsgBatchUpdateOrdersResponse.DerivativeOrderHashes)

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    err = chainClient.QueueBroadcastMsg(msg)

    if err != nil {
        fmt.Println(err)
        return
    }

    time.Sleep(time.Second * 5)

    gasFee, err := chainClient.GetGasFee()

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("gas fee:", gasFee, "INJ")
}
ParameterTypeDescriptionRequired
senderStringThe message sender's addressYes
subaccount_idStringThe subaccount ID is only used for the spot_market_ids_to_cancel_all and derivative_market_ids_to_cancel_allNo
spot_market_ids_to_cancel_allString ArrayList of unique market IDs to cancel all subaccount_id ordersNo
derivative_market_ids_to_cancel_allString ArrayList of unique market IDs to cancel all subaccount_id ordersNo
spot_orders_to_cancelOrderData ArrayList of spot orders to be cancelledNo
derivative_orders_to_cancelOrderData ArrayList of derivative orders to be cancelledNo
spot_orders_to_createSpotOrder ArrayList of spot orders to be createdNo
derivative_orders_to_createDerivativeOrder ArrayList of derivative orders to be createdNo
binary_options_orders_to_cancelOrderData ArrayList of binary options orders to be cancelledNo
binary_options_market_ids_to_cancel_allString ArrayList of unique market IDs to cancel all subaccount_id ordersNo
binary_options_orders_to_createDerivativeOrder ArrayList of binary options orders to be createdNo


OrderData

ParameterTypeDescriptionRequired
market_idStringThe order's market IDYes
subaccount_idStringSubaccount ID that created the orderYes
order_hashStringThe order hash (either the order_hash or the cid should be provided)No
order_maskOrderMaskThe order mask that specifies the order typeNo
cidStringThe order's client order ID (either the order_hash or the cid should be provided)No


SpotOrder

ParameterTypeDescriptionRequired
market_idStringThe unique ID of the marketYes
order_infoOrderInfoOrder's informationYes
order_typeOrderTypeThe order typeYes
trigger_priceDecimalThe trigger price used by stop/take ordersNo


DerivativeOrder

ParameterTypeDescriptionRequired
market_idStringThe unique ID of the marketYes
order_infoOrderInfoOrder's informationYes
order_typeOrderTypeThe order typeYes
marginDecimalThe margin amount used by the orderYes
trigger_priceDecimalThe trigger price used by stop/take ordersNo


OrderMask

CodeName
0OrderMask_UNUSED
1OrderMask_ANY
2OrderMask_REGULAR
4OrderMask_CONDITIONAL
8OrderMask_BUY_OR_HIGHER
16OrderMask_SELL_OR_LOWER
32OrderMask_MARKET
64OrderMask_LIMIT


OrderInfo

ParameterTypeDescriptionRequired
subaccount_idStringSubaccount ID that created the orderYes
fee_recipientStringAddress that will receive fees for the orderNo
priceDecimalPrice of the orderYes
quantityDecimalQuantity of the orderYes
cidStringClient order ID. An optional identifier for the order set by the creatorNo


OrderType

CodeName
0UNSPECIFIED
1BUY
2SELL
3STOP_BUY
4STOP_SELL
5TAKE_BUY
6TAKE_SELL
7BUY_PO
8SELL_PO
9BUY_ATOMIC
10SELL_ATOMIC

Response Parameters

Response Example:

---Simulation Response---
[spot_cancel_success: false
spot_cancel_success: false
derivative_cancel_success: false
derivative_cancel_success: false
spot_order_hashes: "0x3f5b5de6ec72b250c58e0a83408dbc1990cee369999036e3469e19b80fa9002e"
spot_order_hashes: "0x7d8580354e120b038967a180f73bc3aba0f49db9b6d2cb5c4cec85e8cab3e218"
derivative_order_hashes: "0x920a4ea4144c46d1e1084ca5807e4f5608639ce00f97139d5b44e628d487e15e"
derivative_order_hashes: "0x11d75d0c2ce8a07f352523be2e3456212c623397d0fc1a2f688b97a15c04372c"
]
---Transaction Response---
txhash: "4E29226884DCA22E127471588F39E0BB03D314E1AA27ECD810D24C4078D52DED"
raw_log: "[]"

gas wanted: 271213
gas fee: 0.0001356065 INJ
simulated spot order hashes [0xd9f30c7e700202615c2775d630b9fb276572d883fa480b6394abbddcb79c8109]
simulated derivative order hashes [0xb2bea3b15c204699a9ee945ca49650001560518d1e54266adac580aa061fedd4]
DEBU[0001] broadcastTx with nonce 3507                   fn=func1 src="client/chain/chain.go:598"
DEBU[0003] msg batch committed successfully at height 5214679  fn=func1 src="client/chain/chain.go:619" txHash=CF53E0B31B9E28E0D6D8F763ECEC2D91E38481321EA24AC86F6A8774C658AF44
DEBU[0003] nonce incremented to 3508                     fn=func1 src="client/chain/chain.go:623"
DEBU[0003] gas wanted:  659092                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.000329546 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgUpdateSpotMarket

Modifies certain market fields. It can only be sent by the market's admin.

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os
from decimal import Decimal

import dotenv

from pyinjective.async_client import AsyncClient
from pyinjective.core.broadcaster import MsgBroadcasterWithPk
from pyinjective.core.network import Network
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    await client.initialize_tokens_from_chain_denoms()
    composer = await client.composer()
    await client.sync_timeout_height()

    message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
        network=network,
        private_key=configured_private_key,
    )

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    # prepare tx msg
    message = composer.msg_update_spot_market(
        admin=address.to_acc_bech32(),
        market_id="0x215970bfdea5c94d8e964a759d3ce6eae1d113900129cc8428267db5ccdb3d1a",
        new_ticker="INJ/USDC 2",
        new_min_price_tick_size=Decimal("0.01"),
        new_min_quantity_tick_size=Decimal("0.01"),
        new_min_notional=Decimal("2"),
    )

    # broadcast the transaction
    result = await message_broadcaster.broadcast([message])
    print("---Transaction Response---")
    print(result)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "cosmossdk.io/math"
    exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"

    "github.com/InjectiveLabs/sdk-go/client"

    "github.com/InjectiveLabs/sdk-go/client/common"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )
    if err != nil {
        panic(err)
    }

    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketsAssistant, err := chainclient.NewMarketsAssistantInitializedFromChain(ctx, exchangeClient)
    if err != nil {
        panic(err)
    }

    baseToken := marketsAssistant.AllTokens()["INJ"]
    quoteToken := marketsAssistant.AllTokens()["USDC"]
    minPriceTickSize := math.LegacyMustNewDecFromStr("0.01")
    minQuantityTickSize := math.LegacyMustNewDecFromStr("0.01")
    minNotional := math.LegacyMustNewDecFromStr("2")

    chainMinPriceTickSize := minPriceTickSize.Mul(math.LegacyNewDecFromIntWithPrec(math.NewInt(1), int64(quoteToken.Decimals)))
    chainMinPriceTickSize = chainMinPriceTickSize.Quo(math.LegacyNewDecFromIntWithPrec(math.NewInt(1), int64(baseToken.Decimals)))

    chainMinQuantityTickSize := minQuantityTickSize.Mul(math.LegacyNewDecFromIntWithPrec(math.NewInt(1), int64(baseToken.Decimals)))
    chainMinNotional := minNotional.Mul(math.LegacyNewDecFromIntWithPrec(math.NewInt(1), int64(quoteToken.Decimals)))

    msg := &exchangetypes.MsgUpdateSpotMarket{
        Admin:                  senderAddress.String(),
        MarketId:               "0x215970bfdea5c94d8e964a759d3ce6eae1d113900129cc8428267db5ccdb3d1a",
        NewTicker:              "INJ/USDC 2",
        NewMinPriceTickSize:    chainMinPriceTickSize,
        NewMinQuantityTickSize: chainMinQuantityTickSize,
        NewMinNotional:         chainMinNotional,
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    response, err := chainClient.AsyncBroadcastMsg(msg)

    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(response, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
adminStringThe market's admin address (has to be the message broadcaster)Yes
market_idStringThe market's unique IDYes
new_tickerStringNew ticker for the spot marketNo
new_min_price_tick_sizeDecimalDefines the minimum tick size of the order's priceNo
new_min_quantity_tick_sizeDecimalDefines the minimum tick size of the order's quantityNo
new_min_notionalDecimalDefines the minimum notional (in quote asset) required for orders in the marketNo

Response Parameters

Response Example:

txhash: "5AF048ADCE6AF753256F03AF2404A5B78C4C3E7E42A91F0B5C9994372E8AC2FE"
raw_log: "[]"

gas wanted: 106585
gas fee: 0.0000532925 INJ
DEBU[0001] broadcastTx with nonce 3503                   fn=func1 src="client/chain/chain.go:598"
DEBU[0002] msg batch committed successfully at height 5214406  fn=func1 src="client/chain/chain.go:619"
txHash=31FDA89C3122322C0559B5766CDF892FD0AA12469017CF8BF88B53441464ECC4
DEBU[0002] nonce incremented to 3504                     fn=func1 src="client/chain/chain.go:623"
DEBU[0002] gas wanted:  133614                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.000066807 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

LocalOrderHashComputation

This function computes order hashes locally for SpotOrder and DerivativeOrder. For more information, see the note below.

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os
import uuid
from decimal import Decimal

import dotenv

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.orderhash import OrderHashManager
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())
    subaccount_id = address.get_subaccount_id(index=0)
    subaccount_id_2 = address.get_subaccount_id(index=1)

    order_hash_manager = OrderHashManager(address=address, network=network, subaccount_indexes=[0, 1, 2, 7])

    # prepare trade info
    spot_market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
    deriv_market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"

    spot_orders = [
        composer.spot_order(
            market_id=spot_market_id,
            subaccount_id=subaccount_id,
            fee_recipient=fee_recipient,
            price=Decimal("0.524"),
            quantity=Decimal("0.01"),
            order_type="BUY",
            cid=str(uuid.uuid4()),
        ),
        composer.spot_order(
            market_id=spot_market_id,
            subaccount_id=subaccount_id,
            fee_recipient=fee_recipient,
            price=Decimal("27.92"),
            quantity=Decimal("0.01"),
            order_type="SELL",
            cid=str(uuid.uuid4()),
        ),
    ]

    derivative_orders = [
        composer.derivative_order(
            market_id=deriv_market_id,
            subaccount_id=subaccount_id,
            fee_recipient=fee_recipient,
            price=Decimal(10500),
            quantity=Decimal(0.01),
            margin=composer.calculate_margin(
                quantity=Decimal(0.01), price=Decimal(10500), leverage=Decimal(2), is_reduce_only=False
            ),
            order_type="BUY",
            cid=str(uuid.uuid4()),
        ),
        composer.derivative_order(
            market_id=deriv_market_id,
            subaccount_id=subaccount_id,
            fee_recipient=fee_recipient,
            price=Decimal(65111),
            quantity=Decimal(0.01),
            margin=composer.calculate_margin(
                quantity=Decimal(0.01), price=Decimal(65111), leverage=Decimal(2), is_reduce_only=False
            ),
            order_type="SELL",
            cid=str(uuid.uuid4()),
        ),
    ]

    # prepare tx msg
    spot_msg = composer.msg_batch_create_spot_limit_orders(sender=address.to_acc_bech32(), orders=spot_orders)

    deriv_msg = composer.msg_batch_create_derivative_limit_orders(
        sender=address.to_acc_bech32(), orders=derivative_orders
    )

    # compute order hashes
    order_hashes = order_hash_manager.compute_order_hashes(
        spot_orders=spot_orders, derivative_orders=derivative_orders, subaccount_index=0
    )

    print("computed spot order hashes", order_hashes.spot)
    print("computed derivative order hashes", order_hashes.derivative)

    # build tx 1
    tx = (
        Transaction()
        .with_messages(spot_msg, deriv_msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    gas_price = GAS_PRICE
    base_gas = 85000
    gas_limit = base_gas + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))

    # compute order hashes
    order_hashes = order_hash_manager.compute_order_hashes(
        spot_orders=spot_orders, derivative_orders=derivative_orders, subaccount_index=0
    )

    print("computed spot order hashes", order_hashes.spot)
    print("computed derivative order hashes", order_hashes.derivative)

    # build tx 2
    tx = (
        Transaction()
        .with_messages(spot_msg, deriv_msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    gas_price = GAS_PRICE
    base_gas = 85000
    gas_limit = base_gas + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))

    spot_orders = [
        composer.spot_order(
            market_id=spot_market_id,
            subaccount_id=subaccount_id_2,
            fee_recipient=fee_recipient,
            price=Decimal("1.524"),
            quantity=Decimal("0.01"),
            order_type="BUY_PO",
            cid=str(uuid.uuid4()),
        ),
        composer.spot_order(
            market_id=spot_market_id,
            subaccount_id=subaccount_id_2,
            fee_recipient=fee_recipient,
            price=Decimal("27.92"),
            quantity=Decimal("0.01"),
            order_type="SELL_PO",
            cid=str(uuid.uuid4()),
        ),
    ]

    derivative_orders = [
        composer.derivative_order(
            market_id=deriv_market_id,
            subaccount_id=subaccount_id_2,
            fee_recipient=fee_recipient,
            price=Decimal(25111),
            quantity=Decimal(0.01),
            margin=composer.calculate_margin(
                quantity=Decimal(0.01), price=Decimal(25111), leverage=Decimal("1.5"), is_reduce_only=False
            ),
            order_type="BUY",
            cid=str(uuid.uuid4()),
        ),
        composer.derivative_order(
            market_id=deriv_market_id,
            subaccount_id=subaccount_id_2,
            fee_recipient=fee_recipient,
            price=Decimal(65111),
            quantity=Decimal(0.01),
            margin=composer.calculate_margin(
                quantity=Decimal(0.01), price=Decimal(25111), leverage=Decimal(2), is_reduce_only=False
            ),
            order_type="SELL",
            cid=str(uuid.uuid4()),
        ),
    ]

    # prepare tx msg
    spot_msg = composer.msg_batch_create_spot_limit_orders(sender=address.to_acc_bech32(), orders=spot_orders)

    deriv_msg = composer.msg_batch_create_derivative_limit_orders(
        sender=address.to_acc_bech32(), orders=derivative_orders
    )

    # compute order hashes
    order_hashes = order_hash_manager.compute_order_hashes(
        spot_orders=spot_orders, derivative_orders=derivative_orders, subaccount_index=1
    )

    print("computed spot order hashes", order_hashes.spot)
    print("computed derivative order hashes", order_hashes.derivative)

    # build tx 3
    tx = (
        Transaction()
        .with_messages(spot_msg, deriv_msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    gas_price = GAS_PRICE
    base_gas = 85000
    gas_limit = base_gas + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "fmt"
    "os"
    "time"

    exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
    "github.com/google/uuid"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
    "github.com/shopspring/decimal"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )
    if err != nil {
        panic(err)
    }

    // initialize grpc client
    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketsAssistant, err := chainclient.NewMarketsAssistantInitializedFromChain(ctx, exchangeClient)
    if err != nil {
        panic(err)
    }

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    // prepare tx msg
    defaultSubaccountID := chainClient.Subaccount(senderAddress, 1)

    spotOrder := chainClient.CreateSpotOrder(
        defaultSubaccountID,
        &chainclient.SpotOrderData{
            OrderType:    exchangetypes.OrderType_BUY,
            Quantity:     decimal.NewFromFloat(2),
            Price:        decimal.NewFromFloat(22.55),
            FeeRecipient: senderAddress.String(),
            MarketId:     "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe",
            Cid:          uuid.NewString(),
        },
        marketsAssistant,
    )

    derivativeOrder := chainClient.CreateDerivativeOrder(
        defaultSubaccountID,
        &chainclient.DerivativeOrderData{
            OrderType:    exchangetypes.OrderType_BUY,
            Quantity:     decimal.NewFromFloat(2),
            Price:        decimal.RequireFromString("31"),
            Leverage:     decimal.RequireFromString("2.5"),
            FeeRecipient: senderAddress.String(),
            MarketId:     "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
            Cid:          uuid.NewString(),
        },
        marketsAssistant,
    )

    msg := new(exchangetypes.MsgBatchCreateSpotLimitOrders)
    msg.Sender = senderAddress.String()
    msg.Orders = []exchangetypes.SpotOrder{*spotOrder}

    msg1 := new(exchangetypes.MsgBatchCreateDerivativeLimitOrders)
    msg1.Sender = senderAddress.String()
    msg1.Orders = []exchangetypes.DerivativeOrder{*derivativeOrder, *derivativeOrder}

    // compute local order hashes
    orderHashes, err := chainClient.ComputeOrderHashes(msg.Orders, msg1.Orders, defaultSubaccountID)

    if err != nil {
        fmt.Println(err)
    }

    fmt.Println("computed spot order hashes: ", orderHashes.Spot)
    fmt.Println("computed derivative order hashes: ", orderHashes.Derivative)

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    err = chainClient.QueueBroadcastMsg(msg, msg1)

    if err != nil {
        fmt.Println(err)
    }

    time.Sleep(time.Second * 5)

    gasFee, err := chainClient.GetGasFee()

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("gas fee:", gasFee, "INJ")
}

Response Parameters

Response Example:

computed spot order hashes ['0xa2d59cca00bade680a552f02deeb43464df21c73649191d64c6436313b311cba', '0xab78219e6c494373262a310d73660198c7a4c91196c0f6bb8808c81d8fb54a11']
computed derivative order hashes ['0x38d432c011f4a62c6b109615718b26332e7400a86f5e6f44e74a8833b7eed992', '0x66a921d83e6931513df9076c91a920e5e943837e2b836ad370b5cf53a1ed742c']
txhash: "604757CD9024FFF2DDCFEED6FC070E435AC09A829DB2E81AD4AD65B33E987A8B"
raw_log: "[]"

gas wanted: 196604
gas fee: 0.000098302 INJ
computed spot order hashes:  [0x0103ca50d0d033e6b8528acf28a3beb3fd8bac20949fc1ba60a2da06c53ad94f]
computed derivative order hashes:  [0x15334a7a0f1c2f98b9369f79b9a62a1f357d3e63b46a8895a4cec0ca375ddbbb 0xc26c8f74f56eade275e518f73597dd8954041bfbae3951ed4d7efeb0d060edbd]
DEBU[0001] broadcastTx with nonce 3488                   fn=func1 src="client/chain/chain.go:598"
DEBU[0003] msg batch committed successfully at height 5212331  fn=func1 src="client/chain/chain.go:619" txHash=19D8D81BB1DF59889E00EAA600A01079BA719F00A4A43CCC1B56580A1BBD6455
DEBU[0003] nonce incremented to 3489                     fn=func1 src="client/chain/chain.go:623"
DEBU[0003] gas wanted:  271044                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.000135522 INJ

Note on LocalOrderHashComputation for HFTs/API Traders

LocalOrderHashComputation returns a locally computed transaction hash for spot and derivative orders, which is useful when the user needs the transaction hash faster than orders can be streamed through StreamOrdersHistory (there is extra latency since the order must be included by a block, and the block must be indexed by the Indexer). While the hash can also be obtained through transaction simulation, the process adds a layer of latency and can only be used for one transaction per block (simulation relies on a nonce based on the state machine which does not change until the transaction is included in a block).

On Injective, subaccount nonces are used to calculate order hashes. The subaccount nonce is incremented with each order so that order hashes remain unique.

For strategies employing high frequency trading, order hashes should be calculated locally before transactions are broadcasted. This is possible as long as the subaccount nonce is cached/tracked locally instead of queried from the chain. Similarly, the account sequence (like nonce on Ethereum) should be cached if more than one transaction per block is desired. The LocalOrderHashComputation implementation can be found here. Refer to the above API example for usage.

There are two caveats to be mindful of when taking this approach:

1. Gas must be manually calculated instead of fetched from simulation

  class GasLimitConstant:
      base = 65e3
      extra = 20e3
      spot_order = 60e3
      spot_cancel = 40e3

2. In the event a transaction fails, the account sequence and subaccount nonce must both be refreshed

  res = await self.client.broadcast_tx_sync_mode(tx_raw_bytes)
  if res.code == 32:
      await client.fetch_account(address.to_acc_bech32())

- Chain Exchange for Binary Options

Includes all messages related to binary options.

BinaryOptionsMarkets

Retrieves binary options markets

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    markets = await client.fetch_chain_binary_options_markets(status="Active")
    print(markets)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    status := "Active"

    res, err := chainClient.FetchChainBinaryOptionsMarkets(ctx, status)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
statusStringMarket statusNo

Response Parameters

Response Example:

{
   "markets":[

   ]
}
ParameterTypeDescription
marketsBinaryOptionsMarket ArrayList of binary options markets


BinaryOptionsMarket

ParameterTypeDescription
tickerStringName of the pair in format AAA/BBB, where AAA is base asset, BBB is quote asset
oracle_symbolStringOracle symbol
oracle_providerStringOracle provider
oracle_typeOracleTypeThe oracle type
oracle_scale_factorIntegerThe oracle number of scale decimals
expiration_timestampIntegerThe market expiration timestamp
settlement_timestampIntegerThe market settlement timestamp
adminStringThe market's admin address
quote_denomStringCoin denom used for the quote asset
market_idStringThe market ID
maker_fee_rateDecimalFee percentage makers pay when trading
taker_fee_rateDecimalFee percentage takers pay when trading
relayer_fee_share_rateDecimalPercentage of the transaction fee shared with the relayer in a derivative market
statusMarketStatusStatus of the market
min_price_tick_sizeDecimalMinimum tick size that the price required for orders in the market
min_quantity_tick_sizeDecimalMinimum tick size of the quantity required for orders in the market
settlement_priceDecimalThe market's settlement price
min_notionalDecimalMinimum notional (in quote asset) required for orders in the market
admin_permissionsIntegerLevel of admin permissions (the permission number is a result of adding up all individual permissions numbers)


OracleType

CodeName
0Unspecified
1Band
2PriceFeed
3Coinbase
4Chainlink
5Razor
6Dia
7API3
8Uma
9Pyth
10BandIBC
11Provider


AdminPermission

CodeName
1Ticker Permission
2Min Price Tick Size Permission
4Min Quantity Tick Size Permission
8Min Notional Permission
16Initial Margin Ratio Permission
32Maintenance Margin Ratio Permission
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "cosmossdk.io/math"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    oracletypes "github.com/InjectiveLabs/sdk-go/chain/oracle/types"
    exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )
    if err != nil {
        panic(err)
    }

    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketsAssistant, err := chainclient.NewMarketsAssistantInitializedFromChain(ctx, exchangeClient)
    if err != nil {
        panic(err)
    }

    quoteToken := marketsAssistant.AllTokens()["USDC"]
    minPriceTickSize := math.LegacyMustNewDecFromStr("0.01")
    minQuantityTickSize := math.LegacyMustNewDecFromStr("0.001")

    chainMinPriceTickSize := minPriceTickSize.Mul(math.LegacyNewDecFromIntWithPrec(math.NewInt(1), int64(quoteToken.Decimals)))
    chainMinQuantityTickSize := minQuantityTickSize

    msg := &exchangetypes.MsgInstantBinaryOptionsMarketLaunch{
        Sender:              senderAddress.String(),
        Ticker:              "UFC-KHABIB-TKO-05/30/2023",
        OracleSymbol:        "UFC-KHABIB-TKO-05/30/2023",
        OracleProvider:      "UFC",
        OracleType:          oracletypes.OracleType_Provider,
        OracleScaleFactor:   6,
        MakerFeeRate:        math.LegacyMustNewDecFromStr("0.0005"),
        TakerFeeRate:        math.LegacyMustNewDecFromStr("0.0010"),
        ExpirationTimestamp: 1680730982,
        SettlementTimestamp: 1690730982,
        Admin:               senderAddress.String(),
        QuoteDenom:          quoteToken.Denom,
        MinPriceTickSize:    chainMinPriceTickSize,
        MinQuantityTickSize: chainMinQuantityTickSize,
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    response, err := chainClient.AsyncBroadcastMsg(msg)

    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(response, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
senderStringThe market launch requestor addressYes
tickerStringTicker for the binary options marketYes
oracle_symbolStringOracle symbolYes
oracle_providerStringOracle providerYes
oracle_typeOracleTypeThe oracle typeYes
oracle_scale_factorIntegerScale factor for oracle pricesYes
maker_fee_rateDecimalDefines the trade fee rate for makers on the perpetual marketYes
taker_fee_rateDecimalDefines the trade fee rate for takers on the perpetual marketYes
expiration_timestampIntegerThe market's expiration time in secondsYes
settlement_timestampIntegerThe market's settlement time in secondsYes
adminStringThe market's admin addressYes
quote_denomStringQuote tocken denomYes
min_price_tick_sizeDecimalDefines the minimum tick size of the order's priceYes
min_quantity_tick_sizeDecimalDefines the minimum tick size of the order's quantityYes
min_notionalDecimalDefines the minimum notional (in quote asset) required for orders in the marketYes


OracleType

CodeName
0Unspecified
1Band
2PriceFeed
3Coinbase
4Chainlink
5Razor
6Dia
7API3
8Uma
9Pyth
10BandIBC
11Provider

Response Parameters

Response Example:


ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgCreateBinaryOptionsLimitOrder

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os
import uuid
from decimal import Decimal

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.utils.denom import Denom
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())
    subaccount_id = address.get_subaccount_id(index=0)

    # prepare trade info
    market_id = "0x767e1542fbc111e88901e223e625a4a8eb6d630c96884bbde672e8bc874075bb"
    fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"

    # set custom denom to bypass ini file load (optional)
    denom = Denom(
        description="desc",
        base=0,
        quote=6,
        min_price_tick_size=1000,
        min_quantity_tick_size=0.0001,
        min_notional=0,
    )

    # prepare tx msg
    msg = composer.msg_create_binary_options_limit_order(
        sender=address.to_acc_bech32(),
        market_id=market_id,
        subaccount_id=subaccount_id,
        fee_recipient=fee_recipient,
        price=Decimal("0.5"),
        quantity=Decimal("1"),
        margin=Decimal("0.5"),
        order_type="BUY",
        cid=str(uuid.uuid4()),
        denom=denom,
    )

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    sim_res_msg = sim_res["result"]["msgResponses"]
    print("---Simulation Response---")
    print(sim_res_msg)

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print("---Transaction Response---")
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
ParameterTypeDescriptionRequired
senderStringThe message sender's addressYes
orderDerivativeOrderOrder's parametersYes


DerivativeOrder

ParameterTypeDescriptionRequired
market_idStringThe unique ID of the marketYes
order_infoOrderInfoOrder's informationYes
order_typeOrderTypeThe order typeYes
marginDecimalThe margin amount used by the orderYes
trigger_priceDecimalThe trigger price used by stop/take ordersNo


OrderInfo

ParameterTypeDescriptionRequired
subaccount_idStringSubaccount ID that created the orderYes
fee_recipientStringAddress that will receive fees for the orderNo
priceDecimalPrice of the orderYes
quantityDecimalQuantity of the orderYes
cidStringClient order ID. An optional identifier for the order set by the creatorNo


OrderType

CodeName
0UNSPECIFIED
1BUY
2SELL
3STOP_BUY
4STOP_SELL
5TAKE_BUY
6TAKE_SELL
7BUY_PO
8SELL_PO
9BUY_ATOMIC
10SELL_ATOMIC

Response Parameters

Response Example:

---Simulation Response---
[order_hash: "0xc1e1a8e81659360c3092043a000786f23fce5f3b8a355da32227c3e8eafb1fde"
]
---Transaction Response---
txhash: "7955AE8D7EA90E85F07E776372369E92952A0A86DC9BCBDBA3132447DB738282"
raw_log: "[]"

gas wanted: 121249
gas fee: 0.0000606245 INJ

ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgCreateBinaryOptionsMarketOrder

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os
import uuid
from decimal import Decimal

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())
    subaccount_id = address.get_subaccount_id(index=0)

    # prepare trade info
    market_id = "0x00617e128fdc0c0423dd18a1ff454511af14c4db6bdd98005a99cdf8fdbf74e9"
    fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"

    # prepare tx msg
    msg = composer.msg_create_binary_options_market_order(
        sender=address.to_acc_bech32(),
        market_id=market_id,
        subaccount_id=subaccount_id,
        fee_recipient=fee_recipient,
        price=Decimal("0.5"),
        quantity=Decimal(1),
        margin=composer.calculate_margin(
            quantity=Decimal(1), price=Decimal("0.5"), leverage=Decimal(1), is_reduce_only=False
        ),
        cid=str(uuid.uuid4()),
    )
    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    sim_res_msg = sim_res["result"]["msgResponses"]
    print("---Simulation Response---")
    print(sim_res_msg)

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print("---Transaction Response---")
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
ParameterTypeDescriptionRequired
senderStringThe message sender's addressYes
orderDerivativeOrderOrder's parametersYes


DerivativeOrder

ParameterTypeDescriptionRequired
market_idStringThe unique ID of the marketYes
order_infoOrderInfoOrder's informationYes
order_typeOrderTypeThe order typeYes
marginDecimalThe margin amount used by the orderYes
trigger_priceDecimalThe trigger price used by stop/take ordersNo


OrderInfo

ParameterTypeDescriptionRequired
subaccount_idStringSubaccount ID that created the orderYes
fee_recipientStringAddress that will receive fees for the orderNo
priceDecimalPrice of the orderYes
quantityDecimalQuantity of the orderYes
cidStringClient order ID. An optional identifier for the order set by the creatorNo


OrderType

CodeName
0UNSPECIFIED
1BUY
2SELL
3STOP_BUY
4STOP_SELL
5TAKE_BUY
6TAKE_SELL
7BUY_PO
8SELL_PO
9BUY_ATOMIC
10SELL_ATOMIC

Response Parameters

Response Example:

---Simulation Response---
[order_hash: "0x1d4ebeaa75bb6a5232ef20cf9ff10eedc470be8f716fb4b3a57780fb1247b4dc"
]
---Transaction Response---
txhash: "FE91A0828F1900FB9FD202BF872B66580A89E663062B3DF13874328A7F6CF797"
raw_log: "[]"

gas wanted: 107903
gas fee: 0.0000539515 INJ

ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgCancelBinaryOptionsOrder

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())
    subaccount_id = address.get_subaccount_id(index=0)

    # prepare trade info
    market_id = "0x00617e128fdc0c0423dd18a1ff454511af14c4db6bdd98005a99cdf8fdbf74e9"
    order_hash = "a975fbd72b874bdbf5caf5e1e8e2653937f33ce6dd14d241c06c8b1f7b56be46"

    # prepare tx msg
    msg = composer.msg_cancel_binary_options_order(
        sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, order_hash=order_hash
    )
    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    sim_res_msg = sim_res["result"]["msgResponses"]
    print("---Simulation Response---")
    print(sim_res_msg)

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print("---Transaction Response---")
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
ParameterTypeDescriptionRequired
senderStringThe message sender's addressYes
market_idStringThe unique ID of the order's marketYes
subaccount_idStringThe subaccount ID the order belongs toYes
order_hashStringThe order hash (either order_hash or cid have to be provided)No
order_maskOrderMaskThe order mask that specifies the order typeNo
cidStringThe client order ID provided by the creator (either order_hash or cid have to be provided)No


OrderMask

CodeName
0OrderMask_UNUSED
1OrderMask_ANY
2OrderMask_REGULAR
4OrderMask_CONDITIONAL
8OrderMask_BUY_OR_HIGHER
16OrderMask_SELL_OR_LOWER
32OrderMask_MARKET
64OrderMask_LIMIT

Response Parameters

Response Example:

---Transaction Response---
txhash: "4B85368A96A67BB9B6DABB8B730A824051E0E4C9243F5970DF1512B98FCF2D67"
raw_log: "[]"

gas wanted: 111303
gas fee: 0.0000556515 INJ

ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgAdminUpdateBinaryOptionsMarket

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os
from decimal import Decimal

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    # prepare trade info
    market_id = "0xfafec40a7b93331c1fc89c23f66d11fbb48f38dfdd78f7f4fc4031fad90f6896"
    status = "Demolished"
    settlement_price = Decimal(1)
    expiration_timestamp = 1685460582
    settlement_timestamp = 1690730982

    # prepare tx msg
    msg = composer.msg_admin_update_binary_options_market(
        sender=address.to_acc_bech32(),
        market_id=market_id,
        settlement_price=settlement_price,
        expiration_timestamp=expiration_timestamp,
        settlement_timestamp=settlement_timestamp,
        status=status,
    )

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    sim_res_msg = sim_res["result"]["msgResponses"]
    print("---Simulation Response---")
    print(sim_res_msg)

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print("---Transaction Response---")
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
ParameterTypeDescriptionRequired
senderStringThe market launch requestor addressYes
market_idStringThe unique market IDYes
settlement_priceDecimalThe price at which market will be settledNo
expiration_timestampIntegerThe market's expiration time in secondsYes
settlement_timestampIntegerThe market's settlement time in secondsYes
market_statusMarketStatusThe market statusYes


MarketStatus

CodeName
0Unspecified
1Active
2Paused
3Demolished
4Expired

Response Parameters

Response Example:

---Transaction Response---
txhash: "4B85368A96A67BB9B6DABB8B730A824051E0E4C9243F5970DF1512B98FCF2D67"
raw_log: "[]"

gas wanted: 111303
gas fee: 0.0000556515 INJ

ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgBatchUpdateOrders

MsgBatchUpdateOrders allows for the atomic cancellation and creation of spot and derivative limit orders, along with a new order cancellation mode. Upon execution, order cancellations (if any) occur first, followed by order creations (if any).

Users can cancel all limit orders in a given spot or derivative market for a given subaccountID by specifying the associated marketID in the SpotMarketIdsToCancelAll and DerivativeMarketIdsToCancelAll. Users can also cancel individual limit orders in SpotOrdersToCancel or DerivativeOrdersToCancel, but must ensure that marketIDs in these individual order cancellations are not already provided in the SpotMarketIdsToCancelAll or DerivativeMarketIdsToCancelAll.

Further note that if no marketIDs are provided in the SpotMarketIdsToCancelAll or DerivativeMarketIdsToCancelAll, then the SubaccountID in the Msg should be left empty.

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os
import uuid
from decimal import Decimal

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())
    subaccount_id = address.get_subaccount_id(index=0)

    # prepare trade info
    fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"

    derivative_market_id_create = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    spot_market_id_create = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"

    derivative_market_id_cancel = "0xd5e4b12b19ecf176e4e14b42944731c27677819d2ed93be4104ad7025529c7ff"
    derivative_market_id_cancel_2 = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"
    spot_market_id_cancel = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"
    spot_market_id_cancel_2 = "0x7a57e705bb4e09c88aecfc295569481dbf2fe1d5efe364651fbe72385938e9b0"

    derivative_orders_to_cancel = [
        composer.order_data(
            market_id=derivative_market_id_cancel,
            subaccount_id=subaccount_id,
            order_hash="0x48690013c382d5dbaff9989db04629a16a5818d7524e027d517ccc89fd068103",
        ),
        composer.order_data(
            market_id=derivative_market_id_cancel_2,
            subaccount_id=subaccount_id,
            order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5",
        ),
    ]

    spot_orders_to_cancel = [
        composer.order_data(
            market_id=spot_market_id_cancel,
            subaccount_id=subaccount_id,
            cid="0e5c3ad5-2cc4-4a2a-bbe5-b12697739163",
        ),
        composer.order_data(
            market_id=spot_market_id_cancel_2,
            subaccount_id=subaccount_id,
            order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2",
        ),
    ]

    derivative_orders_to_create = [
        composer.derivative_order(
            market_id=derivative_market_id_create,
            subaccount_id=subaccount_id,
            fee_recipient=fee_recipient,
            price=Decimal(25000),
            quantity=Decimal(0.1),
            margin=composer.calculate_margin(
                quantity=Decimal(0.1), price=Decimal(25000), leverage=Decimal(1), is_reduce_only=False
            ),
            order_type="BUY",
            cid=str(uuid.uuid4()),
        ),
        composer.derivative_order(
            market_id=derivative_market_id_create,
            subaccount_id=subaccount_id,
            fee_recipient=fee_recipient,
            price=Decimal(50000),
            quantity=Decimal(0.01),
            margin=composer.calculate_margin(
                quantity=Decimal(0.01), price=Decimal(50000), leverage=Decimal(1), is_reduce_only=False
            ),
            order_type="SELL",
            cid=str(uuid.uuid4()),
        ),
    ]

    spot_orders_to_create = [
        composer.spot_order(
            market_id=spot_market_id_create,
            subaccount_id=subaccount_id,
            fee_recipient=fee_recipient,
            price=Decimal("3"),
            quantity=Decimal("55"),
            order_type="BUY",
            cid=str(uuid.uuid4()),
        ),
        composer.spot_order(
            market_id=spot_market_id_create,
            subaccount_id=subaccount_id,
            fee_recipient=fee_recipient,
            price=Decimal("300"),
            quantity=Decimal("55"),
            order_type="SELL",
            cid=str(uuid.uuid4()),
        ),
    ]

    # prepare tx msg
    msg = composer.msg_batch_update_orders(
        sender=address.to_acc_bech32(),
        derivative_orders_to_create=derivative_orders_to_create,
        spot_orders_to_create=spot_orders_to_create,
        derivative_orders_to_cancel=derivative_orders_to_cancel,
        spot_orders_to_cancel=spot_orders_to_cancel,
    )

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    sim_res_msg = sim_res["result"]["msgResponses"]
    print("---Simulation Response---")
    print(sim_res_msg)

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print("---Transaction Response---")
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "fmt"
    "os"
    "time"

    exchangeclient "github.com/InjectiveLabs/sdk-go/client/exchange"
    "github.com/google/uuid"

    "github.com/InjectiveLabs/sdk-go/client"
    "github.com/InjectiveLabs/sdk-go/client/common"
    "github.com/shopspring/decimal"

    exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        fmt.Println(err)
        return
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    exchangeClient, err := exchangeclient.NewExchangeClient(network)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    marketsAssistant, err := chainclient.NewMarketsAssistantInitializedFromChain(ctx, exchangeClient)
    if err != nil {
        panic(err)
    }

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        fmt.Println(err)
        return
    }

    defaultSubaccountID := chainClient.DefaultSubaccount(senderAddress)

    smarketId := "0x0511ddc4e6586f3bfe1acb2dd905f8b8a82c97e1edaef654b12ca7e6031ca0fa"
    samount := decimal.NewFromFloat(2)
    sprice := decimal.NewFromFloat(22.5)
    smarketIds := []string{"0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0"}

    spot_order := chainClient.CreateSpotOrder(
        defaultSubaccountID,
        &chainclient.SpotOrderData{
            OrderType:    exchangetypes.OrderType_BUY, //BUY SELL BUY_PO SELL_PO
            Quantity:     samount,
            Price:        sprice,
            FeeRecipient: senderAddress.String(),
            MarketId:     smarketId,
            Cid:          uuid.NewString(),
        },
        marketsAssistant,
    )

    dmarketId := "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"
    damount := decimal.NewFromFloat(0.01)
    dprice := decimal.RequireFromString("31000") //31,000
    dleverage := decimal.RequireFromString("2")
    dmarketIds := []string{"0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce"}

    derivative_order := chainClient.CreateDerivativeOrder(
        defaultSubaccountID,
        &chainclient.DerivativeOrderData{
            OrderType:    exchangetypes.OrderType_BUY, //BUY SELL BUY_PO SELL_PO
            Quantity:     damount,
            Price:        dprice,
            Leverage:     dleverage,
            FeeRecipient: senderAddress.String(),
            MarketId:     dmarketId,
            IsReduceOnly: false,
            Cid:          uuid.NewString(),
        },
        marketsAssistant,
    )

    msg := new(exchangetypes.MsgBatchUpdateOrders)
    msg.Sender = senderAddress.String()
    msg.SubaccountId = defaultSubaccountID.Hex()
    msg.SpotOrdersToCreate = []*exchangetypes.SpotOrder{spot_order}
    msg.DerivativeOrdersToCreate = []*exchangetypes.DerivativeOrder{derivative_order}
    msg.SpotMarketIdsToCancelAll = smarketIds
    msg.DerivativeMarketIdsToCancelAll = dmarketIds

    simRes, err := chainClient.SimulateMsg(clientCtx, msg)

    if err != nil {
        fmt.Println(err)
        return
    }

    MsgBatchUpdateOrdersResponse := exchangetypes.MsgBatchUpdateOrdersResponse{}
    MsgBatchUpdateOrdersResponse.Unmarshal(simRes.Result.MsgResponses[0].Value)

    fmt.Println("simulated spot order hashes", MsgBatchUpdateOrdersResponse.SpotOrderHashes)

    fmt.Println("simulated derivative order hashes", MsgBatchUpdateOrdersResponse.DerivativeOrderHashes)

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    err = chainClient.QueueBroadcastMsg(msg)

    if err != nil {
        fmt.Println(err)
        return
    }

    time.Sleep(time.Second * 5)

    gasFee, err := chainClient.GetGasFee()

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("gas fee:", gasFee, "INJ")
}
ParameterTypeDescriptionRequired
senderStringThe message sender's addressYes
subaccount_idStringThe subaccount ID is only used for the spot_market_ids_to_cancel_all and derivative_market_ids_to_cancel_allNo
spot_market_ids_to_cancel_allString ArrayList of unique market IDs to cancel all subaccount_id ordersNo
derivative_market_ids_to_cancel_allString ArrayList of unique market IDs to cancel all subaccount_id ordersNo
spot_orders_to_cancelOrderData ArrayList of spot orders to be cancelledNo
derivative_orders_to_cancelOrderData ArrayList of derivative orders to be cancelledNo
spot_orders_to_createSpotOrder ArrayList of spot orders to be createdNo
derivative_orders_to_createDerivativeOrder ArrayList of derivative orders to be createdNo
binary_options_orders_to_cancelOrderData ArrayList of binary options orders to be cancelledNo
binary_options_market_ids_to_cancel_allString ArrayList of unique market IDs to cancel all subaccount_id ordersNo
binary_options_orders_to_createDerivativeOrder ArrayList of binary options orders to be createdNo


OrderData

ParameterTypeDescriptionRequired
market_idStringThe order's market IDYes
subaccount_idStringSubaccount ID that created the orderYes
order_hashStringThe order hash (either the order_hash or the cid should be provided)No
order_maskOrderMaskThe order mask that specifies the order typeNo
cidStringThe order's client order ID (either the order_hash or the cid should be provided)No


SpotOrder

ParameterTypeDescriptionRequired
market_idStringThe unique ID of the marketYes
order_infoOrderInfoOrder's informationYes
order_typeOrderTypeThe order typeYes
trigger_priceDecimalThe trigger price used by stop/take ordersNo


DerivativeOrder

ParameterTypeDescriptionRequired
market_idStringThe unique ID of the marketYes
order_infoOrderInfoOrder's informationYes
order_typeOrderTypeThe order typeYes
marginDecimalThe margin amount used by the orderYes
trigger_priceDecimalThe trigger price used by stop/take ordersNo


OrderMask

CodeName
0OrderMask_UNUSED
1OrderMask_ANY
2OrderMask_REGULAR
4OrderMask_CONDITIONAL
8OrderMask_BUY_OR_HIGHER
16OrderMask_SELL_OR_LOWER
32OrderMask_MARKET
64OrderMask_LIMIT


OrderInfo

ParameterTypeDescriptionRequired
subaccount_idStringSubaccount ID that created the orderYes
fee_recipientStringAddress that will receive fees for the orderNo
priceDecimalPrice of the orderYes
quantityDecimalQuantity of the orderYes
cidStringClient order ID. An optional identifier for the order set by the creatorNo


OrderType

CodeName
0UNSPECIFIED
1BUY
2SELL
3STOP_BUY
4STOP_SELL
5TAKE_BUY
6TAKE_SELL
7BUY_PO
8SELL_PO
9BUY_ATOMIC
10SELL_ATOMIC

Response Parameters

Response Example:

---Simulation Response---
[spot_cancel_success: false
spot_cancel_success: false
derivative_cancel_success: false
derivative_cancel_success: false
spot_order_hashes: "0x3f5b5de6ec72b250c58e0a83408dbc1990cee369999036e3469e19b80fa9002e"
spot_order_hashes: "0x7d8580354e120b038967a180f73bc3aba0f49db9b6d2cb5c4cec85e8cab3e218"
derivative_order_hashes: "0x920a4ea4144c46d1e1084ca5807e4f5608639ce00f97139d5b44e628d487e15e"
derivative_order_hashes: "0x11d75d0c2ce8a07f352523be2e3456212c623397d0fc1a2f688b97a15c04372c"
]
---Transaction Response---
txhash: "4E29226884DCA22E127471588F39E0BB03D314E1AA27ECD810D24C4078D52DED"
raw_log: "[]"

gas wanted: 271213
gas fee: 0.0001356065 INJ
simulated spot order hashes [0xd9f30c7e700202615c2775d630b9fb276572d883fa480b6394abbddcb79c8109]
simulated derivative order hashes [0xb2bea3b15c204699a9ee945ca49650001560518d1e54266adac580aa061fedd4]
DEBU[0001] broadcastTx with nonce 3507                   fn=func1 src="client/chain/chain.go:598"
DEBU[0003] msg batch committed successfully at height 5214679  fn=func1 src="client/chain/chain.go:619" txHash=CF53E0B31B9E28E0D6D8F763ECEC2D91E38481321EA24AC86F6A8774C658AF44
DEBU[0003] nonce incremented to 3508                     fn=func1 src="client/chain/chain.go:623"
DEBU[0003] gas wanted:  659092                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.000329546 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

- IBC Core Channel

Includes all the messages and queries associated to channels from the IBC core channel module

Channel

Queries an IBC Channel

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    port_id = "transfer"
    channel_id = "channel-126"

    channel = await client.fetch_ibc_channel(port_id=port_id, channel_id=channel_id)
    print(channel)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    portId := "transfer"
    channelId := "channel-126"
    ctx := context.Background()

    res, err := chainClient.FetchIBCChannel(ctx, portId, channelId)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
port_idStringPort unique identifierYes
channel_idStringChannel unique identifierYes

Response Parameters

Response Example:

{
   "channel":{
      "state":"STATE_OPEN",
      "ordering":"ORDER_UNORDERED",
      "counterparty":{
         "portId":"transfer",
         "channelId":"channel-352"
      },
      "connectionHops":[
         "connection-173"
      ],
      "version":"ics20-1"
   },
   "proofHeight":{
      "revisionNumber":"888",
      "revisionHeight":"26820151"
   },
   "proof":""
}
ParameterTypeDescription
channelChannelChannel details
proofByte ArrayMerkle proof of existence
proof_heightHeightHeight at which the proof was retrieved


Channel

ParameterTypeDescription
stateStateCurrent state of the channel end
orderingOrderWhether the channel is ordered or unordered
counterpartyCounterpartyCounterparty channel end
connection_hopsString ArrayList of connection identifiers, in order, along which packets sent on this channel will travel
versionStringOpaque channel version, which is agreed upon during the handshake
upgrade_sequenceIntegerIndicates the latest upgrade attempt performed by this channel. The value of 0 indicates the channel has never been upgraded


State

CodeName
0STATE_UNINITIALIZED_UNSPECIFIED
1STATE_INIT
2STATE_TRYOPEN
3STATE_OPEN
4STATE_CLOSED


Order

CodeName
0ORDER_NONE_UNSPECIFIED
1ORDER_UNORDERED
2ORDER_ORDERED


Counterparty

ParameterTypeDescription
port_idStringPort on the counterparty chain which owns the other end of the channel
channel_idStringChannel end on the counterparty chain


Height

ParameterTypeDescription
revision_numberIntegerThe revision that the client is currently on
revision_heightIntegerThe height within the given revision

Channels

Queries all the IBC channels of a chain

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    pagination = PaginationOption(skip=2, limit=4)

    channels = await client.fetch_ibc_channels(pagination=pagination)
    print(channels)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/cosmos/cosmos-sdk/types/query"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    pagination := query.PageRequest{Offset: 2, Limit: 4}
    ctx := context.Background()

    res, err := chainClient.FetchIBCChannels(ctx, &pagination)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
paginationPageRequestThe optional pagination for the requestNo


PageRequest

ParameterTypeDescriptionRequired
keyByte ArrayKey is a value returned in PageResponse.next_key to begin querying the next page most efficiently. Only one of offset or key should be setNo
offsetIntegerNumeric offset that can be used when key is unavailable. It is less efficient than using key. Only one of offset or key should be setNo
limitIntegerTotal number of results to be returned in the result pageNo
count_totalBooleanSet to true to indicate that the result set should include a count of the total number of items available for pagination in UIs. It is only respected when offset is used. It is ignored when key is setNo
reverseBooleanReverse is set to true if results are to be returned in the descending orderNo

Response Parameters

Response Example:

{
   "channels":[
      {
         "state":"STATE_OPEN",
         "ordering":"ORDER_ORDERED",
         "counterparty":{
            "portId":"icacontroller-sweep-inj",
            "channelId":"channel-19"
         },
         "connectionHops":[
            "connection-182"
         ],
         "version":"{\"version\":\"ics27-1\",\"controller_connection_id\":\"connection-9\",\"host_connection_id\":\"connection-182\",\"address\":\"inj1v0es67dxtlmzmauhr3krk058sp9cvt6e2hvmys2g8pjnpj30fezq93qp07\",\"encoding\":\"proto3\",\"tx_type\":\"sdk_multi_msg\"}",
         "portId":"icahost",
         "channelId":"channel-134"
      },
      {
         "state":"STATE_CLOSED",
         "ordering":"ORDER_ORDERED",
         "counterparty":{
            "portId":"icacontroller-delegation-inj",
            "channelId":"channel-20"
         },
         "connectionHops":[
            "connection-182"
         ],
         "version":"{\"version\":\"ics27-1\",\"controller_connection_id\":\"connection-9\",\"host_connection_id\":\"connection-182\",\"address\":\"inj1urqc59ft3hl75mxhru4848xusu5rhpghz48zdfypyuu923w2gzyqm8y02d\",\"encoding\":\"proto3\",\"tx_type\":\"sdk_multi_msg\"}",
         "portId":"icahost",
         "channelId":"channel-136"
      },
      {
         "state":"STATE_OPEN",
         "ordering":"ORDER_ORDERED",
         "counterparty":{
            "portId":"icacontroller-sweep-inj",
            "channelId":"channel-21"
         },
         "connectionHops":[
            "connection-185"
         ],
         "version":"{\"version\":\"ics27-1\",\"controller_connection_id\":\"connection-3\",\"host_connection_id\":\"connection-185\",\"address\":\"inj1s58qfzwjduykz6emh936v8uxytvck4cf0lkvpuerh2qwt6jkaj9qh9cl7x\",\"encoding\":\"proto3\",\"tx_type\":\"sdk_multi_msg\"}",
         "portId":"icahost",
         "channelId":"channel-182"
      },
      {
         "state":"STATE_OPEN",
         "ordering":"ORDER_ORDERED",
         "counterparty":{
            "portId":"icacontroller-reward-inj",
            "channelId":"channel-20"
         },
         "connectionHops":[
            "connection-185"
         ],
         "version":"{\"version\":\"ics27-1\",\"controller_connection_id\":\"connection-3\",\"host_connection_id\":\"connection-185\",\"address\":\"inj1k3cdwxqkjmmjn62tesyumlynj0n5ap2k9ysnyn56zar4uns09a5qvy575s\",\"encoding\":\"proto3\",\"tx_type\":\"sdk_multi_msg\"}",
         "portId":"icahost",
         "channelId":"channel-183"
      }
   ],
   "pagination":{
      "nextKey":"L3BvcnRzL2ljYWhvc3QvY2hhbm5lbHMvY2hhbm5lbC0xODQ=",
      "total":"0"
   },
   "height":{
      "revisionNumber":"888",
      "revisionHeight":"26823064"
   }
}
ParameterTypeDescription
channelsIdentifiedChannel ArrayList of channels
paginationPageResponsePagination information in the response
heightHeightQuery block height


IdentifiedChannel

ParameterTypeDescription
stateStateCurrent state of the channel end
orderingOrderWhether the channel is ordered or unordered
counterpartyCounterpartyCounterparty channel end
connection_hopsString ArrayList of connection identifiers, in order, along which packets sent on this channel will travel
versionStringOpaque channel version, which is agreed upon during the handshake
port_idStringPort identifier
channel_idStringChannel identifier
upgrade_sequenceIntegerIndicates the latest upgrade attempt performed by this channel. The value of 0 indicates the channel has never been upgraded


State

CodeName
0STATE_UNINITIALIZED_UNSPECIFIED
1STATE_INIT
2STATE_TRYOPEN
3STATE_OPEN
4STATE_CLOSED


Order

CodeName
0ORDER_NONE_UNSPECIFIED
1ORDER_UNORDERED
2ORDER_ORDERED


Counterparty

ParameterTypeDescription
port_idStringPort on the counterparty chain which owns the other end of the channel
channel_idStringChannel end on the counterparty chain


PageResponse

ParameterTypeDescription
next_keyByte ArrayThe key to be passed to PageRequest.key to query the next page most efficiently. It will be empty if there are no more results.
totalIntegerTotal number of results available if PageRequest.count_total was set, its value is undefined otherwise


Height

ParameterTypeDescription
revision_numberIntegerThe revision that the client is currently on
revision_heightIntegerThe height within the given revision

ConnectionChannels

Queries all the channels associated with a connection end

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    connection = "connection-182"
    pagination = PaginationOption(skip=2, limit=4)

    channels = await client.fetch_ibc_connection_channels(connection=connection, pagination=pagination)
    print(channels)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/cosmos/cosmos-sdk/types/query"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    connection := "connection-182"
    pagination := query.PageRequest{Offset: 2, Limit: 4}
    ctx := context.Background()

    res, err := chainClient.FetchIBCConnectionChannels(ctx, connection, &pagination)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
connectionStringConnection unique identifierYes
paginationPageRequestThe optional pagination for the requestNo


PageRequest

ParameterTypeDescriptionRequired
keyByte ArrayKey is a value returned in PageResponse.next_key to begin querying the next page most efficiently. Only one of offset or key should be setNo
offsetIntegerNumeric offset that can be used when key is unavailable. It is less efficient than using key. Only one of offset or key should be setNo
limitIntegerTotal number of results to be returned in the result pageNo
count_totalBooleanSet to true to indicate that the result set should include a count of the total number of items available for pagination in UIs. It is only respected when offset is used. It is ignored when key is setNo
reverseBooleanReverse is set to true if results are to be returned in the descending orderNo

Response Parameters

Response Example:

{
   "channels":[
      {
         "state":"STATE_CLOSED",
         "ordering":"ORDER_ORDERED",
         "counterparty":{
            "portId":"icacontroller-delegation-inj",
            "channelId":"channel-17"
         },
         "connectionHops":[
            "connection-182"
         ],
         "version":"{\"version\":\"ics27-1\",\"controller_connection_id\":\"connection-9\",\"host_connection_id\":\"connection-182\",\"address\":\"inj1urqc59ft3hl75mxhru4848xusu5rhpghz48zdfypyuu923w2gzyqm8y02d\",\"encoding\":\"proto3\",\"tx_type\":\"sdk_multi_msg\"}",
         "portId":"icahost",
         "channelId":"channel-132"
      },
      {
         "state":"STATE_OPEN",
         "ordering":"ORDER_ORDERED",
         "counterparty":{
            "portId":"icacontroller-reward-inj",
            "channelId":"channel-18"
         },
         "connectionHops":[
            "connection-182"
         ],
         "version":"{\"version\":\"ics27-1\",\"controller_connection_id\":\"connection-9\",\"host_connection_id\":\"connection-182\",\"address\":\"inj1mn3p9d2aw02mdrkfhleefmvr70skrx39mlkkc4f5rnewlc5aux3qs37nt6\",\"encoding\":\"proto3\",\"tx_type\":\"sdk_multi_msg\"}",
         "portId":"icahost",
         "channelId":"channel-133"
      },
      {
         "state":"STATE_OPEN",
         "ordering":"ORDER_ORDERED",
         "counterparty":{
            "portId":"icacontroller-sweep-inj",
            "channelId":"channel-19"
         },
         "connectionHops":[
            "connection-182"
         ],
         "version":"{\"version\":\"ics27-1\",\"controller_connection_id\":\"connection-9\",\"host_connection_id\":\"connection-182\",\"address\":\"inj1v0es67dxtlmzmauhr3krk058sp9cvt6e2hvmys2g8pjnpj30fezq93qp07\",\"encoding\":\"proto3\",\"tx_type\":\"sdk_multi_msg\"}",
         "portId":"icahost",
         "channelId":"channel-134"
      },
      {
         "state":"STATE_CLOSED",
         "ordering":"ORDER_ORDERED",
         "counterparty":{
            "portId":"icacontroller-delegation-inj",
            "channelId":"channel-20"
         },
         "connectionHops":[
            "connection-182"
         ],
         "version":"{\"version\":\"ics27-1\",\"controller_connection_id\":\"connection-9\",\"host_connection_id\":\"connection-182\",\"address\":\"inj1urqc59ft3hl75mxhru4848xusu5rhpghz48zdfypyuu923w2gzyqm8y02d\",\"encoding\":\"proto3\",\"tx_type\":\"sdk_multi_msg\"}",
         "portId":"icahost",
         "channelId":"channel-136"
      },
      {
         "state":"STATE_OPEN",
         "ordering":"ORDER_UNORDERED",
         "counterparty":{
            "portId":"transfer",
            "channelId":"channel-16"
         },
         "connectionHops":[
            "connection-182"
         ],
         "version":"ics20-1",
         "portId":"transfer",
         "channelId":"channel-131"
      }
   ],
   "pagination":{
      "nextKey":"",
      "total":"0"
   },
   "height":{
      "revisionNumber":"888",
      "revisionHeight":"26832162"
   }
}
ParameterTypeDescription
channelsIdentifiedChannel ArrayList of channels
paginationPageResponsePagination information in the response
heightHeightQuery block height


IdentifiedChannel

ParameterTypeDescription
stateStateCurrent state of the channel end
orderingOrderWhether the channel is ordered or unordered
counterpartyCounterpartyCounterparty channel end
connection_hopsString ArrayList of connection identifiers, in order, along which packets sent on this channel will travel
versionStringOpaque channel version, which is agreed upon during the handshake
port_idStringPort identifier
channel_idStringChannel identifier
upgrade_sequenceIntegerIndicates the latest upgrade attempt performed by this channel. The value of 0 indicates the channel has never been upgraded


State

CodeName
0STATE_UNINITIALIZED_UNSPECIFIED
1STATE_INIT
2STATE_TRYOPEN
3STATE_OPEN
4STATE_CLOSED


Order

CodeName
0ORDER_NONE_UNSPECIFIED
1ORDER_UNORDERED
2ORDER_ORDERED


Counterparty

ParameterTypeDescription
port_idStringPort on the counterparty chain which owns the other end of the channel
channel_idStringChannel end on the counterparty chain


PageResponse

ParameterTypeDescription
next_keyByte ArrayThe key to be passed to PageRequest.key to query the next page most efficiently. It will be empty if there are no more results.
totalIntegerTotal number of results available if PageRequest.count_total was set, its value is undefined otherwise


Height

ParameterTypeDescription
revision_numberIntegerThe revision that the client is currently on
revision_heightIntegerThe height within the given revision

ChannelClientState

Queries the client state for the channel associated with the provided channel identifiers

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    port_id = "transfer"
    channel_id = "channel-126"

    state = await client.fetch_ibc_channel_client_state(port_id=port_id, channel_id=channel_id)
    print(state)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    portId := "transfer"
    channelId := "channel-126"
    ctx := context.Background()

    res, err := chainClient.FetchIBCChannelClientState(ctx, portId, channelId)
    if err != nil {
        fmt.Println(err)
    }

    fmt.Print(res)

}
ParameterTypeDescriptionRequired
port_idStringPort unique identifierYes
channel_idStringChannel unique identifierYes

Response Parameters

Response Example:

{
   "identifiedClientState":{
      "clientId":"07-tendermint-179",
      "clientState":{
         "@type":"/ibc.lightclients.tendermint.v1.ClientState",
         "chainId":"pisco-1",
         "trustLevel":{
            "numerator":"1",
            "denominator":"3"
         },
         "trustingPeriod":"288000s",
         "unbondingPeriod":"432000s",
         "maxClockDrift":"40s",
         "frozenHeight":{
            "revisionNumber":"0",
            "revisionHeight":"0"
         },
         "latestHeight":{
            "revisionNumber":"1",
            "revisionHeight":"7990906"
         },
         "proofSpecs":[
            {
               "leafSpec":{
                  "hash":"SHA256",
                  "prehashValue":"SHA256",
                  "length":"VAR_PROTO",
                  "prefix":"AA==",
                  "prehashKey":"NO_HASH"
               },
               "innerSpec":{
                  "childOrder":[
                     0,
                     1
                  ],
                  "childSize":33,
                  "minPrefixLength":4,
                  "maxPrefixLength":12,
                  "hash":"SHA256",
                  "emptyChild":""
               },
               "maxDepth":0,
               "minDepth":0,
               "prehashKeyBeforeComparison":false
            },
            {
               "leafSpec":{
                  "hash":"SHA256",
                  "prehashValue":"SHA256",
                  "length":"VAR_PROTO",
                  "prefix":"AA==",
                  "prehashKey":"NO_HASH"
               },
               "innerSpec":{
                  "childOrder":[
                     0,
                     1
                  ],
                  "childSize":32,
                  "minPrefixLength":1,
                  "maxPrefixLength":1,
                  "hash":"SHA256",
                  "emptyChild":""
               },
               "maxDepth":0,
               "minDepth":0,
               "prehashKeyBeforeComparison":false
            }
         ],
         "upgradePath":[
            "upgrade",
            "upgradedIBCState"
         ],
         "allowUpdateAfterExpiry":true,
         "allowUpdateAfterMisbehaviour":true
      }
   },
   "proofHeight":{
      "revisionNumber":"888",
      "revisionHeight":"26834667"
   },
   "proof":""
}
ParameterTypeDescription
identified_client_stateIdentifiedChannelClient state associated with the channel
proofByte ArrayMerkle proof of existence
proof_heightHeightHeight at which the proof was retrieved


IdentifiedChannel

ParameterTypeDescription
stateStateCurrent state of the channel end
orderingOrderWhether the channel is ordered or unordered
counterpartyCounterpartyCounterparty channel end
connection_hopsString ArrayList of connection identifiers, in order, along which packets sent on this channel will travel
versionStringOpaque channel version, which is agreed upon during the handshake
port_idStringPort identifier
channel_idStringChannel identifier
upgrade_sequenceIntegerIndicates the latest upgrade attempt performed by this channel. The value of 0 indicates the channel has never been upgraded


State

CodeName
0STATE_UNINITIALIZED_UNSPECIFIED
1STATE_INIT
2STATE_TRYOPEN
3STATE_OPEN
4STATE_CLOSED


Order

CodeName
0ORDER_NONE_UNSPECIFIED
1ORDER_UNORDERED
2ORDER_ORDERED


Counterparty

ParameterTypeDescription
port_idStringPort on the counterparty chain which owns the other end of the channel
channel_idStringChannel end on the counterparty chain


Height

ParameterTypeDescription
revision_numberIntegerThe revision that the client is currently on
revision_heightIntegerThe height within the given revision

ChannelConsensusState

Queries the client state for the channel associated with the provided channel identifiers

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    port_id = "transfer"
    channel_id = "channel-126"
    revision_number = 1
    revision_height = 7990906

    state = await client.fetch_ibc_channel_consensus_state(
        port_id=port_id, channel_id=channel_id, revision_number=revision_number, revision_height=revision_height
    )
    print(state)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    portId := "transfer"
    channelId := "channel-126"
    revisionNumber := uint64(1)
    revisionHeight := uint64(7990906)
    ctx := context.Background()

    res, err := chainClient.FetchIBCChannelConsensusState(ctx, portId, channelId, revisionNumber, revisionHeight)
    if err != nil {
        fmt.Println(err)
    }

    fmt.Print(res)

}
ParameterTypeDescriptionRequired
port_idStringPort unique identifierYes
channel_idStringChannel unique identifierYes
revision_numberIntegerRevision number of the consensus stateYes
revision_heightIntegerRevision height of the consensus stateYes

Response Parameters

Response Example:

{
   "consensusState":{
      "@type":"/ibc.lightclients.tendermint.v1.ConsensusState",
      "timestamp":"2023-10-21T14:57:23.344911848Z",
      "root":{
         "hash":"89ggv/9AgSoyCBZ0ohhBSMI0LX+ZYe24VdUOA1x6i6I="
      },
      "nextValidatorsHash":"8DzvA/mMhLfz2C0qSK5+YtbfTopxfFpKm4kApB/u10Y="
   },
   "clientId":"07-tendermint-179",
   "proofHeight":{
      "revisionNumber":"888",
      "revisionHeight":"26835676"
   },
   "proof":""
}
ParameterTypeDescription
consensus_stateAnyConsensus state associated with the channel
client_idStringClient ID associated with the consensus state
proofByte ArrayMerkle proof of existence
proof_heightHeightHeight at which the proof was retrieved


Height

ParameterTypeDescription
revision_numberIntegerThe revision that the client is currently on
revision_heightIntegerThe height within the given revision

PacketCommitment

Queries a stored packet commitment hash

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    port_id = "transfer"
    channel_id = "channel-126"
    sequence = 1

    commitment = await client.fetch_ibc_packet_commitment(port_id=port_id, channel_id=channel_id, sequence=sequence)
    print(commitment)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    portId := "transfer"
    channelId := "channel-126"
    sequence := uint64(1)
    ctx := context.Background()

    res, err := chainClient.FetchIBCPacketCommitment(ctx, portId, channelId, sequence)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
port_idStringPort unique identifierYes
channel_idStringChannel unique identifierYes
sequenceIntegerPacket sequenceYes

Response Parameters

Response Example:

{
   "commitment":"bIKl7JAqoA1IGSDDlb0McwW2A/A77Jpph0yt87BnCO4=",
   "proofHeight":{
      "revisionNumber":"888",
      "revisionHeight":"26836334"
   },
   "proof":""
}
ParameterTypeDescription
commitmentByte ArrayPacket associated with the request fields
proofByte ArrayMerkle proof of existence
proof_heightHeightHeight at which the proof was retrieved


Height

ParameterTypeDescription
revision_numberIntegerThe revision that the client is currently on
revision_heightIntegerThe height within the given revision

PacketCommitments

Returns all the packet commitments hashes associated with a channel

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    port_id = "transfer"
    channel_id = "channel-126"
    pagination = PaginationOption(skip=2, limit=4)

    commitment = await client.fetch_ibc_packet_commitments(
        port_id=port_id,
        channel_id=channel_id,
        pagination=pagination,
    )
    print(commitment)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/cosmos/cosmos-sdk/types/query"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    portId := "transfer"
    channelId := "channel-126"
    pagination := query.PageRequest{Offset: 2, Limit: 4}
    ctx := context.Background()

    res, err := chainClient.FetchIBCPacketCommitments(ctx, portId, channelId, &pagination)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
port_idStringPort unique identifierYes
channel_idStringChannel unique identifierYes
paginationPageRequestThe optional pagination for the requestNo

Response Parameters

Response Example:

{
   "commitments":[
      {
         "portId":"transfer",
         "channelId":"channel-126",
         "sequence":"100",
         "data":"CMcjhUhXioc12WQEv+SVK7pdCdBei9Zw2MNyKm64aII="
      },
      {
         "portId":"transfer",
         "channelId":"channel-126",
         "sequence":"101",
         "data":"hUdJyOfw9Y4X6IqtcZNwOy9vvkir2SK6MGlhqn6gF7w="
      },
      {
         "portId":"transfer",
         "channelId":"channel-126",
         "sequence":"102",
         "data":"pi3qUxhzyDrgmrTHMu+9AW3vEsGBl1W6YUsEgi/UCwo="
      },
      {
         "portId":"transfer",
         "channelId":"channel-126",
         "sequence":"103",
         "data":"eDSZipO0vWlCEzM5sS2DNL254KBMSMH5JZn0u5ccIIs="
      }
   ],
   "pagination":{
      "nextKey":"LzEwNA==",
      "total":"0"
   },
   "height":{
      "revisionNumber":"888",
      "revisionHeight":"26836728"
   }
}
ParameterTypeDescription
commitmentsPacketState ArrayCommitments information
paginationPageResponsePagination information in the response
heightHeightQuery block height


PacketState

ParameterTypeDescription
port_idStringPort identifier
channel_idStringChannel identifier
sequenceIntegerPacket sequence
dataByte ArrayEmbedded data that represents packet state


PageResponse

ParameterTypeDescription
next_keyByte ArrayThe key to be passed to PageRequest.key to query the next page most efficiently. It will be empty if there are no more results.
totalIntegerTotal number of results available if PageRequest.count_total was set, its value is undefined otherwise


Height

ParameterTypeDescription
revision_numberIntegerThe revision that the client is currently on
revision_heightIntegerThe height within the given revision

PacketReceipt

Queries if a given packet sequence has been received on the queried chain

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    port_id = "transfer"
    channel_id = "channel-126"
    sequence = 1

    receipt = await client.fetch_ibc_packet_receipt(port_id=port_id, channel_id=channel_id, sequence=sequence)
    print(receipt)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    portId := "transfer"
    channelId := "channel-126"
    sequence := uint64(1)
    ctx := context.Background()

    res, err := chainClient.FetchIBCPacketReceipt(ctx, portId, channelId, sequence)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
port_idStringPort unique identifierYes
channel_idStringChannel unique identifierYes
sequenceIntegerPacket sequenceYes

Response Parameters

Response Example:

{
   "received":true,
   "proofHeight":{
      "revisionNumber":"888",
      "revisionHeight":"27058834"
   },
   "proof":""
}
ParameterTypeDescription
receivedBooleanSuccess flag to mark if the receipt exists
proofByte ArrayMerkle proof of existence
proof_heightHeightHeight at which the proof was retrieved


Height

ParameterTypeDescription
revision_numberIntegerThe revision that the client is currently on
revision_heightIntegerThe height within the given revision

PacketAcknowledgement

Queries a stored packet acknowledgement hash

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    port_id = "transfer"
    channel_id = "channel-126"
    sequence = 1

    acknowledgement = await client.fetch_ibc_packet_acknowledgement(
        port_id=port_id, channel_id=channel_id, sequence=sequence
    )
    print(acknowledgement)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    portId := "transfer"
    channelId := "channel-126"
    sequence := uint64(1)
    ctx := context.Background()

    res, err := chainClient.FetchIBCPacketAcknowledgement(ctx, portId, channelId, sequence)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
port_idStringPort unique identifierYes
channel_idStringChannel unique identifierYes
sequenceIntegerPacket sequenceYes

Response Parameters

Response Example:

{
   "acknowledgement":"CPdVftUYJv4Y2EUSvyTsdQAe268hI6R333KgqfNkCnw=",
   "proofHeight":{
      "revisionNumber":"888",
      "revisionHeight":"27065978"
   },
   "proof":""
}
ParameterTypeDescription
acknowledgementByte ArraySuccess flag to mark if the receipt exists
proofByte ArrayMerkle proof of existence
proof_heightHeightHeight at which the proof was retrieved


Height

ParameterTypeDescription
revision_numberIntegerThe revision that the client is currently on
revision_heightIntegerThe height within the given revision

PacketAcknowledgements

Returns all the packet acknowledgements associated with a channel

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    port_id = "transfer"
    channel_id = "channel-126"
    sequences = [1, 2]
    pagination = PaginationOption(skip=2, limit=4)

    acknowledgements = await client.fetch_ibc_packet_acknowledgements(
        port_id=port_id,
        channel_id=channel_id,
        packet_commitment_sequences=sequences,
        pagination=pagination,
    )
    print(acknowledgements)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/cosmos/cosmos-sdk/types/query"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    portId := "transfer"
    channelId := "channel-126"
    sequences := []uint64{1, 2}
    pagination := query.PageRequest{Offset: 2, Limit: 4}
    ctx := context.Background()

    res, err := chainClient.FetchIBCPacketAcknowledgements(ctx, portId, channelId, sequences, &pagination)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
port_idStringPort unique identifierYes
channel_idStringChannel unique identifierYes
paginationPageRequestThe optional pagination for the requestNo
packet_commitment_sequencesInteger ArrayList of packet sequencesNo


PageRequest

ParameterTypeDescriptionRequired
keyByte ArrayKey is a value returned in PageResponse.next_key to begin querying the next page most efficiently. Only one of offset or key should be setNo
offsetIntegerNumeric offset that can be used when key is unavailable. It is less efficient than using key. Only one of offset or key should be setNo
limitIntegerTotal number of results to be returned in the result pageNo
count_totalBooleanSet to true to indicate that the result set should include a count of the total number of items available for pagination in UIs. It is only respected when offset is used. It is ignored when key is setNo
reverseBooleanReverse is set to true if results are to be returned in the descending orderNo

Response Parameters

Response Example:

{
   "acknowledgements":[
      {
         "portId":"transfer",
         "channelId":"channel-126",
         "sequence":"1",
         "data":"CPdVftUYJv4Y2EUSvyTsdQAe268hI6R333KgqfNkCnw="
      },
      {
         "portId":"transfer",
         "channelId":"channel-126",
         "sequence":"2",
         "data":"CPdVftUYJv4Y2EUSvyTsdQAe268hI6R333KgqfNkCnw="
      }
   ],
   "height":{
      "revisionNumber":"888",
      "revisionHeight":"27066401"
   }
}
ParameterTypeDescription
acknowledgementsPacketState ArrayAcknowledgements details
paginationPageResponsePagination information in the response
heightHeightQuery block height

PacketState

ParameterTypeDescription
port_idStringPort identifier
channel_idStringChannel identifier
sequenceIntegerPacket sequence
dataByte ArrayEmbedded data that represents packet state


PageResponse

ParameterTypeDescription
next_keyByte ArrayThe key to be passed to PageRequest.key to query the next page most efficiently. It will be empty if there are no more results.
totalIntegerTotal number of results available if PageRequest.count_total was set, its value is undefined otherwise


Height

ParameterTypeDescription
revision_numberIntegerThe revision that the client is currently on
revision_heightIntegerThe height within the given revision

UnreceivedPackets

Returns all the unreceived IBC packets associated with a channel and sequences

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    port_id = "transfer"
    channel_id = "channel-126"
    sequences = [1, 2]

    packets = await client.fetch_ibc_unreceived_packets(
        port_id=port_id, channel_id=channel_id, packet_commitment_sequences=sequences
    )
    print(packets)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    portId := "transfer"
    channelId := "channel-126"
    sequences := []uint64{1, 2}
    ctx := context.Background()

    res, err := chainClient.FetchIBCUnreceivedPackets(ctx, portId, channelId, sequences)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
port_idStringPort unique identifierYes
channel_idStringChannel unique identifierYes
packet_commitment_sequencesInteger ArrayList of packet sequencesNo

Response Parameters

Response Example:

{
   "height":{
      "revisionNumber":"888",
      "revisionHeight":"27067282"
   },
   "sequences":[

   ]
}
ParameterTypeDescription
sequencesInteger ArrayList of unreceived packet sequences
heightHeightQuery block height


Height

ParameterTypeDescription
revision_numberIntegerThe revision that the client is currently on
revision_heightIntegerThe height within the given revision

UnreceivedAcks

Returns all the unreceived IBC acknowledgements associated with a channel and sequences

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    port_id = "transfer"
    channel_id = "channel-126"

    acks = await client.fetch_ibc_unreceived_acks(
        port_id=port_id,
        channel_id=channel_id,
    )
    print(acks)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    portId := "transfer"
    channelId := "channel-126"
    sequences := []uint64{1, 2}
    ctx := context.Background()

    res, err := chainClient.FetchIBCUnreceivedAcks(ctx, portId, channelId, sequences)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
port_idStringPort unique identifierYes
channel_idStringChannel unique identifierYes
packet_ack_sequencesInteger ArrayList of acknowledgement sequencesNo

Response Parameters

Response Example:

{
   "height":{
      "revisionNumber":"888",
      "revisionHeight":"27067653"
   },
   "sequences":[

   ]
}
ParameterTypeDescription
sequencesInteger ArrayList of unreceived packet sequences
heightHeightQuery block height


Height

ParameterTypeDescription
revision_numberIntegerThe revision that the client is currently on
revision_heightIntegerThe height within the given revision

NextSequenceReceive

Returns the next receive sequence for a given channel

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    port_id = "transfer"
    channel_id = "channel-126"

    sequence = await client.fetch_next_sequence_receive(
        port_id=port_id,
        channel_id=channel_id,
    )
    print(sequence)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    portId := "transfer"
    channelId := "channel-126"
    ctx := context.Background()

    res, err := chainClient.FetchIBCNextSequenceReceive(ctx, portId, channelId)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
port_idStringPort unique identifierYes
channel_idStringChannel unique identifierYes

Response Parameters

Response Example:

{
   "nextSequenceReceive":"1",
   "proofHeight":{
      "revisionNumber":"888",
      "revisionHeight":"27067952"
   },
   "proof":""
}
ParameterTypeDescription
next_sequence_receiveIntegerNext sequence receive number
proofByte ArrayMerkle proof of existence
proof_heightHeightHeight at which the proof was retrieved


Height

ParameterTypeDescription
revision_numberIntegerThe revision that the client is currently on
revision_heightIntegerThe height within the given revision

- IBC Core Client

Includes all the messages and queries associated to clients and consensus from the IBC core client module

ClientState

Queries an IBC light client

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    client_id = "07-tendermint-0"

    state = await client.fetch_ibc_client_state(client_id=client_id)
    print(state)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    clientId := "07-tendermint-0"
    ctx := context.Background()

    res, err := chainClient.FetchIBCClientState(ctx, clientId)
    if err != nil {
        fmt.Println(err)
    }

    fmt.Print(res)

}
ParameterTypeDescriptionRequired
client_idStringClient state unique identifierYes

Response Parameters

Response Example:

{
   "clientState":{
      "@type":"/ibc.lightclients.tendermint.v1.ClientState",
      "chainId":"band-laozi-testnet4",
      "trustLevel":{
         "numerator":"1",
         "denominator":"3"
      },
      "trustingPeriod":"1209600s",
      "unbondingPeriod":"1814400s",
      "maxClockDrift":"20s",
      "frozenHeight":{
         "revisionNumber":"0",
         "revisionHeight":"0"
      },
      "latestHeight":{
         "revisionHeight":"7379538",
         "revisionNumber":"0"
      },
      "proofSpecs":[
         {
            "leafSpec":{
               "hash":"SHA256",
               "prehashValue":"SHA256",
               "length":"VAR_PROTO",
               "prefix":"AA==",
               "prehashKey":"NO_HASH"
            },
            "innerSpec":{
               "childOrder":[
                  0,
                  1
               ],
               "childSize":33,
               "minPrefixLength":4,
               "maxPrefixLength":12,
               "hash":"SHA256",
               "emptyChild":""
            },
            "maxDepth":0,
            "minDepth":0,
            "prehashKeyBeforeComparison":false
         },
         {
            "leafSpec":{
               "hash":"SHA256",
               "prehashValue":"SHA256",
               "length":"VAR_PROTO",
               "prefix":"AA==",
               "prehashKey":"NO_HASH"
            },
            "innerSpec":{
               "childOrder":[
                  0,
                  1
               ],
               "childSize":32,
               "minPrefixLength":1,
               "maxPrefixLength":1,
               "hash":"SHA256",
               "emptyChild":""
            },
            "maxDepth":0,
            "minDepth":0,
            "prehashKeyBeforeComparison":false
         }
      ],
      "upgradePath":[
         "upgrade",
         "upgradedIBCState"
      ],
      "allowUpdateAfterExpiry":true,
      "allowUpdateAfterMisbehaviour":true
   },
   "proofHeight":{
      "revisionNumber":"888",
      "revisionHeight":"27527237"
   },
   "proof":""
}
ParameterTypeDescription
client_stateAnyClient state associated with the request identifier
proofByte ArrayMerkle proof of existence
proof_heightHeightHeight at which the proof was retrieved


Height

ParameterTypeDescription
revision_numberIntegerThe revision that the client is currently on
revision_heightIntegerThe height within the given revision

ClientStates

Queries all the IBC light clients of a chain

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    pagination = PaginationOption(skip=2, limit=4)

    states = await client.fetch_ibc_client_states(pagination=pagination)
    print(states)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "fmt"

    "github.com/cosmos/cosmos-sdk/types/query"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    pagination := query.PageRequest{Offset: 2, Limit: 4}
    ctx := context.Background()

    res, err := chainClient.FetchIBCClientStates(ctx, &pagination)
    if err != nil {
        fmt.Println(err)
    }

    fmt.Print(res)

}
ParameterTypeDescriptionRequired
paginationPageRequestThe optional pagination for the requestNo

Response Parameters

Response Example:

{
   "clientStates":[
      {
         "clientId":"07-tendermint-0",
         "clientState":{
            "@type":"/ibc.lightclients.tendermint.v1.ClientState",
            "chainId":"band-laozi-testnet4",
            "trustLevel":{
               "numerator":"1",
               "denominator":"3"
            },
            "trustingPeriod":"1209600s",
            "unbondingPeriod":"1814400s",
            "maxClockDrift":"20s",
            "frozenHeight":{
               "revisionNumber":"0",
               "revisionHeight":"0"
            },
            "latestHeight":{
               "revisionHeight":"7379538",
               "revisionNumber":"0"
            },
            "proofSpecs":[
               {
                  "leafSpec":{
                     "hash":"SHA256",
                     "prehashValue":"SHA256",
                     "length":"VAR_PROTO",
                     "prefix":"AA==",
                     "prehashKey":"NO_HASH"
                  },
                  "innerSpec":{
                     "childOrder":[
                        0,
                        1
                     ],
                     "childSize":33,
                     "minPrefixLength":4,
                     "maxPrefixLength":12,
                     "hash":"SHA256",
                     "emptyChild":""
                  },
                  "maxDepth":0,
                  "minDepth":0,
                  "prehashKeyBeforeComparison":false
               },
               {
                  "leafSpec":{
                     "hash":"SHA256",
                     "prehashValue":"SHA256",
                     "length":"VAR_PROTO",
                     "prefix":"AA==",
                     "prehashKey":"NO_HASH"
                  },
                  "innerSpec":{
                     "childOrder":[
                        0,
                        1
                     ],
                     "childSize":32,
                     "minPrefixLength":1,
                     "maxPrefixLength":1,
                     "hash":"SHA256",
                     "emptyChild":""
                  },
                  "maxDepth":0,
                  "minDepth":0,
                  "prehashKeyBeforeComparison":false
               }
            ],
            "upgradePath":[
               "upgrade",
               "upgradedIBCState"
            ],
            "allowUpdateAfterExpiry":true,
            "allowUpdateAfterMisbehaviour":true
         }
      },
      {
         "clientId":"07-tendermint-1",
         "clientState":{
            "@type":"/ibc.lightclients.tendermint.v1.ClientState",
            "chainId":"band-laozi-testnet4",
            "trustLevel":{
               "numerator":"1",
               "denominator":"3"
            },
            "trustingPeriod":"1209600s",
            "unbondingPeriod":"1814400s",
            "maxClockDrift":"20s",
            "frozenHeight":{
               "revisionNumber":"0",
               "revisionHeight":"0"
            },
            "latestHeight":{
               "revisionHeight":"7692651",
               "revisionNumber":"0"
            },
            "proofSpecs":[
               {
                  "leafSpec":{
                     "hash":"SHA256",
                     "prehashValue":"SHA256",
                     "length":"VAR_PROTO",
                     "prefix":"AA==",
                     "prehashKey":"NO_HASH"
                  },
                  "innerSpec":{
                     "childOrder":[
                        0,
                        1
                     ],
                     "childSize":33,
                     "minPrefixLength":4,
                     "maxPrefixLength":12,
                     "hash":"SHA256",
                     "emptyChild":""
                  },
                  "maxDepth":0,
                  "minDepth":0,
                  "prehashKeyBeforeComparison":false
               },
               {
                  "leafSpec":{
                     "hash":"SHA256",
                     "prehashValue":"SHA256",
                     "length":"VAR_PROTO",
                     "prefix":"AA==",
                     "prehashKey":"NO_HASH"
                  },
                  "innerSpec":{
                     "childOrder":[
                        0,
                        1
                     ],
                     "childSize":32,
                     "minPrefixLength":1,
                     "maxPrefixLength":1,
                     "hash":"SHA256",
                     "emptyChild":""
                  },
                  "maxDepth":0,
                  "minDepth":0,
                  "prehashKeyBeforeComparison":false
               }
            ],
            "upgradePath":[
               "upgrade",
               "upgradedIBCState"
            ],
            "allowUpdateAfterExpiry":true,
            "allowUpdateAfterMisbehaviour":true
         }
      },
      {
         "clientId":"07-tendermint-10",
         "clientState":{
            "@type":"/ibc.lightclients.tendermint.v1.ClientState",
            "chainId":"pisco-1",
            "trustLevel":{
               "numerator":"1",
               "denominator":"3"
            },
            "trustingPeriod":"345600s",
            "unbondingPeriod":"432000s",
            "maxClockDrift":"50s",
            "frozenHeight":{
               "revisionNumber":"0",
               "revisionHeight":"0"
            },
            "latestHeight":{
               "revisionNumber":"1",
               "revisionHeight":"2304261"
            },
            "proofSpecs":[
               {
                  "leafSpec":{
                     "hash":"SHA256",
                     "prehashValue":"SHA256",
                     "length":"VAR_PROTO",
                     "prefix":"AA==",
                     "prehashKey":"NO_HASH"
                  },
                  "innerSpec":{
                     "childOrder":[
                        0,
                        1
                     ],
                     "childSize":33,
                     "minPrefixLength":4,
                     "maxPrefixLength":12,
                     "hash":"SHA256",
                     "emptyChild":""
                  },
                  "maxDepth":0,
                  "minDepth":0,
                  "prehashKeyBeforeComparison":false
               },
               {
                  "leafSpec":{
                     "hash":"SHA256",
                     "prehashValue":"SHA256",
                     "length":"VAR_PROTO",
                     "prefix":"AA==",
                     "prehashKey":"NO_HASH"
                  },
                  "innerSpec":{
                     "childOrder":[
                        0,
                        1
                     ],
                     "childSize":32,
                     "minPrefixLength":1,
                     "maxPrefixLength":1,
                     "hash":"SHA256",
                     "emptyChild":""
                  },
                  "maxDepth":0,
                  "minDepth":0,
                  "prehashKeyBeforeComparison":false
               }
            ],
            "upgradePath":[
               "upgrade",
               "upgradedIBCState"
            ],
            "allowUpdateAfterExpiry":true,
            "allowUpdateAfterMisbehaviour":true
         }
      },
      {
         "clientId":"07-tendermint-100",
         "clientState":{
            "@type":"/ibc.lightclients.tendermint.v1.ClientState",
            "chainId":"osmo-test-4",
            "trustLevel":{
               "numerator":"1",
               "denominator":"3"
            },
            "trustingPeriod":"806400s",
            "unbondingPeriod":"1209600s",
            "maxClockDrift":"20s",
            "frozenHeight":{
               "revisionNumber":"0",
               "revisionHeight":"0"
            },
            "latestHeight":{
               "revisionNumber":"4",
               "revisionHeight":"10356505"
            },
            "proofSpecs":[
               {
                  "leafSpec":{
                     "hash":"SHA256",
                     "prehashValue":"SHA256",
                     "length":"VAR_PROTO",
                     "prefix":"AA==",
                     "prehashKey":"NO_HASH"
                  },
                  "innerSpec":{
                     "childOrder":[
                        0,
                        1
                     ],
                     "childSize":33,
                     "minPrefixLength":4,
                     "maxPrefixLength":12,
                     "hash":"SHA256",
                     "emptyChild":""
                  },
                  "maxDepth":0,
                  "minDepth":0,
                  "prehashKeyBeforeComparison":false
               },
               {
                  "leafSpec":{
                     "hash":"SHA256",
                     "prehashValue":"SHA256",
                     "length":"VAR_PROTO",
                     "prefix":"AA==",
                     "prehashKey":"NO_HASH"
                  },
                  "innerSpec":{
                     "childOrder":[
                        0,
                        1
                     ],
                     "childSize":32,
                     "minPrefixLength":1,
                     "maxPrefixLength":1,
                     "hash":"SHA256",
                     "emptyChild":""
                  },
                  "maxDepth":0,
                  "minDepth":0,
                  "prehashKeyBeforeComparison":false
               }
            ],
            "upgradePath":[
               "upgrade",
               "upgradedIBCState"
            ],
            "allowUpdateAfterExpiry":true,
            "allowUpdateAfterMisbehaviour":true
         }
      },
      {
         "clientId":"07-tendermint-101",
         "clientState":{
            "@type":"/ibc.lightclients.tendermint.v1.ClientState",
            "chainId":"osmo-test-4",
            "trustLevel":{
               "numerator":"1",
               "denominator":"3"
            },
            "trustingPeriod":"806400s",
            "unbondingPeriod":"1209600s",
            "maxClockDrift":"20s",
            "frozenHeight":{
               "revisionNumber":"0",
               "revisionHeight":"0"
            },
            "latestHeight":{
               "revisionNumber":"4",
               "revisionHeight":"10356847"
            },
            "proofSpecs":[
               {
                  "leafSpec":{
                     "hash":"SHA256",
                     "prehashValue":"SHA256",
                     "length":"VAR_PROTO",
                     "prefix":"AA==",
                     "prehashKey":"NO_HASH"
                  },
                  "innerSpec":{
                     "childOrder":[
                        0,
                        1
                     ],
                     "childSize":33,
                     "minPrefixLength":4,
                     "maxPrefixLength":12,
                     "hash":"SHA256",
                     "emptyChild":""
                  },
                  "maxDepth":0,
                  "minDepth":0,
                  "prehashKeyBeforeComparison":false
               },
               {
                  "leafSpec":{
                     "hash":"SHA256",
                     "prehashValue":"SHA256",
                     "length":"VAR_PROTO",
                     "prefix":"AA==",
                     "prehashKey":"NO_HASH"
                  },
                  "innerSpec":{
                     "childOrder":[
                        0,
                        1
                     ],
                     "childSize":32,
                     "minPrefixLength":1,
                     "maxPrefixLength":1,
                     "hash":"SHA256",
                     "emptyChild":""
                  },
                  "maxDepth":0,
                  "minDepth":0,
                  "prehashKeyBeforeComparison":false
               }
            ],
            "upgradePath":[
               "upgrade",
               "upgradedIBCState"
            ],
            "allowUpdateAfterExpiry":true,
            "allowUpdateAfterMisbehaviour":true
         }
      },
      {
         "clientId":"07-tendermint-102",
         "clientState":{
            "@type":"/ibc.lightclients.tendermint.v1.ClientState",
            "chainId":"osmo-test-4",
            "trustLevel":{
               "numerator":"1",
               "denominator":"3"
            },
            "trustingPeriod":"806400s",
            "unbondingPeriod":"1209600s",
            "maxClockDrift":"20s",
            "frozenHeight":{
               "revisionNumber":"0",
               "revisionHeight":"0"
            },
            "latestHeight":{
               "revisionNumber":"4",
               "revisionHeight":"10357322"
            },
            "proofSpecs":[
               {
                  "leafSpec":{
                     "hash":"SHA256",
                     "prehashValue":"SHA256",
                     "length":"VAR_PROTO",
                     "prefix":"AA==",
                     "prehashKey":"NO_HASH"
                  },
                  "innerSpec":{
                     "childOrder":[
                        0,
                        1
                     ],
                     "childSize":33,
                     "minPrefixLength":4,
                     "maxPrefixLength":12,
                     "hash":"SHA256",
                     "emptyChild":""
                  },
                  "maxDepth":0,
                  "minDepth":0,
                  "prehashKeyBeforeComparison":false
               },
               {
                  "leafSpec":{
                     "hash":"SHA256",
                     "prehashValue":"SHA256",
                     "length":"VAR_PROTO",
                     "prefix":"AA==",
                     "prehashKey":"NO_HASH"
                  },
                  "innerSpec":{
                     "childOrder":[
                        0,
                        1
                     ],
                     "childSize":32,
                     "minPrefixLength":1,
                     "maxPrefixLength":1,
                     "hash":"SHA256",
                     "emptyChild":""
                  },
                  "maxDepth":0,
                  "minDepth":0,
                  "prehashKeyBeforeComparison":false
               }
            ],
            "upgradePath":[
               "upgrade",
               "upgradedIBCState"
            ],
            "allowUpdateAfterExpiry":true,
            "allowUpdateAfterMisbehaviour":true
         }
      },
      {
         "clientId":"07-tendermint-103",
         "clientState":{
            "@type":"/ibc.lightclients.tendermint.v1.ClientState",
            "chainId":"galileo-3",
            "trustLevel":{
               "numerator":"1",
               "denominator":"3"
            },
            "trustingPeriod":"604800s",
            "unbondingPeriod":"1814400s",
            "maxClockDrift":"30s",
            "frozenHeight":{
               "revisionNumber":"0",
               "revisionHeight":"0"
            },
            "latestHeight":{
               "revisionNumber":"3",
               "revisionHeight":"2848767"
            },
            "proofSpecs":[
               {
                  "leafSpec":{
                     "hash":"SHA256",
                     "prehashValue":"SHA256",
                     "length":"VAR_PROTO",
                     "prefix":"AA==",
                     "prehashKey":"NO_HASH"
                  },
                  "innerSpec":{
                     "childOrder":[
                        0,
                        1
                     ],
                     "childSize":33,
                     "minPrefixLength":4,
                     "maxPrefixLength":12,
                     "hash":"SHA256",
                     "emptyChild":""
                  },
                  "maxDepth":0,
                  "minDepth":0,
                  "prehashKeyBeforeComparison":false
               },
               {
                  "leafSpec":{
                     "hash":"SHA256",
                     "prehashValue":"SHA256",
                     "length":"VAR_PROTO",
                     "prefix":"AA==",
                     "prehashKey":"NO_HASH"
                  },
                  "innerSpec":{
                     "childOrder":[
                        0,
                        1
                     ],
                     "childSize":32,
                     "minPrefixLength":1,
                     "maxPrefixLength":1,
                     "hash":"SHA256",
                     "emptyChild":""
                  },
                  "maxDepth":0,
                  "minDepth":0,
                  "prehashKeyBeforeComparison":false
               }
            ],
            "upgradePath":[
               "upgrade",
               "upgradedIBCState"
            ],
            "allowUpdateAfterExpiry":true,
            "allowUpdateAfterMisbehaviour":true
         }
      }
   ],
   "pagination":{
      "nextKey":"LzA3LXRlbmRlcm1pbnQtMTAzL2NsaWVudFN0YXRl",
      "total":"0"
   }
}
ParameterTypeDescription
client_statesIdentifiedClientState ArrayClient state associated with the request identifier
paginationPageResponsePagination information in the response


IdentifiedClientState

ParameterTypeDescription
client_idStringClient identifier
client_stateAnyClient state

ConsensusState

Queries a consensus state associated with a client state at a given height

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    client_id = "07-tendermint-0"
    revision_number = 0
    revision_height = 7379538

    state = await client.fetch_ibc_consensus_state(
        client_id=client_id, revision_number=revision_number, revision_height=revision_height
    )
    print(state)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    clientId := "07-tendermint-0"
    revisionNumber := uint64(0)
    revisionHeight := uint64(7379538)
    latestHeight := false

    ctx := context.Background()

    res, err := chainClient.FetchIBCConsensusState(ctx, clientId, revisionNumber, revisionHeight, latestHeight)
    if err != nil {
        fmt.Println(err)
    }

    fmt.Print(res)

}
ParameterTypeDescriptionRequired
client_idStringClient identifierYes
revision_numberIntegerConsensus state revision numberYes
client_idIntegerConsensus state revision heightYes
latest_heightBooleanOverrrides the height field and queries the latest stored ConsensusStateNo

Response Parameters

Response Example:

{
   "consensusState":{
      "@type":"/ibc.lightclients.tendermint.v1.ConsensusState",
      "timestamp":"2022-07-04T10:34:53.874345276Z",
      "root":{
         "hash":"viI6JuzZ/kOAh6jIeecglN7Xt+mGQT/PpvAGqGLcVmM="
      },
      "nextValidatorsHash":"olPEfP4dzPCC07Oyg/3+6U5/uumw/HmELk2MwpMogSg="
   },
   "proofHeight":{
      "revisionNumber":"888",
      "revisionHeight":"27531028"
   },
   "proof":""
}
ParameterTypeDescription
consensus_stateAnyClient state associated with the request identifier
proofByte ArrayMerkle proof of existence
proof_heightHeightHeight at which the proof was retrieved


Height

ParameterTypeDescription
revision_numberIntegerThe revision that the client is currently on
revision_heightIntegerThe height within the given revision

ConsensusStates

Queries all the consensus state associated with a given client

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    client_id = "07-tendermint-0"
    pagination = PaginationOption(skip=2, limit=4)

    states = await client.fetch_ibc_consensus_states(client_id=client_id, pagination=pagination)
    print(states)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "fmt"

    "github.com/cosmos/cosmos-sdk/types/query"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    clientId := "07-tendermint-0"
    pagination := query.PageRequest{Offset: 2, Limit: 4}
    ctx := context.Background()

    res, err := chainClient.FetchIBCConsensusStates(ctx, clientId, &pagination)
    if err != nil {
        fmt.Println(err)
    }

    fmt.Print(res)

}
ParameterTypeDescriptionRequired
client_idStringClient identifierYes
paginationPageRequestThe optional pagination for the requestNo

Response Parameters

Response Example:

{
   "consensusStates":[
      {
         "height":{
            "revisionHeight":"7379500",
            "revisionNumber":"0"
         },
         "consensusState":{
            "@type":"/ibc.lightclients.tendermint.v1.ConsensusState",
            "timestamp":"2022-07-04T10:32:23.232327085Z",
            "root":{
               "hash":"PlwKOemX6GQh/sGlPzvT89sRijeZa0pUK+sjvASu/5s="
            },
            "nextValidatorsHash":"olPEfP4dzPCC07Oyg/3+6U5/uumw/HmELk2MwpMogSg="
         }
      },
      {
         "height":{
            "revisionHeight":"7379506",
            "revisionNumber":"0"
         },
         "consensusState":{
            "@type":"/ibc.lightclients.tendermint.v1.ConsensusState",
            "timestamp":"2022-07-04T10:32:46.188675417Z",
            "root":{
               "hash":"LTmLr8YzxO/yfajKO1RrnZeTK3JUMrvYcm/IZyi0XeY="
            },
            "nextValidatorsHash":"olPEfP4dzPCC07Oyg/3+6U5/uumw/HmELk2MwpMogSg="
         }
      },
      {
         "height":{
            "revisionHeight":"7379521",
            "revisionNumber":"0"
         },
         "consensusState":{
            "@type":"/ibc.lightclients.tendermint.v1.ConsensusState",
            "timestamp":"2022-07-04T10:33:46.953207174Z",
            "root":{
               "hash":"lyXb+gmcyDOcHL35Zppqv10y0irbqlnsllERaOEb9R4="
            },
            "nextValidatorsHash":"olPEfP4dzPCC07Oyg/3+6U5/uumw/HmELk2MwpMogSg="
         }
      },
      {
         "height":{
            "revisionHeight":"7379538",
            "revisionNumber":"0"
         },
         "consensusState":{
            "@type":"/ibc.lightclients.tendermint.v1.ConsensusState",
            "timestamp":"2022-07-04T10:34:53.874345276Z",
            "root":{
               "hash":"viI6JuzZ/kOAh6jIeecglN7Xt+mGQT/PpvAGqGLcVmM="
            },
            "nextValidatorsHash":"olPEfP4dzPCC07Oyg/3+6U5/uumw/HmELk2MwpMogSg="
         }
      }
   ],
   "pagination":{
      "nextKey":"",
      "total":"0"
   }
}
ParameterTypeDescription
consensus_statesConsensusStateWithHeight ArrayConsensus states associated with the identifier
paginationPageResponsePagination information in the response


ConsensusStateWithHeight

ParameterTypeDescription
heightHeightConsensus state height
consensus_stateAnyConsensus state


Height

ParameterTypeDescription
revision_numberIntegerThe revision that the client is currently on
revision_heightIntegerThe height within the given revision

ConsensusStateHeights

Queries the height of every consensus states associated with a given client

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    client_id = "07-tendermint-0"
    pagination = PaginationOption(skip=2, limit=4)

    states = await client.fetch_ibc_consensus_state_heights(client_id=client_id, pagination=pagination)
    print(states)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "fmt"

    "github.com/cosmos/cosmos-sdk/types/query"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    clientId := "07-tendermint-0"
    pagination := query.PageRequest{Offset: 2, Limit: 4}
    ctx := context.Background()

    res, err := chainClient.FetchIBCConsensusStateHeights(ctx, clientId, &pagination)
    if err != nil {
        fmt.Println(err)
    }

    fmt.Print(res)

}
ParameterTypeDescriptionRequired
client_idStringClient identifierYes
paginationPageRequestThe optional pagination for the requestNo

Response Parameters

Response Example:

{
   "consensusStateHeights":[
      {
         "revisionHeight":"7379500",
         "revisionNumber":"0"
      },
      {
         "revisionHeight":"7379506",
         "revisionNumber":"0"
      },
      {
         "revisionHeight":"7379521",
         "revisionNumber":"0"
      },
      {
         "revisionHeight":"7379538",
         "revisionNumber":"0"
      }
   ],
   "pagination":{
      "nextKey":"",
      "total":"0"
   }
}
ParameterTypeDescription
consensus_state_heightsHeight ArrayConsensus state heights
paginationPageResponsePagination information in the response


Height

ParameterTypeDescription
revision_numberIntegerThe revision that the client is currently on
revision_heightIntegerThe height within the given revision

ClientStatus

Queries the status of an IBC client

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    client_id = "07-tendermint-0"

    state = await client.fetch_ibc_client_status(client_id=client_id)
    print(state)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    clientId := "07-tendermint-0"
    ctx := context.Background()

    res, err := chainClient.FetchIBCClientStatus(ctx, clientId)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
client_idStringClient unique identifierYes

Response Parameters

Response Example:

{
   "status":"Expired"
}
ParameterTypeDescription
statusStringClient status

ClientParams

Queries all parameters of the ibc client submodule

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    params = await client.fetch_ibc_client_params()
    print(params)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    res, err := chainClient.FetchIBCClientParams(ctx)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}

No parameters

Response Parameters

Response Example:

{
   "params":{
      "allowedClients":[
         "06-solomachine",
         "07-tendermint"
      ]
   }
}
ParameterTypeDescription
paramsparamsModule's parameters


Params

ParameterTypeDescription
allowed_clientsString ArrayAllowed_clients defines the list of allowed client state types which can be created and interacted with. If a client type is removed from the allowed clients list, usage of this client will be disabled until it is added again to the list

UpgradedClientState

Queries an Upgraded IBC light client

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    state = await client.fetch_ibc_upgraded_client_state()
    print(state)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    res, err := chainClient.FetchIBCUpgradedClientState(ctx)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}

No parameters

Response Parameters

Response Example:


ParameterTypeDescription
upgraded_client_stateAnyClient state associated with the request identifier

UpgradedConsensusState

Queries an Upgraded IBC consensus state

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    state = await client.fetch_ibc_upgraded_consensus_state()
    print(state)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    res, err := chainClient.FetchIBCUpgradedConsensusState(ctx)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}

No parameters

Response Parameters

Response Example:


ParameterTypeDescription
upgraded_consensus_stateAnyConsensus state associated with the request identifier

- IBC Core Connection

Includes all the messages and queries associated to connections from the IBC core connection module

Connection

Queries an IBC connection end

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    connection_id = "connection-0"

    connection = await client.fetch_ibc_connection(connection_id=connection_id)
    print(connection)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    connectionId := "connection-0"
    ctx := context.Background()

    res, err := chainClient.FetchIBCConnection(ctx, connectionId)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
connection_idStringConnection unique identifierYes

Response Parameters

Response Example:

{
   "connection":{
      "clientId":"07-tendermint-0",
      "versions":[
         {
            "identifier":"1",
            "features":[
               "ORDER_ORDERED",
               "ORDER_UNORDERED"
            ]
         }
      ],
      "state":"STATE_OPEN",
      "counterparty":{
         "clientId":"07-tendermint-904",
         "connectionId":"connection-877",
         "prefix":{
            "keyPrefix":"aWJj"
         }
      },
      "delayPeriod":"0"
   },
   "proofHeight":{
      "revisionNumber":"888",
      "revisionHeight":"27778433"
   },
   "proof":""
}
ParameterTypeDescription
connectionConnectionEndConnection associated with the request identifier
proofByte ArrayMerkle proof of existence
proof_heightHeightHeight at which the proof was retrieved


ConnectionEnd

ParameterTypeDescription
client_idStringClient associated with this connection
versionsVersion StringChannel identifier
stateStateCurrent state of the connection end
counterpartyCounterpartyCounterparty chain associated with this connection
delay_periodIntegerDelay period that must pass before a consensus state can be used for packet-verification NOTE: delay period logic is only implemented by some clients


Version

ParameterTypeDescription
identifierStringUnique version identifier
featuresString ArrayList of features compatible with the specified identifier


State

CodeName
0STATE_UNINITIALIZED_UNSPECIFIED
1STATE_INIT
2STATE_TRYOPEN
3STATE_OPEN


Counterparty

ParameterTypeDescription
client_idStringIdentifies the client on the counterparty chain associated with a given connection
connection_idStringIdentifies the connection end on the counterparty chain associated with a given connection
prefixMarketPrefixCommitment merkle prefix of the counterparty chain


MerklePrefix

ParameterTypeDescription
key_prefixByte ArrayMerkle path prefixed to the key


Height

ParameterTypeDescription
revision_numberIntegerThe revision that the client is currently on
revision_heightIntegerThe height within the given revision

Connections

Queries all the IBC connections of a chain

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    pagination = PaginationOption(skip=2, limit=4)

    connections = await client.fetch_ibc_connections(pagination=pagination)
    print(connections)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/cosmos/cosmos-sdk/types/query"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    pagination := query.PageRequest{Offset: 2, Limit: 4}
    ctx := context.Background()

    res, err := chainClient.FetchIBCConnections(ctx, &pagination)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
paginationPageRequestThe optional pagination for the requestNo


PageRequest

ParameterTypeDescriptionRequired
keyByte ArrayKey is a value returned in PageResponse.next_key to begin querying the next page most efficiently. Only one of offset or key should be setNo
offsetIntegerNumeric offset that can be used when key is unavailable. It is less efficient than using key. Only one of offset or key should be setNo
limitIntegerTotal number of results to be returned in the result pageNo
count_totalBooleanSet to true to indicate that the result set should include a count of the total number of items available for pagination in UIs. It is only respected when offset is used. It is ignored when key is setNo
reverseBooleanReverse is set to true if results are to be returned in the descending orderNo

Response Parameters

Response Example:

{
   "connections":[
      {
         "id":"connection-10",
         "clientId":"07-tendermint-12",
         "versions":[
            {
               "identifier":"1",
               "features":[
                  "ORDER_ORDERED",
                  "ORDER_UNORDERED"
               ]
            }
         ],
         "state":"STATE_OPEN",
         "counterparty":{
            "clientId":"07-tendermint-103",
            "connectionId":"connection-93",
            "prefix":{
               "keyPrefix":"aWJj"
            }
         },
         "delayPeriod":"0"
      },
      {
         "id":"connection-100",
         "clientId":"07-tendermint-126",
         "versions":[
            {
               "identifier":"1",
               "features":[
                  "ORDER_ORDERED",
                  "ORDER_UNORDERED"
               ]
            }
         ],
         "state":"STATE_OPEN",
         "counterparty":{
            "clientId":"07-tendermint-168",
            "connectionId":"connection-118",
            "prefix":{
               "keyPrefix":"aWJj"
            }
         },
         "delayPeriod":"0"
      },
      {
         "id":"connection-101",
         "clientId":"07-tendermint-127",
         "versions":[
            {
               "identifier":"1",
               "features":[
                  "ORDER_ORDERED",
                  "ORDER_UNORDERED"
               ]
            }
         ],
         "state":"STATE_OPEN",
         "counterparty":{
            "clientId":"07-tendermint-3",
            "connectionId":"connection-5",
            "prefix":{
               "keyPrefix":"aWJj"
            }
         },
         "delayPeriod":"0"
      },
      {
         "id":"connection-102",
         "clientId":"07-tendermint-128",
         "versions":[
            {
               "identifier":"1",
               "features":[
                  "ORDER_ORDERED",
                  "ORDER_UNORDERED"
               ]
            }
         ],
         "state":"STATE_OPEN",
         "counterparty":{
            "clientId":"07-tendermint-633",
            "connectionId":"connection-574",
            "prefix":{
               "keyPrefix":"aWJj"
            }
         },
         "delayPeriod":"0"
      }
   ],
   "pagination":{
      "nextKey":"L2Nvbm5lY3Rpb24tMTAz",
      "total":"0"
   },
   "height":{
      "revisionNumber":"888",
      "revisionHeight":"27779944"
   }
}
ParameterTypeDescription
connectionsIdentifiedConnection ArrayConnection associated with the request identifier
paginationPageResponsePagination information in the response
heightHeightQuery block height


IdentifiedConnection

ParameterTypeDescription
idStringConnection identifier
client_idStringClient associated with this connection
versionsVersion StringIBC version which can be utilised to determine encodings or protocols for channels or packets utilising this connection
stateStateCurrent state of the connection end
counterpartyCounterpartyCounterparty chain associated with this connection
delay_periodIntegerDelay period associated with this connection


PageResponse

ParameterTypeDescription
next_keyByte ArrayThe key to be passed to PageRequest.key to query the next page most efficiently. It will be empty if there are no more results.
totalIntegerTotal number of results available if PageRequest.count_total was set, its value is undefined otherwise


Height

ParameterTypeDescription
revision_numberIntegerThe revision that the client is currently on
revision_heightIntegerThe height within the given revision


Version

ParameterTypeDescription
identifierStringUnique version identifier
featuresString ArrayList of features compatible with the specified identifier


State

CodeName
0STATE_UNINITIALIZED_UNSPECIFIED
1STATE_INIT
2STATE_TRYOPEN
3STATE_OPEN


Counterparty

ParameterTypeDescription
client_idStringIdentifies the client on the counterparty chain associated with a given connection
connection_idStringIdentifies the connection end on the counterparty chain associated with a given connection
prefixMarketPrefixCommitment merkle prefix of the counterparty chain


MerklePrefix

ParameterTypeDescription
key_prefixByte ArrayMerkle path prefixed to the key

ClientConnections

Queries the connection paths associated with a client state

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    client_id = "07-tendermint-0"

    connections = await client.fetch_ibc_client_connections(client_id=client_id)
    print(connections)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    clientId := "07-tendermint-0"
    ctx := context.Background()

    res, err := chainClient.FetchIBCClientConnections(ctx, clientId)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
client_idStringClient identifier associated with a connectionYes

Response Parameters

Response Example:

{
   "connectionPaths":[
      "connection-0"
   ],
   "proofHeight":{
      "revisionNumber":"888",
      "revisionHeight":"27783349"
   },
   "proof":""
}
ParameterTypeDescription
connection_pathsString ArrayAll the connection paths associated with a client
proofByte ArrayMerkle proof of existence
proof_heightHeightHeight at which the proof was retrieved


Height

ParameterTypeDescription
revision_numberIntegerThe revision that the client is currently on
revision_heightIntegerThe height within the given revision

ConnectionClientState

Queries the client state associated with the connection

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    connection_id = "connection-0"

    state = await client.fetch_ibc_connection_client_state(connection_id=connection_id)
    print(state)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    connectionId := "connection-0"
    ctx := context.Background()

    res, err := chainClient.FetchIBCConnectionClientState(ctx, connectionId)
    if err != nil {
        fmt.Println(err)
    }

    fmt.Print(res)

}
ParameterTypeDescriptionRequired
connection_idStringConnection identifierYes

Response Parameters

Response Example:

{
   "identifiedClientState":{
      "clientId":"07-tendermint-0",
      "clientState":{
         "@type":"/ibc.lightclients.tendermint.v1.ClientState",
         "chainId":"band-laozi-testnet4",
         "trustLevel":{
            "numerator":"1",
            "denominator":"3"
         },
         "trustingPeriod":"1209600s",
         "unbondingPeriod":"1814400s",
         "maxClockDrift":"20s",
         "frozenHeight":{
            "revisionNumber":"0",
            "revisionHeight":"0"
         },
         "latestHeight":{
            "revisionHeight":"7379538",
            "revisionNumber":"0"
         },
         "proofSpecs":[
            {
               "leafSpec":{
                  "hash":"SHA256",
                  "prehashValue":"SHA256",
                  "length":"VAR_PROTO",
                  "prefix":"AA==",
                  "prehashKey":"NO_HASH"
               },
               "innerSpec":{
                  "childOrder":[
                     0,
                     1
                  ],
                  "childSize":33,
                  "minPrefixLength":4,
                  "maxPrefixLength":12,
                  "hash":"SHA256",
                  "emptyChild":""
               },
               "maxDepth":0,
               "minDepth":0,
               "prehashKeyBeforeComparison":false
            },
            {
               "leafSpec":{
                  "hash":"SHA256",
                  "prehashValue":"SHA256",
                  "length":"VAR_PROTO",
                  "prefix":"AA==",
                  "prehashKey":"NO_HASH"
               },
               "innerSpec":{
                  "childOrder":[
                     0,
                     1
                  ],
                  "childSize":32,
                  "minPrefixLength":1,
                  "maxPrefixLength":1,
                  "hash":"SHA256",
                  "emptyChild":""
               },
               "maxDepth":0,
               "minDepth":0,
               "prehashKeyBeforeComparison":false
            }
         ],
         "upgradePath":[
            "upgrade",
            "upgradedIBCState"
         ],
         "allowUpdateAfterExpiry":true,
         "allowUpdateAfterMisbehaviour":true
      }
   },
   "proofHeight":{
      "revisionNumber":"888",
      "revisionHeight":"27783852"
   },
   "proof":""
}
ParameterTypeDescription
identified_client_stateIdentifiedClientStateClient state associated with the channel
proofByte ArrayMerkle proof of existence
proof_heightHeightHeight at which the proof was retrieved


IdentifiedClientState

ParameterTypeDescription
client_idStringClient identifier
client_stateAnyClient state


Height

ParameterTypeDescription
revision_numberIntegerThe revision that the client is currently on
revision_heightIntegerThe height within the given revision

ConnectionConsensusState

Queries the consensus state associated with the connection

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    connection_id = "connection-0"
    revision_number = 0
    revision_height = 7379538

    state = await client.fetch_ibc_connection_consensus_state(
        connection_id=connection_id, revision_number=revision_number, revision_height=revision_height
    )
    print(state)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    connectionId := "connection-0"
    revisionNumber := uint64(0)
    revisionHeight := uint64(7379538)

    ctx := context.Background()

    res, err := chainClient.FetchIBCConnectionConsensusState(ctx, connectionId, revisionNumber, revisionHeight)
    if err != nil {
        fmt.Println(err)
    }

    fmt.Print(res)

}
ParameterTypeDescriptionRequired
connection_idStringConnection identifierYes
revision_numberIntegerRevision number of the consensus stateYes
revision_heightIntegerRevision height of the consensus stateYes

Response Parameters

Response Example:

{
   "consensusState":{
      "@type":"/ibc.lightclients.tendermint.v1.ConsensusState",
      "timestamp":"2022-07-04T10:34:53.874345276Z",
      "root":{
         "hash":"viI6JuzZ/kOAh6jIeecglN7Xt+mGQT/PpvAGqGLcVmM="
      },
      "nextValidatorsHash":"olPEfP4dzPCC07Oyg/3+6U5/uumw/HmELk2MwpMogSg="
   },
   "clientId":"07-tendermint-0",
   "proofHeight":{
      "revisionNumber":"888",
      "revisionHeight":"27784841"
   },
   "proof":""
}
ParameterTypeDescription
consensus_stateAnyConsensus state associated with the channel
client_idStringClient identifier associated with the consensus state
proofByte ArrayMerkle proof of existence
proof_heightHeightHeight at which the proof was retrieved


Height

ParameterTypeDescription
revision_numberIntegerThe revision that the client is currently on
revision_heightIntegerThe height within the given revision

ConnectionParams

Queries all parameters of the ibc connection submodule

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    params = await client.fetch_ibc_connection_params()
    print(params)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    res, err := chainClient.FetchIBCConnectionParams(ctx)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}

No parameters

Response Parameters

Response Example:

{
   "params":{
      "maxExpectedTimePerBlock":"30000000000"
   }
}
ParameterTypeDescription
paramsParamsModule's parameters


Params

ParameterTypeDescription
max_expected_time_per_blockIntegerMaximum expected time per block (in nanoseconds), used to enforce block delay. This parameter should reflect the largest amount of time that the chain might reasonably take to produce the next block under normal operating conditions. A safe choice is 3-5x the expected time per block

- IBC Transfer

Includes all the messages and queries associated to transfers from the IBC transfer module

DenomTrace

Queries a denomination trace information

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
from hashlib import sha256

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    path = "transfer/channel-126"
    base_denom = "uluna"
    full_path = f"{path}/{base_denom}"
    path_hash = sha256(full_path.encode()).hexdigest()
    trace_hash = f"ibc/{path_hash}"

    denom_trace = await client.fetch_denom_trace(hash=trace_hash)
    print(denom_trace)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    denomTrace := types.DenomTrace{
        Path:      "transfer/channel-126",
        BaseDenom: "uluna",
    }
    ctx := context.Background()

    res, err := chainClient.FetchDenomTrace(ctx, denomTrace.Hash().String())
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
hashStringThe denom trace hashYes

Response Parameters

Response Example:

{
   "denomTrace":{
      "path":"transfer/channel-126",
      "baseDenom":"uluna"
   }
}
ParameterTypeDescription
denom_traceDenomTraceDenom trace information


DenomTrace

ParameterTypeDescription
pathStringPath is the port and channel
base_denomStringThe token denom

DenomTraces

Queries all denomination traces

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    pagination = PaginationOption(skip=2, limit=4)

    denom_traces = await client.fetch_denom_traces(pagination=pagination)
    print(denom_traces)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"
    "github.com/cosmos/cosmos-sdk/types/query"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    pagination := query.PageRequest{Offset: 2, Limit: 4}
    ctx := context.Background()

    res, err := chainClient.FetchDenomTraces(ctx, &pagination)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
paginationPageRequestThe optional pagination for the requestNo


PageRequest

ParameterTypeDescriptionRequired
keyByte ArrayKey is a value returned in PageResponse.next_key to begin querying the next page most efficiently. Only one of offset or key should be setNo
offsetIntegerNumeric offset that can be used when key is unavailable. It is less efficient than using key. Only one of offset or key should be setNo
limitIntegerTotal number of results to be returned in the result pageNo
count_totalBooleanSet to true to indicate that the result set should include a count of the total number of items available for pagination in UIs. It is only respected when offset is used. It is ignored when key is setNo
reverseBooleanReverse is set to true if results are to be returned in the descending orderNo

Response Parameters

Response Example:

{
   "denomTraces":[
      {
         "path":"transfer/channel-160",
         "baseDenom":"uatom"
      },
      {
         "path":"transfer/channel-2",
         "baseDenom":"uphoton"
      },
      {
         "path":"transfer/channel-43",
         "baseDenom":"uandr"
      },
      {
         "path":"transfer/channel-6",
         "baseDenom":"cw20:terra167dsqkh2alurx997wmycw9ydkyu54gyswe3ygmrs4lwume3vmwks8ruqnv"
      }
   ],
   "pagination":{
      "nextKey":"WZNnsWM6uaj4vFpbpqm1M+3mVbhdRvmgClPl/2jiXlc=",
      "total":"0"
   }
}
ParameterTypeDescription
denom_tracesDenomTrace ArrayDenom traces information
paginationPageResponsePagination information in the response


PageResponse

ParameterTypeDescription
next_keyByte ArrayThe key to be passed to PageRequest.key to query the next page most efficiently. It will be empty if there are no more results.
totalIntegerTotal number of results available if PageRequest.count_total was set, its value is undefined otherwise

DenomHash

Queries a denomination hash information

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    path = "transfer/channel-126"
    base_denom = "uluna"
    full_path = f"{path}/{base_denom}"

    denom_hash = await client.fetch_denom_hash(trace=full_path)
    print(denom_hash)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    path := "transfer/channel-126"
    baseDenom := "uluna"
    fullPath := fmt.Sprintf("%s/%s", path, baseDenom)
    ctx := context.Background()

    res, err := chainClient.FetchDenomHash(ctx, fullPath)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
traceStringThe denomination trace ([port_id]/[channel_id])+/[denom]Yes

Response Parameters

Response Example:

{
   "hash":"97498452BF27CC90656FD7D6EFDA287FA2BFFFF3E84691C84CB9E0451F6DF0A4"
}
ParameterTypeDescription
hashStringHash (in hex format) of the denomination trace information

EscrowAddress

Returns the escrow address for a particular port and channel id

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    port_id = "transfer"
    channel_id = "channel-126"

    escrow_address = await client.fetch_escrow_address(port_id=port_id, channel_id=channel_id)
    print(escrow_address)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    portId := "transfer"
    channelId := "channel-126"
    ctx := context.Background()

    res, err := chainClient.FetchEscrowAddress(ctx, portId, channelId)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
port_idStringThe unique port identifierYes
channel_idStringThe unique channel identifierYes

Response Parameters

Response Example:

{
   "escrowAddress":"inj1w8ent9jwwqy2d5s8grq6muk2hqa6kj2863m3mg"
}
ParameterTypeDescription
escrow_addressStringThe escrow account address

TotalEscrowForDenom

Returns the total amount of tokens in escrow based on the denom

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    base_denom = "uluna"

    escrow = await client.fetch_total_escrow_for_denom(denom=base_denom)
    print(escrow)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/InjectiveLabs/sdk-go/client"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"

    "os"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    baseDenom := "uluna"
    ctx := context.Background()

    res, err := chainClient.FetchTotalEscrowForDenom(ctx, baseDenom)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
denomStringToken denomYes

Response Parameters

Response Example:

{
   "amount":{
      "denom":"uluna",
      "amount":"0"
   }
}
ParameterTypeDescription
amountCoinAmount of token in the escrow


Coin

ParameterTypeDescriptionRequired
denomStringThe token denomYes
amountStringThe amount of tokensYes

MsgTransfer

Defines a msg to transfer fungible tokens (i.e Coins) between ICS20 enabled chains. See ICS Spec here: ICS Spec

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os
from decimal import Decimal

import dotenv

from pyinjective.async_client import AsyncClient
from pyinjective.core.broadcaster import MsgBroadcasterWithPk
from pyinjective.core.network import Network
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    await client.initialize_tokens_from_chain_denoms()
    composer = await client.composer()
    await client.sync_timeout_height()

    message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
        network=network,
        private_key=configured_private_key,
    )

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    source_port = "transfer"
    source_channel = "channel-126"
    token_amount = composer.create_coin_amount(amount=Decimal("0.1"), token_name="INJ")
    sender = address.to_acc_bech32()
    receiver = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
    timeout_height = 10

    # prepare tx msg
    message = composer.msg_ibc_transfer(
        source_port=source_port,
        source_channel=source_channel,
        token_amount=token_amount,
        sender=sender,
        receiver=receiver,
        timeout_height=timeout_height,
    )

    # broadcast the transaction
    result = await message_broadcaster.broadcast([message])
    print("---Transaction Response---")
    print(result)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "encoding/json"
    "fmt"
    "os"

    "cosmossdk.io/math"

    "github.com/InjectiveLabs/sdk-go/client"
    "github.com/InjectiveLabs/sdk-go/client/common"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
    sdktypes "github.com/cosmos/cosmos-sdk/types"
    ibctransfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types"
    ibccoretypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    // initialize grpc client
    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )
    if err != nil {
        panic(err)
    }
    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    sourcePort := "transfer"
    sourceChannel := "channel-126"
    coin := sdktypes.Coin{
        Denom: "inj", Amount: math.NewInt(1000000000000000000), // 1 INJ
    }
    sender := senderAddress.String()
    receiver := "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
    timeoutHeight := ibccoretypes.Height{RevisionNumber: 10, RevisionHeight: 10}

    msg := &ibctransfertypes.MsgTransfer{
        SourcePort:    sourcePort,
        SourceChannel: sourceChannel,
        Token:         coin,
        Sender:        sender,
        Receiver:      receiver,
        TimeoutHeight: timeoutHeight,
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    response, err := chainClient.AsyncBroadcastMsg(msg)

    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(response, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescription
source_portStringThe port on which the packet will be sent
source_channelStringThe channel by which the packet will be sent
tokenCoinThe tokens to be transferred
senderStringThe sender address
receiverStringThe recipient address on the destination chain
timeout_heightHeightTimeout height relative to the current block height. The timeout is disabled when set to 0
timeout_timestampIntegerTimeout timestamp in absolute nanoseconds since unix epoch. The timeout is disabled when set to 0
memoStringOptional memo


Coin

ParameterTypeDescriptionRequired
denomStringThe token denomYes
amountStringThe amount of tokensYes


Height

ParameterTypeDescription
revision_numberIntegerThe revision that the client is currently on
revision_heightIntegerThe height within the given revision

Response Parameters

Response Example:

ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

- Insurance

Includes the messages to create, underwrite and redeem in insurance funds.

MsgCreateInsuranceFund

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    # set custom cookie location (optional) - defaults to current dir
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    msg = composer.MsgCreateInsuranceFund(
        sender=address.to_acc_bech32(),
        ticker="5202d32a9-1701406800-SF",
        quote_denom="USDT",
        oracle_base="Frontrunner",
        oracle_quote="Frontrunner",
        oracle_type=11,
        expiry=-2,
        initial_deposit=1000,
    )

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
Parameter Type Description Required
sender String The Injective Chain address Yes
ticker String The name of the pair Yes
quote_denom String Coin denom used for the quote asset Yes
oracle_base String Oracle base currency Yes
oracle_quote String Oracle quote currency Yes
oracle_type Integer The oracle provider Yes
expiry Integer The expiry date Yes
initial_deposit Integer The initial deposit in the quote asset Yes

Response Parameters

Response Example:

txhash: "BB882A23CF0BC6E287F164DB2650990C7F317D9CF4CC2138B1EE479A8FB7F1CE"
raw_log: "[]"

gas wanted: 151648
gas fee: 0.000075824 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgUnderwrite

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    # set custom cookie location (optional) - defaults to current dir
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    msg = composer.MsgUnderwrite(
        sender=address.to_acc_bech32(),
        market_id="0x141e3c92ed55107067ceb60ee412b86256cedef67b1227d6367b4cdf30c55a74",
        quote_denom="USDT",
        amount=100,
    )

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
Parameter Type Description Required
sender String The Injective Chain address Yes
market_id String The market ID Yes
quote_denom String Coin denom used for the quote asset Yes
amount Integer The amount to underwrite in the quote asset Yes

Response Example:

txhash: "1229C821E16F0DB89B64C86F1E00B6EE51D4B528EC5070B231C6FD8363A1A8BE"
raw_log: "[]"

gas wanted: 142042
gas fee: 0.000071021 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgRequestRedemption

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    # set custom cookie location (optional) - defaults to current dir
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    msg = composer.MsgRequestRedemption(
        sender=address.to_acc_bech32(),
        market_id="0x141e3c92ed55107067ceb60ee412b86256cedef67b1227d6367b4cdf30c55a74",
        share_denom="share15",
        amount=100,  # raw chain value
    )

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
Parameter Type Description Required
sender String The Injective Chain address Yes
market_id String The market ID Yes
share_denom String Share denom used for the insurance fund Yes
amount Integer The amount to redeem in shares Yes

Response Parameters

Response Example:

txhash: "47982CB6CC7418FE7F2B406D40C4AD703CD87F4AA04B12E6151B648061785CD8"
raw_log: "[]"

gas wanted: 110689
gas fee: 0.0000553445 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

- Oracle

Includes the message to relay a price feed.

MsgRelayPriceFeedPrice

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    price = 100
    price_to_send = [str(int(price * 10**18))]
    base = ["BAYC"]
    quote = ["WETH"]

    # prepare tx msg
    msg = composer.MsgRelayPriceFeedPrice(sender=address.to_acc_bech32(), price=price_to_send, base=base, quote=quote)

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "fmt"
    "os"

    "cosmossdk.io/math"
    "github.com/InjectiveLabs/sdk-go/client"
    "github.com/InjectiveLabs/sdk-go/client/common"

    oracletypes "github.com/InjectiveLabs/sdk-go/chain/oracle/types"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    price := []math.LegacyDec{math.LegacyMustNewDecFromStr("100")}
    base := []string{"BAYC"}
    quote := []string{"WETH"}

    msg := &oracletypes.MsgRelayPriceFeedPrice{
        Sender: senderAddress.String(),
        Price:  price,
        Base:   base,
        Quote:  quote,
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    result, err := chainClient.SyncBroadcastMsg(msg)

    if err != nil {
        panic(err)
    }

    fmt.Printf("Broadcast result: %s\n", result)
}
Parameter Type Description Required
sender String The Injective Chain address of the sender Yes
price Array The price of the base asset Yes
base Array The base denom Yes
quote Array The quote denom Yes

Response Example:

txhash: "88F5B9C28813BB32607DF312A5411390F43C44F5E1F9D3BA0023EFE0EE4BD0EC"
raw_log: "[]"

gas wanted: 93486
gas fee: 0.000046743 INJ
DEBU[0001] broadcastTx with nonce 1314                   fn=func1 src="client/chain/chain.go:598"
DEBU[0002] msg batch committed successfully at height 5215101  fn=func1 src="client/chain/chain.go:619" txHash=641DE5923625C1A81C2544B72E5029E53AE721E47F40221182AFAD6F66F39EA4
DEBU[0002] nonce incremented to 1315                     fn=func1 src="client/chain/chain.go:623"
DEBU[0002] gas wanted:  113647                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.0000568235 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgRelayProviderPrices

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    provider = "ufc"
    symbols = ["KHABIB-TKO-05/30/2023", "KHABIB-TKO-05/26/2023"]
    prices = [0.5, 0.8]

    # prepare tx msg
    msg = composer.MsgRelayProviderPrices(
        sender=address.to_acc_bech32(), provider=provider, symbols=symbols, prices=prices
    )

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    sim_res_msg = sim_res["result"]["msgResponses"]
    print("---Simulation Response---")
    print(sim_res_msg)

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print("---Transaction Response---")
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
Parameter Type Description Required
sender String The Injective Chain address Yes
provider String The provider name Yes
symbols List The symbols we want to relay a price for Yes
prices List The prices for the respective symbols Yes

Response Example:

---Transaction Response---
txhash: "784728B42AD56D0241B166A531815FC82511432FF636E2AD22CBA856123F4AB1"
raw_log: "[]"

gas wanted: 172751
gas fee: 0.0000863755 INJ

ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

- Permissions

Permissions module provides an extra layer of configuration for all actions related to tokens: mint, transfer and burn.

AllNamespaces

Defines a gRPC query method that returns the permissions module's created namespaces

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    namespaces = await client.fetch_all_permissions_namespaces()
    print(namespaces)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("devnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    res, err := chainClient.FetchAllNamespaces(ctx)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}

No parameters

Response Parameters

Response Example:


ParameterTypeDescription
namespacesNamespace ArrayList of namespaces


Namespace

ParameterTypeDescription
denomStringToken denom
wasm_hookStringAddress of the wasm contract that will provide the real destination address
mints_pausedBoolMint action status
sends_pausedBoolSend action status
burns_pausedBoolBurn action status
role_permissionsRole ArrayList of roles
address_rolesAddressRoles ArrayList of Injective addresses and their associated role


Role

ParameterTypeDescription
roleStringRole name
permissionsIntegerInteger representing the bitwhise combination of all actions assigned to the role


PermissionAction

ParameterTypeDescription
roleStringRole name
permissionsIntegerInteger representing the bitwhise combination of all actions assigned to the role


AddressRoles

ParameterTypeDescription
addressStringInjective address
rolesString ArrayList of roles assigned to the address

NamespaceByDenom

Defines a gRPC query method that returns the permissions module's namespace associated with a denom

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    denom = "inj"
    namespace = await client.fetch_permissions_namespace_by_denom(denom=denom, include_roles=True)
    print(namespace)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("devnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    namespaceDenom := "factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test"

    ctx := context.Background()

    res, err := chainClient.FetchNamespaceByDenom(ctx, namespaceDenom, true)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
denomStringThe token denomYes
include_rolesBoolOption to request the roles in the responseNo

Response Parameters

Response Example:


ParameterTypeDescription
namespaceNamespaceThe namespace information (if found)


Namespace

ParameterTypeDescription
denomStringToken denom
wasm_hookStringAddress of the wasm contract that will provide the real destination address
mints_pausedBoolMint action status
sends_pausedBoolSend action status
burns_pausedBoolBurn action status
role_permissionsRole ArrayList of roles
address_rolesAddressRoles ArrayList of Injective addresses and their associated role


Role

ParameterTypeDescription
roleStringRole name
permissionsIntegerInteger representing the bitwhise combination of all actions assigned to the role


PermissionAction

ParameterTypeDescription
roleStringRole name
permissionsIntegerInteger representing the bitwhise combination of all actions assigned to the role


AddressRoles

ParameterTypeDescription
addressStringInjective address
rolesString ArrayList of roles assigned to the address

AddressRoles

Defines a gRPC query method that returns a namespace's roles associated with the provided address

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    denom = "inj"
    address = "inj1knhahceyp57j5x7xh69p7utegnnnfgxavmahjr"
    roles = await client.fetch_permissions_address_roles(denom=denom, address=address)
    print(roles)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("devnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    namespaceDenom := "factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test"
    address := senderAddress.String()

    ctx := context.Background()

    res, err := chainClient.FetchAddressRoles(ctx, namespaceDenom, address)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
denomStringThe token denomYes
addressStringThe Injective address to query the roles forYes

Response Parameters

Response Example:


ParameterTypeDescription
rolesString ArrayList of role names

AddressesByRole

Defines a query method that returns a namespace's roles associated with the provided address

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    denom = "inj"
    role = "roleName"
    addresses = await client.fetch_permissions_addresses_by_role(denom=denom, role=role)
    print(addresses)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("devnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    namespaceDenom := "factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test"
    role := "blacklisted"

    ctx := context.Background()

    res, err := chainClient.FetchAddressesByRole(ctx, namespaceDenom, role)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
denomStringThe token denomYes
roleStringThe role name to query the addresses forYes

Response Parameters

Response Example:


ParameterTypeDescription
addressesString ArrayList of Injective addresses

VouchersForAddress

Defines a query method that returns a map of vouchers that are held by permissions module for this address, keyed by the originator address

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    address = "inj1knhahceyp57j5x7xh69p7utegnnnfgxavmahjr"
    addresses = await client.fetch_permissions_vouchers_for_address(address=address)
    print(addresses)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("devnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    address := senderAddress.String()

    ctx := context.Background()

    res, err := chainClient.FetchVouchersForAddress(ctx, address)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
addressStringThe Injective address to query forYes

Response Parameters

Response Example:


ParameterTypeDescription
vouchersCoin ArrayList of available vouchers for the address


Coin

ParameterTypeDescriptionRequired
denomStringThe token denomYes
amountStringThe amount of tokensYes

CreateNamespace

Message to create a new namespace

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

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:
    dotenv.load_dotenv()
    private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.devnet()
    composer = ProtoMsgComposer(network=network.string())

    message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
        network=network,
        private_key=private_key_in_hexa,
    )

    priv_key = PrivateKey.from_hex(private_key_in_hexa)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()

    blocked_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
    denom = "factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test"
    role1 = composer.permissions_role(
        role=composer.DEFAULT_PERMISSIONS_EVERYONE_ROLE,
        permissions=composer.MINT_ACTION_PERMISSION
        | composer.RECEIVE_ACTION_PERMISSION
        | composer.BURN_ACTION_PERMISSION,
    )
    role2 = composer.permissions_role(role="blacklisted", permissions=composer.UNDEFINED_ACTION_PERMISSION)
    address_role1 = composer.permissions_address_roles(address=blocked_address, roles=["blacklisted"])

    message = composer.msg_create_namespace(
        sender=address.to_acc_bech32(),
        denom=denom,
        wasm_hook="",
        mints_paused=False,
        sends_paused=False,
        burns_paused=False,
        role_permissions=[role1, role2],
        address_roles=[address_role1],
    )

    # broadcast the transaction
    result = await message_broadcaster.broadcast([message])
    print("---Transaction Response---")
    print(result)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "encoding/json"
    "fmt"
    "os"

    permissionstypes "github.com/InjectiveLabs/sdk-go/chain/permissions/types"
    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("devnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    blockedAddress := "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
    namespace := permissionstypes.Namespace{
        Denom: "factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test",
        RolePermissions: []*permissionstypes.Role{
            {
                Role:        permissionstypes.EVERYONE,
                Permissions: uint32(permissionstypes.Action_MINT | permissionstypes.Action_RECEIVE | permissionstypes.Action_BURN),
            },
            {
                Role:        "blacklisted",
                Permissions: 0,
            },
        },
        AddressRoles: []*permissionstypes.AddressRoles{
            {
                Address: blockedAddress,
                Roles:   []string{"blacklisted"},
            },
        },
    }

    msg := &permissionstypes.MsgCreateNamespace{
        Sender:    senderAddress.String(),
        Namespace: namespace,
    }

    //AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    response, err := chainClient.SyncBroadcastMsg(msg)

    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(response, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
senderStringThe sender's Injective addressYes
namespaceNamespaceThe namespace informationYes


Namespace

ParameterTypeDescription
denomStringToken denom
wasm_hookStringAddress of the wasm contract that will provide the real destination address
mints_pausedBoolMint action status
sends_pausedBoolSend action status
burns_pausedBoolBurn action status
role_permissionsRole ArrayList of roles
address_rolesAddressRoles ArrayList of Injective addresses and their associated role


Role

ParameterTypeDescription
roleStringRole name
permissionsIntegerInteger representing the bitwhise combination of all actions assigned to the role


PermissionAction

ParameterTypeDescription
roleStringRole name
permissionsIntegerInteger representing the bitwhise combination of all actions assigned to the role


AddressRoles

ParameterTypeDescription
addressStringInjective address
rolesString ArrayList of roles assigned to the address

Response Parameters

Response Example:

ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

DeleteNamespace

Message to delete a namespace

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

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:
    dotenv.load_dotenv()
    private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.devnet()
    composer = ProtoMsgComposer(network=network.string())

    message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
        network=network,
        private_key=private_key_in_hexa,
    )

    priv_key = PrivateKey.from_hex(private_key_in_hexa)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()

    denom = "factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test"
    message = composer.msg_delete_namespace(
        sender=address.to_acc_bech32(),
        namespace_denom=denom,
    )

    # broadcast the transaction
    result = await message_broadcaster.broadcast([message])
    print("---Transaction Response---")
    print(result)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "encoding/json"
    "fmt"
    "os"

    permissionstypes "github.com/InjectiveLabs/sdk-go/chain/permissions/types"
    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("devnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    namespaceDenom := "factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test"

    msg := &permissionstypes.MsgDeleteNamespace{
        Sender:         senderAddress.String(),
        NamespaceDenom: namespaceDenom,
    }

    //AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    response, err := chainClient.SyncBroadcastMsg(msg)

    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(response, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
senderStringThe sender's Injective addressYes
namespace_denomStringThe token denom of the namespace to deleteYes

Response Parameters

Response Example:

ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

UpdateNamespace

Message to update a namespace configuration

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

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:
    dotenv.load_dotenv()
    private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.devnet()
    composer = ProtoMsgComposer(network=network.string())

    message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
        network=network,
        private_key=private_key_in_hexa,
    )

    priv_key = PrivateKey.from_hex(private_key_in_hexa)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()

    denom = "factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test"

    message = composer.msg_update_namespace(
        sender=address.to_acc_bech32(),
        namespace_denom=denom,
        wasm_hook="inj19ld6swyldyujcn72j7ugnu9twafhs9wxlyye5m",
        mints_paused=True,
        sends_paused=True,
        burns_paused=True,
    )

    # broadcast the transaction
    result = await message_broadcaster.broadcast([message])
    print("---Transaction Response---")
    print(result)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "encoding/json"
    "fmt"
    "os"

    permissionstypes "github.com/InjectiveLabs/sdk-go/chain/permissions/types"
    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("devnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    namespaceDenom := "factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test"

    msg := &permissionstypes.MsgUpdateNamespace{
        Sender:         senderAddress.String(),
        NamespaceDenom: namespaceDenom,
        WasmHook:       &permissionstypes.MsgUpdateNamespace_MsgSetWasmHook{NewValue: "inj19ld6swyldyujcn72j7ugnu9twafhs9wxlyye5m"},
        SendsPaused:    &permissionstypes.MsgUpdateNamespace_MsgSetSendsPaused{NewValue: true},
        MintsPaused:    &permissionstypes.MsgUpdateNamespace_MsgSetMintsPaused{NewValue: true},
        BurnsPaused:    &permissionstypes.MsgUpdateNamespace_MsgSetBurnsPaused{NewValue: true},
    }

    //AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    response, err := chainClient.SyncBroadcastMsg(msg)

    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(response, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
senderStringThe sender's Injective addressYes
namespace_denomStringThe token denom of the namespace to updateYes
wasm_hookStringAddress of the wasm contract that will provide the real destination addressYes
mints_pausedBoolMint action statusYes
sends_pausedBoolSend action statusYes
burns_pausedBoolBurn action statusYes

Response Parameters

Response Example:

ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

UpdateNamespaceRoles

Message to update a namespace roles

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

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:
    dotenv.load_dotenv()
    private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.devnet()
    composer = ProtoMsgComposer(network=network.string())

    message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
        network=network,
        private_key=private_key_in_hexa,
    )

    priv_key = PrivateKey.from_hex(private_key_in_hexa)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()

    blocked_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
    denom = "factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test"
    role1 = composer.permissions_role(
        role=composer.DEFAULT_PERMISSIONS_EVERYONE_ROLE,
        permissions=composer.RECEIVE_ACTION_PERMISSION,
    )
    role2 = composer.permissions_role(role="blacklisted", permissions=composer.UNDEFINED_ACTION_PERMISSION)
    address_role1 = composer.permissions_address_roles(address=blocked_address, roles=["blacklisted"])

    message = composer.msg_update_namespace_roles(
        sender=address.to_acc_bech32(),
        namespace_denom=denom,
        role_permissions=[role1, role2],
        address_roles=[address_role1],
    )

    # broadcast the transaction
    result = await message_broadcaster.broadcast([message])
    print("---Transaction Response---")
    print(result)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "encoding/json"
    "fmt"
    "os"

    permissionstypes "github.com/InjectiveLabs/sdk-go/chain/permissions/types"
    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("devnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    namespaceDenom := "factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test"
    blockedAddress := "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"

    msg := &permissionstypes.MsgUpdateNamespaceRoles{
        Sender:         senderAddress.String(),
        NamespaceDenom: namespaceDenom,
        RolePermissions: []*permissionstypes.Role{
            {
                Role:        permissionstypes.EVERYONE,
                Permissions: uint32(permissionstypes.Action_RECEIVE),
            },
            {
                Role:        "blacklisted",
                Permissions: 0,
            },
        },
        AddressRoles: []*permissionstypes.AddressRoles{
            {
                Address: blockedAddress,
                Roles:   []string{"blacklisted"},
            },
        },
    }

    //AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    response, err := chainClient.SyncBroadcastMsg(msg)

    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(response, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
senderStringThe sender's Injective addressYes
namespace_denomStringThe token denom of the namespace to updateYes
role_permissionsRole ArrayList of rolesYes
address_rolesAddressRoles ArrayList of Injective addresses and their associated roleYes


Role

ParameterTypeDescription
roleStringRole name
permissionsIntegerInteger representing the bitwhise combination of all actions assigned to the role


PermissionAction

ParameterTypeDescription
roleStringRole name
permissionsIntegerInteger representing the bitwhise combination of all actions assigned to the role


AddressRoles

ParameterTypeDescription
addressStringInjective address
rolesString ArrayList of roles assigned to the address

Response Parameters

Response Example:

ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

RevokeNamespaceRoles

Message to revoke roles from addresses

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

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:
    dotenv.load_dotenv()
    private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.devnet()
    composer = ProtoMsgComposer(network=network.string())

    message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
        network=network,
        private_key=private_key_in_hexa,
    )

    priv_key = PrivateKey.from_hex(private_key_in_hexa)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()

    blocked_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
    denom = "factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test"
    address_role1 = composer.permissions_address_roles(address=blocked_address, roles=["blacklisted"])

    message = composer.msg_revoke_namespace_roles(
        sender=address.to_acc_bech32(),
        namespace_denom=denom,
        address_roles_to_revoke=[address_role1],
    )

    # broadcast the transaction
    result = await message_broadcaster.broadcast([message])
    print("---Transaction Response---")
    print(result)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "encoding/json"
    "fmt"
    "os"

    permissionstypes "github.com/InjectiveLabs/sdk-go/chain/permissions/types"
    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("devnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    namespaceDenom := "factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test"
    blockedAddress := "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"

    msg := &permissionstypes.MsgRevokeNamespaceRoles{
        Sender:         senderAddress.String(),
        NamespaceDenom: namespaceDenom,
        AddressRolesToRevoke: []*permissionstypes.AddressRoles{
            {
                Address: blockedAddress,
                Roles:   []string{"blacklisted"},
            },
        },
    }

    //AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    response, err := chainClient.SyncBroadcastMsg(msg)

    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(response, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
senderStringThe sender's Injective addressYes
namespace_denomStringThe token denom of the namespace to updateYes
address_roles_to_revokeAddressRoles ArrayList of Injective addresses and their associated roleYes


AddressRoles

ParameterTypeDescription
addressStringInjective address
rolesString ArrayList of roles assigned to the address

Response Parameters

Response Example:

ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

ClaimVoucher

Message to claim existing vouchers for a particular address

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

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:
    dotenv.load_dotenv()
    private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.devnet()
    composer = ProtoMsgComposer(network=network.string())

    message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
        network=network,
        private_key=private_key_in_hexa,
    )

    priv_key = PrivateKey.from_hex(private_key_in_hexa)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()

    denom = "factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test"

    message = composer.msg_claim_voucher(
        sender=address.to_acc_bech32(),
        denom=denom,
    )

    # broadcast the transaction
    result = await message_broadcaster.broadcast([message])
    print("---Transaction Response---")
    print(result)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "encoding/json"
    "fmt"
    "os"

    permissionstypes "github.com/InjectiveLabs/sdk-go/chain/permissions/types"
    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("devnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    denom := "factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test"

    msg := &permissionstypes.MsgClaimVoucher{
        Sender: senderAddress.String(),
        Denom:  denom,
    }

    //AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    response, err := chainClient.SyncBroadcastMsg(msg)

    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(response, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
senderStringThe sender's Injective addressYes
denomStringThe token denom of the voucher to claimYes

Response Parameters

Response Example:

ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

- Staking

Includes the messages to claim and withdraw delegator rewards, and query staking state

ValidatorDistributionInfo

Queries validator commission and self-delegation rewards for validator

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    validator_address = "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z"
    distribution_info = await client.fetch_validator_distribution_info(validator_address=validator_address)
    print(distribution_info)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    validatorAddress := "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z"
    ctx := context.Background()

    res, err := chainClient.FetchValidatorDistributionInfo(ctx, validatorAddress)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
validator_addressStringThe validator address to query forYes

Response Parameters

Response Example:

{
   "operatorAddress":"inj1jue5dpr9lerjn6wlwtrywxrsenrf28rusrhqyx",
   "selfBondRewards":[
      {
         "denom":"inj",
         "amount":"520293543167557100000"
      }
   ],
   "commission":[
      {
         "denom":"inj",
         "amount":"105136140964470306856270639550202093130"
      }
   ]
}
ParameterTypeDescription
operator_addressStringThe validator operator address
self_bond_rewardsDecCoin ArrayThe self delegations rewards
commissionDecCoin ArrayThe commission the validator received


DecCoin

ParameterTypeDescription
denomStringThe token denom
amountStringThe amount of tokens

ValidatorOutstandingRewards

Queries rewards of a validator address

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    validator_address = "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z"
    rewards = await client.fetch_validator_outstanding_rewards(validator_address=validator_address)
    print(rewards)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    validatorAddress := "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z"
    ctx := context.Background()

    res, err := chainClient.FetchValidatorOutstandingRewards(ctx, validatorAddress)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
validator_addressStringThe validator address to query forYes

Response Parameters

Response Example:

{
   "rewards":{
      "rewards":[
         {
            "denom":"inj",
            "amount":"1997451426304473936130044829302179245433"
         }
      ]
   }
}
ParameterTypeDescription
rewardsValidatorOutstandingRewardsDetails of all the rewards


ValidatorOutstandingRewards

ParameterTypeDescription
rewardsDecCoin ArrayDetails of all the rewards


DecCoin

ParameterTypeDescription
denomStringThe token denom
amountStringThe amount of tokens

ValidatorCommission

Queries accumulated commission for a validator

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    validator_address = "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z"
    commission = await client.fetch_validator_commission(validator_address=validator_address)
    print(commission)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    validatorAddress := "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z"
    ctx := context.Background()

    res, err := chainClient.FetchValidatorCommission(ctx, validatorAddress)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
validator_addressStringThe validator address to query forYes

Response Parameters

Response Example:

{
   "commission":{
      "commission":[
         {
            "denom":"inj",
            "amount":"105379963222887965961634697913891232463"
         }
      ]
   }
}
ParameterTypeDescription
commissionValidatorAccumulatedCommissionThe commission the validator received


ValidatorAccumulatedCommission

ParameterTypeDescription
commissionDecCoin ArrayAccumulated commissions for the validator


DecCoin

ParameterTypeDescription
denomStringThe token denom
amountStringThe amount of tokens

ValidatorSlashes

Queries slash events of a validator

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    limit = 2
    pagination = PaginationOption(limit=limit)
    validator_address = "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z"
    contracts = await client.fetch_validator_slashes(validator_address=validator_address, pagination=pagination)
    print(contracts)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/cosmos/cosmos-sdk/types/query"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    validatorAddress := "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z"
    startingHeight := uint64(0)
    endingHeight := uint64(0)
    pagination := query.PageRequest{Limit: 10}
    ctx := context.Background()

    res, err := chainClient.FetchValidatorSlashes(ctx, validatorAddress, startingHeight, endingHeight, &pagination)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
validator_addressStringThe validator address to query forYes
starting_heightIntegerThe optional starting height to query the slashesNo
ending_heightIntegerThe optional ending height to query the slashesNo
paginationPageRequestThe optional pagination for the requestNo


PageRequest

ParameterTypeDescriptionRequired
keyByte ArrayKey is a value returned in PageResponse.next_key to begin querying the next page most efficiently. Only one of offset or key should be setNo
offsetIntegerNumeric offset that can be used when key is unavailable. It is less efficient than using key. Only one of offset or key should be setNo
limitIntegerTotal number of results to be returned in the result pageNo
count_totalBooleanSet to true to indicate that the result set should include a count of the total number of items available for pagination in UIs. It is only respected when offset is used. It is ignored when key is setNo
reverseBooleanReverse is set to true if results are to be returned in the descending orderNo

Response Parameters

Response Example:


ParameterTypeDescription
slashesValidatorSlashEvent ArraySlashes de validator received
paginationPageResponsePagination information in the response


ValidatorSlashEvent

ParameterTypeDescription
validator_periodIntegerThe period when the validator got slashed
fractionStringSlashing applied


PageResponse

ParameterTypeDescription
next_keyByte ArrayThe key to be passed to PageRequest.key to query the next page most efficiently. It will be empty if there are no more results.
totalIntegerTotal number of results available if PageRequest.count_total was set, its value is undefined otherwise

DelegationRewards

Queries the total rewards accrued by a delegation

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    delegator_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
    validator_address = "injvaloper156t3yxd4udv0h9gwagfcmwnmm3quy0nph7tyh5"
    rewards = await client.fetch_delegation_rewards(
        delegator_address=delegator_address, validator_address=validator_address
    )
    print(rewards)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    delegatorAddress := "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
    validatorAddress := "injvaloper156t3yxd4udv0h9gwagfcmwnmm3quy0nph7tyh5"
    ctx := context.Background()

    res, err := chainClient.FetchDelegationRewards(ctx, delegatorAddress, validatorAddress)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
delegator_addressStringDelegator address to query forYes
validator_addressStringValidator address to query forYes

Response Parameters

Response Example:

{
   "rewards":[
      {
         "denom":"inj",
         "amount":"1965602260312"
      }
   ]
}
ParameterTypeDescription
rewardsDecCoin ArrayThe rewards accrued by a delegation


DecCoin

ParameterTypeDescription
denomStringThe token denom
amountStringThe amount of tokens

DelegationTotalRewards

Queries the total rewards accrued by each validator

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    delegator_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
    rewards = await client.fetch_delegation_total_rewards(
        delegator_address=delegator_address,
    )
    print(rewards)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    delegatorAddress := "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
    ctx := context.Background()

    res, err := chainClient.FetchDelegationTotalRewards(ctx, delegatorAddress)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
delegator_addressStringThe delegator address to query forYes

Response Parameters

Response Example:

{
   "rewards":[
      {
         "validatorAddress":"injvaloper156t3yxd4udv0h9gwagfcmwnmm3quy0nph7tyh5",
         "reward":[
            {
               "denom":"inj",
               "amount":"1972565915361"
            }
         ]
      },
      {
         "validatorAddress":"injvaloper1cq6mvxqp978f6lxrh5s6c35ddr2slcj9h7tqng",
         "reward":[

         ]
      },
      {
         "validatorAddress":"injvaloper16nd8yqxe9p6ggnrz58qr7dxn5y2834yeytmczf",
         "reward":[

         ]
      },
      {
         "validatorAddress":"injvaloper1u3slvlxpyckrpdk28a45uthku87wck3e934kl0",
         "reward":[

         ]
      },
      {
         "validatorAddress":"injvaloper17lzhgs2d50qcwlwdn06y3sghphlwl3xxxgml46",
         "reward":[

         ]
      }
   ],
   "total":[
      {
         "denom":"inj",
         "amount":"1972565915361"
      }
   ]
}
ParameterTypeDescription
rewardsDelegationDelegatorReward ArrayAll the rewards accrued by a delegator
totalDecCoin ArrayThe sum of all rewards


DelegationDelegatorReward

ParameterTypeDescription
validator_addressStringThe validator's Injective address
rewardDecCoin ArrayList of all the rewards for the validator


DecCoin

ParameterTypeDescription
denomStringThe token denom
amountStringThe amount of tokens

DelegatorValidators

Queries the validators of a delegator

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    delegator_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
    validators = await client.fetch_delegator_validators(
        delegator_address=delegator_address,
    )
    print(validators)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    delegatorAddress := "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
    ctx := context.Background()

    res, err := chainClient.FetchDelegatorValidators(ctx, delegatorAddress)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
delegator_addressStringThe delegator address to query forYes

Response Parameters

Response Example:

{
   "validators":[
      "injvaloper156t3yxd4udv0h9gwagfcmwnmm3quy0nph7tyh5",
      "injvaloper1cq6mvxqp978f6lxrh5s6c35ddr2slcj9h7tqng",
      "injvaloper16nd8yqxe9p6ggnrz58qr7dxn5y2834yeytmczf",
      "injvaloper1u3slvlxpyckrpdk28a45uthku87wck3e934kl0",
      "injvaloper17lzhgs2d50qcwlwdn06y3sghphlwl3xxxgml46"
   ]
}
ParameterTypeDescription
validatorsString ArrayList of all validators a delegator is delegating for

DelegatorWithdrawAddress

Queries the withdraw address of a delegator

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    delegator_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
    withdraw_address = await client.fetch_delegator_withdraw_address(
        delegator_address=delegator_address,
    )
    print(withdraw_address)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    delegatorAddress := "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
    ctx := context.Background()

    res, err := chainClient.FetchDelegatorWithdrawAddress(ctx, delegatorAddress)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
delegator_addressStringThe delegator address to query forYes

Response Parameters

Response Example:

{
   "withdrawAddress":"inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
}
ParamterTypeDescription
withdraw_addressStringThe delegator's withdraw address

CommunityPool

Queries the community pool coins

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    community_pool = await client.fetch_community_pool()
    print(community_pool)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    res, err := chainClient.FetchCommunityPool(ctx)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}

No parameters

Response Parameters

Response Example:

{
   "pool":[
      {
         "denom":"inj",
         "amount":"619667912004889463981597377474655365826158034046"
      }
   ]
}
ParameterTypeDescription
poolDecCoin ArrayList of coins in the community pool


DecCoin

ParameterTypeDescription
denomStringThe token denom
amountStringThe amount of tokens

SetWithdrawAddress

Changes the withdraw address for a delegator (or validator self-delegation)

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective import AsyncClient, PrivateKey
from pyinjective.core.broadcaster import MsgBroadcasterWithPk
from pyinjective.core.network import Network


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    composer = await client.composer()

    message_broadcaster = MsgBroadcasterWithPk.new_without_simulation(
        network=network,
        private_key=configured_private_key,
        client=client,
        composer=composer,
    )

    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    withdraw_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"

    message = composer.msg_set_withdraw_address(
        delegator_address=address.to_acc_bech32(),
        withdraw_address=withdraw_address,
    )

    # broadcast the transaction
    result = await message_broadcaster.broadcast([message])
    print("---Transaction Response---")
    print(result)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "encoding/json"
    "fmt"
    "os"

    "github.com/cosmos/cosmos-sdk/x/distribution/types"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    withdrawAddress := "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"

    msg := &types.MsgSetWithdrawAddress{
        DelegatorAddress: senderAddress.String(),
        WithdrawAddress:  withdrawAddress,
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    response, err := chainClient.AsyncBroadcastMsg(msg)

    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(response, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
delegator_addressStringThe delegator's injective addressYes
withdraw_addressStringThe new withdraw addressYes

Response Parameters

Response Example:


ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgWithdrawDelegatorReward

Withdraw rewards of a delegator

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective.async_client import AsyncClient
from pyinjective.core.broadcaster import MsgBroadcasterWithPk
from pyinjective.core.network import Network
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    composer = await client.composer()

    message_broadcaster = MsgBroadcasterWithPk.new_without_simulation(
        network=network,
        private_key=configured_private_key,
        client=client,
        composer=composer,
    )

    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    # prepare tx msg
    validator_address = "injvaloper1ultw9r29l8nxy5u6thcgusjn95vsy2caw722q5"

    message = composer.msg_withdraw_delegator_reward(
        delegator_address=address.to_acc_bech32(), validator_address=validator_address
    )

    # broadcast the transaction
    result = await message_broadcaster.broadcast([message])
    print("---Transaction Response---")
    print(result)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "fmt"
    "os"
    "time"

    "github.com/InjectiveLabs/sdk-go/client"
    "github.com/InjectiveLabs/sdk-go/client/common"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
    distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    msg := new(distributiontypes.MsgWithdrawDelegatorReward)
    msg.DelegatorAddress = senderAddress.String()
    msg.ValidatorAddress = "injvaloper14gy4acwjm96wd20awm9ar6j54lev5p7espy9ug"

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    err = chainClient.QueueBroadcastMsg(msg)

    if err != nil {
        fmt.Println(err)
    }

    time.Sleep(time.Second * 5)

    gasFee, err := chainClient.GetGasFee()

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("gas fee:", gasFee, "INJ")
}
ParameterTypeDescriptionRequired
delegator_addressStringThe delegator's addressYes
validator_addressStringThe validator's addressYes

Response parameters

Response Example:

txhash: "0EDB245FE6F59F9DD8B6F03D56E6F37FE0D53DD85C62476BD7A1F72486D44F8E"
raw_log: "[]"

gas wanted: 191525
gas fee: 0.0000957625 INJ
DEBU[0001] broadcastTx with nonce 1321                   fn=func1 src="client/chain/chain.go:598"
DEBU[0003] msg batch committed successfully at height 5215332  fn=func1 src="client/chain/chain.go:619" txHash=A4F9D6998F075E875F611ED279B617EAB4C0332EBC347468EEDAD81DD8236C48
DEBU[0003] nonce incremented to 1322                     fn=func1 src="client/chain/chain.go:623"
DEBU[0003] gas wanted:  195046                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.000097523 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

WithdrawValidatorCommission

Withdraws the full commission to the validator address

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

from pyinjective.async_client import AsyncClient
from pyinjective.core.broadcaster import MsgBroadcasterWithPk
from pyinjective.core.network import Network
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    composer = await client.composer()

    message_broadcaster = MsgBroadcasterWithPk.new_without_simulation(
        network=network,
        private_key=configured_private_key,
        client=client,
        composer=composer,
    )

    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    # prepare tx msg
    validator_address = "injvaloper1ultw9r29l8nxy5u6thcgusjn95vsy2caw722q5"

    message = composer.msg_withdraw_validator_commission(validator_address=validator_address)

    # broadcast the transaction
    result = await message_broadcaster.broadcast([message])
    print("---Transaction Response---")
    print(result)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "encoding/json"
    "fmt"
    "os"

    "github.com/cosmos/cosmos-sdk/x/distribution/types"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    validatorAddress := "injvaloper1ultw9r29l8nxy5u6thcgusjn95vsy2caw722q5"

    msg := &types.MsgWithdrawValidatorCommission{
        ValidatorAddress: validatorAddress,
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    response, err := chainClient.AsyncBroadcastMsg(msg)

    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(response, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
validator_addressStringThe validator's addressYes

Response Parameters

Response Example:


ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

FundCommunityPool

Allows an account to directly fund the community pool

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os
from decimal import Decimal

import dotenv

from pyinjective import AsyncClient, PrivateKey
from pyinjective.core.broadcaster import MsgBroadcasterWithPk
from pyinjective.core.network import Network


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    composer = await client.composer()

    message_broadcaster = MsgBroadcasterWithPk.new_without_simulation(
        network=network,
        private_key=configured_private_key,
        client=client,
        composer=composer,
    )

    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    amount = composer.create_coin_amount(amount=Decimal("0.1"), token_name="INJ")

    message = composer.msg_fund_community_pool(
        amounts=[amount],
        depositor=address.to_acc_bech32(),
    )

    # broadcast the transaction
    result = await message_broadcaster.broadcast([message])
    print("---Transaction Response---")
    print(result)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "encoding/json"
    "fmt"
    "os"

    "cosmossdk.io/math"

    "github.com/cosmos/cosmos-sdk/types"
    distriutiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    amount := types.NewCoin("inj", math.NewInt(1))

    msg := &distriutiontypes.MsgFundCommunityPool{
        Amount:    []types.Coin{amount},
        Depositor: senderAddress.String(),
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    response, err := chainClient.AsyncBroadcastMsg(msg)

    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(response, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
amountCoin ArrayThe token amounts to transferYes
depositorStringThe depositor's accountYes


Coin

ParameterTypeDescriptionRequired
denomStringThe token denomYes
amountStringThe amount of tokensYes

Response Parameters

Response Example:


ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgDelegate

Performs a coins delegation from a delegator to a validator

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    # prepare tx msg
    validator_address = "injvaloper1ultw9r29l8nxy5u6thcgusjn95vsy2caw722q5"
    amount = 100

    msg = composer.MsgDelegate(
        delegator_address=address.to_acc_bech32(), validator_address=validator_address, amount=amount
    )

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "fmt"
    "os"
    "time"

    "cosmossdk.io/math"

    "github.com/InjectiveLabs/sdk-go/client"
    "github.com/InjectiveLabs/sdk-go/client/common"

    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
    sdktypes "github.com/cosmos/cosmos-sdk/types"
    stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    msg := new(stakingtypes.MsgDelegate)
    msg.DelegatorAddress = senderAddress.String()
    msg.ValidatorAddress = "injvaloper14gy4acwjm96wd20awm9ar6j54lev5p7espy9ug"
    msg.Amount = sdktypes.Coin{
        Denom: "inj", Amount: math.NewInt(1000000000000000000), // 1 INJ
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    err = chainClient.QueueBroadcastMsg(msg)

    if err != nil {
        fmt.Println(err)
    }

    time.Sleep(time.Second * 5)

    gasFee, err := chainClient.GetGasFee()

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("gas fee:", gasFee, "INJ")
}
ParameterTypeDescriptionRequired
delegator_addressStringThe delegator's addressYes
validator_addressStringThe validator's addressYes
amountCoinThe token amount to delegateYes


Coin

ParameterTypeDescriptionRequired
denomStringThe token denomYes
amountStringThe amount of tokensYes

Response Parameters

Response Example:

txhash: "0EDB245FE6F59F9DD8B6F03D56E6F37FE0D53DD85C62476BD7A1F72486D44F8E"
raw_log: "[]"

gas wanted: 191525
gas fee: 0.0000957625 INJ
DEBU[0001] broadcastTx with nonce 1318                   fn=func1 src="client/chain/chain.go:598"
DEBU[0003] msg batch committed successfully at height 5215234  fn=func1 src="client/chain/chain.go:619" txHash=1714F24FB2BEE871C0A5CED998CCB0C33069FF40F744AE2AEF3720F24893D92A
DEBU[0003] nonce incremented to 1319                     fn=func1 src="client/chain/chain.go:623"
DEBU[0003] gas wanted:  207846                           fn=func1 src="client/chain/chain.go:624"
gas fee: 0.000103923 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

- Tendermint

Cosmos Tendermint module

GetNodeInfo

Gets the current node info

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    node_info = await client.fetch_node_info()
    print(node_info)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    res, err := chainClient.FetchNodeInfo(ctx)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}

No parameters

Response Parameters

Response Example:

{
   "defaultNodeInfo":{
      "protocolVersion":{
         "p2p":"8",
         "block":"11",
         "app":"0"
      },
      "defaultNodeId":"53c19e8ba2deb109ba8d09dd41ae82bbddd74467",
      "listenAddr":"tcp://0.0.0.0:26656",
      "network":"injective-888",
      "version":"0.37.1",
      "channels":"QCAhIiMwOGBhAA==",
      "moniker":"injective",
      "other":{
         "txIndex":"on",
         "rpcAddress":"tcp://0.0.0.0:26657"
      }
   },
   "applicationVersion":{
      "name":"injective",
      "appName":"injectived",
      "gitCommit":"1f0a39381",
      "goVersion":"go version go1.19.13 linux/amd64",
      "buildDeps":[
         {
            "path":"cloud.google.com/go",
            "version":"v0.110.4",
            "sum":"h1:1JYyxKMN9hd5dR2MYTPWkGUgcoxVVhg0LKNKEo0qvmk="
         },
         {
            "path":"cloud.google.com/go/compute/metadata",
            "version":"v0.2.3",
            "sum":"h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY="
         }
      ],
      "cosmosSdkVersion":"v0.47.5",
      "version":"",
      "buildTags":""
   }
}
ParameterTypeDescription
default_node_infoDefaultNodeInfoNode information
application_versionVersionInfoNode version information


DefaultNodeInfo

ParameterTypeDescription
protocol_versionProtocolVersionProtocol version information
default_nod_idStringNode identifier
listen_addrStringURI of the node's listening endpoint
networkStringThe chain network name
versionStringThe version number
channelsBytesChannels information
monikerString
otherDefaultNodeInfoOtherExtra node information


ProtocolVersion

ParameterTypeDescription
p2pInteger
blockInteger
appInteger


DefaultNodeInfoOther

ParameterTypeDescription
tx_indexStringTX indexing status (on/off)
rpc_addressStringURI for RPC connections


VersionInfo

ParameterTypeDescription
nameStringThe chain name
app_nameStringApplication name
versionStringApplication version
git_commitStringGit commit hash
build_tagsStringApplication build tags
go_versionStringGoLang version used to compile the application
build_depsModule ArrayApplication dependencies
cosmos_sdk_versionStringCosmos SDK version used by the application


Module

ParameterTypeDescription
pathStringModule path
versionStringModule version
sumStringChecksum

GetSyncing

Returns the node's syncing status

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    syncing = await client.fetch_syncing()
    print(syncing)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    res, err := chainClient.FetchSyncing(ctx)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}

No parameters

Response Parameters

Response Example:

{
   "syncing":false
}
ParameterTypeDescription
syncingBooleanSyncing status

GetLatestBlock

Get the latest block

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    latest_block = await client.fetch_latest_block()
    print(latest_block)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    res, err := chainClient.FetchLatestBlock(ctx)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}

No parameters

Response Parameters

Response Example:

{
   "blockId":{
      "hash":"bCxPpTR4INvkmf3kAVYi1KhwzX0ySxQuhc8xBBFNmAo=",
      "partSetHeader":{
         "total":1,
         "hash":"6zGn+fBW1y4cpyos4g/tVNQdqS03D/jr/B68SYVvcbQ="
      }
   },
   "block":{
      "header":{
         "version":{
            "block":"11",
            "app":"0"
         },
         "chainId":"injective-888",
         "height":"23197636",
         "time":"2024-03-14T17:39:19.050602Z",
         "lastBlockId":{
            "hash":"SglGvXqUCRelE9NtLBiJ0EIBBxTXmztat4fVrYagYlM=",
            "partSetHeader":{
               "total":1,
               "hash":"AsAE1Sdl69RqHqaseeRn3U6N43gG9T710HUjXJi6fyw="
            }
         },
         "lastCommitHash":"EBSqUY4fpGLr2FmmcYsFa01H0PDWQLVuKslws5Un9zU=",
         "dataHash":"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
         "validatorsHash":"G0AQ0vfNXTLF7UcNXSvk6ZJRWFo09hadwJSm7haFV6I=",
         "nextValidatorsHash":"G0AQ0vfNXTLF7UcNXSvk6ZJRWFo09hadwJSm7haFV6I=",
         "consensusHash":"5bupI5wNP5Z/jvh5UG/269+5QPiQTXKRNRpGHwCqrU0=",
         "appHash":"UoJN/dwHiiDytgSt3xHcb9zkcP8eFZ+qFZWWclQ6SYg=",
         "lastResultsHash":"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
         "evidenceHash":"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
         "proposerAddress":"M5HjW2EATgO+uI+h2rRES5E7174="
      },
      "data":{
         "txs":[

         ]
      },
      "evidence":{
         "evidence":[

         ]
      },
      "lastCommit":{
         "height":"23197635",
         "blockId":{
            "hash":"SglGvXqUCRelE9NtLBiJ0EIBBxTXmztat4fVrYagYlM=",
            "partSetHeader":{
               "total":1,
               "hash":"AsAE1Sdl69RqHqaseeRn3U6N43gG9T710HUjXJi6fyw="
            }
         },
         "signatures":[
            {
               "blockIdFlag":"BLOCK_ID_FLAG_ABSENT",
               "timestamp":"0001-01-01T00:00:00Z",
               "validatorAddress":"",
               "signature":""
            },
            {
               "blockIdFlag":"BLOCK_ID_FLAG_COMMIT",
               "validatorAddress":"ObUXYdS8jfTSNPonUBFPJkft7eA=",
               "timestamp":"2024-03-14T17:39:19.050602Z",
               "signature":"3ZdA7LqXq4Hj5olf1XKusJ6NHCBkqjpty9pgmsxKyzSG0VL8Uf+Ro0NDuZo8jK4qfLsuctCte3rdGV6lG/cKAA=="
            },
            {
               "blockIdFlag":"BLOCK_ID_FLAG_COMMIT",
               "validatorAddress":"M5HjW2EATgO+uI+h2rRES5E7174=",
               "timestamp":"2024-03-14T17:39:19.044716221Z",
               "signature":"u8QVTQO/QZhNSzAwVCR3bGLUzryi9E+3jQ2COcHi46GfU0SpWOPNBvdbOHsEkRx6EKh0P0acB/hOnDE5JPp5AA=="
            },
            {
               "blockIdFlag":"BLOCK_ID_FLAG_COMMIT",
               "validatorAddress":"y8ctJ4QpJ0S7ZTVY7RTE4z1hS2c=",
               "timestamp":"2024-03-14T17:39:19.051153172Z",
               "signature":"0R/H5GkdKJszELjxfwX9qQlr5nuANTQYN9aTTDvKkUqJDoXW3OwbQPHtegKJlVKU8BT80D2Glng+SnQMO3JSCA=="
            }
         ],
         "round":0
      }
   },
   "sdkBlock":{
      "header":{
         "version":{
            "block":"11",
            "app":"0"
         },
         "chainId":"injective-888",
         "height":"23197636",
         "time":"2024-03-14T17:39:19.050602Z",
         "lastBlockId":{
            "hash":"SglGvXqUCRelE9NtLBiJ0EIBBxTXmztat4fVrYagYlM=",
            "partSetHeader":{
               "total":1,
               "hash":"AsAE1Sdl69RqHqaseeRn3U6N43gG9T710HUjXJi6fyw="
            }
         },
         "lastCommitHash":"EBSqUY4fpGLr2FmmcYsFa01H0PDWQLVuKslws5Un9zU=",
         "dataHash":"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
         "validatorsHash":"G0AQ0vfNXTLF7UcNXSvk6ZJRWFo09hadwJSm7haFV6I=",
         "nextValidatorsHash":"G0AQ0vfNXTLF7UcNXSvk6ZJRWFo09hadwJSm7haFV6I=",
         "consensusHash":"5bupI5wNP5Z/jvh5UG/269+5QPiQTXKRNRpGHwCqrU0=",
         "appHash":"UoJN/dwHiiDytgSt3xHcb9zkcP8eFZ+qFZWWclQ6SYg=",
         "lastResultsHash":"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
         "evidenceHash":"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
         "proposerAddress":"injvalcons1xwg7xkmpqp8q804c37sa4dzyfwgnh4a74ll9pz"
      },
      "data":{
         "txs":[

         ]
      },
      "evidence":{
         "evidence":[

         ]
      },
      "lastCommit":{
         "height":"23197635",
         "blockId":{
            "hash":"SglGvXqUCRelE9NtLBiJ0EIBBxTXmztat4fVrYagYlM=",
            "partSetHeader":{
               "total":1,
               "hash":"AsAE1Sdl69RqHqaseeRn3U6N43gG9T710HUjXJi6fyw="
            }
         },
         "signatures":[
            {
               "blockIdFlag":"BLOCK_ID_FLAG_ABSENT",
               "timestamp":"0001-01-01T00:00:00Z",
               "validatorAddress":"",
               "signature":""
            },
            {
               "blockIdFlag":"BLOCK_ID_FLAG_COMMIT",
               "validatorAddress":"ObUXYdS8jfTSNPonUBFPJkft7eA=",
               "timestamp":"2024-03-14T17:39:19.050602Z",
               "signature":"3ZdA7LqXq4Hj5olf1XKusJ6NHCBkqjpty9pgmsxKyzSG0VL8Uf+Ro0NDuZo8jK4qfLsuctCte3rdGV6lG/cKAA=="
            },
            {
               "blockIdFlag":"BLOCK_ID_FLAG_COMMIT",
               "validatorAddress":"M5HjW2EATgO+uI+h2rRES5E7174=",
               "timestamp":"2024-03-14T17:39:19.044716221Z",
               "signature":"u8QVTQO/QZhNSzAwVCR3bGLUzryi9E+3jQ2COcHi46GfU0SpWOPNBvdbOHsEkRx6EKh0P0acB/hOnDE5JPp5AA=="
            },
            {
               "blockIdFlag":"BLOCK_ID_FLAG_COMMIT",
               "validatorAddress":"y8ctJ4QpJ0S7ZTVY7RTE4z1hS2c=",
               "timestamp":"2024-03-14T17:39:19.051153172Z",
               "signature":"0R/H5GkdKJszELjxfwX9qQlr5nuANTQYN9aTTDvKkUqJDoXW3OwbQPHtegKJlVKU8BT80D2Glng+SnQMO3JSCA=="
            }
         ],
         "round":0
      }
   }
}
ParameterTypeDescription
block_idBlockIDBlock identifier
sdk_blockBlockBlock details


BlockID

ParameterTypeDescription
hashBytesBlock hash
part_set_headerPartSetHeader


PartSetHeader

ParameterTypeDescription
totalInteger
hashBytes


Block

ParameterTypeDescription
headerHeaderHeader information
dataDataBlock data
evidenceEvidenceList
last_commitCommit


Header

ParameterTypeDescription
versionConsensus
chain_idStringChain identifier
heightIntegerBlock height
timeTimeBlock time
last_block_idBlockIDPrevious block identifier
last_commit_hashBytesLast commit hash
data_hashBytesBlock data hash
validators_hashBytesValidators information hash
next_validators_hashBytesValidators information hash
consensus_hashBytesConsensus information hash
app_hashBytesApplication hash
last_result_hashBytesLast result hash
evidence_hashBytesEvidence data hash
proposer_addressStringBlock proposer's address


Consensus

ParameterTypeDescription
versionConsensus
chain_idStringChain identifier
heightIntegerBlock height
timeTimeBlock time
last_block_idBlockIDPrevious block identifier
last_commit_hashBytesLast commit hash
data_hashBytesBlock data hash
validators_hashBytesValidators information hash
next_validators_hashBytesValidators information hash
consensus_hashBytesConsensus information hash
app_hashBytesApplication hash
last_result_hashBytesLast result hash
evidence_hashBytesEvidence data hash
proposer_addressStringBlock proposer's address


Data

ParameterTypeDescription
txsByte ArrayTxs that will be applied by state @ block.Height+1. NOTE: not all txs here are valid. We're just agreeing on the order first. This means that block.AppHash does not include these txs.


EvidenceList

ParameterTypeDescription
evidenceEvidence ArrayBlock evidence


Evidence

ParameterTypeDescription
sumisEvidence_SumValid types for 'sum' are Evidence_DuplicateVoteEvidence and Evidence_LightClientAttackEvidence


Commit

ParameterTypeDescription
heightIntegerBlock height
roundIntegerConsensus round
block_idBlockIDBlock identifier
signaturesCommitSig ArraySigantures


CommitSig

ParameterTypeDescription
block_id_flagBlockIDFlagBlock height
validator_addressBytesValidator address
timestampTimeBlock time
signatureBytesBlock signature


BlockIDFlag

CodeName
0BLOCK_ID_FLAG_UNKNOWN
1BLOCK_ID_FLAG_ABSENT
2BLOCK_ID_FLAG_COMMIT
3BLOCK_ID_FLAG_NIL

GetBlockByHeight

Get the block for a given height

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    block = await client.fetch_block_by_height(height=15793860)
    print(block)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    height := int64(23040174)
    res, err := chainClient.FetchBlockByHeight(ctx, height)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescription
block_idBlockIDBlock identifier
sdk_blockBlockBlock details

Response Parameters

Response Example:

{
   "blockId":{
      "hash":"MNF+X0DQFIsnEJAzyTxHMD8vZChOpW4rQeSnRKBiJ1Y=",
      "partSetHeader":{
         "total":1,
         "hash":"Fqg81sOmF9dqH8lORXGat/mOFyqh52/lSHvsehg9OWk="
      }
   },
   "block":{
      "header":{
         "version":{
            "block":"11",
            "app":"0"
         },
         "chainId":"injective-888",
         "height":"15793860",
         "time":"2023-09-07T03:59:36.393462082Z",
         "lastBlockId":{
            "hash":"RRhRSiIf1E08mJAtACM4J1RFSVJ96eR0PBVuoD7rb2c=",
            "partSetHeader":{
               "total":1,
               "hash":"SeO5JkVtLUrhegd0rwDatDbvS5PQf/0Yvn+BmL1MOko="
            }
         },
         "lastCommitHash":"rNxjhSihfCPkPMak9qPlmUYeXRc0weFu1nmmKMUPLAQ=",
         "dataHash":"1RjS2VAhrWt2lLnVLozfeI7oAi7PoDILROzeheXN5H0=",
         "validatorsHash":"6lDaVNHY4DtceWtHsVS7SdR8XuPSATqQ7qNKWIxcnhg=",
         "nextValidatorsHash":"6lDaVNHY4DtceWtHsVS7SdR8XuPSATqQ7qNKWIxcnhg=",
         "consensusHash":"ItjUyLlUnqkCxmoaGPck+PeXC45MXx6zsLXxtOHeBTE=",
         "appHash":"Sv2MdUKQxwE/glEI8c8RFQKmc4HSyKO7j3sAqySultQ=",
         "lastResultsHash":"Le4RmI//Wh43Mq6ro+VMWn7ZbVZRw3HXUAQILODtag8=",
         "evidenceHash":"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
         "proposerAddress":"ObUXYdS8jfTSNPonUBFPJkft7eA="
      },
      "data":{
         "txs":[
            "CvMLCpUBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnUKKmluajF3bGY1NzdtbHd0eW01N3Njem1semtsN2tjdDAycXNsZHN4Z2p2NxIqaW5qMXIyNDh5c3IyeTQwcW0yazgzMHZhbnF4bm02dmNtbGhxcnVtczJlGhsKA2luahIUMTAwMDAwMDAwMDAwMDAwMDAwMDAKuQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSmAEKKmluajF3bGY1NzdtbHd0eW01N3Njem1semtsN2tjdDAycXNsZHN4Z2p2NxIqaW5qMXIyNDh5c3IyeTQwcW0yazgzMHZhbnF4bm02dmNtbGhxcnVtczJlGj4KL3BlZ2d5MHg4N2FCM0I0Qzg2NjFlMDdENjM3MjM2MTIxMUI5NmVkNERjMzZCMUI1EgsxMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMXdsZjU3N21sd3R5bTU3c2N6bWx6a2w3a2N0MDJxc2xkc3hnanY3EippbmoxcjI0OHlzcjJ5NDBxbTJrODMwdmFucXhubTZ2Y21saHFydW1zMmUaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvdXNkYxILMTAwMDAwMDAwMDAKxQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSpAEKKmluajF3bGY1NzdtbHd0eW01N3Njem1semtsN2tjdDAycXNsZHN4Z2p2NxIqaW5qMXIyNDh5c3IyeTQwcW0yazgzMHZhbnF4bm02dmNtbGhxcnVtczJlGkoKL3BlZ2d5MHg0NEMyMWFmQWFGMjBjMjcwRUJiRjU5MTRDZmMzYjUwMjIxNzNGRUI3EhcxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMXdsZjU3N21sd3R5bTU3c2N6bWx6a2w3a2N0MDJxc2xkc3hnanY3EippbmoxcjI0OHlzcjJ5NDBxbTJrODMwdmFucXhubTZ2Y21saHFydW1zMmUaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvYWF2ZRILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajF3bGY1NzdtbHd0eW01N3Njem1semtsN2tjdDAycXNsZHN4Z2p2NxIqaW5qMXIyNDh5c3IyeTQwcW0yazgzMHZhbnF4bm02dmNtbGhxcnVtczJlGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2NydhILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajF3bGY1NzdtbHd0eW01N3Njem1semtsN2tjdDAycXNsZHN4Z2p2NxIqaW5qMXIyNDh5c3IyeTQwcW0yazgzMHZhbnF4bm02dmNtbGhxcnVtczJlGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2N2eBILMTAwMDAwMDAwMDAKwQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSoAEKKmluajF3bGY1NzdtbHd0eW01N3Njem1semtsN2tjdDAycXNsZHN4Z2p2NxIqaW5qMXIyNDh5c3IyeTQwcW0yazgzMHZhbnF4bm02dmNtbGhxcnVtczJlGkYKN2ZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3NoaWISCzEwMDAwMDAwMDAwGJz+wwcSggEKYApUCi0vaW5qZWN0aXZlLmNyeXB0by52MWJldGExLmV0aHNlY3AyNTZrMS5QdWJLZXkSIwohAjr+rkaXrlMyQvUjnSB+viWNMY4CU7VHptUN/MxDVEOVEgQKAggBGLymARIeChcKA2luahIQMTYwMDAwMDAwMDAwMDAwMBCAqMMBGkCHh6hdDRsHw1dfkRZkwLOmP7uNT6RSwNJPIBf8dg1bsnLtzAhpBlAd1nF1V7oWvAvoZ/gVoiNVdzjCWYYcUB/s",
            "CvMLCpUBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnUKKmluajFwMmh2N2Z6NnY3ZTk5c3dramZhNjllcmhjaGNkeGgya3l4cWp6axIqaW5qMWN6dGw4aDU4bDh6Y3YyM2xtMHpyOGg4cnlzdTVoeGNmZ2Q1MHl1GhsKA2luahIUMTAwMDAwMDAwMDAwMDAwMDAwMDAKuQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSmAEKKmluajFwMmh2N2Z6NnY3ZTk5c3dramZhNjllcmhjaGNkeGgya3l4cWp6axIqaW5qMWN6dGw4aDU4bDh6Y3YyM2xtMHpyOGg4cnlzdTVoeGNmZ2Q1MHl1Gj4KL3BlZ2d5MHg4N2FCM0I0Qzg2NjFlMDdENjM3MjM2MTIxMUI5NmVkNERjMzZCMUI1EgsxMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMXAyaHY3Zno2djdlOTlzd2tqZmE2OWVyaGNoY2R4aDJreXhxanprEippbmoxY3p0bDhoNThsOHpjdjIzbG0wenI4aDhyeXN1NWh4Y2ZnZDUweXUaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvdXNkYxILMTAwMDAwMDAwMDAKxQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSpAEKKmluajFwMmh2N2Z6NnY3ZTk5c3dramZhNjllcmhjaGNkeGgya3l4cWp6axIqaW5qMWN6dGw4aDU4bDh6Y3YyM2xtMHpyOGg4cnlzdTVoeGNmZ2Q1MHl1GkoKL3BlZ2d5MHg0NEMyMWFmQWFGMjBjMjcwRUJiRjU5MTRDZmMzYjUwMjIxNzNGRUI3EhcxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMXAyaHY3Zno2djdlOTlzd2tqZmE2OWVyaGNoY2R4aDJreXhxanprEippbmoxY3p0bDhoNThsOHpjdjIzbG0wenI4aDhyeXN1NWh4Y2ZnZDUweXUaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvYWF2ZRILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFwMmh2N2Z6NnY3ZTk5c3dramZhNjllcmhjaGNkeGgya3l4cWp6axIqaW5qMWN6dGw4aDU4bDh6Y3YyM2xtMHpyOGg4cnlzdTVoeGNmZ2Q1MHl1GkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2NydhILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFwMmh2N2Z6NnY3ZTk5c3dramZhNjllcmhjaGNkeGgya3l4cWp6axIqaW5qMWN6dGw4aDU4bDh6Y3YyM2xtMHpyOGg4cnlzdTVoeGNmZ2Q1MHl1GkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2N2eBILMTAwMDAwMDAwMDAKwQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSoAEKKmluajFwMmh2N2Z6NnY3ZTk5c3dramZhNjllcmhjaGNkeGgya3l4cWp6axIqaW5qMWN6dGw4aDU4bDh6Y3YyM2xtMHpyOGg4cnlzdTVoeGNmZ2Q1MHl1GkYKN2ZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3NoaWISCzEwMDAwMDAwMDAwGJz+wwcSggEKYApUCi0vaW5qZWN0aXZlLmNyeXB0by52MWJldGExLmV0aHNlY3AyNTZrMS5QdWJLZXkSIwohA3SZsAXlR9pzcFHog/kjOFSR1EiYHVqNOnWpNWiq7NcuEgQKAggBGNmNARIeChcKA2luahIQMTYwMDAwMDAwMDAwMDAwMBCAqMMBGkA0yE1i3DE6GGITZpVWhESrrYNgKdPRPYKCAnz9QcAdEkwOLHJ9HgOz2Ok9NhjFN5akpyxZTKRGTFX11//hT3Wd",
            "CugFCrgECjgvaW5qZWN0aXZlLmV4Y2hhbmdlLnYxYmV0YTEuTXNnUHJpdmlsZWdlZEV4ZWN1dGVDb250cmFjdBL7AwoqaW5qMWV6dGttMzZ5NmMzZTZ6bXI0aGc0Zzc3YTZ3eWoweGMwZDVneDV2EngxMDIwMDAwMDAwIGZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3VzZGMsIDExMDAgcGVnZ3kweDg3YUIzQjRDODY2MWUwN0Q2MzcyMzYxMjExQjk2ZWQ0RGMzNkIxQjUaKmluajE3cTdkczB5aDdoaHR1c2ZmN2d6OGE1a3gydXd4cnV0dGx4dXI5NiKmAnsiYXJncyI6eyJtc2ciOnsic3Vic2NyaWJlIjp7fX0sInRyYWRlcl9zdWJhY2NvdW50X2lkIjoiMHhjODk3NmRjNzQ0ZDYyMzlkMGI2M2FkZDE1NDdiZGRkMzg5Mjc5YjBmMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIiwidmF1bHRfc3ViYWNjb3VudF9pZCI6IjB4ZjAzY2Q4M2M5N2Y1ZWViZTQxMjlmMjA0N2VkMmM2NTcxYzYxZjE2YjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMyJ9LCJuYW1lIjoiVmF1bHRTdWJzY3JpYmUiLCJvcmlnaW4iOiJpbmoxZXp0a20zNnk2YzNlNnptcjRoZzRnNzdhNnd5ajB4YzBkNWd4NXYifRjp/cMH+j+kAQovL2luamVjdGl2ZS50eXBlcy52MWJldGExLkV4dGVuc2lvbk9wdGlvbnNXZWIzVHgScQgFEippbmoxN2drdWV0OGY2cHNzeGQ4bnljbTNxcjlkOXk2OTlydXB2NjM5N3oaQS7bNDH7L/B112pVzWT5OTygLht+2aFCIbvRfdlbaJqFAEXaPzWWgHCwBc4C3bCN22c8OHvjiS4ExPfg9EKkTKgAEn4KXgpUCi0vaW5qZWN0aXZlLmNyeXB0by52MWJldGExLmV0aHNlY3AyNTZrMS5QdWJLZXkSIwohAp46ZxDpNDxsP5gvCZkCc84ZllP7P7q0tL57X7fN0WOcEgQKAgh/GGYSHAoWCgNpbmoSDzM2Mjg2MjUwMDAwMDAwMBDdpSwaQXHoIQ/X5yai6B0reASgAArSShjzpxprthDLEyr+zX7GR07Hr+r8UmZftLbafrcZfRX2UwFw8Q8pHaMINsSjckgb",
            "CvMLCpUBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnUKKmluajE5dXE4Z2Rta3hxZnJnaHRlazQ5d2E4azJmOGhobTN4ZTZ2OXZ4eBIqaW5qMXc5cnY1dTM1NWtlMDdjamY0d2cwd2EyY3ZhdG1keWNkaDZud2czGhsKA2luahIUMTAwMDAwMDAwMDAwMDAwMDAwMDAKuQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSmAEKKmluajE5dXE4Z2Rta3hxZnJnaHRlazQ5d2E4azJmOGhobTN4ZTZ2OXZ4eBIqaW5qMXc5cnY1dTM1NWtlMDdjamY0d2cwd2EyY3ZhdG1keWNkaDZud2czGj4KL3BlZ2d5MHg4N2FCM0I0Qzg2NjFlMDdENjM3MjM2MTIxMUI5NmVkNERjMzZCMUI1EgsxMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMTl1cThnZG1reHFmcmdodGVrNDl3YThrMmY4aGhtM3hlNnY5dnh4EippbmoxdzlydjV1MzU1a2UwN2NqZjR3ZzB3YTJjdmF0bWR5Y2RoNm53ZzMaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvdXNkYxILMTAwMDAwMDAwMDAKxQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSpAEKKmluajE5dXE4Z2Rta3hxZnJnaHRlazQ5d2E4azJmOGhobTN4ZTZ2OXZ4eBIqaW5qMXc5cnY1dTM1NWtlMDdjamY0d2cwd2EyY3ZhdG1keWNkaDZud2czGkoKL3BlZ2d5MHg0NEMyMWFmQWFGMjBjMjcwRUJiRjU5MTRDZmMzYjUwMjIxNzNGRUI3EhcxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMTl1cThnZG1reHFmcmdodGVrNDl3YThrMmY4aGhtM3hlNnY5dnh4EippbmoxdzlydjV1MzU1a2UwN2NqZjR3ZzB3YTJjdmF0bWR5Y2RoNm53ZzMaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvYWF2ZRILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajE5dXE4Z2Rta3hxZnJnaHRlazQ5d2E4azJmOGhobTN4ZTZ2OXZ4eBIqaW5qMXc5cnY1dTM1NWtlMDdjamY0d2cwd2EyY3ZhdG1keWNkaDZud2czGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2NydhILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajE5dXE4Z2Rta3hxZnJnaHRlazQ5d2E4azJmOGhobTN4ZTZ2OXZ4eBIqaW5qMXc5cnY1dTM1NWtlMDdjamY0d2cwd2EyY3ZhdG1keWNkaDZud2czGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2N2eBILMTAwMDAwMDAwMDAKwQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSoAEKKmluajE5dXE4Z2Rta3hxZnJnaHRlazQ5d2E4azJmOGhobTN4ZTZ2OXZ4eBIqaW5qMXc5cnY1dTM1NWtlMDdjamY0d2cwd2EyY3ZhdG1keWNkaDZud2czGkYKN2ZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3NoaWISCzEwMDAwMDAwMDAwGJ3+wwcSggEKYApUCi0vaW5qZWN0aXZlLmNyeXB0by52MWJldGExLmV0aHNlY3AyNTZrMS5QdWJLZXkSIwohA9YRhWDK9v8bR+HRAI7OzzTaeuCFfDffiIO9zTWhbk4cEgQKAggBGMmeARIeChcKA2luahIQMTYwMDAwMDAwMDAwMDAwMBCAqMMBGkBAcshkCtJATtQYYHVorDRUSOGQ7gR1bLp17ZXO5S5aTmB+pRc+/uz8cY3zfP28wpZE4BFa40sSn+vsN7YDc0Ne",
            "CvMLCpUBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnUKKmluajFocXJzbWZsdjc2dDB3MGZxcm16d3p4dHhxdWUzNG12MzRtc3h2bRIqaW5qMXVsMjM1c2ZwZm55bWNnOGdodXQ5OHV3c251NjlsbnpuYTN6ZGpkGhsKA2luahIUMTAwMDAwMDAwMDAwMDAwMDAwMDAKuQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSmAEKKmluajFocXJzbWZsdjc2dDB3MGZxcm16d3p4dHhxdWUzNG12MzRtc3h2bRIqaW5qMXVsMjM1c2ZwZm55bWNnOGdodXQ5OHV3c251NjlsbnpuYTN6ZGpkGj4KL3BlZ2d5MHg4N2FCM0I0Qzg2NjFlMDdENjM3MjM2MTIxMUI5NmVkNERjMzZCMUI1EgsxMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMWhxcnNtZmx2NzZ0MHcwZnFybXp3enh0eHF1ZTM0bXYzNG1zeHZtEippbmoxdWwyMzVzZnBmbnltY2c4Z2h1dDk4dXdzbnU2OWxuem5hM3pkamQaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvdXNkYxILMTAwMDAwMDAwMDAKxQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSpAEKKmluajFocXJzbWZsdjc2dDB3MGZxcm16d3p4dHhxdWUzNG12MzRtc3h2bRIqaW5qMXVsMjM1c2ZwZm55bWNnOGdodXQ5OHV3c251NjlsbnpuYTN6ZGpkGkoKL3BlZ2d5MHg0NEMyMWFmQWFGMjBjMjcwRUJiRjU5MTRDZmMzYjUwMjIxNzNGRUI3EhcxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMWhxcnNtZmx2NzZ0MHcwZnFybXp3enh0eHF1ZTM0bXYzNG1zeHZtEippbmoxdWwyMzVzZnBmbnltY2c4Z2h1dDk4dXdzbnU2OWxuem5hM3pkamQaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvYWF2ZRILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFocXJzbWZsdjc2dDB3MGZxcm16d3p4dHhxdWUzNG12MzRtc3h2bRIqaW5qMXVsMjM1c2ZwZm55bWNnOGdodXQ5OHV3c251NjlsbnpuYTN6ZGpkGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2NydhILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFocXJzbWZsdjc2dDB3MGZxcm16d3p4dHhxdWUzNG12MzRtc3h2bRIqaW5qMXVsMjM1c2ZwZm55bWNnOGdodXQ5OHV3c251NjlsbnpuYTN6ZGpkGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2N2eBILMTAwMDAwMDAwMDAKwQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSoAEKKmluajFocXJzbWZsdjc2dDB3MGZxcm16d3p4dHhxdWUzNG12MzRtc3h2bRIqaW5qMXVsMjM1c2ZwZm55bWNnOGdodXQ5OHV3c251NjlsbnpuYTN6ZGpkGkYKN2ZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3NoaWISCzEwMDAwMDAwMDAwGJ3+wwcSggEKYApUCi0vaW5qZWN0aXZlLmNyeXB0by52MWJldGExLmV0aHNlY3AyNTZrMS5QdWJLZXkSIwohAimG00m9nDJwqtOiErp8o619mH/3VcEADzWzSqGpnGdIEgQKAggBGLuRARIeChcKA2luahIQMTYwMDAwMDAwMDAwMDAwMBCAqMMBGkCnWeua6pt6p7Te8JuofcIaJWaZEhgiOuFqskm9sjQ9yi5qJkOEQXCmCRFCS5uYBpk0/1tuwYXJwtro9GdxHJMI",
            "CvMLCpUBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnUKKmluajFnMG04cTNrZHczMzNzeHEyOXc3bmMzNm1mZmN2aDgwZ3ZjZDM5ZBIqaW5qMW45d2ZoN2E2Y2cydWdneWdhZDlhZGxqODNhNHl3ZHp1dmhybXB2GhsKA2luahIUMTAwMDAwMDAwMDAwMDAwMDAwMDAKuQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSmAEKKmluajFnMG04cTNrZHczMzNzeHEyOXc3bmMzNm1mZmN2aDgwZ3ZjZDM5ZBIqaW5qMW45d2ZoN2E2Y2cydWdneWdhZDlhZGxqODNhNHl3ZHp1dmhybXB2Gj4KL3BlZ2d5MHg4N2FCM0I0Qzg2NjFlMDdENjM3MjM2MTIxMUI5NmVkNERjMzZCMUI1EgsxMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMWcwbThxM2tkdzMzM3N4cTI5dzduYzM2bWZmY3ZoODBndmNkMzlkEippbmoxbjl3Zmg3YTZjZzJ1Z2d5Z2FkOWFkbGo4M2E0eXdkenV2aHJtcHYaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvdXNkYxILMTAwMDAwMDAwMDAKxQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSpAEKKmluajFnMG04cTNrZHczMzNzeHEyOXc3bmMzNm1mZmN2aDgwZ3ZjZDM5ZBIqaW5qMW45d2ZoN2E2Y2cydWdneWdhZDlhZGxqODNhNHl3ZHp1dmhybXB2GkoKL3BlZ2d5MHg0NEMyMWFmQWFGMjBjMjcwRUJiRjU5MTRDZmMzYjUwMjIxNzNGRUI3EhcxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMWcwbThxM2tkdzMzM3N4cTI5dzduYzM2bWZmY3ZoODBndmNkMzlkEippbmoxbjl3Zmg3YTZjZzJ1Z2d5Z2FkOWFkbGo4M2E0eXdkenV2aHJtcHYaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvYWF2ZRILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFnMG04cTNrZHczMzNzeHEyOXc3bmMzNm1mZmN2aDgwZ3ZjZDM5ZBIqaW5qMW45d2ZoN2E2Y2cydWdneWdhZDlhZGxqODNhNHl3ZHp1dmhybXB2GkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2NydhILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFnMG04cTNrZHczMzNzeHEyOXc3bmMzNm1mZmN2aDgwZ3ZjZDM5ZBIqaW5qMW45d2ZoN2E2Y2cydWdneWdhZDlhZGxqODNhNHl3ZHp1dmhybXB2GkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2N2eBILMTAwMDAwMDAwMDAKwQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSoAEKKmluajFnMG04cTNrZHczMzNzeHEyOXc3bmMzNm1mZmN2aDgwZ3ZjZDM5ZBIqaW5qMW45d2ZoN2E2Y2cydWdneWdhZDlhZGxqODNhNHl3ZHp1dmhybXB2GkYKN2ZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3NoaWISCzEwMDAwMDAwMDAwGJ3+wwcSggEKYApUCi0vaW5qZWN0aXZlLmNyeXB0by52MWJldGExLmV0aHNlY3AyNTZrMS5QdWJLZXkSIwohAhKZIyozzEpDEuAl3ypUW3R3JoD7AtBIAujqq4wwPfVdEgQKAggBGOufARIeChcKA2luahIQMTYwMDAwMDAwMDAwMDAwMBCAqMMBGkDMNT7feu38IDUKGBHpWaoydtomgYQZjGPXjj7pb8fEj0MshAm2XfDad53SLdLeKmsXMjQ5cXyYyH15EwUxDYSU",
            "CvMLCpUBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnUKKmluajFueHpoZTk0Z3NjOWpzeXVjM3dxa3Vuanl2czhwNGVtZTBndTRrZRIqaW5qMWxxa2dyZGxoeXFreTN3ZzZybW54ZGo1a3d0ZXI3NGUydWowbWZmGhsKA2luahIUMTAwMDAwMDAwMDAwMDAwMDAwMDAKuQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSmAEKKmluajFueHpoZTk0Z3NjOWpzeXVjM3dxa3Vuanl2czhwNGVtZTBndTRrZRIqaW5qMWxxa2dyZGxoeXFreTN3ZzZybW54ZGo1a3d0ZXI3NGUydWowbWZmGj4KL3BlZ2d5MHg4N2FCM0I0Qzg2NjFlMDdENjM3MjM2MTIxMUI5NmVkNERjMzZCMUI1EgsxMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMW54emhlOTRnc2M5anN5dWMzd3FrdW5qeXZzOHA0ZW1lMGd1NGtlEippbmoxbHFrZ3JkbGh5cWt5M3dnNnJtbnhkajVrd3Rlcjc0ZTJ1ajBtZmYaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvdXNkYxILMTAwMDAwMDAwMDAKxQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSpAEKKmluajFueHpoZTk0Z3NjOWpzeXVjM3dxa3Vuanl2czhwNGVtZTBndTRrZRIqaW5qMWxxa2dyZGxoeXFreTN3ZzZybW54ZGo1a3d0ZXI3NGUydWowbWZmGkoKL3BlZ2d5MHg0NEMyMWFmQWFGMjBjMjcwRUJiRjU5MTRDZmMzYjUwMjIxNzNGRUI3EhcxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMW54emhlOTRnc2M5anN5dWMzd3FrdW5qeXZzOHA0ZW1lMGd1NGtlEippbmoxbHFrZ3JkbGh5cWt5M3dnNnJtbnhkajVrd3Rlcjc0ZTJ1ajBtZmYaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvYWF2ZRILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFueHpoZTk0Z3NjOWpzeXVjM3dxa3Vuanl2czhwNGVtZTBndTRrZRIqaW5qMWxxa2dyZGxoeXFreTN3ZzZybW54ZGo1a3d0ZXI3NGUydWowbWZmGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2NydhILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFueHpoZTk0Z3NjOWpzeXVjM3dxa3Vuanl2czhwNGVtZTBndTRrZRIqaW5qMWxxa2dyZGxoeXFreTN3ZzZybW54ZGo1a3d0ZXI3NGUydWowbWZmGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2N2eBILMTAwMDAwMDAwMDAKwQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSoAEKKmluajFueHpoZTk0Z3NjOWpzeXVjM3dxa3Vuanl2czhwNGVtZTBndTRrZRIqaW5qMWxxa2dyZGxoeXFreTN3ZzZybW54ZGo1a3d0ZXI3NGUydWowbWZmGkYKN2ZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3NoaWISCzEwMDAwMDAwMDAwGJ3+wwcSggEKYApUCi0vaW5qZWN0aXZlLmNyeXB0by52MWJldGExLmV0aHNlY3AyNTZrMS5QdWJLZXkSIwohAxg89Ih7H74zbkYrMXXb55tjKWTQJQ3D2Sk00p5Y0/ZEEgQKAggBGIqVARIeChcKA2luahIQMTYwMDAwMDAwMDAwMDAwMBCAqMMBGkCo/7pJIihg01V2zd+y3WH++KyVIB4m7WC9DAHPRzJIAghGLVJkAJjzGWTHrIGlh7CIira+E0UeSdy1Ag4GMBfS",
            "CvMLCpUBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnUKKmluajE5Y2hlY3h3enVmZjA5Zm02NmM1MDN4MnJtZmowa3l6emZoM2Z0ZhIqaW5qMWt0djIyYXp2dDVoOG5xejQ4d25ocXNqOTZ1bGU0eHgwZGF3N2pqGhsKA2luahIUMTAwMDAwMDAwMDAwMDAwMDAwMDAKuQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSmAEKKmluajE5Y2hlY3h3enVmZjA5Zm02NmM1MDN4MnJtZmowa3l6emZoM2Z0ZhIqaW5qMWt0djIyYXp2dDVoOG5xejQ4d25ocXNqOTZ1bGU0eHgwZGF3N2pqGj4KL3BlZ2d5MHg4N2FCM0I0Qzg2NjFlMDdENjM3MjM2MTIxMUI5NmVkNERjMzZCMUI1EgsxMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMTljaGVjeHd6dWZmMDlmbTY2YzUwM3gycm1majBreXp6ZmgzZnRmEippbmoxa3R2MjJhenZ0NWg4bnF6NDh3bmhxc2o5NnVsZTR4eDBkYXc3amoaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvdXNkYxILMTAwMDAwMDAwMDAKxQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSpAEKKmluajE5Y2hlY3h3enVmZjA5Zm02NmM1MDN4MnJtZmowa3l6emZoM2Z0ZhIqaW5qMWt0djIyYXp2dDVoOG5xejQ4d25ocXNqOTZ1bGU0eHgwZGF3N2pqGkoKL3BlZ2d5MHg0NEMyMWFmQWFGMjBjMjcwRUJiRjU5MTRDZmMzYjUwMjIxNzNGRUI3EhcxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMTljaGVjeHd6dWZmMDlmbTY2YzUwM3gycm1majBreXp6ZmgzZnRmEippbmoxa3R2MjJhenZ0NWg4bnF6NDh3bmhxc2o5NnVsZTR4eDBkYXc3amoaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvYWF2ZRILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajE5Y2hlY3h3enVmZjA5Zm02NmM1MDN4MnJtZmowa3l6emZoM2Z0ZhIqaW5qMWt0djIyYXp2dDVoOG5xejQ4d25ocXNqOTZ1bGU0eHgwZGF3N2pqGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2NydhILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajE5Y2hlY3h3enVmZjA5Zm02NmM1MDN4MnJtZmowa3l6emZoM2Z0ZhIqaW5qMWt0djIyYXp2dDVoOG5xejQ4d25ocXNqOTZ1bGU0eHgwZGF3N2pqGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2N2eBILMTAwMDAwMDAwMDAKwQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSoAEKKmluajE5Y2hlY3h3enVmZjA5Zm02NmM1MDN4MnJtZmowa3l6emZoM2Z0ZhIqaW5qMWt0djIyYXp2dDVoOG5xejQ4d25ocXNqOTZ1bGU0eHgwZGF3N2pqGkYKN2ZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3NoaWISCzEwMDAwMDAwMDAwGJ3+wwcSggEKYApUCi0vaW5qZWN0aXZlLmNyeXB0by52MWJldGExLmV0aHNlY3AyNTZrMS5QdWJLZXkSIwohAgVaAkMOV5+9OJP2xYw3tKy3aU3SiAIummY3gRAIGDj/EgQKAggBGOihARIeChcKA2luahIQMTYwMDAwMDAwMDAwMDAwMBCAqMMBGkBSSP+Fx12//aSYEjjLjr5gl5X4jOUktkOREMTfArsWVxl4Xl7cyV3f7kYAF7kBbQQqrgMerHsc9KePhRVoXB0k",
            "CvMLCpUBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnUKKmluajFwMzBra2w2dXh5YWhtOGhmMGVkOGY0MDJmNjdhMmo5eHJjNDJ5ZhIqaW5qMXo1ZzRwYXA3YThoaHhhYXkycG5md2czYXduNWRxcDVyNHN2OGthGhsKA2luahIUMTAwMDAwMDAwMDAwMDAwMDAwMDAKuQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSmAEKKmluajFwMzBra2w2dXh5YWhtOGhmMGVkOGY0MDJmNjdhMmo5eHJjNDJ5ZhIqaW5qMXo1ZzRwYXA3YThoaHhhYXkycG5md2czYXduNWRxcDVyNHN2OGthGj4KL3BlZ2d5MHg4N2FCM0I0Qzg2NjFlMDdENjM3MjM2MTIxMUI5NmVkNERjMzZCMUI1EgsxMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMXAzMGtrbDZ1eHlhaG04aGYwZWQ4ZjQwMmY2N2Eyajl4cmM0MnlmEippbmoxejVnNHBhcDdhOGhoeGFheTJwbmZ3ZzNhd241ZHFwNXI0c3Y4a2EaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvdXNkYxILMTAwMDAwMDAwMDAKxQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSpAEKKmluajFwMzBra2w2dXh5YWhtOGhmMGVkOGY0MDJmNjdhMmo5eHJjNDJ5ZhIqaW5qMXo1ZzRwYXA3YThoaHhhYXkycG5md2czYXduNWRxcDVyNHN2OGthGkoKL3BlZ2d5MHg0NEMyMWFmQWFGMjBjMjcwRUJiRjU5MTRDZmMzYjUwMjIxNzNGRUI3EhcxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMXAzMGtrbDZ1eHlhaG04aGYwZWQ4ZjQwMmY2N2Eyajl4cmM0MnlmEippbmoxejVnNHBhcDdhOGhoeGFheTJwbmZ3ZzNhd241ZHFwNXI0c3Y4a2EaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvYWF2ZRILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFwMzBra2w2dXh5YWhtOGhmMGVkOGY0MDJmNjdhMmo5eHJjNDJ5ZhIqaW5qMXo1ZzRwYXA3YThoaHhhYXkycG5md2czYXduNWRxcDVyNHN2OGthGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2NydhILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFwMzBra2w2dXh5YWhtOGhmMGVkOGY0MDJmNjdhMmo5eHJjNDJ5ZhIqaW5qMXo1ZzRwYXA3YThoaHhhYXkycG5md2czYXduNWRxcDVyNHN2OGthGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2N2eBILMTAwMDAwMDAwMDAKwQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSoAEKKmluajFwMzBra2w2dXh5YWhtOGhmMGVkOGY0MDJmNjdhMmo5eHJjNDJ5ZhIqaW5qMXo1ZzRwYXA3YThoaHhhYXkycG5md2czYXduNWRxcDVyNHN2OGthGkYKN2ZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3NoaWISCzEwMDAwMDAwMDAwGJ3+wwcSggEKYApUCi0vaW5qZWN0aXZlLmNyeXB0by52MWJldGExLmV0aHNlY3AyNTZrMS5QdWJLZXkSIwohAl0obf7huaZwDxwoKhqdWfwakrBU8rFlrc/Ihiquc4P5EgQKAggBGIOAARIeChcKA2luahIQMTYwMDAwMDAwMDAwMDAwMBCAqMMBGkCGyhKBN8mu+4qID3ZzBPskvusEorT6TXytayPg3k6UpGMaLx38dXS9wmX2yrLrn4G67rihS/fKVCG2yMhdwk4y",
            "CvMLCpUBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnUKKmluajE0dDVmOTRtNWZnNHY2ZHJzNHFxa2QzZDczM3k2c3MwbGp5eXFsbRIqaW5qMWhtOXVobWhrZHRyeXd6MG1xazh2YTQwMmUzdWQweXBqbHFmcjNqGhsKA2luahIUMTAwMDAwMDAwMDAwMDAwMDAwMDAKuQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSmAEKKmluajE0dDVmOTRtNWZnNHY2ZHJzNHFxa2QzZDczM3k2c3MwbGp5eXFsbRIqaW5qMWhtOXVobWhrZHRyeXd6MG1xazh2YTQwMmUzdWQweXBqbHFmcjNqGj4KL3BlZ2d5MHg4N2FCM0I0Qzg2NjFlMDdENjM3MjM2MTIxMUI5NmVkNERjMzZCMUI1EgsxMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMTR0NWY5NG01Zmc0djZkcnM0cXFrZDNkNzMzeTZzczBsanl5cWxtEippbmoxaG05dWhtaGtkdHJ5d3owbXFrOHZhNDAyZTN1ZDB5cGpscWZyM2oaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvdXNkYxILMTAwMDAwMDAwMDAKxQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSpAEKKmluajE0dDVmOTRtNWZnNHY2ZHJzNHFxa2QzZDczM3k2c3MwbGp5eXFsbRIqaW5qMWhtOXVobWhrZHRyeXd6MG1xazh2YTQwMmUzdWQweXBqbHFmcjNqGkoKL3BlZ2d5MHg0NEMyMWFmQWFGMjBjMjcwRUJiRjU5MTRDZmMzYjUwMjIxNzNGRUI3EhcxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMTR0NWY5NG01Zmc0djZkcnM0cXFrZDNkNzMzeTZzczBsanl5cWxtEippbmoxaG05dWhtaGtkdHJ5d3owbXFrOHZhNDAyZTN1ZDB5cGpscWZyM2oaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvYWF2ZRILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajE0dDVmOTRtNWZnNHY2ZHJzNHFxa2QzZDczM3k2c3MwbGp5eXFsbRIqaW5qMWhtOXVobWhrZHRyeXd6MG1xazh2YTQwMmUzdWQweXBqbHFmcjNqGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2NydhILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajE0dDVmOTRtNWZnNHY2ZHJzNHFxa2QzZDczM3k2c3MwbGp5eXFsbRIqaW5qMWhtOXVobWhrZHRyeXd6MG1xazh2YTQwMmUzdWQweXBqbHFmcjNqGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2N2eBILMTAwMDAwMDAwMDAKwQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSoAEKKmluajE0dDVmOTRtNWZnNHY2ZHJzNHFxa2QzZDczM3k2c3MwbGp5eXFsbRIqaW5qMWhtOXVobWhrZHRyeXd6MG1xazh2YTQwMmUzdWQweXBqbHFmcjNqGkYKN2ZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3NoaWISCzEwMDAwMDAwMDAwGJ3+wwcSggEKYApUCi0vaW5qZWN0aXZlLmNyeXB0by52MWJldGExLmV0aHNlY3AyNTZrMS5QdWJLZXkSIwohA4fTy5A+DmuZfsXgjM48ntVqTXlOBW287TjXr91D0VGREgQKAggBGLuVARIeChcKA2luahIQMTYwMDAwMDAwMDAwMDAwMBCAqMMBGkBdYIUr7S8ky4p9g+WWi2Ef8Cnq9W5eRsQ6Q6YNcnr0rhzy6lgo31o9tJg6XB0ZHtaJb00qBdU8/igNmfhEZXqk",
            "CvMLCpUBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnUKKmluajFhNHc5OXo0cWdxY2Q2bDZ1NGRqZnlsY3VjdDUzZHVxa3VxbnI1ZBIqaW5qMTUyNmszNmNrM2xodm1yZzhzeXlhODd0eTY5dXBsOHl6enJrNWZxGhsKA2luahIUMTAwMDAwMDAwMDAwMDAwMDAwMDAKuQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSmAEKKmluajFhNHc5OXo0cWdxY2Q2bDZ1NGRqZnlsY3VjdDUzZHVxa3VxbnI1ZBIqaW5qMTUyNmszNmNrM2xodm1yZzhzeXlhODd0eTY5dXBsOHl6enJrNWZxGj4KL3BlZ2d5MHg4N2FCM0I0Qzg2NjFlMDdENjM3MjM2MTIxMUI5NmVkNERjMzZCMUI1EgsxMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMWE0dzk5ejRxZ3FjZDZsNnU0ZGpmeWxjdWN0NTNkdXFrdXFucjVkEippbmoxNTI2azM2Y2szbGh2bXJnOHN5eWE4N3R5Njl1cGw4eXp6cms1ZnEaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvdXNkYxILMTAwMDAwMDAwMDAKxQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSpAEKKmluajFhNHc5OXo0cWdxY2Q2bDZ1NGRqZnlsY3VjdDUzZHVxa3VxbnI1ZBIqaW5qMTUyNmszNmNrM2xodm1yZzhzeXlhODd0eTY5dXBsOHl6enJrNWZxGkoKL3BlZ2d5MHg0NEMyMWFmQWFGMjBjMjcwRUJiRjU5MTRDZmMzYjUwMjIxNzNGRUI3EhcxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMWE0dzk5ejRxZ3FjZDZsNnU0ZGpmeWxjdWN0NTNkdXFrdXFucjVkEippbmoxNTI2azM2Y2szbGh2bXJnOHN5eWE4N3R5Njl1cGw4eXp6cms1ZnEaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvYWF2ZRILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFhNHc5OXo0cWdxY2Q2bDZ1NGRqZnlsY3VjdDUzZHVxa3VxbnI1ZBIqaW5qMTUyNmszNmNrM2xodm1yZzhzeXlhODd0eTY5dXBsOHl6enJrNWZxGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2NydhILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFhNHc5OXo0cWdxY2Q2bDZ1NGRqZnlsY3VjdDUzZHVxa3VxbnI1ZBIqaW5qMTUyNmszNmNrM2xodm1yZzhzeXlhODd0eTY5dXBsOHl6enJrNWZxGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2N2eBILMTAwMDAwMDAwMDAKwQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSoAEKKmluajFhNHc5OXo0cWdxY2Q2bDZ1NGRqZnlsY3VjdDUzZHVxa3VxbnI1ZBIqaW5qMTUyNmszNmNrM2xodm1yZzhzeXlhODd0eTY5dXBsOHl6enJrNWZxGkYKN2ZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3NoaWISCzEwMDAwMDAwMDAwGJ3+wwcSggEKYApUCi0vaW5qZWN0aXZlLmNyeXB0by52MWJldGExLmV0aHNlY3AyNTZrMS5QdWJLZXkSIwohArGVpE2Qtw7Pq625UTe8FZfqFAGc7IaBTZYPusGkLfnlEgQKAggBGMmAARIeChcKA2luahIQMTYwMDAwMDAwMDAwMDAwMBCAqMMBGkDk8e2Du8ReB4Jz73ZkpdaWHIBSo5x0XtILIMecnJzbQ3TykogSC6OQ+tWOCFQp9mUhff++iCbVpFwAx08k+zYS",
            "CvMLCpUBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnUKKmluajFnZHZ0ZGtsdjNxZzQzM3Z1bjlqYXBhZGFucjk2MHgwdTI0cWtxbBIqaW5qMWFlYTRtOGZhcnc5ZHI5Y204N2FnN2QwejZtY2ZwMm54bnYyOGE3GhsKA2luahIUMTAwMDAwMDAwMDAwMDAwMDAwMDAKuQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSmAEKKmluajFnZHZ0ZGtsdjNxZzQzM3Z1bjlqYXBhZGFucjk2MHgwdTI0cWtxbBIqaW5qMWFlYTRtOGZhcnc5ZHI5Y204N2FnN2QwejZtY2ZwMm54bnYyOGE3Gj4KL3BlZ2d5MHg4N2FCM0I0Qzg2NjFlMDdENjM3MjM2MTIxMUI5NmVkNERjMzZCMUI1EgsxMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMWdkdnRka2x2M3FnNDMzdnVuOWphcGFkYW5yOTYweDB1MjRxa3FsEippbmoxYWVhNG04ZmFydzlkcjljbTg3YWc3ZDB6Nm1jZnAybnhudjI4YTcaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvdXNkYxILMTAwMDAwMDAwMDAKxQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSpAEKKmluajFnZHZ0ZGtsdjNxZzQzM3Z1bjlqYXBhZGFucjk2MHgwdTI0cWtxbBIqaW5qMWFlYTRtOGZhcnc5ZHI5Y204N2FnN2QwejZtY2ZwMm54bnYyOGE3GkoKL3BlZ2d5MHg0NEMyMWFmQWFGMjBjMjcwRUJiRjU5MTRDZmMzYjUwMjIxNzNGRUI3EhcxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMWdkdnRka2x2M3FnNDMzdnVuOWphcGFkYW5yOTYweDB1MjRxa3FsEippbmoxYWVhNG04ZmFydzlkcjljbTg3YWc3ZDB6Nm1jZnAybnhudjI4YTcaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvYWF2ZRILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFnZHZ0ZGtsdjNxZzQzM3Z1bjlqYXBhZGFucjk2MHgwdTI0cWtxbBIqaW5qMWFlYTRtOGZhcnc5ZHI5Y204N2FnN2QwejZtY2ZwMm54bnYyOGE3GkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2NydhILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFnZHZ0ZGtsdjNxZzQzM3Z1bjlqYXBhZGFucjk2MHgwdTI0cWtxbBIqaW5qMWFlYTRtOGZhcnc5ZHI5Y204N2FnN2QwejZtY2ZwMm54bnYyOGE3GkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2N2eBILMTAwMDAwMDAwMDAKwQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSoAEKKmluajFnZHZ0ZGtsdjNxZzQzM3Z1bjlqYXBhZGFucjk2MHgwdTI0cWtxbBIqaW5qMWFlYTRtOGZhcnc5ZHI5Y204N2FnN2QwejZtY2ZwMm54bnYyOGE3GkYKN2ZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3NoaWISCzEwMDAwMDAwMDAwGJ3+wwcSggEKYApUCi0vaW5qZWN0aXZlLmNyeXB0by52MWJldGExLmV0aHNlY3AyNTZrMS5QdWJLZXkSIwohAz+Zjrtxo20HOm1w4l5I57H9MAmt+87msPR5/1R/D1McEgQKAggBGMSqARIeChcKA2luahIQMTYwMDAwMDAwMDAwMDAwMBCAqMMBGkDhGCp0+Crr0dfoCZrTb5otuTMtIxxTj9tWfxrfN7cnBTEgKFXVDlsXbay4Wlxz4QBVX4Fb6gtUgQbtDrazOEj9",
            "CvMLCpUBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnUKKmluajFobm1kbGVhdHR1N3RldHU2ZWt3dzlybTBjbTAzZXpnNWpsdHJxehIqaW5qMW02M3U1eWtzYWdzc2o3d2N4Zmw1czd0NHU4N2s3MGpmeW5uazJqGhsKA2luahIUMTAwMDAwMDAwMDAwMDAwMDAwMDAKuQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSmAEKKmluajFobm1kbGVhdHR1N3RldHU2ZWt3dzlybTBjbTAzZXpnNWpsdHJxehIqaW5qMW02M3U1eWtzYWdzc2o3d2N4Zmw1czd0NHU4N2s3MGpmeW5uazJqGj4KL3BlZ2d5MHg4N2FCM0I0Qzg2NjFlMDdENjM3MjM2MTIxMUI5NmVkNERjMzZCMUI1EgsxMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMWhubWRsZWF0dHU3dGV0dTZla3d3OXJtMGNtMDNlemc1amx0cnF6EippbmoxbTYzdTV5a3NhZ3Nzajd3Y3hmbDVzN3Q0dTg3azcwamZ5bm5rMmoaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvdXNkYxILMTAwMDAwMDAwMDAKxQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSpAEKKmluajFobm1kbGVhdHR1N3RldHU2ZWt3dzlybTBjbTAzZXpnNWpsdHJxehIqaW5qMW02M3U1eWtzYWdzc2o3d2N4Zmw1czd0NHU4N2s3MGpmeW5uazJqGkoKL3BlZ2d5MHg0NEMyMWFmQWFGMjBjMjcwRUJiRjU5MTRDZmMzYjUwMjIxNzNGRUI3EhcxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMWhubWRsZWF0dHU3dGV0dTZla3d3OXJtMGNtMDNlemc1amx0cnF6EippbmoxbTYzdTV5a3NhZ3Nzajd3Y3hmbDVzN3Q0dTg3azcwamZ5bm5rMmoaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvYWF2ZRILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFobm1kbGVhdHR1N3RldHU2ZWt3dzlybTBjbTAzZXpnNWpsdHJxehIqaW5qMW02M3U1eWtzYWdzc2o3d2N4Zmw1czd0NHU4N2s3MGpmeW5uazJqGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2NydhILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFobm1kbGVhdHR1N3RldHU2ZWt3dzlybTBjbTAzZXpnNWpsdHJxehIqaW5qMW02M3U1eWtzYWdzc2o3d2N4Zmw1czd0NHU4N2s3MGpmeW5uazJqGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2N2eBILMTAwMDAwMDAwMDAKwQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSoAEKKmluajFobm1kbGVhdHR1N3RldHU2ZWt3dzlybTBjbTAzZXpnNWpsdHJxehIqaW5qMW02M3U1eWtzYWdzc2o3d2N4Zmw1czd0NHU4N2s3MGpmeW5uazJqGkYKN2ZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3NoaWISCzEwMDAwMDAwMDAwGJ3+wwcSggEKYApUCi0vaW5qZWN0aXZlLmNyeXB0by52MWJldGExLmV0aHNlY3AyNTZrMS5QdWJLZXkSIwohA+OlGuxc2hUmrU+iVLb2MDnHy6W4exQyJrbMie9/Sv27EgQKAggBGJqQARIeChcKA2luahIQMTYwMDAwMDAwMDAwMDAwMBCAqMMBGkBTfe9A/RDSoHQCDunT60QgdtBrz3eIGvIgLEISRMAh/2w3+A9UB5SoDNGZNUfpNsxZyyq2Emi6pXuVpFzUCjI5"
         ]
      },
      "evidence":{
         "evidence":[

         ]
      },
      "lastCommit":{
         "height":"15793859",
         "blockId":{
            "hash":"RRhRSiIf1E08mJAtACM4J1RFSVJ96eR0PBVuoD7rb2c=",
            "partSetHeader":{
               "total":1,
               "hash":"SeO5JkVtLUrhegd0rwDatDbvS5PQf/0Yvn+BmL1MOko="
            }
         },
         "signatures":[
            {
               "blockIdFlag":"BLOCK_ID_FLAG_COMMIT",
               "validatorAddress":"y8ctJ4QpJ0S7ZTVY7RTE4z1hS2c=",
               "timestamp":"2023-09-07T03:59:36.496584825Z",
               "signature":"AxnPc5AEa6jizZuKhXUAkNi4vic6miF9emyAx+uSMco7oKVwoXGDJ6L0wneNGYOqpKkMVMQm4hcnWgDBjiBLAA=="
            },
            {
               "blockIdFlag":"BLOCK_ID_FLAG_COMMIT",
               "validatorAddress":"M5HjW2EATgO+uI+h2rRES5E7174=",
               "timestamp":"2023-09-07T03:59:36.293269404Z",
               "signature":"mjODCd7P7xHo6Gn+6Qi6/u+FI72noRs9/vcbvpiqz7Hr5hRNhk2a2Jj2tw59GC6cURd2Q6c/CdZhXHgVqzMdAg=="
            },
            {
               "blockIdFlag":"BLOCK_ID_FLAG_COMMIT",
               "validatorAddress":"Nv8cuLE25L4mgnBx8shCmG68xfc=",
               "timestamp":"2023-09-07T03:59:36.393462082Z",
               "signature":"NyTk5W6WLxEbouVJ7LxSwV88FnH/CtmXkr6JczPqEehdrymqrGqT02OJLutGVsBmrPEkMhwa2BegkqvmPLJrBQ=="
            },
            {
               "blockIdFlag":"BLOCK_ID_FLAG_COMMIT",
               "validatorAddress":"ObUXYdS8jfTSNPonUBFPJkft7eA=",
               "timestamp":"2023-09-07T03:59:36.296674286Z",
               "signature":"OAwmf7pEjsXbwIWMD5HbzWiae6OAn0ME49FbXaRLvKIYKWSDKv9f0gprsgRJznOdj60SontlntwmvV+23MV6DQ=="
            }
         ],
         "round":0
      }
   },
   "sdkBlock":{
      "header":{
         "version":{
            "block":"11",
            "app":"0"
         },
         "chainId":"injective-888",
         "height":"15793860",
         "time":"2023-09-07T03:59:36.393462082Z",
         "lastBlockId":{
            "hash":"RRhRSiIf1E08mJAtACM4J1RFSVJ96eR0PBVuoD7rb2c=",
            "partSetHeader":{
               "total":1,
               "hash":"SeO5JkVtLUrhegd0rwDatDbvS5PQf/0Yvn+BmL1MOko="
            }
         },
         "lastCommitHash":"rNxjhSihfCPkPMak9qPlmUYeXRc0weFu1nmmKMUPLAQ=",
         "dataHash":"1RjS2VAhrWt2lLnVLozfeI7oAi7PoDILROzeheXN5H0=",
         "validatorsHash":"6lDaVNHY4DtceWtHsVS7SdR8XuPSATqQ7qNKWIxcnhg=",
         "nextValidatorsHash":"6lDaVNHY4DtceWtHsVS7SdR8XuPSATqQ7qNKWIxcnhg=",
         "consensusHash":"ItjUyLlUnqkCxmoaGPck+PeXC45MXx6zsLXxtOHeBTE=",
         "appHash":"Sv2MdUKQxwE/glEI8c8RFQKmc4HSyKO7j3sAqySultQ=",
         "lastResultsHash":"Le4RmI//Wh43Mq6ro+VMWn7ZbVZRw3HXUAQILODtag8=",
         "evidenceHash":"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
         "proposerAddress":"injvalcons18x63wcw5hjxlf535lgn4qy20yer7mm0qedu0la"
      },
      "data":{
         "txs":[
            "CvMLCpUBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnUKKmluajF3bGY1NzdtbHd0eW01N3Njem1semtsN2tjdDAycXNsZHN4Z2p2NxIqaW5qMXIyNDh5c3IyeTQwcW0yazgzMHZhbnF4bm02dmNtbGhxcnVtczJlGhsKA2luahIUMTAwMDAwMDAwMDAwMDAwMDAwMDAKuQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSmAEKKmluajF3bGY1NzdtbHd0eW01N3Njem1semtsN2tjdDAycXNsZHN4Z2p2NxIqaW5qMXIyNDh5c3IyeTQwcW0yazgzMHZhbnF4bm02dmNtbGhxcnVtczJlGj4KL3BlZ2d5MHg4N2FCM0I0Qzg2NjFlMDdENjM3MjM2MTIxMUI5NmVkNERjMzZCMUI1EgsxMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMXdsZjU3N21sd3R5bTU3c2N6bWx6a2w3a2N0MDJxc2xkc3hnanY3EippbmoxcjI0OHlzcjJ5NDBxbTJrODMwdmFucXhubTZ2Y21saHFydW1zMmUaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvdXNkYxILMTAwMDAwMDAwMDAKxQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSpAEKKmluajF3bGY1NzdtbHd0eW01N3Njem1semtsN2tjdDAycXNsZHN4Z2p2NxIqaW5qMXIyNDh5c3IyeTQwcW0yazgzMHZhbnF4bm02dmNtbGhxcnVtczJlGkoKL3BlZ2d5MHg0NEMyMWFmQWFGMjBjMjcwRUJiRjU5MTRDZmMzYjUwMjIxNzNGRUI3EhcxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMXdsZjU3N21sd3R5bTU3c2N6bWx6a2w3a2N0MDJxc2xkc3hnanY3EippbmoxcjI0OHlzcjJ5NDBxbTJrODMwdmFucXhubTZ2Y21saHFydW1zMmUaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvYWF2ZRILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajF3bGY1NzdtbHd0eW01N3Njem1semtsN2tjdDAycXNsZHN4Z2p2NxIqaW5qMXIyNDh5c3IyeTQwcW0yazgzMHZhbnF4bm02dmNtbGhxcnVtczJlGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2NydhILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajF3bGY1NzdtbHd0eW01N3Njem1semtsN2tjdDAycXNsZHN4Z2p2NxIqaW5qMXIyNDh5c3IyeTQwcW0yazgzMHZhbnF4bm02dmNtbGhxcnVtczJlGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2N2eBILMTAwMDAwMDAwMDAKwQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSoAEKKmluajF3bGY1NzdtbHd0eW01N3Njem1semtsN2tjdDAycXNsZHN4Z2p2NxIqaW5qMXIyNDh5c3IyeTQwcW0yazgzMHZhbnF4bm02dmNtbGhxcnVtczJlGkYKN2ZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3NoaWISCzEwMDAwMDAwMDAwGJz+wwcSggEKYApUCi0vaW5qZWN0aXZlLmNyeXB0by52MWJldGExLmV0aHNlY3AyNTZrMS5QdWJLZXkSIwohAjr+rkaXrlMyQvUjnSB+viWNMY4CU7VHptUN/MxDVEOVEgQKAggBGLymARIeChcKA2luahIQMTYwMDAwMDAwMDAwMDAwMBCAqMMBGkCHh6hdDRsHw1dfkRZkwLOmP7uNT6RSwNJPIBf8dg1bsnLtzAhpBlAd1nF1V7oWvAvoZ/gVoiNVdzjCWYYcUB/s",
            "CvMLCpUBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnUKKmluajFwMmh2N2Z6NnY3ZTk5c3dramZhNjllcmhjaGNkeGgya3l4cWp6axIqaW5qMWN6dGw4aDU4bDh6Y3YyM2xtMHpyOGg4cnlzdTVoeGNmZ2Q1MHl1GhsKA2luahIUMTAwMDAwMDAwMDAwMDAwMDAwMDAKuQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSmAEKKmluajFwMmh2N2Z6NnY3ZTk5c3dramZhNjllcmhjaGNkeGgya3l4cWp6axIqaW5qMWN6dGw4aDU4bDh6Y3YyM2xtMHpyOGg4cnlzdTVoeGNmZ2Q1MHl1Gj4KL3BlZ2d5MHg4N2FCM0I0Qzg2NjFlMDdENjM3MjM2MTIxMUI5NmVkNERjMzZCMUI1EgsxMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMXAyaHY3Zno2djdlOTlzd2tqZmE2OWVyaGNoY2R4aDJreXhxanprEippbmoxY3p0bDhoNThsOHpjdjIzbG0wenI4aDhyeXN1NWh4Y2ZnZDUweXUaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvdXNkYxILMTAwMDAwMDAwMDAKxQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSpAEKKmluajFwMmh2N2Z6NnY3ZTk5c3dramZhNjllcmhjaGNkeGgya3l4cWp6axIqaW5qMWN6dGw4aDU4bDh6Y3YyM2xtMHpyOGg4cnlzdTVoeGNmZ2Q1MHl1GkoKL3BlZ2d5MHg0NEMyMWFmQWFGMjBjMjcwRUJiRjU5MTRDZmMzYjUwMjIxNzNGRUI3EhcxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMXAyaHY3Zno2djdlOTlzd2tqZmE2OWVyaGNoY2R4aDJreXhxanprEippbmoxY3p0bDhoNThsOHpjdjIzbG0wenI4aDhyeXN1NWh4Y2ZnZDUweXUaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvYWF2ZRILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFwMmh2N2Z6NnY3ZTk5c3dramZhNjllcmhjaGNkeGgya3l4cWp6axIqaW5qMWN6dGw4aDU4bDh6Y3YyM2xtMHpyOGg4cnlzdTVoeGNmZ2Q1MHl1GkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2NydhILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFwMmh2N2Z6NnY3ZTk5c3dramZhNjllcmhjaGNkeGgya3l4cWp6axIqaW5qMWN6dGw4aDU4bDh6Y3YyM2xtMHpyOGg4cnlzdTVoeGNmZ2Q1MHl1GkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2N2eBILMTAwMDAwMDAwMDAKwQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSoAEKKmluajFwMmh2N2Z6NnY3ZTk5c3dramZhNjllcmhjaGNkeGgya3l4cWp6axIqaW5qMWN6dGw4aDU4bDh6Y3YyM2xtMHpyOGg4cnlzdTVoeGNmZ2Q1MHl1GkYKN2ZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3NoaWISCzEwMDAwMDAwMDAwGJz+wwcSggEKYApUCi0vaW5qZWN0aXZlLmNyeXB0by52MWJldGExLmV0aHNlY3AyNTZrMS5QdWJLZXkSIwohA3SZsAXlR9pzcFHog/kjOFSR1EiYHVqNOnWpNWiq7NcuEgQKAggBGNmNARIeChcKA2luahIQMTYwMDAwMDAwMDAwMDAwMBCAqMMBGkA0yE1i3DE6GGITZpVWhESrrYNgKdPRPYKCAnz9QcAdEkwOLHJ9HgOz2Ok9NhjFN5akpyxZTKRGTFX11//hT3Wd",
            "CugFCrgECjgvaW5qZWN0aXZlLmV4Y2hhbmdlLnYxYmV0YTEuTXNnUHJpdmlsZWdlZEV4ZWN1dGVDb250cmFjdBL7AwoqaW5qMWV6dGttMzZ5NmMzZTZ6bXI0aGc0Zzc3YTZ3eWoweGMwZDVneDV2EngxMDIwMDAwMDAwIGZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3VzZGMsIDExMDAgcGVnZ3kweDg3YUIzQjRDODY2MWUwN0Q2MzcyMzYxMjExQjk2ZWQ0RGMzNkIxQjUaKmluajE3cTdkczB5aDdoaHR1c2ZmN2d6OGE1a3gydXd4cnV0dGx4dXI5NiKmAnsiYXJncyI6eyJtc2ciOnsic3Vic2NyaWJlIjp7fX0sInRyYWRlcl9zdWJhY2NvdW50X2lkIjoiMHhjODk3NmRjNzQ0ZDYyMzlkMGI2M2FkZDE1NDdiZGRkMzg5Mjc5YjBmMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIiwidmF1bHRfc3ViYWNjb3VudF9pZCI6IjB4ZjAzY2Q4M2M5N2Y1ZWViZTQxMjlmMjA0N2VkMmM2NTcxYzYxZjE2YjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMyJ9LCJuYW1lIjoiVmF1bHRTdWJzY3JpYmUiLCJvcmlnaW4iOiJpbmoxZXp0a20zNnk2YzNlNnptcjRoZzRnNzdhNnd5ajB4YzBkNWd4NXYifRjp/cMH+j+kAQovL2luamVjdGl2ZS50eXBlcy52MWJldGExLkV4dGVuc2lvbk9wdGlvbnNXZWIzVHgScQgFEippbmoxN2drdWV0OGY2cHNzeGQ4bnljbTNxcjlkOXk2OTlydXB2NjM5N3oaQS7bNDH7L/B112pVzWT5OTygLht+2aFCIbvRfdlbaJqFAEXaPzWWgHCwBc4C3bCN22c8OHvjiS4ExPfg9EKkTKgAEn4KXgpUCi0vaW5qZWN0aXZlLmNyeXB0by52MWJldGExLmV0aHNlY3AyNTZrMS5QdWJLZXkSIwohAp46ZxDpNDxsP5gvCZkCc84ZllP7P7q0tL57X7fN0WOcEgQKAgh/GGYSHAoWCgNpbmoSDzM2Mjg2MjUwMDAwMDAwMBDdpSwaQXHoIQ/X5yai6B0reASgAArSShjzpxprthDLEyr+zX7GR07Hr+r8UmZftLbafrcZfRX2UwFw8Q8pHaMINsSjckgb",
            "CvMLCpUBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnUKKmluajE5dXE4Z2Rta3hxZnJnaHRlazQ5d2E4azJmOGhobTN4ZTZ2OXZ4eBIqaW5qMXc5cnY1dTM1NWtlMDdjamY0d2cwd2EyY3ZhdG1keWNkaDZud2czGhsKA2luahIUMTAwMDAwMDAwMDAwMDAwMDAwMDAKuQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSmAEKKmluajE5dXE4Z2Rta3hxZnJnaHRlazQ5d2E4azJmOGhobTN4ZTZ2OXZ4eBIqaW5qMXc5cnY1dTM1NWtlMDdjamY0d2cwd2EyY3ZhdG1keWNkaDZud2czGj4KL3BlZ2d5MHg4N2FCM0I0Qzg2NjFlMDdENjM3MjM2MTIxMUI5NmVkNERjMzZCMUI1EgsxMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMTl1cThnZG1reHFmcmdodGVrNDl3YThrMmY4aGhtM3hlNnY5dnh4EippbmoxdzlydjV1MzU1a2UwN2NqZjR3ZzB3YTJjdmF0bWR5Y2RoNm53ZzMaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvdXNkYxILMTAwMDAwMDAwMDAKxQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSpAEKKmluajE5dXE4Z2Rta3hxZnJnaHRlazQ5d2E4azJmOGhobTN4ZTZ2OXZ4eBIqaW5qMXc5cnY1dTM1NWtlMDdjamY0d2cwd2EyY3ZhdG1keWNkaDZud2czGkoKL3BlZ2d5MHg0NEMyMWFmQWFGMjBjMjcwRUJiRjU5MTRDZmMzYjUwMjIxNzNGRUI3EhcxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMTl1cThnZG1reHFmcmdodGVrNDl3YThrMmY4aGhtM3hlNnY5dnh4EippbmoxdzlydjV1MzU1a2UwN2NqZjR3ZzB3YTJjdmF0bWR5Y2RoNm53ZzMaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvYWF2ZRILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajE5dXE4Z2Rta3hxZnJnaHRlazQ5d2E4azJmOGhobTN4ZTZ2OXZ4eBIqaW5qMXc5cnY1dTM1NWtlMDdjamY0d2cwd2EyY3ZhdG1keWNkaDZud2czGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2NydhILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajE5dXE4Z2Rta3hxZnJnaHRlazQ5d2E4azJmOGhobTN4ZTZ2OXZ4eBIqaW5qMXc5cnY1dTM1NWtlMDdjamY0d2cwd2EyY3ZhdG1keWNkaDZud2czGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2N2eBILMTAwMDAwMDAwMDAKwQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSoAEKKmluajE5dXE4Z2Rta3hxZnJnaHRlazQ5d2E4azJmOGhobTN4ZTZ2OXZ4eBIqaW5qMXc5cnY1dTM1NWtlMDdjamY0d2cwd2EyY3ZhdG1keWNkaDZud2czGkYKN2ZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3NoaWISCzEwMDAwMDAwMDAwGJ3+wwcSggEKYApUCi0vaW5qZWN0aXZlLmNyeXB0by52MWJldGExLmV0aHNlY3AyNTZrMS5QdWJLZXkSIwohA9YRhWDK9v8bR+HRAI7OzzTaeuCFfDffiIO9zTWhbk4cEgQKAggBGMmeARIeChcKA2luahIQMTYwMDAwMDAwMDAwMDAwMBCAqMMBGkBAcshkCtJATtQYYHVorDRUSOGQ7gR1bLp17ZXO5S5aTmB+pRc+/uz8cY3zfP28wpZE4BFa40sSn+vsN7YDc0Ne",
            "CvMLCpUBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnUKKmluajFocXJzbWZsdjc2dDB3MGZxcm16d3p4dHhxdWUzNG12MzRtc3h2bRIqaW5qMXVsMjM1c2ZwZm55bWNnOGdodXQ5OHV3c251NjlsbnpuYTN6ZGpkGhsKA2luahIUMTAwMDAwMDAwMDAwMDAwMDAwMDAKuQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSmAEKKmluajFocXJzbWZsdjc2dDB3MGZxcm16d3p4dHhxdWUzNG12MzRtc3h2bRIqaW5qMXVsMjM1c2ZwZm55bWNnOGdodXQ5OHV3c251NjlsbnpuYTN6ZGpkGj4KL3BlZ2d5MHg4N2FCM0I0Qzg2NjFlMDdENjM3MjM2MTIxMUI5NmVkNERjMzZCMUI1EgsxMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMWhxcnNtZmx2NzZ0MHcwZnFybXp3enh0eHF1ZTM0bXYzNG1zeHZtEippbmoxdWwyMzVzZnBmbnltY2c4Z2h1dDk4dXdzbnU2OWxuem5hM3pkamQaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvdXNkYxILMTAwMDAwMDAwMDAKxQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSpAEKKmluajFocXJzbWZsdjc2dDB3MGZxcm16d3p4dHhxdWUzNG12MzRtc3h2bRIqaW5qMXVsMjM1c2ZwZm55bWNnOGdodXQ5OHV3c251NjlsbnpuYTN6ZGpkGkoKL3BlZ2d5MHg0NEMyMWFmQWFGMjBjMjcwRUJiRjU5MTRDZmMzYjUwMjIxNzNGRUI3EhcxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMWhxcnNtZmx2NzZ0MHcwZnFybXp3enh0eHF1ZTM0bXYzNG1zeHZtEippbmoxdWwyMzVzZnBmbnltY2c4Z2h1dDk4dXdzbnU2OWxuem5hM3pkamQaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvYWF2ZRILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFocXJzbWZsdjc2dDB3MGZxcm16d3p4dHhxdWUzNG12MzRtc3h2bRIqaW5qMXVsMjM1c2ZwZm55bWNnOGdodXQ5OHV3c251NjlsbnpuYTN6ZGpkGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2NydhILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFocXJzbWZsdjc2dDB3MGZxcm16d3p4dHhxdWUzNG12MzRtc3h2bRIqaW5qMXVsMjM1c2ZwZm55bWNnOGdodXQ5OHV3c251NjlsbnpuYTN6ZGpkGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2N2eBILMTAwMDAwMDAwMDAKwQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSoAEKKmluajFocXJzbWZsdjc2dDB3MGZxcm16d3p4dHhxdWUzNG12MzRtc3h2bRIqaW5qMXVsMjM1c2ZwZm55bWNnOGdodXQ5OHV3c251NjlsbnpuYTN6ZGpkGkYKN2ZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3NoaWISCzEwMDAwMDAwMDAwGJ3+wwcSggEKYApUCi0vaW5qZWN0aXZlLmNyeXB0by52MWJldGExLmV0aHNlY3AyNTZrMS5QdWJLZXkSIwohAimG00m9nDJwqtOiErp8o619mH/3VcEADzWzSqGpnGdIEgQKAggBGLuRARIeChcKA2luahIQMTYwMDAwMDAwMDAwMDAwMBCAqMMBGkCnWeua6pt6p7Te8JuofcIaJWaZEhgiOuFqskm9sjQ9yi5qJkOEQXCmCRFCS5uYBpk0/1tuwYXJwtro9GdxHJMI",
            "CvMLCpUBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnUKKmluajFnMG04cTNrZHczMzNzeHEyOXc3bmMzNm1mZmN2aDgwZ3ZjZDM5ZBIqaW5qMW45d2ZoN2E2Y2cydWdneWdhZDlhZGxqODNhNHl3ZHp1dmhybXB2GhsKA2luahIUMTAwMDAwMDAwMDAwMDAwMDAwMDAKuQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSmAEKKmluajFnMG04cTNrZHczMzNzeHEyOXc3bmMzNm1mZmN2aDgwZ3ZjZDM5ZBIqaW5qMW45d2ZoN2E2Y2cydWdneWdhZDlhZGxqODNhNHl3ZHp1dmhybXB2Gj4KL3BlZ2d5MHg4N2FCM0I0Qzg2NjFlMDdENjM3MjM2MTIxMUI5NmVkNERjMzZCMUI1EgsxMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMWcwbThxM2tkdzMzM3N4cTI5dzduYzM2bWZmY3ZoODBndmNkMzlkEippbmoxbjl3Zmg3YTZjZzJ1Z2d5Z2FkOWFkbGo4M2E0eXdkenV2aHJtcHYaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvdXNkYxILMTAwMDAwMDAwMDAKxQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSpAEKKmluajFnMG04cTNrZHczMzNzeHEyOXc3bmMzNm1mZmN2aDgwZ3ZjZDM5ZBIqaW5qMW45d2ZoN2E2Y2cydWdneWdhZDlhZGxqODNhNHl3ZHp1dmhybXB2GkoKL3BlZ2d5MHg0NEMyMWFmQWFGMjBjMjcwRUJiRjU5MTRDZmMzYjUwMjIxNzNGRUI3EhcxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMWcwbThxM2tkdzMzM3N4cTI5dzduYzM2bWZmY3ZoODBndmNkMzlkEippbmoxbjl3Zmg3YTZjZzJ1Z2d5Z2FkOWFkbGo4M2E0eXdkenV2aHJtcHYaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvYWF2ZRILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFnMG04cTNrZHczMzNzeHEyOXc3bmMzNm1mZmN2aDgwZ3ZjZDM5ZBIqaW5qMW45d2ZoN2E2Y2cydWdneWdhZDlhZGxqODNhNHl3ZHp1dmhybXB2GkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2NydhILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFnMG04cTNrZHczMzNzeHEyOXc3bmMzNm1mZmN2aDgwZ3ZjZDM5ZBIqaW5qMW45d2ZoN2E2Y2cydWdneWdhZDlhZGxqODNhNHl3ZHp1dmhybXB2GkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2N2eBILMTAwMDAwMDAwMDAKwQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSoAEKKmluajFnMG04cTNrZHczMzNzeHEyOXc3bmMzNm1mZmN2aDgwZ3ZjZDM5ZBIqaW5qMW45d2ZoN2E2Y2cydWdneWdhZDlhZGxqODNhNHl3ZHp1dmhybXB2GkYKN2ZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3NoaWISCzEwMDAwMDAwMDAwGJ3+wwcSggEKYApUCi0vaW5qZWN0aXZlLmNyeXB0by52MWJldGExLmV0aHNlY3AyNTZrMS5QdWJLZXkSIwohAhKZIyozzEpDEuAl3ypUW3R3JoD7AtBIAujqq4wwPfVdEgQKAggBGOufARIeChcKA2luahIQMTYwMDAwMDAwMDAwMDAwMBCAqMMBGkDMNT7feu38IDUKGBHpWaoydtomgYQZjGPXjj7pb8fEj0MshAm2XfDad53SLdLeKmsXMjQ5cXyYyH15EwUxDYSU",
            "CvMLCpUBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnUKKmluajFueHpoZTk0Z3NjOWpzeXVjM3dxa3Vuanl2czhwNGVtZTBndTRrZRIqaW5qMWxxa2dyZGxoeXFreTN3ZzZybW54ZGo1a3d0ZXI3NGUydWowbWZmGhsKA2luahIUMTAwMDAwMDAwMDAwMDAwMDAwMDAKuQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSmAEKKmluajFueHpoZTk0Z3NjOWpzeXVjM3dxa3Vuanl2czhwNGVtZTBndTRrZRIqaW5qMWxxa2dyZGxoeXFreTN3ZzZybW54ZGo1a3d0ZXI3NGUydWowbWZmGj4KL3BlZ2d5MHg4N2FCM0I0Qzg2NjFlMDdENjM3MjM2MTIxMUI5NmVkNERjMzZCMUI1EgsxMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMW54emhlOTRnc2M5anN5dWMzd3FrdW5qeXZzOHA0ZW1lMGd1NGtlEippbmoxbHFrZ3JkbGh5cWt5M3dnNnJtbnhkajVrd3Rlcjc0ZTJ1ajBtZmYaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvdXNkYxILMTAwMDAwMDAwMDAKxQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSpAEKKmluajFueHpoZTk0Z3NjOWpzeXVjM3dxa3Vuanl2czhwNGVtZTBndTRrZRIqaW5qMWxxa2dyZGxoeXFreTN3ZzZybW54ZGo1a3d0ZXI3NGUydWowbWZmGkoKL3BlZ2d5MHg0NEMyMWFmQWFGMjBjMjcwRUJiRjU5MTRDZmMzYjUwMjIxNzNGRUI3EhcxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMW54emhlOTRnc2M5anN5dWMzd3FrdW5qeXZzOHA0ZW1lMGd1NGtlEippbmoxbHFrZ3JkbGh5cWt5M3dnNnJtbnhkajVrd3Rlcjc0ZTJ1ajBtZmYaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvYWF2ZRILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFueHpoZTk0Z3NjOWpzeXVjM3dxa3Vuanl2czhwNGVtZTBndTRrZRIqaW5qMWxxa2dyZGxoeXFreTN3ZzZybW54ZGo1a3d0ZXI3NGUydWowbWZmGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2NydhILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFueHpoZTk0Z3NjOWpzeXVjM3dxa3Vuanl2czhwNGVtZTBndTRrZRIqaW5qMWxxa2dyZGxoeXFreTN3ZzZybW54ZGo1a3d0ZXI3NGUydWowbWZmGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2N2eBILMTAwMDAwMDAwMDAKwQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSoAEKKmluajFueHpoZTk0Z3NjOWpzeXVjM3dxa3Vuanl2czhwNGVtZTBndTRrZRIqaW5qMWxxa2dyZGxoeXFreTN3ZzZybW54ZGo1a3d0ZXI3NGUydWowbWZmGkYKN2ZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3NoaWISCzEwMDAwMDAwMDAwGJ3+wwcSggEKYApUCi0vaW5qZWN0aXZlLmNyeXB0by52MWJldGExLmV0aHNlY3AyNTZrMS5QdWJLZXkSIwohAxg89Ih7H74zbkYrMXXb55tjKWTQJQ3D2Sk00p5Y0/ZEEgQKAggBGIqVARIeChcKA2luahIQMTYwMDAwMDAwMDAwMDAwMBCAqMMBGkCo/7pJIihg01V2zd+y3WH++KyVIB4m7WC9DAHPRzJIAghGLVJkAJjzGWTHrIGlh7CIira+E0UeSdy1Ag4GMBfS",
            "CvMLCpUBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnUKKmluajE5Y2hlY3h3enVmZjA5Zm02NmM1MDN4MnJtZmowa3l6emZoM2Z0ZhIqaW5qMWt0djIyYXp2dDVoOG5xejQ4d25ocXNqOTZ1bGU0eHgwZGF3N2pqGhsKA2luahIUMTAwMDAwMDAwMDAwMDAwMDAwMDAKuQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSmAEKKmluajE5Y2hlY3h3enVmZjA5Zm02NmM1MDN4MnJtZmowa3l6emZoM2Z0ZhIqaW5qMWt0djIyYXp2dDVoOG5xejQ4d25ocXNqOTZ1bGU0eHgwZGF3N2pqGj4KL3BlZ2d5MHg4N2FCM0I0Qzg2NjFlMDdENjM3MjM2MTIxMUI5NmVkNERjMzZCMUI1EgsxMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMTljaGVjeHd6dWZmMDlmbTY2YzUwM3gycm1majBreXp6ZmgzZnRmEippbmoxa3R2MjJhenZ0NWg4bnF6NDh3bmhxc2o5NnVsZTR4eDBkYXc3amoaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvdXNkYxILMTAwMDAwMDAwMDAKxQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSpAEKKmluajE5Y2hlY3h3enVmZjA5Zm02NmM1MDN4MnJtZmowa3l6emZoM2Z0ZhIqaW5qMWt0djIyYXp2dDVoOG5xejQ4d25ocXNqOTZ1bGU0eHgwZGF3N2pqGkoKL3BlZ2d5MHg0NEMyMWFmQWFGMjBjMjcwRUJiRjU5MTRDZmMzYjUwMjIxNzNGRUI3EhcxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMTljaGVjeHd6dWZmMDlmbTY2YzUwM3gycm1majBreXp6ZmgzZnRmEippbmoxa3R2MjJhenZ0NWg4bnF6NDh3bmhxc2o5NnVsZTR4eDBkYXc3amoaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvYWF2ZRILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajE5Y2hlY3h3enVmZjA5Zm02NmM1MDN4MnJtZmowa3l6emZoM2Z0ZhIqaW5qMWt0djIyYXp2dDVoOG5xejQ4d25ocXNqOTZ1bGU0eHgwZGF3N2pqGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2NydhILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajE5Y2hlY3h3enVmZjA5Zm02NmM1MDN4MnJtZmowa3l6emZoM2Z0ZhIqaW5qMWt0djIyYXp2dDVoOG5xejQ4d25ocXNqOTZ1bGU0eHgwZGF3N2pqGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2N2eBILMTAwMDAwMDAwMDAKwQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSoAEKKmluajE5Y2hlY3h3enVmZjA5Zm02NmM1MDN4MnJtZmowa3l6emZoM2Z0ZhIqaW5qMWt0djIyYXp2dDVoOG5xejQ4d25ocXNqOTZ1bGU0eHgwZGF3N2pqGkYKN2ZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3NoaWISCzEwMDAwMDAwMDAwGJ3+wwcSggEKYApUCi0vaW5qZWN0aXZlLmNyeXB0by52MWJldGExLmV0aHNlY3AyNTZrMS5QdWJLZXkSIwohAgVaAkMOV5+9OJP2xYw3tKy3aU3SiAIummY3gRAIGDj/EgQKAggBGOihARIeChcKA2luahIQMTYwMDAwMDAwMDAwMDAwMBCAqMMBGkBSSP+Fx12//aSYEjjLjr5gl5X4jOUktkOREMTfArsWVxl4Xl7cyV3f7kYAF7kBbQQqrgMerHsc9KePhRVoXB0k",
            "CvMLCpUBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnUKKmluajFwMzBra2w2dXh5YWhtOGhmMGVkOGY0MDJmNjdhMmo5eHJjNDJ5ZhIqaW5qMXo1ZzRwYXA3YThoaHhhYXkycG5md2czYXduNWRxcDVyNHN2OGthGhsKA2luahIUMTAwMDAwMDAwMDAwMDAwMDAwMDAKuQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSmAEKKmluajFwMzBra2w2dXh5YWhtOGhmMGVkOGY0MDJmNjdhMmo5eHJjNDJ5ZhIqaW5qMXo1ZzRwYXA3YThoaHhhYXkycG5md2czYXduNWRxcDVyNHN2OGthGj4KL3BlZ2d5MHg4N2FCM0I0Qzg2NjFlMDdENjM3MjM2MTIxMUI5NmVkNERjMzZCMUI1EgsxMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMXAzMGtrbDZ1eHlhaG04aGYwZWQ4ZjQwMmY2N2Eyajl4cmM0MnlmEippbmoxejVnNHBhcDdhOGhoeGFheTJwbmZ3ZzNhd241ZHFwNXI0c3Y4a2EaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvdXNkYxILMTAwMDAwMDAwMDAKxQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSpAEKKmluajFwMzBra2w2dXh5YWhtOGhmMGVkOGY0MDJmNjdhMmo5eHJjNDJ5ZhIqaW5qMXo1ZzRwYXA3YThoaHhhYXkycG5md2czYXduNWRxcDVyNHN2OGthGkoKL3BlZ2d5MHg0NEMyMWFmQWFGMjBjMjcwRUJiRjU5MTRDZmMzYjUwMjIxNzNGRUI3EhcxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMXAzMGtrbDZ1eHlhaG04aGYwZWQ4ZjQwMmY2N2Eyajl4cmM0MnlmEippbmoxejVnNHBhcDdhOGhoeGFheTJwbmZ3ZzNhd241ZHFwNXI0c3Y4a2EaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvYWF2ZRILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFwMzBra2w2dXh5YWhtOGhmMGVkOGY0MDJmNjdhMmo5eHJjNDJ5ZhIqaW5qMXo1ZzRwYXA3YThoaHhhYXkycG5md2czYXduNWRxcDVyNHN2OGthGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2NydhILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFwMzBra2w2dXh5YWhtOGhmMGVkOGY0MDJmNjdhMmo5eHJjNDJ5ZhIqaW5qMXo1ZzRwYXA3YThoaHhhYXkycG5md2czYXduNWRxcDVyNHN2OGthGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2N2eBILMTAwMDAwMDAwMDAKwQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSoAEKKmluajFwMzBra2w2dXh5YWhtOGhmMGVkOGY0MDJmNjdhMmo5eHJjNDJ5ZhIqaW5qMXo1ZzRwYXA3YThoaHhhYXkycG5md2czYXduNWRxcDVyNHN2OGthGkYKN2ZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3NoaWISCzEwMDAwMDAwMDAwGJ3+wwcSggEKYApUCi0vaW5qZWN0aXZlLmNyeXB0by52MWJldGExLmV0aHNlY3AyNTZrMS5QdWJLZXkSIwohAl0obf7huaZwDxwoKhqdWfwakrBU8rFlrc/Ihiquc4P5EgQKAggBGIOAARIeChcKA2luahIQMTYwMDAwMDAwMDAwMDAwMBCAqMMBGkCGyhKBN8mu+4qID3ZzBPskvusEorT6TXytayPg3k6UpGMaLx38dXS9wmX2yrLrn4G67rihS/fKVCG2yMhdwk4y",
            "CvMLCpUBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnUKKmluajE0dDVmOTRtNWZnNHY2ZHJzNHFxa2QzZDczM3k2c3MwbGp5eXFsbRIqaW5qMWhtOXVobWhrZHRyeXd6MG1xazh2YTQwMmUzdWQweXBqbHFmcjNqGhsKA2luahIUMTAwMDAwMDAwMDAwMDAwMDAwMDAKuQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSmAEKKmluajE0dDVmOTRtNWZnNHY2ZHJzNHFxa2QzZDczM3k2c3MwbGp5eXFsbRIqaW5qMWhtOXVobWhrZHRyeXd6MG1xazh2YTQwMmUzdWQweXBqbHFmcjNqGj4KL3BlZ2d5MHg4N2FCM0I0Qzg2NjFlMDdENjM3MjM2MTIxMUI5NmVkNERjMzZCMUI1EgsxMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMTR0NWY5NG01Zmc0djZkcnM0cXFrZDNkNzMzeTZzczBsanl5cWxtEippbmoxaG05dWhtaGtkdHJ5d3owbXFrOHZhNDAyZTN1ZDB5cGpscWZyM2oaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvdXNkYxILMTAwMDAwMDAwMDAKxQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSpAEKKmluajE0dDVmOTRtNWZnNHY2ZHJzNHFxa2QzZDczM3k2c3MwbGp5eXFsbRIqaW5qMWhtOXVobWhrZHRyeXd6MG1xazh2YTQwMmUzdWQweXBqbHFmcjNqGkoKL3BlZ2d5MHg0NEMyMWFmQWFGMjBjMjcwRUJiRjU5MTRDZmMzYjUwMjIxNzNGRUI3EhcxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMTR0NWY5NG01Zmc0djZkcnM0cXFrZDNkNzMzeTZzczBsanl5cWxtEippbmoxaG05dWhtaGtkdHJ5d3owbXFrOHZhNDAyZTN1ZDB5cGpscWZyM2oaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvYWF2ZRILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajE0dDVmOTRtNWZnNHY2ZHJzNHFxa2QzZDczM3k2c3MwbGp5eXFsbRIqaW5qMWhtOXVobWhrZHRyeXd6MG1xazh2YTQwMmUzdWQweXBqbHFmcjNqGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2NydhILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajE0dDVmOTRtNWZnNHY2ZHJzNHFxa2QzZDczM3k2c3MwbGp5eXFsbRIqaW5qMWhtOXVobWhrZHRyeXd6MG1xazh2YTQwMmUzdWQweXBqbHFmcjNqGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2N2eBILMTAwMDAwMDAwMDAKwQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSoAEKKmluajE0dDVmOTRtNWZnNHY2ZHJzNHFxa2QzZDczM3k2c3MwbGp5eXFsbRIqaW5qMWhtOXVobWhrZHRyeXd6MG1xazh2YTQwMmUzdWQweXBqbHFmcjNqGkYKN2ZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3NoaWISCzEwMDAwMDAwMDAwGJ3+wwcSggEKYApUCi0vaW5qZWN0aXZlLmNyeXB0by52MWJldGExLmV0aHNlY3AyNTZrMS5QdWJLZXkSIwohA4fTy5A+DmuZfsXgjM48ntVqTXlOBW287TjXr91D0VGREgQKAggBGLuVARIeChcKA2luahIQMTYwMDAwMDAwMDAwMDAwMBCAqMMBGkBdYIUr7S8ky4p9g+WWi2Ef8Cnq9W5eRsQ6Q6YNcnr0rhzy6lgo31o9tJg6XB0ZHtaJb00qBdU8/igNmfhEZXqk",
            "CvMLCpUBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnUKKmluajFhNHc5OXo0cWdxY2Q2bDZ1NGRqZnlsY3VjdDUzZHVxa3VxbnI1ZBIqaW5qMTUyNmszNmNrM2xodm1yZzhzeXlhODd0eTY5dXBsOHl6enJrNWZxGhsKA2luahIUMTAwMDAwMDAwMDAwMDAwMDAwMDAKuQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSmAEKKmluajFhNHc5OXo0cWdxY2Q2bDZ1NGRqZnlsY3VjdDUzZHVxa3VxbnI1ZBIqaW5qMTUyNmszNmNrM2xodm1yZzhzeXlhODd0eTY5dXBsOHl6enJrNWZxGj4KL3BlZ2d5MHg4N2FCM0I0Qzg2NjFlMDdENjM3MjM2MTIxMUI5NmVkNERjMzZCMUI1EgsxMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMWE0dzk5ejRxZ3FjZDZsNnU0ZGpmeWxjdWN0NTNkdXFrdXFucjVkEippbmoxNTI2azM2Y2szbGh2bXJnOHN5eWE4N3R5Njl1cGw4eXp6cms1ZnEaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvdXNkYxILMTAwMDAwMDAwMDAKxQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSpAEKKmluajFhNHc5OXo0cWdxY2Q2bDZ1NGRqZnlsY3VjdDUzZHVxa3VxbnI1ZBIqaW5qMTUyNmszNmNrM2xodm1yZzhzeXlhODd0eTY5dXBsOHl6enJrNWZxGkoKL3BlZ2d5MHg0NEMyMWFmQWFGMjBjMjcwRUJiRjU5MTRDZmMzYjUwMjIxNzNGRUI3EhcxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMWE0dzk5ejRxZ3FjZDZsNnU0ZGpmeWxjdWN0NTNkdXFrdXFucjVkEippbmoxNTI2azM2Y2szbGh2bXJnOHN5eWE4N3R5Njl1cGw4eXp6cms1ZnEaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvYWF2ZRILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFhNHc5OXo0cWdxY2Q2bDZ1NGRqZnlsY3VjdDUzZHVxa3VxbnI1ZBIqaW5qMTUyNmszNmNrM2xodm1yZzhzeXlhODd0eTY5dXBsOHl6enJrNWZxGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2NydhILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFhNHc5OXo0cWdxY2Q2bDZ1NGRqZnlsY3VjdDUzZHVxa3VxbnI1ZBIqaW5qMTUyNmszNmNrM2xodm1yZzhzeXlhODd0eTY5dXBsOHl6enJrNWZxGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2N2eBILMTAwMDAwMDAwMDAKwQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSoAEKKmluajFhNHc5OXo0cWdxY2Q2bDZ1NGRqZnlsY3VjdDUzZHVxa3VxbnI1ZBIqaW5qMTUyNmszNmNrM2xodm1yZzhzeXlhODd0eTY5dXBsOHl6enJrNWZxGkYKN2ZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3NoaWISCzEwMDAwMDAwMDAwGJ3+wwcSggEKYApUCi0vaW5qZWN0aXZlLmNyeXB0by52MWJldGExLmV0aHNlY3AyNTZrMS5QdWJLZXkSIwohArGVpE2Qtw7Pq625UTe8FZfqFAGc7IaBTZYPusGkLfnlEgQKAggBGMmAARIeChcKA2luahIQMTYwMDAwMDAwMDAwMDAwMBCAqMMBGkDk8e2Du8ReB4Jz73ZkpdaWHIBSo5x0XtILIMecnJzbQ3TykogSC6OQ+tWOCFQp9mUhff++iCbVpFwAx08k+zYS",
            "CvMLCpUBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnUKKmluajFnZHZ0ZGtsdjNxZzQzM3Z1bjlqYXBhZGFucjk2MHgwdTI0cWtxbBIqaW5qMWFlYTRtOGZhcnc5ZHI5Y204N2FnN2QwejZtY2ZwMm54bnYyOGE3GhsKA2luahIUMTAwMDAwMDAwMDAwMDAwMDAwMDAKuQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSmAEKKmluajFnZHZ0ZGtsdjNxZzQzM3Z1bjlqYXBhZGFucjk2MHgwdTI0cWtxbBIqaW5qMWFlYTRtOGZhcnc5ZHI5Y204N2FnN2QwejZtY2ZwMm54bnYyOGE3Gj4KL3BlZ2d5MHg4N2FCM0I0Qzg2NjFlMDdENjM3MjM2MTIxMUI5NmVkNERjMzZCMUI1EgsxMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMWdkdnRka2x2M3FnNDMzdnVuOWphcGFkYW5yOTYweDB1MjRxa3FsEippbmoxYWVhNG04ZmFydzlkcjljbTg3YWc3ZDB6Nm1jZnAybnhudjI4YTcaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvdXNkYxILMTAwMDAwMDAwMDAKxQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSpAEKKmluajFnZHZ0ZGtsdjNxZzQzM3Z1bjlqYXBhZGFucjk2MHgwdTI0cWtxbBIqaW5qMWFlYTRtOGZhcnc5ZHI5Y204N2FnN2QwejZtY2ZwMm54bnYyOGE3GkoKL3BlZ2d5MHg0NEMyMWFmQWFGMjBjMjcwRUJiRjU5MTRDZmMzYjUwMjIxNzNGRUI3EhcxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMWdkdnRka2x2M3FnNDMzdnVuOWphcGFkYW5yOTYweDB1MjRxa3FsEippbmoxYWVhNG04ZmFydzlkcjljbTg3YWc3ZDB6Nm1jZnAybnhudjI4YTcaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvYWF2ZRILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFnZHZ0ZGtsdjNxZzQzM3Z1bjlqYXBhZGFucjk2MHgwdTI0cWtxbBIqaW5qMWFlYTRtOGZhcnc5ZHI5Y204N2FnN2QwejZtY2ZwMm54bnYyOGE3GkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2NydhILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFnZHZ0ZGtsdjNxZzQzM3Z1bjlqYXBhZGFucjk2MHgwdTI0cWtxbBIqaW5qMWFlYTRtOGZhcnc5ZHI5Y204N2FnN2QwejZtY2ZwMm54bnYyOGE3GkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2N2eBILMTAwMDAwMDAwMDAKwQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSoAEKKmluajFnZHZ0ZGtsdjNxZzQzM3Z1bjlqYXBhZGFucjk2MHgwdTI0cWtxbBIqaW5qMWFlYTRtOGZhcnc5ZHI5Y204N2FnN2QwejZtY2ZwMm54bnYyOGE3GkYKN2ZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3NoaWISCzEwMDAwMDAwMDAwGJ3+wwcSggEKYApUCi0vaW5qZWN0aXZlLmNyeXB0by52MWJldGExLmV0aHNlY3AyNTZrMS5QdWJLZXkSIwohAz+Zjrtxo20HOm1w4l5I57H9MAmt+87msPR5/1R/D1McEgQKAggBGMSqARIeChcKA2luahIQMTYwMDAwMDAwMDAwMDAwMBCAqMMBGkDhGCp0+Crr0dfoCZrTb5otuTMtIxxTj9tWfxrfN7cnBTEgKFXVDlsXbay4Wlxz4QBVX4Fb6gtUgQbtDrazOEj9",
            "CvMLCpUBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnUKKmluajFobm1kbGVhdHR1N3RldHU2ZWt3dzlybTBjbTAzZXpnNWpsdHJxehIqaW5qMW02M3U1eWtzYWdzc2o3d2N4Zmw1czd0NHU4N2s3MGpmeW5uazJqGhsKA2luahIUMTAwMDAwMDAwMDAwMDAwMDAwMDAKuQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSmAEKKmluajFobm1kbGVhdHR1N3RldHU2ZWt3dzlybTBjbTAzZXpnNWpsdHJxehIqaW5qMW02M3U1eWtzYWdzc2o3d2N4Zmw1czd0NHU4N2s3MGpmeW5uazJqGj4KL3BlZ2d5MHg4N2FCM0I0Qzg2NjFlMDdENjM3MjM2MTIxMUI5NmVkNERjMzZCMUI1EgsxMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMWhubWRsZWF0dHU3dGV0dTZla3d3OXJtMGNtMDNlemc1amx0cnF6EippbmoxbTYzdTV5a3NhZ3Nzajd3Y3hmbDVzN3Q0dTg3azcwamZ5bm5rMmoaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvdXNkYxILMTAwMDAwMDAwMDAKxQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSpAEKKmluajFobm1kbGVhdHR1N3RldHU2ZWt3dzlybTBjbTAzZXpnNWpsdHJxehIqaW5qMW02M3U1eWtzYWdzc2o3d2N4Zmw1czd0NHU4N2s3MGpmeW5uazJqGkoKL3BlZ2d5MHg0NEMyMWFmQWFGMjBjMjcwRUJiRjU5MTRDZmMzYjUwMjIxNzNGRUI3EhcxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMArBAQocL2Nvc21vcy5iYW5rLnYxYmV0YTEuTXNnU2VuZBKgAQoqaW5qMWhubWRsZWF0dHU3dGV0dTZla3d3OXJtMGNtMDNlemc1amx0cnF6EippbmoxbTYzdTV5a3NhZ3Nzajd3Y3hmbDVzN3Q0dTg3azcwamZ5bm5rMmoaRgo3ZmFjdG9yeS9pbmoxN3Z5dGR3cWN6cXo3Mmo2NXNhdWtwbHJrdGQ0Z3lmbWU1YWdmNmMvYWF2ZRILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFobm1kbGVhdHR1N3RldHU2ZWt3dzlybTBjbTAzZXpnNWpsdHJxehIqaW5qMW02M3U1eWtzYWdzc2o3d2N4Zmw1czd0NHU4N2s3MGpmeW5uazJqGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2NydhILMTAwMDAwMDAwMDAKwAEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSnwEKKmluajFobm1kbGVhdHR1N3RldHU2ZWt3dzlybTBjbTAzZXpnNWpsdHJxehIqaW5qMW02M3U1eWtzYWdzc2o3d2N4Zmw1czd0NHU4N2s3MGpmeW5uazJqGkUKNmZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL2N2eBILMTAwMDAwMDAwMDAKwQEKHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQSoAEKKmluajFobm1kbGVhdHR1N3RldHU2ZWt3dzlybTBjbTAzZXpnNWpsdHJxehIqaW5qMW02M3U1eWtzYWdzc2o3d2N4Zmw1czd0NHU4N2s3MGpmeW5uazJqGkYKN2ZhY3RvcnkvaW5qMTd2eXRkd3FjenF6NzJqNjVzYXVrcGxya3RkNGd5Zm1lNWFnZjZjL3NoaWISCzEwMDAwMDAwMDAwGJ3+wwcSggEKYApUCi0vaW5qZWN0aXZlLmNyeXB0by52MWJldGExLmV0aHNlY3AyNTZrMS5QdWJLZXkSIwohA+OlGuxc2hUmrU+iVLb2MDnHy6W4exQyJrbMie9/Sv27EgQKAggBGJqQARIeChcKA2luahIQMTYwMDAwMDAwMDAwMDAwMBCAqMMBGkBTfe9A/RDSoHQCDunT60QgdtBrz3eIGvIgLEISRMAh/2w3+A9UB5SoDNGZNUfpNsxZyyq2Emi6pXuVpFzUCjI5"
         ]
      },
      "evidence":{
         "evidence":[

         ]
      },
      "lastCommit":{
         "height":"15793859",
         "blockId":{
            "hash":"RRhRSiIf1E08mJAtACM4J1RFSVJ96eR0PBVuoD7rb2c=",
            "partSetHeader":{
               "total":1,
               "hash":"SeO5JkVtLUrhegd0rwDatDbvS5PQf/0Yvn+BmL1MOko="
            }
         },
         "signatures":[
            {
               "blockIdFlag":"BLOCK_ID_FLAG_COMMIT",
               "validatorAddress":"y8ctJ4QpJ0S7ZTVY7RTE4z1hS2c=",
               "timestamp":"2023-09-07T03:59:36.496584825Z",
               "signature":"AxnPc5AEa6jizZuKhXUAkNi4vic6miF9emyAx+uSMco7oKVwoXGDJ6L0wneNGYOqpKkMVMQm4hcnWgDBjiBLAA=="
            },
            {
               "blockIdFlag":"BLOCK_ID_FLAG_COMMIT",
               "validatorAddress":"M5HjW2EATgO+uI+h2rRES5E7174=",
               "timestamp":"2023-09-07T03:59:36.293269404Z",
               "signature":"mjODCd7P7xHo6Gn+6Qi6/u+FI72noRs9/vcbvpiqz7Hr5hRNhk2a2Jj2tw59GC6cURd2Q6c/CdZhXHgVqzMdAg=="
            },
            {
               "blockIdFlag":"BLOCK_ID_FLAG_COMMIT",
               "validatorAddress":"Nv8cuLE25L4mgnBx8shCmG68xfc=",
               "timestamp":"2023-09-07T03:59:36.393462082Z",
               "signature":"NyTk5W6WLxEbouVJ7LxSwV88FnH/CtmXkr6JczPqEehdrymqrGqT02OJLutGVsBmrPEkMhwa2BegkqvmPLJrBQ=="
            },
            {
               "blockIdFlag":"BLOCK_ID_FLAG_COMMIT",
               "validatorAddress":"ObUXYdS8jfTSNPonUBFPJkft7eA=",
               "timestamp":"2023-09-07T03:59:36.296674286Z",
               "signature":"OAwmf7pEjsXbwIWMD5HbzWiae6OAn0ME49FbXaRLvKIYKWSDKv9f0gprsgRJznOdj60SontlntwmvV+23MV6DQ=="
            }
         ],
         "round":0
      }
   }
}
ParameterTypeDescription
block_idBlockIDBlock identifier
sdk_blockBlockBlock details


BlockID

ParameterTypeDescription
hashBytesBlock hash
part_set_headerPartSetHeader


PartSetHeader

ParameterTypeDescription
totalInteger
hashBytes


Block

ParameterTypeDescription
headerHeaderHeader information
dataDataBlock data
evidenceEvidenceList
last_commitCommit


Header

ParameterTypeDescription
versionConsensus
chain_idStringChain identifier
heightIntegerBlock height
timeTimeBlock time
last_block_idBlockIDPrevious block identifier
last_commit_hashBytesLast commit hash
data_hashBytesBlock data hash
validators_hashBytesValidators information hash
next_validators_hashBytesValidators information hash
consensus_hashBytesConsensus information hash
app_hashBytesApplication hash
last_result_hashBytesLast result hash
evidence_hashBytesEvidence data hash
proposer_addressStringBlock proposer's address


Consensus

ParameterTypeDescription
versionConsensus
chain_idStringChain identifier
heightIntegerBlock height
timeTimeBlock time
last_block_idBlockIDPrevious block identifier
last_commit_hashBytesLast commit hash
data_hashBytesBlock data hash
validators_hashBytesValidators information hash
next_validators_hashBytesValidators information hash
consensus_hashBytesConsensus information hash
app_hashBytesApplication hash
last_result_hashBytesLast result hash
evidence_hashBytesEvidence data hash
proposer_addressStringBlock proposer's address


Data

ParameterTypeDescription
txsByte ArrayTxs that will be applied by state @ block.Height+1. NOTE: not all txs here are valid. We're just agreeing on the order first. This means that block.AppHash does not include these txs.


EvidenceList

ParameterTypeDescription
evidenceEvidence ArrayBlock evidence


Evidence

ParameterTypeDescription
sumisEvidence_SumValid types for 'sum' are Evidence_DuplicateVoteEvidence and Evidence_LightClientAttackEvidence


Commit

ParameterTypeDescription
heightIntegerBlock height
roundIntegerConsensus round
block_idBlockIDBlock identifier
signaturesCommitSig ArraySigantures


CommitSig

ParameterTypeDescription
block_id_flagBlockIDFlagBlock height
validator_addressBytesValidator address
timestampTimeBlock time
signatureBytesBlock signature


BlockIDFlag

CodeName
0BLOCK_ID_FLAG_UNKNOWN
1BLOCK_ID_FLAG_ABSENT
2BLOCK_ID_FLAG_COMMIT
3BLOCK_ID_FLAG_NIL

GetLatestValidatorSet

Get the latest validator-set

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    validator_set = await client.fetch_latest_validator_set()
    print(validator_set)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    res, err := chainClient.FetchLatestValidatorSet(ctx)
    if err != nil {
        fmt.Println(err)
    }

    fmt.Print(res.String())

}

No parameters

Response Parameters

Response Example:

{
   "blockHeight":"23201498",
   "validators":[
      {
         "address":"injvalcons1xml3ew93xmjtuf5zwpcl9jzznphte30hvdre9a",
         "pubKey":{
            "@type":"/cosmos.crypto.ed25519.PubKey",
            "key":"Bi/7vbVB1uj/zz40/aozZOvVBFkV6hLqqxBIQr5kSc4="
         },
         "votingPower":"200001152291153",
         "proposerPriority":"234447499678197"
      },
      {
         "address":"injvalcons18x63wcw5hjxlf535lgn4qy20yer7mm0qedu0la",
         "pubKey":{
            "@type":"/cosmos.crypto.ed25519.PubKey",
            "key":"WlL4lTR+iTbd0rn3xP6oH0juOnGRZ+Hh73Oj6/Lt/Wg="
         },
         "votingPower":"200000153326260",
         "proposerPriority":"-270628320740096"
      },
      {
         "address":"injvalcons1xwg7xkmpqp8q804c37sa4dzyfwgnh4a74ll9pz",
         "pubKey":{
            "@type":"/cosmos.crypto.ed25519.PubKey",
            "key":"Puku/I45dAZ4wKeN+rbYKnmuUUA7Yh7/TrKX3ZoTmk4="
         },
         "votingPower":"199859452893177",
         "proposerPriority":"-192489141052575"
      },
      {
         "address":"injvalcons1e0rj6fuy9yn5fwm9x4vw69xyuv7kzjm8rvw5r3",
         "pubKey":{
            "@type":"/cosmos.crypto.ed25519.PubKey",
            "key":"1mF7OEpB9A60O0e+64pICbqS/nN8VnsVfoySMEW2w1Q="
         },
         "votingPower":"199826816954736",
         "proposerPriority":"228669962114476"
      }
   ],
   "pagination":{
      "total":"4",
      "nextKey":""
   }
}
ParameterTypeDescription
block_heightIntegerBlock height
validatorsValidator ArrayList of validators
paginationPageResponsePagination information in the response


Validator

ParameterTypeDescription
addressStringValidator's address
pub_keyAnyValidator's public key
voting_powerIntegerValidator's voting power
proposer_priorityInteger


PageResponse

ParameterTypeDescription
next_keyByte ArrayThe key to be passed to PageRequest.key to query the next page most efficiently. It will be empty if there are no more results.
totalIntegerTotal number of results available if PageRequest.count_total was set, its value is undefined otherwise

GetValidatorSetByHeight

Get the validator-set at a given height

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from google.protobuf import symbol_database

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)

    pagination = PaginationOption(skip=2, limit=4)

    validator_set = await client.fetch_validator_set_by_height(height=23040174, pagination=pagination)
    print(validator_set)


if __name__ == "__main__":
    symbol_db = symbol_database.Default()
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "fmt"

    "github.com/cosmos/cosmos-sdk/types/query"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    height := int64(23040174)
    pagination := query.PageRequest{Offset: 2, Limit: 10}
    res, err := chainClient.FetchValidatorSetByHeight(ctx, height, &pagination)
    if err != nil {
        fmt.Println(err)
    }

    fmt.Print(res.String())

}
ParameterTypeDescriptionRequired
heightIntegerBlock heightYes
paginationPageRequestThe optional pagination for the requestNo


PageRequest

ParameterTypeDescriptionRequired
keyByte ArrayKey is a value returned in PageResponse.next_key to begin querying the next page most efficiently. Only one of offset or key should be setNo
offsetIntegerNumeric offset that can be used when key is unavailable. It is less efficient than using key. Only one of offset or key should be setNo
limitIntegerTotal number of results to be returned in the result pageNo
count_totalBooleanSet to true to indicate that the result set should include a count of the total number of items available for pagination in UIs. It is only respected when offset is used. It is ignored when key is setNo
reverseBooleanReverse is set to true if results are to be returned in the descending orderNo

Response Parameters

Response Example:

{
   "blockHeight":"23040174",
   "validators":[
      {
         "address":"injvalcons1xml3ew93xmjtuf5zwpcl9jzznphte30hvdre9a",
         "pubKey":{
            "@type":"/cosmos.crypto.ed25519.PubKey",
            "key":"Bi/7vbVB1uj/zz40/aozZOvVBFkV6hLqqxBIQr5kSc4="
         },
         "votingPower":"200001152291142",
         "proposerPriority":"-117113073985972"
      },
      {
         "address":"injvalcons18x63wcw5hjxlf535lgn4qy20yer7mm0qedu0la",
         "pubKey":{
            "@type":"/cosmos.crypto.ed25519.PubKey",
            "key":"WlL4lTR+iTbd0rn3xP6oH0juOnGRZ+Hh73Oj6/Lt/Wg="
         },
         "votingPower":"200000153326249",
         "proposerPriority":"-30678774375098"
      },
      {
         "address":"injvalcons1xwg7xkmpqp8q804c37sa4dzyfwgnh4a74ll9pz",
         "pubKey":{
            "@type":"/cosmos.crypto.ed25519.PubKey",
            "key":"Puku/I45dAZ4wKeN+rbYKnmuUUA7Yh7/TrKX3ZoTmk4="
         },
         "votingPower":"199859452893172",
         "proposerPriority":"358858430481236"
      },
      {
         "address":"injvalcons1e0rj6fuy9yn5fwm9x4vw69xyuv7kzjm8rvw5r3",
         "pubKey":{
            "@type":"/cosmos.crypto.ed25519.PubKey",
            "key":"1mF7OEpB9A60O0e+64pICbqS/nN8VnsVfoySMEW2w1Q="
         },
         "votingPower":"199826816954540",
         "proposerPriority":"504834849146021"
      }
   ],
   "pagination":{
      "total":"7",
      "nextKey":""
   }
}
ParameterTypeDescription
block_heightIntegerBlock height
validatorsValidator ArrayList of validators
paginationPageResponsePagination information in the response


Validator

ParameterTypeDescription
addressStringValidator's address
pub_keyAnyValidator's public key
voting_powerIntegerValidator's voting power
proposer_priorityInteger


PageResponse

ParameterTypeDescription
next_keyByte ArrayThe key to be passed to PageRequest.key to query the next page most efficiently. It will be empty if there are no more results.
totalIntegerTotal number of results available if PageRequest.count_total was set, its value is undefined otherwise

ABCIQuery

Defines a query handler that supports ABCI queries directly to the application, bypassing Tendermint completely. The ABCI query must contain a valid and supported path, including app, custom, p2p, and store.

IP rate limit group: chain

Request Parameters

Request Example:

ParameterTypeDescriptionRequired
dataBytesQuery dataNo
pathStringQuery pathYes
haightIntegerBlock heightNo
proveBooleanNo

Response Parameters

Response Example:


ParameterTypeDescription
codeIntegerQuery result code (zero: success, non-zero: error
logString
infoString
indexInteger
keyBytes
valueBytes
proof_opsProofOps
heightIntegerBlock height
codespaceString


ProofOps

ParameterTypeDescription
opsProofOp Array


ProofOp

ParameterTypeDescription
typeString
keyBytes
dataBytes

- Tokenfactory

Tokenfactory module

DenomAuthorityMetadata

Gets the authority metadata for tokens by their creator address

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    metadata = await client.fetch_denom_authority_metadata(
        creator="inj1uv6psuupldve0c9n3uezqlecadszqexv5vxx04",
        sub_denom="position",
    )
    print(metadata)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    creator := "inj1uv6psuupldve0c9n3uezqlecadszqexv5vxx04"
    subDenom := "position"
    ctx := context.Background()

    res, err := chainClient.FetchDenomAuthorityMetadata(ctx, creator, subDenom)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
creatorStringThe denom creator addressYes
sub_denomStringThe token subdenomNo

Response Parameters

Response Example:

{'authorityMetadata': {'admin': 'inj1uv6psuupldve0c9n3uezqlecadszqexv5vxx04'}}
{
 "authority_metadata": {
  "admin": "inj1uv6psuupldve0c9n3uezqlecadszqexv5vxx04"
 }
}

ParameterTypeDescription
authority_metadataDenomAuthorityMetadataThe denom authority information


DenomAuthorityMetadata

ParameterTypeDescription
adminStringThe denom admin

DenomsFromCreator

Gets all the tokens created by a specific admin/creator

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    denoms = await client.fetch_denoms_from_creator(creator="inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3")
    print(denoms)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    creator := "inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3"
    ctx := context.Background()

    res, err := chainClient.FetchDenomsFromCreator(ctx, creator)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
ParameterTypeDescriptionRequired
creatorStringThe denom creator addressYes

Response Parameters

Response Example:

{
   "denoms":[
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/Stake-0",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/Talis",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/Talis-2",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/Talis-3",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/Talis-4",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/Vote-0",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/banana",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/bananas",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/stake-token",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/stake-token10",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/stake-token2",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/stake-token3",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/stake-token4",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/stake-token5",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/stake-token6",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/stake-token7",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/stake-token8",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/stake-token9",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/talis-5",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/talis-6",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/talis-7",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/talis-8",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/vote-token",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/vote-token10",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/vote-token2",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/vote-token3",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/vote-token4",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/vote-token5",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/vote-token6",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/vote-token7",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/vote-token8",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/vote-token9",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/xTalis-4",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/xbanana",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/xtalis-5",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/xtalis-6",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/xtalis-7",
      "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/xtalis-8"
   ]
}
{
 "denoms": [
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/Stake-0",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/Talis",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/Talis-2",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/Talis-3",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/Talis-4",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/Vote-0",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/banana",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/bananas",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/stake-token",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/stake-token10",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/stake-token2",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/stake-token3",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/stake-token4",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/stake-token5",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/stake-token6",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/stake-token7",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/stake-token8",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/stake-token9",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/talis-5",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/talis-6",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/talis-7",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/talis-8",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/vote-token",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/vote-token10",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/vote-token2",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/vote-token3",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/vote-token4",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/vote-token5",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/vote-token6",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/vote-token7",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/vote-token8",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/vote-token9",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/xTalis-4",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/xbanana",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/xtalis-5",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/xtalis-6",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/xtalis-7",
  "factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/xtalis-8"
 ]
}

ParameterTypeDescription
denomsString ArrayList of denoms

TokenfactoryModuleState

Retrieves the entire auctions module's state

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    state = await client.fetch_tokenfactory_module_state()
    print(state)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    ctx := context.Background()

    res, err := chainClient.FetchTokenfactoryModuleState(ctx)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}

No parameters

Response Parameters

Response Example:

{
   "state":{
      "params":{
         "denomCreationFee":[
            {
               "denom":"inj",
               "amount":"1000000000000000000"
            }
         ]
      },
      "factoryDenoms":[
         {
            "denom":"factory/inj10gcvfpnn4932kzk56h5kp77mrfdqas8z63qr7n/BITS",
            "authorityMetadata":{
               "admin":"inj10gcvfpnn4932kzk56h5kp77mrfdqas8z63qr7n"
            },
            "name":"BITS",
            "symbol":"BITS"
         },
         {
            "denom":"factory/inj10hmmvlqq6rrlf2c2v982d6xqsns4m3sy086r27/position",
            "authorityMetadata":{
               "admin":"inj10hmmvlqq6rrlf2c2v982d6xqsns4m3sy086r27"
            },
            "name":"",
            "symbol":""
         },
         {
            "denom":"factory/inj10jmp6sgh4cc6zt3e8gw05wavvejgr5pw6m8j75/ak",
            "authorityMetadata":{
               "admin":"inj10jmp6sgh4cc6zt3e8gw05wavvejgr5pw6m8j75"
            },
            "name":"AKCoin",
            "symbol":"AK"
         }
      ]
   }
}
{
   "state":{
      "params":{
         "denomCreationFee":[
            {
               "denom":"inj",
               "amount":"1000000000000000000"
            }
         ]
      },
      "factoryDenoms":[
         {
            "denom":"factory/inj10gcvfpnn4932kzk56h5kp77mrfdqas8z63qr7n/BITS",
            "authorityMetadata":{
               "admin":"inj10gcvfpnn4932kzk56h5kp77mrfdqas8z63qr7n"
            },
            "name":"BITS",
            "symbol":"BITS"
         },
         {
            "denom":"factory/inj10hmmvlqq6rrlf2c2v982d6xqsns4m3sy086r27/position",
            "authorityMetadata":{
               "admin":"inj10hmmvlqq6rrlf2c2v982d6xqsns4m3sy086r27"
            },
            "name":"",
            "symbol":""
         },
         {
            "denom":"factory/inj10jmp6sgh4cc6zt3e8gw05wavvejgr5pw6m8j75/ak",
            "authorityMetadata":{
               "admin":"inj10jmp6sgh4cc6zt3e8gw05wavvejgr5pw6m8j75"
            },
            "name":"AKCoin",
            "symbol":"AK"
         }
      ]
   }
}

ParameterTypeDescription
stateGenesisStateThe state details


GenesisState

ParameterTypeDescription
paramsParamsModule parameters
factory_denomsGenesisDenom ArrayModule parameters


Params

ParameterTypeDescription
denoms_creation_feeCoin ArrayFee required to create a denom


Coin

ParameterTypeDescriptionRequired
denomStringThe token denomYes
amountStringThe amount of tokensYes


GenesisDenom

ParameterTypeDescription
denomStringToken denom
authority_metadataDenomAuthorityMetadataToken authority metadata
nameStringToken name
symbolStringToken symbol


DenomAuthorityMetadata

ParameterTypeDescription
adminStringThe denom admin

CreateDenom

Create a new denom

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

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:
    dotenv.load_dotenv()
    private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()
    composer = ProtoMsgComposer(network=network.string())

    message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
        network=network,
        private_key=private_key_in_hexa,
    )

    priv_key = PrivateKey.from_hex(private_key_in_hexa)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()

    message = composer.msg_create_denom(
        sender=address.to_acc_bech32(),
        subdenom="inj_test",
        name="Injective Test Token",
        symbol="INJTEST",
        decimals=18,
    )

    # broadcast the transaction
    result = await message_broadcaster.broadcast([message])
    print("---Transaction Response---")
    print(result)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "encoding/json"
    "fmt"
    "os"

    tokenfactorytypes "github.com/InjectiveLabs/sdk-go/chain/tokenfactory/types"
    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )
    if err != nil {
        fmt.Println(err)
        return
    }
    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    message := new(tokenfactorytypes.MsgCreateDenom)
    message.Sender = senderAddress.String()
    message.Subdenom = "inj_test"
    message.Name = "Injective Test Token"
    message.Symbol = "INJTEST"
    message.Decimals = 18

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    response, err := chainClient.AsyncBroadcastMsg(message)

    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(response, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
senderStringSender Injective addressYes
subdenomStringNew token subdenomYes
nameStringNew token nameYes
symbolStringNew token symbolYes
decimalsIntegerNumber of decimals use to represent token amount on chainYes

Response Parameters

Response Example:

ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgMint

Allows a token admin's account to mint more units

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

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:
    dotenv.load_dotenv()
    private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()
    composer = ProtoMsgComposer(network=network.string())

    message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
        network=network,
        private_key=private_key_in_hexa,
    )

    priv_key = PrivateKey.from_hex(private_key_in_hexa)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()

    amount = composer.coin(amount=1_000_000_000, denom="factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test")

    message = composer.msg_mint(
        sender=address.to_acc_bech32(),
        amount=amount,
    )

    # broadcast the transaction
    result = await message_broadcaster.broadcast([message])
    print("---Transaction Response---")
    print(result)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "encoding/json"
    "fmt"
    "os"

    "cosmossdk.io/math"

    tokenfactorytypes "github.com/InjectiveLabs/sdk-go/chain/tokenfactory/types"
    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
    sdktypes "github.com/cosmos/cosmos-sdk/types"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )
    if err != nil {
        fmt.Println(err)
        return
    }
    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    message := new(tokenfactorytypes.MsgMint)
    message.Sender = senderAddress.String()
    message.Amount = sdktypes.Coin{
        Denom:  "factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test",
        Amount: math.NewInt(1000000000),
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    response, err := chainClient.AsyncBroadcastMsg(message)

    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(response, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
senderStringSender Injective addressYes
amountCoinAmount to mintYes


Coin

ParameterTypeDescriptionRequired
denomStringThe token denomYes
amountStringThe amount of tokensYes

Response Parameters

Response Example:

ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgBurn

Allows a token admin's account to burn circulating units

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

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:
    dotenv.load_dotenv()
    private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()
    composer = ProtoMsgComposer(network=network.string())

    message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
        network=network,
        private_key=private_key_in_hexa,
    )

    priv_key = PrivateKey.from_hex(private_key_in_hexa)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()

    amount = composer.coin(amount=100, denom="factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test")

    message = composer.msg_burn(
        sender=address.to_acc_bech32(),
        amount=amount,
    )

    # broadcast the transaction
    result = await message_broadcaster.broadcast([message])
    print("---Transaction Response---")
    print(result)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "encoding/json"
    "fmt"
    "os"

    "cosmossdk.io/math"

    tokenfactorytypes "github.com/InjectiveLabs/sdk-go/chain/tokenfactory/types"
    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
    sdktypes "github.com/cosmos/cosmos-sdk/types"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )
    if err != nil {
        fmt.Println(err)
        return
    }
    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    message := new(tokenfactorytypes.MsgBurn)
    message.Sender = senderAddress.String()
    message.Amount = sdktypes.Coin{
        Denom:  "factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test",
        Amount: math.NewInt(100),
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    response, err := chainClient.AsyncBroadcastMsg(message)

    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(response, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
senderStringSender Injective addressYes
amountCoinAmount to burnYes


Coin

ParameterTypeDescriptionRequired
denomStringThe token denomYes
amountStringThe amount of tokensYes

Response Parameters

Response Example:

ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgSetDenomMetadata

Allows a token admin's account to set the token metadata

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

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:
    dotenv.load_dotenv()
    private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()
    composer = ProtoMsgComposer(network=network.string())

    message_broadcaster = MsgBroadcasterWithPk.new_without_simulation(
        network=network,
        private_key=private_key_in_hexa,
    )

    priv_key = PrivateKey.from_hex(private_key_in_hexa)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()

    sender = address.to_acc_bech32()
    description = "Injective Test Token"
    subdenom = "inj_test"
    denom = "factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test"
    token_decimals = 6
    name = "Injective Test"
    symbol = "INJTEST"
    uri = "http://injective-test.com/icon.jpg"
    uri_hash = ""

    message = composer.msg_set_denom_metadata(
        sender=sender,
        description=description,
        denom=denom,
        subdenom=subdenom,
        token_decimals=token_decimals,
        name=name,
        symbol=symbol,
        uri=uri,
        uri_hash=uri_hash,
    )

    # broadcast the transaction
    result = await message_broadcaster.broadcast([message])
    print("---Transaction Response---")
    print(result)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "encoding/json"
    "fmt"
    "os"

    tokenfactorytypes "github.com/InjectiveLabs/sdk-go/chain/tokenfactory/types"
    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
    banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )
    if err != nil {
        fmt.Println(err)
        return
    }
    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    denom := "factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test"
    subdenom := "inj_test"
    tokenDecimals := uint32(6)

    microDenomUnit := banktypes.DenomUnit{
        Denom:    denom,
        Exponent: 0,
        Aliases:  []string{fmt.Sprintf("micro%s", subdenom)},
    }
    denomUnit := banktypes.DenomUnit{
        Denom:    subdenom,
        Exponent: tokenDecimals,
        Aliases:  []string{subdenom},
    }

    metadata := banktypes.Metadata{
        Description: "Injective Test Token",
        DenomUnits:  []*banktypes.DenomUnit{&microDenomUnit, &denomUnit},
        Base:        denom,
        Display:     subdenom,
        Name:        "Injective Test",
        Symbol:      "INJTEST",
        URI:         "http://injective-test.com/icon.jpg",
        URIHash:     "",
        Decimals:    tokenDecimals,
    }

    message := new(tokenfactorytypes.MsgSetDenomMetadata)
    message.Sender = senderAddress.String()
    message.Metadata = metadata

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    response, err := chainClient.AsyncBroadcastMsg(message)

    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(response, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
senderStringSender Injective addressYes
metadataMetadataToken metadataYes


Metadata

ParameterTypeDescription
descriptionStringToken description
denom_unitsDenomUnit ArrayAll token units
baseStringThe base token denom
displayStringSuggested denom that should be displayed in clients
nameStringToken name
symbolStringToken symbol
uriStringURI to a document (on or off-chain) that contains additional information. Optional
uri_hashStringURIHash is a sha256 hash of a document pointed by URI. It's used to verify that the document didn't change. Optional
decimalsIntegerNumber of decimals use to represent token amount on chain


DenomUnit

ParameterTypeDescription
denomStringName of the denom unit
exponentIntegerExponent represents power of 10 exponent that one must raise the base_denom to in order to equal the given DenomUnit's denom 1 denom = 10^exponent base_denom (e.g. with a base_denom of uatom, one can create a DenomUnit of 'atom' with exponent = 6, thus: 1 atom = 10^6 uatom)
aliasesString ArrayList of aliases for the denom

Response Parameters

Response Example:

ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgChangeAdmin

Allows a token admin's account to transfer administrative privileged to other account

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv

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:
    dotenv.load_dotenv()
    private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()
    composer = ProtoMsgComposer(network=network.string())

    message_broadcaster = MsgBroadcasterWithPk.new_without_simulation(
        network=network,
        private_key=private_key_in_hexa,
    )

    priv_key = PrivateKey.from_hex(private_key_in_hexa)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()

    message = composer.msg_change_admin(
        sender=address.to_acc_bech32(),
        denom="factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test",
        new_admin="inj1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqe2hm49",  # This is the zero address to remove admin permissions
    )

    # broadcast the transaction
    result = await message_broadcaster.broadcast([message])
    print("---Transaction Response---")
    print(result)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "encoding/json"
    "fmt"
    "os"

    tokenfactorytypes "github.com/InjectiveLabs/sdk-go/chain/tokenfactory/types"
    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )
    if err != nil {
        fmt.Println(err)
        return
    }
    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    message := new(tokenfactorytypes.MsgChangeAdmin)
    message.Sender = senderAddress.String()
    message.Denom = "factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test"
    // This is the zero address to remove admin permissions
    message.NewAdmin = "inj1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqe2hm49"

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    response, err := chainClient.AsyncBroadcastMsg(message)

    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(response, "", " ")
    fmt.Print(string(str))
}
ParameterTypeDescriptionRequired
senderStringSender Injective addressYes
denomStringToken denomYes
new_adminStringNew admin Injective addressYes

Response Parameters

Response Example:

ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

- Wasm

CosmWasm smart contract interactions.

ContractInfo

Queries validator commission and self-delegation rewards for validator

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    address = "inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7"
    contract_info = await client.fetch_contract_info(address=address)
    print(contract_info)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    address := "inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7"
    ctx := context.Background()

    res, err := chainClient.FetchContractInfo(ctx, address)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
Parameter Type Description Required
address String Contract address Yes

Response Parameters

Response Example:

{
   "address":"inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7",
   "contractInfo":{
      "codeId":"290",
      "creator":"inj1h3gepa4tszh66ee67he53jzmprsqc2l9npq3ty",
      "label":"CounterTestInstance",
      "created":{
         "blockHeight":"6232017",
         "txIndex":"145751"
      },
      "admin":"",
      "ibcPortId":""
   }
}
{
 "address": "inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7",
 "code_id": 290,
 "creator": "inj1h3gepa4tszh66ee67he53jzmprsqc2l9npq3ty",
 "label": "CounterTestInstance",
 "created": {
  "block_height": 6232017,
  "tx_index": 145751
 }
}

Parameter Type Description
address String Contract address
contract_info ContractInfo Contract metadata

ContractInfo

Parameter Type Description
code_id Int ID of the stored wasm code
creator String Address that instantiated the contract
admin String Address that can execute migrations
label String Contract label
created AbsoluteTxPosition Tx position when the contract was instantiated
ibc_port_id String

AbsoluteTxPosition | Parameter | Type | Description | | ------------ | ---- | ------------------------------------------------ | | block_height | Int | Block number when the contract was created | | tx_index | Int | Transaction index where the contract was created |

ContractHistory

Gets the contract code history

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    address = "inj18pp4vjwucpgg4nw3rr4wh4zyjg9ct5t8v9wqgj"
    limit = 2
    pagination = PaginationOption(limit=limit)
    contract_history = await client.fetch_contract_history(address=address, pagination=pagination)
    print(contract_history)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/cosmos/cosmos-sdk/types/query"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    address := "inj18pp4vjwucpgg4nw3rr4wh4zyjg9ct5t8v9wqgj"
    pagination := query.PageRequest{Limit: 2}
    ctx := context.Background()

    res, err := chainClient.FetchContractHistory(ctx, address, &pagination)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
Parameter Type Description Required
address String Contract address Yes
pagination Paging Pagination of results No

Response Parameters

Response Example:

{
   "entries":[
      {
         "operation":"CONTRACT_CODE_HISTORY_OPERATION_TYPE_INIT",
         "codeId":"3770",
         "updated":{
            "blockHeight":"20210946",
            "txIndex":"2196537"
         },
         "msg":"eyJhZG1pbiI6ImluajFtYWV5dnhmYW10bjhsZnl4cGpjYThrdXZhdXVmMnFldTZndHhtMyIsImNvZGVJZCI6IjM3NzAiLCJsYWJlbCI6IlRhbGlzIGNhbmR5IG1hY2hpbmUiLCJtc2ciOiIiLCJzZW5kZXIiOiJpbmoxandsbmN1dTY3NnQzcWZqZGxjd3NkZ3gwZ2c2anBhOHNuZXM0eHQiLCJmdW5kc0xpc3QiOltdLCJjb250cmFjdF9hZGRyZXNzIjoiaW5qMWd2emdneGc1NGRmd2FlcnpsZWdqdnFlZzN1ZTk3ZHEydmV0OTJ6Iiwib3duZXIiOiJpbmoxandsbmN1dTY3NnQzcWZqZGxjd3NkZ3gwZ2c2anBhOHNuZXM0eHQiLCJmZWVfY29sbGVjdG9yIjoiaW5qMW1hZXl2eGZhbXRuOGxmeXhwamNhOGt1dmF1dWYycWV1Nmd0eG0zIiwib3BlcmF0b3JfcHVia2V5IjoiQSsxQkVrWXVTQjJQa1IwWDVJMnZzQnNuTldHMVlPRDJUUTJJUHZnelJVVXYiLCJwcml2YXRlX3BoYXNlcyI6W3siaWQiOjAsInByaXZhdGUiOnRydWUsInN0YXJ0IjoxNzA0MTM4NTQwLCJlbmQiOjE3MDQxNDIxNDAsInByaWNlIjp7Im5hdGl2ZSI6W3siZGVub20iOiJpbmoiLCJhbW91bnQiOiIwIn1dfSwid2xfbWVya2xlX3Jvb3QiOiI1NGE5Yzg0MmE5MmY4ZGQ3Zjg3ZTZhZDM0MGEwMWI5ZmVhZWE0MjQyOThjYTA1NmY3NGNmZTAyNzFkZDExYjIwIn0seyJpZCI6MSwicHJpdmF0ZSI6dHJ1ZSwic3RhcnQiOjE3MDQxNDIxNDIsImVuZCI6MTcwNDE0NTc0MCwicHJpY2UiOnsibmF0aXZlIjpbeyJkZW5vbSI6ImluaiIsImFtb3VudCI6IjEwMDAwMDAwMDAwMDAwMDAwMCJ9XX0sIndsX21lcmtsZV9yb290IjoiZjU4YTIwZmUyMWUyYzRkNzE0OTRhMGMyOWQyZWRmZDRjZGJiNzgwOTlmZDQ1NWFkZjg0MjdjMjdiMjFiOGQ3YiJ9XSwicHVibGljX3BoYXNlIjp7ImlkIjoyLCJwcml2YXRlIjpmYWxzZSwic3RhcnQiOjE3MDQxNDU3NDIsImVuZCI6MTcwNDE0OTM0MCwicHJpY2UiOnsibmF0aXZlIjpbeyJkZW5vbSI6ImluaiIsImFtb3VudCI6IjQ1MDAwMDAwMDAwMDAwMDAwMCJ9XX0sIm1pbnRfbGltaXQiOjEwfSwicmVzZXJ2ZWRfdG9rZW5zIjo3NywidG90YWxfdG9rZW5zIjo3Nzd9"
      }
   ],
   "pagination":{
      "nextKey":"",
      "total":"0"
   }
}
{
 "entries": [
  {
   "operation": 1,
   "code_id": 3770,
   "updated": {
    "block_height": 20210946,
    "tx_index": 2196537
   },
   "msg": {
    "admin": "inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3",
    "codeId": "3770",
    "label": "Talis candy machine",
    "msg": "",
    "sender": "inj1jwlncuu676t3qfjdlcwsdgx0gg6jpa8snes4xt",
    "fundsList": [],
    "contract_address": "inj1gvzggxg54dfwaerzlegjvqeg3ue97dq2vet92z",
    "owner": "inj1jwlncuu676t3qfjdlcwsdgx0gg6jpa8snes4xt",
    "fee_collector": "inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3",
    "operator_pubkey": "A+1BEkYuSB2PkR0X5I2vsBsnNWG1YOD2TQ2IPvgzRUUv",
    "private_phases": [
     {
      "id": 0,
      "private": true,
      "start": 1704138540,
      "end": 1704142140,
      "price": {
       "native": [
        {
         "denom": "inj",
         "amount": "0"
        }
       ]
      },
      "wl_merkle_root": "54a9c842a92f8dd7f87e6ad340a01b9feaea424298ca056f74cfe0271dd11b20"
     },
     {
      "id": 1,
      "private": true,
      "start": 1704142142,
      "end": 1704145740,
      "price": {
       "native": [
        {
         "denom": "inj",
         "amount": "100000000000000000"
        }
       ]
      },
      "wl_merkle_root": "f58a20fe21e2c4d71494a0c29d2edfd4cdbb78099fd455adf8427c27b21b8d7b"
     }
    ],
    "public_phase": {
     "id": 2,
     "private": false,
     "start": 1704145742,
     "end": 1704149340,
     "price": {
      "native": [
       {
        "denom": "inj",
        "amount": "450000000000000000"
       }
      ]
     },
     "mint_limit": 10
    },
    "reserved_tokens": 77,
    "total_tokens": 777
   }
  }
 ],
 "pagination": {}
}

Parameter Type Description
entries ContractCodeHistoryEntry Array Contract code history
pagination PageResponse Pagination of results

ContractCodeHistoryEntry

Parameter Type Description
operation ContractCodeHistoryOperationType Contract creation operation type
code_id Int ID of the store wasm code
updated AbsoluteTxPosition Contract update info
msg RawContractMessage Contract update message

AbsoluteTxPosition | Parameter | Type | Description | | ------------ | ---- | ------------------------------------------------ | | block_height | Int | Block number when the contract was created | | tx_index | Int | Transaction index where the contract was created |

ContractCodeHistoryOperationType | ID | Type | | --- | ------------------------------------------- | | 0 | ContractCodeHistoryOperationTypeUnspecified | | 1 | ContractCodeHistoryOperationTypeInit | | 2 | ContractCodeHistoryOperationTypeMigrate | | 3 | ContractCodeHistoryOperationTypeGenesis |

ContractsByCode

Get all smart contracts for a code id

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    code_id = 3770
    limit = 2
    pagination = PaginationOption(limit=limit)
    contracts = await client.fetch_contracts_by_code(code_id=code_id, pagination=pagination)
    print(contracts)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/cosmos/cosmos-sdk/types/query"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    codeId := uint64(3770)
    pagination := query.PageRequest{Limit: 2}
    ctx := context.Background()

    res, err := chainClient.FetchContractsByCode(ctx, codeId, &pagination)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
Parameter Type Description Required
code_id Int ID of the stored wasm code Yes
pagination Paging Pagination of results No

Response Parameters

Response Example:

{
   "contracts":[
      "inj1z4l7jc8dj3y9484aqcrmf6y8mcctvkmm9zkf7n",
      "inj18jead47nj8j20kxq5j2rm6l9fmf45f8ey9muuh"
   ],
   "pagination":{
      "nextKey":"AAAAAAEWkNYAAAAAAAAAAEnOwG7FHHD7R+iyNAZCsoHr5hA1",
      "total":"0"
   }
}
{
 "contracts": [
  "inj1z4l7jc8dj3y9484aqcrmf6y8mcctvkmm9zkf7n",
  "inj18jead47nj8j20kxq5j2rm6l9fmf45f8ey9muuh"
 ],
 "pagination": {
  "next_key": "AAAAAAEWkNYAAAAAAAAAAEnOwG7FHHD7R+iyNAZCsoHr5hA1"
 }
}

Parameter Type Description
contracts String Array Array of contracts addresses
pagination PageResponse Pagination of results

AllContractState

Gets all raw store data for a single contract

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    address = "inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7"
    limit = 2
    pagination = PaginationOption(limit=limit)
    contract_history = await client.fetch_all_contracts_state(address=address, pagination=pagination)
    print(contract_history)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/cosmos/cosmos-sdk/types/query"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    address := "inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7"
    pagination := query.PageRequest{Limit: 2}
    ctx := context.Background()

    res, err := chainClient.FetchAllContractsState(ctx, address, &pagination)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
Parameter Type Description Required
address String Contract address Yes
pagination Paging Pagination of results No

Response Parameters

Response Example:

{
   "models":[
      {
         "key":"Y29udHJhY3RfaW5mbw==",
         "value":"eyJjb250cmFjdCI6ImNyYXRlcy5pbzpjdy1jb3VudGVyIiwidmVyc2lvbiI6IjAuMS4wIn0="
      },
      {
         "key":"c3RhdGU=",
         "value":"eyJjb3VudCI6MTA0MSwib3duZXIiOiJpbmoxaDNnZXBhNHRzemg2NmVlNjdoZTUzanptcHJzcWMybDlucHEzdHkifQ=="
      }
   ],
   "pagination":{
      "nextKey":"",
      "total":"0"
   }
}
{
 "models": [
  {
   "key": "636F6E74726163745F696E666F",
   "value": "eyJjb250cmFjdCI6ImNyYXRlcy5pbzpjdy1jb3VudGVyIiwidmVyc2lvbiI6IjAuMS4wIn0="
  },
  {
   "key": "7374617465",
   "value": "eyJjb3VudCI6MTA0MSwib3duZXIiOiJpbmoxaDNnZXBhNHRzemg2NmVlNjdoZTUzanptcHJzcWMybDlucHEzdHkifQ=="
  }
 ],
 "pagination": {}
}
Parameter Type Description
models Model Array Array of contracts' models
pagination PageResponse Pagination of results

Model | Parameter | Type | Description | | --------- | ---------- | ------------------------------------------ | | key | String | Hexadecimal representation of the byte key | | Value | Byte Array | Raw value in base64 encoding |

RawContractState

Gets single key from the raw store data of a contract

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    address = "inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7"
    query_data = '{"get_count": {}}'
    contract_state = await client.fetch_raw_contract_state(address=address, query_data=query_data)
    print(contract_state)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    address := "inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7"
    queryData := []byte("{\"get_count\": {}}")
    ctx := context.Background()

    res, err := chainClient.RawContractState(ctx, address, queryData)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
Parameter Type Description Required
address String Contract address Yes
query_data Byte Array Key of the data to retrieve Yes

Response Parameters

Response Example:

Parameter Type Description
Data Byte Array Raw data in base64 encoding

SmartContractState

Get smart query result from the contract

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    address = "inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7"
    query_data = '{"get_count": {}}'
    contract_state = await client.fetch_smart_contract_state(address=address, query_data=query_data)
    print(contract_state)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    address := "inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7"
    queryData := []byte("{\"get_count\": {}}")
    ctx := context.Background()

    res, err := chainClient.SmartContractState(ctx, address, queryData)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
Parameter Type Description Required
address String Contract address Yes
query_data Byte Array Query to execute in the contract Yes

Response Parameters

Response Example:

{'data': 'eyJjb3VudCI6MTA0MX0='}
{
 "data": {
  "count": 1041
 }
}
Parameter Type Description
Data Byte Array Raw data in base64 encoding

Code

Gets the binary code and metadata for a contract

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import base64

from pyinjective.async_client import AsyncClient
from pyinjective.core.network import Network


async def main() -> None:
    network = Network.testnet()
    client = AsyncClient(network)
    response = await client.fetch_code(code_id=290)
    print(response)

    code = base64.b64decode(response["data"]).decode(encoding="utf-8", errors="replace")

    print(f"\n\n\n{code}")


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    codeId := uint64(290)
    ctx := context.Background()

    res, err := chainClient.FetchCode(ctx, codeId)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
Parameter Type Description Required
code_id Int ID of the contract code Yes

Response Parameters

Response Example:

{
   "codeInfo":{
      "codeId":"290",
      "creator":"inj1h3gepa4tszh66ee67he53jzmprsqc2l9npq3ty",
      "dataHash":"+OdoniOsDJ1T9EqP2YxobCCwFAqNdtYA4sVGv7undY0=",
      "instantiatePermission":{
         "permission":"ACCESS_TYPE_EVERYBODY",
         "addresses":[

         ]
      }
   },
   "data":"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Qf8BcQshBgJAAkACQCAEIAZyIgZB/wFxIgVBAkcEQCAGQQFxDQEgC0UNAiADQfACakG5gcAAQQcQGCARRQ0KDAkLIAsNCiADQdACakG5gcAAQQcQFiADKALQAkEVRgRAIAMoAtwCIRQgAygC2AIhESADKALUAiELDAsLIANB+AJqIANB2AJqKQMANwMAIAMgAykD0AI3A/ACDAkLIANB0AJqIA4QjgECQCADKALQAiIPQRVHBEAgFyAYKQIANwIAIBdBCGogGEEIaigCADYCACADIA82AoADDAELIANBgANqIA4QFyADKAKAA0EVRg0CCyADQfgCaiADQYgDaikDADcDACADIAMpA4ADNwPwAgwGCyADQdACaiAOEI4BIAMoAtACIgRBFUcNAiADQdACaiAOEBogAygC3AIhFCADKALYAiERIAMoAtQCIQsgAygC0AIiBEEVRw0JCyADQbABaiAOEJABIAMtALEBIQQgAy0AsAFBAXENAAsMAgsgAygC3AIhFCADKALYAiERIAMoAtQCIQsMBgsgC0H/AXEhC0EEIQQMBQsgAyAJNgL8AiADIAQ2AvgCIAMgBTYC9AIgAyABNgLwAgsgC0UgEUVyDQELIAsQqwELIAMoAvwCIRQgAygC+AIhESADKAL0AiELIAMoAvACIgRBFUcNAQsgA0HQAmogCBCNASADKALQAiIEQRVGDQIgAygC3AIhFCADKALYAiADKALUAiEBIBEEQCALEKsBCyERIAEhCwsgAyAUNgKkAiADIBE2AqACIAMgCzYCnAIgAyAENgKYAgwJCyAhQiiIpyEKICFCIIinIRUgIachGyAJIRYLIANBCGogCBCQASADLQAJIQEgAy0ACEEBcQ0AC0ECIQQMAwtBACENDAMLIANBoAJqIANB2AJqKQMANwMAIAMgAykD0AI3A5gCIBZFDQUgDRCrAQwFCyADIBQ2AsgCIAMpA8gCISAgA0GYAmogA0GIAmoQjQEgAygCmAIiAUEVRwRAIAMtAJ8CQRB0IQkgAy8AnQIgAykDoAIhICADLQCcAiEMIBYEQCANEKsBCyAJciECIBFFDQYgCxCrAQwGCyADQZgCaiADQYgCahCLASADKAKYAiIBQRVHBEAgAy0AnwJBEHQhCSADLwCdAiADKQOgAiEgIAMtAJwCIQwgFgRAIA0QqwELIAlyIQIg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aigCACIENgIAIAMgCykCACIMNwMwIAlBCGogBDYCACAJIAw3AgAMAQsgA0EgaiAHEBcgAygCICIFQRVGDQELIAMoAiwhCSADKAIoIQggAy0AJCEEIAMvACUgAy0AJ0EQdHIMBgsgAyAHEJABIAMtAAEhBSADLQAAQQFxDQALCyAEQf8BcSEEQQIhBQwCCyAKQRU2AgAMAwsgAygCTCEJIAYhBAsgBEEIdgsiBjsABSAKIAk2AAwgCiAINgAIIAogBDoABCAKIAU2AgAgCkEHaiAGQRB2OgAACyADQdAAaiQAIAIoAlAiBEEVRw0KIAJB0ABqIAEQjQEgAigCUCIBQRVGBEAgAEEVNgIADAwLIAJByABqIAJB3ABqKAIAIgQ2AgAgAiACKQJUIgw3A0AgAEEMaiAENgIAIAAgDDcCBCAAIAE2AgAMCwsgAEELNgIADAoLIABBFTYCAAwJCyAAQQA7AAUgAEEENgIAIABBB2pBADoAAAwICyAAQQ42AgAMBwsgAikCVCEMIAAgAigCXDYCDCAAIAw3AgQgACABNgIADAYLIABBADsABSAAQQQ2AgAgAEEHakEAOgAADAULIABBDjYCAAwECyACQcgAaiACQdwAaigCACIBNgIAIAIgAikCVCIMNwNAIABBDGogATYCACAAIAw3AgQgACAENgIADAMLIABBADsABSAAQQQ2AgAgAEEHakEAOgAADAILIABBDjYCAAwBCyACQcgAaiACQdwAaigCACIBNgIAIAIgAikCVCIMNwNAIABBDGogATYCACAAIAw3AgQgACAENgIACyACQeAAaiQAC8UBAQF/IwBB8ABrIgMkACADIAI2AgwgAyABNgIIIANBJGpBATYCACADQgI3AhQgA0GUi8AANgIQIANBATYCLCADIANBKGo2AiAgAyADQQhqNgIoIANBADYCOCADQgE3AzAgA0FAayIBIANBMGpBqIXAABDyASADQRBqIAEQ6AEEQEHAhcAAQTcgA0HoAGpB+IXAAEHUhsAAEOkBAAsgACADKQMwNwIEIABBFDYCACAAQQxqIANBOGooAgA2AgAgA0HwAGokAAuFBAIFfwJ+IwBB4ABrIgMkACADIAI2AgwgAyABNgIIIwBBEGsiBiQAIANBEGoiBAJ/AkACQCACRQRAIARBADoAAQwBCwJAAkACQCABLQAAQStrDgMBAgACCyACQQFGDQMMAQsgAkEBayICRQ0CIAFBAWohAQsCQAJAAkAgAkERTwRAA0AgBiAIQgBCChCMAiABLQAAQTBrIgVBCUsNBiAGKQMIQgBSDQQgBikDACIJIAUgByAFQQpJG618IgggCVQNAyABQQFqIQEgBSEHIAJBAWsiAg0ACwwBCwNAIAEtAABBMGsiBUEJSw0FIAFBAWohASAFrSAIQgp+fCEIIAJBAWsiAg0ACwsgBCAINwMIQQAMBAsgBEECOgABDAELIARBAjoAAQtBAQwBCyAEQQE6AAFBAQs6AAAgBkEQaiQAAkAgAy0AEEUEQCAAIAMpAxg3AwggAEEVNgIADAELIAMgAy0AEToAJyADQcQAakECNgIAIANBATYCPCADIANBJ2o2AkAgAyADQQhqNgI4IANBAjYCXCADQgI3AkwgA0Hci8AANgJIIAMgA0E4ajYCWCADQShqIgEgA0HIAGoiAhDQASACQQRyIAEQ0QEgA0EUNgJIIAMoAiwEQCADKAIoEKsBCyAAIAMpA0g3AgAgAEEIaiADQdAAaikDADcCAAsgA0HgAGokAAvFAgIEfwF+IwBBIGsiAiQAIAJBCGogARCQAQJAAkACQAJAAkAgAi0ACEEBcQRAIAItAAlBIkcNASABEIoBIAJBEGogARCPASACKAIQIgFBFUcNAiACQRxqKAIAIQEgAkEYaigCACEDIAIoAhQiBEUEQAJAIAFFBEBBASEEDAELIAFBf0oiBUUNBSABIAUQPSIERQ0GCyAEIAMgARCLAiEDIABBDGogATYCACAAQQhqIAE2AgAgACADNgIEIABBFTYCAAwGCyAAIAQ2AgQgAEEVNgIAIABBDGogATYCACAAQQhqIAM2AgAMBQsgAEEAOwAFIABBBDYCACAAQQdqQQA6AAAMBAsgAEEONgIADAMLIAIpAhQhBiAAIAIoAhw2AgwgACAGNwIEIAAgATYCAAwCCxDPAQALIAEgBRDOAQALIAJBIGokAAv3AQEDfyMAQUBqIgQkAAJAAkACQAJAIAJFBEBBASEFDAELIAJBf0oiBkUNASACIAYQPSIFRQ0CCyAFIAEgAhCLAiEBIARBADYCCCAEQgE3AwAgBEEQaiIFIARBqIXAABDyASADIAUQhwENAiAAQQxqIAI2AgAgAEEIaiACNgIAIAAgATYCBCAAIAQpAwA3AhAgAEEINgIAIABBGGogBEEIaigCADYCAAJAIAMoAgBBFEkNACADQQhqKAIARQ0AIAMoAgQQqwELIARBQGskAA8LEM8BAAsgAiAGEM4BAAtBwIXAAEE3IARBOGpB+IXAAEHUhsAAEOkBAAvwIwIbfwN+IwBBkAJrIgMkACADQZABaiIHIAEgAhCJASADQYgBaiAHEJABQQAhAgJAAkACQCADLQCIAUEBcUUEQEEEIQEMAQsgAy0AiQFB+wBHBEBBDiEBDAELIANBkAFqIgEQigEgA0GAAWogARCIASADLQCEASEEIANB+ABqIAMoAoABIgwQkAECQAJAAkACQAJAIAMtAHhBAXFFBEBBAiECDAELIAMtAHkhAiAEQQFxIRcgA0HoAWpBBHIhESADQYACakEEciEUIANB8AFqIRggA0HUAWohHCADQfMBaiEdA0ACfwJAAkACfwJAIAJB/wFxIgRBLEcEQCAEQf0ARwRAIBcNAkEJDAMLIA1BgH5xIQJBAwwFC0EQIBcNARogDBCKASADQfAAaiAMEJABIAMtAHBBAXFFDQIgAy0AcSECCyACQf8BcSIEQSJGDQJBECAEQf0ARw0AGkETCyECIA0hCwwECyANQf8BcSELQQQhAgwDCyADQegAaiAMEJABIAMtAGhBAXFFBEBBBCECQQAhCwwDCyADLQBpQSJHBEBBDiECDAMLIAwQigEgA0HIAWogDBCPASADKALUASEFIAMoAtABIQQgAygCzAEhCyADKALIASICQRVHDQICQCALRQRAQQIhAgJAAkAgBUEFaw4CAQADCyAEQa6BwABBBhCNAkEAR0EBdCECDAILQQJBASAEQbSBwABBBRCNAhshAgwBC0ECIQICQAJAAkAgBUEFaw4CAQACCyALQa6BwABBBhCNAkEAR0EBdCECDAELQQJBASALQbSBwABBBRCNAhshAgsgBEUNACALEKsBC0EAIRcgDUGAfnELIQQCQAJAAkACQAJAAkACQCACIARyIg1B/wFxIgtBA0cEQCALDgIDAgELIBkhDQJAIBIiB0UEQCADQcgBakGugcAAQQYQFiADKALIAUEVRw0BIANB1AFqKAIAIRUgAygCzAEhByADQdABaigCACENCwJAIAZFBEAgA0HIAWpBtIHAAEEFEBYgAygCyAFBFUcNASADQdABaigCACEJIAMoAswBIQYgA0HUAWooAgAhCAsgAyAJNgKwASADIAY2AqwBIAMgFTYCqAEgAyANNgKkASADIAc2AqABIAdFDQ4gA0HIAWogA0GQAWoQjQEgAygCyAEiAUEVRg0FIAMoAswBIQsgAygC1AEhBCADKALQASEFIA0EQCAHEKsBCyAIBEAgCEEFdCEHIAZBEGohAgNAIAJBBGooAgAEQCACKAIAEKsBCyACQSBqIQIgB0EgayIHDQALCyALQQh2IQIgCUUNDyAGEKsBDA8LIBJFIQIgA0GsAWogA0HQAWopAwA3AgAgAyADKQPIATcCpAEgDUUNDCAHEKsBDAwLIANBrAFqIANB0AFqKQMANwIAIAMgAykDyAE3AqQBQQAhEiAGDQkMCgsgA0HIAWogDBCOAQJAIAMoAsgBIgFBFUcEQCADQfQBaiADQdQBaigCADYCACADIAMpAswBNwLsASADIAE2AugBDAELIANB6AFqIAwQFyADKALoAUEVRg0GCyADQawBaiADQfABaikDADcCACADIAMpA+gBNwKkASADQQA2AqABIAYNCAwJCyAGRQ0DIANBoAFqQQRyQbSBwABBBRAYIANBADYCoAEMBwsgEkUNASADQaABakEEckGugcAAQQYQGCADQQA2AqABIAYNBgwHCyADQcgBaiADQZABahCLASADKALIASIBQRVHBEAgAygC1AEhBCADKALQASEFIAMoAswBIQIgDQRAIAcQqwELIAgEQCAIQQV0IQcgBkEQaiELA0AgC0EEaigCAARAIAsoAgAQqwELIAtBIGohCyAHQSBrIgcNAAsLIAlFDQsgBhCrAQwLCyAAQRhqIAg2AgAgAEEUaiAJNgIAIABBEGogBjYCACAAQQxqIBU2AgAgAEEIaiANNgIAIAAgBzYCBCAAQQ02AgAMCwsgA0HIAWogDBCOAQJ/IAMoAsgBIgJBFUYEQCADQcgBaiAMEBogAygC1AEhFSADKALMASESIAMoAtABIgQgAygCyAEiAkEVRw0BGiAEIRkMAwsgAygC1AEhFSADKALMASESIAMoAtABCyEBIANBsAFqIBU2AgAgA0GsAWogATYCACADQagBaiASNgIAIAMgAjYCpAFBACESIANBADYCoAEgBg0EDAULIANByAFqIAwQjgECQAJAAkACQAJAAkACQAJAAkAgAygCyAEiCkEVRgRAIANB4ABqIAwQkAEgAy0AYEEBcQRAIAMtAGFB2wBHBEBBDiEKDAsLIAwQigEgA0HYAGogDBCIASADLQBcIQQgAygCWCEQQQAhBiADQQA2AsABIANCCDcDuAEgA0HQAGogEBCQAUEBIQpBCCEHIAMtAFBBAXFFDQggAy0AUSECIARBAXEhBkEAIQhBCCETA0ACQCACQf8BcSIEQSxHBEAgBEHdAEYNBSAGQf8BcSEEQQAhBiAEDQFBByEKDAoLIBAQigEgA0HIAGogEBCQASADLQBIQQFxRQRAQQAhBkEEIQoMCgsgAy0ASSECCyACQf8BcUHdAEYEQEEAIQZBEyEKDAkLIANBQGsgEBCQAUEAIQkgAy0AQEEBcUUEQEEEIQoMCAsgAy0AQUH7AEcEQEEOIQoMCAsgEBCKASADQThqIBAQiAEgAy0APCADQTBqIAMoAjgiDhCQAUECIQIgAy0AMEEBcUUEQEEAIQFBACEEDAULIAMtADEhBUEBcSEJQQAhAUIAIR4DQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAn8CQAJAAn8CQCAFQf8BcSIEQSxHBEAgBEH9AEcEQCAJQf8BcQ0CQQkMAwsgB0GAfnEhBUEDDAULQRAgCUH/AXENARogDhCKASADQShqIA4QkAEgAy0AKEEBcUUNAiADLQApIQULIAVB/wFxIgRBIkYNAkEQIARB/QBHDQAaQRMLIQIgByEEDBULIAdB/wFxIQRBBCECDBQLIANBIGogDhCQASADLQAgQQFxRQRAQQQhAkEAIQQMFAsgAy0AIUEiRwRAQQ4hAgwUCyAOEIoBIANB6AFqIA4QjwEgAygC9AEhCiADKALwASEJIAMoAuwBIQQgAygC6AEiBUEVRwRAIAUhAgwUCwJAIARFBEBBAiEFAkACQCAKQQVrDgIAAQMLIAlBoIDAAEEFEI0CQQBHQQF0IQUMAgtBAkEBIAlBpYDAAEEGEI0CGyEFDAELQQIhBQJAAkACQCAKQQVrDgIAAQILIARBoIDAAEEFEI0CQQBHQQF0IQUMAQtBAkEBIARBpYDAAEEGEI0CGyEFCyAJRQ0AIAQQqwELQQAhCSAHQYB+cQsgBXIiB0H/AXEiBEEDRwRAIAQOAgMCAQsgGiEFIAEiBEUEQCADQegBakGggMAAQQUQFiADKALoAUEVRw0FIAMoAvQBIRsgAygC8AEhBSADKALsASEECyAepw0DIAFFIQIgEUGlgMAAQQYQFiADQdABaiARQQhqKQIANwMAIAMgESkCADcDyAEgBUUNEyAEEKsBDBMLIANB6AFqIA4QjgECQCADKALoASIFQRVHBEAgFCARKQIANwIAIBRBCGogEUEIaigCADYCACADIAU2AoACDAELIANBgAJqIA4QFyADKAKAAkEVRg0MCyADQdABaiADQYgCaikDADcDACADIAMpA4ACNwPIAUEBIQIMEgsgHqcNByADQYACaiAOEI4BIAMoAoACIgVBFUcNBiADQRhqIA4QkAEgAy0AGEEBcQRAIAMtABlBIkcNBSAOEIoBIANBgAJqIA4QjwEgAygCjAIhDyADKAKIAiEKIAMoAoQCIQUgAygCgAIiFkEVRw0GAkAgBUUEQCADQegBaiAKIA8QHQwBCyADQegBaiAFIA8QHSAKRQ0AIAUQqwELIAMoAugBDQogA0H4AWopAwAhICADKQPwASEfQgEhHgwLCyAdQQA6AAAgA0EAOwDxASADQQQ2AuwBDAkLIAFFDQcgA0HIAWpBoIDAAEEFEBhBASECDBALIAMgHzcDyAEgAyAbNgLgASADIAU2AtwBIAMgBDYC2AEgAyAgNwPQASAERQ0QIAMpA+ABIR4gA0HIAWogEBCNASADKALIASIKQRVGDQEgAykCzAEiHkIgiKchCSAcKAIAIRAgHqchBiAFRQ0SIAQQqwEMEgsgA0HQAWogGCkDADcDACADIAMpA+gBNwPIAQwPCyADKAK8ASAIRgRAIANBuAFqIRMjAEEgayIPJAACQAJAIAhBAWoiAkUNACATQQRqKAIAIhZBAXQiASACIAEgAksbIgFBBCABQQRLGyIIQQV0IQIgCEGAgIAgSUEDdCEBAkAgFgRAIA9BCDYCGCAPIBZBBXQ2AhQgDyATKAIANgIQDAELIA9BADYCGAsgDyACIAEgD0EQahA1IA8oAgQhAiAPKAIARQRAIBMgAjYCACATQQRqIAg2AgAMAgsgD0EIaigCACIBQYGAgIB4Rg0BIAFFDQAgAiABEM4BAAsQzwEACyAPQSBqJAAgAygCuAEhEyADKALAASEICyATIAhBBXRqIgEgIDcDCCABIB83AwAgASAeNwMYIAEgBTYCFCABIAQ2AhBBASEKIAMgCEEBaiIINgLAASADQQhqIBAQkAEgAy0ACSECIAMtAAhBAXENCEEAIQYMEAsgA0EONgLsAQwECyADIA82AvgBIAMgCjYC9AEgAyAFNgLwASADIBY2AuwBDAMLIBggFCkCADcCACAYQQhqIBRBCGooAgA2AgAgAyAFNgLsAQwCCyADQcgBakGlgMAAQQYQGCADQQA2AtgBQQEhAgwJCyADQegBaiAOEI4BAkACQCADKALoASIFQRVHBEAgFCARKQIANwIAIBRBCGogEUEIaigCADYCACADIAU2AoACDAELIANBgAJqIA4QGiADKAKAAkEVRg0BCyADQdABaiADQYgCaikDADcDACADIAMpA4ACNwPIAQwKCyADKAKMAiEbIAMoAogCIRogAygChAIhAQwBCyADQdABaiARQQhqKQIANwMAIANBADYC2AEgAyARKQIANwPIAUEBIQIMBwsgA0EQaiAOEJABIAMtABEhBSADLQAQQQFxDQALCwwDCyAGQf8BcSEGQQQhCgwJCyADKALUASEIIAMoAtABIQkgAygCzAEhBgwICyADKAK8ASEJIAMoArgBIQYMBgsgAyAKNgLUASADIAk2AtABIAMgBDYCzAEgAyACNgLIAUEBIQILIBpFIAFFIAJFcnINACABEKsBCyADKQPIASIeQiCIpyEGIANB0AFqKQMAIh9CIIinIRAgHqchCiAfpyEJDAELQQAhBkEAIRALIAMoArgBIQcgCARAIAhBBXQhAUEAIQIDQCACIAdqIgRBFGooAgAiBQRAIARBEGooAgAQqwELIAEgAkEgaiICRw0ACwsgECEICyADKAK8AQRAIAcQqwELIApBFUcNAQsgA0HIAWogDBCMASADKALIASIKQRVGDQEgAygC1AEgAygC0AEhDSADKALMASAIBEAgCEEFdCEBIAZBEGohAgNAIAJBBGooAgAEQCACKAIAEKsBCyACQSBqIQIgAUEgayIBDQALCyAJBEAgBhCrAQshBiEIIA0hCQsgA0GwAWogCDYCACADQawBaiAJNgIAIANBqAFqIAY2AgAgAyAKNgKkAQwECyADIAwQkAEgAy0AASECIAMtAABBAXENAAtBAiECCyADQbABaiAFNgIAIANBrAFqIAQ2AgAgA0GoAWogCzYCACADIAI2AqQBIAZFDQELIAgEQCAIQQV0IQEg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A2pB+wA6AAAgAkHQAWogBEGYg8AAQQYQlwECQAJAIAIoAtABRQRAIAQoAggiAyAHKAIARgRAIAQgAxAQIAQoAgghAwsgBCADQQFqNgIIIAQoAgAgA2pBOjoAACACQdABaiAEEJsBIAIoAtABRQ0BIAJBzAFqIAVBCGooAgA2AgAgAiAFKQIANwLEAQwCCyACQZABaiACQdwBaigCADYCACACIAIpAtQBNwOIAQwSCyACQcABaiACKALUASACLQDYARCTASACKALAAUUNAwsgAkGQAWogAkHMAWooAgA2AgAgAiACKQLEATcDiAEMEAsgBygCACADRgRAIAQgAxAQIAQoAgghAwsgBCADQQFqNgIIIAQoAgAgA2pB+wA6AAAgAkHQAWogBEGUg8AAQQQQlwEgAigC0AENBCAEKAIIIgMgBygCAEYEQCAEIAMQECAEKAIIIQMLIAQgA0EBajYCCCAEKAIAIANqQTo6AAACQAJAAkACQAJAIAlBAWsOBAMCAQAECyACQdABaiAEQcKDwABBCxCcASACKALQAQ0HIAIgAi0A2AE6AKQBIAIgAigC1AE2AqABIAJB0AFqIAJBoAFqQc2DwABBDSAIQRRrKAIAIAhBDGsoAgAQDyACKALQAUUEQCACQcABaiACKAKgASACLQCkARCUAQwPCyAGIAUpAgA3AgAgBkEIaiAFQQhqKAIANgIADAsLIAJB0AFqIARB2oPAAEEMEJwBIAIoAtABBEAgBiAFKQIANwIAIAZBCGogBUEIaigCADYCAAwLCyACIAItANgBOgCkASACIAIoAtQBNgKgASACQdABaiACQaABakHNg8AAQQ0gCEEUaygCACAIQQxrKAIAEA8gAigC0AEEQCAGIAUpAgA3AgAgBkEIaiAFQQhqKAIANgIADAsLIAJB0AFqIAJBoAFqQeaDwABBBSAIQQhrKAIAIAgoAgAQDyACKALQAUUNDCAGIAUpAgA3AgAgBkEIaiAFQQhqKAIANgIADAoLIAJB0AFqIARB64PAAEEHEJwBIAIoAtABBEAgBiAFKQIANwIAIAZBCGogBUEIaigCADYCAAwKCyACIAItANgBOgCkASACIAIoAtQBNgKgASACQdABaiACQaABakHNg8AAQQ0gCEEUaygCACAIQQxrKAIAEA8gAigC0AEEQCAGIAUpAgA3AgAgBkEIaiAFQQhqKAIANgIADAoLIAJB0AFqIAJBoAFqQfKDwABBCyAIQQhqKQMAEBIgAigC0AEEQCAGIAUpAgA3AgAgBkEIaiAFQQhqKAIANgIADAoLIAJB0AFqIAJBoAFqIAhBCGsQEyACKALQAUUNCiAGIAUpAgA3AgAgBkEIaiAFQQhqKAIANgIADAkLIAJB0AFqIARBgITAAEELEJwBIAIoAtABRQ0HIAYgBSkCADcCACAGQQhqIAVBCGooAgA2AgAMCAsgAkHQAWogBEGXhMAAQQcQnAEgAigC0AEEQCAGIAUpAgA3AgAgBkEIaiAFQQhqKAIANgIADAgLIAIgAi0A2AE6AKQBIAIgAigC1AE2AqABIAJB0AFqIAJBoAFqQc2DwABBDSAIQRRrKAIAIAhBDGsoAgAQDyACKALQAQRAIAYgBSkCADcCACAGQQhqIAVBCGooAgA2AgAMCAsgAkHQAWogAkGgAWogCEEIaxATIAIoAtABBEAgBiAFKQIANwIAIAZBCGogBUEIaigCADYCAAwICyACQdABaiACQaABakG0gcAAQQUgCEEEaigCACAIQQxqKAIAEBQgAigC0AFFDQUgBiAFKQIANwIAIAZBCGogBUEIaigCADYCAAwHCyACQbwBaiACQdwBaigCADYCACACIAIpAtQBNwK0AQwaCyAEKAIIIgMgBygCAEYNCwwMCyACQZABaiACQdwBaigCADYCACACIAIpAtQBNwOIAQwMCyAGIAUpAgA3AgAgBkEIaiAFQQhqKAIANgIADAMLIAJBkAFqIAJB3AFqKAIANgIAIAIgAikC1AE3A4gBDAoLIAJBwAFqIAIoAqABIAItAKQBEJQBDAQLIAIgAigC1AEiAzYCmAEgCEEMaygCACEPIAhBFGsoAgAhDQJAIAItANgBBEAgAygCCCEJDAELIAMoAggiCiADKAIERgRAIAMgChAQIAMoAgghCgsgAyAKQQFqIgk2AgggAygCACAKakEsOgAACyACQQA6AJwBIANBBGoiCigCACAJRgRAIAMgCRAQIAMoAgghCQsgAygCACAJakEiOgAAIAMgCUEBaiIJNgIIIAooAgAgCWtBBE0EQCADIAlBBRARIAMoAgghCQsgAygCACAJaiIQQeaDwAAoAAA2AAAgEEEEakHqg8AALQAAOgAAIAMgCUEFaiIJNgIIIAooAgAgCWtBAU0EQCADIAlBAhARIAMoAgghCQsgAygCACAJakGi9AA7AAAgAyAJQQJqNgIIAkAgDUUEQCACQdABaiADEJgBDAELIAJB0AFqIAMgDSAPEJcBCwJAAkACQAJAIAIoAtABRQRAIAJB0AFqIAJBmAFqQYuEwABBByAIQSBqKQMAEBIgAigC0AENASACQdABaiACQZgBaiAIQQhrEBMgAigC0AENAiACQdABaiACQZgBakG0gcAAQQUgCEEEaigCACAIQQxqKAIAEBQgAigC0AENAyACQdABaiACQZgBakGShMAAQQUgCEEQaigCACAIQRhqKAIAEA8gAigC0AENBCACQcABaiACKAKYASACLQCcARCUAQwICyACQagBaiAFQQhqKAIAIgM2AgAgAiAFKQIAIhE3A6ABIAZBCGogAzYCACAGIBE3AgAMBAsgBiAFKQIANwIAIAZBCGogBUEIaigCADYCAAwDCyAGIAUpAgA3AgAgBkEIaiAFQQhqKAIANgIADAILIAYgBSkCADcCACAGQQhqIAVBCGooAgA2AgAMAQsgBiAFKQIANwIAIAZBCGogBUEIaigCADYCAAsgAkEBNgLAAQwCCyACQcABaiACKAKgASACLQCkARCUAQwBCyACQcABaiACKAKgASACLQCkARCUAQsgAigCwAFFBEAgBCgCCCIDIAcoAgBHDQQMAwsgAkGQAWogBkEIaigCADYCACACIAYpAgA3A4gBDAQLIAYgBSkCADcCACAGQQhqIAVBCGooAgA2AgAgAkEBNgLAAQsgAigCwAFFBEAgBCgCCCIDIAcoAgBGDQEMAgsgAkGQAWogBkEIaigCADYCACACIAYpAgA3A4gBDAILIAQgAxAQIAQoAgghAwsgBCgCACADakH9ADoAACAEIANBAWoiAzYCCCAMQdAAaikDACERIAxByABqKQMAIRIgAyAHKAIARw0BIAQgAxAQIAQoAgghAwwBCyACQbwBaiACQZABaigCADYCACACIAIpA4gBNwK0AQwLCyAEKAIAIANqQSw6AAAgBCADQQFqIgM2AgggBygCACADRgRAIAQgAxAQIAQoAgghAwsgBCgCACADakEiOgAAIAQgA0EBaiIDNgIIIAcoAgAgA2tBCE0EQCAEIANBCRARIAQoAgghAwsgBCgCACADaiIJQaSEwAApAAA3AAAgCUEIakGshMAALQAAOgAAIAQgA0EJaiIDNgIIIAcoAgAgA2tBAU0EQCAEIANBAhARIAQoAgghAwsgBCgCACADakGi9AA7AAAgBCADQQJqNgIIAkAgElAEQCACQdABaiAEEJgBDAELIAJB0AFqIAQgERCWAQsgAigC0AENAiAMQdgAai0AACEJIAQoAggiAyAHKAIARgRAIAQgAxAQIAQoAgghAwsgBCgCACADakEsOgAAIAQgA0EBaiIDNgIIIAcoAgAgA0YEQCAEIAMQECAEKAIIIQMLIAQoAgAgA2pBIjoAACAEIANBAWoiAzYCCCAHKAIAIANrQQdNBEAgBCADQQgQESAEKAIIIQMLIAQoAgAgA2pC8srB45bv17fuADcAACAEIANBCGoiAzYCCCAHKAIAIANrQQFNBEAgBCADQQIQESAEKAIIIQMLIAQoAgAgA2pBovQAOwAAIAQgA0ECajYCCAJAAkACQAJAAkAgCUEBaw4DAQIDAAsgAkHQAWogBEHFhMAAQQYQmQEMAwsgAkHQAWogBEHAhMAAQQUQmQEMAgsgAkHQAWogBEG5hMAAQQcQmQEMAQsgAkHQAWogBEG0hMAAQQUQmQELIAIoAtABBEAgAkG8AWogAkHcAWooAgA2AgAgAiACKQLUATcCtAEMCwsgAkGwAWogBEEAEJMBIAIoArABDQogCEHgAGohCEEBIQMgDEHgAGogDkcNAAtBAAUgAwtB/wFxQQBHEJIBIAIoAlgNCSACQdABaiACQUBrIAFBDGooAgAgAUEUaigCABAgIAIoAtABBEAgAkE8aiACQdwBaigCADYCACACIAIpAtQBNwI0DAsLIAFBIGooAgAhBiABQRhqKAIAIQcgAigCQCEEIAItAEQEQCAEKAIIIQMMAgsgBCgCCCIFIAQoAgRGBEAgBCAFEBAgBCgCCCEFCyAEIAVBAWoiAzYCCCAEKAIAIAVqQSw6AAAMAQsgAkG8AWogAkHcAWooAgA2AgAgAiACKQLUATcCtAEMBwsgAkEAOgBEIARBBGoiBSgCACADRgRAIAQgAxAQIAQoAgghAwsgBCgCACADakEiOgAAIAQgA0EBaiIDNgIIIAUoAgAgA2tBBU0EQCAEIANBBhARIAQoAgghAwsgBCgCACADaiIFQf6EwAAoAAA2AAAgBUEEakGChcAALwAAOwAAIAQgA0EGaiIDNgIIIARBBGooAgAgA2tBAU0EQCAEIANBAhARIAQoAgghAwsgBCgCACADakGi9AA7AAAgBCADQQJqNgIIIAJB0AFqIAQQmgEgAigC0AENAiACQdgBai0AACEDAkACQAJAIAJBsAFqIAIoAtQBIgUgBgR/IAcgBkEYbGohCCADRSEDIAJB0AFqQQRyIQYDQCADQQFxBEAgBSgCCCIDIAUoAgRGBEAgBSADEBAgBSgCCCEDCyAFIANBAWo2AgggBSgCACADakEsOgAACyACQdABaiAFEJsBIAIoAtABDQIgAiACLQDYAToAjAEgAiACKALUATYCiAEgAkHQAWogAkGIAWpB14TAAEEEIAcoAgAgB0EIaigCABAPIAIoAtABDQYgAkHQAWogAkGIAWogB0EMaigCACAHQRRqKAIAECAgAigC0AEEQCACQcwBaiACQdwBaigCADYCACACIAIpAtQBNwLEAQwJCyACQcABaiACKAKIASACLQCMARCTASACKALAAQ0IQQEhAyAHQRhqIgcgCEcNAAtBAAUgAwtB/wFxQQBHEJIBIAIoArABDQcgBCgCCCIHIARBBGoiAygCAEYEQCAEIAcQECAEKAIIIQcLIAQoAgAgB2pBLDoAACAEIAdBAWoiBzYCCCACQQA6AEQgAygCACAHRgRAIAQgBxAQIAQoAgghBwsgBCgCACAHakEiOgAAIAQgB0EBaiIHNgIIIAFBJGohAyAEQQRqIgUoAgAgB2tBA00EQCAEIAdBBBARIAQoAgghBwsgBCgCACAHakHkwtGLBjYAACAEIAdBBGoiATYCCCAFKAIAIAFrQQFNBEAgBCABQQIQESAEKAIIIQELIAQoAgAgAWpBovQAOwAAIAQgAUECajYCCCADKAIADQEgAkHQAWogBBCYAQwCCyACQcwBaiAGQQhqKAIANgIAIAIgBikCADcCxAEMBQsgAkHAAWogAxBqIAJB0AFqIAQgAigCwAEiASACKALIARCXASACKALEAUUNACABEKsBCyACKALQAQRAIAJBPGogAkHcAWooAgA2AgAgAiACKQLUATcCNAwJCyACQTBqIARBABCTASACKAIwDQggAigCCCIDIAIoAgRGBEAgAiADEBAgAigCCCEDCyACKAIAIANqQf0AOgAAIAIgA0EBajYCCAsgAkHIAWogAkEIaigCACIBNgIAIAIgAikDACIRNwPAASAAQQxqIAE2AgAgACARNwIEIABBDTYCAAwJCyACQcwBaiACQdwBaigCADYCACACIAIpAtQBNwLEAQwBCyACQbwBaiACQdwBaigCADYCACACIAIpAtQBNwK0AQwBCyACQbwBaiACQcwBaigCADYCACACIAIpAsQBNwK0AQsgAkE8aiACQbwBaigCADYCACACIAIpArQBNwI0DAMLIAJB5ABqIAJB3AFqKAIANgIAIAIgAikC1AE3AlwMAQsgAkHkAGogAkG8AWooAgA2AgAgAiACKQK0ATcCXAsgAkE8aiACQeQAaigCADYCACACIAIpAlw3AjQLIAJBHGogAkE8aigCADYCACACIAIpAjQ3AhQLIAJByAFqIgEgAkEcaigCADYCACACIAIpAhQ3A8ABIAIoAgQEQCACKAIAEKsBCyACQdgBaiABKAIANgIAIAIgAikDwAE3A9ABIABBuYfAAEHhACACQdABahAhCyACQeABaiQAC+ACAgJ/AX4jAEEgayIFJAAgASgCCCIEIAEoAgRGBEAgASAEEBAgASgCCCEECyABIARBAWo2AgggASgCACAEakH7ADoAACAFQRBqIAFBwITAAEEFEJcBAkACQCAFKAIQRQRAIAEoAggiBCABKAIERgRAIAEgBBAQIAEoAgghBAsgASAEQQFqNgIIIAEoAgAgBGpBOjoAACAFQRBqIAEgAiADEJcBIAUoAhANASABKAIIIgQgASgCBEYEQCABIAQQECABKAIIIQQLIABBADYCACABIARBAWo2AgggASgCACAEakH9ADoAAAwCCyAFQQhqIAVBHGooAgAiATYCACAFIAUpAhQiBjcDACAAQQxqIAE2AgAgACAGNwIEIABBATYCAAwBCyAFQQhqIAVBHGooAgAiATYCACAFIAUpAhQiBjcDACAAQQxqIAE2AgAgACAGNwIEIABBATYCAAsgBUEgaiQAC9QGAgR/AX4jAEHgAGsiBCQAIAEoAgAhBgJAIAEtAAQEQCAGKAIIIQUMAQsgBigCCCIHIAYoAgRGBEAgBiAHEBAgBigCCCEHCyAGIAdBAWoiBTYCCCAGKAIAIAdqQSw6AAALIAFBADoABCAGQQRqIgEoAgAgBUYEQCAGIAUQECAGKAIIIQULIAYoAgAgBWpBIjoAACAGIAVB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QT9xQYABcjoADyACIAFBBnZBP3FBgAFyOgAOIAIgAUEMdkE/cUGAAXI6AA0gAiABQRJ2QQdxQfABcjoADEEEDAELIAIgAUE/cUGAAXI6AA4gAiABQQx2QeABcjoADCACIAFBBnZBP3FBgAFyOgANQQMLIQEgASAAQQRqKAIAIAAoAggiA2tLBEAgACADIAEQESAAKAIIIQMLIAAoAgAgA2ogAkEMaiABEIsCGiAAIAEgA2o2AggLIAJBEGokAEEAC1oBAX8jAEEgayICJAAgAiAAKAIANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpB9InAACACQQhqEN4BIAJBIGokAAtKAQF/IAIgACgCACIAQQRqKAIAIAAoAggiA2tLBEAgACADIAIQESAAKAIIIQMLIAAoAgAgA2ogASACEIsCGiAAIAIgA2o2AghBAAvGBAICfwF+IwBBsAFrIgIkACACQQhqIAFBDGopAgA3AwAgAkEQaiABQRRqKQIANwMAIAJBGGogAUEcaikCADcDACACQSBqIAFBJGooAgA2AgAgAiABKQIENwMAAkACQCABKAIAIgMEQCABKQMoIQQgACADNgIAIAAgBDcCKCAAIAFBBGoiASkCADcCBCAAQQxqIAFBCGopAgA3AgAgAEEUaiABQRBqKQIANwIAIABBHGogAUEYaikCADcCACAAQSRqIAFBIGooAgA2AgAMAQsgAkFAayACQRxqKQIANwMAIAJBOGogAkEUaikCADcDACACQTBqIAJBDGopAgA3AwAgAiACKQIENwMoIAJBADYCUCACQgE3A0ggAkHYAGogAkHIAGpBqIXAABDyASACKAIoQQ1GBEAgAkGkAWpBADYCACACQYyKwAA2AqABIAJCATcClAEgAkGEjcAANgKQASACQdgAaiACQZABahD3AQ0CIAAgAikDSDcCBCAAQQA2AgAgAEEMaiACQdAAaigCADYCAAwBCyACQaQBakEBNgIAIAJCATcClAEgAkGMjcAANgKQASACQQM2AoQBIAIgAkGAAWo2AqABIAIgAkGMAWo2AoABIAIgAkEoajYCjAEgAkHYAGogAkGQAWoQ9wENASACKAIoIABBDGogAkHQAGooAgA2AgAgACACKQNINwIEIABBADYCAEENRg0AIAJB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yAFBDUcNASADKALMASEBCyADQfQCakH0gMAANgIAIANB7AJqQciAwAA2AgAgA0HkAmpBrIDAADYCACADQbACaiADQcABaikDADcDACADQcgCaiADQbABaikDADcDACADQYwDaiAGNgIAIANBiANqIA02AgAgA0GEA2ogCDYCACADQYADaiATNgIAIANB/AJqIA82AgAgA0HwAmogA0GYA2oiADYCACADQegCaiAANgIAIAMgAykDuAE3A6gCIAMgCjYCvAIgAyAJNgK4AiADIAMpA6gBNwPAAiADIAE2ApADIAMgEDYC+AIgAyAWNwPYAiADIAw2AtQCIAMgCzYC0AIgAyAANgLgAiADQegBaiINIQIgA0GoAmohB0EAIQojAEHgAWsiACQAIAAgATYCDCAAQfAAaiADQfgCaiIEENEBIABBHGogAEH4AGooAgA2AgAgACABNgIQIAAgACkDcDcCFCADQeACaiIBKAIEIQsgASgCACEMAkACQAJAAkACQAJAAkACQAJAQRRBARA9IgEEQCABQRBqQd2MwAAoAAA2AAAgAUEIakHVjMAAKQAANwAAIAFBzYzAACkAADcAAEEFQQEQPSIFRQ0IIAVBBGpB5YzAAC0AADoAACAFQeGMwAAoAAA2AAAgAEGwAWoiBhCVASAAQUBrIAYQmwEgACgCQA0BIAAgACgCRDYCwAEgACAAQcgAai0AADoAxAEgAEFAayAAQcABakGUgcAAQQggAUEUEA8gACgCQA0CIABBQGsgAEHAAWpBk4XAAEEHIAVBBRAPIAAoAkAEQCAAQdQBaiAAQcwAaigCADYCACAAIAApAkQ3AswBDAULIABByAFqIAAoAsABIAAtAMQBEJMBIAAoAsgBRQ0DDAQLQRRBARDOAQALIABB1AFqIABBzABqKAIANgIAIAAgACkCRDcCzAEMAgsgAEHUAWogAEHMAGooAgA2AgAgACAAKQJENwLMAQwBCyAAQfwAaiAAQbgBaigCADYCACAAIAApA7ABNwJ0DAELIABBqAFqIgYgAEHUAWooAgA2AgAgACAAKQLMATcDoAEgACgCtAEEQCAAKAKwARCrAQsgAEHIAGogBigCADYCACAAIAApA6ABNwNAIABB8ABqQd2JwABBFCAAQUBrECEgACgCcCIGQQ1HDQELIABB+ABqKAIAIQhBDSEGIAxBmoXAAEENIAAoAnQiCSAAQfwAaigCACALKAIUEQcAIAhFDQEgCRCrAQwBCyAAQThqIABBiAFqKQMANwMAIAAgACkDgAE3AzAgACgCfCEIIAAoAnghCSAAKAJ0IQoLIAEQqwEgBRCrAQJAAkACQAJAAkACQCAGQQ1GBEAgAEHwAGogDCALIABBEGoQJiAAKAJwIgFBDUYNAiAAQdgAaiAAQYwBaigCACIFNgIAIABB0ABqIABBhAFqKQIAIhU3AwAgAEHIAGogAEH8AGopAgAiFjcDACAAIAApAnQiFzcDQCACQSRqIAU2AgAgAkEcaiAVNwIAIAJBFGogFjcCACACQQxqIBc3AgAgAiABNgIIDAELIABBKGogAEE4aikDACIVNwMAIAAgACkDMCIWNwMgIAJBIGogFTcCACACQRhqIBY3AgAgAkEUaiAINgIAIAJBEGogCTYCACACQQxqIAo2AgAgAiAGNgIICyACQQA2AgAgAEEYaigCAARAIAAoAhQQqwELIARBBGooAgAEQCAEKAIAEKsBCyAEQRRqKAIAIgEEQCABQQV0IQEgBEEMaigCAEEQaiECA0AgAkEEaigCAARAIAIoAgAQqwELIAJBIGohAiABQSBrIgENAAsLIARBEGooAgAEQCAEKAIMEKsBCyAHQRRqKAIABEAgBygCEBCrAQsgB0EsaigCAA0BDAILIABBkAFqQgA3AwAgAEGAAWpCADcDACAAQgQ3A4gBIABCgICAgMAANwN4IABCCDcDcCAAQUBrIABB8ABqQeaMwABBgITAAEELECIgAEE4aiIFIARBCGooAgA2AgAgACAEKQIANwMwQQVBARA9IgFFDQQgAUEEakHwjMAALQAAOgAAIAFB7IzAACgAADYAACAAQfgAaiAFKAIANgIAIAAgACkDMDcDcCAAQdQBaiIFIABB8ABqIgYpAgA3AgAgBUEIaiAGQQhqKAIANgIAIABChYCAgNAANwLMASAAIAE2AsgBIABB1ABqKAIAIgEgAEHQAGooAgBGBEAgAEHMAGogARAjIAAoAlQhAQsgACgCTCABQRhsaiIFIAApA8gBNwIAIAVBCGogAEHQAWopAwA3AgAgBUEQaiAAQdgBaikDADcCACAAQfgAaiAAQcgAaikDADcDACAAQYgBaiAAQdgAaikDADcDACAAQZABaiAAQeAAaikDADcDACAAQZgBaiAAQegAaikDADcDACAAIAFBAWo2AlQgAEGAAWogAEHQAGopAwA3AwAgACAAKQNANwNwIABBADYC0AEgAEIBNwPIASAAQUBrIgUgAEHIAWpBqIXAABDyASAAQQxqKAIAIgGtQgAgAax9IAFBf0oiARsgASAFEIUCDQJBBUEBED0iBUUNAyAFQQRqQfWMwAAtAAA6AAAgBUHxjMAAKAAANgAAIABBhAFqKAIAIgEgAEGAAWoiCCgCAEYEQCAAQfwAaiABECMgACgChAEhAQsgACgCfCABQRhsaiIGQoWAgIDQADcCBCAGIAU2AgAgAiAAKQNwNwIAIAJBCGogAEH4AGopAwA3AgAgAkEYaiAAQYgBaikDADcCACACQSBqIABBkAFqKQMANwIAIAJBKGogAEGYAWopAwA3AgAgACABQQFqNgKEASACQRBqIAgpAwA3AgAgBiAAKQPIATcCDCAGQRRqIABB0AFqKAIANgIAIABBGGooAgAEQCAAKAIUEKsBCyAEQRRqKAIAIgEEQCABQQV0IQEgBEEMaigCAEEQaiECA0AgAkEEaigCAARAIAIoAgAQqwELIAJBIGohAiABQSBrIgENAAsLIARBEGooAgAEQCAEKAIMEKsBCyAHQRRqKAIABEAgBygCEBCrAQsgB0EsaigCAEUNAQsgBygCKBCrAQsgAEHgAWokAAwDC0HAhcAAQTcgAEEwakH4hcAAQdSGwAAQ6QEACwtBBUEBEM4BAAsgA0HIAGogDRAzIAMoApwBBEAgFBCrAQsgAygCjAEEQCASEKsBCyADKAJ8RQ0DIA4QqwEMAwsgA0GAAmogA0HgAWopAwA3AwAgA0H4AWogA0HYAWopAwA3AwAgA0HwAWogA0HQAWopAwA3AwAgAyADKQPIATcD6AEgA0EANgKgAiADQgE3A5gCIANBqAJqIgAgA0GYAmpBqIXAABDyASADQegBaiAAEH1FBEAgA0HUAGogA0GgAmooAgA2AgAgAyADKQOYAjcCTCADQQA2AkggA0HoAWoQLiAPBEAgEBCrAQsgBgRAIAZBBXQhASAIQRBqIQADQCAAQQRqKAIABEAgACgCABCrAQsgAEEgaiEAIAFBIGsiAQ0ACwsgDUUNASAIEKsBDAELDAMLIAoEQCAJEKsBCyAMRQ0AIAsQqwELIAMoApwBBEAgAygCmAEQqwELIAMoAowBBEAgAygCiAEQqwELIAMoAnxFDQAgDhCrAQsgA0HoAWogA0HIAGoQHiADKALoAUENRgRAIANB0AFqIANB9AFqKAIAIgA2AgAgAyADKQLsASIVNwPIASADQbACaiAANgIAIAMgFTcDqAIgA0GoAmoQfiADQcgAahArIANBoANqJAAPCyADQcACaiADQYACaikDADcDACADQbgCaiADQfgBaikDADcDACADQbACaiADQfABaikDADcDACADIAMpA+gBNwOoAkHFgcAAQSsgA0GoAmpB8IHAAEH0gsAAEOkBAAtBwIXAAEE3IANBmANqQfiFwABB1IbAABDpAQALnSoCE38CfiMAQdADayIDJAAQrQEgA0GoAWogABB/IANBuAFqIAEQfyADQcgBaiACEH8gA0HYAmogAygCqAEiEyADKAKwARAVAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJ/AkACfwJAAkACQAJAAkACQAJAAkACQAJAIAMoAvgCQQJHBEAgA0HwAWogA0HgAmopAwA3AwAgA0HgAWogA0H4AmopAwA3AwAgAyADKQPYAjcD6AEgAyADKQPwAjcD2AEgAygC6AIhESADKALsAiEOIAMoAoADIQ8gAygChAMhEiADKQOIAyEWIANB+AFqIAMoArgBIhQgAygCwAEQHCADKAL4AUENRw0CIANBkAJqKAIAIQwgA0GMAmooAgAhCiADQYgCaigCACEJIANBhAJqKAIAIQIgA0GAAmooAgAhDSADKAL8ASEQIANByAJqIgAgAygCyAEiFSADKALQARCJASADQfAAaiAAEJABIAMtAHBBAXENAQwUCyADQZACaiADQfACaikDADcDACADQYgCaiADQegCaikDADcDACADQYACaiADQeACaikDADcDACADIAMpA9gCNwP4ASADQQA2AtACIANCATcDyAIgA0GYAmoiACADQcgCakGohcAAEPIBIANB+AFqIAAQfQ0aIANBhAFqIANB0AJqKAIANgIAIAMgAykDyAI3AnwgA0EANgJ4IANB+AFqEC4MGAsgAy0AcSIAQfsARwRAIABBIkcEQEEKIQAMFQsgA0HYAmogA0HIAmoQOCADKALYAiIAQRVHDQ9BDiEADBQLIANByAJqIgQQigEgA0HYAmogBBA4AkACfyAD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AEEiRw0GIANBCGogBRCQAUEEIQAgAy0ACEEBcUUNB0EOIQAgAy0ACUEiRw0HIAUQigEgA0HYAmogBRCPASADKALYAiIAQRVHDQEgA0HkAmooAgAhByADQeACaigCACEAIAMoAtwCIgVFBEAgA0GYAmogACAHQYyKwABBABA2DAMLIANBmAJqIAUgB0GMisAAQQAQNiAARQ0CIAUQqwEMAgtBEyEADAYLIAMgAygC5AI2AqQCIAMgAykC3AI3ApwCIAMgADYCmAILIAMoApgCIgBBFUYNACADLwCdAiADLQCfAkEQdHIhByADKQOgAiEXIAMtAJwCIQUMBAsgA0HYAmogBBCNASADKALYAiIAQRVHBEAgAygC3AIiAUEIdiEHIAMoAuQCIQUgAygC4AIhBgwFCyADIAQQkAEgAy0AAEEBcUUNBUELIQAgAy0AAUH9AEcNBgsgBBCKASADQdgCaiADQcgCahCLASADKALYAiIAQRVGDQYLIAMoAuQCIQUgAygC4AIhBiADKALcAiEHDAQLQRAhAAsgBUH/AXEhASAXQiCIpyEFIBenIQYLIAFB/wFxIAdBCHRyIQcMAQtBBCEAQQAhBwsgAyAFNgLkAiADIAY2AuACIAMgBzYC3AIgAyAANgLYAiADQfgBakHkhsAAQRsgA0HYAmoQGyADKAL4AUENRw0BIANBgAJqKAIAIQEgAygC/AEhCAsgA0GkA2pB9IDAADYCACADQZwDakHIgMAANgIAIANBlANqQayAwAA2AgAgA0HgAmogA0HwAWopAwA3AwAgA0H4AmogA0HgAWopAwA3AwAgA0HEA2ogATYCACADQbwDaiAMNgIAIANBuANqIAo2AgAgA0G0A2ogCTYCACADQbADaiACNgIAIANBrANqIA02AgAgA0GgA2ogA0HIA2oiADYCACADQZgDaiAANgIAIAMgAykD6AE3A9gCIAMgDjYC7AIgAyARNgLoAiADIAMpA9gBNwPwAiADIAg2AsADIAMgEDYCqAMgAyAWNwOIAyADIBI2AoQDIAMgDzYCgAMgAyAANgKQAyADQZgCaiISIQogA0GQA2ohACADQdgCaiERIANBqANqIQkgASECIwBBMGsiCyQAAkAgCEUEQCALQShqIABBEGopAgA3AwAgC0EgaiAAQQhqKQIANwMAIAsgACkCADcDGCMAQeAAayIEJAAgBEEgaiALQRhqIgAoAgAiECAAKAIEIgJBDGooAgAQJAJAAkACQAJAIAQoAiAiDUENRgRAIAQoAiQiAUEBaiIAIAFIDQMgBEEsaigCACEOIARBKGooAgAhDyAEIARBMGooAgA2AlwgBCAONgJYIAQgDzYCVCAEIAA2AlAgBEEgaiAQIAIgBEHQAGoQJiAEKAIgIg1BDUcEQCAEQRhqIARBPGooAgA2AgAgBCAEKQI0NwMQIAQoAjAhAiAEKAIsIQEgBCgCKCEIIAQoAiQhDCAORQ0CIA8QqwEMAgsgDgRAIA8QqwELIARBQGtCADcDACAEQTBqQgA3AwAgBEIENwM4IARCgICAgMAANwMoIARCCDcDICAKIARBIGpBmIzAAEGejMAAQQkQIgwCCyAEQRhqIARBPGooAgA2AgAgBCAEKQI0NwMQIAQoAjAhAiAEKAIsIQEgBCgCKCEIIAQoAiQhDAsgBEEIaiAEQRhqKAIAIgA2AgAgBCAEKQMQIhY3AwAgCkEkaiAANgIAIApBHGogFjcCACAKQRhqIAI2AgAgCkEUaiABNgIAIApBEGogCDYCACAKQQxqIAw2AgAgCiANNgIIIApBADYCAAsgBEHgAGokAAwBC0GAgMAAQRxBuIzAABDZAQALIAlBBGooAgAEQCAJKAIAEKsBCyAJQQxqKAIAIQIgCUEUaigCACIABEAgAEEFdCEAIAJBEGohAQNAIAFBBGooAgAEQCABKAIAEKsBCyABQSBqIQEgAEEgayIADQALCyAJQRBqKAIARQ0BIAIQqwEMAQsgC0EQaiAAQRBqKQIANwMAIAtBCGogAEEIaikCADcDACALIAApAgA3AwAgC0EoaiAJQRBqKQIANwMAIAtBIGogCUEIaikCADcDACALIAkpAgA3AxgjAEHgAGsiBCQAIAtBGGoiCUEIaigCACEOIAkoAgAhDyAEQSBqIAsoAgAiDSALKAIEIgFBDGooAgAQJAJAAkACQAJAIAQoAiAiCEENRgRAIARBLGooAgAhECAEQShqKAIAIQACQCAOIARBMGooAgAiDEYEQCAPIAAgDhCNAkUNAQtBDSEIIBAEQCAQIQ0gACEBDAMLQQAhDSAAIQEMAwsgBCAONgJcIAQgEDYCWCAEIAA2AlQgBCACNgJQIARBIGogDSABIARB0ABqECYgBCgCICIIQQ1HBEAgBEEYaiAEQTxqKAIANgIAIAQgBCkCNDcDECAEKAIwIQwgBCgCLCENIAQoAighASAEKAIkIQIgEA0CDAMLIBAEQCAAEKsBCyAEQUBrQgA3AwAgBEEwakIANwMAIARCBDcDOCAEQoCAgIDAADcDKCAEQgg3AyAgCiAEQSBqQZiMwABByIzAAEEFECIgCUEEaigCAARAIA8QqwELIAlBDGooAgAhDCAJQRRqKAIAIgAEQCAAQQV0IQggDEEQaiEAA0AgAEEEaigCAARAIAAoAgAQqwELIABBIGohACAIQSBrIggNAAsLIAlBEGooAgANAwwECyAEQRhqIARBPGooAgA2AgAgBCAEKQI0NwMQIAQoAjAhDCAEKAIsIQ0gBCgCKCEBIAQoAiQhAgwBCyAAEKsBCyAEQQhqIARBGGooAgAiADYCACAEIAQpAxAiFjcDACAKQSRqIAA2AgAgCkEcaiAWNwIAIApBGGogDDYCACAKQRRqIA02AgAgCkEQaiABNgIAIApBDGogAjYCACAKIAg2AgggCkEANgIAIAlBBGooAgAEQCAPEKsBCyAJQQxqKAIAIQwgCUEUaigCACIABEAgAEEFdCEIIAxBEGohAANAIABBBGooAgAEQCAAKAIAEKsBCyAAQSBqIQAgCEEgayIIDQALCyAJQRBqKAIARQ0BCyAMEKsBCyAEQeAAaiQACyARQRRqKAIABEAgESgCEBCrAQsgEUEsaigCAARAIBEoAigQqwELIAtBMGokACADQfgAaiASEDMgAygCzAEEQCAVEKsBCyADKAK8AQRAIBQQqwELIAMoAqwBRQ0DIBMQqwEMAwsgA0GwAmogA0GQAmopAwA3AwAgA0GoAmogA0GIAmopAwA3AwAgA0GgAmogA0GAAmopAwA3AwAgAyADKQP4ATcDmAIgA0EANgLQAiADQgE3A8gCIANB2AJqIgAgA0HIAmpBqIXAABDyASADQZgCaiAAEH1FBEAgA0GEAWogA0HQAmooAgA2AgAgAyADKQPIAjcCfCADQQA2AnggA0GYAmoQLiANBEAgEBCrAQsgDARAIAxBBXQhASAJQRBqIQADQCAAQQRqKAIABEAgACgCABCrAQsgAEEgaiEAIAFBIGsiAQ0ACwsgCkUNASAJEKsBDAELDAMLIA4EQCAREKsBCyASRQ0AIA8QqwELIAMoAswBBEAgAygCyAEQqwELIAMoArwBBEAgAygCuAEQqwELIAMoAqwBRQ0AIBMQqwELIANBmAJqIANB+ABqEB4gAygCmAJBDUYEQCADQYACaiADQaQCaigCACIANgIAIAMgAykCnAIiFjcD+AEgA0HgAmogADYCACADIBY3A9gCIANB2AJqEH4gA0H4AGoQKyADQdADaiQADwsgA0HwAmogA0GwAmopAwA3AwAgA0HoAmogA0GoAmopAwA3AwAgA0HgAmogA0GgAmopAwA3AwAgAyADKQOYAjcD2AJBxYHAAEErIANB2AJqQfCBwABB5ILAABDpAQALQcCFwABBNyADQcgDakH4hcAAQdSGwAAQ6QEAC+kZAgx/A34jAEHAAmsiAiQAEK0BIAJB0ABqIAAQfyACQZgCaiABEH8gAkHIAWogAigCUCIHIAIoAlgQFQJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCACKALoAUECRwRAIAJB+ABqIAJB0AFqKQMANwMAIAJB6ABqIAJB6AFqKQMANwMAIAIgAikDyAE3A3AgAiACKQPgATcDYCACKALYASEEIAIoAtwBIQYgAigC8AEhCCACKAL0ASEJIAIpA/gBIQ8gAkFAayIAIAIoApgCIgwgAigCoAIQiQEgAkE4aiAAEJABIAItADhBAXFFDQMCQCACLQA5IgBB+wBHBEAgAEEiRwRAQQohAQwHCyACQcgBaiACQUBrEDkgAigCyAEiAUEVRw0BQQ4hAQwGCyACQUBrIgMQigEgAkHIAWogAxA5IAIoAsgBIgFBFUcNACACQcgBaiADEI4BIAIoAsgBIgFBFUcNACACQTBqIAMQkAFBBCEBIAItADBBAXFFDQMgAi0AMUH7AEcEQEEOIQEMBAsgAxCKASACQShqIAMQiAEgAi0ALCACQSBqIAIoAigiBRCQASACLQAgQQFxRQRAQQIhAQwEC0EBcSEKAkACQCACLQAhIgAiDUEsRwRAIA1B/QBGDQIgCg0BQQkhAQwGCyAKDQQgBRCKASACQRhqIAUQkAEgAi0AGEEBcUUNBSACLQAZIQALAkACQCAAQf0ARwRAIABBIkcNBiACQRBqIAUQkAEgAi0AEEEBcUUNB0EOIQEgAi0AEUEiRw0HIAUQigEgAkHIAWogBRCPASACKALIASIAQRVHDQEgAkHUAWooAgAhACACQdABaigCACEBIAIoAswBIgVFBEAgAkGgAWogASAAQYyKwABBABA2DAMLIAJBoAFqIAUgAEGMisAAQQAQNiABRQ0CIAUQqwEMAgtBEyEBDAYLIAIgAigC1AE2AqwBIAIgAikCzAE3AqQBIAIgADYCoAELIAIoAqABIgFBFUYNACACLwClASACLQCnAUEQdHIhCyACKQOoASEOIAItAKQBIQMMBAsgAkHIAWogAxCNASACKALIASIBQRVHBEAgAi8AzQEgAi0AzwFBEHRyIQsgAikD0AEhDiACLQDMASEDDAQLIAJBCGogAxCQASACLQAIQQFxRQ0EIAItAAlB/QBHBEBBCyEBDAYLIAMQigEgAkHIAWogAkFAaxCLASACKALIASIBQRVGDQYLIAIpA9ABIQ4gAigCzAEhAwwECyACQZgBaiACQeABaikDADcDACACQZABaiACQdgBaikDADcDACACQYgBaiACQdABaikDADcDACACIAIpA8gBNwOAASACQQA2ArACIAJCATcDqAIgAkGgAWoiACACQagCakGohcAAEPIBIAJBgAFqIAAQfUUEQCACQcwAaiACQbACaigCADYCACACIAIpA6gCNwJEIAJBATYCQCACQYABahAuDAkLDA4LQRAhAQsgA0H/AXEgC0EIdHIhAwwBC0EEIQFBACEDCyACIA43A9ABIAIgAzYCzAEgAiABNgLIASACQYABakGgh8AAQRkgAkHIAWoQGyACKAKAAUENRw0BCyACQZQCakH0gMAANgIAIAJBjAJqQciAwAA2AgAgAkGEAmpBrIDAADYCACACQdABaiACQfgAaikDADcDACACQegBaiACQegAaikDADcDACACQZACaiACQbgCaiIANgIAIAJBiAJqIAA2AgAgAiACKQNwNwPIASACIAY2AtwBIAIgBDYC2AEgAiACKQNgNwPgASACIA83A/gBIAIgCTYC9AEgAiAINgLwASACIAA2AoACIAJBgAFqIgUhASACQcgBaiEDIwBB8ABrIgAkACAAQRhqIAJBgAJqIgQoAgAgBCgCBEEMaigCABAkAkACQAJAAkACQAJAAkAgACgCGCIEQQ1GBEAgACgCHCEEIABBJGooAgAEQCAAQSBqKAIAEKsBCyAAQcgAaiIGEJUBIABBGGogBhCbASAAKAIYDQEgACAAKAIcNgJoIAAgAEEgai0AADoAbCAAQRhqIABB6ABqIAQQJyAAKAIYBEAgAEHkAGogAEEkaigCADYCACAAIAApAhw3AlwMBAsgAEHYAGogACgCaCAALQBsEJMBIAAoAlhFDQIMAwsgAEEQaiAAQTRqKAIAIgY2AgAgACAAKQIsIg43AwggACkCHCEPIAApAiQhECABQRxqIAY2AgAgASAONwIUIAEgEDcCDCABIA83AgQgASAENgIAIANBFGooAgAEQCADKAIQEKsBCyADQSxqKAIARQ0GIAMoAigQqwEMBgsgAEHkAGogAEEkaigCADYCACAAIAApAhw3AlwMAQsgAEEkaiAAQdAAaigCADYCACAAIAApA0g3AhwMAQsgAEFAayIEIABB5ABqKAIANgIAIAAgACkCXDcDOCAAKAJMBEAgACgCSBCrAQsgAEHgAGogBCgCADYCACAAIAApAzg3A1ggAEEYakH/hsAAQSEgAEHYAGoQISAAKAIYQQ1HDQELIAEgACkCHDcCBCABQQ02AgAgAUEMaiAAQSRqKAIANgIADAELIAEgACkDGDcDACABQRhqIABBMGopAwA3AwAgAUEQaiAAQShqKQMANwMAIAFBCGogAEEgaikDADcDAAsgA0EUaigCAARAIAMoAhAQqwELIANBLGooAgBFDQAgAygCKBCrAQsgAEHwAGokACAFQQRyIQACQCACKAKAASIBQQ1GBEAgAkHMAGogAEEIaigCADYCACACQQA2AkAgAiAAKQIANwJEDAELIAJBrAFqIABBCGooAgA2AgAgAkG4AWogAkGYAWopAwA3AwAgAiABNgKgASACIAIpA5ABNwOwASACIAApAgA3AqQBIAJBADYCsAIgAkIBNwOoAiACQcgBaiIAIAJBqAJqQaiFwAAQ8gEgAkGgAWogABB9DQogAkHMAGogAkGwAmooAgA2AgAgAiACKQOoAjcCRCACQQE2AkAgAkGgAWoQLgsgAigCnAIEQCAMEKsBCyACKAJUBEAgBxCrAQsgAkGoAmoQlQEgAUENRw0EIAIoArACIgAgAigCrAJGBEAgAkGoAmogABAQIAIoArACIQALIAIoAqgCIABqQfsAOgAAIAIgAEEBajYCsAIgAkHIAWogAkGoAmpBy4TAAEECEJcBIAIoAsgBDQIgAigCsAIiACACKAKsAkYEQCAC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KAIAIQIjAEEwayIAJAACfwJAAkACQAJAIAIoAgBBAWsOAwECAwALIABBHGpBADYCACAAQfSRwAA2AhggAEIBNwIMIABB5KjAADYCCCABIABBCGoQ9wEMAwsgAEEcakEANgIAIABB9JHAADYCGCAAQgE3AgwgAEHIqMAANgIIIAEgAEEIahD3AQwCCyAAQRxqQQA2AgAgAEH0kcAANgIYIABCATcCDCAAQaiowAA2AgggASAAQQhqEPcBDAELIABBHGpBATYCACAAQgE3AgwgAEHop8AANgIIIABBIDYCJCAAIAJBBGo2AiwgACAAQSBqNgIYIAAgAEEsajYCICABIABBCGoQ9wELIABBMGokAAu0AwEBfyAAKAIAIQIjAEEwayIAJAACfwJAAkACQAJAAkACQAJAIAIoAgBBAWsOBgECAwQFBgALIABBHGpBADYCACAAQfSRwAA2AhggAEIBNwIMIABB4LLAADYCCCABIABBCGoQ9wEMBgsgAEEcakEANgIAIABB9JHAADYCGCAAQgE3AgwgAEHMssAANgIIIAEgAEEIahD3AQwFCyAAQRxqQQA2AgAgAEH0kcAANgIYIABCATcCDCAAQeSowAA2AgggASAAQQhqEPcBDAQLIABBHGpBADYCACAAQfSRwAA2AhggAEIBNwIMIABByKjAADYCCCABIABBCGoQ9wEMAwsgAEEcakEANgIAIABB9JHAADYCGCAAQgE3AgwgAEG0ssAANgIIIAEgAEEIahD3AQwCCyAAQRxqQQA2AgAgAEH0kcAANgIYIABCATcCDCAAQaiowAA2AgggASAAQQhqEPcBDAELIABBHGpBATYCACAAQgE3AgwgAEHop8AANgIIIABBIDYCJCAAIAJBBGo2AiwgACAAQSBqNgIYIAAgAEEsajYCICABIABBCGoQ9wELIABBMGokAAsMACAAKAIAIAEQ3AELYgEBfyMAQTBrIgIkACAAKAIAIQAgAkEcakEBNgIAIAJCAjcCDCACQeSwwAA2AgggAkEeNgIkIAIgADYCLCACIAJBIGo2AhggAiACQSxqNgIgIAEgAkEIahD3ASACQTBqJAALVwEBfyMAQSBrIgIkACACIAA2AgQgAkEYaiABQRBqKQIANwMAIAJBEGogAUEIaikCADcDACACIAEpAgA3AwggAkEEakHckcAAIAJBCGoQ3gEgAkEgaiQACwgAIAEgARBUC5oEAQR/IwBBQGoiACQAIABBADYCCCAAQgE3AwAgAEEQaiIEIABBmI/AABDyAQJAIwBBQGoiAiQAQQEhAwJAIAQoAhgiBUGo38AAQQwgBEEcaigCACIEKAIMEQEADQACQCABKAIIIgMEQCACIAM2AgwgAkHnADYCFCACIAJBDGo2AhBBASEDIAJBATYCPCACQgI3AiwgAkG438AANgIoIAIgAkEQajYCOCAFIAQgAkEoahDeAUUNAQwCCyABKAIAIgMgASgCBEEMaigCABEIAELrkZO19tizovQAUg0AIAIgAzYCDCACQegANgIUIAIgAkEMajYCEEEBIQMgAkEBNgI8IAJCAjcCLCACQbjfwAA2AiggAiACQRBqNgI4IAUgBCACQShqEN4BDQELIAEoAgwhASACQSRqQcoANgIAIAJBHGpBygA2AgAgAiABQQxqNgIgIAIgAUEIajYCGCACQekANgIUIAIgATYCECACQQM2AjwgAkIDNwIsIAJBkN/AADYCKCACIAJBEGo2AjggBSAEIAJBKGoQ3gEhAwsgAkFAayQAIANFBEAgACgCCCECIAAoAgAhA0EMQQQQPSIBRQ0BIAEgAjYCCCABIAI2AgQgASADNgIAIAEQACABEKsBIAAoAgQEQCAAKAIAEKsBCyAAQUBrJAAPC0Gwj8AAQTcgAEE4akHoj8AAQcSQwAAQ6QEAC0EMQQQQzgEAC4cBAQV/IwBBIGsiAyQAAn8gAkUEQEEAIQJBAAwBCwJAA0AgA0EIaiABEFYgAygCCCIFRQ0BIAMoAhggAygCFCEHIAMoAgwEQCAFEKsBCyAEQQFqIQQEQCAHEKsBCyACIARHDQALQQAMAQsgBCECQQELIQEgACACNgIEIAAgATYCACADQSBqJAALiQMCCH8BfiMAQUBqIgIkAAJAIAEoAgAQBSIBBEAgASgCACIDRQ0BIAEpAgQhCiABEKsBIAIgCjcCNCACIAM2AjAgAkEYaiIEIAJBMGoiBRBsIAJBEGogAkEgaigCACIGNgIAIAIgAikDGCIKNwMIIAJBKGoiBygCACEBIAJBLGoiCCgCACEJIAIoAiQhAyACQThqIAY2AgAgAiAKNwMwIAQgBRBsIAgoAgAhBCAHKAIAIQUgAigCJCEGIAIoAhwEQCACKAIYEKsBCwJAIARFBEAgAEEANgIAIAEEQCADEKsBCyAFRQ0BIAYQqwEMAQsgACAJNgIUIAAgATYCECAAIAM2AgwgACAENgIIIAAgBTYCBCAAIAY2AgALIAJBQGskAA8LIAJBLGpBADYCACACQfSRwAA2AiggAkIBNwIcIAJBqKbAADYCGCACQRhqQZCnwAAQ1AEACyACQSxqQQA2AgAgAkH0kcAANgIoIAJCATcCHCACQcCnwAA2AhggAkEYakHIp8AAENQBAAt9AQV/IwBBIGsiAyQAAkAgAkUNAANAAkAgA0EIaiABEFYgAygCCCIERQ0AIAMoAhggAygCFCEGIAMoAgwEQCAEEKsBCwRAIAYQqwELIAJBAWsiAg0BDAILC0EBIQcLAkAgB0UEQCAAIAEQVgwBCyAAQQA2AgALIANBIGokAAsJACAAQgA3AgALDQAgACgCACABEFpBAAvNAgECfyMAQRBrIgIkAAJAAn8CQCABQYABTwRAIAJBADYCDCABQYAQTw0BIAIgAUE/cUGAAXI6AA0gAiABQQZ2QcABcjoADEECDAILIAAoAggiAyAAKAIERgRAIAAgAxAQIAAoAgghAwsgACADQQFqNgIIIAAoAgAgA2ogAToAAAwCCyABQYCABE8EQCACIAFBP3FBgAFyOgAPIAIgAUEGdkE/cUGAAXI6AA4gAiABQQx2QT9xQYABcjoADSACIAFBEnZBB3FB8AFyOgAMQQQMAQsgAiABQT9xQYABcjoADiACIAFBDHZB4AFyOgAMIAIgAUEGdkE/cUGAAXI6AA1BAwshASABIABBBGooAgAgACgCCCIDa0sEQCAAIAMgARARIAAoAgghAwsgACgCACADaiACQQxqIAEQiwIaIAAgASADajYCCAsgAkEQaiQAC1oBAX8jAEEgayICJAAgAiAAKAIANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpB3JHAACACQQhqEN4BIAJBIGokAAsKACAAIAEQWkEAC8UBAQF/IwBB8ABrIgMkACADIAI2AgwgAyABNgIIIANBJGpBATYCACADQgI3AhQgA0Ggk8AANgIQIANBITYCLCADIANBKGo2AiAgAyADQQhqNgIoIANBADYCOCADQgE3AzAgA0FAayIBIANBMGpBmI/AABDyASADQRBq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CCAEIAM2AgQgBCACNgIAQcAAQQEQPSIDRQ0EQQxBBBA9IgJFDQUgAkLAADcCBCACIAM2AgAgBCACEAciAw0BIAIoAgAiA0UNByACKQIEIQUgAhCrASAAQQhqIAU3AgAgACADNgIEIABBDTYCACAEEKsBDAILQSRBARA9IgJFDQUgAEKkgICAwAQ3AwggACACNgIEIABBAjYCACACQSBqQZijwAAoAAA2AAAgAkEYakGQo8AAKQAANwAAIAJBEGpBiKPAACkAADcAACACQQhqQYCjwAApAAA3AAAgAkH4osAAKQAANwAADAELIAMoAgAiAkUNBSADKQIEIQUgAxCrASABIAU3AgQgASACNgIAIAFBIjYCJCABIAE2AiAgAUEBNgI8IAFCATcCLCABQbijwAA2AiggASABQSBqNgI4IAFBEGogAUEoahDQASAAQQI2AgAgACABKQMQNwIEIABBDGogAUEYaigCADYCACABKAIEBEAgASgCABCrAQsgBBCrAQsgAUFAayQADwtBDEEEEM4BAAtBwABBARDOAQALQQxBBBDOAQALQSRBARDOAQALIAFBPGpBADYCACABQfSRwAA2AjggAUIBNwIsIAFBwKfAADYCKCABQShqQcinwAAQ1AEAC5kDAgJ/AX4jAEFAaiIBJAAgAkEIaigCACEDIAIoAgAhAgJAAkACQEEMQQQQPSIEBEAgBCADNgIIIAQgAzYCBCAEIAI2AgBB2gBBARA9IgNFDQFBDEEEED0iAkUNAiACQtoANwIEIAIgAzYCAAJAIAQgAhAIIgNFBEAgAigCACIDRQ0FIAIpAgQhBSACEKsBIABBCGogBTcCACAAIAM2AgQgAEENNgIADAELIAMoAgAiAkUNBCADKQIEIQUgAxCrASABIAU3AgQgASACNgIAIAFBIjYCJCABIAE2AiAgAUEBNgI8IAFCATcCLCABQdijwAA2AiggASABQSBqNgI4IAFBEGogAUEoahDQASAAQQI2AgAgACABKQMQNwIEIABBDGogAUEYaigCADYCACABKAIEBEAgASgCABCrAQsLIAQQqwEgAUFAayQADwtBDEEEEM4BAAtB2gBBARDOAQALQQxBBBDOAQALIAFBPGpBADYCACABQfSRwAA2AjggAUIBNwIsIAFBwKfAADYCKCABQShqQcinwAAQ1AEAC8cCAQF/IwBBIGsiASQAQQxBBBA9IggEQAJAIAggAzYCCCAIIAM2AgQgCCACNgIAQQxBBBA9IgJFDQAgAiAFNgIIIAIgBTYCBCACIAQ2AgBBDEEEED0iA0UNACADIAc2AgggAyAHNgIEIAMgBjYCAAJAAkACQAJAAkACQAJAAkACQCAIIAIgAxAJIgQOCwECAwQFBgAAAAAHAAsgACAENgIEIABBBjYCAAwHCyAAQQc2AgAgAEEBOgAEDAYLIABBBzYCACAAQQA6AAQMBQsgAUEcakEANgIAIAFB9JHAADYCGCABQgE3AgwgAUGYpMAANgIIIAFBCGpBoKTAABDUAQALIABBAjYCAAwDCyAAQQM2AgAMAgsgAEEENgIADAELIABBATYCAAsgAxCrASACEKsBIAgQqwEgAUEgaiQADwsLQQxBBBDOAQALrAMCAX8BfiMAQSBrIgEkAAJAAkACQEEMQQQQPSIHBEAgByADNgIIIAcgAzYCBCAHIAI2AgBBDEEEED0iAkUNASACIAU2AgggAiAFNgIEIAIgBDYCAAJAAkACQAJAAkACQAJAIAcgAiAGQf8BcRAKIghCIIinIgMOBwEAAgMEAAUACyAAQoCAgIAwNwIAIABBCGogAzYCAAwFCyAIpyIDRQ0HIAMoAgAiBEUNCCADKQIEIQggAxCrASAAIAg3AgQgACAENgIADAQLIAFBHGpBADYCACABQfSRwAA2AhggAUIBNwIMIAFBmKTAADYCCCABQQhqQbCkwAAQ1AEACyAAQgA3AgAMAgsgAEKAgICAEDcCAAwBCyAAQoCAgIAgNwIACyACEKsBIAcQqwEgAUEgaiQADwtBDEEEEM4BAAtBDEEEEM4BAAsgAUEcakEANgIAIAFB9JHAADYCGCABQgE3AgwgAUGopsAANgIIIAFBCGpBkKfAABDUAQALIAFBHGpBADYCACABQfSRwAA2AhggAUIBNwIMIAFBwKfAADYCCCABQQhqQcinwAAQ1AEAC/ECAQF/IwBBIGsiASQAQQxBBBA9IggEQAJAIAggAzYCCCAIIAM2AgQgCCACNgIAQQxBBBA9IgJFDQAgAiAFNgIIIAIgBTYCBCACIAQ2AgBBDEEEED0iA0UNACADIAc2AgggAyAHNgIEIAMgBjYCAAJAAkACQAJAAkACQAJAAkACQCAIIAIgAxALIgQOCwECAwQFBgAAAAAHAAsgACAENgIEIABBBjYCAAwHCyAAQQc2AgAgAEEBOgAEDAYLIABBBzYCACAAQQA6AAQMBQsgAUEcakEANgIAIAFB9JHAADYCGCABQgE3AgwgAUHYpcAANgIIIAFBCGpB4KXAABDUAQALIAFBHGpBADYCACABQfSRwAA2AhggAUIBNwIMIAFB/KTAADYCCCABQQhqQYSlwAAQ1AEACyAAQQM2AgAMAgsgAEEENgIADAELIABBATYCAAsgAxCrASACEKsBIAgQqwEgAUEgaiQADwsLQQxBBBDOAQAL5wMBAX8jAEHQAGsiASQAIAFBCGogAiADEGsgASgCECEDIAEoAgghCEEMQQQQPSICBEACQCACIAM2AgggAiADNgIEIAIgCDYCACABQRhqIAQgBRBrIAEoAiAhBCABKAIYIQVBDEEEED0iA0UNACADIAQ2AgggAyAENgIEIAMgBTYCACABQShqIAYgBxBrIAEoAjAhBiABKAIoIQdBDEEEED0iBEUNACAEIAY2AgggBCAGNgIEIAQgBzYCAAJAAkACQAJAAkACQAJAAkACQCACIAMgBBAMIgYOCwECAwQFBgAAAAAHAAsgACAGNgIEIABBBjYCAAwHCyAAQQc2AgAgAEEBOgAEDAYLIABBBzYCACAAQQA6AAQMBQsgAUHMAGpBADYCACABQfSRwAA2AkggAUIBNwI8IAFB2KXAADYCOCABQThqQYCmwAAQ1AEACyABQcwAakEANgIAIAFB9JHAADYCSCABQgE3AjwgAUH8pMAANgI4IAFBOGpB8KXAABDUAQALIABBAzYCAAwCCyAAQQQ2AgAMAQsgAEEBNgIACyAEEKsBIAEoAiwEQCAHEKsBCyADEKsBIAEoAhwEQCAFEKsBCyACEKsBIAEoAgwEQCAIEKsBCyABQdAAaiQADwsLQQxBBBDOAQALNABBDEEEED0iAEUEQEEMQQQQzgEACyAAIAI2AgggACACNgIEIAAgATYCACAAEA0gABCrAQuERAIUfwF+IwBBwANrIgQkAAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAQQxBBBA9IhIEQCASIAM2AgggEiADNgIEIBIgAjYCACASEA4iAgRAIAIoAgAiFQRAIAIoAgQhFiACKAIIIRdBBCEBIAIQqwEgBEHYAmoiAiAVIBcQiQEgBEHQAmogAhCQAUEAIQMgBC0A0AJBAXFFDR4gBC0A0QIiBkH7AEcEQCAGQSJHDR4gBEGYA2ogBEHYAmoQYwwdCyAEQdgCaiIKEIoBIARBmANqIAoQYyAEKAKYAyICQRVHDQMgBC0AnAMhBiAEQZgDaiAKEI4BIAQoApgDIgJBFUcEQCAELwCdAyAELQCfA0EQdHIhAyAEKAKkAyEKIAQoAqADIQUgBC0AnAMhBiACIQEMHwsgBEHIAmogChCQASAELQDIAkEBcSEFIAQtAMkCIQICQAJAIAZB/wFxRQRAQQAhBiAFRQ0XIAJB+wBHBEAgAkEiRwRAQQohAQwgCyAEQZgDaiAKEGMgBCgCmAMiAUEVRw0bDB4LIAoQigEgBEGYA2ogCiIDEGMCQAJ/IAQoApgDIgFBFUYEQCAELQCcAyEFIARBmANqIAMQjgEgBCgCmAMiAUEVRg0CIAQvAJ0DIAQtAJ8DQRB0cgwBCyAELwCdAyAELQCfA0EQdHILIQIgBCgCpAMhCiAEKAKgAyEFIAQtAJwDIAJBCHRyIQYMHwsgBUH/AXFFDRYgBEEgaiADEJABIAQtACBBAXFFDRcgBC0AIUEiRw0dIAMQigEgBEGYA2ogAxCPASAEKAKYAyIBQRVHDRogBEGkA2ooAgAhByAEQaADaigCACENIAQoApwDIgVFBEACQCAHRQRAQQEhBQwBCyAHQX9KIgFFDQQgByABED0iBUUNAwsgBSANIAcQiwIaIAchDQsgBEEYaiADEJABQQEhAiAELQAYQQFxBEAgBC0AGUH9AEYNHEELIQEgDUUNHyAFEKsBDB8LIA1FDRcgBRCrAUEEIQEMHgsgBUUNICACIgZB+wBHBEAgBkEiRw0gIARBmANqIAoQZgwfCyAKEIoBIARBmANqIAoiCxBmIAQoApgDIgJBFUYEQCAELQCcAyERIARBmANqIAsQjgEgBCgCmAMiDUEVRwRAIAQvAJ0DIAQtAJ8DQRB0ciEDIAQoAqQDIQogBCgCoAMhBSAELQCcAyEGIA0hAQwiCwJAIBFBAWsOBAsKCQgACyAEQeAAaiALEJABQQAhBiAELQBgQQFxRQ0hIAQtAGFB+wBHBEBBDiEBDCILIAsQigEgBEHYAGogCxCIASAELQBcIARB0ABqIAQoAlgiBhCQASAELQBQQQFxRQRAQQIhAkEAIQdBACEFDBMLIAQtAFEhAkEBcSEMIARB6AJqQQRyIRNBACEHA0ACQAJAAkACQAJAAkACQAJAAkACQAJ/AkACQAJ/AkAgAkH/AXEiBUEsRwRAIAVB/QBHBEAgDEH/AXENAkEJDAMLIAlBgH5xIQJBAwwFC0EQIAxB/wFxDQEaIAYQigEgBEHIAGogBhCQASAELQBIQQFxRQ0CIAQtAEkhAgsgAkH/AXEiBUEiRg0CQRAgBUH9AEcNABpBEwshAiAJIQUMIAsgCUH/AXEhBUEEIQIMHwsgBEFAayAGEJABIAQtAEBBAXFFBEBBBCECQQAhBQwfCyAELQBBQSJHBEBBDiECDB8LIAYQigEgBEH4AmogBhCPASAEKAKEAyEPIAQoAoADIQwgBCgC/AIhBSAEKAL4AiICQRVHDR4CQCAFRQRAQQIhAgJAAkAgD0EFaw4DAAMBAwsgDEGEssAAQQUQjQJBAEdBAXQhAgwCC0ECQQEgDEGRssAAQQcQjQIbIQIMAQtBAiECAkACQAJAIA9BBWsOAwACAQILIAVBhLLAAEEFEI0CQQBHQQF0IQIMAQtBAkEBIAVBkbLAAEEHEI0CGyECCyAMRQ0AIAUQqwELQQAhDCAJQYB+cQsgAnIiCUH/AXEiBUEDRwRAIAUOAgMCAQsgDiEJAkAgCCICRQRAIARB+AJqQYSywABBBRBdIAQoAvgCQRVHDQEgBEGEA2ooAgAhDSAEQYADaigCACEJIAQoAvwCIQILAkAgB0UEQCAEQfgCakGRssAAQQcQXSAEKAL4AkEVRw0BIARBhANqKAIAIRQgBEGAA2ooAgAhECAEKAL8AiEHCyAEIBQ2ArADIAQgEDYCrAMgBCkCrAMhGCAEQZgDaiALEI0BIBinIQ4gBCgCmAMiCEEVRg0GIAQoApwDIQYgBCgCpAMhCiAEKAKgAyEFIAkEQCACEKsBCyAGQQh2IQMgDg0FIAghAQwuCyAIRSEDIARBpANqIARBgANqKQMANwIAIAQgBCkD+AI3ApwDIAlFDSEgAhCrAQwhCyAEQaQDaiAEQYADaikDADcCACAEIAQpA/gCNwKcAwwcCyAEQfgCaiAGEI4BAkAgBCgC+AIiAkEVRwRAIARB9AJqIARBhANqKAIANgIAIAQgBCkC/AI3AuwCIAQgAjYC6AIMAQsgBEHoAmogBhBiIAQoAugCQRVGDQkLIARBpANqIARB8AJqKQMANwIAIAQgBCkD6AI3ApwDIARBBTYCmAMMHQsgB0UNBCAEQZgDakEEckGRssAAQQcQXiAQDR0MBQsgCARAIARBmANqQQRyQYSywABBBRBeIARBBTYCmAMMHAsgBEH4AmogBhBgIAQoAvgCQRVGDQIgBEGkA2ogBEGAA2opAwA3AgAgBCAEKQP4AjcCnAMgBEEFNgKYAwwZCyAHEKsBIAghAQwoCyAEQTBqIAsQkAECQCAELQAwQQFxBEAgBC0AMUH9AEcNASALEIoBIAlBgH5xIQUMEwsgCQRAIAIQqwELIA5FDSggBxCrAQwoCyAJBEAgAhCrAQtBCyEBIA5FDScgBxCrAQwnCyAEKAKEAyENIAQoAoADIQ4gBCgC/AIhCAwDCyAEQfgCaiAGEI4BAkAgBCgC+AIiAkEVRwRAIBMgBCkC/AI3AgAgE0EIaiAEQYQDaigCADYCACAEIAI2AugCDAELIARB6AJqIAYQZCAEKALoAkEVRg0CCyAEQaQDaiAEQfACaikDADcCACAEIAQpA+gCNwKcAwtBASEDDBgLIAQoAvQCIRQgBCgC8AIhECAEKALsAiEHCyAEQThqIAYQkAEgBC0AOSECIAQtADhBAXENAAtBAiECDBILIAQvAJ0DIAQtAJ8DQRB0ciEDIAQoAqQDIQogBCgCoAMhBSAELQCcAyEGIAIhAQwgCyAHIAEQzgEACxDPAQALIARBrANqQQA2AgAgBEH0kcAANgKoAyAEQgE3ApwDIARBwKfAADYCmAMgBEGYA2pByKfAABDUAQALIARBrANqQQA2AgAgBEH0kcAANgKoAyAEQgE3ApwDIARBqKbAADYCmAMgBEGYA2pBkKfAABDUAQALQQxBBBDOAQALIAQvAJ0DIAQtAJ8DQRB0ciEDIAQoAqQDIQogBCgCoAMhBSAELQCcAyEGIAIhAQwaCyAEQcACaiALEJABQQAhBiAELQDAAkEBcUUNGSAELQDBAkH7AEcEQEEOIQEMGgsgCxCKASAEQbgCaiALEIgBIAQtALwCIQUgBEGwAmogBCgCuAIiBhCQAQJAAkACQAJAIAQtALACQQFxRQRAQQIhCEEAIQJBACEFDAELIAQtALECIQcgBUEBcSEPQQAhAgNAAkACQAJAAkACQAJAAkACfwJAAkACQCAHQf8BcSIMQSxHBEAgDEH9AEcEQCAPQf8BcQ0CQQkhCAwOC0ECIQcgBUGAfnEMBAsgD0H/AXEEQEEQIQgMDQsgBhCKASAEQagCaiAGEJABIAQtAKgCQQFxRQ0BIAQtAKkCIQcLIAdB/wFxIgdBIkYNAUETQRAgB0H9AEYbIQgMCwsgBUH/AXEhBUEEIQgMCgsgBEGgAmogBhCQASAELQCgAkEBcUUEQEEEIQhBACEFDAoLIAQtAKECQSJHBEBBDiEIDAoLIAYQigEgBEH4AmogBhCPASAEKAKEAyEMIAQoAoADIQcgBCgC/AIhDiAEKAL4AiIIQRVHBEAgDiEFDAoLAkAgDkUEQEEBIQggDEEERw0BIAcoAABB69K5owZHIQgMAQtBASEIIAxBBEYEQCAOKAAAQevSuaMGRyEICyAHRQ0AIA4QqwELIAVBgH5xIQdBACEPIAhB/wFxCyAHciIFQf8BcUECRwRAIAVBAXENASACDQMgBEH4AmogBhBgIAQoAvgCQRVHDQIgBCgChAMhDSAEKAKAAyEJIAQoAvwCIQIMBwsgAkUEQCAEQfgCakGJrsAAQQQQXSAEKAL4AkEVRw0EIARBhANqKAIAIQ0gBEGAA2ooAgAhCSAEKAL8AiECCyAEQZgDaiALEI0BIAQoApgDIgdBFUYNBSAEKAKcAyIGQQh2IQMgBCgCpAMhCiAEKAKgAyEFIAkNBCAHIQEMJQsgBEH4AmogBhCOAQJAIAQoAvgCIgdBFUcEQCAEQfQCaiAEQYQDaigCADYCACAEIAQpAvwCNwLsAiAEIAc2AugCDAELIARB6AJqIAYQYiAEKALoAkEVRg0GCyAEQaQDaiAEQfACaikDADcCACAEIAQpA+gCNwKcAwwICyAEQaQDaiAEQYADaikDADcCACAEIAQpA/gCNwKcAwwJCyAEQZgDakEEckGJrsAAQQQQXiAJRQ0IDAcLIARBpANqIARBgANqKQMANwIAIAQgBCkD+AI3ApwDDAcLIAIQqwEgByEBDCALIARBkAJqIAsQkAECQCAELQCQAkEBcQRAIAQtAJECQf0ARw0BIAsQigEgCUGAfnEhBQwLCyAJRQ0gIAIQqwEMIAtBCyEBIAlFDR8gAhCrAQwfCyAEQZgCaiAGEJABIAQtAJkCIQcgBC0AmAJBAXENAAsgBUH/AXEhBUECIQgLIARBqANqIAw2AgAgBEGkA2ogBzYCACAEQaADaiAFNgIAIAQgCDYCnAMLIAJFIAlFcg0BCyACEKsBCyAEQaADaigCACIGQQh2IQMgBEGoA2ooAgAhCiAEQaQDaigCACEFIAQoApwDIQEMGQsgBEGIAmogCxCQAUEAIQYCfwJAIAQtAIgCQQFxRQ0AAkAgBC0AiQJB+wBHDQAgCxCKASAEQYACaiALEIgBIAQtAIQCIQIgBEH4AWogBCgCgAIiCBCQAQJAAkACQCAELQD4AUEBcQRAIAQtAPkBIQUgAkEBcSEJA0ACfwJAAkACQCAFQf8BcSICQSxHBEAgAkH9AEcEQCAJQf8BcQ0CIAchBkEJDA0LIAdBgH5xDAQLIAlB/wFxBEAgByEGQRAMDAsgCBCKASAEQfABaiAIEJABIAQtAPABQQFxRQ0BIAQtAPEBIQULIAVB/wFxIgVBIkYNASAHIQZBE0EQIAVB/QBGGwwKCyAHQf8BcSEGQQQMCQsgBEHoAWogCBCQASAELQDoAUEBcUUNByAELQDpAUEiRw0GIAgQigEgBEGYA2ogCBCPASAEKAKgAyEFIAQoApwDIQIgBCgCmAMiCUEVRw0EIAJFIAVFckUEQCACEKsBC0EAIQkgB0GAfnFBAXILIgdB/wFxRQ0CIARBmANqIAgQjgEgBCgCmAMiAkEVRwRAIARBhANqIARBpANqKAIANgIAIAQgBCkCnAM3AvwCDAULIARB+AJqIAgQYiAEKAL4AiICQRVHDQQgBEHgAWogCBCQASAELQDhASEFIAQtAOABQQFxDQALCyAHQf8BcSEGQQIMBQsgBEGYA2ogCxCNASAEKAKYAyINQRVHBEAgBCgCpAMhCiAEKAKgAyEFIAQoApwDIQYgDQwFCyAEQdgBaiALEJABIAQtANgBQQFxRQ0dIAQtANkBQf0ARwRAQQshAQweCyALEIoBQQAhBUEAIQkMBwsgBCgCpAMhCiACIQYgCQwDCyAEKAKEAyEKIAQoAoADIQUgBCgC/AIhBiACDAILQQ4MAQtBBAshASAGQQh2IQMMGAsgBEHQAWogCxCQAUEAIQYgBC0A0AFBAXFFDRcgBC0A0QFB+wBHBEBBDiEBDBgLIAsQigEgBEHIAWogCxCIASAELQDMASEFIARBwAFqIAQoAsgBIgYQkAECQAJAAkACQCAELQDAAUEBcUUEQEECIQhBACECQQAhBQwBCyAELQDBASEHIAVBAXEhD0EAIQIDQAJAAkACQAJAAkACQAJAAn8CQAJAAkAgB0H/AXEiDEEsRwRAIAxB/QBHBEAgD0H/AXENAkEJIQgMDgtBAiEHIAVBgH5xDAQLIA9B/wFxBEBBECEIDA0LIAYQigEgBEG4AWogBhCQASAELQC4AUEBcUUNASAELQC5ASEHCyAHQf8BcSIHQSJGDQFBE0EQIAdB/QBGGyEIDAsLIAVB/wFxIQVBBCEIDAoLIARBsAFqIAYQkAEgBC0AsAFBAXFFBEBBBCEIQQAhBQwKCyAELQCxAUEiRwRAQQ4hCAwKCyAGEIoBIARB+AJqIAYQjwEgBCgChAMhDCAEKAKAAyEHIAQoAvwCIQ4gBCgC+AIiCEEVRwRAIA4hBQwKCwJAIA5FBEBBASEIIAxBBEcNASAHKAAAQeHIkZMHRyEIDAELQQEhCCAMQQRGBEAgDigAAEHhyJGTB0chCAsgB0UNACAOEKsBCyAFQYB+cSEHQQAhDyAIQf8BcQsgB3IiBUH/AXFBAkcEQCAFQQFxDQEgAg0DIARB+AJqIAYQYCAEKAL4AkEVRw0CIAQoAoQDIQ0gBCgCgAMhCSAEKAL8AiECDAcLIAJFBEAgBEH4AmpBgLLAAEEEEF0gBCgC+AJBFUcNBCAEQYQDaigCACENIARBgANqKAIAIQkgBCgC/AIhAgsgBEGYA2ogCxCNASAEKAKYAyIHQRVGDQUgBCgCnAMiBkEIdiEDIAQoAqQDIQogBCgCoAMhBSAJDQQgByEBDCMLIARB+AJqIAYQjgECQCAEKAL4AiIHQRVHBEAgBEH0AmogBEGEA2ooAgA2AgAgBCAEKQL8AjcC7AIgBCAHNgLoAgwBCyAEQegCaiAGEGIgBCgC6AJBFUYNBgsgBEGkA2ogBEHwAmopAwA3AgAgBCAEKQPoAjcCnAMMCAsgBEGkA2ogBEGAA2opAwA3AgAgBCAEKQP4AjcCnAMMCQsgBEGYA2pBBHJBgLLAAEEEEF4gCUUNCAwHCyAEQaQDaiAEQYADaikDADcCACAEIAQpA/gCNwKcAwwHCyACEKsBIAchAQweCyAEQaABaiALEJABAkAgBC0AoAFBAXEEQCAELQChAUH9AEcNASALEIoBIAlBgH5xIQUMCQsgCUUNHiACEKsBDB4LQQshASAJRQ0dIAIQqwEMHQsgBEGoAWogBhCQASAELQCpASEHIAQtAKgBQQFxDQALIAVB/wFxIQVBAiEICyAEQagDaiAMNgIAIARBpANqIAc2AgAgBEGgA2ogBTYCACAEIAg2ApwDCyACRSAJRXINAQsgAhCrAQsgBEGgA2ooAgAiBkEIdiEDIARBqANqKAIAIQogBEGkA2ooAgAhBSAEKAKcAyEBDBcLIARBmAFqIAsQkAFBACEGIAQtAJgBQQFxRQ0WIAQtAJkBQfsARwRAQQ4hAQwXCyALEIoBIARBkAFqIAsQiAEgBC0AlAEgBEGIAWogBCgCkAEiBhCQASAELQCIAUEBcUUEQEECIQJBACEHQQAhBQwDCyAELQCJASECQQFxIQwgBEHoAmpBBHIhE0EAIQcDQAJAAkACQAJAAkACQAJAAkACQAJAAn8CQAJAAn8CQCACQf8BcSIFQSxHBEAgBUH9AEcEQCAMQf8BcQ0CQQkMAwsgCUGAfnEhAkEDDAULQRAgDEH/AXENARogBhCKASAEQYABaiAGEJABIAQtAIABQQFxRQ0CIAQtAIEBIQILIAJB/wFxIgVBIkYNAkEQIAVB/QBHDQAaQRMLIQIgCSEFDBALIAlB/wFxIQVBBCECDA8LIARB+ABqIAYQkAEgBC0AeEEBcUUEQEEEIQJBACEFDA8LIAQtAHlBIkcEQEEOIQIMDwsgBhCKASAEQfgCaiAGEI8BIAQoAoQDIQ8gBCgCgAMhDCAEKAL8AiEFIAQoAvgCIgJBFUcNDgJAIAVFBEBBAiECAkACQCAPQQVrDgQAAwMBAwsgDEGEssAAQQUQjQJBAEdBAXQhAgwCC0EBQQIgDCkAAELyys2D983bueUAURshAgwBC0ECIQICQAJAAkAgD0EFaw4EAAICAQILIAVBhLLAAEEFEI0CQQBHQQF0IQIMAQtBAUECIAUpAABC8srNg/fN27nlAFEbIQILIAxFDQAgBRCrAQtBACEMIAlBgH5xCyACciIJQf8BcSIFQQNHBEAgBQ4CAwIBCyAOIQkCQCAIIgJFBEAgBEH4AmpBhLLAAEEFEF0gBCgC+AJBFUcNASAEQYQDaigCACENIARBgANqKAIAIQkgBCgC/AIhAgsCQCAHRQRAIARB+AJqQYmywABBCBBdIAQoAvgCQRVHDQEgBEGEA2ooAgAhFCAEQYADaigCACEQIAQoAvwCIQcLIAQgFDYCsAMgBCAQNgKsAyAEKQKsAyEYIARBmANqIAsQjQEgGKchDiAEKAKYAyIIQRVGDQYgBCgCnAMhBiAEKAKkAyEKIAQoAqADIQUgCQRAIAIQqwELIAZBCHYhAyAODQUgCCEBDCMLIAhFIQMgBEGkA2ogBEGAA2opAwA3AgAgBCAEKQP4AjcCnAMgCUUNESACEKsBDBELIARBpANqIARBgANqKQMANwIAIAQgBCkD+AI3ApwDDAwLIARB+AJqIAYQjgECQCAEKAL4AiICQRVHBEAgBEH0AmogBEGEA2ooAgA2AgAgBCAEKQL8AjcC7AIgBCACNgLoAgwBCyAEQegCaiAGEGIgBCgC6AJBFUYNCQsgBEGkA2ogBEHwAmopAwA3AgAgBCAEKQPoAjcCnAMgBEEFNgKYAwwNCyAHRQ0EIARBmANqQQRyQYmywABBCBBeIBANDQwFCyAIBEAgBEGYA2pBBHJBhLLAAEEFEF4gBEEFNgKYAwwMCyAEQfgCaiAGEGAgBCgC+AJBFUYNAiAEQaQDaiAEQYADaikDADcCACAEIAQpA/gCNwKcAyAEQQU2ApgDDAkLIAcQqwEgCCEBDB0LIARB6ABqIAsQkAECQCAELQBoQQFxBEAgBC0AaUH9AEcNASALEIoBIAlBgH5xIQUMCAsgCQRAIAIQqwELIA5FDR0gBxCrAQwdCyAJBEAgAhCrAQtBCyEBIA5FDRwgBxCrAQwcCyAEKAKEAyENIAQoAoADIQ4gBCgC/AIhCAwDCyAEQfgCaiAGEI4BAkAgBCgC+AIiAkEVRwRAIBMgBCkC/AI3AgAgE0EIaiAEQYQDaigCADYCACAEIAI2AugCDAELIARB6AJqIAYQZCAEKALoAkEVRg0CCyAEQaQDaiAEQfACaikDADcCACAEIAQpA+gCNwKcAwtBASEDDAgLIAQoAvQCIRQgBCgC8AIhECAEKALsAiEHCyAEQfAAaiAGEJABIAQtAHEhAiAELQBwQQFxDQALQQIhAgwCCyAEQShqIAoQkAEgCUH/AXEiBiAFciEJIBinIQgCQAJAAkACQAJAIAQtAChBAXEEQCAELQApQf0ARg0FQQshASARDgQBAgMbAwsCQAJAAkACQCARDgQAAQIeAgsgCQRAIAIQqwELIAhFDR0MAgsgCQRAIAIQqwELIAhFDRwMAQsgAiEHIAlFDRsLIAcQqwEMGgsgCQRAIAIQqwELIAhFDRkMAgsgCQRAIAIQqwELIAhFDRgMAQsgAiEHIAlFDRcLIAcQqwEMFgsgChCKAQwQC0EAIQgMAQsgBEGoA2ogDzYCACAEQaQDaiAMNgIAIARBoANqIAU2AgAgBCACNgKcAwtBASEDIAdFIBBFcg0BC0EBIQMgBxCrAQsgDkUgCEUgA0VyckUEQCAIEKsBCyAEQaADaigCACIGQQh2IQMgBEGoA2ooAgAhCiAEQaQDaigCACEFIAQoApwDIQEMEAtBACEIDAELIARBqANqIA82AgAgBEGkA2ogDDYCACAEQaADaiAFNgIAIAQgAjYCnAMLQQEhAyAHRSAQRXINAQtBASEDIAcQqwELIA5FIAhFIANFcnJFBEAgCBCrAQsgBEGgA2ooAgAiBkEIdiEDIARBqANqKAIAIQogBEGkA2ooAgAhBSAEKAKcAyEBDAsLIARBmANqIAMQZCAEKAKYAyIBQRVHDQMgBEGkA2ooAgAhByAEQaADaigCACENIAQoApwDIQUgBEEQaiADEJABIAQtABBBAXEEQEEAIQIgBC0AEUH9AEYNBUELIQEgDQ0DDAgLIA0NAQtBBCEBDAYLIAUQqwFBBCEBDAULIAUQqwEMBAsgBCgCpAMhCiAEKAKgAyEFIAQoApwDIQYMAwsgAxCKASAEQQhqIAoQkAECQAJAAkAgBC0ACEEBcQRAIAQtAAlB/QBGDQNBCyEBIA1FDQEgBRCrAUEAIQMMCQtBBCEBIA0NAQtBACEDDAcLIAUQqwFBACEDDAYLIAoQigEgBUH/AXEhBkEFIRELIAVBgH5xIAZyIQYgBEGYA2ogBEHYAmoQiwEgGKchCSAEKAKYAyIBQRVHBEAgBCgCpAMhCiAEKAKgAyEFIAQoApwDIQMCQAJAAkACQAJAIBEOBgABAgsCAwILIAYEQCACEKsBCyAJRQ0KDAMLIAYEQCACEKsBCyAJRQ0JDAILIAIhByAGRQ0IDAELIAYhByANRQ0HCyAHEKsBDAYLIAAgGEIgiD4CGCAAIAk2AhQgACAHNgIQIAAgDTYCDCAAIAY2AgggACACNgIEIAAgETYCACAWRQ0GIBUQqwEMBgtBDiEBCyAGQQh2IQMMAgsgBCgCmAMiAUEVRwRAIAQvAJ0DIAQtAJ8DQRB0ciEDIAQoAqQDIQogBCgCoAMhBSAELQCcAyEGDAILQQ4hAQwBC0EKIQELIAZB/wFxIANBCHRyIQMLIAQgCjYChAMgBCAFNgKAAyAEIAM2AvwCIAQgATYC+AJBiAFBARA9IgFFBEBBiAFBARDOAQALIAFB1JDAAEGIARCLAiEBIARBADYC8AIgBEIBNwPoAiAEQZgDaiICIARB6AJqQZiPwAAQ8gEgBEH4AmogAhCHAQ0BIAQoAugCIQIgBCgC7AIhAyAEKALwAiEHAkAgBCgC+AJBFEkNACAEKAKAA0UNACAEKAL8AhCrAQsgBCAHNgKQAyAEIAM2AowDIAQgAjYCiAMgBEKIgYCAgBE3A4ADIAQgATYC/AIgBEEINgL4AiAEQQA2AvACIARCATcD6AIgBEGYA2oiASAEQegCakGYj8AAEPIBIARB+AJqIAEQfQ0BIAAgBCkD6AI3AgQgAEEMaiAEQfACaigCADYCACAAIBc2AhggACAWNgIUIAAgFTYCECAAQQE2AgAgBEH4AmoQLgsgEhCrASAEQcADaiQADwtBsI/AAEE3IARB2AJqQeiPwABBxJDAABDpAQALyggBAX8jAEEwayICJAACfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIAAoAgBBAWsODAECAwQFBgcICQoLDAALIAJBLGpBATYCACACQgE3AhwgAkHwrMAANgIYIAJBIzYCBCACIABBBGo2AhQgAiACNgIoIAIgAkEUajYCACABIAJBGGoQ9wEMDAsgAkEsakEBNgIAIAJCATcCHCACQdSswAA2AhggAkEkNgIEIAIgAEEEajYCFCACIAI2AiggAiACQRRqNgIAIAEgAkEYahD3AQwLCyACQSxqQQE2AgAgAkIBNwIcIAJBtKzAADYCGCACQR42AgQgAiAAQQRqNgIUIAIgAjYCKCACIAJBFGo2AgAgASACQRhqEPcBDAoLIAJBLGpBATYCACACQgE3AhwgAkGcrMAANgIYIAJBHjYCBCACIABBBGo2AhQgAiACNgIoIAIgAkEUajYCACABIAJBGGoQ9wEMCQsgAkEMakElNgIAIAJBLGpBAjYCACACIABBCGo2AhAgAkICNwIcIAJB9KvAADYCGCACQSU2AgQgAiAAQRBqNgIUIAIgAjYCKCACIAJBFGo2AgggAiACQRBqNgIAIAEgAkEYahD3AQwICyACQSxqQQE2AgAgAkIBNwIcIAJByKvAADYCGCACQR42AgQgAiAAQQRqNgIUIAIgAjYCKCACIAJBFGo2AgAgASACQRhqEPcBDAcLIAJBLGpBATYCACACQgE3AhwgAkGsq8AANgIYIAJBHjYCBCACIABBBGo2AhQgAiACNgIoIAIgAkEUajYCACABIAJBGGoQ9wEMBgsgAkEsakEBNgIAIAJCAjcCHCACQfSqwAA2AhggAkEeNgIEIAIgAEEEajYCFCACIAI2AiggAiACQRRqNgIAIAEgAkEYahD3AQwFCyACQQxqQR42AgAgAkEsakECNgIAIAIgAEEEajYCECACQgI3AhwgAkHYqsAANgIYIAJBHjYCBCACIABBEGo2AhQgAiACNgIoIAIgAkEUajYCCCACIAJBEGo2AgAgASACQRhqEPcBDAQLIAJBDGpBHjYCACACQSxqQQI2AgAgAiAAQQRqNgIQIAJCAjcCHCACQbCqwAA2AhggAkEeNgIEIAIgAEEQajYCFCACIAI2AiggAiACQRRqNgIIIAIgAkEQajYCACABIAJBGGoQ9wEMAwsgAkEsakEBNgIAIAJCATcCHCACQYyqwAA2AhggAkEmNgIEIAIgAEEEajYCFCACIAI2AiggAiACQRRqNgIAIAEgAkEYahD3AQwCCyACQSxqQQE2AgAgAkIBNwIcIAJB+KnAADYCGCACQSc2AgQgAiAAQQRqNgIUIAIgAjYCKCACIAJBFGo2AgAgASACQRhqEPcBDAELIAJBLGpBADYCACACQfSRwAA2AiggAkIBNwIcIAJB4KnAADYCGCABIAJBGGoQ9wELIAJBMGokAAtAAQJ/IABBCGooAgAhASAAKAIAIQJBDEEEED0iAEUEQEEMQQQQzgEACyAAIAE2AgggACABNgIEIAAgAjYCACAAC6EBAQJ/IwBBIGsiAiQAAkAgAQRAIAEoAgAiAw0BIAJBHGpBADYCACACQfSRwAA2AhggAkIBNwIMIAJBwKfAADYCCCACQQhqQcinwAAQ1AEACyACQRxqQQA2AgAgAkH0kcAANgIYIAJCATcCDCACQaimwAA2AgggAkEIakGQp8AAENQBAAsgACADNgIAIAAgASkCBDcCBCABEKsBIAJBIGokAAu5BQEBfyMAQRBrIgIkAAJ/AkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgACgCAEEBaw4MAQIDBAUGBwgJCgsMAAsgAiAAQQRqNgIMIAFBjK/AAEEPQYqtwABBBiACQQxqQZyvwAAQ+gEMDAsgAiAAQQRqNgIMIAFB6a7AAEEQQYqtwABBBiACQQxqQfyuwAAQ+gEMCwsgAiAAQQRqNgIMIAFB367AAEEKQeutwABBAyACQQxqQYSUwAAQ+gEMCgsgAiAAQQRqNgIMIAFB0q7AAEENQeutwABBAyACQQxqQYSUwAAQ+gEMCQsgAiAAQQhqNgIIIAIgAEEQajYCDCABQaKuwABBD0GxrsAAQQggAkEIakG8rsAAQcyuwABBBiACQQxqQbyuwAAQ+wEMCAsgAiAAQQRqNgIMIAFBmK7AAEEKQeutwABBAyACQQxqQYSUwAAQ+gEMBwsgAiAAQQRqNgIMIAFBja7AAEELQeutwABBAyACQQxqQYSUwAAQ+gEMBgsgAiAAQQRqNgIMIAFBga7AAEEIQYmuwABBBCACQQxqQYSUwAAQ+gEMBQsgAiAAQQRqNgIIIAIgAEEQajYCDCABQe6twABBCEH2rcAAQQsgAkEIakGElMAAQeutwABBAyACQQxqQYSUwAAQ+wEMBAsgAiAAQQRqNgIIIAIgAEEQajYCDCABQdStwABBDEHgrcAAQQsgAkEIakGElMAAQeutwABBAyACQQxqQYSUwAAQ+wEMAwsgAiAAQQRqNgIMIAFBvK3AAEEIQYqtwABBBiACQQxqQcStwAAQ+gEMAgsgAiAAQQRqNgIMIAFBoK3AAEEMQYqtwABBBiACQQxqQaytwAAQ+gEMAQsgAiAAQQRqNgIMIAFB+KzAAEESQYqtwABBBiACQQxqQZCtwAAQ+gELIAJBEGokAAscACAAKAIAKAIAIgAoAgAgAEEIaigCACABEIACC7cBAAJAIAIEQAJAAkACfwJAAkAgAUEATgRAIAMoAggNASABDQJBASECDAQLDAYLIAMoAgQiAkUEQCABRQRAQQEhAgwECyABQQEQPQwCCyADKAIAIAJBASABED4MAQsgAUEBED0LIgJFDQELIAAgAjYCBCAAQQhqIAE2AgAgAEEANgIADwsgACABNgIEIABBCGpBATYCACAAQQE2AgAPCyAAIAE2AgQLIABBCGpBADYCACAAQQE2AgALzQEBA38jAEEgayICJAACQAJAIAFBAWoiAUUNACAAQQRqKAIAIgNBAXQiBCABIAEgBEkbIgFBCCABQQhLGyIBQX9zQR92IQQCQCADBEAgAkEBNgIYIAIgAzYCFCACIAAoAgA2AhAMAQsgAkEANgIYCyACIAEgBCACQRBqEIIBIAIoAgQhAyACKAIARQRAIAAgAzYCACAAQQRqIAE2AgAMAgsgAkEIaigCACIAQYGAgIB4Rg0BIABFDQAgAyAAEM4BAAsQzwEACyACQSBqJAALzwEBAn8jAEEgayIDJAACQAJAIAEgASACaiIBSw0AIABBBGooAgAiAkEBdCIEIAEgASAESRsiAUEIIAFBCEsbIgFBf3NBH3YhBAJAIAIEQCADQQE2AhggAyACNgIUIAMgACgCADYCEAwBCyADQQA2AhgLIAMgASAEIANBEGoQggEgAygCBCECIAMoAgBFBEAgACACNgIAIABBBGogATYCAAwCCyADQQhqKAIAIgBBgYCAgHhGDQEgAEUNACACIAAQzgEACxDPAQALIANBIGokAAsdACABKAIARQRAAAsgAEHEs8AANgIEIAAgATYCAAtVAQJ/IAEoAgAhAiABQQA2AgACQCACBEAgASgCBCEDQQhBBBA9IgFFDQEgASADNgIEIAEgAjYCACAAQcSzwAA2AgQgACABNgIADwsAC0EIQQQQzgEAC+0DAQF/IwBBMGsiAiQAAn8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgACgCAEEBaw4UAQIDBAUGBwgJCgsMDQ4PEBESExQACyACQcK5wAA2AihBIgwUCyACQam5wAA2AihBGQwTCyACQY25wAA2AihBHAwSCyACQfK4wAA2AihBGwwRCyACQdO4wAA2AihBHwwQCyACQa24wAA2AihBJgwPCyACQYW4wAA2AihBKAwOCyACQc63wAA2AihBNwwNCyACQae3wAA2AihBJwwMCyACQe+2wAA2AihBOAwLCyACQbe2wAA2AihBOAwKCyACQYm2wAA2AihBLgwJCyACQfG1wAA2AihBGAwICyACQeK1wAA2AihBDwwHCyACQda1wAA2AihBDAwGCyACQbu1wAA2AihBGwwFCyACQaC1wAA2AihBGwwECyACQdG0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ACAERgRAIAEgBBCDASABKAIIIQQLIAEoAgAgBGpB3AA6AAAgBEEBagwHCyADKAIAIARGBEAgASAEEIMBIAEoAgghBAsgASgCACAEakHcADoAACABIARBAWoiBDYCCCADKAIAIARGBEAgASAEEIMBIAEoAgghBAsgASgCACAEakEiOgAAIARBAWoMBgsgAygCACAERgRAIAEgBBCDASABKAIIIQQLIAEoAgAgBGpB3AA6AAAgASAEQQFqIgQ2AgggAygCACAERgRAIAEgBBCDASABKAIIIQQLIAEoAgAgBGpB4gA6AAAgBEEBagwFCyADKAIAIARGBEAgASAEEIMBIAEoAgghBAsgASgCACAEakHcADoAACABIARBAWoiBDYCCCADKAIAIARGBEAgASAEEIMBIAEoAgghBAsgASgCACAEakH0ADoAACAEQQFqDAQLIAMoAgAgBEYEQCABIAQQgwEgASgCCCEECyABKAIAIARqQdwAOgAAIAEgBEEBaiIENgIIIAMoAgAgBEYEQCABIAQQgwEgASgCCCEECyABKAIAIARqQe4AOgAAIARBAWoMAwsgAygCACAERgRAIAEgBBCDASABKAIIIQQLIAEoAgAgBGpB3AA6AAAgASAEQQFqIgQ2AgggAygCACAERgRAIAEgBBCDASABKAIIIQQLIAEoAgAgBGpB5gA6AAAgBEEBagwCCyADKAIAIARGBEAgASAEEIMBIAEoAgghBAsgASgCACAEakHcADoAACABIARBAWoiBDYCCCADKAIAIARGBEAgASAEEIMBIAEoAgghBAsgASgCACAEakHyADoAACAEQQFqDAELAn8CQAJAIAVBIE8EQCAFQYABSQ0BIAVBgBBPDQIgBiAFQT9xQYABcjoADSAGIAVBBnZBwAFyOgAMQQIMAwsgAygCACAERgRAIAEgBBCDASABKAIIIQQLIAEoAgAgBGpB3AA6AAAgASAEQQFqIgQ2AgggAygCACAERgRAIAEgBBCDASABKAIIIQQLIAEoAgAgBGpB9QA6AAAgASAEQQFqIgQ2AgggAygCACAERgRAIAEgBBCDASABKAIIIQQLIAEoAgAgBGpBMDoAACABIARBAWoiBDYCCCADKAIAIARGBEAgASAEEIMBIAEoAgghBAsgASgCACAEakEwOgAAIAEgBEEBaiIENgIIIAVBD3EiCEEKSSEHIAMoAgAgBEYEQCABIAQQgwEgASgCCCEECyABKAIAIARqIAVB8AFxQQR2QTByOgAAIAEgBEEBaiIENgIIIAMoAgAgBEYEQCABIAQQgwEgASgCCCEECyABKAIAIARqIAhBMHIgCEE3aiAHGzoAACAEQQFqDAMLIAMoAgAgBEYEQCABIAQQgwEgASgCCCEECyABKAIAIARqIAU6AAAgBEEBagwCCyAFQYCABE8EQCAGIAVBP3FBgAFyOgAPIAYgBUESdkHwAXI6AAwgBiAFQQZ2QT9xQYABcjoADiAGIAVBDHZBP3FBgAFyOgANQQQMAQsgBiAFQT9xQYABcjoADiAGIAVBDHZB4AFyOgAMIAYgBUEGdkE/cUGAAXI6AA1BAwshBSAFIAMoAgAgBGtLBEAgASAEIAUQhAEgASgCCCEECyABKAIAIARqIAZBDGogBRCLAhogBCAFagsiBDYCCCACIAlHDQALCyABQQRqKAIAIARGBEAgASAEEIMBIAEoAgghBAsgAEEANgIAIAEgBEEBajYCCCABKAIAIARqQSI6AAAgBkEQaiQAC0wBAX8gAUEEaigCACABKAIIIgJrQQNNBEAgASACQQQQhAEgASgCCCECCyAAQQA2AgAgASACQQRqNgIIIAEoAgAgAmpB7uqx4wY2AAALDQAgACABIAIgAxCXAQtSAQF/IAEoAggiAiABKAIERgRAIAEgAhCDASABKAIIIQILIAAgATYCBCAAQQA2AgAgASACQQFqNgIIIABBCGpBAToAACABKAIAIAJqQdsAOgAAC1IBAX8gASgCCCICIAEoAgRGBEAgASACEIMBIAEoAgghAgsgACABNgIEIABBADYCACABIAJBAWo2AgggAEEIakEBOgAAIAEoAgAgAmpB+wA6AAALngICAn8BfiMAQSBrIgUkACABKAIIIgQgASgCBEYEQCABIAQQgwEgASgCCCEECyABIARBAWo2AgggASgCACAEakH7ADoAACAFQRBqIAEgAiADEJcBAkAgBSgCEEUEQCABKAIIIgQgASgCBEYEQCABIAQQgwEgASgCCCEECyABKAIAIARqQTo6AAAgASAEQQFqIgQ2AgggASgCBCAERgRAIAEgBBCDASABKAIIIQQLIAAgATYCBCAAQQA2AgAgASAEQQFqNgIIIABBCGpBAToAACABKAIAIARqQfsAOgAADAELIAVBCGogBUEcaigCACIBNgIAIAUgBSkCFCIGNwMAIABBDGogATYCACAAIAY3AgQgAEEBNgIACyAFQSBqJAALFgAgACgCACIAKAIAIAAoAgQgARCAAgsdACABKAIARQRAAAsgAEGI1cAANgIEIAAgATYCAAtVAQJ/IAEoAgAhAiABQQA2AgACQCACBEAgASgCBCEDQQhBBBA9IgFFDQEgASADNgIEIAEgAjYCACAAQYjVwAA2AgQgACABNgIADwsAC0EIQQQQzgEAC5QEAQN/IwBBMGsiAiQAAn8CQAJAAkACQCAAKAIEIgMOAwACAwELIwBBEGsiACQAIABB0NbAADYCCCAAQQ42AgQgAEG/1sAANgIAIwBBEGsiASQAIAFBCGogAEEIaigCADYCACABIAApAgA3AwAjAEEQayIAJAAgACABKQIANwMIIABBCGpB9NTAAEEAIAEoAghBARCyAQALIAJBLGpBADYCACACQYjVwAA2AiggAkIBNwIcIAJBoNXAADYCGEEBIAEgAkEYahD3AQ0CGiADQQN0IQMgACgCACEAAkADQCACIAA2AhQgBARAIAJBADYCLCACQYjVwAA2AiggAkIBNwIcIAJBrNXAADYCGCABIAJBGGoQ9wENAgsgAkEBNgIsIAJCAjcCHCACQbTVwAA2AhggAkHMADYCBCACIAI2AiggAiACQRRqNgIAIAEgAkEYahD3AQ0BIABBCGohACAEQQFrIQQgA0EIayIDDQALQQAMAwtBAQwCCyACQSxqQQE2AgAgAkICNwIcIAJBtNXAADYCGCACQc0ANgIEIAIgACgCADYCACACIAI2AiggASACQRhqEPcBDAELIAJBDGpBzQA2AgAgAkEsakECNgIAIAJCAzcCHCACQczVwAA2AhggAkHNADYCBCACIAAoAgAiADYCACACIABBCGo2AgggAiACNgIoIAEgAkEYahD3AQsgAkEwaiQACwwAQsiF+aSet9TbEgshAQF/AkAgACgCBCIBRQ0AIABBCGooAgBFDQAgARCrAQsL1gIBAn8jAEEQayICJAAgACgCACEAAkACfwJAIAFBgAFPBEAgAkEANgIMIAFBgBBPDQEgAiABQT9xQYABcjoADSACIAFBBnZBwAFyOgAMQQIMAgsgACgCCCIDIAAoAgRGBEAgACADEBAgACgCCCEDCyAAIANBAWo2AgggACgCACADaiABOgAADAILIAFBgIAETwRAIAIgAUE/cUGAAXI6AA8gAiABQQZ2QT9xQYABcjoADiACIAFBDHZBP3FBgAFyOgANIAIgAUESdkEHcUHwAXI6AAxBBAwBCyACIAFBP3FBgAFyOgAOIAIgAUEMdkHgAXI6AAwgAiABQQZ2QT9xQYABcjoADUEDCyEBIAEgAEEEaigCACAAKAIIIgNrSwRAIAAgAyABEBEgACgCCCEDCyAAKAIAIANqIAJBDGogARCLAhogACABIANqNgIICyACQRBqJABBAAtaAQF/IwBBIGsiAiQAIAIgACgCADYCBCACQRhqIAFBEGopAgA3AwAgAkEQaiABQQhqKQIANwMAIAIgASkCADcDCCACQQRqQeDWwAAgAkEIahDeASACQSBqJAALkwMBBX8CQAJAAkACQCABQQlPBEBBEEEIELMBIAFLDQEMAgsgABCmASEEDAILQRBBCBCzASEBC0EIQQgQswEhA0EUQQgQswEhAkEQQQgQswEhBUEAQRBBCBCzAUECdGsiBkGAgHwgBSACIANqamtBd3FBA2siAyADIAZLGyABayAATQ0AIAFBECAAQQRqQRBBCBCzAUEFayAASxtBCBCzASIDakEQQQgQswFqQQRrEKYBIgJFDQAgAhDDASEAAkAgAUEBayIEIAJxRQRAIAAhAQwBCyACIARqQQAgAWtxEMMBIQJBEEEIELMBIQQgABC3ASACQQAgASACIABrIARLG2oiASAAayICayEEIAAQugFFBEAgASAEELsBIAAgAhC7ASAAIAIQpwEMAQsgACgCACEAIAEgBDYCBCABIAAgAmo2AgALIAEQugENASABELcBIgJBEEEIELMBIANqTQ0BIAEgAxDAASEAIAEgAxC7ASAAIAIgA2siAxC7ASAAIAMQpwEMAQsgBA8LIAEQwgEgARC6ARoL7SECD38BfiMAQRBrIgskAAJAAkAgAEH1AU8EQEEIQQgQswEhBkEUQQgQswEhBUEQQQgQswEhAUEAQRBBCBCzAUECdGsiAkGAgHwgASAFIAZqamtBd3FBA2siASABIAJLGyAATQ0CIABBBGpBCBCzASEEQdD8wAAoAgBFDQFBACAEayEDAkACQAJ/QQAgBEGAAkkNABpBHyAEQf///wdLDQAaIARB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Gg8LDwsgAkF4cUHU/MAAaiEBAn9BzPzAACgCACIDQQEgAkEDdnQiAnEEQCABKAIIDAELQcz8wAAgAiADcjYCACABCyEDIAEgADYCCCADIAA2AgwgACABNgIMIAAgAzYCCAtpACMAQTBrIgEkAEG0/MAALQAABEAgAUEcakEBNgIAIAFCAjcCDCABQcjXwAA2AgggAUHKADYCJCABIAA2AiwgASABQSBqNgIYIAEgAUEsajYCICABQQhqQfDXwAAQ1AEACyABQTBqJAAL3gEBA38jAEEgayIAJAACQEHI/MAAKAIAQf////8HcQRAQZCAwQAoAgANAQtBvPzAACgCAEG8/MAAQX82AgBFBEBBxPzAACgCACEBQcT8wABBuJvAADYCAEHA/MAAKAIAIQJBwPzAAEEBNgIAQbz8wABBADYCAAJAIAFFDQAgAiABKAIAEQYAIAFBBGooAgBFDQAgAUEIaigCABogAhCrAQsgAEEgaiQADwsACyAAQRxqQQA2AgAgAEH41sAANgIYIABCATcCDCAAQbTYwAA2AgggAEEIakHY2MAAENQBAAuLAgIEfwF+IwBBMGsiAiQAIAFBBGohBCABKAIERQRAIAEoAgAhAyACQRBqIgVBADYCACACQgE3AwggAiACQQhqNgIUIAJBKGogA0EQaikCADcDACACQSBqIANBCGopAgA3AwAgAiADKQIANwMYIAJBFGpB4NbAACACQRhqEN4BGiAEQQhqIAUoAgA2AgAgBCACKQMINwIACyACQSBqIgMgBEEIaigCADYCACABQQxqQQA2AgAgBCkCACEGIAFCATcCBCACIAY3AxhBDEEEED0iAUUEQEEMQQQQzgEACyABIAIpAxg3AgAgAUEIaiADKAIANgIAIABBiNnAADYCBCAAIAE2AgAgAkEwaiQAC60BAQN/IwBBMGsiAiQAIAFBBGohAyABKAIERQRAIAEoAgAhASACQRBqIgRBADYCACACQgE3AwggAiACQQhqNgIUIAJBKGogAUEQaikCADcDACACQSBqIAFBCGopAgA3AwAgAiABKQIANwMYIAJBFGpB4NbAACACQRhqEN4BGiADQQhqIAQoAgA2AgAgAyACKQMINwIACyAAQYjZwAA2AgQgACADNgIAIAJBMGokAAtFAQJ/IAEoAgQhAiABKAIAIQNBCEEEED0iAUUE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BnZBwAFyOgAMQQIMAgsgACgCCCIDIAAoAgRGBEAgACADEIMBIAAoAgghAwsgACADQQFqNgIIIAAoAgAgA2ogAToAAAwCCyABQYCABE8EQCACIAFBP3FBgAFyOgAPIAIgAUEGdkE/cUGAAXI6AA4gAiABQQx2QT9xQYABcjoADSACIAFBEnZBB3FB8AFyOgAMQQQMAQsgAiABQT9xQYABcjoADiACIAFBDHZB4AFyOgAMIAIgAUEGdkE/cUGAAXI6AA1BAwshASABIABBBGooAgAgACgCCCIDa0sEQCAAIAMgARCEASAAKAIIIQMLIAAoAgAgA2ogAkEMaiABEIsCGiAAIAEgA2o2AggLIAJBEGokAEEAC1oBAX8jAEEgayICJAAgAiAAKAIANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpB0NnAACACQQhqEN4BIAJBIGokAAtLAQF/IAIgACgCACIAQQRqKAIAIAAoAggiA2tLBEAgACADIAIQhAEgACgCCCEDCyAAKAIAIANqIAEgAhCLAhogACACIANqNgIIQQALGgAgACABQbj8wAAoAgAiAEHSACAAGxECAAALQAEBfyMAQSBrIgAkACAAQRxqQQA2AgAgAEH42cAANgIYIABCATcCDCAAQajawAA2AgggAEEIakGw2sAAENQBAAvpAwEGfyMAQTBrIgUkAAJAAkACQAJAAkAgASgCBCIDBEAgASgCACEHIANBAWtB/////wFxIgNBAWoiBkEHcSEEAn8gA0EHSQRAQQAhAyAHDAELIAdBPGohAiAGQfj///8DcSEGQQAhAwNAIAIoAgAgAkEIaygCACACQRBrKAIAIAJBGGsoAgAgAkEgaygCACACQShrKAIAIAJBMGsoAgAgAkE4aygCACADampqampqamohAyACQUBrIQIgBkEIayIGDQALIAJBPGsLIQIgBARAIAJBBGohAgNAIAIoAgAgA2ohAyACQQhqIQIgBEEBayIEDQALCyABQRRqKAIADQEgAyEEDAMLQQAhAyABQRRqKAIADQFBASECDAQLIAcoAgQNACADQRBJDQILIAMgA2oiBCADSQ0BCyAERQ0AAkAgBEF/SgRAIARBARA9IgJFDQEgBCEDDAMLEM8BAAsgBEEBEM4BAAtBASECQQAhAwsgAEEANgIIIAAgAzYCBCAAIAI2AgAgBSAANgIMIAVBIGogAUEQaikCADcDACAFQRhqIAFBCGopAgA3AwAgBSABKQIANwMQIAVBDGpB0NnAACAFQRBqEN4BBEBBwNrAAEEzIAVBKGpB9NrAAEGc28AAEOkBAAsgBUEwaiQAC2cBAn8gASgCACEDAkACQAJAIAFBCGooAgAiAUUEQEEBIQIMAQsgAUF/TA0BIAFBARA9IgJFDQILIAIgAyABEIsCIQIgACABNgIIIAAgATYCBCAAIAI2AgAPCxDPAQALIAFBARDOAQALUwEBfyMAQRBrIgIkACACIAA2AgggAiAAQQxqNgIMIAFBzNzAAEENQbDcwABBBSACQQhqQaDcwABBtdzAAEEFIAJBDGpBvNzAABD7ASACQRBqJAALDgAgACgCABoDQAwACwAL4QIBAn8jAEEgayICJAAgAkEBOgAYIAIgATYCFCACIAA2AhAgAkHQ38AANgIMIAJB3NzAADYCCCMAQRBrIgEkAAJAIAJBCGoiACgCDCICBEAgACgCCCIDRQ0BIAEgAjYCCCABIAA2AgQgASADNgIAIwBBEGsiACQAIABBCGogAUEIaigCADYCACAAIAEpAgA3AwAjAEEQayIBJAAgACgCACICQRRqKAIAIQMCQAJ/AkACQCACKAIEDgIAAQMLIAMNAkEAIQJB+NbAAAwBCyADDQEgAigCACIDKAIEIQIgAygCAAshAyABIAI2AgQgASADNgIAIAFBvNnAACAAKAIEIgEoAgggACgCCCABLQAQELIBAAsgAUEANgIEIAEgAjYCACABQajZwAAgACgCBCIBKAIIIAAoAgggAS0AEBCyAQALQfjWwABBK0H42MAAENkBAAtB+NbAAEErQejYwAAQ2QEAC28BAX8jAEEwayIDJAAgAyABNgIEIAMgADYCACADQRxqQQI2AgAgA0EsakHKADYCACADQgI3AgwgA0H83sAANgIIIANBygA2AiQgAyADQSBqNgIYIAMgAzYCKCADIANBBGo2AiAgA0EIaiACENQBAAtvAQF/IwBBMGsiAyQAIAMgATYCBCADIAA2AgAgA0EcakECNgIAIANBLGpBygA2AgAgA0ICNwIMIANBkOTAADYCCCADQcoANgIkIAMgA0EgajYCGCADIANBBGo2AiggAyADNgIgIANB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AAgAAAAUAAAAL1VzZXJzL2RlYXJrYW5lLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL2Nvc213YXNtLXN0ZC0xLjEuOS9zcmMvZXhwb3J0cy5ycwAAAAABEABhAAAAjQAAAA0AAAAAARAAYQAAAG8AAAANAAAAAAEQAGEAAADqAAAADQAAAHdhc21jdXN0b21iYW5rQmFua01zZ2J1cm5zZW5kdG9fYWRkcmVzc1dhc21Nc2djbGVhcl9hZG1pbmNvbnRyYWN0X2FkZHJ1cGRhdGVfYWRtaW5hZG1pbm1pZ3JhdGVuZXdfY29kZV9pZG1zZ2luc3RhbnRpYXRlY29kZV9pZGxhYmVsZXhlY3V0ZVN1Yk1zZ2dhc19saW1pdFJlcGx5T25uZXZlcnN1Y2Nlc3NlcnJvcmFsd2F5c29rRW1wdHlFdmVudHR5cGVhdHRyaWJ1dGVzQXR0cmlidXRla2V5dmFsdWVSZXNwb25zZWV2ZW50c0NvbnRyYWN0VmVyc2lvbnZlcnNpb25jb250cmFjdF9pbmZvABUAAAAMAAAABAAAABYAAAAXAAAAGAAAAGEgRGlzcGxheSBpbXBsZW1lbnRhdGlvbiByZXR1cm5lZCBhbiBlcnJvciB1bmV4cGVjdGVkbHkABQAAAAAAAAABAAAAGQAAAC9ydXN0Yy84OTdlMzc1NTNiYmE4YjQyNzUxYzY3NjU4OTY3ODg5ZDExZWNkMTIwL2xpYnJhcnkvYWxsb2Mvc3JjL3N0cmluZy5ycwAIAxAASwAAAM4JAAAJAAAAY3dfY291bnRlcjo6bXNnOjpFeGVjdXRlTXNnY3dfY291bnRlcjo6bXNnOjpHZXRDb3VudFJlc3BvbnNlY3dfY291bnRlcjo6bXNnOjpRdWVyeU1zZ2Nvc213YXNtX3N0ZDo6cmVzdWx0czo6Y29udHJhY3RfcmVzdWx0OjpDb250cmFjdFJlc3VsdDxjb3Ntd2FzbV9zdGQ6OnJlc3VsdHM6OnJlc3BvbnNlOjpSZXNwb25zZT5jb3Ntd2FzbV9zdGQ6OnJlc3VsdHM6OmNvbnRyYWN0X3Jlc3VsdDo6Q29udHJhY3RSZXN1bHQ8Y29zbXdhc21fc3RkOjpiaW5hcnk6OkJpbmFyeT5jb3Ntd2FzbV9zdGQ6OnR5cGVzOjpNZXNzYWdlSW5mb2Nvc213YXNtX3N0ZDo6dHlwZXM6OkVudmN3X2NvdW50ZXI6OnN0YXRlOjpTdGF0ZWN3X2NvdW50ZXI6Om1zZzo6SW5zdGFudGlhdGVNc2djdzI6OkNvbnRyYWN0VmVyc2lvbgAAAAUAAAAEAAAABAAAABoAAAAbAAAAHAAAAG1pc3NpbmcgZmllbGQgYGAMBRAADwAAABsFEAABAAAAdW5rbm93biBmaWVsZCBgYCwgZXhwZWN0ZWQgACwFEAAPAAAAOwUQAAwAAABgLCB0aGVyZSBhcmUgbm8gZmllbGRzAAAsBRAADwAAAFgFEAAWAAAAZHVwbGljYXRlIGZpZWxkIGAAAACABRAAEQAAABsFEAABAAAAdW5rbm93biB2YXJpYW50IGAAAACkBRAAEQAAADsFEAAMAAAAaW52YWxpZCBVaW50NjQgJycgLSDIBRAAEAAAANgFEAAEAAAAaW52YWxpZCBVaW50MTI4ICcAAADsBRAAEQAAANgFEAAEAAAAdWxsc3RhdGVhY3Rpb25pbmNyZW1lbnRzcmMvY29udHJhY3QucnMAACcGEAAPAAAANAAAAA0AAAByZXNldGNyYXRlcy5pbzpjdy1jb3VudGVyMC4xLjBtZXRob2Rvd25lcmNvdW50VW5hdXRob3JpemVkAAB2BhAADAAAAAwFEAAAAAAAcQYQAAUAAAAeBhAACQAAAEgGEAAFAAAAZ2V0X2NvdW50AAAArAYQAAkAAABHZXRDb3VudFJlc3BvbnNlU3RhdGUvcnVzdGMvODk3ZTM3NTUzYmJhOGI0Mjc1MWM2NzY1ODk2Nzg4OWQxMWVjZDEyMC9saWJyYXJ5L2NvcmUvc3JjL2l0ZXIvYWRhcHRlcnMvZW51bWVyYXRlLnJz1QYQAFsAAAAwAAAACQAAAGF0dGVtcHQgdG8gYWRkIHdpdGggb3ZlcmZsb3cAAAAAYXR0ZW1wdCB0byBtdWx0aXBseSB3aXRoIG92ZXJmbG93AAAAKAAAAAgAAAAEAAAAKQAAACoAAAArAAAADAAAAAQAAAAsAAAALQAAAC4AAABhIERpc3BsYXkgaW1wbGVtZW50YXRpb24gcmV0dXJuZWQgYW4gZXJyb3IgdW5leHBlY3RlZGx5ACgAAAAAAAAAAQAAABkAAAAvcnVzdGMvODk3ZTM3NTUzYmJhOGI0Mjc1MWM2NzY1ODk2Nzg4OWQxMWVjZDEyMC9saWJyYXJ5L2FsbG9jL3NyYy9zdHJpbmcucnMA+AcQAEsAAADOCQAACQAAAGNvc213YXNtX3N0ZDo6cmVzdWx0czo6c3lzdGVtX3Jlc3VsdDo6U3lzdGVtUmVzdWx0PGNvc213YXNtX3N0ZDo6cmVzdWx0czo6Y29udHJhY3RfcmVzdWx0OjpDb250cmFjdFJlc3VsdDxjb3Ntd2FzbV9zdGQ6OmJpbmFyeTo6QmluYXJ5Pj4oAAAABAAAAAQAAAAvAAAAMAAAADEAAABpbnRlcm5hbCBlcnJvcjogZW50ZXJlZCB1bnJlYWNoYWJsZSBjb2RlOiAAAPQIEAAqAAAAL3J1c3RjLzg5N2UzNzU1M2JiYThiNDI3NTFjNjc2NTg5Njc4ODlkMTFlY2QxMjAvbGlicmFyeS9jb3JlL3NyYy9pdGVyL3RyYWl0cy9hY2N1bS5ycwAAACgJEABVAAAAjQAAAAEAAABtaXNzaW5nIGZpZWxkIGBgkAkQAA8AAACfCRAAAQAAAGR1cGxpY2F0ZSBmaWVsZCBgAAAAsAkQABEAAACfCRAAAQAAAHVua25vd24gdmFyaWFudCBgYCwgZXhwZWN0ZWQgAAAA1AkQABEAAADlCRAADAAAACgAAAAEAAAABAAAADIAAAAvVXNlcnMvZGVhcmthbmUvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvYmFzZTY0LTAuMTMuMC9zcmMvZGVjb2RlLnJzABQKEABbAAAAbgAAAC8AAABhdHRlbXB0IHRvIHN1YnRyYWN0IHdpdGggb3ZlcmZsb3cAAAAUChAAWwAAAAMBAAA3AAAAFAoQAFsAAAADAQAAJAAAABQKEABbAAAABAEAACkAAAAUChAAWwAAACEBAAARAAAAFAoQAFsAAAAqAQAAKQAAABQKEABbAAAAKgEAABYAAAAUChAAWwAAAC4BAAApAAAAFAoQAFsAAAAuAQAAKAAAABQKEABbAAAALQEAABoAAAAUChAAWwAAADMBAAARAAAAFAoQAFsAAABBAQAADgAAABQKEABbAAAARAEAACcAAAAUChAAWwAAAEQBAAASAAAAFAoQAFsAAABHAQAACQAAABQKEABbAAAAWAEAABMAAAAUChAAWwAAAGYBAAApAAAAFAoQAFsAAAB4AQAADQAAABQKEABbAAAAggEAABEAAAAUChAAWwAAAIoBAAAVAAAAFAoQAFsAAACOAQAAMQAAAEltcG9zc2libGU6IG11c3Qgb25seSBoYXZlIDAgdG8gOCBpbnB1dCBieXRlcyBpbiBsYXN0IGNodW5rLCB3aXRoIG5vIGludmFsaWQgbGVuZ3Roc+QLEABUAAAAFAoQAFsAAACdAQAADgAAABQKEABbAAAAqAEAAA0AAAAUChAAWwAAALEBAAAJAAAAT3ZlcmZsb3cgd2hlbiBjYWxjdWxhdGluZyBvdXRwdXQgYnVmZmVyIGxlbmd0aAAAFAoQAFsAAACTAAAAIAAAABQKEABbAAAAJwIAAAUAAABJbnZhbGlkIFVURjgrAAAAFAAAAAQAAAAzAAAAL1VzZXJzL2RlYXJrYW5lLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL2Jhc2U2NC0wLjEzLjAvc3JjL2VuY29kZS5ycwDcDBAAWwAAADQAAAAFAAAAaW50ZWdlciBvdmVyZmxvdyB3aGVuIGNhbGN1bGF0aW5nIGJ1ZmZlciBzaXplAAAA3AwQAFsAAAAvAAAAEQAAACgAAAAIAAAABAAAADQAAAD0CBAAAAAAAGludmFsaWQgYmFzZTY0OiCgDRAAEAAAACgAAAAAAAAAAQAAADUAAAA2AAAANgAAAC9Vc2Vycy9kZWFya2FuZS8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy9jb3Ntd2FzbS1zdGQtMS4xLjkvc3JjL3NlY3Rpb25zLnJzAADQDRAAYgAAABoAAAAQAAAA0A0QAGIAAAAaAAAABQAAANANEABiAAAAOQAAABgAAABDYW5ub3QgcmVhZCBzZWN0aW9uIGxlbmd0aAAAZA4QABoAAADQDRAAYgAAADcAAAAJAAAAVEw7RFI6IFZhbHVlIG11c3Qgbm90IGJlIGVtcHR5IGluIFN0b3JhZ2U6OnNldCBidXQgaW4gbW9zdCBjYXNlcyB5b3UgY2FuIHVzZSBTdG9yYWdlOjpyZW1vdmUgaW5zdGVhZC4gTG9uZyBzdG9yeTogR2V0dGluZyBlbXB0eSB2YWx1ZXMgZnJvbSBzdG9yYWdlIGlzIG5vdCB3ZWxsIHN1cHBvcnRlZCBhdCB0aGUgbW9tZW50LiBTb21lIG9mIG91ciBpbnRlcm5hbCBpbnRlcmZhY2VzIGNhbm5vdCBkaWZmZXJlbnRpYXRlIGJldHdlZW4gYSBub24tZXhpc3RlbnQga2V5IGFuZCBhbiBlbXB0eSB2YWx1ZS4gUmlnaHQgbm93LCB5b3UgY2Fubm90IHJlbHkgb24gdGhlIGJlaGF2aW91ciBvZiBlbXB0eSB2YWx1ZXMuIFRvIHByb3RlY3QgeW91IGZyb20gdHJvdWJsZSBsYXRlciBvbiwgd2Ugc3RvcCBoZXJlLiBTb3JyeSBmb3IgdGhlIGluY29udmVuaWVuY2UhIFdlIGhpZ2hseSB3ZWxjb21lIHlvdSB0byBjb250cmlidXRlIHRvIENvc21XYXNtLCBtYWtpbmcgdGhpcyBtb3JlIHNvbGlkIG9uZSB3YXkgb3IgdGhlIG90aGVyLpgOEAAIAgAAL1VzZXJzL2RlYXJrYW5lLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL2Nvc213YXNtLXN0ZC0xLjEuOS9zcmMvaW1wb3J0cy5ycwAAAKgQEABhAAAAawAAAA0AAAAoAAAABAAAAAQAAAA3AAAAOAAAADkAAAA6AAAAaW5wdXQgdG9vIGxvbmcgZm9yIGFkZHJfdmFsaWRhdGVhZGRyX3ZhbGlkYXRlIGVycm9yZWQ6IABYERAAFwAAAGlucHV0IHRvbyBsb25nIGZvciBhZGRyX2Nhbm9uaWNhbGl6ZWFkZHJfY2Fub25pY2FsaXplIGVycm9yZWQ6IACcERAAGwAAAGFkZHJfaHVtYW5pemUgZXJyb3JlZDogAMAREAAXAAAATWVzc2FnZVRvb0xvbmcgbXVzdCBub3QgaGFwcGVuLiBUaGlzIGlzIGEgYnVnIGluIHRoZSBWTS7gERAAOAAAAKgQEABhAAAACAEAABIAAACoEBAAYQAAACUBAAASAAAASW52YWxpZEhhc2hGb3JtYXQgbXVzdCBub3QgaGFwcGVuLiBUaGlzIGlzIGEgYnVnIGluIHRoZSBWTS4AQBIQADsAAACoEBAAYQAAAD8BAAASAAAARXJyb3IgY29kZSAyIHVudXNlZCBzaW5jZSBDb3NtV2FzbSAwLjE1LiBUaGlzIGlzIGEgYnVnIGluIHRoZSBWTS4AAACUEhAAQQAAAKgQEABhAAAAPgEAABIAAACoEBAAYQAAAF8BAAASAAAAqBAQAGEAAABeAQAAEgAAAFJlZ2lvbiBwb2ludGVyIGlzIG51bGwAABATEAAWAAAAL1VzZXJzL2RlYXJrYW5lLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL2Nvc213YXNtLXN0ZC0xLjEuOS9zcmMvbWVtb3J5LnJzMBMQAGAAAAA5AAAABQAAAFJlZ2lvbiBzdGFydHMgYXQgbnVsbCBwb2ludGVyAAAAoBMQAB0AAAAwExAAYAAAAD8AAAAFAAAAVW5rbm93biBlcnJvcjogANgTEAAPAAAASW52YWxpZCByZWNvdmVyeSBwYXJhbWV0ZXIuIFN1cHBvcnRlZCB2YWx1ZXM6IDAgYW5kIDEuAADwExAANgAAAEludmFsaWQgc2lnbmF0dXJlIGZvcm1hdDAUEAAYAAAASW52YWxpZCBoYXNoIGZvcm1hdABQFBAAEwAAAFVua25vd25FcnJlcnJvcl9jb2RlKAAAAAQAAAAEAAAAOwAAAEludmFsaWRSZWNvdmVyeVBhcmFtSW52YWxpZFNpZ25hdHVyZUZvcm1hdEludmFsaWRIYXNoRm9ybWF0Q29udmVyc2lvbiBlcnJvcjogAAAAyxQQABIAAABEaXZpZGUgYnkgemVybzog6BQQABAAAABPdmVyZmxvdzogAAAAFRAACgAAAEVycm9yIHNlcmlhbGl6aW5nIHR5cGUgOiAAAAAUFRAAFwAAACsVEAACAAAARXJyb3IgcGFyc2luZyBpbnRvIHR5cGUgQBUQABgAAAArFRAAAgAAACBub3QgZm91bmQAAPQIEAAAAAAAaBUQAAoAAABDYW5ub3QgZGVjb2RlIFVURjggYnl0ZXMgaW50byBzdHJpbmc6IAAAhBUQACYAAABJbnZhbGlkIGhleCBzdHJpbmc6ILQVEAAUAAAASW52YWxpZCBkYXRhIHNpemU6IGV4cGVjdGVkPSBhY3R1YWw90BUQABwAAADsFRAACAAAAEludmFsaWQgQmFzZTY0IHN0cmluZzogAAQWEAAXAAAAR2VuZXJpYyBlcnJvcjogACQWEAAPAAAAUmVjb3ZlciBwdWJrZXkgZXJyb3I6IAAAPBYQABYAAABWZXJpZmljYXRpb24gZXJyb3I6IFwWEAAUAAAAQ29udmVyc2lvbk92ZXJmbG93c291cmNlKAAAAAQAAAAEAAAAPAAAAERpdmlkZUJ5WmVybygAAAAEAAAABAAAAD0AAABPdmVyZmxvdygAAAAEAAAABAAAAD4AAABTZXJpYWxpemVFcnJzb3VyY2VfdHlwZW1zZ1BhcnNlRXJydGFyZ2V0X3R5cGVOb3RGb3VuZGtpbmRJbnZhbGlkVXRmOEludmFsaWRIZXhJbnZhbGlkRGF0YVNpemVleHBlY3RlZAAAACgAAAAEAAAABAAAAD8AAABhY3R1YWxJbnZhbGlkQmFzZTY0R2VuZXJpY0VyclJlY292ZXJQdWJrZXlFcnIAAAAoAAAABAAAAAQAAABAAAAAVmVyaWZpY2F0aW9uRXJyACgAAAAEAAAABAAAAEEAAABTaGxTaHJQb3dNdWxTdWJBZGRDYW5ub3QgIHdpdGggIGFuZCC+FxAABwAAAMUXEAAGAAAAyxcQAAUAAABPdmVyZmxvd0Vycm9yb3BlcmF0aW9uAAAoAAAABAAAAAQAAAAdAAAAb3BlcmFuZDFvcGVyYW5kMkNvbnZlcnNpb25PdmVyZmxvd0Vycm9yACgAAAAEAAAABAAAAEIAAAB2YWx1ZUNhbm5vdCBkZXZpZGUgIGJ5IHplcm8ATRgQAA4AAABbGBAACAAAAERpdmlkZUJ5WmVyb0Vycm9yb3BlcmFuZGludmFsaWRfcmVxdWVzdGludmFsaWRfcmVzcG9uc2Vub19zdWNoX2NvbnRyYWN0dW5rbm93bnVuc3VwcG9ydGVkX3JlcXVlc3QAAACMGBAADwAAAJsYEAAQAAAAqxgQABAAAAC7GBAABwAAAMIYEAATAAAAYWRkcmVycm9ycmVzcG9uc2VyZXF1ZXN0SW52YWxpZCBwdWJsaWMga2V5IGZvcm1hdAAAABgZEAAZAAAAR2VuZXJpYyBlcnJvcgAAADwZEAANAAAAQmF0Y2ggZXJyb3IAVBkQAAsAAABJbnZhbGlkUHVia2V5Rm9ybWF0QmF0Y2hFcnJvawAAAIMZEAACAAAABBkQAAUAAAC7FxAAuBcQALUXEACyFxAArxcQAKwXEABFAAAACAAAAAQAAABGAAAARwAAAEUAAAAIAAAABAAAAEgAAADEGRAAAAAAAEpTT04gaGFzIGEgY29tbWEgYWZ0ZXIgdGhlIGxhc3QgdmFsdWUgaW4gYW4gYXJyYXkgb3IgbWFwLkpTT04gaGFzIG5vbi13aGl0ZXNwYWNlIHRyYWlsaW5nIGNoYXJhY3RlcnMgYWZ0ZXIgdGhlIHZhbHVlLkZvdW5kIGEgbG9uZSBzdXJyb2dhdGUsIHdoaWNoIGNhbiBleGlzdCBpbiBKU09OIGJ1dCBjYW5ub3QgYmUgZW5jb2RlZCB0byBVVEYtOC5PYmplY3Qga2V5IGlzIG5vdCBhIHN0cmluZy5JbnZhbGlkIHVuaWNvZGUgY29kZSBwb2ludC5JbnZhbGlkIHR5cGVJbnZhbGlkIG51bWJlci5JbnZhbGlkIGVzY2FwZSBzZXF1ZW5jZS5FeHBlY3RlZCB0aGlzIGNoYXJhY3RlciB0byBzdGFydCBhIEpTT04gdmFsdWUuRXhwZWN0ZWQgdG8gcGFyc2UgZWl0aGVyIGEgYHRydWVgLCBgZmFsc2VgLCBvciBhIGBudWxsYC5FeHBlY3RlZCB0aGlzIGNoYXJhY3RlciB0byBiZSBlaXRoZXIgYSBgJywnYCBvciBhIGAnfSdgLkV4cGVjdGVkIGEgbG93IHN1cnJvZ2F0ZSAoREMwMOKAk0RGRkYpLkV4cGVjdGVkIHRoaXMgY2hhcmFjdGVyIHRvIGJlIGVpdGhlciBhIGAnLCdgIG9yYSBgJ10nYC5FeHBlY3RlZCBhIGhpZ2ggc3Vycm9nYXRlIChEODAw4oCTREJGRikuRXhwZWN0ZWQgdGhpcyBjaGFyYWN0ZXIgdG8gYmUgYSBgJzonYC5FT0Ygd2hpbGUgcGFyc2luZyBhIEpTT04gdmFsdWUuRU9GIHdoaWxlIHBhcnNpbmcgYSBzdHJpbmcuRU9GIHdoaWxlIHBhcnNpbmcgYW4gb2JqZWN0LkVPRiB3aGlsZSBwYXJzaW5nIGEgbGlzdC5Db250cm9sIGNoYXJhY3RlciBmb3VuZCBpbiBzdHJpbmcuL1VzZXJzL2RlYXJrYW5lLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL3NlcmRlLWpzb24td2FzbS0wLjQuMS9zcmMvZGUvdW5lc2NhcGUucnPkHBAAaAAAACUAAAAVAAAAAAAAAGF0dGVtcHQgdG8gYWRkIHdpdGggb3ZlcmZsb3fkHBAAaAAAADMAAAApAAAAAAAAAGF0dGVtcHQgdG8gc3VidHJhY3Qgd2l0aCBvdmVyZmxvd05vbi1oZXggQVNDSUkgY2hhcmFjdGVyIGZvdW5kAADkHBAAaAAAAJkAAAAOAAAAL1VzZXJzL2RlYXJrYW5lLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL3NlcmRlLWpzb24td2FzbS0wLjQuMS9zcmMvZGUvbW9kLnJzAOAdEABjAAAAJAAAAAkAAADgHRAAYwAAAH0AAAAiAAAA4B0QAGMAAACBAAAALAAAAEJ1ZmZlciBpcyBmdWxsAAB0HhAADgAAAC9Vc2Vycy9kZWFya2FuZS8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy9zZXJkZS1qc29uLXdhc20tMC40LjEvc3JjL3Nlci9tb2QucnOMHhAAZAAAALUAAAAJAAAAjB4QAGQAAADXAAAACQAAAGludGVybmFsIGVycm9yOiBlbnRlcmVkIHVucmVhY2hhYmxlIGNvZGU6IAAAEB8QACoAQdC+wAALIWF0dGVtcHQgdG8gc3VidHJhY3Qgd2l0aCBvdmVyZmxvdwBBgL/AAAv0JmF0dGVtcHQgdG8gYWRkIHdpdGggb3ZlcmZsb3cvVXNlcnMvZGVhcmthbmUvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvYmFzZTY0LTAuMTMuMC9zcmMvZW5jb2RlLnJzAJwfEABbAAAAkgAAACcAAAB1c2l6ZSBvdmVyZmxvdyB3aGVuIGNhbGN1bGF0aW5nIGI2NCBsZW5ndGgAAJwfEABbAAAAlwAAABkAAACcHxAAWwAAALYAAAAgAAAAnB8QAFsAAAC3AAAAOgAAAJwfEABbAAAAtwAAACUAAACcHxAAWwAAAPcAAAAYAAAAnB8QAFsAAAD8AAAALwAAAJwfEABbAAAA/AAAABwAAACcHxAAWwAAAP0AAAA2AAAAnB8QAFsAAAD9AAAAIQAAAJwfEABbAAAAEwEAAC4AAACcHxAAWwAAABMBAAAJAAAAnB8QAFsAAAAUAQAACQAAAJwfEABbAAAACwEAAC4AAACcHxAAWwAAAAsBAAAJAAAAnB8QAFsAAAANAQAADwAAAJwfEABbAAAADAEAAAkAAACcHxAAWwAAAA8BAAAJAAAAnB8QAFsAAAARAQAACQAAAEltcG9zc2libGUgcmVtYWluZGVyVCEQABQAAACcHxAAWwAAACoBAAAWAAAAnB8QAFsAAAA7AQAACQAAAEludmFsaWQgbGFzdCBzeW1ib2wgLCBvZmZzZXQgLgAAkCEQABQAAACkIRAACQAAAK0hEAABAAAARW5jb2RlZCB0ZXh0IGNhbm5vdCBoYXZlIGEgNi1iaXQgcmVtYWluZGVyLgDIIRAAKwAAAEludmFsaWQgYnl0ZSAAAAD8IRAADQAAAKQhEAAJAAAArSEQAAEAAABPdmVyZmxvdyB3aGVuIGNhbGN1bGF0aW5nIG51bWJlciBvZiBjaHVua3MgaW4gaW5wdXQvVXNlcnMvZGVhcmthbmUvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvYmFzZTY0LTAuMTMuMC9zcmMvZGVjb2RlLnJzAABXIhAAWwAAALkAAAAFAAAAISIjJCUmJygpKissLTAxMjM0NTY3ODlAQUJDREVGR0hJSktMTU5QUVJTVFVWWFlaW2BhYmNkZWhpamtsbXBxckFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5KywuL0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Li8wMTIzNDU2Nzg5QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ekFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5LV9BQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSsv////////////////////////////////////////////AAECAwQFBgcICQoLDP//DQ4PEBESExQVFv///////xcYGRobHB0eHyAhIiMkJf8mJygpKiss/y0uLzD/////MTIzNDU2//83ODk6Ozz//z0+P/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8+P////zQ1Njc4OTo7PD3/////////AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBn///////8aGxwdHh8gISIjJCUmJygpKissLS4vMDEyM///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AAE2Nzg5Ojs8PT4//////////wIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRob////////HB0eHyAhIiMkJSYnKCkqKywtLi8wMTIzNDX//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wABAgMEBQYHCAkKC/////////8MDQ4PEBESExQVFhcYGRobHB0eHyAhIiMkJf///////yYnKCkqKywtLi8wMTIzNDU2Nzg5Ojs8PT4//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////z7//zQ1Njc4OTo7PD3/////////AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBn/////P/8aGxwdHh8gISIjJCUmJygpKissLS4vMDEyM///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Pv///z80NTY3ODk6Ozw9/////////wABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZ////////GhscHR4fICEiIyQlJicoKSorLC0uLzAxMjP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////BCQQAMQjEACEIxAARCMQAAQjEADEIhAARCkQAEQoEABEJxAARCYQAEQlEABEJBAATgAAAAgAAAAEAAAATwAAAFAAAABOAAAACAAAAAQAAABRAAAAYG9uZSBvZiCZKhAABwAAACwgAACoKhAAAgAAAJgqEAABAAAAmCoQAAEAAABgIG9yIGAAAJgqEAABAAAAxCoQAAYAAACYKhAAAQAAAC9Vc2Vycy9kZWFya2FuZS8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy9zZXJkZS0xLjAuMTUwL3NyYy9kZS9tb2QucnNleHBsaWNpdCBwYW5pYwAAAOQqEABbAAAA7QgAABIAAABTAAAABAAAAAQAAABUAAAAVQAAAFYAAABjYWxsZWQgYE9wdGlvbjo6dW53cmFwKClgIG9uIGEgYE5vbmVgIHZhbHVlbWVtb3J5IGFsbG9jYXRpb24gb2YgIGJ5dGVzIGZhaWxlZAoAAKMrEAAVAAAAuCsQAA4AAABsaWJyYXJ5L3N0ZC9zcmMvYWxsb2MucnPYKxAAGAAAAFUBAAAJAAAAY2Fubm90IG1vZGlmeSB0aGUgcGFuaWMgaG9vayBmcm9tIGEgcGFuaWNraW5nIHRocmVhZAAsEAA0AAAAbGlicmFyeS9zdGQvc3JjL3Bhbmlja2luZy5yczwsEAAcAAAAfQAAAAkAAAA8LBAAHAAAAEcCAAAPAAAAPCwQABwAAABGAgAADwAAAFcAAAAMAAAABAAAAFgAAABTAAAACAAAAAQAAABZAAAAWgAAABAAAAAEAAAAWwAAAFwAAABTAAAACAAAAAQAAABdAAAAXgAAAF8AAAAEAAAABAAAAGAAAABhAAAAYgAAAF8AAAAEAAAABAAAAGMAAABsaWJyYXJ5L2FsbG9jL3NyYy9yYXdfdmVjLnJzY2FwYWNpdHkgb3ZlcmZsb3cAAAAULRAAEQAAAPgsEAAcAAAABgIAAAUAAABhIGZvcm1hdHRpbmcgdHJhaXQgaW1wbGVtZW50YXRpb24gcmV0dXJuZWQgYW4gZXJyb3IAXwAAAAAAAAABAAAAGQAAAGxpYnJhcnkvYWxsb2Mvc3JjL2ZtdC5yc4QtEAAYAAAAZAIAAAkAAAApbGlicmFyeS9hbGxvYy9zcmMvdmVjL21vZC5ycykgc2hvdWxkIGJlIDw9IGxlbiAoaXMgYGF0YCBzcGxpdCBpbmRleCAoaXMgAAAA4C0QABUAAADJLRAAFwAAAKwtEAABAAAArS0QABwAAADLBwAADQAAAF8AAAAEAAAABAAAAGQAAABieXRlc2Vycm9yAABfAAAABAAAAAQAAABlAAAARnJvbVV0ZjhFcnJvcgAAAGNhbGxlZCBgT3B0aW9uOjp1bndyYXAoKWAgb24gYSBgTm9uZWAgdmFsdWVudW1iZXIgd291bGQgYmUgemVybyBmb3Igbm9uLXplcm8gdHlwZW51bWJlciB0b28gc21hbGwgdG8gZml0IGluIHRhcmdldCB0eXBlbnVtYmVyIHRvbyBsYXJnZSB0byBmaXQgaW4gdGFyZ2V0IHR5cGVpbnZhbGlkIGRpZ2l0IGZvdW5kIGluIHN0cmluZ2Nhbm5vdCBwYXJzZSBpbnRlZ2VyIGZyb20gZW1wdHkgc3RyaW5nKS4uAD0vEAACAAAAaW5kZXggb3V0IG9mIGJvdW5kczogdGhlIGxlbiBpcyAgYnV0IHRoZSBpbmRleCBpcyAAAEgvEAAgAAAAaC8QABIAAAA6AAAAXC4QAAAAAACMLxAAAQAAAIwvEAABAAAAcGFuaWNrZWQgYXQgJycsILQvEAABAAAAtS8QAAMAAABcLhAAAAAAAG0AAAAAAAAAAQAAAG4AAABgOiAAXC4QAAAAAADhLxAAAgAAAG0AAAAMAAAABAAAAG8AAABwAAAAcQAAACAgICAgewosCiwgIHsgfSB9KAooLApbAG0AAAAEAAAABAAAAHIAAABdbGlicmFyeS9jb3JlL3NyYy9mbXQvbnVtLnJzNTAQABsAAABlAAAAFAAAADB4MDAwMTAyMDMwNDA1MDYwNzA4MDkxMDExMTIxMzE0MTUxNjE3MTgxOTIwMjEyMjIzMjQyNTI2MjcyODI5MzAzMTMyMzMzNDM1MzYzNzM4Mzk0MDQxNDI0MzQ0NDU0NjQ3NDg0OTUwNTE1MjUzNTQ1NTU2NTc1ODU5NjA2MTYyNjM2NDY1NjY2NzY4Njk3MDcxNzI3Mzc0NzU3Njc3Nzg3OTgwODE4MjgzODQ4NTg2ODc4ODg5OTA5MTkyOTM5NDk1OTY5Nzk4OTlhc3NlcnRpb24gZmFpbGVkOiAqY3VyciA+IDE5AAA1MBAAGwAAAOUBAAAFAAAAbQAAAAQAAAAEAAAAcwAAAHQAAAB1AAAAbGlicmFyeS9jb3JlL3NyYy9mbXQvbW9kLnJzAHAxEAAbAAAAdAkAAB4AAABwMRAAGwAAAHsJAAAWAAAAbGlicmFyeS9jb3JlL3NyYy9zbGljZS9tZW1jaHIucnOsMRAAIAAAAGgAAAAnAAAAcmFuZ2Ugc3RhcnQgaW5kZXggIG91dCBvZiByYW5nZSBmb3Igc2xpY2Ugb2YgbGVuZ3RoINwxEAASAAAA7jEQACIAAAByYW5nZSBlbmQgaW5kZXggIDIQABAAAADuMRAA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"
}
{
 "id": 290,
 "creator": "inj1h3gepa4tszh66ee67he53jzmprsqc2l9npq3ty",
 "data_hash": "F8E7689E23AC0C9D53F44A8FD98C686C20B0140A8D76D600E2C546BFBBA7758D",
 "instantiate_permission": {
  "permission": "Everybody"
 },
 "data": "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Qf8BcQshBgJAAkACQCAEIAZyIgZB/wFxIgVBAkcEQCAGQQFxDQEgC0UNAiADQfACakG5gcAAQQcQGCARRQ0KDAkLIAsNCiADQdACakG5gcAAQQcQFiADKALQAkEVRgRAIAMoAtwCIRQgAygC2AIhESADKALUAiELDAsLIANB+AJqIANB2AJqKQMANwMAIAMgAykD0AI3A/ACDAkLIANB0AJqIA4QjgECQCADKALQAiIPQRVHBEAgFyAYKQIANwIAIBdBCGogGEEIaigCADYCACADIA82AoADDAELIANBgANqIA4QFyADKAKAA0EVRg0CCyADQfgCaiADQYgDaikDADcDACADIAMpA4ADNwPwAgwGCyADQdACaiAOEI4BIAMoAtACIgRBFUcNAiADQdACaiAOEBogAygC3AIhFCADKALYAiERIAMoAtQCIQsgAygC0AIiBEEVRw0JCyADQbABaiAOEJABIAMtALEBIQQgAy0AsAFBAXENAAsMAgsgAygC3AIhFCADKALYAiERIAMoAtQCIQsMBgsgC0H/AXEhC0EEIQQMBQsgAyAJNgL8AiADIAQ2AvgCIAMgBTYC9AIgAyABNgLwAgsgC0UgEUVyDQELIAsQqwELIAMoAvwCIRQgAygC+AIhESADKAL0AiELIAMoAvACIgRBFUcNAQsgA0HQAmogCBCNASADKALQAiIEQRVGDQIgAygC3AIhFCADKALYAiADKALUAiEBIBEEQCALEKsBCyERIAEhCwsgAyAUNgKkAiADIBE2AqACIAMgCzYCnAIgAyAENgKYAgwJCyAhQiiIpyEKICFCIIinIRUgIachGyAJIRYLIANBCGogCBCQASADLQAJIQEgAy0ACEEBcQ0AC0ECIQQMAwtBACENDAMLIANBoAJqIANB2AJqKQMANwMAIAMgAykD0AI3A5gCIBZFDQUgDRCrAQwFCyADIBQ2AsgCIAMpA8gCISAgA0GYAmogA0GIAmoQjQEgAygCmAIiAUEVRwRAIAMtAJ8CQRB0IQkgAy8AnQIgAykDoAIhICADLQCcAiEMIBYEQCANEKsBCyAJciECIBFFDQYgCxCrAQwGCyADQZgCaiADQYgCahCLASADKAKYAiIBQRVHBEAgAy0AnwJBEHQhCSADLwCdAiADKQOgAiEgIAMtAJwCIQwgFgRAIA0QqwELIAlyIQIg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aigCACIENgIAIAMgCykCACIMNwMwIAlBCGogBDYCACAJIAw3AgAMAQsgA0EgaiAHEBcgAygCICIFQRVGDQELIAMoAiwhCSADKAIoIQggAy0AJCEEIAMvACUgAy0AJ0EQdHIMBgsgAyAHEJABIAMtAAEhBSADLQAAQQFxDQALCyAEQf8BcSEEQQIhBQwCCyAKQRU2AgAMAwsgAygCTCEJIAYhBAsgBEEIdgsiBjsABSAKIAk2AAwgCiAINgAIIAogBDoABCAKIAU2AgAgCkEHaiAGQRB2OgAACyADQdAAaiQAIAIoAlAiBEEVRw0KIAJB0ABqIAEQjQEgAigCUCIBQRVGBEAgAEEVNgIADAwLIAJByABqIAJB3ABqKAIAIgQ2AgAgAiACKQJUIgw3A0AgAEEMaiAENgIAIAAgDDcCBCAAIAE2AgAMCwsgAEELNgIADAoLIABBFTYCAAwJCyAAQQA7AAUgAEEENgIAIABBB2pBADoAAAwICyAAQQ42AgAMBwsgAikCVCEMIAAgAigCXDYCDCAAIAw3AgQgACABNgIADAYLIABBADsABSAAQQQ2AgAgAEEHakEAOgAADAULIABBDjYCAAwECyACQcgAaiACQdwAaigCACIBNgIAIAIgAikCVCIMNwNAIABBDGogATYCACAAIAw3AgQgACAENgIADAMLIABBADsABSAAQQQ2AgAgAEEHakEAOgAADAILIABBDjYCAAwBCyACQcgAaiACQdwAaigCACIBNgIAIAIgAikCVCIMNwNAIABBDGogATYCACAAIAw3AgQgACAENgIACyACQeAAaiQAC8UBAQF/IwBB8ABrIgMkACADIAI2AgwgAyABNgIIIANBJGpBATYCACADQgI3AhQgA0GUi8AANgIQIANBATYCLCADIANBKGo2AiAgAyADQQhqNgIoIANBADYCOCADQgE3AzAgA0FAayIBIANBMGpBqIXAABDyASADQRBqIAEQ6AEEQEHAhcAAQTcgA0HoAGpB+IXAAEHUhsAAEOkBAAsgACADKQMwNwIEIABBFDYCACAAQQxqIANBOGooAgA2AgAgA0HwAGokAAuFBAIFfwJ+IwBB4ABrIgMkACADIAI2AgwgAyABNgIIIwBBEGsiBiQAIANBEGoiBAJ/AkACQCACRQRAIARBADoAAQwBCwJAAkACQCABLQAAQStrDgMBAgACCyACQQFGDQMMAQsgAkEBayICRQ0CIAFBAWohAQsCQAJAAkAgAkERTwRAA0AgBiAIQgBCChCMAiABLQAAQTBrIgVBCUsNBiAGKQMIQgBSDQQgBikDACIJIAUgByAFQQpJG618IgggCVQNAyABQQFqIQEgBSEHIAJBAWsiAg0ACwwBCwNAIAEtAABBMGsiBUEJSw0FIAFBAWohASAFrSAIQgp+fCEIIAJBAWsiAg0ACwsgBCAINwMIQQAMBAsgBEECOgABDAELIARBAjoAAQtBAQwBCyAEQQE6AAFBAQs6AAAgBkEQaiQAAkAgAy0AEEUEQCAAIAMpAxg3AwggAEEVNgIADAELIAMgAy0AEToAJyADQcQAakECNgIAIANBATYCPCADIANBJ2o2AkAgAyADQQhqNgI4IANBAjYCXCADQgI3AkwgA0Hci8AANgJIIAMgA0E4ajYCWCADQShqIgEgA0HIAGoiAhDQASACQQRyIAEQ0QEgA0EUNgJIIAMoAiwEQCADKAIoEKsBCyAAIAMpA0g3AgAgAEEIaiADQdAAaikDADcCAAsgA0HgAGokAAvFAgIEfwF+IwBBIGsiAiQAIAJBCGogARCQAQJAAkACQAJAAkAgAi0ACEEBcQRAIAItAAlBIkcNASABEIoBIAJBEGogARCPASACKAIQIgFBFUcNAiACQRxqKAIAIQEgAkEYaigCACEDIAIoAhQiBEUEQAJAIAFFBEBBASEEDAELIAFBf0oiBUUNBSABIAUQPSIERQ0GCyAEIAMgARCLAiEDIABBDGogATYCACAAQQhqIAE2AgAgACADNgIEIABBFTYCAAwGCyAAIAQ2AgQgAEEVNgIAIABBDGogATYCACAAQQhqIAM2AgAMBQsgAEEAOwAFIABBBDYCACAAQQdqQQA6AAAMBAsgAEEONgIADAMLIAIpAhQhBiAAIAIoAhw2AgwgACAGNwIEIAAgATYCAAwCCxDPAQALIAEgBRDOAQALIAJBIGokAAv3AQEDfyMAQUBqIgQkAAJAAkACQAJAIAJFBEBBASEFDAELIAJBf0oiBkUNASACIAYQPSIFRQ0CCyAFIAEgAhCLAiEBIARBADYCCCAEQgE3AwAgBEEQaiIFIARBqIXAABDyASADIAUQhwENAiAAQQxqIAI2AgAgAEEIaiACNgIAIAAgATYCBCAAIAQpAwA3AhAgAEEINgIAIABBGGogBEEIaigCADYCAAJAIAMoAgBBFEkNACADQQhqKAIARQ0AIAMoAgQQqwELIARBQGskAA8LEM8BAAsgAiAGEM4BAAtBwIXAAEE3IARBOGpB+IXAAEHUhsAAEOkBAAvwIwIbfwN+IwBBkAJrIgMkACADQZABaiIHIAEgAhCJASADQYgBaiAHEJABQQAhAgJAAkACQCADLQCIAUEBcUUEQEEEIQEMAQsgAy0AiQFB+wBHBEBBDiEBDAELIANBkAFqIgEQigEgA0GAAWogARCIASADLQCEASEEIANB+ABqIAMoAoABIgwQkAECQAJAAkACQAJAIAMtAHhBAXFFBEBBAiECDAELIAMtAHkhAiAEQQFxIRcgA0HoAWpBBHIhESADQYACakEEciEUIANB8AFqIRggA0HUAWohHCADQfMBaiEdA0ACfwJAAkACfwJAIAJB/wFxIgRBLEcEQCAEQf0ARwRAIBcNAkEJDAMLIA1BgH5xIQJBAwwFC0EQIBcNARogDBCKASADQfAAaiAMEJABIAMtAHBBAXFFDQIgAy0AcSECCyACQf8BcSIEQSJGDQJBECAEQf0ARw0AGkETCyECIA0hCwwECyANQf8BcSELQQQhAgwDCyADQegAaiAMEJABIAMtAGhBAXFFBEBBBCECQQAhCwwDCyADLQBpQSJHBEBBDiECDAMLIAwQigEgA0HIAWogDBCPASADKALUASEFIAMoAtABIQQgAygCzAEhCyADKALIASICQRVHDQICQCALRQRAQQIhAgJAAkAgBUEFaw4CAQADCyAEQa6BwABBBhCNAkEAR0EBdCECDAILQQJBASAEQbSBwABBBRCNAhshAgwBC0ECIQICQAJAAkAgBUEFaw4CAQACCyALQa6BwABBBhCNAkEAR0EBdCECDAELQQJBASALQbSBwABBBRCNAhshAgsgBEUNACALEKsBC0EAIRcgDUGAfnELIQQCQAJAAkACQAJAAkACQCACIARyIg1B/wFxIgtBA0cEQCALDgIDAgELIBkhDQJAIBIiB0UEQCADQcgBakGugcAAQQYQFiADKALIAUEVRw0BIANB1AFqKAIAIRUgAygCzAEhByADQdABaigCACENCwJAIAZFBEAgA0HIAWpBtIHAAEEFEBYgAygCyAFBFUcNASADQdABaigCACEJIAMoAswBIQYgA0HUAWooAgAhCAsgAyAJNgKwASADIAY2AqwBIAMgFTYCqAEgAyANNgKkASADIAc2AqABIAdFDQ4gA0HIAWogA0GQAWoQjQEgAygCyAEiAUEVRg0FIAMoAswBIQsgAygC1AEhBCADKALQASEFIA0EQCAHEKsBCyAIBEAgCEEFdCEHIAZBEGohAgNAIAJBBGooAgAEQCACKAIAEKsBCyACQSBqIQIgB0EgayIHDQALCyALQQh2IQIgCUUNDyAGEKsBDA8LIBJFIQIgA0GsAWogA0HQAWopAwA3AgAgAyADKQPIATcCpAEgDUUNDCAHEKsBDAwLIANBrAFqIANB0AFqKQMANwIAIAMgAykDyAE3AqQBQQAhEiAGDQkMCgsgA0HIAWogDBCOAQJAIAMoAsgBIgFBFUcEQCADQfQBaiADQdQBaigCADYCACADIAMpAswBNwLsASADIAE2AugBDAELIANB6AFqIAwQFyADKALoAUEVRg0GCyADQawBaiADQfABaikDADcCACADIAMpA+gBNwKkASADQQA2AqABIAYNCAwJCyAGRQ0DIANBoAFqQQRyQbSBwABBBRAYIANBADYCoAEMBwsgEkUNASADQaABakEEckGugcAAQQYQGCADQQA2AqABIAYNBgwHCyADQcgBaiADQZABahCLASADKALIASIBQRVHBEAgAygC1AEhBCADKALQASEFIAMoAswBIQIgDQRAIAcQqwELIAgEQCAIQQV0IQcgBkEQaiELA0AgC0EEaigCAARAIAsoAgAQqwELIAtBIGohCyAHQSBrIgcNAAsLIAlFDQsgBhCrAQwLCyAAQRhqIAg2AgAgAEEUaiAJNgIAIABBEGogBjYCACAAQQxqIBU2AgAgAEEIaiANNgIAIAAgBzYCBCAAQQ02AgAMCwsgA0HIAWogDBCOAQJ/IAMoAsgBIgJBFUYEQCADQcgBaiAMEBogAygC1AEhFSADKALMASESIAMoAtABIgQgAygCyAEiAkEVRw0BGiAEIRkMAwsgAygC1AEhFSADKALMASESIAMoAtABCyEBIANBsAFqIBU2AgAgA0GsAWogATYCACADQagBaiASNgIAIAMgAjYCpAFBACESIANBADYCoAEgBg0EDAULIANByAFqIAwQjgECQAJAAkACQAJAAkACQAJAAkAgAygC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IAMgCEEBaiIINgLAASADQQhqIBAQkAEgAy0ACSECIAMtAAhBAXENCEEAIQYMEAsgA0EONgLsAQwECyADIA82AvgBIAMgCjYC9AEgAyAFNgLwASADIBY2AuwBDAMLIBggFCkCADcCACAYQQhqIBRBCGooAgA2AgAgAyAFNgLsAQwCCyADQcgBakGlgMAAQQYQGCADQQA2AtgBQQEhAgwJCyADQegBaiAOEI4BAkACQCADKALoASIFQRVHBEAgFCARKQIANwIAIBRBCGogEUEIaigCADYCACADIAU2AoACDAELIANBgAJqIA4QGiADKAKAAkEVRg0BCyADQdABaiADQYgCaikDADcDACADIAMpA4ACNwPIAQwKCyADKAKMAiEbIAMoAogCIRogAygChAIhAQwBCyADQdABaiARQQhqKQIANwMAIANBADYC2AEgAyARKQIANwPIAUEBIQIMBwsgA0EQaiAOEJABIAMtABEhBSADLQAQQQFxDQALCwwDCyAGQf8BcSEGQQQhCgwJCyADKALUASEIIAMoAtABIQkgAygCzAEhBgwICyADKAK8ASEJIAMoArgBIQYMBgsgAyAKNgLUASADIAk2AtABIAMgBDYCzAEgAyACNgLIAUEBIQILIBpFIAFFIAJFcnINACABEKsBCyADKQPIASIeQiCIpyEGIANB0AFqKQMAIh9CIIinIRAgHqchCiAfpyEJDAELQQAhBkEAIRALIAMoArgBIQcgCARAIAhBBXQhAUEAIQIDQCACIAdqIgRBFGooAgAiBQRAIARBEGooAgAQqwELIAEgAkEgaiICRw0ACwsgECEICyADKAK8AQRAIAcQqwELIApBFUcNAQsgA0HIAWogDBCMASADKALIASIKQRVGDQEgAygC1AEgAygC0AEhDSADKALMASAIBEAgCEEFdCEBIAZBEGohAgNAIAJBBGooAgAEQCACKAIAEKsBCyACQSBqIQIgAUEgayIBDQALCyAJBEAgBhCrAQshBiEIIA0hCQsgA0GwAWogCDYCACADQawBaiAJNgIAIANBqAFqIAY2AgAgAyAKNgKkAQwECyADIAwQkAEgAy0AASECIAMtAABBAXENAAtBAiECCyADQbABaiAFNgIAIANBrAFqIAQ2AgAgA0GoAWogCzYCACADIAI2AqQBIAZFDQELIAgEQCAIQQV0IQEgBkEQaiECA0AgAkEEaigCAARAIAIoAgAQqwELIAJBIGohAiABQSBrIgENAAsLQQEhAiAJRQ0BIAYQqwEMAQtBASECCyAZRSASRSACRXJyDQAgEhCrAQsgA0GoAWooAgAiC0EIdiECIANBsAFqKAIAIQQgA0GsAWooAgAhBSADKAKkASEBCyALQf8BcSACQQh0ciECCyADIAQ2AtQBIAMgBTYC0AEgAyACNgLMASADIAE2AsgBIABB7ojAAEEgIANByAFqEBsLIANBkAJqJAALgQUCBn8EfiMAQeAAayIDJAAgAyACNgIEIAMgATYCACMAQTBrIgQkACADQQhqIgUCfwJAAkAgAkUEQCAFQQA6AAEMAQsCQAJAAkAgAS0AAEEraw4DAQIAAgsgAkEBRg0DDAELIAJBAWsiAkUNAiABQQFqIQELAkACQAJAIAJBIU8EQCAEQShqIQgDQCAEQRBqIApCAEIKEIwCIARBIGogCUIAQgoQjAIgAS0AAEEwayIGQQlLDQYgBCkDGEIAUiAIKQMAIgkgBCkDEHwiCyAJVHINBCAEKQMgIgwgBiAHIAZBCkkbrXwiCSAMVCIHIAsgCyAHrXwiClYgCSAMWhsNAyABQQFqIQEgBiEHIAJBAWsiAg0ACwwBCyAEQQhqIQYDQCABLQAAQTBrIgdBCUsNBSAEIAkgCkIKEIwCIAFBAWohASAGKQMAIAQpAwAiCiAHrXwiCSAKVK18IQogAkEBayICDQALCyAFIAk3AwggBUEQaiAKNwMAQQAMBAsgBUECOgABDAELIAVBAjoAAQtBAQwBCyAFQQE6AAFBAQs6AAAgBEEwaiQAAkAgAy0ACEUEQCAAIAMpAxA3AwggAEEANgIAIABBEGogA0EYaikDADcDAAwBCyADIAMtAAk6ACcgA0HEAGpBAjYCACADQQE2AjwgAyADQSdqNgJAIAMgAzYCOCADQQI2AlwgA0ICNwJMIANBgIzAADYCSCADIANBOGo2AlggA0EoaiIBIANByABqIgIQ0AEgAkEEciABENEBIANBFDYCSCADKAIsBEAgAygCKBCrAQsgACADKQNINwIEIABBATYCACAAQQxqIANB0ABqKQMANwIACyADQeAAaiQAC9Y0Ag9/An4jAEHgAWsiAiQAIAIQlQECQAJAAkACQAJAAkACQAJAAkACQAJAAkAgASgCACIGBEAgAigCCCIDIAIoAgRGBEAgAiADEBAgAigCCCEDCyACKAIAIANqQfsAOgAAIAIgA0EBajYCCCACQdABaiACQcuEwABBAhCXAQJAIAIoAtABRQRAIAIoAggiAyACKAIERgRAIAIgAxAQIAIoAgghAwsgAigCACADakE6OgAAIAIgA0EBajYCCCACQdABaiACEJsBIAIoAtABDQEgAiACKALUASIENgJAIAFBCGooAgAhCCACQdgBai0AAARAIAQoAgghAwwECyAEKAIIIgUgBCgCBEYEQCAEIAUQECAEKAIIIQULIAQgBUEBaiIDNgIIIAQoAgAgBWpBLDoAAAwDCyACQRxqIAJB3AFqKAIANgIAIAIgAikC1AE3AhQMDAsgAkE8aiACQdwBaigCADYCACACIAIpAtQBNwI0DAoLIAJBEGogAiABQQRqKAIAIAFBDGooAgAQHyACKAIQRQ0BDAoLIAJBADoARCAEQQRqIgUoAgAgA0YEQCAEIAMQECAEKAIIIQMLIAQoAgAgA2pBIjoAACAEIANBAWoiAzYCCCAFKAIAIANrQQdNBEAgBCADQQgQESAEKAIIIQMLIAQoAgAgA2pC7crNm5fs2bLzADcAACAEIANBCGoiAzYCCCAEQQRqKAIAIANrQQFNBEAgBCADQQIQESAEKAIIIQMLIAQoAgAgA2pBovQAOwAAIAQgA0ECajYCCCACQdABaiAEEJoBIAIoAtABDQUgAkHYAWotAAAhAwJAAkAgAkHYAGogAigC1AEiCyAIBH8gBiAIQeAAbGohDiAGQSBqIQggA0UhAyACQdABakEEciEFIAJBwAFqQQRyIQYDQCADQQFxBEAgCygCCCIDIAsoAgRGBEAgCyADEBAgCygCCCEDCyALIANBAWo2AgggCygCACADakEsOgAACyACQdABaiALEJsBAkAgAigC0AFFBEAgAigC1AEhBCAIQSBrIgwpAwAhESACLQDYAQRAIAQoAgghAwwCCyAEKAIIIgcgBCgCBEYEQCAEIAcQECAEKAIIIQcLIAQgB0EBaiIDNgIIIAQoAgAgB2pBLDoAAAwBCyACQbwBaiAFQQhqKAIANgIAIAIgBSkCADcCtAEMCwsgBEEEaiIHKAIAIANGBEAgBCADEBAgBCgCCCEDCyAEKAIAIANqQSI6AAAgBCADQQFqIgM2AgggBygCACADa0EBTQRAIAQgA0ECEBEgBCgCCCEDCyAEKAIAIANqQenIATsAACAEIANBAmoiAzYCCCAHKAIAIANrQQFNBEAgBCADQQIQESAEKAIIIQMLIAQoAgAgA2pBovQAOwAAIAQgA0ECajYCCCACQdABaiAEIBEQlgECQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCACKALQAUUEQCAEKAIIIgMgBygCAEYEQCAEIAMQECAEKAIIIQMLIAQoAgAgA2pBLDoAACAEIANBAWoiAzYCCCAHKAIAIANGBEAgBCADEBAgBCgCCCEDCyAEKAIAIANqQSI6AAAgBCADQQFqIgM2AgggBygCACADa0ECTQRAIAQgA0EDEBEgBCgCCCEDCyAEKAIAIANqIglB/YPAAC8AADsAACAJQQJqQf+DwAAtAAA6AAAgBCADQQNqIgM2AgggBygCACADa0EBTQRAIAQgA0ECEBEgBCgCCCEDCyAEKAIAIANqQaL0ADsAACAEIANBAmoiAzYCCAJAAkACQCAMQQhqKAIAIglBBWsiCkECIApBAkkbQQFrDgIBAgALIAcoAgAgA0YEQCAEIAMQECAEKAIIIQMLIAQgA0EBajYCCCAEKAIAIANqQfsAOgAAIAJB0AFqIARBnoPAAEEEEJcBIAIoAtABDQQgCEEUayEJIAQoAggiAyAHKAIARgRAIAQgAxAQIAQoAgghAwsgBCADQQFqNgIIIAQoAgAgA2pBOjoAAAJAIAhBCGsoAgAiAwRAIAJB0AFqIARBrYPAAEEEEJwBIAIoAtABDQ8gAiACLQDYAToApAEgAiACKALUATYCoAEgAkHQAWogAkGgAWpBsYPAAEEKIAkoAgAgCEEMaygCABAPIAIoAtABDQ8gAkHQAWogAkGgAWpBpYDAAEEGIAMgCCgCABAUIAIoAtABDQEgAkHAAWogAigCoAEgAi0ApAEQlAEMEAsgAkHQAWogBEGpg8AAQQQQnAEgAigC0AENDiACIAItANgBOgCkASACIAIoAtQBNgKgASACQdABaiACQaABakGlgMAAQQYgCSgCACAIQQxrKAIAEBQgAigC0AFFBEAgAkHAAWogAigCoAEgAi0ApAEQlAEMEAsMDgsMDQsgBygCACADRgRAIAQgAxAQIAQoAgghAwsgBCADQQFqNgIIIAQoAgAgA2pB+wA6AAAgAkHQAWogBEGYg8AAQQYQlwECQAJAIAIoAtABRQRAIAQoAggiAyAHKAIARgRAIAQgAxAQIAQoAgghAwsgBCADQQFqNgIIIAQoAgAgA2pBOjoAACACQdABaiAEEJsBIAIoAtABRQ0BIAJBzAFqIAVBCGooAgA2AgAgAiAFKQIANwLEAQwCCyACQZABaiACQdwBaigCADYCACACIAIpAtQBNwOIAQwSCyACQcABaiACKALUASACLQDYARCTASACKALAAUUNAwsgAkGQAWogAkHMAWooAgA2AgAgAiACKQLEATcDiAEMEAsgBygCACADRgRAIAQgAxAQIAQoAgghAwsgBCADQQFqNgIIIAQoAgAgA2pB+wA6AAAgAkHQAWogBEGUg8AAQQQQlwEgAigC0AENBCAEKAIIIgMgBygCAEYEQCAEIAMQECAEKAIIIQMLIAQgA0EBajYCCCAEKAIAIANqQTo6AAACQAJAAkACQAJAIAlBAWsOBAMCAQAECyACQdABaiAEQcKDwABBCxCcASACKALQAQ0HIAIgAi0A2AE6AKQBIAIgAigC1AE2AqABIAJB0AFqIAJBoAFqQc2DwABBDSAIQRRrKAIAIAhBDGsoAgAQDyACKALQAUUEQCACQcABaiACKAKgASACLQCkARCUAQwPCyAGIAUpAgA3AgAgBkEIaiAFQQhqKAIANgIADAsLIAJB0AFqIARB2oPAAEEMEJwBIAIoAtABBEAgBiAFKQIANwIAIAZBCGogBUEIaigCADYCAAwLCyACIAItANgBOgCkASACIAIoAtQBNgKgASACQdABaiACQaABakHNg8AAQQ0gCEEUaygCACAIQQxrKAIAEA8gAigC0AEEQCAGIAUpAgA3AgAgBkEIaiAFQQhqKAIANgIADAsLIAJB0AFqIAJBoAFqQeaDwABBBSAIQQhrKAIAIAgoAgAQDyACKALQAUUNDCAGIAUpAgA3AgAgBkEIaiAFQQhqKAIANgIADAoLIAJB0AFqIARB64PAAEEHEJwBIAIoAtABBEAgBiAFKQIANwIAIAZBCGogBUEIaigCADYCAAwKCyACIAItANgBOgCkASACIAIoAtQBNgKgASACQdABaiACQaABakHNg8AAQQ0gCEEUaygCACAIQQxrKAIAEA8gAigC0AEEQCAGIAUpAgA3AgAgBkEIaiAFQQhqKAIANgIADAoLIAJB0AFqIAJBoAFqQfKDwABBCyAIQQhqKQMAEBIgAigC0AEEQCAGIAUpAgA3AgAgBkEIaiAFQQhqKAIANgIADAoLIAJB0AFqIAJBoAFqIAhBCGsQEyACKALQAUUNCiAGIAUpAgA3AgAgBkEIaiAFQQhqKAIANgIADAkLIAJB0AFqIARBgITAAEELEJwBIAIoAtABRQ0HIAYgBSkCADcCACAGQQhqIAVBCGooAgA2AgAMCAsgAkHQAWogBEGXhMAAQQcQnAEgAigC0AEEQCAGIAUpAgA3AgAgBkEIaiAFQQhqKAIANgIADAgLIAIgAi0A2AE6AKQBIAIgAigC1AE2AqABIAJB0AFqIAJBoAFqQc2DwABBDSAIQRRrKAIAIAhBDGsoAgAQDyACKALQAQRAIAYgBSkCADcCACAGQQhqIAVBCGooAgA2AgAMCAsgAkHQAWogAkGgAWogCEEIaxATIAIoAtABBEAgBiAFKQIANwIAIAZBCGogBUEIaigCADYCAAwICyACQdABaiACQaABakG0gcAAQQUgCEEEaigCACAIQQxqKAIAEBQgAigC0AFFDQUgBiAFKQIANwIAIAZBCGogBUEIaigCADYCAAwHCyACQbwBaiACQdwBaigCADYCACACIAIpAtQBNwK0AQwaCyAEKAIIIgMgBygCAEYNCwwMCyACQZABaiACQdwBaigCADYCACACIAIpAtQBNwOIAQwMCyAGIAUpAgA3AgAgBkEIaiAFQQhqKAIANgIADAMLIAJBkAFqIAJB3AFqKAIANgIAIAIgAikC1AE3A4gBDAoLIAJBwAFqIAIoAqABIAItAKQBEJQBDAQLIAIgAigC1AEiAzYCmAEgCEEMaygCACEPIAhBFGsoAgAhDQJAIAItANgBBEAgAygCCCEJDAELIAMoAggiCiADKAIERgRAIAMgChAQIAMoAgghCgsgAyAKQQFqIgk2AgggAygCACAKakEsOgAACyACQQA6AJwBIANBBGoiCigCACAJRgRAIAMgCRAQIAMoAgghCQsgAygCACAJakEiOgAAIAMgCUEBaiIJNgIIIAooAgAgCWtBBE0EQCADIAlBBRARIAMoAgghCQsgAygCACAJaiIQQeaDwAAoAAA2AAAgEEEEakHqg8AALQAAOgAAIAMgCUEFaiIJNgIIIAooAgAgCWtBAU0EQCADIAlBAhARIAMoAgghCQsgAygCACAJakGi9AA7AAAgAyAJQQJqNgIIAkAgDUUEQCACQdABaiADEJgBDAELIAJB0AFqIAMgDSAPEJcBCwJAAkACQAJAIAIoAtABRQRAIAJB0AFqIAJBmAFqQYuEwABBByAIQSBqKQMAEBIgAigC0AENASACQdABaiACQZgBaiAIQQhrEBMgAigC0AENAiACQdABaiACQZgBakG0gcAAQQUgCEEEaigCACAIQQxqKAIAEBQgAigC0AENAyACQdABaiACQZgBakGShMAAQQUgCEEQaigCACAIQRhqKAIAEA8gAigC0AENBCACQcABaiACKAKYASACLQCcARCUAQwICyACQagBaiAFQQhqKAIAIgM2AgAgAiAFKQIAIhE3A6ABIAZBCGogAzYCACAGIBE3AgAMBAsgBiAFKQIANwIAIAZBCGogBUEIaigCADYCAAwDCyAGIAUpAgA3AgAgBkEIaiAFQQhqKAIANgIADAILIAYgBSkCADcCACAGQQhqIAVBCGooAgA2AgAMAQsgBiAFKQIANwIAIAZBCGogBUEIaigCADYCAAsgAkEBNgLAAQwCCyACQcABaiACKAKgASACLQCkARCUAQwBCyACQcABaiACKAKgASACLQCkARCUAQsgAigCwAFFBEAgBCgCCCIDIAcoAgBHDQQMAwsgAkGQAWogBkEIaigCADYCACACIAYpAgA3A4gBDAQLIAYgBSkCADcCACAGQQhqIAVBCGooAgA2AgAgAkEBNgLAAQsgAigCwAFFBEAgBCgCCCIDIAcoAgBGDQEMAgsgAkGQAWogBkEIaigCADYCACACIAYpAgA3A4gBDAILIAQgAxAQIAQoAgghAwsgBCgCACADakH9ADoAACAEIANBAWoiAzYCCCAMQdAAaikDACERIAxByABqKQMAIRIgAyAHKAIARw0BIAQgAxAQIAQoAgghAwwBCyACQbwBaiACQZABaigCADYCACACIAIpA4gBNwK0AQwLCyAEKAIAIANqQSw6AAAgBCADQQFqIgM2AgggBygCACADRgRAIAQgAxAQIAQoAgghAwsgBCgCACADakEiOgAAIAQgA0EBaiIDNgIIIAcoAgAgA2tBCE0EQCAEIANBCRARIAQoAgghAwsgBCgCACADaiIJQaSEwAApAAA3AAAgCUEIakGshMAALQAAOgAAIAQgA0EJaiIDNgIIIAcoAgAgA2tBAU0EQCAEIANBAhARIAQoAgghAwsgBCgCACADakGi9AA7AAAgBCADQQJqNgIIAkAgElAEQCACQdABaiAEEJgBDAELIAJB0AFqIAQgERCWAQsgAigC0AENAiAMQdgAai0AACEJIAQoAggiAyAHKAIARgRAIAQgAxAQIAQoAgghAwsgBCgCACADakEsOgAAIAQgA0EBaiIDNgIIIAcoAgAgA0YEQCAEIAMQECAEKAIIIQMLIAQoAgAgA2pBIjoAACAEIANBAWoiAzYCCCAHKAIAIANrQQdNBEAgBCADQQgQESAEKAIIIQMLIAQoAgAgA2pC8srB45bv17fuADcAACAEIANBCGoiAzYCCCAHKAIAIANrQQFNBEAgBCADQQIQESAEKAIIIQMLIAQoAgAgA2pBovQAOwAAIAQgA0ECajYCCAJAAkACQAJAAkAgCUEBaw4DAQIDAAsgAkHQAWogBEHFhMAAQQYQmQEMAwsgAkHQAWogBEHAhMAAQQUQmQEMAgsgAkHQAWogBEG5hMAAQQcQmQEMAQsgAkHQAWogBEG0hMAAQQUQmQELIAIoAtABBEAgAkG8AWogAkHcAWooAgA2AgAgAiACKQLUATcCtAEMCwsgAkGwAWogBEEAEJMBIAIoArABDQogCEHgAGohCEEBIQMgDEHgAGogDkcNAAtBAAUgAwtB/wFxQQBHEJIBIAIoAlgNCSACQdABaiACQUBrIAFBDGooAgAgAUEUaigCABAgIAIoAtABBEAgAkE8aiACQdwBaigCADYCACACIAIpAtQBNwI0DAsLIAFBIGooAgAhBiABQRhqKAIAIQcgAigCQCEEIAItAEQEQCAEKAIIIQMMAgsgBCgCCCIFIAQoAgRGBEAgBCAFEBAgBCgCCCEFCyAEIAVBAWoiAzYCCCAEKAIAIAVqQSw6AAAMAQsgAkG8AWogAkHcAWooAgA2AgAgAiACKQLUATcCtAEMBwsgAkEAOgBEIARBBGoiBSgCACADRgRAIAQgAxAQIAQoAgghAwsgBCgCACADakEiOgAAIAQgA0EBaiIDNgIIIAUoAgAgA2tBBU0EQCAEIANBBhARIAQoAgghAwsgBCgCACADaiIFQf6EwAAoAAA2AAAgBUEEakGChcAALwAAOwAAIAQgA0EGaiIDNgIIIARBBGooAgAgA2tBAU0EQCAEIANBAhARIAQoAgghAwsgBCgCACADakGi9AA7AAAgBCADQQJqNgIIIAJB0AFqIAQQmgEgAigC0AENAiACQdgBai0AACEDAkACQAJAIAJBsAFqIAIoAtQBIgUgBgR/IAcgBkEYbGohCCADRSEDIAJB0AFqQQRyIQYDQCADQQFxBEAgBSgCCCIDIAUoAgRGBEAgBSADEBAgBSgCCCEDCyAFIANBAWo2AgggBSgCACADakEsOgAACyACQdABaiAFEJsBIAIoAtABDQIgAiACLQDYAToAjAEgAiACKALUATYCiAEgAkHQAWogAkGIAWpB14TAAEEEIAcoAgAgB0EIaigCABAPIAIoAtABDQYgAkHQAWogAkGIAWogB0EMaigCACAHQRRqKAIAECAgAigC0AEEQCACQcwBaiACQdwBaigCADYCACACIAIpAtQBNwLEAQwJCyACQcABaiACKAKIASACLQCMARCTASACKALAAQ0IQQEhAyAHQRhqIgcgCEcNAAtBAAUgAwtB/wFxQQBHEJIBIAIoArABDQcgBCgCCCIHIARBBGoiAygCAEYEQCAEIAcQECAEKAIIIQcLIAQoAgAgB2pBLDoAACAEIAdBAWoiBzYCCCACQQA6AEQgAygCACAHRgRAIAQgBxAQIAQoAgghBwsgBCgCACAHakEiOgAAIAQgB0EBaiIHNgIIIAFBJGohAyAEQQRqIgUoAgAgB2tBA00EQCAEIAdBBBARIAQoAgghBwsgBCgCACAHakHkwtGLBjYAACAEIAdBBGoiATYCCCAFKAIAIAFrQQFNBEAgBCABQQIQESAEKAIIIQELIAQoAgAgAWpBovQAOwAAIAQgAUECajYCCCADKAIADQEgAkHQAWogBBCYAQwCCyACQcwBaiAGQQhqKAIANgIAIAIgBikCADcCxAEMBQsgAkHAAWogAxBqIAJB0AFqIAQgAigCwAEiASACKALIARCXASACKALEAUUNACABEKsBCyACKALQAQRAIAJBPGogAkHcAWooAgA2AgAgAiACKQLUATcCNAwJCyACQTBqIARBABCTASACKAIwDQggAigCCCIDIAIoAgRGBEAgAiADEBAgAigCCCEDCyACKAIAIANqQf0AOgAAIAIgA0EBajYCCAsgAkHIAWogAkEIaigCACIBNgIAIAIgAikDACIRNwPAASAAQQxqIAE2AgAgACARNwIEIABBDTYCAAwJCyACQcwBaiACQdwBaigCADYCACACIAIpAtQBNwLEAQwBCyACQbwBaiACQdwBaigCADYCACACIAIpAtQBNwK0AQwBCyACQbwBaiACQcwBaigCADYCACACIAIpAsQBNwK0AQsgAkE8aiACQbwBaigCADYCACACIAIpArQBNwI0DAMLIAJB5ABqIAJB3AFqKAIANgIAIAIgAikC1AE3AlwMAQsgAkHkAGogAkG8AWooAgA2AgAgAiACKQK0ATcCXAsgAkE8aiACQeQAaigCADYCACACIAIpAlw3AjQLIAJBHGogAkE8aigCADYCACACIAIpAjQ3AhQLIAJByAFqIgEgAkEcaigCADYCACACIAIpAhQ3A8ABIAIoAgQEQCACKAIAEKsBCyACQdgBaiABKAIANgIAIAIgAikDwAE3A9ABIABBuYfAAEHhACACQdABahAhCyACQeABaiQAC+ACAgJ/AX4jAEEgayIFJAAgASgCCCIEIAEoAgRGBEAgASAEEBAgASgCCCEECyABIARBAWo2AgggASgCACAEakH7ADoAACAFQRBqIAFBwITAAEEFEJcBAkACQCAFKAIQRQRAIAEoAggiBCABKAIERgRAIAEgBBAQIAEoAgghBAsgASAEQQFqNgIIIAEoAgAgBGpBOjoAACAFQRBqIAEgAiADEJcBIAUoAhANASABKAIIIgQgASgCBEYEQCABIAQQECABKAIIIQQLIABBADYCACABIARBAWo2AgggASgCACAEakH9ADoAAAwCCyAFQQhqIAVBHGooAgAiATYCACAFIAUpAhQiBjcDACAAQQxqIAE2AgAgACAGNwIEIABBATYCAAwBCyAFQQhqIAVBHGooAgAiATYCACAFIAUpAhQiBjcDACAAQQxqIAE2AgAgACAGNwIEIABBATYCAAsgBUEgaiQAC9QGAgR/AX4jAEHgAGsiBCQAIAEoAgAhBgJAIAEtAAQEQCAGKAIIIQUMAQsgBigCCCIHIAYoAgRGBEAgBiAHEBAgBigCCCEHCyAGIAdBAWoiBTYCCCAGKAIAIAdqQSw6AAALIAFBADoABCAGQQRqIgEoAgAgBUYEQCAGIAUQECAGKAIIIQULIAYoAgAgBWpBIjoAACAGIAVB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QT9xQYABcjoADyACIAFBBnZBP3FBgAFyOgAOIAIgAUEMdkE/cUGAAXI6AA0gAiABQRJ2QQdxQfABcjoADEEEDAELIAIgAUE/cUGAAXI6AA4gAiABQQx2QeABcjoADCACIAFBBnZBP3FBgAFyOgANQQMLIQEgASAAQQRqKAIAIAAoAggiA2tLBEAgACADIAEQESAAKAIIIQMLIAAoAgAgA2ogAkEMaiABEIsCGiAAIAEgA2o2AggLIAJBEGokAEEAC1oBAX8jAEEgayICJAAgAiAAKAIANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpB9InAACACQQhqEN4BIAJBIGokAAtKAQF/IAIgACgCACIAQQRqKAIAIAAoAggiA2tLBEAgACADIAIQESAAKAIIIQMLIAAoAgAgA2ogASACEIsCGiAAIAIgA2o2AghBAAvGBAICfwF+IwBBsAFrIgIkACACQQhqIAFBDGopAgA3AwAgAkEQaiABQRRqKQIANwMAIAJBGGogAUEcaikCADcDACACQSBqIAFBJGooAgA2AgAgAiABKQIENwMAAkACQCABKAIAIgMEQCABKQMoIQQgACADNgIAIAAgBDcCKCAAIAFBBGoiASkCADcCBCAAQQxqIAFBCGopAgA3AgAgAEEUaiABQRBqKQIANwIAIABBHGogAUEYaikCADcCACAAQSRqIAFBIGooAgA2AgAMAQsgAkFAayACQRxqKQIANwMAIAJBOGogAkEUaikCADcDACACQTBqIAJBDGopAgA3AwAgAiACKQIENwMoIAJBADYCUCACQgE3A0ggAkHYAGogAkHIAGpBqIXAABDyASACKAIoQQ1GBEAgAkGkAWpBADYCACACQYyKwAA2AqABIAJCATcClAEgAkGEjcAANgKQASACQdgAaiACQZABahD3AQ0CIAAgAikDSDcCBCAAQQA2AgAgAEEMaiACQdAAaigCADYCAAwBCyACQaQBakEBNgIAIAJCATcClAEgAkGMjcAANgKQASACQQM2AoQBIAIgAkGAAWo2AqABIAIgAkGMAWo2AoABIAIgAkEoajYCjAEgAkHYAGogAkGQAWoQ9wENASACKAIoIABBDGogAkHQAGooAgA2AgAgACACKQNINwIEIABBADYCAEENRg0AIAJB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yAFBDUcNASADKALMASEBCyADQfQCakH0gMAANgIAIANB7AJqQciAwAA2AgAgA0HkAmpBrIDAADYCACADQbACaiADQcABaikDADcDACADQcgCaiADQbABaikDADcDACADQYwDaiAGNgIAIANBiANqIA02AgAgA0GEA2ogCDYCACADQYADaiATNgIAIANB/AJqIA82AgAgA0HwAmogA0GYA2oiADYCACADQegCaiAANgIAIAMgAykDuAE3A6gCIAMgCjYCvAIgAyAJNgK4AiADIAMpA6gBNwPAAiADIAE2ApADIAMgEDYC+AIgAyAWNwPYAiADIAw2AtQCIAMgCzYC0AIgAyAANgLgAiADQegBaiINIQIgA0GoAmohB0EAIQojAEHgAWsiACQAIAAgATYCDCAAQfAAaiADQfgCaiIEENEBIABBHGogAEH4AGooAgA2AgAgACABNgIQIAAgACkDcDcCFCADQeACaiIBKAIEIQsgASgCACEMAkACQAJAAkACQAJAAkACQAJAQRRBARA9IgEEQCABQRBqQd2MwAAoAAA2AAAgAUEIakHVjMAAKQAANwAAIAFBzYzAACkAADcAAEEFQQEQPSIFRQ0IIAVBBGpB5YzAAC0AADoAACAFQeGMwAAoAAA2AAAgAEGwAWoiBhCVASAAQUBrIAYQmwEgACgCQA0BIAAgACgCRDYCwAEgACAAQcgAai0AADoAxAEgAEFAayAAQcABakGUgcAAQQggAUEUEA8gACgCQA0CIABBQGsgAEHAAWpBk4XAAEEHIAVBBRAPIAAoAkAEQCAAQdQBaiAAQcwAaigCADYCACAAIAApAkQ3AswBDAULIABByAFqIAAoAsABIAAtAMQBEJMBIAAoAsgBRQ0DDAQLQRRBARDOAQALIABB1AFqIABBzABqKAIANgIAIAAgACkCRDcCzAEMAgsgAEHUAWogAEHMAGooAgA2AgAgACAAKQJENwLMAQwBCyAAQfwAaiAAQbgBaigCADYCACAAIAApA7ABNwJ0DAELIABBqAFqIgYgAEHUAWooAgA2AgAgACAAKQLMATcDoAEgACgCtAEEQCAAKAKwARCrAQsgAEHIAGogBigCADYCACAAIAApA6ABNwNAIABB8ABqQd2JwABBFCAAQUBrECEgACgCcCIGQQ1HDQELIABB+ABqKAIAIQhBDSEGIAxBmoXAAEENIAAoAnQiCSAAQfwAaigCACALKAIUEQcAIAhFDQEgCRCrAQwBCyAAQThqIABBiAFqKQMANwMAIAAgACkDgAE3AzAgACgCfCEIIAAoAnghCSAAKAJ0IQoLIAEQqwEgBRCrAQJAAkACQAJAAkACQCAGQQ1GBEAgAEHwAGogDCALIABBEGoQJiAAKAJwIgFBDUYNAiAAQdgAaiAAQYwBaigCACIFNgIAIABB0ABqIABBhAFqKQIAIhU3AwAgAEHIAGogAEH8AGopAgAiFjcDACAAIAApAnQiFzcDQCACQSRqIAU2AgAgAkEcaiAVNwIAIAJBFGogFjcCACACQQxqIBc3AgAgAiABNgIIDAELIABBKGogAEE4aikDACIVNwMAIAAgACkDMCIWNwMgIAJBIGogFTcCACACQRhqIBY3AgAgAkEUaiAINgIAIAJBEGogCTYCACACQQxqIAo2AgAgAiAGNgIICyACQQA2AgAgAEEYaigCAARAIAAoAhQQqwELIARBBGooAgAEQCAEKAIAEKsBCyAEQRRqKAIAIgEEQCABQQV0IQEgBEEMaigCAEEQaiECA0AgAkEEaigCAARAIAIoAgAQqwELIAJBIGohAiABQSBrIgENAAsLIARBEGooAgAEQCAEKAIMEKsBCyAHQRRqKAIABEAgBygCEBCrAQsgB0EsaigCAA0BDAILIABBkAFqQgA3AwAgAEGAAWpCADcDACAAQgQ3A4gBIABCgICAgMAANwN4IABCCDcDcCAAQUBrIABB8ABqQeaMwABBgITAAEELECIgAEE4aiIFIARBCGooAgA2AgAgACAEKQIANwMwQQVBARA9IgFFDQQgAUEEakHwjMAALQAAOgAAIAFB7IzAACgAADYAACAAQfgAaiAFKAIANgIAIAAgACkDMDcDcCAAQdQBaiIFIABB8ABqIgYpAgA3AgAgBUEIaiAGQQhqKAIANgIAIABChYCAgNAANwLMASAAIAE2AsgBIABB1ABqKAIAIgEgAEHQAGooAgBGBEAgAEHMAGogARAjIAAoAlQhAQsgACgCTCABQRhsaiIFIAApA8gBNwIAIAVBCGogAEHQAWopAwA3AgAgBUEQaiAAQdgBaikDADcCACAAQfgAaiAAQcgAaikDADcDACAAQYgBaiAAQdgAaikDADcDACAAQZABaiAAQeAAaikDADcDACAAQZgBaiAAQegAaikDADcDACAAIAFBAWo2AlQgAEGAAWogAEHQAGopAwA3AwAgACAAKQNANwNwIABBADYC0AEgAEIBNwPIASAAQUBrIgUgAEHIAWpBqIXAABDyASAAQQxqKAIAIgGtQgAgAax9IAFBf0oiARsgASAFEIUCDQJBBUEBED0iBUUNAyAFQQRqQfWMwAAtAAA6AAAgBUHxjMAAKAAANgAAIABBhAFqKAIAIgEgAEGAAWoiCCgCAEYEQCAAQfwAaiABECMgACgChAEhAQsgACgCfCABQRhsaiIGQoWAgIDQADcCBCAGIAU2AgAgAiAAKQNwNwIAIAJBCGogAEH4AGopAwA3AgAgAkEYaiAAQYgBaikDADcCACACQSBqIABBkAFqKQMANwIAIAJBKGogAEGYAWopAwA3AgAgACABQQFqNgKEASACQRBqIAgpAwA3AgAgBiAAKQPIATcCDCAGQRRqIABB0AFqKAIANgIAIABBGGooAgAEQCAAKAIUEKsBCyAEQRRqKAIAIgEEQCABQQV0IQEgBEEMaigCAEEQaiECA0AgAkEEaigCAARAIAIoAgAQqwELIAJBIGohAiABQSBrIgENAAsLIARBEGooAgAEQCAEKAIMEKsBCyAHQRRqKAIABEAgBygCEBCrAQsgB0EsaigCAEUNAQsgBygCKBCrAQsgAEHgAWokAAwDC0HAhcAAQTcgAEEwakH4hcAAQdSGwAAQ6QEACwtBBUEBEM4BAAsgA0HIAGogDRAzIAMoApwBBEAgFBCrAQsgAygCjAEEQCASEKsBCyADKAJ8RQ0DIA4QqwEMAwsgA0GAAmogA0HgAWopAwA3AwAgA0H4AWogA0HYAWopAwA3AwAgA0HwAWogA0HQAWopAwA3AwAgAyADKQPIATcD6AEgA0EANgKgAiADQgE3A5gCIANBqAJqIgAgA0GYAmpBqIXAABDyASADQegBaiAAEH1FBEAgA0HUAGogA0GgAmooAgA2AgAgAyADKQOYAjcCTCADQQA2AkggA0HoAWoQLiAPBEAgEBCrAQsgBgRAIAZBBXQhASAIQRBqIQADQCAAQQRqKAIABEAgACgCABCrAQsgAEEgaiEAIAFBIGsiAQ0ACwsgDUUNASAIEKsBDAELDAMLIAoEQCAJEKsBCyAMRQ0AIAsQqwELIAMoApwBBEAgAygCmAEQqwELIAMoAowBBEAgAygCiAEQqwELIAMoAnxFDQAgDhCrAQsgA0HoAWogA0HIAGoQHiADKALoAUENRgRAIANB0AFqIANB9AFqKAIAIgA2AgAgAyADKQLsASIVNwPIASADQbACaiAANgIAIAMgFTcDqAIgA0GoAmoQfiADQcgAahArIANBoANqJAAPCyADQcACaiADQYACaikDADcDACADQbgCaiADQfgBaikDADcDACADQbACaiADQfABaikDADcDACADIAMpA+gBNwOoAkHFgcAAQSsgA0GoAmpB8IHAAEH0gsAAEOkBAAtBwIXAAEE3IANBmANqQfiFwABB1IbAABDpAQALnSoCE38CfiMAQdADayIDJAAQrQEgA0GoAWogABB/IANBuAFqIAEQfyADQcgBaiACEH8gA0HYAmogAygCqAEiEyADKAKwARAVAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJ/AkACfwJAAkACQAJAAkACQAJAAkACQAJAIAMoAvgCQQJHBEAgA0HwAWogA0HgAmopAwA3AwAgA0HgAWogA0H4AmopAwA3AwAgAyADKQPYAjcD6AEgAyADKQPwAjcD2AEgAygC6AIhESADKALsAiEOIAMoAoADIQ8gAygChAMhEiADKQOIAyEWIANB+AFqIAMoArgBIhQgAygCwAEQHCADKAL4AUENRw0CIANBkAJqKAIAIQwgA0GMAmooAgAhCiADQYgCaigCACEJIANBhAJqKAIAIQIgA0GAAmooAgAhDSADKAL8ASEQIANByAJqIgAgAygCyAEiFSADKALQARCJASADQfAAaiAAEJABIAMtAHBBAXENAQwUCyADQZACaiADQfACaikDADcDACADQYgCaiADQegCaikDADcDACADQYACaiADQeACaikDADcDACADIAMpA9gCNwP4ASADQQA2AtACIANCATcDyAIgA0GYAmoiACADQcgCakGohcAAEPIBIANB+AFqIAAQfQ0aIANBhAFqIANB0AJqKAIANgIAIAMgAykDyAI3AnwgA0EANgJ4IANB+AFqEC4MGAsgAy0AcSIAQfsARwRAIABBIkcEQEEKIQAMFQsgA0HYAmogA0HIAmoQOCADKALYAiIAQRVHDQ9BDiEADBQLIANByAJqIgQQigEgA0HYAmogBBA4AkACfyAD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AEEiRw0GIANBCGogBRCQAUEEIQAgAy0ACEEBcUUNB0EOIQAgAy0ACUEiRw0HIAUQigEgA0HYAmogBRCPASADKALYAiIAQRVHDQEgA0HkAmooAgAhByADQeACaigCACEAIAMoAtwCIgVFBEAgA0GYAmogACAHQYyKwABBABA2DAMLIANBmAJqIAUgB0GMisAAQQAQNiAARQ0CIAUQqwEMAgtBEyEADAYLIAMgAygC5AI2AqQCIAMgAykC3AI3ApwCIAMgADYCmAILIAMoApgCIgBBFUYNACADLwCdAiADLQCfAkEQdHIhByADKQOgAiEXIAMtAJwCIQUMBAsgA0HYAmogBBCNASADKALYAiIAQRVHBEAgAygC3AIiAUEIdiEHIAMoAuQCIQUgAygC4AIhBgwFCyADIAQQkAEgAy0AAEEBcUUNBUELIQAgAy0AAUH9AEcNBgsgBBCKASADQdgCaiADQcgCahCLASADKALYAiIAQRVGDQYLIAMoAuQCIQUgAygC4AIhBiADKALcAiEHDAQLQRAhAAsgBUH/AXEhASAXQiCIpyEFIBenIQYLIAFB/wFxIAdBCHRyIQcMAQtBBCEAQQAhBwsgAyAFNgLkAiADIAY2AuACIAMgBzYC3AIgAyAANgLYAiADQfgBakHkhsAAQRsgA0HYAmoQGyADKAL4AUENRw0BIANBgAJqKAIAIQEgAygC/AEhCAsgA0GkA2pB9IDAADYCACADQZwDakHIgMAANgIAIANBlANqQayAwAA2AgAgA0HgAmogA0HwAWopAwA3AwAgA0H4AmogA0HgAWopAwA3AwAgA0HEA2ogATYCACADQbwDaiAMNgIAIANBuANqIAo2AgAgA0G0A2ogCTYCACADQbADaiACNgIAIANBrANqIA02AgAgA0GgA2ogA0HIA2oiADYCACADQZgDaiAANgIAIAMgAykD6AE3A9gCIAMgDjYC7AIgAyARNgLoAiADIAMpA9gBNwPwAiADIAg2AsADIAMgEDYCqAMgAyAWNwOIAyADIBI2AoQDIAMgDzYCgAMgAyAANgKQAyADQZgCaiISIQogA0GQA2ohACADQdgCaiERIANBqANqIQkgASECIwBBMGsiCyQAAkAgCEUEQCALQShqIABBEGopAgA3AwAgC0EgaiAAQQhqKQIANwMAIAsgACkCADcDGCMAQeAA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AWooAgAhACACQdABaigCACEBIAIoAswBIgVFBEAgAkGgAWogASAAQYyKwABBABA2DAMLIAJBoAFqIAUgAEGMisAAQQAQNiABRQ0CIAUQqwEMAgtBEyEBDAYLIAIgAigC1AE2AqwBIAIgAikCzAE3AqQBIAIgADYCoAELIAIoAqABIgFBFUYNACACLwClASACLQCnAUEQdHIhCyACKQOoASEOIAItAKQBIQMMBAsgAkHIAWogAxCNASACKALIASIBQRVHBEAgAi8AzQEgAi0AzwFBEHRyIQsgAikD0AEhDiACLQDMASEDDAQLIAJBCGogAxCQASACLQAIQQFxRQ0EIAItAAlB/QBHBEBBCyEBDAYLIAMQigEgAkHIAWogAkFAaxCLASACKALIASIBQRVGDQYLIAIpA9ABIQ4gAigCzAEhAwwECyACQZgBaiACQeABaikDADcDACACQZABaiACQdgBaikDADcDACACQYgBaiACQdABaikDADcDACACIAIpA8gBNwOAASACQQA2ArACIAJCATcDqAIgAkGgAWoiACACQagCakGohcAAEPIBIAJBgAFqIAAQfUUEQCACQcwAaiACQbACaigCADYCACACIAIpA6gCNwJEIAJBATYCQCACQYABahAuDAkLDA4LQRAhAQsgA0H/AXEgC0EIdHIhAwwBC0EEIQFBACEDCyACIA43A9ABIAIgAzYCzAEgAiABNgLIASACQYABakGgh8AAQRkgAkHIAWoQGyACKAKAAUENRw0BCyACQZQCakH0gMAANgIAIAJBjAJqQciAwAA2AgAgAkGEAmpBrIDAADYCACACQdABaiACQfgAaikDADcDACACQegBaiACQegAaikDADcDACACQZACaiACQbgCaiIANgIAIAJBiAJqIAA2AgAgAiACKQNwNwPIASACIAY2AtwBIAIgBDYC2AEgAiACKQNgNwPgASACIA83A/gBIAIgCTYC9AEgAiAINgLwASACIAA2AoACIAJBgAFqIgUhASACQcgBaiEDIwBB8ABrIgAkACAAQRhqIAJBgAJqIgQoAgAgBCgCBEEMaigCABAkAkACQAJAAkACQAJAAkAgACgCGCIEQQ1GBEAgACgCHCEEIABBJGooAgAEQCAAQSBqKAIAEKsBCyAAQcgAaiIGEJUBIABBGGogBhCbASAAKAIYDQEgACAAKAIcNgJoIAAgAEEgai0AADoAbCAAQRhqIABB6ABqIAQQJyAAKAIYBEAgAEHkAGogAEEkaigCADYCACAAIAApAhw3AlwMBAsgAEHYAGogACgCaCAALQBsEJMBIAAoAlhFDQIMAwsgAEEQaiAAQTRqKAIAIgY2AgAgACAAKQIsIg43AwggACkCHCEPIAApAiQhECABQRxqIAY2AgAgASAONwIUIAEgEDcCDCABIA83AgQgASAENgIAIANBFGooAgAEQCADKAIQEKsBCyADQSxqKAIARQ0GIAMoAigQqwEMBgsgAEHkAGogAEEkaigCADYCACAAIAApAhw3AlwMAQsgAEEkaiAAQdAAaigCADYCACAAIAApA0g3AhwMAQsgAEFAayIEIABB5ABqKAIANgIAIAAgACkCXDcDOCAAKAJMBEAgACgCSBCrAQsgAEHgAGogBCgCADYCACAAIAApAzg3A1ggAEEYakH/hsAAQSEgAEHYAGoQISAAKAIYQQ1HDQELIAEgACkCHDcCBCABQQ02AgAgAUEMaiAAQSRqKAIANgIADAELIAEgACkDGDcDACABQRhqIABBMGopAwA3AwAgAUEQaiAAQShqKQMANwMAIAFBCGogAEEgaikDADcDAAsgA0EUaigCAARAIAMoAhAQqwELIANBLGooAgBFDQAgAygCKBCrAQsgAEHwAGokACAFQQRyIQACQCACKAKAASIBQQ1GBEAgAkHMAGogAEEIaigCADYCACACQQA2AkAgAiAAKQIANwJEDAELIAJBrAFqIABBCGooAgA2AgAgAkG4AWogAkGYAWopAwA3AwAgAiABNgKgASACIAIpA5ABNwOwASACIAApAgA3AqQBIAJBADYCsAIgAkIBNwOoAiACQcgBaiIAIAJBqAJqQaiFwAAQ8gEgAkGgAWogABB9DQogAkHMAGogAkGwAmooAgA2AgAgAiACKQOoAjcCRCACQQE2AkAgAkGgAWoQLgsgAigCnAIEQCAMEKsBCyACKAJUBEAgBxCrAQsgAkGoAmoQlQEgAUENRw0EIAIoArACIgAgAigCrAJGBEAgAkGoAmogABAQIAIoArACIQALIAIoAqgCIABqQfsAOgAAIAIgAEEBajYCsAIgAkHIAWogAkGoAmpBy4TAAEECEJcBIAIoAsgBDQIgAigCsAIiACACKAKsAkYEQCAC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KAIAIQIjAEEwayIAJAACfwJAAkACQAJAIAIoAgBBAWsOAwECAwALIABBHGpBADYCACAAQfSRwAA2AhggAEIBNwIMIABB5KjAADYCCCABIABBCGoQ9wEMAwsgAEEcakEANgIAIABB9JHAADYCGCAAQgE3AgwgAEHIqMAANgIIIAEgAEEIahD3AQwCCyAAQRxqQQA2AgAgAEH0kcAANgIYIABCATcCDCAAQaiowAA2AgggASAAQQhqEPcBDAELIABBHGpBATYCACAAQgE3AgwgAEHop8AANgIIIABBIDYCJCAAIAJBBGo2AiwgACAAQSBqNgIYIAAgAEEsajYCICABIABBCGoQ9wELIABBMGokAAu0AwEBfyAAKAIAIQIjAEEwayIAJAACfwJAAkACQAJAAkACQAJAIAIoAgBBAWsOBgECAwQFBgALIABBHGpBADYCACAAQfSRwAA2AhggAEIBNwIMIABB4LLAADYCCCABIABBCGoQ9wEMBgsgAEEcakEANgIAIABB9JHAADYCGCAAQgE3AgwgAEHMssAANgIIIAEgAEEIahD3AQwFCyAAQRxqQQA2AgAgAEH0kcAANgIYIABCATcCDCAAQeSowAA2AgggASAAQQhqEPcBDAQLIABBHGpBADYCACAAQfSRwAA2AhggAEIBNwIMIABByKjAADYCCCABIABBCGoQ9wEMAwsgAEEcakEANgIAIABB9JHAADYCGCAAQgE3AgwgAEG0ssAANgIIIAEgAEEIahD3AQwCCyAAQRxqQQA2AgAgAEH0kcAANgIYIABCATcCDCAAQaiowAA2AgggASAAQQhqEPcBDAELIABBHGpBATYCACAAQgE3AgwgAEHop8AANgIIIABBIDYCJCAAIAJBBGo2AiwgACAAQSBqNgIYIAAgAEEsajYCICABIABBCGoQ9wELIABBMGokAAsMACAAKAIAIAEQ3AELYgEBfyMAQTBrIgIkACAAKAIAIQAgAkEcakEBNgIAIAJCAjcCDCACQeSwwAA2AgggAkEeNgIkIAIgADYCLCACIAJBIGo2AhggAiACQSxqNgIgIAEgAkEIahD3ASACQTBqJAALVwEBfyMAQSBrIgIkACACIAA2AgQgAkEYaiABQRBqKQIANwMAIAJBEGogAUEIaikCADcDACACIAEpAgA3AwggAkEEakHckcAAIAJBCGoQ3gEgAkEgaiQACwgAIAEgARBUC5oEAQR/IwBBQGoiACQAIABBADYCCCAAQgE3AwAgAEEQaiIEIABBmI/AABDyAQJAIwBBQGoiAiQAQQEhAwJAIAQoAhgiBUGo38AAQQwgBEEcaigCACIEKAIMEQEADQACQCABKAIIIgMEQCACIAM2AgwgAkHnADYCFCACIAJBDGo2AhBBASEDIAJBATYCPCACQgI3AiwgAkG438AANgIoIAIgAkEQajYCOCAFIAQgAkEoahDeAUUNAQwCCyABKAIAIgMgASgCBEEMaigCABEIAELrkZO19tizovQAUg0AIAIgAzYCDCACQegANgIUIAIgAkEMajYCEEEBIQMgAkEBNgI8IAJCAjcCLCACQbjfwAA2AiggAiACQRBqNgI4IAUgBCACQShqEN4BDQELIAEoAgwhASACQSRqQcoANgIAIAJBHGpBygA2AgAgAiABQQxqNgIgIAIgAUEIajYCGCACQekANgIUIAIgATYCECACQQM2AjwgAkIDNwIsIAJBkN/AADYCKCACIAJBEGo2AjggBSAEIAJBKGoQ3gEhAwsgAkFAayQAIANFBEAgACgCCCECIAAoAgAhA0EMQQQQPSIBRQ0BIAEgAjYCCCABIAI2AgQgASADNgIAIAEQACABEKsBIAAoAgQEQCAAKAIAEKsBCyAAQUBrJAAPC0Gwj8AAQTcgAEE4akHoj8AAQcSQwAAQ6QEAC0EMQQQQzgEAC4cBAQV/IwBBIGsiAyQAAn8gAkUEQEEAIQJBAAwBCwJAA0AgA0EIaiABEFYgAygCCCIFRQ0BIAMoAhggAygCFCEHIAMoAgwEQCAFEKsBCyAEQQFqIQQEQCAHEKsBCyACIARHDQALQQAMAQsgBCECQQELIQEgACACNgIEIAAgATYCACADQSBqJAALiQMCCH8BfiMAQUBqIgIkAAJAIAEoAgAQBSIBBEAgASgCACIDRQ0BIAEpAgQhCiABEKsBIAIgCjcCNCACIAM2AjAgAkEYaiIEIAJBMGoiBRBsIAJBEGogAkEgaigCACIGNgIAIAIgAikDGCIKNwMIIAJBKGoiBygCACEBIAJBLGoiCCgCACEJIAIoAiQhAyACQThqIAY2AgAgAiAKNwMwIAQgBRBsIAgoAgAhBCAHKAIAIQUgAigCJCEGIAIoAhwEQCACKAIYEKsBCwJAIARFBEAgAEEANgIAIAEEQCADEKsBCyAFRQ0BIAYQqwEMAQsgACAJNgIUIAAgATYCECAAIAM2AgwgACAENgIIIAAgBTYCBCAAIAY2AgALIAJBQGskAA8LIAJBLGpBADYCACACQfSRwAA2AiggAkIBNwIcIAJBqKbAADYCGCACQRhqQZCnwAAQ1AEACyACQSxqQQA2AgAgAkH0kcAANgIoIAJCATcCHCACQcCnwAA2AhggAkEYakHIp8AAENQBAAt9AQV/IwBBIGsiAyQAAkAgAkUNAANAAkAgA0EIaiABEFYgAygCCCIERQ0AIAMoAhggAygCFCEGIAMoAgwEQCAEEKsBCwRAIAYQqwELIAJBAWsiAg0BDAILC0EBIQcLAkAgB0UEQCAAIAEQVgwBCyAAQQA2AgALIANBIGokAAsJACAAQgA3AgALDQAgACgCACABEFpBAAvNAgECfyMAQRBrIgIkAAJAAn8CQCABQYABTwRAIAJBADYCDCABQYAQTw0BIAIgAUE/cUGAAXI6AA0gAiABQQZ2QcABcjoADEECDAILIAAoAggiAyAAKAIERgRAIAAgAxAQIAAoAgghAwsgACADQQFqNgIIIAAoAgAgA2ogAToAAAwCCyABQYCABE8EQCACIAFBP3FBgAFyOgAPIAIgAUEGdkE/cUGAAXI6AA4gAiABQQx2QT9xQYABcjoADSACIAFBEnZBB3FB8AFyOgAMQQQMAQsgAiABQT9xQYABcjoADiACIAFBDHZB4AFyOgAMIAIgAUEGdkE/cUGAAXI6AA1BAwshASABIABBBGooAgAgACgCCCIDa0sEQCAAIAMgARARIAAoAgghAwsgACgCACADaiACQQxqIAEQiwIaIAAgASADajYCCAsgAkEQaiQAC1oBAX8jAEEgayICJAAgAiAAKAIANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpB3JHAACACQQhqEN4BIAJBIGokAAsKACAAIAEQWkEAC8UBAQF/IwBB8ABrIgMkACADIAI2AgwgAyABNgIIIANBJGpBATYCACADQgI3AhQgA0Ggk8AANgIQIANBITYCLCADIANBKGo2AiAgAyADQQhqNgIoIANBADYCOCADQgE3AzAgA0FAayIBIANBMGpBmI/AABDyASADQRBq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CCAEIAM2AgQgBCACNgIAQcAAQQEQPSIDRQ0EQQxBBBA9IgJFDQUgAkLAADcCBCACIAM2AgAgBCACEAciAw0BIAIoAgAiA0UNByACKQIEIQUgAhCrASAAQQhqIAU3AgAgACADNgIEIABBDTYCACAEEKsBDAILQSRBARA9IgJFDQUgAEKkgICAwAQ3AwggACACNgIEIABBAjYCACACQSBqQZijwAAoAAA2AAAgAkEYakGQo8AAKQAANwAAIAJBEGpBiKPAACkAADcAACACQQhqQYCjwAApAAA3AAAgAkH4osAAKQAANwAADAELIAMoAgAiAkUNBSADKQIEIQUgAxCrASABIAU3AgQgASACNgIAIAFBIjYCJCABIAE2AiAgAUEBNgI8IAFCATcCLCABQbijwAA2AiggASABQSBqNgI4IAFBEGogAUEoahDQASAAQQI2AgAgACABKQMQNwIEIABBDGogAUEYaigCADYCACABKAIEBEAgASgCABCrAQsgBBCrAQsgAUFAayQADwtBDEEEEM4BAAtBwABBARDOAQALQQxBBBDOAQALQSRBARDOAQALIAFBPGpBADYCACABQfSRwAA2AjggAUIBNwIsIAFBwKfAADYCKCABQShqQcinwAAQ1AEAC5kDAgJ/AX4jAEFAaiIBJAAgAkEIaigCACEDIAIoAgAhAgJAAkACQEEMQQQQPSIEBEAgBCADNgIIIAQgAzYCBCAEIAI2AgBB2gBBARA9IgNFDQFBDEEEED0iAkUNAiACQtoANwIEIAIgAzYCAAJAIAQgAhAIIgNFBEAgAigCACIDRQ0FIAIpAgQhBSACEKsBIABBCGogBTcCACAAIAM2AgQgAEENNgIADAELIAMoAgAiAkUNBCADKQIEIQUgAxCrASABIAU3AgQgASACNgIAIAFBIjYCJCABIAE2AiAgAUEBNgI8IAFCATcCLCABQdijwAA2AiggASABQSBqNgI4IAFBEGogAUEoahDQASAAQQI2AgAgACABKQMQNwIEIABBDGogAUEYaigCADYCACABKAIEBEAgASgCABCrAQsLIAQQqwEgAUFAayQADwtBDEEEEM4BAAtB2gBBARDOAQALQQxBBBDOAQALIAFBPGpBADYCACABQfSRwAA2AjggAUIBNwIsIAFBwKfAADYCKCABQShqQcinwAAQ1AEAC8cCAQF/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IABBCGpBADYCACAAQQE2AgALzQEBA38jAEEgayICJAACQAJAIAFBAWoiAUUNACAAQQRqKAIAIgNBAXQiBCABIAEgBEkbIgFBCCABQQhLGyIBQX9zQR92IQQCQCADBEAgAkEBNgIYIAIgAzYCFCACIAAoAgA2AhAMAQsgAkEANgIYCyACIAEgBCACQRBqEIIBIAIoAgQhAyACKAIARQRAIAAgAzYCACAAQQRqIAE2AgAMAgsgAkEIaigCACIAQYGAgIB4Rg0BIABFDQAgAyAAEM4BAAsQzwEACyACQSBqJAALzwEBAn8jAEEgayIDJAACQAJAIAEgASACaiIBSw0AIABBBGooAgAiAkEBdCIEIAEgASAESRsiAUEIIAFBCEsbIgFBf3NBH3YhBAJAIAIEQCADQQE2AhggAyACNgIUIAMgACgCADYCEAwBCyADQQA2AhgLIAMgASAEIANBEGoQggEgAygCBCECIAMoAgBFBEAgACACNgIAIABBBGogATYCAAwCCyADQQhqKAIAIgBBgYCAgHhGDQEgAEUNACACIAAQzgEACxDPAQALIANBIGokAAsdACABKAIARQRAAAsgAEHEs8AANgIEIAAgATYCAAtVAQJ/IAEoAgAhAiABQQA2AgACQCACBEAgASgCBCEDQQhBBBA9IgFFDQEgASADNgIEIAEgAjYCACAAQcSzwAA2AgQgACABNgIADwsAC0EIQQQQzgEAC+0DAQF/IwBBMGsiAiQAAn8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgACgCAEEBaw4UAQIDBAUGBwgJCgsMDQ4PEBESExQACyACQcK5wAA2AihBIgwUCyACQam5wAA2AihBGQwTCyACQY25wAA2AihBHAwSCyACQfK4wAA2AihBGwwRCyACQdO4wAA2AihBHwwQCyACQa24wAA2AihBJgwPCyACQYW4wAA2AihBKAwOCyACQc63wAA2AihBNwwNCyACQae3wAA2AihBJwwMCyACQe+2wAA2AihBOAwLCyACQbe2wAA2AihBOAwKCyACQYm2wAA2AihBLgwJCyACQfG1wAA2AihBGAwICyACQeK1wAA2AihBDwwHCyACQda1wAA2AihBDAwGCyACQbu1wAA2AihBGwwFCyACQaC1wAA2AihBGwwECyACQdG0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ACAERgRAIAEgBBCDASABKAIIIQQLIAEoAgAgBGpB3AA6AAAgBEEBagwHCyADKAIAIARGBEAgASAEEIMBIAEoAgghBAsgASgCACAEakHcADoAACABIARBAWoiBDYCCCADKAIAIARGBEAgASAEEIMBIAEoAgghBAsgASgCACAEakEiOgAAIARBAWoMBgsgAygCACAERgRAIAEgBBCDASABKAIIIQQLIAEoAgAgBGpB3AA6AAAgASAEQQFqIgQ2AgggAygCACAERgRAIAEgBBCDASABKAIIIQQLIAEoAgAgBGpB4gA6AAAgBEEBagwFCyADKAIAIARGBEAgASAEEIMBIAEoAgghBAsgASgCACAEakHcADoAACABIARBAWoiBDYCCCADKAIAIARGBEAgASAEEIMBIAEoAgghBAsgASgCACAEakH0ADoAACAEQQFqDAQLIAMoAgAgBEYEQCABIAQQgwEgASgCCCEECyABKAIAIARqQdwAOgAAIAEgBEEBaiIENgIIIAMoAgAgBEYEQCABIAQQgwEgASgCCCEECyABKAIAIARqQe4AOgAAIARBAWoMAwsgAygCACAERgRAIAEgBBCDASABKAIIIQQLIAEoAgAgBGpB3AA6AAAgASAEQQFqIgQ2AgggAygCACAERgRAIAEgBBCDASABKAIIIQQLIAEoAgAgBGpB5gA6AAAgBEEBagwCCyADKAIAIARGBEAgASAEEIMBIAEoAgghBAsgASgCACAEakHcADoAACABIARBAWoiBDYCCCADKAIAIARGBEAgASAEEIMBIAEoAgghBAsgASgCACAEakHyADoAACAEQQFqDAELAn8CQAJAIAVBIE8EQCAFQYABSQ0BIAVBgBBPDQIgBiAFQT9xQYABcjoADSAGIAVBBnZBwAFyOgAMQQIMAwsgAygCACAERgRAIAEgBBCDASABKAIIIQQLIAEoAgAgBGpB3AA6AAAgASAEQQFqIgQ2AgggAygCACAERgRAIAEgBBCDASABKAIIIQQLIAEoAgAgBGpB9QA6AAAgASAEQQFqIgQ2AgggAygCACAERgRAIAEgBBCDASABKAIIIQQLIAEoAgAgBGpBMDoAACABIARBAWoiBDYCCCADKAIAIARGBEAgASAEEIMBIAEoAgghBAsgASgCACAEakEwOgAAIAEgBEEBaiIENgIIIAVBD3EiCEEKSSEHIAMoAgAgBEYEQCABIAQQgwEgASgCCCEECyABKAIAIARqIAVB8AFxQQR2QTByOgAAIAEgBEEBaiIENgIIIAMoAgAgBEYEQCABIAQQgwEgASgCCCEECyABKAIAIARqIAhBMHIgCEE3aiAHGzoAACAEQQFqDAMLIAMoAgAgBEYEQCABIAQQgwEgASgCCCEECyABKAIAIARqIAU6AAAgBEEBagwCCyAFQYCABE8EQCAGIAVBP3FBgAFyOgAPIAYgBUESdkHwAXI6AAwgBiAFQQZ2QT9xQYABcjoADiAGIAVBDHZBP3FBgAFyOgANQQQMAQsgBiAFQT9xQYABcjoADiAGIAVBDHZB4AFyOgAMIAYgBUEGdkE/cUGAAXI6AA1BAwshBSAFIAMoAgAgBGtLBEAgASAEIAUQhAEgASgCCCEECyABKAIAIARqIAZBDGogBRCLAhogBCAFagsiBDYCCCACIAlHDQALCyABQQRqKAIAIARGBEAgASAEEIMBIAEoAgghBAsgAEEANgIAIAEgBEEBajYCCCABKAIAIARqQSI6AAAgBkEQaiQAC0wBAX8gAUEEaigCACABKAIIIgJrQQNNBEAgASACQQQQhAEgASgCCCECCyAAQQA2AgAgASACQQRqNgIIIAEoAgAgAmpB7uqx4wY2AAALDQAgACABIAIgAxCXAQtSAQF/IAEoAggiAiABKAIERgRAIAEgAhCDASABKAIIIQILIAAgATYCBCAAQQA2AgAgASACQQFqNgIIIABBCGpBAToAACABKAIAIAJqQdsAOgAAC1IBAX8gASgCCCICIAEoAgRGBEAgASACEIMBIAEoAgghAgsgACABNgIEIABBADYCACABIAJBAWo2AgggAEEIakEBOgAAIAEoAgAgAmpB+wA6AAALngICAn8BfiMAQSBrIgUkACABKAIIIgQgASgCBEYEQCABIAQQgwEgASgCCCEECyABIARBAWo2AgggASgCACAEakH7ADoAACAFQRBqIAEgAiADEJcBAkAgBSgCEEUEQCABKAIIIgQgASgCBEYEQCABIAQQgwEgASgCCCEECyABKAIAIARqQTo6AAAgASAEQQFqIgQ2AgggASgCBCAERgRAIAEgBBCDASABKAIIIQQLIAAgATYCBCAAQQA2AgAgASAEQQFqNgIIIABBCGpBAToAACABKAIAIARqQfsAOgAADAELIAVBCGogBUEcaigCACIBNgIAIAUgBSkCFCIGNwMAIABBDGogATYCACAAIAY3AgQgAEEBNgIACyAFQSBqJAALFgAgACgCACIAKAIAIAAoAgQgARCAAgsdACABKAIARQRAAAsgAEGI1cAANgIEIAAgATYCAAtVAQJ/IAEoAgAhAiABQQA2AgACQCACBEAgASgCBCEDQQhBBBA9IgFFDQEgASADNgIEIAEgAjYCACAAQYjVwAA2AgQgACABNgIADwsAC0EIQQQQzgEAC5QEAQN/IwBBMGsiAiQAAn8CQAJAAkACQCAAKAIEIgMOAwACAwELIwBBEGsiACQAIABB0NbAADYCCCAAQQ42AgQgAEG/1sAANgIAIwBBEGsiASQAIAFBCGogAEEIaigCADYCACABIAApAgA3AwAjAEEQayIAJAAgACABKQIANwMIIABBCGpB9NTAAEEAIAEoAghBARCyAQALIAJBLGpBADYCACACQYjVwAA2AiggAkIBNwIcIAJBoNXAADYCGEEBIAEgAkEYahD3AQ0CGiADQQN0IQMgACgCACEAAkADQCACIAA2AhQgBARAIAJBADYCLCACQYjVwAA2AiggAkIBNwIcIAJBrNXAADYCGCABIAJBGGoQ9wENAgsgAkEBNgIsIAJCAjcCHCACQbTVwAA2AhggAkHMADYCBCACIAI2AiggAiACQRRqNgIAIAEgAkEYahD3AQ0BIABBCGohACAEQQFrIQQgA0EIayIDDQALQQAMAwtBAQwCCyACQSxqQQE2AgAgAkICNwIcIAJBtNXAADYCGCACQc0ANgIEIAIgACgCADYCACACIAI2AiggASACQRhqEPcBDAELIAJBDGpBzQA2AgAgAkEsakECNgIAIAJCAzcCHCACQczVwAA2AhggAkHNADYCBCACIAAoAgAiADYCACACIABBCGo2AgggAiACNgIoIAEgAkEYahD3AQsgAkEwaiQACwwAQsiF+aSet9TbEgshAQF/AkAgACgCBCIBRQ0AIABBCGooAgBFDQAgARCrAQsL1gIBAn8jAEEQayICJAAgACgCACEAAkACfwJAIAFBgAFPBEAgAkEANgIMIAFBgBBPDQEgAiABQT9xQYABcjoADSACIAFBBnZBwAFyOgAMQQIMAgsgACgCCCIDIAAoAgRGBEAgACADEBAgACgCCCEDCyAAIANBAWo2AgggACgCACADaiABOgAADAILIAFBgIAETwRAIAIgAUE/cUGAAXI6AA8gAiABQQZ2QT9xQYABcjoADiACIAFBDHZBP3FBgAFyOgANIAIgAUESdkEHcUHwAXI6AAxBBAwBCyACIAFBP3FBgAFyOgAOIAIgAUEMdkHgAXI6AAwgAiABQQZ2QT9xQYABcjoADUEDCyEBIAEgAEEEaigCACAAKAIIIgNrSwRAIAAgAyABEBEgACgCCCEDCyAAKAIAIANqIAJBDGogARCLAhogACABIANqNgIICyACQRBqJABBAAtaAQF/IwBBIGsiAiQAIAIgACgCADYCBCACQRhqIAFBEGopAgA3AwAgAkEQaiABQQhqKQIANwMAIAIgASkCADcDCCACQQRqQeDWwAAgAkEIahDeASACQSBqJAALkwMBBX8CQAJAAkACQCABQQlPBEBBEEEIELMBIAFLDQEMAgsgABCmASEEDAILQRBBCBCzASEBC0EIQQgQswEhA0EUQQgQswEhAkEQQQgQswEhBUEAQRBBCBCzAUECdGsiBkGAgHwgBSACIANqamtBd3FBA2siAyADIAZLGyABayAATQ0AIAFBECAAQQRqQRBBCBCzAUEFayAASxtBCBCzASIDakEQQQgQswFqQQRrEKYBIgJFDQAgAhDDASEAAkAgAUEBayIEIAJxRQRAIAAhAQwBCyACIARqQQAgAWtxEMMBIQJBEEEIELMBIQQgABC3ASACQQAgASACIABrIARLG2oiASAAayICayEEIAAQugFFBEAgASAEELsBIAAgAhC7ASAAIAIQpwEMAQsgACgCACEAIAEgBDYCBCABIAAgAmo2AgALIAEQugENASABELcBIgJBEEEIELMBIANqTQ0BIAEgAxDAASEAIAEgAxC7ASAAIAIgA2siAxC7ASAAIAMQpwEMAQsgBA8LIAEQwgEgARC6ARoL7SECD38BfiMAQRBrIgskAAJAAkAgAEH1AU8EQEEIQQgQswEhBkEUQQgQswEhBUEQQQgQswEhAUEAQRBBCBCzAUECdGsiAkGAgHwgASAFIAZqamtBd3FBA2siASABIAJLGyAATQ0CIABBBGpBCBCzASEEQdD8wAAoAgBFDQFBACAEayEDAkACQAJ/QQAgBEGAAkkNABpBHyAEQf///wdLDQAaIARB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Gg8LDwsgAkF4cUHU/MAAaiEBAn9BzPzAACgCACIDQQEgAkEDdnQiAnEEQCABKAIIDAELQcz8wAAgAiADcjYCACABCyEDIAEgADYCCCADIAA2AgwgACABNgIMIAAgAzYCCAtpACMAQTBrIgEkAEG0/MAALQAABEAgAUEcakEBNgIAIAFCAjcCDCABQcjXwAA2AgggAUHKADYCJCABIAA2AiwgASABQSBqNgIYIAEgAUEsajYCICABQQhqQfDXwAAQ1AEACyABQTBqJAAL3gEBA38jAEEgayIAJAACQEHI/MAAKAIAQf////8HcQRAQZCAwQAoAgANAQtBvPzAACgCAEG8/MAAQX82AgBFBEBBxPzAACgCACEBQcT8wABBuJvAADYCAEHA/MAAKAIAIQJBwPzAAEEBNgIAQbz8wABBADYCAAJAIAFFDQAgAiABKAIAEQYAIAFBBGooAgBFDQAgAUEIaigCABogAhCrAQsgAEEgaiQADwsACyAAQRxqQQA2AgAgAEH41sAANgIYIABCATcCDCAAQbTYwAA2AgggAEEIakHY2MAAENQBAAuLAgIEfwF+IwBBMGsiAiQAIAFBBGohBCABKAIERQRAIAEoAgAhAyACQRBqIgVBADYCACACQgE3AwggAiACQQhqNgIUIAJBKGogA0EQaikCADcDACACQSBqIANBCGopAgA3AwAgAiADKQIANwMYIAJBFGpB4NbAACACQRhqEN4BGiAEQQhqIAUoAgA2AgAgBCACKQMINwIACyACQSBqIgMgBEEIaigCADYCACABQQxqQQA2AgAgBCkCACEGIAFCATcCBCACIAY3AxhBDEEEED0iAUUEQEEMQQQQzgEACyABIAIpAxg3AgAgAUEIaiADKAIANgIAIABBiNnAADYCBCAAIAE2AgAgAkEwaiQAC60BAQN/IwBBMGsiAiQAIAFBBGohAyABKAIERQRAIAEoAgAhASACQRBqIgRBADYCACACQgE3AwggAiACQQhqNgIUIAJBKGogAUEQaikCADcDACACQSBqIAFBCGopAgA3AwAgAiABKQIANwMYIAJBFGpB4NbAACACQRhqEN4BGiADQQhqIAQoAgA2AgAgAyACKQMINwIACyAAQYjZwAA2AgQgACADNgIAIAJBMGokAAtFAQJ/IAEoAgQhAiABKAIAIQNBCEEEED0iAUUE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BnZBwAFyOgAMQQIMAgsgACgCCCIDIAAoAgRGBEAgACADEIMBIAAoAgghAwsgACADQQFqNgIIIAAoAgAgA2ogAToAAAwCCyABQYCABE8EQCACIAFBP3FBgAFyOgAPIAIgAUEGdkE/cUGAAXI6AA4gAiABQQx2QT9xQYABcjoADSACIAFBEnZBB3FB8AFyOgAMQQQMAQsgAiABQT9xQYABcjoADiACIAFBDHZB4AFyOgAMIAIgAUEGdkE/cUGAAXI6AA1BAwshASABIABBBGooAgAgACgCCCIDa0sEQCAAIAMgARCEASAAKAIIIQMLIAAoAgAgA2ogAkEMaiABEIsCGiAAIAEgA2o2AggLIAJBEGokAEEAC1oBAX8jAEEgayICJAAgAiAAKAIANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpB0NnAACACQQhqEN4BIAJBIGokAAtLAQF/IAIgACgCACIAQQRqKAIAIAAoAggiA2tLBEAgACADIAIQhAEgACgCCCEDCyAAKAIAIANqIAEgAhCLAhogACACIANqNgIIQQALGgAgACABQbj8wAAoAgAiAEHSACAAGxECAAALQAEBfyMAQSBrIgAkACAAQRxqQQA2AgAgAEH42cAANgIYIABCATcCDCAAQajawAA2AgggAEEIakGw2sAAENQBAAvpAwEGfyMAQTBrIgUkAAJAAkACQAJAAkAgASgCBCIDBEAgASgCACEHIANBAWtB/////wFxIgNBAWoiBkEHcSEEAn8gA0EHSQRAQQAhAyAHDAELIAdBPGohAiAGQfj///8DcSEGQQAhAwNAIAIoAgAgAkEIaygCACACQRBrKAIAIAJBGGsoAgAgAkEgaygCACACQShrKAIAIAJBMGsoAgAgAkE4aygCACADampqampqamohAyACQUBrIQIgBkEIayIGDQALIAJBPGsLIQIgBARAIAJBBGohAgNAIAIoAgAgA2ohAyACQQhqIQIgBEEBayIEDQALCyABQRRqKAIADQEgAyEEDAMLQQAhAyABQRRqKAIADQFBASECDAQLIAcoAgQNACADQRBJDQILIAMgA2oiBCADSQ0BCyAERQ0AAkAgBEF/SgRAIARBARA9IgJFDQEgBCEDDAMLEM8BAAsgBEEBEM4BAAtBASECQQAhAwsgAEEANgIIIAAgAzYCBCAAIAI2AgAgBSAANgIMIAVBIGogAUEQaikCADcDACAFQRhqIAFBCGopAgA3AwAgBSABKQIANwMQIAVBDGpB0NnAACAFQRBqEN4BBEBBwNrAAEEzIAVBKGpB9NrAAEGc28AAEOkBAAsgBUEwaiQAC2cBAn8gASgCACEDAkACQAJAIAFBCGooAgAiAUUEQEEBIQIMAQsgAUF/TA0BIAFBARA9IgJFDQILIAIgAyABEIsCIQIgACABNgIIIAAgATYCBCAAIAI2AgAPCxDPAQALIAFBARDOAQALUwEBfyMAQRBrIgIkACACIAA2AgggAiAAQQxqNgIMIAFBzNzAAEENQbDcwABBBSACQQhqQaDcwABBtdzAAEEFIAJBDGpBvNzAABD7ASACQRBqJAALDgAgACgCABoDQAwACwAL4QIBAn8jAEEgayICJAAgAkEBOgAYIAIgATYCFCACIAA2AhAgAkHQ38AANgIMIAJB3NzAADYCCCMAQRBrIgEkAAJAIAJBCGoiACgCDCICBEAgACgCCCIDRQ0BIAEgAjYCCCABIAA2AgQgASADNgIAIwBBEGsiACQAIABBCGogAUEIaigCADYCACAAIAEpAgA3AwAjAEEQayIBJAAgACgCACICQRRqKAIAIQMCQAJ/AkACQCACKAIEDgIAAQMLIAMNAkEAIQJB+NbAAAwBCyADDQEgAigCACIDKAIEIQIgAygCAAshAyABIAI2AgQgASADNgIAIAFBvNnAACAAKAIEIgEoAgggACgCCCABLQAQELIBAAsgAUEANgIEIAEgAjYCACABQajZwAAgACgCBCIBKAIIIAAoAgggAS0AEBCyAQALQfjWwABBK0H42MAAENkBAAtB+NbAAEErQejYwAAQ2QEAC28BAX8jAEEwayIDJAAgAyABNgIEIAMgADYCACADQRxqQQI2AgAgA0EsakHKADYCACADQgI3AgwgA0H83sAANgIIIANBygA2AiQgAyADQSBqNgIYIAMgAzYCKCADIANBBGo2AiAgA0EIaiACENQBAAtvAQF/IwBBMGsiAyQAIAMgATYCBCADIAA2AgAgA0EcakECNgIAIANBLGpBygA2AgAgA0ICNwIMIANBkOTAADYCCCADQcoANgIkIAMgA0EgajYCGCADIANBBGo2AiggAyADNgIgIANB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AAgAAAAUAAAAL1VzZXJzL2RlYXJrYW5lLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL2Nvc213YXNtLXN0ZC0xLjEuOS9zcmMvZXhwb3J0cy5ycwAAAAABEABhAAAAjQAAAA0AAAAAARAAYQAAAG8AAAANAAAAAAEQAGEAAADqAAAADQAAAHdhc21jdXN0b21iYW5rQmFua01zZ2J1cm5zZW5kdG9fYWRkcmVzc1dhc21Nc2djbGVhcl9hZG1pbmNvbnRyYWN0X2FkZHJ1cGRhdGVfYWRtaW5hZG1pbm1pZ3JhdGVuZXdfY29kZV9pZG1zZ2luc3RhbnRpYXRlY29kZV9pZGxhYmVsZXhlY3V0ZVN1Yk1zZ2dhc19saW1pdFJlcGx5T25uZXZlcnN1Y2Nlc3NlcnJvcmFsd2F5c29rRW1wdHlFdmVudHR5cGVhdHRyaWJ1dGVzQXR0cmlidXRla2V5dmFsdWVSZXNwb25zZWV2ZW50c0NvbnRyYWN0VmVyc2lvbnZlcnNpb25jb250cmFjdF9pbmZvABUAAAAMAAAABAAAABYAAAAXAAAAGAAAAGEgRGlzcGxheSBpbXBsZW1lbnRhdGlvbiByZXR1cm5lZCBhbiBlcnJvciB1bmV4cGVjdGVkbHkABQAAAAAAAAABAAAAGQAAAC9ydXN0Yy84OTdlMzc1NTNiYmE4YjQyNzUxYzY3NjU4OTY3ODg5ZDExZWNkMTIwL2xpYnJhcnkvYWxsb2Mvc3JjL3N0cmluZy5ycwAIAxAASwAAAM4JAAAJAAAAY3dfY291bnRlcjo6bXNnOjpFeGVjdXRlTXNnY3dfY291bnRlcjo6bXNnOjpHZXRDb3VudFJlc3BvbnNlY3dfY291bnRlcjo6bXNnOjpRdWVyeU1zZ2Nvc213YXNtX3N0ZDo6cmVzdWx0czo6Y29udHJhY3RfcmVzdWx0OjpDb250cmFjdFJlc3VsdDxjb3Ntd2FzbV9zdGQ6OnJlc3VsdHM6OnJlc3BvbnNlOjpSZXNwb25zZT5jb3Ntd2FzbV9zdGQ6OnJlc3VsdHM6OmNvbnRyYWN0X3Jlc3VsdDo6Q29udHJhY3RSZXN1bHQ8Y29zbXdhc21fc3RkOjpiaW5hcnk6OkJpbmFyeT5jb3Ntd2FzbV9zdGQ6OnR5cGVzOjpNZXNzYWdlSW5mb2Nvc213YXNtX3N0ZDo6dHlwZXM6OkVudmN3X2NvdW50ZXI6OnN0YXRlOjpTdGF0ZWN3X2NvdW50ZXI6Om1zZzo6SW5zdGFudGlhdGVNc2djdzI6OkNvbnRyYWN0VmVyc2lvbgAAAAUAAAAEAAAABAAAABoAAAAbAAAAHAAAAG1pc3NpbmcgZmllbGQgYGAMBRAADwAAABsFEAABAAAAdW5rbm93biBmaWVsZCBgYCwgZXhwZWN0ZWQgACwFEAAPAAAAOwUQAAwAAABgLCB0aGVyZSBhcmUgbm8gZmllbGRzAAAsBRAADwAAAFgFEAAWAAAAZHVwbGljYXRlIGZpZWxkIGAAAACABRAAEQAAABsFEAABAAAAdW5rbm93biB2YXJpYW50IGAAAACkBRAAEQAAADsFEAAMAAAAaW52YWxpZCBVaW50NjQgJycgLSDIBRAAEAAAANgFEAAEAAAAaW52YWxpZCBVaW50MTI4ICcAAADsBRAAEQAAANgFEAAEAAAAdWxsc3RhdGVhY3Rpb25pbmNyZW1lbnRzcmMvY29udHJhY3QucnMAACcGEAAPAAAANAAAAA0AAAByZXNldGNyYXRlcy5pbzpjdy1jb3VudGVyMC4xLjBtZXRob2Rvd25lcmNvdW50VW5hdXRob3JpemVkAAB2BhAADAAAAAwFEAAAAAAAcQYQAAUAAAAeBhAACQAAAEgGEAAFAAAAZ2V0X2NvdW50AAAArAYQAAkAAABHZXRDb3VudFJlc3BvbnNlU3RhdGUvcnVzdGMvODk3ZTM3NTUzYmJhOGI0Mjc1MWM2NzY1ODk2Nzg4OWQxMWVjZDEyMC9saWJyYXJ5L2NvcmUvc3JjL2l0ZXIvYWRhcHRlcnMvZW51bWVyYXRlLnJz1QYQAFsAAAAwAAAACQAAAGF0dGVtcHQgdG8gYWRkIHdpdGggb3ZlcmZsb3cAAAAAYXR0ZW1wdCB0byBtdWx0aXBseSB3aXRoIG92ZXJmbG93AAAAKAAAAAgAAAAEAAAAKQAAACoAAAArAAAADAAAAAQAAAAsAAAALQAAAC4AAABhIERpc3BsYXkgaW1wbGVtZW50YXRpb24gcmV0dXJuZWQgYW4gZXJyb3IgdW5leHBlY3RlZGx5ACgAAAAAAAAAAQAAABkAAAAvcnVzdGMvODk3ZTM3NTUzYmJhOGI0Mjc1MWM2NzY1ODk2Nzg4OWQxMWVjZDEyMC9saWJyYXJ5L2FsbG9jL3NyYy9zdHJpbmcucnMA+AcQAEsAAADOCQAACQAAAGNvc213YXNtX3N0ZDo6cmVzdWx0czo6c3lzdGVtX3Jlc3VsdDo6U3lzdGVtUmVzdWx0PGNvc213YXNtX3N0ZDo6cmVzdWx0czo6Y29udHJhY3RfcmVzdWx0OjpDb250cmFjdFJlc3VsdDxjb3Ntd2FzbV9zdGQ6OmJpbmFyeTo6QmluYXJ5Pj4oAAAABAAAAAQAAAAvAAAAMAAAADEAAABpbnRlcm5hbCBlcnJvcjogZW50ZXJlZCB1bnJlYWNoYWJsZSBjb2RlOiAAAPQIEAAqAAAAL3J1c3RjLzg5N2UzNzU1M2JiYThiNDI3NTFjNjc2NTg5Njc4ODlkMTFlY2QxMjAvbGlicmFyeS9jb3JlL3NyYy9pdGVyL3RyYWl0cy9hY2N1bS5ycwAAACgJEABVAAAAjQAAAAEAAABtaXNzaW5nIGZpZWxkIGBgkAkQAA8AAACfCRAAAQAAAGR1cGxpY2F0ZSBmaWVsZCBgAAAAsAkQABEAAACfCRAAAQAAAHVua25vd24gdmFyaWFudCBgYCwgZXhwZWN0ZWQgAAAA1AkQABEAAADlCRAADAAAACgAAAAEAAAABAAAADIAAAAvVXNlcnMvZGVhcmthbmUvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvYmFzZTY0LTAuMTMuMC9zcmMvZGVjb2RlLnJzABQKEABbAAAAbgAAAC8AAABhdHRlbXB0IHRvIHN1YnRyYWN0IHdpdGggb3ZlcmZsb3cAAAAUChAAWwAAAAMBAAA3AAAAFAoQAFsAAAADAQAAJAAAABQKEABbAAAABAEAACkAAAAUChAAWwAAACEBAAARAAAAFAoQAFsAAAAqAQAAKQAAABQKEABbAAAAKgEAABYAAAAUChAAWwAAAC4BAAApAAAAFAoQAFsAAAAuAQAAKAAAABQKEABbAAAALQEAABoAAAAUChAAWwAAADMBAAARAAAAFAoQAFsAAABBAQAADgAAABQKEABbAAAARAEAACcAAAAUChAAWwAAAEQBAAASAAAAFAoQAFsAAABHAQAACQAAABQKEABbAAAAWAEAABMAAAAUChAAWwAAAGYBAAApAAAAFAoQAFsAAAB4AQAADQAAABQKEABbAAAAggEAABEAAAAUChAAWwAAAIoBAAAVAAAAFAoQAFsAAACOAQAAMQAAAEltcG9zc2libGU6IG11c3Qgb25seSBoYXZlIDAgdG8gOCBpbnB1dCBieXRlcyBpbiBsYXN0IGNodW5rLCB3aXRoIG5vIGludmFsaWQgbGVuZ3Roc+QLEABUAAAAFAoQAFsAAACdAQAADgAAABQKEABbAAAAqAEAAA0AAAAUChAAWwAAALEBAAAJAAAAT3ZlcmZsb3cgd2hlbiBjYWxjdWxhdGluZyBvdXRwdXQgYnVmZmVyIGxlbmd0aAAAFAoQAFsAAACTAAAAIAAAABQKEABbAAAAJwIAAAUAAABJbnZhbGlkIFVURjgrAAAAFAAAAAQAAAAzAAAAL1VzZXJzL2RlYXJrYW5lLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL2Jhc2U2NC0wLjEzLjAvc3JjL2VuY29kZS5ycwDcDBAAWwAAADQAAAAFAAAAaW50ZWdlciBvdmVyZmxvdyB3aGVuIGNhbGN1bGF0aW5nIGJ1ZmZlciBzaXplAAAA3AwQAFsAAAAvAAAAEQAAACgAAAAIAAAABAAAADQAAAD0CBAAAAAAAGludmFsaWQgYmFzZTY0OiCgDRAAEAAAACgAAAAAAAAAAQAAADUAAAA2AAAANgAAAC9Vc2Vycy9kZWFya2FuZS8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy9jb3Ntd2FzbS1zdGQtMS4xLjkvc3JjL3NlY3Rpb25zLnJzAADQDRAAYgAAABoAAAAQAAAA0A0QAGIAAAAaAAAABQAAANANEABiAAAAOQAAABgAAABDYW5ub3QgcmVhZCBzZWN0aW9uIGxlbmd0aAAAZA4QABoAAADQDRAAYgAAADcAAAAJAAAAVEw7RFI6IFZhbHVlIG11c3Qgbm90IGJlIGVtcHR5IGluIFN0b3JhZ2U6OnNldCBidXQgaW4gbW9zdCBjYXNlcyB5b3UgY2FuIHVzZSBTdG9yYWdlOjpyZW1vdmUgaW5zdGVhZC4gTG9uZyBzdG9yeTogR2V0dGluZyBlbXB0eSB2YWx1ZXMgZnJvbSBzdG9yYWdlIGlzIG5vdCB3ZWxsIHN1cHBvcnRlZCBhdCB0aGUgbW9tZW50LiBTb21lIG9mIG91ciBpbnRlcm5hbCBpbnRlcmZhY2VzIGNhbm5vdCBkaWZmZXJlbnRpYXRlIGJldHdlZW4gYSBub24tZXhpc3RlbnQga2V5IGFuZCBhbiBlbXB0eSB2YWx1ZS4gUmlnaHQgbm93LCB5b3UgY2Fubm90IHJlbHkgb24gdGhlIGJlaGF2aW91ciBvZiBlbXB0eSB2YWx1ZXMuIFRvIHByb3RlY3QgeW91IGZyb20gdHJvdWJsZSBsYXRlciBvbiwgd2Ugc3RvcCBoZXJlLiBTb3JyeSBmb3IgdGhlIGluY29udmVuaWVuY2UhIFdlIGhpZ2hseSB3ZWxjb21lIHlvdSB0byBjb250cmlidXRlIHRvIENvc21XYXNtLCBtYWtpbmcgdGhpcyBtb3JlIHNvbGlkIG9uZSB3YXkgb3IgdGhlIG90aGVyLpgOEAAIAgAAL1VzZXJzL2RlYXJrYW5lLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL2Nvc213YXNtLXN0ZC0xLjEuOS9zcmMvaW1wb3J0cy5ycwAAAKgQEABhAAAAawAAAA0AAAAoAAAABAAAAAQAAAA3AAAAOAAAADkAAAA6AAAAaW5wdXQgdG9vIGxvbmcgZm9yIGFkZHJfdmFsaWRhdGVhZGRyX3ZhbGlkYXRlIGVycm9yZWQ6IABYERAAFwAAAGlucHV0IHRvbyBsb25nIGZvciBhZGRyX2Nhbm9uaWNhbGl6ZWFkZHJfY2Fub25pY2FsaXplIGVycm9yZWQ6IACcERAAGwAAAGFkZHJfaHVtYW5pemUgZXJyb3JlZDogAMAREAAXAAAATWVzc2FnZVRvb0xvbmcgbXVzdCBub3QgaGFwcGVuLiBUaGlzIGlzIGEgYnVnIGluIHRoZSBWTS7gERAAOAAAAKgQEABhAAAACAEAABIAAACoEBAAYQAAACUBAAASAAAASW52YWxpZEhhc2hGb3JtYXQgbXVzdCBub3QgaGFwcGVuLiBUaGlzIGlzIGEgYnVnIGluIHRoZSBWTS4AQBIQADsAAACoEBAAYQAAAD8BAAASAAAARXJyb3IgY29kZSAyIHVudXNlZCBzaW5jZSBDb3NtV2FzbSAwLjE1LiBUaGlzIGlzIGEgYnVnIGluIHRoZSBWTS4AAACUEhAAQQAAAKgQEABhAAAAPgEAABIAAACoEBAAYQAAAF8BAAASAAAAqBAQAGEAAABeAQAAEgAAAFJlZ2lvbiBwb2ludGVyIGlzIG51bGwAABATEAAWAAAAL1VzZXJzL2RlYXJrYW5lLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL2Nvc213YXNtLXN0ZC0xLjEuOS9zcmMvbWVtb3J5LnJzMBMQAGAAAAA5AAAABQAAAFJlZ2lvbiBzdGFydHMgYXQgbnVsbCBwb2ludGVyAAAAoBMQAB0AAAAwExAAYAAAAD8AAAAFAAAAVW5rbm93biBlcnJvcjogANgTEAAPAAAASW52YWxpZCByZWNvdmVyeSBwYXJhbWV0ZXIuIFN1cHBvcnRlZCB2YWx1ZXM6IDAgYW5kIDEuAADwExAANgAAAEludmFsaWQgc2lnbmF0dXJlIGZvcm1hdDAUEAAYAAAASW52YWxpZCBoYXNoIGZvcm1hdABQFBAAEwAAAFVua25vd25FcnJlcnJvcl9jb2RlKAAAAAQAAAAEAAAAOwAAAEludmFsaWRSZWNvdmVyeVBhcmFtSW52YWxpZFNpZ25hdHVyZUZvcm1hdEludmFsaWRIYXNoRm9ybWF0Q29udmVyc2lvbiBlcnJvcjogAAAAyxQQABIAAABEaXZpZGUgYnkgemVybzog6BQQABAAAABPdmVyZmxvdzogAAAAFRAACgAAAEVycm9yIHNlcmlhbGl6aW5nIHR5cGUgOiAAAAAUFRAAFwAAACsVEAACAAAARXJyb3IgcGFyc2luZyBpbnRvIHR5cGUgQBUQABgAAAArFRAAAgAAACBub3QgZm91bmQAAPQIEAAAAAAAaBUQAAoAAABDYW5ub3QgZGVjb2RlIFVURjggYnl0ZXMgaW50byBzdHJpbmc6IAAAhBUQACYAAABJbnZhbGlkIGhleCBzdHJpbmc6ILQVEAAUAAAASW52YWxpZCBkYXRhIHNpemU6IGV4cGVjdGVkPSBhY3R1YWw90BUQABwAAADsFRAACAAAAEludmFsaWQgQmFzZTY0IHN0cmluZzogAAQWEAAXAAAAR2VuZXJpYyBlcnJvcjogACQWEAAPAAAAUmVjb3ZlciBwdWJrZXkgZXJyb3I6IAAAPBYQABYAAABWZXJpZmljYXRpb24gZXJyb3I6IFwWEAAUAAAAQ29udmVyc2lvbk92ZXJmbG93c291cmNlKAAAAAQAAAAEAAAAPAAAAERpdmlkZUJ5WmVybygAAAAEAAAABAAAAD0AAABPdmVyZmxvdygAAAAEAAAABAAAAD4AAABTZXJpYWxpemVFcnJzb3VyY2VfdHlwZW1zZ1BhcnNlRXJydGFyZ2V0X3R5cGVOb3RGb3VuZGtpbmRJbnZhbGlkVXRmOEludmFsaWRIZXhJbnZhbGlkRGF0YVNpemVleHBlY3RlZAAAACgAAAAEAAAABAAAAD8AAABhY3R1YWxJbnZhbGlkQmFzZTY0R2VuZXJpY0VyclJlY292ZXJQdWJrZXlFcnIAAAAoAAAABAAAAAQAAABAAAAAVmVyaWZpY2F0aW9uRXJyACgAAAAEAAAABAAAAEEAAABTaGxTaHJQb3dNdWxTdWJBZGRDYW5ub3QgIHdpdGggIGFuZCC+FxAABwAAAMUXEAAGAAAAyxcQAAUAAABPdmVyZmxvd0Vycm9yb3BlcmF0aW9uAAAoAAAABAAAAAQAAAAdAAAAb3BlcmFuZDFvcGVyYW5kMkNvbnZlcnNpb25PdmVyZmxvd0Vycm9yACgAAAAEAAAABAAAAEIAAAB2YWx1ZUNhbm5vdCBkZXZpZGUgIGJ5IHplcm8ATRgQAA4AAABbGBAACAAAAERpdmlkZUJ5WmVyb0Vycm9yb3BlcmFuZGludmFsaWRfcmVxdWVzdGludmFsaWRfcmVzcG9uc2Vub19zdWNoX2NvbnRyYWN0dW5rbm93bnVuc3VwcG9ydGVkX3JlcXVlc3QAAACMGBAADwAAAJsYEAAQAAAAqxgQABAAAAC7GBAABwAAAMIYEAATAAAAYWRkcmVycm9ycmVzcG9uc2VyZXF1ZXN0SW52YWxpZCBwdWJsaWMga2V5IGZvcm1hdAAAABgZEAAZAAAAR2VuZXJpYyBlcnJvcgAAADwZEAANAAAAQmF0Y2ggZXJyb3IAVBkQAAsAAABJbnZhbGlkUHVia2V5Rm9ybWF0QmF0Y2hFcnJvawAAAIMZEAACAAAABBkQAAUAAAC7FxAAuBcQALUXEACyFxAArxcQAKwXEABFAAAACAAAAAQAAABGAAAARwAAAEUAAAAIAAAABAAAAEgAAADEGRAAAAAAAEpTT04gaGFzIGEgY29tbWEgYWZ0ZXIgdGhlIGxhc3QgdmFsdWUgaW4gYW4gYXJyYXkgb3IgbWFwLkpTT04gaGFzIG5vbi13aGl0ZXNwYWNlIHRyYWlsaW5nIGNoYXJhY3RlcnMgYWZ0ZXIgdGhlIHZhbHVlLkZvdW5kIGEgbG9uZSBzdXJyb2dhdGUsIHdoaWNoIGNhbiBleGlzdCBpbiBKU09OIGJ1dCBjYW5ub3QgYmUgZW5jb2RlZCB0byBVVEYtOC5PYmplY3Qga2V5IGlzIG5vdCBhIHN0cmluZy5JbnZhbGlkIHVuaWNvZGUgY29kZSBwb2ludC5JbnZhbGlkIHR5cGVJbnZhbGlkIG51bWJlci5JbnZhbGlkIGVzY2FwZSBzZXF1ZW5jZS5FeHBlY3RlZCB0aGlzIGNoYXJhY3RlciB0byBzdGFydCBhIEpTT04gdmFsdWUuRXhwZWN0ZWQgdG8gcGFyc2UgZWl0aGVyIGEgYHRydWVgLCBgZmFsc2VgLCBvciBhIGBudWxsYC5FeHBlY3RlZCB0aGlzIGNoYXJhY3RlciB0byBiZSBlaXRoZXIgYSBgJywnYCBvciBhIGAnfSdgLkV4cGVjdGVkIGEgbG93IHN1cnJvZ2F0ZSAoREMwMOKAk0RGRkYpLkV4cGVjdGVkIHRoaXMgY2hhcmFjdGVyIHRvIGJlIGVpdGhlciBhIGAnLCdgIG9yYSBgJ10nYC5FeHBlY3RlZCBhIGhpZ2ggc3Vycm9nYXRlIChEODAw4oCTREJGRikuRXhwZWN0ZWQgdGhpcyBjaGFyYWN0ZXIgdG8gYmUgYSBgJzonYC5FT0Ygd2hpbGUgcGFyc2luZyBhIEpTT04gdmFsdWUuRU9GIHdoaWxlIHBhcnNpbmcgYSBzdHJpbmcuRU9GIHdoaWxlIHBhcnNpbmcgYW4gb2JqZWN0LkVPRiB3aGlsZSBwYXJzaW5nIGEgbGlzdC5Db250cm9sIGNoYXJhY3RlciBmb3VuZCBpbiBzdHJpbmcuL1VzZXJzL2RlYXJrYW5lLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL3NlcmRlLWpzb24td2FzbS0wLjQuMS9zcmMvZGUvdW5lc2NhcGUucnPkHBAAaAAAACUAAAAVAAAAAAAAAGF0dGVtcHQgdG8gYWRkIHdpdGggb3ZlcmZsb3fkHBAAaAAAADMAAAApAAAAAAAAAGF0dGVtcHQgdG8gc3VidHJhY3Qgd2l0aCBvdmVyZmxvd05vbi1oZXggQVNDSUkgY2hhcmFjdGVyIGZvdW5kAADkHBAAaAAAAJkAAAAOAAAAL1VzZXJzL2RlYXJrYW5lLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL3NlcmRlLWpzb24td2FzbS0wLjQuMS9zcmMvZGUvbW9kLnJzAOAdEABjAAAAJAAAAAkAAADgHRAAYwAAAH0AAAAiAAAA4B0QAGMAAACBAAAALAAAAEJ1ZmZlciBpcyBmdWxsAAB0HhAADgAAAC9Vc2Vycy9kZWFya2FuZS8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy9zZXJkZS1qc29uLXdhc20tMC40LjEvc3JjL3Nlci9tb2QucnOMHhAAZAAAALUAAAAJAAAAjB4QAGQAAADXAAAACQAAAGludGVybmFsIGVycm9yOiBlbnRlcmVkIHVucmVhY2hhYmxlIGNvZGU6IAAAEB8QACoAQdC+wAALIWF0dGVtcHQgdG8gc3VidHJhY3Qgd2l0aCBvdmVyZmxvdwBBgL/AAAv0JmF0dGVtcHQgdG8gYWRkIHdpdGggb3ZlcmZsb3cvVXNlcnMvZGVhcmthbmUvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvYmFzZTY0LTAuMTMuMC9zcmMvZW5jb2RlLnJzAJwfEABbAAAAkgAAACcAAAB1c2l6ZSBvdmVyZmxvdyB3aGVuIGNhbGN1bGF0aW5nIGI2NCBsZW5ndGgAAJwfEABbAAAAlwAAABkAAACcHxAAWwAAALYAAAAgAAAAnB8QAFsAAAC3AAAAOgAAAJwfEABbAAAAtwAAACUAAACcHxAAWwAAAPcAAAAYAAAAnB8QAFsAAAD8AAAALwAAAJwfEABbAAAA/AAAABwAAACcHxAAWwAAAP0AAAA2AAAAnB8QAFsAAAD9AAAAIQAAAJwfEABbAAAAEwEAAC4AAACcHxAAWwAAABMBAAAJAAAAnB8QAFsAAAAUAQAACQAAAJwfEABbAAAACwEAAC4AAACcHxAAWwAAAAsBAAAJAAAAnB8QAFsAAAANAQAADwAAAJwfEABbAAAADAEAAAkAAACcHxAAWwAAAA8BAAAJAAAAnB8QAFsAAAARAQAACQAAAEltcG9zc2libGUgcmVtYWluZGVyVCEQABQAAACcHxAAWwAAACoBAAAWAAAAnB8QAFsAAAA7AQAACQAAAEludmFsaWQgbGFzdCBzeW1ib2wgLCBvZmZzZXQgLgAAkCEQABQAAACkIRAACQAAAK0hEAABAAAARW5jb2RlZCB0ZXh0IGNhbm5vdCBoYXZlIGEgNi1iaXQgcmVtYWluZGVyLgDIIRAAKwAAAEludmFsaWQgYnl0ZSAAAAD8IRAADQAAAKQhEAAJAAAArSEQAAEAAABPdmVyZmxvdyB3aGVuIGNhbGN1bGF0aW5nIG51bWJlciBvZiBjaHVua3MgaW4gaW5wdXQvVXNlcnMvZGVhcmthbmUvLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvYmFzZTY0LTAuMTMuMC9zcmMvZGVjb2RlLnJzAABXIhAAWwAAALkAAAAFAAAAISIjJCUmJygpKissLTAxMjM0NTY3ODlAQUJDREVGR0hJSktMTU5QUVJTVFVWWFlaW2BhYmNkZWhpamtsbXBxckFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5KywuL0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Li8wMTIzNDU2Nzg5QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ekFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5LV9BQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSsv////////////////////////////////////////////AAECAwQFBgcICQoLDP//DQ4PEBESExQVFv///////xcYGRobHB0eHyAhIiMkJf8mJygpKiss/y0uLzD/////MTIzNDU2//83ODk6Ozz//z0+P/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8+P////zQ1Njc4OTo7PD3/////////AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBn///////8aGxwdHh8gISIjJCUmJygpKissLS4vMDEyM///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AAE2Nzg5Ojs8PT4//////////wIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRob////////HB0eHyAhIiMkJSYnKCkqKywtLi8wMTIzNDX//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wABAgMEBQYHCAkKC/////////8MDQ4PEBESExQVFhcYGRobHB0eHyAhIiMkJf///////yYnKCkqKywtLi8wMTIzNDU2Nzg5Ojs8PT4//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////z7//zQ1Njc4OTo7PD3/////////AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBn/////P/8aGxwdHh8gISIjJCUmJygpKissLS4vMDEyM///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Pv///z80NTY3ODk6Ozw9/////////wABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZ////////GhscHR4fICEiIyQlJicoKSorLC0uLzAxMjP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////BCQQAMQjEACEIxAARCMQAAQjEADEIhAARCkQAEQoEABEJxAARCYQAEQlEABEJBAATgAAAAgAAAAEAAAATwAAAFAAAABOAAAACAAAAAQAAABRAAAAYG9uZSBvZiCZKhAABwAAACwgAACoKhAAAgAAAJgqEAABAAAAmCoQAAEAAABgIG9yIGAAAJgqEAABAAAAxCoQAAYAAACYKhAAAQAAAC9Vc2Vycy9kZWFya2FuZS8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy9zZXJkZS0xLjAuMTUwL3NyYy9kZS9tb2QucnNleHBsaWNpdCBwYW5pYwAAAOQqEABbAAAA7QgAABIAAABTAAAABAAAAAQAAABUAAAAVQAAAFYAAABjYWxsZWQgYE9wdGlvbjo6dW53cmFwKClgIG9uIGEgYE5vbmVgIHZhbHVlbWVtb3J5IGFsbG9jYXRpb24gb2YgIGJ5dGVzIGZhaWxlZAoAAKMrEAAVAAAAuCsQAA4AAABsaWJyYXJ5L3N0ZC9zcmMvYWxsb2MucnPYKxAAGAAAAFUBAAAJAAAAY2Fubm90IG1vZGlmeSB0aGUgcGFuaWMgaG9vayBmcm9tIGEgcGFuaWNraW5nIHRocmVhZAAsEAA0AAAAbGlicmFyeS9zdGQvc3JjL3Bhbmlja2luZy5yczwsEAAcAAAAfQAAAAkAAAA8LBAAHAAAAEcCAAAPAAAAPCwQABwAAABGAgAADwAAAFcAAAAMAAAABAAAAFgAAABTAAAACAAAAAQAAABZAAAAWgAAABAAAAAEAAAAWwAAAFwAAABTAAAACAAAAAQAAABdAAAAXgAAAF8AAAAEAAAABAAAAGAAAABhAAAAYgAAAF8AAAAEAAAABAAAAGMAAABsaWJyYXJ5L2FsbG9jL3NyYy9yYXdfdmVjLnJzY2FwYWNpdHkgb3ZlcmZsb3cAAAAULRAAEQAAAPgsEAAcAAAABgIAAAUAAABhIGZvcm1hdHRpbmcgdHJhaXQgaW1wbGVtZW50YXRpb24gcmV0dXJuZWQgYW4gZXJyb3IAXwAAAAAAAAABAAAAGQAAAGxpYnJhcnkvYWxsb2Mvc3JjL2ZtdC5yc4QtEAAYAAAAZAIAAAkAAAApbGlicmFyeS9hbGxvYy9zcmMvdmVjL21vZC5ycykgc2hvdWxkIGJlIDw9IGxlbiAoaXMgYGF0YCBzcGxpdCBpbmRleCAoaXMgAAAA4C0QABUAAADJLRAAFwAAAKwtEAABAAAArS0QABwAAADLBwAADQAAAF8AAAAEAAAABAAAAGQAAABieXRlc2Vycm9yAABfAAAABAAAAAQAAABlAAAARnJvbVV0ZjhFcnJvcgAAAGNhbGxlZCBgT3B0aW9uOjp1bndyYXAoKWAgb24gYSBgTm9uZWAgdmFsdWVudW1iZXIgd291bGQgYmUgemVybyBmb3Igbm9uLXplcm8gdHlwZW51bWJlciB0b28gc21hbGwgdG8gZml0IGluIHRhcmdldCB0eXBlbnVtYmVyIHRvbyBsYXJnZSB0byBmaXQgaW4gdGFyZ2V0IHR5cGVpbnZhbGlkIGRpZ2l0IGZvdW5kIGluIHN0cmluZ2Nhbm5vdCBwYXJzZSBpbnRlZ2VyIGZyb20gZW1wdHkgc3RyaW5nKS4uAD0vEAACAAAAaW5kZXggb3V0IG9mIGJvdW5kczogdGhlIGxlbiBpcyAgYnV0IHRoZSBpbmRleCBpcyAAAEgvEAAgAAAAaC8QABIAAAA6AAAAXC4QAAAAAACMLxAAAQAAAIwvEAABAAAAcGFuaWNrZWQgYXQgJycsILQvEAABAAAAtS8QAAMAAABcLhAAAAAAAG0AAAAAAAAAAQAAAG4AAABgOiAAXC4QAAAAAADhLxAAAgAAAG0AAAAMAAAABAAAAG8AAABwAAAAcQAAACAgICAgewosCiwgIHsgfSB9KAooLApbAG0AAAAEAAAABAAAAHIAAABdbGlicmFyeS9jb3JlL3NyYy9mbXQvbnVtLnJzNTAQABsAAABlAAAAFAAAADB4MDAwMTAyMDMwNDA1MDYwNzA4MDkxMDExMTIxMzE0MTUxNjE3MTgxOTIwMjEyMjIzMjQyNTI2MjcyODI5MzAzMTMyMzMzNDM1MzYzNzM4Mzk0MDQxNDI0MzQ0NDU0NjQ3NDg0OTUwNTE1MjUzNTQ1NTU2NTc1ODU5NjA2MTYyNjM2NDY1NjY2NzY4Njk3MDcxNzI3Mzc0NzU3Njc3Nzg3OTgwODE4MjgzODQ4NTg2ODc4ODg5OTA5MTkyOTM5NDk1OTY5Nzk4OTlhc3NlcnRpb24gZmFpbGVkOiAqY3VyciA+IDE5AAA1MBAAGwAAAOUBAAAFAAAAbQAAAAQAAAAEAAAAcwAAAHQAAAB1AAAAbGlicmFyeS9jb3JlL3NyYy9mbXQvbW9kLnJzAHAxEAAbAAAAdAkAAB4AAABwMRAAGwAAAHsJAAAWAAAAbGlicmFyeS9jb3JlL3NyYy9zbGljZS9tZW1jaHIucnOsMRAAIAAAAGgAAAAnAAAAcmFuZ2Ugc3RhcnQgaW5kZXggIG91dCBvZiByYW5nZSBmb3Igc2xpY2Ugb2YgbGVuZ3RoINwxEAASAAAA7jEQACIAAAByYW5nZSBlbmQgaW5kZXggIDIQABAAAADuMRAA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"
}
Parameter Type Description
code_info_response CodeInfoResponse Contract code info
data Byte Array Raw data in base64 encoding

CodeInfoResponse

Parameter Type Description
code_id Int ID of the contract code
creator String Creator address
data_hash String Contract code hash in hexadecimal
instantiate_permission AccessConfig Access configuration

AccessConfig

Parameter Type Description
permission AccessType Permission configuration
addresses String Array

AccessType

ID Acces Type
0 AccessTypeUnspecified
1 AccessTypeNobody
3 AccessTypeEverybody
4 AccessTypeAnyOfAddresses

Codes

Gets the metadata for all stored contract codes

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    limit = 2
    pagination = PaginationOption(limit=limit)
    response = await client.fetch_codes(pagination=pagination)
    print(response)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/cosmos/cosmos-sdk/types/query"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    pagination := query.PageRequest{Limit: 2}
    ctx := context.Background()

    res, err := chainClient.FetchCodes(ctx, &pagination)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
Parameter Type Description Required
pagination Paging Pagination of results No

Response Parameters

Response Example:

{
   "codeInfos":[
      {
         "codeId":"1",
         "creator":"inj180rl9ezc4389t72pc3vvlkxxs5d9jx60w9eeu3",
         "dataHash":"y9Pfljq5aQPc3nx8Apg3IeUw4JZ15GQe6mp577XlaQc=",
         "instantiatePermission":{
            "permission":"ACCESS_TYPE_EVERYBODY",
            "addresses":[

            ]
         }
      },
      {
         "codeId":"2",
         "creator":"inj180rl9ezc4389t72pc3vvlkxxs5d9jx60w9eeu3",
         "dataHash":"rKYFl6749PJgIK4stNXmpWv7UdX+4rcR6UaGK4JUhu8=",
         "instantiatePermission":{
            "permission":"ACCESS_TYPE_EVERYBODY",
            "addresses":[

            ]
         }
      }
   ],
   "pagination":{
      "nextKey":"AAAAAAAAAAM=",
      "total":"0"
   }
}
{
 "code_infos": [
  {
   "id": 1,
   "creator": "inj180rl9ezc4389t72pc3vvlkxxs5d9jx60w9eeu3",
   "data_hash": "CBD3DF963AB96903DCDE7C7C02983721E530E09675E4641EEA6A79EFB5E56907",
   "instantiate_permission": {
    "permission": "Everybody"
   }
  },
  {
   "id": 2,
   "creator": "inj180rl9ezc4389t72pc3vvlkxxs5d9jx60w9eeu3",
   "data_hash": "ACA60597AEF8F4F26020AE2CB4D5E6A56BFB51D5FEE2B711E946862B825486EF",
   "instantiate_permission": {
    "permission": "Everybody"
   }
  }
 ],
 "pagination": {
  "next_key": "AAAAAAAAAAM="
 }
}

Parameter Type Description
code_infos CodeInfoResponse Array Contract code info
pagination PageResponse Pagination of results

CodeInfoResponse

Parameter Type Description
code_id Int ID of the contract code
creator String Creator address
data_hash String Contract code hash in hexadecimal
instantiate_permission AccessConfig Access configuration

AccessConfig

Parameter Type Description
permission AccessType Permission configuration
addresses String Array

AccessType

ID Acces Type
0 AccessTypeUnspecified
1 AccessTypeNobody
3 AccessTypeEverybody
4 AccessTypeAnyOfAddresses

PinnedCodes

Gets the pinned code ids

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    limit = 2
    pagination = PaginationOption(limit=limit)
    response = await client.fetch_pinned_codes(pagination=pagination)
    print(response)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/cosmos/cosmos-sdk/types/query"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    pagination := query.PageRequest{Limit: 2}
    ctx := context.Background()

    res, err := chainClient.FetchPinnedCodes(ctx, &pagination)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
Parameter Type Description Required
pagination Paging Pagination of results No

Response Parameters

Response Example:

{
   "codeIds":[
      "135",
      "136"
   ],
   "pagination":{
      "nextKey":"AAAAAAAAAIk=",
      "total":"0"
   }
}
{
 "code_ids": [
  135,
  136
 ],
 "pagination": {
  "next_key": "AAAAAAAAAIk="
 }
}

Parameter Type Description
code_ids Int Array Array of contract code IDs
pagination PageResponse Pagination of results

ContractsByCreator

Gets the contracts by creator

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio

from pyinjective.async_client import AsyncClient
from pyinjective.client.model.pagination import PaginationOption
from pyinjective.core.network import Network


async def main() -> None:
    # select network: local, testnet, mainnet
    network = Network.testnet()
    client = AsyncClient(network)
    creator = "inj1h3gepa4tszh66ee67he53jzmprsqc2l9npq3ty"
    limit = 2
    pagination = PaginationOption(limit=limit)
    response = await client.fetch_contracts_by_creator(creator_address=creator, pagination=pagination)
    print(response)


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/cosmos/cosmos-sdk/types/query"

    "os"

    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )

    if err != nil {
        panic(err)
    }

    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    creator := "inj1h3gepa4tszh66ee67he53jzmprsqc2l9npq3ty"
    pagination := query.PageRequest{Limit: 2}
    ctx := context.Background()

    res, err := chainClient.FetchContractsByCreator(ctx, creator, &pagination)
    if err != nil {
        fmt.Println(err)
    }

    str, _ := json.MarshalIndent(res, "", " ")
    fmt.Print(string(str))

}
Parameter Type Description Required
creator_address String Address of the contract creator Yes
pagination Paging Pagination of results No

Response Parameters

Response Example:

{
   "contractAddresses":[
      "inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7"
   ],
   "pagination":{
      "nextKey":"",
      "total":"0"
   }
}
{
 "contract_addresses": [
  "inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7"
 ],
 "pagination": {}
}

Parameter Type Description
contract_addresses String Array Array of all the contracts created by the specified creator
pagination PageResponse Pagination of results

MsgExecuteContract

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import os

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    # set custom cookie location (optional) - defaults to current dir
    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    # prepare tx msg
    # NOTE: COIN MUST BE SORTED IN ALPHABETICAL ORDER BY DENOMS
    funds = [
        composer.coin(
            amount=69,
            denom="factory/inj1hdvy6tl89llqy3ze8lv6mz5qh66sx9enn0jxg6/inj12ngevx045zpvacus9s6anr258gkwpmthnz80e9",
        ),
        composer.coin(amount=420, denom="peggy0x44C21afAaF20c270EBbF5914Cfc3b5022173FEB7"),
        composer.coin(amount=1, denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"),
    ]
    msg = composer.MsgExecuteContract(
        sender=address.to_acc_bech32(),
        contract="inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7",
        msg='{"increment":{}}',
        funds=funds,
    )

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
Parameter Type Description Required
sender String The Injective Chain address of the sender Yes
contract String The Injective Chain address of the contract Yes
msg Bytes JSON encoded message to pass to the contract Yes
funds Coin Array List of Coins to be sent to the contract. Note that the coins must be alphabetically sorted by denoms No

Coin

Parameter Type Description
denom String Denom of the Coin
amount String Amount of Coin

Response Example:

txhash: "814807A5C827FC385DF6108E52494E63A2010F36B1D6F36E43B2AEED5D530D60"
raw_log: "[]"

gas wanted: 217930
gas fee: 0.000108965 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

MsgExecuteContract (second example)

This example shows how to interact with a contract to execute the guardian_set_info functionality using the post_message method in the contract. The parameter sent to the post_message function has to be encoded in Base64 format.

Request Parameters

Request Example: ``` python import asyncio import base64 import json import logging

from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction 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 priv_key = PrivateKey.from_hex("5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e") pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32())

contract_message = '{"guardian_set_info":{}}' encoded_message = base64.b64encode(contract_message.encode(encoding="utf-8")).decode()

execute_message_parameter = { "post_message": { "message": encoded_message, "nonce": 1} }

# prepare tx msg msg = composer.MsgExecuteContract( sender=address.to_acc_bech32(), contract="inj14hj2tavq8fpesdwxxcu44rty3hh90vhujaxlnz", msg=json.dumps(execute_message_parameter), )

# build sim tx tx = ( Transaction() .with_messages(msg) .with_sequence(client.get_sequence()) .with_account_num(client.get_number()) .with_chain_id(network.chain_id) ) sim_sign_doc = tx.get_sign_doc(pub_key) sim_sig = priv_key.sign(sim_sign_doc.SerializeToString()) sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

# simulate tx try: sim_res = await client.simulate(sim_tx_raw_bytes) except RpcError as ex: print(ex) return

# build tx gas_price = GAS_PRICE gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = '{:.18f}'.format((gas_price * gas_limit) / pow(10, 18)).rstrip('0') fee = [composer.Coin( amount=gas_price * gas_limit, denom=network.fee_denom, )] tx = tx.with_gas(gas_limit).with_fee(fee).with_memo('').with_timeout_height(client.timeout_height) sign_doc = tx.get_sign_doc(pub_key) sig = priv_key.sign(sign_doc.SerializeToString()) tx_raw_bytes = tx.get_tx_data(sig, pub_key)

# broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode res = await client.broadcast_tx_sync_mode(tx_raw_bytes) print(res) print("gas wanted: {}".format(gas_limit)) print("gas fee: {} INJ".format(gas_fee))

if name == "main": asyncio.get_event_loop().run_until_complete(main())


| Parameter | Type       | Description                                                                                           | Required |
|-----------|------------|-------------------------------------------------------------------------------------------------------|----------|
| sender    | String     | The Injective Chain address of the sender                                                             | Yes      |
| contract  | String     | The Injective Chain address of the contract                                                           | Yes      |
| msg       | Bytes      | JSON encoded message to pass to the contract                                                          | Yes      |

### Response Parameters
> Response Example:

``` python
txhash: "03DDA0A4B49EF093CCC2999435D6D23C71A570B84E588137A0D314F73F5A336B"
raw_log: "[]"

gas wanted: 139666
gas fee: 0.000069833 INJ
ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

- Wasmx

Wasmx smart contract interactions.

MsgExecuteContractCompat

IP rate limit group: chain

Request Parameters

Request Example:

import asyncio
import json
import os

import dotenv
from grpc import RpcError

from pyinjective.async_client import AsyncClient
from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE
from pyinjective.core.network import Network
from pyinjective.transaction import Transaction
from pyinjective.wallet import PrivateKey


async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    client = AsyncClient(network)
    composer = await client.composer()
    await client.sync_timeout_height()

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

    # prepare tx msg
    # NOTE: COIN MUST BE SORTED IN ALPHABETICAL ORDER BY DENOMS
    funds = (
        "69factory/inj1hdvy6tl89llqy3ze8lv6mz5qh66sx9enn0jxg6/inj12ngevx045zpvacus9s6anr258gkwpmthnz80e9,"
        "420peggy0x44C21afAaF20c270EBbF5914Cfc3b5022173FEB7,"
        "1peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"
    )

    msg = composer.msg_execute_contract_compat(
        sender=address.to_acc_bech32(),
        contract="inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7",
        msg=json.dumps({"increment": {}}),
        funds=funds,
    )

    # build sim tx
    tx = (
        Transaction()
        .with_messages(msg)
        .with_sequence(client.get_sequence())
        .with_account_num(client.get_number())
        .with_chain_id(network.chain_id)
    )
    sim_sign_doc = tx.get_sign_doc(pub_key)
    sim_sig = priv_key.sign(sim_sign_doc.SerializeToString())
    sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key)

    # simulate tx
    try:
        sim_res = await client.simulate(sim_tx_raw_bytes)
    except RpcError as ex:
        print(ex)
        return

    # build tx
    gas_price = GAS_PRICE
    gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT  # add buffer for gas fee computation
    gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0")
    fee = [
        composer.coin(
            amount=gas_price * gas_limit,
            denom=network.fee_denom,
        )
    ]
    tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height)
    sign_doc = tx.get_sign_doc(pub_key)
    sig = priv_key.sign(sign_doc.SerializeToString())
    tx_raw_bytes = tx.get_tx_data(sig, pub_key)

    # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode
    res = await client.broadcast_tx_sync_mode(tx_raw_bytes)
    print(res)
    print("gas wanted: {}".format(gas_limit))
    print("gas fee: {} INJ".format(gas_fee))


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "encoding/json"
    "fmt"
    "os"

    wasmxtypes "github.com/InjectiveLabs/sdk-go/chain/wasmx/types"
    "github.com/InjectiveLabs/sdk-go/client"
    chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
    "github.com/InjectiveLabs/sdk-go/client/common"
    rpchttp "github.com/cometbft/cometbft/rpc/client/http"
)

func main() {
    network := common.LoadNetwork("testnet", "lb")
    tmClient, err := rpchttp.New(network.TmEndpoint, "/websocket")
    if err != nil {
        panic(err)
    }

    senderAddress, cosmosKeyring, err := chainclient.InitCosmosKeyring(
        os.Getenv("HOME")+"/.injectived",
        "injectived",
        "file",
        "inj-user",
        "12345678",
        "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3", // keyring will be used if pk not provided
        false,
    )

    if err != nil {
        panic(err)
    }

    clientCtx, err := chainclient.NewClientContext(
        network.ChainId,
        senderAddress.String(),
        cosmosKeyring,
    )
    if err != nil {
        fmt.Println(err)
        return
    }
    clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

    chainClient, err := chainclient.NewChainClient(
        clientCtx,
        network,
        common.OptionGasPrices(client.DefaultGasPriceWithDenom),
    )

    if err != nil {
        panic(err)
    }

    firstAmount := 69
    firstToken := "factory/inj1hdvy6tl89llqy3ze8lv6mz5qh66sx9enn0jxg6/inj12ngevx045zpvacus9s6anr258gkwpmthnz80e9"
    secondAmount := 420
    secondToken := "peggy0x44C21afAaF20c270EBbF5914Cfc3b5022173FEB7"
    thirdAmount := 1
    thirdToken := "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"
    funds := fmt.Sprintf(
        "%v%s,%v%s,%v%s",
        firstAmount,
        firstToken,
        secondAmount,
        secondToken,
        thirdAmount,
        thirdToken,
    )

    message := wasmxtypes.MsgExecuteContractCompat{
        Sender:   senderAddress.String(),
        Contract: "inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7",
        Msg:      "{\"increment\": {}}",
        Funds:    funds,
    }

    // AsyncBroadcastMsg, SyncBroadcastMsg, QueueBroadcastMsg
    response, err := chainClient.AsyncBroadcastMsg(&message)

    if err != nil {
        panic(err)
    }

    str, _ := json.MarshalIndent(response, "", " ")
    fmt.Println(string(str))
}
Parameter Type Description Required
sender String The Injective Chain address of the sender Yes
contract String The Injective Chain address of the contract Yes
msg String JSON encoded message to pass to the contract Yes
funds String String with comma separated list of amounts and token denoms to transfer to the contract. Note that the coins must be alphabetically sorted by denoms No

Response Parameters

Response Example:

ParamterTypeDescription
tx_responseTxResponseTransaction details


TxResponse

ParameterTypeDescription
heightIntegerThe block height
tx_hashStringTransaction hash
codespaceStringNamespace for the code
codeIntegerResponse code (zero for success, non-zero for errors)
dataStringBytes, if any
raw_logStringThe output of the application's logger (raw string)
logsABCIMessageLog ArrayThe output of the application's logger (typed)
infoStringAdditional information
gas_wantedIntegerAmount of gas requested for the transaction
gas_usedIntegerAmount of gas consumed by the transaction
txAnyThe request transaction bytes
timestampStringTime of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time
eventsEvent ArrayEvents defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.


ABCIMessageLog

ParameterTypeDescription
msg_indexIntegerThe message index
logStringThe log message
eventsStringEvent ArrayEvent objects that were emitted during the execution


Event

ParameterTypeDescription
typeStringEvent type
attributesEventAttribute ArrayAll event object details


StringEvent

ParameterTypeDescription
typeStringEvent type
attributesAttribute ArrayEvent data


EventAttribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value
indexBooleanIf attribute is indexed


Attribute

ParameterTypeDescription
keyStringAttribute key
valueStringAttribute value

- Historical Queries

Execute historical chain queries by passing the block height in the headers. Keep in mind that the chain node being used in the query should not be pruned for the height specified.

Publicly maintained nodes are being pruned every 5-10 days.

To find the available chain queries visit Swagger for Mainnet and Testnet.

Request Parameters

Request Example:

import requests
import asyncio
import logging

async def main() -> None:
    block_height = "9858070"
    lcd = "https://testnet.lcd.injective.network/injective/exchange/v1beta1/derivative/orderbook/0x2e94326a421c3f66c15a3b663c7b1ab7fb6a5298b3a57759ecf07f0036793fc9"
    lcd_request = requests.get(lcd, headers={"Content-Type": "application/json", "x-cosmos-block-height": "{}".format(block_height)}).json()
    print(lcd_request)

if __name__ == '__main__':
    logging.basicConfig(level=logging.INFO)
    asyncio.get_event_loop().run_until_complete(main())
package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "time"
)

func queryAtHeight(url, method string, height int64) ([]byte, error) {
    client := &http.Client{
        Timeout: time.Second * 10,
    }

    req, err := http.NewRequest(method, url, nil)
    if err != nil {
        return nil, fmt.Errorf("new request err: %w", err)
    }

    req.Header.Set("x-cosmos-block-height", fmt.Sprintf("%d", height))
    response, err := client.Do(req)
    if err != nil {
        return nil, fmt.Errorf("exec request err: %w", err)
    }
    defer response.Body.Close()

    return ioutil.ReadAll(response.Body)
}

func main() {
    result, err := queryAtHeight("https://testnet.lcd.injective.network/injective/exchange/v1beta1/derivative/orderbook/0x2e94326a421c3f66c15a3b663c7b1ab7fb6a5298b3a57759ecf07f0036793fc9", "GET", 9858070)
    if err != nil {
        panic(err)
    }

    fmt.Println("query result:", string(result))
}
Parameter Type Description Required
block_height String The block height at which we want to execute the query Yes

Response Example:

query result:  {'buys_price_level': [{'p': '30624950000.000000000000000000', 'q': '4.000000000000000000'}, {'p': '29885630000.000000000000000000', 'q': '3.000000000000000000'}, {'p': '29710520000.000000000000000000', 'q': '3.000000000000000000'}, {'p': '29321790000.000000000000000000', 'q': '2.000000000000000000'}, {'p': '28861950000.000000000000000000', 'q': '1.000000000000000000'}, {'p': '28766450000.000000000000000000', 'q': '1.000000000000000000'}, {'p': '28386560000.000000000000000000', 'q': '4.000000000000000000'}, {'p': '28378550000.000000000000000000', 'q': '2.000000000000000000'}, {'p': '27677610000.000000000000000000', 'q': '6.000000000000000000'}, {'p': '26828710000.000000000000000000', 'q': '1.000000000000000000'}, {'p': '26773560000.000000000000000000', 'q': '8.000000000000000000'}, {'p': '26479000000.000000000000000000', 'q': '9.000000000000000000'}, {'p': '26203470000.000000000000000000', 'q': '16.000000000000000000'}, {'p': '26038150000.000000000000000000', 'q': '14.000000000000000000'}], 'sells_price_level': []}
query result: {
  "buys_price_level": [
    {
      "p": "30624950000.000000000000000000",
      "q": "4.000000000000000000"
    },
    {
      "p": "29885630000.000000000000000000",
      "q": "3.000000000000000000"
    },
    {
      "p": "29710520000.000000000000000000",
      "q": "3.000000000000000000"
    },
    {
      "p": "29321790000.000000000000000000",
      "q": "2.000000000000000000"
    },
    {
      "p": "28861950000.000000000000000000",
      "q": "1.000000000000000000"
    },
    {
      "p": "28766450000.000000000000000000",
      "q": "1.000000000000000000"
    },
    {
      "p": "28386560000.000000000000000000",
      "q": "4.000000000000000000"
    },
    {
      "p": "28378550000.000000000000000000",
      "q": "2.000000000000000000"
    },
    {
      "p": "27677610000.000000000000000000",
      "q": "6.000000000000000000"
    },
    {
      "p": "26828710000.000000000000000000",
      "q": "1.000000000000000000"
    },
    {
      "p": "26773560000.000000000000000000",
      "q": "8.000000000000000000"
    },
    {
      "p": "26479000000.000000000000000000",
      "q": "9.000000000000000000"
    },
    {
      "p": "26203470000.000000000000000000",
      "q": "16.000000000000000000"
    },
    {
      "p": "26038150000.000000000000000000",
      "q": "14.000000000000000000"
    }
  ],
  "sells_price_level": [
  ]
}

- HealthAPI

HealthAPI (HTTP) checks if backend data is up-to-date and reliable or not.

GetStatus

IP rate limit group: chain

To check the health of a node, the GetStatus API can be queried to obtain the Indexer height (localHeight) and the network height (horacleHeight). Next, the chain node height can be queried directly from the node (e.g. curl --insecure http://sentry.lcd.injective.network:26657/abci_info | grep last_block_height or in Python (await async_client.get_latest_block()).block.header.height). Comparing last_block_height with horacleHeight gives a sense of the chain node's health, with a threshold of a 20 block difference being a good starting point for detecting unhealthy nodes. localHeight and horacleHeight can also be compared to check Indexer health, though an error should already be returned from the API query if the Indexer is deemed unhealthy (more than 20 block height difference).

If LB/K8S endpoints are being used, there is no need to do these checks, as the cluster has built-in liveliness checks and excludes unhealthy nodes if any are detected.

A recommended health check frequency of once every 20-30 seconds is recommended.

Notes

horacleHeight: the network height of the chain (average returned by multiple nodes in the network)

localHeight: the latest synced block on the indexer

lastBlock: the latest synced block on the chain

Request Example:

import requests

def main() -> None:
    r = requests.get('https://sentry.lcd.injective.network:4444/api/health/v1/status', verify=False)
    print(r.text)

if __name__ == '__main__':
    main()

package main

import (
  "crypto/tls"
  "fmt"
  "io/ioutil"
  "net/http"
  "time"
)

func queryHealthAPI(url, method string) ([]byte, error) {
  tr := &http.Transport{
    TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
  }
  client := &http.Client{
    Transport: tr,
    Timeout:   time.Second * 10,
  }

  req, err := http.NewRequest(method, url, nil)
  if err != nil {
    return nil, fmt.Errorf("new request err: %w", err)
  }

  response, err := client.Do(req)
  if err != nil {
    return nil, fmt.Errorf("exec request err: %w", err)
  }
  defer response.Body.Close()

  return ioutil.ReadAll(response.Body)
}

func main() {
  result, err := queryHealthAPI("https://sentry.lcd.injective.network:4444/api/health/v1/status", "GET")
  if err != nil {
    panic(err)
  }

  fmt.Println("query result:", string(result))
}

Response Parameters

Response Example:

{
  "s": "",
  "data": {
    "localHeight": 26953309,
    "localTimestamp": 1677042872,
    "horacleHeight": 26953309,
    "horacleTimestamp": 1677042872
  }
}
Parameter Type Description
s String Status of the response
errmsg String Error message, if any
data HealthStatus Height and time information for checking health

HealthStatus

Parameter Type Description
localHeight Integer Injective Indexer block height
localTimestamp Integer Timestamp of localHeight
horacleHeight Integer Height of the network according to the Injective height oracle
horacleTimestamp Integer Timestamp of horacleHeight

Glossary

Injective Chain

The Injective Chain refers to the blockchain running the Injective Protocol. It is is the fundamental piece of infrastructure and ultimate source of truth for any trades happening on the network.

Validator / Injective Node

A validator is a node for the Injective Chain. The term node itself refers to a host computer in a network. In the context of blockchains, nodes are the computers participating in producing new blocks and validating new transactions in a peer-to-peer fashion. All on-chain code for Injective is executed on the hardware of every validator, in contrast to a CEX where code is executed on a central server.

On-chain Matching

The matching algorithm is executed as part of validating the chain. It is executed on the hardware of every validator. Therefore it must be deterministic, so every validator comes to the same matching result. For fairness reasons the matching algorithm consists of frequent batch auctions (FBA).

Frequent Batch Auction (FBA)

Frequent Batch Auctions (FBA) are ensuring fair order matching prices by calculating one uniform clearing price over all orders in the same block. Rather than calculating the clearing price for every order, the FBA algorithm calculates the clearing price for a batch of orders. For more details, here.

Relayer

The Injective Chain itself provides no historical data, no detailed statistics and no front-end. This is the role of the relayer. A relayer will index data emitted from the Injective Chain to provide an additional API and front-end.

Mempool

A mempool refers to pending transactions in a blockchain. It is the place where transactions are stored before they are included in a block.

gRPC

gRPC is a high-performance, open-source, general-purpose RPC framework that is used by the Injective Chain. It is used to communicate with the Injective Chain and the relayer.

Mark Price

Mark price refers to the oracle price for the underlying asset in a futures market. It is used to determine when a position is liquidable. Only when the mark price falls below your position's liquidation price, the position can be liquidated. The mark price is further used for market settlements, either in the case of an emergency stop due to the insurance fund draining or in the case of planned settlements for time-expiry future markets.

Perpetual Swap

A perpetual swap is a futures contract without expiry date. Since those contracts never expire with a settlement price, a new mechanism is used to align future contract prices with the mark price: the funding rate.

Funding Rate

In perpetual swaps a funding rate is used to align future contract prices with the mark price. The funding rate is calculated by keeping track of the volume weighted average of the deltas from mark price vs. trade execution price. It is applied to a position proportionally to the position's size.

FAQ

1. What are the trading fees on Injective?

Trading fees differ per market and are defined through governance for both maker and taker orders. The fees can also be reduced based on your tier which is determined based on your staked INJ and 30-day trailing fees.

Note that if you place trades through the API, you will only pay 60% of the trading fees regardless if your order is filled as a maker or taker. In every exchange-related message you can set recipient_fee to your own address in order to collect 40% of the trading fees. On the DEX UI, recipient_fee is set to the relayer's address which acts as a source of revenue but on the API you can set this field to any address of your choosing, including your own.

The DEX UI will also show you the full fees but if you have placed a trade through the API you would have paid only 60% of those fees.

2. What are the gas fees on Injective?

If you place trades through the UI on one of the available relayers you can experience gas-less trading, if you place trades from the API you will pay gas fees in INJ but they will be very low at an average of 0.00005 INJ per message. Note that the INJ to pay for gas must be in the bank balance (wallet) and not the subaccount (trading account).

3. How can I calculate the gas fees in INJ?

The minimum gas price currently accepted by nodes is 160000000. In order to find the exact INJ amount paid you multiply the gas wanted by the minimum gas price and divide by 1e18 (because INJ token has 18 decimals). For instance, if gas wanted is 104519 then you would calculate it as follows:

160000000 * 104519 / 1e18 = 0.00001672304 INJ

4. Which API nodes can I connect to?

The SDKs default to using a load balanced endpoint. It is possible also to run a local node. The guide to set up your own node can be found here.

5. Does Injective have an API support channel?

Yes, you can join the Discord and Telegram API channels to ask any questions you might have or if you need any support.

6. Can I get the order_hash (order_id) right after I send a new order?

Yes, you can actually fetch the order_hash before you even send the transaction through our simulation, you can see the Chain API examples on how to use the simulation.

A better alternative is to set a client order id (cid) to the orders. It is possible to then cancel the orders by cid instead of hash. With this it is no longer necessary to calculate the order hash in advance.

7. Are there limits in the API requests?

All public nodes have limits to the number of request they allow per IP. Please check the rate limits page.

8. What is the normal order latency I can expect?

There's no guarantee on when the chain will process your transaction. It depends on the peer to peer gossip of the network and whether your transaction reaches a given block producer to get included in a block. You can read more details about this here https://docs.tendermint.com/v0.35/assets/img/tm-transaction-flow.258ca020.png as well as the docs here https://docs.tendermint.com/v0.35/introduction/what-is-tendermint.html

We strongly recommend following the guide to setup your own infrastructure which will ultimately reduce latency to a great extent.

Following we include more details regarding transactions latency and blocks production:

- Validators might miss consensus rounds which will delay block production (instead of a 800ms block, we’ll have a 5000ms block). This happens very rarely and it’s due to issues on the validator node (they have a big chain state and they need to download a pruned snapshot, hardware resources etc.). We’re working with all validators to ensure these don’t take place anymore. This was the issue you mentioned last time with block 61885380 above. Additionally, we can decrease the block proposal timeout so we can lower the delayed block from a missed consensus round if this ever takes place again.

- Even though the Tendermint/CometBFT docs don’t make this clear, transactions are only executed in the next block - a concept called deferred/next-block execution. You can find more details/discussion on Github from the core teams: https://github.com/tendermint/tendermint/issues/7898. This means that if you send txs in block N, they are only executed in block N+1.

- There’s a max block gas limit which is currently set to 50M. This prevents spamming/DDoS attacks since if it has very high or even -1, this would allow one to send huge transactions and delay block time by minutes since the node would take a while to process each tx. We’ve observed that we’re currently hitting the block gas limit and we’re going to put up a proposal soon to increase it. This means that even though the validator mempool might have 100 txs, only 40 or 50 will be included (up to 50M gas) so you’re experiencing unnecessary delay. As an example, this tx spent 1M gas: https://explorer.injective.network/transaction/2CC4E5A54D23AF6CC599E7A4328CAE2EFBF6719F40976985E2381A3411B6DD0A/. There are other txs that spend 200K or even 3-5M in gas. Based on some empirical observations, a reasonable gas increase in the block will not cause any performance issues but we’re running more extensive tests and we’ll put up a proposal soon. We’ll be increasing this value progressively as we scale up along with some on-chain improvements.

- As more nodes get online in the network, this will increase the P2P latency. Gossip latency might increase depending on the peers on the node you sent your tx. Consider this scenario:

A. There are 400 nodes online in the network, the node you broadcast to has 40 peers but none of these peers is the validator proposing the next block.

B. Your node will gossip to its 40 peers, then these 40 peers will gossip to the next peers etc.

C. We don’t have metrics as to how long it takes for a tx to be gossiped but there’s some latency involved here since every node will run checkTx/validations before it includes the tx in its mempool.

On the other hand, your node might have direct peering with the block proposer for the upcoming block so you have zero P2P latency.

9. Can I have my own client id to send messages through the API?

No, we don't store private information on the Injective Chain.

10. Would I save gas fees if I batch messages in transactions?

Yes, a transaction includes fields such as messages, fee, signatures, memo and timeout height. When you send a batch of messages in a single transaction, the transaction size is less than the cumulative transaction size of individual transactions which ultimately results in less gas fees.

11. What is the timeout_height?

The timeout_height specifies a height at which your transaction will timeout and eventually prevents it from being committed past a certain height. Essentially, the transaction will be discarded from the mempool (timeout) after the block with number timeout_height has been mined and your sequence number is cleared if a bad transaction with a lower account sequence does not get processed correctly.

12. Do fee discounts apply to all markets?

Discounts apply to all markets apart from markets that have negative maker fees or markets that have been explicitly excluded.

13. What is the block time on the network?

The average block time is 800ms.

14. Does gas fee affect block inclusion and transaction ordering?

Gas fee affects block inclusion but not ordering, currently there's no ordering of transactions other than the order they've arrived (based on the sequence number). For more information refer to the Tendermint docs

15. When may I see account sequence mismatch errors?

On a high-level, when a sentry node receives a transaction it runs a CheckTx to verify the validity of the transaction which includes stateless and stateful checks. One of those checks is to verify that the sender’s sequence number is valid - the sequence number is primarily used for replay protection and it also affects the ordering logic of transactions.

When you broadcast multiple transactions sequentially to the node the sequence is incremented by one for each transaction and your transactions will be included in a block in the order they arrive (based on the sequence). Should the transaction pass all the checks from CheckTx then it is included in the nodes’ mempool (an in-memory pool of transactions unique to each node) which will be gossiped to other peers in the network prior to consensus. When the transaction reaches the proposer validator node then it will be included in a block. Note that in Tendermint BFT (cosmos-sdk consensus algorithm) finality is absolute, meaning that transactions are finalized when they are included in a block.

There are a couple of reasons you might see account sequence mismatch errors:

1) If you run a trading bot and at the same time you try to broadcast a transaction on the DEX you'll end up with a sequence mismatch since the bot will fetch the sequence from the node and the same will happen with the Frontend so you end up broadcasting a transaction with the same sequence number. Similarly, if you run a trading bot with the same private key you'll also see sequence mismatch errors, thus you should use the private key only at one platform at a time.

2) In the examples we're using a function to handle the sequence locally because if you send multiple transactions in a single block the only way to do that is to use local sequence as until the tx is confirmed the peers in the network are not aware that the sequence has been increased. Essentially, we fetch the sequence the first time through the node directly and then handle it locally for consecutive transactions. If you use sync/async and fetch the sequence from the node every time opposed to handling it locally then you'll occasionally end up with a sequence mismatch.

You can refer to these functions below for sdk-python.

https://github.com/InjectiveLabs/sdk-python/blob/master/pyinjective/wallet.py#L269

https://github.com/InjectiveLabs/sdk-python/blob/master/pyinjective/wallet.py#L296

On the other hand, if you use broadcast mode you essentially expect the tx to be included in a block and then you'll get a response back from the sentry - that's not really recommended since it's wasting a lot of resources from the sentry and it's slower on the client-side too but in this case it guarantees that the sequence will always be unique and you can fetch it from the node every time you send a tx.

3) If you broadcasted a transaction with gas fee lower than the minimum threshold on the node then this transaction will remain in the mempool until the node is restarted and the transaction is discarded or until the transaction expires (if you've set a timeout_height before you broadcasted it). If a transaction is stuck in the mempool then you won't be able to broadcast transactions to that node (and potentially to other nodes in the network if it has been gossiped) since the account sequence will be incorrect. To ensure that transactions don't get stuck in the mempool please use the gas fee set in the examples.

16. What are the broadcast modes I can use to send a transaction?

Sync: Wait for the tx to pass/fail CheckTx

Async: Don’t wait for the tx to pass/fail CheckTx; send and return tx immediately

17. When may I see a max subscriptions per client error?

You can open up to 5 chain channels per IP, if you run more than 5 trading bots from the same IP then this error would naturally show up and you should use a different IP. Every trading bot should open one chain channel only, thus if you're seeing this error and don't have 5 distinct trading bots then it indicates an issue in your logic. If you want to broadcast multiple transactions in a single block you can use sync mode and open one channel only. You can refer here for the chain channel initialization in sdk-python.

18. How long does it take until the Exchange API returns my orders/trades after the transaction has been sent?

This depends on a lot of factors such as the P2P network topology and geolocation of the client-server. When you broadcast a transaction, the following cycle takes place:

1) The transaction is gossiped to other peers in the network

2) The transaction eventually reaches the proposer node

3) Validators participating in the consensus round sign the block and it's produced on-chain

4) The block information is gossiped to the read-only peers (sentry nodes)

5) The events emitted by the chain are picked up by the indexer (Exchange API) and included in a MongoDB

6) Exchange API will query MongoDB to fetch you the data

7) Geolocation between client-sentry will determine the latency until the data is served on the client

Error Codes

Error Description
2 Spot market was not found or is no longer active
5 Invalid market ID
6 Subaccount has insufficient deposits
7 Invalid order type, sender or fee_recipient address
8 Position quantity is insufficient for the order (i.e. an RO order cannot be placed if a better order, that would flip the position exists)
9 Invalid order hash
10 Subaccount ID is invalid or does not correspond to the sender's address
16 Invalid price (i.e. the order price is nil, negative or has wrong tick sizes)
17 Invalid quantity (i.e. the order quantity is nil, negative or has wrong tick sizes)
26 Order has insufficient margin (i.e. if the margin is less than the initial margin ratio)
27 Derivative market was not found or is no longer active
28 Position not found (i.e. when placing RO order with no position open)
29 Position direction does not oppose the RO order (i.e. when trying to place a sell RO with a short position)
30 Price surpasses bankruptcy price (i.e. when trying to place an order that would close the position below the bankruptcy price)
32 Invalid trigger price
36 Invalid minimum order margin (margin is not a multiple of the tick size)
37 Exceeds the order side count in derivatives (per market, per subaccount & per side)
39 Cannot place a conditional market order when a conditional market order in the same relative direction already exists
58 Message contains cancel all MarketIDs but no SubaccountID or duplicate values
59 Post-only order exceeds top of book price
60 Limit order cannot be atomic
81 No margin locked in the subaccount (when placing RO conditional order with no position or vanilla order)
95 Insufficient balance
96 Exchange is in post-only mode (the chain has resumed activities after an upgrade and trading has not been enabled yet)
97 Client order ID already exists
98 Client order ID is invalid. Max length is 36 characters