Simple Python Conversion to Algorand

I am working toward converting the logic programmed in Python to PyTeal or Algorand Python. The program is a simple game, where the user pays a specified amount x in the example below 7. If the payment amount is correct, the game generates a random number from 0 to 9. If the number is 7 the user wins 70, else the user wins 0.

I’m consistently running into errors with the PyTeal logic. I’m looking for a base description of the necessary elements of the language, so I can re-write my python script for processing on Algorand. Any suggestions or guidance would be appreciated.

Python Code

import random

# x is the payment recieved by the smart contract
x = 7

# if the amont recieved is equal to 7, the following logic proceeds
if x == 7:
    # one random numbers are generated
    h = random.randint(0,9)
    print(h)

    # Scoring
    a = 0
    if h == 7:
        print('reward = 70')
    else:
        print('better luck next time')

PyTeal

from pyteal import *


# Check if the payment received is equal to 7
Txn.amount() == int(7),

# Generate a pseudo-random number using the round number as a seed
int(0) <= Global.round() % int(10) <= int(9),
if Global.round() % Int(10) == Int(7):
    App.localPut(Int(0), Bytes("h"), int(70))
else:
    App.localPut(Int(0), Bytes("h"), int(0))

# Print the compiled TEAL program
print(compileTeal(program, mode=Mode.Application))

Error

Traceback (most recent call last):
  File "/Users/brianhaney/Desktop/game2.py", line 6, in <module>
    Txn.amount() == int(7),
    ^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/brianhaney/myenv/lib/python3.12/site-packages/pyteal/ast/expr.py", line 67, in __eq__
    return Eq(self, other)
           ^^^^^^^^^^^^^^^
  File "/Users/brianhaney/myenv/lib/python3.12/site-packages/pyteal/ast/binaryexpr.py", line 186, in Eq
    return BinaryExpr(Op.eq, right.type_of(), TealType.uint64, left, right)
                             ^^^^^^^^^^^^^
AttributeError: 'int' object has no attribute 'type_of'
1 Like

As a start, use Int() instead of int(), like Txn.Amount() == Int(7)

2 Likes

Thank you for that; makes sense. I thought it was establishing an int value.

1 Like

Revised Code

from pyteal import *

# Define the TEAL program logic
program = And(
    # Check if the payment received is equal to 7
    Txn.amount() == Int(7),

    # Generate a pseudo-random number using the round number as a seed
    And(Int(0) <= Global.round(), Global.round() <= Int(9)),

    If(Global.round() == Int(7)).Then(
        App.localPut(Int(0), Bytes("h"), Int(70))
    ).Else(
        App.localPut(Int(0), Bytes("h"), Int(0))
    )
)

# Print the compiled TEAL program
print(compileTeal(program, mode=Mode.Application))


New Error

Traceback (most recent call last):
  File "/Users/brianhaney/Desktop/Slot/algo-game/game2.py", line 4, in <module>
    program = And(
              ^^^^
  File "/Users/brianhaney/Desktop/ArbBot/myenv/lib/python3.12/site-packages/pyteal/ast/naryexpr.py", line 106, in And
    return NaryExpr(Op.logic_and, TealType.uint64, TealType.uint64, args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/brianhaney/Desktop/ArbBot/myenv/lib/python3.12/site-packages/pyteal/ast/naryexpr.py", line 29, in __init__
    require_type(arg, inputType)
  File "/Users/brianhaney/Desktop/ArbBot/myenv/lib/python3.12/site-packages/pyteal/types.py", line 38, in require_type
    raise TealTypeError(actual, expected)
pyteal.TealTypeError: TealType.none while expected TealType.uint64
1 Like

Try this:

from pyteal import *

# Define the TEAL program logic
#program = And(
    # Check if the payment received is equal to 7
    ##Txn.amount() == Int(7),

    # Generate a pseudo-random number using the round number as a seed
    ##Int(0) <= Global.round(), Global.round() <= Int(9),
program = Seq(
    If(And(Txn.amount() == Int(7), Int(0) <= Global.round(), Global.round() <= Int(9), Global.round() == Int(7))).Then(
        App.localPut(Int(0), Bytes("h"), Int(70))
    ).Else(
        App.localPut(Int(0), Bytes("h"), Int(0))
    ),
    Return(Int(1))
    )
#)

# Print the compiled TEAL program
print(compileTeal(program, mode=Mode.Application))
2 Likes

Thanks for this. This is what I got out.

#pragma version 2  // Indicates the version of the scripting language being used.

// Check if the transaction amount is equal to 7.
txn Amount         // Retrieve the value of the 'Amount' variable from transaction data.
int 7              // Push the integer value 7 onto the stack.
==                 // Check if the top two values on the stack are equal.

// Check if the global variable 'Round' is less than or equal to 0.
int 0              // Push the integer value 0 onto the stack.
global Round      // Retrieve the value of the global variable 'Round'.
<=                 // Check if the top two values on the stack satisfy the less than or equal to condition.
&&                 // Perform a logical AND operation on the top two values on the stack.

// Check if the global variable 'Round' is less than or equal to 9.
global Round      // Retrieve the value of the global variable 'Round' again.
int 9              // Push the integer value 9 onto the stack.
<=                 // Check if the top two values on the stack satisfy the less than or equal to condition.
&&                 // Perform a logical AND operation on the top two values on the stack.

// Check if the global variable 'Round' is equal to 7.
global Round      // Retrieve the value of the global variable 'Round' again.
int 7              // Push the integer value 7 onto the stack.
==                 // Check if the top two values on the stack are equal.
&&                 // Perform a logical AND operation on the top two values on the stack.

// Branch to 'main_l2' if the previous conditions are met.
bnz main_l2

// If the conditions are not met, execute the following instructions:
int 0              // Push the integer value 0 onto the stack.
byte "h"           // Push the ASCII character 'h' onto the stack.
int 0              // Push the integer value 0 onto the stack.
app_local_put      // Store the character 'h' in the local application storage.

// Unconditional branch to 'main_l3'.
b main_l3

// Label 'main_l2' - executed if the conditions are met.
main_l2:
int 0              // Push the integer value 0 onto the stack.
byte "h"           // Push the ASCII character 'h' onto the stack.
int 70             // Push the integer value 70 onto the stack.
app_local_put      // Store the character 'h' in the local application storage.

// Label 'main_l3' - executed after 'main_l2' or unconditionally.
main_l3:
int 1              // Push the integer value 1 onto the stack.
return             // Return from the script.

1 Like

Super. Congractulations.

Now comes the real task.

You must decide, what to use: “smart signatures” (not recommended) or smart contracts, i.e. Algorand apps. As for me, I find smart signatures much-much easier, but these are very limited (stateless).

You must also decide to use Beaker, or remain on PyTeal level.

OR: you can try TealScript as a completely different approach. @joe-p has a TealScript video series in
youtube.com/@algodevs I recommend you to try this.

I’m watching the course now. I want to create an Algorand app for the logic.

For beaker, PyTeal, or TealScript. I am struggling through them to understand their purpose.

For the logic you provided:

program = Seq(
    If(And(Txn.amount() == Int(7), Int(0) <= Global.round(), Global.round() <= Int(9), Global.round() == Int(7))).Then(
        App.localPut(Int(0), Bytes("h"), Int(70))
    ).Else(
        App.localPut(Int(0), Bytes("h"), Int(0))
    ),
    Return(Int(1))
    )

Can you explain where the random number is generated? I am not understand the Int(x) syntax or the Global.round() syntax.

Thanks again.

1 Like

The Global.round() gives you back the actual round when the last block was created. It is NOT random at all, I thought you want to use it only for test purposes. Of course, it should be reduced to a number between 0 and 9 by getting the remainer, i.e. using Mod(Global.round(), Int(10))

The Int(x) syntax is used to signal the pyteal that it is not a Python type, but a Teal type. The 2 most common types are Int() and Byte() as I remember. It could be VERY disturbing that the Python is sometimes run to execute normal code, sometypes used to generate TEAL (AVM) code. With TealScript there is no such “double” role, and double operation.

Beaker: an onion layer to abstart away Algorand apps as object
PyTeal: an onion layer to abstart TEAL with more structure (If Then Else, etc.)
Tealscript: everything in one place! It is useful if you know a little typescript.

Layers:
AVM
TEAL
PyTeal
Beaker
Front-end, like React

Instead of PyTeal and Beaker you could use Tealscript.

I suggest you to try to repeat the steps of the video course.
Any questions are welcome. (If I don’t know something, I will relay ypour question to Joe Polny :slight_smile: )

1 Like

Thank you. I tried repeating the steps in the video, but the current version of the software is different than the video. One of the main problems I ran into is all the setup processes, which make it difficult to actually build.

I am not understanding what you mean regarding the global spaces and the random numbers. The goal is to get this simple Python logic operating on the blockchain in an App:

import random

# x is the payment recieved by the smart contract
x = 7

# if the amont recieved is equal to 7, the following logic proceeds
if x == 7:
    # one random numbers are generated
    h = random.randint(0,9)
    print(h)

    # Scoring
    a = 0
    if h == 7:
        print('reward = 70')
    else:
        print('better luck next time')

Basically, to start, all that has to happen is:

  1. Check to see if the transaction value is equal to x.
  2. Generate a random number.
  3. Check to see if the random number is equal to y.
  4. If the random number is equal to y, send reward.
1 Like

I have been hacking at this for a while without much luck. So, I want to simplify the problem. All I need is the script to generate a random number from 0 - 9. For example, Python has the random module, so I can write:

h = random.randint(0,9)

I need something similar that can be deployed in an Algorand application. I know there is a lot of writing about VRF, but do they have the capability of performing basic operations necessary for real use? How can I write this Python code to be processed in TEAL?

1 Like

OK. First of all, about the method of getting a random value on the blockchain, please see this article: Usage and Best Practices for Randomness Beacon.

A Google search shows that Applied Blockchain made the beacon for the Foundation. This is the source: https://github.com/appliedblockchain/algorand-randomness-beacon

So now you can repeat the brave and excellent work of Jean-François Champollion who deciphered the Egyptian hieroglyphs :slight_smile: Please do post your results when you succeed!

1 Like

More seriously: there will be Python and TealScript bootcamps soon, see https://www.algorand.foundation/events I think there you can pose your questions, too…

1 Like

All the setup is EASY when using codespace:

pipx install algokit
algokit localnet start
docker ps
# before "algokit explore" make ports public on the "Ports" tab
algokit explore
# to try out the localnet environment
1 Like