Registry and identity
getMetaAddressHex()
Returns the 98-byte stealth meta-address (V||S||S_ed) derived from the wallet signature.
resolveRecipient(input)
Resolve ANY supported recipient identity to a validated meta-address. This is
the one entry point for “who am I paying”: it accepts the same inputs you can pass to
sendStealthPayment({ recipient }).
Every path validates that both 33-byte halves of the result are valid compressed
secp256k1 points before returning. Unregistered, unset, or malformed identities throw
with a path-specific message.
ONS names (ONS.md). Subnames
of the Opaque Name Service parent resolve mirror-first: with
solana configured, the
SDK derives the mirror PDA from keccak256(name) and reads one Solana account, no
Ethereum RPC. Without solana
(or when the mirror has no record yet), it falls back to the canonical
OpaqueNameRegistry wildcard resolver over your EVM RPC. The mirror lags the canonical
record by Wormhole latency (eventually consistent, canonical-chain-wins). Defaults
(parent name, registry, mirror program) ship in @opaquecash/deployments; override
with ons: { parentName, registry, mirrorProgram }.
.sol names. With solana configured, the SDK reads the domain’s Records V2 TXT
record via the bundled @bonfida/spl-name-service reader and validates it as a CSAP
2.9 value (st:opq:-prefixed or raw 132-hex). Inject sns: { getRecord } to mock or
to read from a custom source.
ONS name management
Register, claim, and track ONS names for this wallet’s meta-address (see the naming guide for the consistency model):
ENS setup. The
*.eth path reads the com.opaque.meta text record (CSAP 2.9).
Pass an ENS-capable viem PublicClient (mainnet or Sepolia; your scan RPC usually is
not one), or inject a custom reader:
ipfs:// path fetches a DID document from public gateways
(ipfs.io, cloudflare-ipfs.com by default; tried in order) and extracts the
meta-address from either a service entry of type OpaqueStealthMetaAddress or a
top-level com.opaque.meta / opaqueMetaAddress field:
resolveRecipientMetaAddress(recipientAddress)
Lower-level Ethereum-only registry lookup. Unlike resolveRecipient, it does not throw
for unregistered recipients, so it suits “is this person on Opaque yet?” UI checks.
buildRegisterMetaAddressTransaction()
Encode registerKeys calldata without submitting.
registerMetaAddress(chain)
Submit meta-address registration on "ethereum" or "solana".
ethereumWalletClient / ethereumProvider (EVM) or solanaWallet (Solana).
isMetaAddressRegistered(chain)
Check if this wallet’s meta-address is registered.
Send
prepareStealthSend(recipientMetaAddressHex)
Derive one-time stealth material for sending. Pure crypto, no chain call.
sendStealthPayment(params)
High-level native send + announce (optional relay, optional delayed announce).
SendStealthPaymentResult:
{ chain, txHash, announceTxHash?, announcePromise?, stealthAddress, destination?, ephemeralPublicKey, metaAddressHex }
Solana bundles transfer + announce in one transaction (unless delayAnnouncement is
set, which forces two). Ethereum submits the transfer first, then the announce.
sendStealthPayment accepts only "ethereum" and "solana" and throws for
"starknet" (as does registerMetaAddress). On Starknet, send via
buildStarknetStealthSend below; meta-address registration goes through the
@opaquecash/stealth-chain-starknet adapter (SNIP-12 on-behalf) — see
Starknet.buildStarknetStealthSend(params)
Starknet send + announce (Starknet Sepolia, testnet-preview). Builds the unsigned
transfer and announce calls; the app’s connected Starknet wallet broadcasts them (the
one meta-address and wallet already span all three chains).
starknet: {} client option and @opaquecash/stealth-chain-starknet. See
Starknet for the full flow and caveats.
prepareGhostReceive()
Derive stealth receive material for your own meta-address (no announce yet).
buildAnnounceTransactionRequest(send)
Build StealthAddressAnnouncer.announce calldata.
buildAnnounceTransactionRequestForGhost(ephemeralPrivateKey)
Rebuild announce calldata from a stored ephemeral private key only.
Anonymity utilities
Two tools for growing the anonymity set around your payments (guide section 17).delayAnnouncement (send option)
Decouple send time from announce time: the value transfer is submitted immediately,
the announcement only after the delay, breaking the timing correlation between the two
on-chain events.
generateDummyAnnouncements(n)
Mint n decoy announcements. Each is a fully valid DKSAP announcement to a freshly
generated THROWAWAY meta-address whose private keys are discarded: on-chain it is
indistinguishable from a real payment announcement (valid curve points, correctly
derived view tag), but nobody will ever match or spend it.
buildDummyAnnouncementTransactions(n)
Convenience over generateDummyAnnouncements: ready-to-submit announce calldata.
Broadcast from any account, interleaved with real sends; announcements carry no value
and anyone may announce.
Scan and filter
fetchAnnouncementRows(chain, opts?)
Fetch ALL native announcements on a chain as indexer-shaped rows, unfiltered, with full
on-chain metadata. Raw input for the metadata-aware scanners (filterOwnedAnnouncements,
discoverTraitsV2, and legacy discoverTraits); unlike scan, nothing is dropped.
scan / fetchCrossChainAnnouncements).
filterOwnedAnnouncements(rows)
WASM scan: filter indexer rows to outputs owned by this wallet. Malformed announcements
(for example an ephemeral key that is not a valid curve point) are skipped, never fatal;
anyone can announce.
scan(opts)
Unified multichain inbox across all three supported chains.
Include
"starknet" (Starknet Sepolia, testnet-preview) only when the client was
created with the starknet: {} option. Starknet participates as a native scan chain,
not a Wormhole/UAB relay endpoint, so includeCrossChain adds no Starknet rows. See
Starknet.Balances
getBalancesFromAnnouncements(rows)
Filter owned outputs and sum balances per tracked token (EVM RPC).
getBalancesForOutputs(outputs)
Native balance per UnifiedOwnedOutput (multichain).
Sweep and keys
sweep(params)
Sweep the full native balance from a stealth output, or the full balance of token
(ERC-20 address / SPL mint) when set. closeAccount (Solana) reclaims the token-account rent.
buildGaslessTokenSweep and submit
the result to a relayer node with postGaslessSweep from @opaquecash/relayer-client; the
relayer fronts the gas and is reimbursed fee in-token on both Ethereum and Solana
(see Gasless token sweep). The gasless
forwarder is EVM/Solana only; Starknet sweeps self-fund instead (below).
buildStarknetSweep(params)
Sweep a Starknet stealth output (Starknet Sepolia, testnet-preview). Returns the sweep
call for the app to broadcast via starknet.js (EthSigner, v10+). There is no
fee-in-token gasless forwarder on Starknet: the counterfactual stealth account
self-funds its deploy_account fee.