px402 - Private x402 payments using zero-knowledge proofs. Pay privately without revealing your identity or transaction history.
- Full Privacy: Each payment uses a fresh burner wallet, unlinkable to previous payments
- x402 Compatible: Works seamlessly with any x402-enabled API
- Cross-Chain: Deposit on one chain, spend on another (Base <-> Polygon)
- ZK Proofs: All transactions validated with Groth16 zero-knowledge proofs
- Note Encryption: AES-256-GCM encryption for secure note storage
npm install @prxvt/sdkimport { PrivacySDK } from '@prxvt/sdk';
const sdk = new PrivacySDK({
chain: 'base', // or 'polygon'
});// Deposit 10 USDC -> Get private note
const note = await sdk.deposit(10, '0xYourPrivateKey');
// The note is your private balance - save it securely!
console.log('Note created:', JSON.stringify(note));// Load your note
sdk.setNote(note);
// Wrap fetch with privacy
const privateFetch = sdk.wrapFetch(fetch);
// Make px402 payment - COMPLETELY PRIVATE!
const response = await privateFetch('https://api.example.com/x402/endpoint', {
method: 'POST',
body: JSON.stringify({ message: 'Hello!' }),
});
// Get updated note (old note is spent, this is the change!)
const updatedNote = sdk.getUpdatedNote();import { encryptNote, decryptNote } from '@prxvt/sdk';
// Encrypt note with password
const encrypted = await encryptNote(note, 'my-secret-password');
localStorage.setItem('encrypted-note', encrypted);
// Later: decrypt to use
const decrypted = await decryptNote(encrypted, 'my-secret-password');import {
PrivacySDK,
encryptNote,
decryptNote,
getNoteBalance,
logger
} from '@prxvt/sdk';
async function main() {
// Enable debug logging (optional)
logger.setLevel('debug');
// 1. Setup SDK
const sdk = new PrivacySDK({ chain: 'base' });
// 2. Deposit USDC
const note = await sdk.deposit(10, '0xYourPrivateKey');
console.log('Deposited:', getNoteBalance(note), 'USDC');
// 3. Encrypt and save
const encrypted = await encryptNote(note, 'password123');
localStorage.setItem('note', encrypted);
// 4. Make payments
sdk.setNote(note);
const privateFetch = sdk.wrapFetch(fetch);
const response = await privateFetch('https://api.example.com/x402');
console.log('Payment successful!');
// 5. Save updated note
const updated = sdk.getUpdatedNote();
const newEncrypted = await encryptNote(updated, 'password123');
localStorage.setItem('note', newEncrypted);
console.log('Remaining:', getNoteBalance(updated), 'USDC');
}The main SDK class for privacy payments.
new PrivacySDK(config: PrivacySDKConfig)Config Options:
| Option | Type | Default | Description |
|---|---|---|---|
chain |
'base' | 'polygon' |
'base' |
Blockchain to use |
bundlerUrl |
string |
prxvt proxy | Custom bundler URL |
bundlerApiKey |
string |
- | Pimlico API key (optional) |
rpcUrl |
string |
public RPC | Custom RPC URL |
Deposit USDC to create a private note.
const note = await sdk.deposit(50, '0xYourPrivateKey');Fast deposit using ERC-3009 transferWithAuthorization (gasless).
const note = await sdk.depositFast(50, '0xYourPrivateKey');Make a direct payment to a recipient.
const result = await sdk.makePayment(note, '0x742d35Cc...', 1.5);
console.log('TX:', result.txHash);
console.log('Change note:', result.note);Wrap fetch to automatically handle x402 payments.
const privateFetch = sdk.wrapFetch(fetch);
const response = await privateFetch('https://api.example.com/x402');Load a saved note into the SDK.
sdk.setNote(savedNote);Get the current note state after payments.
const updatedNote = sdk.getUpdatedNote();Encrypt a note with AES-256-GCM.
const encrypted = await encryptNote(note, 'my-password');
// encrypted is a base64 string safe for storageDecrypt an encrypted note.
const note = await decryptNote(encrypted, 'my-password');Check if a string is an encrypted note.
if (isEncryptedNote(stored)) {
const note = await decryptNote(stored, password);
}Get balance from a note in USDC.
const balance = getNoteBalance(note); // e.g., 10.5Check if note has sufficient balance.
if (!hasEnoughBalance(note, 5)) {
console.log('Insufficient balance');
}Format micro USDC to display string.
formatUSDCAmount(1500000); // "1.50"Parse USDC to micro USDC.
parseUSDCAmount(1.5); // 1500000Check if payment is cross-chain.
isCrossChain('base', 'polygon'); // true
isCrossChain('base', 'base'); // falseGet LayerZero endpoint ID for a chain.
getChainEid('base'); // 30184
getChainEid('polygon'); // 30109Configure logging level.
import { logger } from '@prxvt/sdk';
logger.setLevel('debug'); // 'none' | 'error' | 'warn' | 'info' | 'debug'import {
PrivacySDKError,
InsufficientBalanceError,
InvalidNoteError,
DecryptionError,
MerkleProofError,
ProofGenerationError,
BundlerError,
NetworkError,
PaymentRequiredError,
TransactionError,
NullifierSpentError,
} from '@prxvt/sdk';interface Note {
version: string;
commitments: NoteCommitment[];
}
interface NoteCommitment {
secret: string; // Random secret (field element)
nullifier: string; // Random nullifier (field element)
amount: number; // Amount in micro USDC (6 decimals)
depositChain: string; // Chain where commitment was created
}interface PaymentResult {
note: Note; // Updated note with change
txHash: string; // Transaction hash
nullifierHash: string; // Nullifier hash (for tracking)
burnerAddress?: string; // Burner wallet address
burnerPrivateKey?: string; // Burner private key (for x402)
}interface PrivacySDKConfig {
chain?: 'base' | 'polygon';
bundlerUrl?: string;
bundlerApiKey?: string;
rpcUrl?: string;
attestorUrl?: string;
circuitWasmPath?: string;
circuitZkeyPath?: string;
}- Generate Burner Wallet: SDK creates ephemeral EOA
- ZK Proof Generation: Proves you have a valid note without revealing it
- Withdraw to Burner: UserOperation withdraws USDC to burner (paymaster sponsors gas!)
- Sign x402 Payment: Burner signs EIP-3009 authorization (no gas needed!)
- Make API Call: Payment is sent to merchant
- Create Change Note: Remaining balance becomes a new note
- Discard Burner: Burner wallet is thrown away
Result: Completely private payment, no gas fees, untraceable!
Deposit on Base, pay on Polygon (or vice versa):
// Deposit on Base
const sdk = new PrivacySDK({ chain: 'base' });
const note = await sdk.deposit(10, privateKey);
// Pay on Polygon
const polygonSdk = new PrivacySDK({ chain: 'polygon' });
polygonSdk.setNote(note); // Note from Base works on Polygon!
const result = await polygonSdk.makePayment(note, recipient, 1);Cross-chain payments use an attestor service that verifies the nullifier hasn't been spent on the origin chain.
For browser environments, load Poseidon hash and snarkjs:
<script src="https://cdn.prxvt.io/poseidon-browser.js"></script>
<script src="https://cdn.jsdelivr.net/npm/snarkjs@0.7.0/build/snarkjs.min.js"></script>
<script type="module">
import { PrivacySDK } from '@prxvt/sdk';
const sdk = new PrivacySDK({ chain: 'base' });
// ... use SDK
</script>For Node.js, install circomlibjs:
npm install circomlibjs snarkjsimport { PrivacySDK } from '@prxvt/sdk';
import { buildPoseidon } from 'circomlibjs';
import * as snarkjs from 'snarkjs';
// Setup global Poseidon (required for Node.js)
const poseidon = await buildPoseidon();
globalThis.window = {
poseidonHash3: (a, b, c) => Promise.resolve(
poseidon.F.toString(poseidon([BigInt(a), BigInt(b), BigInt(c)]))
),
poseidonHash2: (a, b) => Promise.resolve(
poseidon.F.toString(poseidon([BigInt(a), BigInt(b)]))
),
poseidonHash: (a) => Promise.resolve(
poseidon.F.toString(poseidon([BigInt(a)]))
),
snarkjs,
};
const sdk = new PrivacySDK({ chain: 'base' });- Notes are spent after each payment: You CANNOT reuse the same note
- Always save the updated note: After each payment, get and save the new note
- UTXO model: Each payment consumes the old commitment and creates a new change commitment
- Unlinkable payments: Each payment uses a fresh burner wallet
- No transaction history: Payments cannot be linked together
- Zero-knowledge proofs: Your identity and note are never revealed
- Cross-chain privacy: Deposit and withdraw on different chains
- Never share your note data: Notes contain secrets that prove ownership
- Use note encryption: Always encrypt notes before storage
- HTTPS only: Always use HTTPS for API calls
- Trusted RPCs: Use trusted RPC providers
| Chain | Network | USDC Contract | LayerZero EID |
|---|---|---|---|
| Base | Mainnet | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 |
30184 |
| Polygon | Mainnet | 0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359 |
30109 |
MIT
- GitHub: github.com/prxvt/sdk
- npm: npmjs.com/package/@prxvt/sdk
- Issues: Report bugs