@payxor/sdk
v0.1.2
Published
TypeScript SDK for PayXor payment and entitlement system
Downloads
8
Maintainers
Readme
@payxor/sdk
TypeScript SDK for integrating PayXor payments and entitlements into your application. Works with any wallet provider (wagmi, RainbowKit, web3-react, etc.) via viem.
Table of Contents
Installation
pnpm add @payxor/sdknpm install @payxor/sdkyarn add @payxor/sdkDependencies: viem
Optional peer dependency: wagmi (for wallet client integration)
Quick Start
import { PayXorClient } from "@payxor/sdk";
import { maxUint256 } from "viem";
// Initialize client with wagmi wallet client
const client = new PayXorClient({
apiUrl: "https://api.payxor.xyz",
walletClient: yourWagmiWalletClient,
});
// 1. Get app's supported stablecoins
const stablecoins = await client.getAppSupportedStablecoins(appId, chainId);
// 2. Check balance and approval
const balance = await client.checkBalance(stablecoins[0].address, userAddress, chainId);
const needsApproval = !(await client.hasSufficientAllowance(
stablecoins[0].address,
userAddress,
requiredAmount,
chainId
));
// 3. Approve if needed
if (needsApproval) {
await client.approveToken(stablecoins[0].address, maxUint256, userAddress, chainId);
}
// 4. Get quote and pay
const { quote, sigBackend } = await client.getQuote({
appId,
productId,
chainId,
payer: userAddress,
tokenAddress: stablecoins[0].address,
});
const txHash = await client.pay(quote, sigBackend, userAddress, chainId);
// 5. Confirm transaction
await client.confirmTransaction(txHash, quote.quoteId);PayXorClient
The main client class for interacting with PayXor.
Constructor
import { PayXorClient } from "@payxor/sdk";
const client = new PayXorClient({
apiUrl: "https://api.payxor.xyz",
walletClient: yourWagmiWalletClient,
});Options:
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| apiUrl | string | "http://localhost:3000" | PayXor API URL |
| walletClient | WalletClient | — | Wagmi v2 wallet client (required for transactions) |
| transport | Transport | — | Viem transport (alternative to walletClient) |
Note: To execute on-chain transactions (
pay,approveToken), you must provide eitherwalletClientortransport.
Core Methods
getProductInfo
Fetch public product information without creating a quote. Use for UI display and approval amount checks.
const product = await client.getProductInfo(appId, productId);Parameters:
| Parameter | Type | Description |
|-----------|------|-------------|
| appId | string | App ID (hex string, e.g., "0x...") |
| productId | string | Product ID (hex string) |
Returns: Promise<ProductInfo>
interface ProductInfo {
appId: string;
productId: string;
name: string;
mode: PaymentMode;
price: string; // Price in smallest unit (wei)
duration: number | null; // Session duration in seconds
entitlementId: string | null;
}getQuote
Get a signed quote from the backend. Call this when the user is ready to purchase.
const { quote, sigBackend } = await client.getQuote({
appId: "0x...",
productId: "0x...",
chainId: 8453,
payer: "0x...",
tokenAddress: "0x...", // Optional
});Parameters:
| Parameter | Type | Description |
|-----------|------|-------------|
| appId | string | App ID (hex string) |
| productId | string | Product ID (hex string) |
| chainId | number | Target chain ID |
| payer | string | User's wallet address |
| tokenAddress | string | (Optional) Payment token address |
Returns: Promise<{ quote: Quote; sigBackend: string }>
pay
Execute the payment transaction on-chain.
const txHash = await client.pay(
quote,
sigBackend,
account,
chainId,
contractAddress, // Optional
onTransactionHash // Optional callback
);Parameters:
| Parameter | Type | Description |
|-----------|------|-------------|
| quote | Quote | Quote from getQuote() |
| sigBackend | string | Backend signature from getQuote() |
| account | Address | User's wallet address |
| chainId | number | Chain ID for the transaction |
| contractAddress | Address | (Optional) PayXor contract address |
| onTransactionHash | (hash: string) => void | (Optional) Callback when tx is submitted |
Returns: Promise<Hash> — Transaction hash
confirmTransaction
Confirm a transaction with the backend after payment. Updates quote status to "used".
await client.confirmTransaction(txHash, quoteId);Parameters:
| Parameter | Type | Description |
|-----------|------|-------------|
| txHash | Hash | Transaction hash |
| quoteId | string | Quote ID from the quote |
Returns: Promise<ConfirmTxResponse>
Entitlement Methods
isSessionActive
Check if a user has an active time-based session.
const isActive = await client.isSessionActive(
payer,
appId,
productId,
chainId,
contractAddress, // Optional
rpcUrl // Optional
);Parameters:
| Parameter | Type | Description |
|-----------|------|-------------|
| payer | Address | User's wallet address |
| appId | string | App ID (hex string) |
| productId | string | Product ID (hex string) |
| chainId | number | Chain ID |
| contractAddress | Address | (Optional) PayXor contract address |
| rpcUrl | string | (Optional) Custom RPC URL |
Returns: Promise<boolean>
isFeatureUnlocked
Check if a user has permanently unlocked a feature.
const isUnlocked = await client.isFeatureUnlocked(
payer,
appId,
entitlementId,
chainId,
contractAddress, // Optional
rpcUrl // Optional
);Parameters:
| Parameter | Type | Description |
|-----------|------|-------------|
| payer | Address | User's wallet address |
| appId | string | App ID (hex string) |
| entitlementId | string | Entitlement ID (from product or custom) |
| chainId | number | Chain ID |
| contractAddress | Address | (Optional) PayXor contract address |
| rpcUrl | string | (Optional) Custom RPC URL |
Returns: Promise<boolean>
hasPass
Check if a user holds a specific pass.
const hasUserPass = await client.hasPass(
payer,
appId,
passId,
chainId,
contractAddress, // Optional
rpcUrl // Optional
);Parameters:
| Parameter | Type | Description |
|-----------|------|-------------|
| payer | Address | User's wallet address |
| appId | string | App ID (hex string) |
| passId | string | Pass ID (hex string) |
| chainId | number | Chain ID |
| contractAddress | Address | (Optional) PayXor contract address |
| rpcUrl | string | (Optional) Custom RPC URL |
Returns: Promise<boolean>
verifyReceipt
Verify a payment receipt by checking on-chain events.
const isValid = await client.verifyReceipt(
txHash,
expectedQuoteId,
chainId,
contractAddress, // Optional
rpcUrl // Optional
);Returns: Promise<boolean>
Token Management
getAppSupportedStablecoins
Get the stablecoins configured for a specific app on a chain.
const stablecoins = await client.getAppSupportedStablecoins(appId, chainId);
// Returns app-specific tokens configured in the dashboardParameters:
| Parameter | Type | Description |
|-----------|------|-------------|
| appId | string | App ID (hex string) |
| chainId | number | Chain ID |
Returns: Promise<StablecoinConfig[]>
interface StablecoinConfig {
symbol: string; // e.g., "USDC", "USDT", "DAI"
name: string; // e.g., "USD Coin"
address: string; // Token contract address
decimals: number; // Usually 6 for USDC/USDT, 18 for DAI
}getAvailableStablecoins
Get all PayXor-supported stablecoins for a chain (not app-specific).
const allStablecoins = client.getAvailableStablecoins(chainId);Returns: StablecoinConfig[]
checkBalance
Check a user's token balance.
const balance = await client.checkBalance(
tokenAddress,
owner,
chainId,
rpcUrl // Optional
);Parameters:
| Parameter | Type | Description |
|-----------|------|-------------|
| tokenAddress | Address | ERC20 token address |
| owner | Address | Address to check |
| chainId | number | Chain ID |
| rpcUrl | string | (Optional) Custom RPC URL |
Returns: Promise<bigint> — Balance in smallest unit (wei)
checkAllowance
Check the current token allowance for the PayXor contract.
const allowance = await client.checkAllowance(
tokenAddress,
owner,
chainId,
contractAddress, // Optional
rpcUrl // Optional
);Returns: Promise<bigint> — Allowance in smallest unit (wei)
hasSufficientAllowance
Check if allowance is sufficient for a payment amount.
const hasEnough = await client.hasSufficientAllowance(
tokenAddress,
owner,
requiredAmount,
chainId,
contractAddress, // Optional
rpcUrl // Optional
);Returns: Promise<boolean>
approveToken
Approve token spending for the PayXor contract.
import { maxUint256 } from "viem";
const txHash = await client.approveToken(
tokenAddress,
maxUint256, // Or specific amount
account,
chainId,
contractAddress // Optional
);Parameters:
| Parameter | Type | Description |
|-----------|------|-------------|
| tokenAddress | Address | ERC20 token address |
| amount | bigint | Amount to approve (use maxUint256 for unlimited) |
| account | Address | User's wallet address |
| chainId | number | Chain ID |
| contractAddress | Address | (Optional) PayXor contract address |
Returns: Promise<Hash> — Transaction hash
Note: Requires
walletClientto be configured.
Utility Methods
formatTokenAmount
Format a token amount for display.
const displayAmount = client.formatTokenAmount(1000000n, 6);
// Returns: "1"Parameters:
| Parameter | Type | Description |
|-----------|------|-------------|
| amount | bigint | Amount in smallest unit |
| decimals | number | Token decimals |
Returns: string
parseTokenAmount
Parse a display amount to smallest unit.
const rawAmount = client.parseTokenAmount("100.50", 6);
// Returns: 100500000nParameters:
| Parameter | Type | Description |
|-----------|------|-------------|
| amount | string | Display amount |
| decimals | number | Token decimals |
Returns: bigint
Types
The SDK exports all types from @payxor/types:
PaymentMode
enum PaymentMode {
SESSION = 0, // Time-based access
FEATURE = 1, // Permanent unlock
RECEIPT = 2, // One-time payment proof
PASS = 3, // Pass/membership
}Quote
interface Quote {
appId: string; // bytes32 hex
productId: string; // bytes32 hex
mode: PaymentMode;
token: string; // Token address
amount: string; // Payment amount (wei)
payee: string; // Recipient address
entitlementId: string; // bytes32 hex
duration: number; // Session duration (seconds)
expiresAt: number; // Quote expiration timestamp
quoteId: string; // Unique quote identifier
payer: string; // Payer address
deadline: number; // Payment deadline timestamp
chainId: number; // Target chain ID
}QuoteRequest
interface QuoteRequest {
appId: string;
productId: string;
chainId: number;
payer: string;
tokenAddress?: string; // Optional token selection
}ProductInfo
interface ProductInfo {
appId: string;
productId: string;
name: string;
mode: PaymentMode;
price: string;
duration: number | null;
entitlementId: string | null;
}StablecoinConfig
interface StablecoinConfig {
symbol: string; // "USDC", "USDT", "DAI", "USD1"
name: string; // Full name
address: string; // Contract address
decimals: number; // Token decimals
}ChainConfig
interface ChainConfig {
chainId: number;
name: string;
rpcUrl?: string;
usdcAddress: string;
payxorContractAddress?: string;
}Supported Chains
Mainnets
| Chain | Chain ID | Supported Stablecoins | |-------|----------|----------------------| | Ethereum | 1 | USDC, USDT, DAI, USD1 | | Arbitrum | 42161 | USDC, USDT, DAI | | Base | 8453 | USDC, USDT, DAI | | Polygon | 137 | USDC, USDC.e, USDT, DAI | | Avalanche | 43114 | USDC, USDT, DAI | | Optimism | 10 | USDC, USDT, DAI | | BNB Chain | 56 | USDC, USDT, DAI, USD1 | | zkSync | 324 | USDC, USDT, DAI |
Testnets
| Chain | Chain ID | |-------|----------| | Ethereum Sepolia | 11155111 | | Base Sepolia | 84532 | | Arbitrum Sepolia | 421614 | | Polygon Mumbai | 80001 | | Optimism Sepolia | 11155420 | | Avalanche Fuji | 43113 | | BNB Chain Testnet | 97 | | zkSync Sepolia | 300 |
Standalone Functions
The SDK also exports standalone functions for use without the client:
Chain Utilities
import {
getViemChain,
getPublicClient,
getChainConfig,
} from "@payxor/sdk";
// Get viem chain configuration
const chain = getViemChain(8453); // Base
// Create a public client for reading
const publicClient = getPublicClient(8453, customRpcUrl);
// Get chain config with contract address
const config = getChainConfig(8453);Token Utilities
import {
getAvailableStablecoins,
getStablecoinsForChain,
getMockTokensForChain,
getAllTokensForChain,
checkBalance,
checkAllowance,
approveToken,
formatTokenAmount,
parseTokenAmount,
} from "@payxor/sdk";Hex Utilities
import { normalizeBytes32 } from "@payxor/sdk";
// Normalize a bytes32 value (pads to 64 hex chars)
const normalized = normalizeBytes32("0x123");
// Returns: "0x0000...0123" (64 hex chars)EIP-712 Utilities
import { getDomain, getQuoteTypedData } from "@payxor/sdk";
// Get EIP-712 domain for signing
const domain = getDomain(chainId, contractAddress);
// Get typed data for quote signing
const typedData = getQuoteTypedData(quote, chainId, contractAddress);Chain Helper Functions
import {
isTestnet,
getTestnetChains,
getMainnetChains,
getFaucetAddress,
getMockTokenAddress,
} from "@payxor/sdk";
isTestnet(11155111); // true (Sepolia)
isTestnet(8453); // false (Base mainnet)
const testnets = getTestnetChains();
const mainnets = getMainnetChains();
// For testnets with mock tokens
const faucetAddress = getFaucetAddress(11155111);
const mockUsdcAddress = getMockTokenAddress(11155111, "MockUSDC");Examples
Complete Payment Flow with wagmi
import { PayXorClient } from "@payxor/sdk";
import { maxUint256, parseUnits } from "viem";
import { useWalletClient, useAccount, useChainId } from "wagmi";
function PaymentComponent({ appId, productId }: Props) {
const { address } = useAccount();
const chainId = useChainId();
const { data: walletClient } = useWalletClient();
const handlePayment = async () => {
if (!walletClient || !address) return;
const client = new PayXorClient({
apiUrl: "https://api.payxor.xyz",
walletClient,
});
// Get product info for price
const product = await client.getProductInfo(appId, productId);
// Get supported tokens
const stablecoins = await client.getAppSupportedStablecoins(appId, chainId);
const selectedToken = stablecoins[0];
// Check balance
const balance = await client.checkBalance(
selectedToken.address,
address,
chainId
);
const requiredAmount = BigInt(product.price);
if (balance < requiredAmount) {
throw new Error("Insufficient balance");
}
// Check and handle approval
const hasApproval = await client.hasSufficientAllowance(
selectedToken.address,
address,
requiredAmount,
chainId
);
if (!hasApproval) {
const approveTx = await client.approveToken(
selectedToken.address,
maxUint256,
address,
chainId
);
// Wait for approval confirmation...
}
// Get quote and execute payment
const { quote, sigBackend } = await client.getQuote({
appId,
productId,
chainId,
payer: address,
tokenAddress: selectedToken.address,
});
const txHash = await client.pay(
quote,
sigBackend,
address,
chainId,
undefined,
(hash) => console.log("Transaction submitted:", hash)
);
// Confirm with backend
await client.confirmTransaction(txHash, quote.quoteId);
console.log("Payment complete:", txHash);
};
return <button onClick={handlePayment}>Pay</button>;
}Checking Entitlements
import { PayXorClient } from "@payxor/sdk";
const client = new PayXorClient({
apiUrl: "https://api.payxor.xyz",
});
// Check session-based access
const hasActiveSession = await client.isSessionActive(
userAddress,
appId,
productId,
chainId
);
if (hasActiveSession) {
// Grant temporary access
}
// Check permanent feature unlock
const hasPremium = await client.isFeatureUnlocked(
userAddress,
appId,
"premium-feature-id",
chainId
);
if (hasPremium) {
// Show premium content
}
// Check pass ownership
const hasVipPass = await client.hasPass(
userAddress,
appId,
"vip-pass-id",
chainId
);Server-Side Receipt Verification
import { PayXorClient } from "@payxor/sdk";
const client = new PayXorClient({
apiUrl: "https://api.payxor.xyz",
});
// Verify a payment receipt
const isValidReceipt = await client.verifyReceipt(
txHash,
expectedQuoteId,
chainId
);
if (isValidReceipt) {
// Fulfill the order
}Multi-Chain Token Selection UI
import { PayXorClient, getMainnetChains } from "@payxor/sdk";
const client = new PayXorClient({
apiUrl: "https://api.payxor.xyz",
walletClient,
});
// Get all supported chains
const chains = getMainnetChains();
// For each chain, get app's supported tokens
const tokensByChain = await Promise.all(
chains.map(async (chain) => ({
chainId: chain.chainId,
chainName: chain.name,
tokens: await client.getAppSupportedStablecoins(appId, chain.chainId),
}))
);
// Display token selector UI with chain/token optionsNotes
- Chain selection is configured during app creation in the PayXor dashboard. The SDK supports multi-chain apps by specifying
chainIdper method call. - All
bytes32values (appId, productId, entitlementId) should be hex strings. UsenormalizeBytes32()to ensure proper formatting. - For React applications, consider using
@payxor/reactwhich provides hooks and components built on top of this SDK.
