Skip to content

Commit 6ffa2de

Browse files
committed
chore: bundle wasm-sdk
1 parent f11a0eb commit 6ffa2de

26 files changed

+178
-40
lines changed

.pnp.cjs

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/js-evo-sdk/package.json

Whitespace-only changes.

packages/scripts/build-wasm.sh

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -96,17 +96,18 @@ cd "$PACKAGE_DIR"
9696

9797
echo "Building $PACKAGE_NAME..."
9898

99-
# Create pkg directory if it doesn't exist
99+
# Create a new clean directory package directory
100+
rm -rf pkg
100101
mkdir -p pkg
101102

102103
if [ "$USE_WASM_PACK" = true ]; then
103104
# Build using wasm-pack
104105
echo "Building with wasm-pack..."
105-
106+
106107
# Disable LTO for wasm-pack builds to avoid conflicts
107108
export CARGO_PROFILE_RELEASE_LTO=false
108109
export RUSTFLAGS="-C lto=off"
109-
110+
110111
# Add features if specified
111112
FEATURES_ARG=""
112113
if [ -n "${CARGO_BUILD_FEATURES:-}" ]; then
@@ -117,19 +118,19 @@ if [ "$USE_WASM_PACK" = true ]; then
117118
# Explicitly pass default features to ensure they're used
118119
FEATURES_ARG="--features default"
119120
fi
120-
121+
121122
echo "Running: wasm-pack build --target $TARGET_TYPE --release --no-opt $FEATURES_ARG"
122123
wasm-pack build --target "$TARGET_TYPE" --release --no-opt $FEATURES_ARG
123124
else
124125
# Build using cargo directly
125126
echo "Building with cargo..."
126-
127+
127128
# Add features if specified
128129
FEATURES_ARG=""
129130
if [ -n "${CARGO_BUILD_FEATURES:-}" ]; then
130131
FEATURES_ARG="--features $CARGO_BUILD_FEATURES"
131132
fi
132-
133+
133134
cargo build --target wasm32-unknown-unknown --release $FEATURES_ARG \
134135
--config 'profile.release.panic="abort"' \
135136
--config 'profile.release.strip=true' \
@@ -138,22 +139,22 @@ else
138139
--config 'profile.release.lto=true' \
139140
--config 'profile.release.opt-level="z"' \
140141
--config 'profile.release.codegen-units=1'
141-
142+
142143
# Run wasm-snip if available
143144
if command -v wasm-snip &> /dev/null; then
144145
wasm-snip "../../target/wasm32-unknown-unknown/release/${PACKAGE_NAME//-/_}.wasm" \
145146
-o "../../target/wasm32-unknown-unknown/release/${PACKAGE_NAME//-/_}.wasm" \
146147
--snip-rust-fmt-code \
147148
--snip-rust-panicking-code
148149
fi
149-
150+
150151
# Run wasm-bindgen
151152
echo "Running wasm-bindgen..."
152153
if ! command -v wasm-bindgen &> /dev/null; then
153154
echo "Error: 'wasm-bindgen' not found. Install via 'cargo install wasm-bindgen-cli'." >&2
154155
exit 1
155156
fi
156-
157+
157158
wasm-bindgen \
158159
--typescript \
159160
--out-dir=pkg \
@@ -165,13 +166,13 @@ fi
165166
# Optimize the WASM file
166167
if [ "$OPT_LEVEL" != "none" ] && command -v wasm-opt &> /dev/null; then
167168
echo "Optimizing wasm using Binaryen (level: $OPT_LEVEL)..."
168-
169+
169170
WASM_PATH="pkg/$WASM_FILE"
170-
171+
171172
if [ "$OPT_LEVEL" = "full" ]; then
172173
# Check wasm-opt version to determine available options
173174
WASM_OPT_VERSION=$(wasm-opt --version 2>/dev/null || echo "")
174-
175+
175176
# Core optimization flags that should work with most versions
176177
CORE_FLAGS=(
177178
--strip-producers
@@ -191,7 +192,7 @@ if [ "$OPT_LEVEL" != "none" ] && command -v wasm-opt &> /dev/null; then
191192
-Oz
192193
-Oz
193194
)
194-
195+
195196
# Additional flags to test for compatibility
196197
OPTIONAL_FLAGS=(
197198
"--code-folding"
@@ -209,7 +210,7 @@ if [ "$OPT_LEVEL" != "none" ] && command -v wasm-opt &> /dev/null; then
209210
"--generate-global-effects"
210211
"--abstract-type-refining"
211212
)
212-
213+
213214
# Test which optional flags are supported
214215
SUPPORTED_FLAGS=()
215216
for flag in "${OPTIONAL_FLAGS[@]}"; do
@@ -219,15 +220,15 @@ if [ "$OPT_LEVEL" != "none" ] && command -v wasm-opt &> /dev/null; then
219220
echo "Note: $flag not supported by this wasm-opt version, skipping..."
220221
fi
221222
done
222-
223+
223224
# Run optimization with core flags and any supported optional flags
224225
wasm-opt \
225226
"${CORE_FLAGS[@]}" \
226227
"${SUPPORTED_FLAGS[@]}" \
227228
"$WASM_PATH" \
228229
-o \
229230
"$WASM_PATH"
230-
231+
231232
# Create optimized version for wasm-sdk
232233
if [ "$PACKAGE_NAME" = "wasm-sdk" ]; then
233234
cp "$WASM_PATH" "pkg/optimized.wasm"

packages/wasm-sdk/.gitignore

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,2 @@
1-
playwright-report/
2-
test-results/
3-
test/test-report.html
4-
5-
# Environment variables with sensitive test data
6-
test/ui-automation/.env
1+
dist
2+
pkg

packages/wasm-sdk/README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
6161

6262
# Build the WASM module
6363
./build.sh
64+
65+
# Build the TypeScript EvoSDK facade and bundle with WASM into dist/
66+
yarn workspace @dashevo/evo-sdk run build:evosdk
6467
```
6568

6669
### Documentation
@@ -83,6 +86,10 @@ The CI will fail if documentation is out of sync with the code.
8386
2. Implement the corresponding method in the Rust code
8487
3. Regenerate documentation: `python3 generate_docs.py`
8588
4. Test your changes using the web interface
89+
5. If you modified the TS facade (js/src), rebuild the bundle:
90+
```bash
91+
yarn workspace @dashevo/evo-sdk run build:evosdk
92+
```
8693

8794
### CI/CD
8895

@@ -142,4 +149,4 @@ The web interface (`index.html`) provides comprehensive testing capabilities:
142149

143150
## License
144151

145-
See the main platform repository for license information.
152+
See the main platform repository for license information.

packages/wasm-sdk/package.json

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,33 @@
11
{
2-
"name": "@dashevo/evo-sdk",
3-
"version": "0.0.0",
2+
"name": "@dashevo/wasm-sdk",
3+
"version": "2.0.0",
4+
"type": "module",
5+
"main": "./dist/sdk.js",
6+
"types": "./dist/sdk.d.ts",
7+
"exports": {
8+
".": {
9+
"types": "./dist/sdk.d.ts",
10+
"import": "./dist/sdk.js"
11+
},
12+
"./raw": {
13+
"types": "./dist/raw/wasm_sdk.d.ts",
14+
"import": "./dist/raw/wasm_sdk.js"
15+
},
16+
"./raw/*": "./dist/raw/*"
17+
},
18+
"files": [
19+
"dist/**",
20+
"README.md"
21+
],
422
"scripts": {
5-
"build": "./build.sh",
6-
"build:release": "./build-optimized.sh",
7-
"test": "echo 'Tests run from web interface at index.html'",
8-
"prepublishOnly": "echo 'Publishing handled by pkg/package.json'"
23+
"build:dev": "./scripts/build.sh && node ./scripts/bundle.cjs",
24+
"build:release": "./scripts/build-optimized.sh && node ./scripts/bundle.cjs",
25+
"build": "yarn build:release",
26+
"prepack": "yarn build:release"
927
},
1028
"ultra": {
11-
"concurrent": ["test"]
29+
"concurrent": [
30+
"test"
31+
]
1232
}
1333
}

packages/wasm-sdk/scripts/build-optimized.sh

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
1111
echo "Building wasm-sdk with full optimization for npm release..."
1212

1313
# Call unified build script with full optimization
14-
"$SCRIPT_DIR/../scripts/build-wasm.sh" --package wasm-sdk --opt-level full
14+
"$SCRIPT_DIR/../../scripts/build-wasm.sh" --package wasm-sdk --opt-level full
1515

1616
# Additional post-processing for npm release
1717
echo "Post-processing for npm release..."
1818

19-
cd "$SCRIPT_DIR/pkg"
19+
cd "$SCRIPT_DIR/../pkg"
2020

2121
# Ensure the package.json is correct
2222
if [ ! -f "package.json" ]; then
@@ -41,10 +41,3 @@ ls -lah
4141
WASM_SIZE=$(wc -c < wasm_sdk_bg.wasm)
4242
WASM_SIZE_KB=$((WASM_SIZE / 1024))
4343
echo "WASM file size: ${WASM_SIZE_KB}KB"
44-
45-
# Verify the package.json has correct name
46-
if ! grep -q '"name": "dash"' package.json; then
47-
echo "Warning: package.json does not have 'dash' as the package name"
48-
fi
49-
50-
echo "Ready for npm publish!"

packages/wasm-sdk/scripts/build.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@ if [ "${CARGO_BUILD_PROFILE:-}" = "dev" ] || [ "${CI:-}" != "true" ]; then
1717
fi
1818

1919
# Call unified build script with default features (no need to specify)
20-
exec "$SCRIPT_DIR/../scripts/build-wasm.sh" --package wasm-sdk --opt-level "$OPT_LEVEL"
20+
exec "$SCRIPT_DIR/../../scripts/build-wasm.sh" --package wasm-sdk --opt-level "$OPT_LEVEL"
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#!/usr/bin/env node
2+
/*
3+
Bundle the wasm-bindgen JS glue and WASM binary into a single ESM file.
4+
- Input: pkg/wasm_sdk.js, pkg/wasm_sdk_bg.wasm, pkg/wasm_sdk.d.ts
5+
- Output: dist/sdk.js (single-file with embedded WASM), dist/sdk.d.ts
6+
7+
Notes:
8+
- We keep the exported API identical to wasm_bindgen output, including default export (init) and initSync.
9+
- We replace the default loader path with inlined bytes so no network or file access is required at runtime.
10+
*/
11+
12+
const fs = require('fs');
13+
const path = require('path');
14+
15+
const root = process.cwd();
16+
const pkgDir = path.join(root, 'pkg');
17+
const distDir = path.join(root, 'dist');
18+
const rawDir = path.join(distDir, 'raw');
19+
20+
const jsPath = path.join(pkgDir, 'wasm_sdk.js');
21+
const wasmPath = path.join(pkgDir, 'wasm_sdk_bg.wasm');
22+
const dtsPath = path.join(pkgDir, 'wasm_sdk.d.ts');
23+
const wasmDtsPath = path.join(pkgDir, 'wasm_sdk_bg.wasm.d.ts');
24+
25+
if (!fs.existsSync(jsPath) || !fs.existsSync(wasmPath) || !fs.existsSync(dtsPath)) {
26+
console.error('Missing build artifacts in pkg/. Run build first.');
27+
process.exit(1);
28+
}
29+
30+
const js = fs.readFileSync(jsPath, 'utf8');
31+
const wasmBase64 = fs.readFileSync(wasmPath).toString('base64');
32+
33+
// Helper injected to decode base64 → Uint8Array in both Node and browser
34+
const injectHeader = `
35+
// Inlined WASM bytes (base64)
36+
const __WASM_BASE64 = '${wasmBase64}';
37+
function __wasmBytes() {
38+
if (typeof Buffer !== 'undefined' && typeof Buffer.from === 'function') {
39+
return Buffer.from(__WASM_BASE64, 'base64');
40+
}
41+
const atobFn = (typeof atob === 'function') ? atob : (s) => globalThis.atob(s);
42+
const bin = atobFn(__WASM_BASE64);
43+
const len = bin.length;
44+
const bytes = new Uint8Array(len);
45+
for (let i = 0; i < len; i++) bytes[i] = bin.charCodeAt(i);
46+
return bytes;
47+
}
48+
`;
49+
50+
// Patch 1: default init path resolution to use inlined bytes
51+
const initDefaultSearch = /if \(typeof module_or_path === 'undefined'\) {\s*\n\s*module_or_path = new URL\('wasm_sdk_bg\.wasm', import\.meta\.url\);\s*\n\s*}/;
52+
const initDefaultReplace = `if (typeof module_or_path === 'undefined') {\n module_or_path = __wasmBytes();\n }`;
53+
54+
// Patch 2: initSync to use inlined bytes when module is not provided
55+
const initSyncSearch = /(__wbg_init_memory\(imports\);\s*\n\s*if \(!\(module instanceof WebAssembly\.Module\)\) {)/;
56+
const initSyncReplace = `__wbg_init_memory(imports);\n\n if (typeof module === 'undefined') {\n module = __wasmBytes();\n }\n\n if (!(module instanceof WebAssembly.Module)) {`;
57+
58+
let patched = js;
59+
60+
if (!initDefaultSearch.test(patched)) {
61+
console.error('Failed to find default init block to patch');
62+
process.exit(1);
63+
}
64+
patched = patched.replace(initDefaultSearch, initDefaultReplace);
65+
66+
if (!initSyncSearch.test(patched)) {
67+
console.error('Failed to find initSync block to patch');
68+
process.exit(1);
69+
}
70+
patched = patched.replace(initSyncSearch, initSyncReplace);
71+
72+
// Prepend helper header
73+
patched = injectHeader + '\n' + patched;
74+
75+
// Ensure dist directories and write outputs
76+
fs.mkdirSync(distDir, { recursive: true });
77+
fs.mkdirSync(rawDir, { recursive: true });
78+
fs.writeFileSync(path.join(distDir, 'sdk.js'), patched);
79+
fs.copyFileSync(dtsPath, path.join(distDir, 'sdk.d.ts'));
80+
81+
// Also ship non-bundled artifacts for advanced/asset-pipeline users
82+
fs.copyFileSync(jsPath, path.join(rawDir, 'wasm_sdk.js'));
83+
fs.copyFileSync(wasmPath, path.join(rawDir, 'wasm_sdk_bg.wasm'));
84+
fs.copyFileSync(dtsPath, path.join(rawDir, 'wasm_sdk.d.ts'));
85+
if (fs.existsSync(wasmDtsPath)) {
86+
fs.copyFileSync(wasmDtsPath, path.join(rawDir, 'wasm_sdk_bg.wasm.d.ts'));
87+
}
88+
89+
// Basic report
90+
const outStat = fs.statSync(path.join(distDir, 'sdk.js'));
91+
console.log(`Wrote dist/sdk.js (${outStat.size} bytes) with inlined WASM (${Math.round(Buffer.byteLength(wasmBase64, 'utf8')/1024)} KB base64)`);
92+
console.log('Wrote dist/sdk.d.ts');
93+
console.log('Wrote dist/raw/* (separate JS + WASM)');
94+
95+
// Clean up: remove pkg directory after bundling to avoid publishing it
96+
try {
97+
fs.rmSync(pkgDir, { recursive: true, force: true });
98+
console.log('Removed pkg/ directory after bundling');
99+
} catch (e) {
100+
console.warn('Warning: failed to remove pkg/ directory:', e?.message || e);
101+
}

0 commit comments

Comments
 (0)