Atomic USDx wallet โ Redis-backed balance engine, NowPayments deposits, ITC PSBT withdrawals, OTC rate engine
Project description
๐ช interchained-usdx
Atomic, Redis-backed USDx wallet engine for the Interchained ecosystem.
Four independent modules. Zero application-level locks. Battle-tested in production.
โก The Lore
In the Interchained ecosystem, USDx is the stable settlement layer โ minted from real crypto deposits, redeemable for native ITC tokens at a provably-fair OTC rate. It powers creator earnings, node operator rewards, game prize pools, and marketplace settlements.
Every balance mutation โ credit, debit, transfer, freeze โ executes as a single Redis Lua script. Atomically. No application-level locks. No race conditions. No double-spends. Just raw, nanosecond-precision financial logic running in the kernel of a battle-hardened in-memory database.
This is the engine behind $50k+ in transaction volume and 275+ live users on the Interchained network. Now open-sourced under GPLv3 for any project that demands the same standard.
๐ฆ Install
pip install interchained-usdx
๐บ๏ธ What's inside
| Module | Class | What it does |
|---|---|---|
usdx.wallet |
USDxWallet |
Atomic Redis balance engine โ credit / debit / transfer / freeze |
usdx.payments |
NowPaymentsService |
Multi-chain crypto deposit handler via NowPayments (22 coins) |
usdx.psbt |
PSBTBuilder + ITCRPCClient |
ITC blockchain PSBT payout builder, wallet-funded with auto fee estimation |
usdx.otc |
OTCRateEngine |
Dynamic ITC โ USDx exchange rate driven by on-chain reserve / circulating supply |
All four modules are independently usable โ pull only what you need.
๐๏ธ Architecture
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Your Application โ
โ โ
โ from usdx import USDxWallet, NowPaymentsService, โ
โ PSBTBuilder, OTCRateEngine โ
โโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโ
โ โ โ
โผ โผ โผ
โโโโโโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ
โ USDxWallet โ โNowPaymts โ โ PSBTBuilder โ
โ (Lua core) โ โ (HTTP) โ โ (ITC RPC) โ
โโโโโโโโฌโโโโโโโโ โโโโโโฌโโโโโโ โโโโโโโโฌโโโโโโโโโโโโ
โ โ โ
โโโโโโโโผโโโโโโโโโโโโโโโผโโโโโโโ โ
โ Redis 6+ โ โ
โ (atomic Lua scripts run โ โ
โ inside the server, โ โ
โ no app-level locks) โ โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ ITC Node RPC
(PSBT payouts)
๐ Quick start
1 โ Balance engine
import asyncio
import redis.asyncio as aioredis
from usdx import USDxWallet, InsufficientBalance, AccountFrozen
async def main():
r = aioredis.from_url("redis://localhost:6379/0")
wallet = USDxWallet(r)
# โโ Credit โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
tx = await wallet.credit("alice", 20.74, description="Welcome bonus", tx_type="bonus")
print(tx.balance_after) # 20.74
# Premium creators get a 1.5ร earnings multiplier
tx = await wallet.credit("alice", 10.00, multiplier=1.5, description="Article view")
print(tx.amount) # 15.0 โ applied inside the Lua script
# โโ Debit โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
try:
tx = await wallet.debit("alice", 3.99, description="Monthly subscription")
except InsufficientBalance:
print("Not enough funds")
except AccountFrozen:
print("Account is locked (fraud protection)")
# โโ Atomic transfer (single Lua round-trip) โโโโโโโโโโโโโโโ
debit_tx, credit_tx = await wallet.transfer("alice", "bob", 5.00, description="Tip")
# โโ Account snapshot โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
info = await wallet.get_info("alice")
print(info.balance, info.total_credited, info.is_frozen)
# โโ Full transaction history โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
history = await wallet.get_history("alice", limit=10)
for tx in history:
print(f"{tx.direction:6s} {tx.amount:8.2f} {tx.description}")
# โโ Fraud protection โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
await wallet.freeze("alice") # blocks all outgoing transfers
await wallet.unfreeze("alice") # restores full access
asyncio.run(main())
2 โ Custom Redis namespace
# Isolate keys per application / environment
wallet = USDxWallet(r, key_prefix="myapp:balance:", tx_prefix="myapp:tx:")
3 โ NowPayments deposits
Accept 22 cryptocurrencies โ BTC, ETH, USDT, TRX, BNB, XRP, DOGE, LTC, AVAX, and more.
from usdx import NowPaymentsService, USDxWallet
wallet = USDxWallet(redis_client)
async def on_confirmed(username: str, amount: float, currency: str, payment_id: str) -> bool:
"""Called automatically when a crypto payment reaches 'finished' status."""
await wallet.credit(
username, amount,
description=f"Deposit via {currency.upper()}",
tx_type="deposit",
metadata={"payment_id": payment_id, "currency": currency},
)
return True # return False to mark as failed without consuming idempotency token
svc = NowPaymentsService(
redis_client,
api_key="YOUR_NOWPAYMENTS_API_KEY",
on_confirmed=on_confirmed,
success_url="https://yourapp.com/wallet?status=success",
cancel_url="https://yourapp.com/wallet?status=cancelled",
namespace="myapp", # Redis key namespace โ keeps keys isolated
order_prefix="myapp", # Prefix in NowPayments order_id field
)
# Create a deposit invoice โ redirect the user to payment_url
invoice = await svc.create_deposit_invoice("alice", 25.00, "usdttrc20")
print(invoice["payment_url"]) # โ https://nowpayments.io/payment/...
# Check a payment's current status
status = await svc.check_payment_status(payment_id)
print(status["status"]) # "waiting" | "confirming" | "finished" | "failed"
# Handle an IPN webhook (wire this into your web framework)
await svc.handle_ipn_callback(ipn_payload)
# Manually trigger processing (idempotent โ safe to call multiple times)
result = await svc.process_completed_payment(payment_id)
4 โ PSBT withdrawals (ITC blockchain)
Build, sign, and broadcast multi-output ITC payouts โ wallet-funded, with automatic fee estimation.
from usdx import ITCRPCClient, PSBTBuilder, PSBTError
rpc = ITCRPCClient(
rpc_url="http://127.0.0.1:8332",
wallet_name="hot-wallet",
username="rpcuser",
password="rpcpass",
fallback_fee=10.0, # sat/byte fallback if estimatesmartfee fails
)
builder = PSBTBuilder(rpc, conf_target=6) # target 6-block confirmation
# Build a batch payout โ as many recipients as you need
payouts = [
{"address": "itc1qrecipient1...", "amount": 12.50},
{"address": "itc1qrecipient2...", "amount": 7.25},
{"address": "itc1qrecipient3...", "amount": 42.00},
]
tx_hex, info = await builder.create_payout(payouts)
print(f"Total payout : {info['total_payout']:.4f} ITC")
print(f"Network fee : {info['fee']:.4f} ITC")
print(f"Est. size : {info['estimated_size']} bytes")
txid = await builder.broadcast(tx_hex)
print(f"Broadcast txid: {txid}")
5 โ OTC rate engine
Drive a dynamic ITC โ USDx exchange rate from on-chain reserve and circulating supply.
from usdx import OTCRateEngine
engine = OTCRateEngine(
redis_client,
default_itc_reserve=10_000.0, # initial ITC in the treasury reserve
default_usdx_supply=1_000.0, # initial USDx in circulation
)
await engine.initialize() # seeds defaults on first run, no-op after
# Read the current rate
rate = await engine.get_rate() # ITC per 1 USDx (e.g. 10.5)
# Update the reserve after a user deposits crypto
await engine.increment_supply(25.0, source="alice_deposit")
await engine.decrement_itc_reserve(12.5, source="alice_withdrawal")
# Full treasury snapshot
stats = await engine.get_stats()
# {
# "itc_reserve": 9987.5,
# "usdx_supply": 1025.0,
# "current_rate": 9.74,
# "paused": False,
# "last_updated": "2026-06-12T14:30:00Z"
# }
๐ Redis key layout
Every key prefix is configurable at construction time.
usdx:balance:{user_id} โ HASH balance / total_credited / total_debited / is_frozen / created_at / last_updated
usdx:tx:{user_id} โ ZSET JSON transaction records, score = UTC timestamp (ms)
usdx:otc:itc_reserve โ STRING ITC reserve amount
usdx:otc:usdx_supply โ STRING circulating USDx supply
usdx:otc:rate_history โ ZSET historical rate snapshots
usdx:payment:invoice:{id} โ HASH NowPayments invoice state
usdx:payment:user:{u}:invoices โ ZSET per-user invoice index
โ๏ธ Atomicity guarantee
Every state-changing wallet operation is a single EVAL call โ no multi-exec, no application-level locks, no read-modify-write round trips.
credit(user, 10.00)
โโโบ EVAL _LUA_CREDIT โโโบ Redis executes atomically:
HINCRBYFLOAT balance
HINCRBYFLOAT total_credited
HSET last_updated
โโโ returns [new_balance]
If Redis crashes mid-operation: the script either ran fully or not at all.
If two processes call debit simultaneously: one wins, the other gets INSUFFICIENT_BALANCE.
No coordination required between workers.
๐งช Tests
pip install -e ".[dev]" # installs pytest, fakeredis, lupa, ruff, mypy
pytest # 24 tests โ all green
ruff check usdx/ # linting
mypy usdx/ # strict type-checking
Note:
lupa(Lua runtime) is required forfakeredisto executeEVALin tests. It is listed in[dev]extras and installed automatically.
๐ Examples
See examples/ for runnable code:
| Example | Description |
|---|---|
quickstart.py |
End-to-end async script covering every method |
fastapi_wallet_app/ |
Full REST API skeleton โ drop-in FastAPI service with Pydantic models, lifespan Redis, and Swagger UI |
๐ Companion package
The TypeScript HTTP client โ @interchained/usdx โ pairs with this package:
import { USDxClient } from "@interchained/usdx";
const client = new USDxClient({ baseUrl: "https://api.yourapp.com" });
const balance = await client.getBalance("alice");
Zero production dependencies. Works in Node.js 18+, browsers, Deno, and Bun.
๐ค Contributing
- Fork โ branch โ make your changes
pip install -e ".[dev]"and runpytestโ all 24 must stay greenruff check usdx/ && mypy usdx/โ zero warnings- Open a PR with a clear description of what changed and why
Please report security issues via private message, not public issues.
๐ License
GNU General Public License v3.0 or later. See LICENSE for the full text.
interchained-usdx Copyright (C) 2024 Interchained
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under the terms of the GPLv3.
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 interchained_usdx-0.1.0.tar.gz.
File metadata
- Download URL: interchained_usdx-0.1.0.tar.gz
- Upload date:
- Size: 35.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
89665e602f57503e0561c0c154e766e491f240703067aa26dccfb3b0b3a5846a
|
|
| MD5 |
3cc2a819566ea43ae53fa7d1b7f37956
|
|
| BLAKE2b-256 |
a000ce1a46ccd837375ddc5df9977e26bbdb7217b6dbef9f26371eb2b0550cc5
|
File details
Details for the file interchained_usdx-0.1.0-py3-none-any.whl.
File metadata
- Download URL: interchained_usdx-0.1.0-py3-none-any.whl
- Upload date:
- Size: 33.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
def28a908a0310c6685ecfc0e4afb10b8bcd32a8b5eae2a4b7a32b63293e2134
|
|
| MD5 |
f968ee1bc5dbce33ede168aae3258f3d
|
|
| BLAKE2b-256 |
a4fbef8e97b2e31d836bb76bd6dc28ad906d28b916846475ddca6b88c81dd226
|