33from dataclasses import dataclass
44from enum import IntEnum
55from functools import cached_property
6- from typing import Any , ClassVar , Dict , Generic , List , Literal , Sequence
6+ from typing import Any , ClassVar , Dict , Generic , List , Literal , Sequence , Union
77
88import ethereum_rlp as eth_rlp
99from coincurve .keys import PrivateKey , PublicKey
@@ -655,9 +655,27 @@ class NetworkWrappedTransaction(CamelModel, RLPSerializable):
655655 """
656656
657657 tx : Transaction
658- wrapper_version : Literal [ 1 ] | None = None
658+ wrapper_version : Union [ Bytes | None ] = None
659659 blobs : Sequence [Blob ]
660660
661+ @computed_field # type: ignore[prop-decorator]
662+ @property
663+ def blob_wrapper_version (self ) -> bytes | None :
664+ """Return the wrapper version (byte 1 for Osaka, None pre-Osaka)."""
665+ # TODO: it could be a mix of blobs from different forks, then what would be the wrapper version?
666+ if len (self .blobs ) == 0 :
667+ return None
668+
669+ fork = self .blobs [0 ].fork
670+ amount_cell_proofs = fork .get_blob_constant ("AMOUNT_CELL_PROOFS" )
671+ assert isinstance (amount_cell_proofs , int ), (
672+ f"Expected AMOUNT_CELL_PROOFS of fork { fork } to be an int but this is not the case!"
673+ )
674+ if amount_cell_proofs > 0 :
675+ return bytes ([1 ])
676+
677+ return None
678+
661679 @computed_field # type: ignore[prop-decorator]
662680 @property
663681 def blob_data (self ) -> Sequence [Bytes ]:
@@ -672,13 +690,24 @@ def blob_kzg_commitments(self) -> Sequence[Bytes]:
672690
673691 @computed_field # type: ignore[prop-decorator]
674692 @property
675- def blob_kzg_proofs (self ) -> Sequence [Sequence [ Bytes ]] | Sequence [Bytes ]:
693+ def blob_kzg_proofs (self ) -> Sequence [Bytes | Sequence [Bytes ] ]:
676694 """Return a list of kzg proofs."""
677- proofs : List [ List [ Bytes ]] | List [Bytes ] = []
695+ proofs : list [ Bytes | list [Bytes ] ] = []
678696 for blob in self .blobs :
679- proofs .append (blob .proof ) # type: ignore[arg-type]
697+ proofs .append (blob .proof )
698+
680699 return proofs
681700
701+ @computed_field # type: ignore[prop-decorator]
702+ @property
703+ def blob_cells (self ) -> Sequence [Sequence [Bytes ] | None ]:
704+ """Return a list of cells."""
705+ cells : list [list [Bytes ] | None ] = []
706+ for blob in self .blobs :
707+ cells .append (blob .cells )
708+
709+ return cells
710+
682711 def get_rlp_fields (self ) -> List [str ]:
683712 """
684713 Return an ordered list of field names to be included in RLP serialization.
@@ -689,10 +718,14 @@ def get_rlp_fields(self) -> List[str]:
689718
690719 The list can be nested list up to one extra level to represent nested fields.
691720 """
692- wrapper = []
693- if self .wrapper_version is not None :
694- wrapper = ["wrapper_version" ]
695- return ["tx" , * wrapper , "blob_data" , "blob_kzg_commitments" , "blob_kzg_proofs" ]
721+ return [ # structure explained in https://eips.ethereum.org/EIPS/eip-7594#Networking
722+ "tx" , # tx_payload_body
723+ "blob_wrapper_version" , # wrapper_version, which is always 1 for osaka (was it non-existing before?)
724+ "blob_data" , # blobs
725+ "blob_kzg_commitments" , # commitments
726+ "blob_kzg_proofs" , # cell_proofs
727+ "blob_cells" ,
728+ ]
696729
697730 def get_rlp_prefix (self ) -> bytes :
698731 """
0 commit comments