Logical Functionality in AlgoKit

I am working on creating a basic application in AlgoKit. Here is the demo file.

# Sample Hello World Beaker smart contract - the most basic starting point for an Algorand smart contract
import beaker
import pyteal as pt

app = beaker.Application("HelloWorldApp")


@app.external
def hello(name: pt.abi.String, *, output: pt.abi.String) -> pt.Expr:
    return output.set(pt.Concat(pt.Bytes("Hello, "), name.get()))

I want to write a program that:

  1. Receives and ASA
  2. Generates a random number
  3. If the number is X, returns Y.
  4. If the number is Z, returns U.

I can do this in Python using an if statement and the random module. But, I don’t know where to start for doing this in PyTeal. Any advice or suggestions would be appreciated. The problem is how edit the demo file to have functionality beyond return Hello World. For example, how can one edit the file for a conditional if statement?

Here is an example.

# Sample Hello World Beaker smart contract - the most basic starting point for an Algorand smart contract
import beaker
import pyteal as pt
import random

app = beaker.Application("RandomNumberApp")

@app.external
def random_number(*, output: pt.abi.String) -> pt.Expr:
    # Generate a random number between 1 and 10
    number = random.randint(1, 10)
    # Define the conditions and corresponding actions
    # If the number is X, return Y
    # If the number is Z, return U
    # Otherwise, return an error message
    return pt.If(
        pt.Eq(number, 7),  # Replace X with your desired value
        output.set(pt.Bytes("7")),  # Replace Y with your desired value
        pt.If(
            pt.Eq(number, 6),  # Replace Z with your desired value
            output.set(pt.Bytes("6")),  # Replace U with your desired value
            output.set(pt.Bytes("Invalid number"))
        )
    )

I’m still not understanding how to effectively run this. One additional question is how to effectively write PyTEAL to send an arbitrary ASA from Alice to Bob. The Docs have an example of an atomic swap, but no simple transaction functions.

# This example is provided for informational purposes only and has not been audited for security.

from pyteal import *

"""Atomic Swap"""

alice = Addr("6ZHGHH5Z5CTPCF5WCESXMGRSVK7QJETR63M3NY5FJCUYDHO57VTCMJOBGY")
bob = Addr("7Z5PWO2C6LFNQFGHWKSK5H47IQP5OJW2M3HA2QPXTY3WTNP5NU2MHBW27M")
secret = Bytes("base32", "2323232323232323")
timeout = 3000


def htlc(
    tmpl_seller=alice,
    tmpl_buyer=bob,
    tmpl_fee=1000,
    tmpl_secret=secret,
    tmpl_hash_fn=Sha256,
    tmpl_timeout=timeout,
):
    fee_cond = Txn.fee() < Int(tmpl_fee)
    safety_cond = And(
        Txn.type_enum() == TxnType.Payment,
        Txn.close_remainder_to() == Global.zero_address(),
        Txn.rekey_to() == Global.zero_address(),
    )

    recv_cond = And(Txn.receiver() == tmpl_seller, tmpl_hash_fn(Arg(0)) == tmpl_secret)

    esc_cond = And(Txn.receiver() == tmpl_buyer, Txn.first_valid() > Int(tmpl_timeout))

    return And(fee_cond, safety_cond, Or(recv_cond, esc_cond))


if __name__ == "__main__":
    print(compileTeal(htlc(), mode=Mode.Signature, version=2))

Rather than an atomic swap, how can Alice send Bob 5.00 USDC?

Here’s an example.

from pyteal import *

def approval_program():
    on_payment = And(
        Txn.type_enum() == TxnType.Payment,
        Txn.receiver() == Addr("ALICE_ADDRESS")
    )

    transfer_usdc = Seq([
        App.localPut(Int(0), Bytes("sent"), Int(1)),
        App.localPut(Int(0), Bytes("amount"), Int(500)),
        App.localPut(Int(0), Bytes("token"), Int(31566704)),
        App.localPut(Int(0), Bytes("recipient"), Addr("BOB_ADDRESS")),
        Return(Int(1))
    ])

    program = Cond(
        [on_payment, transfer_usdc],
        [Txn.application_id() == Int(0), Return(Int(1))],
        [Txn.application_id() != Int(0), Return(App.localGet(Int(0), Bytes("sent")))]
    )

    return program

def clear_program():
    return Return(Int(1))

# Compile the smart contract
approval_teal = compileTeal(approval_program(), mode=Mode.Application)
clear_teal = compileTeal(clear_program(), mode=Mode.Application)

# Print the compiled TEAL code
print("Approval Program:")
print(approval_teal)

print("Clear Program:")
print(clear_teal)

Here is the updated code.

# Sample Hello World Beaker smart contract - the most basic starting point for an Algorand smart contract
import beaker
import pyteal as pt
import random

app = beaker.Application("RandomNumberApp")

@app.external

def approval_program():
    on_payment = And(
        Txn.type_enum() == TxnType.Payment,
        Txn.receiver() == Addr("ALICE_ADDRESS")
    )

    transfer_usdc = Seq([
        App.localPut(Int(0), Bytes("sent"), Int(1)),
        App.localPut(Int(0), Bytes("amount"), Int(5)),
        App.localPut(Int(0), Bytes("token"), Int(31566704)),
        App.localPut(Int(0), Bytes("recipient"), Addr("BOB_ADDRESS")),
        Return(Int(1))
    ])

    program = Cond(
        [on_payment, transfer_usdc],
        [Txn.application_id() == Int(0), Return(Int(1))],
        [Txn.application_id() != Int(0), Return(App.localGet(Int(0), Bytes("sent")))]
    )

    return program

# Compile the smart contract
approval_teal = compileTeal(approval_program(), mode=Mode.Application)


# Print the compiled TEAL code
print("Approval Program:")
print(approval_teal)


def random_number(*, output: pt.abi.String) -> pt.Expr:
    # Generate a random number between 1 and 10
    number = random.randint(1, 10)
    # Define the conditions and corresponding actions
    # If the number is X, return Y
    # If the number is Z, return U
    # Otherwise, return an error message
    return pt.If(
        pt.Eq(number, 7),  # Replace X with your desired value
        output.set(pt.Bytes("7")),  # Replace Y with your desired value
        pt.If(
            pt.Eq(number, 6),  # Replace Z with your desired value
            output.set(pt.Bytes("6")),  # Replace U with your desired value
            output.set(pt.Bytes("Invalid number"))
        )
    )


The next step is how to condense this. Ultimately, the application should work the same way as the demo game, which was written in JS.

A problem is how to deploy the smart contract, then have the front end communicate with the smart contract directly. It seems these two things could be done separately, where the smart contract is deployed first, then react front-end is deployed via another mechanism.

It seems there are a couple of misunderstandings about how smart contract development with PyTeal works. I recommend checking out the YouTube playlists on getting started with PyTeal and Beaker

2 Likes

May I suggest few new videos on how to use the randomness onchain?

In my mind it comes these usecases

  • using random beacon
  • using zero knowledge proofs
  • using encrypted data storage with decryption after some action

Videos are clear. Will keep hacking.

What is the mechanism by which a wallet connect in a front end can engage with the on-chain application? For example, user connects there wallet and sends 1 USDC via the front-end. What is the programatic system for calling the application?

Use this to sign any transaction that you compose in the frontend… GitHub - TxnLab/use-wallet: React library for integrating multiple Algorand wallets with your decentralized applications (dApps)

Thanks. I already have a mechanism for sending transactions. What I’m looking for is a way to connect the frontend to the application on-chain.

Yes, you need mechanism to sign transactions by users… That’s what the use-wallet library is for… Then you can send signed txs to the blockchain

I have signing too. I need the code to send the transaction to the smart contract. I guess that would just be something like:

/////////////////////////
const vote_transaction = async () => {
  try{
    const suggestedParams = await algodClient.getTransactionParams().do();
    const txn = algosdk.makeAssetTransferTxnWithSuggestedParamsFromObject({
      from: address,
      /////// TO APPLICATION ID
      to: Application_ID,
      amount: 1000000,
      assetIndex: ASSET_ID,
      suggestedParams,
    });
    const optInTxn = [{txn : txn, signers: [address]}]
    const signedTxn = await deflywallet.signTransaction([optInTxn])
    const success = await algodClient.sendRawTransaction(signedTxn).do();
    return success
  }
  catch(err){
    console.log(err)
    return false
  }
  }

Here is an MVE for the logic I want to program.

# On Chain Application
# # If application receives 0.01 USDC from sender
# # Generate a random number 0 or 1
# # If the random number is 0
# # # Then send the sender 0.02 USDC
# # If the random number is 1
# # # Then nothing

import random
@router.method
def slot():
    return Seq(
        lucky_number = random.randint(0,1)
        if lucky_number > 0:
            # Print lucky_number
        else:
            # Print lucky_number
            # Send transaction to sender.

    )

A couple problems. 1) Is it possible to use the random module in PyTeal? 2) Why is there a severance of the demo.py file and the app.py file in AlgoKit?

New code from chatGPT.

from pyteal import *

def on_chain_application():
    # Check if the transaction is a payment transaction
    on_payment = Txn.type_enum() == TxnType.Payment
    
    # Check if the transaction amount is 0.01 USDC
    amount_check = Txn.amount() == Int(1000000)
    
    # Generate a random number
    random_number = App.localGet(Int(0), Bytes("random_number"))
    random_number_exists = random_number.hasValue()
    generate_random_number = random_number.exists() == Int(0)
    
    # Set the random number if it doesn't exist
    set_random_number = Seq([
        App.localPut(Int(0), Bytes("random_number"), Btoi(Sha256(Arg(0)))),
        Return(Int(1))
    ])
    
    # If the random number is 0, send 0.02 USDC back to the sender
    send_usdc = Seq([
        App.localPut(Int(0), Bytes("random_number"), Int(0)),
        Return(Int(1))
    ])
    
    # If the random number is 1, do nothing
    do_nothing = Return(Int(1))
    
    program = Cond(
        [on_payment & amount_check & random_number_exists, do_nothing],
        [on_payment & amount_check & generate_random_number, set_random_number],
        [on_payment & amount_check & random_number.eq(Int(0)), send_usdc]
    )
    
    return program

if __name__ == "__main__":
    print(compileTeal(on_chain_application(), mode=Mode.Application))

Ongoing questions.

  1. How do you set an asset ID for PyTeal?
  2. What is the mechanism for deploying to MainNet?