Atomic, Redis-backed USDx wallet engine for the Interchained ecosystem.
Four independent modules. Zero application-level locks. Battle-tested in production.
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.
pip install interchained-usdx| 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.
┌─────────────────────────────────────────────────────────────┐
│ 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)
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())# Isolate keys per application / environment
wallet = USDxWallet(r, key_prefix="myapp:balance:", tx_prefix="myapp:tx:")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)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}")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"
# }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
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.
pip install -e ".[dev]" # installs pytest, fakeredis, lupa, ruff, mypy
pytest # 24 tests — all green
ruff check usdx/ # linting
mypy usdx/ # strict type-checkingNote:
lupa(Lua runtime) is required forfakeredisto executeEVALin tests. It is listed in[dev]extras and installed automatically.
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 |
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.
- 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.
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.