derive-py
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.
- Derive v3 documentation
- Quickstart and depositing
- Action signing, session keys and access scopes
- Migrating from v2, written to double as a
SKILL.mdfor a coding agent - llms.txt, an index of every page for agents
- Machine readable specs, which this client is generated from: openapi.json, websocket.asyncapi.json, subscriptions.asyncapi.json
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
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
|
Zarathustra |
8ball030 |
8ball030-max |
Saikat K |
Andrei Augustin |
DomRom |
|
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
- Derive
- Protocol documentation
- Discord
- X / Twitter
- Sibling SDKs: derive-ts, derive-rs
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)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| derive_py-0.1.5.tar.gz | 221.0 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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 logRelease 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 logSecurity 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.
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 logA 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.