Skip to content

Wallet iframe

Keep credential prompts, workers, signing state, and key export inside an isolated wallet-origin iframe.

Wallet iframe

The wallet iframe is the browser isolation boundary. It runs at a wallet origin separate from the app origin and owns wallet UI, encrypted local records, worker lifecycles, and wallet-origin session state.

Boundary

BoundaryResponsibility
App originCalls the SDK, renders app UI, and passes public operation inputs.
Wallet iframe originOwns wallet UI, wallet IndexedDB, auth-method flows, and workers.
Browser workersOwn hot holder material and operation-local secret state.

App-origin JavaScript receives public results and non-secret flow state. Holder shares, PRF output, Email OTP secret material, VoiceID templates, and server shares stay outside the app origin. Exported key material reaches the app origin only through a dedicated export flow.

Why it matters

The iframe keeps wallet authority independent from the app page. A compromised app page still has to pass wallet-origin checks, policy, auth-method requirements, Wallet Session admission, replay checks, and signing budget admission before a signing lane can participate.

Configure the boundary

Set the wallet origin explicitly when mounting the React provider. The wallet service and SDK paths resolve against that dedicated origin.

Runnable React example
tsx
import { SeamsWebProvider, seamsTestnetConfig, useSeams } from '@seams/wallet/react';

// Everything else — wallet service path, SDK base path, relayer account, chain
// RPC and explorer URLs — comes from the SDK defaults.
const seamsConfig = seamsTestnetConfig({
  walletOrigin: import.meta.env.VITE_WALLET_ORIGIN,
  relayerUrl: import.meta.env.VITE_RELAYER_URL,
  publishableKey: import.meta.env.VITE_SEAMS_PUBLISHABLE_KEY,
});

function WalletApp() {
  const { loginState } = useSeams();
  return <p>{loginState.isLoggedIn ? 'Wallet unlocked' : 'Wallet locked'}</p>;
}

export function App() {
  return (
    <SeamsWebProvider config={seamsConfig}>
      <WalletApp />
    </SeamsWebProvider>
  );
}