Developers
Developer Preview: Stellar Private Payments
Author
Maryam Mazraei
Publishing date
Editor's note: Stellar's Developer Previews put new developer tooling and protocol capabilities in developers' hands before they're production-ready. While they're not yet approved for mainnet, the Stellar Private Payments contract is live on testnet. Preview and test them now while the contracts are unaudited and development is underway.
Today we're previewing Stellar Private Payments (SPP), a privacy primitive on Stellar. Stellar Private Payments is a privacy pool implementation built by Nethermind that gives payments counterparty-level privacy. Users hold a private balance in a shared shielded pool and pay each other inside it. The public ledger records that the pool was used, while keeping who paid whom or how much private. As Nethermind highlights in their writeup; privacy and compliance are not opposing requirements and SPP is designed to enforce both, on public rails.
Counterparty privacy, not just confidential amounts
One thing worth reiterating from our last Developer Preview on Confidential Token: Privacy on a public blockchain isn't one thing. Different use cases need different properties, and the architecture you choose at the start decides what you can do later.
Where a Confidential Token keeps amounts and balances between known counterparties private, Stellar Private Payments provides privacy for counterparties. Deposit and withdrawal addresses are visible at the edges of the pool; you can see funds went in, and out, but the link between a specific deposit and a specific withdrawal, and the amount and counterparties of any transfer inside the pool, are kept private from the public. Suitable use cases include B2B payments or donations where the relationship between the transacting parties is sensitive.
This post focuses on Stellar Private Payments, for flows where the counterparties need privacy.
How it works: a shared pool where funds live
The pool is the place where funds live and transactions happen. A user deposits an asset into a shared pool contract, and their deposit becomes a commitment in a Merkle tree, a cryptographic note that proves value exists in the pool without revealing whose it is.

From there the main event is the private transfer within the pool. When you pay or transfer funds to another address inside the pool, your notes are spent and new notes are created under the recipient's key. Every operation that spends notes, whether a transfer or a withdrawal, publishes a zero-knowledge proof that says: “the notes I am spending are valid and I own them,” without revealing which notes they are. A nullifier is published onchain at the same time so the same note can never be spent twice. Users can hold a private balance indefinitely and pay many counterparties before ever leaving the pool.
In a pool using SPP, you can pay someone using Stellar G-address and recent ecosystem developer builds have demonstrated testnet payments to Stellar C-addresses with smart accounts (Privacy Wallet demo).
And then there's withdrawing, which is simply the exit. Prove your notes and move value back to the public ledger to an address of your choice.
To make this tangible, let's run a transaction example. The thing to look out for onchain that tells the story is ext_amount, the external amount on a pool transaction:
- Deposit: ext_amount is positive (e.g. +50000000 stroops = 5 XLM). Funds in are public.
- Private transfer: ext_amount is 0. The amount moves entirely inside encrypted commitments, and the recipient's address appears nowhere on the transaction.
- Withdrawal: ext_amount is negative (e.g. −20000000). The amount out is public on the ledger.
Public in, private middle, public out, with nothing onchain tying the two ends together. The zero-knowledge proof system used is Groth16, with resource-efficient verification onchain using the cryptographic host functions introduced in Protocol 25 (X-Ray) and Protocol 26 (Yardstick). The network itself verifies every proof; there is no third-party verifier or operator to trust.
Stellar Private Payments and the demo have a working testnet implementation you can build against today.
Pools love a crowd
Privacy pools demonstrate their full potential in a busy pool. The scenario it applies to best: having more deposits from multiple accounts in the same pool increases the “privacy set”, making it more difficult for a public observer to associate a given transaction to any single party. For example, if there are just two people in a pool, you deposit 5 XLM, and moments later someone withdraws 5 XLM, an observer can correlate that by amount and timing.

What's in this version
This preview includes configurable mechanisms designed to help deployers address compliance obligations in their privacy pool deployments.
- Association Set Providers (ASP), configurable per pool. Stellar Private Payments currently implements a key-based association set model, a different approach from the original Privacy Pools whitepaper, which is deposit-based. When a pool is deployed, a single flag sets its mode: block-list (exclude specific accounts), allow-list (admit only specific accounts), or both. Every pool transaction (deposit, transfer, and withdrawal) then proves membership or non-membership through a designated association set provider without revealing the user's history. Because association is at the key level, not the note level, it's easier to KYC-gate entry and automatically freeze every note owned by a flagged key. The hosted demo runs in block-list-only mode, so anyone can try it without ASP onboarding. Note-level deposit labeling and tracing, drawing on the original Privacy Pools design, are in design to extend enforcement to funds already transferred to other users in the pool.
- Global View Keys. Optionally provide pool-wide visibility for administrators across all in-pool transactions via a designated auditor account. This helps admins with compliance obligations such as transaction monitoring and reporting and can assist them with regulatory investigations where required. The global view key can be secured with an institutional wallet solution, and even remain within a trusted execution environment for secure disclosure of only relevant, scoped transaction data.
- Selective Disclosure, enabled by user view keys. A user can prove note-level facts about a specific transaction (amount, commitment, spent status) to a party of their choosing via a context-bound proof, without exposing the rest of their activity. Today this disclosure is note-scoped: it does not prove source of funds or transaction history, so it is not yet an attestation a user can hand to an outside party for a guarantee of transaction integrity and completeness, though this is a near-term goal for the project.
- Embedded testnet deployment. All contract IDs (pool, Groth16 verifier, ASP membership and non-membership contracts, public-key registry) are baked in, so there's minimal configuration necessary to start exploring.
Compliance is a design parameter, not a fixed setting. The same pool contract can be configured to support multiple different kinds of use cases or jurisdictions. These extensions are open source and actively being iterated on.
Try it yourself
You can either (1) test the hosted demo for a quick review, or (2) use the SDK to build against it. Both run on testnet; keep everything on testnet only.
Fastest: the hosted demo
- Open the hosted app
- Connect Freighter on Stellar Testnet (get testnet XLM on Stellar Lab and select “Fund account”) and run one deposit → private transfer → withdraw. If the app misbehaves after an update, clear the site's local storage; the alpha evolves quickly
- Watch a single field, ext_amount, on each transaction in a testnet explorer like stellar.expert, like this example below.
deposit ext_amount +50000000 +5 XLM (public)
transfer ext_amount 0 amount + recipient private
withdraw ext_amount -20000000 -2 XLM (public, to a new address)The testnet deployment currently runs XLM and EURC pools.
Build with the SDK. The web SDK ships as a prebuilt-WASM package on npm, so you can add private payments to an app without touching a Rust toolchain:
npm i stellar-private-payments@alpha @stellar/freighter-apiSPP ships two SDKs: the TS/JS SDK used here, and a Rust SDK for backend or native clients. Once the client is set up (WASM init, storage, and a wallet signer, all walked through in the SDK README), the whole loop is three calls:
await pool.deposit(50000000n); // ext_amount +5 · public
await pool.transfer(recipient, 20000000n); // ext_amount 0 · amount + recipient private
await pool.withdraw(20000000n); // ext_amount -2 · publicThe amounts shown above are in stroops i.e. 1 stroop = 0.0000001 XLM.
The SDK handles historical sync via a “bootnode” indexer and background event sync for you, so you don't hit the 7-day ledger-sync gaps a raw RPC connection would. The SDK README has the full working loop, from init to Freighter signing, and is the source of truth as the alpha evolves.
Signing is pluggable: FreighterSigner is the built-in Freighter adapter, but any signer that implements the SDK's interface works, so you're not locked to one wallet.
Or skip the app entirely: the spp CLI (the CLI is just a small preview, it's not fully compatible with all features). One-line install:
curl -fsSL https://nethermindeth.github.io/stellar-private-payments/install.sh | shIt downloads a checksummed binary for your platform, provisions the circuits and proving keys, and gives you the full deposit, transfer, withdraw loop from the terminal (Stellar CLI with keys imported is required). Then run spp onboard to accept the disclaimer and derive your keys; spp --help shows the full command set. This is for you or your agent: the CLI is a fully scriptable surface, so if you build with a coding agent, point it at the repo README and the spp CLI and let it drive the whole testnet flow for you.
Clone stellar-private-payments and submit issues during the testnet window. Full docs are at Privacy on Stellar.
We welcome design partners and developer contributions. If you're building compliance-focused privacy solutions on Stellar, an SCF cohort member, or joined our recent Stellar Hacks: Real-World ZK hackathon or Stellar Summit São Paulo, share what you're working on in our Developer Discord.
Developer Preview with Nethermind

We're excited to have Antonio Larriba Cryptography Researcher at Nethermind, who worked on the build, join Alessandro Voto Senior Product Manager at Stellar Development Foundation to discuss Stellar Private Payments and our work with Nethermind furthering privacy on Stellar.
Tune in Aug 28th @ 4:00 PM UTC to watch the stream on @BuildOnStellar.
Stellar Private Payments is part of a broader privacy stack on Stellar. For background on the primitives that made this possible, see: stellar.org/privacy, Stellar's developer docs on privacy, Developer Preview: Confidential Tokens on Stellar and the taxonomy in the Appendix below.
Appendix: Privacy on Stellar (a working taxonomy)
An easy way to understand privacy solutions onchain is to ask:
What does the network see, and what stays private?
Solution | Public | Private |
Confidential Token | Sender and recipient addresses; deposit and withdrawal amounts | Balances; transfer amounts |
Privacy pool implementations (e.g. SPP) | Deposit and withdrawal addresses; the amounts entering and leaving the pool | The link between a deposit and a withdrawal; the transfer amount inside the pool |
Standard SEP-41 tokens | Everything (addresses, amounts, balances) | Nothing |
Why both lanes exist. Privacy pools are designed for flows where the counterparties need privacy such as B2B settlements, donations. While Confidential Tokens fit known-counterparty flows where the amount needs privacy such as payroll, treasury management. Some use cases may benefit from both.
Stellar's privacy layering hierarchy
Application layer: Stellar smart contracts that implement specific privacy behavior. These include privacy pool implementations like Stellar Private Payments (SPP) and Confidential Tokens.
Verifier layer: An onchain verifier is a smart contract that accepts a compact ZK proof and confirms its validity without re-running the original computation. Examples include the Groth16 verifier used by Stellar Private Payments and Nethermind's UltraHonk verifier used by the Confidential Token contract.
Cryptographic host functions. Built into the Stellar protocol at the base layer: elliptic curve operations on the BN254 and BLS12-381 curves, and the Poseidon/Poseidon2 hash function. Introduced in the X-Ray (Protocol 25) and Yardstick (Protocol 26) upgrades. These host function primitives allow for resource-efficient verification directly onchain, providing greater security assurance and decentralization.
Base (public) ledger. Privacy contracts live in the layers above, with cryptographic host functions living in the public ledger layer.
