From d3dd4b346702b3731c9f20340a80c80e045a3f5b Mon Sep 17 00:00:00 2001 From: fatemeh imanipour Date: Mon, 23 Feb 2026 20:20:12 +0330 Subject: [PATCH] Find the address holder at the specific time --- .../bcgateway/app/config/SecurityConfig.kt | 1 + .../app/controller/AddressController.kt | 22 ++++++++++++++++++- .../core/api/AssignAddressService.kt | 9 ++++++++ .../core/service/AssignAddressServiceImpl.kt | 20 ++++++++++++++--- .../core/spi/AssignedAddressHandler.kt | 8 +++++++ .../postgres/dao/AssignedAddressRepository.kt | 7 ++++++ .../impl/AssignedAddressHandlerImpl.kt | 12 ++++++++++ 7 files changed, 75 insertions(+), 4 deletions(-) diff --git a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/config/SecurityConfig.kt b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/config/SecurityConfig.kt index eee949f3c..d5b553971 100644 --- a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/config/SecurityConfig.kt +++ b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/config/SecurityConfig.kt @@ -52,6 +52,7 @@ class SecurityConfig(private val webClient: WebClient) { .pathMatchers("/omni-balance/bc/**").hasAuthority("ROLE_admin") .pathMatchers("/actuator/**").permitAll() .pathMatchers("/scanner/**").permitAll() + .pathMatchers(HttpMethod.GET,"/v1/address/*/holder").permitAll() .anyExchange().authenticated() .and() .oauth2ResourceServer() diff --git a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/AddressController.kt b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/AddressController.kt index ba408faa8..09de48aae 100644 --- a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/AddressController.kt +++ b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/AddressController.kt @@ -1,6 +1,7 @@ package co.nilin.opex.bcgateway.app.controller import co.nilin.opex.bcgateway.core.api.AssignAddressService +import co.nilin.opex.bcgateway.core.model.AddressStatus import co.nilin.opex.bcgateway.core.model.AssignedAddress import co.nilin.opex.bcgateway.core.model.ReservedAddress import co.nilin.opex.bcgateway.core.spi.AddressTypeHandler @@ -21,10 +22,14 @@ import java.nio.charset.StandardCharsets class AddressController( private val assignAddressService: AssignAddressService, private val reservedAddressHandler: ReservedAddressHandler, - private val addressTypeHandler: AddressTypeHandler + private val addressTypeHandler: AddressTypeHandler, ) { data class AssignAddressRequest(val uuid: String, val currency: String, val gatewayUuid: String) data class AssignAddressResponse(val addresses: List) + data class AddressHolderResponse( + val uuid: String?, + val currentStatus: AddressStatus? + ) @PostMapping("/assign") suspend fun assignAddress( @@ -49,6 +54,19 @@ class AddressController( // }.collect(Collectors.toList())) } + @GetMapping("/{address}/holder") + suspend fun getAddressHolder( + @PathVariable address: String, + @RequestParam(required = false) memo: String?, + @RequestParam(required = false) time: Long? + ): AddressHolderResponse { + val (holderUuid, currentStatus) = assignAddressService.findHolder(address, memo, time) + return AddressHolderResponse( + uuid = holderUuid, + currentStatus = currentStatus + ) + } + /** * (address, regex, address_type) */ @@ -67,4 +85,6 @@ class AddressController( // Do nothing in case of duplication (Or any constraint issue) runCatching { reservedAddressHandler.addReservedAddress(items) } } + + } diff --git a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/api/AssignAddressService.kt b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/api/AssignAddressService.kt index 28864bad0..eb6de7d38 100644 --- a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/api/AssignAddressService.kt +++ b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/api/AssignAddressService.kt @@ -1,9 +1,18 @@ package co.nilin.opex.bcgateway.core.api +import co.nilin.opex.bcgateway.core.model.AddressStatus import co.nilin.opex.bcgateway.core.model.AssignedAddress //import co.nilin.opex.bcgateway.core.model.Currency interface AssignAddressService { suspend fun assignAddress(user: String, currency: String, gatewayUuid: String): List + /** + * Find the holder (uuid) and status of an address. + * @param address The on-chain address. + * @param memo Optional memo/tag for chains that require it. + * @param time If non-null, represents epoch milliseconds specifying the moment to check; if null, checks current. + * @return Pair of (uuid at the requested time or current, current status). Both may be null when unassigned. + */ + suspend fun findHolder(address: String, memo: String? = null, time: Long?): Pair } \ No newline at end of file diff --git a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/service/AssignAddressServiceImpl.kt b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/service/AssignAddressServiceImpl.kt index 83d1e1ce2..bf754dcb3 100644 --- a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/service/AssignAddressServiceImpl.kt +++ b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/service/AssignAddressServiceImpl.kt @@ -1,14 +1,20 @@ package co.nilin.opex.bcgateway.core.service import co.nilin.opex.bcgateway.core.api.AssignAddressService -import co.nilin.opex.bcgateway.core.model.* -import co.nilin.opex.bcgateway.core.spi.* +import co.nilin.opex.bcgateway.core.model.AddressStatus +import co.nilin.opex.bcgateway.core.model.AssignedAddress +import co.nilin.opex.bcgateway.core.spi.AssignedAddressHandler +import co.nilin.opex.bcgateway.core.spi.ChainLoader +import co.nilin.opex.bcgateway.core.spi.CryptoCurrencyHandlerV2 +import co.nilin.opex.bcgateway.core.spi.ReservedAddressHandler import co.nilin.opex.bcgateway.core.utils.LoggerDelegate import co.nilin.opex.common.OpexError import org.slf4j.Logger import org.springframework.beans.factory.annotation.Value import org.springframework.transaction.annotation.Transactional +import java.time.Instant import java.time.LocalDateTime +import java.time.ZoneId open class AssignAddressServiceImpl( private val currencyHandler: CryptoCurrencyHandlerV2, @@ -30,7 +36,7 @@ open class AssignAddressServiceImpl( ?: throw OpexError.CurrencyNotFound.exception() val requestedChain = chainLoader.fetchChainInfo(requestedGateway.chain) - val addressTypes = requestedChain?.addressTypes?: throw OpexError.BadRequest.exception() + val addressTypes = requestedChain?.addressTypes ?: throw OpexError.BadRequest.exception() val userAssignedAddresses = (assignedAddressHandler.fetchAssignedAddresses(user, addressTypes!!)).toMutableList() @@ -73,4 +79,12 @@ open class AssignAddressServiceImpl( return result.toMutableList() } + override suspend fun findHolder(address: String, memo: String?, time: Long?): Pair { + val at: LocalDateTime? = time?.let { ts -> + val instant = Instant.ofEpochMilli(ts) + LocalDateTime.ofInstant(instant, ZoneId.systemDefault()) + } + return assignedAddressHandler.findHolder(address, memo, at) + } + } diff --git a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/AssignedAddressHandler.kt b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/AssignedAddressHandler.kt index 9af419764..ad506df02 100644 --- a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/AssignedAddressHandler.kt +++ b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/AssignedAddressHandler.kt @@ -1,7 +1,9 @@ package co.nilin.opex.bcgateway.core.spi +import co.nilin.opex.bcgateway.core.model.AddressStatus import co.nilin.opex.bcgateway.core.model.AddressType import co.nilin.opex.bcgateway.core.model.AssignedAddress +import java.time.LocalDateTime interface AssignedAddressHandler { suspend fun fetchAssignedAddresses(user: String, addressTypes: List): List @@ -13,4 +15,10 @@ interface AssignedAddressHandler { suspend fun fetchExpiredAssignedAddresses(): List? + /** + * Find the holder (uuid) and status of an address at a given time. + * If [at] is null, returns the current holder (status Assigned) if any. + * Returns Pair, where both can be null when unassigned. + */ + suspend fun findHolder(address: String, memo: String?, at: LocalDateTime?): Pair } \ No newline at end of file diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/AssignedAddressRepository.kt b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/AssignedAddressRepository.kt index de431c1d4..e58e92dd5 100644 --- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/AssignedAddressRepository.kt +++ b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/AssignedAddressRepository.kt @@ -40,4 +40,11 @@ interface AssignedAddressRepository : ReactiveCrudRepository? + + @Query("select * from assigned_addresses where address = :address and (memo is null or memo = '' or memo = :memo) and assigned_date <= :at and (exp_time is null or exp_time > :at) order by assigned_date desc limit 1") + fun findHolderAt( + @Param("address") address: String, + @Param("memo") memo: String?, + @Param("at") at: LocalDateTime + ): Mono } \ No newline at end of file diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/AssignedAddressHandlerImpl.kt b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/AssignedAddressHandlerImpl.kt index 8c5220a3d..f820a56ae 100644 --- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/AssignedAddressHandlerImpl.kt +++ b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/AssignedAddressHandlerImpl.kt @@ -106,6 +106,18 @@ class AssignedAddressHandlerImpl( }?.toList() } + override suspend fun findHolder(address: String, memo: String?, at: LocalDateTime?): Pair { + + if (at == null) { + val current = assignedAddressRepository + .findByAddressAndMemoAndStatus(address, memo, AddressStatus.Assigned) + .awaitFirstOrNull() + return Pair(current?.uuid, current?.status) + } + val atModel = assignedAddressRepository.findHolderAt(address, memo, at).awaitFirstOrNull() + return Pair(atModel?.uuid, atModel?.status) + } + private suspend fun AssignedAddressModel.toDto(addressTypeMap: MutableMap): AssignedAddress { return AssignedAddress( this.uuid,