Skip to main content

Institutional-grade Python SDK for the Viper Execution trading API on Hyperliquid.

Project description

Viper Execution Python SDK

Institutional-grade Python client for the Viper Execution trading API on Hyperliquid.

Status: SDK 0.2.0 (beta). Ships the resilient WebSocket client and the resync REST-fetch mapping. The full typed REST client lands in a subsequent release. The SDK version is independent of the API version — this is SDK 0.x against API v1.

Install

pip install viper-execution

Requires Python ≥ 3.10.

Quickstart

import os
import asyncio
from viper import ViperWSClient

async def main():
    # from_env() reads VIPER_API_KEY / VIPER_API_SECRET / VIPER_HANDLE /
    # VIPER_WALLET. Pass anything explicitly to override the environment.
    wallet = os.environ["VIPER_WALLET"].lower()
    client = ViperWSClient.from_env(
        on_event=lambda f: print(f["channel"], f.get("event")),
    )
    await client.start()
    await client.subscribe("account.state", wallet)
    await asyncio.sleep(30)
    await client.close()

asyncio.run(main())

Using credentials

ViperWSClient takes credentials two ways, both first-class — pick whichever fits how your process gets its secrets.

From the environment (quickest, and production-correct). from_env() reads VIPER_API_KEY, VIPER_API_SECRET, VIPER_HANDLE, and VIPER_WALLET. This is also the right pattern for deployment: containers, CI, and secret managers all inject secrets as env vars, so the same code runs unchanged from laptop to production. Anything passed explicitly overrides the environment:

client = ViperWSClient.from_env(handle="override-handle")

Explicitly (your own secret store). If your keys live in Vault, AWS Secrets Manager, an HSM, or a config file, fetch them in your code and pass them to the constructor directly — from_env() is never required:

api_key_id, api_secret = my_secret_store.get("viper")  # however you fetch them
client = ViperWSClient(
    api_key_id=api_key_id,
    api_secret=api_secret,
    handle="your-handle",
    wallet="0x...",
    on_event=lambda f: print(f["channel"], f.get("event")),
)

Runnable examples

Examples ship inside the package — no extra downloads. List the catalog and run one by name or number:

viper-examples                          # list the catalog
viper-examples stream-account-state     # run by name
viper-examples 01                       # ...or by number

Set the env vars the examples read — bash/zsh:

export VIPER_API_KEY=vk_...
export VIPER_API_SECRET=vs_...
export VIPER_HANDLE=your-handle     # optional
export VIPER_WALLET=0x...           # the wallet to stream

…or PowerShell:

$env:VIPER_API_KEY = "vk_..."
$env:VIPER_API_SECRET = "vs_..."
$env:VIPER_HANDLE = "your-handle"   # optional
$env:VIPER_WALLET = "0x..."         # the wallet to stream

Live algo examples

Two examples fire a real algo over the WebSocket command surface:

viper-examples start-glidemaker     # passive limit
viper-examples start-pacemaker      # TWAP

These place real orders on mainnet (there is no testnet). Each one reads the live BTC mark from /v1/instruments, sizes the order to a USD notional, prints exactly what it is about to do with a short Ctrl-C abort window, fires once, streams the execution's frames (fills, slices, status), then cancels. Optional knobs:

export VIPER_EXAMPLE_USD=250         # target notional (default 250)
export VIPER_EXAMPLE_OBSERVE_S=10    # seconds to observe before cancel (default 10)
export VIPER_EXAMPLE_NO_CANCEL=1     # leave the execution running instead of cancelling

The source for each example lives in src/viper/examples/.

What the WebSocket client handles for you

The /v1/ws stream has a number of behaviors a naive client gets wrong. ViperWSClient handles them as a built-in contract:

  • Liveness — transport ping/pong plus a data-staleness watchdog; silent half-open connections are detected and reconnected.
  • Reconnect with resume — on drop, it reconnects with exponential backoff and resubscribes every scope carrying its last_seq cursor, so you resume exactly where you left off (replay from the per-scope ring buffer).
  • Resync recovery — when the server can't satisfy a cursor (buffer_overflow / last_seq_ahead_of_server / scope_not_found), it REST-fetches authoritative current state and resubscribes fresh.
  • Multi-wallet attribution — every data frame is routed by data.wallet, so one socket can carry many wallets without cross-attribution. (Control markers such as hydrated carry no data.wallet; route those by scope_id.)
  • Slow hydration — account.state hydration is server-slow (~5s; it gathers balance + HIP-3 collateral across all dexes, then bursts frames). The client does not mistake that for a dead stream, and neither should your application logic.
  • Terminal conditions — credential revocation (close 4013), a handshake auth rejection (HTTP 401/403 — revoked/invalid key or insufficient scope), or an exhausted reconnect budget all stop the loop permanently via on_terminal rather than reconnect-hammering.

Callbacks

Callback Fires on
on_event(frame) Every classified data frame (the main path)
on_meta(frame) _meta frames: welcome + upstream connectivity events
on_terminal(code) Terminal stop. code is the WS close code (4013 = credentials revoked), the handshake HTTP status (401/403), or -1 (reconnect budget exhausted)
on_command_result(frame) Subscribe acks / command errors (no correlation id)
on_raw(frame) Optional advanced tap: every frame pre-classification (audit/metrics)

License

MIT — see LICENSE.

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

viper_execution-0.2.1.tar.gz (28.4 kB view details)

Uploaded Source

Built Distribution

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

viper_execution-0.2.1-py3-none-any.whl (35.1 kB view details)

Uploaded Python 3

File details

Details for the file viper_execution-0.2.1.tar.gz.

File metadata

  • Download URL: viper_execution-0.2.1.tar.gz
  • Upload date:
  • Size: 28.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for viper_execution-0.2.1.tar.gz
Algorithm Hash digest
SHA256 33c734dfe28d411f0325c88bd7e0f3c6eb93ed2da7aed30896913a31101afca0
MD5 a8210cf2eafe412342035b9c2e92f305
BLAKE2b-256 df58ae9cf821407a30d497913fcab08d9e66ed2fea655f0588e104bce662ee19

See more details on using hashes here.

Provenance

The following attestation bundles were made for viper_execution-0.2.1.tar.gz:

Publisher: release.yml on viperexecution/viper-sdk-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file viper_execution-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: viper_execution-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 35.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for viper_execution-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 efdae6df1127f99a192ddd2840a347949ec5be09ca1069214527c6f0cb5b17a4
MD5 487d973666a2630b2d168e0c64c12903
BLAKE2b-256 2b20571331ff81290ce33657abc3ce39b72b675980154664a41a3aa93e4c48a8

See more details on using hashes here.

Provenance

The following attestation bundles were made for viper_execution-0.2.1-py3-none-any.whl:

Publisher: release.yml on viperexecution/viper-sdk-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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