@opengrant/sdk
v1.1.0
Published
OpenGrant SDK - Pay for APIs with USDC micropayments using the x402 protocol
Maintainers
Readme
@opengrant/sdk
The official JavaScript/TypeScript SDK for OpenGrant — a platform for monetizing APIs with USDC micropayments using the x402 protocol.
Features
- Pay-per-call APIs — Call any registered API and pay only for what you use in USDC
- Multi-chain — Base, Arbitrum, Linea, Polygon, World Chain (mainnet & testnet)
- Auto-retry — Exponential backoff with configurable retries
- OSS Donations — Donate USDC directly to GitHub repos via on-chain escrow
- Auto-tip — Automatically tip linked open source projects on every paid API call
- TypeScript-first — Full type safety, dual CJS/ESM output
Installation
npm install @opengrant/sdk
# or
pnpm add @opengrant/sdk
# or
yarn add @opengrant/sdkRequirements: Node.js >= 18 (uses native fetch)
Quick Start
import { OpenGrant } from '@opengrant/sdk';
const client = new OpenGrant({
apiKey: 'og_live_xxx', // Your OpenGrant API key
privateKey: '0x...', // Wallet private key for signing payments
});
// Call a paid API endpoint
const response = await client.call('tailwind-ai', 'POST', '/v1/generate', {
body: { prompt: 'button primary' },
});
console.log(response.data);
// response.payment → { amount: "1000", txHash: "0x..." }Configuration
const client = new OpenGrant({
// Required
apiKey: 'og_live_xxx',
// Wallet (one of these required for paid calls)
privateKey: '0x...', // Private key string
walletClient: walletClient, // Or a viem WalletClient
// Optional
baseUrl: 'https://api.opengrant.dev', // Default
chainId: 84532, // Base Sepolia (default). Use 8453 for Base mainnet
rpcUrl: 'https://...', // Override default RPC for the chain
timeout: 30000, // Request timeout ms (default: 30000)
autoRetry: true, // Auto-retry on network errors (default: true)
maxRetries: 3, // Max retry attempts (default: 3)
debug: false, // Log debug info (default: false)
// Auto-tipping (donate a % of each payment to linked OSS projects)
tipPercentage: 5, // Tip 5% of each payment to the API's linked GitHub repo
onTip: (result) => {
if (result.success) {
console.log(`Tipped ${result.amount} USDC to ${result.repo}`);
}
},
});API Calls
// GET request
const { data } = await client.get('weather-api', '/v1/forecast', {
params: { city: 'Istanbul' },
});
// POST request
const { data } = await client.post('image-gen', '/v1/generate', {
prompt: 'a cat wearing a hat',
size: '1024x1024',
});
// Full call with all options
const response = await client.call('my-api', 'POST', '/v1/endpoint', {
body: { key: 'value' },
params: { filter: 'active' },
headers: { 'X-Custom': 'header' },
timeout: 60000, // Override timeout for this request
maxPrice: 5000n, // Reject if price > 5000 USDC wei ($0.005)
});Supported Chains
| Chain | Chain ID | USDC Address |
|-------|----------|-------------|
| Base | 8453 | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 |
| Ethereum | 1 | 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 |
| Arbitrum One | 42161 | 0xaf88d065e77c8cC2239327C5EDb3A432268e5831 |
| Linea | 59144 | 0xFEce4462d57bD51A6A552365a011b95f0E16d9B7 |
| Polygon PoS | 137 | 0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359 |
| World Chain | 480 | 0x79A02482A880bCe3F13E09da970dC34dB4cD24D1 |
| Base Sepolia | 84532 | 0x036CbD53842c5426634e7929541eC2318f3dCF7e (default) |
Wallet Balance
const balance = await client.getBalance();
// { usdc: "10000000", usdcFormatted: "10.00", eth: "1000000000000000" }Usage Statistics
const stats = await client.getUsage('30d'); // '7d' | '30d' | '90d'
// { totalCalls: 150, totalSpent: "15000000", byApi: [...], daily: [...] }OSS Donations
Donate USDC directly to any GitHub repository. Funds are held in an on-chain escrow and released when the repo owner verifies ownership.
// Donate to a single repo
const result = await client.donate({
repoOwner: 'facebook',
repoName: 'react',
amount: '10.00', // USDC (human-readable)
redistributeOnTimeout: false, // If unclaimed after 1 year, redistribute (default: false)
});
// result → { txHash: '0x...', repoHash: '0x...', amount: '10.00', chainId: 8453 }
// Donate to multiple repos in one transaction
const result = await client.batchDonate({
donations: [
{ repoOwner: 'facebook', repoName: 'react', amount: '5.00' },
{ repoOwner: 'vercel', repoName: 'next.js', amount: '5.00' },
],
});
// result → { txHash: '0x...', repoCount: 2, totalAmount: '10.00', chainId: 8453 }Claiming Escrow Funds
If you're a repo owner, you can claim accumulated donations:
const result = await client.claim({
repoOwner: 'your-github-username',
repoName: 'your-repo',
githubToken: 'ghp_xxx', // GitHub PAT to prove ownership
});
// result → { txHash: '0x...', repoHash: '0x...', chainId: 8453 }Repository Funding Info
const info = await client.getRepoFundInfo('facebook', 'react');
// { id, owner, name, totalFunded, donorCount, claimStatus, repoHash }Error Handling
import {
OpenGrantError,
InsufficientBalanceError,
PaymentRequiredError,
UnauthorizedError,
APINotFoundError,
RateLimitError,
TimeoutError,
NetworkError,
} from '@opengrant/sdk';
try {
const response = await client.call('my-api', 'GET', '/v1/data');
} catch (err) {
if (err instanceof InsufficientBalanceError) {
console.log('Not enough USDC. Fund your wallet first.');
} else if (err instanceof UnauthorizedError) {
console.log('Invalid API key.');
} else if (err instanceof RateLimitError) {
console.log(`Rate limited. Retry after ${err.retryAfter}s`);
} else if (err instanceof OpenGrantError) {
console.log(`Error ${err.code}: ${err.message}`);
}
}Auto-Tipping OSS
Automatically donate a percentage of every payment to the API's linked GitHub repository:
const client = new OpenGrant({
apiKey: 'og_live_xxx',
privateKey: '0x...',
tipPercentage: 10, // Tip 10% of every paid call
onTip: ({ success, repo, amount, error }) => {
if (success) console.log(`Tipped $${amount} to ${repo}`);
else console.warn(`Tip failed: ${error}`);
},
});
// Every paid call now automatically donates 10% to the API's linked OSS project
await client.call('react-docs-api', 'GET', '/v1/search');Multi-Chain Example
// Base Sepolia (default — testnet)
const testClient = new OpenGrant({ apiKey, privateKey });
// Base (mainnet)
const baseClient = new OpenGrant({ apiKey, privateKey, chainId: 8453 });
// Arbitrum
const arbClient = new OpenGrant({ apiKey, privateKey, chainId: 42161 });TypeScript Types
import type {
OpenGrantConfig,
APIResponse,
APIInfo,
UsageStats,
WalletBalance,
DonationConfig,
DonationResult,
BatchDonationConfig,
BatchDonationResult,
ClaimConfig,
ClaimResult,
RepoFundInfo,
Donation,
TipResult,
CallOptions,
PaymentDetails,
} from '@opengrant/sdk';License
MIT — see LICENSE
