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 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.
exportclassUniV2LikeAddLiquidity_BeefyDeposit_ComboMealextendsComboMeal {// 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.privatereadonly uniV2LikeAddLiquidityRecipe:UniV2LikeAddLiquidityRecipe;privatereadonly 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 =newUniV2LikeAddLiquidityRecipe( uniswapV2Fork, erc20InfoA, erc20InfoB, slippagePercentage, provider, );this.beefyDepositRecipe =newBeefyDepositRecipe(vaultID);constforkName=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, ) {returnthis.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.protectedasyncgetRecipes():Promise<Recipe[]> {return [this.uniV2LikeAddLiquidityRecipe,this.beefyDepositRecipe]; }}