@fatsolutions/privacy-pools-core-starknet-sdk
v0.0.41
Published
Starknet SDK for Privacy Pool protocol with Garaga proof verification support
Downloads
127
Readme
Privacy Pool Starknet SDK
A TypeScript SDK for interacting with Privacy Pool contracts on Starknet, featuring Garaga proof verification and comprehensive contract interaction capabilities.
Overview
The Privacy Pool Starknet SDK extends the core Privacy Pool SDK with Starknet-specific functionality. It provides:
- Garaga Integration: Converts zero-knowledge proofs to Garaga format for efficient verification on Starknet
- Contract Interactions: Type-safe interfaces for all Privacy Pool operations (deposits, withdrawals, relays, ragequits)
- Event Fetching: Comprehensive event parsing and data retrieval from Starknet networks
- Admin Operations: Full support for pool management and configuration
- Error Handling: Detailed error codes with human-readable contract error parsing
Installation
npm install @fatsolutions/privacy-pools-core-starknet-sdkQuick Start
import { PrivacyPoolStarknetSDK, StarknetDataService, Mode } from '@fatsolutions/privacy-pools-core-starknet-sdk';
import { Account, RpcProvider } from 'starknet';
// Initialize the SDK
const circuits = new YourCircuitsImplementation(); // Implement CircuitsInterface
const sdk = new PrivacyPoolStarknetSDK(circuits);
// Create contract service
const account = new Account(provider, accountAddress, privateKey);
const contractService = sdk.createSNContractInstance(entrypointAddress, account);
// Deposit ETH
const depositCall = await contractService.depositETH(
BigInt("1000000000000000000"), // 1 ETH in wei
precommitment,
{ mode: Mode.EXECUTE }
);
// Generate withdrawal proof and execute
const { withdrawalProof, calldata } = await sdk.proveWithdrawalSN(commitment, withdrawalInput);
const withdrawResult = await contractService.withdraw(
withdrawal,
calldata,
scope,
{ mode: Mode.EXECUTE }
);Core Components
PrivacyPoolStarknetSDK
The main SDK class that extends the core Privacy Pool SDK with Starknet-specific functionality.
// Initialize SDK
const sdk = new PrivacyPoolStarknetSDK(circuits);
// Create contract service
const contractService = sdk.createSNContractInstance(entrypointAddress, account);
// Generate Starknet-optimized proofs
const { withdrawalProof, calldata } = await sdk.proveWithdrawalSN(commitment, input);
const { commitmentProof, calldata: commitCalldata } = await sdk.proveCommitmentSN(commitment);Contract Interactions Service
The SNContractInteractionsService provides methods for all Privacy Pool operations with support for both simulation and execution modes.
// Deposit operations
await contractService.depositETH(amount, precommitment, { mode: Mode.EXECUTE });
await contractService.depositERC20(tokenAddress, amount, precommitment, { mode: Mode.SIMULATE });
// Withdrawal operations
await contractService.withdraw(withdrawal, proof, scope, { mode: Mode.EXECUTE });
await contractService.relay(withdrawal, proof, scope, { mode: Mode.EXECUTE });
// Ragequit operation
await contractService.ragequit(ragequitProof, poolAddress, { mode: Mode.EXECUTE });
// Approve and deposit in one transaction
await contractService.approveAndDeposit(
entrypointAddress,
tokenAddress,
amount,
precommitment,
{ mode: Mode.EXECUTE }
);Data Service
The StarknetDataService fetches and parses events from Starknet networks.
const provider = new RpcProvider({ nodeUrl: "https://starknet-mainnet.public.blastapi.io" });
const dataService = new StarknetDataService(provider);
// Fetch pool events
const deposits = await dataService.getDeposits(poolInfo);
const withdrawals = await dataService.getWithdrawals(poolInfo);
const ragequits = await dataService.getRagequits(poolInfo);Admin Operations
Administrative functions for pool management:
// Register a new pool
await contractService.admin.registerPool(
assetAddress,
poolAddress,
minimumDepositAmount,
vettingFeeBPS,
maxRelayFeeBPS,
{ mode: Mode.EXECUTE }
);
// Update pool configuration
await contractService.admin.updatePoolConfiguration(
assetAddress,
newMinimumDepositAmount,
newVettingFeeBPS,
newMaxRelayFeeBPS,
{ mode: Mode.EXECUTE }
);
// Update merkle root
await contractService.admin.updateRoot(newRoot, ipfsCID, { mode: Mode.EXECUTE });Execution Modes
The SDK supports different execution modes for all operations:
Mode.EXECUTE: Execute the transaction on-chainMode.SIMULATE: Simulate the transaction without executing- No mode specified: Returns a
Callobject for manual execution
// Execute immediately
const result = await contractService.depositETH(amount, precommitment, { mode: Mode.EXECUTE });
// Simulate first
const simulation = await contractService.depositETH(amount, precommitment, { mode: Mode.SIMULATE });
// Get call for manual execution
const call = await contractService.depositETH(amount, precommitment);
// Execute manually with account.execute([call])Error Handling
The SDK provides comprehensive error handling with specific error types:
import {
StarknetSDKError,
SNPoolError,
SNContractError,
SNFormatError,
parseContractError
} from '@fatsolutions/privacy-pools-core-starknet-sdk';
try {
await contractService.depositETH(tooSmallAmount, precommitment, { mode: Mode.EXECUTE });
} catch (error) {
if (error instanceof SNPoolError) {
console.log('Pool validation error:', error.message);
} else if (error instanceof SNContractError) {
console.log('Contract error:', error.message);
// Parse contract error for human-readable message
const readable = parseContractError(error.message);
if (readable) console.log('Readable error:', readable);
}
}Types and Interfaces
Core Types
// Withdrawal data structure
interface Withdrawal {
processor: BigNumberish;
data: BigNumberish[];
}
// Relay data for withdrawal processing
interface RelayData {
recipient: BigNumberish;
feeRecipient: BigNumberish;
relayFeeBPS: BigNumberish;
}
// Garaga proof structures
interface Groth16Proof {
a: G1Point$1;
b: G2Point$1;
c: G1Point$1;
publicInputs: bigint[];
}Utility Functions
// Compute scope for a privacy pool
const scope = computeScope(poolAddress, chainId, assetAddress);
// Compute context for withdrawals
const context = computeContext(withdrawal, scope);
// Convert proof to Garaga calldata
const calldata = await withdrawalProofToGaragaCalldata(withdrawalProof, vkeyRaw);Contract Error Codes
The SDK automatically parses common contract errors:
| Error Code | Description |
|------------|-------------|
| 0x496e76616c69642050726f6f66 | Invalid Proof |
| 0x4e756c6c69666965722075736564 | Nullifier used |
| 0x496e76616c696420416d6f756e74 | Invalid Amount |
| 0x506f6f6c206e6f7420666f756e64 | Pool not found |
| 0x56616c7565206c6573732074686174206d696e696d756d | Value less than minimum |
Development
Building
npm run buildTesting
npm test
npm run test:cov # With coverageType Checking
npx tsc --noEmitExamples
Complete Deposit Flow
import { PrivacyPoolStarknetSDK, Mode } from '@fatsolutions/privacy-pools-core-starknet-sdk';
import { Account, RpcProvider } from 'starknet';
async function depositExample() {
// Setup
const provider = new RpcProvider({ nodeUrl: "your-starknet-node" });
const account = new Account(provider, accountAddress, privateKey);
const sdk = new PrivacyPoolStarknetSDK(circuits);
const contractService = sdk.createSNContractInstance(entrypointAddress, account);
// Generate precommitment
const { precommitment } = generatePrecommitment(nullifier, secret);
// Execute deposit
try {
const result = await contractService.depositETH(
BigInt("1000000000000000000"), // 1 ETH
precommitment,
{ mode: Mode.EXECUTE }
);
console.log('Deposit successful:', result.transaction_hash);
} catch (error) {
console.error('Deposit failed:', error.message);
}
}Complete Withdrawal Flow
async function withdrawalExample() {
// Generate withdrawal proof
const { withdrawalProof, calldata } = await sdk.proveWithdrawalSN(commitment, {
nullifier: commitment.preimage.precommitment.nullifier,
secret: commitment.preimage.precommitment.secret,
recipient: recipientAddress,
relayerFee: BigInt(0)
});
// Prepare withdrawal data
const withdrawal: Withdrawal = {
processor: processorAddress,
data: [recipientAddress, BigInt(0)] // recipient, relayer fee
};
// Execute withdrawal
const result = await contractService.withdraw(
withdrawal,
calldata,
scope,
{ mode: Mode.EXECUTE }
);
console.log('Withdrawal successful:', result.transaction_hash);
}License
Apache-2.0
Support
For questions and support, please open an issue on the GitHub repository.
