Verification

How Vanta SDK verifies blockchain payments.

Verification Overview

Payment verification confirms that a transaction exists on-chain and meets all requirements before granting access to protected resources.

Verification Steps

  1. Parse Authorization: Extract payment proof from headers
  2. Validate Challenge: Check challenge exists and isn't expired
  3. Fetch Transaction: Query blockchain for transaction details
  4. Verify Amount: Confirm payment amount matches or exceeds price
  5. Verify Recipient: Confirm funds sent to correct address
  6. Verify Data: Confirm challenge ID in transaction data
  7. Check Confirmations: Ensure sufficient block confirmations
  8. Mark Challenge Used: Prevent replay attacks

Implementation

verifier.ts
interface VerificationResult {
  valid: boolean
  payment?: {
    transactionHash: string
    from: string
    amount: string
    blockNumber: number
    confirmations: number
  }
  error?: string
}

async function verifyPayment(
  authorization: string,
  challenge: StoredChallenge
): Promise<VerificationResult> {
  const proof = parseAuthorization(authorization)
  
  // Fetch transaction from blockchain
  const tx = await provider.getTransaction(proof.txHash)
  if (!tx) return { valid: false, error: 'PAYMENT_NOT_FOUND' }
  
  // Verify all requirements
  if (tx.to !== challenge.recipient) {
    return { valid: false, error: 'WRONG_RECIPIENT' }
  }
  
  if (BigInt(tx.value) < parseEther(challenge.price)) {
    return { valid: false, error: 'INSUFFICIENT_PAYMENT' }
  }
  
  // Check confirmations
  const receipt = await tx.wait(1)
  
  return {
    valid: true,
    payment: {
      transactionHash: tx.hash,
      from: tx.from,
      amount: formatEther(tx.value),
      blockNumber: receipt.blockNumber,
      confirmations: await getConfirmations(receipt),
    },
  }
}

RPC Providers

Configure RPC endpoints for each supported network:

VantaMiddleware({
  // ...
  rpcUrls: {
    base: process.env.RPC_BASE || 'https://mainnet.base.org',
    ethereum: process.env.RPC_ETH || 'https://eth.llamarpc.com',
    optimism: process.env.RPC_OP || 'https://mainnet.optimism.io',
    arbitrum: process.env.RPC_ARB || 'https://arb1.arbitrum.io/rpc',
  },
  confirmations: 1,  // Blocks to wait
})

Performance Considerations

  • On-chain verification typically takes 100-500ms
  • Use access tokens to avoid repeated verification
  • Consider caching transaction receipts
  • Use reliable RPC providers with good uptime