Skip to content

Commit 4d8828a

Browse files
author
Isabek Tashiev
committed
Merge branch 'sprint' into 'master'
Sprint into Master See merge request open-platform/state!33
2 parents 8ba8290 + 5d9535a commit 4d8828a

48 files changed

Lines changed: 658 additions & 32 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitlab-ci.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ tests-unit:
2424
POSTGRES_USER: "user"
2525
POSTGRES_PASSWORD: "password"
2626
OPEN_API_URL: "open_api_url"
27+
OPEN_CHAIN_URL: "open_chain_url"
28+
EVENT_SUBSCRIPTION: "false"
2729
services:
2830
- name: postgres:10
2931
alias: $POSTGRES_HOST
@@ -35,6 +37,11 @@ tests-unit:
3537
paths:
3638
- .gradle/wrapper
3739
- .gradle/caches
40+
artifacts:
41+
when: always
42+
paths:
43+
- build/reports
44+
expire_in: 1 week
3845

3946
###########################
4047
# Building
@@ -106,6 +113,9 @@ deploy-sprint:
106113
- SERVER=$SPRINT_SERVER
107114
- DEPLOY_KEY=$SPRINT_DEPLOY_KEY
108115
- export OPEN_API_URL=http://api.open-platform.zensoft.io
116+
- export OPEN_CHAIN_URL=$OPEN_CHAIN_URL
117+
- export NETWORK_URL=$NETWORK_URL_DEV
118+
- export EVENT_SUBSCRIPTION=true
109119
- export POSTGRES_PASSWORD=$SPRINT_POSTGRES_PASSWORD
110120
script: *deploy_to_host
111121
dependencies:
@@ -120,6 +130,9 @@ deploy-master:
120130
- SERVER=$MASTER_SERVER
121131
- DEPLOY_KEY=$MASTER_DEPLOY_KEY
122132
- export OPEN_API_URL=https://api.openfuture.io
133+
- export OPEN_CHAIN_URL=$OPEN_CHAIN_URL
134+
- export NETWORK_URL=$NETWORK_URL_PROD
135+
- export EVENT_SUBSCRIPTION=true
123136
- export POSTGRES_PASSWORD=$MASTER_POSTGRES_PASSWORD
124137
script: *deploy_to_host
125138
dependencies:

build.gradle

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,17 @@ ext {
2121
kotlinVersion = '1.3.31'
2222
springBootVersion = '2.1.5.RELEASE'
2323
swaggerVersion = '2.9.2'
24+
feignVersion = '2.1.3.RELEASE'
2425
}
2526

2627
dependencies {
2728
implementation "org.springframework.boot:spring-boot-starter-web"
2829
implementation "org.springframework.boot:spring-boot-starter-data-jpa"
2930
implementation "org.springframework.boot:spring-boot-starter-security"
3031

32+
// Feign
33+
implementation "org.springframework.cloud:spring-cloud-starter-openfeign:$feignVersion"
34+
3135
// Kotlin
3236
implementation "com.fasterxml.jackson.module:jackson-module-kotlin"
3337
implementation "org.jetbrains.kotlin:kotlin-reflect"
@@ -37,12 +41,17 @@ dependencies {
3741
runtime "org.postgresql:postgresql"
3842
implementation "org.flywaydb:flyway-core"
3943

44+
// Ethereum
45+
implementation "org.web3j:web3j-spring-boot-starter:1.6.0"
46+
implementation 'org.web3j:core:4.5.0'
47+
4048
// Swagger
4149
compile "io.springfox:springfox-swagger2:$swaggerVersion"
4250
compile "io.springfox:springfox-swagger-ui:$swaggerVersion"
4351

4452
//Utils
4553
compile "commons-validator:commons-validator:1.6"
54+
implementation "org.apache.httpcomponents:httpclient:4.5.7"
4655

4756
// Tests
4857
testImplementation "org.springframework.boot:spring-boot-starter-test"

docker-compose-server.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ services:
1010
- POSTGRES_USER=openstate
1111
- POSTGRES_PASSWORD=$POSTGRES_PASSWORD
1212
- OPEN_API_URL=$OPEN_API_URL
13+
- OPEN_CHAIN_URL=$OPEN_CHAIN_URL
14+
- NETWORK_URL=$NETWORK_URL
15+
- EVENT_SUBSCRIPTION=$EVENT_SUBSCRIPTION
1316
ports:
1417
- 80:8080
1518
postgres:

src/main/kotlin/io/openfuture/state/Application.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ package io.openfuture.state
22

33
import org.springframework.boot.autoconfigure.SpringBootApplication
44
import org.springframework.boot.runApplication
5+
import org.springframework.cloud.openfeign.EnableFeignClients
56

7+
@EnableFeignClients
68
@SpringBootApplication
79
class Application
810

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package io.openfuture.state.component
2+
3+
import io.openfuture.state.config.property.EthereumProperties
4+
import io.openfuture.state.controller.domain.dto.TransactionDto
5+
import io.openfuture.state.controller.domain.dto.pow
6+
import io.openfuture.state.service.StateTrackingService
7+
import io.reactivex.disposables.Disposable
8+
import io.reactivex.functions.Consumer
9+
import org.slf4j.LoggerFactory
10+
import org.springframework.stereotype.Component
11+
import org.web3j.protocol.Web3j
12+
import org.web3j.protocol.core.DefaultBlockParameterName
13+
import org.web3j.protocol.core.methods.response.EthBlock
14+
import java.math.BigInteger
15+
import javax.annotation.PostConstruct
16+
import javax.annotation.PreDestroy
17+
18+
19+
@Component
20+
class Web3Wrapper(
21+
private val web3j: Web3j,
22+
private val properties: EthereumProperties,
23+
private val stateService: StateTrackingService
24+
) {
25+
26+
private var blockSubscriber: Disposable? = null
27+
28+
29+
@PostConstruct
30+
fun subscribe() {
31+
if (!properties.eventSubscription) return
32+
33+
blockSubscriber = web3j.blockFlowable(true).subscribe(
34+
Consumer { processBlock(it.block) },
35+
onErrorSubscription()
36+
)
37+
}
38+
39+
@PreDestroy
40+
fun destroy() {
41+
unsubscribe()
42+
}
43+
44+
fun getEthBalance(address: String): Long = web3j.ethGetBalance(address, DefaultBlockParameterName.LATEST)
45+
.sendAsync()
46+
.get()
47+
.balance
48+
.toLong()
49+
50+
private fun unsubscribe() {
51+
blockSubscriber?.dispose()
52+
}
53+
54+
private fun processBlock(block: EthBlock.Block?) {
55+
if (block == null) return
56+
57+
val transactions = block.transactions
58+
59+
transactions.forEach { txObject ->
60+
val tx = txObject.get() as EthBlock.TransactionObject
61+
62+
if ((tx.from != null && stateService.isTrackedAddress(tx.from, 1)) ||
63+
(tx.to != null && stateService.isTrackedAddress(tx.to, 1))) {
64+
stateService.processTransaction(getTransaction(tx, block.timestamp))
65+
}
66+
}
67+
}
68+
69+
private fun onErrorSubscription(): Consumer<Throwable> = Consumer {
70+
log.warn("Error subscription: $it")
71+
subscribe()
72+
}
73+
74+
private fun getTransaction(tx: EthBlock.TransactionObject, timestamp: BigInteger): TransactionDto {
75+
return TransactionDto(1, tx.hash, tx.from, tx.to, tx.value.toLong(),
76+
tx.gas.toLong() * 10.pow(10).toLong(),
77+
timestamp.toLong(), tx.blockNumber.toLong(), tx.blockHash)
78+
}
79+
80+
81+
companion object {
82+
private val log = LoggerFactory.getLogger(Web3Wrapper::class.java)
83+
}
84+
85+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package io.openfuture.state.config
2+
3+
import org.springframework.context.annotation.Configuration
4+
import org.springframework.scheduling.annotation.EnableScheduling
5+
6+
@Configuration
7+
@EnableScheduling
8+
class AppConfig
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package io.openfuture.state.config.property
2+
3+
import org.springframework.boot.context.properties.ConfigurationProperties
4+
import org.springframework.stereotype.Component
5+
import org.springframework.validation.annotation.Validated
6+
import javax.validation.constraints.NotNull
7+
8+
@ConfigurationProperties(prefix = "ethereum")
9+
@Validated
10+
@Component
11+
class EthereumProperties(
12+
@field:NotNull var eventSubscription: Boolean = true
13+
)

src/main/kotlin/io/openfuture/state/controller/ExceptionHandler.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package io.openfuture.state.controller
22

33
import io.openfuture.state.controller.domain.dto.ErrorDto
44
import io.openfuture.state.controller.domain.dto.FieldErrorDto
5+
import io.openfuture.state.exception.ApiException
56
import io.openfuture.state.exception.NotFoundException
67
import org.springframework.http.HttpStatus
78
import org.springframework.web.bind.MethodArgumentNotValidException
@@ -18,6 +19,12 @@ class ExceptionHandler {
1819
return ErrorDto(HttpStatus.NOT_FOUND.value(), ex.message)
1920
}
2021

22+
@ResponseStatus(HttpStatus.BAD_REQUEST)
23+
@ExceptionHandler(ApiException::class)
24+
fun handleApiException(ex: ApiException): ErrorDto {
25+
return ErrorDto(HttpStatus.BAD_REQUEST.value(), ex.message)
26+
}
27+
2128
@ResponseStatus(HttpStatus.BAD_REQUEST)
2229
@ExceptionHandler(MethodArgumentNotValidException::class)
2330
fun handleException(ex: MethodArgumentNotValidException): ErrorDto {

src/main/kotlin/io/openfuture/state/controller/WalletController.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package io.openfuture.state.controller
33
import io.openfuture.state.controller.domain.dto.AccountDto
44
import io.openfuture.state.controller.domain.dto.WalletDto
55
import io.openfuture.state.controller.domain.request.AddWalletsRequest
6+
import io.openfuture.state.controller.domain.request.DeleteWalletRequest
67
import io.openfuture.state.service.AccountService
78
import io.openfuture.state.service.WalletService
89
import org.springframework.web.bind.annotation.*
@@ -41,4 +42,10 @@ class WalletController(
4142
return AccountDto(account)
4243
}
4344

45+
@PostMapping("/delete")
46+
fun deleteByAddress(@PathVariable accountId: Long, @RequestBody @Valid request: DeleteWalletRequest): AccountDto {
47+
val account = accountService.deleteWalletByAddress(accountId, request.address, request.blockchainId)
48+
return AccountDto(account)
49+
}
50+
4451
}

src/main/kotlin/io/openfuture/state/controller/domain/dto/TrackingTransactionDto.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ data class TrackingTransactionDto(
66
val id: Long,
77
val hash: String,
88
val amount: Long,
9+
val fee: Long,
910
val address: String,
1011
val type: String,
1112
val participant: String,
@@ -20,6 +21,7 @@ data class TrackingTransactionDto(
2021
tx.id,
2122
tx.hash,
2223
tx.amount,
24+
tx.fee,
2325
tx.wallet.address,
2426
tx.getType().name,
2527
tx.participant,

0 commit comments

Comments
 (0)