Skip to content

Instantly share code, notes, and snippets.

@Reecepbcups
Last active March 5, 2022 06:58
Show Gist options
  • Save Reecepbcups/4bdc9c5df2f4c366b47a7be1ebb5e378 to your computer and use it in GitHub Desktop.
Save Reecepbcups/4bdc9c5df2f4c366b47a7be1ebb5e378 to your computer and use it in GitHub Desktop.
Simple MintEXP webapp logic for CraftEconomy
#/usr/bin/python3
import datetime
import dateutil.parser as dp # parse iso to epoch seconds
'''
Reece Williams | Reecepbcups - March 4th, 2022
- CraftEconomy MintEXP POC
Has some passed proposals in relation to our custom RequestEXPProposal type
When someone request in the webapp to mint, we search through to check if their:
- Wallet is whitelisted
- Pool is still open from that proposal
if either of these are false, the user can not mint EXP
if both are true, we stop looking for more proposals and allow the user to mint EXP
'''
listOfProposals = [
{ # passed for craft1234 to mint EXP
"proposal_id": "1",
"content": {
"@type": "/cosmos.gov.v1beta1.RequestEXPProposal",
"title": "I want to be in the DAO",
"description": "Blah blah desc",
"walletToBeWhitelisted": "craft1234",
"depositAssets": ['BTC', 'ETH', 'ATOM', 'JUNO'],
"maxMintableExp": 5000,
"closePoolDate": "2023-01-01T00:00:00Z",
"vestingPeriodEnd": "2025-01-01T00:00:00Z",
},
"status": "PROPOSAL_STATUS_PASSED",
"final_tally_result": {
"yes": "173108681300321",
"abstain": "0",
"no": "0",
"no_with_veto": "0"
},
"submit_time": "2022-02-14T21:58:11.145504429Z",
"deposit_end_time": "2022-02-16T21:58:11.145504429Z",
"total_deposit": [
{
"denom": "ucraft",
"amount": "10000000000"
}
],
"voting_start_time": "2022-02-14T21:58:11.145504429Z",
"voting_end_time": "2022-02-16T21:58:11.145504429Z"
},
{ # denied for craftxxxx to mint EXP
"proposal_id": "2",
"content": {
"@type": "/cosmos.gov.v1beta1.TextProposal",
"title": "When airdrop?",
"description": "Deny me",
"walletToBeWhitelisted": "craftxxxx",
"depositAssets": ['MOM'],
"maxMintableExp": 1000,
"closePoolDate": "2023-01-01T00:00:00Z",
"vestingPeriodEnd": "2025-01-01T00:00:00Z",
},
"status": "PROPOSAL_STATUS_REJECTED",
"final_tally_result": {
"yes": "173108681300321",
"abstain": "0",
"no": "0",
"no_with_veto": "0"
},
"submit_time": "2022-02-14T21:58:11.145504429Z",
"deposit_end_time": "2022-02-16T21:58:11.145504429Z",
"total_deposit": [
{
"denom": "ucraft",
"amount": "10000000000"
}
],
"voting_start_time": "2022-02-14T21:58:11.145504429Z",
"voting_end_time": "2022-02-16T21:58:11.145504429Z"
},
]
# would be via CoinGecko API
prices = {"BTC": 50000, "ETH": 5000, "ATOM": 30, "JUNO": 40}
# example single wallet, this would be a CRAFT wallet
reecesWalletHeldEXP = 0
class DAO:
exp_supply = 300_000 # get from blockchain lcd /cosmos/bank/supply?denom=exp
nav = 0
held_assets = { # This would be done by querying DAO's wallets
"BTC": 5,
"ETH": 10,
}
# opens webapp crafteconomy.io/mint
# Buttons "Mint EXP" and "Burn EXP" are shown
# User clicks Mint EXP, Requires keplr to connect, grabs their CRAFT address
# then:
def main(): # this is webapp logic
yourKeplrAddress = "craft1234"
hasPermission = False
# Loop through proposals
for proposal in listOfProposals:
if proposal['content']['@type'] != "/cosmos.gov.v1beta1.RequestEXPProposal":
continue # if it is not RequestEXPProposal, check next
if proposal['content']['walletToBeWhitelisted'] != yourKeplrAddress:
continue # if their wallet is not whitelisted, next
if proposal['status'] != "PROPOSAL_STATUS_PASSED":
continue # if not passed yet, next
currentTime = datetime.datetime.now().timestamp() # EPOCH time in seconds
closePoolTime = dp.parse(proposal['content']['closePoolDate']).timestamp()
# if now is past closePoolTime, theyir pool time is closed, check next proposal to see if they have an updated time proposal
if currentTime > closePoolTime:
print("This proposals pool is closed now since it was in the past " + str(proposal['content']['closePoolDate']))
continue
else:
print(f"Your Pool is open for another {secondsToDays(closePoolTime - currentTime)} days")
# They have a prop which passed & their whitelisted to mint EXP
# Could add check here to ensure they have not already minted MaxEXP for this proposals whitelistedWallet
hasPermission = True
break
if hasPermission:
mintExpScreen(proposal)
else:
print(f"no proposals passed for your account {yourKeplrAddress}. ")
def mintExpScreen(proposal):
global prices
print("Mint EXP Screen here since " + proposal['content']['walletToBeWhitelisted'] + " has permission & pool is still open")
assetsTheyCanMint = proposal['content']['depositAssets']
maxMintableExp = int(proposal['content']['maxMintableExp'])
# just doing BTC as default for testing
# while True: # check user is allowed to deposit this
# asset = input(f"\nWhat asset do you want to mint {assetsTheyCanMint}? ").upper()
# if asset in assetsTheyCanMint:
# break
# while True:
# # show EXP exchange rate
# amount = input("How much EXP Do you want to mint? ")
# try:
# amount = int(amount)
# break
# except:
# pass
# print(f"\nMinting {amount} EXP @ RATE for {asset}")
# EXP = $1 still since no prices have moved, just deposited @ current market rates.
depositToDAO('BTC', 0.05, maxMintableExp)
# Assume EXP price has gone up by 10%, since DAO holds ETH too, its not a linear correlation
# prices['BTC'] *= 1.1
# print("\nBTC PRICE INCREASE OF 10%")
# deposit at new rate, if BTC price increases, EXP deposit rate would change thus
# causing the user to have deposited too much provided maxDeposit for EXP is 5000 in this example.
# so BTC deposit rate will show as needing to be 0.485BTC deposit
depositToDAO('BTC', 0.05, maxMintableExp)
def depositToDAO(asset, amount, maxDepositRateFromProposal):
global reecesWalletHeldEXP
depositRate = getAssetDepositRate(asset, amount) # Whole asset deposit rate
print(f"\nDepositing {amount} {asset} to DAO for {depositRate}EXP (1 {asset} = {getAssetDepositRate(asset, 1)}EXP)\n")
if asset not in dao.held_assets:
print("The DAO does not hold this asset")
return
# if their totalEXP + current ask > what they can mint max, stop it & let them know the max asset they can deposit
if (reecesWalletHeldEXP+depositRate) > maxDepositRateFromProposal:
print(f"This request would bypass your max deposit rate of {maxDepositRateFromProposal}EXP")
# gets the max amount of EXP they can deposit for their asset requested into the pool.
# ex: I try to deposit 1BTC, but that would be 50k exp, if I can only mint 25k exp, it will tell me max I can deposit is 0.5BTC
maxDeposit = amount - ((((reecesWalletHeldEXP+depositRate) - maxDepositRateFromProposal)*getExpPrice()) / getAssetDepositRate(asset, 1))
print(f"The max you can deposit is {maxDeposit} {asset}")
return
print(f"DAO currently holds {dao.held_assets[asset]} {asset}")
dao.held_assets[asset] += amount
dao.exp_supply += depositRate
print(f"DAO now holds {dao.held_assets[asset]} {asset} thanks to your deposit of {amount}")
print(f"DAO NAV is now ${round(getNAV(), 2):,.2f}")
print(f"EXP price is now ${getExpPrice():,.2f}")
# Give user EXP, done via TokenFaucet (:4500, whitelist only to our (dao's) machines)
print(f"You have minted {depositRate:,} EXP")
reecesWalletHeldEXP += depositRate
print(f"Your Total EXP held: {reecesWalletHeldEXP:,} is valued @ ${reecesWalletHeldEXP*getExpPrice():,.2f}")
def getNAV():
'''Get value of wallets DAO holds'''
temp = 0
for asset in dao.held_assets:
temp += (dao.held_assets[asset] * coinGekoGetAssetPrice(asset))
dao.nav = temp
return dao.nav
def getExpPrice():
# print(f"Getting EXP price with {dao.nav} NAV & {dao.exp_supply} EXP supply")
return round(getNAV()/dao.exp_supply, 2)
def coinGekoGetAssetPrice(asset):
return prices[asset]
def getAssetDepositRate(asset, amount=1):
return round((coinGekoGetAssetPrice(asset) / getExpPrice()) * amount, 4)
def secondsToDays(seconds):
return round(seconds/86400, 2)
if __name__ == '__main__':
dao = DAO()
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment