Privacy
SDK Quickstart
Integrate UPP privacy into your app
Private Preview
The UPP SDK is in private preview. Join our Telegram for access.
Installation
# Coming soon - contact us for early access
npm install [coming soon]Setup
import { createUPPClient } from '@upd/upp-sdk'
import { createWalletClient, http } from 'viem'
import { sepolia } from 'viem/chains'
// 1. Create wallet client
const walletClient = createWalletClient({
chain: sepolia,
transport: http(),
})
// 2. Initialize UPP client
const upp = await createUPPClient({
walletClient,
// SDK will prompt for signature to derive keys
})
// Keys are derived from wallet signature - no extra seed phrasesCore Operations
Shield (Deposit)
Move public tokens into the private pool:
// Approve UPP to spend your tokens
await upp.approve({ token: UPD_ADDRESS, amount: 1000n * 10n**18n })
// Shield tokens - creates an encrypted note
const { commitment } = await upp.shield({
token: UPD_ADDRESS,
amount: 1000n * 10n**18n,
})
console.log('Shielded! Note commitment:', commitment)Transfer (Private Send)
Send to another user within the pool:
// Get recipient's stealth meta-address (they share this publicly)
const recipientAddress = '0zk1...'
// Transfer - proves you own the note without revealing which one
const { recipientCommitment, changeCommitment } = await upp.transfer({
amount: 500n * 10n**18n,
to: recipientAddress,
})
// Recipient gets 500 UPD, you get change noteCheck Balance
Scan for your notes and compute balance:
// Scans encrypted notes, decrypts yours
const notes = await upp.scan()
const balance = notes
.filter(n => n.token === UPD_ADDRESS && !n.spent)
.reduce((sum, n) => sum + n.amount, 0n)
console.log('Private balance:', balance)Unshield (Withdraw)
Move back to public:
const { txHash } = await upp.unshield({
amount: 200n * 10n**18n,
to: '0x...recipient',
aspId: 1, // Which ASP to use for compliance proof
})React Integration
import { UPPProvider, useUPP } from '@upd/upp-sdk/react'
function App() {
return (
<UPPProvider>
<PrivateBalance />
</UPPProvider>
)
}
function PrivateBalance() {
const { balance, isScanning, shield, transfer } = useUPP()
if (isScanning) return <div>Scanning notes...</div>
return (
<div>
<p>Private balance: {formatUnits(balance, 18)} UPD</p>
<button onClick={() => shield({ amount: parseUnits('100', 18) })}>
Shield 100 UPD
</button>
</div>
)
}Key Concepts
Stealth Addresses
Recipients share a stealth meta-address (0zk1...). Senders derive unique one-time addresses for each payment. Even the recipient's public address doesn't appear on-chain.
// Generate your stealth meta-address to receive payments
const myStealthAddress = upp.getStealthMetaAddress()
// Share this publicly - senders use it to create unlinkable paymentsViewing Keys
Export viewing keys for auditors:
const auditExport = await upp.exportViewingKeys({
notes: [note1, note2], // Specific notes to share
})
// Send auditExport to auditor - they can decrypt these notes onlyNote Management
Each shield/transfer creates notes (encrypted UTXOs). The SDK tracks these automatically:
const notes = await upp.getNotes()
// Each note has:
// - amount: token amount
// - token: which token
// - commitment: on-chain identifier
// - spent: whether it's been usedError Handling
try {
await upp.transfer({ amount, to })
} catch (e) {
if (e.code === 'INSUFFICIENT_BALANCE') {
// Not enough private balance
} else if (e.code === 'ASP_PROOF_FAILED') {
// Origin not in ASP allowlist
} else if (e.code === 'PROOF_GENERATION_FAILED') {
// ZK proof failed - check inputs
}
}Next Steps
- Architecture - How it works under the hood
- Join our Telegram - Get SDK access