
Product
Introducing Webhook Events for Alert Changes
Add real-time Socket webhook events to your workflows to automatically receive software supply chain alert changes in real time.
@zkp2p/client-sdk
Advanced tools
Browser-first TypeScript SDK for ZKP2P with React hooks, unified authentication, and peerauth extension integration
Browser-first TypeScript SDK for integrating ZKP2P into web applications.
This SDK consumes contract addresses, ABIs, and payment method catalogs directly from @zkp2p/contracts-v2 with type safety.
@zkp2p/contracts-v2/addresses/<network>@zkp2p/contracts-v2/abis/<network>/<Contract>.json@zkp2p/contracts-v2/paymentMethods/<network>Helpers exported by the SDK:
import { getContracts, getPaymentMethodsCatalog } from '@zkp2p/client-sdk';
// Resolve addresses/ABIs per chain/env
const { addresses, abis } = getContracts(8453, 'production');
// addresses.Escrow, addresses.Orchestrator, ...
// abis.escrow, abis.orchestrator, ...
// Resolve payment methods catalog with hashes and optional allowed currencies
const methods = getPaymentMethodsCatalog(8453, 'production');
const wise = methods['wise'];
console.log(wise.paymentMethodHash);
Networks available:
base (chainId 8453)base_staging (used when runtimeEnv: 'staging')base_sepolia (chainId 84532)@zkp2p/client-sdk/extension.npm install @zkp2p/client-sdk viem
# or
yarn add @zkp2p/client-sdk viem
# or
pnpm add @zkp2p/client-sdk viem
import { Zkp2pClient } from '@zkp2p/client-sdk';
import { createWalletClient, custom } from 'viem';
import { base } from 'viem/chains';
// Create viem wallet client
const walletClient = createWalletClient({
chain: base,
transport: custom(window.ethereum),
});
// Initialize ZKP2P client (Production)
const client = new Zkp2pClient({ walletClient, chainId: base.id, runtimeEnv: 'production' });
// Get active deposits with payment methods/currencies and latest intents
const deposits = await client.getDepositsWithRelations({ status: 'ACTIVE', acceptingIntents: true }, { limit: 50 }, { includeIntents: true });
// Request quotes; when escrowAddresses is omitted, the client defaults to its native escrow
const quote = await client.getQuote({
paymentPlatforms: ['venmo', 'cashapp'],
fiatCurrency: 'USD',
user: '0xUser',
recipient: '0xRecipient',
destinationChainId: 8453,
destinationToken: '0xUSDC',
amount: '100',
// Optional: restrict to specific escrows
// escrowAddresses: ['0xEscrow1', '0xEscrow2']
});
These helpers call the on-chain ProtocolViewer contract when available (Base Sepolia/Staging).
const pvDeposit = await client.getPvDepositById('1');
const pvDeposits = await client.getPvAccountDeposits('0xOwner');
const pvIntents = await client.getPvAccountIntents('0xOwner');
const pvIntent = await client.getPvIntent('0xIntentHash');
import { getPaymentMethodsCatalog } from '@zkp2p/client-sdk';
const methods = getPaymentMethodsCatalog(8453, 'production');
// Use in signalIntent inputs
const hash = methods['wise'].paymentMethodHash;
// Provide baseApiUrl + apiKey (or authorizationToken) to auto-fetch gating signature
const client = new Zkp2pClient({ walletClient, chainId: base.id, baseApiUrl: 'https://api.zkp2p.xyz', apiKey: 'YOUR_API_KEY' });
await client.signalIntent({
depositId: 1n,
amount: 1000000n,
toAddress: '0xRecipient',
processorName: 'wise',
fiatCurrencyCode: 'USD',
conversionRate: 123n,
payeeDetails: '0xPayeeHash',
});
// If you already have the signature and expiration, pass them directly
// gatingServiceSignature: '0x…',
// signatureExpiration: 172800000n,
Breaking (vX): fulfillIntent now only needs intentHash and a proof. The SDK derives the rest (amount, fiatCurrency, conversionRate, payeeDetails, payment method) from the intent via the indexer.
// `proof` can be an object from the extension or a stringified JSON
const txHash = await client.fulfillIntent({
intentHash: '0xIntentHash',
proof,
// Optional: timestampBufferMs (default 5 minutes = 300000)
// Optional: attestationServiceUrl, verifyingContract, postIntentHookData, txOverrides
// Optional callbacks: onAttestationStart, onTxSent, onTxMined
});
Notes:
paymentMethodHash to the Attestation Service endpoint; no platform input is required.// Toggle accepting intents
await client.setAcceptingIntents({ depositId: 1n, accepting: false });
// Update allowed intent amount range
await client.setIntentRange({ depositId: 1n, min: 100000n, max: 10000000n });
// Update min conversion rate for a currency under a payment method
await client.setCurrencyMinRate({
depositId: 1n,
paymentMethod: '0x…',
fiatCurrency: '0x…',
minConversionRate: 1000000n,
});
// Manage funds
await client.addFunds({ depositId: 1n, amount: 5_000_000n });
await client.removeFunds({ depositId: 1n, amount: 1_000_000n });
await client.withdrawDeposit({ depositId: 1n });
Use the optional extension entry for browser proof generation. The hook wraps window.postMessage and the ExtensionProofFlow class:
import { usePeerauthProofFlow } from '@zkp2p/client-sdk/extension';
function ProofButton({ platform, intentHash, originalIndex }: { platform: string; intentHash: string; originalIndex: number }) {
const { start, status, progress, proofs, error, reset } = usePeerauthProofFlow({ requiredProofs: 1, timeoutMs: 60000 });
const onClick = async () => {
try {
await start(platform as any, intentHash, originalIndex);
// proofs[0] contains the Reclaim proof object ready to be encoded
} catch (e) {
console.error(e);
}
};
return (
<div>
<button onClick={onClick} disabled={status === 'polling_proof' || status === 'waiting_proof_id'}>Generate Proof</button>
{status !== 'idle' && <div>status: {status} (stage: {progress?.stage})</div>}
{error && <div>Error: {String(error.message)}</div>}
</div>
);
}
This hook is only available in the browser. For SSR, conditionally render components that import from @zkp2p/client-sdk/extension.
You can resolve bytes32 values conveniently:
import { resolvePaymentMethodHash, resolveFiatCurrencyBytes32, resolvePaymentMethodNameFromHash, getCurrencyInfoFromHash } from '@zkp2p/client-sdk';
import { getPaymentMethodsCatalog } from '@zkp2p/client-sdk';
// Staging uses mainnet with a separate contract set
const paymentMethod = resolvePaymentMethodHash('wise', { env: 'staging', network: 'base' });
const usd = resolveFiatCurrencyBytes32('USD');
// Reverse lookups for dashboards/explorers
const catalog = getPaymentMethodsCatalog(8453, 'production');
const name = resolvePaymentMethodNameFromHash(paymentMethod, catalog); // 'wise'
const usdInfo = getCurrencyInfoFromHash(usd); // { currencyCode: 'USD', currencySymbol: '$', ... }
See examples/node-scripts:
create-deposit.ts (v3)create-deposit-v3.ts (struct demonstration)signal-intent-orchestrator.tsfulfill-intent-orchestrator.tsrelease-funds-to-payer.tscancel-intent.tsAdditional example:
inspect-client.ts — prints resolved addresses and indexer URL for quick sanity checksRun with ts-node or compile locally; provide env vars (see headers of each file).
The extension entry is browser-only. When server-rendering, guard access and use dynamic import:
// Safe access pattern
const isBrowser = typeof window !== 'undefined';
if (isBrowser) {
const { ExtensionMetadataFlow } = await import('@zkp2p/client-sdk/extension');
// use ExtensionMetadataFlow
}
In React frameworks (Next.js), prefer dynamic(() => import('@zkp2p/client-sdk/extension'), { ssr: false }) for UI components that rely on the extension.
apiKey (or authorizationToken) at runtime via app config.event.origin. Only listen to trusted origins and propagate data defensively.validatePayeeDetails before registering or signaling intents.npm run lint (ESLint with TypeScript + import and Prettier compatibility)npm run format / npm run format:write (Prettier)npm run typecheck (strict TS)npm run test (Vitest unit tests)npm run build (tsup ESM/CJS + d.ts)cd packages/client-sdk
npm ci
npm run build
npm run test
npm run lint && npm run format
We follow Conventional Commits for releases. See PUBLISHING.md for package publishing guidance.
Client supports both x-api-key and optional Authorization: Bearer <token> for hybrid auth.
const client = new Zkp2pClient({
walletClient,
apiKey: 'YOUR_API_KEY',
authorizationToken: 'JWT_OR_OAUTH_TOKEN',
chainId: 8453,
});
IndexerDeposit, IndexerDepositWithRelations, and IndexerIntent.Use the minimal hooks from @zkp2p/client-sdk/react with your existing Zkp2pClient instance.
import { Zkp2pClient } from '@zkp2p/client-sdk';
import { useSignalIntent, useCreateDeposit, useFulfillIntent } from '@zkp2p/client-sdk/react';
export function SignalButton({ client, params }: { client: Zkp2pClient; params: Parameters<Zkp2pClient['signalIntent']>[0] }) {
const { signalIntent, isLoading, error, txHash } = useSignalIntent({ client, onSuccess: (hash) => console.log('Signaled:', hash) });
return <button disabled={isLoading} onClick={() => signalIntent(params)}>Signal Intent</button>;
}
export function CreateDepositButton({ client, params }: { client: Zkp2pClient; params: Parameters<Zkp2pClient['createDeposit']>[0] }) {
const { createDeposit, isLoading, error, txHash } = useCreateDeposit({ client });
return <button disabled={isLoading} onClick={() => createDeposit(params)}>Create Deposit</button>;
}
export function FulfillButton({ client, params }: { client: Zkp2pClient; params: Parameters<Zkp2pClient['fulfillIntent']>[0] }) {
const { fulfillIntent, isLoading, error, txHash } = useFulfillIntent({ client });
return <button disabled={isLoading} onClick={() => fulfillIntent(params)}>Fulfill Intent</button>;
}
getDeposits(filter?, pagination?)getDepositsWithRelations(filter?, pagination?, { includeIntents?, intentStatuses? })getDepositById(id, { includeIntents?, intentStatuses? })getIntentsForDeposits(ids, statuses?)getOwnerIntents(owner, statuses?)createDeposit({ token, amount, intentAmountRange, processorNames, depositData, conversionRates, ... })signalIntent({ depositId, amount, toAddress, processorName, payeeDetails, fiatCurrencyCode, conversionRate, ... })fulfillIntent({ intentHash, zkTlsProof, platform, actionType, ... })cancelIntent({ intentHash })import { Zkp2pClient } from '@zkp2p/client-sdk';
import { createWalletClient, http } from 'viem';
import { hardhat } from 'viem/chains';
const testClient = new Zkp2pClient({
walletClient: createWalletClient({
chain: hardhat,
transport: http(),
}),
chainId: hardhat.id,
});
cd packages/client-sdk
npm ci
npm run build
npm run test
npm run lint && npm run format
We follow Conventional Commits for releases. See PUBLISHING.md for package publishing guidance.
Client supports both x-api-key and optional Authorization: Bearer <token> for hybrid auth.
const client = new Zkp2pClient({
walletClient,
apiKey: 'YOUR_API_KEY',
authorizationToken: 'JWT_OR_OAUTH_TOKEN',
chainId: 8453,
});
IndexerDeposit, IndexerDepositWithRelations, and IndexerIntent.import React, { useState } from 'react';
import {
useZkp2pClient,
useQuote,
useSignalIntent,
useCreateDeposit,
useFulfillIntent,
useExtensionOrchestrator,
PLATFORM_METADATA,
Currency,
type PaymentPlatformType
} from '@zkp2p/client-sdk';
function ZKP2PApp() {
const [selectedPlatform, setSelectedPlatform] = useState<PaymentPlatformType>('venmo');
// Initialize client with hooks
const { client, isInitialized, error: clientError } = useZkp2pClient({
walletClient: window.walletClient, // Your viem wallet client
apiKey: process.env.REACT_APP_ZKP2P_API_KEY!,
chainId: 8453, // Base mainnet
});
// Quote management
const {
fetchQuote,
quote,
isLoading: quoteLoading,
error: quoteError
} = useQuote({
client,
onSuccess: (quote) => {
console.log('Quote received:', quote);
},
onError: (error) => {
console.error('Quote error:', error);
},
});
// Signal intent hook
const {
signalIntent,
response: intentResponse,
isLoading: intentLoading
} = useSignalIntent({
client,
onSuccess: (response) => {
console.log('Intent signaled:', response);
},
});
// Extension orchestrator for proof generation
const {
authenticate,
payments,
proofs,
proofBytes,
isAuthenticating,
isGeneratingProof,
progress,
error: proofError,
} = useExtensionOrchestrator({
debug: true,
autoDispose: true,
});
// Fulfill intent with proof
const {
fulfillIntent,
txHash,
isLoading: fulfillLoading
} = useFulfillIntent({
client,
onSuccess: (hash) => {
console.log('Intent fulfilled! Transaction:', hash);
},
});
// Handle authentication and proof generation
const handleAuthenticateAndProve = async () => {
if (!intentResponse?.intentHash) {
alert('Please signal an intent first');
return;
}
const result = await authenticate(selectedPlatform, {
autoGenerateProof: {
intentHashHex: intentResponse.intentHash,
itemIndex: 0,
onProofGenerated: (proofs) => {
console.log('Proofs generated:', proofs);
},
onProofError: (error) => {
console.error('Proof generation failed:', error);
},
onProgress: (progress) => {
console.log('Progress:', progress);
},
},
onPaymentsReceived: (payments) => {
console.log('Payments received:', payments);
},
});
// Automatically fulfill intent with generated proofs
if (result?.proofs && intentResponse?.intentHash) {
await fulfillIntent({
intentHash: intentResponse.intentHash,
paymentProofs: result.proofs.map(proof => ({ proof })),
});
}
};
// Handle quote fetching
const handleFetchQuote = async () => {
await fetchQuote({
paymentPlatforms: [selectedPlatform],
fiatCurrency: Currency.USD,
user: '0xYourAddress',
recipient: '0xRecipientAddress',
destinationChainId: 8453,
destinationToken: client?.getUsdcAddress() || '0x',
amount: '100',
});
};
if (!isInitialized) {
return <div>Initializing ZKP2P client...</div>;
}
if (clientError) {
return <div>Error initializing client: {clientError.message}</div>;
}
return (
<div className="zkp2p-app">
<h1>ZKP2P Integration</h1>
{/* Platform Selection */}
<div className="platform-selector">
<h2>Select Payment Platform</h2>
{Object.entries(PLATFORM_METADATA).map(([key, platform]) => (
<button
key={key}
onClick={() => setSelectedPlatform(key as PaymentPlatformType)}
className={selectedPlatform === key ? 'selected' : ''}
>
{platform.logo} {platform.displayName}
</button>
))}
</div>
{/* Quote Section */}
<div className="quote-section">
<h2>Get Quote</h2>
<button onClick={handleFetchQuote} disabled={quoteLoading}>
{quoteLoading ? 'Fetching...' : 'Fetch Quote'}
</button>
{quote && (
<div className="quote-display">
<h3>Quote Details:</h3>
<pre>{JSON.stringify(quote, null, 2)}</pre>
</div>
)}
{quoteError && <div className="error">Error: {quoteError.message}</div>}
</div>
{/* Authentication & Proof Generation */}
<div className="proof-section">
<h2>Generate Payment Proof</h2>
<button
onClick={handleAuthenticateAndProve}
disabled={isAuthenticating || isGeneratingProof}
>
{isAuthenticating
? 'Authenticating...'
: isGeneratingProof
? `Generating Proof... ${progress?.stage || ''}`
: 'Authenticate & Generate Proof'}
</button>
{/* Display progress */}
{progress && (
<div className="progress">
<p>Stage: {progress.stage}</p>
<p>Proof Index: {progress.proofIndex}</p>
{progress.message && <p>Message: {progress.message}</p>}
</div>
)}
{/* Display generated proofs */}
{proofs && (
<div className="proof-display">
<h3>Generated Proofs:</h3>
<p>Number of proofs: {proofs.length}</p>
<p>Proof bytes: {proofBytes}</p>
</div>
)}
{/* Display errors */}
{proofError && <div className="error">Error: {proofError.message}</div>}
</div>
{/* Transaction Status */}
{txHash && (
<div className="success">
<h3>✅ Transaction Successful!</h3>
<p>Hash: {txHash}</p>
<a
href={`https://basescan.org/tx/${txHash}`}
target="_blank"
rel="noopener noreferrer"
>
View on BaseScan
</a>
</div>
)}
</div>
);
}
export default ZKP2PApp;
Basic usage:
import { useCreateDeposit, useSignalIntent, useFulfillIntent, useReleaseFundsToPayer } from '@zkp2p/client-sdk/react';
function Actions({ client }: { client: Zkp2pClient }) {
const { createDeposit, isLoading: creating } = useCreateDeposit({ client });
const { signalIntent, isLoading: signaling } = useSignalIntent({ client });
const { fulfillIntent, isLoading: fulfilling } = useFulfillIntent({ client });
const { releaseFundsToPayer, isLoading: releasing } = useReleaseFundsToPayer({ client });
// call createDeposit({ token, amount, intentAmountRange, processorNames, depositData, conversionRates })
// call signalIntent({ escrow, depositId, amount, to, paymentMethod, fiatCurrency, conversionRate, ... })
// call fulfillIntent({ intentHash, zkTlsProof, platform, actionType, ... })
// call releaseFundsToPayer({ intentHash })
return null;
}
import { PLATFORM_METADATA } from '@zkp2p/client-sdk';
import { ExtensionOrchestrator } from '@zkp2p/client-sdk/extension';
async function authenticateAndGenerateProof() {
const orchestrator = new ExtensionOrchestrator({
debug: true,
metadataTimeoutMs: 60000,
});
try {
// Single call for authentication and proof generation
const result = await orchestrator.authenticateAndGenerateProof('revolut', {
paymentMethod: 1,
autoGenerateProof: {
intentHashHex: '0x123...abc',
itemIndex: 0,
onProofGenerated: (proofs) => {
console.log(`✅ Generated ${proofs.length} proof(s)`);
},
onProofError: (error) => {
console.error('❌ Proof generation failed:', error);
},
onProgress: (progress) => {
console.log(`⏳ ${progress.stage} - Proof ${progress.proofIndex + 1}`);
},
},
onPaymentsReceived: (payments) => {
console.log(`📱 Received ${payments.length} payments`);
},
});
// Access results
console.log('Payments:', result.payments);
console.log('Proofs:', result.proofs);
console.log('Proof bytes:', result.proofBytes);
// Submit to blockchain
if (result.proofs && result.proofBytes) {
await client.fulfillIntent({
intentHash: '0x123...abc',
paymentProofs: result.proofs.map(p => ({ proof: p })),
});
}
} finally {
orchestrator.dispose();
}
}
import {
ExtensionProofFlow,
ExtensionMetadataFlow,
metadataUtils,
intentHashHexToDecimalString,
assembleProofBytes
} from '@zkp2p/client-sdk/extension';
async function manualProofFlow() {
// Step 1: Get payment metadata
const metaFlow = new ExtensionMetadataFlow({ debug: true });
const payments = await new Promise((resolve) => {
const unsub = metaFlow.subscribe((platform, record) => {
if (platform === 'venmo') {
const visible = metadataUtils.filterVisible(record.metadata);
const sorted = metadataUtils.sortByDateDesc(visible);
unsub();
resolve(sorted);
}
});
// Request metadata from extension
metaFlow.requestMetadata('list_transactions', 'venmo');
});
// Step 2: User selects a payment
const selectedPayment = payments[0]; // In real app, let user choose
// Step 3: Generate proof(s)
const proofFlow = new ExtensionProofFlow({ debug: true });
const proofs = await proofFlow.generateProofs(
'venmo',
intentHashHexToDecimalString('0x123...abc'),
selectedPayment.originalIndex,
{
requiredProofs: 1, // Venmo requires 1 proof
timeoutMs: 120000,
pollIntervalMs: 3000,
},
(progress) => {
console.log('Progress:', progress);
}
);
// Step 4: Build proof bytes and submit
const proofBytes = assembleProofBytes(proofs, { paymentMethod: 1 });
await client.fulfillIntent({
intentHash: '0x123...abc',
paymentProofs: proofs.map(p => ({ proof: p })),
});
// Cleanup
metaFlow.dispose();
proofFlow.dispose();
}
import {
PAYMENT_PLATFORMS,
PLATFORM_METADATA,
type PaymentPlatformType
} from '@zkp2p/client-sdk';
// List all supported platforms
console.log('Supported platforms:', PAYMENT_PLATFORMS);
// ['wise', 'venmo', 'revolut', 'cashapp', 'mercadopago', 'zelle', 'paypal', 'monzo']
// Get platform metadata
PAYMENT_PLATFORMS.forEach(platform => {
const meta = PLATFORM_METADATA[platform];
console.log(`${meta.logo} ${meta.displayName}: ${meta.requiredProofs} proof(s) required`);
});
// Type-safe platform usage
function processPlatform(platform: PaymentPlatformType) {
const metadata = PLATFORM_METADATA[platform];
console.log(`Processing ${metadata.displayName}...`);
}
import {
Currency,
currencyInfo,
type CurrencyType,
type CurrencyData
} from '@zkp2p/client-sdk';
// Use currency constants
const usdCurrency: CurrencyType = Currency.USD;
const eurCurrency: CurrencyType = Currency.EUR;
// Get detailed currency information
const usdInfo: CurrencyData = currencyInfo[Currency.USD];
console.log(`${usdInfo.currencySymbol} - ${usdInfo.currencyName}`);
// $ - United States Dollar
// List all supported currencies
Object.values(Currency).forEach(code => {
const info = currencyInfo[code];
console.log(`${info.countryCode}: ${info.currencySymbol} ${info.currencyCode}`);
});
import {
SUPPORTED_CHAIN_IDS,
DEPLOYED_ADDRESSES,
DEFAULT_BASE_API_URL,
DEFAULT_WITNESS_URL,
type SupportedChainId
} from '@zkp2p/client-sdk';
// Supported chains
console.log('Base Mainnet:', SUPPORTED_CHAIN_IDS.BASE_MAINNET); // 8453
console.log('Base Sepolia:', SUPPORTED_CHAIN_IDS.BASE_SEPOLIA); // 84532
console.log('Scroll:', SUPPORTED_CHAIN_IDS.SCROLL_MAINNET); // 534352
// Get contract addresses for a specific chain
const baseContracts = DEPLOYED_ADDRESSES[SUPPORTED_CHAIN_IDS.BASE_MAINNET];
console.log('Escrow:', baseContracts.escrow);
console.log('USDC:', baseContracts.usdc);
console.log('Venmo Verifier:', baseContracts.venmo);
// API endpoints
console.log('API URL:', DEFAULT_BASE_API_URL);
console.log('Witness URL:', DEFAULT_WITNESS_URL);
When fetching on-chain deposits and intents, the SDK automatically enriches the data with payment metadata when an API key is provided:
// Fetch deposits with automatic enrichment
const deposits = await client.getAccountDeposits('0xYourAddress');
// Each deposit's verifiers will include:
// - paymentMethod: Platform key (e.g., 'venmo', 'revolut', 'paypal')
// - paymentData: Platform-specific metadata from API (when available)
deposits.forEach(deposit => {
deposit.verifiers.forEach(verifier => {
console.log('Platform:', verifier.verificationData.paymentMethod);
console.log('Payment Data:', verifier.verificationData.paymentData);
});
});
// Fetch intent with automatic enrichment
const intent = await client.getAccountIntent('0xYourAddress');
if (intent) {
// Top-level intent includes enriched data
console.log('Payment Platform:', intent.intent.paymentMethod);
console.log('Payment Data:', intent.intent.paymentData);
// Verifiers also include enriched data
intent.deposit.verifiers.forEach(verifier => {
console.log('Verifier Platform:', verifier.verificationData.paymentMethod);
console.log('Verifier Data:', verifier.verificationData.paymentData);
});
}
Notes:
paymentMethod is always set when the verifier is a recognized platformpaymentData requires a valid API key and may not always be availableconst client = new Zkp2pClient({
walletClient,
apiKey: 'YOUR_API_KEY',
chainId: 8453,
timeouts: {
api: 30000, // 30 seconds for API calls
transaction: 60000, // 60 seconds for transactions
proofGeneration: 120000, // 2 minutes for proof generation
extension: 60000, // 60 seconds for extension communication
},
});
import {
ZKP2PError,
ValidationError,
NetworkError,
APIError,
ContractError,
ProofGenerationError,
ErrorCode
} from '@zkp2p/client-sdk';
try {
await client.signalIntent({ /* ... */ });
} catch (error) {
if (error instanceof ValidationError) {
console.error('Validation failed:', error.message);
console.error('Error code:', error.code);
} else if (error instanceof NetworkError) {
console.error('Network error:', error.message);
} else if (error instanceof APIError) {
console.error('API error:', error.message);
} else if (error instanceof ContractError) {
console.error('Smart contract error:', error.message);
} else if (error instanceof ProofGenerationError) {
console.error('Proof generation failed:', error.message);
} else {
console.error('Unknown error:', error);
}
}
import { logger, setLogLevel } from '@zkp2p/client-sdk';
// Set log level
setLogLevel('debug'); // 'debug' | 'info' | 'warn' | 'error' | 'none'
// Use logger in your app
logger.debug('Debug message');
logger.info('Info message');
logger.warn('Warning message');
logger.error('Error message');
import {
encodeProofAsBytes,
encodeTwoProofs,
encodeManyProofs,
encodeProofAndPaymentMethodAsBytes,
assembleProofBytes,
type ReclaimProof
} from '@zkp2p/client-sdk';
import { parseExtensionProof } from '@zkp2p/client-sdk/extension';
// Parse proof from extension
const extensionPayload = '...'; // From extension
const reclaimProof: ReclaimProof = parseExtensionProof(extensionPayload);
// Encode single proof
const singleBytes = encodeProofAsBytes(reclaimProof);
// Encode two proofs (for platforms requiring 2 proofs)
const twoBytes = encodeTwoProofs(proof1, proof2);
// Encode many proofs
const manyBytes = encodeManyProofs([proof1, proof2, proof3]);
// Add payment method to encoded bytes
const taggedBytes = encodeProofAndPaymentMethodAsBytes(singleBytes, 1);
// Assemble proofs with optional payment method
const assembled = assembleProofBytes([proof1, proof2], { paymentMethod: 1 });
# .env
VITE_ZKP2P_API_KEY=your_api_key_here
VITE_ZKP2P_RPC_URL=https://base-mainnet.g.alchemy.com/v2/your_key
VITE_ZKP2P_BASE_API_URL=https://api.zkp2p.xyz
VITE_ZKP2P_WITNESS_URL=https://witness-proxy.zkp2p.xyz
// main.tsx
import { Zkp2pClient } from '@zkp2p/client-sdk';
const client = new Zkp2pClient({
walletClient,
apiKey: import.meta.env.VITE_ZKP2P_API_KEY!,
chainId: 8453,
rpcUrl: import.meta.env.VITE_ZKP2P_RPC_URL,
baseApiUrl: import.meta.env.VITE_ZKP2P_BASE_API_URL,
witnessUrl: import.meta.env.VITE_ZKP2P_WITNESS_URL,
});
# .env.local
NEXT_PUBLIC_ZKP2P_API_KEY=your_api_key_here
NEXT_PUBLIC_ZKP2P_RPC_URL=https://base-mainnet.g.alchemy.com/v2/your_key
// app/providers.tsx
'use client';
import { Zkp2pClient } from '@zkp2p/client-sdk';
const client = new Zkp2pClient({
walletClient,
chainId: 8453,
});
# .env
REACT_APP_ZKP2P_API_KEY=your_api_key_here
REACT_APP_ZKP2P_RPC_URL=https://base-mainnet.g.alchemy.com/v2/your_key
// App.tsx
const client = new Zkp2pClient({
walletClient,
apiKey: process.env.REACT_APP_ZKP2P_API_KEY!,
chainId: 8453,
rpcUrl: process.env.REACT_APP_ZKP2P_RPC_URL,
});
We welcome contributions! Please see our Contributing Guide for details.
MIT License - see LICENSE for details.
GitHub Issues: Create an issue
Email: support@zkp2p.xyz
FAQs
Browser-first TypeScript SDK for ZKP2P with React hooks, unified authentication, and peerauth extension integration
We found that @zkp2p/client-sdk demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
Add real-time Socket webhook events to your workflows to automatically receive software supply chain alert changes in real time.

Product
Socket now scans OpenVSX extensions, giving teams early detection of risky behaviors, hidden capabilities, and supply chain threats in developer tools.

Product
Bringing supply chain security to the next generation of JavaScript package managers