Mangrove
Developper
Developper
  • Welcome
  • Protocol
    • Introduction
    • Technical References
      • Overview
      • Ticks, ratios, and prices
      • Offer-list
        • Views on offers
      • Market-order
        • Delegation
      • Creating & Updating offers
        • Maker contract
        • Offer provisions
        • Gas requirement
        • Public data structures
        • Executing offers
      • Cleaning offers
      • Governance-parameters
        • Global variables
        • Local variables
        • Data structures and views
      • Periphery Contracts
        • MgvReader
        • MgvOracle
      • Literate Source Code
    • Background
      • Taking available liquidity
      • Making liquidity available
      • Reneging on offers
  • Strat Lib
    • What is the Strat Library?
    • Getting-started
      • Set Up Your Local Environment
      • Post a Smart Offer
    • Guides
      • Unlocking liquidity
      • Reposting an offer in the posthook
      • Using last look to renege trades
      • Determining gas requirements
      • Creating a Direct contract
      • Deploying your contract
      • Testing a maker contract
      • Safe offer logic guidelines
      • Approvals
    • Technical references
      • Principal hooks
      • Liquidity routing
      • API preferences
        • Core
          • SRC
            • IMangrove
        • Strats
          • SRC
            • Strategies
              • MangroveOffer
              • MangroveOrder
              • Integrations
                • AaveV3Borrower
                • AaveV3BorrowerImplementation
                • AaveV3BorrowerStorage
                • AaveV3Lender
                • CompoundModule
              • Interfaces
                • IForwarder
                • ILiquidityProvider
                • IOfferLogic
                • IOrderLogic
              • Offer_forwarder
                • Abstract
                  • Forwarder
              • Offer_maker
                • Abstract
                  • Direct
                • Market_making
                  • Kandel
                    • AaveKandel
                    • AaveKandelSeeder
                    • KandelSeeder
                    • Abstract
                      • AbstractKandelSeeder
                      • CoreKandel
                      • DirectWithBidsAndAsksDistribution
                      • GeometricKandel
                      • HasIndexedBidsAndAsks
                      • KandelLib
                      • TradesBaseQuotePair
              • Routeurs
                • SimpleRouter
                • Abstract
                  • AbstractRouter
                • Integrations
                  • AavePooledRouter
                  • HasAaveBalanceMemoizer
              • Utils
                • AccessControlled
              • Vendor
                • AAVE
                  • V3
                    • Contracts
                      • Dependencies
                        • Oppenzeppelin
                          • Contracts
                            • IERC20
                      • Interfaces
                        • IAToken
                        • IAaveIncentivesController
                        • IAaveOracle
                        • ICreditDelegationToken
                        • IInitializableAToken
                        • IPool
                        • IPoolAddressesProvider
                        • IPriceOracleGetter
                        • IScaledBalanceToken
                      • Protocol
                        • Libraries
                          • Configurations
                            • ReserveConfiguration
                          • Helpers
                            • Errors
                          • Types
                            • DataTypes
                    • Periphery
                      • Contracts
                        • MISC
                          • Interfaces
                            • IEACAggregatorProxy
                        • Rewards
                          • Interfaces
                            • IRewardsController
                            • IRewardsDistributor
                            • ITransferStrategyBase
                          • Libraries
                            • RewardsDataTypes
                • Compound
                  • CarefulMath
                  • Exponential
                  • ExponentialNoError
                  • ICompound
    • Background
      • Building Blocks
        • MangroveOffer
        • Direct
        • Forwarder
  • Vaults
    • Understanding vaults
      • Oracles
    • Managing a vault (CLI)
      • Deploying an oracle
      • Creating a vault
      • Monitoring the vault
      • Setting the vault position
      • Setting the fee data
      • Rebalancing
      • Adding or removing liquidity
    • Custom interactions
      • Oracles
      • Vault Factory
      • Managing a vault
        • Setting the position
        • Rebalancing
        • Setting a manager
        • Setting fee
  • Interacting with JS
    • Getting started
  • Query mangrove
  • Market orders
  • Limit orders
  • Keeper Bots
    • Keeper Bots
    • Guides
      • Using borrowed funds for cleaning
    • Backgroud
      • The role of cleaning bots in Mangrove
      • The role of gas price updater bots in Mangrove
  • Adresses
    • Deployment Addresses
  • Quick Links
    • Glossary
    • Website
    • Whitepaper
Powered by GitBook
On this page
  • Giving allowance
  • Making the market order

Market orders

PreviousQuery mangroveNextLimit orders

Last updated 5 days ago

Here is a how a market order works:

In order to make a market order on mangrove, you call the market order function on mangrove (with a given market, limit price, and volume), then Mangrove will take your tokens and send you back the resulting tokens. This trade is the result of the consumption of the book queried in Query mangrove minus the possible changes between the book query and the actual transaction time (thus you can deine a slippage tolerance by increasing/decreasing the expected maximum price).

Giving allowance

From that, we infer that we need to give allowance to mangrove first (infinite for testing here):

src/allowance.ts
import { erc20Abi, maxUint128, maxUint256, type Address } from "viem";
import { client } from "./client";

export async function giveAllowanceIfNeeded(token: Address, spender: Address) {
  const allowance = await client.readContract({
    address: token,
    abi: erc20Abi,
    functionName: "allowance",
    args: [client.account.address, spender],
  });

  if (allowance < maxUint128) {
    const tx = await client.writeContract({
      address: token,
      abi: erc20Abi,
      functionName: "approve",
      args: [spender, maxUint256],
    });

    return client.waitForTransactionReceipt({
      hash: tx,
    });
  }
  return null;
}

Making the market order

Then what you can do is get the book and make a local simulation of the trade to get the maximum exepected offer price (tick), then add the slippage you want to this, and finally broadcast the trade. Ticks is always the log of the price base 1.0001 that is relative the each semi market. So a higher tick always means a worst price for the taker, a better one for the maker. Here is the full implementation of a market order to buy 1 ETH:

src/market-order.ts
import { marketOrderSimulation } from "@mangrovedao/mgv";
import { giveAllowanceIfNeeded } from "./allowance";
import { getBook } from "./book";
import { mangroveConfig } from "./config";
import { getOpenMarkets } from "./markets";
import { BS, getSemibooksOLKeys } from "@mangrovedao/mgv/lib";
import { parseEther } from "viem";
import { marketOrderByTickParams } from "@mangrovedao/mgv/builder";
import { client } from "./client";

const markets = await getOpenMarkets();

const market = markets[0];
if (!market) {
  throw new Error("No market found");
}

// buying the token

// give allowance for the quote asset
const allowance = await giveAllowanceIfNeeded(
  market.quote.address,
  mangroveConfig.mgv
);

if (allowance) {
  if (allowance.status === "success") {
    console.log("Allowance given");
  } else {
    console.error("Allowance failed");
    process.exit(1);
  }
}

const book = await getBook(market);

const {
  // baseAmount, // should be at most 1 ETH
  // quoteAmount, // amound to send (assumed to have enough)
  // feePaid,
  maxTickEncountered,
  fillWants,
  fillVolume,
} = marketOrderSimulation({
  book,
  bs: BS.buy,
  base: parseEther("1"), // buy 1 ETH
});

const { asksMarket } = getSemibooksOLKeys(market);

const params = marketOrderByTickParams({
  maxTick: maxTickEncountered + 100n, // 1% slippage tolerance,
  fillVolume,
  fillWants,
  olKey: asksMarket,
});

const {
  result: [takerGot, takerGave, bounty, feePaid], // result of onchain simulation
  request,
} = await client.simulateContract({
  address: mangroveConfig.mgv,
  ...params,
  account: client.account,
});

const tx = await client.writeContract(request);

const receipt = await client.waitForTransactionReceipt({
  hash: tx,
});

console.log(receipt.status, receipt.transactionHash);
market order on mangrove