Which client should you use?
Run the TypeScript SDK in the browser, so proving stays on the user's device. Reach for Rust or Python when the work is server-side — a payout scheduler, a treasury service, an indexer — and you control the host holding the keys.
Installation
Cargo.toml
shell
# Cargo.toml
[dependencies]
zrelay-sdk = "0.1"
tokio = { version = "1", features = ["full"] }
alloy = { version = "0.8", features = ["signer-local"] }- Rust crate
- zrelay-sdk · MSRV 1.79 · tokio runtime
- Python package
- zrelay · 3.10+ · asyncio native
- Signing
- Rust: alloy · Python: eth-account
- Proving
- arkworks (Rust) · bundled wheel (Python)
- Network calls
- Public RPC + public lightwalletd only
- Blocking API
- Python exposes sync wrappers under zrelay.sync
Shield
Moves an EVM asset into a Zcash shielded note. Handles the approval, the DEX route, the escrow deposit and the gas surcharge, then resolves once the Orchard output lands in a finalised block.
main.rs
rust
1use zrelay_sdk::{Client, ShieldParams, Pool};2use alloy::signers::local::PrivateKeySigner;3 4#[tokio::main]5async fn main() -> anyhow::Result<()> {6 let signer: PrivateKeySigner = std::env::var("PRIVATE_KEY")?.parse()?;7 8 let client = Client::builder()9 .chain_id(4663) // Robinhood Chain mainnet10 .signer(signer)11 .build()?;12 13 // One call: swap, escrow, threshold-sign, mint into Orchard.14 let settlement = client15 .shield(ShieldParams {16 token: "0xUSDG_ADDRESS".parse()?,17 amount: 2_500_000_000u128, // 2,500 USDG (6 decimals)18 recipient_z_address: "u1xyz...orchard_unified_address".into(),19 memo: Some("Quarterly stock-token yield".into()),20 pool: Pool::Orchard,21 ..Default::default()22 })23 .await?;24 25 println!("{}", settlement.zcash_tx_id);26 println!("{:?}", settlement.status); // Status::Settled27 Ok(())28}Attest
Builds a Groth16 proof about shielded holdings. On a server the viewing key is read from your secret store into process memory and never transmitted — but it is on a machine you operate, which is a materially different risk profile from the browser prover.
attest.rs
rust
1use zrelay_sdk::{Client, AttestParams, Condition};2 3// The witness is built in-process. The viewing key never leaves the host.4let attestation = client5 .attest(AttestParams {6 viewing_key: viewing_key, // read from your secret store7 condition: Condition::MinZecBalance {8 amount: "100.0".into(),9 at_block_height: Some(2_654_900),10 },11 destination_contract: vault_address,12 })13 .await?;14 15// Groth16 proof, ready to submit from your own signer.16println!("{:?}", attestation.claim_hash);17println!("{} bytes", attestation.proof.len()); // ~192Server-side proving moves the risk, it does not remove it
A compromised host with a full viewing key in memory discloses the whole wallet history. Prefer an incoming viewing key (
ivk) where the predicate only concerns received value, scope the secret to a single process, and zero it as soon as the proof exists.Track
Both clients expose the settlement stages as a stream, so a worker can record progress instead of polling.
track.rs
rust
use futures::StreamExt;
let mut stream = client.track(&settlement.tracking_id).await?;
while let Some(update) = stream.next().await {
let update = update?;
println!("{:?} at {}", update.stage, update.at);
// Stage::EvmSequenced | FrostSigned | OrchardIncluded | Settled
}Errors
Failures are typed. The variants match the TypeScript ZRelayError.code values one-for-one, so a service that already handles the TS errors needs no new logic.
errors.rs
rust
1use zrelay_sdk::Error;2 3match client.shield(params).await {4 Ok(settlement) => println!("{}", settlement.zcash_tx_id),5 Err(Error::QuoteExpired { quote_id, .. }) => { /* re-quote */ }6 Err(Error::TransparentReceiverOnly { .. }) => { /* bad z-addr */ }7 Err(Error::InsufficientGasCoverage { .. }) => { /* attach surcharge */ }8 Err(Error::SlippageExceeded { .. }) => { /* route moved */ }9 Err(Error::ThresholdNotMet { tracking_id }) => { /* reclaim later */ }10 Err(e) => return Err(e.into()),11}Feature parity
- shield / quote / track
- Rust ✓ · Python ✓
- attest (server-side proving)
- Rust ✓ · Python ✓
- verify_attestation
- Rust ✓ · Python ✓
- Browser / WASM proving
- TypeScript only
- React bindings
- TypeScript only
Related
- TypeScript SDK — the browser client and the React hook.
- Smart contracts — what the attestation looks like on the receiving end.
- Run a relayer — the Rust relayer binary, which shares these crates.