The GlueX Widget provides a comprehensive event system through the useWidgetEvents
hook that allows you to subscribe to various widget events.
These hooks helps you retrieve helpful information and to track swap progress, monitor quote execution, observe chain and token selections, track UI interactions and more
We actively work on extending the list of available widget events. If you need
support for a specific event, please contact us via our support
channels
Setup
First, import the necessary types and hooks:
import {
WidgetEvent,
useWidgetEvents,
type Route,
type RouteExecutionUpdate,
} from "@gluex/widget";
export const WidgetEvents = () => {
const events = useWidgetEvents();
useEffect(() => {
const onRouteExecutionStarted = (route: Route) => {
// Handle route start
};
const onRouteExecutionUpdated = (update: RouteExecutionUpdate) => {
// Handle route updates
};
const onRouteExecutionCompleted = (route: Route) => {
// Handle route completion
};
const onRouteExecutionFailed = (update: RouteExecutionUpdate) => {
// Handle route failure
};
events.on(WidgetEvent.RouteExecutionStarted, onRouteExecutionStarted);
events.on(WidgetEvent.RouteExecutionUpdated, onRouteExecutionUpdated);
events.on(WidgetEvent.RouteExecutionCompleted, onRouteExecutionCompleted);
events.on(WidgetEvent.RouteExecutionFailed, onRouteExecutionFailed);
// Cleanup subscriptions
return () => {
events.all.clear();
};
}, [events]);
return <></>;
};
For optimal performance and to avoid unnecessary re-renders or unexpected
behavior in your main widget component, we recommend using the
useWidgetEvents
hook outside of the component where the primary
GlueXWidget
is rendered
Event Type
The widget emits various events that you can listen to:
enum WidgetEvent {
// Route Events
RouteExecutionStarted = "routeExecutionStarted" // When a route starts executing
RouteExecutionUpdated = "routeExecutionUpdated" // Progress updates during execution
RouteExecutionCompleted = "routeExecutionCompleted" // When route completes successfully
RouteExecutionFailed = "routeExecutionFailed" // When route execution fails
RouteHighValueLoss = "routeHighValueLoss" // High value loss detection
RouteSelected = "routeSelected" // When a route is selected
// Chain and Token Events
SourceChainTokenSelected = "sourceChainTokenSelected"
DestinationChainTokenSelected = "destinationChainTokenSelected"
// Wallet Events
WalletConnected = "walletConnected"
SendToWalletToggled = "sendToWalletToggled"
// UI and Form Events
PageEntered = "pageEntered"
FormFieldChanged = "formFieldChanged"
SettingUpdated = "settingUpdated"
TokenSearch = "tokenSearch"
TransactionError = "transactionError"
}
Available Events
Route Events
RouteExecutionStarted
Fires when the user clicks the “Start swapping” or “Start bridging” button, initiating the execution of a selected route. This marks the beginning of the cross-chain transaction process.
Payload: Route
interface Route {
id: string; // Unique identifier for this route instance
fromChainId: number; // Numeric ID of source chain (e.g. 1 = Ethereum, 137 = Polygon)
fromAddress?: string; // Wallet address tokens are taken from (if pre-filled)
fromToken: TokenWithPriceAndAmount & WithAdditionalDetails; // Source token metadata + price/amount info
fromAmount: string; // Amount of source token user requested (in token units)
effectiveFromAmount?: string; // Actual amount used after fee/slippage adjustments
fromAmountUSD: string; // USD value of `fromAmount`
toChainId: number; // Numeric ID of destination chain
toAddress?: string; // Destination wallet address (if sending to different wallet)
toToken: TokenWithPriceAndAmount & WithAdditionalDetails; // Destination token metadata + price/amount info
toAmount: string; // Expected amount of destination token
toAmountReceive: string; // Amount that will actually arrive (after fees)
toAmountMin: string; // Minimum acceptable output (slippage protection floor)
toAmountUSD: string; // USD value of `toAmount`
gasCostUSD?: string; // Estimated gas cost in USD
steps: GlueXStep[]; // Ordered list of low-level execution steps (bridge, swap, etc.)
}
Handler:
const onRouteExecutionStarted = (route: Route) => {
console.log("Route execution started:", route.id);
console.log(
`Converting ${route.fromAmount} ${route.fromToken.symbol} on chain ${route.fromChainId}`
);
console.log(
`Expected to receive ${route.toAmountReceive} ${route.toToken.symbol} on chain ${route.toChainId}`
);
};
RouteExecutionUpdated
Fires during route execution to provide real-time progress updates. Contains the current process step and updated route information, allowing you to track execution progress and display status to users.
Payload: RouteExecutionUpdate
interface RouteExecutionUpdate {
route: Route; // Updated route object with current state
process: Process; // Current execution process details
}
interface Process {
id: string; // Unique process identifier
status: ProcessStatus; // Current status (pending, running, completed, failed)
type: ProcessType; // Type of process (swap, bridge, approval, etc.)
txHash?: string; // Transaction hash if available
message?: string; // Human-readable status message
error?: string; // Error message if process failed
}
Handler:
const onRouteExecutionUpdated = (update: RouteExecutionUpdate) => {
const { route, process } = update;
console.log(`Route ${route.id} update:`, process.status);
console.log(`Current step: ${process.type}`);
if (process.txHash) {
console.log(`Transaction hash: ${process.txHash}`);
}
};
RouteExecutionCompleted
Fires when a route execution completes successfully. All steps have been executed and the user has received their destination tokens.
Payload: Route
Handler:
const onRouteExecutionCompleted = (route: Route) => {
console.log("Route execution completed successfully:", route.id);
console.log(
`Successfully converted ${route.fromAmount} ${route.fromToken.symbol} to ${route.toAmountReceive} ${route.toToken.symbol}`
);
// Show success notification
showSuccessNotification(
`Swap completed! You received ${route.toAmountReceive} ${route.toToken.symbol}`
);
};
RouteExecutionFailed
Fires when route execution fails at any step. Provides details about the failure through the process object.
Payload: RouteExecutionUpdate
Handler:
const onRouteExecutionFailed = (update: RouteExecutionUpdate) => {
const { route, process } = update;
console.error("Route execution failed:", route.id);
console.error("Failure reason:", process.error);
// Show error notification to user
showErrorNotification(
`Swap failed: ${process.error || "Unknown error occurred"}`
);
};
RouteHighValueLoss
Fires when the system detects a significant value loss (high slippage, fees, or unfavorable market conditions) and displays a warning to the user.
Payload: RouteHighValueLossUpdate
interface RouteHighValueLossUpdate {
fromAmountUSD: number; // USD value of input amount
toAmountUSD: number; // USD value of expected output
gasCostUSD?: number; // Estimated gas costs in USD
feeCostUSD?: number; // Protocol/bridge fees in USD
valueLoss: number; // Total value loss as percentage (0.05 = 5%)
}
Handler:
const onRouteHighValueLoss = (valueLoss: RouteHighValueLossUpdate) => {
console.warn("High value loss detected:");
console.warn(`Input: $${valueLoss.fromAmountUSD}`);
console.warn(`Output: $${valueLoss.toAmountUSD}`);
console.warn(`Total loss: ${(valueLoss.valueLoss * 100).toFixed(2)}%`);
// Show warning modal
showHighValueLossWarning({
inputValue: valueLoss.fromAmountUSD,
outputValue: valueLoss.toAmountUSD,
lossPercentage: valueLoss.valueLoss,
gasCost: valueLoss.gasCostUSD,
fees: valueLoss.feeCostUSD,
});
};
RouteSelected
Fires when a user selects a specific route from the available options. This happens before execution begins.
Payload: RouteSelected
interface RouteSelected {
route: Route; // The selected route object
}
Handler:
const onRouteSelected = (selection: RouteSelected) => {
const { route } = selection;
console.log("Route selected:", route.id);
console.log(
`Route details: ${route.fromToken.symbol} → ${route.toToken.symbol}`
);
console.log(`Estimated output: ${route.toAmount} ${route.toToken.symbol}`);
};
Token and Chain Selection Events
SourceChainTokenSelected
Fires when the user selects or changes the source chain and token combination.
Payload: ChainTokenSelected
interface ChainTokenSelected {
chainId: Chain["id"]; // Numeric chain ID (e.g., 1 for Ethereum)
tokenAddress: string; // Token contract address (or "0x0" for native tokens)
}
Handler:
const onSourceChainTokenSelected = (selection: ChainTokenSelected) => {
console.log(
`Source selected: Token ${selection.tokenAddress} on chain ${selection.chainId}`
);
};
DestinationChainTokenSelected
Fires when the user selects or changes the destination chain and token combination.
Payload: ChainTokenSelected
Handler:
const onDestinationChainTokenSelected = (selection: ChainTokenSelected) => {
console.log(
`Destination selected: Token ${selection.tokenAddress} on chain ${selection.chainId}`
);
};
Wallet Events
WalletConnected
Fires when a user successfully connects their wallet through the widget’s internal wallet management UI.
Payload: WalletConnected
interface WalletConnected {
address?: string; // Connected wallet address
chainId?: number; // Currently connected chain ID
chainType?: ChainType; // Type of chain (EVM, Solana, etc.)
}
Handler:
const onWalletConnected = (wallet: WalletConnected) => {
console.log("Wallet connected:", wallet.address);
console.log("Connected to chain:", wallet.chainId);
};
SendToWalletToggled
Fires when the user toggles the “send to different wallet” option by clicking the wallet icon next to the action button.
Payload: boolean
(true if enabled, false if disabled)
Handler:
const onSendToWalletToggled = (isEnabled: boolean) => {
console.log("Send to wallet toggled:", isEnabled);
if (isEnabled) {
// Show destination wallet input
showDestinationWalletInput();
console.log("User can now specify a different destination wallet");
} else {
// Hide destination wallet input
hideDestinationWalletInput();
console.log("Tokens will be sent to connected wallet");
}
};
UI and Navigation Events
PageEntered
Fires when the user navigates to a different page within the widget.
Payload: NavigationRouteType
(string indicating the page/route name)
Handler:
const onPageEntered = (page: NavigationRouteType) => {
console.log("User navigated to page:", page);
};
ReviewTransactionPageEntered
Fires when the user enters the transaction review page by clicking on a specific route.
Payload: Route
(optional - the route being reviewed)
Handler:
const onReviewTransactionPageEntered = (route?: Route) => {
console.log("User entered transaction review page");
if (route) {
console.log("Reviewing route:", route.id);
console.log(
`Route summary: ${route.fromAmount} ${route.fromToken.symbol} → ${route.toAmount} ${route.toToken.symbol}`
);
// Pre-populate review page with route details
populateReviewPage(route);
}
// Track review page entry
analytics.track("review_page_entered", {
routeId: route?.id,
hasRoute: !!route,
});
// Show transaction warnings or additional info
showTransactionWarnings(route);
};
Fires whenever any form field value changes in the widget (amount input, slippage settings, etc.).
Payload: FormFieldChanged
type FormFieldChanged = {
[K in keyof DefaultValues]: {
fieldName: K; // Name of the changed field
newValue: DefaultValues[K]; // New value
oldValue: DefaultValues[K]; // Previous value
};
}[keyof DefaultValues];
Handler:
const onFormFieldChanged = (change: FormFieldChanged) => {
console.log(`Form field "${change.fieldName}" changed:`);
console.log(` Old value: ${change.oldValue}`);
console.log(` New value: ${change.newValue}`);
// Field-specific logic
switch (change.fieldName) {
case "amount":
// Recalculate routes when amount changes
if (change.newValue && parseFloat(change.newValue) > 0) {
debounceRecalculateRoutes();
}
break;
case "slippage":
// Update slippage warnings
validateSlippageSetting(change.newValue);
break;
}
};
SettingUpdated
Fires when any widget setting is updated (theme, slippage tolerance, gas price, etc.).
Payload: SettingUpdated
interface SettingUpdated<K extends keyof SettingsProps = keyof SettingsProps> {
setting: K; // Name of the updated setting
newValue: SettingsProps[K]; // New setting value
oldValue: SettingsProps[K]; // Previous setting value
newSettings: SettingsProps; // Complete updated settings object
oldSettings: SettingsProps; // Complete previous settings object
}
Handler:
const onSettingUpdated = (update: SettingUpdated) => {
console.log(`Setting "${update.setting}" updated:`);
console.log(` Old value: ${update.oldValue}`);
console.log(` New value: ${update.newValue}`);
};
TokenSearch
Fires when the user searches for tokens in the token selection interface.
Payload: TokenSearch
interface TokenSearch {
value: string; // Search query entered by user
tokens: TokenWithPriceAndAmount[]; // Array of tokens matching the search
}
Handler:
const onTokenSearch = (search: TokenSearch) => {
console.log(`User searched for: "${search.value}"`);
console.log(`Found ${search.tokens.length} matching tokens`);
// Display search results
displaySearchResults(search.tokens);
};
Error and Support Events
TransactionError
Fires when a transaction error occurs during route execution, providing detailed error information for debugging and support.
Payload: TransactionErrorEvent
interface TransactionErrorEvent {
supportId?: string; // Unique support ID for tracking
errorCode: string; // Standardized error code
errorMessage: string; // Human-readable error message
chainId?: number; // Chain where error occurred
tokenSymbol?: string; // Token involved in failed transaction
toolName?: string; // Bridge/DEX tool that failed
stepType?: string; // Type of step that failed (swap, bridge, approval)
txHash?: string; // Transaction hash if available
timestamp: string; // ISO timestamp of error
}
Handler:
const onTransactionError = (error: TransactionErrorEvent) => {
console.error("Transaction error occurred:");
console.error(` Error code: ${error.errorCode}`);
console.error(` Message: ${error.errorMessage}`);
console.error(` Support ID: ${error.supportId}`);
if (error.txHash) {
console.error(` Transaction: ${error.txHash}`);
}
// Show user-friendly error message
showErrorNotification({
title: "Transaction Failed",
message: error.errorMessage,
supportId: error.supportId,
actionButton: "Contact Support",
});
};
Fires when the user clicks the “Contact support” button, typically from the transaction details page or error states.
Payload: ContactSupport
interface ContactSupport {
supportId?: string; // Unique identifier for support context
}
Handler:
const onContactSupport = (support: ContactSupport) => {
console.log("User requesting support");
if (support.supportId) {
console.log(`Support ID: ${support.supportId}`);
}
};
LowAddressActivityConfirmed
Fires when the user confirms they want to proceed despite low activity on the destination address, typically shown as a security warning.
Payload: LowAddressActivityConfirmed
interface LowAddressActivityConfirmed {
address: string; // The address with low activity
chainId: number; // Chain ID where address has low activity
}
Handler:
const onLowAddressActivityConfirmed = (
confirmation: LowAddressActivityConfirmed
) => {
console.log("User confirmed low activity address:");
console.log(` Address: ${confirmation.address}`);
console.log(` Chain ID: ${confirmation.chainId}`);
};