Website Swap Widget Development
Embed swap—not just "add a swap button to the site". It's a full token exchange interface that must run in someone else's DOM, manage wallet state, handle transactions—while staying isolated from the host page. 1inch, Uniswap, Paraswap offer their embed widgets, but custom development is needed for branded UI, protocol-specific tokens, host commission, or custom aggregation routing.
Widget Architecture
iframe vs. Web Component vs. npm Package
iframe—most isolated option. Widget is a separate page embedded via <iframe src="https://swap.yourprotocol.com">. Host page has no access to widget DOM; XSS on host can't reach the widget. Downside: communication only via postMessage, style customization limited to CSS variables via URL params.
Web Component—best balance of isolation and integration. Shadow DOM isolates styles, but the component lives in the same JavaScript context. Allows the host page to pass config via attributes and react to events:
<swap-widget
tokens="ETH,USDC,USDT"
default-input="ETH"
default-output="USDC"
fee-bps="30"
theme="dark"
></swap-widget>
npm package—maximum flexibility for integrator developers. Exports React component (or headless logic) for embedding in existing React project.
Recommended: Web Component as primary embed form + npm package for React projects. iframe only if security requirements demand full isolation.
Routing and Aggregation
Own DEX vs. Aggregator
Widget for single protocol (e.g., Uniswap v3 only)—simpler: direct contract calls, familiar routing. But user sees only one AMM's prices.
Aggregation via 1inch API, Paraswap API or 0x API gets better prices. API request returns optimal route + calldata for transaction:
const quote = await fetch(
`https://api.1inch.dev/swap/v6.0/1/swap?` +
`src=${inputToken}&dst=${outputToken}&amount=${amount}&from=${userAddress}&slippage=1`
).then(r => r.json());
// quote.tx contains ready transaction to send
await writeContractAsync({
to: quote.tx.to,
data: quote.tx.data,
value: BigInt(quote.tx.value),
});
Referral Fees
Most aggregator APIs support referral fees: you specify your address and bps, each swap routes a fee portion to you. 1inch: fee parameter in API. 0x: affiliateAddress + buyTokenPercentageFee. Doesn't affect widget smart contract—only routing calldata.
Key UX Components
Token Selector
Token list with search by name/symbol/address. Token lists: Uniswap default tokenlist, 1inch tokenlist, or custom. Load balances via Multicall3—one request instead of N.
Token verification (verified/unverified)—protects against scam tokens. Warn for tokens outside trusted list.
Price Display and Slippage
Exchange price, price impact (critical for large amounts), slippage tolerance (usually 0.1-1%, higher for volatile pairs). Show minimum received after slippage—what the contract guarantees.
Auto-update quote every 15-30 seconds. Indicator "price updated" when change > X%.
Approve Flow
Before first ERC-20 swap, need approve. Permit (EIP-2612) combines approve + swap in one transaction (via off-chain signature). Check if token supports Permit via DOMAIN_SEPARATOR() or ERC-165.
Embedding and Configuration
// Initialize via script tag
<script src="https://cdn.yourprotocol.com/swap-widget.js"></script>
<swap-widget
rpc-url="https://mainnet.infura.io/v3/KEY"
chain-id="1"
tokens="0x...,0x..."
theme='{"primaryColor":"#6366f1","borderRadius":"12px"}'
></swap-widget>
// Or via npm
import { SwapWidget } from '@yourprotocol/swap-widget';
<SwapWidget onSwapSuccess={(tx) => analytics.track('swap', tx)} />
Config parameters: token list, default input/output, theme (light/dark + CSS variables), referral address + fee bps, slippage defaults, feature toggles.
Isolation and Security
Host page's Content Security Policy may block widget's inline scripts. Document required CSP directives (connect-src, script-src) for integrators.
Wallet connection in widget: if host page already connected wallet, widget should reuse connection. For Web Component: shared window.ethereum provider or custom event bus.
No private key storage, no access to host page's localStorage (Shadow DOM isolates this automatically).
Development Timeline
Widget with fixed aggregator API (1inch/0x), Web Component packaging, basic customization: 3 days. Custom routing, permit support, iframe + npm variants, full integrator documentation: 5 days.







