Skip to content

Commit

Permalink
Add DCM supply bot
Browse files Browse the repository at this point in the history
  • Loading branch information
0xAurelius committed Feb 14, 2024
1 parent 86139dc commit e97a242
Show file tree
Hide file tree
Showing 10 changed files with 174 additions and 40 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ jobs:
WEB3_PROVIDER_POLYGON_URL: ${{ secrets.WEB3_PROVIDER_POLYGON_URL }}
DISCORD_BOT_TOKEN_REBASE: ${{ secrets.DISCORD_BOT_TOKEN_REBASE }}
DISCORD_BOT_WEBHOOK_REBASE: ${{ secrets.DISCORD_BOT_WEBHOOK_REBASE }}
DISCORD_BOT_TOKEN_RUNWAY: ${{ secrets.DISCORD_BOT_TOKEN_RUNWAY }}
DISCORD_BOT_TOKEN_DAO_FEE: ${{ secrets.DISCORD_BOT_TOKEN_DAO_FEE }}
DISCORD_BOT_TOKEN_DAO_BALANCE: ${{ secrets.DISCORD_BOT_TOKEN_DAO_BALANCE }}
DISCORD_BOT_TOKEN_DCM_SUPPLY: ${{ secrets.DISCORD_BOT_TOKEN_DCM_SUPPLY }}
DISCORD_BOT_TOKEN_KLIMA_BOND_ALERTS: ${{ secrets.DISCORD_BOT_TOKEN_KLIMA_BOND_ALERTS }}
DISCORD_BOT_TOKEN_KLIMA_PRICE: ${{ secrets.DISCORD_BOT_TOKEN_KLIMA_PRICE }}
DISCORD_BOT_TOKEN_BCT_PRICE: ${{ secrets.DISCORD_BOT_TOKEN_BCT_PRICE }}
Expand Down
16 changes: 16 additions & 0 deletions k8s/dcm_supply/deployment_set_bot.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: bot
spec:
template:
spec:
containers:
- name: bot
args: ["src.dcm_supply.main"]
env:
- name: DISCORD_BOT_TOKEN
valueFrom:
secretKeyRef:
name: discord-bots-secret
key: DISCORD_BOT_TOKEN_DCM_SUPPLY
13 changes: 13 additions & 0 deletions k8s/dcm_supply/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- ../base

namePrefix: dcm-supply-

commonLabels:
bot: dcm-supply

patchesStrategicMerge:
- deployment_set_bot.yaml
2 changes: 1 addition & 1 deletion k8s/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ resources:
- ./treasury_carbon
- ./treasury_market
- ./ubo_price
- ./runway
- ./retirement_fee_info
- ./dao_fee
- ./dao_balance
- ./dcm_supply
- ./cco2_price

namespace: discord-bots
Expand Down
1 change: 1 addition & 0 deletions k8s/secret.properties.template
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ DISCORD_BOT_TOKEN_UBO_PRICE=${DISCORD_BOT_TOKEN_UBO_PRICE}
DISCORD_BOT_TOKEN_RETIREMENT_FEE_INFO=${DISCORD_BOT_TOKEN_RETIREMENT_FEE_INFO}
DISCORD_BOT_TOKEN_DAO_FEE=${DISCORD_BOT_TOKEN_DAO_FEE}
DISCORD_BOT_TOKEN_DAO_BALANCE=${DISCORD_BOT_TOKEN_DAO_BALANCE}
DISCORD_BOT_TOKEN_DCM_SUPPLY=${DISCORD_BOT_TOKEN_DCM_SUPPLY}
DISCORD_BOT_WEBHOOK_REBASE=${DISCORD_BOT_WEBHOOK_REBASE}
DISCORD_WEBHOOK_BROKEN_BOND_ALERT=${DISCORD_WEBHOOK_BROKEN_BOND_ALERT}

Expand Down
4 changes: 4 additions & 0 deletions src/constants.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from web3 import Web3

# Hard-coded since Polygon block times have stabilized
AVG_BLOCK_SECS = 2.21

# Token Decimals
BCT_DECIMALS = 18
C3_DECIMALS = 18
Expand Down Expand Up @@ -46,3 +49,4 @@
KLIMA_PROTOCOL_SUBGRAPH = 'https://api.thegraph.com/subgraphs/name/klimadao/klimadao-protocol-metrics'
KLIMA_CARBON_SUBGRAPH = 'https://api.thegraph.com/subgraphs/name/klimadao/polygon-bridged-carbon'
KLIMA_BONDS_SUBGRAPH = 'https://api.thegraph.com/subgraphs/name/klimadao/klimadao-bonds'
POLYGON_DIGITAL_CARBON_SUBGRAPH = 'https://api.thegraph.com/subgraphs/name/klimadao/polygon-digital-carbon'
Empty file added src/dcm_supply/__init__.py
Empty file.
90 changes: 90 additions & 0 deletions src/dcm_supply/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import os
import math

from discord.ext import tasks
from subgrounds.subgrounds import Subgrounds
from web3.middleware import geth_poa_middleware

from ..utils import (
get_discord_client,
get_polygon_web3,
update_nickname,
update_presence,
get_last_metric,
get_last_carbon,
prettify_number,
get_rebases_per_day,
get_staking_params
)

BOT_TOKEN = os.environ["DISCORD_BOT_TOKEN"]

# Initialized Discord client
client = get_discord_client()

sg = Subgrounds()

# Initialize web3
web3 = get_polygon_web3()
web3.middleware_onion.inject(geth_poa_middleware, layer=0)


def get_info():
last_metric = get_last_metric(sg)
total_carbon = sg.query([last_metric.treasuryCarbon])

last_carbon = get_last_carbon(sg)
current_sma, credit_supply = sg.query(
[last_carbon.creditSMA, last_carbon.creditSupply]
)
return total_carbon, current_sma, credit_supply


@client.event
async def on_ready():
print("Logged in as {0.user}".format(client))
if not update_info.is_running():
update_info.start()


@tasks.loop(seconds=300)
async def update_info():
staking_reward, epoch_length = get_staking_params(web3)
rebases_per_day = get_rebases_per_day(epoch_length)

treasury_carbon, carbon_sma, credit_supply = get_info()

carbon_sma = carbon_sma / 1e18
credit_supply = credit_supply / 1e18

print(treasury_carbon)
print(carbon_sma)
if (
treasury_carbon is not None
and carbon_sma is not None
and rebases_per_day is not None
):
sma_percent = carbon_sma / credit_supply
# ie, annualized reward %
supply_change_annual = math.pow(1 + sma_percent, 365 * rebases_per_day) - 1
else:
return

yield_text = f"{supply_change_annual*100:,.2f}% Δ DCM Supply"
print(yield_text)

success = await update_nickname(client, yield_text)
if not success:
return

presence_txt = f'Total DCM Supply: {prettify_number(credit_supply)}t'
success = await update_presence(
client,
presence_txt,
type='playing'
)
if not success:
return


client.run(BOT_TOKEN)
42 changes: 5 additions & 37 deletions src/staking_rewards/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@
from web3.middleware import geth_poa_middleware
from discord.ext import tasks

from ..constants import DISTRIBUTOR_ADDRESS, SKLIMA_ADDRESS
from ..utils import get_discord_client, get_polygon_web3, load_abi, update_nickname, update_presence

# Hard-coded since Polygon block times have stabilized
AVG_BLOCK_SECS = 2.21
from ..constants import SKLIMA_ADDRESS
from ..utils import get_discord_client, get_polygon_web3, load_abi, \
update_nickname, update_presence, get_rebases_per_day, \
get_staking_params

BOT_TOKEN = os.environ["DISCORD_BOT_TOKEN"]
SCAN_API_KEY = os.environ['POLYGONSCAN_API_KEY']
Expand All @@ -22,29 +21,9 @@
web3.middleware_onion.inject(geth_poa_middleware, layer=0)

# Load ABIs
DISTRIBUTOR_ABI = load_abi('distributor.json')
SKLIMA_ABI = load_abi('sklima.json')


def get_staking_params():
distributor_contract = web3.eth.contract(
address=DISTRIBUTOR_ADDRESS,
abi=DISTRIBUTOR_ABI
)

try:
epoch_length = distributor_contract.functions.epochLength().call()

info = distributor_contract.functions.info(0).call()
reward_rate = info[0]
staking_reward = distributor_contract.functions.nextRewardAt(reward_rate).call()

return staking_reward, epoch_length
except ValueError:
traceback.print_exc()
return None


def get_circ_supply():
sklima_contract = web3.eth.contract(
address=SKLIMA_ADDRESS,
Expand All @@ -58,17 +37,6 @@ def get_circ_supply():
return None


def get_rebases_per_day(blocks_per_rebase):
'''
Calculates the average number of rebases per day based on the average
block production time for the previous 1 million blocks
'''

secs_per_rebase = blocks_per_rebase * AVG_BLOCK_SECS

return 24 / (secs_per_rebase / 60 / 60)


@client.event
async def on_ready():
print('Logged in as {0.user}'.format(client))
Expand All @@ -78,7 +46,7 @@ async def on_ready():

@tasks.loop(seconds=300)
async def update_info():
staking_reward, epoch_length = get_staking_params()
staking_reward, epoch_length = get_staking_params(web3)
circulating_supply = get_circ_supply()

if epoch_length is not None:
Expand Down
44 changes: 43 additions & 1 deletion src/utils.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import os
import traceback

import discord
from discord.ext import commands
import json
from web3 import Web3

from .constants import KLIMA_PROTOCOL_SUBGRAPH
from .constants import KLIMA_PROTOCOL_SUBGRAPH, POLYGON_DIGITAL_CARBON_SUBGRAPH, \
AVG_BLOCK_SECS, DISTRIBUTOR_ADDRESS

PROVIDER_POLYGON_URL = os.environ['WEB3_PROVIDER_POLYGON_URL']
PROVIDER_ETH_URL = os.environ['WEB3_PROVIDER_ETH_URL']
Expand Down Expand Up @@ -95,10 +97,50 @@ def get_last_metric(sg):
return last_metric


def get_last_carbon(sg):
kpm = sg.load_subgraph(POLYGON_DIGITAL_CARBON_SUBGRAPH)

last_carbon = kpm.Query.epoches(
orderBy=kpm.Epoch.epoch, orderDirection='desc', first=1
)

return last_carbon


def prettify_number(number):
num = float('{:.3g}'.format(number))
magnitude = 0
while abs(num) >= 1000:
magnitude += 1
num /= 1000.0
return '{}{}'.format('{:f}'.format(num).rstrip('0').rstrip('.'), ['', 'K', 'M', 'B', 'T'][magnitude])


def get_staking_params(web3):
distributor_contract = web3.eth.contract(
address=DISTRIBUTOR_ADDRESS,
abi=load_abi('distributor.json')
)

try:
epoch_length = distributor_contract.functions.epochLength().call()

info = distributor_contract.functions.info(0).call()
reward_rate = info[0]
staking_reward = distributor_contract.functions.nextRewardAt(reward_rate).call()

return staking_reward, epoch_length
except ValueError:
traceback.print_exc()
return None


def get_rebases_per_day(blocks_per_rebase):
'''
Calculates the average number of rebases per day based on the average
block production time for the previous 1 million blocks
'''

secs_per_rebase = blocks_per_rebase * AVG_BLOCK_SECS

return 24 / (secs_per_rebase / 60 / 60)

0 comments on commit e97a242

Please sign in to comment.