From zerion-agent
Integrate Umbra SDK for Solana privacy: registration, master-seed derivation, encrypted deposits/withdrawals/UTXOs, scans/claims, MPC recovery, and Zerion CLI workflows.
npx claudepluginhub zeriontech/zerion-ai --plugin zerion-agentThis skill uses the workspace's default tool permissions.
Quick-reference for building privacy features on Solana with Umbra. Full
Checks USDC balances, sends transfers, approves spending, and verifies transactions on EVM chains and Solana using viem and @solana/kit.
Builds frontend Solana apps with Phantom Connect SDK for React, React Native, and browser, plus Helius for transaction signing, NFT minting, payments, real-time updates, and secure architecture.
Executes Alchemy CLI (@alchemy/cli) for live blockchain queries, transaction/NFT/token lookups, simulation, tracing, Solana RPC/DAS, webhooks, and app admin. For agent runtime tasks with local install.
Share bugs, ideas, or general feedback.
Quick-reference for building privacy features on Solana with Umbra. Full reference docs live at https://sdk.umbraprivacy.com/.
register (1× per wallet, idempotent — derives master seed deterministically)
│
├─ deposit (ATA → ETA, MPC) ────────────┐ if callback drops →
├─ withdraw (ETA → ATA, MPC) ────────────┤ getStagedSplRecovererFunction
├─ convert (MXE-only → Shared) │ getStagedSolRecovererFunction
└─ create UTXO │ (Pitfalls §6)
4 variants: {ATA,ETA} × {self,receiver}-claimable
│ if create fails → re-run (closeProofAccount auto-recovers)
▼
scan (indexer, cursor — UNTRUSTED, verify every commitment + proof)
│
▼
claim 3 variants: self→ETA, self→ATA, receiver→ETA
│ relayer submits, Arcium callback finalises (ETA variant)
▼
monitor + retry — DUPLICATE_OFFSET (409) means verify on-chain first
import { getUmbraClient } from "@umbra-privacy/sdk";
const client = await getUmbraClient({
signer: yourSigner, // IUmbraSigner
network: "mainnet", // | "devnet" | "localnet"
rpcUrl: "https://api.mainnet-beta.solana.com",
rpcSubscriptionsUrl: "wss://api.mainnet-beta.solana.com",
indexerApiEndpoint: "https://utxo-indexer.api.umbraprivacy.com",
relayerApiEndpoint: "https://relayer.api.umbraprivacy.com",
});
Signer factories (IUmbraSigner): createInMemorySigner(),
createSignerFromPrivateKeyBytes(bytes), createSignerFromKeyPair(kps),
createSignerFromWalletAccount(wallet, account) (Wallet Standard).
getUserRegistrationFunction, getUserAccountQuerierFunction, getEncryptedBalanceQuerierFunctiongetPublicBalanceToEncryptedBalanceDirectDepositorFunction, getEncryptedBalanceToPublicBalanceDirectWithdrawerFunctionget{Public,Encrypted}BalanceTo{Self,Receiver}ClaimableUtxoCreatorFunction. Self-claim only needs sender registered; receiver-claim needs all 3 recipient flags. Pre-check via getUserAccountQuerierFunction.getClaimableUtxoScannerFunction({ client }) → scan(treeIndex, startInsertionIndex, endInsertionIndex?) — POSITIONAL args, returns { selfBurnable, received, publicSelfBurnable, publicReceived } already proof-bundled.getReceiverClaimableUtxoToEncryptedBalanceClaimerFunction (native batching ≤4/proof), getSelfClaimableUtxoToEncryptedBalanceClaimerFunction, getSelfClaimableUtxoToPublicBalanceClaimerFunction (both MAX_UTXOS_PER_PROOF=1, SDK loops internally).getStagedSplRecovererFunction, getStagedSolRecovererFunction for dropped callbacks. Failed creates: just re-run.@umbra-privacy/web-zk-prover): 8 per-circuit factory functions, getCdnZkAssetProvider({ baseUrl? }) for assets, always wrap in a Web Worker (comlink). Browser 2–8s, Node 1–3s.getNetworkEncryptionToSharedEncryptionConverterFunction (MXE-only → Shared).generationIndex, derive the same KMAC keypair, and collide silently. Serialize creates per (signer, network).request_id. Poll GET /v1/claims/{id} to terminal state AND verify on-chain nullifier. HTTP 409 DUPLICATE_OFFSET means upstream-reserved — wait, recheck on-chain.closeProofAccount step. ETA-source MPC variants leak input-buffer rent (~4.85M lamports) unless you persist generationIndex and replay with the same value.optionalData (32 bytes) MUST be encrypted or hashed — NEVER plaintext. Plaintext orderId is observable on-chain and replay-attackable. Use Poseidon hash (ZK-bindable) or AES-GCM (recipient-decryptable).getStagedSplRecovererFunction, do not panic. Tokens stay in pool ATA; reclaim with no MPC, no ZK proof.UMBRA_MESSAGE_TO_SIGN verbatim. Any byte change → different seed → unrecoverable funds. Do not template, prepend, or trim.endInsertionIndex to indexer tip. Iterate every active tree (don't hardcode treeIndex=0). Open-ended scans time-bomb on large trees. Recommended chunk: 10_000.@umbra-privacy/sdk, /types, /constants, /errors. ZK proving is @umbra-privacy/web-zk-prover. All other sub-paths are internal layout — they will reorganize without notice.utxo-indexer.api.umbraprivacy.com): UNTRUSTED. Verify every commitment + Merkle proof.relayer.api.umbraprivacy.com): semi-trusted (claim submission only — cannot forge proofs).data-indexer.api.umbraprivacy.com): JSON event index for history/analytics, NOT used in claim path.UMBRAD2ishebJTcgCLkTkNUx1v3GyoAgpTRPeWoLykh, devnet 342qFp62fzTt4zowrVPhrDdcRLGapPCMe8w5kFSoJ4f4. Arcium Arcj82pX7HxYKLR92qvgZUAd7vGS1k4hQvAFcPATFdEQ.UMBRA_MESSAGE_TO_SIGN exported from @umbra-privacy/sdk. Source src/shared/protocol-constants.ts:65.BPS_DIVISOR = 16_384n (2^14, NOT 10_000). Formula: fee = baseFee + floor((amount - baseFee) * bps / BPS_DIVISOR). Fetch live values from on-chain fee config — hardcoded providers are 0/35 BPS defaults.Two families:
UmbraError (typed stage + code) — pipeline / validation errors
├─ AssertionError, ComputationMonitorError, TransactionError,
│ RegistrationError, CreateUtxoError, ClaimUtxoError, FetchUtxosError,
│ KeyConsistencyError, EncryptedDeposit/WithdrawalError, ConversionError,
│ QueryError, RpcError, InstructionError, CryptographyError
Error (NOT instanceof UmbraError) — transport
├─ IndexerError (retry 5xx with backoff)
└─ RelayerError (DUPLICATE_OFFSET 409 → verify on-chain)
Never retry: user-rejection signing errors, KeyConsistencyError,
ComputationMonitorError(stage="timeout"), RelayerError 409 DUPLICATE_OFFSET, InstructionError, Math/CryptographyAssertionError.
optionalData (CRITICAL §5).Zerion CLI manages Solana wallets, portfolio analysis, swaps, bridges, and off-chain signing. Umbra adds confidential payments on top of those wallets. The two integrate cleanly because both speak Wallet Standard and target Solana mainnet/devnet.
Wallet provisioning (zerion-wallet)
Use zerion wallet create or zerion wallet import to provision a
Solana wallet. Umbra wraps it via createSignerFromWalletAccount(wallet, account) — the same wallet object Zerion CLI exposes.
Portfolio inspection before depositing (zerion-analyze)
Before calling getPublicBalanceToEncryptedBalanceDirectDepositorFunction,
ask Zerion for the wallet's USDC / USDT / wSOL / UMBRA balance to confirm
the user has enough public-balance tokens for the deposit + the SOL
preflight (CRITICAL §2).
Token acquisition (zerion-trading)
If the wallet doesn't hold an Umbra-supported mint, use zerion swap to
acquire USDC / USDT / wSOL on Solana before depositing. Always validate
the mint against https://sdk.umbraprivacy.com/supported-tokens first
(CRITICAL §9).
Master-seed derivation (zerion-sign)
Umbra registration calls signer.signMessage(UMBRA_MESSAGE_TO_SIGN).
This routes through zerion sign-message for any wallet under Zerion CLI
management. Do NOT modify the message — CRITICAL §7. The sign message
constant is exported from @umbra-privacy/sdk verbatim.
Autonomous claim retry (zerion-agent-management)
Claim callbacks can drop (CRITICAL §3). Use Zerion's agent tokens +
policies to grant a scoped agent the ability to re-submit claims on
behalf of the user. Policy MUST gate retries on the on-chain nullifier
check before each re-submit, otherwise DUPLICATE_OFFSET 409s loop.
History view (zerion-analyze + Umbra data-indexer)
For end-user transaction history that mixes public Solana txs (from
Zerion) with private Umbra UTXO events, query Umbra's data-indexer
(data-indexer.api.umbraprivacy.com, JSON) and merge by timestamp on
the client side.
"Using my default Solana wallet, swap 100 USDC to wSOL on Jupiter, then deposit 50 wSOL to Umbra encrypted balance, then create a receiver-claimable UTXO of 10 wSOL to
<recipient.sol>."
Routing: zerion-trading (swap) → zerion-wallet (signer hand-off) →
this skill's deposit + create flows → zerion-sign (any extra signature
prompts).
The full skill content has been moved to https://sdk.umbraprivacy.com/ to keep this file under the 300-line constraint. Load the relevant page on demand:
offsets) — https://sdk.umbraprivacy.com/sdk/installation, https://sdk.umbraprivacy.com/pricing, https://sdk.umbraprivacy.com/supported-tokensWhen working on a specific task, fetch the matching page above with WebFetch instead of guessing — the site is the source of truth.