# Use your zkApp privately

Given a full Recipe and its inputs, [RAILGUN Wallet SDK](/developer-guide/wallet/transactions/cross-contract-calls.md) will generate a [zero-knowledge proof](https://docs.railgun.org/wiki/learn/privacy-system/zero-knowledge-cryptography) and a final serialized transaction for the RAILGUN Relay Adapt contract.

This final transaction can be submitted to the blockchain by any wallet, including a [Broadcaster](/developer-guide/wallet/broadcasters.md).

{% code title="cook-recipe-example.ts" %}

```typescript
import {
  RecipeERC20Info,
  ZeroXSwapRecipe,
  RecipeInput,
  RecipeOutput
} from '@railgun-community/cookbook';
import {
  NetworkName,
} from '@railgun-community/shared-models';

const sellERC20Info: RecipeERC20Info = {
  tokenAddress: '0x6B175474E89094C44Da98b954EedeAC495271d0F', // DAI
  decimals: BigInt(18)
}

const buyERC20Info: RecipeERC20Info = {
  tokenAddress: '0xdac17f958d2ee523a2206206994597c13d831ec7', // USDT
  decimals: BigInt(18)
}

const slippagePercentage = 0.05;

const swap = new ZeroXSwapRecipe(sellERC20Info, buyERC20Info, slippagePercentage);

// Inputs that will be unshielded from private balance.
const unshieldERC20Amounts = [
  { 
    ...sellERC20Info,
    amount: BigInt('0x10'), // hexadecimal amount
  }
];

const recipeInput: RecipeInput = { NetworkName.Ethereum, unshieldERC20Amounts };
const {
  crossContractCalls,
  erc20AmountRecipients,
  nftRecipients,
  feeERC20AmountRecipients,
  minGasLimit,
} = await swap.getRecipeOutput(recipeInput);

// Outputs to re-shield after the Recipe multicall.
const shieldERC20Addresses = erc20AmountRecipients.map(({tokenAddress}) => tokenAddress);

// RAILGUN Wallet will generate a [unshield -> call -> re-shield] 
// transaction enclosing the Recipe multicall.

const { gasEstimate } = await gasEstimateForUnprovenCrossContractCalls(
    ...
    unshieldERC20Amounts,
    ...
    shieldERC20Addresses,
    ...
    crossContractCalls,
    ...
)
await generateCrossContractCallsProof(
    ...
    unshieldERC20Amounts,
    ...
    shieldERC20Addresses,
    ...
    crossContractCalls,
    ...
)
const { transaction } = await populateProvedCrossContractCalls(
    ...
    unshieldERC20Amounts,
    ...
    shieldERC20Addresses,
    ...
    crossContractCalls,
    ...
);

// Submit transaction to RPC.
await wallet.sendTransaction(transaction);

// Note: use @railgun-community/waku-broadcaster-client to submit 
// through a Broadcaster instead of signing with your own wallet.
```

{% endcode %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.railgun.org/developer-guide/cookbook/use-your-zkapp-privately.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
