Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
wip

wip

wip
  • Loading branch information
Bromel777 committed Apr 1, 2022
1 parent a71cc63 commit 4ba0b56
Show file tree
Hide file tree
Showing 25 changed files with 412 additions and 32 deletions.
15 changes: 13 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,14 @@ lazy val core =
Libraries.tapirCirce,
Libraries.derevoCirce,
Libraries.enumeratum,
Libraries.enumeratumCirce
Libraries.enumeratumCirce,
Libraries.sttpClient,
Libraries.sttpBackendCats,
Libraries.derevoPureconfig,
Libraries.sttpBackendMonix,
Libraries.zioInterop,
Libraries.sttpCirce,
Libraries.sttpSlf4j
)
)

Expand All @@ -72,7 +79,11 @@ lazy val api =
Libraries.tapirDocs,
Libraries.tapirOpenApi,
Libraries.derevoPureconfig,
Libraries.pureconfig
Libraries.pureconfig,
Libraries.sttpClient,
Libraries.sttpBackendCats,
Libraries.sttpCirce,
Libraries.sttpSlf4j
)
)
.dependsOn(core)
4 changes: 2 additions & 2 deletions config/explorer-api.conf
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
http {
host = "0.0.0.0"
port = 8081
host = "127.0.0.1"
port = 8084
}

pg {
Expand Down
13 changes: 11 additions & 2 deletions modules/api/src/main/resources/base.conf
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
http {
host = "127.0.0.1"
host = "0.0.0.0"
port = 8084
}

pg {
url = "jdbc:postgresql://1.1.1.1:5432/cexplorer"
url = "url"
user = "user"
pass = "pass"
connection-timeout = 10s
Expand All @@ -15,4 +15,13 @@ pg {
requests {
max-limit-transactions = 500
max-limit-outputs = 500
}

web-socket-cfg {
uri = "ws://ogmios"
}

timeouts {
connect-timeout = 10s
timeout = 10s
}
4 changes: 2 additions & 2 deletions modules/api/src/main/resources/logback.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
</appender>

<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/var/log/cardano-explorer-backend/explorer-api.log</file>
<file>/Users/aleksandr/IdeaProjects/cardano-explorer-backend-scala/logs/explorer-api.log</file>
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="tofu.logging.ELKLayout"/>
</encoder>

<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>/var/log/cardano-explorer-backend/explorer-api.%d{yyyy-MM-dd}.%i.log
<fileNamePattern>/Users/aleksandr/IdeaProjects/cardano-explorer-backend-scala/logs/explorer-api.%d{yyyy-MM-dd}.%i.log
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,45 @@
package io.ergolabs.cardano.explorer.api

import cats.arrow.FunctionK
import cats.data.ReaderT
import cats.effect.{Blocker, Resource}
import cats.syntax.option._
import cats.~>
import io.ergolabs.cardano.explorer.api
import io.ergolabs.cardano.explorer.api.App.{InitF, RunF}
import io.ergolabs.cardano.explorer.api.configs.ConfigBundle
import io.ergolabs.cardano.explorer.api.v1.services.{Assets, Blocks, Outputs, Transactions, NetworkParamsService}
import sttp.capabilities.WebSockets
import io.ergolabs.cardano.explorer.api.v1.services.{Assets, Blocks, NetworkParamsService, Outputs, Transactions}
import io.ergolabs.cardano.explorer.core.db.repositories.RepoBundle
import io.ergolabs.cardano.explorer.core.gateway.WebSocketGateway
import io.ergolabs.cardano.explorer.core.ogmios.service.OgmiosService
import org.http4s.server.Server
import sttp.client3.SttpBackend
import sttp.tapir.server.http4s.Http4sServerOptions
import tofu.doobie.log.EmbeddableLogHandler
import tofu.doobie.transactor.Txr
import tofu.lift.{IsoK, Unlift}
import zio._
import zio.interop.monix._
import tofu.logging.Logs
import tofu.logging.derivation.loggable.generate
import zio.interop.catz._
import zio.{ExitCode, URIO, ZIO}
import monix.eval
import zio.{ExitCode, RIO, URIO, ZIO}

object App extends EnvApp[AppContext] {

implicit val serverOptions: Http4sServerOptions[RunF, RunF] = Http4sServerOptions.default[RunF, RunF]
//todo: only for debug
implicit def fromTask2I: eval.Task ~> InitF = new FunctionK[eval.Task, InitF]{
override def apply[A](fa: eval.Task[A]): InitF[A] = ZIO.fromMonixTask(fa)
}
implicit def fromTask2F: eval.Task ~> RunF = new FunctionK[eval.Task, RunF]{
override def apply[A](fa: eval.Task[A]): RunF[A] = new ReaderT[InitF, AppContext, A](ctx => ZIO.fromMonixTask(fa))
}
def fromF2Task(unlift: Unlift[RunF, InitF]): RunF ~> eval.Task = new FunctionK[RunF, eval.Task]{
override def apply[A](fa: RunF[A]): eval.Task[A] = Runtime.default.unsafeRun(unlift.lift(fa).toMonixTask)
}

def run(args: List[String]): URIO[zio.ZEnv, ExitCode] =
init(args.headOption).use(_ => ZIO.never).orDie
Expand All @@ -27,12 +50,16 @@ object App extends EnvApp[AppContext] {
configs <- Resource.eval(ConfigBundle.load[InitF](configPathOpt, blocker))
ctx = AppContext.init(configs)
implicit0(ul: Unlift[RunF, InitF]) = Unlift.byIso(IsoK.byFunK(wr.runContextK(ctx))(wr.liftF))
implicit0(rF: FunctionK[RunF, eval.Task]) = fromF2Task(ul)
trans <- PostgresTransactor.make[InitF]("explorer-db-pool", configs.pg)
implicit0(xa: Txr.Continuational[RunF]) = Txr.continuational[RunF](trans.mapK(wr.liftF))
implicit0(elh: EmbeddableLogHandler[xa.DB]) <-
Resource.eval(doobieLogging.makeEmbeddableHandler[InitF, RunF, xa.DB]("explorer-db-logging"))
implicit0(logsDb: Logs[InitF, xa.DB]) = Logs.sync[InitF, xa.DB]
implicit0(txReps: RepoBundle[xa.DB]) <- Resource.eval(RepoBundle.make[InitF, xa.DB])
implicit0(sttpBackF: SttpBackend[RunF, WebSockets]) <- makeSttpBackend[InitF, RunF](ctx, none)
implicit0(gateway: WebSocketGateway[RunF]) <- Resource.eval(WebSocketGateway.make[InitF, RunF](configs.webSocketCfg))
implicit0(ogmios: OgmiosService[RunF]) <- Resource.eval(OgmiosService.make[InitF, RunF])
implicit0(m: NetworkParamsService[RunF]) = NetworkParamsService.make[RunF, xa.DB]
implicit0(txs: Transactions[RunF]) = Transactions.make[RunF, xa.DB]
implicit0(outs: Outputs[RunF]) = Outputs.make[RunF, xa.DB]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package io.ergolabs.cardano.explorer.api.configs

import derevo.derive
import derevo.pureconfig.pureconfigReader
import tofu.logging.derivation.loggable

import scala.concurrent.duration.FiniteDuration

@derive(pureconfigReader, loggable)
final case class ClientTimeouts(connectTimeout: FiniteDuration, timeout: FiniteDuration)
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,18 @@ package io.ergolabs.cardano.explorer.api.configs

import derevo.derive
import derevo.pureconfig.pureconfigReader
import io.ergolabs.cardano.explorer.core.gateway.WebSocketSettings
import tofu.logging.derivation.loggable
import tofu.optics.macros.{promote, ClassyOptics}

@derive(loggable, pureconfigReader)
@ClassyOptics
final case class ConfigBundle(@promote http: HttpConfig, @promote pg: PgConfig, @promote requests: RequestConfig)
final case class ConfigBundle(
@promote http: HttpConfig,
@promote pg: PgConfig,
@promote requests: RequestConfig,
@promote webSocketCfg: WebSocketSettings,
@promote timeouts: ClientTimeouts
)

object ConfigBundle extends ConfigBundleCompanion[ConfigBundle]
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package io.ergolabs.cardano.explorer

import cats.{~>, Applicative, Defer}
import cats.effect.{Concurrent, ContextShift, Resource}
import io.ergolabs.cardano.explorer.api.configs.ClientTimeouts
import monix.eval.Task
import org.asynchttpclient.DefaultAsyncHttpClientConfig
import sttp.capabilities.WebSockets
import sttp.client3._
import sttp.client3.SttpBackend
import sttp.client3.asynchttpclient.monix.AsyncHttpClientMonixBackend
import sttp.client3.impl.cats.implicits._
import sttp.client3.logging.slf4j.Slf4jLoggingBackend
import tofu.WithRun

package object api {

def makeSttpBackend[I[_]: Defer: Applicative, F[_]: Concurrent: ContextShift](
ctx: AppContext,
httpClientTimeouts: Option[ClientTimeouts] = None
)(implicit
WR: WithRun[F, I, AppContext],
fromTaskI: Task ~> I,
fromTaskF: Task ~> F,
toTaskF: F ~> Task
): Resource[I, SttpBackend[F, WebSockets]] =
AsyncHttpClientMonixBackend.resource().mapK(fromTaskI).map(_.mapK(fromTaskF, toTaskF))

def setupTimeouts(builder: DefaultAsyncHttpClientConfig.Builder, config: ClientTimeouts) = {
import config._
builder
.setConnectTimeout(connectTimeout.toMillis.toInt)
.setReadTimeout(timeout.toMillis.toInt)
.setRequestTimeout(
timeout.toMillis.toInt + connectTimeout.toMillis.toInt * 2
)
}

def wrapWithLogs[F[_], S](delegate: SttpBackend[F, S]): SttpBackend[F, S] =
Slf4jLoggingBackend(delegate, logRequestBody = true, logResponseBody = true)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import derevo.circe.magnolia.{decoder, encoder}
import derevo.derive
import io.circe.Json
import io.ergolabs.cardano.explorer.api.v1.instances._
import io.ergolabs.cardano.explorer.core.ogmios.models.EraInfo
import io.ergolabs.cardano.explorer.core.ogmios.models.OgmiosResponseBody.EraSummaries
import io.ergolabs.cardano.explorer.core.types.{Bytea, PoolId}
import sttp.tapir.Schema

Expand All @@ -12,7 +14,8 @@ final case class EnvParams(
pparams: ProtocolParams,
network: NetworkName,
sysstart: SystemStart,
collateralPercent: Option[Int]
collateralPercent: Option[Int],
eraHistory: List[EraInfo]
)

object EnvParams {
Expand All @@ -24,4 +27,5 @@ object EnvParams {
.modify(_.network)(_.description("Network Id"))
.modify(_.sysstart)(_.description("System start"))
.modify(_.collateralPercent)(_.description("Collateral Percent"))
.modify(_.eraHistory)(_.description("Era history"))
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package io.ergolabs.cardano.explorer.api.v1.routes

import cats.effect.{Concurrent, ContextShift, Timer}
import cats.effect.{Concurrent, ContextShift, Sync, Timer}
import cats.syntax.semigroupk._
import io.ergolabs.cardano.explorer.api.configs.RequestConfig
import io.ergolabs.cardano.explorer.api.v1.endpoints.OutputsEndpoints
import io.ergolabs.cardano.explorer.api.v1.services.Outputs
import io.ergolabs.cardano.explorer.api.v1.syntax._
import tofu.syntax.monadic._
import org.http4s.HttpRoutes
import sttp.tapir.server.http4s.{Http4sServerInterpreter, Http4sServerOptions}

Expand Down Expand Up @@ -42,7 +43,10 @@ final class OutputsRoutes[F[_]: Concurrent: ContextShift: Timer](requestConfig:

def getUnspentByAddrR: HttpRoutes[F] =
interpreter.toRoutes(endpoints.getUnspentByAddr) { case (addr, paging) =>
service.getUnspentByAddr(addr, paging).eject
for {
test <- service.getUnspentByAddr(addr, paging)
res <- service.getUnspentByAddr(addr, paging).eject
} yield res
}

def getUnspentByPCredR: HttpRoutes[F] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import io.ergolabs.cardano.explorer.core.types.PoolId
import tofu.Throws
import tofu.syntax.raise._
import io.circe.parser
import io.ergolabs.cardano.explorer.core.ogmios.service.OgmiosService

trait NetworkParamsService[F[_]] {

Expand All @@ -21,29 +22,34 @@ trait NetworkParamsService[F[_]] {

object NetworkParamsService {

def make[F[_], D[_]: Monad: LiftConnectionIO: Throws](implicit
def make[F[_]: Monad, D[_]: Monad: LiftConnectionIO: Throws](implicit
txr: Txr[F, D],
repos: RepoBundle[D]
): NetworkParamsService[F] = new Live[F, D](txr, repos)
repos: RepoBundle[D],
ogmios: OgmiosService[F]
): NetworkParamsService[F] = new Live[F, D](txr, repos, ogmios)

final class Live[F[_], D[_]: Monad: Throws](txr: Txr[F, D], repos: RepoBundle[D]) extends NetworkParamsService[F] {
final class Live[F[_]: Monad, D[_]: Monad: Throws](txr: Txr[F, D], repos: RepoBundle[D], ogmios: OgmiosService[F])
extends NetworkParamsService[F] {

def getNetworkParams: F[EnvParams] =
(for {
meta <- repos.network.getMeta
epochParams <- repos.network.getLastEpochParams
costModel <- repos.network.getCostModel(epochParams.costModelId)
parsedCm <- parser.parse(costModel).toRaise
transformed <- parsedCm.as[Map[String, Map[String, Int]]].toRaise
((for {
meta <- repos.network.getMeta
epochParams <- repos.network.getLastEpochParams
costModel <- repos.network.getCostModel(epochParams.costModelId)
parsedCm <- parser.parse(costModel).toRaise[D]
transformed <- parsedCm.as[Map[String, Map[String, Int]]].toRaise[D]
cmCorrectFormat = transformed.map { case (k, v) => "PlutusScriptV1" -> v }
} yield
EnvParams(
ProtocolParams.fromEpochParams(epochParams, cmCorrectFormat),
NetworkName(meta.networkName),
SystemStart.fromExplorer(meta.startTime),
epochParams.collateralPercent
} yield (meta, epochParams, cmCorrectFormat)) ||> txr.trans).flatMap {
case (meta, epochParams, cmCorrectFormat) =>
ogmios.getEraSummaries.map(eraSums =>
EnvParams(
ProtocolParams.fromEpochParams(epochParams, cmCorrectFormat),
NetworkName(meta.networkName),
SystemStart.fromExplorer(meta.startTime),
epochParams.collateralPercent,
eraSums.infoList
)
)
) ||> txr.trans

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package io.ergolabs.cardano.explorer.api.v1.services

import cats.Monad
import cats.data.{NonEmptyList, OptionT}
import cats.effect.Sync
import io.ergolabs.cardano.explorer.api.v1.models._
import io.ergolabs.cardano.explorer.core.db.models.{Output => DbOutput}
import io.ergolabs.cardano.explorer.core.db.repositories.RepoBundle
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import sttp.tapir.Schema
sealed abstract class ScriptPurpose(override val entryName: String) extends EnumEntry

object ScriptPurpose extends Enum[ScriptPurpose] {

val values = findValues

case object Spend extends ScriptPurpose("spend")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.ergolabs.cardano.explorer.core.gateway

sealed trait GatewayError extends Throwable

object GatewayError {
final case class UnexpectedError(description: String) extends GatewayError
final case class GatewayResponseDecodingFailure(description: String) extends GatewayError
}
Loading

0 comments on commit 4ba0b56

Please sign in to comment.