React Hooks

The monterrey.app React SDK provides hooks for building custom payment UIs with full control over the user experience.

usePayment

The primary hook for creating and managing payments.

import { usePayment } from "@monterrey/react";

function CheckoutForm() {
  const {
    payment,
    isLoading,
    error,
    createPayment,
    cancelPayment,
  } = usePayment();

  const handleSubmit = async () => {
    const newPayment = await createPayment({
      merchantRef: "order_12345",
      amount: "1000000",
      currency: "USDC",
      chain: "polygon",
    });

    console.log("Payment address:", newPayment.address);
  };

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

  if (payment) {
    return (
      <div>
        <p>Send {payment.amount} {payment.currency} to:</p>
        <code>{payment.address}</code>
        <p>Status: {payment.status}</p>
      </div>
    );
  }

  return (
    <button onClick={handleSubmit}>
      Create Payment
    </button>
  );
}

Return Values

PropertyTypeDescription
paymentPayment | nullCurrent payment object
isLoadingbooleanTrue while creating payment
errorError | nullError if payment creation failed
createPaymentfunctionCreate a new payment
cancelPaymentfunctionCancel the current payment

usePaymentStatus

Subscribe to real-time payment status updates via WebSocket.

import { usePaymentStatus } from "@monterrey/react";

function PaymentWatcher({ paymentId }: { paymentId: string }) {
  const { status, txHash, confirmedAt } = usePaymentStatus(paymentId);

  useEffect(() => {
    if (status === "confirmed") {
      // Payment successful!
      confetti();
      router.push("/order/success");
    }
  }, [status]);

  return (
    <div>
      <p>Status: {status}</p>
      {status === "detecting" && (
        <p>Transaction detected! Waiting for confirmations...</p>
      )}
      {status === "confirmed" && (
        <p>Confirmed! Tx: {txHash}</p>
      )}
    </div>
  );
}

useQuote

Get real-time price quotes for currency conversions.

import { useQuote } from "@monterrey/react";

function PriceDisplay({ usdAmount }: { usdAmount: string }) {
  const { quote, isLoading, refresh } = useQuote({
    fromCurrency: "USD",
    toCurrency: "ETH",
    amount: usdAmount,
  });

  if (isLoading) return <span>Loading...</span>;

  return (
    <div>
      <p>${usdAmount} USD = {quote?.toAmount} ETH</p>
      <p>Rate: {quote?.rate}</p>
      <p>Valid for: {quote?.validUntil}</p>
      <button onClick={refresh}>Refresh Quote</button>
    </div>
  );
}

useChains

Get available chains and their supported tokens.

import { useChains } from "@monterrey/react";

function ChainSelector({ onSelect }) {
  const { chains, isLoading } = useChains();

  if (isLoading) return <div>Loading chains...</div>;

  return (
    <select onChange={(e) => onSelect(e.target.value)}>
      {chains.map((chain) => (
        <option key={chain.id} value={chain.id}>
          {chain.name}
        </option>
      ))}
    </select>
  );
}

useTokens

Get supported tokens for a specific chain.

import { useTokens } from "@monterrey/react";

function TokenSelector({ chain, onSelect }) {
  const { tokens, isLoading } = useTokens(chain);

  if (isLoading) return <div>Loading tokens...</div>;

  return (
    <select onChange={(e) => onSelect(e.target.value)}>
      {tokens.map((token) => (
        <option key={token.symbol} value={token.symbol}>
          {token.name} ({token.symbol})
        </option>
      ))}
    </select>
  );
}

Custom Payment Flow Example

import {
  usePayment,
  usePaymentStatus,
  useQuote,
  useChains,
  useTokens,
} from "@monterrey/react";
import { useState } from "react";

function CustomCheckout({ orderId, amount }) {
  const [chain, setChain] = useState("polygon");
  const [token, setToken] = useState("USDC");

  const { chains } = useChains();
  const { tokens } = useTokens(chain);
  const { quote } = useQuote({
    fromCurrency: "USD",
    toCurrency: token,
    amount,
  });

  const { payment, createPayment, isLoading } = usePayment();
  const status = usePaymentStatus(payment?.id);

  const handlePay = async () => {
    await createPayment({
      merchantRef: orderId,
      amount: quote.toAmount,
      currency: token,
      chain,
    });
  };

  if (status?.status === "confirmed") {
    return <div>Payment successful!</div>;
  }

  if (payment) {
    return (
      <div>
        <h3>Send {payment.amount} {payment.currency}</h3>
        <p>To: {payment.address}</p>
        <p>Status: {status?.status || "pending"}</p>
      </div>
    );
  }

  return (
    <div>
      <h3>Pay ${amount}</h3>

      <label>
        Chain:
        <select value={chain} onChange={(e) => setChain(e.target.value)}>
          {chains.map((c) => (
            <option key={c.id} value={c.id}>{c.name}</option>
          ))}
        </select>
      </label>

      <label>
        Token:
        <select value={token} onChange={(e) => setToken(e.target.value)}>
          {tokens.map((t) => (
            <option key={t.symbol} value={t.symbol}>{t.symbol}</option>
          ))}
        </select>
      </label>

      {quote && (
        <p>You'll pay: {quote.toAmount} {token}</p>
      )}

      <button onClick={handlePay} disabled={isLoading || !quote}>
        {isLoading ? "Creating..." : "Pay Now"}
      </button>
    </div>
  );
}

Next Steps

    Documentation | Monterrey