Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The wasm_bindgen support of fuel-asm and fuel-types #499

Merged
merged 8 commits into from
Jul 24, 2023
Merged
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
57 changes: 55 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
- command: check
args: --all-targets -p fuel-crypto
- command: check
args: --all-targets -p fuel-merkle
args: --all-targets -p fuel-merkle
- command: check
args: --all-targets -p fuel-storage
- command: check
Expand All @@ -51,6 +51,10 @@ jobs:
args: --target thumbv6m-none-eabi -p fuel-asm -p fuel-storage -p fuel-merkle --no-default-features
- command: check
args: --target wasm32-unknown-unknown -p fuel-crypto --no-default-features
- command: rustc
args: --target wasm32-unknown-unknown -p fuel-types --features typescript --crate-type=cdylib
- command: rustc
args: --target wasm32-unknown-unknown -p fuel-asm --features typescript --crate-type=cdylib
- command: make
args: check
- command: test
Expand Down Expand Up @@ -156,7 +160,7 @@ jobs:
uses: katyo/publish-crates@v2
with:
registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }}

cargo_audit:
runs-on: ubuntu-latest
continue-on-error: true
Expand All @@ -165,3 +169,52 @@ jobs:
- uses: rustsec/audit-check@v1.4.1
with:
token: ${{ secrets.GITHUB_TOKEN }}

publish_wasm_packages:
needs:
- publish
if: github.event_name == 'release' && github.event.action == 'published'
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.ref }}

- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.RUST_VERSION }}
targets: "wasm32-unknown-unknown"

- name: Installing required crates
run: cargo install wasm-bindgen-cli wasm-opt

- name: Setup PNPM
uses: pnpm/action-setup@v2
with:
version: 8.6.9

- name: Setup Node
uses: actions/setup-node@v3
with:
cache: "pnpm"
node-version: 18.14.1
node-version-file: ".npm/package.json"
cache-dependency-path: ".npm/pnpm-lock.yaml"
registry-url: 'https://registry.npmjs.org'

- name: Build and Test packages
run: |
pnpm -C .npm install
pnpm -C .npm pack:all

- name: Ensure NPM access
run: npm whoami
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Publish
run: pnpm -C .npm publish -r --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk

.vscode/
.vscode/
.history
6 changes: 6 additions & 0 deletions .npm/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.turbo
node_modules

packages/*/*
!packages/*/index.test.cjs
!packages/*/index.test.mjs
59 changes: 59 additions & 0 deletions .npm/.scripts/prepare-wasm-packages.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/usr/bin/env bash

ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )"
NPM_DIR=${ROOT_DIR}/.npm
PKGS_DIR=${NPM_DIR}/packages


write_template ()
{
NAME_DASHED=$1
NAME_UNDERSCORED=$2
TEMPLATE=$3

PKG_TEMPLATE_DIR=${NPM_DIR}/.scripts/template
PKG_DIR=${PKGS_DIR}/${NAME_DASHED}

PKG_NAME=$(echo "${NAME_DASHED}" | sed -e 's/fuel-//g')
PKG_VERSION=$(cat ${ROOT_DIR}/Cargo.toml | sed -nr 's/^version = "([^"]+)"/\1/p')

echo "$(
cat ${PKG_TEMPLATE_DIR}/${TEMPLATE} \
| sed -e "s/{{NAME_DASHED}}/${NAME_DASHED}/g" \
| sed -e "s/{{NAME_UNDERSCORED}}/${NAME_UNDERSCORED}/g" \
| sed -e "s/{{PKG_NAME}}/${PKG_NAME}/g" \
| sed -e "s/{{PKG_VERSION}}/${PKG_VERSION}/g"
)" > ${PKG_DIR}/${TEMPLATE}

}


build_wasm_npm_pkg_for ()
{
NAME_DASHED=$1
NAME_UNDERSCORED=$(echo "${NAME_DASHED}" | sed -e 's/-/_/g')

PKG_DIR=${PKGS_DIR}/${NAME_DASHED}

rm -rf ${PKG_DIR}/{src,dist}

cd ${ROOT_DIR}
cargo rustc -p ${NAME_DASHED} --target wasm32-unknown-unknown --features typescript --crate-type=cdylib --release
wasm-bindgen --typescript --target web ./target/wasm32-unknown-unknown/release/${NAME_UNDERSCORED}.wasm --out-dir ${PKG_DIR}/src
wasm-opt ${PKG_DIR}/src/${NAME_UNDERSCORED}_bg.wasm -o ${PKG_DIR}/src/${NAME_UNDERSCORED}_bg.wasm -Oz
cd ~-

write_template ${NAME_DASHED} ${NAME_UNDERSCORED} README.md
write_template ${NAME_DASHED} ${NAME_UNDERSCORED} package.json
write_template ${NAME_DASHED} ${NAME_UNDERSCORED} rollup.config.mjs
write_template ${NAME_DASHED} ${NAME_UNDERSCORED} src/index.js

# commenting out all `new URL()` and `fetch()` calls for great compatibility with JS bundlers
sed -i.bkp -r 's;(input = new URL.+);//\1;g' ${PKG_DIR}/src/${NAME_UNDERSCORED}.js
sed -i.bkp -r 's;(input = fetch.+);//\1;g' ${PKG_DIR}/src/${NAME_UNDERSCORED}.js
rm ${PKG_DIR}/src/${NAME_UNDERSCORED}.js.bkp
}


build_wasm_npm_pkg_for "fuel-asm"
build_wasm_npm_pkg_for "fuel-types"
6 changes: 6 additions & 0 deletions .npm/.scripts/template/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

# @fuels/vm-{{NAME_DASHED}}

WASM version of `{{NAME_DASHED}}` Rust crate:
- https://crates.io/crates/{{NAME_DASHED}}
- https://github.com/FuelLabs/fuel-vm/tree/master/{{NAME_DASHED}}
17 changes: 17 additions & 0 deletions .npm/.scripts/template/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "@fuels/vm-{{PKG_NAME}}",
"version": "{{PKG_VERSION}}",
"description": "WASM version of `{{NAME_DASHED}}` Rust crate",
"author": "Fuel Labs <contact@fuel.sh> (https://fuel.network/)",
"main": "dist/node/index.cjs",
"types": "dist/node/index.d.ts",
"browser": "dist/web/index.mjs",
"files": [
"dist"
],
"scripts": {
"build": "rollup -c rollup.config.mjs",
"test": "mocha index.test.cjs index.test.mjs"
},
"license": "Apache-2.0"
}
25 changes: 25 additions & 0 deletions .npm/.scripts/template/rollup.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { wasm } from '@rollup/plugin-wasm'
import dts from 'rollup-plugin-dts'

export default [
{
plugins: [wasm({ targetEnv: 'auto-inline' })],
input: 'src/index.js',
output: [
{ file: 'dist/node/index.cjs', format: 'cjs' },
]
}, {
plugins: [wasm({ targetEnv: 'auto-inline' })],
input: 'src/index.js',
output: [
{ file: 'dist/web/index.mjs', format: 'es' },
]
}, {
plugins: [dts()],
input: 'src/{{NAME_UNDERSCORED}}.d.ts',
output: [
{ file: 'dist/web/index.d.ts', format: 'es' },
{ file: 'dist/node/index.d.ts', format: 'es' }
],
}
]
6 changes: 6 additions & 0 deletions .npm/.scripts/template/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import init from './{{NAME_UNDERSCORED}}.js'
import wasm from './{{NAME_UNDERSCORED}}_bg.wasm'

init(wasm())

export * from './{{NAME_UNDERSCORED}}.js'
73 changes: 73 additions & 0 deletions .npm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# WASM version of Rust Crates

You'll find all the routines to publish selected Rust crates as NPM packages here.

# Testing Locally

To get started and test things locally, you'll need to:

```shell
# install the required crates
cargo install wasm-bindgen-cli wasm-opt

# ensure you have the needed target
rustup target add wasm32-unknown-unknown

# then install deps, generate wasm files, build and test the package
pnpm install
pnpm run wasm
pnpm run build
pnpm run test
```

# Output

The above commands will give ready-to-publish packages inside `.npm/packages`.

```shell
.npm
├── .scripts
│   └── prepare-wasm-packages
├── packages
│   ├── fuel-asm # <—— package #1
│   └── fuel-types # <—— package #2
└── package.json
```

# How does it work?

For an in-depth understanding, check:
- `.npm/package.json`
- `.npm/.scripts/prepare-wasm-packages.sh`
- `.github/workflows/ci.yml`
- _Look for the `publish_wasm_packages` job_

# Using local sym-linked packages

First, we need to link our `packages` package globally in our local `global pnpm store`:

```sh
cd packages/fuel-asm
pnpm link -g
```

Let's check it out:

```sh
pnpm list -g
```

You should see something like:

```
@fuels/vm-asm link:<...>/fuel-vm/.npm/packages/fuel-asm
```

Cool, now on the root directory of your desired project `my-local-project`:

```sh
cd my-local-project
pnpm link -g @fuels/vm-asm
```

Done — you're using the local version of `@fuels/vm-asm`.
28 changes: 28 additions & 0 deletions .npm/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"private": true,
"name": "@fuels/wasm-packages",
"version": "0.0.0",
"description": "Workspace for building WASM versions of Rust crates",
"author": "Fuel Labs <contact@fuel.sh> (https://fuel.network/)",
"engines": {
"node": ">= 18.14.1",
"pnpm": ">= 8.1.1"
},
"packageManager": "pnpm@8.1.1",
"scripts": {
"wasm": ".scripts/prepare-wasm-packages.sh",
"build": "turbo run build",
"test": "turbo run test",
"pack:all": "pnpm run-s wasm build test"
},
"license": "Apache-2.0",
"devDependencies": {
"@rollup/plugin-wasm": "^6.1.3",
"chai": "^4.3.7",
"mocha": "^10.2.0",
"npm-run-all": "^4.1.5",
"rollup": "^3.26.2",
"rollup-plugin-dts": "^5.3.0",
"turbo": "^1.10.9"
}
}
33 changes: 33 additions & 0 deletions .npm/packages/fuel-asm/index.test.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const { expect } = require('chai')
const asm = require('.')

describe('fuel-asm [cjs]', () => {

it('should compose simple script', () => {

const gtf = asm.gtf(0x10, 0x00, asm.GTFArgs.ScriptData)
const addi = asm.addi(0x11, 0x10, 0x20)
const lw = asm.lw(0x12, 0x11, 0x0)
const addi2 = asm.addi(0x13, 0x11, 0x8)
const tr = asm.tr(0x10, 0x12, 0x13)
const ret = asm.ret(0x1)

const script = Uint8Array.from([
...gtf.to_bytes(),
...addi.to_bytes(),
...lw.to_bytes(),
...addi2.to_bytes(),
...tr.to_bytes(),
...ret.to_bytes(),
])

const expected = new Uint8Array([
97, 64, 0, 12, 80, 69, 0, 32,
93, 73, 16, 0, 80, 77, 16, 8,
60, 65, 36, 192, 36, 4, 0, 0
])

expect(script).to.deep.equal(expected)
})

})
33 changes: 33 additions & 0 deletions .npm/packages/fuel-asm/index.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { expect } from 'chai'
import * as asm from './dist/web/index.mjs'

describe('fuel-asm [esm]', () => {

it('should compose simple script', () => {

const gtf = asm.gtf(0x10, 0x00, asm.GTFArgs.ScriptData)
const addi = asm.addi(0x11, 0x10, 0x20)
const lw = asm.lw(0x12, 0x11, 0x0)
const addi2 = asm.addi(0x13, 0x11, 0x8)
const tr = asm.tr(0x10, 0x12, 0x13)
const ret = asm.ret(0x1)

const script = Uint8Array.from([
...gtf.to_bytes(),
...addi.to_bytes(),
...lw.to_bytes(),
...addi2.to_bytes(),
...tr.to_bytes(),
...ret.to_bytes(),
])

const expected = new Uint8Array([
97, 64, 0, 12, 80, 69, 0, 32,
93, 73, 16, 0, 80, 77, 16, 8,
60, 65, 36, 192, 36, 4, 0, 0
])

expect(script).to.deep.equal(expected)
})

})
Loading