diff --git a/sandboxes/spraay/Dockerfile b/sandboxes/spraay/Dockerfile new file mode 100644 index 0000000..6b951fe --- /dev/null +++ b/sandboxes/spraay/Dockerfile @@ -0,0 +1,43 @@ +ARG BASE_IMAGE=ghcr.io/nvidia/openshell-community/sandboxes/base:latest +FROM ${BASE_IMAGE} + +# ── Spraay x402 Payment Toolkit ────────────────────────────────────────────── +# Pre-configured sandbox for AI agent crypto payments via the x402 protocol. +# Supports 13 blockchains, 76+ gateway endpoints, batch payments, escrow, +# payroll, token swaps, and Robot Task Protocol (RTP). + +# Install Node.js (required for ethers.js wallet operations) +USER root +RUN apt-get update && apt-get install -y --no-install-recommends \ + curl \ + jq \ + && curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \ + && apt-get install -y --no-install-recommends nodejs \ + && npm install -g ethers@6 \ + && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Python dependencies for wallet and signing operations +USER sandbox +RUN pip install --no-cache-dir \ + httpx \ + eth-account \ + web3 \ + pynacl \ + base58 + +# ── Spraay CLI wrapper ────────────────────────────────────────────────────── +COPY spraay.sh /usr/local/bin/spraay +USER root +RUN chmod +x /usr/local/bin/spraay +USER sandbox + +# ── Agent skills ───────────────────────────────────────────────────────────── +COPY skills/ /sandbox/.agents/skills/ + +# ── Default environment ────────────────────────────────────────────────────── +ENV SPRAAY_GATEWAY_URL=https://gateway.spraay.app +ENV SPRAAY_CHAIN=base + +# ── Healthcheck ────────────────────────────────────────────────────────────── +HEALTHCHECK --interval=30s --timeout=5s --retries=3 \ + CMD curl -sf ${SPRAAY_GATEWAY_URL}/health || exit 1 diff --git a/sandboxes/spraay/README.md b/sandboxes/spraay/README.md new file mode 100644 index 0000000..13e840b --- /dev/null +++ b/sandboxes/spraay/README.md @@ -0,0 +1,92 @@ +# Spraay — Crypto Payment Sandbox for OpenShell + +OpenShell sandbox image pre-configured with [Spraay](https://spraay.app) for AI agent crypto payments via the x402 protocol. + +## What's Included + +| Component | Description | +|-----------|-------------| +| **Spraay CLI** | Shell wrapper for 76+ paid gateway endpoints across 13 blockchains | +| **x402 Protocol** | HTTP 402-based micropayment protocol — agents pay per request with USDC | +| **Agent Skills** | Pre-built skills for batch payments, escrow, payroll, token swaps, and Robot Task Protocol (RTP) | +| **Multi-Chain** | Base, Ethereum, Arbitrum, Polygon, BNB, Avalanche, Solana, Bitcoin, Stacks, Unichain, Plasma, BOB, Bittensor | + +## Quick Start + +### Using the pre-built image + +```bash +openshell sandbox create --from spraay -- claude +``` + +### Building locally + +```bash +docker build -t openshell-spraay \ + --build-arg BASE_IMAGE=ghcr.io/nvidia/openshell-community/sandboxes/base:latest . +``` + +Then launch: + +```bash +openshell sandbox create --from openshell-spraay -- claude +``` + +## Environment Variables + +| Variable | Required | Description | +|----------|----------|-------------| +| `SPRAAY_GATEWAY_URL` | No | Gateway URL (default: `https://gateway.spraay.app`) | +| `SPRAAY_PAYMENT_ADDRESS` | Yes | Your wallet address for x402 payments | +| `SPRAAY_CHAIN` | No | Default chain (default: `base`) | + +## Skills + +The sandbox ships with agent skills in `.agents/skills/`: + +| Skill | Description | +|-------|-------------| +| `spraay-payments` | Batch send tokens to multiple recipients on any supported chain | +| `spraay-escrow` | Create and manage escrow contracts with milestone-based releases | +| `spraay-rtp` | Robot Task Protocol — hire robots and IoT devices via x402 micropayments | +| `spraay-gateway` | Query gateway endpoints, check pricing, discover available routes | + +## Network Policy + +The default network policy allows egress to: + +- `gateway.spraay.app` — Spraay x402 gateway (HTTPS) +- `*.infura.io` — RPC provider (HTTPS) +- `*.alchemy.com` — RPC provider (HTTPS) +- `*.base.org` — Base chain RPC (HTTPS) + +All other egress is denied by default. Customize via OpenShell policy overrides. + +## How x402 Works Inside the Sandbox + +1. Agent calls a Spraay gateway endpoint (e.g., `/v1/batch-send`) +2. Gateway returns HTTP `402 Payment Required` with a payment header +3. Agent signs USDC payment using its configured wallet +4. Gateway verifies payment on-chain and executes the request +5. Agent receives the result + +The sandbox enforces that all payment signing happens within the isolated environment. Private keys never leave the sandbox boundary. + +## Use Cases + +- **Autonomous payroll**: Agent runs scheduled batch payments to employees/contractors +- **Escrow automation**: Agent creates milestone-based escrow for freelance work +- **Robot hiring**: Agent uses RTP to commission physical tasks from IoT devices +- **Multi-chain treasury**: Agent manages token distributions across 13+ chains +- **DCA/Scheduled swaps**: Agent executes dollar-cost averaging strategies + +## Resources + +- [Spraay Gateway Docs](https://docs.spraay.app) +- [x402 Protocol Spec](https://www.x402.org) +- [Spraay MCP Server](https://smithery.ai/server/@plagtech/spraay-x402-mcp) +- [OpenShell Documentation](https://docs.nvidia.com/openshell/latest/index.html) + +## License + +Apache 2.0 — see [LICENSE](../../LICENSE). diff --git a/sandboxes/spraay/policy.yaml b/sandboxes/spraay/policy.yaml new file mode 100644 index 0000000..3916441 --- /dev/null +++ b/sandboxes/spraay/policy.yaml @@ -0,0 +1,92 @@ +# Spraay Sandbox Network Policy +# This policy allows egress only to the Spraay gateway and required +# blockchain RPC providers. All other egress is denied by default. +# +# Apply with: openshell policy set --policy policy.yaml --wait + +version: "1" + +# ── Spraay Gateway ─────────────────────────────────────────────────────────── +spraay_gateway: + destination: "gateway.spraay.app" + port: 443 + protocol: tcp + action: allow + note: "Spraay x402 payment gateway — all API requests route here" + +spraay_docs: + destination: "docs.spraay.app" + port: 443 + protocol: tcp + action: allow + note: "Spraay API documentation" + +# ── Blockchain RPC Providers ───────────────────────────────────────────────── +infura_rpc: + destination: "*.infura.io" + port: 443 + protocol: tcp + action: allow + note: "Infura — Ethereum, Polygon, Arbitrum, Optimism RPC" + +alchemy_rpc: + destination: "*.alchemy.com" + port: 443 + protocol: tcp + action: allow + note: "Alchemy — multi-chain RPC provider" + +base_rpc: + destination: "*.base.org" + port: 443 + protocol: tcp + action: allow + note: "Base chain public RPC" + +quicknode_rpc: + destination: "*.quiknode.pro" + port: 443 + protocol: tcp + action: allow + note: "QuickNode — multi-chain RPC provider" + +# ── Coinbase (x402 payment verification) ───────────────────────────────────── +coinbase_cdp: + destination: "*.coinbase.com" + port: 443 + protocol: tcp + action: allow + note: "Coinbase CDP — x402 payment facilitation and verification" + +# ── Solana RPC ─────────────────────────────────────────────────────────────── +solana_rpc: + destination: "*.solana.com" + port: 443 + protocol: tcp + action: allow + note: "Solana mainnet RPC" + +helius_rpc: + destination: "*.helius-rpc.com" + port: 443 + protocol: tcp + action: allow + note: "Helius — Solana RPC provider" + +# ── Bitcoin / Stacks ───────────────────────────────────────────────────────── +blockstream_api: + destination: "blockstream.info" + port: 443 + protocol: tcp + action: allow + note: "Blockstream — Bitcoin block explorer API" + +stacks_api: + destination: "*.stacks.co" + port: 443 + protocol: tcp + action: allow + note: "Stacks blockchain API" + +# ── Deny everything else ───────────────────────────────────────────────────── +# OpenShell default policy denies all egress not explicitly allowed above. diff --git a/sandboxes/spraay/skills/spraay-escrow.md b/sandboxes/spraay/skills/spraay-escrow.md new file mode 100644 index 0000000..bb70015 --- /dev/null +++ b/sandboxes/spraay/skills/spraay-escrow.md @@ -0,0 +1,60 @@ +# Spraay Escrow Skill + +Create and manage on-chain escrow contracts with milestone-based fund releases. + +## When to Use + +Use this skill when the user or agent needs to: + +- Hold funds in escrow between two parties +- Release payments based on milestone completion +- Create trustless payment agreements for freelance or contract work +- Automate conditional fund releases + +## How It Works + +1. **Create**: Deposit tokens into an escrow smart contract with defined milestones +2. **Monitor**: Check escrow status and milestone completion +3. **Release**: Release funds when milestones are verified +4. **Refund**: Return funds if conditions are not met + +## Commands + +### Create an escrow +```bash +spraay escrow-create '{ + "depositor": "0xYourAddress", + "beneficiary": "0xFreelancerAddress", + "token": "USDC", + "totalAmount": "500.0", + "chain": "base", + "milestones": [ + {"description": "Design mockups delivered", "amount": "150.0"}, + {"description": "Frontend implementation", "amount": "200.0"}, + {"description": "Testing and deployment", "amount": "150.0"} + ] +}' +``` + +### Check escrow status +```bash +spraay escrow-status +``` + +### Release milestone funds +```bash +spraay escrow-release +``` + +## Important Notes + +- Escrow creation requires sufficient token balance plus the x402 gateway fee +- Milestone releases are sequential by default +- Both parties can view escrow status on-chain +- Escrow contracts are non-custodial — funds are held by the smart contract, not by Spraay + +## Error Handling + +- HTTP 402: Payment required for gateway fee +- HTTP 409: Escrow already exists or milestone already released +- HTTP 404: Escrow ID not found diff --git a/sandboxes/spraay/skills/spraay-gateway.md b/sandboxes/spraay/skills/spraay-gateway.md new file mode 100644 index 0000000..75d00bb --- /dev/null +++ b/sandboxes/spraay/skills/spraay-gateway.md @@ -0,0 +1,89 @@ +# Spraay Gateway Skill + +Query the Spraay x402 gateway to discover available endpoints, check pricing, and understand supported chains and tokens. + +## When to Use + +Use this skill when the user or agent needs to: + +- See all available Spraay gateway routes and their pricing +- Check which chains and tokens are supported +- Verify gateway health and connectivity +- Understand x402 payment requirements before making a request + +## Commands + +### Check gateway health +```bash +spraay health +``` + +### Get gateway info +```bash +spraay info +``` + +### List all routes with pricing +```bash +spraay routes +``` + +### List supported chains +```bash +spraay chains +``` + +### Make a raw API call +```bash +spraay raw GET /v1/some-endpoint +spraay raw POST /v1/some-endpoint '{"key": "value"}' +``` + +## Gateway Overview + +The Spraay gateway at `gateway.spraay.app` exposes 76+ paid endpoints across 16 categories: + +| Category | Description | Example Endpoints | +|----------|-------------|-------------------| +| 1. Batch Payments | Multi-recipient token sends | `/v1/batch-send` | +| 2. Token Swaps | DEX aggregation | `/v1/swap`, `/v1/quote` | +| 3. Escrow | Milestone-based contracts | `/v1/escrow/*` | +| 4. Payroll | Recurring payment runs | `/v1/payroll/*` | +| 5. Price Oracle | Token pricing data | `/v1/price` | +| 6. Balance | Wallet balance queries | `/v1/balance` | +| 7. NFT | Mint and transfer NFTs | `/v1/nft/*` | +| 8. Bridge | Cross-chain transfers | `/v1/bridge/*` | +| 9. Staking | Stake and unstake tokens | `/v1/staking/*` | +| 10. Governance | DAO proposal tools | `/v1/governance/*` | +| 11. Analytics | On-chain data queries | `/v1/analytics/*` | +| 12. AI Inference | Proxy to AI models | `/v1/inference/*` | +| 13. Wallet | Wallet management | `/v1/wallet/*` | +| 14. Agent Wallet | Managed agent wallets | `/v1/agent-wallet/*` | +| 15. RTP | Robot Task Protocol | `/v1/rtp/*` | +| 16. Identity | On-chain identity | `/v1/identity/*` | + +## Pricing Tiers + +- **Free endpoints**: `/health`, `/v1/info`, `/v1/routes`, `/v1/chains` (11 total) +- **Standard**: $0.01–$0.05 per request (most query endpoints) +- **Premium**: $0.05–$0.25 per request (escrow, bridge, payroll execution) + +## x402 Payment Flow + +All paid endpoints use the HTTP 402 protocol: + +1. Client sends a request without payment +2. Gateway responds with `402 Payment Required` + payment details header +3. Client signs a USDC payment transaction +4. Client resends request with the signed payment in the header +5. Gateway verifies payment and processes the request + +The payment address for all gateway requests: +`0xAd62f03C7514bb8c51f1eA70C2b75C37404695c8` + +## Important Notes + +- Free endpoints do not require x402 payment +- The gateway is chain-agnostic — specify the target chain per request +- Rate limiting applies: check `X-RateLimit-*` response headers +- The Spraay MCP server (`@plagtech/spraay-x402-mcp`) wraps all these endpoints for LLM tool use diff --git a/sandboxes/spraay/skills/spraay-payments.md b/sandboxes/spraay/skills/spraay-payments.md new file mode 100644 index 0000000..c764779 --- /dev/null +++ b/sandboxes/spraay/skills/spraay-payments.md @@ -0,0 +1,65 @@ +# Spraay Payments Skill + +Send tokens to one or many recipients on any of 13 supported blockchains using the Spraay x402 gateway. + +## When to Use + +Use this skill when the user or agent needs to: + +- Send tokens (USDC, ETH, MATIC, etc.) to one or more wallet addresses +- Execute batch payments to multiple recipients in a single transaction +- Distribute tokens across different chains +- Pay invoices, bounties, or rewards programmatically + +## Supported Chains + +Base, Ethereum, Arbitrum, Polygon, BNB Chain, Avalanche, Solana, Bitcoin, Stacks, Unichain, Plasma, BOB, Bittensor + +## How It Works + +1. The Spraay gateway uses the **x402 protocol** — HTTP 402 Payment Required +2. Each API call costs a small USDC fee (typically $0.01–$0.05) +3. The gateway executes the on-chain transaction after payment verification +4. Responses include transaction hashes for on-chain verification + +## Commands + +### Check balance +```bash +spraay balance --address 0xYourAddress --chain base --token USDC +``` + +### Send to multiple recipients +```bash +spraay batch-send \ + --recipients '[ + {"address": "0xRecipient1", "amount": "10.0"}, + {"address": "0xRecipient2", "amount": "25.0"}, + {"address": "0xRecipient3", "amount": "5.0"} + ]' \ + --token USDC \ + --chain base +``` + +### Get token price +```bash +spraay price --token ETH --chain base +``` + +## Important Notes + +- Always verify the recipient addresses before sending +- Check balances before executing batch sends +- The `SPRAAY_PAYMENT_ADDRESS` environment variable must be set +- All amounts are in human-readable format (e.g., "1.0" = 1 USDC) +- Transaction fees are paid in USDC via x402 on top of the transfer amount + +## Error Handling + +- HTTP 402: Payment required — agent wallet needs USDC for the gateway fee +- HTTP 400: Invalid parameters — check addresses and amounts +- HTTP 503: Chain RPC unavailable — retry or try a different RPC + +## API Reference + +Full endpoint documentation: https://docs.spraay.app diff --git a/sandboxes/spraay/skills/spraay-rtp.md b/sandboxes/spraay/skills/spraay-rtp.md new file mode 100644 index 0000000..571fe43 --- /dev/null +++ b/sandboxes/spraay/skills/spraay-rtp.md @@ -0,0 +1,78 @@ +# Spraay RTP (Robot Task Protocol) Skill + +Hire robots and IoT devices to perform physical tasks using x402 USDC micropayments. + +## When to Use + +Use this skill when the user or agent needs to: + +- Discover available robots or IoT devices on the network +- Commission a physical task (delivery, sensing, manufacturing, etc.) +- Pay for robot services via automated micropayments +- Monitor task execution status and completion + +## What is RTP? + +The Robot Task Protocol (RTP) is an open standard for AI agents to hire robots via x402 USDC micropayments. It bridges the digital agent world with physical robotics infrastructure. + +- **Spec**: https://github.com/plagtech/rtp-spec +- **SDK**: https://github.com/plagtech/rtp-sdk +- **Gateway endpoints**: Category 15 on the Spraay gateway (v3.4.0+) + +## Commands + +### Discover available devices +```bash +spraay rtp-discover +spraay rtp-discover --category robotics +spraay rtp-discover --category sensing +spraay rtp-discover --category delivery +``` + +### Hire a robot for a task +```bash +spraay rtp-hire '{ + "deviceId": "device-abc-123", + "task": "Capture temperature reading at location A", + "maxBudget": "0.05", + "chain": "base", + "callback": "https://your-webhook.com/rtp-result" +}' +``` + +### Check task status +```bash +spraay rtp-status +``` + +## Task Lifecycle + +1. **Discovery**: Agent queries available devices and capabilities +2. **Negotiation**: Agent reviews pricing and selects a device +3. **Hire**: Agent sends x402 micropayment to commission the task +4. **Execution**: Device performs the physical task +5. **Completion**: Device reports results; agent receives callback +6. **Verification**: On-chain proof of task completion + +## Supported Device Categories + +- `robotics` — Robotic arms, humanoids, manipulators +- `sensing` — Environmental sensors, cameras, LiDAR +- `delivery` — Drones, autonomous vehicles, couriers +- `manufacturing` — 3D printers, CNC, assembly +- `compute` — Edge GPU nodes, inference endpoints + +## Important Notes + +- RTP tasks are paid upfront via x402 micropayments +- Device availability depends on the RTP network in your region +- Task results are delivered via webhook callback or polling +- All payments are in USDC on Base by default +- This integrates with NVIDIA's Physical AI stack for robotics applications + +## Error Handling + +- HTTP 402: Payment required for task commissioning +- HTTP 404: Device not found or task ID invalid +- HTTP 408: Task timed out — device did not respond +- HTTP 503: RTP network unavailable diff --git a/sandboxes/spraay/spraay.sh b/sandboxes/spraay/spraay.sh new file mode 100644 index 0000000..bc9770d --- /dev/null +++ b/sandboxes/spraay/spraay.sh @@ -0,0 +1,277 @@ +#!/usr/bin/env bash +# spraay — CLI wrapper for the Spraay x402 gateway +# Usage: spraay [options] +# +# This script provides a thin wrapper around the Spraay gateway API, +# designed for use by AI agents inside an OpenShell sandbox. + +set -euo pipefail + +GATEWAY="${SPRAAY_GATEWAY_URL:-https://gateway.spraay.app}" +CHAIN="${SPRAAY_CHAIN:-base}" + +# ── Helpers ────────────────────────────────────────────────────────────────── + +usage() { + cat < [options] + +COMMANDS + health Check gateway status + info Show gateway info and supported chains + routes List all available routes and pricing + chains List supported blockchains + + batch-send Send tokens to multiple recipients + escrow-create Create an escrow contract + escrow-release Release escrow funds + escrow-status Check escrow status + + swap Execute a token swap + price Get token price + balance Check wallet balance + + rtp-discover Discover available robots/devices + rtp-hire Hire a robot for a task + rtp-status Check task status + + payroll-run Execute a payroll batch + payroll-schedule Schedule recurring payroll + + raw Make a raw gateway request + +ENVIRONMENT + SPRAAY_GATEWAY_URL Gateway URL (default: https://gateway.spraay.app) + SPRAAY_PAYMENT_ADDRESS Your wallet address for x402 payments + SPRAAY_CHAIN Default chain (default: base) + +EXAMPLES + spraay health + spraay routes + spraay balance --address 0x1234... --chain base + spraay batch-send --recipients '[{"address":"0x...","amount":"1.0"}]' --token USDC + spraay rtp-discover --category robotics +EOF +} + +gateway_get() { + local path="$1" + shift + curl -sf -H "Content-Type: application/json" "${GATEWAY}${path}" "$@" +} + +gateway_post() { + local path="$1" + local data="$2" + shift 2 + curl -sf -X POST \ + -H "Content-Type: application/json" \ + -d "${data}" \ + "${GATEWAY}${path}" "$@" +} + +# ── Commands ───────────────────────────────────────────────────────────────── + +cmd_health() { + gateway_get "/health" | jq . +} + +cmd_info() { + gateway_get "/v1/info" | jq . +} + +cmd_routes() { + gateway_get "/v1/routes" | jq . +} + +cmd_chains() { + gateway_get "/v1/chains" | jq . +} + +cmd_balance() { + local address="${SPRAAY_PAYMENT_ADDRESS:-}" + local chain="${CHAIN}" + local token="USDC" + + while [[ $# -gt 0 ]]; do + case "$1" in + --address) address="$2"; shift 2 ;; + --chain) chain="$2"; shift 2 ;; + --token) token="$2"; shift 2 ;; + *) echo "Unknown option: $1" >&2; exit 1 ;; + esac + done + + if [[ -z "$address" ]]; then + echo "Error: --address required or set SPRAAY_PAYMENT_ADDRESS" >&2 + exit 1 + fi + + gateway_get "/v1/balance?address=${address}&chain=${chain}&token=${token}" | jq . +} + +cmd_price() { + local token="" + local chain="${CHAIN}" + + while [[ $# -gt 0 ]]; do + case "$1" in + --token) token="$2"; shift 2 ;; + --chain) chain="$2"; shift 2 ;; + *) echo "Unknown option: $1" >&2; exit 1 ;; + esac + done + + if [[ -z "$token" ]]; then + echo "Error: --token required" >&2 + exit 1 + fi + + gateway_get "/v1/price?token=${token}&chain=${chain}" | jq . +} + +cmd_batch_send() { + local recipients="" + local token="USDC" + local chain="${CHAIN}" + + while [[ $# -gt 0 ]]; do + case "$1" in + --recipients) recipients="$2"; shift 2 ;; + --token) token="$2"; shift 2 ;; + --chain) chain="$2"; shift 2 ;; + *) echo "Unknown option: $1" >&2; exit 1 ;; + esac + done + + if [[ -z "$recipients" ]]; then + echo "Error: --recipients required (JSON array)" >&2 + exit 1 + fi + + local payload + payload=$(jq -n \ + --argjson recipients "${recipients}" \ + --arg token "${token}" \ + --arg chain "${chain}" \ + '{recipients: $recipients, token: $token, chain: $chain}') + + gateway_post "/v1/batch-send" "${payload}" | jq . +} + +cmd_escrow_create() { + local data="$1" + gateway_post "/v1/escrow/create" "${data}" | jq . +} + +cmd_escrow_release() { + local escrow_id="$1" + gateway_post "/v1/escrow/release" "{\"escrowId\": \"${escrow_id}\"}" | jq . +} + +cmd_escrow_status() { + local escrow_id="$1" + gateway_get "/v1/escrow/status?escrowId=${escrow_id}" | jq . +} + +cmd_swap() { + local from_token="" + local to_token="" + local amount="" + local chain="${CHAIN}" + + while [[ $# -gt 0 ]]; do + case "$1" in + --from) from_token="$2"; shift 2 ;; + --to) to_token="$2"; shift 2 ;; + --amount) amount="$2"; shift 2 ;; + --chain) chain="$2"; shift 2 ;; + *) echo "Unknown option: $1" >&2; exit 1 ;; + esac + done + + local payload + payload=$(jq -n \ + --arg from "${from_token}" \ + --arg to "${to_token}" \ + --arg amount "${amount}" \ + --arg chain "${chain}" \ + '{fromToken: $from, toToken: $to, amount: $amount, chain: $chain}') + + gateway_post "/v1/swap" "${payload}" | jq . +} + +cmd_rtp_discover() { + local category="" + while [[ $# -gt 0 ]]; do + case "$1" in + --category) category="$2"; shift 2 ;; + *) echo "Unknown option: $1" >&2; exit 1 ;; + esac + done + + if [[ -n "$category" ]]; then + gateway_get "/v1/rtp/discover?category=${category}" | jq . + else + gateway_get "/v1/rtp/discover" | jq . + fi +} + +cmd_rtp_hire() { + local data="$1" + gateway_post "/v1/rtp/hire" "${data}" | jq . +} + +cmd_rtp_status() { + local task_id="$1" + gateway_get "/v1/rtp/status?taskId=${task_id}" | jq . +} + +cmd_payroll_run() { + local data="$1" + gateway_post "/v1/payroll/run" "${data}" | jq . +} + +cmd_payroll_schedule() { + local data="$1" + gateway_post "/v1/payroll/schedule" "${data}" | jq . +} + +cmd_raw() { + local method="${1:-GET}" + local path="${2:-/}" + local data="${3:-}" + + if [[ "$method" == "POST" && -n "$data" ]]; then + gateway_post "${path}" "${data}" | jq . + else + gateway_get "${path}" | jq . + fi +} + +# ── Router ─────────────────────────────────────────────────────────────────── + +case "${1:-help}" in + health) shift; cmd_health "$@" ;; + info) shift; cmd_info "$@" ;; + routes) shift; cmd_routes "$@" ;; + chains) shift; cmd_chains "$@" ;; + balance) shift; cmd_balance "$@" ;; + price) shift; cmd_price "$@" ;; + batch-send) shift; cmd_batch_send "$@" ;; + escrow-create) shift; cmd_escrow_create "$@" ;; + escrow-release) shift; cmd_escrow_release "$@" ;; + escrow-status) shift; cmd_escrow_status "$@" ;; + swap) shift; cmd_swap "$@" ;; + rtp-discover) shift; cmd_rtp_discover "$@" ;; + rtp-hire) shift; cmd_rtp_hire "$@" ;; + rtp-status) shift; cmd_rtp_status "$@" ;; + payroll-run) shift; cmd_payroll_run "$@" ;; + payroll-schedule) shift; cmd_payroll_schedule "$@" ;; + raw) shift; cmd_raw "$@" ;; + help|--help|-h) usage ;; + *) echo "Unknown command: $1" >&2; usage; exit 1 ;; +esac