Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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<AssignedAddress>)
data class AddressHolderResponse(
val uuid: String?,
val currentStatus: AddressStatus?
)

@PostMapping("/assign")
suspend fun assignAddress(
Expand All @@ -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)
*/
Expand All @@ -67,4 +85,6 @@ class AddressController(
// Do nothing in case of duplication (Or any constraint issue)
runCatching { reservedAddressHandler.addReservedAddress(items) }
}


}
Original file line number Diff line number Diff line change
@@ -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<AssignedAddress>
/**
* 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<String?, AddressStatus?>
}
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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()
Expand Down Expand Up @@ -73,4 +79,12 @@ open class AssignAddressServiceImpl(
return result.toMutableList()
}

override suspend fun findHolder(address: String, memo: String?, time: Long?): Pair<String?, AddressStatus?> {
val at: LocalDateTime? = time?.let { ts ->
val instant = Instant.ofEpochMilli(ts)
LocalDateTime.ofInstant(instant, ZoneId.systemDefault())
}
return assignedAddressHandler.findHolder(address, memo, at)
}

}
Original file line number Diff line number Diff line change
@@ -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<AddressType>): List<AssignedAddress>
Expand All @@ -13,4 +15,10 @@ interface AssignedAddressHandler {

suspend fun fetchExpiredAssignedAddresses(): List<AssignedAddress>?

/**
* 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<uuid, status>, where both can be null when unassigned.
*/
suspend fun findHolder(address: String, memo: String?, at: LocalDateTime?): Pair<String?, AddressStatus?>
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,11 @@ interface AssignedAddressRepository : ReactiveCrudRepository<AssignedAddressMode
@Param("now") now: LocalDateTime?,
@Param("status") status: AddressStatus? = null
): Flow<AssignedAddressModel>?

@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<AssignedAddressModel>
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,18 @@ class AssignedAddressHandlerImpl(
}?.toList()
}

override suspend fun findHolder(address: String, memo: String?, at: LocalDateTime?): Pair<String?, AddressStatus?> {

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<Long, AddressType>): AssignedAddress {
return AssignedAddress(
this.uuid,
Expand Down
Loading