Skip to main content

derive-py

PyPI CI Licence

Official Python SDK for the Derive Protocol

Market data, orders, RFQs, transfers, withdrawals, deposits, vaults and session keys over HTTP or WebSocket, synchronously or asynchronously, plus a drv command line tool.

Documentation · Quickstart · Examples · CLI · Contributing


Documentation

Protocol semantics are documented by Derive and are not repeated here. Read them first, then come back for the Python bindings.

Install

pip install derive-py

Python 3.11 or newer.

Configure

Configuration comes from the environment, or from a .env file in the working directory (default), or from a custom path. Keep private keys out of it: store them in an encrypted keystore and let .env name the keystore. A plaintext DERIVE_SESSION_KEY still works, for the shared testnet keys in .env.template, for unattended runs where a secrets manager injects it, and for existing setups. There is no password variable on purpose: a keystore whose password sits next to it in .env protects nothing.

All variables are optional:

You set You get
nothing Public data only: markets and system. Anything account-scoped raises CredentialsRequired
DERIVE_KEYSTORE The owner key, decrypted from a keystore; the wallet is its address
DERIVE_KEYSTORE and DERIVE_WALLET A session key from a keystore, acting for that wallet
DERIVE_SESSION_KEY and DERIVE_WALLET A plaintext session key, or owner key, acting for that wallet
any signer above, plus DERIVE_SUBACCOUNT_ID A default subaccount, so client.orders and the like work
Variable Notes
DERIVE_WALLET The owner wallet, your own EOA or multisig
DERIVE_SESSION_KEY Private key of the signer, a session key or the owner. Takes precedence over DERIVE_KEYSTORE
DERIVE_KEYSTORE Keystore name in ~/.derive-py/keystores, or a path. Web3 Secret Storage, as geth and foundry use. The password is prompted for, so this needs a terminal
DERIVE_KEYSTORE_DIR Where keystore names resolve, for example ~/.foundry/keystores
DERIVE_SUBACCOUNT_ID Subaccount the client acts on by default
DERIVE_ETH_CHAIN SEPOLIA or ETHEREUM, defaults to SEPOLIA
DERIVE_ETH_RPC_ENDPOINTS Comma separated L1 RPC URLs, only used by the deposit flows

from_env() takes a session_key_path if you would rather keep the key in a file than in the environment, and an env_file to point at a .env elsewhere. Without from_env(), HTTPClient(ClientConfig(chain=Chain.ETHEREUM)) is a public-data client.

A wallet with no Derive account yet is valid: connect() succeeds, and the first deposit creates the account. examples/01-deposit.py walks through it, from creating an owner keystore to a funded subaccount, and examples/02-session-keys.py then registers a session key in its own keystore, so day-to-day trading never needs the owner key.

.env.template holds working testnet credentials. They are published on purpose so the examples run with no setup, and they are worthless: never reuse that key for anything else.

Quickstart

from derive_py import HTTPClient
from derive_py.data_types import D, Direction, OrderType

client = HTTPClient.from_env()

# Public market data needs no credentials and no connect().
ticker = client.markets.get_ticker(instrument_name="ETH-PERP")

# connect() validates the credentials and warms the instrument cache.
# Anything touching subaccount state needs it.
client.connect()

order = client.orders.create(
    instrument_name="ETH-PERP",
    amount=D("0.1"),
    limit_price=D("1000"),
    direction=Direction.buy,
    order_type=OrderType.limit,
)

client.disconnect()

D builds a Decimal. Pass decimals, never floats: amounts and prices are quantized to the instrument's amount_step and tick_size, and the protocol rejects rather than truncates excess precision.

Clients

Client Transport Concurrency
HTTPClient JSON-RPC over HTTP Blocking. Not thread safe, use one client per thread
AsyncHTTPClient JSON-RPC over HTTP Safe for concurrent tasks on a single event loop, not safe to share between threads
WebSocketClient JSON-RPC over WebSocket Safe for concurrent tasks on a single event loop, not safe to share between threads

Only WebSocketClient carries subscriptions. It also holds one connection open rather than paying setup on every call, so it is the one to reach for when latency matters. Its connect() is mandatory, since there is no transport before it. Both HTTP clients open their session lazily on first use, so they need connect() only for credential validation and cached state.

When its connection drops, WebSocketClient fails requests in flight with RequestAbandoned, reconnects with backoff, logs in again and resubscribes every channel, and keeps retrying until disconnect(). Messages sent during the outage are not replayed. If you subscribe, pass on_state_change to connect() and re-read anything built from the stream when it reports CONNECTED after RECONNECTING; examples/04-subscribe.py shows how. Subscribing without one logs a warning, once.

All three expose the same operations:

Attribute What it does
client.markets Currencies, instruments, tickers, risk universes. Public
client.system Server time, rate limits, operation lookup by uuid. Public
client.account The wallet: session keys, whitelisted recipients, subaccounts, portfolios
client.orders Create, replace, cancel, query
client.positions Open positions and position transfers
client.collateral Balances, margin, withdrawals, spot transfers
client.rfq Taker and maker RFQ flows
client.history Trades, orders, deposits, withdrawals, funding, interest
client.mmp Market maker protection config and reset
client.vaults Shareholder and curator operations
client.active_subaccount The subaccount the above act on, with cached_subaccounts for the rest
client.plan_deposit_to_new_subaccount On-chain deposit that creates a subaccount as it funds it

WebSocketClient adds public_channels, private_channels, subscriptions, connection_state and on_state_change. Every operation is also reachable per subaccount, subaccount.orders and so on, when one client drives several.

Anything not wrapped is reachable through client.public_api and client.private_api, which are generated from the specs above and cover the whole RPC surface.

Examples

Runnable and heavily commented, ordered by the v3 onboarding flow: your first deposit creates the account, then session keys, then the rest.

git clone git@github.com:derivexyz/derive-py.git
cd derive-py
pip install -e .
cp .env.template .env
python examples/03-market-data.py
Example What it covers
01-deposit.py Deposit: the only way an account or subaccount comes into existence
02-session-keys.py Session keys: register a scoped, expiring key, edit it, retire it
03-market-data.py Public market data: currencies, instruments, tickers
04-subscribe.py Websocket subscriptions: two public channels over one socket
05-place-order.py Order lifecycle: place, inspect, cancel
06-rfq-taker.py RFQ taker: request quotes for a package, execute the best one
07-rfq-maker.py RFQ maker: a bounded quoting loop
08-transfers.py Spot transfers: between your own subaccounts, and out to another owner
09-withdraw.py Withdraw collateral to L1
10-vaults.py Vaults: browse, queue a deposit, cancel it
11-position-transfer.py Position transfers: moving part of an open position between two subaccounts owned by the same wallet

01-deposit.py is the only one needing a funded L1 key and an RPC endpoint. The rest run against testnet with the credentials in .env.template.

CLI

drv --help          # every command
drv tree            # the tree below, from your installed version
drv market ticker ETH-PERP

CLI demo

drv
├── account.......... Account details.
│   ├── get.......... Account details.
│   └── portfolios... Get all portfolios of a wallet.
├── collateral....... Manage collateral.
│   └── get.......... Get subaccount collaterals.
├── market........... Query market data: currencies, instruments, tickers.
│   ├── currency..... Get currency details.
│   ├── instrument... Get instrument details.
│   ├── ticker....... Get ticker details.
│   └── universe..... List risk universes, their managers and accepted collaterals.
├── mmp.............. Market maker protection configuration.
│   ├── get-config... Get the current mmp config for a subaccount (optionally filtered by currency).
│   ├── reset........ Resets (unfreezes) the mmp state for a subaccount (optionally filtered by currency).
│   └── set-config... Set the mmp config for the subaccount and currency.
├── order............ Create, view, list, and cancel orders.
│   ├── cancel....... Cancel a single order.
│   ├── cancel-all... Cancel all orders.
│   ├── create....... Create a new order.
│   ├── get.......... Get state of an order by order id.
│   └── list-open.... List all open orders of a subaccount.
├── position......... Inspect and transfer positions across subaccounts.
│   ├── list......... List active positions of a subaccount.
│   └── transfer..... Transfer part of a position to another subaccount of the same wallet.
├── system........... Query system-level information.
│   ├── rate-limits.. Get the caller's current rate limits.
│   ├── time......... Get the current system time.
│   └── transaction.. Get a transaction by its operation UUID.
└── tree............. Print the command tree structure.

Development

git clone git@github.com:derivexyz/derive-py.git
cd derive-py
make install            # dependencies and git hooks
make fmt lint typecheck # while working
make tests              # hits the live testnet API
make all                # everything CI runs, in the order CI runs it

make all regenerates the client from the published specs, the API reference and the generated blocks in this README, then formats, lints, type checks and tests. CI runs the same targets and fails on a dirty tree, so run it before pushing and commit whatever it regenerates.

make codegen-all        # regenerate models, API and tests from the specs
make docs               # regenerate the README blocks and build the site
make demo               # re-record the CLI gif, needs cowsay, gum, asciinema, agg

shell.nix provides all of it, recording tools included.

Releasing

poetry run tbump 0.1.1

Tagging triggers the release workflow, which builds, creates a GitHub release and publishes to PyPI.

Contributors

Karrenbelt
Zarathustra
8ball030
8ball030
8ball030-max
8ball030-max
Aviksaikat
Saikat K
andreiaugustin
Andrei Augustin
0xdomrom
DomRom
DeBelg
Mf

This client library is developed with support from Derive, who host it under their organization. Requests include default referral_code and client identifiers. All code is open source and auditable.

Resources

Licence

MIT, see LICENSE.

Disclaimer

This software is provided as-is, without warranty. Trading derivatives involves substantial risk of loss.

Metadata

Release files for derive-py 0.1.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for derive-py 0.1.5
File Size Uploaded Provenance
derive_py-0.1.5.tar.gz 221.0 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for derive-py 0.1.5
File Interpreter ABI Platform
derive_py-0.1.5-py3-none-any.whl Python 3 none any Details

Total release size: 488.1 kB

Release files / derive_py-0.1.5.tar.gz

Download URL derive_py-0.1.5.tar.gz
Size 221.0 kB
Tags Source
SHA-256 checksum
How to use checksums
90bd0eb62a91d62984921ff3bf1a0b667c0891c794248dbaa2741a6a00fd2ef0
BLAKE2b-256 checksum
How to use checksums
eaba21b3a7fe426e415add32f0240b42820f233735cae8b085a862d1fbd3c3da
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / derive_py-0.1.5-py3-none-any.whl

Download URL derive_py-0.1.5-py3-none-any.whl
Size 267.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c3e9b16cac0c497e221d4cf099558111ad38c7712087298bb9edd0f2589af204
BLAKE2b-256 checksum
How to use checksums
c6df27e80275f093a1c1a947faaba590a97b7c0de4e9ae1e03522654c205fa03
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Security for derive-py 0.1.5

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for derive_py-0.1.5.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page