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.
Prerequisites
- Rust Toolchain
- Install Rust via rustup
- Version: 1.75.0 or later
- WASM Targets
# Install the WASI Preview 1 target
rustup target add wasm32-wasip1
# Optionally, install WASI Preview 2 target for future compatibility
rustup target add wasm32-wasip2
- Required Tools
# Install cargo-component for building WASM components
cargo install cargo-component
# Install wasm-tools for validation and inspection
cargo install wasm-tools
Project Structure
component/
├── Cargo.toml # Rust project configuration
├── src/
│ └── lib.rs # Main Rust implementation
└── wit/
└── world.wit # WebAssembly Interface Types definition
Step-by-Step Build Process
Step 1: Define the WIT Interface
Create a WIT file (wit/world.wit) compatible with Newton Protocol:
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>;
}
Set up your Cargo.toml for WASM component compilation:
[package]
name = "eligibility-checker"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"] # Required for WASM components
[dependencies]
wit-bindgen = "0.36" # WIT bindings generator
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
[package.metadata.component]
package = "newton:provider"
[package.metadata.component.dependencies]
# Add any WIT dependencies here
Step 3: Implement the Rust Code
In src/lib.rs, generate bindings and implement your functionality:
use serde::{Deserialize, Serialize};
use serde_json;
// Generate bindings from the WIT file
wit_bindgen::generate!({
world: "newton-provider", // Must match the world name in WIT
path: "wit", // Path to WIT files
});
// Export the implementation
export!(YourImplementation);
struct YourImplementation;
impl Guest for YourImplementation {
fn run(input: String) -> Result<String, String> {
// Fetch ETH price from CoinGecko
let request = newton::provider::http::HttpRequest {
url: "https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd"
.to_string(),
method: "GET".to_string(),
headers: vec![],
body: None,
};
let response = newton::provider::http::fetch(&request)
.map_err(|e| format!("HTTP fetch failed: {e}"))?;
let body = String::from_utf8(response.body)
.map_err(|e| format!("Invalid UTF-8: {e}"))?;
let data: serde_json::Value = serde_json::from_str(&body)
.map_err(|e| format!("JSON parse error: {e}"))?;
let price = data["ethereum"]["usd"]
.as_f64()
.ok_or("Missing price field")?;
Ok(serde_json::json!({
"eth_price_usd": price
}).to_string())
}
}
Step 4: Build the WASM Component
Option A: Using cargo-component (Recommended)
# Build the component
cargo component build --release
# Output location:
# target/wasm32-wasip1/release/<package_name>.wasm
Option B: Using standard cargo
# Build for WASI Preview 1
cargo build --target wasm32-wasip1 --release
# Output location:
# target/wasm32-wasip1/release/<package_name>.wasm
Step 5: Validate the WASM Component
# Validate the WASM module
wasm-tools validate target/wasm32-wasip1/release/<package_name>.wasm
# Inspect the component's WIT interface
wasm-tools component wit target/wasm32-wasip1/release/<package_name>.wasm
# Check the component's imports and exports
wasm-tools component new target/wasm32-wasip1/release/<package_name>.wasm \
-o component.wasm --adapt wasi_snapshot_preview1.wasm
Step 6: 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 target/wasm32-wasip1/release/<package_name>.wasm \
--input-json '{}'
Replace <package_name> with your crate name and --input-json with your component’s expected input schema.
For more options, see the Newton CLI reference.