> ## Documentation Index
> Fetch the complete documentation index at: https://docs.streambird.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Send Transaction

The Send Transaction screen is displayed when your application requests to sign and broadcast a blockchain transaction. This screen shows users the transaction details, signs it with their wallet, and automatically broadcasts it to the blockchain network.

<Info>
  Send Transaction combines signing and broadcasting in one step. For more control over when a transaction is broadcast, use [Sign Transaction](/authentication/user-authentication/ui-components/sign-transaction) instead.
</Info>

## How it works

When your application requests to send a transaction:

1. Your app calls the send transaction method from the MoonKey SDK
2. The Send Transaction screen appears, displaying transaction details
3. User reviews the transaction information (recipient, amount, gas, etc.)
4. User approves or rejects the transaction
5. If approved, MoonKey signs the transaction with the user's wallet
6. MoonKey automatically broadcasts the signed transaction to the blockchain
7. The transaction hash is returned to your application

## Triggering the Send Transaction screen

Use the `useSendTransaction` hook from the MoonKey SDK to trigger the Send Transaction screen:

<Tabs>
  <Tab title="Ethereum">
    ```tsx theme={null}
    import { useMoonKey } from '@moon-key/react-auth';
    import { useSendTransaction } from '@moon-key/react-auth/ethereum';

    export default function SendTransactionButton() {
      const { user } = useMoonKey();
      const { sendTransaction } = useSendTransaction();
      
      const handleSend = async () => {
        if (!user?.wallet) {
          alert('No wallet found');
          return;
        }
        
        try {
          const result = await sendTransaction({
            transaction: {
              to: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
              value: '0x38d7ea4c68000', // 0.001 ETH in hex
              data: '0x'
            },
            wallet: user.wallet,
            uiConfig: {
              title: 'Send 0.001 ETH',
              description: 'Transfer 0.001 ETH to the recipient',
              confirmButtonText: 'Send',
              showWalletUI: true,
              success: {
                title: 'Transaction Sent!',
                description: 'Your transaction is being processed'
              }
            }
          });
          
          console.log('Transaction hash:', result.transactionHash);
          alert(`Transaction sent! Hash: ${result.transactionHash}`);
        } catch (error) {
          console.error('Transaction failed:', error);
        }
      };
      
      return <button onClick={handleSend}>Send 0.001 ETH</button>;
    }
    ```
  </Tab>

  <Tab title="Solana">
    ```tsx theme={null}
    import { useMoonKey } from '@moon-key/react-auth';
    import { useSendTransaction } from '@moon-key/react-auth/solana';
    import { Transaction, SystemProgram, LAMPORTS_PER_SOL, PublicKey } from '@solana/web3.js';

    export default function SendTransactionButton() {
      const { user } = useMoonKey();
      const { sendTransaction } = useSendTransaction();
      
      const handleSend = async () => {
        if (!user?.wallet) {
          alert('No wallet found');
          return;
        }
        
        try {
          // Create a Solana transaction
          const transaction = new Transaction().add(
            SystemProgram.transfer({
              fromPubkey: new PublicKey(user.wallet.address),
              toPubkey: new PublicKey('RecipientAddressHere'),
              lamports: 0.001 * LAMPORTS_PER_SOL
            })
          );
          
          const result = await sendTransaction({
            transaction,
            wallet: user.wallet,
            uiConfig: {
              title: 'Send 0.001 SOL',
              description: 'Transfer 0.001 SOL to the recipient',
              confirmButtonText: 'Send',
              showWalletUI: true,
              success: {
                title: 'Transaction Sent!',
                description: 'Your transaction is being processed'
              }
            }
          });
          
          console.log('Transaction signature:', result.signature);
          alert(`Transaction sent! Signature: ${result.signature}`);
        } catch (error) {
          console.error('Transaction failed:', error);
        }
      };
      
      return <button onClick={handleSend}>Send 0.001 SOL</button>;
    }
    ```
  </Tab>
</Tabs>

## Customizing the Send Transaction screen

You can customize the Send Transaction screen by passing UI configuration in the `uiConfig` object:

```tsx theme={null}
const result = await sendTransaction({
  transaction: transactionData,
  wallet: user.wallet,
  uiConfig: {
    logoUrl: 'https://your-app.com/logo.png',
    title: 'Send Payment',
    description: 'Review and send this payment',
    confirmButtonText: 'Send Now',
    cancelButtonText: 'Cancel',
    showWalletUI: true,
    waitBeforeCloseTime: 2000,
    advancedTransaction: {
      title: 'Advanced Settings',
      closeButtonText: 'Close'
    },
    success: {
      title: 'Payment Sent!',
      description: 'Your payment is on its way'
    },
    failed: {
      title: 'Transaction Failed',
      description: 'Your transaction could not be completed',
      errorTitle: 'Error Details',
      closeButtonText: 'Close'
    }
  }
});
```

## Configuration options

### Basic UI Options

<ParamField path="logoUrl" type="string">
  URL to your company logo. Displayed at the top of the Send Transaction screen.

  **Example:**

  ```tsx theme={null}
  uiConfig: {
    logoUrl: 'https://myapp.com/logo.png'
  }
  ```
</ParamField>

<ParamField path="title" type="string">
  Custom title text displayed at the top of the Send Transaction screen.

  **Example:**

  ```tsx theme={null}
  uiConfig: {
    title: 'Send Payment'
  }
  ```
</ParamField>

<ParamField path="description" type="string">
  Custom description text displayed below the title, providing context for the transaction.

  **Example:**

  ```tsx theme={null}
  uiConfig: {
    description: 'Review the payment details before sending'
  }
  ```
</ParamField>

<ParamField path="confirmButtonText" type="string">
  Custom text for the confirm/send button.

  **Default:** `'Send'`

  **Example:**

  ```tsx theme={null}
  uiConfig: {
    confirmButtonText: 'Send Now'
  }
  ```
</ParamField>

<ParamField path="cancelButtonText" type="string">
  Custom text for the cancel button.

  **Default:** `'Cancel'`

  **Example:**

  ```tsx theme={null}
  uiConfig: {
    cancelButtonText: 'Go Back'
  }
  ```
</ParamField>

<ParamField path="showWalletUI" type="boolean">
  Whether to show wallet information (address, balance) in the Send Transaction screen.

  **Default:** `true`

  **Example:**

  ```tsx theme={null}
  uiConfig: {
    showWalletUI: true // Show balance to prevent insufficient funds errors
  }
  ```
</ParamField>

<ParamField path="waitBeforeCloseTime" type="number">
  Time in milliseconds to wait before automatically closing the screen after a successful transaction.

  **Default:** `1500` (1.5 seconds)

  **Example:**

  ```tsx theme={null}
  uiConfig: {
    waitBeforeCloseTime: 2000 // Wait 2 seconds before closing
  }
  ```
</ParamField>

### Advanced Transaction Options

<ParamField path="advancedTransaction" type="object">
  Configuration for the advanced transaction settings screen.

  <Expandable title="properties">
    <ParamField path="title" type="string">
      Title for the advanced transaction settings screen.

      **Example:**

      ```tsx theme={null}
      uiConfig: {
        advancedTransaction: {
          title: 'Advanced Settings'
        }
      }
      ```
    </ParamField>

    <ParamField path="closeButtonText" type="string">
      Text for the close button in the advanced settings screen.

      **Example:**

      ```tsx theme={null}
      uiConfig: {
        advancedTransaction: {
          closeButtonText: 'Done'
        }
      }
      ```
    </ParamField>
  </Expandable>
</ParamField>

### Success Screen Options

<ParamField path="success" type="object">
  Configuration for the success screen displayed after the transaction is sent.

  <Expandable title="properties">
    <ParamField path="title" type="string">
      Title text displayed on the success screen.

      **Example:**

      ```tsx theme={null}
      uiConfig: {
        success: {
          title: 'Transaction Sent Successfully!'
        }
      }
      ```
    </ParamField>

    <ParamField path="description" type="string">
      Description text displayed on the success screen.

      **Example:**

      ```tsx theme={null}
      uiConfig: {
        success: {
          description: 'Your transaction has been broadcast and is being confirmed'
        }
      }
      ```
    </ParamField>
  </Expandable>
</ParamField>

### Failed Screen Options

<ParamField path="failed" type="object">
  Configuration for the error screen displayed if the transaction fails.

  <Expandable title="properties">
    <ParamField path="title" type="string">
      Title text displayed on the failed screen.

      **Example:**

      ```tsx theme={null}
      uiConfig: {
        failed: {
          title: 'Transaction Failed'
        }
      }
      ```
    </ParamField>

    <ParamField path="description" type="string">
      Description text displayed on the failed screen.

      **Example:**

      ```tsx theme={null}
      uiConfig: {
        failed: {
          description: 'Your transaction could not be completed. Please try again.'
        }
      }
      ```
    </ParamField>

    <ParamField path="errorTitle" type="string">
      Title for the error details section.

      **Example:**

      ```tsx theme={null}
      uiConfig: {
        failed: {
          errorTitle: 'Error Details'
        }
      }
      ```
    </ParamField>

    <ParamField path="closeButtonText" type="string">
      Text for the close button on the failed screen.

      **Example:**

      ```tsx theme={null}
      uiConfig: {
        failed: {
          closeButtonText: 'Close'
        }
      }
      ```
    </ParamField>
  </Expandable>
</ParamField>

## Common use cases

### Simple ETH/SOL transfer

Send native currency to a recipient:

```tsx theme={null}
import { useMoonKey } from '@moon-key/react-auth';
import { useSendTransaction } from '@moon-key/react-auth/ethereum';
import { parseEther } from 'viem';

export default function SendETH() {
  const { user } = useMoonKey();
  const { sendTransaction } = useSendTransaction();
  
  const sendETH = async (recipient: string, amount: string) => {
    if (!user?.wallet) return;
    
    try {
      const result = await sendTransaction({
        transaction: {
          to: recipient,
          value: parseEther(amount).toString(16) // Convert to hex
        },
        wallet: user.wallet,
        uiConfig: {
          title: `Send ${amount} ETH`,
          description: `Transfer ${amount} ETH to ${recipient.slice(0, 6)}...${recipient.slice(-4)}`,
          confirmButtonText: 'Send ETH',
          showWalletUI: true,
          success: {
            title: 'ETH Sent!',
            description: 'Your ETH transfer is being confirmed on the blockchain'
          }
        }
      });
      
      console.log('Transaction hash:', result.transactionHash);
      return result.transactionHash;
    } catch (error) {
      console.error('Failed to send ETH:', error);
      throw error;
    }
  };
  
  return (
    <button onClick={() => sendETH('0xRecipient...', '0.1')}>
      Send 0.1 ETH
    </button>
  );
}
```

### Token transfer

Send ERC-20 or SPL tokens:

```tsx theme={null}
import { useMoonKey } from '@moon-key/react-auth';
import { useSendTransaction } from '@moon-key/react-auth/ethereum';
import { encodeFunctionData } from 'viem';

export default function SendTokens() {
  const { user } = useMoonKey();
  const { sendTransaction } = useSendTransaction();
  
  const sendTokens = async (tokenAddress: string, recipient: string, amount: bigint) => {
    if (!user?.wallet) return;
    
    try {
      // Encode ERC-20 transfer
      const data = encodeFunctionData({
        abi: [{
          name: 'transfer',
          type: 'function',
          inputs: [
            { name: 'to', type: 'address' },
            { name: 'amount', type: 'uint256' }
          ]
        }],
        functionName: 'transfer',
        args: [recipient, amount]
      });
      
      const result = await sendTransaction({
        transaction: {
          to: tokenAddress,
          data,
          value: '0x0'
        },
        wallet: user.wallet,
        uiConfig: {
          title: 'Send USDC',
          description: 'Transfer 100 USDC to recipient',
          confirmButtonText: 'Send Tokens',
          success: {
            title: 'Tokens Sent!',
            description: 'Your token transfer is being processed'
          }
        }
      });
      
      console.log('Transaction hash:', result.transactionHash);
      return result.transactionHash;
    } catch (error) {
      console.error('Failed to send tokens:', error);
      throw error;
    }
  };
  
  return (
    <button onClick={() => sendTokens('0xUSDC...', '0xRecipient...', BigInt(100_000000))}>
      Send 100 USDC
    </button>
  );
}
```

### NFT transfer

Transfer an NFT to another wallet:

```tsx theme={null}
const transferNFT = async (nftContract: string, tokenId: string, recipient: string) => {
  if (!user?.wallet) return;
  
  // Encode ERC-721 transferFrom
  const data = encodeFunctionData({
    abi: [{
      name: 'transferFrom',
      type: 'function',
      inputs: [
        { name: 'from', type: 'address' },
        { name: 'to', type: 'address' },
        { name: 'tokenId', type: 'uint256' }
      ]
    }],
    functionName: 'transferFrom',
    args: [user.wallet.address, recipient, BigInt(tokenId)]
  });
  
  const result = await sendTransaction({
    transaction: {
      to: nftContract,
      data,
      value: '0x0'
    },
    wallet: user.wallet,
    uiConfig: {
      title: 'Transfer NFT',
      description: `Transfer NFT #${tokenId} to ${recipient.slice(0, 6)}...${recipient.slice(-4)}`,
      confirmButtonText: 'Transfer',
      showWalletUI: true,
      success: {
        title: 'NFT Transferred!',
        description: 'Your NFT has been sent to the recipient'
      }
    }
  });
  
  return result.transactionHash;
};
```

### Mint NFT

Mint an NFT with payment:

```tsx theme={null}
const mintNFT = async (nftContract: string, mintPrice: string) => {
  if (!user?.wallet) return;
  
  const result = await sendTransaction({
    transaction: {
      to: nftContract,
      data: encodedMintFunction,
      value: mintPrice // e.g., '0x16345785D8A0000' for 0.1 ETH
    },
    wallet: user.wallet,
    uiConfig: {
      title: 'Mint NFT',
      description: 'Mint your NFT for 0.1 ETH',
      confirmButtonText: 'Mint Now',
      showWalletUI: true,
      success: {
        title: 'NFT Minted!',
        description: 'Your NFT is being minted. Check your wallet in a few moments.'
      }
    }
  });
  
  console.log('Mint transaction hash:', result.transactionHash);
  return result.transactionHash;
};
```

### Contract interaction with gas estimation

Send a transaction with custom gas settings:

```tsx theme={null}
const interactWithContract = async () => {
  if (!user?.wallet) return;
  
  const result = await sendTransaction({
    transaction: {
      to: '0xContractAddress',
      data: encodedFunctionCall,
      value: '0x0',
      gas: '0x30d40', // 200,000 gas limit
      gasPrice: '0x4a817c800' // 20 gwei
    },
    wallet: user.wallet,
    uiConfig: {
      title: 'Execute Contract Function',
      description: 'Call the contract function with the specified parameters',
      confirmButtonText: 'Execute',
      success: {
        title: 'Contract Called!',
        description: 'Your transaction is being confirmed'
      }
    }
  });
  
  return result.transactionHash;
};
```

## Complete example

Here's a complete example with transaction tracking:

```tsx theme={null}
'use client';
import { useMoonKey } from '@moon-key/react-auth';
import { useSendTransaction } from '@moon-key/react-auth/ethereum';
import { useState } from 'react';
import { parseEther } from 'viem';

export default function SendTransactionDemo() {
  const { user, isAuthenticated } = useMoonKey();
  const { sendTransaction } = useSendTransaction();
  const [txHash, setTxHash] = useState<string | null>(null);
  const [sending, setSending] = useState(false);
  const [recipient, setRecipient] = useState('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045');
  const [amount, setAmount] = useState('0.001');
  
  if (!isAuthenticated) {
    return <div>Please sign in first</div>;
  }
  
  if (!user?.wallet) {
    return <div>No wallet found</div>;
  }
  
  const handleSendTransaction = async () => {
    setSending(true);
    try {
      const result = await sendTransaction({
        transaction: {
          to: recipient,
          value: `0x${parseEther(amount).toString(16)}`,
          data: '0x'
        },
        wallet: user.wallet,
        uiConfig: {
          title: `Send ${amount} ETH`,
          description: `Transfer ${amount} ETH to ${recipient.slice(0, 6)}...${recipient.slice(-4)}`,
          confirmButtonText: 'Send Transaction',
          cancelButtonText: 'Cancel',
          showWalletUI: true,
          success: {
            title: 'Transaction Sent!',
            description: 'Your transaction is being confirmed on the blockchain'
          },
          failed: {
            title: 'Transaction Failed',
            description: 'Please try again or check your balance',
            closeButtonText: 'Close'
          }
        }
      });
      
      setTxHash(result.transactionHash);
      console.log('Transaction sent:', result.transactionHash);
      alert('Transaction sent successfully!');
    } catch (error) {
      console.error('Failed to send transaction:', error);
      alert('Transaction failed or was cancelled');
    } finally {
      setSending(false);
    }
  };
  
  return (
    <div style={{ padding: '20px' }}>
      <h2>Send Transaction Example</h2>
      <p>Wallet: {user.wallet.address}</p>
      
      <div style={{ marginTop: '20px' }}>
        <div style={{ marginBottom: '10px' }}>
          <label>
            Recipient Address:
            <input
              type="text"
              value={recipient}
              onChange={(e) => setRecipient(e.target.value)}
              style={{
                width: '100%',
                padding: '8px',
                marginTop: '5px'
              }}
            />
          </label>
        </div>
        
        <div style={{ marginBottom: '10px' }}>
          <label>
            Amount (ETH):
            <input
              type="text"
              value={amount}
              onChange={(e) => setAmount(e.target.value)}
              style={{
                width: '100%',
                padding: '8px',
                marginTop: '5px'
              }}
            />
          </label>
        </div>
        
        <button 
          onClick={handleSendTransaction}
          disabled={sending || !recipient || !amount}
          style={{
            padding: '10px 20px',
            marginTop: '10px'
          }}
        >
          {sending ? 'Sending...' : 'Send Transaction'}
        </button>
      </div>
      
      {txHash && (
        <div style={{ 
          marginTop: '20px',
          padding: '15px',
          background: '#f0f9ff',
          borderRadius: '5px'
        }}>
          <h3>Transaction Sent!</h3>
          <p>Transaction Hash:</p>
          <pre style={{ 
            background: '#fff', 
            padding: '10px', 
            borderRadius: '5px',
            overflow: 'auto',
            fontSize: '12px'
          }}>
            {txHash}
          </pre>
          <a 
            href={`https://etherscan.io/tx/${txHash}`}
            target="_blank"
            rel="noopener noreferrer"
            style={{ color: '#0066cc' }}
          >
            View on Etherscan →
          </a>
        </div>
      )}
    </div>
  );
}
```

## User experience flow

<Steps>
  <Step title="Trigger transaction">
    Your application calls `sendTransaction()` with transaction data, wallet, and optional UI options.
  </Step>

  <Step title="Send Transaction screen appears">
    The customized Send Transaction screen is displayed with transaction details.
  </Step>

  <Step title="Review transaction details">
    User reviews the transaction information including recipient, amount, gas fees, and any contract interactions.
  </Step>

  <Step title="Approve or reject">
    User clicks the send button to proceed, or cancels (if `isCancellable: true`) to reject.
  </Step>

  <Step title="Transaction signed and broadcast">
    If approved, MoonKey signs the transaction and automatically broadcasts it to the blockchain network.
  </Step>

  <Step title="Success screen">
    The success screen appears with the configured `successHeader` and `successDescription`.
  </Step>

  <Step title="Return transaction hash">
    The transaction hash (or signature for Solana) is returned to your application for tracking.
  </Step>
</Steps>

## Send Transaction vs. Sign Transaction

Understanding when to use each:

<AccordionGroup>
  <Accordion title="Send Transaction (this screen)">
    * **Signs and broadcasts** in one step
    * Automatically submits to the blockchain
    * Returns transaction hash immediately
    * Simpler API for basic operations
    * Best for immediate transactions
    * User can't control broadcast timing
    * Most common for standard transfers
    * Example: Send ETH, transfer tokens, mint NFTs
  </Accordion>

  <Accordion title="Sign Transaction">
    * **Only signs** the transaction
    * Does not broadcast automatically
    * Returns signed transaction data
    * Requires manual broadcasting
    * More control over when to broadcast
    * Can sign offline
    * Good for batch operations or complex flows
    * Example: Multi-step flows, conditional broadcasting
  </Accordion>
</AccordionGroup>

<Tip>
  Use **Send Transaction** for most use cases. Only use Sign Transaction when you need explicit control over the broadcasting step.
</Tip>

## Tracking transaction status

After sending a transaction, you typically want to track its confirmation status:

<Tabs>
  <Tab title="Ethereum">
    ```tsx theme={null}
    import { createPublicClient, http } from 'viem';
    import { mainnet } from 'viem/chains';

    // After sending
    const result = await sendTransaction({
      transaction: txData,
      wallet: user.wallet
    });

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

    // Track confirmation using viem
    const publicClient = createPublicClient({
      chain: mainnet,
      transport: http()
    });

    // Wait for transaction receipt
    const receipt = await publicClient.waitForTransactionReceipt({
      hash: result.transactionHash as `0x${string}`
    });

    console.log('Transaction confirmed!', receipt);
    console.log('Block number:', receipt.blockNumber);
    console.log('Gas used:', receipt.gasUsed);
    console.log('Status:', receipt.status); // 'success' or 'reverted'

    // Get transaction details
    const transaction = await publicClient.getTransaction({
      hash: result.transactionHash as `0x${string}`
    });

    console.log('Transaction details:', transaction);
    ```
  </Tab>

  <Tab title="Solana">
    ```tsx theme={null}
    import { Connection } from '@solana/web3.js';

    // After sending
    const result = await sendTransaction({
      transaction,
      wallet: user.wallet
    });

    console.log('Transaction signature:', result.signature);

    // Track confirmation using Solana web3.js
    const connection = new Connection('https://api.mainnet-beta.solana.com');

    // Wait for confirmation
    const confirmation = await connection.confirmTransaction(
      result.signature,
      'confirmed' // commitment level
    );

    console.log('Transaction confirmed!', confirmation);

    // Get transaction details
    const txDetails = await connection.getTransaction(result.signature, {
      maxSupportedTransactionVersion: 0
    });

    console.log('Transaction details:', txDetails);
    console.log('Slot:', txDetails?.slot);
    console.log('Block time:', txDetails?.blockTime);
    ```
  </Tab>
</Tabs>

## Best practices

<AccordionGroup>
  <Accordion title="Show clear transaction details">
    Always provide clear information about what the transaction does:

    ```tsx theme={null}
    uiConfig: {
      title: 'Send 100 USDC',
      description: 'Transfer 100 USDC to alice.eth. Estimated gas: $2.50'
    }
    ```
  </Accordion>

  <Accordion title="Validate inputs before sending">
    Check transaction validity before showing the UI:

    ```tsx theme={null}
    // Validate recipient address
    if (!isAddress(recipient)) {
      alert('Invalid recipient address');
      return;
    }

    // Check sufficient balance
    const balance = await getBalance(user.wallet.address);
    if (balance < amount + estimatedGas) {
      alert('Insufficient funds');
      return;
    }

    // Then send
    const result = await sendTransaction({ ... });
    ```
  </Accordion>

  <Accordion title="Handle errors appropriately">
    Different errors require different handling:

    ```tsx theme={null}
    try {
      const result = await sendTransaction({ 
        transaction: txData, 
        wallet: user.wallet 
      });
      toast.success('Transaction sent!');
    } catch (error) {
      if (error.code === 4001) {
        // User rejected
        toast.info('Transaction cancelled');
      } else if (error.message?.includes('insufficient funds')) {
        toast.error('Insufficient balance for transaction');
      } else if (error.message?.includes('gas')) {
        toast.error('Gas estimation failed. Transaction may fail.');
      } else {
        toast.error('Transaction failed. Please try again.');
      }
      console.error('Transaction error:', error);
    }
    ```
  </Accordion>

  <Accordion title="Provide transaction tracking">
    Help users track their transaction:

    ```tsx theme={null}
    const result = await sendTransaction({ ... });

    // Show link to block explorer
    const explorerUrl = `https://etherscan.io/tx/${result.transactionHash}`;

    toast.success(
      <div>
        Transaction sent!
        <a href={explorerUrl} target="_blank">View on Etherscan</a>
      </div>
    );

    // Store for user's transaction history
    await saveTransaction({
      hash: result.transactionHash,
      from: user.wallet.address,
      to: recipient,
      amount,
      timestamp: Date.now()
    });
    ```
  </Accordion>

  <Accordion title="Enable wallet UI for balance checks">
    Always show wallet UI so users can verify they have sufficient funds:

    ```tsx theme={null}
    uiConfig: {
      showWalletUI: true // Critical for preventing failed transactions
    }
    ```
  </Accordion>

  <Accordion title="Set appropriate gas limits">
    For complex transactions, set appropriate gas limits:

    ```tsx theme={null}
    // Estimate gas first
    const estimatedGas = await publicClient.estimateGas({
      to: recipient,
      data,
      value: amount
    });

    // Add 20% buffer
    const gasLimit = (estimatedGas * 120n) / 100n;

    const result = await sendTransaction({
      transaction: {
        to: recipient,
        data,
        value: amount,
        gas: `0x${gasLimit.toString(16)}`
      },
      wallet: user.wallet
    });
    ```
  </Accordion>

  <Accordion title="Store transaction history">
    Keep a record of sent transactions for user reference:

    ```tsx theme={null}
    const result = await sendTransaction({ ... });

    // Store in local storage or database
    const txRecord = {
      hash: result.transactionHash,
      from: user.wallet.address,
      to: recipient,
      amount,
      timestamp: Date.now(),
      status: 'pending'
    };

    await saveTxHistory(txRecord);

    // Update status when confirmed
    const receipt = await waitForReceipt(result.transactionHash);
    await updateTxStatus(result.transactionHash, receipt.status);
    ```
  </Accordion>

  <Accordion title="Use descriptive success messages">
    Inform users about next steps:

    ```tsx theme={null}
    uiConfig: {
      success: {
        title: 'Payment Sent!',
        description: 'Your payment is being confirmed. This usually takes 15-30 seconds.'
      }
    }
    ```
  </Accordion>
</AccordionGroup>

## Error handling

Common errors and how to handle them:

```tsx theme={null}
try {
  const result = await sendTransaction({ ... });
  return result.transactionHash;
} catch (error) {
  // User rejected the transaction
  if (error.code === 4001) {
    console.log('User cancelled transaction');
    return null;
  }
  
  // Insufficient funds
  if (error.message?.includes('insufficient funds')) {
    alert('Not enough balance to complete transaction');
    return null;
  }
  
  // Gas estimation failed
  if (error.message?.includes('gas required exceeds allowance')) {
    alert('Transaction would fail. Please check parameters.');
    return null;
  }
  
  // Network error
  if (error.message?.includes('network')) {
    alert('Network error. Please check your connection.');
    return null;
  }
  
  // Generic error
  console.error('Transaction error:', error);
  alert('Transaction failed. Please try again.');
  return null;
}
```

## Security considerations

<Warning>
  Always validate transaction parameters before sending. Malicious applications could trick users into sending funds to unintended recipients or approving dangerous contract interactions.
</Warning>

**For developers:**

1. **Validate all inputs** - Check addresses, amounts, and data before sending
2. **Show full details** - Display recipient, amount, gas fees, and contract interactions
3. **Estimate gas** - Provide accurate gas estimates to prevent failed transactions
4. **Check balances** - Verify sufficient funds before attempting to send
5. **Rate limit** - Prevent abuse by limiting transaction frequency
6. **Log transactions** - Keep records for debugging and support
7. **Handle errors** - Provide clear error messages for different failure scenarios

**For users:**

The Send Transaction screen helps users by:

* Displaying full transaction details before sending
* Showing wallet balance to prevent insufficient funds errors
* Providing clear context via title and description
* Allowing cancellation if `isCancellable` is true
* Showing success confirmation with transaction hash

## Next steps

<CardGroup cols={2}>
  <Card title="Sign Transaction" icon="file-signature" href="/authentication/user-authentication/ui-components/sign-transaction">
    Sign transactions without broadcasting
  </Card>

  <Card title="Sign Message" icon="signature" href="/authentication/user-authentication/ui-components/sign-message">
    Sign messages for authentication
  </Card>

  <Card title="UI Components Overview" icon="window-maximize" href="/authentication/user-authentication/ui-components/overview">
    Explore all UI components
  </Card>

  <Card title="Configure Appearance" icon="palette" href="/get-started/frontend-sdks/react/advance/configure-appearance">
    Global appearance settings
  </Card>
</CardGroup>
