Skip to main content
The payment flow is the recommended approach for handling payments in OnDB. The SDK automatically manages the entire payment process.

How It Works

1. App calls store()
       |
2. SDK sends request to broker
       |
3. Broker returns payment required response
       |
4. SDK invokes your payment callback
       |
5. Your callback executes payment
       |
6. Callback returns payment result
       |
7. SDK retries with payment proof
       |
8. Broker verifies and stores data
       |
9. SDK returns confirmed result

Basic Implementation

const result = await client.store(
  {
    collection: 'posts',
    data: [{
      title: 'My First Post',
      content: 'Stored on blockchain!',
      author: 'alice'
    }]
  },
  // Payment callback - SDK invokes this when server requires payment
  async (quote) => {
    const txHash = await processPayment(quote);

    return {
      txHash,
      network: quote.network,
      sender: walletAddress,
      chainType: quote.chainType,
      paymentMethod: 'native'
    };
  },
  true // waitForConfirmation
);

console.log(`Confirmed at block ${result.block_height}`);

Payment Quote Structure

The quote object passed to your callback contains:
interface PaymentQuote {
  quoteId: string;           // Unique quote identifier
  totalCost: number;         // Total cost in USDC
  amountRaw: string;         // Amount in smallest units
  brokerAddress: string;     // Address to pay
  description: string;       // Payment description
  expiresAt: number;         // Quote expiration timestamp
  network: string;           // Network identifier (e.g., "base", "solana")
  asset: string;             // Asset address/identifier
  tokenSymbol: string;       // Token symbol (e.g., "USDC")
  tokenDecimals: number;     // Token decimal places (e.g., 6 for USDC)
  chainType: 'cosmos' | 'evm' | 'solana';
  paymentMethod: 'native' | 'x402-facilitator';
  facilitator?: string;      // Facilitator URL (if applicable)
}

Callback Return Value

Your callback must return a payment result:

Payment Result

interface PaymentResult {
  txHash: string;          // Transaction hash from blockchain
  network: string;         // Network identifier
  sender: string;          // Sender address
  chainType: 'cosmos' | 'evm' | 'solana';
  paymentMethod: 'native';
}

Wait for Confirmation Options

With Confirmation (Blocking)

Waits for blockchain confirmation before returning:
const confirmed = await client.store(
  { collection: 'products', data: products },
  paymentCallback,
  true  // Waits for on-chain confirmation
);

console.log('Data confirmed at height:', confirmed.block_height);

Without Confirmation (Non-Blocking)

Returns immediately with a task ticket:
const quick = await client.store(
  { collection: 'products', data: products },
  paymentCallback,
  false  // Returns immediately
);

console.log('Task ticket:', quick.ticket_id);

// Check status later
const status = await client.getTaskStatus(quick.ticket_id);
console.log('Status:', status.status);

Payment Callback Example

const paymentCallback = async (quote) => {
  // Use your wallet or payment provider to send USDC
  const txHash = await processPayment(quote);

  return {
    txHash,
    network: quote.network,
    sender: walletAddress,
    chainType: quote.chainType,
    paymentMethod: 'native'
  };
};

// Use the callback
await client.store(
  { collection: 'data', data: [{ content: 'example' }] },
  paymentCallback,
  true
);

Error Handling

import { PaymentVerificationError, OnDBError } from '@ondb/sdk';

try {
  await client.store(
    { collection: 'data', data: [{ content: 'example' }] },
    paymentCallback,
    true
  );
} catch (error) {
  if (error instanceof PaymentVerificationError) {
    console.log('Payment verification failed');
    console.log('Transaction hash:', error.txHash);
    console.log('Error:', error.message);
  } else if (error instanceof OnDBError) {
    console.log('OnDB error:', error.code, error.statusCode);
  }
}

Next Steps