diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml
index 17152d073..46282070c 100644
--- a/.github/workflows/dev.yml
+++ b/.github/workflows/dev.yml
@@ -25,7 +25,10 @@ jobs:
- name: Build
run: mvn -B -T 1C clean install
- name: Build Docker images
- run: TAG=dev docker-compose -f docker-compose.build.yml build
+ env:
+ TAG: dev
+ PREFERENCES_IDENTIFIER: dev
+ run: docker-compose -f docker-compose.build.yml build
- name: Login to GitHub Container Registry
uses: docker/login-action@v1
with:
@@ -33,4 +36,7 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Push images to GitHub Container Registry
- run: TAG=dev docker-compose -f docker-compose.build.yml push
+ env:
+ TAG: dev
+ PREFERENCES_IDENTIFIER: dev
+ run: docker-compose -f docker-compose.build.yml push
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 69b0c85c5..7ffad3312 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -25,7 +25,10 @@ jobs:
- name: Build
run: mvn -B -T 1C clean install
- name: Build Docker images
- run: TAG=latest docker-compose -f docker-compose.build.yml build
+ env:
+ TAG: latest
+ PREFERENCES_IDENTIFIER: dev
+ run: docker-compose -f docker-compose.build.yml build
- name: Login to GitHub Container Registry
uses: docker/login-action@v1
with:
@@ -33,4 +36,7 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Push images to GitHub Container Registry
- run: TAG=latest docker-compose -f docker-compose.build.yml push
+ env:
+ TAG: dev
+ PREFERENCES_IDENTIFIER: demo
+ run: docker-compose -f docker-compose.build.yml push
diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml
index 3911048fd..206221671 100644
--- a/.github/workflows/pr.yml
+++ b/.github/workflows/pr.yml
@@ -24,4 +24,7 @@ jobs:
- name: Build
run: mvn -B -T 1C clean install
- name: Build Docker images
- run: TAG=latest docker-compose -f docker-compose.build.yml build
+ env:
+ TAG: dev
+ PREFERENCES_IDENTIFIER: dev
+ run: docker-compose -f docker-compose.build.yml build
diff --git a/accountant/accountant-app/pom.xml b/accountant/accountant-app/pom.xml
index aa8f7f94d..835465fa0 100644
--- a/accountant/accountant-app/pom.xml
+++ b/accountant/accountant-app/pom.xml
@@ -63,6 +63,10 @@
org.springframework.boot
spring-boot-starter-actuator
+
+ co.nilin.opex.utility.preferences
+ preferences
+
diff --git a/accountant/accountant-app/src/main/kotlin/co/nilin/opex/accountant/app/config/InitializeService.kt b/accountant/accountant-app/src/main/kotlin/co/nilin/opex/accountant/app/config/InitializeService.kt
new file mode 100644
index 000000000..71c857eb0
--- /dev/null
+++ b/accountant/accountant-app/src/main/kotlin/co/nilin/opex/accountant/app/config/InitializeService.kt
@@ -0,0 +1,54 @@
+package co.nilin.opex.accountant.app.config
+
+import co.nilin.opex.accountant.ports.postgres.dao.PairConfigRepository
+import co.nilin.opex.accountant.ports.postgres.dao.PairFeeConfigRepository
+import co.nilin.opex.accountant.ports.postgres.model.PairFeeConfigModel
+import co.nilin.opex.utility.preferences.Preferences
+import kotlinx.coroutines.reactor.awaitSingleOrNull
+import kotlinx.coroutines.runBlocking
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.context.annotation.DependsOn
+import org.springframework.stereotype.Component
+
+@Component
+@DependsOn("postgresConfig")
+class InitializeService(
+ private val pairConfigRepository: PairConfigRepository,
+ private val pairFeeConfigRepository: PairFeeConfigRepository
+) {
+ @Autowired
+ private lateinit var preferences: Preferences
+
+ @Autowired
+ fun init() = runBlocking {
+ preferences.markets.map {
+ val pair = it.pair ?: "${it.leftSide}_${it.rightSide}"
+ val leftSideCurrency = preferences.currencies.first { c -> it.leftSide == c.symbol }
+ val rightSideCurrency = preferences.currencies.first { c -> it.rightSide == c.symbol }
+ val leftSideFraction = (it.leftSideFraction ?: leftSideCurrency.precision).toDouble()
+ val rightSideFraction = (it.rightSideFraction ?: rightSideCurrency.precision).toDouble()
+ pairConfigRepository.insert(
+ pair,
+ it.leftSide,
+ it.rightSide,
+ leftSideFraction,
+ rightSideFraction,
+ 0.0
+ ).awaitSingleOrNull()
+ it.feeConfigs.forEach { f ->
+ runCatching {
+ pairFeeConfigRepository.save(
+ PairFeeConfigModel(
+ null,
+ pair,
+ f.direction,
+ f.userLevel,
+ f.makerFee.toDouble(),
+ f.takerFee.toDouble()
+ )
+ ).awaitSingleOrNull()
+ }
+ }
+ }
+ }
+}
diff --git a/accountant/accountant-app/src/main/resources/application.yml b/accountant/accountant-app/src/main/resources/application.yml
index 6e5e58484..9bf8bbb6a 100644
--- a/accountant/accountant-app/src/main/resources/application.yml
+++ b/accountant/accountant-app/src/main/resources/application.yml
@@ -45,7 +45,7 @@ spring:
config:
import: vault://secret/${spring.application.name}
app:
- coin: nln
+ coin: IRT
address: 1
wallet:
url: lb://opex-wallet/
diff --git a/accountant/accountant-ports/accountant-persister-postgres/src/main/kotlin/co/nilin/opex/accountant/ports/postgres/config/PostgresConfig.kt b/accountant/accountant-ports/accountant-persister-postgres/src/main/kotlin/co/nilin/opex/accountant/ports/postgres/config/PostgresConfig.kt
index 10fe331da..dd0fbf78e 100644
--- a/accountant/accountant-ports/accountant-persister-postgres/src/main/kotlin/co/nilin/opex/accountant/ports/postgres/config/PostgresConfig.kt
+++ b/accountant/accountant-ports/accountant-persister-postgres/src/main/kotlin/co/nilin/opex/accountant/ports/postgres/config/PostgresConfig.kt
@@ -11,17 +11,13 @@ import org.springframework.r2dbc.core.DatabaseClient
@EnableR2dbcRepositories(basePackages = ["co.nilin.opex"])
class PostgresConfig(
db: DatabaseClient,
- @Value("classpath:schema.sql") private val schemaResource: Resource,
- @Value("classpath:data.sql") private val dataResource: Resource?
+ @Value("classpath:schema.sql") private val schemaResource: Resource
) {
init {
val schemaReader = schemaResource.inputStream.reader()
val schema = schemaReader.readText().trim()
schemaReader.close()
- val dataReader = dataResource?.inputStream?.reader()
- val data = dataReader?.readText()?.trim() ?: ""
- dataReader?.close()
- val initDb = db.sql { schema.plus(data) }
+ val initDb = db.sql { schema }
initDb // initialize the database
.then()
.subscribe() // execute
diff --git a/accountant/accountant-ports/accountant-persister-postgres/src/main/kotlin/co/nilin/opex/accountant/ports/postgres/dao/PairConfigRepository.kt b/accountant/accountant-ports/accountant-persister-postgres/src/main/kotlin/co/nilin/opex/accountant/ports/postgres/dao/PairConfigRepository.kt
index 9f76a937b..c3d9ca417 100644
--- a/accountant/accountant-ports/accountant-persister-postgres/src/main/kotlin/co/nilin/opex/accountant/ports/postgres/dao/PairConfigRepository.kt
+++ b/accountant/accountant-ports/accountant-persister-postgres/src/main/kotlin/co/nilin/opex/accountant/ports/postgres/dao/PairConfigRepository.kt
@@ -1,8 +1,20 @@
package co.nilin.opex.accountant.ports.postgres.dao
import co.nilin.opex.accountant.ports.postgres.model.PairConfigModel
+import org.springframework.data.r2dbc.repository.Query
import org.springframework.data.repository.reactive.ReactiveCrudRepository
import org.springframework.stereotype.Repository
+import reactor.core.publisher.Mono
@Repository
-interface PairConfigRepository : ReactiveCrudRepository
+interface PairConfigRepository : ReactiveCrudRepository {
+ @Query("insert into pair_config values (:pair, :leftSide, :rightSide, :leftSideFraction, :rightSideFraction, :rate) on conflict do nothing")
+ fun insert(
+ pair: String,
+ leftSide: String,
+ rightSide: String,
+ leftSideFraction: Double,
+ rightSideFraction: Double,
+ rate: Double
+ ): Mono
+}
diff --git a/accountant/accountant-ports/accountant-persister-postgres/src/main/resources/data.sql b/accountant/accountant-ports/accountant-persister-postgres/src/main/resources/data.sql
deleted file mode 100644
index 0b209872f..000000000
--- a/accountant/accountant-ports/accountant-persister-postgres/src/main/resources/data.sql
+++ /dev/null
@@ -1,62 +0,0 @@
-INSERT INTO pair_config
-VALUES ('btc_usdt', 'btc', 'usdt', 0.000001, 0.01, 55000),
- ('eth_usdt', 'eth', 'usdt', 0.00001, 0.01, 3800),
- ('btc_irt', 'btc', 'irt', 0.000001, 0.01, 55000),
- ('eth_irt', 'eth', 'irt', 0.00001, 0.01, 3800),
- ('bnb_irt', 'bnb', 'irt', 0.00001, 0.01, 3800),
- ('bnb_usdt', 'bnb', 'usdt', 0.00001, 0.01, 3800),
- ('busd_irt', 'busd', 'irt', 0.00001, 0.01, 3800),
- ('nln_usdt', 'nln', 'usdt', 1.0, 0.01, 0.01),
- ('nln_btc', 'nln', 'btc', 1.0, 0.000001, 1 / 5500000),
- ('nln_eth', 'nln', 'eth', 1.0, 0.000001, 1 / 550000)
-ON CONFLICT DO NOTHING;
-
--- Test pairs
-INSERT INTO pair_config
-VALUES ('tbtc_tusdt', 'tbtc', 'tusdt', 0.000001, 0.01, 55000),
- ('teth_tusdt', 'teth', 'tusdt', 0.00001, 0.01, 3800),
- ('nln_tusdt', 'nln', 'tusdt', 1.0, 0.01, 0.01),
- ('nln_tbtc', 'nln', 'tbtc', 1.0, 0.000001, 1 / 5500000),
- ('nln_teth', 'nln', 'teth', 1.0, 0.000001, 1 / 550000)
-ON CONFLICT DO NOTHING;
-
-INSERT INTO pair_fee_config
-VALUES (1, 'btc_usdt', 'ASK', '*', 0.01, 0.01),
- (2, 'btc_usdt', 'BID', '*', 0.01, 0.01),
- (3, 'nln_usdt', 'ASK', '*', 0.01, 0.01),
- (4, 'nln_usdt', 'BID', '*', 0.01, 0.01),
- (5, 'nln_btc', 'ASK', '*', 0.01, 0.01),
- (6, 'nln_btc', 'BID', '*', 0.01, 0.01),
- (7, 'eth_usdt', 'ASK', '*', 0.01, 0.01),
- (8, 'eth_usdt', 'BID', '*', 0.01, 0.01),
- (9, 'nln_eth', 'ASK', '*', 0.01, 0.01),
- (10, 'nln_eth', 'BID', '*', 0.01, 0.01),
- (11, 'btc_irt', 'ASK', '*', 0.01, 0.01),
- (12, 'btc_irt', 'BID', '*', 0.01, 0.01),
- (13, 'eth_irt', 'ASK', '*', 0.01, 0.01),
- (14, 'eth_irt', 'BID', '*', 0.01, 0.01),
- (15, 'bnb_irt', 'ASK', '*', 0.01, 0.01),
- (16, 'bnb_irt', 'BID', '*', 0.01, 0.01),
- (17, 'bnb_usdt', 'ASK', '*', 0.01, 0.01),
- (18, 'bnb_usdt', 'BID', '*', 0.01, 0.01),
- (19, 'busd_irt', 'ASK', '*', 0.01, 0.01),
- (20, 'busd_irt', 'BID', '*', 0.01, 0.01)
-ON CONFLICT DO NOTHING;
-
--- Test pair configs
-INSERT INTO pair_fee_config
-VALUES (21, 'tbtc_tusdt', 'ASK', '*', 0.01, 0.01),
- (22, 'tbtc_tusdt', 'BID', '*', 0.01, 0.01),
- (23, 'nln_tusdt', 'ASK', '*', 0.01, 0.01),
- (24, 'nln_tusdt', 'BID', '*', 0.01, 0.01),
- (25, 'nln_tbtc', 'ASK', '*', 0.01, 0.01),
- (26, 'nln_tbtc', 'BID', '*', 0.01, 0.01),
- (27, 'teth_tusdt', 'ASK', '*', 0.01, 0.01),
- (28, 'teth_tusdt', 'BID', '*', 0.01, 0.01),
- (29, 'nln_teth', 'ASK', '*', 0.01, 0.01),
- (30, 'nln_teth', 'BID', '*', 0.01, 0.01)
-ON CONFLICT DO NOTHING;
-
-SELECT setval(pg_get_serial_sequence('pair_fee_config', 'id'), (SELECT MAX(id) FROM pair_fee_config));
-
-COMMIT;
diff --git a/accountant/pom.xml b/accountant/pom.xml
index 1a20c1ff2..01387a319 100644
--- a/accountant/pom.xml
+++ b/accountant/pom.xml
@@ -73,6 +73,11 @@
logging-handler
${project.version}
+
+ co.nilin.opex.utility.preferences
+ preferences
+ ${project.version}
+
org.springframework.cloud
spring-cloud-dependencies
diff --git a/api/api-app/pom.xml b/api/api-app/pom.xml
index 00529ca01..f7324038b 100644
--- a/api/api-app/pom.xml
+++ b/api/api-app/pom.xml
@@ -68,6 +68,10 @@
org.springframework.cloud
spring-cloud-starter-vault-config
+
+ co.nilin.opex.utility.preferences
+ preferences
+
diff --git a/api/api-app/src/main/kotlin/co/nilin/opex/api/app/config/InitializeService.kt b/api/api-app/src/main/kotlin/co/nilin/opex/api/app/config/InitializeService.kt
new file mode 100644
index 000000000..63a9291b3
--- /dev/null
+++ b/api/api-app/src/main/kotlin/co/nilin/opex/api/app/config/InitializeService.kt
@@ -0,0 +1,26 @@
+package co.nilin.opex.api.app.config
+
+import co.nilin.opex.api.ports.postgres.dao.SymbolMapRepository
+import co.nilin.opex.api.ports.postgres.model.SymbolMapModel
+import co.nilin.opex.utility.preferences.Preferences
+import kotlinx.coroutines.reactor.awaitSingleOrNull
+import kotlinx.coroutines.runBlocking
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.context.annotation.DependsOn
+import org.springframework.stereotype.Component
+
+@Component
+@DependsOn("postgresConfig")
+class InitializeService(private val symbolMapRepository: SymbolMapRepository) {
+ @Autowired
+ private lateinit var preferences: Preferences
+
+ @Autowired
+ fun init() = runBlocking {
+ preferences.markets.map {
+ val pair = it.pair ?: "${it.leftSide}_${it.rightSide}"
+ val items = it.aliases.map { a -> SymbolMapModel(null, pair, a.key, a.alias) }
+ runCatching { symbolMapRepository.saveAll(items).collectList().awaitSingleOrNull() }
+ }
+ }
+}
diff --git a/api/api-core/src/main/kotlin/co/nilin/opex/api/core/spi/SymbolMapper.kt b/api/api-core/src/main/kotlin/co/nilin/opex/api/core/spi/SymbolMapper.kt
index 6e36e717c..893080836 100644
--- a/api/api-core/src/main/kotlin/co/nilin/opex/api/core/spi/SymbolMapper.kt
+++ b/api/api-core/src/main/kotlin/co/nilin/opex/api/core/spi/SymbolMapper.kt
@@ -4,7 +4,7 @@ interface SymbolMapper {
suspend fun map(symbol: String?): String?
- suspend fun unmap(value: String?): String?
+ suspend fun unmap(alias: String?): String?
- suspend fun getKeyValues(): Map
-}
\ No newline at end of file
+ suspend fun getAll(): Map
+}
diff --git a/api/api-ports/api-binance-rest/src/main/kotlin/co/nilin/opex/api/ports/binance/controller/FiltersController.kt b/api/api-ports/api-binance-rest/src/main/kotlin/co/nilin/opex/api/ports/binance/controller/FiltersController.kt
index 46db1b010..a8bf2d9ca 100644
--- a/api/api-ports/api-binance-rest/src/main/kotlin/co/nilin/opex/api/ports/binance/controller/FiltersController.kt
+++ b/api/api-ports/api-binance-rest/src/main/kotlin/co/nilin/opex/api/ports/binance/controller/FiltersController.kt
@@ -3,5 +3,4 @@ package co.nilin.opex.api.ports.binance.controller
import org.springframework.web.bind.annotation.RestController
@RestController
-class FiltersController {
-}
\ No newline at end of file
+class FiltersController
diff --git a/api/api-ports/api-binance-rest/src/main/kotlin/co/nilin/opex/api/ports/binance/controller/MarketController.kt b/api/api-ports/api-binance-rest/src/main/kotlin/co/nilin/opex/api/ports/binance/controller/MarketController.kt
index 92899a607..75f7177a0 100644
--- a/api/api-ports/api-binance-rest/src/main/kotlin/co/nilin/opex/api/ports/binance/controller/MarketController.kt
+++ b/api/api-ports/api-binance-rest/src/main/kotlin/co/nilin/opex/api/ports/binance/controller/MarketController.kt
@@ -141,15 +141,15 @@ class MarketController(
@RequestParam("symbols", required = false)
symbols: String?
): ExchangeInfoResponse {
- val symbolsMap = symbolMapper.getKeyValues()
+ val symbolsMap = symbolMapper.getAll()
val pairConfigs = accountantProxy.getPairConfigs()
.map {
ExchangeInfoSymbol(
symbolsMap[it.pair] ?: it.pair,
"TRADING",
- it.leftSideWalletSymbol.toUpperCase(),
+ it.leftSideWalletSymbol.uppercase(),
BigDecimal.valueOf(it.leftSideFraction).scale(),
- it.rightSideWalletSymbol.toUpperCase(),
+ it.rightSideWalletSymbol.uppercase(),
BigDecimal.valueOf(it.rightSideFraction).scale()
)
}
@@ -200,4 +200,4 @@ class MarketController(
return list
}
-}
\ No newline at end of file
+}
diff --git a/api/api-ports/api-persister-postgres/src/main/kotlin/co/nilin/opex/api/ports/postgres/config/PostgresConfig.kt b/api/api-ports/api-persister-postgres/src/main/kotlin/co/nilin/opex/api/ports/postgres/config/PostgresConfig.kt
index a2924ed23..47e7038ae 100644
--- a/api/api-ports/api-persister-postgres/src/main/kotlin/co/nilin/opex/api/ports/postgres/config/PostgresConfig.kt
+++ b/api/api-ports/api-persister-postgres/src/main/kotlin/co/nilin/opex/api/ports/postgres/config/PostgresConfig.kt
@@ -10,17 +10,13 @@ import org.springframework.r2dbc.core.DatabaseClient
@EnableR2dbcRepositories(basePackages = ["co.nilin.opex"])
class PostgresConfig(
db: DatabaseClient,
- @Value("classpath:schema.sql") private val schemaResource: Resource,
- @Value("classpath:data.sql") private val dataResource: Resource?
+ @Value("classpath:schema.sql") private val schemaResource: Resource
) {
init {
val schemaReader = schemaResource.inputStream.reader()
val schema = schemaReader.readText().trim()
schemaReader.close()
- val dataReader = dataResource?.inputStream?.reader()
- val data = dataReader?.readText()?.trim() ?: ""
- dataReader?.close()
- val initDb = db.sql { schema.plus(data) }
+ val initDb = db.sql { schema }
initDb // initialize the database
.then()
.subscribe() // execute
diff --git a/api/api-ports/api-persister-postgres/src/main/kotlin/co/nilin/opex/api/ports/postgres/dao/SymbolMapRepository.kt b/api/api-ports/api-persister-postgres/src/main/kotlin/co/nilin/opex/api/ports/postgres/dao/SymbolMapRepository.kt
index 4bc30a34a..0c1824218 100644
--- a/api/api-ports/api-persister-postgres/src/main/kotlin/co/nilin/opex/api/ports/postgres/dao/SymbolMapRepository.kt
+++ b/api/api-ports/api-persister-postgres/src/main/kotlin/co/nilin/opex/api/ports/postgres/dao/SymbolMapRepository.kt
@@ -9,10 +9,9 @@ import reactor.core.publisher.Mono
@Repository
interface SymbolMapRepository : ReactiveCrudRepository {
+ @Query("select * from symbol_maps where symbol = :symbol and aliasKey = :aliasKey")
+ fun findByAliasKeyAndSymbol(aliasKey: String, @Param("symbol") symbol: String): Mono
- @Query("select * from symbol_maps where symbol = :symbol")
- fun findBySymbol(@Param("symbol") symbol: String): Mono
-
- @Query("select * from symbol_maps where value = :value")
- fun findByValue(@Param("value") value: String): Mono
-}
\ No newline at end of file
+ @Query("select * from symbol_maps where aliasKey = :aliasKey and alias = :alias")
+ fun findByAliasKeyAndAlias(aliasKey: String, @Param("alias") alias: String): Mono
+}
diff --git a/api/api-ports/api-persister-postgres/src/main/kotlin/co/nilin/opex/api/ports/postgres/impl/SymbolMapperImpl.kt b/api/api-ports/api-persister-postgres/src/main/kotlin/co/nilin/opex/api/ports/postgres/impl/SymbolMapperImpl.kt
index d8f462be7..fd7194925 100644
--- a/api/api-ports/api-persister-postgres/src/main/kotlin/co/nilin/opex/api/ports/postgres/impl/SymbolMapperImpl.kt
+++ b/api/api-ports/api-persister-postgres/src/main/kotlin/co/nilin/opex/api/ports/postgres/impl/SymbolMapperImpl.kt
@@ -11,20 +11,21 @@ class SymbolMapperImpl(val symbolMapRepository: SymbolMapRepository) : SymbolMap
override suspend fun map(symbol: String?): String? {
if (symbol == null) return null
- return symbolMapRepository.findBySymbol(symbol).awaitFirstOrNull()?.value
+ return symbolMapRepository.findByAliasKeyAndSymbol("binance", symbol).awaitFirstOrNull()?.alias
}
- override suspend fun unmap(value: String?): String? {
- if (value == null) return null
- return symbolMapRepository.findByValue(value).awaitFirstOrNull()?.symbol
+ override suspend fun unmap(alias: String?): String? {
+ if (alias == null) return null
+ return symbolMapRepository.findByAliasKeyAndAlias("binance", alias).awaitFirstOrNull()?.symbol
}
- override suspend fun getKeyValues(): Map {
+ override suspend fun getAll(): Map {
val map = HashMap()
symbolMapRepository.findAll()
.collectList()
.awaitFirstOrElse { emptyList() }
- .forEach { map[it.symbol] = it.value }
+ .filter { it.aliasKey == "binance" }
+ .associate { it.symbol to it.alias }
return map
}
-}
\ No newline at end of file
+}
diff --git a/api/api-ports/api-persister-postgres/src/main/kotlin/co/nilin/opex/api/ports/postgres/model/SymbolMapModel.kt b/api/api-ports/api-persister-postgres/src/main/kotlin/co/nilin/opex/api/ports/postgres/model/SymbolMapModel.kt
index 5897724ee..e72ed124a 100644
--- a/api/api-ports/api-persister-postgres/src/main/kotlin/co/nilin/opex/api/ports/postgres/model/SymbolMapModel.kt
+++ b/api/api-ports/api-persister-postgres/src/main/kotlin/co/nilin/opex/api/ports/postgres/model/SymbolMapModel.kt
@@ -2,11 +2,12 @@ package co.nilin.opex.api.ports.postgres.model
import org.springframework.data.annotation.Id
-import org.springframework.data.relational.core.mapping.Column
import org.springframework.data.relational.core.mapping.Table
@Table("symbol_maps")
class SymbolMapModel(
- @Id val symbol: String,
- @Column("value") val value: String,
-)
\ No newline at end of file
+ @Id var id: Long?,
+ val symbol: String,
+ val aliasKey: String,
+ val alias: String,
+)
diff --git a/api/api-ports/api-persister-postgres/src/main/resources/data.sql b/api/api-ports/api-persister-postgres/src/main/resources/data.sql
deleted file mode 100644
index 803ee830b..000000000
--- a/api/api-ports/api-persister-postgres/src/main/resources/data.sql
+++ /dev/null
@@ -1,21 +0,0 @@
-INSERT INTO symbol_maps(symbol, value)
-VALUES ('btc_usdt', 'BTCUSDT'),
- ('eth_usdt', 'ETHUSDT'),
- ('bnb_usdt', 'BNBUSDT'),
- ('eth_btc', 'ETHBTC'),
- ('nln_usdt', 'NLNUSDT'),
- ('nln_btc', 'NLNBTC'),
- ('btc_irt', 'BTCIRT'),
- ('eth_irt', 'ETHIRT'),
- ('bnb_irt', 'BNBIRT'),
- ('busd_irt', 'BUSDIRT')
-ON CONFLICT DO NOTHING;
-
--- Test symbol mapper
-INSERT INTO symbol_maps(symbol, value)
-VALUES ('tbtc_tusdt', 'TBTCTUSDT'),
- ('teth_tusdt', 'TETHTUSDT'),
- ('teth_tbtc', 'TETHTBTC'),
- ('nln_tusdt', 'NLNTUSDT'),
- ('nln_tbtc', 'NLNTBTC')
-ON CONFLICT DO NOTHING;
diff --git a/api/api-ports/api-persister-postgres/src/main/resources/schema.sql b/api/api-ports/api-persister-postgres/src/main/resources/schema.sql
index 497ccb398..4c59f00ce 100644
--- a/api/api-ports/api-persister-postgres/src/main/resources/schema.sql
+++ b/api/api-ports/api-persister-postgres/src/main/resources/schema.sql
@@ -56,8 +56,11 @@ CREATE TABLE IF NOT EXISTS trades
CREATE TABLE IF NOT EXISTS symbol_maps
(
- symbol VARCHAR(72) PRIMARY KEY,
- value VARCHAR(72) UNIQUE NOT NULL
+ id SERIAL PRIMARY KEY,
+ symbol VARCHAR(72) NOT NULL,
+ alias_key VARCHAR(72) NOT NULL,
+ alias VARCHAR(72) NOT NULL,
+ UNIQUE (symbol, alias_key, alias)
);
CREATE OR REPLACE FUNCTION interval_generator(
diff --git a/api/pom.xml b/api/pom.xml
index 701612a51..ec4485c61 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -77,6 +77,11 @@
interceptors
${project.version}
+
+ co.nilin.opex.utility.preferences
+ preferences
+ ${project.version}
+
org.springframework.cloud
spring-cloud-dependencies
diff --git a/bc-gateway/bc-gateway-app/pom.xml b/bc-gateway/bc-gateway-app/pom.xml
index c8a5fa93b..7c66de544 100644
--- a/bc-gateway/bc-gateway-app/pom.xml
+++ b/bc-gateway/bc-gateway-app/pom.xml
@@ -81,6 +81,10 @@
co.nilin.opex.bcgateway.ports.kafka.listener
bc-gateway-eventlistener-kafka
+
+ co.nilin.opex.utility.preferences
+ preferences
+
io.springfox
springfox-boot-starter
diff --git a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/config/InitializeService.kt b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/config/InitializeService.kt
new file mode 100644
index 000000000..9e4a1e6ff
--- /dev/null
+++ b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/config/InitializeService.kt
@@ -0,0 +1,96 @@
+package co.nilin.opex.bcgateway.app.config
+
+import co.nilin.opex.bcgateway.ports.postgres.dao.*
+import co.nilin.opex.bcgateway.ports.postgres.model.*
+import co.nilin.opex.utility.preferences.AddressType
+import co.nilin.opex.utility.preferences.Chain
+import co.nilin.opex.utility.preferences.Currency
+import co.nilin.opex.utility.preferences.Preferences
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.reactor.awaitSingle
+import kotlinx.coroutines.reactor.awaitSingleOrNull
+import kotlinx.coroutines.runBlocking
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.context.annotation.DependsOn
+import org.springframework.stereotype.Component
+import java.time.LocalDateTime
+
+@Component
+@DependsOn("postgresConfig")
+class InitializeService(
+ private val addressTypeRepository: AddressTypeRepository,
+ private val chainRepository: ChainRepository,
+ private val chainAddressTypeRepository: ChainAddressTypeRepository,
+ private val chainEndpointRepository: ChainEndpointRepository,
+ private val currencyRepository: CurrencyRepository,
+ private val currencyImplementationRepository: CurrencyImplementationRepository,
+ private val chainSyncScheduleRepository: ChainSyncScheduleRepository,
+ private val walletSyncScheduleRepository: WalletSyncScheduleRepository
+) {
+ @Autowired
+ private lateinit var preferences: Preferences
+
+ @Autowired
+ fun init() = runBlocking {
+ addAddressTypes(preferences.addressTypes)
+ addChains(preferences.chains)
+ addCurrencies(preferences.currencies)
+ addSchedules(preferences)
+ }
+
+ private suspend fun addAddressTypes(data: List) = coroutineScope {
+ val items = data.mapIndexed { i, it ->
+ if (addressTypeRepository.existsById(i + 1L).awaitSingle()) null
+ else AddressTypeModel(null, it.addressType, it.addressRegex, null)
+ }.filterNotNull()
+ runCatching { addressTypeRepository.saveAll(items).collectList().awaitSingleOrNull() }
+ }
+
+ private suspend fun addChains(data: List) = coroutineScope {
+ data.map { chainRepository.insert(it.name).awaitSingleOrNull() }
+ val items1 = data.map {
+ val addressTypeId = addressTypeRepository.findByType(it.addressType).awaitSingle().id!!
+ ChainAddressTypeModel(null, it.name, addressTypeId)
+ }
+ runCatching { chainAddressTypeRepository.saveAll(items1).collectList().awaitSingleOrNull() }
+ val items2 = data.map { ChainEndpointModel(null, it.name, it.endpointUrl, null, null) }
+ runCatching { chainEndpointRepository.saveAll(items2).collectList().awaitSingleOrNull() }
+ }
+
+ private suspend fun addCurrencies(data: List) = coroutineScope {
+ coroutineScope {
+ data.forEach {
+ currencyRepository.insert(it.name, it.symbol).awaitSingleOrNull()
+ }
+ }
+ val items = data.flatMap { it.implementations.map { impl -> it to impl } }.map { (currency, impl) ->
+ CurrencyImplementationModel(
+ null,
+ currency.symbol,
+ impl.chain,
+ impl.token,
+ impl.tokenAddress,
+ impl.tokenName,
+ impl.withdrawEnabled,
+ impl.withdrawFee,
+ impl.withdrawMin,
+ impl.decimal
+ )
+ }
+ runCatching { currencyImplementationRepository.saveAll(items).collectList().awaitSingleOrNull() }
+ }
+
+ private suspend fun addSchedules(data: Preferences) = coroutineScope {
+ data.chains.map {
+ chainSyncScheduleRepository.insert(it.name, it.schedule.delay.toInt(), it.schedule.errorDelay.toInt())
+ .awaitSingleOrNull()
+ }
+ if (walletSyncScheduleRepository.existsById(1).awaitSingle()) null
+ else {
+ val item = WalletSyncScheduleModel(
+ null, LocalDateTime.now(), data.wallet.schedule.delay, data.wallet.schedule.batchSize
+ )
+ runCatching { walletSyncScheduleRepository.save(item).awaitSingleOrNull() }
+ }
+ }
+}
diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/config/PostgresConfig.kt b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/config/PostgresConfig.kt
index 0b6367666..c1dae05d6 100644
--- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/config/PostgresConfig.kt
+++ b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/config/PostgresConfig.kt
@@ -10,17 +10,13 @@ import org.springframework.r2dbc.core.DatabaseClient
@EnableR2dbcRepositories(basePackages = ["co.nilin.opex"])
class PostgresConfig(
db: DatabaseClient,
- @Value("classpath:schema.sql") private val schemaResource: Resource,
- @Value("classpath:data.sql") private val dataResource: Resource?
+ @Value("classpath:schema.sql") private val schemaResource: Resource
) {
init {
val schemaReader = schemaResource.inputStream.reader()
val schema = schemaReader.readText().trim()
schemaReader.close()
- val dataReader = dataResource?.inputStream?.reader()
- val data = dataReader?.readText()?.trim() ?: ""
- dataReader?.close()
- val initDb = db.sql { schema.plus(data) }
+ val initDb = db.sql { schema }
initDb // initialize the database
.then()
.subscribe() // execute
diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/resources/data.sql b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/resources/data.sql
deleted file mode 100644
index acad3fe8b..000000000
--- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/resources/data.sql
+++ /dev/null
@@ -1,112 +0,0 @@
-INSERT INTO currency
-VALUES ('BTC', 'Bitcoin'),
- ('ETH', 'Ethereum'),
- ('USDT', 'Tether'),
- ('IRT', 'Toman'),
- ('BNB', 'Binance'),
- ('BUSD', 'Binance USD')
-ON CONFLICT DO NOTHING;
-
--- Test currency
-INSERT INTO currency
-VALUES ('TBTC', 'Bitcoin (Test)'),
- ('TETH', 'Ethereum (Test)'),
- ('TUSDT', 'Tether (Test)')
-ON CONFLICT DO NOTHING;
-
-INSERT INTO chains
-VALUES ('bitcoin'),
- ('ethereum'),
- ('bsc')
-ON CONFLICT DO NOTHING;
-
--- Test chains
-INSERT INTO chains
-VALUES ('test-bitcoin'),
- ('test-ethereum')
-ON CONFLICT DO NOTHING;
-
-INSERT INTO address_types(id, address_type, address_regex)
-VALUES (1, 'bitcoin', '.*'),
- (2, 'ethereum', '.*'),
- (3, 'test-bitcoin', '.*')
-ON CONFLICT DO NOTHING;
-
-SELECT setval(pg_get_serial_sequence('address_types', 'id'), (SELECT MAX(id) FROM address_types));
-
-INSERT INTO chain_address_types(chain_name, addr_type_id)
-VALUES ('bitcoin', 1),
- ('ethereum', 2),
- ('bsc', 2)
-ON CONFLICT DO NOTHING;
-
--- Test chain address types
-INSERT INTO chain_address_types(chain_name, addr_type_id)
-VALUES ('test-bitcoin', 3),
- ('test-ethereum', 2)
-ON CONFLICT DO NOTHING;
-
-INSERT INTO currency_implementations(id,
- symbol,
- chain,
- token,
- token_address,
- token_name,
- withdraw_enabled,
- withdraw_fee,
- withdraw_min,
- decimal)
-VALUES (1, 'BTC', 'bitcoin', false, null, null, true, 0.0001, 0.0001, 0),
- (2, 'ETH', 'ethereum', false, null, null, true, 0.00001, 0.000001, 18),
- (3, 'USDT', 'ethereum', true, '0xdac17f958d2ee523a2206206994597c13d831ec7', 'USDT', true, 0.01, 0.01, 6),
- (4, 'BNB', 'bsc', false, null, null, true, 0.0001, 0.0001, 0),
- (5, 'BUSD', 'bsc', true, '0xe9e7cea3dedca5984780bafc599bd69add087d56', 'BUSD', true, 0.01, 0.01, 6)
-ON CONFLICT DO NOTHING;
-
--- Test currency implementation
-INSERT INTO currency_implementations(id,
- symbol,
- chain,
- token,
- token_address,
- token_name,
- withdraw_enabled,
- withdraw_fee,
- withdraw_min,
- decimal)
-VALUES (6, 'TBTC', 'test-bitcoin', false, null, null, true, 0.0001, 0.0001, 0),
- (7, 'TETH', 'test-ethereum', false, null, null, true, 0.00001, 0.000001, 18),
- (8, 'TUSDT', 'test-ethereum', true, '0x110a13fc3efe6a245b50102d2d79b3e76125ae83', 'TUSDT', true, 0.01, 0.01, 6)
-ON CONFLICT DO NOTHING;
-
-SELECT setval(pg_get_serial_sequence('currency_implementations', 'id'), (SELECT MAX(id) FROM currency_implementations));
-
-INSERT INTO chain_endpoints(id, chain_name, endpoint_url)
-VALUES (1, 'bitcoin', 'lb://chain-scan-gateway/bitcoin/transfers'),
- (2, 'ethereum', 'lb://chain-scan-gateway/eth/transfers'),
- (3, 'bsc', 'lb://chain-scan-gateway/bsc/transfers')
-ON CONFLICT DO NOTHING;
-
--- Test chain endpoints
-INSERT INTO chain_endpoints(id, chain_name, endpoint_url)
-VALUES (4, 'test-bitcoin', 'lb://chain-scan-gateway/test-bitcoin/transfers'),
- (5, 'test-ethereum', 'lb://chain-scan-gateway/test-eth/transfers')
-ON CONFLICT DO NOTHING;
-
-SELECT setval(pg_get_serial_sequence('chain_endpoints', 'id'), (SELECT MAX(id) FROM chain_endpoints));
-
-INSERT INTO chain_sync_schedules
-VALUES ('bitcoin', CURRENT_DATE, 600, 60),
- ('ethereum', CURRENT_DATE, 90, 60),
- ('bsc', CURRENT_DATE, 90, 60)
-ON CONFLICT DO NOTHING;
-
--- Test chain scan schedules
-INSERT INTO chain_sync_schedules
-VALUES ('test-bitcoin', CURRENT_DATE, 600, 60),
- ('test-ethereum', CURRENT_DATE, 90, 60)
-ON CONFLICT DO NOTHING;
-
-INSERT INTO wallet_sync_schedules
-VALUES (1, CURRENT_DATE, 10, 10000)
-ON CONFLICT DO NOTHING;
diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/resources/schema.sql b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/resources/schema.sql
index 9ee61fab8..6733d6103 100644
--- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/resources/schema.sql
+++ b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/resources/schema.sql
@@ -40,7 +40,7 @@ CREATE TABLE IF NOT EXISTS assigned_address_chains
CREATE TABLE IF NOT EXISTS chain_address_types
(
id SERIAL PRIMARY KEY,
- chain_name VARCHAR(72) NOT NULL REFERENCES chains (name),
+ chain_name VARCHAR(72) UNIQUE NOT NULL REFERENCES chains (name),
addr_type_id INTEGER NOT NULL REFERENCES address_types (id)
);
diff --git a/bc-gateway/pom.xml b/bc-gateway/pom.xml
index 3c408f018..6fc01550a 100644
--- a/bc-gateway/pom.xml
+++ b/bc-gateway/pom.xml
@@ -72,6 +72,11 @@
interceptors
${project.version}
+
+ co.nilin.opex.utility.preferences
+ preferences
+ ${project.version}
+
diff --git a/docker-compose.override.yml b/docker-compose.override.yml
new file mode 100644
index 000000000..647bb9cbc
--- /dev/null
+++ b/docker-compose.override.yml
@@ -0,0 +1,17 @@
+version: '3.8'
+services:
+ accountant:
+ volumes:
+ - "./preferences-$PREFERENCES_IDENTIFIER.yml:/preferences.yml"
+ matching-engine:
+ volumes:
+ - "./preferences-$PREFERENCES_IDENTIFIER.yml:/preferences.yml"
+ wallet:
+ volumes:
+ - "./preferences-$PREFERENCES_IDENTIFIER.yml:/preferences.yml"
+ api:
+ volumes:
+ - "./preferences-$PREFERENCES_IDENTIFIER.yml:/preferences.yml"
+ bc-gateway:
+ volumes:
+ - "./preferences-$PREFERENCES_IDENTIFIER.yml:/preferences.yml"
diff --git a/docker-compose.yml b/docker-compose.yml
index 1a50b6fb9..23226d405 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -256,6 +256,7 @@ services:
- BACKEND_USER=${BACKEND_USER}
- VAULT_HOST=vault
- SWAGGER_AUTH_URL=$KEYCLOAK_FRONTEND_URL
+ - PREFERENCES=$PREFERENCES
networks:
- default
depends_on:
@@ -292,6 +293,7 @@ services:
- JAVA_OPTS=-Xmx256m -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
- KAFKA_IP_PORT=kafka-1:29092,kafka-2:29092,kafka-3:29092
- REDIS_HOST=redis
+ - PREFERENCES=$PREFERENCES
networks:
- default
depends_on:
@@ -352,6 +354,7 @@ services:
- BACKEND_USER=${BACKEND_USER}
- VAULT_HOST=vault
- SWAGGER_AUTH_URL=$KEYCLOAK_FRONTEND_URL
+ - PREFERENCES=$PREFERENCES
depends_on:
- kafka-1
- kafka-2
@@ -376,6 +379,7 @@ services:
- BACKEND_USER=${BACKEND_USER}
- VAULT_HOST=vault
- SWAGGER_AUTH_URL=$KEYCLOAK_FRONTEND_URL
+ - PREFERENCES=$PREFERENCES
depends_on:
- kafka-1
- kafka-2
@@ -429,6 +433,7 @@ services:
- BACKEND_USER=${BACKEND_USER}
- VAULT_HOST=vault
- SWAGGER_AUTH_URL=$KEYCLOAK_FRONTEND_URL
+ - PREFERENCES=$PREFERENCES
depends_on:
- kafka-1
- kafka-2
diff --git a/matching-engine/matching-engine-app/pom.xml b/matching-engine/matching-engine-app/pom.xml
index f35dadf9c..c27f3b7b4 100644
--- a/matching-engine/matching-engine-app/pom.xml
+++ b/matching-engine/matching-engine-app/pom.xml
@@ -47,6 +47,10 @@
org.springframework.boot
spring-boot-starter-actuator
+
+ co.nilin.opex.utility.preferences
+ preferences
+
diff --git a/matching-engine/matching-engine-app/src/main/kotlin/co/nilin/opex/matching/engine/app/config/AppConfig.kt b/matching-engine/matching-engine-app/src/main/kotlin/co/nilin/opex/matching/engine/app/config/AppConfig.kt
index ef535cba3..246c936ee 100644
--- a/matching-engine/matching-engine-app/src/main/kotlin/co/nilin/opex/matching/engine/app/config/AppConfig.kt
+++ b/matching-engine/matching-engine-app/src/main/kotlin/co/nilin/opex/matching/engine/app/config/AppConfig.kt
@@ -12,16 +12,14 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
@Configuration
class AppConfig {
-
- @Value("\${spring.app.symbols}")
- private val symbols: String? = null
+ @Autowired
+ private lateinit var symbols: List
@Bean
@ConditionalOnMissingBean(value = [OrderBookPersister::class])
@@ -38,22 +36,21 @@ class AppConfig {
@Autowired
fun configureOrderBooks(orderBookPersister: OrderBookPersister) {
- symbols!!.split(",")
- .forEach { symbol ->
- CoroutineScope(AppSchedulers.generalExecutor).launch {
- val lastOrderBook = orderBookPersister.loadLastState(symbol)
- //todo: load db orders from last order in order book and put in order book
- //todo: add missing orders to lastOrderBook or create one
- if (lastOrderBook != null) {
- withContext(coroutineContext) {
- OrderBooks.reloadOrderBook(lastOrderBook)
- }
- } else {
- OrderBooks.createOrderBook(symbol)
+ symbols.forEach { symbol ->
+ CoroutineScope(AppSchedulers.generalExecutor).launch {
+ val lastOrderBook = orderBookPersister.loadLastState(symbol)
+ //todo: load db orders from last order in order book and put in order book
+ //todo: add missing orders to lastOrderBook or create one
+ if (lastOrderBook != null) {
+ withContext(coroutineContext) {
+ OrderBooks.reloadOrderBook(lastOrderBook)
}
-
+ } else {
+ OrderBooks.createOrderBook(symbol)
}
+
}
+ }
}
@Bean
@@ -80,5 +77,4 @@ class AppConfig {
fun configureMatchingEngineListener(exchangeEventHandler: ExchangeEventHandler) {
exchangeEventHandler.register()
}
-
-}
\ No newline at end of file
+}
diff --git a/matching-engine/matching-engine-app/src/main/kotlin/co/nilin/opex/matching/engine/app/config/InitializeService.kt b/matching-engine/matching-engine-app/src/main/kotlin/co/nilin/opex/matching/engine/app/config/InitializeService.kt
new file mode 100644
index 000000000..ede9e53a1
--- /dev/null
+++ b/matching-engine/matching-engine-app/src/main/kotlin/co/nilin/opex/matching/engine/app/config/InitializeService.kt
@@ -0,0 +1,17 @@
+package co.nilin.opex.matching.engine.app.config
+
+import co.nilin.opex.utility.preferences.Preferences
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.Configuration
+
+@Configuration
+class InitializeService() {
+ @Autowired
+ private lateinit var preferences: Preferences
+
+ @Bean("symbols")
+ fun getSymbols(): List {
+ return preferences.markets.map { it.pair ?: "${it.leftSide}_${it.rightSide}" }.map { it.lowercase() }
+ }
+}
diff --git a/matching-engine/matching-engine-app/src/main/resources/application.yml b/matching-engine/matching-engine-app/src/main/resources/application.yml
index 74dec34ed..694e6c8a0 100644
--- a/matching-engine/matching-engine-app/src/main/resources/application.yml
+++ b/matching-engine/matching-engine-app/src/main/resources/application.yml
@@ -10,5 +10,3 @@ spring:
redis:
host: ${REDIS_HOST:localhost}
port: 6379
- app:
- symbols: btc_usdt,eth_usdt,eth_btc,tbtc_tusdt,teth_tusdt,teth_tbtc,btc_irt,eth_irt,bnb_irt,bnb_usdt,busd_irt
diff --git a/matching-engine/matching-engine-ports/matching-engine-eventlistener-kafka/src/main/kotlin/co/nilin/opex/matching/engine/ports/kafka/listener/config/OrderKafkaConfig.kt b/matching-engine/matching-engine-ports/matching-engine-eventlistener-kafka/src/main/kotlin/co/nilin/opex/matching/engine/ports/kafka/listener/config/OrderKafkaConfig.kt
index 8f2edb314..2817f2c00 100644
--- a/matching-engine/matching-engine-ports/matching-engine-eventlistener-kafka/src/main/kotlin/co/nilin/opex/matching/engine/ports/kafka/listener/config/OrderKafkaConfig.kt
+++ b/matching-engine/matching-engine-ports/matching-engine-eventlistener-kafka/src/main/kotlin/co/nilin/opex/matching/engine/ports/kafka/listener/config/OrderKafkaConfig.kt
@@ -29,8 +29,8 @@ class OrderKafkaConfig {
@Value("\${spring.kafka.consumer.group-id}")
private lateinit var groupId: String
- @Value("\${spring.app.symbols}")
- private lateinit var symbols: String
+ @Autowired
+ private lateinit var symbols: List
@Bean("consumerConfigs")
fun consumerConfigs(): Map {
@@ -60,7 +60,7 @@ class OrderKafkaConfig {
@Qualifier("orderKafkaTemplate") template: KafkaTemplate,
@Qualifier("orderConsumerFactory") consumerFactory: ConsumerFactory
) {
- val topics = symbols.split(",").map { s -> "orders_$s" }.toTypedArray()
+ val topics = symbols.map { s -> "orders_$s" }.toTypedArray()
val containerProps = ContainerProperties(*topics)
containerProps.messageListener = orderKafkaListener
val container = KafkaMessageListenerContainer(consumerFactory, containerProps)
@@ -91,4 +91,4 @@ class OrderKafkaConfig {
return DefaultErrorHandler(recoverer, FixedBackOff(5_000, 20))
}
-}
\ No newline at end of file
+}
diff --git a/matching-engine/matching-engine-ports/matching-engine-submitter-kafka/src/main/kotlin/co/nilin/opex/matching/engine/ports/kafka/submitter/config/KafkaTopicConfig.kt b/matching-engine/matching-engine-ports/matching-engine-submitter-kafka/src/main/kotlin/co/nilin/opex/matching/engine/ports/kafka/submitter/config/KafkaTopicConfig.kt
index 5cbc89854..ee8446e29 100644
--- a/matching-engine/matching-engine-ports/matching-engine-submitter-kafka/src/main/kotlin/co/nilin/opex/matching/engine/ports/kafka/submitter/config/KafkaTopicConfig.kt
+++ b/matching-engine/matching-engine-ports/matching-engine-submitter-kafka/src/main/kotlin/co/nilin/opex/matching/engine/ports/kafka/submitter/config/KafkaTopicConfig.kt
@@ -3,7 +3,6 @@ package co.nilin.opex.matching.engine.ports.kafka.submitter.config
import org.apache.kafka.clients.admin.NewTopic
import org.apache.kafka.common.config.TopicConfig
import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Configuration
import org.springframework.context.support.GenericApplicationContext
import org.springframework.kafka.config.TopicBuilder
@@ -12,13 +11,12 @@ import java.util.function.Supplier
@Configuration
class KafkaTopicConfig {
- @Value("\${spring.app.symbols}")
- private lateinit var symbols: String
+ @Autowired
+ private lateinit var symbols: List
@Autowired
fun createTopics(applicationContext: GenericApplicationContext) {
- symbols.split(",")
- .map { s -> "orders_$s" }
+ symbols.map { s -> "orders_$s" }
.forEach { topic ->
applicationContext.registerBean("topic_${topic}", NewTopic::class.java, Supplier {
TopicBuilder.name(topic)
@@ -29,8 +27,7 @@ class KafkaTopicConfig {
})
}
- symbols.split(",")
- .map { s -> "events_$s" }
+ symbols.map { s -> "events_$s" }
.forEach { topic ->
applicationContext.registerBean("topic_${topic}", NewTopic::class.java, Supplier {
TopicBuilder.name(topic)
@@ -41,8 +38,7 @@ class KafkaTopicConfig {
})
}
- symbols.split(",")
- .map { s -> "trades_$s" }
+ symbols.map { s -> "trades_$s" }
.forEach { topic ->
applicationContext.registerBean("topic_${topic}", NewTopic::class.java, Supplier {
TopicBuilder.name(topic)
@@ -54,4 +50,4 @@ class KafkaTopicConfig {
}
}
-}
\ No newline at end of file
+}
diff --git a/matching-engine/pom.xml b/matching-engine/pom.xml
index da7a0072b..c53a2590f 100644
--- a/matching-engine/pom.xml
+++ b/matching-engine/pom.xml
@@ -67,6 +67,11 @@
interceptors
${project.version}
+
+ co.nilin.opex.utility.preferences
+ preferences
+ ${project.version}
+
diff --git a/preferences-demo.yml b/preferences-demo.yml
new file mode 100644
index 000000000..3cbd08b42
--- /dev/null
+++ b/preferences-demo.yml
@@ -0,0 +1,203 @@
+addressTypes:
+ - addressType: bitcoin
+ addressRegex: "*"
+ - addressType: ethereum
+ addressRegex: "*"
+chains:
+ - name: bitcoin
+ addressType: bitcoin
+ endpointUrl: lb://chain-scan-gateway/bitcoin/transfers
+ schedule:
+ delay: 600
+ errorDelay: 60
+ - name: ethereum
+ addressType: ethereum
+ endpointUrl: lb://chain-scan-gateway/eth/transfers
+ schedule:
+ delay: 90
+ errorDelay: 60
+ - name: bsc
+ addressType: ethereum
+ endpointUrl: lb://chain-scan-gateway/bsc/transfers
+ schedule:
+ delay: 90
+ errorDelay: 60
+currencies:
+ - symbol: BTC
+ name: Bitcoin
+ precision: 0.000001
+ mainBalance: 10000
+ dailyTotal: 1000
+ dailyCount: 100
+ monthlyTotal: 30000
+ monthlyCount: 3000
+ implementations:
+ - chain: bitcoin
+ withdrawFee: 0.0001
+ withdrawMin: 0.0001
+ decimal: 0
+ - symbol: ETH
+ name: Ethereum
+ precision: 0.000001
+ mainBalance: 10000
+ dailyTotal: 1000
+ dailyCount: 100
+ monthlyTotal: 30000
+ monthlyCount: 3000
+ implementations:
+ - chain: ethereum
+ withdrawFee: 0.00001
+ withdrawMin: 0.000001
+ decimal: 18
+ - symbol: BNB
+ name: Binance
+ precision: 0.0001
+ mainBalance: 10000
+ dailyTotal: 1000
+ dailyCount: 100
+ monthlyTotal: 30000
+ monthlyCount: 3000
+ implementations:
+ - chain: bsc
+ withdrawFee: 0.00001
+ withdrawMin: 0.000001
+ decimal: 18
+ - symbol: BUSD
+ name: Binance USD
+ precision: 0.01
+ mainBalance: 10000
+ dailyTotal: 1000
+ dailyCount: 100
+ monthlyTotal: 30000
+ monthlyCount: 3000
+ implementations:
+ - chain: bsc
+ token: true
+ tokenAddress: 0xe9e7cea3dedca5984780bafc599bd69add087d56
+ tokenName: BUSD Token
+ withdrawFee: 0.01
+ withdrawMin: 0.01
+ decimal: 18
+ - symbol: IRT
+ name: Toman
+ precision: 0.1
+ mainBalance: 10000
+ dailyTotal: 1000
+ dailyCount: 100
+ monthlyTotal: 30000
+ monthlyCount: 3000
+markets:
+ - leftSide: BTC
+ rightSide: BUSD
+ aliases:
+ - key: binance
+ alias: BTCBUSD
+ feeConfigs:
+ - direction: ASK
+ userLevel: "*"
+ makerFee: 0.01
+ takerFee: 0.01
+ - direction: BID
+ userLevel: "*"
+ makerFee: 0.01
+ takerFee: 0.01
+ - leftSide: ETH
+ rightSide: BUSD
+ aliases:
+ - key: binance
+ alias: ETHBUSD
+ feeConfigs:
+ - direction: ASK
+ userLevel: "*"
+ makerFee: 0.01
+ takerFee: 0.01
+ - direction: BID
+ userLevel: "*"
+ makerFee: 0.01
+ takerFee: 0.01
+ - leftSide: BNB
+ rightSide: BUSD
+ aliases:
+ - key: binance
+ alias: BNBBUSD
+ feeConfigs:
+ - direction: ASK
+ userLevel: "*"
+ makerFee: 0.01
+ takerFee: 0.01
+ - direction: BID
+ userLevel: "*"
+ makerFee: 0.01
+ takerFee: 0.01
+ - leftSide: BTC
+ rightSide: IRT
+ aliases:
+ - key: binance
+ alias: BTCIRT
+ feeConfigs:
+ - direction: ASK
+ userLevel: "*"
+ makerFee: 0.01
+ takerFee: 0.01
+ - direction: BID
+ userLevel: "*"
+ makerFee: 0.01
+ takerFee: 0.01
+ - leftSide: ETH
+ rightSide: IRT
+ aliases:
+ - key: binance
+ alias: ETHIRT
+ feeConfigs:
+ - direction: ASK
+ userLevel: "*"
+ makerFee: 0.01
+ takerFee: 0.01
+ - direction: BID
+ userLevel: "*"
+ makerFee: 0.01
+ takerFee: 0.01
+ - leftSide: BNB
+ rightSide: IRT
+ aliases:
+ - key: binance
+ alias: BNBIRT
+ feeConfigs:
+ - direction: ASK
+ userLevel: "*"
+ makerFee: 0.01
+ takerFee: 0.01
+ - direction: BID
+ userLevel: "*"
+ makerFee: 0.01
+ takerFee: 0.01
+ - leftSide: BUSD
+ rightSide: IRT
+ aliases:
+ - key: binance
+ alias: BUSDIRT
+ feeConfigs:
+ - direction: ASK
+ userLevel: "*"
+ makerFee: 0.01
+ takerFee: 0.01
+ - direction: BID
+ userLevel: "*"
+ makerFee: 0.01
+ takerFee: 0.01
+wallet:
+ schedule:
+ delay: 10
+ batchSize: 10000
+userLimits:
+ - owner: 1
+ action: withdraw
+ walletType: main
+ withdrawFee: 0.0001
+ dailyTotal: 1000
+ dailyCount: 100
+ monthlyTotal: 30000
+ monthlyCount: 3000
+system:
+ walletTitle: system
+ walletLevel: basic
diff --git a/preferences-dev.yml b/preferences-dev.yml
new file mode 100644
index 000000000..1e97292ea
--- /dev/null
+++ b/preferences-dev.yml
@@ -0,0 +1,159 @@
+addressTypes:
+ - addressType: ethereum
+ addressRegex: "*"
+ - addressType: test-bitcoin
+ addressRegex: "*"
+chains:
+ - name: test-bitcoin
+ addressType: test-bitcoin
+ endpointUrl: lb://chain-scan-gateway/test-bitcoin/transfers
+ schedule:
+ delay: 600
+ errorDelay: 60
+ - name: test-ethereum
+ addressType: ethereum
+ endpointUrl: lb://chain-scan-gateway/test-eth/transfers
+ schedule:
+ delay: 90
+ errorDelay: 60
+currencies:
+ - symbol: IRT
+ name: Toman
+ precision: 0.1
+ mainBalance: 10000
+ dailyTotal: 1000
+ dailyCount: 100
+ monthlyTotal: 30000
+ monthlyCount: 3000
+ - symbol: TBTC
+ name: Bitcoin (Test)
+ precision: 0.000001
+ mainBalance: 10000
+ dailyTotal: 1000
+ dailyCount: 100
+ monthlyTotal: 30000
+ monthlyCount: 3000
+ implementations:
+ - chain: test-bitcoin
+ withdrawFee: 0.0001
+ withdrawMin: 0.0001
+ decimal: 0
+ gift: 21000000
+ - symbol: TETH
+ name: Ethereum (Test)
+ precision: 0.000001
+ mainBalance: 10000
+ dailyTotal: 1000
+ dailyCount: 100
+ monthlyTotal: 30000
+ monthlyCount: 3000
+ implementations:
+ - chain: test-ethereum
+ withdrawFee: 0.00001
+ withdrawMin: 0.000001
+ decimal: 18
+ gift: 2000
+ - symbol: TUSDT
+ name: Tether (Test)
+ precision: 0.01
+ mainBalance: 10000
+ dailyTotal: 1000
+ dailyCount: 100
+ monthlyTotal: 30000
+ monthlyCount: 3000
+ implementations:
+ - chain: ethereum
+ token: true
+ tokenAddress: 0x110a13fc3efe6a245b50102d2d79b3e76125ae83
+ tokenName: Tether USD
+ withdrawFee: 0.01
+ withdrawMin: 0.01
+ decimal: 6
+ gift: 1000000
+markets:
+ - leftSide: TBTC
+ rightSide: TUSDT
+ aliases:
+ - key: binance
+ alias: TBTCTUSDT
+ feeConfigs:
+ - direction: ASK
+ userLevel: "*"
+ makerFee: 0.01
+ takerFee: 0.01
+ - direction: BID
+ userLevel: "*"
+ makerFee: 0.01
+ takerFee: 0.01
+ - leftSide: TETH
+ rightSide: TUSDT
+ aliases:
+ - key: binance
+ alias: TETHTUSDT
+ feeConfigs:
+ - direction: ASK
+ userLevel: "*"
+ makerFee: 0.01
+ takerFee: 0.01
+ - direction: BID
+ userLevel: "*"
+ makerFee: 0.01
+ takerFee: 0.01
+ - leftSide: TBTC
+ rightSide: IRT
+ aliases:
+ - key: binance
+ alias: TBTCIRT
+ feeConfigs:
+ - direction: ASK
+ userLevel: "*"
+ makerFee: 0.01
+ takerFee: 0.01
+ - direction: BID
+ userLevel: "*"
+ makerFee: 0.01
+ takerFee: 0.01
+ - leftSide: TETH
+ rightSide: IRT
+ aliases:
+ - key: binance
+ alias: TETHIRT
+ feeConfigs:
+ - direction: ASK
+ userLevel: "*"
+ makerFee: 0.01
+ takerFee: 0.01
+ - direction: BID
+ userLevel: "*"
+ makerFee: 0.01
+ takerFee: 0.01
+ - leftSide: TUSDT
+ rightSide: IRT
+ aliases:
+ - key: binance
+ alias: TUSDTIRT
+ feeConfigs:
+ - direction: ASK
+ userLevel: "*"
+ makerFee: 0.01
+ takerFee: 0.01
+ - direction: BID
+ userLevel: "*"
+ makerFee: 0.01
+ takerFee: 0.01
+wallet:
+ schedule:
+ delay: 10
+ batchSize: 10000
+userLimits:
+ - owner: 1
+ action: withdraw
+ walletType: main
+ withdrawFee: 0.0001
+ dailyTotal: 1000
+ dailyCount: 100
+ monthlyTotal: 30000
+ monthlyCount: 3000
+system:
+ walletTitle: system
+ walletLevel: basic
diff --git a/utility/pom.xml b/utility/pom.xml
index b55db498f..6216eec86 100644
--- a/utility/pom.xml
+++ b/utility/pom.xml
@@ -20,6 +20,7 @@
error-handler
logging-handler
interceptors
+ preferences
diff --git a/utility/preferences/pom.xml b/utility/preferences/pom.xml
new file mode 100644
index 000000000..6dfc536ef
--- /dev/null
+++ b/utility/preferences/pom.xml
@@ -0,0 +1,26 @@
+
+
+ 4.0.0
+
+ utility
+ co.nilin.opex.utility
+ 1.0-SNAPSHOT
+
+
+ co.nilin.opex.utility.preferences
+ preferences
+
+
+
+ org.springframework
+ spring-context
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-yaml
+ 2.13.0
+
+
+
diff --git a/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/AddressType.kt b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/AddressType.kt
new file mode 100644
index 000000000..7ef22eba0
--- /dev/null
+++ b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/AddressType.kt
@@ -0,0 +1,3 @@
+package co.nilin.opex.utility.preferences
+
+data class AddressType(var addressType: String = "", var addressRegex: String = "*")
diff --git a/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/Alias.kt b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/Alias.kt
new file mode 100644
index 000000000..4fbd6b4a8
--- /dev/null
+++ b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/Alias.kt
@@ -0,0 +1,3 @@
+package co.nilin.opex.utility.preferences
+
+data class Alias(var key: String = "", var alias: String = "")
diff --git a/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/Chain.kt b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/Chain.kt
new file mode 100644
index 000000000..8cc4abecc
--- /dev/null
+++ b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/Chain.kt
@@ -0,0 +1,8 @@
+package co.nilin.opex.utility.preferences
+
+data class Chain(
+ var name: String = "",
+ var addressType: String = "",
+ val endpointUrl: String = "",
+ var schedule: ChainSyncSchedule = ChainSyncSchedule()
+)
diff --git a/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/ChainSyncSchedule.kt b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/ChainSyncSchedule.kt
new file mode 100644
index 000000000..19b8f824a
--- /dev/null
+++ b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/ChainSyncSchedule.kt
@@ -0,0 +1,5 @@
+package co.nilin.opex.utility.preferences
+
+data class ChainSyncSchedule(
+ var delay: Long = 600, var errorDelay: Long = 60
+)
diff --git a/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/Currency.kt b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/Currency.kt
new file mode 100644
index 000000000..1537c7583
--- /dev/null
+++ b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/Currency.kt
@@ -0,0 +1,16 @@
+package co.nilin.opex.utility.preferences
+
+import java.math.BigDecimal
+
+data class Currency(
+ var symbol: String = "",
+ var name: String = "",
+ var precision: BigDecimal = BigDecimal.ONE,
+ var mainBalance: BigDecimal = BigDecimal.ZERO,
+ var dailyTotal: BigDecimal = BigDecimal.valueOf(1000),
+ var dailyCount: Int = 100,
+ var monthlyTotal: BigDecimal = BigDecimal.valueOf(30000),
+ var monthlyCount: Int = 3000,
+ var implementations: List = emptyList(),
+ var gift: BigDecimal = BigDecimal.ZERO
+)
diff --git a/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/CurrencyImplementation.kt b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/CurrencyImplementation.kt
new file mode 100644
index 000000000..97d778095
--- /dev/null
+++ b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/CurrencyImplementation.kt
@@ -0,0 +1,14 @@
+package co.nilin.opex.utility.preferences
+
+import java.math.BigDecimal
+
+data class CurrencyImplementation(
+ var chain: String = "",
+ var withdrawEnabled: Boolean = true,
+ var token: Boolean = false,
+ var tokenAddress: String? = null,
+ var tokenName: String? = null,
+ var withdrawFee: BigDecimal = BigDecimal.valueOf(0.01),
+ var withdrawMin: BigDecimal = BigDecimal.valueOf(0.01),
+ var decimal: Int = 0
+)
diff --git a/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/FeeConfig.kt b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/FeeConfig.kt
new file mode 100644
index 000000000..44e10c193
--- /dev/null
+++ b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/FeeConfig.kt
@@ -0,0 +1,10 @@
+package co.nilin.opex.utility.preferences
+
+import java.math.BigDecimal
+
+data class FeeConfig(
+ var userLevel: String = "",
+ var direction: String = "",
+ var makerFee: BigDecimal = BigDecimal.valueOf(0.01),
+ var takerFee: BigDecimal = BigDecimal.valueOf(0.01)
+)
diff --git a/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/Market.kt b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/Market.kt
new file mode 100644
index 000000000..04c738c88
--- /dev/null
+++ b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/Market.kt
@@ -0,0 +1,13 @@
+package co.nilin.opex.utility.preferences
+
+import java.math.BigDecimal
+
+data class Market(
+ var leftSide: String = "",
+ var rightSide: String = "",
+ var pair: String? = null,
+ var feeConfigs: List = emptyList(),
+ var aliases: List = emptyList(),
+ var leftSideFraction: BigDecimal? = null,
+ var rightSideFraction: BigDecimal? = null
+)
diff --git a/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/Preferences.kt b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/Preferences.kt
new file mode 100644
index 000000000..5649f35d2
--- /dev/null
+++ b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/Preferences.kt
@@ -0,0 +1,11 @@
+package co.nilin.opex.utility.preferences
+
+data class Preferences(
+ var addressTypes: List = emptyList(),
+ var chains: List = emptyList(),
+ var currencies: List = emptyList(),
+ var markets: List = emptyList(),
+ var userLimits: List = emptyList(),
+ var wallet: Wallet = Wallet(),
+ var system: System = System()
+)
diff --git a/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/System.kt b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/System.kt
new file mode 100644
index 000000000..7820c402d
--- /dev/null
+++ b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/System.kt
@@ -0,0 +1,5 @@
+package co.nilin.opex.utility.preferences
+
+data class System(
+ var walletTitle: String = "system", var walletLevel: String = "basic"
+)
diff --git a/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/UserLimit.kt b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/UserLimit.kt
new file mode 100644
index 000000000..958374899
--- /dev/null
+++ b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/UserLimit.kt
@@ -0,0 +1,15 @@
+package co.nilin.opex.utility.preferences
+
+import java.math.BigDecimal
+
+data class UserLimit(
+ var level: String? = null,
+ var owner: Long = 1,
+ var action: String = "withdraw",
+ var walletType: String = "main",
+ var withdrawFee: BigDecimal = BigDecimal.valueOf(0.0001),
+ var dailyTotal: BigDecimal = BigDecimal.valueOf(1000),
+ var dailyCount: Int = 100,
+ var monthlyTotal: BigDecimal = BigDecimal.valueOf(30000),
+ var monthlyCount: Int = 3000
+)
diff --git a/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/Wallet.kt b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/Wallet.kt
new file mode 100644
index 000000000..487130f88
--- /dev/null
+++ b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/Wallet.kt
@@ -0,0 +1,5 @@
+package co.nilin.opex.utility.preferences
+
+data class Wallet(
+ var schedule: WalletSyncSchedule = WalletSyncSchedule()
+)
diff --git a/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/WalletSyncSchedule.kt b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/WalletSyncSchedule.kt
new file mode 100644
index 000000000..d001817e2
--- /dev/null
+++ b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/WalletSyncSchedule.kt
@@ -0,0 +1,3 @@
+package co.nilin.opex.utility.preferences
+
+class WalletSyncSchedule(var delay: Long = 10, var batchSize: Long = 10000)
diff --git a/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/reader/ReadPreferences.kt b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/reader/ReadPreferences.kt
new file mode 100644
index 000000000..cce06f5cd
--- /dev/null
+++ b/utility/preferences/src/main/kotlin/co/nilin/opex/utility/preferences/reader/ReadPreferences.kt
@@ -0,0 +1,23 @@
+package co.nilin.opex.utility.preferences.reader
+
+import co.nilin.opex.utility.preferences.Preferences
+import com.fasterxml.jackson.databind.ObjectMapper
+import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
+import org.springframework.beans.factory.annotation.Value
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.Configuration
+import java.io.File
+
+@Configuration
+class ReadPreferences() {
+ private val mapper = ObjectMapper(YAMLFactory())
+
+ @Value("\${PREFERENCES:classpath:preferences.yml}")
+ private lateinit var preferencesYmlPath: String
+
+ @Bean
+ fun preferences(): Preferences = runCatching {
+ val preferencesYml = File(preferencesYmlPath)
+ mapper.readValue(preferencesYml, Preferences::class.java)
+ }.getOrElse { Preferences() }
+}
diff --git a/wallet/pom.xml b/wallet/pom.xml
index 8b7b0dd83..79ffc0cc5 100644
--- a/wallet/pom.xml
+++ b/wallet/pom.xml
@@ -61,6 +61,11 @@
interceptors
${project.version}
+
+ co.nilin.opex.utility.preferences
+ preferences
+ ${project.version}
+
diff --git a/wallet/wallet-app/pom.xml b/wallet/wallet-app/pom.xml
index f38284053..f3fa59979 100644
--- a/wallet/wallet-app/pom.xml
+++ b/wallet/wallet-app/pom.xml
@@ -107,6 +107,10 @@
org.springframework.cloud
spring-cloud-starter-vault-config
+
+ co.nilin.opex.utility.preferences
+ preferences
+
diff --git a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/config/InitializeService.kt b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/config/InitializeService.kt
new file mode 100644
index 000000000..f98c87207
--- /dev/null
+++ b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/config/InitializeService.kt
@@ -0,0 +1,83 @@
+package co.nilin.opex.wallet.app.config
+
+import co.nilin.opex.utility.preferences.Currency
+import co.nilin.opex.utility.preferences.Preferences
+import co.nilin.opex.utility.preferences.UserLimit
+import co.nilin.opex.wallet.ports.postgres.dao.CurrencyRepository
+import co.nilin.opex.wallet.ports.postgres.dao.UserLimitsRepository
+import co.nilin.opex.wallet.ports.postgres.dao.WalletOwnerRepository
+import co.nilin.opex.wallet.ports.postgres.dao.WalletRepository
+import co.nilin.opex.wallet.ports.postgres.model.UserLimitsModel
+import co.nilin.opex.wallet.ports.postgres.model.WalletModel
+import co.nilin.opex.wallet.ports.postgres.model.WalletOwnerModel
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.reactor.awaitSingle
+import kotlinx.coroutines.reactor.awaitSingleOrNull
+import kotlinx.coroutines.runBlocking
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.beans.factory.annotation.Value
+import org.springframework.context.annotation.DependsOn
+import org.springframework.stereotype.Component
+import java.math.BigDecimal
+
+@Component
+@DependsOn("postgresConfig")
+class InitializeService(
+ @Value("\${app.system.uuid}") val systemUuid: String,
+ private val currencyRepository: CurrencyRepository,
+ private val walletOwnerRepository: WalletOwnerRepository,
+ private val walletRepository: WalletRepository,
+ private val userLimitsRepository: UserLimitsRepository
+) {
+ @Autowired
+ private lateinit var preferences: Preferences
+
+ @Autowired
+ fun init() = runBlocking {
+ addCurrencies(preferences.currencies)
+ addSystemWallet(preferences)
+ addUserLimits(preferences.userLimits)
+ }
+
+ private suspend fun addUserLimits(data: List) = coroutineScope {
+ data.forEachIndexed { i, it ->
+ if (!userLimitsRepository.existsById(i + 1L).awaitSingle()) {
+ runCatching {
+ userLimitsRepository.save(
+ UserLimitsModel(
+ null,
+ it.level,
+ it.owner,
+ it.action,
+ it.walletType,
+ it.dailyTotal,
+ it.dailyCount,
+ it.monthlyTotal,
+ it.monthlyCount
+ )
+ ).awaitSingleOrNull()
+ }
+ }
+ }
+ }
+
+ private suspend fun addSystemWallet(p: Preferences) = coroutineScope {
+ if (!walletOwnerRepository.existsById(1).awaitSingle()) {
+ walletOwnerRepository.save(WalletOwnerModel(null, systemUuid, p.system.walletTitle, p.system.walletLevel))
+ .awaitSingleOrNull()
+ }
+ val items = p.currencies.flatMap {
+ listOf(
+ WalletModel(null, 1, "main", it.symbol, it.mainBalance),
+ WalletModel(null, 1, "exchange", it.symbol, BigDecimal.ZERO)
+ )
+ }
+ runCatching { walletRepository.saveAll(items).collectList().awaitSingleOrNull() }
+ }
+
+ private suspend fun addCurrencies(data: List) = coroutineScope {
+ data.forEach {
+ currencyRepository.insert(it.name, it.symbol, it.precision.toDouble()).awaitSingleOrNull()
+ }
+ }
+}
diff --git a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/service/UserRegistrationService.kt b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/service/UserRegistrationService.kt
index 4ee4c420e..f2c679c81 100644
--- a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/service/UserRegistrationService.kt
+++ b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/service/UserRegistrationService.kt
@@ -2,47 +2,31 @@ package co.nilin.opex.wallet.app.service
import co.nilin.opex.utility.error.data.OpexError
import co.nilin.opex.utility.error.data.OpexException
+import co.nilin.opex.utility.preferences.Preferences
import co.nilin.opex.wallet.core.model.Amount
-import co.nilin.opex.wallet.core.model.Wallet
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.ports.kafka.listener.model.UserCreatedEvent
-import org.springframework.beans.factory.annotation.Value
+import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
import org.springframework.transaction.annotation.Transactional
import java.math.BigDecimal
@Component
class UserRegistrationService(
- val walletOwnerManager: WalletOwnerManager,
- val walletManager: WalletManager,
- val currencyService: CurrencyService,
- @Value("\${app.gift.symbol}")
- val symbol: String,
- @Value("\${app.gift.amount}")
- val amount: BigDecimal
+ val walletOwnerManager: WalletOwnerManager, val walletManager: WalletManager, val currencyService: CurrencyService
) {
- @Transactional
- suspend fun registerNewUser(event: UserCreatedEvent): Wallet {
- val owner =
- walletOwnerManager.createWalletOwner(event.uuid, "${event.firstName} ${event.lastName}", "1")
+ @Autowired
+ private lateinit var preferences: Preferences
- val btcSymbol = currencyService.getCurrency("tbtc") ?: throw OpexException(OpexError.CurrencyNotFound)
- //TODO REMOVE LATER
- walletManager.createWallet(
- owner,
- Amount(btcSymbol, BigDecimal.ONE),
- btcSymbol,
- "main"
- )
+ @Transactional
+ suspend fun registerNewUser(event: UserCreatedEvent) {
+ val owner = walletOwnerManager.createWalletOwner(event.uuid, "${event.firstName} ${event.lastName}", "1")
- val giftSymbol = currencyService.getCurrency(symbol) ?: throw OpexException(OpexError.CurrencyNotFound)
- return walletManager.createWallet(
- owner,
- Amount(giftSymbol, amount),
- giftSymbol,
- "main"
- )
+ preferences.currencies.filter { it.gift > BigDecimal.ZERO }.forEach {
+ val currency = currencyService.getCurrency(it.symbol) ?: throw OpexException(OpexError.CurrencyNotFound)
+ walletManager.createWallet(owner, Amount(currency, it.gift), currency, "main")
+ }
}
}
diff --git a/wallet/wallet-app/src/main/resources/application.yml b/wallet/wallet-app/src/main/resources/application.yml
index 6874669f9..2f3f0f75e 100644
--- a/wallet/wallet-app/src/main/resources/application.yml
+++ b/wallet/wallet-app/src/main/resources/application.yml
@@ -44,9 +44,6 @@ spring:
config:
import: vault://secret/${spring.application.name}
app:
- gift:
- symbol: tusdt
- amount: 1000
auth:
cert-url: lb://opex-auth/auth/realms/opex/protocol/openid-connect/certs
system:
diff --git a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/config/PostgresConfig.kt b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/config/PostgresConfig.kt
index 793b4a09a..d06b8686d 100644
--- a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/config/PostgresConfig.kt
+++ b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/config/PostgresConfig.kt
@@ -10,17 +10,13 @@ import org.springframework.r2dbc.core.DatabaseClient
@EnableR2dbcRepositories(basePackages = ["co.nilin.opex"])
class PostgresConfig(
db: DatabaseClient,
- @Value("classpath:schema.sql") private val schemaResource: Resource,
- @Value("classpath:data.sql") private val dataResource: Resource?
+ @Value("classpath:schema.sql") private val schemaResource: Resource
) {
init {
val schemaReader = schemaResource.inputStream.reader()
val schema = schemaReader.readText().trim()
schemaReader.close()
- val dataReader = dataResource?.inputStream?.reader()
- val data = dataReader?.readText()?.trim() ?: ""
- dataReader?.close()
- val initDb = db.sql { schema.plus(data) }
+ val initDb = db.sql { schema }
initDb // initialize the database
.then()
.subscribe() // execute
diff --git a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/dao/CurrencyRepository.kt b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/dao/CurrencyRepository.kt
index dcc8981a2..53700ce0b 100644
--- a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/dao/CurrencyRepository.kt
+++ b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/dao/CurrencyRepository.kt
@@ -12,10 +12,10 @@ interface CurrencyRepository : ReactiveCrudRepository {
@Query("select * from currency where symbol = :symbol")
fun findBySymbol(symbol: String): Mono
- @Query("insert into currency values (:name, :symbol, :precision) on conflict do nothing")
+ @Query("insert into currency values (:symbol, :name, :precision) on conflict do nothing")
fun insert(name: String, symbol: String, precision: Double): Mono
@Query("delete from currency where name = :name")
fun deleteByName(name: String): Mono
-}
\ No newline at end of file
+}
diff --git a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/model/UserLimitsModel.kt b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/model/UserLimitsModel.kt
index edc298c78..cb70e3379 100644
--- a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/model/UserLimitsModel.kt
+++ b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/model/UserLimitsModel.kt
@@ -7,7 +7,7 @@ import java.math.BigDecimal
@Table("user_limits")
class UserLimitsModel(
- @Id val id: Long?,
+ @Id var id: Long?,
val level: String?,
val owner: Long?,
val action: String, //withdraw or deposit
@@ -16,4 +16,4 @@ class UserLimitsModel(
@Column("daily_count") val dailyCount: Int?,
@Column("monthly_total") val monthlyTotal: BigDecimal?,
@Column("monthly_count") val monthlyCount: Int?
-)
\ No newline at end of file
+)
diff --git a/wallet/wallet-ports/wallet-persister-postgres/src/main/resources/data.sql b/wallet/wallet-ports/wallet-persister-postgres/src/main/resources/data.sql
deleted file mode 100644
index edc167ca4..000000000
--- a/wallet/wallet-ports/wallet-persister-postgres/src/main/resources/data.sql
+++ /dev/null
@@ -1,87 +0,0 @@
-INSERT INTO wallet_owner(id, uuid, title, level)
-VALUES (1, '1', 'system', 'basic')
-ON CONFLICT DO NOTHING;
-
-SELECT setval(pg_get_serial_sequence('wallet_owner', 'id'), (SELECT MAX(id) FROM wallet_owner));
-
-INSERT INTO currency(name, symbol, precision)
-VALUES ('btc', 'btc', 0.000001),
- ('eth', 'eth', 0.00001),
- ('usdt', 'usdt', 0.01),
- ('bnb', 'bnb', 0.01),
- ('busd', 'busd', 0.01),
- ('nln', 'nln', 1),
- ('irt', 'irt', 1)
-ON CONFLICT DO NOTHING;
-
--- Test currency
-INSERT INTO currency(name, symbol, precision)
-VALUES ('tbtc', 'tbtc', 0.000001),
- ('teth', 'teth', 0.00001),
- ('tusdt', 'tusdt', 0.01)
-ON CONFLICT DO NOTHING;
-
-INSERT INTO currency_rate(id, source_currency, dest_currency, rate)
-VALUES (1, 'btc', 'nln', 5500000),
- (2, 'usdt', 'nln', 100),
- (3, 'btc', 'usdt', 55000),
- (4, 'eth', 'usdt', 3800),
- (5, 'btc', 'irt', 3800),
- (6, 'eth', 'irt', 3800),
- (7, 'bnb', 'irt', 3800),
- (8, 'bnb', 'usdt', 3800),
- (9, 'busd', 'usdt', 3800)
-ON CONFLICT DO NOTHING;
-
--- Test currency rate
-INSERT INTO currency_rate(id, source_currency, dest_currency, rate)
-VALUES (10, 'tbtc', 'nln', 5500000),
- (11, 'tusdt', 'nln', 100),
- (12, 'tbtc', 'tusdt', 55000),
- (13, 'teth', 'tusdt', 3800)
-ON CONFLICT DO NOTHING;
-
-SELECT setval(pg_get_serial_sequence('currency_rate', 'id'), (SELECT MAX(id) FROM currency_rate));
-
-INSERT INTO wallet(id, owner, wallet_type, currency, balance)
-VALUES (1, 1, 'main', 'btc', 10),
- (2, 1, 'exchange', 'btc', 0),
- (3, 1, 'main', 'usdt', 550000),
- (4, 1, 'exchange', 'usdt', 0),
- (5, 1, 'main', 'nln', 100000000),
- (6, 1, 'exchange', 'nln', 0),
- (7, 1, 'main', 'eth', 10000),
- (8, 1, 'exchange', 'eth', 0),
- (9, 1, 'main', 'irt', 100000000),
- (10, 1, 'exchange', 'irt', 0),
- (11, 1, 'main', 'bnb', 100000000),
- (12, 1, 'exchange', 'bnb', 0),
- (13, 1, 'main', 'busd', 100000000),
- (14, 1, 'exchange', 'busd', 0)
-ON CONFLICT DO NOTHING;
-
--- Test wallet
-INSERT INTO wallet(id, owner, wallet_type, currency, balance)
-VALUES (15, 1, 'main', 'tbtc', 10),
- (16, 1, 'exchange', 'tbtc', 0),
- (17, 1, 'main', 'tusdt', 550000),
- (18, 1, 'exchange', 'tusdt', 0),
- (19, 1, 'main', 'teth', 10000),
- (20, 1, 'exchange', 'teth', 0)
-ON CONFLICT DO NOTHING;
-
-SELECT setval(pg_get_serial_sequence('wallet', 'id'), (SELECT MAX(id) FROM wallet));
-
-INSERT INTO user_limits(id,
- level,
- owner,
- action,
- wallet_type,
- daily_total,
- daily_count,
- monthly_total,
- monthly_count)
-VALUES (1, null, 1, 'withdraw', 'main', 1000, 100, 10000, 1000)
-ON CONFLICT DO NOTHING;
-
-SELECT setval(pg_get_serial_sequence('user_limits', 'id'), (SELECT MAX(id) FROM user_limits));
diff --git a/wallet/wallet-ports/wallet-persister-postgres/src/main/resources/schema.sql b/wallet/wallet-ports/wallet-persister-postgres/src/main/resources/schema.sql
index fd9462799..e37ea43c1 100644
--- a/wallet/wallet-ports/wallet-persister-postgres/src/main/resources/schema.sql
+++ b/wallet/wallet-ports/wallet-persister-postgres/src/main/resources/schema.sql
@@ -31,7 +31,8 @@ CREATE TABLE IF NOT EXISTS wallet
owner INTEGER NOT NULL REFERENCES wallet_owner (id),
wallet_type VARCHAR(10) NOT NULL,
currency VARCHAR(25) NOT NULL REFERENCES currency (symbol),
- balance DECIMAL NOT NULL
+ balance DECIMAL NOT NULL,
+ UNIQUE (owner, wallet_type, currency)
);
CREATE TABLE IF NOT EXISTS transaction