@steerprotocol/app-loader
v3.2.6
Published
App Loader for Steer Protocol
Readme
Steer Protocol App Loader
Load and execute Steer wasm bundles in Node.js and browser environments.
Node 18+ is required.
Install
npm install @steerprotocol/app-loaderRuntime Support
- Root import
@steerprotocol/app-loader- Node: resolves to the Node entrypoint
- Browser bundlers: resolves to the browser entrypoint through the
browserexport condition
- Explicit browser import:
@steerprotocol/app-loader/browser - Explicit Node import:
@steerprotocol/app-loader/node
Usage
Node
Use the root import for typical Node usage.
import { loadWasm } from '@steerprotocol/app-loader';
import type { WasmModule } from '@steerprotocol/app-loader';
const bundle: WasmModule = await loadWasm('/absolute/path/to/bundle.wasm');
bundle.initialize('{"example":true}');Node supports:
- filesystem paths
ArrayBuffer- remote URLs
Node runtime note:
- native
fetchis required - Node 18+ is the supported baseline
If you want an explicit Node-only import:
import { loadWasm } from '@steerprotocol/app-loader/node';
import type { WasmModule } from '@steerprotocol/app-loader/node';
const bundle: WasmModule = await loadWasm('/absolute/path/to/bundle.wasm');Browser
The browser entry supports ArrayBuffer and remote URL loading.
import { loadWasm } from '@steerprotocol/app-loader';
import type { WasmModule } from '@steerprotocol/app-loader';
const response = await fetch('/bundle.wasm');
const bundle: WasmModule = await loadWasm(await response.arrayBuffer());
bundle.initialize('{"example":true}');If you want to pin the browser-specific entrypoint:
import { loadWasm } from '@steerprotocol/app-loader/browser';
import type { WasmModule } from '@steerprotocol/app-loader/browser';
const response = await fetch('/bundle.wasm');
const bundle: WasmModule = await loadWasm(await response.arrayBuffer());Browser ccxt
In browsers, ccxt is expected on globalThis.ccxt.
If you load ccxt from a CDN or hosted bundle, make sure it is available before executing wasm that depends on it.
<script src="https://unpkg.com/[email protected]/dist/ccxt.browser.min.js"></script>The hosted browser build is covered by the default test suite with a live network smoke test against the same unpkg URL.
Node ccxt
In Node, ccxt is loaded from the installed module automatically.
API
Main exports:
loadWasm(input, imports?)loadWasmSync(input, imports?)WasmModule(type-only export)CandleRawTradeData
WasmModule is a type-only export. Strict TypeScript consumers, including projects using
moduleResolution: "NodeNext", module: "NodeNext", and verbatimModuleSyntax: true, must import it with
import type:
import { loadWasm } from '@steerprotocol/app-loader';
import type { WasmModule } from '@steerprotocol/app-loader';The same rule applies to @steerprotocol/app-loader/node and @steerprotocol/app-loader/browser.
The non-type-only form is not the supported pattern for strict TS consumers:
import { WasmModule, loadWasm } from '@steerprotocol/app-loader';The returned wasm wrapper exposes the module surface when available, including:
initialize(config)execute(...args)config()transform()reset()
Panoptic RuntimeAdapter
The Panoptic RuntimeAdapter is an additive Node-only feature. It is intended as a minor release surface, not a major-version runtime contract change:
- existing
as-fetchimports keep the same module names, function names, and argument shapes - existing
env.ccxt_fetchOHLCVkeeps the same import name and argument shape env.panoptic_callis added for wasm bundles that opt into Panoptic helpers- Panoptic SDK dependencies are optional unless a Panoptic method is called
Browser entrypoints reject panoptic options explicitly until browser support
is designed.
Panoptic support is optional. Consumers that call Panoptic methods must install the optional peers used by the adapter:
npm install @panoptic-eng/[email protected] viemSome SDK entrypoints also declare React/Wagmi peers; packaged SDK smoke tests install the full SDK peer set.
WASM calls the adapter through the additive async import:
env.panoptic_call(methodPtr, paramsJsonPtr)Only JSON-serializable DTOs cross that boundary. SDK objects, viem clients, providers, wallet clients, signers, and transaction submission helpers stay in the JavaScript host. The adapter returns deterministic reads, protocol calldata parts, and DynamicJobs fragments; it does not sign or submit transactions.
The stable helper families are:
- read snapshots:
pool.*,account.*,greeks.*,hypovault.*, anduniswap.*read/quote helpers - protocol fragments:
erc20.*Fragment,permit2.*Fragment,collateral.*Fragment,hypovault.*Fragment,merkle.*Fragment, andpanoptic.*Fragment - calldata parts for nested composition: Panoptic dispatch, HypoVault manager
manage, WETH wrap/unwrap calls, and Universal Router v3 exact-in execute - DynamicJobs rendering:
dynamicJobs.renderExecuteJob
DynamicJobs fragments use the same shape the strategy already emits:
target + userProvidedData + strategyProvidedData. Fragment builders take
semantic contract inputs and return that fragment shape directly. App-loader
does not duplicate the orchestrator/job registration manifest:
await loadWasm(wasmBytes, {}, {
panoptic: {
sourceRegistry: {
sources: [{ sourceId: 'base-mainnet', chainId: '8453', rpcUrl: 'https://base.example' }],
},
},
});dynamicJobs.renderExecuteJob renders fragments into
executeJob(address[],bytes[],bytes[]). It validates only fragment shape,
zero native value, and serializable bytes, then returns the payload arrays.
Whether target + userProvidedData is registered/executable is handled later
by the orchestrator and DynamicJobs/contracts. The actual execution boundary
remains the DynamicJobs registration, the orchestrator caller check, and the
destination contracts.
The adapter intentionally does not expose host signing, wallet clients, write
transaction helpers, or SDK object graphs across the wasm boundary.
calldata.* names are not part of the stable RuntimeAdapter API.
Development
Build
npm run buildUnit And Integration Tests
npm testAn env-gated live repro for the deprecated Sushi Polygon v2 connector is enabled when
STEER_SUBGRAPH_STUDIO_KEY is set (or STEER_SUBGRAPH_GATEWAY_KEY for local debugging). This connector is kept as historical evidence of a
known-broken path and is not part of the supported execution contract.
Packed Consumer Checks
These checks validate the packed artifact in consumer fixtures for:
- Node ESM
- Node CJS
- Strict TypeScript NodeNext consumers
- Vite browser bundler builds
- Next.js browser bundler builds
npm run test:consumersThis command builds the package, packs it, installs the tarball into fixture apps, validates the packed export artifacts, and runs each fixture check.
The Panoptic SDK package smoke test additionally installs @panoptic-eng/[email protected]
and exercises a real SDK-backed AS fixture:
npm run test:panoptic-sdk-smokeThe full verification gate is:
npm run verify:phase0Migration Notes
Version 2 changes the package runtime contract.
- Browser consumers should rely on the root import only when their bundler honors the
browserexport condition. - Browser
ccxtintegration now expects the hosted browser build onglobalThis.ccxt. - Node consumers should use the root import or
@steerprotocol/app-loader/node. - Browser consumers can use
@steerprotocol/app-loader/browserto pin the browser-safe entrypoint explicitly.
