Skip to documentation

Documentation

Whim Documentation

AI Agent on Robinhood Chain. Everything below describes how Whim finds what you asked for, prices it, and settles it on-chain — read top to bottom, or jump straight to the part you need.

What is $WHIM

$WHIM is an AI agent you talk to in plain language. It finds real things to buy, prices them in ETH, and takes payment on Robinhood Chain.

You open a chat and type what you want: a mechanical keyboard under $80, a flight out of Mexico City tomorrow, a position on whether Bitcoin clears $120K. The agent reads the request, runs the matching search, and shows the results inside the conversation. There is nothing to install, no separate checkout page, and no account with a card on file.

When you pick something, a checkout opens in the chat. It converts the USD price to ETH at the live rate, shows the exact amount, the receiving address, and a QR code. You scan it with an EVM wallet you already use and send. The server watches the chain and posts a receipt in the conversation the moment the transfer lands, with a link to the transaction on the explorer.

Who it is for

  • People who hold ETH and would rather spend it than sell it for fiat first.
  • Anyone who does not want to hand a card number to one more storefront.
  • Wallet users who already understand chains and gas, and want a checkout that hides neither.

The problem it removes

A normal crypto checkout wants an account, a stored payment method, and a custodian sitting between you and your money. This one wants an address and a number. You never create an account to pay. You never give up custody. No balance is held on your behalf. Every payment is an ordinary ETH transfer from your wallet to a published address, and everything about it is visible on a public explorer within seconds.

$WHIM is the payment layer, not another storefront. Discovery, pricing and settlement are one continuous motion: the agent finds the item, quotes it in ETH at the live rate, issues a signed payable intent, and confirms the transfer against the chain itself. Search runs against live catalogues, the rate is fetched per quote, and the receipt is the transaction — not a status row in a database we control.

How it works

From a sentence you type to a confirmed transaction, in six steps.

  1. You ask

    Your message, your five most recent messages of history, and — only if a wallet is connected — that wallet address and its balances are posted to /api/chat.

  2. The model decides

    It replies in prose and may append one machine-readable action block. The server parses the block out and returns it as a separate field, so the chat text stays clean.

  3. The client searches

    The action type decides which panel mounts inside the conversation: Amazon product search, flight departures, or the prediction market list. Results render in the chat.

  4. The server quotes

    You pick one. The checkout posts the USD price to /api/evm-pay/prepare, which fetches the ETH rate, converts, adds a per-order offset, signs the result, and returns a QR code.

  5. You pay

    Scan with your own wallet on Robinhood Chain and send the exact amount. The app holds no key and signs nothing on your behalf.

  6. The chain confirms

    The open checkout polls /api/evm-pay/status every four seconds. When a matching deposit appears, the chat writes a receipt with the transaction hash and an explorer link.

The model never sees a private key and never produces a price. It is explicitly barred from stating an ETH amount, an exchange rate, or a wallet address — all three come from the server at checkout time, and the model is told to say only that the checkout will show them. Its replies are clamped to two short paragraphs and sixty words. Questions about the date or time skip the model entirely and are answered from the server clock, so it cannot invent a deadline.

Nothing about the flow is stored between requests. Each serverless function starts with no memory of the last one: no order table, no session, no cart. The payment intent itself carries everything needed to check it later, which is why the amount and the signature both have to travel back to the status endpoint unchanged.

The payment window

A quote is good for the payment window, fifteen minutes by default. After that the ETH price behind it is stale, the countdown stops, and the checkout offers to generate a fresh one rather than let you pay an old rate. A transfer that lands a few seconds after the deadline still counts: the status endpoint marks it late and confirms it anyway, because the money arrived and the buyer did their part.

If a poll fails, nothing is shown to you. A dropped request or a slow RPC means "ask again in four seconds", not "your payment failed". The only status the checkout surfaces from a failure is that the chain is answering slowly, and it keeps waiting underneath a running countdown.

Payments

ETH on Robinhood Chain, chain id 4663, paid from any wallet by scanning a QR.

Robinhood Chain is an EVM chain with id 4663. Its native currency is ETH with eighteen decimals, and it has its own public RPC and block explorer. The app reads the chain through an indexed provider when one is configured and falls back to the public endpoint otherwise. It only ever reads: no transaction is signed server-side, on this chain or any other.

Prices are quoted in USD and converted at the moment you ask to pay. The rate comes from the Coinbase ETH-USD spot endpoint, with CoinGecko as a fallback and a sixty-second cache in front of both. If neither source answers, the server reuses its last cached rate rather than guessing; if it has no cached rate, the checkout fails instead of quoting a wrong number. Orders are capped at $100,000.

The payment intent

/api/evm-pay/prepare answers with a small object that fully describes what you owe. These are its fields. All of them must travel back to the status endpoint byte for byte — mutate any one and the poll answers 401.

FieldTypeWhat it does
orderIdstringOrder reference. Also the seed for the dust offset below.
weistringThe exact amount owed, in wei. This is the number matched against the chain.
addressEVM addressThe checkout wallet. Identical for every order — the amount is what tells orders apart.
createdAttimestamp (ms)Floor for matching. A deposit that landed earlier is somebody else’s.
expiresAttimestamp (ms)createdAt plus the payment window: 900 seconds by default.
signatureHMAC-SHA256 hexSigns the five fields above. Sent on every status poll and verified before any chain read.

What the QR contains

The QR encodes a plain EIP-681 URI: the address, the chain id, and the value in wei. Any wallet that understands the standard fills all three in for you. The chain id in the URI is the part that matters most — it is what tells a compliant wallet to switch networks instead of sending on whatever chain it happens to be on.

ethereum:0xYourCheckoutAddress@4663?value=20722960000044318

Why the amount has a strange tail

There is no database, so there is no order table to look a deposit up in. The amount itself is the reference. The server rounds the ETH price to eight decimal places, then adds a dust offset of between 1 and 65,535 wei derived from the order id with an FNV-1a hash. Eight decimals of ETH is a step of 10,000,000,000 wei; the dust is at most five digits. The two can never overlap. The visible price sits above, the order fingerprint sits below it.

A $49.99 order at $2,412.30 per ETH rounds to 0.02072296 ETH, or 20,722,960,000,000,000 wei. With a dust offset of 44,318 the intent asks for 20,722,960,000,044,318 wei — 0.020722960000044318 ETH. A second buyer checking out at the same price in the same second gets a different tail from a different order id, so the two deposits are distinct amounts on chain. The offset is worth a small fraction of a billionth of a cent, so it costs nobody anything and never appears in the USD figure you were shown.

The mechanism is deterministic, not magic. There are 65,535 possible offsets, so two orders at an identical price collide roughly once in 65,535. Section six of the architecture notes explains where this matcher is still thin.

Tolerance and fees

A deposit counts as paid if it is at or above the asked amount minus a tolerance of 200 basis points — two percent — which absorbs wallets that round. Overpaying always counts. Underpaying by more than the tolerance does not, and the checkout keeps waiting. Gas is paid by your wallet to the network; the app adds no fee of its own on top of the quoted amount.

Architecture

A Next.js app, a handful of stateless API routes, and a payment path with no database behind it.

The site is a Next.js 13 app on the pages router. Every server function is a serverless route with no database, no session store, and no shared memory. The chat, the search panels, and the checkouts all live in the browser; the routes exist to hold secrets, call third parties, and read the chain.

The agent loop

/api/chat builds a system prompt from the brand file plus one instruction block per capability: wallet actions, Amazon search, flight search, prediction markets, and price lookups. It sends that with the five most recent messages of the conversation to Cerebras first and falls back to Groq, rotating through a pool of keys so one exhausted key does not take the chat down. The reply comes back as prose with an optional JSON action appended; the server strips the action out, normalises it, and returns both. The client keys off the action type to decide which panel to mount.

API surface

EndpointMethodWhat it does
/api/chatPOSTPrompt assembly, model call with provider fallback, action extraction.
/api/amazon/searchPOSTReal-time Amazon product data through RapidAPI, with key rotation.
/api/flights/searchPOSTAirport lookup and departures through AeroDataBox.
/api/evm-pay/preparePOSTUSD to wei, signed intent, EIP-681 URI, QR image.
/api/evm-pay/statusPOSTVerifies the intent signature, then looks for the deposit.
/api/ttsPOSTSpeech synthesis, only when voice replies are switched on.
/api/jupiter-*POSTLegacy trading endpoints. Not reachable from the interface and not part of checkout.

Server side and client side

Everything that must not be forgeable is server-side: the ETH price, the amount owed, the signing secret, the receiving address, and every third-party key. The client holds the conversation, the checkout forms, the countdown, and the four-second polling loop. Chat history never leaves the browser except as the five most recent messages sent with each new question. The two payment routes are the only code that touches the chain, and both are read-only.

Identity is deliberately a different system from checkout. Email login and the embedded wallet are handled by Privy, and that embedded wallet is an EVM wallet on Robinhood Chain — the same chain checkout uses. Send it only assets that exist on Robinhood Chain: anything transferred from a different network arrives at an address that cannot spend it, and is not recoverable. Checkout itself is always an ETH transfer on Robinhood Chain from a wallet you control, which is why it works whether or not you are logged in.

Where each capability gets its data

  • Product search is live Amazon catalogue data through RapidAPI, with key rotation so a single exhausted key never takes search down.
  • Flight search resolves airports and departures through AeroDataBox. Ticket pricing is computed by our own pricing model rather than quoted by a carrier.
  • Prediction markets are presented from a curated market list held in the client.
  • Quotes are priced per request against the live ETH rate; nothing is cached across checkouts, so an intent always reflects the rate at the moment it was issued.
  • Deposit attribution runs on an indexed RPC. Against a plain public endpoint the status route reports itself degraded rather than guessing, because a balance figure alone cannot be tied to a specific order.

Where the boundary of the system is

$WHIM owns the path from request to settled payment, and that path is complete: search, quote, signed intent, QR, on-chain confirmation, receipt. It does not extend past settlement into the merchant's own systems — placing the order with Amazon, issuing a ticket with a carrier, or opening a position at a venue are those parties' operations, performed under their terms, and this application does not perform them on your behalf.

Security

You keep your keys. The server keeps a receiving address and a signing secret, and can do nothing else.

Custody

Paying involves no wallet connection, no signature prompt, and no token allowance. The checkout shows an address and an amount; your wallet does the rest. Nothing in the app can initiate a transfer from your side, because it never holds anything that could authorise one.

On the receiving side, the server knows the checkout address and nothing more. The payment module reads that address from the environment and validates it; there is no private key in the payment path, no signer object, and no code that could move a single wei. Funds that arrive sit in that wallet until the operator sweeps them by hand, with a key that is not part of this application.

Be clear about the other half of that sentence. Non-custodial means the app never holds your keys. It does not mean your money is escrowed. An ETH transfer is final. No smart contract holds the payment, there is no dispute button, and there is no automatic refund path.

Intent signing

Every intent is signed with HMAC-SHA256 over its five fields joined into one canonical string before it leaves the server. The signature travels with the intent and comes back on every status poll, where it is checked with a constant-time compare. A bad signature returns 401 before a single chain read happens.

orderId | wei | address | createdAt | expiresAt

That is what stops a client asking "has 0.01 ETH arrived?" about an amount it never requested and claiming a stranger's deposit: it cannot produce a valid signature for an amount the server never quoted. Deposits that landed more than a minute before the intent was created are rejected as well, so an older unrelated transfer of a similar size can never mark a fresh order as paid.

If the signing secret is rotated between the deploy that issued an intent and the one answering the poll, that intent stops verifying. The checkout says so plainly and tells you not to send, because a transfer against a dead intent would go unnoticed by the matcher.

What the app can and cannot do

  • It cannot move funds from your wallet. It never holds a key and never requests a signature.
  • It cannot see a private key or seed phrase. It never asks, and there is nowhere to type one.
  • It can read public chain data: the balance of its own address and recent transfers to it.
  • It can quote a price and sign it. The amount you owe is decided server-side, not in your browser.
  • It cannot reverse, refund, or redirect a transfer once your wallet has broadcast it.

Check these five things before you send

  • Your wallet is on Robinhood Chain, chain id 4663 — not Ethereum mainnet, not a testnet.
  • The address your wallet shows matches the address in the checkout panel, character for character.
  • The amount matches exactly, tail digits included. Rounding it down can push the payment outside tolerance.
  • The countdown is still running. If it expired, generate a new payment instead of sending against the old quote.
  • If the panel says the payment can no longer be verified, send nothing at all and start again.

Privacy

There is no user database. Your history lives in your own browser, and the little that leaves it is listed here.

Nothing you type is stored on a server we run, because there is no server-side store to put it in. The API routes are stateless: they receive a request, call a provider or read the chain, answer, and forget. Everything persistent is in your browser's local storage, under three keys.

Kept in your browser

  • Conversations: every message you and the agent exchanged, a title taken from your first line, and created and updated timestamps.
  • Usage stats: how many messages you have sent, total seconds spent in the app, a consecutive-day streak, and the date you were last active.
  • A first name, only if you ever told the agent one. It is picked out of your own message by pattern matching and reused so the agent can address you.

What leaves your browser

On each chat turn the server receives your message, the five most recent messages of history, the assistant mode, your first name if it knows one, your browser's timezone string, and — only while a wallet is connected — that wallet's public address and token balances, which are injected into the system prompt so the agent can answer balance questions. All of it is forwarded to whichever model provider handles the request.

A checkout sends far less: the USD amount, the product title — which the server truncates to sixty characters — and a short memo. Shipping details are never sent to the payment endpoints, and no fulfilment system ever receives them, which is why nothing can be shipped from them automatically.

Third parties

ServiceWhen it is calledWhat it receives
Cerebras, GroqEvery chat turnYour message, recent history, and the wallet context described above.
RapidAPI (Amazon data)Product searchesThe search query and any price or rating filter.
RapidAPI (AeroDataBox)Flight searchesAn airport code and a date.
Coinbase, CoinGeckoEach new quoteNothing about you — a plain ETH/USD price request.
Alchemy or the public RPCEvery four seconds while a checkout is openThe checkout address. Never yours.
ElevenLabsOnly when voice replies are onThe reply text, stripped of links, addresses and hashes first.
PrivyLogin and embedded walletYour email. The wallet it creates for you is an EVM wallet on Robinhood Chain.

Never collected

  • Seed phrases and private keys. There is no field for them anywhere in the app.
  • Card numbers, bank details, and passwords. Login is an email link handled by Privy.
  • Analytics. The app ships no tracking, advertising, or session-recording script, and sets no tracking cookie.

On-chain data is public forever

Your payment is a public transaction. The sending address, the amount, the timestamp, and the receiving address are permanent and visible to anyone with a block explorer. That is a property of the chain, not a choice of this app, and no privacy policy can undo it. If you would rather a purchase were not linked to an address you use elsewhere, pay from one you do not.

Clearing your data

Delete a conversation from the sidebar to remove it. To remove everything — conversations, stats, and stored name — clear site data for this domain in your browser settings; that is the only copy in existence. One caveat worth knowing: deleting your last remaining conversation does not immediately rewrite the stored copy, so clear site data if you want to be certain. What cannot be cleared is the model providers' own request logs and anything already written to the chain.

Where to find the project

Every link on this site comes from one object, so there is exactly one place to check.

The navbar, the footer, the floating social bar, and the block of URLs handed to the agent all read from a single LINKS object in the brand file. Adding, moving, or retiring a channel is one edit, and every surface follows. Nothing is hardcoded into a component, which means a link you see on one page cannot quietly disagree with the same link on another.

The official channels

  • X — x.com/AppWhim, the account that speaks for the project.
  • Documentation — this site, at /docs.

That is the whole list, and it is deliberately short: a channel appears here once it exists and is ours, not before. Anything else claiming to be an official Whim channel is not one, however closely the handle resembles this one.

The agent quotes a link when you ask where to find the project, but only for entries that are absolute URLs. Anything relative is filtered out of its prompt before the model ever sees it, so it cannot advertise a channel that is not in the list above. If it declines to give you a link, that is why.