💻
Developer Guide
  • Wallet SDK
    • Wallet Overview
    • Getting Started
      • 1. Start the RAILGUN Privacy Engine
      • 2. Build a persistent store for artifact downloads
      • 3. Load a Groth16 prover for each platform
      • 4. Add networks and RPC providers
      • 5. Set up a debug logger
    • Private Wallets
      • RAILGUN Wallets
      • View-Only Wallets
      • Encryption Keys
    • Private Balances
      • Balance and Sync Callbacks
      • Updating Balances
      • QuickSync
    • Transactions
      • Shielding
        • Shield ERC-20 tokens
        • Shield base token
        • Shield NFTs
      • Private Transfers
        • Private ERC-20 Transfers
        • Private NFT Transfers
      • Cross-Contract Calls
      • Unshielding
        • Unshield ERC-20 tokens
        • Unshield base token
        • Unshield NFTs
      • UX: Private Transactions
    • Broadcasters
  • Cookbook SDK
    • Cookbook Overview
    • Recipe Guide: Write a zkApp
      • "Step" — A smart contract call
      • "Recipe" — Steps in series
      • "Combo Meal" — 2+ Recipes
    • Use your zkApp privately
  • Engine SDK
    • Engine Overview
  • ZK Account Abstraction
    • Account Abstraction Overview
    • Getting started with the contracts
    • Wallets
    • State Structure
    • Example Primitives
Powered by GitBook
On this page
  1. Cookbook SDK
  2. Recipe Guide: Write a zkApp

"Combo Meal" — 2+ Recipes

Previous"Recipe" — Steps in seriesNextUse your zkApp privately

Last updated 1 year ago

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 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)

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];
  }
}
Combo Meal