diff --git a/BlockchainGateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/NetworkController.kt b/BlockchainGateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/NetworkController.kt new file mode 100644 index 000000000..d101e80f8 --- /dev/null +++ b/BlockchainGateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/NetworkController.kt @@ -0,0 +1,16 @@ +package co.nilin.opex.bcgateway.app.controller + +import co.nilin.opex.bcgateway.core.model.CurrencyInfo +import co.nilin.opex.bcgateway.core.spi.CurrencyLoader +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PathVariable +import org.springframework.web.bind.annotation.RestController + +@RestController +class NetworkController(val currencyLoader: CurrencyLoader) { + + @GetMapping("currency/{currency}") + suspend fun fetchCurrencyInfo(@PathVariable("currency") currency: String): CurrencyInfo { + return currencyLoader.fetchCurrencyInfo(currency) + } +} \ No newline at end of file diff --git a/BlockchainGateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/model/Address.kt b/BlockchainGateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/model/Address.kt index 4efb82bb0..be688312a 100644 --- a/BlockchainGateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/model/Address.kt +++ b/BlockchainGateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/model/Address.kt @@ -1,6 +1,6 @@ package co.nilin.opex.bcgateway.core.model -data class AddressType(val id: Long, val type: String, val addressRegex: String, val memoRegex: String) +data class AddressType(val id: Long, val type: String, val addressRegex: String, val memoRegex: String?) data class ReservedAddress(val address: String, val memo: String?, val type: AddressType) data class AssignedAddress( val uuid: String, diff --git a/BlockchainGateway/bc-gateway-ports/bc-persister-postgres/src/main/kotlin/co/nilin/opex/port/bcgateway/postgres/config/DemoPostgresConfig.kt b/BlockchainGateway/bc-gateway-ports/bc-persister-postgres/src/main/kotlin/co/nilin/opex/port/bcgateway/postgres/config/DemoPostgresConfig.kt new file mode 100644 index 000000000..7571e4043 --- /dev/null +++ b/BlockchainGateway/bc-gateway-ports/bc-persister-postgres/src/main/kotlin/co/nilin/opex/port/bcgateway/postgres/config/DemoPostgresConfig.kt @@ -0,0 +1,39 @@ +package co.nilin.opex.port.bcgateway.postgres.config + +import org.springframework.context.annotation.Configuration +import org.springframework.context.annotation.Profile +import org.springframework.r2dbc.core.DatabaseClient + +@Configuration +@Profile("demo") +class DemoPostgresConfig(db: DatabaseClient) { + + init { + val initDb = db.sql { + """ + insert into currency values ('BTC', 'Bitcoin') ON CONFLICT DO NOTHING; + insert into chains values ('Bit') ON CONFLICT DO NOTHING; + insert into chains values ('Bsc') ON CONFLICT DO NOTHING; + insert into address_types(id, address_type, address_regex) values (1, 'BTC', '.*') ON CONFLICT DO NOTHING; + insert into address_types(id, address_type, address_regex) values (2, 'ETH', '.*') ON CONFLICT DO NOTHING; + insert into chain_address_types (chain_name, addr_type_id) values ('Bit', 1) ON CONFLICT DO NOTHING; + insert into chain_address_types (chain_name, addr_type_id) values ('Bsc', 2) ON CONFLICT DO NOTHING; + insert into currency_implementations ( + id, + symbol, + chain, + token, + token_address, + token_name, + withdraw_enabled, + withdraw_fee, + withdraw_min + )values(1, 'BTC', 'Bit', false, null, null, true, 0.0001, 0.0001) + ,(2, 'BTC', 'Bsc', true, '0x1111', 'WBTC', true, 0.00001, 0.000001) ON CONFLICT DO NOTHING; + """ + } + initDb // initialize the database + .then() + .subscribe() // execute + } +} diff --git a/BlockchainGateway/bc-gateway-ports/bc-persister-postgres/src/main/kotlin/co/nilin/opex/port/bcgateway/postgres/config/PostgresConfig.kt b/BlockchainGateway/bc-gateway-ports/bc-persister-postgres/src/main/kotlin/co/nilin/opex/port/bcgateway/postgres/config/PostgresConfig.kt index c749663a6..a5081214e 100644 --- a/BlockchainGateway/bc-gateway-ports/bc-persister-postgres/src/main/kotlin/co/nilin/opex/port/bcgateway/postgres/config/PostgresConfig.kt +++ b/BlockchainGateway/bc-gateway-ports/bc-persister-postgres/src/main/kotlin/co/nilin/opex/port/bcgateway/postgres/config/PostgresConfig.kt @@ -13,9 +13,9 @@ class PostgresConfig(db: DatabaseClient) { """ CREATE TABLE IF NOT EXISTS address_types ( id SERIAL PRIMARY KEY, - address_type VARCHAR(72) NOT NULL, + address_type VARCHAR(20) NOT NULL, address_regex VARCHAR(72) NOT NULL, - memo_regex VARCHAR(72) NOT NULL + memo_regex VARCHAR(72) ); CREATE TABLE IF NOT EXISTS assigned_addresses ( id SERIAL PRIMARY KEY, diff --git a/BlockchainGateway/bc-gateway-ports/bc-persister-postgres/src/main/kotlin/co/nilin/opex/port/bcgateway/postgres/impl/CurrencyLoaderImpl.kt b/BlockchainGateway/bc-gateway-ports/bc-persister-postgres/src/main/kotlin/co/nilin/opex/port/bcgateway/postgres/impl/CurrencyLoaderImpl.kt index 118329469..539b3973f 100644 --- a/BlockchainGateway/bc-gateway-ports/bc-persister-postgres/src/main/kotlin/co/nilin/opex/port/bcgateway/postgres/impl/CurrencyLoaderImpl.kt +++ b/BlockchainGateway/bc-gateway-ports/bc-persister-postgres/src/main/kotlin/co/nilin/opex/port/bcgateway/postgres/impl/CurrencyLoaderImpl.kt @@ -21,11 +21,14 @@ class CurrencyLoaderImpl( private val currencyImplementationRepository: CurrencyImplementationRepository ) : CurrencyLoader { override suspend fun fetchCurrencyInfo(symbol: String): CurrencyInfo { - val currencyDao = currencyRepository.findBySymbol(symbol).awaitSingleOrNull() - if (currencyDao === null) return CurrencyInfo(Currency("", symbol), emptyList()) - val currencyImplDao = currencyImplementationRepository.findBySymbol(symbol) - val currency = Currency(currencyDao.symbol, currencyDao.name) - val implementations = currencyImplDao.map { projectCurrencyImplementation(it, currencyDao) } + val symbol = symbol.toUpperCase() + val currencyModel = currencyRepository.findBySymbol(symbol).awaitSingleOrNull() + if (currencyModel === null) { + return CurrencyInfo(Currency("", symbol), emptyList()) + } + val currencyImplModel = currencyImplementationRepository.findBySymbol(symbol) + val currency = Currency(currencyModel.symbol, currencyModel.name) + val implementations = currencyImplModel.map { projectCurrencyImplementation(it, currencyModel) } return CurrencyInfo(currency, implementations.toList()) } @@ -39,24 +42,24 @@ class CurrencyLoaderImpl( } private suspend fun projectCurrencyImplementation( - implDao: CurrencyImplementationModel, - currencyDao: CurrencyModel? = null + currencyImplementationModel: CurrencyImplementationModel, + currencyModel: CurrencyModel? = null ): CurrencyImplementation { - val addressTypesDao = chainRepository.findAddressTypesByName(implDao.chain) - val addressTypes = addressTypesDao.map { AddressType(it.id!!, it.type, it.addressRegex, it.memoRegex) } - val endpointsDao = chainRepository.findEndpointsByName(implDao.chain) - val endpoints = endpointsDao.map { Endpoint(it.url) } - val currencyDaoVal = currencyDao ?: currencyRepository.findBySymbol(implDao.symbol).awaitSingle() - val currency = Currency(currencyDaoVal.symbol, currencyDaoVal.name) + val addressTypesModel = chainRepository.findAddressTypesByName(currencyImplementationModel.chain) + val addressTypes = addressTypesModel.map { AddressType(it.id!!, it.type, it.addressRegex, it.memoRegex) } + val endpointsModel = chainRepository.findEndpointsByName(currencyImplementationModel.chain) + val endpoints = endpointsModel.map { Endpoint(it.url) } + val currencyModelVal = currencyModel ?: currencyRepository.findBySymbol(currencyImplementationModel.symbol).awaitSingle() + val currency = Currency(currencyModelVal.symbol, currencyModelVal.name) return CurrencyImplementation( currency, - Chain(implDao.chain, addressTypes.toList(), endpoints.toList()), - implDao.token, - implDao.tokenAddress, - implDao.tokenName, - implDao.withdrawEnabled, - implDao.withdrawFee, - implDao.withdrawMin + Chain(currencyImplementationModel.chain, addressTypes.toList(), endpoints.toList()), + currencyImplementationModel.token, + currencyImplementationModel.tokenAddress, + currencyImplementationModel.tokenName, + currencyImplementationModel.withdrawEnabled, + currencyImplementationModel.withdrawFee, + currencyImplementationModel.withdrawMin ) } } diff --git a/BlockchainGateway/bc-gateway-ports/bc-persister-postgres/src/main/kotlin/co/nilin/opex/port/bcgateway/postgres/model/AddressTypeModel.kt b/BlockchainGateway/bc-gateway-ports/bc-persister-postgres/src/main/kotlin/co/nilin/opex/port/bcgateway/postgres/model/AddressTypeModel.kt index 14d1d330f..dc971ed09 100644 --- a/BlockchainGateway/bc-gateway-ports/bc-persister-postgres/src/main/kotlin/co/nilin/opex/port/bcgateway/postgres/model/AddressTypeModel.kt +++ b/BlockchainGateway/bc-gateway-ports/bc-persister-postgres/src/main/kotlin/co/nilin/opex/port/bcgateway/postgres/model/AddressTypeModel.kt @@ -9,5 +9,5 @@ data class AddressTypeModel( @Id val id: Long?, @Column("address_type") val type: String, @Column("address_regex") val addressRegex: String, - @Column("memo_regex") val memoRegex: String + @Column("memo_regex") val memoRegex: String? ) \ No newline at end of file diff --git a/Utility/interceptors/src/main/kotlin/co/nilin/opex/utility/interceptor/FormDataWorkaroundFilter.java b/Utility/interceptors/src/main/kotlin/co/nilin/opex/utility/interceptor/FormDataWorkaroundFilter.java index 17dccc05f..a779571f9 100644 --- a/Utility/interceptors/src/main/kotlin/co/nilin/opex/utility/interceptor/FormDataWorkaroundFilter.java +++ b/Utility/interceptors/src/main/kotlin/co/nilin/opex/utility/interceptor/FormDataWorkaroundFilter.java @@ -9,37 +9,36 @@ import java.util.*; - public class FormDataWorkaroundFilter implements WebFilter { - @Override - public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { - final ServerHttpRequest request = exchange.getRequest(); - - final MultiValueMap queryParams = new LinkedMultiValueMap<>(); - - //add all content from form data to query params - exchange.getFormData().subscribe(queryParams::putAll); - - exchange.getMultipartData().subscribe(map -> { - map.forEach((key, value) -> { - List list = value; - list.forEach(item -> { - //add each form field parts to query params - if (item instanceof FormFieldPart) { - final FormFieldPart formFieldPart = (FormFieldPart) item; - queryParams.add(key, formFieldPart.value()); - } - }); - - }); - }); - - //add original query params to win identical name war - queryParams.putAll(request.getQueryParams()); - - return chain.filter(new FormDataServerWebExchangeDecorator(queryParams, exchange)); - } - + @Override + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + final ServerHttpRequest request = exchange.getRequest(); + + final MultiValueMap queryParams = new LinkedMultiValueMap<>(); + + return exchange.getFormData() + .doOnNext(queryParams::putAll) + .flatMap( it -> + exchange.getMultipartData().map(map -> { + map.forEach((key, value) -> { + value.forEach(item -> { + //add each form field parts to query params + if (item instanceof FormFieldPart) { + final FormFieldPart formFieldPart = (FormFieldPart) item; + queryParams.add(key, formFieldPart.value()); + } + }); + + }); + return map; + }) + ) + .doOnNext(it -> + queryParams.putAll(request.getQueryParams())) + .flatMap(it -> + chain.filter(new FormDataServerWebExchangeDecorator(queryParams, exchange)) + ); + } } diff --git a/Wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/controller/TransferController.kt b/Wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/controller/TransferController.kt index 5cda9748b..8aa53380d 100644 --- a/Wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/controller/TransferController.kt +++ b/Wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/controller/TransferController.kt @@ -72,7 +72,7 @@ class TransferController( Amount(sourceWallet.currency(), amount), description, transferRef, emptyMap() ) - ) + ).transferResult } @PostMapping("/deposit/{amount}_{symbol}/{receiverUuid}_{receiverWalletType}") @@ -122,6 +122,6 @@ class TransferController( Amount(sourceWallet.currency(), amount), description, transferRef, emptyMap() ) - ) + ).transferResult } } diff --git a/Wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/controller/WithdrawController.kt b/Wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/controller/WithdrawController.kt index bb524b0c6..eabc6b3fd 100644 --- a/Wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/controller/WithdrawController.kt +++ b/Wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/controller/WithdrawController.kt @@ -1,36 +1,18 @@ package co.nilin.opex.wallet.app.controller -import co.nilin.opex.port.wallet.postgres.dao.WithdrawRepository -import co.nilin.opex.port.wallet.postgres.model.WithdrawModel -import co.nilin.opex.utility.error.data.OpexError -import co.nilin.opex.utility.error.data.OpexException -import co.nilin.opex.wallet.core.inout.TransferCommand -import co.nilin.opex.wallet.core.inout.TransferResult -import co.nilin.opex.wallet.core.model.Amount -import co.nilin.opex.wallet.core.service.TransferService -import co.nilin.opex.wallet.core.spi.CurrencyService -import co.nilin.opex.wallet.core.spi.WalletManager -import co.nilin.opex.wallet.core.spi.WalletOwnerManager +import co.nilin.opex.wallet.core.inout.* +import co.nilin.opex.wallet.core.service.WithdrawService import io.swagger.annotations.ApiResponse import io.swagger.annotations.Example import io.swagger.annotations.ExampleProperty -import kotlinx.coroutines.flow.toList -import kotlinx.coroutines.reactive.awaitFirstOrElse import org.springframework.beans.factory.annotation.Value import org.springframework.web.bind.annotation.* -import java.lang.IllegalArgumentException -import java.lang.RuntimeException import java.math.BigDecimal import java.security.Principal @RestController class WithdrawController( - val withdrawRepository: WithdrawRepository, - val transferService: TransferService, - val walletManager: WalletManager, - val walletOwnerManager: WalletOwnerManager, - val currencyService: CurrencyService, - @Value("\${app.system.uuid}") val systemUuid: String + val withdrawService: WithdrawService ) { @GetMapping("/admin/withdraw") @@ -46,14 +28,14 @@ class WithdrawController( ) suspend fun searchWithdraws( @RequestParam("uuid", required = false) uuid: String?, - @RequestParam("transaction_ref", required = false) txRef: String?, + @RequestParam("withdraw_id", required = false) withdrawId: String?, + @RequestParam("currency", required = false) currency: String?, @RequestParam("dest_transaction_ref", required = false) destTxRef: String?, @RequestParam("dest_address", required = false) destAddress: String?, @RequestParam("status", required = false) status: List? - ): List { - return withdrawRepository - .findByCriteria(uuid, txRef, destTxRef, destAddress, status?.isEmpty() ?: true, status ?: listOf("")) - .toList() + ): List { + return withdrawService + .findByCriteria(uuid, withdrawId, currency, destTxRef, destAddress, status?.isEmpty() ?: true, status ?: listOf("")) } @GetMapping("/withdraw") @@ -69,21 +51,22 @@ class WithdrawController( ) suspend fun getMyWithdraws( principal: Principal, - @RequestParam("transaction_ref", required = false) txRef: String?, + @RequestParam("withdraw_id", required = false) withdrawId: String?, + @RequestParam("currency", required = false) currency: String?, @RequestParam("dest_transaction_ref", required = false) destTxRef: String?, @RequestParam("dest_address", required = false) destAddress: String?, @RequestParam("status", required = false) status: List? - ): List { - return withdrawRepository + ): List { + return withdrawService .findByCriteria( principal.name, - txRef, + withdrawId, + currency, destTxRef, destAddress, status?.isEmpty() ?: true, status ?: listOf("") ) - .toList() } @PostMapping("/withdraw/{amount}_{symbol}") @@ -101,41 +84,16 @@ class WithdrawController( principal: Principal, @PathVariable("symbol") symbol: String, @PathVariable("amount") amount: BigDecimal, - @PathVariable("description") description: String?, - @PathVariable("transferRef") transferRef: String?, - @RequestParam("fee", required = false) fee: Double?, - @RequestParam("destCurrency") destCurrency: String?, - @RequestParam("destAddress") destAddress: String?, + @RequestParam("description", required = false) description: String?, + @RequestParam("transferRef", required = false) transferRef: String?, + @RequestParam("fee") fee: BigDecimal, + @RequestParam("destCurrency") destCurrency: String, + @RequestParam("destAddress") destAddress: String, + @RequestParam("destNetwork") destNetwork: String, @RequestParam("destNote", required = false) destNote: String?, - ): TransferResult { - val currency = currencyService.getCurrency(symbol)?: throw OpexException(OpexError.CurrencyNotFound) - val owner = walletOwnerManager.findWalletOwner(principal.name) - ?: throw OpexException(OpexError.WalletOwnerNotFound) - val sourceWallet = walletManager.findWalletByOwnerAndCurrencyAndType(owner, "main", currency) - ?: throw OpexException(OpexError.WalletNotFound) - - val receiverWallet = walletManager.findWalletByOwnerAndCurrencyAndType( - owner, "cashout", currency - ) ?: walletManager.createWallet( - owner, - Amount(currency, BigDecimal.ZERO), - currency, - "cashout" - ) - val allAdditionalData = mutableMapOf() - allAdditionalData["fee"] = fee?.toString() - allAdditionalData["destCurrency"] = destCurrency - allAdditionalData["destAddress"] = destAddress - allAdditionalData["destNote"] = destNote - allAdditionalData["description"] = description - return transferService.transfer( - TransferCommand( - sourceWallet, - receiverWallet, - Amount(sourceWallet.currency(), amount), - description, transferRef, allAdditionalData - ) - ) + ): WithdrawResult { + return withdrawService.requestWithdraw(WithdrawCommand(principal.name, symbol, + amount, description, transferRef, destCurrency, destAddress, destNetwork, destNote, fee)) } @PostMapping( @@ -153,33 +111,10 @@ class WithdrawController( ) suspend fun rejectWithdraw( @PathVariable("id") withdrawId: String, - @RequestParam("statusReason", required = false) statusReason: String?, + @RequestParam("statusReason") statusReason: String, @RequestParam("destNote", required = false) destNote: String? - ): TransferResult { - val withdraw = withdrawRepository.findById(withdrawId) - .awaitFirstOrElse { throw RuntimeException("No matching withdraw request") } - val sourceWallet = walletManager.findWalletById(withdraw.wallet) ?: throw RuntimeException("Wallet not found") - val receiverWallet = walletManager.findWalletByOwnerAndCurrencyAndType( - sourceWallet.owner(), "main", sourceWallet.currency() - ) ?: walletManager.createWallet( - sourceWallet.owner(), - Amount(sourceWallet.currency(), BigDecimal.ZERO), - sourceWallet.currency(), - "main" - ) - val allAdditionalData = mutableMapOf() - allAdditionalData["statusReason"] = statusReason - allAdditionalData["destNote"] = destNote - allAdditionalData["transactionId"] = withdraw.transactionId - allAdditionalData["status"] = "REJECTED" - return transferService.transfer( - TransferCommand( - sourceWallet, - receiverWallet, - Amount(sourceWallet.currency(), withdraw.amount), - withdraw.description, allAdditionalData["transactionRef"], allAdditionalData - ) - ) + ): WithdrawResult { + return withdrawService.rejectWithdraw(WithdrawRejectCommand(withdrawId, statusReason, destNote)) } @PostMapping("/admin/withdraw/{id}/accept") @@ -196,32 +131,9 @@ class WithdrawController( suspend fun acceptWithdraw( @PathVariable("id") withdrawId: String, @RequestParam("destTransactionRef", required = false) destTransactionRef: String?, - @RequestParam("destNote", required = false) destNote: String? - ): TransferResult { - val system = walletOwnerManager.findWalletOwner(systemUuid) ?: throw IllegalArgumentException() - val withdraw = withdrawRepository.findById(withdrawId) - .awaitFirstOrElse { throw RuntimeException("No matching withdraw request") } - val sourceWallet = walletManager.findWalletById(withdraw.wallet) ?: throw RuntimeException("Wallet not found") - val receiverWallet = walletManager.findWalletByOwnerAndCurrencyAndType( - system, "main", sourceWallet.currency() - ) ?: walletManager.createWallet( - system, - Amount(sourceWallet.currency(), BigDecimal.ZERO), - sourceWallet.currency(), - "main" - ) - val allAdditionalData = mutableMapOf() - allAdditionalData["destNote"] = destNote - allAdditionalData["destTransactionRef"] = destTransactionRef - allAdditionalData["transactionId"] = withdraw.transactionId - allAdditionalData["status"] = "DONE" - return transferService.transfer( - TransferCommand( - sourceWallet, - receiverWallet, - Amount(sourceWallet.currency(), withdraw.amount), - withdraw.description, allAdditionalData["transactionRef"], allAdditionalData - ) - ) + @RequestParam("destNote", required = false) destNote: String?, + @RequestParam("fee", required = false) fee: BigDecimal = BigDecimal.ZERO, + ): WithdrawResult { + return withdrawService.acceptWithdraw(WithdrawAcceptCommand(withdrawId, destTransactionRef, destNote, fee)) } } diff --git a/Wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/listener/WalletListenerImpl.kt b/Wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/listener/WalletListenerImpl.kt index 1894c7db8..fccdacd1e 100644 --- a/Wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/listener/WalletListenerImpl.kt +++ b/Wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/listener/WalletListenerImpl.kt @@ -21,34 +21,10 @@ class WalletListenerImpl(val withdrawRepository: WithdrawRepository) : WalletLis transaction: String, additionalData: Map? ) { - if (me.type().equals("cashout")) { - val fee = (additionalData?.get("fee") ?: "0").toBigDecimal() - withdrawRepository.save( - WithdrawModel( - null, transaction , me.id()!!, finalAmount, fee, finalAmount.subtract(fee), additionalData?.get("destCurrency"), additionalData?.get("destAddress"), additionalData?.get("destNote"), null, additionalData?.get("description"), null, "CREATED" - ) - ).awaitFirst() - } + } override suspend fun onWithdraw(me: Wallet, destWallet: Wallet, amount: Amount, transaction: String, additionalData: Map?) { - if (me.type().equals("cashout")) { - val withdrawModel = withdrawRepository.findByWalletAndTransactionId( - me.id()!!, additionalData!!.get("transactionId") ?: throw RuntimeException("transactionId is required") - ).awaitFirstOrElse { throw RuntimeException("No matching withdraw request") } - if (withdrawModel!!.status != "CREATED") { - throw RuntimeException("This withdraw request processed before") - } - val newStatus = additionalData.get("status") ?: throw RuntimeException("status is required") - withdrawModel.status = newStatus - withdrawModel.statusReason = additionalData.get("statusReason") - if ( additionalData.get("destNote") != null) { - withdrawModel.destNote += "\n---------------\n" + additionalData.get("destNote") - } - if (newStatus == "DONE") { - withdrawModel.destTransactionRef = additionalData.get("destTransactionRef") - } - withdrawRepository.save(withdrawModel).awaitFirst() - } + } } \ No newline at end of file diff --git a/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/TransferResult.kt b/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/TransferResult.kt index fea370441..58c14d7c8 100644 --- a/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/TransferResult.kt +++ b/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/TransferResult.kt @@ -14,3 +14,8 @@ data class TransferResult( val destWalletType: String, val receivedAmount: Amount ) + +data class TransferResultDetailed( + val transferResult: TransferResult, + val tx: String +) \ No newline at end of file diff --git a/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/WithdrawAcceptCommand.kt b/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/WithdrawAcceptCommand.kt new file mode 100644 index 000000000..0b54e7f4d --- /dev/null +++ b/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/WithdrawAcceptCommand.kt @@ -0,0 +1,10 @@ +package co.nilin.opex.wallet.core.inout + +import java.math.BigDecimal + +class WithdrawAcceptCommand( + val withdrawId: String, + val destTransactionRef: String?, + val destNote: String?, + val appliedFee: BigDecimal +) \ No newline at end of file diff --git a/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/WithdrawCommand.kt b/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/WithdrawCommand.kt new file mode 100644 index 000000000..75cdeac91 --- /dev/null +++ b/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/WithdrawCommand.kt @@ -0,0 +1,16 @@ +package co.nilin.opex.wallet.core.inout + +import java.math.BigDecimal + +class WithdrawCommand( + val uuid: String + , val symbol: String + , val amount: BigDecimal + , val description: String? + , val transferRef: String? + , val destCurrency: String + , val destAddress: String + , val destNetwork: String + , val destNote: String? + , val acceptedFee: BigDecimal +) \ No newline at end of file diff --git a/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/WithdrawRejectCommand.kt b/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/WithdrawRejectCommand.kt new file mode 100644 index 000000000..5eb515b9e --- /dev/null +++ b/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/WithdrawRejectCommand.kt @@ -0,0 +1,7 @@ +package co.nilin.opex.wallet.core.inout + +class WithdrawRejectCommand( + val withdrawId: String, + val statusReason: String, + val destNote: String? +) \ No newline at end of file diff --git a/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/WithdrawResponse.kt b/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/WithdrawResponse.kt new file mode 100644 index 000000000..8adcdfc19 --- /dev/null +++ b/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/WithdrawResponse.kt @@ -0,0 +1,24 @@ +package co.nilin.opex.wallet.core.inout + +import java.math.BigDecimal +import java.util.* + +class WithdrawResponse( + val withdrawId: Long, + val ownerUuid: String, + val requestDate: Date, + val finalizedDate: Date?, + val requestTransaction: String, + val finalizedTransaction: String?, + val acceptedFee: BigDecimal, + val appliedFee: BigDecimal?, + val amount: BigDecimal?, + val destAmount: BigDecimal?, + val destCurrency: String?, + val destAddress: String?, + val destNetwork: String?, + var destNote: String?, + var destTransactionRef: String?, + val statusReason: String?, + val status: String +) \ No newline at end of file diff --git a/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/WithdrawResult.kt b/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/WithdrawResult.kt new file mode 100644 index 000000000..db93db417 --- /dev/null +++ b/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/WithdrawResult.kt @@ -0,0 +1,4 @@ +package co.nilin.opex.wallet.core.inout + +class WithdrawResult(val withdrawId: Long, val status: String){ +} \ No newline at end of file diff --git a/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/model/Transaction.kt b/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/model/Transaction.kt index 551d563f2..b62b4be96 100644 --- a/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/model/Transaction.kt +++ b/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/model/Transaction.kt @@ -1,5 +1,6 @@ package co.nilin.opex.wallet.core.model import java.math.BigDecimal +import java.time.LocalDateTime -data class Transaction(val sourceWallet: Wallet, val destWallet: Wallet, val sourceAmount: BigDecimal, val destAmount: BigDecimal, val description: String?, val transferRef: String?) \ No newline at end of file +data class Transaction(val sourceWallet: Wallet, val destWallet: Wallet, val sourceAmount: BigDecimal, val destAmount: BigDecimal, val description: String?, val transferRef: String?, val transactionDate: LocalDateTime) \ No newline at end of file diff --git a/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/model/Withdraw.kt b/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/model/Withdraw.kt new file mode 100644 index 000000000..f4011ed6d --- /dev/null +++ b/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/model/Withdraw.kt @@ -0,0 +1,22 @@ +package co.nilin.opex.wallet.core.model + +import java.math.BigDecimal + +class Withdraw( + val withdrawId: Long? = null, + val ownerUuid: String, + val wallet: Long, + val amount: BigDecimal, + val requestTransaction: String, + val finalizedTransaction: String?, + val acceptedFee: BigDecimal, + val appliedFee: BigDecimal?, + val destAmount: BigDecimal?, + val destCurrency: String?, + val destAddress: String?, + val destNetwork: String?, + var destNote: String?, + var destTransactionRef: String?, + val statusReason: String?, + val status: String +) \ No newline at end of file diff --git a/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/service/TransferService.kt b/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/service/TransferService.kt index 7ccfdef51..addeb4bdf 100644 --- a/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/service/TransferService.kt +++ b/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/service/TransferService.kt @@ -6,6 +6,7 @@ import co.nilin.opex.wallet.core.exc.NotEnoughBalanceException import co.nilin.opex.wallet.core.exc.WithdrawLimitExceededException import co.nilin.opex.wallet.core.inout.TransferCommand import co.nilin.opex.wallet.core.inout.TransferResult +import co.nilin.opex.wallet.core.inout.TransferResultDetailed import co.nilin.opex.wallet.core.model.Amount import co.nilin.opex.wallet.core.model.Transaction import co.nilin.opex.wallet.core.spi.CurrencyRateService @@ -27,7 +28,7 @@ class TransferService( val transactionManager: TransactionManager ) { @Transactional - suspend fun transfer(transferCommand: TransferCommand): TransferResult { + suspend fun transfer(transferCommand: TransferCommand): TransferResultDetailed { //pre transfer hook (dispatch pre transfer event) val srcWallet = transferCommand.sourceWallet val srcWalletOwner = srcWallet.owner() @@ -43,7 +44,6 @@ class TransferService( val destWallet = transferCommand.destWallet val destWalletOwner = destWallet.owner() - val balance = destWallet.balance() //check wallet if can accept the value type val amountToTransfer = currencyRateService.convert(transferCommand.amount, destWallet.currency()) @@ -61,7 +61,8 @@ class TransferService( transferCommand.amount.amount, amountToTransfer, transferCommand.description, - transferCommand.transferRef + transferCommand.transferRef, + LocalDateTime.now() ) ) //get the result and add to return result type @@ -70,15 +71,18 @@ class TransferService( //post transfer hook(dispatch post transfer event) //notify balance change - return TransferResult( - Date().time, srcWalletOwner.uuid() - , srcWallet.type() - , srcWalletBalance - , walletManager.findWalletById(srcWallet.id()!!)!!.balance() - , transferCommand.amount - , destWalletOwner.uuid() - , destWallet.type() - , Amount(destWallet.currency(), amountToTransfer) + return TransferResultDetailed( + TransferResult( + Date().time, + srcWalletOwner.uuid(), + srcWallet.type(), + srcWalletBalance, + walletManager.findWalletById(srcWallet.id()!!)!!.balance(), + transferCommand.amount, + destWalletOwner.uuid(), + destWallet.type(), + Amount(destWallet.currency(), amountToTransfer) + ), tx ) } } \ No newline at end of file diff --git a/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/service/WithdrawService.kt b/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/service/WithdrawService.kt new file mode 100644 index 000000000..bd48370e8 --- /dev/null +++ b/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/service/WithdrawService.kt @@ -0,0 +1,158 @@ +package co.nilin.opex.wallet.core.service + +import co.nilin.opex.wallet.core.inout.* +import co.nilin.opex.wallet.core.model.Amount +import co.nilin.opex.wallet.core.model.Withdraw +import co.nilin.opex.wallet.core.spi.CurrencyService +import co.nilin.opex.wallet.core.spi.WalletManager +import co.nilin.opex.wallet.core.spi.WalletOwnerManager +import co.nilin.opex.wallet.core.spi.WithdrawPersister +import org.springframework.beans.factory.annotation.Value +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import java.lang.IllegalArgumentException +import java.lang.RuntimeException +import java.math.BigDecimal + +@Service +class WithdrawService( + val withdrawPersister: WithdrawPersister, + val walletManager: WalletManager, + val walletOwnerManager: WalletOwnerManager, + val currencyService: CurrencyService, + val transferService: TransferService, + @Value("\${app.system.uuid}") val systemUuid: String +) { + @Transactional + suspend fun requestWithdraw( + withdrawCommand: WithdrawCommand + ): WithdrawResult { + val currency = currencyService.getCurrency(withdrawCommand.symbol) ?: throw IllegalArgumentException() + val owner = walletOwnerManager.findWalletOwner(withdrawCommand.uuid) ?: throw IllegalArgumentException() + val sourceWallet = + walletManager.findWalletByOwnerAndCurrencyAndType(owner, "main", currency) + ?: throw IllegalArgumentException() + val receiverWallet = walletManager.findWalletByOwnerAndCurrencyAndType( + owner, "cashout", currency + ) ?: walletManager.createWallet( + owner, + Amount(currency, BigDecimal.ZERO), + currency, + "cashout" + ) + val transferResultDetailed = transferService.transfer( + TransferCommand( + sourceWallet, receiverWallet, Amount(currency, withdrawCommand.amount), withdrawCommand.description, withdrawCommand.transferRef, emptyMap() + ) + ) + val withdraw = withdrawPersister.persist( + Withdraw( + null, owner.uuid(), receiverWallet.id()!!, withdrawCommand.amount, + transferResultDetailed.tx, null, + withdrawCommand.acceptedFee, null, + null, withdrawCommand.destCurrency, + withdrawCommand.destAddress, withdrawCommand.destNetwork, + withdrawCommand.destNote, null, null, "CREATED" + ) + ) + return WithdrawResult(withdraw.withdrawId!!, withdraw.status) + } + + @Transactional + suspend fun acceptWithdraw( + acceptCommand: WithdrawAcceptCommand + ): WithdrawResult { + val system = walletOwnerManager.findWalletOwner(systemUuid) ?: throw IllegalArgumentException() + val withdraw = withdrawPersister.findById(acceptCommand.withdrawId) ?: throw RuntimeException("No matching withdraw request") + if (withdraw.status != "CREATED") { + throw RuntimeException("This withdraw request processed before") + } + if (withdraw.acceptedFee < acceptCommand.appliedFee) { + throw RuntimeException("Applied Fee ${acceptCommand.appliedFee} is bigger than accepted Fee ${withdraw.acceptedFee}") + } + val sourceWallet = walletManager.findWalletById(withdraw.wallet) ?: throw RuntimeException("Wallet not found") + val receiverWallet = walletManager.findWalletByOwnerAndCurrencyAndType( + system, "main", sourceWallet.currency() + ) ?: walletManager.createWallet( + system, + Amount(sourceWallet.currency(), BigDecimal.ZERO), + sourceWallet.currency(), + "main" + ) + val transferResultDetailed = transferService.transfer( + TransferCommand( + sourceWallet, + receiverWallet, + Amount(sourceWallet.currency(), withdraw.amount), + null, null, emptyMap() + ) + ) + + val updateWithdraw = withdrawPersister.persist( + Withdraw( + withdraw.withdrawId, withdraw.ownerUuid, + withdraw.wallet, withdraw.amount, + withdraw.requestTransaction, transferResultDetailed.tx, withdraw.acceptedFee, withdraw.appliedFee, + withdraw.amount.subtract(acceptCommand.appliedFee), + withdraw.destCurrency, + withdraw.destAddress, withdraw.destNetwork, + withdraw.destNote ?: "" + "-----------" + (acceptCommand.destNote ?: ""), null, acceptCommand.destTransactionRef!!, "DONE" + ) + ) + + return WithdrawResult(withdraw.withdrawId!!, updateWithdraw.status) + + } + + @Transactional + suspend fun rejectWithdraw( + rejectCommand: WithdrawRejectCommand + ): WithdrawResult { + val withdraw = withdrawPersister.findById(rejectCommand.withdrawId) ?: throw RuntimeException("No matching withdraw request") + if (withdraw.status != "CREATED") { + throw RuntimeException("This withdraw request processed before") + } + val sourceWallet = walletManager.findWalletById(withdraw.wallet) ?: throw RuntimeException("Wallet not found") + val receiverWallet = walletManager.findWalletByOwnerAndCurrencyAndType( + sourceWallet.owner(), "main", sourceWallet.currency() + ) ?: walletManager.createWallet( + sourceWallet.owner(), + Amount(sourceWallet.currency(), BigDecimal.ZERO), + sourceWallet.currency(), + "main" + ) + val transferResultDetailed = transferService.transfer( + TransferCommand( + sourceWallet, + receiverWallet, + Amount(sourceWallet.currency(), withdraw.amount), + rejectCommand.statusReason, null, emptyMap() + ) + ) + val updateWithdraw = withdrawPersister.persist( + Withdraw( + withdraw.withdrawId, withdraw.ownerUuid, + withdraw.wallet, withdraw.amount, + withdraw.requestTransaction, transferResultDetailed.tx, withdraw.acceptedFee, null, + null, + withdraw.destCurrency, + withdraw.destAddress, withdraw.destNetwork, + withdraw.destNote ?: "" + "-----------" + (rejectCommand.destNote ?: ""), null, rejectCommand.statusReason, "REJECTED" + ) + ) + return WithdrawResult(withdraw.withdrawId!!, updateWithdraw.status) + } + + suspend fun findByCriteria( + ownerUuid: String?, + withdrawId: String?, + currency: String?, + destTxRef: String?, + destAddress: String?, + noStatus: Boolean, + status: List? + ): List { + return withdrawPersister + .findByCriteria(ownerUuid, withdrawId, currency, destTxRef, destAddress, noStatus, status) + } +} \ No newline at end of file diff --git a/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/spi/WithdrawPersister.kt b/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/spi/WithdrawPersister.kt new file mode 100644 index 000000000..3172441f6 --- /dev/null +++ b/Wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/spi/WithdrawPersister.kt @@ -0,0 +1,19 @@ +package co.nilin.opex.wallet.core.spi + +import co.nilin.opex.wallet.core.inout.WithdrawResponse +import co.nilin.opex.wallet.core.model.Withdraw + +interface WithdrawPersister { + suspend fun findByCriteria( + ownerUuid: String?, + withdrawId: String?, + currency: String?, + destTxRef: String?, + destAddress: String?, + noStatus: Boolean, + status: List? + ): List + + suspend fun persist(withdraw: Withdraw):Withdraw + suspend fun findById(withdrawId: String): Withdraw? +} \ No newline at end of file diff --git a/Wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/port/wallet/postgres/config/PostgresConfig.kt b/Wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/port/wallet/postgres/config/PostgresConfig.kt index e9f9d8b93..6a5d2706d 100644 --- a/Wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/port/wallet/postgres/config/PostgresConfig.kt +++ b/Wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/port/wallet/postgres/config/PostgresConfig.kt @@ -10,7 +10,7 @@ class PostgresConfig(db: DatabaseClient) { init { val initDb = db.sql { - """ + """ CREATE TABLE IF NOT EXISTS currency ( name VARCHAR(25) PRIMARY KEY, symbol VARCHAR(25) NOT NULL UNIQUE, @@ -86,12 +86,16 @@ class PostgresConfig(db: DatabaseClient) { CREATE TABLE IF NOT EXISTS withdraws ( id SERIAL PRIMARY KEY, - transaction_id VARCHAR(20) NOT NULL UNIQUE, + uuid VARCHAR(36) NOT NULL, + req_transaction_id VARCHAR(20) NOT NULL UNIQUE, + final_transaction_id VARCHAR(20) UNIQUE, wallet numeric, amount decimal, - fee decimal, - net_amount decimal, + accepted_fee decimal, + applied_fee decimal, + dest_amount decimal, dest_currency VARCHAR(20), + dest_network VARCHAR(20), dest_address VARCHAR(80), dest_notes VARCHAR(2000), dest_transaction_ref VARCHAR(100), diff --git a/Wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/port/wallet/postgres/dao/WithdrawRepository.kt b/Wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/port/wallet/postgres/dao/WithdrawRepository.kt index feacaca27..eba601790 100644 --- a/Wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/port/wallet/postgres/dao/WithdrawRepository.kt +++ b/Wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/port/wallet/postgres/dao/WithdrawRepository.kt @@ -29,14 +29,17 @@ interface WithdrawRepository : ReactiveCrudRepository { " join wallet wm on wm.id = wth.wallet " + " join wallet_owner wo on wm.owner = wo.id " + " where ( :owner is null or wo.uuid = :owner) " + - " and (:tx_id is null or wth.transaction_id = :tx_id )" + + " and (:withdraw_id is null or wth.id = :withdraw_id )" + " and (:dest_transaction_ref is null or wth.dest_transaction_ref = :dest_transaction_ref)"+ " and (:dest_address is null or wth.dest_address = :dest_address)"+ - " and (:no_status IS TRUE or wth.status in (:status))" + " and (:no_status IS TRUE or wth.status in (:status))" + + " and (:currency is null or wm.currency in (:currency))" + + " order by wth.id asc" ) fun findByCriteria( @Param("owner") ownerUuid: String?, - @Param("tx_id") withdrawId: String?, + @Param("withdraw_id") withdrawId: Long?, + @Param("currency") currency: String?, @Param("dest_transaction_ref") destTxRef: String?, @Param("dest_address") destAddress: String?, @Param("no_status") noStatus: Boolean, diff --git a/Wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/port/wallet/postgres/impl/WithdrawPersisterImpl.kt b/Wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/port/wallet/postgres/impl/WithdrawPersisterImpl.kt new file mode 100644 index 000000000..90711d739 --- /dev/null +++ b/Wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/port/wallet/postgres/impl/WithdrawPersisterImpl.kt @@ -0,0 +1,110 @@ +package co.nilin.opex.port.wallet.postgres.impl + +import co.nilin.opex.port.wallet.postgres.dao.TransactionRepository +import co.nilin.opex.port.wallet.postgres.dao.WithdrawRepository +import co.nilin.opex.port.wallet.postgres.model.WithdrawModel +import co.nilin.opex.wallet.core.inout.WithdrawResponse +import co.nilin.opex.wallet.core.model.Withdraw +import co.nilin.opex.wallet.core.spi.WithdrawPersister +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.toList +import kotlinx.coroutines.reactive.awaitFirst +import kotlinx.coroutines.reactive.awaitFirstOrNull +import org.springframework.stereotype.Service +import java.time.ZoneId +import java.util.* + +@Service +class WithdrawPersisterImpl( + val withdrawRepository: WithdrawRepository, val transactionRepository: TransactionRepository +) : WithdrawPersister { + override suspend fun findByCriteria(ownerUuid: String?, withdrawId: String?, currency: String?, destTxRef: String?, destAddress: String?, noStatus: Boolean, status: List?): List { + return withdrawRepository + .findByCriteria(ownerUuid, withdrawId?.toLong(), currency, destTxRef, destAddress, noStatus, status) + .map { wm -> + val reqTx = transactionRepository.findById(wm.requestTransaction.toLong()).awaitFirst() + val finalTx = if (wm.finalizedTransaction == null) + null + else + transactionRepository.findById(wm.finalizedTransaction.toLong()).awaitFirstOrNull() + WithdrawResponse( + wm.id!!, + wm.ownerUuid, Date.from( + reqTx.txDate.atZone(ZoneId.systemDefault()).toInstant() + ), if (finalTx == null) + null + else + Date.from( + finalTx.txDate.atZone(ZoneId.systemDefault()).toInstant() + ), reqTx.id.toString(), finalTx?.id.toString(), wm.acceptedFee, wm.appliedFee, wm.amount, wm.destAmount, wm.destCurrency, wm.destAddress, wm.destNetwork, wm.destNote, wm.destTransactionRef, wm.statusReason, wm.status + ) + } + .toList() + } + + override suspend fun persist(withdraw: Withdraw): Withdraw { + val wm = withdrawRepository.save( + WithdrawModel( + withdraw.withdrawId, + withdraw.ownerUuid, + withdraw.wallet, + withdraw.amount, + withdraw.requestTransaction, + withdraw.finalizedTransaction, + withdraw.acceptedFee, + withdraw.appliedFee, + withdraw.destAmount, + withdraw.destCurrency, + withdraw.destNetwork, + withdraw.destAddress, + withdraw.destNote, + withdraw.destTransactionRef, + withdraw.statusReason, + withdraw.status + ) + ).awaitFirst() + return Withdraw( + wm.id, + withdraw.ownerUuid, + withdraw.wallet, + withdraw.amount, + withdraw.requestTransaction, + withdraw.finalizedTransaction, + withdraw.acceptedFee, + withdraw.appliedFee, + withdraw.destAmount, + withdraw.destCurrency, + withdraw.destNetwork, + withdraw.destAddress, + withdraw.destNote, + withdraw.destTransactionRef, + withdraw.statusReason, + withdraw.status + ) + } + + override suspend fun findById(withdrawId: String): Withdraw? { + return withdrawRepository.findById(withdrawId) + .map { withdraw -> + Withdraw( + withdraw.id, + withdraw.ownerUuid, + withdraw.wallet, + withdraw.amount, + withdraw.requestTransaction, + withdraw.finalizedTransaction, + withdraw.acceptedFee, + withdraw.appliedFee, + withdraw.destAmount, + withdraw.destCurrency, + withdraw.destNetwork, + withdraw.destAddress, + withdraw.destNote, + withdraw.destTransactionRef, + withdraw.statusReason, + withdraw.status + ) + } + .awaitFirstOrNull() + } +} \ No newline at end of file diff --git a/Wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/port/wallet/postgres/model/CurrencyModel.kt b/Wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/port/wallet/postgres/model/CurrencyModel.kt index 3beed44a9..abdf4359b 100644 --- a/Wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/port/wallet/postgres/model/CurrencyModel.kt +++ b/Wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/port/wallet/postgres/model/CurrencyModel.kt @@ -8,7 +8,7 @@ import org.springframework.data.relational.core.mapping.Column import org.springframework.data.relational.core.mapping.Table @Table("currency") -class CurrencyModel( +data class CurrencyModel( @JsonIgnore @Id @Column("name") val name_: String, @JsonIgnore @Column("symbol") val symbol_: String, @JsonIgnore @Column("precision") val precision_: Int diff --git a/Wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/port/wallet/postgres/model/WithdrawModel.kt b/Wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/port/wallet/postgres/model/WithdrawModel.kt index dea70fee0..ddf9bffcd 100644 --- a/Wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/port/wallet/postgres/model/WithdrawModel.kt +++ b/Wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/port/wallet/postgres/model/WithdrawModel.kt @@ -7,16 +7,19 @@ import java.math.BigDecimal @Table("withdraws") class WithdrawModel(@Id var id: Long?, - @Column("transaction_id") val transactionId: String, + @Column("uuid") val ownerUuid: String, @Column("wallet") val wallet: Long, @Column("amount") val amount: BigDecimal, - @Column("fee") val fee: BigDecimal, - @Column("net_amount") val netAmount: BigDecimal, + @Column("req_transaction_id") val requestTransaction: String, + @Column("final_transaction_id") val finalizedTransaction: String?, + @Column("accepted_fee") val acceptedFee: BigDecimal, + @Column("applied_fee") val appliedFee: BigDecimal?, + @Column("dest_amount") val destAmount: BigDecimal?, @Column("dest_currency") val destCurrency: String?, + @Column("dest_network") val destNetwork: String?, @Column("dest_address") val destAddress: String?, @Column("dest_notes") var destNote: String?, @Column("dest_transaction_ref") var destTransactionRef: String?, - @Column("description") val description: String?, @Column("status_reason") var statusReason: String?, @Column("status") var status: String ) \ No newline at end of file