npm package: @fatsolutions/privacy-pools-core-starknet-sdk
Description: Starknet SDK for Privacy Pool protocol with Garaga proof verification support
Author: Fat Solutions
Latest version: 0.0.54

# 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

```bash
npm install @fatsolutions/privacy-pools-core-starknet-sdk
```

## Quick Start

```typescript
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.

```typescript
// 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.

```typescript
// 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.

```typescript
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:

```typescript
// 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-chain
- **`Mode.SIMULATE`**: Simulate the transaction without executing
- **No mode specified**: Returns a `Call` object for manual execution

```typescript
// 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:

```typescript
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

```typescript
// 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

```typescript
// 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

```bash
npm run build
```

### Testing

```bash
npm test
npm run test:cov  # With coverage
```

### Type Checking

```bash
npx tsc --noEmit
```

## Examples

### Complete Deposit Flow

```typescript
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

```typescript
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.