Build in Public

Reducing On-Chain Interaction Anxiety Through Frontend Optimization

ClawDUX TeamApril 9, 20266 min read0 views

Reducing On-Chain Interaction Anxiety Through Frontend Optimization

"I clicked approve and nothing happened for 30 seconds. Did I just lose my money?"

This is the most common support ticket in DeFi. Here's how to eliminate that anxiety.

The Anxiety Points

  1. Pre-transaction: "Will this do what I think it does?"
  2. During transaction: "Is it working? How long will it take?"
  3. Post-transaction: "Did it succeed? Where are my funds?"

Solution 1: Transaction Preview

Show exactly what will happen BEFORE the user signs:

tsx
function TransactionPreview({ action, details }: Props) {
  return (
    <div className="bg-surface-elevated border border-surface-border
                    rounded-xl p-4 mb-4">
      <h4 className="text-sm font-semibold text-gray-300 mb-3">
        Transaction Preview
      </h4>

      <div className="space-y-2 text-sm">
        <div className="flex justify-between">
          <span className="text-gray-500">Action</span>
          <span className="text-white font-medium">{action}</span>
        </div>
        <div className="flex justify-between">
          <span className="text-gray-500">You Pay</span>
          <span className="text-red-400">
            -{details.amount} USDC
          </span>
        </div>
        <div className="flex justify-between">
          <span className="text-gray-500">You Receive</span>
          <span className="text-emerald-400">
            Strategy: {details.strategyName}
          </span>
        </div>
        <div className="flex justify-between">
          <span className="text-gray-500">Protection</span>
          <span className="text-blue-400">
            72h escrow + AI arbitration
          </span>
        </div>
        <div className="flex justify-between">
          <span className="text-gray-500">Est. Gas</span>
          <span className="text-gray-300">
            ~${details.estimatedGas.toFixed(2)}
          </span>
        </div>
      </div>

      <div className="mt-3 p-2 bg-blue-600/10 border border-blue-500/20
                      rounded-lg text-xs text-blue-400">
        Your USDC will be locked in the escrow smart contract
        (not sent to the seller) until you confirm or the 72-hour
        window expires.
      </div>
    </div>
  );
}

Solution 2: Real-Time Transaction Status

tsx
function TransactionTracker({ txHash, expectedConfirmations = 2 }: Props) {
  const [status, setStatus] = useState<'pending' | 'confirming' | 'confirmed' | 'failed'>('pending');
  const [confirmations, setConfirmations] = useState(0);
  const [elapsed, setElapsed] = useState(0);

  useEffect(() => {
    const timer = setInterval(() => setElapsed(e => e + 1), 1000);
    return () => clearInterval(timer);
  }, []);

  return (
    <div className="bg-surface-card border border-surface-border
                    rounded-xl p-5">
      {/* Animated status indicator */}
      <div className="flex items-center gap-3 mb-4">
        {status === 'pending' && (
          <div className="w-3 h-3 rounded-full bg-amber-400 animate-pulse" />
        )}
        {status === 'confirming' && (
          <div className="w-3 h-3 rounded-full bg-blue-400 animate-pulse" />
        )}
        {status === 'confirmed' && (
          <div className="w-3 h-3 rounded-full bg-emerald-400" />
        )}
        <span className="text-sm text-gray-300">
          {status === 'pending' && 'Waiting for network...'}
          {status === 'confirming' && `Confirming (${confirmations}/${expectedConfirmations})...`}
          {status === 'confirmed' && 'Transaction confirmed!'}
        </span>
        <span className="text-xs text-gray-600 ml-auto">
          {elapsed}s
        </span>
      </div>

      {/* Progress bar */}
      <div className="h-1.5 bg-surface-elevated rounded-full overflow-hidden">
        <div
          className={`h-full rounded-full transition-all duration-500 ${
            status === 'confirmed' ? 'bg-emerald-500' : 'bg-blue-500'
          }`}
          style={{
            width: status === 'confirmed' ? '100%'
              : `${(confirmations / expectedConfirmations) * 100}%`,
          }}
        />
      </div>

      {/* Etherscan link */}
      {txHash && (
        <a
          href={`https://etherscan.io/tx/${txHash}`}
          target="_blank"
          rel="noopener noreferrer"
          className="text-xs text-blue-400 hover:text-blue-300 mt-3
                     inline-block"
        >
          View on Etherscan ↗
        </a>
      )}
    </div>
  );
}

Solution 3: Error Recovery

tsx
function TransactionError({ error, onRetry }: Props) {
  // Parse common wallet errors into human language
  const getMessage = (err: string) => {
    if (err.includes('user rejected'))
      return { title: 'Transaction Cancelled',
               desc: 'You declined the transaction in your wallet.',
               action: 'Try Again' };
    if (err.includes('insufficient funds'))
      return { title: 'Insufficient Balance',
               desc: 'You need more ETH for gas or USDC for the purchase.',
               action: 'Add Funds' };
    if (err.includes('nonce'))
      return { title: 'Transaction Conflict',
               desc: 'A previous transaction is still pending.',
               action: 'Wait & Retry' };
    return { title: 'Transaction Failed',
             desc: err.slice(0, 200),
             action: 'Try Again' };
  };

  const msg = getMessage(error);

  return (
    <div className="bg-red-600/10 border border-red-500/20
                    rounded-xl p-4">
      <h4 className="text-red-400 font-semibold">{msg.title}</h4>
      <p className="text-sm text-gray-400 mt-1">{msg.desc}</p>
      <button
        onClick={onRetry}
        className="mt-3 text-sm text-red-400 hover:text-red-300
                   underline underline-offset-2"
      >
        {msg.action}
      </button>
    </div>
  );
}

These patterns are the result of real user testing on ClawDUX, where first-time Web3 users need to feel confident locking USDC into an escrow smart contract.

The core logic discussed in this article has been integrated into the ClawDUX API. Access ClawDUX-core for full permissions, or browse the marketplace to discover verified trading strategies.

#ux#blockchain#anxiety-reduction#transactions#web3

Related Articles