From 1fe28f084d882613cf30bba07d2de7bd40129940 Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Wed, 10 Aug 2022 08:19:16 -0400 Subject: [PATCH 1/4] windows compatability (#499) --- tests/integration/abi_roundtrip_test.py | 2 +- ...,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_2.teal} | 0 ...app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_7.teal} | 0 ...trip_address[]_<10>.teal => app_roundtrip_address[]_10.teal} | 0 ...trip_bool[3][]_<11>.teal => app_roundtrip_bool[3][]_11.teal} | 0 ...pp_roundtrip_bool[]_<0>.teal => app_roundtrip_bool[]_0.teal} | 0 ...pp_roundtrip_bool[]_<1>.teal => app_roundtrip_bool[]_1.teal} | 0 ..._roundtrip_bool[]_<42>.teal => app_roundtrip_bool[]_42.teal} | 0 ...pp_roundtrip_string_<0>.teal => app_roundtrip_string_0.teal} | 0 ...pp_roundtrip_string_<1>.teal => app_roundtrip_string_1.teal} | 0 ..._roundtrip_string_<13>.teal => app_roundtrip_string_13.teal} | 0 ...oundtrip_uint64[]_<0>.teal => app_roundtrip_uint64[]_0.teal} | 0 ...oundtrip_uint64[]_<1>.teal => app_roundtrip_uint64[]_1.teal} | 0 ...ndtrip_uint64[]_<42>.teal => app_roundtrip_uint64[]_42.teal} | 0 14 files changed, 1 insertion(+), 1 deletion(-) rename tests/integration/teal/roundtrip/{app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_<2>.teal => app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_2.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_<7>.teal => app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_7.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_address[]_<10>.teal => app_roundtrip_address[]_10.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_bool[3][]_<11>.teal => app_roundtrip_bool[3][]_11.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_bool[]_<0>.teal => app_roundtrip_bool[]_0.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_bool[]_<1>.teal => app_roundtrip_bool[]_1.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_bool[]_<42>.teal => app_roundtrip_bool[]_42.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_string_<0>.teal => app_roundtrip_string_0.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_string_<1>.teal => app_roundtrip_string_1.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_string_<13>.teal => app_roundtrip_string_13.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_uint64[]_<0>.teal => app_roundtrip_uint64[]_0.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_uint64[]_<1>.teal => app_roundtrip_uint64[]_1.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_uint64[]_<42>.teal => app_roundtrip_uint64[]_42.teal} (100%) diff --git a/tests/integration/abi_roundtrip_test.py b/tests/integration/abi_roundtrip_test.py index 5231af4c7..c1b5ca778 100644 --- a/tests/integration/abi_roundtrip_test.py +++ b/tests/integration/abi_roundtrip_test.py @@ -211,7 +211,7 @@ def test_pure_compilation(abi_type): filename = ( f"app_roundtrip_{sdk_abi_type}" - + ("" if dynamic_length is None else f"_<{dynamic_length}>") + + ("" if dynamic_length is None else f"_{dynamic_length}") + ".teal" ) tealdir = GENERATED / "roundtrip" diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_<2>.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_2.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_<2>.teal rename to tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_2.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_<7>.teal b/tests/integration/teal/roundtrip/app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_7.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_<7>.teal rename to tests/integration/teal/roundtrip/app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_7.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_address[]_<10>.teal b/tests/integration/teal/roundtrip/app_roundtrip_address[]_10.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_address[]_<10>.teal rename to tests/integration/teal/roundtrip/app_roundtrip_address[]_10.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[3][]_<11>.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[3][]_11.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_bool[3][]_<11>.teal rename to tests/integration/teal/roundtrip/app_roundtrip_bool[3][]_11.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[]_<0>.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_0.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_bool[]_<0>.teal rename to tests/integration/teal/roundtrip/app_roundtrip_bool[]_0.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[]_<1>.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_1.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_bool[]_<1>.teal rename to tests/integration/teal/roundtrip/app_roundtrip_bool[]_1.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[]_<42>.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_42.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_bool[]_<42>.teal rename to tests/integration/teal/roundtrip/app_roundtrip_bool[]_42.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_string_<0>.teal b/tests/integration/teal/roundtrip/app_roundtrip_string_0.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_string_<0>.teal rename to tests/integration/teal/roundtrip/app_roundtrip_string_0.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_string_<1>.teal b/tests/integration/teal/roundtrip/app_roundtrip_string_1.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_string_<1>.teal rename to tests/integration/teal/roundtrip/app_roundtrip_string_1.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_string_<13>.teal b/tests/integration/teal/roundtrip/app_roundtrip_string_13.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_string_<13>.teal rename to tests/integration/teal/roundtrip/app_roundtrip_string_13.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_<0>.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_0.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_uint64[]_<0>.teal rename to tests/integration/teal/roundtrip/app_roundtrip_uint64[]_0.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_<1>.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_1.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_uint64[]_<1>.teal rename to tests/integration/teal/roundtrip/app_roundtrip_uint64[]_1.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_<42>.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_42.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_uint64[]_<42>.teal rename to tests/integration/teal/roundtrip/app_roundtrip_uint64[]_42.teal From d3f688bf91c7096bbe3105fda129981db8bbb7c0 Mon Sep 17 00:00:00 2001 From: Jason Paulos Date: Thu, 11 Aug 2022 09:54:27 -0700 Subject: [PATCH 2/4] Update `Block` docs to match spec change (#503) * Update `Block` docs * Changelog update --- CHANGELOG.md | 1 + pyteal/ast/block.py | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71aafd130..42faf2823 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * CI: Fail readthedocs build on warning ([#478](https://github.com/algorand/pyteal/pull/478)) ## Changed +* Update `Block` docs to match spec change ([#503](https://github.com/algorand/pyteal/pull/503)) # 0.15.0 ## Added diff --git a/pyteal/ast/block.py b/pyteal/ast/block.py index 775f1593c..053887f79 100644 --- a/pyteal/ast/block.py +++ b/pyteal/ast/block.py @@ -60,8 +60,8 @@ def seed(cls, block: Expr) -> Expr: Args: block: A block index that corresponds to the block to check, - must be evaluated to uint64. Fails if the block index is not less than the - current round or more than 1001 rounds before txn.LastValid. + must be evaluated to uint64. Fails if the block index is not less than + :code:`Txn.first_valid()` or more than 1001 rounds before :code:`Txn.last_valid()`. """ return cls(BlockField.block_seed, block) @@ -71,8 +71,8 @@ def timestamp(cls, block: Expr) -> Expr: Args: block: A block index that corresponds to the block to check, - must be evaluated to uint64. Fails if the block index is not less than the - current round or more than 1001 rounds before txn.LastValid. + must be evaluated to uint64. Fails if the block index is not less than + :code:`Txn.first_valid()` or more than 1001 rounds before :code:`Txn.last_valid()`. """ return cls(BlockField.block_timestamp, block) From a93c9db018082cd9fd57227ce592e3636fc2f786 Mon Sep 17 00:00:00 2001 From: Ben Guidarelli Date: Thu, 11 Aug 2022 18:00:16 -0400 Subject: [PATCH 3/4] add ExecuteMethod helper (#501) * add ExecuteMethodCall helper --- pyteal/ast/itxn.py | 63 +++++++++- pyteal/ast/itxn_test.py | 264 +++++----------------------------------- 2 files changed, 90 insertions(+), 237 deletions(-) diff --git a/pyteal/ast/itxn.py b/pyteal/ast/itxn.py index b2e53ad06..d38eb55d5 100644 --- a/pyteal/ast/itxn.py +++ b/pyteal/ast/itxn.py @@ -217,7 +217,7 @@ def Execute(cls, fields: dict[TxnField, Expr | list[Expr]]) -> Expr: InnerTxnBuilder.Begin() InnerTxnBuilder.SetFields(fields) - InnerTxnBuilder.End() + InnerTxnBuilder.Submit() Requires program version 5 or higher. This operation is only permitted in application mode. @@ -249,6 +249,63 @@ def SetFields(cls, fields: dict[TxnField, Expr | list[Expr]]) -> Expr: fieldsToSet = [cls.SetField(field, value) for field, value in fields.items()] return Seq(fieldsToSet) + @classmethod + def ExecuteMethodCall( + cls, + *, + app_id: Expr, + method_signature: str, + args: list[abi.BaseType | Expr | dict[TxnField, Expr | list[Expr]]], + extra_fields: dict[TxnField, Expr | list[Expr]] = None, + ) -> Expr: + """Performs a single app call transaction formatted as an ABI method call. + + A convenience method that accepts fields to submit a single inner transaction, which is equivalent to: + + .. code-block:: python + + InnerTxnBuilder.Begin() + InnerTxnBuilder.MethodCall( + app_id=app_id, + method_signature=method_signature, + args=args, + extra_fields=extra_fields, + ), + InnerTxnBuilder.Submit() + + Requires program version 5 or higher. This operation is only permitted in application mode. + + Args: + app_id: An expression that evaluates to a `TealType.uint64` corresponding to the application being called. + method_signature: A string representing the method signature of the method we're calling. This is used to do + type checking on the arguments passed and to create the method selector passed as the first argument. + args: A list of arguments to pass to the application. The values in this list depend on the kind of argument you wish to pass: + + - For basic ABI arguments (not Reference or Transaction types): + If an ABI type is passed it **MUST** match the type specified in the `method_signature`. If an Expr is passed it must evaluate to `TealType.bytes` but beyond that no type checking is performed. + + - For Reference arguments: + Either the Reference type or an Expr that returns the type corresponding to the reference type are allowed. + (i.e. Asset is TealType.uint64, Application is TealType.uint64, Account is TealType.bytes) + + - For Transaction arguments: + A dictionary containing TxnField to Expr that describe Transactions to be pre-pended to the transaction group being constructed. The `TxnField.type_enum` key MUST be set and MUST match the expected transaction type specified in the `method_signature`. + + extra_fields (optional): A dictionary whose keys are fields to set and whose values are the value each + field should take. Each value must evaluate to a type that is compatible with the + field being set. These fields are set on the ApplicationCallTransaction being constructed + """ + return Seq( + cls.Begin(), + cls.MethodCall( + app_id=app_id, + method_signature=method_signature, + args=args, + extra_fields=extra_fields, + ), + cls.Submit(), + ) + @classmethod def MethodCall( cls, @@ -256,7 +313,7 @@ def MethodCall( app_id: Expr, method_signature: str, args: list[abi.BaseType | Expr | dict[TxnField, Expr | list[Expr]]], - extra_fields: dict[TxnField, Expr | list[Expr]] = {}, + extra_fields: dict[TxnField, Expr | list[Expr]] = None, ) -> Expr: """Adds an ABI method call transaction to the current inner transaction group. @@ -425,7 +482,7 @@ def MethodCall( # Set the fields for the app call in app args and foreign arrays *fields_to_set, # Add any remaining fields specified by the user - InnerTxnBuilder.SetFields(extra_fields), + InnerTxnBuilder.SetFields({} if extra_fields is None else extra_fields), ) diff --git a/pyteal/ast/itxn_test.py b/pyteal/ast/itxn_test.py index 5012c0a05..f6ee455ef 100644 --- a/pyteal/ast/itxn_test.py +++ b/pyteal/ast/itxn_test.py @@ -435,8 +435,16 @@ def test_InnerTxnBuilder_method_call( args=args, extra_fields=extra_fields, ) + with pytest.raises(expected_error): + pt.InnerTxnBuilder.ExecuteMethodCall( + app_id=app_id, + method_signature=sig, + args=args, + extra_fields=extra_fields, + ) return + # First run the test with MethodCall expr: pt.Expr = pt.InnerTxnBuilder.MethodCall( app_id=app_id, method_signature=sig, args=args, extra_fields=extra_fields ) @@ -458,241 +466,29 @@ def test_InnerTxnBuilder_method_call( pt.TealBlock.GetReferencedScratchSlots(expected), ) + # Now run the same test with ExecuteMethodCall + expr = pt.InnerTxnBuilder.ExecuteMethodCall( + app_id=app_id, method_signature=sig, args=args, extra_fields=extra_fields + ) + assert expr.type_of() == pt.TealType.none + assert not expr.has_return() -ITXN_METHOD_CASES = ( - ( - pt.Int(1), - "add(uint64,uint64)void", - [t1_1 := pt.Itob(pt.Int(1)), t1_2 := pt.Itob(pt.Int(1))], - {TxnField.fee: pt.Int(0)}, - pt.Seq( - pt.InnerTxnBuilder.SetFields( - { - pt.TxnField.type_enum: TxnType.ApplicationCall, - pt.TxnField.application_id: pt.Int(1), - pt.TxnField.application_args: [ - pt.MethodSignature("add(uint64,uint64)void"), - t1_1, - t1_2, - ], - pt.TxnField.fee: pt.Int(0), - } - ), - ), - None, - ), - ( - pt.Int(1), - "add(uint64,uint64)void", - [t2_1 := pt.abi.Uint64(), t2_2 := pt.abi.Uint64()], - {TxnField.fee: pt.Int(0)}, - pt.Seq( - pt.InnerTxnBuilder.SetFields( - { - pt.TxnField.type_enum: TxnType.ApplicationCall, - pt.TxnField.application_id: pt.Int(1), - pt.TxnField.application_args: [ - pt.MethodSignature("add(uint64,uint64)void"), - t2_1.encode(), - t2_2.encode(), - ], - pt.TxnField.fee: pt.Int(0), - } - ), - ), - None, - ), - ( - pt.Int(1), - "add(application,account,asset)void", - [ - t3_1 := pt.abi.Application(), - t3_2 := pt.abi.Account(), - t3_3 := pt.abi.Asset(), - ], - {TxnField.fee: pt.Int(0)}, - pt.Seq( - pt.InnerTxnBuilder.SetFields( - { - pt.TxnField.type_enum: TxnType.ApplicationCall, - pt.TxnField.application_id: pt.Int(1), - pt.TxnField.accounts: [t3_2.address()], - pt.TxnField.applications: [t3_1.application_id()], - pt.TxnField.assets: [t3_3.asset_id()], - pt.TxnField.application_args: [ - pt.MethodSignature("add(application,account,asset)void"), - pt.Bytes(b"\x01"), - pt.Bytes(b"\x01"), - pt.Bytes(b"\x00"), - ], - pt.TxnField.fee: pt.Int(0), - } - ), - ), - None, - ), - ( - pt.Int(1), - "add(application,account,asset)void", - [ - t4_1 := pt.Int(1), - t4_2 := pt.Global.zero_address(), - t4_3 := pt.Int(2), - ], - {TxnField.fee: pt.Int(0)}, - pt.Seq( - pt.InnerTxnBuilder.SetFields( - { - pt.TxnField.type_enum: TxnType.ApplicationCall, - pt.TxnField.application_id: pt.Int(1), - pt.TxnField.accounts: [t4_2], - pt.TxnField.applications: [t4_1], - pt.TxnField.assets: [t4_3], - pt.TxnField.application_args: [ - pt.MethodSignature("add(application,account,asset)void"), - pt.Bytes(b"\x01"), - pt.Bytes(b"\x01"), - pt.Bytes(b"\x00"), - ], - pt.TxnField.fee: pt.Int(0), - } - ), - ), - None, - ), - ( - pt.Int(1), - "add(pay,txn,appl)void", - [ - t5_1 := {TxnField.type_enum: TxnType.Payment}, - t5_2 := {TxnField.type_enum: TxnType.AssetTransfer}, - t5_3 := {TxnField.type_enum: TxnType.ApplicationCall}, - ], - {TxnField.fee: pt.Int(0)}, - pt.Seq( - pt.InnerTxnBuilder.SetFields(t5_1), # type: ignore - pt.InnerTxnBuilder.Next(), - pt.InnerTxnBuilder.SetFields(t5_2), # type: ignore - pt.InnerTxnBuilder.Next(), - pt.InnerTxnBuilder.SetFields(t5_3), # type: ignore - pt.InnerTxnBuilder.Next(), - pt.InnerTxnBuilder.SetFields( - { - pt.TxnField.type_enum: TxnType.ApplicationCall, - pt.TxnField.application_id: pt.Int(1), - pt.TxnField.application_args: [ - pt.MethodSignature("add(pay,txn,appl)void"), - ], - pt.TxnField.fee: pt.Int(0), - } - ), - ), - None, - ), - # Error cases - ( - pt.Int(1), - "add(pay,txn,appl)void", - [ - {}, - {TxnField.type_enum: TxnType.AssetTransfer}, - {TxnField.type_enum: TxnType.ApplicationCall}, - ], - None, - None, - pt.TealInputError, - ), - ( - pt.Int(1), - "add(pay,txn,appl)void", - [ - {TxnField.type_enum: pt.Int(10)}, - {TxnField.type_enum: TxnType.AssetTransfer}, - {TxnField.type_enum: TxnType.ApplicationCall}, - ], - None, - None, - pt.TealTypeError, - ), - ( - pt.Int(1), - "add(pay,txn,appl)void", - [ - {TxnField.type_enum: TxnType.ApplicationCall}, - {TxnField.type_enum: TxnType.AssetTransfer}, - {TxnField.type_enum: TxnType.ApplicationCall}, - ], - None, - None, - pt.TealInputError, - ), - ( - pt.Int(1), - "add(application,account,asset)void", - [ - pt.abi.Asset(), - pt.abi.Account(), - pt.abi.Asset(), - ], - None, - None, - pt.TealTypeError, - ), - ( - pt.Int(1), - "add(application)void", - [ - pt.Bytes(""), - ], - None, - None, - pt.TealTypeError, - ), - ( - pt.Int(1), - "add(asset)void", - [ - pt.Bytes(""), - ], - None, - None, - pt.TealTypeError, - ), - ( - pt.Int(1), - "add(account)void", - [ - pt.Int(1), - ], - None, - None, - pt.TealTypeError, - ), - ( - pt.Int(1), - "add(uint64,uint64)void", - [pt.abi.String(), pt.abi.Uint64()], - None, - None, - pt.TealTypeError, - ), - ( - pt.Int(1), - "add(uint64,uint64)void", - [pt.abi.Uint64()], - None, - None, - pt.TealInputError, - ), - ( - pt.Int(1), - "add(uint64,uint64)void", - [pt.abi.Uint64(), pt.abi.Uint64(), pt.abi.Uint64()], - None, - None, - pt.TealInputError, - ), -) + expected, _ = pt.Seq( + pt.InnerTxnBuilder.Begin(), expected_expr, pt.InnerTxnBuilder.Submit() + ).__teal__(avm6Options) + expected.addIncoming() + expected = pt.TealBlock.NormalizeBlocks(expected) + + actual, _ = expr.__teal__(avm6Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + with pt.TealComponent.Context.ignoreScratchSlotEquality(), pt.TealComponent.Context.ignoreExprEquality(): + assert actual == expected + assert pt.TealBlock.MatchScratchSlotReferences( + pt.TealBlock.GetReferencedScratchSlots(actual), + pt.TealBlock.GetReferencedScratchSlots(expected), + ) # txn_test.py performs additional testing From d4c1df3683e8d0ab0eaeda2c03ac29cb3c21fcb7 Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Mon, 15 Aug 2022 13:17:31 -0400 Subject: [PATCH 4/4] Release/v0.16.0 (#507) * 0.16.0 --- CHANGELOG.md | 9 +++++++++ setup.py | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42faf2823..50cb0b647 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,16 +1,25 @@ # Unreleased + +# 0.16.0 + ## Added * Add the ability to pass foreign reference arrays directly into inner transactions ([#384](https://github.com/algorand/pyteal/pull/384)) + * NamedTuple Implementation ([#473](https://github.com/algorand/pyteal/pull/473)) +* ExecuteMethodCall helper ([#501](https://github.com/algorand/pyteal/pull/501)) + ## Fixed * CI: Fail readthedocs build on warning ([#478](https://github.com/algorand/pyteal/pull/478)) +* Windows Compatibility ([#499](https://github.com/algorand/pyteal/pull/499)) + ## Changed * Update `Block` docs to match spec change ([#503](https://github.com/algorand/pyteal/pull/503)) # 0.15.0 + ## Added * Support AVM 7 updates: * New opcodes: diff --git a/setup.py b/setup.py index 57519a4e9..fc8940126 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ setuptools.setup( name="pyteal", - version="0.15.0", + version="0.16.0", author="Algorand", author_email="pypiservice@algorand.com", description="Algorand Smart Contracts in Python",