Docs Navigation

Embedded Wallet

Embedded Wallet: Customization

Brand the 1Shot embedded wallet from your Host with configure — theme tokens, product copy, feature flags, and dark mode via a single partial-merge RPC.

Overview

The 1Shot Wallet Branding Layer (wallet.1shotapi.com) exposes a Host-only custom RPC — configure — for product branding without forking wallet CSS or touching the Signing Layer. Your Host calls it through proxy.rpc("configure", options) after OWSProxy.create().

Each call partially merges into the current style state, so you can set an initial theme at embed time and update colors or copy later (for example when the user toggles light/dark mode in your app). The RPC returns { ok: true, productName: string } with the resolved product name. Unknown top-level keys are rejected (Zod .strict()).

When and how to call configure

Call configure after the proxy handshake completes and before the user sees wallet UI you care about branding — typically before proxy.showWallet() on flyout hosts. Inline embeds (homepage-style previews) call configure immediately after OWSProxy.create(), as in the marketing site `EmbeddedWalletHero`.

Re-call configure whenever your Host theme changes; the playground Design mode applies changes live and re-applies the last payload when the iframe is recreated.

Minimal branding

const proxy = await OWSProxy.create(container, "https://wallet.1shotapi.com/");

await proxy.rpc("configure", {
  copy: {
    productName: "Acme Wallet",
    tagline: "Powered by 1Shot",
  },
  theme: {
    primary: "oklch(0.45 0.18 250)",
    radius: "0.625rem",
  },
});

proxy.showWallet();

Marketing site embed (homepage / wallet page)

await proxy.rpc("configure", {
  copy: {
    productName: "1Shot Wallet",
    tagline: "The ultimate embedded wallet.",
  },
  theme: {
    primary: "#239aaa",
    radius: "2rem",
  },
});
Note

Presentation (showWallet / hideWallet, inline vs flyout) is separate from branding — set shell behavior through OWSProxy.create options, not the configure RPC.

theme tokens

Map Host-provided colors and typography to Branding Layer CSS variables. Values are any valid CSS color or length string (hex, oklch, rem, etc.).

  • theme.primary--primary
  • theme.primaryForeground--primary-foreground
  • theme.background / theme.foreground → page colors
  • theme.muted / theme.mutedForeground → secondary surfaces and text
  • theme.border, theme.accent, theme.accentForeground → chrome and highlights
  • theme.radius--radius (e.g. "0.625rem", "2rem")
  • theme.fontSans--font-sans
  • dark: true → toggles html.dark on the Branding document

features flags

Optional booleans and allowlists that change wallet chrome without hiding Host-driven flows.

  • features.hideCloseBox — hide the flyout Close (×) control; default false. Use for inline hosts (browser extension side panel, fixed embeds).
  • features.disableCredentials — hide the Credentials tab; default false. Host OID4 RPC flows still work.
  • features.disableDelegations — hide the Delegations tab; default false. Host delegation flows still work.
  • features.allowedChains — hex chain id strings ("0x1", "0x2105", …) restricting the Network dropdown; omit or [] for all enabled catalog chains.

destinationUrl (status webhooks)

Optional top-level destinationUrl (HTTPS URL, ≤256 characters) is a URL to receive transaction status update webhooks from the 1Shot Relayer. When set, the Branding Layer includes it on wallet-submitted transactions so the Host backend can learn status before (or without) relying on the wallet UI.

Pass null or "" to clear a previously configured URL. Omit the field to leave the current value unchanged.

Webhook destination

await proxy.rpc("configure", {
  destinationUrl: "https://my-app.example.com/relayer-webhook",
});

copy overrides

Override user-facing strings across connect, setup, signing consent, credentials, and advanced flows. Keys are grouped by surface — you only need to set the strings your product exposes.

Some credential copy supports template placeholders substituted at runtime: {issuerName}, {issuerId}, {verifierName}, {verifierId}, {credentialType}, {credentialIssuer}, {count}.

Optional nested **copy.passkeyPrompt.*** overrides Signing Layer Confirm/Cancel copy during export/import private key ceremonies (for example copy.passkeyPrompt.exportPrivateKey.title).

For the exhaustive key list (every modal label and error string), see 1shot-wallet SKILL.md.

  • Product chromecopy.productName, copy.tagline
  • Connect & setupcopy.connect.*, copy.walletSetup.*, copy.passkeyName.*
  • Signing consentcopy.personalSign.*, copy.typedData.*
  • Credentialscopy.credentialOffer.*, copy.credentialPresentation.*, copy.credentials.* (tab, list, detail, errors)
  • Advancedcopy.exportPrivateKey.*, copy.importPrivateKey.*, copy.advancedOptions.*

Reference implementations

Marketing site`EmbeddedWalletHero` on the homepage and 1Shot Wallet solution page sets productName, tagline, theme.primary, and optional theme.radius after create.

Playground Design mode/playground exposes a live WalletConfigurator backed by styleForm.ts: tweak theme, copy, and features, then export/import JSON for your Host configure payload.

What not to do

  • Do not embed https://wallet.1shotapi.com/signer/ from the Host — always Host → Branding → Signing.
  • Do not inject CSS into the wallet iframe from the Host page — use configure tokens and copy only.
  • Do not rely on undocumented keys — they fail validation on strict configure schemas.

Test before production

Open the wallet playground, switch to Design mode, and iterate on theme and copy with live preview. Export the JSON payload and paste it into your Host integration. Pair with the 1Shot Wallet quickstart for EIP-1193 connect and send flows.