Skip to main content

Official non-custodial Python SDK for the Kash prediction-market protocol. Dual-mode: vanilla EIP-1559 from a plain EOA (canonical Hummingbot path) or ERC-4337 v0.7 via SimpleAccount + bundler. Mirrors @kashdao/protocol-sdk (TypeScript).

Project description

kashdao-protocol-sdk (Python)

Official Python SDK for the Kash prediction-market protocol — the canonical Hummingbot integration path and a first-class option for any Python trading bot, AI agent, or partner integration.

PyPI version Python versions License: MIT CI mypy: strict Ruff

🧪 Staging release. Base mainnet (8453) protocol contracts are not yet deployed; only Base Sepolia (84532) is supported today. See Supported chains for the mainnet timeline.

Status: 0.1.0b1 (beta). Both modes ship complete:

  • EOA mode (vanilla EIP-1559) — create_eoa_client. The canonical Hummingbot integration path; bring your own RPC + signer.
  • Smart Account mode (ERC-4337 v0.7) — create_smart_account_client. SimpleAccount + bundler; bring your own RPC + signer + bundler URL.

Cross-language parity with @kashdao/protocol-sdk (TypeScript) is validated by tests/parity/ — the same JSON fixtures drive both SDKs, so EIP-1559 serialization and UserOp v0.7 hashes are byte-equal by construction. A position opened via either SDK can be closed via the other.

Supported chains

Chain Chain ID Status
Base mainnet 8453 ⏳ Pre-deploy — KashChainError(CHAIN_NOT_DEPLOYED) until launch
Base Sepolia 84532 ✅ Live
Custom chain any ✅ Via custom_chain=CustomChain(...) (Anvil / forks / dev)

When to use this package

You are… Mode Notes
A Hummingbot strategy author with eth_account already in use EOA Canonical path — see HUMMINGBOT_INTEGRATION.md
A Python market maker with existing tx-signing infra (HSM, Fireblocks, web3signer, AWS-KMS) EOA Plug your signer in via the EoaSignerAdapter Protocol
An AI agent runner in Python with a bundler relationship SA Adds gasless onboarding via paymaster + batched approve+trade
A research / data-science user evaluating the protocol from a Jupyter notebook EOA One create_eoa_client(...) call away from quotes + reads
A TypeScript / web developer building a retail integration Use @kashdao/sdk (REST) or @kashdao/protocol-sdk (TS) instead

Install

pip install kashdao-protocol-sdk

Requires Python ≥ 3.10. End-user installs touch only the public PyPI registry — no private repos, no auth tokens.

Quickstart (EOA mode — canonical Hummingbot path)

import asyncio
import os

from eth_account import Account
from kashdao_protocol_sdk import (
    BuildApproveParams,
    BuildBuyParams,
    MAX_UINT256,
    create_eoa_client,
    usdc,
    viem_account_eoa_signer,
)

MARKET = "0x..."  # the Market contract address you're trading


async def main() -> None:
    account = Account.from_key(os.environ["KASH_PRIVATE_KEY"])
    signer = viem_account_eoa_signer(account)

    client = create_eoa_client(
        chain_id=84532,                            # Base Sepolia
        rpc=os.environ["BASE_SEPOLIA_RPC"],
        signer=signer,
    )

    # First-time setup: approve the Market contract to spend USDC.
    await client.trades.send.approve(
        BuildApproveParams(
            account=account.address,
            spender=MARKET,
            amount=MAX_UINT256,
        ),
    )

    # Per trade tick:
    result = await client.trades.send.buy(
        MARKET,
        BuildBuyParams(
            smart_account=account.address,         # in EOA mode, this is the EOA itself
            outcome=0,
            amount_usdc=usdc(10),                  # 10 USDC
            max_slippage_bps=50,                   # 0.5%
        ),
    )
    print(result.transaction_hash, result.success, result.gas_used)


asyncio.run(main())

That's it. No bundler URL, no SimpleAccount provisioning, no UserOp. Just an EOA, an RPC URL, and EIP-1559 transactions.

For Hummingbot users: see HUMMINGBOT_INTEGRATION.md for the full strategy-author guide.

Quickstart — smart-account mode

For consumers on AA stacks (Privy, Coinbase Smart Wallet, Pimlico, Alchemy AA), or who want gasless onboarding via paymaster:

import asyncio
import os

from eth_account import Account
from kashdao_protocol_sdk import (
    BuildBuyParams,
    BundlerOptions,
    create_smart_account_client,
    usdc,
    viem_account_signer,
)


async def main() -> None:
    account = Account.from_key(os.environ["KASH_PRIVATE_KEY"])

    async with create_smart_account_client(
        chain_id=84532,
        rpc=os.environ["BASE_SEPOLIA_RPC"],
        signer=viem_account_signer(account),
        bundler=BundlerOptions(
            provider="pimlico",
            url=os.environ["KASH_BUNDLER_URL"],
        ),
    ) as client:
        sa = await client.account.address()  # deterministic, no deploy needed
        result = await client.trades.send.buy(
            os.environ["KASH_MARKET"],
            BuildBuyParams(
                smart_account=sa,
                outcome=0,
                amount_usdc=usdc(10),
                max_slippage_bps=50,
            ),
        )
        print(result.user_op_hash, result.transaction_hash, result.success)


asyncio.run(main())

The full set of runnable examples (EOA, SA, Hummingbot, local Anvil) lives in examples/.

Power users — explicit trade lifecycle

client.trades.send.{buy,sell,close_position,approve} is the all-in-one ergonomic path: it builds, prepares (gas + fees + nonce), simulates, signs, submits, and (by default) waits for inclusion. For full control the lifecycle is exposed in three layers — pick the highest one that fits:

Layer When you'd use it
client.trades.send.<action>(...) Default. Hummingbot, AI agents, dashboards.
client.trades.prepare_<action>(...) then submit You want explicit control of the signing step — e.g. log + audit before signing.
client.trades.build_<action>(...) + hash_of(...) You want to construct the unsigned tx, hash it, route to a remote signer yourself.

client.trades.hash_of(transaction) and the SA equivalent client.trades.hash_of(user_op) are the canonical hash that the chain's signature-recovery validates against — call this AFTER populating gas + fees and BEFORE signing to avoid stale-hash footguns. Submit-time STALE_SIGNED_TX / STALE_USEROP_HASH checks are the backstop.

Real-time market events

async with client.markets.watch(market_address) as sub:
    async for event in sub:
        print(event.event_type, event.market, event.data)

WebSocket if your RPC URL starts with wss://, otherwise polling. Both yield the same event shape. Events are bounded queues; a slow consumer won't OOM the SDK — the queue's high-water mark is documented in the watch config.

Error handling

Every error inherits from KashProtocolError and carries a stable code, structured context, plus is_retryable / is_operational flags. Mirrors the TypeScript @kashdao/protocol-sdk hierarchy exactly — same class names, same string-valued ErrorCode constants.

from kashdao_protocol_sdk import (
    KashChainError,
    KashConfigError,
    KashSignerError,
    KashSimulationRevertedError,
    KashAbortedError,
)

try:
    await client.trades.send.buy(market, params)
except KashSimulationRevertedError as e:
    # Pre-flight `eth_call` caught a revert before any signing happened.
    # `revert_hint` decodes the on-chain custom error name when known.
    print(f"would revert: {e.revert_hint or e}")
except KashSignerError as e:
    # Signer-side failure. ALWAYS non-retryable — re-prompting MFA on
    # retry is a footgun.
    print(f"signer failed: {e}")
except KashChainError as e:
    # Chain/RPC failure. May be retryable.
    if e.is_retryable:
        ...  # back off and retry
except KashConfigError as e:
    # Misconfig. Never retryable. Fix the code.
    raise
except KashAbortedError:
    # The caller's `signal` fired. Deliberate; don't auto-retry.
    raise

A full worked example lives in examples/eoa/03_error_handling.py.

What this SDK deliberately does NOT do

  • Kash-orchestrated trade routing. No Kash backend on the trade path. If you want a REST surface that wraps the Kash public API, use @kashdao/sdk — that path is also non-custodial (Kash never holds funds, never moves funds, never holds keys, never signs anything; the user's Privy-managed smart account is the signer).
  • Sponsor or bundle UserOps. Bring your own bundler URL.
  • Hold or generate keys. Bring your own signer (eth_account, KMS, Fireblocks, hardware wallet).
  • Background market scanners. markets.watch only fires while a consumer is iterating; idle subscriptions are torn down via aclose.
  • Auto-retries on submit. Submit is single-attempt by design. Reads (prepare_*, simulate) are retryable via RetryOptions.
  • Telemetry. Zero phone-home. The SDK never reaches Kash infrastructure.

Public surface

The SDK mirrors @kashdao/protocol-sdk (TypeScript) with snake_case names. ~210 public exports across:

  • Factories: create_eoa_client, create_smart_account_client
  • Signers: LocalEoaSigner, JsonRpcEoaSigner (EOA); LocalSigner, JsonRpcSigner (SA)
  • Bundlers (SA): create_generic_bundler_client plus presets for create_alchemy_bundler_client, create_pimlico_bundler_client, create_flashbots_bundler_client
  • Trade lifecycle: client.trades.{build_*, prepare_*, simulate, hash_of, submit, send.*}
  • Market reads: client.markets.{get, state, quote, watch}
  • Account reads: client.account.{usdc_balance, position, gas_balance, usdc_allowance}
  • Allowance helpers: encode_approve, MAX_UINT256, get_usdc_allowance
  • Unit conversion: usdc, tokens, format_usdc, format_tokens
  • Fee estimation: estimate_chain_fees with EstimateFeesOptions (eth_feeHistory windowing, percentile, base multiplier, priority floor)
  • Custom-chain support: CustomChain, resolve_custom_chain for Anvil / Hardhat / Tenderly forks
  • Error hierarchy: KashProtocolError and 6 subclasses (KashConfigError, KashChainError, KashBundlerError, KashSignerError, KashSimulationRevertedError, KashAbortedError); cross-class identity via KashProtocolError.is_(value)
  • Lifecycle hooks: KashProtocolHooks Protocol with 5 fire-and-forget callbacks for telemetry / structured logging
  • Cancellation: every async method takes a signal parameter; throw_if_aborted and to_kash_aborted helpers wrap asyncio.CancelledError into KashAbortedError

Architectural boundary

This is a non-custodial library. Consumers bring:

  • their own RPC URL,
  • their own private key OR signer abstraction (eth_account.Account, web3signer over RPC, hardware wallet, Fireblocks, AWS-KMS — anything exposing the EoaSignerAdapter Protocol),
  • (SA mode only) ERC-4337 bundler URL + smart-account address.

Kash never sees a private key, never relays a transaction or UserOp, never sponsors gas, and is never on the trade path. The library's job is to construct calldata + the unsigned tx, then forward signed artifacts to the consumer's RPC.

Why dual modes?

  • EOA mode — vanilla EIP-1559 from a plain EOA. Best for market makers, Hummingbot strategies, AI agents, any consumer with their own EIP-1559 signing infrastructure (web3signer, Fireblocks, AWS-KMS, eth-account local key, hardware wallets).
  • Smart Account mode — ERC-4337 v0.7 via SimpleAccount + bundler. Best for users on AA stacks (Privy embedded wallets, Coinbase Smart Wallet, Pimlico, Alchemy AA), or flows that benefit from gasless onboarding via paymaster, batched approve+trade, or session keys.

Both modes share the same markets / account-read surface and the same discriminated TradingClient union.

Source repository

This repository is the canonical public source. PyPI releases are published from tags here via OIDC trusted publishing (.github/workflows/publish-pypi.yml).

ABIs under kashdao_protocol_sdk/shared/contracts/generated/ are vendored at release time and shipped in the wheel; runtime loading goes through importlib.resources, so consumers don't need any post-install fetch step.

See RELEASING.md for the full release runbook, CONTRIBUTING.md for the contributor workflow, and SECURITY.md for the vulnerability-disclosure policy.

License

MIT. The artifact published to PyPI is MIT-licensed; the development repo is private but the published library carries no usage restrictions.

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

kashdao_protocol_sdk-0.1.0b1.tar.gz (189.9 kB view details)

Uploaded Source

Built Distribution

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

kashdao_protocol_sdk-0.1.0b1-py3-none-any.whl (161.7 kB view details)

Uploaded Python 3

File details

Details for the file kashdao_protocol_sdk-0.1.0b1.tar.gz.

File metadata

  • Download URL: kashdao_protocol_sdk-0.1.0b1.tar.gz
  • Upload date:
  • Size: 189.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for kashdao_protocol_sdk-0.1.0b1.tar.gz
Algorithm Hash digest
SHA256 14ddad4cc2896a15ad20a5c2a723d04a1299e8dd8bfd5cc8a5a9d1e881a3e504
MD5 5db2aa6e29c518cf95be243c3a9dd70b
BLAKE2b-256 0efab20044697012ba4b7f39ce342ffb7b8f23c9b65cf3b009f1e66da45c5821

See more details on using hashes here.

File details

Details for the file kashdao_protocol_sdk-0.1.0b1-py3-none-any.whl.

File metadata

File hashes

Hashes for kashdao_protocol_sdk-0.1.0b1-py3-none-any.whl
Algorithm Hash digest
SHA256 f9f7da52b821e60153be54c3907cd1dc77da907aa2a5f7a61ae4e68969d52243
MD5 9792cc91ab4075d817e728f3b8c58e7d
BLAKE2b-256 bbf46ec947d736d2e337341f20e797d54bec2e25b1850d2d0b85797c660cc441

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