Skip to content

useSilentQuote

The useSilentQuote hook provides a high-level API for getting quotes and executing complete Silent Swap transactions. It handles the full flow from quote to execution, including authorization signing, order creation, and transaction execution.

Import

import { useSilentQuote, useSilentClient, useAuth, useWallet } from '@silentswap/react';
import { useAccount, useWalletClient } from 'wagmi';
import { DeliveryMethod, caip19FungibleEvmToken, FacilitatorKeyType, PublicKeyArgGroups } from '@silentswap/sdk';

Basic Usage

import { 
  useSilentQuote, 
  useSilentClient, 
  useAuth, 
  useWallet 
} from '@silentswap/react';
import { useAccount, useWalletClient } from 'wagmi';
import { DeliveryMethod, caip19FungibleEvmToken, FacilitatorKeyType, PublicKeyArgGroups } from '@silentswap/sdk';
 
function SwapComponent() {
  const { address, connector } = useAccount();
  const { data: walletClient } = useWalletClient();
  
  const { client } = useSilentClient({ config: { /* ... */ } });
  const { auth } = useAuth({ client, address: address!, walletClient });
  const { wallet } = useWallet({ address: address!, auth, walletClient, connector });
  
  const {
    getQuote,
    executeSwap,
    quote,
    isLoading,
    currentStep,
    error,
  } = useSilentQuote({
    client,
    address: address!,
    walletClient: walletClient as any,
    connector,
    facilitatorGroup: wallet?.accounts[0]?.group(),
    bridgeProvider: 'relay',
    onStatus: (status) => console.log('Status:', status),
  });
 
  const handleGetQuote = async () => {
    // Generate facilitator group
    const facilitatorGroup = await wallet?.accounts[0]?.group();
    const viewer = await facilitatorGroup.viewer();
    const { publicKeyBytes: viewerPk } = viewer.exportPublicKey('*', FacilitatorKeyType.SECP256K1);
    const groupPks = await facilitatorGroup.exportPublicKeys(1, PublicKeyArgGroups.GENERIC);
 
    // Get quote
    const quoteResult = await getQuote({
      signer: address!,
      viewer: viewerPk,
      outputs: [{
        method: DeliveryMethod.SNIP,
        asset: caip19FungibleEvmToken(1, '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'),
        value: '1000000',
        recipient: address!,
        facilitatorPublicKeys: groupPks[0],
      }],
    });
 
    if (quoteResult) {
      console.log('Quote ID:', quoteResult.quoteId);
    }
  };
 
  const handleExecuteSwap = async () => {
    if (!quote) return;
 
    const result = await executeSwap({
      quote,
      sourceAsset: 'eip155:43114/erc20:0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E',
      sourceAmount: '1000000',
      senderContactId: `caip10:eip155:*:${address}`,
    });
 
    if (result) {
      console.log('Swap completed:', result.orderId);
    }
  };
 
  return (
    <div>
      {isLoading && <div>{currentStep || 'Processing...'}</div>}
      {error && <div>Error: {error.message}</div>}
      <button onClick={handleGetQuote} disabled={isLoading}>
        Get Quote
      </button>
      {quote && (
        <button onClick={handleExecuteSwap} disabled={isLoading}>
          Execute Swap
        </button>
      )}
    </div>
  );
}

API Reference

Options

interface useSilentQuoteOptions {
  /** SilentSwap client instance */
  client: SilentSwapClient;
  /** User's EVM address */
  address: `0x${string}`;
  /** Wallet client for signing operations */
  walletClient?: WalletClient;
  /** Wagmi connector */
  connector?: Connector;
  /** Facilitator group for the swap */
  facilitatorGroup?: HdFacilitatorGroup;
  /** Bridge provider to use for cross-chain swaps */
  bridgeProvider?: BridgeProvider;
  /** Status update callback */
  onStatus?: (status: string) => void;
}

Return Value

interface useSilentQuoteReturn {
  // State
  isLoading: boolean;
  currentStep: string;
  quote: QuoteResponse | null;
  error: Error | null;
 
  // Methods
  getQuote: (request: QuoteRequest) => Promise<QuoteResponse | null>;
  executeSwap: (params: ExecuteSwapParams) => Promise<SwapResult | null>;
  clearQuote: () => void;
}
 
interface ExecuteSwapParams {
  /** Quote to execute */
  quote: QuoteResponse;
  /** Source asset CAIP-19 identifier */
  sourceAsset: string;
  /** Source amount */
  sourceAmount: string;
  /** Contact ID of the sender */
  senderContactId: string;
  /** Allowance target address (for ERC-20 approvals) */
  allowanceTarget?: `0x${string}`;
  /** Bridge provider override */
  bridgeProvider?: BridgeProvider;
}
 
interface SwapResult {
  orderId: string;
  viewingAuth: string;
  depositTransaction: SwapTransaction;
  bridgeTransaction?: SwapTransaction;
}

Complete Swap Flow

The executeSwap method handles the complete swap flow:

  1. Sign Authorizations - Sign all required authorization instructions
  2. Create Order - Submit order with signed quote and authorizations
  3. Execute Deposit - Send deposit transaction
  4. Bridge (if needed) - Execute bridge transaction for cross-chain swaps
  5. Return Result - Return order ID and transaction hashes

Getting a Quote

const { getQuote } = useSilentQuote({
  client,
  address: address!,
  walletClient,
  facilitatorGroup: wallet?.accounts[0]?.group(),
});
 
// Generate facilitator group and public keys
const facilitatorGroup = await wallet?.accounts[0]?.group();
const viewer = await facilitatorGroup.viewer();
const { publicKeyBytes: viewerPk } = viewer.exportPublicKey('*', FacilitatorKeyType.SECP256K1);
const groupPks = await facilitatorGroup.exportPublicKeys(
  outputs.length,
  PublicKeyArgGroups.GENERIC
);
 
// Get quote
const quote = await getQuote({
  signer: address!,
  viewer: viewerPk,
  outputs: [
    {
      method: DeliveryMethod.SNIP,
      asset: caip19FungibleEvmToken(1, '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'),
      value: '1000000',
      recipient: recipientAddress,
      facilitatorPublicKeys: groupPks[0],
    },
  ],
});

Executing a Swap

const { executeSwap, quote } = useSilentQuote({
  client,
  address: address!,
  walletClient,
  facilitatorGroup: wallet?.accounts[0]?.group(),
});
 
const handleSwap = async () => {
  if (!quote) return;
 
  const result = await executeSwap({
    quote,
    sourceAsset: 'eip155:43114/erc20:0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E',
    sourceAmount: '1000000',
    senderContactId: `caip10:eip155:*:${address}`,
    bridgeProvider: 'relay', // Optional override
  });
 
  if (result) {
    console.log('Order ID:', result.orderId);
    console.log('Deposit TX:', result.depositTransaction.hash);
    if (result.bridgeTransaction) {
      console.log('Bridge TX:', result.bridgeTransaction.hash);
    }
  }
};

Multi-Output Swaps

Support for multiple outputs (splitting one input across multiple recipients):

const quote = await getQuote({
  signer: address!,
  viewer: viewerPk,
  outputs: [
    {
      method: DeliveryMethod.SNIP,
      asset: caip19FungibleEvmToken(1, '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'),
      value: '500000', // 50% of input
      recipient: recipient1,
      facilitatorPublicKeys: groupPks[0],
    },
    {
      method: DeliveryMethod.SNIP,
      asset: caip19FungibleEvmToken(1, '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'),
      value: '500000', // 50% of input
      recipient: recipient2,
      facilitatorPublicKeys: groupPks[1],
    },
  ],
});

Status Updates

Monitor swap progress with status callbacks:

const { executeSwap, currentStep } = useSilentQuote({
  client,
  address: address!,
  walletClient,
  facilitatorGroup: wallet?.accounts[0]?.group(),
  onStatus: (status) => {
    console.log('Swap status:', status);
    // Update UI with status
  },
});
 
// currentStep will also be updated automatically
{currentStep && <div>Status: {currentStep}</div>}

Bridge Providers

Choose between bridge providers:

// Use Relay.link (default)
const { executeSwap } = useSilentQuote({
  client,
  address: address!,
  walletClient,
  facilitatorGroup: wallet?.accounts[0]?.group(),
  bridgeProvider: 'relay',
});
 
// Use deBridge
const { executeSwap } = useSilentQuote({
  client,
  address: address!,
  walletClient,
  facilitatorGroup: wallet?.accounts[0]?.group(),
  bridgeProvider: 'debridge',
});
 
// No bridge (direct deposit to Avalanche USDC)
const { executeSwap } = useSilentQuote({
  client,
  address: address!,
  walletClient,
  facilitatorGroup: wallet?.accounts[0]?.group(),
  bridgeProvider: 'none',
});
 
// Override per swap
await executeSwap({
  quote,
  sourceAsset: '...',
  sourceAmount: '...',
  senderContactId: '...',
  bridgeProvider: 'relay', // Override default
});

Error Handling

const { getQuote, executeSwap, error } = useSilentQuote({
  client,
  address: address!,
  walletClient,
  facilitatorGroup: wallet?.accounts[0]?.group(),
});
 
const handleSwap = async () => {
  try {
    const quote = await getQuote(/* ... */);
    if (!quote) {
      throw new Error('Failed to get quote');
    }
 
    const result = await executeSwap({
      quote,
      sourceAsset: '...',
      sourceAmount: '...',
      senderContactId: '...',
    });
 
    if (!result) {
      throw new Error('Swap execution failed');
    }
 
    // Success
    console.log('Swap completed:', result.orderId);
  } catch (err) {
    console.error('Swap error:', err);
    // Show error to user
  }
};
 
// Display errors
{error && (
  <div className="error">
    Swap error: {error.message}
  </div>
)}

Best Practices

  1. Check Prerequisites - Ensure auth, wallet, and facilitator group are ready
  2. Handle Loading States - Show progress using currentStep
  3. Validate Quotes - Check quote exists before executing
  4. Monitor Status - Use onStatus callback for real-time updates
  5. Error Recovery - Provide retry mechanisms for failed swaps

Next Steps