Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: AppClient, AppFactory, AppDeployer interface and various refinements on top of existing new interfaces #124

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ repos:
additional_dependencies: []
minimum_pre_commit_version: "0"
files: "^(src|tests)/"
exclude: "^tests/artifacts/"
- id: mypy
name: mypy
description: "`mypy` will check Python types for correctness"
Expand All @@ -33,3 +34,4 @@ repos:
additional_dependencies: []
minimum_pre_commit_version: "2.9.2"
files: "^(src|tests)/"
exclude: "^tests/artifacts/"
16 changes: 16 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: Debug Tests",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"purpose": [
"debug-test"
],
"console": "integratedTerminal",
"justMyCode": false
}
]
}
23 changes: 12 additions & 11 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,24 @@
"**/__pycache__": true,
".idea": true
},

// Python
"platformSettings.autoLoad": true,
"python.defaultInterpreterPath": "${workspaceFolder}/.venv",
"python.analysis.extraPaths": ["${workspaceFolder}/src"],
"python.analysis.extraPaths": [
"${workspaceFolder}/src"
],
"[python]": {
"editor.defaultFormatter": "charliermarsh.ruff"
},
"python.analysis.exclude": [
"tests/artifacts/**"
],
"python.analysis.typeCheckingMode": "basic",
"ruff.enable": true,
"ruff.lint.run": "onSave",
"ruff.lint.args": ["--config=pyproject.toml"],
"ruff.lint.args": [
"--config=pyproject.toml"
],
"ruff.importStrategy": "fromEnvironment",
"ruff.fixAll": true, //lint and fix all files in workspace
"ruff.organizeImports": true, //organize imports on save
Expand All @@ -37,7 +43,6 @@
"ruff.codeAction.fixViolation": {
"enable": true
},

"mypy.configFile": "pyproject.toml",
// set to empty array to use config from project
"mypy.targets": [],
Expand All @@ -52,11 +57,7 @@
}
]
},

// PowerShell
"[powershell]": {
"editor.defaultFormatter": "ms-vscode.powershell"
},
"powershell.codeFormatting.preset": "Stroustrup",
"python.testing.pytestArgs": ["."]
"python.testing.pytestArgs": [
"."
],
}
69 changes: 35 additions & 34 deletions docs/markdown/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,46 +7,47 @@ The goal of this library is to provide intuitive, productive utility functions t
Largely these functions wrap the underlying Algorand SDK, but provide a higher level interface with sensible defaults and capabilities for common tasks.

#### NOTE

If you prefer TypeScript there’s an equivalent [TypeScript utility library](https://github.com/algorandfoundation/algokit-utils-ts).

[Core principles]() | [Installation]() | [Usage]() | [Capabilities]() | [Reference docs]()

# Contents

* [Account management](capabilities/account.md)
* [`Account`](capabilities/account.md#account)
* [Client management](capabilities/client.md)
* [Network configuration](capabilities/client.md#network-configuration)
* [Clients](capabilities/client.md#clients)
* [App client](capabilities/app-client.md)
* [Design](capabilities/app-client.md#design)
* [Creating an application client](capabilities/app-client.md#creating-an-application-client)
* [Calling methods on the app](capabilities/app-client.md#calling-methods-on-the-app)
* [Composing calls](capabilities/app-client.md#composing-calls)
* [Reading state](capabilities/app-client.md#reading-state)
* [Handling logic errors and diagnosing errors](capabilities/app-client.md#handling-logic-errors-and-diagnosing-errors)
* [App deployment](capabilities/app-deploy.md)
* [Design](capabilities/app-deploy.md#design)
* [Finding apps by creator](capabilities/app-deploy.md#finding-apps-by-creator)
* [Deploying an application](capabilities/app-deploy.md#deploying-an-application)
* [Algo transfers](capabilities/transfer.md)
* [Transferring Algos](capabilities/transfer.md#transferring-algos)
* [Ensuring minimum Algos](capabilities/transfer.md#ensuring-minimum-algos)
* [Transfering Assets](capabilities/transfer.md#transfering-assets)
* [Dispenser](capabilities/transfer.md#dispenser)
* [TestNet Dispenser Client](capabilities/dispenser-client.md)
* [Creating a Dispenser Client](capabilities/dispenser-client.md#creating-a-dispenser-client)
* [Funding an Account](capabilities/dispenser-client.md#funding-an-account)
* [Registering a Refund](capabilities/dispenser-client.md#registering-a-refund)
* [Getting Current Limit](capabilities/dispenser-client.md#getting-current-limit)
* [Error Handling](capabilities/dispenser-client.md#error-handling)
* [Debugger](capabilities/debugger.md)
* [Configuration](capabilities/debugger.md#configuration)
* [Debugging Utilities](capabilities/debugger.md#debugging-utilities)
* [`algokit_utils`](apidocs/algokit_utils/algokit_utils.md)
* [Data](apidocs/algokit_utils/algokit_utils.md#data)
* [Classes](apidocs/algokit_utils/algokit_utils.md#classes)
* [Functions](apidocs/algokit_utils/algokit_utils.md#functions)
- [Account management](capabilities/account.md)
- [`Account`](capabilities/account.md#account)
- [Client management](capabilities/client.md)
- [Network configuration](capabilities/client.md#network-configuration)
- [Clients](capabilities/client.md#clients)
- [App client](capabilities/app-client.md)
- [Design](capabilities/app-client.md#design)
- [Creating an application client](capabilities/app-client.md#creating-an-application-client)
- [Calling methods on the app](capabilities/app-client.md#calling-methods-on-the-app)
- [Composing calls](capabilities/app-client.md#composing-calls)
- [Reading state](capabilities/app-client.md#reading-state)
- [Handling logic errors and diagnosing errors](capabilities/app-client.md#handling-logic-errors-and-diagnosing-errors)
- [App deployment](capabilities/app-deploy.md)
- [Design](capabilities/app-deploy.md#design)
- [Finding apps by creator](capabilities/app-deploy.md#finding-apps-by-creator)
- [Deploying an application](capabilities/app-deploy.md#deploying-an-application)
- [Algo transfers](capabilities/transfer.md)
- [Transferring Algos](capabilities/transfer.md#transferring-algos)
- [Ensuring minimum Algos](capabilities/transfer.md#ensuring-minimum-algos)
- [Transfering Assets](capabilities/transfer.md#transfering-assets)
- [Dispenser](capabilities/transfer.md#dispenser)
- [TestNet Dispenser Client](capabilities/dispenser-client.md)
- [Creating a Dispenser Client](capabilities/dispenser-client.md#creating-a-dispenser-client)
- [Funding an Account](capabilities/dispenser-client.md#funding-an-account)
- [Registering a Refund](capabilities/dispenser-client.md#registering-a-refund)
- [Getting Current Limit](capabilities/dispenser-client.md#getting-current-limit)
- [Error Handling](capabilities/dispenser-client.md#error-handling)
- [Debugger](capabilities/debugger.md)
- [Configuration](capabilities/debugger.md#configuration)
- [Debugging Utilities](capabilities/debugger.md#debugging-utilities)
- [`algokit_utils`](apidocs/algokit_utils/algokit_utils.md)
- [Data](apidocs/algokit_utils/algokit_utils.md#data)
- [Classes](apidocs/algokit_utils/algokit_utils.md#classes)
- [Functions](apidocs/algokit_utils/algokit_utils.md#functions)

<a id="core-principles"></a>

Expand Down
6 changes: 3 additions & 3 deletions legacy_v2_tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

import algosdk.transaction
import pytest
from dotenv import load_dotenv

from algokit_utils import (
DELETABLE_TEMPLATE_NAME,
UPDATABLE_TEMPLATE_NAME,
Expand All @@ -22,8 +24,6 @@
get_kmd_client_from_algod_client,
replace_template_variables,
)
from dotenv import load_dotenv

from legacy_v2_tests import app_client_test

if TYPE_CHECKING:
Expand Down Expand Up @@ -142,7 +142,7 @@ def indexer_client() -> "IndexerClient":
return get_indexer_client()


@pytest.fixture()
@pytest.fixture
def creator(algod_client: "AlgodClient") -> Account:
creator_name = get_unique_name()
return get_account(algod_client, creator_name)
Expand Down
1 change: 0 additions & 1 deletion legacy_v2_tests/test_account.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from typing import TYPE_CHECKING

from algokit_utils import get_account

from legacy_v2_tests.conftest import get_unique_name

if TYPE_CHECKING:
Expand Down
1 change: 1 addition & 0 deletions legacy_v2_tests/test_app.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import pytest

from algokit_utils import AppDeployMetaData


Expand Down
1 change: 1 addition & 0 deletions legacy_v2_tests/test_app_client.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import pytest

from algokit_utils import (
DeploymentFailedError,
get_next_version,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ Txn {txn} had error 'assert failed pc=743' at PC 743:

Could not determine TEAL source line for the error as no approval source map was provided, to receive a trace of the
error please provide an approval SourceMap. Either by:
1.) Providing template_values when creating the ApplicationClient, so a SourceMap can be obtained automatically OR
2.) Set approval_source_map from a previously compiled approval program OR
3.) Import a previously exported source map using import_source_map
1. Providing template_values when creating the ApplicationClient, so a SourceMap can be obtained automatically OR
2. Set approval_source_map from a previously compiled approval program OR
3. Import a previously exported source map using import_source_map
40 changes: 21 additions & 19 deletions legacy_v2_tests/test_app_client_call.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
from collections.abc import Generator
from hashlib import sha256
from pathlib import Path
from typing import TYPE_CHECKING
from unittest.mock import Mock, patch

import algokit_utils
import pytest
from algokit_utils import (
Account,
ApplicationClient,
ApplicationSpecification,
CreateCallParameters,
get_account,
)
from algosdk.atomic_transaction_composer import (
AccountTransactionSigner,
AtomicTransactionComposer,
TransactionWithSigner,
)
from algosdk.transaction import ApplicationCallTxn, PaymentTxn

import algokit_utils
import algokit_utils._legacy_v2
import algokit_utils._legacy_v2.logic_error
from algokit_utils import (
Account,
ApplicationClient,
ApplicationSpecification,
CreateCallParameters,
get_account,
)
from legacy_v2_tests.conftest import check_output_stability, get_unique_name

if TYPE_CHECKING:
Expand Down Expand Up @@ -84,7 +87,7 @@ def test_abi_call_with_transaction_arg(client_fixture: ApplicationClient, funded
sender=funded_account.address,
receiver=client_fixture.app_address,
amt=1_000_000,
note=b"Payment",
note=sha256(b"self-payment").digest(),
sp=client_fixture.algod_client.suggested_params(),
) # type: ignore[no-untyped-call]
payment_with_signer = TransactionWithSigner(payment, AccountTransactionSigner(funded_account.private_key))
Expand Down Expand Up @@ -186,7 +189,7 @@ def test_readonly_call(client_fixture: ApplicationClient) -> None:


def test_readonly_call_with_error(client_fixture: ApplicationClient) -> None:
with pytest.raises(algokit_utils.LogicError) as ex:
with pytest.raises(algokit_utils._legacy_v2.logic_error.LogicError) as ex: # noqa: SLF001
client_fixture.call(
"readonly",
error=1,
Expand All @@ -211,7 +214,7 @@ def test_readonly_call_with_error_with_new_client_provided_template_values(
)
new_client.approval_source_map = client.approval_source_map

with pytest.raises(algokit_utils.LogicError) as ex:
with pytest.raises(algokit_utils._legacy_v2.logic_error.LogicError) as ex: # noqa: SLF001
new_client.call(
"readonly",
error=1,
Expand All @@ -234,7 +237,7 @@ def test_readonly_call_with_error_with_new_client_provided_source_map(
new_client = ApplicationClient(algod_client, app_spec, app_id=client.app_id, signer=funded_account)
new_client.approval_source_map = client.approval_source_map

with pytest.raises(algokit_utils.LogicError) as ex:
with pytest.raises(algokit_utils._legacy_v2.logic_error.LogicError) as ex: # noqa: SLF001
new_client.call(
"readonly",
error=1,
Expand All @@ -259,7 +262,7 @@ def test_readonly_call_with_error_with_imported_source_map(
new_client = ApplicationClient(algod_client, app_spec, app_id=client.app_id, signer=funded_account)
new_client.import_source_map(source_map_export)

with pytest.raises(algokit_utils.LogicError) as ex:
with pytest.raises(algokit_utils._legacy_v2.logic_error.LogicError) as ex: # noqa: SLF001
new_client.call(
"readonly",
error=1,
Expand All @@ -281,7 +284,7 @@ def test_readonly_call_with_error_with_new_client_missing_source_map(

new_client = ApplicationClient(algod_client, app_spec, app_id=client.app_id, signer=funded_account)

with pytest.raises(algokit_utils.LogicError) as ex:
with pytest.raises(algokit_utils._legacy_v2.logic_error.LogicError) as ex: # noqa: SLF001
new_client.call(
"readonly",
error=1,
Expand All @@ -292,7 +295,7 @@ def test_readonly_call_with_error_with_new_client_missing_source_map(

def test_readonly_call_with_error_debug_mode_disabled(mock_config: Mock, client_fixture: ApplicationClient) -> None:
mock_config.debug = False
with pytest.raises(algokit_utils.LogicError) as ex:
with pytest.raises(algokit_utils._legacy_v2.logic_error.LogicError) as ex: # noqa: SLF001
client_fixture.call(
"readonly",
error=1,
Expand All @@ -302,7 +305,7 @@ def test_readonly_call_with_error_debug_mode_disabled(mock_config: Mock, client_


def test_readonly_call_with_error_debug_mode_enabled(client_fixture: ApplicationClient) -> None:
with pytest.raises(algokit_utils.LogicError) as ex:
with pytest.raises(algokit_utils._legacy_v2.logic_error.LogicError) as ex: # noqa: SLF001
client_fixture.call(
"readonly",
error=1,
Expand All @@ -322,7 +325,7 @@ def test_app_call_with_error_debug_mode_disabled(mock_config: Mock, client_fixtu
min_funding_increment_micro_algos=200_000,
),
)
with pytest.raises(algokit_utils.LogicError) as ex:
with pytest.raises(algokit_utils._legacy_v2.logic_error.LogicError) as ex: # noqa: SLF001
client_fixture.call(
"set_box",
name=b"ssss",
Expand All @@ -342,12 +345,11 @@ def test_app_call_with_error_debug_mode_enabled(client_fixture: ApplicationClien
min_funding_increment_micro_algos=200_000,
),
)
with pytest.raises(algokit_utils.LogicError) as ex:
with pytest.raises(algokit_utils._legacy_v2.logic_error.LogicError) as ex: # noqa: SLF001
client_fixture.call(
"set_box",
name=b"ssss",
value="test",
)

assert ex.value.traces is not None
assert ex.value.traces[0].exec_trace["approval-program-trace"] is not None
4 changes: 2 additions & 2 deletions legacy_v2_tests/test_app_client_clear_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@
from typing import TYPE_CHECKING

import pytest

from algokit_utils import (
Account,
ApplicationClient,
ApplicationSpecification,
)

from legacy_v2_tests.conftest import is_opted_in

if TYPE_CHECKING:
from algosdk.v2client.algod import AlgodClient
from algosdk.v2client.indexer import IndexerClient


@pytest.fixture()
@pytest.fixture
def client_fixture(
algod_client: "AlgodClient",
indexer_client: "IndexerClient",
Expand Down
4 changes: 2 additions & 2 deletions legacy_v2_tests/test_app_client_close_out.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
from typing import TYPE_CHECKING

import pytest

from algokit_utils import (
Account,
ApplicationClient,
ApplicationSpecification,
LogicError,
)

from legacy_v2_tests.conftest import check_output_stability, is_opted_in

if TYPE_CHECKING:
from algosdk.v2client.algod import AlgodClient
from algosdk.v2client.indexer import IndexerClient


@pytest.fixture()
@pytest.fixture
def client_fixture(
algod_client: "AlgodClient",
indexer_client: "IndexerClient",
Expand Down
Loading
Loading