Browser-native Move compiler, package manager, and deployment pipeline for Aptos. Includes a Shelby Protocol runtime for browser microVM orchestration.
- Compiles Move contracts in the browser via a WASM-compiled Move Compiler v2 (no server required for simple packages)
- Resolves package dependencies from GitHub (git deps in Move.toml) with full transitive resolution
- Deploys to Aptos via wallet integration (Petra/Martian) with on-chain verification
- Runs Move tests and functions via a daemon bridge to the host
aptosCLI - Manages browser microVMs via the Shelby Protocol (v86-based, content-addressed snapshots)
┌─────────────────────────────────────────────────────────┐
│ Browser (Vanilla JS + Vite + Tailwind) │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ WASM Move │ │ Package │ │ Deploy │ │
│ │ Compiler v2 │ │ Resolver │ │ Pipeline │ │
│ │ (Web Worker) │ │ (GitHub + │ │ (Wallet + │ │
│ │ │ │ IndexedDB) │ │ BCS + Verify│ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ On-chain Dep │ │ Bytecode │ │ v86 Browser │ │
│ │ Fetcher │ │ Lockfile │ │ MicroVMs │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└──────────────────────┬──────────────────────────────────┘
│ /api proxy
┌──────────────────────▼──────────────────────────────────┐
│ Node.js Daemon (localhost:8787) │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Aptos CLI │ │ Move Test │ │ Move Run │ │
│ │ Compile │ │ Executor │ │ Executor │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Shelby │ │ Capability │ │
│ │ Protocol │ │ Auth │ │
│ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────┘
npm install
npm run dev # Start Vite dev server (port 4173)
npm run daemon # Start Node.js daemon (port 8787)
npm test # Run all tests (338 tests)The core of blinknow is a Move Compiler v2 compiled to WebAssembly (WASI target). It runs in-browser via a Web Worker or server-side via wasmtime.
| Browser (V8 WASI) | Server (wasmtime) | |
|---|---|---|
| Runtime | Web Worker + WASI shim | wasmtime run --dir /tmp |
| Dep limit | ~39 modules (V8 recursion) | Unlimited |
| Use case | Simple packages, fast iteration | Full packages, CI, large deps |
| Binary | public/wasm/move-compiler-v2.wasm (7.5MB) |
Same binary |
# Requires Rust nightly-2026-02-15
npm run build:wasm
# Or manually:
cd crates/move-wasm-compiler && ./build.shPinned to aptos-core commit 214bb53. Uses wasm32-wasip1 target with -Zbuild-std.
The WASM binary reads JSON from stdin, writes JSON to stdout:
{
"package_name": "MyPackage",
"sources": { "sources/main.move": "module 0x1::main { ... }" },
"precompiled_deps": { "0x1::string": "<base64 bytecode>" },
"dependency_sources": { "deps/vector.move": "<source>" },
"named_addresses": { "my_addr": "0x42" },
"output_encoding": "base64"
}Output includes compiled bytecodes and diagnostics:
{
"success": true,
"modules": { "main": "<base64 bytecode>" },
"diagnostics": [{ "severity": "Warning", "message": "...", "file": "...", "line": 10 }]
}To avoid recompiling the Aptos framework on every build, we ship pre-compiled bytecodes and source stubs.
| Asset | File | Contents |
|---|---|---|
| Framework bytecodes | public/wasm/framework-bytecodes.json |
137 modules (0x1, 0x3, 0x4), 515KB |
| Framework stubs | public/wasm/framework-stubs.json |
137 Move source stubs, 289KB |
| Third-party bytecodes | public/wasm/thirdparty-bytecodes.json |
69 modules (Pyth, Wormhole, OrderBook, Chainlink) |
| v86 VM runtime | public/wasm/v86.wasm |
Browser x86 emulator, 2MB |
npm run fetch:framework # Fetch 137 framework bytecodes from Aptos mainnet
npm run generate:stubs # Generate Move stubs from bytecodes
node scripts/fetch-thirdparty-bytecodes.mjs # Fetch Pyth/Wormhole/OrderBook/ChainlinkSome framework functions (vector::for_each, vector::for_each_ref, vector::map, etc.) are public inline fun — they exist only in source code, not in compiled bytecodes. If your contract uses these, pass vector.move and mem.move as dependency_sources alongside precompiled bytecodes. See test/econiaCompile.test.js for an example.
The browser-side package resolver handles Move.toml dependency trees:
- Parse Move.toml (git deps with rev/branch/tag, local deps, address substitution)
- Fetch from GitHub via tarball API (IndexedDB cache, rate limit handling)
- Resolve transitive dependencies with cycle and diamond detection
- Short-circuit framework deps (AptosFramework, AptosStdlib, AptosTokenObjects, MoveStdlib) to pre-compiled bytecodes
- Compile with resolved sources + precompiled deps
Supports .tar.gz and .zip uploads for offline/air-gapped use.
Browser-side deployment to Aptos:
- Connect wallet (Petra or Martian extension detection)
- Build publish payload (hand-rolled BCS encoding for PackageMetadata)
- Sign and submit via
window.aptos.signAndSubmitTransaction() - Verify by fetching on-chain modules and comparing bytecode hashes
The Node.js daemon wraps the host aptos CLI for operations that need filesystem access.
| Method | Path | Description |
|---|---|---|
GET |
/health |
Health check |
GET |
/aptos/cli |
Check if aptos CLI is available |
POST |
/aptos/move/compile |
Compile a Move package |
POST |
/aptos/move/test |
Run Move tests |
POST |
/aptos/move/run |
Execute a Move function |
All Move endpoints use ephemeral sandbox mode (compile in temp dir, clean up after).
See docs/api.md for full request/response schemas.
Content-addressed microVM orchestration:
- Images: Chunk-store ingestion with content-addressed manifests
- VMs: Create from image CID, lifecycle management (start/stop)
- Snapshots: DAG-structured deltas (upserts/deletes) with parent pointers
- Filesystem: Replay snapshot chain to materialize current state
- Capabilities: Scoped auth tokens with resource validation
See docs/protocol-spec.md for the protocol specification.
blinknow/
├── crates/move-wasm-compiler/ # Rust → WASM Move compiler
│ ├── src/lib.rs # Compiler entry, stub generator, interface generator
│ └── build.sh # Build script (wasm32-wasip1 target)
├── src/
│ ├── core/ # Browser-side modules (5.4K lines)
│ │ ├── moveCompiler.js # WASM compiler wrapper (browser)
│ │ ├── moveCompilerWorker.js # Web Worker runtime
│ │ ├── moveCompilerWasm.js # Node.js WASI runtime (tests)
│ │ ├── moveDependencyResolver.js # Package dependency resolver
│ │ ├── moveTomlParser.js # Move.toml parser
│ │ ├── dependencyGraph.js # Dep graph (cycles, diamonds, topo sort)
│ │ ├── githubFetcher.js # GitHub tarball fetcher + IndexedDB cache
│ │ ├── aptosModuleFetcher.js # On-chain module fetcher (any network)
│ │ ├── aptosBytecodeBundle.js # Framework bytecodes loader
│ │ ├── aptosStubsBundle.js # Framework stubs loader
│ │ ├── stubPruner.js # Transitive stub pruning
│ │ ├── aptosDeployService.js # Wallet + BCS + deploy + verify
│ │ ├── bytecodeLockfile.js # Reproducible build lockfile
│ │ ├── compileErrors.js # Error classification + actionable messages
│ │ ├── daemonClient.js # Daemon HTTP client
│ │ ├── tarExtractor.js # .tar.gz extraction (fflate)
│ │ ├── zipExtractor.js # .zip extraction (fflate)
│ │ ├── specStripper.js # Strip spec/verify_only blocks
│ │ ├── wasiHelpers.js # Shared WASI filesystem helpers
│ │ ├── v86Runtime.js # Browser VM runtime
│ │ └── ...
│ ├── node/
│ │ ├── daemon/
│ │ │ ├── server.ts # HTTP server (port 8787)
│ │ │ ├── handler.ts # Route handler
│ │ │ ├── aptos.ts # Aptos CLI compile bridge
│ │ │ └── moveExecutor.ts # Move test/run executor
│ │ ├── protocol/ # Shelby protocol engine
│ │ └── cli/shelbyvm.ts # CLI tool
│ └── main.js # Browser UI entry point
├── public/
│ ├── wasm/ # WASM binaries + precompiled assets
│ └── sw.js # Service worker (cache WASM assets)
├── test/ # 338 tests (27 test files, 6.7K lines)
├── scripts/ # Build/fetch scripts
├── aptos/sources/registry.move # On-chain VM registry contract
└── docs/ # Protocol spec, API docs, roadmap
npm test # All 338 tests
node --test test/moveCompilerE2E.test.js # Compiler end-to-end
node --test test/econiaCompile.test.js # Econia DEX (8 modules, requires wasmtime + clone)
node --test test/decibelCompile.test.js # Decibel contracts (51 modules, requires wasmtime)| Area | Tests | What's Tested |
|---|---|---|
| Move compiler | 80+ | Compilation, diagnostics, bytecode output, edge cases |
| Package resolution | 60+ | TOML parsing, GitHub fetch, dep resolution, cycles, diamonds |
| Framework deps | 30+ | Bytecodes, stubs, pruning, lockfile, on-chain fetching |
| Deploy pipeline | 10+ | BCS encoding, wallet detection, payload building |
| Error UX | 12 | Error classification patterns, formatting |
| Daemon/executor | 10+ | Route handling, test parsing, input validation |
| Protocol | 20+ | CAS objects, snapshots, capabilities, VM lifecycle |
| Extractors | 15+ | tar.gz, zip, path traversal protection |
| Real contracts | 8 | Econia DEX (8 modules), Decibel (51 modules) |
| Contract | Modules | Lines | Result |
|---|---|---|---|
| Econia DEX | 8 | 40,000 | 0 errors, 0 parse errors |
| Decibel Perp DEX | 51 | — | 0 parse errors, 64 semantic errors (decompiler artifacts) |
| DLMM (Thala) | 15 | — | Partial (friend dep issues) |
| Variable | Default | Description |
|---|---|---|
PORT |
8787 |
Daemon HTTP port |
VITE_DAEMON_URL |
/api |
Daemon base URL (browser) |
SHELBY_VM_DATA_DIR |
.shelby |
Protocol data directory |
SHELBY_VM_CAP_SECRET |
dev-secret |
Capability signing secret |
SHELBY_VM_APTOS_BIN |
aptos |
Path to aptos CLI binary |
SHELBY_VM_WORKSPACE_ROOT |
cwd |
Workspace root for Move packages |
SHELBY_VM_APTOS_TIMEOUT_MS |
120000 |
Compilation timeout |
SHELBY_VM_MAX_BODY_BYTES |
10485760 |
Max request body size |
SHELBY_VM_CORS_ORIGIN |
http://localhost:4173 |
CORS origin |
- WASI target: The compiler targets
wasm32-wasip1, eliminating the need to patch aptos-core. File I/O, tempfiles, and env vars work natively. - V8 dep limit: Browser V8 WASI hits SIGABRT at ~39 dependencies due to Move compiler v2 recursion depth. Use wasmtime for larger packages.
- Stub pruning: Browser compilation uses transitive stub pruning to stay under the V8 limit — only the stubs your code actually needs are included.
- Service worker: WASM assets (~10.5MB total) are cached via a service worker for instant repeat loads.
- COOP/COEP headers: Required for
SharedArrayBuffer(v86 VMs). Vite dev server and service worker both set these. - Rust toolchain: Pinned to
nightly-2026-02-15(later nightlies have a WASI regression in Node.js).
Private — SeamMoney/blinknow