-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuild.sbt
More file actions
414 lines (371 loc) · 15.8 KB
/
build.sbt
File metadata and controls
414 lines (371 loc) · 15.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
import java.time.Instant
import sbt.Compile
// Versions
val akkaVersion = "2.6.17"
val akkaHttpVersion = "10.2.7"
val calibanVersion = "1.3.0"
val commonsIoVersion = "2.6"
val configLibVersion = "1.4.1"
val flywayDbVersion = "7.15.0"
val h2DatabaseVersion = "1.4.199"
val logbackVersion = "1.2.3"
val postgresqlVersion = "42.2.24"
val scalaLoggingVersion = "3.9.2"
val scalaParallelCollectionsVersion = "1.0.0"
val scalaTestVersion = "3.1.0"
val scalikeJdbcVersion = "4.0.0"
val scoptVersion = "4.0.0"
val sttpClient3Version = "3.3.18"
val web3jVersion = "4.9.0"
val jacksonCoreVersion = "2.11.4" // same version as used by akka-serialization-jackson for Scala 2.13
val javaSlf4jVersion = "1.7.30"
val javaJunitVersion = "4.13.2"
val javaCheckerVersion = "3.14.0"
val javaCommonsCLIVersion = "1.4"
// Helper functions
def versionFileTask(filename: String) = Def.task {
val file = (Compile / resourceManaged).value / "unicherrygarden" / filename
val contents =
s"""version=${version.value}
|build_timestamp=${unicherryGardenBuildTimestamp}"""
.stripMargin
IO.write(file, contents)
Seq(file)
}
// Common settings
sonatypeRepository := "https://s01.oss.sonatype.org/service/local"
sonatypeCredentialHost := "s01.oss.sonatype.org"
publishTo := sonatypePublishToBundle.value
val projectVersion = "0.10.9"
name := "unicherrygarden"
version := projectVersion
val unicherryGardenBuildTimestamp = Instant.now
// Configure settings for all (!) subprojects
inThisBuild(List(
organization := "com.myodov.unicherrygarden",
version := projectVersion,
scalaVersion := "2.13.8",
javacOptions ++= Seq("-source", "1.8", "-target", "1.8", "-parameters", "-Xlint:unchecked"),
organizationName := "UniCherryGarden",
organizationHomepage := Some(url("https://github.com/UniversaBlockchain/UniCherryGarden")),
homepage := Some(url("https://github.com/UniversaBlockchain/UniCherryGarden")),
startYear := Some(2021),
description := "UniCherryGarden: universal “data gardening” solution for Ethereum blockchain data",
scmInfo := Some(ScmInfo(
url("https://github.com/UniversaBlockchain/UniCherryGarden"),
"scm:git@github.com:UniversaBlockchain/UniCherryGarden.git"
)),
licenses := Seq("MIT License" -> url("https://github.com/UniversaBlockchain/UniCherryGarden/blob/master/LICENSE")),
developers := List(
Developer(
id = "amyodov",
name = "Alex Myodov",
email = "amyodov@gmail.com",
url = url("https://myodov.com/")
)
),
scalacOptions ++= Seq(
// display deprecations, warnings and feature warnings on compilations
"-unchecked", "-deprecation", "-feature")
++ Seq("-Xelide-below", sys.props.getOrElse("elide.below", "0"))
++ Seq(sys.props.getOrElse("scalacopt", "-opt:l:default")),
))
usePgpKeyHex("BE53ACD082329B6231C5D4F41B6C3A2684CA4538")
lazy val commonSettings = Seq(
// We don't want Javadoc generated, as it issues too many problems with “wrong” Javadoc tags;
// and also causes many warnings for bad Javadoc.
sources in(Compile, doc) := Seq.empty,
publishTo := sonatypePublishToBundle.value,
)
lazy val commonJavaSettings = Seq(
libraryDependencies ++= Seq(
// For logging
"org.slf4j" % "slf4j-api" % javaSlf4jVersion,
// For Unit tests
"junit" % "junit" % javaJunitVersion % Test,
// So the test scripts will have its data logged to STDOUT
"ch.qos.logback" % "logback-classic" % logbackVersion % Test,
// Type annotations
"org.checkerframework" % "checker-qual" % javaCheckerVersion,
),
// Java-only artifacts shouldn't have the Scala-version postfix in their names.
crossPaths := false,
)
lazy val commonScalaSettings = Seq(
libraryDependencies ++= Seq(
"org.scalatest" %% "scalatest" % scalaTestVersion % Test,
// So the test scripts will have its data logged to STDOUT
"ch.qos.logback" % "logback-classic" % logbackVersion % Test,
"com.typesafe.scala-logging" %% "scala-logging" % scalaLoggingVersion,
"org.scala-lang.modules" %% "scala-parallel-collections" % scalaParallelCollectionsVersion
),
)
/** Settings common to any component that uses Akka for microservice/actor architecture. */
lazy val commonAkkaMicroserviceSettings = Seq(
libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-actor-typed" % akkaVersion,
"com.typesafe.akka" %% "akka-cluster-typed" % akkaVersion,
"com.typesafe.akka" %% "akka-serialization-jackson" % akkaVersion,
"com.typesafe.akka" %% "akka-slf4j" % akkaVersion,
"com.typesafe.akka" %% "akka-actor-testkit-typed" % akkaVersion % Test,
),
)
/** Settings common to anything that uses JavaAppPackaging to deploy a binary runnable package. */
lazy val commonJavaAppPackagingSettings = Seq(
Universal / javaOptions ++= Seq(
"-Dlog4j2.formatMsgNoLookups=true",
),
)
//
// Java components
//
// (Java-based) a virtual “project” that contains all settings/data common for all Java projects.
lazy val commonJava = (project in file("java/common_java"))
.settings(
commonSettings,
commonJavaSettings,
name := "common_java",
description := "UniCherryGarden: the contents common for all Java-language components",
)
// (Java-based) Low-level Akka interoperability layer (messages) to communicate
// between CherryGarden Akka remote actors and Client Connector.
lazy val ethUtils = (project in file("java/ethutils"))
.settings(
commonSettings,
commonJavaSettings,
name := "ethutils",
description := "UniCherryGarden: Java-based classes and helpers to work with Ethereum blockchain/data structures",
libraryDependencies ++= Seq(
"org.web3j" % "core" % web3jVersion,
),
)
.dependsOn(commonJava)
// (Java-based) Low-level Akka interoperability layer (messages) to communicate
// between CherryGarden Akka remote actors and Client Connector.
lazy val cherryGardenerInterop = (project in file("java/cherrygardener_interop"))
.settings(
commonSettings,
commonJavaSettings,
name := "cherrygardener_interop",
description := "UniCherryGarden: “interop” classes defining the Akka communication messages between Java and Scala code",
libraryDependencies ++= Seq(
// Web3j library, for Ethereum-specific data and algorithms
"org.web3j" % "core" % web3jVersion,
"org.web3j" % "contracts" % web3jVersion,
// Akka
"com.typesafe.akka" %% "akka-actor-typed" % akkaVersion,
// "com.typesafe.akka" %% "akka-actor-testkit-typed" % akkaVersion % Test, // or should not use "% Test"?
),
)
.dependsOn(commonJava, ethUtils)
// (Java-based) Client connector (API library) to CherryGardener;
// allows external clients to use high-level CherryGardener interface
// to Ethereum blockchain.
lazy val cherryGardenerConnector = (project in file("java/cherrygardener_connector"))
.settings(
commonSettings,
commonJavaSettings,
commonAkkaMicroserviceSettings,
name := "cherrygardener_connector",
description := "UniCherryGarden: primary Java API to access the UniCherryGarden system from Java/Scala/Kotlin code",
libraryDependencies ++= Seq(
// Jackson used to parse JSON structures
"com.fasterxml.jackson.core" % "jackson-core" % jacksonCoreVersion,
"com.fasterxml.jackson.module" % "jackson-module-parameter-names" % jacksonCoreVersion,
"com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % jacksonCoreVersion,
"com.fasterxml.jackson.datatype" % "jackson-datatype-jdk8" % jacksonCoreVersion,
// Parse HOCON config files
"com.typesafe" % "config" % configLibVersion,
),
Compile / resourceGenerators += versionFileTask("cherrygardener_connector.properties").taskValue,
)
.dependsOn(
commonJava,
cherryGardenerInterop % "test->test;compile->compile"
)
lazy val cherryGardenerConnectorCLI = (project in file("java/cherrygardener_connector_cli"))
.settings(
commonSettings,
commonJavaSettings,
commonAkkaMicroserviceSettings,
commonJavaAppPackagingSettings,
name := "cherrygardener_connector_cli",
description := "UniCherryGarden: CLI tool to access the CherryGardener Connector features from command line",
libraryDependencies ++= Seq(
"commons-cli" % "commons-cli" % javaCommonsCLIVersion,
"ch.qos.logback" % "logback-classic" % logbackVersion,
// Parse HOCON config files - to read the CLI config file
"com.typesafe" % "config" % configLibVersion,
),
Compile / resourceGenerators += versionFileTask("cherrygardener_connector_cli.properties").taskValue,
mainClass in Compile := Some("com.myodov.unicherrygarden.cherrygardener.CherryGardenerCLI"),
)
.dependsOn(commonJava, cherryGardenerConnector)
.enablePlugins(JavaAppPackaging)
//
// Scala components
//
// a virtual “project” that contains all settings/data common for all Scala projects.
lazy val commonScala = (project in file("scala/common_scala"))
.settings(
commonSettings,
commonScalaSettings,
name := "common_scala",
description := "UniCherryGarden: the contents common for all Scala-language components",
)
// Common modules (for all Scala components).
lazy val api = (project in file("scala/api"))
.settings(
commonSettings,
commonScalaSettings,
name := "api",
description := "UniCherryGarden: internal Scala API commons",
libraryDependencies ++= Seq(
// Convenient Scala-like interface to SQL queries
"org.scalikejdbc" %% "scalikejdbc" % scalikeJdbcVersion,
"org.scalikejdbc" %% "scalikejdbc-test" % scalikeJdbcVersion % "test",
),
)
.dependsOn(commonScala, cherryGardenerInterop, ethUtils)
// Separate module to handle reading the HOCON conf files.
// Used from CLI launcher of CherryGarden components, and from "test" targets of other modules.
lazy val confreader = (project in file("scala/confreader"))
.settings(
commonSettings,
commonScalaSettings,
name := "confreader",
description := "UniCherryGarden: read the HOCON conf files by any UniCherryGarden components",
libraryDependencies ++= Seq(
// Parse HOCON config files
"com.typesafe" % "config" % configLibVersion,
),
)
.dependsOn(commonScala)
// Separate module to handle logging configuration.
// Used from CLI launcher, and from "test" targets of other modules.
lazy val logging = (project in file("scala/logging"))
.settings(
commonSettings,
commonScalaSettings,
name := "logging",
description := "UniCherryGarden: setup the logging subsystem by any UniCherryGarden components",
libraryDependencies ++= Seq(
// Default logging output
"ch.qos.logback" % "logback-classic" % logbackVersion,
),
)
.dependsOn(commonScala)
// RDBMS Storage
lazy val db_postgresql_storage = (project in file("scala/storages/db_postgresql_storage"))
.settings(
commonSettings,
commonScalaSettings,
name := "db_postgresql_storage",
description := "UniCherryGarden: PostgreSQL data storage available to UniCherryGarden server components",
libraryDependencies ++= Seq(
"org.postgresql" % "postgresql" % postgresqlVersion,
"org.flywaydb" % "flyway-core" % flywayDbVersion,
),
)
.dependsOn(commonScala, api)
// Interface to Web3 Ethereum nodes via RPC.
lazy val ethereum_connector = (project in file("scala/connectors/ethereum_connector"))
.settings(
commonSettings,
commonScalaSettings,
commonAkkaMicroserviceSettings, // for akka-http
name := "ethereum_connector",
description := "UniCherryGarden: connect to Web3 (geth) nodes from Scala code via JSON-RPC or GraphQL",
libraryDependencies ++= Seq(
// Web3/Ethereum node JSON-RPC client
"org.web3j" % "core" % web3jVersion,
"org.web3j" % "contracts" % web3jVersion,
// GraphQL client
"com.github.ghostdogpr" %% "caliban-client" % calibanVersion,
// Used by Caliban Client for outgoing queries
"com.softwaremill.sttp.client3" %% "core" % sttpClient3Version,
"com.softwaremill.sttp.client3" %% "akka-http-backend" % sttpClient3Version, // backend of choice
"com.typesafe.akka" %% "akka-http" % akkaHttpVersion, // needed for "akka-http-backend
"com.typesafe.akka" %% "akka-stream" % akkaVersion, // needed for akka-http explicitly
),
Compile / caliban / calibanSettings ++= Seq(
calibanSetting(file("scala/connectors/ethereum_connector/src/main/graphql/Geth.graphql"))(
cs => cs
.packageName("caliban")
.genView(true)
.imports(
"com.myodov.unicherrygarden.connectors.graphql.ScalarDecoder.long",
"com.myodov.unicherrygarden.connectors.graphql.ScalarDecoder.bigInt")
)
),
Compile / resourceGenerators += versionFileTask("unicherrygarden_ethereum_connector.properties").taskValue,
)
.dependsOn(commonScala, api, confreader % "test->compile", logging % "test->compile")
.enablePlugins(CalibanPlugin)
// CherryPicker: investigates the Ethereum blockchain and cherry-picks
// the information about the Ether/ERC20 transfers.
lazy val cherrypicker = (project in file("scala/cherrypicker"))
.settings(
commonSettings,
commonScalaSettings,
commonAkkaMicroserviceSettings,
name := "cherrypicker",
description := "UniCherryGarden: CherryPicker – the subsystem that keeps track " +
"of Ethereum blockchain data, stores it in the DB storage and “cherry-picks” the data on the fly " +
"(selective currencies, selective addresses to watch)",
Compile / resourceGenerators += versionFileTask("unicherrygarden_cherrypicker.properties").taskValue,
)
.dependsOn(commonScala, api, db_postgresql_storage, ethereum_connector)
// CherryPlanter: sends the transactions to the Ethereum blockchain.
lazy val cherryplanter = (project in file("scala/cherryplanter"))
.settings(
commonSettings,
commonScalaSettings,
commonAkkaMicroserviceSettings,
name := "cherryplanter",
description := "UniCherryGarden: CherryPlanter – the subsystem that registers the transactions " +
"in the Ethereum blockchain in the safest possible manner (retries; increasing the gas price" +
"if needed, maintaining the nonce values)",
Compile / resourceGenerators += versionFileTask("unicherrygarden_cherryplanter.properties").taskValue,
)
.dependsOn(commonScala, api, db_postgresql_storage, ethereum_connector)
// CherryGardener: provides high-level convenient front-end to the .
lazy val cherrygardener = (project in file("scala/cherrygardener"))
.settings(
commonSettings,
commonScalaSettings,
commonAkkaMicroserviceSettings,
name := "cherrygardener",
description := "UniCherryGarden: CherryGardener – the primary frontend to all other UniCherryGarden components",
Compile / resourceGenerators += versionFileTask("unicherrygarden_cherrygardener.properties").taskValue,
)
.dependsOn(
commonScala, api,
db_postgresql_storage, ethereum_connector,
cherrypicker, cherryplanter
)
// Launcher; launches the CherryPicker/CherryPlanter/CherryGardener daemons.
lazy val launcher = (project in file("scala/launcher"))
.settings(
commonSettings,
commonScalaSettings,
commonJavaAppPackagingSettings,
name := "launcher",
description := "UniCherryGarden: launcher CLI to execute the UniCherryGarden components",
resolvers += Resolver.bintrayRepo("serioussam", "oss"),
libraryDependencies ++= Seq(
// Parse command line arguments
"com.github.scopt" %% "scopt" % scoptVersion,
),
// Define the launch option for sbt-native-packager
// mainClass in Compile := Some("com.myodov.unicherrygarden.launcher.Launcher"),
// discoveredMainClasses in Compile := Seq(),
Compile / resourceGenerators += versionFileTask("unicherrygarden_launcher.properties").taskValue,
)
.dependsOn(
commonScala, api, confreader, db_postgresql_storage, logging,
cherrypicker, cherryplanter, cherrygardener
)
.enablePlugins(JavaAppPackaging)
// So the “main project” won’t build its own super-artifact; only the subprojects will do
publishArtifact := false