Skip to content

Expiry & countdown

Live order expiry state for the checkout screen.

When to use

Show time remaining while an order is active, and switch to expired UI when the timer hits zero. Prefer these hooks over manually parsing order.expiresAt.

Hooks

HookReturnsUpdates
useExchangePayOrderExpiry(){ expiresAt, hasActiveOrder, timeLeftMs, isExpired }When the active order changes
useExchangePayOrderCountdown()Same + { hours, minutes, seconds }Ticks every 1 second while active

Both wrap the active order from useExchangePayOrder, so they require ExchangePayContextProvider. Countdown is what you usually want for a visible timer.

Example

tsx
import {
  useExchangePayOrder,
  useExchangePayOrderCountdown,
} from '@swapped/connect-sdk/react'

function PendingPayment() {
  const { order, isCompleted, closeOrder } = useExchangePayOrder()
  const { hours, minutes, seconds, isExpired, hasActiveOrder } =
    useExchangePayOrderCountdown()

  if (!hasActiveOrder) return null
  if (isCompleted) return <p>Payment received</p>
  if (isExpired) return <p>Order expired — create a new one</p>

  return (
    <div>
      <p>
        Time left: {hours}:{minutes}:{seconds}
      </p>
      {order?.canClose && (
        <button type="button" onClick={() => void closeOrder()}>
          Cancel
        </button>
      )}
    </div>
  )
}

For side effects when the order expires (navigate away, toast), use useOnExchangePayOrderExpired — see Event hooks.

Notes

  • Expiry is per order, not a Coinbase submission cooldown.
  • When the order expires, useExchangePayOrder().order is cleared and the last order is kept on expiredOrder if you still need the payload.
  • After expiry, create a new order — do not reuse old checkout links.
  • isExpired from the countdown hook and useExchangePayOrder().isExpired should stay in sync; either is fine for UI.

Errors

These hooks do not throw. Order create / close errors come from useExchangePayOrder — see Errors.