One iframe each: a stock's buy / sell panel, or its live price and chart. Visitors sign in their own wallet and the trade goes straight to the route the quote names; your site never holds funds, keys or approvals.
Buy and sell one stock with the live quote, route, slippage and review step the stock page has. Visitors trade from their own wallet.
Only visitors whose connection comes from a restricted country (the United States) are asked, where the trade button is; BStocks refuses their orders until they confirm.
Buttons, links, the selected tab, the focus ring and the chart line take this colour in light and dark; the shades are derived from it.
A hidden option keeps its plain default: pay with USDC, the automatic route, no gift, no limit orders. The price, the quote, the fees, the review step and the eligibility question always stay.
<iframe
src="https://basestocks.finance/embed/trade/0xb20000000000000000000078ee7ce2fe4908108c"
title="Trade on BStocks"
width="100%" height="900"
style="border:0;max-width:480px;border-radius:8px"
allow="clipboard-write"
loading="lazy"
></iframe><script>
window.addEventListener('message', function (e) {
if (e.origin !== 'https://basestocks.finance' || !e.data || e.data.source !== 'bstocks' || e.data.type !== 'resize') return;
document.querySelectorAll('iframe').forEach(function (f) {
if (f.contentWindow === e.source) f.style.height = e.data.height + 'px';
});
});
</script>Without the script the frame keeps the height in the code (900px) and scrolls inside when the widget grows. Leave the iframe unsandboxed: wallets open popups and browser wallets inject into the frame.
The widget posts messages to your page with source: 'bstocks'. Check event.origin is https://basestocks.finance.
A limit order or a CoW order settles later, so its txHash is null. Any page can post a message that looks like these: treat a trade as a hint to refresh your UI, and look the transaction up on Base before you reward anyone for it. No address, balance or signature leaves the widget.