Skip to content

Commit

Permalink
Merge pull request #11 from NTF-marketplace/refactor/transaction
Browse files Browse the repository at this point in the history
Refactor/transaction
  • Loading branch information
min-96 authored Sep 4, 2024
2 parents bed431a + 36ed4f4 commit 2e39eb4
Show file tree
Hide file tree
Showing 18 changed files with 306 additions and 179 deletions.
6 changes: 1 addition & 5 deletions src/main/kotlin/com/api/admin/config/RabbitMQConfig.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package com.api.admin.config

import org.springframework.amqp.core.Binding
import org.springframework.amqp.core.BindingBuilder
import org.springframework.amqp.core.DirectExchange

import org.springframework.amqp.core.FanoutExchange
import org.springframework.amqp.core.Queue
import org.springframework.amqp.rabbit.connection.ConnectionFactory
import org.springframework.amqp.rabbit.core.RabbitTemplate
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter
Expand Down Expand Up @@ -33,5 +30,4 @@ class RabbitMQConfig {

@Bean
fun transferExchange() = createExchange("transferExchange")

}
19 changes: 6 additions & 13 deletions src/main/kotlin/com/api/admin/controller/AdminController.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ class AdminController(
@RequestParam address: String,
@RequestBody request: DepositRequest,
): Mono<ResponseEntity<Void>> {
return transferService.getTransferData(address, request.chainType, request.transactionHash, AccountType.DEPOSIT)
return transferService.getTransferData(address, request.chainType, request.transactionHash, AccountType.DEPOSIT, request.accountLogId)
.then(Mono.just(ResponseEntity.ok().build<Void>()))
.onErrorResume {
Mono.just(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build())
Mono.just(ResponseEntity.status(HttpStatus.BAD_REQUEST).build())
}
}

Expand All @@ -37,13 +37,9 @@ class AdminController(
@RequestBody request: WithdrawERC20Request,
): Mono<ResponseEntity<Void>> {
println("Received withdraw request for address: $address with amount: ${request.amount}")
return web3jService.createTransactionERC20(address, request.amount, request.chainType)
return web3jService.createTransactionERC20(address, request.amount, request.chainType,request.accountLogId)
.doOnSuccess { println("Transaction successful") }
.then(Mono.just(ResponseEntity.ok().build<Void>()))
.doOnError { e ->
println("Error in withdrawERC20: ${e.message}")
e.printStackTrace()
}
.then(Mono.just(ResponseEntity.ok().build()))
}


Expand All @@ -53,11 +49,8 @@ class AdminController(
@RequestParam address: String,
@RequestBody request: WithdrawERC721Request,
): Mono<ResponseEntity<Void>> {
return web3jService.createTransactionERC721(address, request.nftId)
.then(Mono.just(ResponseEntity.ok().build<Void>()))
.onErrorResume {
Mono.just(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build())
}
return web3jService.createTransactionERC721(address, request.nftId,request.accountLogId)
.then(Mono.just(ResponseEntity.ok().build()))
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ import com.api.admin.enums.ChainType
data class DepositRequest(
val chainType: ChainType,
val transactionHash: String,
val accountLogId: Long,
)

Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ import java.math.BigInteger
data class WithdrawERC20Request(
val chainType: ChainType,
val amount: BigDecimal,
val accountLogId: Long,
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ package com.api.admin.controller.dto

data class WithdrawERC721Request(
val nftId: Long,
val accountLogId: Long,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.api.admin.domain.transferFailLog

import com.api.admin.enums.TransferType
import org.springframework.data.annotation.Id
import org.springframework.data.relational.core.mapping.Table
import java.sql.Timestamp

@Table("transfer_fail_log")
data class TransferFailLog(
@Id val id: Long? = null,
val wallet: String,
val timestamp: Long? = System.currentTimeMillis(),
val transactionHash: String?,
val errorMessage: String,
val transferType: TransferType,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.api.admin.domain.transferFailLog

import org.springframework.data.repository.reactive.ReactiveCrudRepository

interface TransferFailLogRepository: ReactiveCrudRepository<TransferFailLog,Long> {
}
4 changes: 3 additions & 1 deletion src/main/kotlin/com/api/admin/enums/Enum.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,7 @@ enum class TokenType {
MATIC, ETH
}


enum class TransactionStatusType {
SUCCESS, FAILURE
}

Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class AdminEventListener(
) {

@EventListener
fun onDepositSend(event: AdminTransferCreatedEvent) {
fun onTransferSend(event: AdminTransferCreatedEvent) {
provider.transferSend(event.transfer)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.api.admin.rabbitMQ.event.dto

import com.api.admin.enums.TransferType
import java.math.BigDecimal

data class AdminTransferDetailResponse(
val nftId: Long?,
val transferType: TransferType,
val balance: BigDecimal?,
)
Original file line number Diff line number Diff line change
@@ -1,18 +1,43 @@
package com.api.admin.rabbitMQ.event.dto

import com.api.admin.domain.transfer.Transfer
import com.api.admin.domain.transferFailLog.TransferFailLog
import com.api.admin.enums.AccountType
import com.api.admin.enums.ChainType
import com.api.admin.enums.TransactionStatusType
import com.api.admin.enums.TransferType
import com.api.admin.rabbitMQ.event.dto.AdminTransferResponse.Companion.toResponse
import java.math.BigDecimal


data class AdminTransferResponse(
val id: Long,
val walletAddress: String,
val nftId: Long?,
val timestamp: Long,
val accountLogId: Long,
val accountType: AccountType,
val transferType: TransferType,
val balance: BigDecimal?,
val chainType: ChainType,
)
val transactionStatusType: TransactionStatusType,
val adminTransferDetailResponse: AdminTransferDetailResponse?
) {
companion object {
fun Transfer.toResponse(accountId: Long) = AdminTransferResponse(
accountLogId = accountId,
accountType = this.accountType,
transferType = this.transferType,
transactionStatusType = TransactionStatusType.SUCCESS,
adminTransferDetailResponse = AdminTransferDetailResponse(
nftId = this.nftId,
transferType =this.transferType,
balance = this.balance
)
)

fun TransferFailLog.toResponse(accountId: Long,accountType: AccountType) = AdminTransferResponse(
accountLogId = accountId,
accountType = accountType,
transferType = this.transferType,
transactionStatusType = TransactionStatusType.FAILURE,
adminTransferDetailResponse = null

)

}
}
38 changes: 38 additions & 0 deletions src/main/kotlin/com/api/admin/service/TransferFailService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.api.admin.service

import com.api.admin.domain.transferFailLog.TransferFailLog
import com.api.admin.domain.transferFailLog.TransferFailLogRepository
import com.api.admin.enums.AccountType
import com.api.admin.enums.TransferType
import com.api.admin.rabbitMQ.event.dto.AdminTransferCreatedEvent
import com.api.admin.rabbitMQ.event.dto.AdminTransferResponse.Companion.toResponse
import org.springframework.context.ApplicationEventPublisher
import org.springframework.stereotype.Service
import reactor.core.publisher.Mono

@Service
class TransferFailService(
private val transferFailLogRepository: TransferFailLogRepository,
private val eventPublisher: ApplicationEventPublisher,
) {

fun save(accountId: Long,
address: String,
transactionHash: String?,
message: String,
transferType: TransferType,
accountType: AccountType
): Mono<Void> {
return transferFailLogRepository.save(
TransferFailLog(
wallet = address,
transactionHash = transactionHash,
errorMessage = message,
transferType = transferType
)
).doOnSuccess {
eventPublisher.publishEvent(AdminTransferCreatedEvent(this, it.toResponse(accountId,accountType)))
}.then()

}
}
57 changes: 26 additions & 31 deletions src/main/kotlin/com/api/admin/service/TransferService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ import com.api.admin.enums.ChainType
import com.api.admin.enums.TransferType
import com.api.admin.properties.AdminInfoProperties
import com.api.admin.rabbitMQ.event.dto.AdminTransferCreatedEvent
import com.api.admin.rabbitMQ.event.dto.AdminTransferResponse
import com.api.admin.rabbitMQ.event.dto.AdminTransferResponse.Companion.toResponse
import com.api.admin.service.dto.InfuraTransferDetail
import org.springframework.context.ApplicationEventPublisher
import org.springframework.stereotype.Service
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
import reactor.core.scheduler.Schedulers
import java.math.BigDecimal
import java.math.BigInteger
import java.time.Instant
Expand All @@ -25,33 +26,36 @@ class TransferService(
private val nftService: NftService,
private val adminInfoProperties: AdminInfoProperties,
) {

private val transferEventSignature = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
private val nativeTransferEventSignature = "0xe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c4"

companion object{
const val transferEventSignature = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
const val nativeTransferEventSignature = "0xe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c4"
}

fun getTransferData(
wallet: String,
chainType: ChainType,
transactionHash: String,
accountType: AccountType,
accountLogId: Long
): Mono<Void> {
println("transactionHash : $transactionHash")
return transferRepository.existsByTransactionHash(transactionHash)
.flatMap {
if (it) {
.flatMap { exists ->
if (exists) {
Mono.error(IllegalStateException("Transaction already exists"))
} else {
saveTransfer(wallet, chainType, transactionHash, accountType)
.doOnNext { transfer ->
eventPublisher.publishEvent(AdminTransferCreatedEvent(this, transfer.toResponse()))
}
.then()
Mono.defer { saveTransfer(wallet, chainType, transactionHash, accountType,accountLogId).then() }
.subscribeOn(Schedulers.boundedElastic())
.then(Mono.empty())
}
}
}

fun saveTransfer(wallet: String, chainType: ChainType, transactionHash: String, accountType: AccountType): Flux<Transfer> {
fun saveTransfer(wallet: String,
chainType: ChainType,
transactionHash: String,
accountType: AccountType,
accountId: Long
): Flux<Void> {
return infuraApiService.getTransferLog(chainType, transactionHash)
.flatMapMany { response ->
val result = response.result
Expand All @@ -62,30 +66,21 @@ class TransferService(
Flux.error(IllegalStateException("Transaction logs not found for transaction hash: $transactionHash"))
}
}
.flatMap { transfer -> transferRepository.save(transfer) }
.flatMap { transfer -> transferRepository.save(transfer).doOnNext { println("having ?") }
.doOnSuccess {transfer ->
eventPublisher.publishEvent(AdminTransferCreatedEvent(this, transfer.toResponse(accountId)))
}.then()
}
}


private fun Transfer.toResponse() = AdminTransferResponse(
id = this.id!!,
walletAddress = this.wallet,
nftId = this.nftId,
timestamp = this.timestamp,
accountType = this.accountType,
transferType = this.transferType,
balance = this.balance,
chainType = this.chainType,
)

fun InfuraTransferDetail.toEntity(wallet: String, accountType: AccountType, chainType: ChainType): Mono<Transfer> {
return Mono.just(this)
.flatMap { log ->
println("log : " + log.toString())
when {
log.topics[0] == nativeTransferEventSignature ->
handleERC20Transfer(log, wallet, accountType, chainType,TransferType.NATIVE)
// log.topics[0] == transferEventSignature && log.topics.size == 3 ->
// handleERC20Transfer(log, wallet, accountType, chainType, TransferType.ERC20)
// log.topics[0] == transferEventSignature && log.topics.size == 3 ->
// handleERC20Transfer(log, wallet, accountType, chainType, TransferType.ERC20)
log.topics[0] == transferEventSignature && log.topics.size == 4 ->
handleERC721Transfer(log, wallet, accountType, chainType)
else -> Mono.empty()
Expand All @@ -98,7 +93,7 @@ class TransferService(
val to = parseAddress(log.topics[3])
val amount = when (transferType) {
TransferType.NATIVE -> parseNativeTransferAmount(log.data)
// TransferType.ERC20 -> toBigDecimal(log.data)
// TransferType.ERC20 -> toBigDecimal(log.data)
else -> BigDecimal.ZERO
}

Expand Down
Loading

0 comments on commit 2e39eb4

Please sign in to comment.