Skip to content

Commit 096a9ee

Browse files
committed
refactor(algod-client): restructure block models to align with JS SDK
Align Python block model structure with the JavaScript SDK and OpenAPI spec for cross-SDK consistency. Structural changes: - Rename GetBlock -> BlockResponse (matches OAS spec + JS/TS SDKs) - Add TxnCommitments nested type for transaction roots (txn, txn256) - Add RewardState nested type for reward fields (fees, rwd, earn, etc.) - Add UpgradeState nested type for protocol upgrade state - Add UpgradeVote nested type for upgrade vote parameters - Refactor BlockHeader to use flattened nested types - Change BlockEvalDelta.bytes -> bytes_value (avoid Python keyword) - Fix inner_txns type: SignedTxnInBlock -> SignedTxnWithAD - Make previous_block_hash and genesis_hash non-optional with defaults - Fix get_block() to return BlockResponse (typed) instead of Block - Export typed BlockResponse from _block.py instead of untyped version BREAKING CHANGE: - GetBlock removed, use BlockResponse instead - Field access patterns changed in BlockHeader: - header.fee_sink -> header.reward_state.fee_sink - header.current_protocol -> header.upgrade_state.current_protocol - header.upgrade_propose -> header.upgrade_vote.upgrade_propose - header.transactions_root -> header.txn_commitments.transactions_root - Block response structure: result.header -> result.block.header
1 parent 9de43f5 commit 096a9ee

File tree

9 files changed

+192
-64
lines changed

9 files changed

+192
-64
lines changed

api/oas-generator/src/oas_generator/builder.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -936,11 +936,11 @@ def _build_response(self, responses: dict[str, Any], operation_id: str) -> ctx.R
936936
self.uses_block_models = True
937937
media_types = media_types or ["application/json"]
938938
return ctx.ResponseDescriptor(
939-
type_hint="models.GetBlock",
939+
type_hint="models.BlockResponse",
940940
media_types=media_types,
941941
description=payload.get("description"),
942942
is_binary=False,
943-
model="GetBlock",
943+
model="BlockResponse",
944944
)
945945
if schema is None:
946946
return None

api/oas-generator/src/oas_generator/renderer/engine.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,12 @@
1717

1818
class TemplateRenderer:
1919
BLOCK_MODEL_EXPORTS: ClassVar[list[str]] = [
20-
"ApplyData",
21-
"BlockEvalDelta",
22-
"BlockStateDelta",
23-
"BlockAccountStateDelta",
24-
"BlockAppEvalDelta",
25-
"BlockStateProofTrackingData",
2620
"BlockStateProofTracking",
2721
"ParticipationUpdates",
2822
"SignedTxnInBlock",
2923
"BlockHeader",
3024
"Block",
31-
"GetBlock",
25+
"BlockResponse",
3226
]
3327
LEDGER_STATE_DELTA_EXPORTS: ClassVar[list[str]] = [
3428
"LedgerTealValue",

api/oas-generator/src/oas_generator/renderer/templates/models/block.py.j2

Lines changed: 67 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,17 @@ __all__ = [
2626
"BlockAppEvalDelta",
2727
"BlockStateProofTrackingData",
2828
"BlockStateProofTracking",
29+
"TxnCommitments",
30+
"RewardState",
31+
"UpgradeState",
32+
"UpgradeVote",
2933
"ParticipationUpdates",
3034
"ApplyData",
3135
"SignedTxnWithAD",
3236
"SignedTxnInBlock",
3337
"BlockHeader",
3438
"Block",
35-
"GetBlock",
39+
"BlockResponse",
3640
]
3741

3842

@@ -118,7 +122,7 @@ class BlockEvalDelta:
118122
"""Represents a TEAL value delta within block state changes."""
119123

120124
action: int = field(metadata=wire("at", required=True))
121-
bytes: str | None = field(default=None, metadata=wire("bs"))
125+
bytes_value: bytes | None = field(default=None, metadata=wire("bs"))
122126
uint: int | None = field(default=None, metadata=wire("ui"))
123127

124128

@@ -179,6 +183,46 @@ class SignedTxnWithAD:
179183
apply_data: ApplyData | None = field(default=None, metadata=flatten(lambda: ApplyData))
180184

181185

186+
@dataclass(slots=True)
187+
class TxnCommitments:
188+
"""Transaction commitment hashes for the block."""
189+
190+
transactions_root: bytes = field(default_factory=lambda: bytes(32), metadata=wire("txn"))
191+
transactions_root_sha256: bytes = field(default_factory=lambda: bytes(32), metadata=wire("txn256"))
192+
193+
194+
@dataclass(slots=True)
195+
class RewardState:
196+
"""Reward distribution state for the block."""
197+
198+
fee_sink: str | None = field(default=None, metadata=addr("fees"))
199+
rewards_pool: str | None = field(default=None, metadata=addr("rwd"))
200+
rewards_level: int | None = field(default=None, metadata=wire("earn"))
201+
rewards_rate: int | None = field(default=None, metadata=wire("rate"))
202+
rewards_residue: int | None = field(default=None, metadata=wire("frac"))
203+
rewards_recalculation_round: int | None = field(default=None, metadata=wire("rwcalr"))
204+
205+
206+
@dataclass(slots=True)
207+
class UpgradeState:
208+
"""Protocol upgrade state for the block."""
209+
210+
current_protocol: str | None = field(default=None, metadata=wire("proto"))
211+
next_protocol: str | None = field(default=None, metadata=wire("nextproto"))
212+
next_protocol_approvals: int | None = field(default=None, metadata=wire("nextyes"))
213+
next_protocol_vote_before: int | None = field(default=None, metadata=wire("nextbefore"))
214+
next_protocol_switch_on: int | None = field(default=None, metadata=wire("nextswitch"))
215+
216+
217+
@dataclass(slots=True)
218+
class UpgradeVote:
219+
"""Protocol upgrade vote parameters for the block."""
220+
221+
upgrade_propose: str | None = field(default=None, metadata=wire("upgradeprop"))
222+
upgrade_delay: int | None = field(default=None, metadata=wire("upgradedelay"))
223+
upgrade_approve: bool | None = field(default=None, metadata=wire("upgradeyes"))
224+
225+
182226
@dataclass(slots=True)
183227
class ParticipationUpdates:
184228
"""Participation account updates embedded in a block."""
@@ -216,12 +260,12 @@ class BlockAppEvalDelta:
216260
decode=_decode_local_deltas,
217261
),
218262
)
219-
inner_txns: list[SignedTxnInBlock] | None = field(
263+
inner_txns: list[SignedTxnWithAD] | None = field(
220264
default=None,
221265
metadata=wire(
222266
"itx",
223267
encode=encode_model_sequence,
224-
decode=lambda raw: decode_model_sequence(lambda: SignedTxnInBlock, raw),
268+
decode=lambda raw: decode_model_sequence(lambda: SignedTxnWithAD, raw),
225269
),
226270
)
227271
shared_accounts: tuple[str, ...] | None = field(default=None, metadata=addr_seq("sa"))
@@ -232,34 +276,34 @@ class BlockAppEvalDelta:
232276
class BlockHeader:
233277
"""Block header fields."""
234278

235-
transactions_root: bytes = field(metadata=wire("txn", required=True))
236279
round: int | None = field(default=None, metadata=wire("rnd"))
237-
previous_block_hash: bytes | None = field(default=None, metadata=wire("prev"))
280+
txn_commitments: TxnCommitments = field(
281+
default_factory=TxnCommitments,
282+
metadata=flatten(lambda: TxnCommitments),
283+
)
284+
previous_block_hash: bytes = field(default_factory=lambda: bytes(32), metadata=wire("prev"))
238285
previous_block_hash_512: bytes | None = field(default=None, metadata=wire("prev512"))
239286
seed: bytes | None = field(default=None, metadata=wire("seed"))
240-
transactions_root_sha256: bytes | None = field(default=None, metadata=wire("txn256"))
241287
transactions_root_sha512: bytes | None = field(default=None, metadata=wire("txn512"))
242288
timestamp: int | None = field(default=None, metadata=wire("ts"))
243289
genesis_id: str | None = field(default=None, metadata=wire("gen"))
244-
genesis_hash: bytes | None = field(default=None, metadata=wire("gh"))
290+
genesis_hash: bytes = field(default_factory=lambda: bytes(32), metadata=wire("gh"))
245291
proposer: str | None = field(default=None, metadata=addr("prp"))
246292
fees_collected: int | None = field(default=None, metadata=wire("fc"))
247293
bonus: int | None = field(default=None, metadata=wire("bi"))
248294
proposer_payout: int | None = field(default=None, metadata=wire("pp"))
249-
fee_sink: str | None = field(default=None, metadata=addr("fees"))
250-
rewards_pool: str | None = field(default=None, metadata=addr("rwd"))
251-
rewards_level: int | None = field(default=None, metadata=wire("earn"))
252-
rewards_rate: int | None = field(default=None, metadata=wire("rate"))
253-
rewards_residue: int | None = field(default=None, metadata=wire("frac"))
254-
rewards_recalculation_round: int | None = field(default=None, metadata=wire("rwcalr"))
255-
current_protocol: str | None = field(default=None, metadata=wire("proto"))
256-
next_protocol: str | None = field(default=None, metadata=wire("nextproto"))
257-
next_protocol_approvals: int | None = field(default=None, metadata=wire("nextyes"))
258-
next_protocol_vote_before: int | None = field(default=None, metadata=wire("nextbefore"))
259-
next_protocol_switch_on: int | None = field(default=None, metadata=wire("nextswitch"))
260-
upgrade_propose: str | None = field(default=None, metadata=wire("upgradeprop"))
261-
upgrade_delay: int | None = field(default=None, metadata=wire("upgradedelay"))
262-
upgrade_approve: bool | None = field(default=None, metadata=wire("upgradeyes"))
295+
reward_state: RewardState = field(
296+
default_factory=RewardState,
297+
metadata=flatten(lambda: RewardState),
298+
)
299+
upgrade_state: UpgradeState = field(
300+
default_factory=UpgradeState,
301+
metadata=flatten(lambda: UpgradeState),
302+
)
303+
upgrade_vote: UpgradeVote = field(
304+
default_factory=UpgradeVote,
305+
metadata=flatten(lambda: UpgradeVote),
306+
)
263307
txn_counter: int | None = field(default=None, metadata=wire("tc"))
264308
state_proof_tracking: BlockStateProofTracking | None = field(
265309
default=None,
@@ -294,7 +338,7 @@ class Block:
294338

295339

296340
@dataclass(slots=True)
297-
class GetBlock:
341+
class BlockResponse:
298342
"""Response payload for the get block endpoint (with optional certificate)."""
299343

300344
block: Block = field(metadata=nested("block", lambda: Block))

src/algokit_algod_client/client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ def get_block(
455455
round_: int,
456456
*,
457457
header_only: bool | None = None,
458-
) -> models.GetBlock:
458+
) -> models.BlockResponse:
459459
"""
460460
Get the block for the given round.
461461
"""
@@ -483,7 +483,7 @@ def get_block(
483483

484484
response = self._request_with_retry(request_kwargs)
485485
if response.is_success:
486-
return self._decode_response(response, model=models.GetBlock)
486+
return self._decode_response(response, model=models.BlockResponse)
487487

488488
raise UnexpectedStatusError(response.status_code, response.text)
489489

src/algokit_algod_client/models/__init__.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,18 @@
3030
BlockAppEvalDelta,
3131
BlockEvalDelta,
3232
BlockHeader,
33+
BlockResponse,
3334
BlockStateDelta,
3435
BlockStateProofTracking,
3536
BlockStateProofTrackingData,
36-
GetBlock,
3737
ParticipationUpdates,
38+
RewardState,
3839
SignedTxnInBlock,
40+
TxnCommitments,
41+
UpgradeState,
42+
UpgradeVote,
3943
)
4044
from ._block_hash_response import BlockHashResponse
41-
from ._block_response import BlockResponse
4245
from ._block_txids_response import BlockTxidsResponse
4346
from ._box import Box
4447
from ._box_descriptor import BoxDescriptor
@@ -155,7 +158,6 @@
155158
"EvalDelta",
156159
"EvalDeltaKeyValue",
157160
"GenesisFileInJson",
158-
"GetBlock",
159161
"GetBlockTimeStampOffsetResponse",
160162
"GetSyncRoundResponse",
161163
"GetTransactionGroupLedgerStateDeltasForRound",
@@ -191,6 +193,7 @@
191193
"PendingTransactionResponse",
192194
"PendingTransactionsResponse",
193195
"PostTransactionsResponse",
196+
"RewardState",
194197
"ScratchChange",
195198
"SignedTransaction",
196199
"SignedTxnInBlock",
@@ -217,5 +220,8 @@
217220
"TransactionGroupLedgerStateDeltasForRoundResponse",
218221
"TransactionParametersResponse",
219222
"TransactionProof",
223+
"TxnCommitments",
224+
"UpgradeState",
225+
"UpgradeVote",
220226
"VersionContainsTheCurrentAlgodVersion",
221227
]

0 commit comments

Comments
 (0)