Native On-chain Banking for AI Agents w/ Visa & Ethereum Integration

Nuro is a bank for AI agents. For ETHGlobal we integrated three partners into one product shell.
ENS: Every user and agent gets a name under our namespace (yourbiz.nurofi.eth, agent-yourbiz.nurofi.eth). Claims happen in onboarding, live in Postgres, and resolve through our Cloudflare CCIP Read gateway so names work like standard ENS without paying gas on every registration. Send in My Wallet accepts ENS and resolves before the tx goes out.
Privy: Login plus external wallet connect. Users link MetaMask, Coinbase Wallet, or Uniswap Wallet on their phone through WalletConnect. Privy owns the session and signing path so swaps run from the user's real wallet, not a mock address in the UI.
Uniswap: Live swaps on Base (chain 8453). We pull firm quotes from the Uniswap Trading API, build executable calldata on our Express backend, and the user signs in their Privy connected wallet. ETH to USDC with a real on chain tx and hash in the app.
Everything sits inside the full Nuro dashboard: cards, agent wallets, transactions, vault. Demo: log in, claim your ENS name, connect wallet, swap on Base. Live at https://ethglobal.nuro.finance. Code at https://github.com/Nuro-Finance/Eth_Global_Hackathon.
Stack: Next.js 15 (App Router) on port 2800, Express API in TypeScript on port 3000, Postgres for users, cards, wallet state, and ENS claims. Production at https://ethglobal.nuro.finance.
ENS: We run a Cloudflare Worker (workers/nuro-ens-gateway) as a CCIP Read gateway with D1 storing name records. Onboarding hits /api/ens/check for slug availability, writes the claim to ens_claims in Postgres, then syncs addr records to the gateway through gatewaySync.ts. Business names are slug.nurofi.eth. Agent names are agentslug-businessslug.nurofi.eth. My Wallet Send resolves ENS via /api/ens/resolve before building the transaction. The hacky part: scalable subnames without an L1 registration tx per user. Resolver data is served offchain through EIP-3668 CCIP Read but still resolves in normal ENS clients.
Privy: PrivyProvider handles email, Google, and wallet login. External wallets connect through useConnectWallet with Uniswap, MetaMask, Coinbase, and WalletConnect in the wallet list. Swap signing uses useWallets() plus a viem createWalletClient on the Privy provider. We had to do this because WalletConnect to Uniswap Wallet on iOS was failing when we routed signing through wagmi or raw eth_sendTransaction. The taker address is pinned to the Privy connected wallet and chain switch runs inside the sign flow right before the tx goes out.
Uniswap: Firm quotes hit Express /quote/swap-firm, which calls the Uniswap Trading API on Base (8453) and returns executable to, data, and value. Next.js proxies preview quotes through /api/quote/swap. The client fetches a firm quote at sign time, switches the wallet to Base if needed, then signs with viem. ConnectedWalletDashboard in My Wallet and useBaseSwapExecutor in Reload share the same executor pattern end to end.
Hack note: When a user claims their ENS name in onboarding we do not stop at a UI label. We sign a gateway payload that writes the same wallet address under two coin types in one shot: Ethereum mainnet (60) and Base via ENSIP-11 (2147492101). That means yourbiz.nurofi.eth resolves on L1 for Send and on Base where the Uniswap swap actually executes. One name claim, two chains, same address from the Privy connected wallet. The identity layer and the swap layer share one identity without the user registering on chain twice or paying L1 gas per subname.

