1use std::{
19 collections::hash_map::DefaultHasher,
20 hash::{Hash, Hasher},
21 sync::Arc,
22};
23
24use nautilus_core::python::to_pyvalue_err;
25use pyo3::{basic::CompareOp, prelude::*};
26
27use crate::{
28 defi::{
29 Chain, Dex,
30 chain::Blockchain,
31 data::{
32 Block, DefiData, PoolFeeCollect, PoolFlash, PoolLiquidityUpdate,
33 PoolLiquidityUpdateType, PoolSwap, Transaction,
34 },
35 },
36 identifiers::InstrumentId,
37};
38
39#[pymethods]
40#[pyo3_stub_gen::derive::gen_stub_pymethods]
41impl Block {
42 #[new]
44 #[expect(clippy::too_many_arguments)]
45 fn py_new(
46 chain: Blockchain,
47 hash: String,
48 parent_hash: String,
49 number: u64,
50 miner: String,
51 gas_limit: u64,
52 gas_used: u64,
53 timestamp: u64,
54 ) -> Self {
55 Self::new(
56 hash,
57 parent_hash,
58 number,
59 miner.into(),
60 gas_limit,
61 gas_used,
62 timestamp.into(),
63 Some(chain),
64 )
65 }
66
67 #[getter]
69 #[pyo3(name = "chain")]
70 fn py_chain(&self) -> Option<Blockchain> {
71 self.chain
72 }
73
74 #[getter]
75 #[pyo3(name = "hash")]
76 fn py_hash(&self) -> &str {
77 &self.hash
78 }
79
80 #[getter]
81 #[pyo3(name = "number")]
82 fn py_number(&self) -> u64 {
83 self.number
84 }
85
86 #[getter]
87 #[pyo3(name = "parent_hash")]
88 fn py_parent_hash(&self) -> &str {
89 &self.parent_hash
90 }
91
92 #[getter]
93 #[pyo3(name = "miner")]
94 fn py_miner(&self) -> &str {
95 &self.miner
96 }
97
98 #[getter]
99 #[pyo3(name = "gas_limit")]
100 fn py_gas_limit(&self) -> u64 {
101 self.gas_limit
102 }
103
104 #[getter]
105 #[pyo3(name = "gas_used")]
106 fn py_gas_used(&self) -> u64 {
107 self.gas_used
108 }
109
110 #[getter]
111 #[pyo3(name = "base_fee_per_gas")]
112 fn py_base_fee_per_gas(&self) -> Option<String> {
113 self.base_fee_per_gas.map(|x| x.to_string())
114 }
115
116 #[getter]
117 #[pyo3(name = "blob_gas_used")]
118 fn py_blob_gas_used(&self) -> Option<String> {
119 self.blob_gas_used.map(|x| x.to_string())
120 }
121
122 #[getter]
123 #[pyo3(name = "excess_blob_gas")]
124 fn py_excess_blob_gas(&self) -> Option<String> {
125 self.excess_blob_gas.map(|x| x.to_string())
126 }
127
128 #[getter]
129 #[pyo3(name = "l1_gas_price")]
130 fn py_l1_gas_price(&self) -> Option<String> {
131 self.l1_gas_price.map(|x| x.to_string())
132 }
133
134 #[getter]
135 #[pyo3(name = "l1_gas_used")]
136 fn py_l1_gas_used(&self) -> Option<u64> {
137 self.l1_gas_used
138 }
139
140 #[getter]
141 #[pyo3(name = "l1_fee_scalar")]
142 fn py_l1_fee_scalar(&self) -> Option<u64> {
143 self.l1_fee_scalar
144 }
145
146 #[getter]
147 #[pyo3(name = "timestamp")]
148 fn py_timestamp(&self) -> u64 {
149 self.timestamp.as_u64()
150 }
151
152 #[getter]
153 #[pyo3(name = "ts_event")]
154 fn py_ts_event(&self) -> u64 {
155 self.timestamp.as_u64()
156 }
157
158 #[getter]
159 #[pyo3(name = "ts_init")]
160 fn py_ts_init(&self) -> u64 {
161 self.timestamp.as_u64()
162 }
163
164 fn __str__(&self) -> String {
165 self.to_string()
166 }
167
168 fn __repr__(&self) -> String {
169 format!("{self:?}")
170 }
171
172 fn __hash__(&self) -> u64 {
173 let mut hasher = DefaultHasher::new();
174 self.hash.hash(&mut hasher);
175 hasher.finish()
176 }
177}
178
179#[pymethods]
180#[pyo3_stub_gen::derive::gen_stub_pymethods]
181impl DefiData {
182 #[getter]
184 #[pyo3(name = "block_number")]
185 fn py_block_number(&self) -> u64 {
186 self.block_number()
187 }
188
189 #[getter]
191 #[pyo3(name = "transaction_index")]
192 fn py_transaction_index(&self) -> u32 {
193 self.transaction_index()
194 }
195
196 #[getter]
198 #[pyo3(name = "log_index")]
199 fn py_log_index(&self) -> u32 {
200 self.log_index()
201 }
202
203 #[getter]
205 #[pyo3(name = "timestamp")]
206 fn py_timestamp(&self) -> u64 {
207 self.timestamp().as_u64()
208 }
209
210 #[getter]
212 #[pyo3(name = "ts_event")]
213 fn py_ts_event(&self) -> u64 {
214 self.ts_event().as_u64()
215 }
216
217 #[getter]
219 #[pyo3(name = "ts_init")]
220 fn py_ts_init(&self) -> u64 {
221 self.ts_init().as_u64()
222 }
223
224 #[pyo3(name = "block_position")]
226 fn py_block_position(&self) -> (u64, u32, u32) {
227 self.block_position()
228 }
229}
230
231#[pymethods]
232#[pyo3_stub_gen::derive::gen_stub_pymethods]
233impl PoolSwap {
234 #[new]
240 #[expect(clippy::too_many_arguments, clippy::needless_pass_by_value)]
241 fn py_new(
242 chain: Chain,
243 dex: Dex,
244 instrument_id: InstrumentId,
245 pool_identifier: String,
246 block: u64,
247 transaction_hash: String,
248 transaction_index: u32,
249 log_index: u32,
250 timestamp: u64,
251 sender: String,
252 receiver: String,
253 amount0: String,
254 amount1: String,
255 sqrt_price_x96: String,
256 liquidity: u128,
257 tick: i32,
258 ) -> PyResult<Self> {
259 let sender = sender.parse().map_err(to_pyvalue_err)?;
260 let receiver = receiver.parse().map_err(to_pyvalue_err)?;
261 let amount0 = amount0.parse().map_err(to_pyvalue_err)?;
262 let amount1 = amount1.parse().map_err(to_pyvalue_err)?;
263 let sqrt_price_x96 = sqrt_price_x96.parse().map_err(to_pyvalue_err)?;
264 let pool_identifier = pool_identifier.parse().map_err(to_pyvalue_err)?;
265 Ok(Self::new(
266 Arc::new(chain),
267 Arc::new(dex),
268 instrument_id,
269 pool_identifier,
270 block,
271 transaction_hash,
272 transaction_index,
273 log_index,
274 timestamp.into(), timestamp.into(), sender,
277 receiver,
278 amount0,
279 amount1,
280 sqrt_price_x96,
281 liquidity,
282 tick,
283 ))
284 }
285
286 fn __str__(&self) -> String {
287 self.to_string()
288 }
289
290 fn __repr__(&self) -> String {
291 format!("{self:?}")
292 }
293
294 fn __hash__(&self) -> u64 {
295 let mut hasher = DefaultHasher::new();
296 self.chain.chain_id.hash(&mut hasher);
297 self.transaction_hash.hash(&mut hasher);
298 self.log_index.hash(&mut hasher);
299 hasher.finish()
300 }
301
302 fn __richcmp__(&self, other: &Self, op: CompareOp) -> bool {
303 match op {
304 CompareOp::Eq => self == other,
305 CompareOp::Ne => self != other,
306 _ => panic!("Unsupported comparison for PoolSwap"),
307 }
308 }
309
310 #[getter]
311 #[pyo3(name = "chain")]
312 fn py_chain(&self) -> Chain {
313 self.chain.as_ref().clone()
314 }
315
316 #[getter]
317 #[pyo3(name = "dex")]
318 fn py_dex(&self) -> Dex {
319 self.dex.as_ref().clone()
320 }
321
322 #[getter]
323 #[pyo3(name = "instrument_id")]
324 fn py_instrument_id(&self) -> InstrumentId {
325 self.instrument_id
326 }
327
328 #[getter]
329 #[pyo3(name = "pool_identifier")]
330 fn py_pool_identifier(&self) -> String {
331 self.pool_identifier.to_string()
332 }
333
334 #[getter]
335 #[pyo3(name = "block")]
336 fn py_block(&self) -> u64 {
337 self.block
338 }
339
340 #[getter]
341 #[pyo3(name = "transaction_hash")]
342 fn py_transaction_hash(&self) -> &str {
343 &self.transaction_hash
344 }
345
346 #[getter]
347 #[pyo3(name = "transaction_index")]
348 fn py_transaction_index(&self) -> u32 {
349 self.transaction_index
350 }
351
352 #[getter]
353 #[pyo3(name = "log_index")]
354 fn py_log_index(&self) -> u32 {
355 self.log_index
356 }
357
358 #[getter]
359 #[pyo3(name = "sender")]
360 fn py_sender(&self) -> String {
361 self.sender.to_string()
362 }
363
364 #[getter]
365 #[pyo3(name = "timestamp")]
366 fn py_timestamp(&self) -> u64 {
367 self.ts_event.as_u64()
368 }
369
370 #[getter]
371 #[pyo3(name = "ts_event")]
372 fn py_ts_event(&self) -> u64 {
373 self.ts_event.as_u64()
374 }
375
376 #[getter]
377 #[pyo3(name = "ts_init")]
378 fn py_ts_init(&self) -> u64 {
379 self.ts_init.as_u64()
380 }
381}
382
383#[pymethods]
384#[pyo3_stub_gen::derive::gen_stub_pymethods]
385impl PoolLiquidityUpdate {
386 #[new]
388 #[expect(clippy::too_many_arguments, clippy::needless_pass_by_value)]
389 fn py_new(
390 chain: Chain,
391 dex: Dex,
392 pool_identifier: String,
393 instrument_id: InstrumentId,
394 kind: PoolLiquidityUpdateType,
395 block: u64,
396 transaction_hash: String,
397 transaction_index: u32,
398 log_index: u32,
399 sender: Option<String>,
400 owner: String,
401 position_liquidity: String,
402 amount0: String,
403 amount1: String,
404 tick_lower: i32,
405 tick_upper: i32,
406 timestamp: u64,
407 ) -> PyResult<Self> {
408 let sender = sender
409 .map(|s| s.parse())
410 .transpose()
411 .map_err(to_pyvalue_err)?;
412 let owner = owner.parse().map_err(to_pyvalue_err)?;
413 let position_liquidity = position_liquidity.parse().map_err(to_pyvalue_err)?;
414 let amount0 = amount0.parse().map_err(to_pyvalue_err)?;
415 let amount1 = amount1.parse().map_err(to_pyvalue_err)?;
416 let pool_identifier = pool_identifier.parse().map_err(to_pyvalue_err)?;
417 Ok(Self::new(
418 Arc::new(chain),
419 Arc::new(dex),
420 instrument_id,
421 pool_identifier,
422 kind,
423 block,
424 transaction_hash,
425 transaction_index,
426 log_index,
427 sender,
428 owner,
429 position_liquidity,
430 amount0,
431 amount1,
432 tick_lower,
433 tick_upper,
434 timestamp.into(), timestamp.into(), ))
437 }
438
439 fn __str__(&self) -> String {
440 self.to_string()
441 }
442
443 fn __repr__(&self) -> String {
444 format!("{self:?}")
445 }
446
447 fn __hash__(&self) -> u64 {
448 let mut hasher = DefaultHasher::new();
449 self.chain.chain_id.hash(&mut hasher);
450 self.transaction_hash.hash(&mut hasher);
451 self.log_index.hash(&mut hasher);
452 hasher.finish()
453 }
454
455 fn __richcmp__(&self, other: &Self, op: pyo3::pyclass::CompareOp) -> bool {
456 match op {
457 CompareOp::Eq => self == other,
458 CompareOp::Ne => self != other,
459 _ => panic!("Unsupported comparison for PoolLiquidityUpdate"),
460 }
461 }
462
463 #[getter]
464 #[pyo3(name = "chain")]
465 fn py_chain(&self) -> Chain {
466 self.chain.as_ref().clone()
467 }
468
469 #[getter]
470 #[pyo3(name = "dex")]
471 fn py_dex(&self) -> Dex {
472 self.dex.as_ref().clone()
473 }
474
475 #[getter]
476 #[pyo3(name = "instrument_id")]
477 fn py_instrument_id(&self) -> InstrumentId {
478 self.instrument_id
479 }
480
481 #[getter]
482 #[pyo3(name = "pool_identifier")]
483 fn py_pool_identifier(&self) -> String {
484 self.pool_identifier.to_string()
485 }
486
487 #[getter]
488 #[pyo3(name = "kind")]
489 fn py_kind(&self) -> PoolLiquidityUpdateType {
490 self.kind
491 }
492
493 #[getter]
494 #[pyo3(name = "block")]
495 fn py_block(&self) -> u64 {
496 self.block
497 }
498
499 #[getter]
500 #[pyo3(name = "transaction_hash")]
501 fn py_transaction_hash(&self) -> &str {
502 &self.transaction_hash
503 }
504
505 #[getter]
506 #[pyo3(name = "transaction_index")]
507 fn py_transaction_index(&self) -> u32 {
508 self.transaction_index
509 }
510
511 #[getter]
512 #[pyo3(name = "log_index")]
513 fn py_log_index(&self) -> u32 {
514 self.log_index
515 }
516
517 #[getter]
518 #[pyo3(name = "sender")]
519 fn py_sender(&self) -> Option<String> {
520 self.sender.map(|s| s.to_string())
521 }
522
523 #[getter]
524 #[pyo3(name = "owner")]
525 fn py_owner(&self) -> String {
526 self.owner.to_string()
527 }
528
529 #[getter]
530 #[pyo3(name = "position_liquidity")]
531 fn py_position_liquidity(&self) -> String {
532 self.position_liquidity.to_string()
533 }
534
535 #[getter]
536 #[pyo3(name = "amount0")]
537 fn py_amount0(&self) -> String {
538 self.amount0.to_string()
539 }
540
541 #[getter]
542 #[pyo3(name = "amount1")]
543 fn py_amount1(&self) -> String {
544 self.amount1.to_string()
545 }
546
547 #[getter]
548 #[pyo3(name = "tick_lower")]
549 fn py_tick_lower(&self) -> i32 {
550 self.tick_lower
551 }
552
553 #[getter]
554 #[pyo3(name = "tick_upper")]
555 fn py_tick_upper(&self) -> i32 {
556 self.tick_upper
557 }
558
559 #[getter]
560 #[pyo3(name = "timestamp")]
561 fn py_timestamp(&self) -> u64 {
562 self.ts_event.as_u64()
563 }
564
565 #[getter]
566 #[pyo3(name = "ts_event")]
567 fn py_ts_event(&self) -> u64 {
568 self.ts_event.as_u64()
569 }
570
571 #[getter]
572 #[pyo3(name = "ts_init")]
573 fn py_ts_init(&self) -> u64 {
574 self.ts_init.as_u64()
575 }
576}
577
578#[pymethods]
579#[pyo3_stub_gen::derive::gen_stub_pymethods]
580impl PoolFeeCollect {
581 #[new]
583 #[expect(clippy::too_many_arguments, clippy::needless_pass_by_value)]
584 fn py_new(
585 chain: Chain,
586 dex: Dex,
587 pool_identifier: String,
588 instrument_id: InstrumentId,
589 block: u64,
590 transaction_hash: String,
591 transaction_index: u32,
592 log_index: u32,
593 owner: String,
594 amount0: String,
595 amount1: String,
596 tick_lower: i32,
597 tick_upper: i32,
598 timestamp: u64,
599 ) -> PyResult<Self> {
600 let owner = owner.parse().map_err(to_pyvalue_err)?;
601 let amount0 = amount0.parse().map_err(to_pyvalue_err)?;
602 let amount1 = amount1.parse().map_err(to_pyvalue_err)?;
603 let pool_identifier = pool_identifier.parse().map_err(to_pyvalue_err)?;
604 Ok(Self::new(
605 Arc::new(chain),
606 Arc::new(dex),
607 instrument_id,
608 pool_identifier,
609 block,
610 transaction_hash,
611 transaction_index,
612 log_index,
613 owner,
614 amount0,
615 amount1,
616 tick_lower,
617 tick_upper,
618 timestamp.into(), timestamp.into(), ))
621 }
622
623 fn __str__(&self) -> String {
624 self.to_string()
625 }
626
627 fn __repr__(&self) -> String {
628 format!("{self:?}")
629 }
630
631 fn __hash__(&self) -> u64 {
632 let mut hasher = DefaultHasher::new();
633 self.chain.chain_id.hash(&mut hasher);
634 self.transaction_hash.hash(&mut hasher);
635 self.log_index.hash(&mut hasher);
636 hasher.finish()
637 }
638
639 fn __richcmp__(&self, other: &Self, op: CompareOp) -> bool {
640 match op {
641 CompareOp::Eq => self == other,
642 CompareOp::Ne => self != other,
643 _ => panic!("Unsupported comparison for PoolFeeCollect"),
644 }
645 }
646
647 #[getter]
648 #[pyo3(name = "chain")]
649 fn py_chain(&self) -> Chain {
650 self.chain.as_ref().clone()
651 }
652
653 #[getter]
654 #[pyo3(name = "dex")]
655 fn py_dex(&self) -> Dex {
656 self.dex.as_ref().clone()
657 }
658
659 #[getter]
660 #[pyo3(name = "instrument_id")]
661 fn py_instrument_id(&self) -> InstrumentId {
662 self.instrument_id
663 }
664
665 #[getter]
666 #[pyo3(name = "pool_identifier")]
667 fn py_pool_identifier(&self) -> String {
668 self.pool_identifier.to_string()
669 }
670
671 #[getter]
672 #[pyo3(name = "block")]
673 fn py_block(&self) -> u64 {
674 self.block
675 }
676
677 #[getter]
678 #[pyo3(name = "transaction_hash")]
679 fn py_transaction_hash(&self) -> &str {
680 &self.transaction_hash
681 }
682
683 #[getter]
684 #[pyo3(name = "transaction_index")]
685 fn py_transaction_index(&self) -> u32 {
686 self.transaction_index
687 }
688
689 #[getter]
690 #[pyo3(name = "log_index")]
691 fn py_log_index(&self) -> u32 {
692 self.log_index
693 }
694
695 #[getter]
696 #[pyo3(name = "owner")]
697 fn py_owner(&self) -> String {
698 self.owner.to_string()
699 }
700
701 #[getter]
702 #[pyo3(name = "amount0")]
703 fn py_amount0(&self) -> String {
704 self.amount0.to_string()
705 }
706
707 #[getter]
708 #[pyo3(name = "amount1")]
709 fn py_amount1(&self) -> String {
710 self.amount1.to_string()
711 }
712
713 #[getter]
714 #[pyo3(name = "tick_lower")]
715 fn py_tick_lower(&self) -> i32 {
716 self.tick_lower
717 }
718
719 #[getter]
720 #[pyo3(name = "tick_upper")]
721 fn py_tick_upper(&self) -> i32 {
722 self.tick_upper
723 }
724
725 #[getter]
726 #[pyo3(name = "timestamp")]
727 fn py_timestamp(&self) -> u64 {
728 self.ts_event.as_u64()
729 }
730
731 #[getter]
732 #[pyo3(name = "ts_event")]
733 fn py_ts_event(&self) -> u64 {
734 self.ts_event.as_u64()
735 }
736
737 #[getter]
738 #[pyo3(name = "ts_init")]
739 fn py_ts_init(&self) -> u64 {
740 self.ts_init.as_u64()
741 }
742}
743
744#[pymethods]
745#[pyo3_stub_gen::derive::gen_stub_pymethods]
746impl PoolFlash {
747 #[new]
753 #[expect(clippy::too_many_arguments, clippy::needless_pass_by_value)]
754 fn py_new(
755 chain: Chain,
756 dex: Dex,
757 pool_identifier: String,
758 instrument_id: InstrumentId,
759 block: u64,
760 transaction_hash: String,
761 transaction_index: u32,
762 log_index: u32,
763 sender: String,
764 recipient: String,
765 amount0: String,
766 amount1: String,
767 paid0: String,
768 paid1: String,
769 timestamp: u64,
770 ) -> PyResult<Self> {
771 let sender = sender.parse().map_err(to_pyvalue_err)?;
772 let recipient = recipient.parse().map_err(to_pyvalue_err)?;
773 let amount0 = amount0.parse().map_err(to_pyvalue_err)?;
774 let amount1 = amount1.parse().map_err(to_pyvalue_err)?;
775 let paid0 = paid0.parse().map_err(to_pyvalue_err)?;
776 let paid1 = paid1.parse().map_err(to_pyvalue_err)?;
777 let pool_identifier = pool_identifier.parse().map_err(to_pyvalue_err)?;
778 Ok(Self::new(
779 Arc::new(chain),
780 Arc::new(dex),
781 instrument_id,
782 pool_identifier,
783 block,
784 transaction_hash,
785 transaction_index,
786 log_index,
787 timestamp.into(), timestamp.into(), sender,
790 recipient,
791 amount0,
792 amount1,
793 paid0,
794 paid1,
795 ))
796 }
797
798 fn __str__(&self) -> String {
799 self.to_string()
800 }
801
802 fn __repr__(&self) -> String {
803 format!("{self:?}")
804 }
805
806 fn __hash__(&self) -> u64 {
807 let mut hasher = DefaultHasher::new();
808 self.chain.chain_id.hash(&mut hasher);
809 self.transaction_hash.hash(&mut hasher);
810 self.log_index.hash(&mut hasher);
811 hasher.finish()
812 }
813
814 fn __richcmp__(&self, other: &Self, op: CompareOp) -> bool {
815 match op {
816 CompareOp::Eq => self == other,
817 CompareOp::Ne => self != other,
818 _ => panic!("Unsupported comparison for PoolFlash"),
819 }
820 }
821
822 #[getter]
823 #[pyo3(name = "chain")]
824 fn py_chain(&self) -> Chain {
825 self.chain.as_ref().clone()
826 }
827
828 #[getter]
829 #[pyo3(name = "dex")]
830 fn py_dex(&self) -> Dex {
831 self.dex.as_ref().clone()
832 }
833
834 #[getter]
835 #[pyo3(name = "instrument_id")]
836 fn py_instrument_id(&self) -> InstrumentId {
837 self.instrument_id
838 }
839
840 #[getter]
841 #[pyo3(name = "pool_identifier")]
842 fn py_pool_identifier(&self) -> String {
843 self.pool_identifier.to_string()
844 }
845
846 #[getter]
847 #[pyo3(name = "block")]
848 fn py_block(&self) -> u64 {
849 self.block
850 }
851
852 #[getter]
853 #[pyo3(name = "transaction_hash")]
854 fn py_transaction_hash(&self) -> &str {
855 &self.transaction_hash
856 }
857
858 #[getter]
859 #[pyo3(name = "transaction_index")]
860 fn py_transaction_index(&self) -> u32 {
861 self.transaction_index
862 }
863
864 #[getter]
865 #[pyo3(name = "log_index")]
866 fn py_log_index(&self) -> u32 {
867 self.log_index
868 }
869
870 #[getter]
871 #[pyo3(name = "sender")]
872 fn py_sender(&self) -> String {
873 self.sender.to_string()
874 }
875
876 #[getter]
877 #[pyo3(name = "recipient")]
878 fn py_recipient(&self) -> String {
879 self.recipient.to_string()
880 }
881
882 #[getter]
883 #[pyo3(name = "amount0")]
884 fn py_amount0(&self) -> String {
885 self.amount0.to_string()
886 }
887
888 #[getter]
889 #[pyo3(name = "amount1")]
890 fn py_amount1(&self) -> String {
891 self.amount1.to_string()
892 }
893
894 #[getter]
895 #[pyo3(name = "paid0")]
896 fn py_paid0(&self) -> String {
897 self.paid0.to_string()
898 }
899
900 #[getter]
901 #[pyo3(name = "paid1")]
902 fn py_paid1(&self) -> String {
903 self.paid1.to_string()
904 }
905
906 #[getter]
907 #[pyo3(name = "timestamp")]
908 fn py_timestamp(&self) -> u64 {
909 self.ts_event.as_u64()
910 }
911
912 #[getter]
913 #[pyo3(name = "ts_event")]
914 fn py_ts_event(&self) -> u64 {
915 self.ts_event.as_u64()
916 }
917
918 #[getter]
919 #[pyo3(name = "ts_init")]
920 fn py_ts_init(&self) -> u64 {
921 self.ts_init.as_u64()
922 }
923}
924
925#[pymethods]
926#[pyo3_stub_gen::derive::gen_stub_pymethods]
927impl Transaction {
928 #[new]
930 #[expect(clippy::too_many_arguments, clippy::needless_pass_by_value)]
931 fn py_new(
932 chain: Chain,
933 hash: String,
934 block_hash: String,
935 block_number: u64,
936 from: String,
937 to: String,
938 gas: String,
939 gas_price: String,
940 transaction_index: u64,
941 value: String,
942 ) -> PyResult<Self> {
943 let from = from.parse().map_err(to_pyvalue_err)?;
944 let to = to.parse().map_err(to_pyvalue_err)?;
945 let gas = gas.parse().map_err(to_pyvalue_err)?;
946 let gas_price = gas_price.parse().map_err(to_pyvalue_err)?;
947 let value = value.parse().map_err(to_pyvalue_err)?;
948 Ok(Self::new(
949 chain,
950 hash,
951 block_hash,
952 block_number,
953 from,
954 to,
955 gas,
956 gas_price,
957 transaction_index,
958 value,
959 ))
960 }
961
962 fn __str__(&self) -> String {
963 format!(
964 "Transaction(chain={}, hash={}, block_number={}, from={}, to={}, value={})",
965 self.chain.name, self.hash, self.block_number, self.from, self.to, self.value
966 )
967 }
968
969 fn __repr__(&self) -> String {
970 format!("{self:?}")
971 }
972
973 fn __hash__(&self) -> u64 {
974 let mut hasher = DefaultHasher::new();
975 self.hash.hash(&mut hasher);
976 hasher.finish()
977 }
978
979 fn __richcmp__(&self, other: &Self, op: CompareOp) -> bool {
980 match op {
981 CompareOp::Eq => self.hash == other.hash,
982 CompareOp::Ne => self.hash != other.hash,
983 _ => panic!("Unsupported comparison for Transaction"),
984 }
985 }
986
987 #[getter]
988 #[pyo3(name = "chain")]
989 fn py_chain(&self) -> Chain {
990 self.chain.clone()
991 }
992
993 #[getter]
994 #[pyo3(name = "hash")]
995 fn py_hash(&self) -> &str {
996 &self.hash
997 }
998
999 #[getter]
1000 #[pyo3(name = "block_hash")]
1001 fn py_block_hash(&self) -> &str {
1002 &self.block_hash
1003 }
1004
1005 #[getter]
1006 #[pyo3(name = "block_number")]
1007 fn py_block_number(&self) -> u64 {
1008 self.block_number
1009 }
1010
1011 #[getter]
1012 #[pyo3(name = "from")]
1013 fn py_from(&self) -> String {
1014 self.from.to_string()
1015 }
1016
1017 #[getter]
1018 #[pyo3(name = "to")]
1019 fn py_to(&self) -> String {
1020 self.to.to_string()
1021 }
1022
1023 #[getter]
1024 #[pyo3(name = "value")]
1025 fn py_value(&self) -> String {
1026 self.value.to_string()
1027 }
1028
1029 #[getter]
1030 #[pyo3(name = "transaction_index")]
1031 fn py_transaction_index(&self) -> u64 {
1032 self.transaction_index
1033 }
1034
1035 #[getter]
1036 #[pyo3(name = "gas")]
1037 fn py_gas(&self) -> String {
1038 self.gas.to_string()
1039 }
1040
1041 #[getter]
1042 #[pyo3(name = "gas_price")]
1043 fn py_gas_price(&self) -> String {
1044 self.gas_price.to_string()
1045 }
1046}