Getting Started
@mirageprivacy/sdk is the TypeScript SDK for private transfers on the Mirage protocol. It wraps the full transfer lifecycle (fee estimation, token approvals, escrow deployment, compliance, encrypted signal submission, and transfer polling) behind a single async generator flow.
Install
npm install @mirageprivacy/sdk viemviem is a peer dependency. The SDK does not connect wallets or manage framework state, so bring your own wallet client (AppKit, MetaMask, wagmi, etc.).
Quick start
import { networks, prepareTransfer, getTokenMetadata, getTokenBalance } from "@mirageprivacy/sdk";
import { createPublicClient, createWalletClient, http, custom, parseUnits, formatUnits } from "viem";
import { mainnet } from "viem/chains";
const publicClient = createPublicClient({ chain: mainnet, transport: http() });
const walletClient = createWalletClient({ chain: mainnet, transport: custom(window.ethereum) });
const TOKEN = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"; // USDC
const RECIPIENT = "0x...";
const token = await getTokenMetadata(TOKEN, publicClient);
const balance = await getTokenBalance(TOKEN, walletClient.account.address, publicClient);
const amount = parseUnits("100", token.decimals);
// 1. Preview fees
const prepared = await prepareTransfer({
tokenAddress: TOKEN,
recipientAddress: RECIPIENT,
amount,
walletClient,
publicClient,
network: networks.ethereum,
});
console.log(
`Service fee: ${formatUnits(prepared.fees.serviceFee.amount, token.decimals)} ${token.symbol}`,
);
// 2. Execute the transfer
for await (const event of prepared.execute()) {
switch (event.step) {
case "fees": console.log("Fees calculated"); break;
case "approve": console.log(`Approved: ${event.hash}`); break;
// Persist event.secrets here. Without them a failed transfer is unrecoverable.
case "deploy": await saveSecrets(event.secrets); break;
case "signal": console.log("Signal sent"); break;
case "transfer": console.log(`Delivered: ${event.transfer.transactionHash}`); break;
case "complete": console.log(`Done: ${event.transfers.length} transfers`); break;
}
}All amounts are bigint values in raw token units. Use viem's parseUnits and formatUnits at the boundary; the SDK never formats for display.
Networks
Built-in configs ship for ethereum, sepolia, and tempo. Only ethereum is a production network.
import { networks, createNetworkConfig } from "@mirageprivacy/sdk";
// Use a built-in config directly
const network = networks.ethereum;
// Or customize transport and attestation policy.
const custom = createNetworkConfig("ethereum", {
rpcUrl: "https://my-rpc.example.com",
attestation: { maxAgeSecs: 180 }, // merged, keeps the other attestation values
});Merging is field-by-field so a partial override cannot silently drop sibling values such as attestation.required. Gas profiles and fee parameters are no longer part of the network config: they are owned by the API.
What the SDK does not do
- Wallet connection (use AppKit, MetaMask, etc.)
- ENS resolution
- Gas and price subscriptions (it fetches on demand; you manage polling)
- Framework-specific state (React hooks, Svelte stores, etc.)
- Display formatting (use viem's
formatUnits)