For the complete documentation index, see llms.txt. This page is also available as Markdown.

Examples

Runnable scripts that ship with the Native Core Python SDK, plus two self-contained snippets.

The SDK ships a folder of runnable scripts under examples/ in the source distribution (the .tar.gz on PyPI). They all read examples/config.json — a two-field file you copy from the template and fill in with your API wallet key:

{ "secret_key": "0x<agentPrivateKey>", "account_address": "0x<accountAddress>" }

secret_key is the agentPrivateKey from your connection bundle; account_address is your main wallet (leave it blank to derive it from the key and trade in direct-owner mode). For how to create the API wallet and set this up, see getting-started.md.

cp examples/config.json.example examples/config.json   # then paste your key

The read-only scripts under examples/info/ place no orders, but they still read secret_key from config.json (the account address is derived from the key when account_address is blank), so a valid key must be present.

Get the examples

The runnable scripts live in examples/. pip install native-core-python-sdk==1.0.0 ships most of them inside the source distribution, but the complete folder — including market_maker_bot.py — lives only in the repo, which is excluded from the published PyPI package. Clone it from the Native GitHub org to get everything, set up the config as above, and run any script from the repo root:

git clone https://github.com/Native-org/native-core-python-sdk.git
cd native-core-python-sdk
cp examples/config.json.example examples/config.json   # paste your key (see above)
python examples/basic_order.py                          # runs from the repo root

Preflight: setup()

Every shipped script opens with the same call — run it first:

from example_utils import setup

address, info, exchange = setup()   # reads examples/config.json

setup() reads examples/config.json, builds the API wallet from secret_key, resolves agent-vs-owner (a blank account_address derives the address from the key and trades in direct-owner mode; a filled one signs as an agent on that owner), prints the effective account and endpoint, then — before returning — reads user_balances for the owner and hard-fails if the account holds nothing:

It turns the two misconfigs that would otherwise surface as empty query results or opaque rejections — a wrong owner address, or an unfunded account — into one clear up-front error (RuntimeError: account 0x… has no balances … fund it before running). Read-only scripts call read_only() instead: same config, but no balance gate and no signing wallet, so it runs even when the key is not yet an approved agent.

Shipped scripts

File
What it shows

basic_order.py

A resting gtc limit order end to end: place with a cloid, poll order_status until it rests (open), cancel_by_cloid, then wait_for_order to confirm the terminal cancelled state.

basic_market_order.py

A protected market_order with an explicit protection_px (the worst price you accept — this example passes it directly rather than deriving it from slippage_bps). Buys a minimum-notional clip 2% through the best ask, then market-sells the fill to flatten.

basic_batch.py

A mixed batch under one nonce: two resting bids in one call, then a second batch that modifys the first order and cancels the second — atomically. Per-leg outcomes are reconciled with one order_status lookup per leg.

info/query_markets_info.py

Read-only: list the tradable markets and their precision (markets()).

info/query_orderbook_info.py

Read-only: the L2 order book for one market (l2_book).

info/query_balances_info.py

Read-only: your spot balances, available and locked per asset (user_balances).

info/query_open_order_info.py

Read-only: your resting orders in one market (open_orders).

The trading scripts default to testnet (the base-url default in example_utils.setup()) and to ETH/USDT. Pass setup(base_url=constants.MAINNET_API_URL) to run on mainnet, or edit the MARKET constant for another market. Run them from the repo root:

examples/market_maker_bot.py is an illustrative cancel-and-replace market-making loop — it re-quotes both sides as post-only (alo) orders every few seconds and caps inventory. It is excluded from the published PyPI package, so pip install does not ship it; clone the repo from the Native GitHub org to run it.

Read markets and the order book

Self-contained read-only script. Info wraps POST /info; reads need only the endpoint, so no order is ever signed here. See Decimals & Units for what price_decimals and base_quantity_decimals mean.

Place a resting limit order and cancel it

Self-contained write script. Exchange wraps POST /trade and owns an internal Info as exchange.info. Use one Exchange per API wallet and share it across threads — the nonce is a per-instance, lock-guarded counter. Pass sz and limit_px as str or Decimal, never float.

Rounding & precision

A price or size from your own model rarely lands on the market's grid. Snap both to what the market accepts before signing: info.snap_price(market, price) rounds to the market's price_decimals / max_price_sig_figs, and info.min_order_size(market, px) returns the smallest size that clears the quote asset's minimum notional at that price. Both return wire-ready strings; floats are rejected — pass str or Decimal or the SDK raises LocalValidationError at validation rather than round you down silently.

snap_price takes a rounding argument (ROUND_DOWN by default; pass ROUND_UP for an ask so it never snaps below your target), and min_order_size a margin (default "1.1") for headroom over the bare minimum. See Decimals & Units for the raw/atom conversion that makes floats unsafe, and notation for the field-level number rules.

Cancel on disconnect (dead-man's switch)

There is no server-side scheduled cancel: if your process dies, its resting orders stay on the book until they fill or you cancel them. Build the dead-man's switch client-side — flatten everything on the way out, on every exit path. exchange.cancel_open() finds where the effective account actually rests (one read) and issues a cancelAll on each of those markets; cancels are always admitted, even for a frozen account.

market_maker_bot.py ships this pattern in full: it re-quotes as post-only (alo) orders and, in its finally, calls cancel_all and reconciles per handle so nothing is left resting after the process exits.

See also

Last updated