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