Payment Verification

Each X-Qwery-Payment signature is checked by:

  • getTransaction(signature) on Solana

  • Conditions:

    • confirmed tx

    • correct USDC mint and amount

    • recipient = Qwery escrow

    • sender = registered wallet

    • within time window (e.g. 30s)

    • not seen before (Redis)

On failure → HTTP 402 with instructions.

Always Verify Payments On-Chain:

Method 1: Use /verify endpoint

const verification = await fetch('https://facilitator.qwery.xyz/verify', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ tx_signature: 'abc123...' })
});

const result = await verification.json();
if (result.verified && result.status === 'confirmed') {
  // Payment is valid
}

Method 2: Check blockchain directly

from solana.rpc.async_api import AsyncClient

async def verify_payment(tx_signature: str):
    client = AsyncClient("https://api.mainnet-beta.solana.com")
    tx = await client.get_transaction(tx_signature)
    
    if not tx.value:
        return False
    
    # Check transaction succeeded
    if tx.value.transaction.meta.err:
        return False
    
    # Verify amount, recipient, etc.
    return True

Never Trust Client-Side Only:

// ❌ BAD - Client says "I paid"
if (userSaysPaid) {
  if (userSaysPaid) {
    grantAccess();  // Dangerous!
  }

// ✅ GOOD - Verify on blockchain
const verified = await verifyOnChain(txSignature);
if (verified) {
  grantAccess();
}

Last updated