Create A Guess Game On Algorand Using Python.
Create A Guess Game On Algorand Using Python.

By Ddev | Ddev@ALgorand | 23 Jun 2020


f2449f05e724db91a309ba008cf2e3ffcaf07ce4948d8cc8e0b4dd1f03fdaf03.jpeg src

In this solution, you will be able to:

  • Install and write program with Algorand's Python SDK.
  • Connect to Algorand testnet using REST API call. 
  • create a simple guess game using Python and deploy on Algorand blockchain.
  • Learn basis of secure way of programming in Python

To make a guess game, we will need to:

 

I have created a .py  file named guessgame.py which contains all the source code for Guessgame. The program allows a user opt in as a player with the dribbling algorithm as opponent. There can only be a player for our Guessgame who is required to submit an address compatible with underlining protocol at when the program is launched, perhaps an Algorand public key. Usually public key is used in place of wallet address. Player only need to find the winning number  with length equals 7. Winning number is generated using a low-level computation on the value 8[1][2] of type int in account information of the default address. A list of number range is suggested to player to harness the difficulty in guessing. If argument matches winning number, player is sent 100 ALGO as reward.

//guessgame.py


from sendtransaction import defaultAddr, private_key_alc
from algosdk import algod
from algosdk import  transaction
import time, sys, random

# Setup HTTP client w/guest key provided by PureStake
class Connect():
    def __init__(self):
        self.algod_address = "https://testnet-algorand.api.purestake.io/ps1"# declaring the third party API
        self.algod_token = "eVXi2wPlDE8uF15mkil5Z2FzRm20GTJg8r3R7ldv" # <-----shortened - my personal API token
        self.headers = {"X-API-Key": self.algod_token}

    def connectToNetwork(self):       
        # establish connection
        return algod.AlgodClient(self.algod_token, self.algod_address, self.headers)

# Player address and private key for testing
testPlayer = "32KTOUGLIPPEZTJZ4BP423LKXEURMAHK3QRHBZVIJSWPWPQED26GKHPD4Q"
playerKey = "5jCryvD1BE3R0akY48j1++dyMGWwrE97n7kmMizcjAPelTdQy0PeTM054F/NbWq5KRYA6twicOaoTKz7PgQevA=="
# usual algorand wallet for testing purpose
contractAlc = "K5UUTXMOU5CB77UHGEPBTUVKTZYZ37TJHAGYS3VIU2YMO6GGACFNJK4QD4"
toConnect = Connect()
forParam = toConnect.connectToNetwork()
# Get suggeted parameters from the network
params = forParam.suggested_params()
note = "Congratulation, you just won 100 ALGO".encode()

randomSeal = random.randint(int(49799), int(50001))
print("Random seal = {}".format(randomSeal))
winRounds = int(0)
playRound = int(0)
ACTIVE = True 
max_reward = (int(100000000))
  • Ignore the sendtransaction module. "defaultAddr" and "private_key_alc" are imported from same file.
  • Connect() establishes connection to algorand testnet. If would run a node to use goal - the command-line, see guide on how to set up a node. 
  • To test-run, we need a player and private key - lines 17 and 18.
  • From line 24, compiling a transaction requires arbitrary arguments of type dict of which we will request some parameters from the network such as:
    • genesishashb64
    • genesis ID
    • first round
    • last round
    • min fee 
...snippet>

# transfering Algo from one account to another
def payAlgo(senderAddr, rec, prvKey):
    global ACTIVE
    min_pay_1 = int(5000000)
    min_pay_2 = int(2000000)
    if ACTIVE:
        # Get account balance of supposedly contract account
        balance = forParam.account_info(defaultAddr)['amountwithoutpendingrewards']
        check = bool(balance >= (min_pay_1+min_pay_2))
        # transaction parameters
        txn = {
            "sender": senderAddr,
            "receiver": rec,
            "fee": params.get('minFee'),
            "flat_fee": True,
            "amt": max_reward,
            "first": params.get('lastRound'),
            "last": params.get('lastRound') + 1000,
            "note": note,
            "gen": params.get('genesisID'),
            "gh": params.get('genesishashb64')
        }
        # validate token transfer
        if((senderAddr != (defaultAddr or contractAlc)) and ((playRound == int(0)) and winRounds == int(0))):
            if(len(senderAddr) == int(58) and (check == True)):
                ACTIVE = True
                txn["amt"] = min_pay_1
                preTrxn = transaction.PaymentTxn(**txn)
                trxn = preTrxn.sign(prvKey)
                try:
                    return("Transaction was signed with ID : ", forParam.send_transaction(trxn, headers={'content-type': 'application/x-binary'}))
                except Exception as e:
                    print(e)
            elif(playRound > int(0) and winRounds > 0):
                ACTIVE = True
                txn["amt"] = min_pay_2
                preTrxn = transaction.PaymentTxn(**txn)
                trxn = preTrxn.sign(prvKey)
                try:
                    return("Transaction was signed with ID : ", forParam.send_transaction(trxn, headers={'content-type': 'application/x-binary'}))
                except Exception as e:
                    print(e)
        elif(senderAddr == (defaultAddr or contractAlc)):
            preTrxn = transaction.PaymentTxn(**txn)
            trxn = preTrxn.sign(prvKey)
            try:
                return("Transaction was signed with ID : ", forParam.send_transaction(trxn, headers={'content-type': 'application/x-binary'}))
            except Exception as e:
                print(e)

With payAlgo(), Player is allowed to continue after paying minimum fee of 5000000 microAlgos (5 Algo) provided some conditions are true such as playRound and winRounds evaluate to 0. If player is one other than the default or contract address, Amount to send as pass (i.e Txn["amt"]) is set to 5 Algo otherwise, where player has made a guess or more, we want to reduce the pass. And if caller is contract account or any account from which we intend to authorize payment of reward, the reward of 100 Algo is sent to player. This can only go through if player already made the right guess.

 

# A class for all guessgame attributes
class GuessGame():
    """Prototyping Guessgame"""
    def __init__(self):
        self.players = []
        self.alcInfo = forParam.account_info(defaultAddr)
        self.alcdetailList = [self.alcInfo]
        self.threshold = int(self.alcdetailList[0]['thisassettotal']['9604118']['total'])
        self.round = [int((self.alcdetailList[0]['round'] -int(1)) -self.threshold)]
        self.suggestedNumbers = range(self.round[0]-(int(self.threshold) +int(150000)), self.round[0]+randomSeal, randomSeal)
        self.active = False

    # returns a series of suggested numbers where winning number lies 
    def printSuggestedNNumbers(self):
        sug_nums_len = []
        print("Winning numbers is spotted among range : \n")
        for num in self.suggestedNumbers:
            sug_nums_len.append(num)
        print(sug_nums_len)
        print(len(sug_nums_len))

    # function for guessgame
    def guessByRound(self, arg):
        global winRounds
        global playRound
        i = GuessGame()
        i.printSuggestedNNumbers()
        self.luckyNum = self.round[0]
        while ACTIVE:
            player = input("Enter Your Algorand Wallet Address: ")
            key = input("Enter Your Pkey: ")
            keyList = [key]
            # assert(len(player) == 58)
            self.players.append(player)
            guessLists = []
            pay = payAlgo(player, defaultAddr, key)
            time.sleep(int(5))
            if arg != self.luckyNum:
                winRounds = winRounds
                guessLists.append(arg)
                print("Oop! This roll does not match.")
                self.active = self.active
                print("Last guess was: " + str(arg))
            elif arg == self.round[0]:
                self.active = True
                playRound = playRound+int(1)
                winRounds = winRounds+int(1)
                guessLists.append(arg)
                print("Congratulations! You won!" + "\n" + "100 Algo was sent to you.")
                pay = payAlgo(defaultAddr, player, private_key_alc)
                time.sleep(int(5))
                print("You are in the {} round and {} playround.".format(winRounds, playRound))
            print("Do you want to make more guess? '\n'")           
            replay = input("Press 'y' to continue, 'n' to quit: ")
            replay = replay.lower()
            if(replay == "n"):
                self.active = False
                print("That was really tough right?", "\n", "Algorand Blockchain is awesome!.")
                print("Your total balance is {}".format(forParam.account_info(player)['amountwithoutpendingrewards']))
                sys.exit(int(1))
            elif(replay == "y"):
                self.active == True
                continue

toGuess = GuessGame()
d = toGuess.round[0]
m = toGuess.guessByRound(<arg>)

 

Run this code in your editor to see the result. If all things go well as it ought to, player, should receive reward after making the right guess otherwise, the code block terminates and the process is restarted again continuously. 

 

Why Algorand?

ASC1s are Layer-1 smart contracts that automatically enforce custom rules and logic, typically around how assets (Algorand Standard Assets or Algos) can be transferred. They are complex economic relationships made up of basic transaction primitives written in a new language called Transaction Execution Approval Language (TEAL).

There typically three ways you can write smart contract on Algorand. You can write using Python SDK or using Pyteal which is pythonic way of representing Teal programs or directly writing from scratch using Teal opcodes. In the next article, you will learn how to execute transaction using pyteal.

Resources.

Website

Developer

My blog


Ddev
Ddev

I'm a crypto lover, a developer(python, Solidity, Javascript, CSS, HTML), ambassador, blockchain enthusiast and a writer. I am always learning.


Ddev@ALgorand
Ddev@ALgorand

A technology company that built and developed the world’s first open, permissionless, pure proof-of-stake blockchain protocol that, without forking, provides the necessary security, scalability, and decentralization needed for today’s economy. With an award-winning team, we enable traditional finance and decentralized financial businesses to embrace the world of frictionless finance.

Send a $0.01 microtip in crypto to the author, and earn yourself as you read!

20% to author / 80% to me.
We pay the tips from our rewards pool.