Skip to content

Commit c4e0620

Browse files
authored
Find the address holder at the specific time (#655)
1 parent ddde2fa commit c4e0620

7 files changed

Lines changed: 75 additions & 4 deletions

File tree

bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/config/SecurityConfig.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class SecurityConfig(private val webClient: WebClient) {
5252
.pathMatchers("/omni-balance/bc/**").hasAuthority("ROLE_admin")
5353
.pathMatchers("/actuator/**").permitAll()
5454
.pathMatchers("/scanner/**").permitAll()
55+
.pathMatchers(HttpMethod.GET,"/v1/address/*/holder").permitAll()
5556
.anyExchange().authenticated()
5657
.and()
5758
.oauth2ResourceServer()

bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/AddressController.kt

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package co.nilin.opex.bcgateway.app.controller
22

33
import co.nilin.opex.bcgateway.core.api.AssignAddressService
4+
import co.nilin.opex.bcgateway.core.model.AddressStatus
45
import co.nilin.opex.bcgateway.core.model.AssignedAddress
56
import co.nilin.opex.bcgateway.core.model.ReservedAddress
67
import co.nilin.opex.bcgateway.core.spi.AddressTypeHandler
@@ -21,10 +22,14 @@ import java.nio.charset.StandardCharsets
2122
class AddressController(
2223
private val assignAddressService: AssignAddressService,
2324
private val reservedAddressHandler: ReservedAddressHandler,
24-
private val addressTypeHandler: AddressTypeHandler
25+
private val addressTypeHandler: AddressTypeHandler,
2526
) {
2627
data class AssignAddressRequest(val uuid: String, val currency: String, val gatewayUuid: String)
2728
data class AssignAddressResponse(val addresses: List<AssignedAddress>)
29+
data class AddressHolderResponse(
30+
val uuid: String?,
31+
val currentStatus: AddressStatus?
32+
)
2833

2934
@PostMapping("/assign")
3035
suspend fun assignAddress(
@@ -49,6 +54,19 @@ class AddressController(
4954
// }.collect(Collectors.toList()))
5055
}
5156

57+
@GetMapping("/{address}/holder")
58+
suspend fun getAddressHolder(
59+
@PathVariable address: String,
60+
@RequestParam(required = false) memo: String?,
61+
@RequestParam(required = false) time: Long?
62+
): AddressHolderResponse {
63+
val (holderUuid, currentStatus) = assignAddressService.findHolder(address, memo, time)
64+
return AddressHolderResponse(
65+
uuid = holderUuid,
66+
currentStatus = currentStatus
67+
)
68+
}
69+
5270
/**
5371
* (address, regex, address_type)
5472
*/
@@ -67,4 +85,6 @@ class AddressController(
6785
// Do nothing in case of duplication (Or any constraint issue)
6886
runCatching { reservedAddressHandler.addReservedAddress(items) }
6987
}
88+
89+
7090
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
11
package co.nilin.opex.bcgateway.core.api
22

3+
import co.nilin.opex.bcgateway.core.model.AddressStatus
34
import co.nilin.opex.bcgateway.core.model.AssignedAddress
45

56
//import co.nilin.opex.bcgateway.core.model.Currency
67

78
interface AssignAddressService {
89
suspend fun assignAddress(user: String, currency: String, gatewayUuid: String): List<AssignedAddress>
10+
/**
11+
* Find the holder (uuid) and status of an address.
12+
* @param address The on-chain address.
13+
* @param memo Optional memo/tag for chains that require it.
14+
* @param time If non-null, represents epoch milliseconds specifying the moment to check; if null, checks current.
15+
* @return Pair of (uuid at the requested time or current, current status). Both may be null when unassigned.
16+
*/
17+
suspend fun findHolder(address: String, memo: String? = null, time: Long?): Pair<String?, AddressStatus?>
918
}

bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/service/AssignAddressServiceImpl.kt

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
package co.nilin.opex.bcgateway.core.service
22

33
import co.nilin.opex.bcgateway.core.api.AssignAddressService
4-
import co.nilin.opex.bcgateway.core.model.*
5-
import co.nilin.opex.bcgateway.core.spi.*
4+
import co.nilin.opex.bcgateway.core.model.AddressStatus
5+
import co.nilin.opex.bcgateway.core.model.AssignedAddress
6+
import co.nilin.opex.bcgateway.core.spi.AssignedAddressHandler
7+
import co.nilin.opex.bcgateway.core.spi.ChainLoader
8+
import co.nilin.opex.bcgateway.core.spi.CryptoCurrencyHandlerV2
9+
import co.nilin.opex.bcgateway.core.spi.ReservedAddressHandler
610
import co.nilin.opex.bcgateway.core.utils.LoggerDelegate
711
import co.nilin.opex.common.OpexError
812
import org.slf4j.Logger
913
import org.springframework.beans.factory.annotation.Value
1014
import org.springframework.transaction.annotation.Transactional
15+
import java.time.Instant
1116
import java.time.LocalDateTime
17+
import java.time.ZoneId
1218

1319
open class AssignAddressServiceImpl(
1420
private val currencyHandler: CryptoCurrencyHandlerV2,
@@ -30,7 +36,7 @@ open class AssignAddressServiceImpl(
3036
?: throw OpexError.CurrencyNotFound.exception()
3137

3238
val requestedChain = chainLoader.fetchChainInfo(requestedGateway.chain)
33-
val addressTypes = requestedChain?.addressTypes?: throw OpexError.BadRequest.exception()
39+
val addressTypes = requestedChain?.addressTypes ?: throw OpexError.BadRequest.exception()
3440

3541
val userAssignedAddresses =
3642
(assignedAddressHandler.fetchAssignedAddresses(user, addressTypes!!)).toMutableList()
@@ -73,4 +79,12 @@ open class AssignAddressServiceImpl(
7379
return result.toMutableList()
7480
}
7581

82+
override suspend fun findHolder(address: String, memo: String?, time: Long?): Pair<String?, AddressStatus?> {
83+
val at: LocalDateTime? = time?.let { ts ->
84+
val instant = Instant.ofEpochMilli(ts)
85+
LocalDateTime.ofInstant(instant, ZoneId.systemDefault())
86+
}
87+
return assignedAddressHandler.findHolder(address, memo, at)
88+
}
89+
7690
}

bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/AssignedAddressHandler.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package co.nilin.opex.bcgateway.core.spi
22

3+
import co.nilin.opex.bcgateway.core.model.AddressStatus
34
import co.nilin.opex.bcgateway.core.model.AddressType
45
import co.nilin.opex.bcgateway.core.model.AssignedAddress
6+
import java.time.LocalDateTime
57

68
interface AssignedAddressHandler {
79
suspend fun fetchAssignedAddresses(user: String, addressTypes: List<AddressType>): List<AssignedAddress>
@@ -13,4 +15,10 @@ interface AssignedAddressHandler {
1315

1416
suspend fun fetchExpiredAssignedAddresses(): List<AssignedAddress>?
1517

18+
/**
19+
* Find the holder (uuid) and status of an address at a given time.
20+
* If [at] is null, returns the current holder (status Assigned) if any.
21+
* Returns Pair<uuid, status>, where both can be null when unassigned.
22+
*/
23+
suspend fun findHolder(address: String, memo: String?, at: LocalDateTime?): Pair<String?, AddressStatus?>
1624
}

bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/AssignedAddressRepository.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,11 @@ interface AssignedAddressRepository : ReactiveCrudRepository<AssignedAddressMode
4040
@Param("now") now: LocalDateTime?,
4141
@Param("status") status: AddressStatus? = null
4242
): Flow<AssignedAddressModel>?
43+
44+
@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")
45+
fun findHolderAt(
46+
@Param("address") address: String,
47+
@Param("memo") memo: String?,
48+
@Param("at") at: LocalDateTime
49+
): Mono<AssignedAddressModel>
4350
}

bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/AssignedAddressHandlerImpl.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,18 @@ class AssignedAddressHandlerImpl(
106106
}?.toList()
107107
}
108108

109+
override suspend fun findHolder(address: String, memo: String?, at: LocalDateTime?): Pair<String?, AddressStatus?> {
110+
111+
if (at == null) {
112+
val current = assignedAddressRepository
113+
.findByAddressAndMemoAndStatus(address, memo, AddressStatus.Assigned)
114+
.awaitFirstOrNull()
115+
return Pair(current?.uuid, current?.status)
116+
}
117+
val atModel = assignedAddressRepository.findHolderAt(address, memo, at).awaitFirstOrNull()
118+
return Pair(atModel?.uuid, atModel?.status)
119+
}
120+
109121
private suspend fun AssignedAddressModel.toDto(addressTypeMap: MutableMap<Long, AddressType>): AssignedAddress {
110122
return AssignedAddress(
111123
this.uuid,

0 commit comments

Comments
 (0)