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 voting example #596

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 4 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
3 changes: 2 additions & 1 deletion .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ ignore =

per-file-ignores =
pyteal/compiler/optimizer/__init__.py: F401
examples/application/abi/algobank.py: F403, F405
examples/application/abi/algobank/algobank.py: F403, F405
examples/application/abi/poll/contract.py: F403, F405
examples/application/asset.py: F403, F405
examples/application/opup.py: F403, F405
examples/application/security_token.py: F403, F405
Expand Down
4 changes: 2 additions & 2 deletions docs/abi.rst
Original file line number Diff line number Diff line change
Expand Up @@ -916,12 +916,12 @@ In addition to receiving the approval and clear state programs, the :any:`Router

Here's an example of a complete application that uses the :any:`Router` class:

.. literalinclude:: ../examples/application/abi/algobank.py
.. literalinclude:: ../examples/application/abi/algobank/algobank.py
:language: python

This example uses the :code:`Router.compile_program` method to create the approval program, clear state program, and contract description for the "AlgoBank" contract. The produced :code:`algobank.json` file is below:

.. literalinclude:: ../examples/application/abi/algobank.json
.. literalinclude:: ../examples/application/abi/algobank/algobank.json
:language: json

Calling an ARC-4 Program
Expand Down
Empty file.
Empty file.
169 changes: 169 additions & 0 deletions examples/application/abi/poll/approval.teal
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
#pragma version 8
txn NumAppArgs
int 0
==
bnz main_l12
txna ApplicationArgs 0
method "create(string[],bool)void"
==
bnz main_l11
txna ApplicationArgs 0
method "open()void"
==
bnz main_l10
txna ApplicationArgs 0
method "close()void"
==
bnz main_l9
txna ApplicationArgs 0
method "submit(uint16)void"
==
bnz main_l8
txna ApplicationArgs 0
method "status()(bool,bool,(string,uint64)[])"
==
bnz main_l7
err
main_l7:
txn OnCompletion
int NoOp
==
txn ApplicationID
int 0
!=
&&
assert
callsub status_4
store 2
byte 0x151f7c75
load 2
concat
log
int 1
return
main_l8:
txn OnCompletion
int NoOp
==
txn ApplicationID
int 0
!=
&&
assert
txna ApplicationArgs 1
int 0
extract_uint16
callsub submit_3
int 1
return
main_l9:
txn OnCompletion
int NoOp
==
txn ApplicationID
int 0
!=
&&
assert
callsub close_2
int 1
return
main_l10:
txn OnCompletion
int NoOp
==
txn ApplicationID
int 0
!=
&&
assert
callsub open_1
int 1
return
main_l11:
txn OnCompletion
int NoOp
==
txn ApplicationID
int 0
==
&&
assert
txna ApplicationArgs 1
store 0
txna ApplicationArgs 2
int 0
int 8
*
getbit
store 1
load 0
load 1
callsub create_0
int 1
return
main_l12:
txn OnCompletion
int DeleteApplication
==
bnz main_l14
err
main_l14:
txn ApplicationID
int 0
!=
assert
txn Sender
global CreatorAddress
==
assert
int 1
return

// create
create_0:
store 8
store 7
retsub

// open
open_1:
retsub

// close
close_2:
retsub

// submit
submit_3:
store 9
retsub

// status
status_4:
int 0
store 3
int 0
store 4
int 0
itob
extract 6 0
byte ""
concat
store 5
byte 0x00
int 0
load 3
setbit
int 1
load 4
setbit
load 5
store 6
int 3
itob
extract 6 0
concat
load 6
concat
retsub
3 changes: 3 additions & 0 deletions examples/application/abi/poll/clear_state.teal
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#pragma version 8
int 0
return
65 changes: 65 additions & 0 deletions examples/application/abi/poll/contract.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{
"name": "OpenPollingApp",
"methods": [
{
"name": "create",
"args": [
{
"type": "string[]",
"name": "options",
"desc": "A list of options for the poll. This list should not contain duplicate entries."
tzaffi marked this conversation as resolved.
Show resolved Hide resolved
},
{
"type": "bool",
"name": "can_resubmit",
"desc": "Whether this poll allows accounts to change their submissions or not."
}
],
"returns": {
"type": "void"
},
"desc": "Create a new polling application."
},
{
"name": "open",
"args": [],
"returns": {
"type": "void"
},
"desc": "Marks this poll as open.\nThis will fail if the poll is already open.\nThe poll must be open in order to receive user input."
},
{
"name": "close",
"args": [],
"returns": {
"type": "void"
},
"desc": "Marks this poll as closed.\nThis will fail if the poll is already closed."
},
{
"name": "submit",
"args": [
{
"type": "uint16",
jasonpaulos marked this conversation as resolved.
Show resolved Hide resolved
"name": "choice",
"desc": "The choice made by the sender. This must be an index into the options for this poll."
}
],
"returns": {
"type": "void"
},
"desc": "Submit a response to the poll.\nSubmissions can only be received if the poll is open. If the poll is closed, this will fail.\nIf a submission has already been made by the sender and the poll allows resubmissions, the sender's choice will be updated to the most recent submission. If the poll does not allow resubmissions, this action will fail."
},
{
"name": "status",
"args": [],
"returns": {
"type": "(bool,bool,(string,uint64)[])",
"desc": "A tuple containing the following information, in order: whether the poll allows resubmission, whether the poll is open, and an array of the poll's current results. This array contains one entry per option, and each entry is a tuple of that option's value and the number of accounts who have voted for it."
},
"desc": "Get the status of this poll."
}
],
"networks": {},
"desc": "This is a polling application with no restrictions on who can participate."
}
107 changes: 107 additions & 0 deletions examples/application/abi/poll/contract.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# This example is provided for informational purposes only and has not been audited for security.
from pyteal import *
import json


def on_delete() -> Expr:
return Assert(Txn.sender() == Global.creator_address())


router = Router(
name="OpenPollingApp",
descr="This is a polling application with no restrictions on who can participate.",
bare_calls=BareCallActions(
delete_application=OnCompleteAction.call_only(on_delete())
),
)


@router.method(no_op=CallConfig.CREATE)
def create(options: abi.DynamicArray[abi.String], can_resubmit: abi.Bool) -> Expr:
"""Create a new polling application.

Args:
options: A list of options for the poll. This list should not contain duplicate entries.
resubmission: A boolean value indicating whether this poll allows accounts to change their
answer after their first submission.
can_resubmit: Whether this poll allows accounts to change their submissions or not.
"""
return Seq()


@router.method(name="open")
def open_poll() -> Expr:
Comment on lines +57 to +58
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good to see naming overriding being used 👍

"""Marks this poll as open.

This will fail if the poll is already open.

The poll must be open in order to receive user input.
"""
return Seq()


@router.method(name="close")
def close_poll() -> Expr:
"""Marks this poll as closed.

This will fail if the poll is already closed.
"""
return Seq()


@router.method
def submit(choice: abi.Uint16) -> Expr:
"""Submit a response to the poll.

Submissions can only be received if the poll is open. If the poll is closed, this will fail.

If a submission has already been made by the sender and the poll allows resubmissions, the
sender's choice will be updated to the most recent submission. If the poll does not allow
resubmissions, this action will fail.

Args:
choice: The choice made by the sender. This must be an index into the options for this poll.
"""
return Seq()


class PollStatus(abi.NamedTuple):
can_resubmit: abi.Field[abi.Bool]
is_open: abi.Field[abi.Bool]
results: abi.Field[abi.DynamicArray[abi.Tuple2[abi.String, abi.Uint64]]]


@router.method
def status(*, output: PollStatus) -> Expr:
"""Get the status of this poll.

Returns:
A tuple containing the following information, in order: whether the poll allows
resubmission, whether the poll is open, and an array of the poll's current results. This
array contains one entry per option, and each entry is a tuple of that option's value and
the number of accounts who have voted for it.
"""
can_resubmit = abi.make(abi.Bool)
is_open = abi.make(abi.Bool)
results = abi.make(abi.DynamicArray[abi.Tuple2[abi.String, abi.Uint64]])
return Seq(
can_resubmit.set(False),
is_open.set(False),
results.set([]),
output.set(can_resubmit, is_open, results),
)


approval_program, clear_state_program, contract = router.compile_program(
version=8, optimize=OptimizeOptions(scratch_slots=True)
)

if __name__ == "__main__":
with open("approval.teal", "w") as f:
f.write(approval_program)

with open("clear_state.teal", "w") as f:
f.write(clear_state_program)

with open("contract.json", "w") as f:
f.write(json.dumps(contract.dictify(), indent=4))
Loading