diff --git a/.github/workflows/check-python.yaml b/.github/workflows/check-python.yaml index cc493db..bae2ed2 100644 --- a/.github/workflows/check-python.yaml +++ b/.github/workflows/check-python.yaml @@ -44,6 +44,11 @@ jobs: # set git user and email as test invoke git git config --global user.email "actions@github.com" && git config --global user.name "github-actions" + - name: Setup Node.js 20.x + uses: actions/setup-node@v4 + with: + node-version: "20.x" + - name: Run tests shell: bash run: | diff --git a/examples/generators/production_python_smart_contract_python/README.md b/examples/generators/production_python_smart_contract_python/README.md index b41dabd..715d773 100644 --- a/examples/generators/production_python_smart_contract_python/README.md +++ b/examples/generators/production_python_smart_contract_python/README.md @@ -77,15 +77,7 @@ By default the template creates a single `HelloWorld` contract under hello_world By default the template instance does not contain any env files. Using [`algokit project deploy`](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/project/deploy.md) against `localnet` | `testnet` | `mainnet` will use default values for `algod` and `indexer` unless overwritten via `.env` or `.env.{target_network}`. -To generate a new `.env` or `.env.{target_network}` file, run `algokit generate env-file`### Continuous Integration / Continuous Deployment (CI/CD) - -This project uses [GitHub Actions](https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions) to define CI/CD workflows, which are located in the [.github/workflows](`.github/workflows`) folder. - -> Please note, if you instantiated the project with --workspace flag in `algokit init` it will automatically attempt to move the contents of the `.github` folder to the root of the workspace. - -### AlgoKit Workspaces - -To define custom `algokit project run` commands refer to [documentation](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/project/run.md). This allows orchestration of commands spanning across multiple projects within an algokit workspace based project (monorepo). +To generate a new `.env` or `.env.{target_network}` file, run `algokit generate env-file` ### Debugging Smart Contracts @@ -94,7 +86,15 @@ Refer to the commented header in the `__main__.py` file in the `smart_contracts` 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). +For information on using and setting up the `AlgoKit AVM Debugger` VSCode extension refer [here](https://github.com/algorandfoundation/algokit-avm-vscode-debugger). To install the extension from the VSCode Marketplace, use the following link: [AlgoKit AVM Debugger extension](https://marketplace.visualstudio.com/items?itemName=algorandfoundation.algokit-avm-vscode-debugger).### Continuous Integration / Continuous Deployment (CI/CD) + +This project uses [GitHub Actions](https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions) to define CI/CD workflows, which are located in the [.github/workflows](`.github/workflows`) folder. + +> Please note, if you instantiated the project with --workspace flag in `algokit init` it will automatically attempt to move the contents of the `.github` folder to the root of the workspace. + +### AlgoKit Workspaces + +To define custom `algokit project run` commands refer to [documentation](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/project/run.md). This allows orchestration of commands spanning across multiple projects within an algokit workspace based project (monorepo). #### Setting up GitHub for CI/CD workflow and TestNet deployment diff --git a/examples/generators/production_python_smart_contract_python/pyproject.toml b/examples/generators/production_python_smart_contract_python/pyproject.toml index 64cf76d..a340d5f 100644 --- a/examples/generators/production_python_smart_contract_python/pyproject.toml +++ b/examples/generators/production_python_smart_contract_python/pyproject.toml @@ -7,7 +7,7 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.12" -algokit-utils = "^2.3.0" +algokit-utils = { git = "https://github.com/algorandfoundation/algokit-utils-py.git", branch = "feat/puya-debugging" } python-dotenv = "^1.0.0" algorand-python = "^2.0.0" algorand-python-testing = "^0.4.0" @@ -21,7 +21,7 @@ pytest = "*" pytest-cov = "*" pip-audit = "*" pre-commit = "*" -puyapy = "*" +puyapy = { git = "https://github.com/algorandfoundation/puya.git", branch = "main" } [build-system] requires = ["poetry-core"] @@ -57,7 +57,7 @@ warn_redundant_casts = true warn_unused_ignores = true warn_return_any = true strict_equality = true -strict_concatenate = true +extra_checks = true disallow_any_unimported = true disallow_any_expr = true disallow_any_decorated = true diff --git a/examples/generators/production_python_smart_contract_python/smart_contracts/_helpers/build.py b/examples/generators/production_python_smart_contract_python/smart_contracts/_helpers/build.py index 0afee9c..3461154 100644 --- a/examples/generators/production_python_smart_contract_python/smart_contracts/_helpers/build.py +++ b/examples/generators/production_python_smart_contract_python/smart_contracts/_helpers/build.py @@ -31,7 +31,7 @@ def build(output_dir: Path, contract_path: Path) -> Path: contract_path.absolute(), f"--out-dir={output_dir}", "--output-arc32", - "--debug-level=0", + "--output-source-map", ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, diff --git a/examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/deploy-config.ts.j2 b/examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/deploy-config.ts.j2 index ac114cc..bd3ad2d 100644 --- a/examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/deploy-config.ts.j2 +++ b/examples/generators/production_python_smart_contract_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/deploy-config.ts.j2 @@ -1,5 +1,5 @@ import * as algokit from '@algorandfoundation/algokit-utils' -import { {{ contract_name.split('_')|map('capitalize')|join }}Client } from '../artifacts/{{ contract_name }}/{{ contract_name.split('_')|map('capitalize')|join }}Client' +import { {{ contract_name.split('_')|map('capitalize')|join }}Factory } from '../artifacts/{{ contract_name }}/{{ contract_name.split('_')|map('capitalize')|join }}Client' // Below is a showcase of various deployment options you can use in TypeScript Client export async function deploy() { @@ -7,27 +7,27 @@ export async function deploy() { const algorand = algokit.AlgorandClient.fromEnvironment() const deployer = await algorand.account.fromEnvironment('DEPLOYER') - - const appClient = algorand.client.getTypedAppClientByCreatorAndName({{ contract_name.split('_')|map('capitalize')|join }}Client, { - sender: deployer, - creatorAddress: deployer.addr, - }) - const app = await appClient.deploy({ - onSchemaBreak: 'append', - onUpdate: 'append', + const factory = algorand.client.getTypedAppFactory({{ contract_name.split('_')|map('capitalize')|join }}Factory, { + defaultSender: deployer.addr, }) + const { appClient, result } = await factory.deploy({ onUpdate: 'append', onSchemaBreak: 'append' }) + // If app was just created fund the app account - if (['create', 'replace'].includes(app.operationPerformed)) { + if (['create', 'replace'].includes(result.operationPerformed)) { await algorand.send.payment({ - amount: algokit.algos(1), + amount: (1).algo(), sender: deployer.addr, receiver: app.appAddress, }) } - const method = 'hello' - const response = await appClient.hello({ name: 'world' }) - console.log(`Called ${method} on ${app.name} (${app.appId}) with name = world, received: ${response.return}`) + const method = 'hello' + const response = await appClient.send.hello({ + args: { name: 'world' }, + }) + console.log( + `Called ${method} on ${appClient.appClient.appName} (${appClient.appClient.appId}) with name = world, received: ${response.return}`, + ) } diff --git a/examples/generators/production_python_smart_contract_typescript/README.md b/examples/generators/production_python_smart_contract_typescript/README.md index 28c68bb..c2c6505 100644 --- a/examples/generators/production_python_smart_contract_typescript/README.md +++ b/examples/generators/production_python_smart_contract_typescript/README.md @@ -78,15 +78,7 @@ By default the template creates a single `HelloWorld` contract under hello_world By default the template instance does not contain any env files. Using [`algokit project deploy`](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/project/deploy.md) against `localnet` | `testnet` | `mainnet` will use default values for `algod` and `indexer` unless overwritten via `.env` or `.env.{target_network}`. -To generate a new `.env` or `.env.{target_network}` file, run `algokit generate env-file`### Continuous Integration / Continuous Deployment (CI/CD) - -This project uses [GitHub Actions](https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions) to define CI/CD workflows, which are located in the [.github/workflows](`.github/workflows`) folder. - -> Please note, if you instantiated the project with --workspace flag in `algokit init` it will automatically attempt to move the contents of the `.github` folder to the root of the workspace. - -### AlgoKit Workspaces - -To define custom `algokit project run` commands refer to [documentation](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/project/run.md). This allows orchestration of commands spanning across multiple projects within an algokit workspace based project (monorepo). +To generate a new `.env` or `.env.{target_network}` file, run `algokit generate env-file` ### Debugging Smart Contracts @@ -95,7 +87,15 @@ Refer to the commented header in the `index.ts` file in the `smart_contracts` fo 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). +For information on using and setting up the `AlgoKit AVM Debugger` VSCode extension refer [here](https://github.com/algorandfoundation/algokit-avm-vscode-debugger). To install the extension from the VSCode Marketplace, use the following link: [AlgoKit AVM Debugger extension](https://marketplace.visualstudio.com/items?itemName=algorandfoundation.algokit-avm-vscode-debugger).### Continuous Integration / Continuous Deployment (CI/CD) + +This project uses [GitHub Actions](https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions) to define CI/CD workflows, which are located in the [.github/workflows](`.github/workflows`) folder. + +> Please note, if you instantiated the project with --workspace flag in `algokit init` it will automatically attempt to move the contents of the `.github` folder to the root of the workspace. + +### AlgoKit Workspaces + +To define custom `algokit project run` commands refer to [documentation](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/project/run.md). This allows orchestration of commands spanning across multiple projects within an algokit workspace based project (monorepo). #### Setting up GitHub for CI/CD workflow and TestNet deployment diff --git a/examples/generators/production_python_smart_contract_typescript/package.json b/examples/generators/production_python_smart_contract_typescript/package.json index e64561d..4cc398e 100644 --- a/examples/generators/production_python_smart_contract_typescript/package.json +++ b/examples/generators/production_python_smart_contract_typescript/package.json @@ -10,15 +10,16 @@ "format": "prettier --write ." }, "engines": { - "node": ">=18.0", + "node": ">=20.0", "npm": ">=9.0" }, "dependencies": { - "@algorandfoundation/algokit-utils": "^6.0.2", - "algosdk": "^2.7.0" + "@algorandfoundation/algokit-utils": "^7.0.0", + "@algorandfoundation/algokit-utils-debug": "^1.0.2", + "algosdk": ">=2.9.0 <3.0" }, "devDependencies": { - "@algorandfoundation/algokit-client-generator": "^3.0.3", + "@algorandfoundation/algokit-client-generator": "^4.0.0", "@types/jest": "^29.5.11", "dotenv": "^16.0.3", "prettier": "^2.8.4", diff --git a/examples/generators/production_python_smart_contract_typescript/pyproject.toml b/examples/generators/production_python_smart_contract_typescript/pyproject.toml index 0db3c06..174c21f 100644 --- a/examples/generators/production_python_smart_contract_typescript/pyproject.toml +++ b/examples/generators/production_python_smart_contract_typescript/pyproject.toml @@ -7,7 +7,7 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.12" -algokit-utils = "^2.3.0" +algokit-utils = { git = "https://github.com/algorandfoundation/algokit-utils-py.git", branch = "feat/puya-debugging" } python-dotenv = "^1.0.0" algorand-python = "^2.0.0" algorand-python-testing = "^0.4.0" @@ -18,7 +18,7 @@ ruff = "^0.1.6" mypy = "1.11.0" pip-audit = "*" pre-commit = "*" -puyapy = "*" +puyapy = { git = "https://github.com/algorandfoundation/puya.git", branch = "main" } [build-system] requires = ["poetry-core"] @@ -51,7 +51,7 @@ warn_redundant_casts = true warn_unused_ignores = true warn_return_any = true strict_equality = true -strict_concatenate = true +extra_checks = true disallow_any_unimported = true disallow_any_expr = true disallow_any_decorated = true diff --git a/examples/generators/production_python_smart_contract_typescript/smart_contracts/_helpers/build.py b/examples/generators/production_python_smart_contract_typescript/smart_contracts/_helpers/build.py index 2694825..37ceb1f 100644 --- a/examples/generators/production_python_smart_contract_typescript/smart_contracts/_helpers/build.py +++ b/examples/generators/production_python_smart_contract_typescript/smart_contracts/_helpers/build.py @@ -31,7 +31,7 @@ def build(output_dir: Path, contract_path: Path) -> Path: contract_path.absolute(), f"--out-dir={output_dir}", "--output-arc32", - "--debug-level=0", + "--output-source-map", ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, diff --git a/examples/generators/production_python_smart_contract_typescript/smart_contracts/cool_contract/deploy-config.ts b/examples/generators/production_python_smart_contract_typescript/smart_contracts/cool_contract/deploy-config.ts index a5dc036..d629083 100644 --- a/examples/generators/production_python_smart_contract_typescript/smart_contracts/cool_contract/deploy-config.ts +++ b/examples/generators/production_python_smart_contract_typescript/smart_contracts/cool_contract/deploy-config.ts @@ -1,5 +1,5 @@ import * as algokit from '@algorandfoundation/algokit-utils' -import { CoolContractClient } from '../artifacts/cool_contract/CoolContractClient' +import { CoolContractFactory } from '../artifacts/cool_contract/CoolContractClient' // Below is a showcase of various deployment options you can use in TypeScript Client export async function deploy() { @@ -7,27 +7,27 @@ export async function deploy() { const algorand = algokit.AlgorandClient.fromEnvironment() const deployer = await algorand.account.fromEnvironment('DEPLOYER') - - const appClient = algorand.client.getTypedAppClientByCreatorAndName(CoolContractClient, { - sender: deployer, - creatorAddress: deployer.addr, - }) - const app = await appClient.deploy({ - onSchemaBreak: 'append', - onUpdate: 'append', + const factory = algorand.client.getTypedAppFactory(CoolContractFactory, { + defaultSender: deployer.addr, }) + const { appClient, result } = await factory.deploy({ onUpdate: 'append', onSchemaBreak: 'append' }) + // If app was just created fund the app account - if (['create', 'replace'].includes(app.operationPerformed)) { + if (['create', 'replace'].includes(result.operationPerformed)) { await algorand.send.payment({ - amount: algokit.algos(1), + amount: (1).algo(), sender: deployer.addr, receiver: app.appAddress, }) } - const method = 'hello' - const response = await appClient.hello({ name: 'world' }) - console.log(`Called ${method} on ${app.name} (${app.appId}) with name = world, received: ${response.return}`) + const method = 'hello' + const response = await appClient.send.hello({ + args: { name: 'world' }, + }) + console.log( + `Called ${method} on ${appClient.appClient.appName} (${appClient.appClient.appId}) with name = world, received: ${response.return}`, + ) } diff --git a/examples/generators/production_python_smart_contract_typescript/smart_contracts/hello_world/deploy-config.ts b/examples/generators/production_python_smart_contract_typescript/smart_contracts/hello_world/deploy-config.ts index 5df7a31..e0608c9 100644 --- a/examples/generators/production_python_smart_contract_typescript/smart_contracts/hello_world/deploy-config.ts +++ b/examples/generators/production_python_smart_contract_typescript/smart_contracts/hello_world/deploy-config.ts @@ -1,5 +1,5 @@ import * as algokit from '@algorandfoundation/algokit-utils' -import { HelloWorldClient } from '../artifacts/hello_world/HelloWorldClient' +import { HelloWorldFactory } from '../artifacts/hello_world/HelloWorldClient' // Below is a showcase of various deployment options you can use in TypeScript Client export async function deploy() { @@ -8,26 +8,26 @@ export async function deploy() { const algorand = algokit.AlgorandClient.fromEnvironment() const deployer = await algorand.account.fromEnvironment('DEPLOYER') - const appClient = algorand.client.getTypedAppClientByCreatorAndName(HelloWorldClient, { - sender: deployer, - creatorAddress: deployer.addr, + const factory = algorand.client.getTypedAppFactory(HelloWorldFactory, { + defaultSender: deployer.addr, }) - const app = await appClient.deploy({ - onSchemaBreak: 'append', - onUpdate: 'append', - }) + const { appClient, result } = await factory.deploy({ onUpdate: 'append', onSchemaBreak: 'append' }) // If app was just created fund the app account - if (['create', 'replace'].includes(app.operationPerformed)) { + if (['create', 'replace'].includes(result.operationPerformed)) { await algorand.send.payment({ - amount: algokit.algos(1), + amount: (1).algo(), sender: deployer.addr, - receiver: app.appAddress, + receiver: appClient.appAddress, }) } - const method = 'hello' - const response = await appClient.hello({ name: 'world' }) - console.log(`Called ${method} on ${app.name} (${app.appId}) with name = world, received: ${response.return}`) + const method = 'hello' + const response = await appClient.send.hello({ + args: { name: 'world' }, + }) + console.log( + `Called ${method} on ${appClient.appClient.appName} (${appClient.appClient.appId}) with name = world, received: ${response.return}`, + ) } diff --git a/examples/generators/production_python_smart_contract_typescript/smart_contracts/index.ts b/examples/generators/production_python_smart_contract_typescript/smart_contracts/index.ts index 6955e33..623ca2b 100644 --- a/examples/generators/production_python_smart_contract_typescript/smart_contracts/index.ts +++ b/examples/generators/production_python_smart_contract_typescript/smart_contracts/index.ts @@ -2,6 +2,7 @@ import * as fs from 'fs' import * as path from 'path' import { consoleLogger } from '@algorandfoundation/algokit-utils/types/logging' import * as algokit from '@algorandfoundation/algokit-utils' +// import { registerDebugEventHandlers } from '@algorandfoundation/algokit-utils-debug' // Uncomment to enable persisting artifacts required by AlgoKit AVM Debugger // Uncomment the debug and traceAll options to enable auto generation of AVM Debugger compliant sourceMap and simulation trace file. // Learn more about using AlgoKit AVM Debugger to debug your TEAL source codes and inspect various kinds of Algorand transactions in atomic groups -> https://github.com/algorandfoundation/algokit-avm-vscode-Debugger @@ -11,6 +12,7 @@ algokit.Config.configure({ // debug: true, // traceAll: true, }) +// registerDebugEventHandlers() // Uncomment to enable persisting artifacts required by AlgoKit AVM Debugger // base directory const baseDir = path.resolve(__dirname) diff --git a/examples/generators/production_python_smart_contract_typescript/tests/hello-world.spec.ts b/examples/generators/production_python_smart_contract_typescript/tests/hello-world.spec.ts index 0c99f4b..c2ce598 100644 --- a/examples/generators/production_python_smart_contract_typescript/tests/hello-world.spec.ts +++ b/examples/generators/production_python_smart_contract_typescript/tests/hello-world.spec.ts @@ -1,7 +1,8 @@ import { algorandFixture } from '@algorandfoundation/algokit-utils/testing' -import { HelloWorldClient } from '../smart_contracts/artifacts/hello_world/HelloWorldClient' +import { HelloWorldFactory } from '../smart_contracts/artifacts/hello_world/HelloWorldClient' import { Account, Algodv2, Indexer } from 'algosdk' import * as algokit from '@algorandfoundation/algokit-utils' +import { TransactionSignerAccount } from '@algorandfoundation/algokit-utils/types/account' describe('hello world contract', () => { const localnet = algorandFixture() @@ -13,39 +14,36 @@ describe('hello world contract', () => { }) 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', + const deploy = async (account: Account & TransactionSignerAccount) => { + const factory = localnet.algorand.client.getTypedAppFactory(HelloWorldFactory, { + defaultSender: account.addr, + defaultSigner: account.signer, }) - return { client } + + const { appClient } = await factory.deploy({ onUpdate: 'append', onSchemaBreak: 'append' }) + return { client: appClient } } test('says hello', async () => { - const { algod, indexer, testAccount } = localnet.context - const { client } = await deploy(testAccount, algod, indexer) + const { testAccount } = localnet.context + const { client } = await deploy(testAccount) - const result = await client.hello({ name: 'World' }) + const result = await client.send.hello({ args: { 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() + const { testAccount } = localnet.context + const { client } = await deploy(testAccount) + const result = await client + .newGroup() + .hello({ args: { name: 'World' } }) + .hello({ args: { name: 'Jane' } }) + .simulate() - expect(result.methodResults[0].returnValue).toBe('Hello, World') - expect(result.methodResults[1].returnValue).toBe('Hello, Jane') + expect(result.returns[0]).toBe('Hello, World') + expect(result.returns[1]).toBe('Hello, Jane') expect(result.simulateResponse.txnGroups[0].appBudgetConsumed).toBeLessThan(100) }) }) diff --git a/examples/generators/starter_python_smart_contract_python/README.md b/examples/generators/starter_python_smart_contract_python/README.md index fb1bc17..e7d5844 100644 --- a/examples/generators/starter_python_smart_contract_python/README.md +++ b/examples/generators/starter_python_smart_contract_python/README.md @@ -79,6 +79,15 @@ By default the template instance does not contain any env files. Using [`algokit To generate a new `.env` or `.env.{target_network}` file, run `algokit generate env-file` +### Debugging Smart Contracts + +This project is optimized to work with AlgoKit AVM Debugger extension. To activate it: +Refer to the commented header in the `__main__.py` file in the `smart_contracts` folder. + +If you have opted in to include VSCode launch configurations in your project, you can also use the `Debug TEAL via AlgoKit AVM Debugger` launch configuration to interactively select an available trace file and launch the debug session for your smart contract. + +For information on using and setting up the `AlgoKit AVM Debugger` VSCode extension refer [here](https://github.com/algorandfoundation/algokit-avm-vscode-debugger). To install the extension from the VSCode Marketplace, use the following link: [AlgoKit AVM Debugger extension](https://marketplace.visualstudio.com/items?itemName=algorandfoundation.algokit-avm-vscode-debugger). + # Tools This project makes use of Algorand Python to build Algorand smart contracts. The following tools are in use: diff --git a/examples/generators/starter_python_smart_contract_python/pyproject.toml b/examples/generators/starter_python_smart_contract_python/pyproject.toml index 26ee7c1..22393d1 100644 --- a/examples/generators/starter_python_smart_contract_python/pyproject.toml +++ b/examples/generators/starter_python_smart_contract_python/pyproject.toml @@ -7,14 +7,14 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.12" -algokit-utils = "^2.3.0" +algokit-utils = { git = "https://github.com/algorandfoundation/algokit-utils-py.git", branch = "feat/puya-debugging" } python-dotenv = "^1.0.0" algorand-python = "^2.0.0" algorand-python-testing = "^0.4.0" [tool.poetry.group.dev.dependencies] algokit-client-generator = "^1.1.3" -puyapy = "*" +puyapy = { git = "https://github.com/algorandfoundation/puya.git", branch = "main" } [build-system] requires = ["poetry-core"] diff --git a/examples/generators/starter_python_smart_contract_python/smart_contracts/_helpers/build.py b/examples/generators/starter_python_smart_contract_python/smart_contracts/_helpers/build.py index 0afee9c..3461154 100644 --- a/examples/generators/starter_python_smart_contract_python/smart_contracts/_helpers/build.py +++ b/examples/generators/starter_python_smart_contract_python/smart_contracts/_helpers/build.py @@ -31,7 +31,7 @@ def build(output_dir: Path, contract_path: Path) -> Path: contract_path.absolute(), f"--out-dir={output_dir}", "--output-arc32", - "--debug-level=0", + "--output-source-map", ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, diff --git a/examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/deploy-config.ts.j2 b/examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/deploy-config.ts.j2 index ac114cc..bd3ad2d 100644 --- a/examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/deploy-config.ts.j2 +++ b/examples/generators/starter_python_smart_contract_typescript/.algokit/generators/create_contract/smart_contracts/{{ contract_name }}/deploy-config.ts.j2 @@ -1,5 +1,5 @@ import * as algokit from '@algorandfoundation/algokit-utils' -import { {{ contract_name.split('_')|map('capitalize')|join }}Client } from '../artifacts/{{ contract_name }}/{{ contract_name.split('_')|map('capitalize')|join }}Client' +import { {{ contract_name.split('_')|map('capitalize')|join }}Factory } from '../artifacts/{{ contract_name }}/{{ contract_name.split('_')|map('capitalize')|join }}Client' // Below is a showcase of various deployment options you can use in TypeScript Client export async function deploy() { @@ -7,27 +7,27 @@ export async function deploy() { const algorand = algokit.AlgorandClient.fromEnvironment() const deployer = await algorand.account.fromEnvironment('DEPLOYER') - - const appClient = algorand.client.getTypedAppClientByCreatorAndName({{ contract_name.split('_')|map('capitalize')|join }}Client, { - sender: deployer, - creatorAddress: deployer.addr, - }) - const app = await appClient.deploy({ - onSchemaBreak: 'append', - onUpdate: 'append', + const factory = algorand.client.getTypedAppFactory({{ contract_name.split('_')|map('capitalize')|join }}Factory, { + defaultSender: deployer.addr, }) + const { appClient, result } = await factory.deploy({ onUpdate: 'append', onSchemaBreak: 'append' }) + // If app was just created fund the app account - if (['create', 'replace'].includes(app.operationPerformed)) { + if (['create', 'replace'].includes(result.operationPerformed)) { await algorand.send.payment({ - amount: algokit.algos(1), + amount: (1).algo(), sender: deployer.addr, receiver: app.appAddress, }) } - const method = 'hello' - const response = await appClient.hello({ name: 'world' }) - console.log(`Called ${method} on ${app.name} (${app.appId}) with name = world, received: ${response.return}`) + const method = 'hello' + const response = await appClient.send.hello({ + args: { name: 'world' }, + }) + console.log( + `Called ${method} on ${appClient.appClient.appName} (${appClient.appClient.appId}) with name = world, received: ${response.return}`, + ) } diff --git a/examples/generators/starter_python_smart_contract_typescript/README.md b/examples/generators/starter_python_smart_contract_typescript/README.md index 81c6bf4..8d981a3 100644 --- a/examples/generators/starter_python_smart_contract_typescript/README.md +++ b/examples/generators/starter_python_smart_contract_typescript/README.md @@ -80,6 +80,15 @@ By default the template instance does not contain any env files. Using [`algokit To generate a new `.env` or `.env.{target_network}` file, run `algokit generate env-file` +### Debugging Smart Contracts + +This project is optimized to work with AlgoKit AVM Debugger extension. To activate it: +Refer to the commented header in the `index.ts` file in the `smart_contracts` folder. + +If you have opted in to include VSCode launch configurations in your project, you can also use the `Debug TEAL via AlgoKit AVM Debugger` launch configuration to interactively select an available trace file and launch the debug session for your smart contract. + +For information on using and setting up the `AlgoKit AVM Debugger` VSCode extension refer [here](https://github.com/algorandfoundation/algokit-avm-vscode-debugger). To install the extension from the VSCode Marketplace, use the following link: [AlgoKit AVM Debugger extension](https://marketplace.visualstudio.com/items?itemName=algorandfoundation.algokit-avm-vscode-debugger). + # Tools This project makes use of Algorand Python to build Algorand smart contracts. The following tools are in use: diff --git a/examples/generators/starter_python_smart_contract_typescript/package.json b/examples/generators/starter_python_smart_contract_typescript/package.json index e329b0d..5b1fef2 100644 --- a/examples/generators/starter_python_smart_contract_typescript/package.json +++ b/examples/generators/starter_python_smart_contract_typescript/package.json @@ -9,15 +9,16 @@ "format": "prettier --write ." }, "engines": { - "node": ">=18.0", + "node": ">=20.0", "npm": ">=9.0" }, "dependencies": { - "@algorandfoundation/algokit-utils": "^6.0.2", - "algosdk": "^2.7.0" + "@algorandfoundation/algokit-utils": "^7.0.0", + "@algorandfoundation/algokit-utils-debug": "^1.0.2", + "algosdk": ">=2.9.0 <3.0" }, "devDependencies": { - "@algorandfoundation/algokit-client-generator": "^3.0.3", + "@algorandfoundation/algokit-client-generator": "^4.0.0", "dotenv": "^16.0.3", "prettier": "^2.8.4", "ts-node-dev": "^2.0.0", diff --git a/examples/generators/starter_python_smart_contract_typescript/pyproject.toml b/examples/generators/starter_python_smart_contract_typescript/pyproject.toml index 39ddab1..3d0984c 100644 --- a/examples/generators/starter_python_smart_contract_typescript/pyproject.toml +++ b/examples/generators/starter_python_smart_contract_typescript/pyproject.toml @@ -7,13 +7,13 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.12" -algokit-utils = "^2.3.0" +algokit-utils = { git = "https://github.com/algorandfoundation/algokit-utils-py.git", branch = "feat/puya-debugging" } python-dotenv = "^1.0.0" algorand-python = "^2.0.0" algorand-python-testing = "^0.4.0" [tool.poetry.group.dev.dependencies] -puyapy = "*" +puyapy = { git = "https://github.com/algorandfoundation/puya.git", branch = "main" } [build-system] requires = ["poetry-core"] diff --git a/examples/generators/starter_python_smart_contract_typescript/smart_contracts/_helpers/build.py b/examples/generators/starter_python_smart_contract_typescript/smart_contracts/_helpers/build.py index 2694825..37ceb1f 100644 --- a/examples/generators/starter_python_smart_contract_typescript/smart_contracts/_helpers/build.py +++ b/examples/generators/starter_python_smart_contract_typescript/smart_contracts/_helpers/build.py @@ -31,7 +31,7 @@ def build(output_dir: Path, contract_path: Path) -> Path: contract_path.absolute(), f"--out-dir={output_dir}", "--output-arc32", - "--debug-level=0", + "--output-source-map", ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, diff --git a/examples/generators/starter_python_smart_contract_typescript/smart_contracts/cool_contract/deploy-config.ts b/examples/generators/starter_python_smart_contract_typescript/smart_contracts/cool_contract/deploy-config.ts index a5dc036..d629083 100644 --- a/examples/generators/starter_python_smart_contract_typescript/smart_contracts/cool_contract/deploy-config.ts +++ b/examples/generators/starter_python_smart_contract_typescript/smart_contracts/cool_contract/deploy-config.ts @@ -1,5 +1,5 @@ import * as algokit from '@algorandfoundation/algokit-utils' -import { CoolContractClient } from '../artifacts/cool_contract/CoolContractClient' +import { CoolContractFactory } from '../artifacts/cool_contract/CoolContractClient' // Below is a showcase of various deployment options you can use in TypeScript Client export async function deploy() { @@ -7,27 +7,27 @@ export async function deploy() { const algorand = algokit.AlgorandClient.fromEnvironment() const deployer = await algorand.account.fromEnvironment('DEPLOYER') - - const appClient = algorand.client.getTypedAppClientByCreatorAndName(CoolContractClient, { - sender: deployer, - creatorAddress: deployer.addr, - }) - const app = await appClient.deploy({ - onSchemaBreak: 'append', - onUpdate: 'append', + const factory = algorand.client.getTypedAppFactory(CoolContractFactory, { + defaultSender: deployer.addr, }) + const { appClient, result } = await factory.deploy({ onUpdate: 'append', onSchemaBreak: 'append' }) + // If app was just created fund the app account - if (['create', 'replace'].includes(app.operationPerformed)) { + if (['create', 'replace'].includes(result.operationPerformed)) { await algorand.send.payment({ - amount: algokit.algos(1), + amount: (1).algo(), sender: deployer.addr, receiver: app.appAddress, }) } - const method = 'hello' - const response = await appClient.hello({ name: 'world' }) - console.log(`Called ${method} on ${app.name} (${app.appId}) with name = world, received: ${response.return}`) + const method = 'hello' + const response = await appClient.send.hello({ + args: { name: 'world' }, + }) + console.log( + `Called ${method} on ${appClient.appClient.appName} (${appClient.appClient.appId}) with name = world, received: ${response.return}`, + ) } diff --git a/examples/generators/starter_python_smart_contract_typescript/smart_contracts/hello_world/deploy-config.ts b/examples/generators/starter_python_smart_contract_typescript/smart_contracts/hello_world/deploy-config.ts index 5df7a31..e0608c9 100644 --- a/examples/generators/starter_python_smart_contract_typescript/smart_contracts/hello_world/deploy-config.ts +++ b/examples/generators/starter_python_smart_contract_typescript/smart_contracts/hello_world/deploy-config.ts @@ -1,5 +1,5 @@ import * as algokit from '@algorandfoundation/algokit-utils' -import { HelloWorldClient } from '../artifacts/hello_world/HelloWorldClient' +import { HelloWorldFactory } from '../artifacts/hello_world/HelloWorldClient' // Below is a showcase of various deployment options you can use in TypeScript Client export async function deploy() { @@ -8,26 +8,26 @@ export async function deploy() { const algorand = algokit.AlgorandClient.fromEnvironment() const deployer = await algorand.account.fromEnvironment('DEPLOYER') - const appClient = algorand.client.getTypedAppClientByCreatorAndName(HelloWorldClient, { - sender: deployer, - creatorAddress: deployer.addr, + const factory = algorand.client.getTypedAppFactory(HelloWorldFactory, { + defaultSender: deployer.addr, }) - const app = await appClient.deploy({ - onSchemaBreak: 'append', - onUpdate: 'append', - }) + const { appClient, result } = await factory.deploy({ onUpdate: 'append', onSchemaBreak: 'append' }) // If app was just created fund the app account - if (['create', 'replace'].includes(app.operationPerformed)) { + if (['create', 'replace'].includes(result.operationPerformed)) { await algorand.send.payment({ - amount: algokit.algos(1), + amount: (1).algo(), sender: deployer.addr, - receiver: app.appAddress, + receiver: appClient.appAddress, }) } - const method = 'hello' - const response = await appClient.hello({ name: 'world' }) - console.log(`Called ${method} on ${app.name} (${app.appId}) with name = world, received: ${response.return}`) + const method = 'hello' + const response = await appClient.send.hello({ + args: { name: 'world' }, + }) + console.log( + `Called ${method} on ${appClient.appClient.appName} (${appClient.appClient.appId}) with name = world, received: ${response.return}`, + ) } diff --git a/examples/generators/starter_python_smart_contract_typescript/smart_contracts/index.ts b/examples/generators/starter_python_smart_contract_typescript/smart_contracts/index.ts index 6955e33..623ca2b 100644 --- a/examples/generators/starter_python_smart_contract_typescript/smart_contracts/index.ts +++ b/examples/generators/starter_python_smart_contract_typescript/smart_contracts/index.ts @@ -2,6 +2,7 @@ import * as fs from 'fs' import * as path from 'path' import { consoleLogger } from '@algorandfoundation/algokit-utils/types/logging' import * as algokit from '@algorandfoundation/algokit-utils' +// import { registerDebugEventHandlers } from '@algorandfoundation/algokit-utils-debug' // Uncomment to enable persisting artifacts required by AlgoKit AVM Debugger // Uncomment the debug and traceAll options to enable auto generation of AVM Debugger compliant sourceMap and simulation trace file. // Learn more about using AlgoKit AVM Debugger to debug your TEAL source codes and inspect various kinds of Algorand transactions in atomic groups -> https://github.com/algorandfoundation/algokit-avm-vscode-Debugger @@ -11,6 +12,7 @@ algokit.Config.configure({ // debug: true, // traceAll: true, }) +// registerDebugEventHandlers() // Uncomment to enable persisting artifacts required by AlgoKit AVM Debugger // base directory const baseDir = path.resolve(__dirname) diff --git a/examples/production_python/README.md b/examples/production_python/README.md index d2c173e..5bb9ac6 100644 --- a/examples/production_python/README.md +++ b/examples/production_python/README.md @@ -77,15 +77,7 @@ By default the template creates a single `HelloWorld` contract under hello_world By default the template instance does not contain any env files. Using [`algokit project deploy`](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/project/deploy.md) against `localnet` | `testnet` | `mainnet` will use default values for `algod` and `indexer` unless overwritten via `.env` or `.env.{target_network}`. -To generate a new `.env` or `.env.{target_network}` file, run `algokit generate env-file`### Continuous Integration / Continuous Deployment (CI/CD) - -This project uses [GitHub Actions](https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions) to define CI/CD workflows, which are located in the [.github/workflows](`.github/workflows`) folder. - -> Please note, if you instantiated the project with --workspace flag in `algokit init` it will automatically attempt to move the contents of the `.github` folder to the root of the workspace. - -### AlgoKit Workspaces - -To define custom `algokit project run` commands refer to [documentation](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/project/run.md). This allows orchestration of commands spanning across multiple projects within an algokit workspace based project (monorepo). +To generate a new `.env` or `.env.{target_network}` file, run `algokit generate env-file` ### Debugging Smart Contracts @@ -94,7 +86,15 @@ Refer to the commented header in the `__main__.py` file in the `smart_contracts` 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). +For information on using and setting up the `AlgoKit AVM Debugger` VSCode extension refer [here](https://github.com/algorandfoundation/algokit-avm-vscode-debugger). To install the extension from the VSCode Marketplace, use the following link: [AlgoKit AVM Debugger extension](https://marketplace.visualstudio.com/items?itemName=algorandfoundation.algokit-avm-vscode-debugger).### Continuous Integration / Continuous Deployment (CI/CD) + +This project uses [GitHub Actions](https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions) to define CI/CD workflows, which are located in the [.github/workflows](`.github/workflows`) folder. + +> Please note, if you instantiated the project with --workspace flag in `algokit init` it will automatically attempt to move the contents of the `.github` folder to the root of the workspace. + +### AlgoKit Workspaces + +To define custom `algokit project run` commands refer to [documentation](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/project/run.md). This allows orchestration of commands spanning across multiple projects within an algokit workspace based project (monorepo). #### Setting up GitHub for CI/CD workflow and TestNet deployment diff --git a/examples/production_python/pyproject.toml b/examples/production_python/pyproject.toml index 72e4923..bf2bfc2 100644 --- a/examples/production_python/pyproject.toml +++ b/examples/production_python/pyproject.toml @@ -7,7 +7,7 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.12" -algokit-utils = "^2.3.0" +algokit-utils = { git = "https://github.com/algorandfoundation/algokit-utils-py.git", branch = "feat/puya-debugging" } python-dotenv = "^1.0.0" algorand-python = "^2.0.0" algorand-python-testing = "^0.4.0" @@ -21,7 +21,7 @@ pytest = "*" pytest-cov = "*" pip-audit = "*" pre-commit = "*" -puyapy = "*" +puyapy = { git = "https://github.com/algorandfoundation/puya.git", branch = "main" } [build-system] requires = ["poetry-core"] @@ -57,7 +57,7 @@ warn_redundant_casts = true warn_unused_ignores = true warn_return_any = true strict_equality = true -strict_concatenate = true +extra_checks = true disallow_any_unimported = true disallow_any_expr = true disallow_any_decorated = true diff --git a/examples/production_python/smart_contracts/_helpers/build.py b/examples/production_python/smart_contracts/_helpers/build.py index 0afee9c..3461154 100644 --- a/examples/production_python/smart_contracts/_helpers/build.py +++ b/examples/production_python/smart_contracts/_helpers/build.py @@ -31,7 +31,7 @@ def build(output_dir: Path, contract_path: Path) -> Path: contract_path.absolute(), f"--out-dir={output_dir}", "--output-arc32", - "--debug-level=0", + "--output-source-map", ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, diff --git a/examples/starter_python/README.md b/examples/starter_python/README.md index 7733b5e..ee20af5 100644 --- a/examples/starter_python/README.md +++ b/examples/starter_python/README.md @@ -79,6 +79,15 @@ By default the template instance does not contain any env files. Using [`algokit To generate a new `.env` or `.env.{target_network}` file, run `algokit generate env-file` +### Debugging Smart Contracts + +This project is optimized to work with AlgoKit AVM Debugger extension. To activate it: +Refer to the commented header in the `__main__.py` file in the `smart_contracts` folder. + +If you have opted in to include VSCode launch configurations in your project, you can also use the `Debug TEAL via AlgoKit AVM Debugger` launch configuration to interactively select an available trace file and launch the debug session for your smart contract. + +For information on using and setting up the `AlgoKit AVM Debugger` VSCode extension refer [here](https://github.com/algorandfoundation/algokit-avm-vscode-debugger). To install the extension from the VSCode Marketplace, use the following link: [AlgoKit AVM Debugger extension](https://marketplace.visualstudio.com/items?itemName=algorandfoundation.algokit-avm-vscode-debugger). + # Tools This project makes use of Algorand Python to build Algorand smart contracts. The following tools are in use: diff --git a/examples/starter_python/pyproject.toml b/examples/starter_python/pyproject.toml index bca9124..33ccbbb 100644 --- a/examples/starter_python/pyproject.toml +++ b/examples/starter_python/pyproject.toml @@ -7,14 +7,14 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.12" -algokit-utils = "^2.3.0" +algokit-utils = { git = "https://github.com/algorandfoundation/algokit-utils-py.git", branch = "feat/puya-debugging" } python-dotenv = "^1.0.0" algorand-python = "^2.0.0" algorand-python-testing = "^0.4.0" [tool.poetry.group.dev.dependencies] algokit-client-generator = "^1.1.3" -puyapy = "*" +puyapy = { git = "https://github.com/algorandfoundation/puya.git", branch = "main" } [build-system] requires = ["poetry-core"] diff --git a/examples/starter_python/smart_contracts/_helpers/build.py b/examples/starter_python/smart_contracts/_helpers/build.py index 0afee9c..3461154 100644 --- a/examples/starter_python/smart_contracts/_helpers/build.py +++ b/examples/starter_python/smart_contracts/_helpers/build.py @@ -31,7 +31,7 @@ def build(output_dir: Path, contract_path: Path) -> Path: contract_path.absolute(), f"--out-dir={output_dir}", "--output-arc32", - "--debug-level=0", + "--output-source-map", ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, diff --git a/template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/{% if deployment_language == 'typescript' %}deploy-config.ts.j2{% endif %} b/template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/{% if deployment_language == 'typescript' %}deploy-config.ts.j2{% endif %} index ac114cc..bd3ad2d 100644 --- a/template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/{% if deployment_language == 'typescript' %}deploy-config.ts.j2{% endif %} +++ b/template_content/.algokit/generators/create_contract/smart_contracts/{% raw %}{{ contract_name }}{% endraw %}/{% if deployment_language == 'typescript' %}deploy-config.ts.j2{% endif %} @@ -1,5 +1,5 @@ import * as algokit from '@algorandfoundation/algokit-utils' -import { {{ contract_name.split('_')|map('capitalize')|join }}Client } from '../artifacts/{{ contract_name }}/{{ contract_name.split('_')|map('capitalize')|join }}Client' +import { {{ contract_name.split('_')|map('capitalize')|join }}Factory } from '../artifacts/{{ contract_name }}/{{ contract_name.split('_')|map('capitalize')|join }}Client' // Below is a showcase of various deployment options you can use in TypeScript Client export async function deploy() { @@ -7,27 +7,27 @@ export async function deploy() { const algorand = algokit.AlgorandClient.fromEnvironment() const deployer = await algorand.account.fromEnvironment('DEPLOYER') - - const appClient = algorand.client.getTypedAppClientByCreatorAndName({{ contract_name.split('_')|map('capitalize')|join }}Client, { - sender: deployer, - creatorAddress: deployer.addr, - }) - const app = await appClient.deploy({ - onSchemaBreak: 'append', - onUpdate: 'append', + const factory = algorand.client.getTypedAppFactory({{ contract_name.split('_')|map('capitalize')|join }}Factory, { + defaultSender: deployer.addr, }) + const { appClient, result } = await factory.deploy({ onUpdate: 'append', onSchemaBreak: 'append' }) + // If app was just created fund the app account - if (['create', 'replace'].includes(app.operationPerformed)) { + if (['create', 'replace'].includes(result.operationPerformed)) { await algorand.send.payment({ - amount: algokit.algos(1), + amount: (1).algo(), sender: deployer.addr, receiver: app.appAddress, }) } - const method = 'hello' - const response = await appClient.hello({ name: 'world' }) - console.log(`Called ${method} on ${app.name} (${app.appId}) with name = world, received: ${response.return}`) + const method = 'hello' + const response = await appClient.send.hello({ + args: { name: 'world' }, + }) + console.log( + `Called ${method} on ${appClient.appClient.appName} (${appClient.appClient.appId}) with name = world, received: ${response.return}`, + ) } diff --git a/template_content/README.md.jinja b/template_content/README.md.jinja index 99b904c..73ca5e9 100644 --- a/template_content/README.md.jinja +++ b/template_content/README.md.jinja @@ -82,17 +82,6 @@ By default the template instance does not contain any env files. Using [`algokit To generate a new `.env` or `.env.{target_network}` file, run `algokit generate env-file` -{%- if use_github_actions -%} -### 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](`{% if use_workspace %}../../.github/workflows{% else %}.github/workflows{% endif %}`) folder. - -> Please note, if you instantiated the project with --workspace flag in `algokit init` it will automatically attempt to move the contents of the `.github` folder to the root of the workspace. - -### AlgoKit Workspaces - -To define custom `algokit project run` commands refer to [documentation](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/project/run.md). This allows orchestration of commands spanning across multiple projects within an algokit workspace based project (monorepo). - ### Debugging Smart Contracts This project is optimized to work with AlgoKit AVM Debugger extension. To activate it: @@ -106,6 +95,17 @@ If you have opted in to include VSCode launch configurations in your project, yo 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). +{%- if use_github_actions -%} +### 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](`{% if use_workspace %}../../.github/workflows{% else %}.github/workflows{% endif %}`) folder. + +> Please note, if you instantiated the project with --workspace flag in `algokit init` it will automatically attempt to move the contents of the `.github` folder to the root of the workspace. + +### AlgoKit Workspaces + +To define custom `algokit project run` commands refer to [documentation](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/project/run.md). This allows orchestration of commands spanning across multiple projects within an algokit workspace based project (monorepo). + #### Setting up GitHub for CI/CD workflow and TestNet deployment 1. Every time you have a change to your smart contract, and when you first initialize the project you need to [build the contract](#initial-setup) and then commit the `smart_contracts/artifacts` folder so the [output stability](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/articles/output_stability.md) tests pass diff --git a/template_content/pyproject.toml.jinja b/template_content/pyproject.toml.jinja index 889fb37..1f1ff84 100644 --- a/template_content/pyproject.toml.jinja +++ b/template_content/pyproject.toml.jinja @@ -7,7 +7,7 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.12" -algokit-utils = "^2.3.0" +algokit-utils = { git = "https://github.com/algorandfoundation/algokit-utils-py.git", branch = "feat/puya-debugging" } python-dotenv = "^1.0.0" algorand-python = "^2.0.0" algorand-python-testing = "^0.4.0" @@ -37,7 +37,7 @@ pip-audit = "*" {% if use_pre_commit -%} pre-commit = "*" {% endif -%} -puyapy = "*" +puyapy = { git = "https://github.com/algorandfoundation/puya.git", branch = "main" } [build-system] requires = ["poetry-core"] @@ -76,7 +76,7 @@ warn_redundant_casts = true warn_unused_ignores = true warn_return_any = true strict_equality = true -strict_concatenate = true +extra_checks = true disallow_any_unimported = true disallow_any_expr = true disallow_any_decorated = true diff --git a/template_content/smart_contracts/_helpers/build.py.jinja b/template_content/smart_contracts/_helpers/build.py.jinja index a861b68..152f340 100644 --- a/template_content/smart_contracts/_helpers/build.py.jinja +++ b/template_content/smart_contracts/_helpers/build.py.jinja @@ -34,7 +34,7 @@ def build(output_dir: Path, contract_path: Path) -> Path: contract_path.absolute(), f"--out-dir={output_dir}", "--output-arc32", - "--debug-level=0", + "--output-source-map", ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, 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 6955e33..623ca2b 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 @@ -2,6 +2,7 @@ import * as fs from 'fs' import * as path from 'path' import { consoleLogger } from '@algorandfoundation/algokit-utils/types/logging' import * as algokit from '@algorandfoundation/algokit-utils' +// import { registerDebugEventHandlers } from '@algorandfoundation/algokit-utils-debug' // Uncomment to enable persisting artifacts required by AlgoKit AVM Debugger // Uncomment the debug and traceAll options to enable auto generation of AVM Debugger compliant sourceMap and simulation trace file. // Learn more about using AlgoKit AVM Debugger to debug your TEAL source codes and inspect various kinds of Algorand transactions in atomic groups -> https://github.com/algorandfoundation/algokit-avm-vscode-Debugger @@ -11,6 +12,7 @@ algokit.Config.configure({ // debug: true, // traceAll: true, }) +// registerDebugEventHandlers() // Uncomment to enable persisting artifacts required by AlgoKit AVM Debugger // base directory const baseDir = path.resolve(__dirname) 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 ba3fc68..a375c9f 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 @@ -1,5 +1,5 @@ import * as algokit from '@algorandfoundation/algokit-utils' -import { {{ contract_name.split('_')|map('capitalize')|join }}Client } from '../artifacts/{{ contract_name }}/{{ contract_name.split('_')|map('capitalize')|join }}Client' +import { {{ contract_name.split('_')|map('capitalize')|join }}Factory } from '../artifacts/{{ contract_name }}/{{ contract_name.split('_')|map('capitalize')|join }}Client' // Below is a showcase of various deployment options you can use in TypeScript Client export async function deploy() { @@ -8,26 +8,26 @@ export async function deploy() { const algorand = algokit.AlgorandClient.fromEnvironment() const deployer = await algorand.account.fromEnvironment('DEPLOYER') - const appClient = algorand.client.getTypedAppClientByCreatorAndName({% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client, { - sender: deployer, - creatorAddress: deployer.addr, + const factory = algorand.client.getTypedAppFactory({{ contract_name.split('_')|map('capitalize')|join }}Factory, { + defaultSender: deployer.addr, }) - const app = await appClient.deploy({ - onSchemaBreak: 'append', - onUpdate: 'append', - }) + const { appClient, result } = await factory.deploy({ onUpdate: 'append', onSchemaBreak: 'append' }) // If app was just created fund the app account - if (['create', 'replace'].includes(app.operationPerformed)) { + if (['create', 'replace'].includes(result.operationPerformed)) { await algorand.send.payment({ - amount: algokit.algos(1), + amount: (1).algo(), sender: deployer.addr, - receiver: app.appAddress, + receiver: appClient.appAddress, }) } - const method = 'hello' - const response = await appClient.hello({ name: 'world' }) - console.log(`Called ${method} on ${app.name} (${app.appId}) with name = world, received: ${response.return}`) + const method = 'hello' + const response = await appClient.send.hello({ + args: { name: 'world' }, + }) + console.log( + `Called ${method} on ${appClient.appClient.appName} (${appClient.appClient.appId}) with name = world, received: ${response.return}`, + ) } diff --git a/template_content/{% 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 index 14b0174..e65dc5a 100644 --- 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 @@ -12,15 +12,16 @@ "format": "prettier --write ." }, "engines": { - "node": ">=18.0", + "node": ">=20.0", "npm": ">=9.0" }, "dependencies": { - "@algorandfoundation/algokit-utils": "^6.0.2", - "algosdk": "^2.7.0" + "@algorandfoundation/algokit-utils": "^7.0.0", + "@algorandfoundation/algokit-utils-debug": "^1.0.2", + "algosdk": ">=2.9.0 <3.0" }, "devDependencies": { - "@algorandfoundation/algokit-client-generator": "^3.0.3", + "@algorandfoundation/algokit-client-generator": "^4.0.0", {%- if use_typescript_jest %} "@types/jest": "^29.5.11", {%- endif %} 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 index 5f54543..b7ea209 100644 --- a/template_content/{% if use_typescript_jest %}tests{% endif %}/{% if use_typescript_jest %}{% include pathjoin('includes', 'contract_name_kebab.jinja') %}.spec.ts{% endif %}.jinja +++ b/template_content/{% if use_typescript_jest %}tests{% endif %}/{% if use_typescript_jest %}{% include pathjoin('includes', 'contract_name_kebab.jinja') %}.spec.ts{% endif %}.jinja @@ -1,7 +1,8 @@ import { algorandFixture } from '@algorandfoundation/algokit-utils/testing' -import { {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client } from '../smart_contracts/artifacts/{{ contract_name }}/{{ contract_name.split('_')|map('capitalize')|join }}Client' +import { {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Factory } from '../smart_contracts/artifacts/{{ contract_name }}/{{ contract_name.split('_')|map('capitalize')|join }}Client' import { Account, Algodv2, Indexer } from 'algosdk' import * as algokit from '@algorandfoundation/algokit-utils' +import { TransactionSignerAccount } from '@algorandfoundation/algokit-utils/types/account' describe('{{ contract_name.split('_')|join(' ') }} contract', () => { const localnet = algorandFixture() @@ -13,39 +14,36 @@ describe('{{ contract_name.split('_')|join(' ') }} contract', () => { }) 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', + const deploy = async (account: Account & TransactionSignerAccount) => { + const factory = localnet.algorand.client.getTypedAppFactory({% include pathjoin('includes', 'contract_name_pascal.jinja') %}Factory, { + defaultSender: account.addr, + defaultSigner: account.signer, }) - return { client } + + const { appClient } = await factory.deploy({ onUpdate: 'append', onSchemaBreak: 'append' }) + return { client: appClient } } test('says hello', async () => { - const { algod, indexer, testAccount } = localnet.context - const { client } = await deploy(testAccount, algod, indexer) + const { testAccount } = localnet.context + const { client } = await deploy(testAccount) - const result = await client.hello({ name: 'World' }) + const result = await client.send.hello({ args: { 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() + const { testAccount } = localnet.context + const { client } = await deploy(testAccount) + const result = await client + .newGroup() + .hello({ args: { name: 'World' } }) + .hello({ args: { name: 'Jane' } }) + .simulate() - expect(result.methodResults[0].returnValue).toBe('Hello, World') - expect(result.methodResults[1].returnValue).toBe('Hello, Jane') + expect(result.returns[0]).toBe('Hello, World') + expect(result.returns[1]).toBe('Hello, Jane') expect(result.simulateResponse.txnGroups[0].appBudgetConsumed).toBeLessThan(100) }) })