From 1a6c611c13588e65063ab3bb1b7d7a85ccaba119 Mon Sep 17 00:00:00 2001 From: "Rob Moore (MakerX)" Date: Mon, 13 Jan 2025 19:46:00 +0800 Subject: [PATCH] Added initial version of algorand typescript template without tests being run yet --- copier.yaml | 42 +- .../.algokit.toml | 52 -- .../.algokit/.copier-answers.yml | 10 - .../{{ contract_name }}/deploy_config.py.j2 | 35 -- ...ction-python-smart-contract-python-cd.yaml | 48 -- ...ction-python-smart-contract-python-ci.yaml | 64 --- .../Build_Beaker_application.xml | 35 -- .../Build_Beaker_application____LocalNet.xml | 37 -- .../Build___Deploy_Beaker_application.xml | 38 -- .../Deploy_Built_Beaker_application.xml | 36 -- .../README.md | 155 ------ .../pyproject.toml | 70 --- .../smart_contracts/cool_contract/contract.py | 9 - .../cool_contract/deploy_config.py | 35 -- .../.algokit.toml | 52 -- .../.algokit/.copier-answers.yml | 10 - .../generators/create_contract/copier.yaml | 10 - .../{{ contract_name }}/contract.py.j2 | 9 - .../generators/create_env_file/copier.yaml | 49 -- ... %}.env.{{custom_network_name}}{% endif %} | 7 - ... if is_localnet %}.env.localnet{% endif %} | 7 - ...{% if is_mainnet %}.env.mainnet{% endif %} | 3 - ...{% if is_testnet %}.env.testnet{% endif %} | 3 - ...n-python-smart-contract-typescript-cd.yaml | 48 -- ...n-python-smart-contract-typescript-ci.yaml | 64 --- .../Build_Beaker_application.xml | 35 -- .../Build_Beaker_application____LocalNet.xml | 37 -- .../Reset_AlgoKit_LocalNet.xml | 17 - .../Start_AlgoKit_LocalNet.xml | 17 - .../.pre-commit-config.yaml | 49 -- .../.vscode/extensions.json | 13 - .../.vscode/settings.json | 54 -- .../README.md | 157 ------ .../jest.config.ts | 16 - .../package.json | 30 -- .../pyproject.toml | 64 --- .../smart_contracts/__main__.py | 42 -- .../smart_contracts/_helpers/build.py | 76 --- .../smart_contracts/cool_contract/contract.py | 9 - .../cool_contract/deploy-config.ts | 33 -- .../hello_world/deploy-config.ts | 33 -- .../.algokit.toml | 42 -- .../.algokit/.copier-answers.yml | 10 - .../generators/create_contract/copier.yaml | 10 - .../{{ contract_name }}/contract.py.j2 | 9 - .../{{ contract_name }}/deploy_config.py.j2 | 35 -- .../generators/create_env_file/copier.yaml | 49 -- ... %}.env.{{custom_network_name}}{% endif %} | 7 - ... if is_localnet %}.env.localnet{% endif %} | 7 - ...{% if is_mainnet %}.env.mainnet{% endif %} | 3 - ...{% if is_testnet %}.env.testnet{% endif %} | 3 - .../.vscode/tasks.json | 79 --- .../README.md | 101 ---- .../poetry.toml | 3 - .../pyproject.toml | 22 - .../smart_contracts/__init__.py | 0 .../smart_contracts/_helpers/__init__.py | 0 .../smart_contracts/_helpers/config.py | 61 --- .../smart_contracts/cool_contract/contract.py | 9 - .../cool_contract/deploy_config.py | 35 -- .../smart_contracts/hello_world/contract.py | 8 - .../generators/create_contract/copier.yaml | 10 - .../{{ contract_name }}/contract.py.j2 | 9 - .../generators/create_env_file/copier.yaml | 49 -- ... %}.env.{{custom_network_name}}{% endif %} | 7 - ... if is_localnet %}.env.localnet{% endif %} | 7 - ...{% if is_mainnet %}.env.mainnet{% endif %} | 3 - ...{% if is_testnet %}.env.testnet{% endif %} | 3 - .../.editorconfig | 10 - .../.gitattributes | 1 - .../.gitignore | 180 ------- ...ing-started-with-your-algokit-project.tour | 51 -- .../.vscode/settings.json | 36 -- .../.vscode/tasks.json | 79 --- .../package.json | 27 - .../poetry.toml | 3 - .../pyproject.toml | 21 - .../smart_contracts/__init__.py | 0 .../smart_contracts/__main__.py | 42 -- .../smart_contracts/_helpers/__init__.py | 0 .../smart_contracts/_helpers/build.py | 76 --- .../smart_contracts/_helpers/config.py | 61 --- .../smart_contracts/cool_contract/contract.py | 9 - .../cool_contract/deploy-config.ts | 33 -- .../smart_contracts/hello_world/contract.py | 8 - .../smart_contracts/index.ts | 62 --- .../.algokit.toml | 0 .../.editorconfig | 0 .../.gitattributes | 0 .../workflows/production-python-cd.yaml | 0 .../workflows/production-python-ci.yaml | 0 .../.gitignore | 0 .../Build_Beaker_application.xml | 0 .../Build_Beaker_application____LocalNet.xml | 0 .../Build___Deploy_Beaker_application.xml | 0 .../Deploy_Built_Beaker_application.xml | 0 .../Reset_AlgoKit_LocalNet.xml | 0 .../Start_AlgoKit_LocalNet.xml | 0 .../Stop_AlgoKit_LocalNet.xml | 0 .../.pre-commit-config.yaml | 0 ...ing-started-with-your-algokit-project.tour | 0 .../.vscode/extensions.json | 0 .../.vscode/launch.json | 0 .../.vscode/settings.json | 0 .../.vscode/tasks.json | 0 .../README.md | 0 .../poetry.toml | 0 .../pyproject.toml | 0 .../smart_contracts/__init__.py | 0 .../smart_contracts/__main__.py | 0 .../smart_contracts/_helpers/__init__.py | 0 .../smart_contracts/_helpers/build.py | 0 .../smart_contracts/_helpers/config.py | 0 .../smart_contracts/_helpers/deploy.py | 0 .../smart_contracts/hello_world/contract.py | 0 .../hello_world/deploy_config.py | 0 .../tests/__init__.py | 0 .../tests/conftest.py | 0 .../tests/hello_world_client_test.py | 0 .../tests/hello_world_test.py | 0 examples/production_python/.editorconfig | 10 - examples/production_python/.gitattributes | 1 - examples/production_python/.gitignore | 180 ------- .../Reset_AlgoKit_LocalNet.xml | 17 - .../Start_AlgoKit_LocalNet.xml | 17 - .../production_python/.pre-commit-config.yaml | 49 -- ...ing-started-with-your-algokit-project.tour | 56 --- .../production_python/.vscode/extensions.json | 12 - .../production_python/.vscode/launch.json | 52 -- .../production_python/.vscode/settings.json | 52 -- examples/production_python/.vscode/tasks.json | 79 --- examples/production_python/poetry.toml | 3 - .../smart_contracts/__init__.py | 0 .../smart_contracts/__main__.py | 72 --- .../smart_contracts/_helpers/__init__.py | 0 .../smart_contracts/_helpers/build.py | 76 --- .../smart_contracts/_helpers/config.py | 61 --- .../smart_contracts/_helpers/deploy.py | 53 -- .../smart_contracts/hello_world/contract.py | 8 - .../hello_world/deploy_config.py | 36 -- examples/production_python/tests/__init__.py | 0 examples/production_python/tests/conftest.py | 26 - .../tests/hello_world_client_test.py | 48 -- .../tests/hello_world_test.py | 24 - .../{starter_python => starter}/.algokit.toml | 0 .../.editorconfig | 0 .../.gitattributes | 0 .../.gitignore | 0 ...ing-started-with-your-algokit-project.tour | 0 .../.vscode/extensions.json | 0 .../.vscode/launch.json | 0 .../.vscode/settings.json | 0 .../.vscode/tasks.json | 0 .../{starter_python => starter}/README.md | 0 .../poetry.toml | 0 .../pyproject.toml | 0 .../smart_contracts/__init__.py | 0 .../smart_contracts/__main__.py | 0 .../smart_contracts/_helpers/__init__.py | 0 .../smart_contracts/_helpers/build.py | 0 .../smart_contracts/_helpers/config.py | 0 .../smart_contracts/_helpers/deploy.py | 0 .../smart_contracts/hello_world/contract.py | 0 .../hello_world/deploy_config.py | 0 examples/starter_python/.editorconfig | 10 - examples/starter_python/.gitattributes | 1 - examples/starter_python/.gitignore | 180 ------- ...ing-started-with-your-algokit-project.tour | 51 -- .../starter_python/.vscode/extensions.json | 9 - examples/starter_python/.vscode/launch.json | 52 -- examples/starter_python/.vscode/settings.json | 33 -- examples/starter_python/poetry.toml | 3 - .../smart_contracts/__init__.py | 0 .../smart_contracts/__main__.py | 72 --- .../smart_contracts/_helpers/__init__.py | 0 .../smart_contracts/_helpers/build.py | 76 --- .../smart_contracts/_helpers/config.py | 61 --- .../smart_contracts/_helpers/deploy.py | 53 -- .../smart_contracts/hello_world/contract.py | 8 - .../hello_world/deploy_config.py | 36 -- .../.algokit.toml | 3 +- .../.algokit/.copier-answers.yml | 0 .../generators/create_contract/copier.yaml | 0 .../{{ contract_name }}/contract.py.j2 | 0 .../{{ contract_name }}/deploy-config.ts.j2 | 0 .../generators/create_env_file/copier.yaml | 0 ... %}.env.{{custom_network_name}}{% endif %} | 0 ... if is_localnet %}.env.localnet{% endif %} | 0 ...{% if is_mainnet %}.env.mainnet{% endif %} | 0 ...{% if is_testnet %}.env.testnet{% endif %} | 0 .../snapshots/HelloWorld.approval.json | 466 ++++++++++++++++++ .../snapshots/HelloWorld.clear.json | 216 ++++++++ .../.editorconfig | 3 - .../.gitattributes | 0 .../.gitignore | 0 .../.npmrc | 0 .../.prettierignore | 0 .../.prettierrc.js | 0 ...ing-started-with-your-algokit-project.tour | 0 .../.vscode/extensions.json | 4 +- .../.vscode/launch.json | 11 +- .../.vscode/settings.json | 18 + .../.vscode/tasks.json | 24 +- .../README.md | 0 ...0250113_111427_lr3650_1appl.trace.avm.json | 310 ++++++++++++ .../starter_typescript_desired/package.json | 43 ++ .../hello_world/contract.algo.ts | 11 + .../hello_world/contract.e2e.spec.ts} | 21 +- .../hello_world/contract.spec.ts | 14 + .../hello_world/deploy-config.ts | 6 +- .../smart_contracts/index.ts | 24 +- .../tsconfig.json | 0 .../tsconfig.test.json | 14 + .../vitest.config.mts | 26 + template_content/.algokit.toml.jinja | 37 +- .../generators/create_contract/copier.yaml | 5 + .../contract.algo.ts.j2 | 11 + .../contract.py.j2 | 9 - .../deploy-config.ts.j2 | 4 +- ... 'python' %}deploy_config.py.j2{% endif %} | 35 -- ...pescript' %}deploy-config.ts.j2{% endif %} | 33 -- ...tests %}contract.e2e.spec.ts{% endif %}.j2 | 36 ++ ...ude_tests %}contract.spec.ts{% endif %}.j2 | 14 + template_content/.editorconfig | 3 - template_content/.gitignore.jinja | 201 ++------ .../.npmrc | 0 template_content/README.md.jinja | 110 ++--- template_content/package.json.jinja | 56 +++ template_content/poetry.toml | 3 - template_content/pyproject.toml.jinja | 90 ---- template_content/smart_contracts/__init__.py | 0 .../smart_contracts/__main__.py.jinja | 76 --- .../smart_contracts/_helpers/__init__.py | 0 .../smart_contracts/_helpers/build.py.jinja | 79 --- .../smart_contracts/_helpers/config.py.jinja | 61 --- ...e == 'python' %}deploy.py{% endif %}.jinja | 53 -- ...= 'typescript' %}index.ts{% endif %}.jinja | 16 +- .../contract.algo.ts.jinja | 11 + .../{{ contract_name }}/contract.py.jinja | 8 - ... endif %}.jinja => deploy-config.ts.jinja} | 4 +- ...ython' %}deploy_config.py{% endif %}.jinja | 36 -- ...t %}contract.e2e.spec.ts{% endif %}.jinja} | 25 +- ...vitest %}contract.spec.ts{% endif %}.jinja | 14 + .../tsconfig.json | 0 ...arted-with-your-algokit-project.tour.jinja | 30 +- ...or use_typescript_jest %}.npmrc{% endif %} | 1 - ...pescript_jest %}.prettierignore{% endif %} | 12 - ...ypescript_jest %}.prettierrc.js{% endif %} | 10 - ...cript_jest %}package.json{% endif %}.jinja | 36 -- ...typescript_jest %}tsconfig.json{% endif %} | 25 - ...Build_Smart_Contract_application.xml.jinja | 5 +- ...Contract_application____LocalNet.xml.jinja | 9 +- ...eploy_Smart_Contract_application.xml.jinja | 4 +- ...Built_Smart_Contract_application.xml.jinja | 0 .../extensions.json.jinja | 19 +- .../launch.json | 11 +- .../launch.json.jinja | 92 ---- .../settings.json.jinja | 80 +-- .../tasks.json | 24 +- ...on_linter == 'flake8' %}.flake8{% endif %} | 4 - ...roject_name_kebab.jinja') %}-cd.yaml.jinja | 11 +- ...roject_name_kebab.jinja') %}-ci.yaml.jinja | 20 +- ...%}.pre-commit-config.yaml{% endif %}.jinja | 53 +- ... use_prettier %}.prettierignore{% endif %} | 0 ...f use_prettier %}.prettierrc.js{% endif %} | 0 .../__init__.py | 0 .../conftest.py | 26 - ...ct_name }}_client_test.py{% endif %}.jinja | 48 -- ... contract_name }}_test.py{% endif %}.jinja | 24 - ...ypescript_jest %}jest.config.ts{% endif %} | 16 - ...use_vitest %}tsconfig.test.json{% endif %} | 14 + ... use_vitest %}vitest.config.mts{% endif %} | 26 + tests/test_generators.py | 246 --------- tests/test_templates.py | 3 +- 274 files changed, 1581 insertions(+), 5979 deletions(-) delete mode 100644 examples/generators/production_python_smart_contract_python/.algokit.toml delete mode 100644 examples/generators/production_python_smart_contract_python/.algokit/.copier-answers.yml delete mode 100644 examples/generators/production_python_smart_contract_python/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/deploy_config.py.j2 delete mode 100644 examples/generators/production_python_smart_contract_python/.github/workflows/production-python-smart-contract-python-cd.yaml delete mode 100644 examples/generators/production_python_smart_contract_python/.github/workflows/production-python-smart-contract-python-ci.yaml delete mode 100644 examples/generators/production_python_smart_contract_python/.idea/runConfigurations/Build_Beaker_application.xml delete mode 100644 examples/generators/production_python_smart_contract_python/.idea/runConfigurations/Build_Beaker_application____LocalNet.xml delete mode 100644 examples/generators/production_python_smart_contract_python/.idea/runConfigurations/Build___Deploy_Beaker_application.xml delete mode 100644 examples/generators/production_python_smart_contract_python/.idea/runConfigurations/Deploy_Built_Beaker_application.xml delete mode 100644 examples/generators/production_python_smart_contract_python/README.md delete mode 100644 examples/generators/production_python_smart_contract_python/pyproject.toml delete mode 100644 examples/generators/production_python_smart_contract_python/smart_contracts/cool_contract/contract.py delete mode 100644 examples/generators/production_python_smart_contract_python/smart_contracts/cool_contract/deploy_config.py delete mode 100644 examples/generators/production_python_smart_contract_typescript/.algokit.toml delete mode 100644 examples/generators/production_python_smart_contract_typescript/.algokit/.copier-answers.yml delete mode 100644 examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_contract/copier.yaml delete mode 100644 examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 delete mode 100644 examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_env_file/copier.yaml delete mode 100644 examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_customnet %}.env.{{custom_network_name}}{% endif %} delete mode 100644 examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_localnet %}.env.localnet{% endif %} delete mode 100644 examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_mainnet %}.env.mainnet{% endif %} delete mode 100644 examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_testnet %}.env.testnet{% endif %} delete mode 100644 examples/generators/production_python_smart_contract_typescript/.github/workflows/production-python-smart-contract-typescript-cd.yaml delete mode 100644 examples/generators/production_python_smart_contract_typescript/.github/workflows/production-python-smart-contract-typescript-ci.yaml delete mode 100644 examples/generators/production_python_smart_contract_typescript/.idea/runConfigurations/Build_Beaker_application.xml delete mode 100644 examples/generators/production_python_smart_contract_typescript/.idea/runConfigurations/Build_Beaker_application____LocalNet.xml delete mode 100644 examples/generators/production_python_smart_contract_typescript/.idea/runConfigurations/Reset_AlgoKit_LocalNet.xml delete mode 100644 examples/generators/production_python_smart_contract_typescript/.idea/runConfigurations/Start_AlgoKit_LocalNet.xml delete mode 100644 examples/generators/production_python_smart_contract_typescript/.pre-commit-config.yaml delete mode 100644 examples/generators/production_python_smart_contract_typescript/.vscode/extensions.json delete mode 100644 examples/generators/production_python_smart_contract_typescript/.vscode/settings.json delete mode 100644 examples/generators/production_python_smart_contract_typescript/README.md delete mode 100644 examples/generators/production_python_smart_contract_typescript/jest.config.ts delete mode 100644 examples/generators/production_python_smart_contract_typescript/package.json delete mode 100644 examples/generators/production_python_smart_contract_typescript/pyproject.toml delete mode 100644 examples/generators/production_python_smart_contract_typescript/smart_contracts/__main__.py delete mode 100644 examples/generators/production_python_smart_contract_typescript/smart_contracts/_helpers/build.py delete mode 100644 examples/generators/production_python_smart_contract_typescript/smart_contracts/cool_contract/contract.py delete mode 100644 examples/generators/production_python_smart_contract_typescript/smart_contracts/cool_contract/deploy-config.ts delete mode 100644 examples/generators/production_python_smart_contract_typescript/smart_contracts/hello_world/deploy-config.ts delete mode 100644 examples/generators/starter_python_smart_contract_python/.algokit.toml delete mode 100644 examples/generators/starter_python_smart_contract_python/.algokit/.copier-answers.yml delete mode 100644 examples/generators/starter_python_smart_contract_python/.algokit/generators/create_contract/copier.yaml delete mode 100644 examples/generators/starter_python_smart_contract_python/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 delete mode 100644 examples/generators/starter_python_smart_contract_python/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/deploy_config.py.j2 delete mode 100644 examples/generators/starter_python_smart_contract_python/.algokit/generators/create_env_file/copier.yaml delete mode 100644 examples/generators/starter_python_smart_contract_python/.algokit/generators/create_env_file/{% if is_customnet %}.env.{{custom_network_name}}{% endif %} delete mode 100644 examples/generators/starter_python_smart_contract_python/.algokit/generators/create_env_file/{% if is_localnet %}.env.localnet{% endif %} delete mode 100644 examples/generators/starter_python_smart_contract_python/.algokit/generators/create_env_file/{% if is_mainnet %}.env.mainnet{% endif %} delete mode 100644 examples/generators/starter_python_smart_contract_python/.algokit/generators/create_env_file/{% if is_testnet %}.env.testnet{% endif %} delete mode 100644 examples/generators/starter_python_smart_contract_python/.vscode/tasks.json delete mode 100644 examples/generators/starter_python_smart_contract_python/README.md delete mode 100644 examples/generators/starter_python_smart_contract_python/poetry.toml delete mode 100644 examples/generators/starter_python_smart_contract_python/pyproject.toml delete mode 100644 examples/generators/starter_python_smart_contract_python/smart_contracts/__init__.py delete mode 100644 examples/generators/starter_python_smart_contract_python/smart_contracts/_helpers/__init__.py delete mode 100644 examples/generators/starter_python_smart_contract_python/smart_contracts/_helpers/config.py delete mode 100644 examples/generators/starter_python_smart_contract_python/smart_contracts/cool_contract/contract.py delete mode 100644 examples/generators/starter_python_smart_contract_python/smart_contracts/cool_contract/deploy_config.py delete mode 100644 examples/generators/starter_python_smart_contract_python/smart_contracts/hello_world/contract.py delete mode 100644 examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_contract/copier.yaml delete mode 100644 examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 delete mode 100644 examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_env_file/copier.yaml delete mode 100644 examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_customnet %}.env.{{custom_network_name}}{% endif %} delete mode 100644 examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_localnet %}.env.localnet{% endif %} delete mode 100644 examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_mainnet %}.env.mainnet{% endif %} delete mode 100644 examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_testnet %}.env.testnet{% endif %} delete mode 100644 examples/generators/starter_python_smart_contract_typescript/.editorconfig delete mode 100644 examples/generators/starter_python_smart_contract_typescript/.gitattributes delete mode 100644 examples/generators/starter_python_smart_contract_typescript/.gitignore delete mode 100644 examples/generators/starter_python_smart_contract_typescript/.tours/getting-started-with-your-algokit-project.tour delete mode 100644 examples/generators/starter_python_smart_contract_typescript/.vscode/settings.json delete mode 100644 examples/generators/starter_python_smart_contract_typescript/.vscode/tasks.json delete mode 100644 examples/generators/starter_python_smart_contract_typescript/package.json delete mode 100644 examples/generators/starter_python_smart_contract_typescript/poetry.toml delete mode 100644 examples/generators/starter_python_smart_contract_typescript/pyproject.toml delete mode 100644 examples/generators/starter_python_smart_contract_typescript/smart_contracts/__init__.py delete mode 100644 examples/generators/starter_python_smart_contract_typescript/smart_contracts/__main__.py delete mode 100644 examples/generators/starter_python_smart_contract_typescript/smart_contracts/_helpers/__init__.py delete mode 100644 examples/generators/starter_python_smart_contract_typescript/smart_contracts/_helpers/build.py delete mode 100644 examples/generators/starter_python_smart_contract_typescript/smart_contracts/_helpers/config.py delete mode 100644 examples/generators/starter_python_smart_contract_typescript/smart_contracts/cool_contract/contract.py delete mode 100644 examples/generators/starter_python_smart_contract_typescript/smart_contracts/cool_contract/deploy-config.ts delete mode 100644 examples/generators/starter_python_smart_contract_typescript/smart_contracts/hello_world/contract.py delete mode 100644 examples/generators/starter_python_smart_contract_typescript/smart_contracts/index.ts rename examples/{production_python => production}/.algokit.toml (100%) rename examples/{generators/production_python_smart_contract_python => production}/.editorconfig (100%) rename examples/{generators/production_python_smart_contract_python => production}/.gitattributes (100%) rename examples/{production_python => production}/.github/workflows/production-python-cd.yaml (100%) rename examples/{production_python => production}/.github/workflows/production-python-ci.yaml (100%) rename examples/{generators/production_python_smart_contract_python => production}/.gitignore (100%) rename examples/{production_python => production}/.idea/runConfigurations/Build_Beaker_application.xml (100%) rename examples/{production_python => production}/.idea/runConfigurations/Build_Beaker_application____LocalNet.xml (100%) rename examples/{production_python => production}/.idea/runConfigurations/Build___Deploy_Beaker_application.xml (100%) rename examples/{production_python => production}/.idea/runConfigurations/Deploy_Built_Beaker_application.xml (100%) rename examples/{generators/production_python_smart_contract_python => production}/.idea/runConfigurations/Reset_AlgoKit_LocalNet.xml (100%) rename examples/{generators/production_python_smart_contract_python => production}/.idea/runConfigurations/Start_AlgoKit_LocalNet.xml (100%) rename examples/{generators/production_python_smart_contract_python => production}/.idea/runConfigurations/Stop_AlgoKit_LocalNet.xml (100%) rename examples/{generators/production_python_smart_contract_python => production}/.pre-commit-config.yaml (100%) rename examples/{generators/production_python_smart_contract_python => production}/.tours/getting-started-with-your-algokit-project.tour (100%) rename examples/{generators/production_python_smart_contract_python => production}/.vscode/extensions.json (100%) rename examples/{generators/production_python_smart_contract_python => production}/.vscode/launch.json (100%) rename examples/{generators/production_python_smart_contract_python => production}/.vscode/settings.json (100%) rename examples/{generators/production_python_smart_contract_python => production}/.vscode/tasks.json (100%) rename examples/{production_python => production}/README.md (100%) rename examples/{generators/production_python_smart_contract_python => production}/poetry.toml (100%) rename examples/{production_python => production}/pyproject.toml (100%) rename examples/{generators/production_python_smart_contract_python => production}/smart_contracts/__init__.py (100%) rename examples/{generators/production_python_smart_contract_python => production}/smart_contracts/__main__.py (100%) rename examples/{generators/production_python_smart_contract_python => production}/smart_contracts/_helpers/__init__.py (100%) rename examples/{generators/production_python_smart_contract_python => production}/smart_contracts/_helpers/build.py (100%) rename examples/{generators/production_python_smart_contract_python => production}/smart_contracts/_helpers/config.py (100%) rename examples/{generators/production_python_smart_contract_python => production}/smart_contracts/_helpers/deploy.py (100%) rename examples/{generators/production_python_smart_contract_python => production}/smart_contracts/hello_world/contract.py (100%) rename examples/{generators/production_python_smart_contract_python => production}/smart_contracts/hello_world/deploy_config.py (100%) rename examples/{generators/production_python_smart_contract_python => production}/tests/__init__.py (100%) rename examples/{generators/production_python_smart_contract_python => production}/tests/conftest.py (100%) rename examples/{generators/production_python_smart_contract_python => production}/tests/hello_world_client_test.py (100%) rename examples/{generators/production_python_smart_contract_python => production}/tests/hello_world_test.py (100%) delete mode 100644 examples/production_python/.editorconfig delete mode 100644 examples/production_python/.gitattributes delete mode 100644 examples/production_python/.gitignore delete mode 100644 examples/production_python/.idea/runConfigurations/Reset_AlgoKit_LocalNet.xml delete mode 100644 examples/production_python/.idea/runConfigurations/Start_AlgoKit_LocalNet.xml delete mode 100644 examples/production_python/.pre-commit-config.yaml delete mode 100644 examples/production_python/.tours/getting-started-with-your-algokit-project.tour delete mode 100644 examples/production_python/.vscode/extensions.json delete mode 100644 examples/production_python/.vscode/launch.json delete mode 100644 examples/production_python/.vscode/settings.json delete mode 100644 examples/production_python/.vscode/tasks.json delete mode 100644 examples/production_python/poetry.toml delete mode 100644 examples/production_python/smart_contracts/__init__.py delete mode 100644 examples/production_python/smart_contracts/__main__.py delete mode 100644 examples/production_python/smart_contracts/_helpers/__init__.py delete mode 100644 examples/production_python/smart_contracts/_helpers/build.py delete mode 100644 examples/production_python/smart_contracts/_helpers/config.py delete mode 100644 examples/production_python/smart_contracts/_helpers/deploy.py delete mode 100644 examples/production_python/smart_contracts/hello_world/contract.py delete mode 100644 examples/production_python/smart_contracts/hello_world/deploy_config.py delete mode 100644 examples/production_python/tests/__init__.py delete mode 100644 examples/production_python/tests/conftest.py delete mode 100644 examples/production_python/tests/hello_world_client_test.py delete mode 100644 examples/production_python/tests/hello_world_test.py rename examples/{starter_python => starter}/.algokit.toml (100%) rename examples/{generators/production_python_smart_contract_typescript => starter}/.editorconfig (100%) rename examples/{generators/production_python_smart_contract_typescript => starter}/.gitattributes (100%) rename examples/{generators/production_python_smart_contract_typescript => starter}/.gitignore (100%) rename examples/{generators/starter_python_smart_contract_python => starter}/.tours/getting-started-with-your-algokit-project.tour (100%) rename examples/{generators/starter_python_smart_contract_python => starter}/.vscode/extensions.json (100%) rename examples/{generators/starter_python_smart_contract_python => starter}/.vscode/launch.json (100%) rename examples/{generators/starter_python_smart_contract_python => starter}/.vscode/settings.json (100%) rename examples/{generators/production_python_smart_contract_typescript => starter}/.vscode/tasks.json (100%) rename examples/{starter_python => starter}/README.md (100%) rename examples/{generators/production_python_smart_contract_typescript => starter}/poetry.toml (100%) rename examples/{starter_python => starter}/pyproject.toml (100%) rename examples/{generators/production_python_smart_contract_typescript => starter}/smart_contracts/__init__.py (100%) rename examples/{generators/starter_python_smart_contract_python => starter}/smart_contracts/__main__.py (100%) rename examples/{generators/production_python_smart_contract_typescript => starter}/smart_contracts/_helpers/__init__.py (100%) rename examples/{generators/starter_python_smart_contract_python => starter}/smart_contracts/_helpers/build.py (100%) rename examples/{generators/production_python_smart_contract_typescript => starter}/smart_contracts/_helpers/config.py (100%) rename examples/{generators/starter_python_smart_contract_python => starter}/smart_contracts/_helpers/deploy.py (100%) rename examples/{generators/production_python_smart_contract_typescript => starter}/smart_contracts/hello_world/contract.py (100%) rename examples/{generators/starter_python_smart_contract_python => starter}/smart_contracts/hello_world/deploy_config.py (100%) delete mode 100644 examples/starter_python/.editorconfig delete mode 100644 examples/starter_python/.gitattributes delete mode 100644 examples/starter_python/.gitignore delete mode 100644 examples/starter_python/.tours/getting-started-with-your-algokit-project.tour delete mode 100644 examples/starter_python/.vscode/extensions.json delete mode 100644 examples/starter_python/.vscode/launch.json delete mode 100644 examples/starter_python/.vscode/settings.json delete mode 100644 examples/starter_python/poetry.toml delete mode 100644 examples/starter_python/smart_contracts/__init__.py delete mode 100644 examples/starter_python/smart_contracts/__main__.py delete mode 100644 examples/starter_python/smart_contracts/_helpers/__init__.py delete mode 100644 examples/starter_python/smart_contracts/_helpers/build.py delete mode 100644 examples/starter_python/smart_contracts/_helpers/config.py delete mode 100644 examples/starter_python/smart_contracts/_helpers/deploy.py delete mode 100644 examples/starter_python/smart_contracts/hello_world/contract.py delete mode 100644 examples/starter_python/smart_contracts/hello_world/deploy_config.py rename examples/{generators/starter_python_smart_contract_typescript => starter_typescript_desired}/.algokit.toml (97%) rename examples/{generators/starter_python_smart_contract_typescript => starter_typescript_desired}/.algokit/.copier-answers.yml (100%) rename examples/{generators/production_python_smart_contract_python => starter_typescript_desired}/.algokit/generators/create_contract/copier.yaml (100%) rename examples/{generators/production_python_smart_contract_python => starter_typescript_desired}/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 (100%) rename examples/{generators/production_python_smart_contract_typescript => starter_typescript_desired}/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/deploy-config.ts.j2 (100%) rename examples/{generators/production_python_smart_contract_python => starter_typescript_desired}/.algokit/generators/create_env_file/copier.yaml (100%) rename examples/{generators/production_python_smart_contract_python => starter_typescript_desired}/.algokit/generators/create_env_file/{% if is_customnet %}.env.{{custom_network_name}}{% endif %} (100%) rename examples/{generators/production_python_smart_contract_python => starter_typescript_desired}/.algokit/generators/create_env_file/{% if is_localnet %}.env.localnet{% endif %} (100%) rename examples/{generators/production_python_smart_contract_python => starter_typescript_desired}/.algokit/generators/create_env_file/{% if is_mainnet %}.env.mainnet{% endif %} (100%) rename examples/{generators/production_python_smart_contract_python => starter_typescript_desired}/.algokit/generators/create_env_file/{% if is_testnet %}.env.testnet{% endif %} (100%) create mode 100644 examples/starter_typescript_desired/.algokit/static-analysis/snapshots/HelloWorld.approval.json create mode 100644 examples/starter_typescript_desired/.algokit/static-analysis/snapshots/HelloWorld.clear.json rename examples/{generators/starter_python_smart_contract_python => starter_typescript_desired}/.editorconfig (80%) rename examples/{generators/starter_python_smart_contract_python => starter_typescript_desired}/.gitattributes (100%) rename examples/{generators/starter_python_smart_contract_python => starter_typescript_desired}/.gitignore (100%) rename examples/{generators/production_python_smart_contract_typescript => starter_typescript_desired}/.npmrc (100%) rename examples/{generators/production_python_smart_contract_typescript => starter_typescript_desired}/.prettierignore (100%) rename examples/{generators/production_python_smart_contract_typescript => starter_typescript_desired}/.prettierrc.js (100%) rename examples/{generators/production_python_smart_contract_typescript => starter_typescript_desired}/.tours/getting-started-with-your-algokit-project.tour (100%) rename examples/{generators/starter_python_smart_contract_typescript => starter_typescript_desired}/.vscode/extensions.json (75%) rename examples/{generators/starter_python_smart_contract_typescript => starter_typescript_desired}/.vscode/launch.json (87%) create mode 100644 examples/starter_typescript_desired/.vscode/settings.json rename examples/{starter_python => starter_typescript_desired}/.vscode/tasks.json (71%) rename examples/{generators/starter_python_smart_contract_typescript => starter_typescript_desired}/README.md (100%) create mode 100644 examples/starter_typescript_desired/debug-traces/20250113_111427_lr3650_1appl.trace.avm.json create mode 100644 examples/starter_typescript_desired/package.json create mode 100644 examples/starter_typescript_desired/smart_contracts/hello_world/contract.algo.ts rename examples/{generators/production_python_smart_contract_typescript/tests/hello-world.spec.ts => starter_typescript_desired/smart_contracts/hello_world/contract.e2e.spec.ts} (64%) create mode 100644 examples/starter_typescript_desired/smart_contracts/hello_world/contract.spec.ts rename examples/{generators/starter_python_smart_contract_typescript => starter_typescript_desired}/smart_contracts/hello_world/deploy-config.ts (87%) rename examples/{generators/production_python_smart_contract_typescript => starter_typescript_desired}/smart_contracts/index.ts (71%) rename examples/{generators/production_python_smart_contract_typescript => starter_typescript_desired}/tsconfig.json (100%) create mode 100644 examples/starter_typescript_desired/tsconfig.test.json create mode 100644 examples/starter_typescript_desired/vitest.config.mts create mode 100644 template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/contract.algo.ts.j2 delete mode 100644 template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/contract.py.j2 rename {examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }} => template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}}/deploy-config.ts.j2 (91%) delete mode 100644 template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/{% if deployment_language == 'python' %}deploy_config.py.j2{% endif %} delete mode 100644 template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/{% if deployment_language == 'typescript' %}deploy-config.ts.j2{% endif %} create mode 100644 template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/{% if include_tests %}contract.e2e.spec.ts{% endif %}.j2 create mode 100644 template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/{% if include_tests %}contract.spec.ts{% endif %}.j2 rename {examples/generators/starter_python_smart_contract_typescript => template_content}/.npmrc (100%) create mode 100644 template_content/package.json.jinja delete mode 100644 template_content/poetry.toml delete mode 100644 template_content/pyproject.toml.jinja delete mode 100644 template_content/smart_contracts/__init__.py delete mode 100644 template_content/smart_contracts/__main__.py.jinja delete mode 100644 template_content/smart_contracts/_helpers/__init__.py delete mode 100644 template_content/smart_contracts/_helpers/build.py.jinja delete mode 100644 template_content/smart_contracts/_helpers/config.py.jinja delete mode 100644 template_content/smart_contracts/_helpers/{% if deployment_language == 'python' %}deploy.py{% endif %}.jinja create mode 100644 template_content/smart_contracts/{{ contract_name }}/contract.algo.ts.jinja delete mode 100644 template_content/smart_contracts/{{ contract_name }}/contract.py.jinja rename template_content/smart_contracts/{{ contract_name }}/{{% if deployment_language == 'typescript' %}deploy-config.ts{% endif %}.jinja => deploy-config.ts.jinja} (91%) delete mode 100644 template_content/smart_contracts/{{ contract_name }}/{% if deployment_language == 'python' %}deploy_config.py{% endif %}.jinja rename template_content/{{% if use_typescript_jest %}tests{% endif %}/{% if use_typescript_jest %}{% include pathjoin('includes', 'contract_name_kebab.jinja') %}.spec.ts{% endif %}.jinja => smart_contracts/{{ contract_name }}/{% if use_vitest %}contract.e2e.spec.ts{% endif %}.jinja} (54%) create mode 100644 template_content/smart_contracts/{{ contract_name }}/{% if use_vitest %}contract.spec.ts{% endif %}.jinja rename {examples/generators/starter_python_smart_contract_typescript => template_content}/tsconfig.json (100%) delete mode 100644 template_content/{% if deployment_language == 'typescript' or use_typescript_jest %}.npmrc{% endif %} delete mode 100644 template_content/{% if deployment_language == 'typescript' or use_typescript_jest %}.prettierignore{% endif %} delete mode 100644 template_content/{% if deployment_language == 'typescript' or use_typescript_jest %}.prettierrc.js{% endif %} delete mode 100644 template_content/{% if deployment_language == 'typescript' or use_typescript_jest %}package.json{% endif %}.jinja delete mode 100644 template_content/{% if deployment_language == 'typescript' or use_typescript_jest %}tsconfig.json{% endif %} rename examples/production_python/.idea/runConfigurations/Stop_AlgoKit_LocalNet.xml => template_content/{% if ide_jetbrains %}.idea{% endif %}/runConfigurations/Build_Smart_Contract_application.xml.jinja (79%) rename examples/generators/production_python_smart_contract_typescript/.idea/runConfigurations/Stop_AlgoKit_LocalNet.xml => template_content/{% if ide_jetbrains %}.idea{% endif %}/runConfigurations/Build_Smart_Contract_application____LocalNet.xml.jinja (65%) rename examples/generators/production_python_smart_contract_typescript/.idea/runConfigurations/Build___Deploy_Beaker_application.xml => template_content/{% if ide_jetbrains %}.idea{% endif %}/runConfigurations/Build___Deploy_Smart_Contract_application.xml.jinja (89%) rename examples/generators/production_python_smart_contract_typescript/.idea/runConfigurations/Deploy_Built_Beaker_application.xml => template_content/{% if ide_jetbrains %}.idea{% endif %}/runConfigurations/Deploy_Built_Smart_Contract_application.xml.jinja (100%) rename {examples/generators/production_python_smart_contract_typescript/.vscode => template_content/{% if ide_vscode %}.vscode{% endif %}}/launch.json (87%) delete mode 100644 template_content/{% if ide_vscode %}.vscode{% endif %}/launch.json.jinja delete mode 100644 template_content/{% if python_linter == 'flake8' %}.flake8{% endif %} rename examples/generators/starter_python_smart_contract_typescript/.prettierignore => template_content/{% if use_prettier %}.prettierignore{% endif %} (100%) rename examples/generators/starter_python_smart_contract_typescript/.prettierrc.js => template_content/{% if use_prettier %}.prettierrc.js{% endif %} (100%) delete mode 100644 template_content/{% if use_python_pytest %}tests{% endif %}/__init__.py delete mode 100644 template_content/{% if use_python_pytest %}tests{% endif %}/conftest.py delete mode 100644 template_content/{% if use_python_pytest %}tests{% endif %}/{% if use_python_pytest %}{{ contract_name }}_client_test.py{% endif %}.jinja delete mode 100644 template_content/{% if use_python_pytest %}tests{% endif %}/{% if use_python_pytest %}{{ contract_name }}_test.py{% endif %}.jinja delete mode 100644 template_content/{% if use_typescript_jest %}jest.config.ts{% endif %} create mode 100644 template_content/{% if use_vitest %}tsconfig.test.json{% endif %} create mode 100644 template_content/{% if use_vitest %}vitest.config.mts{% endif %} delete mode 100644 tests/test_generators.py diff --git a/copier.yaml b/copier.yaml index d9f7c11..d029905 100644 --- a/copier.yaml +++ b/copier.yaml @@ -44,14 +44,6 @@ preset_name: "Custom - for tailoring the template output to your needs": "custom" default: "starter" -deployment_language: - type: str - help: What programming language do you want to use for your contract deployment code? - choices: - Python: "python" - TypeScript: "typescript" - default: "python" - ide_vscode: type: bool help: Do you want to add VSCode configuration? @@ -70,44 +62,28 @@ ide_jetbrains: when: "{{ preset_name == 'custom' }}" default: "{{ 'yes' if preset_name == 'production' else 'no' }}" -use_python_pytest: - type: bool - when: "{{ deployment_language == 'python' and preset_name == 'custom' }}" - help: Do you want to include unit tests (via pytest)? - default: "{{ 'yes' if preset_name == 'production' and deployment_language == 'python' else 'no' }}" - -use_typescript_jest: +use_vitest: type: bool - when: "{{ deployment_language == 'typescript' and preset_name == 'custom' }}" - help: Do you want to include unit tests (via jest)? - default: "{{ 'yes' if preset_name == 'production' and deployment_language == 'typescript' else 'no' }}" - -python_linter: - type: str - help: Do you want to use a Python linter? when: "{{ preset_name == 'custom' }}" - choices: - Ruff: "ruff" - Flake8: "flake8" - No thanks: "none" - default: "{{ 'ruff' if preset_name == 'production' else 'none' }}" + help: Do you want to include unit tests (via vitest)? + default: "{{ 'yes' if preset_name == 'production' else 'no' }}" -use_python_black: +use_linter: type: bool - help: Do you want to use a Python formatter (via Black)? + help: Do you want to use a linter (via ESLint)? when: "{{ preset_name == 'custom' }}" default: "{{ 'yes' if preset_name == 'production' else 'no' }}" -use_python_mypy: +use_prettier: type: bool + help: Do you want to use a formatter (via Prettier)? when: "{{ preset_name == 'custom' }}" - help: Do you want to use a Python type checker (via mypy)? default: "{{ 'yes' if preset_name == 'production' else 'no' }}" -use_python_pip_audit: +use_audit: type: bool when: "{{ preset_name == 'custom' }}" - help: Do you want to include Python dependency vulnerability scanning (via pip-audit)? + help: Do you want to include dependency vulnerability scanning (via better-npm-audit)? default: "{{ 'yes' if preset_name == 'production' else 'no' }}" use_github_actions: diff --git a/examples/generators/production_python_smart_contract_python/.algokit.toml b/examples/generators/production_python_smart_contract_python/.algokit.toml deleted file mode 100644 index 69bba4a..0000000 --- a/examples/generators/production_python_smart_contract_python/.algokit.toml +++ /dev/null @@ -1,52 +0,0 @@ -[algokit] -min_version = "v2.0.0" - -[generate.smart-contract] -description = "Generate a new smart contract for existing project" -path = ".algokit/generators/create_contract" - -[generate.env-file] -description = "Generate a new generic or Algorand network specific .env file" -path = ".algokit/generators/create_env_file" - -[project] -type = 'contract' -name = 'production_python_smart_contract_python' -artifacts = 'smart_contracts/artifacts' - -[project.deploy] -command = "poetry run python -m smart_contracts deploy" -environment_secrets = [ - "DEPLOYER_MNEMONIC", - "DISPENSER_MNEMONIC", -] - -[project.deploy.localnet] -environment_secrets = [] - -[project.run] -# Commands intented for use locally and in CI -build = { commands = [ - 'poetry run python -m smart_contracts build', -], description = 'Build all smart contracts in the project' } -test = { commands = [ - 'poetry run pytest', -], description = 'Run smart contract tests' } -audit = { commands = [ - 'poetry run pip-audit', -], description = 'Audit with pip-audit' } -lint = { commands = [ - 'poetry run black --check --diff .', - 'poetry run ruff check .', - 'poetry run mypy', -], description = 'Perform linting' } -audit-teal = { commands = [ - # 🚨 IMPORTANT 🚨: For strict TEAL validation, remove --exclude statements. The default starter contract is not for production. Ensure thorough testing and adherence to best practices in smart contract development. This is not a replacement for a professional audit. - 'algokit task analyze smart_contracts/artifacts --recursive --force --exclude rekey-to --exclude is-updatable --exclude missing-fee-check --exclude is-deletable --exclude can-close-asset --exclude can-close-account --exclude unprotected-deletable --exclude unprotected-updatable', -], description = 'Audit TEAL files' } - -# Commands intented for CI only, prefixed with `ci-` by convention -ci-teal-diff = { commands = [ - 'git add -N ./smart_contracts/artifacts', - 'git diff --exit-code --minimal ./smart_contracts/artifacts', -], description = 'Check TEAL files for differences' } diff --git a/examples/generators/production_python_smart_contract_python/.algokit/.copier-answers.yml b/examples/generators/production_python_smart_contract_python/.algokit/.copier-answers.yml deleted file mode 100644 index db599c8..0000000 --- a/examples/generators/production_python_smart_contract_python/.algokit/.copier-answers.yml +++ /dev/null @@ -1,10 +0,0 @@ -# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY -_commit: -_src_path: -author_email: None -author_name: None -contract_name: hello_world -deployment_language: python -preset_name: production -project_name: production_python_smart_contract_python - diff --git a/examples/generators/production_python_smart_contract_python/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/deploy_config.py.j2 b/examples/generators/production_python_smart_contract_python/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/deploy_config.py.j2 deleted file mode 100644 index eb726b9..0000000 --- a/examples/generators/production_python_smart_contract_python/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/deploy_config.py.j2 +++ /dev/null @@ -1,35 +0,0 @@ -import logging - -import algokit_utils -from algosdk.v2client.algod import AlgodClient -from algosdk.v2client.indexer import IndexerClient - -logger = logging.getLogger(__name__) - - -# define deployment behaviour based on supplied app spec -def deploy( - algod_client: AlgodClient, - indexer_client: IndexerClient, - app_spec: algokit_utils.ApplicationSpecification, - deployer: algokit_utils.Account, -) -> None: - from smart_contracts.artifacts.{{ contract_name }}.{{ contract_name }}_client import ( - {{ contract_name.split('_')|map('capitalize')|join }}Client, - ) - - app_client = {{ contract_name.split('_')|map('capitalize')|join }}Client( - algod_client, - creator=deployer, - indexer_client=indexer_client, - ) - app_client.deploy( - on_schema_break=algokit_utils.OnSchemaBreak.AppendApp, - on_update=algokit_utils.OnUpdate.AppendApp, - ) - name = "world" - response = app_client.hello(name=name) - logger.info( - f"Called hello on {app_spec.contract.name} ({app_client.app_id}) " - f"with name={name}, received: {response.return_value}" - ) diff --git a/examples/generators/production_python_smart_contract_python/.github/workflows/production-python-smart-contract-python-cd.yaml b/examples/generators/production_python_smart_contract_python/.github/workflows/production-python-smart-contract-python-cd.yaml deleted file mode 100644 index a022c98..0000000 --- a/examples/generators/production_python_smart_contract_python/.github/workflows/production-python-smart-contract-python-cd.yaml +++ /dev/null @@ -1,48 +0,0 @@ -name: Release production_python_smart_contract_python - -on: - workflow_call: - push: - branches: - - main - -jobs: - validate: - name: Validate production_python_smart_contract_python - uses: ./.github/workflows/production-python-smart-contract-python-ci.yaml - deploy-testnet: - runs-on: "ubuntu-latest" - needs: validate - environment: contract-testnet - steps: - - name: Checkout source code - uses: actions/checkout@v4 - - - name: Install poetry - run: pipx install poetry - - - name: Set up Python 3.12 - uses: actions/setup-python@v5 - with: - python-version: "3.12" - cache: "poetry" - - - name: Install algokit - run: pipx install algokit - - - name: Bootstrap dependencies - run: algokit project bootstrap all - - - name: Configure git - shell: bash - run: | - # set git user and email as test invoke git - git config --global user.email "actions@github.com" && git config --global user.name "github-actions" - - - name: Deploy to testnet - run: algokit project deploy testnet - env: - # This is the account that becomes the creator of the contract - DEPLOYER_MNEMONIC: ${{ secrets.DEPLOYER_MNEMONIC }} - # The dispenser account is used to ensure the deployer account is funded - DISPENSER_MNEMONIC: ${{ secrets.DISPENSER_MNEMONIC }} diff --git a/examples/generators/production_python_smart_contract_python/.github/workflows/production-python-smart-contract-python-ci.yaml b/examples/generators/production_python_smart_contract_python/.github/workflows/production-python-smart-contract-python-ci.yaml deleted file mode 100644 index d0fa078..0000000 --- a/examples/generators/production_python_smart_contract_python/.github/workflows/production-python-smart-contract-python-ci.yaml +++ /dev/null @@ -1,64 +0,0 @@ -name: Validate production_python_smart_contract_python - -on: - workflow_call: - pull_request: - -jobs: - validate: - runs-on: "ubuntu-latest" - steps: - - name: Checkout source code - uses: actions/checkout@v4 - - - name: Install poetry - run: pipx install poetry - - - name: Set up Python 3.12 - uses: actions/setup-python@v5 - with: - python-version: "3.12" - cache: "poetry" - - - name: Install algokit - run: pipx install algokit - - - name: Start LocalNet - run: algokit localnet start - - - name: Bootstrap dependencies - run: algokit project bootstrap all - - - name: Configure git - shell: bash - run: | - # set git user and email as test invoke git - git config --global user.email "actions@github.com" && git config --global user.name "github-actions" - - - name: Audit python dependencies - run: algokit project run audit - - - name: Lint and format python dependencies - run: algokit project run lint - - - name: Run tests - shell: bash - run: | - set -o pipefail - algokit project run test - - - name: Build smart contracts - run: algokit project run build - - - name: Scan TEAL files for issues - run: algokit project run audit-teal - - # # Uncomment to enable TEAL static analysis with snapshoting using Tealer package - # # Would first require running locally using audit-teal command and committing the snapshots into source control - # # Please note, tealer has a known bug that may result in large snapshot file sizes, track resolution here: - # # https://github.com/crytic/tealer/issues/101 - # - name: Check output stability of the smart contracts - # run: algokit project run ci-teal-diff - - - name: Run deployer against LocalNet - run: algokit project deploy localnet diff --git a/examples/generators/production_python_smart_contract_python/.idea/runConfigurations/Build_Beaker_application.xml b/examples/generators/production_python_smart_contract_python/.idea/runConfigurations/Build_Beaker_application.xml deleted file mode 100644 index f0a1d62..0000000 --- a/examples/generators/production_python_smart_contract_python/.idea/runConfigurations/Build_Beaker_application.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - diff --git a/examples/generators/production_python_smart_contract_python/.idea/runConfigurations/Build_Beaker_application____LocalNet.xml b/examples/generators/production_python_smart_contract_python/.idea/runConfigurations/Build_Beaker_application____LocalNet.xml deleted file mode 100644 index 8730b9c..0000000 --- a/examples/generators/production_python_smart_contract_python/.idea/runConfigurations/Build_Beaker_application____LocalNet.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - diff --git a/examples/generators/production_python_smart_contract_python/.idea/runConfigurations/Build___Deploy_Beaker_application.xml b/examples/generators/production_python_smart_contract_python/.idea/runConfigurations/Build___Deploy_Beaker_application.xml deleted file mode 100644 index f4e0f96..0000000 --- a/examples/generators/production_python_smart_contract_python/.idea/runConfigurations/Build___Deploy_Beaker_application.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - diff --git a/examples/generators/production_python_smart_contract_python/.idea/runConfigurations/Deploy_Built_Beaker_application.xml b/examples/generators/production_python_smart_contract_python/.idea/runConfigurations/Deploy_Built_Beaker_application.xml deleted file mode 100644 index f13cffc..0000000 --- a/examples/generators/production_python_smart_contract_python/.idea/runConfigurations/Deploy_Built_Beaker_application.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - diff --git a/examples/generators/production_python_smart_contract_python/README.md b/examples/generators/production_python_smart_contract_python/README.md deleted file mode 100644 index 715d773..0000000 --- a/examples/generators/production_python_smart_contract_python/README.md +++ /dev/null @@ -1,155 +0,0 @@ -# production_python_smart_contract_python - -This project has been generated using AlgoKit. See below for default getting started instructions. - -# Setup - -### Pre-requisites - -- [Python 3.12](https://www.python.org/downloads/) or later -- [Docker](https://www.docker.com/) (only required for LocalNet) - -> For interactive tour over the codebase, download [vsls-contrib.codetour](https://marketplace.visualstudio.com/items?itemName=vsls-contrib.codetour) extension for VS Code, then open the [`.codetour.json`](./.tours/getting-started-with-your-algokit-project.tour) file in code tour extension. - -### Initial Setup - -#### 1. Clone the Repository -Start by cloning this repository to your local machine. - -#### 2. Install Pre-requisites -Ensure the following pre-requisites are installed and properly configured: - -- **Docker**: Required for running a local Algorand network. [Install Docker](https://www.docker.com/). -- **AlgoKit CLI**: Essential for project setup and operations. Install the latest version from [AlgoKit CLI Installation Guide](https://github.com/algorandfoundation/algokit-cli#install). Verify installation with `algokit --version`, expecting `2.0.0` or later. - -#### 3. Bootstrap Your Local Environment -Run the following commands within the project folder: - -- **Install Poetry**: Required for Python dependency management. [Installation Guide](https://python-poetry.org/docs/#installation). Verify with `poetry -V` to see version `1.2`+. -- **Setup Project**: Execute `algokit project bootstrap all` to install dependencies and setup a Python virtual environment in `.venv`. -- **Configure environment**: Execute `algokit generate env-file -a target_network localnet` to create a `.env.localnet` file with default configuration for `localnet`. -- **Start LocalNet**: Use `algokit localnet start` to initiate a local Algorand network. - -### Development Workflow - -#### Terminal -Directly manage and interact with your project using AlgoKit commands: - -1. **Build Contracts**: `algokit project run build` compiles all smart contracts. You can also specify a specific contract by passing the name of the contract folder as an extra argument. -For example: `algokit project run build -- hello_world` will only build the `hello_world` contract. -2. **Deploy**: Use `algokit project deploy localnet` to deploy contracts to the local network. You can also specify a specific contract by passing the name of the contract folder as an extra argument. -For example: `algokit project deploy localnet -- hello_world` will only deploy the `hello_world` contract. - -#### VS Code -For a seamless experience with breakpoint debugging and other features: - -1. **Open Project**: In VS Code, open the repository root. -2. **Install Extensions**: Follow prompts to install recommended extensions. -3. **Debugging**: - - Use `F5` to start debugging. - - **Windows Users**: Select the Python interpreter at `./.venv/Scripts/python.exe` via `Ctrl/Cmd + Shift + P` > `Python: Select Interpreter` before the first run. - -#### JetBrains IDEs -While primarily optimized for VS Code, JetBrains IDEs are supported: - -1. **Open Project**: In your JetBrains IDE, open the repository root. -2. **Automatic Setup**: The IDE should configure the Python interpreter and virtual environment. -3. **Debugging**: Use `Shift+F10` or `Ctrl+R` to start debugging. Note: Windows users may encounter issues with pre-launch tasks due to a known bug. See [JetBrains forums](https://youtrack.jetbrains.com/issue/IDEA-277486/Shell-script-configuration-cannot-run-as-before-launch-task) for workarounds. - -## AlgoKit Workspaces and Project Management -This project supports both standalone and monorepo setups through AlgoKit workspaces. Leverage [`algokit project run`](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/project/run.md) commands for efficient monorepo project orchestration and management across multiple projects within a workspace. - -## AlgoKit Generators - -This template provides a set of [algokit generators](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/generate.md) that allow you to further modify the project instantiated from the template to fit your needs, as well as giving you a base to build your own extensions to invoke via the `algokit generate` command. - -### Generate Smart Contract - -By default the template creates a single `HelloWorld` contract under hello_world folder in the `smart_contracts` directory. To add a new contract: - -1. From the root of the project (`../`) execute `algokit generate smart-contract`. This will create a new starter smart contract and deployment configuration file under `{your_contract_name}` subfolder in the `smart_contracts` directory. -2. Each contract potentially has different creation parameters and deployment steps. Hence, you need to define your deployment logic in `deploy_config.py`file. -3. `config.py` file will automatically build all contracts in the `smart_contracts` directory. If you want to build specific contracts manually, modify the default code provided by the template in `config.py` file. - -> Please note, above is just a suggested convention tailored for the base configuration and structure of this template. The default code supplied by the template in `config.py` and `index.ts` (if using ts clients) files are tailored for the suggested convention. You are free to modify the structure and naming conventions as you see fit. - -### Generate '.env' files - -By default the template instance does not contain any env files. Using [`algokit project deploy`](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/project/deploy.md) against `localnet` | `testnet` | `mainnet` will use default values for `algod` and `indexer` unless overwritten via `.env` or `.env.{target_network}`. - -To generate a new `.env` or `.env.{target_network}` file, run `algokit generate env-file` - -### Debugging Smart Contracts - -This project is optimized to work with AlgoKit AVM Debugger extension. To activate it: -Refer to the commented header in the `__main__.py` file in the `smart_contracts` folder. - -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. - -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).### Continuous Integration / Continuous Deployment (CI/CD) - -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. - -> Please note, if you instantiated the project with --workspace flag in `algokit init` it will automatically attempt to move the contents of the `.github` folder to the root of the workspace. - -### AlgoKit Workspaces - -To define custom `algokit project run` commands refer to [documentation](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/project/run.md). This allows orchestration of commands spanning across multiple projects within an algokit workspace based project (monorepo). - -#### Setting up GitHub for CI/CD workflow and TestNet deployment - - 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 - 2. Decide what values you want to use for the `allow_update`, `allow_delete` and the `on_schema_break`, `on_update` parameters specified in [`contract.py`](./smart_contracts/hello_world/contract.py). - When deploying to LocalNet these values are both set to allow update and replacement of the app for convenience. But for non-LocalNet networks - the defaults are more conservative. - These default values will allow the smart contract to be deployed initially, but will not allow the app to be updated or deleted if is changed and the build will instead fail. - To help you decide it may be helpful to read the [AlgoKit Utils app deployment documentation](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/docs/capabilities/app-deploy.md) or the [AlgoKit smart contract deployment architecture](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/architecture-decisions/2023-01-12_smart-contract-deployment.md#upgradeable-and-deletable-contracts). - 3. Create a [Github Environment](https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#creating-an-environment) named `Test`. - Note: If you have a private repository and don't have GitHub Enterprise then Environments won't work and you'll need to convert the GitHub Action to use a different approach. Ignore this step if you picked `Starter` preset. - 4. Create or obtain a mnemonic for an Algorand account for use on TestNet to deploy apps, referred to as the `DEPLOYER` account. - 5. Store the mnemonic as a [secret](https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#environment-secrets) `DEPLOYER_MNEMONIC` - in the Test environment created in step 3. - 6. The account used to deploy the smart contract will require enough funds to create the app, and also fund it. There are two approaches available here: - * Either, ensure the account is funded outside of CI/CD. - In Testnet, funds can be obtained by using the [Algorand TestNet dispenser](https://bank.testnet.algorand.network/) and we recommend provisioning 50 ALGOs. - * Or, fund the account as part of the CI/CD process by using a `DISPENSER_MNEMONIC` GitHub Environment secret to point to a separate `DISPENSER` account that you maintain ALGOs in (similarly, you need to provision ALGOs into this account using the [TestNet dispenser](https://bank.testnet.algorand.network/)). - -#### Continuous Integration - -For pull requests and pushes to `main` branch against this repository the following checks are automatically performed by GitHub Actions: - - Python dependencies are audited using [pip-audit](https://pypi.org/project/pip-audit/) - - Code formatting is checked using [Black](https://github.com/psf/black) - - Linting is checked using [Ruff](https://github.com/charliermarsh/ruff) - - Types are checked using [mypy](https://mypy-lang.org/) -- The base framework for testing is [pytest](https://docs.pytest.org/), and the project includes two separate kinds of tests: -- - `Algorand Python` smart contract unit tests, that are run using [`algorand-python-testing`](https://pypi.org/project/algorand-python-testing/), which are executed in a Python intepreter emulating major AVM behaviour -- - Python `ApplicationClient` tests that are run against `algokit localnet` and test the behaviour in a real network enviornment - - Smart contract artifacts are built - - Smart contract artifacts are checked for [output stability](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/articles/output_stability.md). - - Smart contract is deployed to a AlgoKit LocalNet instance - -> NOTE: By default smart contract artifacts are compiled with `--debug-level` set to 0, to change this, modify the compiler invocation under `smart_contracts/_helpers/build.py` - -#### Continuous Deployment - -For pushes to `main` branch, after the above checks pass, the following deployment actions are performed: - - The smart contract(s) are deployed to TestNet using [AlgoNode](https://algonode.io). - -> Please note deployment is also performed via `algokit deploy` command which can be invoked both via CI as seen on this project, or locally. For more information on how to use `algokit deploy` please see [AlgoKit documentation](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/deploy.md). - -# Tools - -This project makes use of Algorand Python to build Algorand smart contracts. The following tools are in use: - -- [Algorand](https://www.algorand.com/) - Layer 1 Blockchain; [Developer portal](https://developer.algorand.org/), [Why Algorand?](https://developer.algorand.org/docs/get-started/basics/why_algorand/) -- [AlgoKit](https://github.com/algorandfoundation/algokit-cli) - One-stop shop tool for developers building on the Algorand network; [docs](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/algokit.md), [intro tutorial](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/tutorials/intro.md) -- [Algorand Python](https://github.com/algorandfoundation/puya) - A semantically and syntactically compatible, typed Python language that works with standard Python tooling and allows you to express smart contracts (apps) and smart signatures (logic signatures) for deployment on the Algorand Virtual Machine (AVM); [docs](https://github.com/algorandfoundation/puya), [examples](https://github.com/algorandfoundation/puya/tree/main/examples) -- [AlgoKit Utils](https://github.com/algorandfoundation/algokit-utils-py) - A set of core Algorand utilities that make it easier to build solutions on Algorand. -- [Poetry](https://python-poetry.org/): Python packaging and dependency management.- [Black](https://github.com/psf/black): A Python code formatter.- [Ruff](https://github.com/charliermarsh/ruff): An extremely fast Python linter. - -- [mypy](https://mypy-lang.org/): Static type checker. -- [pytest](https://docs.pytest.org/): Automated testing. -- [pip-audit](https://pypi.org/project/pip-audit/): Tool for scanning Python environments for packages with known vulnerabilities. -- [pre-commit](https://pre-commit.com/): A framework for managing and maintaining multi-language pre-commit hooks, to enable pre-commit you need to run `pre-commit install` in the root of the repository. This will install the pre-commit hooks and run them against modified files when committing. If any of the hooks fail, the commit will be aborted. To run the hooks on all files, use `pre-commit run --all-files`. -It has also been configured to have a productive dev experience out of the box in [VS Code](https://code.visualstudio.com/), see the [.vscode](./.vscode) folder. - diff --git a/examples/generators/production_python_smart_contract_python/pyproject.toml b/examples/generators/production_python_smart_contract_python/pyproject.toml deleted file mode 100644 index 8ccc29a..0000000 --- a/examples/generators/production_python_smart_contract_python/pyproject.toml +++ /dev/null @@ -1,70 +0,0 @@ -[tool.poetry] -name = "production_python_smart_contract_python" -version = "0.1.0" -description = "Algorand smart contracts" -authors = ["None "] -readme = "README.md" - -[tool.poetry.dependencies] -python = "^3.12" -algokit-utils = "^2.4.0" -python-dotenv = "^1.0.0" -algorand-python = "^2.0.0" -algorand-python-testing = "^0.4.0" - -[tool.poetry.group.dev.dependencies] -algokit-client-generator = "^1.1.3" -black = {extras = ["d"], version = "*"} -ruff = "^0.1.6" -mypy = "1.11.0" -pytest = "*" -pytest-cov = "*" -pip-audit = "*" -pre-commit = "*" -puyapy = "*" - -[build-system] -requires = ["poetry-core"] -build-backend = "poetry.core.masonry.api" - -[tool.ruff] -line-length = 120 -select = ["E", "F", "ANN", "UP", "N", "C4", "B", "A", "YTT", "W", "FBT", "Q", "RUF", "I"] -ignore = [ - "ANN101", # no type for self - "ANN102", # no type for cls -] -unfixable = ["B", "RUF"] - -[tool.ruff.flake8-annotations] -allow-star-arg-any = true -suppress-none-returning = true - -[tool.pytest.ini_options] -pythonpath = ["smart_contracts", "tests"] - -[tool.mypy] -files = "smart_contracts/" -python_version = "3.12" -disallow_any_generics = true -disallow_subclassing_any = true -disallow_untyped_calls = true -disallow_untyped_defs = true -disallow_incomplete_defs = true -check_untyped_defs = true -disallow_untyped_decorators = true -warn_redundant_casts = true -warn_unused_ignores = true -warn_return_any = true -strict_equality = true -extra_checks = true -disallow_any_unimported = true -disallow_any_expr = true -disallow_any_decorated = true -disallow_any_explicit = true -untyped_calls_exclude = ["algosdk"] -# Remove if you prefer to use mypy's default behavior against -# untyped algosdk types -[[tool.mypy.overrides]] -module = "tests.*" -disallow_any_expr = false diff --git a/examples/generators/production_python_smart_contract_python/smart_contracts/cool_contract/contract.py b/examples/generators/production_python_smart_contract_python/smart_contracts/cool_contract/contract.py deleted file mode 100644 index 271ad93..0000000 --- a/examples/generators/production_python_smart_contract_python/smart_contracts/cool_contract/contract.py +++ /dev/null @@ -1,9 +0,0 @@ -# pyright: reportMissingModuleSource=false -from algopy import ARC4Contract, String -from algopy.arc4 import abimethod - - -class CoolContract(ARC4Contract): - @abimethod() - def hello(self, name: String) -> String: - return "Hello, " + name diff --git a/examples/generators/production_python_smart_contract_python/smart_contracts/cool_contract/deploy_config.py b/examples/generators/production_python_smart_contract_python/smart_contracts/cool_contract/deploy_config.py deleted file mode 100644 index c4f0afd..0000000 --- a/examples/generators/production_python_smart_contract_python/smart_contracts/cool_contract/deploy_config.py +++ /dev/null @@ -1,35 +0,0 @@ -import logging - -import algokit_utils -from algosdk.v2client.algod import AlgodClient -from algosdk.v2client.indexer import IndexerClient - -logger = logging.getLogger(__name__) - - -# define deployment behaviour based on supplied app spec -def deploy( - algod_client: AlgodClient, - indexer_client: IndexerClient, - app_spec: algokit_utils.ApplicationSpecification, - deployer: algokit_utils.Account, -) -> None: - from smart_contracts.artifacts.cool_contract.cool_contract_client import ( - CoolContractClient, - ) - - app_client = CoolContractClient( - algod_client, - creator=deployer, - indexer_client=indexer_client, - ) - app_client.deploy( - on_schema_break=algokit_utils.OnSchemaBreak.AppendApp, - on_update=algokit_utils.OnUpdate.AppendApp, - ) - name = "world" - response = app_client.hello(name=name) - logger.info( - f"Called hello on {app_spec.contract.name} ({app_client.app_id}) " - f"with name={name}, received: {response.return_value}" - ) diff --git a/examples/generators/production_python_smart_contract_typescript/.algokit.toml b/examples/generators/production_python_smart_contract_typescript/.algokit.toml deleted file mode 100644 index 1719c4e..0000000 --- a/examples/generators/production_python_smart_contract_typescript/.algokit.toml +++ /dev/null @@ -1,52 +0,0 @@ -[algokit] -min_version = "v2.0.0" - -[generate.smart-contract] -description = "Generate a new smart contract for existing project" -path = ".algokit/generators/create_contract" - -[generate.env-file] -description = "Generate a new generic or Algorand network specific .env file" -path = ".algokit/generators/create_env_file" - -[project] -type = 'contract' -name = 'production_python_smart_contract_typescript' -artifacts = 'smart_contracts/artifacts' - -[project.deploy] -command = "npm run deploy:ci" -environment_secrets = [ - "DEPLOYER_MNEMONIC", - "DISPENSER_MNEMONIC", -] - -[project.deploy.localnet] -environment_secrets = [] - -[project.run] -# Commands intented for use locally and in CI -build = { commands = [ - 'poetry run python -m smart_contracts build', -], description = 'Build all smart contracts in the project' } -test = { commands = [ - 'npm run test', -], description = 'Run smart contract tests using Jest' } -audit = { commands = [ - 'poetry run pip-audit', -], description = 'Audit with pip-audit' } -lint = { commands = [ - 'poetry run black --check --diff .', - 'poetry run ruff check .', - 'poetry run mypy', -], description = 'Perform linting' } -audit-teal = { commands = [ - # 🚨 IMPORTANT 🚨: For strict TEAL validation, remove --exclude statements. The default starter contract is not for production. Ensure thorough testing and adherence to best practices in smart contract development. This is not a replacement for a professional audit. - 'algokit task analyze smart_contracts/artifacts --recursive --force --exclude rekey-to --exclude is-updatable --exclude missing-fee-check --exclude is-deletable --exclude can-close-asset --exclude can-close-account --exclude unprotected-deletable --exclude unprotected-updatable', -], description = 'Audit TEAL files' } - -# Commands intented for CI only, prefixed with `ci-` by convention -ci-teal-diff = { commands = [ - 'git add -N ./smart_contracts/artifacts', - 'git diff --exit-code --minimal ./smart_contracts/artifacts', -], description = 'Check TEAL files for differences' } diff --git a/examples/generators/production_python_smart_contract_typescript/.algokit/.copier-answers.yml b/examples/generators/production_python_smart_contract_typescript/.algokit/.copier-answers.yml deleted file mode 100644 index 47664f0..0000000 --- a/examples/generators/production_python_smart_contract_typescript/.algokit/.copier-answers.yml +++ /dev/null @@ -1,10 +0,0 @@ -# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY -_commit: -_src_path: -author_email: None -author_name: None -contract_name: hello_world -deployment_language: typescript -preset_name: production -project_name: production_python_smart_contract_typescript - diff --git a/examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_contract/copier.yaml b/examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_contract/copier.yaml deleted file mode 100644 index 73805de..0000000 --- a/examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_contract/copier.yaml +++ /dev/null @@ -1,10 +0,0 @@ -_tasks: - - "echo '==== Successfully initialized new smart contract 🚀 ===='" - -contract_name: - type: str - help: Name of your new contract. - placeholder: "my-new-contract" - default: "my-new-contract" - -_templates_suffix: ".j2" diff --git a/examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 b/examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 deleted file mode 100644 index 829e3a0..0000000 --- a/examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 +++ /dev/null @@ -1,9 +0,0 @@ -# pyright: reportMissingModuleSource=false -from algopy import ARC4Contract, String -from algopy.arc4 import abimethod - - -class {{ contract_name.split('_')|map('capitalize')|join }}(ARC4Contract): - @abimethod() - def hello(self, name: String) -> String: - return "Hello, " + name diff --git a/examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_env_file/copier.yaml b/examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_env_file/copier.yaml deleted file mode 100644 index afa2cac..0000000 --- a/examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_env_file/copier.yaml +++ /dev/null @@ -1,49 +0,0 @@ -_tasks: - - "echo '==== Successfully generated new .env file 🚀 ===='" - -target_network: - type: str - help: Name of your target network. - choices: - - mainnet - - testnet - - localnet - - custom - default: "localnet" - when: "{{ not use_generic_env }}" - -custom_network_name: - type: str - help: Name of your custom Algorand network. - placeholder: "custom" - when: "{{ not use_generic_env and target_network == 'custom' }}" - -is_localnet: - type: bool - help: Whether to deploy on localnet. - placeholder: "true" - default: "{{ target_network == 'localnet' and not use_generic_env }}" - when: 'false' - -is_testnet: - type: bool - help: Whether to deploy on testnet. - placeholder: "true" - default: "{{ target_network == 'testnet' and not use_generic_env }}" - when: 'false' - -is_mainnet: - type: bool - help: Whether to deploy on mainnet. - placeholder: "true" - default: "{{ target_network == 'mainnet' and not use_generic_env }}" - when: 'false' - -is_customnet: - type: bool - help: Whether to deploy on custom network. - placeholder: "true" - default: "{{ target_network == 'custom' and not use_generic_env }}" - when: 'false' - -_templates_suffix: ".j2" diff --git a/examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_customnet %}.env.{{custom_network_name}}{% endif %} b/examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_customnet %}.env.{{custom_network_name}}{% endif %} deleted file mode 100644 index cfc9f21..0000000 --- a/examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_customnet %}.env.{{custom_network_name}}{% endif %} +++ /dev/null @@ -1,7 +0,0 @@ -# this file contains algorand network settings for interacting with testnet via algonode -ALGOD_TOKEN={YOUR_ALGOD_TOKEN} -ALGOD_SERVER={YOUR_ALGOD_SERVER_URL} -ALGOD_PORT={YOUR_ALGOD_PORT} -INDEXER_TOKEN={YOUR_INDEXER_TOKEN} -INDEXER_SERVER={YOUR_INDEXER_SERVER_URL} -INDEXER_PORT={YOUR_INDEXER_PORT} diff --git a/examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_localnet %}.env.localnet{% endif %} b/examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_localnet %}.env.localnet{% endif %} deleted file mode 100644 index fcbf442..0000000 --- a/examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_localnet %}.env.localnet{% endif %} +++ /dev/null @@ -1,7 +0,0 @@ -# this file should contain environment variables specific to algokit localnet -ALGOD_TOKEN=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -ALGOD_SERVER=http://localhost -ALGOD_PORT=4001 -INDEXER_TOKEN=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -INDEXER_SERVER=http://localhost -INDEXER_PORT=8980 diff --git a/examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_mainnet %}.env.mainnet{% endif %} b/examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_mainnet %}.env.mainnet{% endif %} deleted file mode 100644 index bb9a787..0000000 --- a/examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_mainnet %}.env.mainnet{% endif %} +++ /dev/null @@ -1,3 +0,0 @@ -# this file contains algorand network settings for interacting with testnet via algonode -ALGOD_SERVER=https://mainnet-api.algonode.cloud -INDEXER_SERVER=https://mainnet-idx.algonode.cloud diff --git a/examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_testnet %}.env.testnet{% endif %} b/examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_testnet %}.env.testnet{% endif %} deleted file mode 100644 index eeea43d..0000000 --- a/examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_testnet %}.env.testnet{% endif %} +++ /dev/null @@ -1,3 +0,0 @@ -# this file contains algorand network settings for interacting with testnet via algonode -ALGOD_SERVER=https://testnet-api.algonode.cloud -INDEXER_SERVER=https://testnet-idx.algonode.cloud diff --git a/examples/generators/production_python_smart_contract_typescript/.github/workflows/production-python-smart-contract-typescript-cd.yaml b/examples/generators/production_python_smart_contract_typescript/.github/workflows/production-python-smart-contract-typescript-cd.yaml deleted file mode 100644 index fe64e69..0000000 --- a/examples/generators/production_python_smart_contract_typescript/.github/workflows/production-python-smart-contract-typescript-cd.yaml +++ /dev/null @@ -1,48 +0,0 @@ -name: Release production_python_smart_contract_typescript - -on: - workflow_call: - push: - branches: - - main - -jobs: - validate: - name: Validate production_python_smart_contract_typescript - uses: ./.github/workflows/production-python-smart-contract-typescript-ci.yaml - deploy-testnet: - runs-on: "ubuntu-latest" - needs: validate - environment: contract-testnet - steps: - - name: Checkout source code - uses: actions/checkout@v4 - - - name: Install poetry - run: pipx install poetry - - - name: Set up Python 3.12 - uses: actions/setup-python@v5 - with: - python-version: "3.12" - cache: "poetry" - - - name: Install algokit - run: pipx install algokit - - - name: Bootstrap dependencies - run: algokit project bootstrap all - - - name: Configure git - shell: bash - run: | - # set git user and email as test invoke git - git config --global user.email "actions@github.com" && git config --global user.name "github-actions" - - - name: Deploy to testnet - run: algokit project deploy testnet - env: - # This is the account that becomes the creator of the contract - DEPLOYER_MNEMONIC: ${{ secrets.DEPLOYER_MNEMONIC }} - # The dispenser account is used to ensure the deployer account is funded - DISPENSER_MNEMONIC: ${{ secrets.DISPENSER_MNEMONIC }} diff --git a/examples/generators/production_python_smart_contract_typescript/.github/workflows/production-python-smart-contract-typescript-ci.yaml b/examples/generators/production_python_smart_contract_typescript/.github/workflows/production-python-smart-contract-typescript-ci.yaml deleted file mode 100644 index 9a8fced..0000000 --- a/examples/generators/production_python_smart_contract_typescript/.github/workflows/production-python-smart-contract-typescript-ci.yaml +++ /dev/null @@ -1,64 +0,0 @@ -name: Validate production_python_smart_contract_typescript - -on: - workflow_call: - pull_request: - -jobs: - validate: - runs-on: "ubuntu-latest" - steps: - - name: Checkout source code - uses: actions/checkout@v4 - - - name: Install poetry - run: pipx install poetry - - - name: Set up Python 3.12 - uses: actions/setup-python@v5 - with: - python-version: "3.12" - cache: "poetry" - - - name: Install algokit - run: pipx install algokit - - - name: Start LocalNet - run: algokit localnet start - - - name: Bootstrap dependencies - run: algokit project bootstrap all - - - name: Configure git - shell: bash - run: | - # set git user and email as test invoke git - git config --global user.email "actions@github.com" && git config --global user.name "github-actions" - - - name: Audit python dependencies - run: algokit project run audit - - - name: Lint and format python dependencies - run: algokit project run lint - - - name: Run tests - shell: bash - run: | - set -o pipefail - algokit project run test - - - name: Build smart contracts - run: algokit project run build - - - name: Scan TEAL files for issues - run: algokit project run audit-teal - - # # Uncomment to enable TEAL static analysis with snapshoting using Tealer package - # # Would first require running locally using audit-teal command and committing the snapshots into source control - # # Please note, tealer has a known bug that may result in large snapshot file sizes, track resolution here: - # # https://github.com/crytic/tealer/issues/101 - # - name: Check output stability of the smart contracts - # run: algokit project run ci-teal-diff - - - name: Run deployer against LocalNet - run: algokit project deploy localnet diff --git a/examples/generators/production_python_smart_contract_typescript/.idea/runConfigurations/Build_Beaker_application.xml b/examples/generators/production_python_smart_contract_typescript/.idea/runConfigurations/Build_Beaker_application.xml deleted file mode 100644 index debed6d..0000000 --- a/examples/generators/production_python_smart_contract_typescript/.idea/runConfigurations/Build_Beaker_application.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - diff --git a/examples/generators/production_python_smart_contract_typescript/.idea/runConfigurations/Build_Beaker_application____LocalNet.xml b/examples/generators/production_python_smart_contract_typescript/.idea/runConfigurations/Build_Beaker_application____LocalNet.xml deleted file mode 100644 index a04c6b0..0000000 --- a/examples/generators/production_python_smart_contract_typescript/.idea/runConfigurations/Build_Beaker_application____LocalNet.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - diff --git a/examples/generators/production_python_smart_contract_typescript/.idea/runConfigurations/Reset_AlgoKit_LocalNet.xml b/examples/generators/production_python_smart_contract_typescript/.idea/runConfigurations/Reset_AlgoKit_LocalNet.xml deleted file mode 100644 index 7f1236a..0000000 --- a/examples/generators/production_python_smart_contract_typescript/.idea/runConfigurations/Reset_AlgoKit_LocalNet.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - diff --git a/examples/generators/production_python_smart_contract_typescript/.idea/runConfigurations/Start_AlgoKit_LocalNet.xml b/examples/generators/production_python_smart_contract_typescript/.idea/runConfigurations/Start_AlgoKit_LocalNet.xml deleted file mode 100644 index f699a7a..0000000 --- a/examples/generators/production_python_smart_contract_typescript/.idea/runConfigurations/Start_AlgoKit_LocalNet.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - diff --git a/examples/generators/production_python_smart_contract_typescript/.pre-commit-config.yaml b/examples/generators/production_python_smart_contract_typescript/.pre-commit-config.yaml deleted file mode 100644 index e5c820b..0000000 --- a/examples/generators/production_python_smart_contract_typescript/.pre-commit-config.yaml +++ /dev/null @@ -1,49 +0,0 @@ -repos: - - repo: local - hooks: - - - id: black - name: black - description: "Black: The uncompromising Python code formatter" - entry: poetry run black - language: system - minimum_pre_commit_version: 2.9.2 - require_serial: true - types_or: [ python, pyi ] - - - - id: ruff - name: ruff - description: "Run 'ruff' for extremely fast Python linting" - entry: poetry run ruff - language: system - types: [ python ] - args: [ "check", "--fix" ] - require_serial: false - additional_dependencies: [ ] - minimum_pre_commit_version: '0' - files: '^(smart_contracts|tests)/' - - - - id: mypy - name: mypy - description: '`mypy` will check Python types for correctness' - entry: poetry run mypy - language: system - types_or: [ python, pyi ] - require_serial: true - additional_dependencies: [ ] - minimum_pre_commit_version: '2.9.2' - files: '^(smart_contracts|tests)/' - - # # Uncomment to enable TEAL static analysis using Tealer package - # - id: tealer - # name: tealer - # description: "Run AlgoKit `Tealer` for TEAL static analysis" - # entry: algokit - # language: system - # args: [project, run, "audit-teal"] - # require_serial: false - # additional_dependencies: [] - # minimum_pre_commit_version: "0" - # files: '^.*\.teal$' diff --git a/examples/generators/production_python_smart_contract_typescript/.vscode/extensions.json b/examples/generators/production_python_smart_contract_typescript/.vscode/extensions.json deleted file mode 100644 index 684e4dd..0000000 --- a/examples/generators/production_python_smart_contract_typescript/.vscode/extensions.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "recommendations": [ - "ms-python.python", - "charliermarsh.ruff", - "matangover.mypy", - "ms-python.black-formatter", - "esbenp.prettier-vscode", - "tamasfe.even-better-toml", - "editorconfig.editorconfig", - "vsls-contrib.codetour", - "algorandfoundation.algokit-avm-vscode-debugger" - ] -} diff --git a/examples/generators/production_python_smart_contract_typescript/.vscode/settings.json b/examples/generators/production_python_smart_contract_typescript/.vscode/settings.json deleted file mode 100644 index df0395b..0000000 --- a/examples/generators/production_python_smart_contract_typescript/.vscode/settings.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - // General - see also /.editorconfig - "editor.formatOnSave": true, - "files.exclude": { - "**/.git": true, - "**/.DS_Store": true, - "**/Thumbs.db": true, - ".mypy_cache": true, - ".pytest_cache": true, - ".ruff_cache": true, - "**/__pycache__": true, - ".idea": true - }, - - // TypeScript - "editor.defaultFormatter": "esbenp.prettier-vscode", - - // Python - "python.analysis.extraPaths": ["${workspaceFolder}/smart_contracts"], - "python.analysis.diagnosticSeverityOverrides": { - "reportMissingModuleSource": "none" - }, - "python.defaultInterpreterPath": "${workspaceFolder}/.venv", - "[python]": { - "editor.codeActionsOnSave": { - "source.fixAll": "explicit", - // Prevent default import sorting from running; Ruff will sort imports for us anyway - "source.organizeImports": "never" - }, - "editor.defaultFormatter": "ms-python.black-formatter", - }, - "black-formatter.args": ["--config=pyproject.toml"], - "ruff.enable": true, - "ruff.lint.run": "onSave", - "ruff.lint.args": ["--config=pyproject.toml"], - "ruff.importStrategy": "fromEnvironment", - "ruff.fixAll": true, //lint and fix all files in workspace - "ruff.organizeImports": true, //organize imports on save - "ruff.codeAction.disableRuleComment": { - "enable": true - }, - "ruff.codeAction.fixViolation": { - "enable": true - }, - "python.analysis.typeCheckingMode": "off", - "mypy.configFile": "pyproject.toml", - // set to empty array to use config from project - "mypy.targets": [], - "mypy.runUsingActiveInterpreter": true, - - // On Windows, if execution policy is set to Signed (default) then it won't be able to activate the venv - // so instead let's set it to RemoteSigned for VS Code terminal - "terminal.integrated.shellArgs.windows": ["-ExecutionPolicy", "RemoteSigned"], -} diff --git a/examples/generators/production_python_smart_contract_typescript/README.md b/examples/generators/production_python_smart_contract_typescript/README.md deleted file mode 100644 index c2c6505..0000000 --- a/examples/generators/production_python_smart_contract_typescript/README.md +++ /dev/null @@ -1,157 +0,0 @@ -# production_python_smart_contract_typescript - -This project has been generated using AlgoKit. See below for default getting started instructions. - -# Setup - -### Pre-requisites - -- [Python 3.12](https://www.python.org/downloads/) or later -- [Docker](https://www.docker.com/) (only required for LocalNet) - -> For interactive tour over the codebase, download [vsls-contrib.codetour](https://marketplace.visualstudio.com/items?itemName=vsls-contrib.codetour) extension for VS Code, then open the [`.codetour.json`](./.tours/getting-started-with-your-algokit-project.tour) file in code tour extension. - -### Initial Setup - -#### 1. Clone the Repository -Start by cloning this repository to your local machine. - -#### 2. Install Pre-requisites -Ensure the following pre-requisites are installed and properly configured: - -- **Docker**: Required for running a local Algorand network. [Install Docker](https://www.docker.com/). -- **AlgoKit CLI**: Essential for project setup and operations. Install the latest version from [AlgoKit CLI Installation Guide](https://github.com/algorandfoundation/algokit-cli#install). Verify installation with `algokit --version`, expecting `2.0.0` or later. - -#### 3. Bootstrap Your Local Environment -Run the following commands within the project folder: - -- **Install Poetry**: Required for Python dependency management. [Installation Guide](https://python-poetry.org/docs/#installation). Verify with `poetry -V` to see version `1.2`+. -- **Setup Project**: Execute `algokit project bootstrap all` to install dependencies and setup a Python virtual environment in `.venv`. -- **Configure environment**: Execute `algokit generate env-file -a target_network localnet` to create a `.env.localnet` file with default configuration for `localnet`. -- **Start LocalNet**: Use `algokit localnet start` to initiate a local Algorand network. - -### Development Workflow - -#### Terminal -Directly manage and interact with your project using AlgoKit commands: - -1. **Build Contracts**: `algokit project run build` compiles all smart contracts. You can also specify a specific contract by passing the name of the contract folder as an extra argument. -For example: `algokit project run build -- hello_world` will only build the `hello_world` contract. -2. **Deploy**: Use `algokit project deploy localnet` to deploy contracts to the local network. You can also specify a specific contract by passing the name of the contract folder as an extra argument. -For example: `algokit project deploy localnet -- hello_world` will only deploy the `hello_world` contract. - -#### VS Code -For a seamless experience with breakpoint debugging and other features: - -1. **Open Project**: In VS Code, open the repository root. -2. **Install Extensions**: Follow prompts to install recommended extensions. -3. **Debugging**: - - Use `F5` to start debugging. - - **Windows Users**: Select the Python interpreter at `./.venv/Scripts/python.exe` via `Ctrl/Cmd + Shift + P` > `Python: Select Interpreter` before the first run. - -#### JetBrains IDEs -While primarily optimized for VS Code, JetBrains IDEs are supported: - -1. **Open Project**: In your JetBrains IDE, open the repository root. -2. **Automatic Setup**: The IDE should configure the Python interpreter and virtual environment. -3. **Debugging**: Use `Shift+F10` or `Ctrl+R` to start debugging. Note: Windows users may encounter issues with pre-launch tasks due to a known bug. See [JetBrains forums](https://youtrack.jetbrains.com/issue/IDEA-277486/Shell-script-configuration-cannot-run-as-before-launch-task) for workarounds. - -## AlgoKit Workspaces and Project Management -This project supports both standalone and monorepo setups through AlgoKit workspaces. Leverage [`algokit project run`](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/project/run.md) commands for efficient monorepo project orchestration and management across multiple projects within a workspace. - -## AlgoKit Generators - -This template provides a set of [algokit generators](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/generate.md) that allow you to further modify the project instantiated from the template to fit your needs, as well as giving you a base to build your own extensions to invoke via the `algokit generate` command. - -### Generate Smart Contract - -By default the template creates a single `HelloWorld` contract under hello_world folder in the `smart_contracts` directory. To add a new contract: - -1. From the root of the project (`../`) execute `algokit generate smart-contract`. This will create a new starter smart contract and deployment configuration file under `{your_contract_name}` subfolder in the `smart_contracts` directory. -2. Each contract potentially has different creation parameters and deployment steps. Hence, you need to define your deployment logic in `deploy-config.ts`file. -3. `config.py` file will automatically build all contracts in the `smart_contracts` directory. If you want to build specific contracts manually, modify the default code provided by the template in `config.py` file. -4. Since you are generating a TypeScript client, you also need to reference your contract deployment logic in `index.ts` file. However, similar to config.py, by default, `index.ts` will auto import all TypeScript deployment files under `smart_contracts` directory. If you want to manually import specific contracts, modify the default code provided by the template in `index.ts` file. - -> Please note, above is just a suggested convention tailored for the base configuration and structure of this template. The default code supplied by the template in `config.py` and `index.ts` (if using ts clients) files are tailored for the suggested convention. You are free to modify the structure and naming conventions as you see fit. - -### Generate '.env' files - -By default the template instance does not contain any env files. Using [`algokit project deploy`](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/project/deploy.md) against `localnet` | `testnet` | `mainnet` will use default values for `algod` and `indexer` unless overwritten via `.env` or `.env.{target_network}`. - -To generate a new `.env` or `.env.{target_network}` file, run `algokit generate env-file` - -### Debugging Smart Contracts - -This project is optimized to work with AlgoKit AVM Debugger extension. To activate it: -Refer to the commented header in the `index.ts` file in the `smart_contracts` folder. - -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. - -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).### Continuous Integration / Continuous Deployment (CI/CD) - -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. - -> Please note, if you instantiated the project with --workspace flag in `algokit init` it will automatically attempt to move the contents of the `.github` folder to the root of the workspace. - -### AlgoKit Workspaces - -To define custom `algokit project run` commands refer to [documentation](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/project/run.md). This allows orchestration of commands spanning across multiple projects within an algokit workspace based project (monorepo). - -#### Setting up GitHub for CI/CD workflow and TestNet deployment - - 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 - 2. Decide what values you want to use for the `allowUpdate` and `allowDelete` parameters specified in [`deploy-config.ts`](./smart_contracts/hello_world/deploy-config.ts). - When deploying to LocalNet these values are both set to `true` for convenience. But for non-LocalNet networks - they are more conservative and use `false` - These default values will allow the smart contract to be deployed initially, but will not allow the app to be updated or deleted if is changed and the build will instead fail. - To help you decide it may be helpful to read the [AlgoKit Utils app deployment documentation](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/docs/capabilities/app-deploy.md) or the [AlgoKit smart contract deployment architecture](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/architecture-decisions/2023-01-12_smart-contract-deployment.md#upgradeable-and-deletable-contracts). - 3. Create a [Github Environment](https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#creating-an-environment) named `Test`. - Note: If you have a private repository and don't have GitHub Enterprise then Environments won't work and you'll need to convert the GitHub Action to use a different approach. Ignore this step if you picked `Starter` preset. - 4. Create or obtain a mnemonic for an Algorand account for use on TestNet to deploy apps, referred to as the `DEPLOYER` account. - 5. Store the mnemonic as a [secret](https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#environment-secrets) `DEPLOYER_MNEMONIC` - in the Test environment created in step 3. - 6. The account used to deploy the smart contract will require enough funds to create the app, and also fund it. There are two approaches available here: - * Either, ensure the account is funded outside of CI/CD. - In Testnet, funds can be obtained by using the [Algorand TestNet dispenser](https://bank.testnet.algorand.network/) and we recommend provisioning 50 ALGOs. - * Or, fund the account as part of the CI/CD process by using a `DISPENSER_MNEMONIC` GitHub Environment secret to point to a separate `DISPENSER` account that you maintain ALGOs in (similarly, you need to provision ALGOs into this account using the [TestNet dispenser](https://bank.testnet.algorand.network/)). - -#### Continuous Integration - -For pull requests and pushes to `main` branch against this repository the following checks are automatically performed by GitHub Actions: - - Python dependencies are audited using [pip-audit](https://pypi.org/project/pip-audit/) - - Code formatting is checked using [Black](https://github.com/psf/black) - - Linting is checked using [Ruff](https://github.com/charliermarsh/ruff) - - Types are checked using [mypy](https://mypy-lang.org/) - - Typescript `ApplicationClient` tests against `algokit localnet` are executed using [jest](https://jestjs.io/) - - Smart contract artifacts are built - - Smart contract artifacts are checked for [output stability](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/articles/output_stability.md). - - Smart contract is deployed to a AlgoKit LocalNet instance - -> NOTE: By default smart contract artifacts are compiled with `--debug-level` set to 0, to change this, modify the compiler invocation under `smart_contracts/_helpers/build.py` - -#### Continuous Deployment - -For pushes to `main` branch, after the above checks pass, the following deployment actions are performed: - - The smart contract(s) are deployed to TestNet using [AlgoNode](https://algonode.io). - -> Please note deployment is also performed via `algokit deploy` command which can be invoked both via CI as seen on this project, or locally. For more information on how to use `algokit deploy` please see [AlgoKit documentation](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/deploy.md). - -# Tools - -This project makes use of Algorand Python to build Algorand smart contracts. The following tools are in use: - -- [Algorand](https://www.algorand.com/) - Layer 1 Blockchain; [Developer portal](https://developer.algorand.org/), [Why Algorand?](https://developer.algorand.org/docs/get-started/basics/why_algorand/) -- [AlgoKit](https://github.com/algorandfoundation/algokit-cli) - One-stop shop tool for developers building on the Algorand network; [docs](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/algokit.md), [intro tutorial](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/tutorials/intro.md) -- [Algorand Python](https://github.com/algorandfoundation/puya) - A semantically and syntactically compatible, typed Python language that works with standard Python tooling and allows you to express smart contracts (apps) and smart signatures (logic signatures) for deployment on the Algorand Virtual Machine (AVM); [docs](https://github.com/algorandfoundation/puya), [examples](https://github.com/algorandfoundation/puya/tree/main/examples) -- [AlgoKit Utils](https://github.com/algorandfoundation/algokit-utils-ts) - A set of core Algorand utilities that make it easier to build solutions on Algorand. -- [Poetry](https://python-poetry.org/): Python packaging and dependency management.- [Black](https://github.com/psf/black): A Python code formatter.- [Ruff](https://github.com/charliermarsh/ruff): An extremely fast Python linter. - -- [mypy](https://mypy-lang.org/): Static type checker. -- [pip-audit](https://pypi.org/project/pip-audit/): Tool for scanning Python environments for packages with known vulnerabilities. -- [pre-commit](https://pre-commit.com/): A framework for managing and maintaining multi-language pre-commit hooks, to enable pre-commit you need to run `pre-commit install` in the root of the repository. This will install the pre-commit hooks and run them against modified files when committing. If any of the hooks fail, the commit will be aborted. To run the hooks on all files, use `pre-commit run --all-files`. -- [npm](https://www.npmjs.com/): Node.js package manager -- [TypeScript](https://www.typescriptlang.org/): Strongly typed programming language that builds on JavaScript -- [ts-node-dev](https://github.com/wclr/ts-node-dev): TypeScript development execution environment - -It has also been configured to have a productive dev experience out of the box in [VS Code](https://code.visualstudio.com/), see the [.vscode](./.vscode) folder. - diff --git a/examples/generators/production_python_smart_contract_typescript/jest.config.ts b/examples/generators/production_python_smart_contract_typescript/jest.config.ts deleted file mode 100644 index 381e1e0..0000000 --- a/examples/generators/production_python_smart_contract_typescript/jest.config.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * For a detailed explanation regarding each configuration property and type check, visit: - * https://jestjs.io/docs/configuration - */ -import type { Config } from 'jest' - -const config: Config = { - preset: 'ts-jest', - verbose: true, - transform: { - '^.+\\.tsx?$': 'ts-jest', - }, - testPathIgnorePatterns: ['node_modules', '.venv', 'coverage'], - testTimeout: 10000, -} -export default config diff --git a/examples/generators/production_python_smart_contract_typescript/package.json b/examples/generators/production_python_smart_contract_typescript/package.json deleted file mode 100644 index 4cc398e..0000000 --- a/examples/generators/production_python_smart_contract_typescript/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "smart_contracts", - "version": "1.0.0", - "description": "Smart contract deployer", - "main": "index.ts", - "scripts": { - "deploy": "ts-node-dev --transpile-only --watch .env -r dotenv/config smart_contracts/index.ts", - "deploy:ci": "ts-node --transpile-only -r dotenv/config smart_contracts/index.ts", - "test": "jest --coverage", - "format": "prettier --write ." - }, - "engines": { - "node": ">=20.0", - "npm": ">=9.0" - }, - "dependencies": { - "@algorandfoundation/algokit-utils": "^7.0.0", - "@algorandfoundation/algokit-utils-debug": "^1.0.2", - "algosdk": ">=2.9.0 <3.0" - }, - "devDependencies": { - "@algorandfoundation/algokit-client-generator": "^4.0.0", - "@types/jest": "^29.5.11", - "dotenv": "^16.0.3", - "prettier": "^2.8.4", - "ts-jest": "^29.1.1", - "ts-node-dev": "^2.0.0", - "typescript": "^4.9.5" - } -} diff --git a/examples/generators/production_python_smart_contract_typescript/pyproject.toml b/examples/generators/production_python_smart_contract_typescript/pyproject.toml deleted file mode 100644 index 3c6c5c4..0000000 --- a/examples/generators/production_python_smart_contract_typescript/pyproject.toml +++ /dev/null @@ -1,64 +0,0 @@ -[tool.poetry] -name = "production_python_smart_contract_typescript" -version = "0.1.0" -description = "Algorand smart contracts" -authors = ["None "] -readme = "README.md" - -[tool.poetry.dependencies] -python = "^3.12" -algokit-utils = "^2.4.0" -python-dotenv = "^1.0.0" -algorand-python = "^2.0.0" -algorand-python-testing = "^0.4.0" - -[tool.poetry.group.dev.dependencies] -black = {extras = ["d"], version = "*"} -ruff = "^0.1.6" -mypy = "1.11.0" -pip-audit = "*" -pre-commit = "*" -puyapy = "*" - -[build-system] -requires = ["poetry-core"] -build-backend = "poetry.core.masonry.api" - -[tool.ruff] -line-length = 120 -select = ["E", "F", "ANN", "UP", "N", "C4", "B", "A", "YTT", "W", "FBT", "Q", "RUF", "I"] -ignore = [ - "ANN101", # no type for self - "ANN102", # no type for cls -] -unfixable = ["B", "RUF"] - -[tool.ruff.flake8-annotations] -allow-star-arg-any = true -suppress-none-returning = true - -[tool.mypy] -files = "smart_contracts/" -python_version = "3.12" -disallow_any_generics = true -disallow_subclassing_any = true -disallow_untyped_calls = true -disallow_untyped_defs = true -disallow_incomplete_defs = true -check_untyped_defs = true -disallow_untyped_decorators = true -warn_redundant_casts = true -warn_unused_ignores = true -warn_return_any = true -strict_equality = true -extra_checks = true -disallow_any_unimported = true -disallow_any_expr = true -disallow_any_decorated = true -disallow_any_explicit = true -untyped_calls_exclude = ["algosdk"] -# Remove if you prefer to use mypy's default behavior against -# untyped algosdk types -[[tool.mypy.overrides]] -module = "tests.*" -disallow_any_expr = false diff --git a/examples/generators/production_python_smart_contract_typescript/smart_contracts/__main__.py b/examples/generators/production_python_smart_contract_typescript/smart_contracts/__main__.py deleted file mode 100644 index 62fadcd..0000000 --- a/examples/generators/production_python_smart_contract_typescript/smart_contracts/__main__.py +++ /dev/null @@ -1,42 +0,0 @@ -import logging -import sys -from pathlib import Path - -from dotenv import load_dotenv - -from smart_contracts._helpers.build import build -from smart_contracts._helpers.config import contracts - -logging.basicConfig( - level=logging.DEBUG, format="%(asctime)s %(levelname)-10s: %(message)s" -) -logger = logging.getLogger(__name__) -logger.info("Loading .env") -# For manual script execution (bypassing `algokit project deploy`) with a custom .env, -# modify `load_dotenv()` accordingly. For example, `load_dotenv('.env.localnet')`. -load_dotenv() -root_path = Path(__file__).parent - - -def main(action: str, contract_name: str | None = None) -> None: - artifact_path = root_path / "artifacts" - - # Filter contracts if a specific contract name is provided - filtered_contracts = [ - c for c in contracts if contract_name is None or c.name == contract_name - ] - - match action: - case "build": - for contract in filtered_contracts: - logger.info(f"Building app at {contract.path}") - build(artifact_path / contract.name, contract.path) - - -if __name__ == "__main__": - if len(sys.argv) > 2: - main(sys.argv[1], sys.argv[2]) - elif len(sys.argv) > 1: - main(sys.argv[1]) - else: - main("build") diff --git a/examples/generators/production_python_smart_contract_typescript/smart_contracts/_helpers/build.py b/examples/generators/production_python_smart_contract_typescript/smart_contracts/_helpers/build.py deleted file mode 100644 index 37ceb1f..0000000 --- a/examples/generators/production_python_smart_contract_typescript/smart_contracts/_helpers/build.py +++ /dev/null @@ -1,76 +0,0 @@ -import logging -import subprocess -from pathlib import Path -from shutil import rmtree - -logger = logging.getLogger(__name__) -deployment_extension = "ts" - - -def _get_output_path(output_dir: Path, deployment_extension: str) -> Path: - return output_dir / Path( - "{contract_name}" - + ("_client" if deployment_extension == "py" else "Client") - + f".{deployment_extension}" - ) - - -def build(output_dir: Path, contract_path: Path) -> Path: - output_dir = output_dir.resolve() - if output_dir.exists(): - rmtree(output_dir) - output_dir.mkdir(exist_ok=True, parents=True) - logger.info(f"Exporting {contract_path} to {output_dir}") - - build_result = subprocess.run( - [ - "algokit", - "--no-color", - "compile", - "python", - contract_path.absolute(), - f"--out-dir={output_dir}", - "--output-arc32", - "--output-source-map", - ], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - text=True, - ) - if build_result.returncode: - raise Exception(f"Could not build contract:\n{build_result.stdout}") - - app_spec_file_names = [file.name for file in output_dir.glob("*.arc32.json")] - app_spec_file_name = None - for app_spec_file_name in app_spec_file_names: - if app_spec_file_name is None: - logger.warning( - "No '*.arc32.json' file found (likely a logic signature being compiled). Skipping client generation." - ) - continue - print(app_spec_file_name) - generate_result = subprocess.run( - [ - "algokit", - "generate", - "client", - output_dir, - "--output", - _get_output_path(output_dir, deployment_extension), - ], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - text=True, - ) - if generate_result.returncode: - if "No such command" in generate_result.stdout: - raise Exception( - "Could not generate typed client, requires AlgoKit 2.0.0 or " - "later. Please update AlgoKit" - ) - else: - raise Exception( - f"Could not generate typed client:\n{generate_result.stdout}" - ) - - return output_dir / app_spec_file_name if app_spec_file_name else output_dir diff --git a/examples/generators/production_python_smart_contract_typescript/smart_contracts/cool_contract/contract.py b/examples/generators/production_python_smart_contract_typescript/smart_contracts/cool_contract/contract.py deleted file mode 100644 index 271ad93..0000000 --- a/examples/generators/production_python_smart_contract_typescript/smart_contracts/cool_contract/contract.py +++ /dev/null @@ -1,9 +0,0 @@ -# pyright: reportMissingModuleSource=false -from algopy import ARC4Contract, String -from algopy.arc4 import abimethod - - -class CoolContract(ARC4Contract): - @abimethod() - def hello(self, name: String) -> String: - return "Hello, " + name diff --git a/examples/generators/production_python_smart_contract_typescript/smart_contracts/cool_contract/deploy-config.ts b/examples/generators/production_python_smart_contract_typescript/smart_contracts/cool_contract/deploy-config.ts deleted file mode 100644 index d629083..0000000 --- a/examples/generators/production_python_smart_contract_typescript/smart_contracts/cool_contract/deploy-config.ts +++ /dev/null @@ -1,33 +0,0 @@ -import * as algokit from '@algorandfoundation/algokit-utils' -import { CoolContractFactory } from '../artifacts/cool_contract/CoolContractClient' - -// Below is a showcase of various deployment options you can use in TypeScript Client -export async function deploy() { - console.log('=== Deploying CoolContract ===') - - const algorand = algokit.AlgorandClient.fromEnvironment() - const deployer = await algorand.account.fromEnvironment('DEPLOYER') - - const factory = algorand.client.getTypedAppFactory(CoolContractFactory, { - defaultSender: deployer.addr, - }) - - const { appClient, result } = await factory.deploy({ onUpdate: 'append', onSchemaBreak: 'append' }) - - // If app was just created fund the app account - if (['create', 'replace'].includes(result.operationPerformed)) { - await algorand.send.payment({ - amount: (1).algo(), - sender: deployer.addr, - receiver: app.appAddress, - }) - } - - const method = 'hello' - const response = await appClient.send.hello({ - args: { name: 'world' }, - }) - console.log( - `Called ${method} on ${appClient.appClient.appName} (${appClient.appClient.appId}) with name = world, received: ${response.return}`, - ) -} diff --git a/examples/generators/production_python_smart_contract_typescript/smart_contracts/hello_world/deploy-config.ts b/examples/generators/production_python_smart_contract_typescript/smart_contracts/hello_world/deploy-config.ts deleted file mode 100644 index e0608c9..0000000 --- a/examples/generators/production_python_smart_contract_typescript/smart_contracts/hello_world/deploy-config.ts +++ /dev/null @@ -1,33 +0,0 @@ -import * as algokit from '@algorandfoundation/algokit-utils' -import { HelloWorldFactory } from '../artifacts/hello_world/HelloWorldClient' - -// Below is a showcase of various deployment options you can use in TypeScript Client -export async function deploy() { - console.log('=== Deploying HelloWorld ===') - - const algorand = algokit.AlgorandClient.fromEnvironment() - const deployer = await algorand.account.fromEnvironment('DEPLOYER') - - const factory = algorand.client.getTypedAppFactory(HelloWorldFactory, { - defaultSender: deployer.addr, - }) - - const { appClient, result } = await factory.deploy({ onUpdate: 'append', onSchemaBreak: 'append' }) - - // If app was just created fund the app account - if (['create', 'replace'].includes(result.operationPerformed)) { - await algorand.send.payment({ - amount: (1).algo(), - sender: deployer.addr, - receiver: appClient.appAddress, - }) - } - - const method = 'hello' - const response = await appClient.send.hello({ - args: { name: 'world' }, - }) - console.log( - `Called ${method} on ${appClient.appClient.appName} (${appClient.appClient.appId}) with name = world, received: ${response.return}`, - ) -} diff --git a/examples/generators/starter_python_smart_contract_python/.algokit.toml b/examples/generators/starter_python_smart_contract_python/.algokit.toml deleted file mode 100644 index bdb2685..0000000 --- a/examples/generators/starter_python_smart_contract_python/.algokit.toml +++ /dev/null @@ -1,42 +0,0 @@ -[algokit] -min_version = "v2.0.0" - -[generate.smart-contract] -description = "Generate a new smart contract for existing project" -path = ".algokit/generators/create_contract" - -[generate.env-file] -description = "Generate a new generic or Algorand network specific .env file" -path = ".algokit/generators/create_env_file" - -[project] -type = 'contract' -name = 'starter_python_smart_contract_python' -artifacts = 'smart_contracts/artifacts' - -[project.deploy] -command = "poetry run python -m smart_contracts deploy" -environment_secrets = [ - "DEPLOYER_MNEMONIC", -] - -[project.deploy.localnet] -environment_secrets = [] - -[project.run] -# Commands intented for use locally and in CI -build = { commands = [ - 'poetry run python -m smart_contracts build', -], description = 'Build all smart contracts in the project' } -lint = { commands = [ -], description = 'Perform linting' } -audit-teal = { commands = [ - # 🚨 IMPORTANT 🚨: For strict TEAL validation, remove --exclude statements. The default starter contract is not for production. Ensure thorough testing and adherence to best practices in smart contract development. This is not a replacement for a professional audit. - 'algokit task analyze smart_contracts/artifacts --recursive --force --exclude rekey-to --exclude is-updatable --exclude missing-fee-check --exclude is-deletable --exclude can-close-asset --exclude can-close-account --exclude unprotected-deletable --exclude unprotected-updatable', -], description = 'Audit TEAL files' } - -# Commands intented for CI only, prefixed with `ci-` by convention -ci-teal-diff = { commands = [ - 'git add -N ./smart_contracts/artifacts', - 'git diff --exit-code --minimal ./smart_contracts/artifacts', -], description = 'Check TEAL files for differences' } diff --git a/examples/generators/starter_python_smart_contract_python/.algokit/.copier-answers.yml b/examples/generators/starter_python_smart_contract_python/.algokit/.copier-answers.yml deleted file mode 100644 index 6f932ac..0000000 --- a/examples/generators/starter_python_smart_contract_python/.algokit/.copier-answers.yml +++ /dev/null @@ -1,10 +0,0 @@ -# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY -_commit: -_src_path: -author_email: None -author_name: None -contract_name: hello_world -deployment_language: python -preset_name: starter -project_name: starter_python_smart_contract_python - diff --git a/examples/generators/starter_python_smart_contract_python/.algokit/generators/create_contract/copier.yaml b/examples/generators/starter_python_smart_contract_python/.algokit/generators/create_contract/copier.yaml deleted file mode 100644 index 73805de..0000000 --- a/examples/generators/starter_python_smart_contract_python/.algokit/generators/create_contract/copier.yaml +++ /dev/null @@ -1,10 +0,0 @@ -_tasks: - - "echo '==== Successfully initialized new smart contract 🚀 ===='" - -contract_name: - type: str - help: Name of your new contract. - placeholder: "my-new-contract" - default: "my-new-contract" - -_templates_suffix: ".j2" diff --git a/examples/generators/starter_python_smart_contract_python/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 b/examples/generators/starter_python_smart_contract_python/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 deleted file mode 100644 index 829e3a0..0000000 --- a/examples/generators/starter_python_smart_contract_python/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 +++ /dev/null @@ -1,9 +0,0 @@ -# pyright: reportMissingModuleSource=false -from algopy import ARC4Contract, String -from algopy.arc4 import abimethod - - -class {{ contract_name.split('_')|map('capitalize')|join }}(ARC4Contract): - @abimethod() - def hello(self, name: String) -> String: - return "Hello, " + name diff --git a/examples/generators/starter_python_smart_contract_python/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/deploy_config.py.j2 b/examples/generators/starter_python_smart_contract_python/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/deploy_config.py.j2 deleted file mode 100644 index eb726b9..0000000 --- a/examples/generators/starter_python_smart_contract_python/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/deploy_config.py.j2 +++ /dev/null @@ -1,35 +0,0 @@ -import logging - -import algokit_utils -from algosdk.v2client.algod import AlgodClient -from algosdk.v2client.indexer import IndexerClient - -logger = logging.getLogger(__name__) - - -# define deployment behaviour based on supplied app spec -def deploy( - algod_client: AlgodClient, - indexer_client: IndexerClient, - app_spec: algokit_utils.ApplicationSpecification, - deployer: algokit_utils.Account, -) -> None: - from smart_contracts.artifacts.{{ contract_name }}.{{ contract_name }}_client import ( - {{ contract_name.split('_')|map('capitalize')|join }}Client, - ) - - app_client = {{ contract_name.split('_')|map('capitalize')|join }}Client( - algod_client, - creator=deployer, - indexer_client=indexer_client, - ) - app_client.deploy( - on_schema_break=algokit_utils.OnSchemaBreak.AppendApp, - on_update=algokit_utils.OnUpdate.AppendApp, - ) - name = "world" - response = app_client.hello(name=name) - logger.info( - f"Called hello on {app_spec.contract.name} ({app_client.app_id}) " - f"with name={name}, received: {response.return_value}" - ) diff --git a/examples/generators/starter_python_smart_contract_python/.algokit/generators/create_env_file/copier.yaml b/examples/generators/starter_python_smart_contract_python/.algokit/generators/create_env_file/copier.yaml deleted file mode 100644 index afa2cac..0000000 --- a/examples/generators/starter_python_smart_contract_python/.algokit/generators/create_env_file/copier.yaml +++ /dev/null @@ -1,49 +0,0 @@ -_tasks: - - "echo '==== Successfully generated new .env file 🚀 ===='" - -target_network: - type: str - help: Name of your target network. - choices: - - mainnet - - testnet - - localnet - - custom - default: "localnet" - when: "{{ not use_generic_env }}" - -custom_network_name: - type: str - help: Name of your custom Algorand network. - placeholder: "custom" - when: "{{ not use_generic_env and target_network == 'custom' }}" - -is_localnet: - type: bool - help: Whether to deploy on localnet. - placeholder: "true" - default: "{{ target_network == 'localnet' and not use_generic_env }}" - when: 'false' - -is_testnet: - type: bool - help: Whether to deploy on testnet. - placeholder: "true" - default: "{{ target_network == 'testnet' and not use_generic_env }}" - when: 'false' - -is_mainnet: - type: bool - help: Whether to deploy on mainnet. - placeholder: "true" - default: "{{ target_network == 'mainnet' and not use_generic_env }}" - when: 'false' - -is_customnet: - type: bool - help: Whether to deploy on custom network. - placeholder: "true" - default: "{{ target_network == 'custom' and not use_generic_env }}" - when: 'false' - -_templates_suffix: ".j2" diff --git a/examples/generators/starter_python_smart_contract_python/.algokit/generators/create_env_file/{% if is_customnet %}.env.{{custom_network_name}}{% endif %} b/examples/generators/starter_python_smart_contract_python/.algokit/generators/create_env_file/{% if is_customnet %}.env.{{custom_network_name}}{% endif %} deleted file mode 100644 index cfc9f21..0000000 --- a/examples/generators/starter_python_smart_contract_python/.algokit/generators/create_env_file/{% if is_customnet %}.env.{{custom_network_name}}{% endif %} +++ /dev/null @@ -1,7 +0,0 @@ -# this file contains algorand network settings for interacting with testnet via algonode -ALGOD_TOKEN={YOUR_ALGOD_TOKEN} -ALGOD_SERVER={YOUR_ALGOD_SERVER_URL} -ALGOD_PORT={YOUR_ALGOD_PORT} -INDEXER_TOKEN={YOUR_INDEXER_TOKEN} -INDEXER_SERVER={YOUR_INDEXER_SERVER_URL} -INDEXER_PORT={YOUR_INDEXER_PORT} diff --git a/examples/generators/starter_python_smart_contract_python/.algokit/generators/create_env_file/{% if is_localnet %}.env.localnet{% endif %} b/examples/generators/starter_python_smart_contract_python/.algokit/generators/create_env_file/{% if is_localnet %}.env.localnet{% endif %} deleted file mode 100644 index fcbf442..0000000 --- a/examples/generators/starter_python_smart_contract_python/.algokit/generators/create_env_file/{% if is_localnet %}.env.localnet{% endif %} +++ /dev/null @@ -1,7 +0,0 @@ -# this file should contain environment variables specific to algokit localnet -ALGOD_TOKEN=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -ALGOD_SERVER=http://localhost -ALGOD_PORT=4001 -INDEXER_TOKEN=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -INDEXER_SERVER=http://localhost -INDEXER_PORT=8980 diff --git a/examples/generators/starter_python_smart_contract_python/.algokit/generators/create_env_file/{% if is_mainnet %}.env.mainnet{% endif %} b/examples/generators/starter_python_smart_contract_python/.algokit/generators/create_env_file/{% if is_mainnet %}.env.mainnet{% endif %} deleted file mode 100644 index bb9a787..0000000 --- a/examples/generators/starter_python_smart_contract_python/.algokit/generators/create_env_file/{% if is_mainnet %}.env.mainnet{% endif %} +++ /dev/null @@ -1,3 +0,0 @@ -# this file contains algorand network settings for interacting with testnet via algonode -ALGOD_SERVER=https://mainnet-api.algonode.cloud -INDEXER_SERVER=https://mainnet-idx.algonode.cloud diff --git a/examples/generators/starter_python_smart_contract_python/.algokit/generators/create_env_file/{% if is_testnet %}.env.testnet{% endif %} b/examples/generators/starter_python_smart_contract_python/.algokit/generators/create_env_file/{% if is_testnet %}.env.testnet{% endif %} deleted file mode 100644 index eeea43d..0000000 --- a/examples/generators/starter_python_smart_contract_python/.algokit/generators/create_env_file/{% if is_testnet %}.env.testnet{% endif %} +++ /dev/null @@ -1,3 +0,0 @@ -# this file contains algorand network settings for interacting with testnet via algonode -ALGOD_SERVER=https://testnet-api.algonode.cloud -INDEXER_SERVER=https://testnet-idx.algonode.cloud diff --git a/examples/generators/starter_python_smart_contract_python/.vscode/tasks.json b/examples/generators/starter_python_smart_contract_python/.vscode/tasks.json deleted file mode 100644 index eb1e767..0000000 --- a/examples/generators/starter_python_smart_contract_python/.vscode/tasks.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "label": "Build contracts", - "command": "${workspaceFolder}/.venv/bin/python", - "windows": { - "command": "${workspaceFolder}/.venv/Scripts/python.exe" - }, - "args": ["-m", "smart_contracts", "build"], - "options": { - "cwd": "${workspaceFolder}" - }, - "group": { - "kind": "build", - "isDefault": true - }, - "problemMatcher": [] - }, - { - "label": "Build contracts (+ LocalNet)", - "command": "${workspaceFolder}/.venv/bin/python", - "windows": { - "command": "${workspaceFolder}/.venv/Scripts/python.exe" - }, - "args": ["-m", "smart_contracts", "build"], - "options": { - "cwd": "${workspaceFolder}" - }, - "dependsOn": "Start AlgoKit LocalNet", - "problemMatcher": [] - }, - { - "label": "Start AlgoKit LocalNet", - "command": "algokit", - "args": ["localnet", "start"], - "type": "shell", - "options": { - "cwd": "${workspaceFolder}" - }, - "problemMatcher": [] - }, - { - "label": "Stop AlgoKit LocalNet", - "command": "algokit", - "args": ["localnet", "stop"], - "type": "shell", - "options": { - "cwd": "${workspaceFolder}" - }, - "problemMatcher": [] - }, - { - "label": "Reset AlgoKit LocalNet", - "command": "algokit", - "args": ["localnet", "reset"], - "type": "shell", - "options": { - "cwd": "${workspaceFolder}" - }, - "problemMatcher": [] - }, - { - "label": "Analyze TEAL contracts with AlgoKit Tealer integration", - "command": "algokit", - "args": [ - "task", - "analyze", - "${workspaceFolder}/.algokit", - "--recursive", - "--force" - ], - "options": { - "cwd": "${workspaceFolder}" - }, - "problemMatcher": [] - } - ] -} diff --git a/examples/generators/starter_python_smart_contract_python/README.md b/examples/generators/starter_python_smart_contract_python/README.md deleted file mode 100644 index e7d5844..0000000 --- a/examples/generators/starter_python_smart_contract_python/README.md +++ /dev/null @@ -1,101 +0,0 @@ -# starter_python_smart_contract_python - -This project has been generated using AlgoKit. See below for default getting started instructions. - -# Setup - -### Pre-requisites - -- [Python 3.12](https://www.python.org/downloads/) or later -- [Docker](https://www.docker.com/) (only required for LocalNet) - -> For interactive tour over the codebase, download [vsls-contrib.codetour](https://marketplace.visualstudio.com/items?itemName=vsls-contrib.codetour) extension for VS Code, then open the [`.codetour.json`](./.tours/getting-started-with-your-algokit-project.tour) file in code tour extension. - -### Initial Setup - -#### 1. Clone the Repository -Start by cloning this repository to your local machine. - -#### 2. Install Pre-requisites -Ensure the following pre-requisites are installed and properly configured: - -- **Docker**: Required for running a local Algorand network. [Install Docker](https://www.docker.com/). -- **AlgoKit CLI**: Essential for project setup and operations. Install the latest version from [AlgoKit CLI Installation Guide](https://github.com/algorandfoundation/algokit-cli#install). Verify installation with `algokit --version`, expecting `2.0.0` or later. - -#### 3. Bootstrap Your Local Environment -Run the following commands within the project folder: - -- **Install Poetry**: Required for Python dependency management. [Installation Guide](https://python-poetry.org/docs/#installation). Verify with `poetry -V` to see version `1.2`+. -- **Setup Project**: Execute `algokit project bootstrap all` to install dependencies and setup a Python virtual environment in `.venv`. -- **Configure environment**: Execute `algokit generate env-file -a target_network localnet` to create a `.env.localnet` file with default configuration for `localnet`. -- **Start LocalNet**: Use `algokit localnet start` to initiate a local Algorand network. - -### Development Workflow - -#### Terminal -Directly manage and interact with your project using AlgoKit commands: - -1. **Build Contracts**: `algokit project run build` compiles all smart contracts. You can also specify a specific contract by passing the name of the contract folder as an extra argument. -For example: `algokit project run build -- hello_world` will only build the `hello_world` contract. -2. **Deploy**: Use `algokit project deploy localnet` to deploy contracts to the local network. You can also specify a specific contract by passing the name of the contract folder as an extra argument. -For example: `algokit project deploy localnet -- hello_world` will only deploy the `hello_world` contract. - -#### VS Code -For a seamless experience with breakpoint debugging and other features: - -1. **Open Project**: In VS Code, open the repository root. -2. **Install Extensions**: Follow prompts to install recommended extensions. -3. **Debugging**: - - Use `F5` to start debugging. - - **Windows Users**: Select the Python interpreter at `./.venv/Scripts/python.exe` via `Ctrl/Cmd + Shift + P` > `Python: Select Interpreter` before the first run. - -#### JetBrains IDEs -While primarily optimized for VS Code, JetBrains IDEs are supported: - -1. **Open Project**: In your JetBrains IDE, open the repository root. -2. **Automatic Setup**: The IDE should configure the Python interpreter and virtual environment. -3. **Debugging**: Use `Shift+F10` or `Ctrl+R` to start debugging. Note: Windows users may encounter issues with pre-launch tasks due to a known bug. See [JetBrains forums](https://youtrack.jetbrains.com/issue/IDEA-277486/Shell-script-configuration-cannot-run-as-before-launch-task) for workarounds. - -## AlgoKit Workspaces and Project Management -This project supports both standalone and monorepo setups through AlgoKit workspaces. Leverage [`algokit project run`](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/project/run.md) commands for efficient monorepo project orchestration and management across multiple projects within a workspace. - -## AlgoKit Generators - -This template provides a set of [algokit generators](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/generate.md) that allow you to further modify the project instantiated from the template to fit your needs, as well as giving you a base to build your own extensions to invoke via the `algokit generate` command. - -### Generate Smart Contract - -By default the template creates a single `HelloWorld` contract under hello_world folder in the `smart_contracts` directory. To add a new contract: - -1. From the root of the project (`../`) execute `algokit generate smart-contract`. This will create a new starter smart contract and deployment configuration file under `{your_contract_name}` subfolder in the `smart_contracts` directory. -2. Each contract potentially has different creation parameters and deployment steps. Hence, you need to define your deployment logic in `deploy_config.py`file. -3. `config.py` file will automatically build all contracts in the `smart_contracts` directory. If you want to build specific contracts manually, modify the default code provided by the template in `config.py` file. - -> Please note, above is just a suggested convention tailored for the base configuration and structure of this template. The default code supplied by the template in `config.py` and `index.ts` (if using ts clients) files are tailored for the suggested convention. You are free to modify the structure and naming conventions as you see fit. - -### Generate '.env' files - -By default the template instance does not contain any env files. Using [`algokit project deploy`](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/project/deploy.md) against `localnet` | `testnet` | `mainnet` will use default values for `algod` and `indexer` unless overwritten via `.env` or `.env.{target_network}`. - -To generate a new `.env` or `.env.{target_network}` file, run `algokit generate env-file` - -### Debugging Smart Contracts - -This project is optimized to work with AlgoKit AVM Debugger extension. To activate it: -Refer to the commented header in the `__main__.py` file in the `smart_contracts` folder. - -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. - -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). - -# Tools - -This project makes use of Algorand Python to build Algorand smart contracts. The following tools are in use: - -- [Algorand](https://www.algorand.com/) - Layer 1 Blockchain; [Developer portal](https://developer.algorand.org/), [Why Algorand?](https://developer.algorand.org/docs/get-started/basics/why_algorand/) -- [AlgoKit](https://github.com/algorandfoundation/algokit-cli) - One-stop shop tool for developers building on the Algorand network; [docs](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/algokit.md), [intro tutorial](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/tutorials/intro.md) -- [Algorand Python](https://github.com/algorandfoundation/puya) - A semantically and syntactically compatible, typed Python language that works with standard Python tooling and allows you to express smart contracts (apps) and smart signatures (logic signatures) for deployment on the Algorand Virtual Machine (AVM); [docs](https://github.com/algorandfoundation/puya), [examples](https://github.com/algorandfoundation/puya/tree/main/examples) -- [AlgoKit Utils](https://github.com/algorandfoundation/algokit-utils-py) - A set of core Algorand utilities that make it easier to build solutions on Algorand. -- [Poetry](https://python-poetry.org/): Python packaging and dependency management. -It has also been configured to have a productive dev experience out of the box in [VS Code](https://code.visualstudio.com/), see the [.vscode](./.vscode) folder. - diff --git a/examples/generators/starter_python_smart_contract_python/poetry.toml b/examples/generators/starter_python_smart_contract_python/poetry.toml deleted file mode 100644 index 5fcef8c..0000000 --- a/examples/generators/starter_python_smart_contract_python/poetry.toml +++ /dev/null @@ -1,3 +0,0 @@ -[virtualenvs] -in-project = true -prefer-active-python = true diff --git a/examples/generators/starter_python_smart_contract_python/pyproject.toml b/examples/generators/starter_python_smart_contract_python/pyproject.toml deleted file mode 100644 index 8f843a7..0000000 --- a/examples/generators/starter_python_smart_contract_python/pyproject.toml +++ /dev/null @@ -1,22 +0,0 @@ -[tool.poetry] -name = "starter_python_smart_contract_python" -version = "0.1.0" -description = "Algorand smart contracts" -authors = ["None "] -readme = "README.md" - -[tool.poetry.dependencies] -python = "^3.12" -algokit-utils = "^2.4.0" -python-dotenv = "^1.0.0" -algorand-python = "^2.0.0" -algorand-python-testing = "^0.4.0" - -[tool.poetry.group.dev.dependencies] -algokit-client-generator = "^1.1.3" -puyapy = "*" - -[build-system] -requires = ["poetry-core"] -build-backend = "poetry.core.masonry.api" - diff --git a/examples/generators/starter_python_smart_contract_python/smart_contracts/__init__.py b/examples/generators/starter_python_smart_contract_python/smart_contracts/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/examples/generators/starter_python_smart_contract_python/smart_contracts/_helpers/__init__.py b/examples/generators/starter_python_smart_contract_python/smart_contracts/_helpers/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/examples/generators/starter_python_smart_contract_python/smart_contracts/_helpers/config.py b/examples/generators/starter_python_smart_contract_python/smart_contracts/_helpers/config.py deleted file mode 100644 index 8f3ca93..0000000 --- a/examples/generators/starter_python_smart_contract_python/smart_contracts/_helpers/config.py +++ /dev/null @@ -1,61 +0,0 @@ -import dataclasses -import importlib -from collections.abc import Callable -from pathlib import Path - -from algokit_utils import Account, ApplicationSpecification -from algosdk.v2client.algod import AlgodClient -from algosdk.v2client.indexer import IndexerClient - - -@dataclasses.dataclass -class SmartContract: - path: Path - name: str - deploy: ( - Callable[[AlgodClient, IndexerClient, ApplicationSpecification, Account], None] - | None - ) = None - - -def import_contract(folder: Path) -> Path: - """Imports the contract from a folder if it exists.""" - contract_path = folder / "contract.py" - if contract_path.exists(): - return contract_path - else: - raise Exception(f"Contract not found in {folder}") - - -def import_deploy_if_exists( - folder: Path, -) -> ( - Callable[[AlgodClient, IndexerClient, ApplicationSpecification, Account], None] - | None -): - """Imports the deploy function from a folder if it exists.""" - try: - deploy_module = importlib.import_module( - f"{folder.parent.name}.{folder.name}.deploy_config" - ) - return deploy_module.deploy # type: ignore - except ImportError: - return None - - -def has_contract_file(directory: Path) -> bool: - """Checks whether the directory contains contract.py file.""" - return (directory / "contract.py").exists() - - -# define contracts to build and/or deploy -base_dir = Path("smart_contracts") -contracts = [ - SmartContract( - path=import_contract(folder), - name=folder.name, - deploy=import_deploy_if_exists(folder), - ) - for folder in base_dir.iterdir() - if folder.is_dir() and has_contract_file(folder) -] diff --git a/examples/generators/starter_python_smart_contract_python/smart_contracts/cool_contract/contract.py b/examples/generators/starter_python_smart_contract_python/smart_contracts/cool_contract/contract.py deleted file mode 100644 index 271ad93..0000000 --- a/examples/generators/starter_python_smart_contract_python/smart_contracts/cool_contract/contract.py +++ /dev/null @@ -1,9 +0,0 @@ -# pyright: reportMissingModuleSource=false -from algopy import ARC4Contract, String -from algopy.arc4 import abimethod - - -class CoolContract(ARC4Contract): - @abimethod() - def hello(self, name: String) -> String: - return "Hello, " + name diff --git a/examples/generators/starter_python_smart_contract_python/smart_contracts/cool_contract/deploy_config.py b/examples/generators/starter_python_smart_contract_python/smart_contracts/cool_contract/deploy_config.py deleted file mode 100644 index c4f0afd..0000000 --- a/examples/generators/starter_python_smart_contract_python/smart_contracts/cool_contract/deploy_config.py +++ /dev/null @@ -1,35 +0,0 @@ -import logging - -import algokit_utils -from algosdk.v2client.algod import AlgodClient -from algosdk.v2client.indexer import IndexerClient - -logger = logging.getLogger(__name__) - - -# define deployment behaviour based on supplied app spec -def deploy( - algod_client: AlgodClient, - indexer_client: IndexerClient, - app_spec: algokit_utils.ApplicationSpecification, - deployer: algokit_utils.Account, -) -> None: - from smart_contracts.artifacts.cool_contract.cool_contract_client import ( - CoolContractClient, - ) - - app_client = CoolContractClient( - algod_client, - creator=deployer, - indexer_client=indexer_client, - ) - app_client.deploy( - on_schema_break=algokit_utils.OnSchemaBreak.AppendApp, - on_update=algokit_utils.OnUpdate.AppendApp, - ) - name = "world" - response = app_client.hello(name=name) - logger.info( - f"Called hello on {app_spec.contract.name} ({app_client.app_id}) " - f"with name={name}, received: {response.return_value}" - ) diff --git a/examples/generators/starter_python_smart_contract_python/smart_contracts/hello_world/contract.py b/examples/generators/starter_python_smart_contract_python/smart_contracts/hello_world/contract.py deleted file mode 100644 index 8a8d12b..0000000 --- a/examples/generators/starter_python_smart_contract_python/smart_contracts/hello_world/contract.py +++ /dev/null @@ -1,8 +0,0 @@ -from algopy import ARC4Contract, String -from algopy.arc4 import abimethod - - -class HelloWorld(ARC4Contract): - @abimethod() - def hello(self, name: String) -> String: - return "Hello, " + name diff --git a/examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_contract/copier.yaml b/examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_contract/copier.yaml deleted file mode 100644 index 73805de..0000000 --- a/examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_contract/copier.yaml +++ /dev/null @@ -1,10 +0,0 @@ -_tasks: - - "echo '==== Successfully initialized new smart contract 🚀 ===='" - -contract_name: - type: str - help: Name of your new contract. - placeholder: "my-new-contract" - default: "my-new-contract" - -_templates_suffix: ".j2" diff --git a/examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 b/examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 deleted file mode 100644 index 829e3a0..0000000 --- a/examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 +++ /dev/null @@ -1,9 +0,0 @@ -# pyright: reportMissingModuleSource=false -from algopy import ARC4Contract, String -from algopy.arc4 import abimethod - - -class {{ contract_name.split('_')|map('capitalize')|join }}(ARC4Contract): - @abimethod() - def hello(self, name: String) -> String: - return "Hello, " + name diff --git a/examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_env_file/copier.yaml b/examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_env_file/copier.yaml deleted file mode 100644 index afa2cac..0000000 --- a/examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_env_file/copier.yaml +++ /dev/null @@ -1,49 +0,0 @@ -_tasks: - - "echo '==== Successfully generated new .env file 🚀 ===='" - -target_network: - type: str - help: Name of your target network. - choices: - - mainnet - - testnet - - localnet - - custom - default: "localnet" - when: "{{ not use_generic_env }}" - -custom_network_name: - type: str - help: Name of your custom Algorand network. - placeholder: "custom" - when: "{{ not use_generic_env and target_network == 'custom' }}" - -is_localnet: - type: bool - help: Whether to deploy on localnet. - placeholder: "true" - default: "{{ target_network == 'localnet' and not use_generic_env }}" - when: 'false' - -is_testnet: - type: bool - help: Whether to deploy on testnet. - placeholder: "true" - default: "{{ target_network == 'testnet' and not use_generic_env }}" - when: 'false' - -is_mainnet: - type: bool - help: Whether to deploy on mainnet. - placeholder: "true" - default: "{{ target_network == 'mainnet' and not use_generic_env }}" - when: 'false' - -is_customnet: - type: bool - help: Whether to deploy on custom network. - placeholder: "true" - default: "{{ target_network == 'custom' and not use_generic_env }}" - when: 'false' - -_templates_suffix: ".j2" diff --git a/examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_customnet %}.env.{{custom_network_name}}{% endif %} b/examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_customnet %}.env.{{custom_network_name}}{% endif %} deleted file mode 100644 index cfc9f21..0000000 --- a/examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_customnet %}.env.{{custom_network_name}}{% endif %} +++ /dev/null @@ -1,7 +0,0 @@ -# this file contains algorand network settings for interacting with testnet via algonode -ALGOD_TOKEN={YOUR_ALGOD_TOKEN} -ALGOD_SERVER={YOUR_ALGOD_SERVER_URL} -ALGOD_PORT={YOUR_ALGOD_PORT} -INDEXER_TOKEN={YOUR_INDEXER_TOKEN} -INDEXER_SERVER={YOUR_INDEXER_SERVER_URL} -INDEXER_PORT={YOUR_INDEXER_PORT} diff --git a/examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_localnet %}.env.localnet{% endif %} b/examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_localnet %}.env.localnet{% endif %} deleted file mode 100644 index fcbf442..0000000 --- a/examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_localnet %}.env.localnet{% endif %} +++ /dev/null @@ -1,7 +0,0 @@ -# this file should contain environment variables specific to algokit localnet -ALGOD_TOKEN=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -ALGOD_SERVER=http://localhost -ALGOD_PORT=4001 -INDEXER_TOKEN=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -INDEXER_SERVER=http://localhost -INDEXER_PORT=8980 diff --git a/examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_mainnet %}.env.mainnet{% endif %} b/examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_mainnet %}.env.mainnet{% endif %} deleted file mode 100644 index bb9a787..0000000 --- a/examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_mainnet %}.env.mainnet{% endif %} +++ /dev/null @@ -1,3 +0,0 @@ -# this file contains algorand network settings for interacting with testnet via algonode -ALGOD_SERVER=https://mainnet-api.algonode.cloud -INDEXER_SERVER=https://mainnet-idx.algonode.cloud diff --git a/examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_testnet %}.env.testnet{% endif %} b/examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_testnet %}.env.testnet{% endif %} deleted file mode 100644 index eeea43d..0000000 --- a/examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_env_file/{% if is_testnet %}.env.testnet{% endif %} +++ /dev/null @@ -1,3 +0,0 @@ -# this file contains algorand network settings for interacting with testnet via algonode -ALGOD_SERVER=https://testnet-api.algonode.cloud -INDEXER_SERVER=https://testnet-idx.algonode.cloud diff --git a/examples/generators/starter_python_smart_contract_typescript/.editorconfig b/examples/generators/starter_python_smart_contract_typescript/.editorconfig deleted file mode 100644 index e2fda34..0000000 --- a/examples/generators/starter_python_smart_contract_typescript/.editorconfig +++ /dev/null @@ -1,10 +0,0 @@ -root=true - -[*] -indent_style = space -indent_size = 2 -end_of_line = lf -insert_final_newline = true - -[*.py] -indent_size = 4 diff --git a/examples/generators/starter_python_smart_contract_typescript/.gitattributes b/examples/generators/starter_python_smart_contract_typescript/.gitattributes deleted file mode 100644 index 6313b56..0000000 --- a/examples/generators/starter_python_smart_contract_typescript/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -* text=auto eol=lf diff --git a/examples/generators/starter_python_smart_contract_typescript/.gitignore b/examples/generators/starter_python_smart_contract_typescript/.gitignore deleted file mode 100644 index 070829c..0000000 --- a/examples/generators/starter_python_smart_contract_typescript/.gitignore +++ /dev/null @@ -1,180 +0,0 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.py,cover -.hypothesis/ -.pytest_cache/ -cover/ -coverage/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -.pybuilder/ -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -# For a library or package, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# .python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# poetry -# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control -#poetry.lock - -# pdm -# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. -#pdm.lock -# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it -# in version control. -# https://pdm.fming.dev/#use-with-ide -.pdm.toml - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -.env.* -!.env.*.template -!.env.template -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# pytype static type analyzer -.pytype/ - -# Ruff (linter) -.ruff_cache/ - -# Cython debug symbols -cython_debug/ - -# PyCharm -.idea -!.idea/ -.idea/* -!.idea/runConfigurations/ - -# macOS -.DS_Store - -# Received approval test files -*.received.* - -# NPM -node_modules - -# AlgoKit -debug_traces/ -.algokit/static-analysis/ # Replace with .algokit/static-analysis/tealer/ to enable snapshot checks in CI -.algokit/sources diff --git a/examples/generators/starter_python_smart_contract_typescript/.tours/getting-started-with-your-algokit-project.tour b/examples/generators/starter_python_smart_contract_typescript/.tours/getting-started-with-your-algokit-project.tour deleted file mode 100644 index 4a58a5b..0000000 --- a/examples/generators/starter_python_smart_contract_typescript/.tours/getting-started-with-your-algokit-project.tour +++ /dev/null @@ -1,51 +0,0 @@ -{ - "$schema": "https://aka.ms/codetour-schema", - "title": "Getting Started with Your AlgoKit Project", - "steps": [ - { - "file": "README.md", - "description": "Welcome to your brand new AlgoKit template-based project. In this tour, we will guide you through the main features and capabilities included in the template.", - "line": 3 - }, - { - "file": "README.md", - "description": "Start by ensuring you have followed the setup of pre-requisites.", - "line": 9 - }, - { - "file": ".algokit.toml", - "description": "This is the main configuration file used by algokit-cli to manage the project. The default template includes a starter 'Hello World' contract that is deployed via the `algokit-utils` package (either `ts` or `py`, depending on your choice). To create a new smart contract, you can use the [`algokit generate`](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/generate.md) command and invoke a pre-bundled generator template by running `algokit generate smart-contract` (see how it is defined in the `.algokit.toml`, you can create your own generators if needed). This action will create a new folder in the `smart_contracts` directory, named after your project. Each folder contains a `contract.py` file, which is the entry point for your contract implementation, and `deploy_config.py` | `deployConfig.ts` files (depending on the language chosen for the template), that perform the deployment of the contract. Additionally you can define custom commands to run (similar to `npm` scripts), see definitions under `[project]` section in `.algokit.toml`.", - "line": 1 - }, - { - "file": "smart_contracts/hello_world/deploy-config.ts", - "description": "The default deployment scripts invoke a sample method on the starter contract that demonstrates how to interact with your deployed Algorand on-chain applications using the [`AlgoKit Typed Clients`](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/generate.md#1-typed-clients) feature. The invocation if deploy is aliased in `.algokit.toml` file, allowing simple deployments via `algokit project deploy` command.", - "line": 32 - }, - { - "file": ".env.localnet.template", - "description": "Environment files are a crucial mechanism that allows you to set up the [`algokit deploy`](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/deploy.md) feature to simplify deploying your contracts in CI/CD environments (please note we still recommend careful evaluation when it comes to deployment to MainNet). Clone the file and remove the `.template` suffix to apply the changes to deployment scripts and launch configurations. The network prefix `localnet|testnet|mainnet` is primarily optimized for `algokit deploy`. The order of loading the variables is `.env.{network}` < `.env`.", - "line": 2 - }, - { - "file": ".vscode/launch.json", - "description": "Refer to the pre-bundled Visual Studio launch configurations, offering various options on how to execute the build and deployment of your smart contracts. Alternatively execute `algokit project run` to see list of available custom commands.", - "line": 5 - }, - { - "file": ".vscode/extensions.json", - "description": "We highly recommend installing the recommended extensions to get the most out of this template starter project in your VSCode IDE.", - "line": 3 - }, - { - "file": "smart_contracts/index.ts", - "description": "Uncomment the following lines to enable complementary utilities that will generate artifacts required for the [AlgoKit AVM Debugger](https://github.com/algorandfoundation/algokit-avm-vscode-debugger) VSCode plugin available on the [VSCode Extension Marketplace](https://marketplace.visualstudio.com/items?itemName=algorandfoundation.algokit-avm-vscode-debugger). A new folder will be automatically created in the `.algokit` directory with source maps of all TEAL contracts in this workspace, as well as traces that will appear in a folder at the root of the workspace. You can then use the traces as entry points to trigger the debug extension. Make sure to have the `.algokit.toml` file available at the root of the workspace.", - "line": 15 - }, - { - "file": "smart_contracts/_helpers/__init__.py", - "description": "This folder contains helper scripts for contract management. These automate tasks like compiling, generating clients, and deploying. Usually, you won't need to edit these files, but advanced users can expand them for custom needs.", - "line": 1 - } - ] -} diff --git a/examples/generators/starter_python_smart_contract_typescript/.vscode/settings.json b/examples/generators/starter_python_smart_contract_typescript/.vscode/settings.json deleted file mode 100644 index 42babe6..0000000 --- a/examples/generators/starter_python_smart_contract_typescript/.vscode/settings.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - // General - see also /.editorconfig - "editor.formatOnSave": true, - "files.exclude": { - "**/.git": true, - "**/.DS_Store": true, - "**/Thumbs.db": true, - ".mypy_cache": true, - ".pytest_cache": true, - ".ruff_cache": true, - "**/__pycache__": true, - ".idea": true - }, - - // TypeScript - "editor.defaultFormatter": "esbenp.prettier-vscode", - - // Python - "python.analysis.extraPaths": ["${workspaceFolder}/smart_contracts"], - "python.analysis.diagnosticSeverityOverrides": { - "reportMissingModuleSource": "none" - }, - "python.defaultInterpreterPath": "${workspaceFolder}/.venv", - "[python]": { - "editor.codeActionsOnSave": { - "source.fixAll": "explicit", - // Prevent default import sorting from running; Ruff will sort imports for us anyway - "source.organizeImports": "never" - }, - "editor.defaultFormatter": null, - }, - - // On Windows, if execution policy is set to Signed (default) then it won't be able to activate the venv - // so instead let's set it to RemoteSigned for VS Code terminal - "terminal.integrated.shellArgs.windows": ["-ExecutionPolicy", "RemoteSigned"], -} diff --git a/examples/generators/starter_python_smart_contract_typescript/.vscode/tasks.json b/examples/generators/starter_python_smart_contract_typescript/.vscode/tasks.json deleted file mode 100644 index eb1e767..0000000 --- a/examples/generators/starter_python_smart_contract_typescript/.vscode/tasks.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "label": "Build contracts", - "command": "${workspaceFolder}/.venv/bin/python", - "windows": { - "command": "${workspaceFolder}/.venv/Scripts/python.exe" - }, - "args": ["-m", "smart_contracts", "build"], - "options": { - "cwd": "${workspaceFolder}" - }, - "group": { - "kind": "build", - "isDefault": true - }, - "problemMatcher": [] - }, - { - "label": "Build contracts (+ LocalNet)", - "command": "${workspaceFolder}/.venv/bin/python", - "windows": { - "command": "${workspaceFolder}/.venv/Scripts/python.exe" - }, - "args": ["-m", "smart_contracts", "build"], - "options": { - "cwd": "${workspaceFolder}" - }, - "dependsOn": "Start AlgoKit LocalNet", - "problemMatcher": [] - }, - { - "label": "Start AlgoKit LocalNet", - "command": "algokit", - "args": ["localnet", "start"], - "type": "shell", - "options": { - "cwd": "${workspaceFolder}" - }, - "problemMatcher": [] - }, - { - "label": "Stop AlgoKit LocalNet", - "command": "algokit", - "args": ["localnet", "stop"], - "type": "shell", - "options": { - "cwd": "${workspaceFolder}" - }, - "problemMatcher": [] - }, - { - "label": "Reset AlgoKit LocalNet", - "command": "algokit", - "args": ["localnet", "reset"], - "type": "shell", - "options": { - "cwd": "${workspaceFolder}" - }, - "problemMatcher": [] - }, - { - "label": "Analyze TEAL contracts with AlgoKit Tealer integration", - "command": "algokit", - "args": [ - "task", - "analyze", - "${workspaceFolder}/.algokit", - "--recursive", - "--force" - ], - "options": { - "cwd": "${workspaceFolder}" - }, - "problemMatcher": [] - } - ] -} diff --git a/examples/generators/starter_python_smart_contract_typescript/package.json b/examples/generators/starter_python_smart_contract_typescript/package.json deleted file mode 100644 index 5b1fef2..0000000 --- a/examples/generators/starter_python_smart_contract_typescript/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "smart_contracts", - "version": "1.0.0", - "description": "Smart contract deployer", - "main": "index.ts", - "scripts": { - "deploy": "ts-node-dev --transpile-only --watch .env -r dotenv/config smart_contracts/index.ts", - "deploy:ci": "ts-node --transpile-only -r dotenv/config smart_contracts/index.ts", - "format": "prettier --write ." - }, - "engines": { - "node": ">=20.0", - "npm": ">=9.0" - }, - "dependencies": { - "@algorandfoundation/algokit-utils": "^7.0.0", - "@algorandfoundation/algokit-utils-debug": "^1.0.2", - "algosdk": ">=2.9.0 <3.0" - }, - "devDependencies": { - "@algorandfoundation/algokit-client-generator": "^4.0.0", - "dotenv": "^16.0.3", - "prettier": "^2.8.4", - "ts-node-dev": "^2.0.0", - "typescript": "^4.9.5" - } -} diff --git a/examples/generators/starter_python_smart_contract_typescript/poetry.toml b/examples/generators/starter_python_smart_contract_typescript/poetry.toml deleted file mode 100644 index 5fcef8c..0000000 --- a/examples/generators/starter_python_smart_contract_typescript/poetry.toml +++ /dev/null @@ -1,3 +0,0 @@ -[virtualenvs] -in-project = true -prefer-active-python = true diff --git a/examples/generators/starter_python_smart_contract_typescript/pyproject.toml b/examples/generators/starter_python_smart_contract_typescript/pyproject.toml deleted file mode 100644 index a4e8c74..0000000 --- a/examples/generators/starter_python_smart_contract_typescript/pyproject.toml +++ /dev/null @@ -1,21 +0,0 @@ -[tool.poetry] -name = "starter_python_smart_contract_typescript" -version = "0.1.0" -description = "Algorand smart contracts" -authors = ["None "] -readme = "README.md" - -[tool.poetry.dependencies] -python = "^3.12" -algokit-utils = "^2.4.0" -python-dotenv = "^1.0.0" -algorand-python = "^2.0.0" -algorand-python-testing = "^0.4.0" - -[tool.poetry.group.dev.dependencies] -puyapy = "*" - -[build-system] -requires = ["poetry-core"] -build-backend = "poetry.core.masonry.api" - diff --git a/examples/generators/starter_python_smart_contract_typescript/smart_contracts/__init__.py b/examples/generators/starter_python_smart_contract_typescript/smart_contracts/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/examples/generators/starter_python_smart_contract_typescript/smart_contracts/__main__.py b/examples/generators/starter_python_smart_contract_typescript/smart_contracts/__main__.py deleted file mode 100644 index 62fadcd..0000000 --- a/examples/generators/starter_python_smart_contract_typescript/smart_contracts/__main__.py +++ /dev/null @@ -1,42 +0,0 @@ -import logging -import sys -from pathlib import Path - -from dotenv import load_dotenv - -from smart_contracts._helpers.build import build -from smart_contracts._helpers.config import contracts - -logging.basicConfig( - level=logging.DEBUG, format="%(asctime)s %(levelname)-10s: %(message)s" -) -logger = logging.getLogger(__name__) -logger.info("Loading .env") -# For manual script execution (bypassing `algokit project deploy`) with a custom .env, -# modify `load_dotenv()` accordingly. For example, `load_dotenv('.env.localnet')`. -load_dotenv() -root_path = Path(__file__).parent - - -def main(action: str, contract_name: str | None = None) -> None: - artifact_path = root_path / "artifacts" - - # Filter contracts if a specific contract name is provided - filtered_contracts = [ - c for c in contracts if contract_name is None or c.name == contract_name - ] - - match action: - case "build": - for contract in filtered_contracts: - logger.info(f"Building app at {contract.path}") - build(artifact_path / contract.name, contract.path) - - -if __name__ == "__main__": - if len(sys.argv) > 2: - main(sys.argv[1], sys.argv[2]) - elif len(sys.argv) > 1: - main(sys.argv[1]) - else: - main("build") diff --git a/examples/generators/starter_python_smart_contract_typescript/smart_contracts/_helpers/__init__.py b/examples/generators/starter_python_smart_contract_typescript/smart_contracts/_helpers/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/examples/generators/starter_python_smart_contract_typescript/smart_contracts/_helpers/build.py b/examples/generators/starter_python_smart_contract_typescript/smart_contracts/_helpers/build.py deleted file mode 100644 index 37ceb1f..0000000 --- a/examples/generators/starter_python_smart_contract_typescript/smart_contracts/_helpers/build.py +++ /dev/null @@ -1,76 +0,0 @@ -import logging -import subprocess -from pathlib import Path -from shutil import rmtree - -logger = logging.getLogger(__name__) -deployment_extension = "ts" - - -def _get_output_path(output_dir: Path, deployment_extension: str) -> Path: - return output_dir / Path( - "{contract_name}" - + ("_client" if deployment_extension == "py" else "Client") - + f".{deployment_extension}" - ) - - -def build(output_dir: Path, contract_path: Path) -> Path: - output_dir = output_dir.resolve() - if output_dir.exists(): - rmtree(output_dir) - output_dir.mkdir(exist_ok=True, parents=True) - logger.info(f"Exporting {contract_path} to {output_dir}") - - build_result = subprocess.run( - [ - "algokit", - "--no-color", - "compile", - "python", - contract_path.absolute(), - f"--out-dir={output_dir}", - "--output-arc32", - "--output-source-map", - ], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - text=True, - ) - if build_result.returncode: - raise Exception(f"Could not build contract:\n{build_result.stdout}") - - app_spec_file_names = [file.name for file in output_dir.glob("*.arc32.json")] - app_spec_file_name = None - for app_spec_file_name in app_spec_file_names: - if app_spec_file_name is None: - logger.warning( - "No '*.arc32.json' file found (likely a logic signature being compiled). Skipping client generation." - ) - continue - print(app_spec_file_name) - generate_result = subprocess.run( - [ - "algokit", - "generate", - "client", - output_dir, - "--output", - _get_output_path(output_dir, deployment_extension), - ], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - text=True, - ) - if generate_result.returncode: - if "No such command" in generate_result.stdout: - raise Exception( - "Could not generate typed client, requires AlgoKit 2.0.0 or " - "later. Please update AlgoKit" - ) - else: - raise Exception( - f"Could not generate typed client:\n{generate_result.stdout}" - ) - - return output_dir / app_spec_file_name if app_spec_file_name else output_dir diff --git a/examples/generators/starter_python_smart_contract_typescript/smart_contracts/_helpers/config.py b/examples/generators/starter_python_smart_contract_typescript/smart_contracts/_helpers/config.py deleted file mode 100644 index 8f3ca93..0000000 --- a/examples/generators/starter_python_smart_contract_typescript/smart_contracts/_helpers/config.py +++ /dev/null @@ -1,61 +0,0 @@ -import dataclasses -import importlib -from collections.abc import Callable -from pathlib import Path - -from algokit_utils import Account, ApplicationSpecification -from algosdk.v2client.algod import AlgodClient -from algosdk.v2client.indexer import IndexerClient - - -@dataclasses.dataclass -class SmartContract: - path: Path - name: str - deploy: ( - Callable[[AlgodClient, IndexerClient, ApplicationSpecification, Account], None] - | None - ) = None - - -def import_contract(folder: Path) -> Path: - """Imports the contract from a folder if it exists.""" - contract_path = folder / "contract.py" - if contract_path.exists(): - return contract_path - else: - raise Exception(f"Contract not found in {folder}") - - -def import_deploy_if_exists( - folder: Path, -) -> ( - Callable[[AlgodClient, IndexerClient, ApplicationSpecification, Account], None] - | None -): - """Imports the deploy function from a folder if it exists.""" - try: - deploy_module = importlib.import_module( - f"{folder.parent.name}.{folder.name}.deploy_config" - ) - return deploy_module.deploy # type: ignore - except ImportError: - return None - - -def has_contract_file(directory: Path) -> bool: - """Checks whether the directory contains contract.py file.""" - return (directory / "contract.py").exists() - - -# define contracts to build and/or deploy -base_dir = Path("smart_contracts") -contracts = [ - SmartContract( - path=import_contract(folder), - name=folder.name, - deploy=import_deploy_if_exists(folder), - ) - for folder in base_dir.iterdir() - if folder.is_dir() and has_contract_file(folder) -] diff --git a/examples/generators/starter_python_smart_contract_typescript/smart_contracts/cool_contract/contract.py b/examples/generators/starter_python_smart_contract_typescript/smart_contracts/cool_contract/contract.py deleted file mode 100644 index 271ad93..0000000 --- a/examples/generators/starter_python_smart_contract_typescript/smart_contracts/cool_contract/contract.py +++ /dev/null @@ -1,9 +0,0 @@ -# pyright: reportMissingModuleSource=false -from algopy import ARC4Contract, String -from algopy.arc4 import abimethod - - -class CoolContract(ARC4Contract): - @abimethod() - def hello(self, name: String) -> String: - return "Hello, " + name diff --git a/examples/generators/starter_python_smart_contract_typescript/smart_contracts/cool_contract/deploy-config.ts b/examples/generators/starter_python_smart_contract_typescript/smart_contracts/cool_contract/deploy-config.ts deleted file mode 100644 index d629083..0000000 --- a/examples/generators/starter_python_smart_contract_typescript/smart_contracts/cool_contract/deploy-config.ts +++ /dev/null @@ -1,33 +0,0 @@ -import * as algokit from '@algorandfoundation/algokit-utils' -import { CoolContractFactory } from '../artifacts/cool_contract/CoolContractClient' - -// Below is a showcase of various deployment options you can use in TypeScript Client -export async function deploy() { - console.log('=== Deploying CoolContract ===') - - const algorand = algokit.AlgorandClient.fromEnvironment() - const deployer = await algorand.account.fromEnvironment('DEPLOYER') - - const factory = algorand.client.getTypedAppFactory(CoolContractFactory, { - defaultSender: deployer.addr, - }) - - const { appClient, result } = await factory.deploy({ onUpdate: 'append', onSchemaBreak: 'append' }) - - // If app was just created fund the app account - if (['create', 'replace'].includes(result.operationPerformed)) { - await algorand.send.payment({ - amount: (1).algo(), - sender: deployer.addr, - receiver: app.appAddress, - }) - } - - const method = 'hello' - const response = await appClient.send.hello({ - args: { name: 'world' }, - }) - console.log( - `Called ${method} on ${appClient.appClient.appName} (${appClient.appClient.appId}) with name = world, received: ${response.return}`, - ) -} diff --git a/examples/generators/starter_python_smart_contract_typescript/smart_contracts/hello_world/contract.py b/examples/generators/starter_python_smart_contract_typescript/smart_contracts/hello_world/contract.py deleted file mode 100644 index 8a8d12b..0000000 --- a/examples/generators/starter_python_smart_contract_typescript/smart_contracts/hello_world/contract.py +++ /dev/null @@ -1,8 +0,0 @@ -from algopy import ARC4Contract, String -from algopy.arc4 import abimethod - - -class HelloWorld(ARC4Contract): - @abimethod() - def hello(self, name: String) -> String: - return "Hello, " + name diff --git a/examples/generators/starter_python_smart_contract_typescript/smart_contracts/index.ts b/examples/generators/starter_python_smart_contract_typescript/smart_contracts/index.ts deleted file mode 100644 index 623ca2b..0000000 --- a/examples/generators/starter_python_smart_contract_typescript/smart_contracts/index.ts +++ /dev/null @@ -1,62 +0,0 @@ -import * as fs from 'fs' -import * as path from 'path' -import { consoleLogger } from '@algorandfoundation/algokit-utils/types/logging' -import * as algokit from '@algorandfoundation/algokit-utils' -// import { registerDebugEventHandlers } from '@algorandfoundation/algokit-utils-debug' // Uncomment to enable persisting artifacts required by AlgoKit AVM Debugger - -// Uncomment the debug and traceAll options to enable auto generation of AVM Debugger compliant sourceMap and simulation trace file. -// 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 - -algokit.Config.configure({ - logger: consoleLogger, - // debug: true, - // traceAll: true, -}) -// registerDebugEventHandlers() // Uncomment to enable persisting artifacts required by AlgoKit AVM Debugger - -// base directory -const baseDir = path.resolve(__dirname) - -// function to validate and dynamically import a module -async function importDeployerIfExists(dir: string) { - const deployerPath = path.resolve(dir, 'deploy-config') - if (fs.existsSync(deployerPath + '.ts') || fs.existsSync(deployerPath + '.js')) { - const deployer = await import(deployerPath) - return { ...deployer, name: path.basename(dir) } - } - return null -} - -// get a list of all deployers from the subdirectories -async function getDeployers() { - const directories = fs - .readdirSync(baseDir, { withFileTypes: true }) - .filter((dirent) => dirent.isDirectory()) - .map((dirent) => path.resolve(baseDir, dirent.name)) - - const deployers = await Promise.all(directories.map(importDeployerIfExists)) - return deployers.filter((deployer) => deployer !== null) // Filter out null values -} - -// execute all the deployers -(async () => { - const contractName = process.argv.length > 2 ? process.argv[2] : undefined - const contractDeployers = await getDeployers() - - const filteredDeployers = contractName - ? contractDeployers.filter(deployer => deployer.name === contractName) - : contractDeployers - - if (contractName && filteredDeployers.length === 0) { - console.warn(`No deployer found for contract name: ${contractName}`) - return - } - - for (const deployer of filteredDeployers) { - try { - await deployer.deploy() - } catch (e) { - console.error(`Error deploying ${deployer.name}:`, e) - } - } -})() diff --git a/examples/production_python/.algokit.toml b/examples/production/.algokit.toml similarity index 100% rename from examples/production_python/.algokit.toml rename to examples/production/.algokit.toml diff --git a/examples/generators/production_python_smart_contract_python/.editorconfig b/examples/production/.editorconfig similarity index 100% rename from examples/generators/production_python_smart_contract_python/.editorconfig rename to examples/production/.editorconfig diff --git a/examples/generators/production_python_smart_contract_python/.gitattributes b/examples/production/.gitattributes similarity index 100% rename from examples/generators/production_python_smart_contract_python/.gitattributes rename to examples/production/.gitattributes diff --git a/examples/production_python/.github/workflows/production-python-cd.yaml b/examples/production/.github/workflows/production-python-cd.yaml similarity index 100% rename from examples/production_python/.github/workflows/production-python-cd.yaml rename to examples/production/.github/workflows/production-python-cd.yaml diff --git a/examples/production_python/.github/workflows/production-python-ci.yaml b/examples/production/.github/workflows/production-python-ci.yaml similarity index 100% rename from examples/production_python/.github/workflows/production-python-ci.yaml rename to examples/production/.github/workflows/production-python-ci.yaml diff --git a/examples/generators/production_python_smart_contract_python/.gitignore b/examples/production/.gitignore similarity index 100% rename from examples/generators/production_python_smart_contract_python/.gitignore rename to examples/production/.gitignore diff --git a/examples/production_python/.idea/runConfigurations/Build_Beaker_application.xml b/examples/production/.idea/runConfigurations/Build_Beaker_application.xml similarity index 100% rename from examples/production_python/.idea/runConfigurations/Build_Beaker_application.xml rename to examples/production/.idea/runConfigurations/Build_Beaker_application.xml diff --git a/examples/production_python/.idea/runConfigurations/Build_Beaker_application____LocalNet.xml b/examples/production/.idea/runConfigurations/Build_Beaker_application____LocalNet.xml similarity index 100% rename from examples/production_python/.idea/runConfigurations/Build_Beaker_application____LocalNet.xml rename to examples/production/.idea/runConfigurations/Build_Beaker_application____LocalNet.xml diff --git a/examples/production_python/.idea/runConfigurations/Build___Deploy_Beaker_application.xml b/examples/production/.idea/runConfigurations/Build___Deploy_Beaker_application.xml similarity index 100% rename from examples/production_python/.idea/runConfigurations/Build___Deploy_Beaker_application.xml rename to examples/production/.idea/runConfigurations/Build___Deploy_Beaker_application.xml diff --git a/examples/production_python/.idea/runConfigurations/Deploy_Built_Beaker_application.xml b/examples/production/.idea/runConfigurations/Deploy_Built_Beaker_application.xml similarity index 100% rename from examples/production_python/.idea/runConfigurations/Deploy_Built_Beaker_application.xml rename to examples/production/.idea/runConfigurations/Deploy_Built_Beaker_application.xml diff --git a/examples/generators/production_python_smart_contract_python/.idea/runConfigurations/Reset_AlgoKit_LocalNet.xml b/examples/production/.idea/runConfigurations/Reset_AlgoKit_LocalNet.xml similarity index 100% rename from examples/generators/production_python_smart_contract_python/.idea/runConfigurations/Reset_AlgoKit_LocalNet.xml rename to examples/production/.idea/runConfigurations/Reset_AlgoKit_LocalNet.xml diff --git a/examples/generators/production_python_smart_contract_python/.idea/runConfigurations/Start_AlgoKit_LocalNet.xml b/examples/production/.idea/runConfigurations/Start_AlgoKit_LocalNet.xml similarity index 100% rename from examples/generators/production_python_smart_contract_python/.idea/runConfigurations/Start_AlgoKit_LocalNet.xml rename to examples/production/.idea/runConfigurations/Start_AlgoKit_LocalNet.xml diff --git a/examples/generators/production_python_smart_contract_python/.idea/runConfigurations/Stop_AlgoKit_LocalNet.xml b/examples/production/.idea/runConfigurations/Stop_AlgoKit_LocalNet.xml similarity index 100% rename from examples/generators/production_python_smart_contract_python/.idea/runConfigurations/Stop_AlgoKit_LocalNet.xml rename to examples/production/.idea/runConfigurations/Stop_AlgoKit_LocalNet.xml diff --git a/examples/generators/production_python_smart_contract_python/.pre-commit-config.yaml b/examples/production/.pre-commit-config.yaml similarity index 100% rename from examples/generators/production_python_smart_contract_python/.pre-commit-config.yaml rename to examples/production/.pre-commit-config.yaml diff --git a/examples/generators/production_python_smart_contract_python/.tours/getting-started-with-your-algokit-project.tour b/examples/production/.tours/getting-started-with-your-algokit-project.tour similarity index 100% rename from examples/generators/production_python_smart_contract_python/.tours/getting-started-with-your-algokit-project.tour rename to examples/production/.tours/getting-started-with-your-algokit-project.tour diff --git a/examples/generators/production_python_smart_contract_python/.vscode/extensions.json b/examples/production/.vscode/extensions.json similarity index 100% rename from examples/generators/production_python_smart_contract_python/.vscode/extensions.json rename to examples/production/.vscode/extensions.json diff --git a/examples/generators/production_python_smart_contract_python/.vscode/launch.json b/examples/production/.vscode/launch.json similarity index 100% rename from examples/generators/production_python_smart_contract_python/.vscode/launch.json rename to examples/production/.vscode/launch.json diff --git a/examples/generators/production_python_smart_contract_python/.vscode/settings.json b/examples/production/.vscode/settings.json similarity index 100% rename from examples/generators/production_python_smart_contract_python/.vscode/settings.json rename to examples/production/.vscode/settings.json diff --git a/examples/generators/production_python_smart_contract_python/.vscode/tasks.json b/examples/production/.vscode/tasks.json similarity index 100% rename from examples/generators/production_python_smart_contract_python/.vscode/tasks.json rename to examples/production/.vscode/tasks.json diff --git a/examples/production_python/README.md b/examples/production/README.md similarity index 100% rename from examples/production_python/README.md rename to examples/production/README.md diff --git a/examples/generators/production_python_smart_contract_python/poetry.toml b/examples/production/poetry.toml similarity index 100% rename from examples/generators/production_python_smart_contract_python/poetry.toml rename to examples/production/poetry.toml diff --git a/examples/production_python/pyproject.toml b/examples/production/pyproject.toml similarity index 100% rename from examples/production_python/pyproject.toml rename to examples/production/pyproject.toml diff --git a/examples/generators/production_python_smart_contract_python/smart_contracts/__init__.py b/examples/production/smart_contracts/__init__.py similarity index 100% rename from examples/generators/production_python_smart_contract_python/smart_contracts/__init__.py rename to examples/production/smart_contracts/__init__.py diff --git a/examples/generators/production_python_smart_contract_python/smart_contracts/__main__.py b/examples/production/smart_contracts/__main__.py similarity index 100% rename from examples/generators/production_python_smart_contract_python/smart_contracts/__main__.py rename to examples/production/smart_contracts/__main__.py diff --git a/examples/generators/production_python_smart_contract_python/smart_contracts/_helpers/__init__.py b/examples/production/smart_contracts/_helpers/__init__.py similarity index 100% rename from examples/generators/production_python_smart_contract_python/smart_contracts/_helpers/__init__.py rename to examples/production/smart_contracts/_helpers/__init__.py diff --git a/examples/generators/production_python_smart_contract_python/smart_contracts/_helpers/build.py b/examples/production/smart_contracts/_helpers/build.py similarity index 100% rename from examples/generators/production_python_smart_contract_python/smart_contracts/_helpers/build.py rename to examples/production/smart_contracts/_helpers/build.py diff --git a/examples/generators/production_python_smart_contract_python/smart_contracts/_helpers/config.py b/examples/production/smart_contracts/_helpers/config.py similarity index 100% rename from examples/generators/production_python_smart_contract_python/smart_contracts/_helpers/config.py rename to examples/production/smart_contracts/_helpers/config.py diff --git a/examples/generators/production_python_smart_contract_python/smart_contracts/_helpers/deploy.py b/examples/production/smart_contracts/_helpers/deploy.py similarity index 100% rename from examples/generators/production_python_smart_contract_python/smart_contracts/_helpers/deploy.py rename to examples/production/smart_contracts/_helpers/deploy.py diff --git a/examples/generators/production_python_smart_contract_python/smart_contracts/hello_world/contract.py b/examples/production/smart_contracts/hello_world/contract.py similarity index 100% rename from examples/generators/production_python_smart_contract_python/smart_contracts/hello_world/contract.py rename to examples/production/smart_contracts/hello_world/contract.py diff --git a/examples/generators/production_python_smart_contract_python/smart_contracts/hello_world/deploy_config.py b/examples/production/smart_contracts/hello_world/deploy_config.py similarity index 100% rename from examples/generators/production_python_smart_contract_python/smart_contracts/hello_world/deploy_config.py rename to examples/production/smart_contracts/hello_world/deploy_config.py diff --git a/examples/generators/production_python_smart_contract_python/tests/__init__.py b/examples/production/tests/__init__.py similarity index 100% rename from examples/generators/production_python_smart_contract_python/tests/__init__.py rename to examples/production/tests/__init__.py diff --git a/examples/generators/production_python_smart_contract_python/tests/conftest.py b/examples/production/tests/conftest.py similarity index 100% rename from examples/generators/production_python_smart_contract_python/tests/conftest.py rename to examples/production/tests/conftest.py diff --git a/examples/generators/production_python_smart_contract_python/tests/hello_world_client_test.py b/examples/production/tests/hello_world_client_test.py similarity index 100% rename from examples/generators/production_python_smart_contract_python/tests/hello_world_client_test.py rename to examples/production/tests/hello_world_client_test.py diff --git a/examples/generators/production_python_smart_contract_python/tests/hello_world_test.py b/examples/production/tests/hello_world_test.py similarity index 100% rename from examples/generators/production_python_smart_contract_python/tests/hello_world_test.py rename to examples/production/tests/hello_world_test.py diff --git a/examples/production_python/.editorconfig b/examples/production_python/.editorconfig deleted file mode 100644 index e2fda34..0000000 --- a/examples/production_python/.editorconfig +++ /dev/null @@ -1,10 +0,0 @@ -root=true - -[*] -indent_style = space -indent_size = 2 -end_of_line = lf -insert_final_newline = true - -[*.py] -indent_size = 4 diff --git a/examples/production_python/.gitattributes b/examples/production_python/.gitattributes deleted file mode 100644 index 6313b56..0000000 --- a/examples/production_python/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -* text=auto eol=lf diff --git a/examples/production_python/.gitignore b/examples/production_python/.gitignore deleted file mode 100644 index 070829c..0000000 --- a/examples/production_python/.gitignore +++ /dev/null @@ -1,180 +0,0 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.py,cover -.hypothesis/ -.pytest_cache/ -cover/ -coverage/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -.pybuilder/ -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -# For a library or package, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# .python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# poetry -# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control -#poetry.lock - -# pdm -# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. -#pdm.lock -# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it -# in version control. -# https://pdm.fming.dev/#use-with-ide -.pdm.toml - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -.env.* -!.env.*.template -!.env.template -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# pytype static type analyzer -.pytype/ - -# Ruff (linter) -.ruff_cache/ - -# Cython debug symbols -cython_debug/ - -# PyCharm -.idea -!.idea/ -.idea/* -!.idea/runConfigurations/ - -# macOS -.DS_Store - -# Received approval test files -*.received.* - -# NPM -node_modules - -# AlgoKit -debug_traces/ -.algokit/static-analysis/ # Replace with .algokit/static-analysis/tealer/ to enable snapshot checks in CI -.algokit/sources diff --git a/examples/production_python/.idea/runConfigurations/Reset_AlgoKit_LocalNet.xml b/examples/production_python/.idea/runConfigurations/Reset_AlgoKit_LocalNet.xml deleted file mode 100644 index 7f1236a..0000000 --- a/examples/production_python/.idea/runConfigurations/Reset_AlgoKit_LocalNet.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - diff --git a/examples/production_python/.idea/runConfigurations/Start_AlgoKit_LocalNet.xml b/examples/production_python/.idea/runConfigurations/Start_AlgoKit_LocalNet.xml deleted file mode 100644 index f699a7a..0000000 --- a/examples/production_python/.idea/runConfigurations/Start_AlgoKit_LocalNet.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - diff --git a/examples/production_python/.pre-commit-config.yaml b/examples/production_python/.pre-commit-config.yaml deleted file mode 100644 index e5c820b..0000000 --- a/examples/production_python/.pre-commit-config.yaml +++ /dev/null @@ -1,49 +0,0 @@ -repos: - - repo: local - hooks: - - - id: black - name: black - description: "Black: The uncompromising Python code formatter" - entry: poetry run black - language: system - minimum_pre_commit_version: 2.9.2 - require_serial: true - types_or: [ python, pyi ] - - - - id: ruff - name: ruff - description: "Run 'ruff' for extremely fast Python linting" - entry: poetry run ruff - language: system - types: [ python ] - args: [ "check", "--fix" ] - require_serial: false - additional_dependencies: [ ] - minimum_pre_commit_version: '0' - files: '^(smart_contracts|tests)/' - - - - id: mypy - name: mypy - description: '`mypy` will check Python types for correctness' - entry: poetry run mypy - language: system - types_or: [ python, pyi ] - require_serial: true - additional_dependencies: [ ] - minimum_pre_commit_version: '2.9.2' - files: '^(smart_contracts|tests)/' - - # # Uncomment to enable TEAL static analysis using Tealer package - # - id: tealer - # name: tealer - # description: "Run AlgoKit `Tealer` for TEAL static analysis" - # entry: algokit - # language: system - # args: [project, run, "audit-teal"] - # require_serial: false - # additional_dependencies: [] - # minimum_pre_commit_version: "0" - # files: '^.*\.teal$' diff --git a/examples/production_python/.tours/getting-started-with-your-algokit-project.tour b/examples/production_python/.tours/getting-started-with-your-algokit-project.tour deleted file mode 100644 index 48867d6..0000000 --- a/examples/production_python/.tours/getting-started-with-your-algokit-project.tour +++ /dev/null @@ -1,56 +0,0 @@ -{ - "$schema": "https://aka.ms/codetour-schema", - "title": "Getting Started with Your AlgoKit Project", - "steps": [ - { - "file": "README.md", - "description": "Welcome to your brand new AlgoKit template-based project. In this tour, we will guide you through the main features and capabilities included in the template.", - "line": 3 - }, - { - "file": "README.md", - "description": "Start by ensuring you have followed the setup of pre-requisites.", - "line": 9 - }, - { - "file": ".algokit.toml", - "description": "This is the main configuration file used by algokit-cli to manage the project. The default template includes a starter 'Hello World' contract that is deployed via the `algokit-utils` package (either `ts` or `py`, depending on your choice). To create a new smart contract, you can use the [`algokit generate`](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/generate.md) command and invoke a pre-bundled generator template by running `algokit generate smart-contract` (see how it is defined in the `.algokit.toml`, you can create your own generators if needed). This action will create a new folder in the `smart_contracts` directory, named after your project. Each folder contains a `contract.py` file, which is the entry point for your contract implementation, and `deploy_config.py` | `deployConfig.ts` files (depending on the language chosen for the template), that perform the deployment of the contract. Additionally you can define custom commands to run (similar to `npm` scripts), see definitions under `[project]` section in `.algokit.toml`.", - "line": 1 - }, - { - "file": "smart_contracts/hello_world/deploy_config.py", - "description": "The default deployment scripts invoke a sample method on the starter contract that demonstrates how to interact with your deployed Algorand on-chain applications using the [`AlgoKit Typed Clients`](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/generate.md#1-typed-clients) feature. The invocation if deploy is aliased in `.algokit.toml` file, allowing simple deployments via `algokit project deploy` command.", - "line": 32 - }, - { - "file": "tests/hello_world_test.py", - "description": "If you opted to include unit tests, the default tests provided demonstrate an example of mocking, setting up fixtures, and testing smart contract calls on an AlgoKit typed client.", - "line": 36 - }, - { - "file": ".env.localnet.template", - "description": "Environment files are a crucial mechanism that allows you to set up the [`algokit deploy`](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/deploy.md) feature to simplify deploying your contracts in CI/CD environments (please note we still recommend careful evaluation when it comes to deployment to MainNet). Clone the file and remove the `.template` suffix to apply the changes to deployment scripts and launch configurations. The network prefix `localnet|testnet|mainnet` is primarily optimized for `algokit deploy`. The order of loading the variables is `.env.{network}` < `.env`.", - "line": 2 - }, - { - "file": ".vscode/launch.json", - "description": "Refer to the pre-bundled Visual Studio launch configurations, offering various options on how to execute the build and deployment of your smart contracts. Alternatively execute `algokit project run` to see list of available custom commands.", - "line": 5 - }, - { - "file": ".vscode/extensions.json", - "description": "We highly recommend installing the recommended extensions to get the most out of this template starter project in your VSCode IDE.", - "line": 3 - }, - { - "file": "smart_contracts/__main__.py", - "description": "Uncomment the following lines to enable complementary utilities that will generate artifacts required for the [AlgoKit AVM Debugger](https://github.com/algorandfoundation/algokit-avm-vscode-debugger) VSCode plugin available on the [VSCode Extension Marketplace](https://marketplace.visualstudio.com/items?itemName=algorandfoundation.algokit-avm-vscode-debugger). A new folder will be automatically created in the `.algokit` directory with source maps of all TEAL contracts in this workspace, as well as traces that will appear in a folder at the root of the workspace. You can then use the traces as entry points to trigger the debug extension. Make sure to have the `.algokit.toml` file available at the root of the workspace.", - "line": 15 - }, - { - "file": "smart_contracts/_helpers/__init__.py", - "description": "This folder contains helper scripts for contract management. These automate tasks like compiling, generating clients, and deploying. Usually, you won't need to edit these files, but advanced users can expand them for custom needs.", - "line": 1 - } - ] -} diff --git a/examples/production_python/.vscode/extensions.json b/examples/production_python/.vscode/extensions.json deleted file mode 100644 index 1d2e7cf..0000000 --- a/examples/production_python/.vscode/extensions.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "recommendations": [ - "ms-python.python", - "charliermarsh.ruff", - "matangover.mypy", - "ms-python.black-formatter", - "tamasfe.even-better-toml", - "editorconfig.editorconfig", - "vsls-contrib.codetour", - "algorandfoundation.algokit-avm-vscode-debugger" - ] -} diff --git a/examples/production_python/.vscode/launch.json b/examples/production_python/.vscode/launch.json deleted file mode 100644 index dbaea6e..0000000 --- a/examples/production_python/.vscode/launch.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Build & Deploy contracts", - "type": "python", - "request": "launch", - "module": "smart_contracts", - "cwd": "${workspaceFolder}", - "preLaunchTask": "Start AlgoKit LocalNet", - "env": { - "ALGOD_TOKEN": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "ALGOD_SERVER": "http://localhost", - "ALGOD_PORT": "4001", - "INDEXER_TOKEN": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "INDEXER_SERVER": "http://localhost", - "INDEXER_PORT": "8980" - } - }, - { - "name": "Deploy contracts", - "type": "python", - "request": "launch", - "module": "smart_contracts", - "args": ["deploy"], - "cwd": "${workspaceFolder}", - "env": { - "ALGOD_TOKEN": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "ALGOD_SERVER": "http://localhost", - "ALGOD_PORT": "4001", - "INDEXER_TOKEN": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "INDEXER_SERVER": "http://localhost", - "INDEXER_PORT": "8980" - } - }, - { - "name": "Build contracts", - "type": "python", - "request": "launch", - "module": "smart_contracts", - "args": ["build"], - "cwd": "${workspaceFolder}" - }, - { - "type": "avm", - "request": "launch", - "name": "Debug TEAL via AlgoKit AVM Debugger", - "simulateTraceFile": "${workspaceFolder}/${command:PickSimulateTraceFile}", - "stopOnEntry": true - } - ] -} diff --git a/examples/production_python/.vscode/settings.json b/examples/production_python/.vscode/settings.json deleted file mode 100644 index 2130dbb..0000000 --- a/examples/production_python/.vscode/settings.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - // General - see also /.editorconfig - "editor.formatOnSave": true, - "files.exclude": { - "**/.git": true, - "**/.DS_Store": true, - "**/Thumbs.db": true, - ".mypy_cache": true, - ".pytest_cache": true, - ".ruff_cache": true, - "**/__pycache__": true, - ".idea": true - }, - - // Python - "python.analysis.extraPaths": ["${workspaceFolder}/smart_contracts"], - "python.analysis.diagnosticSeverityOverrides": { - "reportMissingModuleSource": "none" - }, - "python.defaultInterpreterPath": "${workspaceFolder}/.venv", - "[python]": { - "editor.codeActionsOnSave": { - "source.fixAll": "explicit", - // Prevent default import sorting from running; Ruff will sort imports for us anyway - "source.organizeImports": "never" - }, - "editor.defaultFormatter": "ms-python.black-formatter", - }, - "black-formatter.args": ["--config=pyproject.toml"], - "python.testing.pytestEnabled": true, - "ruff.enable": true, - "ruff.lint.run": "onSave", - "ruff.lint.args": ["--config=pyproject.toml"], - "ruff.importStrategy": "fromEnvironment", - "ruff.fixAll": true, //lint and fix all files in workspace - "ruff.organizeImports": true, //organize imports on save - "ruff.codeAction.disableRuleComment": { - "enable": true - }, - "ruff.codeAction.fixViolation": { - "enable": true - }, - "python.analysis.typeCheckingMode": "off", - "mypy.configFile": "pyproject.toml", - // set to empty array to use config from project - "mypy.targets": [], - "mypy.runUsingActiveInterpreter": true, - - // On Windows, if execution policy is set to Signed (default) then it won't be able to activate the venv - // so instead let's set it to RemoteSigned for VS Code terminal - "terminal.integrated.shellArgs.windows": ["-ExecutionPolicy", "RemoteSigned"], -} diff --git a/examples/production_python/.vscode/tasks.json b/examples/production_python/.vscode/tasks.json deleted file mode 100644 index eb1e767..0000000 --- a/examples/production_python/.vscode/tasks.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "label": "Build contracts", - "command": "${workspaceFolder}/.venv/bin/python", - "windows": { - "command": "${workspaceFolder}/.venv/Scripts/python.exe" - }, - "args": ["-m", "smart_contracts", "build"], - "options": { - "cwd": "${workspaceFolder}" - }, - "group": { - "kind": "build", - "isDefault": true - }, - "problemMatcher": [] - }, - { - "label": "Build contracts (+ LocalNet)", - "command": "${workspaceFolder}/.venv/bin/python", - "windows": { - "command": "${workspaceFolder}/.venv/Scripts/python.exe" - }, - "args": ["-m", "smart_contracts", "build"], - "options": { - "cwd": "${workspaceFolder}" - }, - "dependsOn": "Start AlgoKit LocalNet", - "problemMatcher": [] - }, - { - "label": "Start AlgoKit LocalNet", - "command": "algokit", - "args": ["localnet", "start"], - "type": "shell", - "options": { - "cwd": "${workspaceFolder}" - }, - "problemMatcher": [] - }, - { - "label": "Stop AlgoKit LocalNet", - "command": "algokit", - "args": ["localnet", "stop"], - "type": "shell", - "options": { - "cwd": "${workspaceFolder}" - }, - "problemMatcher": [] - }, - { - "label": "Reset AlgoKit LocalNet", - "command": "algokit", - "args": ["localnet", "reset"], - "type": "shell", - "options": { - "cwd": "${workspaceFolder}" - }, - "problemMatcher": [] - }, - { - "label": "Analyze TEAL contracts with AlgoKit Tealer integration", - "command": "algokit", - "args": [ - "task", - "analyze", - "${workspaceFolder}/.algokit", - "--recursive", - "--force" - ], - "options": { - "cwd": "${workspaceFolder}" - }, - "problemMatcher": [] - } - ] -} diff --git a/examples/production_python/poetry.toml b/examples/production_python/poetry.toml deleted file mode 100644 index 5fcef8c..0000000 --- a/examples/production_python/poetry.toml +++ /dev/null @@ -1,3 +0,0 @@ -[virtualenvs] -in-project = true -prefer-active-python = true diff --git a/examples/production_python/smart_contracts/__init__.py b/examples/production_python/smart_contracts/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/examples/production_python/smart_contracts/__main__.py b/examples/production_python/smart_contracts/__main__.py deleted file mode 100644 index 9c691ba..0000000 --- a/examples/production_python/smart_contracts/__main__.py +++ /dev/null @@ -1,72 +0,0 @@ -import logging -import sys -from pathlib import Path - -from dotenv import load_dotenv - -from smart_contracts._helpers.build import build -from smart_contracts._helpers.config import contracts -from smart_contracts._helpers.deploy import deploy - -# Uncomment the following lines to enable auto generation of AVM Debugger compliant sourcemap and simulation trace file. -# 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 -# from algokit_utils.config import config -# config.configure(debug=True, trace_all=True) -logging.basicConfig( - level=logging.DEBUG, format="%(asctime)s %(levelname)-10s: %(message)s" -) -logger = logging.getLogger(__name__) -logger.info("Loading .env") -# For manual script execution (bypassing `algokit project deploy`) with a custom .env, -# modify `load_dotenv()` accordingly. For example, `load_dotenv('.env.localnet')`. -load_dotenv() -root_path = Path(__file__).parent - - -def main(action: str, contract_name: str | None = None) -> None: - artifact_path = root_path / "artifacts" - - # Filter contracts if a specific contract name is provided - filtered_contracts = [ - c for c in contracts if contract_name is None or c.name == contract_name - ] - - match action: - case "build": - for contract in filtered_contracts: - logger.info(f"Building app at {contract.path}") - build(artifact_path / contract.name, contract.path) - case "deploy": - for contract in filtered_contracts: - output_dir = artifact_path / contract.name - app_spec_file_name = next( - ( - file.name - for file in output_dir.iterdir() - if file.is_file() and file.suffixes == [".arc32", ".json"] - ), - None, - ) - if app_spec_file_name is None: - raise Exception("Could not deploy app, .arc32.json file not found") - app_spec_path = output_dir / app_spec_file_name - if contract.deploy: - logger.info(f"Deploying app {contract.name}") - deploy(app_spec_path, contract.deploy) - case "all": - for contract in filtered_contracts: - logger.info(f"Building app at {contract.path}") - app_spec_path = build(artifact_path / contract.name, contract.path) - if contract.deploy: - logger.info(f"Deploying {contract.path.name}") - deploy(app_spec_path, contract.deploy) - - -if __name__ == "__main__": - if len(sys.argv) > 2: - main(sys.argv[1], sys.argv[2]) - elif len(sys.argv) > 1: - main(sys.argv[1]) - else: - main("all") diff --git a/examples/production_python/smart_contracts/_helpers/__init__.py b/examples/production_python/smart_contracts/_helpers/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/examples/production_python/smart_contracts/_helpers/build.py b/examples/production_python/smart_contracts/_helpers/build.py deleted file mode 100644 index 3461154..0000000 --- a/examples/production_python/smart_contracts/_helpers/build.py +++ /dev/null @@ -1,76 +0,0 @@ -import logging -import subprocess -from pathlib import Path -from shutil import rmtree - -logger = logging.getLogger(__name__) -deployment_extension = "py" - - -def _get_output_path(output_dir: Path, deployment_extension: str) -> Path: - return output_dir / Path( - "{contract_name}" - + ("_client" if deployment_extension == "py" else "Client") - + f".{deployment_extension}" - ) - - -def build(output_dir: Path, contract_path: Path) -> Path: - output_dir = output_dir.resolve() - if output_dir.exists(): - rmtree(output_dir) - output_dir.mkdir(exist_ok=True, parents=True) - logger.info(f"Exporting {contract_path} to {output_dir}") - - build_result = subprocess.run( - [ - "algokit", - "--no-color", - "compile", - "python", - contract_path.absolute(), - f"--out-dir={output_dir}", - "--output-arc32", - "--output-source-map", - ], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - text=True, - ) - if build_result.returncode: - raise Exception(f"Could not build contract:\n{build_result.stdout}") - - app_spec_file_names = [file.name for file in output_dir.glob("*.arc32.json")] - app_spec_file_name = None - for app_spec_file_name in app_spec_file_names: - if app_spec_file_name is None: - logger.warning( - "No '*.arc32.json' file found (likely a logic signature being compiled). Skipping client generation." - ) - continue - print(app_spec_file_name) - generate_result = subprocess.run( - [ - "algokit", - "generate", - "client", - output_dir, - "--output", - _get_output_path(output_dir, deployment_extension), - ], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - text=True, - ) - if generate_result.returncode: - if "No such command" in generate_result.stdout: - raise Exception( - "Could not generate typed client, requires AlgoKit 2.0.0 or " - "later. Please update AlgoKit" - ) - else: - raise Exception( - f"Could not generate typed client:\n{generate_result.stdout}" - ) - - return output_dir / app_spec_file_name if app_spec_file_name else output_dir diff --git a/examples/production_python/smart_contracts/_helpers/config.py b/examples/production_python/smart_contracts/_helpers/config.py deleted file mode 100644 index 8f3ca93..0000000 --- a/examples/production_python/smart_contracts/_helpers/config.py +++ /dev/null @@ -1,61 +0,0 @@ -import dataclasses -import importlib -from collections.abc import Callable -from pathlib import Path - -from algokit_utils import Account, ApplicationSpecification -from algosdk.v2client.algod import AlgodClient -from algosdk.v2client.indexer import IndexerClient - - -@dataclasses.dataclass -class SmartContract: - path: Path - name: str - deploy: ( - Callable[[AlgodClient, IndexerClient, ApplicationSpecification, Account], None] - | None - ) = None - - -def import_contract(folder: Path) -> Path: - """Imports the contract from a folder if it exists.""" - contract_path = folder / "contract.py" - if contract_path.exists(): - return contract_path - else: - raise Exception(f"Contract not found in {folder}") - - -def import_deploy_if_exists( - folder: Path, -) -> ( - Callable[[AlgodClient, IndexerClient, ApplicationSpecification, Account], None] - | None -): - """Imports the deploy function from a folder if it exists.""" - try: - deploy_module = importlib.import_module( - f"{folder.parent.name}.{folder.name}.deploy_config" - ) - return deploy_module.deploy # type: ignore - except ImportError: - return None - - -def has_contract_file(directory: Path) -> bool: - """Checks whether the directory contains contract.py file.""" - return (directory / "contract.py").exists() - - -# define contracts to build and/or deploy -base_dir = Path("smart_contracts") -contracts = [ - SmartContract( - path=import_contract(folder), - name=folder.name, - deploy=import_deploy_if_exists(folder), - ) - for folder in base_dir.iterdir() - if folder.is_dir() and has_contract_file(folder) -] diff --git a/examples/production_python/smart_contracts/_helpers/deploy.py b/examples/production_python/smart_contracts/_helpers/deploy.py deleted file mode 100644 index 10185a9..0000000 --- a/examples/production_python/smart_contracts/_helpers/deploy.py +++ /dev/null @@ -1,53 +0,0 @@ -# mypy: disable-error-code="no-untyped-call, misc" - - -import logging -from collections.abc import Callable -from pathlib import Path - -from algokit_utils import ( - Account, - ApplicationSpecification, - EnsureBalanceParameters, - ensure_funded, - get_account, - get_algod_client, - get_indexer_client, -) -from algosdk.util import algos_to_microalgos -from algosdk.v2client.algod import AlgodClient -from algosdk.v2client.indexer import IndexerClient - -logger = logging.getLogger(__name__) - - -def deploy( - app_spec_path: Path, - deploy_callback: Callable[ - [AlgodClient, IndexerClient, ApplicationSpecification, Account], None - ], - deployer_initial_funds: int = 2, -) -> None: - # get clients - # by default client configuration is loaded from environment variables - algod_client = get_algod_client() - indexer_client = get_indexer_client() - - # get app spec - app_spec = ApplicationSpecification.from_json(app_spec_path.read_text()) - - # get deployer account by name - deployer = get_account(algod_client, "DEPLOYER", fund_with_algos=0) - - minimum_funds_micro_algos = algos_to_microalgos(deployer_initial_funds) - ensure_funded( - algod_client, - EnsureBalanceParameters( - account_to_fund=deployer, - min_spending_balance_micro_algos=minimum_funds_micro_algos, - min_funding_increment_micro_algos=minimum_funds_micro_algos, - ), - ) - - # use provided callback to deploy the app - deploy_callback(algod_client, indexer_client, app_spec, deployer) diff --git a/examples/production_python/smart_contracts/hello_world/contract.py b/examples/production_python/smart_contracts/hello_world/contract.py deleted file mode 100644 index 8a8d12b..0000000 --- a/examples/production_python/smart_contracts/hello_world/contract.py +++ /dev/null @@ -1,8 +0,0 @@ -from algopy import ARC4Contract, String -from algopy.arc4 import abimethod - - -class HelloWorld(ARC4Contract): - @abimethod() - def hello(self, name: String) -> String: - return "Hello, " + name diff --git a/examples/production_python/smart_contracts/hello_world/deploy_config.py b/examples/production_python/smart_contracts/hello_world/deploy_config.py deleted file mode 100644 index 36dda16..0000000 --- a/examples/production_python/smart_contracts/hello_world/deploy_config.py +++ /dev/null @@ -1,36 +0,0 @@ -import logging - -import algokit_utils -from algosdk.v2client.algod import AlgodClient -from algosdk.v2client.indexer import IndexerClient - -logger = logging.getLogger(__name__) - - -# define deployment behaviour based on supplied app spec -def deploy( - algod_client: AlgodClient, - indexer_client: IndexerClient, - app_spec: algokit_utils.ApplicationSpecification, - deployer: algokit_utils.Account, -) -> None: - from smart_contracts.artifacts.hello_world.hello_world_client import ( - HelloWorldClient, - ) - - app_client = HelloWorldClient( - algod_client, - creator=deployer, - indexer_client=indexer_client, - ) - - app_client.deploy( - on_schema_break=algokit_utils.OnSchemaBreak.AppendApp, - on_update=algokit_utils.OnUpdate.AppendApp, - ) - name = "world" - response = app_client.hello(name=name) - logger.info( - f"Called hello on {app_spec.contract.name} ({app_client.app_id}) " - f"with name={name}, received: {response.return_value}" - ) diff --git a/examples/production_python/tests/__init__.py b/examples/production_python/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/examples/production_python/tests/conftest.py b/examples/production_python/tests/conftest.py deleted file mode 100644 index aec2485..0000000 --- a/examples/production_python/tests/conftest.py +++ /dev/null @@ -1,26 +0,0 @@ -import pytest -from algokit_utils import ( - get_algod_client, - get_default_localnet_config, - get_indexer_client, -) -from algosdk.v2client.algod import AlgodClient -from algosdk.v2client.indexer import IndexerClient - -# Uncomment if you want to load network specific or generic .env file -# @pytest.fixture(autouse=True, scope="session") -# def environment_fixture() -> None: -# env_path = Path(__file__).parent.parent / ".env" -# load_dotenv(env_path) - - -@pytest.fixture(scope="session") -def algod_client() -> AlgodClient: - # by default we are using localnet algod - client = get_algod_client(get_default_localnet_config("algod")) - return client - - -@pytest.fixture(scope="session") -def indexer_client() -> IndexerClient: - return get_indexer_client(get_default_localnet_config("indexer")) diff --git a/examples/production_python/tests/hello_world_client_test.py b/examples/production_python/tests/hello_world_client_test.py deleted file mode 100644 index 1c8ebff..0000000 --- a/examples/production_python/tests/hello_world_client_test.py +++ /dev/null @@ -1,48 +0,0 @@ -import algokit_utils -import pytest -from algokit_utils import get_localnet_default_account -from algokit_utils.config import config -from algosdk.v2client.algod import AlgodClient -from algosdk.v2client.indexer import IndexerClient - -from smart_contracts.artifacts.hello_world.hello_world_client import HelloWorldClient - - -@pytest.fixture(scope="session") -def hello_world_client( - algod_client: AlgodClient, indexer_client: IndexerClient -) -> HelloWorldClient: - config.configure( - debug=True, - # trace_all=True, - ) - - client = HelloWorldClient( - algod_client, - creator=get_localnet_default_account(algod_client), - indexer_client=indexer_client, - ) - - client.deploy( - on_schema_break=algokit_utils.OnSchemaBreak.AppendApp, - on_update=algokit_utils.OnUpdate.AppendApp, - ) - return client - - -def test_says_hello(hello_world_client: HelloWorldClient) -> None: - result = hello_world_client.hello(name="World") - - assert result.return_value == "Hello, World" - - -def test_simulate_says_hello_with_correct_budget_consumed( - hello_world_client: HelloWorldClient, algod_client: AlgodClient -) -> None: - result = ( - hello_world_client.compose().hello(name="World").hello(name="Jane").simulate() - ) - - assert result.abi_results[0].return_value == "Hello, World" - assert result.abi_results[1].return_value == "Hello, Jane" - assert result.simulate_response["txn-groups"][0]["app-budget-consumed"] < 100 diff --git a/examples/production_python/tests/hello_world_test.py b/examples/production_python/tests/hello_world_test.py deleted file mode 100644 index b2d41ee..0000000 --- a/examples/production_python/tests/hello_world_test.py +++ /dev/null @@ -1,24 +0,0 @@ -from collections.abc import Iterator - -import pytest -from algopy_testing import AlgopyTestContext, algopy_testing_context - -from smart_contracts.hello_world.contract import HelloWorld - - -@pytest.fixture() -def context() -> Iterator[AlgopyTestContext]: - with algopy_testing_context() as ctx: - yield ctx - - -def test_hello(context: AlgopyTestContext) -> None: - # Arrange - dummy_input = context.any.string(length=10) - contract = HelloWorld() - - # Act - output = contract.hello(dummy_input) - - # Assert - assert output == f"Hello, {dummy_input}" diff --git a/examples/starter_python/.algokit.toml b/examples/starter/.algokit.toml similarity index 100% rename from examples/starter_python/.algokit.toml rename to examples/starter/.algokit.toml diff --git a/examples/generators/production_python_smart_contract_typescript/.editorconfig b/examples/starter/.editorconfig similarity index 100% rename from examples/generators/production_python_smart_contract_typescript/.editorconfig rename to examples/starter/.editorconfig diff --git a/examples/generators/production_python_smart_contract_typescript/.gitattributes b/examples/starter/.gitattributes similarity index 100% rename from examples/generators/production_python_smart_contract_typescript/.gitattributes rename to examples/starter/.gitattributes diff --git a/examples/generators/production_python_smart_contract_typescript/.gitignore b/examples/starter/.gitignore similarity index 100% rename from examples/generators/production_python_smart_contract_typescript/.gitignore rename to examples/starter/.gitignore diff --git a/examples/generators/starter_python_smart_contract_python/.tours/getting-started-with-your-algokit-project.tour b/examples/starter/.tours/getting-started-with-your-algokit-project.tour similarity index 100% rename from examples/generators/starter_python_smart_contract_python/.tours/getting-started-with-your-algokit-project.tour rename to examples/starter/.tours/getting-started-with-your-algokit-project.tour diff --git a/examples/generators/starter_python_smart_contract_python/.vscode/extensions.json b/examples/starter/.vscode/extensions.json similarity index 100% rename from examples/generators/starter_python_smart_contract_python/.vscode/extensions.json rename to examples/starter/.vscode/extensions.json diff --git a/examples/generators/starter_python_smart_contract_python/.vscode/launch.json b/examples/starter/.vscode/launch.json similarity index 100% rename from examples/generators/starter_python_smart_contract_python/.vscode/launch.json rename to examples/starter/.vscode/launch.json diff --git a/examples/generators/starter_python_smart_contract_python/.vscode/settings.json b/examples/starter/.vscode/settings.json similarity index 100% rename from examples/generators/starter_python_smart_contract_python/.vscode/settings.json rename to examples/starter/.vscode/settings.json diff --git a/examples/generators/production_python_smart_contract_typescript/.vscode/tasks.json b/examples/starter/.vscode/tasks.json similarity index 100% rename from examples/generators/production_python_smart_contract_typescript/.vscode/tasks.json rename to examples/starter/.vscode/tasks.json diff --git a/examples/starter_python/README.md b/examples/starter/README.md similarity index 100% rename from examples/starter_python/README.md rename to examples/starter/README.md diff --git a/examples/generators/production_python_smart_contract_typescript/poetry.toml b/examples/starter/poetry.toml similarity index 100% rename from examples/generators/production_python_smart_contract_typescript/poetry.toml rename to examples/starter/poetry.toml diff --git a/examples/starter_python/pyproject.toml b/examples/starter/pyproject.toml similarity index 100% rename from examples/starter_python/pyproject.toml rename to examples/starter/pyproject.toml diff --git a/examples/generators/production_python_smart_contract_typescript/smart_contracts/__init__.py b/examples/starter/smart_contracts/__init__.py similarity index 100% rename from examples/generators/production_python_smart_contract_typescript/smart_contracts/__init__.py rename to examples/starter/smart_contracts/__init__.py diff --git a/examples/generators/starter_python_smart_contract_python/smart_contracts/__main__.py b/examples/starter/smart_contracts/__main__.py similarity index 100% rename from examples/generators/starter_python_smart_contract_python/smart_contracts/__main__.py rename to examples/starter/smart_contracts/__main__.py diff --git a/examples/generators/production_python_smart_contract_typescript/smart_contracts/_helpers/__init__.py b/examples/starter/smart_contracts/_helpers/__init__.py similarity index 100% rename from examples/generators/production_python_smart_contract_typescript/smart_contracts/_helpers/__init__.py rename to examples/starter/smart_contracts/_helpers/__init__.py diff --git a/examples/generators/starter_python_smart_contract_python/smart_contracts/_helpers/build.py b/examples/starter/smart_contracts/_helpers/build.py similarity index 100% rename from examples/generators/starter_python_smart_contract_python/smart_contracts/_helpers/build.py rename to examples/starter/smart_contracts/_helpers/build.py diff --git a/examples/generators/production_python_smart_contract_typescript/smart_contracts/_helpers/config.py b/examples/starter/smart_contracts/_helpers/config.py similarity index 100% rename from examples/generators/production_python_smart_contract_typescript/smart_contracts/_helpers/config.py rename to examples/starter/smart_contracts/_helpers/config.py diff --git a/examples/generators/starter_python_smart_contract_python/smart_contracts/_helpers/deploy.py b/examples/starter/smart_contracts/_helpers/deploy.py similarity index 100% rename from examples/generators/starter_python_smart_contract_python/smart_contracts/_helpers/deploy.py rename to examples/starter/smart_contracts/_helpers/deploy.py diff --git a/examples/generators/production_python_smart_contract_typescript/smart_contracts/hello_world/contract.py b/examples/starter/smart_contracts/hello_world/contract.py similarity index 100% rename from examples/generators/production_python_smart_contract_typescript/smart_contracts/hello_world/contract.py rename to examples/starter/smart_contracts/hello_world/contract.py diff --git a/examples/generators/starter_python_smart_contract_python/smart_contracts/hello_world/deploy_config.py b/examples/starter/smart_contracts/hello_world/deploy_config.py similarity index 100% rename from examples/generators/starter_python_smart_contract_python/smart_contracts/hello_world/deploy_config.py rename to examples/starter/smart_contracts/hello_world/deploy_config.py diff --git a/examples/starter_python/.editorconfig b/examples/starter_python/.editorconfig deleted file mode 100644 index e2fda34..0000000 --- a/examples/starter_python/.editorconfig +++ /dev/null @@ -1,10 +0,0 @@ -root=true - -[*] -indent_style = space -indent_size = 2 -end_of_line = lf -insert_final_newline = true - -[*.py] -indent_size = 4 diff --git a/examples/starter_python/.gitattributes b/examples/starter_python/.gitattributes deleted file mode 100644 index 6313b56..0000000 --- a/examples/starter_python/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -* text=auto eol=lf diff --git a/examples/starter_python/.gitignore b/examples/starter_python/.gitignore deleted file mode 100644 index 070829c..0000000 --- a/examples/starter_python/.gitignore +++ /dev/null @@ -1,180 +0,0 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.py,cover -.hypothesis/ -.pytest_cache/ -cover/ -coverage/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -.pybuilder/ -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -# For a library or package, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# .python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# poetry -# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control -#poetry.lock - -# pdm -# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. -#pdm.lock -# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it -# in version control. -# https://pdm.fming.dev/#use-with-ide -.pdm.toml - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -.env.* -!.env.*.template -!.env.template -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# pytype static type analyzer -.pytype/ - -# Ruff (linter) -.ruff_cache/ - -# Cython debug symbols -cython_debug/ - -# PyCharm -.idea -!.idea/ -.idea/* -!.idea/runConfigurations/ - -# macOS -.DS_Store - -# Received approval test files -*.received.* - -# NPM -node_modules - -# AlgoKit -debug_traces/ -.algokit/static-analysis/ # Replace with .algokit/static-analysis/tealer/ to enable snapshot checks in CI -.algokit/sources diff --git a/examples/starter_python/.tours/getting-started-with-your-algokit-project.tour b/examples/starter_python/.tours/getting-started-with-your-algokit-project.tour deleted file mode 100644 index 728218d..0000000 --- a/examples/starter_python/.tours/getting-started-with-your-algokit-project.tour +++ /dev/null @@ -1,51 +0,0 @@ -{ - "$schema": "https://aka.ms/codetour-schema", - "title": "Getting Started with Your AlgoKit Project", - "steps": [ - { - "file": "README.md", - "description": "Welcome to your brand new AlgoKit template-based project. In this tour, we will guide you through the main features and capabilities included in the template.", - "line": 3 - }, - { - "file": "README.md", - "description": "Start by ensuring you have followed the setup of pre-requisites.", - "line": 9 - }, - { - "file": ".algokit.toml", - "description": "This is the main configuration file used by algokit-cli to manage the project. The default template includes a starter 'Hello World' contract that is deployed via the `algokit-utils` package (either `ts` or `py`, depending on your choice). To create a new smart contract, you can use the [`algokit generate`](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/generate.md) command and invoke a pre-bundled generator template by running `algokit generate smart-contract` (see how it is defined in the `.algokit.toml`, you can create your own generators if needed). This action will create a new folder in the `smart_contracts` directory, named after your project. Each folder contains a `contract.py` file, which is the entry point for your contract implementation, and `deploy_config.py` | `deployConfig.ts` files (depending on the language chosen for the template), that perform the deployment of the contract. Additionally you can define custom commands to run (similar to `npm` scripts), see definitions under `[project]` section in `.algokit.toml`.", - "line": 1 - }, - { - "file": "smart_contracts/hello_world/deploy_config.py", - "description": "The default deployment scripts invoke a sample method on the starter contract that demonstrates how to interact with your deployed Algorand on-chain applications using the [`AlgoKit Typed Clients`](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/generate.md#1-typed-clients) feature. The invocation if deploy is aliased in `.algokit.toml` file, allowing simple deployments via `algokit project deploy` command.", - "line": 32 - }, - { - "file": ".env.localnet.template", - "description": "Environment files are a crucial mechanism that allows you to set up the [`algokit deploy`](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/deploy.md) feature to simplify deploying your contracts in CI/CD environments (please note we still recommend careful evaluation when it comes to deployment to MainNet). Clone the file and remove the `.template` suffix to apply the changes to deployment scripts and launch configurations. The network prefix `localnet|testnet|mainnet` is primarily optimized for `algokit deploy`. The order of loading the variables is `.env.{network}` < `.env`.", - "line": 2 - }, - { - "file": ".vscode/launch.json", - "description": "Refer to the pre-bundled Visual Studio launch configurations, offering various options on how to execute the build and deployment of your smart contracts. Alternatively execute `algokit project run` to see list of available custom commands.", - "line": 5 - }, - { - "file": ".vscode/extensions.json", - "description": "We highly recommend installing the recommended extensions to get the most out of this template starter project in your VSCode IDE.", - "line": 3 - }, - { - "file": "smart_contracts/__main__.py", - "description": "Uncomment the following lines to enable complementary utilities that will generate artifacts required for the [AlgoKit AVM Debugger](https://github.com/algorandfoundation/algokit-avm-vscode-debugger) VSCode plugin available on the [VSCode Extension Marketplace](https://marketplace.visualstudio.com/items?itemName=algorandfoundation.algokit-avm-vscode-debugger). A new folder will be automatically created in the `.algokit` directory with source maps of all TEAL contracts in this workspace, as well as traces that will appear in a folder at the root of the workspace. You can then use the traces as entry points to trigger the debug extension. Make sure to have the `.algokit.toml` file available at the root of the workspace.", - "line": 15 - }, - { - "file": "smart_contracts/_helpers/__init__.py", - "description": "This folder contains helper scripts for contract management. These automate tasks like compiling, generating clients, and deploying. Usually, you won't need to edit these files, but advanced users can expand them for custom needs.", - "line": 1 - } - ] -} diff --git a/examples/starter_python/.vscode/extensions.json b/examples/starter_python/.vscode/extensions.json deleted file mode 100644 index e16b76b..0000000 --- a/examples/starter_python/.vscode/extensions.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "recommendations": [ - "ms-python.python", - "tamasfe.even-better-toml", - "editorconfig.editorconfig", - "vsls-contrib.codetour", - "algorandfoundation.algokit-avm-vscode-debugger" - ] -} diff --git a/examples/starter_python/.vscode/launch.json b/examples/starter_python/.vscode/launch.json deleted file mode 100644 index dbaea6e..0000000 --- a/examples/starter_python/.vscode/launch.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Build & Deploy contracts", - "type": "python", - "request": "launch", - "module": "smart_contracts", - "cwd": "${workspaceFolder}", - "preLaunchTask": "Start AlgoKit LocalNet", - "env": { - "ALGOD_TOKEN": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "ALGOD_SERVER": "http://localhost", - "ALGOD_PORT": "4001", - "INDEXER_TOKEN": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "INDEXER_SERVER": "http://localhost", - "INDEXER_PORT": "8980" - } - }, - { - "name": "Deploy contracts", - "type": "python", - "request": "launch", - "module": "smart_contracts", - "args": ["deploy"], - "cwd": "${workspaceFolder}", - "env": { - "ALGOD_TOKEN": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "ALGOD_SERVER": "http://localhost", - "ALGOD_PORT": "4001", - "INDEXER_TOKEN": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "INDEXER_SERVER": "http://localhost", - "INDEXER_PORT": "8980" - } - }, - { - "name": "Build contracts", - "type": "python", - "request": "launch", - "module": "smart_contracts", - "args": ["build"], - "cwd": "${workspaceFolder}" - }, - { - "type": "avm", - "request": "launch", - "name": "Debug TEAL via AlgoKit AVM Debugger", - "simulateTraceFile": "${workspaceFolder}/${command:PickSimulateTraceFile}", - "stopOnEntry": true - } - ] -} diff --git a/examples/starter_python/.vscode/settings.json b/examples/starter_python/.vscode/settings.json deleted file mode 100644 index 687f930..0000000 --- a/examples/starter_python/.vscode/settings.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - // General - see also /.editorconfig - "editor.formatOnSave": true, - "files.exclude": { - "**/.git": true, - "**/.DS_Store": true, - "**/Thumbs.db": true, - ".mypy_cache": true, - ".pytest_cache": true, - ".ruff_cache": true, - "**/__pycache__": true, - ".idea": true - }, - - // Python - "python.analysis.extraPaths": ["${workspaceFolder}/smart_contracts"], - "python.analysis.diagnosticSeverityOverrides": { - "reportMissingModuleSource": "none" - }, - "python.defaultInterpreterPath": "${workspaceFolder}/.venv", - "[python]": { - "editor.codeActionsOnSave": { - "source.fixAll": "explicit", - // Prevent default import sorting from running; Ruff will sort imports for us anyway - "source.organizeImports": "never" - }, - "editor.defaultFormatter": null, - }, - - // On Windows, if execution policy is set to Signed (default) then it won't be able to activate the venv - // so instead let's set it to RemoteSigned for VS Code terminal - "terminal.integrated.shellArgs.windows": ["-ExecutionPolicy", "RemoteSigned"], -} diff --git a/examples/starter_python/poetry.toml b/examples/starter_python/poetry.toml deleted file mode 100644 index 5fcef8c..0000000 --- a/examples/starter_python/poetry.toml +++ /dev/null @@ -1,3 +0,0 @@ -[virtualenvs] -in-project = true -prefer-active-python = true diff --git a/examples/starter_python/smart_contracts/__init__.py b/examples/starter_python/smart_contracts/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/examples/starter_python/smart_contracts/__main__.py b/examples/starter_python/smart_contracts/__main__.py deleted file mode 100644 index 9c691ba..0000000 --- a/examples/starter_python/smart_contracts/__main__.py +++ /dev/null @@ -1,72 +0,0 @@ -import logging -import sys -from pathlib import Path - -from dotenv import load_dotenv - -from smart_contracts._helpers.build import build -from smart_contracts._helpers.config import contracts -from smart_contracts._helpers.deploy import deploy - -# Uncomment the following lines to enable auto generation of AVM Debugger compliant sourcemap and simulation trace file. -# 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 -# from algokit_utils.config import config -# config.configure(debug=True, trace_all=True) -logging.basicConfig( - level=logging.DEBUG, format="%(asctime)s %(levelname)-10s: %(message)s" -) -logger = logging.getLogger(__name__) -logger.info("Loading .env") -# For manual script execution (bypassing `algokit project deploy`) with a custom .env, -# modify `load_dotenv()` accordingly. For example, `load_dotenv('.env.localnet')`. -load_dotenv() -root_path = Path(__file__).parent - - -def main(action: str, contract_name: str | None = None) -> None: - artifact_path = root_path / "artifacts" - - # Filter contracts if a specific contract name is provided - filtered_contracts = [ - c for c in contracts if contract_name is None or c.name == contract_name - ] - - match action: - case "build": - for contract in filtered_contracts: - logger.info(f"Building app at {contract.path}") - build(artifact_path / contract.name, contract.path) - case "deploy": - for contract in filtered_contracts: - output_dir = artifact_path / contract.name - app_spec_file_name = next( - ( - file.name - for file in output_dir.iterdir() - if file.is_file() and file.suffixes == [".arc32", ".json"] - ), - None, - ) - if app_spec_file_name is None: - raise Exception("Could not deploy app, .arc32.json file not found") - app_spec_path = output_dir / app_spec_file_name - if contract.deploy: - logger.info(f"Deploying app {contract.name}") - deploy(app_spec_path, contract.deploy) - case "all": - for contract in filtered_contracts: - logger.info(f"Building app at {contract.path}") - app_spec_path = build(artifact_path / contract.name, contract.path) - if contract.deploy: - logger.info(f"Deploying {contract.path.name}") - deploy(app_spec_path, contract.deploy) - - -if __name__ == "__main__": - if len(sys.argv) > 2: - main(sys.argv[1], sys.argv[2]) - elif len(sys.argv) > 1: - main(sys.argv[1]) - else: - main("all") diff --git a/examples/starter_python/smart_contracts/_helpers/__init__.py b/examples/starter_python/smart_contracts/_helpers/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/examples/starter_python/smart_contracts/_helpers/build.py b/examples/starter_python/smart_contracts/_helpers/build.py deleted file mode 100644 index 3461154..0000000 --- a/examples/starter_python/smart_contracts/_helpers/build.py +++ /dev/null @@ -1,76 +0,0 @@ -import logging -import subprocess -from pathlib import Path -from shutil import rmtree - -logger = logging.getLogger(__name__) -deployment_extension = "py" - - -def _get_output_path(output_dir: Path, deployment_extension: str) -> Path: - return output_dir / Path( - "{contract_name}" - + ("_client" if deployment_extension == "py" else "Client") - + f".{deployment_extension}" - ) - - -def build(output_dir: Path, contract_path: Path) -> Path: - output_dir = output_dir.resolve() - if output_dir.exists(): - rmtree(output_dir) - output_dir.mkdir(exist_ok=True, parents=True) - logger.info(f"Exporting {contract_path} to {output_dir}") - - build_result = subprocess.run( - [ - "algokit", - "--no-color", - "compile", - "python", - contract_path.absolute(), - f"--out-dir={output_dir}", - "--output-arc32", - "--output-source-map", - ], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - text=True, - ) - if build_result.returncode: - raise Exception(f"Could not build contract:\n{build_result.stdout}") - - app_spec_file_names = [file.name for file in output_dir.glob("*.arc32.json")] - app_spec_file_name = None - for app_spec_file_name in app_spec_file_names: - if app_spec_file_name is None: - logger.warning( - "No '*.arc32.json' file found (likely a logic signature being compiled). Skipping client generation." - ) - continue - print(app_spec_file_name) - generate_result = subprocess.run( - [ - "algokit", - "generate", - "client", - output_dir, - "--output", - _get_output_path(output_dir, deployment_extension), - ], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - text=True, - ) - if generate_result.returncode: - if "No such command" in generate_result.stdout: - raise Exception( - "Could not generate typed client, requires AlgoKit 2.0.0 or " - "later. Please update AlgoKit" - ) - else: - raise Exception( - f"Could not generate typed client:\n{generate_result.stdout}" - ) - - return output_dir / app_spec_file_name if app_spec_file_name else output_dir diff --git a/examples/starter_python/smart_contracts/_helpers/config.py b/examples/starter_python/smart_contracts/_helpers/config.py deleted file mode 100644 index 8f3ca93..0000000 --- a/examples/starter_python/smart_contracts/_helpers/config.py +++ /dev/null @@ -1,61 +0,0 @@ -import dataclasses -import importlib -from collections.abc import Callable -from pathlib import Path - -from algokit_utils import Account, ApplicationSpecification -from algosdk.v2client.algod import AlgodClient -from algosdk.v2client.indexer import IndexerClient - - -@dataclasses.dataclass -class SmartContract: - path: Path - name: str - deploy: ( - Callable[[AlgodClient, IndexerClient, ApplicationSpecification, Account], None] - | None - ) = None - - -def import_contract(folder: Path) -> Path: - """Imports the contract from a folder if it exists.""" - contract_path = folder / "contract.py" - if contract_path.exists(): - return contract_path - else: - raise Exception(f"Contract not found in {folder}") - - -def import_deploy_if_exists( - folder: Path, -) -> ( - Callable[[AlgodClient, IndexerClient, ApplicationSpecification, Account], None] - | None -): - """Imports the deploy function from a folder if it exists.""" - try: - deploy_module = importlib.import_module( - f"{folder.parent.name}.{folder.name}.deploy_config" - ) - return deploy_module.deploy # type: ignore - except ImportError: - return None - - -def has_contract_file(directory: Path) -> bool: - """Checks whether the directory contains contract.py file.""" - return (directory / "contract.py").exists() - - -# define contracts to build and/or deploy -base_dir = Path("smart_contracts") -contracts = [ - SmartContract( - path=import_contract(folder), - name=folder.name, - deploy=import_deploy_if_exists(folder), - ) - for folder in base_dir.iterdir() - if folder.is_dir() and has_contract_file(folder) -] diff --git a/examples/starter_python/smart_contracts/_helpers/deploy.py b/examples/starter_python/smart_contracts/_helpers/deploy.py deleted file mode 100644 index 10185a9..0000000 --- a/examples/starter_python/smart_contracts/_helpers/deploy.py +++ /dev/null @@ -1,53 +0,0 @@ -# mypy: disable-error-code="no-untyped-call, misc" - - -import logging -from collections.abc import Callable -from pathlib import Path - -from algokit_utils import ( - Account, - ApplicationSpecification, - EnsureBalanceParameters, - ensure_funded, - get_account, - get_algod_client, - get_indexer_client, -) -from algosdk.util import algos_to_microalgos -from algosdk.v2client.algod import AlgodClient -from algosdk.v2client.indexer import IndexerClient - -logger = logging.getLogger(__name__) - - -def deploy( - app_spec_path: Path, - deploy_callback: Callable[ - [AlgodClient, IndexerClient, ApplicationSpecification, Account], None - ], - deployer_initial_funds: int = 2, -) -> None: - # get clients - # by default client configuration is loaded from environment variables - algod_client = get_algod_client() - indexer_client = get_indexer_client() - - # get app spec - app_spec = ApplicationSpecification.from_json(app_spec_path.read_text()) - - # get deployer account by name - deployer = get_account(algod_client, "DEPLOYER", fund_with_algos=0) - - minimum_funds_micro_algos = algos_to_microalgos(deployer_initial_funds) - ensure_funded( - algod_client, - EnsureBalanceParameters( - account_to_fund=deployer, - min_spending_balance_micro_algos=minimum_funds_micro_algos, - min_funding_increment_micro_algos=minimum_funds_micro_algos, - ), - ) - - # use provided callback to deploy the app - deploy_callback(algod_client, indexer_client, app_spec, deployer) diff --git a/examples/starter_python/smart_contracts/hello_world/contract.py b/examples/starter_python/smart_contracts/hello_world/contract.py deleted file mode 100644 index 8a8d12b..0000000 --- a/examples/starter_python/smart_contracts/hello_world/contract.py +++ /dev/null @@ -1,8 +0,0 @@ -from algopy import ARC4Contract, String -from algopy.arc4 import abimethod - - -class HelloWorld(ARC4Contract): - @abimethod() - def hello(self, name: String) -> String: - return "Hello, " + name diff --git a/examples/starter_python/smart_contracts/hello_world/deploy_config.py b/examples/starter_python/smart_contracts/hello_world/deploy_config.py deleted file mode 100644 index 36dda16..0000000 --- a/examples/starter_python/smart_contracts/hello_world/deploy_config.py +++ /dev/null @@ -1,36 +0,0 @@ -import logging - -import algokit_utils -from algosdk.v2client.algod import AlgodClient -from algosdk.v2client.indexer import IndexerClient - -logger = logging.getLogger(__name__) - - -# define deployment behaviour based on supplied app spec -def deploy( - algod_client: AlgodClient, - indexer_client: IndexerClient, - app_spec: algokit_utils.ApplicationSpecification, - deployer: algokit_utils.Account, -) -> None: - from smart_contracts.artifacts.hello_world.hello_world_client import ( - HelloWorldClient, - ) - - app_client = HelloWorldClient( - algod_client, - creator=deployer, - indexer_client=indexer_client, - ) - - app_client.deploy( - on_schema_break=algokit_utils.OnSchemaBreak.AppendApp, - on_update=algokit_utils.OnUpdate.AppendApp, - ) - name = "world" - response = app_client.hello(name=name) - logger.info( - f"Called hello on {app_spec.contract.name} ({app_client.app_id}) " - f"with name={name}, received: {response.return_value}" - ) diff --git a/examples/generators/starter_python_smart_contract_typescript/.algokit.toml b/examples/starter_typescript_desired/.algokit.toml similarity index 97% rename from examples/generators/starter_python_smart_contract_typescript/.algokit.toml rename to examples/starter_typescript_desired/.algokit.toml index da1bb1f..4aeb85d 100644 --- a/examples/generators/starter_python_smart_contract_typescript/.algokit.toml +++ b/examples/starter_typescript_desired/.algokit.toml @@ -26,9 +26,10 @@ environment_secrets = [] [project.run] # Commands intented for use locally and in CI build = { commands = [ - 'poetry run python -m smart_contracts build', + 'npm run build', ], description = 'Build all smart contracts in the project' } lint = { commands = [ + 'npm run lint' ], description = 'Perform linting' } audit-teal = { commands = [ # 🚨 IMPORTANT 🚨: For strict TEAL validation, remove --exclude statements. The default starter contract is not for production. Ensure thorough testing and adherence to best practices in smart contract development. This is not a replacement for a professional audit. diff --git a/examples/generators/starter_python_smart_contract_typescript/.algokit/.copier-answers.yml b/examples/starter_typescript_desired/.algokit/.copier-answers.yml similarity index 100% rename from examples/generators/starter_python_smart_contract_typescript/.algokit/.copier-answers.yml rename to examples/starter_typescript_desired/.algokit/.copier-answers.yml diff --git a/examples/generators/production_python_smart_contract_python/.algokit/generators/create_contract/copier.yaml b/examples/starter_typescript_desired/.algokit/generators/create_contract/copier.yaml similarity index 100% rename from examples/generators/production_python_smart_contract_python/.algokit/generators/create_contract/copier.yaml rename to examples/starter_typescript_desired/.algokit/generators/create_contract/copier.yaml diff --git a/examples/generators/production_python_smart_contract_python/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 b/examples/starter_typescript_desired/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 similarity index 100% rename from examples/generators/production_python_smart_contract_python/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 rename to examples/starter_typescript_desired/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 diff --git a/examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/deploy-config.ts.j2 b/examples/starter_typescript_desired/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/deploy-config.ts.j2 similarity index 100% rename from examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/deploy-config.ts.j2 rename to examples/starter_typescript_desired/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/deploy-config.ts.j2 diff --git a/examples/generators/production_python_smart_contract_python/.algokit/generators/create_env_file/copier.yaml b/examples/starter_typescript_desired/.algokit/generators/create_env_file/copier.yaml similarity index 100% rename from examples/generators/production_python_smart_contract_python/.algokit/generators/create_env_file/copier.yaml rename to examples/starter_typescript_desired/.algokit/generators/create_env_file/copier.yaml diff --git a/examples/generators/production_python_smart_contract_python/.algokit/generators/create_env_file/{% if is_customnet %}.env.{{custom_network_name}}{% endif %} b/examples/starter_typescript_desired/.algokit/generators/create_env_file/{% if is_customnet %}.env.{{custom_network_name}}{% endif %} similarity index 100% rename from examples/generators/production_python_smart_contract_python/.algokit/generators/create_env_file/{% if is_customnet %}.env.{{custom_network_name}}{% endif %} rename to examples/starter_typescript_desired/.algokit/generators/create_env_file/{% if is_customnet %}.env.{{custom_network_name}}{% endif %} diff --git a/examples/generators/production_python_smart_contract_python/.algokit/generators/create_env_file/{% if is_localnet %}.env.localnet{% endif %} b/examples/starter_typescript_desired/.algokit/generators/create_env_file/{% if is_localnet %}.env.localnet{% endif %} similarity index 100% rename from examples/generators/production_python_smart_contract_python/.algokit/generators/create_env_file/{% if is_localnet %}.env.localnet{% endif %} rename to examples/starter_typescript_desired/.algokit/generators/create_env_file/{% if is_localnet %}.env.localnet{% endif %} diff --git a/examples/generators/production_python_smart_contract_python/.algokit/generators/create_env_file/{% if is_mainnet %}.env.mainnet{% endif %} b/examples/starter_typescript_desired/.algokit/generators/create_env_file/{% if is_mainnet %}.env.mainnet{% endif %} similarity index 100% rename from examples/generators/production_python_smart_contract_python/.algokit/generators/create_env_file/{% if is_mainnet %}.env.mainnet{% endif %} rename to examples/starter_typescript_desired/.algokit/generators/create_env_file/{% if is_mainnet %}.env.mainnet{% endif %} diff --git a/examples/generators/production_python_smart_contract_python/.algokit/generators/create_env_file/{% if is_testnet %}.env.testnet{% endif %} b/examples/starter_typescript_desired/.algokit/generators/create_env_file/{% if is_testnet %}.env.testnet{% endif %} similarity index 100% rename from examples/generators/production_python_smart_contract_python/.algokit/generators/create_env_file/{% if is_testnet %}.env.testnet{% endif %} rename to examples/starter_typescript_desired/.algokit/generators/create_env_file/{% if is_testnet %}.env.testnet{% endif %} diff --git a/examples/starter_typescript_desired/.algokit/static-analysis/snapshots/HelloWorld.approval.json b/examples/starter_typescript_desired/.algokit/static-analysis/snapshots/HelloWorld.approval.json new file mode 100644 index 0000000..1cb58a2 --- /dev/null +++ b/examples/starter_typescript_desired/.algokit/static-analysis/snapshots/HelloWorld.approval.json @@ -0,0 +1,466 @@ +{ + "success": false, + "error": null, + "result": [ + { + "type": "ExecutionPaths", + "count": 1, + "description": "\nCheck: \"unprotected-deletable\", Impact: High, Confidence: High\nDescription: Unprotected Deletable Applications\n\nWiki: https://github.com/crytic/tealer/wiki/Detector-Documentation#unprotected-deletable-application\n", + "check": "unprotected-deletable", + "impact": "High", + "confidence": "High", + "help": "- Avoid deletable applications.\n- Add access controls to the vulnerable method.", + "paths": [ + { + "short": "0 -> 1 -> 2 -> 4 -> 8 -> 5", + "blocks": [ + [ + "1: #pragma version 10", + "2: UNSUPPORTED #pragma typetrack false" + ], + [ + "5: main:", + "8: txn NumAppArgs", + "9: bz main_bare_routing@6" + ], + [ + "10: pushbytes 0x02bece11", + "11: txna ApplicationArgs 0", + "12: match main_hello_route@3" + ], + [ + "20: main_hello_route@3:", + "23: txn OnCompletion", + "24: !", + "25: assert", + "26: txn ApplicationID", + "27: assert", + "30: txna ApplicationArgs 1", + "31: extract 2 0", + "34: callsub hello" + ], + [ + "61: hello:", + "64: proto 1 1", + "67: pushbytes \"Hello \"", + "68: frame_dig -1", + "69: concat", + "70: retsub" + ], + [ + "35: dup", + "36: len", + "37: itob", + "38: extract 6 2", + "39: swap", + "40: concat", + "41: pushbytes 0x151f7c75", + "42: swap", + "43: concat", + "44: log", + "45: pushint 1", + "46: return" + ] + ] + } + ] + }, + { + "type": "ExecutionPaths", + "count": 1, + "description": "\nCheck: \"unprotected-updatable\", Impact: High, Confidence: High\nDescription: Unprotected Upgradable Applications\n\nWiki: https://github.com/crytic/tealer/wiki/Detector-Documentation#unprotected-updatable-application\n", + "check": "unprotected-updatable", + "impact": "High", + "confidence": "High", + "help": "- Avoid upgradable applications.\n- Add access controls to the vulnerable method.", + "paths": [ + { + "short": "0 -> 1 -> 2 -> 4 -> 8 -> 5", + "blocks": [ + [ + "1: #pragma version 10", + "2: UNSUPPORTED #pragma typetrack false" + ], + [ + "5: main:", + "8: txn NumAppArgs", + "9: bz main_bare_routing@6" + ], + [ + "10: pushbytes 0x02bece11", + "11: txna ApplicationArgs 0", + "12: match main_hello_route@3" + ], + [ + "20: main_hello_route@3:", + "23: txn OnCompletion", + "24: !", + "25: assert", + "26: txn ApplicationID", + "27: assert", + "30: txna ApplicationArgs 1", + "31: extract 2 0", + "34: callsub hello" + ], + [ + "61: hello:", + "64: proto 1 1", + "67: pushbytes \"Hello \"", + "68: frame_dig -1", + "69: concat", + "70: retsub" + ], + [ + "35: dup", + "36: len", + "37: itob", + "38: extract 6 2", + "39: swap", + "40: concat", + "41: pushbytes 0x151f7c75", + "42: swap", + "43: concat", + "44: log", + "45: pushint 1", + "46: return" + ] + ] + } + ] + }, + { + "type": "ExecutionPaths", + "count": 0, + "description": "\nCheck: \"can-close-account\", Impact: High, Confidence: High\nDescription: Missing CloseRemainderTo field Validation\n\nWiki: https://github.com/crytic/tealer/wiki/Detector-Documentation#missing-closeremainderto-field-validation\n", + "check": "can-close-account", + "impact": "High", + "confidence": "High", + "help": "Validate `CloseRemainderTo` field in the LogicSig.", + "paths": [] + }, + { + "type": "ExecutionPaths", + "count": 0, + "description": "\nCheck: \"can-close-asset\", Impact: High, Confidence: High\nDescription: Missing AssetCloseTo Field Validation\n\nWiki: https://github.com/crytic/tealer/wiki/Detector-Documentation#missing-assetcloseto-field-validation\n", + "check": "can-close-asset", + "impact": "High", + "confidence": "High", + "help": "Validate `AssetCloseTo` field in the LogicSig.", + "paths": [] + }, + { + "type": "ExecutionPaths", + "count": 1, + "description": "\nCheck: \"is-deletable\", Impact: High, Confidence: High\nDescription: Deletable Applications\n\nWiki: https://github.com/crytic/tealer/wiki/Detector-Documentation#deletable-application\n", + "check": "is-deletable", + "impact": "High", + "confidence": "High", + "help": "Do not approve `DeleteApplication` type application calls.", + "paths": [ + { + "short": "0 -> 1 -> 2 -> 4 -> 8 -> 5", + "blocks": [ + [ + "1: #pragma version 10", + "2: UNSUPPORTED #pragma typetrack false" + ], + [ + "5: main:", + "8: txn NumAppArgs", + "9: bz main_bare_routing@6" + ], + [ + "10: pushbytes 0x02bece11", + "11: txna ApplicationArgs 0", + "12: match main_hello_route@3" + ], + [ + "20: main_hello_route@3:", + "23: txn OnCompletion", + "24: !", + "25: assert", + "26: txn ApplicationID", + "27: assert", + "30: txna ApplicationArgs 1", + "31: extract 2 0", + "34: callsub hello" + ], + [ + "61: hello:", + "64: proto 1 1", + "67: pushbytes \"Hello \"", + "68: frame_dig -1", + "69: concat", + "70: retsub" + ], + [ + "35: dup", + "36: len", + "37: itob", + "38: extract 6 2", + "39: swap", + "40: concat", + "41: pushbytes 0x151f7c75", + "42: swap", + "43: concat", + "44: log", + "45: pushint 1", + "46: return" + ] + ] + } + ] + }, + { + "type": "ExecutionPaths", + "count": 1, + "description": "\nCheck: \"is-updatable\", Impact: High, Confidence: High\nDescription: Upgradable Applications\n\nWiki: https://github.com/crytic/tealer/wiki/Detector-Documentation#upgradable-application\n", + "check": "is-updatable", + "impact": "High", + "confidence": "High", + "help": "Do not approve `UpdateApplication` type application calls.", + "paths": [ + { + "short": "0 -> 1 -> 2 -> 4 -> 8 -> 5", + "blocks": [ + [ + "1: #pragma version 10", + "2: UNSUPPORTED #pragma typetrack false" + ], + [ + "5: main:", + "8: txn NumAppArgs", + "9: bz main_bare_routing@6" + ], + [ + "10: pushbytes 0x02bece11", + "11: txna ApplicationArgs 0", + "12: match main_hello_route@3" + ], + [ + "20: main_hello_route@3:", + "23: txn OnCompletion", + "24: !", + "25: assert", + "26: txn ApplicationID", + "27: assert", + "30: txna ApplicationArgs 1", + "31: extract 2 0", + "34: callsub hello" + ], + [ + "61: hello:", + "64: proto 1 1", + "67: pushbytes \"Hello \"", + "68: frame_dig -1", + "69: concat", + "70: retsub" + ], + [ + "35: dup", + "36: len", + "37: itob", + "38: extract 6 2", + "39: swap", + "40: concat", + "41: pushbytes 0x151f7c75", + "42: swap", + "43: concat", + "44: log", + "45: pushint 1", + "46: return" + ] + ] + } + ] + }, + { + "type": "ExecutionPaths", + "count": 2, + "description": "\nCheck: \"missing-fee-check\", Impact: High, Confidence: High\nDescription: Missing Fee Field Validation\n\nWiki: https://github.com/crytic/tealer/wiki/Detector-Documentation#missing-fee-field-validation\n", + "check": "missing-fee-check", + "impact": "High", + "confidence": "High", + "help": "Validate `Fee` field in the LogicSig.", + "paths": [ + { + "short": "0 -> 1 -> 2 -> 4 -> 8 -> 5", + "blocks": [ + [ + "1: #pragma version 10", + "2: UNSUPPORTED #pragma typetrack false" + ], + [ + "5: main:", + "8: txn NumAppArgs", + "9: bz main_bare_routing@6" + ], + [ + "10: pushbytes 0x02bece11", + "11: txna ApplicationArgs 0", + "12: match main_hello_route@3" + ], + [ + "20: main_hello_route@3:", + "23: txn OnCompletion", + "24: !", + "25: assert", + "26: txn ApplicationID", + "27: assert", + "30: txna ApplicationArgs 1", + "31: extract 2 0", + "34: callsub hello" + ], + [ + "61: hello:", + "64: proto 1 1", + "67: pushbytes \"Hello \"", + "68: frame_dig -1", + "69: concat", + "70: retsub" + ], + [ + "35: dup", + "36: len", + "37: itob", + "38: extract 6 2", + "39: swap", + "40: concat", + "41: pushbytes 0x151f7c75", + "42: swap", + "43: concat", + "44: log", + "45: pushint 1", + "46: return" + ] + ] + }, + { + "short": "0 -> 1 -> 6 -> 7", + "blocks": [ + [ + "1: #pragma version 10", + "2: UNSUPPORTED #pragma typetrack false" + ], + [ + "5: main:", + "8: txn NumAppArgs", + "9: bz main_bare_routing@6" + ], + [ + "48: main_bare_routing@6:", + "51: txn OnCompletion", + "52: bnz main_after_if_else@10" + ], + [ + "53: txn ApplicationID", + "54: !", + "55: assert", + "56: pushint 1", + "57: return" + ] + ] + } + ] + }, + { + "type": "ExecutionPaths", + "count": 0, + "description": "\nCheck: \"group-size-check\", Impact: High, Confidence: High\nDescription: Usage of absolute indexes without validating GroupSize\n\nWiki: https://github.com/crytic/tealer/wiki/Detector-Documentation#missing-groupsize-validation\n", + "check": "group-size-check", + "impact": "High", + "confidence": "High", + "help": "- Avoid using absolute indexes. Validate GroupSize if used.\n- Favor using ARC-4 ABI and relative indexes for group transactions.", + "paths": [] + }, + { + "type": "ExecutionPaths", + "count": 2, + "description": "\nCheck: \"rekey-to\", Impact: High, Confidence: High\nDescription: Rekeyable Logic Signatures\n\nWiki: https://github.com/crytic/tealer/wiki/Detector-Documentation#rekeyable-logicsig\n", + "check": "rekey-to", + "impact": "High", + "confidence": "High", + "help": "Validate `RekeyTo` field in the LogicSig.", + "paths": [ + { + "short": "0 -> 1 -> 2 -> 4 -> 8 -> 5", + "blocks": [ + [ + "1: #pragma version 10", + "2: UNSUPPORTED #pragma typetrack false" + ], + [ + "5: main:", + "8: txn NumAppArgs", + "9: bz main_bare_routing@6" + ], + [ + "10: pushbytes 0x02bece11", + "11: txna ApplicationArgs 0", + "12: match main_hello_route@3" + ], + [ + "20: main_hello_route@3:", + "23: txn OnCompletion", + "24: !", + "25: assert", + "26: txn ApplicationID", + "27: assert", + "30: txna ApplicationArgs 1", + "31: extract 2 0", + "34: callsub hello" + ], + [ + "61: hello:", + "64: proto 1 1", + "67: pushbytes \"Hello \"", + "68: frame_dig -1", + "69: concat", + "70: retsub" + ], + [ + "35: dup", + "36: len", + "37: itob", + "38: extract 6 2", + "39: swap", + "40: concat", + "41: pushbytes 0x151f7c75", + "42: swap", + "43: concat", + "44: log", + "45: pushint 1", + "46: return" + ] + ] + }, + { + "short": "0 -> 1 -> 6 -> 7", + "blocks": [ + [ + "1: #pragma version 10", + "2: UNSUPPORTED #pragma typetrack false" + ], + [ + "5: main:", + "8: txn NumAppArgs", + "9: bz main_bare_routing@6" + ], + [ + "48: main_bare_routing@6:", + "51: txn OnCompletion", + "52: bnz main_after_if_else@10" + ], + [ + "53: txn ApplicationID", + "54: !", + "55: assert", + "56: pushint 1", + "57: return" + ] + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/examples/starter_typescript_desired/.algokit/static-analysis/snapshots/HelloWorld.clear.json b/examples/starter_typescript_desired/.algokit/static-analysis/snapshots/HelloWorld.clear.json new file mode 100644 index 0000000..51e0326 --- /dev/null +++ b/examples/starter_typescript_desired/.algokit/static-analysis/snapshots/HelloWorld.clear.json @@ -0,0 +1,216 @@ +{ + "success": false, + "error": null, + "result": [ + { + "type": "ExecutionPaths", + "count": 1, + "description": "\nCheck: \"unprotected-deletable\", Impact: High, Confidence: High\nDescription: Unprotected Deletable Applications\n\nWiki: https://github.com/crytic/tealer/wiki/Detector-Documentation#unprotected-deletable-application\n", + "check": "unprotected-deletable", + "impact": "High", + "confidence": "High", + "help": "- Avoid deletable applications.\n- Add access controls to the vulnerable method.", + "paths": [ + { + "short": "0 -> 1", + "blocks": [ + [ + "1: #pragma version 10", + "2: UNSUPPORTED #pragma typetrack false" + ], + [ + "5: main:", + "6: pushint 1", + "7: return" + ] + ] + } + ] + }, + { + "type": "ExecutionPaths", + "count": 1, + "description": "\nCheck: \"unprotected-updatable\", Impact: High, Confidence: High\nDescription: Unprotected Upgradable Applications\n\nWiki: https://github.com/crytic/tealer/wiki/Detector-Documentation#unprotected-updatable-application\n", + "check": "unprotected-updatable", + "impact": "High", + "confidence": "High", + "help": "- Avoid upgradable applications.\n- Add access controls to the vulnerable method.", + "paths": [ + { + "short": "0 -> 1", + "blocks": [ + [ + "1: #pragma version 10", + "2: UNSUPPORTED #pragma typetrack false" + ], + [ + "5: main:", + "6: pushint 1", + "7: return" + ] + ] + } + ] + }, + { + "type": "ExecutionPaths", + "count": 1, + "description": "\nCheck: \"can-close-account\", Impact: High, Confidence: High\nDescription: Missing CloseRemainderTo field Validation\n\nWiki: https://github.com/crytic/tealer/wiki/Detector-Documentation#missing-closeremainderto-field-validation\n", + "check": "can-close-account", + "impact": "High", + "confidence": "High", + "help": "Validate `CloseRemainderTo` field in the LogicSig.", + "paths": [ + { + "short": "0 -> 1", + "blocks": [ + [ + "1: #pragma version 10", + "2: UNSUPPORTED #pragma typetrack false" + ], + [ + "5: main:", + "6: pushint 1", + "7: return" + ] + ] + } + ] + }, + { + "type": "ExecutionPaths", + "count": 1, + "description": "\nCheck: \"can-close-asset\", Impact: High, Confidence: High\nDescription: Missing AssetCloseTo Field Validation\n\nWiki: https://github.com/crytic/tealer/wiki/Detector-Documentation#missing-assetcloseto-field-validation\n", + "check": "can-close-asset", + "impact": "High", + "confidence": "High", + "help": "Validate `AssetCloseTo` field in the LogicSig.", + "paths": [ + { + "short": "0 -> 1", + "blocks": [ + [ + "1: #pragma version 10", + "2: UNSUPPORTED #pragma typetrack false" + ], + [ + "5: main:", + "6: pushint 1", + "7: return" + ] + ] + } + ] + }, + { + "type": "ExecutionPaths", + "count": 1, + "description": "\nCheck: \"is-deletable\", Impact: High, Confidence: High\nDescription: Deletable Applications\n\nWiki: https://github.com/crytic/tealer/wiki/Detector-Documentation#deletable-application\n", + "check": "is-deletable", + "impact": "High", + "confidence": "High", + "help": "Do not approve `DeleteApplication` type application calls.", + "paths": [ + { + "short": "0 -> 1", + "blocks": [ + [ + "1: #pragma version 10", + "2: UNSUPPORTED #pragma typetrack false" + ], + [ + "5: main:", + "6: pushint 1", + "7: return" + ] + ] + } + ] + }, + { + "type": "ExecutionPaths", + "count": 1, + "description": "\nCheck: \"is-updatable\", Impact: High, Confidence: High\nDescription: Upgradable Applications\n\nWiki: https://github.com/crytic/tealer/wiki/Detector-Documentation#upgradable-application\n", + "check": "is-updatable", + "impact": "High", + "confidence": "High", + "help": "Do not approve `UpdateApplication` type application calls.", + "paths": [ + { + "short": "0 -> 1", + "blocks": [ + [ + "1: #pragma version 10", + "2: UNSUPPORTED #pragma typetrack false" + ], + [ + "5: main:", + "6: pushint 1", + "7: return" + ] + ] + } + ] + }, + { + "type": "ExecutionPaths", + "count": 1, + "description": "\nCheck: \"missing-fee-check\", Impact: High, Confidence: High\nDescription: Missing Fee Field Validation\n\nWiki: https://github.com/crytic/tealer/wiki/Detector-Documentation#missing-fee-field-validation\n", + "check": "missing-fee-check", + "impact": "High", + "confidence": "High", + "help": "Validate `Fee` field in the LogicSig.", + "paths": [ + { + "short": "0 -> 1", + "blocks": [ + [ + "1: #pragma version 10", + "2: UNSUPPORTED #pragma typetrack false" + ], + [ + "5: main:", + "6: pushint 1", + "7: return" + ] + ] + } + ] + }, + { + "type": "ExecutionPaths", + "count": 0, + "description": "\nCheck: \"group-size-check\", Impact: High, Confidence: High\nDescription: Usage of absolute indexes without validating GroupSize\n\nWiki: https://github.com/crytic/tealer/wiki/Detector-Documentation#missing-groupsize-validation\n", + "check": "group-size-check", + "impact": "High", + "confidence": "High", + "help": "- Avoid using absolute indexes. Validate GroupSize if used.\n- Favor using ARC-4 ABI and relative indexes for group transactions.", + "paths": [] + }, + { + "type": "ExecutionPaths", + "count": 1, + "description": "\nCheck: \"rekey-to\", Impact: High, Confidence: High\nDescription: Rekeyable Logic Signatures\n\nWiki: https://github.com/crytic/tealer/wiki/Detector-Documentation#rekeyable-logicsig\n", + "check": "rekey-to", + "impact": "High", + "confidence": "High", + "help": "Validate `RekeyTo` field in the LogicSig.", + "paths": [ + { + "short": "0 -> 1", + "blocks": [ + [ + "1: #pragma version 10", + "2: UNSUPPORTED #pragma typetrack false" + ], + [ + "5: main:", + "6: pushint 1", + "7: return" + ] + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/examples/generators/starter_python_smart_contract_python/.editorconfig b/examples/starter_typescript_desired/.editorconfig similarity index 80% rename from examples/generators/starter_python_smart_contract_python/.editorconfig rename to examples/starter_typescript_desired/.editorconfig index e2fda34..0a71b07 100644 --- a/examples/generators/starter_python_smart_contract_python/.editorconfig +++ b/examples/starter_typescript_desired/.editorconfig @@ -5,6 +5,3 @@ indent_style = space indent_size = 2 end_of_line = lf insert_final_newline = true - -[*.py] -indent_size = 4 diff --git a/examples/generators/starter_python_smart_contract_python/.gitattributes b/examples/starter_typescript_desired/.gitattributes similarity index 100% rename from examples/generators/starter_python_smart_contract_python/.gitattributes rename to examples/starter_typescript_desired/.gitattributes diff --git a/examples/generators/starter_python_smart_contract_python/.gitignore b/examples/starter_typescript_desired/.gitignore similarity index 100% rename from examples/generators/starter_python_smart_contract_python/.gitignore rename to examples/starter_typescript_desired/.gitignore diff --git a/examples/generators/production_python_smart_contract_typescript/.npmrc b/examples/starter_typescript_desired/.npmrc similarity index 100% rename from examples/generators/production_python_smart_contract_typescript/.npmrc rename to examples/starter_typescript_desired/.npmrc diff --git a/examples/generators/production_python_smart_contract_typescript/.prettierignore b/examples/starter_typescript_desired/.prettierignore similarity index 100% rename from examples/generators/production_python_smart_contract_typescript/.prettierignore rename to examples/starter_typescript_desired/.prettierignore diff --git a/examples/generators/production_python_smart_contract_typescript/.prettierrc.js b/examples/starter_typescript_desired/.prettierrc.js similarity index 100% rename from examples/generators/production_python_smart_contract_typescript/.prettierrc.js rename to examples/starter_typescript_desired/.prettierrc.js diff --git a/examples/generators/production_python_smart_contract_typescript/.tours/getting-started-with-your-algokit-project.tour b/examples/starter_typescript_desired/.tours/getting-started-with-your-algokit-project.tour similarity index 100% rename from examples/generators/production_python_smart_contract_typescript/.tours/getting-started-with-your-algokit-project.tour rename to examples/starter_typescript_desired/.tours/getting-started-with-your-algokit-project.tour diff --git a/examples/generators/starter_python_smart_contract_typescript/.vscode/extensions.json b/examples/starter_typescript_desired/.vscode/extensions.json similarity index 75% rename from examples/generators/starter_python_smart_contract_typescript/.vscode/extensions.json rename to examples/starter_typescript_desired/.vscode/extensions.json index e5ca4ca..a3da688 100644 --- a/examples/generators/starter_python_smart_contract_typescript/.vscode/extensions.json +++ b/examples/starter_typescript_desired/.vscode/extensions.json @@ -1,10 +1,10 @@ { "recommendations": [ - "ms-python.python", "esbenp.prettier-vscode", - "tamasfe.even-better-toml", "editorconfig.editorconfig", "vsls-contrib.codetour", + "vitest.explorer", + "dbaeumer.vscode-eslint", "algorandfoundation.algokit-avm-vscode-debugger" ] } diff --git a/examples/generators/starter_python_smart_contract_typescript/.vscode/launch.json b/examples/starter_typescript_desired/.vscode/launch.json similarity index 87% rename from examples/generators/starter_python_smart_contract_typescript/.vscode/launch.json rename to examples/starter_typescript_desired/.vscode/launch.json index 6c40d26..093ebb1 100644 --- a/examples/generators/starter_python_smart_contract_typescript/.vscode/launch.json +++ b/examples/starter_typescript_desired/.vscode/launch.json @@ -40,16 +40,17 @@ }, { "name": "Build contracts", - "type": "python", "request": "launch", - "module": "smart_contracts", - "args": ["build"], - "cwd": "${workspaceFolder}" + "runtimeExecutable": "npm", + "runtimeArgs": ["run", "build"], + "cwd": "${workspaceFolder}", + "console": "integratedTerminal", + "skipFiles": ["/**", "node_modules/**"], }, { "type": "avm", "request": "launch", - "name": "Debug TEAL via AlgoKit AVM Debugger", + "name": "Debug AVM executions", "simulateTraceFile": "${workspaceFolder}/${command:PickSimulateTraceFile}", "stopOnEntry": true } diff --git a/examples/starter_typescript_desired/.vscode/settings.json b/examples/starter_typescript_desired/.vscode/settings.json new file mode 100644 index 0000000..13edad9 --- /dev/null +++ b/examples/starter_typescript_desired/.vscode/settings.json @@ -0,0 +1,18 @@ +{ + "files.eol": "\n", + "editor.formatOnSave": true, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.codeActionsOnSave": { + "source.organizeImports": "explicit" + }, + "jest.enable": false, + "files.associations": { + ".github/**/*.yml": "github-actions-workflow" + }, + "eslint.enable": true, + "eslint.validate": ["typescript"], + "eslint.options": { + "extensions": [".ts"] + }, + "eslint.workingDirectories": ["./smart_contracts"] +} diff --git a/examples/starter_python/.vscode/tasks.json b/examples/starter_typescript_desired/.vscode/tasks.json similarity index 71% rename from examples/starter_python/.vscode/tasks.json rename to examples/starter_typescript_desired/.vscode/tasks.json index eb1e767..55310ab 100644 --- a/examples/starter_python/.vscode/tasks.json +++ b/examples/starter_typescript_desired/.vscode/tasks.json @@ -3,11 +3,9 @@ "tasks": [ { "label": "Build contracts", - "command": "${workspaceFolder}/.venv/bin/python", - "windows": { - "command": "${workspaceFolder}/.venv/Scripts/python.exe" - }, - "args": ["-m", "smart_contracts", "build"], + "type": "npm", + "script": "build", + "path": "${workspaceFolder}", "options": { "cwd": "${workspaceFolder}" }, @@ -19,11 +17,9 @@ }, { "label": "Build contracts (+ LocalNet)", - "command": "${workspaceFolder}/.venv/bin/python", - "windows": { - "command": "${workspaceFolder}/.venv/Scripts/python.exe" - }, - "args": ["-m", "smart_contracts", "build"], + "type": "npm", + "script": "build", + "path": "${workspaceFolder}", "options": { "cwd": "${workspaceFolder}" }, @@ -63,13 +59,7 @@ { "label": "Analyze TEAL contracts with AlgoKit Tealer integration", "command": "algokit", - "args": [ - "task", - "analyze", - "${workspaceFolder}/.algokit", - "--recursive", - "--force" - ], + "args": ["task", "analyze", "${workspaceFolder}/.algokit", "--recursive", "--force"], "options": { "cwd": "${workspaceFolder}" }, diff --git a/examples/generators/starter_python_smart_contract_typescript/README.md b/examples/starter_typescript_desired/README.md similarity index 100% rename from examples/generators/starter_python_smart_contract_typescript/README.md rename to examples/starter_typescript_desired/README.md diff --git a/examples/starter_typescript_desired/debug-traces/20250113_111427_lr3650_1appl.trace.avm.json b/examples/starter_typescript_desired/debug-traces/20250113_111427_lr3650_1appl.trace.avm.json new file mode 100644 index 0000000..ee1a973 --- /dev/null +++ b/examples/starter_typescript_desired/debug-traces/20250113_111427_lr3650_1appl.trace.avm.json @@ -0,0 +1,310 @@ +{ + "last-round": 3650, + "txn-groups": [ + { + "txn-results": [ + { + "txn-result": { + "txn": { + "txn": { + "type": "appl", + "snd": "ICVTTWVDKV2FTBH7PDDGPXBQKHZMUAE26CYOX5MH5H6ZSZHAY3ASG4VL4A", + "lv": 4650, + "gen": "dockernet-v1", + "gh": "S5soihBjmKDkdk5Abh0oIFZsDhx4qN2Gs0p03i9pdes=", + "fee": 1000, + "fv": 3650, + "apid": 5214, + "apaa": [ + "Ar7OEQ==", + "AAV3b3JsZA==" + ] + } + }, + "logs": [ + "FR98dQALSGVsbG8gd29ybGQ=" + ] + }, + "app-budget-consumed": 30, + "exec-trace": { + "approval-program-hash": "0yY983w6C1t4ExFeUARpuqywpMkOl/kgoacuUf8k8/M=", + "approval-program-trace": [ + { + "pc": 1, + "stack-additions": [ + { + "type": 2, + "uint": 2 + } + ] + }, + { + "pc": 3, + "stack-pop-count": 1 + }, + { + "pc": 6, + "stack-additions": [ + { + "type": 1, + "bytes": "Ar7OEQ==" + } + ] + }, + { + "pc": 12, + "stack-additions": [ + { + "type": 1, + "bytes": "Ar7OEQ==" + } + ] + }, + { + "pc": 15, + "stack-pop-count": 2 + }, + { + "pc": 22, + "stack-additions": [ + { + "type": 2 + } + ] + }, + { + "pc": 24, + "stack-additions": [ + { + "type": 2, + "uint": 1 + } + ], + "stack-pop-count": 1 + }, + { + "pc": 25, + "stack-pop-count": 1 + }, + { + "pc": 26, + "stack-additions": [ + { + "type": 2, + "uint": 5214 + } + ] + }, + { + "pc": 28, + "stack-pop-count": 1 + }, + { + "pc": 29, + "stack-additions": [ + { + "type": 1, + "bytes": "AAV3b3JsZA==" + } + ] + }, + { + "pc": 32, + "stack-additions": [ + { + "type": 1, + "bytes": "d29ybGQ=" + } + ], + "stack-pop-count": 1 + }, + { + "pc": 35 + }, + { + "pc": 70 + }, + { + "pc": 73, + "stack-additions": [ + { + "type": 1, + "bytes": "SGVsbG8g" + } + ] + }, + { + "pc": 81, + "stack-additions": [ + { + "type": 1, + "bytes": "d29ybGQ=" + } + ] + }, + { + "pc": 83, + "stack-additions": [ + { + "type": 1, + "bytes": "SGVsbG8gd29ybGQ=" + } + ], + "stack-pop-count": 2 + }, + { + "pc": 84, + "stack-additions": [ + { + "type": 1, + "bytes": "SGVsbG8gd29ybGQ=" + } + ], + "stack-pop-count": 2 + }, + { + "pc": 38, + "stack-additions": [ + { + "type": 1, + "bytes": "SGVsbG8gd29ybGQ=" + }, + { + "type": 1, + "bytes": "SGVsbG8gd29ybGQ=" + } + ], + "stack-pop-count": 1 + }, + { + "pc": 39, + "stack-additions": [ + { + "type": 2, + "uint": 11 + } + ], + "stack-pop-count": 1 + }, + { + "pc": 40, + "stack-additions": [ + { + "type": 1, + "bytes": "AAAAAAAAAAs=" + } + ], + "stack-pop-count": 1 + }, + { + "pc": 41, + "stack-additions": [ + { + "type": 1, + "bytes": "AAs=" + } + ], + "stack-pop-count": 1 + }, + { + "pc": 44, + "stack-additions": [ + { + "type": 1, + "bytes": "AAs=" + }, + { + "type": 1, + "bytes": "SGVsbG8gd29ybGQ=" + } + ], + "stack-pop-count": 2 + }, + { + "pc": 45, + "stack-additions": [ + { + "type": 1, + "bytes": "AAtIZWxsbyB3b3JsZA==" + } + ], + "stack-pop-count": 2 + }, + { + "pc": 46, + "stack-additions": [ + { + "type": 1, + "bytes": "FR98dQ==" + } + ] + }, + { + "pc": 52, + "stack-additions": [ + { + "type": 1, + "bytes": "FR98dQ==" + }, + { + "type": 1, + "bytes": "AAtIZWxsbyB3b3JsZA==" + } + ], + "stack-pop-count": 2 + }, + { + "pc": 53, + "stack-additions": [ + { + "type": 1, + "bytes": "FR98dQALSGVsbG8gd29ybGQ=" + } + ], + "stack-pop-count": 2 + }, + { + "pc": 54, + "stack-pop-count": 1 + }, + { + "pc": 55, + "stack-additions": [ + { + "type": 2, + "uint": 1 + } + ] + }, + { + "pc": 57, + "stack-additions": [ + { + "type": 2, + "uint": 1 + } + ], + "stack-pop-count": 1 + } + ] + } + } + ], + "app-budget-added": 700, + "app-budget-consumed": 30 + } + ], + "version": 2, + "eval-overrides": { + "allow-empty-signatures": true, + "fix-signers": true, + "max-log-calls": 2048, + "max-log-size": 65536 + }, + "exec-trace-config": { + "enable": true, + "scratch-change": true, + "stack-change": true, + "state-change": true + } +} \ No newline at end of file diff --git a/examples/starter_typescript_desired/package.json b/examples/starter_typescript_desired/package.json new file mode 100644 index 0000000..499d056 --- /dev/null +++ b/examples/starter_typescript_desired/package.json @@ -0,0 +1,43 @@ +{ + "name": "smart_contracts", + "version": "1.0.0", + "description": "Smart contract deployer", + "main": "smart_contracts/index.ts", + "scripts": { + "build": "puya-ts build smart_contracts --output-source-map --out-dir artifacts && algokit generate client smart_contracts/artifacts --output {app_spec_dir}/{contract_name}Client.ts", + "deploy": "ts-node-dev --transpile-only --watch .env -r dotenv/config smart_contracts/index.ts", + "deploy:ci": "ts-node --transpile-only -r dotenv/config smart_contracts/index.ts", + "lint": "eslint ./src/ --ext .ts", + "lint:fix": "eslint ./src/ --ext .ts --fix", + "check-types": "tsc --noEmit", + "audit": "better-npm-audit audit", + "format": "prettier --write .", + "test": "vitest run --coverage", + "test:watch": "vitest watch" + }, + "engines": { + "node": ">=20.0", + "npm": ">=9.0" + }, + "dependencies": { + "@algorandfoundation/algorand-typescript": "^0.0.1-alpha.24" + }, + "devDependencies": { + "@algorandfoundation/algokit-client-generator": "^4.0.6", + "@algorandfoundation/algokit-utils": "^8.0.3", + "@algorandfoundation/algokit-utils-debug": "^1.0.2", + "@algorandfoundation/algorand-typescript-testing": "^1.0.0-alpha.18", + "@algorandfoundation/puya-ts": "^1.0.0-alpha.37", + "@algorandfoundation/tealscript": "0.105.5", + "@rollup/plugin-typescript": "^12.1.2", + "@tsconfig/node20": "^20.1.4", + "@vitest/coverage-v8": "^2.1.8", + "algosdk": "^3.0.0", + "better-npm-audit": "^3.11.0", + "dotenv": "^16.4.7", + "prettier": "^3.4.2", + "ts-node-dev": "^2.0.0", + "typescript": "^5.7.3", + "vitest": "^2.1.8" + } +} diff --git a/examples/starter_typescript_desired/smart_contracts/hello_world/contract.algo.ts b/examples/starter_typescript_desired/smart_contracts/hello_world/contract.algo.ts new file mode 100644 index 0000000..efd4c04 --- /dev/null +++ b/examples/starter_typescript_desired/smart_contracts/hello_world/contract.algo.ts @@ -0,0 +1,11 @@ +import { Contract } from '@algorandfoundation/algorand-typescript' + +export class HelloWorld extends Contract { + hello(name: string): string { + return `${this.getHello()} ${name}` + } + + private getHello() { + return 'Hello' + } +} diff --git a/examples/generators/production_python_smart_contract_typescript/tests/hello-world.spec.ts b/examples/starter_typescript_desired/smart_contracts/hello_world/contract.e2e.spec.ts similarity index 64% rename from examples/generators/production_python_smart_contract_typescript/tests/hello-world.spec.ts rename to examples/starter_typescript_desired/smart_contracts/hello_world/contract.e2e.spec.ts index c2ce598..f687e65 100644 --- a/examples/generators/production_python_smart_contract_typescript/tests/hello-world.spec.ts +++ b/examples/starter_typescript_desired/smart_contracts/hello_world/contract.e2e.spec.ts @@ -1,23 +1,22 @@ +import { Config } from '@algorandfoundation/algokit-utils' import { algorandFixture } from '@algorandfoundation/algokit-utils/testing' -import { HelloWorldFactory } from '../smart_contracts/artifacts/hello_world/HelloWorldClient' -import { Account, Algodv2, Indexer } from 'algosdk' -import * as algokit from '@algorandfoundation/algokit-utils' -import { TransactionSignerAccount } from '@algorandfoundation/algokit-utils/types/account' +import { Address } from 'algosdk' +import { beforeAll, beforeEach, describe, expect, test } from 'vitest' +import { HelloWorldFactory } from '../artifacts/hello_world/HelloWorldClient' describe('hello world contract', () => { const localnet = algorandFixture() beforeAll(() => { - algokit.Config.configure({ + Config.configure({ debug: true, // traceAll: true, }) }) beforeEach(localnet.beforeEach) - const deploy = async (account: Account & TransactionSignerAccount) => { + const deploy = async (account: Address) => { const factory = localnet.algorand.client.getTypedAppFactory(HelloWorldFactory, { - defaultSender: account.addr, - defaultSigner: account.signer, + defaultSender: account, }) const { appClient } = await factory.deploy({ onUpdate: 'append', onSchemaBreak: 'append' }) @@ -30,7 +29,7 @@ describe('hello world contract', () => { const result = await client.send.hello({ args: { name: 'World' } }) - expect(result.return).toBe('Hello, World') + expect(result.return).toBe('Hello World') }) test('simulate says hello with correct budget consumed', async () => { @@ -42,8 +41,8 @@ describe('hello world contract', () => { .hello({ args: { name: 'Jane' } }) .simulate() - expect(result.returns[0]).toBe('Hello, World') - expect(result.returns[1]).toBe('Hello, Jane') + expect(result.returns[0]).toBe('Hello World') + expect(result.returns[1]).toBe('Hello Jane') expect(result.simulateResponse.txnGroups[0].appBudgetConsumed).toBeLessThan(100) }) }) diff --git a/examples/starter_typescript_desired/smart_contracts/hello_world/contract.spec.ts b/examples/starter_typescript_desired/smart_contracts/hello_world/contract.spec.ts new file mode 100644 index 0000000..a7df973 --- /dev/null +++ b/examples/starter_typescript_desired/smart_contracts/hello_world/contract.spec.ts @@ -0,0 +1,14 @@ +import { TestExecutionContext } from '@algorandfoundation/algorand-typescript-testing' +import { describe, expect, it } from 'vitest' +import { HelloWorld } from './contract.algo' + +describe('HelloWorld contract', () => { + const ctx = new TestExecutionContext() + it('Logs the returned value when sayHello is called', () => { + const contract = ctx.contract.create(HelloWorld) + + const result = contract.hello('Sally') + + expect(result).toBe('Hello Sally') + }) +}) diff --git a/examples/generators/starter_python_smart_contract_typescript/smart_contracts/hello_world/deploy-config.ts b/examples/starter_typescript_desired/smart_contracts/hello_world/deploy-config.ts similarity index 87% rename from examples/generators/starter_python_smart_contract_typescript/smart_contracts/hello_world/deploy-config.ts rename to examples/starter_typescript_desired/smart_contracts/hello_world/deploy-config.ts index e0608c9..6cf7f14 100644 --- a/examples/generators/starter_python_smart_contract_typescript/smart_contracts/hello_world/deploy-config.ts +++ b/examples/starter_typescript_desired/smart_contracts/hello_world/deploy-config.ts @@ -1,11 +1,11 @@ -import * as algokit from '@algorandfoundation/algokit-utils' +import { AlgorandClient } from '@algorandfoundation/algokit-utils' import { HelloWorldFactory } from '../artifacts/hello_world/HelloWorldClient' // Below is a showcase of various deployment options you can use in TypeScript Client export async function deploy() { console.log('=== Deploying HelloWorld ===') - const algorand = algokit.AlgorandClient.fromEnvironment() + const algorand = AlgorandClient.fromEnvironment() const deployer = await algorand.account.fromEnvironment('DEPLOYER') const factory = algorand.client.getTypedAppFactory(HelloWorldFactory, { @@ -23,7 +23,7 @@ export async function deploy() { }) } - const method = 'hello' + const method = 'hello' const response = await appClient.send.hello({ args: { name: 'world' }, }) diff --git a/examples/generators/production_python_smart_contract_typescript/smart_contracts/index.ts b/examples/starter_typescript_desired/smart_contracts/index.ts similarity index 71% rename from examples/generators/production_python_smart_contract_typescript/smart_contracts/index.ts rename to examples/starter_typescript_desired/smart_contracts/index.ts index 623ca2b..3e54886 100644 --- a/examples/generators/production_python_smart_contract_typescript/smart_contracts/index.ts +++ b/examples/starter_typescript_desired/smart_contracts/index.ts @@ -1,18 +1,18 @@ -import * as fs from 'fs' -import * as path from 'path' +import { Config } from '@algorandfoundation/algokit-utils' +import { registerDebugEventHandlers } from '@algorandfoundation/algokit-utils-debug' import { consoleLogger } from '@algorandfoundation/algokit-utils/types/logging' -import * as algokit from '@algorandfoundation/algokit-utils' -// import { registerDebugEventHandlers } from '@algorandfoundation/algokit-utils-debug' // Uncomment to enable persisting artifacts required by AlgoKit AVM Debugger +import * as fs from 'node:fs' +import * as path from 'node:path' -// Uncomment the debug and traceAll options to enable auto generation of AVM Debugger compliant sourceMap and simulation trace file. +// Uncomment the traceAll option to enable auto generation of AVM Debugger compliant sourceMap and simulation trace file for all AVM calls. // 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 -algokit.Config.configure({ +Config.configure({ logger: consoleLogger, - // debug: true, - // traceAll: true, + debug: true, + traceAll: true, }) -// registerDebugEventHandlers() // Uncomment to enable persisting artifacts required by AlgoKit AVM Debugger +registerDebugEventHandlers() // base directory const baseDir = path.resolve(__dirname) @@ -39,12 +39,12 @@ async function getDeployers() { } // execute all the deployers -(async () => { +;(async () => { const contractName = process.argv.length > 2 ? process.argv[2] : undefined const contractDeployers = await getDeployers() - + const filteredDeployers = contractName - ? contractDeployers.filter(deployer => deployer.name === contractName) + ? contractDeployers.filter((deployer) => deployer.name === contractName) : contractDeployers if (contractName && filteredDeployers.length === 0) { diff --git a/examples/generators/production_python_smart_contract_typescript/tsconfig.json b/examples/starter_typescript_desired/tsconfig.json similarity index 100% rename from examples/generators/production_python_smart_contract_typescript/tsconfig.json rename to examples/starter_typescript_desired/tsconfig.json diff --git a/examples/starter_typescript_desired/tsconfig.test.json b/examples/starter_typescript_desired/tsconfig.test.json new file mode 100644 index 0000000..38d2911 --- /dev/null +++ b/examples/starter_typescript_desired/tsconfig.test.json @@ -0,0 +1,14 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "compilerOptions": { + "noEmit": true, + "target": "ES2023", + "module": "ESNext", + "lib": ["ES2023"], + "moduleResolution": "Bundler", + "resolveJsonModule": true, + "esModuleInterop": true + }, + "include": ["**/*.ts", "**/*.mts"], + "exclude": ["node_modules"] +} diff --git a/examples/starter_typescript_desired/vitest.config.mts b/examples/starter_typescript_desired/vitest.config.mts new file mode 100644 index 0000000..ff8fd56 --- /dev/null +++ b/examples/starter_typescript_desired/vitest.config.mts @@ -0,0 +1,26 @@ +import { puyaTsTransformer } from '@algorandfoundation/algorand-typescript-testing/test-transformer' +import typescript from '@rollup/plugin-typescript' +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + esbuild: {}, + test: { + server: { + deps: { + inline: ['@algorandfoundation/algorand-typescript-testing'], + }, + }, + testTimeout: 10000, + coverage: { + provider: 'v8', + }, + }, + plugins: [ + typescript({ + tsconfig: './tsconfig.test.json', + transformers: { + before: [puyaTsTransformer], + }, + }), + ], +}) diff --git a/template_content/.algokit.toml.jinja b/template_content/.algokit.toml.jinja index ffb4f8c..62e70eb 100644 --- a/template_content/.algokit.toml.jinja +++ b/template_content/.algokit.toml.jinja @@ -15,11 +15,7 @@ name = '{{ project_name }}' artifacts = 'smart_contracts/artifacts' [project.deploy] -{%- if deployment_language == 'python' %} -command = "poetry run python -m smart_contracts deploy" -{%- elif deployment_language == 'typescript' %} command = "npm run deploy:ci" -{%- endif %} environment_secrets = [ "DEPLOYER_MNEMONIC", {%- if use_dispenser %} @@ -31,37 +27,28 @@ environment_secrets = [ environment_secrets = [] [project.run] -# Commands intented for use locally and in CI +# Commands intended for use locally and in CI build = { commands = [ - 'poetry run python -m smart_contracts build', + 'npm run build', ], description = 'Build all smart contracts in the project' } -{%- if deployment_language == 'python' and use_python_pytest %} -test = { commands = [ - 'poetry run pytest', -], description = 'Run smart contract tests' } -{%- elif deployment_language == 'typescript' and use_typescript_jest %} +{%- if use_vitest %} test = { commands = [ 'npm run test', -], description = 'Run smart contract tests using Jest' } +], description = 'Run smart contract tests using vitest' } {%- endif %} -{%- if use_python_pip_audit %} +{%- if use_audit %} audit = { commands = [ - 'poetry run pip-audit', -], description = 'Audit with pip-audit' } + 'npm run audit', +], description = 'Audit with better-npm-audit' } {%- endif %} +{%- if use_linter %} lint = { commands = [ -{%- if use_python_black %} - 'poetry run black --check --diff .', -{%- endif %} -{%- if python_linter == 'ruff' %} - 'poetry run ruff check .', -{%- elif python_linter == 'flake8' %} - 'poetry run flake8 .', -{%- endif %} -{%- if use_python_mypy %} - 'poetry run mypy', + 'npm run lint', +{%- if use_prettier %} + 'npm run format', {%- endif %} ], description = 'Perform linting' } +{%- endif %} audit-teal = { commands = [ # 🚨 IMPORTANT 🚨: For strict TEAL validation, remove --exclude statements. The default starter contract is not for production. Ensure thorough testing and adherence to best practices in smart contract development. This is not a replacement for a professional audit. 'algokit task analyze smart_contracts/artifacts --recursive --force --exclude rekey-to --exclude is-updatable --exclude missing-fee-check --exclude is-deletable --exclude can-close-asset --exclude can-close-account --exclude unprotected-deletable --exclude unprotected-updatable', diff --git a/template_content/.algokit/generators/create_contract/copier.yaml b/template_content/.algokit/generators/create_contract/copier.yaml index 73805de..276c17a 100644 --- a/template_content/.algokit/generators/create_contract/copier.yaml +++ b/template_content/.algokit/generators/create_contract/copier.yaml @@ -7,4 +7,9 @@ contract_name: placeholder: "my-new-contract" default: "my-new-contract" +include_tests: + type: bool + help: Should we include testing files? + default: True + _templates_suffix: ".j2" diff --git a/template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/contract.algo.ts.j2 b/template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/contract.algo.ts.j2 new file mode 100644 index 0000000..1494b9c --- /dev/null +++ b/template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/contract.algo.ts.j2 @@ -0,0 +1,11 @@ +import { Contract } from '@algorandfoundation/algorand-typescript' + +export class {{ contract_name.split('_')|map('capitalize')|join }} extends Contract { + hello(name: string): string { + return `${this.getHello()} ${name}` + } + + private getHello() { + return 'Hello' + } +} diff --git a/template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/contract.py.j2 b/template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/contract.py.j2 deleted file mode 100644 index 829e3a0..0000000 --- a/template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/contract.py.j2 +++ /dev/null @@ -1,9 +0,0 @@ -# pyright: reportMissingModuleSource=false -from algopy import ARC4Contract, String -from algopy.arc4 import abimethod - - -class {{ contract_name.split('_')|map('capitalize')|join }}(ARC4Contract): - @abimethod() - def hello(self, name: String) -> String: - return "Hello, " + name diff --git a/examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/deploy-config.ts.j2 b/template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/deploy-config.ts.j2 similarity index 91% rename from examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/deploy-config.ts.j2 rename to template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/deploy-config.ts.j2 index bd3ad2d..11464e7 100644 --- a/examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/deploy-config.ts.j2 +++ b/template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/deploy-config.ts.j2 @@ -1,11 +1,11 @@ -import * as algokit from '@algorandfoundation/algokit-utils' +import { AlgorandClient } from '@algorandfoundation/algokit-utils' import { {{ contract_name.split('_')|map('capitalize')|join }}Factory } from '../artifacts/{{ contract_name }}/{{ contract_name.split('_')|map('capitalize')|join }}Client' // Below is a showcase of various deployment options you can use in TypeScript Client export async function deploy() { console.log('=== Deploying {{ contract_name.split('_')|map('capitalize')|join }} ===') - const algorand = algokit.AlgorandClient.fromEnvironment() + const algorand = AlgorandClient.fromEnvironment() const deployer = await algorand.account.fromEnvironment('DEPLOYER') const factory = algorand.client.getTypedAppFactory({{ contract_name.split('_')|map('capitalize')|join }}Factory, { diff --git a/template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/{% if deployment_language == 'python' %}deploy_config.py.j2{% endif %} b/template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/{% if deployment_language == 'python' %}deploy_config.py.j2{% endif %} deleted file mode 100644 index eb726b9..0000000 --- a/template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/{% if deployment_language == 'python' %}deploy_config.py.j2{% endif %} +++ /dev/null @@ -1,35 +0,0 @@ -import logging - -import algokit_utils -from algosdk.v2client.algod import AlgodClient -from algosdk.v2client.indexer import IndexerClient - -logger = logging.getLogger(__name__) - - -# define deployment behaviour based on supplied app spec -def deploy( - algod_client: AlgodClient, - indexer_client: IndexerClient, - app_spec: algokit_utils.ApplicationSpecification, - deployer: algokit_utils.Account, -) -> None: - from smart_contracts.artifacts.{{ contract_name }}.{{ contract_name }}_client import ( - {{ contract_name.split('_')|map('capitalize')|join }}Client, - ) - - app_client = {{ contract_name.split('_')|map('capitalize')|join }}Client( - algod_client, - creator=deployer, - indexer_client=indexer_client, - ) - app_client.deploy( - on_schema_break=algokit_utils.OnSchemaBreak.AppendApp, - on_update=algokit_utils.OnUpdate.AppendApp, - ) - name = "world" - response = app_client.hello(name=name) - logger.info( - f"Called hello on {app_spec.contract.name} ({app_client.app_id}) " - f"with name={name}, received: {response.return_value}" - ) diff --git a/template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/{% if deployment_language == 'typescript' %}deploy-config.ts.j2{% endif %} b/template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/{% if deployment_language == 'typescript' %}deploy-config.ts.j2{% endif %} deleted file mode 100644 index bd3ad2d..0000000 --- a/template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/{% if deployment_language == 'typescript' %}deploy-config.ts.j2{% endif %} +++ /dev/null @@ -1,33 +0,0 @@ -import * as algokit from '@algorandfoundation/algokit-utils' -import { {{ contract_name.split('_')|map('capitalize')|join }}Factory } from '../artifacts/{{ contract_name }}/{{ contract_name.split('_')|map('capitalize')|join }}Client' - -// Below is a showcase of various deployment options you can use in TypeScript Client -export async function deploy() { - console.log('=== Deploying {{ contract_name.split('_')|map('capitalize')|join }} ===') - - const algorand = algokit.AlgorandClient.fromEnvironment() - const deployer = await algorand.account.fromEnvironment('DEPLOYER') - - const factory = algorand.client.getTypedAppFactory({{ contract_name.split('_')|map('capitalize')|join }}Factory, { - defaultSender: deployer.addr, - }) - - const { appClient, result } = await factory.deploy({ onUpdate: 'append', onSchemaBreak: 'append' }) - - // If app was just created fund the app account - if (['create', 'replace'].includes(result.operationPerformed)) { - await algorand.send.payment({ - amount: (1).algo(), - sender: deployer.addr, - receiver: app.appAddress, - }) - } - - const method = 'hello' - const response = await appClient.send.hello({ - args: { name: 'world' }, - }) - console.log( - `Called ${method} on ${appClient.appClient.appName} (${appClient.appClient.appId}) with name = world, received: ${response.return}`, - ) -} diff --git a/template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/{% if include_tests %}contract.e2e.spec.ts{% endif %}.j2 b/template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/{% if include_tests %}contract.e2e.spec.ts{% endif %}.j2 new file mode 100644 index 0000000..e395598 --- /dev/null +++ b/template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/{% if include_tests %}contract.e2e.spec.ts{% endif %}.j2 @@ -0,0 +1,36 @@ +import { Config } from '@algorandfoundation/algokit-utils' +import { algorandFixture } from '@algorandfoundation/algokit-utils/testing' +import { Address } from 'algosdk' +import { beforeAll, beforeEach, describe, expect, test } from 'vitest' +import { {{ contract_name.split('_')|map('capitalize')|join }}Factory } from '../artifacts/hello_world/{{ contract_name.split('_')|map('capitalize')|join }}Client' + +describe('{{ contract_name.split('_')|map('capitalize')|join }} contract', () => { + const localnet = algorandFixture() + beforeAll(() => { + Config.configure({ + debug: true, + // traceAll: true, + }) + }) + beforeEach(localnet.beforeEach) + + const deploy = async (account: Address) => { + const factory = localnet.algorand.client.getTypedAppFactory({{ contract_name.split('_')|map('capitalize')|join }}Factory, { + defaultSender: account, + }) + + const { appClient } = await factory.deploy({ onUpdate: 'append', onSchemaBreak: 'append' }) + return { client: appClient } + } + + test('says hello', async () => { + const { testAccount } = localnet.context + const { client } = await deploy(testAccount) + + const result = await client.send.hello({ args: { name: 'World' } }) + + expect(result.return).toBe('Hello World') + }) + +}) + diff --git a/template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/{% if include_tests %}contract.spec.ts{% endif %}.j2 b/template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/{% if include_tests %}contract.spec.ts{% endif %}.j2 new file mode 100644 index 0000000..e7a7414 --- /dev/null +++ b/template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/{% if include_tests %}contract.spec.ts{% endif %}.j2 @@ -0,0 +1,14 @@ +import { TestExecutionContext } from '@algorandfoundation/algorand-typescript-testing' +import { describe, expect, it } from 'vitest' +import { {{ contract_name.split('_')|map('capitalize')|join }} } from './contract.algo' + +describe('{{ contract_name.split('_')|map('capitalize')|join }} contract', () => { + const ctx = new TestExecutionContext() + it('Logs the returned value when sayHello is called', () => { + const contract = ctx.contract.create({{ contract_name.split('_')|map('capitalize')|join }}) + + const result = contract.hello('Sally') + + expect(result).toBe('Hello Sally') + }) +}) diff --git a/template_content/.editorconfig b/template_content/.editorconfig index e2fda34..0a71b07 100644 --- a/template_content/.editorconfig +++ b/template_content/.editorconfig @@ -5,6 +5,3 @@ indent_style = space indent_size = 2 end_of_line = lf insert_final_newline = true - -[*.py] -indent_size = 4 diff --git a/template_content/.gitignore.jinja b/template_content/.gitignore.jinja index 070829c..0aeb5a7 100644 --- a/template_content/.gitignore.jinja +++ b/template_content/.gitignore.jinja @@ -1,180 +1,63 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.py,cover -.hypothesis/ -.pytest_cache/ -cover/ -coverage/ - -# Translations -*.mo -*.pot - -# Django stuff: +# Logs +logs *.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -.pybuilder/ -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -# For a library or package, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# .python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# poetry -# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control -#poetry.lock +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* -# pdm -# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. -#pdm.lock -# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it -# in version control. -# https://pdm.fming.dev/#use-with-ide -.pdm.toml +# Dependency directories +node_modules/ -# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm -__pypackages__/ +# TypeScript cache +*.tsbuildinfo -# Celery stuff -celerybeat-schedule -celerybeat.pid +# Optional npm cache directory +.npm -# SageMath parsed files -*.sage.py +# Optional eslint cache +.eslintcache -# Environments -.env -.venv -env/ -.env.* -!.env.*.template -!.env.template -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json +# Stores VSCode versions used for testing VSCode extensions +.vscode-test -# Pyre type checker -.pyre/ - -# pytype static type analyzer -.pytype/ - -# Ruff (linter) -.ruff_cache/ - -# Cython debug symbols -cython_debug/ +# Editor/OS directories and files +.DS_Store +*.suo -# PyCharm +# IntelliJ family .idea !.idea/ .idea/* !.idea/runConfigurations/ -# macOS -.DS_Store +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +# Compiled code +dist/ +build/ + +# Coverage report +coverage + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local # Received approval test files *.received.* -# NPM -node_modules - # AlgoKit debug_traces/ .algokit/static-analysis/ # Replace with .algokit/static-analysis/tealer/ to enable snapshot checks in CI .algokit/sources + diff --git a/examples/generators/starter_python_smart_contract_typescript/.npmrc b/template_content/.npmrc similarity index 100% rename from examples/generators/starter_python_smart_contract_typescript/.npmrc rename to template_content/.npmrc diff --git a/template_content/README.md.jinja b/template_content/README.md.jinja index 73ca5e9..b7924f9 100644 --- a/template_content/README.md.jinja +++ b/template_content/README.md.jinja @@ -6,7 +6,8 @@ This project has been generated using AlgoKit. See below for default getting sta ### Pre-requisites -- [Python 3.12](https://www.python.org/downloads/) or later +- [Nodejs 20](https://nodejs.org/en/download) or later +- [AlgoKit CLI 2.5](https://github.com/algorandfoundation/algokit-cli?tab=readme-ov-file#install) or later - [Docker](https://www.docker.com/) (only required for LocalNet) > For interactive tour over the codebase, download [vsls-contrib.codetour](https://marketplace.visualstudio.com/items?itemName=vsls-contrib.codetour) extension for VS Code, then open the [`.codetour.json`](./.tours/getting-started-with-your-algokit-project.tour) file in code tour extension. @@ -19,14 +20,13 @@ Start by cloning this repository to your local machine. #### 2. Install Pre-requisites Ensure the following pre-requisites are installed and properly configured: -- **Docker**: Required for running a local Algorand network. [Install Docker](https://www.docker.com/). -- **AlgoKit CLI**: Essential for project setup and operations. Install the latest version from [AlgoKit CLI Installation Guide](https://github.com/algorandfoundation/algokit-cli#install). Verify installation with `algokit --version`, expecting `2.0.0` or later. +- **Docker**: Required for running a local Algorand network. +- **AlgoKit CLI**: Essential for project setup and operations. Verify installation with `algokit --version`, expecting `2.5.0` or later. #### 3. Bootstrap Your Local Environment Run the following commands within the project folder: -- **Install Poetry**: Required for Python dependency management. [Installation Guide](https://python-poetry.org/docs/#installation). Verify with `poetry -V` to see version `1.2`+. -- **Setup Project**: Execute `algokit project bootstrap all` to install dependencies and setup a Python virtual environment in `.venv`. +- **Setup Project**: Execute `algokit project bootstrap all` to install dependencies and setup npm dependencies. - **Configure environment**: Execute `algokit generate env-file -a target_network localnet` to create a `.env.localnet` file with default configuration for `localnet`. - **Start LocalNet**: Use `algokit localnet start` to initiate a local Algorand network. @@ -47,13 +47,12 @@ For a seamless experience with breakpoint debugging and other features: 2. **Install Extensions**: Follow prompts to install recommended extensions. 3. **Debugging**: - Use `F5` to start debugging. - - **Windows Users**: Select the Python interpreter at `./.venv/Scripts/python.exe` via `Ctrl/Cmd + Shift + P` > `Python: Select Interpreter` before the first run. #### JetBrains IDEs While primarily optimized for VS Code, JetBrains IDEs are supported: 1. **Open Project**: In your JetBrains IDE, open the repository root. -2. **Automatic Setup**: The IDE should configure the Python interpreter and virtual environment. +2. **Automatic Setup**: The IDE should configure the Node.js environment. 3. **Debugging**: Use `Shift+F10` or `Ctrl+R` to start debugging. Note: Windows users may encounter issues with pre-launch tasks due to a known bug. See [JetBrains forums](https://youtrack.jetbrains.com/issue/IDEA-277486/Shell-script-configuration-cannot-run-as-before-launch-task) for workarounds. ## AlgoKit Workspaces and Project Management @@ -68,30 +67,26 @@ This template provides a set of [algokit generators](https://github.com/algorand By default the template creates a single `HelloWorld` contract under {{ contract_name }} folder in the `smart_contracts` directory. To add a new contract: 1. From the root of the project (`../`) execute `algokit generate smart-contract`. This will create a new starter smart contract and deployment configuration file under `{your_contract_name}` subfolder in the `smart_contracts` directory. -2. Each contract potentially has different creation parameters and deployment steps. Hence, you need to define your deployment logic in {% if deployment_language == 'python' %}`deploy_config.py`{% elif deployment_language == 'typescript' %}`deploy-config.ts`{% endif %}file. -3. `config.py` file will automatically build all contracts in the `smart_contracts` directory. If you want to build specific contracts manually, modify the default code provided by the template in `config.py` file. -{%- if deployment_language == 'typescript' %} -4. Since you are generating a TypeScript client, you also need to reference your contract deployment logic in `index.ts` file. However, similar to config.py, by default, `index.ts` will auto import all TypeScript deployment files under `smart_contracts` directory. If you want to manually import specific contracts, modify the default code provided by the template in `index.ts` file. -{%- endif %} +2. Each contract potentially has different creation parameters and deployment steps. Hence, you need to define your deployment logic in `deploy-config.ts` file. +3. Technically, you need to reference your contract deployment logic in the `index.ts` file. However, by default, `index.ts` will auto import all TypeScript deployment files under `smart_contracts` directory. If you want to manually import specific contracts, modify the default code provided by the template in `index.ts` file. -> Please note, above is just a suggested convention tailored for the base configuration and structure of this template. The default code supplied by the template in `config.py` and `index.ts` (if using ts clients) files are tailored for the suggested convention. You are free to modify the structure and naming conventions as you see fit. +> Please note, above is just a suggested convention tailored for the base configuration and structure of this template. The default code supplied by the template in the `index.ts` file is tailored for the suggested convention. You are free to modify the structure and naming conventions as you see fit. ### Generate '.env' files -By default the template instance does not contain any env files. Using [`algokit project deploy`](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/project/deploy.md) against `localnet` | `testnet` | `mainnet` will use default values for `algod` and `indexer` unless overwritten via `.env` or `.env.{target_network}`. +By default the template instance does not contain any env files to deploy to different networks. Using [`algokit project deploy`](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/project/deploy.md) against `localnet` | `testnet` | `mainnet` will use default values for `algod` and `indexer` unless overwritten via `.env` or `.env.{target_network}`. To generate a new `.env` or `.env.{target_network}` file, run `algokit generate env-file` ### Debugging Smart Contracts This project is optimized to work with AlgoKit AVM Debugger extension. To activate it: -{%- if deployment_language == 'python' %} -Refer to the commented header in the `__main__.py` file in the `smart_contracts` folder. -{%- elif deployment_language == 'typescript' %} + Refer to the commented header in the `index.ts` file in the `smart_contracts` folder. -{%- endif %} -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. +{%- if ide_vscode -%} +Since 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. +{% endif %} 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). @@ -109,15 +104,9 @@ To define custom `algokit project run` commands refer to [documentation](https:/ #### Setting up GitHub for CI/CD workflow and TestNet deployment 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 -{%- if deployment_language == 'python' %} - 2. Decide what values you want to use for the `allow_update`, `allow_delete` and the `on_schema_break`, `on_update` parameters specified in [`contract.py`](./smart_contracts/{{ contract_name }}/contract.py). - When deploying to LocalNet these values are both set to allow update and replacement of the app for convenience. But for non-LocalNet networks - the defaults are more conservative. -{%- elif deployment_language == 'typescript' %} 2. Decide what values you want to use for the `allowUpdate` and `allowDelete` parameters specified in [`deploy-config.ts`](./smart_contracts/{{ contract_name }}/deploy-config.ts). When deploying to LocalNet these values are both set to `true` for convenience. But for non-LocalNet networks they are more conservative and use `false` -{%- endif %} These default values will allow the smart contract to be deployed initially, but will not allow the app to be updated or deleted if is changed and the build will instead fail. To help you decide it may be helpful to read the [AlgoKit Utils app deployment documentation](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/docs/capabilities/app-deploy.md) or the [AlgoKit smart contract deployment architecture](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/architecture-decisions/2023-01-12_smart-contract-deployment.md#upgradeable-and-deletable-contracts). 3. Create a [Github Environment](https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#creating-an-environment) named `Test`. @@ -133,33 +122,24 @@ To define custom `algokit project run` commands refer to [documentation](https:/ #### Continuous Integration For pull requests and pushes to `main` branch against this repository the following checks are automatically performed by GitHub Actions: -{%- if use_python_pip_audit %} - - Python dependencies are audited using [pip-audit](https://pypi.org/project/pip-audit/) -{%- endif %} -{%- if use_python_black %} - - Code formatting is checked using [Black](https://github.com/psf/black) -{%- endif %} -{%- if python_linter == 'ruff' %} - - Linting is checked using [Ruff](https://github.com/charliermarsh/ruff) -{%- elif python_linter == 'flake8' %} - - Linting is checked using [Flake8](https://flake8.pycqa.org/en/latest/) -{%- endif %} -{%- if use_python_mypy %} - - Types are checked using [mypy](https://mypy-lang.org/) +{%- if use_audit %} + - NPM dependencies are audited using [better-npm-audit](https://github.com/jeemok/better-npm-audit#readme) {%- endif %} -{%- if use_python_pytest %} -- The base framework for testing is [pytest](https://docs.pytest.org/), and the project includes two separate kinds of tests: -- - `Algorand Python` smart contract unit tests, that are run using [`algorand-python-testing`](https://pypi.org/project/algorand-python-testing/), which are executed in a Python intepreter emulating major AVM behaviour -- - Python `ApplicationClient` tests that are run against `algokit localnet` and test the behaviour in a real network enviornment +{%- if use_prettier %} + - Code formatting is performed using [Prettier](https://prettier.io/) {%- endif %} -{%- if use_typescript_jest %} - - Typescript `ApplicationClient` tests against `algokit localnet` are executed using [jest](https://jestjs.io/) +{%- if use_linter %} + - Linting is checked using [ESLint](https://eslint.org/) +{%- if use_vitest %} +- The base framework for testing is [vitest](https://vitest.dev/), and the project includes two separate kinds of tests: +- - `Algorand TypeScript` smart contract unit tests, that are run using [`algorand-typescript-testing`](https://github.com/algorandfoundation/algorand-typescript-testing), which are executed in a Node.js intepreter emulating major AVM behaviour +- - End-to-end (e2e) `AppClient` tests that are run against `algokit localnet` and test the behaviour in a real network environment {%- endif %} - Smart contract artifacts are built - Smart contract artifacts are checked for [output stability](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/articles/output_stability.md). - Smart contract is deployed to a AlgoKit LocalNet instance -> NOTE: By default smart contract artifacts are compiled with `--debug-level` set to 0, to change this, modify the compiler invocation under `smart_contracts/_helpers/build.py` +> NOTE: By default smart contract artifacts are compiled with `--debug-level` set to 0, to change this, modify the compiler invocation under the `build` script in `package.json` #### Continuous Deployment @@ -172,39 +152,35 @@ For pushes to `main` branch, after the above checks pass, the following deployme # Tools -This project makes use of Algorand Python to build Algorand smart contracts. The following tools are in use: +This project makes use of Algorand TypeScript to build Algorand smart contracts. The following tools are in use: - [Algorand](https://www.algorand.com/) - Layer 1 Blockchain; [Developer portal](https://developer.algorand.org/), [Why Algorand?](https://developer.algorand.org/docs/get-started/basics/why_algorand/) - [AlgoKit](https://github.com/algorandfoundation/algokit-cli) - One-stop shop tool for developers building on the Algorand network; [docs](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/algokit.md), [intro tutorial](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/tutorials/intro.md) -- [Algorand Python](https://github.com/algorandfoundation/puya) - A semantically and syntactically compatible, typed Python language that works with standard Python tooling and allows you to express smart contracts (apps) and smart signatures (logic signatures) for deployment on the Algorand Virtual Machine (AVM); [docs](https://github.com/algorandfoundation/puya), [examples](https://github.com/algorandfoundation/puya/tree/main/examples) -- [AlgoKit Utils]({% if deployment_language == "typescript" %}https://github.com/algorandfoundation/algokit-utils-ts{% else %}https://github.com/algorandfoundation/algokit-utils-py{% endif %}) - A set of core Algorand utilities that make it easier to build solutions on Algorand. -- [Poetry](https://python-poetry.org/): Python packaging and dependency management. -{%- if use_python_black -%} -- [Black](https://github.com/psf/black): A Python code formatter. -{%- endif %} -{%- if python_linter == "ruff" -%} -- [Ruff](https://github.com/charliermarsh/ruff): An extremely fast Python linter. -{% elif python_linter == "flake8" -%} -- [Flake8](https://flake8.pycqa.org/en/latest/): A Python linter for style guide enforcement. +- [Algorand TypeScript](https://github.com/algorandfoundation/puya-ts/) - A semantically and syntactically compatible, typed TypeScript language that works with standard TypeScript tooling and allows you to express smart contracts (apps) and smart signatures (logic signatures) for deployment on the Algorand Virtual Machine (AVM); [docs](https://github.com/algorandfoundation/puya-ts/), [examples](https://github.com/algorandfoundation/puya-ts/tree/main/examples) +- [AlgoKit Utils](https://github.com/algorandfoundation/algokit-utils-ts) - A set of core Algorand utilities that make it easier to build solutions on Algorand. +- [NPM](https://www.npmjs.com/): TypeScript packaging and dependency management. +- [TypeScript](https://www.typescriptlang.org/): Strongly typed programming language that builds on JavaScript +- [ts-node-dev](https://github.com/wclr/ts-node-dev): TypeScript development execution environment +{%- if use_prettier -%} +- [Prettier](https://prettier.io/): A code formatter. {%- endif %} -{%- if use_python_mypy %} -- [mypy](https://mypy-lang.org/): Static type checker. +{%- if use_linter -%} +- [ESLint](https://eslint.org/): A JavaScript / TypeScript linter. {%- endif %} -{%- if use_python_pytest %} -- [pytest](https://docs.pytest.org/): Automated testing. +{%- if use_vitest %} +- [vitest](https://vitest.dev/): Automated testing. {%- endif %} -{%- if use_python_pip_audit %} -- [pip-audit](https://pypi.org/project/pip-audit/): Tool for scanning Python environments for packages with known vulnerabilities. +{%- if use_audit %} +- [better-npm-audit](https://github.com/jeemok/better-npm-audit#readme): Tool for scanning JavaScript / TypeScript environments for packages with known vulnerabilities. {%- endif %} {%- if use_pre_commit %} - [pre-commit](https://pre-commit.com/): A framework for managing and maintaining multi-language pre-commit hooks, to enable pre-commit you need to run `pre-commit install` in the root of the repository. This will install the pre-commit hooks and run them against modified files when committing. If any of the hooks fail, the commit will be aborted. To run the hooks on all files, use `pre-commit run --all-files`. {%- endif %} -{%- if deployment_language == "typescript" %} -- [npm](https://www.npmjs.com/): Node.js package manager -- [TypeScript](https://www.typescriptlang.org/): Strongly typed programming language that builds on JavaScript -- [ts-node-dev](https://github.com/wclr/ts-node-dev): TypeScript development execution environment -{% endif -%} {% if ide_vscode %} It has also been configured to have a productive dev experience out of the box in [VS Code](https://code.visualstudio.com/), see the [.vscode](./.vscode) folder. {% endif %} + +{% if ide_jetbrains %} +It has also been configured to have a productive dev experience out of the box in [Jetbrains IDEs](https://www.jetbrains.com/ides/), see the [.idea](./.idea) folder. +{% endif %} diff --git a/template_content/package.json.jinja b/template_content/package.json.jinja new file mode 100644 index 0000000..56983d8 --- /dev/null +++ b/template_content/package.json.jinja @@ -0,0 +1,56 @@ +{ + "name": "smart_contracts", + "version": "1.0.0", + "description": "Smart contract deployer", + "main": "smart_contracts/index.ts", + "scripts": { + "build": "puya-ts build smart_contracts --output-source-map --out-dir artifacts && algokit generate client smart_contracts/artifacts --output {app_spec_dir}/{contract_name}Client.ts", + "deploy": "ts-node-dev --transpile-only --watch .env -r dotenv/config smart_contracts/index.ts", + "deploy:ci": "ts-node --transpile-only -r dotenv/config smart_contracts/index.ts", + {%- if use_eslint %} + "lint": "eslint ./src/ --ext .ts", + "lint:fix": "eslint ./src/ --ext .ts --fix", + {%- endif %} + "check-types": "tsc --noEmit", + {%- if use_audit %} + "audit": "better-npm-audit audit", + {%- endif %} + {%- if use_prettier %} + "format": "prettier --write .", + {%- endif %} + {%- if use_vitest %} + "test": "vitest run --coverage", + "test:watch": "vitest watch" + {%- endif %} + }, + "engines": { + "node": ">=20.0", + "npm": ">=9.0" + }, + "dependencies": { + "@algorandfoundation/algorand-typescript": "^1.0.0-beta.4" + }, + "devDependencies": { + "@algorandfoundation/algokit-client-generator": "^4.0.6", + "@algorandfoundation/algokit-utils": "^8.0.3", + "@algorandfoundation/algokit-utils-debug": "^1.0.2", + "@algorandfoundation/puya-ts": "^1.0.0-beta.6", + "@rollup/plugin-typescript": "^12.1.2", + "@tsconfig/node20": "^20.1.4", + "algosdk": "^3.0.0", + {%- if use_audit %} + "better-npm-audit": "^3.11.0", + {%- endif %} + "dotenv": "^16.4.7", + {%- if use_prettier %} + "prettier": "^3.4.2", + {%- endif %} + "ts-node-dev": "^2.0.0", + {%- if use_vitest %} + "@algorandfoundation/algorand-typescript-testing": "^1.0.0-beta.1", + "vitest": "^2.1.8", + "@vitest/coverage-v8": "^2.1.8", + {%- endif %} + "typescript": "^5.7.3" + } +} diff --git a/template_content/poetry.toml b/template_content/poetry.toml deleted file mode 100644 index 5fcef8c..0000000 --- a/template_content/poetry.toml +++ /dev/null @@ -1,3 +0,0 @@ -[virtualenvs] -in-project = true -prefer-active-python = true diff --git a/template_content/pyproject.toml.jinja b/template_content/pyproject.toml.jinja deleted file mode 100644 index a2fafa8..0000000 --- a/template_content/pyproject.toml.jinja +++ /dev/null @@ -1,90 +0,0 @@ -[tool.poetry] -name = "{{ project_name }}" -version = "0.1.0" -description = "Algorand smart contracts" -authors = ["{{ author_name }} <{{ author_email }}>"] -readme = "README.md" - -[tool.poetry.dependencies] -python = "^3.12" -algokit-utils = "^2.4.0" -python-dotenv = "^1.0.0" -algorand-python = "^2.0.0" -algorand-python-testing = "^0.4.0" - -[tool.poetry.group.dev.dependencies] -{% if deployment_language == 'python' -%} -algokit-client-generator = "^1.1.3" -{% endif -%} -{% if use_python_black -%} -black = {extras = ["d"], version = "*"} -{% endif -%} -{% if python_linter == 'ruff' -%} -ruff = "^0.1.6" -{% elif python_linter == 'flake8' -%} -flake8 = "*" -{% endif -%} -{% if use_python_mypy -%} -mypy = "1.11.0" -{% endif -%} -{% if use_python_pytest -%} -pytest = "*" -pytest-cov = "*" -{% endif -%} -{% if use_python_pip_audit -%} -pip-audit = "*" -{% endif -%} -{% if use_pre_commit -%} -pre-commit = "*" -{% endif -%} -puyapy = "*" - -[build-system] -requires = ["poetry-core"] -build-backend = "poetry.core.masonry.api" - -{% if python_linter == 'ruff' -%} -[tool.ruff] -line-length = 120 -select = ["E", "F", "ANN", "UP", "N", "C4", "B", "A", "YTT", "W", "FBT", "Q", "RUF", "I"] -ignore = [ - "ANN101", # no type for self - "ANN102", # no type for cls -] -unfixable = ["B", "RUF"] - -[tool.ruff.flake8-annotations] -allow-star-arg-any = true -suppress-none-returning = true -{% endif -%} -{% if use_python_pytest %} -[tool.pytest.ini_options] -pythonpath = ["smart_contracts", "tests"] -{% endif -%} -{% if use_python_mypy %} -[tool.mypy] -files = "smart_contracts/" -python_version = "3.12" -disallow_any_generics = true -disallow_subclassing_any = true -disallow_untyped_calls = true -disallow_untyped_defs = true -disallow_incomplete_defs = true -check_untyped_defs = true -disallow_untyped_decorators = true -warn_redundant_casts = true -warn_unused_ignores = true -warn_return_any = true -strict_equality = true -extra_checks = true -disallow_any_unimported = true -disallow_any_expr = true -disallow_any_decorated = true -disallow_any_explicit = true -untyped_calls_exclude = ["algosdk"] -# Remove if you prefer to use mypy's default behavior against -# untyped algosdk types -[[tool.mypy.overrides]] -module = "tests.*" -disallow_any_expr = false -{% endif -%} diff --git a/template_content/smart_contracts/__init__.py b/template_content/smart_contracts/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/template_content/smart_contracts/__main__.py.jinja b/template_content/smart_contracts/__main__.py.jinja deleted file mode 100644 index a0c4fee..0000000 --- a/template_content/smart_contracts/__main__.py.jinja +++ /dev/null @@ -1,76 +0,0 @@ -import logging -import sys -from pathlib import Path - -from dotenv import load_dotenv - -from smart_contracts._helpers.build import build -from smart_contracts._helpers.config import contracts -{% if deployment_language == 'python' -%} -from smart_contracts._helpers.deploy import deploy - -# Uncomment the following lines to enable auto generation of AVM Debugger compliant sourcemap and simulation trace file. -# 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 -# from algokit_utils.config import config -# config.configure(debug=True, trace_all=True) -{%- endif %} -logging.basicConfig( - level=logging.DEBUG, format="%(asctime)s %(levelname)-10s: %(message)s" -) -logger = logging.getLogger(__name__) -logger.info("Loading .env") -# For manual script execution (bypassing `algokit project deploy`) with a custom .env, -# modify `load_dotenv()` accordingly. For example, `load_dotenv('.env.localnet')`. -load_dotenv() -root_path = Path(__file__).parent - - -def main(action: str, contract_name: str | None = None) -> None: - artifact_path = root_path / "artifacts" - - # Filter contracts if a specific contract name is provided - filtered_contracts = [ - c for c in contracts if contract_name is None or c.name == contract_name - ] - - match action: - case "build": - for contract in filtered_contracts: - logger.info(f"Building app at {contract.path}") - build(artifact_path / contract.name, contract.path) - {%- if deployment_language == 'python' %} - case "deploy": - for contract in filtered_contracts: - output_dir = artifact_path / contract.name - app_spec_file_name = next( - ( - file.name - for file in output_dir.iterdir() - if file.is_file() and file.suffixes == [".arc32", ".json"] - ), - None, - ) - if app_spec_file_name is None: - raise Exception("Could not deploy app, .arc32.json file not found") - app_spec_path = output_dir / app_spec_file_name - if contract.deploy: - logger.info(f"Deploying app {contract.name}") - deploy(app_spec_path, contract.deploy) - case "all": - for contract in filtered_contracts: - logger.info(f"Building app at {contract.path}") - app_spec_path = build(artifact_path / contract.name, contract.path) - if contract.deploy: - logger.info(f"Deploying {contract.path.name}") - deploy(app_spec_path, contract.deploy) - {%- endif %} - - -if __name__ == "__main__": - if len(sys.argv) > 2: - main(sys.argv[1], sys.argv[2]) - elif len(sys.argv) > 1: - main(sys.argv[1]) - else: - main("{{ 'all' if deployment_language == 'python' else 'build' }}") diff --git a/template_content/smart_contracts/_helpers/__init__.py b/template_content/smart_contracts/_helpers/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/template_content/smart_contracts/_helpers/build.py.jinja b/template_content/smart_contracts/_helpers/build.py.jinja deleted file mode 100644 index 152f340..0000000 --- a/template_content/smart_contracts/_helpers/build.py.jinja +++ /dev/null @@ -1,79 +0,0 @@ -import logging -import subprocess -from pathlib import Path -from shutil import rmtree - -logger = logging.getLogger(__name__) -{% if deployment_language == 'python' -%} -deployment_extension = "py" -{% elif deployment_language == 'typescript' -%} -deployment_extension = "ts" -{% endif %} - -def _get_output_path(output_dir: Path, deployment_extension: str) -> Path: - return output_dir / Path( - "{contract_name}" - + ("_client" if deployment_extension == "py" else "Client") - + f".{deployment_extension}" - ) - - -def build(output_dir: Path, contract_path: Path) -> Path: - output_dir = output_dir.resolve() - if output_dir.exists(): - rmtree(output_dir) - output_dir.mkdir(exist_ok=True, parents=True) - logger.info(f"Exporting {contract_path} to {output_dir}") - - build_result = subprocess.run( - [ - "algokit", - "--no-color", - "compile", - "python", - contract_path.absolute(), - f"--out-dir={output_dir}", - "--output-arc32", - "--output-source-map", - ], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - text=True, - ) - if build_result.returncode: - raise Exception(f"Could not build contract:\n{build_result.stdout}") - - app_spec_file_names = [file.name for file in output_dir.glob("*.arc32.json")] - app_spec_file_name = None - for app_spec_file_name in app_spec_file_names: - if app_spec_file_name is None: - logger.warning( - "No '*.arc32.json' file found (likely a logic signature being compiled). Skipping client generation." - ) - continue - print(app_spec_file_name) - generate_result = subprocess.run( - [ - "algokit", - "generate", - "client", - output_dir, - "--output", - _get_output_path(output_dir, deployment_extension), - ], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - text=True, - ) - if generate_result.returncode: - if "No such command" in generate_result.stdout: - raise Exception( - "Could not generate typed client, requires AlgoKit 2.0.0 or " - "later. Please update AlgoKit" - ) - else: - raise Exception( - f"Could not generate typed client:\n{generate_result.stdout}" - ) - - return output_dir / app_spec_file_name if app_spec_file_name else output_dir diff --git a/template_content/smart_contracts/_helpers/config.py.jinja b/template_content/smart_contracts/_helpers/config.py.jinja deleted file mode 100644 index 8f3ca93..0000000 --- a/template_content/smart_contracts/_helpers/config.py.jinja +++ /dev/null @@ -1,61 +0,0 @@ -import dataclasses -import importlib -from collections.abc import Callable -from pathlib import Path - -from algokit_utils import Account, ApplicationSpecification -from algosdk.v2client.algod import AlgodClient -from algosdk.v2client.indexer import IndexerClient - - -@dataclasses.dataclass -class SmartContract: - path: Path - name: str - deploy: ( - Callable[[AlgodClient, IndexerClient, ApplicationSpecification, Account], None] - | None - ) = None - - -def import_contract(folder: Path) -> Path: - """Imports the contract from a folder if it exists.""" - contract_path = folder / "contract.py" - if contract_path.exists(): - return contract_path - else: - raise Exception(f"Contract not found in {folder}") - - -def import_deploy_if_exists( - folder: Path, -) -> ( - Callable[[AlgodClient, IndexerClient, ApplicationSpecification, Account], None] - | None -): - """Imports the deploy function from a folder if it exists.""" - try: - deploy_module = importlib.import_module( - f"{folder.parent.name}.{folder.name}.deploy_config" - ) - return deploy_module.deploy # type: ignore - except ImportError: - return None - - -def has_contract_file(directory: Path) -> bool: - """Checks whether the directory contains contract.py file.""" - return (directory / "contract.py").exists() - - -# define contracts to build and/or deploy -base_dir = Path("smart_contracts") -contracts = [ - SmartContract( - path=import_contract(folder), - name=folder.name, - deploy=import_deploy_if_exists(folder), - ) - for folder in base_dir.iterdir() - if folder.is_dir() and has_contract_file(folder) -] diff --git a/template_content/smart_contracts/_helpers/{% if deployment_language == 'python' %}deploy.py{% endif %}.jinja b/template_content/smart_contracts/_helpers/{% if deployment_language == 'python' %}deploy.py{% endif %}.jinja deleted file mode 100644 index 10185a9..0000000 --- a/template_content/smart_contracts/_helpers/{% if deployment_language == 'python' %}deploy.py{% endif %}.jinja +++ /dev/null @@ -1,53 +0,0 @@ -# mypy: disable-error-code="no-untyped-call, misc" - - -import logging -from collections.abc import Callable -from pathlib import Path - -from algokit_utils import ( - Account, - ApplicationSpecification, - EnsureBalanceParameters, - ensure_funded, - get_account, - get_algod_client, - get_indexer_client, -) -from algosdk.util import algos_to_microalgos -from algosdk.v2client.algod import AlgodClient -from algosdk.v2client.indexer import IndexerClient - -logger = logging.getLogger(__name__) - - -def deploy( - app_spec_path: Path, - deploy_callback: Callable[ - [AlgodClient, IndexerClient, ApplicationSpecification, Account], None - ], - deployer_initial_funds: int = 2, -) -> None: - # get clients - # by default client configuration is loaded from environment variables - algod_client = get_algod_client() - indexer_client = get_indexer_client() - - # get app spec - app_spec = ApplicationSpecification.from_json(app_spec_path.read_text()) - - # get deployer account by name - deployer = get_account(algod_client, "DEPLOYER", fund_with_algos=0) - - minimum_funds_micro_algos = algos_to_microalgos(deployer_initial_funds) - ensure_funded( - algod_client, - EnsureBalanceParameters( - account_to_fund=deployer, - min_spending_balance_micro_algos=minimum_funds_micro_algos, - min_funding_increment_micro_algos=minimum_funds_micro_algos, - ), - ) - - # use provided callback to deploy the app - deploy_callback(algod_client, indexer_client, app_spec, deployer) diff --git a/template_content/smart_contracts/{% if deployment_language == 'typescript' %}index.ts{% endif %}.jinja b/template_content/smart_contracts/{% if deployment_language == 'typescript' %}index.ts{% endif %}.jinja index 623ca2b..6030d0e 100644 --- a/template_content/smart_contracts/{% if deployment_language == 'typescript' %}index.ts{% endif %}.jinja +++ b/template_content/smart_contracts/{% if deployment_language == 'typescript' %}index.ts{% endif %}.jinja @@ -1,18 +1,18 @@ -import * as fs from 'fs' -import * as path from 'path' +import { Config } from '@algorandfoundation/algokit-utils' +import { registerDebugEventHandlers } from '@algorandfoundation/algokit-utils-debug' import { consoleLogger } from '@algorandfoundation/algokit-utils/types/logging' -import * as algokit from '@algorandfoundation/algokit-utils' -// import { registerDebugEventHandlers } from '@algorandfoundation/algokit-utils-debug' // Uncomment to enable persisting artifacts required by AlgoKit AVM Debugger +import * as fs from 'node:fs' +import * as path from 'node:path' -// Uncomment the debug and traceAll options to enable auto generation of AVM Debugger compliant sourceMap and simulation trace file. +// Uncomment the traceAll option to enable auto generation of AVM Debugger compliant sourceMap and simulation trace file for all AVM calls. // 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 -algokit.Config.configure({ +Config.configure({ logger: consoleLogger, - // debug: true, + debug: true, // traceAll: true, }) -// registerDebugEventHandlers() // Uncomment to enable persisting artifacts required by AlgoKit AVM Debugger +registerDebugEventHandlers() // base directory const baseDir = path.resolve(__dirname) diff --git a/template_content/smart_contracts/{{ contract_name }}/contract.algo.ts.jinja b/template_content/smart_contracts/{{ contract_name }}/contract.algo.ts.jinja new file mode 100644 index 0000000..1494b9c --- /dev/null +++ b/template_content/smart_contracts/{{ contract_name }}/contract.algo.ts.jinja @@ -0,0 +1,11 @@ +import { Contract } from '@algorandfoundation/algorand-typescript' + +export class {{ contract_name.split('_')|map('capitalize')|join }} extends Contract { + hello(name: string): string { + return `${this.getHello()} ${name}` + } + + private getHello() { + return 'Hello' + } +} diff --git a/template_content/smart_contracts/{{ contract_name }}/contract.py.jinja b/template_content/smart_contracts/{{ contract_name }}/contract.py.jinja deleted file mode 100644 index 50ce4ca..0000000 --- a/template_content/smart_contracts/{{ contract_name }}/contract.py.jinja +++ /dev/null @@ -1,8 +0,0 @@ -from algopy import ARC4Contract, String -from algopy.arc4 import abimethod - - -class {{ contract_name.split('_')|map('capitalize')|join }}(ARC4Contract): - @abimethod() - def hello(self, name: String) -> String: - return "Hello, " + name diff --git a/template_content/smart_contracts/{{ contract_name }}/{% if deployment_language == 'typescript' %}deploy-config.ts{% endif %}.jinja b/template_content/smart_contracts/{{ contract_name }}/deploy-config.ts.jinja similarity index 91% rename from template_content/smart_contracts/{{ contract_name }}/{% if deployment_language == 'typescript' %}deploy-config.ts{% endif %}.jinja rename to template_content/smart_contracts/{{ contract_name }}/deploy-config.ts.jinja index a375c9f..4626980 100644 --- a/template_content/smart_contracts/{{ contract_name }}/{% if deployment_language == 'typescript' %}deploy-config.ts{% endif %}.jinja +++ b/template_content/smart_contracts/{{ contract_name }}/deploy-config.ts.jinja @@ -1,11 +1,11 @@ -import * as algokit from '@algorandfoundation/algokit-utils' +import { AlgorandClient } from '@algorandfoundation/algokit-utils' import { {{ contract_name.split('_')|map('capitalize')|join }}Factory } from '../artifacts/{{ contract_name }}/{{ contract_name.split('_')|map('capitalize')|join }}Client' // Below is a showcase of various deployment options you can use in TypeScript Client export async function deploy() { console.log('=== Deploying {{ contract_name.split('_')|map('capitalize')|join }} ===') - const algorand = algokit.AlgorandClient.fromEnvironment() + const algorand = AlgorandClient.fromEnvironment() const deployer = await algorand.account.fromEnvironment('DEPLOYER') const factory = algorand.client.getTypedAppFactory({{ contract_name.split('_')|map('capitalize')|join }}Factory, { diff --git a/template_content/smart_contracts/{{ contract_name }}/{% if deployment_language == 'python' %}deploy_config.py{% endif %}.jinja b/template_content/smart_contracts/{{ contract_name }}/{% if deployment_language == 'python' %}deploy_config.py{% endif %}.jinja deleted file mode 100644 index a261e79..0000000 --- a/template_content/smart_contracts/{{ contract_name }}/{% if deployment_language == 'python' %}deploy_config.py{% endif %}.jinja +++ /dev/null @@ -1,36 +0,0 @@ -import logging - -import algokit_utils -from algosdk.v2client.algod import AlgodClient -from algosdk.v2client.indexer import IndexerClient - -logger = logging.getLogger(__name__) - - -# define deployment behaviour based on supplied app spec -def deploy( - algod_client: AlgodClient, - indexer_client: IndexerClient, - app_spec: algokit_utils.ApplicationSpecification, - deployer: algokit_utils.Account, -) -> None: - from smart_contracts.artifacts.{{ contract_name }}.{{ contract_name }}_client import ( - {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client, - ) - - app_client = {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client( - algod_client, - creator=deployer, - indexer_client=indexer_client, - ) - - app_client.deploy( - on_schema_break=algokit_utils.OnSchemaBreak.AppendApp, - on_update=algokit_utils.OnUpdate.AppendApp, - ) - name = "world" - response = app_client.hello(name=name) - logger.info( - f"Called hello on {app_spec.contract.name} ({app_client.app_id}) " - f"with name={name}, received: {response.return_value}" - ) diff --git a/template_content/{% if use_typescript_jest %}tests{% endif %}/{% if use_typescript_jest %}{% include pathjoin('includes', 'contract_name_kebab.jinja') %}.spec.ts{% endif %}.jinja b/template_content/smart_contracts/{{ contract_name }}/{% if use_vitest %}contract.e2e.spec.ts{% endif %}.jinja similarity index 54% rename from template_content/{% if use_typescript_jest %}tests{% endif %}/{% if use_typescript_jest %}{% include pathjoin('includes', 'contract_name_kebab.jinja') %}.spec.ts{% endif %}.jinja rename to template_content/smart_contracts/{{ contract_name }}/{% if use_vitest %}contract.e2e.spec.ts{% endif %}.jinja index b7ea209..1537cd7 100644 --- a/template_content/{% if use_typescript_jest %}tests{% endif %}/{% if use_typescript_jest %}{% include pathjoin('includes', 'contract_name_kebab.jinja') %}.spec.ts{% endif %}.jinja +++ b/template_content/smart_contracts/{{ contract_name }}/{% if use_vitest %}contract.e2e.spec.ts{% endif %}.jinja @@ -1,23 +1,22 @@ +import { Config } from '@algorandfoundation/algokit-utils' import { algorandFixture } from '@algorandfoundation/algokit-utils/testing' -import { {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Factory } from '../smart_contracts/artifacts/{{ contract_name }}/{{ contract_name.split('_')|map('capitalize')|join }}Client' -import { Account, Algodv2, Indexer } from 'algosdk' -import * as algokit from '@algorandfoundation/algokit-utils' -import { TransactionSignerAccount } from '@algorandfoundation/algokit-utils/types/account' +import { Address } from 'algosdk' +import { beforeAll, beforeEach, describe, expect, test } from 'vitest' +import { {{ contract_name.split('_')|map('capitalize')|join }}Factory } from '../artifacts/{{ contact_name }}/{{ contract_name.split('_')|map('capitalize')|join }}Client' -describe('{{ contract_name.split('_')|join(' ') }} contract', () => { +describe('{{ contract_name.split('_')|map('capitalize')|join }} contract', () => { const localnet = algorandFixture() beforeAll(() => { - algokit.Config.configure({ + Config.configure({ debug: true, // traceAll: true, }) }) beforeEach(localnet.beforeEach) - const deploy = async (account: Account & TransactionSignerAccount) => { - const factory = localnet.algorand.client.getTypedAppFactory({% include pathjoin('includes', 'contract_name_pascal.jinja') %}Factory, { - defaultSender: account.addr, - defaultSigner: account.signer, + const deploy = async (account: Address) => { + const factory = localnet.algorand.client.getTypedAppFactory({{ contract_name.split('_')|map('capitalize')|join }}Factory, { + defaultSender: account, }) const { appClient } = await factory.deploy({ onUpdate: 'append', onSchemaBreak: 'append' }) @@ -30,7 +29,7 @@ describe('{{ contract_name.split('_')|join(' ') }} contract', () => { const result = await client.send.hello({ args: { name: 'World' } }) - expect(result.return).toBe('Hello, World') + expect(result.return).toBe('Hello World') }) test('simulate says hello with correct budget consumed', async () => { @@ -42,8 +41,8 @@ describe('{{ contract_name.split('_')|join(' ') }} contract', () => { .hello({ args: { name: 'Jane' } }) .simulate() - expect(result.returns[0]).toBe('Hello, World') - expect(result.returns[1]).toBe('Hello, Jane') + expect(result.returns[0]).toBe('Hello World') + expect(result.returns[1]).toBe('Hello Jane') expect(result.simulateResponse.txnGroups[0].appBudgetConsumed).toBeLessThan(100) }) }) diff --git a/template_content/smart_contracts/{{ contract_name }}/{% if use_vitest %}contract.spec.ts{% endif %}.jinja b/template_content/smart_contracts/{{ contract_name }}/{% if use_vitest %}contract.spec.ts{% endif %}.jinja new file mode 100644 index 0000000..e7a7414 --- /dev/null +++ b/template_content/smart_contracts/{{ contract_name }}/{% if use_vitest %}contract.spec.ts{% endif %}.jinja @@ -0,0 +1,14 @@ +import { TestExecutionContext } from '@algorandfoundation/algorand-typescript-testing' +import { describe, expect, it } from 'vitest' +import { {{ contract_name.split('_')|map('capitalize')|join }} } from './contract.algo' + +describe('{{ contract_name.split('_')|map('capitalize')|join }} contract', () => { + const ctx = new TestExecutionContext() + it('Logs the returned value when sayHello is called', () => { + const contract = ctx.contract.create({{ contract_name.split('_')|map('capitalize')|join }}) + + const result = contract.hello('Sally') + + expect(result).toBe('Hello Sally') + }) +}) diff --git a/examples/generators/starter_python_smart_contract_typescript/tsconfig.json b/template_content/tsconfig.json similarity index 100% rename from examples/generators/starter_python_smart_contract_typescript/tsconfig.json rename to template_content/tsconfig.json diff --git a/template_content/{% if code_tours %}.tours{% endif %}/getting-started-with-your-algokit-project.tour.jinja b/template_content/{% if code_tours %}.tours{% endif %}/getting-started-with-your-algokit-project.tour.jinja index d5e1488..8816034 100644 --- a/template_content/{% if code_tours %}.tours{% endif %}/getting-started-with-your-algokit-project.tour.jinja +++ b/template_content/{% if code_tours %}.tours{% endif %}/getting-started-with-your-algokit-project.tour.jinja @@ -14,19 +14,24 @@ }, { "file": ".algokit.toml", - "description": "This is the main configuration file used by algokit-cli to manage the project. The default template includes a starter 'Hello World' contract that is deployed via the `algokit-utils` package (either `ts` or `py`, depending on your choice). To create a new smart contract, you can use the [`algokit generate`](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/generate.md) command and invoke a pre-bundled generator template by running `algokit generate smart-contract` (see how it is defined in the `.algokit.toml`, you can create your own generators if needed). This action will create a new folder in the `smart_contracts` directory, named after your project. Each folder contains a `contract.py` file, which is the entry point for your contract implementation, and `deploy_config.py` | `deployConfig.ts` files (depending on the language chosen for the template), that perform the deployment of the contract. Additionally you can define custom commands to run (similar to `npm` scripts), see definitions under `[project]` section in `.algokit.toml`.", + "description": "This is the main configuration file used by algokit-cli to manage the project. The default template includes a starter 'Hello World' contract that is deployed via the `algokit-utils` package. To create a new smart contract, you can use the [`algokit generate`](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/generate.md) command and invoke a pre-bundled generator template by running `algokit generate smart-contract` (see how it is defined in the `.algokit.toml`, you can create your own generators if needed). This action will create a new folder in the `smart_contracts` directory, named after your project. Each folder contains a `contract.algo.ts` file, which is the entry point for your contract implementation, and `deployConfig.ts` file, that perform the deployment of the contract. Additionally you can define custom commands to run (similar to `npm` scripts), see definitions under `[project]` section in `.algokit.toml`.", "line": 1 }, { - "file": "smart_contracts/hello_world/{% if deployment_language == 'typescript' %}deploy-config.ts{% else %}deploy_config.py{% endif %}", + "file": "smart_contracts/hello_world/deploy-config.ts", "description": "The default deployment scripts invoke a sample method on the starter contract that demonstrates how to interact with your deployed Algorand on-chain applications using the [`AlgoKit Typed Clients`](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/generate.md#1-typed-clients) feature. The invocation if deploy is aliased in `.algokit.toml` file, allowing simple deployments via `algokit project deploy` command.", "line": 32 }, - {%- if use_python_pytest %} + {%- if use_vitest %} { - "file": "tests/{% if deployment_language == 'typescript' %}{% include pathjoin('includes', 'contract_name_kebab.jinja') %}.spec.ts{% else %}{{ contract_name }}_test.py{% endif %}", - "description": "If you opted to include unit tests, the default tests provided demonstrate an example of mocking, setting up fixtures, and testing smart contract calls on an AlgoKit typed client.", - "line": {% if deployment_language == 'typescript' %}39{% else %}36{% endif %} + "file": "smart_contracts/{{ contract_name }}/contact.spec.ts", + "description": "The default tests provided demonstrate an example of setting up in-memory fast unit tests with the Algorand TypeScript testing library that mocks AVM functionality.", + "line": 5 + }, + { + "file": "smart_contracts/{{ contract_name }}/contact.e2e.spec.ts", + "description": "The default tests provided demonstrate an example of setting up an end-to-end test with fixtures, and testing smart contract calls against a LocalNet network via an AlgoKit typed client.", + "line": 7 }, {%- endif %} { @@ -34,6 +39,7 @@ "description": "Environment files are a crucial mechanism that allows you to set up the [`algokit deploy`](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/deploy.md) feature to simplify deploying your contracts in CI/CD environments (please note we still recommend careful evaluation when it comes to deployment to MainNet). Clone the file and remove the `.template` suffix to apply the changes to deployment scripts and launch configurations. The network prefix `localnet|testnet|mainnet` is primarily optimized for `algokit deploy`. The order of loading the variables is `.env.{network}` < `.env`.", "line": 2 }, + {%- if ide_vscode %} { "file": ".vscode/launch.json", "description": "Refer to the pre-bundled Visual Studio launch configurations, offering various options on how to execute the build and deployment of your smart contracts. Alternatively execute `algokit project run` to see list of available custom commands.", @@ -44,15 +50,11 @@ "description": "We highly recommend installing the recommended extensions to get the most out of this template starter project in your VSCode IDE.", "line": 3 }, + {%- endif %} { - "file": "smart_contracts/{% if deployment_language == 'python' %}__main__.py{% else %}index.ts{% endif %}", - "description": "Uncomment the following lines to enable complementary utilities that will generate artifacts required for the [AlgoKit AVM Debugger](https://github.com/algorandfoundation/algokit-avm-vscode-debugger) VSCode plugin available on the [VSCode Extension Marketplace](https://marketplace.visualstudio.com/items?itemName=algorandfoundation.algokit-avm-vscode-debugger). A new folder will be automatically created in the `.algokit` directory with source maps of all TEAL contracts in this workspace, as well as traces that will appear in a folder at the root of the workspace. You can then use the traces as entry points to trigger the debug extension. Make sure to have the `.algokit.toml` file available at the root of the workspace.", - "line": 15 - }, - { - "file": "smart_contracts/_helpers/__init__.py", - "description": "This folder contains helper scripts for contract management. These automate tasks like compiling, generating clients, and deploying. Usually, you won't need to edit these files, but advanced users can expand them for custom needs.", - "line": 1 + "file": "smart_contracts/index.ts", + "description": "Uncomment the following line to enable artifacts required for the [AlgoKit AVM Debugger](https://github.com/algorandfoundation/algokit-avm-vscode-debugger) that run for every single call rather than just failures. This VSCode plugin is available on the [VSCode Extension Marketplace](https://marketplace.visualstudio.com/items?itemName=algorandfoundation.algokit-avm-vscode-debugger) for every call. A new folder will be automatically created in the `.algokit` directory with source maps of all TEAL contracts in this workspace, as well as traces that will appear in a folder at the root of the workspace. You can then use the traces as entry points to trigger the debug extension. Make sure to have the `.algokit.toml` file available at the root of the workspace.", + "line": 13 } ] } diff --git a/template_content/{% if deployment_language == 'typescript' or use_typescript_jest %}.npmrc{% endif %} b/template_content/{% if deployment_language == 'typescript' or use_typescript_jest %}.npmrc{% endif %} deleted file mode 100644 index c42da84..0000000 --- a/template_content/{% if deployment_language == 'typescript' or use_typescript_jest %}.npmrc{% endif %} +++ /dev/null @@ -1 +0,0 @@ -engine-strict = true diff --git a/template_content/{% if deployment_language == 'typescript' or use_typescript_jest %}.prettierignore{% endif %} b/template_content/{% if deployment_language == 'typescript' or use_typescript_jest %}.prettierignore{% endif %} deleted file mode 100644 index dbda6ae..0000000 --- a/template_content/{% if deployment_language == 'typescript' or use_typescript_jest %}.prettierignore{% endif %} +++ /dev/null @@ -1,12 +0,0 @@ -# don't ever format node_modules -node_modules -# don't lint format output (make sure it's set to your correct build folder name) -dist -build -# don't format nyc coverage output -coverage -# don't format generated types -**/generated/types.d.ts -**/generated/types.ts -# don't format ide files -.idea diff --git a/template_content/{% if deployment_language == 'typescript' or use_typescript_jest %}.prettierrc.js{% endif %} b/template_content/{% if deployment_language == 'typescript' or use_typescript_jest %}.prettierrc.js{% endif %} deleted file mode 100644 index c484d0e..0000000 --- a/template_content/{% if deployment_language == 'typescript' or use_typescript_jest %}.prettierrc.js{% endif %} +++ /dev/null @@ -1,10 +0,0 @@ -module.exports = { - singleQuote: true, - jsxSingleQuote: false, - semi: false, - tabWidth: 2, - trailingComma: 'all', - printWidth: 120, - endOfLine: 'lf', - arrowParens: 'always', -} diff --git a/template_content/{% if deployment_language == 'typescript' or use_typescript_jest %}package.json{% endif %}.jinja b/template_content/{% if deployment_language == 'typescript' or use_typescript_jest %}package.json{% endif %}.jinja deleted file mode 100644 index e65dc5a..0000000 --- a/template_content/{% if deployment_language == 'typescript' or use_typescript_jest %}package.json{% endif %}.jinja +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "smart_contracts", - "version": "1.0.0", - "description": "Smart contract deployer", - "main": "index.ts", - "scripts": { - "deploy": "ts-node-dev --transpile-only --watch .env -r dotenv/config smart_contracts/index.ts", - "deploy:ci": "ts-node --transpile-only -r dotenv/config smart_contracts/index.ts", - {%- if use_typescript_jest %} - "test": "jest --coverage", - {%- endif %} - "format": "prettier --write ." - }, - "engines": { - "node": ">=20.0", - "npm": ">=9.0" - }, - "dependencies": { - "@algorandfoundation/algokit-utils": "^7.0.0", - "@algorandfoundation/algokit-utils-debug": "^1.0.2", - "algosdk": ">=2.9.0 <3.0" - }, - "devDependencies": { - "@algorandfoundation/algokit-client-generator": "^4.0.0", - {%- if use_typescript_jest %} - "@types/jest": "^29.5.11", - {%- endif %} - "dotenv": "^16.0.3", - "prettier": "^2.8.4", - {%- if use_typescript_jest %} - "ts-jest": "^29.1.1", - {%- endif %} - "ts-node-dev": "^2.0.0", - "typescript": "^4.9.5" - } -} diff --git a/template_content/{% if deployment_language == 'typescript' or use_typescript_jest %}tsconfig.json{% endif %} b/template_content/{% if deployment_language == 'typescript' or use_typescript_jest %}tsconfig.json{% endif %} deleted file mode 100644 index fc75893..0000000 --- a/template_content/{% if deployment_language == 'typescript' or use_typescript_jest %}tsconfig.json{% endif %} +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "declaration": true, - "declarationMap": true, - "sourceMap": true, - "strict": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "esModuleInterop": true, - "experimentalDecorators": true, - "emitDecoratorMetadata": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "allowJs": false, - "allowSyntheticDefaultImports": true, - "module": "CommonJS", - "moduleResolution": "Node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true - }, - "include": ["smart_contracts/**/*.ts"], - "exclude": ["node_modules", "dist", "coverage"] -} diff --git a/examples/production_python/.idea/runConfigurations/Stop_AlgoKit_LocalNet.xml b/template_content/{% if ide_jetbrains %}.idea{% endif %}/runConfigurations/Build_Smart_Contract_application.xml.jinja similarity index 79% rename from examples/production_python/.idea/runConfigurations/Stop_AlgoKit_LocalNet.xml rename to template_content/{% if ide_jetbrains %}.idea{% endif %}/runConfigurations/Build_Smart_Contract_application.xml.jinja index e510cbc..c182f6e 100644 --- a/examples/production_python/.idea/runConfigurations/Stop_AlgoKit_LocalNet.xml +++ b/template_content/{% if ide_jetbrains %}.idea{% endif %}/runConfigurations/Build_Smart_Contract_application.xml.jinja @@ -1,6 +1,6 @@ - - diff --git a/examples/generators/production_python_smart_contract_typescript/.idea/runConfigurations/Stop_AlgoKit_LocalNet.xml b/template_content/{% if ide_jetbrains %}.idea{% endif %}/runConfigurations/Build_Smart_Contract_application____LocalNet.xml.jinja similarity index 65% rename from examples/generators/production_python_smart_contract_typescript/.idea/runConfigurations/Stop_AlgoKit_LocalNet.xml rename to template_content/{% if ide_jetbrains %}.idea{% endif %}/runConfigurations/Build_Smart_Contract_application____LocalNet.xml.jinja index e510cbc..d9fcbc3 100644 --- a/examples/generators/production_python_smart_contract_typescript/.idea/runConfigurations/Stop_AlgoKit_LocalNet.xml +++ b/template_content/{% if ide_jetbrains %}.idea{% endif %}/runConfigurations/Build_Smart_Contract_application____LocalNet.xml.jinja @@ -1,6 +1,6 @@ - - diff --git a/examples/generators/production_python_smart_contract_typescript/.idea/runConfigurations/Build___Deploy_Beaker_application.xml b/template_content/{% if ide_jetbrains %}.idea{% endif %}/runConfigurations/Build___Deploy_Smart_Contract_application.xml.jinja similarity index 89% rename from examples/generators/production_python_smart_contract_typescript/.idea/runConfigurations/Build___Deploy_Beaker_application.xml rename to template_content/{% if ide_jetbrains %}.idea{% endif %}/runConfigurations/Build___Deploy_Smart_Contract_application.xml.jinja index 0091510..beca23f 100644 --- a/examples/generators/production_python_smart_contract_typescript/.idea/runConfigurations/Build___Deploy_Beaker_application.xml +++ b/template_content/{% if ide_jetbrains %}.idea{% endif %}/runConfigurations/Build___Deploy_Smart_Contract_application.xml.jinja @@ -1,6 +1,6 @@ - diff --git a/examples/generators/production_python_smart_contract_typescript/.idea/runConfigurations/Deploy_Built_Beaker_application.xml b/template_content/{% if ide_jetbrains %}.idea{% endif %}/runConfigurations/Deploy_Built_Smart_Contract_application.xml.jinja similarity index 100% rename from examples/generators/production_python_smart_contract_typescript/.idea/runConfigurations/Deploy_Built_Beaker_application.xml rename to template_content/{% if ide_jetbrains %}.idea{% endif %}/runConfigurations/Deploy_Built_Smart_Contract_application.xml.jinja diff --git a/template_content/{% if ide_vscode %}.vscode{% endif %}/extensions.json.jinja b/template_content/{% if ide_vscode %}.vscode{% endif %}/extensions.json.jinja index 06d3c69..aee6e0c 100644 --- a/template_content/{% if ide_vscode %}.vscode{% endif %}/extensions.json.jinja +++ b/template_content/{% if ide_vscode %}.vscode{% endif %}/extensions.json.jinja @@ -1,21 +1,14 @@ { "recommendations": [ - "ms-python.python", - {% if python_linter == 'ruff' -%} - "charliermarsh.ruff", - {% elif python_linter == 'flake8' -%} - "ms-python.flake8", + {% if use_linter -%} + "dbaeumer.vscode-eslint", {% endif -%} - {% if use_python_mypy -%} - "matangover.mypy", - {% endif -%} - {% if use_python_black -%} - "ms-python.black-formatter", - {% endif -%} - {% if deployment_language == 'typescript' -%} + {% if use_prettier -%} "esbenp.prettier-vscode", {% endif -%} - "tamasfe.even-better-toml", + {% if use_vitest -%} + "vitest.explorer", + {% endif -%} "editorconfig.editorconfig", "vsls-contrib.codetour", "algorandfoundation.algokit-avm-vscode-debugger" diff --git a/examples/generators/production_python_smart_contract_typescript/.vscode/launch.json b/template_content/{% if ide_vscode %}.vscode{% endif %}/launch.json similarity index 87% rename from examples/generators/production_python_smart_contract_typescript/.vscode/launch.json rename to template_content/{% if ide_vscode %}.vscode{% endif %}/launch.json index 6c40d26..093ebb1 100644 --- a/examples/generators/production_python_smart_contract_typescript/.vscode/launch.json +++ b/template_content/{% if ide_vscode %}.vscode{% endif %}/launch.json @@ -40,16 +40,17 @@ }, { "name": "Build contracts", - "type": "python", "request": "launch", - "module": "smart_contracts", - "args": ["build"], - "cwd": "${workspaceFolder}" + "runtimeExecutable": "npm", + "runtimeArgs": ["run", "build"], + "cwd": "${workspaceFolder}", + "console": "integratedTerminal", + "skipFiles": ["/**", "node_modules/**"], }, { "type": "avm", "request": "launch", - "name": "Debug TEAL via AlgoKit AVM Debugger", + "name": "Debug AVM executions", "simulateTraceFile": "${workspaceFolder}/${command:PickSimulateTraceFile}", "stopOnEntry": true } diff --git a/template_content/{% if ide_vscode %}.vscode{% endif %}/launch.json.jinja b/template_content/{% if ide_vscode %}.vscode{% endif %}/launch.json.jinja deleted file mode 100644 index 2b6ed9c..0000000 --- a/template_content/{% if ide_vscode %}.vscode{% endif %}/launch.json.jinja +++ /dev/null @@ -1,92 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - {% if deployment_language == 'python' -%} - { - "name": "Build & Deploy contracts", - "type": "python", - "request": "launch", - "module": "smart_contracts", - "cwd": "${workspaceFolder}", - "preLaunchTask": "Start AlgoKit LocalNet", - "env": { - "ALGOD_TOKEN": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "ALGOD_SERVER": "http://localhost", - "ALGOD_PORT": "4001", - "INDEXER_TOKEN": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "INDEXER_SERVER": "http://localhost", - "INDEXER_PORT": "8980" - } - }, - { - "name": "Deploy contracts", - "type": "python", - "request": "launch", - "module": "smart_contracts", - "args": ["deploy"], - "cwd": "${workspaceFolder}", - "env": { - "ALGOD_TOKEN": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "ALGOD_SERVER": "http://localhost", - "ALGOD_PORT": "4001", - "INDEXER_TOKEN": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "INDEXER_SERVER": "http://localhost", - "INDEXER_PORT": "8980" - } - }, - {% elif deployment_language == 'typescript' -%} - { - "name": "Build & Deploy contracts", - "type": "node", - "request": "launch", - "runtimeExecutable": "npm", - "runtimeArgs": ["run", "deploy"], - "cwd": "${workspaceFolder}/smart_contracts", - "console": "integratedTerminal", - "skipFiles": ["/**", "node_modules/**"], - "preLaunchTask": "Build contracts (+ LocalNet)", - "env": { - "ALGOD_TOKEN": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "ALGOD_SERVER": "http://localhost", - "ALGOD_PORT": "4001", - "INDEXER_TOKEN": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "INDEXER_SERVER": "http://localhost", - "INDEXER_PORT": "8980" - } - }, - { - "name": "Deploy contracts", - "type": "node", - "request": "launch", - "runtimeExecutable": "npm", - "runtimeArgs": ["run", "deploy"], - "cwd": "${workspaceFolder}/smart_contracts", - "console": "integratedTerminal", - "skipFiles": ["/**", "node_modules/**"], - "env": { - "ALGOD_TOKEN": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "ALGOD_SERVER": "http://localhost", - "ALGOD_PORT": "4001", - "INDEXER_TOKEN": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "INDEXER_SERVER": "http://localhost", - "INDEXER_PORT": "8980" - } - }, - {% endif -%} - { - "name": "Build contracts", - "type": "python", - "request": "launch", - "module": "smart_contracts", - "args": ["build"], - "cwd": "${workspaceFolder}" - }, - { - "type": "avm", - "request": "launch", - "name": "Debug TEAL via AlgoKit AVM Debugger", - "simulateTraceFile": "${workspaceFolder}/${command:PickSimulateTraceFile}", - "stopOnEntry": true - } - ] -} diff --git a/template_content/{% if ide_vscode %}.vscode{% endif %}/settings.json.jinja b/template_content/{% if ide_vscode %}.vscode{% endif %}/settings.json.jinja index af166ab..8d1b037 100644 --- a/template_content/{% if ide_vscode %}.vscode{% endif %}/settings.json.jinja +++ b/template_content/{% if ide_vscode %}.vscode{% endif %}/settings.json.jinja @@ -1,70 +1,26 @@ { - // General - see also /.editorconfig + "files.eol": "\n", + {% if use_prettier %} "editor.formatOnSave": true, - "files.exclude": { - "**/.git": true, - "**/.DS_Store": true, - "**/Thumbs.db": true, - ".mypy_cache": true, - ".pytest_cache": true, - ".ruff_cache": true, - "**/__pycache__": true, - ".idea": true - }, - {% if deployment_language == 'typescript' %} - // TypeScript "editor.defaultFormatter": "esbenp.prettier-vscode", - {% endif %} - // Python - "python.analysis.extraPaths": ["${workspaceFolder}/smart_contracts"], - "python.analysis.diagnosticSeverityOverrides": { - "reportMissingModuleSource": "none" - }, - "python.defaultInterpreterPath": "${workspaceFolder}/.venv", - "[python]": { - "editor.codeActionsOnSave": { - "source.fixAll": "explicit", - // Prevent default import sorting from running; Ruff will sort imports for us anyway - "source.organizeImports": "never" - }, - {% if use_python_black -%} - "editor.defaultFormatter": "ms-python.black-formatter", - {% else -%} - "editor.defaultFormatter": null, - {% endif -%} + "editor.codeActionsOnSave": { + "source.organizeImports": "explicit" }, - {% if use_python_black -%} - "black-formatter.args": ["--config=pyproject.toml"], - {% endif -%} - {% if use_python_pytest -%} - "python.testing.pytestEnabled": true, - {% endif -%} - {% if python_linter == 'flake8' -%} - "flake8.importStrategy": "fromEnvironment", - "flake8.args": ["--config=.flake8"], - {% endif -%} - {% if python_linter == 'ruff' -%} - "ruff.enable": true, - "ruff.lint.run": "onSave", - "ruff.lint.args": ["--config=pyproject.toml"], - "ruff.importStrategy": "fromEnvironment", - "ruff.fixAll": true, //lint and fix all files in workspace - "ruff.organizeImports": true, //organize imports on save - "ruff.codeAction.disableRuleComment": { - "enable": true + {% endif %} + {% if use_vitest %} + "jest.enable": false, + {% endif %} + {% if use_github_actions %} + "files.associations": { + ".github/**/*.yml": "github-actions-workflow" }, - "ruff.codeAction.fixViolation": { - "enable": true + {% endif %} + {% if use_linter %} + "eslint.enable": true, + "eslint.validate": ["typescript"], + "eslint.options": { + "extensions": [".ts"] }, - {% endif -%} - {% if use_python_mypy -%} - "python.analysis.typeCheckingMode": "off", - "mypy.configFile": "pyproject.toml", - // set to empty array to use config from project - "mypy.targets": [], - "mypy.runUsingActiveInterpreter": true, + "eslint.workingDirectories": ["./smart_contracts"] {% endif %} - // On Windows, if execution policy is set to Signed (default) then it won't be able to activate the venv - // so instead let's set it to RemoteSigned for VS Code terminal - "terminal.integrated.shellArgs.windows": ["-ExecutionPolicy", "RemoteSigned"], } diff --git a/template_content/{% if ide_vscode %}.vscode{% endif %}/tasks.json b/template_content/{% if ide_vscode %}.vscode{% endif %}/tasks.json index eb1e767..55310ab 100644 --- a/template_content/{% if ide_vscode %}.vscode{% endif %}/tasks.json +++ b/template_content/{% if ide_vscode %}.vscode{% endif %}/tasks.json @@ -3,11 +3,9 @@ "tasks": [ { "label": "Build contracts", - "command": "${workspaceFolder}/.venv/bin/python", - "windows": { - "command": "${workspaceFolder}/.venv/Scripts/python.exe" - }, - "args": ["-m", "smart_contracts", "build"], + "type": "npm", + "script": "build", + "path": "${workspaceFolder}", "options": { "cwd": "${workspaceFolder}" }, @@ -19,11 +17,9 @@ }, { "label": "Build contracts (+ LocalNet)", - "command": "${workspaceFolder}/.venv/bin/python", - "windows": { - "command": "${workspaceFolder}/.venv/Scripts/python.exe" - }, - "args": ["-m", "smart_contracts", "build"], + "type": "npm", + "script": "build", + "path": "${workspaceFolder}", "options": { "cwd": "${workspaceFolder}" }, @@ -63,13 +59,7 @@ { "label": "Analyze TEAL contracts with AlgoKit Tealer integration", "command": "algokit", - "args": [ - "task", - "analyze", - "${workspaceFolder}/.algokit", - "--recursive", - "--force" - ], + "args": ["task", "analyze", "${workspaceFolder}/.algokit", "--recursive", "--force"], "options": { "cwd": "${workspaceFolder}" }, diff --git a/template_content/{% if python_linter == 'flake8' %}.flake8{% endif %} b/template_content/{% if python_linter == 'flake8' %}.flake8{% endif %} deleted file mode 100644 index eeaac64..0000000 --- a/template_content/{% if python_linter == 'flake8' %}.flake8{% endif %} +++ /dev/null @@ -1,4 +0,0 @@ -[flake8] -max-line-length = 88 -select = B,C,E,F,W,T4,B9 -extend-ignore = E203 diff --git a/template_content/{% if use_github_actions %}.github{% endif %}/workflows/{% include pathjoin('includes', 'project_name_kebab.jinja') %}-cd.yaml.jinja b/template_content/{% if use_github_actions %}.github{% endif %}/workflows/{% include pathjoin('includes', 'project_name_kebab.jinja') %}-cd.yaml.jinja index eabe343..4253d42 100644 --- a/template_content/{% if use_github_actions %}.github{% endif %}/workflows/{% include pathjoin('includes', 'project_name_kebab.jinja') %}-cd.yaml.jinja +++ b/template_content/{% if use_github_actions %}.github{% endif %}/workflows/{% include pathjoin('includes', 'project_name_kebab.jinja') %}-cd.yaml.jinja @@ -23,14 +23,11 @@ jobs: - name: Checkout source code uses: actions/checkout@v4 - - name: Install poetry - run: pipx install poetry - - - name: Set up Python 3.12 - uses: actions/setup-python@v5 + - name: Use Node.js lts + uses: actions/setup-node@v3 with: - python-version: "3.12" - cache: "poetry" + node-version: lts + cache: 'npm' - name: Install algokit run: pipx install algokit diff --git a/template_content/{% if use_github_actions %}.github{% endif %}/workflows/{% include pathjoin('includes', 'project_name_kebab.jinja') %}-ci.yaml.jinja b/template_content/{% if use_github_actions %}.github{% endif %}/workflows/{% include pathjoin('includes', 'project_name_kebab.jinja') %}-ci.yaml.jinja index b1456de..ca08163 100644 --- a/template_content/{% if use_github_actions %}.github{% endif %}/workflows/{% include pathjoin('includes', 'project_name_kebab.jinja') %}-ci.yaml.jinja +++ b/template_content/{% if use_github_actions %}.github{% endif %}/workflows/{% include pathjoin('includes', 'project_name_kebab.jinja') %}-ci.yaml.jinja @@ -14,8 +14,11 @@ jobs: - name: Checkout source code uses: actions/checkout@v4 - - name: Install poetry - run: pipx install poetry + - name: Use Node.js lts + uses: actions/setup-node@v3 + with: + node-version: lts + cache: 'npm' - name: Set up Python 3.12 uses: actions/setup-python@v5 @@ -26,6 +29,9 @@ jobs: - name: Install algokit run: pipx install algokit + - name: Install puya compiler + run: pipx install puya + - name: Start LocalNet run: algokit localnet start @@ -38,17 +44,23 @@ jobs: # set git user and email as test invoke git git config --global user.email "actions@github.com" && git config --global user.name "github-actions" - - name: Audit python dependencies +{% if use_audit %} + - name: Audit dependencies run: algokit project run audit {% if use_workspace %}--project-name '{{ project_name }}'{% endif %} +{% endif %} - - name: Lint and format python dependencies +{% if use_linter %} + - name: Lint and format run: algokit project run lint {% if use_workspace %}--project-name '{{ project_name }}'{% endif %} +{% endif %} +{% if use_vitest %} - name: Run tests shell: bash run: | set -o pipefail algokit project run test {% if use_workspace %}--project-name '{{ project_name }}'{% endif %} +{% endif %} - name: Build smart contracts run: algokit project run build {% if use_workspace %}--project-name '{{ project_name }}'{% endif %} diff --git a/template_content/{% if use_pre_commit %}.pre-commit-config.yaml{% endif %}.jinja b/template_content/{% if use_pre_commit %}.pre-commit-config.yaml{% endif %}.jinja index 3fcc8b7..4ddbeb2 100644 --- a/template_content/{% if use_pre_commit %}.pre-commit-config.yaml{% endif %}.jinja +++ b/template_content/{% if use_pre_commit %}.pre-commit-config.yaml{% endif %}.jinja @@ -1,40 +1,29 @@ repos: - repo: local hooks: - {% if use_python_black %} - - id: black - name: black - description: "Black: The uncompromising Python code formatter" - entry: poetry run black - language: system - minimum_pre_commit_version: 2.9.2 - require_serial: true - types_or: [ python, pyi ] + {% if use_prettier %} + - repo: local + hooks: + - id: prettier + name: Prettier + entry: npm run format + language: system {% endif %} - {% if python_linter == 'ruff' %} - - id: ruff - name: ruff - description: "Run 'ruff' for extremely fast Python linting" - entry: poetry run ruff - language: system - types: [ python ] - args: [ "check", "--fix" ] - require_serial: false - additional_dependencies: [ ] - minimum_pre_commit_version: '0' - files: '^(smart_contracts|tests)/' + {% if use_linter == 'ruff' %} + - repo: local + hooks: + - id: eslint + name: ESLint + entry: npm run lint + language: system {% endif %} - {% if use_python_mypy %} - - id: mypy - name: mypy - description: '`mypy` will check Python types for correctness' - entry: poetry run mypy - language: system - types_or: [ python, pyi ] - require_serial: true - additional_dependencies: [ ] - minimum_pre_commit_version: '2.9.2' - files: '^(smart_contracts|tests)/' + {% if use_vitest %} + - repo: local + hooks: + - id: vitest + name: Vitest + entry: npm run test + language: system {% endif %} # # Uncomment to enable TEAL static analysis using Tealer package # - id: tealer diff --git a/examples/generators/starter_python_smart_contract_typescript/.prettierignore b/template_content/{% if use_prettier %}.prettierignore{% endif %} similarity index 100% rename from examples/generators/starter_python_smart_contract_typescript/.prettierignore rename to template_content/{% if use_prettier %}.prettierignore{% endif %} diff --git a/examples/generators/starter_python_smart_contract_typescript/.prettierrc.js b/template_content/{% if use_prettier %}.prettierrc.js{% endif %} similarity index 100% rename from examples/generators/starter_python_smart_contract_typescript/.prettierrc.js rename to template_content/{% if use_prettier %}.prettierrc.js{% endif %} diff --git a/template_content/{% if use_python_pytest %}tests{% endif %}/__init__.py b/template_content/{% if use_python_pytest %}tests{% endif %}/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/template_content/{% if use_python_pytest %}tests{% endif %}/conftest.py b/template_content/{% if use_python_pytest %}tests{% endif %}/conftest.py deleted file mode 100644 index aec2485..0000000 --- a/template_content/{% if use_python_pytest %}tests{% endif %}/conftest.py +++ /dev/null @@ -1,26 +0,0 @@ -import pytest -from algokit_utils import ( - get_algod_client, - get_default_localnet_config, - get_indexer_client, -) -from algosdk.v2client.algod import AlgodClient -from algosdk.v2client.indexer import IndexerClient - -# Uncomment if you want to load network specific or generic .env file -# @pytest.fixture(autouse=True, scope="session") -# def environment_fixture() -> None: -# env_path = Path(__file__).parent.parent / ".env" -# load_dotenv(env_path) - - -@pytest.fixture(scope="session") -def algod_client() -> AlgodClient: - # by default we are using localnet algod - client = get_algod_client(get_default_localnet_config("algod")) - return client - - -@pytest.fixture(scope="session") -def indexer_client() -> IndexerClient: - return get_indexer_client(get_default_localnet_config("indexer")) diff --git a/template_content/{% if use_python_pytest %}tests{% endif %}/{% if use_python_pytest %}{{ contract_name }}_client_test.py{% endif %}.jinja b/template_content/{% if use_python_pytest %}tests{% endif %}/{% if use_python_pytest %}{{ contract_name }}_client_test.py{% endif %}.jinja deleted file mode 100644 index e3b5098..0000000 --- a/template_content/{% if use_python_pytest %}tests{% endif %}/{% if use_python_pytest %}{{ contract_name }}_client_test.py{% endif %}.jinja +++ /dev/null @@ -1,48 +0,0 @@ -import algokit_utils -import pytest -from algokit_utils import get_localnet_default_account -from algokit_utils.config import config -from algosdk.v2client.algod import AlgodClient -from algosdk.v2client.indexer import IndexerClient - -from smart_contracts.artifacts.{{ contract_name }}.{{ contract_name }}_client import {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client - - -@pytest.fixture(scope="session") -def {{ contract_name }}_client( - algod_client: AlgodClient, indexer_client: IndexerClient -) -> {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client: - config.configure( - debug=True, - # trace_all=True, - ) - - client = {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client( - algod_client, - creator=get_localnet_default_account(algod_client), - indexer_client=indexer_client, - ) - - client.deploy( - on_schema_break=algokit_utils.OnSchemaBreak.AppendApp, - on_update=algokit_utils.OnUpdate.AppendApp, - ) - return client - - -def test_says_hello({{ contract_name }}_client: {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client) -> None: - result = {{ contract_name }}_client.hello(name="World") - - assert result.return_value == "Hello, World" - - -def test_simulate_says_hello_with_correct_budget_consumed( - {{ contract_name }}_client: {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client, algod_client: AlgodClient -) -> None: - result = ( - {{ contract_name }}_client.compose().hello(name="World").hello(name="Jane").simulate() - ) - - assert result.abi_results[0].return_value == "Hello, World" - assert result.abi_results[1].return_value == "Hello, Jane" - assert result.simulate_response["txn-groups"][0]["app-budget-consumed"] < 100 diff --git a/template_content/{% if use_python_pytest %}tests{% endif %}/{% if use_python_pytest %}{{ contract_name }}_test.py{% endif %}.jinja b/template_content/{% if use_python_pytest %}tests{% endif %}/{% if use_python_pytest %}{{ contract_name }}_test.py{% endif %}.jinja deleted file mode 100644 index a8faaff..0000000 --- a/template_content/{% if use_python_pytest %}tests{% endif %}/{% if use_python_pytest %}{{ contract_name }}_test.py{% endif %}.jinja +++ /dev/null @@ -1,24 +0,0 @@ -from collections.abc import Iterator - -import pytest -from algopy_testing import AlgopyTestContext, algopy_testing_context - -from smart_contracts.{{ contract_name }}.contract import {{ contract_name.split('_')|map('capitalize')|join }} - - -@pytest.fixture() -def context() -> Iterator[AlgopyTestContext]: - with algopy_testing_context() as ctx: - yield ctx - - -def test_hello(context: AlgopyTestContext) -> None: - # Arrange - dummy_input = context.any.string(length=10) - contract = {{ contract_name.split('_')|map('capitalize')|join }}() - - # Act - output = contract.hello(dummy_input) - - # Assert - assert output == f"Hello, {dummy_input}" diff --git a/template_content/{% if use_typescript_jest %}jest.config.ts{% endif %} b/template_content/{% if use_typescript_jest %}jest.config.ts{% endif %} deleted file mode 100644 index 381e1e0..0000000 --- a/template_content/{% if use_typescript_jest %}jest.config.ts{% endif %} +++ /dev/null @@ -1,16 +0,0 @@ -/* - * For a detailed explanation regarding each configuration property and type check, visit: - * https://jestjs.io/docs/configuration - */ -import type { Config } from 'jest' - -const config: Config = { - preset: 'ts-jest', - verbose: true, - transform: { - '^.+\\.tsx?$': 'ts-jest', - }, - testPathIgnorePatterns: ['node_modules', '.venv', 'coverage'], - testTimeout: 10000, -} -export default config diff --git a/template_content/{% if use_vitest %}tsconfig.test.json{% endif %} b/template_content/{% if use_vitest %}tsconfig.test.json{% endif %} new file mode 100644 index 0000000..38d2911 --- /dev/null +++ b/template_content/{% if use_vitest %}tsconfig.test.json{% endif %} @@ -0,0 +1,14 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "compilerOptions": { + "noEmit": true, + "target": "ES2023", + "module": "ESNext", + "lib": ["ES2023"], + "moduleResolution": "Bundler", + "resolveJsonModule": true, + "esModuleInterop": true + }, + "include": ["**/*.ts", "**/*.mts"], + "exclude": ["node_modules"] +} diff --git a/template_content/{% if use_vitest %}vitest.config.mts{% endif %} b/template_content/{% if use_vitest %}vitest.config.mts{% endif %} new file mode 100644 index 0000000..ff8fd56 --- /dev/null +++ b/template_content/{% if use_vitest %}vitest.config.mts{% endif %} @@ -0,0 +1,26 @@ +import { puyaTsTransformer } from '@algorandfoundation/algorand-typescript-testing/test-transformer' +import typescript from '@rollup/plugin-typescript' +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + esbuild: {}, + test: { + server: { + deps: { + inline: ['@algorandfoundation/algorand-typescript-testing'], + }, + }, + testTimeout: 10000, + coverage: { + provider: 'v8', + }, + }, + plugins: [ + typescript({ + tsconfig: './tsconfig.test.json', + transformers: { + before: [puyaTsTransformer], + }, + }), + ], +}) diff --git a/tests/test_generators.py b/tests/test_generators.py deleted file mode 100644 index c638b3f..0000000 --- a/tests/test_generators.py +++ /dev/null @@ -1,246 +0,0 @@ -import re -import shutil -import subprocess -import tempfile -from collections.abc import Iterator -from pathlib import Path - -import pytest -import yaml - -commit_pattern = re.compile(r"^_commit: .*", flags=re.MULTILINE) -src_path_pattern = re.compile(r"_src_path: .*") -tests_path = Path(__file__).parent -root = tests_path.parent -generated_folder = "examples/generators" -generated_root = root / generated_folder -DEFAULT_PARAMETERS = { - "author_name": "None", - "author_email": "None", -} -config_path = Path(__file__).parent.parent / "pyproject.toml" -BUILD_ARGS = ["algokit", "project", "run", "build"] -BUILD_SINGLE_CONTRACT_ARGS = ["algokit", "project", "run", "build", "--", "hello_world"] -TEST_ARGS = ["algokit", "project", "run", "test"] -LINT_ARGS = ["algokit", "project", "run", "lint"] -DEPLOY_ARGS = ["algokit", "project", "deploy", "localnet"] -DEPLOY_SINGLE_CONTRACT_ARGS = [ - "algokit", - "project", - "deploy", - "localnet", - "--", - "hello_world", -] - - -def _load_copier_yaml(path: Path) -> dict[str, str | bool | dict]: - with path.open("r", encoding="utf-8") as stream: - return yaml.safe_load(stream) - - -@pytest.fixture(autouse=True, scope="module") -def working_dir() -> Iterator[Path]: - with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as temp: - working_dir = Path(temp) / "template" - working_generated_root = working_dir / generated_folder - shutil.copytree(root, working_dir) - subprocess.run(["git", "add", "-A"], cwd=working_dir) - subprocess.run( - ["git", "commit", "-m", "draft changes", "--no-verify"], cwd=working_dir - ) - - yield working_dir - - for src_dir in working_generated_root.iterdir(): - if not src_dir.is_dir(): - continue - - dest_dir = generated_root / src_dir.stem - shutil.rmtree(dest_dir, ignore_errors=True) - shutil.copytree( - src_dir, - dest_dir, - dirs_exist_ok=True, - ignore=shutil.ignore_patterns( - ".*_cache", ".venv", "__pycache__", "node_modules" - ), - ) - - -def run_init( - working_dir: Path, - test_name: str, - *args: str, - template_url: str | None = None, - template_branch: str | None = None, - answers: dict[str, str] | None = None, -) -> subprocess.CompletedProcess: - copy_to = working_dir / generated_folder / test_name - shutil.rmtree(copy_to, ignore_errors=True) - if template_url is None: - template_url = str(working_dir) - - if template_branch is None: - git_output = subprocess.run( - ["git", "rev-parse", "--abbrev-ref", "HEAD"], - cwd=working_dir, - stdout=subprocess.PIPE, - ) - template_branch = git_output.stdout.decode("utf-8").strip() - - init_args = [ - "algokit", - "--verbose", - "init", - "--name", - str(copy_to.stem), - "--template-url", - template_url, - "--UNSAFE-SECURITY-accept-template-url", - "--defaults", - "--no-ide", - "--no-git", - "--no-workspace", - ] - answers = {**DEFAULT_PARAMETERS, **(answers or {})} - - for question, answer in answers.items(): - init_args.extend(["-a", question, answer]) - if template_branch: - init_args.extend(["--template-url-ref", template_branch]) - init_args.extend(args) - - result = subprocess.run( - init_args, - input="y", # acknowledge that input is not a tty - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - text=True, - cwd=copy_to.parent, - ) - - return result - - -def check_codebase(working_dir: Path, test_name: str) -> subprocess.CompletedProcess: - copy_to = working_dir / generated_folder / test_name - - # if successful, normalize .copier-answers.yml to make observing diffs easier - copier_answers = Path(copy_to / ".algokit" / ".copier-answers.yml") - content = copier_answers.read_text("utf-8") - content = commit_pattern.sub("_commit: ", content) - content = src_path_pattern.sub("_src_path: ", content) - copier_answers.write_text(content, "utf-8") - - check_args = [BUILD_ARGS, BUILD_SINGLE_CONTRACT_ARGS] - - processed_questions = _load_copier_yaml(copier_answers) - if processed_questions["preset_name"] == "production": - check_args += [LINT_ARGS, TEST_ARGS, DEPLOY_SINGLE_CONTRACT_ARGS, DEPLOY_ARGS] - - for check_arg in check_args: - result = subprocess.run( - check_arg, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - text=True, - cwd=copy_to, - ) - if result.returncode: - break - - return result - - -def run_generator( - working_dir: Path, - test_name: str, - generator_name: str, - answers: dict[str, str] | None = None, -) -> subprocess.CompletedProcess: - copy_to = working_dir / generated_folder / test_name - - init_args = [ - "algokit", - "--verbose", - "generate", - str(generator_name), - ] - - if answers: - for question, answer in answers.items(): - init_args.extend(["-a", question, answer]) - - result = subprocess.run( - init_args, - input="y", # acknowledge that input is not a tty - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - text=True, - cwd=copy_to.absolute(), - ) - - return result - - -@pytest.mark.parametrize("language", ["python", "typescript"]) -def test_smart_contract_generator_default_starter_preset( - language: str, working_dir: Path -) -> None: - test_name = f"starter_python_smart_contract_{language}" - - response = run_init( - working_dir, - test_name, - answers={ - "preset_name": "starter", - "deployment_language": language, - }, - ) - assert response.returncode == 0, response.stdout - - response = run_generator( - working_dir, - test_name, - "smart-contract", - { - "contract_name": "cool_contract", - "deployment_language": language, - }, - ) - assert response.returncode == 0, response.stdout - - response = check_codebase(working_dir, test_name) - assert response.returncode == 0, response.stdout - - -@pytest.mark.parametrize("language", ["python", "typescript"]) -def test_smart_contract_generator_default_production_preset( - language: str, working_dir: Path -) -> None: - test_name = f"production_python_smart_contract_{language}" - - response = run_init( - working_dir, - test_name, - answers={ - "preset_name": "production", - "deployment_language": language, - }, - ) - assert response.returncode == 0, response.stdout - - response = run_generator( - working_dir, - test_name, - "smart-contract", - { - "contract_name": "cool_contract", - "deployment_language": language, - }, - ) - assert response.returncode == 0, response.stdout - - response = check_codebase(working_dir, test_name) - assert response.returncode == 0, response.stdout diff --git a/tests/test_templates.py b/tests/test_templates.py index b3be18a..9dbe801 100644 --- a/tests/test_templates.py +++ b/tests/test_templates.py @@ -94,7 +94,6 @@ def run_init( "--no-workspace", ] answers = {**DEFAULT_PARAMETERS, **(answers or {})} - answers["deployment_language"] = "python" for question, answer in answers.items(): init_args.extend(["-a", question, answer]) @@ -163,7 +162,7 @@ def run_init_kwargs( working_dir: Path, **kwargs: str | bool ) -> subprocess.CompletedProcess: answers = {k: str(v) for k, v in kwargs.items()} - name_suffix = "_".join(f"{v}_python" for _, v in answers.items()) + name_suffix = "_".join(f"{v}" for _, v in answers.items()) return run_init(working_dir, f"{name_suffix}", answers=answers)