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
@@ -0,0 +1,13 @@
package co.nilin.opex.api.core.inout

import java.math.BigDecimal
import java.time.LocalDateTime

data class TransactionHistoryResponse(
val id: Long,
val currency: String,
val amount: BigDecimal,
val description: String?,
val ref: String?,
val date: Long
)
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package co.nilin.opex.api.core.spi

import co.nilin.opex.api.core.inout.OwnerLimitsResponse
import co.nilin.opex.api.core.inout.TransactionHistoryResponse
import co.nilin.opex.api.core.inout.Wallet

interface WalletProxy {
Expand All @@ -9,4 +10,24 @@ interface WalletProxy {

suspend fun getOwnerLimits(uuid: String?, token: String?): OwnerLimitsResponse

suspend fun getDepositTransactions(
uuid: String,
token: String?,
coin:String?,
startTime: Long,
endTime: Long,
limit: Int,
offset: Int
): List<TransactionHistoryResponse>

suspend fun getWithdrawTransactions(
uuid: String,
token: String?,
coin:String?,
startTime: Long,
endTime: Long,
limit: Int,
offset: Int
): List<TransactionHistoryResponse>

}
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
package co.nilin.opex.port.api.binance.controller

import co.nilin.opex.api.core.inout.TransactionHistoryResponse
import co.nilin.opex.api.core.spi.BlockchainGatewayProxy
import co.nilin.opex.api.core.spi.WalletProxy
import co.nilin.opex.port.api.binance.data.AssignAddressResponse
import co.nilin.opex.port.api.binance.data.DepositResponse
import co.nilin.opex.port.api.binance.data.Interval
import co.nilin.opex.port.api.binance.data.WithdrawResponse
import co.nilin.opex.port.api.binance.util.jwtAuthentication
import co.nilin.opex.port.api.binance.util.tokenValue
import org.springframework.security.core.annotation.CurrentSecurityContext
import org.springframework.security.core.context.SecurityContext
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import java.time.Instant
import java.time.LocalDateTime
import java.time.ZoneId
import java.util.*

@RestController
class WalletController(private val bcGatewayProxy: BlockchainGatewayProxy) {
class WalletController(
private val walletProxy: WalletProxy,
private val bcGatewayProxy: BlockchainGatewayProxy
) {

@GetMapping("/v1/capital/deposit/address")
suspend fun assignAddress(
@RequestParam("coin")
coin: String,
@RequestParam("network", required = false)
network: String,
network: String?,
@RequestParam(name = "recvWindow", required = false)
recvWindow: Long?, //The value cannot be greater than 60000
@RequestParam(name = "timestamp")
Expand All @@ -29,4 +42,103 @@ class WalletController(private val bcGatewayProxy: BlockchainGatewayProxy) {
return AssignAddressResponse(address?.address ?: "", coin, "", "")
}

@GetMapping("/v1/capital/deposit/hisrec")
suspend fun getDepositTransactions(
@RequestParam("coin", required = false)
coin: String?,
@RequestParam("network", required = false)
status: Int?,
@RequestParam("startTime", required = false)
startTime: Long?,
@RequestParam("endTime", required = false)
endTime: Long?,
@RequestParam("offset", required = false)
offset: Int?,
@RequestParam("limit", required = false)
limit: Int?,
@RequestParam(name = "recvWindow", required = false)
recvWindow: Long?, //The value cannot be greater than 60000
@RequestParam(name = "timestamp")
timestamp: Long,
@CurrentSecurityContext securityContext: SecurityContext
): List<DepositResponse> {
val validLimit = limit ?: 1000
val response = walletProxy.getDepositTransactions(
securityContext.jwtAuthentication().name,
securityContext.jwtAuthentication().tokenValue(),
coin,
startTime ?: Interval.ThreeMonth.getDate().time,
endTime ?: Date().time,
if (validLimit > 1000 || validLimit < 1) 1000 else validLimit,
offset ?: 0
)
return response.map {
DepositResponse(
it.amount,
it.currency,
"",
1,
"user_address",
null,
it.ref ?: it.id.toString(),
it.date,
0,
"1/1",
"1/1"
)
}
}

@GetMapping("/v1/capital/withdraw/history")
suspend fun getWithdrawTransactions(
@RequestParam("coin", required = false)
coin: String,
@RequestParam("withdrawOrderId", required = false)
withdrawOrderId: String?,
@RequestParam("status", required = false)
status: Int?,
@RequestParam("offset", required = false)
offset: Int?,
@RequestParam("limit", required = false)
limit: Int?,
@RequestParam("startTime", required = false)
startTime: Long?,
@RequestParam("endTime", required = false)
endTime: Long?,
@RequestParam(name = "recvWindow", required = false)
recvWindow: Long?, //The value cannot be greater than 60000
@RequestParam(name = "timestamp")
timestamp: Long,
@CurrentSecurityContext securityContext: SecurityContext
): List<WithdrawResponse> {
val validLimit = limit ?: 1000
val response = walletProxy.getWithdrawTransactions(
securityContext.jwtAuthentication().name,
securityContext.jwtAuthentication().tokenValue(),
coin,
startTime ?: Interval.ThreeMonth.getDate().time,
endTime ?: Date().time,
if (validLimit > 1000 || validLimit < 1) 1000 else validLimit,
offset ?: 0
)
return response.map {
WithdrawResponse(
"user_wallet",
it.amount,
LocalDateTime.ofInstant(Instant.ofEpochMilli(it.date), TimeZone.getDefault().toZoneId())
.toString()
.replace("T", " "),
it.currency,
it.id.toString(),
"",
"",
0,
1,
"0.001",
1,
it.id.toString()
)
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ import java.math.BigDecimal
data class BalanceResponse(
var asset: String,
var free: BigDecimal,
var locked: BigDecimal
var locked: BigDecimal,
var withdraw: BigDecimal
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package co.nilin.opex.port.api.binance.data

import java.math.BigDecimal

data class DepositResponse(
val amount: BigDecimal,
val coin: String,
val network: String,
val status: Int,
val address: String,
val addressTag: String?,
val txId: String,
val insertTime: Long,
val transferType: Int,
val unlockConfirm: String,
val confirmTimes: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ enum class Interval(val label: String, val unit: TimeUnit, val duration: Long) {
Day("1d", TimeUnit.DAYS, 1),
ThreeDays("3d", TimeUnit.DAYS, 3),
Week("1w", TimeUnit.DAYS, 7),
Month("1M", TimeUnit.DAYS, 31);
Month("1M", TimeUnit.DAYS, 31),
ThreeMonth("3M",TimeUnit.DAYS, 90);

private fun getOffsetTime() = unit.toMillis(duration)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package co.nilin.opex.port.api.binance.data

data class TransactionRequest(
val coin:String?,
val startTime: Long,
val endTime: Long,
val limit: Int,
val offset: Int
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package co.nilin.opex.port.api.binance.data

import java.math.BigDecimal

data class WithdrawResponse(
val address: String,
val amount: BigDecimal,
val applyTime: String,
val coin: String,
val id: String,
val withdrawOrderId: String,
val network: String,
val transferType: Int,
val status: Int,
val transactionFee: String,
val confirmNo: Int,
val txId: String,
)
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
package co.nilin.opex.port.api.binance.proxy

import co.nilin.opex.api.core.inout.OwnerLimitsResponse
import co.nilin.opex.api.core.inout.TransactionHistoryResponse
import co.nilin.opex.api.core.inout.Wallet
import co.nilin.opex.api.core.spi.WalletProxy
import co.nilin.opex.port.api.binance.data.TransactionRequest
import co.nilin.opex.port.api.binance.util.LoggerDelegate
import kotlinx.coroutines.reactive.awaitFirstOrElse
import kotlinx.coroutines.reactive.awaitSingle
import org.springframework.beans.factory.annotation.Value
import org.springframework.core.ParameterizedTypeReference
import org.springframework.http.HttpHeaders
import org.springframework.http.MediaType
import org.springframework.stereotype.Component
import org.springframework.web.reactive.function.client.WebClient
import org.springframework.web.reactive.function.client.body
import reactor.core.publisher.Mono
import java.math.BigDecimal
import java.time.LocalDateTime

Expand Down Expand Up @@ -49,4 +54,48 @@ class WalletProxyImpl(private val webClient: WebClient) : WalletProxy {
.bodyToMono(typeRef<OwnerLimitsResponse>())
.awaitSingle()
}

override suspend fun getDepositTransactions(
uuid: String,
token: String?,
coin:String?,
startTime: Long,
endTime: Long,
limit: Int,
offset: Int
): List<TransactionHistoryResponse> {
logger.info("fetching deposit transaction history for $uuid")
return webClient.post()
.uri("$baseUrl/transaction/deposit/$uuid")
.accept(MediaType.APPLICATION_JSON)
.header(HttpHeaders.AUTHORIZATION, "Bearer $token")
.body(Mono.just(TransactionRequest(coin, startTime, endTime, limit, offset)))
.retrieve()
.onStatus({ t -> t.isError }, { it.createException() })
.bodyToFlux(typeRef<TransactionHistoryResponse>())
.collectList()
.awaitFirstOrElse { emptyList() }
}

override suspend fun getWithdrawTransactions(
uuid: String,
token: String?,
coin:String?,
startTime: Long,
endTime: Long,
limit: Int,
offset: Int
): List<TransactionHistoryResponse> {
logger.info("fetching withdraw transaction history for $uuid")
return webClient.post()
.uri("$baseUrl/transaction/withdraw/$uuid")
.accept(MediaType.APPLICATION_JSON)
.header(HttpHeaders.AUTHORIZATION, "Bearer $token")
.body(Mono.just(TransactionRequest(coin, startTime, endTime, limit, offset)))
.retrieve()
.onStatus({ t -> t.isError }, { it.createException() })
.bodyToFlux(typeRef<TransactionHistoryResponse>())
.collectList()
.awaitFirstOrElse { emptyList() }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ object BalanceParser {
when (w.type) {
"exchange" -> locked = w.balance
"main" -> free = w.balance
"cashout" -> withdraw = w.balance
}
}
}
Expand All @@ -25,7 +26,7 @@ object BalanceParser {
if (w.asset == symbol)
return w

add(BalanceResponse(symbol, BigDecimal.ZERO, BigDecimal.ZERO))
add(BalanceResponse(symbol, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO))
return this.last()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,10 @@ interface TradeRepository : ReactiveCrudRepository<TradeModel, Long> {
select
f.start_time as open_time,
f.end_time as close_time,
(select taker_price from trades tt where tt.create_date >= f.start_time and tt.create_date < f.end_time order by tt.create_date asc limit 1) as open,
(select taker_price from trades tt where symbol = :symbol and tt.create_date >= f.start_time and tt.create_date < f.end_time order by tt.create_date asc limit 1) as open,
max(t.taker_price) as high,
min(t.taker_price) as low,
(select taker_price from trades tt where tt.create_date >= f.start_time and tt.create_date < f.end_time order by tt.create_date desc limit 1) as close,
(select taker_price from trades tt where symbol = :symbol and tt.create_date >= f.start_time and tt.create_date < f.end_time order by tt.create_date desc limit 1) as close,
sum(t.matched_quantity) as volume,
count(id) as trades
from trades t
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class WalletSyncServiceImpl(
val symbol = currencyLoader.findSymbol(deposit.chain, deposit.tokenAddress)
if (symbol != null) {
logger.info("sending deposit to $uuid - ${deposit.amount} $symbol")
walletProxy.transfer(uuid, symbol, deposit.amount)
walletProxy.transfer(uuid, symbol, deposit.amount, deposit.hash)
}
}
walletSyncRecordHandler.saveWalletSyncRecord(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ package co.nilin.opex.bcgateway.core.spi
import java.math.BigDecimal

interface WalletProxy {
suspend fun transfer(uuid: String, symbol: String, amount: BigDecimal)
suspend fun transfer(uuid: String, symbol: String, amount: BigDecimal, hash: String)
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ class WalletProxyImpl(@Qualifier("loadBalanced") private val webClient: WebClien
@Value("\${app.wallet.url}")
private lateinit var baseUrl: String

override suspend fun transfer(uuid: String, symbol: String, amount: BigDecimal) {
override suspend fun transfer(uuid: String, symbol: String, amount: BigDecimal, hash: String) {
webClient.post()
.uri(URI.create("$baseUrl/deposit/${amount}_$symbol/${uuid}_main"))
.uri(URI.create("$baseUrl/deposit/${amount}_$symbol/${uuid}_main?transferRef=$hash"))
.header("Content-Type", "application/json")
.retrieve()
.onStatus({ t -> t.isError }, { it.createException() })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class SecurityConfig(private val webClient: WebClient) {
.pathMatchers("/owner/**").hasAuthority("SCOPE_trust")
.pathMatchers("/withdraw").hasAuthority("SCOPE_trust")
.pathMatchers("/withdraw/**").hasAuthority("SCOPE_trust")
.pathMatchers("/transaction/**").hasAuthority("SCOPE_trust")
.pathMatchers("/admin/**").access { mono, authorizationContext ->
mono.map { auth ->
auth.authorities.any { authority -> authority.authority == "SCOPE_trust" }
Expand Down
Loading