Widget Embed Guide
How to easily add staking and DeFi to your application
Overview
The Blockdaemon Earn Widget lets you offer staking and DeFi lending in your application via a hosted widget, without building protocol integrations or on-chain logic in-house. Blockdaemon deploys the widget on a per-client basis and connects directly to the Blockdaemon Earn Stack.
The purpose of this guide is to support the evaluation and integration of the widget into your staging or production environments.
Supported Features
The Blockdaemon Earn Widget currently supports the following functionality:
- Staking: Ethereum (via Stakewise vaults); Solana support is planned.
- DeFi lending: Aave on Ethereum, Base, Arbitrum, Optimism; Morpho and additional chains (Solana, Polygon) are planned.
- Swaps: Ethereum, Base, Arbitrum, Optimism, Kaia.
Implementation Checklist
When preparing to go live, typical steps include:
- Widget Deployment: Confirm your
https://<client-slug>.widget.blockdaemon.comdeployment and target environment (staging vs production). - Embedding the Widget: Embed and size the iframe appropriately within your UI.
- Configuration Model: Align features configuration with your product scope (staking, DeFi, swaps) and regulatory requirements.
- Appearance & Branding: Configure appearance to meet brand, theme, locale, and currency guidelines.
- Wallet Integration Modes: Select wallet mode (internal vs external) and, for external mode, implement the
postMessageintegration contract. - Validate transaction flows, balances, and lifecycle (connect / transact / disconnect) in your staging environment.
Widget Deployment
Each customer receives a dedicated widget instance hosted at:
https://<client-slug>.widget.blockdaemon.com
Blockdaemon manages the deployment lifecycle, upgrades, and configuration of the widget instance. A client-specific slug will be provided as part of your implementation onboarding.
Embedding the Widget
To embed the widget, add the iframe to the relevant view or component in your application:
<iframe
src="https://<client-slug>.widget.blockdaemon.com" // Your Widget Instance URL
id="blockdaemon-widget"
title="Blockdaemon Earn Widget"
allow="clipboard-write"
style="width: 100%; height: 100%;">
</iframe>Consider the following when embedding:
- Sizing: The widget supports two sizing modes via
appearance.sizingMode.- Fixed mode: Use fixed mode when you want a predictable, static widget footprint. The numeric sizing limits require a width between 375 and 1000 and a height between 480 and 1200.
- Responsive mode: Use the responsive mode when the widget should adapt to the host layout. In this mode, the widget requires a minimum width of 375px and a minimum height of 480px.
Recommended Usage- Use responsive mode + host CSS for adaptive embeds.
- Use fixed mode for stable, known-size placements.
- Use URL overrides for per-placement tuning or testing.
- Scroll behavior: The widget's internal scroll area depends on host container sizing. Constrained iframe heights trigger internal scrolling, while unconstrained heights shift it to the outer page.
- Security & Content Security Policy (CSP): Ensure you allow the widget origin in frame-src, e.g.
https://<client-slug>.widget.blockdaemon.com.
Configuration Model
Blockdaemon currently manages widget configuration on your behalf; self-serve configuration will be provided via the Blockdaemon Partner Portal in a future release. Configuration can be applied per widget instance, with these specific parameters also available via URL query parameters:
colorScheme: Overrides theme (light or dark).width: Overrides widget width (mobile, tablet, or numeric 375-1000)height: Overrides widget height (mobile, tablet, or numeric 480-1200)currency: Overrides currency (USD, KRW, JPY)locale: Overrides locale (en-US, ko-KR, ja-JP)
Features Configuration
The widget’s functionality is controlled through a features configuration object:
"features": {
"portfolio": { "enabled": false },
"staking": { "enabled": true },
"swap": {
"enabled": false,
"chains": { "allowList": [], "blockList": [] },
"assets": { "allowList": [], "blockList": [] },
"dexes": { "allowList": [], "blockList": [ ] },
"bridges": { "allowList": [], "blockList": [] },
"fees": { "enabled": false }
},
"defi": {
"enabled": true,
"markets": [],
"chains": { "allowList": [], "blockList": [] },
"assets": { "allowList": [], "blockList": [] },
"customVaults": false
},
"walletInfo": false,
"walletMode": "internal/external"
}| Field | Description |
|---|---|
portfolio | Enables a unified view to track and manage user balances. |
staking | Provides the interface for depositing assets to earn protocol rewards. |
swap | Enables token exchanges within a single chain or across chains. |
defi | Connects users to liquidity markets for lending and borrowing assets. |
walletInfo | Controls the visibility of connected wallet addresses and balance data. |
walletMode | Determines whether the widget or host application manages wallet connectivity. |
Typical configuration patterns include:
- Enabling only staking for a particular chain or product line.
- Restricting swap or DeFi to a curated allow-list of assets, chains, or markets.
- Selecting wallet mode (internal vs external) to match your custody or wallet strategy.
Configuration changes are coordinated with your Blockdaemon contact and applied to your dedicated widget deployment.
Appearance & Branding
The widget supports appearance configuration to align with your brand and layout:
"appearance": {
"width": "375px"
"height": "667px",
"theme": "light",
"builtByBlockdaemon": true,
"logoUrl": "",
"locale": "en-US",
"currency": "USD"
}Field | Description |
|---|---|
| Sets the horizontal size of the widget using presets or custom pixel values to fit your application's layout. Once configured, the iframe container should be adjusted to match the widget’s configured size to ensure a proper visual fit. |
`height | Sets the vertical size of the widget using presets or custom pixel values to fit your application's layout. Once configured, the iframe container should be adjusted to match the widget’s configured size to ensure a proper visual fit. |
| Configuration supports light or dark modes with a default option available. Apps with a light / dark toggle should update this parameter to reflect the active selection. |
| The widget supports a single logo or individual logos tailored for light and dark color schemes. |
| The flag determines whether the "Built by Blockdaemon" logo appears at the bottom of the widget UI. |
| Determines language for balances and yields. |
| Determines displayed currency for balances and yields. |
Wallet Integration Modes
The widget supports two wallet integration modes:
- Internal mode The widget manages wallet connection and network switching within the iframe. Users connect and approve transactions directly in the widget UI.
- External mode
The host application owns wallet state, connection flow, and transaction execution. The widget requests wallet actions via
postMessage, and the host responds with wallet state and transaction results.
In both modes, wallet connectivity is non-custodial and your application remains in control of user session and authentication outside the widget.
Before a wallet is connected, the widget displays a default, disconnected state; once a wallet is connected, the widget updates to a fully interactive state.
External Wallet Mode: Messaging Contract
When using external wallet mode, the host application and the widget communicate via the standard window.postMessage API. All postMessage events must be filtered by origin, and only the widget origin (https://<client-slug>.widget.blockdaemon.com) should be trusted.
Message Types
The widget may send the following message types to your application:
getWalletState: Widget requests the latest host wallet state.sendTransaction: Widget requests host submission of a transaction payload.switchNetwork: Widget requests that the host switch to a target network.
Your application is expected to respond with:
walletState: Host sends current wallet connection/network state.sendTransactionResponse: Host returns transaction success/failure and result details.
Example: App ↔ Widget Integration
Below is a reference implementation illustrating event handling and wallet state propagation:
<script>
const WIDGET_ORIGIN = "https://<client-slug>.widget.blockdaemon.com";
const iframe = document.getElementById("blockdaemon-widget");
// Host-owned wallet state (external mode)
let walletState = {
isConnected: false,
address: null,
chainId: null, // CAIP-2, e.g. "eip155:1"
walletInfo: "Client Wallet",
namespace: "eip155",
};
function postToWidget(message) {
if (!iframe?.contentWindow) return;
iframe.contentWindow.postMessage(message, WIDGET_ORIGIN);
}
function sendWalletState() {
postToWidget({
type: "walletState",
data: walletState,
});
}
async function handleSendTransaction(transactionData) {
try {
// TODO: execute host wallet transaction
const txHash = "0xtxhash...";
postToWidget({
type: "sendTransactionResponse",
success: true,
data: {
hash: txHash,
chainId: walletState.chainId, // required
},
});
} catch (error) {
postToWidget({
type: "sendTransactionResponse",
success: false,
error: error instanceof Error ? error.message : "Transaction failed",
});
}
}
async function handleSwitchNetwork(request) {
// request: { chainId: "eip155:137" } (CAIP-2)
// TODO: trigger host wallet network switch flow
// After switch completes, update walletState and notify widget:
walletState = { ...walletState, chainId: request?.chainId ?? walletState.chainId };
sendWalletState();
}
window.addEventListener("message", (event) => {
// Validate origin + source
if (event.origin !== WIDGET_ORIGIN) return;
if (event.source !== iframe?.contentWindow) return;
const { type, data } = event.data || {};
switch (type) {
case "getWalletState":
sendWalletState();
break;
case "sendTransaction":
handleSendTransaction(data);
break;
case "switchNetwork":
handleSwitchNetwork(data);
break;
default:
// ignore unknown message types
}
});
// Initial sync
iframe?.addEventListener("load", () => {
setTimeout(sendWalletState, 0);
});
</script>
The following table serves as the formal communication contract between the Widget and the Host:
Direction | Type | Payload | Purpose | Required Host Behavior |
|---|---|---|---|---|
Widget |
| none | Request current wallet status | Respond with |
Widget
-> |
| transaction request object ( | Ask host to submit a transaction | Execute with host wallet, then respond with |
Widget |
|
| Ask host to switch wallet network | Trigger network switch flow, then publish updated |
Host |
|
| Provide latest host wallet state | Send on |
Host |
|
| Return tx result to widget | Include |
Next Steps and Support
For configuration changes, production cutover, or to discuss additional feature flags and chains, please contact your Blockdaemon representative or support channel. Blockdaemon can work with you to align widget behavior, branding, and wallet flows with your institutional requirements.
👋 Need Help?
Contact us through email or our support page for any issues, bugs, or assistance you may need.
Updated 5 days ago
