Node.js Setup
This guide covers using the Privacy Boost WASM SDK in Node.js environments.Prerequisites
- Node.js 18.0 or later (for native WASM support)
- npm/yarn/pnpm
Installation
npm install @sunnyside-io/privacy-boost-wasm
Basic Usage
import init, { PrivacyBoost } from '@sunnyside-io/privacy-boost-wasm';
import { readFileSync } from 'fs';
import { join } from 'path';
async function main() {
// Initialize WASM
await init();
// Create SDK
const sdk = new PrivacyBoost({
serverUrl: 'https://optimism.privacyboost.io',
appId: 'my-app',
});
console.log('SDK initialized');
}
main().catch(console.error);
Server-Side Wallet Adapter
For server-side usage, create a wallet adapter using ethers.js or viem:With ethers.js
import { Wallet, JsonRpcProvider } from 'ethers';
function createEthersAdapter(privateKey: string, rpcUrl: string) {
const provider = new JsonRpcProvider(rpcUrl);
const wallet = new Wallet(privateKey, provider);
return {
async getAddress(): Promise<string> {
return wallet.address;
},
async getChainId(): Promise<number> {
const network = await provider.getNetwork();
return Number(network.chainId);
},
async signMessage(message: string): Promise<string> {
return wallet.signMessage(message);
},
async signTypedData(typedDataJson: string): Promise<string> {
const typedData = JSON.parse(typedDataJson);
const { domain, types, message: data } = typedData;
// Remove EIP712Domain from types (ethers handles it)
const { EIP712Domain, ...signingTypes } = types;
return wallet.signTypedData(domain, signingTypes, data);
},
async sendTransaction(tx: {
to: string;
value: string;
data: string;
}): Promise<string> {
const response = await wallet.sendTransaction({
to: tx.to,
value: BigInt(tx.value),
data: tx.data,
});
return response.hash;
},
async waitForTransactionReceipt(txHash: string): Promise<{
transactionHash: string;
status: boolean;
logs: Array<{ address: string; topics: string[]; data: string }>;
}> {
const receipt = await provider.waitForTransaction(txHash);
if (!receipt) {
throw new Error(`Transaction not found: ${txHash}`);
}
return {
transactionHash: receipt.hash,
status: receipt.status === 1,
logs: receipt.logs.map((log) => ({
address: log.address,
topics: [...log.topics],
data: log.data,
})),
};
},
};
}
With viem
import { createPublicClient, createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { mainnet } from 'viem/chains';
function createViemAdapter(privateKey: `0x${string}`, rpcUrl: string) {
const account = privateKeyToAccount(privateKey);
const client = createWalletClient({
account,
chain: mainnet,
transport: http(rpcUrl),
});
const publicClient = createPublicClient({
chain: mainnet,
transport: http(rpcUrl),
});
return {
async getAddress(): Promise<string> {
return account.address;
},
async getChainId(): Promise<number> {
return mainnet.id;
},
async signMessage(message: string): Promise<string> {
return client.signMessage({ message });
},
async signTypedData(typedDataJson: string): Promise<string> {
const typedData = JSON.parse(typedDataJson);
return client.signTypedData(typedData);
},
async sendTransaction(tx: {
to: string;
value: string;
data: string;
}): Promise<string> {
return client.sendTransaction({
to: tx.to as `0x${string}`,
value: BigInt(tx.value),
data: tx.data as `0x${string}`,
});
},
async waitForTransactionReceipt(txHash: string): Promise<{
transactionHash: string;
status: boolean;
logs: Array<{ address: string; topics: string[]; data: string }>;
}> {
const receipt = await publicClient.waitForTransactionReceipt({
hash: txHash as `0x${string}`,
});
return {
transactionHash: receipt.transactionHash,
status: receipt.status === 'success',
logs: receipt.logs.map((log) => ({
address: log.address,
topics: [...log.topics],
data: log.data,
})),
};
},
};
}
Complete Server Example
import init, { PrivacyBoost } from '@sunnyside-io/privacy-boost-wasm';
import { Wallet, JsonRpcProvider } from 'ethers';
const config = {
serverUrl: process.env.SERVER_URL!,
wethContractAddress: process.env.WETH_CONTRACT_ADDRESS!,
appId: process.env.APP_ID!,
};
async function main() {
// Initialize WASM
await init();
// Create SDK
const sdk = new PrivacyBoost(config);
// Create wallet adapter
const adapter = createEthersAdapter(
process.env.PRIVATE_KEY!,
process.env.RPC_URL!
);
// Authenticate
const result = await sdk.authenticate(adapter, undefined);
console.log('Privacy Address:', result.privacyAddress);
// Check balance
const balance = await sdk.getBalance(config.wethContractAddress);
console.log('Shielded balance:', balance.shieldedBalance);
// Perform operations...
}
main().catch(console.error);
Express.js API Server
import express from 'express';
import init, { PrivacyBoost } from '@sunnyside-io/privacy-boost-wasm';
const app = express();
app.use(express.json());
let sdk: PrivacyBoost;
// Initialize on startup
async function initSDK() {
await init();
sdk = new PrivacyBoost({
serverUrl: process.env.SERVER_URL!,
appId: process.env.APP_ID!,
});
}
// Endpoint to check balance
app.get('/api/balance/:token', async (req, res) => {
try {
const balance = await sdk.getBalance(req.params.token);
res.json(balance);
} catch (error) {
res.status(500).json({ error: (error as Error).message });
}
});
// Endpoint to get transaction history
app.get('/api/transactions', async (req, res) => {
try {
const { type, token, limit } = req.query;
const txs = await sdk.getTransactionHistory({
type: type as string,
tokenAddress: token as string,
limit: limit ? Number(limit) : undefined,
});
res.json(txs);
} catch (error) {
res.status(500).json({ error: (error as Error).message });
}
});
// Start server
initSDK().then(() => {
app.listen(3000, () => {
console.log('Server running on port 3000');
});
});
Batch Processing Script
import init, { PrivacyBoost } from '@sunnyside-io/privacy-boost-wasm';
import { readFileSync } from 'fs';
interface TransferJob {
token: string;
amount: string;
recipient: string;
}
async function processTransfers(jobs: TransferJob[]) {
await init();
const sdk = new PrivacyBoost(config);
const adapter = createWalletAdapter();
await sdk.authenticate(adapter, undefined);
const results = [];
for (const job of jobs) {
try {
const result = await sdk.send({
tokenAddress: job.token,
amount: job.amount,
recipient: job.recipient,
});
results.push({ success: true, txHash: result.txHash });
} catch (error) {
results.push({ success: false, error: (error as Error).message });
}
}
return results;
}
// Load jobs from file
const jobs = JSON.parse(readFileSync('transfers.json', 'utf-8'));
processTransfers(jobs)
.then(results => console.log(JSON.stringify(results, null, 2)))
.catch(console.error);
Environment Variables
Create a.env file:
# Privacy Boost Services
SERVER_URL=https://optimism.privacyboost.io
APP_ID=app_abc123xyz
# Network
RPC_URL=https://mainnet.infura.io/v3/YOUR_KEY
WETH_CONTRACT_ADDRESS=0x4200000000000000000000000000000000000006
# Wallet (for server-side signing)
PRIVATE_KEY=0x...
import 'dotenv/config';
Error Handling
try {
await sdk.shield({ tokenAddress: token, amount });
} catch (error) {
const message = (error as Error).message;
if (message.includes('Not authenticated')) {
// Re-authenticate
await sdk.authenticate(adapter, undefined);
} else if (message.includes('Network error')) {
// Retry with exponential backoff
} else {
// Log and alert
console.error('SDK error:', message);
}
}
Next Steps
- Wallet Integration - Detailed adapter implementation
- Browser Setup - Client-side usage
- API Reference - Complete API documentation