Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 7 additions & 10 deletions .github/workflows/publish-to-npmjs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,17 @@ jobs:
attestations: write
id-token: write
steps:
- uses: actions/checkout@v4
- uses: proudust/gh-describe@70f72d4f6304ea053cf5a3d71c36211d5acc0c73
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: proudust/gh-describe@d7279b40f5aa4868ba0be464c4789cbee41fb279 # v2.1.1
id: ghd
- uses: actions/setup-java@v4
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: 'temurin'
java-version: '17'
cache: 'sbt'
- uses: sbt/setup-sbt@v1
- run: sbt -Dproject.version=${{ steps.ghd.outputs.describe }} --batch ';lang-tests/test;lang-tests-js/test;repl/test;langJS/fullOptJS;replJS/fullOptJS'
- uses: actions/setup-node@v4
- uses: sbt/setup-sbt@6bec67c98f542b9e17369bfca0ec822ac1363194 # v1.1.19
- run: sbt -Dproject.version=${{ steps.ghd.outputs.describe }} --batch ';lang-tests/test;lang-tests-js/test;repl/test;ride-js-bundle/fullLinkJS'
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
registry-url: 'https://registry.npmjs.org'
node-version: '>=24.7.0' # Trusted publishing requires npm CLI version 11.5.1 or later.
Expand All @@ -52,10 +52,7 @@ jobs:
echo "TAG=latest" >> $GITHUB_ENV
- id: publish
run: |
cd lang/js
npm version $VERSION --no-git-tag-version
npm publish --provenance --access public --tag $TAG
cd ../../repl/js
cd ride-js-bundle
npm version $VERSION --no-git-tag-version
npm publish --provenance --access public --tag $TAG
echo "url=https://www.npmjs.com/package/@waves/ride-lang/v/$VERSION" >> "$GITHUB_OUTPUT"
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,4 @@ package
!ride-runner/src/package
native

lang/js/dist
repl/js/dist
ride-js-bundle/dist
10 changes: 8 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,15 @@ lazy val `lang-tests` = project
.in(file("lang/tests"))
.dependsOn(`lang-testkit`)

lazy val `ride-js-bundle` = project
.in(file("ride-js-bundle"))
.enablePlugins(ScalaJSPlugin)
.dependsOn(`lang-js`, `repl-js`)

lazy val `lang-tests-js` = project
.in(file("lang/tests-js"))
.enablePlugins(ScalaJSPlugin)
.dependsOn(`lang-js`)
.dependsOn(`ride-js-bundle`)
.settings(
libraryDependencies += Dependencies.scalaJsTest.value,
testFrameworks += new TestFramework("utest.runner.Framework")
Expand Down Expand Up @@ -158,6 +163,7 @@ lazy val `waves-node` = (project in file("."))
`lang-testkit`,
`repl-js`,
`repl-jvm`,
`ride-js-bundle`,
node,
`node-it`,
`node-testkit`,
Expand Down Expand Up @@ -259,7 +265,7 @@ checkPRRaw := Def
test.all(
ScopeFilter(inProjects(`lang-tests`, `repl-jvm`, `lang-tests-js`, `grpc-server`, `node-tests`, `ride-runner`), inConfigurations(Test))
),
fullOptJS.all(ScopeFilter(inProjects(`lang-js`, `repl-js`), inConfigurations(Compile))),
fullLinkJS.all(ScopeFilter(inProjects(`ride-js-bundle`), inConfigurations(Compile))),
assembly.all(ScopeFilter(inProjects(node, `lang-jvm`))),
buildTarballsForDocker
)
Expand Down
5 changes: 0 additions & 5 deletions lang/js/build.sbt

This file was deleted.

14 changes: 0 additions & 14 deletions lang/js/package.json

This file was deleted.

100 changes: 85 additions & 15 deletions lang/js/src/main/scala/com/wavesplatform/lang/impl/Global.scala
Original file line number Diff line number Diff line change
@@ -1,21 +1,91 @@
package com.wavesplatform.lang.impl

import com.wavesplatform.lang.v1.evaluator.ctx.impl.crypto.RSA
import com.wavesplatform.lang.v1.evaluator.ctx.impl.crypto.RSA.DigestAlgorithm

import scala.scalajs.js
import scala.scalajs.js.annotation.JSGlobalScope
import scala.scalajs.js.typedarray.ArrayBuffer
import scala.scalajs.js.{Object, Promise, native}

@native
@JSGlobalScope
object Global extends Object {
def curve25519verify(message: ArrayBuffer, sig: ArrayBuffer, pub: ArrayBuffer): Boolean = native
def rsaVerify(alg: DigestAlgorithm, message: ArrayBuffer, sig: ArrayBuffer, pub: ArrayBuffer): Boolean = native
def keccak256(message: ArrayBuffer): ArrayBuffer = native
def blake2b256(message: ArrayBuffer): ArrayBuffer = native
def sha256(message: ArrayBuffer): ArrayBuffer = native
def merkleVerify(root: ArrayBuffer, proof: ArrayBuffer, data: ArrayBuffer): Boolean = native

def httpGet(params: js.Dynamic): Promise[js.Dynamic] = native
import scala.scalajs.js.annotation.JSImport
import scala.scalajs.js.typedarray.{ArrayBuffer, Uint8Array}
import scala.scalajs.js.{Promise, UndefOr}

@js.native
@JSImport("@waves/ts-lib-crypto", JSImport.Namespace)
private object TsLibCrypto extends js.Object {
def verifySignature(publicKey: Uint8Array, message: Uint8Array, signature: Uint8Array): Boolean = js.native
def rsaVerify(publicKey: Uint8Array, message: Uint8Array, signature: Uint8Array, digest: UndefOr[String]): Boolean = js.native
def keccak(bytes: Uint8Array): Uint8Array = js.native
def blake2b(bytes: Uint8Array): Uint8Array = js.native
def sha256(bytes: Uint8Array): String = js.native
def merkleVerify(rootHash: Uint8Array, merkleProof: Uint8Array, leafData: Uint8Array): Boolean = js.native
}

@js.native
@JSImport("axios", JSImport.Namespace)
private object Axios extends js.Object {
def get(url: String, config: js.Dynamic): Promise[js.Dynamic] = js.native
}

object Global {
private def toUint8Array(buf: ArrayBuffer): Uint8Array = new Uint8Array(buf)

// ts-lib-crypto sha256 returns a hex string; decode it to ArrayBuffer
private def hexToArrayBuffer(hex: String): ArrayBuffer = {
val len = hex.length / 2
val result = new Uint8Array(len)
var i = 0
while (i < len) {
result(i) = (Integer.parseInt(hex.substring(i * 2, i * 2 + 2), 16) & 0xff).toByte
i += 1
}
result.buffer
}

// Map DigestAlgorithm ADT to the string (or undefined) ts-lib-crypto expects
private def digestToString(alg: DigestAlgorithm): UndefOr[String] = alg match {
case RSA.NONE => js.undefined
case RSA.MD5 => "MD5"
case RSA.SHA1 => "SHA1"
case RSA.SHA224 => "SHA224"
case RSA.SHA256 => "SHA256"
case RSA.SHA384 => "SHA384"
case RSA.SHA512 => "SHA512"
case RSA.SHA3224 => "SHA3-224"
case RSA.SHA3256 => "SHA3-256"
case RSA.SHA3384 => "SHA3-384"
case RSA.SHA3512 => "SHA3-512"
}

// Public API — identical signatures to the previous @JSGlobalScope object

def curve25519verify(message: ArrayBuffer, sig: ArrayBuffer, pub: ArrayBuffer): Boolean =
TsLibCrypto.verifySignature(toUint8Array(pub), toUint8Array(message), toUint8Array(sig))

def rsaVerify(alg: DigestAlgorithm, message: ArrayBuffer, sig: ArrayBuffer, pub: ArrayBuffer): Boolean =
TsLibCrypto.rsaVerify(toUint8Array(pub), toUint8Array(message), toUint8Array(sig), digestToString(alg))

def keccak256(message: ArrayBuffer): ArrayBuffer = TsLibCrypto.keccak(toUint8Array(message)).buffer
def blake2b256(message: ArrayBuffer): ArrayBuffer = TsLibCrypto.blake2b(toUint8Array(message)).buffer
def sha256(message: ArrayBuffer): ArrayBuffer = hexToArrayBuffer(TsLibCrypto.sha256(toUint8Array(message)))

def merkleVerify(root: ArrayBuffer, proof: ArrayBuffer, data: ArrayBuffer): Boolean =
TsLibCrypto.merkleVerify(toUint8Array(root), toUint8Array(proof), toUint8Array(data))

def httpGet(params: js.Dynamic): Promise[js.Dynamic] = {
val url = params.url.asInstanceOf[UndefOr[String]]
if (url.isEmpty) {
js.Promise.resolve[js.Dynamic](
js.Dynamic.literal("url" -> params.url, "status" -> 404, "body" -> "url is undefined")
)
} else {
Axios
.get(url.get, js.Dynamic.literal(validateStatus = ((_: Int) => true): js.Function1[Int, Boolean]))
.`then`[js.Dynamic] { resp =>
val status = resp.status.asInstanceOf[Int]
val bodyStr =
if (js.typeOf(resp.data) != "string") js.JSON.stringify(resp.data)
else resp.data.asInstanceOf[String]
js.Dynamic.literal("url" -> params.url, "status" -> status, "body" -> bodyStr)
}
}
}
}
5 changes: 0 additions & 5 deletions repl/js/build.sbt

This file was deleted.

14 changes: 0 additions & 14 deletions repl/js/package.json

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package com.wavesplatform.lang.v1.repl.impl

import scala.scalajs.js
import scala.scalajs.js.annotation.JSGlobalScope
import scala.scalajs.js.{Object, Promise, native}
import scala.scalajs.js.Promise

@native
@JSGlobalScope
object Global extends Object {
def httpGet(params: js.Dynamic): Promise[js.Dynamic] = native
object Global {
def httpGet(params: js.Dynamic): Promise[js.Dynamic] =
com.wavesplatform.lang.impl.Global.httpGet(params)
}
9 changes: 9 additions & 0 deletions ride-js-bundle/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import org.scalajs.linker.interface.ModuleSplitStyle

scalaJSLinkerConfig ~= {
_.withModuleKind(ModuleKind.ESModule)
.withModuleSplitStyle(ModuleSplitStyle.SmallestModules)
}

Compile / fullLinkJS / scalaJSLinkerOutputDirectory := baseDirectory.value / "dist"
Compile / fastLinkJS / scalaJSLinkerOutputDirectory := baseDirectory.value / "dist"
Loading
Loading