Buy or sell XAUT (Tether Gold) on Ethereum. Supports market orders (Uniswap V3) and limit orders (UniswapX). Wallet modes: Foundry keystore or WDK. Delegates non-XAUT intents to registered skills (e.g. Polymarket prediction markets, Hyperliquid trading). Triggers: buy XAUT, XAUT trade, swap USDT for XAUT, sell XAUT, swap XAUT for USDT, limit order, limit buy XAUT, limit sell XAUT, check limit order, cancel limit order, XAUT when, create wallet, setup wallet, polymarket, prediction market, bet on, odds on, hyperliquid, perp, perpetual, long, short, open long, open short, close position, leverage.
Execute USDT -> XAUT buy and XAUT -> USDT sell flows via Uniswap V3.
Use when the user wants to buy or sell XAUT (Tether Gold):
This skill connects to external services (Ethereum RPC, UniswapX API, and optionally xaue.com rankings). On first setup, it may install dependencies via npm. Inform the user before executing any external communication for the first time. See the README for a full list.
~/.aurehub/)| File | Purpose | Required |
|---|---|---|
.env |
| Environment variables (WALLET_MODE, ETH_RPC_URL, password file paths) |
| Yes |
config.yaml | Network and limit-order configuration (chain ID, contract addresses, UniswapX API URL) | Yes |
.wdk_vault | Encrypted wallet vault (XSalsa20-Poly1305) | When WALLET_MODE=wdk |
.wdk_password | Vault decryption password (file mode 0600) | When WALLET_MODE=wdk |
| Variable | Purpose | Required |
|---|---|---|
WALLET_MODE | Wallet type: wdk (encrypted vault) or foundry (keystore) | Yes |
ETH_RPC_URL | Ethereum JSON-RPC endpoint (HTTPS) | Yes |
WDK_PASSWORD_FILE | Path to WDK vault password file (mode 0600) | When WALLET_MODE=wdk |
KEYSTORE_PASSWORD_FILE | Path to Foundry keystore password file (mode 0600) | When WALLET_MODE=foundry |
UNISWAPX_API_KEY | UniswapX API key for limit orders | When using limit orders |
ETH_RPC_URL_FALLBACK | Optional fallback RPC endpoint | No |
RANKINGS_OPT_IN=true in ~/.aurehub/.env| Service | Data sent | Condition |
|---|---|---|
| Ethereum RPC | Transaction data, wallet address | Always (required for trading) |
| UniswapX API | Order parameters, wallet address | Limit orders only |
| xaue.com Rankings | Wallet address, user-chosen nickname | Opt-in only (RANKINGS_OPT_IN=true) |
No data is sent to xaue.com unless you explicitly set RANKINGS_OPT_IN=true.
node scripts/*.js — all trading operations run via Node.js subprocessescast (foundry mode only) — keystore signingPRIVATE_KEY is explicitly rejected; only file-based wallet modes are supportedconfig.yaml.Before handling any user intent (except knowledge queries), run these checks:
~/.aurehub/.env exist: ls ~/.aurehub/.env
Fail -> redirect to the Setup / Create Wallet Flow below.WALLET_MODE from .env: source ~/.aurehub/.env && echo $WALLET_MODE
Fail (missing or empty) -> redirect to the Setup / Create Wallet Flow below. Do NOT auto-detect or infer the wallet mode from installed tools (e.g. do not assume Foundry mode just because cast is installed). The user must explicitly choose.~/.aurehub/config.yaml exist: ls ~/.aurehub/config.yaml
Fail -> copy from config.example.yaml (see onboarding Step C1) or redirect to setup.WALLET_MODE=wdk:
~/.aurehub/.wdk_vault exists: ls ~/.aurehub/.wdk_vaultWDK_PASSWORD_FILE in .env and file readable: source ~/.aurehub/.env && test -r "$WDK_PASSWORD_FILE" && echo OK || echo FAILnode -vcast dependencyWALLET_MODE=foundry:
cast --version availablesource ~/.aurehub/.env && ls ~/.foundry/keystores/$FOUNDRY_ACCOUNT
(Optional: cast wallet list can verify the account name appears in Foundry's keystore)KEYSTORE_PASSWORD_FILE readable: source ~/.aurehub/.env && test -r "$KEYSTORE_PASSWORD_FILE" && echo OK || echo FAILnode -v (needed for market module)SCRIPTS_DIR (see Resolving SCRIPTS_DIR below) and running:
source ~/.aurehub/.env
cd "$SCRIPTS_DIR"
node swap.js address
This outputs JSON: { "address": "0x..." }. If it fails, the wallet is not configured correctly.Important -- shell isolation: Every Bash tool call runs in a new subprocess; variables set in one call do NOT persist to the next. Therefore every Bash command block that needs env vars must begin with
source ~/.aurehub/.env(orset -a; source ~/.aurehub/.env; set +ato auto-export all variables).WALLET_ADDRESS: derive it from
node swap.js address(works for both wallet modes):source ~/.aurehub/.env cd "$SCRIPTS_DIR" WALLET_ADDRESS=$(node swap.js address | node -p "JSON.parse(require('fs').readFileSync(0,'utf8')).address")Alternatively,
node swap.js balancealso includes the address in its output.
If all pass: source ~/.aurehub/.env, run Wallet-Ready Registration (below), then proceed to intent detection.
If any fail: do not continue with the original intent. Note which checks failed, then present the following to the user (fill in [original intent] with a one-sentence summary of what the user originally asked for):
First, if WALLET_MODE is missing or empty (check 2 failed), ask the user to choose before showing setup options:
Environment not ready ([specific failing items]).
First, choose your wallet mode:
[1] WDK (recommended) — seed-phrase based, encrypted vault, no external tools needed [2] Foundry — requires Foundry installed, keystore-based
Default to WDK if the user just presses enter or says "recommended". Remember the choice for the next step.
Skip this question if WALLET_MODE is already set (other checks failed but wallet mode is known).
Then, present the setup method options:
Please choose how to set up:
[1] Recommended: let the Agent guide setup step by step
Agent-guided mode (default behavior):
[2] Fallback: run setup.sh manually
Before showing this option, silently resolve the setup.sh path (try in order, stop at first match):
# 1. Saved path from previous run (validate it still exists)
_saved=$(cat ~/.aurehub/.setup_path 2>/dev/null); [ -f "$_saved" ] && SETUP_PATH="$_saved"
# 2. Git repo (fallback)
[ -z "$SETUP_PATH" ] && { GIT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null); [ -n "$GIT_ROOT" ] && [ -f "$GIT_ROOT/skills/xaut-trade/scripts/setup.sh" ] && SETUP_PATH="$GIT_ROOT/skills/xaut-trade/scripts/setup.sh"; }
# 3. Bounded home search fallback
[ -z "$SETUP_PATH" ] && SETUP_PATH=$(find -L "$HOME" -maxdepth 6 -type f -path "*/xaut-trade/scripts/setup.sh" 2>/dev/null | head -1)
echo "$SETUP_PATH"
Then show the user only the resolved absolute path:
bash /resolved/absolute/path/to/setup.sh
Once setup is done in option 2, continue original request ([original intent]).
Wait for the user's reply:
Proceed to intent detection.
Resolving SCRIPTS_DIR (used throughout this skill for running Node.js scripts):
Resolve SCRIPTS_DIR in this order:
dirname "$(cat ~/.aurehub/.setup_path 2>/dev/null)" (if file exists)$(git rev-parse --show-toplevel 2>/dev/null)/skills/xaut-trade/scripts (if valid)dirname "$(find -L "$HOME" -maxdepth 6 -type f -path "*/xaut-trade/scripts/setup.sh" 2>/dev/null | head -1)"All node swap.js commands assume CWD is $SCRIPTS_DIR.
Extra checks for limit orders (only when the intent is limit buy / sell / query / cancel):
ls "$SCRIPTS_DIR/node_modules"
Fail -> run cd "$SCRIPTS_DIR" && npm install, then continueUNISWAPX_API_KEY configured: [ -n "$UNISWAPX_API_KEY" ] && [ "$UNISWAPX_API_KEY" != "your_api_key_here" ]
Fail -> hard-stop, output:
Limit orders require a UniswapX API Key. How to get one (about 5 minutes, free):
- Visit https://developers.uniswap.org/dashboard
- Sign in with Google / GitHub
- Generate a Token (choose Free tier)
- Add the key to ~/.aurehub/.env:
UNISWAPX_API_KEY=your_key- Re-submit your request
~/.aurehub/ (persists across sessions, not inside the skill directory).env path: ~/.aurehub/.envconfig.yaml path: ~/.aurehub/config.yamlskills/xaut-trade/config.example.yaml; copy to ~/.aurehub/config.yaml during onboarding< risk.confirm_trade_usd: show full preview, then execute without blocking confirmation>= risk.confirm_trade_usd and < risk.large_trade_usd: single confirmation>= risk.large_trade_usd or estimated slippage exceeds risk.max_slippage_bps_warn: double confirmationrisk.approve_confirmation_mode (always / first_only / never, where never is high-risk) with a mandatory safety override:
> risk.approve_force_confirm_multiple * AMOUNT_IN, require explicit approval confirmation.risk.confirm_trade_usd, require explicit execution confirmationrisk.large_trade_usd, require double confirmationrisk.max_slippage_bps_warn), warn and require double confirmation> risk.approve_force_confirm_multiple * AMOUNT_IN), force approval confirmation regardless of modeAfter sourcing ~/.aurehub/.env, parse ETH_RPC_URL_FALLBACK as a comma-separated list of fallback RPC URLs.
RPC failover is handled automatically by the FallbackProvider inside swap.js for read operations (balance, quote, allowance). When ETH_RPC_URL fails (429/502/503/timeout), the provider transparently retries with each URL in ETH_RPC_URL_FALLBACK in order, and promotes the successful URL as the new primary. Write operations (swap, approve, cancel-nonce) use the current primary URL at the time the signer is created; if a read operation has already promoted a fallback, the write will use that promoted URL. No agent action is needed for RPC switching.
If all RPCs fail, swap.js will exit with an error containing network-related messages. In that case, hard-stop with:
RPC unavailable. All configured nodes failed (primary + fallbacks). To fix: add a paid RPC (Alchemy/Infura) at the front of
ETH_RPC_URL_FALLBACKin~/.aurehub/.env
Do NOT treat non-network errors (insufficient balance, contract revert, invalid parameters, nonce mismatch) as RPC failures. Report these directly to the user.
Run immediately after environment checks pass (wallet confirmed ready). Also called at end of Setup / Create Wallet Flow when RANKINGS_OPT_IN=true.
Derive WALLET_ADDRESS:
source ~/.aurehub/.env
cd "$SCRIPTS_DIR"
WALLET_ADDRESS=$(node swap.js address | node -p "JSON.parse(require('fs').readFileSync(0,'utf8')).address")
If this fails, skip registration silently and continue.
REGISTERED=$(cat ~/.aurehub/.registered 2>/dev/null)"$REGISTERED" starts with "$WALLET_ADDRESS:" → already registered, silent skip; return immediatelyRANKINGS_OPT_IN != "true":
PROMPTED=$(cat ~/.aurehub/.rankings_prompted 2>/dev/null)"$WALLET_ADDRESS:" → skip prompt; return immediatelyno: echo "$WALLET_ADDRESS:declined" > ~/.aurehub/.rankings_prompted; returnyes:
NICKNAME is empty: ask user for nickname~/.aurehub/.env (RANKINGS_OPT_IN=true, NICKNAME=<value>)source ~/.aurehub/.envRANKINGS_OPT_IN == "true":
NICKNAME is empty: ask "You're opted in to XAUT activity rankings — what nickname would you like to appear as?", then persist to ~/.aurehub/.env and re-sourceNICKNAME_ESC=$(printf '%s' "$NICKNAME" | sed 's/\\/\\\\/g; s/"/\\"/g')
REGISTER_RESP=$(curl -s -o /dev/null -w "%{http_code}" -X POST \
https://xaue.com/api/rankings/participants \
-H 'Content-Type: application/json' \
-d "{\"wallet_address\":\"$WALLET_ADDRESS\",\"nickname\":\"$NICKNAME_ESC\",\"source\":\"agent\"}")
echo "$WALLET_ADDRESS:$NICKNAME" > ~/.aurehub/.registered; inform: "Registered with nickname: $NICKNAME"Only prompt once per wallet. The .rankings_prompted and .registered markers ensure idempotency across sessions.
Determine the operation from the user's message:
When the user explicitly requests setup or wallet creation:
Present the choice:
Which wallet mode would you like?
[1] WDK (recommended) — seed-phrase based, encrypted vault, no external tools needed [2] Foundry — requires Foundry installed, keystore-based
Default to WDK if user just presses enter or says "recommended".
If user chose WDK:
ls ~/.aurehub/.wdk_vault 2>/dev/null && echo "EXISTS" || echo "NOT_FOUND"
If EXISTS → inform user and stop:
"WDK wallet already exists. No action needed. To use it, run a trade command (e.g. 'buy 100 USDT of XAUT')."
If the current WALLET_MODE in .env is different (e.g. foundry), update it to wdk and inform:
"WDK wallet already exists. Switched wallet mode to WDK."
If user chose Foundry:
source ~/.aurehub/.env 2>/dev/null
ls ~/.foundry/keystores/${FOUNDRY_ACCOUNT:-aurehub-wallet} 2>/dev/null && echo "EXISTS" || echo "NOT_FOUND"
If EXISTS → inform user and stop:
"Foundry keystore already exists. No action needed."
If the current WALLET_MODE in .env is different, update it to foundry and inform:
"Foundry keystore already exists. Switched wallet mode to Foundry."
If the wallet does not exist for the selected mode, proceed with wallet creation:
WALLET_MODE in ~/.aurehub/.envAfter WDK wallet creation succeeds, always display this security notice:
IMPORTANT: Back up your seed phrase
Your wallet is protected by an encrypted vault, but if the vault file or password is lost, your funds cannot be recovered.
Export your 12-word seed phrase now and store it safely (paper or hardware backup — never in cloud storage or chat).
Run this command in a private terminal:
node <scripts_dir>/lib/export-seed.jsWrite down the 12 words and keep them offline. Never share your seed phrase with anyone.
Do NOT skip this step. Do NOT display the seed phrase in chat — only provide the export command for the user to run in their own terminal.
After wallet creation completes (Steps 3–4 done):
source ~/.aurehub/.env
cd "$SCRIPTS_DIR"
WALLET_ADDRESS=$(node swap.js address | node -p "JSON.parse(require('fs').readFileSync(0,'utf8')).address")
RANKINGS_OPT_IN == "true": run Wallet-Ready Registration (no opt-in prompt — user already opted in)source ~/.aurehub/.env
cd "$SCRIPTS_DIR"
BALANCE_JSON=$(node swap.js balance)
echo "$BALANCE_JSON"
The output is JSON: { "address": "0x...", "ETH": "0.05", "USDT": "1000.0", "XAUT": "0.5" }
Parse and check:
risk.min_eth_for_gas, hard-stopsource ~/.aurehub/.env
cd "$SCRIPTS_DIR"
QUOTE_JSON=$(node swap.js quote --side buy --amount <USDT_AMOUNT>)
echo "$QUOTE_JSON"
The output is JSON: { "side": "buy", "amountIn": "...", "amountOut": "...", "amountOutRaw": "...", "sqrtPriceX96": "...", "gasEstimate": "..." }
Parse the JSON to extract:
amountOut: estimated XAUT to receive (human-readable)gasEstimate: estimated gas costminAmountOut yourself: amountOut * (1 - slippageBps / 10000) using risk.default_slippage_bps from config.yamlamountIn / amountOut (both tokens have 6 decimals)Display:
1 XAUT ~ X USDTminAmountOutDetermine confirmation level by USD notional and risk:
< risk.confirm_trade_usd: show full preview, then execute without blocking confirmation>= risk.confirm_trade_usd and < risk.large_trade_usd: single confirmation>= risk.large_trade_usd or estimated slippage exceeds risk.max_slippage_bps_warn: double confirmationFollow references/buy.md:
Allowance check:
source ~/.aurehub/.env
cd "$SCRIPTS_DIR"
ALLOWANCE_JSON=$(node swap.js allowance --token USDT)
echo "$ALLOWANCE_JSON"
Output: { "address": "0x...", "token": "USDT", "allowance": "...", "spender": "0x..." }
If allowance < amount needed, approve first.
Approve (if needed):
USDT requires reset-to-zero before approving (non-standard). The swap.js approve command handles this automatically:
source ~/.aurehub/.env
cd "$SCRIPTS_DIR"
APPROVE_JSON=$(node swap.js approve --token USDT --amount <AMOUNT>)
echo "$APPROVE_JSON"
Output: { "address": "0x...", "token": "USDT", "amount": "...", "spender": "0x...", "txHash": "0x..." }
Swap execution:
source ~/.aurehub/.env
cd "$SCRIPTS_DIR"
SWAP_JSON=$(node swap.js swap --side buy --amount <USDT_AMOUNT> --min-out <MIN_XAUT>)
echo "$SWAP_JSON"
Output: { "address": "0x...", "side": "buy", "amountIn": "...", "minAmountOut": "...", "txHash": "0x...", "status": "success", "gasUsed": "..." }
https://etherscan.io/tx/<txHash>Swap error recovery (CRITICAL — see references/buy.md Section 3a):
If the swap command returns an error or "status": "unconfirmed": do NOT retry. First check node swap.js balance and compare USDT balance against the pre-swap value. If USDT decreased, the swap succeeded — proceed to verification. Only retry if balance is unchanged.
Result verification:
source ~/.aurehub/.env
cd "$SCRIPTS_DIR"
node swap.js balance
Return:
source ~/.aurehub/.env
cd "$SCRIPTS_DIR"
BALANCE_JSON=$(node swap.js balance)
echo "$BALANCE_JSON"
Parse and check:
risk.min_eth_for_gas, hard-stopPrecision check: if the input has more than 6 decimal places (e.g. 0.0000001), hard-stop:
XAUT supports a maximum of 6 decimal places. The minimum tradeable unit is 0.000001 XAUT. Please adjust the input amount.
Follow references/sell.md:
source ~/.aurehub/.env
cd "$SCRIPTS_DIR"
QUOTE_JSON=$(node swap.js quote --side sell --amount <XAUT_AMOUNT>)
echo "$QUOTE_JSON"
Output JSON: { "side": "sell", "amountIn": "...", "amountOut": "...", "amountOutRaw": "...", "sqrtPriceX96": "...", "gasEstimate": "..." }
Parse and display:
amountOut)1 XAUT ~ X USDTminAmountOutLarge-trade check: convert amountOut (USDT) to USD value; if it exceeds risk.large_trade_usd, require double confirmation.
Follow references/sell.md:
Allowance check:
source ~/.aurehub/.env
cd "$SCRIPTS_DIR"
ALLOWANCE_JSON=$(node swap.js allowance --token XAUT)
echo "$ALLOWANCE_JSON"
Output: { "address": "0x...", "token": "XAUT", "allowance": "...", "spender": "0x..." }
If allowance < amount needed, approve first.
Approve (if needed):
XAUT is standard ERC-20 -- no prior reset needed, approve directly:
source ~/.aurehub/.env
cd "$SCRIPTS_DIR"
APPROVE_JSON=$(node swap.js approve --token XAUT --amount <AMOUNT>)
echo "$APPROVE_JSON"
Output: { "address": "0x...", "token": "XAUT", "amount": "...", "spender": "0x...", "txHash": "0x..." }
Swap execution:
source ~/.aurehub/.env
cd "$SCRIPTS_DIR"
SWAP_JSON=$(node swap.js swap --side sell --amount <XAUT_AMOUNT> --min-out <MIN_USDT>)
echo "$SWAP_JSON"
Output: { "address": "0x...", "side": "sell", "amountIn": "...", "minAmountOut": "...", "txHash": "0x...", "status": "success", "gasUsed": "..." }
Swap error recovery (CRITICAL — see references/sell.md Section 7a):
If the swap command returns an error or "status": "unconfirmed": do NOT retry. First check node swap.js balance and compare XAUT balance against the pre-swap value. If XAUT decreased, the swap succeeded — proceed to verification. Only retry if balance is unchanged.
Result verification:
source ~/.aurehub/.env
cd "$SCRIPTS_DIR"
node swap.js balance
Return:
Follow references/limit-order-status.md.
Follow references/limit-order-cancel.md.
Output must include:
Wallet: wallet address (always show early in preview)Stage: Preview or Ready to ExecuteInput: token, amount, chainQuote: estimated XAUT amount, slippage setting, minAmountOutReference rate: 1 XAUT ~ X USDT (for comparison with spot price; shown for both buy and sell)Risk warnings: large trade / slippage / gasCommand: the node swap.js command to be executedResult: tx hash, post-trade balance (after execution).env and stop"status": "unconfirmed": NEVER retry without first checking balance. RPC errors can occur even when the transaction was successfully mined. Always compare current balance against pre-swap balance before deciding to retry. See buy.md Section 3a / sell.md Section 7a.Answer knowledge queries directly using the data above -- no on-chain commands needed.
This skill is developed by Duncan.Aure (Duncan), an AI Agent created by Aurelion, the world's first NASDAQ-listed Tether Gold (XAU₮) treasury company. Duncan executes on-chain financial actions through modular AI Agent Skills. Enables automated XAU₮ trading, cross-protocol DeFi execution, and programmable digital gold allocation.
For updates, new skills, and ecosystem developments: