Documentation Index
Fetch the complete documentation index at: https://docs.newton.xyz/llms.txt
Use this file to discover all available pages before exploring further.
0) Prerequisites
- Node.js 18+ and npm installed
- A terminal on macOS/Linux/WSL (Windows PowerShell also works)
Tip: Use nvm to manage Node versions:
# macOS/Linux example
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
nvm install --lts
nvm use --lts
1) Create a project folder
mkdir my_project
cd my_project
2) Install CLI
npm install -g @bytecodealliance/componentize-js
3) Add the WIT world
Create newton-provider.wit in the project root:
package newton:provider@0.1.0;
interface http {
record http-request {
url: string,
method: string,
headers: list<tuple<string, string>>,
body: option<list<u8>>,
}
record http-response {
status: u16,
headers: list<tuple<string, string>>,
body: list<u8>,
}
fetch: func(request: http-request) -> result<http-response, string>;
}
world newton-provider {
import http;
export run: func(input: string) -> result<string, string>;
}
4) Implement your component logic
Create app.js:
// Import the WIT import exactly like the ComponentizeJS usage pattern:
// e.g. import { log } from 'local:hello/logger' in their docs.
// Here our package is newton:provider and interface is http.
import { fetch as httpFetch } from "newton:provider/http@0.1.0";
// WIT: export run: func(input: string) -> result<string, string>
// We return a JSON string on success AND on "errors"
// (i.e., we don't surface WIT Err<string> — we encode error info in JSON)
export function run(input) {
const req = JSON.parse(input);
// Fetch ETH price from CoinGecko
const response = httpFetch({
url: "https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd",
method: "GET",
headers: [],
body: null,
});
if (response.tag === "err") {
return JSON.stringify({ error: response.val });
}
const body = new TextDecoder().decode(new Uint8Array(response.val.body));
const data = JSON.parse(body);
return JSON.stringify({
eth_price_usd: data.ethereum.usd,
timestamp: Date.now(),
});
}
Note: Keep this import at the top level of your module; ComponentizeJS resolves virtual specifiers like 'newton:provider/http@0.1.0' when you build the component.
5) Build the component
componentize-js --wit newton-provider.wit -o policy.wasm app.js -d stdio random clocks http fetch-event
This produces policy.wasm in the project root — a component that:
- Imports
newton:provider/http.fetch from the host
- Exports
run(input: string) -> result<string, string>
Resulting project tree:
my_project/
├─ policy.wasm
├─ newton-provider.wit
└─ app.js
6) (Alternative) Programmatic build
Create componentize.mjs:
import { componentize } from "@bytecodealliance/componentize-js";
import { readFile, writeFile } from "node:fs/promises";
const { component, imports } = await componentize({
sourcePath: "./app.js", // your JS file
witPath: "./newton-provider.wit", // WIT file path
worldName: "newton-provider", // the world in your WIT
});
await writeFile("policy.wasm", component);
console.log("guest imports:", imports);
Run it with:
7) Test your component
Use the Newton CLI to simulate your WASM data provider locally without deploying to the blockchain:
newton-cli --chain-id 11155111 policy-data simulate \
--wasm-file policy.wasm \
--input-json '{"inquiry_id": "inq_xRZrQFKg7rqZ5UZGLhnvb2ympshE"}'
The --input-json value is passed directly to your component’s run function as the input string argument. Replace the example JSON with your own input schema.
For more options, see the Newton CLI reference.