Dynamic.xyz Integration
Complete integration with Dynamic.xyz for multi-chain wallet support.Copy
Ask AI
import { EthereumWalletConnectors } from '@dynamic-labs/ethereum';
import { DynamicContextProvider, mergeNetworks } from '@dynamic-labs/sdk-react-core';
import { SolanaWalletConnectors, isSolanaWallet } from '@dynamic-labs/solana';
import { DynamicWagmiConnector } from '@dynamic-labs/wagmi-connector';
import { chainToViemChain, ChainArchitecture } from '@metalayer/sdk';
import { WidgetProvider, Widget } from '@metalayer/widget';
import { useState, useMemo } from 'react';
function App() {
const [evmNetworks, setEvmNetworks] = useState([]);
return (
<DynamicContextProvider
settings={{
environmentId: 'your-dynamic-environment-id',
walletConnectors: [EthereumWalletConnectors, SolanaWalletConnectors],
overrides: {
evmNetworks: (networks) => mergeNetworks(evmNetworks, networks),
},
}}
>
<WidgetProvider
sdkConfig={{
apiKey: 'your-api-key',
environment: 'production',
}}
defaultSource={{
chainId: 1,
tokenAddress: '0xa0b86a33e6441e073b793e4e36b4de0d82cd5e22', // USDC - see Default Source/Destination section
}}
onSupportedChainsLoad={(chains) => {
// See Chain Loading Callback section for details
const evmNetworks = chains
.filter(chain => chain.identifier?.architecture === ChainArchitecture.ETHEREUM)
.map(chain => {
const viemChain = chainToViemChain(chain);
return viemChainToEvmNetwork(viemChain, chain.imageUrl);
});
setEvmNetworks(evmNetworks);
}}
onError={(error) => console.error('Widget error:', error)}
>
<DynamicWagmiConnector>
<WidgetWrapper />
</DynamicWagmiConnector>
</WidgetProvider>
</DynamicContextProvider>
);
}
function WidgetWrapper() {
const { setShowAuthFlow, primaryWallet } = useDynamicContext();
const solanaSigner = useMemo(() => {
if (!primaryWallet || !isSolanaWallet(primaryWallet)) return undefined;
return {
address: primaryWallet.address,
isConnected: () => !!primaryWallet.address,
signTransaction: async (transaction) => {
const signer = await primaryWallet.getSigner();
return await signer.signTransaction(transaction);
},
};
}, [primaryWallet]);
return (
<Widget
config={{
solanaSigner,
onOpenConnectModal: () => setShowAuthFlow(true),
}}
/>
);
}
// Helper function to convert Viem chain to EVM network
function viemChainToEvmNetwork(viemChain, iconUrl) {
return {
chainId: viemChain.id,
name: viemChain.name,
networkId: viemChain.id,
nativeCurrency: viemChain.nativeCurrency,
rpcUrls: Object.values(chain.rpcUrls.default).flat(),
blockExplorerUrls: viemChain.blockExplorers?.default?.url ? [viemChain.blockExplorers.default.url] : [],
isTestnet: chain.testnet,
iconUrls: iconUrl ? [iconUrl] : [],
};
}
RainbowKit Integration
Copy
Ask AI
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { RainbowKitProvider, useConnectModal } from '@rainbow-me/rainbowkit';
import { WidgetProvider, Widget } from '@metalayer/widget';
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
<WidgetProvider
sdkConfig={{
apiKey: 'your-api-key',
environment: 'production',
}}
>
<RainbowKitProvider>
<BridgePage />
</RainbowKitProvider>
</WidgetProvider>
</QueryClientProvider>
);
}
function BridgePage() {
const { openConnectModal } = useConnectModal();
return (
<Widget config={{ onOpenConnectModal: openConnectModal }} />
);
}
Next.js Setup
App Router
In yourlayout.tsx
:
Copy
Ask AI
import '@metalayer/widget/styles.css';
import 'material-symbols/rounded.css';
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
<Providers>{children}</Providers>
</body>
</html>
);
}
Pages Router
In your_app.tsx
:
Copy
Ask AI
import '@metalayer/widget/styles.css';
import 'material-symbols/rounded.css';
export default function App({ Component, pageProps }) {
return (
<Providers>
<Component {...pageProps} />
</Providers>
);
}
Advanced Configuration
Configure the widget with advanced options for production use.Copy
Ask AI
import { WidgetProvider, Widget } from '@metalayer/widget';
function AdvancedBridgeApp() {
return (
<WidgetProvider
sdkConfig={{
apiKey: process.env.NEXT_PUBLIC_METALAYER_API_KEY,
environment: process.env.NODE_ENV === 'production'
? 'production'
: 'staging',
}}
defaultSource={{
chainId: 1, // Ethereum Mainnet
tokenAddress: '0x0000000000000000000000000000000000000000', // ETH
}}
defaultDestination={{
chainId: 42161, // Arbitrum One
tokenAddress: '0x0000000000000000000000000000000000000000', // ETH
}}
onSupportedChainsLoad={(chains) => {
// Update your application's chain configuration
console.log('Supported chains loaded:', chains.length);
}}
onError={(error) => {
// Send to error tracking service
console.error('Widget error:', error);
// trackError(error);
}}
debugEnabled={process.env.NODE_ENV === 'development'}
>
<Widget
config={{
onOpenConnectModal: () => {
// Your wallet connection logic
openWalletModal();
},
solanaSigner: getSolanaSigner(), // If supporting Solana
}}
/>
</WidgetProvider>
);
}
Analytics Integration
Track widget usage and user interactions:Copy
Ask AI
import { WidgetProvider, Widget } from '@metalayer/widget';
function AnalyticsEnabledWidget() {
const trackEvent = (eventName, properties) => {
// Your analytics implementation
analytics.track(eventName, properties);
};
return (
<WidgetProvider
sdkConfig={{
apiKey: 'your-api-key',
environment: 'production',
}}
onSupportedChainsLoad={(chains) => {
trackEvent('widget_chains_loaded', {
chainCount: chains.length
});
}}
>
<Widget
config={{
onOpenConnectModal: () => {
trackEvent('wallet_connect_initiated');
openWalletModal();
},
onSubmitTransaction: (
sourceChainId?: number,
destChainId?: number,
amount?: string
) => {
trackEvent('bridge_transaction_submitted', {
sourceChainId,
destChainId,
amount
});
},
}}
/>
</WidgetProvider>
);
}