diff --git a/copier.yaml b/copier.yaml index 962dc64..3c2055f 100644 --- a/copier.yaml +++ b/copier.yaml @@ -30,11 +30,13 @@ author_name: type: str help: Package author name placeholder: "Your Name" + default: "Your Name" author_email: type: str help: Package author email placeholder: "your@email.tld" + default: "your@email.tld" ide_vscode: type: bool @@ -55,9 +57,33 @@ deployment_language: TypeScript: "typescript" default: "python" +use_python_pytest: + type: bool + when: false + help: Do you want to include unit tests (via pytest)? + # deployment_language is empty when using the default_language + default: |- + {% if deployment_language|length == 0 or deployment_language == 'python' -%} + yes + {%- else -%} + no + {%- endif %} + +use_typescript_jest: + type: bool + when: false + help: Do you want to include unit tests (via jest)? + default: |- + {% if deployment_language == 'typescript' -%} + yes + {%- else -%} + no + {%- endif %} + python_linter: type: str help: Do you want to use a Python linter? + when: false choices: Ruff: "ruff" Flake8: "flake8" @@ -67,39 +93,40 @@ python_linter: use_python_black: type: bool + when: false help: Do you want to use a Python formatter (via Black)? default: yes use_python_mypy: type: bool + when: false help: Do you want to use a Python type checker (via mypy)? default: |- yes -use_python_pytest: - type: bool - help: Do you want to include unit tests (via pytest)? - default: yes - use_python_pip_audit: type: bool + when: false help: Do you want to include Python dependency vulnerability scanning (via pip-audit)? default: yes use_github_actions: type: bool + when: false help: Do you want to include Github Actions workflows for build and testnet deployment? default: |- yes use_pre_commit: type: bool + when: false help: Do you want to include pre-commit for linting, type checking and formatting? default: |- yes use_dispenser: type: bool + when: false help: Do you want to fund your deployment account using an optional dispenser account? default: no diff --git a/includes/contract_name_kebab.jinja b/includes/contract_name_kebab.jinja new file mode 100644 index 0000000..6950548 --- /dev/null +++ b/includes/contract_name_kebab.jinja @@ -0,0 +1 @@ +{{- contract_name.split('_')|join('-') -}} diff --git a/includes/contract_name_pascal.jinja b/includes/contract_name_pascal.jinja new file mode 100644 index 0000000..e0f3c4d --- /dev/null +++ b/includes/contract_name_pascal.jinja @@ -0,0 +1 @@ +{{- contract_name.split('_')|map('capitalize')|join -}} diff --git a/template_content/.algokit.toml.jinja b/template_content/.algokit.toml.jinja index 786275c..29ab5a9 100644 --- a/template_content/.algokit.toml.jinja +++ b/template_content/.algokit.toml.jinja @@ -1,5 +1,5 @@ [algokit] -min_version = "v1.7.3" +min_version = "v1.8.0" [deploy] {%- if deployment_language == 'python' %} 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 index 83b938b..ab5ac39 100644 --- 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 @@ -5,4 +5,4 @@ from puyapy.arc4 import String, abimethod class {{ contract_name.split('_')|map('capitalize')|join }}(ARC4Contract): @abimethod() def hello(self, name: String) -> String: - return String.encode(Bytes(b"Hello ") + name.decode()) + return String.encode(Bytes(b"Hello, ") + name.decode()) diff --git a/template_content/.gitignore.jinja b/template_content/.gitignore.jinja index 832924c..4a926bb 100644 --- a/template_content/.gitignore.jinja +++ b/template_content/.gitignore.jinja @@ -50,6 +50,7 @@ coverage.xml .hypothesis/ .pytest_cache/ cover/ +coverage/ # Translations *.mo @@ -172,3 +173,6 @@ cython_debug/ # NPM node_modules + +# AlgoKit +debug_traces/ diff --git a/template_content/README.md.jinja b/template_content/README.md.jinja index 341120b..d8db073 100644 --- a/template_content/README.md.jinja +++ b/template_content/README.md.jinja @@ -56,6 +56,19 @@ This project has been generated using AlgoKit. See below for default getting sta 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. +### 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. + +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). + #### 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 diff --git a/template_content/pyproject.toml.jinja b/template_content/pyproject.toml.jinja index 4febe86..150304c 100644 --- a/template_content/pyproject.toml.jinja +++ b/template_content/pyproject.toml.jinja @@ -7,9 +7,9 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.12" -algokit-utils = "^2.0.1" +algokit-utils = "^2.2.0" python-dotenv = "^1.0.0" -puya = "^0.1.3" +puya = "^0.2.0" [tool.poetry.group.dev.dependencies] {% if use_python_black -%} diff --git a/template_content/smart_contracts/__main__.py.jinja b/template_content/smart_contracts/__main__.py.jinja index 0ab813e..c94b3f3 100644 --- a/template_content/smart_contracts/__main__.py.jinja +++ b/template_content/smart_contracts/__main__.py.jinja @@ -5,13 +5,16 @@ from pathlib import Path from dotenv import load_dotenv from smart_contracts.config import contracts -{% if deployment_language == 'python' -%} from smart_contracts.helpers.build import build +{% if deployment_language == 'python' -%} from smart_contracts.helpers.deploy import deploy -{%- elif deployment_language == 'typescript' -%} -from smart_contracts.helpers.build import build -{%- endif %} +# 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" ) 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 4f18d4d..af40ab4 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 @@ -3,8 +3,13 @@ import * as path from 'path' import { consoleLogger } from '@algorandfoundation/algokit-utils/types/logging' import * as algokit from '@algorandfoundation/algokit-utils' +// 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, }) // base directory diff --git a/template_content/smart_contracts/{{ contract_name }}/contract.py.jinja b/template_content/smart_contracts/{{ contract_name }}/contract.py.jinja index 83b938b..ab5ac39 100644 --- a/template_content/smart_contracts/{{ contract_name }}/contract.py.jinja +++ b/template_content/smart_contracts/{{ contract_name }}/contract.py.jinja @@ -5,4 +5,4 @@ from puyapy.arc4 import String, abimethod class {{ contract_name.split('_')|map('capitalize')|join }}(ARC4Contract): @abimethod() def hello(self, name: String) -> String: - return String.encode(Bytes(b"Hello ") + name.decode()) + return String.encode(Bytes(b"Hello, ") + name.decode()) 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 index 7d4017a..61612db 100644 --- 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 @@ -15,14 +15,15 @@ def deploy( deployer: algokit_utils.Account, ) -> None: from smart_contracts.artifacts.{{ contract_name }}.client import ( - {{ contract_name.split('_')|map('capitalize')|join }}Client, + {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client, ) - app_client = {{ contract_name.split('_')|map('capitalize')|join }}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, 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 }}/{% if deployment_language == 'typescript' %}deploy-config.ts{% endif %}.jinja index e8c272e..b5ff685 100644 --- a/template_content/smart_contracts/{{ contract_name }}/{% if deployment_language == 'typescript' %}deploy-config.ts{% endif %}.jinja +++ b/template_content/smart_contracts/{{ contract_name }}/{% if deployment_language == 'typescript' %}deploy-config.ts{% endif %}.jinja @@ -16,7 +16,7 @@ export async function deploy() { }, algod, ) - const appClient = new {{ contract_name.split('_')|map('capitalize')|join }}Client( + const appClient = new {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client( { resolveBy: 'creatorAndName', findExistingUsing: indexer, diff --git a/template_content/{% if deployment_language == 'typescript' %}.prettierignore{% endif %} b/template_content/{% if deployment_language == 'typescript' or use_typescript_jest %}.prettierignore{% endif %} similarity index 100% rename from template_content/{% if deployment_language == 'typescript' %}.prettierignore{% endif %} rename to template_content/{% if deployment_language == 'typescript' or use_typescript_jest %}.prettierignore{% endif %} diff --git a/template_content/{% if deployment_language == 'typescript' %}.prettierrc.js{% endif %} b/template_content/{% if deployment_language == 'typescript' or use_typescript_jest %}.prettierrc.js{% endif %} similarity index 100% rename from template_content/{% if deployment_language == 'typescript' %}.prettierrc.js{% endif %} rename to template_content/{% if deployment_language == 'typescript' or use_typescript_jest %}.prettierrc.js{% endif %} 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 new file mode 100644 index 0000000..360bdae --- /dev/null +++ b/template_content/{% if deployment_language == 'typescript' or use_typescript_jest %}package.json{% endif %}.jinja @@ -0,0 +1,33 @@ +{ + "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": ">=18.0" + }, + "dependencies": { + "@algorandfoundation/algokit-utils": "^5.1.0", + "algosdk": "^2.5.0" + }, + "devDependencies": { + {%- 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 %} new file mode 100644 index 0000000..7c76204 --- /dev/null +++ b/template_content/{% if deployment_language == 'typescript' or use_typescript_jest %}tsconfig.json{% endif %} @@ -0,0 +1,24 @@ +{ + "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, + "moduleResolution": "Node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true + }, + "include": ["src/**/*.ts"], + "exclude": ["node_modules", "dist", "coverage"] +} 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 6ef4824..8a8c996 100644 --- a/template_content/{% if ide_vscode %}.vscode{% endif %}/extensions.json.jinja +++ b/template_content/{% if ide_vscode %}.vscode{% endif %}/extensions.json.jinja @@ -16,6 +16,7 @@ "esbenp.prettier-vscode", {% endif -%} "tamasfe.even-better-toml", - "editorconfig.editorconfig" + "editorconfig.editorconfig", + "algorandfoundation.algokit-avm-vscode-debugger" ] } diff --git a/template_content/{% if ide_vscode %}.vscode{% endif %}/launch.json.jinja b/template_content/{% if ide_vscode %}.vscode{% endif %}/launch.json.jinja index e4ffc92..c2d30bd 100644 --- a/template_content/{% if ide_vscode %}.vscode{% endif %}/launch.json.jinja +++ b/template_content/{% if ide_vscode %}.vscode{% endif %}/launch.json.jinja @@ -52,6 +52,13 @@ "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 use_python_pytest %}tests{% endif %}/conftest.py b/template_content/{% if use_python_pytest %}tests{% endif %}/conftest.py index 06a89eb..b0622e7 100644 --- a/template_content/{% if use_python_pytest %}tests{% endif %}/conftest.py +++ b/template_content/{% if use_python_pytest %}tests{% endif %}/conftest.py @@ -3,9 +3,11 @@ import pytest from algokit_utils import ( get_algod_client, + get_indexer_client, is_localnet, ) from algosdk.v2client.algod import AlgodClient +from algosdk.v2client.indexer import IndexerClient from dotenv import load_dotenv @@ -23,3 +25,8 @@ def algod_client() -> AlgodClient: # included here to prevent accidentally running against other networks assert is_localnet(client) return client + + +@pytest.fixture(scope="session") +def indexer_client() -> IndexerClient: + return get_indexer_client() 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 index 62bf2ff..bbd585a 100644 --- 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 @@ -1,32 +1,48 @@ 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 }}.client import {{ contract_name.split('_')|map('capitalize')|join }}Client +from smart_contracts.artifacts.{{ 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 -) -> {{ contract_name.split('_')|map('capitalize')|join }}Client: - client = {{ contract_name.split('_')|map('capitalize')|join }}Client( +) -> {% 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.ReplaceApp, - on_update=algokit_utils.OnUpdate.UpdateApp, - allow_delete=True, - allow_update=True, + on_schema_break=algokit_utils.OnSchemaBreak.AppendApp, + on_update=algokit_utils.OnUpdate.AppendApp, ) return client -def test_says_hello({{ contract_name }}_client: {{ contract_name.split('_')|map('capitalize')|join }}Client) -> None: +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_typescript_jest %}jest.config.ts{% endif %} b/template_content/{% if use_typescript_jest %}jest.config.ts{% endif %} new file mode 100644 index 0000000..381e1e0 --- /dev/null +++ b/template_content/{% if use_typescript_jest %}jest.config.ts{% endif %} @@ -0,0 +1,16 @@ +/* + * 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_typescript_jest %}tests{% endif %}/{% if use_typescript_jest %}{% include pathjoin('includes', 'contract_name_kebab.jinja') %}.spec.ts{% endif %}.jinja b/template_content/{% if use_typescript_jest %}tests{% endif %}/{% if use_typescript_jest %}{% include pathjoin('includes', 'contract_name_kebab.jinja') %}.spec.ts{% endif %}.jinja new file mode 100644 index 0000000..25c4aa5 --- /dev/null +++ b/template_content/{% if use_typescript_jest %}tests{% endif %}/{% if use_typescript_jest %}{% include pathjoin('includes', 'contract_name_kebab.jinja') %}.spec.ts{% endif %}.jinja @@ -0,0 +1,51 @@ +import { algorandFixture } from '@algorandfoundation/algokit-utils/testing' +import { {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client } from '../smart_contracts/artifacts/{{ contract_name }}/client' +import { Account, Algodv2, Indexer } from 'algosdk' +import * as algokit from '@algorandfoundation/algokit-utils' + +describe('{{ contract_name.split('_')|join(' ') }} contract', () => { + const localnet = algorandFixture() + beforeAll(() => { + algokit.Config.configure({ + debug: true, + // traceAll: true, + }) + }) + beforeEach(localnet.beforeEach) + + const deploy = async (account: Account, algod: Algodv2, indexer: Indexer) => { + const client = new {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client( + { + resolveBy: 'creatorAndName', + findExistingUsing: indexer, + sender: account, + creatorAddress: account.addr, + }, + algod, + ) + await client.deploy({ + onSchemaBreak: 'append', + onUpdate: 'append', + }) + return { client } + } + + test('says hello', async () => { + const { algod, indexer, testAccount } = localnet.context + const { client } = await deploy(testAccount, algod, indexer) + + const result = await client.hello({ name: 'World' }) + + expect(result.return).toBe('Hello, World') + }) + + test('simulate says hello with correct budget consumed', async () => { + const { algod, indexer, testAccount } = localnet.context + const { client } = await deploy(testAccount, algod, indexer) + const result = await client.compose().hello({ name: 'World' }).hello({ name: 'Jane' }).simulate() + + expect(result.methodResults[0].returnValue).toBe('Hello, World') + expect(result.methodResults[1].returnValue).toBe('Hello, Jane') + expect(result.simulateResponse.txnGroups[0].appBudgetConsumed).toBeLessThan(100) + }) +}) diff --git a/tests/test_templates.py b/tests/test_templates.py index d76892e..16cc4ee 100644 --- a/tests/test_templates.py +++ b/tests/test_templates.py @@ -200,15 +200,3 @@ def get_questions_from_copier_yaml( elif details_type == "bool": yield question_name, False yield question_name, True - - -@pytest.mark.parametrize(("question_name", "answer"), get_questions_from_copier_yaml()) -def test_parameters(working_dir: Path, question_name: str, answer: str | bool) -> None: - response = run_init_kwargs(working_dir, **{question_name: answer}) - assert response.returncode == 0, response.stdout - - -def test_default_parameters(working_dir: Path) -> None: - response = run_init(working_dir, "test_default_parameters") - - assert response.returncode == 0, response.stdout diff --git a/tests_generated/test_default_parameters/.algokit.toml b/tests_generated/test_default_parameters/.algokit.toml index 77dfd4b..4a26acf 100644 --- a/tests_generated/test_default_parameters/.algokit.toml +++ b/tests_generated/test_default_parameters/.algokit.toml @@ -1,5 +1,5 @@ [algokit] -min_version = "v1.7.3" +min_version = "v1.8.0" [deploy] command = "poetry run python -m smart_contracts deploy" diff --git a/tests_generated/test_default_parameters/.copier-answers.yml b/tests_generated/test_default_parameters/.copier-answers.yml index 50041f3..e38d360 100644 --- a/tests_generated/test_default_parameters/.copier-answers.yml +++ b/tests_generated/test_default_parameters/.copier-answers.yml @@ -13,12 +13,4 @@ indexer_port: 8980 indexer_server: http://localhost indexer_token: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa project_name: test_default_parameters -python_linter: ruff -use_dispenser: false -use_github_actions: true -use_pre_commit: true -use_python_black: true -use_python_mypy: true -use_python_pip_audit: true -use_python_pytest: true diff --git a/tests_generated/test_default_parameters/.gitignore b/tests_generated/test_default_parameters/.gitignore index 832924c..4a926bb 100644 --- a/tests_generated/test_default_parameters/.gitignore +++ b/tests_generated/test_default_parameters/.gitignore @@ -50,6 +50,7 @@ coverage.xml .hypothesis/ .pytest_cache/ cover/ +coverage/ # Translations *.mo @@ -172,3 +173,6 @@ cython_debug/ # NPM node_modules + +# AlgoKit +debug_traces/ diff --git a/tests_generated/test_default_parameters/.vscode/extensions.json b/tests_generated/test_default_parameters/.vscode/extensions.json index 36d7c10..ee83617 100644 --- a/tests_generated/test_default_parameters/.vscode/extensions.json +++ b/tests_generated/test_default_parameters/.vscode/extensions.json @@ -5,6 +5,7 @@ "matangover.mypy", "ms-python.black-formatter", "tamasfe.even-better-toml", - "editorconfig.editorconfig" + "editorconfig.editorconfig", + "algorandfoundation.algokit-avm-vscode-debugger" ] } diff --git a/tests_generated/test_default_parameters/README.md b/tests_generated/test_default_parameters/README.md index bdc3aa3..4fc1a81 100644 --- a/tests_generated/test_default_parameters/README.md +++ b/tests_generated/test_default_parameters/README.md @@ -50,6 +50,15 @@ This project has been generated using AlgoKit. See below for default getting sta 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. +### 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). + #### 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 diff --git a/tests_generated/test_default_parameters/smart_contracts/hello_world/deploy_config.py b/tests_generated/test_default_parameters/smart_contracts/hello_world/deploy_config.py index 9ab7336..82e67a8 100644 --- a/tests_generated/test_default_parameters/smart_contracts/hello_world/deploy_config.py +++ b/tests_generated/test_default_parameters/smart_contracts/hello_world/deploy_config.py @@ -23,6 +23,7 @@ def deploy( creator=deployer, indexer_client=indexer_client, ) + app_client.deploy( on_schema_break=algokit_utils.OnSchemaBreak.AppendApp, on_update=algokit_utils.OnUpdate.AppendApp, diff --git a/tests_generated/test_default_parameters/tests/conftest.py b/tests_generated/test_default_parameters/tests/conftest.py index 06a89eb..b0622e7 100644 --- a/tests_generated/test_default_parameters/tests/conftest.py +++ b/tests_generated/test_default_parameters/tests/conftest.py @@ -3,9 +3,11 @@ import pytest from algokit_utils import ( get_algod_client, + get_indexer_client, is_localnet, ) from algosdk.v2client.algod import AlgodClient +from algosdk.v2client.indexer import IndexerClient from dotenv import load_dotenv @@ -23,3 +25,8 @@ def algod_client() -> AlgodClient: # included here to prevent accidentally running against other networks assert is_localnet(client) return client + + +@pytest.fixture(scope="session") +def indexer_client() -> IndexerClient: + return get_indexer_client() diff --git a/tests_generated/test_default_parameters/tests/hello_world_test.py b/tests_generated/test_default_parameters/tests/hello_world_test.py index f4262b9..0506685 100644 --- a/tests_generated/test_default_parameters/tests/hello_world_test.py +++ b/tests_generated/test_default_parameters/tests/hello_world_test.py @@ -1,6 +1,7 @@ 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 @@ -11,6 +12,11 @@ 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), @@ -30,3 +36,15 @@ 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/tests_generated/test_deployment_language-python/.algokit.toml b/tests_generated/test_deployment_language-python/.algokit.toml index 77dfd4b..4a26acf 100644 --- a/tests_generated/test_deployment_language-python/.algokit.toml +++ b/tests_generated/test_deployment_language-python/.algokit.toml @@ -1,5 +1,5 @@ [algokit] -min_version = "v1.7.3" +min_version = "v1.8.0" [deploy] command = "poetry run python -m smart_contracts deploy" diff --git a/tests_generated/test_deployment_language-python/.gitignore b/tests_generated/test_deployment_language-python/.gitignore index 832924c..4a926bb 100644 --- a/tests_generated/test_deployment_language-python/.gitignore +++ b/tests_generated/test_deployment_language-python/.gitignore @@ -50,6 +50,7 @@ coverage.xml .hypothesis/ .pytest_cache/ cover/ +coverage/ # Translations *.mo @@ -172,3 +173,6 @@ cython_debug/ # NPM node_modules + +# AlgoKit +debug_traces/ diff --git a/tests_generated/test_deployment_language-python/.vscode/extensions.json b/tests_generated/test_deployment_language-python/.vscode/extensions.json index 36d7c10..ee83617 100644 --- a/tests_generated/test_deployment_language-python/.vscode/extensions.json +++ b/tests_generated/test_deployment_language-python/.vscode/extensions.json @@ -5,6 +5,7 @@ "matangover.mypy", "ms-python.black-formatter", "tamasfe.even-better-toml", - "editorconfig.editorconfig" + "editorconfig.editorconfig", + "algorandfoundation.algokit-avm-vscode-debugger" ] } diff --git a/tests_generated/test_deployment_language-python/README.md b/tests_generated/test_deployment_language-python/README.md index 04790de..ca67ca7 100644 --- a/tests_generated/test_deployment_language-python/README.md +++ b/tests_generated/test_deployment_language-python/README.md @@ -50,6 +50,15 @@ This project has been generated using AlgoKit. See below for default getting sta 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. +### 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). + #### 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 diff --git a/tests_generated/test_deployment_language-python/smart_contracts/hello_world/deploy_config.py b/tests_generated/test_deployment_language-python/smart_contracts/hello_world/deploy_config.py index 9ab7336..82e67a8 100644 --- a/tests_generated/test_deployment_language-python/smart_contracts/hello_world/deploy_config.py +++ b/tests_generated/test_deployment_language-python/smart_contracts/hello_world/deploy_config.py @@ -23,6 +23,7 @@ def deploy( creator=deployer, indexer_client=indexer_client, ) + app_client.deploy( on_schema_break=algokit_utils.OnSchemaBreak.AppendApp, on_update=algokit_utils.OnUpdate.AppendApp, diff --git a/tests_generated/test_deployment_language-python/tests/conftest.py b/tests_generated/test_deployment_language-python/tests/conftest.py index 06a89eb..b0622e7 100644 --- a/tests_generated/test_deployment_language-python/tests/conftest.py +++ b/tests_generated/test_deployment_language-python/tests/conftest.py @@ -3,9 +3,11 @@ import pytest from algokit_utils import ( get_algod_client, + get_indexer_client, is_localnet, ) from algosdk.v2client.algod import AlgodClient +from algosdk.v2client.indexer import IndexerClient from dotenv import load_dotenv @@ -23,3 +25,8 @@ def algod_client() -> AlgodClient: # included here to prevent accidentally running against other networks assert is_localnet(client) return client + + +@pytest.fixture(scope="session") +def indexer_client() -> IndexerClient: + return get_indexer_client() diff --git a/tests_generated/test_deployment_language-python/tests/hello_world_test.py b/tests_generated/test_deployment_language-python/tests/hello_world_test.py index f4262b9..0506685 100644 --- a/tests_generated/test_deployment_language-python/tests/hello_world_test.py +++ b/tests_generated/test_deployment_language-python/tests/hello_world_test.py @@ -1,6 +1,7 @@ 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 @@ -11,6 +12,11 @@ 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), @@ -30,3 +36,15 @@ 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/tests_generated/test_deployment_language-typescript/.algokit.toml b/tests_generated/test_deployment_language-typescript/.algokit.toml index 0871756..ad84a3c 100644 --- a/tests_generated/test_deployment_language-typescript/.algokit.toml +++ b/tests_generated/test_deployment_language-typescript/.algokit.toml @@ -1,5 +1,5 @@ [algokit] -min_version = "v1.7.3" +min_version = "v1.8.0" [deploy] command = "npm run deploy:ci" diff --git a/tests_generated/test_deployment_language-typescript/.copier-answers.yml b/tests_generated/test_deployment_language-typescript/.copier-answers.yml index 53b370a..2d3445f 100644 --- a/tests_generated/test_deployment_language-typescript/.copier-answers.yml +++ b/tests_generated/test_deployment_language-typescript/.copier-answers.yml @@ -13,12 +13,4 @@ indexer_port: 8980 indexer_server: http://localhost indexer_token: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa project_name: test_deployment_language-typescript -python_linter: ruff -use_dispenser: false -use_github_actions: true -use_pre_commit: true -use_python_black: true -use_python_mypy: true -use_python_pip_audit: true -use_python_pytest: true diff --git a/tests_generated/test_deployment_language-typescript/.github/workflows/checks.yaml b/tests_generated/test_deployment_language-typescript/.github/workflows/checks.yaml index eea57bf..0f20db5 100644 --- a/tests_generated/test_deployment_language-typescript/.github/workflows/checks.yaml +++ b/tests_generated/test_deployment_language-typescript/.github/workflows/checks.yaml @@ -58,12 +58,6 @@ jobs: - name: Check types with mypy run: poetry run mypy - - name: Run tests - shell: bash - run: | - set -o pipefail - poetry run pytest --junitxml=pytest-junit.xml - - name: Build smart contracts run: poetry run python -m smart_contracts build diff --git a/tests_generated/test_deployment_language-typescript/.gitignore b/tests_generated/test_deployment_language-typescript/.gitignore index 832924c..4a926bb 100644 --- a/tests_generated/test_deployment_language-typescript/.gitignore +++ b/tests_generated/test_deployment_language-typescript/.gitignore @@ -50,6 +50,7 @@ coverage.xml .hypothesis/ .pytest_cache/ cover/ +coverage/ # Translations *.mo @@ -172,3 +173,6 @@ cython_debug/ # NPM node_modules + +# AlgoKit +debug_traces/ diff --git a/tests_generated/test_deployment_language-typescript/.vscode/extensions.json b/tests_generated/test_deployment_language-typescript/.vscode/extensions.json index c170e6c..47b2649 100644 --- a/tests_generated/test_deployment_language-typescript/.vscode/extensions.json +++ b/tests_generated/test_deployment_language-typescript/.vscode/extensions.json @@ -6,6 +6,7 @@ "ms-python.black-formatter", "esbenp.prettier-vscode", "tamasfe.even-better-toml", - "editorconfig.editorconfig" + "editorconfig.editorconfig", + "algorandfoundation.algokit-avm-vscode-debugger" ] } diff --git a/tests_generated/test_deployment_language-typescript/.vscode/settings.json b/tests_generated/test_deployment_language-typescript/.vscode/settings.json index 50d7af1..af8031f 100644 --- a/tests_generated/test_deployment_language-typescript/.vscode/settings.json +++ b/tests_generated/test_deployment_language-typescript/.vscode/settings.json @@ -27,7 +27,6 @@ "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"], diff --git a/tests_generated/test_deployment_language-typescript/README.md b/tests_generated/test_deployment_language-typescript/README.md index 0c2c878..c520d0a 100644 --- a/tests_generated/test_deployment_language-typescript/README.md +++ b/tests_generated/test_deployment_language-typescript/README.md @@ -51,6 +51,15 @@ This project has been generated using AlgoKit. See below for default getting sta 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. +### 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). + #### 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 @@ -76,7 +85,6 @@ For pull requests and pushes to `main` branch against this repository the follow - 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/) - - Python tests are executed using [pytest](https://docs.pytest.org/) - 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 @@ -100,7 +108,6 @@ This project makes use of Python to build Algorand smart contracts. The followin - [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`. - [npm](https://www.npmjs.com/): Node.js package manager diff --git a/tests_generated/test_deployment_language-typescript/jest.config.ts b/tests_generated/test_deployment_language-typescript/jest.config.ts new file mode 100644 index 0000000..381e1e0 --- /dev/null +++ b/tests_generated/test_deployment_language-typescript/jest.config.ts @@ -0,0 +1,16 @@ +/* + * 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/tests_generated/test_deployment_language-typescript/package.json b/tests_generated/test_deployment_language-typescript/package.json index 927b682..4afc3fb 100644 --- a/tests_generated/test_deployment_language-typescript/package.json +++ b/tests_generated/test_deployment_language-typescript/package.json @@ -6,18 +6,21 @@ "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": ">=18.0" }, "dependencies": { - "@algorandfoundation/algokit-utils": "^3.0.0", + "@algorandfoundation/algokit-utils": "^5.1.0", "algosdk": "^2.5.0" }, "devDependencies": { + "@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/tests_generated/test_deployment_language-typescript/pyproject.toml b/tests_generated/test_deployment_language-typescript/pyproject.toml index 7668a04..6142aa6 100644 --- a/tests_generated/test_deployment_language-typescript/pyproject.toml +++ b/tests_generated/test_deployment_language-typescript/pyproject.toml @@ -15,8 +15,6 @@ puya = "^0.1.3" black = {extras = ["d"], version = "*"} ruff = "^0.1.6" mypy = "*" -pytest = "*" -pytest-cov = "*" pip-audit = "*" pre-commit = "*" @@ -37,9 +35,6 @@ unfixable = ["B", "RUF"] 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" diff --git a/tests_generated/test_deployment_language-typescript/tests/hello-world.spec.ts b/tests_generated/test_deployment_language-typescript/tests/hello-world.spec.ts new file mode 100644 index 0000000..81e62fa --- /dev/null +++ b/tests_generated/test_deployment_language-typescript/tests/hello-world.spec.ts @@ -0,0 +1,53 @@ +import { algorandFixture } from '@algorandfoundation/algokit-utils/testing' +import { HelloWorldClient } from '../smart_contracts/artifacts/hello_world/client' +import { Account, Algodv2, Indexer } from 'algosdk' +import * as algokit from '@algorandfoundation/algokit-utils' + +describe('hello world contract', () => { + const localnet = algorandFixture() + beforeAll(() => { + algokit.Config.configure({ + debug: true, + // traceAll: true, + }) + }) + beforeEach(localnet.beforeEach) + + const deploy = async (account: Account, algod: Algodv2, indexer: Indexer) => { + const client = new HelloWorldClient( + { + resolveBy: 'creatorAndName', + findExistingUsing: indexer, + sender: account, + creatorAddress: account.addr, + }, + algod, + ) + await client.deploy({ + allowDelete: true, + allowUpdate: true, + onSchemaBreak: 'replace', + onUpdate: 'update', + }) + return { client } + } + + test('says hello', async () => { + const { algod, indexer, testAccount } = localnet.context + const { client } = await deploy(testAccount, algod, indexer) + + const result = await client.hello({ name: 'World' }) + + expect(result.return).toBe('Hello, World') + }) + + test('simulate says hello with correct budget consumed', async () => { + const { algod, indexer, testAccount } = localnet.context + const { client } = await deploy(testAccount, algod, indexer) + const result = await client.compose().hello({ name: 'World' }).hello({ name: 'Jane' }).simulate() + + expect(result.methodResults[0].returnValue).toBe('Hello, World') + expect(result.methodResults[1].returnValue).toBe('Hello, Jane') + expect(result.simulateResponse.txnGroups[0].appBudgetConsumed).toBeLessThan(100) + }) +}) diff --git a/tests_generated/test_deployment_language-typescript/tests/hello_world_test.py b/tests_generated/test_deployment_language-typescript/tests/hello_world_test.py deleted file mode 100644 index f4262b9..0000000 --- a/tests_generated/test_deployment_language-typescript/tests/hello_world_test.py +++ /dev/null @@ -1,32 +0,0 @@ -import algokit_utils -import pytest -from algokit_utils import get_localnet_default_account -from algosdk.v2client.algod import AlgodClient -from algosdk.v2client.indexer import IndexerClient - -from smart_contracts.artifacts.hello_world.client import HelloWorldClient - - -@pytest.fixture(scope="session") -def hello_world_client( - algod_client: AlgodClient, indexer_client: IndexerClient -) -> HelloWorldClient: - client = HelloWorldClient( - algod_client, - creator=get_localnet_default_account(algod_client), - indexer_client=indexer_client, - ) - - client.deploy( - on_schema_break=algokit_utils.OnSchemaBreak.ReplaceApp, - on_update=algokit_utils.OnUpdate.UpdateApp, - allow_delete=True, - allow_update=True, - ) - return client - - -def test_says_hello(hello_world_client: HelloWorldClient) -> None: - result = hello_world_client.hello(name="World") - - assert result.return_value == "Hello, World" diff --git a/tests_generated/test_deployment_language-typescript/tsconfig.json b/tests_generated/test_deployment_language-typescript/tsconfig.json new file mode 100644 index 0000000..7c76204 --- /dev/null +++ b/tests_generated/test_deployment_language-typescript/tsconfig.json @@ -0,0 +1,24 @@ +{ + "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, + "moduleResolution": "Node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true + }, + "include": ["src/**/*.ts"], + "exclude": ["node_modules", "dist", "coverage"] +} diff --git a/tests_generated/test_ide_jetbrains-False/.algokit.toml b/tests_generated/test_ide_jetbrains-False/.algokit.toml index 77dfd4b..4a26acf 100644 --- a/tests_generated/test_ide_jetbrains-False/.algokit.toml +++ b/tests_generated/test_ide_jetbrains-False/.algokit.toml @@ -1,5 +1,5 @@ [algokit] -min_version = "v1.7.3" +min_version = "v1.8.0" [deploy] command = "poetry run python -m smart_contracts deploy" diff --git a/tests_generated/test_ide_jetbrains-False/.gitignore b/tests_generated/test_ide_jetbrains-False/.gitignore index 832924c..4a926bb 100644 --- a/tests_generated/test_ide_jetbrains-False/.gitignore +++ b/tests_generated/test_ide_jetbrains-False/.gitignore @@ -50,6 +50,7 @@ coverage.xml .hypothesis/ .pytest_cache/ cover/ +coverage/ # Translations *.mo @@ -172,3 +173,6 @@ cython_debug/ # NPM node_modules + +# AlgoKit +debug_traces/ diff --git a/tests_generated/test_ide_jetbrains-False/.vscode/extensions.json b/tests_generated/test_ide_jetbrains-False/.vscode/extensions.json index 36d7c10..ee83617 100644 --- a/tests_generated/test_ide_jetbrains-False/.vscode/extensions.json +++ b/tests_generated/test_ide_jetbrains-False/.vscode/extensions.json @@ -5,6 +5,7 @@ "matangover.mypy", "ms-python.black-formatter", "tamasfe.even-better-toml", - "editorconfig.editorconfig" + "editorconfig.editorconfig", + "algorandfoundation.algokit-avm-vscode-debugger" ] } diff --git a/tests_generated/test_ide_jetbrains-False/README.md b/tests_generated/test_ide_jetbrains-False/README.md index 44d72ed..fe0d460 100644 --- a/tests_generated/test_ide_jetbrains-False/README.md +++ b/tests_generated/test_ide_jetbrains-False/README.md @@ -50,6 +50,15 @@ This project has been generated using AlgoKit. See below for default getting sta 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. +### 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). + #### 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 diff --git a/tests_generated/test_ide_jetbrains-False/smart_contracts/hello_world/deploy_config.py b/tests_generated/test_ide_jetbrains-False/smart_contracts/hello_world/deploy_config.py index 9ab7336..82e67a8 100644 --- a/tests_generated/test_ide_jetbrains-False/smart_contracts/hello_world/deploy_config.py +++ b/tests_generated/test_ide_jetbrains-False/smart_contracts/hello_world/deploy_config.py @@ -23,6 +23,7 @@ def deploy( creator=deployer, indexer_client=indexer_client, ) + app_client.deploy( on_schema_break=algokit_utils.OnSchemaBreak.AppendApp, on_update=algokit_utils.OnUpdate.AppendApp, diff --git a/tests_generated/test_ide_jetbrains-False/tests/conftest.py b/tests_generated/test_ide_jetbrains-False/tests/conftest.py index 06a89eb..b0622e7 100644 --- a/tests_generated/test_ide_jetbrains-False/tests/conftest.py +++ b/tests_generated/test_ide_jetbrains-False/tests/conftest.py @@ -3,9 +3,11 @@ import pytest from algokit_utils import ( get_algod_client, + get_indexer_client, is_localnet, ) from algosdk.v2client.algod import AlgodClient +from algosdk.v2client.indexer import IndexerClient from dotenv import load_dotenv @@ -23,3 +25,8 @@ def algod_client() -> AlgodClient: # included here to prevent accidentally running against other networks assert is_localnet(client) return client + + +@pytest.fixture(scope="session") +def indexer_client() -> IndexerClient: + return get_indexer_client() diff --git a/tests_generated/test_ide_jetbrains-False/tests/hello_world_test.py b/tests_generated/test_ide_jetbrains-False/tests/hello_world_test.py index f4262b9..0506685 100644 --- a/tests_generated/test_ide_jetbrains-False/tests/hello_world_test.py +++ b/tests_generated/test_ide_jetbrains-False/tests/hello_world_test.py @@ -1,6 +1,7 @@ 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 @@ -11,6 +12,11 @@ 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), @@ -30,3 +36,15 @@ 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/tests_generated/test_ide_jetbrains-True/.algokit.toml b/tests_generated/test_ide_jetbrains-True/.algokit.toml index 77dfd4b..4a26acf 100644 --- a/tests_generated/test_ide_jetbrains-True/.algokit.toml +++ b/tests_generated/test_ide_jetbrains-True/.algokit.toml @@ -1,5 +1,5 @@ [algokit] -min_version = "v1.7.3" +min_version = "v1.8.0" [deploy] command = "poetry run python -m smart_contracts deploy" diff --git a/tests_generated/test_ide_jetbrains-True/.copier-answers.yml b/tests_generated/test_ide_jetbrains-True/.copier-answers.yml index f318a4d..667a3b8 100644 --- a/tests_generated/test_ide_jetbrains-True/.copier-answers.yml +++ b/tests_generated/test_ide_jetbrains-True/.copier-answers.yml @@ -13,12 +13,4 @@ indexer_port: 8980 indexer_server: http://localhost indexer_token: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa project_name: test_ide_jetbrains-True -python_linter: ruff -use_dispenser: false -use_github_actions: true -use_pre_commit: true -use_python_black: true -use_python_mypy: true -use_python_pip_audit: true -use_python_pytest: true diff --git a/tests_generated/test_ide_jetbrains-True/.gitignore b/tests_generated/test_ide_jetbrains-True/.gitignore index 832924c..4a926bb 100644 --- a/tests_generated/test_ide_jetbrains-True/.gitignore +++ b/tests_generated/test_ide_jetbrains-True/.gitignore @@ -50,6 +50,7 @@ coverage.xml .hypothesis/ .pytest_cache/ cover/ +coverage/ # Translations *.mo @@ -172,3 +173,6 @@ cython_debug/ # NPM node_modules + +# AlgoKit +debug_traces/ diff --git a/tests_generated/test_ide_jetbrains-True/.vscode/extensions.json b/tests_generated/test_ide_jetbrains-True/.vscode/extensions.json index 36d7c10..ee83617 100644 --- a/tests_generated/test_ide_jetbrains-True/.vscode/extensions.json +++ b/tests_generated/test_ide_jetbrains-True/.vscode/extensions.json @@ -5,6 +5,7 @@ "matangover.mypy", "ms-python.black-formatter", "tamasfe.even-better-toml", - "editorconfig.editorconfig" + "editorconfig.editorconfig", + "algorandfoundation.algokit-avm-vscode-debugger" ] } diff --git a/tests_generated/test_ide_jetbrains-True/README.md b/tests_generated/test_ide_jetbrains-True/README.md index e6071df..04d166e 100644 --- a/tests_generated/test_ide_jetbrains-True/README.md +++ b/tests_generated/test_ide_jetbrains-True/README.md @@ -50,6 +50,15 @@ This project has been generated using AlgoKit. See below for default getting sta 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. +### 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). + #### 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 diff --git a/tests_generated/test_ide_jetbrains-True/smart_contracts/hello_world/deploy_config.py b/tests_generated/test_ide_jetbrains-True/smart_contracts/hello_world/deploy_config.py index 9ab7336..82e67a8 100644 --- a/tests_generated/test_ide_jetbrains-True/smart_contracts/hello_world/deploy_config.py +++ b/tests_generated/test_ide_jetbrains-True/smart_contracts/hello_world/deploy_config.py @@ -23,6 +23,7 @@ def deploy( creator=deployer, indexer_client=indexer_client, ) + app_client.deploy( on_schema_break=algokit_utils.OnSchemaBreak.AppendApp, on_update=algokit_utils.OnUpdate.AppendApp, diff --git a/tests_generated/test_ide_jetbrains-True/tests/conftest.py b/tests_generated/test_ide_jetbrains-True/tests/conftest.py index 06a89eb..b0622e7 100644 --- a/tests_generated/test_ide_jetbrains-True/tests/conftest.py +++ b/tests_generated/test_ide_jetbrains-True/tests/conftest.py @@ -3,9 +3,11 @@ import pytest from algokit_utils import ( get_algod_client, + get_indexer_client, is_localnet, ) from algosdk.v2client.algod import AlgodClient +from algosdk.v2client.indexer import IndexerClient from dotenv import load_dotenv @@ -23,3 +25,8 @@ def algod_client() -> AlgodClient: # included here to prevent accidentally running against other networks assert is_localnet(client) return client + + +@pytest.fixture(scope="session") +def indexer_client() -> IndexerClient: + return get_indexer_client() diff --git a/tests_generated/test_ide_jetbrains-True/tests/hello_world_test.py b/tests_generated/test_ide_jetbrains-True/tests/hello_world_test.py index f4262b9..0506685 100644 --- a/tests_generated/test_ide_jetbrains-True/tests/hello_world_test.py +++ b/tests_generated/test_ide_jetbrains-True/tests/hello_world_test.py @@ -1,6 +1,7 @@ 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 @@ -11,6 +12,11 @@ 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), @@ -30,3 +36,15 @@ 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/tests_generated/test_smart_contract_generator_default_production_preset_python/.algokit.toml b/tests_generated/test_smart_contract_generator_default_production_preset_python/.algokit.toml index 77dfd4b..4a26acf 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_python/.algokit.toml +++ b/tests_generated/test_smart_contract_generator_default_production_preset_python/.algokit.toml @@ -1,5 +1,5 @@ [algokit] -min_version = "v1.7.3" +min_version = "v1.8.0" [deploy] command = "poetry run python -m smart_contracts deploy" diff --git a/tests_generated/test_smart_contract_generator_default_production_preset_python/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 b/tests_generated/test_smart_contract_generator_default_production_preset_python/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 index 83b938b..ab5ac39 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_python/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 +++ b/tests_generated/test_smart_contract_generator_default_production_preset_python/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 @@ -5,4 +5,4 @@ from puyapy.arc4 import String, abimethod class {{ contract_name.split('_')|map('capitalize')|join }}(ARC4Contract): @abimethod() def hello(self, name: String) -> String: - return String.encode(Bytes(b"Hello ") + name.decode()) + return String.encode(Bytes(b"Hello, ") + name.decode()) diff --git a/tests_generated/test_smart_contract_generator_default_production_preset_python/.copier-answers.yml b/tests_generated/test_smart_contract_generator_default_production_preset_python/.copier-answers.yml index b767dbb..129984b 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_python/.copier-answers.yml +++ b/tests_generated/test_smart_contract_generator_default_production_preset_python/.copier-answers.yml @@ -13,12 +13,4 @@ indexer_port: 8980 indexer_server: http://localhost indexer_token: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa project_name: test_smart_contract_generator_default_production_preset_python -python_linter: ruff -use_dispenser: false -use_github_actions: true -use_pre_commit: true -use_python_black: true -use_python_mypy: true -use_python_pip_audit: true -use_python_pytest: true diff --git a/tests_generated/test_smart_contract_generator_default_production_preset_python/.gitignore b/tests_generated/test_smart_contract_generator_default_production_preset_python/.gitignore index 832924c..4a926bb 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_python/.gitignore +++ b/tests_generated/test_smart_contract_generator_default_production_preset_python/.gitignore @@ -50,6 +50,7 @@ coverage.xml .hypothesis/ .pytest_cache/ cover/ +coverage/ # Translations *.mo @@ -172,3 +173,6 @@ cython_debug/ # NPM node_modules + +# AlgoKit +debug_traces/ diff --git a/tests_generated/test_smart_contract_generator_default_production_preset_python/.vscode/extensions.json b/tests_generated/test_smart_contract_generator_default_production_preset_python/.vscode/extensions.json index 36d7c10..ee83617 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_python/.vscode/extensions.json +++ b/tests_generated/test_smart_contract_generator_default_production_preset_python/.vscode/extensions.json @@ -5,6 +5,7 @@ "matangover.mypy", "ms-python.black-formatter", "tamasfe.even-better-toml", - "editorconfig.editorconfig" + "editorconfig.editorconfig", + "algorandfoundation.algokit-avm-vscode-debugger" ] } diff --git a/tests_generated/test_smart_contract_generator_default_production_preset_python/.vscode/launch.json b/tests_generated/test_smart_contract_generator_default_production_preset_python/.vscode/launch.json index d127326..1df1cfc 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_python/.vscode/launch.json +++ b/tests_generated/test_smart_contract_generator_default_production_preset_python/.vscode/launch.json @@ -26,6 +26,13 @@ "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/tests_generated/test_smart_contract_generator_default_production_preset_python/README.md b/tests_generated/test_smart_contract_generator_default_production_preset_python/README.md index 7d4f687..373e868 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_python/README.md +++ b/tests_generated/test_smart_contract_generator_default_production_preset_python/README.md @@ -50,6 +50,15 @@ This project has been generated using AlgoKit. See below for default getting sta 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. +### 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). + #### 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 diff --git a/tests_generated/test_smart_contract_generator_default_production_preset_python/pyproject.toml b/tests_generated/test_smart_contract_generator_default_production_preset_python/pyproject.toml index 89a9a22..0862b27 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_python/pyproject.toml +++ b/tests_generated/test_smart_contract_generator_default_production_preset_python/pyproject.toml @@ -7,9 +7,9 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.12" -algokit-utils = "^2.0.1" +algokit-utils = "^2.2.0" python-dotenv = "^1.0.0" -puya = "^0.1.3" +puya = "^0.2.0" [tool.poetry.group.dev.dependencies] black = {extras = ["d"], version = "*"} diff --git a/tests_generated/test_smart_contract_generator_default_production_preset_python/smart_contracts/__main__.py b/tests_generated/test_smart_contract_generator_default_production_preset_python/smart_contracts/__main__.py index 75df051..7db8a69 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_python/smart_contracts/__main__.py +++ b/tests_generated/test_smart_contract_generator_default_production_preset_python/smart_contracts/__main__.py @@ -8,6 +8,11 @@ from smart_contracts.helpers.build import build 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" ) diff --git a/tests_generated/test_smart_contract_generator_default_production_preset_python/smart_contracts/cool_contract/contract.py b/tests_generated/test_smart_contract_generator_default_production_preset_python/smart_contracts/cool_contract/contract.py index 76d1be4..8d74892 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_python/smart_contracts/cool_contract/contract.py +++ b/tests_generated/test_smart_contract_generator_default_production_preset_python/smart_contracts/cool_contract/contract.py @@ -5,4 +5,4 @@ class CoolContract(ARC4Contract): @abimethod() def hello(self, name: String) -> String: - return String.encode(Bytes(b"Hello ") + name.decode()) + return String.encode(Bytes(b"Hello, ") + name.decode()) diff --git a/tests_generated/test_smart_contract_generator_default_production_preset_python/smart_contracts/hello_world/contract.py b/tests_generated/test_smart_contract_generator_default_production_preset_python/smart_contracts/hello_world/contract.py index 1b8fddb..586abbd 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_python/smart_contracts/hello_world/contract.py +++ b/tests_generated/test_smart_contract_generator_default_production_preset_python/smart_contracts/hello_world/contract.py @@ -5,4 +5,4 @@ class HelloWorld(ARC4Contract): @abimethod() def hello(self, name: String) -> String: - return String.encode(Bytes(b"Hello ") + name.decode()) + return String.encode(Bytes(b"Hello, ") + name.decode()) diff --git a/tests_generated/test_smart_contract_generator_default_production_preset_python/smart_contracts/hello_world/deploy_config.py b/tests_generated/test_smart_contract_generator_default_production_preset_python/smart_contracts/hello_world/deploy_config.py index 9ab7336..82e67a8 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_python/smart_contracts/hello_world/deploy_config.py +++ b/tests_generated/test_smart_contract_generator_default_production_preset_python/smart_contracts/hello_world/deploy_config.py @@ -23,6 +23,7 @@ def deploy( creator=deployer, indexer_client=indexer_client, ) + app_client.deploy( on_schema_break=algokit_utils.OnSchemaBreak.AppendApp, on_update=algokit_utils.OnUpdate.AppendApp, diff --git a/tests_generated/test_smart_contract_generator_default_production_preset_python/tests/conftest.py b/tests_generated/test_smart_contract_generator_default_production_preset_python/tests/conftest.py index 06a89eb..b0622e7 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_python/tests/conftest.py +++ b/tests_generated/test_smart_contract_generator_default_production_preset_python/tests/conftest.py @@ -3,9 +3,11 @@ import pytest from algokit_utils import ( get_algod_client, + get_indexer_client, is_localnet, ) from algosdk.v2client.algod import AlgodClient +from algosdk.v2client.indexer import IndexerClient from dotenv import load_dotenv @@ -23,3 +25,8 @@ def algod_client() -> AlgodClient: # included here to prevent accidentally running against other networks assert is_localnet(client) return client + + +@pytest.fixture(scope="session") +def indexer_client() -> IndexerClient: + return get_indexer_client() diff --git a/tests_generated/test_smart_contract_generator_default_production_preset_python/tests/hello_world_test.py b/tests_generated/test_smart_contract_generator_default_production_preset_python/tests/hello_world_test.py index f4262b9..bb13a43 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_python/tests/hello_world_test.py +++ b/tests_generated/test_smart_contract_generator_default_production_preset_python/tests/hello_world_test.py @@ -1,6 +1,7 @@ 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 @@ -11,6 +12,11 @@ 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), @@ -18,10 +24,8 @@ def hello_world_client( ) client.deploy( - on_schema_break=algokit_utils.OnSchemaBreak.ReplaceApp, - on_update=algokit_utils.OnUpdate.UpdateApp, - allow_delete=True, - allow_update=True, + on_schema_break=algokit_utils.OnSchemaBreak.AppendApp, + on_update=algokit_utils.OnUpdate.AppendApp, ) return client @@ -30,3 +34,15 @@ 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/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.algokit.toml b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.algokit.toml index 0871756..ad84a3c 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.algokit.toml +++ b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.algokit.toml @@ -1,5 +1,5 @@ [algokit] -min_version = "v1.7.3" +min_version = "v1.8.0" [deploy] command = "npm run deploy:ci" diff --git a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 index 83b938b..ab5ac39 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 +++ b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 @@ -5,4 +5,4 @@ from puyapy.arc4 import String, abimethod class {{ contract_name.split('_')|map('capitalize')|join }}(ARC4Contract): @abimethod() def hello(self, name: String) -> String: - return String.encode(Bytes(b"Hello ") + name.decode()) + return String.encode(Bytes(b"Hello, ") + name.decode()) diff --git a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.copier-answers.yml b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.copier-answers.yml index bb502cf..9f23d0e 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.copier-answers.yml +++ b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.copier-answers.yml @@ -13,12 +13,4 @@ indexer_port: 8980 indexer_server: http://localhost indexer_token: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa project_name: test_smart_contract_generator_default_production_preset_typescript -python_linter: ruff -use_dispenser: false -use_github_actions: true -use_pre_commit: true -use_python_black: true -use_python_mypy: true -use_python_pip_audit: true -use_python_pytest: true diff --git a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.github/workflows/checks.yaml b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.github/workflows/checks.yaml index eea57bf..0f20db5 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.github/workflows/checks.yaml +++ b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.github/workflows/checks.yaml @@ -58,12 +58,6 @@ jobs: - name: Check types with mypy run: poetry run mypy - - name: Run tests - shell: bash - run: | - set -o pipefail - poetry run pytest --junitxml=pytest-junit.xml - - name: Build smart contracts run: poetry run python -m smart_contracts build diff --git a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.gitignore b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.gitignore index 832924c..4a926bb 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.gitignore +++ b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.gitignore @@ -50,6 +50,7 @@ coverage.xml .hypothesis/ .pytest_cache/ cover/ +coverage/ # Translations *.mo @@ -172,3 +173,6 @@ cython_debug/ # NPM node_modules + +# AlgoKit +debug_traces/ diff --git a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.vscode/extensions.json b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.vscode/extensions.json index c170e6c..47b2649 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.vscode/extensions.json +++ b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.vscode/extensions.json @@ -6,6 +6,7 @@ "ms-python.black-formatter", "esbenp.prettier-vscode", "tamasfe.even-better-toml", - "editorconfig.editorconfig" + "editorconfig.editorconfig", + "algorandfoundation.algokit-avm-vscode-debugger" ] } diff --git a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.vscode/launch.json b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.vscode/launch.json index b5c1fb6..1217d90 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.vscode/launch.json +++ b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.vscode/launch.json @@ -31,6 +31,13 @@ "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/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.vscode/settings.json b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.vscode/settings.json index 50d7af1..af8031f 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.vscode/settings.json +++ b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/.vscode/settings.json @@ -27,7 +27,6 @@ "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"], diff --git a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/README.md b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/README.md index ea273e5..c6885b7 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/README.md +++ b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/README.md @@ -51,6 +51,15 @@ This project has been generated using AlgoKit. See below for default getting sta 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. +### 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). + #### 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 @@ -76,7 +85,6 @@ For pull requests and pushes to `main` branch against this repository the follow - 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/) - - Python tests are executed using [pytest](https://docs.pytest.org/) - 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 @@ -100,7 +108,6 @@ This project makes use of Python to build Algorand smart contracts. The followin - [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`. - [npm](https://www.npmjs.com/): Node.js package manager diff --git a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/jest.config.ts b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/jest.config.ts new file mode 100644 index 0000000..381e1e0 --- /dev/null +++ b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/jest.config.ts @@ -0,0 +1,16 @@ +/* + * 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/tests_generated/test_smart_contract_generator_default_production_preset_typescript/package.json b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/package.json index 927b682..4afc3fb 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/package.json +++ b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/package.json @@ -6,18 +6,21 @@ "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": ">=18.0" }, "dependencies": { - "@algorandfoundation/algokit-utils": "^3.0.0", + "@algorandfoundation/algokit-utils": "^5.1.0", "algosdk": "^2.5.0" }, "devDependencies": { + "@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/tests_generated/test_smart_contract_generator_default_production_preset_typescript/pyproject.toml b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/pyproject.toml index 2135028..b74e3c6 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/pyproject.toml +++ b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/pyproject.toml @@ -7,16 +7,14 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.12" -algokit-utils = "^2.0.1" +algokit-utils = "^2.2.0" python-dotenv = "^1.0.0" -puya = "^0.1.3" +puya = "^0.2.0" [tool.poetry.group.dev.dependencies] black = {extras = ["d"], version = "*"} ruff = "^0.1.6" mypy = "*" -pytest = "*" -pytest-cov = "*" pip-audit = "*" pre-commit = "*" @@ -37,9 +35,6 @@ unfixable = ["B", "RUF"] 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" diff --git a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/smart_contracts/cool_contract/contract.py b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/smart_contracts/cool_contract/contract.py index 76d1be4..8d74892 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/smart_contracts/cool_contract/contract.py +++ b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/smart_contracts/cool_contract/contract.py @@ -5,4 +5,4 @@ class CoolContract(ARC4Contract): @abimethod() def hello(self, name: String) -> String: - return String.encode(Bytes(b"Hello ") + name.decode()) + return String.encode(Bytes(b"Hello, ") + name.decode()) diff --git a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/smart_contracts/hello_world/contract.py b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/smart_contracts/hello_world/contract.py index 1b8fddb..586abbd 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/smart_contracts/hello_world/contract.py +++ b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/smart_contracts/hello_world/contract.py @@ -5,4 +5,4 @@ class HelloWorld(ARC4Contract): @abimethod() def hello(self, name: String) -> String: - return String.encode(Bytes(b"Hello ") + name.decode()) + return String.encode(Bytes(b"Hello, ") + name.decode()) diff --git a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/smart_contracts/index.ts b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/smart_contracts/index.ts index 4f18d4d..af40ab4 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/smart_contracts/index.ts +++ b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/smart_contracts/index.ts @@ -3,8 +3,13 @@ import * as path from 'path' import { consoleLogger } from '@algorandfoundation/algokit-utils/types/logging' import * as algokit from '@algorandfoundation/algokit-utils' +// 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, }) // base directory diff --git a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/tests/conftest.py b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/tests/conftest.py deleted file mode 100644 index 06a89eb..0000000 --- a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/tests/conftest.py +++ /dev/null @@ -1,25 +0,0 @@ -from pathlib import Path - -import pytest -from algokit_utils import ( - get_algod_client, - is_localnet, -) -from algosdk.v2client.algod import AlgodClient -from dotenv import load_dotenv - - -@pytest.fixture(autouse=True, scope="session") -def environment_fixture() -> None: - env_path = Path(__file__).parent.parent / ".env.localnet" - load_dotenv(env_path) - - -@pytest.fixture(scope="session") -def algod_client() -> AlgodClient: - client = get_algod_client() - - # you can remove this assertion to test on other networks, - # included here to prevent accidentally running against other networks - assert is_localnet(client) - return client diff --git a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/tests/hello-world.spec.ts b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/tests/hello-world.spec.ts new file mode 100644 index 0000000..b5ad81a --- /dev/null +++ b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/tests/hello-world.spec.ts @@ -0,0 +1,51 @@ +import { algorandFixture } from '@algorandfoundation/algokit-utils/testing' +import { HelloWorldClient } from '../smart_contracts/artifacts/hello_world/client' +import { Account, Algodv2, Indexer } from 'algosdk' +import * as algokit from '@algorandfoundation/algokit-utils' + +describe('hello world contract', () => { + const localnet = algorandFixture() + beforeAll(() => { + algokit.Config.configure({ + debug: true, + // traceAll: true, + }) + }) + beforeEach(localnet.beforeEach) + + const deploy = async (account: Account, algod: Algodv2, indexer: Indexer) => { + const client = new HelloWorldClient( + { + resolveBy: 'creatorAndName', + findExistingUsing: indexer, + sender: account, + creatorAddress: account.addr, + }, + algod, + ) + await client.deploy({ + onSchemaBreak: 'append', + onUpdate: 'append', + }) + return { client } + } + + test('says hello', async () => { + const { algod, indexer, testAccount } = localnet.context + const { client } = await deploy(testAccount, algod, indexer) + + const result = await client.hello({ name: 'World' }) + + expect(result.return).toBe('Hello, World') + }) + + test('simulate says hello with correct budget consumed', async () => { + const { algod, indexer, testAccount } = localnet.context + const { client } = await deploy(testAccount, algod, indexer) + const result = await client.compose().hello({ name: 'World' }).hello({ name: 'Jane' }).simulate() + + expect(result.methodResults[0].returnValue).toBe('Hello, World') + expect(result.methodResults[1].returnValue).toBe('Hello, Jane') + expect(result.simulateResponse.txnGroups[0].appBudgetConsumed).toBeLessThan(100) + }) +}) diff --git a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/tsconfig.json b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/tsconfig.json new file mode 100644 index 0000000..7c76204 --- /dev/null +++ b/tests_generated/test_smart_contract_generator_default_production_preset_typescript/tsconfig.json @@ -0,0 +1,24 @@ +{ + "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, + "moduleResolution": "Node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true + }, + "include": ["src/**/*.ts"], + "exclude": ["node_modules", "dist", "coverage"] +} diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_python/.algokit.toml b/tests_generated/test_smart_contract_generator_default_starter_preset_python/.algokit.toml index 77dfd4b..4a26acf 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_python/.algokit.toml +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_python/.algokit.toml @@ -1,5 +1,5 @@ [algokit] -min_version = "v1.7.3" +min_version = "v1.8.0" [deploy] command = "poetry run python -m smart_contracts deploy" diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_python/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 b/tests_generated/test_smart_contract_generator_default_starter_preset_python/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 index 83b938b..ab5ac39 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_python/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_python/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 @@ -5,4 +5,4 @@ from puyapy.arc4 import String, abimethod class {{ contract_name.split('_')|map('capitalize')|join }}(ARC4Contract): @abimethod() def hello(self, name: String) -> String: - return String.encode(Bytes(b"Hello ") + name.decode()) + return String.encode(Bytes(b"Hello, ") + name.decode()) diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_python/.copier-answers.yml b/tests_generated/test_smart_contract_generator_default_starter_preset_python/.copier-answers.yml index a6470a8..7735a69 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_python/.copier-answers.yml +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_python/.copier-answers.yml @@ -13,12 +13,4 @@ indexer_port: 8980 indexer_server: http://localhost indexer_token: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa project_name: test_smart_contract_generator_default_starter_preset_python -python_linter: ruff -use_dispenser: false -use_github_actions: true -use_pre_commit: true -use_python_black: true -use_python_mypy: true -use_python_pip_audit: true -use_python_pytest: true diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_python/.gitignore b/tests_generated/test_smart_contract_generator_default_starter_preset_python/.gitignore index 832924c..4a926bb 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_python/.gitignore +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_python/.gitignore @@ -50,6 +50,7 @@ coverage.xml .hypothesis/ .pytest_cache/ cover/ +coverage/ # Translations *.mo @@ -172,3 +173,6 @@ cython_debug/ # NPM node_modules + +# AlgoKit +debug_traces/ diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_python/.vscode/extensions.json b/tests_generated/test_smart_contract_generator_default_starter_preset_python/.vscode/extensions.json index 36d7c10..ee83617 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_python/.vscode/extensions.json +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_python/.vscode/extensions.json @@ -5,6 +5,7 @@ "matangover.mypy", "ms-python.black-formatter", "tamasfe.even-better-toml", - "editorconfig.editorconfig" + "editorconfig.editorconfig", + "algorandfoundation.algokit-avm-vscode-debugger" ] } diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_python/.vscode/launch.json b/tests_generated/test_smart_contract_generator_default_starter_preset_python/.vscode/launch.json index d127326..1df1cfc 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_python/.vscode/launch.json +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_python/.vscode/launch.json @@ -26,6 +26,13 @@ "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/tests_generated/test_smart_contract_generator_default_starter_preset_python/README.md b/tests_generated/test_smart_contract_generator_default_starter_preset_python/README.md index 8acb8d7..b13c087 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_python/README.md +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_python/README.md @@ -50,6 +50,15 @@ This project has been generated using AlgoKit. See below for default getting sta 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. +### 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). + #### 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 diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_python/pyproject.toml b/tests_generated/test_smart_contract_generator_default_starter_preset_python/pyproject.toml index 52cd316..27063cf 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_python/pyproject.toml +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_python/pyproject.toml @@ -7,9 +7,9 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.12" -algokit-utils = "^2.0.1" +algokit-utils = "^2.2.0" python-dotenv = "^1.0.0" -puya = "^0.1.3" +puya = "^0.2.0" [tool.poetry.group.dev.dependencies] black = {extras = ["d"], version = "*"} diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_python/smart_contracts/__main__.py b/tests_generated/test_smart_contract_generator_default_starter_preset_python/smart_contracts/__main__.py index 75df051..7db8a69 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_python/smart_contracts/__main__.py +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_python/smart_contracts/__main__.py @@ -8,6 +8,11 @@ from smart_contracts.helpers.build import build 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" ) diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_python/smart_contracts/cool_contract/contract.py b/tests_generated/test_smart_contract_generator_default_starter_preset_python/smart_contracts/cool_contract/contract.py index 76d1be4..8d74892 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_python/smart_contracts/cool_contract/contract.py +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_python/smart_contracts/cool_contract/contract.py @@ -5,4 +5,4 @@ class CoolContract(ARC4Contract): @abimethod() def hello(self, name: String) -> String: - return String.encode(Bytes(b"Hello ") + name.decode()) + return String.encode(Bytes(b"Hello, ") + name.decode()) diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_python/smart_contracts/hello_world/contract.py b/tests_generated/test_smart_contract_generator_default_starter_preset_python/smart_contracts/hello_world/contract.py index 1b8fddb..586abbd 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_python/smart_contracts/hello_world/contract.py +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_python/smart_contracts/hello_world/contract.py @@ -5,4 +5,4 @@ class HelloWorld(ARC4Contract): @abimethod() def hello(self, name: String) -> String: - return String.encode(Bytes(b"Hello ") + name.decode()) + return String.encode(Bytes(b"Hello, ") + name.decode()) diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_python/smart_contracts/hello_world/deploy_config.py b/tests_generated/test_smart_contract_generator_default_starter_preset_python/smart_contracts/hello_world/deploy_config.py index 9ab7336..82e67a8 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_python/smart_contracts/hello_world/deploy_config.py +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_python/smart_contracts/hello_world/deploy_config.py @@ -23,6 +23,7 @@ def deploy( creator=deployer, indexer_client=indexer_client, ) + app_client.deploy( on_schema_break=algokit_utils.OnSchemaBreak.AppendApp, on_update=algokit_utils.OnUpdate.AppendApp, diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_python/tests/conftest.py b/tests_generated/test_smart_contract_generator_default_starter_preset_python/tests/conftest.py index 06a89eb..b0622e7 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_python/tests/conftest.py +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_python/tests/conftest.py @@ -3,9 +3,11 @@ import pytest from algokit_utils import ( get_algod_client, + get_indexer_client, is_localnet, ) from algosdk.v2client.algod import AlgodClient +from algosdk.v2client.indexer import IndexerClient from dotenv import load_dotenv @@ -23,3 +25,8 @@ def algod_client() -> AlgodClient: # included here to prevent accidentally running against other networks assert is_localnet(client) return client + + +@pytest.fixture(scope="session") +def indexer_client() -> IndexerClient: + return get_indexer_client() diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_python/tests/hello_world_test.py b/tests_generated/test_smart_contract_generator_default_starter_preset_python/tests/hello_world_test.py index f4262b9..bb13a43 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_python/tests/hello_world_test.py +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_python/tests/hello_world_test.py @@ -1,6 +1,7 @@ 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 @@ -11,6 +12,11 @@ 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), @@ -18,10 +24,8 @@ def hello_world_client( ) client.deploy( - on_schema_break=algokit_utils.OnSchemaBreak.ReplaceApp, - on_update=algokit_utils.OnUpdate.UpdateApp, - allow_delete=True, - allow_update=True, + on_schema_break=algokit_utils.OnSchemaBreak.AppendApp, + on_update=algokit_utils.OnUpdate.AppendApp, ) return client @@ -30,3 +34,15 @@ 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/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.algokit.toml b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.algokit.toml index 0871756..ad84a3c 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.algokit.toml +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.algokit.toml @@ -1,5 +1,5 @@ [algokit] -min_version = "v1.7.3" +min_version = "v1.8.0" [deploy] command = "npm run deploy:ci" diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 index 83b938b..ab5ac39 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/contract.py.j2 @@ -5,4 +5,4 @@ from puyapy.arc4 import String, abimethod class {{ contract_name.split('_')|map('capitalize')|join }}(ARC4Contract): @abimethod() def hello(self, name: String) -> String: - return String.encode(Bytes(b"Hello ") + name.decode()) + return String.encode(Bytes(b"Hello, ") + name.decode()) diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.copier-answers.yml b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.copier-answers.yml index 4e6d7e9..d399dae 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.copier-answers.yml +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.copier-answers.yml @@ -13,12 +13,4 @@ indexer_port: 8980 indexer_server: http://localhost indexer_token: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa project_name: test_smart_contract_generator_default_starter_preset_typescript -python_linter: ruff -use_dispenser: false -use_github_actions: true -use_pre_commit: true -use_python_black: true -use_python_mypy: true -use_python_pip_audit: true -use_python_pytest: true diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.github/workflows/checks.yaml b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.github/workflows/checks.yaml index eea57bf..0f20db5 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.github/workflows/checks.yaml +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.github/workflows/checks.yaml @@ -58,12 +58,6 @@ jobs: - name: Check types with mypy run: poetry run mypy - - name: Run tests - shell: bash - run: | - set -o pipefail - poetry run pytest --junitxml=pytest-junit.xml - - name: Build smart contracts run: poetry run python -m smart_contracts build diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.gitignore b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.gitignore index 832924c..4a926bb 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.gitignore +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.gitignore @@ -50,6 +50,7 @@ coverage.xml .hypothesis/ .pytest_cache/ cover/ +coverage/ # Translations *.mo @@ -172,3 +173,6 @@ cython_debug/ # NPM node_modules + +# AlgoKit +debug_traces/ diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.vscode/extensions.json b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.vscode/extensions.json index c170e6c..47b2649 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.vscode/extensions.json +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.vscode/extensions.json @@ -6,6 +6,7 @@ "ms-python.black-formatter", "esbenp.prettier-vscode", "tamasfe.even-better-toml", - "editorconfig.editorconfig" + "editorconfig.editorconfig", + "algorandfoundation.algokit-avm-vscode-debugger" ] } diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.vscode/launch.json b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.vscode/launch.json index b5c1fb6..1217d90 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.vscode/launch.json +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.vscode/launch.json @@ -31,6 +31,13 @@ "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/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.vscode/settings.json b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.vscode/settings.json index 50d7af1..af8031f 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.vscode/settings.json +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/.vscode/settings.json @@ -27,7 +27,6 @@ "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"], diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/README.md b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/README.md index c94195b..583a1d5 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/README.md +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/README.md @@ -51,6 +51,15 @@ This project has been generated using AlgoKit. See below for default getting sta 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. +### 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). + #### 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 @@ -76,7 +85,6 @@ For pull requests and pushes to `main` branch against this repository the follow - 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/) - - Python tests are executed using [pytest](https://docs.pytest.org/) - 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 @@ -100,7 +108,6 @@ This project makes use of Python to build Algorand smart contracts. The followin - [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`. - [npm](https://www.npmjs.com/): Node.js package manager diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/jest.config.ts b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/jest.config.ts new file mode 100644 index 0000000..381e1e0 --- /dev/null +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/jest.config.ts @@ -0,0 +1,16 @@ +/* + * 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/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/package.json b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/package.json index 927b682..4afc3fb 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/package.json +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/package.json @@ -6,18 +6,21 @@ "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": ">=18.0" }, "dependencies": { - "@algorandfoundation/algokit-utils": "^3.0.0", + "@algorandfoundation/algokit-utils": "^5.1.0", "algosdk": "^2.5.0" }, "devDependencies": { + "@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/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/pyproject.toml b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/pyproject.toml index b825fb8..80f44ec 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/pyproject.toml +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/pyproject.toml @@ -7,16 +7,14 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.12" -algokit-utils = "^2.0.1" +algokit-utils = "^2.2.0" python-dotenv = "^1.0.0" -puya = "^0.1.3" +puya = "^0.2.0" [tool.poetry.group.dev.dependencies] black = {extras = ["d"], version = "*"} ruff = "^0.1.6" mypy = "*" -pytest = "*" -pytest-cov = "*" pip-audit = "*" pre-commit = "*" @@ -37,9 +35,6 @@ unfixable = ["B", "RUF"] 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" diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/smart_contracts/cool_contract/contract.py b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/smart_contracts/cool_contract/contract.py index 76d1be4..8d74892 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/smart_contracts/cool_contract/contract.py +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/smart_contracts/cool_contract/contract.py @@ -5,4 +5,4 @@ class CoolContract(ARC4Contract): @abimethod() def hello(self, name: String) -> String: - return String.encode(Bytes(b"Hello ") + name.decode()) + return String.encode(Bytes(b"Hello, ") + name.decode()) diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/smart_contracts/hello_world/contract.py b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/smart_contracts/hello_world/contract.py index 1b8fddb..586abbd 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/smart_contracts/hello_world/contract.py +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/smart_contracts/hello_world/contract.py @@ -5,4 +5,4 @@ class HelloWorld(ARC4Contract): @abimethod() def hello(self, name: String) -> String: - return String.encode(Bytes(b"Hello ") + name.decode()) + return String.encode(Bytes(b"Hello, ") + name.decode()) diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/smart_contracts/index.ts b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/smart_contracts/index.ts index 4f18d4d..af40ab4 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/smart_contracts/index.ts +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/smart_contracts/index.ts @@ -3,8 +3,13 @@ import * as path from 'path' import { consoleLogger } from '@algorandfoundation/algokit-utils/types/logging' import * as algokit from '@algorandfoundation/algokit-utils' +// 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, }) // base directory diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/tests/hello-world.spec.ts b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/tests/hello-world.spec.ts new file mode 100644 index 0000000..b5ad81a --- /dev/null +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/tests/hello-world.spec.ts @@ -0,0 +1,51 @@ +import { algorandFixture } from '@algorandfoundation/algokit-utils/testing' +import { HelloWorldClient } from '../smart_contracts/artifacts/hello_world/client' +import { Account, Algodv2, Indexer } from 'algosdk' +import * as algokit from '@algorandfoundation/algokit-utils' + +describe('hello world contract', () => { + const localnet = algorandFixture() + beforeAll(() => { + algokit.Config.configure({ + debug: true, + // traceAll: true, + }) + }) + beforeEach(localnet.beforeEach) + + const deploy = async (account: Account, algod: Algodv2, indexer: Indexer) => { + const client = new HelloWorldClient( + { + resolveBy: 'creatorAndName', + findExistingUsing: indexer, + sender: account, + creatorAddress: account.addr, + }, + algod, + ) + await client.deploy({ + onSchemaBreak: 'append', + onUpdate: 'append', + }) + return { client } + } + + test('says hello', async () => { + const { algod, indexer, testAccount } = localnet.context + const { client } = await deploy(testAccount, algod, indexer) + + const result = await client.hello({ name: 'World' }) + + expect(result.return).toBe('Hello, World') + }) + + test('simulate says hello with correct budget consumed', async () => { + const { algod, indexer, testAccount } = localnet.context + const { client } = await deploy(testAccount, algod, indexer) + const result = await client.compose().hello({ name: 'World' }).hello({ name: 'Jane' }).simulate() + + expect(result.methodResults[0].returnValue).toBe('Hello, World') + expect(result.methodResults[1].returnValue).toBe('Hello, Jane') + expect(result.simulateResponse.txnGroups[0].appBudgetConsumed).toBeLessThan(100) + }) +}) diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/tsconfig.json b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/tsconfig.json new file mode 100644 index 0000000..7c76204 --- /dev/null +++ b/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/tsconfig.json @@ -0,0 +1,24 @@ +{ + "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, + "moduleResolution": "Node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true + }, + "include": ["src/**/*.ts"], + "exclude": ["node_modules", "dist", "coverage"] +} diff --git a/tests_generated/test_use_typescript_jest-False/.algokit.toml b/tests_generated/test_use_typescript_jest-False/.algokit.toml new file mode 100644 index 0000000..4a26acf --- /dev/null +++ b/tests_generated/test_use_typescript_jest-False/.algokit.toml @@ -0,0 +1,15 @@ +[algokit] +min_version = "v1.8.0" + +[deploy] +command = "poetry run python -m smart_contracts deploy" +environment_secrets = [ + "DEPLOYER_MNEMONIC", +] + +[deploy.localnet] +environment_secrets = [] + +[generate.smart_contract] +description = "Adds new smart contract to existing project" +path = ".algokit/generators/create_contract" diff --git a/tests_generated/test_use_typescript_jest-False/.copier-answers.yml b/tests_generated/test_use_typescript_jest-False/.copier-answers.yml new file mode 100644 index 0000000..b5b0bb0 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-False/.copier-answers.yml @@ -0,0 +1,16 @@ +# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY +_commit: +_src_path: +algod_port: 4001 +algod_server: http://localhost +algod_token: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +author_email: None +author_name: None +contract_name: hello_world +deployment_language: python +ide_vscode: true +indexer_port: 8980 +indexer_server: http://localhost +indexer_token: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +project_name: test_use_typescript_jest-False + diff --git a/tests_generated/test_use_typescript_jest-False/.editorconfig b/tests_generated/test_use_typescript_jest-False/.editorconfig new file mode 100644 index 0000000..e2fda34 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-False/.editorconfig @@ -0,0 +1,10 @@ +root=true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true + +[*.py] +indent_size = 4 diff --git a/tests_generated/test_use_typescript_jest-False/.env.localnet.template b/tests_generated/test_use_typescript_jest-False/.env.localnet.template new file mode 100644 index 0000000..fcbf442 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-False/.env.localnet.template @@ -0,0 +1,7 @@ +# 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/tests_generated/test_use_typescript_jest-False/.env.template b/tests_generated/test_use_typescript_jest-False/.env.template new file mode 100644 index 0000000..184b393 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-False/.env.template @@ -0,0 +1 @@ +# this file should contain environment variables common to all environments/networks diff --git a/tests_generated/test_use_typescript_jest-False/.env.testnet.template b/tests_generated/test_use_typescript_jest-False/.env.testnet.template new file mode 100644 index 0000000..eeea43d --- /dev/null +++ b/tests_generated/test_use_typescript_jest-False/.env.testnet.template @@ -0,0 +1,3 @@ +# 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/tests_generated/test_use_typescript_jest-False/.gitattributes b/tests_generated/test_use_typescript_jest-False/.gitattributes new file mode 100644 index 0000000..6313b56 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-False/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/tests_generated/test_use_typescript_jest-False/.github/workflows/cd.yaml b/tests_generated/test_use_typescript_jest-False/.github/workflows/cd.yaml new file mode 100644 index 0000000..3e0fd45 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-False/.github/workflows/cd.yaml @@ -0,0 +1,50 @@ +name: Continuous Delivery of Smart Contract + +on: + push: + branches: + - main + +concurrency: release + +jobs: + ci-check: + name: Perform Checks + uses: ./.github/workflows/checks.yaml + + deploy-testnet: + runs-on: 'ubuntu-latest' + needs: ci-check + environment: Test + steps: + - name: Checkout source code + uses: actions/checkout@v3 + + - name: Install poetry + run: pipx install poetry + + - name: Set up Python 3.12 + uses: actions/setup-python@v4 + with: + python-version: '3.12' + cache: 'poetry' + + - name: Install algokit + run: pipx install algokit + + - name: Bootstrap dependencies + run: algokit 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 deploy testnet + env: + # This is the account that becomes the creator of the contract. + # Since we are not using the optional dispenser account (via DISPENSER_MNEMONIC), + # it must also be funded with enough Algos to deploy and fund the smart contracts created + DEPLOYER_MNEMONIC: ${{ secrets.DEPLOYER_MNEMONIC }} diff --git a/tests_generated/test_use_typescript_jest-False/.github/workflows/checks.yaml b/tests_generated/test_use_typescript_jest-False/.github/workflows/checks.yaml new file mode 100644 index 0000000..f6d0102 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-False/.github/workflows/checks.yaml @@ -0,0 +1,79 @@ +name: Check code base + +on: + workflow_call: + +jobs: + checks: + runs-on: 'ubuntu-latest' + steps: + - name: Checkout source code + uses: actions/checkout@v3 + + - name: Install poetry + run: pipx install poetry + + - name: Set up Python 3.12 + uses: actions/setup-python@v4 + 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 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 with pip-audit + run: | + # audit non dev dependencies, no exclusions + poetry export --without=dev > requirements.txt && poetry run pip-audit -r requirements.txt + + # audit all dependencies, with exclusions. + # If a vulnerability is found in a dev dependency without an available fix, + # it can be temporarily ignored by adding --ignore-vuln e.g. + # --ignore-vuln "GHSA-hcpj-qp55-gfph" # GitPython vulnerability, dev only dependency + poetry run pip-audit + + - name: Check formatting with Black + run: | + # stop the build if there are files that don't meet formatting requirements + poetry run black --check . + + - name: Check linting with Ruff + run: | + # stop the build if there are Python syntax errors or undefined names + poetry run ruff . + + - name: Check types with mypy + run: poetry run mypy + + - name: Run tests + shell: bash + run: | + set -o pipefail + poetry run pytest --junitxml=pytest-junit.xml + + - name: Build smart contracts + run: poetry run python -m smart_contracts build + + - name: Check output stability of the smart contracts + shell: bash + run: | + # Add untracked files as empty so they come up in diff + git add -N ./smart_contracts/artifacts + # Error out if there are any changes in teal after generating output + git diff --exit-code --minimal ./smart_contracts/artifacts || (echo "::error ::Smart contract artifacts have changed, ensure committed artifacts are up to date" && exit 1); + + - name: Run deployer against LocalNet + run: poetry run python -m smart_contracts deploy diff --git a/tests_generated/test_use_typescript_jest-False/.github/workflows/pr.yaml b/tests_generated/test_use_typescript_jest-False/.github/workflows/pr.yaml new file mode 100644 index 0000000..a80f784 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-False/.github/workflows/pr.yaml @@ -0,0 +1,8 @@ +name: Pull Request validation + +on: [pull_request] + +jobs: + pr-check: + name: Perform Checks + uses: ./.github/workflows/checks.yaml diff --git a/tests_generated/test_use_typescript_jest-False/.gitignore b/tests_generated/test_use_typescript_jest-False/.gitignore new file mode 100644 index 0000000..4a926bb --- /dev/null +++ b/tests_generated/test_use_typescript_jest-False/.gitignore @@ -0,0 +1,178 @@ +# 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/ diff --git a/tests_generated/test_use_typescript_jest-False/.pre-commit-config.yaml b/tests_generated/test_use_typescript_jest-False/.pre-commit-config.yaml new file mode 100644 index 0000000..93bfff5 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-False/.pre-commit-config.yaml @@ -0,0 +1,38 @@ +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: [ --fix ] + require_serial: false + additional_dependencies: [ ] + minimum_pre_commit_version: '0' + files: '^(src|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: '^(src|tests)/' + diff --git a/tests_generated/test_use_typescript_jest-False/.vscode/extensions.json b/tests_generated/test_use_typescript_jest-False/.vscode/extensions.json new file mode 100644 index 0000000..ee83617 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-False/.vscode/extensions.json @@ -0,0 +1,11 @@ +{ + "recommendations": [ + "ms-python.python", + "charliermarsh.ruff", + "matangover.mypy", + "ms-python.black-formatter", + "tamasfe.even-better-toml", + "editorconfig.editorconfig", + "algorandfoundation.algokit-avm-vscode-debugger" + ] +} diff --git a/tests_generated/test_use_typescript_jest-False/.vscode/launch.json b/tests_generated/test_use_typescript_jest-False/.vscode/launch.json new file mode 100644 index 0000000..d127326 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-False/.vscode/launch.json @@ -0,0 +1,31 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Build & Deploy Puya application", + "type": "python", + "request": "launch", + "module": "smart_contracts", + "cwd": "${workspaceFolder}", + "preLaunchTask": "Start AlgoKit LocalNet", + "envFile": "${workspaceFolder}/.env.localnet" + }, + { + "name": "Deploy Built Puya application", + "type": "python", + "request": "launch", + "module": "smart_contracts", + "args": ["deploy"], + "cwd": "${workspaceFolder}", + "envFile": "${workspaceFolder}/.env.localnet" + }, + { + "name": "Build Puya application", + "type": "python", + "request": "launch", + "module": "smart_contracts", + "args": ["build"], + "cwd": "${workspaceFolder}" + } + ] +} diff --git a/tests_generated/test_use_typescript_jest-False/.vscode/settings.json b/tests_generated/test_use_typescript_jest-False/.vscode/settings.json new file mode 100644 index 0000000..0c2dfec --- /dev/null +++ b/tests_generated/test_use_typescript_jest-False/.vscode/settings.json @@ -0,0 +1,49 @@ +{ + // 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.defaultInterpreterPath": "${workspaceFolder}/.venv", + "[python]": { + "editor.codeActionsOnSave": { + "source.fixAll": true, + // Prevent default import sorting from running; Ruff will sort imports for us anyway + "source.organizeImports": false + }, + "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/tests_generated/test_use_typescript_jest-False/.vscode/tasks.json b/tests_generated/test_use_typescript_jest-False/.vscode/tasks.json new file mode 100644 index 0000000..4873ec8 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-False/.vscode/tasks.json @@ -0,0 +1,64 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Build Puya application", + "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 Puya application (+ 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": [] + } + ] +} diff --git a/tests_generated/test_use_typescript_jest-False/README.md b/tests_generated/test_use_typescript_jest-False/README.md new file mode 100644 index 0000000..11ebc45 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-False/README.md @@ -0,0 +1,115 @@ +# test_use_typescript_jest-False + +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) + +> Please note `Puya` smart contract development language is currently in alpha / developer preview. It is not recommended for production usage yet. + +### Initial setup + +1. Clone this repository locally +2. Install pre-requisites: + - Make sure to have [Docker](https://www.docker.com/) installed and running on your machine. + - Install `AlgoKit` - [Link](https://github.com/algorandfoundation/algokit-cli#install): The recommended version is `1.7.3`. Ensure you can execute `algokit --version` and get `1.7.1` or later. + - Bootstrap your local environment; run `algokit bootstrap all` within this folder, which will: + - Install `Poetry` - [Link](https://python-poetry.org/docs/#installation): The minimum required version is `^1.7`. Ensure you can execute `poetry -V` and get `1.2`+ + - Run `poetry install` in the root directory, which will set up a `.venv` folder with a Python virtual environment and also install all Python dependencies + - Copy `.env.template` to `.env` + - Run `algokit localnet start` to start a local Algorand network in Docker. If you are using VS Code launch configurations provided by the template, this will be done automatically for you. +3. Open the project and start debugging / developing via: + - VS Code + 1. Open the repository root in VS Code + 2. Install recommended extensions + 3. Hit F5 (or whatever you have debug mapped to) and it should start running with breakpoint debugging. + > **Note** + > If using Windows: Before running for the first time you will need to select the Python Interpreter. + 1. Open the command palette (Ctrl/Cmd + Shift + P) + 2. Search for `Python: Select Interpreter` + 3. Select `./.venv/Scripts/python.exe` + - JetBrains IDEs (please note, this setup is primarily optimized for PyCharm Community Edition) + 1. Open the repository root in the IDE + 2. It should automatically detect it's a Poetry project and set up a Python interpreter and virtual environment. + 3. Hit Shift+F10|Ctrl+R (or whatever you have debug mapped to) and it should start running with breakpoint debugging. Please note, JetBrains IDEs on Windows have a known bug that in some cases may prevent executing shell scripts as pre-launch tasks, for workarounds refer to [JetBrains forums](https://youtrack.jetbrains.com/issue/IDEA-277486/Shell-script-configuration-cannot-run-as-before-launch-task). + - Other + 1. Open the repository root in your text editor of choice + 2. In a terminal run `poetry shell` + 3. Run `python -m smart_contracts` through your debugger of choice + +### Subsequently + +1. If you update to the latest source code and there are new dependencies you will need to run `algokit bootstrap all` again +2. Follow step 3 above + +> For guidance on `smart_contracts` folder and adding new contracts to the project please see [README](smart_contracts/README.md) on the respective folder.### 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. + +### 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). + +#### 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/) + - Python tests are executed using [pytest](https://docs.pytest.org/) + - 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 + +#### 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 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) +- [Puya](https://github.com/algorand-foundation/puya) - Smart contract development framework for developing Algorand smart contracts in pure Python; [docs](https://github.com/algorandfoundation/puya), [examples](https://github.com/algorandfoundation/puya/tree/main/examples) +- [PyTEAL](https://github.com/algorand/pyteal) - Python language binding for Algorand smart contracts; [docs](https://pyteal.readthedocs.io/en/stable/) +- [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/tests_generated/test_use_typescript_jest-False/poetry.toml b/tests_generated/test_use_typescript_jest-False/poetry.toml new file mode 100644 index 0000000..ab1033b --- /dev/null +++ b/tests_generated/test_use_typescript_jest-False/poetry.toml @@ -0,0 +1,2 @@ +[virtualenvs] +in-project = true diff --git a/tests_generated/test_use_typescript_jest-False/pyproject.toml b/tests_generated/test_use_typescript_jest-False/pyproject.toml new file mode 100644 index 0000000..bde7162 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-False/pyproject.toml @@ -0,0 +1,50 @@ +[tool.poetry] +name = "test_use_typescript_jest-False" +version = "0.1.0" +description = "Algorand smart contracts" +authors = ["None "] +readme = "README.md" + +[tool.poetry.dependencies] +python = "^3.12" +algokit-utils = "^2.0.1" +python-dotenv = "^1.0.0" +puya = "^0.1.3" + +[tool.poetry.group.dev.dependencies] +black = {extras = ["d"], version = "*"} +ruff = "^0.1.6" +mypy = "*" +pytest = "*" +pytest-cov = "*" +pip-audit = "*" +pre-commit = "*" + +[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" +check_untyped_defs = true +warn_redundant_casts = true +warn_unused_ignores = true +allow_untyped_defs = false +strict_equality = true diff --git a/tests_generated/test_use_typescript_jest-False/smart_contracts/README.md b/tests_generated/test_use_typescript_jest-False/smart_contracts/README.md new file mode 100644 index 0000000..f765c95 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-False/smart_contracts/README.md @@ -0,0 +1,9 @@ +## How to add new smart contracts? + +By the 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 under `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 under `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. 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. diff --git a/tests_generated/test_deployment_language-typescript/tests/__init__.py b/tests_generated/test_use_typescript_jest-False/smart_contracts/__init__.py similarity index 100% rename from tests_generated/test_deployment_language-typescript/tests/__init__.py rename to tests_generated/test_use_typescript_jest-False/smart_contracts/__init__.py diff --git a/tests_generated/test_use_typescript_jest-False/smart_contracts/__main__.py b/tests_generated/test_use_typescript_jest-False/smart_contracts/__main__.py new file mode 100644 index 0000000..75df051 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-False/smart_contracts/__main__.py @@ -0,0 +1,46 @@ +import logging +import sys +from pathlib import Path + +from dotenv import load_dotenv + +from smart_contracts.config import contracts +from smart_contracts.helpers.build import build +from smart_contracts.helpers.deploy import deploy + +logging.basicConfig( + level=logging.DEBUG, format="%(asctime)s %(levelname)-10s: %(message)s" +) +logger = logging.getLogger(__name__) +logger.info("Loading .env") +load_dotenv() +root_path = Path(__file__).parent + + +def main(action: str) -> None: + artifact_path = root_path / "artifacts" + match action: + case "build": + for contract in contracts: + logger.info(f"Building app at {contract.path}") + build(artifact_path / contract.name, contract.path) + case "deploy": + for contract in contracts: + logger.info(f"Deploying app {contract.name}") + app_spec_path = artifact_path / contract.name / "application.json" + if contract.deploy: + deploy(app_spec_path, contract.deploy) + case "all": + for contract in contracts: + logger.info(f"Building app at {contract.path}") + app_spec_path = build(artifact_path / contract.name, contract.path) + logger.info(f"Deploying {contract.path.name}") + if contract.deploy: + deploy(app_spec_path, contract.deploy) + + +if __name__ == "__main__": + if len(sys.argv) > 1: + main(sys.argv[1]) + else: + main("all") diff --git a/tests_generated/test_use_typescript_jest-False/smart_contracts/config.py b/tests_generated/test_use_typescript_jest-False/smart_contracts/config.py new file mode 100644 index 0000000..9c9076a --- /dev/null +++ b/tests_generated/test_use_typescript_jest-False/smart_contracts/config.py @@ -0,0 +1,60 @@ +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 + 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/tests_generated/test_use_typescript_jest-False/smart_contracts/hello_world/contract.py b/tests_generated/test_use_typescript_jest-False/smart_contracts/hello_world/contract.py new file mode 100644 index 0000000..1b8fddb --- /dev/null +++ b/tests_generated/test_use_typescript_jest-False/smart_contracts/hello_world/contract.py @@ -0,0 +1,8 @@ +from puyapy import ARC4Contract, Bytes +from puyapy.arc4 import String, abimethod + + +class HelloWorld(ARC4Contract): + @abimethod() + def hello(self, name: String) -> String: + return String.encode(Bytes(b"Hello ") + name.decode()) diff --git a/tests_generated/test_use_typescript_jest-False/smart_contracts/hello_world/deploy_config.py b/tests_generated/test_use_typescript_jest-False/smart_contracts/hello_world/deploy_config.py new file mode 100644 index 0000000..82e67a8 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-False/smart_contracts/hello_world/deploy_config.py @@ -0,0 +1,36 @@ +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.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/tests_generated/test_smart_contract_generator_default_production_preset_typescript/tests/__init__.py b/tests_generated/test_use_typescript_jest-False/smart_contracts/helpers/__init__.py similarity index 100% rename from tests_generated/test_smart_contract_generator_default_production_preset_typescript/tests/__init__.py rename to tests_generated/test_use_typescript_jest-False/smart_contracts/helpers/__init__.py diff --git a/tests_generated/test_use_typescript_jest-False/smart_contracts/helpers/build.py b/tests_generated/test_use_typescript_jest-False/smart_contracts/helpers/build.py new file mode 100644 index 0000000..0dad0c8 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-False/smart_contracts/helpers/build.py @@ -0,0 +1,56 @@ +import logging +import subprocess +from pathlib import Path +from shutil import rmtree + +logger = logging.getLogger(__name__) +deployment_extension = "py" + + +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( + [ + "poetry", + "run", + "puyapy", + contract_path.absolute(), + f"--out-dir={output_dir}", + "--output-arc32", + ], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True, + ) + if build_result.returncode: + raise Exception(f"Could not build contract:\n{build_result.stdout}") + + generate_result = subprocess.run( + [ + "algokit", + "generate", + "client", + output_dir / "application.json", + "--output", + output_dir / f"client.{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 1.1 or " + "later. Please update AlgoKit" + ) + else: + raise Exception( + f"Could not generate typed client:\n{generate_result.stdout}" + ) + return output_dir / "application.json" diff --git a/tests_generated/test_use_typescript_jest-False/smart_contracts/helpers/deploy.py b/tests_generated/test_use_typescript_jest-False/smart_contracts/helpers/deploy.py new file mode 100644 index 0000000..08367a3 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-False/smart_contracts/helpers/deploy.py @@ -0,0 +1,50 @@ +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/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/tests/__init__.py b/tests_generated/test_use_typescript_jest-False/tests/__init__.py similarity index 100% rename from tests_generated/test_smart_contract_generator_default_starter_preset_typescript/tests/__init__.py rename to tests_generated/test_use_typescript_jest-False/tests/__init__.py diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/tests/conftest.py b/tests_generated/test_use_typescript_jest-False/tests/conftest.py similarity index 78% rename from tests_generated/test_smart_contract_generator_default_starter_preset_typescript/tests/conftest.py rename to tests_generated/test_use_typescript_jest-False/tests/conftest.py index 06a89eb..b0622e7 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/tests/conftest.py +++ b/tests_generated/test_use_typescript_jest-False/tests/conftest.py @@ -3,9 +3,11 @@ import pytest from algokit_utils import ( get_algod_client, + get_indexer_client, is_localnet, ) from algosdk.v2client.algod import AlgodClient +from algosdk.v2client.indexer import IndexerClient from dotenv import load_dotenv @@ -23,3 +25,8 @@ def algod_client() -> AlgodClient: # included here to prevent accidentally running against other networks assert is_localnet(client) return client + + +@pytest.fixture(scope="session") +def indexer_client() -> IndexerClient: + return get_indexer_client() diff --git a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/tests/hello_world_test.py b/tests_generated/test_use_typescript_jest-False/tests/hello_world_test.py similarity index 62% rename from tests_generated/test_smart_contract_generator_default_production_preset_typescript/tests/hello_world_test.py rename to tests_generated/test_use_typescript_jest-False/tests/hello_world_test.py index f4262b9..0506685 100644 --- a/tests_generated/test_smart_contract_generator_default_production_preset_typescript/tests/hello_world_test.py +++ b/tests_generated/test_use_typescript_jest-False/tests/hello_world_test.py @@ -1,6 +1,7 @@ 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 @@ -11,6 +12,11 @@ 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), @@ -30,3 +36,15 @@ 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/tests_generated/test_use_typescript_jest-True/.algokit.toml b/tests_generated/test_use_typescript_jest-True/.algokit.toml new file mode 100644 index 0000000..4a26acf --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/.algokit.toml @@ -0,0 +1,15 @@ +[algokit] +min_version = "v1.8.0" + +[deploy] +command = "poetry run python -m smart_contracts deploy" +environment_secrets = [ + "DEPLOYER_MNEMONIC", +] + +[deploy.localnet] +environment_secrets = [] + +[generate.smart_contract] +description = "Adds new smart contract to existing project" +path = ".algokit/generators/create_contract" diff --git a/tests_generated/test_use_typescript_jest-True/.copier-answers.yml b/tests_generated/test_use_typescript_jest-True/.copier-answers.yml new file mode 100644 index 0000000..20703f1 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/.copier-answers.yml @@ -0,0 +1,16 @@ +# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY +_commit: +_src_path: +algod_port: 4001 +algod_server: http://localhost +algod_token: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +author_email: None +author_name: None +contract_name: hello_world +deployment_language: python +ide_vscode: true +indexer_port: 8980 +indexer_server: http://localhost +indexer_token: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +project_name: test_use_typescript_jest-True + diff --git a/tests_generated/test_use_typescript_jest-True/.editorconfig b/tests_generated/test_use_typescript_jest-True/.editorconfig new file mode 100644 index 0000000..e2fda34 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/.editorconfig @@ -0,0 +1,10 @@ +root=true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true + +[*.py] +indent_size = 4 diff --git a/tests_generated/test_use_typescript_jest-True/.env.localnet.template b/tests_generated/test_use_typescript_jest-True/.env.localnet.template new file mode 100644 index 0000000..fcbf442 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/.env.localnet.template @@ -0,0 +1,7 @@ +# 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/tests_generated/test_use_typescript_jest-True/.env.template b/tests_generated/test_use_typescript_jest-True/.env.template new file mode 100644 index 0000000..184b393 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/.env.template @@ -0,0 +1 @@ +# this file should contain environment variables common to all environments/networks diff --git a/tests_generated/test_use_typescript_jest-True/.env.testnet.template b/tests_generated/test_use_typescript_jest-True/.env.testnet.template new file mode 100644 index 0000000..eeea43d --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/.env.testnet.template @@ -0,0 +1,3 @@ +# 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/tests_generated/test_use_typescript_jest-True/.gitattributes b/tests_generated/test_use_typescript_jest-True/.gitattributes new file mode 100644 index 0000000..6313b56 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/tests_generated/test_use_typescript_jest-True/.github/workflows/cd.yaml b/tests_generated/test_use_typescript_jest-True/.github/workflows/cd.yaml new file mode 100644 index 0000000..3e0fd45 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/.github/workflows/cd.yaml @@ -0,0 +1,50 @@ +name: Continuous Delivery of Smart Contract + +on: + push: + branches: + - main + +concurrency: release + +jobs: + ci-check: + name: Perform Checks + uses: ./.github/workflows/checks.yaml + + deploy-testnet: + runs-on: 'ubuntu-latest' + needs: ci-check + environment: Test + steps: + - name: Checkout source code + uses: actions/checkout@v3 + + - name: Install poetry + run: pipx install poetry + + - name: Set up Python 3.12 + uses: actions/setup-python@v4 + with: + python-version: '3.12' + cache: 'poetry' + + - name: Install algokit + run: pipx install algokit + + - name: Bootstrap dependencies + run: algokit 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 deploy testnet + env: + # This is the account that becomes the creator of the contract. + # Since we are not using the optional dispenser account (via DISPENSER_MNEMONIC), + # it must also be funded with enough Algos to deploy and fund the smart contracts created + DEPLOYER_MNEMONIC: ${{ secrets.DEPLOYER_MNEMONIC }} diff --git a/tests_generated/test_use_typescript_jest-True/.github/workflows/checks.yaml b/tests_generated/test_use_typescript_jest-True/.github/workflows/checks.yaml new file mode 100644 index 0000000..f6d0102 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/.github/workflows/checks.yaml @@ -0,0 +1,79 @@ +name: Check code base + +on: + workflow_call: + +jobs: + checks: + runs-on: 'ubuntu-latest' + steps: + - name: Checkout source code + uses: actions/checkout@v3 + + - name: Install poetry + run: pipx install poetry + + - name: Set up Python 3.12 + uses: actions/setup-python@v4 + 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 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 with pip-audit + run: | + # audit non dev dependencies, no exclusions + poetry export --without=dev > requirements.txt && poetry run pip-audit -r requirements.txt + + # audit all dependencies, with exclusions. + # If a vulnerability is found in a dev dependency without an available fix, + # it can be temporarily ignored by adding --ignore-vuln e.g. + # --ignore-vuln "GHSA-hcpj-qp55-gfph" # GitPython vulnerability, dev only dependency + poetry run pip-audit + + - name: Check formatting with Black + run: | + # stop the build if there are files that don't meet formatting requirements + poetry run black --check . + + - name: Check linting with Ruff + run: | + # stop the build if there are Python syntax errors or undefined names + poetry run ruff . + + - name: Check types with mypy + run: poetry run mypy + + - name: Run tests + shell: bash + run: | + set -o pipefail + poetry run pytest --junitxml=pytest-junit.xml + + - name: Build smart contracts + run: poetry run python -m smart_contracts build + + - name: Check output stability of the smart contracts + shell: bash + run: | + # Add untracked files as empty so they come up in diff + git add -N ./smart_contracts/artifacts + # Error out if there are any changes in teal after generating output + git diff --exit-code --minimal ./smart_contracts/artifacts || (echo "::error ::Smart contract artifacts have changed, ensure committed artifacts are up to date" && exit 1); + + - name: Run deployer against LocalNet + run: poetry run python -m smart_contracts deploy diff --git a/tests_generated/test_use_typescript_jest-True/.github/workflows/pr.yaml b/tests_generated/test_use_typescript_jest-True/.github/workflows/pr.yaml new file mode 100644 index 0000000..a80f784 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/.github/workflows/pr.yaml @@ -0,0 +1,8 @@ +name: Pull Request validation + +on: [pull_request] + +jobs: + pr-check: + name: Perform Checks + uses: ./.github/workflows/checks.yaml diff --git a/tests_generated/test_use_typescript_jest-True/.gitignore b/tests_generated/test_use_typescript_jest-True/.gitignore new file mode 100644 index 0000000..4a926bb --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/.gitignore @@ -0,0 +1,178 @@ +# 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/ diff --git a/tests_generated/test_use_typescript_jest-True/.pre-commit-config.yaml b/tests_generated/test_use_typescript_jest-True/.pre-commit-config.yaml new file mode 100644 index 0000000..93bfff5 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/.pre-commit-config.yaml @@ -0,0 +1,38 @@ +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: [ --fix ] + require_serial: false + additional_dependencies: [ ] + minimum_pre_commit_version: '0' + files: '^(src|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: '^(src|tests)/' + diff --git a/tests_generated/test_use_typescript_jest-True/.prettierignore b/tests_generated/test_use_typescript_jest-True/.prettierignore new file mode 100644 index 0000000..dbda6ae --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/.prettierignore @@ -0,0 +1,12 @@ +# 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/tests_generated/test_use_typescript_jest-True/.prettierrc.js b/tests_generated/test_use_typescript_jest-True/.prettierrc.js new file mode 100644 index 0000000..c484d0e --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/.prettierrc.js @@ -0,0 +1,10 @@ +module.exports = { + singleQuote: true, + jsxSingleQuote: false, + semi: false, + tabWidth: 2, + trailingComma: 'all', + printWidth: 120, + endOfLine: 'lf', + arrowParens: 'always', +} diff --git a/tests_generated/test_use_typescript_jest-True/.vscode/extensions.json b/tests_generated/test_use_typescript_jest-True/.vscode/extensions.json new file mode 100644 index 0000000..ee83617 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/.vscode/extensions.json @@ -0,0 +1,11 @@ +{ + "recommendations": [ + "ms-python.python", + "charliermarsh.ruff", + "matangover.mypy", + "ms-python.black-formatter", + "tamasfe.even-better-toml", + "editorconfig.editorconfig", + "algorandfoundation.algokit-avm-vscode-debugger" + ] +} diff --git a/tests_generated/test_use_typescript_jest-True/.vscode/launch.json b/tests_generated/test_use_typescript_jest-True/.vscode/launch.json new file mode 100644 index 0000000..d127326 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/.vscode/launch.json @@ -0,0 +1,31 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Build & Deploy Puya application", + "type": "python", + "request": "launch", + "module": "smart_contracts", + "cwd": "${workspaceFolder}", + "preLaunchTask": "Start AlgoKit LocalNet", + "envFile": "${workspaceFolder}/.env.localnet" + }, + { + "name": "Deploy Built Puya application", + "type": "python", + "request": "launch", + "module": "smart_contracts", + "args": ["deploy"], + "cwd": "${workspaceFolder}", + "envFile": "${workspaceFolder}/.env.localnet" + }, + { + "name": "Build Puya application", + "type": "python", + "request": "launch", + "module": "smart_contracts", + "args": ["build"], + "cwd": "${workspaceFolder}" + } + ] +} diff --git a/tests_generated/test_use_typescript_jest-True/.vscode/settings.json b/tests_generated/test_use_typescript_jest-True/.vscode/settings.json new file mode 100644 index 0000000..0c2dfec --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/.vscode/settings.json @@ -0,0 +1,49 @@ +{ + // 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.defaultInterpreterPath": "${workspaceFolder}/.venv", + "[python]": { + "editor.codeActionsOnSave": { + "source.fixAll": true, + // Prevent default import sorting from running; Ruff will sort imports for us anyway + "source.organizeImports": false + }, + "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/tests_generated/test_use_typescript_jest-True/.vscode/tasks.json b/tests_generated/test_use_typescript_jest-True/.vscode/tasks.json new file mode 100644 index 0000000..4873ec8 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/.vscode/tasks.json @@ -0,0 +1,64 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Build Puya application", + "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 Puya application (+ 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": [] + } + ] +} diff --git a/tests_generated/test_use_typescript_jest-True/README.md b/tests_generated/test_use_typescript_jest-True/README.md new file mode 100644 index 0000000..a7003ff --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/README.md @@ -0,0 +1,115 @@ +# test_use_typescript_jest-True + +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) + +> Please note `Puya` smart contract development language is currently in alpha / developer preview. It is not recommended for production usage yet. + +### Initial setup + +1. Clone this repository locally +2. Install pre-requisites: + - Make sure to have [Docker](https://www.docker.com/) installed and running on your machine. + - Install `AlgoKit` - [Link](https://github.com/algorandfoundation/algokit-cli#install): The recommended version is `1.7.3`. Ensure you can execute `algokit --version` and get `1.7.1` or later. + - Bootstrap your local environment; run `algokit bootstrap all` within this folder, which will: + - Install `Poetry` - [Link](https://python-poetry.org/docs/#installation): The minimum required version is `^1.7`. Ensure you can execute `poetry -V` and get `1.2`+ + - Run `poetry install` in the root directory, which will set up a `.venv` folder with a Python virtual environment and also install all Python dependencies + - Copy `.env.template` to `.env` + - Run `algokit localnet start` to start a local Algorand network in Docker. If you are using VS Code launch configurations provided by the template, this will be done automatically for you. +3. Open the project and start debugging / developing via: + - VS Code + 1. Open the repository root in VS Code + 2. Install recommended extensions + 3. Hit F5 (or whatever you have debug mapped to) and it should start running with breakpoint debugging. + > **Note** + > If using Windows: Before running for the first time you will need to select the Python Interpreter. + 1. Open the command palette (Ctrl/Cmd + Shift + P) + 2. Search for `Python: Select Interpreter` + 3. Select `./.venv/Scripts/python.exe` + - JetBrains IDEs (please note, this setup is primarily optimized for PyCharm Community Edition) + 1. Open the repository root in the IDE + 2. It should automatically detect it's a Poetry project and set up a Python interpreter and virtual environment. + 3. Hit Shift+F10|Ctrl+R (or whatever you have debug mapped to) and it should start running with breakpoint debugging. Please note, JetBrains IDEs on Windows have a known bug that in some cases may prevent executing shell scripts as pre-launch tasks, for workarounds refer to [JetBrains forums](https://youtrack.jetbrains.com/issue/IDEA-277486/Shell-script-configuration-cannot-run-as-before-launch-task). + - Other + 1. Open the repository root in your text editor of choice + 2. In a terminal run `poetry shell` + 3. Run `python -m smart_contracts` through your debugger of choice + +### Subsequently + +1. If you update to the latest source code and there are new dependencies you will need to run `algokit bootstrap all` again +2. Follow step 3 above + +> For guidance on `smart_contracts` folder and adding new contracts to the project please see [README](smart_contracts/README.md) on the respective folder.### 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. + +### 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). + +#### 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/) + - Python tests are executed using [pytest](https://docs.pytest.org/) + - 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 + +#### 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 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) +- [Puya](https://github.com/algorand-foundation/puya) - Smart contract development framework for developing Algorand smart contracts in pure Python; [docs](https://github.com/algorandfoundation/puya), [examples](https://github.com/algorandfoundation/puya/tree/main/examples) +- [PyTEAL](https://github.com/algorand/pyteal) - Python language binding for Algorand smart contracts; [docs](https://pyteal.readthedocs.io/en/stable/) +- [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/tests_generated/test_use_typescript_jest-True/jest.config.ts b/tests_generated/test_use_typescript_jest-True/jest.config.ts new file mode 100644 index 0000000..381e1e0 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/jest.config.ts @@ -0,0 +1,16 @@ +/* + * 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 deployment_language == 'typescript' %}package.json{% endif %}.jinja b/tests_generated/test_use_typescript_jest-True/package.json similarity index 80% rename from template_content/{% if deployment_language == 'typescript' %}package.json{% endif %}.jinja rename to tests_generated/test_use_typescript_jest-True/package.json index 927b682..4afc3fb 100644 --- a/template_content/{% if deployment_language == 'typescript' %}package.json{% endif %}.jinja +++ b/tests_generated/test_use_typescript_jest-True/package.json @@ -6,18 +6,21 @@ "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": ">=18.0" }, "dependencies": { - "@algorandfoundation/algokit-utils": "^3.0.0", + "@algorandfoundation/algokit-utils": "^5.1.0", "algosdk": "^2.5.0" }, "devDependencies": { + "@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/tests_generated/test_use_typescript_jest-True/poetry.toml b/tests_generated/test_use_typescript_jest-True/poetry.toml new file mode 100644 index 0000000..ab1033b --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/poetry.toml @@ -0,0 +1,2 @@ +[virtualenvs] +in-project = true diff --git a/tests_generated/test_use_typescript_jest-True/pyproject.toml b/tests_generated/test_use_typescript_jest-True/pyproject.toml new file mode 100644 index 0000000..7994419 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/pyproject.toml @@ -0,0 +1,50 @@ +[tool.poetry] +name = "test_use_typescript_jest-True" +version = "0.1.0" +description = "Algorand smart contracts" +authors = ["None "] +readme = "README.md" + +[tool.poetry.dependencies] +python = "^3.12" +algokit-utils = "^2.0.1" +python-dotenv = "^1.0.0" +puya = "^0.1.3" + +[tool.poetry.group.dev.dependencies] +black = {extras = ["d"], version = "*"} +ruff = "^0.1.6" +mypy = "*" +pytest = "*" +pytest-cov = "*" +pip-audit = "*" +pre-commit = "*" + +[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" +check_untyped_defs = true +warn_redundant_casts = true +warn_unused_ignores = true +allow_untyped_defs = false +strict_equality = true diff --git a/tests_generated/test_use_typescript_jest-True/smart_contracts/README.md b/tests_generated/test_use_typescript_jest-True/smart_contracts/README.md new file mode 100644 index 0000000..f765c95 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/smart_contracts/README.md @@ -0,0 +1,9 @@ +## How to add new smart contracts? + +By the 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 under `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 under `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. 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. diff --git a/tests_generated/test_use_typescript_jest-True/smart_contracts/__init__.py b/tests_generated/test_use_typescript_jest-True/smart_contracts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests_generated/test_use_typescript_jest-True/smart_contracts/__main__.py b/tests_generated/test_use_typescript_jest-True/smart_contracts/__main__.py new file mode 100644 index 0000000..75df051 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/smart_contracts/__main__.py @@ -0,0 +1,46 @@ +import logging +import sys +from pathlib import Path + +from dotenv import load_dotenv + +from smart_contracts.config import contracts +from smart_contracts.helpers.build import build +from smart_contracts.helpers.deploy import deploy + +logging.basicConfig( + level=logging.DEBUG, format="%(asctime)s %(levelname)-10s: %(message)s" +) +logger = logging.getLogger(__name__) +logger.info("Loading .env") +load_dotenv() +root_path = Path(__file__).parent + + +def main(action: str) -> None: + artifact_path = root_path / "artifacts" + match action: + case "build": + for contract in contracts: + logger.info(f"Building app at {contract.path}") + build(artifact_path / contract.name, contract.path) + case "deploy": + for contract in contracts: + logger.info(f"Deploying app {contract.name}") + app_spec_path = artifact_path / contract.name / "application.json" + if contract.deploy: + deploy(app_spec_path, contract.deploy) + case "all": + for contract in contracts: + logger.info(f"Building app at {contract.path}") + app_spec_path = build(artifact_path / contract.name, contract.path) + logger.info(f"Deploying {contract.path.name}") + if contract.deploy: + deploy(app_spec_path, contract.deploy) + + +if __name__ == "__main__": + if len(sys.argv) > 1: + main(sys.argv[1]) + else: + main("all") diff --git a/tests_generated/test_use_typescript_jest-True/smart_contracts/config.py b/tests_generated/test_use_typescript_jest-True/smart_contracts/config.py new file mode 100644 index 0000000..9c9076a --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/smart_contracts/config.py @@ -0,0 +1,60 @@ +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 + 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/tests_generated/test_use_typescript_jest-True/smart_contracts/hello_world/contract.py b/tests_generated/test_use_typescript_jest-True/smart_contracts/hello_world/contract.py new file mode 100644 index 0000000..1b8fddb --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/smart_contracts/hello_world/contract.py @@ -0,0 +1,8 @@ +from puyapy import ARC4Contract, Bytes +from puyapy.arc4 import String, abimethod + + +class HelloWorld(ARC4Contract): + @abimethod() + def hello(self, name: String) -> String: + return String.encode(Bytes(b"Hello ") + name.decode()) diff --git a/tests_generated/test_use_typescript_jest-True/smart_contracts/hello_world/deploy_config.py b/tests_generated/test_use_typescript_jest-True/smart_contracts/hello_world/deploy_config.py new file mode 100644 index 0000000..82e67a8 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/smart_contracts/hello_world/deploy_config.py @@ -0,0 +1,36 @@ +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.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/tests_generated/test_use_typescript_jest-True/smart_contracts/helpers/__init__.py b/tests_generated/test_use_typescript_jest-True/smart_contracts/helpers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests_generated/test_use_typescript_jest-True/smart_contracts/helpers/build.py b/tests_generated/test_use_typescript_jest-True/smart_contracts/helpers/build.py new file mode 100644 index 0000000..0dad0c8 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/smart_contracts/helpers/build.py @@ -0,0 +1,56 @@ +import logging +import subprocess +from pathlib import Path +from shutil import rmtree + +logger = logging.getLogger(__name__) +deployment_extension = "py" + + +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( + [ + "poetry", + "run", + "puyapy", + contract_path.absolute(), + f"--out-dir={output_dir}", + "--output-arc32", + ], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True, + ) + if build_result.returncode: + raise Exception(f"Could not build contract:\n{build_result.stdout}") + + generate_result = subprocess.run( + [ + "algokit", + "generate", + "client", + output_dir / "application.json", + "--output", + output_dir / f"client.{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 1.1 or " + "later. Please update AlgoKit" + ) + else: + raise Exception( + f"Could not generate typed client:\n{generate_result.stdout}" + ) + return output_dir / "application.json" diff --git a/tests_generated/test_use_typescript_jest-True/smart_contracts/helpers/deploy.py b/tests_generated/test_use_typescript_jest-True/smart_contracts/helpers/deploy.py new file mode 100644 index 0000000..08367a3 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/smart_contracts/helpers/deploy.py @@ -0,0 +1,50 @@ +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/tests_generated/test_use_typescript_jest-True/tests/__init__.py b/tests_generated/test_use_typescript_jest-True/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests_generated/test_deployment_language-typescript/tests/conftest.py b/tests_generated/test_use_typescript_jest-True/tests/conftest.py similarity index 78% rename from tests_generated/test_deployment_language-typescript/tests/conftest.py rename to tests_generated/test_use_typescript_jest-True/tests/conftest.py index 06a89eb..b0622e7 100644 --- a/tests_generated/test_deployment_language-typescript/tests/conftest.py +++ b/tests_generated/test_use_typescript_jest-True/tests/conftest.py @@ -3,9 +3,11 @@ import pytest from algokit_utils import ( get_algod_client, + get_indexer_client, is_localnet, ) from algosdk.v2client.algod import AlgodClient +from algosdk.v2client.indexer import IndexerClient from dotenv import load_dotenv @@ -23,3 +25,8 @@ def algod_client() -> AlgodClient: # included here to prevent accidentally running against other networks assert is_localnet(client) return client + + +@pytest.fixture(scope="session") +def indexer_client() -> IndexerClient: + return get_indexer_client() diff --git a/tests_generated/test_use_typescript_jest-True/tests/hello-world.spec.ts b/tests_generated/test_use_typescript_jest-True/tests/hello-world.spec.ts new file mode 100644 index 0000000..81e62fa --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/tests/hello-world.spec.ts @@ -0,0 +1,53 @@ +import { algorandFixture } from '@algorandfoundation/algokit-utils/testing' +import { HelloWorldClient } from '../smart_contracts/artifacts/hello_world/client' +import { Account, Algodv2, Indexer } from 'algosdk' +import * as algokit from '@algorandfoundation/algokit-utils' + +describe('hello world contract', () => { + const localnet = algorandFixture() + beforeAll(() => { + algokit.Config.configure({ + debug: true, + // traceAll: true, + }) + }) + beforeEach(localnet.beforeEach) + + const deploy = async (account: Account, algod: Algodv2, indexer: Indexer) => { + const client = new HelloWorldClient( + { + resolveBy: 'creatorAndName', + findExistingUsing: indexer, + sender: account, + creatorAddress: account.addr, + }, + algod, + ) + await client.deploy({ + allowDelete: true, + allowUpdate: true, + onSchemaBreak: 'replace', + onUpdate: 'update', + }) + return { client } + } + + test('says hello', async () => { + const { algod, indexer, testAccount } = localnet.context + const { client } = await deploy(testAccount, algod, indexer) + + const result = await client.hello({ name: 'World' }) + + expect(result.return).toBe('Hello, World') + }) + + test('simulate says hello with correct budget consumed', async () => { + const { algod, indexer, testAccount } = localnet.context + const { client } = await deploy(testAccount, algod, indexer) + const result = await client.compose().hello({ name: 'World' }).hello({ name: 'Jane' }).simulate() + + expect(result.methodResults[0].returnValue).toBe('Hello, World') + expect(result.methodResults[1].returnValue).toBe('Hello, Jane') + expect(result.simulateResponse.txnGroups[0].appBudgetConsumed).toBeLessThan(100) + }) +}) diff --git a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/tests/hello_world_test.py b/tests_generated/test_use_typescript_jest-True/tests/hello_world_test.py similarity index 62% rename from tests_generated/test_smart_contract_generator_default_starter_preset_typescript/tests/hello_world_test.py rename to tests_generated/test_use_typescript_jest-True/tests/hello_world_test.py index f4262b9..0506685 100644 --- a/tests_generated/test_smart_contract_generator_default_starter_preset_typescript/tests/hello_world_test.py +++ b/tests_generated/test_use_typescript_jest-True/tests/hello_world_test.py @@ -1,6 +1,7 @@ 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 @@ -11,6 +12,11 @@ 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), @@ -30,3 +36,15 @@ 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/tests_generated/test_use_typescript_jest-True/tsconfig.json b/tests_generated/test_use_typescript_jest-True/tsconfig.json new file mode 100644 index 0000000..7c76204 --- /dev/null +++ b/tests_generated/test_use_typescript_jest-True/tsconfig.json @@ -0,0 +1,24 @@ +{ + "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, + "moduleResolution": "Node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true + }, + "include": ["src/**/*.ts"], + "exclude": ["node_modules", "dist", "coverage"] +}