Pārlūkot izejas kodu

First pass at new version of rollcoin

Kirk Trombley 3 gadi atpakaļ
vecāks
revīzija
d3ef198007
1 mainītis faili ar 118 papildinājumiem un 0 dzēšanām
  1. 118 0
      commands/commands/rollcoin.py

+ 118 - 0
commands/commands/rollcoin.py

@@ -0,0 +1,118 @@
+from dataclasses import dataclass, field
+from typing import Optional
+
+from rollbot import as_command, initialize_data, RollbotFailure
+from rollbot.injection import Data, Sender, Config, Const, Arg
+
+# View
+#   !wallet - shows your number of rollcoins, NFTs (Non-Functional Tamagotchis), and market balance
+#   !blockchain - shows the contents of all wallets and the rollcoins in the treasury
+# Generate
+#   !mine - provides a sudoku that can be solved for rollcoins, which also adds to the treasury
+#   !appraise - rollbot will purchase a post, based indirectly on number of likes received
+# Spend
+#   !tip - transfer rollcoins from one person to another
+#   !gacha - insert a rollcoin (which enters the treasury), receive a random NFT
+#   !donate - split an amount and donate it to everyone
+#   !bet - put some amount of rollcoins into the market, some portion of which will be put in the treasury, evolves market
+#   !cash - take some amount of rollcoins from the market, up to investment + the number of coins in the treasury, evolves market
+# Admin
+#   !deflate - deflate all coins by a power of 10
+#   !brrr - print some number of coins into the treasury
+#   !mine !clear - clear the current mining puzzle
+#   !market !force - force the market to transition to a given state
+
+
+@initialize_data
+@dataclass
+class RollcoinState:
+    treasury: float
+    mining_puzzle: Optional[list[list[int]]]
+    market_state: int
+
+
+@initialize_data
+@dataclass
+class RollcoinWallet:
+    balance: float = 1
+    invested: float = 0
+    investment_value: float = 0
+    nfts: list[str] = field(default_factory=list)
+
+    def __str__(self):
+        s = f"Wallet: {self.balance} RollCoins\n"
+        if self.invested > 0 or self.investment_value > 0:
+            s += f"Invested: {self.investment_value} RollCoins (cost basis {self.invested})\n"
+        if len(self.nfts) > 0:
+            s += f"NFTs:\n"
+        for nft in self.nfts:
+            s += f"\t{nft}\n"
+        return s.strip()
+
+
+SPECIAL_AMOUNTS = {
+    "all": lambda limit: limit,
+    "half": lambda limit: limit / 2,
+    "frac": lambda limit: limit - int(limit),
+}
+
+
+def convert_amount(amount):
+    if (conv := SPECIAL_AMOUNTS.get(amount.lower(), None)) is not None:
+        return conv
+    return float(amount)
+
+
+# injection values
+State = Data(RollcoinState).For(Const("ROLLCOIN_GLOBAL_STATE"), treasury=100, mining_puzzle=None, market_state=0)
+SenderWallet = Data(RollcoinWallet).For(Sender)
+WalletLookup = Config("rollcoin.wallet_names")
+
+
+@as_command
+def wallet(sender_wallet: SenderWallet):
+    return f"You currently own...\n{sender_wallet}"
+
+
+@as_command
+async def blockchain(wallets: Data(RollcoinWallet), wallet_lookup: WalletLookup, state: State):
+    response = f"Blockchain:\n\tTreasury contains {state.treasury} RollCoins\n\n"
+    names = {v: k.title() for k, v in wallet_lookup.items()}
+    async for (sender_id, wallet) in wallets.all():
+        response += names.get(sender_id, f"Unnamed wallet {sender_id}") + ":\n"
+        response += "\n".join("\t" + s for s in str(wallet).split("\n")) + "\n\n"
+    return response.strip()
+
+
+@as_command
+async def tip(
+    wallets: Data(RollcoinWallet),
+    sender_id: Sender, 
+    sender_wallet: SenderWallet, 
+    wallet_lookup: WalletLookup, 
+    target_name: Arg(0, missing_msg="You must tell me who to tip!"), 
+    amount: Arg(1, convert=convert_amount, missing_msg="You must provide an amount to tip!", fail_msg="Could not parse {} as value"),
+):
+    if not isinstance(amount, float):
+        # handle special converters
+        amount = amount(sender_wallet.balance)
+    
+    if amount < 0:
+        RollbotFailure.INVALID_ARGUMENTS.raise_exc(f"Amount must be positive, not {amount}")
+
+    if amount == 0:
+        return "Sorry! You don't have any rollcoins right now - try mining!"
+
+    if amount > sender_wallet.balance:
+        return f"Sorry! You only have {sender_wallet.balance} RollCoins available - try mining for more!"
+    
+    if (target_id := wallet_lookup.get(target_name.lower(), None)) is None:
+        RollbotFailure.INVALID_ARGUMENTS.raise_exc(f"Cannot find wallet belonging to {target_name}")
+    
+    target_wallet = await wallets.load_or(target_id)
+    sender_wallet.balance -= amount
+    target_wallet.balance += amount
+    await wallets.save(target_id, target_wallet)
+    await wallets.save(sender_id, sender_wallet)
+
+    return f"Done! {target_name} now has {target_wallet.balance} RollCoins!"