Skip to content

Backend Verification

Backend Verification

The onSwapSuccess callback runs in the user's browser and can be spoofed. For any business-critical flow (e-commerce payments, SaaS subscriptions, etc.), always verify the order server-side.

Verify via API

After receiving onSwapSuccess on the frontend, confirm the order on your backend:

GET <your-api-endpoint>/v1/orders/:walletAddress

This returns a paginated list of orders for the given address, including status, amounts, and transaction hashes.

Verification Flow

1. Frontend: onSwapSuccess fires with { orderId, txHash, ... }
2. Frontend: POST to your backend with orderId and txHash
3. Backend:  GET /v1/orders/:address from the API
4. Backend:  Find the order matching the orderId
5. Backend:  Verify status is "filled" or another terminal status
6. Backend:  Confirm amounts match expected values
7. Backend:  Mark payment as verified in your database

Example: Express.js Verification Endpoint

js
const API_ENDPOINT = process.env.HYPERSTREAM_API_URL;

app.post('/api/verify-payment', async (req, res) => {
  const { orderId, walletAddress } = req.body;

  // Query the API directly — don't trust frontend data
  const response = await fetch(
    `${API_ENDPOINT}/v1/orders/${walletAddress}`
  );
  const data = await response.json();

  // Find the specific order
  const order = data.data?.find((o) => o.id === orderId);

  if (!order) {
    return res.status(404).json({ error: 'Order not found' });
  }

  if (order.status !== 'filled') {
    return res.status(400).json({ error: 'Order not yet complete', status: order.status });
  }

  // Verify the order matches your expected payment
  // (check token, amount, recipient, etc.)

  // Mark as verified in your database
  await db.payments.update({
    where: { orderId },
    data: { verified: true },
  });

  return res.json({ verified: true });
});

Transaction Hash Verification

The txHash from onSwapSuccess is the source chain transaction hash. You can also verify it directly on the source chain's block explorer or via an RPC call:

  • EVM chains: Query the transaction receipt via eth_getTransactionReceipt
  • Solana: Query via getTransaction RPC method

This confirms the transaction was actually broadcast and included in a block.

Security Best Practices

  • Never trust frontend callbacks alone for payment verification
  • Always query the API from your backend using the wallet address and order ID
  • Validate amounts and tokens — ensure the order matches what you expected
  • Check for terminal status — only accept orders with a filled status
  • Idempotency — handle duplicate verification requests gracefully