Skip to main content

Typed Python SDK for the TronDealer API

Project description

TronDealer Python SDK

CI PyPI Python Versions License Code style: ruff

Typed Python SDK for the TronDealer API, built for backend integrations that assign deposit wallets, reconcile balances and transactions, and verify HMAC-signed webhooks.

The SDK follows the official integration guide as the primary source for the payment flow.

Installation

pip install trondealer

For local development:

pip install -e ".[dev]"

This repository also supports uv, which is useful when your system Python is externally managed:

uv sync --extra dev

Configuration

Store your API key in an environment variable or secret manager:

export TRONDEALER_API_KEY="td_..."
import os

from trondealer import TronDealerClient

client = TronDealerClient(api_key=os.environ["TRONDEALER_API_KEY"])

Default configuration:

client = TronDealerClient(
    api_key=os.environ["TRONDEALER_API_KEY"],
    base_url="https://www.trondealer.com/api/v2",
    timeout=10.0,
    max_retries=2,
)

Public Registration

Public registration does not use normal API-key authentication. It posts to /clients/register-public, the canonical endpoint documented by the integration guide.

from trondealer import TronDealerClient

client = TronDealerClient()
registration = client.register_client_public(
    name="My Shop",
    webhook_url="https://example.com/webhooks/trondealer",
    webhook_secret="a-long-random-secret",
    min_confirmations=15,
    sweep_wallet="0xABC...123",
    payout_method="wallet",
    turnstile_token="...",
)

api_key = registration.client.api_key

Advanced users can override the registration path if TronDealer changes the canonical endpoint:

client = TronDealerClient(registration_endpoint="/clients/register-public")

Assign A Wallet

Use one label per order or customer. TronDealer documents label as the user-side idempotency key.

import os

from trondealer import TronDealerClient

client = TronDealerClient(api_key=os.environ["TRONDEALER_API_KEY"])

wallet = client.assign_wallet(label="order-A-1024")
print(wallet.address)

Check A Balance

balance = client.get_wallet_balance(address="0xABC...123")
print(balance.balances)

The integration guide shows balances grouped by network. The embedded OpenAPI schema currently shows a flatter balance map. The SDK accepts both shapes.

List Transactions

transactions = client.list_wallet_transactions(
    address="0xABC...123",
    status="confirmed",
    limit=20,
    offset=0,
)

for tx in transactions.transactions:
    print(tx.tx_hash, tx.amount, tx.status)

Supported transaction statuses:

  • detected
  • confirmed
  • notified
  • swept

Verify Webhooks

TronDealer sends HMAC-SHA256 signatures in the X-Signature-256 header when a webhook secret is configured. Always verify the signature against the raw request body before parsing JSON.

from trondealer import parse_webhook_event, verify_webhook_signature

if verify_webhook_signature(raw_body, signature, webhook_secret):
    event = parse_webhook_event(raw_body)

The SDK accepts both documented signature formats: raw hex and sha256=<hex>.

FastAPI

import os

from fastapi import FastAPI, Header, HTTPException, Request

from trondealer import parse_webhook_event, verify_webhook_signature

app = FastAPI()


@app.post("/webhooks/trondealer")
async def trondealer_webhook(
    request: Request,
    x_signature_256: str | None = Header(default=None),
) -> dict[str, str]:
    raw_body = await request.body()
    secret = os.environ["TRONDEALER_WEBHOOK_SECRET"]

    if not x_signature_256 or not verify_webhook_signature(raw_body, x_signature_256, secret):
        raise HTTPException(status_code=401, detail="invalid signature")

    event = parse_webhook_event(raw_body)
    return {"status": "ok"}

Flask

import os

from flask import Flask, abort, request

from trondealer import parse_webhook_event, verify_webhook_signature

app = Flask(__name__)


@app.post("/webhooks/trondealer")
def trondealer_webhook() -> tuple[str, int]:
    raw_body = request.get_data(cache=False)
    signature = request.headers.get("X-Signature-256")
    secret = os.environ["TRONDEALER_WEBHOOK_SECRET"]

    if not signature or not verify_webhook_signature(raw_body, signature, secret):
        abort(401)

    event = parse_webhook_event(raw_body)
    return "ok", 200

Recommended Payment Flow

  1. Create one wallet per order or customer using label.
  2. Show the returned address to the user.
  3. Wait for the confirmed or notified webhook.
  4. Store tx_hash + log_index as a unique key to prevent double crediting.
  5. Do not mark an order as paid when the transaction is only in detected status.

Security Warnings

  • Never expose the x-api-key in frontend or mobile apps.
  • Store api_key and webhook_secret in environment variables or a secret manager.
  • Always verify the webhook HMAC signature.
  • Persist the raw body and signature for audit/debugging purposes.
  • Do not print API keys, webhook secrets, or full signed webhook payloads in logs.

Documentation Discrepancies

The official integration guide documents public registration as:

POST /api/v2/clients/register-public
Auth: none, with Turnstile token

The API docs/OpenAPI surface may list the same public operation as:

POST /api/v2/clients/register-open

This SDK uses /clients/register-public as canonical because the integration guide documents the complete registration flow, request body, auth behavior, and cURL example for that endpoint. The SDK does not silently switch to /clients/register-open. If needed, pass registration_endpoint="/clients/register-open" explicitly.

TODO before stable v1.0: verify /clients/register-public directly against the live API or with TronDealer maintainers.

Other known discrepancies:

  • The guide shows per-network balance responses; embedded OpenAPI shows a flatter balance object.
  • The guide shows raw hex webhook signatures; embedded OpenAPI describes sha256=<hex>.
  • The guide says EVM wallet assignment returns an existing wallet for the same label; embedded OpenAPI only documents 201 for EVM assignment.

Development

The Makefile runs tools through uv run --extra dev, so commands use the project development environment instead of depending on packages installed in your global Python.

make help
make test
make test:coverage
make lint
make format
make format:check

Equivalent direct commands after installing development dependencies:

pip install -e ".[dev]"
ruff check .
ruff format --check .
pytest

If your Python installation is externally managed and pip install -e ".[dev]" is blocked, use:

uv sync --extra dev
uv run pytest
uv run ruff check .
uv run ruff format --check .

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

trondealer-0.1.1.tar.gz (87.5 kB view details)

Uploaded Source

Built Distribution

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

trondealer-0.1.1-py3-none-any.whl (15.0 kB view details)

Uploaded Python 3

File details

Details for the file trondealer-0.1.1.tar.gz.

File metadata

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

File hashes

Hashes for trondealer-0.1.1.tar.gz
Algorithm Hash digest
SHA256 7784a2abbbde0b79f212b0bf7b78e0726ccd69c1f8a6af7ff1d10502160a7836
MD5 55cf78890eaa3d0e5aa7c236d1e53960
BLAKE2b-256 da5ac6816df0975e7a24e0c4f30f5b425e0d441d0e492a70aa6fd22bd6ebc54f

See more details on using hashes here.

Provenance

The following attestation bundles were made for trondealer-0.1.1.tar.gz:

Publisher: publish.yml on ragnarok22/trondealer

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

File details

Details for the file trondealer-0.1.1-py3-none-any.whl.

File metadata

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

File hashes

Hashes for trondealer-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 cdbb70c2adace5f644db68e9193a578c351088a7ae1061c1671ee6d3ae549904
MD5 906911b1e15847875e75b4a37ed6d8ef
BLAKE2b-256 aeccb42e096248ff992a5a10dda0a9d5e3ae0e8931f2094a4c9f17423b765e78

See more details on using hashes here.

Provenance

The following attestation bundles were made for trondealer-0.1.1-py3-none-any.whl:

Publisher: publish.yml on ragnarok22/trondealer

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