--- name: orchestration description: How an AI agent plans, builds, and deploys a complete Hyperliquid application. The three-phase build system for HyperEVM dApps and HyperCore integrations. Use when building any full application on Hyperliquid. --- # dApp Orchestration on Hyperliquid ## What You Probably Got Wrong **"I'll just deploy to mainnet immediately."** Never skip testnet. HyperEVM testnet (chain ID 998) and HyperCore testnet API are available. Test there first. Mainnet mistakes cost real HYPE and USDC. **"I'll handle HyperCore and HyperEVM separately."** Plan both layers from the start. If your app uses HyperEVM contracts AND HyperCore API, coordinate them from day one. Late integration always reveals architectural problems. **"Secrets in env are fine."** AI agents are the #1 source of leaked credentials. Before committing anything, verify no private keys or API credentials are in the codebase. --- ## The Three-Phase Build System | Phase | Environment | What Happens | |-------|-------------|-------------| | **Phase 1** | Local + testnet | Contracts on testnet, HyperCore testnet API. Iterate fast. | | **Phase 2** | Mainnet contracts + local UI | Deploy to mainnet. Test with real state. Polish UI. | | **Phase 3** | Production | Deploy frontend. Final QA. Monitor. | --- ## Phase 1: Build and Test Locally ### 1.1 HyperEVM Contracts ```bash # Fork HyperEVM mainnet for local testing anvil --fork-url https://rpc.hyperliquid.xyz/evm --chain-id 999 # Or work against testnet directly # Chain ID: 998, RPC: https://rpc.hyperliquid-testnet.xyz/evm ``` **Contract development flow:** 1. Write contracts in `src/` (Foundry) or `contracts/` (Hardhat) 2. Write deploy scripts 3. Write tests (≥90% coverage of custom logic) 4. Run security checklist (`security/SKILL.md`) 5. Deploy to testnet ```bash # Deploy to HyperEVM testnet forge create src/MyVault.sol:MyVault \ --rpc-url https://rpc.hyperliquid-testnet.xyz/evm \ --private-key $PRIVATE_KEY \ --broadcast # Run tests forge test -vvv forge test --fuzz-runs 1000 ``` ### 1.2 HyperCore API Integration **Test against the testnet API, never mainnet:** ```python # .env HYPERLIQUID_API_URL=https://api.hyperliquid-testnet.xyz PRIVATE_KEY=0x... # Testnet wallet key # config.py import os from hyperliquid.info import Info from hyperliquid.exchange import Exchange from hyperliquid.utils import constants from eth_account import Account def get_clients(): wallet = Account.from_key(os.environ['PRIVATE_KEY']) api_url = os.environ.get('HYPERLIQUID_API_URL', constants.MAINNET_API_URL) return Info(api_url), Exchange(wallet, api_url) ``` ```typescript // TypeScript: environment-based config const isTestnet = process.env.HYPERLIQUID_TESTNET === 'true'; const client = new HyperliquidClient({ testnet: isTestnet }); ``` **Validate Phase 1:** - [ ] All contract tests pass - [ ] HyperCore API integration tested on testnet - [ ] Nonce handling tested (concurrent orders, high frequency) - [ ] Bridge operations tested (HyperCore ↔ HyperEVM) - [ ] Error cases handled (rejected orders, insufficient balance, price out of range) ### 1.3 Frontend (Local) ```typescript // For development, point at testnet const CHAIN_CONFIG = process.env.NODE_ENV === 'development' ? { chainId: 998, rpcUrl: 'https://rpc.hyperliquid-testnet.xyz/evm', } : { chainId: 999, rpcUrl: 'https://rpc.hyperliquid.xyz/evm', }; ``` **Use ONE loading state per button.** Each button has its own `isLoading` / `isPending` state. Never share. **Four-state flow (MANDATORY for token interactions):** 1. Not connected → Connect Wallet button 2. Wrong network → Switch to HyperEVM button 3. Needs approval → Approve button 4. Ready → Action button ```typescript const needsApproval = !allowance || allowance < amount; const wrongNetwork = chain?.id !== 999; // HyperEVM mainnet const notConnected = !address; {notConnected ? ( ) : wrongNetwork ? ( ) : needsApproval ? ( ) : ( )} ``` --- ## 🚨 NEVER COMMIT SECRETS TO GIT Before touching Phase 2 (real mainnet), read this carefully. **This applies to ALL credentials:** - Wallet private keys (HyperEVM + HyperCore signing key) - Agent wallet private keys - RPC URLs with embedded API keys - Any API credentials ```bash # .gitignore MUST include: .env .env.* *.key *.pem secrets/ __pycache__/ ``` **Pre-commit check:** ```bash # Check for private keys grep -rn "0x[a-fA-F0-9]\{64\}" src/ contracts/ --include="*.ts" --include="*.py" --include="*.sol" # If this matches ANYTHING in source files, STOP. Use environment variables. # Check for hardcoded RPC keys grep -rn "alchemyapi.io\|infura.io" src/ contracts/ ``` --- ## Phase 2: Deploy to Mainnet ### HyperEVM Contract Deployment ```bash # Deploy to HyperEVM mainnet forge create src/MyVault.sol:MyVault \ --rpc-url https://rpc.hyperliquid.xyz/evm \ --private-key $PRIVATE_KEY \ --broadcast \ --verify \ --verifier blockscout \ --verifier-url https://explorer.hyperliquid.xyz/api # Record the deployed address in your config export CONTRACT_ADDRESS=0x... ``` **Post-deployment checklist:** - [ ] Contract verified on https://explorer.hyperliquid.xyz - [ ] Ownership transferred to multisig (not EOA) for production - [ ] All read functions return expected values - [ ] Test one small transaction end-to-end - [ ] Bridge a small amount of HYPE to test the bridge ### HyperCore Integration: Switch to Mainnet ```python # Switch from testnet to mainnet import os # ONLY change the API URL — everything else is the same API_URL = os.environ.get('HYPERLIQUID_API_URL', 'https://api.hyperliquid.xyz') # Default to mainnet # Verify you're on the right network before first trade info = Info(API_URL) meta = info.meta() print(f"Connected to: {API_URL}") print(f"Universe has {len(meta['universe'])} perp markets") ``` **Start with tiny amounts.** First real mainnet test: the smallest allowed order. Verify everything before scaling. ### Frontend Update ```typescript // Update for production const wagmiConfig = createConfig({ chains: [hyperliquid], // Chain ID 999 transports: { [hyperliquid.id]: http(process.env.NEXT_PUBLIC_HL_RPC_URL || 'https://rpc.hyperliquid.xyz/evm'), }, }); ``` **Design rule:** Make the UI actually good. No placeholder styling, no LLM-default purple gradients. --- ## Phase 3: Production Deploy ### Pre-Deploy Checklist - [ ] All testnet tests passing - [ ] Contracts deployed and verified on mainnet - [ ] HyperCore integration verified with small real orders - [ ] No hardcoded testnet values in production code - [ ] Secrets in environment variables, not in code - [ ] Agent wallet funded and approved (if using automated trading) ### Frontend Deployment **Vercel (recommended for Hyperliquid dApps):** ```bash cd packages/nextjs vercel --prod ``` **IPFS (decentralized alternative):** ```bash yarn build # Upload to IPFS — any IPFS pinning service works # Set next.config trailingSlash: true for IPFS routing ``` ### Production QA Before going live, fetch `qa/SKILL.md` and give it to a separate reviewer agent. Key HyperEVM-specific QA items: - [ ] Chain ID 999 in all mainnet config - [ ] HYPE shown as gas token everywhere (not ETH) - [ ] "Switch to HyperEVM" button works (not "Switch to Ethereum") - [ ] USDC shown as 6 decimals - [ ] HyperCore/HyperEVM bridge flows tested - [ ] Block explorer links point to https://explorer.hyperliquid.xyz --- ## Monitoring Post-Launch ### HyperEVM Contract Monitoring ```typescript // Watch for contract events in real-time const unwatch = publicClient.watchContractEvent({ address: contractAddress, abi: vaultAbi, eventName: 'Deposit', onLogs: (logs) => { for (const log of logs) { console.log(`Deposit: ${log.args.amount} from ${log.args.user}`); } }, }); ``` ### HyperCore Position Monitoring ```python import asyncio import websockets import json # WebSocket for real-time updates async def monitor_fills(address): async with websockets.connect('wss://api.hyperliquid.xyz/ws') as ws: # Subscribe to user fills await ws.send(json.dumps({ "method": "subscribe", "subscription": {"type": "userFills", "user": address} })) async for message in ws: data = json.loads(message) if data.get('channel') == 'userFills': for fill in data['data']: print(f"Fill: {fill['coin']} {fill['side']} {fill['sz']} @ {fill['px']}") ``` --- ## Key Directories for Foundry + Next.js Projects ``` my-project/ ├── src/ # Solidity contracts ├── script/ # Deploy scripts ├── test/ # Foundry tests ├── lib/ # Dependencies (OpenZeppelin, etc.) ├── foundry.toml # Chain configs ├── frontend/ │ ├── app/ # Pages │ ├── components/ # React components │ ├── lib/ │ │ ├── chains.ts # HyperEVM chain definitions │ │ ├── wagmi.ts # wagmi config │ │ └── hypercore.ts # HyperCore API helpers │ └── .env.local # NEVER COMMIT THIS └── .gitignore # Includes .env* ```