Python Async Wallet Control: Zero-Dependency SDK for AI Trading Bots

Python Async Wallet Control: Zero-Dependency SDK for AI Trading Bots

Python async wallet control for AI trading bots has never been simpler — and if you've been building agents in Python with LangChain, CrewAI, or any other framework, you've probably hit the same wall: your agent can reason, plan, and execute complex tasks, but the moment it needs to touch real money on a blockchain, you're stuck wiring up RPC clients, managing private keys, and hoping nothing breaks in production. This post shows you exactly how to solve that with WAIaaS's Python SDK.

The Problem: Your AI Agent Is Financially Illiterate

You've built a trading bot. It can read market data, analyze trends, and decide when to swap tokens. But actually executing that swap? That's a different story.

The typical path looks like this: manage a private key somewhere (securely? hopefully?), instantiate a Solana or EVM RPC client, build the transaction manually, sign it, broadcast it, poll for confirmation, and handle all the edge cases that come with on-chain execution. Now multiply that by every chain your agent needs to support. And then ask yourself — should your agent really be holding raw private keys at all?

The answer is no. Your agent should be able to say "send 0.1 SOL to this address" and have something else handle the keys, the signing, the policy guardrails, and the confirmation. That's what WAIaaS is for.

What WAIaaS Actually Does

WAIaaS is an open-source, self-hosted Wallet-as-a-Service daemon. You run it locally or on your server. It holds the keys. Your AI agent talks to it over HTTP using a session token — a scoped, time-limited credential that lets the agent transact without ever seeing the private key.

The architecture is straightforward:

There's a Python SDK (waiaas) that wraps all of this in a clean async interface with zero external dependencies. If you're building async Python agents — which most modern frameworks encourage — it fits in naturally.

Installing the SDK

pip install waiaas

That's it. No web3, no solana-py, no httpx required separately. The SDK has zero external dependencies.

The Async Client Pattern

The Python SDK uses an async context manager, which plays well with any async Python framework:

from waiaas import WAIaaSClient

async with WAIaaSClient("http://localhost:3100", "wai_sess_xxx") as client:
    balance = await client.get_balance()
    print(balance.balance, balance.symbol)

The async with pattern ensures connections are cleaned up properly — important for long-running agent processes that open and close wallet sessions repeatedly.

Building a Simple Trading Bot

Here's a more complete example of what a Python trading agent might look like. The agent checks its balance, decides whether it has enough to trade, and sends a transaction:

from waiaas import WAIaaSClient
import asyncio
import os

async def run_trading_agent():
    session_token = os.environ["WAIAAS_SESSION_TOKEN"]
    
    async with WAIaaSClient("http://localhost:3100", session_token) as client:
        # Step 1: Check what we're working with
        balance = await client.get_balance()
        print(f"Balance: {balance.balance} {balance.symbol}")
        
        # Step 2: Your agent's logic decides what to do
        # (this is where LangChain/CrewAI/your LLM call goes)
        # For this example, we'll just demonstrate the wallet call
        
        # Step 3: Execute the transfer
        result = await client.send_token(
            to="recipient-address",
            amount="0.001"
        )
        print(f"Transaction submitted: {result.id} (status: {result.status})")
        
        # Step 4: Wait for confirmation
        timeout = 60
        elapsed = 0
        while elapsed < timeout:
            tx = await client.get_transaction(result.id)
            if tx.status == "COMPLETED":
                print(f"Confirmed! Hash: {tx.tx_hash}")
                break
            if tx.status == "FAILED":
                print(f"Failed: {tx.error}")
                break
            await asyncio.sleep(1)
            elapsed += 1

asyncio.run(run_trading_agent())

This is the complete loop: check balance, submit transaction, confirm. No key management. No RPC configuration. No manual transaction serialization.

Setting Up WAIaaS in 5 Minutes

Before your Python agent can do anything, you need the daemon running. The fastest path:

Step 1: Install the CLI and start the daemon

npm install -g @waiaas/cli
waiaas init --auto-provision   # Generates random master password → recovery.key
waiaas start                   # No password prompt

Step 2: Create a wallet and session

waiaas quickset   # Creates wallets + sessions automatically

Or manually via the REST API:

# Create a wallet
curl -X POST http://127.0.0.1:3100/v1/wallets \
  -H "Content-Type: application/json" \
  -H "X-Master-Password: my-secret-password" \
  -d '{"name": "trading-wallet", "chain": "solana", "environment": "mainnet"}'

# Create a session token for your agent
curl -X POST http://127.0.0.1:3100/v1/sessions \
  -H "Content-Type: application/json" \
  -H "X-Master-Password: my-secret-password" \
  -d '{"walletId": "<wallet-uuid>"}'

Step 3: Set your session token as an environment variable

export WAIAAS_SESSION_TOKEN="wai_sess_eyJhbGciOiJIUzI1NiJ9..."

Step 4: Set spending policies before your agent goes live

This is the step most people skip and then regret. WAIaaS has a policy engine with 21 policy types. At minimum, set a spending limit:

curl -X POST http://127.0.0.1:3100/v1/policies \
  -H "Content-Type: application/json" \
  -H "X-Master-Password: my-secret-password" \
  -d '{
    "walletId": "<wallet-uuid>",
    "type": "SPENDING_LIMIT",
    "rules": {
      "instant_max_usd": 100,
      "notify_max_usd": 500,
      "delay_max_usd": 2000,
      "delay_seconds": 900,
      "daily_limit_usd": 5000
    }
  }'

This creates a 4-tier security model: transactions under $100 execute instantly, $100–$500 execute with a notification, $500–$2000 execute after a 15-minute delay (giving you time to cancel), and anything above $2000 requires your explicit approval.

Step 5: Run your Python agent

python your_trading_bot.py

Why Policies Matter for AI Agents

If you're new to crypto infrastructure, this is worth slowing down on. An AI agent making financial decisions is a different risk profile from a human clicking "confirm." Agents can have bugs. LLMs can hallucinate parameters. External data sources can be manipulated.

WAIaaS enforces policies at the daemon level — below your agent code. Even if your agent tries to send $50,000 in a single transaction because of a buggy prompt, the policy engine blocks it. The agent doesn't have the ability to override policies; only the master password holder (you) can modify them.

The policy engine uses a default-deny approach for token and contract access: if you haven't explicitly added a token to the ALLOWED_TOKENS policy, the agent can't send it. Same for contract interactions via CONTRACT_WHITELIST. Your agent operates inside the fence you build.

The 4 security tiers in practice:

Handling Errors in Your Agent

The SDK raises WAIaaSError with structured error codes. Your agent should handle these gracefully rather than crashing:

from waiaas import WAIaaSClient, WAIaaSError

async def safe_send(client, to: str, amount: str):
    try:
        return await client.send_token(to=to, amount=amount)
    except WAIaaSError as e:
        # Structured error codes your agent can act on
        # Examples: INSUFFICIENT_BALANCE, POLICY_DENIED, TOKEN_EXPIRED
        print(f"Wallet error [{e.code}]: {e.message}")
        
        if e.code == "POLICY_DENIED":
            # Agent can log this and wait for human review
            print("Transaction blocked by policy — flagging for review")
        elif e.code == "INSUFFICIENT_BALANCE":
            # Agent knows to stop and request a top-up
            print("Not enough funds — pausing agent execution")
        
        return None

The error codes are consistent and machine-readable. Your agent can branch on POLICY_DENIED vs INSUFFICIENT_BALANCE vs TOKEN_EXPIRED without parsing error message strings.

What Your Agent Can Do Beyond Simple Transfers

The Python SDK covers the basics, but WAIaaS also exposes 15 DeFi protocol integrations and 45 MCP tools for agents that need to do more than just send tokens. If you're building a bot that needs to swap, stake, lend, or trade perpetuals, those protocols are available through the REST API's /v1/actions/ endpoints — the same ones the TypeScript SDK's executeAction method wraps.

For example, a Solana DeFi bot could call Jupiter swap directly:

curl -X POST http://127.0.0.1:3100/v1/actions/jupiter-swap/swap \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer wai_sess_<token>" \
  -d '{
    "inputMint": "So11111111111111111111111111111111111111112",
    "outputMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
    "amount": "1000000000"
  }'

Your Python agent can call this endpoint directly using aiohttp or any HTTP client, authenticated with the same session token.

Testing Before You Send Real Money

WAIaaS has a dry-run mode for simulating transactions before execution. Add "dryRun": true to your transaction payload and you get back what would happen — policy evaluation result, estimated fees, expected outcome — without anything hitting the chain.

This is useful during agent development: run your agent in dry-run mode against mainnet data to validate its decision-making before you fund the wallet.

curl -X POST http://127.0.0.1:3100/v1/transactions/send \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer wai_sess_<token>" \
  -d '{
    "type": "TRANSFER",
    "to": "recipient-address",
    "amount": "0.1",
    "dryRun": true
  }'

Running in Docker for Production

When you're ready to move past local development, the Docker setup is minimal:

git clone https://github.com/minhoyoo-iotrust/WAIaaS.git
cd WAIaaS
docker compose up -d

The Docker image (ghcr.io/minhoyoo-iotrust/waiaas:latest) includes healthchecks, runs as a non-root user (UID 1001), and supports Docker Secrets for production credential management. Your Python agent connects to it the same way — it just happens to be in a container instead of running directly on your machine.

The Mental Model

Here's the clearest way to think about this setup:

The session token is what connects them. It's scoped to a specific wallet, can have its own TTL and renewal limits, and can be revoked at any time without touching the underlying wallet or keys.

What's Next

If you've been building Python AI agents and avoiding blockchain integration because of the key management complexity, this is the path that removes that blocker. The zero-dependency SDK means you're not adding a web of crypto libraries to your agent's environment — just one clean async interface.

Start by running the daemon locally, funding a wallet with a small amount to test with, setting a conservative spending limit policy, and connecting your existing agent to the session token. The whole setup takes less time than configuring most LLM API clients.