# self-hosted mean.finance Alerts with Telegram and Python

By [bruderbuck](https://paragraph.com/@bruderbuck) · 2022-12-22

---

In this post, I want to share with you a project that I recently completed: a **Telegram bot** that alerts me when a **position** on [**mean.finance**](https://mean.finance) runs **out of funds**.

For those who may not be familiar with it, mean.finance is a decentralized finance (**DeFi**) platform that allows users to dollar-cost average (**DCA**) into cryptocurrency by automating purchases using **smart contracts**. In addition to DCA, mean.finance also allows users to earn **yield** on their idle cryptocurrency. However, these positions can sometimes **run out of funds**, which might be annoying since there is no direct notification system that informs you of that.

To solve this problem, I decided to write a **Telegram bot** that monitors the funds in my mean.finance positions and sends me a **notification** as soon as one of them becomes depleted. In this post, I'll explain how I built the bot and how you can set up a similar one for your own mean.finance positions.

I hope you find this project as interesting and useful as I do, and I look forward to hearing your thoughts and feedback in the comments section. Let's get started!

### What you need:

*   **Raspberry Pi** or **Server**; something to run the python script on
    
*   a **telegram bot instanc**e; just follow step 2 of this [tutorial](https://www.process.st/telegram-bot/). You should now have the token for the http API
    
*   your own telegram **chat id**: follow this [tutorial](https://diyusthad.com/2022/03/how-to-get-your-telegram-chat-id.html) to get it
    

### The Code

> always use the up to date version of the code: [github](https://github.com/bruderbuck/Mean-Finance-Telegram-Alerts)

I will walk you through the code piece by piece, but don’t worry in the end there will be all to **copy paste.**

First we will import all necessary **libraries**, you can install them via pip install.

    import web3
    import json
    import requests
    from datetime import datetime as Datetime
    import time
    

Than we will import all **individual** inputs

    lastMessageTime = 0
    
    #load telegram bot token
    token = 0
    with open("token.txt") as file:
        token = file.read()
    
    #load the ABI from a JSON file
    contract_abi = 0
    with open("abi.json") as f:
        contract_abi = json.load(f)
    
    #load position ID
    positionID = 0
    with open("positionID.txt") as file:
        positionID = int(file.read())
    
    #load chat ID
    chatID = 0
    with open("chatID.txt") as file:
        chatID = file.read()
    

*   the **bot token** is the one obtained during the setup of your telegram bot instance
    
*   the **ABI,** to get it:
    
    *   look up the smart contract address of the DCA Hub. You can find it in the [docs of mean finance](https://docs.mean.finance/guides/smart-contract-registry), it should be 0xA5AdC5484f9997fBF7D405b9AA62A7d88883C345 for all chains that mean.finance is deployed on
        
    *   paste the **address** in the **block explorer** of the **chain** your position is on, for example polygonscan
        
    *   click **contract** and scroll all the way down until you find the field **“Contract ABI”**
        
    *   copy paste the content into a file called **abi.json** and make sure the file extension is .json
        
*   the **position ID** of the position you want to have alerts for
    
    *   look it up using a block explorer or on mean.finance directly (go to your position and click view NFT).
        
*   the **chat id** we obtained earlier.
    

Then we will create our **web3** instance and initiate the **smart contract** we will work with

    # Set the HTTP endpoint for your Polygon node
    w3 = web3.Web3(web3.Web3.HTTPProvider("https://polygon-rpc.com"))
    
    # Set the contract address and ABI (Application Binary Interface)
    contract_address = "0xA5AdC5484f9997fBF7D405b9AA62A7d88883C345"
    
    
    # Instantiate the contract
    contract = w3.eth.contract(address=contract_address, abi=contract_abi)
    

Now everything is set up and we can get to the **loop** that will run constantly

    #loop
    
    while(True):
    
        #get the current time
        currentTime = int(time.time())
    
        #check wether 4 hours have passed
        if currentTime > (lastMessageTime+(3600*4)): 
            lastMessageTime = currentTime
            # Call the "userPosition" function of the contract with the input "positionID"
            result = contract.functions.userPosition(positionID).call()
    
            #calculate how much time is left until last swap 
            swapsLeft = result[-3]
            secondsBetweenSwaps = result[2]
            roughlyTimeLeftSeconds = swapsLeft*secondsBetweenSwaps
            roughlyTimeLeftHours = swapsLeft*secondsBetweenSwaps/3600
            # Print the result
            print(swapsLeft)
            print(roughlyTimeLeftHours)
    
    
    
            outOfFundsTimestamp = int(time.time()) + roughlyTimeLeftSeconds
            datetime_obj = Datetime.utcfromtimestamp(outOfFundsTimestamp)
    
            print(str(datetime_obj.strftime("%d.%m.%y %H:%M:%S")))
    
            #check wether the last swap is less than 72 hours away
            if roughlyTimeLeftHours < 72:
                
                #text user on telegram
                messageString = str("you have only funds left for " + str(swapsLeft) + " swaps! You will run out of funds around " + str(datetime_obj.strftime("%d.%m.%y %H:%M:%S")))
                params = {"chat_id":chatID, "text":messageString}
                url = f"https://api.telegram.org/bot{token}/sendMessage"
                message = requests.post(url, params=params)
        #wait 60s before checking if 4 hours have passed
        time.sleep(60)
    

The code is currently configured to **check** every **60s** if the **refresh time** of **4 hours** is reached. If that is the case and your position will run out of funds in **less than 72**h it will send you a **message** every **4 hours**!

You can run the code on whatever **device** you want. I use a **Raspberry Pi**, which works perfect for the job and draws very **litle power**.

Pls comment or reach out if you have any questions about the code or on how to get it running :)

As promised here is all the code to copy paste:

    import web3
    import json
    import requests
    from datetime import datetime as Datetime
    import time
    
    lastMessageTime = 0
    
    #load telegram bot token
    token = 0
    with open("token.txt") as file:
        token = file.read()
    
    #load the ABI from a JSON file
    contract_abi = 0
    with open("abi.json") as f:
        contract_abi = json.load(f)
    
    #load position ID
    positionID = 0
    with open("positionID.txt") as file:
        positionID = int(file.read())
    
    #load chat ID
    chatID = 0
    with open("chatID.txt") as file:
        chatID = file.read()
    
    
    # Set the HTTP endpoint for your Polygon node
    w3 = web3.Web3(web3.Web3.HTTPProvider("https://polygon-rpc.com"))
    
    # Set the contract address and ABI (Application Binary Interface)
    contract_address = "0xA5AdC5484f9997fBF7D405b9AA62A7d88883C345"
    
    
    # Instantiate the contract
    contract = w3.eth.contract(address=contract_address, abi=contract_abi)
    
    
    #loop
    while(True):
    
        #get the current time
        currentTime = int(time.time())
    
        #check wether 4 hours have passed
        if currentTime > (lastMessageTime+(3600*4)): 
            lastMessageTime = currentTime
            # Call the "userPosition" function of the contract with the input "positionID"
            result = contract.functions.userPosition(positionID).call()
    
            #calculate how much time is left until last swap 
            swapsLeft = result[-3]
            secondsBetweenSwaps = result[2]
            roughlyTimeLeftSeconds = swapsLeft*secondsBetweenSwaps
            roughlyTimeLeftHours = swapsLeft*secondsBetweenSwaps/3600
            # Print the result
            print(swapsLeft)
            print(roughlyTimeLeftHours)
    
    
    
            outOfFundsTimestamp = int(time.time()) + roughlyTimeLeftSeconds
            datetime_obj = Datetime.utcfromtimestamp(outOfFundsTimestamp)
    
            print(str(datetime_obj.strftime("%d.%m.%y %H:%M:%S")))
    
            #check wether the last swap is less than 72 hours away
            if roughlyTimeLeftHours < 72:
                
                #text user on telegram
                messageString = str("you have only funds left for " + str(swapsLeft) + " swaps! You will run out of funds around " + str(datetime_obj.strftime("%d.%m.%y %H:%M:%S")))
                params = {"chat_id":chatID, "text":messageString}
                url = f"https://api.telegram.org/bot{token}/sendMessage"
                message = requests.post(url, params=params)
        #wait 60s before checking if 4 hours have passed
        time.sleep(60)

---

*Originally published on [bruderbuck](https://paragraph.com/@bruderbuck/self-hosted-mean-finance-alerts-with-telegram-and-python)*
