<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Wallet Guy</title>
    <description>The latest articles on DEV Community by Wallet Guy (@walletguy).</description>
    <link>https://dev.clauneck.workers.dev/walletguy</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3839576%2Fca8024e8-c8ac-4f6a-845c-e8ad44732a67.jpeg</url>
      <title>DEV Community: Wallet Guy</title>
      <link>https://dev.clauneck.workers.dev/walletguy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.clauneck.workers.dev/feed/walletguy"/>
    <language>en</language>
    <item>
      <title>Self-Documenting AI Agents: OpenAPI 3.0 Spec Generation for MCP Tools</title>
      <dc:creator>Wallet Guy</dc:creator>
      <pubDate>Wed, 24 Jun 2026 15:37:47 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/walletguy/self-documenting-ai-agents-openapi-30-spec-generation-for-mcp-tools-jld</link>
      <guid>https://dev.clauneck.workers.dev/walletguy/self-documenting-ai-agents-openapi-30-spec-generation-for-mcp-tools-jld</guid>
      <description>&lt;h1&gt;
  
  
  Self-Documenting AI Agents: OpenAPI 3.0 Spec Generation for MCP Tools
&lt;/h1&gt;

&lt;p&gt;MCP developers building onchain AI agents often hit the same wall: your Claude agent can reason brilliantly, but it has no idea what tools are actually available, what parameters they expect, or how to authenticate. WAIaaS solves this by combining 45 MCP tools with a live OpenAPI 3.0 spec — so your agent always has accurate, machine-readable documentation for every wallet, transaction, and DeFi action it can take.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Actually Matters
&lt;/h2&gt;

&lt;p&gt;When you wire an AI agent to onchain infrastructure, documentation isn't a nice-to-have — it's load-bearing. If your agent guesses at parameter names, misunderstands authentication requirements, or doesn't know which networks are supported, it makes mistakes with real money. The combination of MCP tooling and a live OpenAPI spec means two things: Claude gets structured tool definitions through the MCP protocol, and any HTTP client (including other agents, scripts, or dashboards you build) can discover the full API surface automatically. Both layers stay in sync because they're generated from the same codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  One Line in Your Config
&lt;/h2&gt;

&lt;p&gt;Let's start with the fastest path. Add this to your &lt;code&gt;claude_desktop_config.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"waiaas"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@waiaas/mcp"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_BASE_URL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://127.0.0.1:3100"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_SESSION_TOKEN"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"wai_sess_&amp;lt;your-token&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_DATA_DIR"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"~/.waiaas"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Restart Claude Desktop and your agent now has access to 45 MCP tools covering wallet management, token transfers, DeFi actions, NFT operations, and x402 HTTP payment — all authenticated, all policy-governed, all with typed parameters that Claude can introspect before calling them.&lt;/p&gt;

&lt;p&gt;The MCP server package is &lt;code&gt;@waiaas/mcp&lt;/code&gt; on npm, transport is stdio, and tools are served with full schema definitions so Claude understands input shapes without guessing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the 45 Tools Actually Cover
&lt;/h2&gt;

&lt;p&gt;The tool list isn't just send-token and check-balance. Here's the full scope across categories:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wallet &amp;amp; balance:&lt;/strong&gt; &lt;code&gt;get-wallet-info&lt;/code&gt;, &lt;code&gt;get-address&lt;/code&gt;, &lt;code&gt;get-balance&lt;/code&gt;, &lt;code&gt;get-assets&lt;/code&gt;, &lt;code&gt;get-nonce&lt;/code&gt;, &lt;code&gt;connect-info&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Transactions:&lt;/strong&gt; &lt;code&gt;send-token&lt;/code&gt;, &lt;code&gt;send-batch&lt;/code&gt;, &lt;code&gt;sign-transaction&lt;/code&gt;, &lt;code&gt;sign-message&lt;/code&gt;, &lt;code&gt;simulate-transaction&lt;/code&gt;, &lt;code&gt;get-transaction&lt;/code&gt;, &lt;code&gt;list-transactions&lt;/code&gt;, &lt;code&gt;list-incoming-transactions&lt;/code&gt;, &lt;code&gt;get-incoming-summary&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DeFi:&lt;/strong&gt; &lt;code&gt;action-provider&lt;/code&gt;, &lt;code&gt;get-defi-positions&lt;/code&gt;, &lt;code&gt;get-health-factor&lt;/code&gt;, &lt;code&gt;approve-token&lt;/code&gt;, &lt;code&gt;list-offchain-actions&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Account Abstraction:&lt;/strong&gt; &lt;code&gt;build-userop&lt;/code&gt;, &lt;code&gt;sign-userop&lt;/code&gt;, &lt;code&gt;encode-calldata&lt;/code&gt;, &lt;code&gt;call-contract&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NFT:&lt;/strong&gt; &lt;code&gt;get-nft-metadata&lt;/code&gt;, &lt;code&gt;list-nfts&lt;/code&gt;, &lt;code&gt;transfer-nft&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Protocols:&lt;/strong&gt; &lt;code&gt;hyperliquid&lt;/code&gt;, &lt;code&gt;polymarket&lt;/code&gt;, &lt;code&gt;resolve-asset&lt;/code&gt;, &lt;code&gt;get-tokens&lt;/code&gt;, &lt;code&gt;get-provider-status&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sessions &amp;amp; auth:&lt;/strong&gt; &lt;code&gt;list-sessions&lt;/code&gt;, &lt;code&gt;list-credentials&lt;/code&gt;, &lt;code&gt;get-policies&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ERC standards:&lt;/strong&gt; &lt;code&gt;erc8004-get-agent-info&lt;/code&gt;, &lt;code&gt;erc8004-get-reputation&lt;/code&gt;, &lt;code&gt;erc8004-get-validation-status&lt;/code&gt;, &lt;code&gt;erc8128-sign-request&lt;/code&gt;, &lt;code&gt;erc8128-verify-signature&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WalletConnect:&lt;/strong&gt; &lt;code&gt;wc-connect&lt;/code&gt;, &lt;code&gt;wc-disconnect&lt;/code&gt;, &lt;code&gt;wc-status&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Utility:&lt;/strong&gt; &lt;code&gt;get-rpc-proxy-url&lt;/code&gt;, &lt;code&gt;x402-fetch&lt;/code&gt;, &lt;code&gt;get-transaction&lt;/code&gt; (with full hash resolution)&lt;/p&gt;

&lt;p&gt;When Claude sees &lt;code&gt;simulate-transaction&lt;/code&gt; in the tool list, it knows it can dry-run before executing. When it sees &lt;code&gt;get-health-factor&lt;/code&gt;, it understands DeFi lending positions are trackable. The schema-first design means Claude reasons about what's possible before committing to an action.&lt;/p&gt;

&lt;h2&gt;
  
  
  The OpenAPI Layer: For Everything Else
&lt;/h2&gt;

&lt;p&gt;The MCP interface handles Claude. But you probably also have scripts, dashboards, or other agents that talk to WAIaaS over HTTP. That's where the OpenAPI 3.0 spec comes in.&lt;/p&gt;

&lt;p&gt;WAIaaS auto-generates a live OpenAPI spec at &lt;code&gt;/doc&lt;/code&gt; and serves an interactive Scalar API reference at &lt;code&gt;/reference&lt;/code&gt;. Both stay current with the actual implementation — 39 REST API route modules feeding a single spec.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Download the OpenAPI 3.0 spec&lt;/span&gt;
curl http://127.0.0.1:3100/doc &lt;span class="nt"&gt;-o&lt;/span&gt; openapi.json

&lt;span class="c"&gt;# View the interactive reference in your browser&lt;/span&gt;
open http://127.0.0.1:3100/reference
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The interactive UI at &lt;code&gt;/reference&lt;/code&gt; is useful during development: you can see every endpoint, its authentication requirement, request schema, and response shape without reading source code. When you're building a policy configuration or debugging a DeFi action response, this is significantly faster than grepping through documentation.&lt;/p&gt;

&lt;p&gt;The spec is also what you'd feed to another agent or code generator. If you're building a second AI agent that orchestrates WAIaaS over REST rather than MCP, point it at &lt;code&gt;/doc&lt;/code&gt; and it has a complete, accurate description of the API surface.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authentication Is Part of the Schema
&lt;/h2&gt;

&lt;p&gt;One thing that trips up developers building multi-agent systems: WAIaaS uses three distinct authentication methods, and the OpenAPI spec documents which endpoints require which.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# masterAuth — create wallets, manage sessions, set policies&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt;

&lt;span class="c"&gt;# sessionAuth — AI agent operations (transactions, balance, DeFi)&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer wai_sess_eyJhbGciOiJIUzI1NiJ9..."&lt;/span&gt;

&lt;span class="c"&gt;# ownerAuth — human approval for high-value transactions&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Owner-Signature: &amp;lt;ed25519-or-secp256k1-signature&amp;gt;"&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Owner-Message: &amp;lt;signed-message&amp;gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the MCP context, the session token you put in &lt;code&gt;WAIAAS_SESSION_TOKEN&lt;/code&gt; handles all agent-facing operations. The session was created by a human operator using masterAuth — the agent never sees the master password. This separation is intentional: the agent has a scoped credential with policy limits, not root access to the wallet system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up a Multi-Wallet MCP Configuration
&lt;/h2&gt;

&lt;p&gt;For more sophisticated setups — say, a trading agent and a separate Solana wallet agent — you can run multiple named MCP servers pointing at the same WAIaaS daemon:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"waiaas-trading"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@waiaas/mcp"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_BASE_URL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://127.0.0.1:3100"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_AGENT_ID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"019c47d6-51ef-7f43-a76b-d50e875d95f4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_AGENT_NAME"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"trading-agent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_DATA_DIR"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"~/.waiaas"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"waiaas-solana"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@waiaas/mcp"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_BASE_URL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://127.0.0.1:3100"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_AGENT_ID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"019c4cd2-86e8-758f-a61e-9c560307c788"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_AGENT_NAME"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"solana-wallet"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_DATA_DIR"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"~/.waiaas"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each MCP server instance has its own session token scoped to a specific wallet. Claude sees both as separate tool namespaces and can reason about which wallet to use for which operation — all documented through the MCP tool schemas.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Claude Can Actually Do After This
&lt;/h2&gt;

&lt;p&gt;Here's what the interaction looks like in practice once MCP is connected:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User: "Check my wallet balance"
→ Claude calls get_balance tool → returns balance

User: "Swap 0.1 SOL for USDC on Jupiter"
→ Claude calls execute_action tool with jupiter-swap provider

User: "Show my DeFi positions across all protocols"
→ Claude calls get_defi_positions tool → returns lending/staking positions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Jupiter swap call hits one of 15 integrated DeFi protocol providers — including Aave v3, Across, Drift, Hyperliquid, Jito staking, Jupiter swap, Kamino, Lido staking, LI.FI, Pendle, Polymarket, XRPL DEX, and 0x swap, among others. Claude doesn't need to know the protocol-specific parameters because the tool schema defines them.&lt;/p&gt;

&lt;p&gt;Before any transaction executes, the 7-stage pipeline processes it: validate → auth → policy → wait → execute → confirm. If a policy blocks it, Claude gets back a structured error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POLICY_DENIED"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Transaction denied by SPENDING_LIMIT policy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POLICY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"retryable"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That error code is something Claude can reason about — it knows the transaction was blocked by a spending limit, not a network error, and can explain that to the user or suggest alternatives.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Start: From Zero to MCP Tools in 5 Steps
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Install the CLI and initialize&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @waiaas/cli
waiaas init
waiaas start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: Create wallets and sessions in one command&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;waiaas quickset &lt;span class="nt"&gt;--mode&lt;/span&gt; mainnet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates wallets and MCP sessions. The output includes the MCP config JSON.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Register with Claude Desktop automatically&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;waiaas mcp setup &lt;span class="nt"&gt;--all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4: Verify the OpenAPI spec is live&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://127.0.0.1:3100/doc &lt;span class="nt"&gt;-o&lt;/span&gt; openapi.json
&lt;span class="c"&gt;# Then open http://127.0.0.1:3100/reference in your browser&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 5: Set a spending policy so the agent has safe limits&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/policies &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "walletId": "&amp;lt;wallet-uuid&amp;gt;",
    "type": "SPENDING_LIMIT",
    "rules": {
      "instant_max_usd": 100,
      "notify_max_usd": 500,
      "delay_max_usd": 2000,
      "delay_seconds": 900,
      "daily_limit_usd": 5000
    }
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart Claude Desktop and ask it to check your balance.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Self-Documenting Part
&lt;/h2&gt;

&lt;p&gt;The reason this system is "self-documenting" isn't marketing language — it's a practical property. The 45 MCP tools and the 39 REST API route modules both derive their schemas from the same source. When WAIaaS adds a new capability, the OpenAPI spec at &lt;code&gt;/doc&lt;/code&gt; updates automatically, the interactive reference at &lt;code&gt;/reference&lt;/code&gt; reflects it, and the MCP tool definitions that Claude receives are current.&lt;/p&gt;

&lt;p&gt;For developers building on top of WAIaaS — whether you're writing an agent orchestration layer, a monitoring dashboard, or a second AI system that talks to WAIaaS over HTTP — you always have an accurate map of the territory. You don't maintain separate documentation, you don't discover parameter mismatches at runtime, and you don't need to read source code to understand what's available.&lt;/p&gt;

&lt;p&gt;That's the core value proposition for MCP developers specifically: you get 45 typed, schema-defined tools that Claude can introspect, plus a live HTTP API that any other client can discover — all from a single self-hosted daemon you control.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;If you want to explore the policy engine in depth — setting spending limits, token whitelists, and DeFi-specific controls like maximum leverage — the 21 policy types give you fine-grained control over what your agent can and can't do autonomously. The Docker deployment path is also worth looking at if you're running this in a persistent server environment rather than locally.&lt;/p&gt;

&lt;p&gt;The full codebase, including the MCP package and all 15 DeFi protocol providers, is at &lt;a href="https://github.com/minhoyoo-iotrust/WAIaaS" rel="noopener noreferrer"&gt;https://github.com/minhoyoo-iotrust/WAIaaS&lt;/a&gt;. More documentation and the official site are at &lt;a href="https://waiaas.ai" rel="noopener noreferrer"&gt;https://waiaas.ai&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>api</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building the Financial Rails for Machine-to-Machine Commerce</title>
      <dc:creator>Wallet Guy</dc:creator>
      <pubDate>Wed, 24 Jun 2026 09:53:56 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/walletguy/building-the-financial-rails-for-machine-to-machine-commerce-4k3l</link>
      <guid>https://dev.clauneck.workers.dev/walletguy/building-the-financial-rails-for-machine-to-machine-commerce-4k3l</guid>
      <description>&lt;h1&gt;
  
  
  Building the Financial Rails for Machine-to-Machine Commerce
&lt;/h1&gt;

&lt;p&gt;AI agents will need to pay for compute, data, and API calls — and right now, almost nothing in the infrastructure stack is built to handle that. We talk endlessly about autonomous agents that book travel, execute trades, and negotiate contracts, but when the conversation turns to &lt;em&gt;how they pay&lt;/em&gt;, the answer is usually a hand-wave. Humans still hold the keys, approve every transaction, and act as financial intermediaries for systems that are supposed to operate independently. That's not autonomy. That's a chatbot with extra steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Missing Layer
&lt;/h2&gt;

&lt;p&gt;Think about what a truly autonomous AI agent needs to participate in economic activity. It needs to hold funds. It needs to authorize payments without waking a human up at 3 AM. It needs spending guardrails so it can't accidentally drain a treasury on a bad swap. It needs to handle multiple chains because the internet doesn't run on one blockchain. And it needs to do all of this without a centralized custodian that becomes a single point of failure — or control.&lt;/p&gt;

&lt;p&gt;None of the standard wallet tooling was designed for this. Browser extension wallets need a human to click "confirm." Custodial APIs introduce a trust assumption that defeats the purpose of autonomous operation. Raw key management libraries give you signing primitives but nothing resembling a policy engine or an approval workflow.&lt;/p&gt;

&lt;p&gt;The financial rails for machine-to-machine commerce aren't missing because the problem is unsolved. They're missing because the industry has been building for human users. Agents are a different actor class entirely, and they need infrastructure built specifically for them.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Agent-Native Wallet Infrastructure Looks Like
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://waiaas.ai" rel="noopener noreferrer"&gt;WAIaaS&lt;/a&gt; — Wallet-as-a-Service for AI agents — is an open-source, self-hosted daemon that exists specifically to close this gap. It's running today. You can deploy it in under five minutes with Docker. Here's what makes it different from gluing together a keystore and a REST API yourself.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Architecture: Three Auth Layers for Three Actor Classes
&lt;/h3&gt;

&lt;p&gt;The fundamental insight in WAIaaS's design is that &lt;em&gt;who&lt;/em&gt; is touching the wallet matters enormously. There are three distinct actors with three distinct trust levels:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The system administrator&lt;/strong&gt; sets up wallets, creates sessions, and defines policies. They authenticate with a master password hashed using Argon2id. They should almost never be involved in day-to-day operations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The AI agent&lt;/strong&gt; runs transactions, checks balances, executes DeFi actions. It authenticates with a session JWT (&lt;code&gt;wai_sess_...&lt;/code&gt;). Sessions have configurable TTL, max renewals, and absolute lifetime. The agent gets exactly the access you scope to it — no more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fund owner&lt;/strong&gt; — the human who actually owns the money — can approve transactions, connect via WalletConnect, and activate a kill switch if something goes wrong. They authenticate with a cryptographic signature (SIWS or SIWE), not a password.&lt;/p&gt;

&lt;p&gt;This isn't three passwords for the same interface. It's three genuinely different security principals with different capabilities and different threat models.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Policy Engine: Rules That Run Without Human Intervention
&lt;/h3&gt;

&lt;p&gt;The reason you can let an agent operate autonomously is that you've already told the system what it's allowed to do. WAIaaS ships a policy engine with 21 policy types and 4 security tiers: INSTANT, NOTIFY, DELAY, and APPROVAL.&lt;/p&gt;

&lt;p&gt;The tiers work like this: small transactions execute immediately. Medium transactions execute and notify you. Large transactions queue for a time delay (during which you can cancel). Very large transactions require explicit human approval. You define the dollar thresholds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/policies &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "walletId": "&amp;lt;wallet-uuid&amp;gt;",
    "type": "SPENDING_LIMIT",
    "rules": {
      "instant_max_usd": 100,
      "notify_max_usd": 500,
      "delay_max_usd": 2000,
      "delay_seconds": 900,
      "daily_limit_usd": 5000
    }
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this policy in place, an agent paying a $12 API bill executes immediately. An agent trying to move $3,000 in one shot waits 15 minutes and you get a notification. An agent trying to do something truly unusual hits an approval gate.&lt;/p&gt;

&lt;p&gt;The default is &lt;em&gt;deny&lt;/em&gt;. If you haven't configured &lt;code&gt;ALLOWED_TOKENS&lt;/code&gt; or &lt;code&gt;CONTRACT_WHITELIST&lt;/code&gt;, transactions are blocked. This is the right default for autonomous systems. You opt into access; you don't opt out of it.&lt;/p&gt;

&lt;p&gt;Beyond spending limits, the full policy set covers: token whitelists, contract whitelists, rate limits, time restrictions, allowed networks, approved spenders, approval amount limits, DeFi-specific controls like LTV limits and max perpetual leverage, and even ERC-8004 onchain reputation thresholds. The policy engine isn't an afterthought — it's the thing that makes autonomous operation safe enough to actually deploy.&lt;/p&gt;

&lt;h3&gt;
  
  
  x402: The Payment Protocol Agents Were Waiting For
&lt;/h3&gt;

&lt;p&gt;The most interesting capability for machine-to-machine commerce specifically is x402 HTTP payment protocol support. x402 extends HTTP with a &lt;code&gt;402 Payment Required&lt;/code&gt; status — when an API returns a 402, the client automatically pays and retries. No human interaction. No pre-negotiated API keys. Just an agent that pays for what it uses.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;WAIaaSClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@waiaas/sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WAIaaSClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://127.0.0.1:3100&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;sessionToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WAIAAS_SESSION_TOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// This fetch automatically handles 402 Payment Required responses&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;x402Fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com/premium-data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the agent's perspective, it's just an HTTP call. The wallet handles the 402 negotiation transparently. This is what actual machine-to-machine micropayments look like in practice — not a whitepaper concept, but a working implementation you can wire into an agent loop today.&lt;/p&gt;

&lt;p&gt;You can lock down which domains an agent is allowed to pay automatically using the &lt;code&gt;X402_ALLOWED_DOMAINS&lt;/code&gt; policy, so an agent can't be tricked into paying arbitrary endpoints.&lt;/p&gt;

&lt;h3&gt;
  
  
  7-Stage Transaction Pipeline
&lt;/h3&gt;

&lt;p&gt;Every transaction — whether it's a simple token transfer, a DeFi action, or an NFT transfer — runs through a 7-stage pipeline: validate, auth, policy, wait, execute, confirm. The "wait" stage is where time-delay policies live. The "policy" stage is where spending limits and whitelists fire. The architecture means every transaction goes through the same safety checks regardless of how it was initiated.&lt;/p&gt;

&lt;p&gt;There's also a dry-run mode for simulating transactions before execution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/transactions/send &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer wai_sess_&amp;lt;token&amp;gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "type": "TRANSFER",
    "to": "recipient-address",
    "amount": "0.1",
    "dryRun": true
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A well-built agent doesn't fire transactions blindly. It simulates first, checks the result, then executes. The infrastructure needs to support that workflow, and WAIaaS does.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multi-Chain From Day One
&lt;/h3&gt;

&lt;p&gt;Agent commerce doesn't happen on one chain. WAIaaS supports 2 chain types (EVM and Solana) across 18 networks. The same session token works whether the agent is moving USDC on Ethereum, swapping on Jupiter, or staking SOL via Jito. The wallet abstraction handles chain-specific details — nonces, fee structures, address formats — so agent code stays clean.&lt;/p&gt;

&lt;p&gt;15 DeFi protocol providers are integrated out of the box: Aave v3, Across, D'CENT Swap, Drift, ERC-8004, Hyperliquid, Jito Staking, Jupiter Swap, Kamino, Lido Staking, LI.FI, Pendle, Polymarket, XRPL DEX, and 0x Swap. An agent that needs to rebalance a portfolio, bridge funds cross-chain, enter a yield position, or trade perpetuals can do all of it through the same interface, subject to the same policy engine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/actions/jupiter-swap/swap &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer wai_sess_&amp;lt;token&amp;gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "inputMint": "So11111111111111111111111111111111111111112",
    "outputMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
    "amount": "1000000000"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  MCP Integration: Agents That Think and Spend
&lt;/h3&gt;

&lt;p&gt;If you're building on the Model Context Protocol — connecting Claude, GPT-4, or another LLM to tools via MCP — WAIaaS ships 45 MCP tools covering wallet operations, transactions, DeFi positions, NFTs, and x402 payments. Setup is one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;waiaas mcp setup &lt;span class="nt"&gt;--all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, the AI model can check balances, execute swaps, monitor incoming transactions, and pay for API calls as naturally as it calls any other tool. The MCP layer doesn't bypass the policy engine — every tool call still runs through the same 7-stage pipeline. The agent gets capability; you keep control.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting It Running
&lt;/h2&gt;

&lt;p&gt;The fastest path from zero to a working agent wallet:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Deploy with Docker&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/minhoyoo-iotrust/WAIaaS.git
&lt;span class="nb"&gt;cd &lt;/span&gt;WAIaaS
docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Docker image is &lt;code&gt;ghcr.io/minhoyoo-iotrust/waiaas:latest&lt;/code&gt;, binding to &lt;code&gt;127.0.0.1:3100&lt;/code&gt; by default. For production, use the secrets overlay (&lt;code&gt;docker-compose.secrets.yml&lt;/code&gt;) to inject credentials via Docker Secrets rather than environment variables.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Create a wallet and session&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create wallet&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/wallets &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"name": "trading-wallet", "chain": "solana", "environment": "mainnet"}'&lt;/span&gt;

&lt;span class="c"&gt;# Create agent session&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/sessions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"walletId": "&amp;lt;wallet-uuid&amp;gt;"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3: Set spending policies before funding&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Configure at minimum a &lt;code&gt;SPENDING_LIMIT&lt;/code&gt; and &lt;code&gt;ALLOWED_TOKENS&lt;/code&gt; policy before you put real funds in. Default-deny means nothing moves without explicit permission.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Wire the session token into your agent&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;WAIaaSClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@waiaas/sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WAIaaSClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WAIAAS_BASE_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;sessionToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WAIAAS_SESSION_TOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBalance&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or use the CLI shortcut that handles steps 2-4 in one shot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;waiaas quickset &lt;span class="nt"&gt;--mode&lt;/span&gt; mainnet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 5: Connect the interactive API docs&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;open http://127.0.0.1:3100/reference
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The OpenAPI 3.0 spec is auto-generated from the codebase and served at &lt;code&gt;/doc&lt;/code&gt;. The interactive Scalar UI at &lt;code&gt;/reference&lt;/code&gt; lets you explore all 39 REST API route modules and test calls directly — useful when you're building out agent logic and want to see exactly what each endpoint returns.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Means for the Agent Economy
&lt;/h2&gt;

&lt;p&gt;The question of how AI agents pay for things isn't theoretical anymore. The x402 protocol gives APIs a standard way to charge programmatic clients. ERC-4337 Account Abstraction makes gasless transactions and smart account logic practical. ERC-8004 provides a framework for onchain agent reputation. The pieces are assembling.&lt;/p&gt;

&lt;p&gt;What's been missing is the infrastructure layer that connects agent logic to these payment primitives with appropriate security controls in between. An agent that can spend without guardrails is a liability. An agent that requires human approval for every transaction isn't autonomous. The right answer is a programmable policy engine that enforces rules at the infrastructure level — so that when the agent acts within its mandate, it acts freely, and when it tries to exceed that mandate, the system stops it.&lt;/p&gt;

&lt;p&gt;That's what WAIaaS is built to provide. Not a vision of future infrastructure, but running code you can deploy today.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/minhoyoo-iotrust/WAIaaS" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; has the full source, Docker setup, and SDK documentation. The &lt;a href="https://waiaas.ai" rel="noopener noreferrer"&gt;official site&lt;/a&gt; covers architecture and integration guides. If you're building agents that need economic agency — the ability to pay for APIs, execute trades, manage positions, or participate in on-chain protocols — the financial rails are ready when you are.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>web3</category>
      <category>api</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>From Symbol to Contract: Asset Resolution APIs for Multi-Chain Trading Bots</title>
      <dc:creator>Wallet Guy</dc:creator>
      <pubDate>Tue, 23 Jun 2026 16:06:14 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/walletguy/from-symbol-to-contract-asset-resolution-apis-for-multi-chain-trading-bots-28l5</link>
      <guid>https://dev.clauneck.workers.dev/walletguy/from-symbol-to-contract-asset-resolution-apis-for-multi-chain-trading-bots-28l5</guid>
      <description>&lt;h1&gt;
  
  
  From Symbol to Contract: Asset Resolution APIs for Multi-Chain Trading Bots
&lt;/h1&gt;

&lt;p&gt;Your trading bot spotted the arbitrage window — SOL/USDC spread across Jupiter and a CEX, closing in seconds. The alpha is there. But before a single swap executes, your bot needs to resolve token addresses, verify it has the right session token, check gas conditions, and route the transaction through policy controls that won't silently reject a $500 move. Most of that infrastructure doesn't exist in your codebase yet. That's the problem this post solves.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Infrastructure Debt Kills Good Strategies
&lt;/h2&gt;

&lt;p&gt;Algorithmic trading bots fail in two ways: bad strategy and bad plumbing. Bad strategy is hard to fix. Bad plumbing is just engineering work you haven't done yet.&lt;/p&gt;

&lt;p&gt;The plumbing problem for multi-chain bots is specific: you're operating across Solana and EVM chains simultaneously, hitting 15+ DeFi protocols, managing gas costs, and maintaining risk controls that prevent your bot from blowing up a wallet on a bad trade. If you bolt all of that together yourself — custom signing logic, manual address lookups, ad hoc rate limiting, hand-rolled session management — you'll spend more time maintaining infrastructure than improving your edge. WAIaaS is a self-hosted Wallet-as-a-Service that provides that infrastructure as a local API, so you can focus on the strategy layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Asset Resolution Problem
&lt;/h2&gt;

&lt;p&gt;Multi-chain trading bots constantly need to answer a deceptively annoying question: &lt;em&gt;what is the contract address for this token on this chain?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Hardcoding token addresses is fragile. Token lists go stale. New tokens get listed. Wrapped versions differ across chains. And when you're working across Solana (where tokens are identified by mint addresses like &lt;code&gt;So11111111111111111111111111111111111111112&lt;/code&gt;) and EVM chains (where they're checksummed hex addresses), your address management code gets messy fast.&lt;/p&gt;

&lt;p&gt;WAIaaS exposes a &lt;code&gt;resolve-asset&lt;/code&gt; MCP tool and token resolution via the REST API that handles this lookup layer for you. But more importantly, it normalizes the entire execution path — from asset resolution through policy check through on-chain execution — so your bot doesn't have to think about chain-specific quirks at each step.&lt;/p&gt;

&lt;h2&gt;
  
  
  What WAIaaS Gives a Trading Bot
&lt;/h2&gt;

&lt;p&gt;WAIaaS runs locally (default: &lt;code&gt;127.0.0.1:3100&lt;/code&gt;) and exposes a REST API with 39 route modules. For a trading bot, the relevant surface area is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Wallet management&lt;/strong&gt; — create isolated wallets per strategy, per chain&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Session tokens&lt;/strong&gt; — scoped credentials for bot processes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transaction execution&lt;/strong&gt; — 7 transaction types including &lt;code&gt;Batch&lt;/code&gt; for atomic multi-step trades&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;15 DeFi protocol integrations&lt;/strong&gt; — Jupiter, Drift, Hyperliquid, Aave v3, LI.FI, Across, and more&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gas conditional execution&lt;/strong&gt; — transactions only fire when gas price meets your threshold&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Policy engine&lt;/strong&gt; — 21 policy types with 4 security tiers to bound your bot's risk&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dry-run simulation&lt;/strong&gt; — test a trade path before committing gas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's walk through how a real trading bot interacts with each layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Create an Isolated Wallet Per Strategy
&lt;/h2&gt;

&lt;p&gt;Good bot architecture isolates capital per strategy. A Solana arb bot shouldn't share a wallet with your Drift perpetuals position manager. Create a wallet for each:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/wallets &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"name": "trading-wallet", "chain": "solana", "environment": "mainnet"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then create a session token scoped to that wallet — this is what your bot process uses at runtime:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/sessions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"walletId": "&amp;lt;wallet-uuid&amp;gt;"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The session token (&lt;code&gt;wai_sess_...&lt;/code&gt;) is all your bot needs for transaction execution. The master password stays out of the hot path entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Check Balances Before You Trade
&lt;/h2&gt;

&lt;p&gt;Before your bot enters a position, it needs to know what it's working with. The balance check is a single authenticated call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://127.0.0.1:3100/v1/wallet/balance &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer wai_sess_eyJhbGciOiJIUzI1NiJ9..."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the TypeScript SDK, the same call looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;WAIaaSClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@waiaas/sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WAIaaSClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://127.0.0.1:3100&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;sessionToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WAIAAS_SESSION_TOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBalance&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;network&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use &lt;code&gt;getAssets()&lt;/code&gt; if you need the full picture — all token balances across the wallet, not just the native token. That's your pre-flight check before sizing a position.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Execute a Swap via Jupiter
&lt;/h2&gt;

&lt;p&gt;Once your bot resolves that the Jupiter SOL/USDC spread is worth hitting, execution is a single API call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/actions/jupiter-swap/swap &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer wai_sess_&amp;lt;token&amp;gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "inputMint": "So11111111111111111111111111111111111111112",
    "outputMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
    "amount": "1000000000"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the token addresses here — &lt;code&gt;So111...112&lt;/code&gt; is the native SOL mint, &lt;code&gt;EPjFW...t1v&lt;/code&gt; is USDC on Solana. WAIaaS handles the Jupiter routing, quote fetching, and transaction construction. Your bot just specifies the economic intent.&lt;/p&gt;

&lt;p&gt;The same pattern works across all 15 integrated DeFi protocols. For Hyperliquid perpetuals, for Drift, for Aave v3 on EVM — the action provider pattern is consistent. Your bot doesn't need protocol-specific SDKs; it needs one authenticated HTTP client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Simulate Before You Execute
&lt;/h2&gt;

&lt;p&gt;Sending a transaction without knowing if it'll succeed is expensive. WAIaaS has a dry-run mode that simulates the full transaction pipeline — including policy checks — without touching the chain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/transactions/send &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer wai_sess_&amp;lt;token&amp;gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "type": "TRANSFER",
    "to": "recipient-address",
    "amount": "0.1",
    "dryRun": true
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a trading bot, this is valuable before executing large positions or testing a new strategy path. If a policy would block the trade, you find out before paying gas. If your balance is insufficient, you find out before the swap fails on-chain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Build Risk Controls with the Policy Engine
&lt;/h2&gt;

&lt;p&gt;This is where WAIaaS earns its place in a serious trading setup. Bots go wrong. A bug in your sizing logic can drain a wallet. A policy engine that's always running gives you a hard floor on how badly things can go.&lt;/p&gt;

&lt;p&gt;The policy engine has 21 policy types and 4 security tiers. For a trading bot, the relevant ones are:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SPENDING_LIMIT&lt;/strong&gt; — the primary guardrail. Define how much your bot can move instantly, how much triggers a notification, how much requires a delay, and how much requires your explicit approval:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/policies &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "walletId": "&amp;lt;wallet-uuid&amp;gt;",
    "type": "SPENDING_LIMIT",
    "rules": {
      "instant_max_usd": 100,
      "notify_max_usd": 500,
      "delay_max_usd": 2000,
      "delay_seconds": 900,
      "daily_limit_usd": 5000
    }
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this policy: trades under $100 execute immediately. Trades $100–$500 execute and notify you. Trades $500–$2000 wait 15 minutes (cancellable). Anything above $2000 requires manual approval. A runaway position-sizing bug can't drain more than $5000 in a day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ALLOWED_TOKENS&lt;/strong&gt; — default-deny whitelist. If your bot should only ever touch SOL and USDC, configure exactly that. Any attempt to approve or transfer an unknown token gets blocked at the policy layer, before signing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CONTRACT_WHITELIST&lt;/strong&gt; — only allows calls to contracts you've explicitly approved. If your bot is a Jupiter-only strategy, it should only be able to call the Jupiter router contract. Full stop.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PERP_MAX_LEVERAGE&lt;/strong&gt; and &lt;strong&gt;PERP_MAX_POSITION_USD&lt;/strong&gt; — for bots running on Hyperliquid or Drift, these policies enforce position sizing limits at the infrastructure layer, independent of your strategy code.&lt;/p&gt;

&lt;p&gt;The critical detail: WAIaaS uses &lt;strong&gt;default-deny&lt;/strong&gt; enforcement. A transaction is blocked unless it's explicitly permitted. You're not writing code that says "block this" — you're writing code that says "allow this, and deny everything else."&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Handle Policy Denials Gracefully
&lt;/h2&gt;

&lt;p&gt;When a policy blocks a trade, your bot gets a structured error response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POLICY_DENIED"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Transaction denied by SPENDING_LIMIT policy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POLICY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"retryable"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;retryable&lt;/code&gt; field matters for bot logic. A &lt;code&gt;POLICY_DENIED&lt;/code&gt; with &lt;code&gt;retryable: false&lt;/code&gt; means you need human intervention — don't hammer the endpoint in a retry loop. A different error class might be retryable. Build your bot's error handling around these structured codes, not string matching on error messages.&lt;/p&gt;

&lt;p&gt;In TypeScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;WAIaaSClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;WAIaaSError&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@waiaas/sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendToken&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;WAIaaSError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`API Error: [&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;] &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// error.code examples: INSUFFICIENT_BALANCE, POLICY_DENIED, TOKEN_EXPIRED&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 7: Multi-Step Execution with Batch Transactions
&lt;/h2&gt;

&lt;p&gt;Real trading strategies often involve more than one step. Approve a token, then deposit into a lending protocol. Swap on Jupiter, then stake the output. WAIaaS supports a &lt;code&gt;Batch&lt;/code&gt; transaction type as one of its 7 transaction types, letting you compose atomic multi-step operations into a single transaction submission.&lt;/p&gt;

&lt;p&gt;This matters for MEV protection: if your strategy requires two actions, bundling them prevents another actor from sandwiching the intermediate state.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting to Claude or an LLM Orchestrator via MCP
&lt;/h2&gt;

&lt;p&gt;If your trading bot is LLM-orchestrated — using Claude or another model to interpret market signals and decide on trades — WAIaaS has a 45-tool MCP server that gives the model direct access to wallet operations without you building a custom tool layer.&lt;/p&gt;

&lt;p&gt;Setup is a single command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;waiaas mcp setup &lt;span class="nt"&gt;--all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That auto-registers all your wallets with Claude Desktop. The MCP server exposes tools including &lt;code&gt;get_balance&lt;/code&gt;, &lt;code&gt;send_token&lt;/code&gt;, &lt;code&gt;get_defi_positions&lt;/code&gt;, &lt;code&gt;simulate_transaction&lt;/code&gt;, &lt;code&gt;hyperliquid&lt;/code&gt;, &lt;code&gt;polymarket&lt;/code&gt;, and &lt;code&gt;get_assets&lt;/code&gt; — the full trading surface area, all authenticated and policy-gated.&lt;/p&gt;

&lt;p&gt;For a multi-strategy setup where different LLM agents manage different wallets, you can run one MCP server per wallet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"waiaas-trading"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@waiaas/mcp"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_BASE_URL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://127.0.0.1:3100"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_AGENT_ID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"019c47d6-51ef-7f43-a76b-d50e875d95f4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_AGENT_NAME"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"trading-agent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_DATA_DIR"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"~/.waiaas"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"waiaas-solana"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@waiaas/mcp"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_BASE_URL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://127.0.0.1:3100"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_AGENT_ID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"019c4cd2-86e8-758f-a61e-9c560307c788"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_AGENT_NAME"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"solana-wallet"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_DATA_DIR"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"~/.waiaas"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each agent gets its own session scope, its own policies, its own position limits. They can't interfere with each other's capital.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Start: Bot Infrastructure in 5 Minutes
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Install the CLI&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @waiaas/cli

&lt;span class="c"&gt;# 2. Initialize and start the daemon&lt;/span&gt;
waiaas init
waiaas start

&lt;span class="c"&gt;# 3. Create wallets and sessions in one command&lt;/span&gt;
waiaas quickset &lt;span class="nt"&gt;--mode&lt;/span&gt; mainnet

&lt;span class="c"&gt;# 4. Connect your bot using the session token printed by quickset&lt;/span&gt;
&lt;span class="c"&gt;# Set WAIAAS_SESSION_TOKEN in your bot's environment&lt;/span&gt;

&lt;span class="c"&gt;# 5. (Optional) Register with Claude Desktop&lt;/span&gt;
waiaas mcp setup &lt;span class="nt"&gt;--all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For production deployments, Docker is the better path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/minhoyoo-iotrust/WAIaaS.git
&lt;span class="nb"&gt;cd &lt;/span&gt;WAIaaS
docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The daemon runs on &lt;code&gt;127.0.0.1:3100&lt;/code&gt; by default — local-only by design. Your API keys and session tokens never leave the host.&lt;/p&gt;

&lt;h2&gt;
  
  
  The OpenAPI Spec Is Your Friend
&lt;/h2&gt;

&lt;p&gt;WAIaaS auto-generates an OpenAPI 3.0 spec and serves an interactive API reference:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Download the spec for your bot's HTTP client generation&lt;/span&gt;
curl http://127.0.0.1:3100/doc &lt;span class="nt"&gt;-o&lt;/span&gt; openapi.json

&lt;span class="c"&gt;# Browse the interactive reference&lt;/span&gt;
open http://127.0.0.1:3100/reference
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're generating a typed HTTP client for your bot (which you should be), point your generator at &lt;code&gt;/doc&lt;/code&gt; and get a fully typed interface to all 39 API route modules.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;WAIaaS is open-source and self-hosted — your keys stay on your infrastructure, your trades stay private, and you're not dependent on a third-party service staying online when your bot needs to execute. The full codebase, including the 15 DeFi protocol integrations and policy engine, is on GitHub.&lt;/p&gt;

&lt;p&gt;Star the repo and read the full documentation to go deeper on policy configuration, account abstraction with ERC-4337, and the incoming transaction monitoring that lets your bot react to deposits in real time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/minhoyoo-iotrust/WAIaaS" rel="noopener noreferrer"&gt;https://github.com/minhoyoo-iotrust/WAIaaS&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Official site: &lt;a href="https://waiaas.ai" rel="noopener noreferrer"&gt;https://waiaas.ai&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>defi</category>
      <category>api</category>
      <category>trading</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>Nonce Collision Prevention: Managing Transaction Order Across 18 Networks for AI Agents</title>
      <dc:creator>Wallet Guy</dc:creator>
      <pubDate>Tue, 23 Jun 2026 10:07:45 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/walletguy/nonce-collision-prevention-managing-transaction-order-across-18-networks-for-ai-agents-1f51</link>
      <guid>https://dev.clauneck.workers.dev/walletguy/nonce-collision-prevention-managing-transaction-order-across-18-networks-for-ai-agents-1f51</guid>
      <description>&lt;h1&gt;
  
  
  Nonce Collision Prevention: How WAIaaS Manages Transaction Order for AI Agents Across 18 Networks
&lt;/h1&gt;

&lt;p&gt;Nonce collision is one of the most frustrating problems you'll hit when building AI agents that send blockchain transactions — and it gets worse the moment your agent tries to operate across multiple networks simultaneously. If your agent fires two transactions at once (which AI agents absolutely will do), and both grab the same nonce, one of them silently fails. No error thrown. No retry. Just a lost transaction and a confused agent.&lt;/p&gt;

&lt;p&gt;This post walks through why nonce management is uniquely hard for AI agents, how WAIaaS handles it through its 7-stage transaction pipeline, and how you can get an agent submitting safe, ordered transactions across 18 networks in about 10 minutes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Nonce Collisions Are an AI Agent Problem, Not Just a Blockchain Problem
&lt;/h2&gt;

&lt;p&gt;Human wallets rarely hit nonce collisions. A person clicks "send," waits for confirmation, then sends again. Sequential by nature.&lt;/p&gt;

&lt;p&gt;AI agents don't work that way. LangChain agents, CrewAI crews, AutoGPT loops, Claude via MCP — they're all capable of initiating multiple actions in parallel or in rapid succession. An agent managing a DeFi portfolio might simultaneously:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Swap SOL for USDC on Jupiter&lt;/li&gt;
&lt;li&gt;Stake ETH via Lido&lt;/li&gt;
&lt;li&gt;Submit a limit order on Hyperliquid&lt;/li&gt;
&lt;li&gt;Pay for an API call via x402&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If those four actions hit the same wallet, on even two different chains, you need something that tracks nonce state correctly, queues competing transactions, and retries failed submissions — all without the agent needing to know any of this is happening.&lt;/p&gt;

&lt;p&gt;That's the infrastructure problem WAIaaS solves. The agent just calls an API. WAIaaS handles the rest.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Makes Multi-Network Nonce Management Hard
&lt;/h2&gt;

&lt;p&gt;Before getting to the solution, it helps to understand what you're actually dealing with.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nonces are per-account, per-chain.&lt;/strong&gt; Your Ethereum wallet has its own nonce sequence. Your Solana wallet uses a different mechanism (recent blockhash slots). A wallet on Arbitrum has its own nonce counter separate from Ethereum mainnet, even if it's the same private key. WAIaaS supports 18 networks across 2 chain types (EVM and Solana), which means nonce state has to be tracked independently for each.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Concurrent submissions create races.&lt;/strong&gt; If two processes read nonce &lt;code&gt;42&lt;/code&gt; from the chain at the same moment and both submit with nonce &lt;code&gt;42&lt;/code&gt;, the network accepts one and silently drops the other. No exception. No revert. The second transaction just never exists.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI agents are naturally concurrent.&lt;/strong&gt; Even a single Claude conversation can trigger tool calls that fan out into multiple API requests. The MCP server for WAIaaS exposes 45 tools. An agent using &lt;code&gt;send-batch&lt;/code&gt;, &lt;code&gt;hyperliquid&lt;/code&gt;, and &lt;code&gt;send-token&lt;/code&gt; in the same response is not unusual.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stuck transactions block everything after them.&lt;/strong&gt; If nonce &lt;code&gt;42&lt;/code&gt; gets stuck (gas too low, RPC timeout, whatever), nonces &lt;code&gt;43&lt;/code&gt;, &lt;code&gt;44&lt;/code&gt;, &lt;code&gt;45&lt;/code&gt; are all waiting behind it. The agent appears frozen.&lt;/p&gt;




&lt;h2&gt;
  
  
  How WAIaaS Handles This: The 7-Stage Pipeline
&lt;/h2&gt;

&lt;p&gt;Every transaction submitted to WAIaaS — whether via REST API, TypeScript SDK, Python SDK, or any of the 45 MCP tools — goes through a 7-stage pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;stage1-validate → stage2-auth → stage3-policy → stage4-wait → stage5-execute → stage6-confirm → stages
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key stage for nonce safety is &lt;strong&gt;stage4-wait&lt;/strong&gt;. This is where WAIaaS serializes transactions before they touch the network.&lt;/p&gt;

&lt;p&gt;Here's what that means in practice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Transactions for the same wallet+chain are queued and executed in order&lt;/li&gt;
&lt;li&gt;Nonce assignment happens immediately before broadcast, not at submission time&lt;/li&gt;
&lt;li&gt;If execution fails, the pipeline can retry without creating a gap in the nonce sequence&lt;/li&gt;
&lt;li&gt;The agent's API call returns a transaction ID immediately; confirmation is async&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent doesn't wait for blockchain confirmation before it can do something else. It submits, gets an ID, and can poll or move on. WAIaaS handles the actual sequencing.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Agent's View: Simple API, Complex Safety
&lt;/h2&gt;

&lt;p&gt;From the agent's perspective, sending a transaction looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/transactions/send &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer wai_sess_&amp;lt;token&amp;gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "type": "TRANSFER",
    "to": "recipient-address",
    "amount": "0.1"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent doesn't specify a nonce. It doesn't know what network the wallet is on (that's configured at wallet creation time). It just says "send 0.1" and gets back a transaction ID.&lt;/p&gt;

&lt;p&gt;Behind that call, WAIaaS is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Validating the request format&lt;/li&gt;
&lt;li&gt;Checking the session token is valid and not expired&lt;/li&gt;
&lt;li&gt;Running the transaction through the policy engine (21 policy types, default-deny)&lt;/li&gt;
&lt;li&gt;Queuing it in the pipeline behind any in-flight transactions for that wallet&lt;/li&gt;
&lt;li&gt;Assigning the correct nonce at execution time&lt;/li&gt;
&lt;li&gt;Submitting to the RPC endpoint&lt;/li&gt;
&lt;li&gt;Polling for confirmation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you want to test a transaction without actually submitting it, use the dry-run flag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/transactions/send &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer wai_sess_&amp;lt;token&amp;gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "type": "TRANSFER",
    "to": "recipient-address",
    "amount": "0.1",
    "dryRun": true
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This runs the transaction through validation, auth, and policy stages but stops before execution. You get back what would have happened, including policy verdicts, without touching the chain. Useful for testing agent logic before letting it loose with real funds.&lt;/p&gt;




&lt;h2&gt;
  
  
  Multiple Wallets, Multiple Networks: The MCP Approach
&lt;/h2&gt;

&lt;p&gt;If your agent needs to operate on multiple chains simultaneously — say, ETH on mainnet and SOL on Solana mainnet — the cleanest pattern is one MCP server per wallet. Each wallet has its own session token, its own policy set, and its own nonce sequence. There's no shared state that can collide.&lt;/p&gt;

&lt;p&gt;The Claude Desktop config for this looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"waiaas-trading"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@waiaas/mcp"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_BASE_URL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://127.0.0.1:3100"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_AGENT_ID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"019c47d6-51ef-7f43-a76b-d50e875d95f4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_AGENT_NAME"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"trading-agent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_DATA_DIR"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"~/.waiaas"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"waiaas-solana"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@waiaas/mcp"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_BASE_URL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://127.0.0.1:3100"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_AGENT_ID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"019c4cd2-86e8-758f-a61e-9c560307c788"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_AGENT_NAME"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"solana-wallet"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_DATA_DIR"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"~/.waiaas"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each MCP server instance connects to a different wallet on the same WAIaaS daemon. Claude sees two separate sets of tools — &lt;code&gt;waiaas-trading&lt;/code&gt; tools operate on the EVM wallet, &lt;code&gt;waiaas-solana&lt;/code&gt; tools operate on the Solana wallet. Transactions submitted through either path are independently queued and sequenced. They cannot interfere with each other's nonce state.&lt;/p&gt;

&lt;p&gt;The CLI can auto-generate this entire configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;waiaas mcp setup &lt;span class="nt"&gt;--all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This registers all wallets known to the daemon and prints the JSON you paste into Claude Desktop config.&lt;/p&gt;




&lt;h2&gt;
  
  
  Policy as a Safety Net for Agent Mistakes
&lt;/h2&gt;

&lt;p&gt;Nonce ordering keeps transactions from colliding at the protocol level. But AI agents can also make &lt;em&gt;logical&lt;/em&gt; mistakes — sending to the wrong address, submitting unexpectedly large amounts, or looping on an action that should have stopped.&lt;/p&gt;

&lt;p&gt;WAIaaS's policy engine adds a second layer. With 21 policy types and 4 security tiers (INSTANT, NOTIFY, DELAY, APPROVAL), you can set hard limits on what the agent can actually do — regardless of what it asks for.&lt;/p&gt;

&lt;p&gt;A sensible starting policy for an agent you're testing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/policies &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "walletId": "&amp;lt;wallet-uuid&amp;gt;",
    "type": "SPENDING_LIMIT",
    "rules": {
      "instant_max_usd": 100,
      "notify_max_usd": 500,
      "delay_max_usd": 2000,
      "delay_seconds": 900,
      "daily_limit_usd": 5000
    }
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Under $100: executes immediately (INSTANT)&lt;/li&gt;
&lt;li&gt;$100–$500: executes immediately but you get notified (NOTIFY)&lt;/li&gt;
&lt;li&gt;$500–$2000: waits 15 minutes before executing, giving you a cancellation window (DELAY)&lt;/li&gt;
&lt;li&gt;Over $2000: requires your explicit approval via WalletConnect or Telegram (APPROVAL)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Combined with &lt;code&gt;ALLOWED_TOKENS&lt;/code&gt; and &lt;code&gt;CONTRACT_WHITELIST&lt;/code&gt; (both default-deny — the agent literally cannot interact with tokens or contracts you haven't whitelisted), you have a system where agent bugs hit policy walls before they hit the blockchain.&lt;/p&gt;

&lt;p&gt;When a transaction is blocked by policy, the response looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POLICY_DENIED"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Transaction denied by SPENDING_LIMIT policy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POLICY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"retryable"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent sees a clear error code it can handle, log, or report back to the user.&lt;/p&gt;




&lt;h2&gt;
  
  
  Building an Agent with the TypeScript SDK
&lt;/h2&gt;

&lt;p&gt;For agents built in code rather than via MCP, the TypeScript SDK gives you the same pipeline access with a clean async interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;WAIaaSClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;WAIaaSError&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@waiaas/sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WAIaaSClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;WAIAAS_BASE_URL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3100&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;sessionToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;WAIAAS_SESSION_TOKEN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Check balance before acting&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBalance&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Balance: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;network&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Submit transaction — nonce handled by WAIaaS&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sendResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendToken&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TRANSFER&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;recipient-address&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.001&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Transaction submitted: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sendResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (status: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sendResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Poll for confirmation&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;POLL_TIMEOUT_MS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;startTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;startTime&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;POLL_TIMEOUT_MS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sendResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;COMPLETED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Transaction confirmed! Hash: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;txHash&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;FAILED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Transaction failed: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the pattern: submit, get an ID, poll. The agent isn't blocking on blockchain confirmation. It can do other work between polls. And if two parts of the agent submit transactions simultaneously, WAIaaS serializes them correctly — the agent just sees two IDs to track.&lt;/p&gt;

&lt;p&gt;Error handling is straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendToken&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;WAIaaSError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`API Error: [&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;] &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// error.code examples: INSUFFICIENT_BALANCE, POLICY_DENIED, TOKEN_EXPIRED&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Quick Start: Agent with Safe Transaction Ordering in 5 Steps
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1 — Install and start WAIaaS&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @waiaas/cli
waiaas init
waiaas start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2 — Create wallets and sessions&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;waiaas quickset &lt;span class="nt"&gt;--mode&lt;/span&gt; mainnet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates wallets and MCP sessions in one command.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3 — Set up policies before giving the agent access&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/policies &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "walletId": "&amp;lt;wallet-uuid&amp;gt;",
    "type": "SPENDING_LIMIT",
    "rules": {
      "instant_max_usd": 100,
      "notify_max_usd": 500,
      "delay_max_usd": 2000,
      "delay_seconds": 900,
      "daily_limit_usd": 5000
    }
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4 — Connect Claude via MCP&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;waiaas mcp setup &lt;span class="nt"&gt;--all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste the output into your Claude Desktop config.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5 — Test with a dry run&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/transactions/send &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer wai_sess_&amp;lt;token&amp;gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "type": "TRANSFER",
    "to": "recipient-address",
    "amount": "0.1",
    "dryRun": true
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Confirm the pipeline responds correctly before sending real funds.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;The nonce problem is infrastructure. Once it's solved, the interesting work is building agents that actually do something useful — swapping tokens, managing DeFi positions, paying for their own API calls with x402. WAIaaS has 15 DeFi protocol integrations and 45 MCP tools ready to use once your transaction pipeline is stable.&lt;/p&gt;

&lt;p&gt;Browse the full API reference at &lt;code&gt;http://127.0.0.1:3100/reference&lt;/code&gt; after starting the daemon — it's an interactive Scalar UI generated from the OpenAPI 3.0 spec, covering all 39 REST API route modules. Everything your agent can call is documented there with live examples.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Get started:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/minhoyoo-iotrust/WAIaaS" rel="noopener noreferrer"&gt;https://github.com/minhoyoo-iotrust/WAIaaS&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Official site: &lt;a href="https://waiaas.ai" rel="noopener noreferrer"&gt;https://waiaas.ai&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>blockchain</category>
      <category>architecture</category>
      <category>web3</category>
    </item>
    <item>
      <title>Production Docker Architecture: WAIaaS Daemon + Push-Relay Services for Enterprise AI Wallets</title>
      <dc:creator>Wallet Guy</dc:creator>
      <pubDate>Mon, 22 Jun 2026 17:47:29 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/walletguy/production-docker-architecture-waiaas-daemon-push-relay-services-for-enterprise-ai-wallets-4d28</link>
      <guid>https://dev.clauneck.workers.dev/walletguy/production-docker-architecture-waiaas-daemon-push-relay-services-for-enterprise-ai-wallets-4d28</guid>
      <description>&lt;h1&gt;
  
  
  Production Docker Architecture: Running WAIaaS Daemon + Push-Relay for Enterprise AI Wallets
&lt;/h1&gt;

&lt;p&gt;Would you trust a third party with your AI agent's private keys? If you're building autonomous agents that move real money, that question deserves a serious answer — and for many developers, the answer is no. Self-hosting your wallet infrastructure means your keys live on your server, your policies run in your container, and no external service can rate-limit, suspend, or snoop on your agent's transactions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Self-Hosting Your AI Wallet Infrastructure Matters
&lt;/h2&gt;

&lt;p&gt;The case for self-hosted infrastructure in the AI wallet space isn't just philosophical — it's practical. When your agent executes DeFi trades, pays for API calls via x402, or moves funds across chains, every transaction passes through whatever infrastructure sits between the agent and the blockchain. If that infrastructure is a hosted service, you've introduced a custody and availability dependency you can't control.&lt;/p&gt;

&lt;p&gt;Running WAIaaS on your own server flips that equation. You control the master password, the signing keys, the policy engine, and the notification channel. There are no API rate limits imposed by a third party, no Terms of Service that could cut off your agent mid-operation, and no vendor with visibility into your wallet activity. It's the crypto equivalent of running your own email server — except the tooling has matured to the point where it's actually practical.&lt;/p&gt;

&lt;p&gt;WAIaaS is an open-source, self-hosted Wallet-as-a-Service built for AI agents. Its 15-package monorepo ships everything you need to run production wallet infrastructure: the main daemon, a push-relay service for mobile notifications, a CLI, MCP integration, and a policy engine. Let's walk through what a production Docker deployment looks like.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Two-Service Architecture
&lt;/h2&gt;

&lt;p&gt;One detail worth understanding before you deploy: WAIaaS ships &lt;strong&gt;two Docker images&lt;/strong&gt;, not one.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;waiaas&lt;/code&gt; daemon&lt;/strong&gt; — the core wallet service. This handles the REST API (39 route modules), the 7-stage transaction pipeline, the policy engine, session auth, and DeFi integrations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;push-relay&lt;/code&gt;&lt;/strong&gt; — a companion service that handles mobile push notifications for transaction approvals. When your agent submits a transaction that hits the APPROVAL tier, the push-relay is what sends the alert to your phone.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both images live in the same repository. The daemon is the required service; push-relay is what you add when you want human-in-the-loop approval via mobile notifications rather than requiring you to be at a terminal.&lt;/p&gt;

&lt;p&gt;This separation is deliberate. The push-relay has no access to private keys — it only receives notification events and forwards them. You can run the daemon without it, or run the push-relay on a different host entirely if your security model requires it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Security Model Before You Deploy
&lt;/h2&gt;

&lt;p&gt;WAIaaS implements a 3-layer security architecture:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Session auth → policy evaluation&lt;/strong&gt; — every agent transaction passes through the policy engine before execution&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time delay + approval&lt;/strong&gt; — the DELAY and APPROVAL tiers hold transactions until conditions are met&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring + kill switch&lt;/strong&gt; — incoming transaction monitoring and owner-controlled recovery&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Three auth methods govern who can do what:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;masterAuth&lt;/strong&gt; (Argon2id) — system administrator operations: creating wallets, managing sessions, setting policies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;sessionAuth&lt;/strong&gt; (JWT HS256) — what your AI agent uses for day-to-day operations: sending tokens, querying balances, executing DeFi actions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ownerAuth&lt;/strong&gt; (SIWS/SIWE) — the fund owner: approving held transactions, using the kill switch&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The policy engine enforces a &lt;strong&gt;default-deny&lt;/strong&gt; model. Until you explicitly configure &lt;code&gt;ALLOWED_TOKENS&lt;/code&gt; or &lt;code&gt;CONTRACT_WHITELIST&lt;/code&gt;, transactions are blocked. This is the right default for production — you opt into what your agent can do, not out of what it can't.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying with Docker Compose
&lt;/h2&gt;

&lt;p&gt;The fastest path to a running daemon is &lt;code&gt;docker compose up&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/minhoyoo-iotrust/WAIaaS.git
&lt;span class="nb"&gt;cd &lt;/span&gt;WAIaaS
docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's genuinely it for a first run. The image is &lt;code&gt;ghcr.io/minhoyoo-iotrust/waiaas:latest&lt;/code&gt; and the default port binding is &lt;code&gt;127.0.0.1:3100:3100&lt;/code&gt; — localhost-only by design. Your daemon is not exposed to the internet out of the box.&lt;/p&gt;

&lt;p&gt;For a more controlled first start — useful if you want to script the setup or run headless — use the auto-provision flag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; waiaas &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 127.0.0.1:3100:3100 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; waiaas-data:/data &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;WAIAAS_AUTO_PROVISION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  ghcr.io/minhoyoo-iotrust/waiaas:latest

&lt;span class="c"&gt;# Retrieve the auto-generated master password&lt;/span&gt;
docker &lt;span class="nb"&gt;exec &lt;/span&gt;waiaas &lt;span class="nb"&gt;cat&lt;/span&gt; /data/recovery.key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;WAIAAS_AUTO_PROVISION=true&lt;/code&gt; tells the entrypoint to generate a random master password on first boot and write it to &lt;code&gt;/data/recovery.key&lt;/code&gt;. This is useful for automated deployments where you don't want to manually set a password before the first start. You can harden it later with &lt;code&gt;waiaas set-master&lt;/code&gt; once the daemon is running.&lt;/p&gt;

&lt;p&gt;Here's the full Compose configuration the project ships with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;daemon&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghcr.io/minhoyoo-iotrust/waiaas:latest&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;waiaas-daemon&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;127.0.0.1:3100:3100"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;waiaas-data:/data&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;WAIAAS_DATA_DIR=/data&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;WAIAAS_DAEMON_HOSTNAME=0.0.0.0&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.env&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;healthcheck&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CMD"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;curl"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-f"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://localhost:3100/health"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;30s&lt;/span&gt;
      &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5s&lt;/span&gt;
      &lt;span class="na"&gt;start_period&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10s&lt;/span&gt;
      &lt;span class="na"&gt;retries&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;waiaas-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;local&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few things worth noting in this config:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Named volume&lt;/strong&gt; (&lt;code&gt;waiaas-data&lt;/code&gt;) — your wallet data persists across container restarts and updates. &lt;code&gt;docker compose down&lt;/code&gt; without &lt;code&gt;-v&lt;/code&gt; leaves your data intact.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Healthcheck&lt;/strong&gt; — Docker will restart the container if the health endpoint stops responding. Good for unattended production runs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;restart: unless-stopped&lt;/code&gt;&lt;/strong&gt; — the daemon comes back after host reboots.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;127.0.0.1:3100&lt;/code&gt;&lt;/strong&gt; — only localhost can reach it. If you need external access, put a reverse proxy (nginx, Caddy) in front and handle TLS there. Don't expose port 3100 directly to the internet.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Production Secrets Management
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;docker-compose.secrets.yml&lt;/code&gt; overlay is how you handle credentials in production without putting them in environment variables or &lt;code&gt;.env&lt;/code&gt; files that end up in logs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create secret files&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; secrets
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"your-secure-password"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; secrets/master_password.txt
&lt;span class="nb"&gt;chmod &lt;/span&gt;600 secrets/master_password.txt

&lt;span class="c"&gt;# Deploy with secrets overlay&lt;/span&gt;
docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.yml &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.secrets.yml up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Docker Secrets integration is supported directly in the entrypoint. The secret files are mounted into the container at runtime and read by the entrypoint script — they never appear in &lt;code&gt;docker inspect&lt;/code&gt; output or process environment listings.&lt;/p&gt;

&lt;p&gt;For self-hosters who care about operational security, this is the right way to run it. Your master password lives in a file with &lt;code&gt;600&lt;/code&gt; permissions, not in a shell history or a &lt;code&gt;.env&lt;/code&gt; file sitting next to your &lt;code&gt;docker-compose.yml&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Environment Variables
&lt;/h2&gt;

&lt;p&gt;The daemon is configured primarily through environment variables. The important ones for a production deployment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;WAIAAS_AUTO_PROVISION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;              &lt;span class="c"&gt;# Auto-generate master password on first start&lt;/span&gt;
&lt;span class="nv"&gt;WAIAAS_DAEMON_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3100                 &lt;span class="c"&gt;# Listening port&lt;/span&gt;
&lt;span class="nv"&gt;WAIAAS_DAEMON_HOSTNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.0.0.0         &lt;span class="c"&gt;# Bind address&lt;/span&gt;
&lt;span class="nv"&gt;WAIAAS_DAEMON_LOG_LEVEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;info            &lt;span class="c"&gt;# Log level (trace/debug/info/warn/error)&lt;/span&gt;
&lt;span class="nv"&gt;WAIAAS_DATA_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/data                   &lt;span class="c"&gt;# Data directory&lt;/span&gt;
&lt;span class="nv"&gt;WAIAAS_RPC_SOLANA_MAINNET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;url&amp;gt;         &lt;span class="c"&gt;# Solana mainnet RPC endpoint&lt;/span&gt;
&lt;span class="nv"&gt;WAIAAS_RPC_EVM_ETHEREUM_MAINNET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;url&amp;gt;   &lt;span class="c"&gt;# Ethereum mainnet RPC endpoint&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The RPC endpoint variables matter for production. The daemon needs RPC access for 2 chain types across 18 networks. If you're running a self-hosted Solana or Ethereum node, this is where you point the daemon at it — keeping your infrastructure fully sovereign, not just your keys.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up Wallets and Policies
&lt;/h2&gt;

&lt;p&gt;Once the daemon is running, the CLI handles the initial setup. Install it globally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @waiaas/cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CLI ships 20 commands. For initial setup, the relevant flow is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;waiaas init                        &lt;span class="c"&gt;# Create data directory + config.toml&lt;/span&gt;
waiaas start                       &lt;span class="c"&gt;# Start daemon&lt;/span&gt;
waiaas quickset &lt;span class="nt"&gt;--mode&lt;/span&gt; mainnet     &lt;span class="c"&gt;# Create wallets + MCP sessions in one step&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;quickset&lt;/code&gt; is the fast path. It creates wallets across the chains you configure and generates MCP sessions — the tokens your AI agent will use.&lt;/p&gt;

&lt;p&gt;For manual control, create a wallet directly via the API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/wallets &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"name": "trading-wallet", "chain": "solana", "environment": "mainnet"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then create a session token for your agent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/sessions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"walletId": "&amp;lt;wallet-uuid&amp;gt;"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That session token is what your agent uses. It has no access to wallet creation or policy management — only to the operations you've allowed through policies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring the Policy Engine for Production
&lt;/h2&gt;

&lt;p&gt;The default-deny model means you need to configure policies before your agent can do anything useful. Here's a sensible starting point for a trading wallet — a spending limit with four tiers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/policies &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "walletId": "&amp;lt;wallet-uuid&amp;gt;",
    "type": "SPENDING_LIMIT",
    "rules": {
      "instant_max_usd": 100,
      "notify_max_usd": 500,
      "delay_max_usd": 2000,
      "delay_seconds": 900,
      "daily_limit_usd": 5000
    }
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives you the full 4-tier security model in action:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;≤$100&lt;/strong&gt;: executes immediately, no noise&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;$100–$500&lt;/strong&gt;: executes immediately, sends a notification&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;$500–$2,000&lt;/strong&gt;: queued for 15 minutes, then executes (you can cancel during the window)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&amp;gt;$2,000&lt;/strong&gt;: held until you explicitly approve via WalletConnect, Telegram, or push notification&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The 21 policy types cover everything from token whitelists and contract whitelists to DeFi-specific rules like &lt;code&gt;PERP_MAX_LEVERAGE&lt;/code&gt; for perpetual futures positions and &lt;code&gt;LENDING_LTV_LIMIT&lt;/code&gt; for lending protocols. For production, you'll want at minimum &lt;code&gt;ALLOWED_TOKENS&lt;/code&gt; and &lt;code&gt;CONTRACT_WHITELIST&lt;/code&gt; configured — without them, the default-deny model blocks token transfers and contract calls entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting Your Agent via MCP
&lt;/h2&gt;

&lt;p&gt;Once the daemon is running and wallets are configured, connecting Claude or another MCP-compatible AI is a one-command operation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;waiaas mcp setup &lt;span class="nt"&gt;--all&lt;/span&gt;    &lt;span class="c"&gt;# Auto-register all wallets with Claude Desktop&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or configure it manually in &lt;code&gt;claude_desktop_config.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"waiaas"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@waiaas/mcp"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_BASE_URL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://127.0.0.1:3100"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_SESSION_TOKEN"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"wai_sess_&amp;lt;your-token&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WAIAAS_DATA_DIR"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"~/.waiaas"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The MCP server exposes 45 tools covering wallet operations, transactions, DeFi actions across 15 integrated protocols, NFT operations, and x402 HTTP payment. Your agent gets a session-scoped, policy-enforced interface to your self-hosted wallet — no third-party relay, no external API calls beyond the blockchain RPCs you've configured.&lt;/p&gt;

&lt;h2&gt;
  
  
  Useful Docker Operations
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;          &lt;span class="c"&gt;# Start daemon&lt;/span&gt;
docker compose logs &lt;span class="nt"&gt;-f&lt;/span&gt;        &lt;span class="c"&gt;# Follow logs&lt;/span&gt;
docker compose down           &lt;span class="c"&gt;# Stop (data preserved in named volume)&lt;/span&gt;
docker compose down &lt;span class="nt"&gt;-v&lt;/span&gt;        &lt;span class="c"&gt;# Stop + delete data volume&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The named volume approach means updates are safe. Pull a new image, bring the stack down without &lt;code&gt;-v&lt;/code&gt;, and bring it back up — your wallet data is untouched. The daemon's healthcheck will tell Docker when it's ready.&lt;/p&gt;

&lt;p&gt;For debugging, the OpenAPI spec and interactive docs are available while the daemon is running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Download OpenAPI 3.0 spec&lt;/span&gt;
curl http://127.0.0.1:3100/doc &lt;span class="nt"&gt;-o&lt;/span&gt; openapi.json

&lt;span class="c"&gt;# View interactive API reference in browser&lt;/span&gt;
open http://127.0.0.1:3100/reference
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The interactive reference at &lt;code&gt;/reference&lt;/code&gt; (built with Scalar) makes it straightforward to explore the 39 API routes without reading raw JSON.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Start Summary
&lt;/h2&gt;

&lt;p&gt;If you want to go from zero to a running, policy-protected AI wallet in the shortest path:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Clone and start&lt;/strong&gt;: &lt;code&gt;git clone https://github.com/minhoyoo-iotrust/WAIaaS.git &amp;amp;&amp;amp; cd WAIaaS &amp;amp;&amp;amp; docker compose up -d&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Install the CLI&lt;/strong&gt;: &lt;code&gt;npm install -g @waiaas/cli&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create wallets and sessions&lt;/strong&gt;: &lt;code&gt;waiaas quickset --mode mainnet&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connect to Claude&lt;/strong&gt;: &lt;code&gt;waiaas mcp setup --all&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set spending policies&lt;/strong&gt; via the REST API or Admin UI at &lt;code&gt;/admin&lt;/code&gt; before letting your agent operate on mainnet&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The entire stack runs on your hardware. The push-relay handles mobile approvals. The policy engine enforces your rules. The keys never leave your server.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;The WAIaaS repository has detailed documentation on advanced policy configurations, the 15 integrated DeFi protocols, and the full SDK for building agents programmatically. If you're building something beyond a single-agent setup — multiple agents, multiple wallets, different policy profiles per agent — the multi-wallet MCP configuration and the TypeScript/Python SDKs are the natural next step.&lt;/p&gt;

&lt;p&gt;The code is open source, the deployment is yours, and the keys stay where they belong.&lt;/p&gt;

&lt;p&gt;→ &lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/minhoyoo-iotrust/WAIaaS" rel="noopener noreferrer"&gt;https://github.com/minhoyoo-iotrust/WAIaaS&lt;/a&gt;&lt;br&gt;
→ &lt;strong&gt;Official site&lt;/strong&gt;: &lt;a href="https://waiaas.ai" rel="noopener noreferrer"&gt;https://waiaas.ai&lt;/a&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>selfhosted</category>
      <category>devops</category>
      <category>ai</category>
    </item>
    <item>
      <title>When Machines Become Economic Actors: The x402 Payment Revolution</title>
      <dc:creator>Wallet Guy</dc:creator>
      <pubDate>Mon, 22 Jun 2026 12:29:41 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/walletguy/when-machines-become-economic-actors-the-x402-payment-revolution-5282</link>
      <guid>https://dev.clauneck.workers.dev/walletguy/when-machines-become-economic-actors-the-x402-payment-revolution-5282</guid>
      <description>&lt;h1&gt;
  
  
  When Machines Become Economic Actors: The x402 Payment Revolution
&lt;/h1&gt;

&lt;p&gt;AI agents are already browsing the web, writing code, and making decisions — but they still can't pay for what they use. That's not a philosophical problem; it's a missing infrastructure layer, and it's blocking a category of applications that should exist right now. The x402 HTTP payment protocol changes that equation, and pairing it with autonomous wallet infrastructure makes AI agents full economic participants for the first time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem Is Concrete, Not Hypothetical
&lt;/h2&gt;

&lt;p&gt;Think about what a capable AI agent actually needs to do its job. It needs data feeds. It needs compute. It calls APIs — weather services, market data providers, translation APIs, image generation endpoints. Every one of those services costs money. Right now, that cost is invisible to the agent. A human developer pre-pays for API keys, embeds credentials in environment variables, and hopes the agent doesn't hit rate limits or run up a bill the developer didn't anticipate.&lt;/p&gt;

&lt;p&gt;That model breaks at scale. If you're running ten agents, it's annoying. If you're running a thousand, it's unmanageable. And if you're building a system where agents spawn sub-agents dynamically, the entire model collapses — you can't pre-provision API keys for agents that don't exist yet.&lt;/p&gt;

&lt;p&gt;The deeper issue is that this dependency makes agents fundamentally non-autonomous. An agent that can't pay for its own resources is like a contractor who can't buy their own materials — every job requires a trip back to headquarters to ask for money. Real autonomy means the agent can acquire what it needs, when it needs it, within the limits you've set.&lt;/p&gt;

&lt;h2&gt;
  
  
  The x402 Moment
&lt;/h2&gt;

&lt;p&gt;The HTTP 402 status code has existed since 1991. It was defined as "Payment Required" and marked "reserved for future use." That future is arriving now.&lt;/p&gt;

&lt;p&gt;The x402 protocol gives this status code teeth. When an AI agent makes an HTTP request to a paid API, the server can respond with a 402 status and payment metadata — which blockchain, which token, how much. The agent settles the payment on-chain and retries the request with a payment receipt header. The API server verifies the payment and serves the content.&lt;/p&gt;

&lt;p&gt;From the agent's perspective, this is completely transparent. It makes a fetch call. If the resource requires payment, payment happens automatically. If the resource is free, nothing changes. No API key management. No pre-loaded credits. No human in the loop.&lt;/p&gt;

&lt;p&gt;This is what WAIaaS's &lt;code&gt;x402Fetch&lt;/code&gt; method actually does today:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;WAIaaSClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@waiaas/sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WAIaaSClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://127.0.0.1:3100&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;sessionToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WAIAAS_SESSION_TOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// This automatically handles 402 responses and pays with the agent's wallet&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;x402Fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.some-paid-service.com/data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent calls &lt;code&gt;x402Fetch&lt;/code&gt; exactly like it would call &lt;code&gt;fetch&lt;/code&gt;. If the server returns a 402, WAIaaS handles negotiation, settlement, and retry — all within the same call. The agent gets its data. The API provider gets paid. No human saw any of it.&lt;/p&gt;

&lt;p&gt;You can also interact with x402-capable endpoints directly through the REST API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/actions/x402-fetch &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer wai_sess_&amp;lt;token&amp;gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"url": "https://api.some-paid-service.com/data"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why Wallets Have to Be Different for Agents
&lt;/h2&gt;

&lt;p&gt;At this point you might be thinking: can't you just give an agent a standard crypto wallet? Load it with funds, hand it a private key, let it sign transactions?&lt;/p&gt;

&lt;p&gt;You can. And you probably shouldn't, at least not without guardrails. The difference between an autonomous agent and an autonomous agent &lt;em&gt;with a spending limit&lt;/em&gt; is the difference between a capable employee and one who can commit the company to unlimited financial obligations.&lt;/p&gt;

&lt;p&gt;WAIaaS was built around the assumption that autonomous agents need wallets that are designed for delegation — not just wallets that technically work. That means a few things:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Session-scoped access.&lt;/strong&gt; An agent doesn't hold the private key to the wallet. It holds a session token that grants time-limited, scope-limited access. The session can be revoked instantly. When the agent is done, the session expires. The wallet remains under the owner's control.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Policy enforcement at the infrastructure layer.&lt;/strong&gt; Before any transaction executes, it runs through a 7-stage pipeline that includes policy evaluation. There are 21 policy types covering everything from spending limits to allowed token lists to DeFi-specific constraints like maximum leverage for perpetual futures. Policies aren't applied by the agent — they're enforced &lt;em&gt;on&lt;/em&gt; the agent by the wallet infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Default-deny for token transfers.&lt;/strong&gt; If you haven't explicitly configured an &lt;code&gt;ALLOWED_TOKENS&lt;/code&gt; policy, token transfer transactions are blocked. An agent can't drain your wallet of a token you didn't know it could access. This is the right default.&lt;/p&gt;

&lt;p&gt;For x402 payments specifically, there's an &lt;code&gt;X402_ALLOWED_DOMAINS&lt;/code&gt; policy that whitelists which domains an agent is permitted to pay:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/policies &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "walletId": "&amp;lt;wallet-uuid&amp;gt;",
    "type": "X402_ALLOWED_DOMAINS",
    "rules": {
      "domains": ["api.example.com", "*.openai.com"]
    }
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means even if a malicious page returns a 402, the agent's wallet infrastructure will refuse to pay it. The allowed domain list is your firewall for agent payments.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Four Security Tiers
&lt;/h2&gt;

&lt;p&gt;One of the design choices in WAIaaS that matters for agent autonomy is the four-tier security model: INSTANT, NOTIFY, DELAY, and APPROVAL.&lt;/p&gt;

&lt;p&gt;Not every transaction is equal. Paying $0.003 for an API call should happen instantly and silently — interrupting a human to approve a fraction of a cent is counterproductive. Sending $5,000 somewhere should probably require a human to confirm.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;SPENDING_LIMIT&lt;/code&gt; policy encodes this logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/policies &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "walletId": "&amp;lt;wallet-uuid&amp;gt;",
    "type": "SPENDING_LIMIT",
    "rules": {
      "instant_max_usd": 10,
      "notify_max_usd": 100,
      "delay_max_usd": 1000,
      "delay_seconds": 300,
      "daily_limit_usd": 500,
      "monthly_limit_usd": 5000
    }
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Under this configuration: x402 micro-payments under $10 execute instantly. Payments up to $100 execute but send a notification. Payments up to $1,000 are queued for five minutes — giving you time to cancel if something looks wrong. Anything above $1,000 requires your explicit approval via WalletConnect or Telegram.&lt;/p&gt;

&lt;p&gt;This is what calibrated autonomy looks like. The agent operates freely within the bounds you've defined. It doesn't need to ask permission for small, routine transactions. But the infrastructure catches anything that falls outside the envelope you've established.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting a Working Agent on x402 in Under Ten Minutes
&lt;/h2&gt;

&lt;p&gt;This is a real setup, not a demo with mocked responses. Here's the minimal path from zero to an agent that can make x402 payments:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Start WAIaaS&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @waiaas/cli
waiaas init
waiaas start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On first start, you'll set a master password. This is the &lt;code&gt;masterAuth&lt;/code&gt; credential — it controls wallet creation, session management, and policy configuration. Keep it offline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Create a wallet and session&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create a wallet&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/wallets &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"name": "agent-wallet", "chain": "solana", "environment": "mainnet"}'&lt;/span&gt;

&lt;span class="c"&gt;# Create a session for the agent (save the token from the response)&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/sessions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"walletId": "&amp;lt;wallet-uuid&amp;gt;"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or use the quickset command to do both in one step: &lt;code&gt;waiaas quickset --mode mainnet&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Configure x402 payment policy&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/policies &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "walletId": "&amp;lt;wallet-uuid&amp;gt;",
    "type": "X402_ALLOWED_DOMAINS",
    "rules": {
      "domains": ["api.example.com"]
    }
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4: Fund the wallet and connect your agent&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Send a small amount of SOL (or ETH, depending on your chain) to the wallet address. Then give your agent the session token. With the TypeScript SDK:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;WAIaaSClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@waiaas/sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WAIaaSClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://127.0.0.1:3100&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;sessionToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WAIAAS_SESSION_TOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBalance&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Agent wallet: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Now the agent can pay for APIs automatically&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;x402Fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com/market-data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 5: Connect to Claude via MCP (optional)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're using Claude as your agent runtime, WAIaaS provides 45 MCP tools that Claude can call directly — including &lt;code&gt;x402-fetch&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;waiaas mcp setup &lt;span class="nt"&gt;--all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This auto-generates the Claude Desktop configuration and registers your wallet. Claude can then check balances, send tokens, make x402 payments, and interact with DeFi protocols through natural language.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Agent Economy Actually Looks Like
&lt;/h2&gt;

&lt;p&gt;The x402 pattern enables something that's easy to underestimate: agents that are &lt;em&gt;cost-aware&lt;/em&gt;. Right now most agents operate as if API calls are free. With x402, an agent can see exactly what it's spending, decide whether a data source is worth the price, compare costs across providers, and optimize its behavior accordingly.&lt;/p&gt;

&lt;p&gt;This isn't science fiction. The infrastructure exists today. WAIaaS ships with a Python SDK as well as TypeScript, so agents built in either ecosystem can participate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;waiaas&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;WAIaaSClient&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;WAIaaSClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://localhost:3100&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wai_sess_xxx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_balance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Agent budget: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The remaining gap is on the supply side: more APIs need to implement x402 response handling. That adoption curve is a separate conversation. But the agent infrastructure is ready — and having agents that are &lt;em&gt;capable&lt;/em&gt; of paying is what will push API providers to implement the protocol.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Monitoring Layer
&lt;/h2&gt;

&lt;p&gt;One concern that comes up immediately when you give agents autonomous spending authority: how do you know what they're doing?&lt;/p&gt;

&lt;p&gt;WAIaaS includes incoming transaction monitoring with real-time notifications for deposits. The transaction pipeline logs every stage — validation, policy evaluation, execution, confirmation. Every transaction the agent attempts is recorded, whether it succeeded, was delayed, required approval, or was blocked by policy.&lt;/p&gt;

&lt;p&gt;There's also a dry-run mode that lets agents (or developers testing agents) simulate a transaction before executing it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/transactions/send &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer wai_sess_&amp;lt;token&amp;gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "type": "TRANSFER",
    "to": "recipient-address",
    "amount": "0.1",
    "dryRun": true
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if something goes wrong — if an agent behaves unexpectedly, if a session token is compromised — the owner can revoke access immediately using WalletConnect-based approval flows. The DELAY tier is particularly useful here: large transactions sit in a queue for a configurable period before executing, giving you a window to cancel without the agent having any ability to rush the transaction through.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Comes Next
&lt;/h2&gt;

&lt;p&gt;The x402 pattern is a starting point, not a ceiling. Agents that can pay for API calls can also participate in more complex economic arrangements — lending protocols, prediction markets, perpetual futures, cross-chain asset movements. WAIaaS integrates 15 DeFi protocol providers for exactly this reason. The same wallet infrastructure that handles a $0.003 API payment can also manage a position on Hyperliquid or provide liquidity on Aave.&lt;/p&gt;

&lt;p&gt;The shift happening right now isn't just technical. It's that agents are moving from tools that humans use to participants in systems that include humans. An agent that has its own wallet, earns from its work, and spends on what it needs is a different kind of entity than a chatbot. The infrastructure to support that transition exists today.&lt;/p&gt;

&lt;p&gt;Explore the project on GitHub at &lt;a href="https://github.com/minhoyoo-iotrust/WAIaaS" rel="noopener noreferrer"&gt;https://github.com/minhoyoo-iotrust/WAIaaS&lt;/a&gt; or learn more about what's available at &lt;a href="https://waiaas.ai" rel="noopener noreferrer"&gt;https://waiaas.ai&lt;/a&gt;. The API reference is live at &lt;code&gt;/reference&lt;/code&gt; once you have a daemon running — 39 route modules, interactive docs, and no account required to start experimenting.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>web3</category>
      <category>api</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>Hyperliquid Sub-Accounts: Advanced Position Management for AI Trading Bots</title>
      <dc:creator>Wallet Guy</dc:creator>
      <pubDate>Sun, 21 Jun 2026 15:16:41 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/walletguy/hyperliquid-sub-accounts-advanced-position-management-for-ai-trading-bots-52i6</link>
      <guid>https://dev.clauneck.workers.dev/walletguy/hyperliquid-sub-accounts-advanced-position-management-for-ai-trading-bots-52i6</guid>
      <description>&lt;h1&gt;
  
  
  Hyperliquid Sub-Accounts: Advanced Position Management for AI Trading Bots
&lt;/h1&gt;

&lt;p&gt;Hyperliquid sub-accounts give your trading bot the isolation it needs to run parallel strategies without cross-contaminating risk — but wiring up the signing logic, policy guards, and cross-protocol hedging yourself is where most teams sink weeks. If you're building an automated trading system that touches Hyperliquid perpetuals, you need wallet infrastructure that keeps up with your execution logic without becoming the bottleneck.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Infrastructure Is the Hidden Bottleneck
&lt;/h2&gt;

&lt;p&gt;Algo traders spend most of their time on signal generation and execution logic. Wallet plumbing — key management, transaction signing, approval flows, risk limits — gets bolted on at the end, and that's exactly when it breaks. A missed position because the signing layer threw an unexpected error, a blown leverage limit because nothing was enforcing it programmatically, or a rogue session token that outlived its usefulness: these are infrastructure failures, not strategy failures.&lt;/p&gt;

&lt;p&gt;The same problem gets worse at scale. If you're running multiple sub-accounts on Hyperliquid — one for momentum, one for delta-neutral, one for arb — each account needs its own session, its own policy envelope, and its own audit trail. Managing that manually with raw private keys is a liability waiting to materialize.&lt;/p&gt;

&lt;p&gt;WAIaaS is an open-source, self-hosted Wallet-as-a-Service built specifically for AI agents and automated bots. It gives you a REST API, 45 MCP tools, and a 7-stage transaction pipeline with policy enforcement baked in — so your bot focuses on alpha, not key hygiene.&lt;/p&gt;

&lt;h2&gt;
  
  
  What WAIaaS Brings to Hyperliquid Trading
&lt;/h2&gt;

&lt;p&gt;WAIaaS integrates Hyperliquid directly as one of its 15 DeFi protocol providers. That means perpetual futures, spot trading, and sub-accounts are all accessible through the same session-authenticated REST API your bot already uses for everything else.&lt;/p&gt;

&lt;p&gt;The full protocol list spans aave-v3, across, dcent-swap, drift, erc8004, hyperliquid, jito-staking, jupiter-swap, kamino, lido-staking, lifi, pendle, polymarket, xrpl-dex, and zerox-swap. For a trading bot, that means you can express a complete strategy — long perp on Hyperliquid, hedge spot on Jupiter, bridge collateral via LI.FI — through one API surface with one authentication model.&lt;/p&gt;

&lt;p&gt;No juggling five different SDKs with five different key formats.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Policy Engine: Your Risk Manager in Code
&lt;/h2&gt;

&lt;p&gt;Before we get to execution, let's talk about the piece that matters most for automated systems: enforcing limits programmatically.&lt;/p&gt;

&lt;p&gt;WAIaaS ships a policy engine with 21 policy types and 4 security tiers (INSTANT, NOTIFY, DELAY, APPROVAL). For Hyperliquid specifically, the relevant policies are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;PERP_MAX_LEVERAGE&lt;/code&gt; — hard cap on leverage your bot can set&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PERP_MAX_POSITION_USD&lt;/code&gt; — maximum notional per position&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PERP_ALLOWED_MARKETS&lt;/code&gt; — whitelist of tradeable markets&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SPENDING_LIMIT&lt;/code&gt; — amount-based 4-tier routing for all outgoing value&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;VENUE_WHITELIST&lt;/code&gt; — allowed trading venues&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The system is default-deny: if &lt;code&gt;ALLOWED_TOKENS&lt;/code&gt; or &lt;code&gt;CONTRACT_WHITELIST&lt;/code&gt; isn't configured, transactions are blocked. That's the right default for an autonomous bot. You define exactly what it can touch, and everything else is denied.&lt;/p&gt;

&lt;p&gt;Here's how to set a spending limit with tiered security for a trading wallet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/policies &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "walletId": "&amp;lt;wallet-uuid&amp;gt;",
    "type": "SPENDING_LIMIT",
    "rules": {
      "instant_max_usd": 100,
      "notify_max_usd": 500,
      "delay_max_usd": 2000,
      "delay_seconds": 900,
      "daily_limit_usd": 5000
    }
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this configuration: transactions under $100 execute immediately (INSTANT), $100–$500 execute and notify you (NOTIFY), $500–$2000 queue for 15 minutes before executing (DELAY), and anything above $2000 requires explicit human approval (APPROVAL). Your bot can operate autonomously within its lane, and anything anomalous gets caught before it hits the chain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up a Trading Bot: Step by Step
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Deploy the Daemon
&lt;/h3&gt;

&lt;p&gt;Start with Docker — the image is &lt;code&gt;ghcr.io/minhoyoo-iotrust/waiaas:latest&lt;/code&gt; and binds to &lt;code&gt;127.0.0.1:3100&lt;/code&gt; by default.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/minhoyoo-iotrust/WAIaaS.git
&lt;span class="nb"&gt;cd &lt;/span&gt;WAIaaS
docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For automated deployments, use auto-provision mode to generate the master password without manual input:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; waiaas &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 127.0.0.1:3100:3100 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; waiaas-data:/data &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;WAIAAS_AUTO_PROVISION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  ghcr.io/minhoyoo-iotrust/waiaas:latest

docker &lt;span class="nb"&gt;exec &lt;/span&gt;waiaas &lt;span class="nb"&gt;cat&lt;/span&gt; /data/recovery.key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Create a Trading Wallet and Session
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create a wallet for Hyperliquid trading&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/wallets &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"name": "hyperliquid-perp", "chain": "evm", "environment": "mainnet"}'&lt;/span&gt;

&lt;span class="c"&gt;# Create a session token for the bot&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/sessions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"walletId": "&amp;lt;wallet-uuid&amp;gt;"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The session token (&lt;code&gt;wai_sess_...&lt;/code&gt;) is what your bot uses for all subsequent calls. It's JWT HS256, scoped to a wallet, and has configurable TTL, maxRenewals, and absoluteLifetime. You can run separate sessions for separate sub-account strategies — each session gets its own policy envelope.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Apply Perp-Specific Policies
&lt;/h3&gt;

&lt;p&gt;Before your bot touches Hyperliquid, lock down what it can do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Cap leverage at 10x&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/policies &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "walletId": "&amp;lt;wallet-uuid&amp;gt;",
    "type": "PERP_MAX_LEVERAGE",
    "rules": {"max_leverage": 10}
  }'&lt;/span&gt;

&lt;span class="c"&gt;# Cap max position size&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/policies &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "walletId": "&amp;lt;wallet-uuid&amp;gt;",
    "type": "PERP_MAX_POSITION_USD",
    "rules": {"max_position_usd": 50000}
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Execute a DeFi Action Through the Bot's Session
&lt;/h3&gt;

&lt;p&gt;Once policies are in place, your bot calls the Hyperliquid provider through its session token:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/actions/hyperliquid/&amp;lt;action-name&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer wai_sess_&amp;lt;token&amp;gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{...}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The 7-stage transaction pipeline handles validation, auth check, policy evaluation, optional wait (for DELAY-tier), execution, and confirmation — in that order. Your bot doesn't need to implement any of that logic itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Simulate Before Committing
&lt;/h3&gt;

&lt;p&gt;For strategies where getting the trade wrong is expensive, use dry-run mode to simulate before submitting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/transactions/send &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer wai_sess_&amp;lt;token&amp;gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "type": "TRANSFER",
    "to": "recipient-address",
    "amount": "0.1",
    "dryRun": true
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The simulation runs through the full pipeline — policy checks included — without touching the chain. You get the exact outcome your bot would see on a live submission.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gas Conditional Execution
&lt;/h2&gt;

&lt;p&gt;One detail that matters for algorithmic systems: WAIaaS supports gas conditional execution, meaning transactions only execute when the gas price meets a configured threshold. For bots doing high-frequency or cost-sensitive operations, this is the difference between a profitable trade and a margin-eroded one.&lt;/p&gt;

&lt;p&gt;You define the threshold; the pipeline checks it before execution. If gas is above the limit, the transaction waits. No polling loop in your bot code, no manual gas price checks — the pipeline handles it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-Strategy Architecture with Separate Sessions
&lt;/h2&gt;

&lt;p&gt;Here's a pattern that works well for Hyperliquid sub-account strategies: one WAIaaS daemon, multiple wallets, multiple sessions, each with its own policy set.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WAIaaS Daemon
├── Wallet A (hyperliquid-momentum)
│   ├── Session: bot-momentum-001
│   ├── Policy: PERP_MAX_LEVERAGE = 5x
│   └── Policy: PERP_ALLOWED_MARKETS = BTC-USD, ETH-USD
│
├── Wallet B (hyperliquid-arb)
│   ├── Session: bot-arb-001
│   ├── Policy: PERP_MAX_LEVERAGE = 2x
│   └── Policy: SPENDING_LIMIT = $500 instant / $2000 delay
│
└── Wallet C (hyperliquid-delta-neutral)
    ├── Session: bot-dn-001
    └── Policy: PERP_MAX_POSITION_USD = $25000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each bot process holds its own session token. Policies are enforced independently. If one strategy goes rogue — unexpected order size, wrong market, leverage spike — the policy engine blocks it without affecting the others.&lt;/p&gt;

&lt;h2&gt;
  
  
  TypeScript SDK for Bot Integration
&lt;/h2&gt;

&lt;p&gt;If you'd rather use a typed SDK than raw curl, the TypeScript SDK (&lt;code&gt;@waiaas/sdk&lt;/code&gt;) gives you the same capabilities with async/await and typed errors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;WAIaaSClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;WAIaaSError&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@waiaas/sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WAIaaSClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;WAIAAS_BASE_URL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3100&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;sessionToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;WAIAAS_SESSION_TOKEN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Check balance before opening position&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBalance&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Balance: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;network&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Submit transaction with error handling&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendToken&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TRANSFER&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;recipient-address&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.001&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Poll for confirmation&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;POLL_TIMEOUT_MS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;startTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;startTime&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;POLL_TIMEOUT_MS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;COMPLETED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Confirmed: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;txHash&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;FAILED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Failed: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;WAIaaSError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Structured errors: INSUFFICIENT_BALANCE, POLICY_DENIED, TOKEN_EXPIRED&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`[&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;] &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Python SDK (&lt;code&gt;waiaas&lt;/code&gt;) follows the same pattern with async/await if your bot stack is Python.&lt;/p&gt;

&lt;h2&gt;
  
  
  Human-in-the-Loop for High-Stakes Trades
&lt;/h2&gt;

&lt;p&gt;For positions that exceed your APPROVAL tier threshold, WAIaaS integrates WalletConnect so the fund owner gets a signing request on their mobile wallet. The bot submits the transaction, it queues for approval, and execution only proceeds when the owner signs.&lt;/p&gt;

&lt;p&gt;Three signing channels are available: push-relay, Telegram, and wallet-notification. You configure whichever fits your ops setup. For a trading team running a large book, Telegram notifications for anything above $10k with mobile approval is a sensible pattern — the bot handles everything below that autonomously.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Approve a queued transaction (owner signs off-chain, submits via API)&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/transactions/&amp;lt;tx-id&amp;gt;/approve &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Owner-Signature: &amp;lt;ed25519-or-secp256k1-signature&amp;gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Owner-Message: &amp;lt;signed-message&amp;gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  MCP Integration for AI-Driven Trading
&lt;/h2&gt;

&lt;p&gt;If your trading system uses an LLM layer — Claude, GPT, or any MCP-compatible agent framework — WAIaaS exposes 45 MCP tools covering wallet, transaction, DeFi, NFT, and x402 operations. The &lt;code&gt;hyperliquid&lt;/code&gt; and &lt;code&gt;polymarket&lt;/code&gt; tools are available directly, so an AI agent can reason about positions, execute trades, and query state without custom tool code.&lt;/p&gt;

&lt;p&gt;Setup is one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;waiaas mcp setup &lt;span class="nt"&gt;--all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That auto-registers all wallets with Claude Desktop. For multi-strategy setups, configure separate MCP servers per wallet so each AI agent operates within its own session scope.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;The full API surface — 39 REST route modules with an OpenAPI 3.0 spec and interactive Scalar reference UI at &lt;code&gt;/reference&lt;/code&gt; — is the place to go deep on Hyperliquid-specific action parameters and the complete policy schema. The 683+ test files in the codebase are also worth reading if you want to understand exactly how the pipeline handles edge cases.&lt;/p&gt;

&lt;p&gt;If you're building something where execution reliability and risk containment matter more than convenience, self-hosting WAIaaS gives you full control over the signing layer, the policy engine, and the audit trail — nothing passes through third-party infrastructure.&lt;/p&gt;

&lt;p&gt;Explore the codebase and deploy your own instance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/minhoyoo-iotrust/WAIaaS" rel="noopener noreferrer"&gt;https://github.com/minhoyoo-iotrust/WAIaaS&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Official site&lt;/strong&gt;: &lt;a href="https://waiaas.ai" rel="noopener noreferrer"&gt;https://waiaas.ai&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>defi</category>
      <category>trading</category>
      <category>ai</category>
      <category>solana</category>
    </item>
    <item>
      <title>ALLOWED_TOKENS + CONTRACT_WHITELIST: The Foundation of AI Agent Security</title>
      <dc:creator>Wallet Guy</dc:creator>
      <pubDate>Sun, 21 Jun 2026 10:08:40 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/walletguy/allowedtokens-contractwhitelist-the-foundation-of-ai-agent-security-ha2</link>
      <guid>https://dev.clauneck.workers.dev/walletguy/allowedtokens-contractwhitelist-the-foundation-of-ai-agent-security-ha2</guid>
      <description>&lt;h1&gt;
  
  
  ALLOWED_TOKENS + CONTRACT_WHITELIST: The Foundation of AI Agent Security
&lt;/h1&gt;

&lt;p&gt;Giving an AI agent a wallet without guardrails is like giving a toddler a credit card — the agent might be perfectly capable of executing trades, but one misconfigured prompt or unexpected edge case can drain your funds before you can blink. If you're building anything that lets an AI agent sign transactions on your behalf, the question isn't &lt;em&gt;whether&lt;/em&gt; you need security controls — it's &lt;em&gt;which&lt;/em&gt; controls actually prevent the scenarios that matter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Is a Hard Problem
&lt;/h2&gt;

&lt;p&gt;Most wallet security is designed around human users who behave predictably. You log in, you review a transaction, you click confirm. AI agents don't work that way. They receive instructions in natural language, interpret them, and fire off API calls — sometimes in rapid succession, sometimes for amounts and contracts they've never touched before. A prompt injection in a data source, an overly broad system prompt, or a simple misunderstanding can translate directly into an on-chain transaction.&lt;/p&gt;

&lt;p&gt;The security model has to shift. You can't rely on the agent to know what it shouldn't do. You need a layer that enforces those limits at the infrastructure level, before any transaction reaches the network — regardless of what the agent believes it was asked to do.&lt;/p&gt;

&lt;p&gt;WAIaaS approaches this with three layers between your agent and your funds: session authentication, a policy engine with default-deny enforcement, and human approval channels for high-stakes operations. This post focuses on the two policies that form the foundation of that middle layer: &lt;code&gt;ALLOWED_TOKENS&lt;/code&gt; and &lt;code&gt;CONTRACT_WHITELIST&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Default-Deny Principle
&lt;/h2&gt;

&lt;p&gt;Before getting into specifics, it's worth understanding the default posture. In WAIaaS, the policy engine operates on &lt;strong&gt;default-deny&lt;/strong&gt;: if &lt;code&gt;ALLOWED_TOKENS&lt;/code&gt; or &lt;code&gt;CONTRACT_WHITELIST&lt;/code&gt; is not configured for a wallet, those transaction types are blocked. The agent doesn't get to try and fail — the request never reaches the network.&lt;/p&gt;

&lt;p&gt;This is the opposite of how most systems work. Most systems are default-allow with optional restrictions layered on top. Default-allow is convenient for development and catastrophic for production. Default-deny means you make an explicit decision about every token and every contract your agent is permitted to interact with. Anything outside that explicit list returns a &lt;code&gt;POLICY_DENIED&lt;/code&gt; error immediately.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POLICY_DENIED"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Transaction denied by SPENDING_LIMIT policy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POLICY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"retryable"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The error is not retryable. There is no fallback. The transaction is dead on arrival.&lt;/p&gt;

&lt;h2&gt;
  
  
  ALLOWED_TOKENS: Controlling What the Agent Can Send
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;ALLOWED_TOKENS&lt;/code&gt; is a whitelist of token contracts your agent is permitted to transfer. If a token address isn't on the list, the transaction is blocked — full stop.&lt;/p&gt;

&lt;p&gt;Here's what that policy configuration looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:3100/v1/policies &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'X-Master-Password: &amp;lt;password&amp;gt;'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "walletId": "&amp;lt;wallet-uuid&amp;gt;",
    "type": "ALLOWED_TOKENS",
    "rules": {
      "tokens": [
        {
          "address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
          "symbol": "USDC",
          "chain": "solana"
        }
      ]
    }
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This policy is set via &lt;code&gt;masterAuth&lt;/code&gt; — the system administrator credential authenticated with Argon2id. The AI agent itself, which only holds a &lt;code&gt;sessionAuth&lt;/code&gt; JWT, cannot create or modify policies. That separation is intentional and critical. The agent operates within whatever envelope the operator defines; it has no mechanism to expand that envelope.&lt;/p&gt;

&lt;p&gt;The practical implication: if your agent is a USDC-only treasury bot, you configure exactly one token in &lt;code&gt;ALLOWED_TOKENS&lt;/code&gt;. Any attempt to transfer SOL, any other SPL token, any ERC-20 — denied. Even if the agent is convinced by a user or a data source that it should be doing something else.&lt;/p&gt;

&lt;h2&gt;
  
  
  CONTRACT_WHITELIST: Controlling What the Agent Can Call
&lt;/h2&gt;

&lt;p&gt;Token transfers are only half the picture. DeFi interactions — swaps, lending, staking — go through smart contracts. &lt;code&gt;CONTRACT_WHITELIST&lt;/code&gt; gives you the same default-deny control over contract interactions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:3100/v1/policies &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'X-Master-Password: &amp;lt;password&amp;gt;'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "walletId": "&amp;lt;wallet-uuid&amp;gt;",
    "type": "CONTRACT_WHITELIST",
    "rules": {
      "contracts": [
        {
          "address": "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4",
          "name": "Jupiter",
          "chain": "solana"
        }
      ]
    }
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your agent is authorized to swap via Jupiter, that's the one contract address in the list. An attempt to call any other program — a new DEX, a yield protocol your agent found in some documentation, a contract it was hallucinated into believing exists — hits the whitelist and stops.&lt;/p&gt;

&lt;p&gt;This matters particularly for prompt injection scenarios. A malicious document or API response that tells your agent to "approve spending to 0x[attacker-contract]" can't actually succeed if that address isn't in &lt;code&gt;CONTRACT_WHITELIST&lt;/code&gt;. The policy layer doesn't read natural language; it reads transaction parameters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layering Policies: Defense in Depth
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;ALLOWED_TOKENS&lt;/code&gt; and &lt;code&gt;CONTRACT_WHITELIST&lt;/code&gt; are the access control layer — they define what the agent &lt;em&gt;can&lt;/em&gt; interact with. But WAIaaS gives you additional policies to layer on top of that foundation.&lt;/p&gt;

&lt;p&gt;The policy engine supports 21 policy types in total. For a security-focused deployment, you'd typically combine several:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SPENDING_LIMIT&lt;/strong&gt; adds amount-based tier escalation on top of the token whitelist. Even if USDC is an allowed token, you can require human approval for transfers above a certain threshold:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:3100/v1/policies &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'X-Master-Password: &amp;lt;password&amp;gt;'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "walletId": "&amp;lt;wallet-uuid&amp;gt;",
    "type": "SPENDING_LIMIT",
    "rules": {
      "instant_max_usd": 10,
      "notify_max_usd": 100,
      "delay_max_usd": 1000,
      "delay_seconds": 300,
      "daily_limit_usd": 500,
      "monthly_limit_usd": 5000
    }
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The four security tiers work like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;INSTANT&lt;/strong&gt; — execute immediately, no notification&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NOTIFY&lt;/strong&gt; — execute immediately, send you a notification&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DELAY&lt;/strong&gt; — queue the transaction for &lt;code&gt;delay_seconds&lt;/code&gt;, then execute (you can cancel it during that window)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;APPROVAL&lt;/strong&gt; — full stop, requires your explicit approval via WalletConnect, Telegram, or push notification&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;APPROVED_SPENDERS&lt;/strong&gt; closes a common attack vector: token approvals. An AI agent managing DeFi positions will sometimes need to call &lt;code&gt;approve()&lt;/code&gt; to allow a protocol to spend tokens on its behalf. &lt;code&gt;APPROVED_SPENDERS&lt;/code&gt; applies default-deny to that operation — only whitelisted addresses can be approved, and you can cap the maximum approval amount:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"spenders"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0xDEF1..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Uniswap Router"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"maxAmount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1000000000"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;APPROVE_AMOUNT_LIMIT&lt;/strong&gt; and &lt;strong&gt;APPROVE_TIER_OVERRIDE&lt;/strong&gt; give you further control over approval transactions specifically — blocking unlimited approvals and forcing them through the APPROVAL tier regardless of dollar amount.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Three-Layer Architecture
&lt;/h2&gt;

&lt;p&gt;Zooming out, the full security model has three layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Session authentication&lt;/strong&gt; — AI agents authenticate with JWT session tokens (&lt;code&gt;sessionAuth&lt;/code&gt;). Sessions have configurable TTL, maximum renewals, and absolute lifetime. The agent can't extend its own session or escalate its own permissions. Session creation is &lt;code&gt;masterAuth&lt;/code&gt; only.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Policy engine&lt;/strong&gt; — The 7-stage transaction pipeline runs every transaction through validation, authentication, and policy enforcement before execution. Policies are evaluated in the &lt;code&gt;stage3-policy&lt;/code&gt; stage. A &lt;code&gt;POLICY_DENIED&lt;/code&gt; result terminates the pipeline immediately.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Human approval channels&lt;/strong&gt; — Transactions that reach the APPROVAL tier don't execute until you sign off. WAIaaS supports WalletConnect integration for owner approval, with the owner authenticating via &lt;code&gt;ownerAuth&lt;/code&gt; (SIWE for EVM, SIWS for Solana). There are 3 signing channels available: push-relay, Telegram, and wallet notification.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These layers are independent. Compromising the session token doesn't let an attacker bypass policy. Bypassing policy would require &lt;code&gt;masterAuth&lt;/code&gt; credentials, which aren't exposed to the agent at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simulating Before You Deploy
&lt;/h2&gt;

&lt;p&gt;Before putting any of this in production, you should verify that your policies behave the way you expect them to. WAIaaS has a dry-run API for exactly this purpose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/transactions/send &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer wai_sess_&amp;lt;token&amp;gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "type": "TRANSFER",
    "to": "recipient-address",
    "amount": "0.1",
    "dryRun": true
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;dryRun: true&lt;/code&gt;, the transaction runs through the full pipeline — validation, policy evaluation, simulation — but never broadcasts to the network. You get back the same response structure you'd get from a real transaction, including any policy denials. This lets you confirm that your &lt;code&gt;ALLOWED_TOKENS&lt;/code&gt; and &lt;code&gt;CONTRACT_WHITELIST&lt;/code&gt; configurations are actually blocking what you think they're blocking before real funds are involved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Start: Securing Your First Agent Wallet
&lt;/h2&gt;

&lt;p&gt;Here's the minimal path to a policy-hardened agent wallet:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Start WAIaaS&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @waiaas/cli
waiaas init
waiaas start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: Create a wallet and session&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/wallets &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"name": "trading-wallet", "chain": "solana", "environment": "mainnet"}'&lt;/span&gt;

curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/sessions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"walletId": "&amp;lt;wallet-uuid&amp;gt;"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3: Apply ALLOWED_TOKENS&lt;/strong&gt; — whitelist only the tokens your agent needs&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:3100/v1/policies &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'X-Master-Password: &amp;lt;password&amp;gt;'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "walletId": "&amp;lt;wallet-uuid&amp;gt;",
    "type": "ALLOWED_TOKENS",
    "rules": {
      "tokens": [{"address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "symbol": "USDC", "chain": "solana"}]
    }
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4: Apply CONTRACT_WHITELIST&lt;/strong&gt; — whitelist only the contracts your agent needs to call&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Test with dry-run&lt;/strong&gt; — confirm policy denials work before going live, using the &lt;code&gt;dryRun: true&lt;/code&gt; flag shown above.&lt;/p&gt;

&lt;p&gt;The session token goes to your agent. The master password stays with you. Your agent now operates in an explicitly defined envelope, and anything outside that envelope fails fast with a clear error code.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Looks Like at Runtime
&lt;/h2&gt;

&lt;p&gt;Once your agent is running with the TypeScript SDK, the security layer is invisible when everything is authorized — and loud when it isn't:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;WAIaaSClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;WAIaaSError&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@waiaas/sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WAIaaSClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;WAIAAS_BASE_URL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3100&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;sessionToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;WAIAAS_SESSION_TOKEN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendToken&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;WAIaaSError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`API Error: [&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;] &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// error.code examples: INSUFFICIENT_BALANCE, POLICY_DENIED, TOKEN_EXPIRED&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;code&gt;POLICY_DENIED&lt;/code&gt; error with &lt;code&gt;retryable: false&lt;/code&gt; means the policy engine caught it. The transaction never left your machine. You have a complete audit trail in the daemon logs, and your funds are untouched.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Honest Assessment
&lt;/h2&gt;

&lt;p&gt;No security system is perfect. WAIaaS's policy engine operates at the transaction level — it enforces rules about &lt;em&gt;what&lt;/em&gt; gets signed and sent, not about &lt;em&gt;why&lt;/em&gt; your agent decided to send it. If your agent is given legitimate authorization to transfer USDC to a whitelisted address, and it does so because it was manipulated, that transaction will execute.&lt;/p&gt;

&lt;p&gt;The value of &lt;code&gt;ALLOWED_TOKENS&lt;/code&gt; and &lt;code&gt;CONTRACT_WHITELIST&lt;/code&gt; is that they constrain the blast radius. A compromised agent with a narrow token whitelist and a small spending limit can do far less damage than one with no policy controls at all. The DELAY tier gives you a cancellation window. The APPROVAL tier requires you to be in the loop entirely.&lt;/p&gt;

&lt;p&gt;Layer these with sensible system prompts, conservative spending limits, and regular review of your agent's transaction history. The policy engine is one part of a broader security practice, not a substitute for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;The full OpenAPI 3.0 spec for WAIaaS is available at &lt;code&gt;http://127.0.0.1:3100/doc&lt;/code&gt;, with an interactive reference UI at &lt;code&gt;/reference&lt;/code&gt; — useful for exploring the complete policy configuration surface. The codebase is open source, so you can review exactly how the 7-stage transaction pipeline evaluates policies before trusting it with real funds.&lt;/p&gt;

&lt;p&gt;If you're ready to go further, the GitHub repository is at &lt;strong&gt;&lt;a href="https://github.com/minhoyoo-iotrust/WAIaaS" rel="noopener noreferrer"&gt;https://github.com/minhoyoo-iotrust/WAIaaS&lt;/a&gt;&lt;/strong&gt; and the official site is at &lt;strong&gt;&lt;a href="https://waiaas.ai" rel="noopener noreferrer"&gt;https://waiaas.ai&lt;/a&gt;&lt;/strong&gt;. Both have the current documentation and deployment guides for getting a hardened instance running in production.&lt;/p&gt;

</description>
      <category>security</category>
      <category>ai</category>
      <category>blockchain</category>
      <category>web3</category>
    </item>
    <item>
      <title>Zero-Config Docker Deployment: Auto-Provisioning Your Self-Hosted Crypto Wallet</title>
      <dc:creator>Wallet Guy</dc:creator>
      <pubDate>Sat, 20 Jun 2026 15:09:35 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/walletguy/zero-config-docker-deployment-auto-provisioning-your-self-hosted-crypto-wallet-293n</link>
      <guid>https://dev.clauneck.workers.dev/walletguy/zero-config-docker-deployment-auto-provisioning-your-self-hosted-crypto-wallet-293n</guid>
      <description>&lt;h1&gt;
  
  
  Zero-Config Docker Deployment: Auto-Provisioning Your Self-Hosted Crypto Wallet
&lt;/h1&gt;

&lt;p&gt;Docker makes running your own self-hosted crypto wallet infrastructure surprisingly approachable — no third-party custody, no rate limits, no one else holding your AI agent's private keys. If you've ever asked yourself whether you'd trust a hosted service with keys that control real funds on behalf of an autonomous agent, you already know the answer. This post walks through how WAIaaS handles the hardest part of self-hosting: that first-run setup that usually trips people up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Would You Hand a Stranger Your Keys?
&lt;/h2&gt;

&lt;p&gt;Here's the uncomfortable truth about most "Wallet-as-a-Service" offerings: when you use a hosted provider, someone else generates, stores, and ultimately controls the cryptographic keys that sign your transactions. For personal wallets, that's a familiar trade-off. For AI agents that transact autonomously — potentially 24/7, across DeFi protocols, with real funds — it's a much bigger bet.&lt;/p&gt;

&lt;p&gt;The self-hosted alternative has traditionally meant accepting a painful setup process: generating keys manually, configuring secure storage, wiring up RPC endpoints, building your own policy layer. Most developers give up and go back to the hosted option. WAIaaS is designed to eliminate that gap. You get the sovereignty of self-hosting with a setup experience that doesn't require a weekend.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Self-Hosting Philosophy
&lt;/h2&gt;

&lt;p&gt;Running your own infrastructure is the crypto equivalent of hosting your own email server — except in 2026, Docker has made this actually practical rather than aspirational. When you self-host WAIaaS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your private keys never leave your machine&lt;/li&gt;
&lt;li&gt;No third party can rate-limit, suspend, or inspect your agent's transactions&lt;/li&gt;
&lt;li&gt;You control the upgrade cycle — nothing changes unless you choose to update&lt;/li&gt;
&lt;li&gt;Your data (transaction history, policy configs, session tokens) stays on your hardware&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This matters especially for AI agents. An autonomous trading agent or a workflow bot that handles payments needs a wallet backend it can rely on without external dependencies introducing latency, outages, or policy changes outside your control.&lt;/p&gt;

&lt;p&gt;WAIaaS is open-source and built as a 15-package monorepo. The Docker image — &lt;code&gt;ghcr.io/minhoyoo-iotrust/waiaas:latest&lt;/code&gt; — packages the daemon that handles everything: key management, policy enforcement, DeFi protocol integrations, MCP tools for AI frameworks, and the REST API your agents call.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Auto-Provision Feature: Zero First-Run Friction
&lt;/h2&gt;

&lt;p&gt;The single biggest barrier to self-hosting any secrets-management service is the bootstrap problem: you need a master password before you can do anything, but generating and storing that password securely is exactly the kind of thing people get wrong.&lt;/p&gt;

&lt;p&gt;WAIaaS solves this with &lt;code&gt;WAIAAS_AUTO_PROVISION&lt;/code&gt;. When this environment variable is set to &lt;code&gt;true&lt;/code&gt;, the daemon generates a cryptographically random master password on first start, writes it to &lt;code&gt;/data/recovery.key&lt;/code&gt;, and continues without waiting for human input. You retrieve the password after startup and store it somewhere safe.&lt;/p&gt;

&lt;p&gt;Here's the single-container version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; waiaas &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 127.0.0.1:3100:3100 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; waiaas-data:/data &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;WAIAAS_AUTO_PROVISION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  ghcr.io/minhoyoo-iotrust/waiaas:latest

&lt;span class="c"&gt;# Retrieve auto-generated master password&lt;/span&gt;
docker &lt;span class="nb"&gt;exec &lt;/span&gt;waiaas &lt;span class="nb"&gt;cat&lt;/span&gt; /data/recovery.key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the port binding: &lt;code&gt;127.0.0.1:3100:3100&lt;/code&gt;. This is intentional — the daemon listens only on localhost by default, so it's not exposed to the network until you explicitly decide otherwise. That's the right default for a service that controls signing keys.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker Compose: The Practical Setup
&lt;/h2&gt;

&lt;p&gt;For anything beyond a quick test, Docker Compose is the right approach. WAIaaS ships a &lt;code&gt;docker-compose.yml&lt;/code&gt; you can use directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;daemon&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghcr.io/minhoyoo-iotrust/waiaas:latest&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;waiaas-daemon&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;127.0.0.1:3100:3100"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;waiaas-data:/data&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;WAIAAS_DATA_DIR=/data&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;WAIAAS_DAEMON_HOSTNAME=0.0.0.0&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.env&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;healthcheck&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CMD"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;curl"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-f"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://localhost:3100/health"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;30s&lt;/span&gt;
      &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5s&lt;/span&gt;
      &lt;span class="na"&gt;start_period&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10s&lt;/span&gt;
      &lt;span class="na"&gt;retries&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;waiaas-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;local&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few things worth noting here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Named volume for data persistence.&lt;/strong&gt; &lt;code&gt;waiaas-data&lt;/code&gt; is a Docker-managed named volume. This means &lt;code&gt;docker compose down&lt;/code&gt; preserves your wallets and transaction history. You'd need &lt;code&gt;docker compose down -v&lt;/code&gt; to actually delete data — a deliberate extra step that prevents accidental key loss.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Built-in healthcheck.&lt;/strong&gt; The compose file includes a healthcheck that polls &lt;code&gt;/health&lt;/code&gt; every 30 seconds. This integrates naturally with Docker's restart policies and with monitoring tools in a homelab setup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The daemon runs as UID 1001 (non-root).&lt;/strong&gt; This is a security default baked into the Docker image — the process doesn't have root privileges inside the container.&lt;/p&gt;

&lt;p&gt;Getting started with Compose is three commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/minhoyoo-iotrust/WAIaaS.git
&lt;span class="nb"&gt;cd &lt;/span&gt;WAIaaS
docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Production Secrets: Docker Secrets Overlay
&lt;/h2&gt;

&lt;p&gt;For a homelab or production deployment where you want proper secrets management, WAIaaS supports Docker Secrets via a &lt;code&gt;docker-compose.secrets.yml&lt;/code&gt; overlay. This keeps your master password out of environment variables entirely:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create secret files&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; secrets
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"your-secure-password"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; secrets/master_password.txt
&lt;span class="nb"&gt;chmod &lt;/span&gt;600 secrets/master_password.txt

&lt;span class="c"&gt;# Deploy with secrets overlay&lt;/span&gt;
docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.yml &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.secrets.yml up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The secrets overlay pattern means your actual credentials never appear in &lt;code&gt;docker inspect&lt;/code&gt; output, shell history, or &lt;code&gt;.env&lt;/code&gt; files that might accidentally get committed to version control. For anyone running a homelab where the threat model includes shared machines or accidentally public repositories, this is worth the extra step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Environment Variables
&lt;/h2&gt;

&lt;p&gt;The daemon is configured entirely through environment variables — no config files to manually edit before first boot. The most important ones:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;WAIAAS_AUTO_PROVISION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;              &lt;span class="c"&gt;# Auto-generate master password on first start&lt;/span&gt;
&lt;span class="nv"&gt;WAIAAS_DAEMON_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3100                 &lt;span class="c"&gt;# Listening port&lt;/span&gt;
&lt;span class="nv"&gt;WAIAAS_DAEMON_HOSTNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.0.0.0         &lt;span class="c"&gt;# Bind address&lt;/span&gt;
&lt;span class="nv"&gt;WAIAAS_DAEMON_LOG_LEVEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;info            &lt;span class="c"&gt;# Log level (trace/debug/info/warn/error)&lt;/span&gt;
&lt;span class="nv"&gt;WAIAAS_DATA_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/data                   &lt;span class="c"&gt;# Data directory&lt;/span&gt;
&lt;span class="nv"&gt;WAIAAS_RPC_SOLANA_MAINNET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;url&amp;gt;         &lt;span class="c"&gt;# Solana mainnet RPC endpoint&lt;/span&gt;
&lt;span class="nv"&gt;WAIAAS_RPC_EVM_ETHEREUM_MAINNET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;url&amp;gt;   &lt;span class="c"&gt;# Ethereum mainnet RPC endpoint&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The RPC endpoint variables are where you plug in your own node URLs — Alchemy, QuickNode, your own Geth instance, whatever fits your setup. This is another sovereignty point: you're not locked into any particular RPC provider.&lt;/p&gt;

&lt;h2&gt;
  
  
  From Container to Working Wallet: The Quick Path
&lt;/h2&gt;

&lt;p&gt;Once the container is running, you need to create a wallet and give your AI agent a session token. This is where the three-layer auth model comes in. There's a master password (for admin operations like creating wallets and setting policies), owner auth (for approving high-stakes transactions via WalletConnect or similar), and session tokens (what your AI agent actually uses for day-to-day operations).&lt;/p&gt;

&lt;p&gt;Create a wallet with the master password:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/wallets &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"name": "trading-wallet", "chain": "solana", "environment": "mainnet"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a session token for your agent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/sessions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"walletId": "&amp;lt;wallet-uuid&amp;gt;"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your agent can check its balance using just the session token — the master password never touches agent code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://127.0.0.1:3100/v1/wallet/balance &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer wai_sess_eyJhbGciOiJIUzI1NiJ9..."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This separation matters. The session token is scoped to one wallet, subject to whatever policies you've set, and can be revoked without touching the underlying key material.&lt;/p&gt;

&lt;h2&gt;
  
  
  Policies: The Safety Layer You Set Once
&lt;/h2&gt;

&lt;p&gt;Self-hosting means you're also responsible for setting the guardrails. WAIaaS has a policy engine with 21 policy types and a default-deny stance: if &lt;code&gt;ALLOWED_TOKENS&lt;/code&gt; or &lt;code&gt;CONTRACT_WHITELIST&lt;/code&gt; aren't configured, transactions are blocked by default.&lt;/p&gt;

&lt;p&gt;A basic spending limit policy looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/policies &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "walletId": "&amp;lt;wallet-uuid&amp;gt;",
    "type": "SPENDING_LIMIT",
    "rules": {
      "instant_max_usd": 100,
      "notify_max_usd": 500,
      "delay_max_usd": 2000,
      "delay_seconds": 900,
      "daily_limit_usd": 5000
    }
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates four tiers of behavior: under $100 executes immediately, $100-$500 executes and notifies you, $500-$2000 waits 15 minutes before executing (giving you a cancellation window), and anything over $2000 requires your explicit approval. You set this once and the daemon enforces it on every transaction your agent submits — no matter what the agent asks for.&lt;/p&gt;

&lt;p&gt;The 4 security tiers — INSTANT, NOTIFY, DELAY, and APPROVAL — map to real threat scenarios. An agent that accidentally goes rogue, a bug that causes runaway transactions, or a prompt injection attack that tries to drain a wallet all get caught at different tiers depending on the amount involved.&lt;/p&gt;

&lt;h2&gt;
  
  
  CLI Alternative: Even Faster Setup
&lt;/h2&gt;

&lt;p&gt;If you prefer the CLI over raw curl commands, the &lt;code&gt;@waiaas/cli&lt;/code&gt; package wraps all of this into a few commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @waiaas/cli
waiaas init &lt;span class="nt"&gt;--auto-provision&lt;/span&gt;     &lt;span class="c"&gt;# Generates random master password → recovery.key&lt;/span&gt;
waiaas start                     &lt;span class="c"&gt;# No password prompt&lt;/span&gt;
waiaas quickset                  &lt;span class="c"&gt;# Creates wallets + sessions automatically&lt;/span&gt;
waiaas set-master                &lt;span class="c"&gt;# (Later) Harden password, then delete recovery.key&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CLI has 20 commands covering everything from backup and restore to MCP setup and notification configuration. For anyone who finds curl-based setup tedious, this is the faster path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Operations
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;          &lt;span class="c"&gt;# Start daemon&lt;/span&gt;
docker compose logs &lt;span class="nt"&gt;-f&lt;/span&gt;        &lt;span class="c"&gt;# Follow logs&lt;/span&gt;
docker compose down           &lt;span class="c"&gt;# Stop (data preserved in named volume)&lt;/span&gt;
docker compose down &lt;span class="nt"&gt;-v&lt;/span&gt;        &lt;span class="c"&gt;# Stop + delete data volume&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The interactive API reference is available at &lt;code&gt;http://127.0.0.1:3100/reference&lt;/code&gt; once the daemon is running — useful for exploring the 39 REST API route modules without leaving the browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Self-Hosting Is Actually Practical Now
&lt;/h2&gt;

&lt;p&gt;Three things have changed that make self-hosting crypto wallet infrastructure reasonable in 2026:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Docker has solved the environment problem.&lt;/strong&gt; The same image runs the same way on a Raspberry Pi 5, a homelab server, or a cloud VPS. You're not debugging library versions or system dependencies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Auto-provisioning has solved the bootstrap problem.&lt;/strong&gt; The hardest part of setting up any secrets management service used to be the first run. &lt;code&gt;WAIAAS_AUTO_PROVISION=true&lt;/code&gt; eliminates that entirely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The policy layer handles the "what if the agent goes wrong" problem.&lt;/strong&gt; The default-deny stance and the 4-tier spending limit system mean you can hand an agent a session token without losing sleep about what it might do with it.&lt;/p&gt;

&lt;p&gt;The result is a setup that genuinely takes one afternoon, produces a running system you fully control, and doesn't require ongoing maintenance beyond occasional updates (which Docker handles automatically if you configure Watchtower).&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Start Summary
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Clone the repo and run &lt;code&gt;docker compose up -d&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;WAIAAS_AUTO_PROVISION=true&lt;/code&gt; to your environment or &lt;code&gt;.env&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;Retrieve the generated master password from &lt;code&gt;/data/recovery.key&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Create a wallet and session token via the REST API or CLI&lt;/li&gt;
&lt;li&gt;Set a spending limit policy before handing the session token to your agent&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's the full path from zero to a running, policy-enforced, self-hosted wallet backend.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;The REST API documentation is auto-generated and available at &lt;code&gt;/reference&lt;/code&gt; on your running instance — it's the fastest way to explore what's available across all 39 route modules. If you're planning to connect an AI agent via Claude Desktop or another MCP-compatible framework, the 45 MCP tools in &lt;code&gt;@waiaas/mcp&lt;/code&gt; are the next thing to look at. And if you want to go deeper on keeping your agent's spending within safe boundaries, the full policy engine — all 21 policy types — is worth reading through before you go to production.&lt;/p&gt;

&lt;p&gt;The project is on GitHub at &lt;a href="https://github.com/minhoyoo-iotrust/WAIaaS" rel="noopener noreferrer"&gt;https://github.com/minhoyoo-iotrust/WAIaaS&lt;/a&gt; and the official site is at &lt;a href="https://waiaas.ai" rel="noopener noreferrer"&gt;https://waiaas.ai&lt;/a&gt;. Both are good starting points depending on whether you want to read code or documentation first.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>selfhosted</category>
      <category>devops</category>
      <category>web3</category>
    </item>
    <item>
      <title>The Payment Layer for Autonomous AI: Building Economic Infrastructure for Agent Commerce</title>
      <dc:creator>Wallet Guy</dc:creator>
      <pubDate>Sat, 20 Jun 2026 09:46:23 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/walletguy/the-payment-layer-for-autonomous-ai-building-economic-infrastructure-for-agent-commerce-49ck</link>
      <guid>https://dev.clauneck.workers.dev/walletguy/the-payment-layer-for-autonomous-ai-building-economic-infrastructure-for-agent-commerce-49ck</guid>
      <description>&lt;h1&gt;
  
  
  The Payment Layer for Autonomous AI: Building Economic Infrastructure for Agent Commerce
&lt;/h1&gt;

&lt;p&gt;AI agents will need to pay for compute, data, and API calls — and the infrastructure to let them do that autonomously exists today. Not as a concept paper, not as a whitepaper with a 2027 roadmap, but as working, self-hosted software you can run in a Docker container this afternoon. The question isn't whether AI agents will participate in economic activity. The question is what the payment layer looks like when they do.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem Nobody Is Talking About Yet
&lt;/h2&gt;

&lt;p&gt;There's a gap in how we build AI agent systems that becomes obvious the moment an agent needs to do something that costs money.&lt;/p&gt;

&lt;p&gt;Today, when an AI agent needs to call a paid API, swap tokens, pay for compute, or move funds on behalf of a user, one of a few things happens: a human manually approves every transaction, the agent uses a shared custodied account that nobody really controls, or the whole capability gets punted — "we'll add payments later."&lt;/p&gt;

&lt;p&gt;None of these are good answers. The first doesn't scale. The second is a security nightmare. The third means your agent is fundamentally limited to free operations.&lt;/p&gt;

&lt;p&gt;The deeper issue is structural. We've built incredible reasoning and planning capabilities into AI agents, but we haven't built the economic infrastructure that would let them act on those plans when acting costs money. An agent that can identify the best DeFi yield opportunity but can't execute a swap isn't an autonomous agent — it's an expensive suggestion engine.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Autonomous Wallet Infrastructure Actually Requires
&lt;/h2&gt;

&lt;p&gt;Let's be specific about what "a wallet for an AI agent" actually needs to do, because it's more than just holding keys.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The agent needs to act independently within defined limits.&lt;/strong&gt; This is the core tension. You want the agent to be able to execute transactions without asking for human permission every time — that's the whole point. But you also need hard guarantees about what it can and can't do. These aren't contradictory requirements; they need a policy engine that enforces rules at the infrastructure layer, not at the application layer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The human owner needs real oversight without becoming a bottleneck.&lt;/strong&gt; There's a spectrum between "approve every transaction" and "trust the agent completely." Good infrastructure needs to support the whole spectrum — instant execution for small trusted operations, notifications for medium operations, time delays for large operations, and mandatory human approval for anything above a threshold.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The infrastructure needs to speak the protocols that autonomous payments require.&lt;/strong&gt; Agents paying for API calls need HTTP-level payment protocols. Agents operating across chains need cross-chain bridging. Agents using DeFi need protocol integrations that understand lending, staking, and swaps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Everything needs to be auditable.&lt;/strong&gt; When an agent takes an economic action, there needs to be a complete record. Not for regulatory compliance (though that matters too) — for debugging, for trust-building, and for the basic engineering requirement of knowing what your system did and why.&lt;/p&gt;

&lt;p&gt;WAIaaS is built around exactly these requirements. It's an open-source, self-hosted Wallet-as-a-Service designed specifically for the case where AI agents are the primary actors.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Three-Layer Security Model
&lt;/h2&gt;

&lt;p&gt;The security architecture in WAIaaS reflects a specific philosophy: agents should be able to act autonomously, but within hard limits that humans set and can always override.&lt;/p&gt;

&lt;p&gt;There are three authentication tiers, each representing a different principal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# masterAuth — system administrator (wallet creation, session management, policies)&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt;

&lt;span class="c"&gt;# sessionAuth — AI agent (transactions, balance queries, DeFi actions)&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer wai_sess_eyJhbGciOiJIUzI1NiJ9..."&lt;/span&gt;

&lt;span class="c"&gt;# ownerAuth — fund owner (transaction approval, kill switch recovery)&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Owner-Signature: &amp;lt;ed25519-or-secp256k1-signature&amp;gt;"&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Owner-Message: &amp;lt;signed-message&amp;gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;master password&lt;/strong&gt; is for the system operator — creating wallets, managing sessions, configuring policies. Think of it as the infrastructure admin role.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;session token&lt;/strong&gt; is what the AI agent holds. It can execute transactions, query balances, call DeFi protocols — but only within whatever policies the master has configured. This is the credential your agent code uses.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;owner signature&lt;/strong&gt; is cryptographic proof from the human who owns the funds — using SIWS (Solana) or SIWE (Ethereum). This can't be faked by software. It's the human's key, and it's what's required to approve transactions that exceed the agent's autonomous limits or to trigger recovery.&lt;/p&gt;

&lt;p&gt;This maps cleanly onto the actual principals in an AI agent system. The operator who deploys the agent isn't the same person as the end user who owns the funds, and the agent itself is a third party that neither fully trusts.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Policy Engine: Programmable Limits
&lt;/h2&gt;

&lt;p&gt;The policy system is where the interesting infrastructure work lives. WAIaaS supports 21 policy types with 4 security tiers — and it operates with default-deny semantics.&lt;/p&gt;

&lt;p&gt;Default-deny means if you haven't explicitly allowed something, it's blocked. An agent without an &lt;code&gt;ALLOWED_TOKENS&lt;/code&gt; policy configured can't transfer tokens. An agent without a &lt;code&gt;CONTRACT_WHITELIST&lt;/code&gt; can't call contracts. This is the right default for autonomous systems where mistakes are expensive and irreversible.&lt;/p&gt;

&lt;p&gt;The four security tiers map to the spectrum from "execute immediately" to "require human approval":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INSTANT   — Execute immediately, no notification
NOTIFY    — Execute immediately, send notification
DELAY     — Queue for delay_seconds, then execute (cancellable)
APPROVAL  — Require human approval via WalletConnect/Telegram/Push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;code&gt;SPENDING_LIMIT&lt;/code&gt; policy assigns tiers based on transaction amount:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/policies &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "walletId": "&amp;lt;wallet-uuid&amp;gt;",
    "type": "SPENDING_LIMIT",
    "rules": {
      "instant_max_usd": 100,
      "notify_max_usd": 500,
      "delay_max_usd": 2000,
      "delay_seconds": 900,
      "daily_limit_usd": 5000
    }
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this configuration, a $50 transaction executes immediately. A $300 transaction executes with a notification. A $1,500 transaction queues for 15 minutes before executing — giving the owner time to cancel if something looks wrong. Anything over $2,000 requires explicit human approval.&lt;/p&gt;

&lt;p&gt;This isn't just spending limits. The full policy set covers DeFi-specific risks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;LENDING_LTV_LIMIT&lt;/code&gt; — caps the loan-to-value ratio an agent can take on in lending protocols&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PERP_MAX_LEVERAGE&lt;/code&gt; — prevents an agent from opening overleveraged perpetual futures positions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PERP_MAX_POSITION_USD&lt;/code&gt; — hard cap on position size&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;APPROVED_SPENDERS&lt;/code&gt; — controls which contracts can be approved to spend tokens (critical for preventing drainer approvals)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;REPUTATION_THRESHOLD&lt;/code&gt; — ERC-8004 onchain reputation gating&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These aren't generic finance policies bolted onto a crypto wallet. They reflect the specific risk surface of autonomous agents operating in DeFi.&lt;/p&gt;

&lt;h2&gt;
  
  
  x402: The HTTP Payment Protocol
&lt;/h2&gt;

&lt;p&gt;One of the most interesting capabilities in WAIaaS is x402 support — an HTTP payment protocol where AI agents automatically pay for API calls.&lt;/p&gt;

&lt;p&gt;The x402 protocol works at the HTTP level. When an agent requests a resource that requires payment, the server returns a 402 Payment Required response. The agent's wallet infrastructure handles the payment automatically and retries the request with proof of payment.&lt;/p&gt;

&lt;p&gt;From the agent's perspective, this is a transparent operation. The agent calls an API; the wallet layer handles the economics. This is exactly the right abstraction for autonomous systems — the agent shouldn't need to know about payment mechanics any more than it needs to know about TCP/IP.&lt;/p&gt;

&lt;p&gt;For a developer building an agent that consumes paid APIs, the MCP tool &lt;code&gt;x402-fetch&lt;/code&gt; exposes this capability directly, and the TypeScript SDK includes &lt;code&gt;x402Fetch()&lt;/code&gt; for programmatic use. The policy type &lt;code&gt;X402_ALLOWED_DOMAINS&lt;/code&gt; lets you define a whitelist of domains where automatic payment is permitted — so the agent can't be tricked into paying for arbitrary endpoints.&lt;/p&gt;

&lt;p&gt;This is the infrastructure primitive that makes "agents that pay for what they use" real. Not a concept. Working today.&lt;/p&gt;

&lt;h2&gt;
  
  
  DeFi as a Native Capability
&lt;/h2&gt;

&lt;p&gt;WAIaaS integrates 15 DeFi protocol providers. For an autonomous agent, this means DeFi operations aren't special cases that require custom integration work — they're just actions the agent can take through the standard session token interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/actions/jupiter-swap/swap &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer wai_sess_&amp;lt;token&amp;gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "inputMint": "So11111111111111111111111111111111111111112",
    "outputMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
    "amount": "1000000000"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The integrated protocols cover the major categories of DeFi activity: swaps (Jupiter, ZeroX, D'CENT, LI.FI), cross-chain bridging (LI.FI, Across), lending (Aave v3, Kamino), liquid staking (Lido for EVM, Jito for Solana), perpetual futures (Hyperliquid, Drift), yield (Pendle), and prediction markets (Polymarket). All of this is available through the same session token your agent already holds.&lt;/p&gt;

&lt;p&gt;The 7-stage transaction pipeline handles the full lifecycle: validation → authentication → policy check → wait (for delay-tier transactions) → execute → confirm. The gas conditional execution feature means transactions can be queued to execute only when gas prices meet a threshold — useful for agents that are cost-sensitive about when they execute.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting Agents to Wallets: Three Integration Paths
&lt;/h2&gt;

&lt;p&gt;WAIaaS supports three ways for an agent to interact with its wallet, depending on how you're building.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MCP (Model Context Protocol)&lt;/strong&gt; is the integration path for conversational AI like Claude. WAIaaS provides 45 MCP tools covering wallet operations, transactions, DeFi, NFTs, and x402 payments. Setup is a single command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;waiaas mcp setup &lt;span class="nt"&gt;--all&lt;/span&gt;    &lt;span class="c"&gt;# Auto-register all wallets with Claude Desktop&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, Claude can check balances, send tokens, and execute DeFi actions directly from conversation. The MCP tools enforce the same policy engine — Claude can't do anything the agent's session token isn't authorized to do.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The TypeScript and Python SDKs&lt;/strong&gt; are the path for agents built in code. The TypeScript SDK (&lt;code&gt;@waiaas/sdk&lt;/code&gt;) has 40+ methods. The Python SDK (&lt;code&gt;waiaas&lt;/code&gt;) is async/await native. Both are zero-external-dependency libraries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;WAIaaSClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@waiaas/sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WAIaaSClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://127.0.0.1:3100&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;sessionToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WAIAAS_SESSION_TOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBalance&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendToken&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;recipient-address...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The REST API&lt;/strong&gt; is the path for any agent framework or language. The 39 API route modules cover everything from wallet management to DeFi positions to NFT operations. There's an OpenAPI 3.0 spec auto-generated at &lt;code&gt;/doc&lt;/code&gt; and an interactive Scalar API reference at &lt;code&gt;/reference&lt;/code&gt; — so any agent framework with HTTP capability can integrate without a dedicated SDK.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running It: Self-Hosted in Minutes
&lt;/h2&gt;

&lt;p&gt;Self-hosted is a deliberate choice in WAIaaS's design. For agents handling real economic activity, the infrastructure should be under the operator's control. Keys, transaction history, and policy configuration don't belong in someone else's cloud.&lt;/p&gt;

&lt;p&gt;The deployment path is straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/minhoyoo-iotrust/WAIaaS.git
&lt;span class="nb"&gt;cd &lt;/span&gt;WAIaaS
docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Docker image is &lt;code&gt;ghcr.io/minhoyoo-iotrust/waiaas:latest&lt;/code&gt;, binding to &lt;code&gt;127.0.0.1:3100&lt;/code&gt; by default — localhost only, not exposed to the internet. The entrypoint supports auto-provisioning for unattended deployments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; waiaas &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 127.0.0.1:3100:3100 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; waiaas-data:/data &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;WAIAAS_AUTO_PROVISION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  ghcr.io/minhoyoo-iotrust/waiaas:latest

docker &lt;span class="nb"&gt;exec &lt;/span&gt;waiaas &lt;span class="nb"&gt;cat&lt;/span&gt; /data/recovery.key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For production, Docker Secrets overlay via &lt;code&gt;docker-compose.secrets.yml&lt;/code&gt; keeps credentials out of environment variables. The image runs as a non-root user (UID 1001) with a built-in healthcheck.&lt;/p&gt;

&lt;p&gt;The CLI adds an operational layer on top:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @waiaas/cli
waiaas init                        &lt;span class="c"&gt;# Create data directory + config.toml&lt;/span&gt;
waiaas start                       &lt;span class="c"&gt;# Start daemon&lt;/span&gt;
waiaas quickset &lt;span class="nt"&gt;--mode&lt;/span&gt; mainnet     &lt;span class="c"&gt;# Create wallets + MCP sessions in one step&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The 20 CLI commands cover the full operational lifecycle: wallet creation, session management, backup and restore, status monitoring, MCP setup, and notification configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Infrastructure That Doesn't Exist Without This
&lt;/h2&gt;

&lt;p&gt;Here's what becomes possible when agents have autonomous wallet infrastructure with proper policy enforcement:&lt;/p&gt;

&lt;p&gt;An agent that manages a treasury can rebalance positions based on market conditions, staying within per-protocol limits and daily spend caps, notifying the owner for anything unusual, and requiring explicit approval for anything large. No human needs to approve each rebalance — but no agent can go rogue either.&lt;/p&gt;

&lt;p&gt;An agent that consumes paid APIs can handle the economics transparently through x402, paying only domains on the approved list, within spending limits the owner set. The agent focuses on its actual task; the wallet layer handles payments.&lt;/p&gt;

&lt;p&gt;An agent operating across chains can bridge assets, stake for yield, and execute swaps — all through the same credential, with the same policy enforcement, across the 18 networks WAIaaS supports.&lt;/p&gt;

&lt;p&gt;None of this requires trusting the agent with unconstrained access. The policy engine enforces limits at the infrastructure layer. The three-tier auth model keeps humans in control of the limits while letting agents execute autonomously within them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Start: Agent Wallet in Five Steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Deploy the daemon&lt;/strong&gt; — &lt;code&gt;docker compose up -d&lt;/code&gt; after cloning the repo&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create a wallet&lt;/strong&gt; — &lt;code&gt;curl -X POST http://127.0.0.1:3100/v1/wallets -H "X-Master-Password: ..." -d '{"name": "agent-wallet", "chain": "solana", "environment": "mainnet"}'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set policies&lt;/strong&gt; — Configure &lt;code&gt;SPENDING_LIMIT&lt;/code&gt; and &lt;code&gt;ALLOWED_TOKENS&lt;/code&gt; before creating sessions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create a session&lt;/strong&gt; — &lt;code&gt;curl -X POST http://127.0.0.1:3100/v1/sessions -H "X-Master-Password: ..."&lt;/code&gt; — this gives you the session token your agent holds&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connect your agent&lt;/strong&gt; — Use the MCP integration, SDK, or REST API with the session token&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The agent can now execute transactions within the policy limits you set. The owner can monitor and approve. The infrastructure enforces the rules.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;The economic infrastructure for autonomous AI agents isn't a future problem — it's a present one, and the building blocks are available now. WAIaaS is open-source, self-hosted, and production-capable: explore the full codebase and contribute at &lt;a href="https://github.com/minhoyoo-iotrust/WAIaaS" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, and see documentation and deployment guides at &lt;a href="https://waiaas.ai" rel="noopener noreferrer"&gt;waiaas.ai&lt;/a&gt;. If you're building agents that need to participate in economic activity, this is the layer worth understanding today — because the agents that can pay for what they use will do things the ones that can't simply cannot.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>blockchain</category>
      <category>web3</category>
      <category>defi</category>
    </item>
    <item>
      <title>4-Tier Security Model: From INSTANT to APPROVAL for AI Agent Transactions</title>
      <dc:creator>Wallet Guy</dc:creator>
      <pubDate>Fri, 19 Jun 2026 16:13:20 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/walletguy/4-tier-security-model-from-instant-to-approval-for-ai-agent-transactions-5bdh</link>
      <guid>https://dev.clauneck.workers.dev/walletguy/4-tier-security-model-from-instant-to-approval-for-ai-agent-transactions-5bdh</guid>
      <description>&lt;h1&gt;
  
  
  4-Tier Security Model: How WAIaaS Puts Guardrails on AI Agent Wallets
&lt;/h1&gt;

&lt;p&gt;Giving an AI agent a wallet without guardrails is like giving a toddler a credit card — the agent will enthusiastically do exactly what you told it to do, including the parts you didn't think through. If you're building systems where AI agents hold and move real funds, the security model underneath that wallet isn't an afterthought. It's the entire game.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Problem Is Harder Than It Looks
&lt;/h2&gt;

&lt;p&gt;The naive approach to AI agent wallets goes something like this: generate a private key, give the agent signing authority, and let it rip. That works fine in a sandbox. In production, with real money, it creates a single point of catastrophic failure. One compromised session token, one hallucinated recipient address, one runaway trading loop — and the funds are gone.&lt;/p&gt;

&lt;p&gt;The challenge is that you need the agent to operate autonomously most of the time. If every transaction requires manual approval, you've built an expensive UI for yourself, not an autonomous agent. What you actually need is a system that lets small, routine transactions flow through instantly while catching anything unusual before it executes. That's a policy engine problem, and it requires thinking carefully about the threat model: what are the realistic ways this goes wrong?&lt;/p&gt;

&lt;p&gt;WAIaaS approaches this with three distinct layers between your agent and your funds, and a default-deny stance that means if you haven't explicitly configured something, it's blocked.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 1: Three Authentication Roles
&lt;/h2&gt;

&lt;p&gt;Before we get to the policy engine, it's worth understanding that WAIaaS separates who can do what at the authentication level. There are three distinct auth roles:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;masterAuth&lt;/strong&gt; (Argon2id) — The system administrator role. Creates wallets, manages sessions, configures policies. This is the password you set once and lock away. AI agents never see it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;sessionAuth&lt;/strong&gt; (JWT HS256) — What the AI agent actually uses. Scoped to a specific wallet. Time-limited. The agent carries this token and uses it for transactions, balance queries, and DeFi actions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ownerAuth&lt;/strong&gt; (SIWS/SIWE — ed25519 or secp256k1 signature) — The fund owner. Used for approving pending transactions, recovery, and the kill switch. This maps to a wallet you control, not a password stored anywhere on the server.&lt;/p&gt;

&lt;p&gt;This separation means that even if an attacker gets hold of the agent's session token, they can't create new wallets, modify policies, or approve high-value transactions. The blast radius is bounded.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# masterAuth — system administrator (wallet creation, session management, policies)&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt;

&lt;span class="c"&gt;# sessionAuth — AI agent (transactions, balance queries, DeFi actions)&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer wai_sess_eyJhbGciOiJIUzI1NiJ9..."&lt;/span&gt;

&lt;span class="c"&gt;# ownerAuth — fund owner (transaction approval, kill switch recovery)&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Owner-Signature: &amp;lt;ed25519-or-secp256k1-signature&amp;gt;"&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Owner-Message: &amp;lt;signed-message&amp;gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sessions also carry per-session TTL, maxRenewals, and absoluteLifetime controls. A session issued to a short-lived agent job can be configured to expire when the job ends.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 2: Default-Deny Policies
&lt;/h2&gt;

&lt;p&gt;This is the part that actually prevents your agent from draining your wallet. WAIaaS enforces a default-deny posture on two critical policy types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ALLOWED_TOKENS&lt;/strong&gt; — If you haven't explicitly whitelisted a token, the agent cannot transfer it. Your agent can't suddenly start moving tokens you didn't know it could see.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CONTRACT_WHITELIST&lt;/strong&gt; — If a contract address isn't on the list, the agent can't call it. This stops the agent from interacting with arbitrary DeFi protocols you haven't reviewed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's not "secure by default" as a marketing claim. It's a hard block at the policy evaluation stage. The transaction pipeline runs a policy check before execution, and a missing whitelist entry returns &lt;code&gt;POLICY_DENIED&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The policy engine supports 21 policy types in total. Beyond the two default-deny types above, you have tools for controlling approved spenders, method selectors, network restrictions, DeFi-specific limits (LTV ratios, leverage caps, position sizes), and more. Here's the full list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SPENDING_LIMIT          — Amount-based 4-tier security
WHITELIST               — Allowed recipient addresses
TIME_RESTRICTION        — Allowed transaction hours
RATE_LIMIT              — Max transactions per period
ALLOWED_TOKENS          — Token transfer whitelist (default-deny)
CONTRACT_WHITELIST      — Contract call whitelist (default-deny)
METHOD_WHITELIST        — Allowed function selectors
APPROVED_SPENDERS       — Token approval whitelist (default-deny)
APPROVE_AMOUNT_LIMIT    — Max approve amount, block unlimited
APPROVE_TIER_OVERRIDE   — Force tier for APPROVE transactions
ALLOWED_NETWORKS        — Network restriction
X402_ALLOWED_DOMAINS    — x402 payment domain whitelist
LENDING_LTV_LIMIT       — Max loan-to-value ratio for DeFi lending
LENDING_ASSET_WHITELIST — Allowed lending assets
PERP_MAX_LEVERAGE       — Max perpetual futures leverage
PERP_MAX_POSITION_USD   — Max position size in USD
PERP_ALLOWED_MARKETS    — Allowed perpetual markets
REPUTATION_THRESHOLD    — ERC-8004 onchain reputation threshold
ERC8128_ALLOWED_DOMAINS — ERC-8128 HTTP signing domains
VENUE_WHITELIST         — Allowed trading venues
ACTION_CATEGORY_LIMIT   — DeFi action category limits
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The DeFi-specific policy types are worth calling out for trading agents in particular. &lt;code&gt;PERP_MAX_LEVERAGE&lt;/code&gt; means your perpetuals agent literally cannot open a position above your configured leverage cap, regardless of what the LLM decides is a good idea. &lt;code&gt;LENDING_LTV_LIMIT&lt;/code&gt; prevents your lending agent from borrowing against collateral right up to the liquidation threshold.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 3: The 4-Tier Security Model
&lt;/h2&gt;

&lt;p&gt;This is the architecture that lets you have autonomous operation without losing control. Every transaction is assigned to one of four security tiers based on your policy configuration:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;INSTANT&lt;/strong&gt; — Execute immediately, no notification. For small, routine operations that you've decided carry acceptable risk. A $5 transaction to a whitelisted address shouldn't wake you up at 3am.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTIFY&lt;/strong&gt; — Execute immediately, but send a notification. You're informed, but the transaction doesn't wait for you. Useful for mid-range amounts where you want visibility without friction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DELAY&lt;/strong&gt; — Queue the transaction for a configured delay period (e.g., 15 minutes), then execute. The window is cancellable. If the agent did something wrong — or if you notice an anomaly — you can stop it before it settles.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;APPROVAL&lt;/strong&gt; — Block until the fund owner explicitly approves. High-value transactions, unusual patterns, anything you've decided requires a human in the loop.&lt;/p&gt;

&lt;p&gt;The tier assignment happens automatically based on your &lt;code&gt;SPENDING_LIMIT&lt;/code&gt; policy rules. Here's what that configuration looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/policies &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "walletId": "&amp;lt;wallet-uuid&amp;gt;",
    "type": "SPENDING_LIMIT",
    "rules": {
      "instant_max_usd": 100,
      "notify_max_usd": 500,
      "delay_max_usd": 2000,
      "delay_seconds": 900,
      "daily_limit_usd": 5000
    }
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this configuration: transactions under $100 execute immediately. $100-$500 execute immediately with a notification. $500-$2000 are queued for 15 minutes before execution. Anything above $2000 waits for your manual approval. There's also a $5000 daily aggregate limit — if the agent somehow exhausts that in a session, subsequent transactions are blocked for the rest of the day.&lt;/p&gt;

&lt;p&gt;The tier logic is straightforward: &lt;code&gt;amount &amp;lt;= instant_max → INSTANT&lt;/code&gt;, &lt;code&gt;&amp;lt;= notify_max → NOTIFY&lt;/code&gt;, &lt;code&gt;&amp;lt;= delay_max → DELAY&lt;/code&gt;, &lt;code&gt;&amp;gt; delay_max → APPROVAL&lt;/code&gt;. Every transaction that enters the 7-stage pipeline gets evaluated against this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Human Approval Channels
&lt;/h2&gt;

&lt;p&gt;When a transaction hits the APPROVAL tier, something needs to reach you. WAIaaS provides three signing channels: a push relay channel, a Telegram channel, and a wallet notification channel. The WalletConnect integration means you can approve transactions directly from your existing wallet app.&lt;/p&gt;

&lt;p&gt;Approving a pending transaction via the API looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/transactions/&amp;lt;tx-id&amp;gt;/approve &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Owner-Signature: &amp;lt;ed25519-or-secp256k1-signature&amp;gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Owner-Message: &amp;lt;signed-message&amp;gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The ownerAuth signature is what makes this secure. Approval requires a cryptographic signature from the owner's key — not just a password or session token. An attacker with access to the server can't approve their own pending transactions without also controlling your private key.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simulate Before You Execute
&lt;/h2&gt;

&lt;p&gt;One more tool worth knowing about: the dry-run API. Before any transaction executes for real, you can simulate it to see exactly how it would be evaluated — which tier it would hit, whether it would be denied by policy, what the estimated gas cost looks like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/transactions/send &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer wai_sess_&amp;lt;token&amp;gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "type": "TRANSFER",
    "to": "recipient-address",
    "amount": "0.1",
    "dryRun": true
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is particularly useful when you're configuring policies for the first time. You can test edge cases — what happens when the agent tries to send $150? $2500? — without committing real funds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Start: Setting Up Security in 5 Steps
&lt;/h2&gt;

&lt;p&gt;Here's the minimal path to running an agent with real guardrails:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Install and start the daemon&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @waiaas/cli
waiaas init
waiaas start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: Create a wallet&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/wallets &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"name": "trading-wallet", "chain": "solana", "environment": "mainnet"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3: Set a spending limit policy&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/policies &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "walletId": "&amp;lt;wallet-uuid&amp;gt;",
    "type": "SPENDING_LIMIT",
    "rules": {
      "instant_max_usd": 100,
      "notify_max_usd": 500,
      "delay_max_usd": 2000,
      "delay_seconds": 900,
      "daily_limit_usd": 5000
    }
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4: Whitelist the tokens your agent should touch&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Configure an &lt;code&gt;ALLOWED_TOKENS&lt;/code&gt; policy for the specific tokens the agent needs. Anything not on the list stays untouchable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Issue a session token for the agent and connect&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/sessions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"walletId": "&amp;lt;wallet-uuid&amp;gt;"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hand that session token to your agent. It's scoped, time-limited, and bounded by every policy you just configured.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Error Response Tells You
&lt;/h2&gt;

&lt;p&gt;When a transaction is blocked, the error response is explicit about why:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POLICY_DENIED"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Transaction denied by SPENDING_LIMIT policy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POLICY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"retryable"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;retryable: false&lt;/code&gt; on a policy denial is intentional — the agent shouldn't retry. It should surface the denial upstream so a human can decide whether the policy needs adjustment or whether the agent's behavior was wrong. Clear error semantics matter for building reliable agent systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;The security model described here is one layer of a larger system — the WAIaaS monorepo also includes MCP integration for connecting agents to Claude and other frameworks, DeFi protocol integrations across 15 providers, and NFT support for EVM and Solana. If you're building an agent that needs to operate in production, the right starting point is the full documentation and the open-source codebase.&lt;/p&gt;

&lt;p&gt;Browse the source and open issues on GitHub: &lt;a href="https://github.com/minhoyoo-iotrust/WAIaaS" rel="noopener noreferrer"&gt;https://github.com/minhoyoo-iotrust/WAIaaS&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Learn more about the project and deployment options at: &lt;a href="https://waiaas.ai" rel="noopener noreferrer"&gt;https://waiaas.ai&lt;/a&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>ai</category>
      <category>web3</category>
      <category>architecture</category>
    </item>
    <item>
      <title>39 REST API Routes: How We Built Comprehensive Wallet Control for Trading Bots</title>
      <dc:creator>Wallet Guy</dc:creator>
      <pubDate>Fri, 19 Jun 2026 11:00:03 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/walletguy/39-rest-api-routes-how-we-built-comprehensive-wallet-control-for-trading-bots-4oec</link>
      <guid>https://dev.clauneck.workers.dev/walletguy/39-rest-api-routes-how-we-built-comprehensive-wallet-control-for-trading-bots-4oec</guid>
      <description>&lt;h1&gt;
  
  
  39 REST API Routes: How We Built Comprehensive Wallet Control for Trading Bots
&lt;/h1&gt;

&lt;p&gt;Your trading bot spotted the arbitrage opportunity — the price gap is there, the math checks out, but can it actually execute before the block closes? Reliable wallet infrastructure is the unglamorous part of trading bot development that determines whether your strategy lives or dies in production. WAIaaS is an open-source, self-hosted Wallet-as-a-Service that gives trading bots a complete REST API with built-in risk controls, multi-protocol DeFi access, and the execution primitives you actually need.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Wallet Infrastructure Is the Hard Part
&lt;/h2&gt;

&lt;p&gt;Most trading bot tutorials stop at strategy. They show you how to detect a price discrepancy on Jupiter versus another DEX, and then wave their hands at "signing and sending a transaction." In production, that hand-wave collapses into a pile of problems: gas spikes eating your margins, unsigned approvals blocking execution, no way to simulate before committing, and a single compromised key wiping out everything your bot has earned.&lt;/p&gt;

&lt;p&gt;The infrastructure layer needs to handle gas optimization, policy enforcement, transaction simulation, and multi-protocol execution — and it needs to do all of that without becoming the bottleneck in your execution path. That's the problem WAIaaS was built to solve.&lt;/p&gt;

&lt;h2&gt;
  
  
  39 API Routes Covering Every Trading Primitive
&lt;/h2&gt;

&lt;p&gt;WAIaaS exposes 39 REST API route modules. For a trading bot, that full surface area matters because different trading scenarios need different primitives. Let's walk through the ones that matter most.&lt;/p&gt;

&lt;h3&gt;
  
  
  Authentication: Three Layers for Three Roles
&lt;/h3&gt;

&lt;p&gt;WAIaaS separates concerns cleanly with three authentication methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# masterAuth — system administrator (wallet creation, session management, policies)&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt;

&lt;span class="c"&gt;# sessionAuth — AI agent or trading bot (transactions, balance queries, DeFi actions)&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer wai_sess_eyJhbGciOiJIUzI1NiJ9..."&lt;/span&gt;

&lt;span class="c"&gt;# ownerAuth — fund owner (transaction approval, kill switch recovery)&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Owner-Signature: &amp;lt;ed25519-or-secp256k1-signature&amp;gt;"&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Owner-Message: &amp;lt;signed-message&amp;gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your trading bot runs exclusively on &lt;code&gt;sessionAuth&lt;/code&gt;. It never touches the master password. This means a compromised bot session has bounded blast radius — it can only operate within the policies you've configured for that session, and you can revoke it instantly without affecting the underlying wallet or other sessions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Create the Trading Wallet
&lt;/h3&gt;

&lt;p&gt;Before your bot executes a single trade, you set up the wallet once using &lt;code&gt;masterAuth&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/wallets &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"name": "trading-wallet", "chain": "solana", "environment": "mainnet"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then create a session token that your bot will use for every subsequent request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/sessions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"walletId": "&amp;lt;wallet-uuid&amp;gt;"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From this point, your bot operates entirely with the returned session token. The wallet creation and session management are one-time setup steps — your hot path only uses &lt;code&gt;sessionAuth&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gas Conditional Execution: Only Trade When Gas Is Cheap
&lt;/h2&gt;

&lt;p&gt;One of the most practical features for any bot running on EVM chains is gas conditional execution. WAIaaS has a dedicated pipeline stage (&lt;code&gt;stage-gas-condition&lt;/code&gt;) that holds a transaction in queue until the gas price meets your configured threshold. Your bot submits the transaction, and the daemon handles the gas monitoring — you're not writing a polling loop.&lt;/p&gt;

&lt;p&gt;For MEV bots and arbitrage strategies with thin margins, this is the difference between a profitable trade and a loss. You define the acceptable gas ceiling in your policy, and the execution engine enforces it automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  15 DeFi Protocols, One Wallet
&lt;/h2&gt;

&lt;p&gt;This is where WAIaaS gets interesting for multi-leg strategies. WAIaaS integrates 15 DeFi protocol providers: aave-v3, across, dcent-swap, drift, erc8004, hyperliquid, jito-staking, jupiter-swap, kamino, lido-staking, lifi, pendle, polymarket, xrpl-dex, and zerox-swap.&lt;/p&gt;

&lt;p&gt;For a Solana-based bot, you can swap on Jupiter in the same session you use to open a Drift perpetual:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Leg 1: Swap SOL → USDC on Jupiter&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/actions/jupiter-swap/swap &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer wai_sess_&amp;lt;token&amp;gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "inputMint": "So11111111111111111111111111111111111111112",
    "outputMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
    "amount": "1000000000"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Hyperliquid integration covers perpetual futures, spot trading, and sub-accounts. The cross-chain story is handled by LI.FI and Across, both integrated as first-class DeFi providers. Swap on Solana, hedge the exposure on an EVM chain, bridge the collateral — all through the same session token, same API surface, same policy enforcement layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simulate Before You Execute
&lt;/h2&gt;

&lt;p&gt;Trading bots that don't simulate are trading bots that occasionally blow up. WAIaaS has a dry-run API baked into the transaction route:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/transactions/send &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer wai_sess_&amp;lt;token&amp;gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "type": "TRANSFER",
    "to": "recipient-address",
    "amount": "0.1",
    "dryRun": true
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;dryRun: true&lt;/code&gt; flag runs the transaction through the full 7-stage pipeline — validation, auth, policy check, gas conditions — without committing to the chain. Your bot can verify that a planned execution would actually pass all policy gates before spending gas on a transaction that was going to get blocked anyway.&lt;/p&gt;

&lt;p&gt;The 7-stage pipeline is: validate → auth → policy → wait → execute → confirm. Every transaction goes through all of these stages. Simulation gives you deterministic pipeline output without the on-chain side effect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Policy Engine: Risk Controls That Run Before Every Trade
&lt;/h2&gt;

&lt;p&gt;The policy engine has 21 policy types with 4 security tiers (INSTANT, NOTIFY, DELAY, APPROVAL) and enforces default-deny on token transfers and contract calls. For a trading bot, the most relevant policies are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/policies &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "walletId": "&amp;lt;wallet-uuid&amp;gt;",
    "type": "SPENDING_LIMIT",
    "rules": {
      "instant_max_usd": 100,
      "notify_max_usd": 500,
      "delay_max_usd": 2000,
      "delay_seconds": 900,
      "daily_limit_usd": 5000
    }
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tier assignment is deterministic: transaction value ≤ &lt;code&gt;instant_max_usd&lt;/code&gt; executes immediately, ≤ &lt;code&gt;notify_max_usd&lt;/code&gt; executes with a notification, ≤ &lt;code&gt;delay_max_usd&lt;/code&gt; queues for &lt;code&gt;delay_seconds&lt;/code&gt; before executing (and can be cancelled in that window), and anything above that requires explicit owner approval.&lt;/p&gt;

&lt;p&gt;For a bot you want running autonomously, you set &lt;code&gt;instant_max_usd&lt;/code&gt; to the maximum trade size you're comfortable with the bot executing without any human in the loop. Large unexpected transactions hit the DELAY or APPROVAL tier automatically.&lt;/p&gt;

&lt;p&gt;Beyond &lt;code&gt;SPENDING_LIMIT&lt;/code&gt;, the policy types most relevant to trading bots are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;CONTRACT_WHITELIST&lt;/code&gt;&lt;/strong&gt; — default-deny contract calls. Your bot can only interact with protocols you've explicitly whitelisted. A compromised session can't drain funds into an arbitrary contract.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;ALLOWED_TOKENS&lt;/code&gt;&lt;/strong&gt; — default-deny token transfers. Only the tokens you've listed can be moved.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;PERP_MAX_LEVERAGE&lt;/code&gt;&lt;/strong&gt; — hard cap on perpetual futures leverage, enforced at the API layer before the order reaches the protocol.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;PERP_MAX_POSITION_USD&lt;/code&gt;&lt;/strong&gt; — maximum position size in USD across perp markets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;PERP_ALLOWED_MARKETS&lt;/code&gt;&lt;/strong&gt; — restrict which perpetual markets the bot can trade.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;RATE_LIMIT&lt;/code&gt;&lt;/strong&gt; — maximum transactions per period, useful for preventing runaway execution loops.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;VENUE_WHITELIST&lt;/code&gt;&lt;/strong&gt; — restrict which trading venues the bot can route through.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The default-deny enforcement means &lt;code&gt;ALLOWED_TOKENS&lt;/code&gt; and &lt;code&gt;CONTRACT_WHITELIST&lt;/code&gt; block all transfers and contract calls unless explicitly configured. This is the correct default for a bot wallet — not permissive until locked down, but locked down until explicitly opened.&lt;/p&gt;

&lt;h2&gt;
  
  
  Batch Transactions for Multi-Leg Strategies
&lt;/h2&gt;

&lt;p&gt;The transaction schema supports 7 types in a discriminated union: Transfer, TokenTransfer, ContractCall, Approve, Batch, NftTransfer, and ContractDeploy. The &lt;code&gt;Batch&lt;/code&gt; type lets you bundle multiple operations into a single atomic submission — useful for strategies that need to approve a spender and execute a swap in the same block, or open a position and set a stop-loss simultaneously.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checking Balance Before Every Trade
&lt;/h2&gt;

&lt;p&gt;Your bot's execution loop almost certainly starts with a balance check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://127.0.0.1:3100/v1/wallet/balance &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer wai_sess_eyJhbGciOiJIUzI1NiJ9..."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The TypeScript SDK wraps all of these calls with type safety and async/await ergonomics:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;WAIaaSClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;WAIaaSError&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@waiaas/sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WAIaaSClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;WAIAAS_BASE_URL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3100&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;sessionToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;WAIAAS_SESSION_TOKEN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Check balance before attempting execution&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBalance&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Balance: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;network&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Send tokens&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sendResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendToken&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TRANSFER&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;recipient-address&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.001&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Transaction submitted: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sendResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (status: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sendResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Poll for confirmation&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;POLL_TIMEOUT_MS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;startTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;startTime&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;POLL_TIMEOUT_MS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sendResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;COMPLETED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Confirmed! Hash: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;txHash&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;FAILED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Failed: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Error codes from the API are structured and machine-readable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POLICY_DENIED"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Transaction denied by SPENDING_LIMIT policy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POLICY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"retryable"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;POLICY_DENIED&lt;/code&gt; with &lt;code&gt;retryable: false&lt;/code&gt; means your bot should not retry — the transaction was blocked by a policy rule. &lt;code&gt;INSUFFICIENT_BALANCE&lt;/code&gt; and &lt;code&gt;TOKEN_EXPIRED&lt;/code&gt; are also first-class error codes your execution loop can handle explicitly.&lt;/p&gt;

&lt;h2&gt;
  
  
  ERC-4337 Account Abstraction for Gasless Execution
&lt;/h2&gt;

&lt;p&gt;For EVM bots, WAIaaS supports ERC-4337 Account Abstraction with a dedicated UserOp build/sign API. This means gasless transactions and smart account execution — your bot can execute strategies without holding the native gas token, relying instead on a paymaster. The &lt;code&gt;build-userop&lt;/code&gt; and &lt;code&gt;sign-userop&lt;/code&gt; tools are available both via REST and through the 45 MCP tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  x402: Paying for API Calls Automatically
&lt;/h2&gt;

&lt;p&gt;The x402 HTTP payment protocol support deserves a mention for bots that consume paid data APIs. When your bot hits an API endpoint that returns an HTTP 402 Payment Required, WAIaaS can handle the micropayment automatically using the &lt;code&gt;x402-fetch&lt;/code&gt; route. Combined with &lt;code&gt;X402_ALLOWED_DOMAINS&lt;/code&gt; policy, you whitelist which API domains the bot is allowed to pay, and the payment flow is fully automated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Start for Trading Bot Developers
&lt;/h2&gt;

&lt;p&gt;Getting WAIaaS running for a trading bot takes five steps:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Start the daemon with Docker:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; waiaas &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 127.0.0.1:3100:3100 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; waiaas-data:/data &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;WAIAAS_AUTO_PROVISION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  ghcr.io/minhoyoo-iotrust/waiaas:latest

docker &lt;span class="nb"&gt;exec &lt;/span&gt;waiaas &lt;span class="nb"&gt;cat&lt;/span&gt; /data/recovery.key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Create a wallet and session:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/wallets &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: &amp;lt;from-recovery.key&amp;gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"name": "trading-wallet", "chain": "solana", "environment": "mainnet"}'&lt;/span&gt;

curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/sessions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: &amp;lt;from-recovery.key&amp;gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"walletId": "&amp;lt;wallet-uuid&amp;gt;"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Set policies before funding the wallet:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Configure &lt;code&gt;SPENDING_LIMIT&lt;/code&gt;, &lt;code&gt;ALLOWED_TOKENS&lt;/code&gt;, and &lt;code&gt;CONTRACT_WHITELIST&lt;/code&gt; policies as shown above. Default-deny enforcement means you must set &lt;code&gt;ALLOWED_TOKENS&lt;/code&gt; and &lt;code&gt;CONTRACT_WHITELIST&lt;/code&gt; before the bot can transact.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Install the SDK and point it at your daemon:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @waiaas/sdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WAIaaSClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://127.0.0.1:3100&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;sessionToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WAIAAS_SESSION_TOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. Explore the interactive API reference:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;open http://127.0.0.1:3100/reference
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The OpenAPI 3.0 spec is auto-generated at &lt;code&gt;/doc&lt;/code&gt; and the interactive Scalar API reference is at &lt;code&gt;/reference&lt;/code&gt; — useful for exploring the full 39 route surface without reading source code.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;The full API surface — all 39 route modules with request/response schemas — is available interactively at &lt;code&gt;/reference&lt;/code&gt; once you have the daemon running. The GitHub repository has the complete source for the policy engine, pipeline stages, and all 15 DeFi protocol integrations if you want to understand exactly what happens between your bot's API call and the on-chain transaction.&lt;/p&gt;

&lt;p&gt;If you're building a trading bot that needs wallet infrastructure that doesn't get in the way of your strategy, start here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/minhoyoo-iotrust/WAIaaS" rel="noopener noreferrer"&gt;https://github.com/minhoyoo-iotrust/WAIaaS&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Official site&lt;/strong&gt;: &lt;a href="https://waiaas.ai" rel="noopener noreferrer"&gt;https://waiaas.ai&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>api</category>
      <category>architecture</category>
      <category>defi</category>
      <category>web3</category>
    </item>
  </channel>
</rss>
