Skip to content

Commit c7f9444

Browse files
committed
wip
1 parent 996f260 commit c7f9444

File tree

10 files changed

+87
-88
lines changed

10 files changed

+87
-88
lines changed

src/main/scala/units/ELUpdater.scala

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ class ELUpdater(
112112
}
113113
}
114114

115-
private def callContract(fc: FUNCTION_CALL, invoker: KeyPair): JobResult[Unit] = {
115+
private def callContract(fc: FUNCTION_CALL, invoker: KeyPair): Result[Unit] = {
116116
val extraFee = if (blockchain.hasPaidVerifier(invoker.toAddress)) ScriptExtraFee else 0
117117

118118
val tx = InvokeScriptTransaction(
@@ -150,7 +150,7 @@ class ELUpdater(
150150
}
151151
}
152152

153-
private def rollbackDryRun(prevState: Working[ChainStatus], target: L2BlockLike, finalizedBlock: ContractBlock): JobResult[Working[ChainStatus]] = {
153+
private def rollbackDryRun(prevState: Working[ChainStatus], target: L2BlockLike, finalizedBlock: ContractBlock): Result[Working[ChainStatus]] = {
154154
val targetHash = target.hash
155155
for {
156156
lastEcBlock <- engineApiClient.getBlockByHash(targetHash).flatMap(_.toRight(s"Block $targetHash was not found"))
@@ -183,7 +183,7 @@ class ELUpdater(
183183
chainContractOptions: ChainContractOptions,
184184
prevEpochMinerRewardAddress: Option[EthAddress],
185185
willSimulateBlock: Boolean
186-
): JobResult[MiningData] = {
186+
): Result[MiningData] = {
187187
val startElWithdrawalIndex = lastElWithdrawalIndex + 1
188188
val startC2ETransferIndex = lastC2ETransferIndex + 1
189189

@@ -993,7 +993,7 @@ class ELUpdater(
993993
logger.debug(s"Unexpected state on sync: $other")
994994
})
995995

996-
private def validateRandao(block: EcBlock, epochNumber: Int): JobResult[Unit] =
996+
private def validateRandao(block: EcBlock, epochNumber: Int): Result[Unit] =
997997
blockchain.vrf(epochNumber) match {
998998
case None => s"VRF of $epochNumber epoch is empty".asLeft
999999
case Some(vrf) =>
@@ -1004,7 +1004,7 @@ class ELUpdater(
10041004
}
10051005

10061006
// Of a current epoch miner
1007-
private def validateBlockSignature(block: NetworkL2Block, epochInfo: Option[EpochInfo]): JobResult[Unit] = {
1007+
private def validateBlockSignature(block: NetworkL2Block, epochInfo: Option[EpochInfo]): Result[Unit] = {
10081008
epochInfo match {
10091009
case Some(epochMeta) =>
10101010
for {
@@ -1024,19 +1024,19 @@ class ELUpdater(
10241024
}
10251025
}
10261026

1027-
private def validateTimestamp(newNetworkBlock: NetworkL2Block, parentEcBlock: EcBlock): JobResult[Unit] = {
1027+
private def validateTimestamp(newNetworkBlock: NetworkL2Block, parentEcBlock: EcBlock): Result[Unit] = {
10281028
val minAppendTs = parentEcBlock.timestamp + config.blockDelay.toSeconds
10291029
Either.raiseUnless(newNetworkBlock.timestamp >= minAppendTs) {
10301030
s"timestamp (${newNetworkBlock.timestamp}) of appended block must be greater or equal $minAppendTs, Δ${minAppendTs - newNetworkBlock.timestamp}s"
10311031
}
10321032
}
10331033

1034-
private def preValidateBlock(networkBlock: NetworkL2Block, parentBlock: EcBlock, epochInfo: Option[EpochInfo]): JobResult[Unit] = for {
1034+
private def preValidateBlock(networkBlock: NetworkL2Block, parentBlock: EcBlock, epochInfo: Option[EpochInfo]): Result[Unit] = for {
10351035
_ <- validateTimestamp(networkBlock, parentBlock)
10361036
_ <- validateBlockSignature(networkBlock, epochInfo)
10371037
} yield ()
10381038

1039-
private def getAltChainReferenceBlock(nodeChainInfo: ChainInfo, lastContractBlock: ContractBlock): JobResult[ContractBlock] = {
1039+
private def getAltChainReferenceBlock(nodeChainInfo: ChainInfo, lastContractBlock: ContractBlock): Result[ContractBlock] = {
10401040
if (nodeChainInfo.isMain) {
10411041
for {
10421042
lastEpoch <- chainContractClient
@@ -1212,7 +1212,7 @@ class ELUpdater(
12121212
contractBlock: ContractBlock,
12131213
parentContractBlock: ContractBlock,
12141214
chainContractOptions: ChainContractOptions
1215-
): JobResult[Unit] = {
1215+
): Result[Unit] = {
12161216
val expectedAddedAssets =
12171217
if (
12181218
contractBlock.epoch < chainContractOptions.assetTransfersActivationEpoch ||
@@ -1287,7 +1287,7 @@ class ELUpdater(
12871287
getContractBlocksForValidation(startState).fold[Unit](
12881288
err => logger.error(s"Validation of applied blocks error: $err"),
12891289
blocksToValidate =>
1290-
blocksToValidate.foldLeft[JobResult[Working[ChainStatus]]](Right(startState)) {
1290+
blocksToValidate.foldLeft[Result[Working[ChainStatus]]](Right(startState)) {
12911291
case (Right(curState), block) =>
12921292
logger.trace(s"Trying to validate applied block ${block.hash}")
12931293
validateAppliedBlock(block.contractBlock, block.ecBlock, curState) match {
@@ -1315,7 +1315,7 @@ class ELUpdater(
13151315
fullValidationStatus: FullValidationStatus,
13161316
miningReward: Option[MiningReward],
13171317
options: ChainContractOptions
1318-
): JobResult[Option[WithdrawalIndex]] = for {
1318+
): Result[Option[WithdrawalIndex]] = for {
13191319
blockJsonE <- engineApiClient.getBlockByHashJson(ecBlock.hash, fullTransactionObjects = true)
13201320
blockJson <- blockJsonE.toRight(s"Can't find EC block ${ecBlock.hash} transactions")
13211321

@@ -1569,15 +1569,15 @@ class ELUpdater(
15691569
contractBlock: ContractBlock,
15701570
parentBlock: EcBlock,
15711571
prevState: Working[ChainStatus]
1572-
): JobResult[Working[ChainStatus]] = {
1572+
): Result[Working[ChainStatus]] = {
15731573
logger.trace(s"Trying to apply and do a full validation of block ${networkBlock.hash}")
15741574
for {
15751575
_ <- applyBlock(networkBlock, parentBlock, epochInfo = None) // epochInfo is empty, because we don't need to validate a block signature
15761576
updatedState <- validateAppliedBlock(contractBlock, networkBlock.toEcBlock, prevState)
15771577
} yield updatedState
15781578
}
15791579

1580-
private def applyBlock(networkBlock: NetworkL2Block, parentBlock: EcBlock, epochInfo: Option[EpochInfo]): JobResult[Unit] = for {
1580+
private def applyBlock(networkBlock: NetworkL2Block, parentBlock: EcBlock, epochInfo: Option[EpochInfo]): Result[Unit] = for {
15811581
_ <- preValidateBlock(networkBlock, parentBlock, epochInfo)
15821582
_ <- engineApiClient.newPayload(networkBlock.payload)
15831583
} yield ()
@@ -1588,7 +1588,7 @@ class ELUpdater(
15881588
prevState: Working[ChainStatus],
15891589
ecBlockLogs: Option[List[GetLogsResponseEntry]] = None,
15901590
updateState: Boolean = true
1591-
): JobResult[Working[ChainStatus]] = {
1591+
): Result[Working[ChainStatus]] = {
15921592
val validationResult =
15931593
for {
15941594
_ <- Either.raiseUnless(contractBlock.minerRewardL2Address == ecBlock.minerRewardL2Address) {
@@ -1673,9 +1673,9 @@ class ELUpdater(
16731673
}
16741674
}
16751675

1676-
private def getContractBlocksForValidation(curState: Working[ChainStatus]): JobResult[List[BlockForValidation]] = {
1676+
private def getContractBlocksForValidation(curState: Working[ChainStatus]): Result[List[BlockForValidation]] = {
16771677
@tailrec
1678-
def loop(curBlock: ContractBlock, acc: List[BlockForValidation]): JobResult[List[BlockForValidation]] = {
1678+
def loop(curBlock: ContractBlock, acc: List[BlockForValidation]): Result[List[BlockForValidation]] = {
16791679
if (curBlock.height <= curState.fullValidationStatus.lastValidatedBlock.height || curBlock.height <= curState.finalizedBlock.height) {
16801680
Right(acc)
16811681
} else {
@@ -1702,7 +1702,7 @@ class ELUpdater(
17021702
loop(curState.lastContractBlock, List.empty)
17031703
}
17041704

1705-
private def confirmBlock(block: L2BlockLike, finalizedBlock: L2BlockLike): JobResult[PayloadStatus] = {
1705+
private def confirmBlock(block: L2BlockLike, finalizedBlock: L2BlockLike): Result[PayloadStatus] = {
17061706
val finalizedBlockHash = if (finalizedBlock.height > block.height) block.hash else finalizedBlock.hash
17071707
engineApiClient.forkchoiceUpdated(block.hash, finalizedBlockHash)
17081708
}
@@ -1841,7 +1841,7 @@ object ELUpdater {
18411841

18421842
def registryKey(chainContract: Address): String = s"unit_${chainContract}_approved"
18431843

1844-
private def validateE2CTransfers(contractBlock: ContractBlock, ecBlockLogs: List[GetLogsResponseEntry]): JobResult[Unit] =
1844+
private def validateE2CTransfers(contractBlock: ContractBlock, ecBlockLogs: List[GetLogsResponseEntry]): Result[Unit] =
18451845
for {
18461846
elRootHash <- BridgeMerkleTree.getE2CTransfersRootHash(ecBlockLogs)
18471847
_ <- Either.raiseUnless(java.util.Arrays.equals(contractBlock.e2cTransfersRootHash, elRootHash)) { // elRootHash is the source of true

src/main/scala/units/client/contract/ContractFunction.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import com.wavesplatform.lang.v1.FunctionHeader
88
import com.wavesplatform.lang.v1.compiler.Terms.{CONST_BYTESTR, CONST_LONG, CONST_STRING, EVALUATED, FUNCTION_CALL}
99
import org.web3j.utils.Numeric.cleanHexPrefix
1010
import units.util.HexBytesConverter.toHexNoPrefix
11-
import units.{BlockHash, JobResult}
11+
import units.{BlockHash, Result}
1212

1313
abstract class ContractFunction(baseName: String, extraArgs: Either[CommonError, List[EVALUATED]]) {
1414
def reference: BlockHash
@@ -20,7 +20,7 @@ abstract class ContractFunction(baseName: String, extraArgs: Either[CommonError,
2020
transfersRootHash: Digest,
2121
lastC2ETransferIndex: Long,
2222
lastAssetRegistrySyncedIndex: Long
23-
): JobResult[FUNCTION_CALL] = (for {
23+
): Result[FUNCTION_CALL] = (for {
2424
hash <- CONST_STRING(cleanHexPrefix(blockHash.toString))
2525
ref <- CONST_STRING(cleanHexPrefix(reference.toString))
2626
ntrh <- CONST_STRING(toHexNoPrefix(transfersRootHash))

src/main/scala/units/client/engine/EngineApiClient.scala

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ import units.client.engine.model.Withdrawal.WithdrawalIndex
88
import units.el.DepositedTransaction
99
import units.eth.{EmptyL2Block, EthAddress}
1010
import units.util.BlockToPayloadMapper
11-
import units.{BlockHash, JobResult}
11+
import units.{BlockHash, Result}
1212

1313
import scala.annotation.tailrec
1414

1515
trait EngineApiClient {
16-
def forkchoiceUpdated(blockHash: BlockHash, finalizedBlockHash: BlockHash, requestId: Int = newRequestId): JobResult[PayloadStatus]
16+
def forkchoiceUpdated(blockHash: BlockHash, finalizedBlockHash: BlockHash, requestId: Int = newRequestId): Result[PayloadStatus]
1717

1818
def forkchoiceUpdatedWithPayload(
1919
lastBlockHash: BlockHash,
@@ -24,32 +24,32 @@ trait EngineApiClient {
2424
withdrawals: Vector[Withdrawal] = Vector.empty,
2525
transactions: Vector[String] = Vector.empty,
2626
requestId: Int = newRequestId
27-
): JobResult[PayloadId]
27+
): Result[PayloadId]
2828

29-
def getPayload(payloadId: PayloadId, requestId: Int = newRequestId): JobResult[JsObject]
29+
def getPayload(payloadId: PayloadId, requestId: Int = newRequestId): Result[JsObject]
3030

31-
def newPayload(payload: JsObject, requestId: Int = newRequestId): JobResult[Option[BlockHash]]
31+
def newPayload(payload: JsObject, requestId: Int = newRequestId): Result[Option[BlockHash]]
3232

33-
def getPayloadBodyByHash(hash: BlockHash, requestId: Int = newRequestId): JobResult[Option[JsObject]]
33+
def getPayloadBodyByHash(hash: BlockHash, requestId: Int = newRequestId): Result[Option[JsObject]]
3434

35-
def getBlockByNumber(number: BlockNumber, requestId: Int = newRequestId): JobResult[Option[EcBlock]]
35+
def getBlockByNumber(number: BlockNumber, requestId: Int = newRequestId): Result[Option[EcBlock]]
3636

37-
def getBlockByHash(hash: BlockHash, requestId: Int = newRequestId): JobResult[Option[EcBlock]]
37+
def getBlockByHash(hash: BlockHash, requestId: Int = newRequestId): Result[Option[EcBlock]]
3838

39-
def simulate(blockStateCalls: Seq[BlockStateCall], hash: BlockHash, requestId: Int = newRequestId): JobResult[Seq[JsObject]]
39+
def simulate(blockStateCalls: Seq[BlockStateCall], hash: BlockHash, requestId: Int = newRequestId): Result[Seq[JsObject]]
4040

41-
def getBlockByHashJson(hash: BlockHash, fullTransactionObjects: Boolean = false, requestId: Int = newRequestId): JobResult[Option[JsObject]]
41+
def getBlockByHashJson(hash: BlockHash, fullTransactionObjects: Boolean = false, requestId: Int = newRequestId): Result[Option[JsObject]]
4242

43-
def getLastExecutionBlock(requestId: Int = newRequestId): JobResult[EcBlock]
43+
def getLastExecutionBlock(requestId: Int = newRequestId): Result[EcBlock]
4444

45-
def blockExists(hash: BlockHash, requestId: Int = newRequestId): JobResult[Boolean]
45+
def blockExists(hash: BlockHash, requestId: Int = newRequestId): Result[Boolean]
4646

4747
def getLogs(
4848
hash: BlockHash,
4949
addresses: List[EthAddress] = Nil,
5050
topics: List[String] = Nil,
5151
requestId: Int = newRequestId
52-
): JobResult[List[GetLogsResponseEntry]]
52+
): Result[List[GetLogsResponseEntry]]
5353

5454
def onRetry(requestId: Int): Unit = {}
5555
}
@@ -65,7 +65,7 @@ object EngineApiClient {
6565
prevRandao: String,
6666
withdrawals: Seq[Withdrawal],
6767
depositedTransactions: Seq[DepositedTransaction]
68-
): JobResult[JsObject] = for {
68+
): Result[JsObject] = for {
6969
targetBlockOpt <- c.getBlockByHash(rollbackTargetBlockId)
7070
targetBlock <- targetBlockOpt.toRight(s"Target block $rollbackTargetBlockId is not in EC")
7171
simulatedBlockJson <- c.simulate(
@@ -75,7 +75,7 @@ object EngineApiClient {
7575
} yield BlockToPayloadMapper.toPayloadJson(simulatedBlockJson.head, Json.obj("transactions" -> Json.arr(), "withdrawals" -> withdrawals))
7676

7777
@tailrec
78-
def getLastWithdrawalIndex(hash: BlockHash): JobResult[WithdrawalIndex] =
78+
def getLastWithdrawalIndex(hash: BlockHash): Result[WithdrawalIndex] =
7979
c.getBlockByHash(hash) match {
8080
case Left(e) => Left(e)
8181
case Right(None) => Left(s"Can't find $hash block on EC during withdrawal search")

src/main/scala/units/client/engine/HttpEngineApiClient.scala

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ import units.client.engine.model.ForkchoiceUpdatedRequest.ForkChoiceAttributes
1111
import units.client.engine.model.PayloadStatus.{Syncing, Valid}
1212
import units.client.engine.model.{*, given}
1313
import units.eth.EthAddress
14-
import units.{BlockHash, JobResult}
14+
import units.{BlockHash, Result}
1515

1616
import scala.concurrent.duration.{DurationInt, FiniteDuration}
1717

1818
class HttpEngineApiClient(val config: JsonRpcClient.Config, val backend: SttpBackend[Identity, ?]) extends EngineApiClient with JsonRpcClient {
19-
def forkchoiceUpdated(blockHash: BlockHash, finalizedBlockHash: BlockHash, requestId: Int): JobResult[PayloadStatus] = {
19+
def forkchoiceUpdated(blockHash: BlockHash, finalizedBlockHash: BlockHash, requestId: Int): Result[PayloadStatus] = {
2020
sendEngineRequest[ForkchoiceUpdatedRequest, ForkChoiceUpdatedResponse](
2121
ForkchoiceUpdatedRequest(blockHash, finalizedBlockHash, None, requestId),
2222
BlockExecutionTimeout,
@@ -39,7 +39,7 @@ class HttpEngineApiClient(val config: JsonRpcClient.Config, val backend: SttpBac
3939
withdrawals: Vector[Withdrawal],
4040
transactions: Vector[String],
4141
requestId: Int
42-
): JobResult[PayloadId] = {
42+
): Result[PayloadId] = {
4343
sendEngineRequest[ForkchoiceUpdatedRequest, ForkChoiceUpdatedResponse](
4444
ForkchoiceUpdatedRequest(
4545
lastBlockHash,
@@ -61,13 +61,13 @@ class HttpEngineApiClient(val config: JsonRpcClient.Config, val backend: SttpBac
6161
}
6262
}
6363

64-
def getPayload(payloadId: PayloadId, requestId: Int): JobResult[JsObject] = {
64+
def getPayload(payloadId: PayloadId, requestId: Int): Result[JsObject] = {
6565
sendEngineRequest[GetPayloadRequest, GetPayloadResponse](GetPayloadRequest(payloadId, requestId), NonBlockExecutionTimeout, requestId).map(
6666
_.executionPayload - "withdrawalsRoot" - "depositRequests"
6767
)
6868
}
6969

70-
def newPayload(payload: JsObject, requestId: Int): JobResult[Option[BlockHash]] = {
70+
def newPayload(payload: JsObject, requestId: Int): Result[Option[BlockHash]] = {
7171
sendEngineRequest[NewPayloadRequest, PayloadState](NewPayloadRequest(payload, requestId), BlockExecutionTimeout, requestId).flatMap {
7272
case PayloadState(_, _, Some(validationError)) => Left(s"Payload validation error: $validationError")
7373
case PayloadState(Valid, Some(latestValidHash), _) => Right(Some(latestValidHash))
@@ -77,53 +77,53 @@ class HttpEngineApiClient(val config: JsonRpcClient.Config, val backend: SttpBac
7777
}
7878
}
7979

80-
def getPayloadBodyByHash(hash: BlockHash, requestId: Int): JobResult[Option[JsObject]] = {
80+
def getPayloadBodyByHash(hash: BlockHash, requestId: Int): Result[Option[JsObject]] = {
8181
sendEngineRequest[GetPayloadBodyByHash, JsArray](GetPayloadBodyByHash(hash, requestId), NonBlockExecutionTimeout, requestId)
8282
.map(_.value.headOption.flatMap(_.asOpt[JsObject]))
8383
}
8484

85-
def getBlockByNumber(number: BlockNumber, requestId: Int): JobResult[Option[EcBlock]] = {
85+
def getBlockByNumber(number: BlockNumber, requestId: Int): Result[Option[EcBlock]] = {
8686
for {
8787
json <- getBlockByNumberJson(number.str, requestId)
8888
blockMeta <- json.traverse(parseJson[EcBlock](_))
8989
} yield blockMeta
9090
}
9191

92-
def getBlockByHash(hash: BlockHash, requestId: Int): JobResult[Option[EcBlock]] = {
92+
def getBlockByHash(hash: BlockHash, requestId: Int): Result[Option[EcBlock]] = {
9393
sendRequest[GetBlockByHashRequest, EcBlock](
9494
GetBlockByHashRequest(hash, fullTransactionObjects = false, requestId),
9595
NonBlockExecutionTimeout,
9696
requestId
9797
).leftMap(err => s"Error getting block by hash $hash: $err")
9898
}
9999

100-
def getBlockByHashJson(hash: BlockHash, fullTransactionObjects: Boolean, requestId: Int): JobResult[Option[JsObject]] = {
100+
def getBlockByHashJson(hash: BlockHash, fullTransactionObjects: Boolean, requestId: Int): Result[Option[JsObject]] = {
101101
sendRequest[GetBlockByHashRequest, JsObject](
102102
GetBlockByHashRequest(hash, fullTransactionObjects, requestId),
103103
NonBlockExecutionTimeout,
104104
requestId
105105
).leftMap(err => s"Error getting block json by hash $hash: $err")
106106
}
107107

108-
def getLastExecutionBlock(requestId: Int): JobResult[EcBlock] = for {
108+
def getLastExecutionBlock(requestId: Int): Result[EcBlock] = for {
109109
lastEcBlockOpt <- getBlockByNumber(BlockNumber.Latest, requestId)
110110
lastEcBlock <- Either.fromOption(lastEcBlockOpt, "Impossible: EC doesn't have blocks")
111111
} yield lastEcBlock
112112

113-
def blockExists(hash: BlockHash, requestId: Int): JobResult[Boolean] =
113+
def blockExists(hash: BlockHash, requestId: Int): Result[Boolean] =
114114
getBlockByHash(hash, requestId).map(_.isDefined)
115115

116-
override def simulate(blockStateCalls: Seq[BlockStateCall], hash: BlockHash, requestId: Int): JobResult[Seq[JsObject]] =
116+
override def simulate(blockStateCalls: Seq[BlockStateCall], hash: BlockHash, requestId: Int): Result[Seq[JsObject]] =
117117
sendRequest[SimulateRequest, Seq[JsObject]](SimulateRequest(blockStateCalls, hash, requestId), NonBlockExecutionTimeout, requestId)
118118
.flatMap(_.toRight("Simulated block was empty"))
119119
.leftMap(err => s"Error simulating block: $err")
120120

121-
private def getBlockByNumberJson(number: String, requestId: Int): JobResult[Option[JsObject]] = {
121+
private def getBlockByNumberJson(number: String, requestId: Int): Result[Option[JsObject]] = {
122122
sendRequest[GetBlockByNumberRequest, JsObject](GetBlockByNumberRequest(number, requestId), NonBlockExecutionTimeout, requestId)
123123
.leftMap(err => s"Error getting block by number $number: $err")
124124
}
125125

126-
override def getLogs(hash: BlockHash, addresses: List[EthAddress], topics: List[String], requestId: Int): JobResult[List[GetLogsResponseEntry]] =
126+
override def getLogs(hash: BlockHash, addresses: List[EthAddress], topics: List[String], requestId: Int): Result[List[GetLogsResponseEntry]] =
127127
sendRequest[GetLogsRequest, List[GetLogsResponseEntry]](
128128
GetLogsRequest(hash, addresses, topics, requestId),
129129
NonBlockExecutionTimeout,
@@ -132,7 +132,7 @@ class HttpEngineApiClient(val config: JsonRpcClient.Config, val backend: SttpBac
132132
.leftMap(err => s"Error getting block logs by hash $hash: $err")
133133
.map(_.getOrElse(List.empty))
134134

135-
private def sendEngineRequest[A: Writes, B: Reads](request: A, timeout: FiniteDuration, requestId: Int): JobResult[B] = {
135+
private def sendEngineRequest[A: Writes, B: Reads](request: A, timeout: FiniteDuration, requestId: Int): Result[B] = {
136136
sendRequest(request, timeout, requestId) match {
137137
case Right(response) => response.toRight(s"Unexpected engine API empty response")
138138
case Left(err) => Left(s"Engine API request error: $err")

0 commit comments

Comments
 (0)