Typed Python SDK for the TronDealer API
Project description
TronDealer Python SDK
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:
detectedconfirmednotifiedswept
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
- Create one wallet per order or customer using
label. - Show the returned address to the user.
- Wait for the
confirmedornotifiedwebhook. - Store
tx_hash + log_indexas a unique key to prevent double crediting. - Do not mark an order as paid when the transaction is only in
detectedstatus.
Security Warnings
- Never expose the
x-api-keyin frontend or mobile apps. - Store
api_keyandwebhook_secretin 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 documents201for 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 .
Publishing To PyPI
Do not publish until endpoint behavior has been verified against the live API or with TronDealer maintainers.
Example publishing flow:
python -m build
twine check dist/*
twine upload dist/*
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file trondealer-0.1.0.tar.gz.
File metadata
- Download URL: trondealer-0.1.0.tar.gz
- Upload date:
- Size: 83.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9497288a4f9294a268befbacb27a5d0eacb4633fd06c831e18f222abe5650b1a
|
|
| MD5 |
c21acaabce0db0654afe54ece1ac86d0
|
|
| BLAKE2b-256 |
cb92842cac1b1e23e090f963de9adc4037e7dbfc5c5fea7d3b1ca2b8b0e338c8
|
Provenance
The following attestation bundles were made for trondealer-0.1.0.tar.gz:
Publisher:
publish.yml on ragnarok22/trondealer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
trondealer-0.1.0.tar.gz -
Subject digest:
9497288a4f9294a268befbacb27a5d0eacb4633fd06c831e18f222abe5650b1a - Sigstore transparency entry: 1465586967
- Sigstore integration time:
-
Permalink:
ragnarok22/trondealer@d97f3d9b2bf0d16f11937d7298bf9d1c513b0c10 -
Branch / Tag:
refs/tags/v0.0.1 - Owner: https://github.com/ragnarok22
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d97f3d9b2bf0d16f11937d7298bf9d1c513b0c10 -
Trigger Event:
push
-
Statement type:
File details
Details for the file trondealer-0.1.0-py3-none-any.whl.
File metadata
- Download URL: trondealer-0.1.0-py3-none-any.whl
- Upload date:
- Size: 14.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d00b600fa658b788f00c5d24222572026ef082f934570da9751b185b05301032
|
|
| MD5 |
706ec649b39e9b56145602526b4ebf10
|
|
| BLAKE2b-256 |
ff7e071bcb816f68519c5e006fb4365eb15dccd4c3961610a18e1bf752215e93
|
Provenance
The following attestation bundles were made for trondealer-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on ragnarok22/trondealer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
trondealer-0.1.0-py3-none-any.whl -
Subject digest:
d00b600fa658b788f00c5d24222572026ef082f934570da9751b185b05301032 - Sigstore transparency entry: 1465587116
- Sigstore integration time:
-
Permalink:
ragnarok22/trondealer@d97f3d9b2bf0d16f11937d7298bf9d1c513b0c10 -
Branch / Tag:
refs/tags/v0.0.1 - Owner: https://github.com/ragnarok22
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d97f3d9b2bf0d16f11937d7298bf9d1c513b0c10 -
Trigger Event:
push
-
Statement type: