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
onyx_sdk::addressClone, Debug, Serialize, DeserializeDefinition
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_addressPubkeyThe 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.
amountu64The amount to send in lamports (1 SOL = 1,000,000,000 lamports).
Methods
createpub 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:
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:
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)?;