Skip to content
New issue

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

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

Already on GitHub? # to your account

allow app id to be none since it may be called during create #592

Merged
merged 4 commits into from
Nov 3, 2022
Merged
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Unreleased

# Fixed
* Allowing the `MethodCall` and `ExecuteMethodCall` to be passed `None` as app_id argument in the case of an app create transaction ([#592](https://github.com/algorand/pyteal/pull/592))


# 0.20.1

## Added
Expand Down
20 changes: 12 additions & 8 deletions pyteal/ast/itxn.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,10 +253,10 @@ def SetFields(cls, fields: dict[TxnField, Expr | list[Expr]]) -> Expr:
def ExecuteMethodCall(
cls,
*,
app_id: Expr,
app_id: Expr | None,
method_signature: str,
args: list[abi.BaseType | Expr | dict[TxnField, Expr | list[Expr]]],
extra_fields: dict[TxnField, Expr | list[Expr]] = None,
extra_fields: dict[TxnField, Expr | list[Expr]] | None = None,
) -> Expr:
"""Performs a single app call transaction formatted as an ABI method call.

Expand All @@ -277,6 +277,7 @@ def ExecuteMethodCall(

Args:
app_id: An expression that evaluates to a `TealType.uint64` corresponding to the application being called.
If the call is meant to create an application, the value `None` should be passed
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:
Expand Down Expand Up @@ -310,10 +311,10 @@ def ExecuteMethodCall(
def MethodCall(
cls,
*,
app_id: Expr,
app_id: Expr | None,
method_signature: str,
args: list[abi.BaseType | Expr | dict[TxnField, Expr | list[Expr]]],
extra_fields: dict[TxnField, Expr | list[Expr]] = None,
extra_fields: dict[TxnField, Expr | list[Expr]] | None = None,
) -> Expr:
"""Adds an ABI method call transaction to the current inner transaction group.

Expand All @@ -323,6 +324,7 @@ def MethodCall(

Args:
app_id: An expression that evaluates to a `TealType.uint64` corresponding to the application being called.
If the call is meant to create an application, the value `None` should be passed
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:
Expand All @@ -344,14 +346,16 @@ def MethodCall(

from pyteal.ast.abi.util import type_spec_is_assignable_to

require_type(app_id, TealType.uint64)

# Default, always need these
# Start collecting the fields we'd like to set
fields_to_set = [
cls.SetField(TxnField.type_enum, TxnType.ApplicationCall),
cls.SetField(TxnField.application_id, app_id),
]

# In the case of an app create, the `app_id` arg may be `None`
if app_id is not None:
require_type(app_id, TealType.uint64)
fields_to_set.append(cls.SetField(TxnField.application_id, app_id))

# We only care about the args
arg_type_specs: list[abi.TypeSpec]
arg_type_specs, _ = abi.type_specs_from_signature(method_signature)
Expand Down
21 changes: 21 additions & 0 deletions pyteal/ast/itxn_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,27 @@ def test_InnerTxnBuilder_Execute():
),
None,
),
# App create case
(
None,
"create(byte[],uint64)void",
[t6_1 := pt.abi.DynamicBytes(), t6_2 := pt.abi.Uint64()],
{TxnField.fee: pt.Int(0)},
pt.Seq(
pt.InnerTxnBuilder.SetFields(
{
pt.TxnField.type_enum: TxnType.ApplicationCall,
pt.TxnField.application_args: [
pt.MethodSignature("create(byte[],uint64)void"),
t6_1.encode(),
t6_2.encode(),
],
pt.TxnField.fee: pt.Int(0),
}
),
),
None,
),
# Error cases
(
pt.Int(1),
Expand Down