> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ondb.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Write Payments

> Automatic payment handling for write operations

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

```typescript theme={null}
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:

```typescript theme={null}
interface X402Quote {
  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)
  allOptions: X402PaymentRequirement[]; // All available payment options
}
```

## Callback Return Value

Your callback must return a payment result:

### Payment Result

```typescript theme={null}
interface X402PaymentResult {
  txHash: string;          // Transaction hash from blockchain
  network: string;         // Network identifier
  sender: string;          // Sender address
  chainType: 'cosmos' | 'evm' | 'solana';
  paymentMethod: PaymentMethod;
}
```

## Wait for Confirmation Options

### With Confirmation (Blocking)

Waits for blockchain confirmation before returning:

```typescript theme={null}
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:

```typescript theme={null}
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

```typescript theme={null}
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

```typescript theme={null}
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

<CardGroup cols={2}>
  <Card title="PriceIndex" icon="tags" href="/payments/price-index">
    Value-based payment model
  </Card>

  <Card title="Paid Reads" icon="book" href="/payments/paid-reads">
    HTTP 402 for read operations
  </Card>
</CardGroup>
