Skip to content

Commit ee81044

Browse files
authored
feat: adding latest changes from beaker template (debugger, typed simulate) (#2)
* feat: adding latest changes from beaker template (debugger, typed simulate) * chore: minor tweaks * refactor: simplifying configuration and test variations * chore: fixing typos * feat: Update contract.py.j2 templates - Updated the `hello` method in the `contract.py.j2` template files to return a modified greeting message. - The greeting message now includes a comma after "Hello" for better readability and clarity.
1 parent a8c9a1b commit ee81044

File tree

198 files changed

+3050
-243
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

198 files changed

+3050
-243
lines changed

copier.yaml

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,13 @@ author_name:
3030
type: str
3131
help: Package author name
3232
placeholder: "Your Name"
33+
default: "Your Name"
3334

3435
author_email:
3536
type: str
3637
help: Package author email
3738
placeholder: "your@email.tld"
39+
default: "your@email.tld"
3840

3941
ide_vscode:
4042
type: bool
@@ -55,9 +57,33 @@ deployment_language:
5557
TypeScript: "typescript"
5658
default: "python"
5759

60+
use_python_pytest:
61+
type: bool
62+
when: false
63+
help: Do you want to include unit tests (via pytest)?
64+
# deployment_language is empty when using the default_language
65+
default: |-
66+
{% if deployment_language|length == 0 or deployment_language == 'python' -%}
67+
yes
68+
{%- else -%}
69+
no
70+
{%- endif %}
71+
72+
use_typescript_jest:
73+
type: bool
74+
when: false
75+
help: Do you want to include unit tests (via jest)?
76+
default: |-
77+
{% if deployment_language == 'typescript' -%}
78+
yes
79+
{%- else -%}
80+
no
81+
{%- endif %}
82+
5883
python_linter:
5984
type: str
6085
help: Do you want to use a Python linter?
86+
when: false
6187
choices:
6288
Ruff: "ruff"
6389
Flake8: "flake8"
@@ -67,39 +93,40 @@ python_linter:
6793
6894
use_python_black:
6995
type: bool
96+
when: false
7097
help: Do you want to use a Python formatter (via Black)?
7198
default: yes
7299

73100
use_python_mypy:
74101
type: bool
102+
when: false
75103
help: Do you want to use a Python type checker (via mypy)?
76104
default: |-
77105
yes
78106
79-
use_python_pytest:
80-
type: bool
81-
help: Do you want to include unit tests (via pytest)?
82-
default: yes
83-
84107
use_python_pip_audit:
85108
type: bool
109+
when: false
86110
help: Do you want to include Python dependency vulnerability scanning (via pip-audit)?
87111
default: yes
88112

89113
use_github_actions:
90114
type: bool
115+
when: false
91116
help: Do you want to include Github Actions workflows for build and testnet deployment?
92117
default: |-
93118
yes
94119
95120
use_pre_commit:
96121
type: bool
122+
when: false
97123
help: Do you want to include pre-commit for linting, type checking and formatting?
98124
default: |-
99125
yes
100126
101127
use_dispenser:
102128
type: bool
129+
when: false
103130
help: Do you want to fund your deployment account using an optional dispenser account?
104131
default: no
105132

includes/contract_name_kebab.jinja

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{{- contract_name.split('_')|join('-') -}}

includes/contract_name_pascal.jinja

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{{- contract_name.split('_')|map('capitalize')|join -}}

template_content/.algokit.toml.jinja

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[algokit]
2-
min_version = "v1.7.3"
2+
min_version = "v1.8.0"
33

44
[deploy]
55
{%- if deployment_language == 'python' %}

template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/contract.py.j2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ from puyapy.arc4 import String, abimethod
55
class {{ contract_name.split('_')|map('capitalize')|join }}(ARC4Contract):
66
@abimethod()
77
def hello(self, name: String) -> String:
8-
return String.encode(Bytes(b"Hello ") + name.decode())
8+
return String.encode(Bytes(b"Hello, ") + name.decode())

template_content/.gitignore.jinja

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ coverage.xml
5050
.hypothesis/
5151
.pytest_cache/
5252
cover/
53+
coverage/
5354

5455
# Translations
5556
*.mo
@@ -172,3 +173,6 @@ cython_debug/
172173

173174
# NPM
174175
node_modules
176+
177+
# AlgoKit
178+
debug_traces/

template_content/README.md.jinja

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,19 @@ This project has been generated using AlgoKit. See below for default getting sta
5656

5757
This project uses [GitHub Actions](https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions) to define CI/CD workflows, which are located in the [`.github/workflows`](./.github/workflows) folder.
5858

59+
### Debugging Smart Contracts
60+
61+
This project is optimized to work with AlgoKit AVM Debugger extension. To activate it:
62+
{%- if deployment_language == 'python' %}
63+
Refer to the commented header in the `__main__.py` file in the `smart_contracts` folder.
64+
{%- elif deployment_language == 'typescript' %}
65+
Refer to the commented header in the `index.ts` file in the `smart_contracts` folder.
66+
{%- endif %}
67+
68+
If you have opted in to include VSCode launch configurations in your project, you can also use the `Debug TEAL via AlgoKit AVM Debugger` launch configuration to interactively select an available trace file and launch the debug session for your smart contract.
69+
70+
For information on using and setting up the `AlgoKit AVM Debugger` VSCode extension refer [here](https://github.com/algorandfoundation/algokit-avm-vscode-debugger). To install the extension from the VSCode Marketplace, use the following link: [AlgoKit AVM Debugger extension](https://marketplace.visualstudio.com/items?itemName=algorandfoundation.algokit-avm-vscode-debugger).
71+
5972
#### Setting up GitHub for CI/CD workflow and TestNet deployment
6073

6174
1. Every time you have a change to your smart contract, and when you first initialize the project you need to [build the contract](#initial-setup) and then commit the `smart_contracts/artifacts` folder so the [output stability](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/articles/output_stability.md) tests pass

template_content/pyproject.toml.jinja

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ readme = "README.md"
77

88
[tool.poetry.dependencies]
99
python = "^3.12"
10-
algokit-utils = "^2.0.1"
10+
algokit-utils = "^2.2.0"
1111
python-dotenv = "^1.0.0"
12-
puya = "^0.1.3"
12+
puya = "^0.2.0"
1313

1414
[tool.poetry.group.dev.dependencies]
1515
{% if use_python_black -%}

template_content/smart_contracts/__main__.py.jinja

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@ from pathlib import Path
55
from dotenv import load_dotenv
66

77
from smart_contracts.config import contracts
8-
{% if deployment_language == 'python' -%}
98
from smart_contracts.helpers.build import build
9+
{% if deployment_language == 'python' -%}
1010
from smart_contracts.helpers.deploy import deploy
11-
{%- elif deployment_language == 'typescript' -%}
12-
from smart_contracts.helpers.build import build
13-
{%- endif %}
1411

12+
# Uncomment the following lines to enable auto generation of AVM Debugger compliant sourcemap and simulation trace file.
13+
# Learn more about using AlgoKit AVM Debugger to debug your TEAL source codes and inspect various kinds of
14+
# Algorand transactions in atomic groups -> https://github.com/algorandfoundation/algokit-avm-vscode-debugger
15+
# from algokit_utils.config import config
16+
# config.configure(debug=True, trace_all=True)
17+
{%- endif %}
1518
logging.basicConfig(
1619
level=logging.DEBUG, format="%(asctime)s %(levelname)-10s: %(message)s"
1720
)

template_content/smart_contracts/{% if deployment_language == 'typescript' %}index.ts{% endif %}.jinja

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,13 @@ import * as path from 'path'
33
import { consoleLogger } from '@algorandfoundation/algokit-utils/types/logging'
44
import * as algokit from '@algorandfoundation/algokit-utils'
55

6+
// Uncomment the debug and traceAll options to enable auto generation of AVM Debugger compliant sourceMap and simulation trace file.
7+
// Learn more about using AlgoKit AVM Debugger to debug your TEAL source codes and inspect various kinds of Algorand transactions in atomic groups -> https://github.com/algorandfoundation/algokit-avm-vscode-Debugger
8+
69
algokit.Config.configure({
710
logger: consoleLogger,
11+
// debug: true,
12+
// traceAll: true,
813
})
914

1015
// base directory

template_content/smart_contracts/{{ contract_name }}/contract.py.jinja

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ from puyapy.arc4 import String, abimethod
55
class {{ contract_name.split('_')|map('capitalize')|join }}(ARC4Contract):
66
@abimethod()
77
def hello(self, name: String) -> String:
8-
return String.encode(Bytes(b"Hello ") + name.decode())
8+
return String.encode(Bytes(b"Hello, ") + name.decode())

template_content/smart_contracts/{{ contract_name }}/{% if deployment_language == 'python' %}deploy_config.py{% endif %}.jinja

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,15 @@ def deploy(
1515
deployer: algokit_utils.Account,
1616
) -> None:
1717
from smart_contracts.artifacts.{{ contract_name }}.client import (
18-
{{ contract_name.split('_')|map('capitalize')|join }}Client,
18+
{% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client,
1919
)
2020

21-
app_client = {{ contract_name.split('_')|map('capitalize')|join }}Client(
21+
app_client = {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client(
2222
algod_client,
2323
creator=deployer,
2424
indexer_client=indexer_client,
2525
)
26+
2627
app_client.deploy(
2728
on_schema_break=algokit_utils.OnSchemaBreak.AppendApp,
2829
on_update=algokit_utils.OnUpdate.AppendApp,

template_content/smart_contracts/{{ contract_name }}/{% if deployment_language == 'typescript' %}deploy-config.ts{% endif %}.jinja

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export async function deploy() {
1616
},
1717
algod,
1818
)
19-
const appClient = new {{ contract_name.split('_')|map('capitalize')|join }}Client(
19+
const appClient = new {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client(
2020
{
2121
resolveBy: 'creatorAndName',
2222
findExistingUsing: indexer,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"name": "smart_contracts",
3+
"version": "1.0.0",
4+
"description": "Smart contract deployer",
5+
"main": "index.ts",
6+
"scripts": {
7+
"deploy": "ts-node-dev --transpile-only --watch .env -r dotenv/config smart_contracts/index.ts",
8+
"deploy:ci": "ts-node --transpile-only -r dotenv/config smart_contracts/index.ts",
9+
{%- if use_typescript_jest %}
10+
"test": "jest --coverage",
11+
{%- endif %}
12+
"format": "prettier --write ."
13+
},
14+
"engines": {
15+
"node": ">=18.0"
16+
},
17+
"dependencies": {
18+
"@algorandfoundation/algokit-utils": "^5.1.0",
19+
"algosdk": "^2.5.0"
20+
},
21+
"devDependencies": {
22+
{%- if use_typescript_jest %}
23+
"@types/jest": "^29.5.11",
24+
{%- endif %}
25+
"dotenv": "^16.0.3",
26+
"prettier": "^2.8.4",
27+
{%- if use_typescript_jest %}
28+
"ts-jest": "^29.1.1",
29+
{%- endif %}
30+
"ts-node-dev": "^2.0.0",
31+
"typescript": "^4.9.5"
32+
}
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ES2020",
4+
"declaration": true,
5+
"declarationMap": true,
6+
"sourceMap": true,
7+
"strict": true,
8+
"noImplicitReturns": true,
9+
"noFallthroughCasesInSwitch": true,
10+
"esModuleInterop": true,
11+
"experimentalDecorators": true,
12+
"emitDecoratorMetadata": true,
13+
"skipLibCheck": true,
14+
"forceConsistentCasingInFileNames": true,
15+
"allowJs": false,
16+
"allowSyntheticDefaultImports": true,
17+
"moduleResolution": "Node",
18+
"resolveJsonModule": true,
19+
"isolatedModules": true,
20+
"noEmit": true
21+
},
22+
"include": ["src/**/*.ts"],
23+
"exclude": ["node_modules", "dist", "coverage"]
24+
}

template_content/{% if ide_vscode %}.vscode{% endif %}/extensions.json.jinja

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"esbenp.prettier-vscode",
1717
{% endif -%}
1818
"tamasfe.even-better-toml",
19-
"editorconfig.editorconfig"
19+
"editorconfig.editorconfig",
20+
"algorandfoundation.algokit-avm-vscode-debugger"
2021
]
2122
}

template_content/{% if ide_vscode %}.vscode{% endif %}/launch.json.jinja

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@
5252
"module": "smart_contracts",
5353
"args": ["build"],
5454
"cwd": "${workspaceFolder}"
55+
},
56+
{
57+
"type": "avm",
58+
"request": "launch",
59+
"name": "Debug TEAL via AlgoKit AVM Debugger",
60+
"simulateTraceFile": "${workspaceFolder}/${command:PickSimulateTraceFile}",
61+
"stopOnEntry": true
5562
}
5663
]
5764
}

template_content/{% if use_python_pytest %}tests{% endif %}/conftest.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
import pytest
44
from algokit_utils import (
55
get_algod_client,
6+
get_indexer_client,
67
is_localnet,
78
)
89
from algosdk.v2client.algod import AlgodClient
10+
from algosdk.v2client.indexer import IndexerClient
911
from dotenv import load_dotenv
1012

1113

@@ -23,3 +25,8 @@ def algod_client() -> AlgodClient:
2325
# included here to prevent accidentally running against other networks
2426
assert is_localnet(client)
2527
return client
28+
29+
30+
@pytest.fixture(scope="session")
31+
def indexer_client() -> IndexerClient:
32+
return get_indexer_client()
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,48 @@
11
import algokit_utils
22
import pytest
33
from algokit_utils import get_localnet_default_account
4+
from algokit_utils.config import config
45
from algosdk.v2client.algod import AlgodClient
56
from algosdk.v2client.indexer import IndexerClient
67

7-
from smart_contracts.artifacts.{{ contract_name }}.client import {{ contract_name.split('_')|map('capitalize')|join }}Client
8+
from smart_contracts.artifacts.{{ contract_name }}.client import {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client
89

910

1011
@pytest.fixture(scope="session")
1112
def {{ contract_name }}_client(
1213
algod_client: AlgodClient, indexer_client: IndexerClient
13-
) -> {{ contract_name.split('_')|map('capitalize')|join }}Client:
14-
client = {{ contract_name.split('_')|map('capitalize')|join }}Client(
14+
) -> {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client:
15+
config.configure(
16+
debug=True,
17+
# trace_all=True,
18+
)
19+
20+
client = {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client(
1521
algod_client,
1622
creator=get_localnet_default_account(algod_client),
1723
indexer_client=indexer_client,
1824
)
1925

2026
client.deploy(
21-
on_schema_break=algokit_utils.OnSchemaBreak.ReplaceApp,
22-
on_update=algokit_utils.OnUpdate.UpdateApp,
23-
allow_delete=True,
24-
allow_update=True,
27+
on_schema_break=algokit_utils.OnSchemaBreak.AppendApp,
28+
on_update=algokit_utils.OnUpdate.AppendApp,
2529
)
2630
return client
2731

2832

29-
def test_says_hello({{ contract_name }}_client: {{ contract_name.split('_')|map('capitalize')|join }}Client) -> None:
33+
def test_says_hello({{ contract_name }}_client: {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client) -> None:
3034
result = {{ contract_name }}_client.hello(name="World")
3135

3236
assert result.return_value == "Hello, World"
37+
38+
39+
def test_simulate_says_hello_with_correct_budget_consumed(
40+
{{ contract_name }}_client: {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client, algod_client: AlgodClient
41+
) -> None:
42+
result = (
43+
{{ contract_name }}_client.compose().hello(name="World").hello(name="Jane").simulate()
44+
)
45+
46+
assert result.abi_results[0].return_value == "Hello, World"
47+
assert result.abi_results[1].return_value == "Hello, Jane"
48+
assert result.simulate_response["txn-groups"][0]["app-budget-consumed"] < 100

0 commit comments

Comments
 (0)