Skip to content

Commit a178338

Browse files
committed
feat: add support for populate-resources
See algorand/algorand-sdk-testing#319 for the test scenario
1 parent a2d610c commit a178338

File tree

4 files changed

+103
-1
lines changed

4 files changed

+103
-1
lines changed

algosdk/atomic_transaction_composer.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from abc import ABC, abstractmethod
22
import base64
33
import copy
4+
from dataclasses import dataclass
45
from enum import IntEnum
56
from typing import (
67
Any,
@@ -25,6 +26,18 @@
2526
T = TypeVar("T")
2627

2728

29+
@dataclass(kw_only=True)
30+
class PopulatedResourceArrays:
31+
"""
32+
Contains the populated resource arrays when `populate_resources` is set to true on a simulate request
33+
"""
34+
35+
apps: list[int]
36+
accounts: list[str]
37+
assets: list[int]
38+
boxes: list[tuple[int, bytes]]
39+
40+
2841
def populate_foreign_array(
2942
value_to_add: T, foreign_array: List[T], zero_value: Optional[T] = None
3043
) -> int:
@@ -322,6 +335,8 @@ def __init__(
322335
results: List[SimulateABIResult],
323336
eval_overrides: Optional[SimulateEvalOverrides] = None,
324337
exec_trace_config: Optional[models.SimulateTraceConfig] = None,
338+
extra_resource_arrays: list[PopulatedResourceArrays] | None = None,
339+
populated_resource_arrays: list[PopulatedResourceArrays] | None = None,
325340
) -> None:
326341
self.version = version
327342
self.failure_message = failure_message
@@ -331,6 +346,8 @@ def __init__(
331346
self.abi_results = results
332347
self.eval_overrides = eval_overrides
333348
self.exec_trace_config = exec_trace_config
349+
self.extra_resource_arrays = extra_resource_arrays
350+
self.populated_resource_arrays = populated_resource_arrays
334351

335352

336353
class AtomicTransactionComposer:
@@ -823,6 +840,40 @@ def simulate(
823840
)
824841
)
825842

843+
populated_resource_arrays = []
844+
for txn in txn_group["txn-results"]:
845+
if txn.get("populated-resource-arrays"):
846+
populated_resource_arrays.append(
847+
PopulatedResourceArrays(
848+
apps=txn["populated-resource-arrays"].get("apps", []),
849+
accounts=txn["populated-resource-arrays"].get(
850+
"accounts", []
851+
),
852+
assets=txn["populated-resource-arrays"].get(
853+
"assets", []
854+
),
855+
boxes=[
856+
(b["app"], base64.b64decode(b["name"]))
857+
for b in txn["populated-resource-arrays"].get(
858+
"boxes", []
859+
)
860+
],
861+
)
862+
)
863+
864+
extra_resource_arrays = []
865+
for arrays in txn_group.get("extra-resource-arrays", []):
866+
extra_resource_arrays.append(
867+
PopulatedResourceArrays(
868+
apps=arrays.get("apps", []),
869+
accounts=arrays.get("accounts", []),
870+
assets=arrays.get("assets", []),
871+
boxes=[
872+
(b["app"], base64.b64decode(b["name"]))
873+
for b in arrays.get("boxes", [])
874+
],
875+
)
876+
)
826877
return SimulateAtomicTransactionResponse(
827878
version=simulation_result.get("version", 0),
828879
failure_message=txn_group.get("failure-message", ""),
@@ -834,6 +885,8 @@ def simulate(
834885
simulation_result
835886
),
836887
exec_trace_config=exec_trace_config,
888+
extra_resource_arrays=extra_resource_arrays,
889+
populated_resource_arrays=populated_resource_arrays,
837890
)
838891

839892
def execute(

algosdk/v2client/models/simulate_request.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ def __init__(
7272
allow_unnamed_resources: bool = False,
7373
extra_opcode_budget: int = 0,
7474
exec_trace_config: Optional[SimulateTraceConfig] = None,
75+
populate_resources: bool = False,
7576
) -> None:
7677
self.txn_groups = txn_groups
7778
self.round = round
@@ -82,6 +83,7 @@ def __init__(
8283
self.exec_trace_config = (
8384
exec_trace_config if exec_trace_config else SimulateTraceConfig()
8485
)
86+
self.populate_resources = populate_resources
8587

8688
def dictify(self) -> Dict[str, Any]:
8789
return {
@@ -94,4 +96,5 @@ def dictify(self) -> Dict[str, Any]:
9496
"allow-empty-signatures": self.allow_empty_signatures,
9597
"extra-opcode-budget": self.extra_opcode_budget,
9698
"exec-trace-config": self.exec_trace_config.dictify(),
99+
"populate-resources": self.populate_resources,
97100
}

tests/integration.tags

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@
1818
@simulate.lift_log_limits
1919
@simulate.extra_opcode_budget
2020
@simulate.exec_trace_with_stack_scratch
21-
@simulate.exec_trace_with_state_change_and_hash
21+
@simulate.exec_trace_with_state_change_and_hash
22+
@simulate.populate_resources

tests/steps/other_v2_steps.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2036,3 +2036,48 @@ def get_ledger_state_delta_for_transaction_group(context, id):
20362036
@when("we make a GetBlockTxids call against block number {round}")
20372037
def get_block_txids_call(context, round):
20382038
context.response = context.acl.get_block_txids(round)
2039+
2040+
2041+
@when('I set unnamed-resources "{value}"')
2042+
def step_impl(context, value):
2043+
context.simulate_request.allow_unnamed_resources = value == "true"
2044+
2045+
2046+
@when('I set populate-resources "{value}"')
2047+
def step_impl(context, value):
2048+
context.simulate_request.populate_resources = value == "true"
2049+
2050+
2051+
@then(
2052+
"the response should include populated-resource-arrays for the transaction"
2053+
)
2054+
def step_impl(context):
2055+
resp: SimulateAtomicTransactionResponse = (
2056+
context.atomic_transaction_composer_return
2057+
)
2058+
assert len(resp.populated_resource_arrays) == 1
2059+
2060+
resources = resp.populated_resource_arrays[0]
2061+
assert resources.apps == [10000, 20000, 30000]
2062+
assert resources.accounts == [
2063+
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ",
2064+
"AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKE3PRHE",
2065+
"AIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGFFWAF4",
2066+
"AMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANVWEXNA",
2067+
]
2068+
assert resources.boxes == [(context.current_application_id, b"box_key")]
2069+
assert resources.assets == []
2070+
2071+
2072+
@then("the response should include extra-resource-arrays for the group")
2073+
def step_impl(context):
2074+
resp: SimulateAtomicTransactionResponse = (
2075+
context.atomic_transaction_composer_return
2076+
)
2077+
assert len(resp.extra_resource_arrays) == 1
2078+
assert resp.extra_resource_arrays[0].apps == [40000]
2079+
assert resp.extra_resource_arrays[0].accounts == [
2080+
"AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJVBPJXY"
2081+
]
2082+
assert resp.extra_resource_arrays[0].assets == [10001]
2083+
assert resp.extra_resource_arrays[0].boxes == [(0, b"")]

0 commit comments

Comments
 (0)