From 6c7853318e9d9260db7bf83119bd6662059f6a21 Mon Sep 17 00:00:00 2001 From: frkralj Date: Mon, 4 Sep 2023 16:19:42 +0200 Subject: [PATCH 01/38] remove Kandel infobox + draft Kandel param. recommendation --- docs/kandel/README.md | 4 --- .../details-on-strats/details-on-strats.md | 3 -- .../choosing-parameters.md | 29 +++++++++++++++++++ .../how-does-kandel-work.md | 3 -- .../more-on-failing-offers.md | 5 +--- .../kandel/how-does-kandel-work/parameters.md | 4 --- .../step-by-step-visual-explanation.md | 3 -- .../how-does-kandel-work/strategy-reserve.md | 5 +--- .../kandel/potential-risks/potential-risks.md | 4 --- 9 files changed, 31 insertions(+), 29 deletions(-) create mode 100644 docs/kandel/how-does-kandel-work/choosing-parameters.md diff --git a/docs/kandel/README.md b/docs/kandel/README.md index 673f1f9b..526abccd 100644 --- a/docs/kandel/README.md +++ b/docs/kandel/README.md @@ -6,10 +6,6 @@ sidebar_position: 1 # What is Kandel? -:::info -Kandel strategy is coming soon! -::: - Kandel is an Automated Market Making strategy that uses on-chain order flow to repost offers instantly, without any latency. It could be considered as a market-making bot equivalent that operates solely on the blockchain. It leverages **the interaction between buyers and sellers** that creates price movement, rather than the price itself. Within a market and price range you select, Kandel automatically posts Bids and Asks. **Its main goal is to buy low and sell high** - profits are made through accumulated spread, i.e. the difference between the Bids and Asks that are taken. \ No newline at end of file diff --git a/docs/kandel/details-on-strats/details-on-strats.md b/docs/kandel/details-on-strats/details-on-strats.md index c01da872..fd808006 100644 --- a/docs/kandel/details-on-strats/details-on-strats.md +++ b/docs/kandel/details-on-strats/details-on-strats.md @@ -6,9 +6,6 @@ sidebar_position: 3 # Details on strategies -:::info -Kandel strategy is coming soon! -::: ## Market making strategies diff --git a/docs/kandel/how-does-kandel-work/choosing-parameters.md b/docs/kandel/how-does-kandel-work/choosing-parameters.md new file mode 100644 index 00000000..d840c1c4 --- /dev/null +++ b/docs/kandel/how-does-kandel-work/choosing-parameters.md @@ -0,0 +1,29 @@ +--- +description: Choosing Kandel parameters +sidebar_position: 4 +--- + + +# Choosing Kandel parameters + + +This section aims to help you develop an intuition to choose your Kandel parameters. It should be taken as an explanation on how the various parameters can impact your Kandel, and how the market conditions (ex: volatility) could be taken into account. It is **not** a trading advice. + +> 💡 +> As a reminder, Kandel is not intended as a "set and forget" strategy, and needs ongoing maintenance and checks. + +We will be going through standard steps you might want a take in order to check the market and deploy a new Kandel. + +## Check-in frequency + +First, it is good practice to know how often you aim to update your Kandel. Depending on the trading pair you chose, markets can behave very differently. + +Example: I will update my Kandel every 24h. + +## Set your price range + +Next, you should try to anticipate how much the market/price will vary during that period you just decided on. You are kind of betting on daily volatility. + +Example: I will look at the market volatility for the past 24h, and decide on the price range for my new Kandel. + +## Ratio: will depend on expected volatility \ No newline at end of file diff --git a/docs/kandel/how-does-kandel-work/how-does-kandel-work.md b/docs/kandel/how-does-kandel-work/how-does-kandel-work.md index 5f763f32..20202cda 100644 --- a/docs/kandel/how-does-kandel-work/how-does-kandel-work.md +++ b/docs/kandel/how-does-kandel-work/how-does-kandel-work.md @@ -6,9 +6,6 @@ sidebar_position: 2 # How does Kandel work? -:::info -Kandel strategy is coming soon! -::: This section is a detailed explanation of how Kandel works, introducing configuration parameters and key mechanics. For the sake of simplicity, we have clearly separated the startup steps and picked round numbers. diff --git a/docs/kandel/how-does-kandel-work/more-on-failing-offers.md b/docs/kandel/how-does-kandel-work/more-on-failing-offers.md index 9b0ca601..853890fe 100644 --- a/docs/kandel/how-does-kandel-work/more-on-failing-offers.md +++ b/docs/kandel/how-does-kandel-work/more-on-failing-offers.md @@ -1,14 +1,11 @@ --- description: How does Kandel work -sidebar_position: 5 +sidebar_position: 6 --- # More on failing offers -:::info -Kandel strategy is coming soon! -::: This section explains the reasons why some offers might fail using Kandel. diff --git a/docs/kandel/how-does-kandel-work/parameters.md b/docs/kandel/how-does-kandel-work/parameters.md index cf86c9ee..94eaae05 100644 --- a/docs/kandel/how-does-kandel-work/parameters.md +++ b/docs/kandel/how-does-kandel-work/parameters.md @@ -6,10 +6,6 @@ sidebar_position: 3 # Parameters -:::info -Kandel strategy is coming soon! -::: - This section describes Kandel's parameters. For more contextual information, head over to the [visual explanation](./step-by-step-visual-explanation.md). Parameters | Description diff --git a/docs/kandel/how-does-kandel-work/step-by-step-visual-explanation.md b/docs/kandel/how-does-kandel-work/step-by-step-visual-explanation.md index 5846b91e..12602b6a 100644 --- a/docs/kandel/how-does-kandel-work/step-by-step-visual-explanation.md +++ b/docs/kandel/how-does-kandel-work/step-by-step-visual-explanation.md @@ -6,9 +6,6 @@ sidebar_position: 2 # Step-by-step visual explanation -:::info -Kandel strategy is coming soon! -::: ## Setting things up diff --git a/docs/kandel/how-does-kandel-work/strategy-reserve.md b/docs/kandel/how-does-kandel-work/strategy-reserve.md index a03ee18a..5e2c9193 100644 --- a/docs/kandel/how-does-kandel-work/strategy-reserve.md +++ b/docs/kandel/how-does-kandel-work/strategy-reserve.md @@ -1,14 +1,11 @@ --- description: How does Kandel work -sidebar_position: 4 +sidebar_position: 5 --- # Strategy reserve -:::info -Kandel strategy is coming soon! -::: All Kandel instances have a local liquidity source, i.e. the funds deposited in the Strategy reserve. It includes Published liquidity and Unallocated liquidity: diff --git a/docs/kandel/potential-risks/potential-risks.md b/docs/kandel/potential-risks/potential-risks.md index 7e799279..0d6060c5 100644 --- a/docs/kandel/potential-risks/potential-risks.md +++ b/docs/kandel/potential-risks/potential-risks.md @@ -6,10 +6,6 @@ sidebar_position: 2 # Potential risks -:::info -Kandel strategy is coming soon! -::: - Kandel strategy is subject to some risks that should be taken into consideration. By using Kandel, you acknowledge (i) having the necessary knowledge and understanding of the blockchain technology and the tokens, and (ii) comprehended the risks associated with blockchain-based software systems and tokens, as described below and in the disclaimer. From 2534bfd0d64a0a6a3e2fb16c5199a984787d2825 Mon Sep 17 00:00:00 2001 From: frkralj Date: Wed, 13 Sep 2023 10:01:37 +0200 Subject: [PATCH 02/38] Return definition + guide typo --- docs/kandel/how-does-kandel-work/choosing-parameters.md | 2 +- docs/strat-lib/guides/howToUnlockLiquidity.md | 4 ++-- docs/web-app/strategies/manage-strat/overview-tab.md | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/kandel/how-does-kandel-work/choosing-parameters.md b/docs/kandel/how-does-kandel-work/choosing-parameters.md index d840c1c4..109b5b87 100644 --- a/docs/kandel/how-does-kandel-work/choosing-parameters.md +++ b/docs/kandel/how-does-kandel-work/choosing-parameters.md @@ -7,7 +7,7 @@ sidebar_position: 4 # Choosing Kandel parameters -This section aims to help you develop an intuition to choose your Kandel parameters. It should be taken as an explanation on how the various parameters can impact your Kandel, and how the market conditions (ex: volatility) could be taken into account. It is **not** a trading advice. +This section goal is to help you develop an intuition to choose your Kandel parameters. It should be taken as an explanation on how the various parameters can impact your Kandel, and how the market conditions (ex: volatility) could be taken into account. It is **not** a trading advice. > 💡 > As a reminder, Kandel is not intended as a "set and forget" strategy, and needs ongoing maintenance and checks. diff --git a/docs/strat-lib/guides/howToUnlockLiquidity.md b/docs/strat-lib/guides/howToUnlockLiquidity.md index 7559c5ed..6822ce7b 100644 --- a/docs/strat-lib/guides/howToUnlockLiquidity.md +++ b/docs/strat-lib/guides/howToUnlockLiquidity.md @@ -9,7 +9,7 @@ sidebar_position: 1 In the previous [smart offer tutorial](../getting-started/smart-offer.md), the offer we posted had to receive a transfer liquidity for it to succeed when taken. Now, we want instead to post the offer without transferring tokens from the admin to Mangrove or the `OfferMakerTutorial` (unlocked or %%reactive liquidity|reactive-liquidity%%). This way, the tokens are pulled just-in-time when the offer is taken and can thus be made available for other purposes (ex: generating extra yield in another DeFi protocol). :::info Note -Since you are not committing your liquidity to your smart offer, you can post multiple offers with "unlocked liqudity". We call that [liquidity amplification](../../terms/amplified-liquidity.md). +Since you are not committing your liquidity to your smart offer, you can post multiple offers with "unlocked liquidity". We call that [liquidity amplification](../../terms/amplified-liquidity.md). ::: For this to work, we use a so-called %%router|router%%: it is a contract that can be used to route tokens from the admin to the `OfferMakerTutorial` when the offer is taken.
@@ -101,4 +101,4 @@ cast send --rpc-url $LOCAL_URL "$WBTC" "approve(address, uint)" "$ROUTER" 100000 ``` -The `OfferMakerTutorial` now uses the uses the approval of the `SimpleRouter` to transfer funds from the admin. If you wonder where the approval of the transfers from `OfferMakerTutorial` happens, then its the `activate` call. See [approvals](../guides/approvals.md) for more details on that topic. +The `OfferMakerTutorial` now uses the approval of the `SimpleRouter` to transfer funds from the admin. If you wonder where the approval of the transfers from `OfferMakerTutorial` happens, then its the `activate` call. See [approvals](../guides/approvals.md) for more details on that topic. diff --git a/docs/web-app/strategies/manage-strat/overview-tab.md b/docs/web-app/strategies/manage-strat/overview-tab.md index 37438835..193ea0c1 100644 --- a/docs/web-app/strategies/manage-strat/overview-tab.md +++ b/docs/web-app/strategies/manage-strat/overview-tab.md @@ -12,7 +12,8 @@ import useBaseUrl from '@docusaurus/useBaseUrl'; ## Information cards -* **Return**: the average monthly return of your Kandel strategy. It is calculated by dividing the [profits from the spread](../../../kandel/README.md) by [published liquidity](../../../kandel/how-does-kandel-work/strategy-reserve.md#published-liquidity) for a period of time. It is then averaged out per day for that period, and extrapolated to obtain the monthly average. +* **Return**: the average monthly return of your Kandel strategy (or in other word, the growth rate of your wealth). It is calculated by dividing the [profits from the spread](../../../kandel/README.md) and the impermanent loss by the [published liquidity](../../../kandel/how-does-kandel-work/strategy-reserve.md#published-liquidity) for a period of time. It is then averaged out per day for that period, and extrapolated to obtain the monthly average. + * Return = (profit from spread + impermanent loss) / published liquidity > 💡 > For the sake of this calculation, the published liquidity is converted entirely to USDC. From c82295d8feb73918ace1850ae72c6f10c4e868ef Mon Sep 17 00:00:00 2001 From: frkralj Date: Mon, 25 Sep 2023 19:22:20 +0200 Subject: [PATCH 03/38] test mangrove sidebar and colors --- docs/SDK/README.md | 33 --- docs/SDK/background/_category_.json | 5 - docs/SDK/getting-started/_category_.json | 5 - docs/SDK/getting-started/_preparation-post.md | 41 ---- docs/SDK/getting-started/_preparation-pre.md | 44 ---- docs/SDK/getting-started/basic-offer.md | 118 ----------- docs/SDK/getting-started/deploy-kandel.md | 132 ------------ docs/SDK/getting-started/preparation.md | 20 -- docs/SDK/guides/_category_.json | 5 - docs/SDK/guides/fill-or-kill.md | 73 ------- docs/SDK/guides/reuse-offer.md | 44 ---- docs/SDK/guides/sell-and-buy-orders.md | 32 --- docs/SDK/guides/snipe-offer.md | 101 ---------- docs/SDK/guides/update-offer.md | 74 ------- docs/SDK/technical-references/_category_.json | 5 - docs/SDK/technical-references/api-overview.md | 188 ------------------ src/css/custom.css | 35 ++-- src/pages/index.js | 2 +- static/img/assets/Twitter_dark.png | Bin 0 -> 103849 bytes 19 files changed, 14 insertions(+), 943 deletions(-) delete mode 100644 docs/SDK/README.md delete mode 100644 docs/SDK/background/_category_.json delete mode 100644 docs/SDK/getting-started/_category_.json delete mode 100644 docs/SDK/getting-started/_preparation-post.md delete mode 100644 docs/SDK/getting-started/_preparation-pre.md delete mode 100644 docs/SDK/getting-started/basic-offer.md delete mode 100644 docs/SDK/getting-started/deploy-kandel.md delete mode 100644 docs/SDK/getting-started/preparation.md delete mode 100644 docs/SDK/guides/_category_.json delete mode 100644 docs/SDK/guides/fill-or-kill.md delete mode 100644 docs/SDK/guides/reuse-offer.md delete mode 100644 docs/SDK/guides/sell-and-buy-orders.md delete mode 100644 docs/SDK/guides/snipe-offer.md delete mode 100644 docs/SDK/guides/update-offer.md delete mode 100644 docs/SDK/technical-references/_category_.json delete mode 100644 docs/SDK/technical-references/api-overview.md create mode 100644 static/img/assets/Twitter_dark.png diff --git a/docs/SDK/README.md b/docs/SDK/README.md deleted file mode 100644 index 60969a29..00000000 --- a/docs/SDK/README.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -description: mangrove.js is a TypeScript SDK for Mangrove DEX, the on-chain order book where offers are code. -sidebar_position: 1 ---- - -# The TypeScript SDK - -The Mangrove SDK is a TypeScript library that can help you write off-chain apps that work with Mangrove's ecosystem. It wraps around [ethers.js](https://github.com/ethers-io/ethers.js) and adds a number of Mangrove-specific functionality and API. In a nod towards its `ethers.js`-underpinnings, the SDK package is named `mangrove.js`. - -The SDK is appropriate for both **client-** and **server-side** apps: It is web browser-compatible and works with [Node.js](https://nodejs.org/en/). - -## Open source and free to use - on your own responsibility - -The SDK is used in production in the Mangrove web app, and in a number of keeper bots, but the SDK should be used responsibly. It is considered in open beta, and is constantly under development. - -The SDK is open source, and is provided freely to the community as a starting point for writing apps to work with Mangrove's ecosystem. However, do note that the SDK may contain bugs or may change significantly between patch versions. As such it should be used responsibly and with care. - -If you have questions about how to use the SDK, which are not answered sufficiently in this documentation, do reach out on the Mangrove [Discord](https://discord.gg/rk9Qthz5YE). And pull requests to the SDK are, of course, welcome! - -## Where do I start? - -The best starting point for developing your app, is the Getting Started section - start by reading the page on [Setting up your local development environment](./getting-started/preparation.md). - -If you just want to dive directly into reading about the technical details of the SDK, jump to the [SDK Overview](./technical-references/api-overview.md) or refer directly to the [mangrove.js API Reference](technical-references/code/index.md) generated from the [latest published package on NPM](#where-is-the-mangrovejs-package). - -## Where is the `mangrove.js` package? - -If you just want to find the latest `mangrove.js` package on NPM - go to [@mangrovedao/mangrove.js](https://www.npmjs.com/package/@mangrovedao/mangrove.js). - -## Where is the code? - -The code for the `mangrove.js` SDK is available on [GitHub](https://github.com/mangrovedao/mangrove.js). Pull requests are welcome! - diff --git a/docs/SDK/background/_category_.json b/docs/SDK/background/_category_.json deleted file mode 100644 index 0cea9dd7..00000000 --- a/docs/SDK/background/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "label": "Background", - "position": 5, - "collapsed": false -} \ No newline at end of file diff --git a/docs/SDK/getting-started/_category_.json b/docs/SDK/getting-started/_category_.json deleted file mode 100644 index 90993058..00000000 --- a/docs/SDK/getting-started/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "label": "Getting Started", - "position": 2, - "collapsed": false -} \ No newline at end of file diff --git a/docs/SDK/getting-started/_preparation-post.md b/docs/SDK/getting-started/_preparation-post.md deleted file mode 100644 index 2b81bca9..00000000 --- a/docs/SDK/getting-started/_preparation-post.md +++ /dev/null @@ -1,41 +0,0 @@ -## Environment - -Inside the tutorial folder, create a `.env` file. This will hold the secrets such as private key and API keys. Here we describe it in general, but the next section provides some working example values. - -The file should typically look as follows (with `<...>` replaced by proper values) - for instance you need a RPC URL from, e.g., [Infura](https://infura.io/) or [Alchemy](https://www.alchemy.com/), and an EOA with a private key. Note, there are other ways to provide secrets, but this is what we do in the tutorials. - -If you do not have a RPC URL, there exists free RPC URLs, some examples can be found here: [ChainList](https://chainlist.org/) - note that they can be unstable and in that case we recommend creating your own through the listed providers. - -```bash -# .env -export PRIVATE_KEY= # 0xabcd.... <- This is the private key you'll be using in the tutorial - a test key for the Polygon Mumbai network -export ADMIN_ADDRESS= # 0xabcd... -export RPC_URL= # alchemy or infura node url for Polygon Mumbai -export LOCAL_URL=http://127.0.0.1:8545 # Url for the local chain that anvil starts (see next section) -``` - -## Local chain - -The tutorials can be run directly on networks where Mangrove is deployed (see [Addresses](../../contracts/technical-references/contract-addresses.md)). However on a real network you will spend real tokens, so we recommend starting on test networks with a test account. - -To further speed things up we run tutorials on a local fork of a chain using Foundry's `anvil` tool. - -```bash title="How to fork an existing chain" -source .env -anvil --fork-url $RPC_URL -``` - -This starts a new chain on with a local url of `http://127.0.0.1:8545`. You can read more about the `anvil` command [here](https://book.getfoundry.sh/reference/anvil/), if you are interested. - -When `anvil` starts up, it creates 10 test accounts, with some native tokens. If you do not have a real account on the chain, you can always use these accounts. Here is an example of a `.env` file that uses the first anvil account, a demo RPC URL and with a LOCAL URL. - -:::tip -The demo RPC URLs are unstable, so if you cannot connect then create your own or use a different one. -::: - -``` bash title=".env file" -export PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 # The first anvil private key -export ADMIN_ADDRESS=0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266 # The matching public key, to the first anvil private key -export RPC_URL=https://polygon-mumbai.g.alchemy.com/v2/demo # Demo RPC provided by alchemy -export LOCAL_URL=http://127.0.0.1:8545 # Url for the local chan that anvil starts -``` diff --git a/docs/SDK/getting-started/_preparation-pre.md b/docs/SDK/getting-started/_preparation-pre.md deleted file mode 100644 index 88ac72d6..00000000 --- a/docs/SDK/getting-started/_preparation-pre.md +++ /dev/null @@ -1,44 +0,0 @@ -## Local development - -If you want to do any local development we recommend installing [Node.js](https://nodejs.org/en/) and [Foundry](https://book.getfoundry.sh/getting-started/installation.html). -We are going to be using Node.js for package management and running javascript in the tutorials, but it is not required. You can use any development environment that supports javascript and npm packages. - -We are going to be using Foundry to start local forks for existing chains. You don't have to use Foundry to do this, you can use any tool you want to do this, but we recommend Foundry. - -For Linux or macOS everything should work out of the box, if you are using Windows, then we recommend installing everything from within WSL2 and expect some quirks. -Remember to reopen your shell after running the first line. - -1. [Node.js](https://nodejs.org/en/) v18+, we recommend installation through [nvm](https://github.com/nvm-sh/nvm#installing-and-updating), with [Yarn 2](https://yarnpkg.com/getting-started/install) enabled: - -```shell -curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash -# Reopen shell -nvm install --lts -# Enable the Yarn 2 package manager -corepack enable -``` - -2. [Foundry](https://book.getfoundry.sh/getting-started/installation.html) development framework for Ethereum: - -```shell -curl -L https://foundry.paradigm.xyz | bash -# Reopen shell -foundryup -``` - -## Create tutorial folder - -The tutorials can be run in an isolated folder where you install Mangrove dependencies. - -Open a terminal and run the following commands: - -```bash -# Create a folder for the tutorial and enter it -mkdir tutorial -cd tutorial -npm init -y -``` - -## Install dependencies - -Now install the following dependencies: diff --git a/docs/SDK/getting-started/basic-offer.md b/docs/SDK/getting-started/basic-offer.md deleted file mode 100644 index f5dba2c1..00000000 --- a/docs/SDK/getting-started/basic-offer.md +++ /dev/null @@ -1,118 +0,0 @@ ---- -description: The most simple liquidity providing strategy, no offer logic, just a Wallet. -sidebar_position: 2 ---- - -# Post a simple offer - -Posting a simple offer is also referred to as an %%on-the-fly offer|on-the-fly-offer%%. - -## Prerequisites - -The tutorial assumes knowledge of JavaScript. Follow [preparation](./preparation.md) to create a new `tutorial` folder. - -Make sure to use a chain where Mangrove is live. You can find all live addresses for Mangrove [here](../../contracts/technical-references/contract-addresses.md) - -:::info - -When running the tutorial be aware that some of the script calls the chain and it can therefore take a few seconds before the transaction is completed. - -::: - -### Start local node - -Before proceeding, import the environment variables made as part of the preparation - -```bash -source .env -``` - -Start Foundry's local node `anvil` to test things locally, with `$RPC_URL` coming from `.env` and pointing, for instance, to the Polygon Mumbai testnet. - -```bash -anvil --fork-url $RPC_URL -``` - -### Import and connect - -Start up `node` in a new terminal and issue the following code which performs the following steps: - -1. The first thing needed is to import `dotenv`, this handles the `.env` file you added in the [preparation](./preparation.md). -2. Then import both `Mangrove` and `ethers` from the Mangrove package. `ethers` will allow you to connect to a node and your wallet. `Mangrove` will allow you to connect to the Mangrove protocol. -3. We connect to a local `anvil` node through `LOCAL_URL`. In order to connect to a real chain can replace `LOCAL_URL` with `RPC_URL`. -4. The `PRIVATE_KEY` is needed in order to connect to your wallet. -5. Once you have connected your wallet, you can connect to the Mangrove protocol using your wallet. - -```javascript reference -https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/on-the-fly-offer.js#L1-L12 -``` - -### Check existing market - -Next you need to connect to a market, in order to see the existing offers. This way you can figure out at what price you want to post your offer. - -1. Connect to the market using `mgv.market`, with a base and a quote. -2. Console log asks. This outputs table of the 50 best asks. -3. Console log bids. This outputs table of the 50 best bids. - -```javascript reference -https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/on-the-fly-offer.js#L14-L19 -``` - -``` bash -┌─────────┬──────┬──────────────────────────────────────────────┬────────────────────┬────────────────────────┐ -│ (index) │ id │ maker │ volume │ price │ -├─────────┼──────┼──────────────────────────────────────────────┼────────────────────┼────────────────────────┤ -│ 0 │ 2774 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1317.1775894557795 │ 1.00337113885004310077 │ -│ 1 │ 3299 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1308.2741138999688 │ 1.00337482875577922516 │ -│ 2 │ 1829 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 50.674948479792484 │ 1.00337923422410191358 │ -│ 3 │ 598 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 561.6921678391515 │ 1.00337932460078748916 │ -│ 4 │ 5026 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 189.47603337984367 │ 1.00338137023837699789 │ -... -``` - -### Post new offer - -After having looked at the market you now know what the prices are and you can now post an offer at a better price, so that the offer will be on top of the book. - -1. First create a [`LiquidityProvider`](../technical-references/code/classes/LiquidityProvider). This allows for posting new offers. -2. Then you need to approve your account/wallet. To make sure that the transaction has been made, we do `await tx.wait()`. -3. Then you need to calculate how much %%provision|provision%% is needed. -4. You can then post an offer using, in this case `wants: 100.5` and `gives:100.4`, which gives a price of $$100.5/100.4\approx1.00099$$. And since you saw that the best price was $$\approx1.003$$ you know our offer will be at the top of the list. - -```javascript reference -https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/on-the-fly-offer.js#L21-L38 -``` - -### Check market after new offer - -We can then check if our offer has best been posted and is on the top of the list, as excepted. - -1. First log the `offerId` in order to makes sure, you know what offer is yours. -2. Then log the asks for the market. You will then see that your offer is on top of the list. - -```javascript reference -https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/on-the-fly-offer.js#L40-L42 -``` - -```js -> console.log(offerId); -5571 -undefined -> market.consoleAsks(); -┌─────────┬──────┬──────────────────────────────────────────────┬────────────────────┬────────────────────────┐ -│ (index) │ id │ maker │ volume │ price │ -├─────────┼──────┼──────────────────────────────────────────────┼────────────────────┼────────────────────────┤ -│ 0 │ 5571 │ '0xA4C7c59EB3D4Ab5CA4E6fB012CeD9c8F9A5Ecdd8' │ 100.4 │ 1.00099601593625498008 │ -│ 1 │ 2774 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1317.1775894557795 │ 1.00337113885004310077 │ -│ 2 │ 3299 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1308.2741138999688 │ 1.00337482875577922516 │ -│ 3 │ 1829 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 50.674948479792484 │ 1.00337923422410191358 │ -``` - -Another way to check your offer is to go to [testnet](https://testnet.mangrove.exchange/trade) and look at the asks for DAI-USDC. Here you will be able to see your offer. This can only be done if you didn't use a local chain, but actually ran on a real chain. - -import useBaseUrl from '@docusaurus/useBaseUrl'; - - - -The full script can be found on [github](https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/on-the-fly-offer.js). diff --git a/docs/SDK/getting-started/deploy-kandel.md b/docs/SDK/getting-started/deploy-kandel.md deleted file mode 100644 index 98695b33..00000000 --- a/docs/SDK/getting-started/deploy-kandel.md +++ /dev/null @@ -1,132 +0,0 @@ ---- -description: Deploy Kandel - an Automated Market Making strategy -sidebar_position: 2 ---- - -# Deploy Kandel strategy - -This tutorial covers how to deploy a Kandel strategy from a developer standpoint. For more information about Kandel, see the [Kandel documentation](../../kandel/README.md). - -## Prerequisites - -* The tutorial assumes knowledge of JavaScript -* Follow [preparation](./preparation.md) to create a new `tutorial` folder. -* Make sure to use a chain where Mangrove is live - you can find all live addresses for Mangrove [here](../../contracts/technical-references/contract-addresses.md) -* For a more simple tutorial to get acquainted with Mangrove, we recommend [Deploy a simple offer](./basic-offer.md) - -### Start local node - -Before proceeding, let's import the environment variables made as part of the preparation. - -```bash -source .env -``` - -Start Foundry's local node `anvil` to test things locally, with `$RPC_URL` coming from `.env` and pointing, for instance, to the Polygon Mumbai testnet. - -```bash -anvil --fork-url $RPC_URL -``` - -### Import and connect - -Start up `node` in a new terminal and issue the following code which performs the initial setup of loading the `.env` you added in [preparation](./preparation.md), importing the Mangrove SDK, and connecting the SDK to the local node for a specific market. - -```javascript reference -https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/deploy-kandel.js#L1-L19 -``` - -### Generate a minimum distribution - -Next, create an instance to manage Kandel strategies (`kandelStrategies`), and load the recommended configuration for the market. - -```javascript reference -https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/deploy-kandel.js#L21-L25 -``` - -With this, you can generate a [distribution](../../kandel/how-does-kandel-work/step-by-step-visual-explanation.md#price-distribution) with the minimum recommended amount of liquidity to avoid %%density|density%% issues by: -* Creating a generator -* Calculating minimums per offer -* Calculating the distribution for the given price parameters of `minPrice: 900`, `maxPrice: 1100`, and default ratio - -See the API documentation for [calculateMinimumDistribution](../technical-references/code/classes/KandelDistributionGenerator.md#calculateminimumdistribution) for more details on other `priceParams`. In our example here, `midPrice: 1100` is used to set the [current price](../../kandel/how-does-kandel-work/parameters.md), and decide which offers become bids and which become asks. - -```javascript reference -https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/deploy-kandel.js#L27-L58 -``` - -The last three lines should output something similar to the following (actual volumes may differ due to different configuration for the market): - -``` bash -Number of price points: 21 -Minimum base volume: 1.91296 -Minimum quote volume: 1893.8304 -``` - -> 💡 -> The minimums depend on the price; if the price range is changed, then the minimums should be re-checked. - - -### Generate desired distribution - -Based on the minimum volumes we calculated, we can select a desired distribution with volumes above these values. Here we use `3` for base (WETH) and `3000` for quote (USDC). - -```javascript reference -https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/deploy-kandel.js#L60-L70 -``` - - -### Deploy Kandel instance - -Now, you can use the `seeder` to [sow](../technical-references/code/classes/KandelSeeder.md#sow) a Kandel instance for a given seed, and retrieve a `kandelInstance` to manage the deployed instance. - -```javascript reference -https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/deploy-kandel.js#L72-L82 -``` - -A brief explanation on the above `seed` parameters: -* `onAave` indicates whether or not the liquidity to be used by Kandel is sitting on AAVE - here, it is not the case (it will be fetched from a wallet) -* `market`: this is the WETH/USDC pair that we previously chose -* `liquiditySharing` indicates whether you are using shared liquidity or not (SDK only, not available via the UI). This refers to the concept [amplified liquidity](../../terms/amplified-liquidity.md). -* `gaspriceFactor`: - * By using the `recommendedConfig.gaspriceFactor`, we make sure to select the right amount of gas for our Kandel strategy - * This is also connected to the amount of [bounty](../../terms/bounty.md) to be paid in case of a failure to deliver - - -### Approve transfers - -The `kandelInstance` has functions for approving transfers for the base and quote tokens. This is required for the Kandel strategy to be able to transfer tokens from the wallet when depositing funds. - -```javascript reference -https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/deploy-kandel.js#L84-L89 -``` - -### Populate offers for the distribution - -Now that our Kandel instance is deployed, we can [populate the offers](../../kandel/how-does-kandel-work/step-by-step-visual-explanation.md#populating-bids-and-asks) for the distribution. -This will create offers for the base and quote tokens, and deposit the required amounts of tokens into the Kandel instance. - -The offers also need a %%provision|provision%%, hence here the default that we are using can be inspected. - -> 💡 -> The population can span multiple transactions due to gas limits. After this step, the Kandel offers are deployed and are ready to be taken! - -```javascript reference -https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/deploy-kandel.js#L91-L115 -``` - -### Manage existing Kandel instance - -Later on, you can also manage an existing Kandel instance. For example, you might want to inspect the status of your offers. For this, the [farm](../technical-references/code/classes/KandelFarm.md) can be used to retrieve Kandel instances you own based on events from the seeder. - -```javascript reference -https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/deploy-kandel.js#L117-L131 -``` - -### Close Kandel strategy and withdraw funds - -At some point, you might want to close your Kandel strategy (for instance due to price movements). This can be easily done with the [retractAndWithdraw](../technical-references/code/classes/KandelInstance.md#retractandwithdraw) function. It will withdraw all funds (both tokens and provision) from the Kandel instance and retract all offers. - -```javascript reference -https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/deploy-kandel.js#L132-L178 -``` diff --git a/docs/SDK/getting-started/preparation.md b/docs/SDK/getting-started/preparation.md deleted file mode 100644 index 9a66fc51..00000000 --- a/docs/SDK/getting-started/preparation.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -description: Preparation for tutorials -sidebar_position: 1 ---- - -# Set Up Your Local Environment - -import Preamble from './_preparation-pre.md'; - - - -```bash -# To use the mangrove SDK -npm install --save dotenv -npm install --save @mangrovedao/mangrove.js@latest -``` - -import Post from './_preparation-post.md'; - - diff --git a/docs/SDK/guides/_category_.json b/docs/SDK/guides/_category_.json deleted file mode 100644 index 5824e635..00000000 --- a/docs/SDK/guides/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "label": "Guides", - "position": 3, - "collapsed": false -} \ No newline at end of file diff --git a/docs/SDK/guides/fill-or-kill.md b/docs/SDK/guides/fill-or-kill.md deleted file mode 100644 index fa2752a0..00000000 --- a/docs/SDK/guides/fill-or-kill.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -description: Create Fill or Kill order using mangrove.js -sidebar_position: 3 ---- - -# Use Fill or Kill - -## Intro - -This section will go through how to create a Fill or Kill ([FOK](https://www.investopedia.com/terms/f/fok.asp)) order using mangrove.js. - -We assume you know how to connect to Mangrove. We are going to be buying 2000 USDC at a maximum avg. price of 1.3. It is a requirement for this script to have enough USDC. If you do not have enough USDC, you can use a testnet and mint some USDC. This can either be done by going to our [dApp](https://testnet.mangrove.exchange/faucet) or by minting directly in the [script](https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/how-tos/fill-or-kill.js) (see the commented lines in the script about minting). - -### Approvals - -After having connected to Mangrove, we then have to make sure that we have the correct approvals for transferring our USDC tokens. When approving for transfers we have to determine what contract is going to make the actual transfers. If we were to use the normal [`buy`](../technical-references/code/classes/Market#-buy) function for a market, we would be using the Mangrove protocol, to make a standard [market order](../../contracts/technical-references/taking-and-making-offers/taker-order/README.md#market-order). This would mean that we would have to approve Mangrove to make transfers of USDC on our behalf. - -In this case we are not going to be using the Mangrove protocol directly. Instead we are going to be using a different contract, provided by the [Mangrove strat lib](../../strat-lib/README.md) - the [MangroveOrder](../../strat-lib/technical-references/code/strategies/MangroveOrder) contract. This contract makes it possible to make a real FoK order and not just a normal market order. This means that we need to approve the MangroveOrder contract to handle all our USDC transfers. One way of doing this, would be to just call approve directly on the USDC token, with the MangroveOrder contract as spender. But because strategies made with the Mangrove strat lib, can be using a more complex way of dealing with transfers, we should not rely on calling approve directly on the token. Instead we will create an %%OfferLogic|offer-logic%% using the MangroveOrder contract. This will provide us with an 'approveToken' function. This function will handle all the necessary approvals in order to use a token with the contract. - -```js reference -https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/how-tos/fill-or-kill.js#L27 -``` - -### Buying with MangroveOrder - -We are now ready to buy some DAI using a FoK order. It is very simple to do. Using the same method as for a market order (`buy`), we just give it an extra parameter `fillOrKill` which we set to true. This way we use the [MangroveOrder](../../strat-lib/technical-references/code/strategies/MangroveOrder) contract to buy. - -```js reference -https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/how-tos/fill-or-kill.js#L29-L37 -``` - -Here we show logs asks for the market before buying and after buying, you will see that the first 3 offers were taken. Offers 1669, 3344 and 1157 were all taken. But when we look at the result of the Fill or Kill order, we see that we got a %%bounty|bounty%%. This means that one of the offers failed and we got a bounty for making the offer fail. - - - - - -```js title="Asks before Fill or Kill order" -> market.consoleAsks(); -┌─────────┬──────┬──────────────────────────────────────────────┬────────────────────┬────────────────────────┐ -│ (index) │ id │ maker │ volume │ price │ -├─────────┼──────┼──────────────────────────────────────────────┼────────────────────┼────────────────────────┤ -│ 0 │ 1669 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 1376.6273438550415 │ 1.00346478817687987934 │ -│ 1 │ 3344 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1622.836373407379 │ 1.00346894837019272508 │ -│ 2 │ 1157 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 1163.3709308116254 │ 1.0034723140155791771 │ -│ 3 │ 4214 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1227.0562038171438 │ 1.003482667028260286 │ -│ 4 │ 930 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 1486.735792592364 │ 1.00348572922872847571 │ -│ 5 │ 3837 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1458.6523528414643 │ 1.00348711133850858816 │ -│ 6 │ 2721 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 629.9748527543823 │ 1.00348954285398244855 │ -│ 7 │ 2668 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1504.307740487991 │ 1.00349288205504048327 │ -``` - -```bash title="Result of Fill or Kill order" - summary: { - got: 2000, - gave: 2006.934268, - partialFill: false, - bounty: 0.000426, - feePaid: 0 - }, - successes: [], -``` - -```js title="Asks after fill or kill order" -> market.consoleAsks() -┌─────────┬──────┬──────────────────────────────────────────────┬────────────────────┬────────────────────────┐ -│ (index) │ id │ maker │ volume │ price │ -├─────────┼──────┼──────────────────────────────────────────────┼────────────────────┼────────────────────────┤ -│ 0 │ 4214 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1227.0562038171438 │ 1.003482667028260286 │ -│ 1 │ 930 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 1486.735792592364 │ 1.00348572922872847571 │ -│ 2 │ 3837 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1458.6523528414643 │ 1.00348711133850858816 │ -│ 3 │ 2721 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 629.9748527543823 │ 1.00348954285398244855 │ -``` diff --git a/docs/SDK/guides/reuse-offer.md b/docs/SDK/guides/reuse-offer.md deleted file mode 100644 index b77f2aa3..00000000 --- a/docs/SDK/guides/reuse-offer.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -description: Create fill or kill order using mangrove.js -sidebar_position: 4 ---- - -# Reuse Offer - -## Intro - -In this section we will go through how to reuse an offer, that has been taken or has failed. When an offer is taken, the offer still exists in Mangrove. This means that a previous offer made, can be reused again by the same maker. The same applies for an offer that failed when it was taken. The reason for keeping the offers around, is that cleaning up old/dead offers costs gas and by reusing a existing offer we save gas vs posting a completely new offer. This means that when we post an offer, we should save the %%Offer ID|offer-id%% for that offer, in case we ever want to reuse it. - -### Update existing offer - -In order to update an offer that is no longer live, we need the ID of an offer that has been taken or failed. In this example we are going to use ID 5573. If you do not have an offer that has been taken you can simply post a completely new offer and then snipe it. The [script](https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/how-tos/reuse-offer.js) has some commented out sections that helps with creating a dead offer. - -When we have a dead offer, then we can figure out how much %%provision|provision%% is needed when reposting it. This is done by using the [`computeAskProvision`](../technical-references/code/classes/LiquidityProvider#-computeaskprovision) given the offer id. The last thing we need is to give a wants and a gives for the offer. In this case we are going to use `wants: 1000.5` and `gives: 1000.4`. - -If we look at the asks before and after we have updated the offer, we now see that our offer has been updated and is at the top of the order book. - - - -```js reference -https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/how-tos/reuse-offer.js#L66-L78 -``` - -```js title="Asks before update"x -> market.consoleAsks(); -┌─────────┬──────┬──────────────────────────────────────────────┬────────────────────┬────────────────────────┐ -│ (index) │ id │ maker │ volume │ price │ -├─────────┼──────┼──────────────────────────────────────────────┼────────────────────┼────────────────────────┤ -│ 0 │ 1173 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 844.0536473037303 │ 1.00354291069746851135 │ -│ 1 │ 3003 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 280.69589368327456 │ 1.00354551434175376498 │ -│ 2 │ 967 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 578.3096271867598 │ 1.00355019649807276339 │ -``` - -```js title="Asks after update" -> market.consoleAsks(); -┌─────────┬──────┬──────────────────────────────────────────────┬────────────────────┬────────────────────────┐ -│ (index) │ id │ maker │ volume │ price │ -├─────────┼──────┼──────────────────────────────────────────────┼────────────────────┼────────────────────────┤ -│ 0 │ 5573 │ '0xA4C7c59EB3D4Ab5CA4E6fB012CeD9c8F9A5Ecdd8' │ 1000.4 │ 1.00009996001599360256 │ -│ 1 │ 1173 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 844.0536473037303 │ 1.00354291069746851135 │ -│ 2 │ 3003 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 280.69589368327456 │ 1.00354551434175376498 │ -``` diff --git a/docs/SDK/guides/sell-and-buy-orders.md b/docs/SDK/guides/sell-and-buy-orders.md deleted file mode 100644 index e65a287b..00000000 --- a/docs/SDK/guides/sell-and-buy-orders.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -description: Using the API to pass taker orders on a Mangrove market. -sidebar_position: 4 ---- - -# Sell and buy orders - -Buying with cash or selling for cash can be done via the [`buy`](../technical-references/code/classes/Market.md#-buy) and [`sell`](../technical-references/code/classes/Market.md#-sell) functions of a [Market](../technical-references/api-overview.md#market) instance. The code snippets below send limit buy (taker) orders on the market, with an allowed slippage of 2%: - -```typescript -// buy limit order for 100 base tokens at an average price of 0.1 quote per base -const buyPromises = await mgvMarket.buy({volume:100, price:0.1, slippage:2}); -const buyResult = await buyPromises.result; -// limit order with a desired quantitiy -const butPromises_ = await mgvMarket.buy({wants:100, gives:1000, slippage:2}); -const buyResult_ = await buyPromises_.result; -// sell limit order (selling 10 base tokens). -const sellPromises = await mgvMarket.sell({volume:10, price: 0.09, slippage:2}); -const sellResult = await sellPromises.result; -``` - -:::info - -`sell` and `buy` orders return a pair `{ response: Promise, result: Promise }` - -The result (`OrderResult`) returns a triple `{`takerGave:Big, takerGot:Big, bounty:Big`}` where: - -* `takerGave` is the total amount of base (for a sell) or quote (for a buy) tokens that the taker spent for the order -* `takerGot` is the total amount of quote (for a sell) or base (for a buy) tokens that the taker received as a result of the order -* `bounty` is the amount of native tokens the taker received to compensate for the gas lost of executing failing offer during the order execution see %%bounty|bounty%%. - -::: diff --git a/docs/SDK/guides/snipe-offer.md b/docs/SDK/guides/snipe-offer.md deleted file mode 100644 index b9548206..00000000 --- a/docs/SDK/guides/snipe-offer.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -description: Snipe a offer using mangrove.js -sidebar_position: 2 ---- - -# Snipe An Offer - -## Intro - -This will go through sniping an offer using mangrove.js. In this section we assume that you already know how to connect to Mangrove either on a real chain or on a local chain. When sniping we need to make sure that we actually have the funds. If we do not have the funds the transaction will revert with the error `mgv/takerTransferFail`. This means that the taker is the cause of the failed transfer and since we are trying to snipe an offer, we are the taker. Another result could be that the transfer failed because of the maker, then we will get this error `mgv/makerTransferFail`. This means that for some reason the makers funds was not transferred and the transfer therefore failed. In this case the taker (us), will be compensated for the gas we just used to make the offer fail. We are compensated in form of a %%bounty|bounty%%. - -### Connect to market (and mint tokens) - -As mentioned we assume that you are already connected to Mangrove, if not you can look at [github](https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/how-tos/snipe-offer.js), to see the full script. - -When connected to Mangrove we need to connect to a market. We do this to check whether the market is live and has offers. In this case we look at all the asks for the market. In this case the best offer is id 5572. Another way to check the market is to go to [testnet](https://testnet.mangrove.exchange/trade) and look at the DAI-USDC market. - -If we want to snipe this offer, then it requires that we have enough USDC. In this case we need $$100.5 \times 1.00345 \approx 100.85$$. If we look at UI for the testnet, we will also be able to see that the required USDC is 100.85. - -If you do not have the funds need for this, we can mint them using the commented out lines 4 to 7 below. In this example we mint 10.000 USDC, which is plenty for taking this offer. - -```js -> market.consoleAsks(); -┌─────────┬──────┬──────────────────────────────────────────────┬────────────────────┬────────────────────────┐ -│ (index) │ id │ maker │ volume │ price │ -├─────────┼──────┼──────────────────────────────────────────────┼────────────────────┼────────────────────────┤ -│ 0 │ 5572 │ '0xA4C7c59EB3D4Ab5CA4E6fB012CeD9c8F9A5Ecdd8' │ 100.5 │ 1.00345 │ -│ 1 │ 3137 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1883.81894460173 │ 1.00346413248309787013 │ -│ 2 │ 1384 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 1143.1714506162793 │ 1.00346467660785745789 │ -│ 3 │ 1669 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 1376.6273438550415 │ 1.00346478817687987934 │ -``` - -import useBaseUrl from '@docusaurus/useBaseUrl'; - -
- -
UI of offers
-
- -```javascript showLineNumbers reference -https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/how-tos/snipe-offer.js#L15-L24 -``` - -### Snipe best offer - -We now know that we want to snipe the best offer on the book, which is offer 5572. In order to snipe the offer, want to get all the info about the offer. We do this because we want the precise numbers for wants and gives. - -Before sniping the offer with the information we just gathered, we have to [approve](../../strat-lib/guides/approvals.md) Mangrove to be able to take the funds (USDC), from our account. We need to do this, because when taking any offer, the first thing Mangrove does, is to transfer the takers funds to Mangrove and from Mangrove to the maker. If we have not approved this, the transfer will fail with a `mgv/takerTransferFail`. - -We can now snipe the offer. Be ware that the information on the offer, is from the makers side. This means that what we, the taker, wants is what the offer (the maker) gives. Similarly with gives; what we, the taker, gives, is what the offer (the maker) wants. When taking a offer we should be aware that if we do not give a %%`gasLimit`|gasLimit%%, mangrove.js will get the `gasLimit` from the offer's %%`gasreq`|gasreq%%. The `gasLimit` sets a limit on how much gas we max want to use, when taking the offer. This way we can control, that if it is very costly to take the offer and it ends up costing more than our `gasLimit`, then the transfer will revert. - -```javascript reference -https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/how-tos/snipe-offer.js#L27-L50 -``` - -### Check the result of sniping - -After sniping we will get a result. We can look at the result to see if the transaction was successful or failed. - -If the transaction was successful then we should see a result like this. In this case we sniped offerId 5572, we got 100.5 `DAI` and gave 100.6 `USDC`. - -```bash title="Snipe successful" - feePaid: 0 - }, - successes: [ { offerId: 5572, got: 100.5, gave: 100.6 } ], - tradeFailures: [], - posthookFailures: [], -``` - -If the transaction failed, it is most likely that the account that posted the offer (the maker) couldn't complete the transaction. Because of this we will receive a %%bounty|bounty%% for making an offer fail. If sniped your own offer after following the [Post a simple offer](../getting-started/basic-offer.md) and it failed, then you most likely lack the DAI to fulfil the offer - try minting some. - -```bash title="Snipe failed because of maker" - events: [ [Object], [Object], [Object], [Object] ] - }, - summary: { got: 0, gave: 0, partialFill: false, bounty: 0.000426, feePaid: 0 }, - successes: [], - tradeFailures: [ - { - offerId: 3137, - reason: '0x6d67762f6d616b65725472616e736665724661696c0000000000000000000000', - FailToDeliver: 1883.81894460173, - volumeGiven: 1890.344743 - } - ], -``` - -We will also see the offer being gone when we log the asks on the market. - -```javascript reference -https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/how-tos/snipe-offer.js#L52-L56 -``` - -```js -> market.consoleAsks(); -┌─────────┬──────┬──────────────────────────────────────────────┬────────────────────┬────────────────────────┐ -│ (index) │ id │ maker │ volume │ price │ -├─────────┼──────┼──────────────────────────────────────────────┼────────────────────┼────────────────────────┤ -│ 0 │ 1384 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 1143.1714506162793 │ 1.00346467660785745789 │ -│ 1 │ 1669 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 1376.6273438550415 │ 1.00346478817687987934 │ -│ 2 │ 3344 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1622.836373407379 │ 1.00346894837019272508 │ -``` diff --git a/docs/SDK/guides/update-offer.md b/docs/SDK/guides/update-offer.md deleted file mode 100644 index 44d34178..00000000 --- a/docs/SDK/guides/update-offer.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -description: How to update an offer using mangrove.js -sidebar_position: 1 ---- - -# Update Your Offer - -## Intro - -This will explain how you update an offer using mangrove.js. - -Since you need to have an offer on the book in order to update it, this will assume that you already have an offer on the book. In this case we will use the offer id 5572. But make sure you use your own offer id. See for instance [Post a simple offer](../getting-started/basic-offer.md). - -### Update offer - -We start by logging all the asks on the DAI-USDC market. For this guide we will assume that the offer is an ask on the DAI-USDC market. If your offer is on another market, make sure to connect to the market where your offer is posted. - -Here we can see that my offer has a volume of 100.5 and a price of 1.00099. Lets say we want to update the offer to match the price of the next best offer. - -```js -market.consoleAsks(); -``` - -```bash -┌─────────┬──────┬──────────────────────────────────────────────┬────────────────────┬────────────────────────┐ -│ (index) │ id │ maker │ volume │ price │ -├─────────┼──────┼──────────────────────────────────────────────┼────────────────────┼────────────────────────┤ -│ 0 │ 5572 │ '0xA4C7c59EB3D4Ab5CA4E6fB012CeD9c8F9A5Ecdd8' │ 100.5 │ 1.00099502487562189055 │ -│ 1 │ 3137 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1883.81894460173 │ 1.00346413248309787013 │ -│ 2 │ 1384 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 1143.1714506162793 │ 1.00346467660785745789 │ -│ 3 │ 1669 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 1376.6273438550415 │ 1.00346478817687987934 │ -``` - -To update the offer we use the [`updateAsk`](../technical-references/code/classes/LiquidityProvider.md#-updateask) function on our `liquidityProvider`. This has two options available in the [OfferParams](../technical-references/code/namespaces/LiquidityProvider-1.md#offerparams). First, you can provide `wants` and `gives`. If we chose to use this, we would have to calculate what `gives` should be, given that `wants` stays a 100.5 and we want the price to be slightly better than the next best offer, e.g. 1.00345. $$\frac{wants}{price}=gives$$ -> $$\frac{100.5}{1.00345}\approx 100.1494$$. - -Second, you can provide `volume` and `price`, since this is exactly what we want to use, we don't have to calculate `gives`. We then just update the offer using `volume: 100.5` and `price: 1.00345`. - -```js reference -https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/how-tos/update-offer.js#L23-L41 -``` - -```bash -┌─────────┬──────┬──────────────────────────────────────────────┬────────────────────┬────────────────────────┐ -│ (index) │ id │ maker │ volume │ price │ -├─────────┼──────┼──────────────────────────────────────────────┼────────────────────┼────────────────────────┤ -│ 0 │ 5572 │ '0xA4C7c59EB3D4Ab5CA4E6fB012CeD9c8F9A5Ecdd8' │ 100.5 │ 1.00345 │ -│ 1 │ 3137 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1883.81894460173 │ 1.00346413248309787013 │ -│ 2 │ 1384 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 1143.1714506162793 │ 1.00346467660785745789 │ -│ 3 │ 1669 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 1376.6273438550415 │ 1.00346478817687987934 │ -``` - -Changing the price of an offer can change its %%rank|offer-rank%% in the offer book. - -### Update offer using OfferLogic - -When we updated our offer before, we used a `liquidityProvider` and we created this using Mangrove. This means that when we updated our offer, we did using Mangrove directly. But if you have your own contract with your own update offer logic, you can use that by creating an [`OfferLogic`](../technical-references/code/classes/OfferLogic). This is simply done by calling the constructor with Mangrove (remember to import the type first, e.g., using `const { OfferLogic } = require("@mangrovedao/mangrove.js");`). - -```js reference -https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/how-tos/update-offer.js#L43-L46 -``` - -When you have a OfferLogic you can the call update offer directly on the underlying contract (which is assumed to implement the [`ILiquidityProvider` interface](../../strat-lib/technical-references/code/strategies/interfaces/ILiquidityProvider.md), but this requires a lot more info and unit conversions. - -```js reference -https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/how-tos/update-offer.js#L49-L60 -``` - -To keep things more simple you can create a `liquidityProvider` with your offerLogic and a market. This way the LiquidityProvider will make sure to update your offer using your offerLogic. This saves you for taking any other decisions than `wants` and `gives` or `volume` and `price`. - -```js reference -https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/how-tos/update-offer.js#L62-L67 -``` - -You can only update offers you own as a maker. And from the `consoleAsks()` above you can see the `maker` of each offer. So for instance, you cannot update an offer posted directly in [Post a simple offer](../getting-started/basic-offer.md) using your `offerLogic`'s `liquitidyProvider` - it has to be an offer posted by the `offerLogic`. diff --git a/docs/SDK/technical-references/_category_.json b/docs/SDK/technical-references/_category_.json deleted file mode 100644 index c9ffec35..00000000 --- a/docs/SDK/technical-references/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "label": "Technical Reference", - "position": 4, - "collapsed": false -} \ No newline at end of file diff --git a/docs/SDK/technical-references/api-overview.md b/docs/SDK/technical-references/api-overview.md deleted file mode 100644 index fc0735bb..00000000 --- a/docs/SDK/technical-references/api-overview.md +++ /dev/null @@ -1,188 +0,0 @@ ---- -sidebar_position: 0 ---- - -# SDK Overview - -:::info **Numbers** - -* Numbers returned by functions are either plain JavaScript [`number`](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Global\_Objects/Number) or [`big.js`](https://github.com/MikeMcl/big.js/)instances. Some functions with names ending in `Raw` may return`ethers.BigNumbers`. -* As input, numbers can be as plain JavaScript `numbers`, `big.js` instances, but also a`string`. - -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: - -```typescript -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](../../contracts/technical-references/contract-addresses.md) 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](https://www.investopedia.com/terms/b/bid.asp) and [asks](https://www.investopedia.com/terms/a/ask.asp) on Mangrove) objects. - -:::info - -`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](https://eips.ethereum.org/EIPS/eip-20). To obtain an instance use: - -```javascript -mgvTkn = await mgv.token(""); // e.g "DAI", "WETH", "amDAI", etc. -``` - -with the above `MgvT` object one has access to standard calls using human readable input/outputs. For instance: - -```javascript -await mgvTkn.approve(""); // gives infinite approval to spender -await mgvTkn.approve("",0.5); // gives allowance to spend 0.5 token units to spender -await mgvTkn.contract.approve("", mgvTkn.mgv.toUnits(0.5)); // ethers.js call -``` - -Note that Mangrove's API deals with token decimals automatically (see definitions in [`constants.ts`](https://github.com/mangrovedao/mangrove/blob/master/packages/mangrove.js/src/constants.ts)). - -:::info - -`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](../guides/sell-and-buy-orders.md). To obtain one instance use: - -```typescript -//connect to a (base,quote) market with default options -mgvMarket = await mgv.connect({base:"", quote:""}); - -// connect to the market, caching the first 50 best bids and asks -mgvMarket = await mgv.connect({base:"", quote:"", maxOffers: 50}); -``` - -:::info - -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:})`. - -::: - -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: - -```typescript -// 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: - -```javascript -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 bid `offer` is removed from the book -* `{type: 'OfferWrite', ba:'asks'|'bids', offer:Market.Offer}` when a bid or ask `offer` is added to the book (or updated) -* `{type:'OfferFail', ba:'asks'|'bids', taker:string, 'takerWants':Big, takerGives:Big, mgvData:string, offer:Market.Offer}` when `offer` failed to deliver. Note that `mgvData` 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}` when `offer` was successfully executed (possibly on a partial fill whenever `offer.gives`>`takerWants`). - -and where `Market.Offer` has the following main fields: - -```typescript -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](https://docs.mangrove.exchange/data-structures/market) is managed by a smart contract which implements its [logic](api-overview.md#offerlogic). One may use the API to post liquidity on Mangrove via a deployed logic that complies to the [IOfferLogic](https://github.com/mangrovedao/mangrove/blob/master/packages/mangrove-solidity/contracts/Strategies/interfaces/IOfferLogic.sol) interface. To do so, one first need an `OfferLogic` instance: - -```typescript -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: - -```javascript -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 -``` - -:::danger - -When using an offer logic that inherits from the [`MultiUser.sol`](https://github.com/mangrovedao/mangrove/blob/master/packages/mangrove-solidity/contracts/Strategies/OfferLogics/MultiUsers/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](../getting-started/basic-offer.md) or to post an offer relying on some on-chain [logic](api-overview.md#offerlogic). - -To act as a direct liquidity provider on a [`mgvMarket`](api-overview.md#market) you must obtain a `LiquidityProvider` instance from an [`mgv`](api-overview.md#mangrove) object using: - -```javascript -const mgvDirectLP = await mgv.liquidityProvider(mgvMarket); -``` - -:::info - -The EOA providing the liquidity for ask and bid offers emanating from a direct liquidity provider is the address of the [`mgv`](api-overview.md#mangrove)'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: - -```javascript -const mgvOnchainLP = await mgvLogic.liquidityProvider(mgvMarket); -``` - -Besides posting offers on Mangrove, a `LiquidityProvider` instance `mgvLP` gives access to various useful functions such as: - -```javascript -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: - -```javascript -const ethersTx = await mgvLP.fundMangrove(missingAskProvision); -await ethersTx.wait(); // waiting for the funding tx to be confirmed -``` diff --git a/src/css/custom.css b/src/css/custom.css index 3173c800..6689edf2 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -7,7 +7,7 @@ /* You can override the default Infima variables here. */ :root { --ifm-font-family-base: 'Inter'; - --ifm-color-primary: #2e4385; + --ifm-color-primary: #2e4285; --ifm-color-primary-dark: #293c78; --ifm-color-primary-darker: #273971; --ifm-color-primary-darkest: #202f5d; @@ -18,14 +18,14 @@ /* For readability concerns, you should choose a lighter palette in dark mode. */ [data-theme='dark'] { - --ifm-color-primary: #477fdd; - --ifm-color-primary-dark: #2e6ed8; - --ifm-color-primary-darker: #2766d1; - --ifm-color-primary-darkest: #2054ad; - --ifm-color-primary-light: #6090e2; - --ifm-color-primary-lighter: #6c99e4; - --ifm-color-primary-lightest: #91b2eb; - background-color: #000618; + --ifm-color-primary: #47d77d; + --ifm-color-primary-dark: #30d26c; + --ifm-color-primary-darker: #2bc866; + --ifm-color-primary-darkest: #24a454; + --ifm-color-primary-light: #5edc8e; + --ifm-color-primary-lighter: #6adf96; + --ifm-color-primary-lightest: #8de6af; + background-color: #072221; } h1, h2, h3, h4, h5, h6 { @@ -55,7 +55,7 @@ table { } [data-theme='dark'] .navbar { - background-color: #1a1f30; + background-color: #051817; } @media screen and (min-width: 996px) and (max-width: 1239px) { @@ -89,11 +89,11 @@ table { } [data-theme='dark'] .hero--primary { - background-color: #000618; + background-color: #072221; } .footer { - background-color: #1f263b; + background-color: #051817; } .hero-image { @@ -108,16 +108,7 @@ table { object-fit: cover; - -webkit-mask-image: linear-gradient( - rgb(0 0 0 / 0.5), - rgb(0 0 0 / 0.2), - rgb(0 0 0 / 0) - ); - mask-image: linear-gradient( - rgb(0 0 0 / 0.5), - rgb(0 0 0 / 0.2), - rgb(0 0 0 / 0) - ); + } @media screen and (min-width: 400px) and (max-width: 996px) { diff --git a/src/pages/index.js b/src/pages/index.js index 2bf6fecd..42ec8b77 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -13,7 +13,7 @@ function HomepageHeader() { return (
- +

Welcome to Mangrove Docs

diff --git a/static/img/assets/Twitter_dark.png b/static/img/assets/Twitter_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..74797f235cec16b7e602a18f0f2c6db90660f42c GIT binary patch literal 103849 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�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 md=nC3`Mahe;6nS|80Nv~hiAFv Date: Mon, 25 Sep 2023 20:25:34 +0200 Subject: [PATCH 04/38] test mangrove sidebar and colors --- docs/SDK/README.md | 33 +++ docs/SDK/background/_category_.json | 5 + docs/SDK/getting-started/_category_.json | 5 + docs/SDK/getting-started/_preparation-post.md | 41 ++++ docs/SDK/getting-started/_preparation-pre.md | 44 ++++ docs/SDK/getting-started/basic-offer.md | 118 +++++++++++ docs/SDK/getting-started/deploy-kandel.md | 132 ++++++++++++ docs/SDK/getting-started/preparation.md | 20 ++ docs/SDK/guides/_category_.json | 5 + docs/SDK/guides/fill-or-kill.md | 73 +++++++ docs/SDK/guides/reuse-offer.md | 44 ++++ docs/SDK/guides/sell-and-buy-orders.md | 32 +++ docs/SDK/guides/snipe-offer.md | 101 ++++++++++ docs/SDK/guides/update-offer.md | 74 +++++++ docs/SDK/technical-references/_category_.json | 5 + docs/SDK/technical-references/api-overview.md | 188 ++++++++++++++++++ docusaurus.config.js | 42 +--- sidebars.js | 103 +++++++--- src/css/custom.css | 6 +- src/pages/index.js | 35 ---- 20 files changed, 1000 insertions(+), 106 deletions(-) create mode 100644 docs/SDK/README.md create mode 100644 docs/SDK/background/_category_.json create mode 100644 docs/SDK/getting-started/_category_.json create mode 100644 docs/SDK/getting-started/_preparation-post.md create mode 100644 docs/SDK/getting-started/_preparation-pre.md create mode 100644 docs/SDK/getting-started/basic-offer.md create mode 100644 docs/SDK/getting-started/deploy-kandel.md create mode 100644 docs/SDK/getting-started/preparation.md create mode 100644 docs/SDK/guides/_category_.json create mode 100644 docs/SDK/guides/fill-or-kill.md create mode 100644 docs/SDK/guides/reuse-offer.md create mode 100644 docs/SDK/guides/sell-and-buy-orders.md create mode 100644 docs/SDK/guides/snipe-offer.md create mode 100644 docs/SDK/guides/update-offer.md create mode 100644 docs/SDK/technical-references/_category_.json create mode 100644 docs/SDK/technical-references/api-overview.md delete mode 100644 src/pages/index.js diff --git a/docs/SDK/README.md b/docs/SDK/README.md new file mode 100644 index 00000000..60969a29 --- /dev/null +++ b/docs/SDK/README.md @@ -0,0 +1,33 @@ +--- +description: mangrove.js is a TypeScript SDK for Mangrove DEX, the on-chain order book where offers are code. +sidebar_position: 1 +--- + +# The TypeScript SDK + +The Mangrove SDK is a TypeScript library that can help you write off-chain apps that work with Mangrove's ecosystem. It wraps around [ethers.js](https://github.com/ethers-io/ethers.js) and adds a number of Mangrove-specific functionality and API. In a nod towards its `ethers.js`-underpinnings, the SDK package is named `mangrove.js`. + +The SDK is appropriate for both **client-** and **server-side** apps: It is web browser-compatible and works with [Node.js](https://nodejs.org/en/). + +## Open source and free to use - on your own responsibility + +The SDK is used in production in the Mangrove web app, and in a number of keeper bots, but the SDK should be used responsibly. It is considered in open beta, and is constantly under development. + +The SDK is open source, and is provided freely to the community as a starting point for writing apps to work with Mangrove's ecosystem. However, do note that the SDK may contain bugs or may change significantly between patch versions. As such it should be used responsibly and with care. + +If you have questions about how to use the SDK, which are not answered sufficiently in this documentation, do reach out on the Mangrove [Discord](https://discord.gg/rk9Qthz5YE). And pull requests to the SDK are, of course, welcome! + +## Where do I start? + +The best starting point for developing your app, is the Getting Started section - start by reading the page on [Setting up your local development environment](./getting-started/preparation.md). + +If you just want to dive directly into reading about the technical details of the SDK, jump to the [SDK Overview](./technical-references/api-overview.md) or refer directly to the [mangrove.js API Reference](technical-references/code/index.md) generated from the [latest published package on NPM](#where-is-the-mangrovejs-package). + +## Where is the `mangrove.js` package? + +If you just want to find the latest `mangrove.js` package on NPM - go to [@mangrovedao/mangrove.js](https://www.npmjs.com/package/@mangrovedao/mangrove.js). + +## Where is the code? + +The code for the `mangrove.js` SDK is available on [GitHub](https://github.com/mangrovedao/mangrove.js). Pull requests are welcome! + diff --git a/docs/SDK/background/_category_.json b/docs/SDK/background/_category_.json new file mode 100644 index 00000000..0cea9dd7 --- /dev/null +++ b/docs/SDK/background/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Background", + "position": 5, + "collapsed": false +} \ No newline at end of file diff --git a/docs/SDK/getting-started/_category_.json b/docs/SDK/getting-started/_category_.json new file mode 100644 index 00000000..90993058 --- /dev/null +++ b/docs/SDK/getting-started/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Getting Started", + "position": 2, + "collapsed": false +} \ No newline at end of file diff --git a/docs/SDK/getting-started/_preparation-post.md b/docs/SDK/getting-started/_preparation-post.md new file mode 100644 index 00000000..2b81bca9 --- /dev/null +++ b/docs/SDK/getting-started/_preparation-post.md @@ -0,0 +1,41 @@ +## Environment + +Inside the tutorial folder, create a `.env` file. This will hold the secrets such as private key and API keys. Here we describe it in general, but the next section provides some working example values. + +The file should typically look as follows (with `<...>` replaced by proper values) - for instance you need a RPC URL from, e.g., [Infura](https://infura.io/) or [Alchemy](https://www.alchemy.com/), and an EOA with a private key. Note, there are other ways to provide secrets, but this is what we do in the tutorials. + +If you do not have a RPC URL, there exists free RPC URLs, some examples can be found here: [ChainList](https://chainlist.org/) - note that they can be unstable and in that case we recommend creating your own through the listed providers. + +```bash +# .env +export PRIVATE_KEY= # 0xabcd.... <- This is the private key you'll be using in the tutorial - a test key for the Polygon Mumbai network +export ADMIN_ADDRESS= # 0xabcd... +export RPC_URL= # alchemy or infura node url for Polygon Mumbai +export LOCAL_URL=http://127.0.0.1:8545 # Url for the local chain that anvil starts (see next section) +``` + +## Local chain + +The tutorials can be run directly on networks where Mangrove is deployed (see [Addresses](../../contracts/technical-references/contract-addresses.md)). However on a real network you will spend real tokens, so we recommend starting on test networks with a test account. + +To further speed things up we run tutorials on a local fork of a chain using Foundry's `anvil` tool. + +```bash title="How to fork an existing chain" +source .env +anvil --fork-url $RPC_URL +``` + +This starts a new chain on with a local url of `http://127.0.0.1:8545`. You can read more about the `anvil` command [here](https://book.getfoundry.sh/reference/anvil/), if you are interested. + +When `anvil` starts up, it creates 10 test accounts, with some native tokens. If you do not have a real account on the chain, you can always use these accounts. Here is an example of a `.env` file that uses the first anvil account, a demo RPC URL and with a LOCAL URL. + +:::tip +The demo RPC URLs are unstable, so if you cannot connect then create your own or use a different one. +::: + +``` bash title=".env file" +export PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 # The first anvil private key +export ADMIN_ADDRESS=0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266 # The matching public key, to the first anvil private key +export RPC_URL=https://polygon-mumbai.g.alchemy.com/v2/demo # Demo RPC provided by alchemy +export LOCAL_URL=http://127.0.0.1:8545 # Url for the local chan that anvil starts +``` diff --git a/docs/SDK/getting-started/_preparation-pre.md b/docs/SDK/getting-started/_preparation-pre.md new file mode 100644 index 00000000..88ac72d6 --- /dev/null +++ b/docs/SDK/getting-started/_preparation-pre.md @@ -0,0 +1,44 @@ +## Local development + +If you want to do any local development we recommend installing [Node.js](https://nodejs.org/en/) and [Foundry](https://book.getfoundry.sh/getting-started/installation.html). +We are going to be using Node.js for package management and running javascript in the tutorials, but it is not required. You can use any development environment that supports javascript and npm packages. + +We are going to be using Foundry to start local forks for existing chains. You don't have to use Foundry to do this, you can use any tool you want to do this, but we recommend Foundry. + +For Linux or macOS everything should work out of the box, if you are using Windows, then we recommend installing everything from within WSL2 and expect some quirks. +Remember to reopen your shell after running the first line. + +1. [Node.js](https://nodejs.org/en/) v18+, we recommend installation through [nvm](https://github.com/nvm-sh/nvm#installing-and-updating), with [Yarn 2](https://yarnpkg.com/getting-started/install) enabled: + +```shell +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash +# Reopen shell +nvm install --lts +# Enable the Yarn 2 package manager +corepack enable +``` + +2. [Foundry](https://book.getfoundry.sh/getting-started/installation.html) development framework for Ethereum: + +```shell +curl -L https://foundry.paradigm.xyz | bash +# Reopen shell +foundryup +``` + +## Create tutorial folder + +The tutorials can be run in an isolated folder where you install Mangrove dependencies. + +Open a terminal and run the following commands: + +```bash +# Create a folder for the tutorial and enter it +mkdir tutorial +cd tutorial +npm init -y +``` + +## Install dependencies + +Now install the following dependencies: diff --git a/docs/SDK/getting-started/basic-offer.md b/docs/SDK/getting-started/basic-offer.md new file mode 100644 index 00000000..f5dba2c1 --- /dev/null +++ b/docs/SDK/getting-started/basic-offer.md @@ -0,0 +1,118 @@ +--- +description: The most simple liquidity providing strategy, no offer logic, just a Wallet. +sidebar_position: 2 +--- + +# Post a simple offer + +Posting a simple offer is also referred to as an %%on-the-fly offer|on-the-fly-offer%%. + +## Prerequisites + +The tutorial assumes knowledge of JavaScript. Follow [preparation](./preparation.md) to create a new `tutorial` folder. + +Make sure to use a chain where Mangrove is live. You can find all live addresses for Mangrove [here](../../contracts/technical-references/contract-addresses.md) + +:::info + +When running the tutorial be aware that some of the script calls the chain and it can therefore take a few seconds before the transaction is completed. + +::: + +### Start local node + +Before proceeding, import the environment variables made as part of the preparation + +```bash +source .env +``` + +Start Foundry's local node `anvil` to test things locally, with `$RPC_URL` coming from `.env` and pointing, for instance, to the Polygon Mumbai testnet. + +```bash +anvil --fork-url $RPC_URL +``` + +### Import and connect + +Start up `node` in a new terminal and issue the following code which performs the following steps: + +1. The first thing needed is to import `dotenv`, this handles the `.env` file you added in the [preparation](./preparation.md). +2. Then import both `Mangrove` and `ethers` from the Mangrove package. `ethers` will allow you to connect to a node and your wallet. `Mangrove` will allow you to connect to the Mangrove protocol. +3. We connect to a local `anvil` node through `LOCAL_URL`. In order to connect to a real chain can replace `LOCAL_URL` with `RPC_URL`. +4. The `PRIVATE_KEY` is needed in order to connect to your wallet. +5. Once you have connected your wallet, you can connect to the Mangrove protocol using your wallet. + +```javascript reference +https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/on-the-fly-offer.js#L1-L12 +``` + +### Check existing market + +Next you need to connect to a market, in order to see the existing offers. This way you can figure out at what price you want to post your offer. + +1. Connect to the market using `mgv.market`, with a base and a quote. +2. Console log asks. This outputs table of the 50 best asks. +3. Console log bids. This outputs table of the 50 best bids. + +```javascript reference +https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/on-the-fly-offer.js#L14-L19 +``` + +``` bash +┌─────────┬──────┬──────────────────────────────────────────────┬────────────────────┬────────────────────────┐ +│ (index) │ id │ maker │ volume │ price │ +├─────────┼──────┼──────────────────────────────────────────────┼────────────────────┼────────────────────────┤ +│ 0 │ 2774 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1317.1775894557795 │ 1.00337113885004310077 │ +│ 1 │ 3299 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1308.2741138999688 │ 1.00337482875577922516 │ +│ 2 │ 1829 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 50.674948479792484 │ 1.00337923422410191358 │ +│ 3 │ 598 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 561.6921678391515 │ 1.00337932460078748916 │ +│ 4 │ 5026 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 189.47603337984367 │ 1.00338137023837699789 │ +... +``` + +### Post new offer + +After having looked at the market you now know what the prices are and you can now post an offer at a better price, so that the offer will be on top of the book. + +1. First create a [`LiquidityProvider`](../technical-references/code/classes/LiquidityProvider). This allows for posting new offers. +2. Then you need to approve your account/wallet. To make sure that the transaction has been made, we do `await tx.wait()`. +3. Then you need to calculate how much %%provision|provision%% is needed. +4. You can then post an offer using, in this case `wants: 100.5` and `gives:100.4`, which gives a price of $$100.5/100.4\approx1.00099$$. And since you saw that the best price was $$\approx1.003$$ you know our offer will be at the top of the list. + +```javascript reference +https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/on-the-fly-offer.js#L21-L38 +``` + +### Check market after new offer + +We can then check if our offer has best been posted and is on the top of the list, as excepted. + +1. First log the `offerId` in order to makes sure, you know what offer is yours. +2. Then log the asks for the market. You will then see that your offer is on top of the list. + +```javascript reference +https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/on-the-fly-offer.js#L40-L42 +``` + +```js +> console.log(offerId); +5571 +undefined +> market.consoleAsks(); +┌─────────┬──────┬──────────────────────────────────────────────┬────────────────────┬────────────────────────┐ +│ (index) │ id │ maker │ volume │ price │ +├─────────┼──────┼──────────────────────────────────────────────┼────────────────────┼────────────────────────┤ +│ 0 │ 5571 │ '0xA4C7c59EB3D4Ab5CA4E6fB012CeD9c8F9A5Ecdd8' │ 100.4 │ 1.00099601593625498008 │ +│ 1 │ 2774 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1317.1775894557795 │ 1.00337113885004310077 │ +│ 2 │ 3299 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1308.2741138999688 │ 1.00337482875577922516 │ +│ 3 │ 1829 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 50.674948479792484 │ 1.00337923422410191358 │ +``` + +Another way to check your offer is to go to [testnet](https://testnet.mangrove.exchange/trade) and look at the asks for DAI-USDC. Here you will be able to see your offer. This can only be done if you didn't use a local chain, but actually ran on a real chain. + +import useBaseUrl from '@docusaurus/useBaseUrl'; + + + +The full script can be found on [github](https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/on-the-fly-offer.js). diff --git a/docs/SDK/getting-started/deploy-kandel.md b/docs/SDK/getting-started/deploy-kandel.md new file mode 100644 index 00000000..98695b33 --- /dev/null +++ b/docs/SDK/getting-started/deploy-kandel.md @@ -0,0 +1,132 @@ +--- +description: Deploy Kandel - an Automated Market Making strategy +sidebar_position: 2 +--- + +# Deploy Kandel strategy + +This tutorial covers how to deploy a Kandel strategy from a developer standpoint. For more information about Kandel, see the [Kandel documentation](../../kandel/README.md). + +## Prerequisites + +* The tutorial assumes knowledge of JavaScript +* Follow [preparation](./preparation.md) to create a new `tutorial` folder. +* Make sure to use a chain where Mangrove is live - you can find all live addresses for Mangrove [here](../../contracts/technical-references/contract-addresses.md) +* For a more simple tutorial to get acquainted with Mangrove, we recommend [Deploy a simple offer](./basic-offer.md) + +### Start local node + +Before proceeding, let's import the environment variables made as part of the preparation. + +```bash +source .env +``` + +Start Foundry's local node `anvil` to test things locally, with `$RPC_URL` coming from `.env` and pointing, for instance, to the Polygon Mumbai testnet. + +```bash +anvil --fork-url $RPC_URL +``` + +### Import and connect + +Start up `node` in a new terminal and issue the following code which performs the initial setup of loading the `.env` you added in [preparation](./preparation.md), importing the Mangrove SDK, and connecting the SDK to the local node for a specific market. + +```javascript reference +https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/deploy-kandel.js#L1-L19 +``` + +### Generate a minimum distribution + +Next, create an instance to manage Kandel strategies (`kandelStrategies`), and load the recommended configuration for the market. + +```javascript reference +https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/deploy-kandel.js#L21-L25 +``` + +With this, you can generate a [distribution](../../kandel/how-does-kandel-work/step-by-step-visual-explanation.md#price-distribution) with the minimum recommended amount of liquidity to avoid %%density|density%% issues by: +* Creating a generator +* Calculating minimums per offer +* Calculating the distribution for the given price parameters of `minPrice: 900`, `maxPrice: 1100`, and default ratio + +See the API documentation for [calculateMinimumDistribution](../technical-references/code/classes/KandelDistributionGenerator.md#calculateminimumdistribution) for more details on other `priceParams`. In our example here, `midPrice: 1100` is used to set the [current price](../../kandel/how-does-kandel-work/parameters.md), and decide which offers become bids and which become asks. + +```javascript reference +https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/deploy-kandel.js#L27-L58 +``` + +The last three lines should output something similar to the following (actual volumes may differ due to different configuration for the market): + +``` bash +Number of price points: 21 +Minimum base volume: 1.91296 +Minimum quote volume: 1893.8304 +``` + +> 💡 +> The minimums depend on the price; if the price range is changed, then the minimums should be re-checked. + + +### Generate desired distribution + +Based on the minimum volumes we calculated, we can select a desired distribution with volumes above these values. Here we use `3` for base (WETH) and `3000` for quote (USDC). + +```javascript reference +https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/deploy-kandel.js#L60-L70 +``` + + +### Deploy Kandel instance + +Now, you can use the `seeder` to [sow](../technical-references/code/classes/KandelSeeder.md#sow) a Kandel instance for a given seed, and retrieve a `kandelInstance` to manage the deployed instance. + +```javascript reference +https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/deploy-kandel.js#L72-L82 +``` + +A brief explanation on the above `seed` parameters: +* `onAave` indicates whether or not the liquidity to be used by Kandel is sitting on AAVE - here, it is not the case (it will be fetched from a wallet) +* `market`: this is the WETH/USDC pair that we previously chose +* `liquiditySharing` indicates whether you are using shared liquidity or not (SDK only, not available via the UI). This refers to the concept [amplified liquidity](../../terms/amplified-liquidity.md). +* `gaspriceFactor`: + * By using the `recommendedConfig.gaspriceFactor`, we make sure to select the right amount of gas for our Kandel strategy + * This is also connected to the amount of [bounty](../../terms/bounty.md) to be paid in case of a failure to deliver + + +### Approve transfers + +The `kandelInstance` has functions for approving transfers for the base and quote tokens. This is required for the Kandel strategy to be able to transfer tokens from the wallet when depositing funds. + +```javascript reference +https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/deploy-kandel.js#L84-L89 +``` + +### Populate offers for the distribution + +Now that our Kandel instance is deployed, we can [populate the offers](../../kandel/how-does-kandel-work/step-by-step-visual-explanation.md#populating-bids-and-asks) for the distribution. +This will create offers for the base and quote tokens, and deposit the required amounts of tokens into the Kandel instance. + +The offers also need a %%provision|provision%%, hence here the default that we are using can be inspected. + +> 💡 +> The population can span multiple transactions due to gas limits. After this step, the Kandel offers are deployed and are ready to be taken! + +```javascript reference +https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/deploy-kandel.js#L91-L115 +``` + +### Manage existing Kandel instance + +Later on, you can also manage an existing Kandel instance. For example, you might want to inspect the status of your offers. For this, the [farm](../technical-references/code/classes/KandelFarm.md) can be used to retrieve Kandel instances you own based on events from the seeder. + +```javascript reference +https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/deploy-kandel.js#L117-L131 +``` + +### Close Kandel strategy and withdraw funds + +At some point, you might want to close your Kandel strategy (for instance due to price movements). This can be easily done with the [retractAndWithdraw](../technical-references/code/classes/KandelInstance.md#retractandwithdraw) function. It will withdraw all funds (both tokens and provision) from the Kandel instance and retract all offers. + +```javascript reference +https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/deploy-kandel.js#L132-L178 +``` diff --git a/docs/SDK/getting-started/preparation.md b/docs/SDK/getting-started/preparation.md new file mode 100644 index 00000000..9a66fc51 --- /dev/null +++ b/docs/SDK/getting-started/preparation.md @@ -0,0 +1,20 @@ +--- +description: Preparation for tutorials +sidebar_position: 1 +--- + +# Set Up Your Local Environment + +import Preamble from './_preparation-pre.md'; + + + +```bash +# To use the mangrove SDK +npm install --save dotenv +npm install --save @mangrovedao/mangrove.js@latest +``` + +import Post from './_preparation-post.md'; + + diff --git a/docs/SDK/guides/_category_.json b/docs/SDK/guides/_category_.json new file mode 100644 index 00000000..5824e635 --- /dev/null +++ b/docs/SDK/guides/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Guides", + "position": 3, + "collapsed": false +} \ No newline at end of file diff --git a/docs/SDK/guides/fill-or-kill.md b/docs/SDK/guides/fill-or-kill.md new file mode 100644 index 00000000..fa2752a0 --- /dev/null +++ b/docs/SDK/guides/fill-or-kill.md @@ -0,0 +1,73 @@ +--- +description: Create Fill or Kill order using mangrove.js +sidebar_position: 3 +--- + +# Use Fill or Kill + +## Intro + +This section will go through how to create a Fill or Kill ([FOK](https://www.investopedia.com/terms/f/fok.asp)) order using mangrove.js. + +We assume you know how to connect to Mangrove. We are going to be buying 2000 USDC at a maximum avg. price of 1.3. It is a requirement for this script to have enough USDC. If you do not have enough USDC, you can use a testnet and mint some USDC. This can either be done by going to our [dApp](https://testnet.mangrove.exchange/faucet) or by minting directly in the [script](https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/how-tos/fill-or-kill.js) (see the commented lines in the script about minting). + +### Approvals + +After having connected to Mangrove, we then have to make sure that we have the correct approvals for transferring our USDC tokens. When approving for transfers we have to determine what contract is going to make the actual transfers. If we were to use the normal [`buy`](../technical-references/code/classes/Market#-buy) function for a market, we would be using the Mangrove protocol, to make a standard [market order](../../contracts/technical-references/taking-and-making-offers/taker-order/README.md#market-order). This would mean that we would have to approve Mangrove to make transfers of USDC on our behalf. + +In this case we are not going to be using the Mangrove protocol directly. Instead we are going to be using a different contract, provided by the [Mangrove strat lib](../../strat-lib/README.md) - the [MangroveOrder](../../strat-lib/technical-references/code/strategies/MangroveOrder) contract. This contract makes it possible to make a real FoK order and not just a normal market order. This means that we need to approve the MangroveOrder contract to handle all our USDC transfers. One way of doing this, would be to just call approve directly on the USDC token, with the MangroveOrder contract as spender. But because strategies made with the Mangrove strat lib, can be using a more complex way of dealing with transfers, we should not rely on calling approve directly on the token. Instead we will create an %%OfferLogic|offer-logic%% using the MangroveOrder contract. This will provide us with an 'approveToken' function. This function will handle all the necessary approvals in order to use a token with the contract. + +```js reference +https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/how-tos/fill-or-kill.js#L27 +``` + +### Buying with MangroveOrder + +We are now ready to buy some DAI using a FoK order. It is very simple to do. Using the same method as for a market order (`buy`), we just give it an extra parameter `fillOrKill` which we set to true. This way we use the [MangroveOrder](../../strat-lib/technical-references/code/strategies/MangroveOrder) contract to buy. + +```js reference +https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/how-tos/fill-or-kill.js#L29-L37 +``` + +Here we show logs asks for the market before buying and after buying, you will see that the first 3 offers were taken. Offers 1669, 3344 and 1157 were all taken. But when we look at the result of the Fill or Kill order, we see that we got a %%bounty|bounty%%. This means that one of the offers failed and we got a bounty for making the offer fail. + + + + + +```js title="Asks before Fill or Kill order" +> market.consoleAsks(); +┌─────────┬──────┬──────────────────────────────────────────────┬────────────────────┬────────────────────────┐ +│ (index) │ id │ maker │ volume │ price │ +├─────────┼──────┼──────────────────────────────────────────────┼────────────────────┼────────────────────────┤ +│ 0 │ 1669 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 1376.6273438550415 │ 1.00346478817687987934 │ +│ 1 │ 3344 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1622.836373407379 │ 1.00346894837019272508 │ +│ 2 │ 1157 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 1163.3709308116254 │ 1.0034723140155791771 │ +│ 3 │ 4214 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1227.0562038171438 │ 1.003482667028260286 │ +│ 4 │ 930 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 1486.735792592364 │ 1.00348572922872847571 │ +│ 5 │ 3837 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1458.6523528414643 │ 1.00348711133850858816 │ +│ 6 │ 2721 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 629.9748527543823 │ 1.00348954285398244855 │ +│ 7 │ 2668 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1504.307740487991 │ 1.00349288205504048327 │ +``` + +```bash title="Result of Fill or Kill order" + summary: { + got: 2000, + gave: 2006.934268, + partialFill: false, + bounty: 0.000426, + feePaid: 0 + }, + successes: [], +``` + +```js title="Asks after fill or kill order" +> market.consoleAsks() +┌─────────┬──────┬──────────────────────────────────────────────┬────────────────────┬────────────────────────┐ +│ (index) │ id │ maker │ volume │ price │ +├─────────┼──────┼──────────────────────────────────────────────┼────────────────────┼────────────────────────┤ +│ 0 │ 4214 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1227.0562038171438 │ 1.003482667028260286 │ +│ 1 │ 930 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 1486.735792592364 │ 1.00348572922872847571 │ +│ 2 │ 3837 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1458.6523528414643 │ 1.00348711133850858816 │ +│ 3 │ 2721 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 629.9748527543823 │ 1.00348954285398244855 │ +``` diff --git a/docs/SDK/guides/reuse-offer.md b/docs/SDK/guides/reuse-offer.md new file mode 100644 index 00000000..b77f2aa3 --- /dev/null +++ b/docs/SDK/guides/reuse-offer.md @@ -0,0 +1,44 @@ +--- +description: Create fill or kill order using mangrove.js +sidebar_position: 4 +--- + +# Reuse Offer + +## Intro + +In this section we will go through how to reuse an offer, that has been taken or has failed. When an offer is taken, the offer still exists in Mangrove. This means that a previous offer made, can be reused again by the same maker. The same applies for an offer that failed when it was taken. The reason for keeping the offers around, is that cleaning up old/dead offers costs gas and by reusing a existing offer we save gas vs posting a completely new offer. This means that when we post an offer, we should save the %%Offer ID|offer-id%% for that offer, in case we ever want to reuse it. + +### Update existing offer + +In order to update an offer that is no longer live, we need the ID of an offer that has been taken or failed. In this example we are going to use ID 5573. If you do not have an offer that has been taken you can simply post a completely new offer and then snipe it. The [script](https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/how-tos/reuse-offer.js) has some commented out sections that helps with creating a dead offer. + +When we have a dead offer, then we can figure out how much %%provision|provision%% is needed when reposting it. This is done by using the [`computeAskProvision`](../technical-references/code/classes/LiquidityProvider#-computeaskprovision) given the offer id. The last thing we need is to give a wants and a gives for the offer. In this case we are going to use `wants: 1000.5` and `gives: 1000.4`. + +If we look at the asks before and after we have updated the offer, we now see that our offer has been updated and is at the top of the order book. + + + +```js reference +https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/how-tos/reuse-offer.js#L66-L78 +``` + +```js title="Asks before update"x +> market.consoleAsks(); +┌─────────┬──────┬──────────────────────────────────────────────┬────────────────────┬────────────────────────┐ +│ (index) │ id │ maker │ volume │ price │ +├─────────┼──────┼──────────────────────────────────────────────┼────────────────────┼────────────────────────┤ +│ 0 │ 1173 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 844.0536473037303 │ 1.00354291069746851135 │ +│ 1 │ 3003 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 280.69589368327456 │ 1.00354551434175376498 │ +│ 2 │ 967 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 578.3096271867598 │ 1.00355019649807276339 │ +``` + +```js title="Asks after update" +> market.consoleAsks(); +┌─────────┬──────┬──────────────────────────────────────────────┬────────────────────┬────────────────────────┐ +│ (index) │ id │ maker │ volume │ price │ +├─────────┼──────┼──────────────────────────────────────────────┼────────────────────┼────────────────────────┤ +│ 0 │ 5573 │ '0xA4C7c59EB3D4Ab5CA4E6fB012CeD9c8F9A5Ecdd8' │ 1000.4 │ 1.00009996001599360256 │ +│ 1 │ 1173 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 844.0536473037303 │ 1.00354291069746851135 │ +│ 2 │ 3003 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 280.69589368327456 │ 1.00354551434175376498 │ +``` diff --git a/docs/SDK/guides/sell-and-buy-orders.md b/docs/SDK/guides/sell-and-buy-orders.md new file mode 100644 index 00000000..e65a287b --- /dev/null +++ b/docs/SDK/guides/sell-and-buy-orders.md @@ -0,0 +1,32 @@ +--- +description: Using the API to pass taker orders on a Mangrove market. +sidebar_position: 4 +--- + +# Sell and buy orders + +Buying with cash or selling for cash can be done via the [`buy`](../technical-references/code/classes/Market.md#-buy) and [`sell`](../technical-references/code/classes/Market.md#-sell) functions of a [Market](../technical-references/api-overview.md#market) instance. The code snippets below send limit buy (taker) orders on the market, with an allowed slippage of 2%: + +```typescript +// buy limit order for 100 base tokens at an average price of 0.1 quote per base +const buyPromises = await mgvMarket.buy({volume:100, price:0.1, slippage:2}); +const buyResult = await buyPromises.result; +// limit order with a desired quantitiy +const butPromises_ = await mgvMarket.buy({wants:100, gives:1000, slippage:2}); +const buyResult_ = await buyPromises_.result; +// sell limit order (selling 10 base tokens). +const sellPromises = await mgvMarket.sell({volume:10, price: 0.09, slippage:2}); +const sellResult = await sellPromises.result; +``` + +:::info + +`sell` and `buy` orders return a pair `{ response: Promise, result: Promise }` + +The result (`OrderResult`) returns a triple `{`takerGave:Big, takerGot:Big, bounty:Big`}` where: + +* `takerGave` is the total amount of base (for a sell) or quote (for a buy) tokens that the taker spent for the order +* `takerGot` is the total amount of quote (for a sell) or base (for a buy) tokens that the taker received as a result of the order +* `bounty` is the amount of native tokens the taker received to compensate for the gas lost of executing failing offer during the order execution see %%bounty|bounty%%. + +::: diff --git a/docs/SDK/guides/snipe-offer.md b/docs/SDK/guides/snipe-offer.md new file mode 100644 index 00000000..b9548206 --- /dev/null +++ b/docs/SDK/guides/snipe-offer.md @@ -0,0 +1,101 @@ +--- +description: Snipe a offer using mangrove.js +sidebar_position: 2 +--- + +# Snipe An Offer + +## Intro + +This will go through sniping an offer using mangrove.js. In this section we assume that you already know how to connect to Mangrove either on a real chain or on a local chain. When sniping we need to make sure that we actually have the funds. If we do not have the funds the transaction will revert with the error `mgv/takerTransferFail`. This means that the taker is the cause of the failed transfer and since we are trying to snipe an offer, we are the taker. Another result could be that the transfer failed because of the maker, then we will get this error `mgv/makerTransferFail`. This means that for some reason the makers funds was not transferred and the transfer therefore failed. In this case the taker (us), will be compensated for the gas we just used to make the offer fail. We are compensated in form of a %%bounty|bounty%%. + +### Connect to market (and mint tokens) + +As mentioned we assume that you are already connected to Mangrove, if not you can look at [github](https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/how-tos/snipe-offer.js), to see the full script. + +When connected to Mangrove we need to connect to a market. We do this to check whether the market is live and has offers. In this case we look at all the asks for the market. In this case the best offer is id 5572. Another way to check the market is to go to [testnet](https://testnet.mangrove.exchange/trade) and look at the DAI-USDC market. + +If we want to snipe this offer, then it requires that we have enough USDC. In this case we need $$100.5 \times 1.00345 \approx 100.85$$. If we look at UI for the testnet, we will also be able to see that the required USDC is 100.85. + +If you do not have the funds need for this, we can mint them using the commented out lines 4 to 7 below. In this example we mint 10.000 USDC, which is plenty for taking this offer. + +```js +> market.consoleAsks(); +┌─────────┬──────┬──────────────────────────────────────────────┬────────────────────┬────────────────────────┐ +│ (index) │ id │ maker │ volume │ price │ +├─────────┼──────┼──────────────────────────────────────────────┼────────────────────┼────────────────────────┤ +│ 0 │ 5572 │ '0xA4C7c59EB3D4Ab5CA4E6fB012CeD9c8F9A5Ecdd8' │ 100.5 │ 1.00345 │ +│ 1 │ 3137 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1883.81894460173 │ 1.00346413248309787013 │ +│ 2 │ 1384 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 1143.1714506162793 │ 1.00346467660785745789 │ +│ 3 │ 1669 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 1376.6273438550415 │ 1.00346478817687987934 │ +``` + +import useBaseUrl from '@docusaurus/useBaseUrl'; + +
+ +
UI of offers
+
+ +```javascript showLineNumbers reference +https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/how-tos/snipe-offer.js#L15-L24 +``` + +### Snipe best offer + +We now know that we want to snipe the best offer on the book, which is offer 5572. In order to snipe the offer, want to get all the info about the offer. We do this because we want the precise numbers for wants and gives. + +Before sniping the offer with the information we just gathered, we have to [approve](../../strat-lib/guides/approvals.md) Mangrove to be able to take the funds (USDC), from our account. We need to do this, because when taking any offer, the first thing Mangrove does, is to transfer the takers funds to Mangrove and from Mangrove to the maker. If we have not approved this, the transfer will fail with a `mgv/takerTransferFail`. + +We can now snipe the offer. Be ware that the information on the offer, is from the makers side. This means that what we, the taker, wants is what the offer (the maker) gives. Similarly with gives; what we, the taker, gives, is what the offer (the maker) wants. When taking a offer we should be aware that if we do not give a %%`gasLimit`|gasLimit%%, mangrove.js will get the `gasLimit` from the offer's %%`gasreq`|gasreq%%. The `gasLimit` sets a limit on how much gas we max want to use, when taking the offer. This way we can control, that if it is very costly to take the offer and it ends up costing more than our `gasLimit`, then the transfer will revert. + +```javascript reference +https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/how-tos/snipe-offer.js#L27-L50 +``` + +### Check the result of sniping + +After sniping we will get a result. We can look at the result to see if the transaction was successful or failed. + +If the transaction was successful then we should see a result like this. In this case we sniped offerId 5572, we got 100.5 `DAI` and gave 100.6 `USDC`. + +```bash title="Snipe successful" + feePaid: 0 + }, + successes: [ { offerId: 5572, got: 100.5, gave: 100.6 } ], + tradeFailures: [], + posthookFailures: [], +``` + +If the transaction failed, it is most likely that the account that posted the offer (the maker) couldn't complete the transaction. Because of this we will receive a %%bounty|bounty%% for making an offer fail. If sniped your own offer after following the [Post a simple offer](../getting-started/basic-offer.md) and it failed, then you most likely lack the DAI to fulfil the offer - try minting some. + +```bash title="Snipe failed because of maker" + events: [ [Object], [Object], [Object], [Object] ] + }, + summary: { got: 0, gave: 0, partialFill: false, bounty: 0.000426, feePaid: 0 }, + successes: [], + tradeFailures: [ + { + offerId: 3137, + reason: '0x6d67762f6d616b65725472616e736665724661696c0000000000000000000000', + FailToDeliver: 1883.81894460173, + volumeGiven: 1890.344743 + } + ], +``` + +We will also see the offer being gone when we log the asks on the market. + +```javascript reference +https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/how-tos/snipe-offer.js#L52-L56 +``` + +```js +> market.consoleAsks(); +┌─────────┬──────┬──────────────────────────────────────────────┬────────────────────┬────────────────────────┐ +│ (index) │ id │ maker │ volume │ price │ +├─────────┼──────┼──────────────────────────────────────────────┼────────────────────┼────────────────────────┤ +│ 0 │ 1384 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 1143.1714506162793 │ 1.00346467660785745789 │ +│ 1 │ 1669 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 1376.6273438550415 │ 1.00346478817687987934 │ +│ 2 │ 3344 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1622.836373407379 │ 1.00346894837019272508 │ +``` diff --git a/docs/SDK/guides/update-offer.md b/docs/SDK/guides/update-offer.md new file mode 100644 index 00000000..44d34178 --- /dev/null +++ b/docs/SDK/guides/update-offer.md @@ -0,0 +1,74 @@ +--- +description: How to update an offer using mangrove.js +sidebar_position: 1 +--- + +# Update Your Offer + +## Intro + +This will explain how you update an offer using mangrove.js. + +Since you need to have an offer on the book in order to update it, this will assume that you already have an offer on the book. In this case we will use the offer id 5572. But make sure you use your own offer id. See for instance [Post a simple offer](../getting-started/basic-offer.md). + +### Update offer + +We start by logging all the asks on the DAI-USDC market. For this guide we will assume that the offer is an ask on the DAI-USDC market. If your offer is on another market, make sure to connect to the market where your offer is posted. + +Here we can see that my offer has a volume of 100.5 and a price of 1.00099. Lets say we want to update the offer to match the price of the next best offer. + +```js +market.consoleAsks(); +``` + +```bash +┌─────────┬──────┬──────────────────────────────────────────────┬────────────────────┬────────────────────────┐ +│ (index) │ id │ maker │ volume │ price │ +├─────────┼──────┼──────────────────────────────────────────────┼────────────────────┼────────────────────────┤ +│ 0 │ 5572 │ '0xA4C7c59EB3D4Ab5CA4E6fB012CeD9c8F9A5Ecdd8' │ 100.5 │ 1.00099502487562189055 │ +│ 1 │ 3137 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1883.81894460173 │ 1.00346413248309787013 │ +│ 2 │ 1384 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 1143.1714506162793 │ 1.00346467660785745789 │ +│ 3 │ 1669 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 1376.6273438550415 │ 1.00346478817687987934 │ +``` + +To update the offer we use the [`updateAsk`](../technical-references/code/classes/LiquidityProvider.md#-updateask) function on our `liquidityProvider`. This has two options available in the [OfferParams](../technical-references/code/namespaces/LiquidityProvider-1.md#offerparams). First, you can provide `wants` and `gives`. If we chose to use this, we would have to calculate what `gives` should be, given that `wants` stays a 100.5 and we want the price to be slightly better than the next best offer, e.g. 1.00345. $$\frac{wants}{price}=gives$$ -> $$\frac{100.5}{1.00345}\approx 100.1494$$. + +Second, you can provide `volume` and `price`, since this is exactly what we want to use, we don't have to calculate `gives`. We then just update the offer using `volume: 100.5` and `price: 1.00345`. + +```js reference +https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/how-tos/update-offer.js#L23-L41 +``` + +```bash +┌─────────┬──────┬──────────────────────────────────────────────┬────────────────────┬────────────────────────┐ +│ (index) │ id │ maker │ volume │ price │ +├─────────┼──────┼──────────────────────────────────────────────┼────────────────────┼────────────────────────┤ +│ 0 │ 5572 │ '0xA4C7c59EB3D4Ab5CA4E6fB012CeD9c8F9A5Ecdd8' │ 100.5 │ 1.00345 │ +│ 1 │ 3137 │ '0x2CB51201CD176CcEa67a9c0B64391aE34e50C058' │ 1883.81894460173 │ 1.00346413248309787013 │ +│ 2 │ 1384 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 1143.1714506162793 │ 1.00346467660785745789 │ +│ 3 │ 1669 │ '0x4326Ab97823d7509C1f0CB3bF68151081B26c970' │ 1376.6273438550415 │ 1.00346478817687987934 │ +``` + +Changing the price of an offer can change its %%rank|offer-rank%% in the offer book. + +### Update offer using OfferLogic + +When we updated our offer before, we used a `liquidityProvider` and we created this using Mangrove. This means that when we updated our offer, we did using Mangrove directly. But if you have your own contract with your own update offer logic, you can use that by creating an [`OfferLogic`](../technical-references/code/classes/OfferLogic). This is simply done by calling the constructor with Mangrove (remember to import the type first, e.g., using `const { OfferLogic } = require("@mangrovedao/mangrove.js");`). + +```js reference +https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/how-tos/update-offer.js#L43-L46 +``` + +When you have a OfferLogic you can the call update offer directly on the underlying contract (which is assumed to implement the [`ILiquidityProvider` interface](../../strat-lib/technical-references/code/strategies/interfaces/ILiquidityProvider.md), but this requires a lot more info and unit conversions. + +```js reference +https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/how-tos/update-offer.js#L49-L60 +``` + +To keep things more simple you can create a `liquidityProvider` with your offerLogic and a market. This way the LiquidityProvider will make sure to update your offer using your offerLogic. This saves you for taking any other decisions than `wants` and `gives` or `volume` and `price`. + +```js reference +https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/how-tos/update-offer.js#L62-L67 +``` + +You can only update offers you own as a maker. And from the `consoleAsks()` above you can see the `maker` of each offer. So for instance, you cannot update an offer posted directly in [Post a simple offer](../getting-started/basic-offer.md) using your `offerLogic`'s `liquitidyProvider` - it has to be an offer posted by the `offerLogic`. diff --git a/docs/SDK/technical-references/_category_.json b/docs/SDK/technical-references/_category_.json new file mode 100644 index 00000000..c9ffec35 --- /dev/null +++ b/docs/SDK/technical-references/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Technical Reference", + "position": 4, + "collapsed": false +} \ No newline at end of file diff --git a/docs/SDK/technical-references/api-overview.md b/docs/SDK/technical-references/api-overview.md new file mode 100644 index 00000000..fc0735bb --- /dev/null +++ b/docs/SDK/technical-references/api-overview.md @@ -0,0 +1,188 @@ +--- +sidebar_position: 0 +--- + +# SDK Overview + +:::info **Numbers** + +* Numbers returned by functions are either plain JavaScript [`number`](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Global\_Objects/Number) or [`big.js`](https://github.com/MikeMcl/big.js/)instances. Some functions with names ending in `Raw` may return`ethers.BigNumbers`. +* As input, numbers can be as plain JavaScript `numbers`, `big.js` instances, but also a`string`. + +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: + +```typescript +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](../../contracts/technical-references/contract-addresses.md) 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](https://www.investopedia.com/terms/b/bid.asp) and [asks](https://www.investopedia.com/terms/a/ask.asp) on Mangrove) objects. + +:::info + +`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](https://eips.ethereum.org/EIPS/eip-20). To obtain an instance use: + +```javascript +mgvTkn = await mgv.token(""); // e.g "DAI", "WETH", "amDAI", etc. +``` + +with the above `MgvT` object one has access to standard calls using human readable input/outputs. For instance: + +```javascript +await mgvTkn.approve(""); // gives infinite approval to spender +await mgvTkn.approve("",0.5); // gives allowance to spend 0.5 token units to spender +await mgvTkn.contract.approve("", mgvTkn.mgv.toUnits(0.5)); // ethers.js call +``` + +Note that Mangrove's API deals with token decimals automatically (see definitions in [`constants.ts`](https://github.com/mangrovedao/mangrove/blob/master/packages/mangrove.js/src/constants.ts)). + +:::info + +`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](../guides/sell-and-buy-orders.md). To obtain one instance use: + +```typescript +//connect to a (base,quote) market with default options +mgvMarket = await mgv.connect({base:"", quote:""}); + +// connect to the market, caching the first 50 best bids and asks +mgvMarket = await mgv.connect({base:"", quote:"", maxOffers: 50}); +``` + +:::info + +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:})`. + +::: + +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: + +```typescript +// 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: + +```javascript +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 bid `offer` is removed from the book +* `{type: 'OfferWrite', ba:'asks'|'bids', offer:Market.Offer}` when a bid or ask `offer` is added to the book (or updated) +* `{type:'OfferFail', ba:'asks'|'bids', taker:string, 'takerWants':Big, takerGives:Big, mgvData:string, offer:Market.Offer}` when `offer` failed to deliver. Note that `mgvData` 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}` when `offer` was successfully executed (possibly on a partial fill whenever `offer.gives`>`takerWants`). + +and where `Market.Offer` has the following main fields: + +```typescript +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](https://docs.mangrove.exchange/data-structures/market) is managed by a smart contract which implements its [logic](api-overview.md#offerlogic). One may use the API to post liquidity on Mangrove via a deployed logic that complies to the [IOfferLogic](https://github.com/mangrovedao/mangrove/blob/master/packages/mangrove-solidity/contracts/Strategies/interfaces/IOfferLogic.sol) interface. To do so, one first need an `OfferLogic` instance: + +```typescript +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: + +```javascript +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 +``` + +:::danger + +When using an offer logic that inherits from the [`MultiUser.sol`](https://github.com/mangrovedao/mangrove/blob/master/packages/mangrove-solidity/contracts/Strategies/OfferLogics/MultiUsers/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](../getting-started/basic-offer.md) or to post an offer relying on some on-chain [logic](api-overview.md#offerlogic). + +To act as a direct liquidity provider on a [`mgvMarket`](api-overview.md#market) you must obtain a `LiquidityProvider` instance from an [`mgv`](api-overview.md#mangrove) object using: + +```javascript +const mgvDirectLP = await mgv.liquidityProvider(mgvMarket); +``` + +:::info + +The EOA providing the liquidity for ask and bid offers emanating from a direct liquidity provider is the address of the [`mgv`](api-overview.md#mangrove)'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: + +```javascript +const mgvOnchainLP = await mgvLogic.liquidityProvider(mgvMarket); +``` + +Besides posting offers on Mangrove, a `LiquidityProvider` instance `mgvLP` gives access to various useful functions such as: + +```javascript +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: + +```javascript +const ethersTx = await mgvLP.fundMangrove(missingAskProvision); +await ethersTx.wait(); // waiting for the funding tx to be confirmed +``` diff --git a/docusaurus.config.js b/docusaurus.config.js index 6d958ca8..447b35f8 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -129,49 +129,19 @@ const config = { }, items: [ { - to: '/high-level', - position: 'left', - label: 'Concepts', - }, - { - to: '/web-app', - position: 'left', - label: 'Web App', - }, - { - to: '/kandel', - position: 'left', - label: 'Kandel', - }, - { - to: '/contracts', - position: 'left', - label: 'Protocol', - }, - { - to: '/strat-lib', - position: 'left', - label: 'Strat Lib', - }, - { - to: '/SDK', - position: 'left', - label: 'SDK', - }, - { - to: '/FAQ', + to: 'https://app.mangrove.exchange/', position: 'right', - label: 'FAQ', + label: '🌳 App', }, { - href: 'https://bafybeig62o75bfxssic66w2zwerbo6ezlhb33vsg5idr4uprckn2dxrucy.ipfs.infura-ipfs.io/', - label: 'White Paper', + to: 'https://github.com/mangrovedao', position: 'right', + label: '👾 GitHub', }, { - href: 'https://github.com/mangrovedao', - label: 'GitHub', + to: 'https://twitter.com/MangroveDAO', position: 'right', + label: '🐦 Twitter', }, ], }, diff --git a/sidebars.js b/sidebars.js index 62593262..d5300830 100644 --- a/sidebars.js +++ b/sidebars.js @@ -15,48 +15,87 @@ const sidebars = { // By default, Docusaurus generates a sidebar from the docs folder structure - mangrovehighleveldocSidebar: [ { - type: 'autogenerated', - dirName: 'high-level' + docsSidebar: [ + + { + type: 'category', + label: 'Concepts', + items: [ + { + type: 'autogenerated', + dirName: 'high-level', // Generate sidebar slice from docs/high-level + }, + ], }, - ], - webappdocSidebar: [ { - type: 'autogenerated', - dirName: 'web-app' + { + type: 'category', + label: 'Web App', + items: [ + { + type: 'autogenerated', + dirName: 'web-app', + }, + ], }, - ], - kandeldocSidebar: [ { - type: 'autogenerated', - dirName: 'kandel' + { + type: 'category', + label: 'Kandel', + items: [ + { + type: 'autogenerated', + dirName: 'kandel', + }, + ], }, - ], - contractsSidebar: [ { - type: 'autogenerated', - dirName: 'contracts' + { + type: 'category', + label: 'Contracts', + items: [ + { + type: 'autogenerated', + dirName: 'contracts', + }, + ], }, - ], - stratLibSidebar: [ { - type: 'autogenerated', - dirName: 'strat-lib' + { + type: 'category', + label: 'Strat Lib', + items: [ + { + type: 'autogenerated', + dirName: 'strat-lib', + }, + ], }, - ], - sdkSidebar: [ { - type: 'autogenerated', - dirName: 'SDK' + type: 'category', + label: 'SDK', + items: [ + { + type: 'autogenerated', + dirName: 'SDK', + }, + ], }, - ], - keeperBotsSidebar: [ { - type: 'autogenerated', - dirName: 'keeper-bots' + type: 'category', + label: 'Keeper Bots', + items: [ + { + type: 'autogenerated', + dirName: 'keeper-bots', + }, + ], }, - ], - termSidebar: [ - 'glossary', { - type: 'autogenerated', - dirName: 'terms' + type: 'category', + label: 'Glossary', + items: [ + { + type: 'autogenerated', + dirName: 'terms', + }, + ], }, ], }; diff --git a/src/css/custom.css b/src/css/custom.css index 6689edf2..d8bb526d 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -55,7 +55,7 @@ table { } [data-theme='dark'] .navbar { - background-color: #051817; + background-color: #051b1a; } @media screen and (min-width: 996px) and (max-width: 1239px) { @@ -89,11 +89,11 @@ table { } [data-theme='dark'] .hero--primary { - background-color: #072221; + background-color: #051b1a; } .footer { - background-color: #051817; + background-color: #051b1a; } .hero-image { diff --git a/src/pages/index.js b/src/pages/index.js deleted file mode 100644 index 42ec8b77..00000000 --- a/src/pages/index.js +++ /dev/null @@ -1,35 +0,0 @@ -import React from 'react'; -import clsx from 'clsx'; -import Link from '@docusaurus/Link'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import Layout from '@theme/Layout'; -import HomepageSections from '@site/src/components/HomepageSections'; -import useBaseUrl from '@docusaurus/useBaseUrl'; - -import styles from './index.module.css'; - -function HomepageHeader() { - const {siteConfig} = useDocusaurusContext(); - return ( -
-
- -

Welcome to Mangrove Docs

-
-
- ); -} - -export default function Home() { - const {siteConfig} = useDocusaurusContext(); - return ( - - -
- -
-
- ); -} From e3d94ad3cdca8132156998a9b43b6a180ff63678 Mon Sep 17 00:00:00 2001 From: frkralj Date: Mon, 25 Sep 2023 20:49:43 +0200 Subject: [PATCH 05/38] bug fix homepage --- src/pages/index.js | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/pages/index.js diff --git a/src/pages/index.js b/src/pages/index.js new file mode 100644 index 00000000..42ec8b77 --- /dev/null +++ b/src/pages/index.js @@ -0,0 +1,35 @@ +import React from 'react'; +import clsx from 'clsx'; +import Link from '@docusaurus/Link'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import Layout from '@theme/Layout'; +import HomepageSections from '@site/src/components/HomepageSections'; +import useBaseUrl from '@docusaurus/useBaseUrl'; + +import styles from './index.module.css'; + +function HomepageHeader() { + const {siteConfig} = useDocusaurusContext(); + return ( +
+
+ +

Welcome to Mangrove Docs

+
+
+ ); +} + +export default function Home() { + const {siteConfig} = useDocusaurusContext(); + return ( + + +
+ +
+
+ ); +} From f29283795fcd33b55352d17976608c2673f65084 Mon Sep 17 00:00:00 2001 From: frkralj Date: Tue, 26 Sep 2023 11:52:24 +0200 Subject: [PATCH 06/38] more tweaks --- docs/SDK/background/_category_.json | 2 +- docs/SDK/getting-started/_category_.json | 2 +- docs/SDK/guides/_category_.json | 2 +- docs/SDK/technical-references/_category_.json | 2 +- docs/contracts/README.md | 2 +- docs/contracts/background/_category_.json | 2 +- .../contracts/getting-started/_category_.json | 2 +- docs/contracts/guides/_category_.json | 2 +- .../technical-references/_category_.json | 2 +- docs/high-level/concepts/_category_.json | 4 +- .../makers-takers-keepers/_category_.json | 2 +- docs/high-level/ecosystem/_category_.json | 2 +- docs/{high-level/README.md => homepage.md} | 59 ++++---- docs/kandel/details-on-strats/_category_.json | 2 +- .../how-does-kandel-work/_category_.json | 2 +- docs/kandel/potential-risks/_category_.json | 2 +- docs/keeper-bots/background/_category_.json | 2 +- .../getting-started/_category_.json | 2 +- docs/keeper-bots/guides/_category_.json | 2 +- .../technical-reference/_category_.json | 2 +- docs/strat-lib/background/_category_.json | 2 +- .../strat-lib/getting-started/_category_.json | 2 +- docs/strat-lib/guides/_category_.json | 2 +- .../technical-references/_category_.json | 2 +- .../how-to-connect-wallet/_category_.json | 2 +- docs/web-app/strategies/_category_.json | 2 +- .../key-actions-questions/_category_.json | 2 +- .../strategies/manage-strat/_category_.json | 2 +- docs/web-app/swap/_category_.json | 2 +- docs/web-app/trade/_category_.json | 2 +- docusaurus.config.js | 123 ++-------------- sidebars.js | 136 +++++++++++++++--- src/css/custom.css | 20 +-- 33 files changed, 193 insertions(+), 205 deletions(-) rename docs/{high-level/README.md => homepage.md} (76%) diff --git a/docs/SDK/background/_category_.json b/docs/SDK/background/_category_.json index 0cea9dd7..bdf60ff7 100644 --- a/docs/SDK/background/_category_.json +++ b/docs/SDK/background/_category_.json @@ -1,5 +1,5 @@ { "label": "Background", "position": 5, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docs/SDK/getting-started/_category_.json b/docs/SDK/getting-started/_category_.json index 90993058..c411717a 100644 --- a/docs/SDK/getting-started/_category_.json +++ b/docs/SDK/getting-started/_category_.json @@ -1,5 +1,5 @@ { "label": "Getting Started", "position": 2, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docs/SDK/guides/_category_.json b/docs/SDK/guides/_category_.json index 5824e635..9a13fa6c 100644 --- a/docs/SDK/guides/_category_.json +++ b/docs/SDK/guides/_category_.json @@ -1,5 +1,5 @@ { "label": "Guides", "position": 3, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docs/SDK/technical-references/_category_.json b/docs/SDK/technical-references/_category_.json index c9ffec35..25b739bd 100644 --- a/docs/SDK/technical-references/_category_.json +++ b/docs/SDK/technical-references/_category_.json @@ -1,5 +1,5 @@ { "label": "Technical Reference", "position": 4, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docs/contracts/README.md b/docs/contracts/README.md index 60ad1dd4..e6f5c820 100644 --- a/docs/contracts/README.md +++ b/docs/contracts/README.md @@ -15,7 +15,7 @@ The order book of Mangrove lists promises to trade, instead of locked commitment * [Governance](technical-references/governance-parameters/README.md) adjusts Mangrove parameters, sets fees, and opens and closes new markets. > 💡 -> For non technical information about Mangrove, check out the [Concepts](../high-level/README.md) section. +> For non technical information about Mangrove, check out the [Concepts](../homepage) section. ## Where do I start? diff --git a/docs/contracts/background/_category_.json b/docs/contracts/background/_category_.json index 0cea9dd7..bdf60ff7 100644 --- a/docs/contracts/background/_category_.json +++ b/docs/contracts/background/_category_.json @@ -1,5 +1,5 @@ { "label": "Background", "position": 5, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docs/contracts/getting-started/_category_.json b/docs/contracts/getting-started/_category_.json index 90993058..c411717a 100644 --- a/docs/contracts/getting-started/_category_.json +++ b/docs/contracts/getting-started/_category_.json @@ -1,5 +1,5 @@ { "label": "Getting Started", "position": 2, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docs/contracts/guides/_category_.json b/docs/contracts/guides/_category_.json index 5824e635..9a13fa6c 100644 --- a/docs/contracts/guides/_category_.json +++ b/docs/contracts/guides/_category_.json @@ -1,5 +1,5 @@ { "label": "Guides", "position": 3, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docs/contracts/technical-references/_category_.json b/docs/contracts/technical-references/_category_.json index c9ffec35..25b739bd 100644 --- a/docs/contracts/technical-references/_category_.json +++ b/docs/contracts/technical-references/_category_.json @@ -1,5 +1,5 @@ { "label": "Technical Reference", "position": 4, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docs/high-level/concepts/_category_.json b/docs/high-level/concepts/_category_.json index cc5e2d2f..5ea525ed 100644 --- a/docs/high-level/concepts/_category_.json +++ b/docs/high-level/concepts/_category_.json @@ -1,5 +1,5 @@ { - "label": "Concepts", + "label": "Core", "position": 1, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docs/high-level/concepts/makers-takers-keepers/_category_.json b/docs/high-level/concepts/makers-takers-keepers/_category_.json index f337541d..e0006269 100644 --- a/docs/high-level/concepts/makers-takers-keepers/_category_.json +++ b/docs/high-level/concepts/makers-takers-keepers/_category_.json @@ -1,5 +1,5 @@ { "label": "Makers, Takers, Keepers", "position": 3, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docs/high-level/ecosystem/_category_.json b/docs/high-level/ecosystem/_category_.json index 4aa8a5e4..b476755c 100644 --- a/docs/high-level/ecosystem/_category_.json +++ b/docs/high-level/ecosystem/_category_.json @@ -1,5 +1,5 @@ { "label": "Ecosystem", "position": 2, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docs/high-level/README.md b/docs/homepage.md similarity index 76% rename from docs/high-level/README.md rename to docs/homepage.md index e545f5d1..ba9d2062 100644 --- a/docs/high-level/README.md +++ b/docs/homepage.md @@ -1,30 +1,29 @@ ---- -description: What is Mangrove? -sidebar_position: 1 ---- - - -# What is Mangrove? - -It's a Decentralized Exchange (DEX)! On Mangrove, you can trade, swap tokens and create blueprint trading strategies or brand new ones. On Mangrove, we refer to strategies as programs which will run certain trading behavior, whose goal is to make profits (ex: buy low, sell high). - -> 💡 -> For a concrete example of strategies on Mangrove, check out the [Kandel strategy](../kandel/README.md) documentation. - - -## The orderbook model - -Mangrove is based on an "order book" model, which you may know from traditional finance exchanges. However, Mangrove is particular in that it allows liquidity providers to post arbitrary smart contracts as offers. What that means, is that the **listed offers can point to pieces of code**: we call them [Smart Offers](../terms/smart-offer.md). 🤓 - -As you can imagine, this new flexibility enables participants to post offers that are not fully provisioned. The Mangrove's order book **lists promises instead of locked commitments**. - -> 💡 -> There might be new words and concepts for you in here, and that's okay: we will provide you with either direct explanations or links and references. Feel free to check our [Glossary](../glossary.md) and [FAQ](../FAQ/README.md) as well, it might help! - - -## Making promises - -The promised liquidity can be shared, borrowed, lent somewhere **and at the same time** displayed on Mangrove, ready to be sourced when (and only when) an offer is taken. -The resulting consequences are far-reaching, because it removes liquidity fragmentation and the lock on assets, allowing its use in multiple places. 🔐 - -If you're curious about the unique features of Mangrove DEX enabled by Smart Offers, head over to our [Concepts section](./concepts/smart-offers.md). \ No newline at end of file +--- +title: Homepage +sidebar_position: 0 +--- + +# What is Mangrove? + +It's a Decentralized Exchange (DEX)! On Mangrove, you can trade, swap tokens and create blueprint trading strategies or brand new ones. On Mangrove, we refer to strategies as programs which will run certain trading behavior, whose goal is to make profits (ex: buy low, sell high). + +> 💡 +> For a concrete example of strategies on Mangrove, check out the [Kandel strategy](./kandel/README.md) documentation. + + +## The orderbook model + +Mangrove is based on an "order book" model, which you may know from traditional finance exchanges. However, Mangrove is particular in that it allows liquidity providers to post arbitrary smart contracts as offers. What that means, is that the **listed offers can point to pieces of code**: we call them [Smart Offers](./terms/smart-offer.md). 🤓 + +As you can imagine, this new flexibility enables participants to post offers that are not fully provisioned. The Mangrove's order book **lists promises instead of locked commitments**. + +> 💡 +> There might be new words and concepts for you in here, and that's okay: we will provide you with either direct explanations or links and references. Feel free to check our [Glossary](./glossary.md) and [FAQ](./FAQ/README.md) as well, it might help! + + +## Making promises + +The promised liquidity can be shared, borrowed, lent somewhere **and at the same time** displayed on Mangrove, ready to be sourced when (and only when) an offer is taken. +The resulting consequences are far-reaching, because it removes liquidity fragmentation and the lock on assets, allowing its use in multiple places. 🔐 + +If you're curious about the unique features of Mangrove DEX enabled by Smart Offers, head over to our [Concepts section](./high-level/concepts/smart-offers.md). \ No newline at end of file diff --git a/docs/kandel/details-on-strats/_category_.json b/docs/kandel/details-on-strats/_category_.json index f6716948..ced583fb 100644 --- a/docs/kandel/details-on-strats/_category_.json +++ b/docs/kandel/details-on-strats/_category_.json @@ -1,5 +1,5 @@ { "label": "Details on strategies", "position": 3, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docs/kandel/how-does-kandel-work/_category_.json b/docs/kandel/how-does-kandel-work/_category_.json index 73d4b1dd..d768c88b 100644 --- a/docs/kandel/how-does-kandel-work/_category_.json +++ b/docs/kandel/how-does-kandel-work/_category_.json @@ -1,5 +1,5 @@ { "label": "How does Kandel work?", "position": 2, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docs/kandel/potential-risks/_category_.json b/docs/kandel/potential-risks/_category_.json index ecafdc82..d1b06f8b 100644 --- a/docs/kandel/potential-risks/_category_.json +++ b/docs/kandel/potential-risks/_category_.json @@ -1,5 +1,5 @@ { "label": "Potential risks", "position": 4, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docs/keeper-bots/background/_category_.json b/docs/keeper-bots/background/_category_.json index 0cea9dd7..bdf60ff7 100644 --- a/docs/keeper-bots/background/_category_.json +++ b/docs/keeper-bots/background/_category_.json @@ -1,5 +1,5 @@ { "label": "Background", "position": 5, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docs/keeper-bots/getting-started/_category_.json b/docs/keeper-bots/getting-started/_category_.json index 90993058..c411717a 100644 --- a/docs/keeper-bots/getting-started/_category_.json +++ b/docs/keeper-bots/getting-started/_category_.json @@ -1,5 +1,5 @@ { "label": "Getting Started", "position": 2, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docs/keeper-bots/guides/_category_.json b/docs/keeper-bots/guides/_category_.json index 5824e635..9a13fa6c 100644 --- a/docs/keeper-bots/guides/_category_.json +++ b/docs/keeper-bots/guides/_category_.json @@ -1,5 +1,5 @@ { "label": "Guides", "position": 3, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docs/keeper-bots/technical-reference/_category_.json b/docs/keeper-bots/technical-reference/_category_.json index c9ffec35..25b739bd 100644 --- a/docs/keeper-bots/technical-reference/_category_.json +++ b/docs/keeper-bots/technical-reference/_category_.json @@ -1,5 +1,5 @@ { "label": "Technical Reference", "position": 4, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docs/strat-lib/background/_category_.json b/docs/strat-lib/background/_category_.json index 0cea9dd7..bdf60ff7 100644 --- a/docs/strat-lib/background/_category_.json +++ b/docs/strat-lib/background/_category_.json @@ -1,5 +1,5 @@ { "label": "Background", "position": 5, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docs/strat-lib/getting-started/_category_.json b/docs/strat-lib/getting-started/_category_.json index 90993058..c411717a 100644 --- a/docs/strat-lib/getting-started/_category_.json +++ b/docs/strat-lib/getting-started/_category_.json @@ -1,5 +1,5 @@ { "label": "Getting Started", "position": 2, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docs/strat-lib/guides/_category_.json b/docs/strat-lib/guides/_category_.json index 5824e635..9a13fa6c 100644 --- a/docs/strat-lib/guides/_category_.json +++ b/docs/strat-lib/guides/_category_.json @@ -1,5 +1,5 @@ { "label": "Guides", "position": 3, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docs/strat-lib/technical-references/_category_.json b/docs/strat-lib/technical-references/_category_.json index c9ffec35..25b739bd 100644 --- a/docs/strat-lib/technical-references/_category_.json +++ b/docs/strat-lib/technical-references/_category_.json @@ -1,5 +1,5 @@ { "label": "Technical Reference", "position": 4, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docs/web-app/how-to-connect-wallet/_category_.json b/docs/web-app/how-to-connect-wallet/_category_.json index 5d87948c..6d7d091a 100644 --- a/docs/web-app/how-to-connect-wallet/_category_.json +++ b/docs/web-app/how-to-connect-wallet/_category_.json @@ -1,5 +1,5 @@ { "label": "How to connect your wallet", "position": 2, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docs/web-app/strategies/_category_.json b/docs/web-app/strategies/_category_.json index 8f4bc467..9ef9ee13 100644 --- a/docs/web-app/strategies/_category_.json +++ b/docs/web-app/strategies/_category_.json @@ -1,5 +1,5 @@ { "label": "Strategies", "position": 5, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docs/web-app/strategies/key-actions-questions/_category_.json b/docs/web-app/strategies/key-actions-questions/_category_.json index 559a5385..035f8cb6 100644 --- a/docs/web-app/strategies/key-actions-questions/_category_.json +++ b/docs/web-app/strategies/key-actions-questions/_category_.json @@ -1,5 +1,5 @@ { "label": "Key Actions/Questions", "position": 6, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docs/web-app/strategies/manage-strat/_category_.json b/docs/web-app/strategies/manage-strat/_category_.json index 34d4b707..02308957 100644 --- a/docs/web-app/strategies/manage-strat/_category_.json +++ b/docs/web-app/strategies/manage-strat/_category_.json @@ -1,5 +1,5 @@ { "label": "Manage a strategy", "position": 5, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docs/web-app/swap/_category_.json b/docs/web-app/swap/_category_.json index bfe2d8dc..4afc7a98 100644 --- a/docs/web-app/swap/_category_.json +++ b/docs/web-app/swap/_category_.json @@ -1,5 +1,5 @@ { "label": "Swap", "position": 4, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docs/web-app/trade/_category_.json b/docs/web-app/trade/_category_.json index ef114ed3..70c86401 100644 --- a/docs/web-app/trade/_category_.json +++ b/docs/web-app/trade/_category_.json @@ -1,5 +1,5 @@ { "label": "Trade", "position": 3, - "collapsed": false + "collapsed": true } \ No newline at end of file diff --git a/docusaurus.config.js b/docusaurus.config.js index 447b35f8..864d93ab 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -12,7 +12,7 @@ const config = { title: 'Mangrove', tagline: 'Developer documentation for all things Mangrove', - url: 'https://testnet.mangrove.exchange', + url: 'https://app.mangrove.exchange', baseUrl: '/', onBrokenLinks: 'throw', onBrokenMarkdownLinks: 'throw', @@ -126,129 +126,22 @@ const config = { alt: 'Mangrove logo', src: 'img/assets/mangrove_only_logo_dark.png', srcDark: 'img/assets/mangrove_only_logo_white.png', + href: '/homepage', + target: '_self', }, items: [ { - to: 'https://app.mangrove.exchange/', + to: '/homepage', position: 'right', - label: '🌳 App', + label: 'General', }, { - to: 'https://github.com/mangrovedao', + to: '/contracts', position: 'right', - label: '👾 GitHub', - }, - { - to: 'https://twitter.com/MangroveDAO', - position: 'right', - label: '🐦 Twitter', + label: 'Developers', }, ], - }, - footer: { - style: 'dark', - links: [ - { - title: 'User', - items: [ - { - label: 'Web App', - to: '/web-app', - }, - { - label: 'Kandel', - to: '/kandel' - }, - ], - }, - { - title: 'Developer', - items: [ - { - label: 'Contracts', - to: '/contracts', - }, - { - label: 'Strat Library', - to: '/strat-lib' - }, - { - label: 'SDK', - to: '/SDK', - }, - { - label: 'Keeper Bots', - to: '/keeper-bots', - }, - ], - }, - { - title: 'Community', - items: [ - { - label: 'Discord', - href: 'https://discord.mangrove.exchange' - }, - { - label: 'Twitter', - href: 'https://twitter.com/MangroveDAO' - }, - { - label: 'LinkedIn', - href: 'https://www.linkedin.com/company/mangrovedao/' - } - ], - }, - { - title: 'GitHub', - items: [ - { - label: 'Contracts and Strat Lib', - href: 'https://github.com/mangrovedao/mangrove-core' - }, - { - label: 'SDK', - href: 'https://github.com/mangrovedao/mangrove.js' - }, - { - label: 'Bots', - href: 'https://github.com/mangrovedao/mangrove-bots' - }, - { - label: 'Docs', - href: 'https://github.com/mangrovedao/mangrove-docs' - }, - ], - }, - { - title: 'More', - items: [ - { - label: 'Glossary', - to: '/glossary' - }, - { - label: 'FAQ', - to: '/FAQ' - }, - { - label: 'White Paper', - href: 'https://bafybeig62o75bfxssic66w2zwerbo6ezlhb33vsg5idr4uprckn2dxrucy.ipfs.infura-ipfs.io/' - }, - { - label: 'Blog', - href: 'https://blog.mangrove.exchange/' - }, - { - label: 'Home', - href: 'https://mangrove.exchange' - }, - ] - } - ], - copyright: `Copyright © ${new Date().getFullYear()} ADDMA. All rights reserved.`, - }, - + }, }), }; diff --git a/sidebars.js b/sidebars.js index d5300830..a039af40 100644 --- a/sidebars.js +++ b/sidebars.js @@ -15,38 +15,130 @@ const sidebars = { // By default, Docusaurus generates a sidebar from the docs folder structure - docsSidebar: [ - + generalSidebar: [ { type: 'category', - label: 'Concepts', + label: 'Getting started', + link: {type: 'doc', id: 'homepage'}, items: [ { - type: 'autogenerated', - dirName: 'high-level', // Generate sidebar slice from docs/high-level + type: 'category', + label: '💡 Concepts', + items: [ + { + type: 'autogenerated', + dirName: 'high-level', // Generate sidebar slice from docs/high-level + }, + ] }, - ], - }, - { - type: 'category', - label: 'Web App', - items: [ { - type: 'autogenerated', - dirName: 'web-app', + type: 'category', + label: '🔤 Glossary', + items: [ + { + type: 'autogenerated', + dirName: 'terms', + }, + ] }, - ], - }, - { - type: 'category', - label: 'Kandel', - items: [ { - type: 'autogenerated', - dirName: 'kandel', + type: 'category', + label: '❓ FAQ', + items: [ + { + type: 'autogenerated', + dirName: 'FAQ', + }, + ] + }, + { + type: 'category', + label: '💻 App guide', + items: [ + { + type: 'autogenerated', + dirName: 'web-app', + }, + ] }, ], }, + { + type: 'category', + label: 'Strategies', + items: [ + { + type: 'category', + label: '🕯️ Kandel', + items: [ + { + type: 'autogenerated', + dirName: 'kandel', // Generate sidebar slice from docs/high-level + }, + ] + }, + ], + }, + { + type: 'category', + label: 'Quick links', + items: [ + { + type: 'link', + label: '📃 Whitepaper', // The link label + href: 'https://bafybeig62o75bfxssic66w2zwerbo6ezlhb33vsg5idr4uprckn2dxrucy.ipfs.dweb.link/', + }, + { + type: 'link', + label: '🕸️ Website', // The link label + href: 'https://mangrove.exchange/', + }, + { + type: 'link', + label: '🏗️ Developers', // The link label + href: 'https://mangrove.exchange/', + }, + ], + }, + { + type: 'category', + label: 'Socials', + items: [ + { + type: 'link', + label: '📰 Blog', // The link label + href: 'https://blog.mangrove.exchange/', + }, + { + type: 'link', + label: '👾 Discord', // The link label + href: 'https://discord.gg/rk9Qthz5YE', + }, + { + type: 'link', + label: '🐦 X', // The link label + href: 'https://twitter.com/MangroveDAO', + }, + { + type: 'link', + label: '🧩 GitHub', // The link label + href: 'https://github.com/mangrovedao', + }, + { + type: 'link', + label: '🎨 Assets', // The link label + href: 'https://www.mangrove.exchange/brand-assets', + }, + { + type: 'link', + label: '📝 Contact', // The link label + href: 'https://docs.google.com/forms/d/e/1FAIpQLSewVLx1AcOwK0DOvMOCIb7hSEfHGwMzB0P4yeH-Aeq65ctlKg/viewform', + }, + ], + }, + ], + + developerSidebar: [ { type: 'category', label: 'Contracts', @@ -97,7 +189,7 @@ const sidebars = { }, ], }, - ], + ], }; module.exports = sidebars; diff --git a/src/css/custom.css b/src/css/custom.css index d8bb526d..1da61e42 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -7,13 +7,14 @@ /* You can override the default Infima variables here. */ :root { --ifm-font-family-base: 'Inter'; - --ifm-color-primary: #2e4285; - --ifm-color-primary-dark: #293c78; - --ifm-color-primary-darker: #273971; - --ifm-color-primary-darkest: #202f5d; - --ifm-color-primary-light: #334a92; - --ifm-color-primary-lighter: #354d99; - --ifm-color-primary-lightest: #3c57ad; + --ifm-color-primary: #1eb759; + --ifm-color-primary-dark: #195644; + --ifm-color-primary-darker: #185240; + --ifm-color-primary-darkest: #144335; + --ifm-color-primary-light: #1f6a53; + --ifm-color-primary-lighter: #206e56; + --ifm-color-primary-lightest: #247d62; + --ifm-font-size-base: 15px; } /* For readability concerns, you should choose a lighter palette in dark mode. */ @@ -26,6 +27,9 @@ --ifm-color-primary-lighter: #6adf96; --ifm-color-primary-lightest: #8de6af; background-color: #072221; + --ifm-font-size-base: 15px; + + } h1, h2, h3, h4, h5, h6 { @@ -51,7 +55,7 @@ table { .navbar { /* make room for headings that break in two lines */ - min-height: 70px; + min-height: 50px; } [data-theme='dark'] .navbar { From 3a07094e1257239bc214f65820dc09c080e49c57 Mon Sep 17 00:00:00 2001 From: frkralj Date: Tue, 26 Sep 2023 15:03:55 +0200 Subject: [PATCH 07/38] editing menu --- sidebars.js | 33 +++++++++++---------------------- src/css/custom.css | 22 +++++++++++++++++++++- 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/sidebars.js b/sidebars.js index a039af40..ebfe7720 100644 --- a/sidebars.js +++ b/sidebars.js @@ -32,24 +32,14 @@ const sidebars = { ] }, { - type: 'category', + type: 'link', label: '🔤 Glossary', - items: [ - { - type: 'autogenerated', - dirName: 'terms', - }, - ] + href: '/glossary', }, { - type: 'category', + type: 'link', label: '❓ FAQ', - items: [ - { - type: 'autogenerated', - dirName: 'FAQ', - }, - ] + href: '/FAQ', }, { type: 'category', @@ -66,10 +56,12 @@ const sidebars = { { type: 'category', label: 'Strategies', + collapsed: false, items: [ { type: 'category', label: '🕯️ Kandel', + collapsed: false, items: [ { type: 'autogenerated', @@ -82,6 +74,7 @@ const sidebars = { { type: 'category', label: 'Quick links', + collapsed: false, items: [ { type: 'link', @@ -96,13 +89,14 @@ const sidebars = { { type: 'link', label: '🏗️ Developers', // The link label - href: 'https://mangrove.exchange/', + href: '/contracts', }, ], }, { type: 'category', label: 'Socials', + collapsed: false, items: [ { type: 'link', @@ -180,14 +174,9 @@ const sidebars = { ], }, { - type: 'category', + type: 'link', label: 'Glossary', - items: [ - { - type: 'autogenerated', - dirName: 'terms', - }, - ], + href: '/glossary', }, ], }; diff --git a/src/css/custom.css b/src/css/custom.css index 1da61e42..f5085757 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -28,10 +28,30 @@ --ifm-color-primary-lightest: #8de6af; background-color: #072221; --ifm-font-size-base: 15px; +} + +.theme-doc-sidebar-menu { + font-size: 14px; +} - +.theme-doc-sidebar-item-category-level-1 { + font-weight: bold; } +.theme-doc-sidebar-item-category-level-2 { + font-weight: 400 !important +} + +.theme-doc-sidebar-item-category-level-3 { + font-weight: 400 !important +} + +.theme-doc-sidebar-item-link-level-2 { + font-weight: 400 !important +} + + + h1, h2, h3, h4, h5, h6 { font-family: 'Exo', sans-serif; } From 9f9ee927ca492ed6361b7cae1539b4778c232d80 Mon Sep 17 00:00:00 2001 From: frkralj Date: Wed, 27 Sep 2023 08:49:09 +0200 Subject: [PATCH 08/38] Adding /developers slug --- docs/contracts/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/contracts/README.md b/docs/contracts/README.md index e6f5c820..f3e0d30b 100644 --- a/docs/contracts/README.md +++ b/docs/contracts/README.md @@ -1,6 +1,7 @@ --- description: The Mangrove DEX is an on-chain, order book-based exchange where offers are code. sidebar_position: 1 +slug: '/developers' --- From 16eab57b7e3bfd1439c5cb1882366c3902dc2c6e Mon Sep 17 00:00:00 2001 From: frkralj Date: Wed, 27 Sep 2023 08:57:45 +0200 Subject: [PATCH 09/38] Removing /developers slug since it breaks all links --- docs/contracts/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/contracts/README.md b/docs/contracts/README.md index f3e0d30b..e6f5c820 100644 --- a/docs/contracts/README.md +++ b/docs/contracts/README.md @@ -1,7 +1,6 @@ --- description: The Mangrove DEX is an on-chain, order book-based exchange where offers are code. sidebar_position: 1 -slug: '/developers' --- From 960f67db477d466623972ff9583006b2509dffc9 Mon Sep 17 00:00:00 2001 From: frkralj Date: Fri, 29 Sep 2023 11:40:39 +0200 Subject: [PATCH 10/38] modifying sidebar for FAQ and Glossary pages --- docs/FAQ/README.md | 2 +- docs/glossary.md | 2 +- sidebars.js | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/FAQ/README.md b/docs/FAQ/README.md index 6d065308..141f3238 100644 --- a/docs/FAQ/README.md +++ b/docs/FAQ/README.md @@ -1,7 +1,7 @@ --- title: FAQ description: Frequently Asked Questions -sidebar_position: 1 +sidebar_position: 2 --- # FAQ diff --git a/docs/glossary.md b/docs/glossary.md index 7e22d918..280db44b 100644 --- a/docs/glossary.md +++ b/docs/glossary.md @@ -1,6 +1,6 @@ --- title: Glossary -sidebar_position: 0 +sidebar_position: 1 --- THIS FILE IS AUTOGENERATED \ No newline at end of file diff --git a/sidebars.js b/sidebars.js index ebfe7720..05985423 100644 --- a/sidebars.js +++ b/sidebars.js @@ -32,14 +32,14 @@ const sidebars = { ] }, { - type: 'link', + type: 'doc', + id: 'glossary', label: '🔤 Glossary', - href: '/glossary', }, { - type: 'link', + type: 'doc', + id: 'FAQ/README', label: '❓ FAQ', - href: '/FAQ', }, { type: 'category', From af81cace12122ec6cd24cec34a638adcd576c955 Mon Sep 17 00:00:00 2001 From: frkralj Date: Fri, 29 Sep 2023 12:00:09 +0200 Subject: [PATCH 11/38] adding a developers.md landing page for the Dev section --- docs/contracts/README.md | 28 ---------------------------- docs/developers.md | 25 +++++++++++++++++++++++++ docusaurus.config.js | 2 +- sidebars.js | 9 +++++++-- src/css/custom.css | 4 ++++ 5 files changed, 37 insertions(+), 31 deletions(-) delete mode 100644 docs/contracts/README.md create mode 100644 docs/developers.md diff --git a/docs/contracts/README.md b/docs/contracts/README.md deleted file mode 100644 index e6f5c820..00000000 --- a/docs/contracts/README.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -description: The Mangrove DEX is an on-chain, order book-based exchange where offers are code. -sidebar_position: 1 ---- - - -# Introduction - -The Mangrove is an [EVM-compatible](https://ethereum.org/en/developers/docs/scaling/sidechains/#evm-compatibility) order book-based exchange protocol (a [DEX](https://ethereum.org/en/defi/)), in which offers can be bound to a [smart contract](https://ethereum.org/en/smart-contracts/). - -The order book of Mangrove lists promises to trade, instead of locked commitments. - -* Offer makers add [liquidity promises](./background/offer-maker.md) to Mangrove. They own offers in %%offer lists|offer-list%% and manage contracts that react to [offer execution](technical-references/taking-and-making-offers/reactive-offer/executing-offers.md). -* Takers go to Mangrove to [find liquidity](background/offer-taker.md) by executing offers already in Mangrove. -* [Governance](technical-references/governance-parameters/README.md) adjusts Mangrove parameters, sets fees, and opens and closes new markets. - -> 💡 -> For non technical information about Mangrove, check out the [Concepts](../homepage) section. - -## Where do I start? - -A good entry-point to the developer documentation for Mangrove protocol is the [Overview of Mangrove](./technical-references/overview.md) in the Technical Reference section. - -## Where can I join the community? - -The Mangrove project is open source. Follow and contribute on [GitHub](https://github.com/mangrovedao/), and join the [Mangrove Discord](https://discord.gg/rk9Qthz5YE). - - diff --git a/docs/developers.md b/docs/developers.md new file mode 100644 index 00000000..b82523ec --- /dev/null +++ b/docs/developers.md @@ -0,0 +1,25 @@ +--- +title: Developers +sidebar_position: 1 +--- + +# Welcome to the Developers Doc + +The Mangrove is an [EVM-compatible](https://ethereum.org/en/developers/docs/scaling/sidechains/#evm-compatibility) order book-based exchange protocol (a [DEX](https://ethereum.org/en/defi/)), in which offers can be bound to a [smart contract](https://ethereum.org/en/smart-contracts/). + +The order book of Mangrove lists promises to trade, instead of locked commitments. + +* Offer makers add [liquidity promises](./contracts/background/offer-maker.md) to Mangrove. They own offers in %%offer lists|offer-list%% and manage contracts that react to [offer execution](./contracts/technical-references/taking-and-making-offers/reactive-offer/executing-offers.md). +* Takers go to Mangrove to [find liquidity](./contracts/background/offer-maker.md) by executing offers already in Mangrove. +* [Governance](./contracts/technical-references/governance-parameters/README.md) adjusts Mangrove parameters, sets fees, and opens and closes new markets. + +> 💡 +> For non technical information about Mangrove, check out the [Concepts](./homepage.md) section. + +## Where do I start? + +A good entry-point to the developer documentation for Mangrove protocol is the [Overview of Mangrove](./contracts/technical-references/overview.md) in the Technical Reference section. + +## Where can I join the community? + +The Mangrove project is open source. Follow and contribute on [GitHub](https://github.com/mangrovedao/), and join the [Mangrove Discord](https://discord.gg/rk9Qthz5YE). \ No newline at end of file diff --git a/docusaurus.config.js b/docusaurus.config.js index 864d93ab..043a1a8e 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -136,7 +136,7 @@ const config = { label: 'General', }, { - to: '/contracts', + to: '/developers', position: 'right', label: 'Developers', }, diff --git a/sidebars.js b/sidebars.js index 05985423..04fd7c23 100644 --- a/sidebars.js +++ b/sidebars.js @@ -133,6 +133,11 @@ const sidebars = { ], developerSidebar: [ + { + type: 'doc', + id: 'developers', + label: 'Welcome', + }, { type: 'category', label: 'Contracts', @@ -174,9 +179,9 @@ const sidebars = { ], }, { - type: 'link', + type: 'doc', + id: 'glossary', label: 'Glossary', - href: '/glossary', }, ], }; diff --git a/src/css/custom.css b/src/css/custom.css index f5085757..fc9c6851 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -46,6 +46,10 @@ font-weight: 400 !important } +.theme-doc-sidebar-item-link-level-1 { + font-weight: bold; +} + .theme-doc-sidebar-item-link-level-2 { font-weight: 400 !important } From ca7fb5566cfd7fe634ffece9e5674aabbaecab06 Mon Sep 17 00:00:00 2001 From: frkralj Date: Fri, 29 Sep 2023 12:13:36 +0200 Subject: [PATCH 12/38] adding /general and /developers slugs --- docs/{homepage.md => general.md} | 0 docs/terms/hook.md | 2 +- docusaurus.config.js | 4 +- sidebars.js | 2 +- src/components/HomepageSections/index.js | 185 +---------------------- 5 files changed, 7 insertions(+), 186 deletions(-) rename docs/{homepage.md => general.md} (100%) diff --git a/docs/homepage.md b/docs/general.md similarity index 100% rename from docs/homepage.md rename to docs/general.md diff --git a/docs/terms/hook.md b/docs/terms/hook.md index c4c55394..dd9faf8b 100644 --- a/docs/terms/hook.md +++ b/docs/terms/hook.md @@ -4,7 +4,7 @@ title: Hook hoverText: Internal functions in the building blocks of the Strat Lib, which may be overridden to change the default behavior of an offer logic. --- -In the [Strat Lib](../contracts/README.md) building blocks, we use _hooks_ to denote internal functions in a %%maker contract's|maker-contract%%, which may be overridden to change the default behavior of an %%offer logic|offer-logic%%. +In the [Strat Lib](../strat-lib/README.md) building blocks, we use _hooks_ to denote internal functions in a %%maker contract's|maker-contract%%, which may be overridden to change the default behavior of an %%offer logic|offer-logic%%. ## References * [Strat Lib -> Maker contract hooks](../strat-lib/technical-references/main-hooks.md) - the main available hooks in the [Strat Lib](../strat-lib/README.md). diff --git a/docusaurus.config.js b/docusaurus.config.js index 043a1a8e..c5ef93a6 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -126,12 +126,12 @@ const config = { alt: 'Mangrove logo', src: 'img/assets/mangrove_only_logo_dark.png', srcDark: 'img/assets/mangrove_only_logo_white.png', - href: '/homepage', + href: '/general', target: '_self', }, items: [ { - to: '/homepage', + to: '/general', position: 'right', label: 'General', }, diff --git a/sidebars.js b/sidebars.js index 04fd7c23..f77f2566 100644 --- a/sidebars.js +++ b/sidebars.js @@ -19,7 +19,7 @@ const sidebars = { { type: 'category', label: 'Getting started', - link: {type: 'doc', id: 'homepage'}, + link: {type: 'doc', id: 'general'}, items: [ { type: 'category', diff --git a/src/components/HomepageSections/index.js b/src/components/HomepageSections/index.js index 0b318651..8c484107 100644 --- a/src/components/HomepageSections/index.js +++ b/src/components/HomepageSections/index.js @@ -1,185 +1,6 @@ import React from 'react'; -import clsx from 'clsx'; -import Link from '@docusaurus/Link'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import Layout from '@theme/Layout'; +import { Redirect } from 'react-router-dom'; -import styles from './styles.module.css'; - -const TopFeatureList = [ - { - title: 'What is Mangrove?', - path: 'high-level', - Svg: 'img/streamlinehq-nature-ecology-leaf-nature-ecology.svg', - description: ( - <> - Learn about the core concepts of Mangrove and its ecosystem. - - ), - elementClass: 'frontpage--button', - }, - { - title: 'Web App', - path: 'web-app', - Svg: 'img/streamlinehq-computer-laptop-computer-devices.svg', - description: ( - <> - Step-by-step explanations on how to use the Mangrove web app. - - ), - elementClass: 'frontpage--button', - }, - { - title: 'Mangrove Protocol', - path: 'contracts', - Svg: 'img/streamlinehq-phone-contact-phone-book-phone.svg', - description: ( - <> - Delve into technical documentation and reference material for the core contracts. - - ), - elementClass: 'frontpage--button', - }, - { - title: 'SDK', - path: 'SDK', - Svg: 'img/streamlinehq-computer-robot-computer-devices.svg', - description: ( - <> - Off-chain builders interfacing with Mangrove should check out the documentation for the SDK. - - ), - elementClass: 'frontpage--button', - }, -] - -const MessageList = [ - -] - - -function Section({Svg, title, path = '', description, colStyle = '', elementClass=''}) { - const renderInner = () => - { - return ( -
-
- -
-
-

{title}

-

{description}

-
- -
- ); - } - if(path) { - return ( - - {renderInner()} - - ); - } - else - return renderInner(); -} - -function BoxLink({title, path, description}) { - return ( - -
-
- {title} -

{description}

-
- -
-
- ); -} - -export default function HomepageSections() { - const renderMessages = () => { - if(MessageList.length > 0){ - return ( -
-
-
- {MessageList.map((props, idx) => ( -
- ))} -
-
-
- )} - else - return; - }; - - return ( - <> -
-
-
-
- Disclaimer -
-

This documentation is currently work in progress! You might notice several "Coming soon" or "Pre-release" annotations. We are still fine-tuning the corresponding sections, as we launch Mangrove in stages. -

- Stay tuned for more information on Twitter and Discord!.

-
-
-
-
-
-
-
- {TopFeatureList.map((props, idx) => ( -
- ))} -
-
-
-
-
-
-

Web app

-

Explore these links to learn about the functionality available in Mangrove's web app.

- - - - -

Kandel

-

Kandel is the Automated Market Making strategy backing the functionality provided in the web app.

- -
-
-

Integrating dApps

-

If you're a developer looking to integrate your dApp with Mangrove, dive into the sections on the SDK.

- - - - - -

Keeper bots

-

Keeper bots are an essential part of Mangrove's ecosystem that ensure a smooth experience for all.

- -
-
-

Protocol and smart contracts

-

Dive deeper into the technical documentation for the Mangrove Protocol.

- - - -

Strat Lib

-

The Mangrove Strat Library is a repository of Solidity code provided to help you write safe and efficient maker contracts for liquidity providing.

- - - -
-
-
- - ); +export default function Home() { + return ; } From eef0107c6894df95ed67760792dc15b5269bb5b6 Mon Sep 17 00:00:00 2001 From: frkralj Date: Fri, 29 Sep 2023 12:19:15 +0200 Subject: [PATCH 13/38] correcting broken link --- docs/developers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developers.md b/docs/developers.md index b82523ec..0966237a 100644 --- a/docs/developers.md +++ b/docs/developers.md @@ -14,7 +14,7 @@ The order book of Mangrove lists promises to trade, instead of locked commitment * [Governance](./contracts/technical-references/governance-parameters/README.md) adjusts Mangrove parameters, sets fees, and opens and closes new markets. > 💡 -> For non technical information about Mangrove, check out the [Concepts](./homepage.md) section. +> For non technical information about Mangrove, check out the [Concepts](./general.md) section. ## Where do I start? From a143d413acee78c5941304d64d6311efd33d4e4f Mon Sep 17 00:00:00 2001 From: frkralj Date: Fri, 29 Sep 2023 12:31:51 +0200 Subject: [PATCH 14/38] correcting broken links again --- docs/contracts/README.md | 25 +++++++++++++++++++++++++ docs/developers.md | 23 ++++++----------------- 2 files changed, 31 insertions(+), 17 deletions(-) create mode 100644 docs/contracts/README.md diff --git a/docs/contracts/README.md b/docs/contracts/README.md new file mode 100644 index 00000000..c50b8050 --- /dev/null +++ b/docs/contracts/README.md @@ -0,0 +1,25 @@ +--- +title: Introduction +sidebar_position: 1 +--- + +# Introduction + +The Mangrove is an [EVM-compatible](https://ethereum.org/en/developers/docs/scaling/sidechains/#evm-compatibility) order book-based exchange protocol (a [DEX](https://ethereum.org/en/defi/)), in which offers can be bound to a [smart contract](https://ethereum.org/en/smart-contracts/). + +The order book of Mangrove lists promises to trade, instead of locked commitments. + +* Offer makers add [liquidity promises](./background/offer-maker.md) to Mangrove. They own offers in %%offer lists|offer-list%% and manage contracts that react to [offer execution](./technical-references/taking-and-making-offers/reactive-offer/executing-offers.md). +* Takers go to Mangrove to [find liquidity](./background/offer-maker.md) by executing offers already in Mangrove. +* [Governance](./technical-references/governance-parameters/README.md) adjusts Mangrove parameters, sets fees, and opens and closes new markets. + +> 💡 +> For non technical information about Mangrove, check out the [Concepts](../general.md) section. + +## Where do I start? + +A good entry-point to the developer documentation for Mangrove protocol is the [Overview of Mangrove](./technical-references/overview.md) in the Technical Reference section. + +## Where can I join the community? + +The Mangrove project is open source. Follow and contribute on [GitHub](https://github.com/mangrovedao/), and join the [Mangrove Discord](https://discord.gg/rk9Qthz5YE). \ No newline at end of file diff --git a/docs/developers.md b/docs/developers.md index 0966237a..4c81db63 100644 --- a/docs/developers.md +++ b/docs/developers.md @@ -5,21 +5,10 @@ sidebar_position: 1 # Welcome to the Developers Doc -The Mangrove is an [EVM-compatible](https://ethereum.org/en/developers/docs/scaling/sidechains/#evm-compatibility) order book-based exchange protocol (a [DEX](https://ethereum.org/en/defi/)), in which offers can be bound to a [smart contract](https://ethereum.org/en/smart-contracts/). +In here, we will cover in details: +* the [core protocol](./contracts/README.md) +* the [Strategies Library](./strat-lib/README.md) +* our [SDK](./SDK/README.md) +* [Keeper and Cleaning bots](./keeper-bots/). -The order book of Mangrove lists promises to trade, instead of locked commitments. - -* Offer makers add [liquidity promises](./contracts/background/offer-maker.md) to Mangrove. They own offers in %%offer lists|offer-list%% and manage contracts that react to [offer execution](./contracts/technical-references/taking-and-making-offers/reactive-offer/executing-offers.md). -* Takers go to Mangrove to [find liquidity](./contracts/background/offer-maker.md) by executing offers already in Mangrove. -* [Governance](./contracts/technical-references/governance-parameters/README.md) adjusts Mangrove parameters, sets fees, and opens and closes new markets. - -> 💡 -> For non technical information about Mangrove, check out the [Concepts](./general.md) section. - -## Where do I start? - -A good entry-point to the developer documentation for Mangrove protocol is the [Overview of Mangrove](./contracts/technical-references/overview.md) in the Technical Reference section. - -## Where can I join the community? - -The Mangrove project is open source. Follow and contribute on [GitHub](https://github.com/mangrovedao/), and join the [Mangrove Discord](https://discord.gg/rk9Qthz5YE). \ No newline at end of file +We suggest you start by reading [this introduction](./contracts/README.md)! \ No newline at end of file From 9c0ac4496ac521803cdcf263dc9a8d3c16cc166e Mon Sep 17 00:00:00 2001 From: Troels Damgaard Date: Thu, 12 Oct 2023 09:26:01 +0200 Subject: [PATCH 15/38] updates General -> root Glossary -> links section Deleted unused frontpages --- docs/general.md | 1 + docusaurus.config.js | 4 +-- sidebars.js | 10 +++---- src/components/HomepageSections/index.js | 6 ---- src/pages/index.js | 35 ------------------------ 5 files changed, 8 insertions(+), 48 deletions(-) delete mode 100644 src/components/HomepageSections/index.js delete mode 100644 src/pages/index.js diff --git a/docs/general.md b/docs/general.md index ba9d2062..1ae7243b 100644 --- a/docs/general.md +++ b/docs/general.md @@ -1,6 +1,7 @@ --- title: Homepage sidebar_position: 0 +slug: / --- # What is Mangrove? diff --git a/docusaurus.config.js b/docusaurus.config.js index c5ef93a6..293f9f9e 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -126,12 +126,12 @@ const config = { alt: 'Mangrove logo', src: 'img/assets/mangrove_only_logo_dark.png', srcDark: 'img/assets/mangrove_only_logo_white.png', - href: '/general', + href: '/', target: '_self', }, items: [ { - to: '/general', + to: '/', position: 'right', label: 'General', }, diff --git a/sidebars.js b/sidebars.js index f77f2566..b87ce141 100644 --- a/sidebars.js +++ b/sidebars.js @@ -31,11 +31,6 @@ const sidebars = { }, ] }, - { - type: 'doc', - id: 'glossary', - label: '🔤 Glossary', - }, { type: 'doc', id: 'FAQ/README', @@ -86,6 +81,11 @@ const sidebars = { label: '🕸️ Website', // The link label href: 'https://mangrove.exchange/', }, + { + type: 'link', + href: '/glossary', + label: '🔤 Glossary', + }, { type: 'link', label: '🏗️ Developers', // The link label diff --git a/src/components/HomepageSections/index.js b/src/components/HomepageSections/index.js deleted file mode 100644 index 8c484107..00000000 --- a/src/components/HomepageSections/index.js +++ /dev/null @@ -1,6 +0,0 @@ -import React from 'react'; -import { Redirect } from 'react-router-dom'; - -export default function Home() { - return ; -} diff --git a/src/pages/index.js b/src/pages/index.js deleted file mode 100644 index 42ec8b77..00000000 --- a/src/pages/index.js +++ /dev/null @@ -1,35 +0,0 @@ -import React from 'react'; -import clsx from 'clsx'; -import Link from '@docusaurus/Link'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import Layout from '@theme/Layout'; -import HomepageSections from '@site/src/components/HomepageSections'; -import useBaseUrl from '@docusaurus/useBaseUrl'; - -import styles from './index.module.css'; - -function HomepageHeader() { - const {siteConfig} = useDocusaurusContext(); - return ( -
-
- -

Welcome to Mangrove Docs

-
-
- ); -} - -export default function Home() { - const {siteConfig} = useDocusaurusContext(); - return ( - - -
- -
-
- ); -} From 6892c302e3bce88ed186a65a1691ee0d54c5bf9a Mon Sep 17 00:00:00 2001 From: Troels Damgaard Date: Fri, 13 Oct 2023 11:29:54 +0200 Subject: [PATCH 16/38] restructure developers into folder --- docs/{general.md => README.md} | 3 +- docs/{developers.md => developers/README.md} | 0 docs/{ => developers}/SDK/README.md | 0 .../SDK/background/_category_.json | 0 .../SDK/getting-started/_category_.json | 0 .../SDK/getting-started/_preparation-post.md | 0 .../SDK/getting-started/_preparation-pre.md | 0 .../SDK/getting-started/basic-offer.md | 0 .../SDK/getting-started/deploy-kandel.md | 12 +- .../SDK/getting-started/preparation.md | 0 .../SDK/guides/_category_.json | 0 .../SDK/guides/fill-or-kill.md | 0 .../SDK/guides/reuse-offer.md | 0 .../SDK/guides/sell-and-buy-orders.md | 0 .../SDK/guides/snipe-offer.md | 0 .../SDK/guides/update-offer.md | 0 .../SDK/technical-references/_category_.json | 0 .../SDK/technical-references/api-overview.md | 0 .../technical-references/code/_category_.yml | 2 + .../code/classes/KandelDistribution.md | 322 ++++ .../classes/KandelDistributionGenerator.md | 243 ++++ .../code/classes/KandelFarm.md | 97 ++ .../code/classes/KandelInstance.md | 1196 +++++++++++++++ .../code/classes/KandelSeeder.md | 260 ++++ .../code/classes/KandelStrategies.md | 130 ++ .../code/classes/LiquidityProvider.md | 587 ++++++++ .../code/classes/Mangrove.md | 1292 +++++++++++++++++ .../code/classes/Market.md | 1202 +++++++++++++++ .../code/classes/MgvToken.md | 512 +++++++ .../code/classes/OfferLogic.md | 369 +++++ .../code/classes/OfferMaker.md | 36 + .../code/classes/Semibook.md | 807 ++++++++++ .../code/classes/_category_.yml | 2 + .../code/classes/eth.Mnemonic.md | 126 ++ .../code/enums/_category_.yml | 2 + .../code/enums/mgvTestUtil.AccountName.md | 48 + .../SDK/technical-references/code/index.md | 107 ++ .../interfaces/Semibook-1.CacheIterator.md | 168 +++ .../code/interfaces/_category_.yml | 2 + .../interfaces/eth.CreateSignerOptions.md | 98 ++ .../code/interfaces/eth.ProviderNetwork.md | 28 + .../SDK/technical-references/code/modules.md | 54 + .../code/namespaces/KandelStrategies-1.md | 8 + .../code/namespaces/LiquidityProvider-1.md | 59 + .../code/namespaces/Mangrove-1.md | 161 ++ .../code/namespaces/Market-1.BookReturns.md | 38 + .../code/namespaces/Market-1.md | 415 ++++++ .../code/namespaces/MgvToken-1.md | 25 + .../code/namespaces/Semibook-1.md | 170 +++ .../code/namespaces/_category_.yml | 2 + .../code/namespaces/eth.md | 16 + .../code/namespaces/mgvTestUtil.md | 602 ++++++++ docs/{ => developers}/contracts/README.md | 2 +- .../contracts/background/_category_.json | 0 .../contracts/background/offer-maker.md | 2 +- .../contracts/background/offer-taker.md | 0 .../background/taker-compensation.md | 0 .../contracts/getting-started/_category_.json | 0 .../contracts/guides/_category_.json | 0 .../technical-references/_category_.json | 0 .../_contract-addresses-raw.md | 0 .../technical-references/codebase.md | 0 .../contract-addresses.md | 0 .../governance-parameters/README.md | 0 .../governance-parameters/global-variables.md | 0 .../governance-parameters/local-variables.md | 0 .../mangrove-configuration.md | 0 .../mangrove-core-version.json | 0 .../mangrove-js-version.json | 0 .../technical-references/overview.md | 4 +- .../technical-references/periphery/README.md | 0 .../technical-references/periphery/cleaner.md | 2 +- .../technical-references/periphery/oracle.md | 0 .../technical-references/periphery/reader.md | 0 .../taking-and-making-offers/README.md | 0 .../taking-and-making-offers/offer-list.md | 0 .../reactive-offer/README.md | 0 .../reactive-offer/executing-offers.md | 0 .../reactive-offer/gas-requirement.md | 0 .../reactive-offer/maker-contract.md | 0 .../reactive-offer/offer-data-structures.md | 0 .../reactive-offer/offer-provision.md | 0 .../taker-order/README.md | 0 .../taker-order/delegate-takers.md | 0 .../views-on-offers.md | 0 docs/{ => developers}/keeper-bots/README.md | 0 .../keeper-bots/background/_category_.json | 0 .../the-role-of-cleaning-bots-in-mangrove.md | 0 ...e-of-gas-price-updater-bots-in-mangrove.md | 2 +- .../getting-started/_category_.json | 0 .../run-a-simple-cleaning-bot.md | 0 .../keeper-bots/guides/_category_.json | 0 ...delegation-to-borrow-funds-for-cleaning.md | 2 +- .../guides/use-mgvcleaner-to-clean-offers.md | 2 +- .../technical-reference/_category_.json | 0 .../technical-reference/examples.md | 0 docs/{ => developers}/strat-lib/README.md | 0 .../strat-lib/background/_category_.json | 0 .../background/offer-maker/_category_.json | 0 .../background/offer-maker/direct.md | 2 +- .../background/offer-maker/forwarder.md | 2 +- .../background/offer-maker/mangrove-offer.md | 2 +- .../strat-lib/getting-started/_category_.json | 0 .../strat-lib/getting-started/preparation.md | 0 .../strat-lib/getting-started/smart-offer.md | 0 .../strat-lib/guides/DirectHowTo.md | 0 .../strat-lib/guides/HowToDeploy.md | 0 .../strat-lib/guides/HowToImplement.md | 0 .../strat-lib/guides/HowToTest.md | 0 .../strat-lib/guides/_category_.json | 0 .../strat-lib/guides/approvals.md | 2 +- .../strat-lib/guides/howToRenege.md | 0 .../strat-lib/guides/howToResidual.md | 0 .../strat-lib/guides/howToSnipe.md | 0 .../strat-lib/guides/howToUnlockLiquidity.md | 2 +- .../strat-lib/guides/howtoGasreq.md | 0 .../technical-references/_category_.json | 0 .../technical-references/code/IERC20.md | 0 .../technical-references/code/_category_.json | 0 .../code/strategies/MangroveOffer.md | 0 .../code/strategies/MangroveOrder.md | 0 .../strategies/integrations/AaveV2Module.md | 0 .../strategies/integrations/AaveV3Borrower.md | 0 .../AaveV3BorrowerImplementation.md | 0 .../integrations/AaveV3BorrowerStorage.md | 0 .../strategies/integrations/AaveV3Lender.md | 0 .../strategies/integrations/CompoundModule.md | 0 .../code/strategies/interfaces/IForwarder.md | 0 .../interfaces/ILiquidityProvider.md | 0 .../code/strategies/interfaces/IOfferLogic.md | 0 .../code/strategies/interfaces/IOrderLogic.md | 0 .../offer_forwarder/OfferForwarder.md | 0 .../offer_forwarder/abstract/Forwarder.md | 0 .../code/strategies/offer_maker/AaveMaker.md | 0 .../code/strategies/offer_maker/OfferMaker.md | 0 .../strategies/offer_maker/abstract/Direct.md | 0 .../market_making/kandel/AaveKandel.md | 0 .../market_making/kandel/AaveKandelSeeder.md | 0 .../market_making/kandel/Kandel.md | 0 .../market_making/kandel/KandelSeeder.md | 0 .../kandel/abstract/AbstractKandel.md | 0 .../kandel/abstract/AbstractKandelSeeder.md | 0 .../kandel/abstract/CoreKandel.md | 0 .../DirectWithBidsAndAsksDistribution.md | 0 .../kandel/abstract/GeometricKandel.md | 0 .../kandel/abstract/HasIndexedBidsAndAsks.md | 0 .../kandel/abstract/TradesBaseQuotePair.md | 0 .../offer_maker/market_making/mango/Mango.md | 0 .../mango/MangoImplementation.md | 0 .../market_making/mango/MangoStorage.md | 0 .../code/strategies/routers/AbstractRouter.md | 0 .../code/strategies/routers/SimpleRouter.md | 0 .../routers/integrations/AavePooledRouter.md | 0 .../integrations/HasAaveBalanceMemoizer.md | 0 .../code/strategies/utils/AccessControlled.md | 0 .../code/strategies/utils/TransferLib.md | 0 .../strategies/vendor/aave/v2/DataTypes.md | 0 .../strategies/vendor/aave/v2/ILendingPool.md | 0 .../aave/v2/ILendingPoolAddressesProvider.md | 0 .../vendor/aave/v2/IPriceOracleGetter.md | 0 .../strategies/vendor/aave/v3/DataTypes.md | 0 .../code/strategies/vendor/aave/v3/Errors.md | 0 .../strategies/vendor/aave/v3/IATokenIsh.md | 0 .../vendor/aave/v3/ICreditDelegationToken.md | 0 .../code/strategies/vendor/aave/v3/IPool.md | 0 .../vendor/aave/v3/IPoolAddressesProvider.md | 0 .../vendor/aave/v3/IPriceOracleGetter.md | 0 .../vendor/aave/v3/IRewardsControllerIsh.md | 0 .../vendor/aave/v3/ReserveConfiguration.md | 0 .../strategies/vendor/compound/CarefulMath.md | 0 .../strategies/vendor/compound/Exponential.md | 0 .../vendor/compound/ExponentialNoError.md | 0 .../strategies/vendor/compound/ICompound.md | 0 .../technical-references/code/toy/ERC20.md | 0 .../technical-references/code/toy/ERC20BL.md | 0 .../technical-references/code/toy/ERC20Lib.md | 0 .../code/toy/MintableERC20BLWithDecimals.md | 0 .../code/toy/PixieMATIC.md | 0 .../code/toy/PixieUSDC.md | 0 .../technical-references/main-hooks.md | 0 .../strat-lib/technical-references/router.md | 0 sidebars.js | 46 +- 182 files changed, 9240 insertions(+), 33 deletions(-) rename docs/{general.md => README.md} (98%) rename docs/{developers.md => developers/README.md} (100%) rename docs/{ => developers}/SDK/README.md (100%) rename docs/{ => developers}/SDK/background/_category_.json (100%) rename docs/{ => developers}/SDK/getting-started/_category_.json (100%) rename docs/{ => developers}/SDK/getting-started/_preparation-post.md (100%) rename docs/{ => developers}/SDK/getting-started/_preparation-pre.md (100%) rename docs/{ => developers}/SDK/getting-started/basic-offer.md (100%) rename docs/{ => developers}/SDK/getting-started/deploy-kandel.md (89%) rename docs/{ => developers}/SDK/getting-started/preparation.md (100%) rename docs/{ => developers}/SDK/guides/_category_.json (100%) rename docs/{ => developers}/SDK/guides/fill-or-kill.md (100%) rename docs/{ => developers}/SDK/guides/reuse-offer.md (100%) rename docs/{ => developers}/SDK/guides/sell-and-buy-orders.md (100%) rename docs/{ => developers}/SDK/guides/snipe-offer.md (100%) rename docs/{ => developers}/SDK/guides/update-offer.md (100%) rename docs/{ => developers}/SDK/technical-references/_category_.json (100%) rename docs/{ => developers}/SDK/technical-references/api-overview.md (100%) create mode 100644 docs/developers/SDK/technical-references/code/_category_.yml create mode 100644 docs/developers/SDK/technical-references/code/classes/KandelDistribution.md create mode 100644 docs/developers/SDK/technical-references/code/classes/KandelDistributionGenerator.md create mode 100644 docs/developers/SDK/technical-references/code/classes/KandelFarm.md create mode 100644 docs/developers/SDK/technical-references/code/classes/KandelInstance.md create mode 100644 docs/developers/SDK/technical-references/code/classes/KandelSeeder.md create mode 100644 docs/developers/SDK/technical-references/code/classes/KandelStrategies.md create mode 100644 docs/developers/SDK/technical-references/code/classes/LiquidityProvider.md create mode 100644 docs/developers/SDK/technical-references/code/classes/Mangrove.md create mode 100644 docs/developers/SDK/technical-references/code/classes/Market.md create mode 100644 docs/developers/SDK/technical-references/code/classes/MgvToken.md create mode 100644 docs/developers/SDK/technical-references/code/classes/OfferLogic.md create mode 100644 docs/developers/SDK/technical-references/code/classes/OfferMaker.md create mode 100644 docs/developers/SDK/technical-references/code/classes/Semibook.md create mode 100644 docs/developers/SDK/technical-references/code/classes/_category_.yml create mode 100644 docs/developers/SDK/technical-references/code/classes/eth.Mnemonic.md create mode 100644 docs/developers/SDK/technical-references/code/enums/_category_.yml create mode 100644 docs/developers/SDK/technical-references/code/enums/mgvTestUtil.AccountName.md create mode 100644 docs/developers/SDK/technical-references/code/index.md create mode 100644 docs/developers/SDK/technical-references/code/interfaces/Semibook-1.CacheIterator.md create mode 100644 docs/developers/SDK/technical-references/code/interfaces/_category_.yml create mode 100644 docs/developers/SDK/technical-references/code/interfaces/eth.CreateSignerOptions.md create mode 100644 docs/developers/SDK/technical-references/code/interfaces/eth.ProviderNetwork.md create mode 100644 docs/developers/SDK/technical-references/code/modules.md create mode 100644 docs/developers/SDK/technical-references/code/namespaces/KandelStrategies-1.md create mode 100644 docs/developers/SDK/technical-references/code/namespaces/LiquidityProvider-1.md create mode 100644 docs/developers/SDK/technical-references/code/namespaces/Mangrove-1.md create mode 100644 docs/developers/SDK/technical-references/code/namespaces/Market-1.BookReturns.md create mode 100644 docs/developers/SDK/technical-references/code/namespaces/Market-1.md create mode 100644 docs/developers/SDK/technical-references/code/namespaces/MgvToken-1.md create mode 100644 docs/developers/SDK/technical-references/code/namespaces/Semibook-1.md create mode 100644 docs/developers/SDK/technical-references/code/namespaces/_category_.yml create mode 100644 docs/developers/SDK/technical-references/code/namespaces/eth.md create mode 100644 docs/developers/SDK/technical-references/code/namespaces/mgvTestUtil.md rename docs/{ => developers}/contracts/README.md (97%) rename docs/{ => developers}/contracts/background/_category_.json (100%) rename docs/{ => developers}/contracts/background/offer-maker.md (96%) rename docs/{ => developers}/contracts/background/offer-taker.md (100%) rename docs/{ => developers}/contracts/background/taker-compensation.md (100%) rename docs/{ => developers}/contracts/getting-started/_category_.json (100%) rename docs/{ => developers}/contracts/guides/_category_.json (100%) rename docs/{ => developers}/contracts/technical-references/_category_.json (100%) rename docs/{ => developers}/contracts/technical-references/_contract-addresses-raw.md (100%) rename docs/{ => developers}/contracts/technical-references/codebase.md (100%) rename docs/{ => developers}/contracts/technical-references/contract-addresses.md (100%) rename docs/{ => developers}/contracts/technical-references/governance-parameters/README.md (100%) rename docs/{ => developers}/contracts/technical-references/governance-parameters/global-variables.md (100%) rename docs/{ => developers}/contracts/technical-references/governance-parameters/local-variables.md (100%) rename docs/{ => developers}/contracts/technical-references/governance-parameters/mangrove-configuration.md (100%) rename docs/{ => developers}/contracts/technical-references/mangrove-core-version.json (100%) rename docs/{ => developers}/contracts/technical-references/mangrove-js-version.json (100%) rename docs/{ => developers}/contracts/technical-references/overview.md (96%) rename docs/{ => developers}/contracts/technical-references/periphery/README.md (100%) rename docs/{ => developers}/contracts/technical-references/periphery/cleaner.md (93%) rename docs/{ => developers}/contracts/technical-references/periphery/oracle.md (100%) rename docs/{ => developers}/contracts/technical-references/periphery/reader.md (100%) rename docs/{ => developers}/contracts/technical-references/taking-and-making-offers/README.md (100%) rename docs/{ => developers}/contracts/technical-references/taking-and-making-offers/offer-list.md (100%) rename docs/{ => developers}/contracts/technical-references/taking-and-making-offers/reactive-offer/README.md (100%) rename docs/{ => developers}/contracts/technical-references/taking-and-making-offers/reactive-offer/executing-offers.md (100%) rename docs/{ => developers}/contracts/technical-references/taking-and-making-offers/reactive-offer/gas-requirement.md (100%) rename docs/{ => developers}/contracts/technical-references/taking-and-making-offers/reactive-offer/maker-contract.md (100%) rename docs/{ => developers}/contracts/technical-references/taking-and-making-offers/reactive-offer/offer-data-structures.md (100%) rename docs/{ => developers}/contracts/technical-references/taking-and-making-offers/reactive-offer/offer-provision.md (100%) rename docs/{ => developers}/contracts/technical-references/taking-and-making-offers/taker-order/README.md (100%) rename docs/{ => developers}/contracts/technical-references/taking-and-making-offers/taker-order/delegate-takers.md (100%) rename docs/{ => developers}/contracts/technical-references/taking-and-making-offers/views-on-offers.md (100%) rename docs/{ => developers}/keeper-bots/README.md (100%) rename docs/{ => developers}/keeper-bots/background/_category_.json (100%) rename docs/{ => developers}/keeper-bots/background/the-role-of-cleaning-bots-in-mangrove.md (100%) rename docs/{ => developers}/keeper-bots/background/the-role-of-gas-price-updater-bots-in-mangrove.md (51%) rename docs/{ => developers}/keeper-bots/getting-started/_category_.json (100%) rename docs/{ => developers}/keeper-bots/getting-started/run-a-simple-cleaning-bot.md (100%) rename docs/{ => developers}/keeper-bots/guides/_category_.json (100%) rename docs/{ => developers}/keeper-bots/guides/use-delegation-to-borrow-funds-for-cleaning.md (98%) rename docs/{ => developers}/keeper-bots/guides/use-mgvcleaner-to-clean-offers.md (97%) rename docs/{ => developers}/keeper-bots/technical-reference/_category_.json (100%) rename docs/{ => developers}/keeper-bots/technical-reference/examples.md (100%) rename docs/{ => developers}/strat-lib/README.md (100%) rename docs/{ => developers}/strat-lib/background/_category_.json (100%) rename docs/{ => developers}/strat-lib/background/offer-maker/_category_.json (100%) rename docs/{ => developers}/strat-lib/background/offer-maker/direct.md (96%) rename docs/{ => developers}/strat-lib/background/offer-maker/forwarder.md (98%) rename docs/{ => developers}/strat-lib/background/offer-maker/mangrove-offer.md (98%) rename docs/{ => developers}/strat-lib/getting-started/_category_.json (100%) rename docs/{ => developers}/strat-lib/getting-started/preparation.md (100%) rename docs/{ => developers}/strat-lib/getting-started/smart-offer.md (100%) rename docs/{ => developers}/strat-lib/guides/DirectHowTo.md (100%) rename docs/{ => developers}/strat-lib/guides/HowToDeploy.md (100%) rename docs/{ => developers}/strat-lib/guides/HowToImplement.md (100%) rename docs/{ => developers}/strat-lib/guides/HowToTest.md (100%) rename docs/{ => developers}/strat-lib/guides/_category_.json (100%) rename docs/{ => developers}/strat-lib/guides/approvals.md (98%) rename docs/{ => developers}/strat-lib/guides/howToRenege.md (100%) rename docs/{ => developers}/strat-lib/guides/howToResidual.md (100%) rename docs/{ => developers}/strat-lib/guides/howToSnipe.md (100%) rename docs/{ => developers}/strat-lib/guides/howToUnlockLiquidity.md (98%) rename docs/{ => developers}/strat-lib/guides/howtoGasreq.md (100%) rename docs/{ => developers}/strat-lib/technical-references/_category_.json (100%) rename docs/{ => developers}/strat-lib/technical-references/code/IERC20.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/_category_.json (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/MangroveOffer.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/MangroveOrder.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/integrations/AaveV2Module.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/integrations/AaveV3Borrower.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/integrations/AaveV3BorrowerImplementation.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/integrations/AaveV3BorrowerStorage.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/integrations/AaveV3Lender.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/integrations/CompoundModule.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/interfaces/IForwarder.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/interfaces/ILiquidityProvider.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/interfaces/IOfferLogic.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/interfaces/IOrderLogic.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/offer_forwarder/OfferForwarder.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/offer_forwarder/abstract/Forwarder.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/offer_maker/AaveMaker.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/offer_maker/OfferMaker.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/offer_maker/abstract/Direct.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/AaveKandel.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/AaveKandelSeeder.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/Kandel.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/KandelSeeder.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/AbstractKandel.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/AbstractKandelSeeder.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/CoreKandel.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/DirectWithBidsAndAsksDistribution.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/GeometricKandel.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/HasIndexedBidsAndAsks.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/TradesBaseQuotePair.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/offer_maker/market_making/mango/Mango.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/offer_maker/market_making/mango/MangoImplementation.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/offer_maker/market_making/mango/MangoStorage.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/routers/AbstractRouter.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/routers/SimpleRouter.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/routers/integrations/AavePooledRouter.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/routers/integrations/HasAaveBalanceMemoizer.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/utils/AccessControlled.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/utils/TransferLib.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/vendor/aave/v2/DataTypes.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/vendor/aave/v2/ILendingPool.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/vendor/aave/v2/ILendingPoolAddressesProvider.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/vendor/aave/v2/IPriceOracleGetter.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/vendor/aave/v3/DataTypes.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/vendor/aave/v3/Errors.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/vendor/aave/v3/IATokenIsh.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/vendor/aave/v3/ICreditDelegationToken.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/vendor/aave/v3/IPool.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/vendor/aave/v3/IPoolAddressesProvider.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/vendor/aave/v3/IPriceOracleGetter.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/vendor/aave/v3/IRewardsControllerIsh.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/vendor/aave/v3/ReserveConfiguration.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/vendor/compound/CarefulMath.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/vendor/compound/Exponential.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/vendor/compound/ExponentialNoError.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/strategies/vendor/compound/ICompound.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/toy/ERC20.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/toy/ERC20BL.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/toy/ERC20Lib.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/toy/MintableERC20BLWithDecimals.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/toy/PixieMATIC.md (100%) rename docs/{ => developers}/strat-lib/technical-references/code/toy/PixieUSDC.md (100%) rename docs/{ => developers}/strat-lib/technical-references/main-hooks.md (100%) rename docs/{ => developers}/strat-lib/technical-references/router.md (100%) diff --git a/docs/general.md b/docs/README.md similarity index 98% rename from docs/general.md rename to docs/README.md index 1ae7243b..cc4fd22b 100644 --- a/docs/general.md +++ b/docs/README.md @@ -1,7 +1,6 @@ --- -title: Homepage +title: General sidebar_position: 0 -slug: / --- # What is Mangrove? diff --git a/docs/developers.md b/docs/developers/README.md similarity index 100% rename from docs/developers.md rename to docs/developers/README.md diff --git a/docs/SDK/README.md b/docs/developers/SDK/README.md similarity index 100% rename from docs/SDK/README.md rename to docs/developers/SDK/README.md diff --git a/docs/SDK/background/_category_.json b/docs/developers/SDK/background/_category_.json similarity index 100% rename from docs/SDK/background/_category_.json rename to docs/developers/SDK/background/_category_.json diff --git a/docs/SDK/getting-started/_category_.json b/docs/developers/SDK/getting-started/_category_.json similarity index 100% rename from docs/SDK/getting-started/_category_.json rename to docs/developers/SDK/getting-started/_category_.json diff --git a/docs/SDK/getting-started/_preparation-post.md b/docs/developers/SDK/getting-started/_preparation-post.md similarity index 100% rename from docs/SDK/getting-started/_preparation-post.md rename to docs/developers/SDK/getting-started/_preparation-post.md diff --git a/docs/SDK/getting-started/_preparation-pre.md b/docs/developers/SDK/getting-started/_preparation-pre.md similarity index 100% rename from docs/SDK/getting-started/_preparation-pre.md rename to docs/developers/SDK/getting-started/_preparation-pre.md diff --git a/docs/SDK/getting-started/basic-offer.md b/docs/developers/SDK/getting-started/basic-offer.md similarity index 100% rename from docs/SDK/getting-started/basic-offer.md rename to docs/developers/SDK/getting-started/basic-offer.md diff --git a/docs/SDK/getting-started/deploy-kandel.md b/docs/developers/SDK/getting-started/deploy-kandel.md similarity index 89% rename from docs/SDK/getting-started/deploy-kandel.md rename to docs/developers/SDK/getting-started/deploy-kandel.md index 98695b33..33de1f1e 100644 --- a/docs/SDK/getting-started/deploy-kandel.md +++ b/docs/developers/SDK/getting-started/deploy-kandel.md @@ -5,7 +5,7 @@ sidebar_position: 2 # Deploy Kandel strategy -This tutorial covers how to deploy a Kandel strategy from a developer standpoint. For more information about Kandel, see the [Kandel documentation](../../kandel/README.md). +This tutorial covers how to deploy a Kandel strategy from a developer standpoint. For more information about Kandel, see the [Kandel documentation](../../../kandel/README.md). ## Prerequisites @@ -44,12 +44,12 @@ Next, create an instance to manage Kandel strategies (`kandelStrategies`), and l https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/deploy-kandel.js#L21-L25 ``` -With this, you can generate a [distribution](../../kandel/how-does-kandel-work/step-by-step-visual-explanation.md#price-distribution) with the minimum recommended amount of liquidity to avoid %%density|density%% issues by: +With this, you can generate a [distribution](../../../kandel/how-does-kandel-work/step-by-step-visual-explanation.md#price-distribution) with the minimum recommended amount of liquidity to avoid %%density|density%% issues by: * Creating a generator * Calculating minimums per offer * Calculating the distribution for the given price parameters of `minPrice: 900`, `maxPrice: 1100`, and default ratio -See the API documentation for [calculateMinimumDistribution](../technical-references/code/classes/KandelDistributionGenerator.md#calculateminimumdistribution) for more details on other `priceParams`. In our example here, `midPrice: 1100` is used to set the [current price](../../kandel/how-does-kandel-work/parameters.md), and decide which offers become bids and which become asks. +See the API documentation for [calculateMinimumDistribution](../technical-references/code/classes/KandelDistributionGenerator.md#calculateminimumdistribution) for more details on other `priceParams`. In our example here, `midPrice: 1100` is used to set the [current price](../../../kandel/how-does-kandel-work/parameters.md), and decide which offers become bids and which become asks. ```javascript reference https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/deploy-kandel.js#L27-L58 @@ -87,10 +87,10 @@ https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f A brief explanation on the above `seed` parameters: * `onAave` indicates whether or not the liquidity to be used by Kandel is sitting on AAVE - here, it is not the case (it will be fetched from a wallet) * `market`: this is the WETH/USDC pair that we previously chose -* `liquiditySharing` indicates whether you are using shared liquidity or not (SDK only, not available via the UI). This refers to the concept [amplified liquidity](../../terms/amplified-liquidity.md). +* `liquiditySharing` indicates whether you are using shared liquidity or not (SDK only, not available via the UI). This refers to the concept [amplified liquidity](../../../terms/amplified-liquidity.md). * `gaspriceFactor`: * By using the `recommendedConfig.gaspriceFactor`, we make sure to select the right amount of gas for our Kandel strategy - * This is also connected to the amount of [bounty](../../terms/bounty.md) to be paid in case of a failure to deliver + * This is also connected to the amount of [bounty](../../../terms/bounty.md) to be paid in case of a failure to deliver ### Approve transfers @@ -103,7 +103,7 @@ https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f ### Populate offers for the distribution -Now that our Kandel instance is deployed, we can [populate the offers](../../kandel/how-does-kandel-work/step-by-step-visual-explanation.md#populating-bids-and-asks) for the distribution. +Now that our Kandel instance is deployed, we can [populate the offers](../../../kandel/how-does-kandel-work/step-by-step-visual-explanation.md#populating-bids-and-asks) for the distribution. This will create offers for the base and quote tokens, and deposit the required amounts of tokens into the Kandel instance. The offers also need a %%provision|provision%%, hence here the default that we are using can be inspected. diff --git a/docs/SDK/getting-started/preparation.md b/docs/developers/SDK/getting-started/preparation.md similarity index 100% rename from docs/SDK/getting-started/preparation.md rename to docs/developers/SDK/getting-started/preparation.md diff --git a/docs/SDK/guides/_category_.json b/docs/developers/SDK/guides/_category_.json similarity index 100% rename from docs/SDK/guides/_category_.json rename to docs/developers/SDK/guides/_category_.json diff --git a/docs/SDK/guides/fill-or-kill.md b/docs/developers/SDK/guides/fill-or-kill.md similarity index 100% rename from docs/SDK/guides/fill-or-kill.md rename to docs/developers/SDK/guides/fill-or-kill.md diff --git a/docs/SDK/guides/reuse-offer.md b/docs/developers/SDK/guides/reuse-offer.md similarity index 100% rename from docs/SDK/guides/reuse-offer.md rename to docs/developers/SDK/guides/reuse-offer.md diff --git a/docs/SDK/guides/sell-and-buy-orders.md b/docs/developers/SDK/guides/sell-and-buy-orders.md similarity index 100% rename from docs/SDK/guides/sell-and-buy-orders.md rename to docs/developers/SDK/guides/sell-and-buy-orders.md diff --git a/docs/SDK/guides/snipe-offer.md b/docs/developers/SDK/guides/snipe-offer.md similarity index 100% rename from docs/SDK/guides/snipe-offer.md rename to docs/developers/SDK/guides/snipe-offer.md diff --git a/docs/SDK/guides/update-offer.md b/docs/developers/SDK/guides/update-offer.md similarity index 100% rename from docs/SDK/guides/update-offer.md rename to docs/developers/SDK/guides/update-offer.md diff --git a/docs/SDK/technical-references/_category_.json b/docs/developers/SDK/technical-references/_category_.json similarity index 100% rename from docs/SDK/technical-references/_category_.json rename to docs/developers/SDK/technical-references/_category_.json diff --git a/docs/SDK/technical-references/api-overview.md b/docs/developers/SDK/technical-references/api-overview.md similarity index 100% rename from docs/SDK/technical-references/api-overview.md rename to docs/developers/SDK/technical-references/api-overview.md diff --git a/docs/developers/SDK/technical-references/code/_category_.yml b/docs/developers/SDK/technical-references/code/_category_.yml new file mode 100644 index 00000000..463a030e --- /dev/null +++ b/docs/developers/SDK/technical-references/code/_category_.yml @@ -0,0 +1,2 @@ +label: "API Reference" +position: 999 \ No newline at end of file diff --git a/docs/developers/SDK/technical-references/code/classes/KandelDistribution.md b/docs/developers/SDK/technical-references/code/classes/KandelDistribution.md new file mode 100644 index 00000000..9d184686 --- /dev/null +++ b/docs/developers/SDK/technical-references/code/classes/KandelDistribution.md @@ -0,0 +1,322 @@ +--- +id: "KandelDistribution" +title: "Class: KandelDistribution" +sidebar_label: "KandelDistribution" +sidebar_position: 0 +custom_edit_url: null +--- + +**`Title`** + +A distribution of bids and ask for Kandel. + +## Properties + +### offers + +• **offers**: `OfferDistribution` + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:20 + +___ + +### baseDecimals + +• **baseDecimals**: `number` + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:21 + +___ + +### quoteDecimals + +• **quoteDecimals**: `number` + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:22 + +___ + +### ratio + +• **ratio**: `Big` + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:23 + +___ + +### pricePoints + +• **pricePoints**: `number` + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:24 + +___ + +### helper + +• **helper**: `KandelDistributionHelper` + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:25 + +## Constructors + +### constructor + +• **new KandelDistribution**(`ratio`, `pricePoints`, `offers`, `baseDecimals`, `quoteDecimals`) + +Constructor + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `ratio` | `Big` | The ratio used when calculating the price distribution. | +| `pricePoints` | `number` | The number of price points in the distribution. Can be more than the number of offers if a subset is considered. | +| `offers` | `OfferDistribution` | The distribution of bids and asks. | +| `baseDecimals` | `number` | The number of decimals for the base token. | +| `quoteDecimals` | `number` | The number of decimals for the quote token. | + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:34 + +## Methods + +### getOfferCount + +▸ **getOfferCount**(): `number` + +Gets the number of offers in the distribution. This can be lower than the number of price points when a subset is considered. + +#### Returns + +`number` + +The number of offers in the distribution. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:53 + +___ + +### calculateOfferGives + +▸ **calculateOfferGives**(`offerType`, `offerCount`, `totalVolume`): `Big` + +Calculates the gives for a single offer of the given type given the total available volume and the count of offers of that type. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `offerType` | [`BA`](../namespaces/Market-1.md#ba) | The type of offer. | +| `offerCount` | `number` | The count of offers of the given type. | +| `totalVolume` | `Big` | The total available volume. | + +#### Returns + +`Big` + +The amount of base or quote to give for the offer. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:63 + +___ + +### calculateConstantGivesPerOffer + +▸ **calculateConstantGivesPerOffer**(`availableBase?`, `availableQuote?`): `Object` + +Calculates the gives for bids and asks based on the available volume for the distribution. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `availableBase?` | `Big` | The available base to consume. | +| `availableQuote?` | `Big` | The available quote to consume. | + +#### Returns + +`Object` + +The amount of base or quote to give for each offer. + +| Name | Type | +| :------ | :------ | +| `askGives` | `undefined` \| `Big` | +| `bidGives` | `undefined` \| `Big` | + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:90 + +___ + +### getFirstAskIndex + +▸ **getFirstAskIndex**(): `number` + +Gets the index of the first ask in the distribution. If there are no asks, then the length of the distribution is returned. + +#### Returns + +`number` + +The index of the first ask in the distribution; or the length of the distribution if there are no asks. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:110 + +___ + +### getOffersIndexOfFirstAskIndex + +▸ **getOffersIndexOfFirstAskIndex**(): `number` + +Gets the index of the first ask in the subset of offers in offers for the distribution. If there are no asks, then the length of offers is returned. + +#### Returns + +`number` + +The index of the first ask in the subset of offers in offers for the distribution. If there are no asks, then the length of offers is returned. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:119 + +___ + +### chunkDistribution + +▸ **chunkDistribution**(`pivots`, `maxOffersInChunk`): { `pivots`: `number`[] ; `distribution`: `OfferDistribution` }[] + +Split a distribution and its pivots into chunks according to the maximum number of offers in a single chunk. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `pivots` | `number`[] | The pivots for the distribution. | +| `maxOffersInChunk` | `number` | The maximum number of offers in a single chunk. | + +#### Returns + +{ `pivots`: `number`[] ; `distribution`: `OfferDistribution` }[] + +The chunks. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:133 + +___ + +### getPricesForDistribution + +▸ **getPricesForDistribution**(): (`undefined` \| `Big`)[] + +Gets the prices for the distribution, with undefined for prices not represented by offers in the distribution. + +#### Returns + +(`undefined` \| `Big`)[] + +The prices in the distribution. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:174 + +___ + +### getOfferedVolumeForDistribution + +▸ **getOfferedVolumeForDistribution**(): `Object` + +Gets the required volume of base and quote for the distribution to be fully provisioned. + +#### Returns + +`Object` + +The offered volume of base and quote for the distribution to be fully provisioned. + +| Name | Type | +| :------ | :------ | +| `requiredBase` | `Big` | +| `requiredQuote` | `Big` | + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:186 + +___ + +### verifyDistribution + +▸ **verifyDistribution**(): `void` + +Verifies the distribution is valid. + +**`Remarks`** + +Throws if the distribution is invalid. +The verification checks that indices are ascending and bids come before asks. +The price distribution is not verified. + +#### Returns + +`void` + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:208 + +___ + +### getRequiredProvision + +▸ **getRequiredProvision**(`params`): `Promise`<`Big`\> + +Determines the required provision for the listed offers in the distribution (disregarding the number of price points). + +**`Remarks`** + +This takes into account that each of the offers represent a price point which can become both an ask and a bid which both require provision. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters used to calculate the provision. | +| `params.market` | [`Market`](Market.md) | The market to get provisions for bids and asks from. | +| `params.gasreq` | `number` | The gas required to execute a trade. | +| `params.gasprice` | `number` | The gas price to calculate provision for. | + +#### Returns + +`Promise`<`Big`\> + +The provision required for the number of offers. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:237 diff --git a/docs/developers/SDK/technical-references/code/classes/KandelDistributionGenerator.md b/docs/developers/SDK/technical-references/code/classes/KandelDistributionGenerator.md new file mode 100644 index 00000000..5f87bb3c --- /dev/null +++ b/docs/developers/SDK/technical-references/code/classes/KandelDistributionGenerator.md @@ -0,0 +1,243 @@ +--- +id: "KandelDistributionGenerator" +title: "Class: KandelDistributionGenerator" +sidebar_label: "KandelDistributionGenerator" +sidebar_position: 0 +custom_edit_url: null +--- + +**`Title`** + +Helper for generating Kandel distributions. + +## Properties + +### distributionHelper + +• **distributionHelper**: `KandelDistributionHelper` + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelDistributionGenerator.ts:14 + +___ + +### priceCalculation + +• **priceCalculation**: `KandelPriceCalculation` + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelDistributionGenerator.ts:15 + +## Constructors + +### constructor + +• **new KandelDistributionGenerator**(`distributionHelper`, `priceCalculation`) + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `distributionHelper` | `KandelDistributionHelper` | +| `priceCalculation` | `KandelPriceCalculation` | + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelDistributionGenerator.ts:17 + +## Methods + +### calculateMinimumDistribution + +▸ **calculateMinimumDistribution**(`params`): [`KandelDistribution`](KandelDistribution.md) + +Calculates a minimal recommended volume distribution of bids and asks and their base and quote amounts to match the geometric price distribution given by parameters. + +**`Remarks`** + +The price distribution may not match the priceDistributionParams exactly due to limited precision. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters for the geometric distribution. | +| `params.priceParams` | `PriceDistributionParams` | The parameters for the geometric price distribution. | +| `params.midPrice` | `BigSource` | The mid-price used to determine when to switch from bids to asks. | +| `params.constantBase?` | `boolean` | Whether the base amount should be constant for all offers. | +| `params.constantQuote?` | `boolean` | Whether the quote amount should be constant for all offers. | +| `params.minimumBasePerOffer` | `BigSource` | The minimum amount of base to give for each offer. Should be at least minimumBasePerOfferFactor from KandelConfiguration multiplied with the minimum volume for the market. | +| `params.minimumQuotePerOffer` | `BigSource` | The minimum amount of quote to give for each offer. Should be at least minimumQuotePerOfferFactor from KandelConfiguration multiplied with the minimum volume for the market. | + +#### Returns + +[`KandelDistribution`](KandelDistribution.md) + +The distribution of bids and asks and their base and quote amounts. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelDistributionGenerator.ts:36 + +___ + +### calculateDistribution + +▸ **calculateDistribution**(`params`): [`KandelDistribution`](KandelDistribution.md) + +Calculates distribution of bids and asks and their base and quote amounts to match the geometric price distribution given by parameters. + +**`Remarks`** + +The price distribution may not match the priceDistributionParams exactly due to limited precision. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters for the geometric distribution. | +| `params.priceParams` | `PriceDistributionParams` | The parameters for the geometric price distribution. | +| `params.midPrice` | `BigSource` | The mid-price used to determine when to switch from bids to asks. | +| `params.initialAskGives?` | `BigSource` | The initial amount of base to give for all asks. Should be at least minimumBasePerOfferFactor from KandelConfiguration multiplied with the minimum volume for the market. If not provided, then initialBidGives is used as quote for asks, and the base the ask gives is set to according to the price. | +| `params.initialBidGives?` | `BigSource` | The initial amount of quote to give for all bids. Should be at least minimumQuotePerOfferFactor from KandelConfiguration multiplied with the minimum volume for the market. If not provided, then initialAskGives is used as base for bids, and the quote the bid gives is set to according to the price. | + +#### Returns + +[`KandelDistribution`](KandelDistribution.md) + +The distribution of bids and asks and their base and quote amounts. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelDistributionGenerator.ts:72 + +___ + +### recalculateDistributionFromAvailable + +▸ **recalculateDistributionFromAvailable**(`params`): [`KandelDistribution`](KandelDistribution.md) + +Recalculates the gives for offers in the distribution such that the available base and quote is consumed uniformly, while preserving the price distribution. + +**`Remarks`** + +The required volume can be slightly less than available due to rounding due to token decimals. +Note that the resulting offered base volume for each offer should be at least minimumBasePerOfferFactor from KandelConfiguration multiplied with the minimum volume for the market - and similar for quote. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters for the recalculation. | +| `params.distribution` | [`KandelDistribution`](KandelDistribution.md) | The distribution to reset the gives for. | +| `params.availableBase?` | `BigSource` | The available base to consume. If not provided, then the quote for bids is also used as quote for asks, and the base the ask gives is set to according to the price. | +| `params.availableQuote?` | `BigSource` | The available quote to consume. If not provided, then the base for asks is also used as base for bids, and the quote the bid gives is set to according to the price. | + +#### Returns + +[`KandelDistribution`](KandelDistribution.md) + +The distribution of bids and asks and their base and quote amounts. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelDistributionGenerator.ts:103 + +___ + +### uniformlyChangeVolume + +▸ **uniformlyChangeVolume**(`params`): `Object` + +Creates a new distribution with uniformly changed volume. + +**`Remarks`** + +The decrease has to respect minimums, and thus may decrease some offers more than others. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters for the change. | +| `params.distribution` | [`KandelDistribution`](KandelDistribution.md) | The distribution to change. | +| `params.baseDelta?` | `BigSource` | The change in base volume. | +| `params.quoteDelta?` | `BigSource` | The change in quote volume. | +| `params.minimumBasePerOffer` | `BigSource` | The minimum amount of base to give for each offer. Should be at least minimumBasePerOfferFactor from KandelConfiguration multiplied with the minimum volume for the market. | +| `params.minimumQuotePerOffer` | `BigSource` | The minimum amount of quote to give for each offer. Should be at least minimumQuotePerOfferFactor from KandelConfiguration multiplied with the minimum volume for the market. | + +#### Returns + +`Object` + +The new distribution. + +| Name | Type | +| :------ | :------ | +| `distribution` | [`KandelDistribution`](KandelDistribution.md) | +| `totalBaseChange` | `Big` | +| `totalQuoteChange` | `Big` | + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelDistributionGenerator.ts:133 + +___ + +### createDistributionWithOffers + +▸ **createDistributionWithOffers**(`params`): [`KandelDistribution`](KandelDistribution.md) + +Creates a distribution based on an explicit set of offers. Either based on an original distribution or parameters for one. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters for the distribution. | +| `params.explicitOffers` | `OffersWithGives` | The explicit offers to use. | +| `params.distribution` | [`KandelDistribution`](KandelDistribution.md) \| { `ratio`: `BigSource` ; `pricePoints`: `number` } | The original distribution or parameters for one. If pricePoints is not provided, then the number of offers is used. | + +#### Returns + +[`KandelDistribution`](KandelDistribution.md) + +The new distribution. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelDistributionGenerator.ts:165 + +___ + +### getMinimumVolumeForIndex + +▸ **getMinimumVolumeForIndex**(`params`): `Big` + +Retrieves the minimum volume for a given offer type at the given index. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters for the minimum volume. | +| `params.offerType` | [`BA`](../namespaces/Market-1.md#ba) | The offer type to get the minimum volume for. | +| `params.index` | `number` | The Kandel index. | +| `params.price` | `BigSource` | The price at the index. | +| `params.ratio` | `BigSource` | The ratio of the geometric progression of prices. | +| `params.spread` | `number` | The spread used when transporting funds from an offer to its dual. | +| `params.pricePoints` | `number` | The number of price points. | +| `params.minimumBasePerOffer` | `BigSource` | The minimum base token volume per offer. If not provided, then the minimum base token volume is used. | +| `params.minimumQuotePerOffer` | `BigSource` | The minimum quote token volume per offer. If not provided, then the minimum quote token volume is used. | + +#### Returns + +`Big` + +The minimum volume for the given offer type and the index. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelDistributionGenerator.ts:199 diff --git a/docs/developers/SDK/technical-references/code/classes/KandelFarm.md b/docs/developers/SDK/technical-references/code/classes/KandelFarm.md new file mode 100644 index 00000000..b883a912 --- /dev/null +++ b/docs/developers/SDK/technical-references/code/classes/KandelFarm.md @@ -0,0 +1,97 @@ +--- +id: "KandelFarm" +title: "Class: KandelFarm" +sidebar_label: "KandelFarm" +sidebar_position: 0 +custom_edit_url: null +--- + +**`Title`** + +Repository for Kandel instances. + +## Properties + +### mgv + +• **mgv**: [`Mangrove`](Mangrove.md) + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelFarm.ts:11 + +___ + +### tradeEventManagement + +• **tradeEventManagement**: `TradeEventManagement` + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelFarm.ts:12 + +___ + +### aaveKandelSeeder + +• **aaveKandelSeeder**: `AaveKandelSeeder` + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelFarm.ts:14 + +___ + +### kandelSeeder + +• **kandelSeeder**: `KandelSeeder` + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelFarm.ts:15 + +## Constructors + +### constructor + +• **new KandelFarm**(`mgv`) + +Constructor + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `mgv` | [`Mangrove`](Mangrove.md) | The Mangrove to get kandels for. | + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelFarm.ts:20 + +## Methods + +### getKandels + +▸ **getKandels**(`filter?`): `Promise`<{ `kandelAddress`: `string` = x.args.kandel; `ownerAddress`: `string` = x.args.owner; `onAave`: `boolean` = false; `baseAddress`: `string` = baseToken.address; `base`: `undefined` \| [`MgvToken`](MgvToken.md) = baseToken.token; `quoteAddress`: `string` = quoteToken.address; `quote`: `undefined` \| [`MgvToken`](MgvToken.md) = quoteToken.token }[]\> + +Gets all Kandels matching a given filter. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `filter?` | `Object` | The filter to apply. | +| `filter.owner?` | ``null`` \| `PromiseOrValue`<`string`\> | The Kandel instance owner - the one who invoked sow. | +| `filter.base?` | ``null`` \| `PromiseOrValue`<`string`\> | The base token for the Kandel instance. | +| `filter.quote?` | ``null`` \| `PromiseOrValue`<`string`\> | The quote token for the Kandel instance. | +| `filter.onAave?` | `boolean` | Whether the Kandel instance uses the Aave router. | + +#### Returns + +`Promise`<{ `kandelAddress`: `string` = x.args.kandel; `ownerAddress`: `string` = x.args.owner; `onAave`: `boolean` = false; `baseAddress`: `string` = baseToken.address; `base`: `undefined` \| [`MgvToken`](MgvToken.md) = baseToken.token; `quoteAddress`: `string` = quoteToken.address; `quote`: `undefined` \| [`MgvToken`](MgvToken.md) = quoteToken.token }[]\> + +All kandels matching the filter. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelFarm.ts:51 diff --git a/docs/developers/SDK/technical-references/code/classes/KandelInstance.md b/docs/developers/SDK/technical-references/code/classes/KandelInstance.md new file mode 100644 index 00000000..00f164b4 --- /dev/null +++ b/docs/developers/SDK/technical-references/code/classes/KandelInstance.md @@ -0,0 +1,1196 @@ +--- +id: "KandelInstance" +title: "Class: KandelInstance" +sidebar_label: "KandelInstance" +sidebar_position: 0 +custom_edit_url: null +--- + +**`Title`** + +Management of a single Kandel instance. + +## Properties + +### kandel + +• **kandel**: `GeometricKandel` + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:53 + +___ + +### address + +• **address**: `string` + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:54 + +___ + +### precision + +• **precision**: `number` + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:55 + +___ + +### market + +• **market**: [`Market`](Market.md) + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:56 + +___ + +### generator + +• **generator**: [`KandelDistributionGenerator`](KandelDistributionGenerator.md) + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:57 + +___ + +### status + +• **status**: `KandelStatus` + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:58 + +___ + +### configuration + +• **configuration**: `KandelConfiguration` + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:59 + +___ + +### seeder + +• **seeder**: [`KandelSeeder`](KandelSeeder.md) + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:60 + +___ + +### offerLogic + +• **offerLogic**: [`OfferLogic`](OfferLogic.md) + +Expose logic relevant for all offer logic implementations, including Kandel. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:63 + +## Methods + +### create + +▸ `Static` **create**(`params`): `Promise`<[`KandelInstance`](KandelInstance.md)\> + +Creates a KandelInstance object to interact with a Kandel strategy on Mangrove. + +**`Dev`** + +If a factory function is provided for the market, then remember to disconnect market when no longer needed. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters used to create an instance. | +| `params.address` | `string` | The address of the Kandel instance. | +| `params.signer` | `Signer` | The signer used to interact with the Kandel instance. | +| `params.market` | [`Market`](Market.md) \| (`baseAddress`: `string`, `quoteAddress`: `string`) => `Promise`<[`Market`](Market.md)\> | The market used by the Kandel instance or a factory function to create the market. | + +#### Returns + +`Promise`<[`KandelInstance`](KandelInstance.md)\> + +A new KandelInstance. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:73 + +___ + +### getBase + +▸ **getBase**(): [`MgvToken`](MgvToken.md) + +Gets the base of the market Kandel is making + +#### Returns + +[`MgvToken`](MgvToken.md) + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:144 + +___ + +### getQuote + +▸ **getQuote**(): [`MgvToken`](MgvToken.md) + +Gets the quote of the market Kandel is making + +#### Returns + +[`MgvToken`](MgvToken.md) + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:149 + +___ + +### getReserveId + +▸ **getReserveId**(): `Promise`<`string`\> + +Retrieves the identifier of this contract's reserve when using a router + +#### Returns + +`Promise`<`string`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:154 + +___ + +### getBalance + +▸ **getBalance**(`offerType`): `Promise`<`Big`\> + +Retrieves the total balance available for this Kandel instance of the offered token for the given offer type. + +**`Remarks`** + +with liquidity sharing and a router, this will be shared among other Kandel instances. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `offerType` | [`BA`](../namespaces/Market-1.md#ba) | The offer type. | + +#### Returns + +`Promise`<`Big`\> + +The balance of the asset. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:163 + +___ + +### getUnpublished + +▸ **getUnpublished**(`offerType`): `Promise`<`Big`\> + +Retrieves the amount of liquidity that is available for the Kandel instance but not offered by the given offer type. + +**`Remarks`** + +with liquidity sharing and a router, the balance will be shared among other Kandel instances and the unpublished can be seen as a buffer. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `offerType` | [`BA`](../namespaces/Market-1.md#ba) | The offer type. | + +#### Returns + +`Promise`<`Big`\> + +the unpublished liquidity. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:173 + +___ + +### getOfferedVolume + +▸ **getOfferedVolume**(`offerType`): `Promise`<`Big`\> + +Retrieves the total offered volume for the offer type for this Kandel instance. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `offerType` | [`BA`](../namespaces/Market-1.md#ba) | The offer type. | + +#### Returns + +`Promise`<`Big`\> + +The offered volume. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:182 + +___ + +### getParameters + +▸ **getParameters**(): `Promise`<`KandelParameters`\> + +Retrieves the current Kandel parameters + +#### Returns + +`Promise`<`KandelParameters`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:188 + +___ + +### getParametersWithOverrides + +▸ **getParametersWithOverrides**(`parameters`, `distributionRatio?`, `distributionPricePoints?`): `Promise`<`KandelParameters`\> + +Gets new Kandel parameters based on current and some overrides. + +**`Remarks`** + +Ratio and price points provided in the parameters must match a provided distribution. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `parameters` | `KandelParameterOverrides` | The Kandel parameters to override, those left out will keep their current value. | +| `distributionRatio?` | `BigSource` | The ratio of the Kandel distribution. | +| `distributionPricePoints?` | `number` | The number of price points of the Kandel distribution. | + +#### Returns + +`Promise`<`KandelParameters`\> + +The new Kandel parameters. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:222 + +___ + +### getOutboundToken + +▸ **getOutboundToken**(`offerType`): [`MgvToken`](MgvToken.md) + +Gets the outbound token for bids/asks. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `offerType` | [`BA`](../namespaces/Market-1.md#ba) | The bid/ask identifier. | + +#### Returns + +[`MgvToken`](MgvToken.md) + +The outbound token. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:290 + +___ + +### getOfferIdAtIndex + +▸ **getOfferIdAtIndex**(`offerType`, `index`): `Promise`<`number`\> + +Gets the Mangrove offer id for a Kandel index. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `offerType` | [`BA`](../namespaces/Market-1.md#ba) | The bid/ask identifier. | +| `index` | `number` | The Kandel index. | + +#### Returns + +`Promise`<`number`\> + +The Mangrove offer id. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:299 + +___ + +### getIndexOfOfferId + +▸ **getIndexOfOfferId**(`offerType`, `offerId`): `Promise`<`number`\> + +Gets the Kandel index for a Mangrove offer id. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `offerType` | [`BA`](../namespaces/Market-1.md#ba) | The bid/ask identifier. | +| `offerId` | `number` | The Mangrove offer id. | + +#### Returns + +`Promise`<`number`\> + +The Kandel index. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:310 + +___ + +### getPivots + +▸ **getPivots**(`distribution`): `Promise`<`number`[]\> + +Retrieves pivots to use for populating the offers in the distribution + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `distribution` | [`KandelDistribution`](KandelDistribution.md) | The distribution to get pivots for. | + +#### Returns + +`Promise`<`number`[]\> + +The pivots to use when populating the distribution. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:320 + +___ + +### getRawDistribution + +▸ **getRawDistribution**(`distribution`): `DistributionStruct` + +Convert public Kandel distribution to internal representation. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `distribution` | `OfferDistribution` | The Kandel distribution. | + +#### Returns + +`DistributionStruct` + +The internal representation of the Kandel distribution. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:340 + +___ + +### getOfferIds + +▸ **getOfferIds**(): `Promise`<{ `offerType`: [`BA`](../namespaces/Market-1.md#ba) ; `offerId`: `number` ; `index`: `number` }[]\> + +Retrieves the Mangrove offer ids for all offers. + +#### Returns + +`Promise`<{ `offerType`: [`BA`](../namespaces/Market-1.md#ba) ; `offerId`: `number` ; `index`: `number` }[]\> + +The Mangrove offer ids for all offers along with their offer type and Kandel index. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:358 + +___ + +### getOffers + +▸ **getOffers**(): `Promise`<{ `offerType`: [`BA`](../namespaces/Market-1.md#ba) ; `offerId`: `number` ; `index`: `number` ; `offer`: [`Offer`](../namespaces/Market-1.md#offer) = offer }[]\> + +Retrieves all offers for the Kandel instance by querying the market. + +#### Returns + +`Promise`<{ `offerType`: [`BA`](../namespaces/Market-1.md#ba) ; `offerId`: `number` ; `index`: `number` ; `offer`: [`Offer`](../namespaces/Market-1.md#offer) = offer }[]\> + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:371 + +___ + +### getOfferStatuses + +▸ **getOfferStatuses**(`midPrice`): `Promise`<`Statuses`\> + +Retrieves all offers from the market and determines their status. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `midPrice` | `BigSource` | The current mid price of the market used to discern expected bids from asks. | + +#### Returns + +`Promise`<`Statuses`\> + +The status of all offers. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:387 + +___ + +### getOfferStatusFromOffers + +▸ **getOfferStatusFromOffers**(`params`): `Promise`<`Statuses`\> + +Determines the status of the Kandel instance based on the passed in offers. + +**`Throws`** + +If no offers are live. At least one live offer is required to determine the status. + +**`Remarks`** + +The expected prices is determined by extrapolating from a live offer closest to the mid price. +Offers are expected to be live bids below the mid price and asks above. +This may not hold if an offer deep in the book has been sniped in which case a dual offer will exist on the wrong side of mid price but quickly be taken due to a good price (Kandel still earns on the spread). +Offers are expected to be dead near the mid price due to the spread (step size) between the live bid and ask. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters to use to determine the status. | +| `params.midPrice` | `BigSource` | The current mid price of the market used to discern expected bids from asks. | +| `params.offers` | `OffersWithPrices` | The offers used as a basis for determining the status. This should include all live and dead offers. | + +#### Returns + +`Promise`<`Statuses`\> + +The status of the Kandel instance. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:412 + +___ + +### createDistributionWithOffers + +▸ **createDistributionWithOffers**(`params`): `Promise`<[`KandelDistribution`](KandelDistribution.md)\> + +Creates a distribution based on an explicit set of offers based on the Kandel parameters. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters for the distribution. | +| `params.explicitOffers` | `OffersWithGives` | The explicit offers to use. | + +#### Returns + +`Promise`<[`KandelDistribution`](KandelDistribution.md)\> + +The new distribution. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:432 + +___ + +### getMinimumVolume + +▸ **getMinimumVolume**(`offerType`): `Promise`<`Big`\> + +Retrieves the minimum volume for a given offer type. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `offerType` | [`BA`](../namespaces/Market-1.md#ba) | The offer type to get the minimum volume for. | + +#### Returns + +`Promise`<`Big`\> + +The minimum volume for the given offer type. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:449 + +___ + +### getMinimumVolumeForIndex + +▸ **getMinimumVolumeForIndex**(`params`): `Promise`<`Big`\> + +Retrieves the minimum volume for a given offer type at the given index. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters for the minimum volume. | +| `params.offerType` | [`BA`](../namespaces/Market-1.md#ba) | The offer type to get the minimum volume for. | +| `params.index` | `number` | The Kandel index. | +| `params.price` | `BigSource` | The price at the index. | +| `params.minimumBasePerOffer?` | `BigSource` | The minimum base token volume per offer. If not provided, then the minimum base token volume is used. | +| `params.minimumQuotePerOffer?` | `BigSource` | The minimum quote token volume per offer. If not provided, then the minimum quote token volume is used. | + +#### Returns + +`Promise`<`Big`\> + +The minimum volume for the given offer type. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:466 + +___ + +### calculateDistributionWithUniformlyChangedVolume + +▸ **calculateDistributionWithUniformlyChangedVolume**(`params`): `Promise`<{ `distribution`: [`KandelDistribution`](KandelDistribution.md) ; `totalBaseChange`: `Big` ; `totalQuoteChange`: `Big` }\> + +Calculates a new distribution based on the provided live offers and deltas. + +**`Remarks`** + +The base and quote deltas are applied uniformly to all offers, except during decrease where offers are kept above their minimum volume. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters for the new distribution. | +| `params.liveOffers` | `OffersWithGives` | The live offers to use. | +| `params.baseDelta?` | `BigSource` | The delta to apply to the base token volume. If not provided, then the base token volume is unchanged. | +| `params.quoteDelta?` | `BigSource` | The delta to apply to the quote token volume. If not provided, then the quote token volume is unchanged. | +| `params.minimumBasePerOffer?` | `BigSource` | The minimum base token volume per offer. If not provided, then the minimum base token volume is used. | +| `params.minimumQuotePerOffer?` | `BigSource` | The minimum quote token volume per offer. If not provided, then the minimum quote token volume is used. | + +#### Returns + +`Promise`<{ `distribution`: [`KandelDistribution`](KandelDistribution.md) ; `totalBaseChange`: `Big` ; `totalQuoteChange`: `Big` }\> + +The new distribution for the live offers, dead offers are not included. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:522 + +___ + +### calculateUniformDistributionFromMinPrice + +▸ **calculateUniformDistributionFromMinPrice**(`params`): `Promise`<[`KandelDistribution`](KandelDistribution.md)\> + +Calculates a new uniform distribution based on the available base and quote balance and min price and mid price. + +**`See`** + + - getOfferStatus or + - getOfferStatusFromOffers . + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters for the new distribution. | +| `params.midPrice` | `BigSource` | The current mid price of the market used to discern expected bids from asks. | +| `params.minPrice` | `BigSource` | The minimum price to generate the distribution from; can be retrieved from the status from | +| `params.minimumBasePerOffer?` | `BigSource` | The minimum base token volume per offer. If not provided, then the minimum base token volume is used. | +| `params.minimumQuotePerOffer?` | `BigSource` | The minimum quote token volume per offer. If not provided, then the minimum quote token volume is used. | + +#### Returns + +`Promise`<[`KandelDistribution`](KandelDistribution.md)\> + +The new distribution, which can be used to re-populate the Kandel instance with this exact distribution. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:553 + +___ + +### approveIfHigher + +▸ **approveIfHigher**(`baseArgs?`, `quoteArgs?`): `Promise`<(`undefined` \| `ContractTransaction`)[]\> + +Approves the Kandel instance for transferring from signer to itself if allowance is not already high enough. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `baseArgs` | `ApproveArgs` | The arguments for approving the base token. If not provided, then infinite approval is used. | +| `quoteArgs` | `ApproveArgs` | The arguments for approving the quote token. If not provided, then infinite approval is used. | + +#### Returns + +`Promise`<(`undefined` \| `ContractTransaction`)[]\> + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:589 + +___ + +### deposit + +▸ **deposit**(`params`, `overrides?`): `Promise`<`ContractTransaction`\> + +Deposits the amounts on the Kandel instance to be available for offers. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters to use when depositing funds. | +| `params.baseAmount?` | `BigSource` | The amount of base to deposit. If not provided, then no base is deposited. | +| `params.quoteAmount?` | `BigSource` | The amount of quote to deposit. If not provided, then no quote is deposited. | +| `overrides` | `Overrides` | The ethers overrides to use when calling the deposit function. | + +#### Returns + +`Promise`<`ContractTransaction`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:605 + +___ + +### getMostSpecificConfig + +▸ **getMostSpecificConfig**(): `KandelNetworkConfiguration` & `Partial`<`KandelMarketConfiguration`\> + +Gets the most specific available default configuration for Kandel instances. + +#### Returns + +`KandelNetworkConfiguration` & `Partial`<`KandelMarketConfiguration`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:620 + +___ + +### getRawDistributionChunks + +▸ **getRawDistributionChunks**(`params`): `Promise`<{ `rawDistributions`: { `pivots`: `number`[] ; `rawDistribution`: `DistributionStruct` }[] ; `firstAskIndex`: `number` }\> + +Splits the distribution into chunks and converts it to internal representation. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters. | +| `params.distribution` | [`KandelDistribution`](KandelDistribution.md) | The distribution to split. | +| `params.maxOffersInChunk?` | `number` | The maximum number of offers in a chunk. If not provided, then KandelConfiguration is used. | + +#### Returns + +`Promise`<{ `rawDistributions`: { `pivots`: `number`[] ; `rawDistribution`: `DistributionStruct` }[] ; `firstAskIndex`: `number` }\> + +The raw distributions in internal representation and the index of the first ask. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:634 + +___ + +### getGasreqAndGasprice + +▸ **getGasreqAndGasprice**(`gasreq?`, `gasprice?`): `Promise`<{ `gasreq`: `number` ; `gasprice`: `number` }\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `gasreq?` | `number` | +| `gasprice?` | `number` | + +#### Returns + +`Promise`<{ `gasreq`: `number` ; `gasprice`: `number` }\> + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:659 + +___ + +### getRequiredProvision + +▸ **getRequiredProvision**(`params`): `Promise`<`Big`\> + +Determines the required provision for the offers in the distribution or the supplied offer count. + +**`Remarks`** + +This takes into account that each price point can become both an ask and a bid which both require provision. Existing locked provision or balance on Mangrove is not accounted for. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters used to calculate the provision. | +| `params.distribution?` | [`KandelDistribution`](KandelDistribution.md) | The distribution to calculate the provision for. Optional if offerCount is provided. | +| `params.offerCount?` | `number` | The number of offers to calculate the provision for. Optional if distribution is provided. | +| `params.gasreq?` | `number` | The gas required to execute a trade. Default is retrieved from Kandel parameters. | +| `params.gasprice?` | `number` | The gas price to calculate provision for. Default is retrieved from Kandel parameters. | + +#### Returns + +`Promise`<`Big`\> + +The provision required for the number of offers. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:679 + +___ + +### getLockedProvision + +▸ **getLockedProvision**(): `Promise`<`Big`\> + +Calculates the provision locked by existing offers based on the given parameters + +#### Returns + +`Promise`<`Big`\> + +the locked provision, in ethers. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:716 + +___ + +### getLockedProvisionFromOffers + +▸ **getLockedProvisionFromOffers**(`existingOffers`): `Big` + +Calculates the provision locked for a set of offers based on the given parameters + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `existingOffers` | { `gasprice`: `number` ; `gasreq`: `number` ; `gasbase`: `number` }[] | + +#### Returns + +`Big` + +the locked provision, in ethers. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:728 + +___ + +### getMissingProvision + +▸ **getMissingProvision**(`params`): `Promise`<`Big`\> + +Gets the missing provision based on provision already available on Mangrove, potentially locked by existing offers. It assumes all locked provision will be made available via deprovision or due to offers being replaced. + +**`Remarks`** + +If neither params.distribution nor params.offerCount is provided, then the current number of price points is used. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters. | +| `params.gasreq?` | `number` | An optional new gas required to execute a trade. Default is retrieved from Kandel parameters. | +| `params.gasprice?` | `number` | An optional new gas price to calculate provision for. Default is retrieved from Kandel parameters. | +| `params.distribution?` | [`KandelDistribution`](KandelDistribution.md) | The distribution to calculate the provision for. Optional. | +| `params.offerCount?` | `number` | The number of offers to calculate the provision for. Optional. | + +#### Returns + +`Promise`<`Big`\> + +the additional required provision, in ethers. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:743 + +___ + +### getMissingProvisionFromOffers + +▸ **getMissingProvisionFromOffers**(`params`, `existingOffers`): `Promise`<`Big`\> + +Gets the missing provision based on provision already available on Mangrove, potentially locked by existing offers, and the new distribution requiring provision. It assumes all the provision locked in the existingOffers will be made available via deprovision or due to offers being updated. + +**`Remarks`** + +If neither distribution nor offerCount is provided, then the current number of price points is used. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters for the required provision. | +| `params.gasreq?` | `number` | An optional new gas required to execute a trade. Default is retrieved from Kandel parameters. | +| `params.gasprice?` | `number` | An optional new gas price to calculate provision for. Default is retrieved from Kandel parameters. | +| `params.distribution?` | [`KandelDistribution`](KandelDistribution.md) | The distribution to calculate the provision for. Optional. | +| `params.offerCount?` | `number` | The number of offers to calculate the provision for. Optional. | +| `existingOffers` | { `gasprice`: `number` ; `gasreq`: `number` ; `gasbase`: `number` }[] | - | + +#### Returns + +`Promise`<`Big`\> + +the additional required provision, in ethers. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:766 + +___ + +### populate + +▸ **populate**(`params`, `overrides?`): `Promise`<`ContractTransaction`[]\> + +Populates the offers in the distribution for the Kandel instance and sets parameters. + +**`See`** + +getRequiredProvision. + +**`Remarks`** + +If this function is invoked with new ratio, pricePoints, or spread, then first retract all offers; otherwise, Kandel will enter an inconsistent state. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters for populating the offers. | +| `params.distribution?` | [`KandelDistribution`](KandelDistribution.md) | The distribution of offers to populate. | +| `params.parameters?` | `KandelParameterOverrides` | The parameters to set leave out values to keep their current value. | +| `params.depositBaseAmount?` | `BigSource` | The amount of base to deposit. If not provided, then no base is deposited. | +| `params.depositQuoteAmount?` | `BigSource` | The amount of quote to deposit. If not provided, then no quote is deposited. | +| `params.funds?` | `BigSource` | The amount of funds to provision. If not provided, then the required funds are provisioned according to | +| `params.maxOffersInChunk?` | `number` | The maximum number of offers to include in a single populate transaction. If not provided, then KandelConfiguration is used. | +| `overrides` | `Overrides` | The ethers overrides to use when calling the populate and populateChunk functions. | + +#### Returns + +`Promise`<`ContractTransaction`[]\> + +The transaction(s) used to populate the offers. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:802 + +___ + +### populateChunk + +▸ **populateChunk**(`params`, `overrides?`): `Promise`<`ContractTransaction`[]\> + +Populates the offers in the distribution for the Kandel instance. To set parameters or add funds, use populate. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters for populating the offers. | +| `params.distribution` | [`KandelDistribution`](KandelDistribution.md) | The distribution of offers to populate. | +| `params.maxOffersInChunk?` | `number` | The maximum number of offers to include in a single populate transaction. If not provided, then KandelConfiguration is used. | +| `overrides` | `Overrides` | The ethers overrides to use when calling the populateChunk function. | + +#### Returns + +`Promise`<`ContractTransaction`[]\> + +The transaction(s) used to populate the offers. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:878 + +___ + +### populateChunks + +▸ **populateChunks**(`firstAskIndex`, `rawDistributions`, `overrides?`): `Promise`<`ContractTransaction`[]\> + +Populates the offers in the distribution for the Kandel instance. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `firstAskIndex` | `number` | The index of the first ask in the distribution. | +| `rawDistributions` | { `pivots`: `number`[] ; `rawDistribution`: `DistributionStruct` }[] | The raw chunked distributions in internal representation to populate. | +| `overrides` | `Overrides` | The ethers overrides to use when calling the populateChunk function. | + +#### Returns + +`Promise`<`ContractTransaction`[]\> + +The transaction(s) used to populate the offers. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:898 + +___ + +### retractAndWithdraw + +▸ **retractAndWithdraw**(`params?`, `overrides?`): `Promise`<`ContractTransaction`[]\> + +Retracts offers and withdraws tokens and provision + +**`Remarks`** + +This function or retractOffers should be used to retract all offers before changing the ratio, pricePoints, or spread using populate. +If offers are retracted over multiple transactions, then the chunks are retracted in opposite order from the populate function. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters. | +| `params.startIndex?` | `number` | The start Kandel index of offers to retract. If not provided, then 0 is used. | +| `params.endIndex?` | `number` | The end index of offers to retract. This is exclusive of the offer the index 'endIndex'. If not provided, then the number of price points is used. | +| `params.withdrawFunds?` | `BigSource` | The amount of funds to withdraw in ethers. If not provided, then the entire provision on Mangrove is withdrawn. | +| `params.withdrawBaseAmount?` | `BigSource` | The amount of base to withdraw. If not provided, then the entire base balance on Kandel is withdrawn. | +| `params.withdrawQuoteAmount?` | `BigSource` | The amount of quote to withdraw. If not provided, then the entire quote balance on Kandel is withdrawn. | +| `params.recipientAddress?` | `string` | The address to withdraw the tokens to. If not provided, then the address of the signer is used. | +| `params.maxOffersInChunk?` | `number` | The maximum number of offers to include in a single retract transaction. If not provided, then KandelConfiguration is used. | +| `params.firstAskIndex?` | `number` | The index of the first ask in the distribution. It is used to determine the order in which to retract offers if multiple chunks are needed; if not provided, the midpoint between start and end is used. | +| `overrides` | `Overrides` | The ethers overrides to use when calling the retractAndWithdraw, and retractOffers functions. | + +#### Returns + +`Promise`<`ContractTransaction`[]\> + +The transaction(s) used to retract the offers. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:953 + +___ + +### retractOffers + +▸ **retractOffers**(`params?`, `overrides?`): `Promise`<`ContractTransaction`[]\> + +Retracts offers + +**`Remarks`** + +This function or retractAndWithdraw should be used to retract all offers before changing the ratio, pricePoints, or spread using populate. +If offers are retracted over multiple transactions, then the chunks are retracted in opposite order from the populate function. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters. | +| `params.startIndex?` | `number` | The start Kandel index of offers to retract. If not provided, then 0 is used. | +| `params.endIndex?` | `number` | The end index of offers to retract. This is exclusive of the offer the index 'endIndex'. If not provided, then the number of price points is used. | +| `params.maxOffersInChunk?` | `number` | The maximum number of offers to include in a single retract transaction. If not provided, then KandelConfiguration is used. | +| `params.firstAskIndex?` | `number` | The index of the first ask in the distribution. It is used to determine the order in which to retract offers if multiple chunks are needed; if not provided, the midpoint between start and end is used. | +| `overrides` | `Overrides` | The ethers overrides to use when calling the retractOffers function. | + +#### Returns + +`Promise`<`ContractTransaction`[]\> + +The transaction(s) used to retract the offers. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:1008 + +___ + +### retractOfferChunks + +▸ **retractOfferChunks**(`params`, `overrides`): `Promise`<{ `txs`: `ContractTransaction`[] ; `lastChunk`: { `from`: `number` ; `to`: `number` } }\> + +Retracts offers + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters. | +| `params.retractParams` | `Object` | The parameters for retracting offers. | +| `params.retractParams.startIndex?` | `number` | - | +| `params.retractParams.endIndex?` | `number` | - | +| `params.retractParams.maxOffersInChunk?` | `number` | - | +| `params.retractParams.firstAskIndex?` | `number` | - | +| `params.skipLast` | `boolean` | Whether to skip the last chunk. This is used to allow the last chunk to be retracted while withdrawing funds. | +| `overrides` | `Overrides` | The ethers overrides to use when calling the retractOffers function. | + +#### Returns + +`Promise`<{ `txs`: `ContractTransaction`[] ; `lastChunk`: { `from`: `number` ; `to`: `number` } }\> + +The transaction(s) used to retract the offers. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:1036 + +___ + +### withdraw + +▸ **withdraw**(`params?`, `overrides?`): `Promise`<`ContractTransaction`\> + +Withdraws tokens from the Kandel instance. + +**`Remarks`** + +it is up to the caller to make sure there are still enough funds for live offers. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters. | +| `params.baseAmount?` | `BigSource` | The amount of base to withdraw. If not provided, then the entire base balance on Kandel is withdrawn. | +| `params.quoteAmount?` | `BigSource` | The amount of quote to withdraw. If not provided, then the entire quote balance on Kandel is withdrawn. | +| `params.recipientAddress?` | `string` | The address to withdraw the tokens to. If not provided, then the address of the signer is used. | +| `overrides` | `Overrides` | The ethers overrides to use when calling the retractAndWithdraw, and retractOffers functions. | + +#### Returns + +`Promise`<`ContractTransaction`\> + +The transaction used to withdraw the offers. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:1090 + +___ + +### setGasprice + +▸ **setGasprice**(`gasprice`, `overrides?`): `Promise`<`ContractTransaction`\> + +Sets the gas price used when provisioning offers. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `gasprice` | `number` | The gas price to set. | +| `overrides` | `Overrides` | The ethers overrides to use when calling the setGasprice function. | + +#### Returns + +`Promise`<`ContractTransaction`\> + +The transaction used to set the gas price. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:1117 + +___ + +### setGasreq + +▸ **setGasreq**(`gasreq`, `overrides?`): `Promise`<`ContractTransaction`\> + +Sets the gas required to execute a trade. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `gasreq` | `number` | The gas requirement to set. | +| `overrides` | `Overrides` | The ethers overrides to use when calling the setGasreq function. | + +#### Returns + +`Promise`<`ContractTransaction`\> + +The transaction used to set the gas requirement. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:1126 diff --git a/docs/developers/SDK/technical-references/code/classes/KandelSeeder.md b/docs/developers/SDK/technical-references/code/classes/KandelSeeder.md new file mode 100644 index 00000000..b2963274 --- /dev/null +++ b/docs/developers/SDK/technical-references/code/classes/KandelSeeder.md @@ -0,0 +1,260 @@ +--- +id: "KandelSeeder" +title: "Class: KandelSeeder" +sidebar_label: "KandelSeeder" +sidebar_position: 0 +custom_edit_url: null +--- + +Seeder for creating Kandel instances on-chain. + +## Properties + +### mgv + +• **mgv**: [`Mangrove`](Mangrove.md) + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelSeeder.ts:35 + +___ + +### configuration + +• **configuration**: `KandelConfiguration` + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelSeeder.ts:36 + +___ + +### tradeEventManagement + +• **tradeEventManagement**: `TradeEventManagement` + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelSeeder.ts:37 + +___ + +### aaveKandelSeeder + +• **aaveKandelSeeder**: `AaveKandelSeeder` + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelSeeder.ts:39 + +___ + +### kandelSeeder + +• **kandelSeeder**: `KandelSeeder` + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelSeeder.ts:40 + +## Constructors + +### constructor + +• **new KandelSeeder**(`mgv`) + +Constructor + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `mgv` | [`Mangrove`](Mangrove.md) | The Mangrove to deploy to. | + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelSeeder.ts:45 + +## Methods + +### sow + +▸ **sow**(`seed`, `overrides?`): `Promise`<{ `response`: `Promise`<`ContractTransaction`\> ; `kandelPromise`: `Promise`<[`KandelInstance`](KandelInstance.md)\> }\> + +Create a new Kandel instance. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `seed` | `KandelSeed` | The parameters for sowing the Kandel instance. | +| `overrides` | `Overrides` | - | + +#### Returns + +`Promise`<{ `response`: `Promise`<`ContractTransaction`\> ; `kandelPromise`: `Promise`<[`KandelInstance`](KandelInstance.md)\> }\> + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelSeeder.ts:70 + +___ + +### getKandelFromReceipt + +▸ **getKandelFromReceipt**(`params`): `Promise`<[`KandelInstance`](KandelInstance.md)\> + +Gets the Kandel instance created in a transaction via sow. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters. | +| `params.receipt` | `ContractReceipt` | The receipt of the transaction. | +| `params.onAave` | `boolean` | Whether the Kandel is an AaveKandel. | +| `params.market` | [`Market`](Market.md) | The market the Kandel is for. | + +#### Returns + +`Promise`<[`KandelInstance`](KandelInstance.md)\> + +The Kandel instance created in the transaction. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelSeeder.ts:110 + +___ + +### getDefaultGasreq + +▸ **getDefaultGasreq**(`onAave`): `Promise`<`number`\> + +Retrieves the default gasreq for the Kandel type. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `onAave` | `boolean` | Whether to get the gasreq for an AaveKandel or a standard Kandel. | + +#### Returns + +`Promise`<`number`\> + +The gasreq for the Kandel type. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelSeeder.ts:150 + +___ + +### getBufferedGasprice + +▸ **getBufferedGasprice**(`seed`): `Promise`<`number`\> + +Retrieves the gasprice for the Kandel type multiplied by the buffer factor. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `seed` | `KandelSeed` | The parameters for sowing the Kandel instance. | + +#### Returns + +`Promise`<`number`\> + +The gasprice for the Kandel type multiplied by the buffer factor. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelSeeder.ts:167 + +___ + +### getRequiredProvision + +▸ **getRequiredProvision**(`seed`, `distribution`): `Promise`<`Big`\> + +Determines the required provision for the distribution prior to sowing based on the number of price points. + +**`Remarks`** + +This takes into account that each price point can become both an ask and a bid which both require provision. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `seed` | `KandelSeed` | The parameters for sowing the Kandel instance. | +| `distribution` | [`KandelDistribution`](KandelDistribution.md) | The distribution to determine the provision for. | + +#### Returns + +`Promise`<`Big`\> + +The provision required for the distribution. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelSeeder.ts:180 + +___ + +### getMinimumVolume + +▸ **getMinimumVolume**(`params`): `Promise`<`Big`\> + +Determines the minimum recommended volume for an offer of the given type to avoid density issues. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters. | +| `params.market` | [`Market`](Market.md) | The market the Kandel is deployed to. | +| `params.offerType` | [`BA`](../namespaces/Market-1.md#ba) | The type of offer. | +| `params.onAave` | `boolean` | Whether the Kandel is an AaveKandel. | +| `params.factor?` | `number` | The factor to multiply the minimum volume by. Defaults to minimumBasePerOfferFactory / minimumQuotePerOfferFactor from KandelConfiguration. | + +#### Returns + +`Promise`<`Big`\> + +The minimum recommended volume. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelSeeder.ts:202 + +___ + +### getMinimumVolumeForGasreq + +▸ **getMinimumVolumeForGasreq**(`params`): `Promise`<`Big`\> + +Determines the minimum recommended volume for an offer of the given type to avoid density issues. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters. | +| `params.market` | [`Market`](Market.md) | The market the Kandel is deployed to. | +| `params.offerType` | [`BA`](../namespaces/Market-1.md#ba) | The type of offer. | +| `params.factor?` | `number` | The factor to multiply the minimum volume by. Defaults to minimumBasePerOfferFactory / minimumQuotePerOfferFactor from KandelConfiguration. | +| `params.gasreq` | `number` | The gasreq to use. | + +#### Returns + +`Promise`<`Big`\> + +The minimum recommended volume. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandel/kandelSeeder.ts:220 diff --git a/docs/developers/SDK/technical-references/code/classes/KandelStrategies.md b/docs/developers/SDK/technical-references/code/classes/KandelStrategies.md new file mode 100644 index 00000000..af1603b5 --- /dev/null +++ b/docs/developers/SDK/technical-references/code/classes/KandelStrategies.md @@ -0,0 +1,130 @@ +--- +id: "KandelStrategies" +title: "Class: KandelStrategies" +sidebar_label: "KandelStrategies" +sidebar_position: 0 +custom_edit_url: null +--- + +Entrypoint for the Kandel strategies. Kandel is an Automated Market Making strategy that uses on-chain order flow to repost offers instantly, without any latency. Within a market and price range you select, Kandel automatically posts bids and asks. Its main goal is to buy low and sell high - profits are made through accumulated spread. + +## Properties + +### seeder + +• **seeder**: [`KandelSeeder`](KandelSeeder.md) + +Seeder for creating Kandel instances on-chain. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandelStrategies.ts:17 + +___ + +### farm + +• **farm**: [`KandelFarm`](KandelFarm.md) + +Repository for Kandel instances. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandelStrategies.ts:20 + +___ + +### mgv + +• **mgv**: [`Mangrove`](Mangrove.md) + +The Mangrove to interact with. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandelStrategies.ts:23 + +___ + +### configuration + +• **configuration**: `KandelConfiguration` + +The default configuration values to use for Kandel. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandelStrategies.ts:26 + +## Constructors + +### constructor + +• **new KandelStrategies**(`mgv`) + +Constructor + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `mgv` | [`Mangrove`](Mangrove.md) | The Mangrove to interact with. | + +#### Defined in + +@mangrovedao/mangrove.js/src/kandelStrategies.ts:31 + +## Methods + +### instance + +▸ **instance**(`params`): `Promise`<[`KandelInstance`](KandelInstance.md)\> + +Creates a KandelInstance object to interact with a Kandel strategy on Mangrove. + +**`Dev`** + +If a factory function is provided for the market, then remember to disconnect market when no longer needed. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `params` | `Object` | The parameters for creating the KandelInstance. | +| `params.address` | `string` | The address of the Kandel strategy. | +| `params.market` | [`Market`](Market.md) \| (`baseAddress`: `string`, `quoteAddress`: `string`) => `Promise`<[`Market`](Market.md)\> | The market used by the Kandel instance or a factory function to create the market. | + +#### Returns + +`Promise`<[`KandelInstance`](KandelInstance.md)\> + +A new KandelInstance. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandelStrategies.ts:45 + +___ + +### generator + +▸ **generator**(`market`, `precision?`): [`KandelDistributionGenerator`](KandelDistributionGenerator.md) + +Creates a generator for generating Kandel distributions for the given market. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `market` | [`Market`](Market.md) | The market to calculate for. | +| `precision?` | `number` | The precision used for Kandel instances. Must match the deployed Kandel contract's PRECISION() value. | + +#### Returns + +[`KandelDistributionGenerator`](KandelDistributionGenerator.md) + +A new KandelDistributionGenerator. + +#### Defined in + +@mangrovedao/mangrove.js/src/kandelStrategies.ts:80 diff --git a/docs/developers/SDK/technical-references/code/classes/LiquidityProvider.md b/docs/developers/SDK/technical-references/code/classes/LiquidityProvider.md new file mode 100644 index 00000000..ccf4ced9 --- /dev/null +++ b/docs/developers/SDK/technical-references/code/classes/LiquidityProvider.md @@ -0,0 +1,587 @@ +--- +id: "LiquidityProvider" +title: "Class: LiquidityProvider" +sidebar_label: "LiquidityProvider" +sidebar_position: 0 +custom_edit_url: null +--- + +The LiquidityProvider class connects an offerLogic (or an EOA) to a market. +It posts onchain offers. + +## Properties + +### mgv + +• **mgv**: [`Mangrove`](Mangrove.md) + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:57 + +___ + +### logic + +• `Optional` **logic**: [`OfferLogic`](OfferLogic.md) + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:58 + +___ + +### contract + +• `Optional` **contract**: `ILiquidityProvider` + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:59 + +___ + +### eoa + +• `Optional` **eoa**: `string` + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:60 + +___ + +### market + +• **market**: [`Market`](Market.md) + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:61 + +___ + +### prettyP + +• **prettyP**: `PrettyPrint` + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:62 + +___ + +### gasreq + +• **gasreq**: `number` + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:63 + +## Constructors + +### constructor + +• **new LiquidityProvider**(`p`) + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `p` | [`ConstructionParams`](../namespaces/LiquidityProvider-1.md#constructionparams) | + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:65 + +## Methods + +### connect + +▸ `Static` **connect**(`offerLogic`, `p`): `Promise`<[`LiquidityProvider`](LiquidityProvider.md)\> + +Connects the logic to a Market in order to pass market orders. This assumes the underlying contract of offer logic is an ILiquidityProvider. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `offerLogic` | [`OfferLogic`](OfferLogic.md) | The offer logic. | +| `p` | [`Market`](Market.md) \| { `base`: `string` ; `quote`: `string` ; `bookOptions?`: [`BookOptions`](../namespaces/Market-1.md#bookoptions) } | The market to connect to. Can be a Market object or a market descriptor. | + +#### Returns + +`Promise`<[`LiquidityProvider`](LiquidityProvider.md)\> + +A LiquidityProvider. + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:90 + +___ + +### computeOfferProvision + +▸ **computeOfferProvision**(`ba`, `opts?`): `Promise`<`Big`\> + +Gets the missing provision in ethers for an offer to be posted or updated with the given parameters, while taking already locked provision into account. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `ba` | [`BA`](../namespaces/Market-1.md#ba) | bids or asks | +| `opts` | `Object` | optional parameters for the calculation. | +| `opts.id?` | `number` | the id of the offer to update. If undefined, then the offer is a new offer and nothing is locked. | +| `opts.gasreq?` | `number` | gas required for the offer execution. If undefined, the liquidity provider's gasreq. | +| `opts.gasprice?` | `number` | gas price to use for the calculation. If undefined, then Mangrove's current gas price is used. | + +#### Returns + +`Promise`<`Big`\> + +the additional required provision, in ethers. + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:125 + +___ + +### computeBidProvision + +▸ **computeBidProvision**(`opts?`): `Promise`<`Big`\> + +Gets the missing provision in ethers for a bid using + +**`See`** + +computeOfferProvision. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `opts` | `Object` | +| `opts.id?` | `number` | +| `opts.gasreq?` | `number` | +| `opts.gasprice?` | `number` | + +#### Returns + +`Promise`<`Big`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:156 + +___ + +### computeAskProvision + +▸ **computeAskProvision**(`opts?`): `Promise`<`Big`\> + +Gets the missing provision in ethers for an ask using + +**`See`** + +computeOfferProvision. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `opts` | `Object` | +| `opts.id?` | `number` | +| `opts.gasreq?` | `number` | +| `opts.gasprice?` | `number` | + +#### Returns + +`Promise`<`Big`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:163 + +___ + +### getBidPivotId + +▸ **getBidPivotId**(`price`): `Promise`<`undefined` \| `number`\> + +Given a price, find the id of the immediately-better offer in the +semibook. If there is no offer with a better price, `undefined` is returned. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `price` | `BigSource` | + +#### Returns + +`Promise`<`undefined` \| `number`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:172 + +___ + +### getAskPivotId + +▸ **getAskPivotId**(`price`): `Promise`<`undefined` \| `number`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `price` | `BigSource` | + +#### Returns + +`Promise`<`undefined` \| `number`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:177 + +___ + +### asks + +▸ **asks**(): [`Offer`](../namespaces/Market-1.md#offer)[] + +List all of the maker's asks in the cache + +#### Returns + +[`Offer`](../namespaces/Market-1.md#offer)[] + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:183 + +___ + +### bids + +▸ **bids**(): [`Offer`](../namespaces/Market-1.md#offer)[] + +List all of the maker's bids in the cache + +#### Returns + +[`Offer`](../namespaces/Market-1.md#offer)[] + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:193 + +___ + +### consoleAsks + +▸ **consoleAsks**(`filter?`): `void` + +Pretty prints the current state of the asks for the maker + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `filter?` | `prettyPrintFilter` | + +#### Returns + +`void` + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:203 + +___ + +### consoleBids + +▸ **consoleBids**(`filter?`): `void` + +Pretty prints the current state of the bids for the maker + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `filter?` | `prettyPrintFilter` | + +#### Returns + +`void` + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:208 + +___ + +### normalizeOfferParams + +▸ `Static` **normalizeOfferParams**(`p`): `Object` + +Given offer params (bids/asks + price info as wants&gives or price&volume), + return `{price,wants,gives}` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `p` | `Object` | + +#### Returns + +`Object` + +| Name | Type | +| :------ | :------ | +| `price` | `Big` | +| `wants` | `Big` | +| `gives` | `Big` | +| `gasreq?` | `number` | +| `gasprice?` | `number` | +| `fund?` | `BigSource` | + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:216 + +___ + +### optValueToPayableOverride + +▸ `Static` **optValueToPayableOverride**(`overrides`, `fund?`): `PayableOverrides` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `overrides` | `Overrides` | +| `fund?` | `BigSource` | + +#### Returns + +`PayableOverrides` + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:247 + +___ + +### newAsk + +▸ **newAsk**(`p`, `overrides?`): `Promise`<{ `id`: `number` ; `event`: `Log` }\> + +Post a new ask + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `p` | [`OfferParams`](../namespaces/LiquidityProvider-1.md#offerparams) | +| `overrides` | `Overrides` | + +#### Returns + +`Promise`<{ `id`: `number` ; `event`: `Log` }\> + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:259 + +___ + +### newBid + +▸ **newBid**(`p`, `overrides?`): `Promise`<{ `id`: `number` ; `event`: `Log` }\> + +Post a new bid + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `p` | [`OfferParams`](../namespaces/LiquidityProvider-1.md#offerparams) | +| `overrides` | `Overrides` | + +#### Returns + +`Promise`<{ `id`: `number` ; `event`: `Log` }\> + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:267 + +___ + +### newOffer + +▸ **newOffer**(`p`, `overrides?`): `Promise`<{ `id`: `number` ; `pivot`: `number` ; `event`: `Log` }\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `p` | `Object` | +| `overrides` | `Overrides` | + +#### Returns + +`Promise`<{ `id`: `number` ; `pivot`: `number` ; `event`: `Log` }\> + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:288 + +___ + +### updateAsk + +▸ **updateAsk**(`id`, `p`, `overrides?`): `Promise`<{ `event`: `Log` }\> + +to change volume and price of the offer, and update its gas requirement and fund 0.01 ether to maker balance + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `id` | `number` | +| `p` | [`OfferParams`](../namespaces/LiquidityProvider-1.md#offerparams) | +| `overrides` | `PayableOverrides` | + +#### Returns + +`Promise`<{ `event`: `Log` }\> + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:377 + +___ + +### updateBid + +▸ **updateBid**(`id`, `p`, `overrides?`): `Promise`<{ `event`: `Log` }\> + +Update an existing offer + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `id` | `number` | +| `p` | [`OfferParams`](../namespaces/LiquidityProvider-1.md#offerparams) | +| `overrides` | `PayableOverrides` | + +#### Returns + +`Promise`<{ `event`: `Log` }\> + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:386 + +___ + +### updateOffer + +▸ **updateOffer**(`id`, `p`, `overrides?`): `Promise`<{ `event`: `Log` }\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `id` | `number` | +| `p` | `Object` | +| `overrides` | `PayableOverrides` | + +#### Returns + +`Promise`<{ `event`: `Log` }\> + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:398 + +___ + +### retractAsk + +▸ **retractAsk**(`id`, `deprovision?`, `overrides?`): `Promise`<`void`\> + +Cancel an ask. If deprovision is true, will return the offer's provision to the maker balance at Mangrove. + +#### Parameters + +| Name | Type | Default value | +| :------ | :------ | :------ | +| `id` | `number` | `undefined` | +| `deprovision` | `boolean` | `false` | +| `overrides` | `Overrides` | `{}` | + +#### Returns + +`Promise`<`void`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:468 + +___ + +### retractBid + +▸ **retractBid**(`id`, `deprovision?`, `overrides?`): `Promise`<`void`\> + +Cancel a bid. If deprovision is true, will return the offer's provision to the maker balance at Mangrove. + +#### Parameters + +| Name | Type | Default value | +| :------ | :------ | :------ | +| `id` | `number` | `undefined` | +| `deprovision` | `boolean` | `false` | +| `overrides` | `Overrides` | `{}` | + +#### Returns + +`Promise`<`void`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:477 + +___ + +### retractOffer + +▸ **retractOffer**(`ba`, `id`, `deprovision?`, `overrides?`): `Promise`<`void`\> + +#### Parameters + +| Name | Type | Default value | +| :------ | :------ | :------ | +| `ba` | [`BA`](../namespaces/Market-1.md#ba) | `undefined` | +| `id` | `number` | `undefined` | +| `deprovision` | `boolean` | `false` | +| `overrides` | `Overrides` | `{}` | + +#### Returns + +`Promise`<`void`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:486 diff --git a/docs/developers/SDK/technical-references/code/classes/Mangrove.md b/docs/developers/SDK/technical-references/code/classes/Mangrove.md new file mode 100644 index 00000000..8267df46 --- /dev/null +++ b/docs/developers/SDK/technical-references/code/classes/Mangrove.md @@ -0,0 +1,1292 @@ +--- +id: "Mangrove" +title: "Class: Mangrove" +sidebar_label: "Mangrove" +sidebar_position: 0 +custom_edit_url: null +--- + +## Properties + +### provider + +• **provider**: `Provider` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:104 + +___ + +### signer + +• **signer**: `Signer` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:105 + +___ + +### network + +• **network**: [`ProviderNetwork`](../interfaces/eth.ProviderNetwork.md) + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:106 + +___ + +### \_readOnly + +• **\_readOnly**: `boolean` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:107 + +___ + +### address + +• **address**: `string` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:108 + +___ + +### contract + +• **contract**: `Mangrove` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:109 + +___ + +### readerContract + +• **readerContract**: `MgvReader` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:110 + +___ + +### cleanerContract + +• **cleanerContract**: `MgvCleaner` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:111 + +___ + +### multicallContract + +• **multicallContract**: `Multicall2` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:112 + +___ + +### orderContract + +• **orderContract**: `MangroveOrder` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:113 + +___ + +### reliableProvider + +• **reliableProvider**: `ReliableProvider` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:114 + +___ + +### mangroveEventSubscriber + +• **mangroveEventSubscriber**: `MangroveEventSubscriber` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:115 + +___ + +### eventEmitter + +• **eventEmitter**: `EventEmitter` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:117 + +___ + +### devNode + +▪ `Static` **devNode**: `DevNode` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:119 + +___ + +### typechain + +▪ `Static` **typechain**: `__module` = `typechain` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:120 + +## Methods + +### connect + +▸ `Static` **connect**(`options?`): `Promise`<[`Mangrove`](Mangrove.md)\> + +Creates an instance of the Mangrove Typescript object + +**`Example`** + +``` +const mgv = await require('mangrove.js').connect(options); // web browser +``` + +if options is a string `s`, it is considered to be `{provider:s}` +const mgv = await require('mangrove.js').connect('http://127.0.0.1:8545'); // HTTP provider + +Options: +* privateKey: `0x...` +* mnemonic: `horse battery ...` +* path: `m/44'/60'/0'/...` +* provider: url, provider object, or chain string + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `options?` | `string` \| [`CreateOptions`](../namespaces/Mangrove-1.md#createoptions) | Optional provider options. | + +#### Returns + +`Promise`<[`Mangrove`](Mangrove.md)\> + +Returns an instance mangrove.js + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:143 + +___ + +### disconnect + +▸ **disconnect**(): `void` + +#### Returns + +`void` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:230 + +___ + +### updateConfiguration + +▸ **updateConfiguration**(`config?`): `void` + +Update the configuration by providing a partial configuration containing only the values that should be changed/added. + +**`Example`** + +``` +updateConfiguration({ + tokens: { + SYM: { + decimals: 18 + } + } +}) +``` +This adds configuration for a new token with symbol "SYM". Or, if "SYM" was already configured, ensures that its `decimals` is set to 18. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `config?` | `RecursivePartial`<`Configuration`\> | Partial configuration that should be merged into the existing configuration. | + +#### Returns + +`void` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:343 + +___ + +### resetConfiguration + +▸ **resetConfiguration**(): `void` + +Reset the configuration to defaults provided by mangrove.js + +#### Returns + +`void` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:348 + +___ + +### market + +▸ **market**(`params`): `Promise`<[`Market`](Market.md)\> + +************ + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `params` | `Object` | +| `params.base` | `string` | +| `params.quote` | `string` | +| `params.bookOptions?` | [`BookOptions`](../namespaces/Market-1.md#bookoptions) | + +#### Returns + +`Promise`<[`Market`](Market.md)\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:379 + +___ + +### offerLogic + +▸ **offerLogic**(`logic`): [`OfferLogic`](OfferLogic.md) + +Get an OfferLogic object allowing one to monitor and set up an onchain offer logic + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `logic` | `string` | + +#### Returns + +[`OfferLogic`](OfferLogic.md) + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:399 + +___ + +### liquidityProvider + +▸ **liquidityProvider**(`p`): `Promise`<[`LiquidityProvider`](LiquidityProvider.md)\> + +Get a LiquidityProvider object to enable Mangrove's signer to pass buy and sell orders + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `p` | [`Market`](Market.md) \| { `base`: `string` ; `quote`: `string` ; `bookOptions?`: [`BookOptions`](../namespaces/Market-1.md#bookoptions) } | + +#### Returns + +`Promise`<[`LiquidityProvider`](LiquidityProvider.md)\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:414 + +___ + +### token + +▸ **token**(`name`, `options?`): `Promise`<[`MgvToken`](MgvToken.md)\> + +Return MgvToken instance, fetching data (decimals) from chain if needed. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `name` | `string` | +| `options?` | [`ConstructorOptions`](../namespaces/MgvToken-1.md#constructoroptions) | + +#### Returns + +`Promise`<[`MgvToken`](MgvToken.md)\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:442 + +___ + +### tokenFromConfig + +▸ **tokenFromConfig**(`name`, `options?`): [`MgvToken`](MgvToken.md) + +Return MgvToken instance reading only from configuration, not from chain. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `name` | `string` | +| `options?` | [`ConstructorOptions`](../namespaces/MgvToken-1.md#constructoroptions) | + +#### Returns + +[`MgvToken`](MgvToken.md) + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:450 + +___ + +### getAddress + +▸ **getAddress**(`name`): `string` + +Read a contract address on the current network. + +Note that this reads from the static `Mangrove` address registry which is shared across instances of this class. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `name` | `string` | + +#### Returns + +`string` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:462 + +___ + +### setAddress + +▸ **setAddress**(`name`, `address`): `void` + +Set a contract address on the current network. + +Note that this writes to the static `Mangrove` address registry which is shared across instances of this class. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `name` | `string` | +| `address` | `string` | + +#### Returns + +`void` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:474 + +___ + +### getNameFromAddress + +▸ **getNameFromAddress**(`address`): `undefined` \| `string` + +Gets the name of an address on the current network. + +Note that this reads from the static `Mangrove` address registry which is shared across instances of this class. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `address` | `string` | + +#### Returns + +`undefined` \| `string` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:487 + +___ + +### getTokenAndAddress + +▸ **getTokenAndAddress**(`address`): `Promise`<{ `address`: `string` ; `token?`: [`MgvToken`](MgvToken.md) }\> + +Gets the token corresponding to the address if it is known; otherwise, undefined. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `address` | `string` | + +#### Returns + +`Promise`<{ `address`: `string` ; `token?`: [`MgvToken`](MgvToken.md) }\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:496 + +___ + +### toUnits + +▸ `Static` **toUnits**(`amount`, `nameOrDecimals`): `BigNumber` + +Convert public token amount to internal token representation. + +if `nameOrDecimals` is a string, it is interpreted as a token name. Otherwise +it is the number of decimals. + +For convenience, has a static and an instance version. + +**`Example`** + +``` + Mangrove.toUnits(10,"USDC") // 10e6 as ethers.BigNumber + mgv.toUnits(10,6) // 10e6 as ethers.BigNumber + ``` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `amount` | `BigSource` | +| `nameOrDecimals` | `string` \| `number` | + +#### Returns + +`BigNumber` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:519 + +___ + +### toUnits + +▸ **toUnits**(`amount`, `nameOrDecimals`): `BigNumber` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `amount` | `BigSource` | +| `nameOrDecimals` | `string` \| `number` | + +#### Returns + +`BigNumber` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:525 + +___ + +### fromUnits + +▸ **fromUnits**(`amount`, `nameOrDecimals`): `Big` + +Convert internal token amount to public token representation. + +if `nameOrDecimals` is a string, it is interpreted as a token name. Otherwise +it is the number of decimals. + +**`Example`** + +``` + mgv.fromUnits("1e19","DAI") // 10 + mgv.fromUnits("1e19",18) // 10 + ``` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `amount` | `string` \| `number` \| `BigNumber` | +| `nameOrDecimals` | `string` \| `number` | + +#### Returns + +`Big` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:540 + +___ + +### balanceOf + +▸ **balanceOf**(`address`, `overrides?`): `Promise`<`Big`\> + +Provision available at mangrove for address given in argument, in ethers + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `address` | `string` | +| `overrides` | `Overrides` | + +#### Returns + +`Promise`<`Big`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:548 + +___ + +### fundMangrove + +▸ **fundMangrove**(`amount`, `maker`, `overrides?`): `Promise`<`ContractTransaction`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `amount` | `BigSource` | +| `maker` | `string` | +| `overrides` | `Overrides` | + +#### Returns + +`Promise`<`ContractTransaction`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:556 + +___ + +### withdraw + +▸ **withdraw**(`amount`, `overrides?`): `Promise`<`ContractTransaction`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `amount` | `BigSource` | +| `overrides` | `Overrides` | + +#### Returns + +`Promise`<`ContractTransaction`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:565 + +___ + +### approveMangrove + +▸ **approveMangrove**(`tokenName`, `arg?`): `Promise`<`ContractTransaction`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `tokenName` | `string` | +| `arg` | `ApproveArgs` | + +#### Returns + +`Promise`<`ContractTransaction`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:572 + +___ + +### calculateOfferProvision + +▸ **calculateOfferProvision**(`gasprice`, `gasreq`, `gasbase`): `Big` + +Calculates the provision required or locked for an offer based on the given parameters + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `gasprice` | `number` | the gas price for the offer in gwei. | +| `gasreq` | `number` | the gas requirement for the offer | +| `gasbase` | `number` | the offer list's offer_gasbase. | + +#### Returns + +`Big` + +the required provision, in ethers. + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:586 + +___ + +### calculateOffersProvision + +▸ **calculateOffersProvision**(`offers`): `Big` + +Calculates the provision required or locked for offers based on the given parameters + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `offers` | { `gasprice`: `number` ; `gasreq`: `number` ; `gasbase`: `number` }[] | + +#### Returns + +`Big` + +the required provision, in ethers. + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:602 + +___ + +### getMissingProvision + +▸ **getMissingProvision**(`lockedProvision`, `totalRequiredProvision`): `Big` + +Gets the missing provision based on the required provision and the locked provision. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `lockedProvision` | `BigSource` | the provision already locked for an offer. | +| `totalRequiredProvision` | `BigSource` | the provision required for an offer. | + +#### Returns + +`Big` + +the additional required provision, in ethers. + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:623 + +___ + +### config + +▸ **config**(): `Promise`<[`GlobalConfig`](../namespaces/Mangrove-1.md#globalconfig)\> + +Return global Mangrove config + +#### Returns + +`Promise`<[`GlobalConfig`](../namespaces/Mangrove-1.md#globalconfig)\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:636 + +___ + +### normalizePermitData + +▸ **normalizePermitData**(`params`): `Promise`<[`PermitData`](../namespaces/Mangrove-1.md#permitdata)\> + +Permit data normalization +Autofill/convert 'nonce' field of permit data if need, convert deadline to +num if needed. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `params` | [`SimplePermitData`](../namespaces/Mangrove-1.md#simplepermitdata) | + +#### Returns + +`Promise`<[`PermitData`](../namespaces/Mangrove-1.md#permitdata)\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:655 + +___ + +### simpleSignPermitData + +▸ **simpleSignPermitData**(`params`): `Promise`<`string`\> + +Sign typed data for permit(). +To set the deadline to +days or +months, you can do +let date = new Date(); +date.setDate(date.getDate() + days); +date.setMonth(date.getMonth() + months); +- Nonce is auto-selected if needed and can be a number +- Date can be a Date or a number + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `params` | [`SimplePermitData`](../namespaces/Mangrove-1.md#simplepermitdata) | + +#### Returns + +`Promise`<`string`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:686 + +___ + +### signPermitData + +▸ **signPermitData**(`data`): `Promise`<`string`\> + +Permit data generator for normalized permit data input + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `data` | [`PermitData`](../namespaces/Mangrove-1.md#permitdata) | + +#### Returns + +`Promise`<`string`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:692 + +___ + +### permit + +▸ **permit**(`params`): `Promise`<`ContractTransaction`\> + +Give permit to Mangrove. +Permit params.spender to buy on behalf of owner on the outbound/inbound +offer list up to value. Default deadline is now + 1 day. Default nonce is +current owner nonce. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `params` | [`SimplePermitData`](../namespaces/Mangrove-1.md#simplepermitdata) | + +#### Returns + +`Promise`<`ContractTransaction`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:728 + +___ + +### getAllAddresses + +▸ `Static` **getAllAddresses**(`network`): [`string`, `string`][] + +Read all contract addresses on the given network. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `network` | `string` | + +#### Returns + +[`string`, `string`][] + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:760 + +___ + +### getAddress + +▸ `Static` **getAddress**(`name`, `network`): `string` + +Read a contract address on a given network. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `name` | `string` | +| `network` | `string` | + +#### Returns + +`string` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:767 + +___ + +### setAddress + +▸ `Static` **setAddress**(`name`, `address`, `network`): `void` + +Set a contract address on the given network. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `name` | `string` | +| `address` | `string` | +| `network` | `string` | + +#### Returns + +`void` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:774 + +___ + +### getNameFromAddress + +▸ `Static` **getNameFromAddress**(`address`, `network`): `undefined` \| `string` + +Gets the name of an address on the given network. + +Note that this reads from the static `Mangrove` address registry which is shared across instances of this class. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `address` | `string` | +| `network` | `string` | + +#### Returns + +`undefined` \| `string` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:783 + +___ + +### getDecimals + +▸ `Static` **getDecimals**(`tokenName`): `undefined` \| `number` + +Read decimals for `tokenName` on given network. +To read decimals directly onchain, use `fetchDecimals`. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `tokenName` | `string` | + +#### Returns + +`undefined` \| `number` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:794 + +___ + +### getDecimalsOrFail + +▸ `Static` **getDecimalsOrFail**(`tokenName`): `number` + +Read decimals for `tokenName`. Fails if the decimals are not in the configuration. +To read decimals directly onchain, use `fetchDecimals`. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `tokenName` | `string` | + +#### Returns + +`number` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:802 + +___ + +### getOrFetchDecimals + +▸ `Static` **getOrFetchDecimals**(`tokenName`, `provider`): `Promise`<`number`\> + +Read decimals for `tokenName` on given network. +If not found in the local configuration, fetch them from the current network and save them + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `tokenName` | `string` | +| `provider` | `Provider` | + +#### Returns + +`Promise`<`number`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:810 + +___ + +### fetchDecimals + +▸ `Static` **fetchDecimals**(`tokenName`, `provider`): `Promise`<`number`\> + +Read chain for decimals of `tokenName` on current network and save them + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `tokenName` | `string` | +| `provider` | `Provider` | + +#### Returns + +`Promise`<`number`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:820 + +___ + +### getDisplayedDecimals + +▸ `Static` **getDisplayedDecimals**(`tokenName`): `number` + +Read displayed decimals for `tokenName`. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `tokenName` | `string` | + +#### Returns + +`number` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:830 + +___ + +### getDisplayedPriceDecimals + +▸ `Static` **getDisplayedPriceDecimals**(`tokenName`): `number` + +Read displayed decimals for `tokenName` when displayed as a price. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `tokenName` | `string` | + +#### Returns + +`number` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:837 + +___ + +### setDecimals + +▸ `Static` **setDecimals**(`tokenName`, `dec`): `void` + +Set decimals for `tokenName` on current network. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `tokenName` | `string` | +| `dec` | `number` | + +#### Returns + +`void` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:844 + +___ + +### setDisplayedDecimals + +▸ `Static` **setDisplayedDecimals**(`tokenName`, `dec`): `void` + +Set displayed decimals for `tokenName`. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `tokenName` | `string` | +| `dec` | `number` | + +#### Returns + +`void` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:851 + +___ + +### setDisplayedPriceDecimals + +▸ `Static` **setDisplayedPriceDecimals**(`tokenName`, `dec`): `void` + +Set displayed decimals for `tokenName` when displayed as a price. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `tokenName` | `string` | +| `dec` | `number` | + +#### Returns + +`void` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:858 + +___ + +### initAndListenToDevNode + +▸ `Static` **initAndListenToDevNode**(`devNode`): `Promise`<`void`\> + +Setup dev node necessary contracts if needed, register dev Multicall2 +address, listen to future additions (a script external to mangrove.js may +deploy contracts during execution). + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `devNode` | `DevNode` | + +#### Returns + +`Promise`<`void`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:867 + +___ + +### openMarketsData + +▸ **openMarketsData**(`params?`): `Promise`<[`OpenMarketInfo`](../namespaces/Mangrove-1.md#openmarketinfo)[]\> + +Returns open markets data according to mangrove reader. + +**`Note`** + +If an open market has a token with no/bad decimals/symbol function, this function will revert. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `params` | `Object` | +| `params.from?` | `number` | +| `params.maxLen?` | `number` \| `BigNumber` | +| `params.configs?` | `boolean` | +| `params.tokenInfos?` | `boolean` | + +#### Returns + +`Promise`<[`OpenMarketInfo`](../namespaces/Mangrove-1.md#openmarketinfo)[]\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:899 + +___ + +### openMarkets + +▸ **openMarkets**(`params?`): `Promise`<[`Market`](Market.md)[]\> + +Returns open markets according to mangrove reader. Will internally update Mangrove token information. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `params` | `Object` | +| `params.from?` | `number` | +| `params.maxLen?` | `number` | +| `params.noInit?` | `boolean` | +| `params.bookOptions?` | [`BookOptions`](../namespaces/Market-1.md#bookoptions) | + +#### Returns + +`Promise`<[`Market`](Market.md)[]\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:1025 + +___ + +### setCashness + +▸ **setCashness**(`name`, `cashness`): `void` + +Set the relative cashness of a token. This determines which token is base & which is quote in a [Market](Market.md). +Lower cashness is base, higher cashness is quote, tiebreaker is lexicographic ordering of name string (name is most likely the same as the symbol). + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `name` | `string` | +| `cashness` | `number` | + +#### Returns + +`void` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:1067 + +___ + +### toBaseQuoteByCashness + +▸ `Static` **toBaseQuoteByCashness**(`name0`, `name1`): `Object` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `name0` | `string` | +| `name1` | `string` | + +#### Returns + +`Object` + +| Name | Type | +| :------ | :------ | +| `baseName` | `string` | +| `quoteName` | `string` | + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:1075 + +## Constructors + +### constructor + +• **new Mangrove**(`params`) + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `params` | `Object` | +| `params.signer` | `Signer` | +| `params.network` | [`ProviderNetwork`](../interfaces/eth.ProviderNetwork.md) | +| `params.readOnly` | `boolean` | +| `params.blockManagerOptions` | `Options` | +| `params.reliableHttpProvider` | `Options` | +| `params.eventEmitter` | `EventEmitter` | +| `params.reliableWebSocketOptions?` | `Object` | +| `params.reliableWebSocketOptions.options` | `Options` | +| `params.reliableWebSocketOptions.wsUrl` | `string` | + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:242 diff --git a/docs/developers/SDK/technical-references/code/classes/Market.md b/docs/developers/SDK/technical-references/code/classes/Market.md new file mode 100644 index 00000000..9da2580d --- /dev/null +++ b/docs/developers/SDK/technical-references/code/classes/Market.md @@ -0,0 +1,1202 @@ +--- +id: "Market" +title: "Class: Market" +sidebar_label: "Market" +sidebar_position: 0 +custom_edit_url: null +--- + +The Market class focuses on a Mangrove market. +On-chain, markets are implemented as two offer lists, +one for asks (base,quote), the other for bids (quote,base). + +Market initialization needs to store the network name, so you cannot +directly use the constructor. Instead of `new Market(...)`, do + +`await Market.connect(...)` + +## Properties + +### mgv + +• **mgv**: [`Mangrove`](Mangrove.md) + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:249 + +___ + +### base + +• **base**: [`MgvToken`](MgvToken.md) + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:250 + +___ + +### quote + +• **quote**: [`MgvToken`](MgvToken.md) + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:251 + +___ + +### trade + +• **trade**: `Trade` + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:256 + +___ + +### tradeEventManagement + +• **tradeEventManagement**: `TradeEventManagement` + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:257 + +___ + +### prettyP + +• **prettyP**: `PrettyPrint` + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:258 + +## Methods + +### connect + +▸ `Static` **connect**(`params`): `Promise`<[`Market`](Market.md)\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `params` | { `mgv`: [`Mangrove`](Mangrove.md) ; `base`: `string` ; `quote`: `string` } & `Partial`<[`OptionalParams`](../namespaces/Market-1.md#optionalparams)\> | + +#### Returns + +`Promise`<[`Market`](Market.md)\> + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:263 + +___ + +### close + +▸ **close**(): `void` + +#### Returns + +`void` + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:309 + +___ + +### initialize + +▸ **initialize**(): `Promise`<`void`\> + +#### Returns + +`Promise`<`void`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:322 + +___ + +### getBook + +▸ **getBook**(): [`Book`](../namespaces/Market-1.md#book) + +Return the semibooks of this market. + +Asks are standing offers to sell base and buy quote. +Bids are standing offers to buy base and sell quote. +All prices are in quote/base, all volumes are in base. +Order is from best to worse from taker perspective. + +#### Returns + +[`Book`](../namespaces/Market-1.md#book) + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:420 + +___ + +### getSemibook + +▸ **getSemibook**(`ba`): [`Semibook`](Semibook.md) + +Return the asks or bids semibook + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `ba` | [`BA`](../namespaces/Market-1.md#ba) | + +#### Returns + +[`Semibook`](Semibook.md) + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:433 + +___ + +### requestBook + +▸ **requestBook**(`opts?`): `Promise`<{ `asks`: [`Offer`](../namespaces/Market-1.md#offer)[] ; `bids`: [`Offer`](../namespaces/Market-1.md#offer)[] }\> + +#### Parameters + +| Name | Type | Default value | +| :------ | :------ | :------ | +| `opts` | [`BookOptions`](../namespaces/Market-1.md#bookoptions) | `bookOptsDefault` | + +#### Returns + +`Promise`<{ `asks`: [`Offer`](../namespaces/Market-1.md#offer)[] ; `bids`: [`Offer`](../namespaces/Market-1.md#offer)[] }\> + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:440 + +___ + +### isActive + +▸ **isActive**(): `Promise`<`boolean`\> + +#### Returns + +`Promise`<`boolean`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:454 + +___ + +### isLive + +▸ **isLive**(`ba`, `offerId`): `Promise`<`boolean`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `ba` | [`BA`](../namespaces/Market-1.md#ba) | +| `offerId` | `number` | + +#### Returns + +`Promise`<`boolean`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:459 + +___ + +### isLiveOffer + +▸ **isLiveOffer**(`offer`): `boolean` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `offer` | [`Offer`](../namespaces/Market-1.md#offer) | + +#### Returns + +`boolean` + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:464 + +___ + +### getPivotId + +▸ **getPivotId**(`ba`, `price`): `Promise`<`undefined` \| `number`\> + +Given a price, find the id of the immediately-better offer in the +book. If there is no offer with a better price, `undefined` is returned. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `ba` | [`BA`](../namespaces/Market-1.md#ba) | +| `price` | `undefined` \| `BigSource` | + +#### Returns + +`Promise`<`undefined` \| `number`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:474 + +___ + +### getOfferProvision + +▸ **getOfferProvision**(`ba`, `gasreq`, `gasprice?`): `Promise`<`Big`\> + +Gets the amount of ethers necessary to provision an offer on the market. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `ba` | [`BA`](../namespaces/Market-1.md#ba) | bids or asks | +| `gasreq` | `number` | gas required for the offer execution. | +| `gasprice?` | `number` | gas price to use for the calculation. If undefined, then Mangrove's current gas price is used. | + +#### Returns + +`Promise`<`Big`\> + +the amount of ethers necessary to provision the offer. + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:487 + +___ + +### getBidProvision + +▸ **getBidProvision**(`gasreq`, `gasprice?`): `Promise`<`Big`\> + +Gets the amount of ethers necessary to provision a bid on the market. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `gasreq` | `number` | gas required for the offer execution. | +| `gasprice?` | `number` | gas price to use for the calculation. If undefined, then Mangrove's current gas price is used. | + +#### Returns + +`Promise`<`Big`\> + +the amount of ethers necessary to provision the offer. + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:506 + +___ + +### getAskProvision + +▸ **getAskProvision**(`gasreq`, `gasprice?`): `Promise`<`Big`\> + +Gets the amount of ethers necessary to provision a bid on the market. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `gasreq` | `number` | gas required for the offer execution. | +| `gasprice?` | `number` | gas price to use for the calculation. If undefined, then Mangrove's current gas price is used. | + +#### Returns + +`Promise`<`Big`\> + +the amount of ethers necessary to provision the offer. + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:515 + +___ + +### getMissingProvision + +▸ **getMissingProvision**(`ba`, `lockedProvision`, `gasreq`, `gasprice?`): `Promise`<`Big`\> + +Gets the missing provision in ethers for an offer with the given parameters + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `ba` | [`BA`](../namespaces/Market-1.md#ba) | bids or asks | +| `lockedProvision` | `BigSource` | the provision already locked with the offer | +| `gasreq` | `number` | gas required for the offer execution. | +| `gasprice?` | `number` | gas price to use for the calculation. If undefined, then Mangrove's current gas price is used. | + +#### Returns + +`Promise`<`Big`\> + +the additional required provision, in ethers. + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:526 + +___ + +### bidInfo + +▸ **bidInfo**(`offerId`): `Promise`<[`Offer`](../namespaces/Market-1.md#offer)\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `offerId` | `number` | + +#### Returns + +`Promise`<[`Offer`](../namespaces/Market-1.md#offer)\> + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:543 + +___ + +### askInfo + +▸ **askInfo**(`offerId`): `Promise`<[`Offer`](../namespaces/Market-1.md#offer)\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `offerId` | `number` | + +#### Returns + +`Promise`<[`Offer`](../namespaces/Market-1.md#offer)\> + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:547 + +___ + +### offerInfo + +▸ **offerInfo**(`ba`, `offerId`): `Promise`<[`Offer`](../namespaces/Market-1.md#offer)\> + +Returns struct containing offer details in the current market + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `ba` | [`BA`](../namespaces/Market-1.md#ba) | +| `offerId` | `number` | + +#### Returns + +`Promise`<[`Offer`](../namespaces/Market-1.md#offer)\> + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:552 + +___ + +### permit + +▸ **permit**(`action`, `data`): `Promise`<`ContractTransaction`\> + +Sign permit data. If action="buy", will permit buying base with spender's +quote token. If action="sell", will permit buying quote with spender's base +token. See mangrove.ts. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `action` | ``"buy"`` \| ``"sell"`` | +| `data` | `Omit`<[`SimplePermitData`](../namespaces/Mangrove-1.md#simplepermitdata), ``"outbound_tkn"`` \| ``"inbound_tkn"``\> | + +#### Returns + +`Promise`<`ContractTransaction`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:559 + +___ + +### buy + +▸ **buy**(`params`, `overrides?`): `Promise`<{ `result`: `Promise`<[`OrderResult`](../namespaces/Market-1.md#orderresult)\> ; `response`: `Promise`<`ContractTransaction`\> }\> + +Market buy order. Will attempt to buy base token using quote tokens. +Params can be of the form: +- `{volume,price}`: buy `volume` base tokens for a max average price of `price`. +- `{total,price}` : buy as many base tokens as possible using up to `total` quote tokens, with a max average price of `price`. +- `{wants,gives,fillWants?}`: accept implicit max average price of `gives/wants` + +In addition, `slippage` defines an allowed slippage in % of the amount of quote token, and +`restingOrder` or `offerId` can be supplied to create a resting order or to snipe a specific order, e.g., +to account for gas. + +Will stop if +- book is empty, or +- price no longer good, or +- `wants` tokens have been bought. + +**`Example`** + +``` +const market = await mgv.market({base:"USDC",quote:"DAI"}; +market.buy({volume: 100, price: '1.01'}) //use strings to be exact +``` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `params` | [`TradeParams`](../namespaces/Market-1.md#tradeparams) | +| `overrides` | `Overrides` | + +#### Returns + +`Promise`<{ `result`: `Promise`<[`OrderResult`](../namespaces/Market-1.md#orderresult)\> ; `response`: `Promise`<`ContractTransaction`\> }\> + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:603 + +___ + +### sell + +▸ **sell**(`params`, `overrides?`): `Promise`<{ `result`: `Promise`<[`OrderResult`](../namespaces/Market-1.md#orderresult)\> ; `response`: `Promise`<`ContractTransaction`\> }\> + +Market sell order. Will attempt to sell base token for quote tokens. +Params can be of the form: +- `{volume,price}`: sell `volume` base tokens for a min average price of `price`. +- `{total,price}` : sell as many base tokens as possible buying up to `total` quote tokens, with a min average price of `price`. +- `{wants,gives,fillWants?}`: accept implicit min average price of `gives/wants`. `fillWants` will be false by default. + +In addition, `slippage` defines an allowed slippage in % of the amount of quote token, and +`restingOrder` or `offerId` can be supplied to create a resting order or to snipe a specific order, e.g., +to account for gas. + +Will stop if +- book is empty, or +- price no longer good, or +-`gives` tokens have been sold. + +**`Example`** + +``` +const market = await mgv.market({base:"USDC",quote:"DAI"}) +market.sell({volume: 100, price: 1}) +``` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `params` | [`TradeParams`](../namespaces/Market-1.md#tradeparams) | +| `overrides` | `Overrides` | + +#### Returns + +`Promise`<{ `result`: `Promise`<[`OrderResult`](../namespaces/Market-1.md#orderresult)\> ; `response`: `Promise`<`ContractTransaction`\> }\> + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:635 + +___ + +### gasEstimateBuy + +▸ **gasEstimateBuy**(`params`): `Promise`<`BigNumber`\> + +Estimate amount of gas for buy. Can be passed as overrides.gasLimit or params.gasLowerBound of + +**`See`** + +buy with same params. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `params` | [`TradeParams`](../namespaces/Market-1.md#tradeparams) | + +#### Returns + +`Promise`<`BigNumber`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:646 + +___ + +### gasEstimateSell + +▸ **gasEstimateSell**(`params`): `Promise`<`BigNumber`\> + +Estimate amount of gas for sell. Can be passed as overrides.gasLimit or params.gasLowerBound of + +**`See`** + +sell with same params. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `params` | [`TradeParams`](../namespaces/Market-1.md#tradeparams) | + +#### Returns + +`Promise`<`BigNumber`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:653 + +___ + +### snipe + +▸ **snipe**(`params`, `overrides?`): `Promise`<{ `result`: `Promise`<[`OrderResult`](../namespaces/Market-1.md#orderresult)\> ; `response`: `Promise`<`ContractTransaction`\> }\> + +Snipe specific offers. +Params are: +`targets`: an array of + `offerId`: the offer to snipe + `takerWants`: the amount of base token (for asks) or quote token (for bids) the taker wants + `takerGives`: the amount of quote token (for asks) or base token (for bids) the take gives + `gasLimit?`: the maximum gas requirement the taker will tolerate for that offer +`ba`: whether to snipe `asks` or `bids` +`fillWants?`: specifies whether you will buy at most `takerWants` (true), or you will buy as many tokens as possible as long as you don't spend more than `takerGives` (false). +`requireOffersToFail`: if true, then a successful offer will cause the call to fail without sniping anything. + Note: Setting `requireOffersToFail=true` uses the cleaner contract and the taker needs to approve spending, with + `await mgv.contract.approve(market.base.address, market.quote.address, mgv.cleanerContract.address, amount);` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `params` | [`SnipeParams`](../namespaces/Market-1.md#snipeparams) | +| `overrides` | `Overrides` | + +#### Returns + +`Promise`<{ `result`: `Promise`<[`OrderResult`](../namespaces/Market-1.md#orderresult)\> ; `response`: `Promise`<`ContractTransaction`\> }\> + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:673 + +___ + +### getRawSnipeParams + +▸ **getRawSnipeParams**(`params`, `overrides?`): `Promise`<[`RawSnipeParams`](../namespaces/Market-1.md#rawsnipeparams)\> + +Gets parameters to send to functions `market.mgv.cleanerContract.collect` or `market.mgv.contract.snipes`. +Params are: +`targets`: an array of + `offerId`: the offer to snipe + `takerWants`: the amount of base token (for asks) or quote token (for bids) the taker wants + `takerGives`: the amount of quote token (for asks) or base token (for bids) the take gives + `gasLimit?`: the maximum gas requirement the taker will tolerate for that offer +`ba`: whether to snipe `asks` or `bids` +`fillWants?`: specifies whether you will buy at most `takerWants` (true), or you will buy as many tokens as possible as long as you don't spend more than `takerGives` (false). +`requireOffersToFail`: defines whether a successful offer will cause the call to fail without sniping anything. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `params` | [`SnipeParams`](../namespaces/Market-1.md#snipeparams) | +| `overrides` | `Overrides` | + +#### Returns + +`Promise`<[`RawSnipeParams`](../namespaces/Market-1.md#rawsnipeparams)\> + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:695 + +___ + +### estimateGas + +▸ **estimateGas**(`bs`, `volume`): `Promise`<`BigNumber`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `bs` | [`BS`](../namespaces/Market-1.md#bs) | +| `volume` | `BigNumber` | + +#### Returns + +`Promise`<`BigNumber`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:702 + +___ + +### simulateGas + +▸ **simulateGas**(`ba`, `gives`, `wants`, `fillWants`): `Promise`<`BigNumber`\> + +Uses the + +**`See`** + +semibook.simulateMarketOrder to simulate the gas required for a market order. An overhead of 50% is added to account for changes to the book and failing offers. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `ba` | [`BA`](../namespaces/Market-1.md#ba) | +| `gives` | `BigNumber` | +| `wants` | `BigNumber` | +| `fillWants` | `boolean` | + +#### Returns + +`Promise`<`BigNumber`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:731 + +___ + +### estimateVolume + +▸ **estimateVolume**(`params`): `Promise`<[`VolumeEstimate`](../namespaces/Market-1.md#volumeestimate)\> + +Volume estimator. + +if you say `estimateVolume({given:100,what:"base",to:"buy"})`, + +it will give you an estimate of how much quote token you would have to +spend to get 100 base tokens. + +if you say `estimateVolume({given:10,what:"quote",to:"sell"})`, + +it will given you an estimate of how much base tokens you'd have to buy in +order to spend 10 quote tokens. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `params` | [`VolumeParams`](../namespaces/Market-1.md#volumeparams) | + +#### Returns + +`Promise`<[`VolumeEstimate`](../namespaces/Market-1.md#volumeestimate)\> + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:771 + +___ + +### estimateVolumeToReceive + +▸ **estimateVolumeToReceive**(`params`): `Promise`<[`VolumeEstimate`](../namespaces/Market-1.md#volumeestimate)\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `params` | [`DirectionlessVolumeParams`](../namespaces/Market-1.md#directionlessvolumeparams) | + +#### Returns + +`Promise`<[`VolumeEstimate`](../namespaces/Market-1.md#volumeestimate)\> + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:785 + +___ + +### estimateVolumeToSpend + +▸ **estimateVolumeToSpend**(`params`): `Promise`<[`VolumeEstimate`](../namespaces/Market-1.md#volumeestimate)\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `params` | [`DirectionlessVolumeParams`](../namespaces/Market-1.md#directionlessvolumeparams) | + +#### Returns + +`Promise`<[`VolumeEstimate`](../namespaces/Market-1.md#volumeestimate)\> + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:792 + +___ + +### config + +▸ **config**(): `Promise`<{ `asks`: [`LocalConfig`](../namespaces/Mangrove-1.md#localconfig) ; `bids`: [`LocalConfig`](../namespaces/Mangrove-1.md#localconfig) }\> + +Return config local to a market. +Returned object is of the form +`{bids,asks}` where bids and asks are of type `localConfig` +Notes: +Amounts are converted to plain numbers. +density is converted to public token units per gas used +fee *remains* in basis points of the token being bought + +#### Returns + +`Promise`<{ `asks`: [`LocalConfig`](../namespaces/Mangrove-1.md#localconfig) ; `bids`: [`LocalConfig`](../namespaces/Mangrove-1.md#localconfig) }\> + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:809 + +___ + +### consoleAsks + +▸ **consoleAsks**(`filter?`): `void` + +Pretty prints the current state of the asks of the market + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `filter?` | `prettyPrintFilter` | + +#### Returns + +`void` + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:822 + +___ + +### consoleBids + +▸ **consoleBids**(`filter?`): `void` + +Pretty prints the current state of the bids of the market + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `filter?` | `prettyPrintFilter` | + +#### Returns + +`void` + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:827 + +___ + +### prettyPrint + +▸ **prettyPrint**(`ba`, `filter`): `void` + +Pretty prints the current state of the asks or bids of the market + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `ba` | [`BA`](../namespaces/Market-1.md#ba) | +| `filter` | `prettyPrintFilter` | + +#### Returns + +`void` + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:832 + +___ + +### subscribe + +▸ **subscribe**(`cb`): `void` + +Subscribe to order book updates. + +`cb` gets called whenever the order book is updated. + Its first argument `event` is a summary of the event. It has the following properties: + +* `type` the type of change. May be: * `"OfferWrite"`: an offer was +inserted or moved in the book. * `"OfferFail"`, `"OfferSuccess"`, +`"OfferRetract"`: an offer was removed from the book because it failed, +succeeded, or was canceled. + +* `ba` is either `"bids"` or `"asks"`. The offer concerned by the change is +either an ask (an offer for `base` asking for `quote`) or a bid (`an offer +for `quote` asking for `base`). + +* `offer` is information about the offer, see type `Offer`. + +* `taker`, `takerWants`, `takerGives` (for `"OfferFail"` and +`"OfferSuccess"` only): address of the taker who executed the offer as well +as the volumes that were requested by the taker. + +* `mgvData` : extra data from mangrove and the maker +contract. See the [Mangrove contracts documentation](#TODO) for the list of possible status codes. + +`opts` may specify the maximum of offers to read initially, and the chunk +size used when querying the reader contract (always ran locally). + +**`Example`** + +``` +const market = await mgv.market({base:"USDC",quote:"DAI"} +market.subscribe((event,utils) => console.log(event.type, utils.book())) +``` + +**`Note`** + +Only one subscription may be active at a time. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `cb` | [`MarketCallback`](../namespaces/Market-1.md#marketcallback)<`void`\> | + +#### Returns + +`void` + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:872 + +___ + +### once + +▸ **once**<`T`\>(`cb`, `filter?`): `Promise`<`T`\> + +Returns a promise which is fulfilled after execution of the callback. + +#### Type parameters + +| Name | +| :------ | +| `T` | + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `cb` | [`MarketCallback`](../namespaces/Market-1.md#marketcallback)<`T`\> | +| `filter?` | [`MarketFilter`](../namespaces/Market-1.md#marketfilter) | + +#### Returns + +`Promise`<`T`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:879 + +___ + +### unsubscribe + +▸ **unsubscribe**(`cb`): `void` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `cb` | [`StorableMarketCallback`](../namespaces/Market-1.md#storablemarketcallback) | + +#### Returns + +`void` + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:893 + +___ + +### getOutboundInbound + +▸ **getOutboundInbound**(`ba`): `Object` + +Determine which token will be Mangrove's outbound/inbound depending on whether you're working with bids or asks. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `ba` | [`BA`](../namespaces/Market-1.md#ba) | + +#### Returns + +`Object` + +| Name | Type | +| :------ | :------ | +| `outbound_tkn` | [`MgvToken`](MgvToken.md) | +| `inbound_tkn` | [`MgvToken`](MgvToken.md) | + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:898 + +___ + +### getOutboundInbound + +▸ `Static` **getOutboundInbound**(`ba`, `base`, `quote`): `Object` + +Determine which token will be Mangrove's outbound/inbound depending on whether you're working with bids or asks. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `ba` | [`BA`](../namespaces/Market-1.md#ba) | +| `base` | [`MgvToken`](MgvToken.md) | +| `quote` | [`MgvToken`](MgvToken.md) | + +#### Returns + +`Object` + +| Name | Type | +| :------ | :------ | +| `outbound_tkn` | [`MgvToken`](MgvToken.md) | +| `inbound_tkn` | [`MgvToken`](MgvToken.md) | + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:906 + +___ + +### getBaseQuoteVolumes + +▸ `Static` **getBaseQuoteVolumes**(`ba`, `gives`, `wants`): `Object` + +Determine whether gives or wants will be baseVolume/quoteVolume depending on whether you're working with bids or asks. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `ba` | [`BA`](../namespaces/Market-1.md#ba) | +| `gives` | `Big` | +| `wants` | `Big` | + +#### Returns + +`Object` + +| Name | Type | +| :------ | :------ | +| `baseVolume` | `Big` | +| `quoteVolume` | `Big` | + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:921 + +___ + +### getPrice + +▸ `Static` **getPrice**(`ba`, `gives`, `wants`): `undefined` \| `Big` + +Determine the price from dividing offer gives with wants depending on whether you're working with bids or asks. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `ba` | [`BA`](../namespaces/Market-1.md#ba) | +| `gives` | `Big` | +| `wants` | `Big` | + +#### Returns + +`undefined` \| `Big` + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:933 + +___ + +### getWantsForPrice + +▸ `Static` **getWantsForPrice**(`ba`, `gives`, `price`): `Big` + +Determine the wants from gives and price depending on whether you're working with bids or asks. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `ba` | [`BA`](../namespaces/Market-1.md#ba) | +| `gives` | `Big` | +| `price` | `Big` | + +#### Returns + +`Big` + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:943 + +___ + +### getGivesForPrice + +▸ `Static` **getGivesForPrice**(`ba`, `wants`, `price`): `Big` + +Determine the gives from wants and price depending on whether you're working with bids or asks. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `ba` | [`BA`](../namespaces/Market-1.md#ba) | +| `wants` | `Big` | +| `price` | `Big` | + +#### Returns + +`Big` + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:948 + +___ + +### getGivesWantsForVolumeAtPrice + +▸ `Static` **getGivesWantsForVolumeAtPrice**(`ba`, `volume`, `price`): `Object` + +Determine gives and wants from a volume (in base) and a price depending on whether you're working with bids or asks. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `ba` | [`BA`](../namespaces/Market-1.md#ba) | +| `volume` | `Big` | +| `price` | `Big` | + +#### Returns + +`Object` + +| Name | Type | +| :------ | :------ | +| `gives` | `Big` | +| `wants` | `Big` | + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:953 + +___ + +### getDisplayDecimalsForPriceDifferences + +▸ **getDisplayDecimalsForPriceDifferences**(): `number` + +Determine the first decimal place where the smallest price difference between neighboring offers in the order book cache is visible. + +#### Returns + +`number` + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:967 + +___ + +### getDisplayDecimalsForPriceDifferences + +▸ `Static` **getDisplayDecimalsForPriceDifferences**(`offers`): `number` + +Determine the first decimal place where the smallest price difference between neighboring offers is visible. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `offers` | [`Offer`](../namespaces/Market-1.md#offer)[] | + +#### Returns + +`number` + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:976 diff --git a/docs/developers/SDK/technical-references/code/classes/MgvToken.md b/docs/developers/SDK/technical-references/code/classes/MgvToken.md new file mode 100644 index 00000000..e716fbdf --- /dev/null +++ b/docs/developers/SDK/technical-references/code/classes/MgvToken.md @@ -0,0 +1,512 @@ +--- +id: "MgvToken" +title: "Class: MgvToken" +sidebar_label: "MgvToken" +sidebar_position: 0 +custom_edit_url: null +--- + +## Properties + +### mgv + +• **mgv**: [`Mangrove`](Mangrove.md) + +#### Defined in + +@mangrovedao/mangrove.js/src/mgvtoken.ts:54 + +___ + +### name + +• **name**: `string` + +#### Defined in + +@mangrovedao/mangrove.js/src/mgvtoken.ts:55 + +___ + +### address + +• **address**: `string` + +#### Defined in + +@mangrovedao/mangrove.js/src/mgvtoken.ts:56 + +___ + +### displayedDecimals + +• **displayedDecimals**: `number` + +#### Defined in + +@mangrovedao/mangrove.js/src/mgvtoken.ts:57 + +___ + +### decimals + +• **decimals**: `number` + +#### Defined in + +@mangrovedao/mangrove.js/src/mgvtoken.ts:58 + +___ + +### contract + +• **contract**: `TestToken` + +#### Defined in + +@mangrovedao/mangrove.js/src/mgvtoken.ts:60 + +## Constructors + +### constructor + +• **new MgvToken**(`name`, `mgv`, `options?`) + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `name` | `string` | +| `mgv` | [`Mangrove`](Mangrove.md) | +| `options?` | [`ConstructorOptions`](../namespaces/MgvToken-1.md#constructoroptions) | + +#### Defined in + +@mangrovedao/mangrove.js/src/mgvtoken.ts:61 + +## Methods + +### createToken + +▸ `Static` **createToken**(`name`, `mgv`, `options?`): `Promise`<[`MgvToken`](MgvToken.md)\> + +Create a MgvToken instance, fetching data (decimals) from chain if needed. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `name` | `string` | +| `mgv` | [`Mangrove`](Mangrove.md) | +| `options?` | [`ConstructorOptions`](../namespaces/MgvToken-1.md#constructoroptions) | + +#### Returns + +`Promise`<[`MgvToken`](MgvToken.md)\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mgvtoken.ts:83 + +___ + +### fromUnits + +▸ **fromUnits**(`amount`): `Big` + +Convert base/quote from internal amount to public amount. +Uses each token's `decimals` parameter. + +**`Example`** + +``` +const usdc = await mgv.token("USDC"); +token.fromUnits("1e7") // 10 +const dai = await mgv.token("DAI") +market.fromUnits("1e18") // 1 +``` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `amount` | `string` \| `number` \| `BigNumber` | + +#### Returns + +`Big` + +#### Defined in + +@mangrovedao/mangrove.js/src/mgvtoken.ts:136 + +___ + +### toUnits + +▸ **toUnits**(`amount`): `BigNumber` + +Convert base/quote from public amount to internal contract amount. +Uses each token's `decimals` parameter. + +If `bq` is `"base"`, will convert the base, the quote otherwise. + +**`Example`** + +``` +const usdc = await mgv.token("USDC"); +token.toUnits(10) // 10e7 as ethers.BigNumber +const dai = await mgv.token("DAI") +market.toUnits(1) // 1e18 as ethers.BigNumber +``` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `amount` | `BigSource` | + +#### Returns + +`BigNumber` + +#### Defined in + +@mangrovedao/mangrove.js/src/mgvtoken.ts:153 + +___ + +### toFixed + +▸ **toFixed**(`amount`, `decimals?`): `string` + +Convert human-readable amounts to a string with the given +number of decimal places. Defaults to the token's decimals places. + +**`Example`** + +``` +token.toFixed("10.123"); // "10.12" +token.toFixed(token.fromUnits("1e7")); +``` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `amount` | `BigSource` | +| `decimals?` | `number` | + +#### Returns + +`string` + +#### Defined in + +@mangrovedao/mangrove.js/src/mgvtoken.ts:167 + +___ + +### allowance + +▸ **allowance**(`params?`): `Promise`<`Big`\> + +Return allowance of `owner` given to `spender`. +If `owner` is not specified, defaults to current signer. +If `spender` is not specified, defaults to Mangrove instance. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `params` | `Object` | +| `params.owner?` | `string` | +| `params.spender?` | `string` | + +#### Returns + +`Promise`<`Big`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mgvtoken.ts:179 + +___ + +### allowanceInfinite + +▸ **allowanceInfinite**(`params?`): `Promise`<`boolean`\> + +Returns whether allowance of `owner` given to `spender` is infinite. +If `owner` is not specified, defaults to current signer. +If `spender` is not specified, defaults to Mangrove instance. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `params` | `Object` | +| `params.owner?` | `string` | +| `params.spender?` | `string` | + +#### Returns + +`Promise`<`boolean`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mgvtoken.ts:191 + +___ + +### getDecimals + +▸ `Static` **getDecimals**(`tokenName`): `undefined` \| `number` + +Read decimals for `tokenName` on given network. +To read decimals directly onchain, use `fetchDecimals`. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `tokenName` | `string` | + +#### Returns + +`undefined` \| `number` + +#### Defined in + +@mangrovedao/mangrove.js/src/mgvtoken.ts:214 + +___ + +### getDecimalsOrFail + +▸ `Static` **getDecimalsOrFail**(`tokenName`): `number` + +Read decimals for `tokenName`. Fails if the decimals are not in the configuration. +To read decimals directly onchain, use `fetchDecimals`. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `tokenName` | `string` | + +#### Returns + +`number` + +#### Defined in + +@mangrovedao/mangrove.js/src/mgvtoken.ts:222 + +___ + +### getOrFetchDecimals + +▸ `Static` **getOrFetchDecimals**(`tokenName`, `provider`): `Promise`<`number`\> + +Read decimals for `tokenName` on given network. +If not found in the local configuration, fetch them from the current network and save them + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `tokenName` | `string` | +| `provider` | `Provider` | + +#### Returns + +`Promise`<`number`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mgvtoken.ts:230 + +___ + +### setDecimals + +▸ `Static` **setDecimals**(`tokenName`, `dec`): `void` + +Set decimals for `tokenName` on current network. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `tokenName` | `string` | +| `dec` | `number` | + +#### Returns + +`void` + +#### Defined in + +@mangrovedao/mangrove.js/src/mgvtoken.ts:240 + +___ + +### approveMangrove + +▸ **approveMangrove**(`arg?`): `Promise`<`ContractTransaction`\> + +Set approval for Mangrove to `amount`. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `arg` | `ApproveArgs` | + +#### Returns + +`Promise`<`ContractTransaction`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mgvtoken.ts:247 + +___ + +### approve + +▸ **approve**(`spender`, `arg?`): `Promise`<`ContractTransaction`\> + +Set approval for `spender` to `amount`. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `spender` | `string` | +| `arg` | `ApproveArgs` | + +#### Returns + +`Promise`<`ContractTransaction`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mgvtoken.ts:254 + +___ + +### approveIfNotInfinite + +▸ **approveIfNotInfinite**(`spender`, `arg?`): `Promise`<`undefined` \| `ContractTransaction`\> + +Sets the allowance for the spender if it is not infinite. Cannot be used to reduce from infinite. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `spender` | `string` | The spender to approve | +| `arg` | `ApproveArgs` | The approval arguments | + +#### Returns + +`Promise`<`undefined` \| `ContractTransaction`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mgvtoken.ts:273 + +___ + +### approveIfHigher + +▸ **approveIfHigher**(`spender`, `arg?`): `Promise`<`undefined` \| `ContractTransaction`\> + +Sets the allowance for the spender if it is not already enough. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `spender` | `string` | The spender to approve | +| `arg` | `ApproveArgs` | The approval arguments | + +#### Returns + +`Promise`<`undefined` \| `ContractTransaction`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mgvtoken.ts:285 + +___ + +### increaseApproval + +▸ **increaseApproval**(`spender`, `arg?`): `Promise`<`undefined` \| `ContractTransaction`\> + +Increases the allowance for the spender unless it is already max. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `spender` | `string` | The spender to approve | +| `arg` | `ApproveArgs` | The approval arguments | + +#### Returns + +`Promise`<`undefined` \| `ContractTransaction`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mgvtoken.ts:298 + +___ + +### balanceOf + +▸ **balanceOf**(`account`, `overrides?`): `Promise`<`Big`\> + +Returns the balance of `account`. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `account` | `string` | +| `overrides` | `Overrides` | + +#### Returns + +`Promise`<`Big`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mgvtoken.ts:320 + +___ + +### transfer + +▸ **transfer**(`to`, `value`, `overrides?`): `Promise`<`ContractTransaction`\> + +Transfers `value` amount of tokens to address `to` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `to` | `string` | +| `value` | `BigSource` | +| `overrides` | `Overrides` | + +#### Returns + +`Promise`<`ContractTransaction`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mgvtoken.ts:331 diff --git a/docs/developers/SDK/technical-references/code/classes/OfferLogic.md b/docs/developers/SDK/technical-references/code/classes/OfferLogic.md new file mode 100644 index 00000000..823c9966 --- /dev/null +++ b/docs/developers/SDK/technical-references/code/classes/OfferLogic.md @@ -0,0 +1,369 @@ +--- +id: "OfferLogic" +title: "Class: OfferLogic" +sidebar_label: "OfferLogic" +sidebar_position: 0 +custom_edit_url: null +--- + +**`Title`** + +The OfferLogic class connects to a Maker contract implementing the IOfferLogic interface. + +## Properties + +### mgv + +• **mgv**: [`Mangrove`](Mangrove.md) + +#### Defined in + +@mangrovedao/mangrove.js/src/offerLogic.ts:14 + +___ + +### contract + +• **contract**: `IOfferLogic` + +#### Defined in + +@mangrovedao/mangrove.js/src/offerLogic.ts:15 + +___ + +### address + +• **address**: `string` + +#### Defined in + +@mangrovedao/mangrove.js/src/offerLogic.ts:16 + +___ + +### signerOrProvider + +• **signerOrProvider**: `SignerOrProvider` + +#### Defined in + +@mangrovedao/mangrove.js/src/offerLogic.ts:17 + +## Constructors + +### constructor + +• **new OfferLogic**(`mgv`, `logic`, `signer?`) + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `mgv` | [`Mangrove`](Mangrove.md) | +| `logic` | `string` | +| `signer?` | `SignerOrProvider` | + +#### Defined in + +@mangrovedao/mangrove.js/src/offerLogic.ts:19 + +## Methods + +### router + +▸ **router**(): `Promise`<`undefined` \| `AbstractRouter`\> + +**`Note`** + +Returns this logic's router. If logic has no router this call will return `undefined` + +#### Returns + +`Promise`<`undefined` \| `AbstractRouter`\> + +the router ethers.js contract responding to the `AbstractRouter` abi. + +#### Defined in + +@mangrovedao/mangrove.js/src/offerLogic.ts:33 + +___ + +### hasRouter + +▸ **hasRouter**(): `Promise`<`boolean`\> + +Determines whether the offer logic has a router + +#### Returns + +`Promise`<`boolean`\> + +True if the offer logic has a router, false otherwise. + +#### Defined in + +@mangrovedao/mangrove.js/src/offerLogic.ts:46 + +___ + +### approve + +▸ **approve**(`tokenName`, `args?`): `Promise`<`ContractTransaction`\> + +**`Note`** + +logic approves signer or `args.optSpender` to spend a certain token on its behalf +This has to be done for each token the signer's wishes to ask or bid for. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `tokenName` | `string` | - | +| `args?` | `Object` | optional `arg.amount` can be used if one wishes to approve a finite amount | +| `args.optSpender?` | `string` | - | +| `args.optAmount?` | `BigSource` | - | +| `args.optOverrides?` | `Overrides` | - | + +#### Returns + +`Promise`<`ContractTransaction`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/offerLogic.ts:55 + +___ + +### connect + +▸ **connect**(`signerOrProvider`): [`OfferLogic`](OfferLogic.md) + +Returns a new `OfferLogic` object with a different signer or provider connected to its ethers.js `contract` + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `signerOrProvider` | `SignerOrProvider` | the new signer or provider to connect to the contract. | + +#### Returns + +[`OfferLogic`](OfferLogic.md) + +a new `OfferLogic` object with a different signer or provider. + +#### Defined in + +@mangrovedao/mangrove.js/src/offerLogic.ts:84 + +___ + +### offerGasreq + +▸ **offerGasreq**(): `Promise`<`number`\> + +Retrieves the gasreq necessary for offers of this OfferLogic to execute a trade. + +#### Returns + +`Promise`<`number`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/offerLogic.ts:89 + +___ + +### setAdmin + +▸ **setAdmin**(`newAdmin`, `overrides?`): `Promise`<`TransactionResponse`\> + +Sets the admin of the contract if the Contract implements the AccessControlled interface. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `newAdmin` | `string` | the new admin address. | +| `overrides` | `Overrides` | The ethers overrides to use when calling the setAdmin function. | + +#### Returns + +`Promise`<`TransactionResponse`\> + +The transaction used to set the new admin. + +#### Defined in + +@mangrovedao/mangrove.js/src/offerLogic.ts:99 + +___ + +### admin + +▸ **admin**(): `Promise`<`string`\> + +Retrieves the current admin of the contract if the contract implements the AccessControlled interface + +#### Returns + +`Promise`<`string`\> + +The address of the current admin. + +#### Defined in + +@mangrovedao/mangrove.js/src/offerLogic.ts:113 + +___ + +### activate + +▸ **activate**(`tokenNames`, `overrides?`): `Promise`<`TransactionResponse`\> + +**`Note`** + +(contract admin action) activates logic + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `tokenNames` | `string`[] | the names of the tokens one wishes the logic to trade | +| `overrides` | `Overrides` | The ethers overrides to use when calling the activate function. | + +#### Returns + +`Promise`<`TransactionResponse`\> + +The transaction used to activate the OfferLogic. + +#### Defined in + +@mangrovedao/mangrove.js/src/offerLogic.ts:127 + +___ + +### getMangroveBalance + +▸ **getMangroveBalance**(): `Promise`<`Big`\> + +Retrieves the provision available on Mangrove for the offer logic, in ethers + +#### Returns + +`Promise`<`Big`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/offerLogic.ts:138 + +___ + +### fundOnMangrove + +▸ **fundOnMangrove**(`funds`, `overrides?`): `Promise`<`ContractTransaction`\> + +Adds ethers for provisioning offers on Mangrove for the offer logic. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `funds` | `BigSource` | The amount of funds to add in ethers. | +| `overrides` | `Overrides` | The ethers overrides to use when calling the fund function. | + +#### Returns + +`Promise`<`ContractTransaction`\> + +The transaction used to fund the offer logic. + +#### Defined in + +@mangrovedao/mangrove.js/src/offerLogic.ts:147 + +___ + +### withdrawFromMangrove + +▸ **withdrawFromMangrove**(`amount`, `overrides?`): `Promise`<`TransactionResponse`\> + +tx will revert is signer is not the admin of the OfferLogic onchain contract + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `amount` | `BigSource` | +| `overrides` | `Overrides` | + +#### Returns + +`Promise`<`TransactionResponse`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/offerLogic.ts:153 + +___ + +### retrieveLockedProvisionForOffer + +▸ **retrieveLockedProvisionForOffer**(`market`, `ba`, `offerId?`): `Promise`<`Big`\> + +Retrieves amount of provision locked for the offer on the offer logic which can be redeemed if the offer is retracted. + +**`Remarks`** + +Provision is either locked on Mangrove or for, e.g., a forwarder, on the offer logic itself. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `market` | [`Market`](Market.md) | the market of the offer | +| `ba` | [`BA`](../namespaces/Market-1.md#ba) | wether the offer is an ask or a bid. | +| `offerId?` | `number` | the id of the offer. | + +#### Returns + +`Promise`<`Big`\> + +the amount of provision locked for the offer on the offer logic. + +#### Defined in + +@mangrovedao/mangrove.js/src/offerLogic.ts:171 + +___ + +### getMissingProvision + +▸ **getMissingProvision**(`market`, `ba`, `opts?`): `Promise`<`Big`\> + +Gets the missing provision in ethers for an offer to be posted or updated on the offer logic with the given parameters, while taking already locked provision into account. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `market` | [`Market`](Market.md) | the market for the offer. | +| `ba` | [`BA`](../namespaces/Market-1.md#ba) | bids or asks | +| `opts` | `Object` | optional parameters for the calculation. | +| `opts.id?` | `number` | the id of the offer to update. If undefined, then the offer is a new offer and nothing is locked. | +| `opts.gasreq?` | `number` | gas required for the offer execution. If undefined, the offer logic's gasreq. | +| `opts.gasprice?` | `number` | gas price to use for the calculation. If undefined, then Mangrove's current gas price is used. | + +#### Returns + +`Promise`<`Big`\> + +the additional required provision, in ethers. + +#### Defined in + +@mangrovedao/mangrove.js/src/offerLogic.ts:200 diff --git a/docs/developers/SDK/technical-references/code/classes/OfferMaker.md b/docs/developers/SDK/technical-references/code/classes/OfferMaker.md new file mode 100644 index 00000000..e004d2d4 --- /dev/null +++ b/docs/developers/SDK/technical-references/code/classes/OfferMaker.md @@ -0,0 +1,36 @@ +--- +id: "OfferMaker" +title: "Class: OfferMaker" +sidebar_label: "OfferMaker" +sidebar_position: 0 +custom_edit_url: null +--- + +The OfferMaker class connects to a simple OfferMaker contract + +## Methods + +### deploy + +▸ `Static` **deploy**(`mgv`, `gasreq?`): `Promise`<`string`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `mgv` | [`Mangrove`](Mangrove.md) | +| `gasreq?` | `number` | + +#### Returns + +`Promise`<`string`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/offerMaker.ts:11 + +## Constructors + +### constructor + +• **new OfferMaker**() diff --git a/docs/developers/SDK/technical-references/code/classes/Semibook.md b/docs/developers/SDK/technical-references/code/classes/Semibook.md new file mode 100644 index 00000000..81c2b808 --- /dev/null +++ b/docs/developers/SDK/technical-references/code/classes/Semibook.md @@ -0,0 +1,807 @@ +--- +id: "Semibook" +title: "Class: Semibook" +sidebar_label: "Semibook" +sidebar_position: 0 +custom_edit_url: null +--- + +The Semibook is a data structure for maintaining a cached prefix +of an offer list for one side (asks or bids) of a market. + +While offer lists on-chain for a market A-B are symmetric (the offer lists are +the same for the market B-A), a `Semibook` depends on the market: + +- Prices are in terms of quote tokens +- Volumes are in terms of base tokens + +## Hierarchy + +- `StateLogSubscriber`<[`State`](../namespaces/Semibook-1.md#state), [`BookSubscriptionEvent`](../namespaces/Market-1.md#booksubscriptionevent)\> + + ↳ **`Semibook`** + +## Implements + +- `Iterable`<[`Offer`](../namespaces/Market-1.md#offer)\> + +## Properties + +### DEFAULT\_MAX\_OFFERS + +▪ `Static` `Readonly` **DEFAULT\_MAX\_OFFERS**: ``50`` + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:173 + +___ + +### ba + +• `Readonly` **ba**: [`BA`](../namespaces/Market-1.md#ba) + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:175 + +___ + +### market + +• `Readonly` **market**: [`Market`](Market.md) + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:176 + +___ + +### options + +• `Readonly` **options**: [`ResolvedOptions`](../namespaces/Semibook-1.md#resolvedoptions) + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:177 + +___ + +### tradeManagement + +• **tradeManagement**: `Trade` + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:184 + +___ + +### optionsIdentifier + +• **optionsIdentifier**: `string` + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:186 + +___ + +### initializedAt + +• `Optional` **initializedAt**: `BlockWithoutParentHash` + +#### Inherited from + +StateLogSubscriber.initializedAt + +#### Defined in + +@mangrovedao/reliable-event-subscriber/dist/logSubscriber.d.ts:14 + +___ + +### lastSeenEventBlock + +• `Optional` **lastSeenEventBlock**: `BlockWithoutParentHash` + +#### Inherited from + +StateLogSubscriber.lastSeenEventBlock + +#### Defined in + +@mangrovedao/reliable-event-subscriber/dist/logSubscriber.d.ts:15 + +___ + +### cacheLock + +• `Protected` **cacheLock**: `Mutex` + +#### Inherited from + +StateLogSubscriber.cacheLock + +#### Defined in + +@mangrovedao/reliable-event-subscriber/dist/stateLogSubscriber.d.ts:12 + +## Methods + +### connect + +▸ `Static` **connect**(`market`, `ba`, `eventListener`, `options`): `Promise`<[`Semibook`](Semibook.md)\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `market` | [`Market`](Market.md) | +| `ba` | [`BA`](../namespaces/Market-1.md#ba) | +| `eventListener` | [`EventListener`](../namespaces/Semibook-1.md#eventlistener) | +| `options` | [`Options`](../namespaces/Semibook-1.md#options) | + +#### Returns + +`Promise`<[`Semibook`](Semibook.md)\> + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:188 + +___ + +### copy + +▸ **copy**(`state`): [`State`](../namespaces/Semibook-1.md#state) + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `state` | [`State`](../namespaces/Semibook-1.md#state) | + +#### Returns + +[`State`](../namespaces/Semibook-1.md#state) + +#### Overrides + +StateLogSubscriber.copy + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:217 + +___ + +### addEventListener + +▸ **addEventListener**(`listener`): `void` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `listener` | [`EventListener`](../namespaces/Semibook-1.md#eventlistener) | + +#### Returns + +`void` + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:221 + +___ + +### removeEventListener + +▸ **removeEventListener**(`listener`): `void` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `listener` | [`EventListener`](../namespaces/Semibook-1.md#eventlistener) | + +#### Returns + +`void` + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:225 + +___ + +### requestOfferListPrefix + +▸ **requestOfferListPrefix**(`options`): `Promise`<[`Offer`](../namespaces/Market-1.md#offer)[]\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `options` | [`Options`](../namespaces/Semibook-1.md#options) | + +#### Returns + +`Promise`<[`Offer`](../namespaces/Market-1.md#offer)[]\> + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:229 + +___ + +### offerInfo + +▸ **offerInfo**(`offerId`): `Promise`<[`Offer`](../namespaces/Market-1.md#offer)\> + +Returns struct containing offer details in the current offer list + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `offerId` | `number` | + +#### Returns + +`Promise`<[`Offer`](../namespaces/Market-1.md#offer)\> + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:249 + +___ + +### getConfig + +▸ **getConfig**(`blockNumber?`): `Promise`<[`LocalConfig`](../namespaces/Mangrove-1.md#localconfig)\> + +Return config local to a semibook. +Notes: +Amounts are converted to plain numbers. +density is converted to public token units per gas used +fee *remains* in basis points of the token being bought + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `blockNumber?` | `number` | + +#### Returns + +`Promise`<[`LocalConfig`](../namespaces/Mangrove-1.md#localconfig)\> + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:286 + +___ + +### getRawConfig + +▸ **getRawConfig**(`blockNumber?`): `Promise`<[`GlobalUnpackedStructOutput`, `LocalUnpackedStructOutput`] & {}\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `blockNumber?` | `number` | + +#### Returns + +`Promise`<[`GlobalUnpackedStructOutput`, `LocalUnpackedStructOutput`] & {}\> + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:291 + +___ + +### permit + +▸ **permit**(`data`): `Promise`<`ContractTransaction`\> + +Sign permit data for buying outbound_tkn with spender's inbound_tkn +See mangrove.ts. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `data` | `Omit`<[`SimplePermitData`](../namespaces/Mangrove-1.md#simplepermitdata), ``"outbound_tkn"`` \| ``"inbound_tkn"``\> | + +#### Returns + +`Promise`<`ContractTransaction`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:306 + +___ + +### size + +▸ **size**(): `number` + +Returns the number of offers in the cache. + +#### Returns + +`number` + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:321 + +___ + +### getBestInCache + +▸ **getBestInCache**(): `undefined` \| `number` + +Returns the id of the best offer in the cache + +#### Returns + +`undefined` \| `number` + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:327 + +___ + +### [iterator] + +▸ **[iterator]**(): [`CacheIterator`](../interfaces/Semibook-1.CacheIterator.md) + +Returns an iterator over the offers in the cache. + +#### Returns + +[`CacheIterator`](../interfaces/Semibook-1.CacheIterator.md) + +#### Implementation of + +Iterable.\_\_@iterator@92 + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:333 + +___ + +### iter + +▸ **iter**(): [`CacheIterator`](../interfaces/Semibook-1.CacheIterator.md) + +Convenience method for getting an iterator without having to call `[Symbol.iterator]()`. + +#### Returns + +[`CacheIterator`](../interfaces/Semibook-1.CacheIterator.md) + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:340 + +___ + +### getPivotId + +▸ **getPivotId**(`price`): `Promise`<`undefined` \| `number`\> + +Given a price, find the id of the immediately-better offer in the +semibook. If there is no offer with a better price, `undefined` is returned. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `price` | `undefined` \| `BigSource` | + +#### Returns + +`Promise`<`undefined` \| `number`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:347 + +___ + +### estimateVolume + +▸ **estimateVolume**(`params`): `Promise`<[`VolumeEstimate`](../namespaces/Market-1.md#volumeestimate)\> + +Volume estimator. + +if you say `estimateVolume({given:100,to:"buy"})`, + +it will give you an estimate of how much quote token you would have to +spend to get 100 base tokens. + +if you say `estimateVolume({given:10,to:"sell"})`, + +it will given you an estimate of how much base tokens you'd have to buy in +order to spend 10 quote tokens. + +if you add a `boundary` field, it either means +- the minimum amount you want to receive if you spend all `given` (if to:"sell"), or +- the maximum amount you are ready to spend if you buy all `given` (if to:"buy") + +So for instance, if you say `{given:10,to:"sell",boundary:"5"}`, estimateVolume will return the volume you will be able to receive if selling up to 10 at a min price of 10/5. + +The returned `givenResidue` is how much of the given token that cannot be +traded due to insufficient volume on the book / price becoming bad. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `params` | [`VolumeParams`](../namespaces/Semibook-1.md#volumeparams) | + +#### Returns + +`Promise`<[`VolumeEstimate`](../namespaces/Market-1.md#volumeestimate)\> + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:402 + +___ + +### simulateMarketOrder + +▸ **simulateMarketOrder**(`initialWants`, `initialGives`, `fillWants`): `Promise`<{ `wants`: `Big` ; `gives`: `Big` ; `totalGot`: `Big` ; `totalGave`: `Big` ; `gas`: `BigNumber` }\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `initialWants` | `Big` | +| `initialGives` | `Big` | +| `fillWants` | `boolean` | + +#### Returns + +`Promise`<{ `wants`: `Big` ; `gives`: `Big` ; `totalGot`: `Big` ; `totalGave`: `Big` ; `gas`: `BigNumber` }\> + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:429 + +___ + +### isPriceBetter + +▸ **isPriceBetter**(`price`, `referencePrice`): `boolean` + +Returns `true` if `price` is better than `referencePrice`; Otherwise, `false` is returned. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `price` | `undefined` \| `BigSource` | +| `referencePrice` | `undefined` \| `BigSource` | + +#### Returns + +`boolean` + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:526 + +___ + +### isPriceWorse + +▸ **isPriceWorse**(`price`, `referencePrice`): `boolean` + +Returns `true` if `price` is worse than `referencePrice`; Otherwise, `false` is returned. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `price` | `undefined` \| `BigSource` | +| `referencePrice` | `undefined` \| `BigSource` | + +#### Returns + +`boolean` + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:535 + +___ + +### getMaxGasReq + +▸ **getMaxGasReq**(): `Promise`<`undefined` \| `number`\> + +#### Returns + +`Promise`<`undefined` \| `number`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:542 + +___ + +### stateInitialize + +▸ **stateInitialize**(`block`): `Promise`<`ErrorOrState`<[`State`](../namespaces/Semibook-1.md#state)\>\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `block` | `BlockWithoutParentHash` | + +#### Returns + +`Promise`<`ErrorOrState`<[`State`](../namespaces/Semibook-1.md#state)\>\> + +#### Overrides + +StateLogSubscriber.stateInitialize + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:701 + +___ + +### stateHandleLog + +▸ **stateHandleLog**(`state`, `log`, `event?`): [`State`](../namespaces/Semibook-1.md#state) + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `state` | [`State`](../namespaces/Semibook-1.md#state) | +| `log` | `Log` | +| `event?` | [`BookSubscriptionEvent`](../namespaces/Market-1.md#booksubscriptionevent) | + +#### Returns + +[`State`](../namespaces/Semibook-1.md#state) + +#### Overrides + +StateLogSubscriber.stateHandleLog + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:748 + +___ + +### rawLocalConfigToLocalConfig + +▸ `Static` **rawLocalConfigToLocalConfig**(`local`, `outboundDecimals`): [`LocalConfig`](../namespaces/Mangrove-1.md#localconfig) + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `local` | `LocalUnpackedStructOutput` | +| `outboundDecimals` | `number` | + +#### Returns + +[`LocalConfig`](../namespaces/Mangrove-1.md#localconfig) + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:1110 + +___ + +### getMinimumVolume + +▸ **getMinimumVolume**(`gasreq`): `Promise`<`Big`\> + +Determines the minimum volume required to stay above density limit for the given gasreq (with a minimum of 1 unit of outbound, since 0 gives is not allowed). + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `gasreq` | `number` | The gas requirement for the offer. | + +#### Returns + +`Promise`<`Big`\> + +The minimum volume required to stay above density limit. + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:1129 + +___ + +### rawIdToId + +▸ `Static` **rawIdToId**(`rawId`): `undefined` \| `number` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `rawId` | `BigNumber` | + +#### Returns + +`undefined` \| `number` + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:1140 + +___ + +### getIsVolumeDesiredForAsks + +▸ `Static` **getIsVolumeDesiredForAsks**(`opts`): `boolean` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `opts` | [`BookOptions`](../namespaces/Market-1.md#bookoptions) | + +#### Returns + +`boolean` + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:1187 + +___ + +### getIsVolumeDesiredForBids + +▸ `Static` **getIsVolumeDesiredForBids**(`opts`): `boolean` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `opts` | [`BookOptions`](../namespaces/Market-1.md#bookoptions) | + +#### Returns + +`boolean` + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:1197 + +___ + +### checkIfLastSeenEventBlockExists + +▸ `Protected` **checkIfLastSeenEventBlockExists**(): `void` + +#### Returns + +`void` + +#### Inherited from + +StateLogSubscriber.checkIfLastSeenEventBlockExists + +#### Defined in + +@mangrovedao/reliable-event-subscriber/dist/stateLogSubscriber.d.ts:16 + +___ + +### getLatestState + +▸ **getLatestState**(): [`State`](../namespaces/Semibook-1.md#state) + +#### Returns + +[`State`](../namespaces/Semibook-1.md#state) + +#### Inherited from + +StateLogSubscriber.getLatestState + +#### Defined in + +@mangrovedao/reliable-event-subscriber/dist/stateLogSubscriber.d.ts:17 + +___ + +### initialize + +▸ **initialize**(`wantedBlock`): `Promise`<`InitializeErrorOrBlock`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `wantedBlock` | `BlockWithoutParentHash` | + +#### Returns + +`Promise`<`InitializeErrorOrBlock`\> + +#### Inherited from + +StateLogSubscriber.initialize + +#### Defined in + +@mangrovedao/reliable-event-subscriber/dist/stateLogSubscriber.d.ts:18 + +___ + +### handleLog + +▸ **handleLog**(`log`, `event?`): `Promise`<`void`\> + +handle received log by creating new cached state if we found a block that is newer +than our cache. Then let implementation `stateHandleLog` modify the state. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `log` | `Log` | +| `event?` | [`BookSubscriptionEvent`](../namespaces/Market-1.md#booksubscriptionevent) | + +#### Returns + +`Promise`<`void`\> + +#### Inherited from + +StateLogSubscriber.handleLog + +#### Defined in + +@mangrovedao/reliable-event-subscriber/dist/stateLogSubscriber.d.ts:27 + +___ + +### rollback + +▸ **rollback**(`block`): `void` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `block` | `Block` | + +#### Returns + +`void` + +#### Inherited from + +StateLogSubscriber.rollback + +#### Defined in + +@mangrovedao/reliable-event-subscriber/dist/stateLogSubscriber.d.ts:28 diff --git a/docs/developers/SDK/technical-references/code/classes/_category_.yml b/docs/developers/SDK/technical-references/code/classes/_category_.yml new file mode 100644 index 00000000..55c7980a --- /dev/null +++ b/docs/developers/SDK/technical-references/code/classes/_category_.yml @@ -0,0 +1,2 @@ +label: "Classes" +position: 3 \ No newline at end of file diff --git a/docs/developers/SDK/technical-references/code/classes/eth.Mnemonic.md b/docs/developers/SDK/technical-references/code/classes/eth.Mnemonic.md new file mode 100644 index 00000000..24968443 --- /dev/null +++ b/docs/developers/SDK/technical-references/code/classes/eth.Mnemonic.md @@ -0,0 +1,126 @@ +--- +id: "eth.Mnemonic" +title: "Class: Mnemonic" +sidebar_label: "eth.Mnemonic" +custom_edit_url: null +--- + +[eth](../namespaces/eth.md).Mnemonic + +## Properties + +### mnemonic + +• **mnemonic**: `string` + +#### Defined in + +@mangrovedao/mangrove.js/src/eth.ts:48 + +___ + +### iterateOn + +• **iterateOn**: ``"index"`` \| ``"change"`` \| ``"account"`` + +#### Defined in + +@mangrovedao/mangrove.js/src/eth.ts:49 + +## Methods + +### path + +▸ `Static` **path**(`iterator`, `iterateOn`): `string` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `iterator` | `number` | +| `iterateOn` | ``"index"`` \| ``"change"`` \| ``"account"`` | + +#### Returns + +`string` + +#### Defined in + +@mangrovedao/mangrove.js/src/eth.ts:50 + +___ + +### signer + +▸ **signer**(`iterator`): `Wallet` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `iterator` | `number` | + +#### Returns + +`Wallet` + +#### Defined in + +@mangrovedao/mangrove.js/src/eth.ts:66 + +___ + +### address + +▸ **address**(`iterator`): `string` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `iterator` | `number` | + +#### Returns + +`string` + +#### Defined in + +@mangrovedao/mangrove.js/src/eth.ts:71 + +___ + +### key + +▸ **key**(`iterator`): `string` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `iterator` | `number` | + +#### Returns + +`string` + +#### Defined in + +@mangrovedao/mangrove.js/src/eth.ts:75 + +## Constructors + +### constructor + +• **new Mnemonic**(`mnemonic`, `iterateOn?`) + +#### Parameters + +| Name | Type | Default value | +| :------ | :------ | :------ | +| `mnemonic` | `string` | `undefined` | +| `iterateOn` | ``"index"`` \| ``"change"`` \| ``"account"`` | `"index"` | + +#### Defined in + +@mangrovedao/mangrove.js/src/eth.ts:58 diff --git a/docs/developers/SDK/technical-references/code/enums/_category_.yml b/docs/developers/SDK/technical-references/code/enums/_category_.yml new file mode 100644 index 00000000..1687a9e0 --- /dev/null +++ b/docs/developers/SDK/technical-references/code/enums/_category_.yml @@ -0,0 +1,2 @@ +label: "Enumerations" +position: 2 \ No newline at end of file diff --git a/docs/developers/SDK/technical-references/code/enums/mgvTestUtil.AccountName.md b/docs/developers/SDK/technical-references/code/enums/mgvTestUtil.AccountName.md new file mode 100644 index 00000000..1aabec7a --- /dev/null +++ b/docs/developers/SDK/technical-references/code/enums/mgvTestUtil.AccountName.md @@ -0,0 +1,48 @@ +--- +id: "mgvTestUtil.AccountName" +title: "Enumeration: AccountName" +sidebar_label: "mgvTestUtil.AccountName" +custom_edit_url: null +--- + +[mgvTestUtil](../namespaces/mgvTestUtil.md).AccountName + +## Enumeration Members + +### Deployer + +• **Deployer** = ``"deployer"`` + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:122 + +___ + +### Cleaner + +• **Cleaner** = ``"cleaner"`` + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:123 + +___ + +### Maker + +• **Maker** = ``"maker"`` + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:124 + +___ + +### Arbitrager + +• **Arbitrager** = ``"arbitrager"`` + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:125 diff --git a/docs/developers/SDK/technical-references/code/index.md b/docs/developers/SDK/technical-references/code/index.md new file mode 100644 index 00000000..9d441a20 --- /dev/null +++ b/docs/developers/SDK/technical-references/code/index.md @@ -0,0 +1,107 @@ +--- +id: "index" +title: "@mangrovedao/mangrove.js" +sidebar_label: "Readme" +sidebar_position: 0 +custom_edit_url: null +--- + +[![CI](https://github.com/mangrovedao/mangrove.js/actions/workflows/node.js.yml/badge.svg)](https://github.com/mangrovedao/mangrove.js/actions/workflows/node.js.yml) [![Coverage Status](https://coveralls.io/repos/github/mangrovedao/mangrove.js/badge.svg)](https://coveralls.io/github/mangrovedao/mangrove.js) + +This repo contains the SDK for developing TypeScript (and JavaScript) apps using the Mangrove. + +The core contracts for Mangrove with example Solidity offer logics live in the [mangrove-core](https://github.com/mangrovedao/mangrove-core) repo. + +# Documentation + +If you are looking for the Mangrove developer documentation, the main site to go to is [docs.mangrove.exchange](https://docs.mangrove.exchange). + +# Prerequisites + +For Linux or macOS everything should work out of the box, if you are using Windows, then we recommend installing everything from within WSL2 and expect some quirks. + +1. [Node.js](https://nodejs.org/en/) 14.14+, we recommend installation through [nvm](https://github.com/nvm-sh/nvm#installing-and-updating), e.g.: + + ```shell + $ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash + # Reopen shell + $ nvm install --lts + ``` + +2. [Yarn 2](https://yarnpkg.com/getting-started/install), with Node.js >= 16.10: + + ```shell + $ corepack enable + ``` + +3. [Foundry](https://book.getfoundry.sh/getting-started/installation.html): + + ```shell + $ curl -L https://foundry.paradigm.xyz | bash + # Reopen shell + $ foundryup + ``` + +4. Clone the git repo with sub-modules + + ```shell + $ git clone --recurse-submodules https://github.com/mangrovedao/mangrove.js.git + # Or set the global git config once: git config --global submodule.recurse true + ``` + +# Usage + +The following sections describe the most common use cases in this repo. + +## Initial setup + +After first cloning the repo, you should run `yarn install` in the root folder. + +```shell +$ yarn install +``` + +Then you need to setup the local environment (still in the root folder): + +```shell +$ cp .env.local.example .env.test.local +``` + +Then open `.env.test.local` in your favorite editor and put in settings for, e.g., node urls, pointing to a node provider, like, for instance, [Alchemy](https://www.alchemy.com/). + +## Build + +To build, run + +```shell +$ yarn build +``` + +If you encounter issues with JavaScript memory consumption, then try increasing the max available space for heap, and try again: + +```shell +$ export NODE_OPTIONS="$NODE_OPTIONS --max_old_space_size=4096" +$ yarn build +``` + +## Test + +To run tests, run + +```shell +$ yarn test +``` + +## Yarn usage details + +⚠️  Be aware that when googling Yarn commands, it's often not clear whether the results pertain to Yarn 1 (aka 'Classic') or Yarn 2+. Currently (November 2021), most examples and much tool support is implicitly engineered towards Yarn 1. + +### Lifecycle scripts and Yarn 2 + +Yarn 2 deliberately only supports a subset of the lifecycle scripts supported by npm. So when adding/modifying lifecycle scripts, you should consult Yarn 2's documentation on the subject: https://yarnpkg.com/advanced/lifecycle-scripts#gatsby-focus-wrapper . + +# Git hooks and Husky + +We use [Husky](https://typicode.github.io/husky/#/) to manage our Git hooks. + +The Git hook scripts are in the `.husky/` folder. diff --git a/docs/developers/SDK/technical-references/code/interfaces/Semibook-1.CacheIterator.md b/docs/developers/SDK/technical-references/code/interfaces/Semibook-1.CacheIterator.md new file mode 100644 index 00000000..78a4009b --- /dev/null +++ b/docs/developers/SDK/technical-references/code/interfaces/Semibook-1.CacheIterator.md @@ -0,0 +1,168 @@ +--- +id: "Semibook-1.CacheIterator" +title: "Interface: CacheIterator" +sidebar_label: "Semibook.CacheIterator" +custom_edit_url: null +--- + +[Semibook](../namespaces/Semibook-1.md).CacheIterator + +An iterator over a semibook cache. + +## Hierarchy + +- `IterableIterator`<[`Offer`](../namespaces/Market-1.md#offer)\> + + ↳ **`CacheIterator`** + +## Methods + +### filter + +▸ **filter**(`predicate`): [`CacheIterator`](Semibook-1.CacheIterator.md) + +Filter the offers in the cache using a predicate. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `predicate` | (`offer`: [`Offer`](../namespaces/Market-1.md#offer)) => `boolean` | Function is a predicate, to test each element of the array. Should return `true` if the element should be kept; otherwise `false` should be returned. | + +#### Returns + +[`CacheIterator`](Semibook-1.CacheIterator.md) + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:130 + +___ + +### find + +▸ **find**(`predicate`): `undefined` \| [`Offer`](../namespaces/Market-1.md#offer) + +Returns the value of the first element in the provided array that +satisfies the provided predicate. If no values satisfy the testing function, +`undefined` is returned. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `predicate` | (`offer`: [`Offer`](../namespaces/Market-1.md#offer)) => `boolean` | Function is a predicate, to test each element of the array. The firs offer that satisfies the predicate is returned; otherwise `undefined` is returned. | + +#### Returns + +`undefined` \| [`Offer`](../namespaces/Market-1.md#offer) + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:140 + +___ + +### toArray + +▸ **toArray**(): [`Offer`](../namespaces/Market-1.md#offer)[] + +Returns the elements in an array. + +#### Returns + +[`Offer`](../namespaces/Market-1.md#offer)[] + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:143 + +___ + +### next + +▸ **next**(`...args`): `IteratorResult`<[`Offer`](../namespaces/Market-1.md#offer), `any`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `...args` | [] \| [`undefined`] | + +#### Returns + +`IteratorResult`<[`Offer`](../namespaces/Market-1.md#offer), `any`\> + +#### Inherited from + +IterableIterator.next + +#### Defined in + +typescript/lib/lib.es2015.iterable.d.ts:45 + +___ + +### return + +▸ `Optional` **return**(`value?`): `IteratorResult`<[`Offer`](../namespaces/Market-1.md#offer), `any`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `value?` | `any` | + +#### Returns + +`IteratorResult`<[`Offer`](../namespaces/Market-1.md#offer), `any`\> + +#### Inherited from + +IterableIterator.return + +#### Defined in + +typescript/lib/lib.es2015.iterable.d.ts:46 + +___ + +### throw + +▸ `Optional` **throw**(`e?`): `IteratorResult`<[`Offer`](../namespaces/Market-1.md#offer), `any`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `e?` | `any` | + +#### Returns + +`IteratorResult`<[`Offer`](../namespaces/Market-1.md#offer), `any`\> + +#### Inherited from + +IterableIterator.throw + +#### Defined in + +typescript/lib/lib.es2015.iterable.d.ts:47 + +___ + +### [iterator] + +▸ **[iterator]**(): `IterableIterator`<[`Offer`](../namespaces/Market-1.md#offer)\> + +#### Returns + +`IterableIterator`<[`Offer`](../namespaces/Market-1.md#offer)\> + +#### Inherited from + +IterableIterator.\_\_@iterator@92 + +#### Defined in + +typescript/lib/lib.es2015.iterable.d.ts:55 diff --git a/docs/developers/SDK/technical-references/code/interfaces/_category_.yml b/docs/developers/SDK/technical-references/code/interfaces/_category_.yml new file mode 100644 index 00000000..43bec88c --- /dev/null +++ b/docs/developers/SDK/technical-references/code/interfaces/_category_.yml @@ -0,0 +1,2 @@ +label: "Interfaces" +position: 4 \ No newline at end of file diff --git a/docs/developers/SDK/technical-references/code/interfaces/eth.CreateSignerOptions.md b/docs/developers/SDK/technical-references/code/interfaces/eth.CreateSignerOptions.md new file mode 100644 index 00000000..2aa833a3 --- /dev/null +++ b/docs/developers/SDK/technical-references/code/interfaces/eth.CreateSignerOptions.md @@ -0,0 +1,98 @@ +--- +id: "eth.CreateSignerOptions" +title: "Interface: CreateSignerOptions" +sidebar_label: "eth.CreateSignerOptions" +custom_edit_url: null +--- + +[eth](../namespaces/eth.md).CreateSignerOptions + +## Properties + +### provider + +• `Optional` **provider**: `string` \| `Provider` + +#### Defined in + +@mangrovedao/mangrove.js/src/eth.ts:22 + +___ + +### providerWsUrl + +• `Optional` **providerWsUrl**: `string` + +#### Defined in + +@mangrovedao/mangrove.js/src/eth.ts:25 + +___ + +### signerIndex + +• `Optional` **signerIndex**: `number` + +#### Defined in + +@mangrovedao/mangrove.js/src/eth.ts:27 + +___ + +### privateKey + +• `Optional` **privateKey**: `string` + +#### Defined in + +@mangrovedao/mangrove.js/src/eth.ts:29 + +___ + +### mnemonic + +• `Optional` **mnemonic**: `string` + +#### Defined in + +@mangrovedao/mangrove.js/src/eth.ts:31 + +___ + +### path + +• `Optional` **path**: `string` + +#### Defined in + +@mangrovedao/mangrove.js/src/eth.ts:33 + +___ + +### signer + +• `Optional` **signer**: `any` + +#### Defined in + +@mangrovedao/mangrove.js/src/eth.ts:35 + +___ + +### jsonWallet + +• `Optional` **jsonWallet**: `JsonWalletOptions` + +#### Defined in + +@mangrovedao/mangrove.js/src/eth.ts:37 + +___ + +### forceReadOnly + +• `Optional` **forceReadOnly**: `boolean` + +#### Defined in + +@mangrovedao/mangrove.js/src/eth.ts:39 diff --git a/docs/developers/SDK/technical-references/code/interfaces/eth.ProviderNetwork.md b/docs/developers/SDK/technical-references/code/interfaces/eth.ProviderNetwork.md new file mode 100644 index 00000000..a13b2e42 --- /dev/null +++ b/docs/developers/SDK/technical-references/code/interfaces/eth.ProviderNetwork.md @@ -0,0 +1,28 @@ +--- +id: "eth.ProviderNetwork" +title: "Interface: ProviderNetwork" +sidebar_label: "eth.ProviderNetwork" +custom_edit_url: null +--- + +[eth](../namespaces/eth.md).ProviderNetwork + +## Properties + +### id + +• `Optional` **id**: `number` + +#### Defined in + +@mangrovedao/mangrove.js/src/eth.ts:43 + +___ + +### name + +• **name**: `string` + +#### Defined in + +@mangrovedao/mangrove.js/src/eth.ts:44 diff --git a/docs/developers/SDK/technical-references/code/modules.md b/docs/developers/SDK/technical-references/code/modules.md new file mode 100644 index 00000000..4772a1af --- /dev/null +++ b/docs/developers/SDK/technical-references/code/modules.md @@ -0,0 +1,54 @@ +--- +id: "modules" +title: "@mangrovedao/mangrove.js" +sidebar_label: "Exports" +sidebar_position: 0.5 +custom_edit_url: null +--- + +## Namespaces + +- [eth](namespaces/eth.md) +- [KandelStrategies](namespaces/KandelStrategies-1.md) +- [LiquidityProvider](namespaces/LiquidityProvider-1.md) +- [Mangrove](namespaces/Mangrove-1.md) +- [Market](namespaces/Market-1.md) +- [MgvToken](namespaces/MgvToken-1.md) +- [Semibook](namespaces/Semibook-1.md) +- [mgvTestUtil](namespaces/mgvTestUtil.md) + +## Classes + +- [KandelDistribution](classes/KandelDistribution.md) +- [KandelDistributionGenerator](classes/KandelDistributionGenerator.md) +- [KandelFarm](classes/KandelFarm.md) +- [KandelInstance](classes/KandelInstance.md) +- [KandelSeeder](classes/KandelSeeder.md) +- [KandelStrategies](classes/KandelStrategies.md) +- [LiquidityProvider](classes/LiquidityProvider.md) +- [Mangrove](classes/Mangrove.md) +- [Market](classes/Market.md) +- [MgvToken](classes/MgvToken.md) +- [OfferLogic](classes/OfferLogic.md) +- [OfferMaker](classes/OfferMaker.md) +- [Semibook](classes/Semibook.md) + +## References + +### default + +Renames and re-exports [Mangrove](classes/Mangrove.md) + +## Functions + +### enableLogging + +▸ **enableLogging**(): `void` + +#### Returns + +`void` + +#### Defined in + +@mangrovedao/mangrove.js/src/util/logger.ts:10 diff --git a/docs/developers/SDK/technical-references/code/namespaces/KandelStrategies-1.md b/docs/developers/SDK/technical-references/code/namespaces/KandelStrategies-1.md new file mode 100644 index 00000000..2c856776 --- /dev/null +++ b/docs/developers/SDK/technical-references/code/namespaces/KandelStrategies-1.md @@ -0,0 +1,8 @@ +--- +id: "KandelStrategies-1" +title: "Namespace: KandelStrategies" +sidebar_label: "KandelStrategies" +sidebar_position: 0 +custom_edit_url: null +--- + diff --git a/docs/developers/SDK/technical-references/code/namespaces/LiquidityProvider-1.md b/docs/developers/SDK/technical-references/code/namespaces/LiquidityProvider-1.md new file mode 100644 index 00000000..5e4a4d40 --- /dev/null +++ b/docs/developers/SDK/technical-references/code/namespaces/LiquidityProvider-1.md @@ -0,0 +1,59 @@ +--- +id: "LiquidityProvider-1" +title: "Namespace: LiquidityProvider" +sidebar_label: "LiquidityProvider" +sidebar_position: 0 +custom_edit_url: null +--- + +## Type Aliases + +### ConstructionParams + +Ƭ **ConstructionParams**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `mgv` | [`Mangrove`](../classes/Mangrove.md) | +| `logic?` | [`OfferLogic`](../classes/OfferLogic.md) | +| `eoa?` | `string` | +| `gasreq` | `number` | +| `market` | [`Market`](../classes/Market.md) | + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:23 + +___ + +### OfferParams + +Ƭ **OfferParams**: { `price`: `Bigish` ; `volume`: `Bigish` } & `OptParams` \| { `wants`: `Bigish` ; `gives`: `Bigish` } & `OptParams` + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:37 + +___ + +### OfferActionResult + +Ƭ **OfferActionResult**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `offerType` | [`BA`](Market-1.md#ba) | +| `market` | `string` | +| `txReceipt` | `ethers.ContractReceipt` | +| `id` | `number` | +| `gasprice?` | `number` | +| `gasreq?` | `number` | +| `refund?` | `Big` | + +#### Defined in + +@mangrovedao/mangrove.js/src/liquidityProvider.ts:41 diff --git a/docs/developers/SDK/technical-references/code/namespaces/Mangrove-1.md b/docs/developers/SDK/technical-references/code/namespaces/Mangrove-1.md new file mode 100644 index 00000000..5b49fb8c --- /dev/null +++ b/docs/developers/SDK/technical-references/code/namespaces/Mangrove-1.md @@ -0,0 +1,161 @@ +--- +id: "Mangrove-1" +title: "Namespace: Mangrove" +sidebar_label: "Mangrove" +sidebar_position: 0 +custom_edit_url: null +--- + +## Type Aliases + +### RawConfig + +Ƭ **RawConfig**: `Awaited`<`ReturnType`<`typechain.Mangrove`[``"functions"``][``"configInfo"``]\>\> + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:42 + +___ + +### LocalConfig + +Ƭ **LocalConfig**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `active` | `boolean` | +| `fee` | `number` | +| `density` | `Big` | +| `offer_gasbase` | `number` | +| `lock` | `boolean` | +| `best` | `number` \| `undefined` | +| `last` | `number` \| `undefined` | + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:46 + +___ + +### GlobalConfig + +Ƭ **GlobalConfig**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `monitor` | `string` | +| `useOracle` | `boolean` | +| `notify` | `boolean` | +| `gasprice` | `number` | +| `gasmax` | `number` | +| `dead` | `boolean` | + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:56 + +___ + +### SimplePermitData + +Ƭ **SimplePermitData**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `outbound_tkn` | `string` | +| `inbound_tkn` | `string` | +| `owner` | `string` | +| `spender` | `string` | +| `value` | `ethers.BigNumber` | +| `nonce?` | `number` \| `ethers.BigNumber` | +| `deadline` | `number` \| `Date` | + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:65 + +___ + +### PermitData + +Ƭ **PermitData**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `outbound_tkn` | `string` | +| `inbound_tkn` | `string` | +| `owner` | `string` | +| `spender` | `string` | +| `value` | `ethers.BigNumber` | +| `nonce` | `ethers.BigNumber` | +| `deadline` | `number` | + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:75 + +___ + +### OpenMarketInfo + +Ƭ **OpenMarketInfo**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `base` | { `name`: `string` ; `address`: `string` ; `symbol`: `string` ; `decimals`: `number` } | +| `base.name` | `string` | +| `base.address` | `string` | +| `base.symbol` | `string` | +| `base.decimals` | `number` | +| `quote` | { `name`: `string` ; `address`: `string` ; `symbol`: `string` ; `decimals`: `number` } | +| `quote.name` | `string` | +| `quote.address` | `string` | +| `quote.symbol` | `string` | +| `quote.decimals` | `number` | +| `asksConfig?` | [`LocalConfig`](Mangrove-1.md#localconfig) | +| `bidsConfig?` | [`LocalConfig`](Mangrove-1.md#localconfig) | + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:85 + +___ + +### CreateOptions + +Ƭ **CreateOptions**: [`CreateSignerOptions`](../interfaces/eth.CreateSignerOptions.md) & { `blockManagerOptions?`: `BlockManager.Options` ; `reliableWebsocketProviderOptions?`: `ReliableWebsocketProvider.Options` ; `reliableHttpProviderOptions?`: `ReliableHttpProvider.Options` } + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:92 + +___ + +### Configuration + +Ƭ **Configuration**: `MangroveJsConfiguration` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:98 + +___ + +### PartialConfiguration + +Ƭ **PartialConfiguration**: `PartialMangroveJsConfiguration` + +#### Defined in + +@mangrovedao/mangrove.js/src/mangrove.ts:100 diff --git a/docs/developers/SDK/technical-references/code/namespaces/Market-1.BookReturns.md b/docs/developers/SDK/technical-references/code/namespaces/Market-1.BookReturns.md new file mode 100644 index 00000000..18110b7d --- /dev/null +++ b/docs/developers/SDK/technical-references/code/namespaces/Market-1.BookReturns.md @@ -0,0 +1,38 @@ +--- +id: "Market-1.BookReturns" +title: "Namespace: BookReturns" +sidebar_label: "Market.BookReturns" +custom_edit_url: null +--- + +[Market](Market-1.md).BookReturns + +## Type Aliases + +### Indices + +Ƭ **Indices**: `_BookReturns`[``1``] + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:191 + +___ + +### Offers + +Ƭ **Offers**: `_BookReturns`[``2``] + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:192 + +___ + +### Details + +Ƭ **Details**: `_BookReturns`[``3``] + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:193 diff --git a/docs/developers/SDK/technical-references/code/namespaces/Market-1.md b/docs/developers/SDK/technical-references/code/namespaces/Market-1.md new file mode 100644 index 00000000..7eed9c84 --- /dev/null +++ b/docs/developers/SDK/technical-references/code/namespaces/Market-1.md @@ -0,0 +1,415 @@ +--- +id: "Market-1" +title: "Namespace: Market" +sidebar_label: "Market" +sidebar_position: 0 +custom_edit_url: null +--- + +## Namespaces + +- [BookReturns](Market-1.BookReturns.md) + +## Type Aliases + +### BA + +Ƭ **BA**: ``"bids"`` \| ``"asks"`` + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:31 + +___ + +### BS + +Ƭ **BS**: ``"buy"`` \| ``"sell"`` + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:32 + +___ + +### MgvReader + +Ƭ **MgvReader**: `typechain.MgvReader` + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:33 + +___ + +### Failure + +Ƭ **Failure**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `offerId` | `number` | +| `reason` | `string` | +| `FailToDeliver?` | `Big` | +| `volumeGiven?` | `Big` | + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:34 + +___ + +### Success + +Ƭ **Success**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `offerId` | `number` | +| `got` | `Big` | +| `gave` | `Big` | + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:40 + +___ + +### Summary + +Ƭ **Summary**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `got` | `Big` | +| `gave` | `Big` | +| `partialFill` | `boolean` | +| `bounty` | `Big` | +| `feePaid` | `Big` | + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:45 + +___ + +### OrderResult + +Ƭ **OrderResult**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `txReceipt` | `ethers.ContractReceipt` | +| `summary` | [`Summary`](Market-1.md#summary) | +| `successes` | [`Success`](Market-1.md#success)[] | +| `tradeFailures` | [`Failure`](Market-1.md#failure)[] | +| `posthookFailures` | [`Failure`](Market-1.md#failure)[] | +| `offerWrites` | { `ba`: [`BA`](Market-1.md#ba) ; `offer`: [`OfferSlim`](Market-1.md#offerslim) }[] | +| `restingOrder?` | [`OfferSlim`](Market-1.md#offerslim) | + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:52 + +___ + +### BookSubscriptionEvent + +Ƭ **BookSubscriptionEvent**: { `name`: ``"OfferWrite"`` } & `TCM.OfferWriteEvent` \| { `name`: ``"OfferFail"`` } & `TCM.OfferFailEvent` \| { `name`: ``"OfferSuccess"`` } & `TCM.OfferSuccessEvent` \| { `name`: ``"OfferRetract"`` } & `TCM.OfferRetractEvent` \| { `name`: ``"SetGasbase"`` } & `TCM.SetGasbaseEvent` + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:62 + +___ + +### OrderRoute + +Ƭ **OrderRoute**: ``"Mangrove"`` \| ``"MangroveOrder"`` + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:69 + +___ + +### TradeParams + +Ƭ **TradeParams**: { `forceRoutingToMangroveOrder?`: `boolean` ; `slippage?`: `number` ; `fillOrKill?`: `boolean` ; `expiryDate?`: `number` ; `gasLowerBound?`: `ethers.ethers.BigNumberish` } & { `restingOrder?`: [`RestingOrderParams`](Market-1.md#restingorderparams) } \| { `offerId?`: `number` } & { `volume`: `Bigish` ; `price`: `Bigish` } \| { `total`: `Bigish` ; `price`: `Bigish` } \| { `wants`: `Bigish` ; `gives`: `Bigish` ; `fillWants?`: `boolean` } + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:71 + +___ + +### RestingOrderParams + +Ƭ **RestingOrderParams**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `provision` | `Bigish` | + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:84 + +___ + +### SnipeParams + +Ƭ **SnipeParams**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `targets` | { `offerId`: `number` ; `takerWants`: `Bigish` ; `takerGives`: `Bigish` ; `gasLimit?`: `number` }[] | +| `ba` | [`BA`](Market-1.md#ba) | +| `fillWants?` | `boolean` | +| `requireOffersToFail?` | `boolean` | + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:88 + +___ + +### RawSnipeParams + +Ƭ **RawSnipeParams**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `ba` | [`BA`](Market-1.md#ba) | +| `outboundTkn` | `string` | +| `inboundTkn` | `string` | +| `targets` | [`Promise`<`ethers.ethers.BigNumberish`\> \| `ethers.ethers.BigNumberish`, `Promise`<`ethers.ethers.BigNumberish`\> \| `ethers.ethers.BigNumberish`, `Promise`<`ethers.ethers.BigNumberish`\> \| `ethers.ethers.BigNumberish`, `Promise`<`ethers.ethers.BigNumberish`\> \| `ethers.ethers.BigNumberish`][] | +| `fillWants` | `boolean` | + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:100 + +___ + +### VolumeParams + +Ƭ **VolumeParams**: [`VolumeParams`](Semibook-1.md#volumeparams) & { `what`: ``"base"`` \| ``"quote"`` } + +Specification of how much volume to (potentially) trade on the market. + +`{given:100, what:"base", to:"buy"}` means buying 100 base tokens. + +`{given:10, what:"quote", to:"sell"})` means selling 10 quote tokens. + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:120 + +___ + +### DirectionlessVolumeParams + +Ƭ **DirectionlessVolumeParams**: `Omit`<[`VolumeParams`](Market-1.md#volumeparams), ``"to"``\> + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:124 + +___ + +### OptionalParams + +Ƭ **OptionalParams**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `bookOptions` | [`BookOptions`](Market-1.md#bookoptions) | +| `noInit` | `boolean` | + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:126 + +___ + +### CacheContentsOptions + +Ƭ **CacheContentsOptions**: { `maxOffers?`: `number` } \| { `desiredPrice`: `Bigish` } \| { `desiredVolume`: [`VolumeParams`](Market-1.md#volumeparams) } + +Options that specify what the cache fetches and retains. + +`maxOffers`, `desiredPrice`, and `desiredVolume` are mutually exclusive. +If none of these are specified, the default is `maxOffers` = `Semibook.DEFAULT_MAX_OFFERS`. + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:137 + +___ + +### BookOptions + +Ƭ **BookOptions**: [`CacheContentsOptions`](Market-1.md#cachecontentsoptions) & { `chunkSize?`: `number` } + +Options that control how the book cache behaves. + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:162 + +___ + +### OfferSlim + +Ƭ **OfferSlim**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `id` | `number` | +| `prev` | `number` \| `undefined` | +| `gasprice` | `number` | +| `maker` | `string` | +| `gasreq` | `number` | +| `wants` | `Big` | +| `gives` | `Big` | +| `volume` | `Big` | +| `price` | `Big` \| `undefined` | + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:169 + +___ + +### Offer + +Ƭ **Offer**: [`OfferSlim`](Market-1.md#offerslim) & { `next`: `number` \| `undefined` ; `offer_gasbase`: `number` } + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:181 + +___ + +### BookSubscriptionCbArgument + +Ƭ **BookSubscriptionCbArgument**: { `ba`: [`BA`](Market-1.md#ba) ; `offerId?`: `number` ; `offer?`: [`Offer`](Market-1.md#offer) } & { `type`: ``"OfferWrite"`` } \| { `type`: ``"OfferFail"`` ; `taker`: `string` ; `takerWants`: `Big` ; `takerGives`: `Big` ; `mgvData`: `string` } \| { `type`: ``"OfferSuccess"`` ; `taker`: `string` ; `takerWants`: `Big` ; `takerGives`: `Big` } \| { `type`: ``"OfferRetract"`` } \| { `type`: ``"SetGasbase"`` } + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:196 + +___ + +### MarketCallback + +Ƭ **MarketCallback**<`T`\>: (`cbArg`: [`BookSubscriptionCbArgument`](Market-1.md#booksubscriptioncbargument), `event?`: [`BookSubscriptionEvent`](Market-1.md#booksubscriptionevent), `ethersLog?`: `ethers.providers.Log`) => `T` \| `Promise`<`T`\> + +#### Type parameters + +| Name | +| :------ | +| `T` | + +#### Type declaration + +▸ (`cbArg`, `event?`, `ethersLog?`): `T` \| `Promise`<`T`\> + +##### Parameters + +| Name | Type | +| :------ | :------ | +| `cbArg` | [`BookSubscriptionCbArgument`](Market-1.md#booksubscriptioncbargument) | +| `event?` | [`BookSubscriptionEvent`](Market-1.md#booksubscriptionevent) | +| `ethersLog?` | `ethers.providers.Log` | + +##### Returns + +`T` \| `Promise`<`T`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:214 + +___ + +### StorableMarketCallback + +Ƭ **StorableMarketCallback**: [`MarketCallback`](Market-1.md#marketcallback)<`any`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:219 + +___ + +### MarketFilter + +Ƭ **MarketFilter**: [`MarketCallback`](Market-1.md#marketcallback)<`boolean`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:220 + +___ + +### SubscriptionParam + +Ƭ **SubscriptionParam**: { `type`: ``"multiple"`` } \| { `type`: ``"once"`` ; `ok`: (...`a`: `any`[]) => `any` ; `ko`: (...`a`: `any`[]) => `any` ; `filter?`: (...`a`: `any`[]) => `boolean` \| `Promise`<`boolean`\> } + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:221 + +___ + +### Book + +Ƭ **Book**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `asks` | [`Semibook`](../classes/Semibook.md) | +| `bids` | [`Semibook`](../classes/Semibook.md) | + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:230 + +___ + +### VolumeEstimate + +Ƭ **VolumeEstimate**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `estimatedVolume` | `Big` | +| `givenResidue` | `Big` | + +#### Defined in + +@mangrovedao/mangrove.js/src/market.ts:232 diff --git a/docs/developers/SDK/technical-references/code/namespaces/MgvToken-1.md b/docs/developers/SDK/technical-references/code/namespaces/MgvToken-1.md new file mode 100644 index 00000000..08010092 --- /dev/null +++ b/docs/developers/SDK/technical-references/code/namespaces/MgvToken-1.md @@ -0,0 +1,25 @@ +--- +id: "MgvToken-1" +title: "Namespace: MgvToken" +sidebar_label: "MgvToken" +sidebar_position: 0 +custom_edit_url: null +--- + +## Type Aliases + +### ConstructorOptions + +Ƭ **ConstructorOptions**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `address?` | `string` | +| `decimals?` | `number` | +| `displayedDecimals?` | `number` | + +#### Defined in + +@mangrovedao/mangrove.js/src/mgvtoken.ts:11 diff --git a/docs/developers/SDK/technical-references/code/namespaces/Semibook-1.md b/docs/developers/SDK/technical-references/code/namespaces/Semibook-1.md new file mode 100644 index 00000000..7ed1a723 --- /dev/null +++ b/docs/developers/SDK/technical-references/code/namespaces/Semibook-1.md @@ -0,0 +1,170 @@ +--- +id: "Semibook-1" +title: "Namespace: Semibook" +sidebar_label: "Semibook" +sidebar_position: 0 +custom_edit_url: null +--- + +## Interfaces + +- [CacheIterator](../interfaces/Semibook-1.CacheIterator.md) + +## Type Aliases + +### Event + +Ƭ **Event**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `cbArg` | [`BookSubscriptionCbArgument`](Market-1.md#booksubscriptioncbargument) | +| `event` | [`BookSubscriptionEvent`](Market-1.md#booksubscriptionevent) | +| `ethersLog` | `ethers.providers.Log` | + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:28 + +___ + +### EventListener + +Ƭ **EventListener**: (`e`: [`Event`](Semibook-1.md#event)) => `Promise`<`void`\> + +#### Type declaration + +▸ (`e`): `Promise`<`void`\> + +##### Parameters + +| Name | Type | +| :------ | :------ | +| `e` | [`Event`](Semibook-1.md#event) | + +##### Returns + +`Promise`<`void`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:34 + +___ + +### BlockListener + +Ƭ **BlockListener**: (`n`: `number`) => `Promise`<`void`\> + +#### Type declaration + +▸ (`n`): `Promise`<`void`\> + +##### Parameters + +| Name | Type | +| :------ | :------ | +| `n` | `number` | + +##### Returns + +`Promise`<`void`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:36 + +___ + +### VolumeParams + +Ƭ **VolumeParams**: `Object` + +Specification of how much volume to (potentially) trade on the semibook. + +`{given:100, to:"buy"}` means buying 100 base tokens. +`{given:100, to:"buy", boundary: 10})` means buying 100 quote tokens for a max. avg. price of 1/10 (boundary/given). + +`{given:10, to:"sell"})` means selling 10 quote tokens. +`{given:10, to:"sell", boundary: 5})` means selling 10 quote tokens for a min. avg. price of 0.5 (given/boundary). + +#### Type declaration + +| Name | Type | Description | +| :------ | :------ | :------ | +| `given` | `Bigish` | Amount of token to trade. | +| `to` | [`BS`](Market-1.md#bs) | Whether `given` is base to be bought or quote to be sold. | +| `boundary?` | `Bigish` | Optional: induce a max avg. price after which to stop buying/selling. | + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:47 + +___ + +### CacheContentsOptions + +Ƭ **CacheContentsOptions**: { `maxOffers?`: `number` } \| { `desiredPrice`: `Bigish` } \| { `desiredVolume`: [`VolumeParams`](Semibook-1.md#volumeparams) } + +Options that specify what the cache fetches and retains. + +`maxOffers`, `desiredPrice`, and `desiredVolume` are mutually exclusive. +If none of these are specified, the default is `maxOffers` = `Semibook.DEFAULT_MAX_OFFERS`. + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:62 + +___ + +### Options + +Ƭ **Options**: [`CacheContentsOptions`](Semibook-1.md#cachecontentsoptions) & { `chunkSize?`: `number` } + +Options that control how the book cache behaves. + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:87 + +___ + +### ResolvedOptions + +Ƭ **ResolvedOptions**: { `maxOffers`: `number` } \| { `desiredPrice`: `Bigish` } \| { `desiredVolume`: [`VolumeParams`](Semibook-1.md#volumeparams) } & { `chunkSize`: `number` } + +Options with defaults resolved + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:97 + +___ + +### State + +Ƭ **State**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `offerCache` | `Map`<`number`, [`Offer`](Market-1.md#offer)\> | +| `bestInCache` | `number` \| `undefined` | +| `worstInCache` | `number` \| `undefined` | + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:146 + +___ + +### FetchOfferListResult + +Ƭ **FetchOfferListResult**: `Result`<[`Offer`](Market-1.md#offer)[], `LogSubscriber.Error`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/semibook.ts:152 diff --git a/docs/developers/SDK/technical-references/code/namespaces/_category_.yml b/docs/developers/SDK/technical-references/code/namespaces/_category_.yml new file mode 100644 index 00000000..1833bbb5 --- /dev/null +++ b/docs/developers/SDK/technical-references/code/namespaces/_category_.yml @@ -0,0 +1,2 @@ +label: "Namespaces" +position: 1 \ No newline at end of file diff --git a/docs/developers/SDK/technical-references/code/namespaces/eth.md b/docs/developers/SDK/technical-references/code/namespaces/eth.md new file mode 100644 index 00000000..636621de --- /dev/null +++ b/docs/developers/SDK/technical-references/code/namespaces/eth.md @@ -0,0 +1,16 @@ +--- +id: "eth" +title: "Namespace: eth" +sidebar_label: "eth" +sidebar_position: 0 +custom_edit_url: null +--- + +## Interfaces + +- [CreateSignerOptions](../interfaces/eth.CreateSignerOptions.md) +- [ProviderNetwork](../interfaces/eth.ProviderNetwork.md) + +## Classes + +- [Mnemonic](../classes/eth.Mnemonic.md) diff --git a/docs/developers/SDK/technical-references/code/namespaces/mgvTestUtil.md b/docs/developers/SDK/technical-references/code/namespaces/mgvTestUtil.md new file mode 100644 index 00000000..be86c919 --- /dev/null +++ b/docs/developers/SDK/technical-references/code/namespaces/mgvTestUtil.md @@ -0,0 +1,602 @@ +--- +id: "mgvTestUtil" +title: "Namespace: mgvTestUtil" +sidebar_label: "mgvTestUtil" +sidebar_position: 0 +custom_edit_url: null +--- + +## Enumerations + +- [AccountName](../enums/mgvTestUtil.AccountName.md) + +## Type Aliases + +### Account + +Ƭ **Account**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `name` | `string` | +| `address` | `string` | +| `signer` | `ethers.Signer` | +| `connectedContracts` | { `mangrove`: `typechain.Mangrove` ; `testMaker`: `typechain.SimpleTestMaker` ; `tokenA`: `typechain.TestToken` ; `tokenB`: `typechain.TestToken` } | +| `connectedContracts.mangrove` | `typechain.Mangrove` | +| `connectedContracts.testMaker` | `typechain.SimpleTestMaker` | +| `connectedContracts.tokenA` | `typechain.TestToken` | +| `connectedContracts.tokenB` | `typechain.TestToken` | + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:10 + +___ + +### Balances + +Ƭ **Balances**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `ether` | `ethers.BigNumber` | +| `tokenA` | `ethers.BigNumber` | +| `tokenB` | `ethers.BigNumber` | + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:23 + +___ + +### AddressAndSigner + +Ƭ **AddressAndSigner**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `address` | `string` | +| `signer` | `string` | + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:31 + +___ + +### Addresses + +Ƭ **Addresses**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `mangrove` | [`AddressAndSigner`](mgvTestUtil.md#addressandsigner) | +| `testMaker` | [`AddressAndSigner`](mgvTestUtil.md#addressandsigner) | +| `tokenA` | [`AddressAndSigner`](mgvTestUtil.md#addressandsigner) | +| `tokenB` | [`AddressAndSigner`](mgvTestUtil.md#addressandsigner) | + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:33 + +___ + +### Contracts + +Ƭ **Contracts**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `mangrove` | `typechain.Mangrove` | +| `testMaker` | `typechain.SimpleTestMaker` | +| `tokenA` | `typechain.TestToken` | +| `tokenB` | `typechain.TestToken` | + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:90 + +___ + +### NewOffer + +Ƭ **NewOffer**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `market` | [`Market`](../classes/Market.md) | +| `ba` | [`BA`](Market-1.md#ba) | +| `maker` | [`Account`](mgvTestUtil.md#account) | +| `wants?` | `ethers.BigNumberish` | +| `gives?` | `ethers.BigNumberish` | +| `gasreq?` | `ethers.BigNumberish` | +| `shouldFail?` | `boolean` | +| `shouldReturnData?` | `boolean` | +| `shouldRevert?` | `boolean` | + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:232 + +## Variables + +### bidsAsks + +• `Const` **bidsAsks**: [`BA`](Market-1.md#ba)[] + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:29 + +___ + +### isTrackingPolls + +• **isTrackingPolls**: `boolean` = `false` + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:244 + +___ + +### eventsForLastTxHaveBeenGeneratedPromise + +• **eventsForLastTxHaveBeenGeneratedPromise**: `Promise`<`void`\> + +Await this when you want to wait for all events corresponding to the last sent tx to have been sent. + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:253 + +## Functions + +### setConfig + +▸ **setConfig**(`_mgv`, `accounts`, `_mgvAdmin`): `void` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `_mgv` | [`Mangrove`](../classes/Mangrove.md) | +| `accounts` | `any` | +| `_mgvAdmin` | [`Mangrove`](../classes/Mangrove.md) | + +#### Returns + +`void` + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:52 + +___ + +### getAddresses + +▸ **getAddresses**(): `Promise`<[`Addresses`](mgvTestUtil.md#addresses)\> + +#### Returns + +`Promise`<[`Addresses`](mgvTestUtil.md#addresses)\> + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:64 + +___ + +### logAddresses + +▸ **logAddresses**(): `Promise`<`void`\> + +#### Returns + +`Promise`<`void`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:83 + +___ + +### getContracts + +▸ **getContracts**(`signer`): `Promise`<[`Contracts`](mgvTestUtil.md#contracts)\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `signer` | `Signer` | + +#### Returns + +`Promise`<[`Contracts`](mgvTestUtil.md#contracts)\> + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:97 + +___ + +### getAccount + +▸ **getAccount**(`name`): `Promise`<[`Account`](mgvTestUtil.md#account)\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `name` | [`AccountName`](../enums/mgvTestUtil.AccountName.md) | + +#### Returns + +`Promise`<[`Account`](mgvTestUtil.md#account)\> + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:128 + +___ + +### getAccountBalances + +▸ **getAccountBalances**(`account`, `provider`): `Promise`<[`Balances`](mgvTestUtil.md#balances)\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `account` | [`Account`](mgvTestUtil.md#account) | +| `provider` | `Provider` | + +#### Returns + +`Promise`<[`Balances`](mgvTestUtil.md#balances)\> + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:141 + +___ + +### getBalances + +▸ **getBalances**(`accounts`, `provider`): `Promise`<`Map`<`string`, [`Balances`](mgvTestUtil.md#balances)\>\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `accounts` | [`Account`](mgvTestUtil.md#account)[] | +| `provider` | `Provider` | + +#### Returns + +`Promise`<`Map`<`string`, [`Balances`](mgvTestUtil.md#balances)\>\> + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:152 + +___ + +### logBalances + +▸ **logBalances**(`accounts`, `balancesBefore`, `balancesAfter`): `Promise`<`void`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `accounts` | [`Account`](mgvTestUtil.md#account)[] | +| `balancesBefore` | `Map`<`string`, [`Balances`](mgvTestUtil.md#balances)\> | +| `balancesAfter` | `Map`<`string`, [`Balances`](mgvTestUtil.md#balances)\> | + +#### Returns + +`Promise`<`void`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:163 + +___ + +### getTokens + +▸ **getTokens**(`market`, `ba`): `Object` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `market` | [`Market`](../classes/Market.md) | +| `ba` | [`BA`](Market-1.md#ba) | + +#### Returns + +`Object` + +| Name | Type | +| :------ | :------ | +| `inboundToken` | [`MgvToken`](../classes/MgvToken.md) | +| `outboundToken` | [`MgvToken`](../classes/MgvToken.md) | + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:219 + +___ + +### waitForBlock + +▸ **waitForBlock**(`mgv`, `blockNumber`): `Promise`<`void`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `mgv` | [`Mangrove`](../classes/Mangrove.md) | +| `blockNumber` | `number` | + +#### Returns + +`Promise`<`void`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:257 + +___ + +### initPollOfTransactionTracking + +▸ **initPollOfTransactionTracking**(`provider`): `void` + +Call this to enable tracking of whether the last transaction sent by this library has been mined and polled. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `provider` | `Provider` | + +#### Returns + +`void` + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:296 + +___ + +### stopPollOfTransactionTracking + +▸ **stopPollOfTransactionTracking**(): `void` + +Call this disable tracking of whether the last transaction sent by this library has been mined and polled. + +#### Returns + +`void` + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:306 + +___ + +### waitForTransactions + +▸ **waitForTransactions**(`txPromises`): `Promise`<`TransactionReceipt`[]\> + +Use this to await transactions. In addition to convenience, +it allows us to track when events for the last tx have been generated. +NB: Only works when this is awaited before sending more tx's. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `txPromises` | `PromiseOrValue`<`PromiseOrValue`<`ContractTransaction`\>[]\> | + +#### Returns + +`Promise`<`TransactionReceipt`[]\> + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:317 + +___ + +### waitForOptionalTransaction + +▸ **waitForOptionalTransaction**(`txPromise`): `Promise`<`TransactionReceipt` \| `undefined`\> + +Use this to await transactions or return immediately if promise returns undefined. In addition to convenience, +it allows us to track when events for the last tx have been generated. +NB: Only works when this is awaited before sending more tx's. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `txPromise` | `PromiseOrValue`<`undefined` \| `ContractTransaction`\> | + +#### Returns + +`Promise`<`TransactionReceipt` \| `undefined`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:333 + +___ + +### waitForTransaction + +▸ **waitForTransaction**(`txPromise`): `Promise`<`TransactionReceipt`\> + +Use this to await transactions. In addition to convenience, +it allows us to track when events for the last tx have been generated. +NB: Only works when this is awaited before sending more tx's. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `txPromise` | `PromiseOrValue`<`ContractTransaction`\> | + +#### Returns + +`Promise`<`TransactionReceipt`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:354 + +___ + +### postNewOffer + +▸ **postNewOffer**(`«destructured»`): `Promise`<`TransactionReceipt`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `«destructured»` | [`NewOffer`](mgvTestUtil.md#newoffer) | + +#### Returns + +`Promise`<`TransactionReceipt`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:365 + +___ + +### postNewRevertingOffer + +▸ **postNewRevertingOffer**(`market`, `ba`, `maker`): `Promise`<`TransactionReceipt`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `market` | [`Market`](../classes/Market.md) | +| `ba` | [`BA`](Market-1.md#ba) | +| `maker` | [`Account`](mgvTestUtil.md#account) | + +#### Returns + +`Promise`<`TransactionReceipt`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:407 + +___ + +### postNewSucceedingOffer + +▸ **postNewSucceedingOffer**(`market`, `ba`, `maker`): `Promise`<`TransactionReceipt`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `market` | [`Market`](../classes/Market.md) | +| `ba` | [`BA`](Market-1.md#ba) | +| `maker` | [`Account`](mgvTestUtil.md#account) | + +#### Returns + +`Promise`<`TransactionReceipt`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:422 + +___ + +### postNewFailingOffer + +▸ **postNewFailingOffer**(`market`, `ba`, `maker`): `Promise`<`TransactionReceipt`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `market` | [`Market`](../classes/Market.md) | +| `ba` | [`BA`](Market-1.md#ba) | +| `maker` | [`Account`](mgvTestUtil.md#account) | + +#### Returns + +`Promise`<`TransactionReceipt`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:430 + +___ + +### setMgvGasPrice + +▸ **setMgvGasPrice**(`gasPrice`): `Promise`<`void`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `gasPrice` | `BigNumberish` | + +#### Returns + +`Promise`<`void`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:438 + +___ + +### mint + +▸ **mint**(`token`, `receiver`, `amount`): `Promise`<`void`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `token` | [`MgvToken`](../classes/MgvToken.md) | +| `receiver` | [`Account`](mgvTestUtil.md#account) | +| `amount` | `number` | + +#### Returns + +`Promise`<`void`\> + +#### Defined in + +@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:476 diff --git a/docs/contracts/README.md b/docs/developers/contracts/README.md similarity index 97% rename from docs/contracts/README.md rename to docs/developers/contracts/README.md index c50b8050..32a67298 100644 --- a/docs/contracts/README.md +++ b/docs/developers/contracts/README.md @@ -14,7 +14,7 @@ The order book of Mangrove lists promises to trade, instead of locked commitment * [Governance](./technical-references/governance-parameters/README.md) adjusts Mangrove parameters, sets fees, and opens and closes new markets. > 💡 -> For non technical information about Mangrove, check out the [Concepts](../general.md) section. +> For non technical information about Mangrove, check out the [Concepts](../) section. ## Where do I start? diff --git a/docs/contracts/background/_category_.json b/docs/developers/contracts/background/_category_.json similarity index 100% rename from docs/contracts/background/_category_.json rename to docs/developers/contracts/background/_category_.json diff --git a/docs/contracts/background/offer-maker.md b/docs/developers/contracts/background/offer-maker.md similarity index 96% rename from docs/contracts/background/offer-maker.md rename to docs/developers/contracts/background/offer-maker.md index e43cda2f..86e1daef 100644 --- a/docs/contracts/background/offer-maker.md +++ b/docs/developers/contracts/background/offer-maker.md @@ -7,7 +7,7 @@ sidebar_position: 2 An offer on Mangrove usually points to a contract containing the [offer logic](../technical-references/taking-and-making-offers/reactive-offer/maker-contract.md) and specifies what it is ready to deliver and its price. Offer are stored in [offer lists](../technical-references//taking-and-making-offers/offer-list.md). -![When a reactive Offer is matched, the contract implementing its logic is called by Mangrove](../../../static/img/assets/MakerOffer.png) +![When a reactive Offer is matched, the contract implementing its logic is called by Mangrove](/img/assets/MakerOffer.png) ### Creating & Updating offers diff --git a/docs/contracts/background/offer-taker.md b/docs/developers/contracts/background/offer-taker.md similarity index 100% rename from docs/contracts/background/offer-taker.md rename to docs/developers/contracts/background/offer-taker.md diff --git a/docs/contracts/background/taker-compensation.md b/docs/developers/contracts/background/taker-compensation.md similarity index 100% rename from docs/contracts/background/taker-compensation.md rename to docs/developers/contracts/background/taker-compensation.md diff --git a/docs/contracts/getting-started/_category_.json b/docs/developers/contracts/getting-started/_category_.json similarity index 100% rename from docs/contracts/getting-started/_category_.json rename to docs/developers/contracts/getting-started/_category_.json diff --git a/docs/contracts/guides/_category_.json b/docs/developers/contracts/guides/_category_.json similarity index 100% rename from docs/contracts/guides/_category_.json rename to docs/developers/contracts/guides/_category_.json diff --git a/docs/contracts/technical-references/_category_.json b/docs/developers/contracts/technical-references/_category_.json similarity index 100% rename from docs/contracts/technical-references/_category_.json rename to docs/developers/contracts/technical-references/_category_.json diff --git a/docs/contracts/technical-references/_contract-addresses-raw.md b/docs/developers/contracts/technical-references/_contract-addresses-raw.md similarity index 100% rename from docs/contracts/technical-references/_contract-addresses-raw.md rename to docs/developers/contracts/technical-references/_contract-addresses-raw.md diff --git a/docs/contracts/technical-references/codebase.md b/docs/developers/contracts/technical-references/codebase.md similarity index 100% rename from docs/contracts/technical-references/codebase.md rename to docs/developers/contracts/technical-references/codebase.md diff --git a/docs/contracts/technical-references/contract-addresses.md b/docs/developers/contracts/technical-references/contract-addresses.md similarity index 100% rename from docs/contracts/technical-references/contract-addresses.md rename to docs/developers/contracts/technical-references/contract-addresses.md diff --git a/docs/contracts/technical-references/governance-parameters/README.md b/docs/developers/contracts/technical-references/governance-parameters/README.md similarity index 100% rename from docs/contracts/technical-references/governance-parameters/README.md rename to docs/developers/contracts/technical-references/governance-parameters/README.md diff --git a/docs/contracts/technical-references/governance-parameters/global-variables.md b/docs/developers/contracts/technical-references/governance-parameters/global-variables.md similarity index 100% rename from docs/contracts/technical-references/governance-parameters/global-variables.md rename to docs/developers/contracts/technical-references/governance-parameters/global-variables.md diff --git a/docs/contracts/technical-references/governance-parameters/local-variables.md b/docs/developers/contracts/technical-references/governance-parameters/local-variables.md similarity index 100% rename from docs/contracts/technical-references/governance-parameters/local-variables.md rename to docs/developers/contracts/technical-references/governance-parameters/local-variables.md diff --git a/docs/contracts/technical-references/governance-parameters/mangrove-configuration.md b/docs/developers/contracts/technical-references/governance-parameters/mangrove-configuration.md similarity index 100% rename from docs/contracts/technical-references/governance-parameters/mangrove-configuration.md rename to docs/developers/contracts/technical-references/governance-parameters/mangrove-configuration.md diff --git a/docs/contracts/technical-references/mangrove-core-version.json b/docs/developers/contracts/technical-references/mangrove-core-version.json similarity index 100% rename from docs/contracts/technical-references/mangrove-core-version.json rename to docs/developers/contracts/technical-references/mangrove-core-version.json diff --git a/docs/contracts/technical-references/mangrove-js-version.json b/docs/developers/contracts/technical-references/mangrove-js-version.json similarity index 100% rename from docs/contracts/technical-references/mangrove-js-version.json rename to docs/developers/contracts/technical-references/mangrove-js-version.json diff --git a/docs/contracts/technical-references/overview.md b/docs/developers/contracts/technical-references/overview.md similarity index 96% rename from docs/contracts/technical-references/overview.md rename to docs/developers/contracts/technical-references/overview.md index 26734768..92ffa1fa 100644 --- a/docs/contracts/technical-references/overview.md +++ b/docs/developers/contracts/technical-references/overview.md @@ -8,7 +8,7 @@ sidebar_position: 1 The illustration below depicts a bird's-eye view of the Mangrove ecosystem. The main actors are depicted as well as their most important interactions. -![A bird's-eye view of Mangrove ecosystem.](../../../static/img/assets/contactMap.png) +![A bird's-eye view of Mangrove ecosystem.](/img/assets/contactMap.png) The Mangrove contract is depicted in the middle, with the three most important actors interacting with Mangrove around it: @@ -55,7 +55,7 @@ This allows makers, for instance, to post another offer to redisplay their liqui The diagram below summarizes the call sequence induced by a taker order. Notice that first the `makerExecute` functions is executed for all offers, and only subsequently are the `makerPosthook` functions of the offers executed. -![Mangrove call sequence induced by a taker order](../../../static/img/assets/execution.png) +![Mangrove call sequence induced by a taker order](/img/assets/execution.png) ## Where can I read more? diff --git a/docs/contracts/technical-references/periphery/README.md b/docs/developers/contracts/technical-references/periphery/README.md similarity index 100% rename from docs/contracts/technical-references/periphery/README.md rename to docs/developers/contracts/technical-references/periphery/README.md diff --git a/docs/contracts/technical-references/periphery/cleaner.md b/docs/developers/contracts/technical-references/periphery/cleaner.md similarity index 93% rename from docs/contracts/technical-references/periphery/cleaner.md rename to docs/developers/contracts/technical-references/periphery/cleaner.md index 360c3e29..f64e6fe8 100644 --- a/docs/contracts/technical-references/periphery/cleaner.md +++ b/docs/developers/contracts/technical-references/periphery/cleaner.md @@ -9,7 +9,7 @@ The `MgvCleaner` contract is provided as part of the periphery contracts. Its pu It has a single function `collect`, with the same signature as as the function for [sniping offers](../taking-and-making-offers/taker-order/README.md#offer-sniping); please refer to that page for a detailed account of the arguments. In brief, for a given pair `(outbound_tkn, inbound_tkn)`, it takes an array of offers `targets` and expects all offers to fail or not to execute. If an offer did not fail, `MgvCleaner` will revert. -This contract may be deployed and used as part of running your own [cleaner keeper bot](/docs/keeper-bots/getting-started/run-a-simple-cleaning-bot.md). +This contract may be deployed and used as part of running your own [cleaner keeper bot](../../../keeper-bots/getting-started/run-a-simple-cleaning-bot.md). ```solidity function collect( diff --git a/docs/contracts/technical-references/periphery/oracle.md b/docs/developers/contracts/technical-references/periphery/oracle.md similarity index 100% rename from docs/contracts/technical-references/periphery/oracle.md rename to docs/developers/contracts/technical-references/periphery/oracle.md diff --git a/docs/contracts/technical-references/periphery/reader.md b/docs/developers/contracts/technical-references/periphery/reader.md similarity index 100% rename from docs/contracts/technical-references/periphery/reader.md rename to docs/developers/contracts/technical-references/periphery/reader.md diff --git a/docs/contracts/technical-references/taking-and-making-offers/README.md b/docs/developers/contracts/technical-references/taking-and-making-offers/README.md similarity index 100% rename from docs/contracts/technical-references/taking-and-making-offers/README.md rename to docs/developers/contracts/technical-references/taking-and-making-offers/README.md diff --git a/docs/contracts/technical-references/taking-and-making-offers/offer-list.md b/docs/developers/contracts/technical-references/taking-and-making-offers/offer-list.md similarity index 100% rename from docs/contracts/technical-references/taking-and-making-offers/offer-list.md rename to docs/developers/contracts/technical-references/taking-and-making-offers/offer-list.md diff --git a/docs/contracts/technical-references/taking-and-making-offers/reactive-offer/README.md b/docs/developers/contracts/technical-references/taking-and-making-offers/reactive-offer/README.md similarity index 100% rename from docs/contracts/technical-references/taking-and-making-offers/reactive-offer/README.md rename to docs/developers/contracts/technical-references/taking-and-making-offers/reactive-offer/README.md diff --git a/docs/contracts/technical-references/taking-and-making-offers/reactive-offer/executing-offers.md b/docs/developers/contracts/technical-references/taking-and-making-offers/reactive-offer/executing-offers.md similarity index 100% rename from docs/contracts/technical-references/taking-and-making-offers/reactive-offer/executing-offers.md rename to docs/developers/contracts/technical-references/taking-and-making-offers/reactive-offer/executing-offers.md diff --git a/docs/contracts/technical-references/taking-and-making-offers/reactive-offer/gas-requirement.md b/docs/developers/contracts/technical-references/taking-and-making-offers/reactive-offer/gas-requirement.md similarity index 100% rename from docs/contracts/technical-references/taking-and-making-offers/reactive-offer/gas-requirement.md rename to docs/developers/contracts/technical-references/taking-and-making-offers/reactive-offer/gas-requirement.md diff --git a/docs/contracts/technical-references/taking-and-making-offers/reactive-offer/maker-contract.md b/docs/developers/contracts/technical-references/taking-and-making-offers/reactive-offer/maker-contract.md similarity index 100% rename from docs/contracts/technical-references/taking-and-making-offers/reactive-offer/maker-contract.md rename to docs/developers/contracts/technical-references/taking-and-making-offers/reactive-offer/maker-contract.md diff --git a/docs/contracts/technical-references/taking-and-making-offers/reactive-offer/offer-data-structures.md b/docs/developers/contracts/technical-references/taking-and-making-offers/reactive-offer/offer-data-structures.md similarity index 100% rename from docs/contracts/technical-references/taking-and-making-offers/reactive-offer/offer-data-structures.md rename to docs/developers/contracts/technical-references/taking-and-making-offers/reactive-offer/offer-data-structures.md diff --git a/docs/contracts/technical-references/taking-and-making-offers/reactive-offer/offer-provision.md b/docs/developers/contracts/technical-references/taking-and-making-offers/reactive-offer/offer-provision.md similarity index 100% rename from docs/contracts/technical-references/taking-and-making-offers/reactive-offer/offer-provision.md rename to docs/developers/contracts/technical-references/taking-and-making-offers/reactive-offer/offer-provision.md diff --git a/docs/contracts/technical-references/taking-and-making-offers/taker-order/README.md b/docs/developers/contracts/technical-references/taking-and-making-offers/taker-order/README.md similarity index 100% rename from docs/contracts/technical-references/taking-and-making-offers/taker-order/README.md rename to docs/developers/contracts/technical-references/taking-and-making-offers/taker-order/README.md diff --git a/docs/contracts/technical-references/taking-and-making-offers/taker-order/delegate-takers.md b/docs/developers/contracts/technical-references/taking-and-making-offers/taker-order/delegate-takers.md similarity index 100% rename from docs/contracts/technical-references/taking-and-making-offers/taker-order/delegate-takers.md rename to docs/developers/contracts/technical-references/taking-and-making-offers/taker-order/delegate-takers.md diff --git a/docs/contracts/technical-references/taking-and-making-offers/views-on-offers.md b/docs/developers/contracts/technical-references/taking-and-making-offers/views-on-offers.md similarity index 100% rename from docs/contracts/technical-references/taking-and-making-offers/views-on-offers.md rename to docs/developers/contracts/technical-references/taking-and-making-offers/views-on-offers.md diff --git a/docs/keeper-bots/README.md b/docs/developers/keeper-bots/README.md similarity index 100% rename from docs/keeper-bots/README.md rename to docs/developers/keeper-bots/README.md diff --git a/docs/keeper-bots/background/_category_.json b/docs/developers/keeper-bots/background/_category_.json similarity index 100% rename from docs/keeper-bots/background/_category_.json rename to docs/developers/keeper-bots/background/_category_.json diff --git a/docs/keeper-bots/background/the-role-of-cleaning-bots-in-mangrove.md b/docs/developers/keeper-bots/background/the-role-of-cleaning-bots-in-mangrove.md similarity index 100% rename from docs/keeper-bots/background/the-role-of-cleaning-bots-in-mangrove.md rename to docs/developers/keeper-bots/background/the-role-of-cleaning-bots-in-mangrove.md diff --git a/docs/keeper-bots/background/the-role-of-gas-price-updater-bots-in-mangrove.md b/docs/developers/keeper-bots/background/the-role-of-gas-price-updater-bots-in-mangrove.md similarity index 51% rename from docs/keeper-bots/background/the-role-of-gas-price-updater-bots-in-mangrove.md rename to docs/developers/keeper-bots/background/the-role-of-gas-price-updater-bots-in-mangrove.md index bda69dd9..361d805c 100644 --- a/docs/keeper-bots/background/the-role-of-gas-price-updater-bots-in-mangrove.md +++ b/docs/developers/keeper-bots/background/the-role-of-gas-price-updater-bots-in-mangrove.md @@ -4,7 +4,7 @@ sidebar_position: 2 # The role of gas price updater bots in Mangrove -Mangrove needs the gas price to [determine the remuneration](/contracts/technical-references/taking-and-making-offers/reactive-offer/offer-provision.md#bounty) of takers for removing a failing offer from a list. On chains where the gas price varies, Mangrove [uses](/contracts/technical-references/governance-parameters/global-variables) an [oracle](/contracts/technical-references/periphery/oracle) to get the gas price. +Mangrove needs the gas price to [determine the remuneration](../../contracts/technical-references/taking-and-making-offers/reactive-offer/offer-provision.md#bounty) of takers for removing a failing offer from a list. On chains where the gas price varies, Mangrove [uses](/contracts/technical-references/governance-parameters/global-variables) an [oracle](/contracts/technical-references/periphery/oracle) to get the gas price. The role of the gas price updater bot is simply to push up-to-date gas prices to the oracle contract whenever the gas price changes significantly. diff --git a/docs/keeper-bots/getting-started/_category_.json b/docs/developers/keeper-bots/getting-started/_category_.json similarity index 100% rename from docs/keeper-bots/getting-started/_category_.json rename to docs/developers/keeper-bots/getting-started/_category_.json diff --git a/docs/keeper-bots/getting-started/run-a-simple-cleaning-bot.md b/docs/developers/keeper-bots/getting-started/run-a-simple-cleaning-bot.md similarity index 100% rename from docs/keeper-bots/getting-started/run-a-simple-cleaning-bot.md rename to docs/developers/keeper-bots/getting-started/run-a-simple-cleaning-bot.md diff --git a/docs/keeper-bots/guides/_category_.json b/docs/developers/keeper-bots/guides/_category_.json similarity index 100% rename from docs/keeper-bots/guides/_category_.json rename to docs/developers/keeper-bots/guides/_category_.json diff --git a/docs/keeper-bots/guides/use-delegation-to-borrow-funds-for-cleaning.md b/docs/developers/keeper-bots/guides/use-delegation-to-borrow-funds-for-cleaning.md similarity index 98% rename from docs/keeper-bots/guides/use-delegation-to-borrow-funds-for-cleaning.md rename to docs/developers/keeper-bots/guides/use-delegation-to-borrow-funds-for-cleaning.md index e31a5b23..85608532 100644 --- a/docs/keeper-bots/guides/use-delegation-to-borrow-funds-for-cleaning.md +++ b/docs/developers/keeper-bots/guides/use-delegation-to-borrow-funds-for-cleaning.md @@ -4,7 +4,7 @@ sidebar_position: 2 # Using borrowed funds for cleaning via Mangrove's delegation mechanism -Cleaners can use Mangrove's [delegation mechanism](/docs/contracts/technical-references/taking-and-making-offers/taker-order/delegate-takers.md) to borrow funds for cleaning: Mangrove will allow an account to call `snipesFor` on behalf of a taker that has not approved that account, as long as all sniped offers fail. This enables borrowing of funds from any taker that has approved Mangrove for some token. +Cleaners can use Mangrove's [delegation mechanism](../../contracts/technical-references/taking-and-making-offers/taker-order/delegate-takers.md) to borrow funds for cleaning: Mangrove will allow an account to call `snipesFor` on behalf of a taker that has not approved that account, as long as all sniped offers fail. This enables borrowing of funds from any taker that has approved Mangrove for some token. The Mangrove periphery contract `MgvCleaner` provides a utility method to make this easy: `collectByImpersonation`. The method is identical to the `collect` method except it takes an extra argument, which is the taker to impersonate/borrow funds from. diff --git a/docs/keeper-bots/guides/use-mgvcleaner-to-clean-offers.md b/docs/developers/keeper-bots/guides/use-mgvcleaner-to-clean-offers.md similarity index 97% rename from docs/keeper-bots/guides/use-mgvcleaner-to-clean-offers.md rename to docs/developers/keeper-bots/guides/use-mgvcleaner-to-clean-offers.md index 61b9f7a4..d6e63cb2 100644 --- a/docs/keeper-bots/guides/use-mgvcleaner-to-clean-offers.md +++ b/docs/developers/keeper-bots/guides/use-mgvcleaner-to-clean-offers.md @@ -5,7 +5,7 @@ sidebar_label: Using the MgvCleaner contract to clean failing offers # Using the `MgvCleaner` contract to clean failing offers -Mangrove provides a [cleaner contract](/docs/contracts/technical-references/periphery/cleaner.md) called `MgvCleaner` to ease cleaning. This contract provides a `collect` method that calls [Mangrove.snipes](../../contracts/technical-references/taking-and-making-offers/taker-order/README.md#offer-sniping) (forwarding the parameters unchanged) but will revert if any offer in the `targets` array succeed. Thus, cleaning via the cleaner contract guards you from offers unexpectedly succeeding when you try to snipe them to collect a bounty. +Mangrove provides a [cleaner contract](../../contracts/technical-references/periphery/cleaner.md) called `MgvCleaner` to ease cleaning. This contract provides a `collect` method that calls [Mangrove.snipes](../../contracts/technical-references/taking-and-making-offers/taker-order/README.md#offer-sniping) (forwarding the parameters unchanged) but will revert if any offer in the `targets` array succeed. Thus, cleaning via the cleaner contract guards you from offers unexpectedly succeeding when you try to snipe them to collect a bounty. The prerequisites and steps needed to use the `MgvCleaner.collect` function are: diff --git a/docs/keeper-bots/technical-reference/_category_.json b/docs/developers/keeper-bots/technical-reference/_category_.json similarity index 100% rename from docs/keeper-bots/technical-reference/_category_.json rename to docs/developers/keeper-bots/technical-reference/_category_.json diff --git a/docs/keeper-bots/technical-reference/examples.md b/docs/developers/keeper-bots/technical-reference/examples.md similarity index 100% rename from docs/keeper-bots/technical-reference/examples.md rename to docs/developers/keeper-bots/technical-reference/examples.md diff --git a/docs/strat-lib/README.md b/docs/developers/strat-lib/README.md similarity index 100% rename from docs/strat-lib/README.md rename to docs/developers/strat-lib/README.md diff --git a/docs/strat-lib/background/_category_.json b/docs/developers/strat-lib/background/_category_.json similarity index 100% rename from docs/strat-lib/background/_category_.json rename to docs/developers/strat-lib/background/_category_.json diff --git a/docs/strat-lib/background/offer-maker/_category_.json b/docs/developers/strat-lib/background/offer-maker/_category_.json similarity index 100% rename from docs/strat-lib/background/offer-maker/_category_.json rename to docs/developers/strat-lib/background/offer-maker/_category_.json diff --git a/docs/strat-lib/background/offer-maker/direct.md b/docs/developers/strat-lib/background/offer-maker/direct.md similarity index 96% rename from docs/strat-lib/background/offer-maker/direct.md rename to docs/developers/strat-lib/background/offer-maker/direct.md index 6f9366fd..f3b22576 100644 --- a/docs/strat-lib/background/offer-maker/direct.md +++ b/docs/developers/strat-lib/background/offer-maker/direct.md @@ -18,4 +18,4 @@ Direct does many of the same things as MangroveOffer with a few key differences. MangroveOffer has no implementations of how to post, update or retract an offer. Direct provides default internal implementations for these methods. -![Flow of taking a offer made by Direct](../../../../static/img/assets/Direct.png) +![Flow of taking a offer made by Direct](/img/assets/Direct.png) diff --git a/docs/strat-lib/background/offer-maker/forwarder.md b/docs/developers/strat-lib/background/offer-maker/forwarder.md similarity index 98% rename from docs/strat-lib/background/offer-maker/forwarder.md rename to docs/developers/strat-lib/background/offer-maker/forwarder.md index d5003964..bbbee377 100644 --- a/docs/strat-lib/background/offer-maker/forwarder.md +++ b/docs/developers/strat-lib/background/offer-maker/forwarder.md @@ -23,4 +23,4 @@ Where MangroveOffer has not implementation of posting a new offer, updating offe When posting a new offer, one would usually also fund Mangrove, so that it has enough funds to cover gas and possible bounty. But since it is the Forwarder contract, that is actually doing the posting of the offers and just keeping track of who owns what internally. Then funding Mangrove directly cannot be done, because Mangrove only knows that the Forwarder contract posted the offer, but has no information about who the Forwarder posted on behalf of. Because of this when posting a new offer using Forwarder, it does not require a gasprice, but uses the amount to be funded combined with the gas requirement, to calculate a gas price, that uses all of the funds. This way the offer has enough information, that when an offer is retracted or updated, it can calculated how much provision is left on the offer. -![Flow of taking a offer made by Forwarder](../../../../static/img/assets/Forwarder.png) +![Flow of taking a offer made by Forwarder](/img/assets/Forwarder.png) diff --git a/docs/strat-lib/background/offer-maker/mangrove-offer.md b/docs/developers/strat-lib/background/offer-maker/mangrove-offer.md similarity index 98% rename from docs/strat-lib/background/offer-maker/mangrove-offer.md rename to docs/developers/strat-lib/background/offer-maker/mangrove-offer.md index 60736129..045bb72c 100644 --- a/docs/strat-lib/background/offer-maker/mangrove-offer.md +++ b/docs/developers/strat-lib/background/offer-maker/mangrove-offer.md @@ -59,4 +59,4 @@ Besides MangroveOffer contract giving approvals, the offer makers reserve needs Mangrove has 2 default implementations of MangroveOffer, they can be found here, [Direct](direct.md) and [Forwarder](forwarder.md). -![Flow of taking a offer made by MangroveOffer](../../../../static/img/assets/MangroveOffer.png) +![Flow of taking a offer made by MangroveOffer](/img/assets/MangroveOffer.png) diff --git a/docs/strat-lib/getting-started/_category_.json b/docs/developers/strat-lib/getting-started/_category_.json similarity index 100% rename from docs/strat-lib/getting-started/_category_.json rename to docs/developers/strat-lib/getting-started/_category_.json diff --git a/docs/strat-lib/getting-started/preparation.md b/docs/developers/strat-lib/getting-started/preparation.md similarity index 100% rename from docs/strat-lib/getting-started/preparation.md rename to docs/developers/strat-lib/getting-started/preparation.md diff --git a/docs/strat-lib/getting-started/smart-offer.md b/docs/developers/strat-lib/getting-started/smart-offer.md similarity index 100% rename from docs/strat-lib/getting-started/smart-offer.md rename to docs/developers/strat-lib/getting-started/smart-offer.md diff --git a/docs/strat-lib/guides/DirectHowTo.md b/docs/developers/strat-lib/guides/DirectHowTo.md similarity index 100% rename from docs/strat-lib/guides/DirectHowTo.md rename to docs/developers/strat-lib/guides/DirectHowTo.md diff --git a/docs/strat-lib/guides/HowToDeploy.md b/docs/developers/strat-lib/guides/HowToDeploy.md similarity index 100% rename from docs/strat-lib/guides/HowToDeploy.md rename to docs/developers/strat-lib/guides/HowToDeploy.md diff --git a/docs/strat-lib/guides/HowToImplement.md b/docs/developers/strat-lib/guides/HowToImplement.md similarity index 100% rename from docs/strat-lib/guides/HowToImplement.md rename to docs/developers/strat-lib/guides/HowToImplement.md diff --git a/docs/strat-lib/guides/HowToTest.md b/docs/developers/strat-lib/guides/HowToTest.md similarity index 100% rename from docs/strat-lib/guides/HowToTest.md rename to docs/developers/strat-lib/guides/HowToTest.md diff --git a/docs/strat-lib/guides/_category_.json b/docs/developers/strat-lib/guides/_category_.json similarity index 100% rename from docs/strat-lib/guides/_category_.json rename to docs/developers/strat-lib/guides/_category_.json diff --git a/docs/strat-lib/guides/approvals.md b/docs/developers/strat-lib/guides/approvals.md similarity index 98% rename from docs/strat-lib/guides/approvals.md rename to docs/developers/strat-lib/guides/approvals.md index ce0ff365..13be1797 100644 --- a/docs/strat-lib/guides/approvals.md +++ b/docs/developers/strat-lib/guides/approvals.md @@ -14,7 +14,7 @@ In the following, we shall refer to the diagram depicting an [overview of the ca Refer to [Contracts -> Technical Reference -> Overview](../../contracts/technical-references/overview.md) and the pages linked there for more details on trade execution on Mangrove. -![Mangrove call sequence induced by a taker order](../../../static/img/assets/execution.png) +![Mangrove call sequence induced by a taker order](/img/assets/execution.png) ## Maker approvals diff --git a/docs/strat-lib/guides/howToRenege.md b/docs/developers/strat-lib/guides/howToRenege.md similarity index 100% rename from docs/strat-lib/guides/howToRenege.md rename to docs/developers/strat-lib/guides/howToRenege.md diff --git a/docs/strat-lib/guides/howToResidual.md b/docs/developers/strat-lib/guides/howToResidual.md similarity index 100% rename from docs/strat-lib/guides/howToResidual.md rename to docs/developers/strat-lib/guides/howToResidual.md diff --git a/docs/strat-lib/guides/howToSnipe.md b/docs/developers/strat-lib/guides/howToSnipe.md similarity index 100% rename from docs/strat-lib/guides/howToSnipe.md rename to docs/developers/strat-lib/guides/howToSnipe.md diff --git a/docs/strat-lib/guides/howToUnlockLiquidity.md b/docs/developers/strat-lib/guides/howToUnlockLiquidity.md similarity index 98% rename from docs/strat-lib/guides/howToUnlockLiquidity.md rename to docs/developers/strat-lib/guides/howToUnlockLiquidity.md index 6822ce7b..99a5ff82 100644 --- a/docs/strat-lib/guides/howToUnlockLiquidity.md +++ b/docs/developers/strat-lib/guides/howToUnlockLiquidity.md @@ -9,7 +9,7 @@ sidebar_position: 1 In the previous [smart offer tutorial](../getting-started/smart-offer.md), the offer we posted had to receive a transfer liquidity for it to succeed when taken. Now, we want instead to post the offer without transferring tokens from the admin to Mangrove or the `OfferMakerTutorial` (unlocked or %%reactive liquidity|reactive-liquidity%%). This way, the tokens are pulled just-in-time when the offer is taken and can thus be made available for other purposes (ex: generating extra yield in another DeFi protocol). :::info Note -Since you are not committing your liquidity to your smart offer, you can post multiple offers with "unlocked liquidity". We call that [liquidity amplification](../../terms/amplified-liquidity.md). +Since you are not committing your liquidity to your smart offer, you can post multiple offers with "unlocked liquidity". We call that [liquidity amplification](../../../terms/amplified-liquidity.md). ::: For this to work, we use a so-called %%router|router%%: it is a contract that can be used to route tokens from the admin to the `OfferMakerTutorial` when the offer is taken.
diff --git a/docs/strat-lib/guides/howtoGasreq.md b/docs/developers/strat-lib/guides/howtoGasreq.md similarity index 100% rename from docs/strat-lib/guides/howtoGasreq.md rename to docs/developers/strat-lib/guides/howtoGasreq.md diff --git a/docs/strat-lib/technical-references/_category_.json b/docs/developers/strat-lib/technical-references/_category_.json similarity index 100% rename from docs/strat-lib/technical-references/_category_.json rename to docs/developers/strat-lib/technical-references/_category_.json diff --git a/docs/strat-lib/technical-references/code/IERC20.md b/docs/developers/strat-lib/technical-references/code/IERC20.md similarity index 100% rename from docs/strat-lib/technical-references/code/IERC20.md rename to docs/developers/strat-lib/technical-references/code/IERC20.md diff --git a/docs/strat-lib/technical-references/code/_category_.json b/docs/developers/strat-lib/technical-references/code/_category_.json similarity index 100% rename from docs/strat-lib/technical-references/code/_category_.json rename to docs/developers/strat-lib/technical-references/code/_category_.json diff --git a/docs/strat-lib/technical-references/code/strategies/MangroveOffer.md b/docs/developers/strat-lib/technical-references/code/strategies/MangroveOffer.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/MangroveOffer.md rename to docs/developers/strat-lib/technical-references/code/strategies/MangroveOffer.md diff --git a/docs/strat-lib/technical-references/code/strategies/MangroveOrder.md b/docs/developers/strat-lib/technical-references/code/strategies/MangroveOrder.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/MangroveOrder.md rename to docs/developers/strat-lib/technical-references/code/strategies/MangroveOrder.md diff --git a/docs/strat-lib/technical-references/code/strategies/integrations/AaveV2Module.md b/docs/developers/strat-lib/technical-references/code/strategies/integrations/AaveV2Module.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/integrations/AaveV2Module.md rename to docs/developers/strat-lib/technical-references/code/strategies/integrations/AaveV2Module.md diff --git a/docs/strat-lib/technical-references/code/strategies/integrations/AaveV3Borrower.md b/docs/developers/strat-lib/technical-references/code/strategies/integrations/AaveV3Borrower.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/integrations/AaveV3Borrower.md rename to docs/developers/strat-lib/technical-references/code/strategies/integrations/AaveV3Borrower.md diff --git a/docs/strat-lib/technical-references/code/strategies/integrations/AaveV3BorrowerImplementation.md b/docs/developers/strat-lib/technical-references/code/strategies/integrations/AaveV3BorrowerImplementation.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/integrations/AaveV3BorrowerImplementation.md rename to docs/developers/strat-lib/technical-references/code/strategies/integrations/AaveV3BorrowerImplementation.md diff --git a/docs/strat-lib/technical-references/code/strategies/integrations/AaveV3BorrowerStorage.md b/docs/developers/strat-lib/technical-references/code/strategies/integrations/AaveV3BorrowerStorage.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/integrations/AaveV3BorrowerStorage.md rename to docs/developers/strat-lib/technical-references/code/strategies/integrations/AaveV3BorrowerStorage.md diff --git a/docs/strat-lib/technical-references/code/strategies/integrations/AaveV3Lender.md b/docs/developers/strat-lib/technical-references/code/strategies/integrations/AaveV3Lender.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/integrations/AaveV3Lender.md rename to docs/developers/strat-lib/technical-references/code/strategies/integrations/AaveV3Lender.md diff --git a/docs/strat-lib/technical-references/code/strategies/integrations/CompoundModule.md b/docs/developers/strat-lib/technical-references/code/strategies/integrations/CompoundModule.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/integrations/CompoundModule.md rename to docs/developers/strat-lib/technical-references/code/strategies/integrations/CompoundModule.md diff --git a/docs/strat-lib/technical-references/code/strategies/interfaces/IForwarder.md b/docs/developers/strat-lib/technical-references/code/strategies/interfaces/IForwarder.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/interfaces/IForwarder.md rename to docs/developers/strat-lib/technical-references/code/strategies/interfaces/IForwarder.md diff --git a/docs/strat-lib/technical-references/code/strategies/interfaces/ILiquidityProvider.md b/docs/developers/strat-lib/technical-references/code/strategies/interfaces/ILiquidityProvider.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/interfaces/ILiquidityProvider.md rename to docs/developers/strat-lib/technical-references/code/strategies/interfaces/ILiquidityProvider.md diff --git a/docs/strat-lib/technical-references/code/strategies/interfaces/IOfferLogic.md b/docs/developers/strat-lib/technical-references/code/strategies/interfaces/IOfferLogic.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/interfaces/IOfferLogic.md rename to docs/developers/strat-lib/technical-references/code/strategies/interfaces/IOfferLogic.md diff --git a/docs/strat-lib/technical-references/code/strategies/interfaces/IOrderLogic.md b/docs/developers/strat-lib/technical-references/code/strategies/interfaces/IOrderLogic.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/interfaces/IOrderLogic.md rename to docs/developers/strat-lib/technical-references/code/strategies/interfaces/IOrderLogic.md diff --git a/docs/strat-lib/technical-references/code/strategies/offer_forwarder/OfferForwarder.md b/docs/developers/strat-lib/technical-references/code/strategies/offer_forwarder/OfferForwarder.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/offer_forwarder/OfferForwarder.md rename to docs/developers/strat-lib/technical-references/code/strategies/offer_forwarder/OfferForwarder.md diff --git a/docs/strat-lib/technical-references/code/strategies/offer_forwarder/abstract/Forwarder.md b/docs/developers/strat-lib/technical-references/code/strategies/offer_forwarder/abstract/Forwarder.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/offer_forwarder/abstract/Forwarder.md rename to docs/developers/strat-lib/technical-references/code/strategies/offer_forwarder/abstract/Forwarder.md diff --git a/docs/strat-lib/technical-references/code/strategies/offer_maker/AaveMaker.md b/docs/developers/strat-lib/technical-references/code/strategies/offer_maker/AaveMaker.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/offer_maker/AaveMaker.md rename to docs/developers/strat-lib/technical-references/code/strategies/offer_maker/AaveMaker.md diff --git a/docs/strat-lib/technical-references/code/strategies/offer_maker/OfferMaker.md b/docs/developers/strat-lib/technical-references/code/strategies/offer_maker/OfferMaker.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/offer_maker/OfferMaker.md rename to docs/developers/strat-lib/technical-references/code/strategies/offer_maker/OfferMaker.md diff --git a/docs/strat-lib/technical-references/code/strategies/offer_maker/abstract/Direct.md b/docs/developers/strat-lib/technical-references/code/strategies/offer_maker/abstract/Direct.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/offer_maker/abstract/Direct.md rename to docs/developers/strat-lib/technical-references/code/strategies/offer_maker/abstract/Direct.md diff --git a/docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/AaveKandel.md b/docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/AaveKandel.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/AaveKandel.md rename to docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/AaveKandel.md diff --git a/docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/AaveKandelSeeder.md b/docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/AaveKandelSeeder.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/AaveKandelSeeder.md rename to docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/AaveKandelSeeder.md diff --git a/docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/Kandel.md b/docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/Kandel.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/Kandel.md rename to docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/Kandel.md diff --git a/docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/KandelSeeder.md b/docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/KandelSeeder.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/KandelSeeder.md rename to docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/KandelSeeder.md diff --git a/docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/AbstractKandel.md b/docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/AbstractKandel.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/AbstractKandel.md rename to docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/AbstractKandel.md diff --git a/docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/AbstractKandelSeeder.md b/docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/AbstractKandelSeeder.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/AbstractKandelSeeder.md rename to docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/AbstractKandelSeeder.md diff --git a/docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/CoreKandel.md b/docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/CoreKandel.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/CoreKandel.md rename to docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/CoreKandel.md diff --git a/docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/DirectWithBidsAndAsksDistribution.md b/docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/DirectWithBidsAndAsksDistribution.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/DirectWithBidsAndAsksDistribution.md rename to docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/DirectWithBidsAndAsksDistribution.md diff --git a/docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/GeometricKandel.md b/docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/GeometricKandel.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/GeometricKandel.md rename to docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/GeometricKandel.md diff --git a/docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/HasIndexedBidsAndAsks.md b/docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/HasIndexedBidsAndAsks.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/HasIndexedBidsAndAsks.md rename to docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/HasIndexedBidsAndAsks.md diff --git a/docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/TradesBaseQuotePair.md b/docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/TradesBaseQuotePair.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/TradesBaseQuotePair.md rename to docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/kandel/abstract/TradesBaseQuotePair.md diff --git a/docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/mango/Mango.md b/docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/mango/Mango.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/mango/Mango.md rename to docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/mango/Mango.md diff --git a/docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/mango/MangoImplementation.md b/docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/mango/MangoImplementation.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/mango/MangoImplementation.md rename to docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/mango/MangoImplementation.md diff --git a/docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/mango/MangoStorage.md b/docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/mango/MangoStorage.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/offer_maker/market_making/mango/MangoStorage.md rename to docs/developers/strat-lib/technical-references/code/strategies/offer_maker/market_making/mango/MangoStorage.md diff --git a/docs/strat-lib/technical-references/code/strategies/routers/AbstractRouter.md b/docs/developers/strat-lib/technical-references/code/strategies/routers/AbstractRouter.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/routers/AbstractRouter.md rename to docs/developers/strat-lib/technical-references/code/strategies/routers/AbstractRouter.md diff --git a/docs/strat-lib/technical-references/code/strategies/routers/SimpleRouter.md b/docs/developers/strat-lib/technical-references/code/strategies/routers/SimpleRouter.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/routers/SimpleRouter.md rename to docs/developers/strat-lib/technical-references/code/strategies/routers/SimpleRouter.md diff --git a/docs/strat-lib/technical-references/code/strategies/routers/integrations/AavePooledRouter.md b/docs/developers/strat-lib/technical-references/code/strategies/routers/integrations/AavePooledRouter.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/routers/integrations/AavePooledRouter.md rename to docs/developers/strat-lib/technical-references/code/strategies/routers/integrations/AavePooledRouter.md diff --git a/docs/strat-lib/technical-references/code/strategies/routers/integrations/HasAaveBalanceMemoizer.md b/docs/developers/strat-lib/technical-references/code/strategies/routers/integrations/HasAaveBalanceMemoizer.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/routers/integrations/HasAaveBalanceMemoizer.md rename to docs/developers/strat-lib/technical-references/code/strategies/routers/integrations/HasAaveBalanceMemoizer.md diff --git a/docs/strat-lib/technical-references/code/strategies/utils/AccessControlled.md b/docs/developers/strat-lib/technical-references/code/strategies/utils/AccessControlled.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/utils/AccessControlled.md rename to docs/developers/strat-lib/technical-references/code/strategies/utils/AccessControlled.md diff --git a/docs/strat-lib/technical-references/code/strategies/utils/TransferLib.md b/docs/developers/strat-lib/technical-references/code/strategies/utils/TransferLib.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/utils/TransferLib.md rename to docs/developers/strat-lib/technical-references/code/strategies/utils/TransferLib.md diff --git a/docs/strat-lib/technical-references/code/strategies/vendor/aave/v2/DataTypes.md b/docs/developers/strat-lib/technical-references/code/strategies/vendor/aave/v2/DataTypes.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/vendor/aave/v2/DataTypes.md rename to docs/developers/strat-lib/technical-references/code/strategies/vendor/aave/v2/DataTypes.md diff --git a/docs/strat-lib/technical-references/code/strategies/vendor/aave/v2/ILendingPool.md b/docs/developers/strat-lib/technical-references/code/strategies/vendor/aave/v2/ILendingPool.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/vendor/aave/v2/ILendingPool.md rename to docs/developers/strat-lib/technical-references/code/strategies/vendor/aave/v2/ILendingPool.md diff --git a/docs/strat-lib/technical-references/code/strategies/vendor/aave/v2/ILendingPoolAddressesProvider.md b/docs/developers/strat-lib/technical-references/code/strategies/vendor/aave/v2/ILendingPoolAddressesProvider.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/vendor/aave/v2/ILendingPoolAddressesProvider.md rename to docs/developers/strat-lib/technical-references/code/strategies/vendor/aave/v2/ILendingPoolAddressesProvider.md diff --git a/docs/strat-lib/technical-references/code/strategies/vendor/aave/v2/IPriceOracleGetter.md b/docs/developers/strat-lib/technical-references/code/strategies/vendor/aave/v2/IPriceOracleGetter.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/vendor/aave/v2/IPriceOracleGetter.md rename to docs/developers/strat-lib/technical-references/code/strategies/vendor/aave/v2/IPriceOracleGetter.md diff --git a/docs/strat-lib/technical-references/code/strategies/vendor/aave/v3/DataTypes.md b/docs/developers/strat-lib/technical-references/code/strategies/vendor/aave/v3/DataTypes.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/vendor/aave/v3/DataTypes.md rename to docs/developers/strat-lib/technical-references/code/strategies/vendor/aave/v3/DataTypes.md diff --git a/docs/strat-lib/technical-references/code/strategies/vendor/aave/v3/Errors.md b/docs/developers/strat-lib/technical-references/code/strategies/vendor/aave/v3/Errors.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/vendor/aave/v3/Errors.md rename to docs/developers/strat-lib/technical-references/code/strategies/vendor/aave/v3/Errors.md diff --git a/docs/strat-lib/technical-references/code/strategies/vendor/aave/v3/IATokenIsh.md b/docs/developers/strat-lib/technical-references/code/strategies/vendor/aave/v3/IATokenIsh.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/vendor/aave/v3/IATokenIsh.md rename to docs/developers/strat-lib/technical-references/code/strategies/vendor/aave/v3/IATokenIsh.md diff --git a/docs/strat-lib/technical-references/code/strategies/vendor/aave/v3/ICreditDelegationToken.md b/docs/developers/strat-lib/technical-references/code/strategies/vendor/aave/v3/ICreditDelegationToken.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/vendor/aave/v3/ICreditDelegationToken.md rename to docs/developers/strat-lib/technical-references/code/strategies/vendor/aave/v3/ICreditDelegationToken.md diff --git a/docs/strat-lib/technical-references/code/strategies/vendor/aave/v3/IPool.md b/docs/developers/strat-lib/technical-references/code/strategies/vendor/aave/v3/IPool.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/vendor/aave/v3/IPool.md rename to docs/developers/strat-lib/technical-references/code/strategies/vendor/aave/v3/IPool.md diff --git a/docs/strat-lib/technical-references/code/strategies/vendor/aave/v3/IPoolAddressesProvider.md b/docs/developers/strat-lib/technical-references/code/strategies/vendor/aave/v3/IPoolAddressesProvider.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/vendor/aave/v3/IPoolAddressesProvider.md rename to docs/developers/strat-lib/technical-references/code/strategies/vendor/aave/v3/IPoolAddressesProvider.md diff --git a/docs/strat-lib/technical-references/code/strategies/vendor/aave/v3/IPriceOracleGetter.md b/docs/developers/strat-lib/technical-references/code/strategies/vendor/aave/v3/IPriceOracleGetter.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/vendor/aave/v3/IPriceOracleGetter.md rename to docs/developers/strat-lib/technical-references/code/strategies/vendor/aave/v3/IPriceOracleGetter.md diff --git a/docs/strat-lib/technical-references/code/strategies/vendor/aave/v3/IRewardsControllerIsh.md b/docs/developers/strat-lib/technical-references/code/strategies/vendor/aave/v3/IRewardsControllerIsh.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/vendor/aave/v3/IRewardsControllerIsh.md rename to docs/developers/strat-lib/technical-references/code/strategies/vendor/aave/v3/IRewardsControllerIsh.md diff --git a/docs/strat-lib/technical-references/code/strategies/vendor/aave/v3/ReserveConfiguration.md b/docs/developers/strat-lib/technical-references/code/strategies/vendor/aave/v3/ReserveConfiguration.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/vendor/aave/v3/ReserveConfiguration.md rename to docs/developers/strat-lib/technical-references/code/strategies/vendor/aave/v3/ReserveConfiguration.md diff --git a/docs/strat-lib/technical-references/code/strategies/vendor/compound/CarefulMath.md b/docs/developers/strat-lib/technical-references/code/strategies/vendor/compound/CarefulMath.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/vendor/compound/CarefulMath.md rename to docs/developers/strat-lib/technical-references/code/strategies/vendor/compound/CarefulMath.md diff --git a/docs/strat-lib/technical-references/code/strategies/vendor/compound/Exponential.md b/docs/developers/strat-lib/technical-references/code/strategies/vendor/compound/Exponential.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/vendor/compound/Exponential.md rename to docs/developers/strat-lib/technical-references/code/strategies/vendor/compound/Exponential.md diff --git a/docs/strat-lib/technical-references/code/strategies/vendor/compound/ExponentialNoError.md b/docs/developers/strat-lib/technical-references/code/strategies/vendor/compound/ExponentialNoError.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/vendor/compound/ExponentialNoError.md rename to docs/developers/strat-lib/technical-references/code/strategies/vendor/compound/ExponentialNoError.md diff --git a/docs/strat-lib/technical-references/code/strategies/vendor/compound/ICompound.md b/docs/developers/strat-lib/technical-references/code/strategies/vendor/compound/ICompound.md similarity index 100% rename from docs/strat-lib/technical-references/code/strategies/vendor/compound/ICompound.md rename to docs/developers/strat-lib/technical-references/code/strategies/vendor/compound/ICompound.md diff --git a/docs/strat-lib/technical-references/code/toy/ERC20.md b/docs/developers/strat-lib/technical-references/code/toy/ERC20.md similarity index 100% rename from docs/strat-lib/technical-references/code/toy/ERC20.md rename to docs/developers/strat-lib/technical-references/code/toy/ERC20.md diff --git a/docs/strat-lib/technical-references/code/toy/ERC20BL.md b/docs/developers/strat-lib/technical-references/code/toy/ERC20BL.md similarity index 100% rename from docs/strat-lib/technical-references/code/toy/ERC20BL.md rename to docs/developers/strat-lib/technical-references/code/toy/ERC20BL.md diff --git a/docs/strat-lib/technical-references/code/toy/ERC20Lib.md b/docs/developers/strat-lib/technical-references/code/toy/ERC20Lib.md similarity index 100% rename from docs/strat-lib/technical-references/code/toy/ERC20Lib.md rename to docs/developers/strat-lib/technical-references/code/toy/ERC20Lib.md diff --git a/docs/strat-lib/technical-references/code/toy/MintableERC20BLWithDecimals.md b/docs/developers/strat-lib/technical-references/code/toy/MintableERC20BLWithDecimals.md similarity index 100% rename from docs/strat-lib/technical-references/code/toy/MintableERC20BLWithDecimals.md rename to docs/developers/strat-lib/technical-references/code/toy/MintableERC20BLWithDecimals.md diff --git a/docs/strat-lib/technical-references/code/toy/PixieMATIC.md b/docs/developers/strat-lib/technical-references/code/toy/PixieMATIC.md similarity index 100% rename from docs/strat-lib/technical-references/code/toy/PixieMATIC.md rename to docs/developers/strat-lib/technical-references/code/toy/PixieMATIC.md diff --git a/docs/strat-lib/technical-references/code/toy/PixieUSDC.md b/docs/developers/strat-lib/technical-references/code/toy/PixieUSDC.md similarity index 100% rename from docs/strat-lib/technical-references/code/toy/PixieUSDC.md rename to docs/developers/strat-lib/technical-references/code/toy/PixieUSDC.md diff --git a/docs/strat-lib/technical-references/main-hooks.md b/docs/developers/strat-lib/technical-references/main-hooks.md similarity index 100% rename from docs/strat-lib/technical-references/main-hooks.md rename to docs/developers/strat-lib/technical-references/main-hooks.md diff --git a/docs/strat-lib/technical-references/router.md b/docs/developers/strat-lib/technical-references/router.md similarity index 100% rename from docs/strat-lib/technical-references/router.md rename to docs/developers/strat-lib/technical-references/router.md diff --git a/sidebars.js b/sidebars.js index b87ce141..d9adf86d 100644 --- a/sidebars.js +++ b/sidebars.js @@ -19,7 +19,7 @@ const sidebars = { { type: 'category', label: 'Getting started', - link: {type: 'doc', id: 'general'}, + link: {type: 'doc', id: 'README'}, items: [ { type: 'category', @@ -82,14 +82,14 @@ const sidebars = { href: 'https://mangrove.exchange/', }, { - type: 'link', - href: '/glossary', + type: 'doc', + id: 'glossary', label: '🔤 Glossary', }, { type: 'link', label: '🏗️ Developers', // The link label - href: '/contracts', + href: '/developers/README', }, ], }, @@ -135,7 +135,7 @@ const sidebars = { developerSidebar: [ { type: 'doc', - id: 'developers', + id: 'developers/README', label: 'Welcome', }, { @@ -144,7 +144,7 @@ const sidebars = { items: [ { type: 'autogenerated', - dirName: 'contracts', + dirName: 'developers/contracts', }, ], }, @@ -154,7 +154,7 @@ const sidebars = { items: [ { type: 'autogenerated', - dirName: 'strat-lib', + dirName: 'developers/strat-lib', }, ], }, @@ -164,7 +164,7 @@ const sidebars = { items: [ { type: 'autogenerated', - dirName: 'SDK', + dirName: 'developers/SDK', }, ], }, @@ -174,14 +174,36 @@ const sidebars = { items: [ { type: 'autogenerated', - dirName: 'keeper-bots', + dirName: 'developers/keeper-bots', }, ], }, { - type: 'doc', - id: 'glossary', - label: 'Glossary', + type: 'category', + label: 'Quick links', + collapsed: false, + items: [ + { + type: 'link', + label: '📃 Whitepaper', // The link label + href: 'https://bafybeig62o75bfxssic66w2zwerbo6ezlhb33vsg5idr4uprckn2dxrucy.ipfs.dweb.link/', + }, + { + type: 'link', + label: '🕸️ Website', // The link label + href: 'https://mangrove.exchange/', + }, + { + type: 'link', + href: '/glossary', + label: '🔤 Glossary', + }, + { + type: 'doc', + label: '🏗️ Developers', + id: 'developers/README', + }, + ], }, ], }; From 2b522422cf516063d2f2e3d96e135d540be28026 Mon Sep 17 00:00:00 2001 From: Troels Damgaard Date: Fri, 13 Oct 2023 12:13:30 +0200 Subject: [PATCH 17/38] fix broken links and move glossary --- docs/FAQ/README.md | 10 +- docs/README.md | 4 +- .../technical-references/code/_category_.yml | 2 - .../code/classes/KandelDistribution.md | 322 ---- .../classes/KandelDistributionGenerator.md | 243 ---- .../code/classes/KandelFarm.md | 97 -- .../code/classes/KandelInstance.md | 1196 --------------- .../code/classes/KandelSeeder.md | 260 ---- .../code/classes/KandelStrategies.md | 130 -- .../code/classes/LiquidityProvider.md | 587 -------- .../code/classes/Mangrove.md | 1292 ----------------- .../code/classes/Market.md | 1202 --------------- .../code/classes/MgvToken.md | 512 ------- .../code/classes/OfferLogic.md | 369 ----- .../code/classes/OfferMaker.md | 36 - .../code/classes/Semibook.md | 807 ---------- .../code/classes/_category_.yml | 2 - .../code/classes/eth.Mnemonic.md | 126 -- .../code/enums/_category_.yml | 2 - .../code/enums/mgvTestUtil.AccountName.md | 48 - docs/SDK/technical-references/code/index.md | 107 -- .../interfaces/Semibook-1.CacheIterator.md | 168 --- .../code/interfaces/_category_.yml | 2 - .../interfaces/eth.CreateSignerOptions.md | 98 -- .../code/interfaces/eth.ProviderNetwork.md | 28 - docs/SDK/technical-references/code/modules.md | 54 - .../code/namespaces/KandelStrategies-1.md | 8 - .../code/namespaces/LiquidityProvider-1.md | 59 - .../code/namespaces/Mangrove-1.md | 161 -- .../code/namespaces/Market-1.BookReturns.md | 38 - .../code/namespaces/Market-1.md | 415 ------ .../code/namespaces/MgvToken-1.md | 25 - .../code/namespaces/Semibook-1.md | 170 --- .../code/namespaces/_category_.yml | 2 - .../code/namespaces/eth.md | 16 - .../code/namespaces/mgvTestUtil.md | 602 -------- .../SDK/getting-started/deploy-kandel.md | 4 +- docs/{ => developers}/glossary.md | 0 .../strat-lib/guides/howToUnlockLiquidity.md | 2 +- .../terms/amplified-liquidity.md | 0 docs/{ => developers}/terms/bounty.md | 0 docs/{ => developers}/terms/cleaning-bot.md | 0 docs/{ => developers}/terms/density.md | 0 docs/{ => developers}/terms/dual-offer.md | 2 +- docs/{ => developers}/terms/gasLimit.md | 0 docs/{ => developers}/terms/gasprice.md | 0 docs/{ => developers}/terms/gasreq.md | 0 docs/{ => developers}/terms/gives.md | 0 docs/{ => developers}/terms/hook.md | 0 docs/{ => developers}/terms/inbound.md | 0 docs/{ => developers}/terms/keeper-bot.md | 0 docs/{ => developers}/terms/last-look.md | 0 docs/{ => developers}/terms/maker-contract.md | 0 .../terms/maker-partial-fill.md | 0 docs/{ => developers}/terms/makerExecute.md | 0 docs/{ => developers}/terms/makerPosthook.md | 0 .../terms/offer-entailed-price.md | 0 docs/{ => developers}/terms/offer-id.md | 0 docs/{ => developers}/terms/offer-list.md | 0 docs/{ => developers}/terms/offer-logic.md | 0 docs/{ => developers}/terms/offer-owner.md | 0 docs/{ => developers}/terms/offer-rank.md | 0 .../terms/on-the-fly-offer.md | 2 +- docs/{ => developers}/terms/outbound.md | 0 docs/{ => developers}/terms/pivot-id.md | 0 docs/{ => developers}/terms/provision.md | 0 .../terms/reactive-liquidity.md | 0 docs/{ => developers}/terms/renege.md | 0 docs/{ => developers}/terms/reserve-id.md | 0 docs/{ => developers}/terms/router.md | 0 docs/{ => developers}/terms/smart-offer.md | 0 docs/{ => developers}/terms/taker-fee.md | 0 docs/{ => developers}/terms/wants.md | 0 docs/high-level/audits.md | 2 +- docs/high-level/concepts/bounty.md | 2 +- .../concepts/makers-takers-keepers/keepers.md | 4 +- .../concepts/makers-takers-keepers/makers.md | 2 +- .../concepts/makers-takers-keepers/takers.md | 6 +- docs/high-level/concepts/smart-offers.md | 2 +- .../details-on-strats/details-on-strats.md | 2 +- .../how-does-kandel-work.md | 2 +- .../more-on-failing-offers.md | 12 +- .../kandel/how-does-kandel-work/parameters.md | 6 +- docs/web-app/strategies/create-strat.md | 2 +- .../strategies/manage-strat/parameters-tab.md | 2 +- .../manage-strat/statuses-and-alerts.md | 2 +- docs/web-app/trade/how-to-limit-order.md | 2 +- docusaurus.config.js | 6 +- sidebars.js | 8 +- 89 files changed, 43 insertions(+), 9229 deletions(-) delete mode 100644 docs/SDK/technical-references/code/_category_.yml delete mode 100644 docs/SDK/technical-references/code/classes/KandelDistribution.md delete mode 100644 docs/SDK/technical-references/code/classes/KandelDistributionGenerator.md delete mode 100644 docs/SDK/technical-references/code/classes/KandelFarm.md delete mode 100644 docs/SDK/technical-references/code/classes/KandelInstance.md delete mode 100644 docs/SDK/technical-references/code/classes/KandelSeeder.md delete mode 100644 docs/SDK/technical-references/code/classes/KandelStrategies.md delete mode 100644 docs/SDK/technical-references/code/classes/LiquidityProvider.md delete mode 100644 docs/SDK/technical-references/code/classes/Mangrove.md delete mode 100644 docs/SDK/technical-references/code/classes/Market.md delete mode 100644 docs/SDK/technical-references/code/classes/MgvToken.md delete mode 100644 docs/SDK/technical-references/code/classes/OfferLogic.md delete mode 100644 docs/SDK/technical-references/code/classes/OfferMaker.md delete mode 100644 docs/SDK/technical-references/code/classes/Semibook.md delete mode 100644 docs/SDK/technical-references/code/classes/_category_.yml delete mode 100644 docs/SDK/technical-references/code/classes/eth.Mnemonic.md delete mode 100644 docs/SDK/technical-references/code/enums/_category_.yml delete mode 100644 docs/SDK/technical-references/code/enums/mgvTestUtil.AccountName.md delete mode 100644 docs/SDK/technical-references/code/index.md delete mode 100644 docs/SDK/technical-references/code/interfaces/Semibook-1.CacheIterator.md delete mode 100644 docs/SDK/technical-references/code/interfaces/_category_.yml delete mode 100644 docs/SDK/technical-references/code/interfaces/eth.CreateSignerOptions.md delete mode 100644 docs/SDK/technical-references/code/interfaces/eth.ProviderNetwork.md delete mode 100644 docs/SDK/technical-references/code/modules.md delete mode 100644 docs/SDK/technical-references/code/namespaces/KandelStrategies-1.md delete mode 100644 docs/SDK/technical-references/code/namespaces/LiquidityProvider-1.md delete mode 100644 docs/SDK/technical-references/code/namespaces/Mangrove-1.md delete mode 100644 docs/SDK/technical-references/code/namespaces/Market-1.BookReturns.md delete mode 100644 docs/SDK/technical-references/code/namespaces/Market-1.md delete mode 100644 docs/SDK/technical-references/code/namespaces/MgvToken-1.md delete mode 100644 docs/SDK/technical-references/code/namespaces/Semibook-1.md delete mode 100644 docs/SDK/technical-references/code/namespaces/_category_.yml delete mode 100644 docs/SDK/technical-references/code/namespaces/eth.md delete mode 100644 docs/SDK/technical-references/code/namespaces/mgvTestUtil.md rename docs/{ => developers}/glossary.md (100%) rename docs/{ => developers}/terms/amplified-liquidity.md (100%) rename docs/{ => developers}/terms/bounty.md (100%) rename docs/{ => developers}/terms/cleaning-bot.md (100%) rename docs/{ => developers}/terms/density.md (100%) rename docs/{ => developers}/terms/dual-offer.md (73%) rename docs/{ => developers}/terms/gasLimit.md (100%) rename docs/{ => developers}/terms/gasprice.md (100%) rename docs/{ => developers}/terms/gasreq.md (100%) rename docs/{ => developers}/terms/gives.md (100%) rename docs/{ => developers}/terms/hook.md (100%) rename docs/{ => developers}/terms/inbound.md (100%) rename docs/{ => developers}/terms/keeper-bot.md (100%) rename docs/{ => developers}/terms/last-look.md (100%) rename docs/{ => developers}/terms/maker-contract.md (100%) rename docs/{ => developers}/terms/maker-partial-fill.md (100%) rename docs/{ => developers}/terms/makerExecute.md (100%) rename docs/{ => developers}/terms/makerPosthook.md (100%) rename docs/{ => developers}/terms/offer-entailed-price.md (100%) rename docs/{ => developers}/terms/offer-id.md (100%) rename docs/{ => developers}/terms/offer-list.md (100%) rename docs/{ => developers}/terms/offer-logic.md (100%) rename docs/{ => developers}/terms/offer-owner.md (100%) rename docs/{ => developers}/terms/offer-rank.md (100%) rename docs/{ => developers}/terms/on-the-fly-offer.md (86%) rename docs/{ => developers}/terms/outbound.md (100%) rename docs/{ => developers}/terms/pivot-id.md (100%) rename docs/{ => developers}/terms/provision.md (100%) rename docs/{ => developers}/terms/reactive-liquidity.md (100%) rename docs/{ => developers}/terms/renege.md (100%) rename docs/{ => developers}/terms/reserve-id.md (100%) rename docs/{ => developers}/terms/router.md (100%) rename docs/{ => developers}/terms/smart-offer.md (100%) rename docs/{ => developers}/terms/taker-fee.md (100%) rename docs/{ => developers}/terms/wants.md (100%) diff --git a/docs/FAQ/README.md b/docs/FAQ/README.md index 141f3238..bc96fb5e 100644 --- a/docs/FAQ/README.md +++ b/docs/FAQ/README.md @@ -11,7 +11,7 @@ sidebar_position: 2 ## Where can I get Mangrove’s addresses? -The deployment addresses for the core contract for Mangrove, as well as the most important periphery contracts are available at [Contracts → Deployment Addresses](../contracts/technical-references/contract-addresses.md). +The deployment addresses for the core contract for Mangrove, as well as the most important periphery contracts are available at [Contracts → Deployment Addresses](../developers/contracts/technical-references/contract-addresses.md).
@@ -20,7 +20,7 @@ The deployment addresses for the core contract for Mangrove, as well as the most Fees on Mangrove are paid by the taker: The fee is taken from the tokens that the taker has bought. -Read more about fees here: [Taker fees](../contracts/technical-references/governance-parameters/local-variables.md#taker-fees). +Read more about fees here: [Taker fees](../developers/contracts/technical-references/governance-parameters/local-variables.md#taker-fees).
@@ -28,7 +28,7 @@ Read more about fees here: [Taker fees](../contracts/technical-references/govern ## Who pays the gas on Mangrove? -If the offer succeeds, the gas costs for the [execution of the trade](../contracts/technical-references/taking-and-making-offers/reactive-offer/executing-offers.md) are paid by the offer taker. If the offer fails the taker is compensated for these gas costs - see [What happens when an offer fails?](#what-happens-when-an-offer-fails) +If the offer succeeds, the gas costs for the [execution of the trade](../developers/contracts/technical-references/taking-and-making-offers/reactive-offer/executing-offers.md) are paid by the offer taker. If the offer fails the taker is compensated for these gas costs - see [What happens when an offer fails?](#what-happens-when-an-offer-fails)
@@ -36,7 +36,7 @@ If the offer succeeds, the gas costs for the [execution of the trade](../contrac ## What happens when an offer fails? -Offers in the order book may fail when taken, either because the maker consciously chose to [renege on the offer to trade](../contracts/background/taker-compensation.md), or because the maker contract reverted for other reasons. In that case, the taker has wasted some gas and will be compensated using the [offer provision](../contracts/technical-references/taking-and-making-offers/reactive-offer/offer-provision.md) (in native token) that the maker has deposited in Mangrove. +Offers in the order book may fail when taken, either because the maker consciously chose to [renege on the offer to trade](../developers/contracts/background/taker-compensation.md), or because the maker contract reverted for other reasons. In that case, the taker has wasted some gas and will be compensated using the [offer provision](../developers/contracts/technical-references/taking-and-making-offers/reactive-offer/offer-provision.md) (in native token) that the maker has deposited in Mangrove.
@@ -44,7 +44,7 @@ Offers in the order book may fail when taken, either because the maker conscious ## Are Mangrove market orders the same as traditional market orders? -Mangrove's [market orders](../contracts/technical-references/taking-and-making-offers/taker-order/README.md) are DeFi market orders - which are different from market orders in TradFi: +Mangrove's [market orders](../developers/contracts/technical-references/taking-and-making-offers/taker-order/README.md) are DeFi market orders - which are different from market orders in TradFi: In TradFi, a market order is an order to buy or sell immediately at the best available price. diff --git a/docs/README.md b/docs/README.md index cc4fd22b..a0475d4f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -13,12 +13,12 @@ It's a Decentralized Exchange (DEX)! On Mangrove, you can trade, swap tokens and ## The orderbook model -Mangrove is based on an "order book" model, which you may know from traditional finance exchanges. However, Mangrove is particular in that it allows liquidity providers to post arbitrary smart contracts as offers. What that means, is that the **listed offers can point to pieces of code**: we call them [Smart Offers](./terms/smart-offer.md). 🤓 +Mangrove is based on an "order book" model, which you may know from traditional finance exchanges. However, Mangrove is particular in that it allows liquidity providers to post arbitrary smart contracts as offers. What that means, is that the **listed offers can point to pieces of code**: we call them [Smart Offers](./developers/terms/smart-offer.md). 🤓 As you can imagine, this new flexibility enables participants to post offers that are not fully provisioned. The Mangrove's order book **lists promises instead of locked commitments**. > 💡 -> There might be new words and concepts for you in here, and that's okay: we will provide you with either direct explanations or links and references. Feel free to check our [Glossary](./glossary.md) and [FAQ](./FAQ/README.md) as well, it might help! +> There might be new words and concepts for you in here, and that's okay: we will provide you with either direct explanations or links and references. Feel free to check our [Glossary](./developers/glossary.md) and [FAQ](./FAQ/README.md) as well, it might help! ## Making promises diff --git a/docs/SDK/technical-references/code/_category_.yml b/docs/SDK/technical-references/code/_category_.yml deleted file mode 100644 index 463a030e..00000000 --- a/docs/SDK/technical-references/code/_category_.yml +++ /dev/null @@ -1,2 +0,0 @@ -label: "API Reference" -position: 999 \ No newline at end of file diff --git a/docs/SDK/technical-references/code/classes/KandelDistribution.md b/docs/SDK/technical-references/code/classes/KandelDistribution.md deleted file mode 100644 index 9d184686..00000000 --- a/docs/SDK/technical-references/code/classes/KandelDistribution.md +++ /dev/null @@ -1,322 +0,0 @@ ---- -id: "KandelDistribution" -title: "Class: KandelDistribution" -sidebar_label: "KandelDistribution" -sidebar_position: 0 -custom_edit_url: null ---- - -**`Title`** - -A distribution of bids and ask for Kandel. - -## Properties - -### offers - -• **offers**: `OfferDistribution` - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:20 - -___ - -### baseDecimals - -• **baseDecimals**: `number` - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:21 - -___ - -### quoteDecimals - -• **quoteDecimals**: `number` - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:22 - -___ - -### ratio - -• **ratio**: `Big` - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:23 - -___ - -### pricePoints - -• **pricePoints**: `number` - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:24 - -___ - -### helper - -• **helper**: `KandelDistributionHelper` - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:25 - -## Constructors - -### constructor - -• **new KandelDistribution**(`ratio`, `pricePoints`, `offers`, `baseDecimals`, `quoteDecimals`) - -Constructor - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `ratio` | `Big` | The ratio used when calculating the price distribution. | -| `pricePoints` | `number` | The number of price points in the distribution. Can be more than the number of offers if a subset is considered. | -| `offers` | `OfferDistribution` | The distribution of bids and asks. | -| `baseDecimals` | `number` | The number of decimals for the base token. | -| `quoteDecimals` | `number` | The number of decimals for the quote token. | - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:34 - -## Methods - -### getOfferCount - -▸ **getOfferCount**(): `number` - -Gets the number of offers in the distribution. This can be lower than the number of price points when a subset is considered. - -#### Returns - -`number` - -The number of offers in the distribution. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:53 - -___ - -### calculateOfferGives - -▸ **calculateOfferGives**(`offerType`, `offerCount`, `totalVolume`): `Big` - -Calculates the gives for a single offer of the given type given the total available volume and the count of offers of that type. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `offerType` | [`BA`](../namespaces/Market-1.md#ba) | The type of offer. | -| `offerCount` | `number` | The count of offers of the given type. | -| `totalVolume` | `Big` | The total available volume. | - -#### Returns - -`Big` - -The amount of base or quote to give for the offer. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:63 - -___ - -### calculateConstantGivesPerOffer - -▸ **calculateConstantGivesPerOffer**(`availableBase?`, `availableQuote?`): `Object` - -Calculates the gives for bids and asks based on the available volume for the distribution. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `availableBase?` | `Big` | The available base to consume. | -| `availableQuote?` | `Big` | The available quote to consume. | - -#### Returns - -`Object` - -The amount of base or quote to give for each offer. - -| Name | Type | -| :------ | :------ | -| `askGives` | `undefined` \| `Big` | -| `bidGives` | `undefined` \| `Big` | - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:90 - -___ - -### getFirstAskIndex - -▸ **getFirstAskIndex**(): `number` - -Gets the index of the first ask in the distribution. If there are no asks, then the length of the distribution is returned. - -#### Returns - -`number` - -The index of the first ask in the distribution; or the length of the distribution if there are no asks. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:110 - -___ - -### getOffersIndexOfFirstAskIndex - -▸ **getOffersIndexOfFirstAskIndex**(): `number` - -Gets the index of the first ask in the subset of offers in offers for the distribution. If there are no asks, then the length of offers is returned. - -#### Returns - -`number` - -The index of the first ask in the subset of offers in offers for the distribution. If there are no asks, then the length of offers is returned. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:119 - -___ - -### chunkDistribution - -▸ **chunkDistribution**(`pivots`, `maxOffersInChunk`): { `pivots`: `number`[] ; `distribution`: `OfferDistribution` }[] - -Split a distribution and its pivots into chunks according to the maximum number of offers in a single chunk. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `pivots` | `number`[] | The pivots for the distribution. | -| `maxOffersInChunk` | `number` | The maximum number of offers in a single chunk. | - -#### Returns - -{ `pivots`: `number`[] ; `distribution`: `OfferDistribution` }[] - -The chunks. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:133 - -___ - -### getPricesForDistribution - -▸ **getPricesForDistribution**(): (`undefined` \| `Big`)[] - -Gets the prices for the distribution, with undefined for prices not represented by offers in the distribution. - -#### Returns - -(`undefined` \| `Big`)[] - -The prices in the distribution. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:174 - -___ - -### getOfferedVolumeForDistribution - -▸ **getOfferedVolumeForDistribution**(): `Object` - -Gets the required volume of base and quote for the distribution to be fully provisioned. - -#### Returns - -`Object` - -The offered volume of base and quote for the distribution to be fully provisioned. - -| Name | Type | -| :------ | :------ | -| `requiredBase` | `Big` | -| `requiredQuote` | `Big` | - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:186 - -___ - -### verifyDistribution - -▸ **verifyDistribution**(): `void` - -Verifies the distribution is valid. - -**`Remarks`** - -Throws if the distribution is invalid. -The verification checks that indices are ascending and bids come before asks. -The price distribution is not verified. - -#### Returns - -`void` - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:208 - -___ - -### getRequiredProvision - -▸ **getRequiredProvision**(`params`): `Promise`<`Big`\> - -Determines the required provision for the listed offers in the distribution (disregarding the number of price points). - -**`Remarks`** - -This takes into account that each of the offers represent a price point which can become both an ask and a bid which both require provision. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters used to calculate the provision. | -| `params.market` | [`Market`](Market.md) | The market to get provisions for bids and asks from. | -| `params.gasreq` | `number` | The gas required to execute a trade. | -| `params.gasprice` | `number` | The gas price to calculate provision for. | - -#### Returns - -`Promise`<`Big`\> - -The provision required for the number of offers. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelDistribution.ts:237 diff --git a/docs/SDK/technical-references/code/classes/KandelDistributionGenerator.md b/docs/SDK/technical-references/code/classes/KandelDistributionGenerator.md deleted file mode 100644 index 5f87bb3c..00000000 --- a/docs/SDK/technical-references/code/classes/KandelDistributionGenerator.md +++ /dev/null @@ -1,243 +0,0 @@ ---- -id: "KandelDistributionGenerator" -title: "Class: KandelDistributionGenerator" -sidebar_label: "KandelDistributionGenerator" -sidebar_position: 0 -custom_edit_url: null ---- - -**`Title`** - -Helper for generating Kandel distributions. - -## Properties - -### distributionHelper - -• **distributionHelper**: `KandelDistributionHelper` - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelDistributionGenerator.ts:14 - -___ - -### priceCalculation - -• **priceCalculation**: `KandelPriceCalculation` - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelDistributionGenerator.ts:15 - -## Constructors - -### constructor - -• **new KandelDistributionGenerator**(`distributionHelper`, `priceCalculation`) - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `distributionHelper` | `KandelDistributionHelper` | -| `priceCalculation` | `KandelPriceCalculation` | - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelDistributionGenerator.ts:17 - -## Methods - -### calculateMinimumDistribution - -▸ **calculateMinimumDistribution**(`params`): [`KandelDistribution`](KandelDistribution.md) - -Calculates a minimal recommended volume distribution of bids and asks and their base and quote amounts to match the geometric price distribution given by parameters. - -**`Remarks`** - -The price distribution may not match the priceDistributionParams exactly due to limited precision. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters for the geometric distribution. | -| `params.priceParams` | `PriceDistributionParams` | The parameters for the geometric price distribution. | -| `params.midPrice` | `BigSource` | The mid-price used to determine when to switch from bids to asks. | -| `params.constantBase?` | `boolean` | Whether the base amount should be constant for all offers. | -| `params.constantQuote?` | `boolean` | Whether the quote amount should be constant for all offers. | -| `params.minimumBasePerOffer` | `BigSource` | The minimum amount of base to give for each offer. Should be at least minimumBasePerOfferFactor from KandelConfiguration multiplied with the minimum volume for the market. | -| `params.minimumQuotePerOffer` | `BigSource` | The minimum amount of quote to give for each offer. Should be at least minimumQuotePerOfferFactor from KandelConfiguration multiplied with the minimum volume for the market. | - -#### Returns - -[`KandelDistribution`](KandelDistribution.md) - -The distribution of bids and asks and their base and quote amounts. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelDistributionGenerator.ts:36 - -___ - -### calculateDistribution - -▸ **calculateDistribution**(`params`): [`KandelDistribution`](KandelDistribution.md) - -Calculates distribution of bids and asks and their base and quote amounts to match the geometric price distribution given by parameters. - -**`Remarks`** - -The price distribution may not match the priceDistributionParams exactly due to limited precision. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters for the geometric distribution. | -| `params.priceParams` | `PriceDistributionParams` | The parameters for the geometric price distribution. | -| `params.midPrice` | `BigSource` | The mid-price used to determine when to switch from bids to asks. | -| `params.initialAskGives?` | `BigSource` | The initial amount of base to give for all asks. Should be at least minimumBasePerOfferFactor from KandelConfiguration multiplied with the minimum volume for the market. If not provided, then initialBidGives is used as quote for asks, and the base the ask gives is set to according to the price. | -| `params.initialBidGives?` | `BigSource` | The initial amount of quote to give for all bids. Should be at least minimumQuotePerOfferFactor from KandelConfiguration multiplied with the minimum volume for the market. If not provided, then initialAskGives is used as base for bids, and the quote the bid gives is set to according to the price. | - -#### Returns - -[`KandelDistribution`](KandelDistribution.md) - -The distribution of bids and asks and their base and quote amounts. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelDistributionGenerator.ts:72 - -___ - -### recalculateDistributionFromAvailable - -▸ **recalculateDistributionFromAvailable**(`params`): [`KandelDistribution`](KandelDistribution.md) - -Recalculates the gives for offers in the distribution such that the available base and quote is consumed uniformly, while preserving the price distribution. - -**`Remarks`** - -The required volume can be slightly less than available due to rounding due to token decimals. -Note that the resulting offered base volume for each offer should be at least minimumBasePerOfferFactor from KandelConfiguration multiplied with the minimum volume for the market - and similar for quote. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters for the recalculation. | -| `params.distribution` | [`KandelDistribution`](KandelDistribution.md) | The distribution to reset the gives for. | -| `params.availableBase?` | `BigSource` | The available base to consume. If not provided, then the quote for bids is also used as quote for asks, and the base the ask gives is set to according to the price. | -| `params.availableQuote?` | `BigSource` | The available quote to consume. If not provided, then the base for asks is also used as base for bids, and the quote the bid gives is set to according to the price. | - -#### Returns - -[`KandelDistribution`](KandelDistribution.md) - -The distribution of bids and asks and their base and quote amounts. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelDistributionGenerator.ts:103 - -___ - -### uniformlyChangeVolume - -▸ **uniformlyChangeVolume**(`params`): `Object` - -Creates a new distribution with uniformly changed volume. - -**`Remarks`** - -The decrease has to respect minimums, and thus may decrease some offers more than others. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters for the change. | -| `params.distribution` | [`KandelDistribution`](KandelDistribution.md) | The distribution to change. | -| `params.baseDelta?` | `BigSource` | The change in base volume. | -| `params.quoteDelta?` | `BigSource` | The change in quote volume. | -| `params.minimumBasePerOffer` | `BigSource` | The minimum amount of base to give for each offer. Should be at least minimumBasePerOfferFactor from KandelConfiguration multiplied with the minimum volume for the market. | -| `params.minimumQuotePerOffer` | `BigSource` | The minimum amount of quote to give for each offer. Should be at least minimumQuotePerOfferFactor from KandelConfiguration multiplied with the minimum volume for the market. | - -#### Returns - -`Object` - -The new distribution. - -| Name | Type | -| :------ | :------ | -| `distribution` | [`KandelDistribution`](KandelDistribution.md) | -| `totalBaseChange` | `Big` | -| `totalQuoteChange` | `Big` | - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelDistributionGenerator.ts:133 - -___ - -### createDistributionWithOffers - -▸ **createDistributionWithOffers**(`params`): [`KandelDistribution`](KandelDistribution.md) - -Creates a distribution based on an explicit set of offers. Either based on an original distribution or parameters for one. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters for the distribution. | -| `params.explicitOffers` | `OffersWithGives` | The explicit offers to use. | -| `params.distribution` | [`KandelDistribution`](KandelDistribution.md) \| { `ratio`: `BigSource` ; `pricePoints`: `number` } | The original distribution or parameters for one. If pricePoints is not provided, then the number of offers is used. | - -#### Returns - -[`KandelDistribution`](KandelDistribution.md) - -The new distribution. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelDistributionGenerator.ts:165 - -___ - -### getMinimumVolumeForIndex - -▸ **getMinimumVolumeForIndex**(`params`): `Big` - -Retrieves the minimum volume for a given offer type at the given index. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters for the minimum volume. | -| `params.offerType` | [`BA`](../namespaces/Market-1.md#ba) | The offer type to get the minimum volume for. | -| `params.index` | `number` | The Kandel index. | -| `params.price` | `BigSource` | The price at the index. | -| `params.ratio` | `BigSource` | The ratio of the geometric progression of prices. | -| `params.spread` | `number` | The spread used when transporting funds from an offer to its dual. | -| `params.pricePoints` | `number` | The number of price points. | -| `params.minimumBasePerOffer` | `BigSource` | The minimum base token volume per offer. If not provided, then the minimum base token volume is used. | -| `params.minimumQuotePerOffer` | `BigSource` | The minimum quote token volume per offer. If not provided, then the minimum quote token volume is used. | - -#### Returns - -`Big` - -The minimum volume for the given offer type and the index. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelDistributionGenerator.ts:199 diff --git a/docs/SDK/technical-references/code/classes/KandelFarm.md b/docs/SDK/technical-references/code/classes/KandelFarm.md deleted file mode 100644 index b883a912..00000000 --- a/docs/SDK/technical-references/code/classes/KandelFarm.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -id: "KandelFarm" -title: "Class: KandelFarm" -sidebar_label: "KandelFarm" -sidebar_position: 0 -custom_edit_url: null ---- - -**`Title`** - -Repository for Kandel instances. - -## Properties - -### mgv - -• **mgv**: [`Mangrove`](Mangrove.md) - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelFarm.ts:11 - -___ - -### tradeEventManagement - -• **tradeEventManagement**: `TradeEventManagement` - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelFarm.ts:12 - -___ - -### aaveKandelSeeder - -• **aaveKandelSeeder**: `AaveKandelSeeder` - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelFarm.ts:14 - -___ - -### kandelSeeder - -• **kandelSeeder**: `KandelSeeder` - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelFarm.ts:15 - -## Constructors - -### constructor - -• **new KandelFarm**(`mgv`) - -Constructor - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `mgv` | [`Mangrove`](Mangrove.md) | The Mangrove to get kandels for. | - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelFarm.ts:20 - -## Methods - -### getKandels - -▸ **getKandels**(`filter?`): `Promise`<{ `kandelAddress`: `string` = x.args.kandel; `ownerAddress`: `string` = x.args.owner; `onAave`: `boolean` = false; `baseAddress`: `string` = baseToken.address; `base`: `undefined` \| [`MgvToken`](MgvToken.md) = baseToken.token; `quoteAddress`: `string` = quoteToken.address; `quote`: `undefined` \| [`MgvToken`](MgvToken.md) = quoteToken.token }[]\> - -Gets all Kandels matching a given filter. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `filter?` | `Object` | The filter to apply. | -| `filter.owner?` | ``null`` \| `PromiseOrValue`<`string`\> | The Kandel instance owner - the one who invoked sow. | -| `filter.base?` | ``null`` \| `PromiseOrValue`<`string`\> | The base token for the Kandel instance. | -| `filter.quote?` | ``null`` \| `PromiseOrValue`<`string`\> | The quote token for the Kandel instance. | -| `filter.onAave?` | `boolean` | Whether the Kandel instance uses the Aave router. | - -#### Returns - -`Promise`<{ `kandelAddress`: `string` = x.args.kandel; `ownerAddress`: `string` = x.args.owner; `onAave`: `boolean` = false; `baseAddress`: `string` = baseToken.address; `base`: `undefined` \| [`MgvToken`](MgvToken.md) = baseToken.token; `quoteAddress`: `string` = quoteToken.address; `quote`: `undefined` \| [`MgvToken`](MgvToken.md) = quoteToken.token }[]\> - -All kandels matching the filter. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelFarm.ts:51 diff --git a/docs/SDK/technical-references/code/classes/KandelInstance.md b/docs/SDK/technical-references/code/classes/KandelInstance.md deleted file mode 100644 index 00f164b4..00000000 --- a/docs/SDK/technical-references/code/classes/KandelInstance.md +++ /dev/null @@ -1,1196 +0,0 @@ ---- -id: "KandelInstance" -title: "Class: KandelInstance" -sidebar_label: "KandelInstance" -sidebar_position: 0 -custom_edit_url: null ---- - -**`Title`** - -Management of a single Kandel instance. - -## Properties - -### kandel - -• **kandel**: `GeometricKandel` - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:53 - -___ - -### address - -• **address**: `string` - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:54 - -___ - -### precision - -• **precision**: `number` - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:55 - -___ - -### market - -• **market**: [`Market`](Market.md) - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:56 - -___ - -### generator - -• **generator**: [`KandelDistributionGenerator`](KandelDistributionGenerator.md) - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:57 - -___ - -### status - -• **status**: `KandelStatus` - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:58 - -___ - -### configuration - -• **configuration**: `KandelConfiguration` - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:59 - -___ - -### seeder - -• **seeder**: [`KandelSeeder`](KandelSeeder.md) - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:60 - -___ - -### offerLogic - -• **offerLogic**: [`OfferLogic`](OfferLogic.md) - -Expose logic relevant for all offer logic implementations, including Kandel. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:63 - -## Methods - -### create - -▸ `Static` **create**(`params`): `Promise`<[`KandelInstance`](KandelInstance.md)\> - -Creates a KandelInstance object to interact with a Kandel strategy on Mangrove. - -**`Dev`** - -If a factory function is provided for the market, then remember to disconnect market when no longer needed. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters used to create an instance. | -| `params.address` | `string` | The address of the Kandel instance. | -| `params.signer` | `Signer` | The signer used to interact with the Kandel instance. | -| `params.market` | [`Market`](Market.md) \| (`baseAddress`: `string`, `quoteAddress`: `string`) => `Promise`<[`Market`](Market.md)\> | The market used by the Kandel instance or a factory function to create the market. | - -#### Returns - -`Promise`<[`KandelInstance`](KandelInstance.md)\> - -A new KandelInstance. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:73 - -___ - -### getBase - -▸ **getBase**(): [`MgvToken`](MgvToken.md) - -Gets the base of the market Kandel is making - -#### Returns - -[`MgvToken`](MgvToken.md) - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:144 - -___ - -### getQuote - -▸ **getQuote**(): [`MgvToken`](MgvToken.md) - -Gets the quote of the market Kandel is making - -#### Returns - -[`MgvToken`](MgvToken.md) - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:149 - -___ - -### getReserveId - -▸ **getReserveId**(): `Promise`<`string`\> - -Retrieves the identifier of this contract's reserve when using a router - -#### Returns - -`Promise`<`string`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:154 - -___ - -### getBalance - -▸ **getBalance**(`offerType`): `Promise`<`Big`\> - -Retrieves the total balance available for this Kandel instance of the offered token for the given offer type. - -**`Remarks`** - -with liquidity sharing and a router, this will be shared among other Kandel instances. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `offerType` | [`BA`](../namespaces/Market-1.md#ba) | The offer type. | - -#### Returns - -`Promise`<`Big`\> - -The balance of the asset. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:163 - -___ - -### getUnpublished - -▸ **getUnpublished**(`offerType`): `Promise`<`Big`\> - -Retrieves the amount of liquidity that is available for the Kandel instance but not offered by the given offer type. - -**`Remarks`** - -with liquidity sharing and a router, the balance will be shared among other Kandel instances and the unpublished can be seen as a buffer. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `offerType` | [`BA`](../namespaces/Market-1.md#ba) | The offer type. | - -#### Returns - -`Promise`<`Big`\> - -the unpublished liquidity. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:173 - -___ - -### getOfferedVolume - -▸ **getOfferedVolume**(`offerType`): `Promise`<`Big`\> - -Retrieves the total offered volume for the offer type for this Kandel instance. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `offerType` | [`BA`](../namespaces/Market-1.md#ba) | The offer type. | - -#### Returns - -`Promise`<`Big`\> - -The offered volume. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:182 - -___ - -### getParameters - -▸ **getParameters**(): `Promise`<`KandelParameters`\> - -Retrieves the current Kandel parameters - -#### Returns - -`Promise`<`KandelParameters`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:188 - -___ - -### getParametersWithOverrides - -▸ **getParametersWithOverrides**(`parameters`, `distributionRatio?`, `distributionPricePoints?`): `Promise`<`KandelParameters`\> - -Gets new Kandel parameters based on current and some overrides. - -**`Remarks`** - -Ratio and price points provided in the parameters must match a provided distribution. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `parameters` | `KandelParameterOverrides` | The Kandel parameters to override, those left out will keep their current value. | -| `distributionRatio?` | `BigSource` | The ratio of the Kandel distribution. | -| `distributionPricePoints?` | `number` | The number of price points of the Kandel distribution. | - -#### Returns - -`Promise`<`KandelParameters`\> - -The new Kandel parameters. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:222 - -___ - -### getOutboundToken - -▸ **getOutboundToken**(`offerType`): [`MgvToken`](MgvToken.md) - -Gets the outbound token for bids/asks. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `offerType` | [`BA`](../namespaces/Market-1.md#ba) | The bid/ask identifier. | - -#### Returns - -[`MgvToken`](MgvToken.md) - -The outbound token. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:290 - -___ - -### getOfferIdAtIndex - -▸ **getOfferIdAtIndex**(`offerType`, `index`): `Promise`<`number`\> - -Gets the Mangrove offer id for a Kandel index. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `offerType` | [`BA`](../namespaces/Market-1.md#ba) | The bid/ask identifier. | -| `index` | `number` | The Kandel index. | - -#### Returns - -`Promise`<`number`\> - -The Mangrove offer id. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:299 - -___ - -### getIndexOfOfferId - -▸ **getIndexOfOfferId**(`offerType`, `offerId`): `Promise`<`number`\> - -Gets the Kandel index for a Mangrove offer id. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `offerType` | [`BA`](../namespaces/Market-1.md#ba) | The bid/ask identifier. | -| `offerId` | `number` | The Mangrove offer id. | - -#### Returns - -`Promise`<`number`\> - -The Kandel index. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:310 - -___ - -### getPivots - -▸ **getPivots**(`distribution`): `Promise`<`number`[]\> - -Retrieves pivots to use for populating the offers in the distribution - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `distribution` | [`KandelDistribution`](KandelDistribution.md) | The distribution to get pivots for. | - -#### Returns - -`Promise`<`number`[]\> - -The pivots to use when populating the distribution. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:320 - -___ - -### getRawDistribution - -▸ **getRawDistribution**(`distribution`): `DistributionStruct` - -Convert public Kandel distribution to internal representation. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `distribution` | `OfferDistribution` | The Kandel distribution. | - -#### Returns - -`DistributionStruct` - -The internal representation of the Kandel distribution. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:340 - -___ - -### getOfferIds - -▸ **getOfferIds**(): `Promise`<{ `offerType`: [`BA`](../namespaces/Market-1.md#ba) ; `offerId`: `number` ; `index`: `number` }[]\> - -Retrieves the Mangrove offer ids for all offers. - -#### Returns - -`Promise`<{ `offerType`: [`BA`](../namespaces/Market-1.md#ba) ; `offerId`: `number` ; `index`: `number` }[]\> - -The Mangrove offer ids for all offers along with their offer type and Kandel index. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:358 - -___ - -### getOffers - -▸ **getOffers**(): `Promise`<{ `offerType`: [`BA`](../namespaces/Market-1.md#ba) ; `offerId`: `number` ; `index`: `number` ; `offer`: [`Offer`](../namespaces/Market-1.md#offer) = offer }[]\> - -Retrieves all offers for the Kandel instance by querying the market. - -#### Returns - -`Promise`<{ `offerType`: [`BA`](../namespaces/Market-1.md#ba) ; `offerId`: `number` ; `index`: `number` ; `offer`: [`Offer`](../namespaces/Market-1.md#offer) = offer }[]\> - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:371 - -___ - -### getOfferStatuses - -▸ **getOfferStatuses**(`midPrice`): `Promise`<`Statuses`\> - -Retrieves all offers from the market and determines their status. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `midPrice` | `BigSource` | The current mid price of the market used to discern expected bids from asks. | - -#### Returns - -`Promise`<`Statuses`\> - -The status of all offers. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:387 - -___ - -### getOfferStatusFromOffers - -▸ **getOfferStatusFromOffers**(`params`): `Promise`<`Statuses`\> - -Determines the status of the Kandel instance based on the passed in offers. - -**`Throws`** - -If no offers are live. At least one live offer is required to determine the status. - -**`Remarks`** - -The expected prices is determined by extrapolating from a live offer closest to the mid price. -Offers are expected to be live bids below the mid price and asks above. -This may not hold if an offer deep in the book has been sniped in which case a dual offer will exist on the wrong side of mid price but quickly be taken due to a good price (Kandel still earns on the spread). -Offers are expected to be dead near the mid price due to the spread (step size) between the live bid and ask. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters to use to determine the status. | -| `params.midPrice` | `BigSource` | The current mid price of the market used to discern expected bids from asks. | -| `params.offers` | `OffersWithPrices` | The offers used as a basis for determining the status. This should include all live and dead offers. | - -#### Returns - -`Promise`<`Statuses`\> - -The status of the Kandel instance. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:412 - -___ - -### createDistributionWithOffers - -▸ **createDistributionWithOffers**(`params`): `Promise`<[`KandelDistribution`](KandelDistribution.md)\> - -Creates a distribution based on an explicit set of offers based on the Kandel parameters. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters for the distribution. | -| `params.explicitOffers` | `OffersWithGives` | The explicit offers to use. | - -#### Returns - -`Promise`<[`KandelDistribution`](KandelDistribution.md)\> - -The new distribution. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:432 - -___ - -### getMinimumVolume - -▸ **getMinimumVolume**(`offerType`): `Promise`<`Big`\> - -Retrieves the minimum volume for a given offer type. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `offerType` | [`BA`](../namespaces/Market-1.md#ba) | The offer type to get the minimum volume for. | - -#### Returns - -`Promise`<`Big`\> - -The minimum volume for the given offer type. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:449 - -___ - -### getMinimumVolumeForIndex - -▸ **getMinimumVolumeForIndex**(`params`): `Promise`<`Big`\> - -Retrieves the minimum volume for a given offer type at the given index. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters for the minimum volume. | -| `params.offerType` | [`BA`](../namespaces/Market-1.md#ba) | The offer type to get the minimum volume for. | -| `params.index` | `number` | The Kandel index. | -| `params.price` | `BigSource` | The price at the index. | -| `params.minimumBasePerOffer?` | `BigSource` | The minimum base token volume per offer. If not provided, then the minimum base token volume is used. | -| `params.minimumQuotePerOffer?` | `BigSource` | The minimum quote token volume per offer. If not provided, then the minimum quote token volume is used. | - -#### Returns - -`Promise`<`Big`\> - -The minimum volume for the given offer type. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:466 - -___ - -### calculateDistributionWithUniformlyChangedVolume - -▸ **calculateDistributionWithUniformlyChangedVolume**(`params`): `Promise`<{ `distribution`: [`KandelDistribution`](KandelDistribution.md) ; `totalBaseChange`: `Big` ; `totalQuoteChange`: `Big` }\> - -Calculates a new distribution based on the provided live offers and deltas. - -**`Remarks`** - -The base and quote deltas are applied uniformly to all offers, except during decrease where offers are kept above their minimum volume. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters for the new distribution. | -| `params.liveOffers` | `OffersWithGives` | The live offers to use. | -| `params.baseDelta?` | `BigSource` | The delta to apply to the base token volume. If not provided, then the base token volume is unchanged. | -| `params.quoteDelta?` | `BigSource` | The delta to apply to the quote token volume. If not provided, then the quote token volume is unchanged. | -| `params.minimumBasePerOffer?` | `BigSource` | The minimum base token volume per offer. If not provided, then the minimum base token volume is used. | -| `params.minimumQuotePerOffer?` | `BigSource` | The minimum quote token volume per offer. If not provided, then the minimum quote token volume is used. | - -#### Returns - -`Promise`<{ `distribution`: [`KandelDistribution`](KandelDistribution.md) ; `totalBaseChange`: `Big` ; `totalQuoteChange`: `Big` }\> - -The new distribution for the live offers, dead offers are not included. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:522 - -___ - -### calculateUniformDistributionFromMinPrice - -▸ **calculateUniformDistributionFromMinPrice**(`params`): `Promise`<[`KandelDistribution`](KandelDistribution.md)\> - -Calculates a new uniform distribution based on the available base and quote balance and min price and mid price. - -**`See`** - - - getOfferStatus or - - getOfferStatusFromOffers . - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters for the new distribution. | -| `params.midPrice` | `BigSource` | The current mid price of the market used to discern expected bids from asks. | -| `params.minPrice` | `BigSource` | The minimum price to generate the distribution from; can be retrieved from the status from | -| `params.minimumBasePerOffer?` | `BigSource` | The minimum base token volume per offer. If not provided, then the minimum base token volume is used. | -| `params.minimumQuotePerOffer?` | `BigSource` | The minimum quote token volume per offer. If not provided, then the minimum quote token volume is used. | - -#### Returns - -`Promise`<[`KandelDistribution`](KandelDistribution.md)\> - -The new distribution, which can be used to re-populate the Kandel instance with this exact distribution. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:553 - -___ - -### approveIfHigher - -▸ **approveIfHigher**(`baseArgs?`, `quoteArgs?`): `Promise`<(`undefined` \| `ContractTransaction`)[]\> - -Approves the Kandel instance for transferring from signer to itself if allowance is not already high enough. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `baseArgs` | `ApproveArgs` | The arguments for approving the base token. If not provided, then infinite approval is used. | -| `quoteArgs` | `ApproveArgs` | The arguments for approving the quote token. If not provided, then infinite approval is used. | - -#### Returns - -`Promise`<(`undefined` \| `ContractTransaction`)[]\> - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:589 - -___ - -### deposit - -▸ **deposit**(`params`, `overrides?`): `Promise`<`ContractTransaction`\> - -Deposits the amounts on the Kandel instance to be available for offers. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters to use when depositing funds. | -| `params.baseAmount?` | `BigSource` | The amount of base to deposit. If not provided, then no base is deposited. | -| `params.quoteAmount?` | `BigSource` | The amount of quote to deposit. If not provided, then no quote is deposited. | -| `overrides` | `Overrides` | The ethers overrides to use when calling the deposit function. | - -#### Returns - -`Promise`<`ContractTransaction`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:605 - -___ - -### getMostSpecificConfig - -▸ **getMostSpecificConfig**(): `KandelNetworkConfiguration` & `Partial`<`KandelMarketConfiguration`\> - -Gets the most specific available default configuration for Kandel instances. - -#### Returns - -`KandelNetworkConfiguration` & `Partial`<`KandelMarketConfiguration`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:620 - -___ - -### getRawDistributionChunks - -▸ **getRawDistributionChunks**(`params`): `Promise`<{ `rawDistributions`: { `pivots`: `number`[] ; `rawDistribution`: `DistributionStruct` }[] ; `firstAskIndex`: `number` }\> - -Splits the distribution into chunks and converts it to internal representation. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters. | -| `params.distribution` | [`KandelDistribution`](KandelDistribution.md) | The distribution to split. | -| `params.maxOffersInChunk?` | `number` | The maximum number of offers in a chunk. If not provided, then KandelConfiguration is used. | - -#### Returns - -`Promise`<{ `rawDistributions`: { `pivots`: `number`[] ; `rawDistribution`: `DistributionStruct` }[] ; `firstAskIndex`: `number` }\> - -The raw distributions in internal representation and the index of the first ask. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:634 - -___ - -### getGasreqAndGasprice - -▸ **getGasreqAndGasprice**(`gasreq?`, `gasprice?`): `Promise`<{ `gasreq`: `number` ; `gasprice`: `number` }\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `gasreq?` | `number` | -| `gasprice?` | `number` | - -#### Returns - -`Promise`<{ `gasreq`: `number` ; `gasprice`: `number` }\> - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:659 - -___ - -### getRequiredProvision - -▸ **getRequiredProvision**(`params`): `Promise`<`Big`\> - -Determines the required provision for the offers in the distribution or the supplied offer count. - -**`Remarks`** - -This takes into account that each price point can become both an ask and a bid which both require provision. Existing locked provision or balance on Mangrove is not accounted for. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters used to calculate the provision. | -| `params.distribution?` | [`KandelDistribution`](KandelDistribution.md) | The distribution to calculate the provision for. Optional if offerCount is provided. | -| `params.offerCount?` | `number` | The number of offers to calculate the provision for. Optional if distribution is provided. | -| `params.gasreq?` | `number` | The gas required to execute a trade. Default is retrieved from Kandel parameters. | -| `params.gasprice?` | `number` | The gas price to calculate provision for. Default is retrieved from Kandel parameters. | - -#### Returns - -`Promise`<`Big`\> - -The provision required for the number of offers. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:679 - -___ - -### getLockedProvision - -▸ **getLockedProvision**(): `Promise`<`Big`\> - -Calculates the provision locked by existing offers based on the given parameters - -#### Returns - -`Promise`<`Big`\> - -the locked provision, in ethers. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:716 - -___ - -### getLockedProvisionFromOffers - -▸ **getLockedProvisionFromOffers**(`existingOffers`): `Big` - -Calculates the provision locked for a set of offers based on the given parameters - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `existingOffers` | { `gasprice`: `number` ; `gasreq`: `number` ; `gasbase`: `number` }[] | - -#### Returns - -`Big` - -the locked provision, in ethers. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:728 - -___ - -### getMissingProvision - -▸ **getMissingProvision**(`params`): `Promise`<`Big`\> - -Gets the missing provision based on provision already available on Mangrove, potentially locked by existing offers. It assumes all locked provision will be made available via deprovision or due to offers being replaced. - -**`Remarks`** - -If neither params.distribution nor params.offerCount is provided, then the current number of price points is used. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters. | -| `params.gasreq?` | `number` | An optional new gas required to execute a trade. Default is retrieved from Kandel parameters. | -| `params.gasprice?` | `number` | An optional new gas price to calculate provision for. Default is retrieved from Kandel parameters. | -| `params.distribution?` | [`KandelDistribution`](KandelDistribution.md) | The distribution to calculate the provision for. Optional. | -| `params.offerCount?` | `number` | The number of offers to calculate the provision for. Optional. | - -#### Returns - -`Promise`<`Big`\> - -the additional required provision, in ethers. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:743 - -___ - -### getMissingProvisionFromOffers - -▸ **getMissingProvisionFromOffers**(`params`, `existingOffers`): `Promise`<`Big`\> - -Gets the missing provision based on provision already available on Mangrove, potentially locked by existing offers, and the new distribution requiring provision. It assumes all the provision locked in the existingOffers will be made available via deprovision or due to offers being updated. - -**`Remarks`** - -If neither distribution nor offerCount is provided, then the current number of price points is used. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters for the required provision. | -| `params.gasreq?` | `number` | An optional new gas required to execute a trade. Default is retrieved from Kandel parameters. | -| `params.gasprice?` | `number` | An optional new gas price to calculate provision for. Default is retrieved from Kandel parameters. | -| `params.distribution?` | [`KandelDistribution`](KandelDistribution.md) | The distribution to calculate the provision for. Optional. | -| `params.offerCount?` | `number` | The number of offers to calculate the provision for. Optional. | -| `existingOffers` | { `gasprice`: `number` ; `gasreq`: `number` ; `gasbase`: `number` }[] | - | - -#### Returns - -`Promise`<`Big`\> - -the additional required provision, in ethers. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:766 - -___ - -### populate - -▸ **populate**(`params`, `overrides?`): `Promise`<`ContractTransaction`[]\> - -Populates the offers in the distribution for the Kandel instance and sets parameters. - -**`See`** - -getRequiredProvision. - -**`Remarks`** - -If this function is invoked with new ratio, pricePoints, or spread, then first retract all offers; otherwise, Kandel will enter an inconsistent state. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters for populating the offers. | -| `params.distribution?` | [`KandelDistribution`](KandelDistribution.md) | The distribution of offers to populate. | -| `params.parameters?` | `KandelParameterOverrides` | The parameters to set leave out values to keep their current value. | -| `params.depositBaseAmount?` | `BigSource` | The amount of base to deposit. If not provided, then no base is deposited. | -| `params.depositQuoteAmount?` | `BigSource` | The amount of quote to deposit. If not provided, then no quote is deposited. | -| `params.funds?` | `BigSource` | The amount of funds to provision. If not provided, then the required funds are provisioned according to | -| `params.maxOffersInChunk?` | `number` | The maximum number of offers to include in a single populate transaction. If not provided, then KandelConfiguration is used. | -| `overrides` | `Overrides` | The ethers overrides to use when calling the populate and populateChunk functions. | - -#### Returns - -`Promise`<`ContractTransaction`[]\> - -The transaction(s) used to populate the offers. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:802 - -___ - -### populateChunk - -▸ **populateChunk**(`params`, `overrides?`): `Promise`<`ContractTransaction`[]\> - -Populates the offers in the distribution for the Kandel instance. To set parameters or add funds, use populate. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters for populating the offers. | -| `params.distribution` | [`KandelDistribution`](KandelDistribution.md) | The distribution of offers to populate. | -| `params.maxOffersInChunk?` | `number` | The maximum number of offers to include in a single populate transaction. If not provided, then KandelConfiguration is used. | -| `overrides` | `Overrides` | The ethers overrides to use when calling the populateChunk function. | - -#### Returns - -`Promise`<`ContractTransaction`[]\> - -The transaction(s) used to populate the offers. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:878 - -___ - -### populateChunks - -▸ **populateChunks**(`firstAskIndex`, `rawDistributions`, `overrides?`): `Promise`<`ContractTransaction`[]\> - -Populates the offers in the distribution for the Kandel instance. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `firstAskIndex` | `number` | The index of the first ask in the distribution. | -| `rawDistributions` | { `pivots`: `number`[] ; `rawDistribution`: `DistributionStruct` }[] | The raw chunked distributions in internal representation to populate. | -| `overrides` | `Overrides` | The ethers overrides to use when calling the populateChunk function. | - -#### Returns - -`Promise`<`ContractTransaction`[]\> - -The transaction(s) used to populate the offers. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:898 - -___ - -### retractAndWithdraw - -▸ **retractAndWithdraw**(`params?`, `overrides?`): `Promise`<`ContractTransaction`[]\> - -Retracts offers and withdraws tokens and provision - -**`Remarks`** - -This function or retractOffers should be used to retract all offers before changing the ratio, pricePoints, or spread using populate. -If offers are retracted over multiple transactions, then the chunks are retracted in opposite order from the populate function. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters. | -| `params.startIndex?` | `number` | The start Kandel index of offers to retract. If not provided, then 0 is used. | -| `params.endIndex?` | `number` | The end index of offers to retract. This is exclusive of the offer the index 'endIndex'. If not provided, then the number of price points is used. | -| `params.withdrawFunds?` | `BigSource` | The amount of funds to withdraw in ethers. If not provided, then the entire provision on Mangrove is withdrawn. | -| `params.withdrawBaseAmount?` | `BigSource` | The amount of base to withdraw. If not provided, then the entire base balance on Kandel is withdrawn. | -| `params.withdrawQuoteAmount?` | `BigSource` | The amount of quote to withdraw. If not provided, then the entire quote balance on Kandel is withdrawn. | -| `params.recipientAddress?` | `string` | The address to withdraw the tokens to. If not provided, then the address of the signer is used. | -| `params.maxOffersInChunk?` | `number` | The maximum number of offers to include in a single retract transaction. If not provided, then KandelConfiguration is used. | -| `params.firstAskIndex?` | `number` | The index of the first ask in the distribution. It is used to determine the order in which to retract offers if multiple chunks are needed; if not provided, the midpoint between start and end is used. | -| `overrides` | `Overrides` | The ethers overrides to use when calling the retractAndWithdraw, and retractOffers functions. | - -#### Returns - -`Promise`<`ContractTransaction`[]\> - -The transaction(s) used to retract the offers. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:953 - -___ - -### retractOffers - -▸ **retractOffers**(`params?`, `overrides?`): `Promise`<`ContractTransaction`[]\> - -Retracts offers - -**`Remarks`** - -This function or retractAndWithdraw should be used to retract all offers before changing the ratio, pricePoints, or spread using populate. -If offers are retracted over multiple transactions, then the chunks are retracted in opposite order from the populate function. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters. | -| `params.startIndex?` | `number` | The start Kandel index of offers to retract. If not provided, then 0 is used. | -| `params.endIndex?` | `number` | The end index of offers to retract. This is exclusive of the offer the index 'endIndex'. If not provided, then the number of price points is used. | -| `params.maxOffersInChunk?` | `number` | The maximum number of offers to include in a single retract transaction. If not provided, then KandelConfiguration is used. | -| `params.firstAskIndex?` | `number` | The index of the first ask in the distribution. It is used to determine the order in which to retract offers if multiple chunks are needed; if not provided, the midpoint between start and end is used. | -| `overrides` | `Overrides` | The ethers overrides to use when calling the retractOffers function. | - -#### Returns - -`Promise`<`ContractTransaction`[]\> - -The transaction(s) used to retract the offers. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:1008 - -___ - -### retractOfferChunks - -▸ **retractOfferChunks**(`params`, `overrides`): `Promise`<{ `txs`: `ContractTransaction`[] ; `lastChunk`: { `from`: `number` ; `to`: `number` } }\> - -Retracts offers - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters. | -| `params.retractParams` | `Object` | The parameters for retracting offers. | -| `params.retractParams.startIndex?` | `number` | - | -| `params.retractParams.endIndex?` | `number` | - | -| `params.retractParams.maxOffersInChunk?` | `number` | - | -| `params.retractParams.firstAskIndex?` | `number` | - | -| `params.skipLast` | `boolean` | Whether to skip the last chunk. This is used to allow the last chunk to be retracted while withdrawing funds. | -| `overrides` | `Overrides` | The ethers overrides to use when calling the retractOffers function. | - -#### Returns - -`Promise`<{ `txs`: `ContractTransaction`[] ; `lastChunk`: { `from`: `number` ; `to`: `number` } }\> - -The transaction(s) used to retract the offers. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:1036 - -___ - -### withdraw - -▸ **withdraw**(`params?`, `overrides?`): `Promise`<`ContractTransaction`\> - -Withdraws tokens from the Kandel instance. - -**`Remarks`** - -it is up to the caller to make sure there are still enough funds for live offers. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters. | -| `params.baseAmount?` | `BigSource` | The amount of base to withdraw. If not provided, then the entire base balance on Kandel is withdrawn. | -| `params.quoteAmount?` | `BigSource` | The amount of quote to withdraw. If not provided, then the entire quote balance on Kandel is withdrawn. | -| `params.recipientAddress?` | `string` | The address to withdraw the tokens to. If not provided, then the address of the signer is used. | -| `overrides` | `Overrides` | The ethers overrides to use when calling the retractAndWithdraw, and retractOffers functions. | - -#### Returns - -`Promise`<`ContractTransaction`\> - -The transaction used to withdraw the offers. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:1090 - -___ - -### setGasprice - -▸ **setGasprice**(`gasprice`, `overrides?`): `Promise`<`ContractTransaction`\> - -Sets the gas price used when provisioning offers. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `gasprice` | `number` | The gas price to set. | -| `overrides` | `Overrides` | The ethers overrides to use when calling the setGasprice function. | - -#### Returns - -`Promise`<`ContractTransaction`\> - -The transaction used to set the gas price. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:1117 - -___ - -### setGasreq - -▸ **setGasreq**(`gasreq`, `overrides?`): `Promise`<`ContractTransaction`\> - -Sets the gas required to execute a trade. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `gasreq` | `number` | The gas requirement to set. | -| `overrides` | `Overrides` | The ethers overrides to use when calling the setGasreq function. | - -#### Returns - -`Promise`<`ContractTransaction`\> - -The transaction used to set the gas requirement. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelInstance.ts:1126 diff --git a/docs/SDK/technical-references/code/classes/KandelSeeder.md b/docs/SDK/technical-references/code/classes/KandelSeeder.md deleted file mode 100644 index b2963274..00000000 --- a/docs/SDK/technical-references/code/classes/KandelSeeder.md +++ /dev/null @@ -1,260 +0,0 @@ ---- -id: "KandelSeeder" -title: "Class: KandelSeeder" -sidebar_label: "KandelSeeder" -sidebar_position: 0 -custom_edit_url: null ---- - -Seeder for creating Kandel instances on-chain. - -## Properties - -### mgv - -• **mgv**: [`Mangrove`](Mangrove.md) - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelSeeder.ts:35 - -___ - -### configuration - -• **configuration**: `KandelConfiguration` - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelSeeder.ts:36 - -___ - -### tradeEventManagement - -• **tradeEventManagement**: `TradeEventManagement` - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelSeeder.ts:37 - -___ - -### aaveKandelSeeder - -• **aaveKandelSeeder**: `AaveKandelSeeder` - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelSeeder.ts:39 - -___ - -### kandelSeeder - -• **kandelSeeder**: `KandelSeeder` - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelSeeder.ts:40 - -## Constructors - -### constructor - -• **new KandelSeeder**(`mgv`) - -Constructor - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `mgv` | [`Mangrove`](Mangrove.md) | The Mangrove to deploy to. | - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelSeeder.ts:45 - -## Methods - -### sow - -▸ **sow**(`seed`, `overrides?`): `Promise`<{ `response`: `Promise`<`ContractTransaction`\> ; `kandelPromise`: `Promise`<[`KandelInstance`](KandelInstance.md)\> }\> - -Create a new Kandel instance. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `seed` | `KandelSeed` | The parameters for sowing the Kandel instance. | -| `overrides` | `Overrides` | - | - -#### Returns - -`Promise`<{ `response`: `Promise`<`ContractTransaction`\> ; `kandelPromise`: `Promise`<[`KandelInstance`](KandelInstance.md)\> }\> - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelSeeder.ts:70 - -___ - -### getKandelFromReceipt - -▸ **getKandelFromReceipt**(`params`): `Promise`<[`KandelInstance`](KandelInstance.md)\> - -Gets the Kandel instance created in a transaction via sow. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters. | -| `params.receipt` | `ContractReceipt` | The receipt of the transaction. | -| `params.onAave` | `boolean` | Whether the Kandel is an AaveKandel. | -| `params.market` | [`Market`](Market.md) | The market the Kandel is for. | - -#### Returns - -`Promise`<[`KandelInstance`](KandelInstance.md)\> - -The Kandel instance created in the transaction. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelSeeder.ts:110 - -___ - -### getDefaultGasreq - -▸ **getDefaultGasreq**(`onAave`): `Promise`<`number`\> - -Retrieves the default gasreq for the Kandel type. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `onAave` | `boolean` | Whether to get the gasreq for an AaveKandel or a standard Kandel. | - -#### Returns - -`Promise`<`number`\> - -The gasreq for the Kandel type. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelSeeder.ts:150 - -___ - -### getBufferedGasprice - -▸ **getBufferedGasprice**(`seed`): `Promise`<`number`\> - -Retrieves the gasprice for the Kandel type multiplied by the buffer factor. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `seed` | `KandelSeed` | The parameters for sowing the Kandel instance. | - -#### Returns - -`Promise`<`number`\> - -The gasprice for the Kandel type multiplied by the buffer factor. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelSeeder.ts:167 - -___ - -### getRequiredProvision - -▸ **getRequiredProvision**(`seed`, `distribution`): `Promise`<`Big`\> - -Determines the required provision for the distribution prior to sowing based on the number of price points. - -**`Remarks`** - -This takes into account that each price point can become both an ask and a bid which both require provision. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `seed` | `KandelSeed` | The parameters for sowing the Kandel instance. | -| `distribution` | [`KandelDistribution`](KandelDistribution.md) | The distribution to determine the provision for. | - -#### Returns - -`Promise`<`Big`\> - -The provision required for the distribution. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelSeeder.ts:180 - -___ - -### getMinimumVolume - -▸ **getMinimumVolume**(`params`): `Promise`<`Big`\> - -Determines the minimum recommended volume for an offer of the given type to avoid density issues. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters. | -| `params.market` | [`Market`](Market.md) | The market the Kandel is deployed to. | -| `params.offerType` | [`BA`](../namespaces/Market-1.md#ba) | The type of offer. | -| `params.onAave` | `boolean` | Whether the Kandel is an AaveKandel. | -| `params.factor?` | `number` | The factor to multiply the minimum volume by. Defaults to minimumBasePerOfferFactory / minimumQuotePerOfferFactor from KandelConfiguration. | - -#### Returns - -`Promise`<`Big`\> - -The minimum recommended volume. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelSeeder.ts:202 - -___ - -### getMinimumVolumeForGasreq - -▸ **getMinimumVolumeForGasreq**(`params`): `Promise`<`Big`\> - -Determines the minimum recommended volume for an offer of the given type to avoid density issues. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters. | -| `params.market` | [`Market`](Market.md) | The market the Kandel is deployed to. | -| `params.offerType` | [`BA`](../namespaces/Market-1.md#ba) | The type of offer. | -| `params.factor?` | `number` | The factor to multiply the minimum volume by. Defaults to minimumBasePerOfferFactory / minimumQuotePerOfferFactor from KandelConfiguration. | -| `params.gasreq` | `number` | The gasreq to use. | - -#### Returns - -`Promise`<`Big`\> - -The minimum recommended volume. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandel/kandelSeeder.ts:220 diff --git a/docs/SDK/technical-references/code/classes/KandelStrategies.md b/docs/SDK/technical-references/code/classes/KandelStrategies.md deleted file mode 100644 index af1603b5..00000000 --- a/docs/SDK/technical-references/code/classes/KandelStrategies.md +++ /dev/null @@ -1,130 +0,0 @@ ---- -id: "KandelStrategies" -title: "Class: KandelStrategies" -sidebar_label: "KandelStrategies" -sidebar_position: 0 -custom_edit_url: null ---- - -Entrypoint for the Kandel strategies. Kandel is an Automated Market Making strategy that uses on-chain order flow to repost offers instantly, without any latency. Within a market and price range you select, Kandel automatically posts bids and asks. Its main goal is to buy low and sell high - profits are made through accumulated spread. - -## Properties - -### seeder - -• **seeder**: [`KandelSeeder`](KandelSeeder.md) - -Seeder for creating Kandel instances on-chain. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandelStrategies.ts:17 - -___ - -### farm - -• **farm**: [`KandelFarm`](KandelFarm.md) - -Repository for Kandel instances. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandelStrategies.ts:20 - -___ - -### mgv - -• **mgv**: [`Mangrove`](Mangrove.md) - -The Mangrove to interact with. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandelStrategies.ts:23 - -___ - -### configuration - -• **configuration**: `KandelConfiguration` - -The default configuration values to use for Kandel. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandelStrategies.ts:26 - -## Constructors - -### constructor - -• **new KandelStrategies**(`mgv`) - -Constructor - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `mgv` | [`Mangrove`](Mangrove.md) | The Mangrove to interact with. | - -#### Defined in - -@mangrovedao/mangrove.js/src/kandelStrategies.ts:31 - -## Methods - -### instance - -▸ **instance**(`params`): `Promise`<[`KandelInstance`](KandelInstance.md)\> - -Creates a KandelInstance object to interact with a Kandel strategy on Mangrove. - -**`Dev`** - -If a factory function is provided for the market, then remember to disconnect market when no longer needed. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `params` | `Object` | The parameters for creating the KandelInstance. | -| `params.address` | `string` | The address of the Kandel strategy. | -| `params.market` | [`Market`](Market.md) \| (`baseAddress`: `string`, `quoteAddress`: `string`) => `Promise`<[`Market`](Market.md)\> | The market used by the Kandel instance or a factory function to create the market. | - -#### Returns - -`Promise`<[`KandelInstance`](KandelInstance.md)\> - -A new KandelInstance. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandelStrategies.ts:45 - -___ - -### generator - -▸ **generator**(`market`, `precision?`): [`KandelDistributionGenerator`](KandelDistributionGenerator.md) - -Creates a generator for generating Kandel distributions for the given market. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `market` | [`Market`](Market.md) | The market to calculate for. | -| `precision?` | `number` | The precision used for Kandel instances. Must match the deployed Kandel contract's PRECISION() value. | - -#### Returns - -[`KandelDistributionGenerator`](KandelDistributionGenerator.md) - -A new KandelDistributionGenerator. - -#### Defined in - -@mangrovedao/mangrove.js/src/kandelStrategies.ts:80 diff --git a/docs/SDK/technical-references/code/classes/LiquidityProvider.md b/docs/SDK/technical-references/code/classes/LiquidityProvider.md deleted file mode 100644 index ccf4ced9..00000000 --- a/docs/SDK/technical-references/code/classes/LiquidityProvider.md +++ /dev/null @@ -1,587 +0,0 @@ ---- -id: "LiquidityProvider" -title: "Class: LiquidityProvider" -sidebar_label: "LiquidityProvider" -sidebar_position: 0 -custom_edit_url: null ---- - -The LiquidityProvider class connects an offerLogic (or an EOA) to a market. -It posts onchain offers. - -## Properties - -### mgv - -• **mgv**: [`Mangrove`](Mangrove.md) - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:57 - -___ - -### logic - -• `Optional` **logic**: [`OfferLogic`](OfferLogic.md) - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:58 - -___ - -### contract - -• `Optional` **contract**: `ILiquidityProvider` - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:59 - -___ - -### eoa - -• `Optional` **eoa**: `string` - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:60 - -___ - -### market - -• **market**: [`Market`](Market.md) - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:61 - -___ - -### prettyP - -• **prettyP**: `PrettyPrint` - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:62 - -___ - -### gasreq - -• **gasreq**: `number` - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:63 - -## Constructors - -### constructor - -• **new LiquidityProvider**(`p`) - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `p` | [`ConstructionParams`](../namespaces/LiquidityProvider-1.md#constructionparams) | - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:65 - -## Methods - -### connect - -▸ `Static` **connect**(`offerLogic`, `p`): `Promise`<[`LiquidityProvider`](LiquidityProvider.md)\> - -Connects the logic to a Market in order to pass market orders. This assumes the underlying contract of offer logic is an ILiquidityProvider. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `offerLogic` | [`OfferLogic`](OfferLogic.md) | The offer logic. | -| `p` | [`Market`](Market.md) \| { `base`: `string` ; `quote`: `string` ; `bookOptions?`: [`BookOptions`](../namespaces/Market-1.md#bookoptions) } | The market to connect to. Can be a Market object or a market descriptor. | - -#### Returns - -`Promise`<[`LiquidityProvider`](LiquidityProvider.md)\> - -A LiquidityProvider. - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:90 - -___ - -### computeOfferProvision - -▸ **computeOfferProvision**(`ba`, `opts?`): `Promise`<`Big`\> - -Gets the missing provision in ethers for an offer to be posted or updated with the given parameters, while taking already locked provision into account. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `ba` | [`BA`](../namespaces/Market-1.md#ba) | bids or asks | -| `opts` | `Object` | optional parameters for the calculation. | -| `opts.id?` | `number` | the id of the offer to update. If undefined, then the offer is a new offer and nothing is locked. | -| `opts.gasreq?` | `number` | gas required for the offer execution. If undefined, the liquidity provider's gasreq. | -| `opts.gasprice?` | `number` | gas price to use for the calculation. If undefined, then Mangrove's current gas price is used. | - -#### Returns - -`Promise`<`Big`\> - -the additional required provision, in ethers. - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:125 - -___ - -### computeBidProvision - -▸ **computeBidProvision**(`opts?`): `Promise`<`Big`\> - -Gets the missing provision in ethers for a bid using - -**`See`** - -computeOfferProvision. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `opts` | `Object` | -| `opts.id?` | `number` | -| `opts.gasreq?` | `number` | -| `opts.gasprice?` | `number` | - -#### Returns - -`Promise`<`Big`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:156 - -___ - -### computeAskProvision - -▸ **computeAskProvision**(`opts?`): `Promise`<`Big`\> - -Gets the missing provision in ethers for an ask using - -**`See`** - -computeOfferProvision. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `opts` | `Object` | -| `opts.id?` | `number` | -| `opts.gasreq?` | `number` | -| `opts.gasprice?` | `number` | - -#### Returns - -`Promise`<`Big`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:163 - -___ - -### getBidPivotId - -▸ **getBidPivotId**(`price`): `Promise`<`undefined` \| `number`\> - -Given a price, find the id of the immediately-better offer in the -semibook. If there is no offer with a better price, `undefined` is returned. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `price` | `BigSource` | - -#### Returns - -`Promise`<`undefined` \| `number`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:172 - -___ - -### getAskPivotId - -▸ **getAskPivotId**(`price`): `Promise`<`undefined` \| `number`\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `price` | `BigSource` | - -#### Returns - -`Promise`<`undefined` \| `number`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:177 - -___ - -### asks - -▸ **asks**(): [`Offer`](../namespaces/Market-1.md#offer)[] - -List all of the maker's asks in the cache - -#### Returns - -[`Offer`](../namespaces/Market-1.md#offer)[] - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:183 - -___ - -### bids - -▸ **bids**(): [`Offer`](../namespaces/Market-1.md#offer)[] - -List all of the maker's bids in the cache - -#### Returns - -[`Offer`](../namespaces/Market-1.md#offer)[] - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:193 - -___ - -### consoleAsks - -▸ **consoleAsks**(`filter?`): `void` - -Pretty prints the current state of the asks for the maker - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `filter?` | `prettyPrintFilter` | - -#### Returns - -`void` - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:203 - -___ - -### consoleBids - -▸ **consoleBids**(`filter?`): `void` - -Pretty prints the current state of the bids for the maker - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `filter?` | `prettyPrintFilter` | - -#### Returns - -`void` - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:208 - -___ - -### normalizeOfferParams - -▸ `Static` **normalizeOfferParams**(`p`): `Object` - -Given offer params (bids/asks + price info as wants&gives or price&volume), - return `{price,wants,gives}` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `p` | `Object` | - -#### Returns - -`Object` - -| Name | Type | -| :------ | :------ | -| `price` | `Big` | -| `wants` | `Big` | -| `gives` | `Big` | -| `gasreq?` | `number` | -| `gasprice?` | `number` | -| `fund?` | `BigSource` | - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:216 - -___ - -### optValueToPayableOverride - -▸ `Static` **optValueToPayableOverride**(`overrides`, `fund?`): `PayableOverrides` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `overrides` | `Overrides` | -| `fund?` | `BigSource` | - -#### Returns - -`PayableOverrides` - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:247 - -___ - -### newAsk - -▸ **newAsk**(`p`, `overrides?`): `Promise`<{ `id`: `number` ; `event`: `Log` }\> - -Post a new ask - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `p` | [`OfferParams`](../namespaces/LiquidityProvider-1.md#offerparams) | -| `overrides` | `Overrides` | - -#### Returns - -`Promise`<{ `id`: `number` ; `event`: `Log` }\> - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:259 - -___ - -### newBid - -▸ **newBid**(`p`, `overrides?`): `Promise`<{ `id`: `number` ; `event`: `Log` }\> - -Post a new bid - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `p` | [`OfferParams`](../namespaces/LiquidityProvider-1.md#offerparams) | -| `overrides` | `Overrides` | - -#### Returns - -`Promise`<{ `id`: `number` ; `event`: `Log` }\> - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:267 - -___ - -### newOffer - -▸ **newOffer**(`p`, `overrides?`): `Promise`<{ `id`: `number` ; `pivot`: `number` ; `event`: `Log` }\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `p` | `Object` | -| `overrides` | `Overrides` | - -#### Returns - -`Promise`<{ `id`: `number` ; `pivot`: `number` ; `event`: `Log` }\> - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:288 - -___ - -### updateAsk - -▸ **updateAsk**(`id`, `p`, `overrides?`): `Promise`<{ `event`: `Log` }\> - -to change volume and price of the offer, and update its gas requirement and fund 0.01 ether to maker balance - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `id` | `number` | -| `p` | [`OfferParams`](../namespaces/LiquidityProvider-1.md#offerparams) | -| `overrides` | `PayableOverrides` | - -#### Returns - -`Promise`<{ `event`: `Log` }\> - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:377 - -___ - -### updateBid - -▸ **updateBid**(`id`, `p`, `overrides?`): `Promise`<{ `event`: `Log` }\> - -Update an existing offer - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `id` | `number` | -| `p` | [`OfferParams`](../namespaces/LiquidityProvider-1.md#offerparams) | -| `overrides` | `PayableOverrides` | - -#### Returns - -`Promise`<{ `event`: `Log` }\> - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:386 - -___ - -### updateOffer - -▸ **updateOffer**(`id`, `p`, `overrides?`): `Promise`<{ `event`: `Log` }\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `id` | `number` | -| `p` | `Object` | -| `overrides` | `PayableOverrides` | - -#### Returns - -`Promise`<{ `event`: `Log` }\> - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:398 - -___ - -### retractAsk - -▸ **retractAsk**(`id`, `deprovision?`, `overrides?`): `Promise`<`void`\> - -Cancel an ask. If deprovision is true, will return the offer's provision to the maker balance at Mangrove. - -#### Parameters - -| Name | Type | Default value | -| :------ | :------ | :------ | -| `id` | `number` | `undefined` | -| `deprovision` | `boolean` | `false` | -| `overrides` | `Overrides` | `{}` | - -#### Returns - -`Promise`<`void`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:468 - -___ - -### retractBid - -▸ **retractBid**(`id`, `deprovision?`, `overrides?`): `Promise`<`void`\> - -Cancel a bid. If deprovision is true, will return the offer's provision to the maker balance at Mangrove. - -#### Parameters - -| Name | Type | Default value | -| :------ | :------ | :------ | -| `id` | `number` | `undefined` | -| `deprovision` | `boolean` | `false` | -| `overrides` | `Overrides` | `{}` | - -#### Returns - -`Promise`<`void`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:477 - -___ - -### retractOffer - -▸ **retractOffer**(`ba`, `id`, `deprovision?`, `overrides?`): `Promise`<`void`\> - -#### Parameters - -| Name | Type | Default value | -| :------ | :------ | :------ | -| `ba` | [`BA`](../namespaces/Market-1.md#ba) | `undefined` | -| `id` | `number` | `undefined` | -| `deprovision` | `boolean` | `false` | -| `overrides` | `Overrides` | `{}` | - -#### Returns - -`Promise`<`void`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:486 diff --git a/docs/SDK/technical-references/code/classes/Mangrove.md b/docs/SDK/technical-references/code/classes/Mangrove.md deleted file mode 100644 index 8267df46..00000000 --- a/docs/SDK/technical-references/code/classes/Mangrove.md +++ /dev/null @@ -1,1292 +0,0 @@ ---- -id: "Mangrove" -title: "Class: Mangrove" -sidebar_label: "Mangrove" -sidebar_position: 0 -custom_edit_url: null ---- - -## Properties - -### provider - -• **provider**: `Provider` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:104 - -___ - -### signer - -• **signer**: `Signer` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:105 - -___ - -### network - -• **network**: [`ProviderNetwork`](../interfaces/eth.ProviderNetwork.md) - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:106 - -___ - -### \_readOnly - -• **\_readOnly**: `boolean` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:107 - -___ - -### address - -• **address**: `string` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:108 - -___ - -### contract - -• **contract**: `Mangrove` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:109 - -___ - -### readerContract - -• **readerContract**: `MgvReader` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:110 - -___ - -### cleanerContract - -• **cleanerContract**: `MgvCleaner` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:111 - -___ - -### multicallContract - -• **multicallContract**: `Multicall2` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:112 - -___ - -### orderContract - -• **orderContract**: `MangroveOrder` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:113 - -___ - -### reliableProvider - -• **reliableProvider**: `ReliableProvider` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:114 - -___ - -### mangroveEventSubscriber - -• **mangroveEventSubscriber**: `MangroveEventSubscriber` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:115 - -___ - -### eventEmitter - -• **eventEmitter**: `EventEmitter` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:117 - -___ - -### devNode - -▪ `Static` **devNode**: `DevNode` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:119 - -___ - -### typechain - -▪ `Static` **typechain**: `__module` = `typechain` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:120 - -## Methods - -### connect - -▸ `Static` **connect**(`options?`): `Promise`<[`Mangrove`](Mangrove.md)\> - -Creates an instance of the Mangrove Typescript object - -**`Example`** - -``` -const mgv = await require('mangrove.js').connect(options); // web browser -``` - -if options is a string `s`, it is considered to be `{provider:s}` -const mgv = await require('mangrove.js').connect('http://127.0.0.1:8545'); // HTTP provider - -Options: -* privateKey: `0x...` -* mnemonic: `horse battery ...` -* path: `m/44'/60'/0'/...` -* provider: url, provider object, or chain string - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `options?` | `string` \| [`CreateOptions`](../namespaces/Mangrove-1.md#createoptions) | Optional provider options. | - -#### Returns - -`Promise`<[`Mangrove`](Mangrove.md)\> - -Returns an instance mangrove.js - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:143 - -___ - -### disconnect - -▸ **disconnect**(): `void` - -#### Returns - -`void` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:230 - -___ - -### updateConfiguration - -▸ **updateConfiguration**(`config?`): `void` - -Update the configuration by providing a partial configuration containing only the values that should be changed/added. - -**`Example`** - -``` -updateConfiguration({ - tokens: { - SYM: { - decimals: 18 - } - } -}) -``` -This adds configuration for a new token with symbol "SYM". Or, if "SYM" was already configured, ensures that its `decimals` is set to 18. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `config?` | `RecursivePartial`<`Configuration`\> | Partial configuration that should be merged into the existing configuration. | - -#### Returns - -`void` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:343 - -___ - -### resetConfiguration - -▸ **resetConfiguration**(): `void` - -Reset the configuration to defaults provided by mangrove.js - -#### Returns - -`void` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:348 - -___ - -### market - -▸ **market**(`params`): `Promise`<[`Market`](Market.md)\> - -************ - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `params` | `Object` | -| `params.base` | `string` | -| `params.quote` | `string` | -| `params.bookOptions?` | [`BookOptions`](../namespaces/Market-1.md#bookoptions) | - -#### Returns - -`Promise`<[`Market`](Market.md)\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:379 - -___ - -### offerLogic - -▸ **offerLogic**(`logic`): [`OfferLogic`](OfferLogic.md) - -Get an OfferLogic object allowing one to monitor and set up an onchain offer logic - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `logic` | `string` | - -#### Returns - -[`OfferLogic`](OfferLogic.md) - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:399 - -___ - -### liquidityProvider - -▸ **liquidityProvider**(`p`): `Promise`<[`LiquidityProvider`](LiquidityProvider.md)\> - -Get a LiquidityProvider object to enable Mangrove's signer to pass buy and sell orders - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `p` | [`Market`](Market.md) \| { `base`: `string` ; `quote`: `string` ; `bookOptions?`: [`BookOptions`](../namespaces/Market-1.md#bookoptions) } | - -#### Returns - -`Promise`<[`LiquidityProvider`](LiquidityProvider.md)\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:414 - -___ - -### token - -▸ **token**(`name`, `options?`): `Promise`<[`MgvToken`](MgvToken.md)\> - -Return MgvToken instance, fetching data (decimals) from chain if needed. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `name` | `string` | -| `options?` | [`ConstructorOptions`](../namespaces/MgvToken-1.md#constructoroptions) | - -#### Returns - -`Promise`<[`MgvToken`](MgvToken.md)\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:442 - -___ - -### tokenFromConfig - -▸ **tokenFromConfig**(`name`, `options?`): [`MgvToken`](MgvToken.md) - -Return MgvToken instance reading only from configuration, not from chain. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `name` | `string` | -| `options?` | [`ConstructorOptions`](../namespaces/MgvToken-1.md#constructoroptions) | - -#### Returns - -[`MgvToken`](MgvToken.md) - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:450 - -___ - -### getAddress - -▸ **getAddress**(`name`): `string` - -Read a contract address on the current network. - -Note that this reads from the static `Mangrove` address registry which is shared across instances of this class. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `name` | `string` | - -#### Returns - -`string` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:462 - -___ - -### setAddress - -▸ **setAddress**(`name`, `address`): `void` - -Set a contract address on the current network. - -Note that this writes to the static `Mangrove` address registry which is shared across instances of this class. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `name` | `string` | -| `address` | `string` | - -#### Returns - -`void` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:474 - -___ - -### getNameFromAddress - -▸ **getNameFromAddress**(`address`): `undefined` \| `string` - -Gets the name of an address on the current network. - -Note that this reads from the static `Mangrove` address registry which is shared across instances of this class. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `address` | `string` | - -#### Returns - -`undefined` \| `string` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:487 - -___ - -### getTokenAndAddress - -▸ **getTokenAndAddress**(`address`): `Promise`<{ `address`: `string` ; `token?`: [`MgvToken`](MgvToken.md) }\> - -Gets the token corresponding to the address if it is known; otherwise, undefined. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `address` | `string` | - -#### Returns - -`Promise`<{ `address`: `string` ; `token?`: [`MgvToken`](MgvToken.md) }\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:496 - -___ - -### toUnits - -▸ `Static` **toUnits**(`amount`, `nameOrDecimals`): `BigNumber` - -Convert public token amount to internal token representation. - -if `nameOrDecimals` is a string, it is interpreted as a token name. Otherwise -it is the number of decimals. - -For convenience, has a static and an instance version. - -**`Example`** - -``` - Mangrove.toUnits(10,"USDC") // 10e6 as ethers.BigNumber - mgv.toUnits(10,6) // 10e6 as ethers.BigNumber - ``` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `amount` | `BigSource` | -| `nameOrDecimals` | `string` \| `number` | - -#### Returns - -`BigNumber` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:519 - -___ - -### toUnits - -▸ **toUnits**(`amount`, `nameOrDecimals`): `BigNumber` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `amount` | `BigSource` | -| `nameOrDecimals` | `string` \| `number` | - -#### Returns - -`BigNumber` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:525 - -___ - -### fromUnits - -▸ **fromUnits**(`amount`, `nameOrDecimals`): `Big` - -Convert internal token amount to public token representation. - -if `nameOrDecimals` is a string, it is interpreted as a token name. Otherwise -it is the number of decimals. - -**`Example`** - -``` - mgv.fromUnits("1e19","DAI") // 10 - mgv.fromUnits("1e19",18) // 10 - ``` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `amount` | `string` \| `number` \| `BigNumber` | -| `nameOrDecimals` | `string` \| `number` | - -#### Returns - -`Big` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:540 - -___ - -### balanceOf - -▸ **balanceOf**(`address`, `overrides?`): `Promise`<`Big`\> - -Provision available at mangrove for address given in argument, in ethers - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `address` | `string` | -| `overrides` | `Overrides` | - -#### Returns - -`Promise`<`Big`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:548 - -___ - -### fundMangrove - -▸ **fundMangrove**(`amount`, `maker`, `overrides?`): `Promise`<`ContractTransaction`\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `amount` | `BigSource` | -| `maker` | `string` | -| `overrides` | `Overrides` | - -#### Returns - -`Promise`<`ContractTransaction`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:556 - -___ - -### withdraw - -▸ **withdraw**(`amount`, `overrides?`): `Promise`<`ContractTransaction`\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `amount` | `BigSource` | -| `overrides` | `Overrides` | - -#### Returns - -`Promise`<`ContractTransaction`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:565 - -___ - -### approveMangrove - -▸ **approveMangrove**(`tokenName`, `arg?`): `Promise`<`ContractTransaction`\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `tokenName` | `string` | -| `arg` | `ApproveArgs` | - -#### Returns - -`Promise`<`ContractTransaction`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:572 - -___ - -### calculateOfferProvision - -▸ **calculateOfferProvision**(`gasprice`, `gasreq`, `gasbase`): `Big` - -Calculates the provision required or locked for an offer based on the given parameters - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `gasprice` | `number` | the gas price for the offer in gwei. | -| `gasreq` | `number` | the gas requirement for the offer | -| `gasbase` | `number` | the offer list's offer_gasbase. | - -#### Returns - -`Big` - -the required provision, in ethers. - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:586 - -___ - -### calculateOffersProvision - -▸ **calculateOffersProvision**(`offers`): `Big` - -Calculates the provision required or locked for offers based on the given parameters - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `offers` | { `gasprice`: `number` ; `gasreq`: `number` ; `gasbase`: `number` }[] | - -#### Returns - -`Big` - -the required provision, in ethers. - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:602 - -___ - -### getMissingProvision - -▸ **getMissingProvision**(`lockedProvision`, `totalRequiredProvision`): `Big` - -Gets the missing provision based on the required provision and the locked provision. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `lockedProvision` | `BigSource` | the provision already locked for an offer. | -| `totalRequiredProvision` | `BigSource` | the provision required for an offer. | - -#### Returns - -`Big` - -the additional required provision, in ethers. - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:623 - -___ - -### config - -▸ **config**(): `Promise`<[`GlobalConfig`](../namespaces/Mangrove-1.md#globalconfig)\> - -Return global Mangrove config - -#### Returns - -`Promise`<[`GlobalConfig`](../namespaces/Mangrove-1.md#globalconfig)\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:636 - -___ - -### normalizePermitData - -▸ **normalizePermitData**(`params`): `Promise`<[`PermitData`](../namespaces/Mangrove-1.md#permitdata)\> - -Permit data normalization -Autofill/convert 'nonce' field of permit data if need, convert deadline to -num if needed. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `params` | [`SimplePermitData`](../namespaces/Mangrove-1.md#simplepermitdata) | - -#### Returns - -`Promise`<[`PermitData`](../namespaces/Mangrove-1.md#permitdata)\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:655 - -___ - -### simpleSignPermitData - -▸ **simpleSignPermitData**(`params`): `Promise`<`string`\> - -Sign typed data for permit(). -To set the deadline to +days or +months, you can do -let date = new Date(); -date.setDate(date.getDate() + days); -date.setMonth(date.getMonth() + months); -- Nonce is auto-selected if needed and can be a number -- Date can be a Date or a number - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `params` | [`SimplePermitData`](../namespaces/Mangrove-1.md#simplepermitdata) | - -#### Returns - -`Promise`<`string`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:686 - -___ - -### signPermitData - -▸ **signPermitData**(`data`): `Promise`<`string`\> - -Permit data generator for normalized permit data input - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `data` | [`PermitData`](../namespaces/Mangrove-1.md#permitdata) | - -#### Returns - -`Promise`<`string`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:692 - -___ - -### permit - -▸ **permit**(`params`): `Promise`<`ContractTransaction`\> - -Give permit to Mangrove. -Permit params.spender to buy on behalf of owner on the outbound/inbound -offer list up to value. Default deadline is now + 1 day. Default nonce is -current owner nonce. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `params` | [`SimplePermitData`](../namespaces/Mangrove-1.md#simplepermitdata) | - -#### Returns - -`Promise`<`ContractTransaction`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:728 - -___ - -### getAllAddresses - -▸ `Static` **getAllAddresses**(`network`): [`string`, `string`][] - -Read all contract addresses on the given network. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `network` | `string` | - -#### Returns - -[`string`, `string`][] - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:760 - -___ - -### getAddress - -▸ `Static` **getAddress**(`name`, `network`): `string` - -Read a contract address on a given network. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `name` | `string` | -| `network` | `string` | - -#### Returns - -`string` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:767 - -___ - -### setAddress - -▸ `Static` **setAddress**(`name`, `address`, `network`): `void` - -Set a contract address on the given network. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `name` | `string` | -| `address` | `string` | -| `network` | `string` | - -#### Returns - -`void` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:774 - -___ - -### getNameFromAddress - -▸ `Static` **getNameFromAddress**(`address`, `network`): `undefined` \| `string` - -Gets the name of an address on the given network. - -Note that this reads from the static `Mangrove` address registry which is shared across instances of this class. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `address` | `string` | -| `network` | `string` | - -#### Returns - -`undefined` \| `string` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:783 - -___ - -### getDecimals - -▸ `Static` **getDecimals**(`tokenName`): `undefined` \| `number` - -Read decimals for `tokenName` on given network. -To read decimals directly onchain, use `fetchDecimals`. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `tokenName` | `string` | - -#### Returns - -`undefined` \| `number` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:794 - -___ - -### getDecimalsOrFail - -▸ `Static` **getDecimalsOrFail**(`tokenName`): `number` - -Read decimals for `tokenName`. Fails if the decimals are not in the configuration. -To read decimals directly onchain, use `fetchDecimals`. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `tokenName` | `string` | - -#### Returns - -`number` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:802 - -___ - -### getOrFetchDecimals - -▸ `Static` **getOrFetchDecimals**(`tokenName`, `provider`): `Promise`<`number`\> - -Read decimals for `tokenName` on given network. -If not found in the local configuration, fetch them from the current network and save them - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `tokenName` | `string` | -| `provider` | `Provider` | - -#### Returns - -`Promise`<`number`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:810 - -___ - -### fetchDecimals - -▸ `Static` **fetchDecimals**(`tokenName`, `provider`): `Promise`<`number`\> - -Read chain for decimals of `tokenName` on current network and save them - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `tokenName` | `string` | -| `provider` | `Provider` | - -#### Returns - -`Promise`<`number`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:820 - -___ - -### getDisplayedDecimals - -▸ `Static` **getDisplayedDecimals**(`tokenName`): `number` - -Read displayed decimals for `tokenName`. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `tokenName` | `string` | - -#### Returns - -`number` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:830 - -___ - -### getDisplayedPriceDecimals - -▸ `Static` **getDisplayedPriceDecimals**(`tokenName`): `number` - -Read displayed decimals for `tokenName` when displayed as a price. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `tokenName` | `string` | - -#### Returns - -`number` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:837 - -___ - -### setDecimals - -▸ `Static` **setDecimals**(`tokenName`, `dec`): `void` - -Set decimals for `tokenName` on current network. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `tokenName` | `string` | -| `dec` | `number` | - -#### Returns - -`void` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:844 - -___ - -### setDisplayedDecimals - -▸ `Static` **setDisplayedDecimals**(`tokenName`, `dec`): `void` - -Set displayed decimals for `tokenName`. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `tokenName` | `string` | -| `dec` | `number` | - -#### Returns - -`void` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:851 - -___ - -### setDisplayedPriceDecimals - -▸ `Static` **setDisplayedPriceDecimals**(`tokenName`, `dec`): `void` - -Set displayed decimals for `tokenName` when displayed as a price. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `tokenName` | `string` | -| `dec` | `number` | - -#### Returns - -`void` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:858 - -___ - -### initAndListenToDevNode - -▸ `Static` **initAndListenToDevNode**(`devNode`): `Promise`<`void`\> - -Setup dev node necessary contracts if needed, register dev Multicall2 -address, listen to future additions (a script external to mangrove.js may -deploy contracts during execution). - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `devNode` | `DevNode` | - -#### Returns - -`Promise`<`void`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:867 - -___ - -### openMarketsData - -▸ **openMarketsData**(`params?`): `Promise`<[`OpenMarketInfo`](../namespaces/Mangrove-1.md#openmarketinfo)[]\> - -Returns open markets data according to mangrove reader. - -**`Note`** - -If an open market has a token with no/bad decimals/symbol function, this function will revert. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `params` | `Object` | -| `params.from?` | `number` | -| `params.maxLen?` | `number` \| `BigNumber` | -| `params.configs?` | `boolean` | -| `params.tokenInfos?` | `boolean` | - -#### Returns - -`Promise`<[`OpenMarketInfo`](../namespaces/Mangrove-1.md#openmarketinfo)[]\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:899 - -___ - -### openMarkets - -▸ **openMarkets**(`params?`): `Promise`<[`Market`](Market.md)[]\> - -Returns open markets according to mangrove reader. Will internally update Mangrove token information. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `params` | `Object` | -| `params.from?` | `number` | -| `params.maxLen?` | `number` | -| `params.noInit?` | `boolean` | -| `params.bookOptions?` | [`BookOptions`](../namespaces/Market-1.md#bookoptions) | - -#### Returns - -`Promise`<[`Market`](Market.md)[]\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:1025 - -___ - -### setCashness - -▸ **setCashness**(`name`, `cashness`): `void` - -Set the relative cashness of a token. This determines which token is base & which is quote in a [Market](Market.md). -Lower cashness is base, higher cashness is quote, tiebreaker is lexicographic ordering of name string (name is most likely the same as the symbol). - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `name` | `string` | -| `cashness` | `number` | - -#### Returns - -`void` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:1067 - -___ - -### toBaseQuoteByCashness - -▸ `Static` **toBaseQuoteByCashness**(`name0`, `name1`): `Object` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `name0` | `string` | -| `name1` | `string` | - -#### Returns - -`Object` - -| Name | Type | -| :------ | :------ | -| `baseName` | `string` | -| `quoteName` | `string` | - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:1075 - -## Constructors - -### constructor - -• **new Mangrove**(`params`) - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `params` | `Object` | -| `params.signer` | `Signer` | -| `params.network` | [`ProviderNetwork`](../interfaces/eth.ProviderNetwork.md) | -| `params.readOnly` | `boolean` | -| `params.blockManagerOptions` | `Options` | -| `params.reliableHttpProvider` | `Options` | -| `params.eventEmitter` | `EventEmitter` | -| `params.reliableWebSocketOptions?` | `Object` | -| `params.reliableWebSocketOptions.options` | `Options` | -| `params.reliableWebSocketOptions.wsUrl` | `string` | - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:242 diff --git a/docs/SDK/technical-references/code/classes/Market.md b/docs/SDK/technical-references/code/classes/Market.md deleted file mode 100644 index 9da2580d..00000000 --- a/docs/SDK/technical-references/code/classes/Market.md +++ /dev/null @@ -1,1202 +0,0 @@ ---- -id: "Market" -title: "Class: Market" -sidebar_label: "Market" -sidebar_position: 0 -custom_edit_url: null ---- - -The Market class focuses on a Mangrove market. -On-chain, markets are implemented as two offer lists, -one for asks (base,quote), the other for bids (quote,base). - -Market initialization needs to store the network name, so you cannot -directly use the constructor. Instead of `new Market(...)`, do - -`await Market.connect(...)` - -## Properties - -### mgv - -• **mgv**: [`Mangrove`](Mangrove.md) - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:249 - -___ - -### base - -• **base**: [`MgvToken`](MgvToken.md) - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:250 - -___ - -### quote - -• **quote**: [`MgvToken`](MgvToken.md) - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:251 - -___ - -### trade - -• **trade**: `Trade` - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:256 - -___ - -### tradeEventManagement - -• **tradeEventManagement**: `TradeEventManagement` - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:257 - -___ - -### prettyP - -• **prettyP**: `PrettyPrint` - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:258 - -## Methods - -### connect - -▸ `Static` **connect**(`params`): `Promise`<[`Market`](Market.md)\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `params` | { `mgv`: [`Mangrove`](Mangrove.md) ; `base`: `string` ; `quote`: `string` } & `Partial`<[`OptionalParams`](../namespaces/Market-1.md#optionalparams)\> | - -#### Returns - -`Promise`<[`Market`](Market.md)\> - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:263 - -___ - -### close - -▸ **close**(): `void` - -#### Returns - -`void` - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:309 - -___ - -### initialize - -▸ **initialize**(): `Promise`<`void`\> - -#### Returns - -`Promise`<`void`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:322 - -___ - -### getBook - -▸ **getBook**(): [`Book`](../namespaces/Market-1.md#book) - -Return the semibooks of this market. - -Asks are standing offers to sell base and buy quote. -Bids are standing offers to buy base and sell quote. -All prices are in quote/base, all volumes are in base. -Order is from best to worse from taker perspective. - -#### Returns - -[`Book`](../namespaces/Market-1.md#book) - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:420 - -___ - -### getSemibook - -▸ **getSemibook**(`ba`): [`Semibook`](Semibook.md) - -Return the asks or bids semibook - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `ba` | [`BA`](../namespaces/Market-1.md#ba) | - -#### Returns - -[`Semibook`](Semibook.md) - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:433 - -___ - -### requestBook - -▸ **requestBook**(`opts?`): `Promise`<{ `asks`: [`Offer`](../namespaces/Market-1.md#offer)[] ; `bids`: [`Offer`](../namespaces/Market-1.md#offer)[] }\> - -#### Parameters - -| Name | Type | Default value | -| :------ | :------ | :------ | -| `opts` | [`BookOptions`](../namespaces/Market-1.md#bookoptions) | `bookOptsDefault` | - -#### Returns - -`Promise`<{ `asks`: [`Offer`](../namespaces/Market-1.md#offer)[] ; `bids`: [`Offer`](../namespaces/Market-1.md#offer)[] }\> - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:440 - -___ - -### isActive - -▸ **isActive**(): `Promise`<`boolean`\> - -#### Returns - -`Promise`<`boolean`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:454 - -___ - -### isLive - -▸ **isLive**(`ba`, `offerId`): `Promise`<`boolean`\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `ba` | [`BA`](../namespaces/Market-1.md#ba) | -| `offerId` | `number` | - -#### Returns - -`Promise`<`boolean`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:459 - -___ - -### isLiveOffer - -▸ **isLiveOffer**(`offer`): `boolean` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `offer` | [`Offer`](../namespaces/Market-1.md#offer) | - -#### Returns - -`boolean` - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:464 - -___ - -### getPivotId - -▸ **getPivotId**(`ba`, `price`): `Promise`<`undefined` \| `number`\> - -Given a price, find the id of the immediately-better offer in the -book. If there is no offer with a better price, `undefined` is returned. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `ba` | [`BA`](../namespaces/Market-1.md#ba) | -| `price` | `undefined` \| `BigSource` | - -#### Returns - -`Promise`<`undefined` \| `number`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:474 - -___ - -### getOfferProvision - -▸ **getOfferProvision**(`ba`, `gasreq`, `gasprice?`): `Promise`<`Big`\> - -Gets the amount of ethers necessary to provision an offer on the market. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `ba` | [`BA`](../namespaces/Market-1.md#ba) | bids or asks | -| `gasreq` | `number` | gas required for the offer execution. | -| `gasprice?` | `number` | gas price to use for the calculation. If undefined, then Mangrove's current gas price is used. | - -#### Returns - -`Promise`<`Big`\> - -the amount of ethers necessary to provision the offer. - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:487 - -___ - -### getBidProvision - -▸ **getBidProvision**(`gasreq`, `gasprice?`): `Promise`<`Big`\> - -Gets the amount of ethers necessary to provision a bid on the market. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `gasreq` | `number` | gas required for the offer execution. | -| `gasprice?` | `number` | gas price to use for the calculation. If undefined, then Mangrove's current gas price is used. | - -#### Returns - -`Promise`<`Big`\> - -the amount of ethers necessary to provision the offer. - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:506 - -___ - -### getAskProvision - -▸ **getAskProvision**(`gasreq`, `gasprice?`): `Promise`<`Big`\> - -Gets the amount of ethers necessary to provision a bid on the market. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `gasreq` | `number` | gas required for the offer execution. | -| `gasprice?` | `number` | gas price to use for the calculation. If undefined, then Mangrove's current gas price is used. | - -#### Returns - -`Promise`<`Big`\> - -the amount of ethers necessary to provision the offer. - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:515 - -___ - -### getMissingProvision - -▸ **getMissingProvision**(`ba`, `lockedProvision`, `gasreq`, `gasprice?`): `Promise`<`Big`\> - -Gets the missing provision in ethers for an offer with the given parameters - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `ba` | [`BA`](../namespaces/Market-1.md#ba) | bids or asks | -| `lockedProvision` | `BigSource` | the provision already locked with the offer | -| `gasreq` | `number` | gas required for the offer execution. | -| `gasprice?` | `number` | gas price to use for the calculation. If undefined, then Mangrove's current gas price is used. | - -#### Returns - -`Promise`<`Big`\> - -the additional required provision, in ethers. - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:526 - -___ - -### bidInfo - -▸ **bidInfo**(`offerId`): `Promise`<[`Offer`](../namespaces/Market-1.md#offer)\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `offerId` | `number` | - -#### Returns - -`Promise`<[`Offer`](../namespaces/Market-1.md#offer)\> - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:543 - -___ - -### askInfo - -▸ **askInfo**(`offerId`): `Promise`<[`Offer`](../namespaces/Market-1.md#offer)\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `offerId` | `number` | - -#### Returns - -`Promise`<[`Offer`](../namespaces/Market-1.md#offer)\> - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:547 - -___ - -### offerInfo - -▸ **offerInfo**(`ba`, `offerId`): `Promise`<[`Offer`](../namespaces/Market-1.md#offer)\> - -Returns struct containing offer details in the current market - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `ba` | [`BA`](../namespaces/Market-1.md#ba) | -| `offerId` | `number` | - -#### Returns - -`Promise`<[`Offer`](../namespaces/Market-1.md#offer)\> - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:552 - -___ - -### permit - -▸ **permit**(`action`, `data`): `Promise`<`ContractTransaction`\> - -Sign permit data. If action="buy", will permit buying base with spender's -quote token. If action="sell", will permit buying quote with spender's base -token. See mangrove.ts. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `action` | ``"buy"`` \| ``"sell"`` | -| `data` | `Omit`<[`SimplePermitData`](../namespaces/Mangrove-1.md#simplepermitdata), ``"outbound_tkn"`` \| ``"inbound_tkn"``\> | - -#### Returns - -`Promise`<`ContractTransaction`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:559 - -___ - -### buy - -▸ **buy**(`params`, `overrides?`): `Promise`<{ `result`: `Promise`<[`OrderResult`](../namespaces/Market-1.md#orderresult)\> ; `response`: `Promise`<`ContractTransaction`\> }\> - -Market buy order. Will attempt to buy base token using quote tokens. -Params can be of the form: -- `{volume,price}`: buy `volume` base tokens for a max average price of `price`. -- `{total,price}` : buy as many base tokens as possible using up to `total` quote tokens, with a max average price of `price`. -- `{wants,gives,fillWants?}`: accept implicit max average price of `gives/wants` - -In addition, `slippage` defines an allowed slippage in % of the amount of quote token, and -`restingOrder` or `offerId` can be supplied to create a resting order or to snipe a specific order, e.g., -to account for gas. - -Will stop if -- book is empty, or -- price no longer good, or -- `wants` tokens have been bought. - -**`Example`** - -``` -const market = await mgv.market({base:"USDC",quote:"DAI"}; -market.buy({volume: 100, price: '1.01'}) //use strings to be exact -``` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `params` | [`TradeParams`](../namespaces/Market-1.md#tradeparams) | -| `overrides` | `Overrides` | - -#### Returns - -`Promise`<{ `result`: `Promise`<[`OrderResult`](../namespaces/Market-1.md#orderresult)\> ; `response`: `Promise`<`ContractTransaction`\> }\> - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:603 - -___ - -### sell - -▸ **sell**(`params`, `overrides?`): `Promise`<{ `result`: `Promise`<[`OrderResult`](../namespaces/Market-1.md#orderresult)\> ; `response`: `Promise`<`ContractTransaction`\> }\> - -Market sell order. Will attempt to sell base token for quote tokens. -Params can be of the form: -- `{volume,price}`: sell `volume` base tokens for a min average price of `price`. -- `{total,price}` : sell as many base tokens as possible buying up to `total` quote tokens, with a min average price of `price`. -- `{wants,gives,fillWants?}`: accept implicit min average price of `gives/wants`. `fillWants` will be false by default. - -In addition, `slippage` defines an allowed slippage in % of the amount of quote token, and -`restingOrder` or `offerId` can be supplied to create a resting order or to snipe a specific order, e.g., -to account for gas. - -Will stop if -- book is empty, or -- price no longer good, or --`gives` tokens have been sold. - -**`Example`** - -``` -const market = await mgv.market({base:"USDC",quote:"DAI"}) -market.sell({volume: 100, price: 1}) -``` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `params` | [`TradeParams`](../namespaces/Market-1.md#tradeparams) | -| `overrides` | `Overrides` | - -#### Returns - -`Promise`<{ `result`: `Promise`<[`OrderResult`](../namespaces/Market-1.md#orderresult)\> ; `response`: `Promise`<`ContractTransaction`\> }\> - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:635 - -___ - -### gasEstimateBuy - -▸ **gasEstimateBuy**(`params`): `Promise`<`BigNumber`\> - -Estimate amount of gas for buy. Can be passed as overrides.gasLimit or params.gasLowerBound of - -**`See`** - -buy with same params. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `params` | [`TradeParams`](../namespaces/Market-1.md#tradeparams) | - -#### Returns - -`Promise`<`BigNumber`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:646 - -___ - -### gasEstimateSell - -▸ **gasEstimateSell**(`params`): `Promise`<`BigNumber`\> - -Estimate amount of gas for sell. Can be passed as overrides.gasLimit or params.gasLowerBound of - -**`See`** - -sell with same params. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `params` | [`TradeParams`](../namespaces/Market-1.md#tradeparams) | - -#### Returns - -`Promise`<`BigNumber`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:653 - -___ - -### snipe - -▸ **snipe**(`params`, `overrides?`): `Promise`<{ `result`: `Promise`<[`OrderResult`](../namespaces/Market-1.md#orderresult)\> ; `response`: `Promise`<`ContractTransaction`\> }\> - -Snipe specific offers. -Params are: -`targets`: an array of - `offerId`: the offer to snipe - `takerWants`: the amount of base token (for asks) or quote token (for bids) the taker wants - `takerGives`: the amount of quote token (for asks) or base token (for bids) the take gives - `gasLimit?`: the maximum gas requirement the taker will tolerate for that offer -`ba`: whether to snipe `asks` or `bids` -`fillWants?`: specifies whether you will buy at most `takerWants` (true), or you will buy as many tokens as possible as long as you don't spend more than `takerGives` (false). -`requireOffersToFail`: if true, then a successful offer will cause the call to fail without sniping anything. - Note: Setting `requireOffersToFail=true` uses the cleaner contract and the taker needs to approve spending, with - `await mgv.contract.approve(market.base.address, market.quote.address, mgv.cleanerContract.address, amount);` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `params` | [`SnipeParams`](../namespaces/Market-1.md#snipeparams) | -| `overrides` | `Overrides` | - -#### Returns - -`Promise`<{ `result`: `Promise`<[`OrderResult`](../namespaces/Market-1.md#orderresult)\> ; `response`: `Promise`<`ContractTransaction`\> }\> - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:673 - -___ - -### getRawSnipeParams - -▸ **getRawSnipeParams**(`params`, `overrides?`): `Promise`<[`RawSnipeParams`](../namespaces/Market-1.md#rawsnipeparams)\> - -Gets parameters to send to functions `market.mgv.cleanerContract.collect` or `market.mgv.contract.snipes`. -Params are: -`targets`: an array of - `offerId`: the offer to snipe - `takerWants`: the amount of base token (for asks) or quote token (for bids) the taker wants - `takerGives`: the amount of quote token (for asks) or base token (for bids) the take gives - `gasLimit?`: the maximum gas requirement the taker will tolerate for that offer -`ba`: whether to snipe `asks` or `bids` -`fillWants?`: specifies whether you will buy at most `takerWants` (true), or you will buy as many tokens as possible as long as you don't spend more than `takerGives` (false). -`requireOffersToFail`: defines whether a successful offer will cause the call to fail without sniping anything. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `params` | [`SnipeParams`](../namespaces/Market-1.md#snipeparams) | -| `overrides` | `Overrides` | - -#### Returns - -`Promise`<[`RawSnipeParams`](../namespaces/Market-1.md#rawsnipeparams)\> - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:695 - -___ - -### estimateGas - -▸ **estimateGas**(`bs`, `volume`): `Promise`<`BigNumber`\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `bs` | [`BS`](../namespaces/Market-1.md#bs) | -| `volume` | `BigNumber` | - -#### Returns - -`Promise`<`BigNumber`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:702 - -___ - -### simulateGas - -▸ **simulateGas**(`ba`, `gives`, `wants`, `fillWants`): `Promise`<`BigNumber`\> - -Uses the - -**`See`** - -semibook.simulateMarketOrder to simulate the gas required for a market order. An overhead of 50% is added to account for changes to the book and failing offers. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `ba` | [`BA`](../namespaces/Market-1.md#ba) | -| `gives` | `BigNumber` | -| `wants` | `BigNumber` | -| `fillWants` | `boolean` | - -#### Returns - -`Promise`<`BigNumber`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:731 - -___ - -### estimateVolume - -▸ **estimateVolume**(`params`): `Promise`<[`VolumeEstimate`](../namespaces/Market-1.md#volumeestimate)\> - -Volume estimator. - -if you say `estimateVolume({given:100,what:"base",to:"buy"})`, - -it will give you an estimate of how much quote token you would have to -spend to get 100 base tokens. - -if you say `estimateVolume({given:10,what:"quote",to:"sell"})`, - -it will given you an estimate of how much base tokens you'd have to buy in -order to spend 10 quote tokens. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `params` | [`VolumeParams`](../namespaces/Market-1.md#volumeparams) | - -#### Returns - -`Promise`<[`VolumeEstimate`](../namespaces/Market-1.md#volumeestimate)\> - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:771 - -___ - -### estimateVolumeToReceive - -▸ **estimateVolumeToReceive**(`params`): `Promise`<[`VolumeEstimate`](../namespaces/Market-1.md#volumeestimate)\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `params` | [`DirectionlessVolumeParams`](../namespaces/Market-1.md#directionlessvolumeparams) | - -#### Returns - -`Promise`<[`VolumeEstimate`](../namespaces/Market-1.md#volumeestimate)\> - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:785 - -___ - -### estimateVolumeToSpend - -▸ **estimateVolumeToSpend**(`params`): `Promise`<[`VolumeEstimate`](../namespaces/Market-1.md#volumeestimate)\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `params` | [`DirectionlessVolumeParams`](../namespaces/Market-1.md#directionlessvolumeparams) | - -#### Returns - -`Promise`<[`VolumeEstimate`](../namespaces/Market-1.md#volumeestimate)\> - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:792 - -___ - -### config - -▸ **config**(): `Promise`<{ `asks`: [`LocalConfig`](../namespaces/Mangrove-1.md#localconfig) ; `bids`: [`LocalConfig`](../namespaces/Mangrove-1.md#localconfig) }\> - -Return config local to a market. -Returned object is of the form -`{bids,asks}` where bids and asks are of type `localConfig` -Notes: -Amounts are converted to plain numbers. -density is converted to public token units per gas used -fee *remains* in basis points of the token being bought - -#### Returns - -`Promise`<{ `asks`: [`LocalConfig`](../namespaces/Mangrove-1.md#localconfig) ; `bids`: [`LocalConfig`](../namespaces/Mangrove-1.md#localconfig) }\> - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:809 - -___ - -### consoleAsks - -▸ **consoleAsks**(`filter?`): `void` - -Pretty prints the current state of the asks of the market - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `filter?` | `prettyPrintFilter` | - -#### Returns - -`void` - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:822 - -___ - -### consoleBids - -▸ **consoleBids**(`filter?`): `void` - -Pretty prints the current state of the bids of the market - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `filter?` | `prettyPrintFilter` | - -#### Returns - -`void` - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:827 - -___ - -### prettyPrint - -▸ **prettyPrint**(`ba`, `filter`): `void` - -Pretty prints the current state of the asks or bids of the market - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `ba` | [`BA`](../namespaces/Market-1.md#ba) | -| `filter` | `prettyPrintFilter` | - -#### Returns - -`void` - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:832 - -___ - -### subscribe - -▸ **subscribe**(`cb`): `void` - -Subscribe to order book updates. - -`cb` gets called whenever the order book is updated. - Its first argument `event` is a summary of the event. It has the following properties: - -* `type` the type of change. May be: * `"OfferWrite"`: an offer was -inserted or moved in the book. * `"OfferFail"`, `"OfferSuccess"`, -`"OfferRetract"`: an offer was removed from the book because it failed, -succeeded, or was canceled. - -* `ba` is either `"bids"` or `"asks"`. The offer concerned by the change is -either an ask (an offer for `base` asking for `quote`) or a bid (`an offer -for `quote` asking for `base`). - -* `offer` is information about the offer, see type `Offer`. - -* `taker`, `takerWants`, `takerGives` (for `"OfferFail"` and -`"OfferSuccess"` only): address of the taker who executed the offer as well -as the volumes that were requested by the taker. - -* `mgvData` : extra data from mangrove and the maker -contract. See the [Mangrove contracts documentation](#TODO) for the list of possible status codes. - -`opts` may specify the maximum of offers to read initially, and the chunk -size used when querying the reader contract (always ran locally). - -**`Example`** - -``` -const market = await mgv.market({base:"USDC",quote:"DAI"} -market.subscribe((event,utils) => console.log(event.type, utils.book())) -``` - -**`Note`** - -Only one subscription may be active at a time. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `cb` | [`MarketCallback`](../namespaces/Market-1.md#marketcallback)<`void`\> | - -#### Returns - -`void` - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:872 - -___ - -### once - -▸ **once**<`T`\>(`cb`, `filter?`): `Promise`<`T`\> - -Returns a promise which is fulfilled after execution of the callback. - -#### Type parameters - -| Name | -| :------ | -| `T` | - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `cb` | [`MarketCallback`](../namespaces/Market-1.md#marketcallback)<`T`\> | -| `filter?` | [`MarketFilter`](../namespaces/Market-1.md#marketfilter) | - -#### Returns - -`Promise`<`T`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:879 - -___ - -### unsubscribe - -▸ **unsubscribe**(`cb`): `void` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `cb` | [`StorableMarketCallback`](../namespaces/Market-1.md#storablemarketcallback) | - -#### Returns - -`void` - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:893 - -___ - -### getOutboundInbound - -▸ **getOutboundInbound**(`ba`): `Object` - -Determine which token will be Mangrove's outbound/inbound depending on whether you're working with bids or asks. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `ba` | [`BA`](../namespaces/Market-1.md#ba) | - -#### Returns - -`Object` - -| Name | Type | -| :------ | :------ | -| `outbound_tkn` | [`MgvToken`](MgvToken.md) | -| `inbound_tkn` | [`MgvToken`](MgvToken.md) | - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:898 - -___ - -### getOutboundInbound - -▸ `Static` **getOutboundInbound**(`ba`, `base`, `quote`): `Object` - -Determine which token will be Mangrove's outbound/inbound depending on whether you're working with bids or asks. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `ba` | [`BA`](../namespaces/Market-1.md#ba) | -| `base` | [`MgvToken`](MgvToken.md) | -| `quote` | [`MgvToken`](MgvToken.md) | - -#### Returns - -`Object` - -| Name | Type | -| :------ | :------ | -| `outbound_tkn` | [`MgvToken`](MgvToken.md) | -| `inbound_tkn` | [`MgvToken`](MgvToken.md) | - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:906 - -___ - -### getBaseQuoteVolumes - -▸ `Static` **getBaseQuoteVolumes**(`ba`, `gives`, `wants`): `Object` - -Determine whether gives or wants will be baseVolume/quoteVolume depending on whether you're working with bids or asks. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `ba` | [`BA`](../namespaces/Market-1.md#ba) | -| `gives` | `Big` | -| `wants` | `Big` | - -#### Returns - -`Object` - -| Name | Type | -| :------ | :------ | -| `baseVolume` | `Big` | -| `quoteVolume` | `Big` | - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:921 - -___ - -### getPrice - -▸ `Static` **getPrice**(`ba`, `gives`, `wants`): `undefined` \| `Big` - -Determine the price from dividing offer gives with wants depending on whether you're working with bids or asks. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `ba` | [`BA`](../namespaces/Market-1.md#ba) | -| `gives` | `Big` | -| `wants` | `Big` | - -#### Returns - -`undefined` \| `Big` - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:933 - -___ - -### getWantsForPrice - -▸ `Static` **getWantsForPrice**(`ba`, `gives`, `price`): `Big` - -Determine the wants from gives and price depending on whether you're working with bids or asks. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `ba` | [`BA`](../namespaces/Market-1.md#ba) | -| `gives` | `Big` | -| `price` | `Big` | - -#### Returns - -`Big` - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:943 - -___ - -### getGivesForPrice - -▸ `Static` **getGivesForPrice**(`ba`, `wants`, `price`): `Big` - -Determine the gives from wants and price depending on whether you're working with bids or asks. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `ba` | [`BA`](../namespaces/Market-1.md#ba) | -| `wants` | `Big` | -| `price` | `Big` | - -#### Returns - -`Big` - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:948 - -___ - -### getGivesWantsForVolumeAtPrice - -▸ `Static` **getGivesWantsForVolumeAtPrice**(`ba`, `volume`, `price`): `Object` - -Determine gives and wants from a volume (in base) and a price depending on whether you're working with bids or asks. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `ba` | [`BA`](../namespaces/Market-1.md#ba) | -| `volume` | `Big` | -| `price` | `Big` | - -#### Returns - -`Object` - -| Name | Type | -| :------ | :------ | -| `gives` | `Big` | -| `wants` | `Big` | - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:953 - -___ - -### getDisplayDecimalsForPriceDifferences - -▸ **getDisplayDecimalsForPriceDifferences**(): `number` - -Determine the first decimal place where the smallest price difference between neighboring offers in the order book cache is visible. - -#### Returns - -`number` - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:967 - -___ - -### getDisplayDecimalsForPriceDifferences - -▸ `Static` **getDisplayDecimalsForPriceDifferences**(`offers`): `number` - -Determine the first decimal place where the smallest price difference between neighboring offers is visible. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `offers` | [`Offer`](../namespaces/Market-1.md#offer)[] | - -#### Returns - -`number` - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:976 diff --git a/docs/SDK/technical-references/code/classes/MgvToken.md b/docs/SDK/technical-references/code/classes/MgvToken.md deleted file mode 100644 index e716fbdf..00000000 --- a/docs/SDK/technical-references/code/classes/MgvToken.md +++ /dev/null @@ -1,512 +0,0 @@ ---- -id: "MgvToken" -title: "Class: MgvToken" -sidebar_label: "MgvToken" -sidebar_position: 0 -custom_edit_url: null ---- - -## Properties - -### mgv - -• **mgv**: [`Mangrove`](Mangrove.md) - -#### Defined in - -@mangrovedao/mangrove.js/src/mgvtoken.ts:54 - -___ - -### name - -• **name**: `string` - -#### Defined in - -@mangrovedao/mangrove.js/src/mgvtoken.ts:55 - -___ - -### address - -• **address**: `string` - -#### Defined in - -@mangrovedao/mangrove.js/src/mgvtoken.ts:56 - -___ - -### displayedDecimals - -• **displayedDecimals**: `number` - -#### Defined in - -@mangrovedao/mangrove.js/src/mgvtoken.ts:57 - -___ - -### decimals - -• **decimals**: `number` - -#### Defined in - -@mangrovedao/mangrove.js/src/mgvtoken.ts:58 - -___ - -### contract - -• **contract**: `TestToken` - -#### Defined in - -@mangrovedao/mangrove.js/src/mgvtoken.ts:60 - -## Constructors - -### constructor - -• **new MgvToken**(`name`, `mgv`, `options?`) - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `name` | `string` | -| `mgv` | [`Mangrove`](Mangrove.md) | -| `options?` | [`ConstructorOptions`](../namespaces/MgvToken-1.md#constructoroptions) | - -#### Defined in - -@mangrovedao/mangrove.js/src/mgvtoken.ts:61 - -## Methods - -### createToken - -▸ `Static` **createToken**(`name`, `mgv`, `options?`): `Promise`<[`MgvToken`](MgvToken.md)\> - -Create a MgvToken instance, fetching data (decimals) from chain if needed. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `name` | `string` | -| `mgv` | [`Mangrove`](Mangrove.md) | -| `options?` | [`ConstructorOptions`](../namespaces/MgvToken-1.md#constructoroptions) | - -#### Returns - -`Promise`<[`MgvToken`](MgvToken.md)\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mgvtoken.ts:83 - -___ - -### fromUnits - -▸ **fromUnits**(`amount`): `Big` - -Convert base/quote from internal amount to public amount. -Uses each token's `decimals` parameter. - -**`Example`** - -``` -const usdc = await mgv.token("USDC"); -token.fromUnits("1e7") // 10 -const dai = await mgv.token("DAI") -market.fromUnits("1e18") // 1 -``` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `amount` | `string` \| `number` \| `BigNumber` | - -#### Returns - -`Big` - -#### Defined in - -@mangrovedao/mangrove.js/src/mgvtoken.ts:136 - -___ - -### toUnits - -▸ **toUnits**(`amount`): `BigNumber` - -Convert base/quote from public amount to internal contract amount. -Uses each token's `decimals` parameter. - -If `bq` is `"base"`, will convert the base, the quote otherwise. - -**`Example`** - -``` -const usdc = await mgv.token("USDC"); -token.toUnits(10) // 10e7 as ethers.BigNumber -const dai = await mgv.token("DAI") -market.toUnits(1) // 1e18 as ethers.BigNumber -``` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `amount` | `BigSource` | - -#### Returns - -`BigNumber` - -#### Defined in - -@mangrovedao/mangrove.js/src/mgvtoken.ts:153 - -___ - -### toFixed - -▸ **toFixed**(`amount`, `decimals?`): `string` - -Convert human-readable amounts to a string with the given -number of decimal places. Defaults to the token's decimals places. - -**`Example`** - -``` -token.toFixed("10.123"); // "10.12" -token.toFixed(token.fromUnits("1e7")); -``` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `amount` | `BigSource` | -| `decimals?` | `number` | - -#### Returns - -`string` - -#### Defined in - -@mangrovedao/mangrove.js/src/mgvtoken.ts:167 - -___ - -### allowance - -▸ **allowance**(`params?`): `Promise`<`Big`\> - -Return allowance of `owner` given to `spender`. -If `owner` is not specified, defaults to current signer. -If `spender` is not specified, defaults to Mangrove instance. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `params` | `Object` | -| `params.owner?` | `string` | -| `params.spender?` | `string` | - -#### Returns - -`Promise`<`Big`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mgvtoken.ts:179 - -___ - -### allowanceInfinite - -▸ **allowanceInfinite**(`params?`): `Promise`<`boolean`\> - -Returns whether allowance of `owner` given to `spender` is infinite. -If `owner` is not specified, defaults to current signer. -If `spender` is not specified, defaults to Mangrove instance. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `params` | `Object` | -| `params.owner?` | `string` | -| `params.spender?` | `string` | - -#### Returns - -`Promise`<`boolean`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mgvtoken.ts:191 - -___ - -### getDecimals - -▸ `Static` **getDecimals**(`tokenName`): `undefined` \| `number` - -Read decimals for `tokenName` on given network. -To read decimals directly onchain, use `fetchDecimals`. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `tokenName` | `string` | - -#### Returns - -`undefined` \| `number` - -#### Defined in - -@mangrovedao/mangrove.js/src/mgvtoken.ts:214 - -___ - -### getDecimalsOrFail - -▸ `Static` **getDecimalsOrFail**(`tokenName`): `number` - -Read decimals for `tokenName`. Fails if the decimals are not in the configuration. -To read decimals directly onchain, use `fetchDecimals`. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `tokenName` | `string` | - -#### Returns - -`number` - -#### Defined in - -@mangrovedao/mangrove.js/src/mgvtoken.ts:222 - -___ - -### getOrFetchDecimals - -▸ `Static` **getOrFetchDecimals**(`tokenName`, `provider`): `Promise`<`number`\> - -Read decimals for `tokenName` on given network. -If not found in the local configuration, fetch them from the current network and save them - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `tokenName` | `string` | -| `provider` | `Provider` | - -#### Returns - -`Promise`<`number`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mgvtoken.ts:230 - -___ - -### setDecimals - -▸ `Static` **setDecimals**(`tokenName`, `dec`): `void` - -Set decimals for `tokenName` on current network. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `tokenName` | `string` | -| `dec` | `number` | - -#### Returns - -`void` - -#### Defined in - -@mangrovedao/mangrove.js/src/mgvtoken.ts:240 - -___ - -### approveMangrove - -▸ **approveMangrove**(`arg?`): `Promise`<`ContractTransaction`\> - -Set approval for Mangrove to `amount`. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `arg` | `ApproveArgs` | - -#### Returns - -`Promise`<`ContractTransaction`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mgvtoken.ts:247 - -___ - -### approve - -▸ **approve**(`spender`, `arg?`): `Promise`<`ContractTransaction`\> - -Set approval for `spender` to `amount`. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `spender` | `string` | -| `arg` | `ApproveArgs` | - -#### Returns - -`Promise`<`ContractTransaction`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mgvtoken.ts:254 - -___ - -### approveIfNotInfinite - -▸ **approveIfNotInfinite**(`spender`, `arg?`): `Promise`<`undefined` \| `ContractTransaction`\> - -Sets the allowance for the spender if it is not infinite. Cannot be used to reduce from infinite. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `spender` | `string` | The spender to approve | -| `arg` | `ApproveArgs` | The approval arguments | - -#### Returns - -`Promise`<`undefined` \| `ContractTransaction`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mgvtoken.ts:273 - -___ - -### approveIfHigher - -▸ **approveIfHigher**(`spender`, `arg?`): `Promise`<`undefined` \| `ContractTransaction`\> - -Sets the allowance for the spender if it is not already enough. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `spender` | `string` | The spender to approve | -| `arg` | `ApproveArgs` | The approval arguments | - -#### Returns - -`Promise`<`undefined` \| `ContractTransaction`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mgvtoken.ts:285 - -___ - -### increaseApproval - -▸ **increaseApproval**(`spender`, `arg?`): `Promise`<`undefined` \| `ContractTransaction`\> - -Increases the allowance for the spender unless it is already max. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `spender` | `string` | The spender to approve | -| `arg` | `ApproveArgs` | The approval arguments | - -#### Returns - -`Promise`<`undefined` \| `ContractTransaction`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mgvtoken.ts:298 - -___ - -### balanceOf - -▸ **balanceOf**(`account`, `overrides?`): `Promise`<`Big`\> - -Returns the balance of `account`. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `account` | `string` | -| `overrides` | `Overrides` | - -#### Returns - -`Promise`<`Big`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mgvtoken.ts:320 - -___ - -### transfer - -▸ **transfer**(`to`, `value`, `overrides?`): `Promise`<`ContractTransaction`\> - -Transfers `value` amount of tokens to address `to` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `to` | `string` | -| `value` | `BigSource` | -| `overrides` | `Overrides` | - -#### Returns - -`Promise`<`ContractTransaction`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mgvtoken.ts:331 diff --git a/docs/SDK/technical-references/code/classes/OfferLogic.md b/docs/SDK/technical-references/code/classes/OfferLogic.md deleted file mode 100644 index 823c9966..00000000 --- a/docs/SDK/technical-references/code/classes/OfferLogic.md +++ /dev/null @@ -1,369 +0,0 @@ ---- -id: "OfferLogic" -title: "Class: OfferLogic" -sidebar_label: "OfferLogic" -sidebar_position: 0 -custom_edit_url: null ---- - -**`Title`** - -The OfferLogic class connects to a Maker contract implementing the IOfferLogic interface. - -## Properties - -### mgv - -• **mgv**: [`Mangrove`](Mangrove.md) - -#### Defined in - -@mangrovedao/mangrove.js/src/offerLogic.ts:14 - -___ - -### contract - -• **contract**: `IOfferLogic` - -#### Defined in - -@mangrovedao/mangrove.js/src/offerLogic.ts:15 - -___ - -### address - -• **address**: `string` - -#### Defined in - -@mangrovedao/mangrove.js/src/offerLogic.ts:16 - -___ - -### signerOrProvider - -• **signerOrProvider**: `SignerOrProvider` - -#### Defined in - -@mangrovedao/mangrove.js/src/offerLogic.ts:17 - -## Constructors - -### constructor - -• **new OfferLogic**(`mgv`, `logic`, `signer?`) - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `mgv` | [`Mangrove`](Mangrove.md) | -| `logic` | `string` | -| `signer?` | `SignerOrProvider` | - -#### Defined in - -@mangrovedao/mangrove.js/src/offerLogic.ts:19 - -## Methods - -### router - -▸ **router**(): `Promise`<`undefined` \| `AbstractRouter`\> - -**`Note`** - -Returns this logic's router. If logic has no router this call will return `undefined` - -#### Returns - -`Promise`<`undefined` \| `AbstractRouter`\> - -the router ethers.js contract responding to the `AbstractRouter` abi. - -#### Defined in - -@mangrovedao/mangrove.js/src/offerLogic.ts:33 - -___ - -### hasRouter - -▸ **hasRouter**(): `Promise`<`boolean`\> - -Determines whether the offer logic has a router - -#### Returns - -`Promise`<`boolean`\> - -True if the offer logic has a router, false otherwise. - -#### Defined in - -@mangrovedao/mangrove.js/src/offerLogic.ts:46 - -___ - -### approve - -▸ **approve**(`tokenName`, `args?`): `Promise`<`ContractTransaction`\> - -**`Note`** - -logic approves signer or `args.optSpender` to spend a certain token on its behalf -This has to be done for each token the signer's wishes to ask or bid for. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `tokenName` | `string` | - | -| `args?` | `Object` | optional `arg.amount` can be used if one wishes to approve a finite amount | -| `args.optSpender?` | `string` | - | -| `args.optAmount?` | `BigSource` | - | -| `args.optOverrides?` | `Overrides` | - | - -#### Returns - -`Promise`<`ContractTransaction`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/offerLogic.ts:55 - -___ - -### connect - -▸ **connect**(`signerOrProvider`): [`OfferLogic`](OfferLogic.md) - -Returns a new `OfferLogic` object with a different signer or provider connected to its ethers.js `contract` - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `signerOrProvider` | `SignerOrProvider` | the new signer or provider to connect to the contract. | - -#### Returns - -[`OfferLogic`](OfferLogic.md) - -a new `OfferLogic` object with a different signer or provider. - -#### Defined in - -@mangrovedao/mangrove.js/src/offerLogic.ts:84 - -___ - -### offerGasreq - -▸ **offerGasreq**(): `Promise`<`number`\> - -Retrieves the gasreq necessary for offers of this OfferLogic to execute a trade. - -#### Returns - -`Promise`<`number`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/offerLogic.ts:89 - -___ - -### setAdmin - -▸ **setAdmin**(`newAdmin`, `overrides?`): `Promise`<`TransactionResponse`\> - -Sets the admin of the contract if the Contract implements the AccessControlled interface. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `newAdmin` | `string` | the new admin address. | -| `overrides` | `Overrides` | The ethers overrides to use when calling the setAdmin function. | - -#### Returns - -`Promise`<`TransactionResponse`\> - -The transaction used to set the new admin. - -#### Defined in - -@mangrovedao/mangrove.js/src/offerLogic.ts:99 - -___ - -### admin - -▸ **admin**(): `Promise`<`string`\> - -Retrieves the current admin of the contract if the contract implements the AccessControlled interface - -#### Returns - -`Promise`<`string`\> - -The address of the current admin. - -#### Defined in - -@mangrovedao/mangrove.js/src/offerLogic.ts:113 - -___ - -### activate - -▸ **activate**(`tokenNames`, `overrides?`): `Promise`<`TransactionResponse`\> - -**`Note`** - -(contract admin action) activates logic - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `tokenNames` | `string`[] | the names of the tokens one wishes the logic to trade | -| `overrides` | `Overrides` | The ethers overrides to use when calling the activate function. | - -#### Returns - -`Promise`<`TransactionResponse`\> - -The transaction used to activate the OfferLogic. - -#### Defined in - -@mangrovedao/mangrove.js/src/offerLogic.ts:127 - -___ - -### getMangroveBalance - -▸ **getMangroveBalance**(): `Promise`<`Big`\> - -Retrieves the provision available on Mangrove for the offer logic, in ethers - -#### Returns - -`Promise`<`Big`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/offerLogic.ts:138 - -___ - -### fundOnMangrove - -▸ **fundOnMangrove**(`funds`, `overrides?`): `Promise`<`ContractTransaction`\> - -Adds ethers for provisioning offers on Mangrove for the offer logic. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `funds` | `BigSource` | The amount of funds to add in ethers. | -| `overrides` | `Overrides` | The ethers overrides to use when calling the fund function. | - -#### Returns - -`Promise`<`ContractTransaction`\> - -The transaction used to fund the offer logic. - -#### Defined in - -@mangrovedao/mangrove.js/src/offerLogic.ts:147 - -___ - -### withdrawFromMangrove - -▸ **withdrawFromMangrove**(`amount`, `overrides?`): `Promise`<`TransactionResponse`\> - -tx will revert is signer is not the admin of the OfferLogic onchain contract - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `amount` | `BigSource` | -| `overrides` | `Overrides` | - -#### Returns - -`Promise`<`TransactionResponse`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/offerLogic.ts:153 - -___ - -### retrieveLockedProvisionForOffer - -▸ **retrieveLockedProvisionForOffer**(`market`, `ba`, `offerId?`): `Promise`<`Big`\> - -Retrieves amount of provision locked for the offer on the offer logic which can be redeemed if the offer is retracted. - -**`Remarks`** - -Provision is either locked on Mangrove or for, e.g., a forwarder, on the offer logic itself. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `market` | [`Market`](Market.md) | the market of the offer | -| `ba` | [`BA`](../namespaces/Market-1.md#ba) | wether the offer is an ask or a bid. | -| `offerId?` | `number` | the id of the offer. | - -#### Returns - -`Promise`<`Big`\> - -the amount of provision locked for the offer on the offer logic. - -#### Defined in - -@mangrovedao/mangrove.js/src/offerLogic.ts:171 - -___ - -### getMissingProvision - -▸ **getMissingProvision**(`market`, `ba`, `opts?`): `Promise`<`Big`\> - -Gets the missing provision in ethers for an offer to be posted or updated on the offer logic with the given parameters, while taking already locked provision into account. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `market` | [`Market`](Market.md) | the market for the offer. | -| `ba` | [`BA`](../namespaces/Market-1.md#ba) | bids or asks | -| `opts` | `Object` | optional parameters for the calculation. | -| `opts.id?` | `number` | the id of the offer to update. If undefined, then the offer is a new offer and nothing is locked. | -| `opts.gasreq?` | `number` | gas required for the offer execution. If undefined, the offer logic's gasreq. | -| `opts.gasprice?` | `number` | gas price to use for the calculation. If undefined, then Mangrove's current gas price is used. | - -#### Returns - -`Promise`<`Big`\> - -the additional required provision, in ethers. - -#### Defined in - -@mangrovedao/mangrove.js/src/offerLogic.ts:200 diff --git a/docs/SDK/technical-references/code/classes/OfferMaker.md b/docs/SDK/technical-references/code/classes/OfferMaker.md deleted file mode 100644 index e004d2d4..00000000 --- a/docs/SDK/technical-references/code/classes/OfferMaker.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -id: "OfferMaker" -title: "Class: OfferMaker" -sidebar_label: "OfferMaker" -sidebar_position: 0 -custom_edit_url: null ---- - -The OfferMaker class connects to a simple OfferMaker contract - -## Methods - -### deploy - -▸ `Static` **deploy**(`mgv`, `gasreq?`): `Promise`<`string`\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `mgv` | [`Mangrove`](Mangrove.md) | -| `gasreq?` | `number` | - -#### Returns - -`Promise`<`string`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/offerMaker.ts:11 - -## Constructors - -### constructor - -• **new OfferMaker**() diff --git a/docs/SDK/technical-references/code/classes/Semibook.md b/docs/SDK/technical-references/code/classes/Semibook.md deleted file mode 100644 index 81c2b808..00000000 --- a/docs/SDK/technical-references/code/classes/Semibook.md +++ /dev/null @@ -1,807 +0,0 @@ ---- -id: "Semibook" -title: "Class: Semibook" -sidebar_label: "Semibook" -sidebar_position: 0 -custom_edit_url: null ---- - -The Semibook is a data structure for maintaining a cached prefix -of an offer list for one side (asks or bids) of a market. - -While offer lists on-chain for a market A-B are symmetric (the offer lists are -the same for the market B-A), a `Semibook` depends on the market: - -- Prices are in terms of quote tokens -- Volumes are in terms of base tokens - -## Hierarchy - -- `StateLogSubscriber`<[`State`](../namespaces/Semibook-1.md#state), [`BookSubscriptionEvent`](../namespaces/Market-1.md#booksubscriptionevent)\> - - ↳ **`Semibook`** - -## Implements - -- `Iterable`<[`Offer`](../namespaces/Market-1.md#offer)\> - -## Properties - -### DEFAULT\_MAX\_OFFERS - -▪ `Static` `Readonly` **DEFAULT\_MAX\_OFFERS**: ``50`` - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:173 - -___ - -### ba - -• `Readonly` **ba**: [`BA`](../namespaces/Market-1.md#ba) - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:175 - -___ - -### market - -• `Readonly` **market**: [`Market`](Market.md) - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:176 - -___ - -### options - -• `Readonly` **options**: [`ResolvedOptions`](../namespaces/Semibook-1.md#resolvedoptions) - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:177 - -___ - -### tradeManagement - -• **tradeManagement**: `Trade` - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:184 - -___ - -### optionsIdentifier - -• **optionsIdentifier**: `string` - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:186 - -___ - -### initializedAt - -• `Optional` **initializedAt**: `BlockWithoutParentHash` - -#### Inherited from - -StateLogSubscriber.initializedAt - -#### Defined in - -@mangrovedao/reliable-event-subscriber/dist/logSubscriber.d.ts:14 - -___ - -### lastSeenEventBlock - -• `Optional` **lastSeenEventBlock**: `BlockWithoutParentHash` - -#### Inherited from - -StateLogSubscriber.lastSeenEventBlock - -#### Defined in - -@mangrovedao/reliable-event-subscriber/dist/logSubscriber.d.ts:15 - -___ - -### cacheLock - -• `Protected` **cacheLock**: `Mutex` - -#### Inherited from - -StateLogSubscriber.cacheLock - -#### Defined in - -@mangrovedao/reliable-event-subscriber/dist/stateLogSubscriber.d.ts:12 - -## Methods - -### connect - -▸ `Static` **connect**(`market`, `ba`, `eventListener`, `options`): `Promise`<[`Semibook`](Semibook.md)\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `market` | [`Market`](Market.md) | -| `ba` | [`BA`](../namespaces/Market-1.md#ba) | -| `eventListener` | [`EventListener`](../namespaces/Semibook-1.md#eventlistener) | -| `options` | [`Options`](../namespaces/Semibook-1.md#options) | - -#### Returns - -`Promise`<[`Semibook`](Semibook.md)\> - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:188 - -___ - -### copy - -▸ **copy**(`state`): [`State`](../namespaces/Semibook-1.md#state) - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `state` | [`State`](../namespaces/Semibook-1.md#state) | - -#### Returns - -[`State`](../namespaces/Semibook-1.md#state) - -#### Overrides - -StateLogSubscriber.copy - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:217 - -___ - -### addEventListener - -▸ **addEventListener**(`listener`): `void` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `listener` | [`EventListener`](../namespaces/Semibook-1.md#eventlistener) | - -#### Returns - -`void` - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:221 - -___ - -### removeEventListener - -▸ **removeEventListener**(`listener`): `void` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `listener` | [`EventListener`](../namespaces/Semibook-1.md#eventlistener) | - -#### Returns - -`void` - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:225 - -___ - -### requestOfferListPrefix - -▸ **requestOfferListPrefix**(`options`): `Promise`<[`Offer`](../namespaces/Market-1.md#offer)[]\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `options` | [`Options`](../namespaces/Semibook-1.md#options) | - -#### Returns - -`Promise`<[`Offer`](../namespaces/Market-1.md#offer)[]\> - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:229 - -___ - -### offerInfo - -▸ **offerInfo**(`offerId`): `Promise`<[`Offer`](../namespaces/Market-1.md#offer)\> - -Returns struct containing offer details in the current offer list - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `offerId` | `number` | - -#### Returns - -`Promise`<[`Offer`](../namespaces/Market-1.md#offer)\> - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:249 - -___ - -### getConfig - -▸ **getConfig**(`blockNumber?`): `Promise`<[`LocalConfig`](../namespaces/Mangrove-1.md#localconfig)\> - -Return config local to a semibook. -Notes: -Amounts are converted to plain numbers. -density is converted to public token units per gas used -fee *remains* in basis points of the token being bought - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `blockNumber?` | `number` | - -#### Returns - -`Promise`<[`LocalConfig`](../namespaces/Mangrove-1.md#localconfig)\> - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:286 - -___ - -### getRawConfig - -▸ **getRawConfig**(`blockNumber?`): `Promise`<[`GlobalUnpackedStructOutput`, `LocalUnpackedStructOutput`] & {}\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `blockNumber?` | `number` | - -#### Returns - -`Promise`<[`GlobalUnpackedStructOutput`, `LocalUnpackedStructOutput`] & {}\> - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:291 - -___ - -### permit - -▸ **permit**(`data`): `Promise`<`ContractTransaction`\> - -Sign permit data for buying outbound_tkn with spender's inbound_tkn -See mangrove.ts. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `data` | `Omit`<[`SimplePermitData`](../namespaces/Mangrove-1.md#simplepermitdata), ``"outbound_tkn"`` \| ``"inbound_tkn"``\> | - -#### Returns - -`Promise`<`ContractTransaction`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:306 - -___ - -### size - -▸ **size**(): `number` - -Returns the number of offers in the cache. - -#### Returns - -`number` - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:321 - -___ - -### getBestInCache - -▸ **getBestInCache**(): `undefined` \| `number` - -Returns the id of the best offer in the cache - -#### Returns - -`undefined` \| `number` - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:327 - -___ - -### [iterator] - -▸ **[iterator]**(): [`CacheIterator`](../interfaces/Semibook-1.CacheIterator.md) - -Returns an iterator over the offers in the cache. - -#### Returns - -[`CacheIterator`](../interfaces/Semibook-1.CacheIterator.md) - -#### Implementation of - -Iterable.\_\_@iterator@92 - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:333 - -___ - -### iter - -▸ **iter**(): [`CacheIterator`](../interfaces/Semibook-1.CacheIterator.md) - -Convenience method for getting an iterator without having to call `[Symbol.iterator]()`. - -#### Returns - -[`CacheIterator`](../interfaces/Semibook-1.CacheIterator.md) - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:340 - -___ - -### getPivotId - -▸ **getPivotId**(`price`): `Promise`<`undefined` \| `number`\> - -Given a price, find the id of the immediately-better offer in the -semibook. If there is no offer with a better price, `undefined` is returned. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `price` | `undefined` \| `BigSource` | - -#### Returns - -`Promise`<`undefined` \| `number`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:347 - -___ - -### estimateVolume - -▸ **estimateVolume**(`params`): `Promise`<[`VolumeEstimate`](../namespaces/Market-1.md#volumeestimate)\> - -Volume estimator. - -if you say `estimateVolume({given:100,to:"buy"})`, - -it will give you an estimate of how much quote token you would have to -spend to get 100 base tokens. - -if you say `estimateVolume({given:10,to:"sell"})`, - -it will given you an estimate of how much base tokens you'd have to buy in -order to spend 10 quote tokens. - -if you add a `boundary` field, it either means -- the minimum amount you want to receive if you spend all `given` (if to:"sell"), or -- the maximum amount you are ready to spend if you buy all `given` (if to:"buy") - -So for instance, if you say `{given:10,to:"sell",boundary:"5"}`, estimateVolume will return the volume you will be able to receive if selling up to 10 at a min price of 10/5. - -The returned `givenResidue` is how much of the given token that cannot be -traded due to insufficient volume on the book / price becoming bad. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `params` | [`VolumeParams`](../namespaces/Semibook-1.md#volumeparams) | - -#### Returns - -`Promise`<[`VolumeEstimate`](../namespaces/Market-1.md#volumeestimate)\> - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:402 - -___ - -### simulateMarketOrder - -▸ **simulateMarketOrder**(`initialWants`, `initialGives`, `fillWants`): `Promise`<{ `wants`: `Big` ; `gives`: `Big` ; `totalGot`: `Big` ; `totalGave`: `Big` ; `gas`: `BigNumber` }\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `initialWants` | `Big` | -| `initialGives` | `Big` | -| `fillWants` | `boolean` | - -#### Returns - -`Promise`<{ `wants`: `Big` ; `gives`: `Big` ; `totalGot`: `Big` ; `totalGave`: `Big` ; `gas`: `BigNumber` }\> - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:429 - -___ - -### isPriceBetter - -▸ **isPriceBetter**(`price`, `referencePrice`): `boolean` - -Returns `true` if `price` is better than `referencePrice`; Otherwise, `false` is returned. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `price` | `undefined` \| `BigSource` | -| `referencePrice` | `undefined` \| `BigSource` | - -#### Returns - -`boolean` - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:526 - -___ - -### isPriceWorse - -▸ **isPriceWorse**(`price`, `referencePrice`): `boolean` - -Returns `true` if `price` is worse than `referencePrice`; Otherwise, `false` is returned. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `price` | `undefined` \| `BigSource` | -| `referencePrice` | `undefined` \| `BigSource` | - -#### Returns - -`boolean` - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:535 - -___ - -### getMaxGasReq - -▸ **getMaxGasReq**(): `Promise`<`undefined` \| `number`\> - -#### Returns - -`Promise`<`undefined` \| `number`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:542 - -___ - -### stateInitialize - -▸ **stateInitialize**(`block`): `Promise`<`ErrorOrState`<[`State`](../namespaces/Semibook-1.md#state)\>\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `block` | `BlockWithoutParentHash` | - -#### Returns - -`Promise`<`ErrorOrState`<[`State`](../namespaces/Semibook-1.md#state)\>\> - -#### Overrides - -StateLogSubscriber.stateInitialize - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:701 - -___ - -### stateHandleLog - -▸ **stateHandleLog**(`state`, `log`, `event?`): [`State`](../namespaces/Semibook-1.md#state) - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `state` | [`State`](../namespaces/Semibook-1.md#state) | -| `log` | `Log` | -| `event?` | [`BookSubscriptionEvent`](../namespaces/Market-1.md#booksubscriptionevent) | - -#### Returns - -[`State`](../namespaces/Semibook-1.md#state) - -#### Overrides - -StateLogSubscriber.stateHandleLog - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:748 - -___ - -### rawLocalConfigToLocalConfig - -▸ `Static` **rawLocalConfigToLocalConfig**(`local`, `outboundDecimals`): [`LocalConfig`](../namespaces/Mangrove-1.md#localconfig) - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `local` | `LocalUnpackedStructOutput` | -| `outboundDecimals` | `number` | - -#### Returns - -[`LocalConfig`](../namespaces/Mangrove-1.md#localconfig) - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:1110 - -___ - -### getMinimumVolume - -▸ **getMinimumVolume**(`gasreq`): `Promise`<`Big`\> - -Determines the minimum volume required to stay above density limit for the given gasreq (with a minimum of 1 unit of outbound, since 0 gives is not allowed). - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `gasreq` | `number` | The gas requirement for the offer. | - -#### Returns - -`Promise`<`Big`\> - -The minimum volume required to stay above density limit. - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:1129 - -___ - -### rawIdToId - -▸ `Static` **rawIdToId**(`rawId`): `undefined` \| `number` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `rawId` | `BigNumber` | - -#### Returns - -`undefined` \| `number` - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:1140 - -___ - -### getIsVolumeDesiredForAsks - -▸ `Static` **getIsVolumeDesiredForAsks**(`opts`): `boolean` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `opts` | [`BookOptions`](../namespaces/Market-1.md#bookoptions) | - -#### Returns - -`boolean` - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:1187 - -___ - -### getIsVolumeDesiredForBids - -▸ `Static` **getIsVolumeDesiredForBids**(`opts`): `boolean` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `opts` | [`BookOptions`](../namespaces/Market-1.md#bookoptions) | - -#### Returns - -`boolean` - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:1197 - -___ - -### checkIfLastSeenEventBlockExists - -▸ `Protected` **checkIfLastSeenEventBlockExists**(): `void` - -#### Returns - -`void` - -#### Inherited from - -StateLogSubscriber.checkIfLastSeenEventBlockExists - -#### Defined in - -@mangrovedao/reliable-event-subscriber/dist/stateLogSubscriber.d.ts:16 - -___ - -### getLatestState - -▸ **getLatestState**(): [`State`](../namespaces/Semibook-1.md#state) - -#### Returns - -[`State`](../namespaces/Semibook-1.md#state) - -#### Inherited from - -StateLogSubscriber.getLatestState - -#### Defined in - -@mangrovedao/reliable-event-subscriber/dist/stateLogSubscriber.d.ts:17 - -___ - -### initialize - -▸ **initialize**(`wantedBlock`): `Promise`<`InitializeErrorOrBlock`\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `wantedBlock` | `BlockWithoutParentHash` | - -#### Returns - -`Promise`<`InitializeErrorOrBlock`\> - -#### Inherited from - -StateLogSubscriber.initialize - -#### Defined in - -@mangrovedao/reliable-event-subscriber/dist/stateLogSubscriber.d.ts:18 - -___ - -### handleLog - -▸ **handleLog**(`log`, `event?`): `Promise`<`void`\> - -handle received log by creating new cached state if we found a block that is newer -than our cache. Then let implementation `stateHandleLog` modify the state. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `log` | `Log` | -| `event?` | [`BookSubscriptionEvent`](../namespaces/Market-1.md#booksubscriptionevent) | - -#### Returns - -`Promise`<`void`\> - -#### Inherited from - -StateLogSubscriber.handleLog - -#### Defined in - -@mangrovedao/reliable-event-subscriber/dist/stateLogSubscriber.d.ts:27 - -___ - -### rollback - -▸ **rollback**(`block`): `void` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `block` | `Block` | - -#### Returns - -`void` - -#### Inherited from - -StateLogSubscriber.rollback - -#### Defined in - -@mangrovedao/reliable-event-subscriber/dist/stateLogSubscriber.d.ts:28 diff --git a/docs/SDK/technical-references/code/classes/_category_.yml b/docs/SDK/technical-references/code/classes/_category_.yml deleted file mode 100644 index 55c7980a..00000000 --- a/docs/SDK/technical-references/code/classes/_category_.yml +++ /dev/null @@ -1,2 +0,0 @@ -label: "Classes" -position: 3 \ No newline at end of file diff --git a/docs/SDK/technical-references/code/classes/eth.Mnemonic.md b/docs/SDK/technical-references/code/classes/eth.Mnemonic.md deleted file mode 100644 index 24968443..00000000 --- a/docs/SDK/technical-references/code/classes/eth.Mnemonic.md +++ /dev/null @@ -1,126 +0,0 @@ ---- -id: "eth.Mnemonic" -title: "Class: Mnemonic" -sidebar_label: "eth.Mnemonic" -custom_edit_url: null ---- - -[eth](../namespaces/eth.md).Mnemonic - -## Properties - -### mnemonic - -• **mnemonic**: `string` - -#### Defined in - -@mangrovedao/mangrove.js/src/eth.ts:48 - -___ - -### iterateOn - -• **iterateOn**: ``"index"`` \| ``"change"`` \| ``"account"`` - -#### Defined in - -@mangrovedao/mangrove.js/src/eth.ts:49 - -## Methods - -### path - -▸ `Static` **path**(`iterator`, `iterateOn`): `string` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `iterator` | `number` | -| `iterateOn` | ``"index"`` \| ``"change"`` \| ``"account"`` | - -#### Returns - -`string` - -#### Defined in - -@mangrovedao/mangrove.js/src/eth.ts:50 - -___ - -### signer - -▸ **signer**(`iterator`): `Wallet` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `iterator` | `number` | - -#### Returns - -`Wallet` - -#### Defined in - -@mangrovedao/mangrove.js/src/eth.ts:66 - -___ - -### address - -▸ **address**(`iterator`): `string` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `iterator` | `number` | - -#### Returns - -`string` - -#### Defined in - -@mangrovedao/mangrove.js/src/eth.ts:71 - -___ - -### key - -▸ **key**(`iterator`): `string` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `iterator` | `number` | - -#### Returns - -`string` - -#### Defined in - -@mangrovedao/mangrove.js/src/eth.ts:75 - -## Constructors - -### constructor - -• **new Mnemonic**(`mnemonic`, `iterateOn?`) - -#### Parameters - -| Name | Type | Default value | -| :------ | :------ | :------ | -| `mnemonic` | `string` | `undefined` | -| `iterateOn` | ``"index"`` \| ``"change"`` \| ``"account"`` | `"index"` | - -#### Defined in - -@mangrovedao/mangrove.js/src/eth.ts:58 diff --git a/docs/SDK/technical-references/code/enums/_category_.yml b/docs/SDK/technical-references/code/enums/_category_.yml deleted file mode 100644 index 1687a9e0..00000000 --- a/docs/SDK/technical-references/code/enums/_category_.yml +++ /dev/null @@ -1,2 +0,0 @@ -label: "Enumerations" -position: 2 \ No newline at end of file diff --git a/docs/SDK/technical-references/code/enums/mgvTestUtil.AccountName.md b/docs/SDK/technical-references/code/enums/mgvTestUtil.AccountName.md deleted file mode 100644 index 1aabec7a..00000000 --- a/docs/SDK/technical-references/code/enums/mgvTestUtil.AccountName.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -id: "mgvTestUtil.AccountName" -title: "Enumeration: AccountName" -sidebar_label: "mgvTestUtil.AccountName" -custom_edit_url: null ---- - -[mgvTestUtil](../namespaces/mgvTestUtil.md).AccountName - -## Enumeration Members - -### Deployer - -• **Deployer** = ``"deployer"`` - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:122 - -___ - -### Cleaner - -• **Cleaner** = ``"cleaner"`` - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:123 - -___ - -### Maker - -• **Maker** = ``"maker"`` - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:124 - -___ - -### Arbitrager - -• **Arbitrager** = ``"arbitrager"`` - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:125 diff --git a/docs/SDK/technical-references/code/index.md b/docs/SDK/technical-references/code/index.md deleted file mode 100644 index 9d441a20..00000000 --- a/docs/SDK/technical-references/code/index.md +++ /dev/null @@ -1,107 +0,0 @@ ---- -id: "index" -title: "@mangrovedao/mangrove.js" -sidebar_label: "Readme" -sidebar_position: 0 -custom_edit_url: null ---- - -[![CI](https://github.com/mangrovedao/mangrove.js/actions/workflows/node.js.yml/badge.svg)](https://github.com/mangrovedao/mangrove.js/actions/workflows/node.js.yml) [![Coverage Status](https://coveralls.io/repos/github/mangrovedao/mangrove.js/badge.svg)](https://coveralls.io/github/mangrovedao/mangrove.js) - -This repo contains the SDK for developing TypeScript (and JavaScript) apps using the Mangrove. - -The core contracts for Mangrove with example Solidity offer logics live in the [mangrove-core](https://github.com/mangrovedao/mangrove-core) repo. - -# Documentation - -If you are looking for the Mangrove developer documentation, the main site to go to is [docs.mangrove.exchange](https://docs.mangrove.exchange). - -# Prerequisites - -For Linux or macOS everything should work out of the box, if you are using Windows, then we recommend installing everything from within WSL2 and expect some quirks. - -1. [Node.js](https://nodejs.org/en/) 14.14+, we recommend installation through [nvm](https://github.com/nvm-sh/nvm#installing-and-updating), e.g.: - - ```shell - $ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash - # Reopen shell - $ nvm install --lts - ``` - -2. [Yarn 2](https://yarnpkg.com/getting-started/install), with Node.js >= 16.10: - - ```shell - $ corepack enable - ``` - -3. [Foundry](https://book.getfoundry.sh/getting-started/installation.html): - - ```shell - $ curl -L https://foundry.paradigm.xyz | bash - # Reopen shell - $ foundryup - ``` - -4. Clone the git repo with sub-modules - - ```shell - $ git clone --recurse-submodules https://github.com/mangrovedao/mangrove.js.git - # Or set the global git config once: git config --global submodule.recurse true - ``` - -# Usage - -The following sections describe the most common use cases in this repo. - -## Initial setup - -After first cloning the repo, you should run `yarn install` in the root folder. - -```shell -$ yarn install -``` - -Then you need to setup the local environment (still in the root folder): - -```shell -$ cp .env.local.example .env.test.local -``` - -Then open `.env.test.local` in your favorite editor and put in settings for, e.g., node urls, pointing to a node provider, like, for instance, [Alchemy](https://www.alchemy.com/). - -## Build - -To build, run - -```shell -$ yarn build -``` - -If you encounter issues with JavaScript memory consumption, then try increasing the max available space for heap, and try again: - -```shell -$ export NODE_OPTIONS="$NODE_OPTIONS --max_old_space_size=4096" -$ yarn build -``` - -## Test - -To run tests, run - -```shell -$ yarn test -``` - -## Yarn usage details - -⚠️  Be aware that when googling Yarn commands, it's often not clear whether the results pertain to Yarn 1 (aka 'Classic') or Yarn 2+. Currently (November 2021), most examples and much tool support is implicitly engineered towards Yarn 1. - -### Lifecycle scripts and Yarn 2 - -Yarn 2 deliberately only supports a subset of the lifecycle scripts supported by npm. So when adding/modifying lifecycle scripts, you should consult Yarn 2's documentation on the subject: https://yarnpkg.com/advanced/lifecycle-scripts#gatsby-focus-wrapper . - -# Git hooks and Husky - -We use [Husky](https://typicode.github.io/husky/#/) to manage our Git hooks. - -The Git hook scripts are in the `.husky/` folder. diff --git a/docs/SDK/technical-references/code/interfaces/Semibook-1.CacheIterator.md b/docs/SDK/technical-references/code/interfaces/Semibook-1.CacheIterator.md deleted file mode 100644 index 78a4009b..00000000 --- a/docs/SDK/technical-references/code/interfaces/Semibook-1.CacheIterator.md +++ /dev/null @@ -1,168 +0,0 @@ ---- -id: "Semibook-1.CacheIterator" -title: "Interface: CacheIterator" -sidebar_label: "Semibook.CacheIterator" -custom_edit_url: null ---- - -[Semibook](../namespaces/Semibook-1.md).CacheIterator - -An iterator over a semibook cache. - -## Hierarchy - -- `IterableIterator`<[`Offer`](../namespaces/Market-1.md#offer)\> - - ↳ **`CacheIterator`** - -## Methods - -### filter - -▸ **filter**(`predicate`): [`CacheIterator`](Semibook-1.CacheIterator.md) - -Filter the offers in the cache using a predicate. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `predicate` | (`offer`: [`Offer`](../namespaces/Market-1.md#offer)) => `boolean` | Function is a predicate, to test each element of the array. Should return `true` if the element should be kept; otherwise `false` should be returned. | - -#### Returns - -[`CacheIterator`](Semibook-1.CacheIterator.md) - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:130 - -___ - -### find - -▸ **find**(`predicate`): `undefined` \| [`Offer`](../namespaces/Market-1.md#offer) - -Returns the value of the first element in the provided array that -satisfies the provided predicate. If no values satisfy the testing function, -`undefined` is returned. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `predicate` | (`offer`: [`Offer`](../namespaces/Market-1.md#offer)) => `boolean` | Function is a predicate, to test each element of the array. The firs offer that satisfies the predicate is returned; otherwise `undefined` is returned. | - -#### Returns - -`undefined` \| [`Offer`](../namespaces/Market-1.md#offer) - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:140 - -___ - -### toArray - -▸ **toArray**(): [`Offer`](../namespaces/Market-1.md#offer)[] - -Returns the elements in an array. - -#### Returns - -[`Offer`](../namespaces/Market-1.md#offer)[] - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:143 - -___ - -### next - -▸ **next**(`...args`): `IteratorResult`<[`Offer`](../namespaces/Market-1.md#offer), `any`\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `...args` | [] \| [`undefined`] | - -#### Returns - -`IteratorResult`<[`Offer`](../namespaces/Market-1.md#offer), `any`\> - -#### Inherited from - -IterableIterator.next - -#### Defined in - -typescript/lib/lib.es2015.iterable.d.ts:45 - -___ - -### return - -▸ `Optional` **return**(`value?`): `IteratorResult`<[`Offer`](../namespaces/Market-1.md#offer), `any`\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `value?` | `any` | - -#### Returns - -`IteratorResult`<[`Offer`](../namespaces/Market-1.md#offer), `any`\> - -#### Inherited from - -IterableIterator.return - -#### Defined in - -typescript/lib/lib.es2015.iterable.d.ts:46 - -___ - -### throw - -▸ `Optional` **throw**(`e?`): `IteratorResult`<[`Offer`](../namespaces/Market-1.md#offer), `any`\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `e?` | `any` | - -#### Returns - -`IteratorResult`<[`Offer`](../namespaces/Market-1.md#offer), `any`\> - -#### Inherited from - -IterableIterator.throw - -#### Defined in - -typescript/lib/lib.es2015.iterable.d.ts:47 - -___ - -### [iterator] - -▸ **[iterator]**(): `IterableIterator`<[`Offer`](../namespaces/Market-1.md#offer)\> - -#### Returns - -`IterableIterator`<[`Offer`](../namespaces/Market-1.md#offer)\> - -#### Inherited from - -IterableIterator.\_\_@iterator@92 - -#### Defined in - -typescript/lib/lib.es2015.iterable.d.ts:55 diff --git a/docs/SDK/technical-references/code/interfaces/_category_.yml b/docs/SDK/technical-references/code/interfaces/_category_.yml deleted file mode 100644 index 43bec88c..00000000 --- a/docs/SDK/technical-references/code/interfaces/_category_.yml +++ /dev/null @@ -1,2 +0,0 @@ -label: "Interfaces" -position: 4 \ No newline at end of file diff --git a/docs/SDK/technical-references/code/interfaces/eth.CreateSignerOptions.md b/docs/SDK/technical-references/code/interfaces/eth.CreateSignerOptions.md deleted file mode 100644 index 2aa833a3..00000000 --- a/docs/SDK/technical-references/code/interfaces/eth.CreateSignerOptions.md +++ /dev/null @@ -1,98 +0,0 @@ ---- -id: "eth.CreateSignerOptions" -title: "Interface: CreateSignerOptions" -sidebar_label: "eth.CreateSignerOptions" -custom_edit_url: null ---- - -[eth](../namespaces/eth.md).CreateSignerOptions - -## Properties - -### provider - -• `Optional` **provider**: `string` \| `Provider` - -#### Defined in - -@mangrovedao/mangrove.js/src/eth.ts:22 - -___ - -### providerWsUrl - -• `Optional` **providerWsUrl**: `string` - -#### Defined in - -@mangrovedao/mangrove.js/src/eth.ts:25 - -___ - -### signerIndex - -• `Optional` **signerIndex**: `number` - -#### Defined in - -@mangrovedao/mangrove.js/src/eth.ts:27 - -___ - -### privateKey - -• `Optional` **privateKey**: `string` - -#### Defined in - -@mangrovedao/mangrove.js/src/eth.ts:29 - -___ - -### mnemonic - -• `Optional` **mnemonic**: `string` - -#### Defined in - -@mangrovedao/mangrove.js/src/eth.ts:31 - -___ - -### path - -• `Optional` **path**: `string` - -#### Defined in - -@mangrovedao/mangrove.js/src/eth.ts:33 - -___ - -### signer - -• `Optional` **signer**: `any` - -#### Defined in - -@mangrovedao/mangrove.js/src/eth.ts:35 - -___ - -### jsonWallet - -• `Optional` **jsonWallet**: `JsonWalletOptions` - -#### Defined in - -@mangrovedao/mangrove.js/src/eth.ts:37 - -___ - -### forceReadOnly - -• `Optional` **forceReadOnly**: `boolean` - -#### Defined in - -@mangrovedao/mangrove.js/src/eth.ts:39 diff --git a/docs/SDK/technical-references/code/interfaces/eth.ProviderNetwork.md b/docs/SDK/technical-references/code/interfaces/eth.ProviderNetwork.md deleted file mode 100644 index a13b2e42..00000000 --- a/docs/SDK/technical-references/code/interfaces/eth.ProviderNetwork.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -id: "eth.ProviderNetwork" -title: "Interface: ProviderNetwork" -sidebar_label: "eth.ProviderNetwork" -custom_edit_url: null ---- - -[eth](../namespaces/eth.md).ProviderNetwork - -## Properties - -### id - -• `Optional` **id**: `number` - -#### Defined in - -@mangrovedao/mangrove.js/src/eth.ts:43 - -___ - -### name - -• **name**: `string` - -#### Defined in - -@mangrovedao/mangrove.js/src/eth.ts:44 diff --git a/docs/SDK/technical-references/code/modules.md b/docs/SDK/technical-references/code/modules.md deleted file mode 100644 index 4772a1af..00000000 --- a/docs/SDK/technical-references/code/modules.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -id: "modules" -title: "@mangrovedao/mangrove.js" -sidebar_label: "Exports" -sidebar_position: 0.5 -custom_edit_url: null ---- - -## Namespaces - -- [eth](namespaces/eth.md) -- [KandelStrategies](namespaces/KandelStrategies-1.md) -- [LiquidityProvider](namespaces/LiquidityProvider-1.md) -- [Mangrove](namespaces/Mangrove-1.md) -- [Market](namespaces/Market-1.md) -- [MgvToken](namespaces/MgvToken-1.md) -- [Semibook](namespaces/Semibook-1.md) -- [mgvTestUtil](namespaces/mgvTestUtil.md) - -## Classes - -- [KandelDistribution](classes/KandelDistribution.md) -- [KandelDistributionGenerator](classes/KandelDistributionGenerator.md) -- [KandelFarm](classes/KandelFarm.md) -- [KandelInstance](classes/KandelInstance.md) -- [KandelSeeder](classes/KandelSeeder.md) -- [KandelStrategies](classes/KandelStrategies.md) -- [LiquidityProvider](classes/LiquidityProvider.md) -- [Mangrove](classes/Mangrove.md) -- [Market](classes/Market.md) -- [MgvToken](classes/MgvToken.md) -- [OfferLogic](classes/OfferLogic.md) -- [OfferMaker](classes/OfferMaker.md) -- [Semibook](classes/Semibook.md) - -## References - -### default - -Renames and re-exports [Mangrove](classes/Mangrove.md) - -## Functions - -### enableLogging - -▸ **enableLogging**(): `void` - -#### Returns - -`void` - -#### Defined in - -@mangrovedao/mangrove.js/src/util/logger.ts:10 diff --git a/docs/SDK/technical-references/code/namespaces/KandelStrategies-1.md b/docs/SDK/technical-references/code/namespaces/KandelStrategies-1.md deleted file mode 100644 index 2c856776..00000000 --- a/docs/SDK/technical-references/code/namespaces/KandelStrategies-1.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: "KandelStrategies-1" -title: "Namespace: KandelStrategies" -sidebar_label: "KandelStrategies" -sidebar_position: 0 -custom_edit_url: null ---- - diff --git a/docs/SDK/technical-references/code/namespaces/LiquidityProvider-1.md b/docs/SDK/technical-references/code/namespaces/LiquidityProvider-1.md deleted file mode 100644 index 5e4a4d40..00000000 --- a/docs/SDK/technical-references/code/namespaces/LiquidityProvider-1.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -id: "LiquidityProvider-1" -title: "Namespace: LiquidityProvider" -sidebar_label: "LiquidityProvider" -sidebar_position: 0 -custom_edit_url: null ---- - -## Type Aliases - -### ConstructionParams - -Ƭ **ConstructionParams**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `mgv` | [`Mangrove`](../classes/Mangrove.md) | -| `logic?` | [`OfferLogic`](../classes/OfferLogic.md) | -| `eoa?` | `string` | -| `gasreq` | `number` | -| `market` | [`Market`](../classes/Market.md) | - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:23 - -___ - -### OfferParams - -Ƭ **OfferParams**: { `price`: `Bigish` ; `volume`: `Bigish` } & `OptParams` \| { `wants`: `Bigish` ; `gives`: `Bigish` } & `OptParams` - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:37 - -___ - -### OfferActionResult - -Ƭ **OfferActionResult**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `offerType` | [`BA`](Market-1.md#ba) | -| `market` | `string` | -| `txReceipt` | `ethers.ContractReceipt` | -| `id` | `number` | -| `gasprice?` | `number` | -| `gasreq?` | `number` | -| `refund?` | `Big` | - -#### Defined in - -@mangrovedao/mangrove.js/src/liquidityProvider.ts:41 diff --git a/docs/SDK/technical-references/code/namespaces/Mangrove-1.md b/docs/SDK/technical-references/code/namespaces/Mangrove-1.md deleted file mode 100644 index 5b49fb8c..00000000 --- a/docs/SDK/technical-references/code/namespaces/Mangrove-1.md +++ /dev/null @@ -1,161 +0,0 @@ ---- -id: "Mangrove-1" -title: "Namespace: Mangrove" -sidebar_label: "Mangrove" -sidebar_position: 0 -custom_edit_url: null ---- - -## Type Aliases - -### RawConfig - -Ƭ **RawConfig**: `Awaited`<`ReturnType`<`typechain.Mangrove`[``"functions"``][``"configInfo"``]\>\> - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:42 - -___ - -### LocalConfig - -Ƭ **LocalConfig**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `active` | `boolean` | -| `fee` | `number` | -| `density` | `Big` | -| `offer_gasbase` | `number` | -| `lock` | `boolean` | -| `best` | `number` \| `undefined` | -| `last` | `number` \| `undefined` | - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:46 - -___ - -### GlobalConfig - -Ƭ **GlobalConfig**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `monitor` | `string` | -| `useOracle` | `boolean` | -| `notify` | `boolean` | -| `gasprice` | `number` | -| `gasmax` | `number` | -| `dead` | `boolean` | - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:56 - -___ - -### SimplePermitData - -Ƭ **SimplePermitData**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `outbound_tkn` | `string` | -| `inbound_tkn` | `string` | -| `owner` | `string` | -| `spender` | `string` | -| `value` | `ethers.BigNumber` | -| `nonce?` | `number` \| `ethers.BigNumber` | -| `deadline` | `number` \| `Date` | - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:65 - -___ - -### PermitData - -Ƭ **PermitData**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `outbound_tkn` | `string` | -| `inbound_tkn` | `string` | -| `owner` | `string` | -| `spender` | `string` | -| `value` | `ethers.BigNumber` | -| `nonce` | `ethers.BigNumber` | -| `deadline` | `number` | - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:75 - -___ - -### OpenMarketInfo - -Ƭ **OpenMarketInfo**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `base` | { `name`: `string` ; `address`: `string` ; `symbol`: `string` ; `decimals`: `number` } | -| `base.name` | `string` | -| `base.address` | `string` | -| `base.symbol` | `string` | -| `base.decimals` | `number` | -| `quote` | { `name`: `string` ; `address`: `string` ; `symbol`: `string` ; `decimals`: `number` } | -| `quote.name` | `string` | -| `quote.address` | `string` | -| `quote.symbol` | `string` | -| `quote.decimals` | `number` | -| `asksConfig?` | [`LocalConfig`](Mangrove-1.md#localconfig) | -| `bidsConfig?` | [`LocalConfig`](Mangrove-1.md#localconfig) | - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:85 - -___ - -### CreateOptions - -Ƭ **CreateOptions**: [`CreateSignerOptions`](../interfaces/eth.CreateSignerOptions.md) & { `blockManagerOptions?`: `BlockManager.Options` ; `reliableWebsocketProviderOptions?`: `ReliableWebsocketProvider.Options` ; `reliableHttpProviderOptions?`: `ReliableHttpProvider.Options` } - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:92 - -___ - -### Configuration - -Ƭ **Configuration**: `MangroveJsConfiguration` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:98 - -___ - -### PartialConfiguration - -Ƭ **PartialConfiguration**: `PartialMangroveJsConfiguration` - -#### Defined in - -@mangrovedao/mangrove.js/src/mangrove.ts:100 diff --git a/docs/SDK/technical-references/code/namespaces/Market-1.BookReturns.md b/docs/SDK/technical-references/code/namespaces/Market-1.BookReturns.md deleted file mode 100644 index 18110b7d..00000000 --- a/docs/SDK/technical-references/code/namespaces/Market-1.BookReturns.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -id: "Market-1.BookReturns" -title: "Namespace: BookReturns" -sidebar_label: "Market.BookReturns" -custom_edit_url: null ---- - -[Market](Market-1.md).BookReturns - -## Type Aliases - -### Indices - -Ƭ **Indices**: `_BookReturns`[``1``] - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:191 - -___ - -### Offers - -Ƭ **Offers**: `_BookReturns`[``2``] - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:192 - -___ - -### Details - -Ƭ **Details**: `_BookReturns`[``3``] - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:193 diff --git a/docs/SDK/technical-references/code/namespaces/Market-1.md b/docs/SDK/technical-references/code/namespaces/Market-1.md deleted file mode 100644 index 7eed9c84..00000000 --- a/docs/SDK/technical-references/code/namespaces/Market-1.md +++ /dev/null @@ -1,415 +0,0 @@ ---- -id: "Market-1" -title: "Namespace: Market" -sidebar_label: "Market" -sidebar_position: 0 -custom_edit_url: null ---- - -## Namespaces - -- [BookReturns](Market-1.BookReturns.md) - -## Type Aliases - -### BA - -Ƭ **BA**: ``"bids"`` \| ``"asks"`` - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:31 - -___ - -### BS - -Ƭ **BS**: ``"buy"`` \| ``"sell"`` - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:32 - -___ - -### MgvReader - -Ƭ **MgvReader**: `typechain.MgvReader` - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:33 - -___ - -### Failure - -Ƭ **Failure**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `offerId` | `number` | -| `reason` | `string` | -| `FailToDeliver?` | `Big` | -| `volumeGiven?` | `Big` | - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:34 - -___ - -### Success - -Ƭ **Success**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `offerId` | `number` | -| `got` | `Big` | -| `gave` | `Big` | - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:40 - -___ - -### Summary - -Ƭ **Summary**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `got` | `Big` | -| `gave` | `Big` | -| `partialFill` | `boolean` | -| `bounty` | `Big` | -| `feePaid` | `Big` | - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:45 - -___ - -### OrderResult - -Ƭ **OrderResult**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `txReceipt` | `ethers.ContractReceipt` | -| `summary` | [`Summary`](Market-1.md#summary) | -| `successes` | [`Success`](Market-1.md#success)[] | -| `tradeFailures` | [`Failure`](Market-1.md#failure)[] | -| `posthookFailures` | [`Failure`](Market-1.md#failure)[] | -| `offerWrites` | { `ba`: [`BA`](Market-1.md#ba) ; `offer`: [`OfferSlim`](Market-1.md#offerslim) }[] | -| `restingOrder?` | [`OfferSlim`](Market-1.md#offerslim) | - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:52 - -___ - -### BookSubscriptionEvent - -Ƭ **BookSubscriptionEvent**: { `name`: ``"OfferWrite"`` } & `TCM.OfferWriteEvent` \| { `name`: ``"OfferFail"`` } & `TCM.OfferFailEvent` \| { `name`: ``"OfferSuccess"`` } & `TCM.OfferSuccessEvent` \| { `name`: ``"OfferRetract"`` } & `TCM.OfferRetractEvent` \| { `name`: ``"SetGasbase"`` } & `TCM.SetGasbaseEvent` - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:62 - -___ - -### OrderRoute - -Ƭ **OrderRoute**: ``"Mangrove"`` \| ``"MangroveOrder"`` - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:69 - -___ - -### TradeParams - -Ƭ **TradeParams**: { `forceRoutingToMangroveOrder?`: `boolean` ; `slippage?`: `number` ; `fillOrKill?`: `boolean` ; `expiryDate?`: `number` ; `gasLowerBound?`: `ethers.ethers.BigNumberish` } & { `restingOrder?`: [`RestingOrderParams`](Market-1.md#restingorderparams) } \| { `offerId?`: `number` } & { `volume`: `Bigish` ; `price`: `Bigish` } \| { `total`: `Bigish` ; `price`: `Bigish` } \| { `wants`: `Bigish` ; `gives`: `Bigish` ; `fillWants?`: `boolean` } - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:71 - -___ - -### RestingOrderParams - -Ƭ **RestingOrderParams**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `provision` | `Bigish` | - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:84 - -___ - -### SnipeParams - -Ƭ **SnipeParams**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `targets` | { `offerId`: `number` ; `takerWants`: `Bigish` ; `takerGives`: `Bigish` ; `gasLimit?`: `number` }[] | -| `ba` | [`BA`](Market-1.md#ba) | -| `fillWants?` | `boolean` | -| `requireOffersToFail?` | `boolean` | - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:88 - -___ - -### RawSnipeParams - -Ƭ **RawSnipeParams**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `ba` | [`BA`](Market-1.md#ba) | -| `outboundTkn` | `string` | -| `inboundTkn` | `string` | -| `targets` | [`Promise`<`ethers.ethers.BigNumberish`\> \| `ethers.ethers.BigNumberish`, `Promise`<`ethers.ethers.BigNumberish`\> \| `ethers.ethers.BigNumberish`, `Promise`<`ethers.ethers.BigNumberish`\> \| `ethers.ethers.BigNumberish`, `Promise`<`ethers.ethers.BigNumberish`\> \| `ethers.ethers.BigNumberish`][] | -| `fillWants` | `boolean` | - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:100 - -___ - -### VolumeParams - -Ƭ **VolumeParams**: [`VolumeParams`](Semibook-1.md#volumeparams) & { `what`: ``"base"`` \| ``"quote"`` } - -Specification of how much volume to (potentially) trade on the market. - -`{given:100, what:"base", to:"buy"}` means buying 100 base tokens. - -`{given:10, what:"quote", to:"sell"})` means selling 10 quote tokens. - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:120 - -___ - -### DirectionlessVolumeParams - -Ƭ **DirectionlessVolumeParams**: `Omit`<[`VolumeParams`](Market-1.md#volumeparams), ``"to"``\> - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:124 - -___ - -### OptionalParams - -Ƭ **OptionalParams**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `bookOptions` | [`BookOptions`](Market-1.md#bookoptions) | -| `noInit` | `boolean` | - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:126 - -___ - -### CacheContentsOptions - -Ƭ **CacheContentsOptions**: { `maxOffers?`: `number` } \| { `desiredPrice`: `Bigish` } \| { `desiredVolume`: [`VolumeParams`](Market-1.md#volumeparams) } - -Options that specify what the cache fetches and retains. - -`maxOffers`, `desiredPrice`, and `desiredVolume` are mutually exclusive. -If none of these are specified, the default is `maxOffers` = `Semibook.DEFAULT_MAX_OFFERS`. - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:137 - -___ - -### BookOptions - -Ƭ **BookOptions**: [`CacheContentsOptions`](Market-1.md#cachecontentsoptions) & { `chunkSize?`: `number` } - -Options that control how the book cache behaves. - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:162 - -___ - -### OfferSlim - -Ƭ **OfferSlim**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `id` | `number` | -| `prev` | `number` \| `undefined` | -| `gasprice` | `number` | -| `maker` | `string` | -| `gasreq` | `number` | -| `wants` | `Big` | -| `gives` | `Big` | -| `volume` | `Big` | -| `price` | `Big` \| `undefined` | - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:169 - -___ - -### Offer - -Ƭ **Offer**: [`OfferSlim`](Market-1.md#offerslim) & { `next`: `number` \| `undefined` ; `offer_gasbase`: `number` } - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:181 - -___ - -### BookSubscriptionCbArgument - -Ƭ **BookSubscriptionCbArgument**: { `ba`: [`BA`](Market-1.md#ba) ; `offerId?`: `number` ; `offer?`: [`Offer`](Market-1.md#offer) } & { `type`: ``"OfferWrite"`` } \| { `type`: ``"OfferFail"`` ; `taker`: `string` ; `takerWants`: `Big` ; `takerGives`: `Big` ; `mgvData`: `string` } \| { `type`: ``"OfferSuccess"`` ; `taker`: `string` ; `takerWants`: `Big` ; `takerGives`: `Big` } \| { `type`: ``"OfferRetract"`` } \| { `type`: ``"SetGasbase"`` } - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:196 - -___ - -### MarketCallback - -Ƭ **MarketCallback**<`T`\>: (`cbArg`: [`BookSubscriptionCbArgument`](Market-1.md#booksubscriptioncbargument), `event?`: [`BookSubscriptionEvent`](Market-1.md#booksubscriptionevent), `ethersLog?`: `ethers.providers.Log`) => `T` \| `Promise`<`T`\> - -#### Type parameters - -| Name | -| :------ | -| `T` | - -#### Type declaration - -▸ (`cbArg`, `event?`, `ethersLog?`): `T` \| `Promise`<`T`\> - -##### Parameters - -| Name | Type | -| :------ | :------ | -| `cbArg` | [`BookSubscriptionCbArgument`](Market-1.md#booksubscriptioncbargument) | -| `event?` | [`BookSubscriptionEvent`](Market-1.md#booksubscriptionevent) | -| `ethersLog?` | `ethers.providers.Log` | - -##### Returns - -`T` \| `Promise`<`T`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:214 - -___ - -### StorableMarketCallback - -Ƭ **StorableMarketCallback**: [`MarketCallback`](Market-1.md#marketcallback)<`any`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:219 - -___ - -### MarketFilter - -Ƭ **MarketFilter**: [`MarketCallback`](Market-1.md#marketcallback)<`boolean`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:220 - -___ - -### SubscriptionParam - -Ƭ **SubscriptionParam**: { `type`: ``"multiple"`` } \| { `type`: ``"once"`` ; `ok`: (...`a`: `any`[]) => `any` ; `ko`: (...`a`: `any`[]) => `any` ; `filter?`: (...`a`: `any`[]) => `boolean` \| `Promise`<`boolean`\> } - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:221 - -___ - -### Book - -Ƭ **Book**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `asks` | [`Semibook`](../classes/Semibook.md) | -| `bids` | [`Semibook`](../classes/Semibook.md) | - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:230 - -___ - -### VolumeEstimate - -Ƭ **VolumeEstimate**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `estimatedVolume` | `Big` | -| `givenResidue` | `Big` | - -#### Defined in - -@mangrovedao/mangrove.js/src/market.ts:232 diff --git a/docs/SDK/technical-references/code/namespaces/MgvToken-1.md b/docs/SDK/technical-references/code/namespaces/MgvToken-1.md deleted file mode 100644 index 08010092..00000000 --- a/docs/SDK/technical-references/code/namespaces/MgvToken-1.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -id: "MgvToken-1" -title: "Namespace: MgvToken" -sidebar_label: "MgvToken" -sidebar_position: 0 -custom_edit_url: null ---- - -## Type Aliases - -### ConstructorOptions - -Ƭ **ConstructorOptions**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `address?` | `string` | -| `decimals?` | `number` | -| `displayedDecimals?` | `number` | - -#### Defined in - -@mangrovedao/mangrove.js/src/mgvtoken.ts:11 diff --git a/docs/SDK/technical-references/code/namespaces/Semibook-1.md b/docs/SDK/technical-references/code/namespaces/Semibook-1.md deleted file mode 100644 index 7ed1a723..00000000 --- a/docs/SDK/technical-references/code/namespaces/Semibook-1.md +++ /dev/null @@ -1,170 +0,0 @@ ---- -id: "Semibook-1" -title: "Namespace: Semibook" -sidebar_label: "Semibook" -sidebar_position: 0 -custom_edit_url: null ---- - -## Interfaces - -- [CacheIterator](../interfaces/Semibook-1.CacheIterator.md) - -## Type Aliases - -### Event - -Ƭ **Event**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `cbArg` | [`BookSubscriptionCbArgument`](Market-1.md#booksubscriptioncbargument) | -| `event` | [`BookSubscriptionEvent`](Market-1.md#booksubscriptionevent) | -| `ethersLog` | `ethers.providers.Log` | - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:28 - -___ - -### EventListener - -Ƭ **EventListener**: (`e`: [`Event`](Semibook-1.md#event)) => `Promise`<`void`\> - -#### Type declaration - -▸ (`e`): `Promise`<`void`\> - -##### Parameters - -| Name | Type | -| :------ | :------ | -| `e` | [`Event`](Semibook-1.md#event) | - -##### Returns - -`Promise`<`void`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:34 - -___ - -### BlockListener - -Ƭ **BlockListener**: (`n`: `number`) => `Promise`<`void`\> - -#### Type declaration - -▸ (`n`): `Promise`<`void`\> - -##### Parameters - -| Name | Type | -| :------ | :------ | -| `n` | `number` | - -##### Returns - -`Promise`<`void`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:36 - -___ - -### VolumeParams - -Ƭ **VolumeParams**: `Object` - -Specification of how much volume to (potentially) trade on the semibook. - -`{given:100, to:"buy"}` means buying 100 base tokens. -`{given:100, to:"buy", boundary: 10})` means buying 100 quote tokens for a max. avg. price of 1/10 (boundary/given). - -`{given:10, to:"sell"})` means selling 10 quote tokens. -`{given:10, to:"sell", boundary: 5})` means selling 10 quote tokens for a min. avg. price of 0.5 (given/boundary). - -#### Type declaration - -| Name | Type | Description | -| :------ | :------ | :------ | -| `given` | `Bigish` | Amount of token to trade. | -| `to` | [`BS`](Market-1.md#bs) | Whether `given` is base to be bought or quote to be sold. | -| `boundary?` | `Bigish` | Optional: induce a max avg. price after which to stop buying/selling. | - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:47 - -___ - -### CacheContentsOptions - -Ƭ **CacheContentsOptions**: { `maxOffers?`: `number` } \| { `desiredPrice`: `Bigish` } \| { `desiredVolume`: [`VolumeParams`](Semibook-1.md#volumeparams) } - -Options that specify what the cache fetches and retains. - -`maxOffers`, `desiredPrice`, and `desiredVolume` are mutually exclusive. -If none of these are specified, the default is `maxOffers` = `Semibook.DEFAULT_MAX_OFFERS`. - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:62 - -___ - -### Options - -Ƭ **Options**: [`CacheContentsOptions`](Semibook-1.md#cachecontentsoptions) & { `chunkSize?`: `number` } - -Options that control how the book cache behaves. - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:87 - -___ - -### ResolvedOptions - -Ƭ **ResolvedOptions**: { `maxOffers`: `number` } \| { `desiredPrice`: `Bigish` } \| { `desiredVolume`: [`VolumeParams`](Semibook-1.md#volumeparams) } & { `chunkSize`: `number` } - -Options with defaults resolved - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:97 - -___ - -### State - -Ƭ **State**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `offerCache` | `Map`<`number`, [`Offer`](Market-1.md#offer)\> | -| `bestInCache` | `number` \| `undefined` | -| `worstInCache` | `number` \| `undefined` | - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:146 - -___ - -### FetchOfferListResult - -Ƭ **FetchOfferListResult**: `Result`<[`Offer`](Market-1.md#offer)[], `LogSubscriber.Error`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/semibook.ts:152 diff --git a/docs/SDK/technical-references/code/namespaces/_category_.yml b/docs/SDK/technical-references/code/namespaces/_category_.yml deleted file mode 100644 index 1833bbb5..00000000 --- a/docs/SDK/technical-references/code/namespaces/_category_.yml +++ /dev/null @@ -1,2 +0,0 @@ -label: "Namespaces" -position: 1 \ No newline at end of file diff --git a/docs/SDK/technical-references/code/namespaces/eth.md b/docs/SDK/technical-references/code/namespaces/eth.md deleted file mode 100644 index 636621de..00000000 --- a/docs/SDK/technical-references/code/namespaces/eth.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -id: "eth" -title: "Namespace: eth" -sidebar_label: "eth" -sidebar_position: 0 -custom_edit_url: null ---- - -## Interfaces - -- [CreateSignerOptions](../interfaces/eth.CreateSignerOptions.md) -- [ProviderNetwork](../interfaces/eth.ProviderNetwork.md) - -## Classes - -- [Mnemonic](../classes/eth.Mnemonic.md) diff --git a/docs/SDK/technical-references/code/namespaces/mgvTestUtil.md b/docs/SDK/technical-references/code/namespaces/mgvTestUtil.md deleted file mode 100644 index be86c919..00000000 --- a/docs/SDK/technical-references/code/namespaces/mgvTestUtil.md +++ /dev/null @@ -1,602 +0,0 @@ ---- -id: "mgvTestUtil" -title: "Namespace: mgvTestUtil" -sidebar_label: "mgvTestUtil" -sidebar_position: 0 -custom_edit_url: null ---- - -## Enumerations - -- [AccountName](../enums/mgvTestUtil.AccountName.md) - -## Type Aliases - -### Account - -Ƭ **Account**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `name` | `string` | -| `address` | `string` | -| `signer` | `ethers.Signer` | -| `connectedContracts` | { `mangrove`: `typechain.Mangrove` ; `testMaker`: `typechain.SimpleTestMaker` ; `tokenA`: `typechain.TestToken` ; `tokenB`: `typechain.TestToken` } | -| `connectedContracts.mangrove` | `typechain.Mangrove` | -| `connectedContracts.testMaker` | `typechain.SimpleTestMaker` | -| `connectedContracts.tokenA` | `typechain.TestToken` | -| `connectedContracts.tokenB` | `typechain.TestToken` | - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:10 - -___ - -### Balances - -Ƭ **Balances**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `ether` | `ethers.BigNumber` | -| `tokenA` | `ethers.BigNumber` | -| `tokenB` | `ethers.BigNumber` | - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:23 - -___ - -### AddressAndSigner - -Ƭ **AddressAndSigner**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `address` | `string` | -| `signer` | `string` | - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:31 - -___ - -### Addresses - -Ƭ **Addresses**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `mangrove` | [`AddressAndSigner`](mgvTestUtil.md#addressandsigner) | -| `testMaker` | [`AddressAndSigner`](mgvTestUtil.md#addressandsigner) | -| `tokenA` | [`AddressAndSigner`](mgvTestUtil.md#addressandsigner) | -| `tokenB` | [`AddressAndSigner`](mgvTestUtil.md#addressandsigner) | - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:33 - -___ - -### Contracts - -Ƭ **Contracts**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `mangrove` | `typechain.Mangrove` | -| `testMaker` | `typechain.SimpleTestMaker` | -| `tokenA` | `typechain.TestToken` | -| `tokenB` | `typechain.TestToken` | - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:90 - -___ - -### NewOffer - -Ƭ **NewOffer**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `market` | [`Market`](../classes/Market.md) | -| `ba` | [`BA`](Market-1.md#ba) | -| `maker` | [`Account`](mgvTestUtil.md#account) | -| `wants?` | `ethers.BigNumberish` | -| `gives?` | `ethers.BigNumberish` | -| `gasreq?` | `ethers.BigNumberish` | -| `shouldFail?` | `boolean` | -| `shouldReturnData?` | `boolean` | -| `shouldRevert?` | `boolean` | - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:232 - -## Variables - -### bidsAsks - -• `Const` **bidsAsks**: [`BA`](Market-1.md#ba)[] - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:29 - -___ - -### isTrackingPolls - -• **isTrackingPolls**: `boolean` = `false` - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:244 - -___ - -### eventsForLastTxHaveBeenGeneratedPromise - -• **eventsForLastTxHaveBeenGeneratedPromise**: `Promise`<`void`\> - -Await this when you want to wait for all events corresponding to the last sent tx to have been sent. - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:253 - -## Functions - -### setConfig - -▸ **setConfig**(`_mgv`, `accounts`, `_mgvAdmin`): `void` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `_mgv` | [`Mangrove`](../classes/Mangrove.md) | -| `accounts` | `any` | -| `_mgvAdmin` | [`Mangrove`](../classes/Mangrove.md) | - -#### Returns - -`void` - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:52 - -___ - -### getAddresses - -▸ **getAddresses**(): `Promise`<[`Addresses`](mgvTestUtil.md#addresses)\> - -#### Returns - -`Promise`<[`Addresses`](mgvTestUtil.md#addresses)\> - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:64 - -___ - -### logAddresses - -▸ **logAddresses**(): `Promise`<`void`\> - -#### Returns - -`Promise`<`void`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:83 - -___ - -### getContracts - -▸ **getContracts**(`signer`): `Promise`<[`Contracts`](mgvTestUtil.md#contracts)\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `signer` | `Signer` | - -#### Returns - -`Promise`<[`Contracts`](mgvTestUtil.md#contracts)\> - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:97 - -___ - -### getAccount - -▸ **getAccount**(`name`): `Promise`<[`Account`](mgvTestUtil.md#account)\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `name` | [`AccountName`](../enums/mgvTestUtil.AccountName.md) | - -#### Returns - -`Promise`<[`Account`](mgvTestUtil.md#account)\> - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:128 - -___ - -### getAccountBalances - -▸ **getAccountBalances**(`account`, `provider`): `Promise`<[`Balances`](mgvTestUtil.md#balances)\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `account` | [`Account`](mgvTestUtil.md#account) | -| `provider` | `Provider` | - -#### Returns - -`Promise`<[`Balances`](mgvTestUtil.md#balances)\> - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:141 - -___ - -### getBalances - -▸ **getBalances**(`accounts`, `provider`): `Promise`<`Map`<`string`, [`Balances`](mgvTestUtil.md#balances)\>\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `accounts` | [`Account`](mgvTestUtil.md#account)[] | -| `provider` | `Provider` | - -#### Returns - -`Promise`<`Map`<`string`, [`Balances`](mgvTestUtil.md#balances)\>\> - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:152 - -___ - -### logBalances - -▸ **logBalances**(`accounts`, `balancesBefore`, `balancesAfter`): `Promise`<`void`\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `accounts` | [`Account`](mgvTestUtil.md#account)[] | -| `balancesBefore` | `Map`<`string`, [`Balances`](mgvTestUtil.md#balances)\> | -| `balancesAfter` | `Map`<`string`, [`Balances`](mgvTestUtil.md#balances)\> | - -#### Returns - -`Promise`<`void`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:163 - -___ - -### getTokens - -▸ **getTokens**(`market`, `ba`): `Object` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `market` | [`Market`](../classes/Market.md) | -| `ba` | [`BA`](Market-1.md#ba) | - -#### Returns - -`Object` - -| Name | Type | -| :------ | :------ | -| `inboundToken` | [`MgvToken`](../classes/MgvToken.md) | -| `outboundToken` | [`MgvToken`](../classes/MgvToken.md) | - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:219 - -___ - -### waitForBlock - -▸ **waitForBlock**(`mgv`, `blockNumber`): `Promise`<`void`\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `mgv` | [`Mangrove`](../classes/Mangrove.md) | -| `blockNumber` | `number` | - -#### Returns - -`Promise`<`void`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:257 - -___ - -### initPollOfTransactionTracking - -▸ **initPollOfTransactionTracking**(`provider`): `void` - -Call this to enable tracking of whether the last transaction sent by this library has been mined and polled. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `provider` | `Provider` | - -#### Returns - -`void` - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:296 - -___ - -### stopPollOfTransactionTracking - -▸ **stopPollOfTransactionTracking**(): `void` - -Call this disable tracking of whether the last transaction sent by this library has been mined and polled. - -#### Returns - -`void` - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:306 - -___ - -### waitForTransactions - -▸ **waitForTransactions**(`txPromises`): `Promise`<`TransactionReceipt`[]\> - -Use this to await transactions. In addition to convenience, -it allows us to track when events for the last tx have been generated. -NB: Only works when this is awaited before sending more tx's. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `txPromises` | `PromiseOrValue`<`PromiseOrValue`<`ContractTransaction`\>[]\> | - -#### Returns - -`Promise`<`TransactionReceipt`[]\> - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:317 - -___ - -### waitForOptionalTransaction - -▸ **waitForOptionalTransaction**(`txPromise`): `Promise`<`TransactionReceipt` \| `undefined`\> - -Use this to await transactions or return immediately if promise returns undefined. In addition to convenience, -it allows us to track when events for the last tx have been generated. -NB: Only works when this is awaited before sending more tx's. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `txPromise` | `PromiseOrValue`<`undefined` \| `ContractTransaction`\> | - -#### Returns - -`Promise`<`TransactionReceipt` \| `undefined`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:333 - -___ - -### waitForTransaction - -▸ **waitForTransaction**(`txPromise`): `Promise`<`TransactionReceipt`\> - -Use this to await transactions. In addition to convenience, -it allows us to track when events for the last tx have been generated. -NB: Only works when this is awaited before sending more tx's. - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `txPromise` | `PromiseOrValue`<`ContractTransaction`\> | - -#### Returns - -`Promise`<`TransactionReceipt`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:354 - -___ - -### postNewOffer - -▸ **postNewOffer**(`«destructured»`): `Promise`<`TransactionReceipt`\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `«destructured»` | [`NewOffer`](mgvTestUtil.md#newoffer) | - -#### Returns - -`Promise`<`TransactionReceipt`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:365 - -___ - -### postNewRevertingOffer - -▸ **postNewRevertingOffer**(`market`, `ba`, `maker`): `Promise`<`TransactionReceipt`\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `market` | [`Market`](../classes/Market.md) | -| `ba` | [`BA`](Market-1.md#ba) | -| `maker` | [`Account`](mgvTestUtil.md#account) | - -#### Returns - -`Promise`<`TransactionReceipt`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:407 - -___ - -### postNewSucceedingOffer - -▸ **postNewSucceedingOffer**(`market`, `ba`, `maker`): `Promise`<`TransactionReceipt`\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `market` | [`Market`](../classes/Market.md) | -| `ba` | [`BA`](Market-1.md#ba) | -| `maker` | [`Account`](mgvTestUtil.md#account) | - -#### Returns - -`Promise`<`TransactionReceipt`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:422 - -___ - -### postNewFailingOffer - -▸ **postNewFailingOffer**(`market`, `ba`, `maker`): `Promise`<`TransactionReceipt`\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `market` | [`Market`](../classes/Market.md) | -| `ba` | [`BA`](Market-1.md#ba) | -| `maker` | [`Account`](mgvTestUtil.md#account) | - -#### Returns - -`Promise`<`TransactionReceipt`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:430 - -___ - -### setMgvGasPrice - -▸ **setMgvGasPrice**(`gasPrice`): `Promise`<`void`\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `gasPrice` | `BigNumberish` | - -#### Returns - -`Promise`<`void`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:438 - -___ - -### mint - -▸ **mint**(`token`, `receiver`, `amount`): `Promise`<`void`\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `token` | [`MgvToken`](../classes/MgvToken.md) | -| `receiver` | [`Account`](mgvTestUtil.md#account) | -| `amount` | `number` | - -#### Returns - -`Promise`<`void`\> - -#### Defined in - -@mangrovedao/mangrove.js/src/util/test/mgvIntegrationTestUtil.ts:476 diff --git a/docs/developers/SDK/getting-started/deploy-kandel.md b/docs/developers/SDK/getting-started/deploy-kandel.md index 33de1f1e..cfff25a4 100644 --- a/docs/developers/SDK/getting-started/deploy-kandel.md +++ b/docs/developers/SDK/getting-started/deploy-kandel.md @@ -87,10 +87,10 @@ https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f A brief explanation on the above `seed` parameters: * `onAave` indicates whether or not the liquidity to be used by Kandel is sitting on AAVE - here, it is not the case (it will be fetched from a wallet) * `market`: this is the WETH/USDC pair that we previously chose -* `liquiditySharing` indicates whether you are using shared liquidity or not (SDK only, not available via the UI). This refers to the concept [amplified liquidity](../../../terms/amplified-liquidity.md). +* `liquiditySharing` indicates whether you are using shared liquidity or not (SDK only, not available via the UI). This refers to the concept [amplified liquidity](/docs/developers/terms/amplified-liquidity.md). * `gaspriceFactor`: * By using the `recommendedConfig.gaspriceFactor`, we make sure to select the right amount of gas for our Kandel strategy - * This is also connected to the amount of [bounty](../../../terms/bounty.md) to be paid in case of a failure to deliver + * This is also connected to the amount of [bounty](/docs/developers/terms/bounty.md) to be paid in case of a failure to deliver ### Approve transfers diff --git a/docs/glossary.md b/docs/developers/glossary.md similarity index 100% rename from docs/glossary.md rename to docs/developers/glossary.md diff --git a/docs/developers/strat-lib/guides/howToUnlockLiquidity.md b/docs/developers/strat-lib/guides/howToUnlockLiquidity.md index 99a5ff82..2cee48f3 100644 --- a/docs/developers/strat-lib/guides/howToUnlockLiquidity.md +++ b/docs/developers/strat-lib/guides/howToUnlockLiquidity.md @@ -9,7 +9,7 @@ sidebar_position: 1 In the previous [smart offer tutorial](../getting-started/smart-offer.md), the offer we posted had to receive a transfer liquidity for it to succeed when taken. Now, we want instead to post the offer without transferring tokens from the admin to Mangrove or the `OfferMakerTutorial` (unlocked or %%reactive liquidity|reactive-liquidity%%). This way, the tokens are pulled just-in-time when the offer is taken and can thus be made available for other purposes (ex: generating extra yield in another DeFi protocol). :::info Note -Since you are not committing your liquidity to your smart offer, you can post multiple offers with "unlocked liquidity". We call that [liquidity amplification](../../../terms/amplified-liquidity.md). +Since you are not committing your liquidity to your smart offer, you can post multiple offers with "unlocked liquidity". We call that [liquidity amplification](/docs/developers/terms/amplified-liquidity.md). ::: For this to work, we use a so-called %%router|router%%: it is a contract that can be used to route tokens from the admin to the `OfferMakerTutorial` when the offer is taken.
diff --git a/docs/terms/amplified-liquidity.md b/docs/developers/terms/amplified-liquidity.md similarity index 100% rename from docs/terms/amplified-liquidity.md rename to docs/developers/terms/amplified-liquidity.md diff --git a/docs/terms/bounty.md b/docs/developers/terms/bounty.md similarity index 100% rename from docs/terms/bounty.md rename to docs/developers/terms/bounty.md diff --git a/docs/terms/cleaning-bot.md b/docs/developers/terms/cleaning-bot.md similarity index 100% rename from docs/terms/cleaning-bot.md rename to docs/developers/terms/cleaning-bot.md diff --git a/docs/terms/density.md b/docs/developers/terms/density.md similarity index 100% rename from docs/terms/density.md rename to docs/developers/terms/density.md diff --git a/docs/terms/dual-offer.md b/docs/developers/terms/dual-offer.md similarity index 73% rename from docs/terms/dual-offer.md rename to docs/developers/terms/dual-offer.md index 6f760cce..c64eb4f1 100644 --- a/docs/terms/dual-offer.md +++ b/docs/developers/terms/dual-offer.md @@ -7,4 +7,4 @@ hoverText: An offer that is posted as a consequence of previous offer being take A _dual offer_ is posted by Kandel strategy's [posthook](../strat-lib/technical-references/code/strategies/MangroveOffer#makerposthook) logic. It's an offer that is posted as a consequence of previous offer being taken. ## References -* [Kandel: visual explanation](../kandel/how-does-kandel-work/step-by-step-visual-explanation.md#reposting-liquidity-as-an-ask) \ No newline at end of file +* [Kandel: visual explanation](../../kandel/how-does-kandel-work/step-by-step-visual-explanation.md#reposting-liquidity-as-an-ask) \ No newline at end of file diff --git a/docs/terms/gasLimit.md b/docs/developers/terms/gasLimit.md similarity index 100% rename from docs/terms/gasLimit.md rename to docs/developers/terms/gasLimit.md diff --git a/docs/terms/gasprice.md b/docs/developers/terms/gasprice.md similarity index 100% rename from docs/terms/gasprice.md rename to docs/developers/terms/gasprice.md diff --git a/docs/terms/gasreq.md b/docs/developers/terms/gasreq.md similarity index 100% rename from docs/terms/gasreq.md rename to docs/developers/terms/gasreq.md diff --git a/docs/terms/gives.md b/docs/developers/terms/gives.md similarity index 100% rename from docs/terms/gives.md rename to docs/developers/terms/gives.md diff --git a/docs/terms/hook.md b/docs/developers/terms/hook.md similarity index 100% rename from docs/terms/hook.md rename to docs/developers/terms/hook.md diff --git a/docs/terms/inbound.md b/docs/developers/terms/inbound.md similarity index 100% rename from docs/terms/inbound.md rename to docs/developers/terms/inbound.md diff --git a/docs/terms/keeper-bot.md b/docs/developers/terms/keeper-bot.md similarity index 100% rename from docs/terms/keeper-bot.md rename to docs/developers/terms/keeper-bot.md diff --git a/docs/terms/last-look.md b/docs/developers/terms/last-look.md similarity index 100% rename from docs/terms/last-look.md rename to docs/developers/terms/last-look.md diff --git a/docs/terms/maker-contract.md b/docs/developers/terms/maker-contract.md similarity index 100% rename from docs/terms/maker-contract.md rename to docs/developers/terms/maker-contract.md diff --git a/docs/terms/maker-partial-fill.md b/docs/developers/terms/maker-partial-fill.md similarity index 100% rename from docs/terms/maker-partial-fill.md rename to docs/developers/terms/maker-partial-fill.md diff --git a/docs/terms/makerExecute.md b/docs/developers/terms/makerExecute.md similarity index 100% rename from docs/terms/makerExecute.md rename to docs/developers/terms/makerExecute.md diff --git a/docs/terms/makerPosthook.md b/docs/developers/terms/makerPosthook.md similarity index 100% rename from docs/terms/makerPosthook.md rename to docs/developers/terms/makerPosthook.md diff --git a/docs/terms/offer-entailed-price.md b/docs/developers/terms/offer-entailed-price.md similarity index 100% rename from docs/terms/offer-entailed-price.md rename to docs/developers/terms/offer-entailed-price.md diff --git a/docs/terms/offer-id.md b/docs/developers/terms/offer-id.md similarity index 100% rename from docs/terms/offer-id.md rename to docs/developers/terms/offer-id.md diff --git a/docs/terms/offer-list.md b/docs/developers/terms/offer-list.md similarity index 100% rename from docs/terms/offer-list.md rename to docs/developers/terms/offer-list.md diff --git a/docs/terms/offer-logic.md b/docs/developers/terms/offer-logic.md similarity index 100% rename from docs/terms/offer-logic.md rename to docs/developers/terms/offer-logic.md diff --git a/docs/terms/offer-owner.md b/docs/developers/terms/offer-owner.md similarity index 100% rename from docs/terms/offer-owner.md rename to docs/developers/terms/offer-owner.md diff --git a/docs/terms/offer-rank.md b/docs/developers/terms/offer-rank.md similarity index 100% rename from docs/terms/offer-rank.md rename to docs/developers/terms/offer-rank.md diff --git a/docs/terms/on-the-fly-offer.md b/docs/developers/terms/on-the-fly-offer.md similarity index 86% rename from docs/terms/on-the-fly-offer.md rename to docs/developers/terms/on-the-fly-offer.md index 18c1096c..b7a52d31 100644 --- a/docs/terms/on-the-fly-offer.md +++ b/docs/developers/terms/on-the-fly-offer.md @@ -8,7 +8,7 @@ An *on-the-fly offer* is posted by an EOA (i.e., an Externally-Owned Account, cf An on-the-fly offer can be listed on Mangrove but is not equipped with any on-chain [logic](../contracts/technical-references/taking-and-making-offers/reactive-offer/README.md) that executes when the offer is taken. -Whenever an on-the-fly offer is matched by a [taker order](contracts/background/offer-taker.md#taking-offers), the offer sources its liquidity on the EOA. +Whenever an on-the-fly offer is matched by a [taker order](../contracts/background/offer-taker.md#taking-offers), the offer sources its liquidity on the EOA. :::caution diff --git a/docs/terms/outbound.md b/docs/developers/terms/outbound.md similarity index 100% rename from docs/terms/outbound.md rename to docs/developers/terms/outbound.md diff --git a/docs/terms/pivot-id.md b/docs/developers/terms/pivot-id.md similarity index 100% rename from docs/terms/pivot-id.md rename to docs/developers/terms/pivot-id.md diff --git a/docs/terms/provision.md b/docs/developers/terms/provision.md similarity index 100% rename from docs/terms/provision.md rename to docs/developers/terms/provision.md diff --git a/docs/terms/reactive-liquidity.md b/docs/developers/terms/reactive-liquidity.md similarity index 100% rename from docs/terms/reactive-liquidity.md rename to docs/developers/terms/reactive-liquidity.md diff --git a/docs/terms/renege.md b/docs/developers/terms/renege.md similarity index 100% rename from docs/terms/renege.md rename to docs/developers/terms/renege.md diff --git a/docs/terms/reserve-id.md b/docs/developers/terms/reserve-id.md similarity index 100% rename from docs/terms/reserve-id.md rename to docs/developers/terms/reserve-id.md diff --git a/docs/terms/router.md b/docs/developers/terms/router.md similarity index 100% rename from docs/terms/router.md rename to docs/developers/terms/router.md diff --git a/docs/terms/smart-offer.md b/docs/developers/terms/smart-offer.md similarity index 100% rename from docs/terms/smart-offer.md rename to docs/developers/terms/smart-offer.md diff --git a/docs/terms/taker-fee.md b/docs/developers/terms/taker-fee.md similarity index 100% rename from docs/terms/taker-fee.md rename to docs/developers/terms/taker-fee.md diff --git a/docs/terms/wants.md b/docs/developers/terms/wants.md similarity index 100% rename from docs/terms/wants.md rename to docs/developers/terms/wants.md diff --git a/docs/high-level/audits.md b/docs/high-level/audits.md index 67400573..f9aa0638 100644 --- a/docs/high-level/audits.md +++ b/docs/high-level/audits.md @@ -15,7 +15,7 @@ Mangrove has been thoroughly audited. You will find here official reports of the * Kandel audit :::note -* [MangroveOrder](../strat-lib/technical-references/code/strategies/MangroveOrder.md) is a peripheral contract for the Mangrove core protocol which allows users to submit limit orders such as: +* [MangroveOrder](../developers/strat-lib/technical-references/code/strategies/MangroveOrder.md) is a peripheral contract for the Mangrove core protocol which allows users to submit limit orders such as: * [Good-til-cancelled](../web-app/trade/more-on-order-types.md#good-til-time-gtt) (GTC, or GTT) * [Fill-or-kill](../web-app/trade/more-on-order-types.md#fill-or-kill-fok) (FOK) diff --git a/docs/high-level/concepts/bounty.md b/docs/high-level/concepts/bounty.md index 47d6913c..2b7d2bd2 100644 --- a/docs/high-level/concepts/bounty.md +++ b/docs/high-level/concepts/bounty.md @@ -8,7 +8,7 @@ sidebar_position: 2 What if everyone makes empty promises, and the offers in the book are all meant to fail? -This is where Makers **must leave a native token provision ([the bounty](../../terms/bounty.md))** in their offer. Nothing prevents them from posting offers that will always fail. So, to ensure that the offers displayed on the book are credible, it must be costly for Makers to post orders that are not meant to go through. And in that case scenario, the bounty is then given to the Taker as compensation. 💎 +This is where Makers **must leave a native token provision ([the bounty](/docs/developers/terms/bounty.md))** in their offer. Nothing prevents them from posting offers that will always fail. So, to ensure that the offers displayed on the book are credible, it must be costly for Makers to post orders that are not meant to go through. And in that case scenario, the bounty is then given to the Taker as compensation. 💎 At first glance, this might seem one-sided in favor of Makers. However, with powerful market making features to accept or cancel offers, Makers reduce their risk and can offer better prices. In the end, both Makers and Takers win: the possibility of **offers failing is a necessity** for the power of smart offers. diff --git a/docs/high-level/concepts/makers-takers-keepers/keepers.md b/docs/high-level/concepts/makers-takers-keepers/keepers.md index a4ee6937..d5957a90 100644 --- a/docs/high-level/concepts/makers-takers-keepers/keepers.md +++ b/docs/high-level/concepts/makers-takers-keepers/keepers.md @@ -6,6 +6,6 @@ sidebar_position: 3 # Keepers -Mangrove's order book may be cluttered over time with irrelevant orders when the market conditions evolvent. Therefore, bots (or [Keepers](../../../keeper-bots/README.md)) are continuously scanning the book. They are responsible for detecting failing offers and making them fail on-chain by "[sniped](../../../contracts/technical-references/taking-and-making-offers/taker-order/#offer-sniping)" them, with a gas price set such that the offer's bounty compensates for the spent gas. They act as [guardians](../../../keeper-bots/background/the-role-of-cleaning-bots-in-mangrove) of the Mangrove ecosystem. 🤖 +Mangrove's order book may be cluttered over time with irrelevant orders when the market conditions evolvent. Therefore, bots (or [Keepers](../../../developers/keeper-bots/README.md)) are continuously scanning the book. They are responsible for detecting failing offers and making them fail on-chain by "[sniped](../../../developers/contracts/technical-references/taking-and-making-offers/taker-order/#offer-sniping)" them, with a gas price set such that the offer's bounty compensates for the spent gas. They act as [guardians](../../../developers/keeper-bots/background/the-role-of-cleaning-bots-in-mangrove) of the Mangrove ecosystem. 🤖 -Keepers are also in charge of [keeping the gas price updated](../../../keeper-bots/background/the-role-of-gas-price-updater-bots-in-mangrove) to determine the remuneration of takers for removing a failing offer from a list. \ No newline at end of file +Keepers are also in charge of [keeping the gas price updated](../../../developers/keeper-bots/background/the-role-of-gas-price-updater-bots-in-mangrove) to determine the remuneration of takers for removing a failing offer from a list. \ No newline at end of file diff --git a/docs/high-level/concepts/makers-takers-keepers/makers.md b/docs/high-level/concepts/makers-takers-keepers/makers.md index f4343241..ab343f93 100644 --- a/docs/high-level/concepts/makers-takers-keepers/makers.md +++ b/docs/high-level/concepts/makers-takers-keepers/makers.md @@ -8,7 +8,7 @@ sidebar_position: 1 They create and own the offers on Mangrove. For example, they promise to give a Taker some apples 🍎 if he gives them oranges 🍊 in return. That is why Mangrove is beautiful: Makers can plant their apples in their garden, or someone else's, until a Taker that wants some apples picks their offer. -We are explaining Makers in more detail in the [Developer section](../../../contracts/technical-references/overview.md#makers) (relax, it's still very much understandable). +We are explaining Makers in more detail in the [Developer section](../../../developers/contracts/technical-references/overview.md#makers) (relax, it's still very much understandable). import useBaseUrl from '@docusaurus/useBaseUrl'; diff --git a/docs/high-level/concepts/makers-takers-keepers/takers.md b/docs/high-level/concepts/makers-takers-keepers/takers.md index 0dab1961..0c1ed7da 100644 --- a/docs/high-level/concepts/makers-takers-keepers/takers.md +++ b/docs/high-level/concepts/makers-takers-keepers/takers.md @@ -6,15 +6,15 @@ sidebar_position: 2 # Takers -Just like a classical orderbook, the Taker can buy or sell assets on Mangrove, with [market](../../../web-app/trade/how-to-market-order.md) or [limit orders](../../../web-app/trade/how-to-limit-order.md). Offers can be taken using general orders or "[sniped](../../../contracts/technical-references/taking-and-making-offers/taker-order/#offer-sniping)" individually, as part of the strategies enabled by Mangrove's platform design. 🧿 +Just like a classical orderbook, the Taker can buy or sell assets on Mangrove, with [market](../../../web-app/trade/how-to-market-order.md) or [limit orders](../../../web-app/trade/how-to-limit-order.md). Offers can be taken using general orders or "[sniped](../../../developers/contracts/technical-references/taking-and-making-offers/taker-order/#offer-sniping)" individually, as part of the strategies enabled by Mangrove's platform design. 🧿 -Takers may typically operate via a web front-end or with the help of our [SDK](../../../SDK/README.md) to develop off-chain apps that interact with Mangrove ecosystem. +Takers may typically operate via a web front-end or with the help of our [SDK](../../../developers/SDK/README.md) to develop off-chain apps that interact with Mangrove ecosystem. When the Taker sends an order, Mangrove executes the offer logic (i.e. code) of all the smart offers it triggers: * If the first order is successful and the liquidity promise is fulfilled, it is removed from the book. Mangrove moves on to the next offer until the entirety of the Taker's order is filled (whether it's a limit or market order). -* If during the execution, a Maker backs out on his offer (see previous [last look](../smart-offers.md)), and the liquidity is not matched, a penalty ([bounty](../../../terms/bounty.md)) is paid to the Taker and Mangrove executes the next offer logic from the orderbook, until the desired volume or limit price is hit. +* If during the execution, a Maker backs out on his offer (see previous [last look](../smart-offers.md)), and the liquidity is not matched, a penalty ([bounty](/docs/developers/terms/bounty.md)) is paid to the Taker and Mangrove executes the next offer logic from the orderbook, until the desired volume or limit price is hit. import useBaseUrl from '@docusaurus/useBaseUrl'; diff --git a/docs/high-level/concepts/smart-offers.md b/docs/high-level/concepts/smart-offers.md index 7c0d54f3..8e1e0a6d 100644 --- a/docs/high-level/concepts/smart-offers.md +++ b/docs/high-level/concepts/smart-offers.md @@ -6,7 +6,7 @@ sidebar_position: 1 # Smart offers -The main difference between Mangrove and other DEXs is the ability to attach code to offers (check out [Smart Offers](../../terms/smart-offer.md) for more information). +The main difference between Mangrove and other DEXs is the ability to attach code to offers (check out [Smart Offers](/docs/developers/terms/smart-offer.md) for more information). This translates into several disruptive mechanisms: * **Reactive liquidity**⚡
diff --git a/docs/kandel/details-on-strats/details-on-strats.md b/docs/kandel/details-on-strats/details-on-strats.md index fd808006..7481a5c5 100644 --- a/docs/kandel/details-on-strats/details-on-strats.md +++ b/docs/kandel/details-on-strats/details-on-strats.md @@ -34,4 +34,4 @@ Here is more information on the inventory requirements:
## Build your own strategy -Our [Strategy Library](../../strat-lib/README.md) contains a set of contracts and building blocks that can be used to implement custom market making strategies. \ No newline at end of file +Our [Strategy Library](../../developers/strat-lib/README.md) contains a set of contracts and building blocks that can be used to implement custom market making strategies. \ No newline at end of file diff --git a/docs/kandel/how-does-kandel-work/how-does-kandel-work.md b/docs/kandel/how-does-kandel-work/how-does-kandel-work.md index 20202cda..a9ae4318 100644 --- a/docs/kandel/how-does-kandel-work/how-does-kandel-work.md +++ b/docs/kandel/how-does-kandel-work/how-does-kandel-work.md @@ -17,4 +17,4 @@ For a detailed explanation on how to create and manage a Kandel strategy on Mang ## Vocabulary -If some keywords and concepts are new to you, feel free to check our [Glossary](../../glossary.md) and [FAQ](../../FAQ/README.md). \ No newline at end of file +If some keywords and concepts are new to you, feel free to check our [Glossary](../../developers/glossary.md) and [FAQ](../../FAQ/README.md). \ No newline at end of file diff --git a/docs/kandel/how-does-kandel-work/more-on-failing-offers.md b/docs/kandel/how-does-kandel-work/more-on-failing-offers.md index 853890fe..ff019412 100644 --- a/docs/kandel/how-does-kandel-work/more-on-failing-offers.md +++ b/docs/kandel/how-does-kandel-work/more-on-failing-offers.md @@ -15,14 +15,14 @@ This section explains the reasons why some offers might fail using Kandel. When we talk about an offer "failing", we mean that it could not execute. An offer can also fail to update itself. While we won't go into details in this part of the documentation, it is important to mention and differentiate those cases to further understand Kandel strategy's behavior. * [`makerExecute()`](../../strat-lib/technical-references/code/strategies/MangroveOffer/#makerexecute): it is the callback function that is called when an offer is matched. Its role is to execute all offers that were posted on Mangrove by a given contract. - * A failure in `makerExecute()` means the trade is canceled, and the [bounty](../../terms/bounty) is given to the Taker as a [compensation](../../contracts/technical-references/taking-and-making-offers/taker-order/#bounties-for-taking-failing-offers). The offer is removed from the book. + * A failure in `makerExecute()` means the trade is canceled, and the [bounty](/docs/developers/terms/bounty) is given to the Taker as a [compensation](../../developers/contracts/technical-references/taking-and-making-offers/taker-order/#bounties-for-taking-failing-offers). The offer is removed from the book. -* [`makerPosthook()`](../../strat-lib/technical-references/code/strategies/MangroveOffer/#makerposthook): it is the callback function that is called after the offer execution (i.e. after a successful execution of `makerExecute()`). +* [`makerPosthook()`](../../developers/strat-lib/technical-references/code/strategies/MangroveOffer/#makerposthook): it is the callback function that is called after the offer execution (i.e. after a successful execution of `makerExecute()`). * A failure in `makerPosthook()` means the offer cannot update or repost itself after being taken. It does not cancel the trade, since it is called after `makerExecute()`. > 💡 -> For a more visual explanation, see the [call sequence overview](../../contracts/technical-references/overview#call-sequence-overview) diagram. +> For a more visual explanation, see the [call sequence overview](../../developers/contracts/technical-references/overview#call-sequence-overview) diagram. ## Kandel and `makerExecute()` failure @@ -44,10 +44,10 @@ Non-reposted liquidity will be placed into the [Unallocated liquidity](./strateg
-Reposting offers is handled with [`makerPosthook()`](../../strat-lib/technical-references/code/strategies/MangroveOffer/#makerposthook), and failure could happen if: +Reposting offers is handled with [`makerPosthook()`](../../developers/strat-lib/technical-references/code/strategies/MangroveOffer/#makerposthook), and failure could happen if: -* The residual of a partially taken offer is too small with regard to [density](../../terms/density): - * A partially taken offer is the result of a Taker either partially [sniping](../../contracts/technical-references/taking-and-making-offers/taker-order/#offer-sniping) an offer, or placing a Market order +* The residual of a partially taken offer is too small with regard to [density](/docs/developers/terms/density): + * A partially taken offer is the result of a Taker either partially [sniping](../../developers/developers/developers/contracts/technical-references/taking-and-making-offers/taker-order/#offer-sniping) an offer, or placing a Market order * If an offer is almost entirely taken, the remainder (dust) could be too small to pass the density check, leading to a failure to repost itself diff --git a/docs/kandel/how-does-kandel-work/parameters.md b/docs/kandel/how-does-kandel-work/parameters.md index 94eaae05..34b27c78 100644 --- a/docs/kandel/how-does-kandel-work/parameters.md +++ b/docs/kandel/how-does-kandel-work/parameters.md @@ -15,7 +15,7 @@ Price range | The price range is needed to run any market-making strategy. It co Current price | The current price of the base token that is used for constructing the price distribution.

*Example: the price of ETH is used for the ETH/USDC pair* Number of price points | The number of price points on which Kandel will deploy its liquidity (bids and asks). Ratio | The ratio of the progression used to calculate the price grid. It is directly linked to the number of price points. -Step size | It is the distance between an executed bid/ask and its [dual offer](../../terms/dual-offer.md).

Whenever a Kandel ask is taken at a given price point, Kandel uses the amount of quote just received to place a bid at a lower price point. With a step size of 1, it will place the bid at the price point immediately below. With a step size of 2, Kandel will repost two price points below, etc. (Technical aside: if in attempting to repost say 3 steps below Kandel hits the boundaries of its range it will transport as far below as possible). The same applies symmetrically for bids.

Using a step size ≥ 2 allows one to publish a more continuous liquidity on the books, regularising the strat’s PnL, while at the same time keeping a reasonable spread between price points. Indeed, what matters to PnL is not the distance between price points, but how far money moves along the price grid each time an offer is taken. -Initial inventory | The initial inventory is the amount of base tokens and quote tokens that must be deposited into the strategy. The minimum to be deposited into the strategy depends on the selected price range and [density](../../terms/density.md) of the selected market.

*Example on the ETH/USDC pair:
• Base token is ETH
• Quote token is USDC* -[Bounty](../../terms/bounty.md) | It is the required amount of native tokens to be deposited into the strategy. A [provision](../../terms/provision.md) is required to post an offer, in order to pay a potential [bounty](../../terms/bounty.md). The bounty is only a subset, smaller in value than the provision.

The provision covers the whole price grid, hence:
• *Kandel provision = Provision per offer x Number of price points x 2*
• Note: we add a "x2" factor since each price point could be both an ask and a bid.

*Example: if the selected pair is on the Polygon network, the bounty would be an amount of MATIC tokens.* +Step size | It is the distance between an executed bid/ask and its [dual offer](/docs/developers/terms/dual-offer.md).

Whenever a Kandel ask is taken at a given price point, Kandel uses the amount of quote just received to place a bid at a lower price point. With a step size of 1, it will place the bid at the price point immediately below. With a step size of 2, Kandel will repost two price points below, etc. (Technical aside: if in attempting to repost say 3 steps below Kandel hits the boundaries of its range it will transport as far below as possible). The same applies symmetrically for bids.

Using a step size ≥ 2 allows one to publish a more continuous liquidity on the books, regularising the strat’s PnL, while at the same time keeping a reasonable spread between price points. Indeed, what matters to PnL is not the distance between price points, but how far money moves along the price grid each time an offer is taken. +Initial inventory | The initial inventory is the amount of base tokens and quote tokens that must be deposited into the strategy. The minimum to be deposited into the strategy depends on the selected price range and [density](/docs/developers/terms/density.md) of the selected market.

*Example on the ETH/USDC pair:
• Base token is ETH
• Quote token is USDC* +[Bounty](/docs/developers/terms/bounty.md) | It is the required amount of native tokens to be deposited into the strategy. A [provision](/docs/developers/terms/provision.md) is required to post an offer, in order to pay a potential [bounty](/docs/developers/terms/bounty.md). The bounty is only a subset, smaller in value than the provision.

The provision covers the whole price grid, hence:
• *Kandel provision = Provision per offer x Number of price points x 2*
• Note: we add a "x2" factor since each price point could be both an ask and a bid.

*Example: if the selected pair is on the Polygon network, the bounty would be an amount of MATIC tokens.* Compounding rate | The compounding rate is the percentage of the spread to be reinvested into the strategy.
It can be set between 0% and 100% (SDK users only). \ No newline at end of file diff --git a/docs/web-app/strategies/create-strat.md b/docs/web-app/strategies/create-strat.md index 6c802b0b..65825316 100644 --- a/docs/web-app/strategies/create-strat.md +++ b/docs/web-app/strategies/create-strat.md @@ -73,7 +73,7 @@ Risk appetite:
-10. "Waiting for confirmation": you will be asked to sign 4 transactions in a row, including the deployment of your Kandel contract, the spending approvals of your pair's tokens, and the native token amount to be deposited for [bounty](../../glossary.md#bounty). +10. "Waiting for confirmation": you will be asked to sign 4 transactions in a row, including the deployment of your Kandel contract, the spending approvals of your pair's tokens, and the native token amount to be deposited for [bounty](../../developers/glossary.md#bounty). > 💡 > when signing on Metmamask, select "Use default" to set the appropriate amount of Approval. diff --git a/docs/web-app/strategies/manage-strat/parameters-tab.md b/docs/web-app/strategies/manage-strat/parameters-tab.md index 438a565f..98d23651 100644 --- a/docs/web-app/strategies/manage-strat/parameters-tab.md +++ b/docs/web-app/strategies/manage-strat/parameters-tab.md @@ -62,5 +62,5 @@ You can perform the following actions: ## Bounty -Use the "Add bounty" button to top up the amount of [bounty](../../../terms/bounty) you leave available to your Kandel strategy. +Use the "Add bounty" button to top up the amount of [bounty](/docs/devopers/terms/bounty) you leave available to your Kandel strategy. The bounty is a provision (in the network's native token) sent to the taker to compensate for a [failure to deliver](../../../kandel/how-does-kandel-work/more-on-failing-offers.md). It is a requirement for all offers published on Mangrove markets. \ No newline at end of file diff --git a/docs/web-app/strategies/manage-strat/statuses-and-alerts.md b/docs/web-app/strategies/manage-strat/statuses-and-alerts.md index 7135c794..cb9e0fd3 100644 --- a/docs/web-app/strategies/manage-strat/statuses-and-alerts.md +++ b/docs/web-app/strategies/manage-strat/statuses-and-alerts.md @@ -15,7 +15,7 @@ Your strategy can have one of three statuses: active, inactive, or closed. Depen It means that your strategy is running, profiting from the spread. You may see one of these alert messages while your strategy is active: * **"About to be out of bounty" button**
-Your trategy will soon run out of [bounty](../../../terms/bounty.md) to pay for the taker's compensation in case an [offer fails to execute](../../../kandel/how-does-kandel-work/more-on-failing-offers.md). +Your trategy will soon run out of [bounty](/docs/developers/terms/bounty.md) to pay for the taker's compensation in case an [offer fails to execute](../../../kandel/how-does-kandel-work/more-on-failing-offers.md). * **"About to be out of price range" button**
Your strategy's price range is close to being out of range. diff --git a/docs/web-app/trade/how-to-limit-order.md b/docs/web-app/trade/how-to-limit-order.md index dc554905..1637ac91 100644 --- a/docs/web-app/trade/how-to-limit-order.md +++ b/docs/web-app/trade/how-to-limit-order.md @@ -25,7 +25,7 @@ import useBaseUrl from '@docusaurus/useBaseUrl'; 5. Choose from 3 types of limit orders: * **Immediate or Cancel (IOC)**: Your order attempts to execute immediately at the desired price. If successful, it's executed; if not, it's canceled. * **Good 'til time (GTT)**: Set an expiration date for your order (ex: active for 3 days, then canceled). - * [**Fill or Kill (FOK)**](../../SDK/guides/fill-or-kill.md): Your order is either executed fully or not executed at all (ex: you place an order for 1 ETH at $9,500; if only 0.8 ETH can be filled, it's canceled; if fully filled, it's executed). + * [**Fill or Kill (FOK)**](../../developers/SDK/guides/fill-or-kill.md): Your order is either executed fully or not executed at all (ex: you place an order for 1 ETH at $9,500; if only 0.8 ETH can be filled, it's canceled; if fully filled, it's executed). > 💡 > If a "Good 'til time" limit order is [partially filled](./how-to-track-open-orders.md#order-is-partially-filled), a green message will display the transactino details, and the remainder will be reposted automatically. diff --git a/docusaurus.config.js b/docusaurus.config.js index 293f9f9e..23e49f44 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -37,8 +37,8 @@ const config = { plugins: [ ['@docusaurus-terminology/parser', { - "termsUrl": "/terms/", - "termsDir": "./docs/terms/" + "termsUrl": "/developers/terms/", + "termsDir": "./docs/developers/terms/" } ], require.resolve('docusaurus-lunr-search'), @@ -50,7 +50,7 @@ const config = { { "entryPoints": ["node_modules/@mangrovedao/mangrove.js/src/index.ts"], "tsconfig": "node_modules/@mangrovedao/mangrove.js/tsconfig.json", - "out": "SDK/technical-references/code", + "out": "developers/SDK/technical-references/code", "cleanOutputDir": true, "excludePrivate": true, "excludeInternal": true, diff --git a/sidebars.js b/sidebars.js index d9adf86d..b1df313c 100644 --- a/sidebars.js +++ b/sidebars.js @@ -82,8 +82,8 @@ const sidebars = { href: 'https://mangrove.exchange/', }, { - type: 'doc', - id: 'glossary', + type: 'link', + href: '/developers/glossary', label: '🔤 Glossary', }, { @@ -194,8 +194,8 @@ const sidebars = { href: 'https://mangrove.exchange/', }, { - type: 'link', - href: '/glossary', + type: 'doc', + id: 'developers/glossary', label: '🔤 Glossary', }, { From 7cae8d0ec5689e8a06cebfa3a5dbb0c48a0c7b51 Mon Sep 17 00:00:00 2001 From: Troels Damgaard Date: Fri, 13 Oct 2023 12:14:23 +0200 Subject: [PATCH 18/38] typo --- docs/web-app/trade/how-to-limit-order.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/web-app/trade/how-to-limit-order.md b/docs/web-app/trade/how-to-limit-order.md index 1637ac91..ff523d38 100644 --- a/docs/web-app/trade/how-to-limit-order.md +++ b/docs/web-app/trade/how-to-limit-order.md @@ -28,7 +28,7 @@ import useBaseUrl from '@docusaurus/useBaseUrl'; * [**Fill or Kill (FOK)**](../../developers/SDK/guides/fill-or-kill.md): Your order is either executed fully or not executed at all (ex: you place an order for 1 ETH at $9,500; if only 0.8 ETH can be filled, it's canceled; if fully filled, it's executed). > 💡 -> If a "Good 'til time" limit order is [partially filled](./how-to-track-open-orders.md#order-is-partially-filled), a green message will display the transactino details, and the remainder will be reposted automatically. +> If a "Good 'til time" limit order is [partially filled](./how-to-track-open-orders.md#order-is-partially-filled), a green message will display the transaction details, and the remainder will be reposted automatically. 6. Click on "Approve and buy/sell". A card will appear, tick the infinite approval box, click on "Allow 'token'" and confirm the transaction on your wallet. From fbfa4649c65bb782eee7ef6a2903cef83e09c7c8 Mon Sep 17 00:00:00 2001 From: Troels Damgaard Date: Fri, 13 Oct 2023 13:36:51 +0200 Subject: [PATCH 19/38] fix sidebars link --- sidebars.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sidebars.js b/sidebars.js index b1df313c..b94cb8c2 100644 --- a/sidebars.js +++ b/sidebars.js @@ -89,7 +89,7 @@ const sidebars = { { type: 'link', label: '🏗️ Developers', // The link label - href: '/developers/README', + href: 'developers/README', }, ], }, From 06817aed9ea8f4f92468abbdc842729483fba526 Mon Sep 17 00:00:00 2001 From: Troels Damgaard Date: Fri, 13 Oct 2023 13:38:45 +0200 Subject: [PATCH 20/38] temp remove developers/README link --- sidebars.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sidebars.js b/sidebars.js index b94cb8c2..a666ab20 100644 --- a/sidebars.js +++ b/sidebars.js @@ -86,11 +86,6 @@ const sidebars = { href: '/developers/glossary', label: '🔤 Glossary', }, - { - type: 'link', - label: '🏗️ Developers', // The link label - href: 'developers/README', - }, ], }, { From 7a6a476f2b3c8738dcb96d1e19225f642b9d851f Mon Sep 17 00:00:00 2001 From: Troels Damgaard Date: Fri, 13 Oct 2023 13:46:05 +0200 Subject: [PATCH 21/38] fix links --- .../the-role-of-gas-price-updater-bots-in-mangrove.md | 2 +- docs/kandel/how-does-kandel-work/more-on-failing-offers.md | 6 +++--- docs/web-app/strategies/manage-strat/parameters-tab.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/developers/keeper-bots/background/the-role-of-gas-price-updater-bots-in-mangrove.md b/docs/developers/keeper-bots/background/the-role-of-gas-price-updater-bots-in-mangrove.md index 361d805c..b5c2d926 100644 --- a/docs/developers/keeper-bots/background/the-role-of-gas-price-updater-bots-in-mangrove.md +++ b/docs/developers/keeper-bots/background/the-role-of-gas-price-updater-bots-in-mangrove.md @@ -4,7 +4,7 @@ sidebar_position: 2 # The role of gas price updater bots in Mangrove -Mangrove needs the gas price to [determine the remuneration](../../contracts/technical-references/taking-and-making-offers/reactive-offer/offer-provision.md#bounty) of takers for removing a failing offer from a list. On chains where the gas price varies, Mangrove [uses](/contracts/technical-references/governance-parameters/global-variables) an [oracle](/contracts/technical-references/periphery/oracle) to get the gas price. +Mangrove needs the gas price to [determine the remuneration](../../contracts/technical-references/taking-and-making-offers/reactive-offer/offer-provision.md#bounty) of takers for removing a failing offer from a list. On chains where the gas price varies, Mangrove [uses](../../contracts/technical-references/governance-parameters/global-variables) an [oracle](../../contracts/technical-references/periphery/oracle) to get the gas price. The role of the gas price updater bot is simply to push up-to-date gas prices to the oracle contract whenever the gas price changes significantly. diff --git a/docs/kandel/how-does-kandel-work/more-on-failing-offers.md b/docs/kandel/how-does-kandel-work/more-on-failing-offers.md index ff019412..2241812e 100644 --- a/docs/kandel/how-does-kandel-work/more-on-failing-offers.md +++ b/docs/kandel/how-does-kandel-work/more-on-failing-offers.md @@ -14,7 +14,7 @@ This section explains the reasons why some offers might fail using Kandel. When we talk about an offer "failing", we mean that it could not execute. An offer can also fail to update itself. While we won't go into details in this part of the documentation, it is important to mention and differentiate those cases to further understand Kandel strategy's behavior. -* [`makerExecute()`](../../strat-lib/technical-references/code/strategies/MangroveOffer/#makerexecute): it is the callback function that is called when an offer is matched. Its role is to execute all offers that were posted on Mangrove by a given contract. +* [`makerExecute()`](../../developers/strat-lib/technical-references/code/strategies/MangroveOffer/#makerexecute): it is the callback function that is called when an offer is matched. Its role is to execute all offers that were posted on Mangrove by a given contract. * A failure in `makerExecute()` means the trade is canceled, and the [bounty](/docs/developers/terms/bounty) is given to the Taker as a [compensation](../../developers/contracts/technical-references/taking-and-making-offers/taker-order/#bounties-for-taking-failing-offers). The offer is removed from the book. @@ -27,7 +27,7 @@ When we talk about an offer "failing", we mean that it could not execute. An off ## Kandel and `makerExecute()` failure After launching a Kandel strategy, Bids and Asks are populated with a [certain volume](./parameters.md). Kandel strategy's contract is handling all the posting for the user, using liquidity that has been previously deposited.
-Therefore, since the user is not in charge of writing and maintaining the smart contract, failures to execute [`makerExecute()`](../../strat-lib/technical-references/code/strategies/MangroveOffer/#makerexecute) can be almost entirely ruled out, with the exception of some very specific scenarios such as: +Therefore, since the user is not in charge of writing and maintaining the smart contract, failures to execute [`makerExecute()`](../../developers/strat-lib/technical-references/code/strategies/MangroveOffer/#makerexecute) can be almost entirely ruled out, with the exception of some very specific scenarios such as: * Someone severely modifies the volume distribution/sourcing methods, creating issues when a Kandel Bid/Ask is taken (via the SDK) @@ -47,7 +47,7 @@ Non-reposted liquidity will be placed into the [Unallocated liquidity](./strateg Reposting offers is handled with [`makerPosthook()`](../../developers/strat-lib/technical-references/code/strategies/MangroveOffer/#makerposthook), and failure could happen if: * The residual of a partially taken offer is too small with regard to [density](/docs/developers/terms/density): - * A partially taken offer is the result of a Taker either partially [sniping](../../developers/developers/developers/contracts/technical-references/taking-and-making-offers/taker-order/#offer-sniping) an offer, or placing a Market order + * A partially taken offer is the result of a Taker either partially [sniping](../../developers/contracts/technical-references/taking-and-making-offers/taker-order/#offer-sniping) an offer, or placing a Market order * If an offer is almost entirely taken, the remainder (dust) could be too small to pass the density check, leading to a failure to repost itself diff --git a/docs/web-app/strategies/manage-strat/parameters-tab.md b/docs/web-app/strategies/manage-strat/parameters-tab.md index 98d23651..38a2b587 100644 --- a/docs/web-app/strategies/manage-strat/parameters-tab.md +++ b/docs/web-app/strategies/manage-strat/parameters-tab.md @@ -62,5 +62,5 @@ You can perform the following actions: ## Bounty -Use the "Add bounty" button to top up the amount of [bounty](/docs/devopers/terms/bounty) you leave available to your Kandel strategy. +Use the "Add bounty" button to top up the amount of [bounty](/docs/developers/terms/bounty) you leave available to your Kandel strategy. The bounty is a provision (in the network's native token) sent to the taker to compensate for a [failure to deliver](../../../kandel/how-does-kandel-work/more-on-failing-offers.md). It is a requirement for all offers published on Mangrove markets. \ No newline at end of file From d176ce97415368ae94bec924cf62e6cbed09b9c5 Mon Sep 17 00:00:00 2001 From: Troels Damgaard Date: Fri, 13 Oct 2023 13:51:50 +0200 Subject: [PATCH 22/38] term links --- docs/developers/strat-lib/guides/howToUnlockLiquidity.md | 2 +- docs/high-level/concepts/bounty.md | 2 +- docs/high-level/concepts/makers-takers-keepers/takers.md | 2 +- docs/high-level/concepts/smart-offers.md | 2 +- docs/kandel/how-does-kandel-work/more-on-failing-offers.md | 4 ++-- docs/kandel/how-does-kandel-work/parameters.md | 6 +++--- docs/web-app/strategies/manage-strat/parameters-tab.md | 2 +- docs/web-app/strategies/manage-strat/statuses-and-alerts.md | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/developers/strat-lib/guides/howToUnlockLiquidity.md b/docs/developers/strat-lib/guides/howToUnlockLiquidity.md index 2cee48f3..6230752c 100644 --- a/docs/developers/strat-lib/guides/howToUnlockLiquidity.md +++ b/docs/developers/strat-lib/guides/howToUnlockLiquidity.md @@ -9,7 +9,7 @@ sidebar_position: 1 In the previous [smart offer tutorial](../getting-started/smart-offer.md), the offer we posted had to receive a transfer liquidity for it to succeed when taken. Now, we want instead to post the offer without transferring tokens from the admin to Mangrove or the `OfferMakerTutorial` (unlocked or %%reactive liquidity|reactive-liquidity%%). This way, the tokens are pulled just-in-time when the offer is taken and can thus be made available for other purposes (ex: generating extra yield in another DeFi protocol). :::info Note -Since you are not committing your liquidity to your smart offer, you can post multiple offers with "unlocked liquidity". We call that [liquidity amplification](/docs/developers/terms/amplified-liquidity.md). +Since you are not committing your liquidity to your smart offer, you can post multiple offers with "unlocked liquidity". We call that [liquidity amplification](/developers/terms/amplified-liquidity.md). ::: For this to work, we use a so-called %%router|router%%: it is a contract that can be used to route tokens from the admin to the `OfferMakerTutorial` when the offer is taken.
diff --git a/docs/high-level/concepts/bounty.md b/docs/high-level/concepts/bounty.md index 2b7d2bd2..f2fa7afb 100644 --- a/docs/high-level/concepts/bounty.md +++ b/docs/high-level/concepts/bounty.md @@ -8,7 +8,7 @@ sidebar_position: 2 What if everyone makes empty promises, and the offers in the book are all meant to fail? -This is where Makers **must leave a native token provision ([the bounty](/docs/developers/terms/bounty.md))** in their offer. Nothing prevents them from posting offers that will always fail. So, to ensure that the offers displayed on the book are credible, it must be costly for Makers to post orders that are not meant to go through. And in that case scenario, the bounty is then given to the Taker as compensation. 💎 +This is where Makers **must leave a native token provision ([the bounty](/developers/terms/bounty.md))** in their offer. Nothing prevents them from posting offers that will always fail. So, to ensure that the offers displayed on the book are credible, it must be costly for Makers to post orders that are not meant to go through. And in that case scenario, the bounty is then given to the Taker as compensation. 💎 At first glance, this might seem one-sided in favor of Makers. However, with powerful market making features to accept or cancel offers, Makers reduce their risk and can offer better prices. In the end, both Makers and Takers win: the possibility of **offers failing is a necessity** for the power of smart offers. diff --git a/docs/high-level/concepts/makers-takers-keepers/takers.md b/docs/high-level/concepts/makers-takers-keepers/takers.md index 0c1ed7da..632154ee 100644 --- a/docs/high-level/concepts/makers-takers-keepers/takers.md +++ b/docs/high-level/concepts/makers-takers-keepers/takers.md @@ -14,7 +14,7 @@ When the Taker sends an order, Mangrove executes the offer logic (i.e. code) of * If the first order is successful and the liquidity promise is fulfilled, it is removed from the book. Mangrove moves on to the next offer until the entirety of the Taker's order is filled (whether it's a limit or market order). -* If during the execution, a Maker backs out on his offer (see previous [last look](../smart-offers.md)), and the liquidity is not matched, a penalty ([bounty](/docs/developers/terms/bounty.md)) is paid to the Taker and Mangrove executes the next offer logic from the orderbook, until the desired volume or limit price is hit. +* If during the execution, a Maker backs out on his offer (see previous [last look](../smart-offers.md)), and the liquidity is not matched, a penalty ([bounty](/developers/terms/bounty.md)) is paid to the Taker and Mangrove executes the next offer logic from the orderbook, until the desired volume or limit price is hit. import useBaseUrl from '@docusaurus/useBaseUrl'; diff --git a/docs/high-level/concepts/smart-offers.md b/docs/high-level/concepts/smart-offers.md index 8e1e0a6d..ad127c5c 100644 --- a/docs/high-level/concepts/smart-offers.md +++ b/docs/high-level/concepts/smart-offers.md @@ -6,7 +6,7 @@ sidebar_position: 1 # Smart offers -The main difference between Mangrove and other DEXs is the ability to attach code to offers (check out [Smart Offers](/docs/developers/terms/smart-offer.md) for more information). +The main difference between Mangrove and other DEXs is the ability to attach code to offers (check out [Smart Offers](/developers/terms/smart-offer.md) for more information). This translates into several disruptive mechanisms: * **Reactive liquidity**⚡
diff --git a/docs/kandel/how-does-kandel-work/more-on-failing-offers.md b/docs/kandel/how-does-kandel-work/more-on-failing-offers.md index 2241812e..60c8f860 100644 --- a/docs/kandel/how-does-kandel-work/more-on-failing-offers.md +++ b/docs/kandel/how-does-kandel-work/more-on-failing-offers.md @@ -15,7 +15,7 @@ This section explains the reasons why some offers might fail using Kandel. When we talk about an offer "failing", we mean that it could not execute. An offer can also fail to update itself. While we won't go into details in this part of the documentation, it is important to mention and differentiate those cases to further understand Kandel strategy's behavior. * [`makerExecute()`](../../developers/strat-lib/technical-references/code/strategies/MangroveOffer/#makerexecute): it is the callback function that is called when an offer is matched. Its role is to execute all offers that were posted on Mangrove by a given contract. - * A failure in `makerExecute()` means the trade is canceled, and the [bounty](/docs/developers/terms/bounty) is given to the Taker as a [compensation](../../developers/contracts/technical-references/taking-and-making-offers/taker-order/#bounties-for-taking-failing-offers). The offer is removed from the book. + * A failure in `makerExecute()` means the trade is canceled, and the [bounty](/developers/terms/bounty) is given to the Taker as a [compensation](../../developers/contracts/technical-references/taking-and-making-offers/taker-order/#bounties-for-taking-failing-offers). The offer is removed from the book. * [`makerPosthook()`](../../developers/strat-lib/technical-references/code/strategies/MangroveOffer/#makerposthook): it is the callback function that is called after the offer execution (i.e. after a successful execution of `makerExecute()`). @@ -46,7 +46,7 @@ Non-reposted liquidity will be placed into the [Unallocated liquidity](./strateg Reposting offers is handled with [`makerPosthook()`](../../developers/strat-lib/technical-references/code/strategies/MangroveOffer/#makerposthook), and failure could happen if: -* The residual of a partially taken offer is too small with regard to [density](/docs/developers/terms/density): +* The residual of a partially taken offer is too small with regard to [density](/developers/terms/density): * A partially taken offer is the result of a Taker either partially [sniping](../../developers/contracts/technical-references/taking-and-making-offers/taker-order/#offer-sniping) an offer, or placing a Market order * If an offer is almost entirely taken, the remainder (dust) could be too small to pass the density check, leading to a failure to repost itself diff --git a/docs/kandel/how-does-kandel-work/parameters.md b/docs/kandel/how-does-kandel-work/parameters.md index 34b27c78..59ccb88b 100644 --- a/docs/kandel/how-does-kandel-work/parameters.md +++ b/docs/kandel/how-does-kandel-work/parameters.md @@ -15,7 +15,7 @@ Price range | The price range is needed to run any market-making strategy. It co Current price | The current price of the base token that is used for constructing the price distribution.

*Example: the price of ETH is used for the ETH/USDC pair* Number of price points | The number of price points on which Kandel will deploy its liquidity (bids and asks). Ratio | The ratio of the progression used to calculate the price grid. It is directly linked to the number of price points. -Step size | It is the distance between an executed bid/ask and its [dual offer](/docs/developers/terms/dual-offer.md).

Whenever a Kandel ask is taken at a given price point, Kandel uses the amount of quote just received to place a bid at a lower price point. With a step size of 1, it will place the bid at the price point immediately below. With a step size of 2, Kandel will repost two price points below, etc. (Technical aside: if in attempting to repost say 3 steps below Kandel hits the boundaries of its range it will transport as far below as possible). The same applies symmetrically for bids.

Using a step size ≥ 2 allows one to publish a more continuous liquidity on the books, regularising the strat’s PnL, while at the same time keeping a reasonable spread between price points. Indeed, what matters to PnL is not the distance between price points, but how far money moves along the price grid each time an offer is taken. -Initial inventory | The initial inventory is the amount of base tokens and quote tokens that must be deposited into the strategy. The minimum to be deposited into the strategy depends on the selected price range and [density](/docs/developers/terms/density.md) of the selected market.

*Example on the ETH/USDC pair:
• Base token is ETH
• Quote token is USDC* -[Bounty](/docs/developers/terms/bounty.md) | It is the required amount of native tokens to be deposited into the strategy. A [provision](/docs/developers/terms/provision.md) is required to post an offer, in order to pay a potential [bounty](/docs/developers/terms/bounty.md). The bounty is only a subset, smaller in value than the provision.

The provision covers the whole price grid, hence:
• *Kandel provision = Provision per offer x Number of price points x 2*
• Note: we add a "x2" factor since each price point could be both an ask and a bid.

*Example: if the selected pair is on the Polygon network, the bounty would be an amount of MATIC tokens.* +Step size | It is the distance between an executed bid/ask and its [dual offer](/developers/terms/dual-offer.md).

Whenever a Kandel ask is taken at a given price point, Kandel uses the amount of quote just received to place a bid at a lower price point. With a step size of 1, it will place the bid at the price point immediately below. With a step size of 2, Kandel will repost two price points below, etc. (Technical aside: if in attempting to repost say 3 steps below Kandel hits the boundaries of its range it will transport as far below as possible). The same applies symmetrically for bids.

Using a step size ≥ 2 allows one to publish a more continuous liquidity on the books, regularising the strat’s PnL, while at the same time keeping a reasonable spread between price points. Indeed, what matters to PnL is not the distance between price points, but how far money moves along the price grid each time an offer is taken. +Initial inventory | The initial inventory is the amount of base tokens and quote tokens that must be deposited into the strategy. The minimum to be deposited into the strategy depends on the selected price range and [density](/developers/terms/density.md) of the selected market.

*Example on the ETH/USDC pair:
• Base token is ETH
• Quote token is USDC* +[Bounty](/developers/terms/bounty.md) | It is the required amount of native tokens to be deposited into the strategy. A [provision](/developers/terms/provision.md) is required to post an offer, in order to pay a potential [bounty](/developers/terms/bounty.md). The bounty is only a subset, smaller in value than the provision.

The provision covers the whole price grid, hence:
• *Kandel provision = Provision per offer x Number of price points x 2*
• Note: we add a "x2" factor since each price point could be both an ask and a bid.

*Example: if the selected pair is on the Polygon network, the bounty would be an amount of MATIC tokens.* Compounding rate | The compounding rate is the percentage of the spread to be reinvested into the strategy.
It can be set between 0% and 100% (SDK users only). \ No newline at end of file diff --git a/docs/web-app/strategies/manage-strat/parameters-tab.md b/docs/web-app/strategies/manage-strat/parameters-tab.md index 38a2b587..82f39d18 100644 --- a/docs/web-app/strategies/manage-strat/parameters-tab.md +++ b/docs/web-app/strategies/manage-strat/parameters-tab.md @@ -62,5 +62,5 @@ You can perform the following actions: ## Bounty -Use the "Add bounty" button to top up the amount of [bounty](/docs/developers/terms/bounty) you leave available to your Kandel strategy. +Use the "Add bounty" button to top up the amount of [bounty](/developers/terms/bounty) you leave available to your Kandel strategy. The bounty is a provision (in the network's native token) sent to the taker to compensate for a [failure to deliver](../../../kandel/how-does-kandel-work/more-on-failing-offers.md). It is a requirement for all offers published on Mangrove markets. \ No newline at end of file diff --git a/docs/web-app/strategies/manage-strat/statuses-and-alerts.md b/docs/web-app/strategies/manage-strat/statuses-and-alerts.md index cb9e0fd3..de4106fc 100644 --- a/docs/web-app/strategies/manage-strat/statuses-and-alerts.md +++ b/docs/web-app/strategies/manage-strat/statuses-and-alerts.md @@ -15,7 +15,7 @@ Your strategy can have one of three statuses: active, inactive, or closed. Depen It means that your strategy is running, profiting from the spread. You may see one of these alert messages while your strategy is active: * **"About to be out of bounty" button**
-Your trategy will soon run out of [bounty](/docs/developers/terms/bounty.md) to pay for the taker's compensation in case an [offer fails to execute](../../../kandel/how-does-kandel-work/more-on-failing-offers.md). +Your trategy will soon run out of [bounty](/developers/terms/bounty.md) to pay for the taker's compensation in case an [offer fails to execute](../../../kandel/how-does-kandel-work/more-on-failing-offers.md). * **"About to be out of price range" button**
Your strategy's price range is close to being out of range. From f5d1be91629db4749b5cabd60335b157433b508a Mon Sep 17 00:00:00 2001 From: Troels Damgaard Date: Fri, 13 Oct 2023 13:58:01 +0200 Subject: [PATCH 23/38] Glossary file moved --- docusaurus.config.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docusaurus.config.js b/docusaurus.config.js index 23e49f44..362bc3b0 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -38,7 +38,8 @@ const config = { ['@docusaurus-terminology/parser', { "termsUrl": "/developers/terms/", - "termsDir": "./docs/developers/terms/" + "termsDir": "./docs/developers/terms/", + glossaryFilepath: './docs/developers/glossary.md' } ], require.resolve('docusaurus-lunr-search'), From 4f432ee7aeae628498edc58bed78c58549592e91 Mon Sep 17 00:00:00 2001 From: Troels Damgaard Date: Fri, 13 Oct 2023 14:08:48 +0200 Subject: [PATCH 24/38] Developers links reintroduce developers link on General, and remove in Developers --- sidebars.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sidebars.js b/sidebars.js index a666ab20..cc2c523f 100644 --- a/sidebars.js +++ b/sidebars.js @@ -86,6 +86,11 @@ const sidebars = { href: '/developers/glossary', label: '🔤 Glossary', }, + { + type: 'link', + href: '/developers/', + label: '🏗️ Developers', + }, ], }, { @@ -193,11 +198,6 @@ const sidebars = { id: 'developers/glossary', label: '🔤 Glossary', }, - { - type: 'doc', - label: '🏗️ Developers', - id: 'developers/README', - }, ], }, ], From 56878532ce95f0473b36983c83d4e5fb3c4077cd Mon Sep 17 00:00:00 2001 From: Troels Damgaard Date: Fri, 13 Oct 2023 14:50:22 +0200 Subject: [PATCH 25/38] terms sidebar --- sidebars.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sidebars.js b/sidebars.js index cc2c523f..cea9acbf 100644 --- a/sidebars.js +++ b/sidebars.js @@ -200,7 +200,15 @@ const sidebars = { }, ], }, - ], + ], + + termSidebar: [ + 'glossary', + { + type: 'autogenerated', + dirName: 'developers/terms' + }, + ], }; module.exports = sidebars; From a11e7dd893bb2799412e50b7f966f20b12eaa102 Mon Sep 17 00:00:00 2001 From: Troels Damgaard Date: Fri, 13 Oct 2023 14:51:28 +0200 Subject: [PATCH 26/38] link fix --- sidebars.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sidebars.js b/sidebars.js index cea9acbf..74895e48 100644 --- a/sidebars.js +++ b/sidebars.js @@ -203,7 +203,7 @@ const sidebars = { ], termSidebar: [ - 'glossary', + 'developers/glossary.md', { type: 'autogenerated', dirName: 'developers/terms' From 6a3ca85a05925211d4d6f09391ee4758dd8fb29a Mon Sep 17 00:00:00 2001 From: Troels Damgaard Date: Fri, 13 Oct 2023 14:52:44 +0200 Subject: [PATCH 27/38] fix link --- sidebars.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sidebars.js b/sidebars.js index 74895e48..f43e831d 100644 --- a/sidebars.js +++ b/sidebars.js @@ -203,7 +203,7 @@ const sidebars = { ], termSidebar: [ - 'developers/glossary.md', + 'developers/glossary', { type: 'autogenerated', dirName: 'developers/terms' From 4a79d7b75d57e1c91e662ba59621a09beb85babe Mon Sep 17 00:00:00 2001 From: frkralj Date: Fri, 13 Oct 2023 15:30:34 +0200 Subject: [PATCH 28/38] Removing some Kandel file + adding color changes to info bubbles --- .../choosing-parameters.md | 29 ------------------- src/css/custom.css | 5 ++++ 2 files changed, 5 insertions(+), 29 deletions(-) delete mode 100644 docs/kandel/how-does-kandel-work/choosing-parameters.md diff --git a/docs/kandel/how-does-kandel-work/choosing-parameters.md b/docs/kandel/how-does-kandel-work/choosing-parameters.md deleted file mode 100644 index 109b5b87..00000000 --- a/docs/kandel/how-does-kandel-work/choosing-parameters.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -description: Choosing Kandel parameters -sidebar_position: 4 ---- - - -# Choosing Kandel parameters - - -This section goal is to help you develop an intuition to choose your Kandel parameters. It should be taken as an explanation on how the various parameters can impact your Kandel, and how the market conditions (ex: volatility) could be taken into account. It is **not** a trading advice. - -> 💡 -> As a reminder, Kandel is not intended as a "set and forget" strategy, and needs ongoing maintenance and checks. - -We will be going through standard steps you might want a take in order to check the market and deploy a new Kandel. - -## Check-in frequency - -First, it is good practice to know how often you aim to update your Kandel. Depending on the trading pair you chose, markets can behave very differently. - -Example: I will update my Kandel every 24h. - -## Set your price range - -Next, you should try to anticipate how much the market/price will vary during that period you just decided on. You are kind of betting on daily volatility. - -Example: I will look at the market volatility for the past 24h, and decide on the price range for my new Kandel. - -## Ratio: will depend on expected volatility \ No newline at end of file diff --git a/src/css/custom.css b/src/css/custom.css index fc9c6851..b7c9251d 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -30,6 +30,11 @@ --ifm-font-size-base: 15px; } +.alert--info{ + --ifm-alert-background-color: #03624C; + --ifm-alert-border-color: #DEDEDE; +} + .theme-doc-sidebar-menu { font-size: 14px; } From 2ed92fbfb2e1613cd1a62a0a0dda0e0e30c9f3ca Mon Sep 17 00:00:00 2001 From: frkralj Date: Mon, 16 Oct 2023 10:36:22 +0200 Subject: [PATCH 29/38] adding /general folder + other tweaks --- .../SDK/getting-started/deploy-kandel.md | 8 +++---- docs/developers/terms/dual-offer.md | 2 +- docs/{ => general}/FAQ/README.md | 10 ++++----- docs/{ => general}/README.md | 4 ++-- docs/general/high-level/audits.md | 22 +++++++++++++++++++ .../high-level/concepts/_category_.json | 0 .../high-level/concepts/bounty.md | 0 .../concepts/makers-takers-keepers/README.md | 0 .../makers-takers-keepers/_category_.json | 0 .../concepts/makers-takers-keepers/keepers.md | 11 ++++++++++ .../concepts/makers-takers-keepers/makers.md | 2 +- .../concepts/makers-takers-keepers/takers.md | 6 ++--- .../high-level/concepts/smart-offers.md | 0 docs/{ => general}/kandel/README.md | 0 .../kandel/details-on-strats/_category_.json | 0 .../details-on-strats/details-on-strats.md | 2 +- .../how-does-kandel-work/_category_.json | 0 .../how-does-kandel-work.md | 2 +- .../more-on-failing-offers.md | 16 +++++++------- .../kandel/how-does-kandel-work/parameters.md | 21 ++++++++++++++++++ .../step-by-step-visual-explanation.md | 0 .../how-does-kandel-work/strategy-reserve.md | 0 .../kandel/potential-risks/_category_.json | 0 .../kandel/potential-risks/potential-risks.md | 0 docs/{ => general}/web-app/README.md | 0 .../how-to-connect-wallet/_category_.json | 0 .../how-to-connect-wallet.md | 0 .../web-app/strategies/README.md | 0 .../web-app/strategies/_category_.json | 0 .../web-app/strategies/create-strat.md | 2 +- .../key-actions-questions/README.md | 0 .../key-actions-questions/_category_.json | 0 .../how-to-add-bounty.md | 0 .../how-to-close-strat.md | 0 .../how-to-deposit-inventory.md | 0 .../how-to-edit-price-range.md | 0 .../how-to-publish-inventory.md | 0 .../how-to-reopen-strat.md | 0 .../how-to-unpublish-inventory.md | 0 .../how-to-withdraw-inventory.md | 0 .../web-app/strategies/manage-strat/README.md | 0 .../strategies/manage-strat/_category_.json | 0 .../strategies/manage-strat/history-tab.md | 0 .../strategies/manage-strat/overview-tab.md | 0 .../strategies/manage-strat/parameters-tab.md | 0 .../manage-strat/statuses-and-alerts.md | 0 .../web-app/swap/_category_.json | 0 docs/{ => general}/web-app/swap/swap.md | 0 .../web-app/trade/_category_.json | 0 .../web-app/trade/approve-buy.md | 0 .../web-app/trade/common-issues-resolution.md | 0 .../web-app/trade/how-to-give-feedback.md | 2 +- .../web-app/trade/how-to-limit-order.md | 2 +- .../web-app/trade/how-to-market-order.md | 0 .../web-app/trade/how-to-track-open-orders.md | 0 .../web-app/trade/more-on-order-types.md | 0 docs/{ => general}/web-app/trade/revoke.md | 0 docs/{ => general}/web-app/trade/taker-fee.md | 0 docs/{ => general}/web-app/trade/trade.md | 0 docs/high-level/audits.md | 22 ------------------- .../concepts/makers-takers-keepers/keepers.md | 11 ---------- docs/high-level/ecosystem/README.md | 9 -------- docs/high-level/ecosystem/_category_.json | 5 ----- .../mangrove-rooted-in-innovation.md | 13 ----------- .../ecosystem/next-gen-order-book.md | 15 ------------- .../ecosystem/unconventional-team.md | 9 -------- .../kandel/how-does-kandel-work/parameters.md | 21 ------------------ docusaurus.config.js | 4 ++-- sidebars.js | 10 ++++----- 69 files changed, 90 insertions(+), 141 deletions(-) rename docs/{ => general}/FAQ/README.md (60%) rename docs/{ => general}/README.md (86%) create mode 100644 docs/general/high-level/audits.md rename docs/{ => general}/high-level/concepts/_category_.json (100%) rename docs/{ => general}/high-level/concepts/bounty.md (100%) rename docs/{ => general}/high-level/concepts/makers-takers-keepers/README.md (100%) rename docs/{ => general}/high-level/concepts/makers-takers-keepers/_category_.json (100%) create mode 100644 docs/general/high-level/concepts/makers-takers-keepers/keepers.md rename docs/{ => general}/high-level/concepts/makers-takers-keepers/makers.md (80%) rename docs/{ => general}/high-level/concepts/makers-takers-keepers/takers.md (69%) rename docs/{ => general}/high-level/concepts/smart-offers.md (100%) rename docs/{ => general}/kandel/README.md (100%) rename docs/{ => general}/kandel/details-on-strats/_category_.json (100%) rename docs/{ => general}/kandel/details-on-strats/details-on-strats.md (88%) rename docs/{ => general}/kandel/how-does-kandel-work/_category_.json (100%) rename docs/{ => general}/kandel/how-does-kandel-work/how-does-kandel-work.md (88%) rename docs/{ => general}/kandel/how-does-kandel-work/more-on-failing-offers.md (64%) create mode 100644 docs/general/kandel/how-does-kandel-work/parameters.md rename docs/{ => general}/kandel/how-does-kandel-work/step-by-step-visual-explanation.md (100%) rename docs/{ => general}/kandel/how-does-kandel-work/strategy-reserve.md (100%) rename docs/{ => general}/kandel/potential-risks/_category_.json (100%) rename docs/{ => general}/kandel/potential-risks/potential-risks.md (100%) rename docs/{ => general}/web-app/README.md (100%) rename docs/{ => general}/web-app/how-to-connect-wallet/_category_.json (100%) rename docs/{ => general}/web-app/how-to-connect-wallet/how-to-connect-wallet.md (100%) rename docs/{ => general}/web-app/strategies/README.md (100%) rename docs/{ => general}/web-app/strategies/_category_.json (100%) rename docs/{ => general}/web-app/strategies/create-strat.md (94%) rename docs/{ => general}/web-app/strategies/key-actions-questions/README.md (100%) rename docs/{ => general}/web-app/strategies/key-actions-questions/_category_.json (100%) rename docs/{ => general}/web-app/strategies/key-actions-questions/how-to-add-bounty.md (100%) rename docs/{ => general}/web-app/strategies/key-actions-questions/how-to-close-strat.md (100%) rename docs/{ => general}/web-app/strategies/key-actions-questions/how-to-deposit-inventory.md (100%) rename docs/{ => general}/web-app/strategies/key-actions-questions/how-to-edit-price-range.md (100%) rename docs/{ => general}/web-app/strategies/key-actions-questions/how-to-publish-inventory.md (100%) rename docs/{ => general}/web-app/strategies/key-actions-questions/how-to-reopen-strat.md (100%) rename docs/{ => general}/web-app/strategies/key-actions-questions/how-to-unpublish-inventory.md (100%) rename docs/{ => general}/web-app/strategies/key-actions-questions/how-to-withdraw-inventory.md (100%) rename docs/{ => general}/web-app/strategies/manage-strat/README.md (100%) rename docs/{ => general}/web-app/strategies/manage-strat/_category_.json (100%) rename docs/{ => general}/web-app/strategies/manage-strat/history-tab.md (100%) rename docs/{ => general}/web-app/strategies/manage-strat/overview-tab.md (100%) rename docs/{ => general}/web-app/strategies/manage-strat/parameters-tab.md (100%) rename docs/{ => general}/web-app/strategies/manage-strat/statuses-and-alerts.md (100%) rename docs/{ => general}/web-app/swap/_category_.json (100%) rename docs/{ => general}/web-app/swap/swap.md (100%) rename docs/{ => general}/web-app/trade/_category_.json (100%) rename docs/{ => general}/web-app/trade/approve-buy.md (100%) rename docs/{ => general}/web-app/trade/common-issues-resolution.md (100%) rename docs/{ => general}/web-app/trade/how-to-give-feedback.md (77%) rename docs/{ => general}/web-app/trade/how-to-limit-order.md (86%) rename docs/{ => general}/web-app/trade/how-to-market-order.md (100%) rename docs/{ => general}/web-app/trade/how-to-track-open-orders.md (100%) rename docs/{ => general}/web-app/trade/more-on-order-types.md (100%) rename docs/{ => general}/web-app/trade/revoke.md (100%) rename docs/{ => general}/web-app/trade/taker-fee.md (100%) rename docs/{ => general}/web-app/trade/trade.md (100%) delete mode 100644 docs/high-level/audits.md delete mode 100644 docs/high-level/concepts/makers-takers-keepers/keepers.md delete mode 100644 docs/high-level/ecosystem/README.md delete mode 100644 docs/high-level/ecosystem/_category_.json delete mode 100644 docs/high-level/ecosystem/mangrove-rooted-in-innovation.md delete mode 100644 docs/high-level/ecosystem/next-gen-order-book.md delete mode 100644 docs/high-level/ecosystem/unconventional-team.md delete mode 100644 docs/kandel/how-does-kandel-work/parameters.md diff --git a/docs/developers/SDK/getting-started/deploy-kandel.md b/docs/developers/SDK/getting-started/deploy-kandel.md index cfff25a4..a60f0872 100644 --- a/docs/developers/SDK/getting-started/deploy-kandel.md +++ b/docs/developers/SDK/getting-started/deploy-kandel.md @@ -5,7 +5,7 @@ sidebar_position: 2 # Deploy Kandel strategy -This tutorial covers how to deploy a Kandel strategy from a developer standpoint. For more information about Kandel, see the [Kandel documentation](../../../kandel/README.md). +This tutorial covers how to deploy a Kandel strategy from a developer standpoint. For more information about Kandel, see the [Kandel documentation](../../../general/kandel/README.md). ## Prerequisites @@ -44,12 +44,12 @@ Next, create an instance to manage Kandel strategies (`kandelStrategies`), and l https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/deploy-kandel.js#L21-L25 ``` -With this, you can generate a [distribution](../../../kandel/how-does-kandel-work/step-by-step-visual-explanation.md#price-distribution) with the minimum recommended amount of liquidity to avoid %%density|density%% issues by: +With this, you can generate a [distribution](../../../general/kandel/how-does-kandel-work/step-by-step-visual-explanation.md#price-distribution) with the minimum recommended amount of liquidity to avoid %%density|density%% issues by: * Creating a generator * Calculating minimums per offer * Calculating the distribution for the given price parameters of `minPrice: 900`, `maxPrice: 1100`, and default ratio -See the API documentation for [calculateMinimumDistribution](../technical-references/code/classes/KandelDistributionGenerator.md#calculateminimumdistribution) for more details on other `priceParams`. In our example here, `midPrice: 1100` is used to set the [current price](../../../kandel/how-does-kandel-work/parameters.md), and decide which offers become bids and which become asks. +See the API documentation for [calculateMinimumDistribution](../technical-references/code/classes/KandelDistributionGenerator.md#calculateminimumdistribution) for more details on other `priceParams`. In our example here, `midPrice: 1100` is used to set the [current price](../../../general/kandel/how-does-kandel-work/parameters.md), and decide which offers become bids and which become asks. ```javascript reference https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f1381dcd1/examples/tutorials/deploy-kandel.js#L27-L58 @@ -103,7 +103,7 @@ https://github.com/mangrovedao/mangrove.js/blob/2753b3148231a2541d0055a77a169f8f ### Populate offers for the distribution -Now that our Kandel instance is deployed, we can [populate the offers](../../../kandel/how-does-kandel-work/step-by-step-visual-explanation.md#populating-bids-and-asks) for the distribution. +Now that our Kandel instance is deployed, we can [populate the offers](../../../general/kandel/how-does-kandel-work/step-by-step-visual-explanation.md#populating-bids-and-asks) for the distribution. This will create offers for the base and quote tokens, and deposit the required amounts of tokens into the Kandel instance. The offers also need a %%provision|provision%%, hence here the default that we are using can be inspected. diff --git a/docs/developers/terms/dual-offer.md b/docs/developers/terms/dual-offer.md index c64eb4f1..c407b8b4 100644 --- a/docs/developers/terms/dual-offer.md +++ b/docs/developers/terms/dual-offer.md @@ -7,4 +7,4 @@ hoverText: An offer that is posted as a consequence of previous offer being take A _dual offer_ is posted by Kandel strategy's [posthook](../strat-lib/technical-references/code/strategies/MangroveOffer#makerposthook) logic. It's an offer that is posted as a consequence of previous offer being taken. ## References -* [Kandel: visual explanation](../../kandel/how-does-kandel-work/step-by-step-visual-explanation.md#reposting-liquidity-as-an-ask) \ No newline at end of file +* [Kandel: visual explanation](../../general/kandel/how-does-kandel-work/step-by-step-visual-explanation.md#reposting-liquidity-as-an-ask) \ No newline at end of file diff --git a/docs/FAQ/README.md b/docs/general/FAQ/README.md similarity index 60% rename from docs/FAQ/README.md rename to docs/general/FAQ/README.md index bc96fb5e..a40de31d 100644 --- a/docs/FAQ/README.md +++ b/docs/general/FAQ/README.md @@ -11,7 +11,7 @@ sidebar_position: 2 ## Where can I get Mangrove’s addresses? -The deployment addresses for the core contract for Mangrove, as well as the most important periphery contracts are available at [Contracts → Deployment Addresses](../developers/contracts/technical-references/contract-addresses.md). +The deployment addresses for the core contract for Mangrove, as well as the most important periphery contracts are available at [Contracts → Deployment Addresses](../../developers/contracts/technical-references/contract-addresses.md).
@@ -20,7 +20,7 @@ The deployment addresses for the core contract for Mangrove, as well as the most Fees on Mangrove are paid by the taker: The fee is taken from the tokens that the taker has bought. -Read more about fees here: [Taker fees](../developers/contracts/technical-references/governance-parameters/local-variables.md#taker-fees). +Read more about fees here: [Taker fees](../../developers/contracts/technical-references/governance-parameters/local-variables.md#taker-fees).
@@ -28,7 +28,7 @@ Read more about fees here: [Taker fees](../developers/contracts/technical-refere ## Who pays the gas on Mangrove? -If the offer succeeds, the gas costs for the [execution of the trade](../developers/contracts/technical-references/taking-and-making-offers/reactive-offer/executing-offers.md) are paid by the offer taker. If the offer fails the taker is compensated for these gas costs - see [What happens when an offer fails?](#what-happens-when-an-offer-fails) +If the offer succeeds, the gas costs for the [execution of the trade](../../developers/contracts/technical-references/taking-and-making-offers/reactive-offer/executing-offers.md) are paid by the offer taker. If the offer fails the taker is compensated for these gas costs - see [What happens when an offer fails?](#what-happens-when-an-offer-fails)
@@ -36,7 +36,7 @@ If the offer succeeds, the gas costs for the [execution of the trade](../develop ## What happens when an offer fails? -Offers in the order book may fail when taken, either because the maker consciously chose to [renege on the offer to trade](../developers/contracts/background/taker-compensation.md), or because the maker contract reverted for other reasons. In that case, the taker has wasted some gas and will be compensated using the [offer provision](../developers/contracts/technical-references/taking-and-making-offers/reactive-offer/offer-provision.md) (in native token) that the maker has deposited in Mangrove. +Offers in the order book may fail when taken, either because the maker consciously chose to [renege on the offer to trade](../../developers/contracts/background/taker-compensation.md), or because the maker contract reverted for other reasons. In that case, the taker has wasted some gas and will be compensated using the [offer provision](../../developers/contracts/technical-references/taking-and-making-offers/reactive-offer/offer-provision.md) (in native token) that the maker has deposited in Mangrove.
@@ -44,7 +44,7 @@ Offers in the order book may fail when taken, either because the maker conscious ## Are Mangrove market orders the same as traditional market orders? -Mangrove's [market orders](../developers/contracts/technical-references/taking-and-making-offers/taker-order/README.md) are DeFi market orders - which are different from market orders in TradFi: +Mangrove's [market orders](../../developers/contracts/technical-references/taking-and-making-offers/taker-order/README.md) are DeFi market orders - which are different from market orders in TradFi: In TradFi, a market order is an order to buy or sell immediately at the best available price. diff --git a/docs/README.md b/docs/general/README.md similarity index 86% rename from docs/README.md rename to docs/general/README.md index a0475d4f..8abc1927 100644 --- a/docs/README.md +++ b/docs/general/README.md @@ -13,12 +13,12 @@ It's a Decentralized Exchange (DEX)! On Mangrove, you can trade, swap tokens and ## The orderbook model -Mangrove is based on an "order book" model, which you may know from traditional finance exchanges. However, Mangrove is particular in that it allows liquidity providers to post arbitrary smart contracts as offers. What that means, is that the **listed offers can point to pieces of code**: we call them [Smart Offers](./developers/terms/smart-offer.md). 🤓 +Mangrove is based on an "order book" model, which you may know from traditional finance exchanges. However, Mangrove is particular in that it allows liquidity providers to post arbitrary smart contracts as offers. What that means, is that the **listed offers can point to pieces of code**: we call them [Smart Offers](../developers/terms/smart-offer.md). 🤓 As you can imagine, this new flexibility enables participants to post offers that are not fully provisioned. The Mangrove's order book **lists promises instead of locked commitments**. > 💡 -> There might be new words and concepts for you in here, and that's okay: we will provide you with either direct explanations or links and references. Feel free to check our [Glossary](./developers/glossary.md) and [FAQ](./FAQ/README.md) as well, it might help! +> There might be new words and concepts for you in here, and that's okay: we will provide you with either direct explanations or links and references. Feel free to check our [Glossary](../developers/glossary.md) and [FAQ](./FAQ/README.md) as well, it might help! ## Making promises diff --git a/docs/general/high-level/audits.md b/docs/general/high-level/audits.md new file mode 100644 index 00000000..0c706d78 --- /dev/null +++ b/docs/general/high-level/audits.md @@ -0,0 +1,22 @@ +--- +description: Audits +sidebar_position: 4 +--- + + +# Audits + +Mangrove has been thoroughly audited. You will find here official reports of the audits we passed: + +* Mangrove protocol audit + +* MangroveOrder audit + +* Kandel audit + +:::note +* [MangroveOrder](../../developers/strat-lib/technical-references/code/strategies/MangroveOrder.md) is a peripheral contract for the Mangrove core protocol which allows users to submit limit orders such as: + * [Good-til-cancelled](../web-app/trade/more-on-order-types.md#good-til-time-gtt) (GTC, or GTT) + * [Fill-or-kill](../web-app/trade/more-on-order-types.md#fill-or-kill-fok) (FOK) + +* [Kandel](../kandel/README.md) is "buy low, sell high" market making strategy that leverages Mangrove core protocol \ No newline at end of file diff --git a/docs/high-level/concepts/_category_.json b/docs/general/high-level/concepts/_category_.json similarity index 100% rename from docs/high-level/concepts/_category_.json rename to docs/general/high-level/concepts/_category_.json diff --git a/docs/high-level/concepts/bounty.md b/docs/general/high-level/concepts/bounty.md similarity index 100% rename from docs/high-level/concepts/bounty.md rename to docs/general/high-level/concepts/bounty.md diff --git a/docs/high-level/concepts/makers-takers-keepers/README.md b/docs/general/high-level/concepts/makers-takers-keepers/README.md similarity index 100% rename from docs/high-level/concepts/makers-takers-keepers/README.md rename to docs/general/high-level/concepts/makers-takers-keepers/README.md diff --git a/docs/high-level/concepts/makers-takers-keepers/_category_.json b/docs/general/high-level/concepts/makers-takers-keepers/_category_.json similarity index 100% rename from docs/high-level/concepts/makers-takers-keepers/_category_.json rename to docs/general/high-level/concepts/makers-takers-keepers/_category_.json diff --git a/docs/general/high-level/concepts/makers-takers-keepers/keepers.md b/docs/general/high-level/concepts/makers-takers-keepers/keepers.md new file mode 100644 index 00000000..c6d8c852 --- /dev/null +++ b/docs/general/high-level/concepts/makers-takers-keepers/keepers.md @@ -0,0 +1,11 @@ +--- +description: Keepers +sidebar_position: 3 +--- + + +# Keepers + +Mangrove's order book may be cluttered over time with irrelevant orders when the market conditions evolvent. Therefore, bots (or [Keepers](../../../../developers/keeper-bots/README.md)) are continuously scanning the book. They are responsible for detecting failing offers and making them fail on-chain by "[sniped](../../../developers/contracts/technical-references/taking-and-making-offers/taker-order/#offer-sniping)" them, with a gas price set such that the offer's bounty compensates for the spent gas. They act as [guardians](../../../../developers/keeper-bots/background/the-role-of-cleaning-bots-in-mangrove) of the Mangrove ecosystem. 🤖 + +Keepers are also in charge of [keeping the gas price updated](../../../../developers/keeper-bots/background/the-role-of-gas-price-updater-bots-in-mangrove) to determine the remuneration of takers for removing a failing offer from a list. \ No newline at end of file diff --git a/docs/high-level/concepts/makers-takers-keepers/makers.md b/docs/general/high-level/concepts/makers-takers-keepers/makers.md similarity index 80% rename from docs/high-level/concepts/makers-takers-keepers/makers.md rename to docs/general/high-level/concepts/makers-takers-keepers/makers.md index ab343f93..5a957492 100644 --- a/docs/high-level/concepts/makers-takers-keepers/makers.md +++ b/docs/general/high-level/concepts/makers-takers-keepers/makers.md @@ -8,7 +8,7 @@ sidebar_position: 1 They create and own the offers on Mangrove. For example, they promise to give a Taker some apples 🍎 if he gives them oranges 🍊 in return. That is why Mangrove is beautiful: Makers can plant their apples in their garden, or someone else's, until a Taker that wants some apples picks their offer. -We are explaining Makers in more detail in the [Developer section](../../../developers/contracts/technical-references/overview.md#makers) (relax, it's still very much understandable). +We are explaining Makers in more detail in the [Developer section](../../../../developers/contracts/technical-references/overview.md#makers) (relax, it's still very much understandable). import useBaseUrl from '@docusaurus/useBaseUrl'; diff --git a/docs/high-level/concepts/makers-takers-keepers/takers.md b/docs/general/high-level/concepts/makers-takers-keepers/takers.md similarity index 69% rename from docs/high-level/concepts/makers-takers-keepers/takers.md rename to docs/general/high-level/concepts/makers-takers-keepers/takers.md index 632154ee..1f8c1f4a 100644 --- a/docs/high-level/concepts/makers-takers-keepers/takers.md +++ b/docs/general/high-level/concepts/makers-takers-keepers/takers.md @@ -6,15 +6,15 @@ sidebar_position: 2 # Takers -Just like a classical orderbook, the Taker can buy or sell assets on Mangrove, with [market](../../../web-app/trade/how-to-market-order.md) or [limit orders](../../../web-app/trade/how-to-limit-order.md). Offers can be taken using general orders or "[sniped](../../../developers/contracts/technical-references/taking-and-making-offers/taker-order/#offer-sniping)" individually, as part of the strategies enabled by Mangrove's platform design. 🧿 +Just like a classical orderbook, the Taker can buy or sell assets on Mangrove, with [market](../../../web-app/trade/how-to-market-order.md) or [limit orders](../../../web-app/trade/how-to-limit-order.md). Offers can be taken using general orders or "[sniped](../../../../developers/contracts/technical-references/taking-and-making-offers/taker-order/#offer-sniping)" individually, as part of the strategies enabled by Mangrove's platform design. 🧿 -Takers may typically operate via a web front-end or with the help of our [SDK](../../../developers/SDK/README.md) to develop off-chain apps that interact with Mangrove ecosystem. +Takers may typically operate via a web front-end or with the help of our [SDK](../../../../developers/SDK/README.md) to develop off-chain apps that interact with Mangrove ecosystem. When the Taker sends an order, Mangrove executes the offer logic (i.e. code) of all the smart offers it triggers: * If the first order is successful and the liquidity promise is fulfilled, it is removed from the book. Mangrove moves on to the next offer until the entirety of the Taker's order is filled (whether it's a limit or market order). -* If during the execution, a Maker backs out on his offer (see previous [last look](../smart-offers.md)), and the liquidity is not matched, a penalty ([bounty](/developers/terms/bounty.md)) is paid to the Taker and Mangrove executes the next offer logic from the orderbook, until the desired volume or limit price is hit. +* If during the execution, a Maker backs out on his offer (see previous [last look](../smart-offers.md)), and the liquidity is not matched, a penalty ([bounty](../../../../developers/terms/bounty.md)) is paid to the Taker and Mangrove executes the next offer logic from the orderbook, until the desired volume or limit price is hit. import useBaseUrl from '@docusaurus/useBaseUrl'; diff --git a/docs/high-level/concepts/smart-offers.md b/docs/general/high-level/concepts/smart-offers.md similarity index 100% rename from docs/high-level/concepts/smart-offers.md rename to docs/general/high-level/concepts/smart-offers.md diff --git a/docs/kandel/README.md b/docs/general/kandel/README.md similarity index 100% rename from docs/kandel/README.md rename to docs/general/kandel/README.md diff --git a/docs/kandel/details-on-strats/_category_.json b/docs/general/kandel/details-on-strats/_category_.json similarity index 100% rename from docs/kandel/details-on-strats/_category_.json rename to docs/general/kandel/details-on-strats/_category_.json diff --git a/docs/kandel/details-on-strats/details-on-strats.md b/docs/general/kandel/details-on-strats/details-on-strats.md similarity index 88% rename from docs/kandel/details-on-strats/details-on-strats.md rename to docs/general/kandel/details-on-strats/details-on-strats.md index 7481a5c5..22dc7f3c 100644 --- a/docs/kandel/details-on-strats/details-on-strats.md +++ b/docs/general/kandel/details-on-strats/details-on-strats.md @@ -34,4 +34,4 @@ Here is more information on the inventory requirements:
## Build your own strategy -Our [Strategy Library](../../developers/strat-lib/README.md) contains a set of contracts and building blocks that can be used to implement custom market making strategies. \ No newline at end of file +Our [Strategy Library](../../../developers/strat-lib/README.md) contains a set of contracts and building blocks that can be used to implement custom market making strategies. \ No newline at end of file diff --git a/docs/kandel/how-does-kandel-work/_category_.json b/docs/general/kandel/how-does-kandel-work/_category_.json similarity index 100% rename from docs/kandel/how-does-kandel-work/_category_.json rename to docs/general/kandel/how-does-kandel-work/_category_.json diff --git a/docs/kandel/how-does-kandel-work/how-does-kandel-work.md b/docs/general/kandel/how-does-kandel-work/how-does-kandel-work.md similarity index 88% rename from docs/kandel/how-does-kandel-work/how-does-kandel-work.md rename to docs/general/kandel/how-does-kandel-work/how-does-kandel-work.md index a9ae4318..d4d5e19d 100644 --- a/docs/kandel/how-does-kandel-work/how-does-kandel-work.md +++ b/docs/general/kandel/how-does-kandel-work/how-does-kandel-work.md @@ -17,4 +17,4 @@ For a detailed explanation on how to create and manage a Kandel strategy on Mang ## Vocabulary -If some keywords and concepts are new to you, feel free to check our [Glossary](../../developers/glossary.md) and [FAQ](../../FAQ/README.md). \ No newline at end of file +If some keywords and concepts are new to you, feel free to check our [Glossary](../../../developers/glossary.md) and [FAQ](../../FAQ/README.md). \ No newline at end of file diff --git a/docs/kandel/how-does-kandel-work/more-on-failing-offers.md b/docs/general/kandel/how-does-kandel-work/more-on-failing-offers.md similarity index 64% rename from docs/kandel/how-does-kandel-work/more-on-failing-offers.md rename to docs/general/kandel/how-does-kandel-work/more-on-failing-offers.md index 60c8f860..246bed40 100644 --- a/docs/kandel/how-does-kandel-work/more-on-failing-offers.md +++ b/docs/general/kandel/how-does-kandel-work/more-on-failing-offers.md @@ -14,20 +14,20 @@ This section explains the reasons why some offers might fail using Kandel. When we talk about an offer "failing", we mean that it could not execute. An offer can also fail to update itself. While we won't go into details in this part of the documentation, it is important to mention and differentiate those cases to further understand Kandel strategy's behavior. -* [`makerExecute()`](../../developers/strat-lib/technical-references/code/strategies/MangroveOffer/#makerexecute): it is the callback function that is called when an offer is matched. Its role is to execute all offers that were posted on Mangrove by a given contract. - * A failure in `makerExecute()` means the trade is canceled, and the [bounty](/developers/terms/bounty) is given to the Taker as a [compensation](../../developers/contracts/technical-references/taking-and-making-offers/taker-order/#bounties-for-taking-failing-offers). The offer is removed from the book. +* [`makerExecute()`](../../../developers/strat-lib/technical-references/code/strategies/MangroveOffer/#makerexecute): it is the callback function that is called when an offer is matched. Its role is to execute all offers that were posted on Mangrove by a given contract. + * A failure in `makerExecute()` means the trade is canceled, and the [bounty](../../../developers/terms/bounty) is given to the Taker as a [compensation](../../../developers/contracts/technical-references/taking-and-making-offers/taker-order/#bounties-for-taking-failing-offers). The offer is removed from the book. -* [`makerPosthook()`](../../developers/strat-lib/technical-references/code/strategies/MangroveOffer/#makerposthook): it is the callback function that is called after the offer execution (i.e. after a successful execution of `makerExecute()`). +* [`makerPosthook()`](../../../developers/strat-lib/technical-references/code/strategies/MangroveOffer/#makerposthook): it is the callback function that is called after the offer execution (i.e. after a successful execution of `makerExecute()`). * A failure in `makerPosthook()` means the offer cannot update or repost itself after being taken. It does not cancel the trade, since it is called after `makerExecute()`. > 💡 -> For a more visual explanation, see the [call sequence overview](../../developers/contracts/technical-references/overview#call-sequence-overview) diagram. +> For a more visual explanation, see the [call sequence overview](../../../developers/contracts/technical-references/overview#call-sequence-overview) diagram. ## Kandel and `makerExecute()` failure After launching a Kandel strategy, Bids and Asks are populated with a [certain volume](./parameters.md). Kandel strategy's contract is handling all the posting for the user, using liquidity that has been previously deposited.
-Therefore, since the user is not in charge of writing and maintaining the smart contract, failures to execute [`makerExecute()`](../../developers/strat-lib/technical-references/code/strategies/MangroveOffer/#makerexecute) can be almost entirely ruled out, with the exception of some very specific scenarios such as: +Therefore, since the user is not in charge of writing and maintaining the smart contract, failures to execute [`makerExecute()`](../../../developers/strat-lib/technical-references/code/strategies/MangroveOffer/#makerexecute) can be almost entirely ruled out, with the exception of some very specific scenarios such as: * Someone severely modifies the volume distribution/sourcing methods, creating issues when a Kandel Bid/Ask is taken (via the SDK) @@ -44,10 +44,10 @@ Non-reposted liquidity will be placed into the [Unallocated liquidity](./strateg
-Reposting offers is handled with [`makerPosthook()`](../../developers/strat-lib/technical-references/code/strategies/MangroveOffer/#makerposthook), and failure could happen if: +Reposting offers is handled with [`makerPosthook()`](../../../developers/strat-lib/technical-references/code/strategies/MangroveOffer/#makerposthook), and failure could happen if: -* The residual of a partially taken offer is too small with regard to [density](/developers/terms/density): - * A partially taken offer is the result of a Taker either partially [sniping](../../developers/contracts/technical-references/taking-and-making-offers/taker-order/#offer-sniping) an offer, or placing a Market order +* The residual of a partially taken offer is too small with regard to [density](../../../developers/terms/density): + * A partially taken offer is the result of a Taker either partially [sniping](../../../developers/contracts/technical-references/taking-and-making-offers/taker-order/#offer-sniping) an offer, or placing a Market order * If an offer is almost entirely taken, the remainder (dust) could be too small to pass the density check, leading to a failure to repost itself diff --git a/docs/general/kandel/how-does-kandel-work/parameters.md b/docs/general/kandel/how-does-kandel-work/parameters.md new file mode 100644 index 00000000..d79ce69f --- /dev/null +++ b/docs/general/kandel/how-does-kandel-work/parameters.md @@ -0,0 +1,21 @@ +--- +description: Parameters +sidebar_position: 3 +--- + + +# Parameters + +This section describes Kandel's parameters. For more contextual information, head over to the [visual explanation](./step-by-step-visual-explanation.md). + +Parameters | Description +---|--- +Pair | The pair represents the chosen market on which a Kandel strategy is running.

*Example: ETH/USDC is a trading pair* +Price range | The price range is needed to run any market-making strategy. It consists of the lowest and highest prices in the price grid at which Kandel instance posts its bids and asks.

*Example of a price range:
• Lowest price = 1000 USDC per ETH
• Highest price = 1500 USDC per ETH* +Current price | The current price of the base token that is used for constructing the price distribution.

*Example: the price of ETH is used for the ETH/USDC pair* +Number of price points | The number of price points on which Kandel will deploy its liquidity (bids and asks). +Ratio | The ratio of the progression used to calculate the price grid. It is directly linked to the number of price points. +Step size | It is the distance between an executed bid/ask and its [dual offer](../../../developers/terms/dual-offer.md).

Whenever a Kandel ask is taken at a given price point, Kandel uses the amount of quote just received to place a bid at a lower price point. With a step size of 1, it will place the bid at the price point immediately below. With a step size of 2, Kandel will repost two price points below, etc. (Technical aside: if in attempting to repost say 3 steps below Kandel hits the boundaries of its range it will transport as far below as possible). The same applies symmetrically for bids.

Using a step size ≥ 2 allows one to publish a more continuous liquidity on the books, regularising the strat’s PnL, while at the same time keeping a reasonable spread between price points. Indeed, what matters to PnL is not the distance between price points, but how far money moves along the price grid each time an offer is taken. +Initial inventory | The initial inventory is the amount of base tokens and quote tokens that must be deposited into the strategy. The minimum to be deposited into the strategy depends on the selected price range and [density](../../../developers/terms/density.md) of the selected market.

*Example on the ETH/USDC pair:
• Base token is ETH
• Quote token is USDC* +[Bounty](../../../developers/terms/bounty.md) | It is the required amount of native tokens to be deposited into the strategy. A [provision](../../../developers/terms/provision.md) is required to post an offer, in order to pay a potential [bounty](../../../developers/terms/bounty.md). The bounty is only a subset, smaller in value than the provision.

The provision covers the whole price grid, hence:
• *Kandel provision = Provision per offer x Number of price points x 2*
• Note: we add a "x2" factor since each price point could be both an ask and a bid.

*Example: if the selected pair is on the Polygon network, the bounty would be an amount of MATIC tokens.* +Compounding rate | The compounding rate is the percentage of the spread to be reinvested into the strategy.
It can be set between 0% and 100% (SDK users only). \ No newline at end of file diff --git a/docs/kandel/how-does-kandel-work/step-by-step-visual-explanation.md b/docs/general/kandel/how-does-kandel-work/step-by-step-visual-explanation.md similarity index 100% rename from docs/kandel/how-does-kandel-work/step-by-step-visual-explanation.md rename to docs/general/kandel/how-does-kandel-work/step-by-step-visual-explanation.md diff --git a/docs/kandel/how-does-kandel-work/strategy-reserve.md b/docs/general/kandel/how-does-kandel-work/strategy-reserve.md similarity index 100% rename from docs/kandel/how-does-kandel-work/strategy-reserve.md rename to docs/general/kandel/how-does-kandel-work/strategy-reserve.md diff --git a/docs/kandel/potential-risks/_category_.json b/docs/general/kandel/potential-risks/_category_.json similarity index 100% rename from docs/kandel/potential-risks/_category_.json rename to docs/general/kandel/potential-risks/_category_.json diff --git a/docs/kandel/potential-risks/potential-risks.md b/docs/general/kandel/potential-risks/potential-risks.md similarity index 100% rename from docs/kandel/potential-risks/potential-risks.md rename to docs/general/kandel/potential-risks/potential-risks.md diff --git a/docs/web-app/README.md b/docs/general/web-app/README.md similarity index 100% rename from docs/web-app/README.md rename to docs/general/web-app/README.md diff --git a/docs/web-app/how-to-connect-wallet/_category_.json b/docs/general/web-app/how-to-connect-wallet/_category_.json similarity index 100% rename from docs/web-app/how-to-connect-wallet/_category_.json rename to docs/general/web-app/how-to-connect-wallet/_category_.json diff --git a/docs/web-app/how-to-connect-wallet/how-to-connect-wallet.md b/docs/general/web-app/how-to-connect-wallet/how-to-connect-wallet.md similarity index 100% rename from docs/web-app/how-to-connect-wallet/how-to-connect-wallet.md rename to docs/general/web-app/how-to-connect-wallet/how-to-connect-wallet.md diff --git a/docs/web-app/strategies/README.md b/docs/general/web-app/strategies/README.md similarity index 100% rename from docs/web-app/strategies/README.md rename to docs/general/web-app/strategies/README.md diff --git a/docs/web-app/strategies/_category_.json b/docs/general/web-app/strategies/_category_.json similarity index 100% rename from docs/web-app/strategies/_category_.json rename to docs/general/web-app/strategies/_category_.json diff --git a/docs/web-app/strategies/create-strat.md b/docs/general/web-app/strategies/create-strat.md similarity index 94% rename from docs/web-app/strategies/create-strat.md rename to docs/general/web-app/strategies/create-strat.md index 65825316..f3a4e860 100644 --- a/docs/web-app/strategies/create-strat.md +++ b/docs/general/web-app/strategies/create-strat.md @@ -73,7 +73,7 @@ Risk appetite:
-10. "Waiting for confirmation": you will be asked to sign 4 transactions in a row, including the deployment of your Kandel contract, the spending approvals of your pair's tokens, and the native token amount to be deposited for [bounty](../../developers/glossary.md#bounty). +10. "Waiting for confirmation": you will be asked to sign 4 transactions in a row, including the deployment of your Kandel contract, the spending approvals of your pair's tokens, and the native token amount to be deposited for [bounty](../../../developers/glossary.md#bounty). > 💡 > when signing on Metmamask, select "Use default" to set the appropriate amount of Approval. diff --git a/docs/web-app/strategies/key-actions-questions/README.md b/docs/general/web-app/strategies/key-actions-questions/README.md similarity index 100% rename from docs/web-app/strategies/key-actions-questions/README.md rename to docs/general/web-app/strategies/key-actions-questions/README.md diff --git a/docs/web-app/strategies/key-actions-questions/_category_.json b/docs/general/web-app/strategies/key-actions-questions/_category_.json similarity index 100% rename from docs/web-app/strategies/key-actions-questions/_category_.json rename to docs/general/web-app/strategies/key-actions-questions/_category_.json diff --git a/docs/web-app/strategies/key-actions-questions/how-to-add-bounty.md b/docs/general/web-app/strategies/key-actions-questions/how-to-add-bounty.md similarity index 100% rename from docs/web-app/strategies/key-actions-questions/how-to-add-bounty.md rename to docs/general/web-app/strategies/key-actions-questions/how-to-add-bounty.md diff --git a/docs/web-app/strategies/key-actions-questions/how-to-close-strat.md b/docs/general/web-app/strategies/key-actions-questions/how-to-close-strat.md similarity index 100% rename from docs/web-app/strategies/key-actions-questions/how-to-close-strat.md rename to docs/general/web-app/strategies/key-actions-questions/how-to-close-strat.md diff --git a/docs/web-app/strategies/key-actions-questions/how-to-deposit-inventory.md b/docs/general/web-app/strategies/key-actions-questions/how-to-deposit-inventory.md similarity index 100% rename from docs/web-app/strategies/key-actions-questions/how-to-deposit-inventory.md rename to docs/general/web-app/strategies/key-actions-questions/how-to-deposit-inventory.md diff --git a/docs/web-app/strategies/key-actions-questions/how-to-edit-price-range.md b/docs/general/web-app/strategies/key-actions-questions/how-to-edit-price-range.md similarity index 100% rename from docs/web-app/strategies/key-actions-questions/how-to-edit-price-range.md rename to docs/general/web-app/strategies/key-actions-questions/how-to-edit-price-range.md diff --git a/docs/web-app/strategies/key-actions-questions/how-to-publish-inventory.md b/docs/general/web-app/strategies/key-actions-questions/how-to-publish-inventory.md similarity index 100% rename from docs/web-app/strategies/key-actions-questions/how-to-publish-inventory.md rename to docs/general/web-app/strategies/key-actions-questions/how-to-publish-inventory.md diff --git a/docs/web-app/strategies/key-actions-questions/how-to-reopen-strat.md b/docs/general/web-app/strategies/key-actions-questions/how-to-reopen-strat.md similarity index 100% rename from docs/web-app/strategies/key-actions-questions/how-to-reopen-strat.md rename to docs/general/web-app/strategies/key-actions-questions/how-to-reopen-strat.md diff --git a/docs/web-app/strategies/key-actions-questions/how-to-unpublish-inventory.md b/docs/general/web-app/strategies/key-actions-questions/how-to-unpublish-inventory.md similarity index 100% rename from docs/web-app/strategies/key-actions-questions/how-to-unpublish-inventory.md rename to docs/general/web-app/strategies/key-actions-questions/how-to-unpublish-inventory.md diff --git a/docs/web-app/strategies/key-actions-questions/how-to-withdraw-inventory.md b/docs/general/web-app/strategies/key-actions-questions/how-to-withdraw-inventory.md similarity index 100% rename from docs/web-app/strategies/key-actions-questions/how-to-withdraw-inventory.md rename to docs/general/web-app/strategies/key-actions-questions/how-to-withdraw-inventory.md diff --git a/docs/web-app/strategies/manage-strat/README.md b/docs/general/web-app/strategies/manage-strat/README.md similarity index 100% rename from docs/web-app/strategies/manage-strat/README.md rename to docs/general/web-app/strategies/manage-strat/README.md diff --git a/docs/web-app/strategies/manage-strat/_category_.json b/docs/general/web-app/strategies/manage-strat/_category_.json similarity index 100% rename from docs/web-app/strategies/manage-strat/_category_.json rename to docs/general/web-app/strategies/manage-strat/_category_.json diff --git a/docs/web-app/strategies/manage-strat/history-tab.md b/docs/general/web-app/strategies/manage-strat/history-tab.md similarity index 100% rename from docs/web-app/strategies/manage-strat/history-tab.md rename to docs/general/web-app/strategies/manage-strat/history-tab.md diff --git a/docs/web-app/strategies/manage-strat/overview-tab.md b/docs/general/web-app/strategies/manage-strat/overview-tab.md similarity index 100% rename from docs/web-app/strategies/manage-strat/overview-tab.md rename to docs/general/web-app/strategies/manage-strat/overview-tab.md diff --git a/docs/web-app/strategies/manage-strat/parameters-tab.md b/docs/general/web-app/strategies/manage-strat/parameters-tab.md similarity index 100% rename from docs/web-app/strategies/manage-strat/parameters-tab.md rename to docs/general/web-app/strategies/manage-strat/parameters-tab.md diff --git a/docs/web-app/strategies/manage-strat/statuses-and-alerts.md b/docs/general/web-app/strategies/manage-strat/statuses-and-alerts.md similarity index 100% rename from docs/web-app/strategies/manage-strat/statuses-and-alerts.md rename to docs/general/web-app/strategies/manage-strat/statuses-and-alerts.md diff --git a/docs/web-app/swap/_category_.json b/docs/general/web-app/swap/_category_.json similarity index 100% rename from docs/web-app/swap/_category_.json rename to docs/general/web-app/swap/_category_.json diff --git a/docs/web-app/swap/swap.md b/docs/general/web-app/swap/swap.md similarity index 100% rename from docs/web-app/swap/swap.md rename to docs/general/web-app/swap/swap.md diff --git a/docs/web-app/trade/_category_.json b/docs/general/web-app/trade/_category_.json similarity index 100% rename from docs/web-app/trade/_category_.json rename to docs/general/web-app/trade/_category_.json diff --git a/docs/web-app/trade/approve-buy.md b/docs/general/web-app/trade/approve-buy.md similarity index 100% rename from docs/web-app/trade/approve-buy.md rename to docs/general/web-app/trade/approve-buy.md diff --git a/docs/web-app/trade/common-issues-resolution.md b/docs/general/web-app/trade/common-issues-resolution.md similarity index 100% rename from docs/web-app/trade/common-issues-resolution.md rename to docs/general/web-app/trade/common-issues-resolution.md diff --git a/docs/web-app/trade/how-to-give-feedback.md b/docs/general/web-app/trade/how-to-give-feedback.md similarity index 77% rename from docs/web-app/trade/how-to-give-feedback.md rename to docs/general/web-app/trade/how-to-give-feedback.md index ae284c30..f6c9c0ac 100644 --- a/docs/web-app/trade/how-to-give-feedback.md +++ b/docs/general/web-app/trade/how-to-give-feedback.md @@ -6,7 +6,7 @@ sidebar_position: 10 # How to give your feedback -The best way to share your feedback is via our Support chat on our [dApp](https://app.mangrove.exchange/) +The best way to share your feedback is via our Support chat on our [dApp](https://app.mangrove.exchange/), or using [this form](https://tally.so/r/w54D5Q). You can also message us via the dedicated [Discord channel](https://discord.gg/rk9Qthz5YE). If you can, please, make sure to share your tx and details of the issue you are encountering. diff --git a/docs/web-app/trade/how-to-limit-order.md b/docs/general/web-app/trade/how-to-limit-order.md similarity index 86% rename from docs/web-app/trade/how-to-limit-order.md rename to docs/general/web-app/trade/how-to-limit-order.md index ff523d38..32f223bc 100644 --- a/docs/web-app/trade/how-to-limit-order.md +++ b/docs/general/web-app/trade/how-to-limit-order.md @@ -25,7 +25,7 @@ import useBaseUrl from '@docusaurus/useBaseUrl'; 5. Choose from 3 types of limit orders: * **Immediate or Cancel (IOC)**: Your order attempts to execute immediately at the desired price. If successful, it's executed; if not, it's canceled. * **Good 'til time (GTT)**: Set an expiration date for your order (ex: active for 3 days, then canceled). - * [**Fill or Kill (FOK)**](../../developers/SDK/guides/fill-or-kill.md): Your order is either executed fully or not executed at all (ex: you place an order for 1 ETH at $9,500; if only 0.8 ETH can be filled, it's canceled; if fully filled, it's executed). + * [**Fill or Kill (FOK)**](../../../developers/SDK/guides/fill-or-kill.md): Your order is either executed fully or not executed at all (ex: you place an order for 1 ETH at $9,500; if only 0.8 ETH can be filled, it's canceled; if fully filled, it's executed). > 💡 > If a "Good 'til time" limit order is [partially filled](./how-to-track-open-orders.md#order-is-partially-filled), a green message will display the transaction details, and the remainder will be reposted automatically. diff --git a/docs/web-app/trade/how-to-market-order.md b/docs/general/web-app/trade/how-to-market-order.md similarity index 100% rename from docs/web-app/trade/how-to-market-order.md rename to docs/general/web-app/trade/how-to-market-order.md diff --git a/docs/web-app/trade/how-to-track-open-orders.md b/docs/general/web-app/trade/how-to-track-open-orders.md similarity index 100% rename from docs/web-app/trade/how-to-track-open-orders.md rename to docs/general/web-app/trade/how-to-track-open-orders.md diff --git a/docs/web-app/trade/more-on-order-types.md b/docs/general/web-app/trade/more-on-order-types.md similarity index 100% rename from docs/web-app/trade/more-on-order-types.md rename to docs/general/web-app/trade/more-on-order-types.md diff --git a/docs/web-app/trade/revoke.md b/docs/general/web-app/trade/revoke.md similarity index 100% rename from docs/web-app/trade/revoke.md rename to docs/general/web-app/trade/revoke.md diff --git a/docs/web-app/trade/taker-fee.md b/docs/general/web-app/trade/taker-fee.md similarity index 100% rename from docs/web-app/trade/taker-fee.md rename to docs/general/web-app/trade/taker-fee.md diff --git a/docs/web-app/trade/trade.md b/docs/general/web-app/trade/trade.md similarity index 100% rename from docs/web-app/trade/trade.md rename to docs/general/web-app/trade/trade.md diff --git a/docs/high-level/audits.md b/docs/high-level/audits.md deleted file mode 100644 index f9aa0638..00000000 --- a/docs/high-level/audits.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -description: Audits -sidebar_position: 4 ---- - - -# Audits - -Mangrove has been thoroughly audited. You will find here official reports of the audits we passed: - -* Mangrove protocol audit - -* MangroveOrder audit - -* Kandel audit - -:::note -* [MangroveOrder](../developers/strat-lib/technical-references/code/strategies/MangroveOrder.md) is a peripheral contract for the Mangrove core protocol which allows users to submit limit orders such as: - * [Good-til-cancelled](../web-app/trade/more-on-order-types.md#good-til-time-gtt) (GTC, or GTT) - * [Fill-or-kill](../web-app/trade/more-on-order-types.md#fill-or-kill-fok) (FOK) - -* [Kandel](../kandel/README.md) is "buy low, sell high" market making strategy that leverages Mangrove core protocol \ No newline at end of file diff --git a/docs/high-level/concepts/makers-takers-keepers/keepers.md b/docs/high-level/concepts/makers-takers-keepers/keepers.md deleted file mode 100644 index d5957a90..00000000 --- a/docs/high-level/concepts/makers-takers-keepers/keepers.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -description: Keepers -sidebar_position: 3 ---- - - -# Keepers - -Mangrove's order book may be cluttered over time with irrelevant orders when the market conditions evolvent. Therefore, bots (or [Keepers](../../../developers/keeper-bots/README.md)) are continuously scanning the book. They are responsible for detecting failing offers and making them fail on-chain by "[sniped](../../../developers/contracts/technical-references/taking-and-making-offers/taker-order/#offer-sniping)" them, with a gas price set such that the offer's bounty compensates for the spent gas. They act as [guardians](../../../developers/keeper-bots/background/the-role-of-cleaning-bots-in-mangrove) of the Mangrove ecosystem. 🤖 - -Keepers are also in charge of [keeping the gas price updated](../../../developers/keeper-bots/background/the-role-of-gas-price-updater-bots-in-mangrove) to determine the remuneration of takers for removing a failing offer from a list. \ No newline at end of file diff --git a/docs/high-level/ecosystem/README.md b/docs/high-level/ecosystem/README.md deleted file mode 100644 index d3e9a14d..00000000 --- a/docs/high-level/ecosystem/README.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -description: Ecosystem -sidebar_position: 1 ---- - - -# Ecosystem - -Mangrove is built with the goal to be a new design space for strategists, traders, market makers and other market participants such as DeFi builders, to come up with innovative strategies leveraging the principle of reactive liquidity. 🌱 \ No newline at end of file diff --git a/docs/high-level/ecosystem/_category_.json b/docs/high-level/ecosystem/_category_.json deleted file mode 100644 index b476755c..00000000 --- a/docs/high-level/ecosystem/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "label": "Ecosystem", - "position": 2, - "collapsed": true -} \ No newline at end of file diff --git a/docs/high-level/ecosystem/mangrove-rooted-in-innovation.md b/docs/high-level/ecosystem/mangrove-rooted-in-innovation.md deleted file mode 100644 index 85be5363..00000000 --- a/docs/high-level/ecosystem/mangrove-rooted-in-innovation.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -description: Mangrove is rooted in innovation -sidebar_position: 3 ---- - - -# Mangrove is rooted in innovation - -An example of what Mangrove could enable is **partial liquidation**, where someone with a credit line wants protection/reevaluation before his position gets fully liquidated. This would lead to fewer liquidations on borrow/lend protocols. - -Another idea is **carbon tokens trading** (i.e. tokens issued from Carbon Credits). Following its principles, Mangrove could allow Carbon markets to **amplify their liquidity** by listing tokens in several pools, and provisioning them only when offers are taken. - -Of course, there are many paths to explore. We want to lead with examples, to inspire other ideas. For us, Mangrove is not the end of the line - it is the beginning. 🌅 diff --git a/docs/high-level/ecosystem/next-gen-order-book.md b/docs/high-level/ecosystem/next-gen-order-book.md deleted file mode 100644 index 93b8915b..00000000 --- a/docs/high-level/ecosystem/next-gen-order-book.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -description: Next gen order book -sidebar_position: 1 ---- - - -# Next gen order book - -Mangrove is what you could call a **"next generation" order book**. 🆕
- -If you are selling apples 🍎 for oranges 🍊, you don't need to provide the apples upfront and have them sitting idle in a vault, under-utilized and slowly rotting away. -Any person, trader or entity can run their own **personal, custom-made AMM strategies** by listing offers containing code. - -Anyone can write strategies, develop an app, integrate their project, taking advantage of the previously mentioned principles. Mangrove effectively becomes **the cradle of crypto trading innovations**. -That is how we want to measure success: we aim to create **a growing, organic ecosystem** that comes up with disruptive new ideas on its own, all enabled by Mangrove as a platform. \ No newline at end of file diff --git a/docs/high-level/ecosystem/unconventional-team.md b/docs/high-level/ecosystem/unconventional-team.md deleted file mode 100644 index 7691ad63..00000000 --- a/docs/high-level/ecosystem/unconventional-team.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -description: Unconventional team structure -sidebar_position: 2 ---- - - -# Unconventional team structure - -It is worth noting that our team is composed of both engineers and researchers, which is not common in our space. We are proud to work with top-class PhDs and academics, who create innovative strategies and solutions for DeFi. They are always on the lookout for new inventions. 🔍 \ No newline at end of file diff --git a/docs/kandel/how-does-kandel-work/parameters.md b/docs/kandel/how-does-kandel-work/parameters.md deleted file mode 100644 index 59ccb88b..00000000 --- a/docs/kandel/how-does-kandel-work/parameters.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -description: Parameters -sidebar_position: 3 ---- - - -# Parameters - -This section describes Kandel's parameters. For more contextual information, head over to the [visual explanation](./step-by-step-visual-explanation.md). - -Parameters | Description ----|--- -Pair | The pair represents the chosen market on which a Kandel strategy is running.

*Example: ETH/USDC is a trading pair* -Price range | The price range is needed to run any market-making strategy. It consists of the lowest and highest prices in the price grid at which Kandel instance posts its bids and asks.

*Example of a price range:
• Lowest price = 1000 USDC per ETH
• Highest price = 1500 USDC per ETH* -Current price | The current price of the base token that is used for constructing the price distribution.

*Example: the price of ETH is used for the ETH/USDC pair* -Number of price points | The number of price points on which Kandel will deploy its liquidity (bids and asks). -Ratio | The ratio of the progression used to calculate the price grid. It is directly linked to the number of price points. -Step size | It is the distance between an executed bid/ask and its [dual offer](/developers/terms/dual-offer.md).

Whenever a Kandel ask is taken at a given price point, Kandel uses the amount of quote just received to place a bid at a lower price point. With a step size of 1, it will place the bid at the price point immediately below. With a step size of 2, Kandel will repost two price points below, etc. (Technical aside: if in attempting to repost say 3 steps below Kandel hits the boundaries of its range it will transport as far below as possible). The same applies symmetrically for bids.

Using a step size ≥ 2 allows one to publish a more continuous liquidity on the books, regularising the strat’s PnL, while at the same time keeping a reasonable spread between price points. Indeed, what matters to PnL is not the distance between price points, but how far money moves along the price grid each time an offer is taken. -Initial inventory | The initial inventory is the amount of base tokens and quote tokens that must be deposited into the strategy. The minimum to be deposited into the strategy depends on the selected price range and [density](/developers/terms/density.md) of the selected market.

*Example on the ETH/USDC pair:
• Base token is ETH
• Quote token is USDC* -[Bounty](/developers/terms/bounty.md) | It is the required amount of native tokens to be deposited into the strategy. A [provision](/developers/terms/provision.md) is required to post an offer, in order to pay a potential [bounty](/developers/terms/bounty.md). The bounty is only a subset, smaller in value than the provision.

The provision covers the whole price grid, hence:
• *Kandel provision = Provision per offer x Number of price points x 2*
• Note: we add a "x2" factor since each price point could be both an ask and a bid.

*Example: if the selected pair is on the Polygon network, the bounty would be an amount of MATIC tokens.* -Compounding rate | The compounding rate is the percentage of the spread to be reinvested into the strategy.
It can be set between 0% and 100% (SDK users only). \ No newline at end of file diff --git a/docusaurus.config.js b/docusaurus.config.js index 362bc3b0..42624eb9 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -127,12 +127,12 @@ const config = { alt: 'Mangrove logo', src: 'img/assets/mangrove_only_logo_dark.png', srcDark: 'img/assets/mangrove_only_logo_white.png', - href: '/', + href: '/general', target: '_self', }, items: [ { - to: '/', + to: '/general', position: 'right', label: 'General', }, diff --git a/sidebars.js b/sidebars.js index f43e831d..af387abc 100644 --- a/sidebars.js +++ b/sidebars.js @@ -19,7 +19,7 @@ const sidebars = { { type: 'category', label: 'Getting started', - link: {type: 'doc', id: 'README'}, + link: {type: 'doc', id: 'general/README'}, items: [ { type: 'category', @@ -27,13 +27,13 @@ const sidebars = { items: [ { type: 'autogenerated', - dirName: 'high-level', // Generate sidebar slice from docs/high-level + dirName: 'general/high-level', // Generate sidebar slice from docs/high-level }, ] }, { type: 'doc', - id: 'FAQ/README', + id: 'general/FAQ/README', label: '❓ FAQ', }, { @@ -42,7 +42,7 @@ const sidebars = { items: [ { type: 'autogenerated', - dirName: 'web-app', + dirName: 'general/web-app', }, ] }, @@ -60,7 +60,7 @@ const sidebars = { items: [ { type: 'autogenerated', - dirName: 'kandel', // Generate sidebar slice from docs/high-level + dirName: 'general/kandel', // Generate sidebar slice from docs/high-level }, ] }, From 9ce4b098fd6a9336ba26b449007e8b23b8d1460b Mon Sep 17 00:00:00 2001 From: frkralj Date: Mon, 16 Oct 2023 13:32:44 +0200 Subject: [PATCH 30/38] adding new home page + table of content --- docs/README.md | 68 ++++++++++++++++ docs/general/README.md | 29 ------- docs/general/table-content.md | 77 ++++++++++++++++++ .../web-app/trade/common-issues-resolution.md | 1 - .../web-app/trade/how-to-give-feedback.md | 14 ---- docusaurus.config.js | 4 +- sidebars.js | 27 ++++-- static/img/assets/home_page.png | Bin 0 -> 90734 bytes 8 files changed, 168 insertions(+), 52 deletions(-) create mode 100644 docs/README.md delete mode 100644 docs/general/README.md create mode 100644 docs/general/table-content.md delete mode 100644 docs/general/web-app/trade/how-to-give-feedback.md create mode 100644 static/img/assets/home_page.png diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..d453e360 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,68 @@ +--- +title: General +sidebar_position: 0 +--- + +# Overview + +Mangrove is an on-chain order book DEX that allows liquidity providers to post arbitrary smart contracts as offers. + +import useBaseUrl from '@docusaurus/useBaseUrl'; + + + +## Total control over your offers + +Mangrove's order book-based DEX [lists promises instead of locked commitments](./general/high-level/concepts/makers-takers-keepers/README.md). Liquidity can be shared, borrowed, lent somewhere and at the same time displayed on Mangrove, ready to be sourced when (and only when) an offer is taken. + + +## Smart offers + +Smart contracts [can be attached to offers](./general/high-level/concepts/smart-offers.md), which gives the Maker total freedom in setting his sourcing trade parameters. + +#### Powerful applications of smart offers + +* [**Reactive liquidity:**](./developers/terms/reactive-liquidity.md) liquidity on offer is not locked on the Mangrove order book. As long as an offer posted on Mangrove is not taken, it can generate yield elsewhere on the chain. + +* [**Last look:**](./developers/terms/last-look.md) smart offers allow you to code defensive mechanisms that adjust for market condition changes between offer posting and execution. + +* [**Bounty:**](./general/high-level/concepts/bounty.md) every single failed offer is compensated with a bounty,; Keeper bots can make money, and Takers don't lose any. + +* **Permissionless:** everyone can interact with the core protocol without having to ask permission nor risking to be censored. + +* **Non-custodial:** Mangrove users retain full control over their funds - the exchange does not hold custody of their assets. + + +## Deploy your own composable strategy + +Mangrove enables liquidity providers to incorporate defensive code, post unprovisioned offers, and redisplay liquidity after their offers are taken. + +#### Full control over your strategy parameters + +* [**Amplified liquidity:**](./developers/terms/amplified-liquidity.md) optimize your trading potential by leveraging your liquidity across multiple pairs. For instance, you can create offers on WETH/USDC, WMATIC/USDC and WBTC/USDC pairs with an equal amount of USDC liquidity. + +* [**Multi-liquidity sourcing:**](./developers/terms/reactive-liquidity.md) your smart offer on Mangrove can take advantage of liquidity sourcing from other sources and offering it to the taker, allowing for profitable arbitrage opportunities. + +* **Price sensors:** in your smart offer, you can dynamically trigger actions based on Mangrove DEX’s asset prices. It enables instantaneous stop loss and ensures that your offer remains attractive to potential takers in changing market conditions. + +* [**Run AMMs strategies:**](./developers/strat-lib/README.md) provide liquidity on Mangrove’s order book in order to maximize your liquidity potential. + +## Kandel strategy + +[Kandel](./general/kandel/README.md) is an on-chain Automated Market Making strategy that focuses on order flow rather than price. It automatically posts Bids and Asks within your chosen market and price range to buy low and sell high, making a profit through the spread. + +#### Features + +* **On-chain market making bot** Kandel is a market-making bot equivalent that operates solely on the blockchain. Unlike off-chain market making bots that experience delays, Kandel uses on-chain order flow to repost offers instantly, without any latency. + +* **Profit from the spread:** Kandel follows your configuration parameters to populate Bids and Asks offers. When those are taken, the profits are generated from the difference between the two, known as the spread.” + +* **Compounding:** you have the opportunity to accumulate profits generated from spreads and reinvest them back into your offers, a process commonly known as compounding. On Kandel strategy, you can set the compounding rate. + +* **Price range:** since Kandel is an automated market-making strategy, the price range needs to be set. It consists of the lowest and highest prices in the price grid at which the market maker is willing to post its bids and asks on Mangrove DEX. + +* **Earn extra yield on AAVE:** since the liquidity on offer is not locked on the Mangrove order book, it can generate yield elsewhere on the chain. With Kandel, when an offer is taken, your liquidity can be sourced and redeposited on AAVE. + +## Mangrove is a secure protocol + +Mangrove is an open-source protocol that has been rigorously [audited](./general/high-level/audits.md) by the highly reputable and expert firm, ChainSec, ensuring the utmost security and reliability. diff --git a/docs/general/README.md b/docs/general/README.md deleted file mode 100644 index 8abc1927..00000000 --- a/docs/general/README.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: General -sidebar_position: 0 ---- - -# What is Mangrove? - -It's a Decentralized Exchange (DEX)! On Mangrove, you can trade, swap tokens and create blueprint trading strategies or brand new ones. On Mangrove, we refer to strategies as programs which will run certain trading behavior, whose goal is to make profits (ex: buy low, sell high). - -> 💡 -> For a concrete example of strategies on Mangrove, check out the [Kandel strategy](./kandel/README.md) documentation. - - -## The orderbook model - -Mangrove is based on an "order book" model, which you may know from traditional finance exchanges. However, Mangrove is particular in that it allows liquidity providers to post arbitrary smart contracts as offers. What that means, is that the **listed offers can point to pieces of code**: we call them [Smart Offers](../developers/terms/smart-offer.md). 🤓 - -As you can imagine, this new flexibility enables participants to post offers that are not fully provisioned. The Mangrove's order book **lists promises instead of locked commitments**. - -> 💡 -> There might be new words and concepts for you in here, and that's okay: we will provide you with either direct explanations or links and references. Feel free to check our [Glossary](../developers/glossary.md) and [FAQ](./FAQ/README.md) as well, it might help! - - -## Making promises - -The promised liquidity can be shared, borrowed, lent somewhere **and at the same time** displayed on Mangrove, ready to be sourced when (and only when) an offer is taken. -The resulting consequences are far-reaching, because it removes liquidity fragmentation and the lock on assets, allowing its use in multiple places. 🔐 - -If you're curious about the unique features of Mangrove DEX enabled by Smart Offers, head over to our [Concepts section](./high-level/concepts/smart-offers.md). \ No newline at end of file diff --git a/docs/general/table-content.md b/docs/general/table-content.md new file mode 100644 index 00000000..0f14eebc --- /dev/null +++ b/docs/general/table-content.md @@ -0,0 +1,77 @@ +--- +title: Table of content +sidebar_position: 0 +--- + +# Table of Content + +🏗️ **Developers section** → [over here](../developers/README.md) + +### Concepts + +* [Smart offers](./high-level/concepts/smart-offers.md) +* [Bounty](./high-level/concepts/bounty.md) +* [Makers, Takers, Keepers](./high-level/concepts/makers-takers-keepers/README.md) + * [Makers](./high-level/concepts/makers-takers-keepers/makers.md) + * [Takers](./high-level/concepts/makers-takers-keepers/takers.md) + * [Keepers](./high-level/concepts/makers-takers-keepers/keepers.md) +* [Audits](./high-level/audits.md) + + +### FAQ + +* [Link to FAQ](./FAQ/README.md) + +### App Guide + +* [Who is the Mangrove DEX for?](./web-app/README.md) +* [How to connect your wallet](./web-app/how-to-connect-wallet/how-to-connect-wallet.md) +* [Trade](./web-app/trade/trade.md) + * [Approvals](./web-app/trade/approve-buy.md) + * [Revoke tokens approval](./web-app/trade/revoke.md) + * [Taker's fee](./web-app/trade/taker-fee.md) + * [How to place a market order](./web-app/trade/how-to-market-order.md) + * [How to place a limit order](./web-app/trade/how-to-limit-order.md) + * [How to track open and past orders](./web-app/trade/how-to-track-open-orders.md) + * [Common issues and resolution](./web-app/trade/common-issues-resolution.md) + * [More on order types](./web-app/trade/approve-buy.md) +* [Swap](./web-app/swap/swap.md) +* [Strategies](./web-app/strategies/README.md) + * [Create a strategy](./web-app/strategies/create-strat.md) + * [Manage a strategy](./web-app/strategies/manage-strat/README.md) + * [Statuses and alerts](./web-app/strategies/manage-strat/statuses-and-alerts.md) + * [Overview tab](./web-app/strategies/manage-strat/overview-tab.md) + * [Parameters tab](./web-app/strategies/manage-strat/parameters-tab.md) + * [History tab](./web-app/strategies/manage-strat/history-tab.md) + * [Key Actions/Questions](./web-app/strategies/key-actions-questions/README.md) + +### Strategies + +#### Kandel + +* [What is Kandel?](./kandel/README.md) +* [How does Kandel work?](./kandel/how-does-kandel-work/how-does-kandel-work.md) + * [Step-by-step visual explanation](./kandel/how-does-kandel-work/step-by-step-visual-explanation.md) + * [Parameters](./kandel/how-does-kandel-work/parameters.md) + * [Strategy reserve](./kandel/how-does-kandel-work/strategy-reserve.md) + * [More on failing offers](./kandel/how-does-kandel-work/more-on-failing-offers.md) +* [Details on strategies](./kandel/details-on-strats/details-on-strats.md) +* [Potential risks](./kandel/potential-risks/potential-risks.md) + +### Quick links + +* [Whitepaper](https://bafybeig62o75bfxssic66w2zwerbo6ezlhb33vsg5idr4uprckn2dxrucy.ipfs.dweb.link/) +* [Website](https://mangrove.exchange/) +* [Glossary](../developers/glossary.md) +* [Feedback](https://tally.so/r/w54D5Q) +* [Developers](../developers/README.md) + +### Socials + +* [Blog](https://blog.mangrove.exchange/) +* [Discord](https://discord.gg/rk9Qthz5YE) +* [X](https://twitter.com/MangroveDAO) +* [GitHub](https://github.com/mangrovedao) +* [Assets](https://www.mangrove.exchange/brand-assets) +* [Contact](https://docs.google.com/forms/d/e/1FAIpQLSewVLx1AcOwK0DOvMOCIb7hSEfHGwMzB0P4yeH-Aeq65ctlKg/viewform) + diff --git a/docs/general/web-app/trade/common-issues-resolution.md b/docs/general/web-app/trade/common-issues-resolution.md index 3786e299..c3325b7a 100644 --- a/docs/general/web-app/trade/common-issues-resolution.md +++ b/docs/general/web-app/trade/common-issues-resolution.md @@ -17,7 +17,6 @@ Why do my transactions keep failing? It might be the case that the amount of gas or slippage you selected is too low. We encourage you to tweak those values and find out what works best. -We would love to hear your [feedback](./how-to-give-feedback.md) as well.
diff --git a/docs/general/web-app/trade/how-to-give-feedback.md b/docs/general/web-app/trade/how-to-give-feedback.md deleted file mode 100644 index f6c9c0ac..00000000 --- a/docs/general/web-app/trade/how-to-give-feedback.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -description: How to give your feedback -sidebar_position: 10 ---- - - -# How to give your feedback - -The best way to share your feedback is via our Support chat on our [dApp](https://app.mangrove.exchange/), or using [this form](https://tally.so/r/w54D5Q). -You can also message us via the dedicated [Discord channel](https://discord.gg/rk9Qthz5YE). - -If you can, please, make sure to share your tx and details of the issue you are encountering. - -Thank you in advance! \ No newline at end of file diff --git a/docusaurus.config.js b/docusaurus.config.js index 42624eb9..b4106010 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -127,12 +127,12 @@ const config = { alt: 'Mangrove logo', src: 'img/assets/mangrove_only_logo_dark.png', srcDark: 'img/assets/mangrove_only_logo_white.png', - href: '/general', + href: '/general/table-content', target: '_self', }, items: [ { - to: '/general', + to: '/general/table-content', position: 'right', label: 'General', }, diff --git a/sidebars.js b/sidebars.js index af387abc..eb38f1be 100644 --- a/sidebars.js +++ b/sidebars.js @@ -19,8 +19,13 @@ const sidebars = { { type: 'category', label: 'Getting started', - link: {type: 'doc', id: 'general/README'}, + link: {type: 'doc', id: 'README'}, items: [ + { + type: 'doc', + id: 'general/table-content', + label: '🌿 Table of Content', + }, { type: 'category', label: '💡 Concepts', @@ -81,6 +86,11 @@ const sidebars = { label: '🕸️ Website', // The link label href: 'https://mangrove.exchange/', }, + { + type: 'link', + label: '💬 Feedback', // The link label + href: 'https://tally.so/r/w54D5Q', + }, { type: 'link', href: '/developers/glossary', @@ -183,6 +193,16 @@ const sidebars = { label: 'Quick links', collapsed: false, items: [ + { + type: 'doc', + id: 'developers/contracts/technical-references/contract-addresses', + label: '🚁 Deployment addresses', + }, + { + type: 'doc', + id: 'developers/glossary', + label: '🔤 Glossary', + }, { type: 'link', label: '📃 Whitepaper', // The link label @@ -193,11 +213,6 @@ const sidebars = { label: '🕸️ Website', // The link label href: 'https://mangrove.exchange/', }, - { - type: 'doc', - id: 'developers/glossary', - label: '🔤 Glossary', - }, ], }, ], diff --git a/static/img/assets/home_page.png b/static/img/assets/home_page.png new file mode 100644 index 0000000000000000000000000000000000000000..a604fd63452370571004c5202e0d04f6f864a1f7 GIT binary patch literal 90734 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 Date: Mon, 16 Oct 2023 13:40:35 +0200 Subject: [PATCH 31/38] fixing link --- .../high-level/concepts/makers-takers-keepers/keepers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/general/high-level/concepts/makers-takers-keepers/keepers.md b/docs/general/high-level/concepts/makers-takers-keepers/keepers.md index c6d8c852..ebaad6be 100644 --- a/docs/general/high-level/concepts/makers-takers-keepers/keepers.md +++ b/docs/general/high-level/concepts/makers-takers-keepers/keepers.md @@ -6,6 +6,6 @@ sidebar_position: 3 # Keepers -Mangrove's order book may be cluttered over time with irrelevant orders when the market conditions evolvent. Therefore, bots (or [Keepers](../../../../developers/keeper-bots/README.md)) are continuously scanning the book. They are responsible for detecting failing offers and making them fail on-chain by "[sniped](../../../developers/contracts/technical-references/taking-and-making-offers/taker-order/#offer-sniping)" them, with a gas price set such that the offer's bounty compensates for the spent gas. They act as [guardians](../../../../developers/keeper-bots/background/the-role-of-cleaning-bots-in-mangrove) of the Mangrove ecosystem. 🤖 +Mangrove's order book may be cluttered over time with irrelevant orders when the market conditions evolvent. Therefore, bots (or [Keepers](../../../../developers/keeper-bots/README.md)) are continuously scanning the book. They are responsible for detecting failing offers and making them fail on-chain by "[sniped](../../../../developers/contracts/technical-references/taking-and-making-offers/taker-order/#offer-sniping)" them, with a gas price set such that the offer's bounty compensates for the spent gas. They act as [guardians](../../../../developers/keeper-bots/background/the-role-of-cleaning-bots-in-mangrove) of the Mangrove ecosystem. 🤖 Keepers are also in charge of [keeping the gas price updated](../../../../developers/keeper-bots/background/the-role-of-gas-price-updater-bots-in-mangrove) to determine the remuneration of takers for removing a failing offer from a list. \ No newline at end of file From 90ceaa64a595c718f35b66459f12fa553d82b16e Mon Sep 17 00:00:00 2001 From: frkralj Date: Mon, 16 Oct 2023 14:42:17 +0200 Subject: [PATCH 32/38] adding justified text on home page --- docs/README.md | 41 +++++++++++++++++++++++++++++--- static/img/assets/home_page.png | Bin 90734 -> 109967 bytes 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/docs/README.md b/docs/README.md index d453e360..0b6c5991 100644 --- a/docs/README.md +++ b/docs/README.md @@ -5,23 +5,38 @@ sidebar_position: 0 # Overview +

+ Mangrove is an on-chain order book DEX that allows liquidity providers to post arbitrary smart contracts as offers. +
+ + import useBaseUrl from '@docusaurus/useBaseUrl'; - + ## Total control over your offers +
+ Mangrove's order book-based DEX [lists promises instead of locked commitments](./general/high-level/concepts/makers-takers-keepers/README.md). Liquidity can be shared, borrowed, lent somewhere and at the same time displayed on Mangrove, ready to be sourced when (and only when) an offer is taken. +
+ ## Smart offers +
+ Smart contracts [can be attached to offers](./general/high-level/concepts/smart-offers.md), which gives the Maker total freedom in setting his sourcing trade parameters. +
+ #### Powerful applications of smart offers +
+ * [**Reactive liquidity:**](./developers/terms/reactive-liquidity.md) liquidity on offer is not locked on the Mangrove order book. As long as an offer posted on Mangrove is not taken, it can generate yield elsewhere on the chain. * [**Last look:**](./developers/terms/last-look.md) smart offers allow you to code defensive mechanisms that adjust for market condition changes between offer posting and execution. @@ -32,27 +47,41 @@ Smart contracts [can be attached to offers](./general/high-level/concepts/smart- * **Non-custodial:** Mangrove users retain full control over their funds - the exchange does not hold custody of their assets. +
## Deploy your own composable strategy +
+ Mangrove enables liquidity providers to incorporate defensive code, post unprovisioned offers, and redisplay liquidity after their offers are taken. +
+ #### Full control over your strategy parameters +
+ * [**Amplified liquidity:**](./developers/terms/amplified-liquidity.md) optimize your trading potential by leveraging your liquidity across multiple pairs. For instance, you can create offers on WETH/USDC, WMATIC/USDC and WBTC/USDC pairs with an equal amount of USDC liquidity. * [**Multi-liquidity sourcing:**](./developers/terms/reactive-liquidity.md) your smart offer on Mangrove can take advantage of liquidity sourcing from other sources and offering it to the taker, allowing for profitable arbitrage opportunities. -* **Price sensors:** in your smart offer, you can dynamically trigger actions based on Mangrove DEX’s asset prices. It enables instantaneous stop loss and ensures that your offer remains attractive to potential takers in changing market conditions. - * [**Run AMMs strategies:**](./developers/strat-lib/README.md) provide liquidity on Mangrove’s order book in order to maximize your liquidity potential. +
+ ## Kandel strategy +
+ + [Kandel](./general/kandel/README.md) is an on-chain Automated Market Making strategy that focuses on order flow rather than price. It automatically posts Bids and Asks within your chosen market and price range to buy low and sell high, making a profit through the spread. +
+ #### Features +
+ * **On-chain market making bot** Kandel is a market-making bot equivalent that operates solely on the blockchain. Unlike off-chain market making bots that experience delays, Kandel uses on-chain order flow to repost offers instantly, without any latency. * **Profit from the spread:** Kandel follows your configuration parameters to populate Bids and Asks offers. When those are taken, the profits are generated from the difference between the two, known as the spread.” @@ -63,6 +92,12 @@ Mangrove enables liquidity providers to incorporate defensive code, post unprovi * **Earn extra yield on AAVE:** since the liquidity on offer is not locked on the Mangrove order book, it can generate yield elsewhere on the chain. With Kandel, when an offer is taken, your liquidity can be sourced and redeposited on AAVE. +
+ ## Mangrove is a secure protocol +
+ Mangrove is an open-source protocol that has been rigorously [audited](./general/high-level/audits.md) by the highly reputable and expert firm, ChainSec, ensuring the utmost security and reliability. + +
diff --git a/static/img/assets/home_page.png b/static/img/assets/home_page.png index a604fd63452370571004c5202e0d04f6f864a1f7..abed34a3cc1add133cab6654d7c82f8d4dc5a2f1 100644 GIT binary patch literal 109967 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�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
%hdjxlcv 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 Date: Mon, 16 Oct 2023 15:57:01 +0200 Subject: [PATCH 33/38] adding Kandel parameters + home page + dev page modif --- docs/README.md | 12 ++++ docs/developers/README.md | 17 +++--- .../choosing-parameters.md | 52 ++++++++++++++++++ docs/general/table-content.md | 1 - docs/general/web-app/README.md | 2 +- docs/general/web-app/swap/_category_.json | 5 -- docs/general/web-app/swap/swap.md | 49 ----------------- sidebars.js | 4 ++ static/img/assets/home_page.png | Bin 109967 -> 82373 bytes 9 files changed, 79 insertions(+), 63 deletions(-) create mode 100644 docs/general/kandel/how-does-kandel-work/choosing-parameters.md delete mode 100644 docs/general/web-app/swap/_category_.json delete mode 100644 docs/general/web-app/swap/swap.md diff --git a/docs/README.md b/docs/README.md index 0b6c5991..3380730c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -49,6 +49,10 @@ Smart contracts [can be attached to offers](./general/high-level/concepts/smart- +

+ ## Deploy your own composable strategy
@@ -69,6 +73,10 @@ Mangrove enables liquidity providers to incorporate defensive code, post unprovi
+ + ## Kandel strategy
@@ -94,6 +102,10 @@ Mangrove enables liquidity providers to incorporate defensive code, post unprovi
+ + ## Mangrove is a secure protocol
diff --git a/docs/developers/README.md b/docs/developers/README.md index 4c81db63..47b72dcb 100644 --- a/docs/developers/README.md +++ b/docs/developers/README.md @@ -3,12 +3,15 @@ title: Developers sidebar_position: 1 --- -# Welcome to the Developers Doc +# Welcome to the Developers doc -In here, we will cover in details: -* the [core protocol](./contracts/README.md) -* the [Strategies Library](./strat-lib/README.md) -* our [SDK](./SDK/README.md) -* [Keeper and Cleaning bots](./keeper-bots/). +The purpose of the Mangrove Developers doc is to: -We suggest you start by reading [this introduction](./contracts/README.md)! \ No newline at end of file +* learn about Mangrove [core protocol](./contracts/README.md), +* understand how trading [strategies](./strat-lib/README.md) can be created and plugged in, +* use and integrate our [SDK](./SDK/README.md), +* set up [Keeper and Cleaning bots](./keeper-bots/). + + +We suggest you start by reading [this introduction](./contracts/README.md). +If there's anything that is missing, or if you have questions, feel free to reach out to us via [Discord](https://discord.gg/rk9Qthz5YE). \ No newline at end of file diff --git a/docs/general/kandel/how-does-kandel-work/choosing-parameters.md b/docs/general/kandel/how-does-kandel-work/choosing-parameters.md new file mode 100644 index 00000000..9c065691 --- /dev/null +++ b/docs/general/kandel/how-does-kandel-work/choosing-parameters.md @@ -0,0 +1,52 @@ +--- +description: Choosing Kandel parameters +sidebar_position: 4 +--- + + +# Choosing Kandel parameters + + +This section goal is to help you develop an intuition to choose your Kandel parameters. It should be taken as an explanation on how the various parameters can impact your Kandel, and how the market conditions (ex: volatility) could be taken into account. It is **not** a trading advice. + +> 💡 +> As a reminder, Kandel is not intended as a "set and forget" strategy, and needs ongoing maintenance and checks. + +We will be going through standard steps you might want a take in order to check the market and deploy a new Kandel. +Essentially, that means that by using discrete AMM such as Kandel, you can fix the level of liquidity you are offering adjusted per volatility. So choosing the spread starts with answering the question - what is the volatility? If you can estimate or predict it well enough, the only thing you need to do is pick the spread (i.e. your parameters for Kandel). + + +## Check-in frequency + +First, it is good practice to know how often you aim to update your Kandel. Depending on the trading pair you chose, markets can behave very differently. + +Example: I will update my Kandel every 24h. + +## Set your price range + +Next, you should try to anticipate how much the market/price will vary during that period you just decided on. You are kind of betting on daily volatility. + +Example: I will look at the market volatility for the past 24h, and decide on the price range for my new Kandel. + +## Ratio + +This is the ratio of the progression used to calculate the price grid. You would logically bet on intra-day volatility (few min or hours): + +* High volatility: better to have spaced out price points +* Low volatility: narrow price points + +If the volatility is increasing, you can increase the grid size (space between price points). + +## Step size + +The general idea to configure your step size, is that a bigger volatility would likely lead to a bigger step size. + + +## Simple use case +Let's say you want to have a continuous Kandel, and maybe your current paramaters allow you only 2 price points. + +* The solution to this is instead of having 2 points with a step size = 1, you can configure 16 points with a step size of 8 +* That gives you continuity (more price points for a similar interval) +* When your offers are taken, Kandel will be able to "grab" lower prices + + diff --git a/docs/general/table-content.md b/docs/general/table-content.md index 0f14eebc..46976319 100644 --- a/docs/general/table-content.md +++ b/docs/general/table-content.md @@ -35,7 +35,6 @@ sidebar_position: 0 * [How to track open and past orders](./web-app/trade/how-to-track-open-orders.md) * [Common issues and resolution](./web-app/trade/common-issues-resolution.md) * [More on order types](./web-app/trade/approve-buy.md) -* [Swap](./web-app/swap/swap.md) * [Strategies](./web-app/strategies/README.md) * [Create a strategy](./web-app/strategies/create-strat.md) * [Manage a strategy](./web-app/strategies/manage-strat/README.md) diff --git a/docs/general/web-app/README.md b/docs/general/web-app/README.md index c48d26df..8f8eacb1 100644 --- a/docs/general/web-app/README.md +++ b/docs/general/web-app/README.md @@ -9,4 +9,4 @@ sidebar_position: 1 The Mangrove DEX offers a range of functionalities including swapping, limit orders, and the ability to deploy strategies, catering to different levels of DeFi users from beginners to experienced.

While swapping is accessible to all types of users, [limit orders](./trade/how-to-limit-order.md) may be a bit more complex, and strategies are more suitable for experienced DeFi users. -As of now, only the [trade](./trade/trade.md) page is available (more coming soon, rest assured). \ No newline at end of file +As of now, only the [trade](./trade/trade.md) page is available (more coming soon). \ No newline at end of file diff --git a/docs/general/web-app/swap/_category_.json b/docs/general/web-app/swap/_category_.json deleted file mode 100644 index 4afc7a98..00000000 --- a/docs/general/web-app/swap/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "label": "Swap", - "position": 4, - "collapsed": true -} \ No newline at end of file diff --git a/docs/general/web-app/swap/swap.md b/docs/general/web-app/swap/swap.md deleted file mode 100644 index 06ffd0b4..00000000 --- a/docs/general/web-app/swap/swap.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -description: Swap -sidebar_position: 6 ---- - - -# Swap - - -## Steps to perform a swap - -import useBaseUrl from '@docusaurus/useBaseUrl'; - -1. Select a token pair for your swap. Feel free to pick one in the list, or use the search bar. - - -

- -2. Type in the amount of tokens you want to send or get. The corresponding _send / get_ amount will automatically appear. You can also use the arrow in between the boxes to switch around which token you will _send_ and which you will _get_. -> 💡 -> The green percent value indicates the base token's price change for the last 24h. The price is displayed in quote token. Ex: for the pair WETH/USDC, the price displayed is the value of 1 WETH in USDC. - -4. Choose your slippage tolerance. -> 💡 -> Slippage is the difference between expected and actual trade prices. -> * Setting a tolerance allows trades to execute within a certain price range. -> * Higher tolerance may mean quicker execution, but less favorable prices. -> * Lower tolerance may mean better prices, but potential for trade not to execute. -> * Find the right balance for your trade. - -

- -5. Click on "Approve and swap". A card will appear, click on "Allow 'token'", tick "Allow infinite approval" and confirm the transaction on your wallet. - -6. Click "Done" to close the pop-up. - -

- -7. Another card appears: verify the information, click on "Confirm buy/sell" and confirm the transaction on your wallet. - -8. Click on "Done". - -

- - -9. Wait for the notification card to appear, stating that your order has been filled. - -
-Congratulations, you have successfully completed a swap! 🤓 \ No newline at end of file diff --git a/sidebars.js b/sidebars.js index eb38f1be..3a48f774 100644 --- a/sidebars.js +++ b/sidebars.js @@ -151,6 +151,7 @@ const sidebars = { { type: 'category', label: 'Contracts', + collapsed: false, items: [ { type: 'autogenerated', @@ -161,6 +162,7 @@ const sidebars = { { type: 'category', label: 'Strat Lib', + collapsed: false, items: [ { type: 'autogenerated', @@ -171,6 +173,7 @@ const sidebars = { { type: 'category', label: 'SDK', + collapsed: false, items: [ { type: 'autogenerated', @@ -181,6 +184,7 @@ const sidebars = { { type: 'category', label: 'Keeper Bots', + collapsed: false, items: [ { type: 'autogenerated', diff --git a/static/img/assets/home_page.png b/static/img/assets/home_page.png index abed34a3cc1add133cab6654d7c82f8d4dc5a2f1..d51176d2c5fa11732b591e343b6597882ac88d59 100644 GIT binary patch literal 82373 zcmY&=2RN1g`~PDWN>K=*B+4!;2U#I|Z^z1>;T*D85=CWi%04(Y*&<}GW3RH$vC7Om z|HtV2`Td{k>gwXWpZB=$*S%iv`v_4{lDSGuLks}GRoUmy)Bu1G0|0nUmkGh&r0|D# zg8vb{e6H&P03gX;<%{ENC3#5+i36yd`odfaR4a(KyqY40N{x0$vzX; zc!jfiOyp&-=RI?L(i89fP00@+`uLMIB+>S@crXm-e5QOk9}g|me=2!A?4BTIt*$-#al!QD4KUx^!_*rve{8oDnGLPdm>cbFC*#4#iAB zUy}!iQ>tdeQ`?DQ(T~YOoS|$D2#Fe_NHqH0UiF~Jhw$CyWznJ=e@Iy44>MFmE}hQ< z=-_3m?Hb*@LJX9}J0%y7;T*F0Cky$m8otxIf>})#!bX1W@ukFtTnumY(6FhO&leK| z(iFpLW=}%vT;@d!w!hT`Ks?*RjmVsQx7{ z7MOBpb6&p=EMKp4eY~zY#G#FP6ia&XagnYKp*S4{9DszdVa2qE#{7#vZIB^Op?CHq zelO5ErqZQc~S_HIT^5g6T}Zk^(E$iFD3rq%gNbVM2%GdV!_J`Z~rN6 z)QeB%yOUR}?yrx4SoWP9yo(ojU#mYnL>32#I{qE zaGIvmsVz{tc2KxYAb9GJ&QEwZke(C?4q?JS4 zYlJ(S^#9w$`#(vL#5G%B?ZZ8~i?`F9-Y=n4H7}(dll`}Yj)#ZZL%RNcfLP7F|Bj%Q ziK+P>`V3Sxo%sJ=|2!G-EeX;|&UTX=u(HI5Urg)Q>I@}o^HoZI9e@k0y-)k6$G(?J zx$`w|LLtCf__TC)J$RV^PI+0})X6_&(-`*Nz6 z>SJ?WP>YDsZv=j>l$ZZ<{?U^?KPNABoux^Mqe&3Ba2e-+ld3zPVdcU66p*%nkNY2X z7w2O@P`EQ{4B=RbxC%>yqFC#CZ0)U^M|3u$n7T7GeK*#X=?lNa=sIDa1Zuhqen^ zMrVQAk20MNqkzDy>L_Hw?fmgZ_3|_at#4<7g44yh7{ec~|EFPeka)o6df2a+j+1xn z^7%T?0AscSEyX2o0{~cS&$uQ8#-!6n(gF02Z-!&7ZdPijVgE3oe`yZkG*bS_`=<^Q z?9KT3cG%43o zv;P@EDt0ekYfx}s81xfm_k`?T?l9VOohcpe%%(ZR2X2v9z=&H<1_X|D(X7*)4J20( z+-zUC0`j^G>%Zf)70}?r#Y?Nujnb!c4qnFp9xnYp24e#WI|au_*%kT9#mi^H+~KzN zwr=}^%bVb&nf!|o0_01Hl%nSkPS{Vka5plK-=^iu*+`XZEE`xySvCbJI-1@*gv$|^ z+%A7Vp0G5IT>ziPp!MlC-YBqQ;?5;CdZn!XyOxuSdpevSj0JYM8>4Cs1>iUZvLgtQIi7pWet{i$`-_F(i8E2aoutN1b& z0RgU>=_oE$uS17mG^Zz|4Wx?yKcf-T-PbhXqmMoAO{Q(Crz1!krMaKR+$46>9CY8K z0>tzm<>t6_merksEB~q{+{zU>eMKN2Q5x{N0~r2RmeAw${b7L@8P4hC)Iv8mp>y1+ zXCb*rnt4dhH7Si$KPMakVI!jgbl5=siG=1nHwQdzLP%mabwO!O1TNr% zNl>)h+{Xv{_(47TUKTW896W>nuu^Xh5An+E2~{L+*w2_w%p=<(2Ga@CmRFOwIzc8o z1=f7Yr@_PiJMm$xf%-WFb+{^LMGun%;a1EJ^~PmAi9+VZ_N2zFUbpP=*BG*w`Wlonc&AU4H+$?=QmHPJ)P@f}p!4 z55be`T+Ch^sqq^3Ri_2$6HkTD96*Gn`q-6ymd)DXXa8&kurf zlzZbe)39$clRnMv!N)Jmc;H}wn4pff&u&uUTP=cfv0(-`tqz=(FnQIdmRw#EDaksL>6q* zoNX=|48uqce=v*S1H|QU zEP&bMpCX`Jt}>U$UemHA7l8+nyVLjaLVtb~yV&4s7w&;JH|F!seZADkZp8PV26Aa_ zl>nGPQ1bbcqTJI4HAIA1xJZL8DfNwWT`&NG7B;y4L0sLcIQiw=1_azU#z{ z66qP^t|32N_@l34O$}j}FPwhj=a{VH`{RBqp^5D@9OYkB3$HT!@n`0tuUM)%JUd4` z2d6PNsw`$AF7iCbtwdzH)Z5}h!BFAjkU2Z0Fbb6gSFrEk&6vmmA=!Hq5R>NtGpx>i zZ1Y)?<>xUJb0wgf9!sL&Z}HQt)MjtWcy6kqcHXHDR3<^KA9wmcB@>v5AP_h5c};GQ-BURl@0KVp?JHmJt)YU;qng; z>4NT9m1bgsp~Y-$gAuso;?^w0g7&voz;zlc+BZY6gTF=p#8Cu_qgQn3tPJ++p4CD~ zo6vzy_r3$OZCMX-(DzU>3B0vNFuHCVt`KSsy8BiDfL@F}cPg^O>m0Joh@Nck5&T0> zd@BlvOh$)qt4)?uxawD0BLFMY9gV^0uJO6yK+vP=MWrZGabLzH;a*rrx4QhH(H)z% zX52FJ!t!KW6}}g`rYy%o^f*?A`nrls$NRW|l`OM8*Nz?JUmg=Ft3q{qnKCUCOvtHA zIi<=P@%40|rD)=k(=swmiXdM3EK9J$Er(6Jg;5ZP(y{yyvvuk;FT9#{iiCo8FobmP zr>+bi@m&Ve?vJTr*+dZN_h$eqil3CzOsd6p(IYT@p-FZzpas<+(i3{7UXQ^9z=A=H zWMB&o#^Bqm=ZXJSm1N~ZBoU0vG>u^Bwv)5P+PalLQCW-ynAO&kf{{2$47Dm{#Ai7y ze-?E7cDUo!sg^@X`a&m7Kb_8Q9dT|rdMZT|4baPX&xWO`z7ME&2!NC!tM!as-H7}a zhuJUin<<31Z}tZ$&+=QQFKE8h@GO=XfUF+X>>7?16ji+SJs6k84) zlt@dR&n!MEH7l zYursSEtvIQ8UGw*T6;Uh#voE%B<^hlE04z!Wae zi&su%_V1F-`0w>8Botgg{KnfuBX1o=%d-&gCyn6ztBo2feml;z!>|PK@>Ck|Bg^`u zg|yzc3HRLuGZS(7ap{XhMPgM&XSE31{(Ao$u+lD@_cs=U5s)%Gmc%XoEydA4U#YGG zqk3B0%bL{()@BzcVzTPv{Ps}$;y|P1(k__lIQ3xupVhM#B^I_E@^&H}uifE|F(o%n zJo60spyiBV-#_61de4hGjh{lnNOO9!#^IdIW2_<#4f;kJ-Ph>QuLPy-}QKbn4vh`oI3>1sOLyOGYc+qLaYbax;zYi48+*fmYbCUVo0x zuOh%oIMN2v-7ZkEmU$XsIT&*!Af0Kc?i}*qPvA33Q+}U9Pvc1PUEj+FV6Ca$4Avl= zUhb+L0qQwDNW!8NEtmO5`#iicN_f}R+a{T+Cds|vXZr1S7al``KuRNmHjPnl@ky<4360D-an|s;{Y- zeOexqTz-~r8Z24Ag0RNsQJw{%QH3lQ%<5O&AiO@-Bs(R8HoNqhL~W`$LBNh*$bmAn zMyfQ;o9E1eE;AkFp_810K;q<7s4+ar>Srch@D=&h8k=@NC`3=icIzgP_&qOci_51E zr=})o?)9m46X3%)oEgf6FN{P`Ba6y=^ctjo6-6Q*t~1dZeIWpyYXrYYtz_4{C<#k^2n zx4P?yBXO}V&%oVe(v_pW6Y}K7cC%XJ#@7_Y9F^bjRRq{>@8UX&I`m+VP!CR1una5D zbH@T_UgMISIK;Q|S=J~u2FO;AMHE$Ko z8RWs_AS7A(?01tOoL?($5EWLF`h6BNuKLmwtk1bJ9Xr5&iWZ`=&)gSro};%twl*=f zZx;s#;;+vhs{eqduoB*OpW-R-+mawqdL;>x5*T)xy(vD3drw=CzIOjqAZcUq8bd+S zpkwX%HSavDm1pseLmpRT>NVUCN9b2WHfGp{F{`(M5G2a{m~XDG?LZ|jguw>7dCN9N z)3*4wpq^i5k7pro3ij+gt4exIg&4lFOfe7d`i6hq58$Ou83X#vYAa$xUT^&K6nf(D zryLF~4IX!eArHjbas+4DIjDQvOK@?DuL^PFB>wW1F%JPUJxnT23@;Red^4T zf3z=Ph{;xw89H~dTE1cvB>3-BNF4fwuQ;A%hm8JTeN&yFieN=>UeL2WRPH)Btqm%KQ6@w(P#D8c>mwACp%nVRZEKnLn9g+P~`o)PG?fgQ?=%z zD}A38mUyc*xAs5i`-90*f*3cofSz{3pN*w6LQSlcRk_DK z8twyvPbph}M=+l6HJnoaWcjwM@M29XM{HvCT4rl0CHUg2mp|OX)Y(JTt=IEJ&lc4Q zJC`v8s(A?psnj3`DUF6e;+0jyCJ5~E)aJmhZ+=Z?39nE}F;LVJ5b}D|1p9bx;HdU| z%b1QECsU>{6&amNZ=dXYK~0h=E?*!1d{5_75teae2Y17wt&{?&(8(zrv4V1Rp67vL zD|ub)H02FfNVhNht(ZVRTh&gJtW-zhmhlLY|AEex*V*BK@+}GiL%2lUi8%Cr^p^`O z<5>QPd|bC&!&zdf1F*X|S5>nH=Bqqk$lNqLVBftRTm-_qX#|@fngHJZ$7nt2u zO;)A__xWKTTSL9f)T5SAL`v5iUZFf8e@fm|JTI!zUj;=9weG>PN}fqXPto1E$4$}7 zGgVvn(oYC@DYkOE?JwtRxD}g!qw|V9L&3nVTIrn3E?Cd~X~H{}Ua`@=U@OKDg(Ny3${&zLVMGq6SFU9K`A-%a}As@(R^IPj*VjWpU8$}?(JHh^kPzd)XT|8{u4TGzjolJ0QO2D*8KMLHcKU~4 z{$H_wh96R9W;vWqQI4~r$|aDh>sZ_|e9@CDlohX@NF2(q5x^XPrtwI- zT|GwpPoRFDd#}HiOYh%DC2p_tGyr2ff*V8|i`fx!A?nt3Y!~*I*U=TwU;R4=`-CWM zj%@hz)v>#QX-KI(4ef#(@9A$Zu!1!4ozG88ZK?;l^3RP<)<#~ikRU7d_b7ilwUk(! zzOBy4#67K#OScl#qRCEe4u>!+any6OQ$x5xxxd}v1GY{YZtHb{674I&(fhhhz&#B z#zn&wPB-3N3juNhky#|J@O@-@!uhq_A3YmZ`WACGDF>hb)J2>BuxMm zReM+r4wVR=c`IOcO+8^%Q+oG`x(bm0DYAEjZaBo=6ZEU|?!kn`?CEJrdas@)yOtJP zt}m$1-t3Yy+^K~ib#VNK&^8dERbR&349XVkKY35jurm5Q8ci_62g!Kxfm}z3Zdh=~ zP#D<+si~C7*U|7(w7f-JGn7zPk|>_Mj!p7JXYA#LEPqp71UY<>IIxiF$~r3xe!4ES z3#NN_{2omMbc8B(Zn7k+I-&$-I+d8dgZds-&>AgT%bcj*Lh~LD&wv!u!<2a5>U&!l z;OBH#9$HP~oH%@WiEbd8Q{fOf_`)LqZwl9VZPHmcDYL8tg1NFX>r`A*qoHF=QbesV zo?mg`1zAH{s-TaeAVf+bM5jACqg=bYh|do8H4#m3e(DZ&7^Wb7x_Stq{L&^9qV1ix z__(-s4+i&PZ=j5cW1*^Uf40q_TNsJvV_ZN-`a)ML*?C~(ayivKNMSS*<_LD0K+Ai6 zHdoy58?@Ir#=pgrtUMA<0Z({JWRWUrAzaAmW5xiUM=a-DBF6WkS-MZw6g26I#9=zI zYG4r48JPkhxVOt)NlM#lwyG!e8a6JH*aq2G1DBsYb@(vIg{L2VGPGajwj~L^U7Tc~ zH0dRdS?Dg1XU5mzimZsWXFyql)y5!8(~lG~@Zucgn40kLq-}H0mu^(}v;DdsB-{PM z7Us8R&0N&D*l41~d>LFo>rH-~s#JPRiQ*~bbbV!jJC(5jK-A3+({ylVnpw|N902t> z1p#T@0%$uqC|guLb&+!@ctfJgN|Ol=#)5p{p+hbPl4+e{FwN|Rq&qB?oGnI9#gr=2;IFpeRr1?k80~6 zq8D1DU`1U3QZBq8><70n3UXcLKc>mvRN^k*${KOz-E#3Da7k! zL9uq9iZz30r;-j;!0qX26%;ar?vS4lt#-Dx(A8wiVaoxj1d8Eg9zA&y1t9rO-1A%7 zgPIr72p9$fIOy0wbs_NhWA!=ZIm+Ku!JX?UEZnFHxQiLn_hAQ4+O{9|VR}&UWZh@?j z?$*5qNNN_iWH<#i&6jge>c=6bN!OQTK#}r9UfverTEa*M8e$)D=^*Hm0vm_#=XjEU zOTie0Zfc27rS*@`MzfuTZh&7)L=%4VI&d{(X_zB(WQ3T9k^;uu$$uGb1Co?0g_Cv` zE5sO#y+8FB4#c(v#>AVzCl#39G^yE!SeXwE}~qUFS%l!ypooKTT$XG=<6OT_aInubt&lm!l;OY z=7pxW=-n6FSr+2mgmZh`z#DO{<6N(Gl&Vu6s~2|HI@ds-JfHn~m|RZfh?Twdo3Zn* zAiJ0ak#>_APQ&UiN;BI}nf+Qp8qp~hVd@4Cp~&Y7Eke;7+_@byu2#(vNS)s`?^F^q zjOccd^iai6#(nu$(tXB(#JfAkf=CWweKi zS%~a#rigjUnOucAwS=`spmkbtbs~oF6#WOpBY(g{SaQw}N^P zDeW0Fn;~EqF81I-`^nS&@I7I+nVn>YPnPuF3ep~zVw$T~Yz^T0T}$)x(VfmO%@hou zxXH2J;8FX#m`MJVn|bKvbHqDpuEtV494Dw-mBy4)rh3q!Mq_S0mk-G4T)>_qq7d?b8+{&DMEZcJku3hAnTu|8?a$%Z}n;H&O~Z7Gzm(u&6H1nQ?X zOswD;JQa9Y?Dmws|B`D6-Bm8_>4kT*^KxoWe2VX-*0?@k|Ml%|dUxM@k5QQCOf;nNXaT_j7(wN5R+P`kDUZl@1p9Orw?f}Vmjo^ z_FRi`^F-UX+jedgLt@DRTFFZ`%?#eLw-0P*9%47H`J}E=-;R0C)q0OvcvXMnz{4meY?IT&T9|~*h#L9o#;4JVYqDuV`@_i^MJca#AMMn? ze%8A4(E_{sVeOgrV33Dr*lxD{KrXcLo$}c277OFXRQ*WSE|Xt+;nQDCva&lnF7_a2l6*y z5v3+OxI%xrAwTKC!%xhf5s(ZX>M1Q6r?K4y>afvG9)K*Zw4>f(1%&O(0ciA}Xz?JvIaO zE&rHyVX<*smsNxIWOR^Rp;hzpk_Qg7+Tf%1BD1zZ;WaY`?|CA0NP{K~l5Jsj!%HWE z!K>zbiq~%>6~dK~*?;YLdZI^7YtzWRCGQ8xhi&!yMgqT_CK>cWk=93Ut1{($$Z zRHog!ouhsiGy?N|Hz;I~ZAQvlm_ED%yBF*uQT@V6S5cdtd7=<>LVn1<9l2m5%&|!4 zklRF;MMZhZk6rO%+>>D0Yy(yCsdM(kuOL&%JO1*As~%JJ0PnR*9Rn9O1&|)DDU8*M z7D9&U@uCU}e932Mo1?RsF=J z^G5hE7Wp6;7_eUI^qDFw4wgHqROX7XI7THV8YGho33HAufxSFD{d9rkGj*Hq+Z3uE z_`W*H5iYTBgEEv3i7N-g_rl({Zye7zL{)7^cpc7C$0wymnwB$O3lHz)*%QgZ73(Cy z6W!}QDL9JkH;U3$PL2BVgk0tBlw{5B4{_O!NBapsy3w!JBr9vLTuUgg%?HgwmFvtZ z05O-oKP0lZEl&Nf5U03_;Z3rf_eT)(( z(H|WWE9y|}o=f41Q|2RE$m$fIQ7h79QjEgEbG++gyW8oHH~;J*|2~2WQdQXP2km*K z3iE$G87?`v;`ep&w}i>9KP9PgL2EI?mF8!xqMfX6}cZO zRzrMBkb4eQ>}ytodPdV}o!#SLta%1$tm%hwQ z-paw%xwZBBJW1gFJh1=JiTI>o3+5!g-FU#|OjslfW9!PyEH7`;_@>-=2WT2D4Ird| z+r~jhS@}hB24PiI?IHc)QcNY5&w#%#p+w9tD(mthx;wW?WbS)Asj*ho9(XJD7{z~V z*km|i*lhhyFm}1xe36z#`Nzxw3swio!Tv)F<6-;(Ci>NAGJ$RC+FI-h3xnQXmvATP zbJ&tndO76g5J;S#K2}QmBRw<)gF|lq>yU{R9IM-O!{#Nnw&uC|CYT~l`Ww6t>#}XB zpK01p9+cb_Pv)fKN=f0?qZN5#gJQn148x(Yn_=}vhoV?1obvc`m3rjR^Y?SRx!N=L zb@%I24+S>I(z)ElCp*P{r zcO*3AXQ3kfMmi}PY!5t&rs5HpaYbl8Vg zVSfW_=<}EABst@qyKbIZ@q^Nlg!IsSEq3>B2790ISp8tNm2)+3G7rCblfRY8G(1fe z{BgikVN6%=e20Cwn=;)93|QKd)6<+rm3L z2Uah<)LqiQ}~b?!=IGFGxUj7}y-h%5&mUaBG(M zFI#rZ^g$Tp+p|N@m>GrdOc}U&ef6qD8`PhW4Vw-d-U42jFsga=rEuiKd?D|XTF5nI zq4%P+Ed3-$OT4=*{pfw61}xt6A#Q(>4vs$gVJl`|172RsZcxvDhP5Af#lxvevn_^V=p-y8nHl$_5-&H<+En7xI0R*NCgjj=0tH=TiTU+?3zHs zrRhWIU?xHl3arBVe~nLtc1%|>Ttl%U;>{&^0;hmLE`sF4Rc8W{m)FWoWwS(&C+#;#T3I-)B?@1E(huje!oT9YNLo+B4|j)T)@Q>zsRDbkl`>v|@! zY9>)cUQVV*q1-7DK}rIxMpnnmudAgZU2YcjC@$I~2DE;X+=p7h_= zPx>TB$5Md(v(mu1l^exNvhn1x+eRUa@Mz8W)cwg3w$IZ;Ba>_B@T!tv)$DBK?DAvuz*{F@`rH12@qoIba8zn_$Ox;;p>@!<0T<51bIIP{z zZa~E>2RtLr-1ATi-Y1cJxM_Uu1>A%22Yb63r?k^suz8$67HlWf&XcW~C`nUdOBSdJ z2tq)_icvTCZ>ii>Z@A*SI^~RQIGDhUWVeJP>#hc-sJn56L;R079gkzYj@o<;78jQ? zsnK~8>zOgo{m^(1J;N9a%YQpa%!8W22c5BLm!wBJ`l@tcIq?*FAoSKD&{IPeg=TOr-<#fXqK7*Im zgrLNOTKLMFP%bO0^@fYX_LPywi=>w^6}9~cuz(GI>1wyr_e)wcxqgn#io*ePBY5;`UTImm)CpgG+0u7Pxel(ZSac-uo)dLZf(k>9_D+^ z1yPwjOpf_dPh(DUEkeYx#)#b0ZF+0YVP`#!6H?v$b;10kiQt^RT|>9(q=0<)Ou2xb zF=pQt(2E6AVX&lKc_b0zel;?4S9WKz8sq`)jdSxy^s_hG9QyX+X}OKCn7^wULcD%+ z=shy_Cnt&}_oX=P*9AEowp-WbkGVbvRGqMpc8*^2(y8!WmPPyg^`jaH@`#vD=q}RW z>^O8?k6rtN)Ev2ggUJ2&$>G8r!*Pz+jGK=FVdd3VzQK0?hz+q`a-_GHXRizctg|&JF&pR;8RIO zIh<~g`y+m9X`%OImTSIq=I@&%h}&?YdG@sj)s8O}r(i8pb$YhL@|6k8)xHJ?(|^*K z_QDT*8aT1zsqF*(gVPhBy>8aynMzdFcBMS!IFC8U=#R)1ba0*bB~cG$wGBnwylVQB zWu%g88iDK1MmwgXw!EzW`xNf6cfAY7CigxZ z*mcyL>_}kF0sSk@j_2a*w^>=r-!aef^5(V;s*K$Xs@G{_Klqzt1p7)A zeU9-&AN2d_%Kz}Jswldnot?c{Wj@pc8`K%QLb8Uce3({m z+5gL))og-8M26JEKZ|0skP{{Ts~x+if`oz9h;MJ?6cs5`@(%3{?8_9d%tj9aU1eccfZR4MlL3o z+1mLYC|P!QbFh|i+nj033pK8$>M*jt@eV8Yq)eivpR`!|J-oMGm3Q;!3Y>-`Kv^xRTr z0+bXD>y#g?f>kfvKkw-Qk~3jGauO4Vb>1?f;N_-Tysoh$IelGh%xJx$N2<3*HN$w} z?&Wm1LZVSqnV7w-?UtjE;}?&AZ{Jf((2v?*GK_A~R(h+>PEzqkpi+q-t71AZ|Aj*` z>EB6Xl_Uiv?W>oE?->6+UjK+0%*xFfRLH}?a$-e2wEQ@J1?eIWT6S5Nwq?KW+3yv; zVsxNTz7p2nTYor54(36K9_4DaDBr!!*aaieeX{+|c9+c?sry%*Iw>exTcmuI*NWC< z?FzW&H7;$qh+>5z8lGrscgl-Ia{8jr`^f!zBuNxdY&2mV!J>b01hMm9zZRE&D9g=w z{CHm|HFni{H?ty&RKwGw7W1QenM_RHdU3cQh!}!bCz8kMG_*IQs~}rLqB8|ejbc`n zU((bOnD>-GvGi;%j8!n)dApcV7=U(v*>J_XO}*r}S=oKa$Ti10RDEP#?=B0)j+ckm zONCX%9DH`Iyv<3J`~Kp#)PBgN)Cj9P4|;o{F-z*&OmXksXGEc@OXUR6rPPM)R>7*> za_!p68;5)Qr1yqkhyG39UynRKCuL#um14VI8Tt;Bma42ZnoToAf*Eh%vl}FUD7JA4N^nP^(%q3OKx_x_XS^W-`Wg3{V2Mb&s zBgmAt>{?E%OdB)a?WYrZzpf>li6Tk6 z$gpw{-a)^Y)B0P+Ao*;{J;kD9>#)m%6p=qiKjQC(y)D?y6g}8=Yv&36kkbvHpnbS? ze8})Ax!sU@0~1;Q+yG{#ov)dx)wcS0%DMRPw_!Vd!=0fkR8fxiE7f$>bu6XQS#_MP z0Cb9Mm=bTWF%Fu7Vy zTG@j)k~hPRZk91j;r6e~KQ~_T(<%PZ?Zoj-OzdRa=;(dz(l?oPccZB~jD&@uVL}yq zD#T5LGmGjw?1rH>D*3Q#=96CigHb)mvyvKeh*a*1kJ3{v2cNk;(TOmM4+Lji zXkWJddJt?BvF~`Bg4f@V!&O;%>ah7W{Dhq%VEofE!uIqcRN^pr7(BUkmL?ozydLF| z()N_tQ6Du&kG3}hM)gg6}Q3#{GJ*a@Prq?#Y#!hVWcie&-|g8pQouywtZ)Yw_n zc`p_)*>DqKBDLNh9cw*g^nX7F^AWJM$PzeEk{ z61Bz_(#MJVXw{W6e>OX^kQLENlc?UNwVWR)JjvCFEivqrryBr!JU5_V2@m>F?Xa`% zUf?BF+b2C%wqM0}XEHsokDv72TaedB*Z@kAd|1_HX%?S>YYds(YiWC9zK1<=B4Rcj zxSSbuziPKt7Cp_w46Si}?qH+zIF|W7q>rWUQY(SmAl|d3`rXhjA9PD%^RpFe_jnO_ zLe)8s)~LPu`|Gpa_qV|AWaw6D1X$v^y_<^N)-#yS2#izHoy=U|_jD*`=cDMVT0qo~ zIJZotjk`G;P>(-ln)z##8u6#UIMI#kCNX))v)WLIVz67eUbp8=GN+~bX1dV;FYu{0j_B|0i$k<)3{Qrd*U`I8T|-agt(}C78Acjh zJxQWjEW^Ot)e@$hX6ehjOlEC+^@S#PlPS>~pZtT@BT@14YV8zYrRz=3K=YACTQ5H+ zBcLnKcayI@rQU1H8>ExwJ|cOA8|(jal&!c@QZYGQAjv_y>TlDd_@gzh=S~(Ui--0*$Dv_iQ&TZN z=~L5Rx=WlzQ{a8haVzF1;yGxNmC|#L5 z)24m0k8Zpluk!gFv6@Fs%fK(a7BUw7sBt?v8;m7-*{CqbsF3q5Ph`Yqw4nQm{!By* zDnj@b);r>DTc)8<yI6EB3F% z!qZ1H{mO>E~cOMU_kB>C(U2uvZV}o)X}=z9rrhouA942h#qI#PPL&#p=^D941cWQkkU}D=yjDti%YF- z3*H+(l~=ZR-90t?pFg92@=}c6bNMbc!vwsyCPl8h-RQUptG6>K)Dm&~P!yY&Cg>jR z-2PQbw`(I~$%r#k3X-8_$LDX4S8r=GvY2^;*SkIZX)(G3(y+PtBL)0(0QvExp9xcZ z6av~03jM6LTlS@NpTNa!Fa+Wc=p+CB<`1!7iA?jDC|P;3pC9C*IIqzWA;NPvH&*%i z;&*~Vnsud5-|o(R{C5RnT(Es42vxa0KD|++RXF&Wehb4NPuvcBZo1Q27w>ZFHW8bI zQzdGboc1G7YPw`Qc~l)}8<~-@xG&5*mPu7Fztv1Vym_T#Ih<}Y+#@rHZ=#5Ho=55M`({XaA&m;yRQob7%fZ_{ zaGfq+`DGrGXjDK_B+c;8RP*DbPj1N3?CN{DRMaDeqUa!)_ocSFcOju8l=p=MIfC}1 z+!liA!)*xyM)D##Hn1xTQLJiTAuJ>H2PFzvv`fkFqZPHJYG#ME^@Ff~R%DJANf@bPlJxt znEOiy>xcI;HKd6Lw;mt2^@b#JA&TsRpUDI>P0p-ct-89mlVe=K>K})Mxi}gsn&wtQ z;pEk-Vc8Q`m({hc@7{}Uxi8z`u2hoEC2Q^4zl={Y!^6o8`w?sO3vvE8NBlg#MkD5p zglu`UWZuz@uXR_tY~G}_yH#Fzb5elORl6(iy$fYYX94>bYepvpQoEDS==UeCoAc_d z`4e?6*+*Rse`BW)?dYD+80^!lc{;S9Z3CFIb{Xg>I>tpr7L$MEZDMx|2cb!Of?^j(wr5STp-TMMhFO6gaWP`B^7d>O$6ge6lvEQ!y zFsWg-t|mu9$oEa#M0P1bHxPu4NsSK~>$Rg#KZCQ$DydO_868up`)y-&a|o2^oztihI&07%^6 zufbg$qMg0VF`6ZU8(EeEQkOh73_(`m^E8rTBQI}$Qcd?Zd=OC;V8;t)ypMUU$|}HK z8uxl0!tk>O9lzGTEev@5+@LCwK= z!x0Mq|6jW(ilh`8WK*HCS7lt;oONW&%sBf9Nl|2H?{UT*8OL!n$liOG?GBf54rlyc zK6-zDe}OyqTF=MaovJ%H81tFrb%}E3sGjjQZiJuY4=C;P6 zsdIEMJk$q*#~xDKPosllPn zTi3nb8nN*^?-4povUQVD@kuu2uhcaU@*VmWVuaf5y9b+Q2i3sjh$%{J$(^07+hG(H z^Xn(Oc-=|Ykg(JbBZOqiJ^CT`h5CQ<`jtPiJoLl3am-G0m;x@|ZRp7Wi=%;ijlBkT zIgry zrWl>y3e*e>MJOWlc$u&b3U-I#X53 z%cFp|^~^=_%k;Ur^n;PJOl<8QFS|DQhGGwX=KgK26L}N$Orc@nB7|lR7p=0}`2>6tPd)^b)+Ww;|ypgF-Ab z66dkE`a0RA9`bFsYPuuxP_c2nn*W^+7c?a#7a3_!o)zr6!XvZ*kE8s%JAqXjqPE?DAPD|)3 z?sfs?mEA0A-MQ@ifEq9cUH^q$Wpl5hR%1EO;O(Y3IZ6j1r{nOpB(|;5bFPddKUQ4; zUnVGT8GH)%4!2H`=3?3(C3=#Lc_oP*wwL~H-9iVGs}9zZweSBvF7#`Y?hic+@*?P>T#YW*Df$h zr(G!IEHrq2ZY0%$IM(glt^x>rz*u2D##Lt@H;>wnOIIS4%t^<>v(an z{fM2k=7gTL@ae2n7fGh2ak1(gARWc1P}yCE>82SNB=Fp*<^sC>fPu{FkIR%`>4i@R z!;1aSb=Kl6&F4z}7Ta^>6T5{L@UH^7y*gk@H%OJ%k9352+?+`~=DE6;A0TVVNDY4g( z5c>XFhXK=;-s?XYM)a;5WbLta8vcuJSUWDlYwGQ?A~#6!Cd6Bdy?26GIIbk8$j?Rd z7;(g)Dtq}wNyhbwaZJ=6Mb|Jh1V`sEv29hqO~LGYqIbM~rzkbVRj-B5uD|0I8j#u+ zbET6T0lobTsja`gQ!kF6=$EP_RD^3Y2_3%sy&Qwjoc?HVNTtO?jz+r*Lx3Zl#7@~5 zJ2zP)){yd%+dBjRs|O5RWWmQdl&elEE}@I9gMEFD>9u9mBv!{h_Lw-eJsn5H%~Sj`yoagP+PY+AE_<$dCu7h@7*aV+n= z96zOaTtjT8EvfRRP^xEvs}ZJfY0R>Z zE2#a+gM#)hes&;-?=gNLvPOuwK)1$*G{n+cQ|oR+{SE}pH$w%-l1}6<=8GX7C@u{< zwc6E{cWZx6Pssw}mdOHFz7Byg?UWl!$}M54HPGYTO)zrm_Skyl&gMDda{WF6gu{V7 z*L_6b0*zR?s(La+$+~jV-8DRC@a?;uET31;y2duPQqt+9JWEe}LGsq+ZqC;Jt|~ZkFs&?y#)+yc#}~sW)wW9?%|qdt9Sd zVpM(aIl);nt9O0$*TFCMex@E|V1R=xvJNBm1<7Yw&mEU7j9JhY)fN&Z)@M#uI4p|V zj&BLxGLi=gSca4l-biujswo=(vG`VS3bEJPdW@SS=NN>$Nmr^yo^kgK_g@o%b>qGG z1>N@++?DO-$77s#Y%q^CY18E%k?t ziNA`(m*ygmalID5c5M6nHaE4NEsbm3&!0m)(x9ed=W7C4zj%|#wd|wPyIHQ1#i}_{d;FQ5 z#_hA#M;tpg~zdg-r|)(8)~F2Ze~vcF}m;&pKE;)ko~&Kq?%X(k`@B+d=s zv<4Z=ZZcv;ArMpY#(Mxz?j#g#_OVEoqAu_diVGV8vB2U{00bDc^nFF9e@{5Zt;l;r zjb|QDr1jc%;&>qF)L5IlXxfv!xtlAb{kRU&i6A3r^Gu%sk8ZqiO_8Lf%qfqO2-$OV zn_i5%-N~aILyTmU@@jy%cOZk1`?j>0TAyF)Mu|(Lq-QgQm0kPuY!xY7i?cGH`c|O& zI>T$B9*b>U_{4lrre>}W1eV3o3Ubs<7 zB(a1x#4K}kwk0=(fnkR_Yifq^hzPc}1j^eIvr8XXZwTqLNj}E6=kvn8&-M5u{^;G%-)W+?(RzV+~aF8 zaNPmmy|kq7TMQ?(h@JjA!C&H@Yv;Yw?H&Ap=LvE)^uaoy-S@Af6JYUwm}^zLQ^ma< zKk<5P6%Su~kYvu^7~T)j>bfoc`! zS(RFJK3ClAdx{j8b-#)~F1@cxytD>PuDylh?_X52Jx3UkZ#@Iw!P6tMKd`~H8)LXIG;SO< zvF{%lNKJg#KBn>tpJ2GXSNC~0d+}Gas(4tmB~#7l1uPHb%(L(2h8g0)>{+!AEMuqo z+I#Bo_-ZvpoA@MMyg5iri8XF(<5wZq}HQH=RoS$qd5b&OE&Ra!PWiWnm)F%elI- zq~a458&aEZHl+9R>fLB3N{2FH1r=Au7@Li2c(!Svr;3z_uf%ygO1-_?SJD7+r#GL~ zBX;dd87h_z@498Gp`AP5cd2h2b$|?J$C|yKrNi@-ZF5wuAqAE9*M1ppm+0(JWgFPz z4b)EsC*JaNYVqb9_Y`^VV}Opn64%FnC$zD%<#%TAr_)rA#K(2YzzpXol}<|tfufOY z+skLxr#5N~_W}jI5oH)j$`@B@*Oyg490KRh;$=u9gGP_^3k+goEh`g_#;&py@aD`W z#0TT>V$xpWJllP@ntk@*POb{B! z|CG@Qww^Phq!LuOiJpXuI{lqMQ%cfR1OM!O4DT=}o8N{~{NlOh-4CT2yoI|N=mcKH zogq(v*K~M0U1DL?rR5#GK7{Oy0oQ9hrKjK*lh5Vc-0av^nj==URh<$U6MqVw_ALvZ zG2z#3OG1oMn?OnzfG`Y<)QCa73Xa9h+)oO)8n^-k%Qhic?fdsmq(tQ?jp^pCIUBq)z()Og{*iW&Q?3$IKMyj)X_+<@wK7jRa*e>U~mSh zGp3_EHB8S`kW=u3^X~EGT)GUTGak^9JSKCU{w85C3CWt+mBo11v(xqY=bhy)g1WZUWOh=SYZ{@rTtC zHXf(;Y}8!7YgzxEdLe^{>c;+%5TNdfYjZtC6gkg5QH2VnNrqq?T93FGV|nFdyK1l& zJP7WUJOM>jJS%>x=3ZTK7AP1l-B?)7pVP@ywVPFXxC7r3-ty;M8Q#=5^8o6503ocT zkJ;qMCvD*NikYN}*heM_L9VgoqJj99;Uq(GFO8l!l;X~hw=<|VMV)bK7aF4m<4Ruc zKPg!!f0*cnBP36(IZmvqH*2>ZEXb?krVR$5kJY_ z(a#iEfTLyk7GHU3z>|`&^vO;X7uQd&zm-}3#~v5yyIwQ+z(oX0h)4Ne-(Io8p^UN2 zj+tQk$fA7TqsNCpR(9F@;r!od2z}GbmJLaC5aM;h%Ysv342Lh9Z9w2@X*K zWq&?jtEi(Qm)xGD@wlX9?uO;7d&P^{l|X z&0juK-uZ-J9UdZf-_{RF_oTln`f*SP>$m(9(dl%O@Xp__c7!JH(b|rDLUHwS{`z$O z*T=l5Vqc$Mrztp553DnB#4441x=x_h)sPxb=*b3;*VzRz`u9)cI!A3Edp63Oc>3;S z7&d2{d)Gkr*RLDL*=5hP^SiccH>Xtbk$M>YL`XLZb6fzvo)b{6clfl-*hzr&4#pbG zOgM8WRHC6cwQCP{#(*XpeUunMB_j^h88~Bj?mY$onXO5ns~_Ul(W z6;zkn8~NiJG`x47B~SD*<1ou!<7)}zdF7|$%OiL5gzWv0YU6IG% zL1^Ify;Udzl1lONnlax0>Bn`3yb=SQ@G$d4>0j^i*RZ(7KTgLoG)9fpt~)!(`;_QC zbqwr?`JfyznZD(_aYmBdG@W(n4hq??XA@3F-9NYJmQ=x?qmdl|NUTHQm2|bM+}Bx5 z0O7q?Nu0RkpYmhld==ExfIii$lsMArQZ46+rEc;N0uaD22-nSh^oO_Y+Ng%t<&UVh zLbLGnkpa#RPK-UvY*F1;!ISPS#iZLsYJ?k3mm z-&sp09=xfce899q>$YDgS&d}Ea#-{7jW-q;tnQ%AtCSAnSJuwe5cZwG?T^>aAI}Pq zV0jsngYxWmt8(FKa@MLG94uXls&;saY~Acdr$)5Xk4nyIpG;^ME(cMA>SI)hEJn{D7t&SiQw_yH-w}cabm$cQcL~Nn{%m)5eJ|hi#QmH38 zLFz0x)4T~Fz#zCLIq7DivAc@j@ zXO_r^^Fxczi~OkpYX8x4s2Vh1(ZjWgmtgowlgrx#)~I1J`z?yjGkrF>h31u>&uY6i zasQF;!kO7&&Q$C&0w{Ey|EvLTlpTpuah|cmLe)63Epa|exQ@LUAx?A<98NP8hs_S` z{g!G@Nv_0wU7=M$79Ouq60{DbrEAh(tg`~x(G_E{yVsR4H6O!?5A`Ac!1S(HuDVRj zcoLQ`{$}B*egjg}vBTh|&E~p|o0n?we3R^laQnEaep`+9*;6kRgB)V_Q&pSbf!Uj} za1Nu=_Hy>T>g4U01y@X*O{p)Cl{gCoEQq3kDxDIgh=7hi{?%u)Pai+F-Q@10HWETj zpoUt_jzEoLx9cQ$47fkPZ$`0ge|hV(6GOP>4fQ34PBgnp(o+;TJYUAyWdTjlbon+7 z(-BdV7PWv#25&n8{^S+b>(N^gdjY>(3c?KcGSQ0Fi(+Na&HcT)ySVVN++K0nb*DAY z^=%gru<6bu-FkP>S9ZM2PmO6oWlLwgT!^Jddqq7yn-{s%k2+rRRwr<>IVRQuz9t1AA%dIo8vP7$7TW!b8Ih+%Q4HA$(W^?)g;GJBr^?#}6 z+hEin(Of8Kc7UYd+(^+Ev-R2%3$KlqRz>>*i@&f1iSWce^* z;yb&2DB|-Y4|u;w$@}QTLsPqbCi{SeE`;&C2f_w73dcS*@fm#2hw~gLsIA`iB_Z~p z2Wtm_gHUfT5H`1FFjlooMGq~wHN$H3p>ICEn5&$SDtkqhJ6JXQm0UTljQycHsWXjVRb>3RnZl3a z4-~@~Ml_{FXb&y~8pEZ=OU^JV1UAKdl71rbfrvJW3)p4 zu}xI&Hw$eq7+H*Mh%9>Vs=>&m+QrbvZn7=C>ycVy`^}K@rkAN360R~mjUAprC#~uG z^B?gvFI-LE^yV+eEaf*Y<#amfFSp*ztA62q8V(MR0sjx3CwjS~am6T2#{OpPeA6-X zZ99$~>d&Y%n;tRl0J`CHfIj!#`aQ~Scc$jEiu5P+TuE8#8Uq@<}2+xT)}MRd&6u#%v}hb87%OQ!cv!6O?HDGt}me=+v8w0A+R zm8S0erWyQZVF5e*d#}!|ylR-iX?OxlxMFc<-K>%4SC;}0R}anhD_MlvRbcZaJ4^N< z^P{k|^Q>&lQGmIdpBb7e+Z`hq#|g3^^zQo2(;Q#T$H#`H#47Vl#{>+*R($EivM3Xh zbgj~e4ZZEQY=+39=xiN6rIn?(tMgs<&*6+Ofs1Kozq@)Aj#{%)aHnmVqH$z~K7ZzZ z9we~c{SW>t#)9~&)@lEpvjpb6d-qEXucjXt*GykN5$QeqRtwFqq%l57ov`PF(YSdf z21RM)aChjrUh;PCw~n?h(}%H#U-3pYjqwwNB8L|jpB+9OF5ows0asmy2Sp*Df%ZB~ zN}Vwmg_PmAySfSxQsZj3r$%3@_$I$#Z=&-tnh@@)jRL>9Q<_sTmhR68t=h;&O%rDw zaAD51mxZoey)0g~$zbRBn8%O&-MwYf=l3!_-P4&zs&%)Aot1(Np6YomYr#?>P^v3; zb8)r9U~u+aKl@?q5*yxW>dz|E!0FGDNnWLk{~4L6zP0K9#QyEDpV-^jE2+9s z&h$mx@99qJV>_RSnu$~w8Vl~Es-uwHf z#-X6&RWq)bu3O2q`R0Eb%%(0w=&voItAD6;p4n{YiGW|z|u{+%-B@?49*RSjh0T6n|SSr84MBf zd>!Y?Hp1z^Z{4SA0EltJ+OhjC7mjev0b72PWTV_ch5?ahB2f&vIwb6u_?~H-wZ=|} zg_n^j-N#UtP(|J@6PTTA)AjD3tj1BV4T+XP7dF%TQ_w8uLJjP8kKR)7r?A&)jkf+( z%$O+;6Bwt9t%#r+PkS2#9N>diL*Y?^E%lBFl^(|=#zGbHPCv9K%SiN=1xb>2@g*eL z=f!+I%L-d8=Q}sg%oW$y7_@t$51`58A^a`7F6bux7=Y`gr^Cp^`ze{Zts`dQ!8KBS z2-O=Jn4dl5u%A5#9e0f0LlcZ5m3eG8s;J{QYh_8hbNCD`IGGx`#&&WJ?t1DXgR^X%!eby;HxgU9Ny*T*sfqI}Fy!CNGG>)fori z=vu{7Uda-@wTjDcn5(B5^U**IDYhYCB_xC2ez=&aYTl<)dZm%`f>ev+ua^14ir zbvsK67(-2if6^=e(z&oaQDL83gP@=i>kdX@*4HTW#&OxbO#SnscL))64|pYcT!j$b zucP+8aDkPGQZE7bx%@065gG@OH(+#>l}Sa_=O}3cJB++UmL#qvKXVu4ebEk?6lWE# zRkil6JG?}vX1UK@AVI7R&}AW8C=(Ik#sW5bB%%MNx z@KA@U6l#kYeBMUaA%7?yoS1iRg{X`i{Y-?CfntFgGnphq^&~!*hKC?vIqKzYp8JfZ z@x=khK76!~s~HLJmmaMDgP2&jo2#~QLAWAmWbh*`oubaNJHGBwLSTxtRY7q_R%s%m z!_vP+sg^6B3nrJ^K=F7@%mbJtRLLR>5KiSveC+}undpl2$-lqUCtLj8StIIs zzjYc(-Acu|YN%w-Wi9a;4}aD?Hu>7$4hzHIR*l7#EGEvY{d_8Qvc zW?xEHG>~lZ-=pCaR9XWUG#(khxGJ_2E9$1w#SZi*tq-Z!a0n30r2R+v82n$_;J@97j`F?3tSzJm{u%=`I+pHT_Uv>Y0ffHJleAMeFB$3m z=S!uH$9dFdaVVE zMTB*)C)~)tY3|dv+hDrWa~Zp$1DQt*E__u*JjlPlKz|{+#t#FfHey29X*KpJ->q}% zcje_Wj9+)y>7>bHaz{-oyXF}u>G#{lApO`TDqir77LFNVYFsz`kD^tm5_$YKlH8r# zLHOe;V&h}A0ON{9s`Ooz+WSKJVu#NMKAe+|7wd?iZG^{0nz@n0U5GJ4@3h}<`DZ4r zI@EL+#?pcps5x>O12{G#7+Q%*HC#fvIIQ}?l^UJq) z>YTl(pOh@$R_OhiPL-A%=h?Ya3?hucu^O}8e2rVB9ReIdJfV8ipH(`ucso0fW_&8< z%-2g9msJNJ1w4UHaioH+A#r<1SB$-Cb2hHNsHjL>Cynh!SssxSI>LB^)pwtIHv#3=V^)>o{Q4zM4z^m}o>R@5GApQ}^s{nh`4LC0 z)z|_`>^HBG{qMn}oINUFyqQV(fkoxAZSpJ?mrzFuMT$D95AbY$t9(KZ2P)Owd>Tm4 z65nX-AEFONS4ZK=MgE^kRv#M~hG9y3ftT%S!?pwlWApOlT|S(rQv{w*FTE)*L{X@w z%U5kMy_yDJFfi))kCcB|08$wJHtaxjqFDfa_#`LjC=B?NN!|deGkih;eq#w!OIN2k z=Bz#EOQF$dWy~6G_*DS`0Yz7YFF}_Dtw2OOoTg2HI*B=5hzEaVmlwa$e|v}hq_Er| zVp`)7tld&iBSlq-qf}(ie_2iU6g&{{Roo=FK+e%1N@b8Mai24OKFsS*0REEXV;+F3 z27HRDd#$~^T!dp50G^8z2cwki*p{YUM?WK*_!{Br?_{Z4vOiLCGDeNDK^fipyf-!- zh74IQ^(`LDyUTeS^aEVvu?t;($TsI4=q;Jonw+??qwg5>KXbL^5vWaNfR62e%n{I` znq2+xIuLTV=rwoNh4Aow=H`Y5P!o~fudqe=6A^VS8b5oxrI8nNj_UV3`Bw_>D7^O*>Yn1-uOtnQ~zQrKpPmW?K5Iucl^6b znz#Unvt$^sKRFn)6yG}WbcJxK+7Dw#`9lY>uvDM(T`%Q%55rMnC!l5Kgbm#Cu@9dv z&?LNf@Q>dlK3Px?XVZV_fTE?w??OVBA9EyGQ^7BO+(4&$X|h~|bHG-5qJ^3HkE(8{ z^ix65bSDmVJS7OblG}J1UPrwDVF_6Wx$FQ1g6Zv0!sKLV-f!E#jy`Rac$EXP^yjIn zW^dG9P;MPms@9!g*{~R)c|!Gm0cv;wXUXaKkns7+m&5|I0I|9PYGF{_bV&~DTsom) z;=UcXG<*&zaE+ESCi9<$&YI5aiP}oGrUoGNNg*t(aX?7+eMA&bNtN^-uKwbO`*CN~ zoHDuN@BxS`z!!Ik^xVJT1aXHF#s?p99V~TQ&3;HPq70KHywoDe%U6V%pqOuk3GL{t zQ*(2RX=xpP#W^aQ%N~3D=ls1MH)M#V^l$f78zrWQYaY<#kuv@rmogOYloUfvT_(xL zEn`@?zSnYDpEE}5LD8MEUdk{66 zp7XYqtEG>D2XFq1@>!mo1nNPa#U&CQE~cYDgag@E5`J~*MN0+SPVt7%?{j)Pp-kp~ zRO5RM!ou16jm67**I;lQWt#d zSFw9R)9===E}Pt}ee1jbFJq-Q9iB1a`*CyLOm?t%fgXIBR*$^rNr2XaoS#*xX<-{ zKP9n_c(6i#KR(ItM@ijh@Z2voj`rLA>s>=0oQs>8KbVk?tDC^6zME1SevZv|*g{K8 z?~Qkv14U*H_~ETVAjEa9|8db`LDP!nop|V}1zu@orX0sumJ^BT3C&7CuHh~;g>|0Q zG`_5mT6p~?)=U>PEa5fw0x}+ZJ~d1cJbDV-%VK`G7KorfWiZ}DuXj=MK_0dfn1ze( z>*9s8<4-M0l|ci>&ow94vb#N=X-Bu-kQM~o4X(>!u|Gt!}D2ujn|v*Uv!BOOvn;q z$u~2lZFn6DrUixUORgd?yFR--TPI)@7CjgaKl*OgEaeS_S~+tZ!ehoz2n0vWCuSyc z>8DfPHz!_vr z-_fY`dcji~O7HhF{K;vr*&Y``rRT@j7})kIeVnGE`yArqFx_&JN&py$CQHghsY^5P z;*D8sPaQY%|DZ*n1D%NugH8+wpyxu(AGBP&ZEFsVtbW~Zx4gQJZ(_f2X;KKZXC<`$ zcRi=QC~|jz4GJk(2fe!K=cEjJ8i@H___7gOh_?%&1p>rY9Ug4%HX__Aoer)&Dwn99gYAKCOB_F!Y*y~&RfbHFYC6zaPPym2e9wH`vi1i-%e>0ClMZ4+n+ zur6W=FOcE5shiqigWztxWmt^11({v7eEp)w&)U`Mqqro)Z(MH8%~vsoY1BO6P2>k2 z&|7e!h`QGi{~>nv&)vCt#~aIj%c#Q0{X$Ky@MMR;#mfT&tZ2H5;f)3?8p@OXI zmV=A5uf5ou`d19G*yc3v!4P+CcbYI-B`)R|h#*VM!8C)P_Jqh+g?;Cp0CS$i^>v!N zW{0Xm+4b&lNtpIL#<7UaF?R5HDIX~G~5dhRRUMtv>XRiU5@{_;j999I)U`<(tmLH;*3-amG(G zWhIQ)c)spt`APqL3xfdNuiS>4bWBGxUYAso-FMqSJ>r-c|KqMAx#~PErXD;)cY5;> zztGf}O}j1AH5S&&d1suXJBhBAy*oLO9={w}j@4;vp1-To{8Hjp`1z&Jckr9#1@l?D zqeJ++u%g+4vDp%7Ybkt{&8Yy>Q+oym`hPwWQ1cDE7Mfix-uwG)kV^W99NTs zsME|Dku4!bwC2rwQFdiz~V)JqGXA-%m*m)q&E|F#?*mN7@* zbr&VqcRFY#OMyPf-C_NQ)SjnWos0y}crY0xxnL#dfa;5<$_1K5v?mvQwpcFx>B>cp zX)aw`u2LHA9T!wRzZ{7+6y?4CA~?jWvozMKuH;%3-sz>noqc|7N1w5Kx`)$W<0-h9 zPw3LMLxqKAtptIze~MX_F7VT*^UCIV#1vb(@pDQ`CjGwcrrx=pC;IT$U9LBJoh7+@a)(JwgthMz7USX=sfanWu}xAIXe!_ zd$E6Crq;VnWR@loTH2WEW|!~3JL9F3EdMaMvx$jQ)lpe7cTw7)bNWz5Yb}S(?}a%y zE;edVS{>9ejqtre`o8g;Y0JJ>cX82h(T81JSU$udJ_j;E+n9uxR>9|8&01#V^RlnBaMb{apc{1ujj%Wi8_*!~G9-#JFcP^|vGIggIty zxn-mBMNJn$L#wNHGW68Ekj}>t>?j-vvQ=-Sr}wvhg)t_8+M$!yS^5<>w?DjEL~NyH zbr{Ds2r+R;m9;0TyBGYGK?9bzPibQbYdP@r-8=Tahc2cG?7bT? z=<^TZeRQH4ARK6k+aRv3s% zXiF(I+h4p_e62-jJ+j(E+l%gF>tAu!h?jP=711AXnO_Nwb&%s9c2GLl@3cYMzaPCU zs}TOr6h$>=0FoMJjHI;Pf9H@*qEuOO7<1Bl#&DsKd^=bp9}LZBqi`%*`` zDOc;b>eo*@_I8O)*~WWimvd1fg&a8(gpJy}!u*_xy>#@GaHF$Kw~Ubr3a8=a&p}Ze z3VWhLuE=n;rEmGAT7cASee<5#*Lg=jIbcuyi3J*&%!$qzSACw)=;R{?<0Tv`ueZ5v zW}6=t%6cQFewth&NXYbnucWZ?^7DOYGWecgU_d*elc7MY?2wduOj_AUoSzx<+vl%Z zqZmi8jb+$9#HkJgfsrhOW_r=0%cx3yKV3{!V2;?D`0UIc+jFfxlY&ZZ_;E?ZVo{4~ zD)sshYWXWcp$;O40EV;wi@nYHH|*U@CmZz|dp!lOqbwurg&Y*>PGL1hzocf3D~aH; zI1{#H|0l?-mH#C4^?YTrxTuYv^PlZUvtxdHlJS%^2v8Gw3)y?m+1qsX_&ukq2uth~ z#6U=(dnuyiDq(0K?%A^7wE8h-m1M16PQjKQg4HKtbGhKNcn9ApK72xN79HVqd@>eRjM{p_TB?=nA5W<|wDwIl&o9c5@@s-Mq$8Fezl zq{OcDnyXjJ_(rOqJoxDxTYI{Nc+Uh~mvO&9@LRhj>*6A$mkD>{1Ib(IVS57c(bgat z?zr747Isy{PC=xU@5Gi=$tuf(ofB+pEI+P2X9w%v&mu$S@Cvz##qG4V%F2x4mN104AH`3%{XldC=IQbdx@IsN+_N-GQN`n8eNRs4v(_+=<$)6v<~X?m)MPv}{L( z9bGe2I#W6}AcN@dh~DW)lKsdT3YJ~s;mo+PA1fct6S; zhnBxSag?=k8P=}_C>|gAW!W9~lQJ!nB%RccbeyPvBSfs{t508G9! zTcU1b;LJt?&k8lPP&al%diyVobK*L%3z`N)rK!C9P+}gj^Yi~!r>>wRMu6PI4dzr3 zqc5p1iBai9|NJ@@RG`tylyn`)K4;n#Ah=fC_ZR{xwB)6U{hh!}$O%sS7#Uj)lu{Q!6KTdZ^62S-cU zD@Gna3s9lq_E5AM9~_*h0vKmcueEOidSc)K?Ow+CetEFhG0Y`A#UPCAdd@|go4Z8!h6dyj(j{86@ zxOtIG;nx_;#-bd8J>e=E=%nZcwbZxX)qNAwJ0~8(tku3GMf5CXqnLrGGlbYs)fEqw+Ba(lJ%H$`+aovO0w=4dBE1&3+6zpd7c2rIss8@8)Bm8rLVw!fjoJcQ{KgHemq&7s zR@3033n8SGhMsjPDq)0@xLt~dyz(O5f7t)rD4@Br-p!677vD4%XZ#slQD04ND6BD| zlzmP0Gk6MV;2h?#KBM^`#;lCOqNJ_Tj0kTx-|9ad`G?XZxSJXV*g9d0W7@|OKGiBW zaK}zEGZ&zJs-|CFegD*ab=C}Ee;*4Lc^1o}(e}U3F&}Nh%3!>q@|X?COK-;N-^IUC zB`)LBRG@=!c9xI)IqZ+>xPlnsYF0&kA8>-k?6$XA{rko%TTh)J*ZoR-f%*=DPTKHI z0hw#y9ZGXXCxeY?ebQ&T!tDdNElaG%hxhC`Fk1bGB6Bm&2l!(-z8l9TN8UVuy%d@e zc;U&(SCk`H9aG=<4rlx`P~J2{SmY>oj!GsoxfqdfY-%pwNmz6#Jr%+FTxBOV4FAwtaf7n~sYp>LY>th6s zlrK?UPdCF9$rLsQ@rm?fZ#dxVa_Y7h+zT}~+bl#6CVh=9rN}RwS}iGIK-JskyL#&I z%6SxexodaK=eu=s@_U+kuOWm={~36fn5RnXxbr?|8Q=hIP#I?$v&RNkW$;6J39pW{ItDr3cFyI2a;nHf9`283t5Ml^gOKSBO!K|Qt*UsNIBosql z3RQ*O0k}~_Yu(x_B71J@H-7Qo$r}J2H(K=CU;7B+WzT@#lA~4G#h1VSO0cjX+eHHn z8Ycvc3Ga2jh`7Jt=Nos1i;k6EzfLzJ_@X)cU@}#)VSb)@vO4otk!VQ?Xb>;WysS8$ zUkaLx+VbQ>HT;uUn-U}+E#ivUa>Z(T179*3ORVrK)%k|~Yg3>q%ewAD80ewa#C!wo zCE~XWT?~;w%-nrYtp?+lW+#+E__yyQ z@RADMwr|BrC89c}gfJQgzCR}t^2^tDBMo0X)3jRC)(j3yRzG zF=9v^O?PcFjpH~u>$QbS$3fg=OpC_m97S1ZeJcNN2X}0Cf>2?bTQJ}x%Kwe-vFeqU z$I#A-UUk@O+n=ogBb^cl#?slFTue2SgyU~p>$dfpldub)wq$KH@=?CW3aSZFJ?R^= zd|$mO`L<&=+AVRGpz`<-T0|zY!CvG#9xV(R$m<(OLppfC2}#meZ$VyfDZy1cCCWZL zBvr;yuJDPLjV2ALJzw*?kqkm`%++WtX?QEC9o)hei=i@SirWbU+Y-d`1dd4#TZ~YYwQwv>Erwkl(S|^ns)O_cTZMdEH^KNE-$MZ&M z24uc`^;xT$Ey8?X9`=GfHkCGmT9XG%Fs<49NbZf=Qff`y+p?GzvQqb<>>T#VncLYY1 z?iRZ@osRt?yL9hQsN3s1=L_3@7?xJPb{zV6*39yU$*>}8>&I-T);q%=zwM#1`PDq@ z?VQ>5pRD02g%Wx(@ua=yePw(q1=aaq^B;5)B|6XjD978~V_JCJbI@xXNmO-@m?Ri) z$;TAa4rk;Gu*#0>OS^sC+&Q(TT(Ec-Re9SjX>jrFQD-+5mCW#BEj$#>1{tH)95sGO z-h)Yzi)emSwTM99d(W16_~~6C;=Yd z>GWT7eRKnAcEHnD+u$^2342qM-_cedwyHB|zPwlWZ|=FLl7S$ceifuQK0^Hyt8AX@f`SYFQcGFw^nAJELE;l`&~KO z$}bIHfjw2NLN12f9>c5*bbdlHT7J%|5_%C|=}-;gJ$DXPtycGKWqa1DZKu4A?tQ;1 zjX68?+dVL?gM5+=bdg>jn(1G?K58QZ^ZS7NcXQmE(3zizY4F?EoARVWYvOAR`>jkyr^WYxCzrtLqH}5Oz3`Kpt(h!6nI$sX9s&1Br z5?y27X(mR0P$iy~7bEUwY^dyUD_;A5T)l-~l;86{yefjUN=l0oiZs$83Me7X(k0!} z9g@-rA|)YROLr}efD#KV9n!FLE$p)J+`RSkeO|BMAFyZ7ea@VjYi6#QVGp&IT-tEg zwDJxA11lCjD@K2=BnGB>v4`ml5m0_)2_)WTTMlZfgt9~foh%61 zNaU)KkU4HkzMC}rA`x0TNwJvK(49gMqhuk<_##j^D}cFthDxMYS3hCl=x@_j5U4?P zzFx7bNm9octn)tQYI$J^@imuUB{6)Sp28ykv7dzo+|Qrib}Z$td;X(K2?5&@T!J)N zWtNyHiY9_+$rvh0T4k;Yu)JQ-!sxvF^xxSQAP`p`ge&R#v_4$dI1~+^M>V=YxY)`R ze70AN1M(m1@4H_=yOMMB_S7hAV*Jo|wyQQBG8X zh(bb~gW~pPpkD_1bp9-(7y2b4>f`j^71X41ynB_4EP&pNb62ds)NsXeef3E}&ogAS zVd7f&Uor@Uos($C)~7T$5Iz>KK81HoFF_IPHrX8mv0e0fEO_j*b={X46vwf`p-m=m zo}w8c0DbD0R+sb>T9G~U%>C=l!}{4xb|{%Xx%Ez>;cpxp^sWGnuC6-p_y5vBmR|?8 z-9tCO2ezsEzUY^qf{$S?GE73&kZsPVUwzF%g8b4*)63sSsgs_7G+>OYRGFO>I9P^a zHMM2MUgXMdM!~;x(m%OE{sAYGkQMD+QWyDog$YVp!X=K&POhEr zb!gWzCdU5$44r!*ffx{LXRKG*I|EwezmiO@X(d2walZIx89?5ArMg#1i*g&Q-=At& zy);8bdgnFOGAY`kE_fYQ4cIA7_vW+>Nikg%hVJ*zz#;?_ zNS2!@^4Bm72lztqLKaPQp&?fn(udv|AZZftxX@Zu&5ZyRQmK!5me{~_^XvKk>ZZ7t zb|H-i{(g_=)htZ1wY%8(T1ys{{t)S6|VmN zVDhVdPJY{vEzgV-;S$x94(9tWhcXJ^x%VA z(qwheQgEK_%{EJJ?9dkbi_e;{XuiJ!8PGBYP6iYmFpCX6vWV22?EF|dQyKz6Guq$( zE@b>NosDF+JRa_kZfOwit+SSXKB@Q2?>?i~@r#qUhg;&YW^a^nR+H;mTnHCD;N%ql zq9g5_mRj|foY2If{ziQNKREuA`T*CaDG>_(E!4z0-}AgljtjYgY~{*LyIM9VvbPI= zzn7@C%*UMPe+D=&%6RrUkN;bFsyk8h|23TfqloXKPX@11x`$xlKi6e?RreQhUyE!k z|7sCYNgU`70sGmnyw=iO6k`Jm4ux1Z)n=S5n*5NEV-zgwB2Q*|4eVGePl!w;e=*`!QxU+IDaGL;`V{*< z_hFFJyR6ZXXt8g1C28Z-dhIy>P00j-oZjjhm$e+$0jdZyvS=gdZsp-#6mF*(GT{nz zvm8j|T^5Nsx&C$ec%TQel>v-QtG~G%9y{-8-Tdso6JkL>nG8+;3Xo1b44lk+eJ)hA zJHruv_g1?1doF0h9GSnFMu6(*S<*zr*Z+1fk&-gS{ckcb2y|5bPtQDFkP{e13Xy17 z0qLJ;F_8qHG(lcMN9Gckzk_7=F%~Ozfz&Q1?sfo8ah=Ye{3=KAHR6BJ=cfelDo(0b zs?G|KPm5-1XY)?4eHR+Y%-2kGyOBYe7l!z^zkX56{!e`ny{}m=*{az!gO2^r-1TG` z&mTcA!NM#XPoLR^6rtf;SFUM})+EaYLhM)QNB})yu`=2DKcYdH0dwtF<78(C7Z^*7 z|Gvop#_jK-B;ZLV;Frep;}qiTr}NeHnAnL3^{aKcB0qEfIcSOho-gj;c0fE{$+jGT zJAS6z;EvhBTI4n3KhzOX9y%)pL-O+42C}hrW@s|0ZsLK&;~b)I)TuNM4USdSd$BAM zy55s+6+wSxXk@10RWPLTKJ4`|ShEK*AwZwI%UMEpIJx|$RWv6X*qWU4b2ozj!!Ac! zLVh}6#qUJ7ajM1Ee1;PYnxC`+%7MMZCz}L|+TY9YJHz+mAn0+k&23VhMSKI|!@f!Y z*!MAKX5QI03*dPRDmON3##b&k~`H z&+qZ0)W?4CDFh-uW;O-ZL!SZ*<<405#QgYIu?kXFoWXNGJT>g!o@=JQa);#V>f45C zI1f0|q}cLz@_$mry%L?j-^b=g{fc4Pop8N_vkv-#Cs3H-Z80xzr3q@+?4OxaR@9Lm z7e9+}Q5@1gqL+ey)9fx%?}q3l&y>Sig0%hKwzRQK%;c&Ur14;ST6rpWpWnjc6fEm` z>cQcGmIoGOd44MVzoP;L3$qOWgbl~|kKm0VPWeg_!Wq7g87TroSONn&5&HLdo|BLm zyMCE1?Efbvw@Cq`+Z*Fpi!u8I%w-o+NlA^M%>j(jp!)c~9j;`#`#mN=pzsI(v^i73 ztNxdIapLQyj@u;*OECwwN5nh#|C-miXjjY)eI)zCS%O%qtMy`&Q5kEcy z51wYE4W7vNbE@T?zkeM`7wtJiO zi!55cp#ATQ<+AcFLjB*9?}cyEU(2I5D7p_XiLc6Z(n$NVQVW6JCVXc*d{p?W1J*uh zdG^o;1<7A10F`xz1lx|&)j@by;2(lAQt-?u#ms(xL5ry^9crb%(qOu`tv6{~40YRe zOKCiHuIZHeao(Dt0&GD1nY0w}U|;1uGE|w&`JecJMtz&TV1KV&R&@qX4G9^;AOc<= zU=EUFR}>zO-=ch#XF%cZ#OOw2$NA}K8fM*3oZ%@$NOSgzvjxz4G+=&`0EnSxZ`rnRQ5V zz>!SHcGET2`M08!{||O~2@yJ<_iZE4Ht)Au`fu43R?`=wiMP8Q11riHr2!Kbr8QyX z-{hBOEu5ubf4*a}wziR(q~vqCLVpP?R(@Tc)CD5`PoXg2md_{lO!~i6X8W}b2UEf| zbPn&{ZT}g(%Q?B+HxV&;1=w%O%3?|Bc`5+FXm4Lb9p@hzVuUXWyn27``%KvWqzz5T=CbW$X#v|Y09T@bDlu-P4mjRN}XgDDZuezz0EYvj-eEFR@uBgqTL1{jh6tJmWjDV1x zl9S(k#clNpxyw*k%~bkpw(`wi!vY%tfRj5gX21{;a^o5S_xNG8W#YV8c;2g+_2wSA z<}-%?#m}0{4*BMD-OtjKf3Qf`EyUisjN5iY8{V!FRUkbw2Trec3nozA7HsQLX8>VtF317w`v&<9*?f|P80^XrK zE4ULOJF7<5a_zTrc#Mx9-@Otm{#@65dGX%|EL)-n6ITjwX6iX?LoQ-7699;U%cb6= zlx|U>G`|{5dJ8y$+xB99d9wbE?4XE^ksxAbDu2Xe8#A%QS@NL=WL%`-+V8LOs*pxP zbbT;d%i!dhD<=RfnJ)?xq}Q8QDCyTy?rH=0;z6O}`<|Gsv9pJ)G;T)&Ct4_}?AFL^4a!v4FSCS78Dy8r?7MnvkH1h2`2F zmlEs}f!PXJ9&O!HXr;t*rW%o^yV`SKBlf?{8AaM#)fWC+3l0b!)y-9_=^9lz(1!K^ zCpDil)bCFqql`n4q6zDZ;|<95yB)?KgAAD#^_NZ^Cf$q!ss5VsZacUf~A&h zzt;RQcEDHu6*{>*GjJ)0Kml2FOn6qr_9~GDI5X1;;2}|#12Cv3-qfM#$*?$eT}#XO zXy&zOOUg)bllOkx-#)IOstUKg)`}+kxC%u!gmrTrejL+c7A8+Y@!bL-0dLmf)RiV) zgLb!+X((RvR<~}|q}uxq0^?dfZpI~}26pTJHM{}WkgYExpz(V})$!^k`-(;T8DtD> zS2y~;K=n%t02o5wEt2X5VJ+%v1DkT}v#Wm;D|R`qmIm1P8bC!WSeCpWb4&Xx*g+%3 zd4J`itj#-2!S~Nth^55m+uKN!FhLC+!`oT~A1Wl$>zkM}`el+qPF*!s?@P7}Jht+t z9GOiRvHtdzG@^7_Z0ebeWwH+us@yFGVApIZu2I4wqGw-iLy%F37y-PH$HfXg4%yqT zKoC4)ov15oFIr%ck1ENuyeSQL`@hY!$DL5j+}YO^08m1(YsDZkCF)=1ac$n*{_o3`jZQp~cJhQh z7th6l7(h)kCcu+0Yi7Xt0z=)QSHB%PF&hd@HvXPDe}73Zn1zO0nI-ILYtGi{gV+=R zHU0go=*@w4rzi8t?V;0SK&&wc3AA>OV?LSFmy3|QD`!ddb1n)07Dxl^*=0GD5a{qh zx`7m$6ln6BY%dfK5ESv4>FD!&r7nKs1O;br!sE>&w<&` zcUd6*YuzB9BPK)auQlX)4#+Klq=-r3FOm8zuc-Wnv(7`Zhyb%3NjtXx6wPplO9wa$ zs)pa39Pd=~C29YKRE@@gV1N%s^Tri;=)1VOGr{AGX#03AY;@m`v+cCFzfL^|aI6Tz z`$H4|??mzO``-wkhVfc-wr(rj80o*df|6;z#Qwt2k1ajHIlQeLW{qt;ztL^iOCbWH zH?B$_m%4=iUF=i-X`+{yo8FB_(Nk$=4g}Naug>2-`f8XudQB)h-@rJtQ$Re4&ds*Z1dqA8Vq z2>TP9QWS~5ry-NynywilPZnLu>wH(qfeJYAN&ZMrt z{;P&BvW?UCw3AGUn^;Tnk(LA~LSBcVm#}u_H;v_Ue%|LV2{y3_9>j_wzx!-d_Wk`2(lG#v z!!iwtx&+3=Ht!+0?h_)4({NlBYd_Rv&R5)Mi6yEXrHu#UKe}P+-do6pBjW4(3q<;t z&Gb-Iam&NGn6^`JvGvQTAH!clE0J@)?!`v-IsSj8ic}W>N0HZ;CHQvi)aG{VITeb? zW(4O8{QG^nx+L{fB%UGHV*YMWFh&Jn%)=Y8uz7yUpa zXDeU4T(fBX8Vxp~Qmxb80+6wIsa2y#avr_l#*Uv14H*FG^hq3Xsr?=+0=u7|=ce8C}4vNku z5PE-l^Q{ODfJmKOOcZS9emk99C`IIjSLlV;~YV@0T^3gQ=4bwg9Cd6&y z9Bf7Lad}^kz6~QE`D;0jjwZdT&Qay2u6x71i*K~TwA$#Ob{y_<<^iuJioSR&;LB&7 z59ZTEV|+AY2OkF&j<&ggsM3v2ddf!i%SuNc}s5g^Cr=~guh5G0sz-T z{X#2;!LCzLDw9n#dunf$aZF29%X@B86IAC%1i06SN(zs36&;5 zJe@fp?l8dwSV)_8p~{isgFzsP?4$qZC;wBDSDH-}XS5 z6Xo1I>Z|4jU8kUcaA1RuaefugbfET*b zlb*~)wNXBbdbnopbqH0lkt6gxIs4^2tY653f4lU}A`0GatU3-K1#1;ZepQ@GR==9} zp46wuW#rswzrx6@@ZC={RFE(>eUdxY_vhV#=$3Qs^iw!tD7zRCF!`B5C*eNlmZk@_ zP&%j5m$+~jQVCh3rs&d}W!JMCLEoR}^tIcpw3&IWX?SN8Jvqyw=yPD9mleB<>T}_5 zuuDm~SlXW)JK*(F8twb|XW68rk2uz^yR4#fg* zmx+XjLYK+)vZH_F@RDUmg7`OQidb(tO>}k)(I_{)*jwg4?*;Kej#f_86;--_k8g}V zN_ZVZuH8H*)WO2xH~;RWjgtNLO6vnwicaC&Y`{BFLhIU#D|QJ7Z8sY`&c$9sI877` z4^HRPG7Fh^zu-#&k#N{tt@9Z7%$d_xx<5tMubRMZoMBNC5k<~Y`_^Mc?jK~8=L#mPKg-KPG z_?Whf^`HAItfj+Mk*B=xGg)+Z3vxhjboF9aO#N$; zC5N?7#Cq3PPzVy1)x=2y{6&c`dM69HeV2sabjl za7YHt?0(+T@x^+TOv%ZMEi%7#wMZr2>hIkHD(>Tc^s|+JMfF{~jd8cGnOS8Dv%gB& zGVQ3$yzI8z8M@v$4u9Uw_mr}xQ;~Doc1Jtusg?*0mX4!_>mqR=)SEC+qIQ4KQ1KLv z2suJAeUYll?^q}YT!vSrYmw(I;K`~CdM ze&z;>>hrd85(TF(vxYU{<+sx3B#w5f-w^YJzNa7a4(uC)e+U({A{Pn9ck?^ABfBzG z?ms`^tvxebQ%)~xNy=b$(I!zEBBLT$fb0VQOqQxSUp*L8BHndY*w1N`m}w|S36DDe zW|VW5U<)YoPRN90DpZIlNhrKxQ&vu zJnGHssY`CB`6l4u%%q`d=i6WBw+t^kH?zG)BBdc^V+Rb+s42E&nF*JRx8s9Tb^6aH zzCzJ}e@3OK%9O{Z4t3mAUWW5%ht{pg(GT+_wCDGIxgsFs4h0%ZlCW`N{TMXv`c^4R z$oswF`=&UZ=UF3+W?w~PxsYCy@O474BtNrwdCQ(~V=llSaxf=W0LwGM=?@ zNj<7aCtXUQP*v!_ixO`Eo=p6UE$<&3IwST}o`MFaS`+Ot&rP$m?jZ)Ajb+&vKeNxN zynxPceTII`1Q%V*z9eS-BG*a|fKxMn;V7K3$R$aZI+xd~nksM6WXZ5hcT}Sb zw#+BDPXP~*6TSFeCs@YCNg~=Zo&~qHyh-)4ZK;yZ^crU#`b(+-iuG9Eels{(F@wl^ zS-a%9%j>-_)~MTfw;!}XA$Ill5v-^}_+;6{ra4dVi!`L|`kBY|@Db+OR%2n2 zWk(c;-yn}AO*hJf12I|s+gdsSyyKbE_X&cu(|_?L@pJ9K z`)|wEK4ts-l3~`ew!z>dJ;Z;wwz1t@ z%-6?Ip;3!Hdjm_?{D{OOl}rDGoMpGRdrj(-2i-6(JThjYVxD6I=hfr;@W;5&{hk=d z;tOGZz}F*ayg>mzLBaH_cgD^btprFX>*RxiUA=yMTYs(ZUuHF^nEtWRg+8|eGgaTl zln*Nlm}q~}k7Y*+%d;akZE{L+C4E5$%xc;##>D6l>oi1)6 z?Gf9mUenH85;p~I&+Y4`t+yayHD~HS?KC&ISiIJ?jeK5ve3j9VaaH!69@O)Nue78l zmFF}>3BNbaf@^V4FrEcKU!im1;ZxiTR1i*Xx=wItC|lH+;#0zh@U7rZbM|NNpH9D( z=fs;-YO?%jF6>y0L~QCh^k?n0HYf!bvF6G*BNgH?#jrVvT!9_g-%n3mYJc*gI!{=Kx1t1jIEFCs( zbIduX$2@{1b$|~sT&Jkm7DnPSJsX!r(9o1 z^n5#|rHt@uk%7RA%I+Kizz_%|^sbcX>cZwMEaIDqVxW( zG;ME4s7wBY7XQo$!9#c+rcu~9E|)B}jvIz=pUx-G^SFG%#p-qSQ#Qv_&*}%TqC03L zb@bTEDsfF4%_A{#S5@Bqgo}J*eRWCon(!RUc>Y+)SL4E!g%d)k0-ldKc|4NNNd~D@2&kBmwLj=#74P`;xZz zSFEA;Z^7=W+Qw$Eh1lhkN$<+ol^$Vj4B%uQp68Nq%kB-zJlqXJw(e`svh5vW8ROb< zzI~E9{sLw?7@~oq#)*_BWZ};?)~5p(C)vHWr|A^ND6kzN7&wjf$KjB7XpWv|=tKIw zXmCYE2?1a;Hf?^cJ6hN{CV`9BS_e+PQ9F=QFN_3?bux%;tmEZi!v`ssvA)9VXddG?T#jnq(rax7$QT~dxpx9t18k|j>a$7f!Gm0whp3X`6l z>y`g94p}JR5w-B5m(kWJjx~8y{7&GgMm}~v_NNUn*WZ zJ!*R7dli2N9UG~lsY3iZl&V1DSZ@k2Q z&?>?xlj1mDYvHUeh5+EuQENj%{f5=iZ3o90>)O)wPqrbA3jcux%v3kJJ<;nDcIy_}_j zJuXXO6>aj4qLK_gt+Sf9G2p3R91v|kTOox>%ji!NGGt8d5#5LH5<;`P zMJ4Pq(v6Ax!olh%J^h~qU!U&E(O zYw`VcQ`MtW=WnJe6M|tb52%4do`rs}Qd$#n($Xl1jgDTFr|51qYPj1WbK*e@_pV6A zH;_lQY}es>vDaMXM{=G*Thlwhcam~8l0Bz5DcjeqZb%Z>o+djqpt=}rY!Y~ z@MkkTw!KrJeNP?t_1(^fyjOk;m??J&8ss4O=9wRh62DVUFP^kRiEMMnO?bOcZ7~UQ zHl3EZuWz4&4vaA&bv3b==9}oX%nBPMpAX=g`3#E$K0G2kD|9{@y9BayKR=6bKM=`R zLdZvP&-3m9!GND0PD;9v&DFOvc(oJ+LBe^voMWMHy}n$W2I1i7q?A(>Eqd;7%d*MN z%2OL_tB1#Rr#}iKs<6SB%Ei0odD+f6twbAVxj7FZyS<+@7&Pbu-OBA z_LTSJ(z}gSwqzou*4Y&g89kz6u}MCov{>w@Da00pC6kaQ#rI$|NL161Q@pygoqcA- zlnzSOtBpIV7?)5X8#y9rIOw&5czX3)U|#AplZi^19&jx$PQyuzv&dZeJ{u6LtR;yr zc!_R1XZ6XST$vov5wjeQ@J8ipDONbg4?O)EU)4Usc}J|ion?H>W+l@h>R z_|}_|F0;Y{uQ{@_7cB(p z{AeqrJ{F&A2z&aw?wz(8<8;MWX?j0x?jJ@2xfbg9x=~p8W5V)yMIDFk6Gu31k*^^t zKKBO+yO%_Qx~3)BqCnsVS&-0KLMDNo|6?(_+5t6|3K(4)ii!pv?D3GFIf_wOB^S+P z#{H=bY6!lC!`=%eN-`C5afSIZ6>mc(0R zIkJdBD~UhThPm0H=&VI7V|9Z3%%mXbGvA9r@bjavixl#3@mZHjSQhf}+~RrNY@qT^ z?fcmGv`Ew-rv-}6?6_JuJ9EOzXFlOjT%Q<6axm+0N*lKAj#}ENA#@r{u4ST80zb6Rioe^AUx0R{c6Pa5 z(^NUJq>R*2U=ahkUO;ycQ~4_Q(Ye0DRw&-O^fL@_M0SI`%eU}WYtT=U0drX`{D#G^ zrfNt^J;cJssprHm*D5?G8#n&xlMEzt>SX#Gv*ozI zd@QB`q)qYK^w9@|_u|m7|H6!gt5obWLa&obuhGt{!6XuK@jKYHD5{FXw#BpfS%fb^Xe+0YMClKz>iKB*d|F!p?;GiE`7KNKd%*KKBbm@ho0IPQd<>flWd|yE~mJ3y=<7y$&s4*B?v2~3Ke08{ zB5{5oR(8_x+v#=VCZEq_g=opfn^^C(NJY3voKwe;43XHm5%aA9lr*U8yk#u&$FR-$ zg`AeJb{$1#^5ihGVrMmpvhk2jU+o0x-K3krqsdZU(3&+H!C!$P0CK=qd3bDtW zze_H7cRoMGpnI4JeNKIBk|EMJ-#;Ajf;l0Cv9*!|#&>&)f9$Rc2nfWHG$=&)>R>Ak4goBAo{831yf?kOEwWUF_N_ zpp}itVrmcDZ8JAi(cTmzx`p5_k%bBh7YRh+x}>vuwL3*>rk~U{X6w#gnLSXC`tU(f znq| za+hB5cEATM)O7eqVqp^d9A-5`)-#&>;=cr@y@!|z?+gs)ntsb7Iu9^Vr+;L0Ta%N{ zl`}zdX0^qbQk1|ulXO;rvtp5w;qz!82GIVNS^cWMZJ9p{*{OCu>ns!6yk<(3dbBRJ zQh|Is-p@0e=!#shD`5XNkiEOe%CgSrSqOY1VN}?~Roa9NnkW)YWahYo*qGCN>$CHA z!u4$^P5g$2`s1r#_vm6@=orXETFE@XV)GR}<>iayuSa#7)a;C5W10wo+_v0=NPvtcDTtQ(@L1Rh-UCr8u@4%)7mk zQ8Qt7Qhjghh&}Ze%^6npRZAEYt^X+05}IyI?PA=y=F_99^+oz+y5d5N*9Q)sf#Tny zqZ_Ls4{GjAOs4Hlx-G}wxH0#a+KE#yLO#V}^N1WJtj5+hCqcX;(#oJCU zk46M=N?5DOx)%~86CuxZ_vLS}9JX;us?yfNQjXx_%uk$+`fo#bfjoUgmyNsGg`vNV zXdA#cx*-X2lZsX3+1fUT7>)ONj`RmvehBAxxyT3PBK30Y{$s>8NQ|gfW2$g!j${j4eqW`I zE#gS)rO2M~d|@WQa<#+IRB=mMqo*d3!=fBA{fr9F9zx9NG^mvc#jv%fT!cLFwivZ( z44Wio7}D8KjwfUoO7^+=b$6JJpFAC3S?w!N-5qSr_-!qWp*?yClg_Rf>h+uo;r}Io z7w};--7qeZq#(La;B4_g4c8^0r1YRYs5xbX96Jwi2~YmEKQw0UrD}u zE!w`foS7;abd&y42m7t|a@1>u3ciK;{l?=YU=44uh9tKx7Sj^y@`Xi4T}8+`=TfhF z{xw(ZWBsQI7543NQo7Kv3>@M#I$r+UodOF!YU>mU(8ZbJ{OU)ar};POwy1^fV-0{J zasYBEOw1MTaXEgCwsK5+DcKJYw7(|VsH)UAJqL+DZz`WCWsrL8nza-Q(oL--a8hq3?}wo-YPH~KN0M= zR$>w($C)ng;ZNrqlGm6Q`^NI+xX$ZJ)yqc=h>Y_n)}*o$C*;+g#YW`LclEDVmhZDm zTOvyFAIoTH^Wz!66YCs)Id=S>B*$7lJ$RSvJcB`jKGz9MftfBW#-~6NHrD=tWZ90a zEc7mTSbv>=q_F9!r4su9v{gzYK?|M)fcZ)X?=bVZf}1UKbt|h>xn14 z)t9uZo?+hacq`Rqq^mL5v;;UxP` z%~-E0H~m}}BzBIPl$UD5jx718e0dq%^Q_sxSfWjT9c4;bVDUP*x7 z81Av53l*R~H?_Qo1i2^dfZ>?HLx*{>&jVdwEJwv6dQlm-Ex|;fy}O@t^VV0pP}T zdD-V1chr0Q)|#0r4+6O&?{G^mDcWOoA#N=}ZTqu$Pcl8v zw4cT2kdxPJT8t8U@7U9Vj0A5OXg~@$r*cS2Bfsq+<$w*ZTj1WdQy}0P1;{D`oPt~7 z(i5&-8S0p;1SPo#n57g8)8rG+Y2+Fwg%`}}`xE$>~_dP*9U)p^oi1tEjN4ca!b*4+)Jt06y@${g&wq zWxyJu3Z|&?KKgL_Me(AN0Y1&ofP{p2?W`yl*cx>hQOKu}irXTPLJ`4k%rn~&F@Vk3 zL3!5&)$-M~vwY`>3YZM9^!+~dk#LGV+h>~GyIGKlW9jmN(cwf*CoPp!aE9UJHleQM zJgBb?f(bs-sZ5sAMix`MCN})GZepw^!$vfoXQeaR)|!a}T)2K1yTJTYt2`kC`*)Qa z7P*C)dHh2U!Y1g*Uh#he%BYqhF44VJhWfWsNGF7NoN{qrVMpm0mO*d>Iv~V5p`#Dg zbQhwmq4l{yAo~R3Ap0$wJV`|2`r^Pd>$h3uG+tzt5yE}YM!BGzNtYdz(6peMEU|s& z#Q)V%;&+Rt*EDL5Zgr~u(9_^V4)#tP8BcqPj)#cdA3V6SW+R}hc?gI5Rp9XG)fC|G z!0Kj*OQx|)vx#&CbOc#`nozrv@Xv4?Iy~OQ;u5}zZ(Xk~M)g%2(pD`+NM->wl?GO? za!Jh4Z6|reGat+!%xvA=861`{{2bj`yJkj?-u`_zwpOujbEWiFdR;?qU>VI3P0fs# z*v5qxZO=m5K=1axz>A&Tc$~U3g~5at9M>Ej1|yr-D1h_zm8XL2!)kb2K@7^bzn7al zW9-`!W&%w4J%1Td5mL81JUI_RnxsL;GI zuDvqoi60E2LGUD@&6tg*F}2&ESC2M(jJ3>w$}N?=bVa8YJ1ZV#&UQNglL!60kjv_c zBUO5V`RYG6nP2+h;k)(wSpFQd!E{IZDi&;tusbwe(io?WLn8s03Syvp+vo33}q?*$(My=6)Zt&E@+jvaM8@gk<@q>&5_{rn;rbTr~i#VN)Fv%t@*hI8srBxP?{3$ z1)Q0z+{8K*tQURYk0k;9iLObp1sW{Is+9c*Sk@Ifq*ujEkvmc!LfBoQO|=rOEUm{b zRIj}>F#h({&oC1&A9UU^V!dpW>}LldINVhr6m#X!%c|sv&I%wxe&dCm-ocT3*&owk z^-9;=4C)_LF|l53E2*y?Rh(}9U`qIGknfRho%1IZ2?74s#QN`ET2gn3Ryjt6MD7Om zxs7aSvXP$Frtz0TSI%Z3ZRY<$Y_?s$6#lbPF(A$6L2Xe3#Ts}#Q*IB$K)cA3904V0 zrG2?!7(Tg&=QNO&t@ym`XKK`V$a-4LlN;`B6kF?*V$*1A=!Yf>J-V~f8-@=_n2VP` z?$-VOQ##jDg`wc+;_Ry0!7*IDvw4~_6|4vvG(8!3JZW=^-c{M|$qDPMP$~qSP)Bw7 zIRtZ5gBpilT(`QeB(oO7LiRpX5N<3d)b}UkjP$oQ1MVFDRChb$?7_A5C zA7zs#gFsO^EN#fv?u2_y*=MKMr$;}}o{VIcBnIG+)Rn++OIe(znn>CYrnFA=dn+>K zYL3!sKkg(Q3jUd@@9Q=7ohC1uDt`T5_W@er{&*f?-swdva6sLm-g|Aju&PSU7l}r0 z_W>IgZwhVNhJPD(v!h@jM83JsnIxK5dpowZ-Q$tsb`C|i z(igDPDM!$!Q6U=LAZ4&Rbr)72F26~hb;4P3%BVE671Bj*<~A^lX~u%+3M01|1~Bx# z<-RN?zcK@AD!!`iUj~+b7qsK6gIUX&3@b_wo!o>h^&i!4%lH?ubG0&Xp8d~vVHe$0Twl=oi30vYpNz& z(ZOm)a~s_bXsDOU^$|b6j{nU2wIP;XMG?hVm=iYFpm41>Yl0_hFNNXKzJ2lc8v3To1xS=4@$sK(uL-bF8` zWB4e`cMXVK{3Oi8l;-|`iu7q;9ef9^t=BfgF4CtFb9UpoSI>qZali6^3#5DLfA5#Q z1v1jxdOi&ZYxzg^1($~g{tjokcPhTz)j`^QmMc0+tLFML;22m6aG}0b_0KNHP#AbU zJIyA8{FK*8bYFsAyUWV^yX)Rd0=0jyYag%s#$0nZU$#Vn;h}EHqq_FX!IpPWpq4m! z1ouTN<>W+m(`0HH42~NX&0NO^8jCbd7aa4Q>ujBK;{Q|%apXHe0i_N_I;#Yc;(qmh zyEcuj2XGTcQT{*^pqm#59VbG%qmYimOX9?T<8TVpJIx}e^@&$Lk%8cAWh$Rt2=NYV z4l zjgApx_<4SD%#*#7uO7z=QMW++`I3=}td?jBOe+5`yf-N%ES>LRv2CaDpPXJNS5ipG zy^{-%i;Io5%`}HllKVLso1=XWn8Ppm4<9@9VJoZi7Y7e&X-MU%UrY<0l`mGm9gvFk zj`8(Ap_Ffq`-Gf~o;Ik+OJ^aP^Y<@a+|6j-i)YC|W&Gmoy|%BP^T^3{U7fb*;TOx~ zSXoXpX4AnT2L+9eKrn;uHw0gkJ{fi{O~voz42nL=6d#$Hf%n+$a5Ite0in@eBig=k zrEa!Vk#$qfwRPUnaS?|w^(5ORxg%_C@H%hhj_e&lk;Xd2_Xvf3KRWP3D2oRtN@Qs`6YO<4dyUP>gHW`iut1 z?l02bu_emX99=NY$8JBYdl8>Ce9J@XXT`15pGWnekzBieizU&2!*q?_a1-z9;$WyGW+`qh-x|g&Oc)ZUN zXu}Jlq>$Ay0(v6=wGo7!twOgr`cA!l55IjQeA~QS2ee1zGT>_$2675N>x0TYi}*(( zjpxI5(P6{|Gir}f?kC{&xII-Ml;Ui?awu{(mKjRs?U}L)Uwq?Fk7+G@2s|3&kZAJv zGpL3a!1mCAgJUZTGFqD7B3Q)AsSA!XjVm;2J^OZnLV*^pPT9`5Ztub>APp>k_ z#)6e)39^*D7ufG0_%0rZ8L;xqKsiYGY*cw$*EycI0V+MlQGW0vv`I!E1X`mA;qt`W zMg^{WH-Z`JqCJbI4KPnv2dQaept~H8LSJ`!A+`r4c^ZIOWL0= z+PA2{ynuiV6B~c$+DCe;q54}EXF-4BNhA%KJBg*1}u!dR$fsrc4Ll^Q_IkxS>Dx820DR!>+>h*QGbvDf) z>I;U#gf^C|<@haR2zo*`j}a8$6#o1-QU08|FR4qsYxTBp`oRcZ$qP2Dmqy+I&vO-U z5E1~|AS=4<(yZ~Q39;(jF^LYmwtHQo=W+>TF2q~rJr{ldKwVcGH#+-!N^iFmn&pBA z>_|OiZtYzQ`UuvOeM=&l7l6=Uef$&+)}%OVd*P=gIXigx!6uW%&Q)`jfoVn)|7;pB zh?C-yRCXrr`G=Cc&9$5GfNG|R1F28gMEx_0KmwCRGwMG)X#Lxint(vVfuiOTM1XuF z;ySDjdZH;Tvq-t8DImrK3OE{xxDEOG9Mxt()os<>WqI^s5KoeDo$u8c!}~Wc38&f) z0cNSffjdBDoft1MbnSeld$7A8g4ut5?TASw9)eLvUPWfLzoC2R!cQ! z^;5eWiwiBH}jFfL!T@qx;04oMP2b*{*tU`fw^{F#)`wUwya*1r5XkN zL#;2R2CA|Zw!8x~#tMEQPhkh>jIW9HO#%Cbc}woR{GDc<{~ujf84y+1tw#j}6%k2k zR6ryZq*J9E=^;hBB!-lbQW#1p>5=ZvkrD(16r>xJ9uSajxO)iS_kQ<&`-gwroH=`+ zy;nSIt!H^crer~(EKG+27lnqZUS@@UsQ~mQm3@Iq7BZA61_>3V%n+~VJ*}}e(D=eG zxK7PaIBV|a?e*@%u;i;wxLA!NiGp@DX<>>CI+AwZN?(o%}wsi4ls-UaIEN* z(46sPqHKi5r z4!ILSLgvpBOXsC*s~`4Q^t~l1b0m9Iapjjp39*D%YgVN2hqBY%46#KcyZsyucw#4A zdMvV2w#P`0hMFITH7W?wH6rFNy}2uhOCNe2wR_P^pexLJ=8IX1`#b={qWU;IuQRQB zef5V$A@y`-0$D_F&NUxhlCNQve@U}9wj)Py0kZpo354sO&qS-4eZbJ@`mjl2?`n`s zAc1TV9d>_~EYj?68kraTeYT|VXuBK7KEbP`%R`)j#8M@8ekvn8+4a?3mjhNx3#PE3 zkYHe8-?yxU4F2)=L&%$b(EBm~Xep*-Lej#b{MMIxL>-zj=J4qP+FrR!B#$?K+d{ovhXV- ziFI`K3WN*P9y5jW=i>n5v*%!c@x`y>gU4Q9o29fT2yAFSd%%V-h953K5Md5>kK`mt zFg1n)l|~*eNcVD*81Jp1riZw_A!6H3J%N=nOsoD<3`MXy-a{RSNA~z?Zx^PVCYlac z8@|s;9PEs_6zOD?FU#)lptj$%G)LDGmXphsG-xs0b`Tb#M?L7UtjR#V_+4>zP`tDM z`E|lhCAeFyIdtZ>YR1qt#g{H`SX4jz>0G~3-jdJiUAP&8m@8`h?FBYKs`napmSFBW^paLf1u^VcXYb7eqFAu?S|XaCCswnX$`l1F){`(bwdCCKy}e+Qps z-t=%N--V9`VOZ>%+9DP|Gjb#!Mci`KC&83e+A(#bt~B`3qVR;JhI&sscwx2u{%CIi z;o)|Qh@B!biPnI!Ir95`gFKOY-AAFmM3SGV`&^NKQm|XA~uUHIA6e zIHyKw754K%gUH}cG4}*B=cFx;S#(+=`%re!z*J;E64D$wuq?gZ3*f;roe^|~kYXIY zh3+RxEJx$x_e|CnS`bJRf*`_2_m2f=7c)>xto8wysXh>ZZPx8;CgvX^VfCDrWP>Ps zB234aqg;Fe4<(uy`fq)OAvl;pIqJ-E-^9X8hS!)@Ha2y?ToD;GvZs~D5AhsZ*-WBx zS7E168o+^Wj2>dixbd1u64J(SPJBh-Jz!$tm^`0+OfCx%$;U-9B*^oaeiFqs5HDNtlFv4i zH08(W-X|`vyw*@(Z0$vb>1f9EgH?hd1rR`r87w2hnZ&aEA(lM@A$f(58BC}>IVV^O zHemS#Z@rdi=thq>{9gIP$o~9TfbAp}IluB_`4mdgx>*&dYdH8@nLV&jdI&qW+dmua z_5^w7Szx#e9~_0h!Gtuc?nkeX2FDFLMs_7S-mBZujjUy>)vet3H_!q1IE5AB^{QL# zu8*&S5>Y~4)IGC#%unAJ*z@SS{37tL2b31(E+}UP1L+ z4zxdw#fj9i)Ww~@rwF^Lz;AmV3|pu{%V#%V)vKsbO3mRyq&7R)zJgjbaYJ%9Cmj9K ztoVsVc!g!9Ucyld;3HDWxd{21^yHFSw^<=a_SNS0E|FP3!frp|7mCn2v&%Uv_?c(h9Q<0&*_VA|<$TLH~bpNcCT}aq<@*+x=oJ?01JcGdHNHIxn zt@6fn0e_gLuR}_9I(#sfOTjz>e%Y#yVRrRZeT2U~z>MrFb)I%zl7OTX*-e)2Skw&K zMyfqSm(w=KDJfBLODJwso_IJYE3iWZzOYsMv8YWG>eWbPG>!S*^8AY z0-rB>Fz@k3vnxPq%!!rJ{hD}{D>-Q-b3>qjT!;IO_#52@m-s+#d&4V1!G7K2uFz>v z=k{LdZAbWExb+67W%1!rY(}AcXbJPy0mbGnDAj<|Z`7FfUj1oV$3V;iQbEH8lDOw5 z%=~B|cR$kV%sCmutA%kvlMnBgfMfc&2H;20)wghmtP|5d3Rtl6z z1+wROvz0q0=N7A6sXAJUceI1-0VeXIcSC68NO0p7&C0%L0p2{9IV@{{-(}Q?P^1=3 zOau}Ril#VIQ?jkA>Eyer0W+6i$>9QLuDuE9ZWYEh%xd?;@r~;{*zXKsN~xqHQ`ioI zAYbXmx^G&|Qkyu#(^8^&M2o)~_kuk~_QHjPpaFK5u)cg>hx(>~s%zuaDFForb=;{q z%MUypK1!>pZtd-6CMjrMb|hDQO+#IL%}1h0L%Oqy^X|7vSDN3}Vd3_hFGD{^>%KSW z+COTz;W=)+v0bP$lrcBIcZ7~WN+o{5bijAl6GYdqd!?#{Byo{tsKTsE=t&h?+sF12 zcaX_nxvwq)l)yF?bnKjl>q7AOXvxb)ZuO^n$v-xwOOm(4MVhO#y(;T78sAcGzaz+n zl_1+~_$22t=Qqm!)K@CJVa5-2b7aeg2}zx_1jCy4Uu=xC2XzK-CfzE{dVCXa-lIAS zs-IsWR9Hgva(>n0&+|Uh(YqYtOz@v~Zc;+`#<_#odD<~=AYa~B@E@W-{#w#0o%jNu zb#b>IgP)4CsKUt@rkeKD;X<156Q*6Pgd0DkxUNw zZOh{MAJOUF__J$a0R&HIW|?ek&D=&ZL-n8C{)%aUOtdk57E9Otas46w$Jg*9s2&de zM@#Ke6lQw4{oPa%IRhL7+WQ{s&5qL^*YLwD2(I!c&4CG7lp;;TBE@sNQZ?!G#*J zNOwNt_HVK~a{?<%7#vD*wt^LHfr)NnAQxX?(Jd#@6O|-4VVGi{A7_JPw0y=Bh;Xo4JtCxBDs8InviAqpln$uErRLf?pL3TCmL-9YZvizciMTiG(@^E@gU&$6}<-}8(iL2Y9~!l;4eOCk{} zye64_^}{B?C20nX4e#|OxZWHIiSP%SxAch{i%VhPw&SeSsNo5x*0Wz(VPs>c8|0oe-H5*8QyK49FJ`7xKxD)HLd9%f{3UMG+`e#-^bZ-a0c@8s3pG#S z!!iG=H?&@pJ^j%M6AAA?s!tJ6xI&B;bK@K!FWrvRG!%)q>b^=$;xqc4-PvBp7TSZ> zy!XNw*Dxh|JHo;`SOvMZ+)*-FTb$o~?vQMc-$}jn%{M%Q1p4Q~lrhB?d*8q|xlMPi z6`{j}FO>>w68n#de^vkXi`H$+m65>DhdPLwsO|R=MV3pBKYU^&?DYa2tEyRFO=8f3 zp=l72QgFX<@d5-^GJaH*(>wfL{p>nEEp7W>1fRU8y~-?jtZ z5Tm&G{+FrPOIYo!S8|%I-f4C{M!wah9@72l3>09hq(c{#!I&Oyi69T!wdMo7)q5Gn zm{Xs%fQ4bLey|m|>g;5GKQ|v(^5OF1ucm%{)K*tC!!7}3k=NPc9|&|6eGGNiWzZ~b zc$l5cqy@Vd#%+YV7|5p?^sA>8Rb1*07ox^NtsmR*JTm{Pm7n2rJ(2IVp7xG`HrqV{S>=x895{P$eu9;@$?$877j z4{HGroD>_)rsIl^Q|m_?cP7jA2j*JeH$g$moZWjfnH-}0{N9n@A(X$S(mea?xIa!Q z98Z$`0&yLTg{RHhFNHTP#1SrY*E@Tm4tNgg&C}uDQ0>4S{0avX(s+>p% zUkCOyxVHx|8T~wPO-Y}U&%X*JCZ^n*V@`tFDm!=*c zRj*PxLA<&&s0YW$wGrb7c*iu2giE;Z#71H`IlVps=y!Tg(5;~$3A=%p{CF0Z#HR+z z>JtCRt2@A`MzU9U?iWZJ#XZ#7+$ntY`W?mv%CMSy@y8jUnxb`aH0q%&u_0&jKz)Tz zE9%nr1e@5$xhqI&vi+UexWtxu-f>W$sTGKczi37m>rXDWV)t@ma(A1BINv8wL#{&C zVf^rrA&Gfx6^SqCSoS_lo)uz=0z`$tmAwwtwiahvpfA^<1NWF9LLDSw?$kQN;gi-w zw?iy`=x~rum8UnwWv~!I2t^6oOli_SNBBDqnDizITRvDHwpeSx^Zbwl5%=LtK=i;j zp#BsZ;==1cn{XbxYdeT7cU6p&?WWpux_s;lK||;iqjkb1hEK!{jK&+Fh;JKZ#QAse z8uD-Fr<%|SbaxMUsR^U1egNhz`fY+FWmyrH5Id>L{N3#7NrKKG0BcO?6E!X1%x8P{ZEa&AfA?lHr? zE-+1`0ahDA(f>Fac!!mB4?XldXBJ|8dMyk@prs^1WZ4+Wo}_ zYuy%)u@&bggeNSIpY`+wxUZZifPPhA}GMn>8`UHPn zC8@ui%b2}<&YVN>7l))Or7m_^8$OqpK$h4k897xMJ_)@lNS{1)8<~k03jgW+wssqj zWP1+2_4`s7H83?0w^zbjRk~PIkwKtL3H6S>WmA^0DNc zunXOz^sNY9ku?Z&GOQ}yjfB9O2X*rb~?u*p(6~fcfaoRy; z*mKY-`Ws%Ve=`Gn7~@{WE*rf(;JPlyjmuKnV|W-0&qIWJG^gwMrd~A*OUTrcVk%st z8Vr6`|FHmun}X$XC_v!*$|$YHLdCYAWs!a2a!>cRqM#na;N8 zJ?agOI@%fCVtbYB>rEi-y8L;kOvYs^Xu-ZzXpfsUp)`FSMUOsIufT|evcNS++%0w@ zzEO~5^Kh|+Wc$g$bt(w^{o(HJ%Oo*Jl4UC0Ui0fRWhlQuaoEE7B~P zUrVll8!%R+{=k_r(9lzga46P*F3--mNbb848YOG5%xOz)Jw(QDe$?sR<9;hDkZC!J1SC>#TfQ7ALVWk=>3(QxLsr>`E$zIU;C2&5mF4$9F47f|!C6XzWSzWA~5{oY_@sW-U&+0l+4G)<|B&0SvXB!M7IWs9!>_68#~>=_t@SZ?&E?nU7x ze7NBR-<6JGrUn$ygMhS*@Qp6^(a*2%WV7dIS>*Zi&_&~5p#F|Zu()4jDZR> zSf>#4JI?H&3U!Q?@O#|{e{5w!JN2MfbEZd8j47*oBChTVz~F&E3PsgJ7Za_@z1eiW zXSv<++jr1TZ<`|EpHvsiJKpxltAM-Rdz$>CW7gxY(n!u_D%ZDM;vjb=!1RG4nMxkv zK;baJj3D+$T5Qau=79drF_)M+FVThjfQoQJ(wi@hh2>CM?BwSAyXw}ld4yiVgM@Ve zC2XG8m*#IjEM%v#Px&fVo8%u8)K<(i0J|du(%c9N5+h2-g=`-KDj)q$ z09-w+nj*`x9(!d_r8d#$Xq7>rFZIESFdE;+g*P{!W0GgG-1w>YORy25riEz+D#Ky& zmw0hY96gTK*ZTICujc#^FS@PinU3YS$8S1v;-mG}y-~ZhkmwG9AgW7am!m++MQOkK zA)vykzuxmFuiPT8^7{@~%-6biSODA6Ae>nLhV^OLudw6RZUHXj9x3QY=dNKbrQ|}4 z=|C1}Hlvw1jA=HKWkbPt7o7m`Yb7%;6D!SN3@{8uv2bi{H-aapICbhcX%3~RkGP|M zCx3hwQ**z^t!Sz=yCYSOe$8ehAbJJPElmCD5r8kG#YR!-VExih`0`T89UkBByfBu= zS=ckN+5wit^cyQ}iBr$xmkXMdP+GhbUTgKyRd>X*L>O>Yig2M}kzr4H=!@pE)~81^ zDV%vL0TqQW1V*#^PP1Tm%$@*tJ3;lgUdzf#ehEj*1=j|n7W_Lsq5$Wl*ZZO(kZD2N zS386vGEYvF(>ZljSQ^pk-Gp9 zfvV71EfOwCa7#kJCU=V{`?RJ;`jB}q_)>$1r}ddcFHfa^977XIws`FIJT7bO-Rkox zzgS0c(s{@~2XO0FH+6;O7nx)roY$cK{o7xl8V{+Kd(9^~$uB}k_4ta?!%d~0(vI=u zUmMV0>o0I;d38+|Wqtq{EN(-Mf9JMchS1n>jYO+nVzYXa^()$6-z6PxVX4;5c=8kC zDIkL=#TF1?%D|ZHxx~U3J>DVJ6DkNNJRePR#Tn>dhL9>qF{Cu}ro!jl@u+<;495Jj zy(K{2RB@L%Z#aZCTcrm&e*bs!#1d%N7S(5udHP&Xg#ylL?%6q=_AulI>~nQB&jrR4 z5^rWmQ>#Hpxsm1qQc#A+$hz*9pCF6>uDMSZ%jfsYm#`rsk`znW9Dk^lMSkw2~i->qr4m>f4cl zK!W+m%hG8+l9$|88pc{*yo^V`N0o3b6_Xxzy0OCKMjjdSbmq6oujs6d#xFc1EUOY#mEEFiVpAF4J-S27g;FQa< z@_{{;cZUHGq)5T16#0Vfmet6{(;K}8_Ispb!1cT#&m8;X@Iojkk_K#XPhExHskVQW zG5ZtMbY!d9CGAGc1Ekfo%*w%IXZXk)d8l6hnPEE(rA6!1mCYuoIa>b7*^2&C-}YGE5hk;O*RF*b_$;t_j49Q62s{CNsBEg76n*`V-Z z#Q=w6H;o9EW4}TcYz0y{!fgDmEkq1hzj>X&Sn=qNauzlOLGfOt$E>{_h)b!kp!{TR zE2p$hKY7QC5XHL^6RwL-+`haH1LVSpd!=bk3Vz)ltdu@x271Uj1e&hscg z7#+C|3A2&PMwPnXVPU(R;nwp3X(GA55A+gTEo=qU-QHAv7af_%0ccHc(4sYusHxYz+-~q2=Ie{#oSFu|1fZOudKFWtmq?H~l4`qrgNQ$Pc?h`HjrG1OmG(hD{fA>6oTAJs{uz*A)>nK+?9a3!W+Jh z#(>RHbxvLZ2ZE*xUWAHIIdlg^MWav)uFu}o?gFuhcm^41wR7PAy2XTsub2FOtuwgrurhR;Qh@a67Whz2rF`4@8yzi4oo12} zsyafE#*JKcBSfcCDfUVZ@G6?@fL(AaxF?`2#ioX?@Q#$x2Z`%{cN z;9{jK7Akc6^m7UDcL}w_*pLA4Bvo|)52Q;bf~Bj%KxYBWU1elM8&r$9Zh(XQH_v3R zROki7JhI{1D<5~Y0}x4nMMK$KP^-~>zO-q^xHK6}a-x~A zU!uR!cIzCn1i7?e$7{*Ae!oL=jf)$CEXybwa=u$;H+xZcXQE=FzOfY_<3jWWa`9S9 zRkv|PH8PUk?5RQ@k6d3V4OH0v)^nw9-lSxO0%#TIQ^@$i@EbI3FDTIO%+#STRvkvj z@1BHAc)t5XAc0FDxWP##G16`+7Vbswh6(6Gx!V9q4DkL*x%V`ylvDvgvv(^S9?DtW zBP@}W70oKy?P=&?`{1A?am4qSztW67V}A<24J=Uq&e(*7>X@S~d6`@b%5%UL@VR<- z-G?b=04!3w1^)z$wT&rPPW}FDOV?#nwQ6qplVOWlj9Fz3udmD>rv57E4GLWBJa!=We6}}LmUY&DEf{Bz@LCIm3wMo)clqm zesLRWh!0SFTcuZ>1Q3zcr!2{`2YVPyeI>@o%Rh0?2#FzgitG*|x++_Ta?+5GJm3T` zOf0?mP;QgoJ7vQ9!JXHTy+ob25v%v2E-LqM?+Z?fyKRFP?3}Z<{v}|eHh{_yplO4; zZY6<47>$a;yC5U!0q(+VM?C(u7Bn?&iY@o6Sq`9N!0`G7`ji-!9>=ToDyeewO%Z|5 zUiJv291^&P@`OMj;w`23+Z|RoQ@6JQ2*iN_4^AX{G-lB1oa9}6ud9=1Co@FL_a1!D zG(&;$yn!!SY9LpUtfYCrC&o`gva>STx|0fg3ozss(Tc#tJ2}mOd;|cnSK*V} zf@ij8^B(ObuXj7X24V?jktE$5xMBckIBRAmZn88AT7lKw;Fo^_Q1Nf&h}VKsl)-zo zJ7YWVJKsLbddojXXk#k{&e#`n;bWKIA8uoWq}Sa!Z`YPGz{|^Uas={0=`Si#h)H)u zfM1j^WPi18(|Pb1yi*F5B37qw7f#VGoxo>=TpKwhdYYV4vfZ<_}gDJndA{uZ%1PB(G?MAgJuP2 z7c%ue;9Qct2t}~s4%FP}=M@P0`~MT1sZdZXXlm)cechIRp83P0o9PkfKHAx==`rA{ zo^2&x_Cm3QqRH!LIRQPEXIl-_%s5OQ7<4&H!}K6t{q?$N0-bfqEiA|LpMkifpGf3Q zh3{92pD3EV;}@ipkMzhp|9_eZbS@GZH?Lb6h^k@?0b2W3+b>q%->Td{J-1+Dm^y&u z6T(e`n){uesYU~atV`q460bUeTt_Mo-Mrg=9gpSwd0z`aV)JCd=JOUav9T}ZIT%~- z=wtq%O*;ZV*z&iC^LdczNPmZfi5OK-@3eevJJ&}C1C|aV?N_gURW#!WkMx`cw9n>xRhu8L0cQZ@DP?At1R+>y|D_zS596F(4>0*_ z%J{C|A7TmgA$7$5O`A#X^}h_Bv*(FWo$fHGJq5f@uPHHLmrm@N&2LyIfe7ycfm32* zFrUV=G&%poUuYgrxX3RVf;F>0$-)}A;$l3dqdwXXiXG0zw9?%4Ezk`H9+3@&{=!A! z_oj7if6>#xe#~D2XqU6?GZ-(QwNC=3S<1g;Kp2&%j2Ajs$#Cw7tQH z0V4*%n91!)Zp~}F=uiyUfxoXxqX*1;z&WIv02tn}o=Cq4Ux8Otg1oDkV5igQ z8P)-T2ouioS~oTHMDhQ!dN`WXP8AkjGJyS_HnTl!z#3lH{eWr(pgw59cs9OX!bS1b z@f&iM7tMuF%Bo<_VlO8UYKV@Zeh$?cw@W{AxB;Dd%U0&~yt@?NEq-6lB{r5$V1IxMapBm)sv7~h8j^*#M zTg#en+QD3W8v~$%PnO=m_a@`-Aq`RkRkZ>dixo3rpo9RtQY3wVZ{)V~8c_a964mt$J! zKiWvF2Uo1aMMmayt&wd}YBz>gOV1UD*DoMp_(n^v8%sK@b!<1qB`Fa0S8+T$|9=R( zk}4#OCGArSG;_2=MalrNz@-!w>LzaT6so9_t*4D;9a-Xu#IdR^%}!N|Weu7#tO zNdo?tJDE&3{t@>#O`bpgJI6l@O;e$#L2Ma<$k(rSNq;lYWbHG!5|GVHvL~@`?Y8LgZ$p$4lredvVzB9kN5v^ zCeNNyUkJFEK}R?u%OFI4{eO{W2IzqCQS7fMT|<9F{?Gqkl#ybcTs<72Ktw*q|Gz5H z5j|HXV@-c(URxziCKHYgC~HkL7|NWIG?HQ3Y3o6If+wRGWWAkSH%A~zZ0Vct;&&PoBA~zXoJ+>*bCBM^>qH1OM5n9Eg7u? z+Q6=*0=EKWasml=icg$P5YYwksP_-S=0C7;(LB)Yv@Arg6MokB2+W!mPwR^S-LsU{ zzn@Y^voPPnLoWuMAb2*u`k-@+z=F9jV1^BPPy!pXA?NB5%fM$$6Bqt&dZ0wk z0;qA29=g#RjDKd@>q7PU`s}t|{gnny=n^X++ofW_tXuz03YP&iosqyB`Cyub8Etc* zSEVucGV}a}yt=vr(cpM0v!q`0yZ;jyIGYxv<-Q&AvJ?3bNLzKVct5(SU-EhM|Gtqa z(`cDgrqkwyunt1$!p=0!HBjhtHoTOwmxk2>v-!Z=%sKIa^7WvWPdy+rxLrve^ffsh zfl?>7mt+@yuW0qmOd+!4?SGol_2r-yBd~9Q^#u$iAcGUgy(wy&gK<@_Mfh&I!$em_yY!P2OE6KQ%EL;I75r*{4F6+(7P5$nbSP_n0vZv zpi?rg%ToEynCjFjNYG1FKJS+Zfk68^&}H(gBaUX0>c_p;8Ogl)w4*9Y?*elQ*Abl+ zj9Gwjo$>tH`U+^gsS>pGYO*4>_{6GAq@9TV$VvB3GjGr4)f4AsLKEBo5sdu=O!+Pb zY!K8^cpA`RFMVs^GqFG5|6np^)xZq@sr zIO(`vaAHg zvj&>XdjDQdnmmw~8q_SOJ@#HYhtWk$@y%;A$g)Huv?-n>x{-B5g*!?L* zF8M%gJh}fDZaaw@oh`=oO^BtC1P2i|~GkC$zlVlvzA;rG(o9}UMkpID$-SwHa3tloq?z)INZ~F6-eoBDLh=(dDIQs4!*DA(BD0qrzK@G9+S8x*fL)(_lUxB6ch@_T(hG53~Q-=pIrBv8`K_`SDY zk^>U;*q@k_Y^=ZrF-d2O3k2B!C&LS{S_yE^C-SoCRxsFdQUj&Ts(JgD$TIqLn+;hO zE@Bx_{%d{kYgbj0-lfd((DjKN7zU%ARb+D__m!B7f+b+dHwv+kc%M%{HabJ zLX|9Ej-P>k)<8kEUJ<3VV*-R7=z!7LAhih*Rm?cK9ew#@tdVM5V~5xa*Q$c0K8Mi_ z6|g#Y0W17`gCT|;kFXc^4hxg5VaqxXx&}WzD;7~Sxz~P_QYm2Ni2`OsGaouE{m+in zYuHasu^mqi0L~vD=42B7TC{~|c_)+OsUkPuiOkp`39wt({8<(I_mr}y%WCQAj=IV` z0qpkn&y$OsqCpys$=9sn271bVpJgzzk^00mJi1T;gLYpYpy7nGYSEtdf3jQ@udq9Cs5H@u2Q5yWW#Fgt zn=C5KUY|Ch0<(p_1$WwWwUeBNPyzygB`O8qXb6jX(0%k!!t|estiO2V4-g+7BmN>V zl4KY#oEyC}S6SH4k3s#LN~|vRx;m6+e^~zdCywXIpjB)3!CM6Dg^CA^U!(7`uqXUW zGSC?VwsNWbABTsUfJD9}#Gd>SnlaMncBV|dRX-+gI07>rz|KABc=_2dO4Af!ZoG&% z!MOoiLtY6EJL?5Gv3J6tkQy0GlgZ)o?)uf9%jgDp z?@BpuWc5Sq*SD%gbpH7+iqi6rYBgH6-5>OU{@!{P+a#sUxakyi^Uv_ zK8JU}oE62wr(On~)Vj0z-Uni2X0{81LI&q|fO;g}{O?`7cey1vwB`W(3H2+58{MD` zf`e=XRMp-MD8gHa$65a)$9<`n+>TkYp=O3C<)eHJRr%+?P!yg1jb2=3rHs$K{z+npuR7t>^E{LC zT^G+Gey@frvwL!Zb_aw+FhB_asP7(;jf^_!{3i8A2D~7$Q|Tp=3=7)X9l7KR{kEII7&+D%tymo&K$qw*GJC}kK$8+ zBsKkUTm2P_ZWav0%}LRu)!qco!c9B!vM);yA83Ij45i1*va-J1fA@kNixU6P16dxu z2tL!J>}=3#1h`y>#mDZyefV(4{Z|D^KLQmD2pu!|IsW4B2o1CVAqF#0AZwNjnBz55 z#bWv@y|`Xm(M?kYxgRzYU^@SHxto4fV!c!E)K$ztGXS39mpb{`*5GGMZr2j7DTCbz z11N4U7uf<=++HB@-&ceng%d=@5^Q)gpMhYX_!P)f!rX0?Sf}$wUf7BonScHC2yF;k zSgc<1At`-AdX52#Jor#rv*BLS;f7-d0!XSlhMgUu2ZBaVE@cAvGO!hZQo;7*xbLLb z%w^7hj9r`FitSKWp%~p!x~md&r**$;NVbTu2Hga;^oXO?dUwbAc3y`NP*DHlf%B>d zvsJI|ZvpZZAeaD8ASpVwd-&s+3jASMc{F~7CJABqfG*d48<=_7Ptusb3L;D|1kmVS z^Wp0ggsB~r?PLq)WyZzV%=#P)j*IHR{`C8o)-e~J?f(BVm)ZbaL+2t?&UBvDB=G5{z0uh#zx$ms2_f&33>crK`%?9Wt`tk3{*+~Zg0 z!{+YakLI`-FfnKM&pOV6y-<7^VsWF}Xmrc2=EO8dCvxXz8-^k;sFo`#sXJ(?&bgh> zJ~&<)`~Lo!Ni4&k?fE-tDwC;KJw-8YVII{J@jTbQI?w9^~${_IU--cQT? z^R+&S{PQ82y~)+=1O^Sw)IZ*-FmPec$c8K5r%T{)6*Ic^$!k6EfNySo8!kE3fQKRZ znCPSM@!SQk;f2Iwcch6N^%6^M+n1p1<0Dnkv7A7w>Zt?g`-ppwi-cv#`cC`rdM&i_ z&1int%&mFVKfnG-%D%=aU&GynV(GgmVmxq_2ZfiZcDkV|3jJo$cygWjN+jR6{0&|? zF_<})`5-^r`tU8X#UV&T-p`hv?j_>!^Eg(SN+qXeQ5}bua~}8Td%CM4uP=nOCm@aA z2J_{e;`Eu(xjN(NOq1@&+ju4{{ti>0@TBK*YX$r}7UNzU|2TU;*Vg`9HxH)nWb1)M3;L$`EyCe*ny`K{xYCEa=wkm=_?94m>9daM+`xX^y* zvQxR<&V*Wp(g0(@lk}Gv`I_e|-BadbASS{_B@bruk9zEk9+xA7k(+DcI-`_Y;)(;z zTBnAsqB~Kz*@^n#`?f`I%@<1>&(-?Ku51h9^Mw?C>70e5m{nSLmOCa&7t|`1)Tz+4#m{X_ zW40{FUmJIw?TdNa@KSe-7;VPaCy`&mtR42pflpxMgUpRvyDLwUhkTg8t$UTT{b3&R z2cxjYsSyz$lv|<3_v~ACUpl{C<>4O_x}r$jh2gjvmdc@Vc3El$&V^ZF^=eg#lGO4A ztwn3X69HSVDa9xANa&g>?4`+m!Ex<-Q62Nla?{?W<>T+QKjzGAu3!BAel!~z$FM!r zW;}i(O

hyMi>&A|W`wq67Mz~*on~ACGmCKkUS}8SMZc9KC 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 A761SM literal 109967 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�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 nQ)PI4q_45>>O#*G Date: Mon, 16 Oct 2023 16:03:53 +0200 Subject: [PATCH 34/38] fix buttons home page --- docs/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/README.md b/docs/README.md index 3380730c..6dbcb0dd 100644 --- a/docs/README.md +++ b/docs/README.md @@ -50,7 +50,7 @@ Smart contracts [can be attached to offers](./general/high-level/concepts/smart-

## Deploy your own composable strategy @@ -74,7 +74,7 @@ Mangrove enables liquidity providers to incorporate defensive code, post unprovi ## Kandel strategy @@ -103,7 +103,7 @@ Mangrove enables liquidity providers to incorporate defensive code, post unprovi ## Mangrove is a secure protocol From 5b60e18241dcd3d1d349c10c980aad02a084ba52 Mon Sep 17 00:00:00 2001 From: frkralj Date: Mon, 16 Oct 2023 16:12:08 +0200 Subject: [PATCH 35/38] fix buttons home page --- docs/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/README.md b/docs/README.md index 6dbcb0dd..defa5659 100644 --- a/docs/README.md +++ b/docs/README.md @@ -74,7 +74,7 @@ Mangrove enables liquidity providers to incorporate defensive code, post unprovi ## Kandel strategy @@ -103,7 +103,7 @@ Mangrove enables liquidity providers to incorporate defensive code, post unprovi ## Mangrove is a secure protocol From a8bb982a33ec6bbeb8dfdb652479f7b40b8321a9 Mon Sep 17 00:00:00 2001 From: frkralj Date: Mon, 16 Oct 2023 16:30:54 +0200 Subject: [PATCH 36/38] test color change light mode --- docs/developers/README.md | 2 +- src/css/custom.css | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/developers/README.md b/docs/developers/README.md index 47b72dcb..3f024d66 100644 --- a/docs/developers/README.md +++ b/docs/developers/README.md @@ -10,7 +10,7 @@ The purpose of the Mangrove Developers doc is to: * learn about Mangrove [core protocol](./contracts/README.md), * understand how trading [strategies](./strat-lib/README.md) can be created and plugged in, * use and integrate our [SDK](./SDK/README.md), -* set up [Keeper and Cleaning bots](./keeper-bots/). +* set up [Keeper and Cleaning bots](./keeper-bots/README.md). We suggest you start by reading [this introduction](./contracts/README.md). diff --git a/src/css/custom.css b/src/css/custom.css index b7c9251d..aec90c18 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -7,7 +7,7 @@ /* You can override the default Infima variables here. */ :root { --ifm-font-family-base: 'Inter'; - --ifm-color-primary: #1eb759; + --ifm-color-primary: #03624C; --ifm-color-primary-dark: #195644; --ifm-color-primary-darker: #185240; --ifm-color-primary-darkest: #144335; From 3e266058407e6a1bce86459ed16cbdec952ce3a8 Mon Sep 17 00:00:00 2001 From: frkralj Date: Mon, 16 Oct 2023 16:37:16 +0200 Subject: [PATCH 37/38] test color 2 --- src/css/custom.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/css/custom.css b/src/css/custom.css index aec90c18..046f274e 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -7,7 +7,7 @@ /* You can override the default Infima variables here. */ :root { --ifm-font-family-base: 'Inter'; - --ifm-color-primary: #03624C; + --ifm-color-primary: #2FA98C; --ifm-color-primary-dark: #195644; --ifm-color-primary-darker: #185240; --ifm-color-primary-darkest: #144335; From d591dec9716fb06b268645785ede40bc72217432 Mon Sep 17 00:00:00 2001 From: frkralj Date: Mon, 16 Oct 2023 17:04:47 +0200 Subject: [PATCH 38/38] tweaks FAQ light mode --- src/css/custom.css | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/css/custom.css b/src/css/custom.css index 046f274e..0ef0e366 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -9,7 +9,7 @@ --ifm-font-family-base: 'Inter'; --ifm-color-primary: #2FA98C; --ifm-color-primary-dark: #195644; - --ifm-color-primary-darker: #185240; + --ifm-color-primary-darker: #185340; --ifm-color-primary-darkest: #144335; --ifm-color-primary-light: #1f6a53; --ifm-color-primary-lighter: #206e56; @@ -31,6 +31,11 @@ } .alert--info{ + --ifm-alert-background-color: #DEDEDE; + --ifm-alert-border-color: #193c47; +} + +html[data-theme='dark'] .alert--info{ --ifm-alert-background-color: #03624C; --ifm-alert-border-color: #DEDEDE; }