LayerHopDocsLaunch app (opens in a new tab)

Widget customization reference

Every LayerHop embed URL parameter, its range and default, the matching @layerhop/widget option, the postMessage events and the setParams contract (embed protocol 1.1).

The LayerHop widget is the swap card served at https://layerhop.com/embed, configured entirely through URL parameters and reporting back to your page with postMessage events. This page lists every parameter, option and event of embed protocol 1.1 (ready.version is 1.1.0); for a step-by-step setup see Embed the widget, or design it visually in the widget builder.

How are parameters validated?#

Each parameter is checked on its own. The embed ignores an invalid value and uses that parameter's default, so a typo never breaks the card. The contract is additive: parameters and events are only ever added, never renamed or removed.

The @layerhop/widget package is stricter: buildEmbedUrl(), mount() and <LayerHopWidget /> throw a LayerHopWidgetError on an invalid option, so integration mistakes show up during development.

Value type Format
Color Hex without #, 3 or 6 digits (0af, 22d3ee). The package also accepts a leading # and strips it.
Flag 1 turns it on. Omit the parameter to leave it off (showUsd=0 is the one flag that turns something off).
Chain A chain slug (base) or numeric id (8453). Solana's id is 7565164. See Supported chains.
Token A symbol from the token list (USDC), or a contract address / Solana mint.
List Comma-separated values, no spaces needed (base,arbitrum).

Swap parameters#

These are the same parameters as a swap deep link.

Param Example Meaning
srcChain base Chain the user pays from.
srcToken USDC Token the user pays with.
dstChain solana Chain the user receives on.
dstToken SOL Token the user receives.
amount 100 Amount in human units (decimal string, . separator), not base units.
recipient 9WzD… Prefilled destination address. Editable, with a warning when it is not the connected wallet, unless lockRecipient=1.
slippageBps 50 Slippage tolerance in basis points (integer, 0–10000).
defaultSlippage 50 Alias of slippageBps; slippageBps wins when both are set.
integrator myapp Your partner id, [a-z0-9-]{1,32}. Attribution, plus your partner fee when the id is a registered partner. Unknown ids are ignored.

The embed always quotes on the widget fee channel (0.30% LayerHop fee). A registered partner's fee is added on top and shown as its own line.

Theme parameters#

Param Values Default Meaning
theme dark, light, auto dark, or the preset's default auto follows the visitor's prefers-color-scheme.
preset midnight, paper, lime, ocean, mono none A full palette for dark and light mode. paper defaults to light, the others to dark. Explicit colors override it.
accent color theme Buttons and highlights.
accentText color automatic Text on the accent. If it would read below 4.5:1 against the accent, the embed uses dark ink or white instead.
bg color transparent Page background behind the card. Presets never set it.
surface color theme Card background.
surfaceAlt color theme Fields and nested panels.
text color theme Main text.
textMuted color theme Secondary text.
border color, 0 or 1 theme A hex value sets the border color. 0 removes the card outline, 1 makes it stronger.
success color theme Links, success states and the secondary accent.
warning color theme Warnings.
danger color theme Errors.
radius 0–40 (px) theme Card corner radius.
radiusInner 0–32 (px) theme Field and button corner radius.
font inter, system, space-grotesk, ibm-plex-sans, dm-sans, manrope theme ibm-plex-sans, dm-sans and manrope load from Google Fonts only when chosen.
fontScale 0.875–1.125 1 Scales the whole card.
density compact, comfortable comfortable compact tightens fields and the main button.
width 320–720 (px) 480 Maximum card width.
shadow none, soft, strong theme Card shadow.

Focus rings always use a color with at least 3:1 contrast on the card: the accent, then success, then text.

Content and behaviour parameters#

Param Example Meaning
title Deposit to Acme Header text, plain text up to 32 characters. Longer values are ignored.
logo https://acme.xyz/logo.svg Header image, shown at 24 × 24 px. Absolute https URL without credentials; loaded with referrerpolicy=no-referrer and hidden if it fails.
hideHeader 1 Hides the header (title, wallet button, history, settings). Wallets connect from the main button.
buttonLabel Deposit Main button label once the swap is ready to review, up to 24 characters.
showUsd 0 Hides USD values (default 1).
fromChains base,arbitrum Only these chains on the pay side.
toChains solana Only these chains on the receive side.
excludeChains bsc Never offer these chains, on either side.
fromTokens base:USDC,USDT Only these tokens on the pay side: chain:addressOrSymbol entries, or a bare symbol for any allowed chain. With only chain:-qualified entries, the side's chains are limited to the ones named.
toTokens base:USDC Same, for the receive side.
lockSrc 1 The pay chain and token can't be changed.
lockDst 1 The receive chain and token can't be changed.
lockAmount 1 The amount can't be edited.
lockRecipient 1 With a valid recipient, the recipient is fixed and the receive side stays on that address's VM (EVM or Solana). Ignored without a valid recipient.
hideRoutes 1 Shows only the selected route's summary, not the alternatives.
hideSettings 1 Hides the slippage settings.
hideHistory 1 Hides the history panel.
hidePoweredBy 1 Hides "Routed by LayerHop". Needs integrator, and applies once a quote confirms it is a registered partner.
locale en Interface language. Only en today; anything else falls back to en.
allowParentOrigin https://acme.xyz The one origin allowed to send setParams messages. https only (http for localhost), no path.

When an allow-list or a locked recipient rules out the linked or default tokens, the card starts on the first allowed asset. Allow-lists also apply to wallet-based defaults, the flip button and setParams.

How do package options map to URL parameters?#

@layerhop/widget options use the URL parameter names, with these exceptions:

Package option URL parameter Why
headerTitle title title is the iframe's title attribute in mount().
borderColor border (hex) border is the outline flag (true → 1, false → 0).
Booleans (lockDst: true) lockDst=1 showUsd: false becomes showUsd=0.
Arrays (fromChains: ["base", 42161]) fromChains=base,42161
liveUpdates: true allowParentOrigin=<your origin> Set for you from location.origin.

Options that only exist in the package (they never reach the URL):

Option Default Meaning
baseUrl https://layerhop.com Origin (optionally with a path prefix) serving /embed.
autoResize true Resize the iframe height on resize events.
height 640 Initial iframe height in px, before the first resize event.
maxWidth 480 px (or width + 16) CSS max-width of the iframe.
title LayerHop swap The iframe's accessible title.
liveUpdates false Let update() apply amount, token, theme and color changes in place through setParams, without reloading.
onReady, onQuote, onSubmitted, onStatus, onError, onResize, onRoutes, onWalletConnected, onWalletDisconnected, onAmountChanged none One callback per event.
onEvent none Called for every valid event, after the typed callback.

For the <script> tag, every option is a kebab-case data- attribute on an element marked data-layerhop-widget: srcChain → data-src-chain, borderColor → data-border-color. Lists are comma-separated. A flag is on when the attribute is empty, 1, true or yes, and off with 0.

Which events does the widget send?#

The embed posts { source: "layerhop", type, payload } to window.parent with target origin "*". Payloads never contain secrets.

type Payload When
ready { version } The card has loaded. version is the protocol version, 1.1.0 today.
quote { provider, srcChain, dstChain, amount, dstAmount } A new best quote is shown.
routes { count, provider } Routes answered: how many, and the best route's provider.
submitted { provider, srcChainId, srcTxHash } The user's wallet broadcast the source transaction.
status { provider, srcTxHash, state } Order state changed: pending, filled, refunded or failed.
error { code, message } Something failed. code is a stable error code.
resize { height } Content height in px changed.
walletConnected { vm, address } A wallet connected. vm is evm or svm.
walletDisconnected { vm, address } A wallet disconnected.
amountChanged { amount, srcChain, srcToken } The user edited the amount (human units, "" when cleared; chain slug; token address). Debounced, about 400 ms.

routes, walletConnected, walletDisconnected and amountChanged were added in protocol 1.1. With the script tag, each event is also dispatched on the host element as a bubbling DOM CustomEvent named layerhop:<type>, with the payload in event.detail.

Always check event.data.source === "layerhop" and, in production, event.origin === "https://layerhop.com". A connected wallet address is public data, but walletConnected does tell your page which address connected.

How does the host page control the widget?#

Parent → embed messages are opt-in. The embed only listens when its URL has allowParentOrigin, and only accepts a message when event.origin equals that origin exactly and event.source is its parent window.

JavaScript
iframe.contentWindow.postMessage(
  { source: "layerhop-host", type: "setParams", payload: { amount: "250", dstToken: "USDT", accent: "38bdf8" } },
  "https://layerhop.com",
);
type Payload keys (all optional)
setParams amount (human units, "" clears it), srcChain, srcToken, dstChain, dstToken, theme, accent, accentText, bg, surface, surfaceAlt, text, textMuted, border, success, warning, danger

Other keys and invalid values are ignored. Locks and allow-lists still apply: a locked side or a locked amount ignores changes. The integrator, recipient, locks and fees can never be changed this way.

With the package, mount(el, { liveUpdates: true }) sets allowParentOrigin for you, and widget.update() sends setParams for the live keys above and reloads the iframe only when another option changed.

What iframe settings does the widget need?#

Setting Value Why
color-scheme (CSS) normal The embed page is transparent with a normal root color scheme. A different scheme on the iframe makes browsers paint an opaque white or black box behind the card. The package sets it.
allow clipboard-write Lets the user copy addresses and transaction hashes.
Height 640 px to start, then follow resize events The card grows when panels open.
title Any descriptive text Accessible name for screen readers.

Last updated