Skip to content

Commit 08a8459

Browse files
committed
Merge remote-tracking branch 'origin/main' into decoupling
2 parents 8b266d1 + 6971b95 commit 08a8459

File tree

6 files changed

+92
-23
lines changed

6 files changed

+92
-23
lines changed

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,18 @@
22

33
<!--next-version-placeholder-->
44

5+
## v4.2.3 (2025-12-15)
6+
7+
### Fix
8+
9+
* Update urllib3 for audit issue ([#239](https://github.com/algorandfoundation/algokit-utils-py/issues/239)) ([`ab36d0c`](https://github.com/algorandfoundation/algokit-utils-py/commit/ab36d0cfca8998db7837f6a98c2be994c6af4f27))
10+
* Enable LocalNet dispensing after 30000 rounds ([#226](https://github.com/algorandfoundation/algokit-utils-py/issues/226)) ([`d1f8693`](https://github.com/algorandfoundation/algokit-utils-py/commit/d1f8693a6b6253f2dff9a34ba0e474109e789d40))
11+
* Use extra pages available when deploying ([#217](https://github.com/algorandfoundation/algokit-utils-py/issues/217)) ([`afda7ac`](https://github.com/algorandfoundation/algokit-utils-py/commit/afda7ac85a32ef676c5cbefa3616e93af8f81265))
12+
13+
### Documentation
14+
15+
* Remove html docs and gh pages; tweak md docstrings to convert to regular python code blocks ([#205](https://github.com/algorandfoundation/algokit-utils-py/issues/205)) ([`4db24ba`](https://github.com/algorandfoundation/algokit-utils-py/commit/4db24ba4e3193ea442a4b3492cf041c030551b1d))
16+
517
## v4.2.2 (2025-10-15)
618

719
### Fix

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "algokit-utils"
3-
version = "4.2.2"
3+
version = "4.2.3"
44
description = "Utilities for Algorand development for use by AlgoKit"
55
authors = [
66
{ name = "Algorand Foundation", email = "contact@algorand.foundation" },

src/algokit_utils/accounts/kmd_account_manager.py

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,39 @@ def get_wallet_account(
6969
7070
:raises Exception: If error received while exporting the private key from KMD
7171
"""
72+
return self._find_wallet_account(
73+
wallet_name,
74+
predicate,
75+
sender,
76+
)
77+
78+
def _find_matching_address(
79+
self,
80+
addresses: list[str],
81+
predicate_or_address: Callable[[dict[str, Any]], bool] | str | None,
82+
) -> str | None:
83+
"""Find a matching address from a list based on a predicate, specific address, or return the first one."""
84+
if not addresses:
85+
return None
86+
87+
if callable(predicate_or_address):
88+
for address in addresses:
89+
account_info = self._client_manager.algod.account_information(address)
90+
if predicate_or_address(to_wire(account_info)):
91+
return address
92+
return None
93+
94+
if isinstance(predicate_or_address, str):
95+
return predicate_or_address if predicate_or_address in addresses else None
96+
97+
return addresses[0]
7298

99+
def _find_wallet_account(
100+
self,
101+
wallet_name: str,
102+
predicate_or_address: Callable[[dict[str, Any]], bool] | str | None = None,
103+
sender: str | None = None,
104+
) -> AddressWithSigners | None:
73105
kmd_client = self.kmd()
74106
wallets = kmd_client.list_wallets().wallets or []
75107
wallet = next((w for w in wallets if w.name == wallet_name), None)
@@ -80,16 +112,7 @@ def get_wallet_account(
80112
wallet_handle = kmd_client.init_wallet_handle(InitWalletHandleTokenRequest(wallet_id, "")).wallet_handle_token
81113
addresses = kmd_client.list_keys_in_wallet(ListKeysRequest(wallet_handle)).addresses or []
82114

83-
matched_address = None
84-
if predicate:
85-
for address in addresses:
86-
account_info = self._client_manager.algod.account_information(address)
87-
if predicate(to_wire(account_info)):
88-
matched_address = address
89-
break
90-
else:
91-
matched_address = next(iter(addresses), None)
92-
115+
matched_address = self._find_matching_address(addresses, predicate_or_address)
93116
if not matched_address:
94117
return None
95118

@@ -171,11 +194,15 @@ def get_localnet_dispenser_account(self) -> AddressWithSigners:
171194
if not self._client_manager.is_localnet():
172195
raise Exception("Can't get LocalNet dispenser account from non LocalNet network")
173196

174-
dispenser = self.get_wallet_account(
175-
"unencrypted-default-wallet",
176-
lambda a: a["status"] != "Offline" and a["amount"] > 1_000_000_000, # noqa: PLR2004
177-
)
178-
if not dispenser:
179-
raise Exception("Error retrieving LocalNet dispenser account; couldn't find the default account in KMD")
197+
genesis_response = self._client_manager.algod.get_genesis()
198+
dispenser_addresses = [a.addr for a in genesis_response.alloc if a.comment == "Wallet1"]
199+
200+
if dispenser_addresses:
201+
dispenser = self._find_wallet_account(
202+
"unencrypted-default-wallet",
203+
dispenser_addresses[0],
204+
)
205+
if dispenser:
206+
return dispenser
180207

181-
return dispenser
208+
raise Exception("Error retrieving LocalNet dispenser account; couldn't find the default account in KMD")

src/algokit_utils/applications/app_deployer.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -317,9 +317,9 @@ def deploy(self, deployment: AppDeployParams) -> AppDeployResult:
317317

318318
existing_approval = base64.b64encode(existing_app_record.approval_program).decode()
319319
existing_clear = base64.b64encode(existing_app_record.clear_state_program).decode()
320-
existing_extra_pages = calculate_extra_program_pages(
321-
existing_app_record.approval_program, existing_app_record.clear_state_program
322-
)
320+
extra_pages = existing_app_record.extra_program_pages or 0
321+
322+
calculate_extra_program_pages(existing_app_record.approval_program, existing_app_record.clear_state_program)
323323

324324
new_approval = base64.b64encode(approval_program).decode()
325325
new_clear = base64.b64encode(clear_program).decode()
@@ -335,7 +335,7 @@ def deploy(self, deployment: AppDeployParams) -> AppDeployResult:
335335
< (deployment.create_params.schema.get("local_byte_slices", 0) if deployment.create_params.schema else 0)
336336
or existing_app_record.global_byte_slices
337337
< (deployment.create_params.schema.get("global_byte_slices", 0) if deployment.create_params.schema else 0)
338-
or existing_extra_pages < new_extra_pages
338+
or extra_pages < new_extra_pages
339339
)
340340

341341
if is_schema_break:

tests/applications/test_app_factory.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,36 @@ def test_deploy_app_update_detects_extra_pages_as_breaking_change(
271271
assert small_client.app_id != large_client.app_id
272272

273273

274+
def test_deploy_app_update_detects_extra_page_surplus_as_non_breaking_change(
275+
algorand: AlgorandClient, funded_account: AddressWithSigners
276+
) -> None:
277+
small_app_spec = (Path(__file__).parent.parent / "artifacts" / "extra_pages_test" / "small.arc56.json").read_text()
278+
large_app_spec = (Path(__file__).parent.parent / "artifacts" / "extra_pages_test" / "large.arc56.json").read_text()
279+
factory = algorand.client.get_app_factory(
280+
app_spec=small_app_spec,
281+
default_sender=funded_account.addr,
282+
)
283+
small_client, create_deploy_result = factory.deploy(
284+
compilation_params={
285+
"updatable": True,
286+
},
287+
create_params=AppClientBareCallCreateParams(extra_program_pages=1),
288+
)
289+
assert create_deploy_result.operation_performed == OperationPerformed.Create
290+
assert create_deploy_result.create_result
291+
292+
factory._app_spec = arc56.Arc56Contract.from_json(large_app_spec) # noqa: SLF001
293+
large_client, update_deploy_result = factory.deploy(
294+
compilation_params={
295+
"updatable": True,
296+
},
297+
on_schema_break=OnSchemaBreak.AppendApp,
298+
on_update=OnUpdate.UpdateApp,
299+
)
300+
assert update_deploy_result.operation_performed == OperationPerformed.Update
301+
assert small_client.app_id == large_client.app_id
302+
303+
274304
def test_deploy_app_update_abi(factory: AppFactory) -> None:
275305
_, create_deploy_result = factory.deploy(
276306
compilation_params={

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)