Skip to content

Add WASM bindings (offline DIGStore spend bundles) + npm package CI#33

Open
MichaelTaylor3d wants to merge 14 commits into
mainfrom
wasm-bindings-plan
Open

Add WASM bindings (offline DIGStore spend bundles) + npm package CI#33
MichaelTaylor3d wants to merge 14 commits into
mainfrom
wasm-bindings-plan

Conversation

@MichaelTaylor3d
Copy link
Copy Markdown
Contributor

Summary

Adds WebAssembly bindings to datalayer-driver that mirror the offline subset of the existing NAPI interface, published as the npm package @dignetwork/datalayer-driver-wasm via CI. Primary use case: build and sign DIGStore (DataStore) spend bundles client-side in the browser/bundler environments, producing byte-for-byte identical output to the NAPI bindings.

What changed

  • Core crate (native feature gating): new default-on native cargo feature gates all networking (tokio, chia-wallet-sdk native-tls/peer-simulator, every &Peer async fn). The chia meta-crate (which transitively pulls chia-client→tokio) was decomposed into wasm-safe sub-crates so the core crate compiles to wasm32-unknown-unknown. Native + NAPI builds are unchanged.
  • New wasm/ workspace member: wasm-bindgen crate exposing ~30 offline functions — key derivation, address codecs, coin selection, DIGStore spend builders (mintStore/oracleSpend/meltStore/updateStoreMetadata/updateStoreOwnership), signing, serialization, server coins. JS shape matches NAPI exactly: Uint8Array for bytes, bigint for amounts (BigInt-configured serializer — mojo amounts exceed 2^53), camelCase fields.
  • Parity test (wasm/tests/parity.mjs): loads both the NAPI .node and the WASM nodejs build and asserts byte-for-byte equality across the offline surface, including a full mintStoresignCoinSpendsspendBundleToHex bundle, plus meltStore/sendXch/signMessage/verifySignedMessage.
  • Packaging: wasm-pack --target bundler --release + a patch script that sets the scoped package name and ships a hand-written, complete typed .d.ts.
  • CI: new build-wasm job (installs clang/lld for blst, builds, runs the parity test) and publish-wasm-npm job (version-tag-gated, mirrors the existing publish-npm pattern). Existing rust-checks (clippy -D warnings, cargo machete, fmt) remain green.

Scope notes

  • Offline only — no Peer/Tls/networking (WASM has no native sockets). Chain I/O stays the JS consumer's responsibility.
  • One intentional, documented deviation: DataStoreMetadata.sizeProof output is the symmetric 32-byte form (correct, round-trips) rather than replicating a NAPI output bug. Field type remains Uint8Array (matches NAPI).
  • Known follow-up: build:bundler uses --no-opt because the bundled wasm-opt rejects blst's bulk-memory ops; re-enable with a wasm-opt that supports --enable-bulk-memory for size optimization.

Design spec: docs/superpowers/specs/2026-05-29-datalayer-driver-wasm-bindings-design.md
Implementation plan: docs/superpowers/plans/2026-05-29-datalayer-driver-wasm-bindings.md

Test Plan

  • cargo build -p datalayer-driver --target wasm32-unknown-unknown --no-default-features succeeds
  • cargo build -p datalayer-driver and -p datalayer-driver-napi succeed (no native regression)
  • cargo clippy --all-targets --all-features -- -D warnings, cargo machete, cargo fmt --all -- --check pass
  • WASM↔NAPI parity test passes byte-for-byte (mint bundle, melt, sendXch, sign/verify, keys, addresses, cost, coin id)
  • wasm-pack build --target bundler --release + patch produces @dignetwork/datalayer-driver-wasm@3.0.0
  • CI build-wasm job green on this PR
  • (release) publish-wasm-npm publishes on a version-tag commit

🤖 Generated with Claude Code

MichaelTaylor3d and others added 14 commits May 29, 2026 22:35
Add the brainstormed design spec and bite-sized implementation plan for
offline WASM bindings mirroring the NAPI interface. Primary goal: build
and sign DIGStore (DataStore) spend bundles client-side, published as
@dignetwork/datalayer-driver-wasm via CI. Offline-only (no Peer/Tls
networking); core crate gains a `native` feature so it compiles to wasm32.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Add `native` cargo feature (default-on) gating all networking code
- Make `tokio`, `chia` meta-crate, and `chia-wallet-sdk` optional (native-only)
- Add direct wasm-safe sub-crate deps: chia-bls, chia-consensus, chia-protocol,
  chia-puzzle-types, chia-traits, chia-sdk-driver, chia-sdk-signer,
  chia-sdk-types, chia-sdk-utils (all without tokio/mio in dep tree)
- Gate all `pub async fn` taking `&Peer` in wallet.rs, dig_coin.rs,
  dig_collateral_coin.rs with #[cfg(feature = "native")]
- Gate ClientError variant in WalletError and CoinRecord/coin_records_to_states
- Replace all chia:: meta-crate paths with direct sub-crate paths
- WASM build (--no-default-features) succeeds; native + napi builds unchanged

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…asm path)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The native DataStoreMetadata.size_proof is Option<String> (hex); the JS
interface must expose it as Uint8Array like NAPI's Option<Buffer>, not a
string. Convert 32 raw bytes <-> hex string on the boundary.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add build-wasm job (needs rust-checks): installs clang/lld, wasm-pack,
  builds NAPI for parity test, builds WASM nodejs+bundler targets, uploads pkg artifact.
- Add publish-wasm-npm job (needs build-wasm): downloads pkg artifact and
  publishes to NPM on version-tag commits.
- Fix wasm-crate clippy warnings: remove unused Bytes and Serialize imports
  in wasm/src/types.rs so cargo clippy --all-targets --all-features -D warnings passes.
- Add [package.metadata.cargo-machete] ignored list for getrandom and js-sys
  in wasm/Cargo.toml so cargo machete passes.
- Run cargo fmt --all to resolve formatting diffs in wasm/ and src/.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add wasm/README.md with install, scope note, worked mint example, and parity guarantee. Add a 3-sentence WASM pointer near the top of the root README.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…trandom + wasm-opt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant