Skip to content

Commit 3c3757d

Browse files
committed
feat: added new endpoint GET /historical_fees?start_date=&end_date=&interval=
Signed-off-by: kevkevinpal <oapallikunnel@gmail.com>
1 parent fcc12bc commit 3c3757d

2 files changed

Lines changed: 133 additions & 0 deletions

File tree

app/src/main/kotlin/xyz/block/augurref/api/HistoricalFeeEndpoint.kt

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,95 @@ fun Route.configureHistoricalFeesEndpoint(mempoolCollector: MempoolCollector) {
9090
call.respond(response)
9191
}
9292
}
93+
94+
get("/historical_fees") {
95+
logger.info("Received request for historical fee estimates")
96+
97+
// Extract params from query start_date, end_date, interval (seconds)
98+
val startDateParam = call.request.queryParameters["start_date"]
99+
val endDateParam = call.request.queryParameters["end_date"]
100+
val intervalParam = call.request.queryParameters["interval"]
101+
val interval: Int = intervalParam?.toIntOrNull() ?: 3600
102+
103+
if (startDateParam == null) {
104+
call.respondText(
105+
"start_date parameter is required",
106+
status = HttpStatusCode.BadRequest,
107+
contentType = ContentType.Text.Plain,
108+
)
109+
return@get
110+
}
111+
112+
if (endDateParam == null) {
113+
call.respondText(
114+
"end_date parameter is required",
115+
status = HttpStatusCode.BadRequest,
116+
contentType = ContentType.Text.Plain,
117+
)
118+
return@get
119+
}
120+
121+
// Validate and parse the date
122+
val startDate = try {
123+
startDateParam?.let { LocalDateTime.parse(it) }
124+
} catch (e: DateTimeParseException) {
125+
logger.warn("Invalid date format: $startDateParam")
126+
call.respondText(
127+
"Invalid date format. Use YYYY-MM-DDTHH:MM:SS",
128+
status = HttpStatusCode.BadRequest,
129+
contentType = ContentType.Text.Plain,
130+
)
131+
return@get
132+
}
133+
val endDate = try {
134+
endDateParam?.let { LocalDateTime.parse(it) }
135+
} catch (e: DateTimeParseException) {
136+
logger.warn("Invalid date format: $endDateParam")
137+
call.respondText(
138+
"Invalid date format. Use YYYY-MM-DDTHH:MM:SS",
139+
status = HttpStatusCode.BadRequest,
140+
contentType = ContentType.Text.Plain,
141+
)
142+
return@get
143+
}
144+
145+
// Fetch historical fee estimate based on date
146+
val feeEstimate = if (startDate != null && endDate != null && interval != null) {
147+
logger.info(
148+
"Fetching historical fee estimate for start_date: $startDate to " +
149+
"end_date: $endDate for intervals: $interval seconds",
150+
)
151+
mempoolCollector.getFeeEstimateForDateRange(startDate, endDate, interval)
152+
} else {
153+
logger.warn("internal error")
154+
call.respondText(
155+
"internal error",
156+
status = HttpStatusCode.InternalServerError,
157+
contentType = ContentType.Text.Plain,
158+
)
159+
return@get
160+
}
161+
162+
if (feeEstimate == null) {
163+
logger.warn(
164+
"No historical fee estimates available for start_date $startDate to " +
165+
"end_date: $endDate for interval: $interval seconds",
166+
)
167+
call.respondText(
168+
"No historical fee estimates available for start_date $startDate to " +
169+
"end_date: $endDate for interval: $interval seconds",
170+
status = HttpStatusCode.ServiceUnavailable,
171+
contentType = ContentType.Text.Plain,
172+
)
173+
} else {
174+
var mutableResponse = mutableListOf<FeeEstimateResponse>()
175+
logger.info("Transforming historical fee estimates for response")
176+
for (estimate in feeEstimate) {
177+
val response = transformFeeEstimate(estimate)
178+
mutableResponse.add(response)
179+
}
180+
logger.debug("Returning historical fee estimates")
181+
call.respond(mutableResponse)
182+
}
183+
}
93184
}

app/src/main/kotlin/xyz/block/augurref/service/MempoolCollector.kt

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,48 @@ class MempoolCollector(
7272
return latestFeeEstimate.get()
7373
}
7474

75+
fun getFeeEstimateForDateRange(
76+
start_date: LocalDateTime,
77+
end_date: LocalDateTime,
78+
interval: Int,
79+
): List<FeeEstimate>? {
80+
// Ensure start_date is not after end_date
81+
if (start_date.isAfter(end_date)) {
82+
logger.warn("Start date is after end date")
83+
return null
84+
}
85+
86+
// Initialize result list to store fee estimates
87+
val estimates = mutableListOf<FeeEstimate>()
88+
var currentDate = start_date
89+
90+
// Iterate through the date range with the given interval
91+
while (!currentDate.isAfter(end_date)) {
92+
logger.debug("Processing fee estimate for $currentDate")
93+
val feeEstimate = getFeeEstimateForDate(currentDate)
94+
95+
// If fee estimate is non-null and has estimates, merge them
96+
if (feeEstimate != null && feeEstimate.estimates.isNotEmpty()) {
97+
// estimates.putAll(feeEstimate.estimates as Map<Int, BlockTarget>)
98+
estimates.add(feeEstimate)
99+
} else {
100+
logger.debug("No valid fee estimate for $currentDate")
101+
}
102+
103+
// Increment currentDate by interval (in minutes)
104+
currentDate = currentDate.plusSeconds(interval.toLong())
105+
}
106+
107+
// Return null if no estimates were collected
108+
if (estimates.isEmpty()) {
109+
logger.warn("No fee estimates collected for the date range")
110+
return null
111+
}
112+
113+
// Return a FeeEstimate with the aggregated estimates
114+
return estimates
115+
}
116+
75117
/**
76118
* Get the fee estimate for specific date
77119
*/

0 commit comments

Comments
 (0)