@@ -3,13 +3,16 @@ use perpetuals::core::types::asset::AssetId;
33use perpetuals :: core :: types :: asset :: synthetic :: {AssetBalanceDiffEnriched , AssetBalanceInfo };
44use perpetuals :: core :: types :: balance :: {Balance , BalanceDiff };
55use perpetuals :: core :: types :: funding :: FundingIndex ;
6- use starknet :: ContractAddress ;
7- use starknet :: storage :: {Mutable , StoragePath , StoragePointerReadAccess };
6+ use starknet :: storage :: {Mutable , StoragePath , StoragePointer0Offset , StoragePointerReadAccess };
7+ use starknet :: storage_access :: storage_address_from_base_and_offset;
8+ use starknet :: syscalls :: storage_read_syscall;
9+ use starknet :: {ContractAddress , SyscallResultTrait };
810use starkware_utils :: signature :: stark :: PublicKey ;
911use starkware_utils :: storage :: iterable_map :: {
1012 IterableMap , IterableMapIntoIterImpl , IterableMapReadAccessImpl , IterableMapWriteAccessImpl ,
1113};
1214
15+
1316pub const POSITION_VERSION : u8 = 1 ;
1417
1518#[starknet:: storage_node]
@@ -148,3 +151,122 @@ pub impl PositionMutableImpl of PositionMutableTrait {
148151 self . version. read ()
149152 }
150153}
154+
155+ #[generate_trait]
156+ pub impl OptionAssetBalanceReadAccessImpl of OptionAssetBalanceReadAccessTrait {
157+ /// Reads the Option<AssetBalance> from the storage.
158+ /// The offset is used to read specific fields of the struct.
159+ #[inline]
160+ fn read (
161+ entry : StoragePointer0Offset <Option <AssetBalance >>, offset : OptionAssetBalanceOffset ,
162+ ) -> felt252 {
163+ storage_read_syscall (
164+ 0 ,
165+ storage_address_from_base_and_offset (entry . __storage_pointer_address__, offset . into ()),
166+ )
167+ . unwrap_syscall ()
168+ }
169+
170+ /// Reads the variant of the Option<AssetBalance>.
171+ /// The variant mark if the Option is Some or None.
172+ #[inline]
173+ fn read_variant (entry : StoragePointer0Offset <Option <AssetBalance >>) -> felt252 {
174+ Self :: read (entry , OptionAssetBalanceOffset :: VARIANT )
175+ }
176+
177+ /// Returns true if the Option is Some, false if None.
178+ /// At the storage 0 indicates None, 1 indicates Some.
179+ #[inline]
180+ fn is_some (entry : StoragePointer0Offset <Option <AssetBalance >>) -> bool {
181+ let variant = Self :: read_variant (entry );
182+ variant == 1
183+ }
184+
185+ /// Returns true if the Option is None, false if Some.
186+ /// At the storage 0 indicates None, 1 indicates Some.
187+ #[inline]
188+ fn is_none (entry : StoragePointer0Offset <Option <AssetBalance >>) -> bool {
189+ let variant = Self :: read_variant (entry );
190+ variant == 0
191+ }
192+
193+ /// Reads the funding index from the Option<AssetBalance>.
194+ /// This function does not check if the Option is Some or None.
195+ fn at_funding_index (entry : StoragePointer0Offset <Option <AssetBalance >>) -> FundingIndex {
196+ let funding_index = Self :: read (entry , OptionAssetBalanceOffset :: FUNDING_INDEX );
197+ let funding_index : i64 = funding_index . try_into (). unwrap ();
198+ funding_index . into ()
199+ }
200+
201+ /// Gets the funding index from the Option<AssetBalance>.
202+ /// Returns None if the Option is None.
203+ fn get_funding_index (
204+ entry : StoragePointer0Offset <Option <AssetBalance >>,
205+ ) -> Option <FundingIndex > {
206+ if Self :: is_none (entry ) {
207+ return Option :: None ;
208+ }
209+ Option :: Some (Self :: at_funding_index (entry ))
210+ }
211+
212+ /// Reads the balance from the Option<AssetBalance>.
213+ /// This function does not check if the Option is Some or None.
214+ fn at_balance (entry : StoragePointer0Offset <Option <AssetBalance >>) -> Balance {
215+ let balance = Self :: read (entry , OptionAssetBalanceOffset :: BALANCE );
216+ let balance : i64 = balance . try_into (). unwrap ();
217+ balance . into ()
218+ }
219+
220+ /// Gets the balance from the Option<AssetBalance>.
221+ /// Returns None if the Option is None.
222+ fn get_balance (entry : StoragePointer0Offset <Option <AssetBalance >>) -> Option <Balance > {
223+ if Self :: is_none (entry ) {
224+ return Option :: None ;
225+ }
226+ Option :: Some (Self :: at_balance (entry ))
227+ }
228+
229+ /// Reads the version from the Option<AssetBalance>.
230+ /// This function does not check if the Option is Some or None.
231+ fn at_version (entry : StoragePointer0Offset <Option <AssetBalance >>) -> u8 {
232+ let version = Self :: read (entry , OptionAssetBalanceOffset :: VERSION );
233+ let version : u8 = version . try_into (). unwrap ();
234+ version
235+ }
236+
237+ /// Gets the version from the Option<AssetBalance>.
238+ /// Returns None if the Option is None.
239+ fn get_version (entry : StoragePointer0Offset <Option <AssetBalance >>) -> Option <u8 > {
240+ if Self :: is_none (entry ) {
241+ return Option :: None ;
242+ }
243+ Option :: Some (Self :: at_version (entry ))
244+ }
245+ }
246+
247+ /// In the storage, the Option<AssetBalance> is stored as a struct with the following layout:
248+ /// - variant: u8 (1 for Some, 0 for None)
249+ /// - version: u8
250+ /// - balance: i64
251+ /// - funding_index: i64
252+ /// The offsets are used to read specific fields of the struct.
253+ #[derive(Copy , Drop , Debug , PartialEq , Serde )]
254+ pub enum OptionAssetBalanceOffset {
255+ VARIANT ,
256+ VERSION ,
257+ BALANCE ,
258+ FUNDING_INDEX ,
259+ }
260+
261+
262+ /// Convert the enum to u8 for storage access.
263+ pub impl OptionAssetBalanceOffsetIntoU8 of Into <OptionAssetBalanceOffset , u8 > {
264+ fn into (self : OptionAssetBalanceOffset ) -> u8 {
265+ match self {
266+ OptionAssetBalanceOffset :: VARIANT => 0_u8 ,
267+ OptionAssetBalanceOffset :: VERSION => 1_u8 ,
268+ OptionAssetBalanceOffset :: BALANCE => 2_u8 ,
269+ OptionAssetBalanceOffset :: FUNDING_INDEX => 3_u8 ,
270+ }
271+ }
272+ }
0 commit comments