Skip to main content

Python SDK for trading on Native Core via the public gateway (testnet only for now).

Project description

native-core-python-sdk

Testnet only. This release connects to the Native Core testnet (the UAT gateway) and nothing else. Mainnet is not supported yet: approving an API wallet is currently open on the testnet site only, so a mainnet key cannot be created or used through the SDK. Treat this as an early, pre-1.0 release whose surface may still change; mainnet support will land in a later version.

A Python SDK for trading on Native Core. It reads market data, places and cancels orders, and runs trading bots against the public gateway.

There are two classes. Info handles reads, Exchange handles writes. Calls are synchronous (built on requests) and return the gateway's JSON as plain dicts, annotated with TypedDict.

The SDK trades with an API wallet: a key scoped to placing and cancelling orders, never to moving funds (section 2 covers why that makes it safe in a bot). Deposits and withdrawals stay in the web app with your main wallet.

You need Python 3.10 or newer. The runtime dependencies are requests, eth-account, and eth-utils.

Scope. Spot order-book markets only (no perpetual futures). Testnet only for now. Calls are synchronous and blocking: a /trade write returns its settled outcome inline (no polling to learn whether it landed), and there is no async API and no websocket or streaming feed (wrap calls in your own executor if you need concurrency). Deposits and withdrawals are done in the web app, not through the SDK.

1. Install

pip install native-core-python-sdk

While the SDK is pre-1.0, any release may change the API. Pin an exact version and review the changes before upgrading:

pip install native-core-python-sdk==0.2.0

2. Get an API wallet

Before the SDK can trade, you need a funded account and an API wallet (your bot's key). You set this up once in the Native web app. The SDK never handles funds itself.

  1. Open the Native app and connect your main wallet.
  2. Fund the account by depositing through the app. There is no faucet: bring your own Arbitrum Sepolia testnet assets and deposit them from your main wallet. Your trading account is created on the first deposit.
  3. Open the API wallets panel and click Create API wallet. Your main wallet signs one approval, and the app shows you a connection bundle that contains the private key. It shows the key once, so copy it now.

The bundle is a small JSON object. Save the whole thing to a file (e.g. bundle.json — that is what the quickstart loads), and hand it to the SDK as a file path, a dict, or a JSON string:

{
  "network": "testnet",              // which gateway to use
  "accountAddress": "0x…",           // your main wallet, the account the bot trades on
  "agentPrivateKey": "0x…",          // the API wallet key the SDK signs with
  "…": "…"
}

A leaked API wallet key can trade your balance, but it can never withdraw or move funds off Native, so it is safe to run in a bot. Revoke it in the app any time to rotate it.

3. Quickstart

Load the bundle, place a resting limit order, confirm it rests, then cancel it. This runs on testnet:

from decimal import Decimal

from native_core import Exchange, is_accepted, order_state

BUNDLE = "bundle.json"   # the file you saved, or the dict / JSON string itself
MARKET = "ETH/USDT"

exchange = Exchange.from_bundle(BUNDLE)   # picks the gateway, loads the key, sets owner
info = exchange.info

# Check the API wallet is approved before you trade.
print(exchange.agent_info())              # {"approved": True, "slot_id": 0, "epoch": 10}

# Price a bid well below the market so it rests instead of filling.
book = info.l2_book(MARKET, depth=1)
reference = book["asks"] or book["bids"]  # whichever side has liquidity
px = info.snap_price(MARKET, Decimal(reference[0]["price"]) / 2)
sz = info.min_order_size(MARKET, px)

# place() submits the order and waits for it to rest. It returns the handle and the state.
order = exchange.place(MARKET, is_buy=True, sz=sz, limit_px=px, tif="gtc")
print(order["cloid"], order["state"])     # 0x…  open

# Cancel it, then confirm it left the book.
cancel = exchange.cancel_by_cloid(MARKET, order["cloid"])
assert is_accepted(cancel)
final = info.wait_for_order(exchange.effective_account, MARKET, order["cloid"])
print(order_state(final))                 # cancelled

Two ideas this quickstart leans on — a write returns its settled outcome directly, and every order carries a reconcilable cloid — are the heart of the next section.

4. Core concepts

Reads versus writes. Info wraps POST /info (market data, balances, order status). Exchange wraps POST /trade (orders). Both return the gateway's raw JSON.

The write returns the settled outcome. The gateway is synchronous: a write's submission_status is exactly one of three values — accepted (the tx landed and executed, which INCLUDES a benign no-fill/no-rest cancel like ioccancel or marketordernoliquidity), rejected (an admission reject or a genuine execution failure, with the reason on error.code), or timeout (indeterminate). You do not poll to learn whether the write landed. What the response does not carry is the oid, the fill amount, or the fill/rest/cancel lifecycle — those live only on /info order status, so read the order once when you need them:

  • wait_for_open(user, market, cloid) for an order you expect to rest (gtc / alo). It returns the resting snapshot (with the oid).
  • wait_for_order(user, market, cloid) for one you expect to finish (ioc / fok / market, or after a cancel). It returns the terminal snapshot (with filled_qty).
  • exchange.place(...) submits and does that one enrichment read for you, returning {cloid, submission, status, state}.

Do not call wait_for_order on a resting order. A resting order has no terminal state, so the call just times out. That is what wait_for_open is for.

Every order is reconcilable. order() and market_order() return the cloid and the nonce they used; batch() returns cloids (one per order leg) plus the shared nonce. Pass your own cloid or let the SDK generate one; either way the response carries it. If a write times out on the wire, the SDK raises SubmissionUncertain with the cloid attached. Reconcile it with wait_for_order. Do not resubmit under a fresh nonce, or the order may land twice.

One Exchange per API wallet. The nonce is a per-instance monotonic counter and is lock-guarded, so a single Exchange is safe to share across threads. But two instances — or two processes — signing with the same key hand out colliding nonces and draw seemingly random rejections. Construct one and share it, rather than one per worker.

Numbers are strings, never floats. Pass sz and limit_px as str or Decimal: "0.01", not 0.01. Each market has a fixed precision (decimal places, significant figures, a minimum notional). info.snap_price(market, price) and info.min_order_size(market, price) round a value to what the market accepts. The SDK validates before signing and raises LocalValidationError rather than round your number down without telling you.

Errors live in the response body. A business rejection is data, not an exception: {"submission_status": "rejected", "error": {"code": …}}. Read it with the helpers is_accepted, is_rejected, is_timeout, error_code, retry_after_ms, and is_retryable. The SDK raises only for a transport failure (NetworkError), a response that is not a trade response (ClientError / ServerError), or a problem it catches before signing (LocalValidationError).

Markets by symbol or id. Anywhere a market argument appears, pass "ETH/USDT" or its integer id. Symbols and precision are fetched once when you construct Info.

Testnet only, for now. This release runs on testnet. The bundle's network must be testnet, and from_bundle picks the gateway. Building by hand against constants.MAINNET_API_URL (or a bundle with network: "mainnet") raises LocalValidationError — mainnet is not usable through the SDK yet, because an API wallet can only be approved on the testnet site. An API wallet is bound to one network.

5. Running the examples

The examples ship in the source distribution (the .tar.gz on PyPI), under examples/. They read examples/config.json; copy the template and fill in your key:

cp examples/config.json.example examples/config.json
{ "secret_key": "0x<agentPrivateKey>", "account_address": "0x<accountAddress>" }

Read-only tours live under examples/info/. They place no orders, but still read your key from config.json (the account address is derived from the key when account_address is blank), so a valid secret_key must be present:

python examples/info/query_markets_info.py     # tradable markets and their precision
python examples/info/query_orderbook_info.py   # the L2 order book for a market
python examples/info/query_balances_info.py    # your spot balances
python examples/info/query_open_order_info.py  # your open orders in a market

The trading examples sit at the top level. They place real orders on testnet:

python examples/basic_order.py          # resting limit order: place, confirm it rested, cancel
python examples/basic_market_order.py   # market order with an explicit protection price
python examples/basic_batch.py          # several orders and cancels under one nonce

They default to testnet and ETH/USDT. Edit the MARKET constant to trade a different market.

6. Using it from an AI agent

The SDK is built to be driven by an AI agent, not just a person. If you are wiring an agent (or an autonomous bot) to trade, start here: one safety contract, two integration paths.

Pointing an agent at mainnet raises LocalValidationError at construction (testnet only for now — see the top of this README).

The safety contract

An agent that places money-moving orders must hold to a few rules. The SDK returns each outcome as structured fields, so the agent branches on a field instead of parsing prose or remembering the rule. (Section 4 explains each rule; this is the agent-facing summary.)

  • Read the settled status; a fill is not implied. A successful write's submission_status is accepted — the tx landed, but accepted INCLUDES a benign no-fill/no-rest cancel, so it does not mean the order rested or filled. The response carries no oid, fill amount, or lifecycle — call reconcile_by_cloid (or wait_for_open for a resting order) once to read them.
  • Never resubmit an uncertain write. A wire timeout — SubmissionUncertain, or submission_status: "timeout" — means the order MAY still be live. Reconcile by cloid and act on the result; resubmitting under a fresh nonce risks a double-fill. The response says so directly: next_action is RECONCILE_BY_CLOID, with the cloid attached.
  • Rejections are data. A business rejection comes back in the body with an error.code; fix the cause. Only RateLimited is safe to resend (is_retryable).
  • Numbers are strings. Size with min_order_size and validate with build_order (a dry run that sends nothing) to avoid a precision or minimum-notional rejection.
  • Survive a restart. Generate the cloid yourself with random_cloid(), persist {intent, cloid} durably before calling order(..., cloid=cloid), and on restart reconcile every persisted cloid with reconcile_by_cloid before placing anything new. An agent that crashes after sending but before recording an SDK-generated cloid cannot reconcile and may double-fill — this is the idempotency-key pattern.

next_action(response) collapses any trade response into one verdict to branch on (it returns None for a non-trade response):

next_action Situation What the agent does
READ_ORDER_STATUS accepted — landed & executed Read order_status once for the oid / fill amount (the outcome itself is already settled — a single read, not a poll)
RECONCILE_BY_CLOID timeout — indeterminate reconcile_by_cloid; never resubmit
BACKOFF_AND_RETRY RateLimited — never admitted Sleep retry_after_ms, then resend the same order
FIX_AND_RESUBMIT rejected — admission or execution failure Read error.code, fix the input or account state, submit fresh
None not a trade response

as_problem_details(failure) renders any exception or rejected/timeout body into one flat {type, title, retryable, next_action, cloids, …} envelope (see the response helpers in section 7).

Option A — the MCP server (no glue code)

An optional MCP server lets an AI assistant that speaks the Model Context Protocol (such as Claude Desktop) read the market and place orders through the SDK, without you writing any glue code. Install it with the mcp extra:

pip install "native-core-python-sdk[mcp]"

Or, from a clone: pip install -e ".[mcp]".

The server reads its configuration from the environment, never from the assistant. Reads are always available; the order-placing and cancelling tools are registered only when you explicitly turn trading on, so a read-only setup physically cannot place an order.

Variable Purpose
NATIVE_CORE_BUNDLE Path to a connection bundle JSON ({network, accountAddress, agentPrivateKey}). Supplies everything on its own.
NATIVE_CORE_NETWORK testnet (default) when not using a bundle. Mainnet is not supported yet.
NATIVE_CORE_ACCOUNT Your account address, for account-scoped reads.
NATIVE_CORE_AGENT_KEY The API wallet's private key, required for trading.
NATIVE_CORE_ENABLE_TRADING Set to 1 to register the write tools. Off by default: without it the server is read-only even if a key is present.

Run it over stdio with native-core-mcp (or python -m native_core.mcp). To connect it to Claude Desktop, add this to its MCP config, pointing NATIVE_CORE_BUNDLE at your bundle file:

{
  "mcpServers": {
    "native-core": {
      "command": "native-core-mcp",
      "env": {
        "NATIVE_CORE_BUNDLE": "/path/to/your/bundle.json",
        "NATIVE_CORE_ENABLE_TRADING": "1"
      }
    }
  }
}

The read tools are always available: whoami, list_markets, get_orderbook, get_balances, list_open_orders, get_order (poll one order by cloid), get_fills (recent executions), get_min_order_size, and reconcile_order (the uncertain/timeout recovery). The write tools are registered only when trading is enabled: preview_order (a dry run that places nothing), place_limit_order, place_market_order, cancel_order, and cancel_all_orders. Every result is normalized so the assistant sees the order's state and what to do next; a timed-out or uncertain order comes back telling it to reconcile by cloid, never to resubmit.

Use a dedicated, limited API wallet here, never your main wallet. These tools are convenience, not a security boundary: the real protection is that the API wallet is scoped and revocable in the app.

Option B — drive the SDK from your agent code

If your agent does its own tool-calling (not MCP), call the SDK directly and hand the model the same decision-ready fields. A minimal place-then-reconcile loop:

from native_core import Exchange

exchange = Exchange.from_bundle(BUNDLE)   # a testnet bundle
order = exchange.place(MARKET, is_buy=True, sz=sz, limit_px=px, tif="gtc")

# Resolve the real outcome by cloid — never resubmit on an uncertain one.
verdict = exchange.info.reconcile_by_cloid(exchange.effective_account, MARKET, order["cloid"])
if verdict["undetermined"]:
    ...   # not confirmed yet: keep reconciling by cloid, do not re-place
elif verdict["is_filled"]:
    ...   # fully filled
elif verdict["filled_qty"] != "0":
    ...   # partially filled and still resting — verdict["filled_qty"] is how much
else:
    ...   # resting, unfilled (verdict["state"], e.g. "open")

The response helpers and reconcile_by_cloid (section 7) are the agent-facing surface. The MCP tools above are thin wrappers over exactly these SDK calls: get_orderreconcile_by_cloid, get_min_order_sizemin_order_size, preview_orderbuild_order.

7. API reference

Info (reads)

Build with Info(base_url) or Info.from_bundle(bundle). Any market argument takes a "BASE/QUOTE" symbol or an integer market id.

Method Returns
markets() / assets() / quote_assets() Tradable markets and their assets, with precision
resolve_market_id(market) Resolve a "BASE/QUOTE" symbol to its integer market id
l2_book(market, depth=20) Order book, up to 100 levels
mark_prices(asset_ids=None) / oracle_status() Mark prices; oracle health
query_status() Current query height and the available block-height window
user_balances(address) Spot balances
open_orders(address, market) Resting orders in one market
open_orders_all(address, markets=None) Open orders across markets, each tagged with its market id
order_status(oid=None, user=None, market=None, cloid=None) One order, by oid or by (user, market, cloid)
batch_order_status(orders) Up to 20 orders at once
user_fills(address, from_height, to_height, limit) Fills in a raw block-height window (≤10,000 blocks)
recent_fills(address, blocks=10000) Every fill in roughly the last N blocks, window resolved for you
iter_user_fills(address, start_height=None, …) Iterate all fills since a height, paged and deduped
tx_status(user, cloid) Status of a deposit / withdraw / settle / repay by cloid
account_status(address) Whether an account exists and its state
spot_credit_account(address) / spot_credit_positions(address) Credit-account details
user_agents(address) / agent_status(owner, agent_address) Approved API wallets; whether one is approved
snap_price(market, price) / min_order_size(market, price) Round a price or size to what the market accepts
protection_price(market, is_buy, slippage_bps, ref_price=None) Worst acceptable price for a market order, derived from the book
wait_for_open(user, market, cloid, timeout=5.0) Poll until the order is resting or terminal
wait_for_order(user, market, cloid, timeout=5.0) Poll until the order is terminal
reconcile_by_cloid(user, market, cloid, timeout=5.0) Did an order land? A one-call verdict (state, undetermined, is_filled, filled_qty) for the uncertain/timeout recovery path

Exchange (writes)

Build with Exchange.from_bundle(bundle), or Exchange(wallet, base_url, owner=<account_address>) where wallet is an eth_account account made from your API wallet key.

Method Description
place(market, is_buy, sz, limit_px, tif, cloid=None, *, confirm=True, timeout=5.0) Submit an order and wait for the outcome that matches its tif; returns {cloid, submission, status, state}. confirm and timeout are keyword-only
order(market, is_buy, sz, limit_px, tif, cloid=None) Limit order. tif is gtc / ioc / fok / alo
market_order(market, is_buy, sz, protection_px=None, tif="ioc", cloid=None, *, slippage_bps=None) Market order (ioc / fok). Pass protection_px (worst acceptable price) or slippage_bps to derive it from the book
build_order(market, is_buy, sz, limit_px, tif, cloid=None, order_type="limit") Dry run: validate and build an order without signing or sending it
cancel(market, oid) / cancel_by_cloid(market, cloid) Cancel one order
cancel_all(market) Cancel every open order in a market
cancel_open(markets=None) Cancel every open order across markets (only where orders rest)
modify(market, oid_or_cloid, replacement) Atomically cancel and replace one order
batch(items) Up to 10 mixed order / cancel / cancelAll / modify actions under one nonce
set_expires_after(expires_after_ms) Attach an expiry to every signed action
agent_info() Whether this API wallet is approved on the owner: {approved, slot_id, epoch}

Each write returns the raw gateway response with the client handle echoed in: submission_status, tx_hash, error, cloid (or cloids for a batch), and nonce.

Also on Exchange: the agent_address property (the signing wallet), effective_account (the account orders act on: the owner in agent mode, otherwise the wallet), and the static Exchange.random_cloid().

Response helpers

is_accepted, is_rejected, is_timeout, error_code, retry_after_ms, and is_retryable classify a trade response, and next_action turns one into a single verdict (READ_ORDER_STATUS, BACKOFF_AND_RETRY, RECONCILE_BY_CLOID, or FIX_AND_RESUBMIT). order_state pulls the status string out of an order_status response; is_terminal and is_undetermined classify it, and is_filled / filled_quantity read the fill. as_problem_details renders any failure — an exception or a rejected/timeout body — into one flat envelope, and retry_on_rate_limit(action) wraps a write to resend only on RateLimited, honoring retry_after_ms. random_cloid returns a fresh client order id.

Exceptions

Everything inherits from native_core.Error. Business rejections are not exceptions; they arrive in the response body (see above).

Exception Raised when
LocalValidationError Before signing: bad precision, below the minimum notional, an unknown tif or market, or (at construction) an API wallet that is not an approved agent
NetworkError A transport failure (timeout, connection, DNS) before any response arrived
SubmissionUncertain A write was signed and sent, then timed out. Carries cloid and nonce to reconcile with wait_for_order
ClientError An HTTP 4xx whose body is not a trade response. Has status_code, error_code, error_message
ServerError An HTTP 5xx whose body is not a trade response. Has status_code

ErrorCode is a convenience enum of known codes. Admission-layer codes are CamelCase — RateLimited, ExpiredTx, WrongChainId, DirectSignerIsActiveAgent, AgentEpochMismatch; execution-stage codes are lowercased — e.g. insufficientspotbalance, badalopx, tick, lotsize, marketclosed. An execution code lands on error.code of a rejected body when the transaction fails outright. But an order rejected purely at the order level — most notably a post-only (alo) order that would cross — comes back accepted (the transaction itself succeeded) with the code on its orderStatus lifecycle instead; the order did not rest. This is the sharpest case of accepted ≠ rested: read orderStatus for the real outcome. The code set is open-ended, so error_code(resp) returns unknown codes as raw strings.

Rate limits and retries

The SDK surfaces rate limiting but does not throttle or retry on its own. A RateLimited rejection comes back in the body with error.retry_after_ms. Use is_retryable(resp) (true only for RateLimited, which is never admitted, so resending the same order is safe) and retry_after_ms(resp) to back off. A timeout is never retryable. A read that hits an HTTP 429 or 503 with no trade body raises ClientError / ServerError, so pace your own requests. The gateway's real limits are not exposed here; get them from the platform.

Under load the gateway can return two other write-plane families. PlaceOrderSuspended (HTTP 503, with retry_after_ms) is a clean rejected body emitted before the order reaches the node when the chain is degraded (only cancels are allowed); it is not is_retryable, so back off with retry_after_ms(resp) and resubmit yourself once it clears — the order did not land. A submit-routing failure (HandoffTimeout, HandoffBufferFull:*, HandoffMultipleActive at 503; node_unreachable at 504) instead arrives as a timeout body — indeterminate, so next_action is RECONCILE_BY_CLOID: reconcile by cloid, never resubmit.

Transport controls

Info and Exchange (and their from_bundle) both accept timeout (per-request deadline in seconds, default 30; pass None for no deadline), pool_maxsize (connection pool size, default 100), and hooks for logging, latency capture, and tracing:

  • on_request(url_path, body, trace_id) — called before each request; trace_id is the id sent with it (see below), or None.
  • on_response(url_path, status, body, elapsed_ms, trace_id) — called after each response; trace_id is the x-trace-id the gateway returned, or None.

The gateway accepts an x-trace-id request header and echoes it back, so you can line up a request with the gateway's own logs. You supply the id — the SDK never generates one:

  • trace_id_factory (constructor) — called once per request for the id to send; e.g. lambda: str(uuid.uuid4()) for a unique id, or a fixed value to group requests. Omit it to send no header.
  • trace_id= (per call to post) — overrides the factory for one request.

To only capture the id the gateway itself generates, send none and read the trace_id argument of on_response.

import uuid

exchange = Exchange.from_bundle(
    bundle,
    trace_id_factory=lambda: str(uuid.uuid4()),
    on_response=lambda path, status, body, ms, trace_id: log(path, trace_id),
)

Constants

constants.TESTNET_API_URL, constants.MAINNET_API_URL, and constants.NETWORK_URLS (network name to gateway URL). The chain id is derived from the URL. The mainnet values are defined but not usable yet: constructing Info or Exchange against the mainnet gateway raises LocalValidationError (testnet only for now).

8. Troubleshooting

You see Meaning and fix
LocalValidationError: … is not an active agent for owner (at construction) The API wallet is not approved on that account. Check the owner, or create a fresh API wallet: the old key may have been revoked or replaced in the app. Call info.agent_status(owner, agent) to see the current slots.
SubmissionUncertain A write timed out on the wire. Reconcile with wait_for_order(user, market, e.cloid). Do not resubmit under a new nonce.
NetworkError A transport failure (timeout, connection, DNS) on a read. Retry the read.
DirectSignerIsActiveAgent You built Exchange with an API wallet key but no owner. Pass owner=<accountAddress>, or use from_bundle.
WrongChainId The key's network does not match the gateway. from_bundle avoids this; if you build by hand, match the endpoint to the bundle's network.
LocalValidationError: … decimal places / significant figures sz or limit_px exceed the market's precision. Snap them with info.snap_price / info.min_order_size.
insufficientspotbalance (rejected) The account is not funded for that market's quote asset.
submission_status: "rejected" A hard write failure — an admission reject OR a genuine execution failure. Read error_code(resp). It is data, not an exception.
submission_status: "timeout" Indeterminate: the order may still land. Reconcile with wait_for_order; never resubmit with a new nonce.
AgentEpochMismatch The SDK refreshes and retries once on its own. If it persists, the API wallet was revoked or re-approved; create a new one.

9. Development

make install   # uv sync
make lint      # ruff + mypy --strict
make test      # pytest

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

native_core_python_sdk-0.2.0.tar.gz (88.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

native_core_python_sdk-0.2.0-py3-none-any.whl (60.4 kB view details)

Uploaded Python 3

File details

Details for the file native_core_python_sdk-0.2.0.tar.gz.

File metadata

  • Download URL: native_core_python_sdk-0.2.0.tar.gz
  • Upload date:
  • Size: 88.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.27 {"installer":{"name":"uv","version":"0.9.27","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for native_core_python_sdk-0.2.0.tar.gz
Algorithm Hash digest
SHA256 11423357977cf1d45cddb1d5313e55d3c11fc21dbd15ff57ba5fb2989b42de65
MD5 13d63445bff1df2e2424ed1d0a6f69e9
BLAKE2b-256 c25acf51d89e448d0b73daeaad27c2793cd9432a42087e75fdc72f1cdb0df12b

See more details on using hashes here.

File details

Details for the file native_core_python_sdk-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: native_core_python_sdk-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 60.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.27 {"installer":{"name":"uv","version":"0.9.27","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for native_core_python_sdk-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ec8bdc0d5fc50997fafe59ea5501b3c6a75ea42be391c532962f1b0f508a81d4
MD5 0b1b8b20916fc1abf6926209530a97a1
BLAKE2b-256 8ee019c3e1e23cf9c134aaf8276e2f81159cab248b64c0e70d5e29d492c17e9c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page