Storing liquidity events from Uniswap V3 into mongoDB with ethers.js
Tags: typescript, uniswap, mongodb
Published: 2023-01-27 00:06:21

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ec9zglhyem7pii85rh9e.jpeg)

This code is using the ethers library to interact with a smart contract on the Goerli Ethereum test network. The smart contract is an instance of Nonfungiblepositionmanager, and its ABI (Application Binary Interface) and address are imported from a JSON file.

The code also uses the MongoClient from the mongodb library to connect to a MongoDB database and store data.

```
import { ethers } from 'ethers'
import { MongoClient, ServerApiVersion  } from 'mongodb'
import { IIncreaseLiquidityArgs, IIncreaseLiquidity } from './interfaces'


const Nonfungiblepositionmanager = require('./artifacts/Nonfungiblepositionmanager.json')
const ERC20 = require('./artifacts/ERC20.json')

const uri = `mongodb+srv://<username>:<password><dbName>.hkje2xt.mongodb.net/?retryWrites=true&w=majority`
//@ts-ignore
const mongoClient = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true, serverApi: ServerApiVersion.v1 });

const goerliWssProvider = new ethers.providers.WebSocketProvider("wss://eth-mainnet.g.alchemy.com/v2/<apiKey>")

const NFPM = new ethers.Contract(
    '0xC36442b4a4522E871399CD717aBDD847Ab11FE88',
    Nonfungiblepositionmanager.abi,
    goerliWssProvider
    )
```

The code has two event listeners, one for the “IncreaseLiquidity” event and one for the “DecreaseLiquidity” event. When each event is emitted, the storeUntoDb function is called and data from the event is stored in the MongoDB database. The code also uses the WebSocketProvider from ethers to listen for new blocks on the Goerli network, and when a new block is mined, the increaseLiquidityListener and decreaseLiquidityListener functions are called to check for events emitted in that block.

```
const decreaseLiquidityListener = async (blockNumber) => {
    try {
            const decreaseLiquidityEvent = await NFPM.queryFilter(
                'DecreaseLiquidity',
                blockNumber - 1,
                blockNumber                
            )
            storeUntoDb(decreaseLiquidityEvent, blockNumber)
    } catch (error) {
        console.log(error)
    }
}

const increaseLiquidityListener = async (blockNumber) => {
    try {
            const increaseLiquidityEvent = await NFPM.queryFilter(
                'IncreaseLiquidity',
                blockNumber - 1,
                blockNumber                
            )
            storeUntoDb(increaseLiquidityEvent, blockNumber)
    } catch (error) {
        console.log(error)
    } 
}
```

The function storeUntoDb is called with the event data and the block number, it connects to the MongoDB, it then retrieves the token information, symbol, dec

```
const storeUntoDb = async (event: IIncreaseLiquidity[] | any, blockNumber: number) => {
    try {
        if(event.length > 0){
                await mongoClient.connect()
                const position = await NFPM.positions(Number(event[0].args.tokenId._hex))
                const token0 = new ethers.Contract(position.token0, ERC20, goerliWssProvider)
                const token1 = new ethers.Contract(position.token1, ERC20, goerliWssProvider)
                const symbol0 = await token0.symbol()
                const symbol1 = await token1.symbol()
                const decimals0 = await token0.decimals()
                const decimals1 = await token1.decimals()
                const account = await NFPM.ownerOf(Number(event[0].args.tokenId._hex))
                    const tvlCollection = await mongoClient.db("tangle-db").collection("liquidity-transactions")
                    const result = await tvlCollection.insertOne({ 
                        block: blockNumber,
                        eventName: event[0].event,
                        token0Address: position.token0,
                        token1Address: position.token1,
                        symbol0: symbol0,
                        symbol1: symbol1,
                        amount0: (Number(event[0].args.amount0._hex) / (10 ** decimals0)),
                        amount1: (Number(event[0].args.amount1._hex) / (10 ** decimals1)),
                        account: account,
                        time: Date.now()
                    })
                    console.log(result)      
        }
    } catch (error) {
        console.log(error)
    }    
}
```

In the end we assign to the websocket and listen to every block, grab its `blockNumber` and pass through the event listeners who will inser fields in the collection whenever block which has liquidity being added or removed.

```
goerliWssProvider.on('block', async (blockNumber) => {
    await decreaseLiquidityListener(blockNumber)
    await increaseLiquidityListener(blockNumber)
})
```

The whole code:

```
import { ethers } from 'ethers'
import { MongoClient, ServerApiVersion  } from 'mongodb'
import { IIncreaseLiquidityArgs, IIncreaseLiquidity } from './interfaces'


const Nonfungiblepositionmanager = require('./artifacts/Nonfungiblepositionmanager.json')
const ERC20 = require('./artifacts/ERC20.json')

const uri = `mongodb+srv://<username>:<password>@<db>.hkje2xt.mongodb.net/?retryWrites=true&w=majority`
//@ts-ignore
const mongoClient = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true, serverApi: ServerApiVersion.v1 });

const goerliWssProvider = new ethers.providers.WebSocketProvider("wss://eth-mainnet.g.alchemy.com/v2/APY_KEY")

const NFPM = new ethers.Contract(
    '0xC36442b4a4522E871399CD717aBDD847Ab11FE88',
    Nonfungiblepositionmanager.abi,
    goerliWssProvider
    )

const storeUntoDb = async (event: IIncreaseLiquidity[] | any, blockNumber: number) => {
    try {
        if(event.length > 0){
                await mongoClient.connect()
                const position = await NFPM.positions(Number(event[0].args.tokenId._hex))
                const token0 = new ethers.Contract(position.token0, ERC20, goerliWssProvider)
                const token1 = new ethers.Contract(position.token1, ERC20, goerliWssProvider)
                const symbol0 = await token0.symbol()
                const symbol1 = await token1.symbol()
                const decimals0 = await token0.decimals()
                const decimals1 = await token1.decimals()
                const account = await NFPM.ownerOf(Number(event[0].args.tokenId._hex))
                    const tvlCollection = await mongoClient.db("tangle-db").collection("liquidity-transactions")
                    const result = await tvlCollection.insertOne({ 
                        block: blockNumber,
                        eventName: event[0].event,
                        token0Address: position.token0,
                        token1Address: position.token1,
                        symbol0: symbol0,
                        symbol1: symbol1,
                        amount0: (Number(event[0].args.amount0._hex) / (10 ** decimals0)),
                        amount1: (Number(event[0].args.amount1._hex) / (10 ** decimals1)),
                        account: account,
                        time: Date.now()
                    })
                    console.log(result)      
        }
    } catch (error) {
        console.log(error)
    }    
}

const decreaseLiquidityListener = async (blockNumber) => {
    try {
            const decreaseLiquidityEvent = await NFPM.queryFilter(
                'DecreaseLiquidity',
                blockNumber - 1,
                blockNumber                
            )
            storeUntoDb(decreaseLiquidityEvent, blockNumber)
    } catch (error) {
        console.log(error)
    }
}

const increaseLiquidityListener = async (blockNumber) => {
    try {
            const increaseLiquidityEvent = await NFPM.queryFilter(
                'IncreaseLiquidity',
                blockNumber - 1,
                blockNumber                
            )
            storeUntoDb(increaseLiquidityEvent, blockNumber)
    } catch (error) {
        console.log(error)
    } 
}

goerliWssProvider.on('block', async (blockNumber) => {
    await decreaseLiquidityListener(blockNumber)
    await increaseLiquidityListener(blockNumber)
    // createPoolListener(blockNumber)
})
```

Pay me a coffe (all evm chains):
0xe25bf122bc1369754edEC5318AF399EB9D0857CB