<!--
Sitemap:
- [Welcome to Kakushi 隠し](/index): Kakushi is a private execution layer for institutions building on stablecoin rails.
- [What is Kakushi](/introduction/what-is-kakushi): Money is private.
- [How Kakushi compares](/introduction/how-kakushi-compares): Most privacy systems ask you to move to a new public chain, or give up disclosure entirely. Kakushi does neither.
- [Using Kakushi with AI](/introduction/using-kakushi-with-ai): Every page in these docs is available as plain markdown for use with language models.
- [Quickstart](/quickstart): This is the ten minute path.
- [Zones and the trust model](/concepts/zones-and-trust): A zone is a private blockchain only you can see inside, with a public chain's proofs underneath.
- [The portal](/concepts/the-portal): Money walks in as public USDC and becomes private the moment it crosses.
- [Accounts and custody](/concepts/accounts-and-custody): Your existing wallet address is already a Kakushi account. Nothing to deploy, nothing to enroll.
- [Bring your own address](/concepts/bring-your-own-address): A zone account is just an address, the one an auth key recovers to, with nothing deployed.
- [Virtual addresses](/concepts/virtual-addresses): Hand every customer their own address, the way a bank hands out virtual account numbers.
- [Private transfers](/concepts/private-transfers): Pay fifty thousand people and publish zero salaries.
- [Settlement and composability](/concepts/settlement-and-composability): Two institutions settle in real time without sharing a ledger or seeing each other's books.
- [Proofs and the verifier](/concepts/proofs-and-the-verifier): You cannot fake a balance, and you can prove you are solvent without showing a single customer.
- [Fees and gas](/concepts/fees-and-gas): Your users never hold ETH and never see gas. They pay in the dollars they are already sending.
- [Privacy and disclosure](/concepts/privacy-and-disclosure): The public sees nothing, you see everything, the regulator sees what the law entitles them to.
- [Zone policies](/concepts/zone-policies): Compliance is built into the zone. You configure your program; the substrate enforces it on every transfer.
- [Onboard a customer](/guides/onboard-a-customer): Two calls and a webhook, and your customer has a private on-chain account.
- [Accept deposits](/guides/accept-deposits): Anyone with funds on the host chain can pay into your zone, and it lands as a private balance for your user.
- [Make private transfers](/guides/private-transfers): One call moves money privately. One call pays a whole payroll.
- [Process withdrawals](/guides/withdrawals): Burn inside, release canonical USDC outside, in one call.
- [Settle between zones](/guides/settle-between-zones): Send money to another institution's zone like it is a withdrawal. It is interbank settlement.
- [Handle webhooks](/guides/webhooks): React to money moving. Do not poll for it.
- [Non-custodial integration](/guides/non-custodial-integration): The user signs on their device. You never hold the key, and you still cannot move their money.
- [Compliance and disclosure](/guides/compliance): You hold the whole record. Disclosure is an export, not a negotiation with the protocol.
- [SDK reference](/sdk-reference): The look-it-up layer.
- [Connect and EVM reference](/connect-and-evm-reference): The chain-level integration detail.
- [Run a zone](/run-a-zone): Most operators never run any infrastructure.
- [Protocol spec](/protocol-spec): The deep technical layer, for auditors and engineers integrating below the SDK.
- [Resources](/resources): See Key concepts for the working vocabulary, expanded throughout Core concepts.
- [Product updates](/changelogs/product-updates): Product and protocol changes, release by release.
- [SDK changelogs](/changelogs/sdk): Version-by-version changes to the Kakushi SDK.
- [Node network upgrades](/changelogs/node-network-upgrades): Zone node releases and network upgrades.
-->

# Non-custodial integration

When the user holds their own key, you orchestrate everything around the money movement but never touch the key. The user signs on their device, and the node itself enforces that no one but the key holder can move that account's funds. That is the guarantee, and it is enforced by the protocol, not by your good intentions.

```mermaid
sequenceDiagram
  actor User as User (holds the key)
  participant SDK as Kakushi SDK (no keys)
  participant Zone as Zone RPC
  Note over User,Zone: The SDK never holds keys. The account signs locally.
  User->>SDK: provide a viem Account or ethers Signer
  SDK->>SDK: build the transaction and the EIP-712 auth token
  SDK->>User: request signatures (token and transaction)
  User-->>SDK: signed token and signed transaction
  SDK->>Zone: eth_sendRawTransaction (token in x-authorization-token header)
  Zone->>Zone: recover signer, require from == token address
  Zone-->>SDK: accepted
```

```ts
import { toViemAccount } from "@privy-io/react-auth";

// the account comes from the user's embedded wallet; the key stays on their device
const account = await toViemAccount(embeddedWallet);

// 1. prepare the unsigned zone transaction (nonce, gas, chainId set here)
//    no signer is present at build time, so `from` is passed explicitly as an address
const { unsignedTx } = await kakushi.transfers.prepare({
  from: account.address, to: "0xRecipientZoneAddress", amount: "40.00", token: "USDC",
});

// 2. the user signs locally, in their wallet, nothing is broadcast
const signedTx = await account.signTransaction(unsignedTx);

// 3. submit over the authenticated RPC; the user's auth token in the header
//    matches the transaction's signer, which is what the node requires
await kakushi.transfers.submit(signedTx);
```

The node's rule is absolute: a transaction only lands when its recovered `from` equals the address of the auth token in the request header. So even you, the operator, cannot move a user's funds without the user's signature.

:::warning
Injected wallets such as MetaMask work for non-custodial signing today. Because the auth token is EIP-712 typed data, any standard wallet signs it through `eth_signTypedData_v4`, and the prepare, sign, submit flow above is unchanged. Embedded and programmatic wallets like Privy work the same way. The only thing still deferred to a later release is smart accounts (multiple owners, thresholds, passkeys), which is a separate capability, not a wallet limitation. See the Privy examples for React (key on the user's device) and Node (server-held key).
:::
