Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update examples.rst #640

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 47 additions & 35 deletions docs/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,43 +5,13 @@ PyTeal Examples

Here are some additional PyTeal example programs:

Signature Mode
--------------

Atomic Swap
~~~~~~~~~~~~~~~

*Atomic Swap* allows the transfer of Algos from a buyer to a seller in exchange for a good or
service. This is done using a *Hashed Time Locked Contract*. In this scheme, the buyer funds a
TEAL account with the sale price. The buyer also picks a secret value and encodes a secure hash of
this value in the TEAL program. The TEAL program will transfer its balance to the seller if the
seller is able to provide the secret value that corresponds to the hash in the program. When the
seller renders the good or service to the buyer, the buyer discloses the secret from the program.
The seller can immediately verify the secret and withdraw the payment.

.. literalinclude:: ../examples/signature/atomic_swap.py
:language: python
Currently, the majority of dApps do use application mode for signing and verifying transactions on the blockchain.
This is because application mode allows for a more user-friendly experience and can be integrated more easily into web and mobile interfaces.
Additionally, it allows dApps to handle the signing process on behalf of the user, which can simplify the process for non-technical users.

Split Payment
~~~~~~~~~~~~~
In application mode, the dApp can handle the private key storage and signing process, so users do not need to manage their own private keys or use additional hardware wallets.
This can make the process of using the dApp more convenient for users, as they do not need to worry about managing their own private keys.

*Split Payment* splits payment between :code:`tmpl_rcv1` and :code:`tmpl_rcv2` on the ratio of
:code:`tmpl_ratn / tmpl_ratd`.

.. literalinclude:: ../examples/signature/split.py
:language: python

Periodic Payment
~~~~~~~~~~~~~~~~

*Periodic Payment* allows some account to execute periodic withdrawal of funds. This PyTeal program
creates an contract account that allows :code:`tmpl_rcv` to withdraw :code:`tmpl_amt` every
:code:`tmpl_period` rounds for :code:`tmpl_dur` after every multiple of :code:`tmpl_period`.

After :code:`tmpl_timeout`, all remaining funds in the escrow are available to :code:`tmpl_rcv`.

.. literalinclude:: ../examples/signature/periodic_payment.py
:language: python

Application Mode
----------------
Expand Down Expand Up @@ -161,3 +131,45 @@ receiver's account does not have a maximum balance restriction that would be inv

.. literalinclude:: ../examples/application/security_token.py
:language: python





Signature Mode
--------------

Atomic Swap
~~~~~~~~~~~~~~~

*Atomic Swap* allows the transfer of Algos from a buyer to a seller in exchange for a good or
service. This is done using a *Hashed Time Locked Contract*. In this scheme, the buyer funds a
TEAL account with the sale price. The buyer also picks a secret value and encodes a secure hash of
this value in the TEAL program. The TEAL program will transfer its balance to the seller if the
seller is able to provide the secret value that corresponds to the hash in the program. When the
seller renders the good or service to the buyer, the buyer discloses the secret from the program.
The seller can immediately verify the secret and withdraw the payment.

.. literalinclude:: ../examples/signature/atomic_swap.py
:language: python

Split Payment
~~~~~~~~~~~~~

*Split Payment* splits payment between :code:`tmpl_rcv1` and :code:`tmpl_rcv2` on the ratio of
:code:`tmpl_ratn / tmpl_ratd`.

.. literalinclude:: ../examples/signature/split.py
:language: python

Periodic Payment
~~~~~~~~~~~~~~~~

*Periodic Payment* allows some account to execute periodic withdrawal of funds. This PyTeal program
creates an contract account that allows :code:`tmpl_rcv` to withdraw :code:`tmpl_amt` every
:code:`tmpl_period` rounds for :code:`tmpl_dur` after every multiple of :code:`tmpl_period`.

After :code:`tmpl_timeout`, all remaining funds in the escrow are available to :code:`tmpl_rcv`.

.. literalinclude:: ../examples/signature/periodic_payment.py
:language: python
84 changes: 23 additions & 61 deletions examples/signature/periodic_payment_deploy.py
Original file line number Diff line number Diff line change
@@ -1,79 +1,41 @@
#!/usr/bin/env python3

import base64
import params
import uuid

from algosdk import algod, transaction, account, mnemonic
from periodic_payment import periodic_payment

from algosdk import algod, account, mnemonic, transaction
from algosdk.future import template
from pyteal import *

# --------- compile & send transaction using Goal and Python SDK ----------

# Compile and sign the smart contract
teal_source = compileTeal(periodic_payment(), mode=Mode.Signature, version=2)
compiled = compileProgram(teal_source)

# compile teal
teal_file = str(uuid.uuid4()) + ".teal"
with open(teal_file, "w+") as f:
f.write(teal_source)
lsig_fname = str(uuid.uuid4()) + ".tealc"

stdout, stderr = execute(["goal", "clerk", "compile", "-o", lsig_fname, teal_file])

if stderr != "":
print(stderr)
raise
elif len(stdout) < 59:
print("error in compile teal")
raise

with open(lsig_fname, "rb") as f:
teal_bytes = f.read()
lsig = transaction.LogicSig(teal_bytes)

# create algod clients
acl = algod.AlgodClient(params.algod_token, params.algod_address)
# Create an Algod client
acl = algod.AlgodClient(
algod_token="YOUR_ALGOD_TOKEN", algod_address="YOUR_ALGOD_ADDRESS"
)

# Recover the account that is wanting to delegate signature
passphrase = "patrol crawl rule faculty enemy sick reveal embody trumpet win shy zero ill draw swim excuse tongue under exact baby moral kite spring absent double"
sk = mnemonic.to_private_key(passphrase)
addr = account.address_from_private_key(sk)
print("Dispense at least 201000 microAlgo to {}".format(addr))
input("Make sure you did that. Press Enter to continue...")

# sign the logic signature with an account sk
lsig.sign(sk)

# get suggested parameters
# Get suggested parameters for the transaction
params = acl.suggested_params()
gen = params["genesisID"]
gh = params["genesishashb64"]
startRound = params["lastRound"] - (params["lastRound"] % 1000)
endRound = startRound + 1000
fee = 1000
amount = 200000
receiver = "ZZAF5ARA4MEC5PVDOP64JM5O5MQST63Q2KOY2FLYFLXXD3PFSNJJBYAFZM"
lease = base64.b64decode("y9OJ5MRLCHQj8GqbikAUKMBI7hom+SOj8dlopNdNHXI=")

# create a transaction
txn = transaction.PaymentTxn(
addr, fee, startRound, endRound, gh, receiver, amount, flat_fee=True, lease=lease
)
params.flat_fee = True
params.fee = 1000

# Create the LogicSigTransaction with contract account LogicSig
lstx = transaction.LogicSigTransaction(txn, lsig)
# Create the contract account
contract = template.LogicSig(compiled)

# write to file
txns = [lstx]
transaction.write_to_file(txns, "p_pay.stxn")
# Create a payment transaction
receiver = "ZZAF5ARA4MEC5PVDOP64JM5O5MQST63Q2KOY2FLYFLXXD3PFSNJJBYAFZM"
amount = 200000
lease = base64.b64decode("y9OJ5MRLCHQj8GqbikAUKMBI7hom+SOj8dlopNdNHXI=")
txn = transaction.PaymentTxn(addr, params, receiver, amount, lease)

# send raw LogicSigTransaction to network
txid = acl.send_transaction(lstx)
print("Transaction ID: " + txid)
# except Exception as e:
# print(e)
# Sign the transaction with the contract account
stxn = txn.sign(contract)

# send raw LogicSigTransaction again to network
txid = acl.send_transaction(lstx)
print("Transaction ID: " + txid)
# Send the transaction to the network
txid = acl.send_transaction(stxn)
print("Transaction ID:", txid)
111 changes: 13 additions & 98 deletions examples/signature/recurring_swap_deploy.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,17 @@
#!/usr/bin/env python3

import base64
from nacl import encoding, hash
import params
import re

import time
import uuid

from algosdk import algod
from algosdk.future import transaction

from algosdk import algod, account, encoding as algosdk_encoding, transaction
from pyteal import *

from recurring_swap import recurring_swap


# ------- generate provider's account -----------------------------------------------
key_fn = str(uuid.uuid4()) + ".key"
execute(["algokey", "generate", "-f", key_fn])
stdout, stderr = execute(["algokey", "export", "-f", key_fn])
print("generated key file {}".format(key_fn))

if stderr != "":
print(stderr)
raise

result = re.search(r"key: \w+", stdout)
provider_addr = result.group(0)[5:]
private_key, provider_addr = account.generate_account()
print("provider addr: {}".format(provider_addr))

# ------- instantiate template, compile teal source, get escrow address -------------
Expand All @@ -36,23 +21,10 @@
# print(teal_source)

# compile teal
teal_base = str(uuid.uuid4())
teal_file = teal_base + ".teal"
with open(teal_file, "w+") as f:
f.write(teal_source)
lsig_fname = teal_base + ".tealc"

stdout, stderr = execute(["goal", "clerk", "compile", "-o", lsig_fname, teal_file])

if stderr != "":
print(stderr)
raise
elif len(stdout) < 59:
print("error in compile teal")
raise

result = re.search(r": \w+", stdout)
escrow_addr = result.group(0)[2:]
teal_bytes = teal_source.encode()
escrow_lsig = transaction.LogicSig(account.logic_sign(teal_bytes))

escrow_addr = algosdk_encoding.encode_address(escrow_lsig.address())
print("Dispense at least 202000 microAlgo to {}".format(escrow_addr))
input("Make sure you did that. Press Enter to continue...")

Expand All @@ -68,41 +40,12 @@

txn = transaction.PaymentTxn(escrow_addr, sp, provider_addr, 100000, lease=lease_bytes)

with open(lsig_fname, "rb") as f:
teal_bytes = f.read()
lsig = transaction.LogicSig(teal_bytes)
lstx = transaction.LogicSigTransaction(txn, lsig)
lstx = transaction.LogicSigTransaction(txn, escrow_lsig)

assert lstx.verify()

# send LogicSigTransaction to network
transaction.write_to_file([lstx], "r_s_1.txn")

stdout, stderr = execute(
[
"goal",
"clerk",
"tealsign",
"--data-b64",
base64.b64encode(data),
"--lsig-txn",
"r_s_1.txn",
"--keyfile",
key_fn,
"--set-lsig-arg-idx",
"0",
]
)
if stderr != "":
print(stderr)
raise

print(stdout)

lstx = transaction.retrieve_from_file("r_s_1.txn")
txid = acl.send_transactions(lstx)

print("1st withraw Succesfull! txid:{}".format(txid))
txid = acl.send_transaction(lstx)
print("1st withdraw Succesfull! txid:{}".format(txid))

# at least sleep to the next round
time.sleep(6)
Expand All @@ -117,37 +60,9 @@

txn = transaction.PaymentTxn(escrow_addr, sp, provider_addr, 100000, lease=lease_bytes)

with open(lsig_fname, "rb") as f:
teal_bytes = f.read()
lsig = transaction.LogicSig(teal_bytes)
lstx = transaction.LogicSigTransaction(txn, lsig)
lstx = transaction.LogicSigTransaction(txn, escrow_lsig)

assert lstx.verify()

# send LogicSigTransaction to network
transaction.write_to_file([lstx], "r_s_2.txn")

stdout, stderr = execute(
[
"goal",
"clerk",
"tealsign",
"--data-b64",
base64.b64encode(data),
"--lsig-txn",
"r_s_2.txn",
"--keyfile",
key_fn,
"--set-lsig-arg-idx",
"0",
]
)
if stderr != "":
print(stderr)
raise

print(stdout)

lstx = transaction.retrieve_from_file("r_s_2.txn")
txid = acl.send_transactions(lstx)
print("2nd withraw Succesfull! txid:{}".format(txid))
txid = acl.send_transaction(lstx)
print("2nd withdraw Succesfull! txid:{}".format(txid))