# "Combo Meal" — 2+ Recipes

Combo Meals are the final frontier — every zkApp Chef's dream. They combine Recipes into very complex interactions, made 100% safe for execution against a private balance using the Cookbook.

For example, there is a [Combo Meal](https://github.com/Railgun-Community/cookbook/blob/main/src/combo-meals/liquidity-vault/uni-v2-like-add-liquidity-beefy-deposit-combo-meal.ts) that combines an "Add Liquidity" Recipe for Uniswap, with a "Deposit Vault" Recipe for Beefy. This gives a user the ability to add liquidity for a token pair on Uniswap, gain the LP token for that pair, and then deposit the LP token into a Beefy Vault to earn yield.

This all occurs in a single validated transaction call, saving network fees and making the user experience simple and delightful.

**Annotated Example:** Uniswap V2-Like (Add Liquidity) and Beefy Vault (Deposit LP Token)

```typescript
export class UniV2LikeAddLiquidity_BeefyDeposit_ComboMeal extends ComboMeal {
  // Simple name and description. Note that the name of the Uniswap clone is set
  // in the constructor.
  readonly config = {
    name: '[NAME] Add Liquidity + Beefy Vault Deposit Combo Meal',
    description:
      'Adds liquidity to a [NAME] Pool and deposits the LP tokens into a Beefy Vault.',
  };

  // Private variables set during the constructor.
  // In this case, it's a store for the two Recipes that we will combine together.
  private readonly uniV2LikeAddLiquidityRecipe: UniV2LikeAddLiquidityRecipe;
  private readonly beefyDepositRecipe: BeefyDepositRecipe;

  constructor(
    uniswapV2Fork: UniswapV2Fork,
    erc20InfoA: RecipeERC20Info,
    erc20InfoB: RecipeERC20Info,
    slippagePercentage: number,
    vaultID: string,
    provider: BaseProvider,
  ) {
    super();

    // The Recipes are fully initialized here. Note that 
    // input amounts are never passed into Recipe/Combo constructors.
    this.uniV2LikeAddLiquidityRecipe = new UniV2LikeAddLiquidityRecipe(
      uniswapV2Fork,
      erc20InfoA,
      erc20InfoB,
      slippagePercentage,
      provider,
    );
    this.beefyDepositRecipe = new BeefyDepositRecipe(vaultID);

    const forkName = UniV2LikeSDK.getForkName(uniswapV2Fork);
    this.config.name = `${forkName} Add Liquidity + Beefy Vault Deposit Combo Meal`;
    this.config.description = `Adds liquidity to a ${forkName} Pool and deposits the LP tokens into a Beefy Vault.`;
  }

  // This is a helper function that helps a user know how much of "ERC20 B" to unshield
  // for a given amount of "ERC20 A" (A and B make up the liquidity pair).
  // Accuracy is important, as the unshielding operation incurs a small % fee.
  getAddLiquidityAmountBForUnshield(
    networkName: NetworkName,
    targetUnshieldERC20AmountA: RecipeERC20Amount,
  ) {
    return this.uniV2LikeAddLiquidityRecipe.getAddLiquidityAmountBForUnshield(
      networkName,
      targetUnshieldERC20AmountA,
    );
  }

  // Returns the two Recipes that create this "Combo Meal." The steps of each 
  // Recipe will be strung together in series, and sandwiched altogether 
  // by an unshield and shield call. The outputs from the 1st Recipe will not 
  // get automatically re-shielded - they will get passed into the 2nd Recipe 
  // as inputs for its first step.
  // In this way, we can create in a single transaction call, minimizing fees and 
  // building a complex DeFi behavior as a sum of simple parts.
  protected async getRecipes(): Promise<Recipe[]> {
    return [this.uniV2LikeAddLiquidityRecipe, this.beefyDepositRecipe];
  }
}
```


---

# 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/write/combo-meal.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.
