DeployDeploy web demo to Vercel

Deploy the web demo to Vercel

The web app in apps/web runs the whole pipeline: Phantom signs sign_eth_transfer, then /api/finalize signs the payload, submits finalize_signature and broadcasts the EVM transaction. On a laptop the API routes read two key files from disk. On Vercel there is no disk, so both keys go in as environment variables.

⚠️

NEXT_PUBLIC_* variables are inlined into the browser bundle at build time. Changing one in the Vercel dashboard does nothing until you redeploy.

Environment variables

Set these on the Vercel project (Settings → Environment Variables). The canonical list with comments is apps/web/.env.example.

VariableBrowser or serverValue
NEXT_PUBLIC_DEMO_CHAINbrowserbase-sepolia (or sepolia)
DEMO_CHAINserversame value; may be omitted, the server then uses the public one
NEXT_PUBLIC_BASE_SEPOLIA_RPC_URLbrowseran RPC that serves Base Sepolia
BASE_SEPOLIA_RPC_URLserversame
NEXT_PUBLIC_SOLANA_RPC_URLbrowserhttps://api.devnet.solana.com
SOLANA_RPC_URLserverhttps://api.devnet.solana.com
ANCHOR_WALLET_JSONservercontents of ~/.config/solana/id.json, the 64-number array
SODA_SIGNER_KEY_HEXservercontents of keyshare.dev.json, 32-byte hex
SEPOLIA_FUNDER_KEYserversponsor key, funded on the chosen chain

For sepolia use NEXT_PUBLIC_SEPOLIA_RPC_URL and SEPOLIA_RPC_URL instead of the Base pair.

Do not set MPC_COORDINATOR_URL. The committee cannot apply the per-owner derivation tweak yet and its key is not the one on-chain, so every signature it produces is rejected. The page shows which signer the server is actually using; there is no separate display variable to keep in sync.

How a half-configured deployment fails

The page checks its configuration at load and refuses to run rather than failing two steps later with a misleading error. These are the checks and what each one means.

”Deployment misconfigured: built for X, server configured for Y”

NEXT_PUBLIC_DEMO_CHAIN and DEMO_CHAIN differ. The browser would derive an address and build a transaction for one chain while the server funds and broadcasts on another. Set both to the same value and redeploy.

”… is not enabled for this app”

An Alchemy URL whose app does not have that network switched on. Either enable the network on the app, or point the variable at a provider that serves it. The error names the chain and host it came from.

”no signer key: set SODA_SIGNER_KEY_HEX”

/api/finalize found neither the variable nor keyshare.dev.json. It will not generate a key: the committee already exists on-chain with a fixed group_pk, so a fresh key could never match it.

”server signer key does not match the on-chain committee”

SODA_SIGNER_KEY_HEX is set but is not the key that ran init_committee. Copy the laptop’s keyshare.dev.json, or run update_committee with the committee authority to rotate the on-chain key to the one the server holds.

Solana RPC and websockets

Both the browser and /api/finalize confirm transactions by signatureSubscribe over websocket. Alchemy’s Solana endpoint rejects that method, so a page pointed at it hangs on confirmation even though the transaction landed. Use the public devnet endpoint for both Solana variables, or a provider that supports subscriptions.

The two server keys are demo secrets. SODA_SIGNER_KEY_HEX controls every address the committee has ever derived, and SEPOLIA_FUNDER_KEY is a hot wallet. Keep only test funds behind them.