API Reference

StealthPayment

Represents a stealth payment with the derived one-time address, ephemeral key, and amount. Also covers PrivateStealthPayment for zk-SNARK hidden amounts.

Structure

cloak_sdk::address
rust
pub struct StealthPayment {
    pub stealth_address: Pubkey,      // One-time address to send SOL to
    pub ephemeral_pubkey: [u8; 32],   // Publish on-chain for detection
    pub amount: u64,                  // Amount in lamports
}

Methods

create(recipient, amount) → Result<StealthPayment>

Generate a unique stealth address and ephemeral keypair for the given recipient. Uses ECDH with the recipient's viewing public key.

use cloak_sdk::{PublicMetaAddress, StealthPayment};

let recipient = PublicMetaAddress::from_string("stealth1:sol:...")?;
let payment = StealthPayment::create(&recipient, 1_000_000_000)?;

// Each call generates a NEW unique address
let payment2 = StealthPayment::create(&recipient, 1_000_000_000)?;
assert_ne!(payment.stealth_address, payment2.stealth_address);

Sending a payment

After creating the payment, transfer SOL and publish the announcement on-chain:

send.rs
rust
use solana_sdk::{transaction::Transaction, system_instruction};

// 1. Transfer SOL to the stealth address
let transfer_ix = system_instruction::transfer(
    &sender_pubkey,
    &payment.stealth_address,
    payment.amount,
);

// 2. Create the announcement PDA (via Anchor CPI)
// This publishes the ephemeral_pubkey on-chain so the
// receiver can detect the payment.

// The on-chain program handles both in send_stealth instruction

PrivateStealthPayment

For payments with hidden amounts using zk-SNARKs:

cloak_sdk::address
rust
pub struct PrivateStealthPayment {
    pub stealth_address: Pubkey,
    pub ephemeral_pubkey: [u8; 32],
    pub commitment: AmountCommitment,  // Pedersen commitment
    pub proof: AmountProof,            // Groth16 proof
}

The commitment and proof are stored on-chain via the send_stealth_private instruction. The actual amount is never revealed.

private_send.rs
rust
use cloak_sdk::zk::{self, AmountCommitment};

// One-time setup: generate proving/verifying keys
let (pk, pvk) = zk::setup()?;

// Create commitment and proof
let commitment = AmountCommitment::commit(amount);
let proof = zk::prove(&pk, amount, &commitment)?;

// Verify (anyone can do this)
let valid = zk::verify(&pvk, &proof)?;
assert!(valid);

Helper functions

derive_stealth_address(spending_pubkey, shared_secret) → Result<Pubkey>

Low-level function to derive a stealth address from a spending pubkey and shared secret.

use cloak_sdk::derive_stealth_address;

let addr = derive_stealth_address(
    &recipient.spending_pubkey(),
    &shared_secret,
)?;

check_stealth_address(viewing_key, spending_pubkey, ephemeral_pubkey, stealth_address) → Result<bool>

Check if a stealth address belongs to you. Used internally by the Scanner.

use cloak_sdk::check_stealth_address;

let is_mine = check_stealth_address(
    meta.viewing_key(),
    meta.spending_pubkey(),
    &ephemeral_pubkey,
    &stealth_address,
)?;