paybot-sdk (Python port)
Python port of paybot-sdk. Mirror of the TypeScript SDK in ../../src/.
Status: runtime (0.1.0). Type surface, network config, HTTP transport, all client REST methods, EIP-3009 signing (
PayBotClient.pay()real-mode path), and webhook signature verification are implemented and tested. The signed payload and the webhook signature are byte-for-byte compatible with the TS SDK.
Install
pip install paybot-sdk
Or with the signing extras (required for pay() in real mode):
pip install paybot-sdk[signing]
Quick start (mock mode)
import asyncio
from paybot_sdk import PayBotClient, PayBotConfig, PaymentRequest
async def main():
client = PayBotClient(PayBotConfig(
api_key="pb_test_...",
bot_id="my-bot",
))
await client.register()
balance = await client.balance()
print(balance)
asyncio.run(main())
What's implemented
| File | Mirror of TS | Status |
|---|---|---|
paybot_sdk/types.py |
src/types.ts |
✅ Full type surface as @dataclass |
paybot_sdk/networks.py |
src/networks.ts |
✅ Full (chain IDs, USDC addresses, EIP-712 domains, EIP-3009 types) |
paybot_sdk/errors.py |
src/errors.ts |
✅ Full (PayBotApiError, get_error_message) |
paybot_sdk/crypto.py |
src/crypto.ts |
✅ Full (generate_eip3009_nonce via secrets.token_hex) |
paybot_sdk/client.py |
src/client.ts |
✅ Full — all REST methods + real-mode EIP-3009 signing in _sign_payload() |
paybot_sdk/webhook.py |
src/webhook.ts |
✅ Full (verify_webhook_signature, HMAC-SHA256, replay guard) |
paybot_sdk/__init__.py |
src/index.ts |
✅ Full exports |
paybot_sdk/middleware.py |
src/middleware.ts |
❌ Not yet ported |
paybot_sdk/x402_handler.py |
src/x402-handler.ts |
❌ Not yet ported |
Working today:
register(), balance(), history(), set_limits(), health(),
commission_summary(), commission_ledger(), create_api_key(),
list_api_keys(), revoke_api_key(), real-mode pay() (EIP-3009 signing),
and verify_webhook_signature(). Mock mode (no wallet_private_key) and real
mode both mirror the TS SDK wire contract.
Not yet ported:
middleware.pyx402_handler.py
Webhook verification
from paybot_sdk import verify_webhook_signature
ok = verify_webhook_signature(
payload=request_body, # str or bytes — the raw body
signature=headers["Paybot-Signature"], # "t=<unix_ts>,v1=<hex>"
secret="whsec_...",
tolerance=300, # replay window in seconds
)
The signing string is f"{t}.{payload}" and the header format is
t=<unix_ts>,v1=<hmac_sha256_hex>, identical to the TS
verifyWebhookSignature, so a server-signed webhook verifies in either runtime.
Notes
- Snake-case naming. TS uses
botId,walletPrivateKey. Python convention isbot_id,wallet_private_key. Wire format on the HTTP boundary is still camelCase (matches the TS server contract). Worth confirming this is the right boundary placement. PayBotConfigas dataclass vs. kwargs. CurrentlyPayBotConfigis a dataclass that gets passed in. Could also exposePayBotClient(api_key=..., bot_id=...)directly. Open to either; let me know which matches the SDK's intended ergonomics.- Async-first vs. sync wrapper. Right now everything is
async def. The TS SDK is also async-first (promise-based). If the consumer use cases include sync agents (LangChain old-style), a thinpaybot_sdk.syncwrapper is easy to add. Worth deciding now so the public API doesn't drift. _to_base_units. String-based conversion to avoid float drift. Matches the TS path; worth verifying no precision corner cases I missed.
Test plan
cd packages/python
pip install -e ".[signing,test]"
pytest
The test suite (in tests/) covers:
- Type surface (every dataclass constructable from valid inputs)
PayBotClient.__init__validation (api_key required, bot_id required, facilitator_url URL, wallet_private_key 0x-prefix)_to_base_unitscorner cases (zero, no decimal, exact decimal, more decimals than scale)generate_eip3009_nonceshape (0x-prefixed, 66 chars)NETWORKSparity withsrc/networks.ts(chain IDs, USDC addresses)- EIP-3009 signing (
test_signing.py): TS wire shape, signer-address recovery round-trip, unsupported-network + missing-key errors, deterministic-given-nonce structure - Real-mode
pay()verify→settle flow (respx-mocked HTTP) - Webhook verification (
test_webhook.py): valid/tampered/expired/future/malformed-header cases + thef"{t}.{payload}"cross-language signing contract
Release files for paybot-sdk 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| paybot_sdk-0.2.0.tar.gz | 73.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| paybot_sdk-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 125.5 kB
Release files / paybot_sdk-0.2.0.tar.gz
| Download URL | paybot_sdk-0.2.0.tar.gz |
|---|---|
| Size | 73.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2d37101b6679c1c360e0879e7409e709ccd8bcc2f1ddea4d9d76f8fb53a0d47f
|
|
BLAKE2b-256 checksum How to use checksums |
45a639564030dc0fc71c359519beae0c05c7f3d61b32819b97cfeaae59519181
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.0
|
Release files / paybot_sdk-0.2.0-py3-none-any.whl
| Download URL | paybot_sdk-0.2.0-py3-none-any.whl |
|---|---|
| Size | 52.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ef051b7b774dd5ecb767302b6d66dc96d865e571c3e43d9ff2955c37e4412fa9
|
|
BLAKE2b-256 checksum How to use checksums |
985af3f9eff2528c04ebd1504be56731a52cbd772157f894d4fc8bb104d9e764
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.0
|