11import hashlib
22import logging
3- from datetime import datetime
43from typing import Optional
54
65from django .db .models import Q
7- from django .utils import timezone
86
97import django_filters
108from drf_spectacular .types import OpenApiTypes
2826from .cache import CacheSafeTxsView , cache_txs_view_for_address
2927from .models import MultisigTransaction , SafeContract , SafeContractDelegate
3028from .pagination import DummyPagination
29+ from .serializers import SafeExportTransactionRequestParams
3130from .services import BalanceServiceProvider , TransactionServiceProvider
3231from .services .balance_service import Balance
3332from .services .collectibles_service import CollectiblesServiceProvider
@@ -682,6 +681,17 @@ class SafeExportView(GenericAPIView):
682681 serializer_class = serializers .SafeExportTransactionSerializer
683682 pagination_class = pagination .ListPagination
684683
684+ def get_query_params (self ):
685+ serializer = SafeExportTransactionRequestParams (
686+ data = self .request .query_params .dict ()
687+ )
688+ serializer .is_valid (raise_exception = True )
689+
690+ validated_data = serializer .validated_data
691+ parsed_execution_date_gte = validated_data .get ("execution_date__gte" )
692+ parsed_execution_date_lte = validated_data .get ("execution_date__lte" )
693+ return parsed_execution_date_gte , parsed_execution_date_lte
694+
685695 def get (self , request , address ):
686696 """
687697 Get transactions optimized for CSV export with transfer information.
@@ -703,67 +713,14 @@ def get(self, request, address):
703713 except SafeContract .DoesNotExist :
704714 return Response (status = status .HTTP_404_NOT_FOUND )
705715
706- # Parse query parameters
707- execution_date_gte = request .query_params .get ("execution_date__gte" )
708- execution_date_lte = request .query_params .get ("execution_date__lte" )
716+ # Get query params
717+ parsed_execution_date_gte , parsed_execution_date_lte = self .get_query_params ()
718+
719+ # Get pagination
709720 paginator = pagination .ListPagination (self .request , max_limit = 1000 )
710721 limit = paginator .get_limit (request )
711722 offset = paginator .get_offset (request )
712723
713- # Parse dates if provided
714- parsed_execution_date_gte = None
715- parsed_execution_date_lte = None
716-
717- if execution_date_gte :
718- try :
719- # Handle different ISO format variations
720- date_str = execution_date_gte .replace ("Z" , "+00:00" )
721- # Fix format issue where timezone offset has space instead of +
722- if " " in date_str : # e.g., '2025-07-08T19:22:21.558887 00:00'
723- parts = date_str .rsplit (" " , 1 )
724- if (
725- len (parts ) == 2 and ":" in parts [1 ] and len (parts [1 ]) == 5
726- ): # timezone format like '00:00'
727- date_str = parts [0 ] + "+" + parts [1 ]
728- parsed_execution_date_gte = datetime .fromisoformat (date_str )
729- # Ensure timezone-aware
730- if parsed_execution_date_gte .tzinfo is None :
731- parsed_execution_date_gte = timezone .make_aware (
732- parsed_execution_date_gte
733- )
734- except ValueError :
735- return Response (
736- status = status .HTTP_400_BAD_REQUEST ,
737- data = {
738- "error" : "Invalid execution_date__gte format. Use ISO format."
739- },
740- )
741-
742- if execution_date_lte :
743- try :
744- # Handle different ISO format variations
745- date_str = execution_date_lte .replace ("Z" , "+00:00" )
746- # Fix format issue where timezone offset has space instead of +
747- if " " in date_str : # e.g., '2025-07-08T19:22:21.558887 00:00'
748- parts = date_str .rsplit (" " , 1 )
749- if (
750- len (parts ) == 2 and ":" in parts [1 ] and len (parts [1 ]) == 5
751- ): # timezone format like '00:00'
752- date_str = parts [0 ] + "+" + parts [1 ]
753- parsed_execution_date_lte = datetime .fromisoformat (date_str )
754- # Ensure timezone-aware
755- if parsed_execution_date_lte .tzinfo is None :
756- parsed_execution_date_lte = timezone .make_aware (
757- parsed_execution_date_lte
758- )
759- except ValueError :
760- return Response (
761- status = status .HTTP_400_BAD_REQUEST ,
762- data = {
763- "error" : "Invalid execution_date__lte format. Use ISO format."
764- },
765- )
766-
767724 # Get transactions from service
768725 transaction_service = TransactionServiceProvider ()
769726 transactions , total_count = transaction_service .get_export_transactions (
0 commit comments