Introduction
Frontrunner is the first zero gas fee, decentralized sports prediction market built on blockchain where you get the best odds with no house edge. Frontrunner is powered by Injective, a blockchain built for Web3 finance applications. This SDK offers a programmatic way to interact with both, powering use cases such as market making.
Please join our Discord Server to ask questions and become a part of our community.
Quickstart
To demonstrate SDK usage, we'll be using it to create a wallet, place a market order, and listing our orders.
Installation
First install the Injective SDK pre-requisites.
pip install frontrunner-sdk
Then install the Frontrunner SDK.
Contact support@getfrontrunner.com for a Frontrunner API Key. Keep this somewhere safe. When launching a Python REPL or running the scripts in this guide, make sure that API Key is set in the environment variable FR_PARTNER_API_TOKEN
.
Creating and Funding a Wallet
from frontrunner_sdk import FrontrunnerSDK
# Create a synchronous Frontrunner SDK
# By default, this will use testnet; no "real" tokens will be involved.
sdk = FrontrunnerSDK()
# Creates a new wallet locally
# Requests funds from an injective faucet
create_wallet = sdk.injective.create_wallet()
# Save your wallet credentials
print(f"""
Put this somewhere safe!
{create_wallet.wallet.mnemonic}
""")
Output
Put this somewhere safe!
bip39 bip39 bip39 bip39 bip39 bip39 bip39 bip39 bip39 bip39 bip39 bip39 bip39 bip39 bip39 bip39 bip39 bip39 bip39 bip39 bip39 bip39 bip39 bip39
In a script or Python REPL, run the following code.
This will create an instance of the SDK which will be used to interact with both Frontrunner and Injective. There are two "versions" of this SDK: synchronous and asynchronous. For this quickstart, we will use the synchronous version.
Then, we'll call create_wallet
to create our wallet and receive an airdrop from Injective's faucet, to allow us to start placing orders right away! Any subsequent calls that require a wallet will use the one we just made.
Getting Frontrunner Markets
find_markets = sdk.frontrunner.find_markets(
sports=["basketball"], # Looking for basketball game markets
event_types=["game"], # Looking for game (instead of future) markets
prop_types=["winner"], # Looking for winner (instead of other) markets
market_statuses=["active"], # Only active markets
)
# Pick a market
market = find_markets.markets[0]
print(f"Market: {market.long_entity_name} [{market.prop_name}] vs {market.short_entity_name}")
Output
Market: New York Knicks [Winner] vs Cleveland Cavaliers
Before we can bet on markets, we'll need to find them. The example here finds all markets where the sport is basketball, the event is a game, and the proposition is for a winner. The response object contains the raw market objects and the market IDs, which will be useful for placing bets.
Then, we'll pick one market to place bets on, and print some info about it.
View an Order Book
# get the order book for this market
response = sdk.injective.get_order_books([market.injective_id])
order_book = response.order_books[market.injective_id]
# Frontrunner testnet markets are in FRCOIN and on Injective, FRCOIN has 6 decimals.
# 1,000,000 from Injective is $1 FRCOIN.
FRCOIN_SCALE_FACTOR = 10 ** 6
# print order book buys
print("buys:")
for buy in order_book.buys:
print(f" {buy.quantity} @ ${int(buy.price) / FRCOIN_SCALE_FACTOR}")
# print order book sells
print("sells:")
for sell in order_book.sells:
print(f" {sell.quantity} @ ${int(sell.price) / FRCOIN_SCALE_FACTOR}")
# find the highest buy and lowest sell
buy_prices = [int(order.price) / FRCOIN_SCALE_FACTOR for order in order_book.buys]
sell_prices = [int(order.price) / FRCOIN_SCALE_FACTOR for order in order_book.sells]
highest_buy, lowest_sell = max(buy_prices), min(sell_prices)
print(f"bid-ask spread: [${highest_buy}, ${lowest_sell}]")
Output
buys:
5882 @ $0.34
9091 @ $0.33
15625 @ $0.32
5000 @ $0.1
sells:
4364 @ $0.36
8108 @ $0.37
13158 @ $0.38
bid-ask spread: [$0.34, $0.36]
Without knowing much else about the market besides its ID, it's hard to price bets and make orders. Here, we'll place multiple buy orders above the highest buy price.
We'll call get_order_books
, passing in the Injective market id, to get the current order book. This order book contains both the buys and sells. Using the buys, we can find the highest buy price.
Placing buy orders
from frontrunner_sdk.models import Order
highest_buy = 0.01
injective_id = "0xd03091c74e4e76878c2afbeb470b1c825677014afdaa3d315fa534884d2d90e1"
create_orders = sdk.injective.create_orders([
Order.buy_long(injective_id, 10, highest_buy + 0.01),
Order.buy_long(injective_id, 5, highest_buy + 0.02),
])
print(f"""
Transaction: {create_orders.transaction}
You can view your transaction at:
https://testnet.explorer.injective.network/transaction/{create_orders.transaction}
""")
Output
Transaction: 917F980F001120A05642F225E9197CCDF1BB5677A6381F81D2CC95410466008C
You can view your transaction at:
https://testnet.explorer.injective.network/transaction/917F980F001120A05642F225E9197CCDF1BB5677A6381F81D2CC95410466008C
To place the orders, we'll call create_orders
. We'll place...
- An order for 10 shares at $0.01 above the highest buy price
- An order for 5 shares at $0.02 above the highest buy price
Note that we use a hard-coded market ID here that points to a testnet USDT market that can be traded in with Injective Faucet funds.
Contact support@getfrontrunner.com to request testnet FRCOIN to trade in real Frontrunner markets.
Retrieving Your Orders
get_orders = sdk.injective.get_orders(mine=True, execution_types=["limit"])
print("orders:")
for order_history in get_orders.orders:
print(f" {order_history.order_type} {order_history.order.order_hash}: {order_history.order.quantity} @ ${int(order_history.order.price) / FRCOIN_SCALE_FACTOR}")
Output
orders:
OrderType.BUY_LONG 0x642c138d85a8224093665d1c8bd4fc31e2307fcee62157c7175e5865ea850247: 5 @ $0.03
OrderType.BUY_LONG 0xd82ced802fdf5ce55a1b37238d83ece7677e4aeb0d576ebb76d041a590ecff16: 10 @ $0.02
Concepts
Order Types
Participants in Frontrunner markets submit buy
(a.k.a. bid) and sell
(a.k.a. ask)
orders of two different types:
long
: in favor of thelong_entity
outcomeshort
: in favor of theshort_entity
if present. If noshort_entity
is present (i.e. in non-binary markets), this outcome is simply the inverse or "not" of thelong_entity
. See the Non-Binary Markets section below for additional context.
Market Types
Binary markets
In Frontrunner's binary markets, both the long
and the short
side represent distinct entities. All game
markets that cannot end in a draw
are binary markets because there are only two possible standard outcomes.
For example, the game
winner
market Miami Heat @ Orlando Magic
is a binary market where the Heat are
the long_entity
and the Magic are the short_entity
.
For binary markets, long positions resolve at $1 (and short positions at $0) if the
outcome represented by the long_entity
occurs; short positions resolve at $1 (and long positions at $0)
if the outcome represented by the short_entity
occurs.
Non-Binary Markets
Non-binary markets are represented by a group of binary markets that do not have short_entity
specified. When there is no short_entity
, taking a short
position is simply betting against the
long
outcome. All game
markets that can end in a draw (besides NFL) and futures markets are non-binary markets.
For example, the game
winner
market Arsenal FC v Chelsea FC
is a non-binary market
represented by 3 distinct Frontrunner markets:
Arsenal FC
:long
in this market resolves at $1 if Arsenal wins and $0 if they lose or draw.short
in this market resolves at $1 if Arsenal loses or draws.short
can be thought of as "Not Arsenal"Chelsea FC
:long
in this market resolves at $1 if Chelsea wins and $0 if they lose or draw.short
in this market resolves at $1 if Chelsea loses or draws.short
can be thought of as "Not Chelsea"Draw
:long
in this market resolves at $1 if the game ends in a draw.short
in this market resolves at $1 if the game does not end in a draw.short
can be thought of as "Not Draw"
Futures markets may exist for season winners like the NFL Championship, Premier League Season, and NBA Finals. For futures markets, one market exists for each entity with sufficient chances of winning (at the discretion of Frontrunner).
Home and Away
Frontrunner defines the long
entity as the first entity in the matchup description.
This definition changes depending on the sport - the different options are listed below.
League | Sport Event Name | Long Entity | Short Entity |
---|---|---|---|
EPL | Home v Away | n/a* | n/a |
Formula 1 | n/a** | n/a* | n/a |
MLB | Away @ Home | Away | Home |
NBA | Away @ Home | Away | Home |
NFL | Away @ Home | Away | Home |
*The home/away designation does correlate directly to long/short entities for non-binary markets like EPL markets (as well as futures) due to their structure. However, the home team can still be detected based on the Sport Event Name. See the Non-Binary Markets section above for additional context.
**Formula 1 information from Frontrunner does not include information about player/team nationalities.
Configuring
SDK Parameters
There are a few ways to configure values for the SDK. In order of precedence, they are as follows:
- Direct named environment variables
- Presets via environment variables
- Default values
Wallet
This specifies which wallet the SDK will use for mutating the blockchain and querying the blockchain for "my" data. These variables are checked in order.
Environment Variables
FR_WALLET_MNEMONIC
FR_WALLET_PRIVATE_KEY_HEX
Default
None
Frontrunner Base API URL
This is the base URL for Frontrunner-specific operations such as finding markets.
Environment Variables
FR_PARTNER_API_BASE_URL
Default
https://partner-api-testnet.getfrontrunner.com/api/v1
Frontrunner API Token
To interact with the Frontrunner APIs, you will need a token to authenticate. Requests without authentication will fail.
Environment Variable
FR_PARTNER_API_TOKEN
Default
None
Injective Network
The "network" is which blockchain network to use. Valid values are...
testnet
mainnet
For testing with "play" money and developing code, use testnet
. For production and "real" money, use mainnet
.
The chain ID must match with the Injective network you are using.
Network | Chain ID |
---|---|
testnet | injective-888 |
mainnet | injective-1 |
Environment Variable
FR_INJECTIVE_NETWORK
FR_INJECTIVE_CHAIN_ID
Default
Network is testnet
, and Chain ID is injective-888
.
Injective Endpoints
Injective is built on the Cosmos network. Cosmos defines a set of well known endpoint types that are supported for interacting with the blockchain. You can learn more about them here: Cosmos Good-To-Know Dev Terms.
In Cosmos, we have the following endpoints:
- Exchange
- Explorer
- Light Client Daemon (LCD)
- Remote Procedure Call (RPC)
- Google RPC (gRPC)
Normally, these come in sets, and are not interchangeable between sets.
Environment Variables
FR_INJECTIVE_EXCHANGE_AUTHORITY
FR_INJECTIVE_EXPLORER_AUTHORITY
FR_INJECTIVE_LCD_BASE_URL
FR_INJECTIVE_RPC_BASE_URL
FR_INJECTIVE_GRPC_AUTHORITY
Defaults
Frontrunner does not run the Injective Explorer, so Explorer Authority defaults are always Injective's.
Testnet
Endpoint Type | Default Value |
---|---|
Exchange Authority | injective-node-testnet.grpc-exchange.getfrontrunner.com:443 |
Explorer Authority | k8s.testnet.explorer.grpc.injective.network:443 |
LCD Base URL | https://injective-node-testnet.lcd.getfrontrunner.com |
RPC Base URL | wss://injective-node-testnet.tm.getfrontrunner.com/websocket |
gRPC Authority | injective-node-testnet.grpc.getfrontrunner.com:443 |
Mainnet
Endpoint Type | Default Value |
---|---|
Exchange Authority | k8s.global.mainnet.exchange.grpc.injective.network:443 |
Explorer Authority | k8s.global.mainnet.explorer.grpc.injective.network:443 |
LCD Base URL | https://k8s.global.mainnet.lcd.injective.network:443 |
RPC Base URL | wss://k8s.global.mainnet.tm.injective.network:443/websocket |
gRPC Authority | k8s.global.mainnet.chain.grpc.injective.network:443 |
Presets
The preset endpoint groups for Injective are taken from Injective's
Network
class here.
Injective Testnet K8s
When the environment variable FR_PRESET_NODES
is set to injective-k8s
and the SDK is configured for testnet
,
Injective's Kubernetes-based endpoints on the testnet network (Network.testnet()
) will be used instead of the defaults above.
Injective Mainnet Global
When the environment variable FR_PRESET_NODES
is set to injective-global
and the SDK is configured for mainnet
,
Injective's global, load-balanced endpoints on the mainnet network (Network.mainnet("lb")
) will be used.
Injective Mainnet Sentry
When the environment variable FR_PRESET_NODES
is set to injective-sentry
and the SDK is configured for mainnet
,
one of Injective's standalone sentry nodes on the mainnet network (Network.mainnet("sentry0")
) will be used.
SSL
The environment variable FR_INJECTIVE_INSECURE
controls whether or not an insecure/plaintext connection is made to Injective endpoints.
Preset node groups have this set correctly by default (see below).
Set this environment variable to "true"
or "false"
as needed.
Preset | Insecure? |
---|---|
Frontrunner Testnet | False |
Frontrunner Mainnet | False |
Injective Testnet K8s | False |
Injective Mainnet Global | False |
Injective Mainnet Sentry | True |
FR_PRESET_NODES unset |
False |
Injective Faucet
A faucet is a site that dispenses free tokens to a wallet. Faucets are used to acquire tokens without involving "real" money or mining them yourself.
This faucet is only relevant for testnet
- there is no faucet on mainnet.
Environment Variable
FR_INJECTIVE_FAUCET_BASE_URL
Default
https://knroo5qf2e.execute-api.us-east-2.amazonaws.com/default/TestnetFaucetAPI
Configuring Logging
All actions within the SDK are logged via Python's logging
module. The logging
module is hierarchical, so you can selectively turn off sections of a module by name.
import logging
# Set logging for frontrunner-sdk to INFO and above
logging.getLogger("frontrunner_sdk").setLevel(logging.INFO)
# Only log critical errors from config and clients
logging.getLogger("frontrunner_sdk.clients").setLevel(logging.CRITICAL)
logging.getLogger("frontrunner_sdk.config").setLevel(logging.CRITICAL)
The default logging level is the same as logging
's defaults.
For more information on configuring Python's logging, see the Python Logging Cookbook.
Technical Conventions
Sync and Async SDKs
This SDK is designed with async/concurrent programming in mind. However, it can be difficult to use in regular scripts because the way async
code needs to be written requires an all-or-nothing approach. To cater to non-async code, we provide a version of the SDK that can be used without async
.
from frontrunner_sdk import FrontrunnerSDKAsync
sdk = FrontrunnerSDKAsync()
To create an async
version of the SDK, use FrontrunnerSDKAsync
.
from frontrunner_sdk import FrontrunnerSDK
sdk = FrontrunnerSDK()
To create a non-async
version of the SDK, use FrontrunnerSDK
.
Response Objects
SDK return values are always wrapped in a response object. The response object contains the desired values eg. orders, positions, portfolio info. This is to mitigate the effects of SDK changes for developers.
sdk = FrontrunnerSDK()
# SDK return values are always response objects
response = sdk.injective.some_list_operation()
# Desired values will be Within the response object
desired_value = response.desired_value
maybe_other_value = response.maybe_other_value
API Namespaces
Within the SDK, we split the operations into the following namespaces:
- Frontrunner
- Injective
This split exists so that the origin of the call data is transparent. For example, if you only wish to interact with Frontrunner services, only use the calls available in the frontrunner
namespace in the SDK.
To view the Frontrunner REST API Swagger docs, load openapi/frontrunner-api/openapi.json
into https://editor.swagger.io.
To view the Injective API docs, see https://api.injective.exchange/#introduction.
Exceptions
In general, this SDK wraps downstream exceptions in our own exception classes. Also, each exception class has a specific meaning.
Class | Meaning |
---|---|
FrontrunnerException |
Root exception for anything raised by this SDK |
FrontrunnerUserException |
User is at fault |
FrontrunnerExternalException |
User is not at fault |
FrontrunnerConfigurationException |
User did not configure or misconfigured a value required by the SDK |
FrontrunnerArgumentException |
User provided an invalid value to an operation |
FrontrunnerInjectiveException |
User provided an invalid value to an Injective API |
FrontrunnerUnserviceableException |
Service is not usable eg. responds with 5xx status code |
Logging
All actions within the SDK are logged via Python's logging
module. Each log level has a specific meaning.
CRITICAL
logs indicate that the SDK cannot function. Examples include unreachable endpoints, inoperable endpoints, incorrect credentials, and system errors. Typically, these are logged alongside a raised FrontrunnerExternalException
.
ERROR
logs are generated alongisde every raised exception ie. logger.exception(...)
.
WARNING
logs indicate a given operation, parameter, or configuration is deprecated, and should not be used. The warning will include an alternative to use.
INFO
logs are generated after every completed SDK operation. These logs serve as an audit trail of what happened in the SDK.
DEBUG
logs are generated around (before + after) every external API call, before calling an external process, and after configuration is read. With debug logs, there should be enough detail to recreate the sequence of events that lead to a specific failure at the SDK level.
Gas and Fees
Gas represents the computational effor required to execute an operation. The fee is how much INJ
to pay to execute a transaction. Insufficient gas will result in a failed transaction, and consumed gas.
The fee amount is fee = gas * gas price
where gas price
is an arbitrary constant.
To learn more, see Gas and Fees from the Injective and Cosmos documentation.
Gas Estimation
Injective docs suggest using simulation to estimate the amount of gas required to execute a specific transaction. However, simulation is slow (around 2 seconds). For HFT use cases, this SDK uses a precomputed lookup table to estimate the required gas. Because of the way the underlying Cosmos SDK works, gas is strongly tied to the size of the message and is also time-independent. That property allows us to roughly estimate the amount of gas to send based on the type of message and number of orders it contains.
To ensure there is enough gas, and to account for errors in estimation, a flat gas "buffer" amount is also added.
For HFT and API trading notes, see this Injective note.
Subaccount Management
Definition
Subaccounts enable traders to execute transactions through multiple accounts under the same wallet. Each subaccount has independent balances, margin and positions and can trade independently. so they can be used to isolate positions or margin or to run multiple strategies independently. All orders in Injective markets are from a subaccount (often the default subaccount).
Subaccounts are 0-indexed, and the default subaccount, subaccount 0, has a special
property: trading from the default subaccount draws funds from the main bank balance.
Detailed information about this feature can be found here.
The main bank balance is associated with the Injective address (e.g. inj14w0zfp47jqpgjst87vxg5ydgvtevfdm38338xp
).
Subaccount balances are associated with each subaccount (e.g. 0xb4efdbe3240d3d2a1bc6be8a1f717944e734a0dd000000000000000000000000
).
Properties
- Each subaccount can have a maximum of 20 open orders per market
- A single subaccount cannot create orders for both the
long
andshort
sides in a binary options market
Transferring Funds
These are the operations involved in transferring funds between accounts or subaccounts:
Operation | Usage | Notes |
---|---|---|
fund_external_subaccount |
Send funds to a subaccount that is NOT owned by the SDK wallet. | Cannot fund subaccount 0. |
fund_external_wallet |
Send funds to a another Injective wallet. | This sends from the configured SDK wallet's main bank balance to the external wallet's main bank balance |
fund_subaccount |
Send funds from the main bank balance to a subaccount that IS owned by the SDK wallet. Or send funds between subaccounts that ARE BOTH owned by the SDK wallet. | Cannot fund subaccount 0. Funding from source subaccount 0 sends from the main bank balance. |
withdraw_from_subaccount |
Withdraw funds from a subaccount that IS owned by the SDK wallet to the main bank balance. | Cannot withdraw from subaccount 0. |
Where operations involve subaccounts owned by the SDK wallet, either a Subaccount
object or an integer index
can be provided for convenience.
A Subaccount
object can be created in a few different ways:
from frontrunner_sdk.models import Subaccount, Wallet
wallet = Wallet._new()
Subaccount.from_subaccount_id("0xb4efdbe3240d3d2a1bc6be8a1f717944e734a0dd000000000000000000000001")
wallet.subaccount(1)
Subaccount.from_injective_address_and_index("inj1knhahceyp57j5x7xh69p7utegnnnfgxavmahjr", 1)
Subaccount.from_ethereum_address_and_index("0xb4efdbe3240d3d2a1bc6be8a1f717944e734a0dd", 1)
Sample Code: Market Making
A simple setup to create liquidity on both sides of a Frontrunner market involves using two non-default
subaccounts, where one subaccount creates long
orders and another creates short
orders.
For example, this is how two subaccounts could be funded with testnet tokens and then used to submit orders on both sides:
import time
from typing import List
from frontrunner_sdk import FrontrunnerSDKAsync
from frontrunner_sdk.models import Order, OrderType
FRCOIN_SCALE_FACTOR = 10 ** 6
async def _print_orderbook(sdk: FrontrunnerSDKAsync, injective_market_id: str):
response = await sdk.injective.get_order_books([injective_market_id])
order_book = response.order_books[injective_market_id]
print("buys:")
for buy in order_book.buys:
print(f" {buy.quantity} @ ${int(buy.price) / FRCOIN_SCALE_FACTOR}")
print("sells:")
for sell in order_book.sells:
print(f" {sell.quantity} @ ${int(sell.price) / FRCOIN_SCALE_FACTOR}")
buy_prices = [int(order.price) / FRCOIN_SCALE_FACTOR for order in order_book.buys]
sell_prices = [int(order.price) / FRCOIN_SCALE_FACTOR for order in order_book.sells]
highest_buy, lowest_sell = max(buy_prices) if buy_prices else 0, min(sell_prices) if sell_prices else 0
print(f"bid-ask spread: [${highest_buy}, ${lowest_sell}]")
async def _print_orders(sdk: FrontrunnerSDKAsync, injective_market_id: str, subaccount_indexes: List[int]):
for subaccount_index in subaccount_indexes:
get_orders = await sdk.injective.get_orders(mine=True, market_ids=[injective_market_id], subaccount_index=subaccount_index)
print(f"orders for index {subaccount_index}:")
for order_history in get_orders.orders:
print(f"{order_history.order_type} {order_history.order.state} : filled {order_history.order.filled_quantity} / {order_history.order.quantity} @ ${int(float(order_history.order.price)) / FRCOIN_SCALE_FACTOR}")
def calculate_price(probability: float, price_margin: float, order_type: OrderType):
if order_type == OrderType.BUY_LONG:
return round(max(0.01, min(0.99, probability - price_margin)), 2)
else:
return round(min(0.99, max(0.01, probability + price_margin)), 2)
def generate_histogram_orders(injective_market_id: str, total_value_coefficients: List[float], order_type: OrderType, price: float, price_step: float, total_value: float, subaccount_index: int):
orders = []
for coeff in total_value_coefficients:
if price < 0.01 or price > 0.99:
break
coeff_total_value = total_value * coeff # total amount we want to spend on shares at this price
num_shares = coeff_total_value / price # num_shares * price = total_value spent
if order_type == OrderType.BUY_LONG:
orders.append(Order.buy_long(injective_market_id, int(round(num_shares, 0)), round(price, 2), subaccount_index=subaccount_index))
elif order_type == OrderType.BUY_SHORT:
orders.append(Order.buy_short(injective_market_id, int(round(num_shares, 0)), round(price, 2), subaccount_index=subaccount_index))
price += price_step
return orders
async def main():
total_value_coefficients = [0.2, 0.3, 0.5] # the distribution of funds for each price step; sum should always equal 1
assert(int(sum(total_value_coefficients)) == 1)
sdk = FrontrunnerSDKAsync()
print(f"Running with wallet {(await sdk.wallet()).injective_address}")
injective_market_id = "REPLACE_ME"
wallet = await sdk.wallet()
long_subaccount_index = 1
short_subaccount_index = 2
long_subaccount = wallet.subaccount_address(long_subaccount_index)
short_subaccount = wallet.subaccount_address(short_subaccount_index)
print(f"Running with wallet {wallet.injective_address}. {long_subaccount=}, {short_subaccount=}")
response = await sdk.injective.fund_subaccount(1000, "FRCOIN", destination_subaccount_index=long_subaccount_index)
print(f"View deposit transaction to long side subaccount: https://testnet.explorer.injective.network/transaction/{response.transaction}")
response = await sdk.injective.fund_subaccount(1000, "FRCOIN", destination_subaccount_index=short_subaccount_index)
print(f"View deposit transaction to short side subaccount: https://testnet.explorer.injective.network/transaction/{response.transaction}")
probability = 0.68
desired_total_liquidity = 100
spread_per_side = 0.01
long_base_price = calculate_price(probability, spread_per_side, OrderType.BUY_LONG)
short_base_price = calculate_price(probability, spread_per_side, OrderType.BUY_SHORT)
# Note this includes validation of the probability to prevent submitting orders at invalid prices.
# Instead, this case could be detected and a smaller histogram created.
buy_long_orders = generate_histogram_orders(injective_market_id, total_value_coefficients, OrderType.BUY_LONG, long_base_price, -1 * spread_per_side, desired_total_liquidity / 2, long_subaccount_index) if probability >= 0.02 else []
buy_short_orders = generate_histogram_orders(injective_market_id, total_value_coefficients, OrderType.BUY_SHORT, short_base_price, spread_per_side, desired_total_liquidity / 2, short_subaccount_index) if probability <= 0.98 else []
orders = buy_long_orders + buy_short_orders
print(orders)
response = await sdk.injective.create_orders(orders)
print(f"View create orders transaction: https://testnet.explorer.injective.network/transaction/{response.transaction}")
time.sleep(5) # ensure new state is reflected
await _print_orderbook(sdk, injective_market_id)
await _print_orders(sdk, injective_market_id, list(range(3)))
Operations
Frontrunner: Find Markets
Enhanced search of Frontrunner markets.
Parameters
# Find Frontrunner markets where...
response = sdk.frontrunner.find_markets(
# ...the winner
prop_type=["winner"],
# ...of a basketball
sports=["basketball"],
# ...game
event_types=["game"],
# ...is the Los Angeles Lakers (LAL)
sport_entity_abbreviations=["LAL"],
)
# Find Frontrunner markets where...
response = sdk.frontrunner.find_markets(
# ...formula one
sports=["formula1"],
# ...team Williams or Alfa Romeo
sport_entity_names=["Williams", "Alfa Romeo"],
# ...is not for a 'winner' type prop
prop_types=["other"],
)
# Get all active Frontrunner markets
response = sdk.frontrunner.find_markets()
Name | Type | Req? | Description |
---|---|---|---|
sports |
[str] |
◯ | Only include the given sports |
league_names |
[str] |
◯ | Only include the given league names |
event_types |
[str] |
◯ | Only include the given event types; must be in [game, future] |
sport_entity_names |
[str] |
◯ | Only include the given entity names (eg. Atlanta Hawks) |
sport_entity_abbreviations |
[str] |
◯ | Only include the given entity abbreviations (eg. ATL) |
prop_types |
[str] |
◯ | Only include the given prop types; must be in [winner, other] |
market_statuses |
[str] |
◯ | Only include the given market statuses; must be in [active, closed] |
Response
for market in response.markets:
print(f"Market: {market.address} [{market.long_entity_name} / {market.short_entity_name}]")
Name | Type | Description |
---|---|---|
market_ids |
[str] |
Related market IDs, from sport entities, props, and market_statuses constraints |
markets |
[Market] |
Related market objects |
Frontrunner: Get Leagues
Get Frontrunner leagues.
Parameters
# Get all Frontrunner leagues
response = sdk.frontrunner.get_leagues()
Name | Type | Req? | Description |
---|---|---|---|
id |
str |
◯ | Only include the specific league |
sport |
str |
◯ | Only include the leagues for the given sport |
Response
print(f"Leagues: {response.leagues}")
Name | Type | Description |
---|---|---|
leagues |
[League] |
Related league objects |
Frontrunner: Get Markets
Get Frontrunner markets.
Parameters
from frontrunner_sdk.openapi.frontrunner_api import MarketStatus
# Get all active NFL markets
league_id = "c6c521c4-88d0-463d-aa2a-fe3765ec872a"
response = sdk.frontrunner.get_markets(
league_id=league_id,
status=MarketStatus.ACTIVE,
)
# Get all active Frontrunner markets
response = sdk.frontrunner.get_markets()
Name | Type | Req? | Description |
---|---|---|---|
id |
str |
◯ | Only include the specific market |
injective_id |
str |
◯ | Only include the market corresponding to the given Injective market |
prop_id |
str |
◯ | Only include markets for the given prop |
event_id |
str |
◯ | Only include markets for the given event |
league_id |
str |
◯ | Only include markets for the given league |
status |
str |
◯ | Only include the given market status; must be one of [active, closed] |
Response
for market in response.markets:
print(f"Market: {market.address} [{market.long_entity_name} / {market.short_entity_name}]")
Name | Type | Description |
---|---|---|
markets |
[Market] |
Related market objects |
Frontrunner: Get Props
Get Frontrunner props.
Parameters
# Get all NFL props
league_id = "c6c521c4-88d0-463d-aa2a-fe3765ec872a"
response = sdk.frontrunner.get_props(
league_id=league_id,
)
# Get all Frontrunner props
response = sdk.frontrunner.get_props()
Name | Type | Req? | Description |
---|---|---|---|
id |
str |
◯ | Only include the specific prop |
league_id |
str |
◯ | Only include the props for the given league |
Response
print(f"Props: {response.props}")
Name | Type | Description |
---|---|---|
props |
[Prop] |
Related prop objects |
Frontrunner: Get Sport Entities
Get Frontrunner sport entities (i.e. teams, players, etc.)
Parameters
# Get all NFL sport entities
league_id = "c6c521c4-88d0-463d-aa2a-fe3765ec872a"
response = sdk.frontrunner.get_sport_entities(
league_id=league_id,
)
# Get all Frontrunner sport entities
response = sdk.frontrunner.get_sport_entities()
Name | Type | Req? | Description |
---|---|---|---|
id |
str |
◯ | Only include the specific sport entity |
league_id |
str |
◯ | Only include the sport entities for the given league |
sport |
str |
◯ | Only include the sport entities for the given sport |
Response
print(f"Sport Entities: {response.sport_entities}")
Name | Type | Description |
---|---|---|
sport_entities |
[SportEntity] |
Related sport entity objects |
Frontrunner: Get Sport Events
Get Frontrunner sport events
Parameters
# Get all NFL sport events
league_id = "c6c521c4-88d0-463d-aa2a-fe3765ec872a"
response = sdk.frontrunner.get_sport_events(
league_id=league_id,
)
# Get all Frontrunner sport events
response = sdk.frontrunner.get_sport_events()
Name | Type | Req? | Description |
---|---|---|---|
id |
str |
◯ | Only include the specific sport event |
league_id |
str |
◯ | Only include the sport events for the given league |
sport |
str |
◯ | Only include the sport events for the given sport |
starts_since |
datetime |
◯ | Only include the sport events starting after the given datetime |
Response
print(f"Sport Events: {response.sport_events}")
Name | Type | Description |
---|---|---|
sport_events |
[SportEvent] |
Related sport event objects |
Frontrunner: Get Sports
Get supported sports on Frontrunner
Parameters
# Get all Frontrunner sports
response = sdk.frontrunner.get_sports()
No parameters. Note that this is convenience operation that collects all sports from get_leagues
.
Response
print(f"Sports: {response.sports}")
Name | Type | Description |
---|---|---|
sports |
[str] |
All sport names |
Injective: Cancel All Orders
Cancel all your open orders.
Parameters
# Cancel all your orders
response = sdk.injective.cancel_all_orders()
Name | Type | Req? | Description |
---|---|---|---|
subaccount_index |
int |
◯ 0 |
Index of the subaccount to cancel orders for |
Response
print("transaction:", response.transaction)
print("orders:")
for order in response.orders:
print(f"\tmarket: {order.market_id[:12]}... price: {order.price} quantity: {order.quantity}")
Name | Type | Description |
---|---|---|
orders |
Iterable[DerivativeLimitOrder] |
Cancelled orders |
transaction |
Optional[str] |
Transaction ID of the order cancellation |
Injective: Cancel Orders
Cancels specific orders.
Parameters
# Cancel a single specific order
response = sdk.injective.cancel_orders([
CancelOrder(
market_id="0x141e3c92ed55107067ceb60ee412b86256cedef67b1227d6367b4cdf30c55a74",
order_hash="znihpTtkWn/9Npy1Zzku+GNxXfyLE/k05U1KXRUTO1E=",
),
])
Name | Type | Req? | Description |
---|---|---|---|
orders |
[CancelOrder] |
✓ | List of order cancellation specs |
orders[].market_id |
str |
✓ | Market ID of order to cancel |
orders[].order_hash |
str |
✓ | Order hash of order to cancel |
orders[].subaccount_index |
int |
◯ 0 |
Index of the subaccount to cancel the order for |
Response
print("transaction:", response.transaction)
Name | Type | Description |
---|---|---|
transaction |
str |
Transaction ID of the order cancellation |
Injective: Create Orders
Create orders. Order has a market, price, and quantity.
For finding markets, see find_markets
.
Parameters
some_market = "0x141e3c92ed55107067ceb60ee412b86256cedef67b1227d6367b4cdf30c55a74"
other_market = "0x9181874b70fefe3e126b6472c6de647b4dbfa59025ad5dc61be6559532d19e15"
# Create orders
# Note that this specific set of orders (both long and short buys) can't all be executed together due to subaccount
# mechanics (see Subaccount Management for more details) and because sells only work with an existing position.
# This list of orders is just to demonstrate all types.
response = sdk.injective.create_orders([
Order.buy_long(some_market, 120, 0.70),
Order.sell_long(some_market, 100, 0.75),
Order.buy_short(other_market, 30, 0.90),
Order.sell_short(other_market, 25, 0.95),
])
Name | Type | Req? | Description |
---|---|---|---|
orders |
[Order] |
✓ | Orders to place; must have at least 1 order |
orders[].market_id |
str |
✓ | Market of the order |
orders[].quantity |
int |
✓ | How many orders to place |
orders[].price |
float |
✓ | At what price to place the order; must be 0 < price < 1 |
orders[].subaccount_index |
int |
◯ 0 |
Index of the subaccount to create the order from |
orders[].is_post_only |
bool |
◯ False |
If True, this is a post-only order that will only succeed if it enters the orderbook unmatched |
Response
print("transaction:", response.transaction)
for order in response.orders:
print(
"order:",
order.market_id,
"for", order.quantity, "@" order.price,
"in subaccount", order.subaccount_index,
"with hash", order.hash,
)
Name | Type | Description |
---|---|---|
transaction |
str |
Transaction ID of the order creation |
orders |
List[Order] |
Orders from input, but with hash defined |
Failure Detection
Even though a transaction may succeed, the orders within it may individually fail for a number of reasons. Order failure detection is not handled internally within this SDK. However, there is a way to detect failures.
This operation returns your orders augmented with an order hash field, which can be used to cross-reference order failures when retrieving the transaction.
from itertools import chain
create_orders = sdk.injective.create_orders([
Order.buy_long(some_market, 120, 0.70),
Order.sell_short(other_market, 25, 0.95),
])
# store order hashes
order_hashes = { order.hash: order for order in create_orders.orders }
get_transaction = sdk.injective.get_transaction(create_orders.transaction)
# find order failures and causes
order_failures = dict(chain.from_iterable(
zip(order_failure.hashes, order_failure.flags)
for order_failure
in get_transaction.order_failures
))
# get (order, flag) correlated by hash
correlated_failed_orders = [
(order_hashes[order_hash], flag)
for order_hash, flag
in order_failures.items()
if order_hash in order_hashes
]
for order, flag in correlated_failed_orders:
print("failed order:", order.market_id, order.quantity, "@", order.price, "flag =", flag)
Injective: Create Wallet
Creates a new wallet with a small aidrop of INJ and USDT from Injective's faucet.
Parameters
response = sdk.injective.create_wallet()
Name | Type | Req? | Description |
---|---|---|---|
fund_and_initialize |
bool |
◯ True |
If true, fund the wallet from the testnet faucet and initialize (only functions on testnet ) |
Response
print("wallet eth address:", response.wallet.ethereum_address)
print("wallet inj address:", response.wallet.injective_address)
print("wallet mnenomic (keep this safe):")
print("\n\t", response.wallet.mnemonic)
print("wallet private key (keep this safe):")
print("\n\t", response.wallet.private_key.to_hex())
Name | Type | Description |
---|---|---|
wallet |
Wallet |
The created wallet |
Injective: Fund External Subaccount
Send funds to a subaccount that is NOT owned by the SDK wallet.
Parameters
external_subaccount = Subaccount.from_injective_address_and_index("inj1fjlfjy5adns4msjqch3vqjhesmwjnu9ep045wz", 1)
response = await sdk.injective.fund_external_subaccount(10, "FRCOIN", external_subaccount)
Name | Type | Req? | Description |
---|---|---|---|
amount |
int |
✓ | Amount to send |
denom |
str |
✓ | Denom identifier |
destination_subaccount |
Subaccount |
✓ | Subaccount to send to; cannot be subaccount 0 |
source_subaccount_index |
Optional[int] |
◯ None |
If provided, send from SDK wallet's subaccount with this index |
Response
print("transaction:", response.transaction)
Name | Type | Description |
---|---|---|
transaction |
str |
Injective Transaction ID |
Injective: Fund External Subaccount
Send funds to a separate Injective wallet. This sends from main bank balance to main bank balance.
Parameters
response = await sdk.injective.fund_external_wallet(10, "FRCOIN", "inj1fjlfjy5adns4msjqch3vqjhesmwjnu9ep045wz")
Name | Type | Req? | Description |
---|---|---|---|
amount |
int |
✓ | Amount to send |
denom |
str |
✓ | Denom identifier |
destination_injective_address |
str |
✓ | Injective account to send to |
Response
print("transaction:", response.transaction)
Name | Type | Description |
---|---|---|
transaction |
str |
Injective Transaction ID |
Injective: Fund Subaccount
Send funds from the main bank balance to a subaccount that IS owned by the SDK wallet. Or send funds between subaccounts that ARE BOTH owned by the SDK wallet.
Parameters
destination_subaccount_index = 2
wallet = await sdk.wallet()
destination_subaccount = wallet.subaccount(destination_subaccount_index)
# Equivalent methods of transferring from main bank balance to a subaccount
response = await sdk.injective.fund_subaccount(5, "FRCOIN", destination_subaccount_index=1)
response = await sdk.injective.fund_subaccount(5, "FRCOIN", destination_subaccount=destination_subaccount)
# Equivalent methods of transferring between subaccounts
response = await sdk.injective.fund_subaccount(5, "FRCOIN", source_subaccount_index=1, destination_subaccount_index=destination_subaccount_index)
response = await sdk.injective.fund_subaccount(5, "FRCOIN", source_subaccount_index=1, destination_subaccount=destination_subaccount)
Name | Type | Req? | Description |
---|---|---|---|
amount |
int |
✓ | Amount to send |
denom |
str |
✓ | Denom identifier |
destination_subaccount |
Optional[Subaccount] |
◯ None |
Subaccount to send to; cannot be subaccount 0. |
destination_subaccount_index |
Optional[int] |
◯ None |
Subaccount to send to; cannot be subaccount 0 |
source_subaccount_index |
Optional[int] |
◯ None |
If provided, send from SDK wallet's subaccount with this index |
destination_subaccount
and destination_subaccount_index
are mutually exclusive, and at least one must be specified.
Response
print("transaction:", response.transaction)
Name | Type | Description |
---|---|---|
transaction |
str |
Injective Transaction ID |
Injective: Fund Wallet from Faucet
Request a small amount of INJ from the faucet.
Parameters
response = sdk.injective.fund_wallet_from_faucet()
There are no parameters for this operation.
Response
print("message:", response.message)
Name | Type | Description |
---|---|---|
message |
str |
Message from the faucet |
Injective: Get Account Portfolio
Retrieves the account portfolio for the current wallet. For the corresponding Injective API, see Account Portfolio.
Parameters
response = sdk.injective.get_account_portfolio()
There are no parameters for this operation.
Response
print("portfolio bank balances:")
for coins in response.portfolio.bank_balances:
print("\tcoin:", coins.amount, coins.denom)
print("portfolio subaccount balances:")
for subaccount in response.portfolio.subaccounts:
print(
"\tsubaccount:",
subaccount.subaccount_id,
subaccount.deposit.available_balance, "/", subaccount.deposit.available_balance,
subaccount.denom,
)
Name | Type | Description |
---|---|---|
portfolio |
Portfolio |
Your account portfolio |
Injective: Get Order Books
Gets the order books for specific markets. For the corresponding Injective API, see Order Books v2.
Parameters
market_id = "0xd5e4b12b19ecf176e4e14b42944731c27677819d2ed93be4104ad7025529c7ff"
# Get order books for given market ids
response = sdk.injective.get_order_books([market_id])
Name | Type | Req? | Description |
---|---|---|---|
market_ids |
[str] |
✓ | IDs of markets to look up orders for |
Response
print("order_books:")
for market_id, order_book in response.order_books.items():
print("\tmarket:", market_id)
for buy in order_book.buys:
print("\t\tbuy:", buy.quantity, "@", buy.price)
for sell in order_book.sells:
print("\t\tsell:", sell.quantity, "@", sell.price)
Name | Type | Description |
---|---|---|
order_books |
Mapping[str, DerivativeLimitOrderbookV2] |
Order books keyed by market ID |
Injective: Get Orders
Gets open orders. For the corresponding Injective API, see Orders History.
Parameters
# Get all my orders
response = sdk.injective.get_orders(mine=True)
Name | Type | Req? | Description |
---|---|---|---|
mine |
bool |
◯ None |
Only return your orders |
market_ids |
[str] |
◯ None |
Only return orders with this market ID |
subaccount_id |
str |
◯ None |
Only return orders from this subaccount* |
subaccount |
Subaccount |
◯ None |
Only return orders from this subaccount. |
subaccount_index |
int |
◯ None |
Only return orders from this subaccount index of your wallet. Sets mine=True |
direction |
"buy", "sell" |
◯ None |
Only return orders with this direction |
state |
"booked" , "partial_filled" , "filled" , "canceled" |
◯ None |
Only return orders in this state |
is_conditional |
bool |
◯ None |
Only return orders that are/are not conditional |
order_types |
[str] |
◯ None |
Only return orders with these order types |
execution_types |
["limit", "market"] |
◯ None |
Only return orders with these execution types |
start_time |
datetime |
◯ None |
Only return orders starting on or after this time |
end_time |
datetime |
◯ None |
Only return orders ending on or before this time |
*Only one of subaccount_id
, subaccount
, or subaccount_index
may be provided.
Response
print("orders:")
for order_history in response.orders:
print(
"order:",
order_history.order_type,
order_history.order.quantity, "@", order_history.order.trigger_price,
order_history.order.order_hash,
)
Name | Type | Description |
---|---|---|
orders |
[OrderHistory] |
Orders |
Injective: Get Positions
Gets open positions. For the corresponding Injective API, see Positions.
Parameters
market_id = "0x90e662193fa29a3a7e6c07be4407c94833e762d9ee82136a2cc712d6b87d7de3"
# Get all buy positions
response = sdk.injective.get_positions(
[market_id],
direction="buy",
)
Name | Type | Req? | Description |
---|---|---|---|
mine |
bool |
? False |
Only find positions for this wallet |
subaccount |
Subaccount |
◯ None |
Only return orders from this subaccount. |
subaccount_index |
int |
◯ None |
Only return orders from this subaccount index of your wallet. Sets mine=True |
market_ids |
[str] |
? None |
IDs of markets to look up positions for |
direction |
"buy", "sell" |
◯ None |
Only find positions with this direction |
start_time |
datetime |
◯ None |
Only find positions executing on or after this time |
end_time |
datetime |
◯ None |
Only find positions executing on or before this time |
Response
print("positions:", response.positions)
Name | Type | Description |
---|---|---|
positions |
[DerivativePosition] |
Positions for the given markets |
Injective: Get Trades
Get trades (i.e. matched orders). For the corresponding Injective API, see Trades.
Parameters
market_id = "0x90e662193fa29a3a7e6c07be4407c94833e762d9ee82136a2cc712d6b87d7de3"
# Get all trades on the maker side
response = sdk.injective.get_trades(
[market_id],
side="maker",
)
Name | Type | Req? | Description |
---|---|---|---|
market_ids |
[str] |
✓ | IDs of markets to look up trades for |
mine |
bool |
◯ False |
Only find trades for this wallet |
subaccount |
Subaccount |
◯ None |
Only return orders from this subaccount. |
subaccount_index |
int |
◯ None |
Only return orders from this subaccount index of your wallet. Sets mine=True |
subaccounts |
[Subaccount] |
◯ None |
Only return orders from these subaccounts. |
subaccount_indexes |
[int] |
◯ None |
Only return orders from these subaccount indexes of your wallet. Sets mine=True |
direction |
"buy", "sell" |
◯ None |
Only find trades with this direction |
side |
"maker", "taker" |
◯ None |
Only find trades with this side |
start_time |
datetime |
◯ None |
Only find trades executing on or after this time |
end_time |
datetime |
◯ None |
Only find trades executing on or before this time |
Response
print("trades:", response.trades)
Name | Type | Description |
---|---|---|
trades |
[DerivativeTrade] |
Trades for the given markets |
Injective: Get Transaction
Gets open positions. For the corresponding Injective API, see GetTx.
Parameters
transaction_hash = "BAE72A64BE091B323F508F1887FAF4FA94C0EFE9348831C07DBB078CFC71E16A"
# Get all buy positions
response = sdk.injective.get_transaction(transaction_hash)
Name | Type | Req? | Description |
---|---|---|---|
transaction_hash |
str |
✓ | Injective transaction hash |
Response
print("raw injective response:", response.injective_response)
print("order failures:", response.order_failures)
Name | Type | Description |
---|---|---|
injective_response |
GetTxResponse |
Raw Injective response |
order_failures |
List[OrderFailure] |
If order failures are found in the logs, list of those failures |
order_failures[].flags |
List[int] |
Flags (error codes) of the order failure. See https://api.injective.exchange/#error-codes |
order_failures[].hashes |
List[str] |
Hashes of the order failure |
Injective: Refresh Wallet
Refreshes the wallet.
Transactions require a monotonically increasing sequence ID. This sequence ID is tracked internally in the wallet. If the sequence ID known in the wallet drifts for any reason, refreshing the wallet will update the wallet with the latest sequence ID.
Parameters
None.
response = sdk.injective.refresh_wallet()
Response
print("wallet sequence:", response.wallet.sequence)
Name | Type | Description |
---|---|---|
wallet |
Wallet |
The internal wallet, same instance as sdk.wallet() |
Injective: Stream Markets
Get market updates as they arrive. For the corresponding Injective API, see Stream Markets.
Parameters
async def run():
market_id = "0x90e662193fa29a3a7e6c07be4407c94833e762d9ee82136a2cc712d6b87d7de3"
response = async_sdk.injective.stream_markets([market_id])
Name | Type | Req? | Description |
---|---|---|---|
market_ids |
[str] |
✓ | Market IDs to watch for updates |
Response
async def run():
response = ...
async for market in response.markets:
print(market)
Name | Type | Description |
---|---|---|
markets |
AsyncIterator[DerivativeMarketInfo] |
Iterator for market updates |
Injective: Stream Orders
Get new orders as they arrive. For the corresponding Injective API, see Stream Order History.
Parameters
async def run():
market_id = "0x90e662193fa29a3a7e6c07be4407c94833e762d9ee82136a2cc712d6b87d7de3"
response = async_sdk.injective.stream_orders(market_id)
Name | Type | Req? | Description |
---|---|---|---|
market_id |
str |
✓ | Market ID to watch for orders |
mine |
bool |
◯ False |
Only watch for my orders |
subaccount |
Subaccount |
◯ None |
Only return orders from this subaccount. |
subaccount_index |
int |
◯ None |
Only return orders from this subaccount index of your wallet. Sets mine=True |
direction |
"buy", "sell" |
◯ None |
Only watch for orders of this direction |
subaccount_id |
bool |
◯ False |
Only watch for my orders from this subaccount |
order_types |
bool |
◯ False |
Only watch for orders of this type |
state |
bool |
◯ False |
Only watch for orders of this state |
execution_types |
bool |
◯ False |
Only watch for orders of this type |
Response
async def run():
response = ...
async for order_history in response.orders:
print("order:", order_history.order_type, order_history.order.order_hash)
Name | Type | Description |
---|---|---|
orders |
AsyncIterator[OrderHistory] |
Iterator for orders |
Injective: Stream Positions
Get new positions as they arrive. For the corresponding Injective API, see Stream Positions.
Parameters
async def run():
response = async_sdk.injective.stream_positions()
Name | Type | Req? | Description |
---|---|---|---|
mine |
bool |
◯ | Only stream positions that are mine |
market_ids |
[str] None |
◯ | Only stream positions for the given markets |
subaccount_ids |
[str] None |
◯ | Only stream positions that are from the given subaccount |
subaccounts |
[Subaccount] |
◯ None |
Only return orders from these subaccounts. |
subaccount_indexes |
[int] |
◯ None |
Only return orders from these subaccount indexes of your wallet. Sets mine=True |
Response
async def run():
response = ...
async for position in response.positions:
print(
"position:",
position.ticker,
position.direction,
position.quantity, "@", position.entry_price,
)
Name | Type | Description |
---|---|---|
positions |
AsyncIterator[DerivativePosition] |
Iterator for positions |
Injective: Stream Trades
Get new trades as they arrive. For the corresponding Injective API, see Stream Trades.
Parameters
async def run():
market_id = "0x90e662193fa29a3a7e6c07be4407c94833e762d9ee82136a2cc712d6b87d7de3"
response = async_sdk.injective.stream_trades(market_id)
Name | Type | Req? | Description |
---|---|---|---|
market_id |
str |
✓ | Market ID to watch for orders |
mine |
bool |
◯ False |
Only watch for my orders |
subaccount |
Subaccount |
◯ None |
Only return orders from this subaccount. |
subaccount_index |
int |
◯ None |
Only return orders from this subaccount index of your wallet. Sets mine=True |
subaccounts |
[Subaccount] |
◯ None |
Only return orders from these subaccounts. |
subaccount_indexes |
[int] |
◯ None |
Only return orders from these subaccount indexes of your wallet. Sets mine=True |
direction |
"buy", "sell" |
◯ None |
Only watch for orders of this direction |
side |
"maker", "taker" |
◯ None |
Only watch for orders of this side |
Response
async def run():
response = async_sdk.injective.stream_trades(market_id)
async for trade in response.trades:
print("trade:", trade.operation_type, trade.trade.order_hash)
Name | Type | Description |
---|---|---|
trades |
AsyncIterator[DerivativeTrade] |
Iterator for trades |
Injective: Withdraw from Subaccount
Withdraw funds from a subaccount that IS owned by the SDK wallet to the main bank balance.
Parameters
response = await sdk.injective.withdraw_from_subaccount(10, "FRCOIN", subaccount_index=1)
Name | Type | Req? | Description |
---|---|---|---|
amount |
int |
✓ | Amount to send |
denom |
str |
✓ | Denom identifier |
subaccount_index |
int |
✓ | Withdraw from SDK wallet's subaccount with this index |
Response
print("transaction:", response.transaction)
Name | Type | Description |
---|---|---|
transaction |
str |
Injective Transaction ID |
Utilities
Currency
Injective operates on raw coin quantities instead of decimal values. For example, 8 FRCOIN (as well as USDC and USDT) would be represented as "8000000"
. This is because FRCOIN's denomination is to 6 decimal places, and 8 shifted by 6 decimal places is 8,000,000.
Each denomination has its own fractional resolution, and all are mapped in Injective's SDK. See:
Also, denominations are usually returned as their peggy identity. These identities aren't easily human-interpretable and vary between devnet, testnet, and mainnet.
To make working with Injective's units easier, this SDK includes methods to get a unified representation of Currency
without needing to know denomination details such as how many digits of precision are involved.
In Currency
terms, quantity
means the Injective-side raw (decimal-less) value and value
means the human-friendly value (with decimals).
From Value
Factory for Currency
, given the Injective-side quantity and denomination.
Example
currency = sdk.utilities.currency_from_quantity(420_690_000, "FRCOIN")
print(
"currency:",
"[", currency.value, currency.denom.name, "]",
"is represented as",
"[", currency.quantity, currency.denom.peggy, "]",
"in injective",
)
Parameters
Name | Type | Req? | Description |
---|---|---|---|
quantity |
int, str |
✓ | Injective-side coin quantity |
denom_name |
str |
✓ | Name of denomination (human-readable name or peggy identity) |
Returns
A currency object.
From Quantity
Factory for Currency
, given the human-readable quantity and denomination.
Example
currency = sdk.utilities.currency_from_value(420.69, "FRCOIN")
print(
"currency:",
"[", currency.value, currency.denom.name, "]",
"is represented as",
"[", currency.quantity, currency.denom.peggy, "]",
"in injective",
)
Parameters
Name | Type | Req? | Description |
---|---|---|---|
value |
int, str |
✓ | Human-readable coin value |
denom_name |
str |
✓ | Name of denomination (human-readable name or peggy identity) |
Returns
A currency object.