In this tutorial I am going to go through how I built a market maker bot to manage liquidity on Uniswap v3 for a token pair. The idea is to create a automated trading bot which buys tokens when price falls below a base line value and sells tokens when price is above the base line.
The full code for this trading bot is at: https://github.com/jamesbachini/Market-Maker-Bot
The idea behind the bot is to set a base line exchange rate between the two assets in the pool. So if the UNI token is trading at 30 UNI = 1 ETH then we can set that as the target exchange rate.
We then make a trade every predefined period to check the current price and trade accordingly.
The code uses a fixed constant targetPrice but you could quite easily make this dynamic, following a target price channel or even a moving average for example.
Instructions For Setting Up Uniswap Market Maker Trading Bot
You’ll need NodeJS to run this, fork the repo and install the libraries with the node package manager. I’m using ethers.js and dotenv for credential management.
Your dotenv file will need a private key for a wallet with some Goerli ETH in (testnet) and an Alchemy API key for the RPC connection. There is a .env sample file in the repository which you can edit and rename to .env
The mm.js file is setup to trade ETH/UNI pair on Uniswap v3 Goerli testnet. To trade other tokens and/or other chains make sure you change the token contract addresses. For Polygon for example you’ll need to change the weth address to wMatic. Note that the buyTokens() function is setup to transfer in ETH however the sellTokens() function doesn’t unwrap the wETH.
Each Uniswap liquidity pool with have a fee attached. For example on Goerli there are at least two different pools with a 0.3% fee and a 1% fee. We can trade on each individually by setting the fee value on line 9 to basis points i.e. 3000 & 10000 respectively.
const fee = 3000; // Uniswap pool fee bps 500, 3000, 10000
const buyAmount = ethers.parseUnits('0.001', 'ether');
const targetPrice = BigInt(35); // target exchange rate
const targetAmountOut = buyAmount * targetPrice;
const sellAmount = buyAmount / targetPrice;
const tradeFrequency = 3600 * 1000; // ms (once per hour)
We then set a buyAmount for how much ETH we want to spend on each purchase. The targetPrice is the exchange rate between ETH and our token, in this example we are setting it to 35 UNI : 1 ETH. The final user variable that you may wish to change is the tradeFrequency, in the example this is set at a fixed millisecond rate of one trade per hour. In production you might want to add some randomness to this loop so that it executes at different times each day.
The code then fetches a quote using the Uniswap v3 quoter contract and executes either buyTokens() or sellTokens() depending on the current price. For the sellTokens() function we check the allowance and make sure we have approved the router to spend the ERC20 tokens prior to calling the swap.
Use Cases For The Uniswap Market Maker Trading Bot
This bot can be adjusted to fit a number of different use cases such as:
- Transparently sell DAO treasury assets when price is above a predefined level
- Balancing liquidity on either side of the pool
- Reduce volatility on a digital asset by evening out peaks in supply and demand
- Prop up a token so that it doesn’t trade below a certain price
- Dollar cost average into a position when price is below a set level
- Sell out of a position when price reaches a target level
- Create a more sophisticated trading system balancing multiple assets
- Manage price discovery for a newly released ERC20 governance token
This bot isn’t going to be competitive at arbitrage and MEV or any sort of HFT. Also be wary of scams and always check you understand code before you run it or send funds. This code is not production ready and for experimental purposes only.
Everything on the blockchain is transparent and it’s a thin line between managing liquidity and price manipulation. Do good things and be open with your community ❤️