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
  • Creating a limit order
  • Retracting a limit order
  • Modifying a limit order

Limit orders

PreviousMarket ordersNextKeeper Bots

Last updated 5 days ago

Limit orders works by creating offers on mangrove via a shared maker contract: MangroveOrder. In addition, each user will have an associated router (called UserRouter here). This router will hold our approvals and will be called by MangroveOrder to fetch and send back the tokens when the offer are matched.

On mangrove order there are 4 types of orders:

  • GTC (Good Til Cancelled): Will do a market order up to the given price and post the residual volume as an order mangrove.

  • IOC (Immediate or cancel): Equivalent to a markt order only

  • FOK (Fill or kill): Only does a market order, if the market is not filled, then we revert

  • PO (Post only): Does not try a market order and immediately posts order to mangrove.

An order posted on Mangrove has an optional expiry date. Because an offer can fail, the creator of the offer has to deposit a provision. On failure (missing approvals for example), the provision will be used as a bounty sent to the person that tried to execute the offer. This provision can be withdrawn anytime once the offer is not live anymore, and if it has not been used.

The offer is consumed as follows:

The user router is a deterministic address linked to each user. It will be deployed in initial take call if not already. So the first thing to do is to give approval to this router (even though it has no code yet). For infinite approval implementation, see Market orders.

src/router.ts
import type { Address } from "viem";
import { client } from "./client";

export async function getUserRouter(): Promise<Address> {
  return client.getUserRouter({
    user: client.account.address,
  });
}

Creating a limit order

So let's implement a post only limit buy order for 1 ETH with 2500 USDC:

src/limit-order.ts
import { limitOrderParams } from "@mangrovedao/mgv/builder";
import { giveAllowanceIfNeeded } from "./allowance";
import { getBook } from "./book";
import { mangroveConfig } from "./config";
import { getOpenMarkets } from "./markets";
import { getUserRouter } from "./router";
import { BS, Order } from "@mangrovedao/mgv/lib";
import { parseEther, parseUnits } from "viem";
import { client } from "./client";

const markets = await getOpenMarkets();

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

const router = await getUserRouter();

// buying the token

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

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

const book = await getBook(market);

const params = limitOrderParams(market, {
  orderType: Order.PO, // post only order
  baseAmount: parseEther("1"), // buy 1 ETH
  quoteAmount: parseUnits("2500", 6), // 2500 USDC
  restingOrderGasreq: 250_000n, // 250k gas (fixed)
  bs: BS.buy,
  book,
  // no expiry or expiry timestamp in seconds
  expiryDate: undefined, 
});

const {
  // takerGot, takerGave, bounty and fee should be 0 since PO
  // offerId should be defined (not 0)
  result: { takerGot, takerGave, bounty, fee, offerId, offerWriteData },
  request,
} = await client.simulateContract({
  address: mangroveConfig.mgvOrder,
  ...params,
  account: client.account,
});

const tx = await client.writeContract(request);

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

console.log(receipt.status, receipt.transactionHash);

Retracting a limit order

To cancel or modify a limit order, you need to have the offer id, as well as the market side, and then just pass it as params:

src/cancel-limit.ts
import { removeOrderParams } from "@mangrovedao/mgv/builder";
import { BS } from "@mangrovedao/mgv/lib";
import { getOpenMarkets } from "./markets";
import { mangroveConfig } from "./config";
import { client } from "./client";

const markets = await getOpenMarkets();

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

const params = removeOrderParams(market, {
  offerId: 1n,
  bs: BS.buy,
  deprovision: true, // withdraw the provisions (true by default)
});

// returns the withdrawn provision
const { result: provision, request } = await client.simulateContract({
  address: mangroveConfig.mgvOrder,
  ...params,
  account: client.account,
});

const tx = await client.writeContract(request);

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

console.log(receipt.status, receipt.transactionHash);

Modifying a limit order

In order to modify a limit order, any updateOrder***Params function may be used to build the modification, and then it should call MangroveOrder with these params.

creating an order (via MangroveOrder)
consuming an offer (via Mangrove Order)