Decorators

Beaker Application decorators are used to add method handlers to the Application.

They optionally accept parameters that apply configurations to the methods they decorate.

Authorization

Often, we would like to restrict the accounts that may call certain methods.

Let’s add a parameter to the external decorator to prevent anyone but the app creator to call this method.

from beaker.decorators import Authorize

#...

@app.external(authorize=Authorize.only(Global.creator_address()))
def increment(*, output: abi.Uint64):
    return Seq(
        self.counter.set(self.counter + Int(1)),
        output.set(self.counter)
    )

The authorize parameter may be any Subroutine that accepts a sender as its argument and returns an integer interpreted as true/false.

Now let’s write a new method to allow any account that is opted in to call it:

from beaker.decorators import Authorize

# ...

@app.external(authorize=Authorize.opted_in())
def vote(approve: abi.Bool):
    # ...

This value passed to authorize will cause the contract call to fail if the sender has not opted in to the app. Another app ID may be passed in case you want to check if the sender is opted in to a different application.

The pre-defined Authorized checks are:

static Authorize.only(addr: Expr) Callable[[Expr], Expr][source]

require that the sender of the app call match exactly the address passed

static Authorize.holds_token(asset_id: Expr) Callable[[Expr], Expr][source]

require that the sender of the app call holds >0 of the asset id passed

static Authorize.opted_in(app_id: ~pyteal.Expr = <pyteal.Global object>) Callable[[Expr], Expr][source]

require that the sender of the app call has already opted-in to a given app id

But we can define our own

from pyteal import Subroutine
from beaker.consts import Algos

@Subroutine(TealType.uint64)
def is_whale(acct: Expr):
    # Only allow accounts with 1mm algos
    return Balance(acct)>Algos(1_000_000)

# ...

@app.external(authorize=is_whale)
def greet(*, output: abi.String):
    return output.set("hello whale")

Read Only

Methods that are meant to only produce information, having no side effects, should be flagged as read only.

See ARC22 for more details.

class ROAppState:
    count = ApplicationStateValue(stack_type=TealType.uint64)

app = Application("CoolApp", state=ROAppState())

@app.external(read_only=True)
def get_count(id_of_thing: abi.Uint8, *, output: abi.Uint64):
    return output.set(app.state.count)

On Complete

If a method expects the ApplicationCallTransaction to have a certain OnComplete other than NoOp, one of the other OnComplete decorators may be used instead of external with a method config set.

class beaker.application.Application[source]

A class representing an Application.

clear_state(fn: Callable[[], Expr], /) SubroutineFnWrapper[source]
clear_state(*, name: str | None = None, override: bool | None = False) Callable[[Callable[[], Expr]], SubroutineFnWrapper]

Mark a method as one that should be callable during application clear-state.

Parameters
  • name – The name of the method. If not provided, the name of the method will be used.

  • override – If True, the method will override any existing method with the same name.

close_out(fn: Callable[[...], Expr], /) ABIReturnSubroutine[source]
close_out(*, name: str | None = None, authorize: collections.abc.Callable[[pyteal.Expr], pyteal.Expr] | pyteal.SubroutineFnWrapper | None = None, override: bool | None = False) Callable[[Callable[[...], Expr]], ABIReturnSubroutine]
close_out(*, name: str | None = None, authorize: collections.abc.Callable[[pyteal.Expr], pyteal.Expr] | pyteal.SubroutineFnWrapper | None = None, bare: Literal[False], override: bool | None = False) Callable[[Callable[[...], Expr]], ABIReturnSubroutine]
close_out(*, name: str | None = None, authorize: collections.abc.Callable[[pyteal.Expr], pyteal.Expr] | pyteal.SubroutineFnWrapper | None = None, bare: Literal[True], override: bool | None = False) Callable[[Callable[[], Expr]], SubroutineFnWrapper]
close_out(*, name: str | None = None, authorize: collections.abc.Callable[[pyteal.Expr], pyteal.Expr] | pyteal.SubroutineFnWrapper | None = None, bare: bool, override: bool | None = False) collections.abc.Callable[[collections.abc.Callable[[...], pyteal.Expr]], pyteal.ABIReturnSubroutine] | collections.abc.Callable[[collections.abc.Callable[[], pyteal.Expr]], pyteal.SubroutineFnWrapper]

Mark a method as one that should be callable during application close-out.

Parameters
  • name – The name of the method. If not provided, the name of the method will be used.

  • authorize – A function that will be called to authorize the method. If not provided, the method will not be authorized.

  • bare – If True, the router will only consider the OnComplete of the app call transaction to do routing.

  • override – If True, the method will override any existing method with the same name.

create(fn: Callable[[...], Expr], /) ABIReturnSubroutine[source]
create(*, name: str | None = None, authorize: collections.abc.Callable[[pyteal.Expr], pyteal.Expr] | pyteal.SubroutineFnWrapper | None = None, override: bool | None = False) Callable[[Callable[[...], Expr]], ABIReturnSubroutine]
create(*, name: str | None = None, authorize: collections.abc.Callable[[pyteal.Expr], pyteal.Expr] | pyteal.SubroutineFnWrapper | None = None, bare: Literal[False], override: bool | None = False) Callable[[Callable[[...], Expr]], ABIReturnSubroutine]
create(*, name: str | None = None, authorize: collections.abc.Callable[[pyteal.Expr], pyteal.Expr] | pyteal.SubroutineFnWrapper | None = None, bare: Literal[True], override: bool | None = False) Callable[[Callable[[], Expr]], SubroutineFnWrapper]
create(*, name: str | None = None, authorize: collections.abc.Callable[[pyteal.Expr], pyteal.Expr] | pyteal.SubroutineFnWrapper | None = None, bare: bool, override: bool | None = False) collections.abc.Callable[[collections.abc.Callable[[...], pyteal.Expr]], pyteal.ABIReturnSubroutine] | collections.abc.Callable[[collections.abc.Callable[[], pyteal.Expr]], pyteal.SubroutineFnWrapper]

Mark a method as one that should be callable during application create.

delete(fn: Callable[[...], Expr], /) ABIReturnSubroutine[source]
delete(*, name: str | None = None, authorize: collections.abc.Callable[[pyteal.Expr], pyteal.Expr] | pyteal.SubroutineFnWrapper | None = None, override: bool | None = False) Callable[[Callable[[...], Expr]], ABIReturnSubroutine]
delete(*, name: str | None = None, authorize: collections.abc.Callable[[pyteal.Expr], pyteal.Expr] | pyteal.SubroutineFnWrapper | None = None, bare: Literal[False], override: bool | None = False) Callable[[Callable[[...], Expr]], ABIReturnSubroutine]
delete(*, name: str | None = None, authorize: collections.abc.Callable[[pyteal.Expr], pyteal.Expr] | pyteal.SubroutineFnWrapper | None = None, bare: Literal[True], override: bool | None = False) Callable[[Callable[[], Expr]], SubroutineFnWrapper]
delete(*, name: str | None = None, authorize: collections.abc.Callable[[pyteal.Expr], pyteal.Expr] | pyteal.SubroutineFnWrapper | None = None, bare: bool, override: bool | None = False) collections.abc.Callable[[collections.abc.Callable[[...], pyteal.Expr]], pyteal.ABIReturnSubroutine] | collections.abc.Callable[[collections.abc.Callable[[], pyteal.Expr]], pyteal.SubroutineFnWrapper]

Mark a method as one that should be callable during application delete.

Parameters
  • name – The name of the method. If not provided, the name of the method will be used.

  • authorize – A function that will be called to authorize the method. If not provided, the method will not be authorized.

  • bare – If True, the router will only consider the OnComplete of the app call transaction to do routing.

  • override – If True, the method will override any existing method with the same name.

opt_in(fn: Callable[[...], Expr], /) ABIReturnSubroutine[source]
opt_in(*, allow_create: bool = False, name: str | None = None, authorize: collections.abc.Callable[[pyteal.Expr], pyteal.Expr] | pyteal.SubroutineFnWrapper | None = None, override: bool | None = False) Callable[[Callable[[...], Expr]], ABIReturnSubroutine]
opt_in(*, allow_create: bool = False, name: str | None = None, authorize: collections.abc.Callable[[pyteal.Expr], pyteal.Expr] | pyteal.SubroutineFnWrapper | None = None, bare: Literal[False], override: bool | None = False) Callable[[Callable[[...], Expr]], ABIReturnSubroutine]
opt_in(*, allow_create: bool = False, name: str | None = None, authorize: collections.abc.Callable[[pyteal.Expr], pyteal.Expr] | pyteal.SubroutineFnWrapper | None = None, bare: Literal[True], override: bool | None = False) Callable[[Callable[[], Expr]], SubroutineFnWrapper]
opt_in(*, allow_create: bool = False, name: str | None = None, authorize: collections.abc.Callable[[pyteal.Expr], pyteal.Expr] | pyteal.SubroutineFnWrapper | None = None, bare: bool = False, override: bool | None = False) collections.abc.Callable[[collections.abc.Callable[[...], pyteal.Expr]], pyteal.ABIReturnSubroutine] | collections.abc.Callable[[collections.abc.Callable[[], pyteal.Expr]], pyteal.SubroutineFnWrapper]

Mark a method as one that should be callable during application opt-in.

Parameters
  • allow_create – If True, the method will be callable even if the application does not exist.

  • name – The name of the method. If not provided, the name of the method will be used.

  • authorize – A function that will be called to authorize the method. If not provided, the method will not be authorized.

  • bare – If True, the router will only consider the OnComplete of the app call transaction to do routing.

  • override – If True, the method will override any existing method with the same name.

update(fn: Callable[[...], Expr], /) ABIReturnSubroutine[source]
update(*, name: str | None = None, authorize: collections.abc.Callable[[pyteal.Expr], pyteal.Expr] | pyteal.SubroutineFnWrapper | None = None, override: bool | None = False) Callable[[Callable[[...], Expr]], ABIReturnSubroutine]
update(*, name: str | None = None, authorize: collections.abc.Callable[[pyteal.Expr], pyteal.Expr] | pyteal.SubroutineFnWrapper | None = None, bare: Literal[False], override: bool | None = False) Callable[[Callable[[...], Expr]], ABIReturnSubroutine]
update(*, name: str | None = None, authorize: collections.abc.Callable[[pyteal.Expr], pyteal.Expr] | pyteal.SubroutineFnWrapper | None = None, bare: Literal[True], override: bool | None = False) Callable[[Callable[[], Expr]], SubroutineFnWrapper]
update(*, name: str | None = None, authorize: collections.abc.Callable[[pyteal.Expr], pyteal.Expr] | pyteal.SubroutineFnWrapper | None = None, bare: bool, override: bool | None = False) collections.abc.Callable[[collections.abc.Callable[[...], pyteal.Expr]], pyteal.ABIReturnSubroutine] | collections.abc.Callable[[collections.abc.Callable[[], pyteal.Expr]], pyteal.SubroutineFnWrapper]

Mark a method as one that should be callable during application update.

Parameters
  • name – The name of the method. If not provided, the name of the method will be used.

  • authorize – A function that will be called to authorize the method. If not provided, the method will not be authorized.

  • bare – If True, the router will only consider the OnComplete of the app call transaction to do routing.

  • override – If True, the method will override any existing method with the same name.

The ARC4 spec allows applications to define handlers for bare methods, that is, methods with no application arguments. The routing for these methods is based only on the OnComplete value of the transaction rather than the method selector of the method being invoked.