SDK Overview
- Numbers returned by functions are either plain JavaScript
number
orbig.js
instances. Some functions with names ending inRaw
may returnethers.BigNumbers
. - As input, numbers can be as plain JavaScript
numbers
,big.js
instances, but also astring
.
The precision used when dividing is 20 decimal places.
Overrides
All API functions that produce a signed transaction can be equipped with the usual ethers.js
overrides as optional parameters.
Mangroveβ
The root class of the API. Use Mangrove.connect
to get an instance of it. Here are a few possibilities:
mgv = await Mangrove.connect(window.ethereum); // web browser
mgv = await Mangrove.connect('http://127.0.0.1:8545'); // HTTP provider
mgv = await Mangrove.connect(); // Uses Ethers.js fallback mainnet (for testing only)
mgv = await Mangrove.connect('rinkeby'); // Uses Ethers.js fallback (for testing only)
// Init with private key (server side)
mgv = await Mangrove.connect(
'https://mainnet.infura.io/v3/_your_project_id_', // provider
{
privateKey: '0x_your_private_key_', // preferably with environment variable
});
// Init with HD mnemonic (server side)
mgv = await Mangrove.connect( {
signer: myEthersWallet
});
You can test you are indeed connected to the deployed Mangrove by asking for the current global configuration of Mangrove:
config = await mgv.config()
The above mgv
object gives you access to the MgvToken
, Market
and OfferLogic
(allowing one to connect to an on-chain offer logic) and LiquidityProvider
(an abstraction layer to pass bids and asks on Mangrove) objects.
mgv.contract
gives access to the standard ethers.js
contract and allows one to interact with the deployed Mangrove
using low-level ethers.js
calls. Hence, await mgv.contract.f(...)
will produce the ethers.js call to Mangrove (signed when needed by the signer
provided to the connect
function).
MgvTokenβ
This class provides easy means to interact with a deployed contract on the standard EIP-20. To obtain an instance use:
mgvTkn = await mgv.token("<tokenSymbol>"); // e.g "DAI", "WETH", "amDAI", etc.
with the above MgvT
object one has access to standard calls using human readable input/outputs. For instance:
await mgvTkn.approve("<spender>"); // gives infinite approval to spender
await mgvTkn.approve("<spender>",0.5); // gives allowance to spend 0.5 token units to spender
await mgvTkn.contract.approve("<spender>", mgvTkn.mgv.toUnits(0.5)); // ethers.js call
Note that Mangrove's API deals with token decimals automatically (see definitions in constants.ts
).
MgvToken.contract
gives access to the ethers.js
contract allowing one to interact with the deployed contract using low level calls (for instance if the token has functions that are do not belong to the ERC20 standard).
Marketβ
The Market
class is an abstraction layer to interact with Mangrove as a liquidity taker, using standard market buy and sell orders. To obtain one instance use:
//connect to a (base,quote) market with default options
mgvMarket = await mgv.connect({base:"<base_symbol>", quote:"<quote_symbol>"});
// connect to the market, caching the first 50 best bids and asks
mgvMarket = await mgv.connect({base:"<base_symbol>", quote:"<quote_symbol>", maxOffers: 50});
Upon connection to a market, the API subscribes to events emanating from Mangrove in order to maintain a local cache of the order book. One may increase the size of the cache by using mgv.connect({..., maxOffers:<size of the book>})
.
For debugging purpose, the class provides a console of the current state of bids and asks posted on Mangrove. For instance to display the bid offers on Mangrove on this market:
// Pretty prints to console the bid offers, showing offer `id`, offer `volume` and offer `price
await mgvMarket.consoleAsks(["id", "volume", "price"]);
Market
instances allow one to subscribe to markets events using:
const f (event) => ...; // what you want to do when receiving the event
mgvMarket.subscribe (f);
To unsubscribe f
from market events simply use mgvMarket.unsubscribe(f)
.
Market events are records of the following kinds:
{type: 'OfferRetract', ba:'asks'|'bids', offer:Market.Offer}
when an ask or a bidoffer
is removed from the book{type: 'OfferWrite', ba:'asks'|'bids', offer:Market.Offer}
when a bid or askoffer
is added to the book (or updated){type:'OfferFail', ba:'asks'|'bids', taker:string, 'takerWants':Big, takerGives:Big, mgvData:string, offer:Market.Offer}
whenoffer
failed to deliver. Note thatmgvData
is a bytes32 string encoding of the fail reason (according to Mangrove).{type: 'OfferSuccess', ba: 'asks'|'bids', taker: string, takerWants:Big, takerGives:Big, offer:Market.Offer}
whenoffer
was successfully executed (possibly on a partial fill wheneveroffer.gives
>takerWants
).
and where Market.Offer
has the following main fields:
id: number; // the id of the executed offer
maker: string; // address of the maker (contract/wallet) in charge of the offer
gasreq: number; // gas required by the offer
volume: Big; // total volume proposed
price: Big; // price offered
OfferLogicβ
A reactive offer is managed by a smart contract which implements its logic. One may use the API to post liquidity on Mangrove via a deployed logic that complies to the IOfferLogic interface. To do so, one first need an OfferLogic
instance:
const mgvLogic = mgv.offerLogic("0x..."); // NB not an async call
The mgvLogic
instance offers various function to query and set the underlying contract state, for instance:
await mgvLogic.setAdmin("0x..."); // set new admin
await mgvLogic.redeemToken("DAI", 100); // transfer 100 DAI from contract's signer account to signer's EOA
await mgvLogic.depositToken("WETH", 0.1); // put 0.1 WETH from signer's EOA to contract's account
const bal = await mgvLogic.tokenBalance("USDC"); // returns signer's balance of USDC on the contract
const mgvLogic_ = await mgvLogic.connect(newSigner); // returns a new OfferLogic instance with a new signer
cosnt gasreq = await mgvLogic.getDefaultGasreq(); // returns the gas required (by default) for new offers of this contract
await mgvLogic.setDefaultGasreq(200000); // default gasreq setter
When using an offer logic that inherits from the MultiUser.sol
solidity class, one should always use the above depositToken
(and tokenBalance
) instead of sending tokens (or querying balance) directly to the contract which might result in the tokens being burnt (as only depositToken
will increase user balance on the contract).
LiquidityProviderβ
A LiquidityProvider
instance is the object one needs to post bids and asks on a Mangrove market. It can be used to post a direct offer or to post an offer relying on some on-chain logic.
To act as a direct liquidity provider on a mgvMarket
you must obtain a LiquidityProvider
instance from an mgv
object using:
const mgvDirectLP = await mgv.liquidityProvider(mgvMarket);
The EOA providing the liquidity for ask and bid offers emanating from a direct liquidity provider is the address of the mgv
's signer provided at the creation of Mangrove instance.
For more complete experience of Mangrove capabilities, on may rather post bids and asks via an offer logic mgvLogic
. To do so, one does:
const mgvOnchainLP = await mgvLogic.liquidityProvider(mgvMarket);
Besides posting offers on Mangrove, a LiquidityProvider
instance mgvLP
gives access to various useful functions such as:
const missingAskProvision = await mgvLP.computeAskProvision();
const missingBidProvision = await mgvLP.computeBidProvision();
which return the missing provision (in native tokens) this liquidity provider needs to deposit on Mangrove if it wishes to post a new bid or ask. When provision is missing, one may fund Mangrove using:
const ethersTx = await mgvLP.fundMangrove(missingAskProvision);
await ethersTx.wait(); // waiting for the funding tx to be confirmed