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:
- Install Algorand Python SDK (and learn to create your first transaction on Algorand)
- Code editor
- Intermediate knowledge of Python programming
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.