API Reference/StealthPayment

StealthPayment

Represents a stealth payment ready to be sent. Contains the one-time stealth address and the ephemeral public key needed for the recipient to detect and claim the payment.

Quick Overview

Module:onyx_sdk::address
Traits:Clone, Debug, Serialize, Deserialize

Definition

struct
rust
pub struct StealthPayment {
    /// The stealth address where funds will be sent
    pub stealth_address: Pubkey,
    /// The ephemeral public key (must be published for receiver to detect)
    pub ephemeral_pubkey: [u8; 32],
    /// Amount in lamports
    pub amount: u64,
}

Fields

stealth_addressPubkey

The one-time Solana address where funds should be sent. This is a unique address generated specifically for this payment.

ephemeral_pubkey[u8; 32]

The sender's one-time public key. Must be published on-chain so the recipient can detect and claim the payment.

amountu64

The amount to send in lamports (1 SOL = 1,000,000,000 lamports).

Methods

create
pub fn create(recipient: &PublicMetaAddress, amount: u64) -> Result<Self>

Creates a new stealth payment to the specified recipient. Generates a unique stealth address and ephemeral keypair.

use onyx_sdk::{PublicMetaAddress, StealthPayment};

// Parse recipient's public meta-address
let recipient = PublicMetaAddress::from_string("stealth1...")?;

// Create a stealth payment for 1 SOL
let payment = StealthPayment::create(&recipient, 1_000_000_000)?;

println!("Send SOL to: {}", payment.stealth_address);
println!("Ephemeral key: {}", hex::encode(&payment.ephemeral_pubkey));

Complete Usage Example

Here's how to create a payment and send it on-chain:

send_payment.rs
rust
use onyx_sdk::{PublicMetaAddress, StealthPayment};
use solana_sdk::{
    signature::Keypair,
    signer::Signer,
    system_instruction,
    transaction::Transaction,
};
use solana_client::rpc_client::RpcClient;

fn send_stealth_payment(
    recipient_meta: &str,
    amount_sol: f64,
    payer: &Keypair,
    rpc_url: &str,
) -> anyhow::Result<()> {
    // Parse recipient's meta-address
    let recipient = PublicMetaAddress::from_string(recipient_meta)?;

    // Convert SOL to lamports
    let amount_lamports = (amount_sol * 1_000_000_000.0) as u64;

    // Create the stealth payment
    let payment = StealthPayment::create(&recipient, amount_lamports)?;

    println!("Stealth Payment Created:");
    println!("  Address: {}", payment.stealth_address);
    println!("  Amount: {} lamports", payment.amount);

    // Connect to Solana
    let client = RpcClient::new(rpc_url.to_string());

    // Create transfer instruction
    let transfer_ix = system_instruction::transfer(
        &payer.pubkey(),
        &payment.stealth_address,
        amount_lamports,
    );

    // Build and send transaction
    let recent_blockhash = client.get_latest_blockhash()?;
    let tx = Transaction::new_signed_with_payer(
        &[transfer_ix],
        Some(&payer.pubkey()),
        &[payer],
        recent_blockhash,
    );

    let signature = client.send_and_confirm_transaction(&tx)?;
    println!("Transaction sent: {}", signature);

    // IMPORTANT: Share the ephemeral pubkey with the recipient
    // so they can detect and claim the payment
    println!("Share this with recipient: {}", hex::encode(&payment.ephemeral_pubkey));

    Ok(())
}

Recipient Claiming Funds

Once a payment is sent, the recipient detects it using the Scanner and claims funds using StealthKeypair:

claim_funds.rs
rust
use onyx_sdk::{StealthMetaAddress, StealthKeypair, Scanner, Announcement};
use solana_sdk::{
    signer::Signer,
    system_instruction,
    transaction::Transaction,
};

fn claim_payment(
    meta: &StealthMetaAddress,
    ephemeral_pubkey: &[u8; 32],
    stealth_address: &Pubkey,
    destination: &Pubkey,
) -> anyhow::Result<()> {
    // Derive the spending keypair
    let keypair = StealthKeypair::derive(meta, ephemeral_pubkey)?;

    // Verify it matches
    assert_eq!(keypair.address(), *stealth_address);

    // Get Solana keypair for signing
    let signer = keypair.to_solana_keypair()?;

    // Get balance
    let client = RpcClient::new("https://api.devnet.solana.com".to_string());
    let balance = client.get_balance(stealth_address)?;

    // Build transfer to claim funds
    let ix = system_instruction::transfer(
        stealth_address,
        destination,
        balance.saturating_sub(5000), // Leave some for fees
    );

    let recent_blockhash = client.get_latest_blockhash()?;
    let tx = Transaction::new_signed_with_payer(
        &[ix],
        Some(stealth_address),
        &[&signer],
        recent_blockhash,
    );

    client.send_and_confirm_transaction(&tx)?;
    println!("Claimed {} lamports!", balance);

    Ok(())
}

Serialization

StealthPayment implements Serialize and Deserialize for easy storage:

use serde_json;

// Serialize to JSON
let json = serde_json::to_string_pretty(&payment)?;
println!("{}", json);

// Output:
// {
//   "stealth_address": "7xKXtg...",
//   "ephemeral_pubkey": [123, 45, 67, ...],
//   "amount": 1000000000
// }

// Deserialize back
let loaded: StealthPayment = serde_json::from_str(&json)?;