1- from time import time
2- from typing import Union
1+ import logging
2+ import time
3+ from typing import Any , Dict , Optional , Union
34
45import flask
6+ from flask import request
57from flask_restx import Resource
68from sqlalchemy import func
79
810from api .app .address import address_features_namespace
11+ from api .app .address .features import feature_registry , register_feature
912from api .app .address .models import AddressBaseProfile , ScheduledMetadata
10- from api .app .af_ens .routes import ACIEnsCurrent , ACIEnsDetail
1113from api .app .cache import cache
12- from api .app .deposit_to_l2 . routes import ACIDepositToL2Current , ACIDepositToL2Transactions
14+ from api .app .main import app
1315from common .models import db
1416from common .utils .exception_control import APIError
1517from common .utils .format_utils import as_dict , format_to_dict
1820 get_address_deploy_contract_count ,
1921 get_address_first_deploy_contract_time ,
2022)
23+ from indexer .modules .custom .deposit_to_l2 .endpoint .routes import ACIDepositToL2Current , ACIDepositToL2Transactions
24+ from indexer .modules .custom .hemera_ens .endpoint .routes import ACIEnsCurrent , ACIEnsDetail
2125from indexer .modules .custom .opensea .endpoint .routes import ACIOpenseaProfile , ACIOpenseaTransactions
2226from indexer .modules .custom .uniswap_v3 .endpoints .routes import (
23- UniswapV3WalletLiquidityDetail ,
2427 UniswapV3WalletLiquidityHolding ,
2528 UniswapV3WalletTradingRecords ,
2629 UniswapV3WalletTradingSummary ,
3235MAX_INTERNAL_TRANSACTION = 10000
3336MAX_TOKEN_TRANSFER = 10000
3437
38+ logger = app .logger
39+
3540
3641def get_address_recent_info (address : bytes , last_timestamp : int ) -> dict :
3742 pass
@@ -84,14 +89,37 @@ def get(self, address):
8489 return profile , 200
8590
8691
92+ @register_feature ("contract_deployer" , "value" )
93+ def get_contract_deployer_profile (address ) -> Optional [Dict [str , Any ]]:
94+ address_deploy_contract_count = get_address_deploy_contract_count (address )
95+ address_first_deploy_contract_time = get_address_first_deploy_contract_time (address )
96+ return (
97+ {
98+ "deployed_countract_count" : address_deploy_contract_count ,
99+ "first_deployed_time" : address_first_deploy_contract_time ,
100+ }
101+ if address_deploy_contract_count != 0
102+ else None
103+ )
104+
105+
106+ @register_feature ("contract_deployer" , "events" )
107+ def get_contract_deployed_events (address , limit = 5 , offset = 0 ) -> Optional [Dict [str , Any ]]:
108+ count = get_address_deploy_contract_count (address )
109+ if count == 0 :
110+ return None
111+ events = get_address_contract_operations (address , limit = limit , offset = offset )
112+ res = []
113+ for event in events :
114+ res .append (format_to_dict (event ))
115+ return {"data" : res , "total" : count }
116+
117+
87118@address_features_namespace .route ("/v1/aci/<address>/contract_deployer/profile" )
88119class ACIContractDeployerProfile (Resource ):
89120 def get (self , address ):
90121 address = address .lower ()
91- return {
92- "deployed_countract_count" : get_address_deploy_contract_count (address ),
93- "first_deployed_time" : get_address_first_deploy_contract_time (address ),
94- }
122+ return get_contract_deployer_profile (address ) or {"deployed_countract_count" : 0 , "first_deployed_time" : None }
95123
96124
97125@address_features_namespace .route ("/v1/aci/<address>/contract_deployer/events" )
@@ -102,11 +130,11 @@ def get(self, address):
102130 page_size = int (flask .request .args .get ("size" , PAGE_SIZE ))
103131 limit = page_size
104132 offset = (page_index - 1 ) * page_size
105- events = get_address_contract_operations ( address , limit = limit , offset = offset )
106- res = []
107- for event in events :
108- res . append ( format_to_dict ( event ))
109- return { "data" : res }
133+
134+ return ( get_contract_deployed_events ( address , limit = limit , offset = offset ) or { "data" : [], "total" : 0 }) | {
135+ "size" : page_size ,
136+ "page" : page_index ,
137+ }
110138
111139
112140@address_features_namespace .route ("/v1/aci/<address>/all_features" )
@@ -126,7 +154,7 @@ def get(self, address):
126154 if features :
127155 feature_list = features .split ("," )
128156
129- timer = time ()
157+ timer = time . time ()
130158 feature_result = {}
131159
132160 if "contract_deployer" in feature_list :
@@ -178,11 +206,67 @@ def get(self, address):
178206 }
179207 )
180208
181- print (time () - timer )
209+ print (time . time () - timer )
182210
183211 combined_result = {
184212 "address" : address ,
185213 "features" : feature_data_list ,
186214 }
187215
188216 return combined_result , 200
217+
218+
219+ @address_features_namespace .route ("/v2/aci/<address>/all_features" )
220+ class ACIAllFeatures (Resource ):
221+ def get (self , address ):
222+ address = address .lower ()
223+ requested_features = request .args .get ("features" )
224+
225+ if requested_features :
226+ feature_list = [f for f in requested_features .split ("," ) if f in feature_registry .feature_list ]
227+ else :
228+ feature_list = feature_registry .feature_list
229+
230+ feature_result = {}
231+ total_start_time = time .time ()
232+
233+ for feature in feature_list :
234+ feature_start_time = time .time ()
235+ feature_result [feature ] = {}
236+ for subcategory in feature_registry .features [feature ]:
237+ subcategory_start_time = time .time ()
238+ try :
239+ feature_result [feature ][subcategory ] = feature_registry .features [feature ][subcategory ](address )
240+ subcategory_end_time = time .time ()
241+ logger .debug (
242+ f"Feature '{ feature } ' subcategory '{ subcategory } ' execution time: { subcategory_end_time - subcategory_start_time :.4f} seconds"
243+ )
244+ except Exception as e :
245+ logger .error (f"Error in feature '{ feature } ' subcategory '{ subcategory } ': { str (e )} " )
246+ feature_result [feature ][subcategory ] = {"error" : str (e )}
247+
248+ feature_end_time = time .time ()
249+ logger .debug (
250+ f"Total execution time for feature '{ feature } ': { feature_end_time - feature_start_time :.4f} seconds"
251+ )
252+
253+ feature_data_list = [
254+ {"id" : feature_id , ** subcategory_dict }
255+ for feature_id in feature_list
256+ if (
257+ subcategory_dict := {
258+ subcategory : feature_result [feature_id ][subcategory ]
259+ for subcategory in feature_registry .features [feature_id ]
260+ if feature_result [feature_id ][subcategory ] is not None
261+ }
262+ )
263+ ]
264+ combined_result = {
265+ "address" : address ,
266+ "features" : feature_data_list ,
267+ }
268+
269+ total_end_time = time .time ()
270+ logger .debug (f"Total execution time for all features: { total_end_time - total_start_time :.4f} seconds" )
271+
272+ return combined_result , 200
0 commit comments