Skip to main content
Glama

Algorand MCP

by GoPlausible
developer:docs:details:dapps:writing-contracts:beaker.md15.1 kB
title: Beaker !!! note For a native Python experience, checkout our [Algorand Python](https://algorandfoundation.github.io/puya/) docs. Beaker is a framework for building Smart Contracts using PyTeal. Beaker is designed to simplify writing, testing and deploying Algorand smart contracts. The Beaker source code available on [github](https://github.com/algorand-devrel/beaker). This page provides an overview of the features available in Beaker. For complete details see the [Beaker's documentation](https://beaker.algo.xyz). # Quick start videos If you prefer videos, take a look at this playlist to learn about Beaker. Most of the videos in the list are under 12 minutes each. <iframe width="100%" style="aspect-ratio:16/9" src="https://www.youtube-nocookie.com/embed/RhfC5Xd25dk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe> # High Level Overview Beaker provides several packages that extend PyTeal and provide convenience functionality for testing and deploying smart contracts. The `Application` class is Beaker's primary class. It is used to create [ABI](/docs/get-details/dapps/smart-contracts/ABI/) compliant Algorand smart contracts. Beaker also provides decorators to route specific [application transactions](/docs/get-details/dapps/smart-contracts/apps/) to the proper functionality within a smart contract. Beaker facilitates management of [local](/docs/get-details/dapps/smart-contracts/apps/state#local-storage) and [global](/docs/get-details/dapps/smart-contracts/apps/state#global-storage) state, and [box storage](/docs/get-details/dapps/smart-contracts/apps/state#box-storage). The `ApplicationSpecification` class is used to generate a JSON manifest that describes the contract methods, source, and state schema used. This manifest can be used by other modules and utilities to deploy the smart contract. The `ApplicationClient` class can be used to connect to an Algorand node and interact with a specific `Application`. Beaker's sandbox module can be used to quickly connect to the default docker sandbox installation to deploy and call a contract. # Install Beaker can be installed using pip package manager. `pip install beaker-pyteal` Alternatively, Beaker can be installed with [AlgoKit](/docs/get-details/algokit) using the beaker project template. `algokit init --template beaker` Either of these methods will also install PyTeal in addition to Beaker. !!!note Beaker requires python version 3.10 or higher # Initialize Application To create an application simply initialize a new Beaker Application object, supplying the name and description. <!-- ===BEAKER_INIT_APP=== --> ```python from beaker import Application app = Application("MyRadApp", descr="This is a rad app") ``` [Snippet Source](https://github.com/algorand-devrel/beaker/blob/examples/examples/docs_app/app_handlers.py#L1-L4) <!-- ===BEAKER_INIT_APP=== --> This is enough to generate the `ApplicationSpecification` that can be exported for use by other tools. This spec can be generated using the `Application` `build` method. Optionally you can use the `export` method to export the approval and clear TEAL programs, the ABI contract manifest, and the application specification. !!!note At this point a complete smart contract has been written, albeit with no utility. <!-- ===BEAKER_APP_SPEC=== --> ```python app_spec = app.build() print(app_spec.to_json()) ``` [Snippet Source](https://github.com/algorand-devrel/beaker/blob/examples/examples/docs_app/app_handlers.py#L7-L9) <!-- ===BEAKER_APP_SPEC=== --> # Add Method Handlers Method handlers can be added to provide functionality within the smart contract. This can be accomplished using the `external` decorator or by using a blueprint. ## external To provide a method that can be invoked by an application call transaction, Beaker provides the `external` decorator. This instructs the framework to expose the method publicly for incoming transactions. The method is then defined with its required [method signature](/docs/get-details/dapps/smart-contracts/ABI/#methods), where the parameter types in the method signature describe the input types and output type. These types of the arguments must be valid ABI data types, using [PyTeal's ABI](https://pyteal.readthedocs.io/en/stable/abi.html) package. Arguments and output types are optional, omitting any arguments is perfectly valid. !!! note Note that input types come first, and if a value is returned it should be denoted in the method signature at the end using the notation `*, output: abi.ValidABIType`, which provides a variable to write the output into. <!-- ===BEAKER_HANDLERS_DIRECT=== --> ```python import pyteal as pt # use the decorator provided on the `app` object to register a handler @app.external def add(a: pt.abi.Uint64, b: pt.abi.Uint64, *, output: pt.abi.Uint64) -> pt.Expr: return output.set(a.get() + b.get()) ``` [Snippet Source](https://github.com/algorand-devrel/beaker/blob/examples/examples/docs_app/app_handlers.py#L13-L22) <!-- ===BEAKER_HANDLERS_DIRECT=== --> In the example above the add method is defined to take two `Uint64` arguments (`a`, `b`) and return a `Uint64` (`output`). The full method signature for the above is `add(uint64,uint64)uint64` and will, by default, field only application call transactions with an `OnComplete` of `NoOp`. ## On Complete handlers There are other decorators that can be used to modify the behavior of the method handler including `create`, `optin`, `closeout`, `clear`, `update`, and `delete`. These decorators can be used to register handlers for specific `OnComplete` values. See the [full docs](https://beaker.algo.xyz) for more details. ## Blueprints Beaker allows for a pattern called `blueprints` apply a set of method handlers to an Application. Adding handlers using a blueprint allows for code re-use and makes it easier to add behaviors, especially for applications that wish to adhere to some ARC standard. Blueprints can be defined using a standard python method definition that accepts an Application as an argument and applies the handlers. The code below defines a calculator blueprint that applies method handlers for a set of functions to implement a simple calculator. The blueprint must take an `Application` argument and optionally other arguments to modify the behavior of the blueprint An instantiated `Application` can apply this blueprint using the `.apply` method passing blueprint method as an argument. If other arguments in the blueprint method are defined, they can be passed with standard python kwarg format (i.e. `.apply(bp, arg1="hello")`) <!-- ===BEAKER_HANDLERS_BLUEPRINT=== --> ```python # passing the app to this method will register the handlers on the app def calculator_blueprint(app: Application) -> Application: @app.external def add(a: pt.abi.Uint64, b: pt.abi.Uint64, *, output: pt.abi.Uint64) -> pt.Expr: return output.set(a.get() + b.get()) @app.external def sub(a: pt.abi.Uint64, b: pt.abi.Uint64, *, output: pt.abi.Uint64) -> pt.Expr: return output.set(a.get() - b.get()) @app.external def div(a: pt.abi.Uint64, b: pt.abi.Uint64, *, output: pt.abi.Uint64) -> pt.Expr: return output.set(a.get() / b.get()) @app.external def mul(a: pt.abi.Uint64, b: pt.abi.Uint64, *, output: pt.abi.Uint64) -> pt.Expr: return output.set(a.get() * b.get()) return app calculator_app = Application("CalculatorApp", descr="This is a calculator app") calculator_app.apply(calculator_blueprint) calculator_app_spec = calculator_app.build() print(calculator_app_spec.to_json()) ``` [Snippet Source](https://github.com/algorand-devrel/beaker/blob/examples/examples/docs_app/app_handlers.py#L25-L51) <!-- ===BEAKER_HANDLERS_BLUEPRINT=== --> An application that has a blueprint applied can also implement additional handlers or apply additional blueprints. Identical method signatures are not allowed. However, if necessary, an identical method signature still be registered by adding the override attribute to the decorator, `external(override=True)`. # Add State An Application can define the state it uses to store data. This is done by defining a class that contains some number of `StateValue` objects as attributes and passing an instance of that class to the Application constructor. Beaker's `GlobalStateValue` class can be used to define and alter a contract's global state values. Global state values are defined by passing the `TealType` and a description the `GlobalStateValue` constructor. !!! note `TealType` is specific to the AVM and only `bytes`, `unit64` are acceptable values for state. The code below illustrates creating global integer counter that is stored in state. First, a `CounterState` class is created with an instance of a `GlobalStateValue` as an attribute. This class is then instantiated and passed in the `Application` constructor. Two method handlers are also added to the app to increment and decrement the counter. <!-- ===BEAKER_STATE_GLOBAL=== --> ```python import pyteal as pt from beaker import Application, GlobalStateValue class CounterState: counter = GlobalStateValue( stack_type=pt.TealType.uint64, descr="A counter for showing how to use application state", ) app = Application( "CounterApp", descr="An app that holds a counter", state=CounterState() ) @app.external def increment() -> pt.Expr: return app.state.counter.set(app.state.counter + pt.Int(1)) @app.external def decrement() -> pt.Expr: return app.state.counter.set(app.state.counter - pt.Int(1)) app_spec = app.build() print(app_spec.global_state_schema.dictify()) ``` [Snippet Source](https://github.com/algorand-devrel/beaker/blob/examples/examples/docs_app/app_state.py#L3-L31) <!-- ===BEAKER_STATE_GLOBAL=== --> Similarly, a `LocalStateValue` can be used to alter and store local state values. The code below is identical to the previous example, except the counter is stored locally. <!-- ===BEAKER_STATE_LOCAL=== --> ```python import pyteal as pt from beaker import Application, LocalStateValue class LocalCounterState: local_counter = LocalStateValue( stack_type=pt.TealType.uint64, descr="A counter for showing how to use application state", ) local_app = Application( "CounterApp", descr="An app that holds a counter", state=LocalCounterState() ) @local_app.external def user_increment() -> pt.Expr: return local_app.state.local_counter.set(local_app.state.local_counter + pt.Int(1)) @local_app.external def user_decrement() -> pt.Expr: return local_app.state.local_counter.set(local_app.state.local_counter - pt.Int(1)) local_app_spec = local_app.build() print(local_app_spec.local_state_schema.dictify()) ``` [Snippet Source](https://github.com/algorand-devrel/beaker/blob/examples/examples/docs_app/app_state.py#L34-L62) <!-- ===BEAKER_STATE_LOCAL=== --> Beaker provides the `BoxMapping` and `BoxList` classes to work in conjunction with existing PyTeal [box functionality](/docs/get-details/dapps/smart-contracts/apps/state#box-storage). In the example below a `BoxMapping` instance is defined in the `MappingState` class. Each entry in the map is keyed using the type of `Address` and stores a `Uint64` value. The method handler we define allows us to set an integer for the specific application caller's address. <!-- ===BEAKER_STATE_MAPPING=== --> ```python import pyteal as pt from beaker.lib.storage import BoxMapping class MappingState: users = BoxMapping(pt.abi.Address, pt.abi.Uint64) mapping_app = Application( "MappingApp", descr="An app that holds a mapping", state=MappingState() ) @mapping_app.external def store_user_value(value: pt.abi.Uint64) -> pt.Expr: # access an element in the mapping by key return mapping_app.state.users[pt.Txn.sender()].set(value) ``` [Snippet Source](https://github.com/algorand-devrel/beaker/blob/examples/examples/docs_app/app_state.py#L65-L84) <!-- ===BEAKER_STATE_MAPPING=== --> The `BoxList` class can be used to store a list of specific _static_ ABI types. The example below creates a box named `users` that stores a list of five addresses. The `store_user` method is passed an address and an index. The passed-in address is then stored in the `BoxList` at the specified index. <!-- ===BEAKER_STATE_LIST=== --> ```python import pyteal as pt from beaker.lib.storage import BoxList class ListState: users = BoxList(pt.abi.Address, 5) list_app = Application("ListApp", descr="An app that holds a list", state=ListState()) @list_app.external def store_user(user: pt.abi.Address, index: pt.abi.Uint64) -> pt.Expr: # access an element in the list by index return list_app.state.users[index.get()].set(user) ``` [Snippet Source](https://github.com/algorand-devrel/beaker/blob/examples/examples/docs_app/app_state.py#L88-L105) <!-- ===BEAKER_STATE_LIST=== --> # Interacting with the Application The contract can be deployed and tested using Beaker's sandbox module and the `ApplicationClient` class. The code below first retrieves the accounts from the currently running sandbox instance. A `ApplicationClient` (app_client) is then instantiated with an algod client, the `Application` class that is going to be used, and the first sandbox account (sandbox default starts with a couple of predefined accounts) which will be used to sign transactions. <!-- ===BEAKER_APP_CLIENT_INIT=== --> ```python from beaker import sandbox, client # grab funded accounts from the sandbox KMD accts = sandbox.get_accounts() # get a client for the sandbox algod algod_client = sandbox.get_algod_client() # create an application client for the calculator app app_client = client.ApplicationClient( algod_client, calculator_app, signer=accts[0].signer ) ``` [Snippet Source](https://github.com/algorand-devrel/beaker/blob/examples/examples/docs_app/app_client.py#L3-L15) <!-- ===BEAKER_APP_CLIENT_INIT=== --> The instance of `AppliationClient` can deploy the calculator app now using the `create` method. <!-- ===BEAKER_APP_CLIENT_DEPLOY=== --> ```python app_id, app_addr, txid = app_client.create() print(f"Created app with id: {app_id} and address: {app_addr} in tx: {txid}") ``` [Snippet Source](https://github.com/algorand-devrel/beaker/blob/examples/examples/docs_app/app_client.py#L19-L21) <!-- ===BEAKER_APP_CLIENT_DEPLOY=== --> The contract can then be used to call the contract. In this example the contracts `add` method is called, and two integers are passed as method arguments. Finally, the return value is printed. <!-- ===BEAKER_APP_CLIENT_CALL=== --> ```python result = app_client.call("add", a=1, b=2) print(result.return_value) # 3 ``` [Snippet Source](https://github.com/algorand-devrel/beaker/blob/examples/examples/docs_app/app_client.py#L25-L27) <!-- ===BEAKER_APP_CLIENT_CALL=== --> This is only a small sample of what Beaker can do. For more see [Beaker's documentation](https://beaker.algo.xyz)

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/GoPlausible/algorand-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server