DEV Community

Cover image for Trading Hours for Bots: TIME_RESTRICTION Policy for Scheduled DeFi Operations
Wallet Guy
Wallet Guy

Posted on

Trading Hours for Bots: TIME_RESTRICTION Policy for Scheduled DeFi Operations

Trading Hours for Bots: Using TIME_RESTRICTION Policy for Scheduled DeFi Operations

Trading bots that run 24/7 are a liability — your DeFi bot needs hard scheduling controls so it only executes during windows you've vetted, not at 3am when liquidity is thin and you're asleep. Unscheduled execution is one of the most common sources of unexpected losses in algorithmic trading: the opportunity that looked good at midnight often looks a lot worse at 9am when you check the logs. WAIaaS's TIME_RESTRICTION policy gives your bot a hard, server-enforced trading window — not an application-level check you'll forget to ship in the next deploy.

Why Scheduling Matters More Than You Think

Most bot developers think about scheduling at the application layer. A cron job fires, the bot wakes up, checks conditions, trades. The problem is that application-layer scheduling is fragile. Process crashes, missed heartbeats, timezone bugs, a dependency restart at the wrong moment — any of these can cause your bot to trade outside its intended window. And if your session token is long-lived, a bug in your scheduling logic means your wallet is still authorized to fire transactions whenever the process happens to run.

The better approach is defense in depth: schedule at the application layer and enforce at the wallet layer. Even if your bot has a bug that tries to fire a trade at 2am, the wallet rejects it. No trade. No loss. Clean audit log.

WAIaaS enforces this at the policy engine level, inside the transaction pipeline, before any signing happens. The pipeline runs through validation, auth, and policy stages — TIME_RESTRICTION lives in that policy stage. It's not a suggestion; it's a hard block.

The TIME_RESTRICTION Policy

TIME_RESTRICTION is one of 21 policy types in WAIaaS's policy engine, which uses 4 security tiers (INSTANT, NOTIFY, DELAY, APPROVAL) and follows default-deny enforcement. The TIME_RESTRICTION type is specifically about allowed transaction hours. Transactions attempted outside the configured window are rejected at the policy stage before they touch signing or broadcast.

The configuration is straightforward:

{
  "allowedHours": {"start": 9, "end": 17},
  "timezone": "UTC"
}
Enter fullscreen mode Exit fullscreen mode

You set start and end in 24-hour format, pick your timezone, and that's the window. Outside those hours, every transaction from that session is blocked — whether it's a transfer, a Jupiter swap, a Drift perpetual position, or an Aave lending action.

Setting It Up

Here's the full flow for a trading bot that should only operate during US market hours.

Step 1: Create the wallet

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

You get back a wallet UUID. Keep it.

Step 2: Apply the TIME_RESTRICTION policy

curl -X POST http://localhost:3100/v1/policies \
  -H 'Content-Type: application/json' \
  -H 'X-Master-Password: <password>' \
  -d '{
    "walletId": "<wallet-uuid>",
    "type": "TIME_RESTRICTION",
    "rules": {
      "allowedHours": {"start": 9, "end": 17},
      "timezone": "UTC"
    }
  }'
Enter fullscreen mode Exit fullscreen mode

Step 3: Layer a SPENDING_LIMIT on top

TIME_RESTRICTION handles when — SPENDING_LIMIT handles how much. Stack them:

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

Now your bot can only trade between 09:00-17:00 UTC, and anything over $2,000 in a single transaction goes to APPROVAL. Anything over $5,000 in a day hard-stops.

Step 4: Create a session for your bot

curl -X POST http://127.0.0.1:3100/v1/sessions \
  -H "Content-Type: application/json" \
  -H "X-Master-Password: my-secret-password" \
  -d '{"walletId": "<wallet-uuid>"}'
Enter fullscreen mode Exit fullscreen mode

The returned session token is what your bot uses. Hand it off via environment variable. The bot never needs the master password.

Step 5: Let the bot trade (within the window)

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

Inside the window, this goes through normally (subject to your other policies). Outside the window, the response is a clean policy denial:

{
  "error": {
    "code": "POLICY_DENIED",
    "message": "Transaction denied by TIME_RESTRICTION policy",
    "domain": "POLICY",
    "retryable": false
  }
}
Enter fullscreen mode Exit fullscreen mode

retryable: false is the signal to your bot: don't retry, schedule for next window.

Combining TIME_RESTRICTION with Token Whitelists

Here's a pattern that works well for algo traders: combine TIME_RESTRICTION with ALLOWED_TOKENS so your bot can only trade specific assets and only during your window. This is defense in depth for multi-protocol strategies.

curl -X POST http://localhost:3100/v1/policies \
  -H 'Content-Type: application/json' \
  -H 'X-Master-Password: <password>' \
  -d '{
    "walletId": "<wallet-uuid>",
    "type": "ALLOWED_TOKENS",
    "rules": {
      "tokens": [
        {
          "address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
          "symbol": "USDC",
          "chain": "solana"
        }
      ]
    }
  }'
Enter fullscreen mode Exit fullscreen mode

ALLOWED_TOKENS is default-deny: if a token isn't on the list, the transaction is blocked regardless of what time it is. Pair this with TIME_RESTRICTION and CONTRACT_WHITELIST for a locked-down trading setup where your bot can only do exactly what you've pre-approved.

Gas Conditional Execution: Only Trade When It's Cheap

If you're running EVM strategies, WAIaaS has a gas conditional execution feature built into the transaction pipeline — transactions execute only when the gas price meets your threshold. This stacks naturally with TIME_RESTRICTION: your bot only trades in the allowed time window and only when gas is acceptable. Two filters, both enforced server-side, before any transaction is signed or broadcast.

This is especially useful for strategies that aren't time-sensitive down to the second — if you're running end-of-day rebalancing on Ethereum mainnet, there's no reason to pay peak gas when you could wait 15 minutes for it to drop.

DeFi Actions Inside the Window

TIME_RESTRICTION applies to all transaction types, including DeFi protocol actions. WAIaaS integrates 15 DeFi protocol providers — including jupiter-swap, drift, aave-v3, lifi, and hyperliquid — so your bot can execute complex multi-protocol strategies through the same session token, all subject to the same policy stack.

A Jupiter swap during the allowed window:

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

Same token. Same policies. If this fires at 2am, TIME_RESTRICTION blocks it. If the USDC isn't on your ALLOWED_TOKENS list, that blocks it too. If the contract isn't on your CONTRACT_WHITELIST, blocked again. Every policy runs in the pipeline.

Dry-Run Before You Deploy

Before you point your bot at a live wallet with real funds, simulate your transaction to verify policy behavior:

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

The dry-run API simulates the full transaction pipeline including policy evaluation. You can test what happens when you fire a transaction inside and outside the allowed window without moving any funds. This is the right way to validate your policy configuration before go-live.

What the Full Policy Stack Looks Like

For a production trading bot, you're stacking multiple policies:

Policy Purpose
TIME_RESTRICTION Hard trading window (e.g., 09:00-17:00 UTC)
SPENDING_LIMIT Per-transaction and daily amount caps with tier escalation
ALLOWED_TOKENS Whitelist of tradeable assets (default-deny)
CONTRACT_WHITELIST Whitelist of callable contracts (default-deny)
RATE_LIMIT Max transactions per hour to prevent runaway loops
ALLOWED_NETWORKS Lock bot to specific chains

All 21 policy types run through the same pipeline. Policies are additive — if any policy denies the transaction, it's blocked. You build the exact risk profile you want by combining policies, not by writing custom validation logic in your bot.

The RATE_LIMIT Companion

TIME_RESTRICTION tells your bot when to stop. RATE_LIMIT tells it how often. For an arb bot that might loop aggressively, a RATE_LIMIT policy is the circuit breaker:

{"maxTransactions": 10, "period": "hourly"}
Enter fullscreen mode Exit fullscreen mode

More than 10 transactions in an hour, the policy blocks further execution until the period resets. This is the difference between a bot that makes 10 good trades and one that makes 400 trades because a bug caused it to loop on a stale opportunity.

Quickstart: Trading Bot with Scheduling

  1. Install the CLI — npm install -g @waiaas/cli
  2. Initialize and start — waiaas init && waiaas start
  3. Create a wallet — via the REST API or waiaas wallet create
  4. Apply policies — TIME_RESTRICTION + SPENDING_LIMIT + ALLOWED_TOKENS via the policy API
  5. Generate a session token — hand it to your bot via environment variable

Your bot's session token authorizes trades. The policy stack enforces the rules. You sleep.

What's Next

The policy engine has 21 policy types covering DeFi-specific risk controls beyond scheduling — PERP_MAX_LEVERAGE, PERP_MAX_POSITION_USD, LENDING_LTV_LIMIT, and VENUE_WHITELIST are all available for strategies that touch perpetuals or lending protocols. The OpenAPI 3.0 spec is available at /doc and the interactive reference at /reference if you want to explore the full API surface before writing a line of integration code.

WAIaaS is open-source and self-hosted — your keys, your infrastructure, your policy configuration. Explore the codebase and deployment docs on GitHub, and see the full feature set at the official site:

Top comments (0)