Comprehensive guide to using React hooks from the Abstraxn Wallet SDK
This document provides comprehensive usage examples for all hooks available in the Abstraxn Wallet SDK React library.

Table of Contents

  1. Connection & Status Hooks
  2. Authentication Hooks
  3. Transaction Hooks
  4. Contract Interaction Hooks
  5. MFA Hooks
  6. Typed Signing
  7. External Wallet Client Hook
  8. Solana Hooks
  9. Complete Transaction Flow Example
  10. Notes

Connection & Status Hooks

useIsConnected()

Check if the wallet is currently connected.
import { useIsConnected } from '@abstraxn/signer-react';

function MyComponent() {
  const isConnected = useIsConnected();

  return (
    <div>
      {isConnected ? 'Wallet Connected' : 'Wallet Not Connected'}
    </div>
  );
}
Returns: boolean - true if wallet is connected, false otherwise.

useAddress()

Get the current wallet address.
import { useAddress } from '@abstraxn/signer-react';

function MyComponent() {
  const address = useAddress();

  return (
    <div>
      {address ? `Address: ${address}` : 'No address available'}
    </div>
  );
}
Returns: string | null - The wallet address or null if not connected.

useChainId()

Get the current chain ID.
import { useChainId } from '@abstraxn/signer-react';

function MyComponent() {
  const chainId = useChainId();

  return (
    <div>
      {chainId ? `Chain ID: ${chainId}` : 'No chain ID available'}
    </div>
  );
}
Returns: number | null - The chain ID or null if not connected.

useError()

Get the current error state.
import { useError } from '@abstraxn/signer-react';

function MyComponent() {
  const error = useError();

  if (error) {
    return <div>Error: {error.message}</div>;
  }

  return <div>No errors</div>;
}
Returns: Error | null - The current error or null if no error.

useWallet()

Get the wallet instance for advanced usage.
import { useWallet } from '@abstraxn/signer-react';

function MyComponent() {
  const wallet = useWallet();

  // Use wallet for advanced operations
  // Note: Most operations should use dedicated hooks instead
}
Returns: Wallet instance or null if not connected.

useConnectionType()

Get the connection type (how the user connected).
import { useConnectionType } from '@abstraxn/signer-react';

function MyComponent() {
  const { connectionType, connectorMeta } = useConnectionType();

  if (!connectionType) {
    return <div>Not connected</div>;
  }

  return (
    <div>
      <p>Connected via: {connectorMeta?.name || connectionType}</p>
      {connectionType === 'google' && <div>Welcome Google user!</div>}
      {connectionType === 'metamask' && <div>MetaMask wallet connected</div>}
      {connectionType === 'email' && <div>Email OTP user</div>}
      {connectionType === 'passkey' && <div>Passkey user</div>}
    </div>
  );
}
Returns:
  • connectionType: ConnectorType | null - The connection method (‘google’, ‘x’, ‘discord’, ‘metamask’, ‘walletconnect’, ‘email’, ‘passkey’, etc.)
  • connectorMeta: Connector metadata with name, icon, etc.

Authentication Hooks

useAuthContext()

Get current user and whoami information.
import { useAuthContext } from '@abstraxn/signer-react';

function MyComponent() {
  const { user, whoami } = useAuthContext();

  return (
    <div>
      {user && <p>User ID: {user.id}</p>}
      {whoami && (
        <div>
          <p>EVM Address: {whoami.evmAddress}</p>
          <p>Solana Address: {whoami.solanaAddress}</p>
        </div>
      )}
    </div>
  );
}
Returns:
  • user: User object
  • whoami: Whoami response with address information

useWhoami()

Call whoami API with loading state and refresh capability.
import { useWhoami } from '@abstraxn/signer-react';
import { useEffect } from 'react';

function MyComponent() {
  const { whoami, loading, error, refreshWhoami, isConnected } = useWhoami();

  useEffect(() => {
    if (isConnected) {
      refreshWhoami();
    }
  }, [isConnected, refreshWhoami]);

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;
  if (!whoami) return <div>No whoami data</div>;

  return (
    <div>
      <p>EVM Address: {whoami.evmAddress}</p>
      <p>Solana Address: {whoami.solanaAddress}</p>
      <button onClick={refreshWhoami}>Refresh</button>
    </div>
  );
}
Returns:
  • whoami: WhoamiResponse | null - Whoami data
  • loading: boolean - Loading state
  • error: Error | null - Error state
  • refreshWhoami: Function to refresh whoami data
  • isConnected: boolean - Connection status

useExportWallet()

Export wallet private key.
import { useExportWallet } from '@abstraxn/signer-react';

function MyComponent() {
  const { exportWallet, isConnected, address } = useExportWallet();

  const handleExport = async () => {
    try {
      const result = await exportWallet(
        'targetPublicKey', // Target public key for encryption
        'privateKey',       // Your private key for encryption
        'evm'              // or 'solana'
      );
      console.log('Export successful:', result);
    } catch (error) {
      console.error('Export failed:', error);
    }
  };

  if (!isConnected) {
    return <div>Please connect your wallet</div>;
  }

  return (
    <button onClick={handleExport}>
      Export Wallet
    </button>
  );
}
Returns:
  • exportWallet: Function to export wallet
  • isConnected: boolean - Connection status
  • address: string | null - Wallet address

Transaction Hooks

usePublicClient(chain, rpcUrl)

Create a publicClient using viem for read operations.
import { usePublicClient } from '@abstraxn/signer-react';
import { polygonAmoy } from 'viem/chains';

function MyComponent() {
  const { publicClient } = usePublicClient(
    polygonAmoy,
    'https://rpc-amoy.polygon.technology'
  );

  const getBalance = async (address: string) => {
    const balance = await publicClient.getBalance({ address: address as `0x${string}` });
    return balance;
  };

  return (
    <button onClick={() => getBalance('0x...')}>
      Get Balance
    </button>
  );
}
Parameters:
  • chain: Viem chain object (from ‘viem/chains’ or custom)
  • rpcUrl: RPC URL for the chain
Returns:
  • publicClient: PublicClient instance from viem

useWalletClient(chain, rpcUrl?)

Create a walletClient using viem for broadcasting signed transactions.
import { useWalletClient } from '@abstraxn/signer-react';
import { polygonAmoy } from 'viem/chains';

function MyComponent() {
  const { walletClient } = useWalletClient(
    polygonAmoy,
    'https://rpc-amoy.polygon.technology'
  );

  const broadcastTransaction = async (signedTx: string) => {
    const hash = await walletClient.sendRawTransaction({
      serializedTransaction: signedTx as `0x${string}`,
    });
    return hash;
  };

  return (
    <button onClick={() => broadcastTransaction('0x...')}>
      Broadcast Transaction
    </button>
  );
}
Parameters:
  • chain: Viem chain object
  • rpcUrl: Optional RPC URL (uses chain’s default if not provided)
Returns:
  • walletClient: WalletClient instance from viem

usePrepareRawTxn(provider)

Prepare raw transaction data with encoding support.
import { usePrepareRawTxn, usePublicClient, useAddress } from '@abstraxn/signer-react';
import { polygonAmoy } from 'viem/chains';

function MyComponent() {
  const address = useAddress();
  const { publicClient } = usePublicClient(polygonAmoy, 'https://rpc-amoy.polygon.technology');
  const { prepareRawTxn } = usePrepareRawTxn(publicClient);

  // Native transfer
  const handleNativeTransfer = async () => {
    const nativeTx = await prepareRawTxn({
      from: address!,
      to: '0x...',
      value: '0.001', // ETH amount
    });
    // Returns: { to: '0x...', value: '0x...', data: '0x' }
    console.log(nativeTx);
  };

  // Contract call with encoding
  const handleContractCall = async () => {
    const contractTx = await prepareRawTxn({
      from: address!,
      to: '0x...', // Contract address
      abi: erc20Abi,
      functionName: 'transfer',
      args: ['0x...', 1000000n], // Pass values in the expected on-chain format
      value: '0', // Optional ETH value
    });
    // Returns: { to: '0x...', value: '0x', data: '0xa9059cbb...' }
    console.log(contractTx);
  };

  // Contract call with pre-encoded data
  const handlePreEncoded = async () => {
    const contractTx = await prepareRawTxn({
      from: address!,
      to: '0x...',
      data: '0xa9059cbb...', // Already encoded
    });
    console.log(contractTx);
  };

  return (
    <div>
      <button onClick={handleNativeTransfer}>Native Transfer</button>
      <button onClick={handleContractCall}>Contract Call</button>
    </div>
  );
}
Parameters:
  • provider: PublicClient instance
Returns:
  • prepareRawTxn: Function that accepts:
    • from: Address
    • to: Address
    • value?: Native token value (pass in chain/base units, e.g. wei)
    • data?: Pre-encoded function data
    • abi?: Contract ABI (for encoding)
    • functionName?: Function name (for encoding)
    • args?: Function arguments (passed through as-is; no implicit amount conversion)

useSignTxn(provider)

Sign transaction using Abstraxn server wallet API.
import { useSignTxn, usePrepareRawTxn, usePublicClient, useAddress } from '@abstraxn/signer-react';
import { polygonAmoy } from 'viem/chains';

function MyComponent() {
  const address = useAddress();
  const { publicClient } = usePublicClient(polygonAmoy, 'https://rpc-amoy.polygon.technology');
  const { prepareRawTxn } = usePrepareRawTxn(publicClient);
  const { signTxn, isConnected } = useSignTxn(publicClient);

  const handleSign = async () => {
    // Prepare transaction
    const rawTx = await prepareRawTxn({
      from: address!,
      to: '0x...',
      value: '0.001',
    });

    // Sign transaction
    const signedTx = await signTxn({
      from: address!,
      ...rawTx, // Spread to, value, data from prepareRawTxn
    });

    console.log('Signed transaction:', signedTx.signedTransaction);
  };

  if (!isConnected) {
    return <div>Please connect your wallet</div>;
  }

  return <button onClick={handleSign}>Sign Transaction</button>;
}
Parameters:
  • provider: PublicClient instance
Returns:
  • signTxn: Function to sign transaction
  • isConnected: boolean - Connection status
  • address: string | null - Wallet address

useSignAndSendTxn(provider)

Sign and send transaction using Abstraxn server wallet API.
import { useSignAndSendTxn, usePrepareRawTxn, usePublicClient, useAddress } from '@abstraxn/signer-react';
import { polygonAmoy } from 'viem/chains';

function MyComponent() {
  const address = useAddress();
  const { publicClient } = usePublicClient(polygonAmoy, 'https://rpc-amoy.polygon.technology');
  const { prepareRawTxn } = usePrepareRawTxn(publicClient);
  const { signAndSendTxn, isConnected } = useSignAndSendTxn(publicClient);

  const handleSend = async () => {
    // Prepare transaction
    const rawTx = await prepareRawTxn({
      from: address!,
      to: '0x...',
      value: '0.001',
    });

    // Sign and send transaction
    const result = await signAndSendTxn({
      from: address!,
      ...rawTx, // Spread to, value, data from prepareRawTxn
    });

    console.log('Transaction hash:', result.hash);
  };

  if (!isConnected) {
    return <div>Please connect your wallet</div>;
  }

  return <button onClick={handleSend}>Send Transaction</button>;
}
Parameters:
  • provider: PublicClient instance
Returns:
  • signAndSendTxn: Function to sign and send transaction
  • isConnected: boolean - Connection status
  • address: string | null - Wallet address

useWaitForTxnReceipt(provider)

Wait for transaction receipt.
import { useWaitForTxnReceipt, usePublicClient } from '@abstraxn/signer-react';
import { polygonAmoy } from 'viem/chains';

function MyComponent() {
  const { publicClient } = usePublicClient(polygonAmoy, 'https://rpc-amoy.polygon.technology');
  const { waitForTxnReceipt } = useWaitForTxnReceipt(publicClient);

  const handleWait = async (txHash: string) => {
    try {
      const receipt = await waitForTxnReceipt({
        hash: txHash as `0x${string}`,
        confirmations: 1, // Optional: number of confirmations
      });

      console.log('Transaction confirmed:', receipt);
      console.log('Status:', receipt.status);
    } catch (error) {
      console.error('Failed to wait for receipt:', error);
    }
  };

  return (
    <button onClick={() => handleWait('0x...')}>
      Wait for Receipt
    </button>
  );
}
Parameters:
  • provider: PublicClient instance
Returns:
  • waitForTxnReceipt: Function that accepts:
    • hash: Transaction hash
    • confirmations?: Number of confirmations to wait for
    • timeout?: Timeout in milliseconds

useSwitchChain()

Switch chain for both internal (social) and external wallets.
import { useSwitchChain } from '@abstraxn/signer-react';

function MyComponent() {
  const { switchChain } = useSwitchChain();

  const handleSwitch = async () => {
    try {
      await switchChain(137); // Switch to Polygon
      console.log('Chain switched successfully');
    } catch (error) {
      console.error('Failed to switch chain:', error);
    }
  };

  return <button onClick={handleSwitch}>Switch to Polygon</button>;
}
Returns:
  • switchChain: Function to switch chain (accepts chainId: number)

useSignMessage()

Sign a message (for external wallets only).
import { useSignMessage } from '@abstraxn/signer-react';

function MyComponent() {
  const { signMessage } = useSignMessage();

  const handleSign = async () => {
    try {
      const signature = await signMessage('Hello World');
      console.log('Signature:', signature);
    } catch (error) {
      console.error('Failed to sign message:', error);
    }
  };

  return <button onClick={handleSign}>Sign Message</button>;
}
Note: Signing messages is not supported for embedded wallets (Google, email, etc.). Only works with external wallets.
Returns:
  • signMessage: Function to sign message (accepts message: string)

Contract Interaction Hooks

useContract({ address, abi, provider })

Create a contract instance using viem.
import { useContract, usePublicClient } from '@abstraxn/signer-react';
import { polygonAmoy } from 'viem/chains';
import erc20Abi from './erc20Abi.json';

function MyComponent() {
  const { publicClient } = usePublicClient(polygonAmoy, 'https://rpc-amoy.polygon.technology');

  const { contract } = useContract({
    address: '0x...',
    abi: erc20Abi,
    provider: publicClient,
  });

  const readBalance = async (address: string) => {
    const balance = await contract.read.balanceOf([address]);
    return balance;
  };

  return (
    <button onClick={() => readBalance('0x...')}>
      Read Balance
    </button>
  );
}
Parameters:
  • address: Contract address
  • abi: Contract ABI
  • provider: PublicClient instance
Returns:
  • contract: Contract instance from viem

useReadContract(provider)

Read from contract using publicClient.
import { useReadContract, usePublicClient } from '@abstraxn/signer-react';
import { polygonAmoy } from 'viem/chains';
import erc20Abi from './erc20Abi.json';

function MyComponent() {
  const { publicClient } = usePublicClient(polygonAmoy, 'https://rpc-amoy.polygon.technology');
  const { readContract } = useReadContract(publicClient);

  const readBalance = async () => {
    try {
      const balance = await readContract({
        address: '0x...',
        abi: erc20Abi,
        functionName: 'balanceOf',
        args: ['0x...'],
      });
      console.log('Balance:', balance);
    } catch (error) {
      console.error('Failed to read contract:', error);
    }
  };

  const readName = async () => {
    const name = await readContract({
      address: '0x...',
      abi: erc20Abi,
      functionName: 'name',
    });
    console.log('Name:', name);
  };

  return (
    <div>
      <button onClick={readBalance}>Read Balance</button>
      <button onClick={readName}>Read Name</button>
    </div>
  );
}
Parameters:
  • provider: PublicClient instance
Returns:
  • readContract: Function that accepts:
    • address: Contract address
    • abi: Contract ABI
    • functionName: Function name
    • args?: Function arguments

useWriteContract()

Write to contract (for external wallets like MetaMask, WalletConnect, etc.).
import { useWriteContract } from '@abstraxn/signer-react';
import { parseEther } from 'viem';
import erc20Abi from './erc20Abi.json';

function MyComponent() {
  const { writeContract } = useWriteContract();

  const handleTransfer = async () => {
    try {
      // Write to contract
      const hash = await writeContract({
        address: '0x...', // Contract address
        abi: erc20Abi,
        functionName: 'transfer',
        args: ['0x...', '1000000000000000000'], // to, amount in wei
      });

      console.log('Transaction hash:', hash);
    } catch (error) {
      console.error('Transaction failed:', error);
    }
  };

  const handleDeposit = async () => {
    try {
      // With ETH value
      const hash = await writeContract({
        address: '0x...',
        abi: contractAbi,
        functionName: 'deposit',
        value: parseEther('0.1'), // Send 0.1 ETH with the transaction
      });

      console.log('Transaction hash:', hash);
    } catch (error) {
      console.error('Transaction failed:', error);
    }
  };

  return (
    <div>
      <button onClick={handleTransfer}>Transfer Tokens</button>
      <button onClick={handleDeposit}>Deposit</button>
    </div>
  );
}
Returns:
  • writeContract: Function that accepts:
    • address: Contract address
    • abi: Contract ABI
    • functionName: Function name
    • args?: Function arguments
    • value?: ETH value (bigint)
    • account?: Account address
    • gas?: Gas limit
    • gasPrice?: Gas price
    • maxFeePerGas?: Max fee per gas
    • maxPriorityFeePerGas?: Max priority fee per gas
    • nonce?: Nonce

MFA Hooks

useEnableMfa()

Manage the MFA enable setup flow:
  • start() initializes setup and returns QR + secret
  • verifyCode(code) verifies TOTP setup
  • verifyRecoveryCode(code) validates backup/recovery code
  • setupState moves through setup -> verify -> complete
import { useEnableMfa } from '@abstraxn/signer-react';

function EnableMfaCard() {
  const { setupState, start, verifyCode, isLoading, error } = useEnableMfa();

  return (
    <div>
      <button onClick={() => void start()}>Start MFA setup</button>
      {setupState?.step === 'setup' && <img src={setupState.qrCode} alt="MFA QR" />}
      {setupState?.step === 'verify' && (
        <button onClick={() => void verifyCode('123456')}>Verify code</button>
      )}
      {isLoading && <p>Loading...</p>}
      {error && <p>Error: {error}</p>}
    </div>
  );
}

useDisableMfa()

Manage MFA disable flow:
  • start() begins auth step
  • switchMethod('otp' | 'recovery') selects auth mode
  • verifyCode(code) verifies OTP or backup code
  • confirmDisable() disables MFA after verification
import { useDisableMfa } from '@abstraxn/signer-react';

function DisableMfaCard() {
  const { start, verifyCode, confirmDisable, disableState } = useDisableMfa();

  return (
    <div>
      {!disableState && <button onClick={start}>Disable MFA</button>}
      {disableState?.step === 'auth' && (
        <button onClick={() => void verifyCode('123456')}>Verify</button>
      )}
      {disableState?.step === 'confirm' && (
        <button onClick={() => void confirmDisable()}>Confirm disable</button>
      )}
    </div>
  );
}

useEmailForOtp()

Pre-fill the onboarding email field for OTP login.
import { useEmailForOtp } from '@abstraxn/signer-react';

function PrefillEmailButton() {
  const { emailForOtp, setEmailForOtp } = useEmailForOtp();

  return (
    <button onClick={() => setEmailForOtp('[email protected]')}>
      Current email: {emailForOtp || 'not set'}
    </button>
  );
}

Typed Signing

useSignTypedTx()

Sign EIP-712 payloads with embedded wallets.
import { useAddress, useSignTypedTx } from '@abstraxn/signer-react';

function SignTypedDataExample() {
  const address = useAddress();
  const { signTypedTx } = useSignTypedTx();

  const sign = async () => {
    if (!address) return;
    const result = await signTypedTx({
      from: address as `0x${string}`,
      domain: { name: 'Demo', version: '1', chainId: 80002 },
      primaryType: 'Mail',
      types: {
        Mail: [
          { name: 'to', type: 'address' },
          { name: 'contents', type: 'string' },
        ],
      },
      message: {
        to: address,
        contents: 'hello',
      },
      encoding: 'PAYLOAD_ENCODING_EIP712',
      hashFunction: 'HASH_FUNCTION_KECCAK256',
    });
    console.log(result.signature);
  };

  return <button onClick={() => void sign()}>Sign typed payload</button>;
}

External Wallet Client Hook

useExternalWalletClient()

Access the underlying external wallet client (wagmi connector client) and connection state.
import { useExternalWalletClient } from '@abstraxn/signer-react';

function ExternalWalletClientState() {
  const { walletClient, isConnected, isPending, isError, error } =
    useExternalWalletClient();

  return (
    <div>
      <p>Connected: {String(isConnected)}</p>
      <p>Pending: {String(isPending)}</p>
      <p>Error: {isError ? error?.message : 'none'}</p>
      <p>Client ready: {String(!!walletClient)}</p>
    </div>
  );
}

Solana Hooks

useSolanaConnection(rpcUrl, commitment?)

Create a Solana RPC connection.

useSolanaPublicKey()

Get the current Solana address from authenticated user context.

useSolanaBalance()

Load Solana balance (lamports, formattedBalance, loading/error).

usePrepareSolanaTxn(connection)

Prepare transfer or instruction-based transactions.

useSignSolanaTxn(connection)

Sign prepared Solana transaction through SDK signing API.

useSignAndSendSolanaTxn(connection)

Sign and send prepared Solana transaction in one call.

useWaitForSolanaConfirmation(connection)

Wait for signature confirmation on Solana.

usePrepareSolanaProgramTxn(connection) and useSolanaProgramTransaction(connection)

Prepare and send program transactions with programId, accounts, and encoded instruction data.

useSolanaExternalWallet()

Interact with connected external Solana wallets (sign message, sign tx, send tx).
import {
  useSolanaConnection,
  usePrepareSolanaTxn,
  useSignAndSendSolanaTxn,
  useWaitForSolanaConfirmation,
  useSolanaPublicKey,
} from '@abstraxn/signer-react';

function SolanaSendExample() {
  const { solanaAddress } = useSolanaPublicKey();
  const { connection } = useSolanaConnection('https://api.devnet.solana.com');
  const { prepareSolanaTransfer } = usePrepareSolanaTxn(connection);
  const { signAndSendSolanaTxn } = useSignAndSendSolanaTxn(connection);
  const { waitForSolanaConfirmation } = useWaitForSolanaConfirmation(connection);

  const send = async () => {
    if (!solanaAddress) return;
    const { transaction } = await prepareSolanaTransfer({
      fromPubkey: solanaAddress,
      toPubkey: '9xQeWvG816bUx9EPfEZ9PzWQw4j6wVx6U6z9ER6Q9Y2Z',
      amountInSol: 0.01,
    });
    const sent = await signAndSendSolanaTxn({ transaction, fromPubkey: solanaAddress });
    await waitForSolanaConfirmation({ signature: sent.signature });
  };

  return <button onClick={() => void send()}>Send SOL</button>;
}

Complete Transaction Flow Example

Here’s a complete example showing how to use multiple hooks together for a full transaction flow:
import {
  useAddress,
  usePublicClient,
  usePrepareRawTxn,
  useSignAndSendTxn,
  useWaitForTxnReceipt
} from '@abstraxn/signer-react';
import { polygonAmoy } from 'viem/chains';
import { useState } from 'react';

function SendTransactionComponent() {
  const address = useAddress();
  const { publicClient } = usePublicClient(
    polygonAmoy,
    'https://rpc-amoy.polygon.technology'
  );
  const { prepareRawTxn } = usePrepareRawTxn(publicClient);
  const { signAndSendTxn, isConnected } = useSignAndSendTxn(publicClient);
  const { waitForTxnReceipt } = useWaitForTxnReceipt(publicClient);

  const [loading, setLoading] = useState(false);
  const [txHash, setTxHash] = useState<string | null>(null);
  const [receipt, setReceipt] = useState<any>(null);

  const handleSendTransaction = async () => {
    if (!address || !isConnected) {
      alert('Please connect your wallet');
      return;
    }

    setLoading(true);
    try {
      // Step 1: Prepare transaction
      const rawTx = await prepareRawTxn({
        from: address,
        to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', // Example recipient
        value: '0.001', // Send 0.001 ETH
      });

      // Step 2: Sign and send transaction
      const result = await signAndSendTxn({
        from: address,
        ...rawTx,
      });

      setTxHash(result.hash);

      // Step 3: Wait for receipt
      const txReceipt = await waitForTxnReceipt({
        hash: result.hash,
        confirmations: 1,
      });

      setReceipt(txReceipt);
      console.log('Transaction confirmed:', txReceipt);
    } catch (error) {
      console.error('Transaction failed:', error);
      alert(`Transaction failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
    } finally {
      setLoading(false);
    }
  };

  if (!isConnected) {
    return <div>Please connect your wallet</div>;
  }

  return (
    <div>
      <button onClick={handleSendTransaction} disabled={loading}>
        {loading ? 'Processing...' : 'Send 0.001 ETH'}
      </button>

      {txHash && (
        <div>
          <p>Transaction Hash: {txHash}</p>
          <a
            href={`https://amoy.polygonscan.com/tx/${txHash}`}
            target="_blank"
            rel="noopener noreferrer"
          >
            View on PolygonScan
          </a>
        </div>
      )}

      {receipt && (
        <div>
          <p>Status: {receipt.status === 'success' ? 'Success' : 'Failed'}</p>
          <p>Block Number: {receipt.blockNumber.toString()}</p>
        </div>
      )}
    </div>
  );
}

Notes

  1. Provider Setup: Most hooks require a PublicClient instance. Create it using usePublicClient(chain, rpcUrl).
  2. Connection Types:
    • Social logins (Google, email, X, Discord, passkey) use embedded wallets
    • External wallets (MetaMask, WalletConnect) use the connected wallet directly
  3. Transaction Flow:
    • For embedded wallets: Use usePrepareRawTxnuseSignAndSendTxnuseWaitForTxnReceipt
    • For external wallets: Use useWriteContract or useExternalWalletInfo().walletClient
  4. Error Handling: Always wrap hook calls in try-catch blocks for proper error handling.
  5. Loading States: Many hooks provide loading states. Use them to show loading indicators in your UI.
  6. Chain Switching: Use useSwitchChain() to switch chains. It works for both embedded and external wallets.
  7. MFA Step-Up: Signing hooks may require an MFA step-up verification code when enhanced security is enabled.

Next Steps