PaymentRequiredError containing a payment quote. You then pay and re-query using executeWithPayment().
How It Works
1. App executes query via queryBuilder().execute()
|
2. Server determines payment is required
|
3. SDK throws PaymentRequiredError with quote
|
4. App processes payment using quote details
|
5. App re-queries with executeWithPayment(quoteId, txHash)
|
6. Server verifies payment and returns data
Basic Example
import { createClient, PaymentRequiredError } from '@ondb/sdk';
try {
const result = await client.queryBuilder()
.collection('premium_data')
.selectAll()
.execute();
// Query succeeded without payment
console.log('Records:', result.records);
} catch (error) {
if (error instanceof PaymentRequiredError) {
const paymentInfo = error.paymentRequired;
console.log('Payment required!');
console.log('Error:', paymentInfo.error);
console.log('Payment options:', paymentInfo.accepts.length);
// Each option in accepts[] contains: network, maxAmountRequired, payTo, tokenSymbol, etc.
}
}
Pay and Re-Query
After catchingPaymentRequiredError, process the payment and use executeWithPayment() to retry:
import { createClient, PaymentRequiredError } from '@ondb/sdk';
async function queryWithPayment() {
const query = client.queryBuilder()
.collection('premium_data')
.whereField('category').equals('exclusive')
.selectFields(['title', 'content', 'price'])
.limit(10);
try {
// Try the query first
const result = await query.execute();
return result.records;
} catch (error) {
if (error instanceof PaymentRequiredError) {
const requirement = error.paymentRequired.accepts[0];
console.log(`Payment required: ${requirement.maxAmountRequired} ${requirement.tokenSymbol}`);
// Process payment using the requirement details
const txHash = await processPayment(requirement);
// Re-query with payment proof
const paidResult = await query.executeWithPayment(
requirement.extra?.quoteId || '',
txHash,
requirement.network
);
return paidResult.records;
}
throw error;
}
}
executeWithPayment
TheexecuteWithPayment() method on QueryBuilder retries a query with payment proof:
const result = await client.queryBuilder()
.collection('premium_data')
.selectAll()
.executeWithPayment<MyType>(
quoteId, // From PaymentRequiredError.quote.quoteId
txHash, // Transaction hash from your payment
network // Optional: network identifier
);
Parameters
| Parameter | Type | Description |
|---|---|---|
quoteId | string | Quote ID from the PaymentRequiredError |
paymentProof | string | Transaction hash from the payment |
network | string | Optional network identifier |
Return Value
ReturnsQueryResponse<T> with the same structure as execute().
Error Types
import {
PaymentRequiredError,
PaymentVerificationError,
OnDBError
} from '@ondb/sdk';
try {
const result = await client.queryBuilder()
.collection('paid_content')
.selectAll()
.execute();
} catch (error) {
if (error instanceof PaymentRequiredError) {
// Payment is required - paymentRequired has all details
const paymentInfo = error.paymentRequired;
console.log('Error:', paymentInfo.error);
const requirement = paymentInfo.accepts[0];
console.log('Cost:', requirement.maxAmountRequired, requirement.tokenSymbol);
console.log('Pay to:', requirement.payTo);
} else if (error instanceof PaymentVerificationError) {
// Payment was made but verification failed
console.log('Verification failed for tx:', error.txHash);
} else if (error instanceof OnDBError) {
console.log('OnDB error:', error.code, error.statusCode);
}
}
Type-Safe Payment Handling
import { PaymentRequiredError, QueryResponse } from '@ondb/sdk';
interface PremiumContent {
title: string;
content: string;
price: number;
}
async function fetchPremiumContent(): Promise<PremiumContent[] | null> {
const query = client.queryBuilder()
.collection('premium')
.selectAll();
try {
const result = await query.execute<PremiumContent>();
return result.records;
} catch (error) {
if (error instanceof PaymentRequiredError) {
const requirement = error.paymentRequired.accepts[0];
const txHash = await processPayment(requirement);
const paidResult = await query.executeWithPayment<PremiumContent>(
requirement.extra?.quoteId || '',
txHash,
requirement.network
);
return paidResult.records;
}
throw error;
}
}
Use Cases
| Use Case | Description |
|---|---|
| Premium Content | Charge for access to exclusive data |
| API Monetization | Monetize data access with per-query pricing |
| Cost Recovery | Recover computational costs for expensive queries |
| Tiered Access | Free basic queries, paid for detailed fields |
| Data Marketplace | Build marketplaces where data providers set prices |
Next Steps
Cost Estimation
Estimate operation costs
Write Payments
Write operation payments