-
-
Save Reecepbcups/4bdc9c5df2f4c366b47a7be1ebb5e378 to your computer and use it in GitHub Desktop.
Simple MintEXP webapp logic for CraftEconomy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#/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