Complete Integration Example
This example demonstrates how to integrate SilentSwap into a React application using the SilentSwapProvider and the useSilentSwap hook.
1. Setup Provider
The first step is to wrap your application with the SilentSwapProvider. This provider manages the global state and provides the necessary context for the hooks.
// providers/provider.tsx
'use client';
import React from 'react';
import { SilentSwapProvider, useSolanaAdapter } from '@silentswap/react';
import { createSilentSwapClient, ENVIRONMENT } from '@silentswap/sdk';
import { useAccount, useWalletClient } from 'wagmi';
import { useUserAddress } from '@/hooks/useUserAddress';
// Initialize the client
const environment = ENVIRONMENT.STAGING;
const client = createSilentSwapClient({ environment });
export default function Provider({ children }: { children: React.ReactNode }) {
const { isConnected, connector } = useAccount();
const { data: walletClient } = useWalletClient();
const { evmAddress, solAddress } = useUserAddress();
// Use the built-in Solana adapter hook if you need Solana support
const { solanaConnector, solanaConnectionAdapter } = useSolanaAdapter();
return (
<SilentSwapProvider
client={client}
environment={environment}
evmAddress={evmAddress}
solAddress={solAddress}
isConnected={isConnected}
connector={connector}
walletClient={walletClient}
solanaConnector={solanaConnector}
solanaConnection={solanaConnectionAdapter}
solanaRpcUrl="https://api.mainnet-beta.solana.com" // Optional: custom RPC URL
baseUrl={undefined} // Optional: override base URL for API calls
>
{children}
</SilentSwapProvider>
);
}2. Implement Swap Form
The useSilentSwap hook provides everything you need to execute and track a swap.
// components/SwapForm.tsx
'use client';
import React from 'react';
import { useSilentSwap, useSwap, formatUsdValue } from '@silentswap/react';
import { useUserAddress } from '@/hooks/useUserAddress';
export function SwapForm() {
// 1. Get swap settings from useSwap (managed via Zustand)
const {
tokenIn,
tokenOut,
inputAmount,
setInputAmount,
destinations,
splits
} = useSwap();
// 2. Get swap logic and status from useSilentSwap
const {
executeSwap,
isSwapping,
swapLoading,
currentStep,
orderId,
orderComplete,
orderStatusTexts,
handleNewSwap,
serviceFeeUsd,
bridgeFeeIngressUsd,
bridgeFeeEgressUsd,
slippageUsd,
overheadUsd,
egressEstimatesLoading
} = useSilentSwap();
// Get user address for senderContactId
const { evmAddress, solAddress } = useUserAddress();
const handleExecute = async () => {
try {
if (!tokenIn || !inputAmount) {
alert('Please select a token and enter an amount');
return;
}
// Determine sender contact ID based on source asset chain
const isSourceSolana = tokenIn.caip19.startsWith('solana:');
const senderContactId = isSourceSolana && solAddress
? `caip10:solana:*:${solAddress}`
: evmAddress
? `caip10:eip155:1:${evmAddress}`
: '';
if (!senderContactId) {
alert('Wallet address required');
return;
}
// Execute swap with all required parameters
const result = await executeSwap({
sourceAsset: tokenIn.caip19,
sourceAmount: inputAmount,
destinations: destinations,
splits: splits,
senderContactId: senderContactId,
integratorId: process.env.NEXT_PUBLIC_INTEGRATOR_ID, // Optional: for tracking
});
if (result) {
console.log('Swap initiated:', result.orderId);
}
} catch (err) {
console.error('Swap failed:', err);
}
};
if (orderComplete && orderId) {
return (
<div className="p-6 bg-green-50 rounded-xl">
<h2 className="text-xl font-bold mb-4">Swap Complete!</h2>
<p>Order ID: {orderId}</p>
<button
onClick={handleNewSwap}
className="mt-4 px-6 py-2 bg-yellow text-black font-semibold rounded-lg"
>
New Swap
</button>
</div>
);
}
const totalFeesUsd = serviceFeeUsd + bridgeFeeIngressUsd + bridgeFeeEgressUsd;
return (
<div className="flex flex-col gap-6 p-6 max-w-md mx-auto bg-zinc-900 rounded-2xl text-white">
{/* Input Section */}
<div className="flex flex-col gap-2">
<label className="text-sm text-zinc-400">Input Amount ({tokenIn?.symbol})</label>
<input
type="text"
value={inputAmount}
onChange={(e) => setInputAmount(e.target.value)}
placeholder="0.00"
className="p-4 bg-zinc-800 border-none rounded-xl text-xl outline-none focus:ring-1 focus:ring-yellow/50"
disabled={isSwapping}
/>
</div>
{/* Fee Breakdown */}
<div className="space-y-2 p-4 bg-zinc-800/50 rounded-xl text-sm">
<div className="flex justify-between">
<span className="text-zinc-400">Total Fees:</span>
<span>${formatUsdValue(totalFeesUsd)}</span>
</div>
<div className="flex justify-between">
<span className="text-zinc-400">Price Impact:</span>
<span className="text-red-400">-${formatUsdValue(slippageUsd)}</span>
</div>
</div>
{/* Status Tracking */}
{isSwapping && (
<div className="p-4 bg-yellow/10 border border-yellow/20 rounded-xl">
<p className="font-semibold text-yellow mb-2">Status: {currentStep || 'Processing'}</p>
<div className="space-y-2">
{orderStatusTexts.map((text, i) => (
<div key={i} className="flex items-center gap-3 text-sm">
<div className="w-2 h-2 rounded-full bg-yellow animate-pulse" />
<span>{text}</span>
</div>
))}
</div>
</div>
)}
{/* Action Button */}
<button
onClick={handleExecute}
disabled={isSwapping || swapLoading || egressEstimatesLoading || !inputAmount}
className="w-full py-4 bg-yellow text-black font-bold rounded-xl disabled:opacity-20 disabled:cursor-not-allowed transition-opacity"
>
{isSwapping ? 'Executing Swap...' : 'Swap Now'}
</button>
</div>
);
}3. Using Data Hooks
SilentSwap also provides hooks for accessing shared data like balances, prices, and orders.
import { useBalancesContext, usePricesContext, useOrdersContext } from '@silentswap/react';
function UserInfo() {
const { balances, totalUsdValue } = useBalancesContext();
const { prices } = usePricesContext();
const { orders } = useOrdersContext();
return (
<div className="mt-8 space-y-4">
<h3 className="text-lg font-bold">Your Portfolio (${totalUsdValue.toFixed(2)})</h3>
<div className="grid grid-cols-2 gap-4">
{Object.values(balances).map(b => (
<div key={b.asset.caip19} className="p-3 border rounded">
{b.asset.symbol}: {b.balance.toString()} (${b.usdValue.toFixed(2)})
</div>
))}
</div>
<h3 className="text-lg font-bold mt-4">Recent Orders</h3>
<ul className="space-y-2">
{orders.map(o => (
<li key={o.orderId} className="text-sm">
{o.orderId.slice(0, 8)}... - {o.status}
</li>
))}
</ul>
</div>
);
}