Skip to content

Commit 46bcee1

Browse files
committed
transactions
1 parent dfc194c commit 46bcee1

14 files changed

Lines changed: 140 additions & 30 deletions

File tree

src/main/kotlin/io/openfuture/api/component/ScaffoldCompiler.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import io.openfuture.api.domain.scaffold.ScaffoldPropertyDto
44
import io.openfuture.api.exception.CompileException
55
import org.apache.commons.io.FileUtils
66
import org.ethereum.solidity.compiler.CompilationResult
7+
import org.ethereum.solidity.compiler.CompilationResult.ContractMetadata
78
import org.ethereum.solidity.compiler.SolidityCompiler
89
import org.ethereum.solidity.compiler.SolidityCompiler.Options.*
910
import org.springframework.stereotype.Component
@@ -27,7 +28,7 @@ class ScaffoldCompiler(
2728
private const val RETURN_VARIABLES = "CUSTOM_RETURN_VARIABLES"
2829
}
2930

30-
fun compileScaffold(properties: List<ScaffoldPropertyDto>): CompilationResult.ContractMetadata {
31+
fun compile(properties: List<ScaffoldPropertyDto>): ContractMetadata {
3132
val scaffold = generateScaffold(properties)
3233
val compiled = SolidityCompiler.compile(scaffold, true, ABI, BIN, INTERFACE, METADATA)
3334

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package io.openfuture.api.component
2+
3+
import io.openfuture.api.model.scaffold.Transaction
4+
import io.openfuture.api.repository.ScaffoldRepository
5+
import io.openfuture.api.service.TransactionService
6+
import org.slf4j.LoggerFactory
7+
import org.springframework.stereotype.Component
8+
import org.web3j.protocol.core.methods.response.Log
9+
10+
/**
11+
* @author Kadach Alexey
12+
*/
13+
@Component
14+
class TransactionHandler(
15+
private val service: TransactionService,
16+
private val scaffoldRepository: ScaffoldRepository
17+
) {
18+
19+
companion object {
20+
private val log = LoggerFactory.getLogger(TransactionHandler::class.java)
21+
}
22+
23+
fun handle(transactionLog: Log) {
24+
val scaffold = scaffoldRepository.findByAddress(transactionLog.address)
25+
26+
if (null == scaffold) {
27+
log.warn("Scaffold with address ${transactionLog.address} not found")
28+
return
29+
}
30+
31+
service.save(Transaction(scaffold, transactionLog))
32+
}
33+
34+
}

src/main/kotlin/io/openfuture/api/config/SecurityConfig.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ class SecurityConfig(
1818
override fun configure(http: HttpSecurity) {
1919
http
2020
.authorizeRequests()
21-
.anyRequest().authenticated()
21+
.anyRequest().authenticated()
2222

2323
.and()
2424

2525
.oauth2Login()
26-
.successHandler(AuthenticationSuccessHandler(service))
26+
.successHandler(AuthenticationSuccessHandler(service))
2727
}
2828

2929
}

src/main/kotlin/io/openfuture/api/config/handler/AuthenticationSuccessHandler.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.openfuture.api.config.handler
22

3+
import io.openfuture.api.model.auth.User
34
import io.openfuture.api.service.UserService
45
import org.springframework.security.core.Authentication
56
import org.springframework.security.oauth2.core.oidc.user.OidcUser
@@ -20,7 +21,7 @@ class AuthenticationSuccessHandler(
2021
val persistUser = service.findByGoogleId(principal.subject)
2122

2223
if (null == persistUser) {
23-
service.save(principal)
24+
service.save(User(principal.subject))
2425
}
2526

2627
response.sendRedirect("/scaffolds")

src/main/kotlin/io/openfuture/api/domain/scaffold/DeployScaffoldRequest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ data class DeployScaffoldRequest(
1414
@field:NotBlank @field:Digits(integer = Int.MAX_VALUE, fraction = Int.MAX_VALUE) var fiatAmount: String? = null,
1515
@field:NotNull var conversionCurrency: CurrencyType? = null,
1616
@field:NotBlank @field:Digits(integer = Int.MAX_VALUE, fraction = Int.MAX_VALUE) var currencyConversionValue: String? = null,
17-
@field:NotNull var scaffoldFields: List<ScaffoldPropertyDto> = listOf()
17+
@field:NotNull var scaffoldProperties: List<ScaffoldPropertyDto> = listOf()
1818
)
1919

2020
enum class CurrencyType(private val value: String) {

src/main/kotlin/io/openfuture/api/model/auth/User.kt

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package io.openfuture.api.model.auth
22

33
import io.openfuture.api.model.base.BaseModel
4-
import org.springframework.security.oauth2.core.oidc.user.OidcUser
54
import javax.persistence.Column
65
import javax.persistence.Entity
76
import javax.persistence.OneToMany
@@ -23,8 +22,4 @@ class User(
2322
@OneToMany(mappedBy = "user")
2423
val openKeys: MutableSet<OpenKey> = mutableSetOf()
2524

26-
): BaseModel() {
27-
28-
constructor(user: OidcUser) : this(user.subject)
29-
30-
}
25+
): BaseModel()
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package io.openfuture.api.model.scaffold
2+
3+
import io.openfuture.api.model.base.BaseModel
4+
import org.web3j.protocol.core.methods.response.Log
5+
import javax.persistence.*
6+
7+
/**
8+
* @author Kadach Alexey
9+
*/
10+
@Entity
11+
@Table(name = "transactions")
12+
class Transaction(
13+
14+
@ManyToOne
15+
@JoinColumn(name = "scaffold_id", nullable = false)
16+
val scaffold: Scaffold,
17+
18+
@Column(name = "data", nullable = false)
19+
val data: String,
20+
21+
@Column(name = "type", nullable = false)
22+
val type: String
23+
24+
): BaseModel() {
25+
26+
constructor(scaffold: Scaffold, log: Log): this(scaffold, log.data, log.type)
27+
28+
}

src/main/kotlin/io/openfuture/api/repository/Repositories.kt

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package io.openfuture.api.repository
33
import io.openfuture.api.model.auth.OpenKey
44
import io.openfuture.api.model.auth.User
55
import io.openfuture.api.model.scaffold.Scaffold
6+
import io.openfuture.api.model.scaffold.Transaction
67
import org.springframework.data.domain.Page
78
import org.springframework.data.domain.Pageable
89
import org.springframework.data.jpa.repository.JpaRepository
@@ -13,25 +14,29 @@ import org.springframework.stereotype.Repository
1314
interface BaseRepository<T> : JpaRepository<T, Long>
1415

1516
@Repository
16-
interface UserRepository: BaseRepository<User> {
17+
interface UserRepository : BaseRepository<User> {
1718

1819
fun findByGoogleId(googleId: String): User?
1920

2021
}
2122

2223
@Repository
23-
interface ScaffoldRepository: BaseRepository<Scaffold> {
24+
interface ScaffoldRepository : BaseRepository<Scaffold> {
2425

2526
fun findByAddress(address: String): Scaffold?
2627

2728
fun findAllByUser(user: User, pageable: Pageable): Page<Scaffold>
2829

2930
}
3031

31-
interface OpenKeyRepository: BaseRepository<OpenKey> {
32+
@Repository
33+
interface OpenKeyRepository : BaseRepository<OpenKey> {
3234

3335
fun findByValueAndUser(value: String, user: User): OpenKey?
3436

3537
fun findAllByUser(user: User): List<OpenKey>
3638

37-
}
39+
}
40+
41+
@Repository
42+
interface TransactionRepository : BaseRepository<Transaction>

src/main/kotlin/io/openfuture/api/service/DefaultOpenKeyService.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@ import org.springframework.transaction.annotation.Transactional
1313
@Service
1414
class DefaultOpenKeyService(
1515
private val repository: OpenKeyRepository
16-
): OpenKeyService {
16+
) : OpenKeyService {
1717

1818
@Transactional(readOnly = true)
19-
override fun get(key: String, user: User): OpenKey = repository.findByValueAndUser(key, user)
20-
?: throw NotFoundException("Not found key $key")
19+
override fun getAllByUser(user: User): List<OpenKey> = repository.findAllByUser(user)
2120

2221
@Transactional(readOnly = true)
23-
override fun getByUser(user: User): List<OpenKey> = repository.findAllByUser(user)
22+
override fun get(key: String, user: User): OpenKey = repository.findByValueAndUser(key, user)
23+
?: throw NotFoundException("Not found key $key")
2424

2525
@Transactional
2626
override fun save(user: User): OpenKey = repository.save(OpenKey(user))

src/main/kotlin/io/openfuture/api/service/DefaultScaffoldService.kt

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.openfuture.api.service
22

33
import io.openfuture.api.component.ScaffoldCompiler
4+
import io.openfuture.api.component.TransactionHandler
45
import io.openfuture.api.config.propety.BlockchainProperties
56
import io.openfuture.api.domain.scaffold.DeployScaffoldRequest
67
import io.openfuture.api.exception.DeployException
@@ -18,7 +19,9 @@ import org.web3j.abi.datatypes.Type
1819
import org.web3j.abi.datatypes.Utf8String
1920
import org.web3j.abi.datatypes.generated.Uint256
2021
import org.web3j.protocol.Web3j
22+
import org.web3j.protocol.core.DefaultBlockParameterName.EARLIEST
2123
import org.web3j.protocol.core.DefaultBlockParameterName.LATEST
24+
import org.web3j.protocol.core.methods.request.EthFilter
2225
import org.web3j.protocol.core.methods.request.Transaction.createContractTransaction
2326
import org.web3j.protocol.http.HttpService
2427
import org.web3j.tx.gas.DefaultGasProvider.GAS_LIMIT
@@ -38,7 +41,8 @@ class DefaultScaffoldService(
3841
private val repository: ScaffoldRepository,
3942
private val compiler: ScaffoldCompiler,
4043
private val properties: BlockchainProperties,
41-
private val openKeyService: OpenKeyService
44+
private val openKeyService: OpenKeyService,
45+
private val transactionHandler: TransactionHandler
4246
) : ScaffoldService {
4347

4448
private lateinit var web3: Web3j
@@ -47,6 +51,12 @@ class DefaultScaffoldService(
4751
@PostConstruct
4852
fun init() {
4953
web3 = Web3j.build(HttpService(properties.url))
54+
repository.findAll().forEach {
55+
val filter = EthFilter(EARLIEST, LATEST, it.address)
56+
web3.ethLogObservable(filter).subscribe {
57+
transactionHandler.handle(it)
58+
}
59+
}
5060
}
5161

5262
@Transactional(readOnly = true)
@@ -58,7 +68,7 @@ class DefaultScaffoldService(
5868

5969
@Transactional
6070
override fun deploy(request: DeployScaffoldRequest, user: User): Scaffold {
61-
val compiledScaffold = compiler.compileScaffold(request.scaffoldFields)
71+
val compiledScaffold = compiler.compile(request.scaffoldProperties)
6272
val openKey = openKeyService.get(request.openKey!!, user)
6373
val encodedConstructor = FunctionEncoder.encodeConstructor(asList<Type<*>>(
6474
Address(request.developerAddress),
@@ -80,7 +90,13 @@ class DefaultScaffoldService(
8090
throw DeployException("Can't get contract address")
8191
}
8292

83-
return repository.save(Scaffold(transaction.get().contractAddress, user, openKey, compiledScaffold.abi))
93+
val contractAddress = transaction.get().contractAddress.substring(2)
94+
val filter = EthFilter(EARLIEST, LATEST, contractAddress)
95+
web3.ethLogObservable(filter).subscribe {
96+
transactionHandler.handle(it)
97+
}
98+
99+
return repository.save(Scaffold(contractAddress, user, openKey, compiledScaffold.abi))
84100
}
85101

86102
}

0 commit comments

Comments
 (0)