diff --git a/tests_generated/test_all_default_parameters_on_netlify/src/contracts/README.md b/examples/cloud_providers/production_react_netlify/src/contracts/README.md
similarity index 100%
rename from tests_generated/test_all_default_parameters_on_netlify/src/contracts/README.md
rename to examples/cloud_providers/production_react_netlify/src/contracts/README.md
diff --git a/tests_generated/test_all_default_parameters_on_netlify/src/interfaces/network.ts b/examples/cloud_providers/production_react_netlify/src/interfaces/network.ts
similarity index 100%
rename from tests_generated/test_all_default_parameters_on_netlify/src/interfaces/network.ts
rename to examples/cloud_providers/production_react_netlify/src/interfaces/network.ts
diff --git a/tests_generated/test_all_default_parameters_off/src/main.tsx b/examples/cloud_providers/production_react_netlify/src/main.tsx
similarity index 92%
rename from tests_generated/test_all_default_parameters_off/src/main.tsx
rename to examples/cloud_providers/production_react_netlify/src/main.tsx
index 431a30c..adf72ec 100644
--- a/tests_generated/test_all_default_parameters_off/src/main.tsx
+++ b/examples/cloud_providers/production_react_netlify/src/main.tsx
@@ -1,7 +1,7 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
-import './styles/App.css'
+import './styles/main.css'
import ErrorBoundary from './components/ErrorBoundary'
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
diff --git a/examples/cloud_providers/production_react_netlify/src/styles/main.css b/examples/cloud_providers/production_react_netlify/src/styles/main.css
new file mode 100644
index 0000000..b5c61c9
--- /dev/null
+++ b/examples/cloud_providers/production_react_netlify/src/styles/main.css
@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
diff --git a/examples/cloud_providers/production_react_netlify/src/utils/ellipseAddress.spec.tsx b/examples/cloud_providers/production_react_netlify/src/utils/ellipseAddress.spec.tsx
new file mode 100644
index 0000000..2cbff10
--- /dev/null
+++ b/examples/cloud_providers/production_react_netlify/src/utils/ellipseAddress.spec.tsx
@@ -0,0 +1,15 @@
+import { ellipseAddress } from './ellipseAddress'
+
+describe('ellipseAddress', () => {
+ it('should return ellipsed address with specified width', () => {
+ const address = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
+ const result = ellipseAddress(address, 4)
+ expect(result).toBe('aaaa...aaaa')
+ })
+
+ it('should return empty string when address is empty', () => {
+ const address = ''
+ const result = ellipseAddress(address)
+ expect(result).toBe('')
+ })
+})
diff --git a/tests_generated/test_all_default_parameters_on_netlify/src/utils/ellipseAddress.ts b/examples/cloud_providers/production_react_netlify/src/utils/ellipseAddress.ts
similarity index 100%
rename from tests_generated/test_all_default_parameters_on_netlify/src/utils/ellipseAddress.ts
rename to examples/cloud_providers/production_react_netlify/src/utils/ellipseAddress.ts
diff --git a/tests_generated/test_all_default_parameters_on_netlify/src/utils/network/getAlgoClientConfigs.ts b/examples/cloud_providers/production_react_netlify/src/utils/network/getAlgoClientConfigs.ts
similarity index 100%
rename from tests_generated/test_all_default_parameters_on_netlify/src/utils/network/getAlgoClientConfigs.ts
rename to examples/cloud_providers/production_react_netlify/src/utils/network/getAlgoClientConfigs.ts
diff --git a/tests_generated/test_all_default_parameters_on_netlify/src/vite-env.d.ts b/examples/cloud_providers/production_react_netlify/src/vite-env.d.ts
similarity index 100%
rename from tests_generated/test_all_default_parameters_on_netlify/src/vite-env.d.ts
rename to examples/cloud_providers/production_react_netlify/src/vite-env.d.ts
diff --git a/examples/cloud_providers/production_react_netlify/tailwind.config.js b/examples/cloud_providers/production_react_netlify/tailwind.config.js
new file mode 100644
index 0000000..a9f7a95
--- /dev/null
+++ b/examples/cloud_providers/production_react_netlify/tailwind.config.js
@@ -0,0 +1,11 @@
+/** @type {import('tailwindcss').Config} */
+module.exports = {
+ content: ['./src/**/*.{js,ts,jsx,tsx}'],
+ theme: {
+ extend: {},
+ },
+ daisyui: {
+ themes: ['lofi'],
+ },
+ plugins: [require('daisyui')],
+ }
diff --git a/examples/cloud_providers/production_react_netlify/tests/example.spec.ts b/examples/cloud_providers/production_react_netlify/tests/example.spec.ts
new file mode 100644
index 0000000..df83322
--- /dev/null
+++ b/examples/cloud_providers/production_react_netlify/tests/example.spec.ts
@@ -0,0 +1,38 @@
+import { randomAccount } from '@algorandfoundation/algokit-utils'
+import { expect, test } from '@playwright/test'
+
+test.beforeEach(async ({ page }) => {
+ await page.goto('http://localhost:5173/')
+})
+
+test('has title', async ({ page }) => {
+ // Expect a title "to contain" a substring.
+ await expect(page).toHaveTitle('AlgoKit React Template')
+})
+
+test('get started link', async ({ page }) => {
+ await expect(page.getByTestId('getting-started')).toHaveText('Getting started')
+})
+
+test('authentication and dummy payment transaction', async ({ page }) => {
+ page.on('dialog', async (dialog) => {
+ dialog.message() === 'KMD password' ? await dialog.accept() : await dialog.dismiss()
+ })
+
+ // 1. Must be able to connect to a KMD wallet provider
+ await page.getByTestId('connect-wallet').click()
+ await page.getByTestId('kmd-connect').click()
+ await page.getByTestId('close-wallet-modal').click()
+
+ // 2. Must be able to send a dummy payment transaction
+ await page.getByTestId('transactions-demo').click()
+
+ const dummyAccount = randomAccount()
+ await page.getByTestId('receiver-address').fill(dummyAccount.addr)
+ await page.getByTestId('send-algo').click()
+
+ // 3. Must be able to see a notification that the transaction was sent
+ const notification = await page.getByText('Transaction sent:')
+ await notification.waitFor()
+ expect(notification).toBeTruthy()
+})
diff --git a/tests_generated/test_all_default_parameters_off/tsconfig.json b/examples/cloud_providers/production_react_netlify/tsconfig.json
similarity index 95%
rename from tests_generated/test_all_default_parameters_off/tsconfig.json
rename to examples/cloud_providers/production_react_netlify/tsconfig.json
index 443b6bd..5cde02a 100644
--- a/tests_generated/test_all_default_parameters_off/tsconfig.json
+++ b/examples/cloud_providers/production_react_netlify/tsconfig.json
@@ -26,8 +26,8 @@
"src/**/*.ts",
"src/**/*.tsx",
"vite.config.js",
- "src/utils/",
- "src/utils/",
+ "src/utils/ellipseAddress.spec.tsx",
+ "src/utils/ellipseAddress.spec.tsx",
"src/main.tsx",
],
"references": [
diff --git a/tests_generated/test_all_default_parameters_on_netlify/tsconfig.node.json b/examples/cloud_providers/production_react_netlify/tsconfig.node.json
similarity index 100%
rename from tests_generated/test_all_default_parameters_on_netlify/tsconfig.node.json
rename to examples/cloud_providers/production_react_netlify/tsconfig.node.json
diff --git a/tests_generated/test_all_default_parameters_on_netlify/vite.config.ts b/examples/cloud_providers/production_react_netlify/vite.config.ts
similarity index 100%
rename from tests_generated/test_all_default_parameters_on_netlify/vite.config.ts
rename to examples/cloud_providers/production_react_netlify/vite.config.ts
diff --git a/examples/cloud_providers/production_react_vercel/.algokit.toml b/examples/cloud_providers/production_react_vercel/.algokit.toml
new file mode 100644
index 0000000..f3abe6e
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/.algokit.toml
@@ -0,0 +1,10 @@
+[algokit]
+min_version = "v1.3.0b1"
+
+[generate.import_contract]
+description = "Import a typed client from your smart contracts project"
+path = ".algokit/generators/import_contract"
+
+[project]
+type = "frontend"
+name = "production_react_vercel"
diff --git a/examples/cloud_providers/production_react_vercel/.copier-answers.yml b/examples/cloud_providers/production_react_vercel/.copier-answers.yml
new file mode 100644
index 0000000..e4d6d29
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/.copier-answers.yml
@@ -0,0 +1,8 @@
+# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY
+_commit:
+_src_path:
+author_email: None
+author_name: None
+preset_name: production
+project_name: production_react_vercel
+
diff --git a/examples/cloud_providers/production_react_vercel/.editorconfig b/examples/cloud_providers/production_react_vercel/.editorconfig
new file mode 100644
index 0000000..a83b72c
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/.editorconfig
@@ -0,0 +1,9 @@
+[*]
+charset = utf-8
+insert_final_newline = true
+end_of_line = lf
+indent_style = space
+indent_size = 2
+tab_width = 2
+max_line_length = 140
+trim_trailing_whitespace = true
diff --git a/tests_generated/test_all_default_parameters_on_vercel/.env.template b/examples/cloud_providers/production_react_vercel/.env.template
similarity index 100%
rename from tests_generated/test_all_default_parameters_on_vercel/.env.template
rename to examples/cloud_providers/production_react_vercel/.env.template
diff --git a/examples/cloud_providers/production_react_vercel/.eslintrc b/examples/cloud_providers/production_react_vercel/.eslintrc
new file mode 100644
index 0000000..868fe37
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/.eslintrc
@@ -0,0 +1,27 @@
+{
+ "root": true,
+ "env": {
+ "node": true
+ },
+ "parser": "@typescript-eslint/parser",
+ "plugins": ["@typescript-eslint", "prettier"],
+ "extends": [
+ "eslint:recommended",
+ "plugin:@typescript-eslint/eslint-recommended",
+ "plugin:@typescript-eslint/recommended",
+ "plugin:prettier/recommended"
+ ],
+ "rules": {
+ "prettier/prettier": "warn",
+ "no-console": "warn",
+ "@typescript-eslint/no-unused-vars": [
+ "warn",
+ {
+ "ignoreRestSiblings": true,
+ "argsIgnorePattern": "^_",
+ "destructuredArrayIgnorePattern": "^_"
+ }
+ ],
+ "prefer-template": "error"
+ }
+}
diff --git a/tests_generated/test_all_default_parameters_on_vercel/.gitattributes b/examples/cloud_providers/production_react_vercel/.gitattributes
similarity index 100%
rename from tests_generated/test_all_default_parameters_on_vercel/.gitattributes
rename to examples/cloud_providers/production_react_vercel/.gitattributes
diff --git a/tests_generated/test_all_default_parameters_on_vercel/.github/workflows/checks.yaml b/examples/cloud_providers/production_react_vercel/.github/workflows/checks.yaml
similarity index 100%
rename from tests_generated/test_all_default_parameters_on_vercel/.github/workflows/checks.yaml
rename to examples/cloud_providers/production_react_vercel/.github/workflows/checks.yaml
diff --git a/examples/cloud_providers/production_react_vercel/.github/workflows/pr.yaml b/examples/cloud_providers/production_react_vercel/.github/workflows/pr.yaml
new file mode 100644
index 0000000..a80f784
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/.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/examples/cloud_providers/production_react_vercel/.github/workflows/release.yaml b/examples/cloud_providers/production_react_vercel/.github/workflows/release.yaml
new file mode 100644
index 0000000..13152f1
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/.github/workflows/release.yaml
@@ -0,0 +1,66 @@
+name: Release
+
+on:
+ push:
+ branches:
+ - main
+ paths-ignore:
+ - "docs/**"
+ - "**.md"
+ - ".vscode/**"
+ - ".idea/**"
+
+permissions:
+ contents: read
+ packages: read
+
+jobs:
+ lint-and-build:
+ name: CI dApp
+ uses: ./.github/workflows/checks.yaml
+
+ deploy:
+ runs-on: ubuntu-latest
+ name: Deploy to Vercel
+ environment: Prod
+ concurrency: "${{ github.workflow }}-prod"
+ needs:
+ - lint-and-build
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v2
+
+ - name: Install Vercel CLI
+ run: npm install --global vercel@latest
+
+ - name: Pull Vercel Environment Information
+ run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
+
+ - name: Create placeholder .env file
+ uses: makerxstudio/shared-config/.github/actions/env-to-placeholders@main
+ with:
+ env-output-path: './.env'
+ env-template-path: './.env.template'
+ env-variable-prefix: VITE_
+
+ - name: Build Project Artifacts
+ run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
+
+ - name: Replace template vars
+ uses: makerxstudio/shared-config/.github/actions/placeholder-transforms@main
+ with:
+ app-artifact-path: './.vercel/output'
+ static-site-transforms: |-
+ VITE_ALGOD_TOKEN:${{ secrets.VITE_ALGOD_TOKEN }}
+ VITE_ALGOD_SERVER:${{ vars.VITE_ALGOD_SERVER }}
+ VITE_ALGOD_PORT:${{ vars.VITE_ALGOD_PORT }}
+ VITE_ALGOD_NETWORK:${{ vars.VITE_ALGOD_NETWORK }}
+ VITE_INDEXER_SERVER:${{ vars.VITE_INDEXER_SERVER }}
+ VITE_INDEXER_PORT:${{ vars.VITE_INDEXER_PORT }}
+ VITE_INDEXER_TOKEN:${{ secrets.VITE_INDEXER_TOKEN }}
+ VITE_ENVIRONMENT:${{ vars.VITE_ENVIRONMENT }}
+
+ - name: Deploy Project Artifacts to Vercel
+ run: vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }}
+ # Set your vercel project env variables on your github repository (see README for more info)
+
diff --git a/tests_generated/test_all_default_parameters_on_vercel/.gitignore b/examples/cloud_providers/production_react_vercel/.gitignore
similarity index 100%
rename from tests_generated/test_all_default_parameters_on_vercel/.gitignore
rename to examples/cloud_providers/production_react_vercel/.gitignore
diff --git a/examples/cloud_providers/production_react_vercel/.idea/runConfigurations/Run_Chrome.xml b/examples/cloud_providers/production_react_vercel/.idea/runConfigurations/Run_Chrome.xml
new file mode 100644
index 0000000..9dfeeca
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/.idea/runConfigurations/Run_Chrome.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/examples/cloud_providers/production_react_vercel/.idea/runConfigurations/Run_dApp.xml b/examples/cloud_providers/production_react_vercel/.idea/runConfigurations/Run_dApp.xml
new file mode 100644
index 0000000..1cf2273
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/.idea/runConfigurations/Run_dApp.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/cloud_providers/production_react_vercel/.idea/runConfigurations/Run_dApp____LocalNet_.xml b/examples/cloud_providers/production_react_vercel/.idea/runConfigurations/Run_dApp____LocalNet_.xml
new file mode 100644
index 0000000..3758c8b
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/.idea/runConfigurations/Run_dApp____LocalNet_.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/cloud_providers/production_react_vercel/.idea/runConfigurations/Start_AlgoKit_LocalNet.xml b/examples/cloud_providers/production_react_vercel/.idea/runConfigurations/Start_AlgoKit_LocalNet.xml
new file mode 100644
index 0000000..0394a67
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/.idea/runConfigurations/Start_AlgoKit_LocalNet.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/cloud_providers/production_react_vercel/.prettierignore b/examples/cloud_providers/production_react_vercel/.prettierignore
new file mode 100644
index 0000000..dbda6ae
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/.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/examples/cloud_providers/production_react_vercel/.prettierrc.cjs b/examples/cloud_providers/production_react_vercel/.prettierrc.cjs
new file mode 100644
index 0000000..066b8e5
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/.prettierrc.cjs
@@ -0,0 +1,10 @@
+module.exports = {
+ singleQuote: true,
+ jsxSingleQuote: false,
+ semi: false,
+ tabWidth: 2,
+ trailingComma: 'all',
+ printWidth: 140,
+ endOfLine: 'lf',
+ arrowParens: 'always',
+}
diff --git a/examples/cloud_providers/production_react_vercel/.vscode/extensions.json b/examples/cloud_providers/production_react_vercel/.vscode/extensions.json
new file mode 100644
index 0000000..5c94122
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/.vscode/extensions.json
@@ -0,0 +1,14 @@
+{
+ "recommendations": [
+ "EditorConfig.EditorConfig",
+ "dotenv.dotenv-vscode",
+ "esbenp.prettier-vscode",
+ "dbaeumer.vscode-eslint",
+ "krysenlo.vite-plugin-eslint-problemmatcher",
+ "ms-playwright.playwright",
+ "Orta.vscode-jest",
+ "bradlc.vscode-tailwindcss",
+ "csstools.postcss",
+ ]
+}
+
diff --git a/examples/cloud_providers/production_react_vercel/.vscode/launch.json b/examples/cloud_providers/production_react_vercel/.vscode/launch.json
new file mode 100644
index 0000000..7edaf04
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/.vscode/launch.json
@@ -0,0 +1,68 @@
+{
+ "configurations": [
+ {
+ "type": "msedge",
+ "request": "launch",
+ "name": "Run (Edge)",
+ "url": "http://localhost:5173",
+ "webRoot": "${workspaceFolder}",
+ "presentation": {
+ "hidden": false,
+ "group": "2. Web"
+ }
+ },
+ {
+ "type": "chrome",
+ "request": "launch",
+ "name": "Run (Chrome)",
+ "url": "http://localhost:5173",
+ "webRoot": "${workspaceFolder}",
+ "presentation": {
+ "hidden": false,
+ "group": "2. Web"
+ }
+ },
+ {
+ "type": "firefox",
+ "request": "launch",
+ "name": "Run (Firefox)",
+ "url": "http://localhost:5173",
+ "webRoot": "${workspaceFolder}",
+ "presentation": {
+ "hidden": false,
+ "group": "2. Web"
+ }
+ },
+ {
+ "name": "Run dApp",
+ "type": "node",
+ "request": "launch",
+ "runtimeExecutable": "npm",
+ "runtimeArgs": ["run", "dev"],
+ "cwd": "${workspaceRoot}",
+ "console": "integratedTerminal",
+ "skipFiles": ["/**", "node_modules/**"],
+ "presentation": {
+ "hidden": false,
+ "group": "1. Run Project",
+ "order": 1
+ }
+ },
+ {
+ "name": "Run dApp (+ LocalNet)",
+ "type": "node",
+ "request": "launch",
+ "runtimeExecutable": "npm",
+ "runtimeArgs": ["run", "dev"],
+ "cwd": "${workspaceRoot}",
+ "console": "integratedTerminal",
+ "skipFiles": ["/**", "node_modules/**"],
+ "preLaunchTask": "Start AlgoKit LocalNet",
+ "presentation": {
+ "hidden": false,
+ "group": "1. Run Project",
+ "order": 1
+ }
+ }
+ ]
+}
diff --git a/examples/cloud_providers/production_react_vercel/.vscode/settings.json b/examples/cloud_providers/production_react_vercel/.vscode/settings.json
new file mode 100644
index 0000000..6ffe6b3
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/.vscode/settings.json
@@ -0,0 +1,13 @@
+{
+ "editor.formatOnSave": true,
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
+ "editor.codeActionsOnSave": {
+ "source.fixAll.eslint": true,
+ "source.organizeImports": true
+ },
+ "dotenv.enableAutocloaking": false,
+ "jest.autoRun": {
+ "watch": false,
+ "onSave": "test-file"
+ }
+}
diff --git a/examples/cloud_providers/production_react_vercel/.vscode/tasks.json b/examples/cloud_providers/production_react_vercel/.vscode/tasks.json
new file mode 100644
index 0000000..d611c4f
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/.vscode/tasks.json
@@ -0,0 +1,15 @@
+{
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "Start AlgoKit LocalNet",
+ "command": "algokit",
+ "args": ["localnet", "start"],
+ "type": "shell",
+ "options": {
+ "cwd": "${workspaceFolder}"
+ },
+ "problemMatcher": []
+ }
+ ]
+}
diff --git a/tests_generated/test_all_default_parameters_on_vercel/LICENSE b/examples/cloud_providers/production_react_vercel/LICENSE
similarity index 100%
rename from tests_generated/test_all_default_parameters_on_vercel/LICENSE
rename to examples/cloud_providers/production_react_vercel/LICENSE
diff --git a/examples/cloud_providers/production_react_vercel/README.md b/examples/cloud_providers/production_react_vercel/README.md
new file mode 100644
index 0000000..6853822
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/README.md
@@ -0,0 +1,100 @@
+# production_react_vercel
+
+This starter React project has been generated using AlgoKit. See below for default getting started instructions.
+
+# Setup
+
+### 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 minimum required version is `1.1`. Ensure you can execute `algokit --version` and get `1.1` or later.
+ - Bootstrap your local environment; run `algokit bootstrap all` within this folder, which will run `npm install` to install NPM packages and dependencies for your frontend component/webapp.
+ - 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.
+ - JetBrains WebStorm
+ 1. Open the repository root in WebStorm
+ 2. Hit Shift+F10|Ctrl+R (or whatever you have debug mapped to). Then Shift+CMD|Ctrl+Click on the link in the console to open the browser with debugger attached.
+ - Other
+ 1. Open the repository root in your text editor of choice
+ 2. In a terminal run `npm run dev`
+
+### 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
+
+> Please note, by default frontend is pre configured to run against Algorand LocalNet. If you want to run against TestNet or MainNet, comment out the current environment variable and uncomment the relevant one in [`.env`](.env) file that is created after running bootstrap command and based on [`.env.template`](.env.template).
+
+### Continuous Integration
+
+This project uses [GitHub Actions](https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions) to define CI workflows, which are located in the [`.github/workflows`](./.github/workflows) folder.
+
+For pull requests and pushes to `main` branch against this repository the following checks are automatically performed by GitHub Actions:
+
+- `install`: Installs dependencies using `npm`
+- `lint`: Lints the codebase using `ESLint`
+- `build`: Builds the codebase using `vite`
+
+### Continuous Deployment
+
+The project template provides base Github Actions workflows for continuous deployment to [Netlify](https://www.netlify.com/) or [Vercel](https://vercel.com/). These workflows are located in the [`.github/workflows`](./.github/workflows) folder.
+
+**Please note**: when configuring the github repository for the first time. Depending on selected provider you will need to set the provider secrets in the repository settings. Default setup provided by the template allows you to manage the secrets via environment variables and secrets on your github repository.
+
+
+#### Setting up environment variables and secrets for webapp deployment
+
+1. [Create a new environment variable on your repository](https://docs.github.com/en/actions/learn-github-actions/variables#creating-configuration-variables-for-a-repository) called `NETLIFY_AUTH_TOKEN` and `NETLIFY_SITE_ID` if you are using Netlify as your cloud provider. Set it to the value of your Netlify auth token respectively. You can find your Netlify auth token by going to [app.netlify.com](https://app.netlify.com/).
+2. If you are using Vercel as your cloud provider, create a new environment variable on your repository called `VERCEL_TOKEN`. Set it to the value of your Vercel auth token. You can find your Vercel auth token by going to [vercel.com/account/tokens](https://vercel.com/account/tokens).
+3. Set up the environment variables. You can refer to the `.env.template` for default values. The variables to be set are:
+ - `VITE_ALGOD_SERVER`
+ - `VITE_ALGOD_NETWORK`
+ - `VITE_INDEXER_SERVER`
+ - `VITE_ENVIRONMENT` - (Set to either `production` or `development`)
+ - `VITE_ALGOD_PORT` - (This is optional if you are using a public gateway like AlgoNode)
+ - `VITE_INDEXER_PORT` - (This is optional if you are using a public gateway like AlgoNode)
+4. (Optional) If you need to set up environment secrets, you can do so by following the guide [here](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions#creating-secrets-for-a-repository). The variables for which you can set secrets are (refer to `.env.template` for default values):
+ - `VITE_ALGOD_TOKEN` - (This is optional if you are using a public gateway like AlgoNode)
+ - `VITE_INDEXER_TOKEN` - (This is optional if you are using a public gateway like AlgoNode)
+
+> If you prefer alternative deployment methods, you can remove the relevant workflow files from the [`.github/workflows`](./.github/workflows) folder and configure your own.
+
+
+# Algorand Wallet integrations
+
+The template comes with [`use-wallet`](https://github.com/txnlab/use-wallet) integration, which provides a React hook for connecting to an Algorand wallet providers. The following wallet providers are included by default:
+- LocalNet:
+- - [KMD/Local Wallet](https://github.com/TxnLab/use-wallet#kmd-algorand-key-management-daemon) - Algorand's Key Management Daemon (KMD) is a service that manages Algorand private keys and signs transactions. Works best with AlgoKit LocalNet and allows you to easily test and interact with your dApps locally.
+- TestNet and others:
+- - [Pera Wallet](https://perawallet.app).
+- - [Defly Wallet](https://defly.app).
+- - [Exodus Wallet](https://www.exodus.com).
+- - [Daffi Wallet](https://www.daffi.me).
+
+Refer to official [`use-wallet`](https://github.com/txnlab/use-wallet) documentation for detailed guidelines on how to integrate with other wallet providers (such as WalletConnect v2). Too see implementation details on the use wallet hook and initialization of extra wallet providers refer to [`App.tsx`](./src/App.tsx).
+
+# Tools
+
+This project makes use of React and Tailwind to provider a base project configuration to develop frontends for your Algorand dApps and interactions with smart contracts. The following tools are in use:
+
+- [AlgoKit Utils](https://github.com/algorandfoundation/algokit-utils-ts) - Various TypeScript utilities to simplify interactions with Algorand and AlgoKit.
+- [React](https://reactjs.org/) - A JavaScript library for building user interfaces.
+- [Tailwind CSS](https://tailwindcss.com/) - A utility-first CSS framework for rapidly building custom designs.
+- [daisyUI](https://daisyui.com/) - A component library for Tailwind CSS.
+- [use-wallet](https://github.com/txnlab/use-wallet) - A React hook for connecting to an Algorand wallet providers.
+- [npm](https://www.npmjs.com/): Node.js package manager
+- [jest](https://jestjs.io/): JavaScript testing framework
+- [playwright](https://playwright.dev/): Browser automation library
+- [Prettier](https://prettier.io/): Opinionated code formatter
+- [ESLint](https://eslint.org/): Tool for identifying and reporting on patterns in JavaScript
+- Github Actions workflows for build validation
+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.
+# Integrating with smart contracts and application clients
+
+Refer to the detailed guidance on [integrating with smart contracts and application clients](./src/contracts/README.md). In essence, for any smart contract codebase generated with AlgoKit or other tools that produce compile contracts into ARC34 compliant app specifications, you can use the `algokit generate` command to generate TypeScript or Python typed client. Once generated simply drag and drop the generated client into `./src/contracts` and import it into your React components as you see fit.
diff --git a/tests_generated/test_all_default_parameters_on_vercel/index.html b/examples/cloud_providers/production_react_vercel/index.html
similarity index 100%
rename from tests_generated/test_all_default_parameters_on_vercel/index.html
rename to examples/cloud_providers/production_react_vercel/index.html
diff --git a/examples/cloud_providers/production_react_vercel/jest.config.ts b/examples/cloud_providers/production_react_vercel/jest.config.ts
new file mode 100644
index 0000000..28a8c3d
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/jest.config.ts
@@ -0,0 +1,20 @@
+import type { Config } from '@jest/types'
+
+const config: Config.InitialOptions = {
+ preset: 'ts-jest',
+ testEnvironment: 'node',
+ testMatch: ['**/*.spec.ts', '**/*.spec.tsx'],
+ moduleDirectories: ['node_modules', 'src'],
+ transform: {
+ '': [
+ 'ts-jest',
+ {
+ tsconfig: 'tsconfig.test.json',
+ },
+ ],
+ },
+ coveragePathIgnorePatterns: ['tests'],
+ testPathIgnorePatterns: ['/tests/'],
+ }
+
+export default config
diff --git a/examples/cloud_providers/production_react_vercel/package.json b/examples/cloud_providers/production_react_vercel/package.json
new file mode 100644
index 0000000..414d582
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/package.json
@@ -0,0 +1,75 @@
+{
+ "name": "production_react_vercel",
+ "version": "0.1.0",
+ "author": {
+ "name": "None",
+ "email": "None"
+ },
+ "private": true,
+ "type": "module",
+ "engines": {
+ "node": ">=18.0"
+ },
+ "devDependencies": {
+ "@types/node": "^18.17.14",
+ "@types/react": "^18.2.11",
+ "@types/react-dom": "^18.2.4",
+ "@vitejs/plugin-react": "^4.2.1",
+ "autoprefixer": "^10.4.14",
+ "eslint": "^8.42.0",
+ "eslint-config-prettier": "^8.8.0",
+ "eslint-plugin-prettier": "^5.0.0",
+ "@typescript-eslint/eslint-plugin": "^6.5.0",
+ "@typescript-eslint/parser": "^6.5.0",
+ "postcss": "^8.4.24",
+ "tailwindcss": "3.3.2",
+ "ts-jest": "^29.1.1",
+ "@types/jest": "29.5.2",
+ "ts-node": "^10.9.1",
+ "typescript": "^5.1.6",
+ "@playwright/test": "^1.35.0",
+ "playwright": "^1.35.0",
+ "vite": "^5.0.0"
+ },
+ "dependencies": {
+ "@walletconnect/modal-sign-html": "^2.6.1",
+ "@algorandfoundation/algokit-utils": "^5.0.0",
+ "@blockshake/defly-connect": "^1.1.6",
+ "@daffiwallet/connect": "^1.0.3",
+ "@perawallet/connect": "^1.3.1",
+ "@txnlab/use-wallet": "^2.4.0",
+ "algosdk": "^2.7.0",
+ "daisyui": "^4.0.0",
+ "notistack": "^3.0.1",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "tslib": "^2.6.2"
+ },
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc && vite build",
+ "test": "jest --coverage --passWithNoTests",
+ "playwright:test": "playwright test",
+ "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
+ "lint:fix": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0 --fix",
+ "preview": "vite preview"
+ },
+ "eslintConfig": {
+ "extends": [
+ "react-app/jest",
+ "react-app"
+ ]
+ },
+ "browserslist": {
+ "production": [
+ ">0.2%",
+ "not dead",
+ "not op_mini all"
+ ],
+ "development": [
+ "last 1 chrome version",
+ "last 1 firefox version",
+ "last 1 safari version"
+ ]
+ }
+}
diff --git a/examples/cloud_providers/production_react_vercel/playwright.config.ts b/examples/cloud_providers/production_react_vercel/playwright.config.ts
new file mode 100644
index 0000000..d7cbca6
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/playwright.config.ts
@@ -0,0 +1,73 @@
+import { defineConfig, devices } from '@playwright/test'
+
+/**
+ * Read environment variables from file.
+ * https://github.com/motdotla/dotenv
+ */
+// require('dotenv').config();
+
+/**
+ * See https://playwright.dev/docs/test-configuration.
+ */
+export default defineConfig({
+ testDir: './tests',
+ /* Run tests in files in parallel */
+ fullyParallel: true,
+ /* Fail the build on CI if you accidentally left test.only in the source code. */
+ forbidOnly: !!process.env.CI,
+ /* Retry on CI only */
+ retries: process.env.CI ? 2 : 0,
+ /* Opt out of parallel tests on CI. */
+ workers: process.env.CI ? 1 : undefined,
+ /* Reporter to use. See https://playwright.dev/docs/test-reporters */
+ reporter: 'html',
+ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
+ use: {
+ /* Base URL to use in actions like `await page.goto('/')`. */
+ // baseURL: 'http://127.0.0.1:3000',
+
+ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
+ trace: 'on-first-retry',
+ testIdAttribute: 'data-test-id',
+ },
+
+ /* Configure projects for major browsers */
+ projects: [
+ {
+ name: 'chromium',
+ use: { ...devices['Desktop Chrome'] },
+ },
+
+ {
+ name: 'firefox',
+ use: { ...devices['Desktop Firefox'] },
+ },
+
+ /* Test against mobile viewports. */
+ // {
+ // name: 'Mobile Chrome',
+ // use: { ...devices['Pixel 5'] },
+ // },
+ // {
+ // name: 'Mobile Safari',
+ // use: { ...devices['iPhone 12'] },
+ // },
+
+ /* Test against branded browsers. */
+ // {
+ // name: 'Microsoft Edge',
+ // use: { ...devices['Desktop Edge'], channel: 'msedge' },
+ // },
+ // {
+ // name: 'Google Chrome',
+ // use: { ..devices['Desktop Chrome'], channel: 'chrome' },
+ // },
+ ],
+
+ /* Run your local dev server before starting the tests */
+ webServer: {
+ command: 'npm run dev',
+ url: 'http://localhost:5173',
+ reuseExistingServer: !process.env.CI,
+ },
+})
diff --git a/examples/cloud_providers/production_react_vercel/postcss.config.cjs b/examples/cloud_providers/production_react_vercel/postcss.config.cjs
new file mode 100644
index 0000000..33ad091
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/postcss.config.cjs
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/tests_generated/test_all_default_parameters_on_vercel/public/index.html b/examples/cloud_providers/production_react_vercel/public/index.html
similarity index 100%
rename from tests_generated/test_all_default_parameters_on_vercel/public/index.html
rename to examples/cloud_providers/production_react_vercel/public/index.html
diff --git a/tests_generated/test_all_default_parameters_on_vercel/public/robots.txt b/examples/cloud_providers/production_react_vercel/public/robots.txt
similarity index 100%
rename from tests_generated/test_all_default_parameters_on_vercel/public/robots.txt
rename to examples/cloud_providers/production_react_vercel/public/robots.txt
diff --git a/tests_generated/test_all_default_parameters_on_vercel/src/App.tsx b/examples/cloud_providers/production_react_vercel/src/App.tsx
similarity index 100%
rename from tests_generated/test_all_default_parameters_on_vercel/src/App.tsx
rename to examples/cloud_providers/production_react_vercel/src/App.tsx
diff --git a/tests_generated/test_all_default_parameters_on_vercel/src/Home.tsx b/examples/cloud_providers/production_react_vercel/src/Home.tsx
similarity index 100%
rename from tests_generated/test_all_default_parameters_on_vercel/src/Home.tsx
rename to examples/cloud_providers/production_react_vercel/src/Home.tsx
diff --git a/tests_generated/test_all_default_parameters_on_vercel/src/assets/logo.svg b/examples/cloud_providers/production_react_vercel/src/assets/logo.svg
similarity index 100%
rename from tests_generated/test_all_default_parameters_on_vercel/src/assets/logo.svg
rename to examples/cloud_providers/production_react_vercel/src/assets/logo.svg
diff --git a/tests_generated/test_all_default_parameters_on_vercel/src/components/Account.tsx b/examples/cloud_providers/production_react_vercel/src/components/Account.tsx
similarity index 100%
rename from tests_generated/test_all_default_parameters_on_vercel/src/components/Account.tsx
rename to examples/cloud_providers/production_react_vercel/src/components/Account.tsx
diff --git a/examples/cloud_providers/production_react_vercel/src/components/ConnectWallet.tsx b/examples/cloud_providers/production_react_vercel/src/components/ConnectWallet.tsx
new file mode 100644
index 0000000..c4225bc
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/src/components/ConnectWallet.tsx
@@ -0,0 +1,86 @@
+import { Provider, useWallet } from '@txnlab/use-wallet'
+import Account from './Account'
+
+interface ConnectWalletInterface {
+ openModal: boolean
+ closeModal: () => void
+}
+
+const ConnectWallet = ({ openModal, closeModal }: ConnectWalletInterface) => {
+ const { providers, activeAddress } = useWallet()
+
+ const isKmd = (provider: Provider) => provider.metadata.name.toLowerCase() === 'kmd'
+
+ return (
+
+ )
+}
+export default ConnectWallet
diff --git a/tests_generated/test_all_default_parameters_on_vercel/src/components/ErrorBoundary.tsx b/examples/cloud_providers/production_react_vercel/src/components/ErrorBoundary.tsx
similarity index 100%
rename from tests_generated/test_all_default_parameters_on_vercel/src/components/ErrorBoundary.tsx
rename to examples/cloud_providers/production_react_vercel/src/components/ErrorBoundary.tsx
diff --git a/examples/cloud_providers/production_react_vercel/src/components/Transact.tsx b/examples/cloud_providers/production_react_vercel/src/components/Transact.tsx
new file mode 100644
index 0000000..16bd932
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/src/components/Transact.tsx
@@ -0,0 +1,95 @@
+import * as algokit from '@algorandfoundation/algokit-utils'
+import { useWallet } from '@txnlab/use-wallet'
+import algosdk from 'algosdk'
+import { useSnackbar } from 'notistack'
+import { useState } from 'react'
+import { getAlgodConfigFromViteEnvironment } from '../utils/network/getAlgoClientConfigs'
+
+interface TransactInterface {
+ openModal: boolean
+ setModalState: (value: boolean) => void
+}
+
+const Transact = ({ openModal, setModalState }: TransactInterface) => {
+ const [loading, setLoading] = useState(false)
+ const [receiverAddress, setReceiverAddress] = useState('')
+
+ const algodConfig = getAlgodConfigFromViteEnvironment()
+ const algodClient = algokit.getAlgoClient({
+ server: algodConfig.server,
+ port: algodConfig.port,
+ token: algodConfig.token,
+ })
+
+ const { enqueueSnackbar } = useSnackbar()
+
+ const { signer, activeAddress, signTransactions, sendTransactions } = useWallet()
+
+ const handleSubmitAlgo = async () => {
+ setLoading(true)
+
+ if (!signer || !activeAddress) {
+ enqueueSnackbar('Please connect wallet first', { variant: 'warning' })
+ return
+ }
+
+ const suggestedParams = await algodClient.getTransactionParams().do()
+
+ const transaction = algosdk.makePaymentTxnWithSuggestedParamsFromObject({
+ from: activeAddress,
+ to: receiverAddress,
+ amount: 1e6,
+ suggestedParams,
+ })
+
+ const encodedTransaction = algosdk.encodeUnsignedTransaction(transaction)
+
+ const signedTransactions = await signTransactions([encodedTransaction])
+
+ const waitRoundsToConfirm = 4
+
+ try {
+ enqueueSnackbar('Sending transaction...', { variant: 'info' })
+ const { id } = await sendTransactions(signedTransactions, waitRoundsToConfirm)
+ enqueueSnackbar(`Transaction sent: ${id}`, { variant: 'success' })
+ setReceiverAddress('')
+ } catch (e) {
+ enqueueSnackbar('Failed to send transaction', { variant: 'error' })
+ }
+
+ setLoading(false)
+ }
+
+ return (
+
+ )
+}
+
+export default Transact
diff --git a/tests_generated/test_all_default_parameters_on_vercel/src/contracts/README.md b/examples/cloud_providers/production_react_vercel/src/contracts/README.md
similarity index 100%
rename from tests_generated/test_all_default_parameters_on_vercel/src/contracts/README.md
rename to examples/cloud_providers/production_react_vercel/src/contracts/README.md
diff --git a/tests_generated/test_all_default_parameters_on_vercel/src/interfaces/network.ts b/examples/cloud_providers/production_react_vercel/src/interfaces/network.ts
similarity index 100%
rename from tests_generated/test_all_default_parameters_on_vercel/src/interfaces/network.ts
rename to examples/cloud_providers/production_react_vercel/src/interfaces/network.ts
diff --git a/examples/cloud_providers/production_react_vercel/src/main.tsx b/examples/cloud_providers/production_react_vercel/src/main.tsx
new file mode 100644
index 0000000..adf72ec
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/src/main.tsx
@@ -0,0 +1,13 @@
+import React from 'react'
+import ReactDOM from 'react-dom/client'
+import App from './App'
+import './styles/main.css'
+import ErrorBoundary from './components/ErrorBoundary'
+
+ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
+
+
+
+
+ ,
+)
diff --git a/examples/cloud_providers/production_react_vercel/src/styles/main.css b/examples/cloud_providers/production_react_vercel/src/styles/main.css
new file mode 100644
index 0000000..b5c61c9
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/src/styles/main.css
@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
diff --git a/examples/cloud_providers/production_react_vercel/src/utils/ellipseAddress.spec.tsx b/examples/cloud_providers/production_react_vercel/src/utils/ellipseAddress.spec.tsx
new file mode 100644
index 0000000..2cbff10
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/src/utils/ellipseAddress.spec.tsx
@@ -0,0 +1,15 @@
+import { ellipseAddress } from './ellipseAddress'
+
+describe('ellipseAddress', () => {
+ it('should return ellipsed address with specified width', () => {
+ const address = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
+ const result = ellipseAddress(address, 4)
+ expect(result).toBe('aaaa...aaaa')
+ })
+
+ it('should return empty string when address is empty', () => {
+ const address = ''
+ const result = ellipseAddress(address)
+ expect(result).toBe('')
+ })
+})
diff --git a/tests_generated/test_all_default_parameters_on_vercel/src/utils/ellipseAddress.ts b/examples/cloud_providers/production_react_vercel/src/utils/ellipseAddress.ts
similarity index 100%
rename from tests_generated/test_all_default_parameters_on_vercel/src/utils/ellipseAddress.ts
rename to examples/cloud_providers/production_react_vercel/src/utils/ellipseAddress.ts
diff --git a/tests_generated/test_all_default_parameters_on_vercel/src/utils/network/getAlgoClientConfigs.ts b/examples/cloud_providers/production_react_vercel/src/utils/network/getAlgoClientConfigs.ts
similarity index 100%
rename from tests_generated/test_all_default_parameters_on_vercel/src/utils/network/getAlgoClientConfigs.ts
rename to examples/cloud_providers/production_react_vercel/src/utils/network/getAlgoClientConfigs.ts
diff --git a/tests_generated/test_all_default_parameters_on_vercel/src/vite-env.d.ts b/examples/cloud_providers/production_react_vercel/src/vite-env.d.ts
similarity index 100%
rename from tests_generated/test_all_default_parameters_on_vercel/src/vite-env.d.ts
rename to examples/cloud_providers/production_react_vercel/src/vite-env.d.ts
diff --git a/examples/cloud_providers/production_react_vercel/tailwind.config.js b/examples/cloud_providers/production_react_vercel/tailwind.config.js
new file mode 100644
index 0000000..a9f7a95
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/tailwind.config.js
@@ -0,0 +1,11 @@
+/** @type {import('tailwindcss').Config} */
+module.exports = {
+ content: ['./src/**/*.{js,ts,jsx,tsx}'],
+ theme: {
+ extend: {},
+ },
+ daisyui: {
+ themes: ['lofi'],
+ },
+ plugins: [require('daisyui')],
+ }
diff --git a/examples/cloud_providers/production_react_vercel/tests/example.spec.ts b/examples/cloud_providers/production_react_vercel/tests/example.spec.ts
new file mode 100644
index 0000000..df83322
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/tests/example.spec.ts
@@ -0,0 +1,38 @@
+import { randomAccount } from '@algorandfoundation/algokit-utils'
+import { expect, test } from '@playwright/test'
+
+test.beforeEach(async ({ page }) => {
+ await page.goto('http://localhost:5173/')
+})
+
+test('has title', async ({ page }) => {
+ // Expect a title "to contain" a substring.
+ await expect(page).toHaveTitle('AlgoKit React Template')
+})
+
+test('get started link', async ({ page }) => {
+ await expect(page.getByTestId('getting-started')).toHaveText('Getting started')
+})
+
+test('authentication and dummy payment transaction', async ({ page }) => {
+ page.on('dialog', async (dialog) => {
+ dialog.message() === 'KMD password' ? await dialog.accept() : await dialog.dismiss()
+ })
+
+ // 1. Must be able to connect to a KMD wallet provider
+ await page.getByTestId('connect-wallet').click()
+ await page.getByTestId('kmd-connect').click()
+ await page.getByTestId('close-wallet-modal').click()
+
+ // 2. Must be able to send a dummy payment transaction
+ await page.getByTestId('transactions-demo').click()
+
+ const dummyAccount = randomAccount()
+ await page.getByTestId('receiver-address').fill(dummyAccount.addr)
+ await page.getByTestId('send-algo').click()
+
+ // 3. Must be able to see a notification that the transaction was sent
+ const notification = await page.getByText('Transaction sent:')
+ await notification.waitFor()
+ expect(notification).toBeTruthy()
+})
diff --git a/examples/cloud_providers/production_react_vercel/tsconfig.json b/examples/cloud_providers/production_react_vercel/tsconfig.json
new file mode 100644
index 0000000..5cde02a
--- /dev/null
+++ b/examples/cloud_providers/production_react_vercel/tsconfig.json
@@ -0,0 +1,38 @@
+{
+ "compilerOptions": {
+ "target": "ES2020" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
+ "module": "ES2022" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
+ "declaration": true /* Generates corresponding '.d.ts' file. */,
+ "declarationMap": true /* Generates a sourcemap for each corresponding '.d.ts' file. */,
+ "sourceMap": true /* Generates corresponding '.map' file. */,
+ "strict": true /* Enable all strict type-checking options. */,
+ "noImplicitReturns": true /* Report error when not all code paths in function return a value. */,
+ "noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */,
+ "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
+ "experimentalDecorators": true /* Enables experimental support for ES7 decorators. */,
+ "emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */,
+ "skipLibCheck": true /* Skip type checking of declaration files. */,
+ "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */,
+ "allowJs": false,
+ "allowSyntheticDefaultImports": true,
+ "moduleResolution": "Node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+ "outDir": "./dist/"
+ },
+ "include": [
+ "src/**/*.ts",
+ "src/**/*.tsx",
+ "vite.config.js",
+ "src/utils/ellipseAddress.spec.tsx",
+ "src/utils/ellipseAddress.spec.tsx",
+ "src/main.tsx",
+ ],
+ "references": [
+ {
+ "path": "./tsconfig.node.json"
+ }
+ ]
+}
diff --git a/tests_generated/test_all_default_parameters_on_vercel/tsconfig.node.json b/examples/cloud_providers/production_react_vercel/tsconfig.node.json
similarity index 100%
rename from tests_generated/test_all_default_parameters_on_vercel/tsconfig.node.json
rename to examples/cloud_providers/production_react_vercel/tsconfig.node.json
diff --git a/tests_generated/test_all_default_parameters_on_vercel/vite.config.ts b/examples/cloud_providers/production_react_vercel/vite.config.ts
similarity index 100%
rename from tests_generated/test_all_default_parameters_on_vercel/vite.config.ts
rename to examples/cloud_providers/production_react_vercel/vite.config.ts
diff --git a/examples/production_react/.algokit.toml b/examples/production_react/.algokit.toml
new file mode 100644
index 0000000..197568b
--- /dev/null
+++ b/examples/production_react/.algokit.toml
@@ -0,0 +1,10 @@
+[algokit]
+min_version = "v1.3.0b1"
+
+[generate.import_contract]
+description = "Import a typed client from your smart contracts project"
+path = ".algokit/generators/import_contract"
+
+[project]
+type = "frontend"
+name = "production_react"
diff --git a/examples/production_react/.copier-answers.yml b/examples/production_react/.copier-answers.yml
new file mode 100644
index 0000000..be9a94d
--- /dev/null
+++ b/examples/production_react/.copier-answers.yml
@@ -0,0 +1,9 @@
+# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY
+_commit:
+_src_path:
+author_email: None
+author_name: None
+cloud_provider: none
+preset_name: production
+project_name: production_react
+
diff --git a/examples/production_react/.editorconfig b/examples/production_react/.editorconfig
new file mode 100644
index 0000000..a83b72c
--- /dev/null
+++ b/examples/production_react/.editorconfig
@@ -0,0 +1,9 @@
+[*]
+charset = utf-8
+insert_final_newline = true
+end_of_line = lf
+indent_style = space
+indent_size = 2
+tab_width = 2
+max_line_length = 140
+trim_trailing_whitespace = true
diff --git a/examples/production_react/.env.template b/examples/production_react/.env.template
new file mode 100644
index 0000000..e05d499
--- /dev/null
+++ b/examples/production_react/.env.template
@@ -0,0 +1,67 @@
+# ======================
+# LocalNet configuration
+# uncomment below to use
+# ======================
+
+VITE_ENVIRONMENT=local
+
+# Algod
+VITE_ALGOD_TOKEN=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+VITE_ALGOD_SERVER=http://localhost
+VITE_ALGOD_PORT=4001
+VITE_ALGOD_NETWORK=""
+
+# Indexer
+VITE_INDEXER_TOKEN=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+VITE_INDEXER_SERVER=http://localhost
+VITE_INDEXER_PORT=8980
+
+# KMD
+# Please note:
+# 1. This is only needed for LocalNet since
+# by default KMD provider is ignored on other networks.
+# 2. AlgoKit LocalNet starts with a single wallet called 'unencrypted-default-wallet',
+# with heaps of tokens available for testing.
+VITE_KMD_TOKEN=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+VITE_KMD_SERVER=http://localhost
+VITE_KMD_PORT=4002
+VITE_KMD_WALLET="unencrypted-default-wallet"
+VITE_KMD_PASSWORD=""
+
+# # ======================
+# # TestNet configuration:
+# # uncomment below to use
+# # ======================
+
+# VITE_ENVIRONMENT=local
+
+# # Algod
+# VITE_ALGOD_TOKEN=""
+# VITE_ALGOD_SERVER="https://testnet-api.algonode.cloud"
+# VITE_ALGOD_PORT=""
+# VITE_ALGOD_NETWORK="testnet"
+
+# # Indexer
+# VITE_INDEXER_TOKEN=""
+# VITE_INDEXER_SERVER="https://testnet-idx.algonode.cloud"
+# VITE_INDEXER_PORT=""
+
+
+# # ======================
+# # MainNet configuration:
+# # uncomment below to use
+# # ======================
+
+# VITE_ENVIRONMENT=production
+
+# # Algod
+# VITE_ALGOD_TOKEN=""
+# VITE_ALGOD_SERVER="https://mainnet-api.algonode.cloud"
+# VITE_ALGOD_PORT=""
+# VITE_ALGOD_NETWORK="mainnet"
+
+# # Indexer
+# VITE_INDEXER_TOKEN=""
+# VITE_INDEXER_SERVER="https://mainnet-idx.algonode.cloud"
+# VITE_INDEXER_PORT=""
+
diff --git a/examples/production_react/.eslintrc b/examples/production_react/.eslintrc
new file mode 100644
index 0000000..868fe37
--- /dev/null
+++ b/examples/production_react/.eslintrc
@@ -0,0 +1,27 @@
+{
+ "root": true,
+ "env": {
+ "node": true
+ },
+ "parser": "@typescript-eslint/parser",
+ "plugins": ["@typescript-eslint", "prettier"],
+ "extends": [
+ "eslint:recommended",
+ "plugin:@typescript-eslint/eslint-recommended",
+ "plugin:@typescript-eslint/recommended",
+ "plugin:prettier/recommended"
+ ],
+ "rules": {
+ "prettier/prettier": "warn",
+ "no-console": "warn",
+ "@typescript-eslint/no-unused-vars": [
+ "warn",
+ {
+ "ignoreRestSiblings": true,
+ "argsIgnorePattern": "^_",
+ "destructuredArrayIgnorePattern": "^_"
+ }
+ ],
+ "prefer-template": "error"
+ }
+}
diff --git a/examples/production_react/.gitattributes b/examples/production_react/.gitattributes
new file mode 100644
index 0000000..6313b56
--- /dev/null
+++ b/examples/production_react/.gitattributes
@@ -0,0 +1 @@
+* text=auto eol=lf
diff --git a/examples/production_react/.github/workflows/checks.yaml b/examples/production_react/.github/workflows/checks.yaml
new file mode 100644
index 0000000..4723b1a
--- /dev/null
+++ b/examples/production_react/.github/workflows/checks.yaml
@@ -0,0 +1,54 @@
+name: Check code base
+
+on:
+ workflow_call:
+ inputs:
+ run-build:
+ required: false
+ type: boolean
+ default: false
+ push:
+ branches:
+ - main
+
+jobs:
+ checks:
+ runs-on: 'ubuntu-latest'
+ steps:
+ - name: Check out repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Setup node
+ uses: actions/setup-node@v3
+ with:
+ node-version: 18
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Run linters
+ run: npm run lint
+
+ - name: Run unit tests
+ run: npm run test
+
+ - name: Create placeholder .env file
+ if: ${{ inputs.run-build }}
+ uses: makerxstudio/shared-config/.github/actions/env-to-placeholders@main
+ with:
+ env-output-path: './.env'
+ env-template-path: './.env.template'
+ env-variable-prefix: VITE_
+
+ - name: Build
+ if: ${{ inputs.run-build }}
+ run: npm run build
+
+ - name: Archive
+ if: ${{ inputs.run-build }}
+ uses: actions/upload-artifact@v4
+ with:
+ name: dist
+ path: dist/
diff --git a/examples/production_react/.github/workflows/pr.yaml b/examples/production_react/.github/workflows/pr.yaml
new file mode 100644
index 0000000..a80f784
--- /dev/null
+++ b/examples/production_react/.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/examples/production_react/.github/workflows/release.yaml b/examples/production_react/.github/workflows/release.yaml
new file mode 100644
index 0000000..b6a5206
--- /dev/null
+++ b/examples/production_react/.github/workflows/release.yaml
@@ -0,0 +1,62 @@
+name: Release
+
+on:
+ push:
+ branches:
+ - main
+ paths-ignore:
+ - "docs/**"
+ - "**.md"
+ - ".vscode/**"
+ - ".idea/**"
+
+permissions:
+ contents: read
+ packages: read
+
+jobs:
+ lint-and-build:
+ name: CI dApp
+ uses: ./.github/workflows/checks.yaml
+
+ deploy:
+ runs-on: ubuntu-latest
+ name: Deploy to Netlify
+ environment: Prod
+ concurrency: "${{ github.workflow }}-prod"
+ needs:
+ - lint-and-build
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v2
+
+ - name: Download build artifacts
+ uses: actions/download-artifact@v4
+ with:
+ name: dist
+ path: dist
+
+ - name: Replace template vars
+ uses: makerxstudio/shared-config/.github/actions/placeholder-transforms@main
+ with:
+ app-artifact-path: './dist'
+ static-site-transforms: |-
+ VITE_ALGOD_TOKEN:${{ secrets.VITE_ALGOD_TOKEN }}
+ VITE_ALGOD_SERVER:${{ vars.VITE_ALGOD_SERVER }}
+ VITE_ALGOD_PORT:${{ vars.VITE_ALGOD_PORT }}
+ VITE_ALGOD_NETWORK:${{ vars.VITE_ALGOD_NETWORK }}
+ VITE_INDEXER_SERVER:${{ vars.VITE_INDEXER_SERVER }}
+ VITE_INDEXER_PORT:${{ vars.VITE_INDEXER_PORT }}
+ VITE_INDEXER_TOKEN:${{ secrets.VITE_INDEXER_TOKEN }}
+ VITE_ENVIRONMENT:${{ vars.VITE_ENVIRONMENT }}
+
+ - name: Install netlify cli
+ run: npm i netlify-cli
+
+ - name: Publish to netlify
+ run: netlify deploy --prod --dir "dist"
+ env:
+ NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
+ NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
+ # Set your netlify project env variables on your github repository (see README for more info)
+
diff --git a/examples/production_react/.gitignore b/examples/production_react/.gitignore
new file mode 100644
index 0000000..26dc019
--- /dev/null
+++ b/examples/production_react/.gitignore
@@ -0,0 +1,35 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# production
+/build
+
+
+# dotenv environment variable files
+.env
+env/
+
+# misc
+/dist
+.DS_Store
+
+
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+/test-results/
+/playwright-report/
+/playwright/.cache/
+
+# PyCharm
+.idea
+!.idea/
+.idea/*
+!.idea/runConfigurations/
diff --git a/examples/production_react/.idea/runConfigurations/Run_Chrome.xml b/examples/production_react/.idea/runConfigurations/Run_Chrome.xml
new file mode 100644
index 0000000..9dfeeca
--- /dev/null
+++ b/examples/production_react/.idea/runConfigurations/Run_Chrome.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/examples/production_react/.idea/runConfigurations/Run_dApp.xml b/examples/production_react/.idea/runConfigurations/Run_dApp.xml
new file mode 100644
index 0000000..1cf2273
--- /dev/null
+++ b/examples/production_react/.idea/runConfigurations/Run_dApp.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/production_react/.idea/runConfigurations/Run_dApp____LocalNet_.xml b/examples/production_react/.idea/runConfigurations/Run_dApp____LocalNet_.xml
new file mode 100644
index 0000000..3758c8b
--- /dev/null
+++ b/examples/production_react/.idea/runConfigurations/Run_dApp____LocalNet_.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/production_react/.idea/runConfigurations/Start_AlgoKit_LocalNet.xml b/examples/production_react/.idea/runConfigurations/Start_AlgoKit_LocalNet.xml
new file mode 100644
index 0000000..0394a67
--- /dev/null
+++ b/examples/production_react/.idea/runConfigurations/Start_AlgoKit_LocalNet.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/production_react/.prettierignore b/examples/production_react/.prettierignore
new file mode 100644
index 0000000..dbda6ae
--- /dev/null
+++ b/examples/production_react/.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/examples/production_react/.prettierrc.cjs b/examples/production_react/.prettierrc.cjs
new file mode 100644
index 0000000..066b8e5
--- /dev/null
+++ b/examples/production_react/.prettierrc.cjs
@@ -0,0 +1,10 @@
+module.exports = {
+ singleQuote: true,
+ jsxSingleQuote: false,
+ semi: false,
+ tabWidth: 2,
+ trailingComma: 'all',
+ printWidth: 140,
+ endOfLine: 'lf',
+ arrowParens: 'always',
+}
diff --git a/examples/production_react/.vscode/extensions.json b/examples/production_react/.vscode/extensions.json
new file mode 100644
index 0000000..5c94122
--- /dev/null
+++ b/examples/production_react/.vscode/extensions.json
@@ -0,0 +1,14 @@
+{
+ "recommendations": [
+ "EditorConfig.EditorConfig",
+ "dotenv.dotenv-vscode",
+ "esbenp.prettier-vscode",
+ "dbaeumer.vscode-eslint",
+ "krysenlo.vite-plugin-eslint-problemmatcher",
+ "ms-playwright.playwright",
+ "Orta.vscode-jest",
+ "bradlc.vscode-tailwindcss",
+ "csstools.postcss",
+ ]
+}
+
diff --git a/examples/production_react/.vscode/launch.json b/examples/production_react/.vscode/launch.json
new file mode 100644
index 0000000..7edaf04
--- /dev/null
+++ b/examples/production_react/.vscode/launch.json
@@ -0,0 +1,68 @@
+{
+ "configurations": [
+ {
+ "type": "msedge",
+ "request": "launch",
+ "name": "Run (Edge)",
+ "url": "http://localhost:5173",
+ "webRoot": "${workspaceFolder}",
+ "presentation": {
+ "hidden": false,
+ "group": "2. Web"
+ }
+ },
+ {
+ "type": "chrome",
+ "request": "launch",
+ "name": "Run (Chrome)",
+ "url": "http://localhost:5173",
+ "webRoot": "${workspaceFolder}",
+ "presentation": {
+ "hidden": false,
+ "group": "2. Web"
+ }
+ },
+ {
+ "type": "firefox",
+ "request": "launch",
+ "name": "Run (Firefox)",
+ "url": "http://localhost:5173",
+ "webRoot": "${workspaceFolder}",
+ "presentation": {
+ "hidden": false,
+ "group": "2. Web"
+ }
+ },
+ {
+ "name": "Run dApp",
+ "type": "node",
+ "request": "launch",
+ "runtimeExecutable": "npm",
+ "runtimeArgs": ["run", "dev"],
+ "cwd": "${workspaceRoot}",
+ "console": "integratedTerminal",
+ "skipFiles": ["/**", "node_modules/**"],
+ "presentation": {
+ "hidden": false,
+ "group": "1. Run Project",
+ "order": 1
+ }
+ },
+ {
+ "name": "Run dApp (+ LocalNet)",
+ "type": "node",
+ "request": "launch",
+ "runtimeExecutable": "npm",
+ "runtimeArgs": ["run", "dev"],
+ "cwd": "${workspaceRoot}",
+ "console": "integratedTerminal",
+ "skipFiles": ["/**", "node_modules/**"],
+ "preLaunchTask": "Start AlgoKit LocalNet",
+ "presentation": {
+ "hidden": false,
+ "group": "1. Run Project",
+ "order": 1
+ }
+ }
+ ]
+}
diff --git a/examples/production_react/.vscode/settings.json b/examples/production_react/.vscode/settings.json
new file mode 100644
index 0000000..6ffe6b3
--- /dev/null
+++ b/examples/production_react/.vscode/settings.json
@@ -0,0 +1,13 @@
+{
+ "editor.formatOnSave": true,
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
+ "editor.codeActionsOnSave": {
+ "source.fixAll.eslint": true,
+ "source.organizeImports": true
+ },
+ "dotenv.enableAutocloaking": false,
+ "jest.autoRun": {
+ "watch": false,
+ "onSave": "test-file"
+ }
+}
diff --git a/examples/production_react/.vscode/tasks.json b/examples/production_react/.vscode/tasks.json
new file mode 100644
index 0000000..d611c4f
--- /dev/null
+++ b/examples/production_react/.vscode/tasks.json
@@ -0,0 +1,15 @@
+{
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "Start AlgoKit LocalNet",
+ "command": "algokit",
+ "args": ["localnet", "start"],
+ "type": "shell",
+ "options": {
+ "cwd": "${workspaceFolder}"
+ },
+ "problemMatcher": []
+ }
+ ]
+}
diff --git a/examples/production_react/LICENSE b/examples/production_react/LICENSE
new file mode 100644
index 0000000..b39bcd6
--- /dev/null
+++ b/examples/production_react/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2023 Algorand Foundation
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/tests_generated/test_all_default_parameters_off/README.md b/examples/production_react/README.md
similarity index 53%
rename from tests_generated/test_all_default_parameters_off/README.md
rename to examples/production_react/README.md
index 52afa0e..2387940 100644
--- a/tests_generated/test_all_default_parameters_off/README.md
+++ b/examples/production_react/README.md
@@ -1,4 +1,4 @@
-# test_all_default_parameters_off
+# production_react
This starter React project has been generated using AlgoKit. See below for default getting started instructions.
@@ -31,6 +31,41 @@ This starter React project has been generated using AlgoKit. See below for defau
> Please note, by default frontend is pre configured to run against Algorand LocalNet. If you want to run against TestNet or MainNet, comment out the current environment variable and uncomment the relevant one in [`.env`](.env) file that is created after running bootstrap command and based on [`.env.template`](.env.template).
+### Continuous Integration
+
+This project uses [GitHub Actions](https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions) to define CI workflows, which are located in the [`.github/workflows`](./.github/workflows) folder.
+
+For pull requests and pushes to `main` branch against this repository the following checks are automatically performed by GitHub Actions:
+
+- `install`: Installs dependencies using `npm`
+- `lint`: Lints the codebase using `ESLint`
+- `build`: Builds the codebase using `vite`
+
+### Continuous Deployment
+
+The project template provides base Github Actions workflows for continuous deployment to [Netlify](https://www.netlify.com/) or [Vercel](https://vercel.com/). These workflows are located in the [`.github/workflows`](./.github/workflows) folder.
+
+**Please note**: when configuring the github repository for the first time. Depending on selected provider you will need to set the provider secrets in the repository settings. Default setup provided by the template allows you to manage the secrets via environment variables and secrets on your github repository.
+
+
+#### Setting up environment variables and secrets for webapp deployment
+
+1. [Create a new environment variable on your repository](https://docs.github.com/en/actions/learn-github-actions/variables#creating-configuration-variables-for-a-repository) called `NETLIFY_AUTH_TOKEN` and `NETLIFY_SITE_ID` if you are using Netlify as your cloud provider. Set it to the value of your Netlify auth token respectively. You can find your Netlify auth token by going to [app.netlify.com](https://app.netlify.com/).
+2. If you are using Vercel as your cloud provider, create a new environment variable on your repository called `VERCEL_TOKEN`. Set it to the value of your Vercel auth token. You can find your Vercel auth token by going to [vercel.com/account/tokens](https://vercel.com/account/tokens).
+3. Set up the environment variables. You can refer to the `.env.template` for default values. The variables to be set are:
+ - `VITE_ALGOD_SERVER`
+ - `VITE_ALGOD_NETWORK`
+ - `VITE_INDEXER_SERVER`
+ - `VITE_ENVIRONMENT` - (Set to either `production` or `development`)
+ - `VITE_ALGOD_PORT` - (This is optional if you are using a public gateway like AlgoNode)
+ - `VITE_INDEXER_PORT` - (This is optional if you are using a public gateway like AlgoNode)
+4. (Optional) If you need to set up environment secrets, you can do so by following the guide [here](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions#creating-secrets-for-a-repository). The variables for which you can set secrets are (refer to `.env.template` for default values):
+ - `VITE_ALGOD_TOKEN` - (This is optional if you are using a public gateway like AlgoNode)
+ - `VITE_INDEXER_TOKEN` - (This is optional if you are using a public gateway like AlgoNode)
+
+> If you prefer alternative deployment methods, you can remove the relevant workflow files from the [`.github/workflows`](./.github/workflows) folder and configure your own.
+
+
# Algorand Wallet integrations
The template comes with [`use-wallet`](https://github.com/txnlab/use-wallet) integration, which provides a React hook for connecting to an Algorand wallet providers. The following wallet providers are included by default:
@@ -50,8 +85,16 @@ This project makes use of React and Tailwind to provider a base project configur
- [AlgoKit Utils](https://github.com/algorandfoundation/algokit-utils-ts) - Various TypeScript utilities to simplify interactions with Algorand and AlgoKit.
- [React](https://reactjs.org/) - A JavaScript library for building user interfaces.
+- [Tailwind CSS](https://tailwindcss.com/) - A utility-first CSS framework for rapidly building custom designs.
+- [daisyUI](https://daisyui.com/) - A component library for Tailwind CSS.
- [use-wallet](https://github.com/txnlab/use-wallet) - A React hook for connecting to an Algorand wallet providers.
- [npm](https://www.npmjs.com/): Node.js package manager
+- [jest](https://jestjs.io/): JavaScript testing framework
+- [playwright](https://playwright.dev/): Browser automation library
+- [Prettier](https://prettier.io/): Opinionated code formatter
+- [ESLint](https://eslint.org/): Tool for identifying and reporting on patterns in JavaScript
+- Github Actions workflows for build validation
+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.
# Integrating with smart contracts and application clients
Refer to the detailed guidance on [integrating with smart contracts and application clients](./src/contracts/README.md). In essence, for any smart contract codebase generated with AlgoKit or other tools that produce compile contracts into ARC34 compliant app specifications, you can use the `algokit generate` command to generate TypeScript or Python typed client. Once generated simply drag and drop the generated client into `./src/contracts` and import it into your React components as you see fit.
diff --git a/examples/production_react/index.html b/examples/production_react/index.html
new file mode 100644
index 0000000..a85566a
--- /dev/null
+++ b/examples/production_react/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+ AlgoKit React Template
+
+
+
+
+
+
+
diff --git a/examples/production_react/jest.config.ts b/examples/production_react/jest.config.ts
new file mode 100644
index 0000000..28a8c3d
--- /dev/null
+++ b/examples/production_react/jest.config.ts
@@ -0,0 +1,20 @@
+import type { Config } from '@jest/types'
+
+const config: Config.InitialOptions = {
+ preset: 'ts-jest',
+ testEnvironment: 'node',
+ testMatch: ['**/*.spec.ts', '**/*.spec.tsx'],
+ moduleDirectories: ['node_modules', 'src'],
+ transform: {
+ '': [
+ 'ts-jest',
+ {
+ tsconfig: 'tsconfig.test.json',
+ },
+ ],
+ },
+ coveragePathIgnorePatterns: ['tests'],
+ testPathIgnorePatterns: ['/tests/'],
+ }
+
+export default config
diff --git a/tests_generated/test_all_default_parameters_jetbrains/package.json b/examples/production_react/package.json
similarity index 62%
rename from tests_generated/test_all_default_parameters_jetbrains/package.json
rename to examples/production_react/package.json
index 62e7553..0cd594b 100644
--- a/tests_generated/test_all_default_parameters_jetbrains/package.json
+++ b/examples/production_react/package.json
@@ -1,5 +1,5 @@
{
- "name": "test_all_default_parameters_jetbrains",
+ "name": "production_react",
"version": "0.1.0",
"author": {
"name": "None",
@@ -16,8 +16,19 @@
"@types/react-dom": "^18.2.4",
"@vitejs/plugin-react": "^4.2.1",
"autoprefixer": "^10.4.14",
+ "eslint": "^8.42.0",
+ "eslint-config-prettier": "^8.8.0",
+ "eslint-plugin-prettier": "^5.0.0",
+ "@typescript-eslint/eslint-plugin": "^6.5.0",
+ "@typescript-eslint/parser": "^6.5.0",
+ "postcss": "^8.4.24",
+ "tailwindcss": "3.3.2",
+ "ts-jest": "^29.1.1",
+ "@types/jest": "29.5.2",
"ts-node": "^10.9.1",
"typescript": "^5.1.6",
+ "@playwright/test": "^1.35.0",
+ "playwright": "^1.35.0",
"vite": "^5.0.0"
},
"dependencies": {
@@ -28,6 +39,7 @@
"@perawallet/connect": "^1.3.1",
"@txnlab/use-wallet": "^2.4.0",
"algosdk": "^2.7.0",
+ "daisyui": "^4.0.0",
"notistack": "^3.0.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
@@ -36,10 +48,15 @@
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
+ "test": "jest --coverage --passWithNoTests",
+ "playwright:test": "playwright test",
+ "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
+ "lint:fix": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0 --fix",
"preview": "vite preview"
},
"eslintConfig": {
"extends": [
+ "react-app/jest",
"react-app"
]
},
diff --git a/examples/production_react/playwright.config.ts b/examples/production_react/playwright.config.ts
new file mode 100644
index 0000000..d7cbca6
--- /dev/null
+++ b/examples/production_react/playwright.config.ts
@@ -0,0 +1,73 @@
+import { defineConfig, devices } from '@playwright/test'
+
+/**
+ * Read environment variables from file.
+ * https://github.com/motdotla/dotenv
+ */
+// require('dotenv').config();
+
+/**
+ * See https://playwright.dev/docs/test-configuration.
+ */
+export default defineConfig({
+ testDir: './tests',
+ /* Run tests in files in parallel */
+ fullyParallel: true,
+ /* Fail the build on CI if you accidentally left test.only in the source code. */
+ forbidOnly: !!process.env.CI,
+ /* Retry on CI only */
+ retries: process.env.CI ? 2 : 0,
+ /* Opt out of parallel tests on CI. */
+ workers: process.env.CI ? 1 : undefined,
+ /* Reporter to use. See https://playwright.dev/docs/test-reporters */
+ reporter: 'html',
+ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
+ use: {
+ /* Base URL to use in actions like `await page.goto('/')`. */
+ // baseURL: 'http://127.0.0.1:3000',
+
+ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
+ trace: 'on-first-retry',
+ testIdAttribute: 'data-test-id',
+ },
+
+ /* Configure projects for major browsers */
+ projects: [
+ {
+ name: 'chromium',
+ use: { ...devices['Desktop Chrome'] },
+ },
+
+ {
+ name: 'firefox',
+ use: { ...devices['Desktop Firefox'] },
+ },
+
+ /* Test against mobile viewports. */
+ // {
+ // name: 'Mobile Chrome',
+ // use: { ...devices['Pixel 5'] },
+ // },
+ // {
+ // name: 'Mobile Safari',
+ // use: { ...devices['iPhone 12'] },
+ // },
+
+ /* Test against branded browsers. */
+ // {
+ // name: 'Microsoft Edge',
+ // use: { ...devices['Desktop Edge'], channel: 'msedge' },
+ // },
+ // {
+ // name: 'Google Chrome',
+ // use: { ..devices['Desktop Chrome'], channel: 'chrome' },
+ // },
+ ],
+
+ /* Run your local dev server before starting the tests */
+ webServer: {
+ command: 'npm run dev',
+ url: 'http://localhost:5173',
+ reuseExistingServer: !process.env.CI,
+ },
+})
diff --git a/examples/production_react/postcss.config.cjs b/examples/production_react/postcss.config.cjs
new file mode 100644
index 0000000..33ad091
--- /dev/null
+++ b/examples/production_react/postcss.config.cjs
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/examples/production_react/public/index.html b/examples/production_react/public/index.html
new file mode 100644
index 0000000..0d3a3a5
--- /dev/null
+++ b/examples/production_react/public/index.html
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+ React App
+
+
+
+
+
+
+
diff --git a/examples/production_react/public/robots.txt b/examples/production_react/public/robots.txt
new file mode 100644
index 0000000..e9e57dc
--- /dev/null
+++ b/examples/production_react/public/robots.txt
@@ -0,0 +1,3 @@
+# https://www.robotstxt.org/robotstxt.html
+User-agent: *
+Disallow:
diff --git a/examples/production_react/src/App.tsx b/examples/production_react/src/App.tsx
new file mode 100644
index 0000000..58feddf
--- /dev/null
+++ b/examples/production_react/src/App.tsx
@@ -0,0 +1,57 @@
+import { DeflyWalletConnect } from '@blockshake/defly-connect'
+import { DaffiWalletConnect } from '@daffiwallet/connect'
+import { PeraWalletConnect } from '@perawallet/connect'
+import { PROVIDER_ID, ProvidersArray, WalletProvider, useInitializeProviders } from '@txnlab/use-wallet'
+import algosdk from 'algosdk'
+import { SnackbarProvider } from 'notistack'
+import Home from './Home'
+import { getAlgodConfigFromViteEnvironment, getKmdConfigFromViteEnvironment } from './utils/network/getAlgoClientConfigs'
+
+let providersArray: ProvidersArray
+if (import.meta.env.VITE_ALGOD_NETWORK === '') {
+ const kmdConfig = getKmdConfigFromViteEnvironment()
+ providersArray = [
+ {
+ id: PROVIDER_ID.KMD,
+ clientOptions: {
+ wallet: kmdConfig.wallet,
+ password: kmdConfig.password,
+ host: kmdConfig.server,
+ token: String(kmdConfig.token),
+ port: String(kmdConfig.port),
+ },
+ },
+ ]
+} else {
+ providersArray = [
+ { id: PROVIDER_ID.DEFLY, clientStatic: DeflyWalletConnect },
+ { id: PROVIDER_ID.PERA, clientStatic: PeraWalletConnect },
+ { id: PROVIDER_ID.DAFFI, clientStatic: DaffiWalletConnect },
+ { id: PROVIDER_ID.EXODUS },
+ // If you are interested in WalletConnect v2 provider
+ // refer to https://github.com/TxnLab/use-wallet for detailed integration instructions
+ ]
+}
+
+export default function App() {
+ const algodConfig = getAlgodConfigFromViteEnvironment()
+
+ const walletProviders = useInitializeProviders({
+ providers: providersArray,
+ nodeConfig: {
+ network: algodConfig.network,
+ nodeServer: algodConfig.server,
+ nodePort: String(algodConfig.port),
+ nodeToken: String(algodConfig.token),
+ },
+ algosdkStatic: algosdk,
+ })
+
+ return (
+
+
+
+
+
+ )
+}
diff --git a/examples/production_react/src/Home.tsx b/examples/production_react/src/Home.tsx
new file mode 100644
index 0000000..42128d8
--- /dev/null
+++ b/examples/production_react/src/Home.tsx
@@ -0,0 +1,63 @@
+// src/components/Home.tsx
+import { useWallet } from '@txnlab/use-wallet'
+import React, { useState } from 'react'
+import ConnectWallet from './components/ConnectWallet'
+import Transact from './components/Transact'
+
+interface HomeProps {}
+
+const Home: React.FC = () => {
+ const [openWalletModal, setOpenWalletModal] = useState(false)
+ const [openDemoModal, setOpenDemoModal] = useState(false)
+ const { activeAddress } = useWallet()
+
+ const toggleWalletModal = () => {
+ setOpenWalletModal(!openWalletModal)
+ }
+
+ const toggleDemoModal = () => {
+ setOpenDemoModal(!openDemoModal)
+ }
+
+ return (
+
+
+
+
+ Welcome to
AlgoKit 🙂
+
+
+ This starter has been generated using official AlgoKit React template. Refer to the resource below for next steps.
+
+
+
+
+ Getting started
+
+
+
+
+
+ {activeAddress && (
+
+ )}
+
+
+
+
+
+
+
+ )
+}
+
+export default Home
diff --git a/examples/production_react/src/assets/logo.svg b/examples/production_react/src/assets/logo.svg
new file mode 100644
index 0000000..7169476
--- /dev/null
+++ b/examples/production_react/src/assets/logo.svg
@@ -0,0 +1 @@
+
diff --git a/examples/production_react/src/components/Account.tsx b/examples/production_react/src/components/Account.tsx
new file mode 100644
index 0000000..6a6345e
--- /dev/null
+++ b/examples/production_react/src/components/Account.tsx
@@ -0,0 +1,28 @@
+import { useWallet } from '@txnlab/use-wallet'
+import { useMemo } from 'react'
+import { ellipseAddress } from '../utils/ellipseAddress'
+import { getAlgodConfigFromViteEnvironment } from '../utils/network/getAlgoClientConfigs'
+
+const Account = () => {
+ const { activeAddress } = useWallet()
+ const algoConfig = getAlgodConfigFromViteEnvironment()
+
+ const dappFlowNetworkName = useMemo(() => {
+ return algoConfig.network === '' ? 'sandbox' : algoConfig.network.toLocaleLowerCase()
+ }, [algoConfig.network])
+
+ return (
+
+ )
+}
+
+export default Account
diff --git a/examples/production_react/src/components/ConnectWallet.tsx b/examples/production_react/src/components/ConnectWallet.tsx
new file mode 100644
index 0000000..c4225bc
--- /dev/null
+++ b/examples/production_react/src/components/ConnectWallet.tsx
@@ -0,0 +1,86 @@
+import { Provider, useWallet } from '@txnlab/use-wallet'
+import Account from './Account'
+
+interface ConnectWalletInterface {
+ openModal: boolean
+ closeModal: () => void
+}
+
+const ConnectWallet = ({ openModal, closeModal }: ConnectWalletInterface) => {
+ const { providers, activeAddress } = useWallet()
+
+ const isKmd = (provider: Provider) => provider.metadata.name.toLowerCase() === 'kmd'
+
+ return (
+
+ )
+}
+export default ConnectWallet
diff --git a/examples/production_react/src/components/ErrorBoundary.tsx b/examples/production_react/src/components/ErrorBoundary.tsx
new file mode 100644
index 0000000..435bf61
--- /dev/null
+++ b/examples/production_react/src/components/ErrorBoundary.tsx
@@ -0,0 +1,46 @@
+import React, { ReactNode } from 'react'
+
+interface ErrorBoundaryProps {
+ children: ReactNode
+}
+
+interface ErrorBoundaryState {
+ hasError: boolean
+ error: Error | null
+}
+
+class ErrorBoundary extends React.Component {
+ constructor(props: ErrorBoundaryProps) {
+ super(props)
+ this.state = { hasError: false, error: null }
+ }
+
+ static getDerivedStateFromError(error: Error): ErrorBoundaryState {
+ // Update state so the next render will show the fallback UI.
+ return { hasError: true, error: error }
+ }
+
+ render(): ReactNode {
+ if (this.state.hasError) {
+ // You can render any custom fallback UI
+ return (
+
+
+
+
Error occured
+
+ {this.state.error?.message.includes('Attempt to get default algod configuration')
+ ? 'Please make sure to set up your environment variables correctly. Create a .env file based on .env.template and fill in the required values. This controls the network and credentials for connections with Algod and Indexer.'
+ : this.state.error?.message}
+
+
+
+
+ )
+ }
+
+ return this.props.children
+ }
+}
+
+export default ErrorBoundary
diff --git a/examples/production_react/src/components/Transact.tsx b/examples/production_react/src/components/Transact.tsx
new file mode 100644
index 0000000..16bd932
--- /dev/null
+++ b/examples/production_react/src/components/Transact.tsx
@@ -0,0 +1,95 @@
+import * as algokit from '@algorandfoundation/algokit-utils'
+import { useWallet } from '@txnlab/use-wallet'
+import algosdk from 'algosdk'
+import { useSnackbar } from 'notistack'
+import { useState } from 'react'
+import { getAlgodConfigFromViteEnvironment } from '../utils/network/getAlgoClientConfigs'
+
+interface TransactInterface {
+ openModal: boolean
+ setModalState: (value: boolean) => void
+}
+
+const Transact = ({ openModal, setModalState }: TransactInterface) => {
+ const [loading, setLoading] = useState(false)
+ const [receiverAddress, setReceiverAddress] = useState('')
+
+ const algodConfig = getAlgodConfigFromViteEnvironment()
+ const algodClient = algokit.getAlgoClient({
+ server: algodConfig.server,
+ port: algodConfig.port,
+ token: algodConfig.token,
+ })
+
+ const { enqueueSnackbar } = useSnackbar()
+
+ const { signer, activeAddress, signTransactions, sendTransactions } = useWallet()
+
+ const handleSubmitAlgo = async () => {
+ setLoading(true)
+
+ if (!signer || !activeAddress) {
+ enqueueSnackbar('Please connect wallet first', { variant: 'warning' })
+ return
+ }
+
+ const suggestedParams = await algodClient.getTransactionParams().do()
+
+ const transaction = algosdk.makePaymentTxnWithSuggestedParamsFromObject({
+ from: activeAddress,
+ to: receiverAddress,
+ amount: 1e6,
+ suggestedParams,
+ })
+
+ const encodedTransaction = algosdk.encodeUnsignedTransaction(transaction)
+
+ const signedTransactions = await signTransactions([encodedTransaction])
+
+ const waitRoundsToConfirm = 4
+
+ try {
+ enqueueSnackbar('Sending transaction...', { variant: 'info' })
+ const { id } = await sendTransactions(signedTransactions, waitRoundsToConfirm)
+ enqueueSnackbar(`Transaction sent: ${id}`, { variant: 'success' })
+ setReceiverAddress('')
+ } catch (e) {
+ enqueueSnackbar('Failed to send transaction', { variant: 'error' })
+ }
+
+ setLoading(false)
+ }
+
+ return (
+
+ )
+}
+
+export default Transact
diff --git a/examples/production_react/src/contracts/README.md b/examples/production_react/src/contracts/README.md
new file mode 100644
index 0000000..e056b58
--- /dev/null
+++ b/examples/production_react/src/contracts/README.md
@@ -0,0 +1,13 @@
+## How to connect my web app with Algorand smart contracts?
+
+The following folder is reserved for the Algorand Application Clients. The clients are used to interact with instances of Algorand Smart Contracts (ASC1s) deployed on-chain.
+
+To integrate this react frontend template with your smart contracts codebase, perform the following steps:
+
+1. Generate the typed client using `algokit generate client -l typescript -o {path/to/this/folder}`
+2. The generated typescript client should be ready to be imported and used in this react frontend template, making it a full fledged dApp.
+
+### FAQ
+
+- **How to interact with the smart contract?**
+ - The generated client provides a set of functions that can be used to interact with the ABI (Application Binary Interface) compliant Algorand smart contract. For example, if the smart contract has a function called `hello`, the generated client will have a function called `hello` that can be used to interact with the smart contract. Refer to a [full-stack end-to-end starter template](https://github.com/algorandfoundation/algokit-fullstack-template) for a reference example on invoking and interacting with typescript typed clients generated.
diff --git a/examples/production_react/src/interfaces/network.ts b/examples/production_react/src/interfaces/network.ts
new file mode 100644
index 0000000..a458edc
--- /dev/null
+++ b/examples/production_react/src/interfaces/network.ts
@@ -0,0 +1,26 @@
+import { AlgoClientConfig } from '@algorandfoundation/algokit-utils/types/network-client'
+import type { TokenHeader } from 'algosdk/dist/types/client/urlTokenBaseHTTPClient'
+
+export interface AlgoViteClientConfig extends AlgoClientConfig {
+ /** Base URL of the server e.g. http://localhost, https://testnet-api.algonode.cloud/, etc. */
+ server: string
+ /** The port to use e.g. 4001, 443, etc. */
+ port: string | number
+ /** The token to use for API authentication (or undefined if none needed) - can be a string, or an object with the header key => value */
+ token: string | TokenHeader
+ /** String representing current Algorand Network type (testnet/mainnet and etc) */
+ network: string
+}
+
+export interface AlgoViteKMDConfig extends AlgoClientConfig {
+ /** Base URL of the server e.g. http://localhost, https://testnet-api.algonode.cloud/, etc. */
+ server: string
+ /** The port to use e.g. 4001, 443, etc. */
+ port: string | number
+ /** The token to use for API authentication (or undefined if none needed) - can be a string, or an object with the header key => value */
+ token: string | TokenHeader
+ /** KMD wallet name */
+ wallet: string
+ /** KMD wallet password */
+ password: string
+}
diff --git a/examples/production_react/src/main.tsx b/examples/production_react/src/main.tsx
new file mode 100644
index 0000000..adf72ec
--- /dev/null
+++ b/examples/production_react/src/main.tsx
@@ -0,0 +1,13 @@
+import React from 'react'
+import ReactDOM from 'react-dom/client'
+import App from './App'
+import './styles/main.css'
+import ErrorBoundary from './components/ErrorBoundary'
+
+ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
+
+
+
+
+ ,
+)
diff --git a/examples/production_react/src/styles/main.css b/examples/production_react/src/styles/main.css
new file mode 100644
index 0000000..b5c61c9
--- /dev/null
+++ b/examples/production_react/src/styles/main.css
@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
diff --git a/examples/production_react/src/utils/ellipseAddress.spec.tsx b/examples/production_react/src/utils/ellipseAddress.spec.tsx
new file mode 100644
index 0000000..2cbff10
--- /dev/null
+++ b/examples/production_react/src/utils/ellipseAddress.spec.tsx
@@ -0,0 +1,15 @@
+import { ellipseAddress } from './ellipseAddress'
+
+describe('ellipseAddress', () => {
+ it('should return ellipsed address with specified width', () => {
+ const address = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
+ const result = ellipseAddress(address, 4)
+ expect(result).toBe('aaaa...aaaa')
+ })
+
+ it('should return empty string when address is empty', () => {
+ const address = ''
+ const result = ellipseAddress(address)
+ expect(result).toBe('')
+ })
+})
diff --git a/examples/production_react/src/utils/ellipseAddress.ts b/examples/production_react/src/utils/ellipseAddress.ts
new file mode 100644
index 0000000..542f46f
--- /dev/null
+++ b/examples/production_react/src/utils/ellipseAddress.ts
@@ -0,0 +1,3 @@
+export function ellipseAddress(address = ``, width = 6): string {
+ return address ? `${address.slice(0, width)}...${address.slice(-width)}` : address
+}
diff --git a/examples/production_react/src/utils/network/getAlgoClientConfigs.ts b/examples/production_react/src/utils/network/getAlgoClientConfigs.ts
new file mode 100644
index 0000000..b5121f8
--- /dev/null
+++ b/examples/production_react/src/utils/network/getAlgoClientConfigs.ts
@@ -0,0 +1,41 @@
+import { AlgoViteClientConfig, AlgoViteKMDConfig } from '../../interfaces/network'
+
+export function getAlgodConfigFromViteEnvironment(): AlgoViteClientConfig {
+ if (!import.meta.env.VITE_ALGOD_SERVER) {
+ throw new Error('Attempt to get default algod configuration without specifying VITE_ALGOD_SERVER in the environment variables')
+ }
+
+ return {
+ server: import.meta.env.VITE_ALGOD_SERVER,
+ port: import.meta.env.VITE_ALGOD_PORT,
+ token: import.meta.env.VITE_ALGOD_TOKEN,
+ network: import.meta.env.VITE_ALGOD_NETWORK,
+ }
+}
+
+export function getIndexerConfigFromViteEnvironment(): AlgoViteClientConfig {
+ if (!import.meta.env.VITE_INDEXER_SERVER) {
+ throw new Error('Attempt to get default algod configuration without specifying VITE_INDEXER_SERVER in the environment variables')
+ }
+
+ return {
+ server: import.meta.env.VITE_INDEXER_SERVER,
+ port: import.meta.env.VITE_INDEXER_PORT,
+ token: import.meta.env.VITE_INDEXER_TOKEN,
+ network: import.meta.env.VITE_ALGOD_NETWORK,
+ }
+}
+
+export function getKmdConfigFromViteEnvironment(): AlgoViteKMDConfig {
+ if (!import.meta.env.VITE_KMD_SERVER) {
+ throw new Error('Attempt to get default kmd configuration without specifying VITE_KMD_SERVER in the environment variables')
+ }
+
+ return {
+ server: import.meta.env.VITE_KMD_SERVER,
+ port: import.meta.env.VITE_KMD_PORT,
+ token: import.meta.env.VITE_KMD_TOKEN,
+ wallet: import.meta.env.VITE_KMD_WALLET,
+ password: import.meta.env.VITE_KMD_PASSWORD,
+ }
+}
diff --git a/examples/production_react/src/vite-env.d.ts b/examples/production_react/src/vite-env.d.ts
new file mode 100644
index 0000000..67c2d30
--- /dev/null
+++ b/examples/production_react/src/vite-env.d.ts
@@ -0,0 +1,24 @@
+///
+
+interface ImportMetaEnv {
+ readonly VITE_ENVIRONMENT: string
+
+ readonly VITE_ALGOD_TOKEN: string
+ readonly VITE_ALGOD_SERVER: string
+ readonly VITE_ALGOD_PORT: string
+ readonly VITE_ALGOD_NETWORK: string
+
+ readonly VITE_INDEXER_TOKEN: string
+ readonly VITE_INDEXER_SERVER: string
+ readonly VITE_INDEXER_PORT: string
+
+ readonly VITE_KMD_TOKEN: string
+ readonly VITE_KMD_SERVER: string
+ readonly VITE_KMD_PORT: string
+ readonly VITE_KMD_PASSWORD: string
+ readonly VITE_KMD_WALLET: string
+}
+
+interface ImportMeta {
+ readonly env: ImportMetaEnv
+}
diff --git a/examples/production_react/tailwind.config.js b/examples/production_react/tailwind.config.js
new file mode 100644
index 0000000..a9f7a95
--- /dev/null
+++ b/examples/production_react/tailwind.config.js
@@ -0,0 +1,11 @@
+/** @type {import('tailwindcss').Config} */
+module.exports = {
+ content: ['./src/**/*.{js,ts,jsx,tsx}'],
+ theme: {
+ extend: {},
+ },
+ daisyui: {
+ themes: ['lofi'],
+ },
+ plugins: [require('daisyui')],
+ }
diff --git a/examples/production_react/tests/example.spec.ts b/examples/production_react/tests/example.spec.ts
new file mode 100644
index 0000000..df83322
--- /dev/null
+++ b/examples/production_react/tests/example.spec.ts
@@ -0,0 +1,38 @@
+import { randomAccount } from '@algorandfoundation/algokit-utils'
+import { expect, test } from '@playwright/test'
+
+test.beforeEach(async ({ page }) => {
+ await page.goto('http://localhost:5173/')
+})
+
+test('has title', async ({ page }) => {
+ // Expect a title "to contain" a substring.
+ await expect(page).toHaveTitle('AlgoKit React Template')
+})
+
+test('get started link', async ({ page }) => {
+ await expect(page.getByTestId('getting-started')).toHaveText('Getting started')
+})
+
+test('authentication and dummy payment transaction', async ({ page }) => {
+ page.on('dialog', async (dialog) => {
+ dialog.message() === 'KMD password' ? await dialog.accept() : await dialog.dismiss()
+ })
+
+ // 1. Must be able to connect to a KMD wallet provider
+ await page.getByTestId('connect-wallet').click()
+ await page.getByTestId('kmd-connect').click()
+ await page.getByTestId('close-wallet-modal').click()
+
+ // 2. Must be able to send a dummy payment transaction
+ await page.getByTestId('transactions-demo').click()
+
+ const dummyAccount = randomAccount()
+ await page.getByTestId('receiver-address').fill(dummyAccount.addr)
+ await page.getByTestId('send-algo').click()
+
+ // 3. Must be able to see a notification that the transaction was sent
+ const notification = await page.getByText('Transaction sent:')
+ await notification.waitFor()
+ expect(notification).toBeTruthy()
+})
diff --git a/examples/production_react/tsconfig.json b/examples/production_react/tsconfig.json
new file mode 100644
index 0000000..5cde02a
--- /dev/null
+++ b/examples/production_react/tsconfig.json
@@ -0,0 +1,38 @@
+{
+ "compilerOptions": {
+ "target": "ES2020" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
+ "module": "ES2022" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
+ "declaration": true /* Generates corresponding '.d.ts' file. */,
+ "declarationMap": true /* Generates a sourcemap for each corresponding '.d.ts' file. */,
+ "sourceMap": true /* Generates corresponding '.map' file. */,
+ "strict": true /* Enable all strict type-checking options. */,
+ "noImplicitReturns": true /* Report error when not all code paths in function return a value. */,
+ "noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */,
+ "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
+ "experimentalDecorators": true /* Enables experimental support for ES7 decorators. */,
+ "emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */,
+ "skipLibCheck": true /* Skip type checking of declaration files. */,
+ "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */,
+ "allowJs": false,
+ "allowSyntheticDefaultImports": true,
+ "moduleResolution": "Node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+ "outDir": "./dist/"
+ },
+ "include": [
+ "src/**/*.ts",
+ "src/**/*.tsx",
+ "vite.config.js",
+ "src/utils/ellipseAddress.spec.tsx",
+ "src/utils/ellipseAddress.spec.tsx",
+ "src/main.tsx",
+ ],
+ "references": [
+ {
+ "path": "./tsconfig.node.json"
+ }
+ ]
+}
diff --git a/examples/production_react/tsconfig.node.json b/examples/production_react/tsconfig.node.json
new file mode 100644
index 0000000..9d31e2a
--- /dev/null
+++ b/examples/production_react/tsconfig.node.json
@@ -0,0 +1,9 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "module": "ESNext",
+ "moduleResolution": "Node",
+ "allowSyntheticDefaultImports": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/examples/production_react/vite.config.ts b/examples/production_react/vite.config.ts
new file mode 100644
index 0000000..36f7f4e
--- /dev/null
+++ b/examples/production_react/vite.config.ts
@@ -0,0 +1,7 @@
+import react from '@vitejs/plugin-react'
+import { defineConfig } from 'vite'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+})
diff --git a/examples/starter_react/.algokit.toml b/examples/starter_react/.algokit.toml
new file mode 100644
index 0000000..58fbbe7
--- /dev/null
+++ b/examples/starter_react/.algokit.toml
@@ -0,0 +1,10 @@
+[algokit]
+min_version = "v1.3.0b1"
+
+[generate.import_contract]
+description = "Import a typed client from your smart contracts project"
+path = ".algokit/generators/import_contract"
+
+[project]
+type = "frontend"
+name = "starter_react"
diff --git a/examples/starter_react/.copier-answers.yml b/examples/starter_react/.copier-answers.yml
new file mode 100644
index 0000000..e227958
--- /dev/null
+++ b/examples/starter_react/.copier-answers.yml
@@ -0,0 +1,8 @@
+# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY
+_commit:
+_src_path:
+author_email: None
+author_name: None
+preset_name: starter
+project_name: starter_react
+
diff --git a/examples/starter_react/.env.template b/examples/starter_react/.env.template
new file mode 100644
index 0000000..e05d499
--- /dev/null
+++ b/examples/starter_react/.env.template
@@ -0,0 +1,67 @@
+# ======================
+# LocalNet configuration
+# uncomment below to use
+# ======================
+
+VITE_ENVIRONMENT=local
+
+# Algod
+VITE_ALGOD_TOKEN=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+VITE_ALGOD_SERVER=http://localhost
+VITE_ALGOD_PORT=4001
+VITE_ALGOD_NETWORK=""
+
+# Indexer
+VITE_INDEXER_TOKEN=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+VITE_INDEXER_SERVER=http://localhost
+VITE_INDEXER_PORT=8980
+
+# KMD
+# Please note:
+# 1. This is only needed for LocalNet since
+# by default KMD provider is ignored on other networks.
+# 2. AlgoKit LocalNet starts with a single wallet called 'unencrypted-default-wallet',
+# with heaps of tokens available for testing.
+VITE_KMD_TOKEN=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+VITE_KMD_SERVER=http://localhost
+VITE_KMD_PORT=4002
+VITE_KMD_WALLET="unencrypted-default-wallet"
+VITE_KMD_PASSWORD=""
+
+# # ======================
+# # TestNet configuration:
+# # uncomment below to use
+# # ======================
+
+# VITE_ENVIRONMENT=local
+
+# # Algod
+# VITE_ALGOD_TOKEN=""
+# VITE_ALGOD_SERVER="https://testnet-api.algonode.cloud"
+# VITE_ALGOD_PORT=""
+# VITE_ALGOD_NETWORK="testnet"
+
+# # Indexer
+# VITE_INDEXER_TOKEN=""
+# VITE_INDEXER_SERVER="https://testnet-idx.algonode.cloud"
+# VITE_INDEXER_PORT=""
+
+
+# # ======================
+# # MainNet configuration:
+# # uncomment below to use
+# # ======================
+
+# VITE_ENVIRONMENT=production
+
+# # Algod
+# VITE_ALGOD_TOKEN=""
+# VITE_ALGOD_SERVER="https://mainnet-api.algonode.cloud"
+# VITE_ALGOD_PORT=""
+# VITE_ALGOD_NETWORK="mainnet"
+
+# # Indexer
+# VITE_INDEXER_TOKEN=""
+# VITE_INDEXER_SERVER="https://mainnet-idx.algonode.cloud"
+# VITE_INDEXER_PORT=""
+
diff --git a/examples/starter_react/.gitattributes b/examples/starter_react/.gitattributes
new file mode 100644
index 0000000..6313b56
--- /dev/null
+++ b/examples/starter_react/.gitattributes
@@ -0,0 +1 @@
+* text=auto eol=lf
diff --git a/examples/starter_react/.gitignore b/examples/starter_react/.gitignore
new file mode 100644
index 0000000..26dc019
--- /dev/null
+++ b/examples/starter_react/.gitignore
@@ -0,0 +1,35 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# production
+/build
+
+
+# dotenv environment variable files
+.env
+env/
+
+# misc
+/dist
+.DS_Store
+
+
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+/test-results/
+/playwright-report/
+/playwright/.cache/
+
+# PyCharm
+.idea
+!.idea/
+.idea/*
+!.idea/runConfigurations/
diff --git a/examples/starter_react/.vscode/extensions.json b/examples/starter_react/.vscode/extensions.json
new file mode 100644
index 0000000..6d0554a
--- /dev/null
+++ b/examples/starter_react/.vscode/extensions.json
@@ -0,0 +1,7 @@
+{
+ "recommendations": [
+ "EditorConfig.EditorConfig",
+ "dotenv.dotenv-vscode",
+ ]
+}
+
diff --git a/examples/starter_react/.vscode/launch.json b/examples/starter_react/.vscode/launch.json
new file mode 100644
index 0000000..7edaf04
--- /dev/null
+++ b/examples/starter_react/.vscode/launch.json
@@ -0,0 +1,68 @@
+{
+ "configurations": [
+ {
+ "type": "msedge",
+ "request": "launch",
+ "name": "Run (Edge)",
+ "url": "http://localhost:5173",
+ "webRoot": "${workspaceFolder}",
+ "presentation": {
+ "hidden": false,
+ "group": "2. Web"
+ }
+ },
+ {
+ "type": "chrome",
+ "request": "launch",
+ "name": "Run (Chrome)",
+ "url": "http://localhost:5173",
+ "webRoot": "${workspaceFolder}",
+ "presentation": {
+ "hidden": false,
+ "group": "2. Web"
+ }
+ },
+ {
+ "type": "firefox",
+ "request": "launch",
+ "name": "Run (Firefox)",
+ "url": "http://localhost:5173",
+ "webRoot": "${workspaceFolder}",
+ "presentation": {
+ "hidden": false,
+ "group": "2. Web"
+ }
+ },
+ {
+ "name": "Run dApp",
+ "type": "node",
+ "request": "launch",
+ "runtimeExecutable": "npm",
+ "runtimeArgs": ["run", "dev"],
+ "cwd": "${workspaceRoot}",
+ "console": "integratedTerminal",
+ "skipFiles": ["/**", "node_modules/**"],
+ "presentation": {
+ "hidden": false,
+ "group": "1. Run Project",
+ "order": 1
+ }
+ },
+ {
+ "name": "Run dApp (+ LocalNet)",
+ "type": "node",
+ "request": "launch",
+ "runtimeExecutable": "npm",
+ "runtimeArgs": ["run", "dev"],
+ "cwd": "${workspaceRoot}",
+ "console": "integratedTerminal",
+ "skipFiles": ["/**", "node_modules/**"],
+ "preLaunchTask": "Start AlgoKit LocalNet",
+ "presentation": {
+ "hidden": false,
+ "group": "1. Run Project",
+ "order": 1
+ }
+ }
+ ]
+}
diff --git a/examples/starter_react/.vscode/settings.json b/examples/starter_react/.vscode/settings.json
new file mode 100644
index 0000000..f34d28b
--- /dev/null
+++ b/examples/starter_react/.vscode/settings.json
@@ -0,0 +1,6 @@
+{
+ "editor.formatOnSave": true,
+
+ "dotenv.enableAutocloaking": false,
+
+}
diff --git a/examples/starter_react/.vscode/tasks.json b/examples/starter_react/.vscode/tasks.json
new file mode 100644
index 0000000..d611c4f
--- /dev/null
+++ b/examples/starter_react/.vscode/tasks.json
@@ -0,0 +1,15 @@
+{
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "Start AlgoKit LocalNet",
+ "command": "algokit",
+ "args": ["localnet", "start"],
+ "type": "shell",
+ "options": {
+ "cwd": "${workspaceFolder}"
+ },
+ "problemMatcher": []
+ }
+ ]
+}
diff --git a/examples/starter_react/LICENSE b/examples/starter_react/LICENSE
new file mode 100644
index 0000000..b39bcd6
--- /dev/null
+++ b/examples/starter_react/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2023 Algorand Foundation
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/tests_generated/test_all_default_parameters_jetbrains/README.md b/examples/starter_react/README.md
similarity index 95%
rename from tests_generated/test_all_default_parameters_jetbrains/README.md
rename to examples/starter_react/README.md
index 83235a8..ac13881 100644
--- a/tests_generated/test_all_default_parameters_jetbrains/README.md
+++ b/examples/starter_react/README.md
@@ -1,4 +1,4 @@
-# test_all_default_parameters_jetbrains
+# starter_react
This starter React project has been generated using AlgoKit. See below for default getting started instructions.
@@ -52,6 +52,7 @@ This project makes use of React and Tailwind to provider a base project configur
- [React](https://reactjs.org/) - A JavaScript library for building user interfaces.
- [use-wallet](https://github.com/txnlab/use-wallet) - A React hook for connecting to an Algorand wallet providers.
- [npm](https://www.npmjs.com/): Node.js package manager
+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.
# Integrating with smart contracts and application clients
Refer to the detailed guidance on [integrating with smart contracts and application clients](./src/contracts/README.md). In essence, for any smart contract codebase generated with AlgoKit or other tools that produce compile contracts into ARC34 compliant app specifications, you can use the `algokit generate` command to generate TypeScript or Python typed client. Once generated simply drag and drop the generated client into `./src/contracts` and import it into your React components as you see fit.
diff --git a/examples/starter_react/index.html b/examples/starter_react/index.html
new file mode 100644
index 0000000..a85566a
--- /dev/null
+++ b/examples/starter_react/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+ AlgoKit React Template
+
+
+
+
+
+
+
diff --git a/tests_generated/test_all_default_parameters_off/package.json b/examples/starter_react/package.json
similarity index 96%
rename from tests_generated/test_all_default_parameters_off/package.json
rename to examples/starter_react/package.json
index 31d2a7d..dc25421 100644
--- a/tests_generated/test_all_default_parameters_off/package.json
+++ b/examples/starter_react/package.json
@@ -1,5 +1,5 @@
{
- "name": "test_all_default_parameters_off",
+ "name": "starter_react",
"version": "0.1.0",
"author": {
"name": "None",
diff --git a/examples/starter_react/public/index.html b/examples/starter_react/public/index.html
new file mode 100644
index 0000000..0d3a3a5
--- /dev/null
+++ b/examples/starter_react/public/index.html
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+ React App
+
+
+
+
+
+
+
diff --git a/examples/starter_react/public/robots.txt b/examples/starter_react/public/robots.txt
new file mode 100644
index 0000000..e9e57dc
--- /dev/null
+++ b/examples/starter_react/public/robots.txt
@@ -0,0 +1,3 @@
+# https://www.robotstxt.org/robotstxt.html
+User-agent: *
+Disallow:
diff --git a/examples/starter_react/src/App.tsx b/examples/starter_react/src/App.tsx
new file mode 100644
index 0000000..58feddf
--- /dev/null
+++ b/examples/starter_react/src/App.tsx
@@ -0,0 +1,57 @@
+import { DeflyWalletConnect } from '@blockshake/defly-connect'
+import { DaffiWalletConnect } from '@daffiwallet/connect'
+import { PeraWalletConnect } from '@perawallet/connect'
+import { PROVIDER_ID, ProvidersArray, WalletProvider, useInitializeProviders } from '@txnlab/use-wallet'
+import algosdk from 'algosdk'
+import { SnackbarProvider } from 'notistack'
+import Home from './Home'
+import { getAlgodConfigFromViteEnvironment, getKmdConfigFromViteEnvironment } from './utils/network/getAlgoClientConfigs'
+
+let providersArray: ProvidersArray
+if (import.meta.env.VITE_ALGOD_NETWORK === '') {
+ const kmdConfig = getKmdConfigFromViteEnvironment()
+ providersArray = [
+ {
+ id: PROVIDER_ID.KMD,
+ clientOptions: {
+ wallet: kmdConfig.wallet,
+ password: kmdConfig.password,
+ host: kmdConfig.server,
+ token: String(kmdConfig.token),
+ port: String(kmdConfig.port),
+ },
+ },
+ ]
+} else {
+ providersArray = [
+ { id: PROVIDER_ID.DEFLY, clientStatic: DeflyWalletConnect },
+ { id: PROVIDER_ID.PERA, clientStatic: PeraWalletConnect },
+ { id: PROVIDER_ID.DAFFI, clientStatic: DaffiWalletConnect },
+ { id: PROVIDER_ID.EXODUS },
+ // If you are interested in WalletConnect v2 provider
+ // refer to https://github.com/TxnLab/use-wallet for detailed integration instructions
+ ]
+}
+
+export default function App() {
+ const algodConfig = getAlgodConfigFromViteEnvironment()
+
+ const walletProviders = useInitializeProviders({
+ providers: providersArray,
+ nodeConfig: {
+ network: algodConfig.network,
+ nodeServer: algodConfig.server,
+ nodePort: String(algodConfig.port),
+ nodeToken: String(algodConfig.token),
+ },
+ algosdkStatic: algosdk,
+ })
+
+ return (
+
+
+
+
+
+ )
+}
diff --git a/examples/starter_react/src/Home.tsx b/examples/starter_react/src/Home.tsx
new file mode 100644
index 0000000..42128d8
--- /dev/null
+++ b/examples/starter_react/src/Home.tsx
@@ -0,0 +1,63 @@
+// src/components/Home.tsx
+import { useWallet } from '@txnlab/use-wallet'
+import React, { useState } from 'react'
+import ConnectWallet from './components/ConnectWallet'
+import Transact from './components/Transact'
+
+interface HomeProps {}
+
+const Home: React.FC = () => {
+ const [openWalletModal, setOpenWalletModal] = useState(false)
+ const [openDemoModal, setOpenDemoModal] = useState(false)
+ const { activeAddress } = useWallet()
+
+ const toggleWalletModal = () => {
+ setOpenWalletModal(!openWalletModal)
+ }
+
+ const toggleDemoModal = () => {
+ setOpenDemoModal(!openDemoModal)
+ }
+
+ return (
+
+
+
+
+ Welcome to
AlgoKit 🙂
+
+
+ This starter has been generated using official AlgoKit React template. Refer to the resource below for next steps.
+
+
+
+
+ Getting started
+
+
+
+
+
+ {activeAddress && (
+
+ )}
+
+
+
+
+
+
+
+ )
+}
+
+export default Home
diff --git a/examples/starter_react/src/assets/logo.svg b/examples/starter_react/src/assets/logo.svg
new file mode 100644
index 0000000..7169476
--- /dev/null
+++ b/examples/starter_react/src/assets/logo.svg
@@ -0,0 +1 @@
+
diff --git a/examples/starter_react/src/components/Account.tsx b/examples/starter_react/src/components/Account.tsx
new file mode 100644
index 0000000..6a6345e
--- /dev/null
+++ b/examples/starter_react/src/components/Account.tsx
@@ -0,0 +1,28 @@
+import { useWallet } from '@txnlab/use-wallet'
+import { useMemo } from 'react'
+import { ellipseAddress } from '../utils/ellipseAddress'
+import { getAlgodConfigFromViteEnvironment } from '../utils/network/getAlgoClientConfigs'
+
+const Account = () => {
+ const { activeAddress } = useWallet()
+ const algoConfig = getAlgodConfigFromViteEnvironment()
+
+ const dappFlowNetworkName = useMemo(() => {
+ return algoConfig.network === '' ? 'sandbox' : algoConfig.network.toLocaleLowerCase()
+ }, [algoConfig.network])
+
+ return (
+
+ )
+}
+
+export default Account
diff --git a/tests_generated/test_all_default_parameters_jetbrains/src/components/ConnectWallet.tsx b/examples/starter_react/src/components/ConnectWallet.tsx
similarity index 100%
rename from tests_generated/test_all_default_parameters_jetbrains/src/components/ConnectWallet.tsx
rename to examples/starter_react/src/components/ConnectWallet.tsx
diff --git a/examples/starter_react/src/components/ErrorBoundary.tsx b/examples/starter_react/src/components/ErrorBoundary.tsx
new file mode 100644
index 0000000..435bf61
--- /dev/null
+++ b/examples/starter_react/src/components/ErrorBoundary.tsx
@@ -0,0 +1,46 @@
+import React, { ReactNode } from 'react'
+
+interface ErrorBoundaryProps {
+ children: ReactNode
+}
+
+interface ErrorBoundaryState {
+ hasError: boolean
+ error: Error | null
+}
+
+class ErrorBoundary extends React.Component {
+ constructor(props: ErrorBoundaryProps) {
+ super(props)
+ this.state = { hasError: false, error: null }
+ }
+
+ static getDerivedStateFromError(error: Error): ErrorBoundaryState {
+ // Update state so the next render will show the fallback UI.
+ return { hasError: true, error: error }
+ }
+
+ render(): ReactNode {
+ if (this.state.hasError) {
+ // You can render any custom fallback UI
+ return (
+
+
+
+
Error occured
+
+ {this.state.error?.message.includes('Attempt to get default algod configuration')
+ ? 'Please make sure to set up your environment variables correctly. Create a .env file based on .env.template and fill in the required values. This controls the network and credentials for connections with Algod and Indexer.'
+ : this.state.error?.message}
+
+
+
+
+ )
+ }
+
+ return this.props.children
+ }
+}
+
+export default ErrorBoundary
diff --git a/tests_generated/test_all_default_parameters_jetbrains/src/components/Transact.tsx b/examples/starter_react/src/components/Transact.tsx
similarity index 100%
rename from tests_generated/test_all_default_parameters_jetbrains/src/components/Transact.tsx
rename to examples/starter_react/src/components/Transact.tsx
diff --git a/examples/starter_react/src/contracts/README.md b/examples/starter_react/src/contracts/README.md
new file mode 100644
index 0000000..e056b58
--- /dev/null
+++ b/examples/starter_react/src/contracts/README.md
@@ -0,0 +1,13 @@
+## How to connect my web app with Algorand smart contracts?
+
+The following folder is reserved for the Algorand Application Clients. The clients are used to interact with instances of Algorand Smart Contracts (ASC1s) deployed on-chain.
+
+To integrate this react frontend template with your smart contracts codebase, perform the following steps:
+
+1. Generate the typed client using `algokit generate client -l typescript -o {path/to/this/folder}`
+2. The generated typescript client should be ready to be imported and used in this react frontend template, making it a full fledged dApp.
+
+### FAQ
+
+- **How to interact with the smart contract?**
+ - The generated client provides a set of functions that can be used to interact with the ABI (Application Binary Interface) compliant Algorand smart contract. For example, if the smart contract has a function called `hello`, the generated client will have a function called `hello` that can be used to interact with the smart contract. Refer to a [full-stack end-to-end starter template](https://github.com/algorandfoundation/algokit-fullstack-template) for a reference example on invoking and interacting with typescript typed clients generated.
diff --git a/examples/starter_react/src/interfaces/network.ts b/examples/starter_react/src/interfaces/network.ts
new file mode 100644
index 0000000..a458edc
--- /dev/null
+++ b/examples/starter_react/src/interfaces/network.ts
@@ -0,0 +1,26 @@
+import { AlgoClientConfig } from '@algorandfoundation/algokit-utils/types/network-client'
+import type { TokenHeader } from 'algosdk/dist/types/client/urlTokenBaseHTTPClient'
+
+export interface AlgoViteClientConfig extends AlgoClientConfig {
+ /** Base URL of the server e.g. http://localhost, https://testnet-api.algonode.cloud/, etc. */
+ server: string
+ /** The port to use e.g. 4001, 443, etc. */
+ port: string | number
+ /** The token to use for API authentication (or undefined if none needed) - can be a string, or an object with the header key => value */
+ token: string | TokenHeader
+ /** String representing current Algorand Network type (testnet/mainnet and etc) */
+ network: string
+}
+
+export interface AlgoViteKMDConfig extends AlgoClientConfig {
+ /** Base URL of the server e.g. http://localhost, https://testnet-api.algonode.cloud/, etc. */
+ server: string
+ /** The port to use e.g. 4001, 443, etc. */
+ port: string | number
+ /** The token to use for API authentication (or undefined if none needed) - can be a string, or an object with the header key => value */
+ token: string | TokenHeader
+ /** KMD wallet name */
+ wallet: string
+ /** KMD wallet password */
+ password: string
+}
diff --git a/tests_generated/test_all_default_parameters_jetbrains/src/main.tsx b/examples/starter_react/src/main.tsx
similarity index 100%
rename from tests_generated/test_all_default_parameters_jetbrains/src/main.tsx
rename to examples/starter_react/src/main.tsx
diff --git a/tests_generated/test_all_default_parameters_jetbrains/src/styles/App.css b/examples/starter_react/src/styles/App.css
similarity index 100%
rename from tests_generated/test_all_default_parameters_jetbrains/src/styles/App.css
rename to examples/starter_react/src/styles/App.css
diff --git a/examples/starter_react/src/utils/ellipseAddress.ts b/examples/starter_react/src/utils/ellipseAddress.ts
new file mode 100644
index 0000000..542f46f
--- /dev/null
+++ b/examples/starter_react/src/utils/ellipseAddress.ts
@@ -0,0 +1,3 @@
+export function ellipseAddress(address = ``, width = 6): string {
+ return address ? `${address.slice(0, width)}...${address.slice(-width)}` : address
+}
diff --git a/examples/starter_react/src/utils/network/getAlgoClientConfigs.ts b/examples/starter_react/src/utils/network/getAlgoClientConfigs.ts
new file mode 100644
index 0000000..b5121f8
--- /dev/null
+++ b/examples/starter_react/src/utils/network/getAlgoClientConfigs.ts
@@ -0,0 +1,41 @@
+import { AlgoViteClientConfig, AlgoViteKMDConfig } from '../../interfaces/network'
+
+export function getAlgodConfigFromViteEnvironment(): AlgoViteClientConfig {
+ if (!import.meta.env.VITE_ALGOD_SERVER) {
+ throw new Error('Attempt to get default algod configuration without specifying VITE_ALGOD_SERVER in the environment variables')
+ }
+
+ return {
+ server: import.meta.env.VITE_ALGOD_SERVER,
+ port: import.meta.env.VITE_ALGOD_PORT,
+ token: import.meta.env.VITE_ALGOD_TOKEN,
+ network: import.meta.env.VITE_ALGOD_NETWORK,
+ }
+}
+
+export function getIndexerConfigFromViteEnvironment(): AlgoViteClientConfig {
+ if (!import.meta.env.VITE_INDEXER_SERVER) {
+ throw new Error('Attempt to get default algod configuration without specifying VITE_INDEXER_SERVER in the environment variables')
+ }
+
+ return {
+ server: import.meta.env.VITE_INDEXER_SERVER,
+ port: import.meta.env.VITE_INDEXER_PORT,
+ token: import.meta.env.VITE_INDEXER_TOKEN,
+ network: import.meta.env.VITE_ALGOD_NETWORK,
+ }
+}
+
+export function getKmdConfigFromViteEnvironment(): AlgoViteKMDConfig {
+ if (!import.meta.env.VITE_KMD_SERVER) {
+ throw new Error('Attempt to get default kmd configuration without specifying VITE_KMD_SERVER in the environment variables')
+ }
+
+ return {
+ server: import.meta.env.VITE_KMD_SERVER,
+ port: import.meta.env.VITE_KMD_PORT,
+ token: import.meta.env.VITE_KMD_TOKEN,
+ wallet: import.meta.env.VITE_KMD_WALLET,
+ password: import.meta.env.VITE_KMD_PASSWORD,
+ }
+}
diff --git a/examples/starter_react/src/vite-env.d.ts b/examples/starter_react/src/vite-env.d.ts
new file mode 100644
index 0000000..67c2d30
--- /dev/null
+++ b/examples/starter_react/src/vite-env.d.ts
@@ -0,0 +1,24 @@
+///
+
+interface ImportMetaEnv {
+ readonly VITE_ENVIRONMENT: string
+
+ readonly VITE_ALGOD_TOKEN: string
+ readonly VITE_ALGOD_SERVER: string
+ readonly VITE_ALGOD_PORT: string
+ readonly VITE_ALGOD_NETWORK: string
+
+ readonly VITE_INDEXER_TOKEN: string
+ readonly VITE_INDEXER_SERVER: string
+ readonly VITE_INDEXER_PORT: string
+
+ readonly VITE_KMD_TOKEN: string
+ readonly VITE_KMD_SERVER: string
+ readonly VITE_KMD_PORT: string
+ readonly VITE_KMD_PASSWORD: string
+ readonly VITE_KMD_WALLET: string
+}
+
+interface ImportMeta {
+ readonly env: ImportMetaEnv
+}
diff --git a/tests_generated/test_all_default_parameters_jetbrains/tsconfig.json b/examples/starter_react/tsconfig.json
similarity index 100%
rename from tests_generated/test_all_default_parameters_jetbrains/tsconfig.json
rename to examples/starter_react/tsconfig.json
diff --git a/examples/starter_react/tsconfig.node.json b/examples/starter_react/tsconfig.node.json
new file mode 100644
index 0000000..9d31e2a
--- /dev/null
+++ b/examples/starter_react/tsconfig.node.json
@@ -0,0 +1,9 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "module": "ESNext",
+ "moduleResolution": "Node",
+ "allowSyntheticDefaultImports": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/examples/starter_react/vite.config.ts b/examples/starter_react/vite.config.ts
new file mode 100644
index 0000000..36f7f4e
--- /dev/null
+++ b/examples/starter_react/vite.config.ts
@@ -0,0 +1,7 @@
+import react from '@vitejs/plugin-react'
+import { defineConfig } from 'vite'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+})
diff --git a/poetry.lock b/poetry.lock
index eae34f3..1ecebdb 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,112 +1,100 @@
-# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
+# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
[[package]]
name = "aiohttp"
-version = "3.8.6"
+version = "3.9.3"
description = "Async http client/server framework (asyncio)"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.8"
files = [
- {file = "aiohttp-3.8.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:41d55fc043954cddbbd82503d9cc3f4814a40bcef30b3569bc7b5e34130718c1"},
- {file = "aiohttp-3.8.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1d84166673694841d8953f0a8d0c90e1087739d24632fe86b1a08819168b4566"},
- {file = "aiohttp-3.8.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:253bf92b744b3170eb4c4ca2fa58f9c4b87aeb1df42f71d4e78815e6e8b73c9e"},
- {file = "aiohttp-3.8.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3fd194939b1f764d6bb05490987bfe104287bbf51b8d862261ccf66f48fb4096"},
- {file = "aiohttp-3.8.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6c5f938d199a6fdbdc10bbb9447496561c3a9a565b43be564648d81e1102ac22"},
- {file = "aiohttp-3.8.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2817b2f66ca82ee699acd90e05c95e79bbf1dc986abb62b61ec8aaf851e81c93"},
- {file = "aiohttp-3.8.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0fa375b3d34e71ccccf172cab401cd94a72de7a8cc01847a7b3386204093bb47"},
- {file = "aiohttp-3.8.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9de50a199b7710fa2904be5a4a9b51af587ab24c8e540a7243ab737b45844543"},
- {file = "aiohttp-3.8.6-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e1d8cb0b56b3587c5c01de3bf2f600f186da7e7b5f7353d1bf26a8ddca57f965"},
- {file = "aiohttp-3.8.6-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8e31e9db1bee8b4f407b77fd2507337a0a80665ad7b6c749d08df595d88f1cf5"},
- {file = "aiohttp-3.8.6-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7bc88fc494b1f0311d67f29fee6fd636606f4697e8cc793a2d912ac5b19aa38d"},
- {file = "aiohttp-3.8.6-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ec00c3305788e04bf6d29d42e504560e159ccaf0be30c09203b468a6c1ccd3b2"},
- {file = "aiohttp-3.8.6-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ad1407db8f2f49329729564f71685557157bfa42b48f4b93e53721a16eb813ed"},
- {file = "aiohttp-3.8.6-cp310-cp310-win32.whl", hash = "sha256:ccc360e87341ad47c777f5723f68adbb52b37ab450c8bc3ca9ca1f3e849e5fe2"},
- {file = "aiohttp-3.8.6-cp310-cp310-win_amd64.whl", hash = "sha256:93c15c8e48e5e7b89d5cb4613479d144fda8344e2d886cf694fd36db4cc86865"},
- {file = "aiohttp-3.8.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6e2f9cc8e5328f829f6e1fb74a0a3a939b14e67e80832975e01929e320386b34"},
- {file = "aiohttp-3.8.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e6a00ffcc173e765e200ceefb06399ba09c06db97f401f920513a10c803604ca"},
- {file = "aiohttp-3.8.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:41bdc2ba359032e36c0e9de5a3bd00d6fb7ea558a6ce6b70acedf0da86458321"},
- {file = "aiohttp-3.8.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14cd52ccf40006c7a6cd34a0f8663734e5363fd981807173faf3a017e202fec9"},
- {file = "aiohttp-3.8.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2d5b785c792802e7b275c420d84f3397668e9d49ab1cb52bd916b3b3ffcf09ad"},
- {file = "aiohttp-3.8.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1bed815f3dc3d915c5c1e556c397c8667826fbc1b935d95b0ad680787896a358"},
- {file = "aiohttp-3.8.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96603a562b546632441926cd1293cfcb5b69f0b4159e6077f7c7dbdfb686af4d"},
- {file = "aiohttp-3.8.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d76e8b13161a202d14c9584590c4df4d068c9567c99506497bdd67eaedf36403"},
- {file = "aiohttp-3.8.6-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e3f1e3f1a1751bb62b4a1b7f4e435afcdade6c17a4fd9b9d43607cebd242924a"},
- {file = "aiohttp-3.8.6-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:76b36b3124f0223903609944a3c8bf28a599b2cc0ce0be60b45211c8e9be97f8"},
- {file = "aiohttp-3.8.6-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:a2ece4af1f3c967a4390c284797ab595a9f1bc1130ef8b01828915a05a6ae684"},
- {file = "aiohttp-3.8.6-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:16d330b3b9db87c3883e565340d292638a878236418b23cc8b9b11a054aaa887"},
- {file = "aiohttp-3.8.6-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:42c89579f82e49db436b69c938ab3e1559e5a4409eb8639eb4143989bc390f2f"},
- {file = "aiohttp-3.8.6-cp311-cp311-win32.whl", hash = "sha256:efd2fcf7e7b9d7ab16e6b7d54205beded0a9c8566cb30f09c1abe42b4e22bdcb"},
- {file = "aiohttp-3.8.6-cp311-cp311-win_amd64.whl", hash = "sha256:3b2ab182fc28e7a81f6c70bfbd829045d9480063f5ab06f6e601a3eddbbd49a0"},
- {file = "aiohttp-3.8.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:fdee8405931b0615220e5ddf8cd7edd8592c606a8e4ca2a00704883c396e4479"},
- {file = "aiohttp-3.8.6-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d25036d161c4fe2225d1abff2bd52c34ed0b1099f02c208cd34d8c05729882f0"},
- {file = "aiohttp-3.8.6-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d791245a894be071d5ab04bbb4850534261a7d4fd363b094a7b9963e8cdbd31"},
- {file = "aiohttp-3.8.6-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0cccd1de239afa866e4ce5c789b3032442f19c261c7d8a01183fd956b1935349"},
- {file = "aiohttp-3.8.6-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f13f60d78224f0dace220d8ab4ef1dbc37115eeeab8c06804fec11bec2bbd07"},
- {file = "aiohttp-3.8.6-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8a9b5a0606faca4f6cc0d338359d6fa137104c337f489cd135bb7fbdbccb1e39"},
- {file = "aiohttp-3.8.6-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:13da35c9ceb847732bf5c6c5781dcf4780e14392e5d3b3c689f6d22f8e15ae31"},
- {file = "aiohttp-3.8.6-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:4d4cbe4ffa9d05f46a28252efc5941e0462792930caa370a6efaf491f412bc66"},
- {file = "aiohttp-3.8.6-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:229852e147f44da0241954fc6cb910ba074e597f06789c867cb7fb0621e0ba7a"},
- {file = "aiohttp-3.8.6-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:713103a8bdde61d13490adf47171a1039fd880113981e55401a0f7b42c37d071"},
- {file = "aiohttp-3.8.6-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:45ad816b2c8e3b60b510f30dbd37fe74fd4a772248a52bb021f6fd65dff809b6"},
- {file = "aiohttp-3.8.6-cp36-cp36m-win32.whl", hash = "sha256:2b8d4e166e600dcfbff51919c7a3789ff6ca8b3ecce16e1d9c96d95dd569eb4c"},
- {file = "aiohttp-3.8.6-cp36-cp36m-win_amd64.whl", hash = "sha256:0912ed87fee967940aacc5306d3aa8ba3a459fcd12add0b407081fbefc931e53"},
- {file = "aiohttp-3.8.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e2a988a0c673c2e12084f5e6ba3392d76c75ddb8ebc6c7e9ead68248101cd446"},
- {file = "aiohttp-3.8.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebf3fd9f141700b510d4b190094db0ce37ac6361a6806c153c161dc6c041ccda"},
- {file = "aiohttp-3.8.6-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3161ce82ab85acd267c8f4b14aa226047a6bee1e4e6adb74b798bd42c6ae1f80"},
- {file = "aiohttp-3.8.6-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d95fc1bf33a9a81469aa760617b5971331cdd74370d1214f0b3109272c0e1e3c"},
- {file = "aiohttp-3.8.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c43ecfef7deaf0617cee936836518e7424ee12cb709883f2c9a1adda63cc460"},
- {file = "aiohttp-3.8.6-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca80e1b90a05a4f476547f904992ae81eda5c2c85c66ee4195bb8f9c5fb47f28"},
- {file = "aiohttp-3.8.6-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:90c72ebb7cb3a08a7f40061079817133f502a160561d0675b0a6adf231382c92"},
- {file = "aiohttp-3.8.6-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bb54c54510e47a8c7c8e63454a6acc817519337b2b78606c4e840871a3e15349"},
- {file = "aiohttp-3.8.6-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:de6a1c9f6803b90e20869e6b99c2c18cef5cc691363954c93cb9adeb26d9f3ae"},
- {file = "aiohttp-3.8.6-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:a3628b6c7b880b181a3ae0a0683698513874df63783fd89de99b7b7539e3e8a8"},
- {file = "aiohttp-3.8.6-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:fc37e9aef10a696a5a4474802930079ccfc14d9f9c10b4662169671ff034b7df"},
- {file = "aiohttp-3.8.6-cp37-cp37m-win32.whl", hash = "sha256:f8ef51e459eb2ad8e7a66c1d6440c808485840ad55ecc3cafefadea47d1b1ba2"},
- {file = "aiohttp-3.8.6-cp37-cp37m-win_amd64.whl", hash = "sha256:b2fe42e523be344124c6c8ef32a011444e869dc5f883c591ed87f84339de5976"},
- {file = "aiohttp-3.8.6-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9e2ee0ac5a1f5c7dd3197de309adfb99ac4617ff02b0603fd1e65b07dc772e4b"},
- {file = "aiohttp-3.8.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:01770d8c04bd8db568abb636c1fdd4f7140b284b8b3e0b4584f070180c1e5c62"},
- {file = "aiohttp-3.8.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3c68330a59506254b556b99a91857428cab98b2f84061260a67865f7f52899f5"},
- {file = "aiohttp-3.8.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89341b2c19fb5eac30c341133ae2cc3544d40d9b1892749cdd25892bbc6ac951"},
- {file = "aiohttp-3.8.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:71783b0b6455ac8f34b5ec99d83e686892c50498d5d00b8e56d47f41b38fbe04"},
- {file = "aiohttp-3.8.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f628dbf3c91e12f4d6c8b3f092069567d8eb17814aebba3d7d60c149391aee3a"},
- {file = "aiohttp-3.8.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b04691bc6601ef47c88f0255043df6f570ada1a9ebef99c34bd0b72866c217ae"},
- {file = "aiohttp-3.8.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ee912f7e78287516df155f69da575a0ba33b02dd7c1d6614dbc9463f43066e3"},
- {file = "aiohttp-3.8.6-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9c19b26acdd08dd239e0d3669a3dddafd600902e37881f13fbd8a53943079dbc"},
- {file = "aiohttp-3.8.6-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:99c5ac4ad492b4a19fc132306cd57075c28446ec2ed970973bbf036bcda1bcc6"},
- {file = "aiohttp-3.8.6-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:f0f03211fd14a6a0aed2997d4b1c013d49fb7b50eeb9ffdf5e51f23cfe2c77fa"},
- {file = "aiohttp-3.8.6-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:8d399dade330c53b4106160f75f55407e9ae7505263ea86f2ccca6bfcbdb4921"},
- {file = "aiohttp-3.8.6-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ec4fd86658c6a8964d75426517dc01cbf840bbf32d055ce64a9e63a40fd7b771"},
- {file = "aiohttp-3.8.6-cp38-cp38-win32.whl", hash = "sha256:33164093be11fcef3ce2571a0dccd9041c9a93fa3bde86569d7b03120d276c6f"},
- {file = "aiohttp-3.8.6-cp38-cp38-win_amd64.whl", hash = "sha256:bdf70bfe5a1414ba9afb9d49f0c912dc524cf60141102f3a11143ba3d291870f"},
- {file = "aiohttp-3.8.6-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d52d5dc7c6682b720280f9d9db41d36ebe4791622c842e258c9206232251ab2b"},
- {file = "aiohttp-3.8.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4ac39027011414dbd3d87f7edb31680e1f430834c8cef029f11c66dad0670aa5"},
- {file = "aiohttp-3.8.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3f5c7ce535a1d2429a634310e308fb7d718905487257060e5d4598e29dc17f0b"},
- {file = "aiohttp-3.8.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b30e963f9e0d52c28f284d554a9469af073030030cef8693106d918b2ca92f54"},
- {file = "aiohttp-3.8.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:918810ef188f84152af6b938254911055a72e0f935b5fbc4c1a4ed0b0584aed1"},
- {file = "aiohttp-3.8.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:002f23e6ea8d3dd8d149e569fd580c999232b5fbc601c48d55398fbc2e582e8c"},
- {file = "aiohttp-3.8.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4fcf3eabd3fd1a5e6092d1242295fa37d0354b2eb2077e6eb670accad78e40e1"},
- {file = "aiohttp-3.8.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:255ba9d6d5ff1a382bb9a578cd563605aa69bec845680e21c44afc2670607a95"},
- {file = "aiohttp-3.8.6-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d67f8baed00870aa390ea2590798766256f31dc5ed3ecc737debb6e97e2ede78"},
- {file = "aiohttp-3.8.6-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:86f20cee0f0a317c76573b627b954c412ea766d6ada1a9fcf1b805763ae7feeb"},
- {file = "aiohttp-3.8.6-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:39a312d0e991690ccc1a61f1e9e42daa519dcc34ad03eb6f826d94c1190190dd"},
- {file = "aiohttp-3.8.6-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e827d48cf802de06d9c935088c2924e3c7e7533377d66b6f31ed175c1620e05e"},
- {file = "aiohttp-3.8.6-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bd111d7fc5591ddf377a408ed9067045259ff2770f37e2d94e6478d0f3fc0c17"},
- {file = "aiohttp-3.8.6-cp39-cp39-win32.whl", hash = "sha256:caf486ac1e689dda3502567eb89ffe02876546599bbf915ec94b1fa424eeffd4"},
- {file = "aiohttp-3.8.6-cp39-cp39-win_amd64.whl", hash = "sha256:3f0e27e5b733803333bb2371249f41cf42bae8884863e8e8965ec69bebe53132"},
- {file = "aiohttp-3.8.6.tar.gz", hash = "sha256:b0cf2a4501bff9330a8a5248b4ce951851e415bdcce9dc158e76cfd55e15085c"},
+ {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:939677b61f9d72a4fa2a042a5eee2a99a24001a67c13da113b2e30396567db54"},
+ {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1f5cd333fcf7590a18334c90f8c9147c837a6ec8a178e88d90a9b96ea03194cc"},
+ {file = "aiohttp-3.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:82e6aa28dd46374f72093eda8bcd142f7771ee1eb9d1e223ff0fa7177a96b4a5"},
+ {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f56455b0c2c7cc3b0c584815264461d07b177f903a04481dfc33e08a89f0c26b"},
+ {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bca77a198bb6e69795ef2f09a5f4c12758487f83f33d63acde5f0d4919815768"},
+ {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e083c285857b78ee21a96ba1eb1b5339733c3563f72980728ca2b08b53826ca5"},
+ {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab40e6251c3873d86ea9b30a1ac6d7478c09277b32e14745d0d3c6e76e3c7e29"},
+ {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df822ee7feaaeffb99c1a9e5e608800bd8eda6e5f18f5cfb0dc7eeb2eaa6bbec"},
+ {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:acef0899fea7492145d2bbaaaec7b345c87753168589cc7faf0afec9afe9b747"},
+ {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cd73265a9e5ea618014802ab01babf1940cecb90c9762d8b9e7d2cc1e1969ec6"},
+ {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a78ed8a53a1221393d9637c01870248a6f4ea5b214a59a92a36f18151739452c"},
+ {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6b0e029353361f1746bac2e4cc19b32f972ec03f0f943b390c4ab3371840aabf"},
+ {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7cf5c9458e1e90e3c390c2639f1017a0379a99a94fdfad3a1fd966a2874bba52"},
+ {file = "aiohttp-3.9.3-cp310-cp310-win32.whl", hash = "sha256:3e59c23c52765951b69ec45ddbbc9403a8761ee6f57253250c6e1536cacc758b"},
+ {file = "aiohttp-3.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:055ce4f74b82551678291473f66dc9fb9048a50d8324278751926ff0ae7715e5"},
+ {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6b88f9386ff1ad91ace19d2a1c0225896e28815ee09fc6a8932fded8cda97c3d"},
+ {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c46956ed82961e31557b6857a5ca153c67e5476972e5f7190015018760938da2"},
+ {file = "aiohttp-3.9.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:07b837ef0d2f252f96009e9b8435ec1fef68ef8b1461933253d318748ec1acdc"},
+ {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad46e6f620574b3b4801c68255492e0159d1712271cc99d8bdf35f2043ec266"},
+ {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ed3e046ea7b14938112ccd53d91c1539af3e6679b222f9469981e3dac7ba1ce"},
+ {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:039df344b45ae0b34ac885ab5b53940b174530d4dd8a14ed8b0e2155b9dddccb"},
+ {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7943c414d3a8d9235f5f15c22ace69787c140c80b718dcd57caaade95f7cd93b"},
+ {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84871a243359bb42c12728f04d181a389718710129b36b6aad0fc4655a7647d4"},
+ {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5eafe2c065df5401ba06821b9a054d9cb2848867f3c59801b5d07a0be3a380ae"},
+ {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9d3c9b50f19704552f23b4eaea1fc082fdd82c63429a6506446cbd8737823da3"},
+ {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:f033d80bc6283092613882dfe40419c6a6a1527e04fc69350e87a9df02bbc283"},
+ {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:2c895a656dd7e061b2fd6bb77d971cc38f2afc277229ce7dd3552de8313a483e"},
+ {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1f5a71d25cd8106eab05f8704cd9167b6e5187bcdf8f090a66c6d88b634802b4"},
+ {file = "aiohttp-3.9.3-cp311-cp311-win32.whl", hash = "sha256:50fca156d718f8ced687a373f9e140c1bb765ca16e3d6f4fe116e3df7c05b2c5"},
+ {file = "aiohttp-3.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:5fe9ce6c09668063b8447f85d43b8d1c4e5d3d7e92c63173e6180b2ac5d46dd8"},
+ {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:38a19bc3b686ad55804ae931012f78f7a534cce165d089a2059f658f6c91fa60"},
+ {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:770d015888c2a598b377bd2f663adfd947d78c0124cfe7b959e1ef39f5b13869"},
+ {file = "aiohttp-3.9.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee43080e75fc92bf36219926c8e6de497f9b247301bbf88c5c7593d931426679"},
+ {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52df73f14ed99cee84865b95a3d9e044f226320a87af208f068ecc33e0c35b96"},
+ {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc9b311743a78043b26ffaeeb9715dc360335e5517832f5a8e339f8a43581e4d"},
+ {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b955ed993491f1a5da7f92e98d5dad3c1e14dc175f74517c4e610b1f2456fb11"},
+ {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:504b6981675ace64c28bf4a05a508af5cde526e36492c98916127f5a02354d53"},
+ {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6fe5571784af92b6bc2fda8d1925cccdf24642d49546d3144948a6a1ed58ca5"},
+ {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ba39e9c8627edc56544c8628cc180d88605df3892beeb2b94c9bc857774848ca"},
+ {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e5e46b578c0e9db71d04c4b506a2121c0cb371dd89af17a0586ff6769d4c58c1"},
+ {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:938a9653e1e0c592053f815f7028e41a3062e902095e5a7dc84617c87267ebd5"},
+ {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:c3452ea726c76e92f3b9fae4b34a151981a9ec0a4847a627c43d71a15ac32aa6"},
+ {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ff30218887e62209942f91ac1be902cc80cddb86bf00fbc6783b7a43b2bea26f"},
+ {file = "aiohttp-3.9.3-cp312-cp312-win32.whl", hash = "sha256:38f307b41e0bea3294a9a2a87833191e4bcf89bb0365e83a8be3a58b31fb7f38"},
+ {file = "aiohttp-3.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:b791a3143681a520c0a17e26ae7465f1b6f99461a28019d1a2f425236e6eedb5"},
+ {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0ed621426d961df79aa3b963ac7af0d40392956ffa9be022024cd16297b30c8c"},
+ {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7f46acd6a194287b7e41e87957bfe2ad1ad88318d447caf5b090012f2c5bb528"},
+ {file = "aiohttp-3.9.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:feeb18a801aacb098220e2c3eea59a512362eb408d4afd0c242044c33ad6d542"},
+ {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f734e38fd8666f53da904c52a23ce517f1b07722118d750405af7e4123933511"},
+ {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b40670ec7e2156d8e57f70aec34a7216407848dfe6c693ef131ddf6e76feb672"},
+ {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdd215b7b7fd4a53994f238d0f46b7ba4ac4c0adb12452beee724ddd0743ae5d"},
+ {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:017a21b0df49039c8f46ca0971b3a7fdc1f56741ab1240cb90ca408049766168"},
+ {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e99abf0bba688259a496f966211c49a514e65afa9b3073a1fcee08856e04425b"},
+ {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:648056db9a9fa565d3fa851880f99f45e3f9a771dd3ff3bb0c048ea83fb28194"},
+ {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8aacb477dc26797ee089721536a292a664846489c49d3ef9725f992449eda5a8"},
+ {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:522a11c934ea660ff8953eda090dcd2154d367dec1ae3c540aff9f8a5c109ab4"},
+ {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:5bce0dc147ca85caa5d33debc4f4d65e8e8b5c97c7f9f660f215fa74fc49a321"},
+ {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b4af9f25b49a7be47c0972139e59ec0e8285c371049df1a63b6ca81fdd216a2"},
+ {file = "aiohttp-3.9.3-cp38-cp38-win32.whl", hash = "sha256:298abd678033b8571995650ccee753d9458dfa0377be4dba91e4491da3f2be63"},
+ {file = "aiohttp-3.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:69361bfdca5468c0488d7017b9b1e5ce769d40b46a9f4a2eed26b78619e9396c"},
+ {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0fa43c32d1643f518491d9d3a730f85f5bbaedcbd7fbcae27435bb8b7a061b29"},
+ {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:835a55b7ca49468aaaac0b217092dfdff370e6c215c9224c52f30daaa735c1c1"},
+ {file = "aiohttp-3.9.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06a9b2c8837d9a94fae16c6223acc14b4dfdff216ab9b7202e07a9a09541168f"},
+ {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abf151955990d23f84205286938796c55ff11bbfb4ccfada8c9c83ae6b3c89a3"},
+ {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59c26c95975f26e662ca78fdf543d4eeaef70e533a672b4113dd888bd2423caa"},
+ {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f95511dd5d0e05fd9728bac4096319f80615aaef4acbecb35a990afebe953b0e"},
+ {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:595f105710293e76b9dc09f52e0dd896bd064a79346234b521f6b968ffdd8e58"},
+ {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7c8b816c2b5af5c8a436df44ca08258fc1a13b449393a91484225fcb7545533"},
+ {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f1088fa100bf46e7b398ffd9904f4808a0612e1d966b4aa43baa535d1b6341eb"},
+ {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f59dfe57bb1ec82ac0698ebfcdb7bcd0e99c255bd637ff613760d5f33e7c81b3"},
+ {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:361a1026c9dd4aba0109e4040e2aecf9884f5cfe1b1b1bd3d09419c205e2e53d"},
+ {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:363afe77cfcbe3a36353d8ea133e904b108feea505aa4792dad6585a8192c55a"},
+ {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e2c45c208c62e955e8256949eb225bd8b66a4c9b6865729a786f2aa79b72e9d"},
+ {file = "aiohttp-3.9.3-cp39-cp39-win32.whl", hash = "sha256:f7217af2e14da0856e082e96ff637f14ae45c10a5714b63c77f26d8884cf1051"},
+ {file = "aiohttp-3.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:27468897f628c627230dba07ec65dc8d0db566923c48f29e084ce382119802bc"},
+ {file = "aiohttp-3.9.3.tar.gz", hash = "sha256:90842933e5d1ff760fae6caca4b2b3edba53ba8f4b71e95dacf2818a2aca06f7"},
]
[package.dependencies]
aiosignal = ">=1.1.2"
-async-timeout = ">=4.0.0a3,<5.0"
+async-timeout = {version = ">=4.0,<5.0", markers = "python_version < \"3.11\""}
attrs = ">=17.3.0"
-charset-normalizer = ">=2.0,<4.0"
frozenlist = ">=1.1.1"
multidict = ">=4.5,<7.0"
yarl = ">=1.0,<2.0"
[package.extras]
-speedups = ["Brotli", "aiodns", "cchardet"]
+speedups = ["Brotli", "aiodns", "brotlicffi"]
[[package]]
name = "aiosignal"
@@ -323,105 +311,6 @@ files = [
{file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"},
]
-[[package]]
-name = "charset-normalizer"
-version = "3.3.1"
-description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
-optional = false
-python-versions = ">=3.7.0"
-files = [
- {file = "charset-normalizer-3.3.1.tar.gz", hash = "sha256:d9137a876020661972ca6eec0766d81aef8a5627df628b664b234b73396e727e"},
- {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8aee051c89e13565c6bd366813c386939f8e928af93c29fda4af86d25b73d8f8"},
- {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:352a88c3df0d1fa886562384b86f9a9e27563d4704ee0e9d56ec6fcd270ea690"},
- {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:223b4d54561c01048f657fa6ce41461d5ad8ff128b9678cfe8b2ecd951e3f8a2"},
- {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f861d94c2a450b974b86093c6c027888627b8082f1299dfd5a4bae8e2292821"},
- {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1171ef1fc5ab4693c5d151ae0fdad7f7349920eabbaca6271f95969fa0756c2d"},
- {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28f512b9a33235545fbbdac6a330a510b63be278a50071a336afc1b78781b147"},
- {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0e842112fe3f1a4ffcf64b06dc4c61a88441c2f02f373367f7b4c1aa9be2ad5"},
- {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f9bc2ce123637a60ebe819f9fccc614da1bcc05798bbbaf2dd4ec91f3e08846"},
- {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f194cce575e59ffe442c10a360182a986535fd90b57f7debfaa5c845c409ecc3"},
- {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9a74041ba0bfa9bc9b9bb2cd3238a6ab3b7618e759b41bd15b5f6ad958d17605"},
- {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b578cbe580e3b41ad17b1c428f382c814b32a6ce90f2d8e39e2e635d49e498d1"},
- {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6db3cfb9b4fcecb4390db154e75b49578c87a3b9979b40cdf90d7e4b945656e1"},
- {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:debb633f3f7856f95ad957d9b9c781f8e2c6303ef21724ec94bea2ce2fcbd056"},
- {file = "charset_normalizer-3.3.1-cp310-cp310-win32.whl", hash = "sha256:87071618d3d8ec8b186d53cb6e66955ef2a0e4fa63ccd3709c0c90ac5a43520f"},
- {file = "charset_normalizer-3.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:e372d7dfd154009142631de2d316adad3cc1c36c32a38b16a4751ba78da2a397"},
- {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ae4070f741f8d809075ef697877fd350ecf0b7c5837ed68738607ee0a2c572cf"},
- {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:58e875eb7016fd014c0eea46c6fa92b87b62c0cb31b9feae25cbbe62c919f54d"},
- {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dbd95e300367aa0827496fe75a1766d198d34385a58f97683fe6e07f89ca3e3c"},
- {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de0b4caa1c8a21394e8ce971997614a17648f94e1cd0640fbd6b4d14cab13a72"},
- {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:985c7965f62f6f32bf432e2681173db41336a9c2611693247069288bcb0c7f8b"},
- {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a15c1fe6d26e83fd2e5972425a772cca158eae58b05d4a25a4e474c221053e2d"},
- {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae55d592b02c4349525b6ed8f74c692509e5adffa842e582c0f861751701a673"},
- {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be4d9c2770044a59715eb57c1144dedea7c5d5ae80c68fb9959515037cde2008"},
- {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:851cf693fb3aaef71031237cd68699dded198657ec1e76a76eb8be58c03a5d1f"},
- {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:31bbaba7218904d2eabecf4feec0d07469284e952a27400f23b6628439439fa7"},
- {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:871d045d6ccc181fd863a3cd66ee8e395523ebfbc57f85f91f035f50cee8e3d4"},
- {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:501adc5eb6cd5f40a6f77fbd90e5ab915c8fd6e8c614af2db5561e16c600d6f3"},
- {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f5fb672c396d826ca16a022ac04c9dce74e00a1c344f6ad1a0fdc1ba1f332213"},
- {file = "charset_normalizer-3.3.1-cp311-cp311-win32.whl", hash = "sha256:bb06098d019766ca16fc915ecaa455c1f1cd594204e7f840cd6258237b5079a8"},
- {file = "charset_normalizer-3.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:8af5a8917b8af42295e86b64903156b4f110a30dca5f3b5aedea123fbd638bff"},
- {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7ae8e5142dcc7a49168f4055255dbcced01dc1714a90a21f87448dc8d90617d1"},
- {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5b70bab78accbc672f50e878a5b73ca692f45f5b5e25c8066d748c09405e6a55"},
- {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ceca5876032362ae73b83347be8b5dbd2d1faf3358deb38c9c88776779b2e2f"},
- {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34d95638ff3613849f473afc33f65c401a89f3b9528d0d213c7037c398a51296"},
- {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9edbe6a5bf8b56a4a84533ba2b2f489d0046e755c29616ef8830f9e7d9cf5728"},
- {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6a02a3c7950cafaadcd46a226ad9e12fc9744652cc69f9e5534f98b47f3bbcf"},
- {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10b8dd31e10f32410751b3430996f9807fc4d1587ca69772e2aa940a82ab571a"},
- {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edc0202099ea1d82844316604e17d2b175044f9bcb6b398aab781eba957224bd"},
- {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b891a2f68e09c5ef989007fac11476ed33c5c9994449a4e2c3386529d703dc8b"},
- {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:71ef3b9be10070360f289aea4838c784f8b851be3ba58cf796262b57775c2f14"},
- {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:55602981b2dbf8184c098bc10287e8c245e351cd4fdcad050bd7199d5a8bf514"},
- {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:46fb9970aa5eeca547d7aa0de5d4b124a288b42eaefac677bde805013c95725c"},
- {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:520b7a142d2524f999447b3a0cf95115df81c4f33003c51a6ab637cbda9d0bf4"},
- {file = "charset_normalizer-3.3.1-cp312-cp312-win32.whl", hash = "sha256:8ec8ef42c6cd5856a7613dcd1eaf21e5573b2185263d87d27c8edcae33b62a61"},
- {file = "charset_normalizer-3.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:baec8148d6b8bd5cee1ae138ba658c71f5b03e0d69d5907703e3e1df96db5e41"},
- {file = "charset_normalizer-3.3.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63a6f59e2d01310f754c270e4a257426fe5a591dc487f1983b3bbe793cf6bac6"},
- {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d6bfc32a68bc0933819cfdfe45f9abc3cae3877e1d90aac7259d57e6e0f85b1"},
- {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4f3100d86dcd03c03f7e9c3fdb23d92e32abbca07e7c13ebd7ddfbcb06f5991f"},
- {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39b70a6f88eebe239fa775190796d55a33cfb6d36b9ffdd37843f7c4c1b5dc67"},
- {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e12f8ee80aa35e746230a2af83e81bd6b52daa92a8afaef4fea4a2ce9b9f4fa"},
- {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b6cefa579e1237ce198619b76eaa148b71894fb0d6bcf9024460f9bf30fd228"},
- {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:61f1e3fb621f5420523abb71f5771a204b33c21d31e7d9d86881b2cffe92c47c"},
- {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4f6e2a839f83a6a76854d12dbebde50e4b1afa63e27761549d006fa53e9aa80e"},
- {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:1ec937546cad86d0dce5396748bf392bb7b62a9eeb8c66efac60e947697f0e58"},
- {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:82ca51ff0fc5b641a2d4e1cc8c5ff108699b7a56d7f3ad6f6da9dbb6f0145b48"},
- {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:633968254f8d421e70f91c6ebe71ed0ab140220469cf87a9857e21c16687c034"},
- {file = "charset_normalizer-3.3.1-cp37-cp37m-win32.whl", hash = "sha256:c0c72d34e7de5604df0fde3644cc079feee5e55464967d10b24b1de268deceb9"},
- {file = "charset_normalizer-3.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:63accd11149c0f9a99e3bc095bbdb5a464862d77a7e309ad5938fbc8721235ae"},
- {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5a3580a4fdc4ac05f9e53c57f965e3594b2f99796231380adb2baaab96e22761"},
- {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2465aa50c9299d615d757c1c888bc6fef384b7c4aec81c05a0172b4400f98557"},
- {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cb7cd68814308aade9d0c93c5bd2ade9f9441666f8ba5aa9c2d4b389cb5e2a45"},
- {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91e43805ccafa0a91831f9cd5443aa34528c0c3f2cc48c4cb3d9a7721053874b"},
- {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:854cc74367180beb327ab9d00f964f6d91da06450b0855cbbb09187bcdb02de5"},
- {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c15070ebf11b8b7fd1bfff7217e9324963c82dbdf6182ff7050519e350e7ad9f"},
- {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c4c99f98fc3a1835af8179dcc9013f93594d0670e2fa80c83aa36346ee763d2"},
- {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3fb765362688821404ad6cf86772fc54993ec11577cd5a92ac44b4c2ba52155b"},
- {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dced27917823df984fe0c80a5c4ad75cf58df0fbfae890bc08004cd3888922a2"},
- {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a66bcdf19c1a523e41b8e9d53d0cedbfbac2e93c649a2e9502cb26c014d0980c"},
- {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ecd26be9f112c4f96718290c10f4caea6cc798459a3a76636b817a0ed7874e42"},
- {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:3f70fd716855cd3b855316b226a1ac8bdb3caf4f7ea96edcccc6f484217c9597"},
- {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:17a866d61259c7de1bdadef418a37755050ddb4b922df8b356503234fff7932c"},
- {file = "charset_normalizer-3.3.1-cp38-cp38-win32.whl", hash = "sha256:548eefad783ed787b38cb6f9a574bd8664468cc76d1538215d510a3cd41406cb"},
- {file = "charset_normalizer-3.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:45f053a0ece92c734d874861ffe6e3cc92150e32136dd59ab1fb070575189c97"},
- {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bc791ec3fd0c4309a753f95bb6c749ef0d8ea3aea91f07ee1cf06b7b02118f2f"},
- {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0c8c61fb505c7dad1d251c284e712d4e0372cef3b067f7ddf82a7fa82e1e9a93"},
- {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2c092be3885a1b7899cd85ce24acedc1034199d6fca1483fa2c3a35c86e43041"},
- {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2000c54c395d9e5e44c99dc7c20a64dc371f777faf8bae4919ad3e99ce5253e"},
- {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4cb50a0335382aac15c31b61d8531bc9bb657cfd848b1d7158009472189f3d62"},
- {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c30187840d36d0ba2893bc3271a36a517a717f9fd383a98e2697ee890a37c273"},
- {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe81b35c33772e56f4b6cf62cf4aedc1762ef7162a31e6ac7fe5e40d0149eb67"},
- {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0bf89afcbcf4d1bb2652f6580e5e55a840fdf87384f6063c4a4f0c95e378656"},
- {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:06cf46bdff72f58645434d467bf5228080801298fbba19fe268a01b4534467f5"},
- {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:3c66df3f41abee950d6638adc7eac4730a306b022570f71dd0bd6ba53503ab57"},
- {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd805513198304026bd379d1d516afbf6c3c13f4382134a2c526b8b854da1c2e"},
- {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:9505dc359edb6a330efcd2be825fdb73ee3e628d9010597aa1aee5aa63442e97"},
- {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:31445f38053476a0c4e6d12b047b08ced81e2c7c712e5a1ad97bc913256f91b2"},
- {file = "charset_normalizer-3.3.1-cp39-cp39-win32.whl", hash = "sha256:bd28b31730f0e982ace8663d108e01199098432a30a4c410d06fe08fdb9e93f4"},
- {file = "charset_normalizer-3.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:555fe186da0068d3354cdf4bbcbc609b0ecae4d04c921cc13e209eece7720727"},
- {file = "charset_normalizer-3.3.1-py3-none-any.whl", hash = "sha256:800561453acdecedaac137bf09cd719c7a440b6800ec182f077bb8e7025fb708"},
-]
-
[[package]]
name = "click"
version = "8.1.7"
@@ -1223,6 +1112,7 @@ files = [
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
+ {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"},
{file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
{file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
{file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
@@ -1230,8 +1120,16 @@ files = [
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
+ {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"},
{file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
+ {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
+ {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
+ {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"},
+ {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
+ {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
+ {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
+ {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"},
{file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
@@ -1248,6 +1146,7 @@ files = [
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
+ {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"},
{file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
{file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
{file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
@@ -1255,6 +1154,7 @@ files = [
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
+ {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"},
{file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
{file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
{file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
diff --git a/pyproject.toml b/pyproject.toml
index 69d98f7..6c70e32 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -8,12 +8,12 @@ readme = "README.md"
[tool.poetry.dependencies]
python = "^3.10"
beaker-pyteal = "^1.1.1"
-algokit-utils = {version = "^2.1.0", allow-prereleases = true}
+algokit-utils = { version = "^2.1.0", allow-prereleases = true }
python-dotenv = "^1.0.0"
[tool.poetry.group.dev.dependencies]
ruff = ">=0.0.260"
-black = {extras = ["d"], version = "^22.10.0"}
+black = { extras = ["d"], version = "^22.10.0" }
flake8 = "^6.0.0"
pytest = "^7.2.2"
mypy = "^1.1.1"
@@ -26,8 +26,27 @@ requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.ruff]
-select = ["E", "F", "ANN", "UP", "N", "C4", "B", "A", "YTT", "W", "FBT", "Q", "RUF", "I"]
-extend-exclude = ["tests_generated/*python_linter-flake8", "tests_generated/*python_linter-none", "template_content"]
+select = [
+ "E",
+ "F",
+ "ANN",
+ "UP",
+ "N",
+ "C4",
+ "B",
+ "A",
+ "YTT",
+ "W",
+ "FBT",
+ "Q",
+ "RUF",
+ "I",
+]
+extend-exclude = [
+ "examples/*python_linter-flake8",
+ "examples/*python_linter-none",
+ "template_content",
+]
ignore = [
"ANN101", # no type for self
"ANN102", # no type for cls
@@ -36,9 +55,7 @@ unfixable = ["B", "RUF"]
[tool.pytest.ini_options]
pythonpath = ["tests"]
-testpaths = [
- "tests",
-]
+testpaths = ["tests"]
[tool.mypy]
python_version = "3.10"
diff --git a/template_content/.algokit.toml b/template_content/.algokit.toml
deleted file mode 100644
index 839cfe5..0000000
--- a/template_content/.algokit.toml
+++ /dev/null
@@ -1,2 +0,0 @@
-[algokit]
-min_version = "v1.3.0b1"
diff --git a/template_content/.algokit.toml.jinja b/template_content/.algokit.toml.jinja
new file mode 100644
index 0000000..41f9604
--- /dev/null
+++ b/template_content/.algokit.toml.jinja
@@ -0,0 +1,10 @@
+[algokit]
+min_version = "v1.3.0b1"
+
+[generate.import_contract]
+description = "Import a typed client from your smart contracts project"
+path = ".algokit/generators/import_contract"
+
+[project]
+type = "frontend"
+name = "{{ project_name }}"
diff --git a/template_content/{% if use_github_actions %}.github{% endif %}/workflows/checks.yaml.jinja b/template_content/{% if use_github_actions %}.github{% endif %}/workflows/checks.yaml.jinja
index 29fa82e..61aeddf 100644
--- a/template_content/{% if use_github_actions %}.github{% endif %}/workflows/checks.yaml.jinja
+++ b/template_content/{% if use_github_actions %}.github{% endif %}/workflows/checks.yaml.jinja
@@ -16,7 +16,7 @@ jobs:
runs-on: 'ubuntu-latest'
steps:
- name: Check out repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
fetch-depth: 0
diff --git a/tests/test_custom_answers.py b/tests/test_custom_answers.py
new file mode 100644
index 0000000..7f60ce6
--- /dev/null
+++ b/tests/test_custom_answers.py
@@ -0,0 +1,169 @@
+import re
+import shutil
+import subprocess
+import tempfile
+from collections.abc import Iterator
+from pathlib import Path
+
+import pytest
+
+commit_pattern = re.compile(r"_commit: .*")
+src_path_pattern = re.compile(r"_src_path: .*")
+tests_path = Path(__file__).parent
+root = tests_path.parent
+generated_folder = "examples/cloud_provider"
+# specific answer combination
+generated_root = root / generated_folder
+
+config_path = Path(__file__).parent.parent / "pyproject.toml"
+NPM_INSTALL_ARGS = ["npm", "install"]
+NPM_LINT_ARGS = ["npm", "run", "lint"]
+NPM_BUILD_ARGS = ["npm", "run", "build"]
+
+
+def _generate_default_parameters(
+ *, preset_name: str, cloud_provider: str = "none"
+) -> dict[str, str]:
+ return {
+ "author_name": "None",
+ "author_email": "None",
+ "preset_name": preset_name,
+ "cloud_provider": cloud_provider,
+ }
+
+
+@pytest.fixture(autouse=True, scope="module")
+def working_dir(custom_subdir: str = "template") -> Iterator[Path]:
+ with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as temp:
+ working_dir_path = Path(temp) / custom_subdir
+ working_generated_root = working_dir_path / generated_folder
+ shutil.copytree(root, working_dir_path)
+ subprocess.run(["git", "add", "-A"], cwd=working_dir_path)
+ subprocess.run(
+ ["git", "commit", "-m", "draft changes", "--no-verify"],
+ cwd=working_dir_path,
+ )
+
+ yield working_dir_path
+
+ for src_dir in working_generated_root.iterdir():
+ if not src_dir.is_dir():
+ continue
+
+ dest_dir = generated_root / src_dir.stem
+ shutil.rmtree(dest_dir, ignore_errors=True)
+ shutil.copytree(src_dir, dest_dir, dirs_exist_ok=True)
+
+
+def run_init(
+ working_dir: Path,
+ test_name: str,
+ *args: str,
+ template_url: str | None = None,
+ template_branch: str | None = None,
+ answers: dict[str, str] | None = None,
+ custom_check_args: list[list[str]] | None = None,
+) -> subprocess.CompletedProcess:
+ copy_to = working_dir / generated_folder / test_name
+ shutil.rmtree(copy_to, ignore_errors=True)
+ if template_url is None:
+ template_url = str(working_dir)
+
+ if template_branch is None:
+ git_output = subprocess.run(
+ ["git", "rev-parse", "--abbrev-ref", "HEAD"],
+ cwd=working_dir,
+ stdout=subprocess.PIPE,
+ )
+ template_branch = git_output.stdout.decode("utf-8").strip()
+
+ init_args = [
+ "algokit",
+ "--verbose",
+ "init",
+ "--name",
+ str(copy_to.stem),
+ "--template-url",
+ template_url,
+ "--UNSAFE-SECURITY-accept-template-url",
+ "--defaults",
+ "--no-ide",
+ "--no-git",
+ "--no-bootstrap",
+ "--no-workspace",
+ ]
+ answers = {
+ **(answers or {}),
+ }
+
+ for question, answer in answers.items():
+ init_args.extend(["-a", question, str(answer)])
+ if template_branch:
+ init_args.extend(["--template-url-ref", template_branch])
+ init_args.extend(args)
+
+ result = subprocess.run(
+ init_args,
+ input="y", # acknowledge that input is not a tty
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ text=True,
+ cwd=copy_to.parent,
+ )
+
+ if result.returncode:
+ return result
+ # if successful, normalize .copier-answers.yml to make observing diffs easier
+ copier_answers = Path(copy_to / ".copier-answers.yml")
+ content = copier_answers.read_text("utf-8")
+ content = commit_pattern.sub("_commit: ", content)
+ content = src_path_pattern.sub("_src_path: ", content)
+ copier_answers.write_text(content, "utf-8")
+
+ if custom_check_args:
+ for check_args in custom_check_args:
+ result = subprocess.run(
+ check_args,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ text=True,
+ cwd=copy_to,
+ )
+ if result.returncode:
+ break
+
+ # remove node_modules
+ shutil.rmtree(copy_to / "node_modules", ignore_errors=True)
+
+ # Check if .idea folder exists and if so modify os specific SDK_HOME path
+ idea_folder = copy_to / ".idea"
+ if idea_folder.exists():
+ # Iterate over all files in .idea/runConfigurations
+ for file in (idea_folder / "runConfigurations").iterdir():
+ # Read the file content
+ content = file.read_text()
+ # Replace the line containing SDK_HOME
+ content = re.sub(
+ r'',
+ '',
+ content,
+ )
+ # Write the modified content back to the file
+ file.write_text(content)
+ return result
+
+
+# Below places the artifacts to examples/misc folder to separate from default
+# preset tests
+@pytest.mark.parametrize("cloud_provider", ["vercel", "netlify"])
+def test_production_react_cloud(working_dir: Path, cloud_provider: str) -> None:
+ response = run_init(
+ working_dir,
+ f"production_react_{cloud_provider}",
+ answers=_generate_default_parameters(
+ preset_name="production", cloud_provider=cloud_provider
+ ),
+ custom_check_args=[NPM_INSTALL_ARGS, NPM_LINT_ARGS, NPM_BUILD_ARGS],
+ )
+
+ assert response.returncode == 0, response.stdout
diff --git a/tests/test_templates.py b/tests/test_templates.py
index 2d4b4b7..9a23bf4 100644
--- a/tests/test_templates.py
+++ b/tests/test_templates.py
@@ -11,7 +11,8 @@
src_path_pattern = re.compile(r"_src_path: .*")
tests_path = Path(__file__).parent
root = tests_path.parent
-generated_folder = "tests_generated"
+generated_folder = "examples"
+# specific answer combination
generated_root = root / generated_folder
config_path = Path(__file__).parent.parent / "pyproject.toml"
@@ -21,37 +22,29 @@
def _generate_default_parameters(
- default_state: str = "yes",
- cloud_provider: str = "none",
- ide_jetbrains: str = "no",
+ *, preset_name: str, cloud_provider: str = "none"
) -> dict[str, str]:
return {
"author_name": "None",
"author_email": "None",
- "ide_vscode": default_state,
- "ide_jetbrains": ide_jetbrains,
- "use_eslint_prettier": default_state,
- "use_tailwind": default_state,
- "use_daisy_ui": default_state,
- "use_jest": default_state,
- "use_playwright": default_state,
- "use_github_actions": default_state,
+ "preset_name": preset_name,
"cloud_provider": cloud_provider,
}
@pytest.fixture(autouse=True, scope="module")
-def working_dir() -> Iterator[Path]:
+def working_dir(custom_subdir: str = "template") -> Iterator[Path]:
with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as temp:
- working_dir = Path(temp) / "template"
- working_generated_root = working_dir / generated_folder
- shutil.copytree(root, working_dir)
- subprocess.run(["git", "add", "-A"], cwd=working_dir)
+ working_dir_path = Path(temp) / custom_subdir
+ working_generated_root = working_dir_path / generated_folder
+ shutil.copytree(root, working_dir_path)
+ subprocess.run(["git", "add", "-A"], cwd=working_dir_path)
subprocess.run(
- ["git", "commit", "-m", "draft changes", "--no-verify"], cwd=working_dir
+ ["git", "commit", "-m", "draft changes", "--no-verify"],
+ cwd=working_dir_path,
)
- yield working_dir
+ yield working_dir_path
for src_dir in working_generated_root.iterdir():
if not src_dir.is_dir():
@@ -97,9 +90,9 @@ def run_init(
"--no-ide",
"--no-git",
"--no-bootstrap",
+ "--no-workspace",
]
answers = {
- **_generate_default_parameters("yes"),
**(answers or {}),
}
@@ -160,44 +153,12 @@ def run_init(
return result
-def test_all_default_parameters_on_vercel(working_dir: Path) -> None:
+@pytest.mark.parametrize("preset_name", ["starter", "production"])
+def test_react_templates(working_dir: Path, preset_name: str) -> None:
response = run_init(
working_dir,
- "test_all_default_parameters_on_vercel",
- answers=_generate_default_parameters("yes", "vercel"),
- custom_check_args=[NPM_INSTALL_ARGS, NPM_LINT_ARGS, NPM_BUILD_ARGS],
- )
-
- assert response.returncode == 0, response.stdout
-
-
-def test_all_default_parameters_on_netlify(working_dir: Path) -> None:
- response = run_init(
- working_dir,
- "test_all_default_parameters_on_netlify",
- answers=_generate_default_parameters("yes", "netlify"),
- custom_check_args=[NPM_INSTALL_ARGS, NPM_LINT_ARGS, NPM_BUILD_ARGS],
- )
-
- assert response.returncode == 0, response.stdout
-
-
-def test_all_default_parameters_off(working_dir: Path) -> None:
- response = run_init(
- working_dir,
- "test_all_default_parameters_off",
- answers=_generate_default_parameters("no"),
- custom_check_args=[NPM_INSTALL_ARGS, NPM_BUILD_ARGS],
- )
-
- assert response.returncode == 0, response.stdout
-
-
-def test_all_default_parameters_off_jetbrains(working_dir: Path) -> None:
- response = run_init(
- working_dir,
- "test_all_default_parameters_jetbrains",
- answers=_generate_default_parameters("no", ide_jetbrains="yes"),
+ f"{preset_name}_react",
+ answers=_generate_default_parameters(preset_name=preset_name),
custom_check_args=[NPM_INSTALL_ARGS, NPM_BUILD_ARGS],
)
diff --git a/tests_generated/test_all_default_parameters_jetbrains/.algokit.toml b/tests_generated/test_all_default_parameters_jetbrains/.algokit.toml
deleted file mode 100644
index 839cfe5..0000000
--- a/tests_generated/test_all_default_parameters_jetbrains/.algokit.toml
+++ /dev/null
@@ -1,2 +0,0 @@
-[algokit]
-min_version = "v1.3.0b1"
diff --git a/tests_generated/test_all_default_parameters_jetbrains/.copier-answers.yml b/tests_generated/test_all_default_parameters_jetbrains/.copier-answers.yml
deleted file mode 100644
index 35bed0a..0000000
--- a/tests_generated/test_all_default_parameters_jetbrains/.copier-answers.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-# 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
-ide_jetbrains: true
-ide_vscode: false
-indexer_port: 8980
-indexer_server: http://localhost
-indexer_token: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-project_name: test_all_default_parameters_jetbrains
-use_eslint_prettier: false
-use_github_actions: false
-use_jest: false
-use_playwright: false
-use_tailwind: false
-
diff --git a/tests_generated/test_all_default_parameters_off/.algokit.toml b/tests_generated/test_all_default_parameters_off/.algokit.toml
deleted file mode 100644
index 839cfe5..0000000
--- a/tests_generated/test_all_default_parameters_off/.algokit.toml
+++ /dev/null
@@ -1,2 +0,0 @@
-[algokit]
-min_version = "v1.3.0b1"
diff --git a/tests_generated/test_all_default_parameters_off/.copier-answers.yml b/tests_generated/test_all_default_parameters_off/.copier-answers.yml
deleted file mode 100644
index 9186f25..0000000
--- a/tests_generated/test_all_default_parameters_off/.copier-answers.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-# 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
-ide_jetbrains: false
-ide_vscode: false
-indexer_port: 8980
-indexer_server: http://localhost
-indexer_token: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-project_name: test_all_default_parameters_off
-use_eslint_prettier: false
-use_github_actions: false
-use_jest: false
-use_playwright: false
-use_tailwind: false
-
diff --git a/tests_generated/test_all_default_parameters_off/src/styles/App.css b/tests_generated/test_all_default_parameters_off/src/styles/App.css
deleted file mode 100644
index ee2b188..0000000
--- a/tests_generated/test_all_default_parameters_off/src/styles/App.css
+++ /dev/null
@@ -1,126 +0,0 @@
-/* App.css */
-
-.hero {
- display: flex;
- justify-content: center;
- align-items: center;
- min-height: 100vh;
- background-color: #38b2ac;
-}
-
-.hero-content {
- text-align: center;
- border-radius: 0.5rem;
- padding: 1.5rem;
- max-width: 24rem;
- background-color: #ffffff;
- margin: 0 auto;
-}
-
-.text-4xl {
- font-size: 2.25rem;
- line-height: 2.5rem;
-}
-
-.font-bold {
- font-weight: 700;
-}
-
-.py-6 {
- padding-top: 1.5rem;
- padding-bottom: 1.5rem;
-}
-
-.grid {
- display: grid;
-}
-
-.btn {
- margin: 0.5rem;
-}
-
-.btn-primary {
- background-color: #1a202c;
- color: #fff;
-}
-
-.divider {
- border-top: 1px solid #e2e8f0;
- margin-top: 1rem;
- margin-bottom: 1rem;
-}
-
-.modal {
- position: fixed;
- top: 0;
- bottom: 0;
- left: 0;
- right: 0;
- background: rgba(0, 0, 0, 0.6);
- display: none;
- z-index: 9999;
- overflow: auto;
-}
-
-.modal-open {
- display: block;
-}
-
-.modal-box {
- margin: 2.5em auto;
- background: #fff;
- border-radius: 0.5em;
- width: 40em;
- max-width: 90vw;
- padding: 1em;
-}
-
-.font-bold {
- font-weight: bold;
-}
-
-.text-2xl {
- font-size: 1.5rem;
-}
-
-.m-2 {
- margin: 0.5rem;
-}
-
-.pt-5 {
- padding-top: 1.25rem;
-}
-
-.grid {
- display: grid;
-}
-
-.btn {
- margin: 0.5rem;
- padding: 0.5rem 1rem;
- background-color: #00aba2;
- color: #fff;
-}
-
-.btn-warning {
- background-color: #d69e2e;
-}
-
-.border-1 {
- border-width: 1px;
-}
-
-.border-teal-800 {
- border-color: #2c7a7b;
-}
-
-.modal-action {
- display: grid;
- margin-top: 1rem;
-}
-
-.divider {
- border-top: 1px solid #e2e8f0;
- margin-top: 1rem;
- margin-bottom: 1rem;
-}
diff --git a/tests_generated/test_all_default_parameters_on_netlify/.algokit.toml b/tests_generated/test_all_default_parameters_on_netlify/.algokit.toml
deleted file mode 100644
index 839cfe5..0000000
--- a/tests_generated/test_all_default_parameters_on_netlify/.algokit.toml
+++ /dev/null
@@ -1,2 +0,0 @@
-[algokit]
-min_version = "v1.3.0b1"
diff --git a/tests_generated/test_all_default_parameters_on_netlify/.copier-answers.yml b/tests_generated/test_all_default_parameters_on_netlify/.copier-answers.yml
deleted file mode 100644
index fffc018..0000000
--- a/tests_generated/test_all_default_parameters_on_netlify/.copier-answers.yml
+++ /dev/null
@@ -1,21 +0,0 @@
-# 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
-cloud_provider: netlify
-ide_vscode: true
-indexer_port: 8980
-indexer_server: http://localhost
-indexer_token: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-project_name: test_all_default_parameters_on_netlify
-use_daisy_ui: true
-use_eslint_prettier: true
-use_github_actions: true
-use_jest: true
-use_playwright: true
-use_tailwind: true
-
diff --git a/tests_generated/test_all_default_parameters_on_vercel/.algokit.toml b/tests_generated/test_all_default_parameters_on_vercel/.algokit.toml
deleted file mode 100644
index 839cfe5..0000000
--- a/tests_generated/test_all_default_parameters_on_vercel/.algokit.toml
+++ /dev/null
@@ -1,2 +0,0 @@
-[algokit]
-min_version = "v1.3.0b1"
diff --git a/tests_generated/test_all_default_parameters_on_vercel/.copier-answers.yml b/tests_generated/test_all_default_parameters_on_vercel/.copier-answers.yml
deleted file mode 100644
index d2c54ed..0000000
--- a/tests_generated/test_all_default_parameters_on_vercel/.copier-answers.yml
+++ /dev/null
@@ -1,21 +0,0 @@
-# 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
-cloud_provider: vercel
-ide_vscode: true
-indexer_port: 8980
-indexer_server: http://localhost
-indexer_token: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-project_name: test_all_default_parameters_on_vercel
-use_daisy_ui: true
-use_eslint_prettier: true
-use_github_actions: true
-use_jest: true
-use_playwright: true
-use_tailwind: true
-