diff --git a/.github/workflows/check-pr.yaml b/.github/workflows/check-pr.yaml index 14e6d64e3bc..b14e3f1e00d 100644 --- a/.github/workflows/check-pr.yaml +++ b/.github/workflows/check-pr.yaml @@ -27,7 +27,14 @@ jobs: path: ~/.cache/coursier key: coursier-cache - name: Check PR - run: sbt --mem 6144 --batch checkPR + run: sbt --mem 6144 --batch ";checkPR;completeQaseRun" + env: + QASE_ENABLE: true + QASE_RUN_NAME: checkPR + QASE_RUN_ID: 1 + QASE_PROJECT_CODE: PR + QASE_API_TOKEN: ${{ secrets.QASE_API_TOKEN }} + CHECKPR_RUN_ID: ${{ github.run_id }} - uses: dorny/paths-filter@v2 id: filter with: diff --git a/.github/workflows/publish-docker-node.yaml b/.github/workflows/publish-docker-node.yaml index 380bc4249c8..804c39d8b5c 100644 --- a/.github/workflows/publish-docker-node.yaml +++ b/.github/workflows/publish-docker-node.yaml @@ -64,12 +64,24 @@ jobs: type=ref,event=tag type=raw,value=latest,enable=${{ github.event.release.prerelease == false }} + - name: Extract Docker RIDE runner metadata + id: meta-ride-runner + uses: docker/metadata-action@v4 + with: + images: wavesplatform/ride-runner + flavor: | + latest=false + tags: | + type=match,pattern=v(.*),group=1 + type=raw,value=latest,enable=${{ github.event.release.prerelease == false }} + - name: Build and push Docker public image id: build-and-push-public uses: docker/build-push-action@v3 with: context: ./docker push: true + pull: true tags: ${{ steps.meta-public.outputs.tags }} - name: Build and push Docker private image @@ -78,6 +90,16 @@ jobs: with: context: ./docker/private push: true + pull: true tags: ${{ steps.meta-private.outputs.tags }} build-args: | NODE_TAG=${{ steps.meta-public.outputs.version }} + + - name: Build and push Docker RIDE runner image + id: build-and-push-ride-runner + uses: docker/build-push-action@v3 + with: + context: ./ride-runner/docker + push: true + pull: true + tags: ${{ steps.meta-ride-runner.outputs.tags }} diff --git a/.github/workflows/publish-node-sbt-builder.yml b/.github/workflows/publish-node-sbt-builder.yml index 45608e87fbb..91e3a2ab44e 100644 --- a/.github/workflows/publish-node-sbt-builder.yml +++ b/.github/workflows/publish-node-sbt-builder.yml @@ -23,6 +23,7 @@ jobs: context: ./docker file: ./docker/node-sbt-builder.Dockerfile push: true + pull: true tags: wavesplatform/node-sbt-builder:${{ steps.extract-versions.outputs.waves-version }} build-args: | WAVES_VERSION=${{ steps.extract-versions.outputs.waves-version }} diff --git a/.gitignore b/.gitignore index 2637a704c84..690d21a5dc9 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,7 @@ docker/temp package !src/package +!ride-runner/src/package native !lang/jvm/lib/*.jar diff --git a/benchmark/src/main/scala/com/wavesplatform/state/DBState.scala b/benchmark/src/main/scala/com/wavesplatform/state/DBState.scala index fcdda8b024e..7f39682c733 100644 --- a/benchmark/src/main/scala/com/wavesplatform/state/DBState.scala +++ b/benchmark/src/main/scala/com/wavesplatform/state/DBState.scala @@ -1,7 +1,5 @@ package com.wavesplatform.state -import java.io.File - import com.wavesplatform.Application import com.wavesplatform.account.AddressScheme import com.wavesplatform.common.state.ByteStr @@ -13,6 +11,8 @@ import com.wavesplatform.utils.ScorexLogging import monix.eval.Coeval import org.openjdk.jmh.annotations.{Param, Scope, State, TearDown} +import java.io.File + @State(Scope.Benchmark) abstract class DBState extends ScorexLogging { @Param(Array("waves.conf")) @@ -32,7 +32,7 @@ abstract class DBState extends ScorexLogging { AddressScheme.current = new AddressScheme { override val chainId: Byte = 'W' } - lazy val environment = new WavesEnvironment( + lazy val environment = WavesEnvironment( AddressScheme.current.chainId, Coeval.raiseError(new NotImplementedError("`tx` is not implemented")), Coeval(rocksDBWriter.height), diff --git a/benchmark/src/test/scala/com/wavesplatform/lang/v1/DataFuncs.scala b/benchmark/src/test/scala/com/wavesplatform/lang/v1/DataFuncs.scala index 9edcfc50fa4..ba963912aee 100644 --- a/benchmark/src/test/scala/com/wavesplatform/lang/v1/DataFuncs.scala +++ b/benchmark/src/test/scala/com/wavesplatform/lang/v1/DataFuncs.scala @@ -1,31 +1,69 @@ package com.wavesplatform.lang.v1 -import java.util.concurrent.TimeUnit - -import com.wavesplatform.common.utils._ -import com.wavesplatform.lang.v1.DataFuncs._ +import com.esaulpaugh.headlong.util.FastHex +import com.sun.org.apache.xerces.internal.impl.dv.util.HexBin +import com.wavesplatform.common.utils.* +import com.wavesplatform.lang.v1.DataFuncs.* import com.wavesplatform.lang.v1.EnvironmentFunctionsBenchmark.randomBytes -import org.openjdk.jmh.annotations._ +import org.openjdk.jmh.annotations.* import org.openjdk.jmh.infra.Blackhole +import java.util.concurrent.TimeUnit + @OutputTimeUnit(TimeUnit.MICROSECONDS) @BenchmarkMode(Array(Mode.AverageTime)) @Threads(1) @Fork(1) -@Warmup(iterations = 30) -@Measurement(iterations = 30) +@Warmup(iterations = 10, time = 1) +@Measurement(iterations = 10, time = 1) class DataFuncs { @Benchmark def decode64_35Kb(st: StrSt35K, bh: Blackhole): Unit = bh.consume(Base64.decode(st.message)) + @Benchmark + def decode16_32kb_bcprov(st: StrSt32K, bh: Blackhole): Unit = + bh.consume(org.bouncycastle.util.encoders.Hex.decode(st.message)) + + @Benchmark + def decode16_32kb_guava(st: StrSt32K, bh: Blackhole): Unit = + bh.consume(com.google.common.io.BaseEncoding.base16.decode(st.message)) + + @Benchmark + def decode16_32kb_commons_codec(st: StrSt32K, bh: Blackhole): Unit = + bh.consume(org.apache.commons.codec.binary.Hex.decodeHex(st.message)) + + @Benchmark + def decode16_32kb_web3j(st: StrSt32K, bh: Blackhole): Unit = + bh.consume(org.web3j.utils.Numeric.hexStringToByteArray(st.message)) + + @Benchmark + def decode16_32kb_headlong(st: StrSt32K, bh: Blackhole): Unit = + bh.consume(FastHex.decode(st.message)) + + @Benchmark + def decode16_32kb_jdk_hexbin(st: StrSt105K, bh: Blackhole): Unit = + bh.consume(HexBin.decode(st.message)) + @Benchmark def decode64_70Kb(st: StrSt70K, bh: Blackhole): Unit = bh.consume(Base64.decode(st.message)) @Benchmark - def decode64_105Kb(st: StrSt105K, bh: Blackhole): Unit = - bh.consume(Base64.decode(st.message)) + def decode64_105Kb_jdk(st: StrSt105K, bh: Blackhole): Unit = + bh.consume(java.util.Base64.getDecoder.decode(st.message)) + + @Benchmark + def decode64_105Kb_bcprov(st: StrSt105K, bh: Blackhole): Unit = + bh.consume(org.bouncycastle.util.encoders.Base64.decode(st.message)) + + @Benchmark + def decode64_105Kb_guava(st: StrSt105K, bh: Blackhole): Unit = + bh.consume(com.google.common.io.BaseEncoding.base64().decode(st.message)) + + @Benchmark + def decode64_105Kb_commons_codec(st: StrSt105K, bh: Blackhole): Unit = + bh.consume(org.apache.commons.codec.binary.Base64.decodeBase64(st.message)) @Benchmark def decode64_140Kb(st: StrSt140K, bh: Blackhole): Unit = @@ -95,7 +133,6 @@ class DataFuncs { def concatr_175Kb(st: StrSt175K, bh: Blackhole): Unit = bh.consume("q" ++ st.message) - @Benchmark def decode58_16b(st: StrSt16b, bh: Blackhole): Unit = bh.consume(Base58.decode(st.message)) @@ -144,10 +181,11 @@ class DataFuncs { def encode58_896b(st: StrSt896b, bh: Blackhole): Unit = bh.consume(Base58.encode(st.bmessage)) - } object DataFuncs { + @State(Scope.Benchmark) + class StrSt8K extends StrSt(8) @State(Scope.Benchmark) class StrSt35K extends StrSt(35) @State(Scope.Benchmark) @@ -155,12 +193,14 @@ object DataFuncs { @State(Scope.Benchmark) class StrSt105K extends StrSt(105) @State(Scope.Benchmark) + class StrSt32K extends StrSt(32) + @State(Scope.Benchmark) class StrSt140K extends StrSt(140) @State(Scope.Benchmark) class StrSt175K extends StrSt(175) class StrSt(size: Int) { - val message = "B" * (size * 1024) + val message = "B" * (size * 1024) } @State(Scope.Benchmark) @@ -177,8 +217,8 @@ object DataFuncs { class StrSt896b extends StrStS(896) class StrStS(size: Int) { - val message = "B" * size - val bmessage = randomBytes(size) + val message = "B" * size + val bmessage = randomBytes(size) } @State(Scope.Benchmark) @@ -193,6 +233,6 @@ object DataFuncs { class BinSt130K extends BinSt(130) class BinSt(size: Int) { - val message = randomBytes(size * 1024) + val message = randomBytes(size * 1024) } } diff --git a/benchmark/src/test/scala/com/wavesplatform/lang/v1/EnvironmentFunctionsBenchmark.scala b/benchmark/src/test/scala/com/wavesplatform/lang/v1/EnvironmentFunctionsBenchmark.scala index 4857c4d4c81..849d2a07771 100644 --- a/benchmark/src/test/scala/com/wavesplatform/lang/v1/EnvironmentFunctionsBenchmark.scala +++ b/benchmark/src/test/scala/com/wavesplatform/lang/v1/EnvironmentFunctionsBenchmark.scala @@ -34,8 +34,8 @@ import scala.util.Random @BenchmarkMode(Array(Mode.AverageTime)) @Threads(1) @Fork(1) -@Warmup(iterations = 10) -@Measurement(iterations = 10) +@Warmup(iterations = 10, time = 1) +@Measurement(iterations = 10, time = 1) class EnvironmentFunctionsBenchmark { @Benchmark diff --git a/benchmark/src/test/scala/com/wavesplatform/state/RocksDBWriteBatchBenchmark.scala b/benchmark/src/test/scala/com/wavesplatform/state/RocksDBWriteBatchBenchmark.scala index 219e281ed5f..693526e7db6 100644 --- a/benchmark/src/test/scala/com/wavesplatform/state/RocksDBWriteBatchBenchmark.scala +++ b/benchmark/src/test/scala/com/wavesplatform/state/RocksDBWriteBatchBenchmark.scala @@ -7,7 +7,6 @@ import java.util.function.Consumer import com.google.common.primitives.{Ints, UnsignedBytes} import com.typesafe.config.ConfigFactory -import com.wavesplatform.common.ByteStrComparator import com.wavesplatform.common.state.ByteStr import com.wavesplatform.database.RDB import com.wavesplatform.settings.{WavesSettings, loadConfig} @@ -19,6 +18,7 @@ import org.eclipse.collections.impl.utility.MapIterate import org.openjdk.jmh.annotations.* import org.openjdk.jmh.infra.Blackhole import org.rocksdb.{WriteBatch, WriteOptions} +import com.wavesplatform.utils.byteStrOrdering import scala.util.Random @@ -123,7 +123,7 @@ object RocksDBWriteBatchBenchmark { } object SortedBatch { - val byteStrComparator: Comparator[ByteStr] = (o1: ByteStr, o2: ByteStr) => ByteStrComparator.compare(o1, o2) + val byteStrComparator: Comparator[ByteStr] = (o1: ByteStr, o2: ByteStr) => byteStrOrdering.compare(o1, o2) } object ByteArrayHashingStrategy extends HashingStrategy[Array[Byte]] { diff --git a/benchmark/src/test/scala/com/wavesplatform/state/StateSyntheticBenchmark.scala b/benchmark/src/test/scala/com/wavesplatform/state/StateSyntheticBenchmark.scala index 88bba795815..ec4989cb30b 100644 --- a/benchmark/src/test/scala/com/wavesplatform/state/StateSyntheticBenchmark.scala +++ b/benchmark/src/test/scala/com/wavesplatform/state/StateSyntheticBenchmark.scala @@ -67,7 +67,7 @@ object StateSyntheticBenchmark { val textScript = "sigVerify(tx.bodyBytes,tx.proofs[0],tx.senderPublicKey)" val untypedScript = Parser.parseExpr(textScript).get.value - val typedScript = ExpressionCompiler(compilerContext(V1, Expression, isAssetScript = false), untypedScript).explicitGet()._1 + val typedScript = ExpressionCompiler(compilerContext(V1, Expression, isAssetScript = false), V1, untypedScript).explicitGet()._1 val setScriptBlock = nextBlock( Seq( diff --git a/benchmark/src/test/scala/com/wavesplatform/state/WavesEnvironmentBenchmark.scala b/benchmark/src/test/scala/com/wavesplatform/state/WavesEnvironmentBenchmark.scala index b37ed18ac17..8e831b286c1 100644 --- a/benchmark/src/test/scala/com/wavesplatform/state/WavesEnvironmentBenchmark.scala +++ b/benchmark/src/test/scala/com/wavesplatform/state/WavesEnvironmentBenchmark.scala @@ -1,8 +1,5 @@ package com.wavesplatform.state -import java.io.File -import java.util.concurrent.{ThreadLocalRandom, TimeUnit} - import cats.Id import com.typesafe.config.ConfigFactory import com.wavesplatform.account.{AddressOrAlias, AddressScheme, Alias} @@ -21,6 +18,8 @@ import org.openjdk.jmh.annotations.* import org.openjdk.jmh.infra.Blackhole import scodec.bits.BitVector +import java.io.File +import java.util.concurrent.{ThreadLocalRandom, TimeUnit} import scala.io.Codec /** Tests over real database. How to test: @@ -137,7 +136,7 @@ object WavesEnvironmentBenchmark { val environment: Environment[Id] = { val state = new RocksDBWriter(rdb, wavesSettings.blockchainSettings, wavesSettings.dbSettings, wavesSettings.enableLightMode) - new WavesEnvironment( + WavesEnvironment( AddressScheme.current.chainId, Coeval.raiseError(new NotImplementedError("`tx` is not implemented")), Coeval(state.height), diff --git a/benchmark/src/test/scala/com/wavesplatform/state/WavesEnvironmentRebenchmark.scala b/benchmark/src/test/scala/com/wavesplatform/state/WavesEnvironmentRebenchmark.scala index 4142de58081..df311498090 100644 --- a/benchmark/src/test/scala/com/wavesplatform/state/WavesEnvironmentRebenchmark.scala +++ b/benchmark/src/test/scala/com/wavesplatform/state/WavesEnvironmentRebenchmark.scala @@ -123,7 +123,7 @@ class WavesEnvironmentRebenchmark { @Benchmark def biggestDataEntries(bh: Blackhole, st: St): Unit = { val address = Recipient.Address( - ByteStr(Address.fromString("3PFfUN4dRAyMN4nxYayES1CRZHJjS8JVCHf").explicitGet().bytes) + ByteStr(Address.fromString("3PFfUN4dRAyMN4nxYayES1CRZHJjS8JVCHf", None).explicitGet().bytes) ) val checkBinaryOrString = Random.nextBoolean() if (checkBinaryOrString) { @@ -139,7 +139,7 @@ object WavesEnvironmentRebenchmark { lazy val allAliases: Vector[Alias] = { val builder = Vector.newBuilder[Alias] rdb.db.iterateOver(KeyTags.AddressIdOfAlias) { e => - builder += Alias.fromBytes(e.getKey.drop(2)).explicitGet() + builder += Alias.fromBytes(e.getKey.drop(2), None).explicitGet() } builder.result() } diff --git a/build.sbt b/build.sbt index b209e19069b..e5b1187c2d2 100644 --- a/build.sbt +++ b/build.sbt @@ -6,11 +6,15 @@ 2. You've checked "Make project before run" */ -import sbt.{Compile, Def} -import sbt.Keys.{concurrentRestrictions, _} - Global / onChangedBuildSource := ReloadOnSourceChanges +enablePlugins(GitVersioning) + +git.uncommittedSignifier := Some("DIRTY") +git.useGitDescribe := true +ThisBuild / git.useGitDescribe := true +ThisBuild / PB.protocVersion := "3.24.4" // https://protobuf.dev/support/version-support/#java + lazy val lang = crossProject(JSPlatform, JVMPlatform) .withoutSuffixFor(JVMPlatform) @@ -46,12 +50,12 @@ lazy val `lang-testkit` = project .dependsOn(`lang-jvm`) .in(file("lang/testkit")) .settings( - libraryDependencies ++= Dependencies.test.map(_.withConfigurations(Some("compile"))) + libraryDependencies ++= Dependencies.test.map(_.withConfigurations(Some("compile"))) ++ Dependencies.qaseReportDeps ) lazy val `lang-tests` = project .in(file("lang/tests")) - .dependsOn(`lang-testkit`) + .dependsOn(`lang-testkit` % "test;test->test") lazy val `lang-tests-js` = project .in(file("lang/tests-js")) @@ -62,9 +66,10 @@ lazy val `lang-tests-js` = project testFrameworks += new TestFramework("utest.runner.Framework") ) -lazy val node = project.dependsOn(`lang-jvm`, `lang-testkit` % "test") +lazy val node = project.dependsOn(`lang-jvm`, `lang-testkit` % "test;test->test") lazy val `grpc-server` = project.dependsOn(node % "compile;test->test;runtime->provided") +lazy val `ride-runner` = project.dependsOn(node % "compile;test->test", `grpc-server`) lazy val `node-it` = project.dependsOn(node % "compile;test->test", `lang-testkit`, `repl-jvm`, `grpc-server`) lazy val `node-generator` = project.dependsOn(node % "compile->test") lazy val benchmark = project.dependsOn(node % "compile;test->test") @@ -92,7 +97,7 @@ lazy val repl = crossProject(JSPlatform, JVMPlatform) ) lazy val `repl-jvm` = repl.jvm - .dependsOn(`lang-jvm`, `lang-testkit` % "test") + .dependsOn(`lang-jvm`, `lang-testkit` % "test;test->test") .settings( libraryDependencies ++= Dependencies.circe.value ++ Seq( "org.scala-js" %% "scalajs-stubs" % "1.1.0" % Provided, @@ -118,12 +123,13 @@ lazy val `waves-node` = (project in file(".")) `node-generator`, benchmark, `repl-js`, - `repl-jvm` + `repl-jvm`, + `ride-runner` ) inScope(Global)( Seq( - scalaVersion := "2.13.10", + scalaVersion := "2.13.12", organization := "com.wavesplatform", organizationName := "Waves Platform", organizationHomepage := Some(url("https://wavesplatform.com")), @@ -154,11 +160,11 @@ inScope(Global)( * F - show full stack traces * u - select the JUnit XML reporter with output directory */ - testOptions += Tests.Argument("-oIDOF", "-u", "target/test-reports"), + testOptions += Tests.Argument("-oIDOF", "-u", "target/test-reports", "-C", "com.wavesplatform.report.QaseReporter"), testOptions += Tests.Setup(_ => sys.props("sbt-testing") = "true"), network := Network.default(), instrumentation := false, - resolvers ++= Resolver.sonatypeOssRepos("snapshots") ++ Seq(Resolver.mavenLocal), + resolvers ++= Resolver.sonatypeOssRepos("releases") ++ Resolver.sonatypeOssRepos("snapshots") ++ Seq(Resolver.mavenLocal), Compile / doc / sources := Seq.empty, Compile / packageDoc / publishArtifact := false, concurrentRestrictions := Seq(Tags.limit(Tags.Test, math.min(EvaluateTask.SystemProcessors, 8))), @@ -171,21 +177,28 @@ inScope(Global)( ) ) -// ThisBuild options -git.useGitDescribe := true -git.uncommittedSignifier := Some("DIRTY") - lazy val packageAll = taskKey[Unit]("Package all artifacts") packageAll := { (node / assembly).value + (`ride-runner` / assembly).value buildDebPackages.value buildTarballsForDocker.value } lazy val buildTarballsForDocker = taskKey[Unit]("Package node and grpc-server tarballs and copy them to docker/target") buildTarballsForDocker := { - IO.copyFile((node / Universal / packageZipTarball).value, new File(baseDirectory.value, "docker/target/waves.tgz")) - IO.copyFile((`grpc-server` / Universal / packageZipTarball).value, new File(baseDirectory.value, "docker/target/waves-grpc-server.tgz")) + IO.copyFile( + (node / Universal / packageZipTarball).value, + baseDirectory.value / "docker" / "target" / "waves.tgz" + ) + IO.copyFile( + (`grpc-server` / Universal / packageZipTarball).value, + baseDirectory.value / "docker" / "target" / "waves-grpc-server.tgz" + ) + IO.copyFile( + (`ride-runner` / Universal / packageZipTarball).value, + (`ride-runner` / baseDirectory).value / "docker" / "target" / s"${(`ride-runner` / name).value}.tgz" + ) } lazy val checkPRRaw = taskKey[Unit]("Build a project and run unit tests") @@ -203,6 +216,7 @@ checkPRRaw := Def (`node-it` / Test / compile).value (benchmark / Test / compile).value (`node-generator` / Compile / compile).value + (`ride-runner` / Test / compile).value } ) .value @@ -218,10 +232,16 @@ def checkPR: Command = Command.command("checkPR") { state => state } +lazy val completeQaseRun = taskKey[Unit]("Complete Qase run") +completeQaseRun := Def.task { + (`lang-testkit` / Test / runMain).toTask(" com.wavesplatform.report.QaseRunCompleter").value +}.value + lazy val buildDebPackages = taskKey[Unit]("Build debian packages") buildDebPackages := { (`grpc-server` / Debian / packageBin).value (node / Debian / packageBin).value + (`ride-runner` / Debian / packageBin).value } def buildPackages: Command = Command("buildPackages")(_ => Network.networkParser) { (state, args) => diff --git a/docker/Dockerfile b/docker/Dockerfile index 644b6f5f5de..c9ee2f66f04 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,10 +1,10 @@ -FROM eclipse-temurin:11-jre +FROM eclipse-temurin:11-jre-jammy ENV WAVES_LOG_LEVEL=INFO ENV WAVES_HEAP_SIZE=2g ENV WAVES_NETWORK=mainnet -ENV YOURKIT_VERSION=2022.9 +ENV YOURKIT_VERSION=2023.5 SHELL ["/bin/bash", "-c"] diff --git a/docker/build-node-sbt-builder.sh b/docker/build-node-sbt-builder.sh index de74c33e957..1cfc2fbf3fc 100755 --- a/docker/build-node-sbt-builder.sh +++ b/docker/build-node-sbt-builder.sh @@ -5,5 +5,6 @@ WAVES_VERSION=$(cut -d\" -f2 ../version.sbt) docker build \ --build-arg SBT_VERSION=$(cut -d= -f2 ../project/build.properties) \ --build-arg WAVES_VERSION=$WAVES_VERSION \ + --pull \ -t wavesplatform/node-sbt-builder:$WAVES_VERSION \ - < node-sbt-builder.Dockerfile diff --git a/docker/node-sbt-builder.Dockerfile b/docker/node-sbt-builder.Dockerfile index 0e67048e907..038589c20b5 100644 --- a/docker/node-sbt-builder.Dockerfile +++ b/docker/node-sbt-builder.Dockerfile @@ -1,4 +1,4 @@ -FROM eclipse-temurin:8u345-b01-jdk-jammy +FROM eclipse-temurin:8-jdk-jammy ARG WAVES_VERSION ARG SBT_VERSION diff --git a/grpc-server/src/main/scala/com/wavesplatform/api/grpc/AccountsApiGrpcImpl.scala b/grpc-server/src/main/scala/com/wavesplatform/api/grpc/AccountsApiGrpcImpl.scala index 75a848b370d..fbcf7b3e764 100644 --- a/grpc-server/src/main/scala/com/wavesplatform/api/grpc/AccountsApiGrpcImpl.scala +++ b/grpc-server/src/main/scala/com/wavesplatform/api/grpc/AccountsApiGrpcImpl.scala @@ -39,7 +39,7 @@ class AccountsApiGrpcImpl(commonApi: CommonAccountsApi)(implicit sc: Scheduler) BalanceResponse().withAsset(fromAssetIdAndAmount(v)) override def getBalances(request: BalancesRequest, responseObserver: StreamObserver[BalanceResponse]): Unit = responseObserver.interceptErrors { - val addressOption: Option[Address] = if (request.address.isEmpty) None else Some(request.address.toAddress) + val addressOption: Option[Address] = if (request.address.isEmpty) None else Some(request.address.toAddress()) val assetIds: Seq[Asset] = request.assets.map(id => if (id.isEmpty) Asset.Waves else Asset.IssuedAsset(id.toByteStr)) val responseStream = (addressOption, assetIds) match { @@ -61,15 +61,17 @@ class AccountsApiGrpcImpl(commonApi: CommonAccountsApi)(implicit sc: Scheduler) responseObserver.completeWith(responseStream) } - override def getScript(request: AccountRequest): Future[ScriptData] = Future { - commonApi.script(request.address.toAddress) match { - case Some(desc) => ScriptData( + override def getScript(request: AccountRequest): Future[ScriptResponse] = Future { + commonApi.script(request.address.toAddress()) match { + case Some(desc) => + ScriptResponse( PBTransactions.toPBScript(Some(desc.script)), desc.script.expr.toString, - desc.verifierComplexity + desc.verifierComplexity, + desc.publicKey.toByteString ) case None => - ScriptData() + ScriptResponse() } } @@ -78,7 +80,7 @@ class AccountsApiGrpcImpl(commonApi: CommonAccountsApi)(implicit sc: Scheduler) responseObserver.interceptErrors { val result = commonApi - .activeLeases(request.address.toAddress) + .activeLeases(request.address.toAddress()) .map { case LeaseInfo(leaseId, originTransactionId, sender, recipient, amount, height, status, _, _) => assert(status == LeaseInfo.Status.Active) LeaseResponse( @@ -95,9 +97,9 @@ class AccountsApiGrpcImpl(commonApi: CommonAccountsApi)(implicit sc: Scheduler) override def getDataEntries(request: DataRequest, responseObserver: StreamObserver[DataEntryResponse]): Unit = responseObserver.interceptErrors { val stream = if (request.key.nonEmpty) { - Observable.fromIterable(commonApi.data(request.address.toAddress, request.key)) + Observable.fromIterable(commonApi.data(request.address.toAddress(), request.key)) } else { - commonApi.dataStream(request.address.toAddress, Option(request.key).filter(_.nonEmpty)) + commonApi.dataStream(request.address.toAddress(), Option(request.key).filter(_.nonEmpty)) } responseObserver.completeWith(stream.map(de => DataEntryResponse(request.address, Some(PBTransactions.toPBDataEntry(de))))) diff --git a/grpc-server/src/main/scala/com/wavesplatform/api/grpc/AssetsApiGrpcImpl.scala b/grpc-server/src/main/scala/com/wavesplatform/api/grpc/AssetsApiGrpcImpl.scala index 5d847bea2ad..44db0277a0a 100644 --- a/grpc-server/src/main/scala/com/wavesplatform/api/grpc/AssetsApiGrpcImpl.scala +++ b/grpc-server/src/main/scala/com/wavesplatform/api/grpc/AssetsApiGrpcImpl.scala @@ -25,7 +25,7 @@ class AssetsApiGrpcImpl(assetsApi: CommonAssetsApi, accountsApi: CommonAccountsA } override def getNFTList(request: NFTRequest, responseObserver: StreamObserver[NFTResponse]): Unit = responseObserver.interceptErrors { - val addressOption: Option[Address] = if (request.address.isEmpty) None else Some(request.address.toAddress) + val addressOption: Option[Address] = if (request.address.isEmpty) None else Some(request.address.toAddress()) val afterAssetId: Option[IssuedAsset] = if (request.afterAssetId.isEmpty) None else Some(IssuedAsset(request.afterAssetId.toByteStr)) val responseStream = addressOption match { diff --git a/grpc-server/src/main/scala/com/wavesplatform/api/grpc/BlocksApiGrpcImpl.scala b/grpc-server/src/main/scala/com/wavesplatform/api/grpc/BlocksApiGrpcImpl.scala index fda741aeb4b..0edf1c5e6e0 100644 --- a/grpc-server/src/main/scala/com/wavesplatform/api/grpc/BlocksApiGrpcImpl.scala +++ b/grpc-server/src/main/scala/com/wavesplatform/api/grpc/BlocksApiGrpcImpl.scala @@ -36,7 +36,7 @@ class BlocksApiGrpcImpl(commonApi: CommonBlocksApi)(implicit sc: Scheduler) exte responseObserver.completeWith(request.filter match { case Filter.GeneratorPublicKey(publicKey) => stream.filter(_.getBlock.getHeader.generator.toPublicKey == publicKey.toPublicKey) - case Filter.GeneratorAddress(address) => stream.filter(_.getBlock.getHeader.generator.toAddress == address.toAddress) + case Filter.GeneratorAddress(address) => stream.filter(_.getBlock.getHeader.generator.toAddress() == address.toAddress()) case Filter.Empty => stream }) } diff --git a/grpc-server/src/main/scala/com/wavesplatform/api/grpc/TransactionsApiGrpcImpl.scala b/grpc-server/src/main/scala/com/wavesplatform/api/grpc/TransactionsApiGrpcImpl.scala index 8b459f5f16e..7848170398c 100644 --- a/grpc-server/src/main/scala/com/wavesplatform/api/grpc/TransactionsApiGrpcImpl.scala +++ b/grpc-server/src/main/scala/com/wavesplatform/api/grpc/TransactionsApiGrpcImpl.scala @@ -30,7 +30,7 @@ class TransactionsApiGrpcImpl(blockchain: Blockchain, commonApi: CommonTransacti .fold(e => throw new IllegalArgumentException(e.toString), identity) val maybeSender = Option(request.sender) - .collect { case s if !s.isEmpty => s.toAddress } + .collect { case s if !s.isEmpty => s.toAddress() } commonApi.transactionsByAddress( recipientAddrOrAlias, @@ -41,7 +41,7 @@ class TransactionsApiGrpcImpl(blockchain: Blockchain, commonApi: CommonTransacti // By sender case None if !request.sender.isEmpty => - val senderAddress = request.sender.toAddress + val senderAddress = request.sender.toAddress() commonApi.transactionsByAddress( senderAddress, Some(senderAddress), @@ -67,7 +67,7 @@ class TransactionsApiGrpcImpl(blockchain: Blockchain, commonApi: CommonTransacti override def getUnconfirmed(request: TransactionsRequest, responseObserver: StreamObserver[TransactionResponse]): Unit = responseObserver.interceptErrors { val unconfirmedTransactions = if (!request.sender.isEmpty) { - val senderAddress = request.sender.toAddress + val senderAddress = request.sender.toAddress() commonApi.unconfirmedTransactions.collect { case a: Authorized if a.sender.toAddress == senderAddress => a } diff --git a/grpc-server/src/main/scala/com/wavesplatform/events/events.scala b/grpc-server/src/main/scala/com/wavesplatform/events/events.scala index c28f8d4f2d9..c08030cb2fe 100644 --- a/grpc-server/src/main/scala/com/wavesplatform/events/events.scala +++ b/grpc-server/src/main/scala/com/wavesplatform/events/events.scala @@ -23,7 +23,7 @@ import com.wavesplatform.transaction.assets.exchange.ExchangeTransaction import com.wavesplatform.transaction.lease.LeaseTransaction import com.wavesplatform.transaction.smart.InvokeScriptTransaction import com.wavesplatform.transaction.transfer.{MassTransferTransaction, TransferTransaction} -import com.wavesplatform.transaction.{Asset, Authorized, CreateAliasTransaction, EthereumTransaction} +import com.wavesplatform.transaction.{Asset, Authorized, CreateAliasTransaction, EthereumTransaction, Transaction} import scala.collection.mutable import scala.collection.mutable.ArrayBuffer @@ -60,7 +60,7 @@ object StateUpdate { def fromPB(v: PBBalanceUpdate): BalanceUpdate = { val (asset, after) = PBAmounts.toAssetAndAmount(v.getAmountAfter) val before = v.amountBefore - BalanceUpdate(v.address.toAddress, asset, before, after) + BalanceUpdate(v.address.toAddress(), asset, before, after) } def toPB(v: BalanceUpdate): PBBalanceUpdate = { @@ -81,7 +81,7 @@ object StateUpdate { def fromPB(v: PBDataEntryUpdate): DataEntryUpdate = { DataEntryUpdate( - v.address.toAddress, + v.address.toAddress(), PBTransactions.toVanillaDataEntry(v.getDataEntryBefore), PBTransactions.toVanillaDataEntry(v.getDataEntry) ) @@ -105,7 +105,7 @@ object StateUpdate { def fromPB(v: PBLeasingUpdate): LeasingBalanceUpdate = { LeasingBalanceUpdate( - v.address.toAddress, + v.address.toAddress(), LeaseBalance(v.inBefore, v.outBefore), LeaseBalance(v.inAfter, v.outAfter) ) @@ -157,7 +157,7 @@ object StateUpdate { }, v.amount, v.sender.toPublicKey, - v.recipient.toAddress, + v.recipient.toAddress(), v.originTransactionId.toByteStr ) } @@ -386,10 +386,14 @@ object StateUpdate { } } - private lazy val WavesAlias = Alias.fromString("alias:W:waves").explicitGet() - private lazy val WavesAddress = Address.fromString("3PGd1eQR8EhLkSogpmu9Ne7hSH1rQ5ALihd").explicitGet() + private lazy val WavesAlias = Alias.fromString("alias:W:waves", Some('W'.toByte)).explicitGet() + private lazy val WavesAddress = Address.fromString("3PGd1eQR8EhLkSogpmu9Ne7hSH1rQ5ALihd", Some('W'.toByte)).explicitGet() - def atomic(blockchainBeforeWithMinerReward: Blockchain, snapshot: StateSnapshot): StateUpdate = { + def atomic( + blockchainBeforeWithMinerReward: Blockchain, + snapshot: StateSnapshot, + txWithLeases: Iterable[(Transaction, Map[ByteStr, LeaseSnapshot])] + ): StateUpdate = { val blockchain = blockchainBeforeWithMinerReward val blockchainAfter = SnapshotBlockchain(blockchain, snapshot) @@ -426,18 +430,20 @@ object StateUpdate { assetAfter = blockchainAfter.assetDescription(asset) } yield AssetStateUpdate(asset.id, assetBefore, assetAfter) - val updatedLeases = snapshot.leaseStates.map { case (leaseId, newState) => - LeaseUpdate( - leaseId, - if (newState.isActive) LeaseStatus.Active else LeaseStatus.Inactive, - newState.amount, - newState.sender, - newState.recipient match { - case `WavesAlias` => WavesAddress - case other => blockchainAfter.resolveAlias(other).explicitGet() - }, - newState.sourceId - ) + val updatedLeases = txWithLeases.flatMap { case (sourceTxId, leases) => + leases.map { case (leaseId, newState) => + LeaseUpdate( + leaseId, + if (newState.isActive) LeaseStatus.Active else LeaseStatus.Inactive, + newState.amount, + newState.sender, + newState.recipient match { + case `WavesAlias` => WavesAddress + case other => blockchainAfter.resolveAlias(other).explicitGet() + }, + newState.toDetails(blockchain, Some(sourceTxId), blockchain.leaseDetails(leaseId)).sourceId + ) + } }.toVector val updatedScripts = snapshot.accountScriptsByAddress.map { case (address, newScript) => @@ -546,13 +552,17 @@ object StateUpdate { val accBlockchain = SnapshotBlockchain(blockchainBeforeWithReward, accSnapshot) ( accSnapshot |+| txInfo.snapshot, - updates :+ atomic(accBlockchain, txInfo.snapshot) + updates :+ atomic(accBlockchain, txInfo.snapshot, Seq((txInfo.transaction, txInfo.snapshot.leaseStates))) ) } val blockchainAfter = SnapshotBlockchain(blockchainBeforeWithReward, totalSnapshot) val metadata = transactionsMetadata(blockchainAfter, totalSnapshot) val refAssets = referencedAssets(blockchainAfter, txsStateUpdates) - val keyBlockUpdate = atomic(blockchainBeforeWithReward, keyBlockSnapshot) + val keyBlockUpdate = atomic( + blockchainBeforeWithReward, + keyBlockSnapshot, + keyBlockSnapshot.transactions.map { case (_, txInfo) => (txInfo.transaction, txInfo.snapshot.leaseStates) } + ) (keyBlockUpdate, txsStateUpdates, metadata, refAssets) } } diff --git a/grpc-server/src/test/scala/com/wavesplatform/api/grpc/test/AccountsApiGrpcSpec.scala b/grpc-server/src/test/scala/com/wavesplatform/api/grpc/test/AccountsApiGrpcSpec.scala index 4f0d87e1b26..61c1cb035f6 100644 --- a/grpc-server/src/test/scala/com/wavesplatform/api/grpc/test/AccountsApiGrpcSpec.scala +++ b/grpc-server/src/test/scala/com/wavesplatform/api/grpc/test/AccountsApiGrpcSpec.scala @@ -28,10 +28,14 @@ import com.wavesplatform.utils.DiffMatchers import monix.execution.Scheduler.Implicits.global import org.scalatest.{Assertion, BeforeAndAfterAll} +import scala.concurrent.Await +import scala.concurrent.duration.{DurationInt, FiniteDuration} + class AccountsApiGrpcSpec extends FreeSpec with BeforeAndAfterAll with DiffMatchers with WithDomain with GrpcApiHelpers { - val sender: KeyPair = TxHelpers.signer(1) - val recipient: KeyPair = TxHelpers.signer(2) + val sender: KeyPair = TxHelpers.signer(1) + val recipient: KeyPair = TxHelpers.signer(2) + val timeout: FiniteDuration = 2.minutes "GetBalances should work" in withDomain(DomainPresets.RideV6, AddrWithBalance.enoughBalances(sender)) { d => val grpcApi = getGrpcApi(d) @@ -73,6 +77,28 @@ class AccountsApiGrpcSpec extends FreeSpec with BeforeAndAfterAll with DiffMatch } } + "GetScript should work" in withDomain(DomainPresets.RideV6, AddrWithBalance.enoughBalances(sender)) { d => + val grpcApi = getGrpcApi(d) + + val script = TxHelpers.script( + s"""{-# STDLIB_VERSION 6 #-} + |{-# CONTENT_TYPE DAPP #-} + |{-# SCRIPT_TYPE ACCOUNT #-} + |@Callable(i) + |func foo(a: Int) = { ([], a == 42) }""".stripMargin + ) + + d.appendBlock(TxHelpers.setScript(sender, script)) + + val r = Await.result( + grpcApi.getScript(AccountRequest.of(ByteString.copyFrom(sender.toAddress.bytes))), + timeout + ) + + r.scriptBytes shouldBe ByteString.copyFrom(script.bytes().arr) + r.publicKey shouldBe ByteString.copyFrom(sender.publicKey.arr) + } + "GetActiveLeases should work" in withDomain(DomainPresets.RideV6, AddrWithBalance.enoughBalances(sender)) { d => val grpcApi = getGrpcApi(d) diff --git a/grpc-server/src/test/scala/com/wavesplatform/api/grpc/test/AssetsApiGrpcSpec.scala b/grpc-server/src/test/scala/com/wavesplatform/api/grpc/test/AssetsApiGrpcSpec.scala index 3ecbc270e45..abbeee9e08f 100644 --- a/grpc-server/src/test/scala/com/wavesplatform/api/grpc/test/AssetsApiGrpcSpec.scala +++ b/grpc-server/src/test/scala/com/wavesplatform/api/grpc/test/AssetsApiGrpcSpec.scala @@ -3,6 +3,7 @@ package com.wavesplatform.api.grpc.test import com.google.protobuf.ByteString import com.wavesplatform.account.KeyPair import com.wavesplatform.api.grpc.{AssetInfoResponse, AssetsApiGrpcImpl, NFTRequest, NFTResponse} +import com.wavesplatform.block.Block.ProtoBlockVersion import com.wavesplatform.db.WithDomain import com.wavesplatform.db.WithState.AddrWithBalance import com.wavesplatform.features.BlockchainFeatures @@ -55,6 +56,49 @@ class AssetsApiGrpcSpec extends FreeSpec with BeforeAndAfterAll with DiffMatcher } } + "NODE-999. GetNftList limit should work properly" in withDomain( + RideV6.addFeatures(BlockchainFeatures.ReduceNFTFee), + AddrWithBalance.enoughBalances(sender) + ) { d => + val nftIssues = (1 to 5).map(idx => TxHelpers.issue(sender, 1, name = s"nft$idx", reissuable = false)) + val limit = 2 + val afterId = 1 // second element + + d.appendBlock() + val mb1 = d.appendMicroBlock(nftIssues.take(afterId + 1)*) + d.appendMicroBlock(nftIssues.drop(afterId + 1)*) + + // full liquid + d.rocksDBWriter.containsTransaction(nftIssues(afterId)) shouldBe false + d.rocksDBWriter.containsTransaction(nftIssues(afterId + 1)) shouldBe false + check() + + // liquid afterId + d.appendBlock(d.createBlock(ProtoBlockVersion, nftIssues.drop(afterId + 1), Some(mb1))) + d.rocksDBWriter.containsTransaction(nftIssues(afterId)) shouldBe true + d.rocksDBWriter.containsTransaction(nftIssues(afterId + 1)) shouldBe false + check() + + // full solid + d.appendBlock() + d.rocksDBWriter.containsTransaction(nftIssues(afterId)) shouldBe true + d.rocksDBWriter.containsTransaction(nftIssues(afterId + 1)) shouldBe true + check() + + def check() = { + val (observer, result) = createObserver[NFTResponse] + val request = NFTRequest.of( + ByteString.copyFrom(sender.toAddress.bytes), + limit, + afterAssetId = ByteString.copyFrom(nftIssues(afterId).asset.id.arr) + ) + getGrpcApi(d).getNFTList(request, observer) + val response = result.runSyncUnsafe() + response.size shouldBe limit + response.map(_.assetInfo.get.name) shouldBe nftIssues.slice(afterId + 1, afterId + limit + 1).map(_.name.toStringUtf8) + } + } + private def getGrpcApi(d: Domain) = new AssetsApiGrpcImpl(d.assetsApi, d.accountsApi) } diff --git a/grpc-server/src/test/scala/com/wavesplatform/api/grpc/test/BlocksApiGrpcSpec.scala b/grpc-server/src/test/scala/com/wavesplatform/api/grpc/test/BlocksApiGrpcSpec.scala index 7083f98297b..bb210dd8014 100644 --- a/grpc-server/src/test/scala/com/wavesplatform/api/grpc/test/BlocksApiGrpcSpec.scala +++ b/grpc-server/src/test/scala/com/wavesplatform/api/grpc/test/BlocksApiGrpcSpec.scala @@ -23,7 +23,7 @@ import com.wavesplatform.transaction.{TxHelpers, TxVersion} import com.wavesplatform.utils.DiffMatchers import monix.execution.Scheduler.Implicits.global import org.scalatest.{Assertion, BeforeAndAfterAll} - +import com.wavesplatform.utils.byteStrOrdering import scala.concurrent.Await import scala.concurrent.duration.{DurationInt, FiniteDuration} diff --git a/grpc-server/src/test/scala/com/wavesplatform/api/grpc/test/GRPCBroadcastSpec.scala b/grpc-server/src/test/scala/com/wavesplatform/api/grpc/test/GRPCBroadcastSpec.scala index a47b4105d7e..97f4b4e997d 100644 --- a/grpc-server/src/test/scala/com/wavesplatform/api/grpc/test/GRPCBroadcastSpec.scala +++ b/grpc-server/src/test/scala/com/wavesplatform/api/grpc/test/GRPCBroadcastSpec.scala @@ -1,7 +1,7 @@ package com.wavesplatform.api.grpc.test import scala.concurrent.{Await, Future} -import scala.concurrent.duration.Duration +import scala.concurrent.duration.* import com.wavesplatform.account.Address import com.wavesplatform.common.state.ByteStr import com.wavesplatform.test.{FlatSpec, TestTime} @@ -91,7 +91,7 @@ class GRPCBroadcastSpec extends FlatSpec with BeforeAndAfterAll with PathMockFac @throws[StatusException]("on failed broadcast") def assertBroadcast(tx: Transaction): Unit = { - Await.result(grpcTxApi.broadcast(PBTransactions.protobuf(tx)), Duration.Inf) + Await.result(grpcTxApi.broadcast(PBTransactions.protobuf(tx)), 10.seconds) } } } diff --git a/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesEthereumInvokeTxSpec.scala b/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesEthereumInvokeTxSpec.scala new file mode 100644 index 00000000000..ca5cd1faf05 --- /dev/null +++ b/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesEthereumInvokeTxSpec.scala @@ -0,0 +1,218 @@ +package com.wavesplatform.events + +import com.wavesplatform.TestValues.fee +import com.wavesplatform.account.{Address, SeedKeyPair} +import com.wavesplatform.common.state.ByteStr +import com.wavesplatform.db.WithState.AddrWithBalance +import com.wavesplatform.events.fixtures.BlockchainUpdateGrpcMethod.* +import com.wavesplatform.events.fixtures.InvokeWavesTxCheckers.checkInvokeDoubleNestedBlockchainUpdates +import com.wavesplatform.events.fixtures.PrepareInvokeTestData.* +import com.wavesplatform.events.fixtures.WavesTxChecks.* +import com.wavesplatform.events.protobuf.BlockchainUpdated.Append +import com.wavesplatform.test.NumericExt +import com.wavesplatform.transaction.Asset.Waves +import com.wavesplatform.transaction.EthTxGenerator.Arg +import com.wavesplatform.transaction.{Asset, EthTxGenerator, EthereumTransaction, TxHelpers, TxNonNegativeAmount} +import com.wavesplatform.transaction.TxHelpers.secondAddress +import com.wavesplatform.transaction.assets.IssueTransaction +import com.wavesplatform.transaction.transfer.MassTransferTransaction.ParsedTransfer + +class BlockchainUpdatesEthereumInvokeTxSpec extends BlockchainUpdatesTestBase { + val ethAddressBalanceAfterTx: Long = firstTxParticipantBalanceBefore - invokeFee + + "Simple invoke transaction" - { + val issue = TxHelpers.issue(firstTxParticipant) + val asset: Asset = issue.asset + val assetByteStr = Arg.Bytes(asset.compatId.get) + val addressByteStr = Arg.Bytes(ByteStr.apply(secondTxParticipantAddress.bytes)) + val args: Seq[Arg] = Seq(assetByteStr, addressByteStr) + val invoke: EthereumTransaction = + EthTxGenerator.generateEthInvoke(firstTxParticipantEthereum, firstTxParticipantAddress, invokeFunctionName, args, Seq.empty, invokeFee) + val issuerAssetBalanceAfterTx: Long = issue.quantity.value - burnNum - scriptTransferAssetNum + reissueNum + val secondAddressWavesBalanceAfterTx: Long = secondTxParticipantBalanceBefore + scriptTransferUnitNum + val issuerBalanceBeforeInvoke: Long = firstTxParticipantBalanceBefore - issue.fee.value - fee + val balances: Seq[AddrWithBalance] = Seq( + AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore), + AddrWithBalance(firstTxParticipantEthereumAddress, firstTxParticipantBalanceBefore), + AddrWithBalance(secondTxParticipantAddress, secondTxParticipantBalanceBefore) + ) + val expectBalanceMap = Map( + (firstTxParticipantEthereumAddress, Waves) -> (firstTxParticipantBalanceBefore, ethAddressBalanceAfterTx), + (firstTxParticipantAddress, Waves) -> (issuerBalanceBeforeInvoke, issuerBalanceBeforeInvoke - scriptTransferUnitNum), + (secondTxParticipantAddress, Waves) -> (secondTxParticipantBalanceBefore, secondAddressWavesBalanceAfterTx), + (firstTxParticipantAddress, asset) -> (issue.quantity.value, issuerAssetBalanceAfterTx), + (secondTxParticipantAddress, asset) -> (0L, scriptTransferAssetNum) + ) + + "BU-226. Invoke have to return correct data for subscribe" in { + testInvoke(issue, invoke, balances)( + Subscribe, + checkFunction = append => { + val invokeScriptMetadata = append.transactionsMetadata.head.getEthereum.getInvoke + checkEthereumBase(append, invoke, invokeFunctionName) + checkGeneralInvoke(append, issuerAssetBalanceAfterTx, invoke, issue, invokeScriptMetadata, expectBalanceMap) + } + ) + } + + "BU-229. Invoke have to return correct data for getBlockUpdate" in { + testInvoke(issue, invoke, balances)( + GetBlockUpdate, + checkFunction = append => { + val invokeScriptMetadata = append.transactionsMetadata.head.getEthereum.getInvoke + checkEthereumBase(append, invoke, invokeFunctionName) + checkGeneralInvoke(append, issuerAssetBalanceAfterTx, invoke, issue, invokeScriptMetadata, expectBalanceMap) + } + ) + } + + "BU-232. Invoke have to return correct data for getBlockUpdateRange" in { + testInvoke(issue, invoke, balances)( + GetBlockUpdateRange, + checkFunction = append => { + val invokeScriptMetadata = append.transactionsMetadata.head.getEthereum.getInvoke + checkEthereumBase(append, invoke, invokeFunctionName) + checkGeneralInvoke(append, issuerAssetBalanceAfterTx, invoke, issue, invokeScriptMetadata, expectBalanceMap) + } + ) + } + } + + "Double nesting call ethereum tests" - { + val assetDappAccount: SeedKeyPair = TxHelpers.signer(4) + val assetDappAddress: Address = assetDappAccount.toAddress + val invokerDappAccount: SeedKeyPair = TxHelpers.signer(5) + val invokerDappAddress: Address = invokerDappAccount.toAddress + val issue: IssueTransaction = TxHelpers.issue(assetDappAccount) + val asset: Asset = issue.asset + val issueAssetFee = issue.fee.value + val massTx = TxHelpers.massTransfer( + assetDappAccount, + Seq( + ParsedTransfer(firstTxParticipantAddress, TxNonNegativeAmount.unsafeFrom(amount)), + ParsedTransfer(secondAddress, TxNonNegativeAmount.unsafeFrom(amount)), + ParsedTransfer(invokerDappAddress, TxNonNegativeAmount.unsafeFrom(amount)) + ), + asset, + fee = 500000 + ) + val args: Seq[Arg] = + Seq( + Arg.Bytes(ByteStr.apply(secondAddress.bytes)), + Arg.Bytes(ByteStr.apply(assetDappAddress.bytes)), + Arg.Integer(scriptTransferUnitNum), + Arg.Str(bar), + Arg.Bytes(asset.compatId.get) + ) + val invoke = EthTxGenerator.generateEthInvoke(firstTxParticipantEthereum, firstTxParticipantAddress, "foo", args, Seq.empty, invokeFee) + val secondAddressBalance: Long = 8.waves + val assetDappBalance: Long = 12.waves + val secondAddressAssetBalanceForAll = amount - scriptTransferAssetNum + paymentNum + val dAppAddressAssetBalanceForCaller = amount + scriptTransferAssetNum - paymentNum + val dAppAddressAssetBalanceForOriginalCaller = amount - paymentNum + val balancesSeq = Seq( + AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore), + AddrWithBalance(firstTxParticipantEthereumAddress, firstTxParticipantBalanceBefore), + AddrWithBalance(secondAddress, secondAddressBalance), + AddrWithBalance(invokerDappAddress, ethAddressBalanceAfterTx), + AddrWithBalance(assetDappAddress, assetDappBalance) + ) + val secondAddressWavesBalanceBefore = secondAddressBalance - fee + val secondAddressWavesBalanceAfter = secondAddressWavesBalanceBefore + scriptTransferUnitNum + val assetDappAddressWavesBalanceBefore = assetDappBalance - issueAssetFee - massTx.fee.value - fee + val assetDappAddressWavesBalanceAfter = assetDappAddressWavesBalanceBefore - scriptTransferUnitNum + val firstTxParticipantBalanceAfter = ethAddressBalanceAfterTx + scriptTransferUnitNum + val callerBalancesMap = Map( + (secondAddress, Waves) -> (secondAddressWavesBalanceBefore, secondAddressWavesBalanceAfter), + (secondAddress, asset) -> (amount, secondAddressAssetBalanceForAll), + (firstTxParticipantAddress, asset) -> (amount, dAppAddressAssetBalanceForCaller), + (assetDappAddress, Waves) -> (assetDappAddressWavesBalanceBefore, assetDappAddressWavesBalanceAfter), + (firstTxParticipantEthereumAddress, Waves) -> (firstTxParticipantBalanceBefore, ethAddressBalanceAfterTx) + ) + val originalCallerBalancesMap = Map( + (secondAddress, asset) -> (amount, secondAddressAssetBalanceForAll), + (firstTxParticipantEthereumAddress, asset) -> (0L, scriptTransferAssetNum), + (firstTxParticipantAddress, asset) -> (amount, dAppAddressAssetBalanceForOriginalCaller), + (assetDappAddress, Waves) -> (assetDappAddressWavesBalanceBefore, assetDappAddressWavesBalanceAfter), + (firstTxParticipantEthereumAddress, Waves) -> (firstTxParticipantBalanceBefore, firstTxParticipantBalanceAfter) + ) + + "BU-227. doubles nested i.caller. Invoke have to return correct data for subscribe" in { + doubleNestedInvokeTest(assetDappAccount, balancesSeq, issue, invoke, massTx, caller, Subscribe) { append => + val invokeScriptMetadata = append.transactionsMetadata.head.getEthereum.getInvoke + checkEthereumBase(append, invoke, foo) + checkInvokeDoubleNestedBlockchainUpdates(append, invokeScriptMetadata, assetDappAddress, firstTxParticipantAddress, secondAddress, issue, callerBalancesMap) + } + } + + "BU-230. doubles nested i.caller. Invoke have to return correct data for getBlockUpdate" in { + doubleNestedInvokeTest(assetDappAccount, balancesSeq, issue, invoke, massTx, caller, GetBlockUpdate) { append => + val invokeScriptMetadata = append.transactionsMetadata.head.getEthereum.getInvoke + checkEthereumBase(append, invoke, foo) + checkInvokeDoubleNestedBlockchainUpdates(append, invokeScriptMetadata, assetDappAddress, firstTxParticipantAddress, secondAddress, issue, callerBalancesMap) + } + } + + "BU-233. doubles nested i.caller. Invoke have to return correct data for getBlockUpdateRange" in { + doubleNestedInvokeTest(assetDappAccount, balancesSeq, issue, invoke, massTx, caller, GetBlockUpdateRange) { append => + val invokeScriptMetadata = append.transactionsMetadata.head.getEthereum.getInvoke + checkEthereumBase(append, invoke, foo) + checkInvokeDoubleNestedBlockchainUpdates(append, invokeScriptMetadata, assetDappAddress, firstTxParticipantAddress, secondAddress, issue, callerBalancesMap) + } + } + + "BU-228. double nested i.originCaller. Invoke have to return correct data for subscribe" in { + doubleNestedInvokeTest(assetDappAccount, balancesSeq, issue, invoke, massTx, originCaller, Subscribe) { append => + val invokeScriptMetadata = append.transactionsMetadata.head.getEthereum.getInvoke + checkEthereumBase(append, invoke, foo) + checkInvokeDoubleNestedBlockchainUpdates( + append, + invokeScriptMetadata, + assetDappAddress, + firstTxParticipantEthereumAddress, + firstTxParticipantEthereumAddress, + issue, + originalCallerBalancesMap + ) + } + } + + "BU-231. double nested i.originCaller. Invoke have to return correct data for getBlockUpdate" in { + doubleNestedInvokeTest(assetDappAccount, balancesSeq, issue, invoke, massTx, originCaller, GetBlockUpdate) { append => + val invokeScriptMetadata = append.transactionsMetadata.head.getEthereum.getInvoke + checkEthereumBase(append, invoke, foo) + checkInvokeDoubleNestedBlockchainUpdates( + append, + invokeScriptMetadata, + assetDappAddress, + firstTxParticipantEthereumAddress, + firstTxParticipantEthereumAddress, + issue, + originalCallerBalancesMap + ) + } + } + + "BU-234. double nested i.originCaller. Invoke have to return correct data for getBlockUpdateRange" in { + doubleNestedInvokeTest(assetDappAccount, balancesSeq, issue, invoke, massTx, originCaller, GetBlockUpdateRange) { append => + val invokeScriptMetadata = append.transactionsMetadata.head.getEthereum.getInvoke + checkEthereumBase(append, invoke, foo) + checkInvokeDoubleNestedBlockchainUpdates( + append, + invokeScriptMetadata, + assetDappAddress, + firstTxParticipantEthereumAddress, + firstTxParticipantEthereumAddress, + issue, + originalCallerBalancesMap + ) + } + } + } + + def checkEthereumBase(append: Append, invoke: EthereumTransaction, functionName: String): Unit = { + val txMetadata = append.transactionsMetadata.head + checkEthereumTransaction(append.transactionIds.head, append.transactionAt(0), invoke) + checkEthereumInvokeBaseTransactionMetadata(txMetadata, invoke, functionName, firstTxParticipantAddress) + } +} diff --git a/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesGetBlockUpdatesRangeSpec.scala b/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesGetBlockUpdatesRangeSpec.scala new file mode 100644 index 00000000000..3e2c0211a79 --- /dev/null +++ b/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesGetBlockUpdatesRangeSpec.scala @@ -0,0 +1,340 @@ +package com.wavesplatform.events + +import com.wavesplatform.TestValues.fee +import com.wavesplatform.db.WithState.AddrWithBalance +import com.wavesplatform.events.api.grpc.protobuf.GetBlockUpdatesRangeRequest +import com.wavesplatform.features.BlockchainFeatures +import com.wavesplatform.test.* +import com.wavesplatform.test.DomainPresets.* +import com.wavesplatform.transaction.Asset.Waves +import com.wavesplatform.transaction.assets.IssueTransaction +import com.wavesplatform.transaction.assets.exchange.{ExchangeTransaction, Order, OrderType} +import com.wavesplatform.transaction.{EthTxGenerator, EthereumTransaction, TxHelpers, TxVersion} +import com.wavesplatform.events.protobuf.BlockchainUpdated as PBBlockchainUpdated + +class BlockchainUpdatesGetBlockUpdatesRangeSpec extends BlockchainUpdatesTestBase { + "BlockchainUpdates getBlockUpdateRange tests" - { + "BU-157. Return correct data for alias" in { + val aliasTx = TxHelpers.createAlias("test", firstTxParticipant, fee = customFee) + withGenerateGetBlockUpdateRange( + GetBlockUpdatesRangeRequest.of(1, 2), + settings = currentSettings, + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + ) { d => + d.appendBlock(aliasTx) + d.appendBlock() + } { getBlockUpdateRange => + val append = getBlockUpdateRange.apply(1).getAppend + checkAlias(append, aliasTx) + } + } + + "BU-172. Return correct data for transfer" in { + val transferTx = TxHelpers.transfer(firstTxParticipant, secondTxParticipantAddress, amount, Waves, customFee) + withGenerateGetBlockUpdateRange( + GetBlockUpdatesRangeRequest.of(1, 2), + settings = currentSettings, + balances = Seq( + AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore), + AddrWithBalance(secondTxParticipant.toAddress, secondTxParticipantBalanceBefore) + ) + ) { d => + d.appendBlock(transferTx) + d.appendBlock() + } { getBlockUpdateRange => + val append = getBlockUpdateRange.apply(1).getAppend + checkTransferTx(append, transferTx) + } + } + + "BU-161. Return correct data for issue" in { + val issue: IssueTransaction = TxHelpers.issue( + firstTxParticipant, + amount, + decimals = 8, + name = "Test_asset", + description = "description", + customAssetIssueFee, + defaultScript + ) + withGenerateGetBlockUpdateRange( + GetBlockUpdatesRangeRequest.of(1, 2), + settings = currentSettings, + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + ) { d => + d.appendBlock(issue) + d.appendBlock() + } { getBlockUpdateRange => + val append = getBlockUpdateRange.apply(1).getAppend + checkIssueTx(append, issue, isNft = false) + } + } + + "BU-162. Return correct data for issue NFT" in { + val issueNftTx = + TxHelpers.issue(firstTxParticipant, name = "Nft_test_asset", description = "OVER_9000", amount = 1, reissuable = false, script = None) + withGenerateGetBlockUpdateRange( + GetBlockUpdatesRangeRequest.of(1, 2), + settings = currentSettings.addFeatures(BlockchainFeatures.ReduceNFTFee), + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + ) { d => + d.appendBlock(issueNftTx) + d.appendBlock() + } { getBlockUpdateRange => + val append = getBlockUpdateRange.apply(1).getAppend + checkIssueTx(append, issueNftTx, isNft = true) + } + } + + "BU-166. Return correct data for reissue" in { + val issue = TxHelpers.issue(firstTxParticipant, amount) + val reissue = TxHelpers.reissue(issue.asset, firstTxParticipant, additionalAmount, reissuable = false, customAssetIssueFee) + withGenerateGetBlockUpdateRange( + GetBlockUpdatesRangeRequest.of(1, 3), + settings = currentSettings, + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + ) { d => + d.appendBlock(issue) + d.appendBlock(reissue) + d.appendBlock() + } { getBlockUpdateRange => + val append = getBlockUpdateRange.apply(2).getAppend + checkReissueTx(append, reissue, issue) + } + } + + "BU-158. Return correct data for burn" in { + val issue = TxHelpers.issue(firstTxParticipant, amount) + val burn = TxHelpers.burn(issue.asset, additionalAmount, firstTxParticipant, customAssetIssueFee) + withGenerateGetBlockUpdateRange( + GetBlockUpdatesRangeRequest.of(1, 3), + settings = currentSettings, + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + ) { d => + d.appendBlock(issue) + d.appendBlock(burn) + d.appendBlock() + } { getBlockUpdateRange => + val append = getBlockUpdateRange.apply(2).getAppend + checkBurnTx(append, burn, issue) + } + } + + "Exchange transaction subscription tests" - { + "BU-160. Return correct data for order V3, exchange V2" in { + val order1 = createOrder(OrderType.BUY, firstTxParticipant, Order.V3) + val order2 = createOrder(OrderType.SELL, secondTxParticipant, Order.V3) + val normalizedPrice = order1.price.value * order1.amount.value / 100000000 + val exchangeTx = TxHelpers.exchangeFromOrders(order1, order2, firstTxParticipant, version = TxVersion.V2) + withAddedBlocksAndGetBlockUpdateRange(exchangeTx, GetBlockUpdatesRangeRequest.of(1, 4)) { getBlockUpdateRange => + val append = getBlockUpdateRange.apply(3).getAppend + checkExchangeTx(append, exchangeTx, normalizedPrice, order1.amount.value) + } + } + + "BU-188. Return correct data for order V4, exchange V3" in { + val order1 = createOrder(OrderType.BUY, firstTxParticipant, Order.V4) + val order2 = createOrder(OrderType.SELL, secondTxParticipant, Order.V4) + val normalizedPrice = order1.price.value / 2 / 10000000 + val exchangeTx = TxHelpers.exchangeFromOrders(order1, order2, firstTxParticipant, version = TxVersion.V3) + withAddedBlocksAndGetBlockUpdateRange(exchangeTx, GetBlockUpdatesRangeRequest.of(1, 4)) { getBlockUpdateRange => + val append = getBlockUpdateRange.apply(3).getAppend + checkExchangeTx(append, exchangeTx, normalizedPrice, order1.amount.value) + } + } + } + + "BU-163. Return correct data for lease" in { + val lease = TxHelpers.lease(firstTxParticipant, secondTxParticipantAddress, amount, customFee) + withGenerateGetBlockUpdateRange( + GetBlockUpdatesRangeRequest.of(1, 2), + settings = currentSettings, + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + ) { d => + d.appendBlock(lease) + d.appendBlock() + } { getBlockUpdateRange => + val append = getBlockUpdateRange.apply(1).getAppend + checkLeaseTx(append, lease) + } + } + + "BU-164. Return correct data for lease cancel" in { + val lease = TxHelpers.lease(firstTxParticipant, secondTxParticipantAddress, amount, customFee) + val leaseCancel = TxHelpers.leaseCancel(lease.id.value(), firstTxParticipant, customFee) + withGenerateGetBlockUpdateRange( + GetBlockUpdatesRangeRequest.of(1, 3), + settings = currentSettings, + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + ) { d => + d.appendBlock(lease) + d.appendBlock(leaseCancel) + d.appendBlock() + } { getBlockUpdateRange => + val append = getBlockUpdateRange.apply(2).getAppend + checkLeaseCancelTx(append, leaseCancel, lease) + } + } + + "BU-165. Return correct data for massTransfer" in { + val massTransferFee = fee * 6 + val massTransfer = TxHelpers.massTransfer(firstTxParticipant, recipients, firstToken.asset, massTransferFee) + withGenerateGetBlockUpdateRange( + GetBlockUpdatesRangeRequest.of(1, 3), + settings = currentSettings, + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + ) { d => + d.appendBlock(firstToken) + d.appendBlock(massTransfer) + d.appendBlock() + } { getBlockUpdateRange => + val append = getBlockUpdateRange.apply(2).getAppend + checkForMassTransferTx(append, massTransfer) + } + } + + "BU-159. Return correct data for dataTx" in { + val data = TxHelpers.data(firstTxParticipant, entries, customFee, TxVersion.V2) + withGenerateGetBlockUpdateRange( + GetBlockUpdatesRangeRequest.of(1, 2), + settings = currentSettings, + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + ) { d => + d.appendBlock(data) + d.appendBlock() + } { getBlockUpdateRange => + val append = getBlockUpdateRange.apply(1).getAppend + checkDataTransfer(append, data) + } + } + + "BU-168. Return correct data for setScript" in { + val setScript = TxHelpers.setScript(firstTxParticipant, testScript, customFee) + withGenerateGetBlockUpdateRange( + GetBlockUpdatesRangeRequest.of(1, 2), + settings = currentSettings.addFeatures(BlockchainFeatures.SmartAccounts), + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + ) { d => + d.appendBlock(setScript) + d.appendBlock() + } { getBlockUpdateRange => + val append = getBlockUpdateRange.apply(1).getAppend + checkSetScript(append, setScript) + } + } + + "Return correct data for sponsorFee" - { + val sponsorshipFee = Option.apply(additionalAmount) + val sponsorFee = TxHelpers.sponsor(firstToken.asset, sponsorshipFee, firstTxParticipant) + val sponsorFeeCancel = TxHelpers.sponsor(firstToken.asset, None, firstTxParticipant) + val senderBalanceBeforeSponsorFeeTx = firstTxParticipantBalanceBefore - firstToken.fee.value + val senderBalanceAfterSponsorFeeTx = senderBalanceBeforeSponsorFeeTx - sponsorFee.fee.value + val senderBalanceAfterSponsorFeeCancelTx = senderBalanceAfterSponsorFeeTx - sponsorFee.fee.value + + "BU-169. getBlockUpdateRange sponsorFee" in withGenerateGetBlockUpdateRange( + GetBlockUpdatesRangeRequest.of(1, 3), + settings = currentSettings, + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + ) { d => + d.appendBlock(firstToken) + d.appendBlock(sponsorFee) + d.appendBlock() + } { getBlockUpdateRange => + val append = getBlockUpdateRange.apply(2).getAppend + checkSponsorFee(append, sponsorFee, senderBalanceBeforeSponsorFeeTx, senderBalanceAfterSponsorFeeTx) + } + + "BU-171. getBlockUpdateRange sponsorFee cancel" in withGenerateGetBlockUpdateRange( + GetBlockUpdatesRangeRequest.of(1, 4), + settings = currentSettings, + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + ) { d => + d.appendBlock(firstToken) + d.appendBlock(sponsorFee) + d.appendBlock(sponsorFeeCancel) + d.appendBlock() + } { getBlockUpdateRange => + val append = getBlockUpdateRange.apply(3).getAppend + checkSponsorFee(append, sponsorFeeCancel, senderBalanceAfterSponsorFeeTx, senderBalanceAfterSponsorFeeCancelTx) + } + } + + "BU-167. Return correct data for setAssetScript" in { + val issue = TxHelpers.issue(firstTxParticipant, amount, script = complexScriptBefore) + val setAssetScript = TxHelpers.setAssetScript(firstTxParticipant, issue.asset, complexScriptAfter, 1.waves) + withGenerateGetBlockUpdateRange( + GetBlockUpdatesRangeRequest.of(1, 3), + settings = currentSettings.addFeatures(BlockchainFeatures.SmartAccounts), + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + ) { d => + d.appendBlock(issue) + d.appendBlock(setAssetScript) + d.appendBlock() + } { getBlockUpdateRange => + val append = getBlockUpdateRange.apply(2).getAppend + checkSetAssetScript(append, setAssetScript, issue) + } + } + + "BU-189. Return correct data for UpdateAssetInfo" in { + val newName = "new_name" + val newDescription = "new_description" + val updateAssetInfo = TxHelpers.updateAssetInfo(firstTokenAsset.id, newName, newDescription, firstTxParticipant) + withGenerateGetBlockUpdateRange( + GetBlockUpdatesRangeRequest.of(1, 4), + settings = currentSettings.configure(_.copy(minAssetInfoUpdateInterval = 1)), + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + ) { d => + d.appendBlock(firstToken) + d.appendBlock() + d.appendBlock(updateAssetInfo) + d.appendBlock() + } { getBlockUpdateRange => + val append = getBlockUpdateRange.apply(3).getAppend + checkUpdateAssetInfo(append, updateAssetInfo) + } + } + + "BU-190. Return correct data for EthereumTransfer" in { + val ethereumTransfer: EthereumTransaction = + EthTxGenerator.generateEthTransfer(firstTxParticipantEthereum, secondTxParticipantAddress, amount, secondTokenAsset) + val ethAddress = ethereumTransfer.senderAddress.value() + val transfer = TxHelpers.transfer(secondTxParticipant, ethAddress, secondTokenQuantity, secondTokenAsset) + + withGenerateGetBlockUpdateRange( + GetBlockUpdatesRangeRequest.of(1, 4), + settings = currentSettings.addFeatures(BlockchainFeatures.SmartAccounts), + balances = Seq( + AddrWithBalance(ethAddress, firstTxParticipantBalanceBefore), + AddrWithBalance(secondTxParticipantAddress, secondTxParticipantBalanceBefore) + ) + ) { d => + d.appendKeyBlock() + d.appendBlock(secondToken, transfer) + d.appendBlock(ethereumTransfer) + d.appendBlock() + } { getBlockUpdateRange => + val append = getBlockUpdateRange.apply(3).getAppend + checkEthereumTransfer(append, ethereumTransfer, ethAddress) + } + } + + def withAddedBlocksAndGetBlockUpdateRange(exchangeTx: ExchangeTransaction, height: GetBlockUpdatesRangeRequest)( + f: Seq[PBBlockchainUpdated] => Unit + ): Unit = { + withGenerateGetBlockUpdateRange( + height, + settings = currentSettings, + balances = Seq( + AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore), + AddrWithBalance(secondTxParticipantAddress, secondTxParticipantBalanceBefore) + ) + ) { d => + d.appendBlock(firstToken) + d.appendBlock(secondToken) + d.appendBlock(exchangeTx) + d.appendBlock() + }(f) + } + } +} diff --git a/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesGetBlockUpdatesSpec.scala b/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesGetBlockUpdatesSpec.scala new file mode 100644 index 00000000000..cd8ccd2c6e4 --- /dev/null +++ b/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesGetBlockUpdatesSpec.scala @@ -0,0 +1,308 @@ +package com.wavesplatform.events + +import com.wavesplatform.TestValues.fee +import com.wavesplatform.db.WithState.AddrWithBalance +import com.wavesplatform.events.api.grpc.protobuf.GetBlockUpdateResponse +import com.wavesplatform.features.BlockchainFeatures +import com.wavesplatform.test.* +import com.wavesplatform.test.DomainPresets.* +import com.wavesplatform.transaction.Asset.Waves +import com.wavesplatform.transaction.assets.IssueTransaction +import com.wavesplatform.transaction.assets.exchange.{ExchangeTransaction, Order, OrderType} +import com.wavesplatform.transaction.{EthTxGenerator, EthereumTransaction, TxHelpers, TxVersion} + +class BlockchainUpdatesGetBlockUpdatesSpec extends BlockchainUpdatesTestBase { + "BlockchainUpdates getBlockUpdate tests" - { + "BU-192. Return correct data for alias from getBlockUpdate" in { + val aliasTx = TxHelpers.createAlias("test", firstTxParticipant, fee = customFee) + withGenerateGetBlockUpdate( + height = 2, + settings = currentSettings, + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + )(_.appendBlock(aliasTx)) { getBlockUpdate => + val append = getBlockUpdate.getUpdate.getAppend + checkAlias(append, aliasTx) + } + } + + "BU-207. Return correct data for transfer" in { + val transferTx = TxHelpers.transfer(firstTxParticipant, secondTxParticipantAddress, amount, Waves, customFee) + withGenerateGetBlockUpdate( + height = 2, + settings = currentSettings, + balances = Seq( + AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore), + AddrWithBalance(secondTxParticipant.toAddress, secondTxParticipantBalanceBefore) + ) + )(_.appendBlock(transferTx)) { getBlockUpdate => + val append = getBlockUpdate.getUpdate.getAppend + checkTransferTx(append, transferTx) + } + } + + "BU-196. Return correct data for issue" in { + val issue: IssueTransaction = TxHelpers.issue( + firstTxParticipant, + amount, + decimals = 8, + name = "Test_asset", + description = "description", + customAssetIssueFee, + defaultScript + ) + + withGenerateGetBlockUpdate( + height = 2, + settings = currentSettings, + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + )(_.appendBlock(issue)) { getBlockUpdate => + val append = getBlockUpdate.getUpdate.getAppend + checkIssueTx(append, issue, isNft = false) + } + } + + "BU-197. Return correct data for issue NFT" in { + val issueNftTx = + TxHelpers.issue(firstTxParticipant, name = "Nft_test_asset", description = "OVER_9000", amount = 1, reissuable = false, script = None) + withGenerateGetBlockUpdate( + height = 2, + settings = currentSettings.addFeatures(BlockchainFeatures.ReduceNFTFee), + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + )(_.appendBlock(issueNftTx)) { getBlockUpdate => + val append = getBlockUpdate.getUpdate.getAppend + checkIssueTx(append, issueNftTx, isNft = true) + } + } + + "BU-201. Return correct data for reissue" in { + val issue = TxHelpers.issue(firstTxParticipant, amount) + val reissue = TxHelpers.reissue(issue.asset, firstTxParticipant, additionalAmount, reissuable = false, customAssetIssueFee) + withGenerateGetBlockUpdate( + height = 3, + settings = currentSettings, + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + ) { d => + d.appendBlock(issue) + d.appendBlock(reissue) + } { getBlockUpdate => + val append = getBlockUpdate.getUpdate.getAppend + checkReissueTx(append, reissue, issue) + } + } + + "BU-193. Return correct data for burn" in { + val issue = TxHelpers.issue(firstTxParticipant, amount) + val burn = TxHelpers.burn(issue.asset, additionalAmount, firstTxParticipant, customAssetIssueFee) + withGenerateGetBlockUpdate( + height = 3, + settings = currentSettings, + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + ) { d => + d.appendBlock(issue) + d.appendBlock(burn) + } { getBlockUpdate => + val append = getBlockUpdate.getUpdate.getAppend + checkBurnTx(append, burn, issue) + } + } + + "Exchange transaction subscription tests" - { + "BU-195. Return correct data for order V3, exchange V2" in { + val order1 = createOrder(OrderType.BUY, firstTxParticipant, Order.V3) + val order2 = createOrder(OrderType.SELL, secondTxParticipant, Order.V3) + val normalizedPrice = order1.price.value * order1.amount.value / 100000000 + val exchangeTx = TxHelpers.exchangeFromOrders(order1, order2, firstTxParticipant, version = TxVersion.V2) + withAddedBlocksAndGetBlockUpdate(exchangeTx, height = 4) { getBlockUpdate => + val append = getBlockUpdate.getUpdate.getAppend + checkExchangeTx(append, exchangeTx, normalizedPrice, order1.amount.value) + } + } + + "BU-223. Return correct data for order V4, exchange V3" in { + val order1 = createOrder(OrderType.BUY, firstTxParticipant, Order.V4) + val order2 = createOrder(OrderType.SELL, secondTxParticipant, Order.V4) + val normalizedPrice = order1.price.value / 2 / 10000000 + val exchangeTx = TxHelpers.exchangeFromOrders(order1, order2, firstTxParticipant, version = TxVersion.V3) + withAddedBlocksAndGetBlockUpdate(exchangeTx, height = 4) { getBlockUpdate => + val append = getBlockUpdate.getUpdate.getAppend + checkExchangeTx(append, exchangeTx, normalizedPrice, order1.amount.value) + } + } + } + + "BU-198. Return correct data for lease" in { + val lease = TxHelpers.lease(firstTxParticipant, secondTxParticipantAddress, amount, customFee) + withGenerateGetBlockUpdate( + height = 2, + settings = currentSettings, + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + )(_.appendBlock(lease)) { getBlockUpdate => + val append = getBlockUpdate.getUpdate.getAppend + checkLeaseTx(append, lease) + } + } + + "BU-199. Return correct data for lease cancel" in { + val lease = TxHelpers.lease(firstTxParticipant, secondTxParticipantAddress, amount, customFee) + val leaseCancel = TxHelpers.leaseCancel(lease.id.value(), firstTxParticipant, customFee) + withGenerateGetBlockUpdate( + height = 3, + settings = currentSettings, + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + ) { d => + d.appendBlock(lease) + d.appendBlock(leaseCancel) + } { getBlockUpdate => + val append = getBlockUpdate.getUpdate.getAppend + checkLeaseCancelTx(append, leaseCancel, lease) + } + } + + "BU-200. Return correct data for massTransfer" in { + val massTransferFee = fee * 6 + val massTransfer = TxHelpers.massTransfer(firstTxParticipant, recipients, firstToken.asset, massTransferFee) + + withGenerateGetBlockUpdate( + height = 3, + settings = currentSettings, + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + ) { d => + d.appendBlock(firstToken) + d.appendBlock(massTransfer) + } { getBlockUpdate => + val append = getBlockUpdate.getUpdate.getAppend + checkForMassTransferTx(append, massTransfer) + } + } + + "BU-194. Return correct data for dataTx" in { + val data = TxHelpers.data(firstTxParticipant, entries, customFee, TxVersion.V2) + withGenerateGetBlockUpdate( + height = 2, + settings = currentSettings, + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + )(_.appendBlock(data)) { getBlockUpdate => + val append = getBlockUpdate.getUpdate.getAppend + checkDataTransfer(append, data) + } + } + + "BU-203. Return correct data for setScript" in { + val setScript = TxHelpers.setScript(firstTxParticipant, testScript, customFee) + withGenerateGetBlockUpdate( + height = 2, + settings = currentSettings.addFeatures(BlockchainFeatures.SmartAccounts), + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + )(_.appendBlock(setScript)) { getBlockUpdate => + val append = getBlockUpdate.getUpdate.getAppend + checkSetScript(append, setScript) + } + } + + "Return correct data for sponsorFee" - { + val sponsorshipFee = Option.apply(additionalAmount) + val sponsorFee = TxHelpers.sponsor(firstToken.asset, sponsorshipFee, firstTxParticipant) + val sponsorFeeCancel = TxHelpers.sponsor(firstToken.asset, None, firstTxParticipant) + val senderBalanceBeforeSponsorFeeTx = firstTxParticipantBalanceBefore - firstToken.fee.value + val senderBalanceAfterSponsorFeeTx = senderBalanceBeforeSponsorFeeTx - sponsorFee.fee.value + val senderBalanceAfterSponsorFeeCancelTx = senderBalanceAfterSponsorFeeTx - sponsorFee.fee.value + + "BU-204. getBlockUpdate sponsorFee" in withGenerateGetBlockUpdate( + height = 3, + settings = currentSettings, + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + ) { d => + d.appendBlock(firstToken) + d.appendBlock(sponsorFee) + } { getBlockUpdate => + val append = getBlockUpdate.getUpdate.getAppend + checkSponsorFee(append, sponsorFee, senderBalanceBeforeSponsorFeeTx, senderBalanceAfterSponsorFeeTx) + } + + "BU-206. getBlockUpdate sponsorFee cancel" in withGenerateGetBlockUpdate( + height = 4, + settings = currentSettings, + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + ) { d => + d.appendBlock(firstToken) + d.appendBlock(sponsorFee) + d.appendBlock(sponsorFeeCancel) + } { getBlockUpdate => + val append = getBlockUpdate.getUpdate.getAppend + checkSponsorFee(append, sponsorFeeCancel, senderBalanceAfterSponsorFeeTx, senderBalanceAfterSponsorFeeCancelTx) + } + } + + "BU-202. Return correct data for setAssetScript" in { + val issue = TxHelpers.issue(firstTxParticipant, amount, script = complexScriptBefore) + val setAssetScript = TxHelpers.setAssetScript(firstTxParticipant, issue.asset, complexScriptAfter, 1.waves) + withGenerateGetBlockUpdate( + height = 3, + settings = currentSettings.addFeatures(BlockchainFeatures.SmartAccounts), + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + ) { d => + d.appendBlock(issue) + d.appendBlock(setAssetScript) + } { getBlockUpdate => + val append = getBlockUpdate.getUpdate.getAppend + checkSetAssetScript(append, setAssetScript, issue) + } + } + + "BU-224. Return correct data for UpdateAssetInfo" in { + val newName = "new_name" + val newDescription = "new_description" + val updateAssetInfo = TxHelpers.updateAssetInfo(firstTokenAsset.id, newName, newDescription, firstTxParticipant) + withGenerateGetBlockUpdate( + height = 4, + settings = currentSettings.configure(_.copy(minAssetInfoUpdateInterval = 1)), + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + ) { d => + d.appendBlock(firstToken) + d.appendBlock() + d.appendBlock(updateAssetInfo) + } { getBlockUpdate => + val append = getBlockUpdate.getUpdate.getAppend + checkUpdateAssetInfo(append, updateAssetInfo) + } + } + + "BU-225. Return correct data for EthereumTransfer" in { + val ethereumTransfer: EthereumTransaction = + EthTxGenerator.generateEthTransfer(firstTxParticipantEthereum, secondTxParticipantAddress, amount, secondTokenAsset) + val ethAddress = ethereumTransfer.senderAddress.value() + val transfer = TxHelpers.transfer(secondTxParticipant, ethAddress, secondTokenQuantity, secondTokenAsset) + + withGenerateGetBlockUpdate( + height = 4, + settings = currentSettings.addFeatures(BlockchainFeatures.SmartAccounts), + balances = Seq( + AddrWithBalance(ethAddress, firstTxParticipantBalanceBefore), + AddrWithBalance(secondTxParticipantAddress, secondTxParticipantBalanceBefore) + ) + ) { d => + d.appendKeyBlock() + d.appendBlock(secondToken, transfer) + d.appendBlock(ethereumTransfer) + } { getBlockUpdate => + val append = getBlockUpdate.getUpdate.getAppend + checkEthereumTransfer(append, ethereumTransfer, ethAddress) + } + } + + def withAddedBlocksAndGetBlockUpdate(exchangeTx: ExchangeTransaction, height: Int)(f: GetBlockUpdateResponse => Unit): Unit = { + withGenerateGetBlockUpdate( + height, + settings = currentSettings, + balances = Seq( + AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore), + AddrWithBalance(secondTxParticipantAddress, secondTxParticipantBalanceBefore) + ) + ) { d => + d.appendBlock(firstToken) + d.appendBlock(secondToken) + d.appendBlock(exchangeTx) + }(f) + } + } +} diff --git a/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesInvokeTxSpec.scala b/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesInvokeTxSpec.scala new file mode 100644 index 00000000000..a9e8840699d --- /dev/null +++ b/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesInvokeTxSpec.scala @@ -0,0 +1,222 @@ +package com.wavesplatform.events + +import com.wavesplatform.TestValues.fee +import com.wavesplatform.account.{Address, SeedKeyPair} +import com.wavesplatform.common.state.ByteStr +import com.wavesplatform.common.utils.* +import com.wavesplatform.db.WithState.AddrWithBalance +import com.wavesplatform.events.fixtures.BlockchainUpdateGrpcMethod.* +import com.wavesplatform.events.fixtures.InvokeWavesTxCheckers.checkInvokeDoubleNestedBlockchainUpdates +import com.wavesplatform.events.fixtures.PrepareInvokeTestData.* +import com.wavesplatform.events.fixtures.WavesTxChecks.* +import com.wavesplatform.lang.v1.compiler.Terms.{CONST_BYTESTR, CONST_LONG, CONST_STRING, EXPR} +import com.wavesplatform.events.protobuf.BlockchainUpdated.Append +import com.wavesplatform.test.NumericExt +import com.wavesplatform.transaction.Asset.Waves +import com.wavesplatform.transaction.{Asset, TxHelpers, TxNonNegativeAmount} +import com.wavesplatform.transaction.TxHelpers.secondAddress +import com.wavesplatform.transaction.transfer.MassTransferTransaction.ParsedTransfer +import com.wavesplatform.transaction.assets.IssueTransaction +import com.wavesplatform.transaction.smart.InvokeScriptTransaction + +class BlockchainUpdatesInvokeTxSpec extends BlockchainUpdatesTestBase { + "Simple invoke transaction" - { + val issue = TxHelpers.issue(firstTxParticipant) + val asset: Asset = issue.asset + val assetByteStr = CONST_BYTESTR(asset.compatId.get).explicitGet() + val addressByteStr = CONST_BYTESTR(ByteStr.apply(secondTxParticipantAddress.bytes)).explicitGet() + val args: Seq[EXPR] = Seq(assetByteStr, addressByteStr) + val invoke = TxHelpers.invoke(firstTxParticipantAddress, Some(invokeFunctionName), args, Seq.empty, secondTxParticipant, fee = 100500000L) + val issuerAssetBalanceAfterTx: Long = issue.quantity.value - burnNum - scriptTransferAssetNum + reissueNum + val senderWavesBalanceAfterTx: Long = secondTxParticipantBalanceBefore - invoke.fee.value + scriptTransferUnitNum + val issuerBalanceBeforeInvoke: Long = firstTxParticipantBalanceBefore - issue.fee.value - fee + val issuerBalanceAfterInvoke: Long = issuerBalanceBeforeInvoke - scriptTransferUnitNum + val balances = Seq( + AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore), + AddrWithBalance(secondTxParticipantAddress, secondTxParticipantBalanceBefore) + ) + val expectBalanceMap = Map( + (secondTxParticipantAddress, Waves) -> (secondTxParticipantBalanceBefore, senderWavesBalanceAfterTx), + (secondTxParticipantAddress, asset) -> (0L, scriptTransferAssetNum), + (firstTxParticipantAddress, Waves) -> (issuerBalanceBeforeInvoke, issuerBalanceAfterInvoke), + (firstTxParticipantAddress, asset) -> (issue.quantity.value, issuerAssetBalanceAfterTx) + ) + + "BU-31. Invoke have to return correct data for subscribe" in { + testInvoke(issue, invoke, balances)( + Subscribe, + checkFunction = append => { + val invokeScriptMetadata = append.transactionsMetadata.head.getInvokeScript + checkInvokeBase(append, invoke) + checkGeneralInvoke(append, issuerAssetBalanceAfterTx, invoke, issue, invokeScriptMetadata, expectBalanceMap) + } + ) + } + + "BU-208. Invoke have to return correct data for getBlockUpdate" in { + testInvoke(issue, invoke, balances)( + GetBlockUpdate, + checkFunction = append => { + val invokeScriptMetadata = append.transactionsMetadata.head.getInvokeScript + checkInvokeBase(append, invoke) + checkGeneralInvoke(append, issuerAssetBalanceAfterTx, invoke, issue, invokeScriptMetadata, expectBalanceMap) + } + ) + } + + "BU-173. Invoke have to return correct data for getBlockUpdateRange" in { + testInvoke(issue, invoke, balances)( + GetBlockUpdateRange, + checkFunction = append => { + val invokeScriptMetadata = append.transactionsMetadata.head.getInvokeScript + checkInvokeBase(append, invoke) + checkGeneralInvoke(append, issuerAssetBalanceAfterTx, invoke, issue, invokeScriptMetadata, expectBalanceMap) + } + ) + } + } + + "Double nesting call tests" - { + val assetDappAccount: SeedKeyPair = TxHelpers.signer(4) + val assetDappAddress: Address = assetDappAccount.toAddress + val invokerDappAccount: SeedKeyPair = TxHelpers.signer(5) + val invokerDappAddress: Address = invokerDappAccount.toAddress + val issue: IssueTransaction = TxHelpers.issue(assetDappAccount) + val asset: Asset = issue.asset + val issueAssetFee = issue.fee.value + val massTx = TxHelpers.massTransfer( + assetDappAccount, + Seq( + ParsedTransfer(firstTxParticipantAddress, TxNonNegativeAmount.unsafeFrom(amount)), + ParsedTransfer(secondAddress, TxNonNegativeAmount.unsafeFrom(amount)), + ParsedTransfer(invokerDappAddress, TxNonNegativeAmount.unsafeFrom(amount)) + ), + asset, + fee = 500000 + ) + val args: Seq[EXPR] = + Seq( + CONST_BYTESTR(ByteStr.apply(secondAddress.bytes)).explicitGet(), + CONST_BYTESTR(ByteStr.apply(assetDappAddress.bytes)).explicitGet(), + CONST_LONG(scriptTransferUnitNum), + CONST_STRING(bar).explicitGet(), + CONST_BYTESTR(asset.compatId.get).explicitGet() + ) + val invoke = TxHelpers.invoke(firstTxParticipantAddress, Some(foo), args, Seq.empty, invokerDappAccount, fee = 100500000L) + val invokerDappBalance: Long = 4.waves + val secondAddressBalance: Long = 8.waves + val assetDappBalance: Long = 12.waves + val secondAddressAssetBalanceForAll: Long = amount - scriptTransferAssetNum + paymentNum + val dAppAddressAssetBalanceForCaller: Long = amount + scriptTransferAssetNum - paymentNum + val invokerDappAddressAssetBalanceForOriginCaller: Long = amount + scriptTransferAssetNum + val dAppAddressAssetBalanceForOriginCaller: Long = amount - paymentNum + val secondAddressWavesBalanceBefore: Long = secondAddressBalance - fee + val secondAddressWavesBalanceAfter: Long = secondAddressWavesBalanceBefore + scriptTransferUnitNum + val assetDappAddressWavesBalanceBefore: Long = assetDappBalance - issueAssetFee - massTx.fee.value - fee + val assetDappAddressWavesBalanceAfter: Long = assetDappAddressWavesBalanceBefore - scriptTransferUnitNum + val invokerDappAddressWavesBalance: Long = invokerDappBalance - invoke.fee.value + val balancesSeq = Seq( + AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore), + AddrWithBalance(secondAddress, secondAddressBalance), + AddrWithBalance(invokerDappAddress, invokerDappBalance), + AddrWithBalance(assetDappAddress, assetDappBalance) + ) + val callerBalancesMap = Map( + (secondAddress, Waves) -> (secondAddressWavesBalanceBefore, secondAddressWavesBalanceAfter), + (secondAddress, asset) -> (amount, secondAddressAssetBalanceForAll), + (firstTxParticipantAddress, asset) -> (amount, dAppAddressAssetBalanceForCaller), + (assetDappAddress, Waves) -> (assetDappAddressWavesBalanceBefore, assetDappAddressWavesBalanceAfter), + (invokerDappAddress, Waves) -> (invokerDappBalance, invokerDappAddressWavesBalance) + ) + val originalCallerBalancesMap = Map( + (invokerDappAddress, asset) -> (amount, invokerDappAddressAssetBalanceForOriginCaller), + (secondAddress, asset) -> (amount, secondAddressAssetBalanceForAll), + (firstTxParticipantAddress, asset) -> (amount, dAppAddressAssetBalanceForOriginCaller), + (assetDappAddress, Waves) -> (assetDappAddressWavesBalanceBefore, assetDappAddressWavesBalanceAfter), + (invokerDappAddress, Waves) -> (invokerDappBalance, invokerDappAddressWavesBalance + scriptTransferUnitNum) + ) + + "BU-77. doubles nested i.caller. Invoke have to return correct data for subscribe" in { + doubleNestedInvokeTest(assetDappAccount, balancesSeq, issue, invoke, massTx, caller, Subscribe) { append => + val invokeScriptMetadata = append.transactionsMetadata.head.getInvokeScript + checkInvokeBase(append, invoke) + checkInvokeDoubleNestedBlockchainUpdates( + append, + invokeScriptMetadata, + assetDappAddress, + firstTxParticipantAddress, secondAddress, + issue, + callerBalancesMap + ) + } + } + + "BU-210. doubles nested i.caller. Invoke have to return correct data for getBlockUpdate" in { + doubleNestedInvokeTest(assetDappAccount, balancesSeq, issue, invoke, massTx, caller, GetBlockUpdate) { append => + val invokeScriptMetadata = append.transactionsMetadata.head.getInvokeScript + checkInvokeBase(append, invoke) + checkInvokeDoubleNestedBlockchainUpdates( + append, + invokeScriptMetadata, + assetDappAddress, + firstTxParticipantAddress, secondAddress, + issue, + callerBalancesMap + ) + } + } + + "BU-175. doubles nested i.caller. Invoke have to return correct data for getBlockUpdateRange" in { + doubleNestedInvokeTest(assetDappAccount, balancesSeq, issue, invoke, massTx, caller, GetBlockUpdateRange) { append => + val invokeScriptMetadata = append.transactionsMetadata.head.getInvokeScript + checkInvokeBase(append, invoke) + checkInvokeDoubleNestedBlockchainUpdates( + append, + invokeScriptMetadata, + assetDappAddress, + firstTxParticipantAddress, secondAddress, + issue, + callerBalancesMap + ) + } + } + + "BU-39. double nested i.originCaller. Invoke have to return correct data for subscribe" in { + doubleNestedInvokeTest(assetDappAccount, balancesSeq, issue, invoke, massTx, originCaller, Subscribe) { append => + val invokeScriptMetadata = append.transactionsMetadata.head.getInvokeScript + checkInvokeBase(append, invoke) + checkInvokeDoubleNestedBlockchainUpdates( + append, + invokeScriptMetadata, + assetDappAddress, + invokerDappAddress, + invokerDappAddress, + issue, + originalCallerBalancesMap + ) + } + } + + "BU-209. doubles nested i.originCaller. Invoke have to return correct data for getBlockUpdate" in { + doubleNestedInvokeTest(assetDappAccount, balancesSeq, issue, invoke, massTx, originCaller, GetBlockUpdate) { append => + val invokeScriptMetadata = append.transactionsMetadata.head.getInvokeScript + checkInvokeBase(append, invoke) + checkInvokeDoubleNestedBlockchainUpdates(append, invokeScriptMetadata, assetDappAddress, invokerDappAddress, invokerDappAddress, issue, originalCallerBalancesMap) + } + } + + "BU-174. doubles nested i.originCaller. Invoke have to return correct data for getBlockUpdateRange" in { + doubleNestedInvokeTest(assetDappAccount, balancesSeq, issue, invoke, massTx, originCaller, GetBlockUpdateRange) { append => + val invokeScriptMetadata = append.transactionsMetadata.head.getInvokeScript + checkInvokeBase(append, invoke) + checkInvokeDoubleNestedBlockchainUpdates(append, invokeScriptMetadata, assetDappAddress, invokerDappAddress, invokerDappAddress, issue, originalCallerBalancesMap) + } + } + } + + def checkInvokeBase(append: Append, invoke: InvokeScriptTransaction): Unit = { + val transactionMetadata = append.transactionsMetadata.head + checkInvokeTransaction(append.transactionIds.head, append.transactionAt(0), invoke, firstTxParticipantAddress.publicKeyHash) + checkInvokeBaseTransactionMetadata(transactionMetadata, invoke) + } +} diff --git a/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesSpec.scala b/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesSpec.scala index 51ea325a816..3d828e80253 100644 --- a/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesSpec.scala +++ b/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesSpec.scala @@ -11,6 +11,7 @@ import com.wavesplatform.crypto.DigestLength import com.wavesplatform.db.InterferableDB import com.wavesplatform.events.FakeObserver.* import com.wavesplatform.events.StateUpdate.LeaseUpdate.LeaseStatus +import com.wavesplatform.utils.byteStrOrdering import com.wavesplatform.events.StateUpdate.{ AssetInfo, AssetStateUpdate, @@ -419,7 +420,7 @@ class BlockchainUpdatesSpec extends FreeSpec with WithBUDomain with ScalaFutures (1 to blocksCount + 1).foreach(_ => d.appendBlock()) val result = Await - .result(r.getBlockUpdatesRange(GetBlockUpdatesRangeRequest(1, blocksCount)), Duration.Inf) + .result(r.getBlockUpdatesRange(GetBlockUpdatesRangeRequest(1, blocksCount)), 1.minute) .updates .map(_.update.append.map(_.getBlock.vrf.toByteStr).filterNot(_.isEmpty)) @@ -469,13 +470,13 @@ class BlockchainUpdatesSpec extends FreeSpec with WithBUDomain with ScalaFutures val reward = 600000000 val genesisAmount = Constants.TotalWaves * Constants.UnitsInWave + reward val genesis = results.head.getAppend.transactionStateUpdates.head.balances.head - genesis.address.toAddress shouldBe TxHelpers.defaultAddress + genesis.address.toAddress() shouldBe TxHelpers.defaultAddress genesis.getAmountAfter.amount shouldBe genesisAmount genesis.amountBefore shouldBe reward genesis.getAmountAfter.assetId shouldBe empty val payment = results.last.getAppend.transactionStateUpdates.last.balances.find { bu => - bu.address.toAddress == TxHelpers.secondAddress + bu.address.toAddress() == TxHelpers.secondAddress }.get payment.getAmountAfter.amount shouldBe 100 @@ -1214,7 +1215,7 @@ class BlockchainUpdatesSpec extends FreeSpec with WithBUDomain with ScalaFutures Await .result( repo.getBlockUpdate(GetBlockUpdateRequest(height)), - Duration.Inf + 1.minute ) .getUpdate .update diff --git a/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesSubscribeInvokeTxSpec.scala b/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesSubscribeInvokeTxSpec.scala index 64f179d5151..171f1ebdf02 100644 --- a/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesSubscribeInvokeTxSpec.scala +++ b/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesSubscribeInvokeTxSpec.scala @@ -70,8 +70,8 @@ class BlockchainUpdatesSubscribeInvokeTxSpec extends FreeSpec with WithBUDomain d.appendMicroBlock(invoke) } { updates => val append = updates(3).append - val transactionMetadata = append.transactionsMetadata - val invokeScript = transactionMetadata.head.getInvokeScript + val transactionMetadata = append.transactionsMetadata.head + val invokeScript = transactionMetadata.getInvokeScript val arguments = invokeScript.arguments val result = invokeScript.result.get val dataEntries = append.transactionStateUpdates.head.dataEntries @@ -178,7 +178,7 @@ class BlockchainUpdatesSubscribeInvokeTxSpec extends FreeSpec with WithBUDomain val minerBalanceBeforeInvoke = 2 * 6.waves + txsBeforeInvoke.map(_.fee.value).sum * 2 / 5 val minerBalanceAfterInvoke = minerBalanceBeforeInvoke + invoke.fee.value * 2 / 5 - addedBlocksAndSubscribe(mainDAppTx, nestedDAppTx, doubleNestedDAppTx) { updates => + withAddedBlocksAndSubscribe(mainDAppTx, nestedDAppTx, doubleNestedDAppTx) { updates => val actualDataEntries = updates(2).getAppend.transactionStateUpdates.head.dataEntries checkInvokeDoubleNestedBlockchainUpdates(updates(2).getAppend, dAppAddress, secondAddress) checkBalances( @@ -213,7 +213,7 @@ class BlockchainUpdatesSubscribeInvokeTxSpec extends FreeSpec with WithBUDomain val minerBalanceBeforeInvoke = 2 * 6.waves + txsBeforeInvoke.map(_.fee.value).sum * 2 / 5 val minerBalanceAfterInvoke = minerBalanceBeforeInvoke + invoke.fee.value * 2 / 5 - addedBlocksAndSubscribe(mainDAppTx, nestedDAppTx, doubleNestedDAppTx) { updates => + withAddedBlocksAndSubscribe(mainDAppTx, nestedDAppTx, doubleNestedDAppTx) { updates => val actualDataEntries = updates(2).getAppend.transactionStateUpdates.head.dataEntries checkInvokeDoubleNestedBlockchainUpdates(updates(2).getAppend, invokerDappAddress, invokerDappAddress) checkBalances( @@ -232,7 +232,7 @@ class BlockchainUpdatesSubscribeInvokeTxSpec extends FreeSpec with WithBUDomain } } - def addedBlocksAndSubscribe( + def withAddedBlocksAndSubscribe( mainDAppTx: SetScriptTransaction, nestedDAppTx: SetScriptTransaction, doubleNestedDAppTx: SetScriptTransaction @@ -271,7 +271,7 @@ class BlockchainUpdatesSubscribeInvokeTxSpec extends FreeSpec with WithBUDomain arguments(4).value.binaryValue.get.toByteArray ) checkInvokeTransaction(append.transactionIds.head, append.transactionAt(0), invoke, dAppAddress.publicKeyHash) - checkInvokeBaseTransactionMetadata(append.transactionsMetadata, invoke) + checkInvokeBaseTransactionMetadata(append.transactionsMetadata.head, invoke) checkArguments(expectedValues, actualArguments) checkInvokeScriptResultData(result.data, actualData) checkInvokeScriptBaseInvokes(invokes, secondAddress, bar) diff --git a/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesSubscribeSpec.scala b/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesSubscribeSpec.scala index 80677f4efd6..36b47da26c8 100644 --- a/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesSubscribeSpec.scala +++ b/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesSubscribeSpec.scala @@ -1,673 +1,292 @@ package com.wavesplatform.events import com.wavesplatform.TestValues.fee -import com.wavesplatform.account.{Address, SeedKeyPair} -import com.wavesplatform.common.state.ByteStr -import com.wavesplatform.common.utils.EitherExt2 import com.wavesplatform.db.WithState.AddrWithBalance -import com.wavesplatform.events.StateUpdate.LeaseUpdate.LeaseStatus -import com.wavesplatform.events.fixtures.WavesTxChecks.{checkExchange, *} -import com.wavesplatform.events.protobuf.BlockchainUpdated as PBBlockchainUpdated -import com.wavesplatform.events.protobuf.BlockchainUpdated.Append import com.wavesplatform.features.BlockchainFeatures -import com.wavesplatform.lang.script.Script -import com.wavesplatform.settings.WavesSettings -import com.wavesplatform.state.{BinaryDataEntry, BooleanDataEntry, IntegerDataEntry, StringDataEntry} import com.wavesplatform.test.* import com.wavesplatform.test.DomainPresets.* import com.wavesplatform.transaction.Asset.Waves -import com.wavesplatform.transaction.TxHelpers.defaultAddress import com.wavesplatform.transaction.assets.IssueTransaction import com.wavesplatform.transaction.assets.exchange.{ExchangeTransaction, Order, OrderType} -import com.wavesplatform.transaction.{Asset, TxHelpers, TxVersion} -import org.scalatest.concurrent.ScalaFutures - -class BlockchainUpdatesSubscribeSpec extends FreeSpec with WithBUDomain with ScalaFutures { - val currentSettings: WavesSettings = DomainPresets.RideV6 - val customFee: Long = 5234000L - val customAssetIssueFee = 234560000L - val sender: SeedKeyPair = TxHelpers.signer(12) - val senderAddress: Address = sender.toAddress - val senderBalanceBefore: Long = 20.waves - val testScript: Script = TxHelpers.script(s"""{-# STDLIB_VERSION 6 #-} - |{-# CONTENT_TYPE DAPP #-} - |{-# SCRIPT_TYPE ACCOUNT #-} - | - |@Verifier(tx) - |func verify () = match(tx) { - | case _ => - | if ( - | ${(1 to 9).map(_ => "sigVerify(base58'', base58'', base58'')").mkString(" || \n")} - | ) then true else true - |}""".stripMargin) +import com.wavesplatform.transaction.{EthTxGenerator, EthereumTransaction, TxHelpers, TxVersion} +import com.wavesplatform.events.protobuf.BlockchainUpdated as PBBlockchainUpdated +class BlockchainUpdatesSubscribeSpec extends BlockchainUpdatesTestBase { "BlockchainUpdates subscribe tests" - { "BU-1. Return correct data for alias" in { - val aliasTx = TxHelpers.createAlias("test", sender, fee = customFee) - val senderBalanceAfterTx: Long = senderBalanceBefore - aliasTx.fee.value - + val aliasTx = TxHelpers.createAlias("test", firstTxParticipant, fee = customFee) withGenerateSubscription( settings = currentSettings, - balances = Seq(AddrWithBalance(senderAddress, senderBalanceBefore)) + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) )(_.appendMicroBlock(aliasTx)) { updates => val append = updates(1).append - checkCreateAlias(append.transactionIds.head, append.transactionAt(0), aliasTx) - checkBalances( - append.transactionStateUpdates.head.balances, - Map( - (senderAddress, Waves) -> (senderBalanceBefore, senderBalanceAfterTx), - (defaultAddress, Waves) -> (6.waves, 6.waves + customFee * 2 / 5) - ) - ) + checkAlias(append, aliasTx) } } "BU-28. Return correct data for transfer" in { - val amount: Long = 1000L - val transferSenderBalanceAfter = senderBalanceBefore - customFee - amount - val transferRecipient = TxHelpers.signer(123) - val recipientAddress = transferRecipient.toAddress - val transferRecipientBalanceBefore = 1.waves - val transferRecipientBalanceAfter = transferRecipientBalanceBefore + amount - val transferTx = TxHelpers.transfer(sender, recipientAddress, amount, Waves, customFee) - + val transferTx = TxHelpers.transfer(firstTxParticipant, secondTxParticipantAddress, amount, Waves, customFee) withGenerateSubscription( settings = currentSettings, balances = Seq( - AddrWithBalance(senderAddress, senderBalanceBefore), - AddrWithBalance(transferRecipient.toAddress, transferRecipientBalanceBefore) + AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore), + AddrWithBalance(secondTxParticipant.toAddress, secondTxParticipantBalanceBefore) ) )(_.appendMicroBlock(transferTx)) { updates => val append = updates(1).append - checkTransfer(append.transactionIds.head, append.transactionAt(0), transferTx, recipientAddress.publicKeyHash) - checkBalances( - append.transactionStateUpdates.head.balances, - Map( - (senderAddress, Waves) -> (senderBalanceBefore, transferSenderBalanceAfter), - (recipientAddress, Waves) -> (transferRecipientBalanceBefore, transferRecipientBalanceAfter), - (defaultAddress, Waves) -> (6.waves, 6.waves + customFee * 2 / 5) - ) - ) - } - } - - "Return correct data for several transfers to miner" in { - val amount = 1000 - val recipient = TxHelpers.defaultAddress - val fee1 = customFee - val fee2 = customFee + 12345 - val fee3 = customFee + 56789 - val transferTx1 = TxHelpers.transfer(sender, recipient, amount, Waves, fee1) - val transferTx2 = TxHelpers.transfer(sender, recipient, amount, Waves, fee2) - val transferTx3 = TxHelpers.transfer(sender, recipient, amount, Waves, fee3) - - withGenerateSubscription( - settings = currentSettings, - balances = Seq( - AddrWithBalance(senderAddress, senderBalanceBefore) - ) - )(_.appendMicroBlock(transferTx1, transferTx2, transferTx3)) { updates => - val append = updates(1).append - checkTransfer(append.transactionIds(0), append.transactionAt(0), transferTx1, recipient.publicKeyHash) - checkTransfer(append.transactionIds(1), append.transactionAt(1), transferTx2, recipient.publicKeyHash) - checkTransfer(append.transactionIds(2), append.transactionAt(2), transferTx3, recipient.publicKeyHash) - - val reward = 6.waves - checkBalances( - append.transactionStateUpdates(0).balances, - Map( - (senderAddress, Waves) -> (senderBalanceBefore, senderBalanceBefore - (fee1 + amount)), - (recipient, Waves) -> (reward, reward + amount + fee1 / 5 * 2) - ) - ) - checkBalances( - append.transactionStateUpdates(1).balances, - Map( - (senderAddress, Waves) -> (senderBalanceBefore - (fee1 + amount), senderBalanceBefore - (fee1 + fee2 + 2 * amount)), - (recipient, Waves) -> (reward + amount + fee1 / 5 * 2, reward + 2 * amount + (fee1 + fee2) / 5 * 2) - ) - ) - checkBalances( - append.transactionStateUpdates(2).balances, - Map( - (senderAddress, Waves) -> (senderBalanceBefore - (fee1 + fee2 + 2 * amount), senderBalanceBefore - (fee1 + fee2 + fee3 + 3 * amount)), - (recipient, Waves) -> (reward + 2 * amount + (fee1 + fee2) / 5 * 2, reward + 3 * amount + (fee1 + fee2 + fee3) / 5 * 2) - ) - ) + checkTransferTx(append, transferTx) } } "BU-9. Return correct data for issue" in { - val script = Option(TxHelpers.script("true")) - val amount: Long = 599000 - val decimals: Byte = 8 - val name: String = "Test_asset" - val description: String = name + "|_|_|_|_|_|" + 5380000 - val issue = TxHelpers.issue(sender, amount, decimals, name, description, customAssetIssueFee, script) - val issueScript = issue.script.get.bytes.value().arr - + val issue: IssueTransaction = TxHelpers.issue( + firstTxParticipant, + amount, + decimals = 8, + name = "Test_asset", + description = "description", + customAssetIssueFee, + defaultScript + ) withGenerateSubscription( settings = currentSettings, - balances = Seq(AddrWithBalance(senderAddress, senderBalanceBefore)) + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) )(_.appendMicroBlock(issue)) { updates => - val append = updates(1).append - val assetDetails = append.transactionStateUpdates.head.assets.head - - checkIssue(append.transactionIds.head, append.transactionAt(0), issue) - checkBalances( - append.transactionStateUpdates.head.balances, - Map( - (senderAddress, Waves) -> (senderBalanceBefore, senderBalanceBefore - customAssetIssueFee), - (senderAddress, issue.asset) -> (0, amount), - (defaultAddress, Waves) -> (6.waves, 6.waves + customAssetIssueFee * 2 / 5) - ) - ) - checkAssetsStateUpdates(assetDetails.after, issue, isNft = false, issue.quantity.value) - checkAssetsScriptStateUpdates(assetDetails.after.get.scriptInfo, issueScript) + val append = updates(1).append + checkIssueTx(append, issue, isNft = false) } } "BU-11. Return correct data for issue NFT" in { - val name: String = "Nft_test_asset" - val description: String = name + "_OVER_9000" - val issueNftTx = IssueTransaction - .selfSigned( - TxVersion.V3, - sender, - name, - description, - quantity = 1, - decimals = 0, - reissuable = false, - script = None, - 0.001.waves, - System.currentTimeMillis() - ) - .explicitGet() - + val issueNftTx = + TxHelpers.issue(firstTxParticipant, name = "Nft_test_asset", description = "OVER_9000", amount = 1, reissuable = false, script = None) withGenerateSubscription( settings = currentSettings.addFeatures(BlockchainFeatures.ReduceNFTFee), - balances = Seq(AddrWithBalance(senderAddress, senderBalanceBefore)) + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) )(_.appendMicroBlock(issueNftTx)) { updates => - val append = updates(1).append - val assetDetails = append.transactionStateUpdates.head.assets.head - - checkIssue(append.transactionIds.head, append.transactionAt(0), issueNftTx) - checkBalances( - append.transactionStateUpdates.head.balances, - Map( - (senderAddress, Waves) -> (senderBalanceBefore, senderBalanceBefore - 0.001.waves), - (senderAddress, issueNftTx.asset) -> (0, 1), - (defaultAddress, Waves) -> (6.waves, 6.waves + issueNftTx.fee.value * 2 / 5) - ) - ) - checkAssetsStateUpdates(assetDetails.after, issueNftTx, isNft = true, issueNftTx.quantity.value) + val append = updates(1).append + checkIssueTx(append, issueNftTx, isNft = true) } } "BU-19. Return correct data for reissue" in { - val amount: Long = 9000000 - val amountReissue: Long = 7500000 - val issue = TxHelpers.issue(sender, amount) - val reissueTx = TxHelpers.reissue(issue.asset, sender, amountReissue, reissuable = false, customAssetIssueFee) - val quantityAfterReissue = amount + amountReissue - val senderBalanceBeforeReissue = senderBalanceBefore - issue.fee.value - val senderBalanceAfterReissue = senderBalanceBeforeReissue - reissueTx.fee.value - + val issue = TxHelpers.issue(firstTxParticipant, amount) + val reissue = TxHelpers.reissue(issue.asset, firstTxParticipant, additionalAmount, reissuable = false, customAssetIssueFee) withGenerateSubscription( settings = currentSettings, - balances = Seq(AddrWithBalance(senderAddress, senderBalanceBefore)) + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) ) { d => d.appendBlock(issue) - d.appendMicroBlock(reissueTx) + d.appendBlock(reissue) } { updates => - val append = updates(2).append - val assetDetails = append.transactionStateUpdates.head.assets.head - val minerBalanceBefore = 12.waves + issue.fee.value * 2 / 5 - - checkReissue(append.transactionIds.head, append.transactionAt(0), reissueTx) - checkBalances( - append.transactionStateUpdates.head.balances, - Map( - (senderAddress, Waves) -> (senderBalanceBeforeReissue, senderBalanceAfterReissue), - (senderAddress, reissueTx.asset) -> (amount, quantityAfterReissue), - (defaultAddress, Waves) -> (minerBalanceBefore, minerBalanceBefore + reissueTx.fee.value * 2 / 5) - ) - ) - checkAssetsStateUpdates(assetDetails.before, issue, isNft = false, issue.quantity.value) - checkAssetsStateUpdates(assetDetails.after, reissueTx, isNft = false, quantityAfterReissue) + val append = updates(2).append + checkReissueTx(append, reissue, issue) } } "BU-4. Return correct data for burn" in { - val amount: Long = 6000000 - val amountBurn: Long = 5000000 - val issue = TxHelpers.issue(sender, amount) - val burnTx = TxHelpers.burn(issue.asset, amountBurn, sender, customAssetIssueFee) - val amountAfterTx = amount - amountBurn - val senderBalanceBeforeBurn = senderBalanceBefore - issue.fee.value - val senderBalanceAfterBurn = senderBalanceBeforeBurn - burnTx.fee.value - + val issue = TxHelpers.issue(firstTxParticipant, amount) + val burn = TxHelpers.burn(issue.asset, additionalAmount, firstTxParticipant, customAssetIssueFee) withGenerateSubscription( settings = currentSettings, - balances = Seq(AddrWithBalance(senderAddress, senderBalanceBefore)) + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) ) { d => d.appendBlock(issue) - d.appendMicroBlock(burnTx) + d.appendBlock(burn) } { updates => - val append = updates(2).append - val assetDetails = append.transactionStateUpdates.head.assets.head - val minerBalanceBefore = 12.waves + issue.fee.value * 2 / 5 - checkBurn(append.transactionIds.head, append.transactionAt(0), burnTx) - checkBalances( - append.transactionStateUpdates.head.balances, - Map( - (senderAddress, Waves) -> (senderBalanceBeforeBurn, senderBalanceAfterBurn), - (senderAddress, burnTx.asset) -> (amount, amountAfterTx), - (defaultAddress, Waves) -> (minerBalanceBefore, minerBalanceBefore + burnTx.fee.value * 2 / 5) - ) - ) - checkAssetsStateUpdates(assetDetails.before, issue, isNft = false, issue.quantity.value) - checkAssetsStateUpdates(assetDetails.after, burnTx, isNft = false, amountAfterTx) + val append = updates(2).append + checkBurnTx(append, burn, issue) } } "Exchange transaction subscription tests" - { - val buyer = TxHelpers.signer(58) - val seller = TxHelpers.signer(189) - val buyerBalanceBefore = 4.waves - val buyerBalanceBeforeExchange = 3.waves - val sellerBalanceBefore = 4.waves - val sellerBalanceBeforeExchange = 3.waves - val priceAsset = TxHelpers.issue(buyer, 2000000000, 2) - val priceAssetQuantity = priceAsset.quantity.value - val amountAsset = TxHelpers.issue(seller, 1000000000, 6) - val amountAssetQuantity = amountAsset.quantity.value - "BU-6. Return correct data for order V3, exchange V2" in { - val order1 = TxHelpers.order( - OrderType.BUY, - amountAsset.asset, - priceAsset.asset, - Waves, - 50000L, - 400000000L, - fee = customFee, - sender = buyer, - matcher = buyer, - version = Order.V3 - ) - val order2 = TxHelpers.order( - OrderType.SELL, - amountAsset.asset, - priceAsset.asset, - Waves, - amount = 50000L, - price = 400000000L, - fee = customFee, - sender = seller, - matcher = buyer, - version = Order.V3 - ) - val exchangedAssets = order1.price.value * order1.amount.value / 100000000 - val exchangeTx = TxHelpers.exchangeFromOrders(order1, order2, buyer, version = TxVersion.V2) - addedBlocksAndSubscribe(exchangeTx) { updated => - checkingSubscribeFields(updated(3).getAppend, exchangeTx, exchangedAssets, order1.amount.value) + val order1 = createOrder(OrderType.BUY, firstTxParticipant, Order.V3) + val order2 = createOrder(OrderType.SELL, secondTxParticipant, Order.V3) + val normalizedPrice = order1.price.value * order1.amount.value / 100000000 + val exchangeTx = TxHelpers.exchangeFromOrders(order1, order2, firstTxParticipant, version = TxVersion.V2) + withAddedBlocksAndSubscribeExchangeTx(exchangeTx) { updated => + val append = updated.apply(3).getAppend + checkExchangeTx(append, exchangeTx, normalizedPrice, order1.amount.value) } } "BU-120. Return correct data for order V4, exchange V3" in { - val order1 = TxHelpers.order( - OrderType.BUY, - amountAsset.asset, - priceAsset.asset, - Waves, - 50000L, - 400000000L, - fee = customFee, - sender = buyer, - matcher = buyer, - version = Order.V4 - ) - val order2 = TxHelpers.order( - OrderType.SELL, - amountAsset.asset, - priceAsset.asset, - Waves, - amount = 50000L, - price = 400000000L, - fee = customFee, - sender = seller, - matcher = buyer, - version = Order.V4 - ) - val exchangedAssets = order1.price.value / 2 / 10000000 - val exchangeTx = TxHelpers.exchangeFromOrders(order1, order2, buyer, version = TxVersion.V3) - addedBlocksAndSubscribe(exchangeTx) { updated => - checkingSubscribeFields(updated(3).getAppend, exchangeTx, exchangedAssets, order1.amount.value) + val order1 = createOrder(OrderType.BUY, firstTxParticipant, Order.V4) + val order2 = createOrder(OrderType.SELL, secondTxParticipant, Order.V4) + val normalizedPrice = order1.price.value / 2 / 10000000 + val exchangeTx = TxHelpers.exchangeFromOrders(order1, order2, firstTxParticipant, version = TxVersion.V3) + withAddedBlocksAndSubscribeExchangeTx(exchangeTx) { updated => + val append = updated.apply(3).getAppend + checkExchangeTx(append, exchangeTx, normalizedPrice, order1.amount.value) } } - - def addedBlocksAndSubscribe(exchangeTx: ExchangeTransaction)(f: Seq[PBBlockchainUpdated] => Unit): Unit = { - withGenerateSubscription( - settings = currentSettings, - balances = Seq( - AddrWithBalance(buyer.toAddress, buyerBalanceBefore), - AddrWithBalance(seller.toAddress, sellerBalanceBefore) - ) - ) { d => - d.appendBlock(priceAsset) - d.appendBlock(amountAsset) - d.appendMicroBlock(exchangeTx) - }(f) - } - - def checkingSubscribeFields(append: Append, exchangeTx: ExchangeTransaction, exchangedAssets: Long, orderAmount: Long): Unit = { - val minerBalanceBefore = 18.waves + priceAsset.fee.value + amountAsset.fee.value * 2 / 5 - checkExchange(append.transactionIds.head, append.transactionAt(0), exchangeTx) - checkBalances( - append.transactionStateUpdates.head.balances, - Map( - (buyer.toAddress, Waves) -> (buyerBalanceBeforeExchange, buyerBalanceBeforeExchange - fee + customFee), - (seller.toAddress, priceAsset.asset) -> (0, exchangedAssets), - (buyer.toAddress, amountAsset.asset) -> (0, orderAmount), - (seller.toAddress, Waves) -> (sellerBalanceBeforeExchange, sellerBalanceBeforeExchange - customFee), - (buyer.toAddress, priceAsset.asset) -> (priceAssetQuantity, priceAssetQuantity - exchangedAssets), - (seller.toAddress, amountAsset.asset) -> (amountAssetQuantity, amountAssetQuantity - orderAmount), - (defaultAddress, Waves) -> (minerBalanceBefore, minerBalanceBefore + exchangeTx.fee.value * 2 / 5) - ) - ) - } } "BU-12. Return correct data for lease" in { - val recipient = TxHelpers.signer(123) - val recipientAddress = recipient.toAddress - val amount = 5.waves - val lease = TxHelpers.lease(sender, recipientAddress, amount, customFee) - val leaseId = lease.id.value().arr - + val lease = TxHelpers.lease(firstTxParticipant, secondTxParticipantAddress, amount, customFee) withGenerateSubscription( settings = currentSettings, - balances = Seq(AddrWithBalance(senderAddress, senderBalanceBefore)) + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) )(_.appendMicroBlock(lease)) { updates => val append = updates(1).append - checkLease(append.transactionIds.head, append.transactionAt(0), lease, recipientAddress.publicKeyHash) - checkBalances( - append.transactionStateUpdates.head.balances, - Map( - (senderAddress, Waves) -> (senderBalanceBefore, senderBalanceBefore - customFee), - (defaultAddress, Waves) -> (6.waves, 6.waves + customFee * 2 / 5) - ) - ) - checkLeasingForAddress( - append.transactionStateUpdates.head.leasingForAddress, - Map( - (senderAddress, 0L, amount) -> (0L, 0L), - (recipientAddress, amount, 0L) -> (0L, 0L) - ) - ) - checkIndividualLeases( - append.transactionStateUpdates.head.individualLeases, - Map( - (LeaseStatus.Active, amount) -> (leaseId, lease.sender.arr, lease.recipient.bytes, leaseId) - ) - ) + checkLeaseTx(append, lease) } } "BU-14. Return correct data for lease cancel" in { - val recipient = TxHelpers.signer(123) - val recipientAddress = recipient.toAddress - val amount = 5.waves - val lease = TxHelpers.lease(sender, recipientAddress, amount, customFee) - val leaseCancel = TxHelpers.leaseCancel(lease.id.value(), sender, customFee) - val leaseId = leaseCancel.leaseId.arr - val senderBalanceBeforeTx = senderBalanceBefore - lease.fee.value - val senderBalanceAfterTx = senderBalanceBeforeTx - leaseCancel.fee.value - + val lease = TxHelpers.lease(firstTxParticipant, secondTxParticipantAddress, amount, customFee) + val leaseCancel = TxHelpers.leaseCancel(lease.id.value(), firstTxParticipant, customFee) withGenerateSubscription( settings = currentSettings, - balances = Seq(AddrWithBalance(senderAddress, senderBalanceBefore)) + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) ) { d => d.appendBlock(lease) d.appendMicroBlock(leaseCancel) } { updates => - val append = updates(2).append - val minerBalanceBefore = 12.waves + lease.fee.value * 2 / 5 - checkLeaseCancel(append.transactionIds.head, append.transactionAt(0), leaseCancel) - checkBalances( - append.transactionStateUpdates.head.balances, - Map( - (senderAddress, Waves) -> (senderBalanceBeforeTx, senderBalanceAfterTx), - (defaultAddress, Waves) -> (minerBalanceBefore, minerBalanceBefore + leaseCancel.fee.value * 2 / 5) - ) - ) - checkLeasingForAddress( - append.transactionStateUpdates.head.leasingForAddress, - Map( - (senderAddress, 0L, 0L) -> (0L, amount), - (recipientAddress, 0L, 0L) -> (amount, 0L) - ) - ) - checkIndividualLeases( - append.transactionStateUpdates.head.individualLeases, - Map( - (LeaseStatus.Inactive, amount) -> (leaseId, lease.sender.arr, lease.recipient.bytes, leaseId) - ) - ) + val append = updates(2).append + checkLeaseCancelTx(append, leaseCancel, lease) } } "BU-16. Return correct data for massTransfer" in { - val massTransferFee = fee * 6 - val transferAmount = 500000L - val recipients = TxHelpers.accountSeqGenerator(100, transferAmount) - val issue = TxHelpers.issue(sender, 1000000000L) - val issuedAsset: Asset = Asset.fromCompatId(issue.asset.compatId) - val massTransfer = TxHelpers.massTransfer(sender, recipients, issuedAsset, massTransferFee) - val senderBalanceBeforeTx = senderBalanceBefore - issue.fee.value - val senderBalanceAfterTx = senderBalanceBeforeTx - massTransfer.fee.value - val senderAssetBalanceAfterTx = issue.quantity.value - transferAmount * recipients.size + val massTransferFee = fee * 6 + val massTransfer = TxHelpers.massTransfer(firstTxParticipant, recipients, firstToken.asset, massTransferFee) withGenerateSubscription( settings = currentSettings, - balances = Seq(AddrWithBalance(senderAddress, senderBalanceBefore)) + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) ) { d => - d.appendBlock(issue) + d.appendBlock(firstToken) d.appendMicroBlock(massTransfer) } { updates => - val balancesMap = Map( - (senderAddress, Waves) -> (senderBalanceBeforeTx, senderBalanceAfterTx), - (senderAddress, issuedAsset) -> (issue.quantity.value, senderAssetBalanceAfterTx) - ) ++ recipients.map(r => (Address.fromBytes(r.address.bytes).explicitGet(), issuedAsset) -> (0L, transferAmount)).toMap val append = updates(2).append - checkMassTransfer( - append.transactionIds.head, - append.transactionAt(0), - massTransfer, - recipients.map(r => - r.address match { - case address: Address => Some(address.publicKeyHash).get - case _ => fail("not an address") - } - ) - ) - checkMassTransferBalances(append.transactionStateUpdates.head.balances, balancesMap) + checkForMassTransferTx(append, massTransfer) } } - "BU-5. Return correct data for data" in { - val integerDataEntry = IntegerDataEntry.apply("Integer", 3550000L) - val booleanDataEntry = BooleanDataEntry.apply("Boolean", value = true) - val stringDataEntry = StringDataEntry.apply("String", "test") - val binaryDataEntry = BinaryDataEntry.apply("Binary", ByteStr.apply(senderAddress.bytes)) - val entries = Seq(booleanDataEntry, integerDataEntry, stringDataEntry, binaryDataEntry) - val dataTx = TxHelpers.data(sender, entries, customFee, TxVersion.V2) - + "BU-5. Return correct data for dataTx" in { + val data = TxHelpers.data(firstTxParticipant, entries, customFee, TxVersion.V2) withGenerateSubscription( settings = currentSettings.addFeatures(BlockchainFeatures.SmartAccounts), - balances = Seq(AddrWithBalance(senderAddress, senderBalanceBefore)) - )(_.appendMicroBlock(dataTx)) { updates => - val append = updates(1).append - val txUpdates = append.transactionStateUpdates.head - checkDataTransaction(append.transactionIds.head, append.transactionAt(0), dataTx) - checkBalances( - txUpdates.balances, - Map( - (senderAddress, Waves) -> (senderBalanceBefore, senderBalanceBefore - customFee), - (defaultAddress, Waves) -> (6.waves, 6.waves + customFee * 2 / 5) - ) - ) - checkDataEntriesStateUpdate(txUpdates.dataEntries, dataTx.data, senderAddress.bytes) + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) + )(_.appendMicroBlock(data)) { updates => + val append = updates(1).append + checkDataTransfer(append, data) } } "BU-21. Return correct data for setScript" in { - val setScript = TxHelpers.setScript(sender, testScript, customFee) + val setScript = TxHelpers.setScript(firstTxParticipant, testScript, customFee) withGenerateSubscription( settings = currentSettings.addFeatures(BlockchainFeatures.SmartAccounts), - balances = Seq(AddrWithBalance(senderAddress, senderBalanceBefore)) + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) )(_.appendMicroBlock(setScript)) { updates => - val append = updates(1).append - val txUpdates = append.transactionStateUpdates.head - checkSetScriptTransaction(append.transactionIds.head, append.transactionAt(0), setScript) - checkBalances( - txUpdates.balances, - Map( - (senderAddress, Waves) -> (senderBalanceBefore, senderBalanceBefore - customFee), - (defaultAddress, Waves) -> (6.waves, 6.waves + customFee * 2 / 5) - ) - ) - checkSetScriptStateUpdate(txUpdates.scripts.head, setScript) + val append = updates(1).append + checkSetScript(append, setScript) } } "Return correct data for sponsorFee" - { - val sponsorshipFee = Option.apply(3950000L) - val issue = TxHelpers.issue(sender, 99900000L) - val sponsorFee = TxHelpers.sponsor(issue.asset, sponsorshipFee, sender) - val sponsorFeeCancel = TxHelpers.sponsor(issue.asset, None, sender) - val senderBalanceBeforeSponsorFeeTx = senderBalanceBefore - issue.fee.value + val sponsorshipFee = Option.apply(additionalAmount) + val sponsorFee = TxHelpers.sponsor(firstToken.asset, sponsorshipFee, firstTxParticipant) + val sponsorFeeCancel = TxHelpers.sponsor(firstToken.asset, None, firstTxParticipant) + val senderBalanceBeforeSponsorFeeTx = firstTxParticipantBalanceBefore - firstToken.fee.value val senderBalanceAfterSponsorFeeTx = senderBalanceBeforeSponsorFeeTx - sponsorFee.fee.value - val senderBalanceAfterSponsorFeeCancelTx = senderBalanceAfterSponsorFeeTx - sponsorFeeCancel.fee.value + val senderBalanceAfterSponsorFeeCancelTx = senderBalanceAfterSponsorFeeTx - sponsorFee.fee.value - "BU-25. subscribe sponsorFee " in withGenerateSubscription( + "BU-25. subscribe sponsorFee" in withGenerateSubscription( settings = currentSettings, - balances = Seq(AddrWithBalance(senderAddress, senderBalanceBefore)) + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) ) { d => - d.appendBlock(issue) + d.appendBlock(firstToken) d.appendBlock(sponsorFee) } { updates => - val append = updates(2).append - val txUpdates = append.transactionStateUpdates.head - val assetDetails = txUpdates.assets.head - - checkSponsorFeeTransaction(append.transactionIds.head, append.transactionAt(0), sponsorFee) - val minerBalanceBefore = 18.waves + issue.fee.value - checkBalances( - txUpdates.balances, - Map( - (senderAddress, Waves) -> (senderBalanceBeforeSponsorFeeTx, senderBalanceAfterSponsorFeeTx), - (defaultAddress, Waves) -> (minerBalanceBefore, 18.waves + issue.fee.value + sponsorFee.fee.value * 2 / 5) - ) - ) - checkAssetsStateUpdates(assetDetails.before, issue, isNft = false, issue.quantity.value) - checkAssetsStateUpdates(assetDetails.after, issue, isNft = false, issue.quantity.value) + val append = updates(2).append + checkSponsorFee(append, sponsorFee, senderBalanceBeforeSponsorFeeTx, senderBalanceAfterSponsorFeeTx) } "BU-27. subscribe sponsorFee cancel" in withGenerateSubscription( settings = currentSettings, - balances = Seq(AddrWithBalance(senderAddress, senderBalanceBefore)) + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) ) { d => - d.appendBlock(issue) + d.appendBlock(firstToken) d.appendBlock(sponsorFee) d.appendMicroBlock(sponsorFeeCancel) } { updates => - val append = updates(3).append - val txUpdates = append.transactionStateUpdates.head - val assetDetails = txUpdates.assets.head - - checkSponsorFeeTransaction(append.transactionIds.head, append.transactionAt(0), sponsorFeeCancel) - val minerBalanceBefore = 18.waves + issue.fee.value + sponsorFee.fee.value * 2 / 5 - checkBalances( - txUpdates.balances, - Map( - (senderAddress, Waves) -> (senderBalanceAfterSponsorFeeTx, senderBalanceAfterSponsorFeeCancelTx), - (defaultAddress, Waves) -> (minerBalanceBefore, minerBalanceBefore + sponsorFeeCancel.fee.value * 2 / 5) - ) - ) - checkAssetsStateUpdates(assetDetails.before, issue, isNft = false, issue.quantity.value) - checkAssetsStateUpdates(assetDetails.after, issue, isNft = false, issue.quantity.value) + val append = updates(3).append + checkSponsorFee(append, sponsorFeeCancel, senderBalanceAfterSponsorFeeTx, senderBalanceAfterSponsorFeeCancelTx) } } "BU-20. Return correct data for setAssetScript" in { - val complexScriptBefore = Option.apply(TxHelpers.script("true".stripMargin)) - val complexScriptAfter = TxHelpers.script("false".stripMargin) - val issue = TxHelpers.issue(sender, 99900000L, script = complexScriptBefore) - val setAssetScript = TxHelpers.setAssetScript(sender, issue.asset, complexScriptAfter, 1.waves) - val quantity = issue.quantity.value - val senderBalanceBeforeSetAssetScriptTx = senderBalanceBefore - issue.fee.value - val senderBalanceAfterSetAssetScriptTx = senderBalanceBeforeSetAssetScriptTx - setAssetScript.fee.value - + val issue = TxHelpers.issue(firstTxParticipant, amount, script = complexScriptBefore) + val setAssetScript = TxHelpers.setAssetScript(firstTxParticipant, issue.asset, complexScriptAfter, 1.waves) withGenerateSubscription( settings = currentSettings.addFeatures(BlockchainFeatures.SmartAccounts), - balances = Seq(AddrWithBalance(senderAddress, senderBalanceBefore)) + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) ) { d => d.appendBlock(issue) d.appendMicroBlock(setAssetScript) } { updates => - val append = updates(2).append - val txUpdates = append.transactionStateUpdates.head - val assetDetails = txUpdates.assets.head - val minerBalanceBefore = 12.waves + issue.fee.value * 2 / 5 - checkSetAssetScriptTransaction(append.transactionIds.head, append.transactionAt(0), setAssetScript) - checkBalances( - txUpdates.balances, - Map( - (senderAddress, Waves) -> (senderBalanceBeforeSetAssetScriptTx, senderBalanceAfterSetAssetScriptTx), - (defaultAddress, Waves) -> (minerBalanceBefore, minerBalanceBefore + setAssetScript.fee.value * 2 / 5) - ) - ) - checkAssetsStateUpdates(assetDetails.before, issue, isNft = false, quantity) - checkAssetsScriptStateUpdates(assetDetails.before.get.scriptInfo, complexScriptBefore.get.bytes.value().arr) - checkAssetsStateUpdates(assetDetails.after, issue, isNft = false, quantity) - checkAssetsScriptStateUpdates(assetDetails.after.get.scriptInfo, complexScriptAfter.bytes.value().arr) + val append = updates(2).append + checkSetAssetScript(append, setAssetScript, issue) } } "BU-121. Return correct data for UpdateAssetInfo" in { - val newName = "new_name" - val newDescription = "new_description" - val issue = TxHelpers.issue(sender, 99900000L) - val updateAssetInfo = TxHelpers.updateAssetInfo(issue.assetId, newName, newDescription, sender) - val senderBalanceBeforeUpdateAssetInfoTx = senderBalanceBefore - issue.fee.value - val senderBalanceAfterUpdateAssetInfoTx = senderBalanceBeforeUpdateAssetInfoTx - updateAssetInfo.fee + val newName = "new_name" + val newDescription = "new_description" + val updateAssetInfo = TxHelpers.updateAssetInfo(firstTokenAsset.id, newName, newDescription, firstTxParticipant) withGenerateSubscription( settings = currentSettings.configure(_.copy(minAssetInfoUpdateInterval = 1)), - balances = Seq(AddrWithBalance(senderAddress, senderBalanceBefore)) + balances = Seq(AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore)) ) { d => - d.appendBlock(issue) + d.appendBlock(firstToken) d.appendBlock() d.appendMicroBlock(updateAssetInfo) } { updates => - val append = updates(3).append - val txUpdates = append.transactionStateUpdates.head - val assetDetails = txUpdates.assets.head - checkUpdateAssetInfoTransaction(append.transactionIds.head, append.transactionAt(0), updateAssetInfo) - checkBalances( - txUpdates.balances, - Map( - (senderAddress, Waves) -> (senderBalanceBeforeUpdateAssetInfoTx, senderBalanceAfterUpdateAssetInfoTx), - (defaultAddress, Waves) -> (18.waves + issue.fee.value, 18.waves + issue.fee.value + updateAssetInfo.fee * 2 / 5) - ) + val append = updates(3).append + checkUpdateAssetInfo(append, updateAssetInfo) + } + } + + "BU-122. Return correct data for EthereumTransfer" in { + val ethereumTransfer: EthereumTransaction = + EthTxGenerator.generateEthTransfer(firstTxParticipantEthereum, secondTxParticipantAddress, amount, secondTokenAsset) + val ethAddress = ethereumTransfer.senderAddress.value() + val transfer = TxHelpers.transfer(secondTxParticipant, ethAddress, secondTokenQuantity, secondTokenAsset) + + withGenerateSubscription( + settings = currentSettings.addFeatures(BlockchainFeatures.SmartAccounts), + balances = Seq( + AddrWithBalance(ethAddress, firstTxParticipantBalanceBefore), + AddrWithBalance(secondTxParticipantAddress, secondTxParticipantBalanceBefore) ) - checkAssetsStateUpdates(assetDetails.before, issue, isNft = false, issue.quantity.value) - checkAssetUpdatesStateUpdates(assetDetails.after, updateAssetInfo) + ) { d => + d.appendKeyBlock() + d.appendBlock(secondToken, transfer) + d.appendMicroBlock(ethereumTransfer) + } { updates => + val append = updates(3).append + checkEthereumTransfer(append, ethereumTransfer, ethAddress) } } + + def withAddedBlocksAndSubscribeExchangeTx(exchangeTx: ExchangeTransaction)(f: Seq[PBBlockchainUpdated] => Unit): Unit = { + withGenerateSubscription( + settings = currentSettings, + balances = Seq( + AddrWithBalance(firstTxParticipantAddress, firstTxParticipantBalanceBefore), + AddrWithBalance(secondTxParticipantAddress, secondTxParticipantBalanceBefore) + ) + ) { d => + d.appendBlock(firstToken) + d.appendBlock(secondToken) + d.appendMicroBlock(exchangeTx) + }(f) + } } } diff --git a/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesTestBase.scala b/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesTestBase.scala new file mode 100644 index 00000000000..d221a51a47c --- /dev/null +++ b/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesTestBase.scala @@ -0,0 +1,502 @@ +package com.wavesplatform.events + +import com.google.protobuf.ByteString +import com.wavesplatform.account.{Address, PublicKey, SeedKeyPair} +import com.wavesplatform.common.state.ByteStr +import com.wavesplatform.common.utils.EitherExt2 +import com.wavesplatform.db.WithState.AddrWithBalance +import com.wavesplatform.events.StateUpdate.LeaseUpdate.LeaseStatus +import com.wavesplatform.events.api.grpc.protobuf.{GetBlockUpdatesRangeRequest, SubscribeRequest} +import com.wavesplatform.events.fixtures.BlockchainUpdateGrpcMethod +import com.wavesplatform.events.fixtures.BlockchainUpdateGrpcMethod.{GetBlockUpdate, GetBlockUpdateRange, Subscribe} +import com.wavesplatform.events.fixtures.InvokeWavesTxCheckers.checkSimpleInvoke +import com.wavesplatform.events.fixtures.PrepareInvokeTestData.* +import com.wavesplatform.events.fixtures.WavesTxChecks.* +import com.wavesplatform.events.protobuf.BlockchainUpdated.Append +import com.wavesplatform.events.protobuf.BlockchainUpdated.Append.Body +import com.wavesplatform.events.protobuf.StateUpdate +import com.wavesplatform.events.protobuf.TransactionMetadata.InvokeScriptMetadata +import com.wavesplatform.lang.script.Script +import com.wavesplatform.protobuf.transaction.PBAmounts.toVanillaAssetId +import com.wavesplatform.settings.WavesSettings +import com.wavesplatform.state.* +import com.wavesplatform.test.{FreeSpec, NumericExt} +import com.wavesplatform.transaction.Asset.{IssuedAsset, Waves} +import com.wavesplatform.transaction.TxHelpers.secondSigner +import com.wavesplatform.transaction.assets.* +import com.wavesplatform.transaction.assets.exchange.* +import com.wavesplatform.transaction.assets.exchange.Order.Version +import com.wavesplatform.transaction.lease.{LeaseCancelTransaction, LeaseTransaction} +import com.wavesplatform.transaction.smart.SetScriptTransaction +import com.wavesplatform.transaction.transfer.MassTransferTransaction.ParsedTransfer +import com.wavesplatform.transaction.transfer.{MassTransferTransaction, TransferTransaction} +import com.wavesplatform.transaction.utils.EthConverters.EthereumKeyPairExt +import com.wavesplatform.transaction.{Asset, CreateAliasTransaction, DataTransaction, EthereumTransaction, Transaction, TxHelpers} +import org.scalactic.source.Position +import org.scalatest.Assertions +import org.scalatest.concurrent.ScalaFutures +import org.web3j.crypto.Bip32ECKeyPair + +class BlockchainUpdatesTestBase extends FreeSpec with WithBUDomain with ScalaFutures { + import BlockchainUpdatesTestBase.* + val currentSettings: WavesSettings = DomainPresets.RideV6 + val amount: Long = 9000000 + val additionalAmount: Long = 5000000 + val customFee: Long = 5234567L + val customAssetIssueFee = 234567654L + val invokeFee: Long = 1.005.waves + val firstTxParticipant: SeedKeyPair = TxHelpers.signer(2) + val firstTxParticipantAddress: Address = firstTxParticipant.toAddress + val ethKeyPairExt: EthereumKeyPairExt = EthereumKeyPairExt(firstTxParticipant) + val firstTxParticipantEthereum: Bip32ECKeyPair = ethKeyPairExt.toEthKeyPair + val firstTxParticipantEthereumAddress: Address = ethKeyPairExt.toEthWavesAddress + val firstTxParticipantEthereumPublicKey: Array[Byte] = firstTxParticipantEthereum.getPublicKey.toByteArray + val ethKeyPair: SeedKeyPair = SeedKeyPair.apply(firstTxParticipantEthereum.getPrivateKeyBytes33) + val firstTxParticipantBalanceBefore: Long = 20.waves + val secondTxParticipant: SeedKeyPair = TxHelpers.signer(3) + val secondTxParticipantAddress: Address = secondTxParticipant.toAddress + val secondTxParticipantPKHash: Array[Byte] = secondTxParticipantAddress.publicKeyHash + val secondTxParticipantBalanceBefore: Long = 20.waves + val recipients: Seq[ParsedTransfer] = TxHelpers.accountSeqGenerator(100, additionalAmount) + val firstToken: IssueTransaction = TxHelpers.issue(firstTxParticipant, amount = 2000000000L, 2) + val firstTokenAsset: IssuedAsset = firstToken.asset + val firstTokenQuantity: Long = firstToken.quantity.value + val firstTokenFee: Long = firstToken.fee.value + val secondToken: IssueTransaction = TxHelpers.issue(secondTxParticipant, amount = 6000000000L, 6) + val secondTokenAsset: IssuedAsset = secondToken.asset + val secondTokenQuantity: Long = secondToken.quantity.value + val integerDataEntry: IntegerDataEntry = IntegerDataEntry.apply("Integer", 3550000L) + val booleanDataEntry: BooleanDataEntry = BooleanDataEntry.apply("Boolean", value = true) + val stringDataEntry: StringDataEntry = StringDataEntry.apply("String", "test") + val binaryDataEntry: BinaryDataEntry = BinaryDataEntry.apply("Binary", ByteStr.apply(firstTxParticipantAddress.bytes)) + val expectDataEntries: Seq[DataEntry[?]] = Seq[DataEntry[?]](IntegerDataEntry(bar, scriptTransferUnitNum * 2)) + val entries: Seq[DataEntry[?]] = Seq(booleanDataEntry, integerDataEntry, stringDataEntry, binaryDataEntry) + val defaultScript: Option[Script] = Option(TxHelpers.script("true")) + val complexScriptBefore: Option[Script] = Option.apply(TxHelpers.script("true".stripMargin)) + val complexScriptAfter: Script = TxHelpers.script("false".stripMargin) + val invokeFunctionName: String = "setData" + val caller: String = "i.caller" + val originCaller: String = "i.originCaller" + val testScript: Script = TxHelpers.script(s"""{-# STDLIB_VERSION 6 #-} + |{-# CONTENT_TYPE DAPP #-} + |{-# SCRIPT_TYPE ACCOUNT #-} + | + |@Verifier(tx) + |func verify () = match(tx) { + | case _ => + | if ( + | ${(1 to 9).map(_ => "sigVerify(base58'', base58'', base58'')").mkString(" || \n")} + | ) then true else true + |}""".stripMargin) + + protected def createOrder(orderType: OrderType, orderSender: SeedKeyPair, orderVersion: Version): Order = { + TxHelpers.order( + orderType, + secondToken.asset, + firstToken.asset, + Waves, + amount = 50000L, + price = 400000000L, + fee = customFee, + sender = orderSender, + matcher = firstTxParticipant, + version = orderVersion + ) + } + + protected def checkAlias(append: Append, aliasTx: CreateAliasTransaction)(implicit pos: Position): Unit = { + val firstTxParticipantBalanceAfter: Long = firstTxParticipantBalanceBefore - aliasTx.fee.value + checkCreateAlias(append.transactionIds.head, append.transactionAt(0), aliasTx) + checkBalances( + filterOutMinerBalanceUpdates(append), + Map((firstTxParticipantAddress, Waves) -> (firstTxParticipantBalanceBefore, firstTxParticipantBalanceAfter)) + ) + } + + protected def checkTransferTx(append: Append, transferTx: TransferTransaction)(implicit pos: Position): Unit = { + val firstTxParticipantBalanceAfter = firstTxParticipantBalanceBefore - customFee - amount + val secondTxParticipantBalanceAfter = secondTxParticipantBalanceBefore + amount + checkTransfer(append.transactionIds.head, append.transactionAt(0), transferTx, secondTxParticipantAddress.publicKeyHash) + checkBalances( + filterOutMinerBalanceUpdates(append), + Map( + (firstTxParticipantAddress, Waves) -> (firstTxParticipantBalanceBefore, firstTxParticipantBalanceAfter), + (secondTxParticipantAddress, Waves) -> (secondTxParticipantBalanceBefore, secondTxParticipantBalanceAfter) + ) + ) + } + + protected def checkIssueTx(append: Append, issue: IssueTransaction, isNft: Boolean)(implicit pos: Position): Unit = { + val assetDetails = append.transactionStateUpdates.head.assets.head + val issueQuantity = issue.quantity.value + val firstTxParticipantBalanceAfter = firstTxParticipantBalanceBefore - issue.fee.value + + checkIssue(append.transactionIds.head, append.transactionAt(0), issue) + checkBalances( + filterOutMinerBalanceUpdates(append), + Map( + (firstTxParticipantAddress, Waves) -> (firstTxParticipantBalanceBefore, firstTxParticipantBalanceAfter), + (firstTxParticipantAddress, issue.asset) -> (0, issueQuantity) + ) + ) + checkAssetsStateUpdates(assetDetails.after, issue, isNft, issue.quantity.value) + if (issue.script.isDefined) { + checkAssetsScriptStateUpdates(assetDetails.after.get.scriptInfo, issue.script.get.bytes.value().arr) + } + } + + protected def checkReissueTx(append: Append, reissue: ReissueTransaction, issue: IssueTransaction)(implicit pos: Position): Unit = { + val assetDetails = append.transactionStateUpdates.head.assets.head + val quantityAfter = amount + additionalAmount + val firstTxParticipantBalanceBeforeReissue = firstTxParticipantBalanceBefore - issue.fee.value + val firstTxParticipantBalanceAfterReissue = firstTxParticipantBalanceBeforeReissue - reissue.fee.value + + checkReissue(append.transactionIds.head, append.transactionAt(0), reissue) + checkBalances( + filterOutMinerBalanceUpdates(append), + Map( + (firstTxParticipantAddress, Waves) -> (firstTxParticipantBalanceBeforeReissue, firstTxParticipantBalanceAfterReissue), + (firstTxParticipantAddress, reissue.asset) -> (amount, quantityAfter) + ) + ) + checkAssetsStateUpdates(assetDetails.before, issue, isNft = false, issue.quantity.value) + checkAssetsStateUpdates(assetDetails.after, reissue, isNft = false, quantityAfter) + } + + protected def checkBurnTx(append: Append, burn: BurnTransaction, issue: IssueTransaction)(implicit pos: Position): Unit = { + val assetDetails = append.transactionStateUpdates.head.assets.head + val amountAfterTx = amount - additionalAmount + val firstTxParticipantBalanceBeforeBurn = firstTxParticipantBalanceBefore - issue.fee.value + val firstTxParticipantBalanceAfterBurn = firstTxParticipantBalanceBeforeBurn - burn.fee.value + + checkBurn(append.transactionIds.head, append.transactionAt(0), burn) + checkBalances( + filterOutMinerBalanceUpdates(append), + Map( + (firstTxParticipantAddress, Waves) -> (firstTxParticipantBalanceBeforeBurn, firstTxParticipantBalanceAfterBurn), + (firstTxParticipantAddress, burn.asset) -> (amount, amountAfterTx) + ) + ) + checkAssetsStateUpdates(assetDetails.before, issue, isNft = false, issue.quantity.value) + checkAssetsStateUpdates(assetDetails.after, burn, isNft = false, amountAfterTx) + } + + protected def checkExchangeTx(append: Append, exchangeTx: ExchangeTransaction, normalizedPrice: Long, orderAmount: Long)(implicit + pos: Position + ): Unit = { + val amountAssetQuantity = secondToken.quantity.value + val firstTxParticipantBalanceBeforeExchange = firstTxParticipantBalanceBefore - firstTokenFee + val firstTxParticipantBalanceAfterExchange = firstTxParticipantBalanceBeforeExchange - exchangeTx.fee.value + customFee + val secondTxParticipantBalanceBeforeExchange = secondTxParticipantBalanceBefore - secondToken.fee.value + val secondTxParticipantBalanceAfterExchange = secondTxParticipantBalanceBeforeExchange - customFee + + checkExchange(append.transactionIds.head, append.transactionAt(0), exchangeTx) + checkBalances( + filterOutMinerBalanceUpdates(append), + Map( + (firstTxParticipantAddress, Waves) -> (firstTxParticipantBalanceBeforeExchange, firstTxParticipantBalanceAfterExchange), + (secondTxParticipantAddress, firstToken.asset) -> (0, normalizedPrice), + (firstTxParticipantAddress, secondToken.asset) -> (0, orderAmount), + (secondTxParticipantAddress, Waves) -> (secondTxParticipantBalanceBeforeExchange, secondTxParticipantBalanceAfterExchange), + (firstTxParticipantAddress, firstToken.asset) -> (firstTokenQuantity, firstTokenQuantity - normalizedPrice), + (secondTxParticipantAddress, secondToken.asset) -> (amountAssetQuantity, amountAssetQuantity - orderAmount) + ) + ) + } + + protected def checkLeaseTx(append: Append, lease: LeaseTransaction)(implicit pos: Position): Unit = { + val leaseId = lease.id.value().arr + checkLease(append.transactionIds.head, append.transactionAt(0), lease, secondTxParticipantPKHash) + checkBalances( + filterOutMinerBalanceUpdates(append), + Map( + (firstTxParticipantAddress, Waves) -> (firstTxParticipantBalanceBefore, firstTxParticipantBalanceBefore - customFee) + ) + ) + checkLeasingForAddress( + append.transactionStateUpdates.head.leasingForAddress, + Map( + (firstTxParticipantAddress, 0L, amount) -> (0L, 0L), + (secondTxParticipantAddress, amount, 0L) -> (0L, 0L) + ) + ) + checkIndividualLeases( + append.transactionStateUpdates.head.individualLeases, + Map( + (LeaseStatus.Active, amount) -> (leaseId, lease.sender.arr, lease.recipient.bytes, leaseId) + ) + ) + } + + protected def checkLeaseCancelTx(append: Append, leaseCancel: LeaseCancelTransaction, lease: LeaseTransaction)(implicit pos: Position): Unit = { + val leaseId = leaseCancel.leaseId.arr + val firstTxParticipantBalanceBeforeTx = firstTxParticipantBalanceBefore - lease.fee.value + val firstTxParticipantBalanceAfterTx = firstTxParticipantBalanceBeforeTx - leaseCancel.fee.value + checkLeaseCancel(append.transactionIds.head, append.transactionAt(0), leaseCancel) + checkBalances( + filterOutMinerBalanceUpdates(append), + Map( + (firstTxParticipantAddress, Waves) -> (firstTxParticipantBalanceBeforeTx, firstTxParticipantBalanceAfterTx) + ) + ) + checkLeasingForAddress( + append.transactionStateUpdates.head.leasingForAddress, + Map( + (firstTxParticipantAddress, 0L, 0L) -> (0L, amount), + (secondTxParticipantAddress, 0L, 0L) -> (amount, 0L) + ) + ) + checkIndividualLeases( + append.transactionStateUpdates.head.individualLeases, + Map( + (LeaseStatus.Inactive, amount) -> (leaseId, lease.sender.arr, lease.recipient.bytes, leaseId) + ) + ) + } + + protected def checkForMassTransferTx(append: Append, massTransfer: MassTransferTransaction): Unit = { + val firstTxParticipantBalanceBeforeTx = firstTxParticipantBalanceBefore - firstTokenFee + val firstTxParticipantBalanceAfterTx = firstTxParticipantBalanceBeforeTx - massTransfer.fee.value + val firstTxParticipantAssetBalanceAfterTx = firstTokenQuantity - additionalAmount * recipients.size + + val balancesMap = Map( + (firstTxParticipantAddress, Waves) -> (firstTxParticipantBalanceBeforeTx, firstTxParticipantBalanceAfterTx), + (firstTxParticipantAddress, massTransfer.assetId) -> (firstTokenQuantity, firstTxParticipantAssetBalanceAfterTx) + ) ++ recipients.map(r => (Address.fromBytes(r.address.bytes).explicitGet(), massTransfer.assetId) -> (0L, additionalAmount)).toMap + checkMassTransfer( + append.transactionIds.head, + append.transactionAt(0), + massTransfer, + recipients.map(r => + r.address match { + case address: Address => Some(address.publicKeyHash).get + case _ => fail("not an address") + } + ) + ) + checkMassTransferBalances(append.transactionStateUpdates.head.balances, balancesMap) + } + + protected def checkDataTransfer(append: Append, data: DataTransaction)(implicit pos: Position): Unit = { + val txUpdates = append.transactionStateUpdates.head + checkDataTransaction(append.transactionIds.head, append.transactionAt(0), data) + checkBalances( + filterOutMinerBalanceUpdates(append), + Map((firstTxParticipantAddress, Waves) -> (firstTxParticipantBalanceBefore, firstTxParticipantBalanceBefore - customFee)) + ) + checkDataEntriesStateUpdate(txUpdates.dataEntries, data.data, firstTxParticipantAddress.bytes) + } + + protected def checkSetScript(append: Append, setScript: SetScriptTransaction)(implicit pos: Position): Unit = { + val txUpdates = append.transactionStateUpdates.head + checkSetScriptTransaction(append.transactionIds.head, append.transactionAt(0), setScript) + checkBalances( + filterOutMinerBalanceUpdates(append), + Map((firstTxParticipantAddress, Waves) -> (firstTxParticipantBalanceBefore, firstTxParticipantBalanceBefore - customFee)) + ) + checkSetScriptStateUpdate(txUpdates.scripts.head, setScript) + } + + protected def checkSetAssetScript(append: Append, setAssetScript: SetAssetScriptTransaction, issue: IssueTransaction)(implicit + pos: Position + ): Unit = { + val quantity = issue.quantity.value + val firstTxParticipantBalanceBeforeSetAssetScriptTx = firstTxParticipantBalanceBefore - issue.fee.value + val firstTxParticipantBalanceAfterSetAssetScriptTx = firstTxParticipantBalanceBeforeSetAssetScriptTx - setAssetScript.fee.value + val txUpdates = append.transactionStateUpdates.head + val assetDetails = txUpdates.assets.head + checkSetAssetScriptTransaction(append.transactionIds.head, append.transactionAt(0), setAssetScript) + checkBalances( + filterOutMinerBalanceUpdates(append), + Map( + (firstTxParticipantAddress, Waves) -> (firstTxParticipantBalanceBeforeSetAssetScriptTx, firstTxParticipantBalanceAfterSetAssetScriptTx) + ) + ) + checkAssetsStateUpdates(assetDetails.before, issue, isNft = false, quantity) + checkAssetsScriptStateUpdates(assetDetails.before.get.scriptInfo, complexScriptBefore.get.bytes.value().arr) + checkAssetsStateUpdates(assetDetails.after, issue, isNft = false, quantity) + checkAssetsScriptStateUpdates(assetDetails.after.get.scriptInfo, complexScriptAfter.bytes.value().arr) + } + + protected def checkUpdateAssetInfo(append: Append, updateAssetInfo: UpdateAssetInfoTransaction)(implicit pos: Position): Unit = { + val firstTxParticipantBalanceBeforeUpdateAssetInfoTx = firstTxParticipantBalanceBefore - firstTokenFee + val firstTxParticipantBalanceAfterUpdateAssetInfoTx = firstTxParticipantBalanceBeforeUpdateAssetInfoTx - updateAssetInfo.fee + val txUpdates = append.transactionStateUpdates.head + val assetDetails = txUpdates.assets.head + checkUpdateAssetInfoTransaction(append.transactionIds.head, append.transactionAt(0), updateAssetInfo) + checkBalances( + filterOutMinerBalanceUpdates(append), + Map( + (firstTxParticipantAddress, Waves) -> (firstTxParticipantBalanceBeforeUpdateAssetInfoTx, firstTxParticipantBalanceAfterUpdateAssetInfoTx) + ) + ) + checkAssetsStateUpdates(assetDetails.before, firstToken, isNft = false, firstTokenQuantity) + checkAssetUpdatesStateUpdates(assetDetails.after, updateAssetInfo) + } + + protected def checkSponsorFee(append: Append, sponsorFee: SponsorFeeTransaction, balanceBefore: Long, balanceAfter: Long)(implicit + pos: Position + ): Unit = { + val txUpdates = append.transactionStateUpdates.head + val assetDetails = txUpdates.assets.head + + checkSponsorFeeTransaction(append.transactionIds.head, append.transactionAt(0), sponsorFee) + checkBalances( + filterOutMinerBalanceUpdates(append), + Map((firstTxParticipantAddress, Waves) -> (balanceBefore, balanceAfter)) + ) + checkAssetsStateUpdates(assetDetails.before, firstToken, isNft = false, firstTokenQuantity) + checkAssetsStateUpdates(assetDetails.after, firstToken, isNft = false, firstTokenQuantity) + } + + protected def checkEthereumTransfer(append: Append, ethereumTransfer: EthereumTransaction, ethAddress: Address)(implicit pos: Position): Unit = { + val firstTxParticipantBalanceAfter = firstTxParticipantBalanceBefore - ethereumTransfer.fee + val recipientTokenBalanceAfter = secondTokenQuantity - amount + + checkEthereumTransaction(append.transactionIds.head, append.transactionAt(0), ethereumTransfer) + checkBalances( + filterOutMinerBalanceUpdates(append), + Map( + (ethAddress, Waves) -> (firstTxParticipantBalanceBefore, firstTxParticipantBalanceAfter), + (ethAddress, secondTokenAsset) -> (secondTokenQuantity, recipientTokenBalanceAfter), + (secondTxParticipantAddress, secondTokenAsset) -> (0, amount) + ) + ) + } + + def testInvoke(issue: IssueTransaction, invoke: Transaction, balances: Seq[AddrWithBalance])( + checkType: BlockchainUpdateGrpcMethod, + checkFunction: Append => Unit + ): Unit = { + for (libVersion <- 5 to 6) { + val setScript = TxHelpers.setScript(firstTxParticipant, TxHelpers.script(invokeAssetScript(libVersion))) + checkType match { + case Subscribe => + withGenerateSubscription( + settings = currentSettings, + balances = balances + ) { d => + d.appendBlock(setScript) + d.appendBlock(issue) + d.appendMicroBlock(invoke) + } { updates => + checkFunction(updates(3).append) + } + case GetBlockUpdate => + withGenerateGetBlockUpdate( + height = 4, + settings = currentSettings, + balances + ) { d => + d.appendBlock(setScript) + d.appendBlock(issue) + d.appendBlock(invoke) + } { getBlockUpdate => + checkFunction(getBlockUpdate.getUpdate.getAppend) + } + case GetBlockUpdateRange => + withGenerateGetBlockUpdateRange( + GetBlockUpdatesRangeRequest.of(1, 4), + settings = currentSettings, + balances = balances + ) { d => + d.appendBlock(setScript) + d.appendBlock(issue) + d.appendBlock(invoke) + d.appendBlock() + } { getBlockUpdateRange => + checkFunction(getBlockUpdateRange.apply(3).getAppend) + } + } + } + } + + def doubleNestedInvokeTest( + assetDappAccount: SeedKeyPair, + balances: Seq[AddrWithBalance], + issue: IssueTransaction, + invoke: Transaction, + massTx: Transaction, + callerType: String, + checkType: BlockchainUpdateGrpcMethod + )(f: Append => Unit): Unit = { + for (libVersion <- 5 to 6) { + val mainDAppTx = TxHelpers.setScript(firstTxParticipant, TxHelpers.script(mainDAppScript(libVersion))) + val nestedDAppTx = TxHelpers.setScript(secondSigner, TxHelpers.script(nestedDAppScript(callerType, libVersion))) + val doubleNestedDAppTx = TxHelpers.setScript(assetDappAccount, TxHelpers.script(doubleNestedDAppScript(callerType, libVersion))) + checkType match { + case Subscribe => + withGenerateSubscription( + SubscribeRequest.of(1, Int.MaxValue), + settings = currentSettings, + balances + ) { d => + d.appendBlock(issue, massTx, mainDAppTx, nestedDAppTx, doubleNestedDAppTx) + d.appendMicroBlock(invoke) + } { updates => + f(updates(2).getAppend) + } + + case GetBlockUpdate => + withGenerateGetBlockUpdate( + height = 3, + settings = currentSettings, + balances + ) { d => + d.appendBlock(issue, massTx, mainDAppTx, nestedDAppTx, doubleNestedDAppTx) + d.appendBlock(invoke) + } { getBlockUpdate => + f(getBlockUpdate.getUpdate.getAppend) + } + + case GetBlockUpdateRange => + withGenerateGetBlockUpdateRange( + GetBlockUpdatesRangeRequest.of(1, 3), + settings = currentSettings, + balances + ) { d => + d.appendBlock(issue, massTx, mainDAppTx, nestedDAppTx, doubleNestedDAppTx) + d.appendBlock(invoke) + d.appendBlock() + } { getBlockUpdateRange => + f(getBlockUpdateRange.apply(2).getAppend) + } + } + } + } + + + + def checkGeneralInvoke( + append: Append, + issuerAssetBalanceAfterTx: Long, + invoke: Transaction, + issue: IssueTransaction, + invokeScript: InvokeScriptMetadata, + expectBalancesMap: Map[(Address, Asset), (Long, Long)] + )(implicit pos: Position): Unit = { + val issuerInvokeIssueBalance: Long = issueData.apply("amount").toString.toLong - scriptTransferIssueAssetNum + val result = invokeScript.result.get + val invokeIssueAsset = toVanillaAssetId(result.issues.head.assetId) + val expectMap = Map( + (firstTxParticipantAddress, invokeIssueAsset) -> (0L, issuerInvokeIssueBalance), + (secondTxParticipantAddress, invokeIssueAsset) -> (0L, scriptTransferIssueAssetNum) + ) ++ expectBalancesMap + checkSimpleInvoke(append, issue, issuerAssetBalanceAfterTx, invokeScript, invoke.id.value().arr) + + filterOutMinerBalanceUpdates(append) should matchBalances(expectMap) + } +} + +object BlockchainUpdatesTestBase extends Assertions { + def filterOutMinerBalanceUpdates(append: Append): Seq[StateUpdate.BalanceUpdate] = { + val generatorPK = append.body match { + case Body.Empty => fail("Append event is empty") + case Body.Block(value) => value.getBlock.getHeader.generator + case Body.MicroBlock(value) => value.getMicroBlock.getMicroBlock.senderPublicKey + } + val generatorAddress = ByteString.copyFrom(PublicKey(generatorPK.toByteArray).toAddress.bytes) + + append.transactionStateUpdates.head.balances.filterNot(_.address == generatorAddress) + } +} diff --git a/grpc-server/src/test/scala/com/wavesplatform/events/WithBUDomain.scala b/grpc-server/src/test/scala/com/wavesplatform/events/WithBUDomain.scala index d66c621a278..c8132807e6c 100644 --- a/grpc-server/src/test/scala/com/wavesplatform/events/WithBUDomain.scala +++ b/grpc-server/src/test/scala/com/wavesplatform/events/WithBUDomain.scala @@ -4,7 +4,7 @@ import com.google.common.util.concurrent.MoreExecutors import com.wavesplatform.db.WithDomain import FakeObserver.* import com.wavesplatform.db.WithState.AddrWithBalance -import com.wavesplatform.events.api.grpc.protobuf.SubscribeRequest +import com.wavesplatform.events.api.grpc.protobuf.{GetBlockUpdateResponse, GetBlockUpdatesRangeRequest, SubscribeRequest} import com.wavesplatform.events.protobuf.BlockchainUpdated as PBBlockchainUpdated import com.wavesplatform.events.repo.LiquidState import com.wavesplatform.history.Domain @@ -15,6 +15,7 @@ import monix.execution.Scheduler.Implicits.global import org.rocksdb.RocksDB import monix.reactive.subjects.PublishToOneSubject import org.scalatest.Suite +import org.scalatest.concurrent.ScalaFutures.convertScalaFuture trait WithBUDomain extends WithDomain { _: Suite => def withDomainAndRepo(settings: WavesSettings)(f: (Domain, Repo) => Unit, wrapDB: RocksDB => RocksDB = identity): Unit = { @@ -65,6 +66,32 @@ trait WithBUDomain extends WithDomain { _: Suite => } } + def withGenerateGetBlockUpdate( + height: Int = 1, + settings: WavesSettings, + balances: Seq[AddrWithBalance] = Seq(AddrWithBalance(TxHelpers.defaultSigner.toAddress, Constants.TotalWaves * Constants.UnitsInWave)) + )(generateBlocks: Domain => Unit)(f: GetBlockUpdateResponse => Unit): Unit = { + withDomainAndRepo(settings) { (d, repo) => + d.appendBlock(balances.map(awb => TxHelpers.genesis(awb.address, awb.balance))*) + generateBlocks(d) + val getBlockUpdate = repo.getBlockUpdate(height) + f(getBlockUpdate) + } + } + + def withGenerateGetBlockUpdateRange( + request: GetBlockUpdatesRangeRequest, + settings: WavesSettings, + balances: Seq[AddrWithBalance] = Seq(AddrWithBalance(TxHelpers.defaultSigner.toAddress, Constants.TotalWaves * Constants.UnitsInWave)) + )(generateBlocks: Domain => Unit)(f: Seq[PBBlockchainUpdated] => Unit): Unit = { + withDomainAndRepo(settings) { (d, repo) => + d.appendBlock(balances.map(awb => TxHelpers.genesis(awb.address, awb.balance))*) + generateBlocks(d) + val getBlockUpdateRange = repo.getBlockUpdatesRange(request).futureValue.updates + f(getBlockUpdateRange) + } + } + def withNEmptyBlocksSubscription(count: Int = 2, request: SubscribeRequest = SubscribeRequest.of(1, Int.MaxValue), settings: WavesSettings)( f: Seq[PBBlockchainUpdated] => Unit ): Unit = withGenerateSubscription(request, settings)(d => for (_ <- 1 to count) d.appendBlock())(f) diff --git a/grpc-server/src/test/scala/com/wavesplatform/events/fixtures/BlockchainUpdateGrpcMethod.scala b/grpc-server/src/test/scala/com/wavesplatform/events/fixtures/BlockchainUpdateGrpcMethod.scala new file mode 100644 index 00000000000..823f1e61f28 --- /dev/null +++ b/grpc-server/src/test/scala/com/wavesplatform/events/fixtures/BlockchainUpdateGrpcMethod.scala @@ -0,0 +1,9 @@ +package com.wavesplatform.events.fixtures + +sealed trait BlockchainUpdateGrpcMethod + +object BlockchainUpdateGrpcMethod { + case object Subscribe extends BlockchainUpdateGrpcMethod + case object GetBlockUpdate extends BlockchainUpdateGrpcMethod + case object GetBlockUpdateRange extends BlockchainUpdateGrpcMethod +} diff --git a/grpc-server/src/test/scala/com/wavesplatform/events/fixtures/InvokeWavesTxCheckers.scala b/grpc-server/src/test/scala/com/wavesplatform/events/fixtures/InvokeWavesTxCheckers.scala new file mode 100644 index 00000000000..284962d336b --- /dev/null +++ b/grpc-server/src/test/scala/com/wavesplatform/events/fixtures/InvokeWavesTxCheckers.scala @@ -0,0 +1,142 @@ +package com.wavesplatform.events.fixtures + +import com.wavesplatform.account.Address +import com.wavesplatform.events.BlockchainUpdatesTestBase +import com.wavesplatform.events.BlockchainUpdatesTestBase.filterOutMinerBalanceUpdates +import com.wavesplatform.events.StateUpdate.LeaseUpdate.LeaseStatus +import com.wavesplatform.events.fixtures.PrepareInvokeTestData.* +import com.wavesplatform.events.fixtures.WavesTxChecks.* +import com.wavesplatform.events.protobuf.BlockchainUpdated.Append +import com.wavesplatform.events.protobuf.TransactionMetadata.InvokeScriptMetadata +import com.wavesplatform.protobuf.transaction.PBAmounts.toVanillaAssetId +import com.wavesplatform.state.{BinaryDataEntry, BooleanDataEntry, DataEntry, EmptyDataEntry, IntegerDataEntry, StringDataEntry} +import com.wavesplatform.transaction.Asset +import com.wavesplatform.transaction.Asset.Waves +import com.wavesplatform.transaction.TxHelpers.secondAddress +import com.wavesplatform.transaction.assets.IssueTransaction +import org.scalactic.source.Position + +object InvokeWavesTxCheckers extends BlockchainUpdatesTestBase { + def checkSimpleInvoke( + append: Append, + issue: IssueTransaction, + issuerAssetBalanceAfterTx: Long, + invokeScript: InvokeScriptMetadata, + invokeId: Array[Byte] + ): Unit = { + val assetId = issue.assetId.arr + + val dataEntry: Seq[DataEntry[?]] = Seq[DataEntry[?]]( + EmptyDataEntry("int"), + BinaryDataEntry("byte", issue.asset.id), + BooleanDataEntry("bool", value = true), + StringDataEntry("str", "test_string") + ) + val actualData = Seq( + ("int", dataMap.apply("intVal")), + ("byte", assetId), + ("bool", true), + ("str", dataMap.apply("stringVal")), + ("int", None) + ) + + val arguments = invokeScript.arguments + val result = invokeScript.result.get + val invokeIssueAsset = toVanillaAssetId(result.issues.head.assetId) + val invokeLeaseId = result.leases.head.leaseId.toByteArray + val dataEntries = append.transactionStateUpdates.head.dataEntries + val assetDetails = append.transactionStateUpdates.head.assets + val expectedArgumentsValues = List(assetId, secondTxParticipantAddress.bytes) + val actualArgumentsValues = List( + arguments.head.value.binaryValue.get.toByteArray, + arguments.apply(1).value.binaryValue.get.toByteArray + ) + + checkArguments(expectedArgumentsValues, actualArgumentsValues) + checkInvokeScriptResultData(result.data, actualData) + checkInvokeScriptResultIssues(result.issues.head, issueData) + checkInvokeScriptResultTransfers(result.transfers.head, secondTxParticipantAddress, scriptTransferAssetNum, issue.asset) + checkInvokeScriptResultTransfers(result.transfers.apply(1), secondTxParticipantAddress, scriptTransferIssueAssetNum, invokeIssueAsset) + checkInvokeScriptResultTransfers(result.transfers.apply(2), secondTxParticipantAddress, scriptTransferUnitNum, Waves) + checkInvokeScriptResultReissue(result.reissues.head, issue.asset, reissueNum, reissuable = true) + checkInvokeScriptResultBurn(result.burns.head, issue.asset, burnNum) + checkInvokeScriptResultSponsorFee(result.sponsorFees.head, issue.asset, sponsorFeeAssetNum) + checkInvokeScriptResultSponsorFee(result.sponsorFees.apply(1), invokeIssueAsset, sponsorFeeIssueAssetNum) + checkInvokeScriptResultLease(result.leases.head, secondTxParticipantPKHash, leaseNum) + checkInvokeScriptResultLeaseCancel(result.leaseCancels.head, invokeLeaseId) + checkDataEntriesStateUpdate(dataEntries, dataEntry, firstTxParticipantAddress.bytes) + checkAssetsStateUpdates(assetDetails.head.after, issueData, invokeIssueAsset, firstTxParticipant.publicKey.arr) + checkAssetsStateUpdates(assetDetails.apply(1).before, issue, isNft = false, issue.quantity.value) + checkAssetsStateUpdates(assetDetails.apply(1).after, issue, isNft = false, issuerAssetBalanceAfterTx + scriptTransferAssetNum) + checkIndividualLeases( + append.transactionStateUpdates.head.individualLeases, + Map( + ( + LeaseStatus.Inactive, + leaseNum + ) -> (invokeLeaseId, firstTxParticipant.publicKey.arr, secondTxParticipantAddress.bytes, invokeId) + ) + ) + } + + def checkDoubleNestingInvoke( + append: Append, + invokeScript: InvokeScriptMetadata, + issue: IssueTransaction, + assetDappAddress: Address, + nestedTransferAddress: Address, + doubleNestedTransferAddress: Address + ): Unit = { + val scriptTransferWavesSum = scriptTransferUnitNum * 2 + val asset = issue.asset + val actualData = Seq(("bar", scriptTransferWavesSum)) + val arguments = invokeScript.arguments + val result = invokeScript.result.get + val invokes = result.invokes.head + val invokesStateChangeInvoke = invokes.stateChanges.get.invokes.head + val actualDataEntries = append.transactionStateUpdates.head.dataEntries + val expectDataEntries: Seq[DataEntry[?]] = Seq[DataEntry[?]](IntegerDataEntry(bar, scriptTransferWavesSum)) + val expectedValues: List[Any] = List(secondAddress.bytes, assetDappAddress.bytes, scriptTransferUnitNum, bar, issue.asset.id.arr) + val actualArguments: List[Any] = List( + arguments.head.value.binaryValue.get.toByteArray, + arguments(1).value.binaryValue.get.toByteArray, + arguments(2).value.integerValue.get, + arguments(3).value.stringValue.get, + arguments(4).value.binaryValue.get.toByteArray + ) + + checkArguments(expectedValues, actualArguments) + checkInvokeScriptResultData(result.data, actualData) + checkInvokeScriptBaseInvokes(invokes, secondAddress, bar) + checkInvokeScriptInvokesArgs(invokes.call.get.args.head, scriptTransferUnitNum) + checkInvokeScriptInvokesArgs(invokes.call.get.args.apply(1), asset.id.arr) + checkInvokeScriptInvokesArgs(invokes.call.get.args.apply(2), assetDappAddress.bytes) + checkInvokeScriptInvokesPayments(invokes.payments.head, asset, paymentNum) + checkInvokeScriptResultTransfers(invokes.stateChanges.get.transfers.head, nestedTransferAddress, scriptTransferAssetNum, asset) + checkInvokeScriptBaseInvokes(invokesStateChangeInvoke, assetDappAddress, baz) + checkInvokeScriptInvokesArgs(invokesStateChangeInvoke.call.get.args.head, scriptTransferUnitNum) + checkInvokeScriptResultTransfers( + invokesStateChangeInvoke.stateChanges.get.transfers.head, + doubleNestedTransferAddress, + scriptTransferUnitNum, + Waves + ) + checkDataEntriesStateUpdate(actualDataEntries, expectDataEntries, firstTxParticipantAddress.bytes) + } + + def checkInvokeDoubleNestedBlockchainUpdates( + append: Append, + invokeScript: InvokeScriptMetadata, + transferAddress: Address, + nestedTransferAddress: Address, + doubleNestedTransferAddress: Address, + issue: IssueTransaction, + expectBalancesMap: Map[(Address, Asset), (Long, Long)] + )(implicit pos: Position): Unit = { + val actualDataEntries = append.transactionStateUpdates.head.dataEntries + checkDoubleNestingInvoke(append, invokeScript, issue, transferAddress, nestedTransferAddress, doubleNestedTransferAddress) + checkDataEntriesStateUpdate(actualDataEntries, expectDataEntries, firstTxParticipantAddress.bytes) + + checkBalances(filterOutMinerBalanceUpdates(append), expectBalancesMap) + } +} diff --git a/grpc-server/src/test/scala/com/wavesplatform/events/fixtures/PrepareInvokeTestData.scala b/grpc-server/src/test/scala/com/wavesplatform/events/fixtures/PrepareInvokeTestData.scala index 352f1dfdb78..271b4a3bcfa 100644 --- a/grpc-server/src/test/scala/com/wavesplatform/events/fixtures/PrepareInvokeTestData.scala +++ b/grpc-server/src/test/scala/com/wavesplatform/events/fixtures/PrepareInvokeTestData.scala @@ -10,6 +10,7 @@ object PrepareInvokeTestData { val reissueNum: Int = 50000 val burnNum: Int = 100000 val leaseNum: Long = 200000 + val foo = "foo" val baz = "baz" val bar = "bar" diff --git a/grpc-server/src/test/scala/com/wavesplatform/events/fixtures/WavesTxChecks.scala b/grpc-server/src/test/scala/com/wavesplatform/events/fixtures/WavesTxChecks.scala index bf99ea808b9..bb8a73ad3cb 100644 --- a/grpc-server/src/test/scala/com/wavesplatform/events/fixtures/WavesTxChecks.scala +++ b/grpc-server/src/test/scala/com/wavesplatform/events/fixtures/WavesTxChecks.scala @@ -23,6 +23,7 @@ import com.wavesplatform.transaction.{Asset, CreateAliasTransaction, DataTransac import org.scalactic.source.Position import org.scalatest.OptionValues import org.scalatest.matchers.should.Matchers +import org.scalatest.matchers.{MatchResult, Matcher} object WavesTxChecks extends Matchers with OptionValues { import PBAmounts.* @@ -219,7 +220,7 @@ object WavesTxChecks extends Matchers with OptionValues { } } - def checkInvokeTransaction(actualId: ByteString, actual: SignedTransaction, expected: InvokeScriptTransaction, publicKeyHash: Array[Byte])(implicit + def checkInvokeTransaction(actualId: ByteString, actual: SignedTransaction, expected: TransactionBase, publicKeyHash: Array[Byte])(implicit pos: Position ): Unit = { checkBaseTx(actualId, actual, expected) @@ -230,16 +231,45 @@ object WavesTxChecks extends Matchers with OptionValues { } } - def checkInvokeBaseTransactionMetadata(actual: Seq[TransactionMetadata], expected: InvokeScriptTransaction)(implicit + def checkEthereumInvokeTransaction(actualId: ByteString, actual: SignedTransaction, expected: EthereumTransaction, publicKeyHash: Array[Byte])( + implicit pos: Position + ): Unit = { + checkBaseTx(actualId, actual, expected) + actual.transaction.wavesTransaction.value.data match { + case Data.InvokeScript(value) => + value.dApp.get.getPublicKeyHash.toByteArray shouldBe publicKeyHash + case _ => fail("not a InvokeScript transaction") + } + } + + def checkInvokeBaseTransactionMetadata(transactionMetadata: TransactionMetadata, expected: InvokeScriptTransaction)(implicit pos: Position ): Unit = { - val invokeScript = actual.head.getInvokeScript + val invokeScript = transactionMetadata.getInvokeScript - actual.head.senderAddress.toByteArray shouldBe expected.senderAddress.bytes + transactionMetadata.senderAddress.toByteArray shouldBe expected.senderAddress.bytes invokeScript.dAppAddress.toByteArray shouldBe expected.dApp.bytes invokeScript.functionName shouldBe expected.funcCallOpt.get.function.funcName } + def checkEthereumInvokeBaseTransactionMetadata( + transactionMetadata: TransactionMetadata, + expected: EthereumTransaction, + funcName: String, + dAppAddress: Address + )(implicit + pos: Position + ): Unit = { + val ethereumMetadata = transactionMetadata.getEthereum + + transactionMetadata.senderAddress.toByteArray shouldBe expected.senderAddress.value().bytes + ethereumMetadata.getInvoke.dAppAddress.toByteArray shouldBe dAppAddress.bytes + ethereumMetadata.getInvoke.functionName shouldBe funcName + ethereumMetadata.fee shouldBe expected.fee + ethereumMetadata.timestamp shouldBe expected.timestamp + ethereumMetadata.senderPublicKey.toByteArray shouldBe expected.sender.arr + } + def checkArguments(expectedValues: List[Any], actualArguments: List[Any]): Unit = { if (expectedValues.size != actualArguments.size) { throw new IllegalArgumentException("Number of expected values does not match the number of actual arguments.") @@ -353,18 +383,70 @@ object WavesTxChecks extends Matchers with OptionValues { def checkEthereumTransaction(actualId: ByteString, actual: SignedTransaction, expected: EthereumTransaction)(implicit pos: Position): Unit = { checkBaseTx(actualId, actual, expected) - actual.transaction.ethereumTransaction.value.toByteArray shouldBe expected.bytes.value() + withClue("ethereum transaction bytes") { + actual.transaction.ethereumTransaction.value.toByteArray shouldBe expected.bytes() + } } - def checkBalances(actual: Seq[BalanceUpdate], expected: Map[(Address, Asset), (Long, Long)])(implicit pos: Position): Unit = { - actual.map { bu => - ( - (Address.fromBytes(bu.address.toByteArray).explicitGet(), toVanillaAssetId(bu.amountAfter.value.assetId)), - (bu.amountBefore, bu.amountAfter.value.amount) + class BalanceUpdateMatcher(expected: Map[(Address, Asset), (Long, Long)]) extends Matcher[Seq[BalanceUpdate]] { + override def apply(actualBalances: Seq[BalanceUpdate]): MatchResult = { + val mismatchedBalancesB = Seq.newBuilder[(Address, Asset, (Long, Long), (Long, Long))] + val unexpectedBalancesB = Seq.newBuilder[BalanceUpdate] + val unmetExpectations = actualBalances.foldLeft(expected) { case (prevExpected, b) => + val addr = Address.fromBytes(b.address.toByteArray).explicitGet() + val asset = toVanillaAssetId(b.amountAfter.value.assetId) + prevExpected.get(addr -> asset) match { + case Some((expectedBefore, expectedAfter)) => + if (expectedBefore != b.amountBefore || expectedAfter != b.amountAfter.value.amount) { + mismatchedBalancesB += ((addr, asset, (expectedBefore, expectedAfter), (b.amountBefore, b.amountAfter.value.amount))) + } + prevExpected.removed(addr -> asset) + case None => + unexpectedBalancesB += b + prevExpected + } + } + + val mismatched = mismatchedBalancesB.result() + val unexpected = unexpectedBalancesB.result() + + val errorMessage = new StringBuilder("Actual balances did not match expectations.") + if (unmetExpectations.nonEmpty) { + errorMessage.append("\nThe following expected balance updates were not found:") + unmetExpectations.foreach { case ((address, asset), (before, after)) => + errorMessage.append(s"\n$address $asset: $before->$after") + } + } + if (unexpected.nonEmpty) { + errorMessage.append("\nThe following balance updates were not expected:") + unexpected.foreach { b => + errorMessage.append( + s"\n${Address.fromBytes(b.address.toByteArray).explicitGet()} ${toVanillaAssetId(b.amountAfter.value.assetId)}: ${b.amountBefore} -> ${b.amountAfter.value.amount}" + ) + } + } + if (mismatched.nonEmpty) { + errorMessage.append("The following balances did not match:") + mismatched.foreach { case (address, asset, expected, actual) => + errorMessage.append( + s"\n$address $asset: expected $expected != actual $actual" + ) + } + } + + MatchResult( + unmetExpectations.isEmpty && mismatched.isEmpty && unexpected.isEmpty, + errorMessage.toString(), + "Actual balances did not differ from the expected balances" ) - }.toMap shouldBe expected + } } + def matchBalances(expected: Map[(Address, Asset), (Long, Long)]): Matcher[Seq[BalanceUpdate]] = new BalanceUpdateMatcher(expected) + + def checkBalances(actual: Seq[BalanceUpdate], expected: Map[(Address, Asset), (Long, Long)])(implicit pos: Position): Unit = + actual should matchBalances(expected) + def checkMassTransferBalances(actual: Seq[BalanceUpdate], expected: Map[(Address, Asset), (Long, Long)]): Unit = { val actualBalances = actual.map { bu => ( diff --git a/lang/js/src/main/scala/com/wavesplatform/lang/Global.scala b/lang/js/src/main/scala/com/wavesplatform/lang/Global.scala index 1e172440c11..60f573fb05a 100644 --- a/lang/js/src/main/scala/com/wavesplatform/lang/Global.scala +++ b/lang/js/src/main/scala/com/wavesplatform/lang/Global.scala @@ -120,9 +120,8 @@ object Global extends BaseGlobal { if (value.toLong.toDouble == value && value - 1 < Long.MaxValue) BD.valueOf(value.toLong) else BD.valueOf(value) - Right(BigInt(decimal - .setScale(scale.toInt, round.mode) - .unscaledValue)) + val scaled = decimal.setScale(scale.toInt, round.mode).unscaledValue + Right(BigInt(scaled)) } implicit class BigIntOps(val v: BigInteger) extends AnyVal { @@ -143,7 +142,4 @@ object Global extends BaseGlobal { override def ecrecover(messageHash: Array[Byte], signature: Array[Byte]): Array[Byte] = ??? - - override def isIllFormed(s: String): Boolean = - false } diff --git a/lang/jvm/src/main/scala/com/wavesplatform/common/ByteStrComparator.scala b/lang/jvm/src/main/scala/com/wavesplatform/common/ByteStrComparator.scala deleted file mode 100644 index fd1d2144e4d..00000000000 --- a/lang/jvm/src/main/scala/com/wavesplatform/common/ByteStrComparator.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.wavesplatform.common - -import com.google.common.primitives.UnsignedBytes -import com.wavesplatform.common.state.ByteStr - -object ByteStrComparator { - def compare(bs1: ByteStr, bs2: ByteStr): Int = UnsignedBytes.lexicographicalComparator().compare(bs1.arr, bs2.arr) -} diff --git a/lang/jvm/src/main/scala/com/wavesplatform/crypto/Curve25519.scala b/lang/jvm/src/main/scala/com/wavesplatform/crypto/Curve25519.scala index 3e19e95287c..40f876471ff 100644 --- a/lang/jvm/src/main/scala/com/wavesplatform/crypto/Curve25519.scala +++ b/lang/jvm/src/main/scala/com/wavesplatform/crypto/Curve25519.scala @@ -1,16 +1,9 @@ package com.wavesplatform.crypto -import java.lang.reflect.Constructor - import org.whispersystems.curve25519.OpportunisticCurve25519Provider object Curve25519 { - private lazy val provider: OpportunisticCurve25519Provider = { - val constructor = classOf[OpportunisticCurve25519Provider].getDeclaredConstructors.head - .asInstanceOf[Constructor[OpportunisticCurve25519Provider]] - constructor.setAccessible(true) - constructor.newInstance() - } + private lazy val provider = new OpportunisticCurve25519Provider() val KeyLength: Int = 32 diff --git a/lang/jvm/src/main/scala/com/wavesplatform/lang/Global.scala b/lang/jvm/src/main/scala/com/wavesplatform/lang/Global.scala index 1b958887b72..bc34adde7c3 100644 --- a/lang/jvm/src/main/scala/com/wavesplatform/lang/Global.scala +++ b/lang/jvm/src/main/scala/com/wavesplatform/lang/Global.scala @@ -1,11 +1,7 @@ package com.wavesplatform.lang -import java.math.{BigInteger, MathContext, BigDecimal => BD} -import java.security.spec.InvalidKeySpecException - -import cats.syntax.either._ +import cats.syntax.either.* import ch.obermuhlner.math.big.BigDecimalMath -import com.google.common.base.Utf8 import com.google.common.io.BaseEncoding import com.wavesplatform.common.merkle.Merkle import com.wavesplatform.common.utils.{Base58, Base64} @@ -14,11 +10,13 @@ import com.wavesplatform.lang.v1.BaseGlobal import com.wavesplatform.lang.v1.evaluator.ctx.impl.Rounding import com.wavesplatform.lang.v1.evaluator.ctx.impl.crypto.RSA import com.wavesplatform.lang.v1.evaluator.ctx.impl.crypto.RSA.DigestAlgorithm -import com.wavesplatform.zwaves.bls12.{Groth16 => Bls12Groth16} -import com.wavesplatform.zwaves.bn256.{Groth16 => Bn256Groth16} +import com.wavesplatform.zwaves.bls12.Groth16 as Bls12Groth16 +import com.wavesplatform.zwaves.bn256.Groth16 as Bn256Groth16 import org.web3j.crypto.Sign import org.web3j.crypto.Sign.SignatureData +import java.math.{BigInteger, MathContext, BigDecimal as BD} +import java.security.spec.InvalidKeySpecException import scala.annotation.tailrec import scala.util.Try @@ -82,8 +80,8 @@ object Global extends BaseGlobal { private val longContext = new MathContext(longDigits) private val oldLongContext = MathContext.DECIMAL128 - private val bigIntDigits = 154 - private val bigMathContext = new MathContext(bigIntDigits) + private val bigIntDigits = 154 + private val bigMathContext = new MathContext(bigIntDigits) private val oldBigMathContext = new MathContext(156 + 40) // Math functions @@ -125,10 +123,8 @@ object Global extends BaseGlobal { def powBigInt(b: BigInt, bp: Long, e: BigInt, ep: Long, rp: Long, round: Rounding, useNewPrecision: Boolean): Either[String, BigInt] = tryEither { - val base = toJBig(b, bp) - val exp = toJBig(e, ep) - - + val base = toJBig(b, bp) + val exp = toJBig(e, ep) val context = if (useNewPrecision) bigMathContext else oldBigMathContext val res = if (exp == BigDecimal(0.5).bigDecimal) { @@ -187,7 +183,4 @@ object Global extends BaseGlobal { val pk = Sign.signedMessageHashToKey(messageHash, signatureData) base16Encoder.decode(pk.toString(16)) } - - override def isIllFormed(s: String): Boolean = - Try(Utf8.encodedLength(s)).isFailure } diff --git a/lang/shared/src/main/scala/com/wavesplatform/common/state/ByteStr.scala b/lang/shared/src/main/scala/com/wavesplatform/common/state/ByteStr.scala index be469868ec8..523ad161604 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/common/state/ByteStr.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/common/state/ByteStr.scala @@ -1,10 +1,9 @@ package com.wavesplatform.common.state -import scala.util.Try - -import com.wavesplatform.common._ import com.wavesplatform.common.utils.{Base58, Base64} +import scala.util.Try + case class ByteStr(arr: Array[Byte]) { private[this] lazy val base58: String = Base58.encode(arr) lazy val base64Raw: String = Base64.encode(arr) @@ -67,7 +66,7 @@ object ByteStr { def fromLong(longValue: Long): ByteStr = { val buf = new Array[Byte](8) - var b = longValue + var b = longValue for (i <- (buf.length - 1) to 0 by -1) { buf(i) = b.toByte @@ -86,6 +85,4 @@ object ByteStr { def decodeBase64(s: String): Try[ByteStr] = Base64.tryDecode(s).map { bs => ByteStr(bs) } - - implicit val byteStrOrdering: Ordering[ByteStr] = (x, y) => ByteStrComparator.compare(x, y) } diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/contract/meta/MetaVersion.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/contract/meta/MetaVersion.scala index 1124ff4b8b7..5861f93a86b 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/contract/meta/MetaVersion.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/contract/meta/MetaVersion.scala @@ -8,12 +8,12 @@ sealed trait MetaVersion { object V1 extends MetaVersion { override type Self = V1.type - override val strategy = MetaMapperStrategyV1 + override val strategy: MetaMapperStrategy[Self] = MetaMapperStrategyV1 override val number: Int = 1 } object V2 extends MetaVersion { override type Self = V2.type - override val strategy = MetaMapperStrategyV2 + override val strategy: MetaMapperStrategy[Self] = MetaMapperStrategyV2 override val number: Int = 2 } diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/directives/DirectiveKey.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/directives/DirectiveKey.scala index 9f74d99740a..aeb03fdfda6 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/directives/DirectiveKey.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/directives/DirectiveKey.scala @@ -1,6 +1,6 @@ package com.wavesplatform.lang.directives -import com.wavesplatform.lang.directives.values._ +import com.wavesplatform.lang.directives.values.* sealed trait DirectiveKey { type Value <: DirectiveValue @@ -28,10 +28,10 @@ object DirectiveKey { override val valueMapper = mapper } - implicit lazy val STDLIB_VERSION = DirectiveKey.predefined[StdLibVersion]("STDLIB_VERSION") - implicit lazy val CONTENT_TYPE = DirectiveKey.predefined[ContentType]("CONTENT_TYPE") - implicit lazy val SCRIPT_TYPE = DirectiveKey.predefined[ScriptType]("SCRIPT_TYPE") - implicit lazy val IMPORT = DirectiveKey.arbitrary[Imports]("IMPORT") + lazy val STDLIB_VERSION = DirectiveKey.predefined[StdLibVersion]("STDLIB_VERSION") + lazy val CONTENT_TYPE = DirectiveKey.predefined[ContentType]("CONTENT_TYPE") + lazy val SCRIPT_TYPE = DirectiveKey.predefined[ScriptType]("SCRIPT_TYPE") + lazy val IMPORT = DirectiveKey.arbitrary[Imports]("IMPORT") lazy val all: Set[DirectiveKey] = Set( diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/directives/values/ContentType.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/directives/values/ContentType.scala index acbc8435a8a..1421de84de4 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/directives/values/ContentType.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/directives/values/ContentType.scala @@ -1,10 +1,10 @@ package com.wavesplatform.lang.directives.values -import com.wavesplatform.lang.directives.DirectiveDictionary +import com.wavesplatform.lang.directives.{DirectiveDictionary, DirectiveKey} sealed abstract class ContentType(text: String, id: Int) extends DirectiveValue(text, id) { - override val value: Any = text - override def key = resolveKey[ContentType] + override val value: Any = text + override def key: DirectiveKey = DirectiveKey.CONTENT_TYPE } case object Expression extends ContentType("EXPRESSION", 1) case object DApp extends ContentType("DAPP", 2) @@ -12,8 +12,8 @@ case object Library extends ContentType("LIBRARY", 3) object ContentType { implicit object ContentDic extends DirectiveDictionary[ContentType] { - override val default: ContentType = Expression - override val all: Iterable[ContentType] = Seq(Expression, DApp, Library) + override val default: ContentType = Expression + override val all: Iterable[ContentType] = Seq(Expression, DApp, Library) } def isDApp(isDApp: Boolean): ContentType = if (isDApp) DApp else Expression diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/directives/values/Imports.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/directives/values/Imports.scala index 50798305679..2406c8239e8 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/directives/values/Imports.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/directives/values/Imports.scala @@ -1,9 +1,9 @@ package com.wavesplatform.lang.directives.values -import com.wavesplatform.lang.directives._ +import com.wavesplatform.lang.directives.* case class Imports(fileNames: List[String] = Nil) extends DirectiveValue(fileNames.mkString(", "), 0) { - override def key: DirectiveKey = resolveKey[Imports] + override def key: DirectiveKey = DirectiveKey.IMPORT override val value: Any = text } diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/directives/values/ScriptType.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/directives/values/ScriptType.scala index bd745900dfe..cb8174302fa 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/directives/values/ScriptType.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/directives/values/ScriptType.scala @@ -1,10 +1,9 @@ package com.wavesplatform.lang.directives.values -import com.wavesplatform.lang.directives.DirectiveDictionary +import com.wavesplatform.lang.directives.{DirectiveDictionary, DirectiveKey} -//noinspection TypeAnnotation sealed abstract class ScriptType(text: String, id: Int) extends DirectiveValue(text, id) { - override val value: Any = text - override def key = resolveKey[ScriptType] + override val value: Any = text + override def key: DirectiveKey = DirectiveKey.SCRIPT_TYPE } case object Account extends ScriptType("ACCOUNT", 1) case object Asset extends ScriptType("ASSET", 2) diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/directives/values/StdLibVersion.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/directives/values/StdLibVersion.scala index 4aaf21d4c94..742f48aef54 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/directives/values/StdLibVersion.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/directives/values/StdLibVersion.scala @@ -1,9 +1,9 @@ package com.wavesplatform.lang.directives.values -import com.wavesplatform.lang.directives.DirectiveDictionary +import com.wavesplatform.lang.directives.{DirectiveDictionary, DirectiveKey} sealed abstract class StdLibVersion(id: Int) extends DirectiveValue(id.toString, id) with Product with Serializable with Ordered[StdLibVersion] { - override val value: Any = id - override def key = resolveKey[StdLibVersion] + override val value: Any = id + override def key: DirectiveKey = DirectiveKey.STDLIB_VERSION override def compare(that: StdLibVersion): Int = id compare that.id } @@ -20,5 +20,6 @@ object StdLibVersion { implicit object VersionDic extends DirectiveDictionary[StdLibVersion] { override val default: StdLibVersion = V3 override val all: Iterable[StdLibVersion] = Seq(V1, V2, V3, V4, V5, V6, V7, V8) + val latest: StdLibVersion = all.last } } diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/package.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/package.scala index d3264a79f46..91ca2014490 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/package.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/package.scala @@ -1,13 +1,13 @@ package com.wavesplatform -import cats.{Eval, Id, Monad, StackSafeMonad} import cats.data.EitherT +import cats.{Eval, Id, Monad, StackSafeMonad} import monix.eval.Coeval package object lang { implicit def toError(msg: String): CommonError = CommonError(msg) - type ExecutionLog = String + type ExecutionLog = String type CoevalF[F[_], A] = Coeval[F[A]] type EvalF[F[_], A] = Eval[F[A]] @@ -20,4 +20,20 @@ package object lang { override def pure[A](x: A): Coeval[A] = Coeval.now(x) } + + implicit class StringOps(val s: String) extends AnyVal { + def isWellFormed: Boolean = { + var i = 0 + var wellFormed = true + while (i < s.length && wellFormed) { + val c = s.charAt(i) + if (Character.isSurrogate(c)) { + if (s.codePointAt(i) == c) wellFormed = false + else i += 1 + } + i += 1 + } + wellFormed + } + } } diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/script/v1/ExprScript.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/script/v1/ExprScript.scala index f6671d672c0..b59aa393c63 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/script/v1/ExprScript.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/script/v1/ExprScript.scala @@ -3,7 +3,6 @@ package com.wavesplatform.lang.script.v1 import cats.instances.either._ import cats.syntax.either._ import cats.syntax.flatMap._ -import com.google.common.annotations.VisibleForTesting import com.wavesplatform.common.state.ByteStr import com.wavesplatform.lang.directives.values._ import com.wavesplatform.lang.script.Script @@ -29,7 +28,6 @@ object ExprScript { s"Script is too large: ${bs.length} bytes > $limit bytes" ) } - @VisibleForTesting def apply(x: EXPR): Either[String, Script] = apply(V1, x) def apply(version: StdLibVersion, x: EXPR, isFreeCall: Boolean = false, checkSize: Boolean = true): Either[String, ExprScript] = diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/BaseGlobal.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/BaseGlobal.scala index b4c538f106f..9e5002fdba5 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/BaseGlobal.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/BaseGlobal.scala @@ -385,8 +385,6 @@ trait BaseGlobal { } } } - - def isIllFormed(s: String): Boolean } object BaseGlobal { diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/CompilationError.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/CompilationError.scala index 08e377eb8f4..243fa22889e 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/CompilationError.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/CompilationError.scala @@ -1,7 +1,5 @@ package com.wavesplatform.lang.v1.compiler -import java.nio.charset.StandardCharsets - import cats.Show import com.wavesplatform.lang.v1.ContractLimits import com.wavesplatform.lang.v1.compiler.Types.* @@ -9,6 +7,8 @@ import com.wavesplatform.lang.v1.evaluator.ctx.FunctionTypeSignature import com.wavesplatform.lang.v1.parser.Expressions import com.wavesplatform.lang.v1.parser.Expressions.{Declaration, PART} +import java.nio.charset.StandardCharsets + sealed trait CompilationError { def start: Int def end: Int @@ -52,18 +52,11 @@ object CompilationError { s"but ${names.map(n => s"`$n`").mkString(", ")} found" } - final case class UnusedCaseVariables(start: Int, end: Int, names: List[String]) extends CompilationError { - val message = s"Unused case variable(s) ${names.map(n => s"`$n`").mkString(", ")}" - } - final case class AlreadyDefined(start: Int, end: Int, name: String, isFunction: Boolean) extends CompilationError { val message = if (isFunction) s"Value '$name' can't be defined because function with this name is already defined" else s"Value '$name' already defined in the scope" } - final case class NonExistingType(start: Int, end: Int, name: String, existing: List[String]) extends CompilationError { - val message = s"Value '$name' declared as non-existing type, while all possible types are $existing" - } final case class BadFunctionSignatureSameArgNames(start: Int, end: Int, name: String) extends CompilationError { val message = s"Function '$name' declared with duplicating argument names" diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/CompilationStepResultDec.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/CompilationStepResultDec.scala new file mode 100644 index 00000000000..aa0f6f7537f --- /dev/null +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/CompilationStepResultDec.scala @@ -0,0 +1,12 @@ +package com.wavesplatform.lang.v1.compiler + +import com.wavesplatform.lang.v1.compiler.Types.FINAL +import com.wavesplatform.lang.v1.parser.Expressions + +case class CompilationStepResultDec( + ctx: CompilerContext, + dec: Terms.DECLARATION, + t: FINAL, + parseNodeExpr: Expressions.Declaration, + errors: Iterable[CompilationError] = Iterable.empty +) diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/CompilationStepResultExpr.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/CompilationStepResultExpr.scala new file mode 100644 index 00000000000..bf8eb9fd0c5 --- /dev/null +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/CompilationStepResultExpr.scala @@ -0,0 +1,12 @@ +package com.wavesplatform.lang.v1.compiler + +import com.wavesplatform.lang.v1.compiler.Types.FINAL +import com.wavesplatform.lang.v1.parser.Expressions + +case class CompilationStepResultExpr( + ctx: CompilerContext, + expr: Terms.EXPR, + t: FINAL, + parseNodeExpr: Expressions.EXPR, + errors: Iterable[CompilationError] = Iterable.empty +) diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/ContractCompiler.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/ContractCompiler.scala index a8647939e8c..1240d5aae79 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/ContractCompiler.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/ContractCompiler.scala @@ -13,7 +13,7 @@ import com.wavesplatform.lang.contract.meta.{MetaMapper, V1 as MetaV1, V2 as Met import com.wavesplatform.lang.directives.values.{StdLibVersion, V3, V6} import com.wavesplatform.lang.v1.compiler.CompilationError.{AlreadyDefined, Generic, UnionNotAllowedForCallableArgs, WrongArgumentType} import com.wavesplatform.lang.v1.compiler.CompilerContext.{VariableInfo, vars} -import com.wavesplatform.lang.v1.compiler.ExpressionCompiler.* +import com.wavesplatform.lang.v1.compiler.ContractCompiler.* import com.wavesplatform.lang.v1.compiler.ScriptResultSource.FreeCall import com.wavesplatform.lang.v1.compiler.Terms.EXPR import com.wavesplatform.lang.v1.compiler.Types.{BOOLEAN, BYTESTR, LONG, STRING} @@ -25,16 +25,13 @@ import com.wavesplatform.lang.v1.parser.Expressions.{FUNC, PART, Type} import com.wavesplatform.lang.v1.parser.Parser.LibrariesOffset import com.wavesplatform.lang.v1.parser.{Expressions, Parser} import com.wavesplatform.lang.v1.task.imports.* -import com.wavesplatform.lang.v1.{ContractLimits, FunctionHeader, compiler} +import com.wavesplatform.lang.v1.{ContractLimits, FunctionHeader} import scala.annotation.tailrec -object ContractCompiler { - val FreeCallInvocationArg = "i" - +class ContractCompiler(version: StdLibVersion) extends ExpressionCompiler(version) { private def compileAnnotatedFunc( af: Expressions.ANNOTATEDFUNC, - version: StdLibVersion, saveExprContext: Boolean, allowIllFormedStrings: Boolean, source: ScriptResultSource @@ -88,10 +85,10 @@ object ContractCompiler { _.flatMap(_.dic(version).toList).map(nameAndType => (nameAndType._1, VariableInfo(AnyPos, nameAndType._2))) ) .getOrElse(List.empty) - unionInCallableErrs <- checkCallableUnions(af, annotationsWithErr._1.toList.flatten, version) + unionInCallableErrs <- checkCallableUnions(af, annotationsWithErr._1.toList.flatten) compiledBody <- local { modify[Id, CompilerContext, CompilationError](vars.modify(_)(_ ++ annotationBindings)).flatMap(_ => - compiler.ExpressionCompiler.compileFunc(af.f.position, af.f, saveExprContext, annotationBindings.map(_._1), allowIllFormedStrings) + compileFunc(af.f.position, af.f, saveExprContext, annotationBindings.map(_._1), allowIllFormedStrings) ) } annotatedFuncWithErr <- getCompiledAnnotatedFunc(annotationsWithErr, compiledBody._1).handleError() @@ -132,7 +129,6 @@ object ContractCompiler { private def compileContract( parsedDapp: Expressions.DAPP, - version: StdLibVersion, needCompaction: Boolean, removeUnusedCode: Boolean, source: ScriptResultSource, @@ -149,7 +145,7 @@ object ContractCompiler { annFuncArgTypesErr <- validateAnnotatedFuncsArgTypes(parsedDapp).handleError() compiledAnnFuncsWithErr <- parsedDapp.fs .traverse[CompileM, (Option[AnnotatedFunction], List[(String, Types.FINAL)], Expressions.ANNOTATEDFUNC, Iterable[CompilationError])](af => - local(compileAnnotatedFunc(af, version, saveExprContext, allowIllFormedStrings, source)) + local(compileAnnotatedFunc(af, saveExprContext, allowIllFormedStrings, source)) ) annotatedFuncs = compiledAnnFuncsWithErr.filter(_._1.nonEmpty).map(_._1.get) parsedNodeAFuncs = compiledAnnFuncsWithErr.map(_._3) @@ -236,7 +232,7 @@ object ContractCompiler { } yield result } - def handleValid[T](part: PART[T]): CompileM[PART.VALID[T]] = part match { + private def handleValid[T](part: PART[T]): CompileM[PART.VALID[T]] = part match { case x: PART.VALID[T] => x.pure[CompileM] case PART.INVALID(p, message) => raiseError(Generic(p.start, p.end, message)) } @@ -305,13 +301,7 @@ object ContractCompiler { } } - val primitiveCallableTypes: Set[String] = - Set(LONG, BYTESTR, BOOLEAN, STRING).map(_.name) - - val allowedCallableTypesV4: Set[String] = - primitiveCallableTypes + "List[]" - - private def validateDuplicateVarsInContract(contract: Expressions.DAPP): CompileM[Any] = { + private def validateDuplicateVarsInContract(contract: Expressions.DAPP): CompileM[Any] = for { ctx <- get[Id, CompilerContext, CompilationError] annotationVars = contract.fs.flatMap(_.anns.flatMap(_.args)).traverse[CompileM, PART.VALID[String]](handleValid) @@ -339,7 +329,52 @@ object ContractCompiler { } } } yield () + + private def checkCallableUnions( + func: Expressions.ANNOTATEDFUNC, + annotations: List[Annotation], + ): CompileM[Seq[UnionNotAllowedForCallableArgs]] = { + @tailrec + def containsUnion(tpe: Type): Boolean = + tpe match { + case Expressions.Union(types) if types.size > 1 => true + case Expressions.Single(PART.VALID(_, Type.ListTypeName), Some(PART.VALID(_, Expressions.Union(types)))) if types.size > 1 => true + case Expressions.Single( + PART.VALID(_, Type.ListTypeName), + Some(PART.VALID(_, inner @ Expressions.Single(PART.VALID(_, Type.ListTypeName), _))) + ) => + containsUnion(inner) + case _ => false + } + + val isCallable = annotations.exists { + case CallableAnnotation(_) => true + case _ => false + } + + if (version < V6 || !isCallable) { + Seq.empty[UnionNotAllowedForCallableArgs].pure[CompileM] + } else { + func.f.args + .filter { case (_, tpe) => + containsUnion(tpe) + } + .map { case (argName, _) => + UnionNotAllowedForCallableArgs(argName.position.start, argName.position.end) + } + .pure[CompileM] + } } +} + +object ContractCompiler { + val FreeCallInvocationArg = "i" + + val primitiveCallableTypes: Set[String] = + Set(LONG, BYTESTR, BOOLEAN, STRING).map(_.name) + + val allowedCallableTypesV4: Set[String] = + primitiveCallableTypes + "List[]" def apply( c: CompilerContext, @@ -350,7 +385,8 @@ object ContractCompiler { removeUnusedCode: Boolean = false, allowIllFormedStrings: Boolean = false ): Either[String, DApp] = { - compileContract(contract, version, needCompaction, removeUnusedCode, source, allowIllFormedStrings = allowIllFormedStrings) + new ContractCompiler(version) + .compileContract(contract, needCompaction, removeUnusedCode, source, allowIllFormedStrings = allowIllFormedStrings) .run(c) .map( _._2 @@ -375,7 +411,7 @@ object ContractCompiler { val parser = new Parser(version)(offset) parser.parseContract(input) match { case fastparse.Parsed.Success(xs, _) => - ContractCompiler(ctx, xs, version, source, needCompaction, removeUnusedCode, allowIllFormedStrings) match { + apply(ctx, xs, version, source, needCompaction, removeUnusedCode, allowIllFormedStrings) match { case Left(err) => Left(err) case Right(c) => Right(c) } @@ -396,7 +432,8 @@ object ContractCompiler { new Parser(version)(offset) .parseDAPPWithErrorRecovery(input) .flatMap { case (parseResult, removedCharPosOpt) => - compileContract(parseResult, version, needCompaction, removeUnusedCode, ScriptResultSource.CallableFunction, saveExprContext) + new ContractCompiler(version) + .compileContract(parseResult, needCompaction, removeUnusedCode, ScriptResultSource.CallableFunction, saveExprContext) .run(ctx) .map( _._2 @@ -437,41 +474,4 @@ object ContractCompiler { Left(parser.toString(input, f)) } } - - private def checkCallableUnions( - func: Expressions.ANNOTATEDFUNC, - annotations: List[Annotation], - version: StdLibVersion - ): CompileM[Seq[UnionNotAllowedForCallableArgs]] = { - @tailrec - def containsUnion(tpe: Type): Boolean = - tpe match { - case Expressions.Union(types) if types.size > 1 => true - case Expressions.Single(PART.VALID(_, Type.ListTypeName), Some(PART.VALID(_, Expressions.Union(types)))) if types.size > 1 => true - case Expressions.Single( - PART.VALID(_, Type.ListTypeName), - Some(PART.VALID(_, inner @ Expressions.Single(PART.VALID(_, Type.ListTypeName), _))) - ) => - containsUnion(inner) - case _ => false - } - - val isCallable = annotations.exists { - case CallableAnnotation(_) => true - case _ => false - } - - if (version < V6 || !isCallable) { - Seq.empty[UnionNotAllowedForCallableArgs].pure[CompileM] - } else { - func.f.args - .filter { case (_, tpe) => - containsUnion(tpe) - } - .map { case (argName, _) => - UnionNotAllowedForCallableArgs(argName.position.start, argName.position.end) - } - .pure[CompileM] - } - } } diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/Decompiler.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/Decompiler.scala index c6c12a6fc8b..759af4e1dec 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/Decompiler.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/Decompiler.scala @@ -111,7 +111,8 @@ object Decompiler { } } - val MatchRef = """(\$match\d*)""".r + private val MatchRef = """(\$match\d*)""".r + private val EscapingSymbols = "[\\\\\"]".r private[lang] def expr(e: Coeval[EXPR], ctx: DecompilerContext, braces: BlockBraces, firstLinePolicy: FirstLinePolicy): Coeval[String] = { def checkBrackets(expr: EXPR) = expr match { @@ -161,8 +162,8 @@ object Decompiler { case Terms.TRUE => pureOut("true", i) case Terms.FALSE => pureOut("false", i) case Terms.CONST_BOOLEAN(b) => pureOut(b.toString.toLowerCase(), i) - case Terms.CONST_LONG(t) => pureOut(t.toLong.toString, i) - case Terms.CONST_STRING(s) => pureOut("\"" ++ s ++ "\"", i) + case Terms.CONST_LONG(t) => pureOut(t.toString, i) + case Terms.CONST_STRING(s) => pureOut("\"" ++ EscapingSymbols.replaceAllIn(s, "\\\\$0") ++ "\"", i) case Terms.CONST_BYTESTR(bs) => pureOut( if (bs.size <= 128) { "base58'" ++ bs.toString ++ "'" } diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/ExpressionCompiler.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/ExpressionCompiler.scala index 8eab2de33d2..9a9ae79997e 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/ExpressionCompiler.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/ExpressionCompiler.scala @@ -3,123 +3,27 @@ package com.wavesplatform.lang.v1.compiler import cats.implicits.* import cats.{Id, Show} import com.wavesplatform.common.state.ByteStr -import com.wavesplatform.lang.CommonError -import com.wavesplatform.lang.directives.values.StdLibVersion +import com.wavesplatform.lang.{CommonError, StringOps} +import com.wavesplatform.lang.directives.values.{StdLibVersion, V8} import com.wavesplatform.lang.v1.compiler.CompilationError.* import com.wavesplatform.lang.v1.compiler.CompilerContext.* +import com.wavesplatform.lang.v1.compiler.ExpressionCompiler.* import com.wavesplatform.lang.v1.compiler.Terms.* import com.wavesplatform.lang.v1.compiler.Types.* import com.wavesplatform.lang.v1.evaluator.EvaluatorV1.* import com.wavesplatform.lang.v1.evaluator.ctx.* import com.wavesplatform.lang.v1.evaluator.ctx.impl.GlobalValNames import com.wavesplatform.lang.v1.parser.BinaryOperation.* -import com.wavesplatform.lang.v1.parser.Expressions.{ - BINARY_OP, - CompositePattern, - ConstsPat, - MATCH_CASE, - ObjPat, - PART, - Pos, - Single, - TuplePat, - Type, - TypedVar -} +import com.wavesplatform.lang.v1.parser.Expressions.{BINARY_OP, CompositePattern, ConstsPat, MATCH_CASE, ObjPat, PART, Pos, Single, TuplePat, Type, TypedVar} import com.wavesplatform.lang.v1.parser.Parser.LibrariesOffset import com.wavesplatform.lang.v1.parser.{BinaryOperation, Expressions, Parser} import com.wavesplatform.lang.v1.task.imports.* -import com.wavesplatform.lang.v1.{BaseGlobal, ContractLimits, FunctionHeader} +import com.wavesplatform.lang.v1.{ContractLimits, FunctionHeader} import java.nio.charset.StandardCharsets import scala.util.Try -object ExpressionCompiler { - private val global: BaseGlobal = com.wavesplatform.lang.Global - - case class CompilationStepResultExpr( - ctx: CompilerContext, - expr: Terms.EXPR, - t: FINAL, - parseNodeExpr: Expressions.EXPR, - errors: Iterable[CompilationError] = Iterable.empty - ) - - case class CompilationStepResultDec( - ctx: CompilerContext, - dec: Terms.DECLARATION, - t: FINAL, - parseNodeExpr: Expressions.Declaration, - errors: Iterable[CompilationError] = Iterable.empty - ) - - def compile( - input: String, - offset: LibrariesOffset, - ctx: CompilerContext, - version: StdLibVersion, - allowIllFormedStrings: Boolean = false - ): Either[String, (EXPR, FINAL)] = { - val parser = new Parser(version)(offset) - parser.parseExpr(input) match { - case fastparse.Parsed.Success(xs, _) => ExpressionCompiler(ctx, xs, allowIllFormedStrings) - case f: fastparse.Parsed.Failure => Left(parser.toString(input, f)) - } - } - - def compileBoolean(input: String, offset: LibrariesOffset, ctx: CompilerContext, version: StdLibVersion): Either[String, EXPR] = { - compile(input, offset, ctx, version).flatMap { - case (expr, BOOLEAN) => Right(expr) - case _ => Left("Script should return boolean") - } - } - - def compileUntyped(input: String, offset: LibrariesOffset, ctx: CompilerContext, version: StdLibVersion): Either[String, EXPR] = { - compile(input, offset, ctx, version) - .map { case (expr, _) => expr } - } - - def compileWithParseResult( - input: String, - offset: LibrariesOffset, - ctx: CompilerContext, - version: StdLibVersion, - saveExprContext: Boolean = true - ): Either[(String, Int, Int), (EXPR, Expressions.SCRIPT, Iterable[CompilationError])] = - new Parser(version)(offset) - .parseExpressionWithErrorRecovery(input) - .flatMap { case (parseResult, removedCharPosOpt) => - compileExprWithCtx(parseResult.expr, saveExprContext, allowIllFormedStrings = false) - .run(ctx) - .value - ._2 - .map { compRes => - val errorList = - compRes.errors ++ - (if (compRes.t equivalent BOOLEAN) Nil else List(Generic(0, 0, "Script should return boolean"))) ++ - (if (removedCharPosOpt.isEmpty) - Nil - else - List( - Generic( - removedCharPosOpt.get.start, - removedCharPosOpt.get.end, - "Parsing failed. Some chars was removed as result of recovery process." - ) - )) - (compRes.expr, parseResult.copy(expr = compRes.parseNodeExpr), errorList) - } - .leftMap(e => (s"Compilation failed: ${Show[CompilationError].show(e)}", e.start, e.end)) - } - - def compileDecls(input: String, offset: LibrariesOffset, ctx: CompilerContext, version: StdLibVersion): Either[String, EXPR] = { - val adjustedDecls = s"$input\n${GlobalValNames.Unit}" - compileUntyped(adjustedDecls, offset, ctx, version) - } - - private def compileExpr(expr: Expressions.EXPR): CompileM[(Terms.EXPR, FINAL, Expressions.EXPR, Iterable[CompilationError])] = - compileExprWithCtx(expr, allowIllFormedStrings = false).map(r => (r.expr, r.t, r.parseNodeExpr, r.errors)) - +class ExpressionCompiler(val version: StdLibVersion) { private def compileExprWithCtx( expr: Expressions.EXPR, saveExprContext: Boolean = false, @@ -134,7 +38,7 @@ object ExpressionCompiler { def adjustStr(expr: Expressions.CONST_STRING, str: String): Either[CompilationError, CompilationStepResultExpr] = CONST_STRING(str) - .filterOrElse(_ => allowIllFormedStrings || !global.isIllFormed(str), CommonError(s"String '$str' contains ill-formed characters")) + .filterOrElse(_ => allowIllFormedStrings || str.isWellFormed, CommonError(s"String '$str' contains ill-formed characters")) .leftMap(e => CompilationError.Generic(expr.position.start, expr.position.end, e.message)) .map(CompilationStepResultExpr(ctx, _, STRING, expr)) .recover { case err => CompilationStepResultExpr(ctx, FAILED_EXPR(), NOTHING, expr, List(err)) } @@ -174,6 +78,10 @@ object ExpressionCompiler { } } + private def compileExpr(expr: Expressions.EXPR): CompileM[(Terms.EXPR, FINAL, Expressions.EXPR, Iterable[CompilationError])] = + compileExprWithCtx(expr, allowIllFormedStrings = false) + .map(r => (r.expr, r.t, r.parseNodeExpr, r.errors)) + private def compileIf( p: Pos, condExpr: Expressions.EXPR, @@ -355,63 +263,7 @@ object ExpressionCompiler { } } yield result - private def exprContainsRef(expr: Expressions.EXPR, ref: String): Boolean = - expr match { - case Expressions.GETTER(_, expr, _, _, _, _) => - exprContainsRef(expr, ref) - - case Expressions.BLOCK(_, decl, body, _, _) => - val refIsOverlappedByDecl = - decl.name match { - case PART.VALID(_, name) if name == ref => true - case _ => false - } - if (refIsOverlappedByDecl) false - else { - val declContainsRef = - decl match { - case Expressions.LET(_, _, value, _, _) => - exprContainsRef(value, ref) - case Expressions.FUNC(_, expr, _, args) => - val refIsOverlappedByArg = - args.exists { - case (PART.VALID(_, name), _) if name == ref => true - case _ => false - } - if (!refIsOverlappedByArg) exprContainsRef(expr, ref) - else false - } - declContainsRef || exprContainsRef(body, ref) - } - - case Expressions.IF(_, cond, ifTrue, ifFalse, _, _) => - exprContainsRef(cond, ref) || - exprContainsRef(ifTrue, ref) || - exprContainsRef(ifFalse, ref) - - case Expressions.FUNCTION_CALL(_, _, args, _, _) => - args.exists(exprContainsRef(_, ref)) - - case Expressions.REF(_, PART.VALID(_, name), _, _) if name == ref => - true - - case BINARY_OP(_, a, _, b, _, _) => - exprContainsRef(a, ref) || exprContainsRef(b, ref) - - case Expressions.MATCH(_, matchingExpr, cases, _, _) => - exprContainsRef(matchingExpr, ref) || - cases.exists { - case MATCH_CASE(_, TypedVar(Some(PART.VALID(_, varName)), _), caseExpr, _, _) if varName != ref => - exprContainsRef(caseExpr, ref) - case MATCH_CASE(_, TypedVar(None, _), caseExpr, _, _) => - exprContainsRef(caseExpr, ref) - case _ => false - } - - case _ => false - } - - def compileBlock( + private def compileBlock( pos: Expressions.Pos, declaration: Expressions.Declaration, expr: Expressions.EXPR, @@ -441,7 +293,12 @@ object ExpressionCompiler { _.getBytes(StandardCharsets.UTF_8).length <= ContractLimits.MaxDeclarationNameInBytes ) - def compileLet(p: Pos, let: Expressions.LET, saveExprContext: Boolean, allowIllFormedStrings: Boolean): CompileM[CompilationStepResultDec] = + protected def compileLet( + p: Pos, + let: Expressions.LET, + saveExprContext: Boolean, + allowIllFormedStrings: Boolean + ): CompileM[CompilationStepResultDec] = for { _ <- checkDeclarationNameSize(p, let) letNameWithErr <- validateShadowing(p, let).handleError() @@ -460,7 +317,7 @@ object ExpressionCompiler { } } yield result - def compileFunc( + protected def compileFunc( p: Pos, func: Expressions.FUNC, saveExprContext: Boolean, @@ -510,10 +367,10 @@ object ExpressionCompiler { } yield (result, argTypesWithErr._1.map(_.map(nameAnfInfo => (nameAnfInfo._1, nameAnfInfo._2.vType))).getOrElse(List.empty)) } - def updateCtx(letName: String, letType: Types.FINAL, p: Pos): CompileM[Unit] = + protected def updateCtx(letName: String, letType: Types.FINAL, p: Pos): CompileM[Unit] = modify[Id, CompilerContext, CompilationError](vars.modify(_)(_ + (letName -> VariableInfo(p, letType)))) - def updateCtx(funcName: String, typeSig: FunctionTypeSignature, p: Pos): CompileM[Unit] = + protected def updateCtx(funcName: String, typeSig: FunctionTypeSignature, p: Pos): CompileM[Unit] = modify[Id, CompilerContext, CompilationError](functions.modify(_)(_ + (funcName -> FunctionInfo(p, List(typeSig))))) private def compileLetBlock( @@ -755,12 +612,7 @@ object ExpressionCompiler { } } - def mkIf(p: Pos, cond: EXPR, ifTrue: (EXPR, FINAL), ifFalse: (EXPR, FINAL)): Either[CompilationError, (EXPR, FINAL)] = { - val t = TypeInferrer.findCommonType(ifTrue._2, ifFalse._2) - (IF(cond, ifTrue._1, ifFalse._1), t).asRight - } - - def mkIfCases( + private def mkIfCases( cases: List[MATCH_CASE], caseTypes: List[FINAL], refTmp: Expressions.REF, @@ -842,7 +694,8 @@ object ExpressionCompiler { val typeIf = tTypes.foldLeft(isInst(hType))((other, matchType) => BINARY_OP(mc.position, isInst(matchType), BinaryOperation.OR_OP, other)) Right(makeIfCase(typeIf, blockWithNewVar, further)) - case Nil => ??? + case Nil => + ??? } } yield cases case (_: TypedVar, t) => @@ -851,51 +704,49 @@ object ExpressionCompiler { case (ConstsPat(consts, _), _) => val cond = consts .map(c => BINARY_OP(mc.position, c, BinaryOperation.EQ_OP, refTmp)) - .reduceRight((c, r) => BINARY_OP(mc.position, c, BinaryOperation.OR_OP, r)) + .reduceRight(BINARY_OP(mc.position, _, BinaryOperation.OR_OP, _)) Right(makeIfCase(cond, blockWithNewVar, further)) case (p: CompositePattern, _) => - val pos = p.position - val newRef = p.caseType.fold(refTmp)(t => refTmp.copy(resultType = Some(caseType))) - val conditions = makeConditionsFromCompositePattern(p, newRef) - val cond = if (conditions.isEmpty) { - Expressions.TRUE(pos): Expressions.EXPR - } else { - conditions.reduceRight { (c, r) => - BINARY_OP(pos, c, BinaryOperation.AND_OP, r): Expressions.EXPR + val pos = p.position + val newRef = p.caseType.fold(refTmp)(_ => refTmp.copy(resultType = Some(caseType))) + makeConditionsFromCompositePattern(ctx, p, newRef) + .map { conditions => + val cond = + if (conditions.isEmpty) + Expressions.TRUE(pos) + else + conditions.reduceRight(BINARY_OP(pos, _, BinaryOperation.AND_OP, _)) + val checkingCond = + if (p.isInstanceOf[TuplePat]) { + val (resolvedTypes, size) = resolveTypesFromCompositePattern(p) + if (p.patternsWithFields.size == size) { + val typeChecks = + resolvedTypes + .map(t => Expressions.FUNCTION_CALL(pos, PART.VALID(pos, IsInstanceOf), List(refTmp, Expressions.CONST_STRING(pos, t)))) + .reduceLeft[Expressions.EXPR] { case (c, r) => BINARY_OP(pos, c, BinaryOperation.OR_OP, r) } + BINARY_OP(pos, cond, BinaryOperation.AND_OP, typeChecks) + } else { + val size = Expressions.CONST_LONG(pos, p.patternsWithFields.size) + val getSize = Expressions.FUNCTION_CALL(pos, PART.VALID(pos, "size"), List(refTmp)) + val compareSize = BINARY_OP(pos, getSize, BinaryOperation.EQ_OP, size) + BINARY_OP(pos, cond, BinaryOperation.AND_OP, compareSize) + } + } else + cond + makeIfCase( + p.caseType.fold(checkingCond)(t => + BINARY_OP( + pos, + Expressions.FUNCTION_CALL(pos, PART.VALID(pos, IsInstanceOf), List(refTmp, Expressions.CONST_STRING(pos, t.name))), + BinaryOperation.AND_OP, + Expressions.BLOCK(pos, Expressions.LET(pos, newRef.key, newRef, Some(caseType), true), checkingCond) + ) + ), + blockWithNewVar, + further + ) } - } - val checkingCond = - if (p.isInstanceOf[TuplePat]) { - val (resolvedTypes, size) = resolveTypesFromCompositePattern(p) - if (p.patternsWithFields.size == size) { - val typeChecks = - resolvedTypes - .map(t => Expressions.FUNCTION_CALL(pos, PART.VALID(pos, IsInstanceOf), List(refTmp, Expressions.CONST_STRING(pos, t)))) - .reduceLeft[Expressions.EXPR] { case (c, r) => BINARY_OP(pos, c, BinaryOperation.OR_OP, r) } - BINARY_OP(pos, cond, BinaryOperation.AND_OP, typeChecks) - } else { - val size = Expressions.CONST_LONG(pos, p.patternsWithFields.size) - val getSize = Expressions.FUNCTION_CALL(pos, PART.VALID(pos, "size"), List(refTmp)) - val compareSize = BINARY_OP(pos, getSize, BinaryOperation.EQ_OP, size) - BINARY_OP(pos, cond, BinaryOperation.AND_OP, compareSize) - } - } else - cond - Right( - makeIfCase( - p.caseType.fold(checkingCond)(t => - BINARY_OP( - pos, - Expressions.FUNCTION_CALL(pos, PART.VALID(pos, IsInstanceOf), List(refTmp, Expressions.CONST_STRING(pos, t.name))), - BinaryOperation.AND_OP, - Expressions.BLOCK(pos, Expressions.LET(pos, newRef.key, newRef, Some(caseType), true), checkingCond) - ) - ), - blockWithNewVar, - further - ) - ) } } } @@ -925,47 +776,56 @@ object ExpressionCompiler { Expressions.GETTER(pos, exp, field, checkObjectType = false) } - private def makeConditionsFromCompositePattern(p: CompositePattern, newRef: Expressions.REF): Seq[Expressions.EXPR] = - p.subpatterns collect { + private def makeConditionsFromCompositePattern( + ctx: CompilerContext, + p: CompositePattern, + newRef: Expressions.REF + ): Either[Generic, Seq[Expressions.EXPR]] = + p.subpatterns.traverse { case (pat @ TypedVar(_, Expressions.Union(types)), path) if types.nonEmpty => val pos = pat.position val v = mkGet(path, newRef, pos) - types - .map { + val r = types + .collect { case Expressions.Single(t, None) => - Expressions.FUNCTION_CALL(pos, PART.VALID(pos, IsInstanceOf), List(v, Expressions.CONST_STRING(pos, t))): Expressions.EXPR + Expressions.FUNCTION_CALL(pos, PART.VALID(pos, IsInstanceOf), List(v, Expressions.CONST_STRING(pos, t))) case Expressions.Single(PART.VALID(pos, Type.ListTypeName), Some(PART.VALID(_, Expressions.AnyType(_)))) => val t = PART.VALID(pos, "List[Any]") - Expressions.FUNCTION_CALL( - pos, - PART.VALID(pos, IsInstanceOf), - List(v, Expressions.CONST_STRING(pos, t)) - ): Expressions.EXPR - case _ => ??? - } - .reduceRight[Expressions.EXPR] { (c, r) => - BINARY_OP(pos, c, BinaryOperation.OR_OP, r) + Expressions.FUNCTION_CALL(pos, PART.VALID(pos, IsInstanceOf), List(v, Expressions.CONST_STRING(pos, t))) } + .reduceRight[Expressions.EXPR](BINARY_OP(pos, _, BinaryOperation.OR_OP, _)) + Right(r) case (pat @ TypedVar(_, Expressions.Single(PART.VALID(_, Type.ListTypeName), Some(PART.VALID(_, Expressions.AnyType(_))))), path) => val pos = pat.position val v = mkGet(path, newRef, pos) val t = PART.VALID(pos, "List[Any]") - Expressions.FUNCTION_CALL(pos, PART.VALID(pos, IsInstanceOf), List(v, Expressions.CONST_STRING(pos, t))): Expressions.EXPR + val r = Expressions.FUNCTION_CALL(pos, PART.VALID(pos, IsInstanceOf), List(v, Expressions.CONST_STRING(pos, t))) + Right(r) case (pat @ TypedVar(_, Expressions.Single(t, None)), path) => val pos = pat.position val v = mkGet(path, newRef, pos) - Expressions.FUNCTION_CALL(pos, PART.VALID(pos, IsInstanceOf), List(v, Expressions.CONST_STRING(pos, t))): Expressions.EXPR - case (TypedVar(_, Expressions.Single(_, _)), _) => ??? + val r = Expressions.FUNCTION_CALL(pos, PART.VALID(pos, IsInstanceOf), List(v, Expressions.CONST_STRING(pos, t))) + Right(r) case (pat @ ConstsPat(consts, _), path) => val pos = pat.position val v = mkGet(path, newRef, pos) consts - .map { c => - BINARY_OP(pos, c, BinaryOperation.EQ_OP, v) - } - .reduceRight[BINARY_OP] { (c, r) => - BINARY_OP(pos, c, BinaryOperation.OR_OP, r) + .traverse { + case const @ ( + _: Expressions.CONST_LONG | _: Expressions.CONST_STRING | _: Expressions.CONST_BYTESTR | _: Expressions.TRUE | + _: Expressions.FALSE | _: Expressions.REF + ) => + Right(BINARY_OP(pos, const, BinaryOperation.EQ_OP, v)) + case func @ Expressions.FUNCTION_CALL(pos, PART.VALID(_, name), _, _, _) if ctx.predefTypes.contains(name) => + Right(BINARY_OP(pos, func, BinaryOperation.EQ_OP, v)) + case expr if version < V8 => + Right(BINARY_OP(pos, expr, BinaryOperation.EQ_OP, v)) + case expr => + Left(Generic(expr.position.start, expr.position.end, "Only constant value could be matched with object field")) } + .map(_.reduceRight(BINARY_OP(pos, _, BinaryOperation.OR_OP, _))) + case _ => + Right(Expressions.TRUE(newRef.position)) } private def resolveTypesFromCompositePattern(p: CompositePattern): (Seq[PART[String]], Int) = { @@ -1072,27 +932,102 @@ object ExpressionCompiler { types.toList .traverse(handleCompositeType(pos, _, expectedType, varName)) .map(types => TUPLE(types)) - case Expressions.AnyType(pos) => (ANY: FINAL).pure[CompileM] + case _: Expressions.AnyType => + (ANY: FINAL).pure[CompileM] } - def handlePart[T](part: PART[T]): CompileM[T] = part match { + protected def handlePart[T](part: PART[T]): CompileM[T] = part match { case PART.VALID(_, x) => x.pure[CompileM] case PART.INVALID(p, message) => raiseError(Generic(p.start, p.end, message)) } +} +object ExpressionCompiler { implicit class RichBoolean(val b: Boolean) extends AnyVal { final def toOption[A](a: => A): Option[A] = if (b) Some(a) else None } - def apply(c: CompilerContext, expr: Expressions.EXPR, allowIllFormedStrings: Boolean = false): Either[String, (EXPR, FINAL)] = - applyWithCtx(c, expr, allowIllFormedStrings).map(r => (r._2, r._3)) + def compileWithParseResult( + input: String, + offset: LibrariesOffset, + ctx: CompilerContext, + version: StdLibVersion, + saveExprContext: Boolean = true + ): Either[(String, Int, Int), (EXPR, Expressions.SCRIPT, Iterable[CompilationError])] = + new Parser(version)(offset) + .parseExpressionWithErrorRecovery(input) + .flatMap { case (parseResult, removedCharPosOpt) => + new ExpressionCompiler(version) + .compileExprWithCtx(parseResult.expr, saveExprContext, allowIllFormedStrings = false) + .run(ctx) + .value + ._2 + .map { compRes => + val errorList = + compRes.errors ++ + (if (compRes.t equivalent BOOLEAN) Nil else List(Generic(0, 0, "Script should return boolean"))) ++ + (if (removedCharPosOpt.isEmpty) + Nil + else + List( + Generic( + removedCharPosOpt.get.start, + removedCharPosOpt.get.end, + "Parsing failed. Some chars was removed as result of recovery process." + ) + )) + (compRes.expr, parseResult.copy(expr = compRes.parseNodeExpr), errorList) + } + .leftMap(e => (s"Compilation failed: ${Show[CompilationError].show(e)}", e.start, e.end)) + } + + def compile( + input: String, + offset: LibrariesOffset, + ctx: CompilerContext, + version: StdLibVersion, + allowIllFormedStrings: Boolean = false + ): Either[String, (EXPR, FINAL)] = { + val parser = new Parser(version)(offset) + parser.parseExpr(input) match { + case fastparse.Parsed.Success(expr, _) => apply(ctx, version, expr, allowIllFormedStrings) + case f: fastparse.Parsed.Failure => Left(parser.toString(input, f)) + } + } + + def compileBoolean(input: String, offset: LibrariesOffset, ctx: CompilerContext, version: StdLibVersion): Either[String, EXPR] = { + compile(input, offset, ctx, version).flatMap { + case (expr, BOOLEAN) => Right(expr) + case _ => Left("Script should return boolean") + } + } + + def compileUntyped(input: String, offset: LibrariesOffset, ctx: CompilerContext, version: StdLibVersion): Either[String, EXPR] = { + compile(input, offset, ctx, version) + .map { case (expr, _) => expr } + } + + def compileDecls(input: String, offset: LibrariesOffset, ctx: CompilerContext, version: StdLibVersion): Either[String, EXPR] = { + val adjustedDecls = s"$input\n${GlobalValNames.Unit}" + compileUntyped(adjustedDecls, offset, ctx, version) + } + + def apply( + c: CompilerContext, + version: StdLibVersion, + expr: Expressions.EXPR, + allowIllFormedStrings: Boolean = false + ): Either[String, (EXPR, FINAL)] = + applyWithCtx(c, version, expr, allowIllFormedStrings).map(r => (r._2, r._3)) def applyWithCtx( c: CompilerContext, + version: StdLibVersion, expr: Expressions.EXPR, allowIllFormedStrings: Boolean = false ): Either[String, (CompilerContext, EXPR, FINAL)] = - compileExprWithCtx(expr, allowIllFormedStrings = allowIllFormedStrings) + new ExpressionCompiler(version) + .compileExprWithCtx(expr, allowIllFormedStrings = allowIllFormedStrings) .run(c) .value ._2 diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/Terms.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/Terms.scala index f1d1a8ec214..bc7456e3ab1 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/Terms.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/Terms.scala @@ -1,18 +1,19 @@ package com.wavesplatform.lang.v1.compiler import java.nio.charset.StandardCharsets - import cats.Eval import cats.instances.list.* import cats.syntax.traverse.* import com.wavesplatform.common.state.ByteStr -import com.wavesplatform.lang.{ExecutionError, CommonError} +import com.wavesplatform.lang.{CommonError, ExecutionError} import com.wavesplatform.lang.v1.ContractLimits.* import com.wavesplatform.lang.v1.FunctionHeader import com.wavesplatform.lang.v1.compiler.Types.* import com.wavesplatform.lang.v1.evaluator.ctx.impl.PureContext.MaxListLengthV4 import monix.eval.Coeval +import scala.annotation.nowarn + object Terms { val DataTxMaxBytes: Int = 150 * 1024 // should be the same as DataTransaction.MaxBytes val DataTxMaxProtoBytes: Int = 165947 // depends from DataTransaction.MaxProtoBytes @@ -242,6 +243,7 @@ object Terms { lazy val TRUE: CONST_BOOLEAN = CONST_BOOLEAN(true) lazy val FALSE: CONST_BOOLEAN = CONST_BOOLEAN(false) + @nowarn // do not warn about private constructor case class CaseObj private (caseType: CASETYPEREF, fields: Map[String, EVALUATED]) extends EVALUATED { // must be with fixArrIndentation = false, because of makeString behavior before RideV6 (NODE-2370) override def toString: String = TermPrinter().string(this) diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/TypeCast.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/TypeCast.scala index 38b6207c034..eea379da395 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/TypeCast.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/TypeCast.scala @@ -1,7 +1,6 @@ package com.wavesplatform.lang.v1.compiler import com.wavesplatform.common.utils.* import com.wavesplatform.lang.v1.compiler.CompilationError.{GenericFunctionNotFound, TypeCastAllowedOnlyForGenericList} -import com.wavesplatform.lang.v1.compiler.ExpressionCompiler.CompilationStepResultExpr import com.wavesplatform.lang.v1.compiler.Terms.* import com.wavesplatform.lang.v1.compiler.Types.* import com.wavesplatform.lang.v1.evaluator.ctx.impl.GlobalValNames diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/Types.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/Types.scala index ee1a4d55834..1632cdad484 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/Types.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/Types.scala @@ -1,7 +1,7 @@ package com.wavesplatform.lang.v1.compiler -import cats.syntax.traverse.* import cats.instances.list.* +import cats.syntax.traverse.* import scala.annotation.tailrec @@ -14,36 +14,36 @@ object Types { def fields: List[(String, FINAL)] = List() def typeList: List[REAL] def unfold: FINAL = this - def union: UNION = UNION(typeList) + def union: UNION = UNION(typeList) def name: String override def toString: String = name } sealed trait PARAMETERIZED extends TYPE - case class TYPEPARAM(char: Byte) extends PARAMETERIZED with SINGLE { override def toString: String = char.toChar.toString } - case class PARAMETERIZEDLIST(t: TYPE) extends PARAMETERIZED with SINGLE { override def toString: String = s"List[$t]" } + case class TYPEPARAM(char: Byte) extends PARAMETERIZED with SINGLE { override def toString: String = char.toChar.toString } + case class PARAMETERIZEDLIST(t: TYPE) extends PARAMETERIZED with SINGLE { override def toString: String = s"List[$t]" } case class PARAMETERIZEDTUPLE(t: List[TYPE]) extends PARAMETERIZED with SINGLE { override def toString: String = t.mkString("(", ", ", ")") } - case class PARAMETERIZEDUNION(l: List[SINGLE]) extends PARAMETERIZED { override def toString: String = l.mkString("|")} - case object NOTHING extends REAL { override val name = "Nothing"; override val typeList = List() } - case object LONG extends REAL { override val name = "Int"; override val typeList = List(this) } - case object BIGINT extends REAL { override val name = "BigInt"; override val typeList = List(this) } - case object BYTESTR extends REAL { override val name = "ByteVector"; override val typeList = List(this) } - case object BOOLEAN extends REAL { override val name = "Boolean"; override val typeList = List(this) } - case object STRING extends REAL { override val name = "String"; override val typeList = List(this) } + case class PARAMETERIZEDUNION(l: List[SINGLE]) extends PARAMETERIZED { override def toString: String = l.mkString("|") } + case object NOTHING extends REAL { override val name = "Nothing"; override val typeList: List[REAL] = List() } + case object LONG extends REAL { override val name = "Int"; override val typeList: List[REAL] = List(this) } + case object BIGINT extends REAL { override val name = "BigInt"; override val typeList: List[REAL] = List(this) } + case object BYTESTR extends REAL { override val name = "ByteVector"; override val typeList: List[REAL] = List(this) } + case object BOOLEAN extends REAL { override val name = "Boolean"; override val typeList: List[REAL] = List(this) } + case object STRING extends REAL { override val name = "String"; override val typeList: List[REAL] = List(this) } case class LIST(innerType: FINAL) extends REAL { override lazy val name: String = "List[" ++ innerType.toString ++ "]" override def typeList: List[REAL] = List(this) } sealed trait UNIONLIKE extends FINAL - case object ANY extends UNIONLIKE { override val name = "Any"; override val typeList = List() } + case object ANY extends UNIONLIKE { override val name = "Any"; override val typeList: List[REAL] = List() } case class UNION(override val typeList: List[REAL], n: Option[String] = None) extends UNIONLIKE { - override lazy val fields = typeList.map(_.fields.toSet).reduce(_ intersect _).toList - override val name = if (n.nonEmpty) n.get else typeList.sortBy(_.toString).mkString("|") + override lazy val fields: List[(String, FINAL)] = typeList.map(_.fields.toSet).reduce(_ intersect _).toList + override val name: String = if (n.nonEmpty) n.get else typeList.sortBy(_.toString).mkString("|") override def equals(obj: Any): Boolean = obj match { case UNION(typeList, _) if typeList.sortBy(_.toString) == this.typeList.sortBy(_.toString) => true - case _ => false + case _ => false } override def unfold: UNIONLIKE = { @@ -60,7 +60,7 @@ object Types { } case class TUPLE(types: List[FINAL]) extends REAL { - override def name: String = types.mkString("(", ", ", ")") + override def name: String = types.mkString("(", ", ", ")") override def typeList: List[REAL] = List(this) override def fields: List[(String, FINAL)] = @@ -71,7 +71,7 @@ object Types { || \/ (A1, ..., Z1) | ... | (A1, ..., Zk) | ... | (An, ..., Zk) - */ + */ override def unfold: FINAL = { val regrouped = regroup(types.map(_.typeList)).map(t => TUPLE(t.toList)) UNION.reduce(UNION.create(regrouped)) @@ -100,27 +100,28 @@ object Types { object UNION { def create(l: Seq[FINAL], n: Option[String] = None): UNIONLIKE = { - if(l.contains(ANY)) { + if (l.contains(ANY)) { ANY } else { - new UNION(l.flatMap { - case NOTHING => List.empty - case UNION(inner, _) => inner - case s: REAL => List(s) - case ANY => ??? - } - .toList - .distinct , - n) + new UNION( + l.flatMap { + case NOTHING => List.empty + case UNION(inner, _) => inner + case s: REAL => List(s) + case ANY => ??? + }.toList + .distinct, + n + ) } } def apply(l: FINAL*): UNIONLIKE = create(l.toList) def reduce(u: UNIONLIKE): FINAL = u match { - case UNION(Nil, _) => throw new Exception("Empty union") + case UNION(Nil, _) => throw new Exception("Empty union") case UNION(x :: Nil, _) => x - case _ => u + case _ => u } } @@ -128,29 +129,29 @@ object Types { def equivalent(l2: FINAL): Boolean = (l1, l2) match { case (l1: TUPLE, l2: TUPLE) => (l1.types.length == l2.types.length) && { - val unfolded = l1.unfold - if (l1 == unfolded) - (l1.types zip l2.types).forall { case (t1, t2) => t1 equivalent t2 } - else - unfolded equivalent l2.unfold - } - case (l1: LIST, l2: LIST) => l1.innerType equivalent l2.innerType - case (l1: REAL, l2: REAL) => l1 == l2 + val unfolded = l1.unfold + if (l1 == unfolded) + (l1.types zip l2.types).forall { case (t1, t2) => t1 equivalent t2 } + else + unfolded equivalent l2.unfold + } + case (l1: LIST, l2: LIST) => l1.innerType equivalent l2.innerType + case (l1: REAL, l2: REAL) => l1 == l2 case (l1: UNION, l2: UNION) => - l1.typeList.length == l2.typeList.length && + l1.typeList.length == l2.typeList.length && (l1.unfold.typeList.sortBy(_.name) zip l2.unfold.typeList.sortBy(_.name)) .forall { case (t1, t2) => t1 equivalent t2 } case (l1: FINAL, l2: FINAL) => l1.union equivalent l2.union } def >=(l2: FINAL): Boolean = (l1, l2) match { - case (ANY, _) => true - case (l1, UNION(l2, _)) => l2.forall(l1 >= _) - case (UNION(l1, _), l2) => l1.exists(_ >= l2) - case (_, ANY) => false - case (_, NOTHING) => true - case (NOTHING, _) => false - case (LIST(t1), LIST(t2)) => t1 >= t2 + case (ANY, _) => true + case (l1, UNION(l2, _)) => l2.forall(l1 >= _) + case (UNION(l1, _), l2) => l1.exists(_ >= l2) + case (_, ANY) => false + case (_, NOTHING) => true + case (NOTHING, _) => false + case (LIST(t1), LIST(t2)) => t1 >= t2 case (TUPLE(types1), TUPLE(types2)) => types1.length == types2.length && (types1 zip types2).forall { case (t1, t2) => t1 >= t2 } case (l1: REAL, l2: REAL) => l1 equivalent l2 @@ -162,10 +163,10 @@ object Types { @tailrec def check(tpe: FINAL): Boolean = { tpe match { - case Types.UNION(types, _) if types.size > 1 => true + case Types.UNION(types, _) if types.size > 1 => true case Types.LIST(Types.UNION(types, _)) if types.size > 1 => true - case Types.LIST(inner@Types.LIST(_)) => check(inner) - case _ => false + case Types.LIST(inner @ Types.LIST(_)) => check(inner) + case _ => false } } check(l1) diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/PureContext.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/PureContext.scala index 2268cd3ba01..2fbb5dc0d91 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/PureContext.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/PureContext.scala @@ -2,7 +2,6 @@ package com.wavesplatform.lang.v1.evaluator.ctx.impl import cats.implicits.* import cats.{Id, Monad} -import com.google.common.annotations.VisibleForTesting import com.wavesplatform.common.state.ByteStr import com.wavesplatform.common.utils.EitherExt2 import com.wavesplatform.lang.* @@ -1036,7 +1035,7 @@ object PureContext { case CONST_STRING(m) :: CONST_STRING(sub) :: Nil => Right { val i = m.indexOf(sub) - if (!global.isIllFormed(sub) && i != -1) + if (sub.isWellFormed && i != -1) CONST_LONG(m.codePointCount(0, i).toLong) else unit @@ -1080,7 +1079,7 @@ object PureContext { ) { case CONST_STRING(m) :: CONST_STRING(sub) :: CONST_LONG(off) :: Nil => val l = m.codePointCount(0, m.length) - Right(if (!global.isIllFormed(sub) && off >= 0 && off <= l) { + Right(if (sub.isWellFormed && off >= 0 && off <= l) { val i = m.indexOf(sub, m.offsetByCodePoints(0, off.toInt)) if (i != -1) { CONST_LONG(m.codePointCount(0, i).toLong) @@ -1126,7 +1125,7 @@ object PureContext { case CONST_STRING(m) :: CONST_STRING(sub) :: Nil => Right({ val i = m.lastIndexOf(sub) - if (!global.isIllFormed(sub) && i != -1) { + if (sub.isWellFormed && i != -1) { CONST_LONG(m.codePointCount(0, i).toLong) } else { unit @@ -1174,7 +1173,7 @@ object PureContext { Right(if (off >= 0) { val offset = Math.min(off, m.codePointCount(0, m.length)).toInt val i = m.lastIndexOf(sub, m.offsetByCodePoints(0, offset)) - if (!global.isIllFormed(sub) && i != -1) { + if (sub.isWellFormed && i != -1) { CONST_LONG(m.codePointCount(0, i).toLong) } else { unit @@ -1218,7 +1217,7 @@ object PureContext { private def split(str: String, sep: String, unicode: Boolean): Iterable[CONST_STRING] = { if (str == "") listWithEmptyStr - else if (unicode && global.isIllFormed(sep)) List(CONST_STRING(str).explicitGet()) + else if (unicode && !sep.isWellFormed) List(CONST_STRING(str).explicitGet()) else if (sep == "") if (unicode) { (1 to str.codePointCount(0, str.length)) @@ -1507,7 +1506,6 @@ object PureContext { notImplemented[Id, EVALUATED]("replaceByIndex(list: List[T], index: Int, element: T)", xs) } - @VisibleForTesting private[v1] def genericListIndexOf( element: EVALUATED, indexOf: EVALUATED => Int, diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/waves/Functions.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/waves/Functions.scala index 62b9397a6d8..c12a726ef33 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/waves/Functions.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/waves/Functions.scala @@ -67,7 +67,7 @@ object Functions { case (_, (addressOrAlias: CaseObj) :: CONST_STRING(key) :: Nil) => getData(env, addressOrAlias, key) case (_, xs) => - notImplemented[F, EVALUATED](s"$name(s: String)", xs) + notImplemented[F, EVALUATED](s"${this.name}(s: String)", xs) } } } @@ -107,7 +107,7 @@ object Functions { .hasData(addressOrAlias) .map(_.map(v => CONST_BOOLEAN(!v))) - case xs => notImplemented[F, EVALUATED](s"$name(s: AddressOrAlias)", xs) + case xs => notImplemented[F, EVALUATED](s"${this.name}(s: AddressOrAlias)", xs) } } } diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/parser/BinaryOperation.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/parser/BinaryOperation.scala index 39f6d3311d7..9adfa106971 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/parser/BinaryOperation.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/parser/BinaryOperation.scala @@ -46,7 +46,7 @@ object BinaryOperation { } case object GT_OP extends BinaryOperation { val func = ">" - override def parser[A: P] = P(">" ~ !P("=")).map(_ => this) + override def parser[A: P]: P[BinaryOperation] = P(">" ~ !P("=")).map(_ => this) } case object SUM_OP extends BinaryOperation { val func = "+" @@ -64,15 +64,15 @@ object BinaryOperation { override val func: String = "%" } case object LE_OP extends BinaryOperation { - val func = ">=" - override def parser[A: P] = P("<=").map(_ => this) + val func = ">=" + override def parser[A: P]: P[BinaryOperation] = P("<=").map(_ => this) override def expr(shiftedStart: Int, shiftedEnd: Int, op1: EXPR, op2: EXPR): EXPR = { BINARY_OP(Pos.fromShifted(shiftedStart, shiftedEnd), op2, LE_OP, op1) } } case object LT_OP extends BinaryOperation { - val func = ">" - override def parser[A: P] = P("<" ~ !P("=")).map(_ => this) + val func = ">" + override def parser[A: P]: P[BinaryOperation] = P("<" ~ !P("=")).map(_ => this) override def expr(shiftedStart: Int, shiftedEnd: Int, op1: EXPR, op2: EXPR): EXPR = { BINARY_OP(Pos.fromShifted(shiftedStart, shiftedEnd), op2, LT_OP, op1) } diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/parser/Parser.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/parser/Parser.scala index 692d8ee2373..0a61ef2788d 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/parser/Parser.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/parser/Parser.scala @@ -239,13 +239,13 @@ class Parser(stdLibVersion: StdLibVersion)(implicit offset: LibrariesOffset) { .map(Union(_)) def tupleTypeP[A: P]: P[Tuple] = - ("(" ~ + ("(" ~ comment ~ P(unionTypeP).rep( ContractLimits.MinTupleSize, comment ~ "," ~ comment, ContractLimits.MaxTupleSize ) - ~/ ")") + ~ comment ~/ ")") .map(Tuple) def funcP(implicit c: fastparse.P[Any]): P[FUNC] = { @@ -309,10 +309,11 @@ class Parser(stdLibVersion: StdLibVersion)(implicit offset: LibrariesOffset) { }) ).?.map(_.getOrElse(Union(Seq()))) + val objPatMin = if (stdLibVersion >= V8) 1 else 0 def pattern(implicit c: fastparse.P[Any]): P[Pattern] = (varDefP ~ comment ~ typesDefP).map { case (v, t) => TypedVar(v, t) } | (Index ~ "(" ~ pattern.rep(min = 2, sep = ",") ~/ ")" ~ Index).map(p => TuplePat(p._2, Pos(p._1, p._3))) | - (Index ~ anyVarName() ~ "(" ~ (anyVarName() ~ "=" ~ pattern).rep(sep = ",") ~ ")" ~ Index) + (Index ~ anyVarName() ~ "(" ~ (anyVarName() ~ "=" ~ pattern).rep(min = objPatMin, sep = ",") ~ ")" ~ Index) .map(p => ObjPat(p._3.map(kp => (PART.toOption(kp._1).get, kp._2)).toMap, Single(p._2, None), Pos(p._1, p._4))) | (Index ~ baseExpr.rep(min = 1, sep = "|") ~ Index).map(p => ConstsPat(p._2, Pos(p._1, p._3))) diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/traits/domain/CallableAction.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/traits/domain/CallableAction.scala index a1bbeddf7be..8b020b35748 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/traits/domain/CallableAction.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/traits/domain/CallableAction.scala @@ -1,16 +1,16 @@ package com.wavesplatform.lang.v1.traits.domain -import java.io.ByteArrayOutputStream - import com.wavesplatform.common.state.ByteStr import com.wavesplatform.lang.hacks.Global -import com.wavesplatform.lang.utils.Serialize._ +import com.wavesplatform.lang.utils.Serialize.* import com.wavesplatform.lang.v1.traits.domain.Recipient.{Address, Alias} +import java.io.ByteArrayOutputStream + sealed trait CallableAction case class AssetTransfer( - address: Address, + recipientAddressBytes: Address, recipient: Recipient, amount: Long, assetId: Option[ByteStr] @@ -112,9 +112,9 @@ sealed trait DataItem[T] extends DataOp { } object DataItem { - case class Lng(k: String, v: Long) extends DataItem[Long] { val key = k; val value = v } - case class Bool(k: String, v: Boolean) extends DataItem[Boolean] { val key = k; val value = v } - case class Bin(k: String, v: ByteStr) extends DataItem[ByteStr] { val key = k; val value = v } - case class Str(k: String, v: String) extends DataItem[String] { val key = k; val value = v } - case class Delete(key: String) extends DataOp + case class Lng(key: String, value: Long) extends DataItem[Long] + case class Bool(key: String, value: Boolean) extends DataItem[Boolean] + case class Bin(key: String, value: ByteStr) extends DataItem[ByteStr] + case class Str(key: String, value: String) extends DataItem[String] + case class Delete(key: String) extends DataOp } diff --git a/lang/testkit/src/test/scala/com/wavesplatform/report/QaseReporter.scala b/lang/testkit/src/test/scala/com/wavesplatform/report/QaseReporter.scala new file mode 100644 index 00000000000..fc3dbc834c6 --- /dev/null +++ b/lang/testkit/src/test/scala/com/wavesplatform/report/QaseReporter.scala @@ -0,0 +1,87 @@ +package com.wavesplatform.report + +import com.wavesplatform.report.QaseReporter.{CaseIdPattern, QaseProjects, TestResult} +import io.qase.api.QaseClient +import io.qase.api.utils.IntegrationUtils +import io.qase.client.model.ResultCreate +import org.scalatest.Reporter +import org.scalatest.events.* +import play.api.libs.json.{Format, Json} + +import java.io.FileWriter +import java.util.concurrent.ConcurrentHashMap +import scala.jdk.CollectionConverters.* +import scala.util.matching.Regex + +class QaseReporter extends Reporter { + + private val results = initResults() + + override def apply(event: Event): Unit = { + event match { + case ts: TestSucceeded => + extractCaseIds(ts.testName).foreach { case (projectCode, caseId) => + saveTestCaseResults(ResultCreate.StatusEnum.PASSED, ts.testName, projectCode, caseId, None, None, ts.duration) + } + case tf: TestFailed => + extractCaseIds(tf.testName).foreach { case (projectCode, caseId) => + saveTestCaseResults(ResultCreate.StatusEnum.FAILED, tf.testName, projectCode, caseId, tf.throwable, Some(tf.message), tf.duration) + } + case _: RunAborted | _: RunStopped | _: RunCompleted => + saveRunResults() + case _ => () + } + } + + private def extractCaseIds(testName: String): Seq[(String, Long)] = + CaseIdPattern.findAllMatchIn(testName).map(m => m.group(1) -> m.group(2).toLong).toSeq + + private def saveTestCaseResults( + status: ResultCreate.StatusEnum, + testName: String, + projectCode: String, + caseId: Long, + throwable: Option[Throwable], + msgOpt: Option[String], + duration: Option[Long] + ): Unit = + if (QaseClient.isEnabled) { + val errMsg = msgOpt.map(msg => s"\n\n**Error**\n$msg").getOrElse("") + val comment = s"$testName$errMsg" + val stacktrace = throwable.map(IntegrationUtils.getStacktrace) + val timeMs = duration.getOrElse(0L) + + results.computeIfPresent(projectCode, (_, results) => TestResult(status.toString, comment, stacktrace, caseId, timeMs) +: results) + } + + private def saveRunResults(): Unit = + if (QaseClient.isEnabled) { + results.asScala.foreach { case (projectCode, results) => + if (results.nonEmpty) { + val writer = new FileWriter(s"./$projectCode-${System.currentTimeMillis()}") + writer.write(Json.toJson(results).toString) + writer.close() + } + } + } + + private def initResults() = { + val results = new ConcurrentHashMap[String, List[TestResult]]() + QaseProjects.foreach(projectCode => results.put(projectCode, List.empty)) + results + } +} + +object QaseReporter { + val RunIdKeyPrefix = "QASE_RUN_ID_" + val CheckPRRunIdKey = "CHECKPR_RUN_ID" + val QaseProjects = Seq("NODE", "RIDE", "BU", "SAPI") + + private val patternStr = s"""(${QaseProjects.mkString("|")})-([0-9]+)""" + val CaseIdPattern: Regex = patternStr.r + + case class TestResult(status: String, comment: String, stackTrace: Option[String], caseId: Long, timeMs: Long) + object TestResult { + implicit val format: Format[TestResult] = Json.format + } +} diff --git a/lang/testkit/src/test/scala/com/wavesplatform/report/QaseRunCompleter.scala b/lang/testkit/src/test/scala/com/wavesplatform/report/QaseRunCompleter.scala new file mode 100644 index 00000000000..7c3585e45df --- /dev/null +++ b/lang/testkit/src/test/scala/com/wavesplatform/report/QaseRunCompleter.scala @@ -0,0 +1,93 @@ +package com.wavesplatform.report + +import com.wavesplatform.report.QaseReporter.{CheckPRRunIdKey, QaseProjects, TestResult} +import io.qase.api.QaseClient +import io.qase.api.config.QaseConfig.{PROJECT_CODE_KEY, RUN_ID_KEY} +import io.qase.api.services.impl.ReportersResultOperationsImpl +import io.qase.client.ApiClient +import io.qase.client.api.{CasesApi, ResultsApi, RunsApi} +import io.qase.client.model.{GetCasesFiltersParameter, GetRunsFiltersParameter, ResultCreate, RunCreate} +import play.api.libs.json.Json + +import java.io.File +import java.nio.file.Files +import scala.annotation.tailrec +import scala.io.Source +import scala.util.Using + +object QaseRunCompleter extends App { + if (QaseClient.getConfig.isEnabled) { + + val apiClient: ApiClient = QaseClient.getApiClient + val runsApi = new RunsApi(apiClient) + val resultsApi = new ResultsApi(apiClient) + val casesApi = new CasesApi(apiClient) + + QaseProjects.foreach { projectCode => + waitForActiveRunComplete(runsApi) + + val dir = new File("./") + val resultFiles = dir.listFiles + .filter(_.isFile) + .filter(_.getName.startsWith(projectCode)) + .toSeq + + Using.resource(resultFiles) { resultFiles => + val hasCases = casesApi.getCases(projectCode, new GetCasesFiltersParameter(), 1, 0).getResult.getCount > 0 + + if (hasCases) { + val results = resultFiles.flatMap { file => + Using.resource(Source.fromFile(file)) { source => + Json.parse(source.getLines().mkString("\n")).as[Seq[TestResult]] + } + } + + val description = Option(System.getenv(CheckPRRunIdKey)) + .map(rId => s"[GitHub checkPR action run details](https://github.com/wavesplatform/Waves/actions/runs/$rId)") + .getOrElse("Local checkPR run") + val title = Option(QaseClient.getConfig.runName()).getOrElse("unknown") + + val runId = runsApi + .createRun( + projectCode, + new RunCreate() + .title(title) + .description(description) + .includeAllCases(true) + .isAutotest(true) + ) + .getResult + .getId + val resultOps = new ReportersResultOperationsImpl(resultsApi) + results.foreach { result => + resultOps.addBulkResult( + new ResultCreate() + .status(ResultCreate.StatusEnum.fromValue(result.status)) + .comment(result.comment) + .stacktrace(result.stackTrace.orNull) + .caseId(result.caseId) + .timeMs(result.timeMs) + ) + } + + QaseClient.getConfig.setProperty(RUN_ID_KEY, runId.toString) + QaseClient.getConfig.setProperty(PROJECT_CODE_KEY, projectCode) + resultOps.sendBulkResult() + + runsApi.completeRun(projectCode, runId.toInt) + } + }(_.foreach(f => Files.delete(f.toPath))) + } + } + + @tailrec + private def waitForActiveRunComplete(runsApi: RunsApi, retries: Int = 10): Unit = { + val hasActiveRuns = QaseProjects.exists { projectCode => + runsApi.getRuns(projectCode, new GetRunsFiltersParameter().status("active"), 1, 0, "cases").getResult.getCount > 0 + } + if (hasActiveRuns && retries > 0) { + Thread.sleep(3000) + waitForActiveRunComplete(runsApi, retries - 1) + } + } +} diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/JsAPITest.scala b/lang/tests-js/src/test/scala/com/wavesplatform/JsAPITest.scala index fd9c0781652..d7394c16103 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/JsAPITest.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/JsAPITest.scala @@ -222,5 +222,21 @@ object JsAPITest extends JsTestBase { JSON.stringify(result.exprAst.expr) ==> JSON.stringify(JSON.parse(expected)) JSON.stringify(result.errorList) ==> "[]" } + + test("ill-formed characters") { + val invalidChar = '\ud87e' + val script = + s""" + |{-# STDLIB_VERSION 6 #-} + |{-# CONTENT_TYPE DAPP #-} + |{-# SCRIPT_TYPE ACCOUNT #-} + | + |func call(a: String, b: Int) = { + | let zzz = "aaa${invalidChar}bbb" + | ([], zzz) + |} + """.stripMargin + assertCompileError(script, "contains ill-formed characters") + } } } diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/NegativeTestsOfUnsupportedMethods.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/NegativeTestsOfUnsupportedMethods.scala index dcba27f582a..61928f77acd 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/NegativeTestsOfUnsupportedMethods.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/NegativeTestsOfUnsupportedMethods.scala @@ -37,7 +37,7 @@ object NegativeTestsOfUnsupportedMethods extends JsTestBase { private val min = "min(callerTestData)" val tests: Tests = Tests { - test("toBigInt functions compilation error: Undefined type: `BigInt` for ride v3, v4") { + test("RIDE-280. toBigInt function should throw a compilation error for RIDE versions V3 and V4.") { for (version <- oldVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("BigInt", version) for ( @@ -52,7 +52,7 @@ object NegativeTestsOfUnsupportedMethods extends JsTestBase { } } - test("compilation error: invalid data invoke for ride v3, v4 (argument before function)") { + test("RIDE-281. compilation error 'invalid data invoke' should occur for RIDE versions V3 and V4 when an argument is placed before the function.") { for (version <- oldVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) val script = precondition.codeForDAppInvocation(randomByteVectorArrayElement, randomAddressDataArrayElement, invokeArgBeforeFunc) @@ -60,7 +60,7 @@ object NegativeTestsOfUnsupportedMethods extends JsTestBase { } } - test("compilation error: blake2b256 functions Can't find a function for V3") { + test("RIDE-282. blake2b256 functions should throw an error for RIDE version V3.") { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", V3) for ( (data, function, error) <- Seq( @@ -75,7 +75,7 @@ object NegativeTestsOfUnsupportedMethods extends JsTestBase { } } - test("compilation error: keccak256 Can't find a functions for V3") { + test("RIDE-283. keccak256 functions should throw an error for RIDE version V3.") { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", V3) for ( (data, function, error) <- Seq( @@ -90,20 +90,34 @@ object NegativeTestsOfUnsupportedMethods extends JsTestBase { } } - test("Can't find a functions for V3") { + test("RIDE-284. containsElement functions should throw an error for RIDE version V3.") { val precondition = new GeneratorContractsForBuiltInFunctions("", V3) - for ( - (data, list, function) <- Seq( - (randomStringArrayElement, stringList, containsElement), - (randomInt.toString, intList, indexOf), - (randomInt.toString, intList, max), - (randomInt.toString, intList, min), - (randomInt.toString, intList, removeByIndex) - ) - ) { - val script = precondition.simpleRideCode(data, list, function) - assertCompileErrorDApp(script, V3, CANT_FIND_FUNCTION) - } + val script = precondition.simpleRideCode(randomStringArrayElement, stringList, containsElement) + assertCompileErrorDApp(script, V3, CANT_FIND_FUNCTION) + } + + test("RIDE-285. indexOf functions should throw an error for RIDE version V3.") { + val precondition = new GeneratorContractsForBuiltInFunctions("", V3) + val script = precondition.simpleRideCode(randomInt.toString, intList, indexOf) + assertCompileErrorDApp(script, V3, CANT_FIND_FUNCTION) + } + + test("RIDE-286. max functions should throw an error for RIDE version V3.") { + val precondition = new GeneratorContractsForBuiltInFunctions("", V3) + val script = precondition.simpleRideCode(randomInt.toString, intList, max) + assertCompileErrorDApp(script, V3, CANT_FIND_FUNCTION) + } + + test("RIDE-287. min functions should throw an error for RIDE version V3.") { + val precondition = new GeneratorContractsForBuiltInFunctions("", V3) + val script = precondition.simpleRideCode(randomInt.toString, intList, min) + assertCompileErrorDApp(script, V3, CANT_FIND_FUNCTION) + } + + test("RIDE-288. removeByIndex functions should throw an error for RIDE version V3.") { + val precondition = new GeneratorContractsForBuiltInFunctions("", V3) + val script = precondition.simpleRideCode(randomInt.toString, intList, removeByIndex) + assertCompileErrorDApp(script, V3, CANT_FIND_FUNCTION) } } } diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/accountDataStorage/GetBinary.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/accountDataStorage/GetBinary.scala index 301bf0708df..f192f4af3a2 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/accountDataStorage/GetBinary.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/accountDataStorage/GetBinary.scala @@ -23,7 +23,7 @@ object GetBinary extends JsTestBase { private val invalidGetBinaryValue = s"getBinaryValue(callerTestData)" val tests: Tests = Tests { - test("functions getBinary accountDataStorage compiles for address, alias and 'this'") { + test("RIDE-4. Compile getBinary functions for address, alias, and 'this'") { for (version <- testData.actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -48,7 +48,7 @@ object GetBinary extends JsTestBase { } } - test("functions own data getBinary accountDataStorage compiles for address, alias and 'this'") { + test("RIDE-5. Compile own data getBinary functions for address, alias, and 'this'") { for (version <- testData.versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for (ownData <- Seq(ownDataGetBinary, ownDataGetBinaryArgBeforeFunc, ownDataGetBinaryValueArgBeforeFunc, ownDataGetBinaryValue)) { @@ -58,7 +58,7 @@ object GetBinary extends JsTestBase { } } - test("negative tests for getBinary functions") { + test("RIDE-6. Test negative scenarios for getBinary functions") { val invalidFunction = s"getBinaryValue($randomInt)" val invalidArgBeforeFunction = s"$randomInt.getBinaryValue()" for (version <- testData.actualVersions) { @@ -79,8 +79,7 @@ object GetBinary extends JsTestBase { } } - - test("Can't find a own data functions overload Binary accountDataStorage for old Versions") { + test("RIDE-7. Ensure no overload of own data Binary accountDataStorage for old versions") { for (version <- testData.oldVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/accountDataStorage/GetBoolean.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/accountDataStorage/GetBoolean.scala index 21c3d356dd5..fbd9506e11e 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/accountDataStorage/GetBoolean.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/accountDataStorage/GetBoolean.scala @@ -23,7 +23,7 @@ object GetBoolean extends JsTestBase { private val invalidGetBooleanValue = s"getBooleanValue(callerTestData)" val tests: Tests = Tests { - test("functions getBoolean accountDataStorage compiles for address, alias and 'this'") { + test("RIDE-8. Compile getBoolean functions for address, alias, and 'this'") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -48,7 +48,7 @@ object GetBoolean extends JsTestBase { } } - test("functions own data getBoolean accountDataStorage compiles for address, alias and 'this'") { + test("RIDE-9. Compile own data getBoolean functions for address, alias, and 'this'") { for (version <- versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for (ownData <- Seq(ownDataGetBoolean, ownDataGetBooleanArgBeforeFunc, ownDataGetBooleanValueArgBeforeFunc, ownDataGetBooleanValue)) { @@ -58,7 +58,7 @@ object GetBoolean extends JsTestBase { } } - test("negative tests for getBoolean functions") { + test("RIDE-10. Negative tests for getBoolean functions") { val invalidFunction = s"getBooleanValue($randomInt)" val invalidArgBeforeFunction = s"$randomInt.getBooleanValue()" for (version <- actualVersions) { @@ -79,7 +79,7 @@ object GetBoolean extends JsTestBase { } } - test("Can't find a own data functions overload Boolean accountDataStorage for old Versions") { + test("RIDE-11. Ensure no overload of own data Boolean accountDataStorage for old Versions") { for (version <- oldVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/accountDataStorage/GetInteger.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/accountDataStorage/GetInteger.scala index 3fac49789d9..65e7715c890 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/accountDataStorage/GetInteger.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/accountDataStorage/GetInteger.scala @@ -23,7 +23,7 @@ object GetInteger extends JsTestBase { private val invalidGetIntValue = s"getIntegerValue(callerTestData)" val tests: Tests = Tests { - test("functions getInteger accountDataStorage compiles for address, alias and 'this'") { + test("RIDE-12. Compile getInteger functions for address, alias, and 'this'") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) for ( @@ -48,7 +48,7 @@ object GetInteger extends JsTestBase { } } - test("functions own data getInteger accountDataStorage compiles for address, alias and 'this'") { + test("RIDE-13. Compile own data getInteger functions for address, alias, and 'this'") { for (version <- versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) for (ownData <- Seq(ownDataGetInt, ownDataGetIntArgBeforeFunc, ownDataGetIntValueArgBeforeFunc, ownDataGetIntValue)) { @@ -58,7 +58,7 @@ object GetInteger extends JsTestBase { } } - test("negative tests for getInteger functions") { + test("RIDE-14. Test negative scenarios for getInteger functions") { val invalidFunction = s"getIntegerValue($randomInt)" val invalidArgBeforeFunction = s"$randomInt.getIntegerValue()" for (version <- actualVersions) { @@ -79,7 +79,7 @@ object GetInteger extends JsTestBase { } } - test("Can't find a own data functions overload Integer accountDataStorage for old Versions") { + test("RIDE-15. Ensure no overload of own data Integer accountDataStorage for old versions") { for (version <- oldVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/accountDataStorage/GetString.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/accountDataStorage/GetString.scala index 06a723d46ee..fa6d8a6ce89 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/accountDataStorage/GetString.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/accountDataStorage/GetString.scala @@ -23,7 +23,7 @@ object GetString extends JsTestBase { private val invalidGetStringValue = s"getStringValue(callerTestData)" val tests: Tests = Tests { - test("functions getString accountDataStorage compiles for address, alias and 'this'") { + test("RIDE-16. Compile getString functions for address, alias, and 'this'") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("String", version) for ( @@ -48,7 +48,7 @@ object GetString extends JsTestBase { } } - test("functions own data getString accountDataStorage compiles for address, alias and 'this'") { + test("RIDE-17. Compile own data getString functions for address, alias, and 'this'") { for (version <- versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("String", version) for (ownData <- Seq(ownDataGetString, ownDataGetStringArgBeforeFunc, ownDataGetStringValueArgBeforeFunc, ownDataGetStringValue)) { @@ -58,7 +58,7 @@ object GetString extends JsTestBase { } } - test("negative tests for getString functions") { + test("RIDE-18. Test negative scenarios for getString functions") { val invalidFunction = s"getStringValue($randomInt)" val invalidArgBeforeFunction = s"$randomInt.getStringValue()" for (version <- actualVersions) { @@ -79,7 +79,7 @@ object GetString extends JsTestBase { } } - test("Can't find a own data functions overload String accountDataStorage for old Versions") { + test("RIDE-19. Ensure no overload of own data Integer accountDataStorage for old versions") { for (version <- oldVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("String", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/accountDataStorage/IsDataStorageUntouched.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/accountDataStorage/IsDataStorageUntouched.scala index a1142110b0c..e5c1f9f3d37 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/accountDataStorage/IsDataStorageUntouched.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/accountDataStorage/IsDataStorageUntouched.scala @@ -21,7 +21,7 @@ object IsDataStorageUntouched extends JsTestBase { private val invalidFunctionErrorResult: String = invalidFunctionError("isDataStorageUntouched", 1) val tests: Tests = Tests { - test("functions IsDataStorageUntouched accountDataStorage compiles for address, alias and 'this'") { + test("RIDE-20. Compile isDataStorageUntouched functions for address, alias, and 'this'") { for (version <- versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -40,7 +40,7 @@ object IsDataStorageUntouched extends JsTestBase { } } - test("Non-matching types for function is DataStorageUntouched") { + test("RIDE-21. Non-matching types for function isDataStorageUntouched") { for (version <- versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -55,7 +55,7 @@ object IsDataStorageUntouched extends JsTestBase { } } - test("Invalid data for functions isDataStorageUntouched") { + test("RIDE-22. Invalid data for functions isDataStorageUntouched") { for (version <- versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -71,7 +71,7 @@ object IsDataStorageUntouched extends JsTestBase { } } - test("Can't find functions isDataStorageUntouched dataStorage accountDataStorage for old Versions") { + test("RIDE-23. Can't find functions isDataStorageUntouched dataStorage accountDataStorage for old Versions") { for (version <- oldVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/AddressFromRecipient.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/AddressFromRecipient.scala index cfcc832a66b..d5a277f471f 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/AddressFromRecipient.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/AddressFromRecipient.scala @@ -12,7 +12,7 @@ object AddressFromRecipient extends JsTestBase { private val invalidFunc = "addressFromRecipient()" val tests: Tests = Tests { - test("functions addressFromRecipient compiles for address, alias and 'this'") { + test("RIDE-24. Compile addressFromRecipient function for address, alias, and 'this'") { for (version <- testData.actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -31,7 +31,7 @@ object AddressFromRecipient extends JsTestBase { } } - test("addressFromRecipient Non-matching types: expected: Address|Alias") { + test("RIDE-25. Invalid data for functions addressFromRecipient") { for (version <- testData.actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -46,7 +46,7 @@ object AddressFromRecipient extends JsTestBase { } } - test("Function 'addressFromRecipient' requires 1 arguments") { + test("RIDE-26. Function 'addressFromRecipient' requires 1 arguments") { for (version <- testData.actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) val script = precondition.codeForAddressFromRecipient( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/AssetBalance.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/AssetBalance.scala index 11c74fb8d2c..934d92fe8fa 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/AssetBalance.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/AssetBalance.scala @@ -16,7 +16,7 @@ object AssetBalance extends JsTestBase { private val invalidAssetBalanceFunc = "assetBalance()" val tests: Tests = Tests { - test("Functions assetBalance compiles for address, alias and 'this'") { + test("RIDE-27. Compile assetBalance function for address, alias, and 'this'") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -35,7 +35,7 @@ object AssetBalance extends JsTestBase { } } - test("negative cases") { + test("RIDE-28. Invalid data must be validated") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/AssetInfo.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/AssetInfo.scala index c8bf81feaa7..2fc98649e25 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/AssetInfo.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/AssetInfo.scala @@ -16,7 +16,7 @@ object AssetInfo extends JsTestBase { val tests: Tests = Tests { - test("Functions assetInfo compiles") { + test("RIDE-30. Compile assetInfo function for asset") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Asset", version) for ( @@ -31,7 +31,7 @@ object AssetInfo extends JsTestBase { } } - test("negative cases") { + test("RIDE-29. Invalid data must be validated") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Asset", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/BlockInfoByHeight.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/BlockInfoByHeight.scala index 94e6410cb2a..e5489909ab9 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/BlockInfoByHeight.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/BlockInfoByHeight.scala @@ -13,7 +13,7 @@ object BlockInfoByHeight extends JsTestBase { private val invalidBlockInfoByHeight = "blockInfoByHeight()" val tests: Tests = Tests { - test("Functions blockInfoByHeight compiles") { + test("RIDE-31. BlockInfoByHeight function should compile") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("BlockInfo", version) for ( @@ -28,7 +28,7 @@ object BlockInfoByHeight extends JsTestBase { } } - test("negative cases blockInfoByHeight") { + test("RIDE-32. Negative cases for blockInfoByHeight function when invalid arguments are passed") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("BlockInfo", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/CalculateAssetId.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/CalculateAssetId.scala index 07e526de44a..a0779d32e80 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/CalculateAssetId.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/CalculateAssetId.scala @@ -13,7 +13,7 @@ object CalculateAssetId extends JsTestBase { private val invalidCalculateAssetId = "calculateAssetId()" val tests: Tests = Tests { - test("Functions CalculateAssetId for version V4 and more compiled for Issue") { + test("RIDE-33. CalculateAssetId function should compile for version V4 and higher when called for Issue operatio") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -28,7 +28,7 @@ object CalculateAssetId extends JsTestBase { } } - test("negative cases CalculateAssetId for version V4 and more") { + test("RIDE-34. Negative cases for CalculateAssetId function for version V4 and higher") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -44,7 +44,7 @@ object CalculateAssetId extends JsTestBase { } } - test("negative cases CalculateAssetId for version V3") { + test("RIDE-35. Negative cases for CalculateAssetId function for version V3") { val precondition = new GeneratorContractsForBuiltInFunctions("", V3) for ( (data, function) <- Seq( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/CalculateLeaseId.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/CalculateLeaseId.scala index f35e00a9ebe..2cfc43abf61 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/CalculateLeaseId.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/CalculateLeaseId.scala @@ -12,7 +12,7 @@ object CalculateLeaseId extends JsTestBase { private val invalidCalculateLeaseId = "calculateLeaseId()" val tests: Tests = Tests { - test("Functions calculateLeaseId for V5 and more compiles for address") { + test("RIDE-36. calculateLeaseId function should compile for version V5 and higher when called for an address") { for (version <- versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -29,7 +29,7 @@ object CalculateLeaseId extends JsTestBase { } } - test("negative cases CalculateAssetId for version V5 and more") { + test("RIDE-37. Negative cases for calculateLeaseId function for version V5 and higher") { for (version <- versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -46,7 +46,7 @@ object CalculateLeaseId extends JsTestBase { } } - test("negative cases CalculateAssetId for version V3, V4") { + test("RIDE-38. Negative cases for calculateLeaseId function for versions V3 and V4") { for (version <- oldVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/ScriptHash.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/ScriptHash.scala index ef488eccd60..7939e97a755 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/ScriptHash.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/ScriptHash.scala @@ -27,7 +27,7 @@ object ScriptHash extends JsTestBase { private val invalidScriptHashArgBeforeFunc = s"callerTestData.scriptHash($randomStringArrayElement)" val tests: Tests = Tests { - test("Functions ScriptHash for V5 and more compiles for address") { + test("RIDE-39. ScriptHash function should compile for version V5 and higher when called for an address") { for (version <- versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -46,7 +46,7 @@ object ScriptHash extends JsTestBase { } } - test("negative cases ScriptHash for V5 and more") { + test("Ride-40. Negative cases for ScriptHash function for version V5 and higher") { for (version <- versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -64,7 +64,7 @@ object ScriptHash extends JsTestBase { } } - test("negative cases CalculateAssetId for version V3, V4") { + test("RIDE-41. Negative cases for ScriptHash function for versions V3 and V4") { for (version <- oldVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/TransactionHeightById.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/TransactionHeightById.scala index df3ab7c8a91..e5073c55e0a 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/TransactionHeightById.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/TransactionHeightById.scala @@ -15,7 +15,7 @@ object TransactionHeightById extends JsTestBase { val tests: Tests = Tests { - test("Functions TransactionHeightById compiles") { + test("RIDE-42. TransactionHeightById function should compile") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) for ( @@ -30,7 +30,7 @@ object TransactionHeightById extends JsTestBase { } } - test("negative cases TransactionHeightById") { + test("RIDE-43. Negative cases for TransactionHeightById function") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/TransferTransactionById.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/TransferTransactionById.scala index 1cc6004cfb7..eceb3cdf48e 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/TransferTransactionById.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/TransferTransactionById.scala @@ -18,7 +18,7 @@ object TransferTransactionById extends JsTestBase { private val invalidTransferTransactionByIdArg = s"callerTestData.transferTransactionById(callerTestData)" val tests: Tests = Tests { - test("Functions TransactionHeightById compiles") { + test("RIDE-44. TransactionHeightById function should compile") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Unit", version) for ( @@ -33,7 +33,7 @@ object TransferTransactionById extends JsTestBase { } } - test("negative cases TransactionHeightById") { + test("RIDE-45. Negative cases for TransactionHeightById function") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Unit", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/WavesBalance.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/WavesBalance.scala index 795efab3419..0947de58311 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/WavesBalance.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/blockchain/WavesBalance.scala @@ -14,7 +14,7 @@ object WavesBalance extends JsTestBase { private val invalidWavesBalanceArg = s"callerTestData.wavesBalance(callerTestData)" val tests: Tests = Tests { - test(" Functions wavesBalance for version V4 and more compiles for address, alias and 'this'") { + test("RIDE-46. wavesBalance function for version V4 and more should compile for address, alias, and 'this'") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("BalanceDetails", version) for ( @@ -33,7 +33,7 @@ object WavesBalance extends JsTestBase { } } - test(" Functions wavesBalance for version V4 and more - negative cases") { + test("RIDE-47. Negative cases for wavesBalance function for version V4 and more") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("BalanceDetails", version) for ( @@ -50,7 +50,7 @@ object WavesBalance extends JsTestBase { } } - test(" Functions wavesBalance for V3 compiles for address, alias and 'this'") { + test("RIDE-48. Functions wavesBalance for V3 compiles for address, alias and 'this'") { val precondition = new GeneratorContractsForBuiltInFunctions("Int", V3) for ( (data, function) <- Seq( @@ -67,7 +67,7 @@ object WavesBalance extends JsTestBase { } } - test("compilation error: wavesBalance for V3 Non-matching type") { + test("RIDE-49. compilation error: wavesBalance for V3 Non-matching type") { val precondition = new GeneratorContractsForBuiltInFunctions("Int", V3) for ( (data, function, error) <- Seq( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/byteArray/Drop.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/byteArray/Drop.scala index 187ab508361..c73ff10bb68 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/byteArray/Drop.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/byteArray/Drop.scala @@ -14,7 +14,7 @@ object Drop extends JsTestBase { private val invalidDropArgBeforeFunc = s"callerTestData.drop(callerTestData, $randomInt)" val tests: Tests = Tests { - test(" Functions Drop compiles") { + test("RIDE-50. Drop function should compile for valid values") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -29,7 +29,7 @@ object Drop extends JsTestBase { } } - test(" Drop Can't find a function overload") { + test("RIDE-51. Drop function throws an error for invalid values") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/byteArray/DropRight.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/byteArray/DropRight.scala index b6cdcb9c015..164d5e942ff 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/byteArray/DropRight.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/byteArray/DropRight.scala @@ -14,7 +14,7 @@ object DropRight extends JsTestBase { private val invalidDropRightArgBeforeFunc = s"callerTestData.dropRight(callerTestData, $randomInt)" val tests: Tests = Tests { - test(" Functions DropRight compiles") { + test("RIDE-52. DropRight function should compile for valid values") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -29,7 +29,7 @@ object DropRight extends JsTestBase { } } - test(" DropRight Can't find a function overload") { + test("RIDE-53. DropRight function throws an error for invalid values") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/byteArray/Size.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/byteArray/Size.scala index c5f9b4712c8..e6717d440a7 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/byteArray/Size.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/byteArray/Size.scala @@ -13,7 +13,7 @@ object Size extends JsTestBase { private val invalidSizeArgBeforeFunc = s"callerTestData.size(callerTestData, callerTestData)" val tests: Tests = Tests { - test(" Functions Size compiles") { + test("RIDE-54. Size function should compile for valid values") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -28,7 +28,7 @@ object Size extends JsTestBase { } } - test(" DropRight Can't find a function overload") { + test("RIDE-55. Size function throws an error for invalid values") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/byteArray/Take.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/byteArray/Take.scala index 15e69680650..9ebecfa3302 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/byteArray/Take.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/byteArray/Take.scala @@ -14,7 +14,7 @@ object Take extends JsTestBase { private val invalidTakeNotInt = s"take(callerTestData, $randomByteVectorArrayElement)" val tests: Tests = Tests { - test(" Functions Take compiles") { + test("RIDE-56. Take function should compile for valid values") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -29,7 +29,7 @@ object Take extends JsTestBase { } } - test(" Take Can't find a function overload") { + test("RIDE-57. Take function throws an error for invalid values") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/byteArray/TakeRight.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/byteArray/TakeRight.scala index afdf8dce142..90cce3dc752 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/byteArray/TakeRight.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/byteArray/TakeRight.scala @@ -14,7 +14,7 @@ object TakeRight extends JsTestBase { private val invalidTakeRightNotInt = s"takeRight(callerTestData, $randomByteVectorArrayElement)" val tests: Tests = Tests { - test(" Functions TakeRight compiles") { + test("RIDE-58. TakeRight function should compile for valid values") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -29,7 +29,7 @@ object TakeRight extends JsTestBase { } } - test(" TakeRight Can't find a function overload") { + test("RIDE-59. TakeRight function throws an error for invalid values") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/AddressFromPublicKey.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/AddressFromPublicKey.scala index ba66ac2a518..34038f28eba 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/AddressFromPublicKey.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/AddressFromPublicKey.scala @@ -14,7 +14,7 @@ object AddressFromPublicKey extends JsTestBase { private val invalidAddressFromPublicKeyData = s"addressFromPublicKey(callerTestData, $randomUnionArrayElement)" val tests: Tests = Tests { - test(" Functions AddressFromPublicKey compiles") { + test("RIDE-60. AddressFromPublicKey function should compile for valid values") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Address", version) for ( @@ -29,7 +29,7 @@ object AddressFromPublicKey extends JsTestBase { } } - test(" AddressFromPublicKey Can't find a function overload") { + test("RIDE-61. AddressFromPublicKey function throws an error for invalid values") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ParseBigInt.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ParseBigInt.scala index fc916afe371..3dab78972fc 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ParseBigInt.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ParseBigInt.scala @@ -21,7 +21,7 @@ object ParseBigInt extends JsTestBase { private val invalidFunctionErrorResultParseBigIntValue: String = testData.invalidFunctionError("parseBigIntValue", 1) val tests: Tests = Tests { - test(" Functions parseBigInt compiles") { + test("RIDE-62. ParseBigInt function should compile for valid values") { for (version <- versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("BigInt", version) for ( @@ -36,7 +36,7 @@ object ParseBigInt extends JsTestBase { } } - test(" parseBigInt Can't find a function overload") { + test("RIDE-63. ParseBigInt function throws an error for invalid values") { for (version <- oldVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("BigInt", version) for ( @@ -51,7 +51,7 @@ object ParseBigInt extends JsTestBase { } } - test(" parseBigInt invalid functions") { + test("RIDE-64. Function parseBigInt should throw an error for invalid functions") { for (version <- versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("BigInt", version) for ( @@ -68,7 +68,7 @@ object ParseBigInt extends JsTestBase { } } - test(" Functions parseBigIntValue compiles") { + test("RIDE-65. ParseBigIntValue function should compile for valid values") { for (version <- versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("BigInt", version) for ( @@ -83,7 +83,7 @@ object ParseBigInt extends JsTestBase { } } - test(" parseBigIntValue Can't find a function overload") { + test("RIDE-66. ParseBigIntValue function throws an error for invalid values") { for (version <- oldVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("BigInt", version) for ( @@ -98,7 +98,7 @@ object ParseBigInt extends JsTestBase { } } - test(" parseBigIntValue invalid functions") { + test("RIDE-67. Function parseBigIntValue should throw an error for invalid functions") { for (version <- versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("BigInt", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ParseInt.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ParseInt.scala index eaf274f5659..f2adab3e6a9 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ParseInt.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ParseInt.scala @@ -20,7 +20,7 @@ object ParseInt extends JsTestBase { private val invalidParseIntValueArgBeforeFunc = "callerTestData.parseIntValue(callerTestData)" val tests: Tests = Tests { - test(" Functions parseInt compiles") { + test("RIDE-68. ParseInt function should compile for valid values") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) for ( @@ -35,7 +35,7 @@ object ParseInt extends JsTestBase { } } - test(" parseBigInt negative tests") { + test("RIDE-69. ParseInt function throws an error for invalid values") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) for ( @@ -52,7 +52,7 @@ object ParseInt extends JsTestBase { } } - test(" Functions parseIntValue compiles") { + test("RIDE-70. parseIntValue function should compile for valid values") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) for ( @@ -67,7 +67,7 @@ object ParseInt extends JsTestBase { } } - test(" parseIntValue negative tests") { + test("RIDE-71. parseIntValue function throws an error for invalid values") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ToBigInt.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ToBigInt.scala index 9d58eda1ae6..e34f8042cef 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ToBigInt.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ToBigInt.scala @@ -15,7 +15,7 @@ object ToBigInt extends JsTestBase { private val invalidParseBigIntArgBeforeFunc = s"callerTestData.toBigInt(callerTestData, 123, $randomInt)" val tests: Tests = Tests { - test(" Functions toBigInt compiles") { + test("RIDE-72. ToBigInt function should compile for valid values") { for (version <- versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("BigInt", version) for ( @@ -34,7 +34,7 @@ object ToBigInt extends JsTestBase { } } - test(" Functions toBigInt negative tests") { + test("RIDE-73. ToBigInt function throws an error for invalid values") { for (version <- versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("BigInt", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ToBytes.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ToBytes.scala index 5ddcc52b52b..0cd18362c34 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ToBytes.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ToBytes.scala @@ -14,7 +14,7 @@ object ToBytes extends JsTestBase { private val invalidToBytesArgBeforeFunc = "callerTestData.toBytes(callerTestData)" val tests: Tests = Tests { - test(" Functions toBytes compiles with int, string, boolean") { + test("RIDE-74. toBytes function should compile for valid values int, string, boolean") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -33,7 +33,7 @@ object ToBytes extends JsTestBase { } } - test(" Functions toBytes compiles with bigInt for V5, V6 versions") { + test("RIDE-75. toBytes function should compile with bigInt for V5, V6 versions") { for (version <- versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -48,7 +48,7 @@ object ToBytes extends JsTestBase { } } - test(" toBytes negative tests") { + test("RIDE-76. toBytes function throws an error for invalid values") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ToInt.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ToInt.scala index 060c143a2b5..632112619f3 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ToInt.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ToInt.scala @@ -21,7 +21,7 @@ object ToInt extends JsTestBase { private val invalidParseIntArgBeforeFunc = s"callerTestData.toInt(callerTestData, $randomInt)" val tests: Tests = Tests { - test(" Functions toInt compiles with ByteVector") { + test("RIDE-77. Functions toInt function should compile for valid ByteVector") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) for ( @@ -38,7 +38,7 @@ object ToInt extends JsTestBase { } } - test(" Functions toInt compiles with BigInt") { + test("RIDE-78. ToInt function should compile with bigInt for V5, V6 versions") { for (version <- versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) for ( @@ -53,7 +53,7 @@ object ToInt extends JsTestBase { } } - test(" Functions toInt negative tests") { + test("RIDE-79. ToInt function throws an error for invalid values") { for (version <- versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ToString.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ToString.scala index fd759d63c83..1df311f3dd5 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ToString.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ToString.scala @@ -13,14 +13,13 @@ import testHelpers.TestDataConstantsAndMethods.{CANT_FIND_A_FUNCTION_OVERLOAD, a import utest.{Tests, test} object ToString extends JsTestBase { - // toString private val toStr = "toString(callerTestData)" private val toStrArgBeforeFunc = "callerTestData.toString()" private val invalidToStr = "toString()" private val invalidToStrArgBeforeFunc = "callerTestData.toString(callerTestData)" val tests: Tests = Tests { - test(" Functions toString compiles with int, string, boolean") { + test("RIDE-80. Functions toString function should compile with int, string, boolean") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("String", version) for ( @@ -39,7 +38,7 @@ object ToString extends JsTestBase { } } - test(" Functions toString compiles with bigInt for V5, V6 versions") { + test("RIDE-81. Functions toString should compile with bigInt for V5, V6 versions") { for (version <- versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("String", version) for ( @@ -54,7 +53,7 @@ object ToString extends JsTestBase { } } - test(" toString negative tests") { + test("RIDE-82. toString function throws an error for invalid values") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("String", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ToUtf8String.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ToUtf8String.scala index 26c01dd85dd..6f3c196bdff 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ToUtf8String.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/ToUtf8String.scala @@ -7,14 +7,13 @@ import testHelpers.TestDataConstantsAndMethods.{GreaterV3ResultStringEntry, actu import utest.{Tests, test} object ToUtf8String extends JsTestBase { - // toUtf8String private val toUtf8String = "toUtf8String(callerTestData)" private val toUtf8StringArgBeforeFunc = "callerTestData.toUtf8String()" private val invalidToUtf8String = "toUtf8String()" private val invalidToUtf8StringArgBeforeFunc = "callerTestData.toUtf8String(callerTestData)" val tests: Tests = Tests { - test(" Functions toUtf8String compiles") { + test("RIDE-83. Functions toUtf8String function should compile for valid values") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("String", version) for ((data, function) <- Seq( @@ -28,7 +27,7 @@ object ToUtf8String extends JsTestBase { } } - test(" toUtf8String negative tests") { + test("RIDE-84. toUtf8String function throws an error for invalid values") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("String", version) for ((data, function, error) <- Seq( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/TransferTransactionFromProto.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/TransferTransactionFromProto.scala index 0cd0fad95cd..b800d9b2306 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/TransferTransactionFromProto.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/converting/TransferTransactionFromProto.scala @@ -14,7 +14,7 @@ object TransferTransactionFromProto extends JsTestBase { private val invalidTransferTransactionFromProtoArgBeforeFunction = "transferTransactionFromProto()" val tests: Tests = Tests { - test(" Functions transferTransactionFromProto compiles for Issue V4 and more") { + test("RIDE-85. transferTransactionFromProto function should compile for Issue V4 and more") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("TransferTransaction", version) for ( @@ -29,7 +29,7 @@ object TransferTransactionFromProto extends JsTestBase { } } - test(" transferTransactionFromProto negative tests for V4 and more") { + test("RIDE-86. transferTransactionFromProto function throws an error for invalid values for V4 and more") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("TransferTransaction", version) for ( @@ -50,7 +50,7 @@ object TransferTransactionFromProto extends JsTestBase { } } - test("compilation error: transferTransactionFromProto for V3 function is missing") { + test("RIDE-87. transferTransactionFromProto function should throw a compilation error for Ride V3") { val precondition = new GeneratorContractsForBuiltInFunctions("TransferTransaction", V3) for ( (data, function) <- Seq( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/dappToDappInvocation/Invoke.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/dappToDappInvocation/Invoke.scala index 7e60a9fc303..97a40182221 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/dappToDappInvocation/Invoke.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/dappToDappInvocation/Invoke.scala @@ -14,7 +14,7 @@ object Invoke extends JsTestBase { private val invalidFunctionErrorResult: String = invalidFunctionError("invoke", 4) val tests: Tests = Tests { - test(" functions invoke compiles for Issue V4 and more") { + test("RIDE-88. Invoke function should compile for Issue RIDE V5 and more") { for (version <- versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -29,7 +29,7 @@ object Invoke extends JsTestBase { } } - test(" Functions invoke negative tests for V4 and more") { + test("RIDE-89. Invoke function throws an error for invalid values for RIDE V5 and more") { for (version <- versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/dappToDappInvocation/ReentrantInvoke.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/dappToDappInvocation/ReentrantInvoke.scala index 5367cbdd302..b45c83af313 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/dappToDappInvocation/ReentrantInvoke.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/dappToDappInvocation/ReentrantInvoke.scala @@ -14,7 +14,7 @@ object ReentrantInvoke extends JsTestBase { private val invalidFunctionErrorResult: String = testData.invalidFunctionError("reentrantInvoke", 4) val tests: Tests = Tests { - test(" functions invoke compiles for Issue V4 and more") { + test("RIDE-90. ReentrantInvoke function should compile for Issue RIDE V5 and more") { for (version <- versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -29,7 +29,7 @@ object ReentrantInvoke extends JsTestBase { } } - test(" Functions invoke negative tests for V4 and more") { + test("RIDE-91. ReentrantInvoke function throws an error for invalid values for RIDE V5 and more") { for (version <- versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/dataTransaction/GetBinary.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/dataTransaction/GetBinary.scala index 53127bcd593..19db5d5331d 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/dataTransaction/GetBinary.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/dataTransaction/GetBinary.scala @@ -29,7 +29,7 @@ object GetBinary extends JsTestBase { private val invalidGetBinaryValueArgBeforeFunc = s"callerTestData.getBinaryValue()" val tests: Tests = Tests { - test(" Functions getBinary dataTransaction compiles for versions V4 and more") { + test("RIDE-92. getBinary functions for dataTransaction should compile for versions V4 and above") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -74,7 +74,7 @@ object GetBinary extends JsTestBase { } } - test(" Functions getBinary dataTransaction compiles for versions V3") { + test("RIDE-93. getBinary function for dataTransaction should compile for V3") { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", V3) for ( (data, binary) <- Seq( @@ -93,7 +93,7 @@ object GetBinary extends JsTestBase { } } - test(" Can't find getBinary functions overload for V4 and more") { + test("RIDE-94. getBinary function should throw an error for invalid data type for versions V4 and above") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -114,7 +114,7 @@ object GetBinary extends JsTestBase { } } - test(" Can't find getBinary functions overload for V3") { + test("RIDE-95. getBinary function should throw an error for invalid data type for V3") { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", V3) for ( (data, binary) <- Seq( @@ -133,7 +133,7 @@ object GetBinary extends JsTestBase { } } - test(" Invalid getBinary functions for V4 and more") { + test("RIDE-96. Invalid getBinary functions should not compile for versions V4 and above") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -150,7 +150,7 @@ object GetBinary extends JsTestBase { } } - test(" Invalid getBinary functions for V3") { + test("RIDE-97. Invalid getBinary functions should not compile for V3") { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", V3) for ( (data, binary) <- Seq( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/dataTransaction/GetBoolean.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/dataTransaction/GetBoolean.scala index 0f35a867097..22c6fd07fb7 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/dataTransaction/GetBoolean.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/dataTransaction/GetBoolean.scala @@ -29,7 +29,7 @@ object GetBoolean extends JsTestBase { private val invalidGetBooleanValueArgBeforeFunc = s"callerTestData.getBooleanValue()" val tests: Tests = Tests { - test(" Functions getBoolean dataTransaction compiles for versions V4 and more") { + test("RIDE-98. getBoolean functions for dataTransaction should compile for versions V4 and above") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -74,7 +74,7 @@ object GetBoolean extends JsTestBase { } } - test(" Functions getBoolean dataTransaction compiles for versions V3") { + test("RIDE-99. getBoolean function for dataTransaction should compile for V3") { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", V3) for ( (data, binary) <- Seq( @@ -93,7 +93,7 @@ object GetBoolean extends JsTestBase { } } - test(" Can't find getBoolean functions overload for V4 and more") { + test("RIDE-100. getBoolean function should throw an error for invalid data type for versions V4 and above") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -114,7 +114,7 @@ object GetBoolean extends JsTestBase { } } - test(" Can't find getBoolean functions overload for V3") { + test("RIDE-101. getBoolean function should throw an error for invalid data type for V3") { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", V3) for ( (data, binary) <- Seq( @@ -133,7 +133,7 @@ object GetBoolean extends JsTestBase { } } - test(" Invalid getBoolean functions for V4 and more") { + test("RIDE-102. Invalid getBoolean functions should not compile for versions V4 and above") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -150,7 +150,7 @@ object GetBoolean extends JsTestBase { } } - test(" Invalid getBoolean functions for V3") { + test("RIDE-103. Invalid getBoolean functions should not compile for V3") { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", V3) for ( (data, binary) <- Seq( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/dataTransaction/GetInteger.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/dataTransaction/GetInteger.scala index a8d3dba2685..d919d93d4c7 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/dataTransaction/GetInteger.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/dataTransaction/GetInteger.scala @@ -38,7 +38,7 @@ object GetInteger extends JsTestBase { private val invalidGetIntegerValueArgBeforeFunc = s"callerTestData.getIntegerValue()" val tests: Tests = Tests { - test(" Functions getInteger dataTransaction compiles for versions V4 and more") { + test("RIDE-104. getInteger functions for dataTransaction should compile for versions V4 and above") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) for ( @@ -83,7 +83,7 @@ object GetInteger extends JsTestBase { } } - test(" Functions getInteger dataTransaction compiles for versions V3") { + test("RIDE-105. getInteger function for dataTransaction should compile for V3") { val precondition = new GeneratorContractsForBuiltInFunctions("Int", V3) for ( (data, binary) <- Seq( @@ -102,7 +102,7 @@ object GetInteger extends JsTestBase { } } - test(" Can't find getInteger functions overload for V4 and more") { + test("RIDE-106. getInteger function should throw an error for invalid data type for versions V4 and above") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) for ( @@ -123,7 +123,7 @@ object GetInteger extends JsTestBase { } } - test(" Can't find getInteger functions overload for V3") { + test("RIDE-107. getInteger function should throw an error for invalid data type for V3") { val precondition = new GeneratorContractsForBuiltInFunctions("Int", V3) for ( (data, binary) <- Seq( @@ -142,7 +142,7 @@ object GetInteger extends JsTestBase { } } - test(" Invalid getInteger functions for V4 and more") { + test("RIDE-108. Invalid getInteger functions should not compile for versions V4 and above") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) for ( @@ -159,7 +159,7 @@ object GetInteger extends JsTestBase { } } - test(" Invalid getInteger functions for V3") { + test("RIDE-109. Invalid getInteger functions should not compile for V3") { val precondition = new GeneratorContractsForBuiltInFunctions("Int", V3) for ( (data, binary) <- Seq( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/dataTransaction/GetString.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/dataTransaction/GetString.scala index 1a44b5da3bd..f1167868ac5 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/dataTransaction/GetString.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/dataTransaction/GetString.scala @@ -29,7 +29,7 @@ object GetString extends JsTestBase { private val invalidGetStringValueArgBeforeFunc = s"callerTestData.getStringValue()" val tests: Tests = Tests { - test(" Functions getString dataTransaction compiles for versions V4 and more") { + test("RIDE-110. getString functions for dataTransaction should compile for versions V4 and above") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("String", version) for ( @@ -74,7 +74,7 @@ object GetString extends JsTestBase { } } - test(" Functions getString dataTransaction compiles for versions V3") { + test("RIDE-111. getString function for dataTransaction should compile for V3") { val precondition = new GeneratorContractsForBuiltInFunctions("String", V3) for ( (data, binary) <- Seq( @@ -93,7 +93,7 @@ object GetString extends JsTestBase { } } - test(" Can't find getString functions overload for V4 and more") { + test("RIDE-112. getString function should throw an error for invalid data type for versions V4 and above") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("String", version) for ( @@ -114,7 +114,7 @@ object GetString extends JsTestBase { } } - test(" Can't find getString functions overload for V3") { + test("RIDE-113. getString function should throw an error for invalid data type for V3") { val precondition = new GeneratorContractsForBuiltInFunctions("String", V3) for ( (data, binary) <- Seq( @@ -133,7 +133,7 @@ object GetString extends JsTestBase { } } - test(" Invalid getString functions for V4 and more") { + test("RIDE-114. Invalid getString functions should not compile for versions V4 and above") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("String", version) for ( @@ -150,7 +150,7 @@ object GetString extends JsTestBase { } } - test(" Invalid getString functions for V3") { + test("RIDE-115. Invalid getString functions should not compile for V3") { val precondition = new GeneratorContractsForBuiltInFunctions("String", V3) for ( (data, binary) <- Seq( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/decoding/AddressFromString.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/decoding/AddressFromString.scala index ed19899220e..0eb37fc3d9b 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/decoding/AddressFromString.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/decoding/AddressFromString.scala @@ -17,7 +17,7 @@ object AddressFromString extends JsTestBase { private val invalidFunctionErrorForAddressFromStringValue = invalidFunctionError("addressFromStringValue", 1) val tests: Tests = Tests { - test("Functions addressFromString compiles") { + test("RIDE-116. Function addressFromString should compile for valid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Address", version) for ( @@ -34,7 +34,7 @@ object AddressFromString extends JsTestBase { } } - test("Compilation error: addressFromString invalid data or function") { + test("RIDE-117. Function addressFromString should throw an error for invalid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Address", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/decoding/FromBaseString.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/decoding/FromBaseString.scala index 906722a1b2f..58e5a59db4c 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/decoding/FromBaseString.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/decoding/FromBaseString.scala @@ -31,7 +31,7 @@ object FromBaseString extends JsTestBase { private val invalidErrorForFromBase64String = invalidFunctionError("fromBase64String", 1) val tests: Tests = Tests { - test("fromBaseString functions compiles") { + test("RIDE-118. Function fromBaseString should compile for valid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -51,7 +51,7 @@ object FromBaseString extends JsTestBase { } // invalid data - test("fromBaseString functions invalid data") { + test("RIDE-119. Function fromBaseString should throw an error for invalid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/encoding/ToBaseString.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/encoding/ToBaseString.scala index 384281ab049..1ca2701e767 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/encoding/ToBaseString.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/encoding/ToBaseString.scala @@ -32,7 +32,7 @@ object ToBaseString extends JsTestBase { private val invalidErrorForToBase64String = testData.invalidFunctionError("toBase64String", 1) val tests: Tests = Tests { - test("toBaseString functions compiles") { + test("RIDE-120. Function toBaseString should compile for valid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("String", version) for ( @@ -51,8 +51,7 @@ object ToBaseString extends JsTestBase { } } - // invalid data - test("toBaseString functions invalid data") { + test("RIDE-121. Function toBaseString should throw an error for invalid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("String", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/blake2b256/Blake2b256.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/blake2b256/Blake2b256.scala index 45a12dc4822..6fe2bcdc91d 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/blake2b256/Blake2b256.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/blake2b256/Blake2b256.scala @@ -7,7 +7,6 @@ import testHelpers.TestDataConstantsAndMethods.{GreaterV3ResultBinaryEntry, actu import utest.{Tests, test} object Blake2b256 extends JsTestBase { - // blake2b256 private val blake2b256 = "blake2b256(callerTestData)" private val blake2b256ArgBeforeFunc = "callerTestData.blake2b256()" private val invalidBlake2b256 = "blake2b256()" @@ -15,7 +14,7 @@ object Blake2b256 extends JsTestBase { private val invalidErrorBlake2b256 = invalidFunctionError("blake2b256", 1) val tests: Tests = Tests { - test("blake2b256 functions compiles with a ByteVector") { + test("RIDE-122. Function blake2b256 should compile for valid ByteVector") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -30,7 +29,7 @@ object Blake2b256 extends JsTestBase { } } - test("compilation errors blake2b256") { + test("RIDE-123. Function blake2b256 should throw an error for invalid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/blake2b256/Blake2b256_128Kb.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/blake2b256/Blake2b256_128Kb.scala index 974919e5463..ab053a282d8 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/blake2b256/Blake2b256_128Kb.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/blake2b256/Blake2b256_128Kb.scala @@ -7,7 +7,6 @@ import testHelpers.TestDataConstantsAndMethods.{GreaterV3ResultBinaryEntry, actu import utest.{Tests, test} object Blake2b256_128Kb extends JsTestBase { - // blake2b256_128Kb private val blake2b256_128Kb = "blake2b256_128Kb(callerTestData)" private val blake2b256_128KbArgBeforeFunc = "callerTestData.blake2b256_128Kb()" private val invalidBlake2b256_128Kb = "blake2b256_128Kb()" @@ -15,7 +14,7 @@ object Blake2b256_128Kb extends JsTestBase { private val invalidErrorBlake2b256_128Kb = testData.invalidFunctionError("blake2b256_128Kb", 1) val tests: Tests = Tests { - test("blake2b256_128Kb functions compiles with a ByteVector") { + test("RIDE-130. Function blake2b256_128Kb should compile for valid ByteVector") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -30,7 +29,7 @@ object Blake2b256_128Kb extends JsTestBase { } } - test("compilation errors blake2b256_128Kb") { + test("RIDE-131. Function blake2b256_128Kb should throw an error for invalid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -47,5 +46,4 @@ object Blake2b256_128Kb extends JsTestBase { } } } - } diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/blake2b256/Blake2b256_16Kb.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/blake2b256/Blake2b256_16Kb.scala index d9cb48d0ce5..5b71434273f 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/blake2b256/Blake2b256_16Kb.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/blake2b256/Blake2b256_16Kb.scala @@ -7,7 +7,6 @@ import testHelpers.TestDataConstantsAndMethods.{GreaterV3ResultBinaryEntry, actu import utest.{Tests, test} object Blake2b256_16Kb extends JsTestBase { - // blake2b256_16Kb private val blake2b256_16Kb = "blake2b256_16Kb(callerTestData)" private val blake2b256_16KbArgBeforeFunc = "callerTestData.blake2b256_16Kb()" private val invalidBlake2b256_16Kb = "blake2b256_16Kb()" @@ -15,7 +14,7 @@ object Blake2b256_16Kb extends JsTestBase { private val invalidErrorBlake2b256_16Kb = testData.invalidFunctionError("blake2b256_16Kb", 1) val tests: Tests = Tests { - test("blake2b256_16Kb functions compiles with a ByteVector") { + test("RIDE-124. Function blake2b256_16Kb should compile for valid ByteVector") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -30,7 +29,7 @@ object Blake2b256_16Kb extends JsTestBase { } } - test("compilation errors blake2b256_16Kb") { + test("RIDE-125. Function blake2b256 should throw an error for invalid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/blake2b256/Blake2b256_32Kb.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/blake2b256/Blake2b256_32Kb.scala index bcb05bae61a..5460efe85a7 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/blake2b256/Blake2b256_32Kb.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/blake2b256/Blake2b256_32Kb.scala @@ -7,7 +7,6 @@ import testHelpers.TestDataConstantsAndMethods.{GreaterV3ResultBinaryEntry, actu import utest.{Tests, test} object Blake2b256_32Kb extends JsTestBase { - // blake2b256_32Kb private val blake2b256_32Kb = "blake2b256_32Kb(callerTestData)" private val blake2b256_32KbArgBeforeFunc = "callerTestData.blake2b256_32Kb()" private val invalidBlake2b256_32Kb = "blake2b256_32Kb()" @@ -15,7 +14,7 @@ object Blake2b256_32Kb extends JsTestBase { private val invalidErrorBlake2b256_32Kb = testData.invalidFunctionError("blake2b256_32Kb", 1) val tests: Tests = Tests { - test("blake2b256_32Kb functions compiles with a ByteVector") { + test("RIDE-126. Function blake2b256 should compile for valid ByteVector") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -30,7 +29,7 @@ object Blake2b256_32Kb extends JsTestBase { } } - test("compilation errors blake2b256_32Kb") { + test("RIDE-127. Function blake2b256_32Kb should throw an error for invalid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/blake2b256/Blake2b256_64Kb.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/blake2b256/Blake2b256_64Kb.scala index 3e3241c8b45..7bff43f92b7 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/blake2b256/Blake2b256_64Kb.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/blake2b256/Blake2b256_64Kb.scala @@ -7,7 +7,6 @@ import testHelpers.TestDataConstantsAndMethods.{GreaterV3ResultBinaryEntry, actu import utest.{Tests, test} object Blake2b256_64Kb extends JsTestBase { - // blake2b256_64Kb private val blake2b256_64Kb = "blake2b256_64Kb(callerTestData)" private val blake2b256_64KbArgBeforeFunc = "callerTestData.blake2b256_64Kb()" private val invalidBlake2b256_64Kb = "blake2b256_64Kb()" @@ -15,7 +14,7 @@ object Blake2b256_64Kb extends JsTestBase { private val invalidErrorBlake2b256_64Kb = testData.invalidFunctionError("blake2b256_64Kb", 1) val tests: Tests = Tests { - test("blake2b256_64Kb functions compiles with a ByteVector") { + test("RIDE-128. Function blake2b256_64Kb should compile for valid ByteVector") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -30,7 +29,7 @@ object Blake2b256_64Kb extends JsTestBase { } } - test("compilation errors blake2b256_64Kb") { + test("RIDE-128. Function blake2b256_64Kb должна выдавать ошибку при невалидных данных") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/keccak256/Keccak256.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/keccak256/Keccak256.scala index db6baaf54b3..18d8efdf7b3 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/keccak256/Keccak256.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/keccak256/Keccak256.scala @@ -7,7 +7,6 @@ import testHelpers.TestDataConstantsAndMethods.{GreaterV3ResultBinaryEntry, actu import utest.{Tests, test} object Keccak256 extends JsTestBase { - // keccak256 private val keccak256 = "keccak256(callerTestData)" private val keccak256ArgBeforeFunc = "callerTestData.keccak256()" private val invalidKeccak256 = "keccak256()" @@ -15,7 +14,7 @@ object Keccak256 extends JsTestBase { private val invalidErrorKeccak256 = testData.invalidFunctionError("keccak256", 1) val tests: Tests = Tests { - test("blake2b256 functions compiles with a ByteVector") { + test("RIDE-132. Function Keccak256 should compile for valid ByteVector") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -30,7 +29,7 @@ object Keccak256 extends JsTestBase { } } - test("compilation errors keccak256") { + test("RIDE-133. Function blake2b256 should throw an error for invalid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/keccak256/Keccak256_128Kb.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/keccak256/Keccak256_128Kb.scala index 7d69cd3719c..5973ed09331 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/keccak256/Keccak256_128Kb.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/keccak256/Keccak256_128Kb.scala @@ -7,7 +7,6 @@ import testHelpers.TestDataConstantsAndMethods.{GreaterV3ResultBinaryEntry, actu import utest.{Tests, test} object Keccak256_128Kb extends JsTestBase { - // keccak256_128Kb private val keccak256_128Kb = "keccak256_128Kb(callerTestData)" private val keccak256_128KbArgBeforeFunc = "callerTestData.keccak256_128Kb()" private val invalidKeccak256_128Kb = "keccak256_128Kb()" @@ -15,7 +14,7 @@ object Keccak256_128Kb extends JsTestBase { private val invalidErrorKeccak256_128Kb = testData.invalidFunctionError("keccak256_128Kb", 1) val tests: Tests = Tests { - test("keccak256_128Kb functions compiles with a ByteVector") { + test("RIDE-140. Function keccak256_128Kb should compile for valid ByteVector") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -30,7 +29,7 @@ object Keccak256_128Kb extends JsTestBase { } } - test("compilation errors keccak256_128Kb") { + test("RIDE-141. Function keccak256_128Kb should throw an error for invalid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/keccak256/Keccak256_16Kb.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/keccak256/Keccak256_16Kb.scala index 5562117f0c2..4a48caa8275 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/keccak256/Keccak256_16Kb.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/keccak256/Keccak256_16Kb.scala @@ -7,7 +7,6 @@ import testHelpers.TestDataConstantsAndMethods.{GreaterV3ResultBinaryEntry, actu import utest.{Tests, test} object Keccak256_16Kb extends JsTestBase { - // keccak256_16Kb private val keccak256_16Kb = "keccak256_16Kb(callerTestData)" private val keccak256_16KbArgBeforeFunc = "callerTestData.keccak256_16Kb()" private val invalidKeccak256_16Kb = "keccak256_16Kb()" @@ -15,7 +14,7 @@ object Keccak256_16Kb extends JsTestBase { private val invalidErrorKeccak256_16Kb = testData.invalidFunctionError("keccak256_16Kb", 1) val tests: Tests = Tests { - test("keccak256_16Kb functions compiles with a ByteVector") { + test("RIDE-134. Function keccak256_16Kb should compile for valid ByteVector") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -30,7 +29,7 @@ object Keccak256_16Kb extends JsTestBase { } } - test("compilation errors keccak256_16Kb") { + test("RIDE-135. Function keccak256_16Kb should throw an error for invalid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/keccak256/Keccak256_32Kb.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/keccak256/Keccak256_32Kb.scala index 16bb24e9ffd..d99d9a288e8 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/keccak256/Keccak256_32Kb.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/keccak256/Keccak256_32Kb.scala @@ -7,7 +7,6 @@ import testHelpers.TestDataConstantsAndMethods.{GreaterV3ResultBinaryEntry, actu import utest.{Tests, test} object Keccak256_32Kb extends JsTestBase { - // keccak256_32Kb private val keccak256_32Kb = "keccak256_32Kb(callerTestData)" private val keccak256_32KbArgBeforeFunc = "callerTestData.keccak256_32Kb()" private val invalidKeccak256_32Kb = "keccak256_32Kb()" @@ -15,7 +14,7 @@ object Keccak256_32Kb extends JsTestBase { private val invalidErrorKeccak256_32Kb = testData.invalidFunctionError("keccak256_32Kb", 1) val tests: Tests = Tests { - test("keccak256_32Kb functions compiles with a ByteVector") { + test("RIDE-136. Function keccak256_32Kb should compile for valid ByteVector") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -30,7 +29,7 @@ object Keccak256_32Kb extends JsTestBase { } } - test("compilation errors keccak256_32Kb") { + test("RIDE-137. Function keccak256_32Kb should throw an error for invalid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/keccak256/Keccak256_64Kb.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/keccak256/Keccak256_64Kb.scala index dd9923d1cfb..312dd572b79 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/keccak256/Keccak256_64Kb.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/keccak256/Keccak256_64Kb.scala @@ -7,7 +7,6 @@ import testHelpers.TestDataConstantsAndMethods.{GreaterV3ResultBinaryEntry, actu import utest.{Tests, test} object Keccak256_64Kb extends JsTestBase { - // keccak256_64Kb private val keccak256_64Kb = "keccak256_64Kb(callerTestData)" private val keccak256_64KbArgBeforeFunc = "callerTestData.keccak256_64Kb()" private val invalidKeccak256_64Kb = "keccak256_64Kb()" @@ -15,7 +14,7 @@ object Keccak256_64Kb extends JsTestBase { private val invalidErrorKeccak256_64Kb = testData.invalidFunctionError("keccak256_64Kb", 1) val tests: Tests = Tests { - test("keccak256_64Kb functions compiles with a ByteVector") { + test("RIDE-138. Function keccak256_64Kb should compile for valid ByteVector") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -30,7 +29,7 @@ object Keccak256_64Kb extends JsTestBase { } } - test("compilation errors keccak256_64Kb") { + test("RIDE-139. Function keccak256_64Kb should throw an error for invalid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/sha256/Sha256.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/sha256/Sha256.scala index 454845da028..03f5de3c385 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/sha256/Sha256.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/sha256/Sha256.scala @@ -7,7 +7,6 @@ import testHelpers.TestDataConstantsAndMethods.{GreaterV3ResultBinaryEntry, actu import utest.{Tests, test} object Sha256 extends JsTestBase { - // sha256 private val sha256 = "sha256(callerTestData)" private val sha256ArgBeforeFunc = "callerTestData.sha256()" private val invalidSha256 = "sha256()" @@ -15,7 +14,7 @@ object Sha256 extends JsTestBase { private val invalidErrorSha256 = testData.invalidFunctionError("sha256", 1) val tests: Tests = Tests { - test("blake2b256 functions compiles with a ByteVector") { + test("RIDE-142. Function sha256 should compile for valid ByteVector") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -30,7 +29,7 @@ object Sha256 extends JsTestBase { } } - test("compilation errors sha256") { + test("RIDE-143. Function sha256 should throw an error for invalid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/sha256/Sha256_128Kb.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/sha256/Sha256_128Kb.scala index cafd6606203..7b3c79d2006 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/sha256/Sha256_128Kb.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/sha256/Sha256_128Kb.scala @@ -7,7 +7,6 @@ import testHelpers.TestDataConstantsAndMethods.{GreaterV3ResultBinaryEntry, actu import utest.{Tests, test} object Sha256_128Kb extends JsTestBase { - // sha256_128Kb private val sha256_128Kb = "sha256_128Kb(callerTestData)" private val sha256_128KbArgBeforeFunc = "callerTestData.sha256_128Kb()" private val invalidSha256_128Kb = "sha256_128Kb()" @@ -15,7 +14,7 @@ object Sha256_128Kb extends JsTestBase { private val invalidErrorSha256_128Kb = testData.invalidFunctionError("sha256_128Kb", 1) val tests: Tests = Tests { - test("sha256_128Kb functions compiles with a ByteVector") { + test("RIDE-150. Function sha256_128Kb should compile for valid ByteVector") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -30,7 +29,7 @@ object Sha256_128Kb extends JsTestBase { } } - test("compilation errors sha256_128Kb") { + test("RIDE-151. Function sha256_128Kb should throw an error for invalid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/sha256/Sha256_16Kb.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/sha256/Sha256_16Kb.scala index baca94e3a1c..79de0d87770 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/sha256/Sha256_16Kb.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/sha256/Sha256_16Kb.scala @@ -7,7 +7,6 @@ import testHelpers.TestDataConstantsAndMethods.{GreaterV3ResultBinaryEntry, actu import utest.{Tests, test} object Sha256_16Kb extends JsTestBase { - // sha256_16Kb private val sha256_16Kb = "sha256_16Kb(callerTestData)" private val sha256_16KbArgBeforeFunc = "callerTestData.sha256_16Kb()" private val invalidSha256_16Kb = "sha256_16Kb()" @@ -15,7 +14,7 @@ object Sha256_16Kb extends JsTestBase { private val invalidErrorSha256_16Kb = testData.invalidFunctionError("sha256_16Kb", 1) val tests: Tests = Tests { - test("sha256_16Kb functions compiles with a ByteVector") { + test("RIDE-144. Function sha256_16Kb should compile for valid ByteVector") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -30,7 +29,7 @@ object Sha256_16Kb extends JsTestBase { } } - test("compilation errors sha256_16Kb") { + test("RIDE-145. Function sha256_16Kb should throw an error for invalid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/sha256/Sha256_32Kb.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/sha256/Sha256_32Kb.scala index 005f6d7793c..279007f292a 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/sha256/Sha256_32Kb.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/sha256/Sha256_32Kb.scala @@ -7,7 +7,6 @@ import testHelpers.TestDataConstantsAndMethods.{GreaterV3ResultBinaryEntry, actu import utest.{Tests, test} object Sha256_32Kb extends JsTestBase { - // sha256_32Kb private val sha256_32Kb = "sha256_32Kb(callerTestData)" private val sha256_32KbArgBeforeFunc = "callerTestData.sha256_32Kb()" private val invalidSha256_32Kb = "sha256_32Kb()" @@ -15,7 +14,7 @@ object Sha256_32Kb extends JsTestBase { private val invalidErrorSha256_32Kb = testData.invalidFunctionError("sha256_32Kb", 1) val tests: Tests = Tests { - test("sha256_32Kb functions compiles with a ByteVector") { + test("RIDE-146. Function sha256_32Kb should compile for valid ByteVector") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -30,7 +29,7 @@ object Sha256_32Kb extends JsTestBase { } } - test("compilation errors sha256_32Kb") { + test("RIDE-147. Function sha256_32Kb should throw an error for invalid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/sha256/Sha256_64Kb.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/sha256/Sha256_64Kb.scala index d0bc5dc1aae..d27ec125666 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/sha256/Sha256_64Kb.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/hashing/sha256/Sha256_64Kb.scala @@ -7,7 +7,6 @@ import testHelpers.TestDataConstantsAndMethods.{GreaterV3ResultBinaryEntry, actu import utest.{Tests, test} object Sha256_64Kb extends JsTestBase { - // sha256_64Kb private val sha256_64Kb = "sha256_64Kb(callerTestData)" private val sha256_64KbArgBeforeFunc = "callerTestData.sha256_64Kb()" private val invalidSha256_64Kb = "sha256_64Kb()" @@ -15,7 +14,7 @@ object Sha256_64Kb extends JsTestBase { private val invalidErrorSha256_64Kb = testData.invalidFunctionError("sha256_64Kb", 1) val tests: Tests = Tests { - test("sha256_64Kb functions compiles with a ByteVector") { + test("RIDE-148. Function sha256_64Kb should compile for valid ByteVector") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -30,7 +29,7 @@ object Sha256_64Kb extends JsTestBase { } } - test("compilation errors sha256_64Kb") { + test("RIDE-149. Function sha256_64Kb should throw an error for invalid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/Cons.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/Cons.scala index 968e5397d62..4876b912127 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/Cons.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/Cons.scala @@ -14,7 +14,7 @@ object Cons extends JsTestBase { private val invalidErrorCons = invalidFunctionError("cons", 2) val tests: Tests = Tests { - test("Cons functions compiles with a list") { + test("RIDE-152. Function Cons should compile for valid list") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -31,7 +31,7 @@ object Cons extends JsTestBase { } } - test("Compilation errors Cons functions") { + test("RIDE-153. Function Cons should throw an error for invalid data or type") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/ContainsElement.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/ContainsElement.scala index 696b24c3826..71179420236 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/ContainsElement.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/ContainsElement.scala @@ -7,7 +7,6 @@ import testHelpers.TestDataConstantsAndMethods.{actualVersionsWithoutV3, intList import utest.{Tests, test} object ContainsElement extends JsTestBase { - // containsElement private val containsElement = "containsElement(bar, foo)" private val containsElementArgBeforeFunc = "bar.containsElement(foo)" private val invalidContainsElement = "containsElement(foo)" @@ -15,7 +14,7 @@ object ContainsElement extends JsTestBase { private val invalidErrorContainsElement = testData.invalidFunctionError("containsElement", 2) val tests: Tests = Tests { - test("ContainsElement functions compiles with a list") { + test("RIDE-154. Function ContainsElement should compile for valid list") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -32,7 +31,7 @@ object ContainsElement extends JsTestBase { } } - test("Compilation errors Cons functions") { + test("RIDE-155. Function ContainsElement should throw an error for invalid data or type") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/GetElement.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/GetElement.scala index cd2c38d0f4a..05443e10b0c 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/GetElement.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/GetElement.scala @@ -14,7 +14,7 @@ object GetElement extends JsTestBase { private val invalidErrorGetElement = testData.invalidFunctionError("getElement", 2) val tests: Tests = Tests { - test("GetElement functions compiles with a list") { + test("RIDE-156. Function GetElement should compile for valid list") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -31,7 +31,7 @@ object GetElement extends JsTestBase { } } - test("Compilation errors GetElement functions") { + test("RIDE-157. Function GetElement should throw an error for invalid data or type") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/IndexOf.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/IndexOf.scala index d8ce7521e54..4029a039de3 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/IndexOf.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/IndexOf.scala @@ -13,7 +13,7 @@ object IndexOf extends JsTestBase { private val invalidIndexOfArgBeforeFunc = "bar.indexOf(bar, foo)" val tests: Tests = Tests { - test("IndexOf functions compiles with a list") { + test("RIDE-158. Function IndexOf should compile for valid list") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -30,7 +30,7 @@ object IndexOf extends JsTestBase { } } - test("Compilation errors IndexOf functions") { + test("RIDE-159. Function IndexOf should throw an error for invalid data or type") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/LastIndexOf.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/LastIndexOf.scala index 821acb3ef40..ed0a6bc1296 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/LastIndexOf.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/LastIndexOf.scala @@ -13,7 +13,7 @@ object LastIndexOf extends JsTestBase { private val invalidLastIndexOfArgBeforeFunc = "bar.indexOf(bar, foo)" val tests: Tests = Tests { - test("LastIndexOf functions compiles with a list") { + test("RIDE-160. Function LastIndexOf should compile for valid list") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -30,7 +30,7 @@ object LastIndexOf extends JsTestBase { } } - test("Compilation errors LastIndexOf functions") { + test("RIDE-161. Function IndexOf should throw an error for invalid data or type") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/Max.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/Max.scala index 9323c647c13..8aafca83452 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/Max.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/Max.scala @@ -17,7 +17,7 @@ object Max extends JsTestBase { private val invalidMaxForBigInt = "[callerTestData].max([callerTestData], [callerTestData])" val tests: Tests = Tests { - test("Max functions compiles with a list") { + test("RIDE-162. Function Max should compile with a list") { for (version <- actualVersionsWithoutV3) { for ( (data, function, dataType) <- Seq( @@ -32,7 +32,7 @@ object Max extends JsTestBase { } } - test("Max for BigInt functions compiles with a address data type") { + test("RIDE-163. Function Max should compile with a BigInt") { for (version <- versionsSupportingTheNewFeatures) { for ( (data, function, dataType) <- Seq( @@ -47,7 +47,7 @@ object Max extends JsTestBase { } } - test("Compilation error for max") { + test("RIDE-164. Function Max should throw an error for invalid data or type") { for (version <- actualVersionsWithoutV3) { for ( (data, function, dataType, error) <- Seq( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/Min.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/Min.scala index 0f4f1a042c4..8ee68499812 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/Min.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/Min.scala @@ -24,7 +24,7 @@ object Min extends JsTestBase { private val invalidMinForBigInt = "[callerTestData].min([callerTestData], [callerTestData])" val tests: Tests = Tests { - test("Min functions compiles with a list") { + test("RIDE-165. Function Min should compile with a list") { for (version <- actualVersionsWithoutV3) { for ( (data, function, dataType) <- Seq( @@ -39,7 +39,7 @@ object Min extends JsTestBase { } } - test("Min for BigInt functions compiles with a address data type") { + test("RIDE-166. Function Min should compile with a BigInt") { for (version <- versionsSupportingTheNewFeatures) { for ( (data, function, dataType) <- Seq( @@ -54,7 +54,7 @@ object Min extends JsTestBase { } } - test("Compilation error for min") { + test("RIDE-167. Function Min should throw an error for invalid data or type") { for (version <- actualVersionsWithoutV3) { for ( (data, function, dataType, error) <- Seq( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/RemoveByIndex.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/RemoveByIndex.scala index c31be75bf4a..f6239f74a5a 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/RemoveByIndex.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/RemoveByIndex.scala @@ -14,7 +14,7 @@ object RemoveByIndex extends JsTestBase { private val invalidErrorRemoveByIndex = testData.invalidFunctionError("removeByIndex", 2) val tests: Tests = Tests { - test("removeByIndex functions compiles with a list") { + test("RIDE-168. Function RemoveByIndex should compile for valid list") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -29,7 +29,7 @@ object RemoveByIndex extends JsTestBase { } } - test("Compilation errors RemoveByIndex functions") { + test("RIDE-169. Function RemoveByIndex should throw an error for invalid data or type") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/Size.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/Size.scala index 5f56fde610b..a2b3d0952f7 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/Size.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/list/Size.scala @@ -13,7 +13,7 @@ object Size extends JsTestBase { private val invalidSizeArgBeforeFunc = "callerTestData.size(callerTestData)" val tests: Tests = Tests { - test("size functions compiles with a list") { + test("RIDE-170. Function Size should compile for valid list") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) for ( @@ -28,7 +28,7 @@ object Size extends JsTestBase { } } - test("Compilation errors RemoveByIndex functions") { + test("RIDE-171. Function Size should throw an error for invalid data or type") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/math/Fraction.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/math/Fraction.scala index aa3aab63475..41ef536076d 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/math/Fraction.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/math/Fraction.scala @@ -32,7 +32,7 @@ object Fraction extends JsTestBase { private val fractionError: String = testData.invalidFunctionError("fraction", 3) val tests: Tests = Tests { - test("Fraction functions compiles with Int") { + test("RIDE-172. Fraction should compile with the Int type") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) for ( @@ -47,7 +47,7 @@ object Fraction extends JsTestBase { } } - test("Fraction functions compiles with Int and union") { + test("RIDE-173. Fraction should compile with the Int and Union types - Ride V5, V6") { for (version <- versionsSupportingTheNewFeatures) { for ( (data, function, dataType) <- Seq( @@ -66,7 +66,7 @@ object Fraction extends JsTestBase { } } - test("Compilation error for Fraction with Int") { + test("RIDE-174. Fraction should throw an error for invalid data") { for (version <- actualVersions) { for ( (data, function, dataType, error) <- Seq( @@ -87,7 +87,7 @@ object Fraction extends JsTestBase { } } - test("compilation error: invalid fraction data BigInt") { + test("RIDE-175. Fraction should raise a compilation error for BigInt - Ride V5, V6") { for (version <- versionsSupportingTheNewFeatures) { for ( (data, function, dataType, error) <- Seq( @@ -106,7 +106,7 @@ object Fraction extends JsTestBase { } } - test("compilation error: Function 'fraction' requires 3 arguments, but 4 are provided for V3, V4") { + test("RIDE-176. Fraction should raise an error for versions V3 and V4 with incorrect argument count") { for (version <- testData.oldVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) val script = precondition.onlyMatcherContract(randomInt.toString, fractionIntAndUnion) diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/math/Log.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/math/Log.scala index d717c23b540..5f7e94d8b19 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/math/Log.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/math/Log.scala @@ -19,13 +19,12 @@ object Log extends JsTestBase { private val logIntArgBeforeFunc = s"callerTestData.log($randomInt, $randomInt, 4, 2, $union)" private val logBigInt = s"log(callerTestData, 6, callerTestData, $randomInt, 2, $union)" private val logBigIntArgBeforeFunc = s"callerTestData.log(6, callerTestData, $randomInt, 2, $union)" - private val invalidLogInt = s"log(callerTestData, 10, $union)" private val invalidLogIntArgBeforeFunc = s"callerTestData.log(10, $union)" private val logError: String = testData.invalidFunctionError("log", 6) val tests: Tests = Tests { - test("Log function compiles with Int") { + test("RIDE-177. Log function should compile with Int") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) for ( @@ -40,7 +39,7 @@ object Log extends JsTestBase { } } - test("Log function compiles with BigInt") { + test("RIDE-178. Log function should compile with BigInt for Ride V5, V6") { for (version <- testData.versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("BigInt", version) for ( @@ -55,7 +54,7 @@ object Log extends JsTestBase { } } - test("compilation error: invalid log function") { + test("RIDE-179. Log function should throw an error for invalid data") { for (version <- testData.actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) for ( @@ -76,7 +75,7 @@ object Log extends JsTestBase { } } - test("compilation error: invalid log data BigInt") { + test("RIDE-180. Log function should throw an error for invalid data BigInt - Ride V5, V6") { for (version <- testData.versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("BigInt", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/math/Median.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/math/Median.scala index 7152639095f..0b5b96b637b 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/math/Median.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/math/Median.scala @@ -16,7 +16,7 @@ object Median extends JsTestBase { private val medianError: String = testData.invalidFunctionError("median", 1) val tests: Tests = Tests { - test("Median functions compiles with Int") { + test("RIDE-181. Median functions should compile with Int") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) for ( @@ -31,7 +31,7 @@ object Median extends JsTestBase { } } - test("Median functions compiles with BigInt") { + test("RIDE-182. Median functions should compile with BigInt for Ride V5, V6") { for (version <- versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("BigInt", version) for ( @@ -46,7 +46,7 @@ object Median extends JsTestBase { } } - test("invalid median functions with Int") { + test("RIDE-183. Median functions should throw an error for invalid Int data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) for ( @@ -66,7 +66,7 @@ object Median extends JsTestBase { } } - test("invalid median with BigInt") { + test("RIDE-184. Median function should throw an error for invalid BigInt data - Ride V5, V6") { for (version <- versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("BigInt", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/math/Pow.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/math/Pow.scala index 43e2c9de3b7..1077d111eea 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/math/Pow.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/math/Pow.scala @@ -28,7 +28,7 @@ object Pow extends JsTestBase { private val powError: String = testData.invalidFunctionError("pow", 6) val tests: Tests = Tests { - test("Pow functions compiles with Int") { + test("RIDE-185. Pow functions should compile with Int") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) for ( @@ -43,7 +43,7 @@ object Pow extends JsTestBase { } } - test("Pow functions compiles with BigInt") { + test("RIDE-186. Pow functions should compile with BigInt for Ride V5, V6") { for (version <- versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("BigInt", version) for ( @@ -58,7 +58,7 @@ object Pow extends JsTestBase { } } - test("Invalid data for pow functions with Int") { + test("RIDE-187. Median functions should throw an error for invalid Int data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) for ( @@ -78,7 +78,7 @@ object Pow extends JsTestBase { } } - test("Invalid data for pow functions with BigInt") { + test("RIDE-188. Median function should throw an error for invalid BigInt data - Ride V5, V6") { for (version <- testData.versionsSupportingTheNewFeatures) { val precondition = new GeneratorContractsForBuiltInFunctions("BigInt", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/math/Sqrt.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/math/Sqrt.scala index a647e92552d..2859884f800 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/math/Sqrt.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/math/Sqrt.scala @@ -14,7 +14,7 @@ object Sqrt extends JsTestBase { private val invalidSqrtFunction = s"sqrt(callerTestData)" val tests: Tests = Tests { - test("Sqrt functions compiles with Int and BigInt") { + test("RIDE-189. Sqrt functions compile with Int and BigInt") { for ( (data, function, dataType) <- Seq( (randomInt.toString, sqrtIntAndUnion, "Int"), @@ -29,7 +29,7 @@ object Sqrt extends JsTestBase { } } - test("Sqrt functions compilation errors with Int and BigInt") { + test("RIDE-190. Sqrt functions should throw an error for invalid Int data") { for ( (data, function, dataType) <- Seq( (randomStringArrayElement, sqrtIntAndUnion, "Int"), @@ -44,7 +44,7 @@ object Sqrt extends JsTestBase { } } - test("Can't find a function Sqrt for V3 - V5") { + test("RIDE-191. Can't find a function Sqrt for V3 - V5") { for (version <- testData.versionsWithoutV6) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/Contains.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/Contains.scala index 5967ff578c0..33b6222f789 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/Contains.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/Contains.scala @@ -15,7 +15,7 @@ object Contains extends JsTestBase { private val invalidErrorContains = testData.invalidFunctionError("contains", 2) val tests: Tests = Tests { - test("contains functions compiles") { + test("RIDE-208. function contains should compile for valid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("String", version) for ( @@ -30,7 +30,7 @@ object Contains extends JsTestBase { } } - test("compilation error contains functions") { + test("RIDE-209. function contains throw a compilation error for invalid data") { for (version <- testData.actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("String", version) for ( @@ -48,7 +48,7 @@ object Contains extends JsTestBase { } } - test("compilation error: Can't find a function for V3") { + test("RIDE-210. Can't find a function contains for RIDE V3") { val precondition = new GeneratorContractsForBuiltInFunctions("String", V3) val script = precondition.simpleRideCode(randomStringArrayElement, randomStringArrayElement, contains) assertCompileErrorDApp(script, V3, testData.CANT_FIND_FUNCTION) diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/Drop.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/Drop.scala index 94177993ac6..f40e5c6671b 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/Drop.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/Drop.scala @@ -13,7 +13,7 @@ object Drop extends JsTestBase { private val invalidDropArgBeforeFunc = s"callerTestData.drop(callerTestData, $randomInt)" val tests: Tests = Tests { - test("Compiles drop functions") { + test("RIDE-211. function drop should compile for valid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -28,7 +28,7 @@ object Drop extends JsTestBase { } } - test("invalid drop functions") { + test("RIDE-212. function drop throw a compilation error for invalid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/DropRight.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/DropRight.scala index f4b791f5972..7e47ad779ea 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/DropRight.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/DropRight.scala @@ -13,7 +13,7 @@ object DropRight extends JsTestBase { private val invalidDropRightArgBeforeFunc = s"callerTestData.dropRight(callerTestData, $randomInt)" val tests: Tests = Tests { - test("Compiles dropRight functions") { + test("RIDE-213. function dropRight should compile for valid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -28,7 +28,7 @@ object DropRight extends JsTestBase { } } - test("invalid dropRight functions") { + test("RIDE-214. function dropRight throw a compilation error for invalid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/IndexOf.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/IndexOf.scala index 8abc0834401..c445e104be8 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/IndexOf.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/IndexOf.scala @@ -14,7 +14,7 @@ object IndexOf extends JsTestBase { private val invalidIndexOf = "indexOf()" val tests: Tests = Tests { - test("check: indexOf function compiles") { + test("RIDE-215. function indexOf should compile for valid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -31,7 +31,7 @@ object IndexOf extends JsTestBase { } } - test("compilation error: indexOf - Non-matching types - Can't find a function overload") { + test("RIDE-216. function indexOf - Non-matching types - Can't find a function overload") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/LastIndexOf.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/LastIndexOf.scala index a73f0dc4169..122b061d3c4 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/LastIndexOf.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/LastIndexOf.scala @@ -14,7 +14,7 @@ object LastIndexOf extends JsTestBase { private val invalidLastIndexOf = "lastIndexOf()" val tests: Tests = Tests { - test("check: lastIndexOf function compiles") { + test("RIDE-217. function lastIndexOf should compile for valid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -31,7 +31,7 @@ object LastIndexOf extends JsTestBase { } } - test("compilation error: lastIndexOf - Non-matching types - Can't find a function overload") { + test("RIDE-218. function lastIndexOf - Non-matching types - Can't find a function overload") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -49,5 +49,4 @@ object LastIndexOf extends JsTestBase { } } } - } diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/Size.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/Size.scala index af4b4ed8d3e..c1fbb6a4546 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/Size.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/Size.scala @@ -13,7 +13,7 @@ object Size extends JsTestBase { private val invalidSizeArgBeforeFunc = s"callerTestData.size(callerTestData, callerTestData)" val tests: Tests = Tests { - test("Size functions compiles") { + test("RIDE-219. function size should compile for valid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -29,7 +29,7 @@ object Size extends JsTestBase { } } - test("invalid size functions") { + test("RIDE-220. function size throw a compilation error for invalid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/Take.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/Take.scala index c5108c28ece..cadc4a0eaf3 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/Take.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/Take.scala @@ -13,7 +13,7 @@ object Take extends JsTestBase { private val invalidTakeArgBeforeFunc = s"callerTestData.take(callerTestData, $randomInt)" val tests: Tests = Tests { - test("Take functions compiles") { + test("RIDE-221. function take should compile for valid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -28,7 +28,7 @@ object Take extends JsTestBase { } } - test("invalid take functions") { + test("RIDE-222. function take throw a compilation error for invalid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/TakeRight.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/TakeRight.scala index 20c0d858272..775f4379efa 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/TakeRight.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/TakeRight.scala @@ -13,7 +13,7 @@ object TakeRight extends JsTestBase { private val invalidTakeRightArgBeforeFunc = s"callerTestData.takeRight(callerTestData, $randomInt)" val tests: Tests = Tests { - test("Take functions compiles") { + test("RIDE-223. function takeRight should compile for valid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -29,7 +29,7 @@ object TakeRight extends JsTestBase { } } - test("invalid takeRight functions") { + test("RIDE-224. function takeRight throw a compilation error for invalid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/makeStringFunctions/MakeString.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/makeStringFunctions/MakeString.scala index c9bd263230d..92839d0043b 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/makeStringFunctions/MakeString.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/makeStringFunctions/MakeString.scala @@ -14,7 +14,7 @@ object MakeString extends JsTestBase { private val invalidErrorMakeString = invalidFunctionError("makeString", 2) val tests: Tests = Tests { - test("makeString functions compiles") { + test("RIDE-192. makeString function should compile for valid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("String", version) for ( @@ -29,7 +29,7 @@ object MakeString extends JsTestBase { } } - test("compilation error makeString functions") { + test("RIDE-193. makeString function should throw a compilation error for invalid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/makeStringFunctions/MakeString_11C.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/makeStringFunctions/MakeString_11C.scala index 6514ce6226f..83bf262c2f6 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/makeStringFunctions/MakeString_11C.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/makeStringFunctions/MakeString_11C.scala @@ -14,7 +14,7 @@ object MakeString_11C extends JsTestBase { private val invalidErrorMakeString_11C = testData.invalidFunctionError("makeString_11C", 2) val tests: Tests = Tests { - test("MakeString_11C functions compiles") { + test("RIDE-197. makeString_11C function should compile for valid data") { val precondition = new GeneratorContractsForBuiltInFunctions("String", V6) for ( (data, list, function) <- Seq( @@ -27,7 +27,7 @@ object MakeString_11C extends JsTestBase { } } - test("Invalid MakeString_11C functions") { + test("RIDE-198. makeString_11C function should throw a compilation error for invalid data") { val precondition = new GeneratorContractsForBuiltInFunctions("String", V6) for ( (data, list, function, error) <- Seq( @@ -41,7 +41,7 @@ object MakeString_11C extends JsTestBase { } } - test("Can't find a function MakeString_11C with versions V3 - V5") { + test("RIDE-199. Can't find a function makeString_11C for RIDE versions V3 - V5") { for (version <- testData.versionsWithoutV6) { val precondition = new GeneratorContractsForBuiltInFunctions("String", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/makeStringFunctions/MakeString_2C.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/makeStringFunctions/MakeString_2C.scala index 0b2e039b938..bdd9bd5f923 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/makeStringFunctions/MakeString_2C.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/makeStringFunctions/MakeString_2C.scala @@ -14,7 +14,7 @@ object MakeString_2C extends JsTestBase { private val invalidErrorMakeString_2C = testData.invalidFunctionError("makeString_2C", 2) val tests: Tests = Tests { - test("MakeString_2C functions compiles") { + test("RIDE-194. makeString_2C function should compile for valid data") { val precondition = new GeneratorContractsForBuiltInFunctions("String", V6) for ( (data, list, function) <- Seq( @@ -27,7 +27,7 @@ object MakeString_2C extends JsTestBase { } } - test("Invalid MakeString_2C functions") { + test("RIDE-195. makeString_2C function should throw a compilation error for invalid data") { val precondition = new GeneratorContractsForBuiltInFunctions("String", V6) for ( (data, list, function, error) <- Seq( @@ -41,7 +41,7 @@ object MakeString_2C extends JsTestBase { } } - test("Can't find a function MakeString_2C with versions V3 - V5") { + test("RIDE-196. Can't find a function makeString_2C for RIDE versions V3 - V5") { for (version <- testData.versionsWithoutV6) { val precondition = new GeneratorContractsForBuiltInFunctions("String", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/splitFunctions/Split.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/splitFunctions/Split.scala index be5ad5d0ee8..ea89141ea13 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/splitFunctions/Split.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/splitFunctions/Split.scala @@ -14,7 +14,7 @@ object Split extends JsTestBase { private val invalidErrorSplit = testData.invalidFunctionError("split", 2) val tests: Tests = Tests { - test("split functions compiles") { + test("RIDE-200. split function should compile for valid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("String", version) for ( @@ -29,7 +29,7 @@ object Split extends JsTestBase { } } - test("Compilation error for split functions") { + test("RIDE-201. split function should throw a compilation error for invalid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/splitFunctions/Split_4C.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/splitFunctions/Split_4C.scala index 723e869faf9..18d46e5fedb 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/splitFunctions/Split_4C.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/splitFunctions/Split_4C.scala @@ -14,7 +14,7 @@ object Split_4C extends JsTestBase { private val invalidErrorSplit_4C = testData.invalidFunctionError("split_4C", 2) val tests: Tests = Tests { - test("split_4C functions compiles") { + test("RIDE-202. split_4C function should compile for valid data") { val precondition = new GeneratorContractsForBuiltInFunctions("String", V6) for ( (data, list, function) <- Seq( @@ -27,7 +27,7 @@ object Split_4C extends JsTestBase { } } - test("compilation error split_4C functions") { + test("RIDE-203. split_4C function should throw a compilation error for invalid data") { val precondition = new GeneratorContractsForBuiltInFunctions("String", V6) for ( (data, list, function, error) <- Seq( @@ -41,7 +41,7 @@ object Split_4C extends JsTestBase { } } - test("Can't find a function split_4C with versions V3 - V5") { + test("RIDE-204. Can't find a function split_4C for RIDE versions V3 - V5") { for (version <- testData.versionsWithoutV6) { val precondition = new GeneratorContractsForBuiltInFunctions("String", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/splitFunctions/Split_51C.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/splitFunctions/Split_51C.scala index f5d06beccdc..bf98dd1123a 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/splitFunctions/Split_51C.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/string/splitFunctions/Split_51C.scala @@ -14,7 +14,7 @@ object Split_51C extends JsTestBase { private val invalidErrorSplit_51C = testData.invalidFunctionError("split_51C", 2) val tests: Tests = Tests { - test("split_51C functions compiles") { + test("RIDE-205. split_51C function should compile for valid data") { val precondition = new GeneratorContractsForBuiltInFunctions("String", V6) for ( (data, list, function) <- Seq( @@ -27,7 +27,7 @@ object Split_51C extends JsTestBase { } } - test("compilation error split_51C functions") { + test("RIDE-206. split_51C function should throw a compilation error for invalid data") { val precondition = new GeneratorContractsForBuiltInFunctions("String", V6) for ( (data, list, function, error) <- Seq( @@ -41,7 +41,7 @@ object Split_51C extends JsTestBase { } } - test("Can't find a function split_51C with versions V3 - V5") { + test("RIDE-207. Can't find a function split_4C for RIDE versions V3 - V5") { for (version <- testData.versionsWithoutV6) { val precondition = new GeneratorContractsForBuiltInFunctions("String", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/union/Extract.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/union/Extract.scala index 42137b4dbd2..1b93d0a8602 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/union/Extract.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/union/Extract.scala @@ -16,7 +16,7 @@ object Extract extends JsTestBase { private val invalidErrorExtract = invalidFunctionError("extract", 1) val tests: Tests = Tests { - test("Extract functions compiles") { + test("RIDE-225. function extract should compile for valid data") { val precondition = new GeneratorContractsForBuiltInFunctions("Int", V3) for ( (data, function) <- Seq( @@ -29,7 +29,7 @@ object Extract extends JsTestBase { } } - test("invalid extract functions") { + test("RIDE-226. function extract throw a compilation error for invalid data") { val precondition = new GeneratorContractsForBuiltInFunctions("Int", V3) for ( (data, function, error) <- Seq( @@ -44,7 +44,7 @@ object Extract extends JsTestBase { } } - test("invalid extract functions for V4 - V6") { + test("RIDE-227. invalid extract functions for RIDE V4 - V6") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/union/IsDefined.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/union/IsDefined.scala index aceded066bc..ffe830d471b 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/union/IsDefined.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/union/IsDefined.scala @@ -2,17 +2,8 @@ package com.wavesplatform.test.builtInFunctions.union import com.wavesplatform.JsTestBase import testHelpers.GeneratorContractsForBuiltInFunctions -import testHelpers.RandomDataGenerator.{ - randomAddressDataArrayElement, - randomAliasDataArrayElement, - randomBoolean, - randomByteVectorArrayElement, - randomDigestAlgorithmTypeArrayElement, - randomInt, - randomStringArrayElement, - randomUnionArrayElement -} -import testHelpers.TestDataConstantsAndMethods.{actualVersions, invalidFunctionError} +import testHelpers.RandomDataGenerator.{randomAddressDataArrayElement, randomAliasDataArrayElement, randomBoolean, randomByteVectorArrayElement, randomDigestAlgorithmTypeArrayElement, randomInt, randomStringArrayElement, randomUnionArrayElement} +import testHelpers.TestDataConstantsAndMethods.{MATCHING_NOT_EXHAUSTIVE, actualVersions, invalidFunctionError} import utest.{Tests, test} object IsDefined extends JsTestBase { @@ -23,7 +14,7 @@ object IsDefined extends JsTestBase { private val invalidErrorIsDefined = invalidFunctionError("isDefined", 1) val tests: Tests = Tests { - test("IsDefined functions compiles") { + test("RIDE-228. function isDefined should compile for valid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -44,11 +35,13 @@ object IsDefined extends JsTestBase { } } - test("Can't find a function overload isDefined") { + test("RIDE-229. function isDefined throw a compilation error for can't find overload") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( (data, function, error) <- Seq( + (randomUnionArrayElement, invalidIsDefined, MATCHING_NOT_EXHAUSTIVE), + (randomAddressDataArrayElement, invalidIsDefinedArgBeforeFunc, MATCHING_NOT_EXHAUSTIVE), (randomInt.toString, invalidIsDefined, invalidErrorIsDefined), (randomInt.toString, invalidIsDefinedArgBeforeFunc, invalidErrorIsDefined) ) diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/union/Value.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/union/Value.scala index 184f42f6b16..32188359a71 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/union/Value.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/union/Value.scala @@ -14,7 +14,7 @@ object Value extends JsTestBase { private val invalidErrorValue = invalidFunctionError("value", 1) val tests: Tests = Tests { - test("Value functions compiles") { + test("RIDE-230. function value should compile for valid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Int", version) for ( @@ -29,7 +29,7 @@ object Value extends JsTestBase { } } - test("Can't find a function overload isDefined") { + test("RIDE-231. function value throw a compilation error for can't find overload") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/union/ValueOrElse.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/union/ValueOrElse.scala index 3076cfd540d..c2ee0a090f3 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/union/ValueOrElse.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/union/ValueOrElse.scala @@ -22,7 +22,7 @@ object ValueOrElse extends JsTestBase { private val invalidErrorValueOrElse = invalidFunctionError("valueOrElse", 2) val tests: Tests = Tests { - test("check: valueOrElse function compiles with String") { + test("RIDE-232. function valueOrElse should compile for valid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -41,7 +41,7 @@ object ValueOrElse extends JsTestBase { } } - test("invalid valueOrElse functions") { + test("RIDE-233. function valueOrElse throw a compilation error for invalid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("", version) for ( @@ -58,7 +58,7 @@ object ValueOrElse extends JsTestBase { } } - test("Can't find a function valueOrElse V3") { + test("RIDE-234. Can't find a function valueOrElse for RIDE V3") { val precondition = new GeneratorContractsForBuiltInFunctions("", V3) for ( (firstData, secondData, function) <- Seq( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/union/ValueOrErrorMessage.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/union/ValueOrErrorMessage.scala index 70b3af7127c..b5abfb1088c 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/union/ValueOrErrorMessage.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/union/ValueOrErrorMessage.scala @@ -22,7 +22,7 @@ object ValueOrErrorMessage extends JsTestBase { private val valueOrErrorInvalidFunctionMessage = testData.invalidFunctionError("valueOrErrorMessage", 2) val tests: Tests = Tests { - test("valueOrElse functions are compiled with different data types") { + test("RIDE-235. valueOrErrorMessage functions are compiled with valid data types.") { for (version <- actualVersions) { for ( (dataType, firstData, function) <- Seq( @@ -41,7 +41,7 @@ object ValueOrErrorMessage extends JsTestBase { } } - test("invalid functions valueOrError") { + test("RIDE-236. valueOrErrorMessage function should throw a compilation error for invalid data.") { for (version <- actualVersions) { for ( (dataType, firstData, function, error) <- Seq( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/Bn256Groth16Verify.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/Bn256Groth16Verify.scala index b8b29dd7161..c0be40ec392 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/Bn256Groth16Verify.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/Bn256Groth16Verify.scala @@ -15,7 +15,7 @@ object Bn256Groth16Verify extends JsTestBase { private val invalidErrorBn256Groth16Verify = testData.invalidFunctionError("bn256Groth16Verify", 3) val tests: Tests = Tests { - test("bn256Groth16Verify functions compiles") { + test("RIDE-265. bn256Groth16Verify function should compile for valid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -30,7 +30,7 @@ object Bn256Groth16Verify extends JsTestBase { } } - test("invalid functions bn256Groth16Verify") { + test("RIDE-266. bn256Groth16Verify function should throw a compilation error for invalid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -47,7 +47,7 @@ object Bn256Groth16Verify extends JsTestBase { } } - test("compilation error: Can't find a function bn256Groth16Verify") { + test("RIDE-267. Can't find a function bn256Groth16Verify") { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", V3) val script = precondition.onlyMatcherContract(randomByteVectorArrayElement, bn256Groth16Verify) assertCompileErrorDApp(script, V3, testData.CANT_FIND_FUNCTION) diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/CheckMerkleProof.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/CheckMerkleProof.scala index 7b1d3ce6479..979ca4f5b1c 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/CheckMerkleProof.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/CheckMerkleProof.scala @@ -16,7 +16,7 @@ object CheckMerkleProof extends JsTestBase { private val invalidErrorCheckMerkleProof = testData.invalidFunctionError("checkMerkleProof", 3) val tests: Tests = Tests { - test("checkMerkleProof functions compiles") { + test("RIDE-268. checkMerkleProof function should compile for valid data") { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", V3) for ( (data, function) <- Seq( @@ -29,7 +29,7 @@ object CheckMerkleProof extends JsTestBase { } } - test("invalid functions checkMerkleProof") { + test("RIDE-269. checkMerkleProof function should throw a compilation error for invalid data") { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", V3) for ( (data, function, error) <- Seq( @@ -44,7 +44,7 @@ object CheckMerkleProof extends JsTestBase { } } - test("check: checkMerkleProof functions compiles") { + test("RIDE-270. Can't find a function checkMerkleProof") { for (version <- testData.actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/CreateMerkleRoot.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/CreateMerkleRoot.scala index 2f9ddcb5dfa..028eaefd6a6 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/CreateMerkleRoot.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/CreateMerkleRoot.scala @@ -15,7 +15,7 @@ object CreateMerkleRoot extends JsTestBase { private val invalidErrorCreateMerkleRoot = invalidFunctionError("createMerkleRoot", 3) val tests: Tests = Tests { - test("createMerkleRoot function compiles") { + test("RIDE-271. createMerkleRoot function should compile for valid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -30,7 +30,7 @@ object CreateMerkleRoot extends JsTestBase { } } - test("compilation error: createMerkleRoot - Non-matching types: expected: ByteVector") { + test("RIDE-272. createMerkleRoot function should throw a compilation error for invalid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -47,7 +47,7 @@ object CreateMerkleRoot extends JsTestBase { } } - test("compilation error: Can't find a function createMerkleRoot") { + test("RIDE-273. Can't find a function createMerkleRoot") { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", V3) val script = precondition.onlyMatcherContract(randomByteVectorArrayElement, createMerkleRoot) assertCompileErrorDApp(script, V3, CANT_FIND_FUNCTION) diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/Ecrecover.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/Ecrecover.scala index 6343f0d97bb..6a1fefd7c79 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/Ecrecover.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/Ecrecover.scala @@ -15,7 +15,7 @@ object Ecrecover extends JsTestBase { private val invalidErrorEcrecover = invalidFunctionError("ecrecover", 2) val tests: Tests = Tests { - test("ecrecover function compiles") { + test("RIDE-274. ecrecover function should compile for valid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -30,7 +30,7 @@ object Ecrecover extends JsTestBase { } } - test("compilation error: ecrecover - Non-matching types: expected: ByteVector") { + test("RIDE-275. ecrecover function should throw a compilation error for invalid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", version) for ( @@ -47,7 +47,7 @@ object Ecrecover extends JsTestBase { } } - test("compilation error: Can't find a function ecrecover") { + test("RIDE-276. Can't find a function ecrecover") { val precondition = new GeneratorContractsForBuiltInFunctions("ByteVector", V3) val script = precondition.onlyMatcherContract(randomByteVectorArrayElement, ecrecover) assertCompileErrorDApp(script, V3, CANT_FIND_FUNCTION) diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/Groth16Verify.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/Groth16Verify.scala index 232dbbd3599..91236b8e4bd 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/Groth16Verify.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/Groth16Verify.scala @@ -15,7 +15,7 @@ object Groth16Verify extends JsTestBase { private val invalidErrorGroth16Verify = invalidFunctionError("groth16Verify", 3) val tests: Tests = Tests { - test("groth16Verify function compiles") { + test("RIDE-277. groth16Verify function should compile for valid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -30,7 +30,7 @@ object Groth16Verify extends JsTestBase { } } - test("compilation error: groth16Verify - Non-matching types: expected: ByteVector") { + test("RIDE-278. groth16Verify function should throw a compilation error for invalid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -47,7 +47,7 @@ object Groth16Verify extends JsTestBase { } } - test("compilation error: Can't find a function groth16Verify") { + test("RIDE-279. Can't find a function groth16Verify") { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", V3) val script = precondition.onlyMatcherContract(randomByteVectorArrayElement, groth16Verify) assertCompileErrorDApp(script, V3, CANT_FIND_FUNCTION) diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/rsaVerify/RsaVerify.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/rsaVerify/RsaVerify.scala index 91b3b122853..0f3bf398b2a 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/rsaVerify/RsaVerify.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/rsaVerify/RsaVerify.scala @@ -19,7 +19,7 @@ object RsaVerify extends JsTestBase { private val invalidErrorRsaVerify = invalidFunctionError("rsaVerify", 4) val tests: Tests = Tests { - test("rsaVerify functions compiles") { + test("RIDE-237. function rsaVerify should compile for valid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -34,7 +34,7 @@ object RsaVerify extends JsTestBase { } } - test("invalid rsaVerify functions") { + test("RIDE-238. function rsaVerify throw a compilation error for invalid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/rsaVerify/RsaVerify_128Kb.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/rsaVerify/RsaVerify_128Kb.scala index de855be2e3e..7e570891524 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/rsaVerify/RsaVerify_128Kb.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/rsaVerify/RsaVerify_128Kb.scala @@ -15,7 +15,7 @@ object RsaVerify_128Kb extends JsTestBase { private val invalidErrorRsaVerify_128Kb = testData.invalidFunctionError("rsaVerify_128Kb", 4) val tests: Tests = Tests { - test("rsaVerify_128Kb functions compiles") { + test("RIDE-248. rsaVerify_128Kb function should compile for valid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -30,7 +30,7 @@ object RsaVerify_128Kb extends JsTestBase { } } - test("invalid functions rsaVerify_128Kb") { + test("RIDE-249. rsaVerify_128Kb function should throw a compilation error for invalid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -47,7 +47,7 @@ object RsaVerify_128Kb extends JsTestBase { } } - test("compilation error: Can't find a function rsaVerify_128Kb for V3") { + test("RIDE-250. Can't find a function rsaVerify_128Kb for RIDE V3") { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", V3) val script = precondition.onlyMatcherContract(randomByteVectorArrayElement, rsaVerify_128Kb) assertCompileErrorDApp(script, V3, CANT_FIND_FUNCTION) diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/rsaVerify/RsaVerify_16Kb.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/rsaVerify/RsaVerify_16Kb.scala index 50920f787f9..4fa1ae3db02 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/rsaVerify/RsaVerify_16Kb.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/rsaVerify/RsaVerify_16Kb.scala @@ -20,7 +20,7 @@ object RsaVerify_16Kb extends JsTestBase { private val invalidErrorRsaVerify_16Kb = testData.invalidFunctionError("rsaVerify_16Kb", 4) val tests: Tests = Tests { - test("rsaVerify_16Kb functions compiles") { + test("RIDE-239. rsaVerify_16Kb function should compile for valid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -35,7 +35,7 @@ object RsaVerify_16Kb extends JsTestBase { } } - test("invalid functions rsaVerify_16Kb") { + test("RIDE-240. rsaVerify_16Kb function should throw a compilation error for invalid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -52,7 +52,7 @@ object RsaVerify_16Kb extends JsTestBase { } } - test("compilation error: Can't find a function rsaVerify_16Kb for V3") { + test("RIDE-241. Can't find a function makeString_2C for RIDE V3") { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", V3) val script = precondition.onlyMatcherContract(randomByteVectorArrayElement, rsaVerify_16Kb) assertCompileErrorDApp(script, V3, CANT_FIND_FUNCTION) diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/rsaVerify/RsaVerify_32Kb.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/rsaVerify/RsaVerify_32Kb.scala index a3cc6d2b35b..bead03df1c1 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/rsaVerify/RsaVerify_32Kb.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/rsaVerify/RsaVerify_32Kb.scala @@ -20,7 +20,7 @@ object RsaVerify_32Kb extends JsTestBase { private val invalidErrorRsaVerify_32Kb = testData.invalidFunctionError("rsaVerify_32Kb", 4) val tests: Tests = Tests { - test("rsaVerify_32Kb functions compiles") { + test("RIDE-242. rsaVerify_32Kb function should compile for valid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -35,7 +35,7 @@ object RsaVerify_32Kb extends JsTestBase { } } - test("invalid functions rsaVerify_32Kb") { + test("RIDE-243. rsaVerify_32Kb function should throw a compilation error for invalid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -52,7 +52,7 @@ object RsaVerify_32Kb extends JsTestBase { } } - test("compilation error: Can't find a function rsaVerify_32Kb for V3") { + test("RIDE-244. Can't find a function rsaVerify_32Kb for RIDE V3") { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", V3) val script = precondition.onlyMatcherContract(randomByteVectorArrayElement, rsaVerify_32Kb) assertCompileErrorDApp(script, V3, CANT_FIND_FUNCTION) diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/rsaVerify/RsaVerify_64Kb.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/rsaVerify/RsaVerify_64Kb.scala index e978dc05f9e..38cb333e73a 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/rsaVerify/RsaVerify_64Kb.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/rsaVerify/RsaVerify_64Kb.scala @@ -15,7 +15,7 @@ object RsaVerify_64Kb extends JsTestBase { private val invalidErrorRsaVerify_64Kb = testData.invalidFunctionError("rsaVerify_64Kb", 4) val tests: Tests = Tests { - test("rsaVerify_64Kb functions compiles") { + test("RIDE-245. rsaVerify_64Kb function should compile for valid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -30,7 +30,7 @@ object RsaVerify_64Kb extends JsTestBase { } } - test("invalid functions rsaVerify_64Kb") { + test("RIDE-246. rsaVerify_64Kb function should throw a compilation error for invalid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -47,7 +47,7 @@ object RsaVerify_64Kb extends JsTestBase { } } - test("compilation error: Can't find a function rsaVerify_64Kb for V3") { + test("RIDE-247. Can't find a function rsaVerify_64Kb for RIDE V3") { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", V3) val script = precondition.onlyMatcherContract(randomByteVectorArrayElement, rsaVerify_64Kb) assertCompileErrorDApp(script, V3, CANT_FIND_FUNCTION) diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/sigVerify/SigVerify.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/sigVerify/SigVerify.scala index 3e48b883744..e9bb733dd09 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/sigVerify/SigVerify.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/sigVerify/SigVerify.scala @@ -14,7 +14,7 @@ object SigVerify extends JsTestBase { private val invalidErrorSigVerify = testData.invalidFunctionError("sigVerify", 3) val tests: Tests = Tests { - test("sigVerify functions compiles") { + test("RIDE-251. function sigVerify should compile for valid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -29,7 +29,7 @@ object SigVerify extends JsTestBase { } } - test("invalid rsaVerify functions") { + test("RIDE-252. function rsaVerify throw a compilation error for invalid data") { for (version <- actualVersions) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/sigVerify/SigVerify_128Kb.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/sigVerify/SigVerify_128Kb.scala index 1eeeafaa4c9..f4630cdc82e 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/sigVerify/SigVerify_128Kb.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/sigVerify/SigVerify_128Kb.scala @@ -15,7 +15,7 @@ object SigVerify_128Kb extends JsTestBase { private val invalidErrorSigVerify_128Kb = testData.invalidFunctionError("sigVerify_128Kb", 3) val tests: Tests = Tests { - test("sigVerify_128Kb functions compiles") { + test("RIDE-262. sigVerify_128Kb function should compile for valid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -30,7 +30,7 @@ object SigVerify_128Kb extends JsTestBase { } } - test("invalid functions sigVerify_128Kb") { + test("RIDE-263. sigVerify_128Kb function should throw a compilation error for invalid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -47,7 +47,7 @@ object SigVerify_128Kb extends JsTestBase { } } - test("compilation error: Can't find a function sigVerify_128Kb for V3") { + test("RIDE-264. Can't find a function sigVerify_128Kb for RIDE V3") { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", V3) val script = precondition.onlyMatcherContract(randomByteVectorArrayElement, sigVerify_128Kb) assertCompileErrorDApp(script, V3, CANT_FIND_FUNCTION) diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/sigVerify/SigVerify_16Kb.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/sigVerify/SigVerify_16Kb.scala index 9a5883499c6..324e0b1fb27 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/sigVerify/SigVerify_16Kb.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/sigVerify/SigVerify_16Kb.scala @@ -15,7 +15,7 @@ object SigVerify_16Kb extends JsTestBase { private val invalidErrorSigVerify_16Kb = testData.invalidFunctionError("sigVerify_16Kb", 3) val tests: Tests = Tests { - test("sigVerify_16Kb functions compiles") { + test("RIDE-253. sigVerify_16Kb function should compile for valid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -30,7 +30,7 @@ object SigVerify_16Kb extends JsTestBase { } } - test("invalid functions sigVerify_16Kb") { + test("RIDE-254. sigVerify_16Kb function should throw a compilation error for invalid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -47,7 +47,7 @@ object SigVerify_16Kb extends JsTestBase { } } - test("compilation error: Can't find a function sigVerify_16Kb for V3") { + test("RIDE-255. Can't find a function sigVerify_16Kb for RIDE V3") { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", V3) val script = precondition.onlyMatcherContract(randomByteVectorArrayElement, sigVerify_16Kb) assertCompileErrorDApp(script, V3, CANT_FIND_FUNCTION) diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/sigVerify/SigVerify_32Kb.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/sigVerify/SigVerify_32Kb.scala index 658ef6bd954..8faf82e8041 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/sigVerify/SigVerify_32Kb.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/sigVerify/SigVerify_32Kb.scala @@ -15,7 +15,7 @@ object SigVerify_32Kb extends JsTestBase { private val invalidErrorSigVerify_32Kb = testData.invalidFunctionError("sigVerify_32Kb", 3) val tests: Tests = Tests { - test("sigVerify_32Kb functions compiles") { + test("RIDE-256. sigVerify_32Kb function should compile for valid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -30,7 +30,7 @@ object SigVerify_32Kb extends JsTestBase { } } - test("invalid functions sigVerify_32Kb") { + test("RIDE-257. sigVerify_32Kb function should throw a compilation error for invalid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -47,7 +47,7 @@ object SigVerify_32Kb extends JsTestBase { } } - test("compilation error: Can't find a function sigVerify_32Kb for V3") { + test("RIDE-258. Can't find a function sigVerify_32Kb for RIDE V3") { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", V3) val script = precondition.onlyMatcherContract(randomByteVectorArrayElement, sigVerify_32Kb) assertCompileErrorDApp(script, V3, CANT_FIND_FUNCTION) diff --git a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/sigVerify/SigVerify_64Kb.scala b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/sigVerify/SigVerify_64Kb.scala index 0d6cac738a7..df1629ec375 100644 --- a/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/sigVerify/SigVerify_64Kb.scala +++ b/lang/tests-js/src/test/scala/com/wavesplatform/test/builtInFunctions/verification/sigVerify/SigVerify_64Kb.scala @@ -15,7 +15,7 @@ object SigVerify_64Kb extends JsTestBase { private val invalidErrorSigVerify_64Kb = testData.invalidFunctionError("sigVerify_64Kb", 3) val tests: Tests = Tests { - test("sigVerify_64Kb functions compiles") { + test("RIDE-259. sigVerify_64Kb function should compile for valid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -30,7 +30,7 @@ object SigVerify_64Kb extends JsTestBase { } } - test("invalid functions sigVerify_64Kb") { + test("RIDE-260. sigVerify_64Kb function should throw a compilation error for invalid data") { for (version <- actualVersionsWithoutV3) { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", version) for ( @@ -47,7 +47,7 @@ object SigVerify_64Kb extends JsTestBase { } } - test("compilation error: Can't find a function sigVerify_64Kb for V3") { + test("RIDE-261. Can't find a function sigVerify_64Kb for RIDE V3") { val precondition = new GeneratorContractsForBuiltInFunctions("Boolean", V3) val script = precondition.onlyMatcherContract(randomByteVectorArrayElement, sigVerify_64Kb) assertCompileErrorDApp(script, V3, CANT_FIND_FUNCTION) diff --git a/lang/tests/src/test/resources/logback-test.xml b/lang/tests/src/test/resources/logback-test.xml new file mode 100644 index 00000000000..b1f394b2e41 --- /dev/null +++ b/lang/tests/src/test/resources/logback-test.xml @@ -0,0 +1,14 @@ + + + + + %date %-5level [%.15thread] %logger{26} - %msg%n + + + + + + + + + diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ContractCompilerCompactorTest.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ContractCompilerCompactorTest.scala index 02d294b4951..65a8b222920 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ContractCompilerCompactorTest.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ContractCompilerCompactorTest.scala @@ -4,22 +4,22 @@ import cats.syntax.semigroup.* import com.wavesplatform.common.utils.EitherExt2 import com.wavesplatform.lang.Global import com.wavesplatform.lang.contract.DApp -import com.wavesplatform.lang.directives.{Directive, DirectiveParser, DirectiveSet} import com.wavesplatform.lang.directives.values.{DApp as DAppType, *} -import com.wavesplatform.lang.script.{Script, ScriptPreprocessor} +import com.wavesplatform.lang.directives.{Directive, DirectiveParser, DirectiveSet} import com.wavesplatform.lang.script.ContractScript.ContractScriptImpl +import com.wavesplatform.lang.script.{Script, ScriptPreprocessor} import com.wavesplatform.lang.v1.FunctionHeader.User -import com.wavesplatform.lang.v1.compiler.Terms.{CONST_LONG, CaseObj} +import com.wavesplatform.lang.v1.compiler.Terms.{CONST_LONG, CaseObj, FUNC} import com.wavesplatform.lang.v1.compiler.Types.{ANY, BIGINT, BOOLEAN, LIST, LONG, PARAMETERIZED, PARAMETERIZEDLIST, STRING, UNION} import com.wavesplatform.lang.v1.compiler.{ContractScriptCompactor, TestCompiler} import com.wavesplatform.lang.v1.evaluator.Contextful.NoContext import com.wavesplatform.lang.v1.evaluator.ContextfulVal import com.wavesplatform.lang.v1.evaluator.ctx.impl.Rounding.Down -import com.wavesplatform.lang.v1.{CTX, compiler} -import com.wavesplatform.lang.v1.evaluator.ctx.impl.{CryptoContext, GlobalValNames, PureContext} import com.wavesplatform.lang.v1.evaluator.ctx.impl.waves.{Types, WavesContext} +import com.wavesplatform.lang.v1.evaluator.ctx.impl.{CryptoContext, GlobalValNames, PureContext} import com.wavesplatform.lang.v1.parser.{Expressions, Parser} import com.wavesplatform.lang.v1.traits.Environment +import com.wavesplatform.lang.v1.{CTX, compiler} import com.wavesplatform.protobuf.dapp.DAppMeta import com.wavesplatform.protobuf.dapp.DAppMeta.CompactNameAndOriginalNamePair import com.wavesplatform.test.* @@ -438,28 +438,18 @@ class ContractCompilerCompactorTest extends PropSpec { """.stripMargin def checkForV(version: StdLibVersion): Assertion = { - // noinspection RedundantDefaultArgument - val compilationResult = for { + val declarations = for { directives <- DirectiveParser(scriptForV(version)) ds <- Directive.extractDirectives(directives) (linked, _) <- ScriptPreprocessor(scriptForV(version), libraries, ds.imports) expr = Parser.parseContract(linked).get.value - r <- compiler.ContractCompiler(ctxForV(version).compilerContext, expr, version, needCompaction = false, removeUnusedCode = true) - } yield r.compactedSource(version) - - compilationResult.explicitGet() shouldBe s"""{-# STDLIB_VERSION ${version.id} #-} - |{-# SCRIPT_TYPE ACCOUNT #-} - |{-# CONTENT_TYPE DAPP #-} - |func bar () = 2 - | - | - |func foo () = 40 - | - | - | - |@Verifier(tx) - |func verify () = ((foo() + bar()) == 42) - |""".stripMargin + r <- compiler.ContractCompiler(ctxForV(version).compilerContext, expr, version, removeUnusedCode = true) + } yield r.decs + + declarations.explicitGet() should contain.only( + FUNC("foo", Nil, CONST_LONG(40)), + FUNC("bar", Nil, CONST_LONG(2)) + ) } checkForV(V5) diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ContractCompilerTest.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ContractCompilerTest.scala index 961fe41017a..2fd2f236614 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ContractCompilerTest.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ContractCompilerTest.scala @@ -1063,7 +1063,7 @@ class ContractCompilerTest extends PropSpec { ) } - property("union as argument of non-@Callable function is allowed in V6") { + property("NODE-516. union as argument of non-@Callable function is allowed in V6") { val script = """ |{-# STDLIB_VERSION 6 #-} diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/DecompilerTest.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/DecompilerTest.scala index 0affa03e31d..d78e73802aa 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/DecompilerTest.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/DecompilerTest.scala @@ -34,7 +34,7 @@ class DecompilerTest extends PropSpec { val decompilerContextV4 = getTestContext(V4).decompilerContext private def assertDecompile(script: String, decompiled: String, version: StdLibVersion): Assertion = { - val expr = TestCompiler(version).compileExpression(script.stripMargin).expr.asInstanceOf[EXPR] + val expr = TestCompiler(version).compileExpression(script.stripMargin).expr val result = Decompiler(expr, getDecompilerContext(version, Expression)) result shouldBe decompiled.stripMargin.trim } @@ -561,7 +561,7 @@ class DecompilerTest extends PropSpec { def compileExpr(code: String, v: StdLibVersion = V3): Either[String, (EXPR, TYPE)] = { val untyped = Parser.parseExpr(code).get.value - val typed = ExpressionCompiler(getTestContext(v).compilerContext, untyped) + val typed = ExpressionCompiler(getTestContext(v).compilerContext, v, untyped) typed } @@ -1126,4 +1126,14 @@ class DecompilerTest extends PropSpec { val script = """replaceByIndex(["a", "b", "c"], 1, "x")""" assertDecompile(script, script, V8) } + + property("escaping characters in string") { + val script = + s""" + |let a = "aaa\\"qqq\\"aaa" + |let b = "aaa\\\\qqq\\\\aaa" + |true + """ + assertDecompile(script, script, V6) + } } diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ErrorTest.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ErrorTest.scala index 34180e1189f..e3c17978cc7 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ErrorTest.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ErrorTest.scala @@ -3,7 +3,7 @@ package com.wavesplatform.lang.compiler import com.wavesplatform.common.state.ByteStr import com.wavesplatform.lang.Common.multiplierFunction import com.wavesplatform.lang.contract.DApp -import com.wavesplatform.lang.directives.values.V5 +import com.wavesplatform.lang.directives.values.{V3, V5} import com.wavesplatform.lang.v1.compiler.{ExpressionCompiler, TestCompiler} import com.wavesplatform.lang.v1.evaluator.ctx.impl.GlobalValNames import com.wavesplatform.lang.v1.parser.BinaryOperation.SUM_OP @@ -158,7 +158,7 @@ class ErrorTest extends PropSpec { private def errorTests(exprs: ((String, String), Expressions.EXPR)*): Unit = exprs.foreach { case ((label, error), input) => property(s"Error: $label") { - ExpressionCompiler(compilerContext, input) should produce(error) + ExpressionCompiler(compilerContext, V3, input) should produce(error) } } diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ExpressionCompilerV1Test.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ExpressionCompilerV1Test.scala index 0d61679b6f3..db285b5f704 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ExpressionCompilerV1Test.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ExpressionCompilerV1Test.scala @@ -35,7 +35,7 @@ class ExpressionCompilerV1Test extends PropSpec { property("should infer generic function return type") { import com.wavesplatform.lang.v1.parser.Expressions.* - val v = ExpressionCompiler(compilerContext, FUNCTION_CALL(AnyPos, PART.VALID(AnyPos, idT.name), List(CONST_LONG(AnyPos, 1)))).explicitGet() + val v = ExpressionCompiler(compilerContext, V3, FUNCTION_CALL(AnyPos, PART.VALID(AnyPos, idT.name), List(CONST_LONG(AnyPos, 1)))).explicitGet() v._2 shouldBe LONG } @@ -44,6 +44,7 @@ class ExpressionCompilerV1Test extends PropSpec { val v = ExpressionCompiler( compilerContext, + V3, FUNCTION_CALL( AnyPos, PART.VALID(AnyPos, "getElement"), @@ -59,7 +60,7 @@ class ExpressionCompilerV1Test extends PropSpec { } val expectedResult = Right(LONG) - ExpressionCompiler(compilerContext, expr).map(_._2) match { + ExpressionCompiler(compilerContext, V3, expr).map(_._2) match { case Right(x) => Right(x) shouldBe expectedResult case e @ Left(_) => e shouldBe expectedResult } @@ -68,11 +69,11 @@ class ExpressionCompilerV1Test extends PropSpec { property("string limit") { val maxString = "a" * Terms.DataEntryValueMax val expr = Parser.parseExpr(s""" "$maxString" """).get.value - ExpressionCompiler(compilerContext, expr).map(_._1) shouldBe CONST_STRING(maxString) + ExpressionCompiler(compilerContext, V3, expr).map(_._1) shouldBe CONST_STRING(maxString) val tooBigString = maxString + "a" val expr2 = Parser.parseExpr(s""" "$tooBigString" """).get.value - ExpressionCompiler(compilerContext, expr2) should produce("String size=32768 exceeds 32767 bytes") + ExpressionCompiler(compilerContext, V3, expr2) should produce("String size=32768 exceeds 32767 bytes") } @@ -94,8 +95,8 @@ class ExpressionCompilerV1Test extends PropSpec { """.stripMargin Parser.parseExpr(script).get.value } - ExpressionCompiler(compilerContext, funcExpr) should produce(s"Function '$tooLongName' size = 256 bytes exceeds 255") - ExpressionCompiler(compilerContext, letExpr) should produce(s"Let '$tooLongName' size = 256 bytes exceeds 255") + ExpressionCompiler(compilerContext, V3, funcExpr) should produce(s"Function '$tooLongName' size = 256 bytes exceeds 255") + ExpressionCompiler(compilerContext, V3, letExpr) should produce(s"Let '$tooLongName' size = 256 bytes exceeds 255") } @@ -117,18 +118,18 @@ class ExpressionCompilerV1Test extends PropSpec { """.stripMargin Parser.parseExpr(script).get.value } - ExpressionCompiler(compilerContext, funcExpr) shouldBe Symbol("right") - ExpressionCompiler(compilerContext, letExpr) shouldBe Symbol("right") + ExpressionCompiler(compilerContext, V3, funcExpr) shouldBe Symbol("right") + ExpressionCompiler(compilerContext, V3, letExpr) shouldBe Symbol("right") } property("tuple type checks") { val script = """ ("a", true, 123, base58'aaaa')._3 == true """ val expr = Parser.parseExpr(script).get.value - ExpressionCompiler(compilerContextV4, expr) should produce("Can't match inferred types of T over Int, Boolean") + ExpressionCompiler(compilerContextV4, V4, expr) should produce("Can't match inferred types of T over Int, Boolean") val script2 = """ ("a", true, 123, base58'aaaa') == ("a", true, "b", base58'aaaa') """ val expr2 = Parser.parseExpr(script2).get.value - ExpressionCompiler(compilerContextV4, expr2) should produce( + ExpressionCompiler(compilerContextV4, V4, expr2) should produce( "Can't match inferred types of T over (String, Boolean, Int, ByteVector), (String, Boolean, String, ByteVector)" ) @@ -146,7 +147,7 @@ class ExpressionCompilerV1Test extends PropSpec { | (((v, q), (true, v)), q) == (((1, true), (q, q)), v) """.stripMargin val expr3 = Parser.parseExpr(script3).get.value - ExpressionCompiler(compilerContextV4, expr3) shouldBe Symbol("right") + ExpressionCompiler(compilerContextV4, V4, expr3) shouldBe Symbol("right") val script4 = """ @@ -156,7 +157,7 @@ class ExpressionCompilerV1Test extends PropSpec { | (((v, q), (true, v)), q) == (((1, true), (v, q)), v) """.stripMargin val expr4 = Parser.parseExpr(script4).get.value - ExpressionCompiler(compilerContextV4, expr4) should produce( + ExpressionCompiler(compilerContextV4, V4, expr4) should produce( "Can't match inferred types of T over " + "(((Int|String, Boolean|Int|String), (Boolean, Int|String)), Boolean|Int|String), " + "(((Int, Boolean), (Int|String, Boolean|Int|String)), Int|String) in 102-154" @@ -171,7 +172,7 @@ class ExpressionCompilerV1Test extends PropSpec { | a1 == b1 """.stripMargin val expr = Parser.parseExpr(script).get.value - ExpressionCompiler(compilerContextV4, expr) shouldBe Symbol("right") + ExpressionCompiler(compilerContextV4, V4, expr) shouldBe Symbol("right") } property("function with tuple args") { @@ -189,7 +190,7 @@ class ExpressionCompilerV1Test extends PropSpec { | """.stripMargin val expr = Parser.parseExpr(script).get.value - ExpressionCompiler(compilerContextV4, expr) shouldBe Symbol("right") + ExpressionCompiler(compilerContextV4, V4, expr) shouldBe Symbol("right") val script2 = """ @@ -200,7 +201,7 @@ class ExpressionCompilerV1Test extends PropSpec { | """.stripMargin val expr2 = Parser.parseExpr(script2).get.value - ExpressionCompiler(compilerContextV4, expr2) should produce( + ExpressionCompiler(compilerContextV4, V4, expr2) should produce( "Non-matching types: expected: (String, Boolean), actual: Boolean in 69-86" ) @@ -213,7 +214,7 @@ class ExpressionCompilerV1Test extends PropSpec { | """.stripMargin val expr3 = Parser.parseExpr(script3).get.value - ExpressionCompiler(compilerContextV4, expr3) should produce( + ExpressionCompiler(compilerContextV4, V4, expr3) should produce( "Non-matching types: expected: ((Int, String), Boolean)|(Int, String, Boolean), actual: (Int, String) in 73-84" ) } @@ -237,7 +238,7 @@ class ExpressionCompilerV1Test extends PropSpec { | """.stripMargin val expr = Parser.parseExpr(script).get.value - ExpressionCompiler(compilerContextV4, expr) shouldBe Symbol("right") + ExpressionCompiler(compilerContextV4, V4, expr) shouldBe Symbol("right") val script2 = """ @@ -249,7 +250,7 @@ class ExpressionCompilerV1Test extends PropSpec { | true """.stripMargin val expr2 = Parser.parseExpr(script2).get.value - ExpressionCompiler(compilerContextV4, expr2) should produce( + ExpressionCompiler(compilerContextV4, V4, expr2) should produce( "Matching not exhaustive: " + "possibleTypes are (Int, String), ((Boolean, Int), ByteVector), " + "while matched are (Int, String), (Boolean, Int, ByteVector)" @@ -274,7 +275,7 @@ class ExpressionCompilerV1Test extends PropSpec { | """.stripMargin val expr3 = Parser.parseExpr(script3).get.value - ExpressionCompiler(compilerContextV4, expr3) shouldBe Symbol("right") + ExpressionCompiler(compilerContextV4, V4, expr3) shouldBe Symbol("right") val script4 = """ @@ -288,7 +289,7 @@ class ExpressionCompilerV1Test extends PropSpec { | """.stripMargin val expr4 = Parser.parseExpr(script4).get.value - ExpressionCompiler(compilerContextV4, expr4) should produce( + ExpressionCompiler(compilerContextV4, V4, expr4) should produce( "Matching not exhaustive: " + "possibleTypes are (Int, String), (Boolean, String), (ByteVector, Boolean, (String, (Int, Boolean))|Int), " + "while matched are (Boolean|Int, String), (ByteVector, Boolean, Int), (ByteVector, Boolean, (String, Int, Boolean)) " + @@ -303,7 +304,7 @@ class ExpressionCompilerV1Test extends PropSpec { | } """.stripMargin val expr5 = Parser.parseExpr(script5).get.value - ExpressionCompiler(compilerContextV4, expr5) shouldBe Symbol("right") + ExpressionCompiler(compilerContextV4, V4, expr5) shouldBe Symbol("right") } property("JS API compile limit exceeding error") { @@ -330,6 +331,7 @@ class ExpressionCompilerV1Test extends PropSpec { def checkExtract(version: StdLibVersion) = ExpressionCompiler( getTestContext(version).compilerContext, + version, Parser.parseExpr(" extract(1) ").get.value ) @@ -358,7 +360,7 @@ class ExpressionCompilerV1Test extends PropSpec { DirectiveDictionary[StdLibVersion].all .foreach { version => - val result = ExpressionCompiler(getTestContext(version).compilerContext, Parser.parseExpr(expr).get.value) + val result = ExpressionCompiler(getTestContext(version).compilerContext, version, Parser.parseExpr(expr).get.value) if (version >= V4) result shouldBe Symbol("right") else @@ -390,7 +392,7 @@ class ExpressionCompilerV1Test extends PropSpec { version <- DirectiveDictionary[StdLibVersion].all scriptType <- DirectiveDictionary[ScriptType].all } { - val result = ExpressionCompiler(getTestContext(version, scriptType).compilerContext, expr(version, scriptType)) + val result = ExpressionCompiler(getTestContext(version, scriptType).compilerContext, version, expr(version, scriptType)) if (version < V5 || scriptType != Account) result.swap.getOrElse(???).split("Can't find a function").length shouldBe 9 else @@ -415,7 +417,7 @@ class ExpressionCompilerV1Test extends PropSpec { DirectiveDictionary[StdLibVersion].all .foreach { version => - val result = ExpressionCompiler(getTestContext(version).compilerContext, expr(version)) + val result = ExpressionCompiler(getTestContext(version).compilerContext, version, expr(version)) if (version < V5) result should produce( "Compilation failed: [" + @@ -446,7 +448,7 @@ class ExpressionCompilerV1Test extends PropSpec { DirectiveDictionary[StdLibVersion].all .foreach { version => - val result = ExpressionCompiler(getTestContext(version).compilerContext, expr(version)) + val result = ExpressionCompiler(getTestContext(version).compilerContext, version, expr(version)) if (version < V5) result shouldBe Symbol("right") else @@ -484,7 +486,7 @@ class ExpressionCompilerV1Test extends PropSpec { DirectiveDictionary[StdLibVersion].all .foreach { version => - ExpressionCompiler(getTestContext(version).compilerContext, expr(version)) shouldBe Symbol("right") + ExpressionCompiler(getTestContext(version).compilerContext, version, expr(version)) shouldBe Symbol("right") } } @@ -512,7 +514,7 @@ class ExpressionCompilerV1Test extends PropSpec { DirectiveDictionary[StdLibVersion].all .foreach { version => - val result = ExpressionCompiler(getTestContext(version).compilerContext, expr(version)) + val result = ExpressionCompiler(getTestContext(version).compilerContext, version, expr(version)) if (version < V5) result shouldBe Symbol("right") else { @@ -542,7 +544,7 @@ class ExpressionCompilerV1Test extends PropSpec { DirectiveDictionary[StdLibVersion].all .filter(_ >= V3) .foreach { version => - val result = ExpressionCompiler(getTestContext(version).compilerContext, expr(version)) + val result = ExpressionCompiler(getTestContext(version).compilerContext, version, expr(version)) val error = result.swap.getOrElse(???) error should include("Can't find a function 'invoke'") error should include("Can't find a function 'reentrantInvoke'") @@ -662,7 +664,7 @@ class ExpressionCompilerV1Test extends PropSpec { ref = Expressions.REF(AnyPos, Expressions.PART.VALID(AnyPos, "p")), field = Expressions.PART.VALID(AnyPos, "x") ), - expectedResult = { res: Either[String, (EXPR, TYPE)] => + expectedResult = { (res: Either[String, (EXPR, TYPE)]) => res shouldBe Right((GETTER(expr = REF("p"), field = "x"), LONG)) } ) @@ -675,7 +677,7 @@ class ExpressionCompilerV1Test extends PropSpec { provideRuntimeTypeOnCastError = false ), expr = Expressions.REF(AnyPos, Expressions.PART.VALID(AnyPos, "p")), - expectedResult = { res: Either[String, (EXPR, TYPE)] => + expectedResult = { (res: Either[String, (EXPR, TYPE)]) => res shouldBe Right((REF("p"), pointType)) } ) @@ -688,7 +690,7 @@ class ExpressionCompilerV1Test extends PropSpec { provideRuntimeTypeOnCastError = false ), expr = Expressions.REF(AnyPos, Expressions.PART.VALID(AnyPos, "p")), - expectedResult = { res: Either[String, (EXPR, TYPE)] => + expectedResult = { (res: Either[String, (EXPR, TYPE)]) => res shouldBe Right((REF("p"), pointType)) } ) @@ -700,7 +702,7 @@ class ExpressionCompilerV1Test extends PropSpec { Expressions.PART.VALID(AnyPos, multiplierFunction.name), List(Expressions.CONST_LONG(AnyPos, 1), Expressions.CONST_LONG(AnyPos, 2)) ), - expectedResult = { res: Either[String, (EXPR, TYPE)] => + expectedResult = { (res: Either[String, (EXPR, TYPE)]) => res shouldBe Right((FUNCTION_CALL(multiplierFunction.header, List(CONST_LONG(1), CONST_LONG(2))), LONG)) } ) @@ -712,7 +714,7 @@ class ExpressionCompilerV1Test extends PropSpec { Expressions.PART.VALID(AnyPos, getElement.name), List(Expressions.REF(AnyPos, Expressions.PART.VALID(AnyPos, "l")), Expressions.CONST_LONG(AnyPos, 1)) ), - expectedResult = { res: Either[String, (EXPR, TYPE)] => + expectedResult = { (res: Either[String, (EXPR, TYPE)]) => res shouldBe Right((FUNCTION_CALL(getElement.header, List(REF("l"), CONST_LONG(1))), LONG)) } ) @@ -724,7 +726,7 @@ class ExpressionCompilerV1Test extends PropSpec { Expressions.PART.VALID(AnyPos, getElement.name), List(Expressions.REF(AnyPos, Expressions.PART.VALID(AnyPos, "lpa")), Expressions.CONST_LONG(AnyPos, 1)) ), - expectedResult = { res: Either[String, (EXPR, TYPE)] => + expectedResult = { (res: Either[String, (EXPR, TYPE)]) => res shouldBe Right((FUNCTION_CALL(getElement.header, List(REF("lpa"), CONST_LONG(1))), Common.pointTypeA)) } ) @@ -736,7 +738,7 @@ class ExpressionCompilerV1Test extends PropSpec { Expressions.PART.VALID(AnyPos, getElement.name), List(Expressions.REF(AnyPos, Expressions.PART.VALID(AnyPos, "lpabc")), Expressions.CONST_LONG(AnyPos, 1)) ), - expectedResult = { res: Either[String, (EXPR, TYPE)] => + expectedResult = { (res: Either[String, (EXPR, TYPE)]) => res shouldBe Right((FUNCTION_CALL(getElement.header, List(REF("lpabc"), CONST_LONG(1))), Common.AorBorC)) } ) @@ -764,7 +766,7 @@ class ExpressionCompilerV1Test extends PropSpec { List(Expressions.REF(AnyPos, Expressions.PART.VALID(AnyPos, "a")), Expressions.CONST_LONG(AnyPos, 3)) ) ), - expectedResult = { res: Either[String, (EXPR, TYPE)] => + expectedResult = { (res: Either[String, (EXPR, TYPE)]) => res shouldBe Right( ( LET_BLOCK( @@ -784,7 +786,7 @@ class ExpressionCompilerV1Test extends PropSpec { Expressions.PART.VALID(AnyPos, idOptionLong.name), List(Expressions.REF(AnyPos, Expressions.PART.VALID(AnyPos, GlobalValNames.Unit))) ), - expectedResult = { res: Either[String, (EXPR, TYPE)] => + expectedResult = { (res: Either[String, (EXPR, TYPE)]) => res shouldBe Right((FUNCTION_CALL(idOptionLong.header, List(REF(GlobalValNames.Unit))), UNIT)) } ) @@ -816,7 +818,7 @@ class ExpressionCompilerV1Test extends PropSpec { ) ) ), - expectedResult = { res: Either[String, (EXPR, TYPE)] => + expectedResult = { (res: Either[String, (EXPR, TYPE)]) => res shouldBe Right( ( LET_BLOCK( @@ -867,7 +869,7 @@ class ExpressionCompilerV1Test extends PropSpec { """.stripMargin Parser.parseExpr(script).get.value }, - expectedResult = { res: Either[String, (EXPR, TYPE)] => + expectedResult = { (res: Either[String, (EXPR, TYPE)]) => res shouldBe Right( ( LET_BLOCK( @@ -915,7 +917,7 @@ class ExpressionCompilerV1Test extends PropSpec { ) ) ), - expectedResult = { res: Either[String, (EXPR, TYPE)] => + expectedResult = { (res: Either[String, (EXPR, TYPE)]) => res should produce("Value 'foo' already defined in the scope in -1--1") } ) @@ -951,7 +953,7 @@ class ExpressionCompilerV1Test extends PropSpec { ) ) ), - expectedResult = { res: Either[String, (EXPR, TYPE)] => + expectedResult = { (res: Either[String, (EXPR, TYPE)]) => res should produce("Value 'p' already defined in the scope in -1--1") } ) @@ -980,7 +982,7 @@ class ExpressionCompilerV1Test extends PropSpec { ) ) ), - expectedResult = { res: Either[String, (EXPR, TYPE)] => + expectedResult = { (res: Either[String, (EXPR, TYPE)]) => res should produce("Undefined type: `Point0`, expected: PointA, PointB") } ) @@ -992,7 +994,7 @@ class ExpressionCompilerV1Test extends PropSpec { Expressions.LET(AnyPos, Expressions.PART.INVALID(Pos(0, 1), "can't parse"), Expressions.TRUE(AnyPos)), Expressions.REF(AnyPos, Expressions.PART.VALID(AnyPos, "x")) ), - expectedResult = { res: Either[String, (EXPR, TYPE)] => + expectedResult = { (res: Either[String, (EXPR, TYPE)]) => res should produce("can't parse in 0-1") } ) @@ -1001,7 +1003,7 @@ class ExpressionCompilerV1Test extends PropSpec { ctx = compilerContext, expr = Expressions.GETTER(AnyPos, Expressions.REF(AnyPos, Expressions.PART.VALID(AnyPos, "x")), Expressions.PART.INVALID(Pos(2, 3), "can't parse")), - expectedResult = { res: Either[String, (EXPR, TYPE)] => + expectedResult = { (res: Either[String, (EXPR, TYPE)]) => res should produce("can't parse in 2-3") } ) @@ -1009,7 +1011,7 @@ class ExpressionCompilerV1Test extends PropSpec { treeTypeTest("Invalid BYTESTR")( ctx = compilerContext, expr = Expressions.CONST_BYTESTR(AnyPos, Expressions.PART.INVALID(AnyPos, "can't parse")), - expectedResult = { res: Either[String, (EXPR, TYPE)] => + expectedResult = { (res: Either[String, (EXPR, TYPE)]) => res should produce("can't parse in -1--1") } ) @@ -1017,7 +1019,7 @@ class ExpressionCompilerV1Test extends PropSpec { treeTypeTest("Invalid STRING")( ctx = compilerContext, expr = Expressions.CONST_STRING(AnyPos, Expressions.PART.INVALID(AnyPos, "can't parse")), - expectedResult = { res: Either[String, (EXPR, TYPE)] => + expectedResult = { (res: Either[String, (EXPR, TYPE)]) => res should produce("can't parse in -1--1") } ) @@ -1025,7 +1027,7 @@ class ExpressionCompilerV1Test extends PropSpec { treeTypeTest("Invalid REF")( ctx = compilerContext, expr = Expressions.REF(AnyPos, Expressions.PART.INVALID(AnyPos, "can't parse")), - expectedResult = { res: Either[String, (EXPR, TYPE)] => + expectedResult = { (res: Either[String, (EXPR, TYPE)]) => res should produce("can't parse in -1--1") } ) @@ -1033,7 +1035,7 @@ class ExpressionCompilerV1Test extends PropSpec { treeTypeTest("Invalid FUNCTION_CALL")( ctx = compilerContext, expr = Expressions.FUNCTION_CALL(AnyPos, Expressions.PART.INVALID(AnyPos, "can't parse"), List.empty), - expectedResult = { res: Either[String, (EXPR, TYPE)] => + expectedResult = { (res: Either[String, (EXPR, TYPE)]) => res should produce("can't parse in -1--1") } ) @@ -1041,7 +1043,7 @@ class ExpressionCompilerV1Test extends PropSpec { treeTypeTest("INVALID")( ctx = compilerContext, expr = Expressions.INVALID(AnyPos, "###"), - expectedResult = { res: Either[String, (EXPR, TYPE)] => + expectedResult = { (res: Either[String, (EXPR, TYPE)]) => res should produce("### in -1--1") } ) @@ -1053,7 +1055,7 @@ class ExpressionCompilerV1Test extends PropSpec { Expressions.PART.VALID(AnyPos, "dropRight"), List(Expressions.CONST_BYTESTR(AnyPos, Expressions.PART.VALID(AnyPos, ByteStr.empty)), Expressions.CONST_LONG(AnyPos, 1)) ), - expectedResult = { res: Either[String, (EXPR, TYPE)] => + expectedResult = { (res: Either[String, (EXPR, TYPE)]) => res shouldBe Right( ( FUNCTION_CALL(User("dropRightBytes"), List(CONST_BYTESTR(ByteStr.empty).explicitGet(), CONST_LONG(1))), @@ -1070,7 +1072,7 @@ class ExpressionCompilerV1Test extends PropSpec { Expressions.PART.VALID(AnyPos, "dropRight"), List(Expressions.CONST_STRING(AnyPos, Expressions.PART.VALID(AnyPos, "")), Expressions.CONST_LONG(AnyPos, 1)) ), - expectedResult = { res: Either[String, (EXPR, TYPE)] => + expectedResult = { (res: Either[String, (EXPR, TYPE)]) => res shouldBe Right( ( FUNCTION_CALL(User("dropRight"), List(CONST_STRING("").explicitGet(), CONST_LONG(1))), @@ -1087,7 +1089,7 @@ class ExpressionCompilerV1Test extends PropSpec { Expressions.PART.VALID(AnyPos, "dropRight"), List(Expressions.TRUE(AnyPos), Expressions.CONST_LONG(AnyPos, 1)) ), - expectedResult = { res: Either[String, (EXPR, TYPE)] => + expectedResult = { (res: Either[String, (EXPR, TYPE)]) => res should produce("Can't find a function overload 'dropRight'(Boolean, Int) in -1--1") } ) @@ -1104,7 +1106,7 @@ class ExpressionCompilerV1Test extends PropSpec { ), Expressions.FUNCTION_CALL(AnyPos, Expressions.PART.VALID(AnyPos, "id"), List(Expressions.CONST_LONG(AnyPos, 1L))) ), - expectedResult = { res: Either[String, (EXPR, TYPE)] => + expectedResult = { (res: Either[String, (EXPR, TYPE)]) => res shouldBe Right( ( BLOCK( @@ -1123,7 +1125,7 @@ class ExpressionCompilerV1Test extends PropSpec { val script = """[1,""]""" Parser.parseExpr(script).get.value }, - expectedResult = { res: Either[String, (EXPR, TYPE)] => + expectedResult = { (res: Either[String, (EXPR, TYPE)]) => res shouldBe Right( ( FUNCTION_CALL( @@ -1149,7 +1151,7 @@ class ExpressionCompilerV1Test extends PropSpec { propertyName: String )(expr: Expressions.EXPR, expectedResult: Either[String, (EXPR, TYPE)] => org.scalatest.compatible.Assertion, ctx: CompilerContext): Unit = property(propertyName) { - val res = compiler.ExpressionCompiler(ctx, expr) + val res = compiler.ExpressionCompiler(ctx, V3, expr) expectedResult(res) } diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ScriptPreprocessorTest.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ScriptPreprocessorTest.scala index 8ce9d375f90..b953caabf5f 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ScriptPreprocessorTest.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/compiler/ScriptPreprocessorTest.scala @@ -6,7 +6,6 @@ import cats.kernel.Monoid import com.wavesplatform.lang.directives.values.V3 import com.wavesplatform.lang.directives.{Directive, DirectiveParser} import com.wavesplatform.lang.script.ScriptPreprocessor -import com.wavesplatform.lang.v1.CTX import com.wavesplatform.lang.v1.compiler.ExpressionCompiler import com.wavesplatform.lang.v1.compiler.Terms.{CONST_BOOLEAN, EVALUATED} import com.wavesplatform.lang.v1.evaluator.Contextful.NoContext @@ -29,9 +28,9 @@ class ScriptPreprocessorTest extends PropSpec with ScriptGenParser { } yield r private def eval(code: String): Either[String, EVALUATED] = { - val untyped = Parser.parseExpr(code).get.value - val ctx: CTX[NoContext] = Monoid.combineAll(Seq(PureContext.build(V3, useNewPowPrecision = true))) - val typed = ExpressionCompiler(ctx.compilerContext, untyped) + val untyped = Parser.parseExpr(code).get.value + val ctx = Monoid.combineAll(Seq(PureContext.build(V3, useNewPowPrecision = true))) + val typed = ExpressionCompiler(ctx.compilerContext, V3, untyped) typed.flatMap(v => evaluator[EVALUATED](ctx.evaluationContext, v._1).leftMap(_.toString)) } diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/estimator/ScriptEstimatorTestBase.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/estimator/ScriptEstimatorTestBase.scala index 5eae03001d6..ed72f994c1f 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/estimator/ScriptEstimatorTestBase.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/estimator/ScriptEstimatorTestBase.scala @@ -57,7 +57,7 @@ class ScriptEstimatorTestBase(estimators: ScriptEstimator*) extends PropSpec { protected def compile(code: String)(implicit version: StdLibVersion): EXPR = { val untyped = Parser.parseExpr(code).get.value - ExpressionCompiler(ctx.compilerContext, untyped).map(_._1).explicitGet() + ExpressionCompiler(ctx.compilerContext, version, untyped).map(_._1).explicitGet() } protected def estimate( diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorSpec.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorSpec.scala index 4b1cf9590b8..80042803f63 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorSpec.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorSpec.scala @@ -1,18 +1,18 @@ package com.wavesplatform.lang.evaluator -import cats.implicits.* import cats.Id +import cats.implicits.* import com.wavesplatform.common.utils.EitherExt2 -import com.wavesplatform.lang.{Common, ExecutionError} -import com.wavesplatform.lang.directives.{DirectiveDictionary, DirectiveSet} import com.wavesplatform.lang.directives.values.* +import com.wavesplatform.lang.directives.{DirectiveDictionary, DirectiveSet} import com.wavesplatform.lang.utils.lazyContexts import com.wavesplatform.lang.v1.compiler.ExpressionCompiler import com.wavesplatform.lang.v1.compiler.Terms.{EVALUATED, EXPR} import com.wavesplatform.lang.v1.evaluator.ContractEvaluator.LogExtraInfo import com.wavesplatform.lang.v1.evaluator.{EvaluatorV2, Log} -import com.wavesplatform.lang.v1.parser.Parser +import com.wavesplatform.lang.v1.parser.Parser.LibrariesOffset.NoLibraries import com.wavesplatform.lang.v1.testing.ScriptGen +import com.wavesplatform.lang.{Common, ExecutionError} import com.wavesplatform.test.PropSpec import org.scalatest.Inside import org.scalatest.exceptions.TestFailedException @@ -87,9 +87,8 @@ abstract class EvaluatorSpec extends PropSpec with ScriptGen with Inside { ) } - def compile(code: String, version: StdLibVersion): Either[String, EXPR] = { - val ctx = lazyContexts((DirectiveSet(version, Account, Expression).explicitGet(), true, true)).value() - val parsed = Parser.parseExpr(code).get.value - ExpressionCompiler(ctx.compilerContext, parsed, allowIllFormedStrings = true).map(_._1) + private def compile(code: String, version: StdLibVersion): Either[String, EXPR] = { + val ctx = lazyContexts((DirectiveSet(version, Account, Expression).explicitGet(), true, true)).value() + ExpressionCompiler.compile(code, NoLibraries, ctx.compilerContext, version, allowIllFormedStrings = true).map(_._1) } } diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorV1V2Test.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorV1V2Test.scala index 6499fcefe26..93359c2b6e6 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorV1V2Test.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorV1V2Test.scala @@ -882,7 +882,7 @@ class EvaluatorV1V2Test extends PropSpec with EitherValues { evalPure[EVALUATED]( context.evaluationContext[Id], ExpressionCompiler - .apply(context.compilerContext, xs) + .apply(context.compilerContext, version, xs) .explicitGet() ._1 ) diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorV2Test.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorV2Test.scala index 02c24fe2e92..c62dddc1cb4 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorV2Test.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorV2Test.scala @@ -68,7 +68,7 @@ class EvaluatorV2Test extends PropSpec with Inside { private def compile(script: String): EXPR = { val parsed = Parser.parseExpr(script).get.value - ExpressionCompiler(ctx.compilerContext, parsed).explicitGet()._1 + ExpressionCompiler(ctx.compilerContext, version, parsed).explicitGet()._1 } property("multiple lets by step") { diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/NestedPatternsTest.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/NestedPatternsTest.scala index 080aded4dfe..b33b7575958 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/NestedPatternsTest.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/NestedPatternsTest.scala @@ -1,6 +1,7 @@ package com.wavesplatform.lang.evaluator -import com.wavesplatform.lang.directives.values.{StdLibVersion, V6} +import com.wavesplatform.lang.directives.values.{StdLibVersion, V6, V7, V8} import com.wavesplatform.lang.v1.compiler.Terms.CONST_BOOLEAN +import com.wavesplatform.test.produce class NestedPatternsTest extends EvaluatorSpec { implicit val v: StdLibVersion = V6 @@ -126,4 +127,58 @@ class NestedPatternsTest extends EvaluatorSpec { """.stripMargin ) shouldBe Right(CONST_BOOLEAN(true)) } + + property("restrictions from V8") { + val script1 = + s""" + | match Lease(Address(base58''), 1, 1) { + | case Lease(nonce = f()) => true + | case _ => false + | } + """.stripMargin + eval(script1)(V7, checkNext = false) shouldBe Right(CONST_BOOLEAN(true)) + eval(script1)(V8) should produce("Only constant value could be matched with object field in 63-66") + + val script2 = + s""" + | func f() = 777 + | match Lease(Address(base58''), 1, 1) { + | case Lease(nonce = f()) => true + | case _ => false + | } + """.stripMargin + eval(script2)(V7, checkNext = false) shouldBe Right(CONST_BOOLEAN(true)) + eval(script2)(V8) should produce("Only constant value could be matched with object field in 79-82") + + val script3 = + s""" + | func f() = 777 + | match Lease(Address(base58''), 1, 1) { + | case Lease(nonce = {f()}) => true + | case _ => false + | } + """.stripMargin + eval(script3)(V7, checkNext = false) shouldBe Right(CONST_BOOLEAN(false)) + eval(script3)(V8) should produce("Only constant value could be matched with object field in 80-83") + + val script4 = + s""" + | match Lease(Address(base58''), 1, 1) { + | case Lease(nonce = {1 + 2}) => true + | case _ => false + | } + """.stripMargin + eval(script4)(V7, checkNext = false) shouldBe Right(CONST_BOOLEAN(false)) + eval(script4)(V8) should produce("Only constant value could be matched with object field in 64-69") + + val script5 = + s""" + | match Lease(Address(base58''), 1, 1) { + | case Lease(nonce = {if (true) then 2 else 1}) => true + | case _ => false + | } + """.stripMargin + eval(script5)(V7, checkNext = false) shouldBe Right(CONST_BOOLEAN(false)) + eval(script5)(V8) should produce("Only constant value could be matched with object field in 64-87") + } } diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/tuple/TupleSizeTest.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/tuple/TupleSizeTest.scala index a899d6a03eb..57c8a99b371 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/tuple/TupleSizeTest.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/tuple/TupleSizeTest.scala @@ -10,7 +10,6 @@ class TupleSizeTest extends EvaluatorSpec { property("tuple size") { (ContractLimits.MinTupleSize to ContractLimits.MaxTupleSize) - .map(1 to) - .foreach(range => eval(s"(${range.mkString(",")}).size()") shouldBe Right(CONST_LONG(range.length))) + .foreach(size => eval(s"(${(1 to size).mkString(",")}).size()") shouldBe Right(CONST_LONG(size))) } } diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/parser/TupleTypeCommentsTest.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/parser/TupleTypeCommentsTest.scala new file mode 100644 index 00000000000..9a2a4afdc87 --- /dev/null +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/parser/TupleTypeCommentsTest.scala @@ -0,0 +1,47 @@ +package com.wavesplatform.lang.parser + +import com.wavesplatform.common.utils.EitherExt2 +import com.wavesplatform.lang.directives.values.* +import com.wavesplatform.lang.utils.getDecompilerContext +import com.wavesplatform.lang.v1.compiler.{Decompiler, TestCompiler} +import com.wavesplatform.test.PropSpec + +class TupleTypeCommentsTest extends PropSpec { + property("allowed comments between definitions of tuple types") { + val expr = TestCompiler(V6) + .compile( + """ + | func f( + | a: ( # comment + | # comment + | Int, # comment + | # comment + | String, # comment + | # comment + | ( # comment + | # comment + | List[( # comment + | # comment + | List[String], # comment + | # comment + | ( # comment + | # comment + | Address, # comment + | # comment + | Boolean # comment + | # comment + | ) # comment + | # comment + | )], # comment + | # comment + | Int # comment + | # comment + | ) # comment + | ) # comment + | ) = [] + """.stripMargin + ) + .explicitGet() + Decompiler(expr, getDecompilerContext(V6, DApp), V6).trim shouldBe "func f (a) = nil" + } +} diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/serde/SerdeTest.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/serde/SerdeTest.scala index 0d9c56bd73e..8de49007e18 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/serde/SerdeTest.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/serde/SerdeTest.scala @@ -177,7 +177,7 @@ class SerdeTest extends FreeSpec { } private def roundTripTest(untypedExpr: Expressions.EXPR): Unit = { - val typedExpr = ExpressionCompiler(PureContext.build(V1, useNewPowPrecision = true).compilerContext, untypedExpr).map(_._1).explicitGet() + val typedExpr = ExpressionCompiler(PureContext.build(V1, useNewPowPrecision = true).compilerContext, V1, untypedExpr).map(_._1).explicitGet() roundTripTest(typedExpr) } diff --git a/lang/tests/src/test/scala/com/wavesplatform/utils/MerkleTest.scala b/lang/tests/src/test/scala/com/wavesplatform/utils/MerkleTest.scala index b50669e964b..102d83ba4d6 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/utils/MerkleTest.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/utils/MerkleTest.scala @@ -109,7 +109,7 @@ class MerkleTest extends PropSpec { val untyped = Parser.parseExpr(code).get.value val ctx = lazyContexts((DirectiveSet(version, Account, Expression).explicitGet(), true, true))() val evalCtx = ctx.evaluationContext[Id](Common.emptyBlockchainEnvironment()) - val typed = ExpressionCompiler(ctx.compilerContext, untyped) + val typed = ExpressionCompiler(ctx.compilerContext, V3, untyped) typed.flatMap(v => EvaluatorV2.applyCompleted(evalCtx, v._1, LogExtraInfo(), version, true, true, false, true)._3.leftMap(_.toString)) } diff --git a/lang/tests/src/test/scala/com/wavesplatform/utils/RSATest.scala b/lang/tests/src/test/scala/com/wavesplatform/utils/RSATest.scala index 0f15a68e63e..570ff7ad77b 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/utils/RSATest.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/utils/RSATest.scala @@ -337,7 +337,7 @@ class RSATest extends PropSpec with BeforeAndAfterAll { private def eval[T <: EVALUATED](code: String, ctx: CTX[NoContext] = PureContext.build(V4, useNewPowPrecision = true) |+| CryptoContext.build(Global, V4)): Either[String, T] = { val untyped = Parser.parseExpr(code).get.value - val typed = ExpressionCompiler(ctx.compilerContext, untyped) + val typed = ExpressionCompiler(ctx.compilerContext, V4, untyped) typed.flatMap(v => evaluator[T](ctx.evaluationContext, v._1).leftMap(_.message)) } diff --git a/node-generator/src/main/scala/com/wavesplatform/generator/utils/Gen.scala b/node-generator/src/main/scala/com/wavesplatform/generator/utils/Gen.scala index 2282ec6097e..85c77160c4b 100644 --- a/node-generator/src/main/scala/com/wavesplatform/generator/utils/Gen.scala +++ b/node-generator/src/main/scala/com/wavesplatform/generator/utils/Gen.scala @@ -45,7 +45,7 @@ object Gen { else s"if (${recString(n - 1)}) then true else false" - def oracleScript(oracle: KeyPair, data: Set[DataEntry[_]], estimator: ScriptEstimator): Script = { + def oracleScript(oracle: KeyPair, data: Set[DataEntry[?]], estimator: ScriptEstimator): Script = { val conditions = data.map { case IntegerDataEntry(key, value) => s"""(extract(getInteger(oracle, "$key")) == $value)""" @@ -53,7 +53,7 @@ object Gen { case BinaryDataEntry(key, value) => s"""(extract(getBinary(oracle, "$key")) == $value)""" case StringDataEntry(key, value) => s"""(extract(getString(oracle, "$key")) == "$value")""" case EmptyDataEntry(_) => ??? - } reduce [String] { case (l, r) => s"$l && $r " } + }.reduce[String] { case (l, r) => s"$l && $r " } val src = s""" diff --git a/node-it/src/test/scala/com/wavesplatform/it/Docker.scala b/node-it/src/test/scala/com/wavesplatform/it/Docker.scala index 9e643ee19e1..dd783097475 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/Docker.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/Docker.scala @@ -1,29 +1,13 @@ package com.wavesplatform.it -import java.io.{FileOutputStream, IOException} -import java.net.{InetAddress, InetSocketAddress, URL} -import java.nio.file.{Files, Path, Paths} -import java.time.LocalDateTime -import java.time.format.DateTimeFormatter -import java.util.{Properties, List as JList, Map as JMap} -import java.util.Collections.* -import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.atomic.{AtomicBoolean, AtomicInteger} -import scala.annotation.tailrec -import scala.concurrent.{Await, Future, blocking} -import scala.concurrent.ExecutionContext.Implicits.global -import scala.concurrent.duration.* -import scala.jdk.CollectionConverters.* -import scala.util.{Random, Try} -import scala.util.control.NonFatal import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.dataformat.javaprop.JavaPropsMapper import com.google.common.primitives.Ints.* -import com.spotify.docker.client.{DefaultDockerClient, DockerClient} import com.spotify.docker.client.messages.* import com.spotify.docker.client.messages.EndpointConfig.EndpointIpamConfig -import com.typesafe.config.{Config, ConfigFactory, ConfigRenderOptions} +import com.spotify.docker.client.{DefaultDockerClient, DockerClient} import com.typesafe.config.ConfigFactory.* +import com.typesafe.config.{Config, ConfigFactory, ConfigRenderOptions} import com.wavesplatform.account.AddressScheme import com.wavesplatform.block.Block import com.wavesplatform.common.utils.EitherExt2 @@ -40,6 +24,23 @@ import org.apache.commons.compress.archivers.tar.TarArchiveEntry import org.apache.commons.io.IOUtils import org.asynchttpclient.Dsl.* +import java.io.{FileOutputStream, IOException} +import java.net.{InetAddress, InetSocketAddress, URL} +import java.nio.file.{Files, Path, Paths} +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter +import java.util.Collections.* +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.atomic.{AtomicBoolean, AtomicInteger} +import java.util.{Properties, List as JList, Map as JMap} +import scala.annotation.tailrec +import scala.concurrent.ExecutionContext.Implicits.global +import scala.concurrent.duration.* +import scala.concurrent.{Await, Future, blocking} +import scala.jdk.CollectionConverters.* +import scala.util.control.NonFatal +import scala.util.{Random, Try} + class Docker( suiteConfig: Config = empty, tag: String = "", @@ -169,7 +170,7 @@ class Docker( // Exclude disconnected client.inspectContainer(node.containerId).networkSettings().networks().isEmpty } - .map(_.containerNetworkAddress) + .map(_.networkAddress) .toSeq } @@ -260,10 +261,16 @@ class Docker( profilerConfigEnv ).filter(_.nonEmpty) + val exposedPorts = new java.util.HashSet[String]() + exposedPorts.add(s"$internalDebuggerPort") + if (Try(nodeConfig.getStringList("waves.extensions").contains("com.wavesplatform.events.BlockchainUpdates")).getOrElse(false)) { + exposedPorts.add("6881") + } + val containerConfig = ContainerConfig .builder() .image(imageName) - .exposedPorts(s"$internalDebuggerPort") + .exposedPorts(exposedPorts) .networkingConfig(ContainerConfig.NetworkingConfig.create(Map(wavesNetwork.name() -> endpointConfigFor(nodeName)).asJava)) .hostConfig(hostConfig) .env(envs*) @@ -621,9 +628,7 @@ object Docker { override val apiKey = "integration-test-rest-api" - override def networkAddress: InetSocketAddress = nodeInfo.hostNetworkAddress - - def containerNetworkAddress: InetSocketAddress = nodeInfo.containerNetworkAddress + override def networkAddress: InetSocketAddress = nodeInfo.containerNetworkAddress def getConfig: Config = config } diff --git a/node-it/src/test/scala/com/wavesplatform/it/Node.scala b/node-it/src/test/scala/com/wavesplatform/it/Node.scala index e98782eaa65..903f56213ee 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/Node.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/Node.scala @@ -28,7 +28,7 @@ abstract class Node(val config: Config) extends AutoCloseable { ) lazy val grpcChannel: ManagedChannel = ManagedChannelBuilder - .forAddress(networkAddress.getHostString, nodeExternalPort(6870)) + .forAddress(nodeApiEndpoint.getHost, nodeExternalPort(6870)) .usePlaintext() .build() diff --git a/node-it/src/test/scala/com/wavesplatform/it/api/AsyncHttpApi.scala b/node-it/src/test/scala/com/wavesplatform/it/api/AsyncHttpApi.scala index 0dacbcb6978..d2d26afa7b4 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/api/AsyncHttpApi.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/api/AsyncHttpApi.scala @@ -23,7 +23,7 @@ import com.wavesplatform.lang.v1.FunctionHeader import com.wavesplatform.lang.v1.compiler.Terms import com.wavesplatform.lang.v1.compiler.Terms.FUNCTION_CALL import com.wavesplatform.state.DataEntry.Format -import com.wavesplatform.state.{AssetDistributionPage, DataEntry, EmptyDataEntry, LeaseBalance, Portfolio} +import com.wavesplatform.state.{AssetDistribution, AssetDistributionPage, DataEntry, EmptyDataEntry, LeaseBalance, Portfolio} import com.wavesplatform.transaction.Asset.{IssuedAsset, Waves} import com.wavesplatform.transaction.assets.* import com.wavesplatform.transaction.assets.exchange.{Order, ExchangeTransaction as ExchangeTx} @@ -338,6 +338,11 @@ object AsyncHttpApi extends Assertions { get(url, amountsAsStrings).as[AssetDistributionPage](amountsAsStrings) } + def assetDistribution(asset: String, amountsAsStrings: Boolean = false): Future[AssetDistribution] = { + val req = s"/assets/$asset/distribution" + get(req, amountsAsStrings).as[AssetDistribution](amountsAsStrings) + } + def effectiveBalance(address: String, confirmations: Option[Int] = None, amountsAsStrings: Boolean = false): Future[Balance] = { val maybeConfirmations = confirmations.fold("")(a => s"/$a") get(s"/addresses/effectiveBalance/$address$maybeConfirmations", amountsAsStrings).as[Balance](amountsAsStrings) diff --git a/node-it/src/test/scala/com/wavesplatform/it/api/SyncGrpcApi.scala b/node-it/src/test/scala/com/wavesplatform/it/api/SyncGrpcApi.scala index 18f089a22fe..ce4224cd467 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/api/SyncGrpcApi.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/api/SyncGrpcApi.scala @@ -298,7 +298,7 @@ object SyncGrpcApi extends Assertions { maybeWaitForTransaction(sync(async(n).setScript(sender, script, fee, timestamp, version)), waitForTx) } - def scriptInfo(address: ByteString): ScriptData = { + def scriptInfo(address: ByteString): ScriptResponse = { accounts.getScript(AccountRequest.of(address)) } diff --git a/node-it/src/test/scala/com/wavesplatform/it/api/SyncHttpApi.scala b/node-it/src/test/scala/com/wavesplatform/it/api/SyncHttpApi.scala index 2a090fa609b..e9ab3c5ecb2 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/api/SyncHttpApi.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/api/SyncHttpApi.scala @@ -14,7 +14,7 @@ import com.wavesplatform.it.Node import com.wavesplatform.it.sync.* import com.wavesplatform.lang.script.v1.ExprScript import com.wavesplatform.lang.v1.compiler.Terms -import com.wavesplatform.state.{AssetDistributionPage, DataEntry} +import com.wavesplatform.state.{AssetDistribution, AssetDistributionPage, DataEntry} import com.wavesplatform.transaction.assets.exchange.Order import com.wavesplatform.transaction.lease.{LeaseCancelTransaction, LeaseTransaction} import com.wavesplatform.transaction.smart.InvokeScriptTransaction @@ -261,6 +261,9 @@ object SyncHttpApi extends Assertions with matchers.should.Matchers { ): AssetDistributionPage = sync(async(n).assetDistributionAtHeight(asset, height, limit, maybeAfter, amountsAsStrings)) + def assetDistribution(asset: String): AssetDistribution = + sync(async(n).assetDistribution(asset)) + def broadcastIssue( source: KeyPair, name: String, diff --git a/node-it/src/test/scala/com/wavesplatform/it/api/model.scala b/node-it/src/test/scala/com/wavesplatform/it/api/model.scala index 38f32255fd7..1489ae9c547 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/api/model.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/api/model.scala @@ -444,7 +444,7 @@ object AttachedPayment { case class Invocation(dApp: String, call: Call, payments: Seq[AttachedPayment], stateChanges: StateChangesDetails) object Invocation { implicit val invokationFormat: Reads[Invocation] = new Reads[Invocation] { - override def reads(json: JsValue) = + override def reads(json: JsValue): JsResult[Invocation] = JsSuccess( Invocation( (json \ "dApp").as[String], diff --git a/node-it/src/test/scala/com/wavesplatform/it/asset/IssueReissueBurnAssetSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/asset/IssueReissueBurnAssetSuite.scala index 227c2b13254..355adaa7d9f 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/asset/IssueReissueBurnAssetSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/asset/IssueReissueBurnAssetSuite.scala @@ -250,15 +250,15 @@ class IssueReissueBurnAssetSuite extends BaseFreeSpec { val acc = createDapp(script(simpleReissuableAsset)) val asset = issueValidated(acc, simpleReissuableAsset) invokeScript(acc, "transferAndBurn", assetId = asset, count = 100) - val height1 = nodes.waitForHeightArise() - sender.assetDistributionAtHeight(asset, height1 - 1, 10).items.map { case (a, v) => a.toString -> v } shouldBe Map( + nodes.waitForHeightArise() + sender.assetDistribution(asset).map { case (a, v) => a.toString -> v } shouldBe Map( miner.address -> 100L, acc.toAddress.toString -> (simpleReissuableAsset.quantity - 200) ) reissue(acc, CallableMethod, asset, 400, reissuable = false) invokeScript(acc, "transferAndBurn", assetId = asset, count = 100) - val height2 = nodes.waitForHeightArise() - sender.assetDistributionAtHeight(asset, height2 - 1, 10).items.map { case (a, v) => a.toString -> v } shouldBe Map( + nodes.waitForHeightArise() + sender.assetDistribution(asset).map { case (a, v) => a.toString -> v } shouldBe Map( miner.address -> 200L, acc.toAddress.toString -> simpleReissuableAsset.quantity ) diff --git a/node-it/src/test/scala/com/wavesplatform/it/async/MicroblocksGenerationSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/async/MicroblocksGenerationSuite.scala index f14a72b6c59..c84c1be859b 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/async/MicroblocksGenerationSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/async/MicroblocksGenerationSuite.scala @@ -22,10 +22,7 @@ class MicroblocksGenerationSuite extends BaseFreeSpec with TransferSending { block <- miner.blockAt(2) } yield { block.transactions.size shouldBe maxTxs - - val blockTxs = block.transactions.map(_.id) - val diff = uploadedTxs.map(_.id).toSet -- blockTxs - diff shouldBe empty + block.transactions.map(_.id) should contain theSameElementsAs uploadedTxs.map(_.id).toSet }, 3.minutes ) diff --git a/node-it/src/test/scala/com/wavesplatform/it/async/WideStateGenerationSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/async/WideStateGenerationSuite.scala index 2ef4a1f2e21..a9688616178 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/async/WideStateGenerationSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/async/WideStateGenerationSuite.scala @@ -1,14 +1,13 @@ package com.wavesplatform.it.async -import java.util.concurrent.TimeoutException - import com.typesafe.config.{Config, ConfigFactory} -import com.wavesplatform.it._ -import com.wavesplatform.it.api.AsyncHttpApi._ -import com.wavesplatform.it.util._ +import com.wavesplatform.it.* +import com.wavesplatform.it.api.AsyncHttpApi.* +import com.wavesplatform.it.util.* +import java.util.concurrent.TimeoutException import scala.concurrent.Future.traverse -import scala.concurrent.duration._ +import scala.concurrent.duration.* import scala.concurrent.{Await, Future} @LoadTest @@ -66,15 +65,14 @@ class WideStateGenerationSuite extends BaseFreeSpec with WaitForHeight2 with Tra } yield () val limit = GlobalTimer.instance.schedule(Future.failed(new TimeoutException("Time is out for test")), 18.minutes) - val testWithDumps = Future.firstCompletedOf(Seq(test, limit)).recoverWith { - case e => - for { - _ <- dumpBalances() - dumps <- traverse(nodes)(dumpBlockChain) - } yield { - log.debug(dumps.mkString("Dumps:\n", "\n\n", "\n")) - throw e - } + val testWithDumps = Future.firstCompletedOf(Seq(test, limit)).recoverWith { case e => + for { + _ <- dumpBalances() + dumps <- traverse(nodes)(dumpBlockChain) + } yield { + log.debug(dumps.mkString("Dumps:\n", "\n\n", "\n")) + throw e + } } Await.result(testWithDumps, 18.minutes) @@ -84,12 +82,9 @@ class WideStateGenerationSuite extends BaseFreeSpec with WaitForHeight2 with Tra for { height <- node.height blocks <- node.blockSeq(1, height) - } yield { + } yield withClue(s"all transactions in node") { val txsInBlockchain = blocks.flatMap(_.transactions.map(_.id)) - val diff = txIds -- txsInBlockchain - withClue(s"all transactions in node") { - diff shouldBe empty - } + txIds -- txsInBlockchain shouldBe empty } } @@ -99,7 +94,7 @@ class WideStateGenerationSuite extends BaseFreeSpec with WaitForHeight2 with Tra }.map(_.toMap) .map { r => log.debug(s"""Balances: - |${r.map { case (config, balance) => s"${config.getString("address")} -> $balance" }.mkString("\n")}""".stripMargin) + |${r.map { case (config, balance) => s"${config.getString("address")} -> $balance" }.mkString("\n")}""".stripMargin) r } } diff --git a/node-it/src/test/scala/com/wavesplatform/it/grpc/GrpcReflectionApiSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/grpc/GrpcReflectionApiSuite.scala new file mode 100644 index 00000000000..1de45ede9ce --- /dev/null +++ b/node-it/src/test/scala/com/wavesplatform/it/grpc/GrpcReflectionApiSuite.scala @@ -0,0 +1,41 @@ +package com.wavesplatform.it.grpc + +import com.typesafe.config.Config +import com.wavesplatform.it.NodeConfigs +import com.wavesplatform.it.NodeConfigs.Default +import com.wavesplatform.it.sync.grpc.GrpcBaseTransactionSuite +import io.grpc.{CallOptions, ManagedChannelBuilder} +import io.grpc.reflection.v1alpha.ServerReflectionGrpc.getServerReflectionInfoMethod +import io.grpc.reflection.v1alpha.ServerReflectionRequest +import io.grpc.stub.ClientCalls + +import scala.util.Try + +class GrpcReflectionApiSuite extends GrpcBaseTransactionSuite { + override protected def nodeConfigs: Seq[Config] = + NodeConfigs + .Builder(Default, 1, Seq()) + .overrideBase(_.quorum(0)) + .overrideBase(_.raw("waves.extensions = [com.wavesplatform.api.grpc.GRPCServerExtension\ncom.wavesplatform.events.BlockchainUpdates]")) + .buildNonConflicting() + + test("successful getServerReflectionInfo call for BU") { + val buChannel = ManagedChannelBuilder + .forAddress(nodes.head.nodeApiEndpoint.getHost, nodes.head.nodeExternalPort(6881)) + .usePlaintext() + .build() + val call = buChannel.newCall(getServerReflectionInfoMethod, CallOptions.DEFAULT) + val request = ServerReflectionRequest.newBuilder().setFileContainingSymbol("waves.events.grpc.BlockchainUpdatesApi").build() + val result = Try(ClientCalls.blockingUnaryCall(call, request)) + result.isSuccess shouldBe true + result.get.hasFileDescriptorResponse shouldBe true + } + + test("successful getServerReflectionInfo call for GRPC methods") { + val call = nodes.head.grpcChannel.newCall(getServerReflectionInfoMethod, CallOptions.DEFAULT) + val request = ServerReflectionRequest.newBuilder().setFileContainingSymbol("waves.node.grpc.BlocksApi").build() + val result = Try(ClientCalls.blockingUnaryCall(call, request)) + result.isSuccess shouldBe true + result.get.hasFileDescriptorResponse shouldBe true + } +} diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/AssetDistributionSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/AssetDistributionSuite.scala index 2355523ffa5..d8c99c2c072 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/AssetDistributionSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/AssetDistributionSuite.scala @@ -8,6 +8,8 @@ import com.wavesplatform.state.AssetDistributionPage import com.wavesplatform.transaction.transfer.MassTransferTransaction import org.scalatest.CancelAfterFailure +import scala.concurrent.duration.* + class AssetDistributionSuite extends BaseTransactionSuite with CancelAfterFailure { lazy val node: Node = nodes.head @@ -23,7 +25,7 @@ class AssetDistributionSuite extends BaseTransactionSuite with CancelAfterFailur nodes.waitForHeightArise() - val issueTx = node.issue(issuer, "TestCoin", "no description", issueAmount, 8, false, issueFee, waitForTx = true).id + val issueTx = node.issue(issuer, "TestCoin", "no description", issueAmount, 8, reissuable = false, issueFee, waitForTx = true).id node.massTransfer( issuer, @@ -47,6 +49,8 @@ class AssetDistributionSuite extends BaseTransactionSuite with CancelAfterFailur val issuerAssetDis = assetDis.view.filterKeys(_ == issuer.toAddress).values + assetDis should be equals node.assetDistribution(issueTx) + issuerAssetDis.size shouldBe 1 issuerAssetDis.head shouldBe (issueAmount - addresses.length * transferAmount) @@ -68,10 +72,34 @@ class AssetDistributionSuite extends BaseTransactionSuite with CancelAfterFailur ) } + test("'Asset distribution' works properly") { + val receivers = for (i <- 0 until 10) yield KeyPair(s"receiver#$i".getBytes("UTF-8")) + + val issueTx = node.issue(issuer, "TestCoin#2", "no description", issueAmount, 8, reissuable = false, issueFee, waitForTx = true).id + + node + .massTransfer( + issuer, + receivers.map(rc => MassTransferTransaction.Transfer(rc.toAddress.toString, 10)).toList, + minFee + minFee * receivers.length, + assetId = Some(issueTx), + waitForTx = true + ) + + nodes.waitForHeightArise() + + val distribution = node.assetDistribution(issueTx) + + distribution.size shouldBe (receivers.size + 1) + distribution(issuer.toAddress) shouldBe (issueAmount - 10 * receivers.length) + + assert(receivers.forall(rc => distribution(rc.toAddress) == 10), "Distribution correct") + } + test("Correct last page and entry count") { val receivers = for (i <- 0 until 50) yield KeyPair(s"receiver#$i".getBytes("UTF-8")) - val issueTx = node.issue(issuer, "TestCoin#2", "no description", issueAmount, 8, false, issueFee, waitForTx = true).id + val issueTx = node.issue(issuer, "TestCoin#2", "no description", issueAmount, 8, reissuable = false, issueFee, waitForTx = true).id node .massTransfer( @@ -96,6 +124,24 @@ class AssetDistributionSuite extends BaseTransactionSuite with CancelAfterFailur assert(pages.map(_.items.size).sum == 51) } + test("Unlimited list") { + val assetId = node.issue(issuer, "TestCoin#2", "no description", issueAmount, 8, reissuable = false, issueFee, waitForTx = true).id + + val receivers = for (i <- 0 until 2000) yield KeyPair(s"receiver#$i".getBytes("UTF-8")) + + val transfers = receivers.map { r => MassTransferTransaction.Transfer(r.toAddress.toString, 10L) }.toList + + transfers.grouped(100).foreach { t => + node.massTransfer(issuer, t, minFee + t.length * minFee, assetId = Some(assetId)) + } + + node.waitFor("empty utx")(_.utxSize, (_: Int) == 0, 1 second) + nodes.waitForHeightArise() + + val list = node.assetDistribution(assetId) + list should have size 2001 + } + def distributionPages(asset: String, height: Int, limit: Int): List[AssetDistributionPage] = { def _load(acc: List[AssetDistributionPage], maybeAfter: Option[String]): List[AssetDistributionPage] = { val page = node.assetDistributionAtHeight(asset, height, limit, maybeAfter) diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/BlacklistTestSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/BlacklistTestSuite.scala index bf218dff515..af0d96d3763 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/BlacklistTestSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/BlacklistTestSuite.scala @@ -1,11 +1,11 @@ package com.wavesplatform.it.sync import com.typesafe.config.Config -import com.wavesplatform.it.api.SyncHttpApi._ -import com.wavesplatform.it.api._ +import com.wavesplatform.it.api.* +import com.wavesplatform.it.api.SyncHttpApi.* import com.wavesplatform.it.{BaseFreeSpec, NodeConfigs} -import scala.concurrent.duration._ +import scala.concurrent.duration.* class BlacklistTestSuite extends BaseFreeSpec { @@ -20,7 +20,7 @@ class BlacklistTestSuite extends BaseFreeSpec { private def otherNodes = dockerNodes().init "primary node should blacklist other nodes" in { - otherNodes.foreach(n => primaryNode.blacklist(n.containerNetworkAddress)) + otherNodes.foreach(n => primaryNode.blacklist(n.networkAddress)) val expectedBlacklistedPeers = nodes.size - 1 diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/activation/AcceptFailedScriptActivationSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/activation/AcceptFailedScriptActivationSuite.scala index e1c40267844..78100e76a0e 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/activation/AcceptFailedScriptActivationSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/activation/AcceptFailedScriptActivationSuite.scala @@ -300,7 +300,7 @@ class AcceptFailedScriptActivationSuite extends BaseTransactionSuite with NTPTim smartMatcherFee, 100L, ts, - ts + Order.MaxLiveTime, + ts + 2.days.toMillis, smartMatcherFee ) .explicitGet() @@ -314,7 +314,7 @@ class AcceptFailedScriptActivationSuite extends BaseTransactionSuite with NTPTim smartMatcherFee, 100L, ts, - ts + Order.MaxLiveTime, + ts + 2.days.toMillis, smartMatcherFee ) .explicitGet() @@ -375,7 +375,7 @@ class AcceptFailedScriptActivationSuite extends BaseTransactionSuite with NTPTim 10L, 100L, ts, - ts + Order.MaxLiveTime, + ts + 2.days.toMillis, smartMatcherFee, matcherFeeAssetId = IssuedAsset(ByteStr.decodeBase58(feeAsset).get) ) @@ -390,7 +390,7 @@ class AcceptFailedScriptActivationSuite extends BaseTransactionSuite with NTPTim 10L, 100L, ts, - ts + Order.MaxLiveTime, + ts + 2.days.toMillis, smartMatcherFee, matcherFeeAssetId = IssuedAsset(ByteStr.decodeBase58(feeAsset).get) ) diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/FailedTransactionGrpcSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/FailedTransactionGrpcSuite.scala index dbc782c9b13..f659f1e99ce 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/FailedTransactionGrpcSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/FailedTransactionGrpcSuite.scala @@ -121,31 +121,6 @@ class FailedTransactionGrpcSuite extends GrpcBaseTransactionSuite with FailedTra sender.setScript(contract, Right(Some(script)), setScriptFee, waitForTx = true) } - test("InvokeScriptTransaction: insufficient action fees propagates failed transaction") { - val invokeFee = 0.005.waves - val setAssetScriptMinFee = setAssetScriptFee + smartFee * 2 - val priorityFee = setAssetScriptMinFee + invokeFee - - updateAssetScript(result = true, smartAsset, contract, setAssetScriptMinFee) - - for (typeName <- Seq("transfer", "issue", "reissue", "burn")) { - updateTikTok("unknown", setAssetScriptMinFee) - - overflowBlock() - sendTxsAndThenPriorityTx( - _ => - sender - .broadcastInvokeScript( - caller, - Recipient().withPublicKeyHash(contractAddr), - Some(FUNCTION_CALL(FunctionHeader.User("tikTok"), List.empty)), - fee = invokeFee - ), - () => updateTikTok(typeName, priorityFee, waitForTx = false) - )((txs, _) => assertFailedTxs(txs)) - } - } - test("InvokeScriptTransaction: invoke script error in payment asset propagates failed transaction") { val invokeFee = 0.005.waves + smartFee val setAssetScriptMinFee = setAssetScriptFee + smartFee diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/InvokeScriptTransactionGrpcSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/InvokeScriptTransactionGrpcSuite.scala index 2a6c9409c67..6bbe813c69e 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/InvokeScriptTransactionGrpcSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/InvokeScriptTransactionGrpcSuite.scala @@ -107,6 +107,7 @@ class InvokeScriptTransactionGrpcSuite extends GrpcBaseTransactionSuite { val scriptInfo = sender.scriptInfo(firstAddress) PBTransactions.toVanillaScript(scriptInfo.scriptBytes) shouldBe Some(script) + scriptInfo.publicKey shouldBe ByteString.copyFrom(firstAcc.publicKey.arr) } test("dApp caller invokes a nested function on a dApp") { diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/IssueTransactionGrpcSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/IssueTransactionGrpcSuite.scala index 111372e0f7e..017c70c43fd 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/IssueTransactionGrpcSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/IssueTransactionGrpcSuite.scala @@ -183,7 +183,7 @@ class IssueTransactionGrpcSuite extends GrpcBaseTransactionSuite with NTPTime wi "~!|#$%^&*()_+=\";:/?><|\\][{}" ) - forAll(invalid_assets_names) { invalidAssetName: String => + forAll(invalid_assets_names) { (invalidAssetName: String) => test(s"Not able to create asset named $invalidAssetName") { assertGrpcError( sender.broadcastIssue(issuer, invalidAssetName, someAssetAmount, 2, reissuable = false, issueFee), diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/network/NetworkUniqueConnectionsTestSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/network/NetworkUniqueConnectionsTestSuite.scala index bcfb4edb5a9..6ae9b295499 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/network/NetworkUniqueConnectionsTestSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/network/NetworkUniqueConnectionsTestSuite.scala @@ -1,17 +1,17 @@ package com.wavesplatform.it.sync.network import com.typesafe.config.{Config, ConfigFactory} -import com.wavesplatform.it.api.SyncHttpApi._ +import com.wavesplatform.it.api.SyncHttpApi.* import com.wavesplatform.it.{DockerBased, Node, NodeConfigs, Nodes} import com.wavesplatform.utils.ScorexLogging -import org.scalatest._ +import org.scalatest.* -import scala.concurrent._ -import scala.concurrent.duration._ +import scala.concurrent.* +import scala.concurrent.duration.* import scala.util.{Failure, Success, Try} class NetworkUniqueConnectionsTestSuite extends freespec.AnyFreeSpec with matchers.should.Matchers with DockerBased with ScorexLogging with Nodes { - import NetworkUniqueConnectionsTestSuite._ + import NetworkUniqueConnectionsTestSuite.* "nodes should up and connect with each other" in { val firstNode = docker.startNode(FirstNodeConfig, autoConnect = false) @@ -25,8 +25,8 @@ class NetworkUniqueConnectionsTestSuite extends freespec.AnyFreeSpec with matche // Helps to do an incoming connection: second -> first (1) val peersConfig = ConfigFactory.parseString( s"""waves.network.known-peers = [ - | "${firstNode.containerNetworkAddress.getHostName}:${firstNode.containerNetworkAddress.getPort}" - |]""".stripMargin + | "${firstNode.networkAddress.getHostName}:${firstNode.networkAddress.getPort}" + |]""".stripMargin ) docker.startNode(peersConfig.withFallback(SecondNodeConfig), autoConnect = false) @@ -35,7 +35,7 @@ class NetworkUniqueConnectionsTestSuite extends freespec.AnyFreeSpec with matche firstNode.waitForPeers(1) // Outgoing connection: first -> second (2) - firstNode.connect(secondNode.containerNetworkAddress) + firstNode.connect(secondNode.networkAddress) withClue("Should fail with TimeoutException, because the connectionAttempt should fail") { Try(firstNode.waitForPeers(2, 30.seconds)) match { diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/Ride4DAppsActivationTestSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/Ride4DAppsActivationTestSuite.scala index 4245484a3b3..d5342a2e685 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/Ride4DAppsActivationTestSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/Ride4DAppsActivationTestSuite.scala @@ -4,16 +4,16 @@ import com.typesafe.config.{Config, ConfigFactory} import com.wavesplatform.common.state.ByteStr import com.wavesplatform.common.utils.EitherExt2 import com.wavesplatform.it.NodeConfigs -import com.wavesplatform.it.api.SyncHttpApi._ -import com.wavesplatform.it.sync._ +import com.wavesplatform.it.api.SyncHttpApi.* +import com.wavesplatform.it.sync.* import com.wavesplatform.it.transactions.BaseTransactionSuite import com.wavesplatform.lang.v1.estimator.v2.ScriptEstimatorV2 -import com.wavesplatform.test._ -import com.wavesplatform.transaction.Asset +import com.wavesplatform.test.* +import com.wavesplatform.transaction.{Asset, AssetIdLength} import com.wavesplatform.transaction.smart.script.ScriptCompiler import org.scalatest.CancelAfterFailure -import scala.concurrent.duration._ +import scala.concurrent.duration.* class Ride4DAppsActivationTestSuite extends BaseTransactionSuite with CancelAfterFailure { private val estimator = ScriptEstimatorV2 @@ -113,7 +113,7 @@ class Ride4DAppsActivationTestSuite extends BaseTransactionSuite with CancelAfte test("can't set script with user function to asset before Ride4DApps activation") { assertBadRequestAndMessage( sender.setAssetScript( - Asset.IssuedAsset(ByteStr("Test".getBytes("UTF-8"))).id.toString, + Asset.IssuedAsset(ByteStr.fill(AssetIdLength)(1)).id.toString, smartAcc, issueFee, Some(scriptV2) diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/freecall/InvokeExpressionGrpcSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/freecall/InvokeExpressionGrpcSuite.scala index bb506f6df7e..1e539843c43 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/freecall/InvokeExpressionGrpcSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/freecall/InvokeExpressionGrpcSuite.scala @@ -21,7 +21,8 @@ import org.scalatest.{Assertion, CancelAfterFailure} class InvokeExpressionGrpcSuite extends GrpcBaseTransactionSuite with CancelAfterFailure { override protected def nodeConfigs: Seq[Config] = NodeConfigs - .Builder(Default, 2, Seq.empty) + .Builder(Default, 1, Seq.empty) + .overrideBase(_.quorum(0)) .overrideBase(_.preactivatedFeatures((ContinuationTransaction.id, 1))) .buildNonConflicting() diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/AliasTransactionSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/AliasTransactionSuite.scala index bf705ee838b..84120ef17c1 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/AliasTransactionSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/AliasTransactionSuite.scala @@ -5,6 +5,7 @@ import com.typesafe.config.Config import scala.util.{Random, Try} import com.wavesplatform.account.{AddressScheme, KeyPair} +import com.wavesplatform.api.http.ApiError.WrongJson import com.wavesplatform.features.BlockchainFeatures.RideV6 import com.wavesplatform.it.NodeConfigs import com.wavesplatform.it.NodeConfigs.Default @@ -120,7 +121,7 @@ class AliasTransactionSuite extends BaseTransactionSuite with TableDrivenPropert ("aliasName", "message"), ("", "Alias '' length should be between 4 and 30"), ("abc", "Alias 'abc' length should be between 4 and 30"), - (null, "failed to parse json message"), + (null, WrongJson.WrongJsonDataMessage), ("morethen_thirtycharactersinline", "Alias 'morethen_thirtycharactersinline' length should be between 4 and 30"), ("~!|#$%^&*()_+=\";:/?><|\\][{}", "Alias should contain only following characters: -.0123456789@_abcdefghijklmnopqrstuvwxyz"), ("multilnetest\ntest", "Alias should contain only following characters: -.0123456789@_abcdefghijklmnopqrstuvwxyz"), @@ -143,7 +144,7 @@ class AliasTransactionSuite extends BaseTransactionSuite with TableDrivenPropert val aliasFee = createAlias(thirdKeyPair, thirdAddressAlias) val aliasFull = fullAliasByAddress(thirdAddress, thirdAddressAlias) - //lease maximum value, to pass next thirdAddress + // lease maximum value, to pass next thirdAddress val leasingAmount = balance1 - minFee - 0.5.waves val leasingTx = sender.lease(firstKeyPair, aliasFull, leasingAmount, minFee).id @@ -154,7 +155,7 @@ class AliasTransactionSuite extends BaseTransactionSuite with TableDrivenPropert } - //previous test should not be commented to run this one + // previous test should not be commented to run this one test("Not able to create alias when insufficient funds") { for (v <- aliasTxSupportedVersions) { val balance = miner.accountBalances(firstAddress)._1 @@ -177,7 +178,15 @@ class AliasTransactionSuite extends BaseTransactionSuite with TableDrivenPropert ) val kp = KeyPair(Longs.toByteArray(Random.nextLong())) - val cat = CreateAliasTransaction(3.toByte, notMiner.publicKey, "abc12345", TxPositiveAmount.unsafeFrom(0.005.waves), System.currentTimeMillis(), Proofs.empty, AddressScheme.current.chainId) + val cat = CreateAliasTransaction( + 3.toByte, + notMiner.publicKey, + "abc12345", + TxPositiveAmount.unsafeFrom(0.005.waves), + System.currentTimeMillis(), + Proofs.empty, + AddressScheme.current.chainId + ) val signedCreateAlias = cat.copy( proofs = cat.signWith(notMiner.keyPair.privateKey).proofs.proofs ++ cat.signWith(kp.privateKey).proofs.proofs ) diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/DataTransactionSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/DataTransactionSuite.scala index 0c2d5a038a4..b8c7286edb9 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/DataTransactionSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/DataTransactionSuite.scala @@ -3,23 +3,23 @@ package com.wavesplatform.it.sync.transactions import com.google.common.primitives.Ints import com.typesafe.config.Config import com.wavesplatform.account.{AddressScheme, KeyPair} -import com.wavesplatform.api.http.ApiError.{CustomValidationError, TooBigArrayAllocation} +import com.wavesplatform.api.http.ApiError.{CustomValidationError, TooBigArrayAllocation, WrongJson} import com.wavesplatform.common.state.ByteStr import com.wavesplatform.common.utils.{Base58, EitherExt2} import com.wavesplatform.it.NodeConfigs -import com.wavesplatform.it.api.SyncHttpApi._ +import com.wavesplatform.it.api.SyncHttpApi.* import com.wavesplatform.it.api.{TransactionInfo, UnexpectedStatusCodeException} -import com.wavesplatform.it.sync.{calcDataFee, minFee, _} +import com.wavesplatform.it.sync.{calcDataFee, minFee, *} import com.wavesplatform.it.transactions.BaseTransactionSuite -import com.wavesplatform.test._ +import com.wavesplatform.test.* import com.wavesplatform.lang.v1.estimator.ScriptEstimatorV1 import com.wavesplatform.state.{BinaryDataEntry, BooleanDataEntry, DataEntry, EmptyDataEntry, IntegerDataEntry, StringDataEntry} import com.wavesplatform.transaction.smart.script.ScriptCompiler import com.wavesplatform.transaction.{DataTransaction, Proofs, TxVersion} import org.scalatest.{Assertion, Assertions, EitherValues} -import play.api.libs.json._ +import play.api.libs.json.* -import scala.concurrent.duration._ +import scala.concurrent.duration.* import scala.util.{Failure, Random, Try} class DataTransactionSuite extends BaseTransactionSuite with EitherValues { @@ -368,7 +368,7 @@ class DataTransactionSuite extends BaseTransactionSuite with EitherValues { def id(obj: JsObject): String = obj.value("id").as[String] val noProof = request - "proofs" - assertBadRequestAndResponse(sender.postJson("/transactions/broadcast", noProof), "failed to parse json message.*proofs.*missing") + assertBadRequestAndResponse(sender.postJson("/transactions/broadcast", noProof), s"${WrongJson.WrongJsonDataMessage}.*proofs.*missing") nodes.foreach(_.ensureTxDoesntExist(id(noProof))) val badProof = request ++ Json.obj("proofs" -> Seq(Base58.encode(Array.fill(64)(Random.nextInt().toByte)))) diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/FailedTransactionSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/FailedTransactionSuite.scala index 067c5d12378..1c086beb237 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/FailedTransactionSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/FailedTransactionSuite.scala @@ -3,15 +3,12 @@ package com.wavesplatform.it.sync.transactions import com.typesafe.config.Config import com.wavesplatform.api.http.ApiError.TransactionNotAllowedByAssetScript import com.wavesplatform.api.http.DebugMessage -import com.wavesplatform.common.state.ByteStr import com.wavesplatform.common.utils.EitherExt2 import com.wavesplatform.it.api.SyncHttpApi.* -import com.wavesplatform.it.api.{StateChanges, TransactionStatus} import com.wavesplatform.it.sync.* import com.wavesplatform.it.transactions.BaseTransactionSuite -import com.wavesplatform.lang.v1.compiler.Terms import com.wavesplatform.lang.v1.estimator.v3.ScriptEstimatorV3 -import com.wavesplatform.state.{BooleanDataEntry, StringDataEntry} +import com.wavesplatform.state.StringDataEntry import com.wavesplatform.test.* import com.wavesplatform.transaction.assets.exchange.AssetPair import com.wavesplatform.transaction.smart.script.ScriptCompiler @@ -118,52 +115,6 @@ class FailedTransactionSuite extends BaseTransactionSuite with CancelAfterFailur sender.setScript(contract, Some(script), setScriptFee, waitForTx = true).id } - test("InvokeScriptTransaction: insufficient action fees propagates failed transaction") { - val invokeFee = 0.005.waves - val setAssetScriptMinFee = setAssetScriptFee + smartFee - val priorityFee = setAssetScriptMinFee + invokeFee - - updateAssetScript(result = true, smartAsset, contract, setAssetScriptMinFee) - - for (typeName <- Seq("transfer", "issue", "reissue", "burn")) { - updateTikTok("unknown", setAssetScriptMinFee) - - val prevBalance = sender.balance(caller.toAddress.toString).balance - val prevAssetBalance = sender.assetBalance(contractAddress, smartAsset) - val prevAssets = sender.assetsBalance(contractAddress) - - overflowBlock() - sendTxsAndThenPriorityTx( - _ => sender.invokeScript(caller, contractAddress, Some("tikTok"), fee = invokeFee)._1.id, - () => updateTikTok(typeName, priorityFee, waitForTx = false) - ) { (txs, priorityTx) => - logPriorityTx(priorityTx) - - val failed = assertFailedTxs(txs) - - sender.balance(caller.toAddress.toString).balance shouldBe prevBalance - txs.size * invokeFee - sender.assetBalance(contractAddress, smartAsset) shouldBe prevAssetBalance - sender.assetsBalance(contractAddress).balances should contain theSameElementsAs prevAssets.balances - - val (scriptInvokedInfo, issuedInfo) = - if (typeName == "issue") - ("", " with 1 assets issued") - else - (" with 1 total scripts invoked", "") - - val minFee = if (typeName == "issue") invokeFee + issueFee else invokeFee + smartFee - val text = s"Fee in WAVES for InvokeScriptTransaction ($invokeFee in WAVES)" + - s"$scriptInvokedInfo$issuedInfo does not exceed minimal value of $minFee WAVES." - - failed.foreach { s => - checkStateChange(sender.stateChanges(s.id), 2, text) - } - - failed - } - } - } - test("InvokeScriptTransaction: reject transactions if account script failed") { val invokeFee = 0.005.waves val setAssetScriptMinFee = setAssetScriptFee + smartFee @@ -212,50 +163,6 @@ class FailedTransactionSuite extends BaseTransactionSuite with CancelAfterFailur } } - test("InvokeScriptTransaction: transactionHeightById returns only succeed transactions") { - val invokeFee = 0.005.waves + smartFee - val setAssetScriptMinFee = setAssetScriptFee + smartFee - val priorityFee = setAssetScriptMinFee + invokeFee - - updateAccountScript(None, caller, setScriptFee + smartFee) - updateTikTok("reissue", setAssetScriptMinFee) - updateAssetScript(result = true, smartAsset, contract, setAssetScriptMinFee) - waitForEmptyUtx() - overflowBlock() - - val failedTxs = sendTxsAndThenPriorityTx( - _ => sender.invokeScript(caller, contractAddress, Some("tikTok"), fee = invokeFee)._1.id, - () => updateAssetScript(result = false, smartAsset, contract, priorityFee) - ) { (txs, priorityTx) => - logPriorityTx(priorityTx) - assertFailedTxs(txs) - } - - checkTransactionHeightById(failedTxs) - } - - test("ExchangeTransaction: transaction validates as failed when asset script fails") { - val Precondition(amountAsset, priceAsset, buyFeeAsset, sellFeeAsset) = - exchangePreconditions( - Some(ScriptCompiler.compile("true", ScriptEstimatorV3(fixOverflow = true, overhead = false)).explicitGet()._1.bytes().base64) - ) - - val assetPair = AssetPair.createAssetPair(amountAsset, priceAsset).get - val fee = 0.003.waves + 4 * smartFee - val sellMatcherFee = fee / 100000L - val buyMatcherFee = fee / 100000L - - val (assetScript, _) = - ScriptCompiler.compile("if true then throw(\"error\") else false", ScriptEstimatorV3(fixOverflow = true, overhead = false)).explicitGet() - val scriptTx = sender.setAssetScript(priceAsset, buyerAddress, script = Some(assetScript.bytes().base64)) - nodes.waitForHeightAriseAndTxPresent(scriptTx.id) - - val tx = mkExchange(buyer, seller, matcher, assetPair, fee, buyFeeAsset, sellFeeAsset, buyMatcherFee, sellMatcherFee) - val result = sender.signedValidate(tx.json()) - (result \ "valid").as[Boolean] shouldBe false - (result \ "error").as[String] should include("not allowed by script of the asset") - } - test("ExchangeTransaction: invalid exchange tx when asset script fails on broadcast") { val init = Seq( sender.setScript(firstKeyPair, None, setScriptFee + smartFee).id, @@ -309,38 +216,6 @@ class FailedTransactionSuite extends BaseTransactionSuite with CancelAfterFailur private def waitForTxs(txs: Seq[String]): Unit = nodes.waitFor("preconditions", 500.millis)(_.transactionStatus(txs).forall(_.status == "confirmed"))(_.forall(identity)) - private def checkStateChange(info: StateChanges, code: Int, text: String, strict: Boolean = false): Unit = { - info.stateChanges shouldBe defined - info.stateChanges.get.issues.size shouldBe 0 - info.stateChanges.get.reissues.size shouldBe 0 - info.stateChanges.get.burns.size shouldBe 0 - info.stateChanges.get.error shouldBe defined - info.stateChanges.get.error.get.code shouldBe code - if (strict) - info.stateChanges.get.error.get.text shouldBe text - else - info.stateChanges.get.error.get.text should include(text) - } - - private def checkTransactionHeightById(failedTxs: Seq[TransactionStatus]): Unit = { - val defineTxs = failedTxs.map { status => - sender - .invokeScript( - caller, - contractAddress, - Some("defineTxHeight"), - List(Terms.CONST_BYTESTR(ByteStr.decodeBase58(status.id).get).explicitGet()), - fee = invokeFee - ) - ._1 - .id - } - - waitForTxs(defineTxs) - - failedTxs.foreach(status => sender.getDataByKey(contractAddress, status.id) shouldBe BooleanDataEntry(status.id, value = false)) - } - private def exchangePreconditions(initScript: Option[String]): Precondition = { val transfers = Seq( sender.transfer(sender.keyPair, sellerAddress.toAddress.toString, 100.waves).id, diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/IssueTransactionSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/IssueTransactionSuite.scala index afc0441bb0f..0f14dbf4340 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/IssueTransactionSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/IssueTransactionSuite.scala @@ -178,7 +178,7 @@ class IssueTransactionSuite extends BaseTransactionSuite with TableDrivenPropert "~!|#$%^&*()_+=\";:/?><|\\][{}" ) - forAll(invalid_assets_names) { assetName: String => + forAll(invalid_assets_names) { (assetName: String) => test(s"Not able to create asset named $assetName") { for (v <- issueTxSupportedVersions) { assertApiError( diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/MassTransferTransactionSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/MassTransferTransactionSuite.scala index 4f2a823fbd4..4813573fc8b 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/MassTransferTransactionSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/MassTransferTransactionSuite.scala @@ -2,6 +2,7 @@ package com.wavesplatform.it.sync.transactions import com.google.protobuf.ByteString import com.wavesplatform.account.{Address, AddressScheme, Alias} +import com.wavesplatform.api.http.ApiError.WrongJson import com.wavesplatform.api.http.requests.{MassTransferRequest, SignedMassTransferRequest} import com.wavesplatform.common.state.ByteStr import com.wavesplatform.common.utils.EitherExt2 @@ -262,7 +263,7 @@ class MassTransferTransactionSuite extends BaseTransactionSuite { def id(obj: JsObject) = obj.value("id").as[String] val noProof = signedMassTransfer - "proofs" - assertBadRequestAndResponse(sender.postJson("/transactions/broadcast", noProof), "failed to parse json message.*proofs.*missing") + assertBadRequestAndResponse(sender.postJson("/transactions/broadcast", noProof), s"${WrongJson.WrongJsonDataMessage}.*proofs.*missing") nodes.foreach(_.ensureTxDoesntExist(id(noProof))) val badProof = signedMassTransfer ++ Json.obj("proofs" -> Seq(fakeSignature.toString)) diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/SetAssetScriptTransactionSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/SetAssetScriptTransactionSuite.scala index ba2d763c855..25c3e4b0a4c 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/SetAssetScriptTransactionSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/SetAssetScriptTransactionSuite.scala @@ -98,11 +98,11 @@ class SetAssetScriptTransactionSuite extends BaseTransactionSuite { ) assertApiError( broadcastSetAssetScriptJson(assetWOScript, firstKeyPair, setAssetScriptFee, version = v), - AssertiveApiError(WrongJson.Id, "failed to parse json message", matchMessage = true) + AssertiveApiError(WrongJson.Id, WrongJson.WrongJsonDataMessage, matchMessage = true) ) assertApiError( broadcastSetAssetScriptJson(assetWOScript, firstKeyPair, setAssetScriptFee, Some(""), version = v), - AssertiveApiError(WrongJson.Id, "failed to parse json message", matchMessage = true) + AssertiveApiError(WrongJson.Id, WrongJson.WrongJsonDataMessage, matchMessage = true) ) miner.assertBalances(firstAddress, balance, eff) } @@ -158,7 +158,7 @@ class SetAssetScriptTransactionSuite extends BaseTransactionSuite { } assertApiError(broadcastSetAssetScriptJson(assetWAnotherOwner, secondKeyPair, setAssetScriptFee, Some(""), version = v)) { error => error.id shouldBe WrongJson.Id - error.message shouldBe "failed to parse json message" + error.message shouldBe WrongJson.WrongJsonDataMessage } } } @@ -180,10 +180,10 @@ class SetAssetScriptTransactionSuite extends BaseTransactionSuite { test("sender's waves balance is decreased by fee") { val script2 = ScriptCompiler( s""" - |match tx { - | case _: SetAssetScriptTransaction => true - | case _ => false - |} + |match tx { + | case _: SetAssetScriptTransaction => true + | case _ => false + |} """.stripMargin, isAssetScript = true, estimator @@ -253,7 +253,7 @@ class SetAssetScriptTransactionSuite extends BaseTransactionSuite { ), ( sastx(assetId = IssuedAsset(ByteStr.decodeBase58("9ekQuYn92natMnMq8KqeGK3Nn7cpKd3BvPEGgD6fFyyz9ekQuYn92natMnMq8").get)), - AssertiveApiError(WrongJson.Id, "failed to parse json", StatusCodes.BadRequest, true) + AssertiveApiError(WrongJson.Id, WrongJson.WrongJsonDataMessage, StatusCodes.BadRequest, true) ), ( sastx(assetId = IssuedAsset(ByteStr.decodeBase58("9ekQuYn92natMnMq8KqeGK3Nn7cpKd3BvPEGgD6fFyyz").get)), @@ -290,7 +290,7 @@ class SetAssetScriptTransactionSuite extends BaseTransactionSuite { val noProof = request - "proofs" assertApiError(sender.postJson("/transactions/broadcast", noProof)) { error => - error.message should include regex "failed to parse json message" + error.message should include regex WrongJson.WrongJsonDataMessage val validationErrors = (error.json \ "validationErrors" \ "obj.proofs").as[JsArray].value.flatMap(json => (json \ "msg").as[List[String]]) validationErrors should contain("error.path.missing") @@ -313,10 +313,10 @@ class SetAssetScriptTransactionSuite extends BaseTransactionSuite { test("try to update script to null") { for (v <- setAssetScrTxSupportedVersions) { assertApiError(broadcastSetAssetScriptJson(assetWScript, firstKeyPair, setAssetScriptFee, version = v)) { error => - error.message should include regex "failed to parse json message" + error.message should include regex WrongJson.WrongJsonDataMessage } assertApiError(broadcastSetAssetScriptJson(assetWScript, firstKeyPair, setAssetScriptFee, Some(""), version = v)) { error => - error.message should include regex "failed to parse json message" + error.message should include regex WrongJson.WrongJsonDataMessage } } } @@ -401,7 +401,7 @@ class SetAssetScriptTransactionSuite extends BaseTransactionSuite { nodes.waitForHeightAriseAndTxPresent(tx) - //try to change unchangeable script + // try to change unchangeable script val nonIssuerUnsignedTx2 = SetAssetScriptTransaction( version = v, accountA.publicKey, diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/SignAndBroadcastApiSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/SignAndBroadcastApiSuite.scala index f4aa5d312b0..e7ec0682e0f 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/SignAndBroadcastApiSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/SignAndBroadcastApiSuite.scala @@ -2,6 +2,7 @@ package com.wavesplatform.it.sync.transactions import com.typesafe.config.Config import com.wavesplatform.account.{AddressScheme, PublicKey} +import com.wavesplatform.api.http.ApiError.WrongJson import com.wavesplatform.api.http.requests.TransferRequest import com.wavesplatform.common.state.ByteStr import com.wavesplatform.common.utils.{Base58, EitherExt2} @@ -59,9 +60,9 @@ class SignAndBroadcastApiSuite extends BaseTransactionSuite with NTPTime with Be for (v <- supportedVersions) { val json = Json.obj("type" -> CreateAliasTransaction.typeId, "sender" -> firstAddress, "alias" -> "alias", "fee" -> 100000) val js = if (Option(v).isDefined) json ++ Json.obj("version" -> v) else json - assertSignBadJson(js - "type", "failed to parse json message") + assertSignBadJson(js - "type", WrongJson.WrongJsonDataMessage) assertSignBadJson(js + ("type" -> JsNumber(-100)), "Bad transaction type") - assertSignBadJson(js - "alias", "failed to parse json message") + assertSignBadJson(js - "alias", WrongJson.WrongJsonDataMessage) } val obsoleteTx = @@ -78,7 +79,7 @@ class SignAndBroadcastApiSuite extends BaseTransactionSuite with NTPTime with Be "fee" -> 100000, "attachment" -> "W" * 524291 ) - assertSignBadJson(bigBaseTx, "failed to parse json message") + assertSignBadJson(bigBaseTx, WrongJson.WrongJsonDataMessage) } test("/transaction/calculateFee should handle coding size limit") { @@ -92,7 +93,7 @@ class SignAndBroadcastApiSuite extends BaseTransactionSuite with NTPTime with Be "amount" -> 1, "assetId" -> "W" * 524291 ) - assertBadRequestAndMessage(sender.calculateFee(json).feeAmount, "failed to parse json message") + assertBadRequestAndMessage(sender.calculateFee(json).feeAmount, WrongJson.WrongJsonDataMessage) } } @@ -137,10 +138,10 @@ class SignAndBroadcastApiSuite extends BaseTransactionSuite with NTPTime with Be assertBroadcastBadJson(jsonV2, "Proof doesn't validate") for (j <- List(jsonV1, jsonV2)) { - assertBroadcastBadJson(j - "type", "failed to parse json message") + assertBroadcastBadJson(j - "type", WrongJson.WrongJsonDataMessage) assertBroadcastBadJson(j - "type" + ("type" -> Json.toJson(88)), "Bad transaction type") assertBroadcastBadJson(j - "chainId" + ("chainId" -> Json.toJson(123)), "Wrong chain-id") - assertBroadcastBadJson(j - "alias", "failed to parse json message") + assertBroadcastBadJson(j - "alias", WrongJson.WrongJsonDataMessage) } } diff --git a/node/build.sbt b/node/build.sbt index 2ba7441c3f8..6317232b8cb 100644 --- a/node/build.sbt +++ b/node/build.sbt @@ -6,7 +6,6 @@ enablePlugins( UniversalDeployPlugin, JDebPackaging, SystemdPlugin, - GitVersioning, VersionObject, JavaAgent ) diff --git a/node/src/main/resources/swagger-ui/openapi.yaml b/node/src/main/resources/swagger-ui/openapi.yaml index 6ff380ed175..b8fcd02eb0a 100644 --- a/node/src/main/resources/swagger-ui/openapi.yaml +++ b/node/src/main/resources/swagger-ui/openapi.yaml @@ -1,4 +1,4 @@ -openapi: 3.0.1 +openapi: 3.1.0 info: version: '{{version}}' title: Waves Full Node ({{chainId}}) @@ -287,7 +287,7 @@ paths: application/json;large-significand-format=string: schema: allOf: - - $ref: '#/components/schemas/BalanceLSF' + - $ref: '#/components/schemas/BalanceLSF' example: address: 2eEUvypDSivnzPiLrbYEW39SM8yMZ1aq4eJuiKfs4sEY confirmations: 3 @@ -446,7 +446,7 @@ paths: type: object properties: address: - type: string + $ref: '#/components/schemas/Address' script: type: string format: byte @@ -480,6 +480,8 @@ paths: description: >- Extra fee for transactions sending on behalf of the account + publicKey: + $ref: '#/components/schemas/PublicKey' '/addresses/{address}': delete: tags: @@ -598,7 +600,7 @@ paths: application/json;large-significand-format=string: schema: allOf: - - $ref: '#/components/schemas/BalanceLSF' + - $ref: '#/components/schemas/BalanceLSF' example: address: 2eEUvypDSivnzPiLrbYEW39SM8yMZ1aq4eJuiKfs4sEY confirmations: 3 @@ -631,7 +633,7 @@ paths: application/json;large-significand-format=string: schema: allOf: - - $ref: '#/components/schemas/BalanceLSF' + - $ref: '#/components/schemas/BalanceLSF' example: address: 2eEUvypDSivnzPiLrbYEW39SM8yMZ1aq4eJuiKfs4sEY confirmations: 3 @@ -1991,41 +1993,9 @@ paths: content: application/json: schema: - type: object - properties: - expr: - type: string - id: - type: string - example: "C8AgSFP8y91XUTpGtEQAQyjsSemxoY61ocGM852DFKF6" - nullable: true - fee: - type: number - example: 500000 - nullable: true - feeAssetId: - type: string - example: null - nullable: true - sender: - type: string - example: "3Mds6m8XZf4biC72NRkFx2kyoBdC9UvYRUR" - nullable: true - senderPublicKey: - type: string - example: "3T9fL3XpeaHYbumohePPUmeuUqhyEeyzifi9vKouV8QoNtAT6kYV1oPAe9e2KCVquPcyXJpr2QwUiQKEUQPGZnc6" - nullable: true - payment: - type: array - items: - type: object - properties: - amount: - $ref: '#/components/schemas/Amount' - assetId: - allOf: - - $ref: '#/components/schemas/AssetId' - nullable: true + oneOf: + - $ref: '#/components/schemas/RideExprRequest' + - $ref: '#/components/schemas/RideInvocationRequest' required: true responses: '200': @@ -2470,6 +2440,38 @@ paths: type: string balance: type: string + '/assets/{assetId}/distribution': + get: + tags: + - assets + summary: Asset balance distribution + description: Get asset balance distribution by addresses + operationId: getAssetDistributionOld + parameters: + - $ref: '#/components/parameters/assetId' + responses: + '200': + description: successful operation + content: + application/json: + schema: + type: object + additionalProperties: + type: integer + format: int64 + description: map of assetId <-> balance + example: + 2eEUvypDSivnzPiLrbYEW39SM8yMZ1aq4eJuiKfs4sEY: 15 + 3PPqZ623dAfbmxmnpTjwV6yD5GA5s3PJiUG: 25 + application/json;large-significand-format=string: + schema: + type: object + additionalProperties: + type: string + description: map of assetId <-> balance + example: + 2eEUvypDSivnzPiLrbYEW39SM8yMZ1aq4eJuiKfs4sEY: "15" + 3PPqZ623dAfbmxmnpTjwV6yD5GA5s3PJiUG: "25" '/assets/{assetId}/distribution/{height}/limit/{limit}': get: tags: @@ -3300,6 +3302,13 @@ paths: type: string components: schemas: + NonNegativeAmount: + oneOf: + - type: integer + format: int64 + minimum: 0 + - type: string + pattern: '^(0|[1-9]\d*)$' Timestamp: type: integer format: int64 @@ -5194,7 +5203,7 @@ components: - dApp - payment - call - - stateCahnges + - stateChanges properties: error: type: object @@ -5206,7 +5215,7 @@ components: - dApp - payment - call - - stateCahnges + - stateChanges properties: error: type: object @@ -5310,6 +5319,118 @@ components: type: array items: $ref: '#/components/schemas/InvokeActionLSF' + RideFunctionCallArg: + type: object + oneOf: + - properties: + type: + const: 'integer' + value: + type: integer + format: int64 + - properties: + type: + const: 'boolean' + value: + type: boolean + - properties: + type: + const: 'string' + value: + type: string + - properties: + type: + const: 'binary' + value: + type: string + description: 'Evaluated Ride expression either as a Ride code, or as compiled in base64 representation' + - properties: + type: + const: 'list' + value: + type: array + items: + $ref: '#/components/schemas/RideFunctionCallArg' + BlockchainOverrides: + type: object + properties: + accounts: + type: object + description: 'Key is Address' + additionalProperties: + type: object + properties: + assetBalances: + type: object + description: 'Key is AssetId' + additionalProperties: + $ref: '#/components/schemas/NonNegativeAmount' + regularBalance: + $ref: '#/components/schemas/NonNegativeAmount' + example: + accounts: + '3P274YB5qseSE9DTTL3bpSjosZrYBPDpJ8k': + assetBalances: + 'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p': '141592653' + '34N9YcEETLWn93qYQ64EsP1x89tSruJU44RrEMSXXEPJ': 5897932 + regularBalance: '3846264338327' + RideExprRequest: + type: object + properties: + expr: + type: string + example: "default()" + description: "Ride expression" + state: + $ref: '#/components/schemas/BlockchainOverrides' + RideInvocationRequest: + type: object + properties: + call: + type: object + properties: + function: + type: string + default: "default" + nullable: true + args: + type: array + items: + $ref: '#/components/schemas/RideFunctionCallArg' + nullable: true + id: + type: string + example: "C8AgSFP8y91XUTpGtEQAQyjsSemxoY61ocGM852DFKF6" + nullable: true + fee: + type: number + example: 500000 + nullable: true + feeAssetId: + type: string + example: null + nullable: true + sender: + type: string + example: "3Mds6m8XZf4biC72NRkFx2kyoBdC9UvYRUR" + nullable: true + senderPublicKey: + type: string + example: "3T9fL3XpeaHYbumohePPUmeuUqhyEeyzifi9vKouV8QoNtAT6kYV1oPAe9e2KCVquPcyXJpr2QwUiQKEUQPGZnc6" + nullable: true + payment: + type: array + items: + type: object + properties: + amount: + $ref: '#/components/schemas/Amount' + assetId: + allOf: + - $ref: '#/components/schemas/AssetId' + nullable: true + state: + $ref: '#/components/schemas/BlockchainOverrides' responses: Height: description: Block height @@ -5382,7 +5503,7 @@ components: generation-signature: 'qwertyuikmn56khjkKHKJHK787' blocksize: 11234 transactionCount: 10 - features: [0] + features: [ 0 ] reward: '30000' rewardShares: 3MtmVzUQQj1keBsr3Pq5DYkutZzu5H8wdgA: '200000000' @@ -5399,7 +5520,7 @@ components: version: 2 sender: '3PGS9W5aZ4kdBFJJ9jxmgjLW8qfqu1b3Y66' senderPublicKey: 'EAtFj2ycPFH6hzAadJ9UDbo6UGTbo4fenFbGiSDVYPU6' - proof: ['3n8tCEh9dxqvGrc3wuaKpoYX6mpXHfEeY7GFeAKpxZP7yJpqRiiSsyHoD9uCELnNoYBamnnrvY46WzKMVfSRVWGE'] + proof: [ '3n8tCEh9dxqvGrc3wuaKpoYX6mpXHfEeY7GFeAKpxZP7yJpqRiiSsyHoD9uCELnNoYBamnnrvY46WzKMVfSRVWGE' ] recipient: '3PDXpDCRkGz3jNMozjpbbrJeJZhKJHkoqjj' assetId: null feeAsset: null @@ -5432,7 +5553,7 @@ components: generation-signature: 'qwertyuikmn56khjkKHKJHK787' blocksize: 11234 transactionCount: 10 - features: [0] + features: [ 0 ] reward: '30000' rewardShares: 3MtmVzUQQj1keBsr3Pq5DYkutZzu5H8wdgA: '200000000' diff --git a/node/src/main/resources/swagger-ui/swagger-ui-bundle.js b/node/src/main/resources/swagger-ui/swagger-ui-bundle.js index 763a1166858..b628d7fef52 100644 --- a/node/src/main/resources/swagger-ui/swagger-ui-bundle.js +++ b/node/src/main/resources/swagger-ui/swagger-ui-bundle.js @@ -1,3 +1,3 @@ /*! For license information please see swagger-ui-bundle.js.LICENSE.txt */ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.SwaggerUIBundle=t():e.SwaggerUIBundle=t()}(this,(function(){return(()=>{var e={17967:(e,t)=>{"use strict";t.N=void 0;var r=/^([^\w]*)(javascript|data|vbscript)/im,n=/&#(\w+)(^\w|;)?/g,o=/[\u0000-\u001F\u007F-\u009F\u2000-\u200D\uFEFF]/gim,a=/^([^:]+):/gm,i=[".","/"];t.N=function(e){var t,s=(t=e||"",t.replace(n,(function(e,t){return String.fromCharCode(t)}))).replace(o,"").trim();if(!s)return"about:blank";if(function(e){return i.indexOf(e[0])>-1}(s))return s;var l=s.match(a);if(!l)return s;var u=l[0];return r.test(u)?"about:blank":s}},53795:(e,t,r)=>{"use strict";r.d(t,{Z:()=>P});var n=r(23101),o=r.n(n),a=r(61125),i=r.n(a),s=r(11882),l=r.n(s),u=r(97606),c=r.n(u),p=r(67294),f=r(43393);function h(e){return h="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},h(e)}function d(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function m(e,t){for(var r=0;r1&&void 0!==arguments[1]?arguments[1]:{},r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},n=k(t,r),o=e||Object.keys(y({},r,{},t));return o.every(n)}function k(e,t){return function(r){if("string"==typeof r)return(0,f.is)(t[r],e[r]);if(Array.isArray(r))return(0,f.is)(S(t,r),S(e,r));throw new TypeError("Invalid key: expected Array or string: "+r)}}var C=function(e){function t(){return d(this,t),E(this,b(t).apply(this,arguments))}var r,n,o;return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&w(e,t)}(t,e),r=t,n=[{key:"shouldComponentUpdate",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return!A(this.updateOnProps,this.props,e,"updateOnProps")||!A(this.updateOnStates,this.state,t,"updateOnStates")}}],n&&m(r.prototype,n),o&&m(r,o),t}(p.Component);const O=C;var j=r(23930),I=r.n(j),N=r(45697),T=r.n(N);class P extends O{constructor(){super(...arguments),i()(this,"getModelName",(e=>-1!==l()(e).call(e,"#/definitions/")?e.replace(/^.*#\/definitions\//,""):-1!==l()(e).call(e,"#/components/schemas/")?e.replace(/^.*#\/components\/schemas\//,""):void 0)),i()(this,"getRefSchema",(e=>{let{specSelectors:t}=this.props;return t.findDefinition(e)}))}render(){let{getComponent:e,getConfigs:t,specSelectors:n,schema:a,required:i,name:s,isRef:l,specPath:u,displayName:c,includeReadOnly:f,includeWriteOnly:h}=this.props;const d=e("ObjectModel"),m=e("ArrayModel"),g=e("PrimitiveModel");let v="object",y=a&&a.get("$$ref");if(!s&&y&&(s=this.getModelName(y)),!a&&y&&(a=this.getRefSchema(s)),!a)return p.createElement("span",{className:"model model-title"},p.createElement("span",{className:"model-title__text"},c||s),p.createElement("img",{src:r(2517),height:"20px",width:"20px"}));const b=n.isOAS3()&&a.get("deprecated");switch(l=void 0!==l?l:!!y,v=a&&a.get("type")||v,v){case"object":return p.createElement(d,o()({className:"object"},this.props,{specPath:u,getConfigs:t,schema:a,name:s,deprecated:b,isRef:l,includeReadOnly:f,includeWriteOnly:h}));case"array":return p.createElement(m,o()({className:"array"},this.props,{getConfigs:t,schema:a,name:s,deprecated:b,required:i,includeReadOnly:f,includeWriteOnly:h}));default:return p.createElement(g,o()({},this.props,{getComponent:e,getConfigs:t,schema:a,name:s,deprecated:b,required:i}))}}}i()(P,"propTypes",{schema:c()(I()).isRequired,getComponent:T().func.isRequired,getConfigs:T().func.isRequired,specSelectors:T().object.isRequired,name:T().string,displayName:T().string,isRef:T().bool,required:T().bool,expandDepth:T().number,depth:T().number,specPath:I().list.isRequired,includeReadOnly:T().bool,includeWriteOnly:T().bool})},5623:(e,t,r)=>{"use strict";r.d(t,{Z:()=>f});var n=r(61125),o=r.n(n),a=r(28222),i=r.n(a),s=r(67294),l=r(84564),u=r.n(l),c=r(90242),p=r(27504);class f extends s.Component{constructor(e,t){super(e,t),o()(this,"getDefinitionUrl",(()=>{let{specSelectors:e}=this.props;return new(u())(e.url(),p.Z.location).toString()}));let{getConfigs:r}=e,{validatorUrl:n}=r();this.state={url:this.getDefinitionUrl(),validatorUrl:void 0===n?"https://validator.swagger.io/validator":n}}UNSAFE_componentWillReceiveProps(e){let{getConfigs:t}=e,{validatorUrl:r}=t();this.setState({url:this.getDefinitionUrl(),validatorUrl:void 0===r?"https://validator.swagger.io/validator":r})}render(){let{getConfigs:e}=this.props,{spec:t}=e(),r=(0,c.Nm)(this.state.validatorUrl);return"object"==typeof t&&i()(t).length?null:this.state.url&&(0,c.hW)(this.state.validatorUrl)&&(0,c.hW)(this.state.url)?s.createElement("span",{className:"float-right"},s.createElement("a",{target:"_blank",rel:"noopener noreferrer",href:`${r}/debug?url=${encodeURIComponent(this.state.url)}`},s.createElement(h,{src:`${r}?url=${encodeURIComponent(this.state.url)}`,alt:"Online validator badge"}))):null}}class h extends s.Component{constructor(e){super(e),this.state={loaded:!1,error:!1}}componentDidMount(){const e=new Image;e.onload=()=>{this.setState({loaded:!0})},e.onerror=()=>{this.setState({error:!0})},e.src=this.props.src}UNSAFE_componentWillReceiveProps(e){if(e.src!==this.props.src){const t=new Image;t.onload=()=>{this.setState({loaded:!0})},t.onerror=()=>{this.setState({error:!0})},t.src=e.src}}render(){return this.state.error?s.createElement("img",{alt:"Error"}):this.state.loaded?s.createElement("img",{src:this.props.src,alt:this.props.alt}):null}}},86019:(e,t,r)=>{"use strict";r.d(t,{Z:()=>me,s:()=>ge});var n=r(67294),o=r(89927);function a(e,t){if(Array.prototype.indexOf)return e.indexOf(t);for(var r=0,n=e.length;r=0;r--)!0===t(e[r])&&e.splice(r,1)}function s(e){throw new Error("Unhandled case for value: '"+e+"'")}var l=function(){function e(e){void 0===e&&(e={}),this.tagName="",this.attrs={},this.innerHTML="",this.whitespaceRegex=/\s+/,this.tagName=e.tagName||"",this.attrs=e.attrs||{},this.innerHTML=e.innerHtml||e.innerHTML||""}return e.prototype.setTagName=function(e){return this.tagName=e,this},e.prototype.getTagName=function(){return this.tagName||""},e.prototype.setAttr=function(e,t){return this.getAttrs()[e]=t,this},e.prototype.getAttr=function(e){return this.getAttrs()[e]},e.prototype.setAttrs=function(e){return Object.assign(this.getAttrs(),e),this},e.prototype.getAttrs=function(){return this.attrs||(this.attrs={})},e.prototype.setClass=function(e){return this.setAttr("class",e)},e.prototype.addClass=function(e){for(var t,r=this.getClass(),n=this.whitespaceRegex,o=r?r.split(n):[],i=e.split(n);t=i.shift();)-1===a(o,t)&&o.push(t);return this.getAttrs().class=o.join(" "),this},e.prototype.removeClass=function(e){for(var t,r=this.getClass(),n=this.whitespaceRegex,o=r?r.split(n):[],i=e.split(n);o.length&&(t=i.shift());){var s=a(o,t);-1!==s&&o.splice(s,1)}return this.getAttrs().class=o.join(" "),this},e.prototype.getClass=function(){return this.getAttrs().class||""},e.prototype.hasClass=function(e){return-1!==(" "+this.getClass()+" ").indexOf(" "+e+" ")},e.prototype.setInnerHTML=function(e){return this.innerHTML=e,this},e.prototype.setInnerHtml=function(e){return this.setInnerHTML(e)},e.prototype.getInnerHTML=function(){return this.innerHTML||""},e.prototype.getInnerHtml=function(){return this.getInnerHTML()},e.prototype.toAnchorString=function(){var e=this.getTagName(),t=this.buildAttrsStr();return["<",e,t=t?" "+t:"",">",this.getInnerHtml(),""].join("")},e.prototype.buildAttrsStr=function(){if(!this.attrs)return"";var e=this.getAttrs(),t=[];for(var r in e)e.hasOwnProperty(r)&&t.push(r+'="'+e[r]+'"');return t.join(" ")},e}();var u=function(){function e(e){void 0===e&&(e={}),this.newWindow=!1,this.truncate={},this.className="",this.newWindow=e.newWindow||!1,this.truncate=e.truncate||{},this.className=e.className||""}return e.prototype.build=function(e){return new l({tagName:"a",attrs:this.createAttrs(e),innerHtml:this.processAnchorText(e.getAnchorText())})},e.prototype.createAttrs=function(e){var t={href:e.getAnchorHref()},r=this.createCssClass(e);return r&&(t.class=r),this.newWindow&&(t.target="_blank",t.rel="noopener noreferrer"),this.truncate&&this.truncate.length&&this.truncate.length=s)return l.host.length==t?(l.host.substr(0,t-o)+r).substr(0,s+n):i(c,s).substr(0,s+n);var p="";if(l.path&&(p+="/"+l.path),l.query&&(p+="?"+l.query),p){if((c+p).length>=s)return(c+p).length==t?(c+p).substr(0,t):(c+i(p,s-c.length)).substr(0,s+n);c+=p}if(l.fragment){var f="#"+l.fragment;if((c+f).length>=s)return(c+f).length==t?(c+f).substr(0,t):(c+i(f,s-c.length)).substr(0,s+n);c+=f}if(l.scheme&&l.host){var h=l.scheme+"://";if((c+h).length0&&(d=c.substr(-1*Math.floor(s/2))),(c.substr(0,Math.ceil(s/2))+r+d).substr(0,s+n)}(e,r):"middle"===n?function(e,t,r){if(e.length<=t)return e;var n,o;null==r?(r="…",n=8,o=3):(n=r.length,o=r.length);var a=t-o,i="";return a>0&&(i=e.substr(-1*Math.floor(a/2))),(e.substr(0,Math.ceil(a/2))+r+i).substr(0,a+n)}(e,r):function(e,t,r){return function(e,t,r){var n;return e.length>t&&(null==r?(r="…",n=3):n=r.length,e=e.substring(0,t-n)+r),e}(e,t,r)}(e,r)},e}(),c=function(){function e(e){this.__jsduckDummyDocProp=null,this.matchedText="",this.offset=0,this.tagBuilder=e.tagBuilder,this.matchedText=e.matchedText,this.offset=e.offset}return e.prototype.getMatchedText=function(){return this.matchedText},e.prototype.setOffset=function(e){this.offset=e},e.prototype.getOffset=function(){return this.offset},e.prototype.getCssClassSuffixes=function(){return[this.getType()]},e.prototype.buildTag=function(){return this.tagBuilder.build(this)},e}(),p=function(e,t){return p=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])},p(e,t)};function f(e,t){function r(){this.constructor=e}p(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}var h=function(){return h=Object.assign||function(e){for(var t,r=1,n=arguments.length;r-1},e.isValidUriScheme=function(e){var t=e.match(this.uriSchemeRegex),r=t&&t[0].toLowerCase();return"javascript:"!==r&&"vbscript:"!==r},e.urlMatchDoesNotHaveProtocolOrDot=function(e,t){return!(!e||t&&this.hasFullProtocolRegex.test(t)||-1!==e.indexOf("."))},e.urlMatchDoesNotHaveAtLeastOneWordChar=function(e,t){return!(!e||!t)&&(!this.hasFullProtocolRegex.test(t)&&!this.hasWordCharAfterProtocolRegex.test(e))},e.hasFullProtocolRegex=/^[A-Za-z][-.+A-Za-z0-9]*:\/\//,e.uriSchemeRegex=/^[A-Za-z][-.+A-Za-z0-9]*:/,e.hasWordCharAfterProtocolRegex=new RegExp(":[^\\s]*?["+C+"]"),e.ipRegex=/[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?(:[0-9]*)?\/?$/,e}(),V=(d=new RegExp("[/?#](?:["+N+"\\-+&@#/%=~_()|'$*\\[\\]{}?!:,.;^✓]*["+N+"\\-+&@#/%=~_()|'$*\\[\\]{}✓])?"),new RegExp(["(?:","(",/(?:[A-Za-z][-.+A-Za-z0-9]{0,63}:(?![A-Za-z][-.+A-Za-z0-9]{0,63}:\/\/)(?!\d+\/?)(?:\/\/)?)/.source,M(2),")","|","(","(//)?",/(?:www\.)/.source,M(6),")","|","(","(//)?",M(10)+"\\.",L.source,"(?![-"+I+"])",")",")","(?::[0-9]+)?","(?:"+d.source+")?"].join(""),"gi")),$=new RegExp("["+N+"]"),W=function(e){function t(t){var r=e.call(this,t)||this;return r.stripPrefix={scheme:!0,www:!0},r.stripTrailingSlash=!0,r.decodePercentEncoding=!0,r.matcherRegex=V,r.wordCharRegExp=$,r.stripPrefix=t.stripPrefix,r.stripTrailingSlash=t.stripTrailingSlash,r.decodePercentEncoding=t.decodePercentEncoding,r}return f(t,e),t.prototype.parseMatches=function(e){for(var t,r=this.matcherRegex,n=this.stripPrefix,o=this.stripTrailingSlash,a=this.decodePercentEncoding,i=this.tagBuilder,s=[],l=function(){var r=t[0],l=t[1],c=t[4],p=t[5],f=t[9],h=t.index,d=p||f,m=e.charAt(h-1);if(!q.isValid(r,l))return"continue";if(h>0&&"@"===m)return"continue";if(h>0&&d&&u.wordCharRegExp.test(m))return"continue";if(/\?$/.test(r)&&(r=r.substr(0,r.length-1)),u.matchHasUnbalancedClosingParen(r))r=r.substr(0,r.length-1);else{var g=u.matchHasInvalidCharAfterTld(r,l);g>-1&&(r=r.substr(0,g))}var v=["http://","https://"].find((function(e){return!!l&&-1!==l.indexOf(e)}));if(v){var y=r.indexOf(v);r=r.substr(y),l=l.substr(y),h+=y}var w=l?"scheme":c?"www":"tld",E=!!l;s.push(new b({tagBuilder:i,matchedText:r,offset:h,urlMatchType:w,url:r,protocolUrlMatch:E,protocolRelativeMatch:!!d,stripPrefix:n,stripTrailingSlash:o,decodePercentEncoding:a}))},u=this;null!==(t=r.exec(e));)l();return s},t.prototype.matchHasUnbalancedClosingParen=function(e){var t,r=e.charAt(e.length-1);if(")"===r)t="(";else if("]"===r)t="[";else{if("}"!==r)return!1;t="{"}for(var n=0,o=0,a=e.length-1;o"===e?(m=new ne(h(h({},m),{name:H()})),W()):E.test(e)||x.test(e)||":"===e||V()}function w(e){">"===e?V():E.test(e)?f=3:V()}function _(e){S.test(e)||("/"===e?f=12:">"===e?W():"<"===e?$():"="===e||A.test(e)||k.test(e)?V():f=5)}function C(e){S.test(e)?f=6:"/"===e?f=12:"="===e?f=7:">"===e?W():"<"===e?$():A.test(e)&&V()}function O(e){S.test(e)||("/"===e?f=12:"="===e?f=7:">"===e?W():"<"===e?$():A.test(e)?V():f=5)}function j(e){S.test(e)||('"'===e?f=8:"'"===e?f=9:/[>=`]/.test(e)?V():"<"===e?$():f=10)}function I(e){'"'===e&&(f=11)}function N(e){"'"===e&&(f=11)}function T(e){S.test(e)?f=4:">"===e?W():"<"===e&&$()}function P(e){S.test(e)?f=4:"/"===e?f=12:">"===e?W():"<"===e?$():(f=4,c--)}function R(e){">"===e?(m=new ne(h(h({},m),{isClosing:!0})),W()):f=4}function M(t){"--"===e.substr(c,2)?(c+=2,m=new ne(h(h({},m),{type:"comment"})),f=14):"DOCTYPE"===e.substr(c,7).toUpperCase()?(c+=7,m=new ne(h(h({},m),{type:"doctype"})),f=20):V()}function D(e){"-"===e?f=15:">"===e?V():f=16}function L(e){"-"===e?f=18:">"===e?V():f=16}function B(e){"-"===e&&(f=17)}function F(e){f="-"===e?18:16}function z(e){">"===e?W():"!"===e?f=19:"-"===e||(f=16)}function U(e){"-"===e?f=17:">"===e?W():f=16}function q(e){">"===e?W():"<"===e&&$()}function V(){f=0,m=u}function $(){f=1,m=new ne({idx:c})}function W(){var t=e.slice(d,m.idx);t&&a(t,d),"comment"===m.type?i(m.idx):"doctype"===m.type?l(m.idx):(m.isOpening&&n(m.name,m.idx),m.isClosing&&o(m.name,m.idx)),V(),d=c+1}function H(){var t=m.idx+(m.isClosing?2:1);return e.slice(t,c).toLowerCase()}d=0&&n++},onText:function(e,r){if(0===n){var a=function(e,t){if(!t.global)throw new Error("`splitRegex` must have the 'g' flag set");for(var r,n=[],o=0;r=t.exec(e);)n.push(e.substring(o,r.index)),n.push(r[0]),o=r.index+r[0].length;return n.push(e.substring(o)),n}(e,/( | |<|<|>|>|"|"|')/gi),i=r;a.forEach((function(e,r){if(r%2==0){var n=t.parseText(e,i);o.push.apply(o,n)}i+=e.length}))}},onCloseTag:function(e){r.indexOf(e)>=0&&(n=Math.max(n-1,0))},onComment:function(e){},onDoctype:function(e){}}),o=this.compactMatches(o),o=this.removeUnwantedMatches(o)},e.prototype.compactMatches=function(e){e.sort((function(e,t){return e.getOffset()-t.getOffset()}));for(var t=0;to?t:t+1;e.splice(i,1);continue}e[t+1].getOffset()/g,">"));for(var t=this.parse(e),r=[],n=0,o=0,a=t.length;o/i.test(e)}function se(){var e=[],t=new oe({stripPrefix:!1,url:!0,email:!0,replaceFn:function(t){switch(t.getType()){case"url":e.push({text:t.matchedText,url:t.getUrl()});break;case"email":e.push({text:t.matchedText,url:"mailto:"+t.getEmail().replace(/^mailto:/i,"")})}return!1}});return{links:e,autolinker:t}}function le(e){var t,r,n,o,a,i,s,l,u,c,p,f,h,d,m=e.tokens,g=null;for(r=0,n=m.length;r=0;t--)if("link_close"!==(a=o[t]).type){if("htmltag"===a.type&&(d=a.content,/^\s]/i.test(d)&&p>0&&p--,ie(a.content)&&p++),!(p>0)&&"text"===a.type&&ae.test(a.content)){if(g||(f=(g=se()).links,h=g.autolinker),i=a.content,f.length=0,h.link(i),!f.length)continue;for(s=[],c=a.level,l=0;l({useUnsafeMarkdown:!1})};const me=de;function ge(e){let{useUnsafeMarkdown:t=!1}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const r=t,n=t?[]:["style","class"];return t&&!ge.hasWarnedAboutDeprecation&&(console.warn("useUnsafeMarkdown display configuration parameter is deprecated since >3.26.0 and will be removed in v4.0.0."),ge.hasWarnedAboutDeprecation=!0),pe().sanitize(e,{ADD_ATTR:["target"],FORBID_TAGS:["style","form"],ALLOW_DATA_ATTR:r,FORBID_ATTR:n})}ge.hasWarnedAboutDeprecation=!1},45308:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>f});var n,o=r(86),a=r.n(o),i=r(8712),s=r.n(i),l=r(90242),u=r(27621);const c=r(95102),p={},f=p;a()(n=s()(c).call(c)).call(n,(function(e){if("./index.js"===e)return;let t=c(e);p[(0,l.Zl)(e)]=t.default?t.default:t})),p.SafeRender=u.default},55812:(e,t,r)=>{"use strict";r.r(t),r.d(t,{SHOW_AUTH_POPUP:()=>p,AUTHORIZE:()=>f,LOGOUT:()=>h,PRE_AUTHORIZE_OAUTH2:()=>d,AUTHORIZE_OAUTH2:()=>m,VALIDATE:()=>g,CONFIGURE_AUTH:()=>v,RESTORE_AUTHORIZATION:()=>y,showDefinitions:()=>b,authorize:()=>w,authorizeWithPersistOption:()=>E,logout:()=>x,logoutWithPersistOption:()=>_,preAuthorizeImplicit:()=>S,authorizeOauth2:()=>A,authorizeOauth2WithPersistOption:()=>k,authorizePassword:()=>C,authorizeApplication:()=>O,authorizeAccessCodeWithFormParams:()=>j,authorizeAccessCodeWithBasicAuthentication:()=>I,authorizeRequest:()=>N,configureAuth:()=>T,restoreAuthorization:()=>P,persistAuthorizationIfNeeded:()=>R,authPopup:()=>M});var n=r(35627),o=r.n(n),a=r(76986),i=r.n(a),s=r(84564),l=r.n(s),u=r(27504),c=r(90242);const p="show_popup",f="authorize",h="logout",d="pre_authorize_oauth2",m="authorize_oauth2",g="validate",v="configure_auth",y="restore_authorization";function b(e){return{type:p,payload:e}}function w(e){return{type:f,payload:e}}const E=e=>t=>{let{authActions:r}=t;r.authorize(e),r.persistAuthorizationIfNeeded()};function x(e){return{type:h,payload:e}}const _=e=>t=>{let{authActions:r}=t;r.logout(e),r.persistAuthorizationIfNeeded()},S=e=>t=>{let{authActions:r,errActions:n}=t,{auth:a,token:i,isValid:s}=e,{schema:l,name:c}=a,p=l.get("flow");delete u.Z.swaggerUIRedirectOauth2,"accessCode"===p||s||n.newAuthErr({authId:c,source:"auth",level:"warning",message:"Authorization may be unsafe, passed state was changed in server Passed state wasn't returned from auth server"}),i.error?n.newAuthErr({authId:c,source:"auth",level:"error",message:o()(i)}):r.authorizeOauth2WithPersistOption({auth:a,token:i})};function A(e){return{type:m,payload:e}}const k=e=>t=>{let{authActions:r}=t;r.authorizeOauth2(e),r.persistAuthorizationIfNeeded()},C=e=>t=>{let{authActions:r}=t,{schema:n,name:o,username:a,password:s,passwordType:l,clientId:u,clientSecret:p}=e,f={grant_type:"password",scope:e.scopes.join(" "),username:a,password:s},h={};switch(l){case"request-body":!function(e,t,r){t&&i()(e,{client_id:t});r&&i()(e,{client_secret:r})}(f,u,p);break;case"basic":h.Authorization="Basic "+(0,c.r3)(u+":"+p);break;default:console.warn(`Warning: invalid passwordType ${l} was passed, not including client id and secret`)}return r.authorizeRequest({body:(0,c.GZ)(f),url:n.get("tokenUrl"),name:o,headers:h,query:{},auth:e})};const O=e=>t=>{let{authActions:r}=t,{schema:n,scopes:o,name:a,clientId:i,clientSecret:s}=e,l={Authorization:"Basic "+(0,c.r3)(i+":"+s)},u={grant_type:"client_credentials",scope:o.join(" ")};return r.authorizeRequest({body:(0,c.GZ)(u),name:a,url:n.get("tokenUrl"),auth:e,headers:l})},j=e=>{let{auth:t,redirectUrl:r}=e;return e=>{let{authActions:n}=e,{schema:o,name:a,clientId:i,clientSecret:s,codeVerifier:l}=t,u={grant_type:"authorization_code",code:t.code,client_id:i,client_secret:s,redirect_uri:r,code_verifier:l};return n.authorizeRequest({body:(0,c.GZ)(u),name:a,url:o.get("tokenUrl"),auth:t})}},I=e=>{let{auth:t,redirectUrl:r}=e;return e=>{let{authActions:n}=e,{schema:o,name:a,clientId:i,clientSecret:s,codeVerifier:l}=t,u={Authorization:"Basic "+(0,c.r3)(i+":"+s)},p={grant_type:"authorization_code",code:t.code,client_id:i,redirect_uri:r,code_verifier:l};return n.authorizeRequest({body:(0,c.GZ)(p),name:a,url:o.get("tokenUrl"),auth:t,headers:u})}},N=e=>t=>{let r,{fn:n,getConfigs:a,authActions:s,errActions:u,oas3Selectors:c,specSelectors:p,authSelectors:f}=t,{body:h,query:d={},headers:m={},name:g,url:v,auth:y}=e,{additionalQueryStringParams:b}=f.getConfigs()||{};if(p.isOAS3()){let e=c.serverEffectiveValue(c.selectedServer());r=l()(v,e,!0)}else r=l()(v,p.url(),!0);"object"==typeof b&&(r.query=i()({},r.query,b));const w=r.toString();let E=i()({Accept:"application/json, text/plain, */*","Content-Type":"application/x-www-form-urlencoded","X-Requested-With":"XMLHttpRequest"},m);n.fetch({url:w,method:"post",headers:E,query:d,body:h,requestInterceptor:a().requestInterceptor,responseInterceptor:a().responseInterceptor}).then((function(e){let t=JSON.parse(e.data),r=t&&(t.error||""),n=t&&(t.parseError||"");e.ok?r||n?u.newAuthErr({authId:g,level:"error",source:"auth",message:o()(t)}):s.authorizeOauth2WithPersistOption({auth:y,token:t}):u.newAuthErr({authId:g,level:"error",source:"auth",message:e.statusText})})).catch((e=>{let t=new Error(e).message;if(e.response&&e.response.data){const r=e.response.data;try{const e="string"==typeof r?JSON.parse(r):r;e.error&&(t+=`, error: ${e.error}`),e.error_description&&(t+=`, description: ${e.error_description}`)}catch(e){}}u.newAuthErr({authId:g,level:"error",source:"auth",message:t})}))};function T(e){return{type:v,payload:e}}function P(e){return{type:y,payload:e}}const R=()=>e=>{let{authSelectors:t,getConfigs:r}=e;if(r().persistAuthorization){const e=t.authorized();localStorage.setItem("authorized",o()(e.toJS()))}},M=(e,t)=>()=>{u.Z.swaggerUIRedirectOauth2=t,u.Z.open(e)}},93705:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>u,preauthorizeBasic:()=>c,preauthorizeApiKey:()=>p});var n=r(11189),o=r.n(n),a=r(43962),i=r(55812),s=r(60035),l=r(48302);function u(){return{afterLoad(e){this.rootInjects=this.rootInjects||{},this.rootInjects.initOAuth=e.authActions.configureAuth,this.rootInjects.preauthorizeApiKey=o()(p).call(p,null,e),this.rootInjects.preauthorizeBasic=o()(c).call(c,null,e)},statePlugins:{auth:{reducers:a.default,actions:i,selectors:s},spec:{wrapActions:l}}}}function c(e,t,r,n){const{authActions:{authorize:o},specSelectors:{specJson:a,isOAS3:i}}=e,s=i()?["components","securitySchemes"]:["securityDefinitions"],l=a().getIn([...s,t]);return l?o({[t]:{value:{username:r,password:n},schema:l.toJS()}}):null}function p(e,t,r){const{authActions:{authorize:n},specSelectors:{specJson:o,isOAS3:a}}=e,i=a()?["components","securitySchemes"]:["securityDefinitions"],s=o().getIn([...i,t]);return s?n({[t]:{value:r,schema:s.toJS()}}):null}},43962:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>c});var n=r(86),o=r.n(n),a=r(76986),i=r.n(a),s=r(43393),l=r(90242),u=r(55812);const c={[u.SHOW_AUTH_POPUP]:(e,t)=>{let{payload:r}=t;return e.set("showDefinitions",r)},[u.AUTHORIZE]:(e,t)=>{var r;let{payload:n}=t,a=(0,s.fromJS)(n),i=e.get("authorized")||(0,s.Map)();return o()(r=a.entrySeq()).call(r,(t=>{let[r,n]=t;if(!(0,l.Wl)(n.getIn))return e.set("authorized",i);let o=n.getIn(["schema","type"]);if("apiKey"===o||"http"===o)i=i.set(r,n);else if("basic"===o){let e=n.getIn(["value","username"]),t=n.getIn(["value","password"]);i=i.setIn([r,"value"],{username:e,header:"Basic "+(0,l.r3)(e+":"+t)}),i=i.setIn([r,"schema"],n.get("schema"))}})),e.set("authorized",i)},[u.AUTHORIZE_OAUTH2]:(e,t)=>{let r,{payload:n}=t,{auth:o,token:a}=n;o.token=i()({},a),r=(0,s.fromJS)(o);let l=e.get("authorized")||(0,s.Map)();return l=l.set(r.get("name"),r),e.set("authorized",l)},[u.LOGOUT]:(e,t)=>{let{payload:r}=t,n=e.get("authorized").withMutations((e=>{o()(r).call(r,(t=>{e.delete(t)}))}));return e.set("authorized",n)},[u.CONFIGURE_AUTH]:(e,t)=>{let{payload:r}=t;return e.set("configs",r)},[u.RESTORE_AUTHORIZATION]:(e,t)=>{let{payload:r}=t;return e.set("authorized",(0,s.fromJS)(r.authorized))}}},60035:(e,t,r)=>{"use strict";r.r(t),r.d(t,{shownDefinitions:()=>y,definitionsToAuthorize:()=>b,getDefinitionsByNames:()=>w,definitionsForRequirements:()=>E,authorized:()=>x,isAuthorized:()=>_,getConfigs:()=>S});var n=r(86),o=r.n(n),a=r(51679),i=r.n(a),s=r(14418),l=r.n(s),u=r(11882),c=r.n(u),p=r(97606),f=r.n(p),h=r(28222),d=r.n(h),m=r(20573),g=r(43393);const v=e=>e,y=(0,m.P1)(v,(e=>e.get("showDefinitions"))),b=(0,m.P1)(v,(()=>e=>{var t;let{specSelectors:r}=e,n=r.securityDefinitions()||(0,g.Map)({}),a=(0,g.List)();return o()(t=n.entrySeq()).call(t,(e=>{let[t,r]=e,n=(0,g.Map)();n=n.set(t,r),a=a.push(n)})),a})),w=(e,t)=>e=>{var r;let{specSelectors:n}=e;console.warn("WARNING: getDefinitionsByNames is deprecated and will be removed in the next major version.");let a=n.securityDefinitions(),i=(0,g.List)();return o()(r=t.valueSeq()).call(r,(e=>{var t;let r=(0,g.Map)();o()(t=e.entrySeq()).call(t,(e=>{let t,[n,i]=e,s=a.get(n);var l;"oauth2"===s.get("type")&&i.size&&(t=s.get("scopes"),o()(l=t.keySeq()).call(l,(e=>{i.contains(e)||(t=t.delete(e))})),s=s.set("allowedScopes",t));r=r.set(n,s)})),i=i.push(r)})),i},E=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:(0,g.List)();return e=>{let{authSelectors:r}=e;const n=r.definitionsToAuthorize()||(0,g.List)();let a=(0,g.List)();return o()(n).call(n,(e=>{let r=i()(t).call(t,(t=>t.get(e.keySeq().first())));r&&(o()(e).call(e,((t,n)=>{if("oauth2"===t.get("type")){const i=r.get(n);let s=t.get("scopes");var a;if(g.List.isList(i)&&g.Map.isMap(s))o()(a=s.keySeq()).call(a,(e=>{i.contains(e)||(s=s.delete(e))})),e=e.set(n,t.set("scopes",s))}})),a=a.push(e))})),a}},x=(0,m.P1)(v,(e=>e.get("authorized")||(0,g.Map)())),_=(e,t)=>e=>{var r;let{authSelectors:n}=e,o=n.authorized();return g.List.isList(t)?!!l()(r=t.toJS()).call(r,(e=>{var t,r;return-1===c()(t=f()(r=d()(e)).call(r,(e=>!!o.get(e)))).call(t,!1)})).length:null},S=(0,m.P1)(v,(e=>e.get("configs")))},48302:(e,t,r)=>{"use strict";r.r(t),r.d(t,{execute:()=>n});const n=(e,t)=>{let{authSelectors:r,specSelectors:n}=t;return t=>{let{path:o,method:a,operation:i,extras:s}=t,l={authorized:r.authorized()&&r.authorized().toJS(),definitions:n.securityDefinitions()&&n.securityDefinitions().toJS(),specSecurity:n.security()&&n.security().toJS()};return e({path:o,method:a,operation:i,securities:l,...s})}}},70714:(e,t,r)=>{"use strict";r.r(t),r.d(t,{UPDATE_CONFIGS:()=>n,TOGGLE_CONFIGS:()=>o,update:()=>a,toggle:()=>i,loaded:()=>s});const n="configs_update",o="configs_toggle";function a(e,t){return{type:n,payload:{[e]:t}}}function i(e){return{type:o,payload:e}}const s=()=>e=>{let{getConfigs:t,authActions:r}=e;if(t().persistAuthorization){const e=localStorage.getItem("authorized");e&&r.restoreAuthorization({authorized:JSON.parse(e)})}}},92256:(e,t,r)=>{"use strict";r.r(t),r.d(t,{parseYamlConfig:()=>o});var n=r(1272);const o=(e,t)=>{try{return n.ZP.load(e)}catch(e){return t&&t.errActions.newThrownErr(new Error(e)),{}}}},1661:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>c});var n=r(15163),o=r(92256),a=r(70714),i=r(22698),s=r(69018),l=r(37743);const u={getLocalConfig:()=>(0,o.parseYamlConfig)(n)};function c(){return{statePlugins:{spec:{actions:i,selectors:u},configs:{reducers:l.default,actions:a,selectors:s}}}}},37743:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>a});var n=r(43393),o=r(70714);const a={[o.UPDATE_CONFIGS]:(e,t)=>e.merge((0,n.fromJS)(t.payload)),[o.TOGGLE_CONFIGS]:(e,t)=>{const r=t.payload,n=e.get(r);return e.set(r,!n)}}},69018:(e,t,r)=>{"use strict";r.r(t),r.d(t,{get:()=>a});var n=r(58309),o=r.n(n);const a=(e,t)=>e.getIn(o()(t)?t:[t])},22698:(e,t,r)=>{"use strict";r.r(t),r.d(t,{downloadConfig:()=>o,getConfigByUrl:()=>a});var n=r(92256);const o=e=>t=>{const{fn:{fetch:r}}=t;return r(e)},a=(e,t)=>r=>{let{specActions:o}=r;if(e)return o.downloadConfig(e).then(a,a);function a(r){r instanceof Error||r.status>=400?(o.updateLoadingStatus("failedConfig"),o.updateLoadingStatus("failedConfig"),o.updateUrl(""),console.error(r.statusText+" "+e.url),t(null)):t((0,n.parseYamlConfig)(r.text))}}},31970:(e,t,r)=>{"use strict";r.r(t),r.d(t,{setHash:()=>n});const n=e=>e?history.pushState(null,null,`#${e}`):window.location.hash=""},34980:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>i});var n=r(41599),o=r(60877),a=r(34584);function i(){return[n.default,{statePlugins:{configs:{wrapActions:{loaded:(e,t)=>function(){e(...arguments);const r=decodeURIComponent(window.location.hash);t.layoutActions.parseDeepLinkHash(r)}}}},wrapComponents:{operation:o.default,OperationTag:a.default}}]}},41599:(e,t,r)=>{"use strict";r.r(t),r.d(t,{show:()=>b,scrollTo:()=>w,parseDeepLinkHash:()=>E,readyToScroll:()=>x,scrollToElement:()=>_,clearScrollTo:()=>S,default:()=>A});var n=r(58309),o=r.n(n),a=r(24278),i=r.n(a),s=r(97606),l=r.n(s),u=r(11882),c=r.n(u),p=r(31970),f=r(45172),h=r.n(f),d=r(90242),m=r(43393),g=r.n(m);const v="layout_scroll_to",y="layout_clear_scroll",b=(e,t)=>{let{getConfigs:r,layoutSelectors:n}=t;return function(){for(var t=arguments.length,a=new Array(t),i=0;i({type:v,payload:o()(e)?e:[e]}),E=e=>t=>{let{layoutActions:r,layoutSelectors:n,getConfigs:o}=t;if(o().deepLinking&&e){var a;let t=i()(e).call(e,1);"!"===t[0]&&(t=i()(t).call(t,1)),"/"===t[0]&&(t=i()(t).call(t,1));const o=l()(a=t.split("/")).call(a,(e=>e||"")),s=n.isShownKeyFromUrlHashArray(o),[u,p="",f=""]=s;if("operations"===u){const e=n.isShownKeyFromUrlHashArray([p]);c()(p).call(p,"_")>-1&&(console.warn("Warning: escaping deep link whitespace with `_` will be unsupported in v4.0, use `%20` instead."),r.show(l()(e).call(e,(e=>e.replace(/_/g," "))),!0)),r.show(e,!0)}(c()(p).call(p,"_")>-1||c()(f).call(f,"_")>-1)&&(console.warn("Warning: escaping deep link whitespace with `_` will be unsupported in v4.0, use `%20` instead."),r.show(l()(s).call(s,(e=>e.replace(/_/g," "))),!0)),r.show(s,!0),r.scrollTo(s)}},x=(e,t)=>r=>{const n=r.layoutSelectors.getScrollToKey();g().is(n,(0,m.fromJS)(e))&&(r.layoutActions.scrollToElement(t),r.layoutActions.clearScrollTo())},_=(e,t)=>r=>{try{t=t||r.fn.getScrollParent(e),h().createScroller(t).to(e)}catch(e){console.error(e)}},S=()=>({type:y});const A={fn:{getScrollParent:function(e,t){const r=document.documentElement;let n=getComputedStyle(e);const o="absolute"===n.position,a=t?/(auto|scroll|hidden)/:/(auto|scroll)/;if("fixed"===n.position)return r;for(let t=e;t=t.parentElement;)if(n=getComputedStyle(t),(!o||"static"!==n.position)&&a.test(n.overflow+n.overflowY+n.overflowX))return t;return r}},statePlugins:{layout:{actions:{scrollToElement:_,scrollTo:w,clearScrollTo:S,readyToScroll:x,parseDeepLinkHash:E},selectors:{getScrollToKey:e=>e.get("scrollToKey"),isShownKeyFromUrlHashArray(e,t){const[r,n]=t;return n?["operations",r,n]:r?["operations-tag",r]:[]},urlHashArrayFromIsShownKey(e,t){let[r,n,o]=t;return"operations"==r?[n,o]:"operations-tag"==r?[n]:[]}},reducers:{[v]:(e,t)=>e.set("scrollToKey",g().fromJS(t.payload)),[y]:e=>e.delete("scrollToKey")},wrapActions:{show:b}}}}},34584:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>i});var n=r(61125),o=r.n(n),a=r(67294);const i=(e,t)=>class extends a.Component{constructor(){super(...arguments),o()(this,"onLoad",(e=>{const{tag:r}=this.props,n=["operations-tag",r];t.layoutActions.readyToScroll(n,e)}))}render(){return a.createElement("span",{ref:this.onLoad},a.createElement(e,this.props))}}},60877:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>i});var n=r(61125),o=r.n(n),a=r(67294);r(23930);const i=(e,t)=>class extends a.Component{constructor(){super(...arguments),o()(this,"onLoad",(e=>{const{operation:r}=this.props,{tag:n,operationId:o}=r.toObject();let{isShownKey:a}=r.toObject();a=a||["operations",n,o],t.layoutActions.readyToScroll(a,e)}))}render(){return a.createElement("span",{ref:this.onLoad},a.createElement(e,this.props))}}},48011:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>d});var n=r(76986),o=r.n(n),a=r(63460),i=r.n(a),s=r(11882),l=r.n(s),u=r(35627),c=r.n(u),p=r(20573),f=r(43393),h=r(27504);function d(e){let{fn:t}=e;return{statePlugins:{spec:{actions:{download:e=>r=>{let{errActions:n,specSelectors:a,specActions:s,getConfigs:l}=r,{fetch:u}=t;const c=l();function p(t){if(t instanceof Error||t.status>=400)return s.updateLoadingStatus("failed"),n.newThrownErr(o()(new Error((t.message||t.statusText)+" "+e),{source:"fetch"})),void(!t.status&&t instanceof Error&&function(){try{let t;if("URL"in h.Z?t=new(i())(e):(t=document.createElement("a"),t.href=e),"https:"!==t.protocol&&"https:"===h.Z.location.protocol){const e=o()(new Error(`Possible mixed-content issue? The page was loaded over https:// but a ${t.protocol}// URL was specified. Check that you are not attempting to load mixed content.`),{source:"fetch"});return void n.newThrownErr(e)}if(t.origin!==h.Z.location.origin){const e=o()(new Error(`Possible cross-origin (CORS) issue? The URL origin (${t.origin}) does not match the page (${h.Z.location.origin}). Check the server returns the correct 'Access-Control-Allow-*' headers.`),{source:"fetch"});n.newThrownErr(e)}}catch(e){return}}());s.updateLoadingStatus("success"),s.updateSpec(t.text),a.url()!==e&&s.updateUrl(e)}e=e||a.url(),s.updateLoadingStatus("loading"),n.clear({source:"fetch"}),u({url:e,loadSpec:!0,requestInterceptor:c.requestInterceptor||(e=>e),responseInterceptor:c.responseInterceptor||(e=>e),credentials:"same-origin",headers:{Accept:"application/json,*/*"}}).then(p,p)},updateLoadingStatus:e=>{let t=[null,"loading","failed","success","failedConfig"];return-1===l()(t).call(t,e)&&console.error(`Error: ${e} is not one of ${c()(t)}`),{type:"spec_update_loading_status",payload:e}}},reducers:{spec_update_loading_status:(e,t)=>"string"==typeof t.payload?e.set("loadingStatus",t.payload):e},selectors:{loadingStatus:(0,p.P1)((e=>e||(0,f.Map)()),(e=>e.get("loadingStatus")||null))}}}}}},34966:(e,t,r)=>{"use strict";r.r(t),r.d(t,{NEW_THROWN_ERR:()=>o,NEW_THROWN_ERR_BATCH:()=>a,NEW_SPEC_ERR:()=>i,NEW_SPEC_ERR_BATCH:()=>s,NEW_AUTH_ERR:()=>l,CLEAR:()=>u,CLEAR_BY:()=>c,newThrownErr:()=>p,newThrownErrBatch:()=>f,newSpecErr:()=>h,newSpecErrBatch:()=>d,newAuthErr:()=>m,clear:()=>g,clearBy:()=>v});var n=r(7710);const o="err_new_thrown_err",a="err_new_thrown_err_batch",i="err_new_spec_err",s="err_new_spec_err_batch",l="err_new_auth_err",u="err_clear",c="err_clear_by";function p(e){return{type:o,payload:(0,n.serializeError)(e)}}function f(e){return{type:a,payload:e}}function h(e){return{type:i,payload:e}}function d(e){return{type:s,payload:e}}function m(e){return{type:l,payload:e}}function g(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return{type:u,payload:e}}function v(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:()=>!0;return{type:c,payload:e}}},56982:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>c});var n=r(14418),o=r.n(n),a=r(97606),i=r.n(a),s=r(54061),l=r.n(s);const u=[r(2392),r(21835)];function c(e){var t;let r={jsSpec:{}},n=l()(u,((e,t)=>{try{let n=t.transform(e,r);return o()(n).call(n,(e=>!!e))}catch(t){return console.error("Transformer error:",t),e}}),e);return i()(t=o()(n).call(n,(e=>!!e))).call(t,(e=>(!e.get("line")&&e.get("path"),e)))}},2392:(e,t,r)=>{"use strict";r.r(t),r.d(t,{transform:()=>p});var n=r(97606),o=r.n(n),a=r(11882),i=r.n(a),s=r(24278),l=r.n(s),u=r(24282),c=r.n(u);function p(e){return o()(e).call(e,(e=>{var t;let r="is not of a type(s)",n=i()(t=e.get("message")).call(t,r);if(n>-1){var o,a;let t=l()(o=e.get("message")).call(o,n+r.length).split(",");return e.set("message",l()(a=e.get("message")).call(a,0,n)+function(e){return c()(e).call(e,((e,t,r,n)=>r===n.length-1&&n.length>1?e+"or "+t:n[r+1]&&n.length>2?e+t+", ":n[r+1]?e+t+" ":e+t),"should be a")}(t))}return e}))}},21835:(e,t,r)=>{"use strict";r.r(t),r.d(t,{transform:()=>n});r(97606),r(11882),r(27361),r(43393);function n(e,t){let{jsSpec:r}=t;return e}},77793:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>i});var n=r(93527),o=r(34966),a=r(87667);function i(e){return{statePlugins:{err:{reducers:(0,n.default)(e),actions:o,selectors:a}}}}},93527:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>v});var n=r(76986),o=r.n(n),a=r(97606),i=r.n(a),s=r(39022),l=r.n(s),u=r(14418),c=r.n(u),p=r(2250),f=r.n(p),h=r(34966),d=r(43393),m=r(56982);let g={line:0,level:"error",message:"Unknown error"};function v(){return{[h.NEW_THROWN_ERR]:(e,t)=>{let{payload:r}=t,n=o()(g,r,{type:"thrown"});return e.update("errors",(e=>(e||(0,d.List)()).push((0,d.fromJS)(n)))).update("errors",(e=>(0,m.default)(e)))},[h.NEW_THROWN_ERR_BATCH]:(e,t)=>{let{payload:r}=t;return r=i()(r).call(r,(e=>(0,d.fromJS)(o()(g,e,{type:"thrown"})))),e.update("errors",(e=>{var t;return l()(t=e||(0,d.List)()).call(t,(0,d.fromJS)(r))})).update("errors",(e=>(0,m.default)(e)))},[h.NEW_SPEC_ERR]:(e,t)=>{let{payload:r}=t,n=(0,d.fromJS)(r);return n=n.set("type","spec"),e.update("errors",(e=>(e||(0,d.List)()).push((0,d.fromJS)(n)).sortBy((e=>e.get("line"))))).update("errors",(e=>(0,m.default)(e)))},[h.NEW_SPEC_ERR_BATCH]:(e,t)=>{let{payload:r}=t;return r=i()(r).call(r,(e=>(0,d.fromJS)(o()(g,e,{type:"spec"})))),e.update("errors",(e=>{var t;return l()(t=e||(0,d.List)()).call(t,(0,d.fromJS)(r))})).update("errors",(e=>(0,m.default)(e)))},[h.NEW_AUTH_ERR]:(e,t)=>{let{payload:r}=t,n=(0,d.fromJS)(o()({},r));return n=n.set("type","auth"),e.update("errors",(e=>(e||(0,d.List)()).push((0,d.fromJS)(n)))).update("errors",(e=>(0,m.default)(e)))},[h.CLEAR]:(e,t)=>{var r;let{payload:n}=t;if(!n||!e.get("errors"))return e;let o=c()(r=e.get("errors")).call(r,(e=>{var t;return f()(t=e.keySeq()).call(t,(t=>{const r=e.get(t),o=n[t];return!o||r!==o}))}));return e.merge({errors:o})},[h.CLEAR_BY]:(e,t)=>{var r;let{payload:n}=t;if(!n||"function"!=typeof n)return e;let o=c()(r=e.get("errors")).call(r,(e=>n(e)));return e.merge({errors:o})}}}},87667:(e,t,r)=>{"use strict";r.r(t),r.d(t,{allErrors:()=>a,lastError:()=>i});var n=r(43393),o=r(20573);const a=(0,o.P1)((e=>e),(e=>e.get("errors",(0,n.List)()))),i=(0,o.P1)(a,(e=>e.last()))},49978:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>o});var n=r(4309);function o(){return{fn:{opsFilter:n.default}}}},4309:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>s});var n=r(14418),o=r.n(n),a=r(11882),i=r.n(a);function s(e,t){return o()(e).call(e,((e,r)=>-1!==i()(r).call(r,t)))}},25474:(e,t,r)=>{"use strict";r.r(t),r.d(t,{UPDATE_LAYOUT:()=>o,UPDATE_FILTER:()=>a,UPDATE_MODE:()=>i,SHOW:()=>s,updateLayout:()=>l,updateFilter:()=>u,show:()=>c,changeMode:()=>p});var n=r(90242);const o="layout_update_layout",a="layout_update_filter",i="layout_update_mode",s="layout_show";function l(e){return{type:o,payload:e}}function u(e){return{type:a,payload:e}}function c(e){let t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return e=(0,n.AF)(e),{type:s,payload:{thing:e,shown:t}}}function p(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return e=(0,n.AF)(e),{type:i,payload:{thing:e,mode:t}}}},26821:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>s});var n=r(5672),o=r(25474),a=r(4400),i=r(28989);function s(){return{statePlugins:{layout:{reducers:n.default,actions:o,selectors:a},spec:{wrapSelectors:i}}}}},5672:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>s});var n=r(39022),o=r.n(n),a=r(43393),i=r(25474);const s={[i.UPDATE_LAYOUT]:(e,t)=>e.set("layout",t.payload),[i.UPDATE_FILTER]:(e,t)=>e.set("filter",t.payload),[i.SHOW]:(e,t)=>{const r=t.payload.shown,n=(0,a.fromJS)(t.payload.thing);return e.update("shown",(0,a.fromJS)({}),(e=>e.set(n,r)))},[i.UPDATE_MODE]:(e,t)=>{var r;let n=t.payload.thing,a=t.payload.mode;return e.setIn(o()(r=["modes"]).call(r,n),(a||"")+"")}}},4400:(e,t,r)=>{"use strict";r.r(t),r.d(t,{current:()=>i,currentFilter:()=>s,isShown:()=>l,whatMode:()=>u,showSummary:()=>c});var n=r(20573),o=r(90242),a=r(43393);const i=e=>e.get("layout"),s=e=>e.get("filter"),l=(e,t,r)=>(t=(0,o.AF)(t),e.get("shown",(0,a.fromJS)({})).get((0,a.fromJS)(t),r)),u=function(e,t){let r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";return t=(0,o.AF)(t),e.getIn(["modes",...t],r)},c=(0,n.P1)((e=>e),(e=>!l(e,"editor")))},28989:(e,t,r)=>{"use strict";r.r(t),r.d(t,{taggedOperations:()=>a});var n=r(24278),o=r.n(n);const a=(e,t)=>function(r){for(var n=arguments.length,a=new Array(n>1?n-1:0),i=1;i=0&&(s=o()(s).call(s,0,f)),s}},9150:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>a});var n=r(11189),o=r.n(n);function a(e){let{configs:t}=e;const r={debug:0,info:1,log:2,warn:3,error:4},n=e=>r[e]||-1;let{logLevel:a}=t,i=n(a);function s(e){for(var t=arguments.length,r=new Array(t>1?t-1:0),o=1;o=i&&console[e](...r)}return s.warn=o()(s).call(s,null,"warn"),s.error=o()(s).call(s,null,"error"),s.info=o()(s).call(s,null,"info"),s.debug=o()(s).call(s,null,"debug"),{rootInjects:{log:s}}}},67002:(e,t,r)=>{"use strict";r.r(t),r.d(t,{UPDATE_SELECTED_SERVER:()=>n,UPDATE_REQUEST_BODY_VALUE:()=>o,UPDATE_REQUEST_BODY_VALUE_RETAIN_FLAG:()=>a,UPDATE_REQUEST_BODY_INCLUSION:()=>i,UPDATE_ACTIVE_EXAMPLES_MEMBER:()=>s,UPDATE_REQUEST_CONTENT_TYPE:()=>l,UPDATE_RESPONSE_CONTENT_TYPE:()=>u,UPDATE_SERVER_VARIABLE_VALUE:()=>c,SET_REQUEST_BODY_VALIDATE_ERROR:()=>p,CLEAR_REQUEST_BODY_VALIDATE_ERROR:()=>f,CLEAR_REQUEST_BODY_VALUE:()=>h,setSelectedServer:()=>d,setRequestBodyValue:()=>m,setRetainRequestBodyValueFlag:()=>g,setRequestBodyInclusion:()=>v,setActiveExamplesMember:()=>y,setRequestContentType:()=>b,setResponseContentType:()=>w,setServerVariableValue:()=>E,setRequestBodyValidateError:()=>x,clearRequestBodyValidateError:()=>_,initRequestBodyValidateError:()=>S,clearRequestBodyValue:()=>A});const n="oas3_set_servers",o="oas3_set_request_body_value",a="oas3_set_request_body_retain_flag",i="oas3_set_request_body_inclusion",s="oas3_set_active_examples_member",l="oas3_set_request_content_type",u="oas3_set_response_content_type",c="oas3_set_server_variable_value",p="oas3_set_request_body_validate_error",f="oas3_clear_request_body_validate_error",h="oas3_clear_request_body_value";function d(e,t){return{type:n,payload:{selectedServerUrl:e,namespace:t}}}function m(e){let{value:t,pathMethod:r}=e;return{type:o,payload:{value:t,pathMethod:r}}}const g=e=>{let{value:t,pathMethod:r}=e;return{type:a,payload:{value:t,pathMethod:r}}};function v(e){let{value:t,pathMethod:r,name:n}=e;return{type:i,payload:{value:t,pathMethod:r,name:n}}}function y(e){let{name:t,pathMethod:r,contextType:n,contextName:o}=e;return{type:s,payload:{name:t,pathMethod:r,contextType:n,contextName:o}}}function b(e){let{value:t,pathMethod:r}=e;return{type:l,payload:{value:t,pathMethod:r}}}function w(e){let{value:t,path:r,method:n}=e;return{type:u,payload:{value:t,path:r,method:n}}}function E(e){let{server:t,namespace:r,key:n,val:o}=e;return{type:c,payload:{server:t,namespace:r,key:n,val:o}}}const x=e=>{let{path:t,method:r,validationErrors:n}=e;return{type:p,payload:{path:t,method:r,validationErrors:n}}},_=e=>{let{path:t,method:r}=e;return{type:f,payload:{path:t,method:r}}},S=e=>{let{pathMethod:t}=e;return{type:f,payload:{path:t[0],method:t[1]}}},A=e=>{let{pathMethod:t}=e;return{type:h,payload:{pathMethod:t}}}},73723:(e,t,r)=>{"use strict";r.r(t),r.d(t,{definitionsToAuthorize:()=>f});var n=r(86),o=r.n(n),a=r(14418),i=r.n(a),s=r(24282),l=r.n(s),u=r(20573),c=r(43393),p=r(7779);const f=(h=(0,u.P1)((e=>e),(e=>{let{specSelectors:t}=e;return t.securityDefinitions()}),((e,t)=>{var r;let n=(0,c.List)();return t?(o()(r=t.entrySeq()).call(r,(e=>{let[t,r]=e;const a=r.get("type");var s;if("oauth2"===a&&o()(s=r.get("flows").entrySeq()).call(s,(e=>{let[o,a]=e,s=(0,c.fromJS)({flow:o,authorizationUrl:a.get("authorizationUrl"),tokenUrl:a.get("tokenUrl"),scopes:a.get("scopes"),type:r.get("type"),description:r.get("description")});n=n.push(new c.Map({[t]:i()(s).call(s,(e=>void 0!==e))}))})),"http"!==a&&"apiKey"!==a||(n=n.push(new c.Map({[t]:r}))),"openIdConnect"===a&&r.get("openIdConnectData")){let e=r.get("openIdConnectData"),a=e.get("grant_types_supported")||["authorization_code","implicit"];o()(a).call(a,(o=>{var a;let s=e.get("scopes_supported")&&l()(a=e.get("scopes_supported")).call(a,((e,t)=>e.set(t,"")),new c.Map),u=(0,c.fromJS)({flow:o,authorizationUrl:e.get("authorization_endpoint"),tokenUrl:e.get("token_endpoint"),scopes:s,type:"oauth2",openIdConnectUrl:r.get("openIdConnectUrl")});n=n.push(new c.Map({[t]:i()(u).call(u,(e=>void 0!==e))}))}))}})),n):n})),(e,t)=>function(){const r=t.getSystem().specSelectors.specJson();for(var n=arguments.length,o=new Array(n),a=0;a{"use strict";r.r(t),r.d(t,{default:()=>u});var n=r(23101),o=r.n(n),a=r(97606),i=r.n(a),s=r(67294),l=(r(23930),r(43393));const u=e=>{var t;let{callbacks:r,getComponent:n,specPath:a}=e;const u=n("OperationContainer",!0);if(!r)return s.createElement("span",null,"No callbacks");let c=i()(t=r.entrySeq()).call(t,(t=>{var r;let[n,c]=t;return s.createElement("div",{key:n},s.createElement("h2",null,n),i()(r=c.entrySeq()).call(r,(t=>{var r;let[c,p]=t;return"$$ref"===c?null:s.createElement("div",{key:c},i()(r=p.entrySeq()).call(r,(t=>{let[r,i]=t;if("$$ref"===r)return null;let p=(0,l.fromJS)({operation:i});return s.createElement(u,o()({},e,{op:p,key:r,tag:"",method:r,path:c,specPath:a.push(n,c,r),allowTryItOut:!1}))})))})))}));return s.createElement("div",null,c)}},86775:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>f});var n=r(61125),o=r.n(n),a=r(76986),i=r.n(a),s=r(14418),l=r.n(s),u=r(97606),c=r.n(u),p=r(67294);class f extends p.Component{constructor(e,t){super(e,t),o()(this,"onChange",(e=>{let{onChange:t}=this.props,{value:r,name:n}=e.target,o=i()({},this.state.value);n?o[n]=r:o=r,this.setState({value:o},(()=>t(this.state)))}));let{name:r,schema:n}=this.props,a=this.getValue();this.state={name:r,schema:n,value:a}}getValue(){let{name:e,authorized:t}=this.props;return t&&t.getIn([e,"value"])}render(){var e;let{schema:t,getComponent:r,errSelectors:n,name:o}=this.props;const a=r("Input"),i=r("Row"),s=r("Col"),u=r("authError"),f=r("Markdown",!0),h=r("JumpToPath",!0),d=(t.get("scheme")||"").toLowerCase();let m=this.getValue(),g=l()(e=n.allErrors()).call(e,(e=>e.get("authId")===o));if("basic"===d){var v;let e=m?m.get("username"):null;return p.createElement("div",null,p.createElement("h4",null,p.createElement("code",null,o||t.get("name")),"  (http, Basic)",p.createElement(h,{path:["securityDefinitions",o]})),e&&p.createElement("h6",null,"Authorized"),p.createElement(i,null,p.createElement(f,{source:t.get("description")})),p.createElement(i,null,p.createElement("label",null,"Username:"),e?p.createElement("code",null," ",e," "):p.createElement(s,null,p.createElement(a,{type:"text",required:"required",name:"username","aria-label":"auth-basic-username",onChange:this.onChange,autoFocus:!0}))),p.createElement(i,null,p.createElement("label",null,"Password:"),e?p.createElement("code",null," ****** "):p.createElement(s,null,p.createElement(a,{autoComplete:"new-password",name:"password",type:"password","aria-label":"auth-basic-password",onChange:this.onChange}))),c()(v=g.valueSeq()).call(v,((e,t)=>p.createElement(u,{error:e,key:t}))))}var y;return"bearer"===d?p.createElement("div",null,p.createElement("h4",null,p.createElement("code",null,o||t.get("name")),"  (http, Bearer)",p.createElement(h,{path:["securityDefinitions",o]})),m&&p.createElement("h6",null,"Authorized"),p.createElement(i,null,p.createElement(f,{source:t.get("description")})),p.createElement(i,null,p.createElement("label",null,"Value:"),m?p.createElement("code",null," ****** "):p.createElement(s,null,p.createElement(a,{type:"text","aria-label":"auth-bearer-value",onChange:this.onChange,autoFocus:!0}))),c()(y=g.valueSeq()).call(y,((e,t)=>p.createElement(u,{error:e,key:t})))):p.createElement("div",null,p.createElement("em",null,p.createElement("b",null,o)," HTTP authentication: unsupported scheme ",`'${d}'`))}}},76467:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>p});var n=r(33427),o=r(42458),a=r(15757),i=r(56617),s=r(9928),l=r(45327),u=r(86775),c=r(96796);const p={Callbacks:n.default,HttpAuth:u.default,RequestBody:o.default,Servers:i.default,ServersContainer:s.default,RequestBodyEditor:l.default,OperationServers:c.default,operationLink:a.default}},15757:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>u});var n=r(35627),o=r.n(n),a=r(97606),i=r.n(a),s=r(67294);r(23930);class l extends s.Component{render(){const{link:e,name:t,getComponent:r}=this.props,n=r("Markdown",!0);let a=e.get("operationId")||e.get("operationRef"),l=e.get("parameters")&&e.get("parameters").toJS(),u=e.get("description");return s.createElement("div",{className:"operation-link"},s.createElement("div",{className:"description"},s.createElement("b",null,s.createElement("code",null,t)),u?s.createElement(n,{source:u}):null),s.createElement("pre",null,"Operation `",a,"`",s.createElement("br",null),s.createElement("br",null),"Parameters ",function(e,t){var r;if("string"!=typeof t)return"";return i()(r=t.split("\n")).call(r,((t,r)=>r>0?Array(e+1).join(" ")+t:t)).join("\n")}(0,o()(l,null,2))||"{}",s.createElement("br",null)))}}const u=l},96796:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>i});var n=r(61125),o=r.n(n),a=r(67294);r(23930);class i extends a.Component{constructor(){super(...arguments),o()(this,"setSelectedServer",(e=>{const{path:t,method:r}=this.props;return this.forceUpdate(),this.props.setSelectedServer(e,`${t}:${r}`)})),o()(this,"setServerVariableValue",(e=>{const{path:t,method:r}=this.props;return this.forceUpdate(),this.props.setServerVariableValue({...e,namespace:`${t}:${r}`})})),o()(this,"getSelectedServer",(()=>{const{path:e,method:t}=this.props;return this.props.getSelectedServer(`${e}:${t}`)})),o()(this,"getServerVariable",((e,t)=>{const{path:r,method:n}=this.props;return this.props.getServerVariable({namespace:`${r}:${n}`,server:e},t)})),o()(this,"getEffectiveServerValue",(e=>{const{path:t,method:r}=this.props;return this.props.getEffectiveServerValue({server:e,namespace:`${t}:${r}`})}))}render(){const{operationServers:e,pathServers:t,getComponent:r}=this.props;if(!e&&!t)return null;const n=r("Servers"),o=e||t,i=e?"operation":"path";return a.createElement("div",{className:"opblock-section operation-servers"},a.createElement("div",{className:"opblock-section-header"},a.createElement("div",{className:"tab-header"},a.createElement("h4",{className:"opblock-title"},"Servers"))),a.createElement("div",{className:"opblock-description-wrapper"},a.createElement("h4",{className:"message"},"These ",i,"-level options override the global server options."),a.createElement(n,{servers:o,currentServer:this.getSelectedServer(),setSelectedServer:this.setSelectedServer,setServerVariableValue:this.setServerVariableValue,getServerVariable:this.getServerVariable,getEffectiveServerValue:this.getEffectiveServerValue})))}}},45327:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>c});var n=r(61125),o=r.n(n),a=r(67294),i=r(94184),s=r.n(i),l=r(90242);const u=Function.prototype;class c extends a.PureComponent{constructor(e,t){super(e,t),o()(this,"applyDefaultValue",(e=>{const{onChange:t,defaultValue:r}=e||this.props;return this.setState({value:r}),t(r)})),o()(this,"onChange",(e=>{this.props.onChange((0,l.Pz)(e))})),o()(this,"onDomChange",(e=>{const t=e.target.value;this.setState({value:t},(()=>this.onChange(t)))})),this.state={value:(0,l.Pz)(e.value)||e.defaultValue},e.onChange(e.value)}UNSAFE_componentWillReceiveProps(e){this.props.value!==e.value&&e.value!==this.state.value&&this.setState({value:(0,l.Pz)(e.value)}),!e.value&&e.defaultValue&&this.state.value&&this.applyDefaultValue(e)}render(){let{getComponent:e,errors:t}=this.props,{value:r}=this.state,n=t.size>0;const o=e("TextArea");return a.createElement("div",{className:"body-param"},a.createElement(o,{className:s()("body-param__text",{invalid:n}),title:t.size?t.join(", "):"",value:r,onChange:this.onDomChange}))}}o()(c,"defaultProps",{onChange:u,userHasEditedBody:!1})},42458:(e,t,r)=>{"use strict";r.r(t),r.d(t,{getDefaultRequestBodyValue:()=>m,default:()=>g});var n=r(97606),o=r.n(n),a=r(11882),i=r.n(a),s=r(58118),l=r.n(s),u=r(58309),c=r.n(u),p=r(67294),f=(r(23930),r(43393)),h=r(90242),d=r(2518);const m=(e,t,r)=>{const n=e.getIn(["content",t]),o=n.get("schema").toJS(),a=void 0!==n.get("examples"),i=n.get("example"),s=a?n.getIn(["examples",r,"value"]):i,l=(0,h.xi)(o,t,{includeWriteOnly:!0},s);return(0,h.Pz)(l)},g=e=>{let{userHasEditedBody:t,requestBody:r,requestBodyValue:n,requestBodyInclusionSetting:a,requestBodyErrors:s,getComponent:u,getConfigs:g,specSelectors:v,fn:y,contentType:b,isExecute:w,specPath:E,onChange:x,onChangeIncludeEmpty:_,activeExamplesKey:S,updateActiveExamplesKey:A,setRetainRequestBodyValueFlag:k}=e;const C=e=>{x(e.target.files[0])},O=e=>{let t={key:e,shouldDispatchInit:!1,defaultValue:!0};return"no value"===a.get(e,"no value")&&(t.shouldDispatchInit=!0),t},j=u("Markdown",!0),I=u("modelExample"),N=u("RequestBodyEditor"),T=u("highlightCode"),P=u("ExamplesSelectValueRetainer"),R=u("Example"),M=u("ParameterIncludeEmpty"),{showCommonExtensions:D}=g(),L=r&&r.get("description")||null,B=r&&r.get("content")||new f.OrderedMap;b=b||B.keySeq().first()||"";const F=B.get(b,(0,f.OrderedMap)()),z=F.get("schema",(0,f.OrderedMap)()),U=F.get("examples",null),q=null==U?void 0:o()(U).call(U,((e,t)=>{var n;const o=null===(n=e)||void 0===n?void 0:n.get("value",null);return o&&(e=e.set("value",m(r,b,t),o)),e}));if(s=f.List.isList(s)?s:(0,f.List)(),!F.size)return null;const V="object"===F.getIn(["schema","type"]),$="binary"===F.getIn(["schema","format"]),W="base64"===F.getIn(["schema","format"]);if("application/octet-stream"===b||0===i()(b).call(b,"image/")||0===i()(b).call(b,"audio/")||0===i()(b).call(b,"video/")||$||W){const e=u("Input");return w?p.createElement(e,{type:"file",onChange:C}):p.createElement("i",null,"Example values are not available for ",p.createElement("code",null,b)," media types.")}if(V&&("application/x-www-form-urlencoded"===b||0===i()(b).call(b,"multipart/"))&&z.get("properties",(0,f.OrderedMap)()).size>0){var H;const e=u("JsonSchemaForm"),t=u("ParameterExt"),r=z.get("properties",(0,f.OrderedMap)());return n=f.Map.isMap(n)?n:(0,f.OrderedMap)(),p.createElement("div",{className:"table-container"},L&&p.createElement(j,{source:L}),p.createElement("table",null,p.createElement("tbody",null,f.Map.isMap(r)&&o()(H=r.entrySeq()).call(H,(r=>{var i,d;let[m,g]=r;if(g.get("readOnly"))return;let v=D?(0,h.po)(g):null;const b=l()(i=z.get("required",(0,f.List)())).call(i,m),E=g.get("type"),S=g.get("format"),A=g.get("description"),k=n.getIn([m,"value"]),C=n.getIn([m,"errors"])||s,I=a.get(m)||!1,N=g.has("default")||g.has("example")||g.hasIn(["items","example"])||g.hasIn(["items","default"]),T=g.has("enum")&&(1===g.get("enum").size||b),P=N||T;let R="";"array"!==E||P||(R=[]),("object"===E||P)&&(R=(0,h.xi)(g,!1,{includeWriteOnly:!0})),"string"!=typeof R&&"object"===E&&(R=(0,h.Pz)(R)),"string"==typeof R&&"array"===E&&(R=JSON.parse(R));const L="string"===E&&("binary"===S||"base64"===S);return p.createElement("tr",{key:m,className:"parameters","data-property-name":m},p.createElement("td",{className:"parameters-col_name"},p.createElement("div",{className:b?"parameter__name required":"parameter__name"},m,b?p.createElement("span",null," *"):null),p.createElement("div",{className:"parameter__type"},E,S&&p.createElement("span",{className:"prop-format"},"($",S,")"),D&&v.size?o()(d=v.entrySeq()).call(d,(e=>{let[r,n]=e;return p.createElement(t,{key:`${r}-${n}`,xKey:r,xVal:n})})):null),p.createElement("div",{className:"parameter__deprecated"},g.get("deprecated")?"deprecated":null)),p.createElement("td",{className:"parameters-col_description"},p.createElement(j,{source:A}),w?p.createElement("div",null,p.createElement(e,{fn:y,dispatchInitialValue:!L,schema:g,description:m,getComponent:u,value:void 0===k?R:k,required:b,errors:C,onChange:e=>{x(e,[m])}}),b?null:p.createElement(M,{onChange:e=>_(m,e),isIncluded:I,isIncludedOptions:O(m),isDisabled:c()(k)?0!==k.length:!(0,h.O2)(k)})):null))})))))}const J=m(r,b,S);let K=null;return(0,d.O)(J)&&(K="json"),p.createElement("div",null,L&&p.createElement(j,{source:L}),q?p.createElement(P,{userHasEditedBody:t,examples:q,currentKey:S,currentUserInputValue:n,onSelect:e=>{A(e)},updateValue:x,defaultToFirstExample:!0,getComponent:u,setRetainRequestBodyValueFlag:k}):null,w?p.createElement("div",null,p.createElement(N,{value:n,errors:s,defaultValue:J,onChange:x,getComponent:u})):p.createElement(I,{getComponent:u,getConfigs:g,specSelectors:v,expandDepth:1,isExecute:w,schema:F.get("schema"),specPath:E.push("content",b),example:p.createElement(T,{className:"body-param__example",getConfigs:g,language:K,value:(0,h.Pz)(n)||J}),includeWriteOnly:!0}),q?p.createElement(R,{example:q.get(S),getComponent:u,getConfigs:g}):null)}},9928:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>o});var n=r(67294);class o extends n.Component{render(){const{specSelectors:e,oas3Selectors:t,oas3Actions:r,getComponent:o}=this.props,a=e.servers(),i=o("Servers");return a&&a.size?n.createElement("div",null,n.createElement("span",{className:"servers-title"},"Servers"),n.createElement(i,{servers:a,currentServer:t.selectedServer(),setSelectedServer:r.setSelectedServer,setServerVariableValue:r.setServerVariableValue,getServerVariable:t.serverVariableValue,getEffectiveServerValue:t.serverEffectiveValue})):null}}},56617:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>p});var n=r(61125),o=r.n(n),a=r(51679),i=r.n(a),s=r(97606),l=r.n(s),u=r(67294),c=r(43393);r(23930);class p extends u.Component{constructor(){super(...arguments),o()(this,"onServerChange",(e=>{this.setServer(e.target.value)})),o()(this,"onServerVariableValueChange",(e=>{let{setServerVariableValue:t,currentServer:r}=this.props,n=e.target.getAttribute("data-variable"),o=e.target.value;"function"==typeof t&&t({server:r,key:n,val:o})})),o()(this,"setServer",(e=>{let{setSelectedServer:t}=this.props;t(e)}))}componentDidMount(){var e;let{servers:t,currentServer:r}=this.props;r||this.setServer(null===(e=t.first())||void 0===e?void 0:e.get("url"))}UNSAFE_componentWillReceiveProps(e){let{servers:t,setServerVariableValue:r,getServerVariable:n}=e;if(this.props.currentServer!==e.currentServer||this.props.servers!==e.servers){var o;let a=i()(t).call(t,(t=>t.get("url")===e.currentServer)),s=i()(o=this.props.servers).call(o,(e=>e.get("url")===this.props.currentServer))||(0,c.OrderedMap)();if(!a)return this.setServer(t.first().get("url"));let u=s.get("variables")||(0,c.OrderedMap)(),p=(i()(u).call(u,(e=>e.get("default")))||(0,c.OrderedMap)()).get("default"),f=a.get("variables")||(0,c.OrderedMap)(),h=(i()(f).call(f,(e=>e.get("default")))||(0,c.OrderedMap)()).get("default");l()(f).call(f,((t,o)=>{n(e.currentServer,o)&&p===h||r({server:e.currentServer,key:o,val:t.get("default")||""})}))}}render(){var e,t;let{servers:r,currentServer:n,getServerVariable:o,getEffectiveServerValue:a}=this.props,s=(i()(r).call(r,(e=>e.get("url")===n))||(0,c.OrderedMap)()).get("variables")||(0,c.OrderedMap)(),p=0!==s.size;return u.createElement("div",{className:"servers"},u.createElement("label",{htmlFor:"servers"},u.createElement("select",{onChange:this.onServerChange,value:n},l()(e=r.valueSeq()).call(e,(e=>u.createElement("option",{value:e.get("url"),key:e.get("url")},e.get("url"),e.get("description")&&` - ${e.get("description")}`))).toArray())),p?u.createElement("div",null,u.createElement("div",{className:"computed-url"},"Computed URL:",u.createElement("code",null,a(n))),u.createElement("h4",null,"Server variables"),u.createElement("table",null,u.createElement("tbody",null,l()(t=s.entrySeq()).call(t,(e=>{var t;let[r,a]=e;return u.createElement("tr",{key:r},u.createElement("td",null,r),u.createElement("td",null,a.get("enum")?u.createElement("select",{"data-variable":r,onChange:this.onServerVariableValueChange},l()(t=a.get("enum")).call(t,(e=>u.createElement("option",{selected:e===o(n,r),key:e,value:e},e)))):u.createElement("input",{type:"text",value:o(n,r)||"",onChange:this.onServerVariableValueChange,"data-variable":r})))}))))):null)}}},7779:(e,t,r)=>{"use strict";r.r(t),r.d(t,{isOAS3:()=>l,isSwagger2:()=>u,OAS3ComponentWrapFactory:()=>c});var n=r(23101),o=r.n(n),a=r(27043),i=r.n(a),s=r(67294);function l(e){const t=e.get("openapi");return"string"==typeof t&&(i()(t).call(t,"3.0.")&&t.length>4)}function u(e){const t=e.get("swagger");return"string"==typeof t&&i()(t).call(t,"2.0")}function c(e){return(t,r)=>n=>{if(r&&r.specSelectors&&r.specSelectors.specJson){return l(r.specSelectors.specJson())?s.createElement(e,o()({},n,r,{Ori:t})):s.createElement(t,n)}return console.warn("OAS3 wrapper: couldn't get spec"),null}}},97451:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>p});var n=r(92044),o=r(73723),a=r(91741),i=r(76467),s=r(37761),l=r(67002),u=r(5065),c=r(62109);function p(){return{components:i.default,wrapComponents:s.default,statePlugins:{spec:{wrapSelectors:n,selectors:a},auth:{wrapSelectors:o},oas3:{actions:l,reducers:c.default,selectors:u}}}}},62109:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>p});var n=r(8712),o=r.n(n),a=r(86),i=r.n(a),s=r(24282),l=r.n(s),u=r(43393),c=r(67002);const p={[c.UPDATE_SELECTED_SERVER]:(e,t)=>{let{payload:{selectedServerUrl:r,namespace:n}}=t;const o=n?[n,"selectedServer"]:["selectedServer"];return e.setIn(o,r)},[c.UPDATE_REQUEST_BODY_VALUE]:(e,t)=>{let{payload:{value:r,pathMethod:n}}=t,[a,s]=n;if(!u.Map.isMap(r))return e.setIn(["requestData",a,s,"bodyValue"],r);let l,c=e.getIn(["requestData",a,s,"bodyValue"])||(0,u.Map)();u.Map.isMap(c)||(c=(0,u.Map)());const[...p]=o()(r).call(r);return i()(p).call(p,(e=>{let t=r.getIn([e]);c.has(e)&&u.Map.isMap(t)||(l=c.setIn([e,"value"],t))})),e.setIn(["requestData",a,s,"bodyValue"],l)},[c.UPDATE_REQUEST_BODY_VALUE_RETAIN_FLAG]:(e,t)=>{let{payload:{value:r,pathMethod:n}}=t,[o,a]=n;return e.setIn(["requestData",o,a,"retainBodyValue"],r)},[c.UPDATE_REQUEST_BODY_INCLUSION]:(e,t)=>{let{payload:{value:r,pathMethod:n,name:o}}=t,[a,i]=n;return e.setIn(["requestData",a,i,"bodyInclusion",o],r)},[c.UPDATE_ACTIVE_EXAMPLES_MEMBER]:(e,t)=>{let{payload:{name:r,pathMethod:n,contextType:o,contextName:a}}=t,[i,s]=n;return e.setIn(["examples",i,s,o,a,"activeExample"],r)},[c.UPDATE_REQUEST_CONTENT_TYPE]:(e,t)=>{let{payload:{value:r,pathMethod:n}}=t,[o,a]=n;return e.setIn(["requestData",o,a,"requestContentType"],r)},[c.UPDATE_RESPONSE_CONTENT_TYPE]:(e,t)=>{let{payload:{value:r,path:n,method:o}}=t;return e.setIn(["requestData",n,o,"responseContentType"],r)},[c.UPDATE_SERVER_VARIABLE_VALUE]:(e,t)=>{let{payload:{server:r,namespace:n,key:o,val:a}}=t;const i=n?[n,"serverVariableValues",r,o]:["serverVariableValues",r,o];return e.setIn(i,a)},[c.SET_REQUEST_BODY_VALIDATE_ERROR]:(e,t)=>{let{payload:{path:r,method:n,validationErrors:o}}=t,a=[];if(a.push("Required field is not provided"),o.missingBodyValue)return e.setIn(["requestData",r,n,"errors"],(0,u.fromJS)(a));if(o.missingRequiredKeys&&o.missingRequiredKeys.length>0){const{missingRequiredKeys:t}=o;return e.updateIn(["requestData",r,n,"bodyValue"],(0,u.fromJS)({}),(e=>l()(t).call(t,((e,t)=>e.setIn([t,"errors"],(0,u.fromJS)(a))),e)))}return console.warn("unexpected result: SET_REQUEST_BODY_VALIDATE_ERROR"),e},[c.CLEAR_REQUEST_BODY_VALIDATE_ERROR]:(e,t)=>{let{payload:{path:r,method:n}}=t;const a=e.getIn(["requestData",r,n,"bodyValue"]);if(!u.Map.isMap(a))return e.setIn(["requestData",r,n,"errors"],(0,u.fromJS)([]));const[...i]=o()(a).call(a);return i?e.updateIn(["requestData",r,n,"bodyValue"],(0,u.fromJS)({}),(e=>l()(i).call(i,((e,t)=>e.setIn([t,"errors"],(0,u.fromJS)([]))),e))):e},[c.CLEAR_REQUEST_BODY_VALUE]:(e,t)=>{let{payload:{pathMethod:r}}=t,[n,o]=r;const a=e.getIn(["requestData",n,o,"bodyValue"]);return a?u.Map.isMap(a)?e.setIn(["requestData",n,o,"bodyValue"],(0,u.Map)()):e.setIn(["requestData",n,o,"bodyValue"],""):e}}},5065:(e,t,r)=>{"use strict";r.r(t),r.d(t,{selectedServer:()=>g,requestBodyValue:()=>v,shouldRetainRequestBodyValue:()=>y,selectDefaultRequestBodyValue:()=>b,hasUserEditedBody:()=>w,requestBodyInclusionSetting:()=>E,requestBodyErrors:()=>x,activeExamplesMember:()=>_,requestContentType:()=>S,responseContentType:()=>A,serverVariableValue:()=>k,serverVariables:()=>C,serverEffectiveValue:()=>O,validateBeforeExecute:()=>j,validateShallowRequired:()=>N});var n=r(97606),o=r.n(n),a=r(86),i=r.n(a),s=r(28222),l=r.n(s),u=r(11882),c=r.n(u),p=r(43393),f=r(7779),h=r(42458),d=r(90242);function m(e){return function(){for(var t=arguments.length,r=new Array(t),n=0;n{const n=t.getSystem().specSelectors.specJson();return(0,f.isOAS3)(n)?e(...r):null}}}const g=m(((e,t)=>{const r=t?[t,"selectedServer"]:["selectedServer"];return e.getIn(r)||""})),v=m(((e,t,r)=>e.getIn(["requestData",t,r,"bodyValue"])||null)),y=m(((e,t,r)=>e.getIn(["requestData",t,r,"retainBodyValue"])||!1)),b=(e,t,r)=>e=>{const{oas3Selectors:n,specSelectors:o}=e.getSystem(),a=o.specJson();if((0,f.isOAS3)(a)){const e=n.requestContentType(t,r);if(e)return(0,h.getDefaultRequestBodyValue)(o.specResolvedSubtree(["paths",t,r,"requestBody"]),e,n.activeExamplesMember(t,r,"requestBody","requestBody"))}return null},w=(e,t,r)=>e=>{const{oas3Selectors:n,specSelectors:o}=e.getSystem(),a=o.specJson();if((0,f.isOAS3)(a)){let e=!1;const a=n.requestContentType(t,r);let i=n.requestBodyValue(t,r);if(p.Map.isMap(i)&&(i=(0,d.Pz)(i.mapEntries((e=>p.Map.isMap(e[1])?[e[0],e[1].get("value")]:e)).toJS())),p.List.isList(i)&&(i=(0,d.Pz)(i)),a){const s=(0,h.getDefaultRequestBodyValue)(o.specResolvedSubtree(["paths",t,r,"requestBody"]),a,n.activeExamplesMember(t,r,"requestBody","requestBody"));e=!!i&&i!==s}return e}return null},E=m(((e,t,r)=>e.getIn(["requestData",t,r,"bodyInclusion"])||(0,p.Map)())),x=m(((e,t,r)=>e.getIn(["requestData",t,r,"errors"])||null)),_=m(((e,t,r,n,o)=>e.getIn(["examples",t,r,n,o,"activeExample"])||null)),S=m(((e,t,r)=>e.getIn(["requestData",t,r,"requestContentType"])||null)),A=m(((e,t,r)=>e.getIn(["requestData",t,r,"responseContentType"])||null)),k=m(((e,t,r)=>{let n;if("string"!=typeof t){const{server:e,namespace:o}=t;n=o?[o,"serverVariableValues",e,r]:["serverVariableValues",e,r]}else{n=["serverVariableValues",t,r]}return e.getIn(n)||null})),C=m(((e,t)=>{let r;if("string"!=typeof t){const{server:e,namespace:n}=t;r=n?[n,"serverVariableValues",e]:["serverVariableValues",e]}else{r=["serverVariableValues",t]}return e.getIn(r)||(0,p.OrderedMap)()})),O=m(((e,t)=>{var r,n;if("string"!=typeof t){const{server:o,namespace:a}=t;n=o,r=a?e.getIn([a,"serverVariableValues",n]):e.getIn(["serverVariableValues",n])}else n=t,r=e.getIn(["serverVariableValues",n]);r=r||(0,p.OrderedMap)();let a=n;return o()(r).call(r,((e,t)=>{a=a.replace(new RegExp(`{${t}}`,"g"),e)})),a})),j=(I=(e,t)=>((e,t)=>(t=t||[],!!e.getIn(["requestData",...t,"bodyValue"])))(e,t),function(){for(var e=arguments.length,t=new Array(e),r=0;r{const r=e.getSystem().specSelectors.specJson();let n=[...t][1]||[];return!r.getIn(["paths",...n,"requestBody","required"])||I(...t)}});var I;const N=(e,t)=>{var r;let{oas3RequiredRequestBodyContentType:n,oas3RequestContentType:o,oas3RequestBodyValue:a}=t,s=[];if(!p.Map.isMap(a))return s;let u=[];return i()(r=l()(n.requestContentType)).call(r,(e=>{if(e===o){let t=n.requestContentType[e];i()(t).call(t,(e=>{c()(u).call(u,e)<0&&u.push(e)}))}})),i()(u).call(u,(e=>{a.getIn([e,"value"])||s.push(e)})),s}},91741:(e,t,r)=>{"use strict";r.r(t),r.d(t,{servers:()=>u,isSwagger2:()=>p});var n=r(20573),o=r(43393),a=r(7779);const i=e=>e||(0,o.Map)(),s=(0,n.P1)(i,(e=>e.get("json",(0,o.Map)()))),l=(0,n.P1)(i,(e=>e.get("resolved",(0,o.Map)()))),u=(c=(0,n.P1)((e=>{let t=l(e);return t.count()<1&&(t=s(e)),t}),(e=>e.getIn(["servers"])||(0,o.Map)())),()=>function(e){const t=e.getSystem().specSelectors.specJson();if((0,a.isOAS3)(t)){for(var r=arguments.length,n=new Array(r>1?r-1:0),o=1;o()=>{const e=t.getSystem().specSelectors.specJson();return(0,a.isSwagger2)(e)}},92044:(e,t,r)=>{"use strict";r.r(t),r.d(t,{definitions:()=>h,hasHost:()=>d,securityDefinitions:()=>m,host:()=>g,basePath:()=>v,consumes:()=>y,produces:()=>b,schemes:()=>w,servers:()=>E,isOAS3:()=>x,isSwagger2:()=>_});var n=r(20573),o=r(33881),a=r(43393),i=r(7779);function s(e){return(t,r)=>function(){const n=r.getSystem().specSelectors.specJson();return(0,i.isOAS3)(n)?e(...arguments):t(...arguments)}}const l=e=>e||(0,a.Map)(),u=s((0,n.P1)((()=>null))),c=(0,n.P1)(l,(e=>e.get("json",(0,a.Map)()))),p=(0,n.P1)(l,(e=>e.get("resolved",(0,a.Map)()))),f=e=>{let t=p(e);return t.count()<1&&(t=c(e)),t},h=s((0,n.P1)(f,(e=>{const t=e.getIn(["components","schemas"]);return a.Map.isMap(t)?t:(0,a.Map)()}))),d=s((e=>f(e).hasIn(["servers",0]))),m=s((0,n.P1)(o.specJsonWithResolvedSubtrees,(e=>e.getIn(["components","securitySchemes"])||null))),g=u,v=u,y=u,b=u,w=u,E=s((0,n.P1)(f,(e=>e.getIn(["servers"])||(0,a.Map)()))),x=(e,t)=>()=>{const e=t.getSystem().specSelectors.specJson();return(0,i.isOAS3)(a.Map.isMap(e)?e:(0,a.Map)())},_=(e,t)=>()=>{const e=t.getSystem().specSelectors.specJson();return(0,i.isSwagger2)(a.Map.isMap(e)?e:(0,a.Map)())}},70356:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>o});var n=r(67294);const o=(0,r(7779).OAS3ComponentWrapFactory)((e=>{let{Ori:t,...r}=e;const{schema:o,getComponent:a,errSelectors:i,authorized:s,onAuthChange:l,name:u}=r,c=a("HttpAuth");return"http"===o.get("type")?n.createElement(c,{key:u,schema:o,name:u,errSelectors:i,authorized:s,getComponent:a,onChange:l}):n.createElement(t,r)}))},37761:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>u});var n=r(22460),o=r(70356),a=r(69487),i=r(50058),s=r(53499),l=r(90287);const u={Markdown:n.default,AuthItem:o.default,JsonSchema_string:l.default,VersionStamp:a.default,model:s.default,onlineValidatorBadge:i.default}},90287:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>o});var n=r(67294);const o=(0,r(7779).OAS3ComponentWrapFactory)((e=>{let{Ori:t,...r}=e;const{schema:o,getComponent:a,errors:i,onChange:s}=r,l=o&&o.get?o.get("format"):null,u=o&&o.get?o.get("type"):null,c=a("Input");return u&&"string"===u&&l&&("binary"===l||"base64"===l)?n.createElement(c,{type:"file",className:i.length?"invalid":"",title:i.length?i:"",onChange:e=>{s(e.target.files[0])},disabled:t.isDisabled}):n.createElement(t,r)}))},22460:(e,t,r)=>{"use strict";r.r(t),r.d(t,{Markdown:()=>f,default:()=>h});var n=r(81607),o=r.n(n),a=r(67294),i=r(94184),s=r.n(i),l=r(89927),u=r(7779),c=r(86019);const p=new l._("commonmark");p.block.ruler.enable(["table"]),p.set({linkTarget:"_blank"});const f=e=>{let{source:t,className:r="",getConfigs:n}=e;if("string"!=typeof t)return null;if(t){const{useUnsafeMarkdown:e}=n(),i=p.render(t),l=(0,c.s)(i,{useUnsafeMarkdown:e});let u;return"string"==typeof l&&(u=o()(l).call(l)),a.createElement("div",{dangerouslySetInnerHTML:{__html:u},className:s()(r,"renderedMarkdown")})}return null};f.defaultProps={getConfigs:()=>({useUnsafeMarkdown:!1})};const h=(0,u.OAS3ComponentWrapFactory)(f)},53499:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>u});var n=r(23101),o=r.n(n),a=r(67294),i=r(7779),s=r(53795);class l extends a.Component{render(){let{getConfigs:e,schema:t}=this.props,r=["model-box"],n=null;return!0===t.get("deprecated")&&(r.push("deprecated"),n=a.createElement("span",{className:"model-deprecated-warning"},"Deprecated:")),a.createElement("div",{className:r.join(" ")},n,a.createElement(s.Z,o()({},this.props,{getConfigs:e,depth:1,expandDepth:this.props.expandDepth||0})))}}const u=(0,i.OAS3ComponentWrapFactory)(l)},50058:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>a});var n=r(7779),o=r(5623);const a=(0,n.OAS3ComponentWrapFactory)(o.Z)},69487:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>o});var n=r(67294);const o=(0,r(7779).OAS3ComponentWrapFactory)((e=>{const{Ori:t}=e;return n.createElement("span",null,n.createElement(t,e),n.createElement("small",{className:"version-stamp"},n.createElement("pre",{className:"version"},"OAS3")))}))},28560:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>i});var n=r(87198),o=r.n(n);let a=!1;function i(){return{statePlugins:{spec:{wrapActions:{updateSpec:e=>function(){return a=!0,e(...arguments)},updateJsonSpec:(e,t)=>function(){const r=t.getConfigs().onComplete;return a&&"function"==typeof r&&(o()(r,0),a=!1),e(...arguments)}}}}}}},92135:(e,t,r)=>{"use strict";r.r(t),r.d(t,{requestSnippetGenerator_curl_powershell:()=>A,requestSnippetGenerator_curl_bash:()=>k,requestSnippetGenerator_curl_cmd:()=>C});var n=r(11882),o=r.n(n),a=r(81607),i=r.n(a),s=r(35627),l=r.n(s),u=r(97606),c=r.n(u),p=r(12196),f=r.n(p),h=r(74386),d=r.n(h),m=r(58118),g=r.n(m),v=r(27504),y=r(43393);const b=e=>{var t;const r="_**[]";return o()(e).call(e,r)<0?e:i()(t=e.split(r)[0]).call(t)},w=e=>"-d "===e||/^[_\/-]/g.test(e)?e:"'"+e.replace(/'/g,"'\\''")+"'",E=e=>"-d "===(e=e.replace(/\^/g,"^^").replace(/\\"/g,'\\\\"').replace(/"/g,'""').replace(/\n/g,"^\n"))?e.replace(/-d /g,"-d ^\n"):/^[_\/-]/g.test(e)?e:'"'+e+'"',x=e=>"-d "===e?e:/\n/.test(e)?'@"\n'+e.replace(/"/g,'\\"').replace(/`/g,"``").replace(/\$/,"`$")+'\n"@':/^[_\/-]/g.test(e)?e:"'"+e.replace(/"/g,'""').replace(/'/g,"''")+"'";function _(e){let t=[];for(let[r,n]of e.get("body").entrySeq()){let e=b(r);n instanceof v.Z.File?t.push(` "${e}": {\n "name": "${n.name}"${n.type?`,\n "type": "${n.type}"`:""}\n }`):t.push(` "${e}": ${l()(n,null,2).replace(/(\r\n|\r|\n)/g,"\n ")}`)}return`{\n${t.join(",\n")}\n}`}const S=function(e,t,r){let n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"",o=!1,a="";const i=function(){for(var e=arguments.length,r=new Array(e),n=0;na+=` ${r}`,p=function(){var e;let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1;return a+=f()(e=" ").call(e,t)};let h=e.get("headers");if(a+="curl"+n,e.has("curlOptions")&&i(...e.get("curlOptions")),i("-X",e.get("method")),u(),p(),s(`${e.get("url")}`),h&&h.size)for(let t of d()(m=e.get("headers")).call(m)){var m;u(),p();let[e,r]=t;s("-H",`${e}: ${r}`),o=o||/^content-type$/i.test(e)&&/^multipart\/form-data$/i.test(r)}const w=e.get("body");var E;if(w)if(o&&g()(E=["POST","PUT","PATCH"]).call(E,e.get("method")))for(let[e,t]of w.entrySeq()){let r=b(e);u(),p(),s("-F"),t instanceof v.Z.File?i(`${r}=@${t.name}${t.type?`;type=${t.type}`:""}`):i(`${r}=${t}`)}else if(w instanceof v.Z.File)u(),p(),s(`--data-binary '@${w.name}'`);else{u(),p(),s("-d ");let t=w;y.Map.isMap(t)?s(_(e)):("string"!=typeof t&&(t=l()(t)),s(t))}else w||"POST"!==e.get("method")||(u(),p(),s("-d ''"));return a},A=e=>S(e,x,"`\n",".exe"),k=e=>S(e,w,"\\\n"),C=e=>S(e,E,"^\n")},86575:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>i});var n=r(92135),o=r(4669),a=r(84206);const i=()=>({components:{RequestSnippets:a.default},fn:n,statePlugins:{requestSnippets:{selectors:o}}})},84206:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>w});var n=r(14418),o=r.n(n),a=r(25110),i=r.n(a),s=r(86),l=r.n(s),u=r(97606),c=r.n(u),p=r(67294),f=r(27361),h=r.n(f),d=r(23560),m=r.n(d),g=r(74855),v=r(33424);const y={cursor:"pointer",lineHeight:1,display:"inline-flex",backgroundColor:"rgb(250, 250, 250)",paddingBottom:"0",paddingTop:"0",border:"1px solid rgb(51, 51, 51)",borderRadius:"4px 4px 0 0",boxShadow:"none",borderBottom:"none"},b={cursor:"pointer",lineHeight:1,display:"inline-flex",backgroundColor:"rgb(51, 51, 51)",boxShadow:"none",border:"1px solid rgb(51, 51, 51)",paddingBottom:"0",paddingTop:"0",borderRadius:"4px 4px 0 0",marginTop:"-5px",marginRight:"-5px",marginLeft:"-5px",zIndex:"9999",borderBottom:"none"},w=e=>{var t,r;let{request:n,requestSnippetsSelectors:a,getConfigs:s}=e;const u=m()(s)?s():null,f=!1!==h()(u,"syntaxHighlight")&&h()(u,"syntaxHighlight.activated",!0),d=(0,p.useRef)(null),[w,E]=(0,p.useState)(null===(t=a.getSnippetGenerators())||void 0===t?void 0:t.keySeq().first()),[x,_]=(0,p.useState)(null==a?void 0:a.getDefaultExpanded());(0,p.useEffect)((()=>{}),[]),(0,p.useEffect)((()=>{var e;const t=o()(e=i()(d.current.childNodes)).call(e,(e=>{var t;return!!e.nodeType&&(null===(t=e.classList)||void 0===t?void 0:t.contains("curl-command"))}));return l()(t).call(t,(e=>e.addEventListener("mousewheel",j,{passive:!1}))),()=>{l()(t).call(t,(e=>e.removeEventListener("mousewheel",j)))}}),[n]);const S=a.getSnippetGenerators(),A=S.get(w),k=A.get("fn")(n),C=()=>{_(!x)},O=e=>e===w?b:y,j=e=>{const{target:t,deltaY:r}=e,{scrollHeight:n,offsetHeight:o,scrollTop:a}=t;n>o&&(0===a&&r<0||o+a>=n&&r>0)&&e.preventDefault()},I=f?p.createElement(v.d3,{language:A.get("syntax"),className:"curl microlight",style:(0,v.C2)(h()(u,"syntaxHighlight.theme"))},k):p.createElement("textarea",{readOnly:!0,className:"curl",value:k});return p.createElement("div",{className:"request-snippets",ref:d},p.createElement("div",{style:{width:"100%",display:"flex",justifyContent:"flex-start",alignItems:"center",marginBottom:"15px"}},p.createElement("h4",{onClick:()=>C(),style:{cursor:"pointer"}},"Snippets"),p.createElement("button",{onClick:()=>C(),style:{border:"none",background:"none"},title:x?"Collapse operation":"Expand operation"},p.createElement("svg",{className:"arrow",width:"10",height:"10"},p.createElement("use",{href:x?"#large-arrow-down":"#large-arrow",xlinkHref:x?"#large-arrow-down":"#large-arrow"})))),x&&p.createElement("div",{className:"curl-command"},p.createElement("div",{style:{paddingLeft:"15px",paddingRight:"10px",width:"100%",display:"flex"}},c()(r=S.entrySeq()).call(r,(e=>{let[t,r]=e;return p.createElement("div",{style:O(t),className:"btn",key:t,onClick:()=>(e=>{w!==e&&E(e)})(t)},p.createElement("h4",{style:t===w?{color:"white"}:{}},r.get("title")))}))),p.createElement("div",{className:"copy-to-clipboard"},p.createElement(g.CopyToClipboard,{text:k},p.createElement("button",null))),p.createElement("div",null,I)))}},4669:(e,t,r)=>{"use strict";r.r(t),r.d(t,{getGenerators:()=>f,getSnippetGenerators:()=>h,getActiveLanguage:()=>d,getDefaultExpanded:()=>m});var n=r(14418),o=r.n(n),a=r(58118),i=r.n(a),s=r(97606),l=r.n(s),u=r(20573),c=r(43393);const p=e=>e||(0,c.Map)(),f=(0,u.P1)(p,(e=>{const t=e.get("languages"),r=e.get("generators",(0,c.Map)());return!t||t.isEmpty()?r:o()(r).call(r,((e,r)=>i()(t).call(t,r)))})),h=e=>t=>{var r,n;let{fn:a}=t;return o()(r=l()(n=f(e)).call(n,((e,t)=>{const r=(e=>a[`requestSnippetGenerator_${e}`])(t);return"function"!=typeof r?null:e.set("fn",r)}))).call(r,(e=>e))},d=(0,u.P1)(p,(e=>e.get("activeLanguage"))),m=(0,u.P1)(p,(e=>e.get("defaultExpanded")))},36195:(e,t,r)=>{"use strict";r.r(t),r.d(t,{ErrorBoundary:()=>i,default:()=>s});var n=r(67294),o=r(56189),a=r(29403);class i extends n.Component{static getDerivedStateFromError(e){return{hasError:!0,error:e}}constructor(){super(...arguments),this.state={hasError:!1,error:null}}componentDidCatch(e,t){this.props.fn.componentDidCatch(e,t)}render(){const{getComponent:e,targetName:t,children:r}=this.props;if(this.state.hasError){const r=e("Fallback");return n.createElement(r,{name:t})}return r}}i.defaultProps={targetName:"this component",getComponent:()=>a.default,fn:{componentDidCatch:o.componentDidCatch},children:null};const s=i},29403:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>o});var n=r(67294);const o=e=>{let{name:t}=e;return n.createElement("div",{className:"fallback"},"😱 ",n.createElement("i",null,"Could not render ","t"===t?"this component":t,", see the console."))}},56189:(e,t,r)=>{"use strict";r.r(t),r.d(t,{componentDidCatch:()=>i,withErrorBoundary:()=>s});var n=r(23101),o=r.n(n),a=r(67294);const i=console.error,s=e=>t=>{const{getComponent:r,fn:n}=e(),i=r("ErrorBoundary"),s=n.getDisplayName(t);class l extends a.Component{render(){return a.createElement(i,{targetName:s,getComponent:r,fn:n},a.createElement(t,o()({},this.props,this.context)))}}var u;return l.displayName=`WithErrorBoundary(${s})`,(u=t).prototype&&u.prototype.isReactComponent&&(l.prototype.mapStateToProps=t.prototype.mapStateToProps),l}},27621:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>c});var n=r(47475),o=r.n(n),a=r(7287),i=r.n(a),s=r(36195),l=r(29403),u=r(56189);const c=function(){let{componentList:e=[],fullOverride:t=!1}=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return r=>{var n;let{getSystem:a}=r;const c=t?e:["App","BaseLayout","VersionPragmaFilter","InfoContainer","ServersContainer","SchemesContainer","AuthorizeBtnContainer","FilterContainer","Operations","OperationContainer","parameters","responses","OperationServers","Models","ModelWrapper",...e],p=i()(c,o()(n=Array(c.length)).call(n,((e,t)=>{let{fn:r}=t;return r.withErrorBoundary(e)})));return{fn:{componentDidCatch:u.componentDidCatch,withErrorBoundary:(0,u.withErrorBoundary)(a)},components:{ErrorBoundary:s.default,Fallback:l.default},wrapComponents:p}}}},57050:(e,t,r)=>{"use strict";r.r(t),r.d(t,{sampleFromSchemaGeneric:()=>F,inferSchema:()=>z,createXMLExample:()=>U,sampleFromSchema:()=>q,memoizedCreateXMLExample:()=>$,memoizedSampleFromSchema:()=>W});var n=r(11882),o=r.n(n),a=r(86),i=r.n(a),s=r(58309),l=r.n(s),u=r(58118),c=r.n(u),p=r(92039),f=r.n(p),h=r(24278),d=r.n(h),m=r(51679),g=r.n(m),v=r(39022),y=r.n(v),b=r(97606),w=r.n(b),E=r(35627),x=r.n(E),_=r(53479),S=r.n(_),A=r(14419),k=r.n(A),C=r(41609),O=r.n(C),j=r(90242),I=r(60314);const N={string:e=>e.pattern?(e=>{try{return new(k())(e).gen()}catch(e){return"string"}})(e.pattern):"string",string_email:()=>"user@example.com","string_date-time":()=>(new Date).toISOString(),string_date:()=>(new Date).toISOString().substring(0,10),string_uuid:()=>"3fa85f64-5717-4562-b3fc-2c963f66afa6",string_hostname:()=>"example.com",string_ipv4:()=>"198.51.100.42",string_ipv6:()=>"2001:0db8:5b96:0000:0000:426f:8e17:642a",number:()=>0,number_float:()=>0,integer:()=>0,boolean:e=>"boolean"!=typeof e.default||e.default},T=e=>{e=(0,j.mz)(e);let{type:t,format:r}=e,n=N[`${t}_${r}`]||N[t];return(0,j.Wl)(n)?n(e):"Unknown Type: "+e.type},P=e=>(0,j.XV)(e,"$$ref",(e=>"string"==typeof e&&o()(e).call(e,"#")>-1)),R=["maxProperties","minProperties"],M=["minItems","maxItems"],D=["minimum","maximum","exclusiveMinimum","exclusiveMaximum"],L=["minLength","maxLength"],B=function(e,t){var r;let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};const a=r=>{void 0===t[r]&&void 0!==e[r]&&(t[r]=e[r])};var s;(i()(r=["example","default","enum","xml","type",...R,...M,...D,...L]).call(r,(e=>a(e))),void 0!==e.required&&l()(e.required))&&(void 0!==t.required&&t.required.length||(t.required=[]),i()(s=e.required).call(s,(e=>{var r;c()(r=t.required).call(r,e)||t.required.push(e)})));if(e.properties){t.properties||(t.properties={});let r=(0,j.mz)(e.properties);for(let a in r){var u;if(Object.prototype.hasOwnProperty.call(r,a))if(!r[a]||!r[a].deprecated)if(!r[a]||!r[a].readOnly||n.includeReadOnly)if(!r[a]||!r[a].writeOnly||n.includeWriteOnly)if(!t.properties[a])t.properties[a]=r[a],!e.required&&l()(e.required)&&-1!==o()(u=e.required).call(u,a)&&(t.required?t.required.push(a):t.required=[a])}}return e.items&&(t.items||(t.items={}),t.items=B(e.items,t.items,n)),t},F=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0,n=arguments.length>3&&void 0!==arguments[3]&&arguments[3];e&&(0,j.Wl)(e.toJS)&&(e=e.toJS());let a=void 0!==r||e&&void 0!==e.example||e&&void 0!==e.default;const s=!a&&e&&e.oneOf&&e.oneOf.length>0,u=!a&&e&&e.anyOf&&e.anyOf.length>0;if(!a&&(s||u)){const r=(0,j.mz)(s?e.oneOf[0]:e.anyOf[0]);if(B(r,e,t),!e.xml&&r.xml&&(e.xml=r.xml),void 0!==e.example&&void 0!==r.example)a=!0;else if(r.properties){e.properties||(e.properties={});let n=(0,j.mz)(r.properties);for(let a in n){var p;if(Object.prototype.hasOwnProperty.call(n,a))if(!n[a]||!n[a].deprecated)if(!n[a]||!n[a].readOnly||t.includeReadOnly)if(!n[a]||!n[a].writeOnly||t.includeWriteOnly)if(!e.properties[a])e.properties[a]=n[a],!r.required&&l()(r.required)&&-1!==o()(p=r.required).call(p,a)&&(e.required?e.required.push(a):e.required=[a])}}}const h={};let{xml:m,type:v,example:b,properties:E,additionalProperties:x,items:_}=e||{},{includeReadOnly:S,includeWriteOnly:A}=t;m=m||{};let k,{name:C,prefix:I,namespace:N}=m,L={};if(n&&(C=C||"notagname",k=(I?I+":":"")+C,N)){h[I?"xmlns:"+I:"xmlns"]=N}n&&(L[k]=[]);const z=t=>f()(t).call(t,(t=>Object.prototype.hasOwnProperty.call(e,t)));e&&!v&&(E||x||z(R)?v="object":_||z(M)?v="array":z(D)?(v="number",e.type="number"):a||e.enum||(v="string",e.type="string"));const U=t=>{var r,n,o,a,i;null!==(null===(r=e)||void 0===r?void 0:r.maxItems)&&void 0!==(null===(n=e)||void 0===n?void 0:n.maxItems)&&(t=d()(t).call(t,0,null===(i=e)||void 0===i?void 0:i.maxItems));if(null!==(null===(o=e)||void 0===o?void 0:o.minItems)&&void 0!==(null===(a=e)||void 0===a?void 0:a.minItems)){let r=0;for(;t.length<(null===(s=e)||void 0===s?void 0:s.minItems);){var s;t.push(t[r++%t.length])}}return t},q=(0,j.mz)(E);let V,$=0;const W=()=>e&&null!==e.maxProperties&&void 0!==e.maxProperties&&$>=e.maxProperties,H=()=>{if(!e||!e.required)return 0;let t=0;var r,o;n?i()(r=e.required).call(r,(e=>t+=void 0===L[e]?0:1)):i()(o=e.required).call(o,(e=>{var r;return t+=void 0===(null===(r=L[k])||void 0===r?void 0:g()(r).call(r,(t=>void 0!==t[e])))?0:1}));return e.required.length-t},J=t=>{var r;return!(e&&e.required&&e.required.length)||!c()(r=e.required).call(r,t)},K=t=>!e||null===e.maxProperties||void 0===e.maxProperties||!W()&&(!J(t)||e.maxProperties-$-H()>0);if(V=n?function(r){let o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0;if(e&&q[r]){if(q[r].xml=q[r].xml||{},q[r].xml.attribute){const e=l()(q[r].enum)?q[r].enum[0]:void 0,t=q[r].example,n=q[r].default;return void(h[q[r].xml.name||r]=void 0!==t?t:void 0!==n?n:void 0!==e?e:T(q[r]))}q[r].xml.name=q[r].xml.name||r}else q[r]||!1===x||(q[r]={xml:{name:r}});let a=F(e&&q[r]||void 0,t,o,n);var i;K(r)&&($++,l()(a)?L[k]=y()(i=L[k]).call(i,a):L[k].push(a))}:(r,o)=>{if(K(r)){if(Object.prototype.hasOwnProperty.call(e,"discriminator")&&e.discriminator&&Object.prototype.hasOwnProperty.call(e.discriminator,"mapping")&&e.discriminator.mapping&&Object.prototype.hasOwnProperty.call(e,"$$ref")&&e.$$ref&&e.discriminator.propertyName===r){for(let t in e.discriminator.mapping)if(-1!==e.$$ref.search(e.discriminator.mapping[t])){L[r]=t;break}}else L[r]=F(q[r],t,o,n);$++}},a){let o;if(o=P(void 0!==r?r:void 0!==b?b:e.default),!n){if("number"==typeof o&&"string"===v)return`${o}`;if("string"!=typeof o||"string"===v)return o;try{return JSON.parse(o)}catch(e){return o}}if(e||(v=l()(o)?"array":typeof o),"array"===v){if(!l()(o)){if("string"==typeof o)return o;o=[o]}const r=e?e.items:void 0;r&&(r.xml=r.xml||m||{},r.xml.name=r.xml.name||m.name);let a=w()(o).call(o,(e=>F(r,t,e,n)));return a=U(a),m.wrapped?(L[k]=a,O()(h)||L[k].push({_attr:h})):L=a,L}if("object"===v){if("string"==typeof o)return o;for(let t in o)Object.prototype.hasOwnProperty.call(o,t)&&(e&&q[t]&&q[t].readOnly&&!S||e&&q[t]&&q[t].writeOnly&&!A||(e&&q[t]&&q[t].xml&&q[t].xml.attribute?h[q[t].xml.name||t]=o[t]:V(t,o[t])));return O()(h)||L[k].push({_attr:h}),L}return L[k]=O()(h)?o:[{_attr:h},o],L}if("object"===v){for(let e in q)Object.prototype.hasOwnProperty.call(q,e)&&(q[e]&&q[e].deprecated||q[e]&&q[e].readOnly&&!S||q[e]&&q[e].writeOnly&&!A||V(e));if(n&&h&&L[k].push({_attr:h}),W())return L;if(!0===x)n?L[k].push({additionalProp:"Anything can be here"}):L.additionalProp1={},$++;else if(x){const r=(0,j.mz)(x),o=F(r,t,void 0,n);if(n&&r.xml&&r.xml.name&&"notagname"!==r.xml.name)L[k].push(o);else{const t=null!==e.minProperties&&void 0!==e.minProperties&&$F(B(_,e,t),t,void 0,n)));else if(l()(_.oneOf)){var Y;r=w()(Y=_.oneOf).call(Y,(e=>F(B(_,e,t),t,void 0,n)))}else{if(!(!n||n&&m.wrapped))return F(_,t,void 0,n);r=[F(_,t,void 0,n)]}return r=U(r),n&&m.wrapped?(L[k]=r,O()(h)||L[k].push({_attr:h}),L):r}let Q;if(e&&l()(e.enum))Q=(0,j.AF)(e.enum)[0];else{if(!e)return;if(Q=T(e),"number"==typeof Q){let t=e.minimum;null!=t&&(e.exclusiveMinimum&&t++,Q=t);let r=e.maximum;null!=r&&(e.exclusiveMaximum&&r--,Q=r)}if("string"==typeof Q&&(null!==e.maxLength&&void 0!==e.maxLength&&(Q=d()(Q).call(Q,0,e.maxLength)),null!==e.minLength&&void 0!==e.minLength)){let t=0;for(;Q.length(e.schema&&(e=e.schema),e.properties&&(e.type="object"),e),U=(e,t,r)=>{const n=F(e,t,r,!0);if(n)return"string"==typeof n?n:S()(n,{declaration:!0,indent:"\t"})},q=(e,t,r)=>F(e,t,r,!1),V=(e,t,r)=>[e,x()(t),x()(r)],$=(0,I.Z)(U,V),W=(0,I.Z)(q,V)},8883:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>o});var n=r(57050);function o(){return{fn:n}}},51228:(e,t,r)=>{"use strict";r.r(t),r.d(t,{UPDATE_SPEC:()=>U,UPDATE_URL:()=>q,UPDATE_JSON:()=>V,UPDATE_PARAM:()=>$,UPDATE_EMPTY_PARAM_INCLUSION:()=>W,VALIDATE_PARAMS:()=>H,SET_RESPONSE:()=>J,SET_REQUEST:()=>K,SET_MUTATED_REQUEST:()=>G,LOG_REQUEST:()=>Z,CLEAR_RESPONSE:()=>Y,CLEAR_REQUEST:()=>Q,CLEAR_VALIDATE_PARAMS:()=>X,UPDATE_OPERATION_META_VALUE:()=>ee,UPDATE_RESOLVED:()=>te,UPDATE_RESOLVED_SUBTREE:()=>re,SET_SCHEME:()=>ne,updateSpec:()=>oe,updateResolved:()=>ae,updateUrl:()=>ie,updateJsonSpec:()=>se,parseToJson:()=>le,resolveSpec:()=>ce,requestResolvedSubtree:()=>he,changeParam:()=>de,changeParamByIdentity:()=>me,updateResolvedSubtree:()=>ge,invalidateResolvedSubtreeCache:()=>ve,validateParams:()=>ye,updateEmptyParamInclusion:()=>be,clearValidateParams:()=>we,changeConsumesValue:()=>Ee,changeProducesValue:()=>xe,setResponse:()=>_e,setRequest:()=>Se,setMutatedRequest:()=>Ae,logRequest:()=>ke,executeRequest:()=>Ce,execute:()=>Oe,clearResponse:()=>je,clearRequest:()=>Ie,setScheme:()=>Ne});var n=r(58309),o=r.n(n),a=r(97606),i=r.n(a),s=r(96718),l=r.n(s),u=r(24282),c=r.n(u),p=r(2250),f=r.n(p),h=r(6226),d=r.n(h),m=r(14418),g=r.n(m),v=r(3665),y=r.n(v),b=r(11882),w=r.n(b),E=r(86),x=r.n(E),_=r(28222),S=r.n(_),A=r(76986),k=r.n(A),C=r(70586),O=r.n(C),j=r(1272),I=r(43393),N=r(84564),T=r.n(N),P=r(7710),R=r(47037),M=r.n(R),D=r(23279),L=r.n(D),B=r(36968),F=r.n(B),z=r(90242);const U="spec_update_spec",q="spec_update_url",V="spec_update_json",$="spec_update_param",W="spec_update_empty_param_inclusion",H="spec_validate_param",J="spec_set_response",K="spec_set_request",G="spec_set_mutated_request",Z="spec_log_request",Y="spec_clear_response",Q="spec_clear_request",X="spec_clear_validate_param",ee="spec_update_operation_meta_value",te="spec_update_resolved",re="spec_update_resolved_subtree",ne="set_scheme";function oe(e){const t=(r=e,M()(r)?r:"").replace(/\t/g," ");var r;if("string"==typeof e)return{type:U,payload:t}}function ae(e){return{type:te,payload:e}}function ie(e){return{type:q,payload:e}}function se(e){return{type:V,payload:e}}const le=e=>t=>{let{specActions:r,specSelectors:n,errActions:o}=t,{specStr:a}=n,i=null;try{e=e||a(),o.clear({source:"parser"}),i=j.ZP.load(e,{schema:j.A8})}catch(e){return console.error(e),o.newSpecErr({source:"parser",level:"error",message:e.reason,line:e.mark&&e.mark.line?e.mark.line+1:void 0})}return i&&"object"==typeof i?r.updateJsonSpec(i):{}};let ue=!1;const ce=(e,t)=>r=>{let{specActions:n,specSelectors:a,errActions:s,fn:{fetch:u,resolve:c,AST:p={}},getConfigs:f}=r;ue||(console.warn("specActions.resolveSpec is deprecated since v3.10.0 and will be removed in v4.0.0; use requestResolvedSubtree instead!"),ue=!0);const{modelPropertyMacro:h,parameterMacro:d,requestInterceptor:m,responseInterceptor:g}=f();void 0===e&&(e=a.specJson()),void 0===t&&(t=a.url());let v=p.getLineNumberForPath?p.getLineNumberForPath:()=>{},y=a.specStr();return c({fetch:u,spec:e,baseDoc:t,modelPropertyMacro:h,parameterMacro:d,requestInterceptor:m,responseInterceptor:g}).then((e=>{let{spec:t,errors:r}=e;if(s.clear({type:"thrown"}),o()(r)&&r.length>0){let e=i()(r).call(r,(e=>(console.error(e),e.line=e.fullPath?v(y,e.fullPath):null,e.path=e.fullPath?e.fullPath.join("."):null,e.level="error",e.type="thrown",e.source="resolver",l()(e,"message",{enumerable:!0,value:e.message}),e)));s.newThrownErrBatch(e)}return n.updateResolved(t)}))};let pe=[];const fe=L()((async()=>{const e=pe.system;if(!e)return void console.error("debResolveSubtrees: don't have a system to operate on, aborting.");const{errActions:t,errSelectors:r,fn:{resolveSubtree:n,fetch:a,AST:s={}},specSelectors:u,specActions:p}=e;if(!n)return void console.error("Error: Swagger-Client did not provide a `resolveSubtree` method, doing nothing.");let h=s.getLineNumberForPath?s.getLineNumberForPath:()=>{};const m=u.specStr(),{modelPropertyMacro:v,parameterMacro:b,requestInterceptor:w,responseInterceptor:E}=e.getConfigs();try{var x=await c()(pe).call(pe,(async(e,s)=>{const{resultMap:c,specWithCurrentSubtrees:p}=await e,{errors:x,spec:_}=await n(p,s,{baseDoc:u.url(),modelPropertyMacro:v,parameterMacro:b,requestInterceptor:w,responseInterceptor:E});if(r.allErrors().size&&t.clearBy((e=>{var t;return"thrown"!==e.get("type")||"resolver"!==e.get("source")||!f()(t=e.get("fullPath")).call(t,((e,t)=>e===s[t]||void 0===s[t]))})),o()(x)&&x.length>0){let e=i()(x).call(x,(e=>(e.line=e.fullPath?h(m,e.fullPath):null,e.path=e.fullPath?e.fullPath.join("."):null,e.level="error",e.type="thrown",e.source="resolver",l()(e,"message",{enumerable:!0,value:e.message}),e)));t.newThrownErrBatch(e)}var S,A;_&&u.isOAS3()&&"components"===s[0]&&"securitySchemes"===s[1]&&await d().all(i()(S=g()(A=y()(_)).call(A,(e=>"openIdConnect"===e.type))).call(S,(async e=>{const t={url:e.openIdConnectUrl,requestInterceptor:w,responseInterceptor:E};try{const r=await a(t);r instanceof Error||r.status>=400?console.error(r.statusText+" "+t.url):e.openIdConnectData=JSON.parse(r.text)}catch(e){console.error(e)}})));return F()(c,s,_),F()(p,s,_),{resultMap:c,specWithCurrentSubtrees:p}}),d().resolve({resultMap:(u.specResolvedSubtree([])||(0,I.Map)()).toJS(),specWithCurrentSubtrees:u.specJson().toJS()}));delete pe.system,pe=[]}catch(e){console.error(e)}p.updateResolvedSubtree([],x.resultMap)}),35),he=e=>t=>{var r;w()(r=i()(pe).call(pe,(e=>e.join("@@")))).call(r,e.join("@@"))>-1||(pe.push(e),pe.system=t,fe())};function de(e,t,r,n,o){return{type:$,payload:{path:e,value:n,paramName:t,paramIn:r,isXml:o}}}function me(e,t,r,n){return{type:$,payload:{path:e,param:t,value:r,isXml:n}}}const ge=(e,t)=>({type:re,payload:{path:e,value:t}}),ve=()=>({type:re,payload:{path:[],value:(0,I.Map)()}}),ye=(e,t)=>({type:H,payload:{pathMethod:e,isOAS3:t}}),be=(e,t,r,n)=>({type:W,payload:{pathMethod:e,paramName:t,paramIn:r,includeEmptyValue:n}});function we(e){return{type:X,payload:{pathMethod:e}}}function Ee(e,t){return{type:ee,payload:{path:e,value:t,key:"consumes_value"}}}function xe(e,t){return{type:ee,payload:{path:e,value:t,key:"produces_value"}}}const _e=(e,t,r)=>({payload:{path:e,method:t,res:r},type:J}),Se=(e,t,r)=>({payload:{path:e,method:t,req:r},type:K}),Ae=(e,t,r)=>({payload:{path:e,method:t,req:r},type:G}),ke=e=>({payload:e,type:Z}),Ce=e=>t=>{let{fn:r,specActions:n,specSelectors:a,getConfigs:s,oas3Selectors:l}=t,{pathName:u,method:c,operation:p}=e,{requestInterceptor:f,responseInterceptor:h}=s(),d=p.toJS();var m,v;p&&p.get("parameters")&&x()(m=g()(v=p.get("parameters")).call(v,(e=>e&&!0===e.get("allowEmptyValue")))).call(m,(t=>{if(a.parameterInclusionSettingFor([u,c],t.get("name"),t.get("in"))){e.parameters=e.parameters||{};const r=(0,z.cz)(t,e.parameters);(!r||r&&0===r.size)&&(e.parameters[t.get("name")]="")}}));if(e.contextUrl=T()(a.url()).toString(),d&&d.operationId?e.operationId=d.operationId:d&&u&&c&&(e.operationId=r.opId(d,u,c)),a.isOAS3()){const t=`${u}:${c}`;e.server=l.selectedServer(t)||l.selectedServer();const r=l.serverVariables({server:e.server,namespace:t}).toJS(),n=l.serverVariables({server:e.server}).toJS();e.serverVariables=S()(r).length?r:n,e.requestContentType=l.requestContentType(u,c),e.responseContentType=l.responseContentType(u,c)||"*/*";const a=l.requestBodyValue(u,c),s=l.requestBodyInclusionSetting(u,c);var y;if(a&&a.toJS)e.requestBody=g()(y=i()(a).call(a,(e=>I.Map.isMap(e)?e.get("value"):e))).call(y,((e,t)=>(o()(e)?0!==e.length:!(0,z.O2)(e))||s.get(t))).toJS();else e.requestBody=a}let b=k()({},e);b=r.buildRequest(b),n.setRequest(e.pathName,e.method,b);e.requestInterceptor=async t=>{let r=await f.apply(void 0,[t]),o=k()({},r);return n.setMutatedRequest(e.pathName,e.method,o),r},e.responseInterceptor=h;const w=O()();return r.execute(e).then((t=>{t.duration=O()()-w,n.setResponse(e.pathName,e.method,t)})).catch((t=>{"Failed to fetch"===t.message&&(t.name="",t.message='**Failed to fetch.** \n**Possible Reasons:** \n - CORS \n - Network Failure \n - URL scheme must be "http" or "https" for CORS request.'),n.setResponse(e.pathName,e.method,{error:!0,err:(0,P.serializeError)(t)})}))},Oe=function(){let{path:e,method:t,...r}=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return n=>{let{fn:{fetch:o},specSelectors:a,specActions:i}=n,s=a.specJsonWithResolvedSubtrees().toJS(),l=a.operationScheme(e,t),{requestContentType:u,responseContentType:c}=a.contentTypeValues([e,t]).toJS(),p=/xml/i.test(u),f=a.parameterValues([e,t],p).toJS();return i.executeRequest({...r,fetch:o,spec:s,pathName:e,method:t,parameters:f,requestContentType:u,scheme:l,responseContentType:c})}};function je(e,t){return{type:Y,payload:{path:e,method:t}}}function Ie(e,t){return{type:Q,payload:{path:e,method:t}}}function Ne(e,t,r){return{type:ne,payload:{scheme:e,path:t,method:r}}}},37038:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>s});var n=r(20032),o=r(51228),a=r(33881),i=r(77508);function s(){return{statePlugins:{spec:{wrapActions:i,reducers:n.default,actions:o,selectors:a}}}}},20032:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>d});var n=r(24282),o=r.n(n),a=r(97606),i=r.n(a),s=r(76986),l=r.n(s),u=r(43393),c=r(90242),p=r(27504),f=r(33881),h=r(51228);const d={[h.UPDATE_SPEC]:(e,t)=>"string"==typeof t.payload?e.set("spec",t.payload):e,[h.UPDATE_URL]:(e,t)=>e.set("url",t.payload+""),[h.UPDATE_JSON]:(e,t)=>e.set("json",(0,c.oG)(t.payload)),[h.UPDATE_RESOLVED]:(e,t)=>e.setIn(["resolved"],(0,c.oG)(t.payload)),[h.UPDATE_RESOLVED_SUBTREE]:(e,t)=>{const{value:r,path:n}=t.payload;return e.setIn(["resolvedSubtrees",...n],(0,c.oG)(r))},[h.UPDATE_PARAM]:(e,t)=>{let{payload:r}=t,{path:n,paramName:o,paramIn:a,param:i,value:s,isXml:l}=r,u=i?(0,c.V9)(i):`${a}.${o}`;const p=l?"value_xml":"value";return e.setIn(["meta","paths",...n,"parameters",u,p],s)},[h.UPDATE_EMPTY_PARAM_INCLUSION]:(e,t)=>{let{payload:r}=t,{pathMethod:n,paramName:o,paramIn:a,includeEmptyValue:i}=r;if(!o||!a)return console.warn("Warning: UPDATE_EMPTY_PARAM_INCLUSION could not generate a paramKey."),e;const s=`${a}.${o}`;return e.setIn(["meta","paths",...n,"parameter_inclusions",s],i)},[h.VALIDATE_PARAMS]:(e,t)=>{let{payload:{pathMethod:r,isOAS3:n}}=t;const a=(0,f.specJsonWithResolvedSubtrees)(e).getIn(["paths",...r]),i=(0,f.parameterValues)(e,r).toJS();return e.updateIn(["meta","paths",...r,"parameters"],(0,u.fromJS)({}),(t=>{var s;return o()(s=a.get("parameters",(0,u.List)())).call(s,((t,o)=>{const a=(0,c.cz)(o,i),s=(0,f.parameterInclusionSettingFor)(e,r,o.get("name"),o.get("in")),l=(0,c.Ik)(o,a,{bypassRequiredCheck:s,isOAS3:n});return t.setIn([(0,c.V9)(o),"errors"],(0,u.fromJS)(l))}),t)}))},[h.CLEAR_VALIDATE_PARAMS]:(e,t)=>{let{payload:{pathMethod:r}}=t;return e.updateIn(["meta","paths",...r,"parameters"],(0,u.fromJS)([]),(e=>i()(e).call(e,(e=>e.set("errors",(0,u.fromJS)([]))))))},[h.SET_RESPONSE]:(e,t)=>{let r,{payload:{res:n,path:o,method:a}}=t;r=n.error?l()({error:!0,name:n.err.name,message:n.err.message,statusCode:n.err.statusCode},n.err.response):n,r.headers=r.headers||{};let i=e.setIn(["responses",o,a],(0,c.oG)(r));return p.Z.Blob&&n.data instanceof p.Z.Blob&&(i=i.setIn(["responses",o,a,"text"],n.data)),i},[h.SET_REQUEST]:(e,t)=>{let{payload:{req:r,path:n,method:o}}=t;return e.setIn(["requests",n,o],(0,c.oG)(r))},[h.SET_MUTATED_REQUEST]:(e,t)=>{let{payload:{req:r,path:n,method:o}}=t;return e.setIn(["mutatedRequests",n,o],(0,c.oG)(r))},[h.UPDATE_OPERATION_META_VALUE]:(e,t)=>{let{payload:{path:r,value:n,key:o}}=t,a=["paths",...r],i=["meta","paths",...r];return e.getIn(["json",...a])||e.getIn(["resolved",...a])||e.getIn(["resolvedSubtrees",...a])?e.setIn([...i,o],(0,u.fromJS)(n)):e},[h.CLEAR_RESPONSE]:(e,t)=>{let{payload:{path:r,method:n}}=t;return e.deleteIn(["responses",r,n])},[h.CLEAR_REQUEST]:(e,t)=>{let{payload:{path:r,method:n}}=t;return e.deleteIn(["requests",r,n])},[h.SET_SCHEME]:(e,t)=>{let{payload:{scheme:r,path:n,method:o}}=t;return n&&o?e.setIn(["scheme",n,o],r):n||o?void 0:e.setIn(["scheme","_defaultScheme"],r)}}},33881:(e,t,r)=>{"use strict";r.r(t),r.d(t,{lastError:()=>O,url:()=>j,specStr:()=>I,specSource:()=>N,specJson:()=>T,specResolved:()=>P,specResolvedSubtree:()=>R,specJsonWithResolvedSubtrees:()=>D,spec:()=>L,isOAS3:()=>B,info:()=>F,externalDocs:()=>z,version:()=>U,semver:()=>q,paths:()=>V,operations:()=>$,consumes:()=>W,produces:()=>H,security:()=>J,securityDefinitions:()=>K,findDefinition:()=>G,definitions:()=>Z,basePath:()=>Y,host:()=>Q,schemes:()=>X,operationsWithRootInherited:()=>ee,tags:()=>te,tagDetails:()=>re,operationsWithTags:()=>ne,taggedOperations:()=>oe,responses:()=>ae,requests:()=>ie,mutatedRequests:()=>se,responseFor:()=>le,requestFor:()=>ue,mutatedRequestFor:()=>ce,allowTryItOutFor:()=>pe,parameterWithMetaByIdentity:()=>fe,parameterInclusionSettingFor:()=>he,parameterWithMeta:()=>de,operationWithMeta:()=>me,getParameter:()=>ge,hasHost:()=>ve,parameterValues:()=>ye,parametersIncludeIn:()=>be,parametersIncludeType:()=>we,contentTypeValues:()=>Ee,currentProducesFor:()=>xe,producesOptionsFor:()=>_e,consumesOptionsFor:()=>Se,operationScheme:()=>Ae,canExecuteScheme:()=>ke,validationErrors:()=>Ce,validateBeforeExecute:()=>Oe,getOAS3RequiredRequestBodyContentType:()=>je,isMediaTypeSchemaPropertiesEqual:()=>Ie});var n=r(24278),o=r.n(n),a=r(86),i=r.n(a),s=r(11882),l=r.n(s),u=r(97606),c=r.n(u),p=r(14418),f=r.n(p),h=r(51679),d=r.n(h),m=r(24282),g=r.n(m),v=r(2578),y=r.n(v),b=r(92039),w=r.n(b),E=r(58309),x=r.n(E),_=r(20573),S=r(90242),A=r(43393);const k=["get","put","post","delete","options","head","patch","trace"],C=e=>e||(0,A.Map)(),O=(0,_.P1)(C,(e=>e.get("lastError"))),j=(0,_.P1)(C,(e=>e.get("url"))),I=(0,_.P1)(C,(e=>e.get("spec")||"")),N=(0,_.P1)(C,(e=>e.get("specSource")||"not-editor")),T=(0,_.P1)(C,(e=>e.get("json",(0,A.Map)()))),P=(0,_.P1)(C,(e=>e.get("resolved",(0,A.Map)()))),R=(e,t)=>e.getIn(["resolvedSubtrees",...t],void 0),M=(e,t)=>A.Map.isMap(e)&&A.Map.isMap(t)?t.get("$$ref")?t:(0,A.OrderedMap)().mergeWith(M,e,t):t,D=(0,_.P1)(C,(e=>(0,A.OrderedMap)().mergeWith(M,e.get("json"),e.get("resolvedSubtrees")))),L=e=>T(e),B=(0,_.P1)(L,(()=>!1)),F=(0,_.P1)(L,(e=>Ne(e&&e.get("info")))),z=(0,_.P1)(L,(e=>Ne(e&&e.get("externalDocs")))),U=(0,_.P1)(F,(e=>e&&e.get("version"))),q=(0,_.P1)(U,(e=>{var t;return o()(t=/v?([0-9]*)\.([0-9]*)\.([0-9]*)/i.exec(e)).call(t,1)})),V=(0,_.P1)(D,(e=>e.get("paths"))),$=(0,_.P1)(V,(e=>{if(!e||e.size<1)return(0,A.List)();let t=(0,A.List)();return e&&i()(e)?(i()(e).call(e,((e,r)=>{if(!e||!i()(e))return{};i()(e).call(e,((e,n)=>{l()(k).call(k,n)<0||(t=t.push((0,A.fromJS)({path:r,method:n,operation:e,id:`${n}-${r}`})))}))})),t):(0,A.List)()})),W=(0,_.P1)(L,(e=>(0,A.Set)(e.get("consumes")))),H=(0,_.P1)(L,(e=>(0,A.Set)(e.get("produces")))),J=(0,_.P1)(L,(e=>e.get("security",(0,A.List)()))),K=(0,_.P1)(L,(e=>e.get("securityDefinitions"))),G=(e,t)=>{const r=e.getIn(["resolvedSubtrees","definitions",t],null),n=e.getIn(["json","definitions",t],null);return r||n||null},Z=(0,_.P1)(L,(e=>{const t=e.get("definitions");return A.Map.isMap(t)?t:(0,A.Map)()})),Y=(0,_.P1)(L,(e=>e.get("basePath"))),Q=(0,_.P1)(L,(e=>e.get("host"))),X=(0,_.P1)(L,(e=>e.get("schemes",(0,A.Map)()))),ee=(0,_.P1)($,W,H,((e,t,r)=>c()(e).call(e,(e=>e.update("operation",(e=>{if(e){if(!A.Map.isMap(e))return;return e.withMutations((e=>(e.get("consumes")||e.update("consumes",(e=>(0,A.Set)(e).merge(t))),e.get("produces")||e.update("produces",(e=>(0,A.Set)(e).merge(r))),e)))}return(0,A.Map)()})))))),te=(0,_.P1)(L,(e=>{const t=e.get("tags",(0,A.List)());return A.List.isList(t)?f()(t).call(t,(e=>A.Map.isMap(e))):(0,A.List)()})),re=(e,t)=>{var r;let n=te(e)||(0,A.List)();return d()(r=f()(n).call(n,A.Map.isMap)).call(r,(e=>e.get("name")===t),(0,A.Map)())},ne=(0,_.P1)(ee,te,((e,t)=>g()(e).call(e,((e,t)=>{let r=(0,A.Set)(t.getIn(["operation","tags"]));return r.count()<1?e.update("default",(0,A.List)(),(e=>e.push(t))):g()(r).call(r,((e,r)=>e.update(r,(0,A.List)(),(e=>e.push(t)))),e)}),g()(t).call(t,((e,t)=>e.set(t.get("name"),(0,A.List)())),(0,A.OrderedMap)())))),oe=e=>t=>{var r;let{getConfigs:n}=t,{tagsSorter:o,operationsSorter:a}=n();return c()(r=ne(e).sortBy(((e,t)=>t),((e,t)=>{let r="function"==typeof o?o:S.wh.tagsSorter[o];return r?r(e,t):null}))).call(r,((t,r)=>{let n="function"==typeof a?a:S.wh.operationsSorter[a],o=n?y()(t).call(t,n):t;return(0,A.Map)({tagDetails:re(e,r),operations:o})}))},ae=(0,_.P1)(C,(e=>e.get("responses",(0,A.Map)()))),ie=(0,_.P1)(C,(e=>e.get("requests",(0,A.Map)()))),se=(0,_.P1)(C,(e=>e.get("mutatedRequests",(0,A.Map)()))),le=(e,t,r)=>ae(e).getIn([t,r],null),ue=(e,t,r)=>ie(e).getIn([t,r],null),ce=(e,t,r)=>se(e).getIn([t,r],null),pe=()=>!0,fe=(e,t,r)=>{const n=D(e).getIn(["paths",...t,"parameters"],(0,A.OrderedMap)()),o=e.getIn(["meta","paths",...t,"parameters"],(0,A.OrderedMap)()),a=c()(n).call(n,(e=>{const t=o.get(`${r.get("in")}.${r.get("name")}`),n=o.get(`${r.get("in")}.${r.get("name")}.hash-${r.hashCode()}`);return(0,A.OrderedMap)().merge(e,t,n)}));return d()(a).call(a,(e=>e.get("in")===r.get("in")&&e.get("name")===r.get("name")),(0,A.OrderedMap)())},he=(e,t,r,n)=>{const o=`${n}.${r}`;return e.getIn(["meta","paths",...t,"parameter_inclusions",o],!1)},de=(e,t,r,n)=>{const o=D(e).getIn(["paths",...t,"parameters"],(0,A.OrderedMap)()),a=d()(o).call(o,(e=>e.get("in")===n&&e.get("name")===r),(0,A.OrderedMap)());return fe(e,t,a)},me=(e,t,r)=>{var n;const o=D(e).getIn(["paths",t,r],(0,A.OrderedMap)()),a=e.getIn(["meta","paths",t,r],(0,A.OrderedMap)()),i=c()(n=o.get("parameters",(0,A.List)())).call(n,(n=>fe(e,[t,r],n)));return(0,A.OrderedMap)().merge(o,a).set("parameters",i)};function ge(e,t,r,n){t=t||[];let o=e.getIn(["meta","paths",...t,"parameters"],(0,A.fromJS)([]));return d()(o).call(o,(e=>A.Map.isMap(e)&&e.get("name")===r&&e.get("in")===n))||(0,A.Map)()}const ve=(0,_.P1)(L,(e=>{const t=e.get("host");return"string"==typeof t&&t.length>0&&"/"!==t[0]}));function ye(e,t,r){t=t||[];let n=me(e,...t).get("parameters",(0,A.List)());return g()(n).call(n,((e,t)=>{let n=r&&"body"===t.get("in")?t.get("value_xml"):t.get("value");return e.set((0,S.V9)(t,{allowHashes:!1}),n)}),(0,A.fromJS)({}))}function be(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";if(A.List.isList(e))return w()(e).call(e,(e=>A.Map.isMap(e)&&e.get("in")===t))}function we(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";if(A.List.isList(e))return w()(e).call(e,(e=>A.Map.isMap(e)&&e.get("type")===t))}function Ee(e,t){t=t||[];let r=D(e).getIn(["paths",...t],(0,A.fromJS)({})),n=e.getIn(["meta","paths",...t],(0,A.fromJS)({})),o=xe(e,t);const a=r.get("parameters")||new A.List,i=n.get("consumes_value")?n.get("consumes_value"):we(a,"file")?"multipart/form-data":we(a,"formData")?"application/x-www-form-urlencoded":void 0;return(0,A.fromJS)({requestContentType:i,responseContentType:o})}function xe(e,t){t=t||[];const r=D(e).getIn(["paths",...t],null);if(null===r)return;const n=e.getIn(["meta","paths",...t,"produces_value"],null),o=r.getIn(["produces",0],null);return n||o||"application/json"}function _e(e,t){t=t||[];const r=D(e),n=r.getIn(["paths",...t],null);if(null===n)return;const[o]=t,a=n.get("produces",null),i=r.getIn(["paths",o,"produces"],null),s=r.getIn(["produces"],null);return a||i||s}function Se(e,t){t=t||[];const r=D(e),n=r.getIn(["paths",...t],null);if(null===n)return;const[o]=t,a=n.get("consumes",null),i=r.getIn(["paths",o,"consumes"],null),s=r.getIn(["consumes"],null);return a||i||s}const Ae=(e,t,r)=>{let n=e.get("url").match(/^([a-z][a-z0-9+\-.]*):/),o=x()(n)?n[1]:null;return e.getIn(["scheme",t,r])||e.getIn(["scheme","_defaultScheme"])||o||""},ke=(e,t,r)=>{var n;return l()(n=["http","https"]).call(n,Ae(e,t,r))>-1},Ce=(e,t)=>{t=t||[];let r=e.getIn(["meta","paths",...t,"parameters"],(0,A.fromJS)([]));const n=[];return i()(r).call(r,(e=>{let t=e.get("errors");t&&t.count()&&i()(t).call(t,(e=>n.push(e)))})),n},Oe=(e,t)=>0===Ce(e,t).length,je=(e,t)=>{var r;let n={requestBody:!1,requestContentType:{}},o=e.getIn(["resolvedSubtrees","paths",...t,"requestBody"],(0,A.fromJS)([]));return o.size<1||(o.getIn(["required"])&&(n.requestBody=o.getIn(["required"])),i()(r=o.getIn(["content"]).entrySeq()).call(r,(e=>{const t=e[0];if(e[1].getIn(["schema","required"])){const r=e[1].getIn(["schema","required"]).toJS();n.requestContentType[t]=r}}))),n},Ie=(e,t,r,n)=>{if((r||n)&&r===n)return!0;let o=e.getIn(["resolvedSubtrees","paths",...t,"requestBody","content"],(0,A.fromJS)([]));if(o.size<2||!r||!n)return!1;let a=o.getIn([r,"schema","properties"],(0,A.fromJS)([])),i=o.getIn([n,"schema","properties"],(0,A.fromJS)([]));return!!a.equals(i)};function Ne(e){return A.Map.isMap(e)?e:new A.Map}},77508:(e,t,r)=>{"use strict";r.r(t),r.d(t,{updateSpec:()=>u,updateJsonSpec:()=>c,executeRequest:()=>p,validateParams:()=>f});var n=r(28222),o=r.n(n),a=r(86),i=r.n(a),s=r(27361),l=r.n(s);const u=(e,t)=>{let{specActions:r}=t;return function(){e(...arguments),r.parseToJson(...arguments)}},c=(e,t)=>{let{specActions:r}=t;return function(){for(var t=arguments.length,n=new Array(t),a=0;a{l()(u,[e]).$ref&&r.requestResolvedSubtree(["paths",e])})),r.requestResolvedSubtree(["components","securitySchemes"])}},p=(e,t)=>{let{specActions:r}=t;return t=>(r.logRequest(t),e(t))},f=(e,t)=>{let{specSelectors:r}=t;return t=>e(t,r.isOAS3())}},34852:(e,t,r)=>{"use strict";r.r(t),r.d(t,{loaded:()=>n});const n=(e,t)=>function(){e(...arguments);const r=t.getConfigs().withCredentials;void 0!==r&&(t.fn.fetch.withCredentials="string"==typeof r?"true"===r:!!r)}},48792:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>qr});var n={};r.r(n),r.d(n,{JsonPatchError:()=>Fe,_areEquals:()=>Ge,applyOperation:()=>$e,applyPatch:()=>We,applyReducer:()=>He,deepClone:()=>ze,getValueByPointer:()=>Ve,validate:()=>Ke,validator:()=>Je});var o={};r.r(o),r.d(o,{compare:()=>nt,generate:()=>tt,observe:()=>et,unobserve:()=>Xe});var a={};r.r(a),r.d(a,{cookie:()=>kr,header:()=>Ar,path:()=>xr,query:()=>_r});var i=r(80093),s=r.n(i),l=r(30222),u=r.n(l),c=r(36594),p=r.n(c),f=r(20474),h=r.n(f),d=r(67375),m=r.n(d),g=r(58118),v=r.n(g),y=r(74386),b=r.n(y),w=r(25110),E=r.n(w),x=r(35627),_=r.n(x),S=r(97606),A=r.n(S),k=r(28222),C=r.n(k),O=r(39022),j=r.n(O),I=r(2018),N=r.n(I),T=r(14418),P=r.n(T),R=(r(31905),r(80129)),M=r.n(R),D=r(1272);const L="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:window,{FormData:B,Blob:F,File:z}=L;var U=r(15687),q=r.n(U),V=r(24278),$=r.n(V),W=function(e){return":/?#[]@!$&'()*+,;=".indexOf(e)>-1},H=function(e){return/^[a-z0-9\-._~]+$/i.test(e)};function J(e){var t,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=r.escape,o=arguments.length>2?arguments[2]:void 0;return"number"==typeof e&&(e=e.toString()),"string"==typeof e&&e.length&&n?o?JSON.parse(e):A()(t=q()(e)).call(t,(function(e){var t,r;if(H(e))return e;if(W(e)&&"unsafe"===n)return e;var o=new TextEncoder;return A()(t=A()(r=E()(o.encode(e))).call(r,(function(e){var t;return $()(t="0".concat(e.toString(16).toUpperCase())).call(t,-2)}))).call(t,(function(e){return"%".concat(e)})).join("")})).join(""):e}function K(e){var t=e.value;return Array.isArray(t)?function(e){var t=e.key,r=e.value,n=e.style,o=e.explode,a=e.escape,i=function(e){return J(e,{escape:a})};if("simple"===n)return A()(r).call(r,(function(e){return i(e)})).join(",");if("label"===n)return".".concat(A()(r).call(r,(function(e){return i(e)})).join("."));if("matrix"===n)return A()(r).call(r,(function(e){return i(e)})).reduce((function(e,r){var n,a,i;return!e||o?j()(a=j()(i="".concat(e||"",";")).call(i,t,"=")).call(a,r):j()(n="".concat(e,",")).call(n,r)}),"");if("form"===n){var s=o?"&".concat(t,"="):",";return A()(r).call(r,(function(e){return i(e)})).join(s)}if("spaceDelimited"===n){var l=o?"".concat(t,"="):"";return A()(r).call(r,(function(e){return i(e)})).join(" ".concat(l))}if("pipeDelimited"===n){var u=o?"".concat(t,"="):"";return A()(r).call(r,(function(e){return i(e)})).join("|".concat(u))}return}(e):"object"===h()(t)?function(e){var t=e.key,r=e.value,n=e.style,o=e.explode,a=e.escape,i=function(e){return J(e,{escape:a})},s=C()(r);if("simple"===n)return s.reduce((function(e,t){var n,a,s,l=i(r[t]),u=o?"=":",",c=e?"".concat(e,","):"";return j()(n=j()(a=j()(s="".concat(c)).call(s,t)).call(a,u)).call(n,l)}),"");if("label"===n)return s.reduce((function(e,t){var n,a,s,l=i(r[t]),u=o?"=":".",c=e?"".concat(e,"."):".";return j()(n=j()(a=j()(s="".concat(c)).call(s,t)).call(a,u)).call(n,l)}),"");if("matrix"===n&&o)return s.reduce((function(e,t){var n,o,a=i(r[t]),s=e?"".concat(e,";"):";";return j()(n=j()(o="".concat(s)).call(o,t,"=")).call(n,a)}),"");if("matrix"===n)return s.reduce((function(e,n){var o,a,s=i(r[n]),l=e?"".concat(e,","):";".concat(t,"=");return j()(o=j()(a="".concat(l)).call(a,n,",")).call(o,s)}),"");if("form"===n)return s.reduce((function(e,t){var n,a,s,l,u=i(r[t]),c=e?j()(n="".concat(e)).call(n,o?"&":","):"",p=o?"=":",";return j()(a=j()(s=j()(l="".concat(c)).call(l,t)).call(s,p)).call(a,u)}),"");return}(e):function(e){var t,r=e.key,n=e.value,o=e.style,a=e.escape,i=function(e){return J(e,{escape:a})};if("simple"===o)return i(n);if("label"===o)return".".concat(i(n));if("matrix"===o)return j()(t=";".concat(r,"=")).call(t,i(n));if("form"===o)return i(n);if("deepObject"===o)return i(n,{},!0);return}(e)}const G=function(e,t){t.body=e};var Z={serializeRes:te,mergeInQueryOrForm:fe};function Y(e){return Q.apply(this,arguments)}function Q(){return Q=s()(u().mark((function e(t){var r,n,o,a,i,s=arguments;return u().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(r=s.length>1&&void 0!==s[1]?s[1]:{},"object"===h()(t)&&(t=(r=t).url),r.headers=r.headers||{},Z.mergeInQueryOrForm(r),r.headers&&C()(r.headers).forEach((function(e){var t=r.headers[e];"string"==typeof t&&(r.headers[e]=t.replace(/\n+/g," "))})),!r.requestInterceptor){e.next=12;break}return e.next=8,r.requestInterceptor(r);case 8:if(e.t0=e.sent,e.t0){e.next=11;break}e.t0=r;case 11:r=e.t0;case 12:return n=r.headers["content-type"]||r.headers["Content-Type"],/multipart\/form-data/i.test(n)&&r.body instanceof B&&(delete r.headers["content-type"],delete r.headers["Content-Type"]),e.prev=14,e.next=17,(r.userFetch||fetch)(r.url,r);case 17:return o=e.sent,e.next=20,Z.serializeRes(o,t,r);case 20:if(o=e.sent,!r.responseInterceptor){e.next=28;break}return e.next=24,r.responseInterceptor(o);case 24:if(e.t1=e.sent,e.t1){e.next=27;break}e.t1=o;case 27:o=e.t1;case 28:e.next=39;break;case 30:if(e.prev=30,e.t2=e.catch(14),o){e.next=34;break}throw e.t2;case 34:throw(a=new Error(o.statusText||"response status is ".concat(o.status))).status=o.status,a.statusCode=o.status,a.responseError=e.t2,a;case 39:if(o.ok){e.next=45;break}throw(i=new Error(o.statusText||"response status is ".concat(o.status))).status=o.status,i.statusCode=o.status,i.response=o,i;case 45:return e.abrupt("return",o);case 46:case"end":return e.stop()}}),e,null,[[14,30]])}))),Q.apply(this,arguments)}var X=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";return/(json|xml|yaml|text)\b/.test(e)};function ee(e,t){return t&&(0===t.indexOf("application/json")||t.indexOf("+json")>0)?JSON.parse(e):D.ZP.load(e)}function te(e,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},n=r.loadSpec,o=void 0!==n&&n,a={ok:e.ok,url:e.url||t,status:e.status,statusText:e.statusText,headers:ne(e.headers)},i=a.headers["content-type"],s=o||X(i),l=s?e.text:e.blob||e.buffer;return l.call(e).then((function(e){if(a.text=e,a.data=e,s)try{var t=ee(e,i);a.body=t,a.obj=t}catch(e){a.parseError=e}return a}))}function re(e){return v()(e).call(e,", ")?e.split(", "):e}function ne(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return"function"!=typeof b()(e)?{}:E()(b()(e).call(e)).reduce((function(e,t){var r=m()(t,2),n=r[0],o=r[1];return e[n]=re(o),e}),{})}function oe(e,t){return t||"undefined"==typeof navigator||(t=navigator),t&&"ReactNative"===t.product?!(!e||"object"!==h()(e)||"string"!=typeof e.uri):void 0!==z&&e instanceof z||(void 0!==F&&e instanceof F||(!!ArrayBuffer.isView(e)||null!==e&&"object"===h()(e)&&"function"==typeof e.pipe))}function ae(e,t){return Array.isArray(e)&&e.some((function(e){return oe(e,t)}))}var ie={form:",",spaceDelimited:"%20",pipeDelimited:"|"},se={csv:",",ssv:"%20",tsv:"%09",pipes:"|"};function le(e,t){var r=arguments.length>2&&void 0!==arguments[2]&&arguments[2],n=t.collectionFormat,o=t.allowEmptyValue,a=t.serializationOption,i=t.encoding,s="object"!==h()(t)||Array.isArray(t)?t:t.value,l=r?function(e){return e.toString()}:function(e){return encodeURIComponent(e)},u=l(e);if(void 0===s&&o)return[[u,""]];if(oe(s)||ae(s))return[[u,s]];if(a)return ue(e,s,r,a);if(i){if([h()(i.style),h()(i.explode),h()(i.allowReserved)].some((function(e){return"undefined"!==e}))){var c=i.style,p=i.explode,f=i.allowReserved;return ue(e,s,r,{style:c,explode:p,allowReserved:f})}if(i.contentType){if("application/json"===i.contentType){var d="string"==typeof s?s:_()(s);return[[u,l(d)]]}return[[u,l(s.toString())]]}return"object"!==h()(s)?[[u,l(s)]]:Array.isArray(s)&&s.every((function(e){return"object"!==h()(e)}))?[[u,A()(s).call(s,l).join(",")]]:[[u,l(_()(s))]]}return"object"!==h()(s)?[[u,l(s)]]:Array.isArray(s)?"multi"===n?[[u,A()(s).call(s,l)]]:[[u,A()(s).call(s,l).join(se[n||"csv"])]]:[[u,""]]}function ue(e,t,r,n){var o,a,i,s=n.style||"form",l=void 0===n.explode?"form"===s:n.explode,u=!r&&(n&&n.allowReserved?"unsafe":"reserved"),c=function(e){return J(e,{escape:u})},p=r?function(e){return e}:function(e){return J(e,{escape:u})};return"object"!==h()(t)?[[p(e),c(t)]]:Array.isArray(t)?l?[[p(e),A()(t).call(t,c)]]:[[p(e),A()(t).call(t,c).join(ie[s])]]:"deepObject"===s?A()(a=C()(t)).call(a,(function(r){var n;return[p(j()(n="".concat(e,"[")).call(n,r,"]")),c(t[r])]})):l?A()(i=C()(t)).call(i,(function(e){return[p(e),c(t[e])]})):[[p(e),A()(o=C()(t)).call(o,(function(e){var r;return[j()(r="".concat(p(e),",")).call(r,c(t[e]))]})).join(",")]]}function ce(e){return N()(e).reduce((function(e,t){var r,n=m()(t,2),o=n[0],a=n[1],i=p()(le(o,a,!0));try{for(i.s();!(r=i.n()).done;){var s=m()(r.value,2),l=s[0],u=s[1];if(Array.isArray(u)){var c,f=p()(u);try{for(f.s();!(c=f.n()).done;){var h=c.value;if(ArrayBuffer.isView(h)){var d=new F([h]);e.append(l,d)}else e.append(l,h)}}catch(e){f.e(e)}finally{f.f()}}else if(ArrayBuffer.isView(u)){var g=new F([u]);e.append(l,g)}else e.append(l,u)}}catch(e){i.e(e)}finally{i.f()}return e}),new B)}function pe(e){var t=C()(e).reduce((function(t,r){var n,o=p()(le(r,e[r]));try{for(o.s();!(n=o.n()).done;){var a=m()(n.value,2),i=a[0],s=a[1];t[i]=s}}catch(e){o.e(e)}finally{o.f()}return t}),{});return M().stringify(t,{encode:!1,indices:!1})||""}function fe(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.url,r=void 0===t?"":t,n=e.query,o=e.form,a=function(){for(var e=arguments.length,t=new Array(e),r=0;r=48&&t<=57))return!1;r++}return!0}function Re(e){return-1===e.indexOf("/")&&-1===e.indexOf("~")?e:e.replace(/~/g,"~0").replace(/\//g,"~1")}function Me(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")}function De(e){if(void 0===e)return!0;if(e)if(Array.isArray(e)){for(var t=0,r=e.length;t0&&"constructor"==s[u-1]))throw new TypeError("JSON-Patch: modifying `__proto__` or `constructor/prototype` prop is banned for security reasons, if this was on purpose, please set `banPrototypeModifications` flag false and pass it to this function. More info in fast-json-patch README");if(r&&void 0===p&&(void 0===l[f]?p=s.slice(0,u).join("/"):u==c-1&&(p=t.path),void 0!==p&&h(t,0,e,p)),u++,Array.isArray(l)){if("-"===f)f=l.length;else{if(r&&!Pe(f))throw new Fe("Expected an unsigned base-10 integer value, making the new referenced value the array element with the zero-based index","OPERATION_PATH_ILLEGAL_ARRAY_INDEX",a,t,e);Pe(f)&&(f=~~f)}if(u>=c){if(r&&"add"===t.op&&f>l.length)throw new Fe("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",a,t,e);if(!1===(i=qe[t.op].call(t,l,f,e)).test)throw new Fe("Test operation failed","TEST_OPERATION_FAILED",a,t,e);return i}}else if(u>=c){if(!1===(i=Ue[t.op].call(t,l,f,e)).test)throw new Fe("Test operation failed","TEST_OPERATION_FAILED",a,t,e);return i}if(l=l[f],r&&u0)throw new Fe('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",t,e,r);if(("move"===e.op||"copy"===e.op)&&"string"!=typeof e.from)throw new Fe("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",t,e,r);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&void 0===e.value)throw new Fe("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",t,e,r);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&De(e.value))throw new Fe("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED",t,e,r);if(r)if("add"==e.op){var o=e.path.split("/").length,a=n.split("/").length;if(o!==a+1&&o!==a)throw new Fe("Cannot perform an `add` operation at the desired path","OPERATION_PATH_CANNOT_ADD",t,e,r)}else if("replace"===e.op||"remove"===e.op||"_get"===e.op){if(e.path!==n)throw new Fe("Cannot perform the operation at a path that does not exist","OPERATION_PATH_UNRESOLVABLE",t,e,r)}else if("move"===e.op||"copy"===e.op){var i=Ke([{op:"_get",path:e.from,value:void 0}],r);if(i&&"OPERATION_PATH_UNRESOLVABLE"===i.name)throw new Fe("Cannot perform the operation from a path that does not exist","OPERATION_FROM_UNRESOLVABLE",t,e,r)}}function Ke(e,t,r){try{if(!Array.isArray(e))throw new Fe("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");if(t)We(Te(t),Te(e),r||!0);else{r=r||Je;for(var n=0;n0&&(e.patches=[],e.callback&&e.callback(n)),n}function rt(e,t,r,n,o){if(t!==e){"function"==typeof t.toJSON&&(t=t.toJSON());for(var a=Ne(t),i=Ne(e),s=!1,l=i.length-1;l>=0;l--){var u=e[p=i[l]];if(!Ie(t,p)||void 0===t[p]&&void 0!==u&&!1===Array.isArray(t))Array.isArray(e)===Array.isArray(t)?(o&&r.push({op:"test",path:n+"/"+Re(p),value:Te(u)}),r.push({op:"remove",path:n+"/"+Re(p)}),s=!0):(o&&r.push({op:"test",path:n,value:e}),r.push({op:"replace",path:n,value:t}),!0);else{var c=t[p];"object"==typeof u&&null!=u&&"object"==typeof c&&null!=c&&Array.isArray(u)===Array.isArray(c)?rt(u,c,r,n+"/"+Re(p),o):u!==c&&(!0,o&&r.push({op:"test",path:n+"/"+Re(p),value:Te(u)}),r.push({op:"replace",path:n+"/"+Re(p),value:Te(c)}))}}if(s||a.length!=i.length)for(l=0;l0){var o=t(e,r[r.length-1],r);o&&(n=j()(n).call(n,o))}if(Array.isArray(e)){var a=A()(e).call(e,(function(e,n){return pt(e,t,j()(r).call(r,n))}));a&&(n=j()(n).call(n,a))}else if(mt(e)){var i,s=A()(i=C()(e)).call(i,(function(n){return pt(e[n],t,j()(r).call(r,n))}));s&&(n=j()(n).call(n,s))}return n=ht(n)}function ft(e){return Array.isArray(e)?e:[e]}function ht(e){var t;return j()(t=[]).apply(t,q()(A()(e).call(e,(function(e){return Array.isArray(e)?ht(e):e}))))}function dt(e){return P()(e).call(e,(function(e){return void 0!==e}))}function mt(e){return e&&"object"===h()(e)}function gt(e){return e&&"function"==typeof e}function vt(e){if(wt(e)){var t=e.op;return"add"===t||"remove"===t||"replace"===t}return!1}function yt(e){return vt(e)||wt(e)&&"mutation"===e.type}function bt(e){return yt(e)&&("add"===e.op||"replace"===e.op||"merge"===e.op||"mergeDeep"===e.op)}function wt(e){return e&&"object"===h()(e)}function Et(e,t){try{return Ve(e,t)}catch(e){return console.error(e),{}}}var xt=r(28886),_t=r.n(xt),St=r(37659),At=r.n(St),kt=r(8575);function Ct(e,t){function r(){Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=(new Error).stack;for(var e=arguments.length,r=new Array(e),n=0;n-1&&-1===Nt.indexOf(r)||Tt.indexOf(n)>-1||Pt.some((function(e){return n.indexOf(e)>-1}))}function Mt(e,t){var r,n=e.split("#"),o=m()(n,2),a=o[0],i=o[1],s=kt.resolve(a||"",t||"");return i?j()(r="".concat(s,"#")).call(r,i):s}var Dt="application/json, application/yaml",Lt=/^([a-z]+:\/\/|\/\/)/i,Bt=Ct("JSONRefError",(function(e,t,r){this.originalError=r,Ee()(this,t||{})})),Ft={},zt=new(_t()),Ut=[function(e){return"paths"===e[0]&&"responses"===e[3]&&"examples"===e[5]},function(e){return"paths"===e[0]&&"responses"===e[3]&&"content"===e[5]&&"example"===e[7]},function(e){return"paths"===e[0]&&"responses"===e[3]&&"content"===e[5]&&"examples"===e[7]&&"value"===e[9]},function(e){return"paths"===e[0]&&"requestBody"===e[3]&&"content"===e[4]&&"example"===e[6]},function(e){return"paths"===e[0]&&"requestBody"===e[3]&&"content"===e[4]&&"examples"===e[6]&&"value"===e[8]},function(e){return"paths"===e[0]&&"parameters"===e[2]&&"example"===e[4]},function(e){return"paths"===e[0]&&"parameters"===e[3]&&"example"===e[5]},function(e){return"paths"===e[0]&&"parameters"===e[2]&&"examples"===e[4]&&"value"===e[6]},function(e){return"paths"===e[0]&&"parameters"===e[3]&&"examples"===e[5]&&"value"===e[7]},function(e){return"paths"===e[0]&&"parameters"===e[2]&&"content"===e[4]&&"example"===e[6]},function(e){return"paths"===e[0]&&"parameters"===e[2]&&"content"===e[4]&&"examples"===e[6]&&"value"===e[8]},function(e){return"paths"===e[0]&&"parameters"===e[3]&&"content"===e[4]&&"example"===e[7]},function(e){return"paths"===e[0]&&"parameters"===e[3]&&"content"===e[5]&&"examples"===e[7]&&"value"===e[9]}],qt={key:"$ref",plugin:function(e,t,r,n){var o=n.getInstance(),a=$()(r).call(r,0,-1);if(!Rt(a)&&!function(e){return Ut.some((function(t){return t(e)}))}(a)){var i=n.getContext(r).baseDoc;if("string"!=typeof e)return new Bt("$ref: must be a string (JSON-Ref)",{$ref:e,baseDoc:i,fullPath:r});var s,l,u,c=Jt(e),p=c[0],f=c[1]||"";try{s=i||p?Wt(p,i):null}catch(t){return Ht(t,{pointer:f,$ref:e,basePath:s,fullPath:r})}if(function(e,t,r,n){var o,a,i=zt.get(n);i||(i={},zt.set(n,i));var s=function(e){if(0===e.length)return"";return"/".concat(A()(e).call(e,Xt).join("/"))}(r),l=j()(o="".concat(t||"","#")).call(o,e),u=s.replace(/allOf\/\d+\/?/g,""),c=n.contextTree.get([]).baseDoc;if(t===c&&er(u,e))return!0;var p="",f=r.some((function(e){var t;return p=j()(t="".concat(p,"/")).call(t,Xt(e)),i[p]&&i[p].some((function(e){return er(e,l)||er(l,e)}))}));if(f)return!0;return void(i[u]=j()(a=i[u]||[]).call(a,l))}(f,s,a,n)&&!o.useCircularStructures){var h=Mt(e,s);return e===h?null:it.replace(r,h)}if(null==s?(u=Yt(f),void 0===(l=n.get(u))&&(l=new Bt("Could not resolve reference: ".concat(e),{pointer:f,$ref:e,baseDoc:i,fullPath:r}))):l=null!=(l=Kt(s,f)).__value?l.__value:l.catch((function(t){throw Ht(t,{pointer:f,$ref:e,baseDoc:i,fullPath:r})})),l instanceof Error)return[it.remove(r),l];var d=Mt(e,s),m=it.replace(a,l,{$$ref:d});if(s&&s!==i)return[m,it.context(a,{baseDoc:s})];try{if(!function(e,t){var r=[e];return t.path.reduce((function(e,t){return r.push(e[t]),e[t]}),e),n(t.value);function n(e){return it.isObject(e)&&(r.indexOf(e)>=0||C()(e).some((function(t){return n(e[t])})))}}(n.state,m)||o.useCircularStructures)return m}catch(e){return null}}}},Vt=Ee()(qt,{docCache:Ft,absoluteify:Wt,clearCache:function(e){void 0!==e?delete Ft[e]:C()(Ft).forEach((function(e){delete Ft[e]}))},JSONRefError:Bt,wrapError:Ht,getDoc:Gt,split:Jt,extractFromDoc:Kt,fetchJSON:function(e){return fetch(e,{headers:{Accept:Dt},loadSpec:!0}).then((function(e){return e.text()})).then((function(e){return D.ZP.load(e)}))},extract:Zt,jsonPointerToArray:Yt,unescapeJsonPointerToken:Qt});const $t=Vt;function Wt(e,t){if(!Lt.test(e)){var r;if(!t)throw new Bt(j()(r="Tried to resolve a relative URL, without having a basePath. path: '".concat(e,"' basePath: '")).call(r,t,"'"));return kt.resolve(t,e)}return e}function Ht(e,t){var r,n;e&&e.response&&e.response.body?r=j()(n="".concat(e.response.body.code," ")).call(n,e.response.body.message):r=e.message;return new Bt("Could not resolve reference: ".concat(r),t,e)}function Jt(e){return(e+"").split("#")}function Kt(e,t){var r=Ft[e];if(r&&!it.isPromise(r))try{var n=Zt(t,r);return Ee()(Ae().resolve(n),{__value:n})}catch(e){return Ae().reject(e)}return Gt(e).then((function(e){return Zt(t,e)}))}function Gt(e){var t=Ft[e];return t?it.isPromise(t)?t:Ae().resolve(t):(Ft[e]=Vt.fetchJSON(e).then((function(t){return Ft[e]=t,t})),Ft[e])}function Zt(e,t){var r=Yt(e);if(r.length<1)return t;var n=it.getIn(t,r);if(void 0===n)throw new Bt("Could not resolve pointer: ".concat(e," does not exist in document"),{pointer:e});return n}function Yt(e){var t;if("string"!=typeof e)throw new TypeError("Expected a string, got a ".concat(h()(e)));return"/"===e[0]&&(e=e.substr(1)),""===e?[]:A()(t=e.split("/")).call(t,Qt)}function Qt(e){return"string"!=typeof e?e:new(At())("=".concat(e.replace(/~1/g,"/").replace(/~0/g,"~"))).get("")}function Xt(e){var t,r=new(At())([["",e.replace(/~/g,"~0").replace(/\//g,"~1")]]);return $()(t=r.toString()).call(t,1)}function er(e,t){if(!(r=t)||"/"===r||"#"===r)return!0;var r,n=e.charAt(t.length),o=$()(t).call(t,-1);return 0===e.indexOf(t)&&(!n||"/"===n||"#"===n)&&"#"!==o}const tr={key:"allOf",plugin:function(e,t,r,n,o){if(!o.meta||!o.meta.$$ref){var a=$()(r).call(r,0,-1);if(!Rt(a)){if(!Array.isArray(e)){var i=new TypeError("allOf must be an array");return i.fullPath=r,i}var s=!1,l=o.value;if(a.forEach((function(e){l&&(l=l[e])})),l=me()({},l),0!==C()(l).length){delete l.allOf;var u,c,p=[];if(p.push(n.replace(a,{})),e.forEach((function(e,t){if(!n.isObject(e)){if(s)return null;s=!0;var o=new TypeError("Elements in allOf must be objects");return o.fullPath=r,p.push(o)}p.push(n.mergeDeep(a,e));var i=function(e,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},n=r.specmap,o=r.getBaseUrlForNodePath,a=void 0===o?function(e){var r;return n.getContext(j()(r=[]).call(r,q()(t),q()(e))).baseDoc}:o,i=r.targetKeys,s=void 0===i?["$ref","$$ref"]:i,l=[];return jt()(e).forEach((function(){if(v()(s).call(s,this.key)&&"string"==typeof this.node){var e=this.path,r=j()(t).call(t,this.path),o=Mt(this.node,a(e));l.push(n.replace(r,o))}})),l}(e,$()(r).call(r,0,-1),{getBaseUrlForNodePath:function(e){var o;return n.getContext(j()(o=[]).call(o,q()(r),[t],q()(e))).baseDoc},specmap:n});p.push.apply(p,q()(i))})),l.example)p.push(n.remove(j()(u=[]).call(u,a,"example")));if(p.push(n.mergeDeep(a,l)),!l.$$ref)p.push(n.remove(j()(c=[]).call(c,a,"$$ref")));return p}}}}},rr={key:"parameters",plugin:function(e,t,r,n){if(Array.isArray(e)&&e.length){var o=Ee()([],e),a=$()(r).call(r,0,-1),i=me()({},it.getIn(n.spec,a));return e.forEach((function(e,t){try{o[t].default=n.parameterMacro(i,e)}catch(e){var a=new Error(e);return a.fullPath=r,a}})),it.replace(r,o)}return it.replace(r,e)}},nr={key:"properties",plugin:function(e,t,r,n){var o=me()({},e);for(var a in e)try{o[a].default=n.modelPropertyMacro(o[a])}catch(e){var i=new Error(e);return i.fullPath=r,i}return it.replace(r,o)}};var or=function(){function e(t){ve()(this,e),this.root=ar(t||{})}return be()(e,[{key:"set",value:function(e,t){var r=this.getParent(e,!0);if(r){var n=e[e.length-1],o=r.children;o[n]?ir(o[n],t,r):o[n]=ar(t,r)}else ir(this.root,t,null)}},{key:"get",value:function(e){if((e=e||[]).length<1)return this.root.value;for(var t,r,n=this.root,o=0;o1?r-1:0),o=1;o1?n-1:0),a=1;a0}))}},{key:"nextPromisedPatch",value:function(){var e;if(this.promisedPatches.length>0)return Ae().race(A()(e=this.promisedPatches).call(e,(function(e){return e.value})))}},{key:"getPluginHistory",value:function(e){var t=this.constructor.getPluginName(e);return this.pluginHistory[t]||[]}},{key:"getPluginRunCount",value:function(e){return this.getPluginHistory(e).length}},{key:"getPluginHistoryTip",value:function(e){var t=this.getPluginHistory(e);return t&&t[t.length-1]||{}}},{key:"getPluginMutationIndex",value:function(e){var t=this.getPluginHistoryTip(e).mutationIndex;return"number"!=typeof t?-1:t}},{key:"updatePluginHistory",value:function(e,t){var r=this.constructor.getPluginName(e);this.pluginHistory[r]=this.pluginHistory[r]||[],this.pluginHistory[r].push(t)}},{key:"updatePatches",value:function(e){var t=this;it.normalizeArray(e).forEach((function(e){if(e instanceof Error)t.errors.push(e);else try{if(!it.isObject(e))return void t.debug("updatePatches","Got a non-object patch",e);if(t.showDebug&&t.allPatches.push(e),it.isPromise(e.value))return t.promisedPatches.push(e),void t.promisedPatchThen(e);if(it.isContextPatch(e))return void t.setContext(e.path,e.value);if(it.isMutation(e))return void t.updateMutations(e)}catch(e){console.error(e),t.errors.push(e)}}))}},{key:"updateMutations",value:function(e){"object"===h()(e.value)&&!Array.isArray(e.value)&&this.allowMetaPatches&&(e.value=me()({},e.value));var t=it.applyPatch(this.state,e,{allowMetaPatches:this.allowMetaPatches});t&&(this.mutations.push(e),this.state=t)}},{key:"removePromisedPatch",value:function(e){var t,r=this.promisedPatches.indexOf(e);r<0?this.debug("Tried to remove a promisedPatch that isn't there!"):Ce()(t=this.promisedPatches).call(t,r,1)}},{key:"promisedPatchThen",value:function(e){var t=this;return e.value=e.value.then((function(r){var n=me()(me()({},e),{},{value:r});t.removePromisedPatch(e),t.updatePatches(n)})).catch((function(r){t.removePromisedPatch(e),t.updatePatches(r)})),e.value}},{key:"getMutations",value:function(e,t){var r;return e=e||0,"number"!=typeof t&&(t=this.mutations.length),$()(r=this.mutations).call(r,e,t)}},{key:"getCurrentMutations",value:function(){return this.getMutationsForPlugin(this.getCurrentPlugin())}},{key:"getMutationsForPlugin",value:function(e){var t=this.getPluginMutationIndex(e);return this.getMutations(t+1)}},{key:"getCurrentPlugin",value:function(){return this.currentPlugin}},{key:"getLib",value:function(){return this.libMethods}},{key:"_get",value:function(e){return it.getIn(this.state,e)}},{key:"_getContext",value:function(e){return this.contextTree.get(e)}},{key:"setContext",value:function(e,t){return this.contextTree.set(e,t)}},{key:"_hasRun",value:function(e){return this.getPluginRunCount(this.getCurrentPlugin())>(e||0)}},{key:"dispatch",value:function(){var e,t=this,r=this,n=this.nextPlugin();if(!n){var o=this.nextPromisedPatch();if(o)return o.then((function(){return t.dispatch()})).catch((function(){return t.dispatch()}));var a={spec:this.state,errors:this.errors};return this.showDebug&&(a.patches=this.allPatches),Ae().resolve(a)}if(r.pluginCount=r.pluginCount||{},r.pluginCount[n]=(r.pluginCount[n]||0)+1,r.pluginCount[n]>100)return Ae().resolve({spec:r.state,errors:j()(e=r.errors).call(e,new Error("We've reached a hard limit of ".concat(100," plugin runs")))});if(n!==this.currentPlugin&&this.promisedPatches.length){var i,s=A()(i=this.promisedPatches).call(i,(function(e){return e.value}));return Ae().all(A()(s).call(s,(function(e){return e.then(sr,sr)}))).then((function(){return t.dispatch()}))}return function(){r.currentPlugin=n;var e=r.getCurrentMutations(),t=r.mutations.length-1;try{if(n.isGenerator){var o,a=p()(n(e,r.getLib()));try{for(a.s();!(o=a.n()).done;){l(o.value)}}catch(e){a.e(e)}finally{a.f()}}else{l(n(e,r.getLib()))}}catch(e){console.error(e),l([Ee()(Object.create(e),{plugin:n})])}finally{r.updatePluginHistory(n,{mutationIndex:t})}return r.dispatch()}();function l(e){e&&(e=it.fullyNormalizeArray(e),r.updatePatches(e,n))}}}],[{key:"getPluginName",value:function(e){return e.pluginName}},{key:"getPatchesOfType",value:function(e,t){return P()(e).call(e,t)}}]),e}();var ur={refs:$t,allOf:tr,parameters:rr,properties:nr},cr=r(23159);function pr(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=t.requestInterceptor,n=t.responseInterceptor,o=e.withCredentials?"include":"same-origin";return function(t){return e({url:t,loadSpec:!0,requestInterceptor:r,responseInterceptor:n,headers:{Accept:Dt},credentials:o}).then((function(e){return e.body}))}}function fr(e){var t=e.fetch,r=e.spec,n=e.url,o=e.mode,a=e.allowMetaPatches,i=void 0===a||a,l=e.pathDiscriminator,c=e.modelPropertyMacro,p=e.parameterMacro,f=e.requestInterceptor,h=e.responseInterceptor,d=e.skipNormalization,m=e.useCircularStructures,g=e.http,v=e.baseDoc;return v=v||n,g=t||g||Y,r?y(r):pr(g,{requestInterceptor:f,responseInterceptor:h})(v).then(y);function y(e){v&&(ur.refs.docCache[v]=e),ur.refs.fetchJSON=pr(g,{requestInterceptor:f,responseInterceptor:h});var t,r=[ur.refs];return"function"==typeof p&&r.push(ur.parameters),"function"==typeof c&&r.push(ur.properties),"strict"!==o&&r.push(ur.allOf),(t={spec:e,context:{baseDoc:v},plugins:r,allowMetaPatches:i,pathDiscriminator:l,parameterMacro:p,modelPropertyMacro:c,useCircularStructures:m},new lr(t).dispatch()).then(d?function(){var e=s()(u().mark((function e(t){return u().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.abrupt("return",t);case 1:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}():cr.K1)}}var hr=r(88436),dr=r.n(hr),mr=r(27361),gr=r.n(mr),vr=r(76489);function yr(e){return"[object Object]"===Object.prototype.toString.call(e)}function br(e){var t,r;return!1!==yr(e)&&(void 0===(t=e.constructor)||!1!==yr(r=t.prototype)&&!1!==r.hasOwnProperty("isPrototypeOf"))}const wr={body:function(e){var t=e.req,r=e.value;t.body=r},header:function(e){var t=e.req,r=e.parameter,n=e.value;t.headers=t.headers||{},void 0!==n&&(t.headers[r.name]=n)},query:function(e){var t=e.req,r=e.value,n=e.parameter;t.query=t.query||{},!1===r&&"boolean"===n.type&&(r="false");0===r&&["number","integer"].indexOf(n.type)>-1&&(r="0");if(r)t.query[n.name]={collectionFormat:n.collectionFormat,value:r};else if(n.allowEmptyValue&&void 0!==r){var o=n.name;t.query[o]=t.query[o]||{},t.query[o].allowEmptyValue=!0}},path:function(e){var t=e.req,r=e.value,n=e.parameter;t.url=t.url.split("{".concat(n.name,"}")).join(encodeURIComponent(r))},formData:function(e){var t=e.req,r=e.value,n=e.parameter;(r||n.allowEmptyValue)&&(t.form=t.form||{},t.form[n.name]={value:r,allowEmptyValue:n.allowEmptyValue,collectionFormat:n.collectionFormat})}};function Er(e,t){return v()(t).call(t,"application/json")?"string"==typeof e?e:_()(e):e.toString()}function xr(e){var t=e.req,r=e.value,n=e.parameter,o=n.name,a=n.style,i=n.explode,s=n.content;if(s){var l=C()(s)[0];t.url=t.url.split("{".concat(o,"}")).join(J(Er(r,l),{escape:!0}))}else{var u=K({key:n.name,value:r,style:a||"simple",explode:i||!1,escape:!0});t.url=t.url.split("{".concat(o,"}")).join(u)}}function _r(e){var t=e.req,r=e.value,n=e.parameter;if(t.query=t.query||{},n.content){var o=C()(n.content)[0];t.query[n.name]=Er(r,o)}else if(!1===r&&(r="false"),0===r&&(r="0"),r){var a=n.style,i=n.explode,s=n.allowReserved;t.query[n.name]={value:r,serializationOption:{style:a,explode:i,allowReserved:s}}}else if(n.allowEmptyValue&&void 0!==r){var l=n.name;t.query[l]=t.query[l]||{},t.query[l].allowEmptyValue=!0}}var Sr=["accept","authorization","content-type"];function Ar(e){var t=e.req,r=e.parameter,n=e.value;if(t.headers=t.headers||{},!(Sr.indexOf(r.name.toLowerCase())>-1))if(r.content){var o=C()(r.content)[0];t.headers[r.name]=Er(n,o)}else void 0!==n&&(t.headers[r.name]=K({key:r.name,value:n,style:r.style||"simple",explode:void 0!==r.explode&&r.explode,escape:!1}))}function kr(e){var t=e.req,r=e.parameter,n=e.value;t.headers=t.headers||{};var o=h()(n);if(r.content){var a,i=C()(r.content)[0];t.headers.Cookie=j()(a="".concat(r.name,"=")).call(a,Er(n,i))}else if("undefined"!==o){var s="object"===o&&!Array.isArray(n)&&r.explode?"":"".concat(r.name,"=");t.headers.Cookie=s+K({key:r.name,value:n,escape:!1,style:r.style||"form",explode:void 0!==r.explode&&r.explode})}}var Cr=r(92381),Or=r.n(Cr);const jr=(void 0!==Or()?Or():"undefined"!=typeof self?self:window).btoa;function Ir(e,t){var r=e.operation,n=e.requestBody,o=e.securities,a=e.spec,i=e.attachContentTypeForEmptyPayload,s=e.requestContentType;t=function(e){var t=e.request,r=e.securities,n=void 0===r?{}:r,o=e.operation,a=void 0===o?{}:o,i=e.spec,s=me()({},t),l=n.authorized,u=void 0===l?{}:l,c=a.security||i.security||[],p=u&&!!C()(u).length,f=gr()(i,["components","securitySchemes"])||{};if(s.headers=s.headers||{},s.query=s.query||{},!C()(n).length||!p||!c||Array.isArray(a.security)&&!a.security.length)return t;return c.forEach((function(e){C()(e).forEach((function(e){var t=u[e],r=f[e];if(t){var n=t.value||t,o=r.type;if(t)if("apiKey"===o)"query"===r.in&&(s.query[r.name]=n),"header"===r.in&&(s.headers[r.name]=n),"cookie"===r.in&&(s.cookies[r.name]=n);else if("http"===o){if(/^basic$/i.test(r.scheme)){var a,i=n.username||"",l=n.password||"",c=jr(j()(a="".concat(i,":")).call(a,l));s.headers.Authorization="Basic ".concat(c)}/^bearer$/i.test(r.scheme)&&(s.headers.Authorization="Bearer ".concat(n))}else if("oauth2"===o||"openIdConnect"===o){var p,h=t.token||{},d=h[r["x-tokenName"]||"access_token"],m=h.token_type;m&&"bearer"!==m.toLowerCase()||(m="Bearer"),s.headers.Authorization=j()(p="".concat(m," ")).call(p,d)}}}))})),s}({request:t,securities:o,operation:r,spec:a});var l=r.requestBody||{},u=C()(l.content||{}),c=s&&u.indexOf(s)>-1;if(n||i){if(s&&c)t.headers["Content-Type"]=s;else if(!s){var p=u[0];p&&(t.headers["Content-Type"]=p,s=p)}}else s&&c&&(t.headers["Content-Type"]=s);if(!e.responseContentType&&r.responses){var f,d=P()(f=N()(r.responses)).call(f,(function(e){var t=m()(e,2),r=t[0],n=t[1],o=parseInt(r,10);return o>=200&&o<300&&br(n.content)})).reduce((function(e,t){var r=m()(t,2)[1];return j()(e).call(e,C()(r.content))}),[]);d.length>0&&(t.headers.accept=d.join(", "))}if(n)if(s){if(u.indexOf(s)>-1)if("application/x-www-form-urlencoded"===s||"multipart/form-data"===s)if("object"===h()(n)){var g=(l.content[s]||{}).encoding||{};t.form={},C()(n).forEach((function(e){t.form[e]={value:n[e],encoding:g[e]||{}}}))}else t.form=n;else t.body=n}else t.body=n;return t}function Nr(e,t){var r,n,o=e.spec,a=e.operation,i=e.securities,s=e.requestContentType,l=e.responseContentType,u=e.attachContentTypeForEmptyPayload;if(t=function(e){var t=e.request,r=e.securities,n=void 0===r?{}:r,o=e.operation,a=void 0===o?{}:o,i=e.spec,s=me()({},t),l=n.authorized,u=void 0===l?{}:l,c=n.specSecurity,p=void 0===c?[]:c,f=a.security||p,h=u&&!!C()(u).length,d=i.securityDefinitions;if(s.headers=s.headers||{},s.query=s.query||{},!C()(n).length||!h||!f||Array.isArray(a.security)&&!a.security.length)return t;return f.forEach((function(e){C()(e).forEach((function(e){var t=u[e];if(t){var r=t.token,n=t.value||t,o=d[e],a=o.type,i=o["x-tokenName"]||"access_token",l=r&&r[i],c=r&&r.token_type;if(t)if("apiKey"===a){var p="query"===o.in?"query":"headers";s[p]=s[p]||{},s[p][o.name]=n}else if("basic"===a)if(n.header)s.headers.authorization=n.header;else{var f,h=n.username||"",m=n.password||"";n.base64=jr(j()(f="".concat(h,":")).call(f,m)),s.headers.authorization="Basic ".concat(n.base64)}else if("oauth2"===a&&l){var g;c=c&&"bearer"!==c.toLowerCase()?c:"Bearer",s.headers.authorization=j()(g="".concat(c," ")).call(g,l)}}}))})),s}({request:t,securities:i,operation:a,spec:o}),t.body||t.form||u)if(s)t.headers["Content-Type"]=s;else if(Array.isArray(a.consumes)){var c=m()(a.consumes,1);t.headers["Content-Type"]=c[0]}else if(Array.isArray(o.consumes)){var p=m()(o.consumes,1);t.headers["Content-Type"]=p[0]}else a.parameters&&P()(r=a.parameters).call(r,(function(e){return"file"===e.type})).length?t.headers["Content-Type"]="multipart/form-data":a.parameters&&P()(n=a.parameters).call(n,(function(e){return"formData"===e.in})).length&&(t.headers["Content-Type"]="application/x-www-form-urlencoded");else if(s){var f,h,d=a.parameters&&P()(f=a.parameters).call(f,(function(e){return"body"===e.in})).length>0,g=a.parameters&&P()(h=a.parameters).call(h,(function(e){return"formData"===e.in})).length>0;(d||g)&&(t.headers["Content-Type"]=s)}return!l&&Array.isArray(a.produces)&&a.produces.length>0&&(t.headers.accept=a.produces.join(", ")),t}var Tr=["http","fetch","spec","operationId","pathName","method","parameters","securities"],Pr=function(e){return Array.isArray(e)?e:[]},Rr=Ct("OperationNotFoundError",(function(e,t,r){this.originalError=r,Ee()(this,t||{})})),Mr={buildRequest:Lr};function Dr(e){var t=e.http,r=e.fetch,n=e.spec,o=e.operationId,a=e.pathName,i=e.method,s=e.parameters,l=e.securities,u=dr()(e,Tr),c=t||r||Y;a&&i&&!o&&(o=(0,cr.nc)(a,i));var p=Mr.buildRequest(me()({spec:n,operationId:o,parameters:s,securities:l,http:c},u));return p.body&&(br(p.body)||Array.isArray(p.body))&&(p.body=_()(p.body)),c(p)}function Lr(e){var t,r,n=e.spec,o=e.operationId,i=e.responseContentType,s=e.scheme,l=e.requestInterceptor,u=e.responseInterceptor,c=e.contextUrl,p=e.userFetch,f=e.server,h=e.serverVariables,d=e.http,g=e.signal,v=e.parameters,y=e.parameterBuilders,b=(0,cr.z6)(n);y||(y=b?a:wr);var w={url:"",credentials:d&&d.withCredentials?"include":"same-origin",headers:{},cookies:{}};g&&(w.signal=g),l&&(w.requestInterceptor=l),u&&(w.responseInterceptor=u),p&&(w.userFetch=p);var E=(0,cr.$r)(n,o);if(!E)throw new Rr("Operation ".concat(o," not found"));var x,_=E.operation,S=void 0===_?{}:_,k=E.method,O=E.pathName;if(w.url+=(x={spec:n,scheme:s,contextUrl:c,server:f,serverVariables:h,pathName:O,method:k},(0,cr.z6)(x.spec)?function(e){var t=e.spec,r=e.pathName,n=e.method,o=e.server,a=e.contextUrl,i=e.serverVariables,s=void 0===i?{}:i,l=gr()(t,["paths",r,(n||"").toLowerCase(),"servers"])||gr()(t,["paths",r,"servers"])||gr()(t,["servers"]),u="",c=null;if(o&&l&&l.length){var p=A()(l).call(l,(function(e){return e.url}));p.indexOf(o)>-1&&(u=o,c=l[p.indexOf(o)])}if(!u&&l&&l.length){u=l[0].url;var f=m()(l,1);c=f[0]}return u.indexOf("{")>-1&&function(e){for(var t,r=[],n=/{([^}]+)}/g;t=n.exec(e);)r.push(t[1]);return r}(u).forEach((function(e){if(c.variables&&c.variables[e]){var t=c.variables[e],r=s[e]||t.default,n=new RegExp("{".concat(e,"}"),"g");u=u.replace(n,r)}})),function(){var e,t,r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",o=r&&n?kt.parse(kt.resolve(n,r)):kt.parse(r),a=kt.parse(n),i=Br(o.protocol)||Br(a.protocol)||"",s=o.host||a.host,l=o.pathname||"";return"/"===(e=i&&s?j()(t="".concat(i,"://")).call(t,s+l):l)[e.length-1]?$()(e).call(e,0,-1):e}(u,a)}(x):function(e){var t,r,n=e.spec,o=e.scheme,a=e.contextUrl,i=void 0===a?"":a,s=kt.parse(i),l=Array.isArray(n.schemes)?n.schemes[0]:null,u=o||l||Br(s.protocol)||"http",c=n.host||s.host||"",p=n.basePath||"";return"/"===(t=u&&c?j()(r="".concat(u,"://")).call(r,c+p):p)[t.length-1]?$()(t).call(t,0,-1):t}(x)),!o)return delete w.cookies,w;w.url+=O,w.method="".concat(k).toUpperCase(),v=v||{};var I=n.paths[O]||{};i&&(w.headers.accept=i);var N=function(e){var t={};e.forEach((function(e){t[e.in]||(t[e.in]={}),t[e.in][e.name]=e}));var r=[];return C()(t).forEach((function(e){C()(t[e]).forEach((function(n){r.push(t[e][n])}))})),r}(j()(t=j()(r=[]).call(r,Pr(S.parameters))).call(t,Pr(I.parameters)));N.forEach((function(e){var t,r,o=y[e.in];if("body"===e.in&&e.schema&&e.schema.properties&&(t=v),void 0===(t=e&&e.name&&v[e.name]))t=e&&e.name&&v[j()(r="".concat(e.in,".")).call(r,e.name)];else if(function(e,t){return P()(t).call(t,(function(t){return t.name===e}))}(e.name,N).length>1){var a;console.warn(j()(a="Parameter '".concat(e.name,"' is ambiguous because the defined spec has more than one parameter with the name: '")).call(a,e.name,"' and the passed-in parameter values did not define an 'in' value."))}if(null!==t){if(void 0!==e.default&&void 0===t&&(t=e.default),void 0===t&&e.required&&!e.allowEmptyValue)throw new Error("Required parameter ".concat(e.name," is not provided"));if(b&&e.schema&&"object"===e.schema.type&&"string"==typeof t)try{t=JSON.parse(t)}catch(e){throw new Error("Could not parse object parameter value string as JSON")}o&&o({req:w,parameter:e,value:t,operation:S,spec:n})}}));var T=me()(me()({},e),{},{operation:S});if((w=b?Ir(T,w):Nr(T,w)).cookies&&C()(w.cookies).length){var R=C()(w.cookies).reduce((function(e,t){var r=w.cookies[t];return e+(e?"&":"")+vr.serialize(t,r)}),"");w.headers.Cookie=R}return w.cookies&&delete w.cookies,fe(w),w}var Br=function(e){return e?e.replace(/\W/g,""):null};function Fr(e,t){return zr.apply(this,arguments)}function zr(){return zr=s()(u().mark((function e(t,r){var n,o,a,i,s,l,c,p,f,h,d,m,g=arguments;return u().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n=g.length>2&&void 0!==g[2]?g[2]:{},o=n.returnEntireTree,a=n.baseDoc,i=n.requestInterceptor,s=n.responseInterceptor,l=n.parameterMacro,c=n.modelPropertyMacro,p=n.useCircularStructures,f={pathDiscriminator:r,baseDoc:a,requestInterceptor:i,responseInterceptor:s,parameterMacro:l,modelPropertyMacro:c,useCircularStructures:p},h=(0,cr.K1)({spec:t}),d=h.spec,e.next=6,fr(me()(me()({},f),{},{spec:d,allowMetaPatches:!0,skipNormalization:!0}));case 6:return m=e.sent,!o&&Array.isArray(r)&&r.length&&(m.spec=gr()(m.spec,r)||null),e.abrupt("return",m);case 9:case"end":return e.stop()}}),e)}))),zr.apply(this,arguments)}var Ur=r(34852);function qr(e){let{configs:t,getConfigs:r}=e;return{fn:{fetch:(n=Y,o=t.preFetch,a=t.postFetch,a=a||function(e){return e},o=o||function(e){return e},function(e){return"string"==typeof e&&(e={url:e}),Z.mergeInQueryOrForm(e),e=o(e),a(n(e))}),buildRequest:Lr,execute:Dr,resolve:fr,resolveSubtree:function(e,t,n){if(void 0===n){const e=r();n={modelPropertyMacro:e.modelPropertyMacro,parameterMacro:e.parameterMacro,requestInterceptor:e.requestInterceptor,responseInterceptor:e.responseInterceptor}}for(var o=arguments.length,a=new Array(o>3?o-3:0),i=3;i{"use strict";r.r(t),r.d(t,{default:()=>o});var n=r(90242);function o(){return{fn:{shallowEqualKeys:n.be}}}},48347:(e,t,r)=>{"use strict";r.r(t),r.d(t,{getDisplayName:()=>n});const n=e=>e.displayName||e.name||"Component"},73420:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>u});var n=r(35627),o=r.n(n),a=r(90242),i=r(55776),s=r(48347),l=r(60314);const u=e=>{let{getComponents:t,getStore:r,getSystem:n}=e;const u=(c=(0,i.getComponent)(n,r,t),(0,a.HP)(c,(function(){for(var e=arguments.length,t=new Array(e),r=0;r(0,l.Z)(e,(function(){for(var e=arguments.length,t=new Array(e),r=0;r{"use strict";r.r(t),r.d(t,{getComponent:()=>ne,render:()=>re,withMappedContainer:()=>te});var n=r(23101),o=r.n(n),a=r(28222),i=r.n(a),s=r(67294),l=r(73935),u=r(97779),c=s.createContext(null);var p=function(e){e()},f=function(){return p},h={notify:function(){}};var d=function(){function e(e,t){this.store=e,this.parentSub=t,this.unsubscribe=null,this.listeners=h,this.handleChangeWrapper=this.handleChangeWrapper.bind(this)}var t=e.prototype;return t.addNestedSub=function(e){return this.trySubscribe(),this.listeners.subscribe(e)},t.notifyNestedSubs=function(){this.listeners.notify()},t.handleChangeWrapper=function(){this.onStateChange&&this.onStateChange()},t.isSubscribed=function(){return Boolean(this.unsubscribe)},t.trySubscribe=function(){this.unsubscribe||(this.unsubscribe=this.parentSub?this.parentSub.addNestedSub(this.handleChangeWrapper):this.store.subscribe(this.handleChangeWrapper),this.listeners=function(){var e=f(),t=null,r=null;return{clear:function(){t=null,r=null},notify:function(){e((function(){for(var e=t;e;)e.callback(),e=e.next}))},get:function(){for(var e=[],r=t;r;)e.push(r),r=r.next;return e},subscribe:function(e){var n=!0,o=r={callback:e,next:null,prev:r};return o.prev?o.prev.next=o:t=o,function(){n&&null!==t&&(n=!1,o.next?o.next.prev=o.prev:r=o.prev,o.prev?o.prev.next=o.next:t=o.next)}}}}())},t.tryUnsubscribe=function(){this.unsubscribe&&(this.unsubscribe(),this.unsubscribe=null,this.listeners.clear(),this.listeners=h)},e}(),m="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement?s.useLayoutEffect:s.useEffect;const g=function(e){var t=e.store,r=e.context,n=e.children,o=(0,s.useMemo)((function(){var e=new d(t);return e.onStateChange=e.notifyNestedSubs,{store:t,subscription:e}}),[t]),a=(0,s.useMemo)((function(){return t.getState()}),[t]);m((function(){var e=o.subscription;return e.trySubscribe(),a!==t.getState()&&e.notifyNestedSubs(),function(){e.tryUnsubscribe(),e.onStateChange=null}}),[o,a]);var i=r||c;return s.createElement(i.Provider,{value:o},n)};var v=r(87462),y=r(63366),b=r(8679),w=r.n(b),E=r(72973),x=[],_=[null,null];function S(e,t){var r=e[1];return[t.payload,r+1]}function A(e,t,r){m((function(){return e.apply(void 0,t)}),r)}function k(e,t,r,n,o,a,i){e.current=n,t.current=o,r.current=!1,a.current&&(a.current=null,i())}function C(e,t,r,n,o,a,i,s,l,u){if(e){var c=!1,p=null,f=function(){if(!c){var e,r,f=t.getState();try{e=n(f,o.current)}catch(e){r=e,p=e}r||(p=null),e===a.current?i.current||l():(a.current=e,s.current=e,i.current=!0,u({type:"STORE_UPDATED",payload:{error:r}}))}};r.onStateChange=f,r.trySubscribe(),f();return function(){if(c=!0,r.tryUnsubscribe(),r.onStateChange=null,p)throw p}}}var O=function(){return[null,0]};function j(e,t){void 0===t&&(t={});var r=t,n=r.getDisplayName,o=void 0===n?function(e){return"ConnectAdvanced("+e+")"}:n,a=r.methodName,i=void 0===a?"connectAdvanced":a,l=r.renderCountProp,u=void 0===l?void 0:l,p=r.shouldHandleStateChanges,f=void 0===p||p,h=r.storeKey,m=void 0===h?"store":h,g=(r.withRef,r.forwardRef),b=void 0!==g&&g,j=r.context,I=void 0===j?c:j,N=(0,y.Z)(r,["getDisplayName","methodName","renderCountProp","shouldHandleStateChanges","storeKey","withRef","forwardRef","context"]),T=I;return function(t){var r=t.displayName||t.name||"Component",n=o(r),a=(0,v.Z)({},N,{getDisplayName:o,methodName:i,renderCountProp:u,shouldHandleStateChanges:f,storeKey:m,displayName:n,wrappedComponentName:r,WrappedComponent:t}),l=N.pure;var c=l?s.useMemo:function(e){return e()};function p(r){var n=(0,s.useMemo)((function(){var e=r.reactReduxForwardedRef,t=(0,y.Z)(r,["reactReduxForwardedRef"]);return[r.context,e,t]}),[r]),o=n[0],i=n[1],l=n[2],u=(0,s.useMemo)((function(){return o&&o.Consumer&&(0,E.isContextConsumer)(s.createElement(o.Consumer,null))?o:T}),[o,T]),p=(0,s.useContext)(u),h=Boolean(r.store)&&Boolean(r.store.getState)&&Boolean(r.store.dispatch);Boolean(p)&&Boolean(p.store);var m=h?r.store:p.store,g=(0,s.useMemo)((function(){return function(t){return e(t.dispatch,a)}(m)}),[m]),b=(0,s.useMemo)((function(){if(!f)return _;var e=new d(m,h?null:p.subscription),t=e.notifyNestedSubs.bind(e);return[e,t]}),[m,h,p]),w=b[0],j=b[1],I=(0,s.useMemo)((function(){return h?p:(0,v.Z)({},p,{subscription:w})}),[h,p,w]),N=(0,s.useReducer)(S,x,O),P=N[0][0],R=N[1];if(P&&P.error)throw P.error;var M=(0,s.useRef)(),D=(0,s.useRef)(l),L=(0,s.useRef)(),B=(0,s.useRef)(!1),F=c((function(){return L.current&&l===D.current?L.current:g(m.getState(),l)}),[m,P,l]);A(k,[D,M,B,l,F,L,j]),A(C,[f,m,w,g,D,M,B,L,j,R],[m,w,g]);var z=(0,s.useMemo)((function(){return s.createElement(t,(0,v.Z)({},F,{ref:i}))}),[i,t,F]);return(0,s.useMemo)((function(){return f?s.createElement(u.Provider,{value:I},z):z}),[u,z,I])}var h=l?s.memo(p):p;if(h.WrappedComponent=t,h.displayName=p.displayName=n,b){var g=s.forwardRef((function(e,t){return s.createElement(h,(0,v.Z)({},e,{reactReduxForwardedRef:t}))}));return g.displayName=n,g.WrappedComponent=t,w()(g,t)}return w()(h,t)}}function I(e,t){return e===t?0!==e||0!==t||1/e==1/t:e!=e&&t!=t}function N(e,t){if(I(e,t))return!0;if("object"!=typeof e||null===e||"object"!=typeof t||null===t)return!1;var r=Object.keys(e),n=Object.keys(t);if(r.length!==n.length)return!1;for(var o=0;o=0;n--){var o=t[n](e);if(o)return o}return function(t,n){throw new Error("Invalid value of type "+typeof e+" for "+r+" argument when connecting component "+n.wrappedComponentName+".")}}function V(e,t){return e===t}function $(e){var t=void 0===e?{}:e,r=t.connectHOC,n=void 0===r?j:r,o=t.mapStateToPropsFactories,a=void 0===o?D:o,i=t.mapDispatchToPropsFactories,s=void 0===i?M:i,l=t.mergePropsFactories,u=void 0===l?B:l,c=t.selectorFactory,p=void 0===c?U:c;return function(e,t,r,o){void 0===o&&(o={});var i=o,l=i.pure,c=void 0===l||l,f=i.areStatesEqual,h=void 0===f?V:f,d=i.areOwnPropsEqual,m=void 0===d?N:d,g=i.areStatePropsEqual,b=void 0===g?N:g,w=i.areMergedPropsEqual,E=void 0===w?N:w,x=(0,y.Z)(i,["pure","areStatesEqual","areOwnPropsEqual","areStatePropsEqual","areMergedPropsEqual"]),_=q(e,a,"mapStateToProps"),S=q(t,s,"mapDispatchToProps"),A=q(r,u,"mergeProps");return n(p,(0,v.Z)({methodName:"connect",getDisplayName:function(e){return"Connect("+e+")"},shouldHandleStateChanges:Boolean(e),initMapStateToProps:_,initMapDispatchToProps:S,initMergeProps:A,pure:c,areStatesEqual:h,areOwnPropsEqual:m,areStatePropsEqual:b,areMergedPropsEqual:E},x))}}const W=$();var H;H=l.unstable_batchedUpdates,p=H;var J=r(57557),K=r.n(J),G=r(6557),Z=r.n(G);const Y=e=>t=>{const{fn:r}=e();class n extends s.Component{render(){return s.createElement(t,o()({},e(),this.props,this.context))}}return n.displayName=`WithSystem(${r.getDisplayName(t)})`,n},Q=(e,t)=>r=>{const{fn:n}=e();class a extends s.Component{render(){return s.createElement(g,{store:t},s.createElement(r,o()({},this.props,this.context)))}}return a.displayName=`WithRoot(${n.getDisplayName(r)})`,a},X=(e,t,r)=>(0,u.qC)(r?Q(e,r):Z(),W(((r,n)=>{var o;const a={...n,...e()},i=(null===(o=t.prototype)||void 0===o?void 0:o.mapStateToProps)||(e=>({state:e}));return i(r,a)})),Y(e))(t),ee=(e,t,r,n)=>{for(const o in t){const a=t[o];"function"==typeof a&&a(r[o],n[o],e())}},te=(e,t,r)=>(t,n)=>{const{fn:o}=e(),a=r(t,"root");class l extends s.Component{constructor(t,r){super(t,r),ee(e,n,t,{})}UNSAFE_componentWillReceiveProps(t){ee(e,n,t,this.props)}render(){const e=K()(this.props,n?i()(n):[]);return s.createElement(a,e)}}return l.displayName=`WithMappedContainer(${o.getDisplayName(a)})`,l},re=(e,t,r,n)=>o=>{const a=r(e,t,n)("App","root");l.render(s.createElement(a,null),o)},ne=(e,t,r)=>function(n,o){let a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if("string"!=typeof n)throw new TypeError("Need a string, to fetch a component. Was given a "+typeof n);const i=r(n);return i?o?"root"===o?X(e,i,t()):X(e,i):i:(a.failSilently||e().log.warn("Could not find component:",n),null)}},33424:(e,t,r)=>{"use strict";r.d(t,{d3:()=>D,C2:()=>ee});var n=r(28222),o=r.n(n),a=r(58118),i=r.n(a),s=r(63366);function l(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r=4?[t[0],t[1],t[2],t[3],"".concat(t[0],".").concat(t[1]),"".concat(t[0],".").concat(t[2]),"".concat(t[0],".").concat(t[3]),"".concat(t[1],".").concat(t[0]),"".concat(t[1],".").concat(t[2]),"".concat(t[1],".").concat(t[3]),"".concat(t[2],".").concat(t[0]),"".concat(t[2],".").concat(t[1]),"".concat(t[2],".").concat(t[3]),"".concat(t[3],".").concat(t[0]),"".concat(t[3],".").concat(t[1]),"".concat(t[3],".").concat(t[2]),"".concat(t[0],".").concat(t[1],".").concat(t[2]),"".concat(t[0],".").concat(t[1],".").concat(t[3]),"".concat(t[0],".").concat(t[2],".").concat(t[1]),"".concat(t[0],".").concat(t[2],".").concat(t[3]),"".concat(t[0],".").concat(t[3],".").concat(t[1]),"".concat(t[0],".").concat(t[3],".").concat(t[2]),"".concat(t[1],".").concat(t[0],".").concat(t[2]),"".concat(t[1],".").concat(t[0],".").concat(t[3]),"".concat(t[1],".").concat(t[2],".").concat(t[0]),"".concat(t[1],".").concat(t[2],".").concat(t[3]),"".concat(t[1],".").concat(t[3],".").concat(t[0]),"".concat(t[1],".").concat(t[3],".").concat(t[2]),"".concat(t[2],".").concat(t[0],".").concat(t[1]),"".concat(t[2],".").concat(t[0],".").concat(t[3]),"".concat(t[2],".").concat(t[1],".").concat(t[0]),"".concat(t[2],".").concat(t[1],".").concat(t[3]),"".concat(t[2],".").concat(t[3],".").concat(t[0]),"".concat(t[2],".").concat(t[3],".").concat(t[1]),"".concat(t[3],".").concat(t[0],".").concat(t[1]),"".concat(t[3],".").concat(t[0],".").concat(t[2]),"".concat(t[3],".").concat(t[1],".").concat(t[0]),"".concat(t[3],".").concat(t[1],".").concat(t[2]),"".concat(t[3],".").concat(t[2],".").concat(t[0]),"".concat(t[3],".").concat(t[2],".").concat(t[1]),"".concat(t[0],".").concat(t[1],".").concat(t[2],".").concat(t[3]),"".concat(t[0],".").concat(t[1],".").concat(t[3],".").concat(t[2]),"".concat(t[0],".").concat(t[2],".").concat(t[1],".").concat(t[3]),"".concat(t[0],".").concat(t[2],".").concat(t[3],".").concat(t[1]),"".concat(t[0],".").concat(t[3],".").concat(t[1],".").concat(t[2]),"".concat(t[0],".").concat(t[3],".").concat(t[2],".").concat(t[1]),"".concat(t[1],".").concat(t[0],".").concat(t[2],".").concat(t[3]),"".concat(t[1],".").concat(t[0],".").concat(t[3],".").concat(t[2]),"".concat(t[1],".").concat(t[2],".").concat(t[0],".").concat(t[3]),"".concat(t[1],".").concat(t[2],".").concat(t[3],".").concat(t[0]),"".concat(t[1],".").concat(t[3],".").concat(t[0],".").concat(t[2]),"".concat(t[1],".").concat(t[3],".").concat(t[2],".").concat(t[0]),"".concat(t[2],".").concat(t[0],".").concat(t[1],".").concat(t[3]),"".concat(t[2],".").concat(t[0],".").concat(t[3],".").concat(t[1]),"".concat(t[2],".").concat(t[1],".").concat(t[0],".").concat(t[3]),"".concat(t[2],".").concat(t[1],".").concat(t[3],".").concat(t[0]),"".concat(t[2],".").concat(t[3],".").concat(t[0],".").concat(t[1]),"".concat(t[2],".").concat(t[3],".").concat(t[1],".").concat(t[0]),"".concat(t[3],".").concat(t[0],".").concat(t[1],".").concat(t[2]),"".concat(t[3],".").concat(t[0],".").concat(t[2],".").concat(t[1]),"".concat(t[3],".").concat(t[1],".").concat(t[0],".").concat(t[2]),"".concat(t[3],".").concat(t[1],".").concat(t[2],".").concat(t[0]),"".concat(t[3],".").concat(t[2],".").concat(t[0],".").concat(t[1]),"".concat(t[3],".").concat(t[2],".").concat(t[1],".").concat(t[0])]:void 0),m[n]}function v(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=arguments.length>2?arguments[2]:void 0,n=e.filter((function(e){return"token"!==e})),o=g(n);return o.reduce((function(e,t){return d(d({},e),r[t])}),t)}function y(e){return e.join(" ")}function b(e){var t=e.node,r=e.stylesheet,n=e.style,o=void 0===n?{}:n,a=e.useInlineStyles,i=e.key,s=t.properties,l=t.type,u=t.tagName,c=t.value;if("text"===l)return c;if(u){var h,m=function(e,t){var r=0;return function(n){return r+=1,n.map((function(n,o){return b({node:n,stylesheet:e,useInlineStyles:t,key:"code-segment-".concat(r,"-").concat(o)})}))}}(r,a);if(a){var g=Object.keys(r).reduce((function(e,t){return t.split(".").forEach((function(t){e.includes(t)||e.push(t)})),e}),[]),w=s.className&&s.className.includes("token")?["token"]:[],E=s.className&&w.concat(s.className.filter((function(e){return!g.includes(e)})));h=d(d({},s),{},{className:y(E)||void 0,style:v(s.className,Object.assign({},s.style,o),r)})}else h=d(d({},s),{},{className:y(s.className)});var x=m(t.children);return p.createElement(u,(0,f.Z)({key:i},h),x)}}var w=["language","children","style","customStyle","codeTagProps","useInlineStyles","showLineNumbers","showInlineLineNumbers","startingLineNumber","lineNumberContainerStyle","lineNumberStyle","wrapLines","wrapLongLines","lineProps","renderer","PreTag","CodeTag","code","astGenerator"];function E(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function x(e){for(var t=1;t1&&void 0!==arguments[1]?arguments[1]:[],r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],n=0;n2&&void 0!==arguments[2]?arguments[2]:[];return C({children:e,lineNumber:t,lineNumberStyle:s,largestLineNumber:i,showInlineLineNumbers:o,lineProps:r,className:a,showLineNumbers:n,wrapLongLines:l})}function m(e,t){if(n&&t&&o){var r=k(s,t,i);e.unshift(A(t,r))}return e}function g(e,r){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[];return t||n.length>0?d(e,r,n):m(e,r)}for(var v=function(){var e=c[h],t=e.children[0].value;if(t.match(_)){var r=t.split("\n");r.forEach((function(t,o){var i=n&&p.length+a,s={type:"text",value:"".concat(t,"\n")};if(0===o){var l=g(c.slice(f+1,h).concat(C({children:[s],className:e.properties.className})),i);p.push(l)}else if(o===r.length-1){var u=c[h+1]&&c[h+1].children&&c[h+1].children[0],d={type:"text",value:"".concat(t)};if(u){var m=C({children:[d],className:e.properties.className});c.splice(h+1,0,m)}else{var v=g([d],i,e.properties.className);p.push(v)}}else{var y=g([s],i,e.properties.className);p.push(y)}})),f=h}h++};h=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}(e,w);q=q||T;var $=d?p.createElement(S,{containerStyle:b,codeStyle:u.style||{},numberStyle:_,startingLineNumber:y,codeString:U}):null,W=o.hljs||o['pre[class*="language-"]']||{backgroundColor:"#fff"},H=N(q)?"hljs":"prismjs",J=f?Object.assign({},V,{style:Object.assign({},W,i)}):Object.assign({},V,{className:V.className?"".concat(H," ").concat(V.className):H,style:Object.assign({},i)});if(u.style=x(x({},u.style),{},C?{whiteSpace:"pre-wrap"}:{whiteSpace:"pre"}),!q)return p.createElement(L,J,$,p.createElement(F,u,U));(void 0===A&&M||C)&&(A=!0),M=M||I;var K=[{type:"text",value:U}],G=function(e){var t=e.astGenerator,r=e.language,n=e.code,o=e.defaultCodeValue;if(N(t)){var a=function(e,t){return-1!==e.listLanguages().indexOf(t)}(t,r);return"text"===r?{value:o,language:"text"}:a?t.highlight(r,n):t.highlightAuto(n)}try{return r&&"text"!==r?{value:t.highlight(n,r)}:{value:o}}catch(e){return{value:o}}}({astGenerator:q,language:t,code:U,defaultCodeValue:K});null===G.language&&(G.value=K);var Z=j(G,A,R,d,g,y,G.value.length+y,_,C);return p.createElement(L,J,p.createElement(F,u,!g&&$,M({rows:Z,stylesheet:o,useInlineStyles:f})))});M.registerLanguage=R.registerLanguage;const D=M;var L=r(96344);const B=r.n(L)();var F=r(82026);const z=r.n(F)();var U=r(42157);const q=r.n(U)();var V=r(61519);const $=r.n(V)();var W=r(54587);const H=r.n(W)();var J=r(30786);const K=r.n(J)();var G=r(66336);const Z=r.n(G)(),Y={hljs:{display:"block",overflowX:"auto",padding:"0.5em",background:"#333",color:"white"},"hljs-name":{fontWeight:"bold"},"hljs-strong":{fontWeight:"bold"},"hljs-code":{fontStyle:"italic",color:"#888"},"hljs-emphasis":{fontStyle:"italic"},"hljs-tag":{color:"#62c8f3"},"hljs-variable":{color:"#ade5fc"},"hljs-template-variable":{color:"#ade5fc"},"hljs-selector-id":{color:"#ade5fc"},"hljs-selector-class":{color:"#ade5fc"},"hljs-string":{color:"#a2fca2"},"hljs-bullet":{color:"#d36363"},"hljs-type":{color:"#ffa"},"hljs-title":{color:"#ffa"},"hljs-section":{color:"#ffa"},"hljs-attribute":{color:"#ffa"},"hljs-quote":{color:"#ffa"},"hljs-built_in":{color:"#ffa"},"hljs-builtin-name":{color:"#ffa"},"hljs-number":{color:"#d36363"},"hljs-symbol":{color:"#d36363"},"hljs-keyword":{color:"#fcc28c"},"hljs-selector-tag":{color:"#fcc28c"},"hljs-literal":{color:"#fcc28c"},"hljs-comment":{color:"#888"},"hljs-deletion":{color:"#333",backgroundColor:"#fc9b9b"},"hljs-regexp":{color:"#c6b4f0"},"hljs-link":{color:"#c6b4f0"},"hljs-meta":{color:"#fc9b9b"},"hljs-addition":{backgroundColor:"#a2fca2",color:"#333"}};D.registerLanguage("json",z),D.registerLanguage("js",B),D.registerLanguage("xml",q),D.registerLanguage("yaml",H),D.registerLanguage("http",K),D.registerLanguage("bash",$),D.registerLanguage("powershell",Z),D.registerLanguage("javascript",B);const Q={agate:Y,arta:{hljs:{display:"block",overflowX:"auto",padding:"0.5em",background:"#222",color:"#aaa"},"hljs-subst":{color:"#aaa"},"hljs-section":{color:"#fff",fontWeight:"bold"},"hljs-comment":{color:"#444"},"hljs-quote":{color:"#444"},"hljs-meta":{color:"#444"},"hljs-string":{color:"#ffcc33"},"hljs-symbol":{color:"#ffcc33"},"hljs-bullet":{color:"#ffcc33"},"hljs-regexp":{color:"#ffcc33"},"hljs-number":{color:"#00cc66"},"hljs-addition":{color:"#00cc66"},"hljs-built_in":{color:"#32aaee"},"hljs-builtin-name":{color:"#32aaee"},"hljs-literal":{color:"#32aaee"},"hljs-type":{color:"#32aaee"},"hljs-template-variable":{color:"#32aaee"},"hljs-attribute":{color:"#32aaee"},"hljs-link":{color:"#32aaee"},"hljs-keyword":{color:"#6644aa"},"hljs-selector-tag":{color:"#6644aa"},"hljs-name":{color:"#6644aa"},"hljs-selector-id":{color:"#6644aa"},"hljs-selector-class":{color:"#6644aa"},"hljs-title":{color:"#bb1166"},"hljs-variable":{color:"#bb1166"},"hljs-deletion":{color:"#bb1166"},"hljs-template-tag":{color:"#bb1166"},"hljs-doctag":{fontWeight:"bold"},"hljs-strong":{fontWeight:"bold"},"hljs-emphasis":{fontStyle:"italic"}},monokai:{hljs:{display:"block",overflowX:"auto",padding:"0.5em",background:"#272822",color:"#ddd"},"hljs-tag":{color:"#f92672"},"hljs-keyword":{color:"#f92672",fontWeight:"bold"},"hljs-selector-tag":{color:"#f92672",fontWeight:"bold"},"hljs-literal":{color:"#f92672",fontWeight:"bold"},"hljs-strong":{color:"#f92672"},"hljs-name":{color:"#f92672"},"hljs-code":{color:"#66d9ef"},"hljs-class .hljs-title":{color:"white"},"hljs-attribute":{color:"#bf79db"},"hljs-symbol":{color:"#bf79db"},"hljs-regexp":{color:"#bf79db"},"hljs-link":{color:"#bf79db"},"hljs-string":{color:"#a6e22e"},"hljs-bullet":{color:"#a6e22e"},"hljs-subst":{color:"#a6e22e"},"hljs-title":{color:"#a6e22e",fontWeight:"bold"},"hljs-section":{color:"#a6e22e",fontWeight:"bold"},"hljs-emphasis":{color:"#a6e22e"},"hljs-type":{color:"#a6e22e",fontWeight:"bold"},"hljs-built_in":{color:"#a6e22e"},"hljs-builtin-name":{color:"#a6e22e"},"hljs-selector-attr":{color:"#a6e22e"},"hljs-selector-pseudo":{color:"#a6e22e"},"hljs-addition":{color:"#a6e22e"},"hljs-variable":{color:"#a6e22e"},"hljs-template-tag":{color:"#a6e22e"},"hljs-template-variable":{color:"#a6e22e"},"hljs-comment":{color:"#75715e"},"hljs-quote":{color:"#75715e"},"hljs-deletion":{color:"#75715e"},"hljs-meta":{color:"#75715e"},"hljs-doctag":{fontWeight:"bold"},"hljs-selector-id":{fontWeight:"bold"}},nord:{hljs:{display:"block",overflowX:"auto",padding:"0.5em",background:"#2E3440",color:"#D8DEE9"},"hljs-subst":{color:"#D8DEE9"},"hljs-selector-tag":{color:"#81A1C1"},"hljs-selector-id":{color:"#8FBCBB",fontWeight:"bold"},"hljs-selector-class":{color:"#8FBCBB"},"hljs-selector-attr":{color:"#8FBCBB"},"hljs-selector-pseudo":{color:"#88C0D0"},"hljs-addition":{backgroundColor:"rgba(163, 190, 140, 0.5)"},"hljs-deletion":{backgroundColor:"rgba(191, 97, 106, 0.5)"},"hljs-built_in":{color:"#8FBCBB"},"hljs-type":{color:"#8FBCBB"},"hljs-class":{color:"#8FBCBB"},"hljs-function":{color:"#88C0D0"},"hljs-function > .hljs-title":{color:"#88C0D0"},"hljs-keyword":{color:"#81A1C1"},"hljs-literal":{color:"#81A1C1"},"hljs-symbol":{color:"#81A1C1"},"hljs-number":{color:"#B48EAD"},"hljs-regexp":{color:"#EBCB8B"},"hljs-string":{color:"#A3BE8C"},"hljs-title":{color:"#8FBCBB"},"hljs-params":{color:"#D8DEE9"},"hljs-bullet":{color:"#81A1C1"},"hljs-code":{color:"#8FBCBB"},"hljs-emphasis":{fontStyle:"italic"},"hljs-formula":{color:"#8FBCBB"},"hljs-strong":{fontWeight:"bold"},"hljs-link:hover":{textDecoration:"underline"},"hljs-quote":{color:"#4C566A"},"hljs-comment":{color:"#4C566A"},"hljs-doctag":{color:"#8FBCBB"},"hljs-meta":{color:"#5E81AC"},"hljs-meta-keyword":{color:"#5E81AC"},"hljs-meta-string":{color:"#A3BE8C"},"hljs-attr":{color:"#8FBCBB"},"hljs-attribute":{color:"#D8DEE9"},"hljs-builtin-name":{color:"#81A1C1"},"hljs-name":{color:"#81A1C1"},"hljs-section":{color:"#88C0D0"},"hljs-tag":{color:"#81A1C1"},"hljs-variable":{color:"#D8DEE9"},"hljs-template-variable":{color:"#D8DEE9"},"hljs-template-tag":{color:"#5E81AC"},"abnf .hljs-attribute":{color:"#88C0D0"},"abnf .hljs-symbol":{color:"#EBCB8B"},"apache .hljs-attribute":{color:"#88C0D0"},"apache .hljs-section":{color:"#81A1C1"},"arduino .hljs-built_in":{color:"#88C0D0"},"aspectj .hljs-meta":{color:"#D08770"},"aspectj > .hljs-title":{color:"#88C0D0"},"bnf .hljs-attribute":{color:"#8FBCBB"},"clojure .hljs-name":{color:"#88C0D0"},"clojure .hljs-symbol":{color:"#EBCB8B"},"coq .hljs-built_in":{color:"#88C0D0"},"cpp .hljs-meta-string":{color:"#8FBCBB"},"css .hljs-built_in":{color:"#88C0D0"},"css .hljs-keyword":{color:"#D08770"},"diff .hljs-meta":{color:"#8FBCBB"},"ebnf .hljs-attribute":{color:"#8FBCBB"},"glsl .hljs-built_in":{color:"#88C0D0"},"groovy .hljs-meta:not(:first-child)":{color:"#D08770"},"haxe .hljs-meta":{color:"#D08770"},"java .hljs-meta":{color:"#D08770"},"ldif .hljs-attribute":{color:"#8FBCBB"},"lisp .hljs-name":{color:"#88C0D0"},"lua .hljs-built_in":{color:"#88C0D0"},"moonscript .hljs-built_in":{color:"#88C0D0"},"nginx .hljs-attribute":{color:"#88C0D0"},"nginx .hljs-section":{color:"#5E81AC"},"pf .hljs-built_in":{color:"#88C0D0"},"processing .hljs-built_in":{color:"#88C0D0"},"scss .hljs-keyword":{color:"#81A1C1"},"stylus .hljs-keyword":{color:"#81A1C1"},"swift .hljs-meta":{color:"#D08770"},"vim .hljs-built_in":{color:"#88C0D0",fontStyle:"italic"},"yaml .hljs-meta":{color:"#D08770"}},obsidian:{hljs:{display:"block",overflowX:"auto",padding:"0.5em",background:"#282b2e",color:"#e0e2e4"},"hljs-keyword":{color:"#93c763",fontWeight:"bold"},"hljs-selector-tag":{color:"#93c763",fontWeight:"bold"},"hljs-literal":{color:"#93c763",fontWeight:"bold"},"hljs-selector-id":{color:"#93c763"},"hljs-number":{color:"#ffcd22"},"hljs-attribute":{color:"#668bb0"},"hljs-code":{color:"white"},"hljs-class .hljs-title":{color:"white"},"hljs-section":{color:"white",fontWeight:"bold"},"hljs-regexp":{color:"#d39745"},"hljs-link":{color:"#d39745"},"hljs-meta":{color:"#557182"},"hljs-tag":{color:"#8cbbad"},"hljs-name":{color:"#8cbbad",fontWeight:"bold"},"hljs-bullet":{color:"#8cbbad"},"hljs-subst":{color:"#8cbbad"},"hljs-emphasis":{color:"#8cbbad"},"hljs-type":{color:"#8cbbad",fontWeight:"bold"},"hljs-built_in":{color:"#8cbbad"},"hljs-selector-attr":{color:"#8cbbad"},"hljs-selector-pseudo":{color:"#8cbbad"},"hljs-addition":{color:"#8cbbad"},"hljs-variable":{color:"#8cbbad"},"hljs-template-tag":{color:"#8cbbad"},"hljs-template-variable":{color:"#8cbbad"},"hljs-string":{color:"#ec7600"},"hljs-symbol":{color:"#ec7600"},"hljs-comment":{color:"#818e96"},"hljs-quote":{color:"#818e96"},"hljs-deletion":{color:"#818e96"},"hljs-selector-class":{color:"#A082BD"},"hljs-doctag":{fontWeight:"bold"},"hljs-title":{fontWeight:"bold"},"hljs-strong":{fontWeight:"bold"}},"tomorrow-night":{"hljs-comment":{color:"#969896"},"hljs-quote":{color:"#969896"},"hljs-variable":{color:"#cc6666"},"hljs-template-variable":{color:"#cc6666"},"hljs-tag":{color:"#cc6666"},"hljs-name":{color:"#cc6666"},"hljs-selector-id":{color:"#cc6666"},"hljs-selector-class":{color:"#cc6666"},"hljs-regexp":{color:"#cc6666"},"hljs-deletion":{color:"#cc6666"},"hljs-number":{color:"#de935f"},"hljs-built_in":{color:"#de935f"},"hljs-builtin-name":{color:"#de935f"},"hljs-literal":{color:"#de935f"},"hljs-type":{color:"#de935f"},"hljs-params":{color:"#de935f"},"hljs-meta":{color:"#de935f"},"hljs-link":{color:"#de935f"},"hljs-attribute":{color:"#f0c674"},"hljs-string":{color:"#b5bd68"},"hljs-symbol":{color:"#b5bd68"},"hljs-bullet":{color:"#b5bd68"},"hljs-addition":{color:"#b5bd68"},"hljs-title":{color:"#81a2be"},"hljs-section":{color:"#81a2be"},"hljs-keyword":{color:"#b294bb"},"hljs-selector-tag":{color:"#b294bb"},hljs:{display:"block",overflowX:"auto",background:"#1d1f21",color:"#c5c8c6",padding:"0.5em"},"hljs-emphasis":{fontStyle:"italic"},"hljs-strong":{fontWeight:"bold"}}},X=o()(Q),ee=e=>i()(X).call(X,e)?Q[e]:(console.warn(`Request style '${e}' is not available, returning default instead`),Y)},90242:(e,t,r)=>{"use strict";r.d(t,{mz:()=>pe,oG:()=>fe,AF:()=>he,LQ:()=>de,Kn:()=>me,Wl:()=>ge,kJ:()=>ve,HP:()=>ye,Ay:()=>be,Q2:()=>we,_5:()=>Ee,iQ:()=>xe,gp:()=>_e,DR:()=>Se,Zl:()=>Ae,Ik:()=>Ce,xi:()=>Pe,UG:()=>Re,r3:()=>Me,wh:()=>De,GZ:()=>Le,be:()=>Be,Nm:()=>Fe,hW:()=>ze,QG:()=>Ue,oJ:()=>qe,J6:()=>Ve,nX:()=>$e,po:()=>We,XV:()=>He,Pz:()=>Je,D$:()=>Ke,V9:()=>Ge,cz:()=>Ze,Uj:()=>Ye,Xb:()=>Qe,O2:()=>et});var n=r(58309),o=r.n(n),a=r(97606),i=r.n(a),s=r(74386),l=r.n(s),u=r(86),c=r.n(u),p=r(14418),f=r.n(p),h=r(28222),d=r.n(h),m=(r(11189),r(24282)),g=r.n(m),v=r(76986),y=r.n(v),b=r(2578),w=r.n(b),E=r(24278),x=r.n(E),_=(r(39022),r(92039)),S=r.n(_),A=(r(58118),r(35627)),k=r.n(A),C=r(11882),O=r.n(C),j=r(51679),I=r.n(j),N=r(27043),T=r.n(N),P=r(81607),R=r.n(P),M=r(43393),D=r.n(M),L=r(17967),B=r(68929),F=r.n(B),z=r(11700),U=r.n(z),q=r(88306),V=r.n(q),$=r(13311),W=r.n($),H=r(59704),J=r.n(H),K=r(77813),G=r.n(K),Z=r(23560),Y=r.n(Z),Q=r(57050),X=r(27504),ee=r(8269),te=r.n(ee),re=r(19069),ne=r(92282),oe=r.n(ne),ae=r(89072),ie=r.n(ae),se=r(1272),le=r(48764).Buffer;const ue="default",ce=e=>D().Iterable.isIterable(e);function pe(e){return me(e)?ce(e)?e.toJS():e:{}}function fe(e){var t,r;if(ce(e))return e;if(e instanceof X.Z.File)return e;if(!me(e))return e;if(o()(e))return i()(r=D().Seq(e)).call(r,fe).toList();if(Y()(l()(e))){var n;const t=function(e){if(!Y()(l()(e)))return e;const t={},r="_**[]",n={};for(let o of l()(e).call(e))if(t[o[0]]||n[o[0]]&&n[o[0]].containsMultiple){if(!n[o[0]]){n[o[0]]={containsMultiple:!0,length:1},t[`${o[0]}${r}${n[o[0]].length}`]=t[o[0]],delete t[o[0]]}n[o[0]].length+=1,t[`${o[0]}${r}${n[o[0]].length}`]=o[1]}else t[o[0]]=o[1];return t}(e);return i()(n=D().OrderedMap(t)).call(n,fe)}return i()(t=D().OrderedMap(e)).call(t,fe)}function he(e){return o()(e)?e:[e]}function de(e){return"function"==typeof e}function me(e){return!!e&&"object"==typeof e}function ge(e){return"function"==typeof e}function ve(e){return o()(e)}const ye=V();function be(e,t){var r;return g()(r=d()(e)).call(r,((r,n)=>(r[n]=t(e[n],n),r)),{})}function we(e,t){var r;return g()(r=d()(e)).call(r,((r,n)=>{let o=t(e[n],n);return o&&"object"==typeof o&&y()(r,o),r}),{})}function Ee(e){return t=>{let{dispatch:r,getState:n}=t;return t=>r=>"function"==typeof r?r(e()):t(r)}}function xe(e){var t;let r=e.keySeq();return r.contains(ue)?ue:w()(t=f()(r).call(r,(e=>"2"===(e+"")[0]))).call(t).first()}function _e(e,t){if(!D().Iterable.isIterable(e))return D().List();let r=e.getIn(o()(t)?t:[t]);return D().List.isList(r)?r:D().List()}function Se(e){let t,r=[/filename\*=[^']+'\w*'"([^"]+)";?/i,/filename\*=[^']+'\w*'([^;]+);?/i,/filename="([^;]*);?"/i,/filename=([^;]*);?/i];if(S()(r).call(r,(r=>(t=r.exec(e),null!==t))),null!==t&&t.length>1)try{return decodeURIComponent(t[1])}catch(e){console.error(e)}return null}function Ae(e){return t=e.replace(/\.[^./]*$/,""),U()(F()(t));var t}function ke(e,t,r,n,a){if(!t)return[];let s=[],l=t.get("nullable"),u=t.get("required"),p=t.get("maximum"),h=t.get("minimum"),d=t.get("type"),m=t.get("format"),g=t.get("maxLength"),v=t.get("minLength"),y=t.get("uniqueItems"),b=t.get("maxItems"),w=t.get("minItems"),E=t.get("pattern");const x=r||!0===u,_=null!=e;if(l&&null===e||!d||!(x||_&&"array"===d||!(!x&&!_)))return[];let A="string"===d&&e,k="array"===d&&o()(e)&&e.length,C="array"===d&&D().List.isList(e)&&e.count();const O=[A,k,C,"array"===d&&"string"==typeof e&&e,"file"===d&&e instanceof X.Z.File,"boolean"===d&&(e||!1===e),"number"===d&&(e||0===e),"integer"===d&&(e||0===e),"object"===d&&"object"==typeof e&&null!==e,"object"===d&&"string"==typeof e&&e],j=S()(O).call(O,(e=>!!e));if(x&&!j&&!n)return s.push("Required field is not provided"),s;if("object"===d&&(null===a||"application/json"===a)){let r=e;if("string"==typeof e)try{r=JSON.parse(e)}catch(e){return s.push("Parameter string value must be valid JSON"),s}var I;if(t&&t.has("required")&&ge(u.isList)&&u.isList()&&c()(u).call(u,(e=>{void 0===r[e]&&s.push({propKey:e,error:"Required property not found"})})),t&&t.has("properties"))c()(I=t.get("properties")).call(I,((e,t)=>{const o=ke(r[t],e,!1,n,a);s.push(...i()(o).call(o,(e=>({propKey:t,error:e}))))}))}if(E){let t=((e,t)=>{if(!new RegExp(t).test(e))return"Value must follow pattern "+t})(e,E);t&&s.push(t)}if(w&&"array"===d){let t=((e,t)=>{if(!e&&t>=1||e&&e.length{if(e&&e.length>t)return`Array must not contain more then ${t} item${1===t?"":"s"}`})(e,b);t&&s.push({needRemove:!0,error:t})}if(y&&"array"===d){let t=((e,t)=>{if(e&&("true"===t||!0===t)){const t=(0,M.fromJS)(e),r=t.toSet();if(e.length>r.size){let e=(0,M.Set)();if(c()(t).call(t,((r,n)=>{f()(t).call(t,(e=>ge(e.equals)?e.equals(r):e===r)).size>1&&(e=e.add(n))})),0!==e.size)return i()(e).call(e,(e=>({index:e,error:"No duplicates allowed."}))).toArray()}}})(e,y);t&&s.push(...t)}if(g||0===g){let t=((e,t)=>{if(e.length>t)return`Value must be no longer than ${t} character${1!==t?"s":""}`})(e,g);t&&s.push(t)}if(v){let t=((e,t)=>{if(e.length{if(e>t)return`Value must be less than ${t}`})(e,p);t&&s.push(t)}if(h||0===h){let t=((e,t)=>{if(e{if(isNaN(Date.parse(e)))return"Value must be a DateTime"})(e):"uuid"===m?(e=>{if(e=e.toString().toLowerCase(),!/^[{(]?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}[)}]?$/.test(e))return"Value must be a Guid"})(e):(e=>{if(e&&"string"!=typeof e)return"Value must be a string"})(e),!t)return s;s.push(t)}else if("boolean"===d){let t=(e=>{if("true"!==e&&"false"!==e&&!0!==e&&!1!==e)return"Value must be a boolean"})(e);if(!t)return s;s.push(t)}else if("number"===d){let t=(e=>{if(!/^-?\d+(\.?\d+)?$/.test(e))return"Value must be a number"})(e);if(!t)return s;s.push(t)}else if("integer"===d){let t=(e=>{if(!/^-?\d+$/.test(e))return"Value must be an integer"})(e);if(!t)return s;s.push(t)}else if("array"===d){if(!k&&!C)return s;e&&c()(e).call(e,((e,r)=>{const o=ke(e,t.get("items"),!1,n,a);s.push(...i()(o).call(o,(e=>({index:r,error:e}))))}))}else if("file"===d){let t=(e=>{if(e&&!(e instanceof X.Z.File))return"Value must be a file"})(e);if(!t)return s;s.push(t)}return s}const Ce=function(e,t){let{isOAS3:r=!1,bypassRequiredCheck:n=!1}=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},o=e.get("required"),{schema:a,parameterContentMediaType:i}=(0,re.Z)(e,{isOAS3:r});return ke(t,a,o,n,i)},Oe=(e,t,r)=>{if(e&&!e.xml&&(e.xml={}),e&&!e.xml.name){if(!e.$$ref&&(e.type||e.items||e.properties||e.additionalProperties))return'\n\x3c!-- XML example cannot be generated; root element name is undefined --\x3e';if(e.$$ref){let t=e.$$ref.match(/\S*\/(\S+)$/);e.xml.name=t[1]}}return(0,Q.memoizedCreateXMLExample)(e,t,r)},je=[{when:/json/,shouldStringifyTypes:["string"]}],Ie=["object"],Ne=(e,t,r,n)=>{const o=(0,Q.memoizedSampleFromSchema)(e,t,n),a=typeof o,i=g()(je).call(je,((e,t)=>t.when.test(r)?[...e,...t.shouldStringifyTypes]:e),Ie);return J()(i,(e=>e===a))?k()(o,null,2):o},Te=(e,t,r,n)=>{const o=Ne(e,t,r,n);let a;try{a=se.ZP.dump(se.ZP.load(o),{lineWidth:-1},{schema:se.A8}),"\n"===a[a.length-1]&&(a=x()(a).call(a,0,a.length-1))}catch(e){return console.error(e),"error: could not generate yaml example"}return a.replace(/\t/g," ")},Pe=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:void 0;return e&&ge(e.toJS)&&(e=e.toJS()),n&&ge(n.toJS)&&(n=n.toJS()),/xml/.test(t)?Oe(e,r,n):/(yaml|yml)/.test(t)?Te(e,r,t,n):Ne(e,r,t,n)},Re=()=>{let e={},t=X.Z.location.search;if(!t)return{};if(""!=t){let r=t.substr(1).split("&");for(let t in r)Object.prototype.hasOwnProperty.call(r,t)&&(t=r[t].split("="),e[decodeURIComponent(t[0])]=t[1]&&decodeURIComponent(t[1])||"")}return e},Me=e=>{let t;return t=e instanceof le?e:le.from(e.toString(),"utf-8"),t.toString("base64")},De={operationsSorter:{alpha:(e,t)=>e.get("path").localeCompare(t.get("path")),method:(e,t)=>e.get("method").localeCompare(t.get("method"))},tagsSorter:{alpha:(e,t)=>e.localeCompare(t)}},Le=e=>{let t=[];for(let r in e){let n=e[r];void 0!==n&&""!==n&&t.push([r,"=",encodeURIComponent(n).replace(/%20/g,"+")].join(""))}return t.join("&")},Be=(e,t,r)=>!!W()(r,(r=>G()(e[r],t[r])));function Fe(e){return"string"!=typeof e||""===e?"":(0,L.N)(e)}function ze(e){return!(!e||O()(e).call(e,"localhost")>=0||O()(e).call(e,"127.0.0.1")>=0||"none"===e)}function Ue(e){if(!D().OrderedMap.isOrderedMap(e))return null;if(!e.size)return null;const t=I()(e).call(e,((e,t)=>T()(t).call(t,"2")&&d()(e.get("content")||{}).length>0)),r=e.get("default")||D().OrderedMap(),n=(r.get("content")||D().OrderedMap()).keySeq().toJS().length?r:null;return t||n}const qe=e=>"string"==typeof e||e instanceof String?R()(e).call(e).replace(/\s/g,"%20"):"",Ve=e=>te()(qe(e).replace(/%20/g,"_")),$e=e=>f()(e).call(e,((e,t)=>/^x-/.test(t))),We=e=>f()(e).call(e,((e,t)=>/^pattern|maxLength|minLength|maximum|minimum/.test(t)));function He(e,t){var r;let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:()=>!0;if("object"!=typeof e||o()(e)||null===e||!t)return e;const a=y()({},e);return c()(r=d()(a)).call(r,(e=>{e===t&&n(a[e],e)?delete a[e]:a[e]=He(a[e],t,n)})),a}function Je(e){if("string"==typeof e)return e;if(e&&e.toJS&&(e=e.toJS()),"object"==typeof e&&null!==e)try{return k()(e,null,2)}catch(t){return String(e)}return null==e?"":e.toString()}function Ke(e){return"number"==typeof e?e.toString():e}function Ge(e){let{returnAll:t=!1,allowHashes:r=!0}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!D().Map.isMap(e))throw new Error("paramToIdentifier: received a non-Im.Map parameter as input");const n=e.get("name"),o=e.get("in");let a=[];return e&&e.hashCode&&o&&n&&r&&a.push(`${o}.${n}.hash-${e.hashCode()}`),o&&n&&a.push(`${o}.${n}`),a.push(n),t?a:a[0]||""}function Ze(e,t){var r;const n=Ge(e,{returnAll:!0});return f()(r=i()(n).call(n,(e=>t[e]))).call(r,(e=>void 0!==e))[0]}function Ye(){return Xe(oe()(32).toString("base64"))}function Qe(e){return Xe(ie()("sha256").update(e).digest("base64"))}function Xe(e){return e.replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}const et=e=>!e||!(!ce(e)||!e.isEmpty())},2518:(e,t,r)=>{"use strict";function n(e){return function(e){try{return!!JSON.parse(e)}catch(e){return null}}(e)?"json":null}r.d(t,{O:()=>n})},27504:(e,t,r)=>{"use strict";r.d(t,{Z:()=>n});const n=function(){var e={location:{},history:{},open:()=>{},close:()=>{},File:function(){}};if("undefined"==typeof window)return e;try{e=window;for(var t of["File","Blob","FormData"])t in window&&(e[t]=window[t])}catch(e){console.error(e)}return e}()},19069:(e,t,r)=>{"use strict";r.d(t,{Z:()=>c});var n=r(14418),o=r.n(n),a=r(58118),i=r.n(a),s=r(43393),l=r.n(s);const u=l().Set.of("type","format","items","default","maximum","exclusiveMaximum","minimum","exclusiveMinimum","maxLength","minLength","pattern","maxItems","minItems","uniqueItems","enum","multipleOf");function c(e){let{isOAS3:t}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!l().Map.isMap(e))return{schema:l().Map(),parameterContentMediaType:null};if(!t)return"body"===e.get("in")?{schema:e.get("schema",l().Map()),parameterContentMediaType:null}:{schema:o()(e).call(e,((e,t)=>i()(u).call(u,t))),parameterContentMediaType:null};if(e.get("content")){const t=e.get("content",l().Map({})).keySeq().first();return{schema:e.getIn(["content",t,"schema"],l().Map()),parameterContentMediaType:t}}return{schema:e.get("schema")?e.get("schema",l().Map()):l().Map(),parameterContentMediaType:null}}},60314:(e,t,r)=>{"use strict";r.d(t,{Z:()=>x});var n=r(58309),o=r.n(n),a=r(2250),i=r.n(a),s=r(25110),l=r.n(s),u=r(8712),c=r.n(u),p=r(51679),f=r.n(p),h=r(12373),d=r.n(h),m=r(18492),g=r.n(m),v=r(88306),y=r.n(v);const b=e=>t=>o()(e)&&o()(t)&&e.length===t.length&&i()(e).call(e,((e,r)=>e===t[r])),w=function(){for(var e=arguments.length,t=new Array(e),r=0;r1&&void 0!==arguments[1]?arguments[1]:w;const{Cache:r}=y();y().Cache=E;const n=y()(e,t);return y().Cache=r,n}},79742:(e,t)=>{"use strict";t.byteLength=function(e){var t=l(e),r=t[0],n=t[1];return 3*(r+n)/4-n},t.toByteArray=function(e){var t,r,a=l(e),i=a[0],s=a[1],u=new o(function(e,t,r){return 3*(t+r)/4-r}(0,i,s)),c=0,p=s>0?i-4:i;for(r=0;r>16&255,u[c++]=t>>8&255,u[c++]=255&t;2===s&&(t=n[e.charCodeAt(r)]<<2|n[e.charCodeAt(r+1)]>>4,u[c++]=255&t);1===s&&(t=n[e.charCodeAt(r)]<<10|n[e.charCodeAt(r+1)]<<4|n[e.charCodeAt(r+2)]>>2,u[c++]=t>>8&255,u[c++]=255&t);return u},t.fromByteArray=function(e){for(var t,n=e.length,o=n%3,a=[],i=16383,s=0,l=n-o;sl?l:s+i));1===o?(t=e[n-1],a.push(r[t>>2]+r[t<<4&63]+"==")):2===o&&(t=(e[n-2]<<8)+e[n-1],a.push(r[t>>10]+r[t>>4&63]+r[t<<2&63]+"="));return a.join("")};for(var r=[],n=[],o="undefined"!=typeof Uint8Array?Uint8Array:Array,a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",i=0,s=a.length;i0)throw new Error("Invalid string. Length must be a multiple of 4");var r=e.indexOf("=");return-1===r&&(r=t),[r,r===t?0:4-r%4]}function u(e,t,n){for(var o,a,i=[],s=t;s>18&63]+r[a>>12&63]+r[a>>6&63]+r[63&a]);return i.join("")}n["-".charCodeAt(0)]=62,n["_".charCodeAt(0)]=63},48764:(e,t,r)=>{"use strict";const n=r(79742),o=r(80645),a="function"==typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("nodejs.util.inspect.custom"):null;t.Buffer=l,t.SlowBuffer=function(e){+e!=e&&(e=0);return l.alloc(+e)},t.INSPECT_MAX_BYTES=50;const i=2147483647;function s(e){if(e>i)throw new RangeError('The value "'+e+'" is invalid for option "size"');const t=new Uint8Array(e);return Object.setPrototypeOf(t,l.prototype),t}function l(e,t,r){if("number"==typeof e){if("string"==typeof t)throw new TypeError('The "string" argument must be of type string. Received type number');return p(e)}return u(e,t,r)}function u(e,t,r){if("string"==typeof e)return function(e,t){"string"==typeof t&&""!==t||(t="utf8");if(!l.isEncoding(t))throw new TypeError("Unknown encoding: "+t);const r=0|m(e,t);let n=s(r);const o=n.write(e,t);o!==r&&(n=n.slice(0,o));return n}(e,t);if(ArrayBuffer.isView(e))return function(e){if(G(e,Uint8Array)){const t=new Uint8Array(e);return h(t.buffer,t.byteOffset,t.byteLength)}return f(e)}(e);if(null==e)throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof e);if(G(e,ArrayBuffer)||e&&G(e.buffer,ArrayBuffer))return h(e,t,r);if("undefined"!=typeof SharedArrayBuffer&&(G(e,SharedArrayBuffer)||e&&G(e.buffer,SharedArrayBuffer)))return h(e,t,r);if("number"==typeof e)throw new TypeError('The "value" argument must not be of type number. Received type number');const n=e.valueOf&&e.valueOf();if(null!=n&&n!==e)return l.from(n,t,r);const o=function(e){if(l.isBuffer(e)){const t=0|d(e.length),r=s(t);return 0===r.length||e.copy(r,0,0,t),r}if(void 0!==e.length)return"number"!=typeof e.length||Z(e.length)?s(0):f(e);if("Buffer"===e.type&&Array.isArray(e.data))return f(e.data)}(e);if(o)return o;if("undefined"!=typeof Symbol&&null!=Symbol.toPrimitive&&"function"==typeof e[Symbol.toPrimitive])return l.from(e[Symbol.toPrimitive]("string"),t,r);throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof e)}function c(e){if("number"!=typeof e)throw new TypeError('"size" argument must be of type number');if(e<0)throw new RangeError('The value "'+e+'" is invalid for option "size"')}function p(e){return c(e),s(e<0?0:0|d(e))}function f(e){const t=e.length<0?0:0|d(e.length),r=s(t);for(let n=0;n=i)throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+i.toString(16)+" bytes");return 0|e}function m(e,t){if(l.isBuffer(e))return e.length;if(ArrayBuffer.isView(e)||G(e,ArrayBuffer))return e.byteLength;if("string"!=typeof e)throw new TypeError('The "string" argument must be one of type string, Buffer, or ArrayBuffer. Received type '+typeof e);const r=e.length,n=arguments.length>2&&!0===arguments[2];if(!n&&0===r)return 0;let o=!1;for(;;)switch(t){case"ascii":case"latin1":case"binary":return r;case"utf8":case"utf-8":return H(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*r;case"hex":return r>>>1;case"base64":return J(e).length;default:if(o)return n?-1:H(e).length;t=(""+t).toLowerCase(),o=!0}}function g(e,t,r){let n=!1;if((void 0===t||t<0)&&(t=0),t>this.length)return"";if((void 0===r||r>this.length)&&(r=this.length),r<=0)return"";if((r>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return I(this,t,r);case"utf8":case"utf-8":return k(this,t,r);case"ascii":return O(this,t,r);case"latin1":case"binary":return j(this,t,r);case"base64":return A(this,t,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return N(this,t,r);default:if(n)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),n=!0}}function v(e,t,r){const n=e[t];e[t]=e[r],e[r]=n}function y(e,t,r,n,o){if(0===e.length)return-1;if("string"==typeof r?(n=r,r=0):r>2147483647?r=2147483647:r<-2147483648&&(r=-2147483648),Z(r=+r)&&(r=o?0:e.length-1),r<0&&(r=e.length+r),r>=e.length){if(o)return-1;r=e.length-1}else if(r<0){if(!o)return-1;r=0}if("string"==typeof t&&(t=l.from(t,n)),l.isBuffer(t))return 0===t.length?-1:b(e,t,r,n,o);if("number"==typeof t)return t&=255,"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(e,t,r):Uint8Array.prototype.lastIndexOf.call(e,t,r):b(e,[t],r,n,o);throw new TypeError("val must be string, number or Buffer")}function b(e,t,r,n,o){let a,i=1,s=e.length,l=t.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(e.length<2||t.length<2)return-1;i=2,s/=2,l/=2,r/=2}function u(e,t){return 1===i?e[t]:e.readUInt16BE(t*i)}if(o){let n=-1;for(a=r;as&&(r=s-l),a=r;a>=0;a--){let r=!0;for(let n=0;no&&(n=o):n=o;const a=t.length;let i;for(n>a/2&&(n=a/2),i=0;i>8,o=r%256,a.push(o),a.push(n);return a}(t,e.length-r),e,r,n)}function A(e,t,r){return 0===t&&r===e.length?n.fromByteArray(e):n.fromByteArray(e.slice(t,r))}function k(e,t,r){r=Math.min(e.length,r);const n=[];let o=t;for(;o239?4:t>223?3:t>191?2:1;if(o+i<=r){let r,n,s,l;switch(i){case 1:t<128&&(a=t);break;case 2:r=e[o+1],128==(192&r)&&(l=(31&t)<<6|63&r,l>127&&(a=l));break;case 3:r=e[o+1],n=e[o+2],128==(192&r)&&128==(192&n)&&(l=(15&t)<<12|(63&r)<<6|63&n,l>2047&&(l<55296||l>57343)&&(a=l));break;case 4:r=e[o+1],n=e[o+2],s=e[o+3],128==(192&r)&&128==(192&n)&&128==(192&s)&&(l=(15&t)<<18|(63&r)<<12|(63&n)<<6|63&s,l>65535&&l<1114112&&(a=l))}}null===a?(a=65533,i=1):a>65535&&(a-=65536,n.push(a>>>10&1023|55296),a=56320|1023&a),n.push(a),o+=i}return function(e){const t=e.length;if(t<=C)return String.fromCharCode.apply(String,e);let r="",n=0;for(;nn.length?(l.isBuffer(t)||(t=l.from(t)),t.copy(n,o)):Uint8Array.prototype.set.call(n,t,o);else{if(!l.isBuffer(t))throw new TypeError('"list" argument must be an Array of Buffers');t.copy(n,o)}o+=t.length}return n},l.byteLength=m,l.prototype._isBuffer=!0,l.prototype.swap16=function(){const e=this.length;if(e%2!=0)throw new RangeError("Buffer size must be a multiple of 16-bits");for(let t=0;tr&&(e+=" ... "),""},a&&(l.prototype[a]=l.prototype.inspect),l.prototype.compare=function(e,t,r,n,o){if(G(e,Uint8Array)&&(e=l.from(e,e.offset,e.byteLength)),!l.isBuffer(e))throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. Received type '+typeof e);if(void 0===t&&(t=0),void 0===r&&(r=e?e.length:0),void 0===n&&(n=0),void 0===o&&(o=this.length),t<0||r>e.length||n<0||o>this.length)throw new RangeError("out of range index");if(n>=o&&t>=r)return 0;if(n>=o)return-1;if(t>=r)return 1;if(this===e)return 0;let a=(o>>>=0)-(n>>>=0),i=(r>>>=0)-(t>>>=0);const s=Math.min(a,i),u=this.slice(n,o),c=e.slice(t,r);for(let e=0;e>>=0,isFinite(r)?(r>>>=0,void 0===n&&(n="utf8")):(n=r,r=void 0)}const o=this.length-t;if((void 0===r||r>o)&&(r=o),e.length>0&&(r<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");let a=!1;for(;;)switch(n){case"hex":return w(this,e,t,r);case"utf8":case"utf-8":return E(this,e,t,r);case"ascii":case"latin1":case"binary":return x(this,e,t,r);case"base64":return _(this,e,t,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return S(this,e,t,r);default:if(a)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),a=!0}},l.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};const C=4096;function O(e,t,r){let n="";r=Math.min(e.length,r);for(let o=t;on)&&(r=n);let o="";for(let n=t;nr)throw new RangeError("Trying to access beyond buffer length")}function P(e,t,r,n,o,a){if(!l.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>o||te.length)throw new RangeError("Index out of range")}function R(e,t,r,n,o){q(t,n,o,e,r,7);let a=Number(t&BigInt(4294967295));e[r++]=a,a>>=8,e[r++]=a,a>>=8,e[r++]=a,a>>=8,e[r++]=a;let i=Number(t>>BigInt(32)&BigInt(4294967295));return e[r++]=i,i>>=8,e[r++]=i,i>>=8,e[r++]=i,i>>=8,e[r++]=i,r}function M(e,t,r,n,o){q(t,n,o,e,r,7);let a=Number(t&BigInt(4294967295));e[r+7]=a,a>>=8,e[r+6]=a,a>>=8,e[r+5]=a,a>>=8,e[r+4]=a;let i=Number(t>>BigInt(32)&BigInt(4294967295));return e[r+3]=i,i>>=8,e[r+2]=i,i>>=8,e[r+1]=i,i>>=8,e[r]=i,r+8}function D(e,t,r,n,o,a){if(r+n>e.length)throw new RangeError("Index out of range");if(r<0)throw new RangeError("Index out of range")}function L(e,t,r,n,a){return t=+t,r>>>=0,a||D(e,0,r,4),o.write(e,t,r,n,23,4),r+4}function B(e,t,r,n,a){return t=+t,r>>>=0,a||D(e,0,r,8),o.write(e,t,r,n,52,8),r+8}l.prototype.slice=function(e,t){const r=this.length;(e=~~e)<0?(e+=r)<0&&(e=0):e>r&&(e=r),(t=void 0===t?r:~~t)<0?(t+=r)<0&&(t=0):t>r&&(t=r),t>>=0,t>>>=0,r||T(e,t,this.length);let n=this[e],o=1,a=0;for(;++a>>=0,t>>>=0,r||T(e,t,this.length);let n=this[e+--t],o=1;for(;t>0&&(o*=256);)n+=this[e+--t]*o;return n},l.prototype.readUint8=l.prototype.readUInt8=function(e,t){return e>>>=0,t||T(e,1,this.length),this[e]},l.prototype.readUint16LE=l.prototype.readUInt16LE=function(e,t){return e>>>=0,t||T(e,2,this.length),this[e]|this[e+1]<<8},l.prototype.readUint16BE=l.prototype.readUInt16BE=function(e,t){return e>>>=0,t||T(e,2,this.length),this[e]<<8|this[e+1]},l.prototype.readUint32LE=l.prototype.readUInt32LE=function(e,t){return e>>>=0,t||T(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},l.prototype.readUint32BE=l.prototype.readUInt32BE=function(e,t){return e>>>=0,t||T(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},l.prototype.readBigUInt64LE=Q((function(e){V(e>>>=0,"offset");const t=this[e],r=this[e+7];void 0!==t&&void 0!==r||$(e,this.length-8);const n=t+256*this[++e]+65536*this[++e]+this[++e]*2**24,o=this[++e]+256*this[++e]+65536*this[++e]+r*2**24;return BigInt(n)+(BigInt(o)<>>=0,"offset");const t=this[e],r=this[e+7];void 0!==t&&void 0!==r||$(e,this.length-8);const n=t*2**24+65536*this[++e]+256*this[++e]+this[++e],o=this[++e]*2**24+65536*this[++e]+256*this[++e]+r;return(BigInt(n)<>>=0,t>>>=0,r||T(e,t,this.length);let n=this[e],o=1,a=0;for(;++a=o&&(n-=Math.pow(2,8*t)),n},l.prototype.readIntBE=function(e,t,r){e>>>=0,t>>>=0,r||T(e,t,this.length);let n=t,o=1,a=this[e+--n];for(;n>0&&(o*=256);)a+=this[e+--n]*o;return o*=128,a>=o&&(a-=Math.pow(2,8*t)),a},l.prototype.readInt8=function(e,t){return e>>>=0,t||T(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},l.prototype.readInt16LE=function(e,t){e>>>=0,t||T(e,2,this.length);const r=this[e]|this[e+1]<<8;return 32768&r?4294901760|r:r},l.prototype.readInt16BE=function(e,t){e>>>=0,t||T(e,2,this.length);const r=this[e+1]|this[e]<<8;return 32768&r?4294901760|r:r},l.prototype.readInt32LE=function(e,t){return e>>>=0,t||T(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},l.prototype.readInt32BE=function(e,t){return e>>>=0,t||T(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},l.prototype.readBigInt64LE=Q((function(e){V(e>>>=0,"offset");const t=this[e],r=this[e+7];void 0!==t&&void 0!==r||$(e,this.length-8);const n=this[e+4]+256*this[e+5]+65536*this[e+6]+(r<<24);return(BigInt(n)<>>=0,"offset");const t=this[e],r=this[e+7];void 0!==t&&void 0!==r||$(e,this.length-8);const n=(t<<24)+65536*this[++e]+256*this[++e]+this[++e];return(BigInt(n)<>>=0,t||T(e,4,this.length),o.read(this,e,!0,23,4)},l.prototype.readFloatBE=function(e,t){return e>>>=0,t||T(e,4,this.length),o.read(this,e,!1,23,4)},l.prototype.readDoubleLE=function(e,t){return e>>>=0,t||T(e,8,this.length),o.read(this,e,!0,52,8)},l.prototype.readDoubleBE=function(e,t){return e>>>=0,t||T(e,8,this.length),o.read(this,e,!1,52,8)},l.prototype.writeUintLE=l.prototype.writeUIntLE=function(e,t,r,n){if(e=+e,t>>>=0,r>>>=0,!n){P(this,e,t,r,Math.pow(2,8*r)-1,0)}let o=1,a=0;for(this[t]=255&e;++a>>=0,r>>>=0,!n){P(this,e,t,r,Math.pow(2,8*r)-1,0)}let o=r-1,a=1;for(this[t+o]=255&e;--o>=0&&(a*=256);)this[t+o]=e/a&255;return t+r},l.prototype.writeUint8=l.prototype.writeUInt8=function(e,t,r){return e=+e,t>>>=0,r||P(this,e,t,1,255,0),this[t]=255&e,t+1},l.prototype.writeUint16LE=l.prototype.writeUInt16LE=function(e,t,r){return e=+e,t>>>=0,r||P(this,e,t,2,65535,0),this[t]=255&e,this[t+1]=e>>>8,t+2},l.prototype.writeUint16BE=l.prototype.writeUInt16BE=function(e,t,r){return e=+e,t>>>=0,r||P(this,e,t,2,65535,0),this[t]=e>>>8,this[t+1]=255&e,t+2},l.prototype.writeUint32LE=l.prototype.writeUInt32LE=function(e,t,r){return e=+e,t>>>=0,r||P(this,e,t,4,4294967295,0),this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e,t+4},l.prototype.writeUint32BE=l.prototype.writeUInt32BE=function(e,t,r){return e=+e,t>>>=0,r||P(this,e,t,4,4294967295,0),this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e,t+4},l.prototype.writeBigUInt64LE=Q((function(e,t=0){return R(this,e,t,BigInt(0),BigInt("0xffffffffffffffff"))})),l.prototype.writeBigUInt64BE=Q((function(e,t=0){return M(this,e,t,BigInt(0),BigInt("0xffffffffffffffff"))})),l.prototype.writeIntLE=function(e,t,r,n){if(e=+e,t>>>=0,!n){const n=Math.pow(2,8*r-1);P(this,e,t,r,n-1,-n)}let o=0,a=1,i=0;for(this[t]=255&e;++o>0)-i&255;return t+r},l.prototype.writeIntBE=function(e,t,r,n){if(e=+e,t>>>=0,!n){const n=Math.pow(2,8*r-1);P(this,e,t,r,n-1,-n)}let o=r-1,a=1,i=0;for(this[t+o]=255&e;--o>=0&&(a*=256);)e<0&&0===i&&0!==this[t+o+1]&&(i=1),this[t+o]=(e/a>>0)-i&255;return t+r},l.prototype.writeInt8=function(e,t,r){return e=+e,t>>>=0,r||P(this,e,t,1,127,-128),e<0&&(e=255+e+1),this[t]=255&e,t+1},l.prototype.writeInt16LE=function(e,t,r){return e=+e,t>>>=0,r||P(this,e,t,2,32767,-32768),this[t]=255&e,this[t+1]=e>>>8,t+2},l.prototype.writeInt16BE=function(e,t,r){return e=+e,t>>>=0,r||P(this,e,t,2,32767,-32768),this[t]=e>>>8,this[t+1]=255&e,t+2},l.prototype.writeInt32LE=function(e,t,r){return e=+e,t>>>=0,r||P(this,e,t,4,2147483647,-2147483648),this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24,t+4},l.prototype.writeInt32BE=function(e,t,r){return e=+e,t>>>=0,r||P(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e,t+4},l.prototype.writeBigInt64LE=Q((function(e,t=0){return R(this,e,t,-BigInt("0x8000000000000000"),BigInt("0x7fffffffffffffff"))})),l.prototype.writeBigInt64BE=Q((function(e,t=0){return M(this,e,t,-BigInt("0x8000000000000000"),BigInt("0x7fffffffffffffff"))})),l.prototype.writeFloatLE=function(e,t,r){return L(this,e,t,!0,r)},l.prototype.writeFloatBE=function(e,t,r){return L(this,e,t,!1,r)},l.prototype.writeDoubleLE=function(e,t,r){return B(this,e,t,!0,r)},l.prototype.writeDoubleBE=function(e,t,r){return B(this,e,t,!1,r)},l.prototype.copy=function(e,t,r,n){if(!l.isBuffer(e))throw new TypeError("argument should be a Buffer");if(r||(r=0),n||0===n||(n=this.length),t>=e.length&&(t=e.length),t||(t=0),n>0&&n=this.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("sourceEnd out of bounds");n>this.length&&(n=this.length),e.length-t>>=0,r=void 0===r?this.length:r>>>0,e||(e=0),"number"==typeof e)for(o=t;o=n+4;r-=3)t=`_${e.slice(r-3,r)}${t}`;return`${e.slice(0,r)}${t}`}function q(e,t,r,n,o,a){if(e>r||e3?0===t||t===BigInt(0)?`>= 0${n} and < 2${n} ** ${8*(a+1)}${n}`:`>= -(2${n} ** ${8*(a+1)-1}${n}) and < 2 ** ${8*(a+1)-1}${n}`:`>= ${t}${n} and <= ${r}${n}`,new F.ERR_OUT_OF_RANGE("value",o,e)}!function(e,t,r){V(t,"offset"),void 0!==e[t]&&void 0!==e[t+r]||$(t,e.length-(r+1))}(n,o,a)}function V(e,t){if("number"!=typeof e)throw new F.ERR_INVALID_ARG_TYPE(t,"number",e)}function $(e,t,r){if(Math.floor(e)!==e)throw V(e,r),new F.ERR_OUT_OF_RANGE(r||"offset","an integer",e);if(t<0)throw new F.ERR_BUFFER_OUT_OF_BOUNDS;throw new F.ERR_OUT_OF_RANGE(r||"offset",`>= ${r?1:0} and <= ${t}`,e)}z("ERR_BUFFER_OUT_OF_BOUNDS",(function(e){return e?`${e} is outside of buffer bounds`:"Attempt to access memory outside buffer bounds"}),RangeError),z("ERR_INVALID_ARG_TYPE",(function(e,t){return`The "${e}" argument must be of type number. Received type ${typeof t}`}),TypeError),z("ERR_OUT_OF_RANGE",(function(e,t,r){let n=`The value of "${e}" is out of range.`,o=r;return Number.isInteger(r)&&Math.abs(r)>2**32?o=U(String(r)):"bigint"==typeof r&&(o=String(r),(r>BigInt(2)**BigInt(32)||r<-(BigInt(2)**BigInt(32)))&&(o=U(o)),o+="n"),n+=` It must be ${t}. Received ${o}`,n}),RangeError);const W=/[^+/0-9A-Za-z-_]/g;function H(e,t){let r;t=t||1/0;const n=e.length;let o=null;const a=[];for(let i=0;i55295&&r<57344){if(!o){if(r>56319){(t-=3)>-1&&a.push(239,191,189);continue}if(i+1===n){(t-=3)>-1&&a.push(239,191,189);continue}o=r;continue}if(r<56320){(t-=3)>-1&&a.push(239,191,189),o=r;continue}r=65536+(o-55296<<10|r-56320)}else o&&(t-=3)>-1&&a.push(239,191,189);if(o=null,r<128){if((t-=1)<0)break;a.push(r)}else if(r<2048){if((t-=2)<0)break;a.push(r>>6|192,63&r|128)}else if(r<65536){if((t-=3)<0)break;a.push(r>>12|224,r>>6&63|128,63&r|128)}else{if(!(r<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;a.push(r>>18|240,r>>12&63|128,r>>6&63|128,63&r|128)}}return a}function J(e){return n.toByteArray(function(e){if((e=(e=e.split("=")[0]).trim().replace(W,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function K(e,t,r,n){let o;for(o=0;o=t.length||o>=e.length);++o)t[o+r]=e[o];return o}function G(e,t){return e instanceof t||null!=e&&null!=e.constructor&&null!=e.constructor.name&&e.constructor.name===t.name}function Z(e){return e!=e}const Y=function(){const e="0123456789abcdef",t=new Array(256);for(let r=0;r<16;++r){const n=16*r;for(let o=0;o<16;++o)t[n+o]=e[r]+e[o]}return t}();function Q(e){return"undefined"==typeof BigInt?X:e}function X(){throw new Error("BigInt not supported")}},21924:(e,t,r)=>{"use strict";var n=r(40210),o=r(55559),a=o(n("String.prototype.indexOf"));e.exports=function(e,t){var r=n(e,!!t);return"function"==typeof r&&a(e,".prototype.")>-1?o(r):r}},55559:(e,t,r)=>{"use strict";var n=r(58612),o=r(40210),a=o("%Function.prototype.apply%"),i=o("%Function.prototype.call%"),s=o("%Reflect.apply%",!0)||n.call(i,a),l=o("%Object.getOwnPropertyDescriptor%",!0),u=o("%Object.defineProperty%",!0),c=o("%Math.max%");if(u)try{u({},"a",{value:1})}catch(e){u=null}e.exports=function(e){var t=s(n,i,arguments);if(l&&u){var r=l(t,"length");r.configurable&&u(t,"length",{value:1+c(0,e.length-(arguments.length-1))})}return t};var p=function(){return s(n,a,arguments)};u?u(e.exports,"apply",{value:p}):e.exports.apply=p},94184:(e,t)=>{var r;!function(){"use strict";var n={}.hasOwnProperty;function o(){for(var e=[],t=0;t{"use strict";t.parse=function(e,t){if("string"!=typeof e)throw new TypeError("argument str must be a string");var r={},n=(t||{}).decode||o,a=0;for(;a{"use strict";var n=r(11742),o={"text/plain":"Text","text/html":"Url",default:"Text"};e.exports=function(e,t){var r,a,i,s,l,u,c=!1;t||(t={}),r=t.debug||!1;try{if(i=n(),s=document.createRange(),l=document.getSelection(),(u=document.createElement("span")).textContent=e,u.style.all="unset",u.style.position="fixed",u.style.top=0,u.style.clip="rect(0, 0, 0, 0)",u.style.whiteSpace="pre",u.style.webkitUserSelect="text",u.style.MozUserSelect="text",u.style.msUserSelect="text",u.style.userSelect="text",u.addEventListener("copy",(function(n){if(n.stopPropagation(),t.format)if(n.preventDefault(),void 0===n.clipboardData){r&&console.warn("unable to use e.clipboardData"),r&&console.warn("trying IE specific stuff"),window.clipboardData.clearData();var a=o[t.format]||o.default;window.clipboardData.setData(a,e)}else n.clipboardData.clearData(),n.clipboardData.setData(t.format,e);t.onCopy&&(n.preventDefault(),t.onCopy(n.clipboardData))})),document.body.appendChild(u),s.selectNodeContents(u),l.addRange(s),!document.execCommand("copy"))throw new Error("copy command was unsuccessful");c=!0}catch(n){r&&console.error("unable to copy using execCommand: ",n),r&&console.warn("trying IE specific stuff");try{window.clipboardData.setData(t.format||"text",e),t.onCopy&&t.onCopy(window.clipboardData),c=!0}catch(n){r&&console.error("unable to copy using clipboardData: ",n),r&&console.error("falling back to prompt"),a=function(e){var t=(/mac os x/i.test(navigator.userAgent)?"⌘":"Ctrl")+"+C";return e.replace(/#{\s*key\s*}/g,t)}("message"in t?t.message:"Copy to clipboard: #{key}, Enter"),window.prompt(a,e)}}finally{l&&("function"==typeof l.removeRange?l.removeRange(s):l.removeAllRanges()),u&&document.body.removeChild(u),i()}return c}},95299:(e,t,r)=>{var n=r(24848);e.exports=n},83450:(e,t,r)=>{var n=r(83363);e.exports=n},66820:(e,t,r)=>{var n=r(56243);e.exports=n},5023:(e,t,r)=>{var n=r(72369);e.exports=n},90093:(e,t,r)=>{var n=r(28196);e.exports=n},3688:(e,t,r)=>{var n=r(11955);e.exports=n},83838:(e,t,r)=>{var n=r(46279);e.exports=n},15684:(e,t,r)=>{var n=r(19373);e.exports=n},99826:(e,t,r)=>{var n=r(28427);e.exports=n},84234:(e,t,r)=>{var n=r(82073);e.exports=n},65362:(e,t,r)=>{var n=r(63383);e.exports=n},32271:(e,t,r)=>{var n=r(14471);e.exports=n},91254:(e,t,r)=>{var n=r(57396);e.exports=n},43536:(e,t,r)=>{var n=r(41910);e.exports=n},37331:(e,t,r)=>{var n=r(79427);e.exports=n},68522:(e,t,r)=>{var n=r(62857);e.exports=n},73151:(e,t,r)=>{var n=r(9534);e.exports=n},99565:(e,t,r)=>{var n=r(96507);e.exports=n},45012:(e,t,r)=>{var n=r(23059);e.exports=n},78690:(e,t,r)=>{var n=r(16670);e.exports=n},25626:(e,t,r)=>{var n=r(27460);e.exports=n},80281:(e,t,r)=>{var n=r(92547);e.exports=n},40031:(e,t,r)=>{var n=r(46509);e.exports=n},54493:(e,t,r)=>{r(77971),r(53242);var n=r(54058);e.exports=n.Array.from},24034:(e,t,r)=>{r(92737);var n=r(54058);e.exports=n.Array.isArray},15367:(e,t,r)=>{r(85906);var n=r(35703);e.exports=n("Array").concat},12710:(e,t,r)=>{r(66274),r(55967);var n=r(35703);e.exports=n("Array").entries},51459:(e,t,r)=>{r(48851);var n=r(35703);e.exports=n("Array").every},6172:(e,t,r)=>{r(80290);var n=r(35703);e.exports=n("Array").fill},62383:(e,t,r)=>{r(21501);var n=r(35703);e.exports=n("Array").filter},60009:(e,t,r)=>{r(44929);var n=r(35703);e.exports=n("Array").findIndex},17671:(e,t,r)=>{r(80833);var n=r(35703);e.exports=n("Array").find},99324:(e,t,r)=>{r(2437);var n=r(35703);e.exports=n("Array").forEach},80991:(e,t,r)=>{r(97690);var n=r(35703);e.exports=n("Array").includes},8700:(e,t,r)=>{r(99076);var n=r(35703);e.exports=n("Array").indexOf},95909:(e,t,r)=>{r(66274),r(55967);var n=r(35703);e.exports=n("Array").keys},6442:(e,t,r)=>{r(75915);var n=r(35703);e.exports=n("Array").lastIndexOf},23866:(e,t,r)=>{r(68787);var n=r(35703);e.exports=n("Array").map},52999:(e,t,r)=>{r(81876);var n=r(35703);e.exports=n("Array").reduce},91876:(e,t,r)=>{r(11490);var n=r(35703);e.exports=n("Array").reverse},24900:(e,t,r)=>{r(60186);var n=r(35703);e.exports=n("Array").slice},3824:(e,t,r)=>{r(36026);var n=r(35703);e.exports=n("Array").some},2948:(e,t,r)=>{r(4115);var n=r(35703);e.exports=n("Array").sort},78209:(e,t,r)=>{r(98611);var n=r(35703);e.exports=n("Array").splice},14423:(e,t,r)=>{r(66274),r(55967);var n=r(35703);e.exports=n("Array").values},81103:(e,t,r)=>{r(95160);var n=r(54058);e.exports=n.Date.now},27700:(e,t,r)=>{r(73381);var n=r(35703);e.exports=n("Function").bind},13830:(e,t,r)=>{r(66274),r(77971);var n=r(22902);e.exports=n},91031:(e,t,r)=>{r(52595),e.exports=r(21899)},16246:(e,t,r)=>{var n=r(7046),o=r(27700),a=Function.prototype;e.exports=function(e){var t=e.bind;return e===a||n(a,e)&&t===a.bind?o:t}},56043:(e,t,r)=>{var n=r(7046),o=r(15367),a=Array.prototype;e.exports=function(e){var t=e.concat;return e===a||n(a,e)&&t===a.concat?o:t}},13160:(e,t,r)=>{var n=r(7046),o=r(51459),a=Array.prototype;e.exports=function(e){var t=e.every;return e===a||n(a,e)&&t===a.every?o:t}},80446:(e,t,r)=>{var n=r(7046),o=r(6172),a=Array.prototype;e.exports=function(e){var t=e.fill;return e===a||n(a,e)&&t===a.fill?o:t}},2480:(e,t,r)=>{var n=r(7046),o=r(62383),a=Array.prototype;e.exports=function(e){var t=e.filter;return e===a||n(a,e)&&t===a.filter?o:t}},7147:(e,t,r)=>{var n=r(7046),o=r(60009),a=Array.prototype;e.exports=function(e){var t=e.findIndex;return e===a||n(a,e)&&t===a.findIndex?o:t}},32236:(e,t,r)=>{var n=r(7046),o=r(17671),a=Array.prototype;e.exports=function(e){var t=e.find;return e===a||n(a,e)&&t===a.find?o:t}},58557:(e,t,r)=>{var n=r(7046),o=r(80991),a=r(21631),i=Array.prototype,s=String.prototype;e.exports=function(e){var t=e.includes;return e===i||n(i,e)&&t===i.includes?o:"string"==typeof e||e===s||n(s,e)&&t===s.includes?a:t}},34570:(e,t,r)=>{var n=r(7046),o=r(8700),a=Array.prototype;e.exports=function(e){var t=e.indexOf;return e===a||n(a,e)&&t===a.indexOf?o:t}},57564:(e,t,r)=>{var n=r(7046),o=r(6442),a=Array.prototype;e.exports=function(e){var t=e.lastIndexOf;return e===a||n(a,e)&&t===a.lastIndexOf?o:t}},88287:(e,t,r)=>{var n=r(7046),o=r(23866),a=Array.prototype;e.exports=function(e){var t=e.map;return e===a||n(a,e)&&t===a.map?o:t}},68025:(e,t,r)=>{var n=r(7046),o=r(52999),a=Array.prototype;e.exports=function(e){var t=e.reduce;return e===a||n(a,e)&&t===a.reduce?o:t}},59257:(e,t,r)=>{var n=r(7046),o=r(80454),a=String.prototype;e.exports=function(e){var t=e.repeat;return"string"==typeof e||e===a||n(a,e)&&t===a.repeat?o:t}},91060:(e,t,r)=>{var n=r(7046),o=r(91876),a=Array.prototype;e.exports=function(e){var t=e.reverse;return e===a||n(a,e)&&t===a.reverse?o:t}},69601:(e,t,r)=>{var n=r(7046),o=r(24900),a=Array.prototype;e.exports=function(e){var t=e.slice;return e===a||n(a,e)&&t===a.slice?o:t}},28299:(e,t,r)=>{var n=r(7046),o=r(3824),a=Array.prototype;e.exports=function(e){var t=e.some;return e===a||n(a,e)&&t===a.some?o:t}},69355:(e,t,r)=>{var n=r(7046),o=r(2948),a=Array.prototype;e.exports=function(e){var t=e.sort;return e===a||n(a,e)&&t===a.sort?o:t}},18339:(e,t,r)=>{var n=r(7046),o=r(78209),a=Array.prototype;e.exports=function(e){var t=e.splice;return e===a||n(a,e)&&t===a.splice?o:t}},71611:(e,t,r)=>{var n=r(7046),o=r(3269),a=String.prototype;e.exports=function(e){var t=e.startsWith;return"string"==typeof e||e===a||n(a,e)&&t===a.startsWith?o:t}},62774:(e,t,r)=>{var n=r(7046),o=r(13348),a=String.prototype;e.exports=function(e){var t=e.trim;return"string"==typeof e||e===a||n(a,e)&&t===a.trim?o:t}},84426:(e,t,r)=>{r(32619);var n=r(54058),o=r(79730);n.JSON||(n.JSON={stringify:JSON.stringify}),e.exports=function(e,t,r){return o(n.JSON.stringify,null,arguments)}},91018:(e,t,r)=>{r(66274),r(37501),r(55967),r(77971);var n=r(54058);e.exports=n.Map},45999:(e,t,r)=>{r(49221);var n=r(54058);e.exports=n.Object.assign},35254:(e,t,r)=>{r(53882);var n=r(54058).Object;e.exports=function(e,t){return n.create(e,t)}},7702:(e,t,r)=>{r(74979);var n=r(54058).Object,o=e.exports=function(e,t){return n.defineProperties(e,t)};n.defineProperties.sham&&(o.sham=!0)},48171:(e,t,r)=>{r(86450);var n=r(54058).Object,o=e.exports=function(e,t,r){return n.defineProperty(e,t,r)};n.defineProperty.sham&&(o.sham=!0)},73081:(e,t,r)=>{r(94366);var n=r(54058);e.exports=n.Object.entries},286:(e,t,r)=>{r(46924);var n=r(54058).Object,o=e.exports=function(e,t){return n.getOwnPropertyDescriptor(e,t)};n.getOwnPropertyDescriptor.sham&&(o.sham=!0)},92766:(e,t,r)=>{r(88482);var n=r(54058);e.exports=n.Object.getOwnPropertyDescriptors},30498:(e,t,r)=>{r(35824);var n=r(54058);e.exports=n.Object.getOwnPropertySymbols},13966:(e,t,r)=>{r(17405);var n=r(54058);e.exports=n.Object.getPrototypeOf},48494:(e,t,r)=>{r(21724);var n=r(54058);e.exports=n.Object.keys},3065:(e,t,r)=>{r(90108);var n=r(54058);e.exports=n.Object.setPrototypeOf},98430:(e,t,r)=>{r(26614);var n=r(54058);e.exports=n.Object.values},52956:(e,t,r)=>{r(47627),r(66274),r(55967),r(98881),r(4560),r(91302),r(44349),r(77971);var n=r(54058);e.exports=n.Promise},21631:(e,t,r)=>{r(11035);var n=r(35703);e.exports=n("String").includes},80454:(e,t,r)=>{r(60986);var n=r(35703);e.exports=n("String").repeat},3269:(e,t,r)=>{r(94761);var n=r(35703);e.exports=n("String").startsWith},13348:(e,t,r)=>{r(57398);var n=r(35703);e.exports=n("String").trim},57473:(e,t,r)=>{r(85906),r(55967),r(35824),r(8555),r(52615),r(21732),r(35903),r(1825),r(28394),r(45915),r(61766),r(62737),r(89911),r(74315),r(63131),r(64714),r(70659),r(69120),r(79413),r(1502);var n=r(54058);e.exports=n.Symbol},24227:(e,t,r)=>{r(66274),r(55967),r(77971),r(1825);var n=r(11477);e.exports=n.f("iterator")},32304:(e,t,r)=>{r(66274),r(55967),r(54334);var n=r(54058);e.exports=n.WeakMap},27385:(e,t,r)=>{var n=r(95299);e.exports=n},81522:(e,t,r)=>{var n=r(83450);e.exports=n},32209:(e,t,r)=>{var n=r(66820);e.exports=n},30888:(e,t,r)=>{r(9668);var n=r(5023);e.exports=n},14122:(e,t,r)=>{var n=r(90093);e.exports=n},44442:(e,t,r)=>{var n=r(3688);e.exports=n},57152:(e,t,r)=>{var n=r(83838);e.exports=n},69447:(e,t,r)=>{var n=r(15684);e.exports=n},17579:(e,t,r)=>{var n=r(99826);e.exports=n},81493:(e,t,r)=>{var n=r(84234);e.exports=n},60269:(e,t,r)=>{var n=r(65362);e.exports=n},76094:(e,t,r)=>{var n=r(32271);e.exports=n},70573:(e,t,r)=>{var n=r(91254);e.exports=n},73685:(e,t,r)=>{var n=r(43536);e.exports=n},27533:(e,t,r)=>{var n=r(37331);e.exports=n},39057:(e,t,r)=>{var n=r(68522);e.exports=n},84710:(e,t,r)=>{var n=r(73151);e.exports=n},74303:(e,t,r)=>{var n=r(99565);e.exports=n},93799:(e,t,r)=>{var n=r(45012);e.exports=n},55122:(e,t,r)=>{var n=r(78690);e.exports=n},29531:(e,t,r)=>{var n=r(25626);r(89731),r(55708),r(30014),r(88731),e.exports=n},86600:(e,t,r)=>{var n=r(80281);r(28783),r(43975),r(65799),r(45414),r(46774),r(80620),r(36172),e.exports=n},9759:(e,t,r)=>{var n=r(40031);e.exports=n},24883:(e,t,r)=>{var n=r(21899),o=r(57475),a=r(69826),i=n.TypeError;e.exports=function(e){if(o(e))return e;throw i(a(e)+" is not a function")}},174:(e,t,r)=>{var n=r(21899),o=r(24284),a=r(69826),i=n.TypeError;e.exports=function(e){if(o(e))return e;throw i(a(e)+" is not a constructor")}},11851:(e,t,r)=>{var n=r(21899),o=r(57475),a=n.String,i=n.TypeError;e.exports=function(e){if("object"==typeof e||o(e))return e;throw i("Can't set "+a(e)+" as a prototype")}},18479:e=>{e.exports=function(){}},5743:(e,t,r)=>{var n=r(21899),o=r(7046),a=n.TypeError;e.exports=function(e,t){if(o(t,e))return e;throw a("Incorrect invocation")}},96059:(e,t,r)=>{var n=r(21899),o=r(10941),a=n.String,i=n.TypeError;e.exports=function(e){if(o(e))return e;throw i(a(e)+" is not an object")}},97135:(e,t,r)=>{var n=r(95981);e.exports=n((function(){if("function"==typeof ArrayBuffer){var e=new ArrayBuffer(8);Object.isExtensible(e)&&Object.defineProperty(e,"a",{value:8})}}))},91860:(e,t,r)=>{"use strict";var n=r(89678),o=r(59413),a=r(10623);e.exports=function(e){for(var t=n(this),r=a(t),i=arguments.length,s=o(i>1?arguments[1]:void 0,r),l=i>2?arguments[2]:void 0,u=void 0===l?r:o(l,r);u>s;)t[s++]=e;return t}},56837:(e,t,r)=>{"use strict";var n=r(3610).forEach,o=r(34194)("forEach");e.exports=o?[].forEach:function(e){return n(this,e,arguments.length>1?arguments[1]:void 0)}},11354:(e,t,r)=>{"use strict";var n=r(21899),o=r(86843),a=r(78834),i=r(89678),s=r(75196),l=r(6782),u=r(24284),c=r(10623),p=r(55449),f=r(53476),h=r(22902),d=n.Array;e.exports=function(e){var t=i(e),r=u(this),n=arguments.length,m=n>1?arguments[1]:void 0,g=void 0!==m;g&&(m=o(m,n>2?arguments[2]:void 0));var v,y,b,w,E,x,_=h(t),S=0;if(!_||this==d&&l(_))for(v=c(t),y=r?new this(v):d(v);v>S;S++)x=g?m(t[S],S):t[S],p(y,S,x);else for(E=(w=f(t,_)).next,y=r?new this:[];!(b=a(E,w)).done;S++)x=g?s(w,m,[b.value,S],!0):b.value,p(y,S,x);return y.length=S,y}},31692:(e,t,r)=>{var n=r(74529),o=r(59413),a=r(10623),i=function(e){return function(t,r,i){var s,l=n(t),u=a(l),c=o(i,u);if(e&&r!=r){for(;u>c;)if((s=l[c++])!=s)return!0}else for(;u>c;c++)if((e||c in l)&&l[c]===r)return e||c||0;return!e&&-1}};e.exports={includes:i(!0),indexOf:i(!1)}},3610:(e,t,r)=>{var n=r(86843),o=r(95329),a=r(37026),i=r(89678),s=r(10623),l=r(64692),u=o([].push),c=function(e){var t=1==e,r=2==e,o=3==e,c=4==e,p=6==e,f=7==e,h=5==e||p;return function(d,m,g,v){for(var y,b,w=i(d),E=a(w),x=n(m,g),_=s(E),S=0,A=v||l,k=t?A(d,_):r||f?A(d,0):void 0;_>S;S++)if((h||S in E)&&(b=x(y=E[S],S,w),e))if(t)k[S]=b;else if(b)switch(e){case 3:return!0;case 5:return y;case 6:return S;case 2:u(k,y)}else switch(e){case 4:return!1;case 7:u(k,y)}return p?-1:o||c?c:k}};e.exports={forEach:c(0),map:c(1),filter:c(2),some:c(3),every:c(4),find:c(5),findIndex:c(6),filterReject:c(7)}},67145:(e,t,r)=>{"use strict";var n=r(79730),o=r(74529),a=r(62435),i=r(10623),s=r(34194),l=Math.min,u=[].lastIndexOf,c=!!u&&1/[1].lastIndexOf(1,-0)<0,p=s("lastIndexOf"),f=c||!p;e.exports=f?function(e){if(c)return n(u,this,arguments)||0;var t=o(this),r=i(t),s=r-1;for(arguments.length>1&&(s=l(s,a(arguments[1]))),s<0&&(s=r+s);s>=0;s--)if(s in t&&t[s]===e)return s||0;return-1}:u},50568:(e,t,r)=>{var n=r(95981),o=r(99813),a=r(53385),i=o("species");e.exports=function(e){return a>=51||!n((function(){var t=[];return(t.constructor={})[i]=function(){return{foo:1}},1!==t[e](Boolean).foo}))}},34194:(e,t,r)=>{"use strict";var n=r(95981);e.exports=function(e,t){var r=[][e];return!!r&&n((function(){r.call(null,t||function(){throw 1},1)}))}},46499:(e,t,r)=>{var n=r(21899),o=r(24883),a=r(89678),i=r(37026),s=r(10623),l=n.TypeError,u=function(e){return function(t,r,n,u){o(r);var c=a(t),p=i(c),f=s(c),h=e?f-1:0,d=e?-1:1;if(n<2)for(;;){if(h in p){u=p[h],h+=d;break}if(h+=d,e?h<0:f<=h)throw l("Reduce of empty array with no initial value")}for(;e?h>=0:f>h;h+=d)h in p&&(u=r(u,p[h],h,c));return u}};e.exports={left:u(!1),right:u(!0)}},15790:(e,t,r)=>{var n=r(21899),o=r(59413),a=r(10623),i=r(55449),s=n.Array,l=Math.max;e.exports=function(e,t,r){for(var n=a(e),u=o(t,n),c=o(void 0===r?n:r,n),p=s(l(c-u,0)),f=0;u{var n=r(95329);e.exports=n([].slice)},61388:(e,t,r)=>{var n=r(15790),o=Math.floor,a=function(e,t){var r=e.length,l=o(r/2);return r<8?i(e,t):s(e,a(n(e,0,l),t),a(n(e,l),t),t)},i=function(e,t){for(var r,n,o=e.length,a=1;a0;)e[n]=e[--n];n!==a++&&(e[n]=r)}return e},s=function(e,t,r,n){for(var o=t.length,a=r.length,i=0,s=0;i{var n=r(21899),o=r(1052),a=r(24284),i=r(10941),s=r(99813)("species"),l=n.Array;e.exports=function(e){var t;return o(e)&&(t=e.constructor,(a(t)&&(t===l||o(t.prototype))||i(t)&&null===(t=t[s]))&&(t=void 0)),void 0===t?l:t}},64692:(e,t,r)=>{var n=r(5693);e.exports=function(e,t){return new(n(e))(0===t?0:t)}},75196:(e,t,r)=>{var n=r(96059),o=r(7609);e.exports=function(e,t,r,a){try{return a?t(n(r)[0],r[1]):t(r)}catch(t){o(e,"throw",t)}}},21385:(e,t,r)=>{var n=r(99813)("iterator"),o=!1;try{var a=0,i={next:function(){return{done:!!a++}},return:function(){o=!0}};i[n]=function(){return this},Array.from(i,(function(){throw 2}))}catch(e){}e.exports=function(e,t){if(!t&&!o)return!1;var r=!1;try{var a={};a[n]=function(){return{next:function(){return{done:r=!0}}}},e(a)}catch(e){}return r}},82532:(e,t,r)=>{var n=r(95329),o=n({}.toString),a=n("".slice);e.exports=function(e){return a(o(e),8,-1)}},9697:(e,t,r)=>{var n=r(21899),o=r(22885),a=r(57475),i=r(82532),s=r(99813)("toStringTag"),l=n.Object,u="Arguments"==i(function(){return arguments}());e.exports=o?i:function(e){var t,r,n;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(r=function(e,t){try{return e[t]}catch(e){}}(t=l(e),s))?r:u?i(t):"Object"==(n=i(t))&&a(t.callee)?"Arguments":n}},38694:(e,t,r)=>{var n=r(95329)("".replace),o=String(Error("zxcasd").stack),a=/\n\s*at [^:]*:[^\n]*/,i=a.test(o);e.exports=function(e,t){if(i&&"string"==typeof e)for(;t--;)e=n(e,a,"");return e}},85616:(e,t,r)=>{"use strict";var n=r(65988).f,o=r(29290),a=r(87524),i=r(86843),s=r(5743),l=r(93091),u=r(47771),c=r(94431),p=r(55746),f=r(21647).fastKey,h=r(45402),d=h.set,m=h.getterFor;e.exports={getConstructor:function(e,t,r,u){var c=e((function(e,n){s(e,h),d(e,{type:t,index:o(null),first:void 0,last:void 0,size:0}),p||(e.size=0),null!=n&&l(n,e[u],{that:e,AS_ENTRIES:r})})),h=c.prototype,g=m(t),v=function(e,t,r){var n,o,a=g(e),i=y(e,t);return i?i.value=r:(a.last=i={index:o=f(t,!0),key:t,value:r,previous:n=a.last,next:void 0,removed:!1},a.first||(a.first=i),n&&(n.next=i),p?a.size++:e.size++,"F"!==o&&(a.index[o]=i)),e},y=function(e,t){var r,n=g(e),o=f(t);if("F"!==o)return n.index[o];for(r=n.first;r;r=r.next)if(r.key==t)return r};return a(h,{clear:function(){for(var e=g(this),t=e.index,r=e.first;r;)r.removed=!0,r.previous&&(r.previous=r.previous.next=void 0),delete t[r.index],r=r.next;e.first=e.last=void 0,p?e.size=0:this.size=0},delete:function(e){var t=this,r=g(t),n=y(t,e);if(n){var o=n.next,a=n.previous;delete r.index[n.index],n.removed=!0,a&&(a.next=o),o&&(o.previous=a),r.first==n&&(r.first=o),r.last==n&&(r.last=a),p?r.size--:t.size--}return!!n},forEach:function(e){for(var t,r=g(this),n=i(e,arguments.length>1?arguments[1]:void 0);t=t?t.next:r.first;)for(n(t.value,t.key,this);t&&t.removed;)t=t.previous},has:function(e){return!!y(this,e)}}),a(h,r?{get:function(e){var t=y(this,e);return t&&t.value},set:function(e,t){return v(this,0===e?0:e,t)}}:{add:function(e){return v(this,e=0===e?0:e,e)}}),p&&n(h,"size",{get:function(){return g(this).size}}),c},setStrong:function(e,t,r){var n=t+" Iterator",o=m(t),a=m(n);u(e,t,(function(e,t){d(this,{type:n,target:e,state:o(e),kind:t,last:void 0})}),(function(){for(var e=a(this),t=e.kind,r=e.last;r&&r.removed;)r=r.previous;return e.target&&(e.last=r=r?r.next:e.state.first)?"keys"==t?{value:r.key,done:!1}:"values"==t?{value:r.value,done:!1}:{value:[r.key,r.value],done:!1}:(e.target=void 0,{value:void 0,done:!0})}),r?"entries":"values",!r,!0),c(t)}}},8850:(e,t,r)=>{"use strict";var n=r(95329),o=r(87524),a=r(21647).getWeakData,i=r(96059),s=r(10941),l=r(5743),u=r(93091),c=r(3610),p=r(90953),f=r(45402),h=f.set,d=f.getterFor,m=c.find,g=c.findIndex,v=n([].splice),y=0,b=function(e){return e.frozen||(e.frozen=new w)},w=function(){this.entries=[]},E=function(e,t){return m(e.entries,(function(e){return e[0]===t}))};w.prototype={get:function(e){var t=E(this,e);if(t)return t[1]},has:function(e){return!!E(this,e)},set:function(e,t){var r=E(this,e);r?r[1]=t:this.entries.push([e,t])},delete:function(e){var t=g(this.entries,(function(t){return t[0]===e}));return~t&&v(this.entries,t,1),!!~t}},e.exports={getConstructor:function(e,t,r,n){var c=e((function(e,o){l(e,f),h(e,{type:t,id:y++,frozen:void 0}),null!=o&&u(o,e[n],{that:e,AS_ENTRIES:r})})),f=c.prototype,m=d(t),g=function(e,t,r){var n=m(e),o=a(i(t),!0);return!0===o?b(n).set(t,r):o[n.id]=r,e};return o(f,{delete:function(e){var t=m(this);if(!s(e))return!1;var r=a(e);return!0===r?b(t).delete(e):r&&p(r,t.id)&&delete r[t.id]},has:function(e){var t=m(this);if(!s(e))return!1;var r=a(e);return!0===r?b(t).has(e):r&&p(r,t.id)}}),o(f,r?{get:function(e){var t=m(this);if(s(e)){var r=a(e);return!0===r?b(t).get(e):r?r[t.id]:void 0}},set:function(e,t){return g(this,e,t)}}:{add:function(e){return g(this,e,!0)}}),c}}},24683:(e,t,r)=>{"use strict";var n=r(76887),o=r(21899),a=r(21647),i=r(95981),s=r(32029),l=r(93091),u=r(5743),c=r(57475),p=r(10941),f=r(90904),h=r(65988).f,d=r(3610).forEach,m=r(55746),g=r(45402),v=g.set,y=g.getterFor;e.exports=function(e,t,r){var g,b=-1!==e.indexOf("Map"),w=-1!==e.indexOf("Weak"),E=b?"set":"add",x=o[e],_=x&&x.prototype,S={};if(m&&c(x)&&(w||_.forEach&&!i((function(){(new x).entries().next()})))){var A=(g=t((function(t,r){v(u(t,A),{type:e,collection:new x}),null!=r&&l(r,t[E],{that:t,AS_ENTRIES:b})}))).prototype,k=y(e);d(["add","clear","delete","forEach","get","has","set","keys","values","entries"],(function(e){var t="add"==e||"set"==e;!(e in _)||w&&"clear"==e||s(A,e,(function(r,n){var o=k(this).collection;if(!t&&w&&!p(r))return"get"==e&&void 0;var a=o[e](0===r?0:r,n);return t?this:a}))})),w||h(A,"size",{configurable:!0,get:function(){return k(this).collection.size}})}else g=r.getConstructor(t,e,b,E),a.enable();return f(g,e,!1,!0),S[e]=g,n({global:!0,forced:!0},S),w||r.setStrong(g,e,b),g}},23489:(e,t,r)=>{var n=r(90953),o=r(31136),a=r(49677),i=r(65988);e.exports=function(e,t,r){for(var s=o(t),l=i.f,u=a.f,c=0;c{var n=r(99813)("match");e.exports=function(e){var t=/./;try{"/./"[e](t)}catch(r){try{return t[n]=!1,"/./"[e](t)}catch(e){}}return!1}},64160:(e,t,r)=>{var n=r(95981);e.exports=!n((function(){function e(){}return e.prototype.constructor=null,Object.getPrototypeOf(new e)!==e.prototype}))},31046:(e,t,r)=>{"use strict";var n=r(35143).IteratorPrototype,o=r(29290),a=r(31887),i=r(90904),s=r(12077),l=function(){return this};e.exports=function(e,t,r,u){var c=t+" Iterator";return e.prototype=o(n,{next:a(+!u,r)}),i(e,c,!1,!0),s[c]=l,e}},32029:(e,t,r)=>{var n=r(55746),o=r(65988),a=r(31887);e.exports=n?function(e,t,r){return o.f(e,t,a(1,r))}:function(e,t,r){return e[t]=r,e}},31887:e=>{e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},55449:(e,t,r)=>{"use strict";var n=r(83894),o=r(65988),a=r(31887);e.exports=function(e,t,r){var i=n(t);i in e?o.f(e,i,a(0,r)):e[i]=r}},47771:(e,t,r)=>{"use strict";var n=r(76887),o=r(78834),a=r(82529),i=r(79417),s=r(57475),l=r(31046),u=r(249),c=r(88929),p=r(90904),f=r(32029),h=r(99754),d=r(99813),m=r(12077),g=r(35143),v=i.PROPER,y=i.CONFIGURABLE,b=g.IteratorPrototype,w=g.BUGGY_SAFARI_ITERATORS,E=d("iterator"),x="keys",_="values",S="entries",A=function(){return this};e.exports=function(e,t,r,i,d,g,k){l(r,t,i);var C,O,j,I=function(e){if(e===d&&M)return M;if(!w&&e in P)return P[e];switch(e){case x:case _:case S:return function(){return new r(this,e)}}return function(){return new r(this)}},N=t+" Iterator",T=!1,P=e.prototype,R=P[E]||P["@@iterator"]||d&&P[d],M=!w&&R||I(d),D="Array"==t&&P.entries||R;if(D&&(C=u(D.call(new e)))!==Object.prototype&&C.next&&(a||u(C)===b||(c?c(C,b):s(C[E])||h(C,E,A)),p(C,N,!0,!0),a&&(m[N]=A)),v&&d==_&&R&&R.name!==_&&(!a&&y?f(P,"name",_):(T=!0,M=function(){return o(R,this)})),d)if(O={values:I(_),keys:g?M:I(x),entries:I(S)},k)for(j in O)(w||T||!(j in P))&&h(P,j,O[j]);else n({target:t,proto:!0,forced:w||T},O);return a&&!k||P[E]===M||h(P,E,M,{name:d}),m[t]=M,O}},66349:(e,t,r)=>{var n=r(54058),o=r(90953),a=r(11477),i=r(65988).f;e.exports=function(e){var t=n.Symbol||(n.Symbol={});o(t,e)||i(t,e,{value:a.f(e)})}},55746:(e,t,r)=>{var n=r(95981);e.exports=!n((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]}))},61333:(e,t,r)=>{var n=r(21899),o=r(10941),a=n.document,i=o(a)&&o(a.createElement);e.exports=function(e){return i?a.createElement(e):{}}},63281:e=>{e.exports={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0}},34342:(e,t,r)=>{var n=r(2861).match(/firefox\/(\d+)/i);e.exports=!!n&&+n[1]},23321:e=>{e.exports="object"==typeof window},81046:(e,t,r)=>{var n=r(2861);e.exports=/MSIE|Trident/.test(n)},4470:(e,t,r)=>{var n=r(2861),o=r(21899);e.exports=/ipad|iphone|ipod/i.test(n)&&void 0!==o.Pebble},22749:(e,t,r)=>{var n=r(2861);e.exports=/(?:ipad|iphone|ipod).*applewebkit/i.test(n)},6049:(e,t,r)=>{var n=r(82532),o=r(21899);e.exports="process"==n(o.process)},58045:(e,t,r)=>{var n=r(2861);e.exports=/web0s(?!.*chrome)/i.test(n)},2861:(e,t,r)=>{var n=r(626);e.exports=n("navigator","userAgent")||""},53385:(e,t,r)=>{var n,o,a=r(21899),i=r(2861),s=a.process,l=a.Deno,u=s&&s.versions||l&&l.version,c=u&&u.v8;c&&(o=(n=c.split("."))[0]>0&&n[0]<4?1:+(n[0]+n[1])),!o&&i&&(!(n=i.match(/Edge\/(\d+)/))||n[1]>=74)&&(n=i.match(/Chrome\/(\d+)/))&&(o=+n[1]),e.exports=o},18938:(e,t,r)=>{var n=r(2861).match(/AppleWebKit\/(\d+)\./);e.exports=!!n&&+n[1]},35703:(e,t,r)=>{var n=r(54058);e.exports=function(e){return n[e+"Prototype"]}},56759:e=>{e.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},18780:(e,t,r)=>{var n=r(95981),o=r(31887);e.exports=!n((function(){var e=Error("a");return!("stack"in e)||(Object.defineProperty(e,"stack",o(1,7)),7!==e.stack)}))},76887:(e,t,r)=>{"use strict";var n=r(21899),o=r(79730),a=r(95329),i=r(57475),s=r(49677).f,l=r(37252),u=r(54058),c=r(86843),p=r(32029),f=r(90953),h=function(e){var t=function(r,n,a){if(this instanceof t){switch(arguments.length){case 0:return new e;case 1:return new e(r);case 2:return new e(r,n)}return new e(r,n,a)}return o(e,this,arguments)};return t.prototype=e.prototype,t};e.exports=function(e,t){var r,o,d,m,g,v,y,b,w=e.target,E=e.global,x=e.stat,_=e.proto,S=E?n:x?n[w]:(n[w]||{}).prototype,A=E?u:u[w]||p(u,w,{})[w],k=A.prototype;for(d in t)r=!l(E?d:w+(x?".":"#")+d,e.forced)&&S&&f(S,d),g=A[d],r&&(v=e.noTargetGet?(b=s(S,d))&&b.value:S[d]),m=r&&v?v:t[d],r&&typeof g==typeof m||(y=e.bind&&r?c(m,n):e.wrap&&r?h(m):_&&i(m)?a(m):m,(e.sham||m&&m.sham||g&&g.sham)&&p(y,"sham",!0),p(A,d,y),_&&(f(u,o=w+"Prototype")||p(u,o,{}),p(u[o],d,m),e.real&&k&&!k[d]&&p(k,d,m)))}},95981:e=>{e.exports=function(e){try{return!!e()}catch(e){return!0}}},45602:(e,t,r)=>{var n=r(95981);e.exports=!n((function(){return Object.isExtensible(Object.preventExtensions({}))}))},79730:(e,t,r)=>{var n=r(18285),o=Function.prototype,a=o.apply,i=o.call;e.exports="object"==typeof Reflect&&Reflect.apply||(n?i.bind(a):function(){return i.apply(a,arguments)})},86843:(e,t,r)=>{var n=r(95329),o=r(24883),a=r(18285),i=n(n.bind);e.exports=function(e,t){return o(e),void 0===t?e:a?i(e,t):function(){return e.apply(t,arguments)}}},18285:(e,t,r)=>{var n=r(95981);e.exports=!n((function(){var e=function(){}.bind();return"function"!=typeof e||e.hasOwnProperty("prototype")}))},98308:(e,t,r)=>{"use strict";var n=r(21899),o=r(95329),a=r(24883),i=r(10941),s=r(90953),l=r(93765),u=r(18285),c=n.Function,p=o([].concat),f=o([].join),h={},d=function(e,t,r){if(!s(h,t)){for(var n=[],o=0;o{var n=r(18285),o=Function.prototype.call;e.exports=n?o.bind(o):function(){return o.apply(o,arguments)}},79417:(e,t,r)=>{var n=r(55746),o=r(90953),a=Function.prototype,i=n&&Object.getOwnPropertyDescriptor,s=o(a,"name"),l=s&&"something"===function(){}.name,u=s&&(!n||n&&i(a,"name").configurable);e.exports={EXISTS:s,PROPER:l,CONFIGURABLE:u}},95329:(e,t,r)=>{var n=r(18285),o=Function.prototype,a=o.bind,i=o.call,s=n&&a.bind(i,i);e.exports=n?function(e){return e&&s(e)}:function(e){return e&&function(){return i.apply(e,arguments)}}},626:(e,t,r)=>{var n=r(54058),o=r(21899),a=r(57475),i=function(e){return a(e)?e:void 0};e.exports=function(e,t){return arguments.length<2?i(n[e])||i(o[e]):n[e]&&n[e][t]||o[e]&&o[e][t]}},22902:(e,t,r)=>{var n=r(9697),o=r(14229),a=r(12077),i=r(99813)("iterator");e.exports=function(e){if(null!=e)return o(e,i)||o(e,"@@iterator")||a[n(e)]}},53476:(e,t,r)=>{var n=r(21899),o=r(78834),a=r(24883),i=r(96059),s=r(69826),l=r(22902),u=n.TypeError;e.exports=function(e,t){var r=arguments.length<2?l(e):t;if(a(r))return i(o(r,e));throw u(s(e)+" is not iterable")}},14229:(e,t,r)=>{var n=r(24883);e.exports=function(e,t){var r=e[t];return null==r?void 0:n(r)}},21899:(e,t,r)=>{var n=function(e){return e&&e.Math==Math&&e};e.exports=n("object"==typeof globalThis&&globalThis)||n("object"==typeof window&&window)||n("object"==typeof self&&self)||n("object"==typeof r.g&&r.g)||function(){return this}()||Function("return this")()},90953:(e,t,r)=>{var n=r(95329),o=r(89678),a=n({}.hasOwnProperty);e.exports=Object.hasOwn||function(e,t){return a(o(e),t)}},27748:e=>{e.exports={}},34845:(e,t,r)=>{var n=r(21899);e.exports=function(e,t){var r=n.console;r&&r.error&&(1==arguments.length?r.error(e):r.error(e,t))}},15463:(e,t,r)=>{var n=r(626);e.exports=n("document","documentElement")},2840:(e,t,r)=>{var n=r(55746),o=r(95981),a=r(61333);e.exports=!n&&!o((function(){return 7!=Object.defineProperty(a("div"),"a",{get:function(){return 7}}).a}))},37026:(e,t,r)=>{var n=r(21899),o=r(95329),a=r(95981),i=r(82532),s=n.Object,l=o("".split);e.exports=a((function(){return!s("z").propertyIsEnumerable(0)}))?function(e){return"String"==i(e)?l(e,""):s(e)}:s},81302:(e,t,r)=>{var n=r(95329),o=r(57475),a=r(63030),i=n(Function.toString);o(a.inspectSource)||(a.inspectSource=function(e){return i(e)}),e.exports=a.inspectSource},53794:(e,t,r)=>{var n=r(10941),o=r(32029);e.exports=function(e,t){n(t)&&"cause"in t&&o(e,"cause",t.cause)}},21647:(e,t,r)=>{var n=r(76887),o=r(95329),a=r(27748),i=r(10941),s=r(90953),l=r(65988).f,u=r(10946),c=r(684),p=r(91584),f=r(99418),h=r(45602),d=!1,m=f("meta"),g=0,v=function(e){l(e,m,{value:{objectID:"O"+g++,weakData:{}}})},y=e.exports={enable:function(){y.enable=function(){},d=!0;var e=u.f,t=o([].splice),r={};r[m]=1,e(r).length&&(u.f=function(r){for(var n=e(r),o=0,a=n.length;o{var n,o,a,i=r(38019),s=r(21899),l=r(95329),u=r(10941),c=r(32029),p=r(90953),f=r(63030),h=r(44262),d=r(27748),m="Object already initialized",g=s.TypeError,v=s.WeakMap;if(i||f.state){var y=f.state||(f.state=new v),b=l(y.get),w=l(y.has),E=l(y.set);n=function(e,t){if(w(y,e))throw new g(m);return t.facade=e,E(y,e,t),t},o=function(e){return b(y,e)||{}},a=function(e){return w(y,e)}}else{var x=h("state");d[x]=!0,n=function(e,t){if(p(e,x))throw new g(m);return t.facade=e,c(e,x,t),t},o=function(e){return p(e,x)?e[x]:{}},a=function(e){return p(e,x)}}e.exports={set:n,get:o,has:a,enforce:function(e){return a(e)?o(e):n(e,{})},getterFor:function(e){return function(t){var r;if(!u(t)||(r=o(t)).type!==e)throw g("Incompatible receiver, "+e+" required");return r}}}},6782:(e,t,r)=>{var n=r(99813),o=r(12077),a=n("iterator"),i=Array.prototype;e.exports=function(e){return void 0!==e&&(o.Array===e||i[a]===e)}},1052:(e,t,r)=>{var n=r(82532);e.exports=Array.isArray||function(e){return"Array"==n(e)}},57475:e=>{e.exports=function(e){return"function"==typeof e}},24284:(e,t,r)=>{var n=r(95329),o=r(95981),a=r(57475),i=r(9697),s=r(626),l=r(81302),u=function(){},c=[],p=s("Reflect","construct"),f=/^\s*(?:class|function)\b/,h=n(f.exec),d=!f.exec(u),m=function(e){if(!a(e))return!1;try{return p(u,c,e),!0}catch(e){return!1}},g=function(e){if(!a(e))return!1;switch(i(e)){case"AsyncFunction":case"GeneratorFunction":case"AsyncGeneratorFunction":return!1}try{return d||!!h(f,l(e))}catch(e){return!0}};g.sham=!0,e.exports=!p||o((function(){var e;return m(m.call)||!m(Object)||!m((function(){e=!0}))||e}))?g:m},37252:(e,t,r)=>{var n=r(95981),o=r(57475),a=/#|\.prototype\./,i=function(e,t){var r=l[s(e)];return r==c||r!=u&&(o(t)?n(t):!!t)},s=i.normalize=function(e){return String(e).replace(a,".").toLowerCase()},l=i.data={},u=i.NATIVE="N",c=i.POLYFILL="P";e.exports=i},10941:(e,t,r)=>{var n=r(57475);e.exports=function(e){return"object"==typeof e?null!==e:n(e)}},82529:e=>{e.exports=!0},60685:(e,t,r)=>{var n=r(10941),o=r(82532),a=r(99813)("match");e.exports=function(e){var t;return n(e)&&(void 0!==(t=e[a])?!!t:"RegExp"==o(e))}},56664:(e,t,r)=>{var n=r(21899),o=r(626),a=r(57475),i=r(7046),s=r(32302),l=n.Object;e.exports=s?function(e){return"symbol"==typeof e}:function(e){var t=o("Symbol");return a(t)&&i(t.prototype,l(e))}},93091:(e,t,r)=>{var n=r(21899),o=r(86843),a=r(78834),i=r(96059),s=r(69826),l=r(6782),u=r(10623),c=r(7046),p=r(53476),f=r(22902),h=r(7609),d=n.TypeError,m=function(e,t){this.stopped=e,this.result=t},g=m.prototype;e.exports=function(e,t,r){var n,v,y,b,w,E,x,_=r&&r.that,S=!(!r||!r.AS_ENTRIES),A=!(!r||!r.IS_ITERATOR),k=!(!r||!r.INTERRUPTED),C=o(t,_),O=function(e){return n&&h(n,"normal",e),new m(!0,e)},j=function(e){return S?(i(e),k?C(e[0],e[1],O):C(e[0],e[1])):k?C(e,O):C(e)};if(A)n=e;else{if(!(v=f(e)))throw d(s(e)+" is not iterable");if(l(v)){for(y=0,b=u(e);b>y;y++)if((w=j(e[y]))&&c(g,w))return w;return new m(!1)}n=p(e,v)}for(E=n.next;!(x=a(E,n)).done;){try{w=j(x.value)}catch(e){h(n,"throw",e)}if("object"==typeof w&&w&&c(g,w))return w}return new m(!1)}},7609:(e,t,r)=>{var n=r(78834),o=r(96059),a=r(14229);e.exports=function(e,t,r){var i,s;o(e);try{if(!(i=a(e,"return"))){if("throw"===t)throw r;return r}i=n(i,e)}catch(e){s=!0,i=e}if("throw"===t)throw r;if(s)throw i;return o(i),r}},35143:(e,t,r)=>{"use strict";var n,o,a,i=r(95981),s=r(57475),l=r(29290),u=r(249),c=r(99754),p=r(99813),f=r(82529),h=p("iterator"),d=!1;[].keys&&("next"in(a=[].keys())?(o=u(u(a)))!==Object.prototype&&(n=o):d=!0),null==n||i((function(){var e={};return n[h].call(e)!==e}))?n={}:f&&(n=l(n)),s(n[h])||c(n,h,(function(){return this})),e.exports={IteratorPrototype:n,BUGGY_SAFARI_ITERATORS:d}},12077:e=>{e.exports={}},10623:(e,t,r)=>{var n=r(43057);e.exports=function(e){return n(e.length)}},66132:(e,t,r)=>{var n,o,a,i,s,l,u,c,p=r(21899),f=r(86843),h=r(49677).f,d=r(42941).set,m=r(22749),g=r(4470),v=r(58045),y=r(6049),b=p.MutationObserver||p.WebKitMutationObserver,w=p.document,E=p.process,x=p.Promise,_=h(p,"queueMicrotask"),S=_&&_.value;S||(n=function(){var e,t;for(y&&(e=E.domain)&&e.exit();o;){t=o.fn,o=o.next;try{t()}catch(e){throw o?i():a=void 0,e}}a=void 0,e&&e.enter()},m||y||v||!b||!w?!g&&x&&x.resolve?((u=x.resolve(void 0)).constructor=x,c=f(u.then,u),i=function(){c(n)}):y?i=function(){E.nextTick(n)}:(d=f(d,p),i=function(){d(n)}):(s=!0,l=w.createTextNode(""),new b(n).observe(l,{characterData:!0}),i=function(){l.data=s=!s})),e.exports=S||function(e){var t={fn:e,next:void 0};a&&(a.next=t),o||(o=t,i()),a=t}},19297:(e,t,r)=>{var n=r(21899);e.exports=n.Promise},72497:(e,t,r)=>{var n=r(53385),o=r(95981);e.exports=!!Object.getOwnPropertySymbols&&!o((function(){var e=Symbol();return!String(e)||!(Object(e)instanceof Symbol)||!Symbol.sham&&n&&n<41}))},28468:(e,t,r)=>{var n=r(95981),o=r(99813),a=r(82529),i=o("iterator");e.exports=!n((function(){var e=new URL("b?a=1&b=2&c=3","http://a"),t=e.searchParams,r="";return e.pathname="c%20d",t.forEach((function(e,n){t.delete("b"),r+=n+e})),a&&!e.toJSON||!t.sort||"http://a/c%20d?a=1&c=3"!==e.href||"3"!==t.get("c")||"a=1"!==String(new URLSearchParams("?a=1"))||!t[i]||"a"!==new URL("https://a@b").username||"b"!==new URLSearchParams(new URLSearchParams("a=b")).get("a")||"xn--e1aybc"!==new URL("http://тест").host||"#%D0%B1"!==new URL("http://a#б").hash||"a1c3"!==r||"x"!==new URL("http://x",void 0).host}))},38019:(e,t,r)=>{var n=r(21899),o=r(57475),a=r(81302),i=n.WeakMap;e.exports=o(i)&&/native code/.test(a(i))},69520:(e,t,r)=>{"use strict";var n=r(24883),o=function(e){var t,r;this.promise=new e((function(e,n){if(void 0!==t||void 0!==r)throw TypeError("Bad Promise constructor");t=e,r=n})),this.resolve=n(t),this.reject=n(r)};e.exports.f=function(e){return new o(e)}},14649:(e,t,r)=>{var n=r(85803);e.exports=function(e,t){return void 0===e?arguments.length<2?"":t:n(e)}},70344:(e,t,r)=>{var n=r(21899),o=r(60685),a=n.TypeError;e.exports=function(e){if(o(e))throw a("The method doesn't accept regular expressions");return e}},24420:(e,t,r)=>{"use strict";var n=r(55746),o=r(95329),a=r(78834),i=r(95981),s=r(14771),l=r(87857),u=r(36760),c=r(89678),p=r(37026),f=Object.assign,h=Object.defineProperty,d=o([].concat);e.exports=!f||i((function(){if(n&&1!==f({b:1},f(h({},"a",{enumerable:!0,get:function(){h(this,"b",{value:3,enumerable:!1})}}),{b:2})).b)return!0;var e={},t={},r=Symbol(),o="abcdefghijklmnopqrst";return e[r]=7,o.split("").forEach((function(e){t[e]=e})),7!=f({},e)[r]||s(f({},t)).join("")!=o}))?function(e,t){for(var r=c(e),o=arguments.length,i=1,f=l.f,h=u.f;o>i;)for(var m,g=p(arguments[i++]),v=f?d(s(g),f(g)):s(g),y=v.length,b=0;y>b;)m=v[b++],n&&!a(h,g,m)||(r[m]=g[m]);return r}:f},29290:(e,t,r)=>{var n,o=r(96059),a=r(59938),i=r(56759),s=r(27748),l=r(15463),u=r(61333),c=r(44262),p=c("IE_PROTO"),f=function(){},h=function(e){return"