OutLayer Documentation

NEAR Integration

Call OutLayer from your NEAR smart contract to execute off-chain WASM code and receive the result via callback. You stay in full control — no need to grant special access or delegate permissions to workers.

For Web2 projects (web apps, mobile apps, APIs) see Web2 Integration — call OutLayer via HTTPS without blockchain transactions.

Method: request_execution#

Call outlayer.testnet (testnet) or outlayer.near (mainnet)

Parameters (all fields):

source: ExecutionSource (required)

Specifies where to get WASM code. Three variants available:

Variant 1: GitHub (compile from source)

  • repo: GitHub repository URL (e.g., "https://github.com/user/project")
  • commit: Branch name ("main") or commit hash (40-char SHA)
  • build_target: Optional. "wasm32-wasip1" or "wasm32-wasip2" (default: wasip1)

Variant 2: WasmUrl (pre-compiled WASM)

  • url: URL to pre-compiled WASM file (FastFS, IPFS, etc.)
  • hash: SHA256 hash of WASM file for verification
  • build_target: "wasm32-wasip1" or "wasm32-wasip2"

Use WasmUrl for instant execution without compilation. Ideal for closed-source WASM or permanent deployments on FastFS/IPFS.

Variant 3: Project (registered project)

  • project_id: Project ID (e.g., "alice.near/my-app")
  • version_key: Optional. Specific version key (null = active version)

Use Project for registered apps with persistent storage. Automatically uses project secrets if available.

resource_limits: ResourceLimits (optional)

Maximum resources to allocate. Defaults shown below:

  • max_instructions: u64 (default: 1 billion, max: 500 billion)
  • max_memory_mb: u32 (default: 128 MB)
  • max_execution_seconds: u64 (default: 60s, max: 180s)

input_data: String (optional)

JSON string passed to WASM as stdin. Your code reads it via std::io::stdin()

Example: {"min":1,"max":100}

secrets_ref: SecretsReference (optional)

Reference to encrypted secrets stored on-chain

  • profile: Profile name (e.g., "production", "staging")
  • account_id: Account that owns the secrets

Worker decrypts secrets and injects as environment variables accessible via std::env::var()

Secrets can be bound to GitHub repo+branch OR to a WASM hash. When using WasmUrl, secrets bound to the hash are automatically matched.

response_format: ResponseFormat (optional)

How to parse WASM stdout (default: Text)

  • Text: Return raw stdout as string (default)
  • Json: Parse stdout as JSON value
  • Bytes: Return raw bytes

payer_account_id: AccountId (optional)

Who receives the refund for unused resources:

  • None (default): Sender pays and receives refund
  • Some(user_account): Charge end user, refund to user

Useful for contracts that want users to pay for their own executions

params: ExecutionParams (optional)

Advanced execution control parameters:

  • force_rebuild: bool (default: false) - Force recompilation even if WASM exists in cache. Useful when you updated code but kept the same commit hash, or need a fresh build for debugging.
  • compile_only: bool (default: false) - Only compile, don't execute. Returns checksum of compiled WASM. Useful for pre-warming cache or verifying compilation.
  • store_on_fastfs: bool (default: false) - Store compiled WASM on FastFS after compilation. Returns FastFS URL instead of execution result. Useful for permanent storage and sharing.

Example: "params": {"force_rebuild": true, "compile_only": false, "store_on_fastfs": false}

What You Get Back (Callback)#

OutLayer reads stdout from your WASM code and returns it to your contract's callback. You can write anything to stdout — a number, text, JSON object — and parse it however you want.

  • Success case: Your stdout output (parsed according to response_format: Text/Json/Bytes)
  • Failure case: Error information (compilation failed, timeout, etc.)
  • Resource metrics: Actual instructions used, execution time
  • Automatic refund: Unused deposit sent to payer_account_id

Important: You stay in full control. OutLayer just executes your code and returns stdout — no special permissions needed on your contract. You decide what to do with the results in your callback logic.

Example Contract Call#

use near_sdk::{near, env, Promise, Gas};
use serde_json::json;

#[near(contract_state)]
pub struct Contract {}

#[near]
impl Contract {
    pub fn call_outlayer(&mut self, city: String) -> Promise {
        // Call OutLayer with a project
        Promise::new("outlayer.near".parse().unwrap())
            .function_call(
                "request_execution".to_string(),
                json!({
                    "source": {
                        "Project": {
                            "project_id": "alice.near/weather-api"
                        }
                    },
                    "input_data": json!({"city": city}).to_string(),
                    "resource_limits": {
                        "max_instructions": 1_000_000_000,
                        "max_execution_seconds": 30
                    }
                }).to_string().into_bytes(),
                env::attached_deposit(),
                Gas::from_tgas(100)
            )
            .then(
                Self::ext(env::current_account_id())
                    .with_static_gas(Gas::from_tgas(10))
                    .on_outlayer_result()
            )
    }

    #[private]
    pub fn on_outlayer_result(&mut self) {
        // Handle the result from OutLayer
        match env::promise_result(0) {
            near_sdk::PromiseResult::Successful(data) => {
                let result: String = String::from_utf8(data).unwrap();
                env::log_str(&format!("Weather result: {}", result));
            }
            _ => {
                env::log_str("OutLayer execution failed");
            }
        }
    }
}

Pricing & Payment#

Attach NEAR tokens when calling request_execution. Cost is calculated dynamically based on resources used:

  • Base fee + (instructions used × per-instruction fee) + (execution time × per-millisecond fee)
  • Unused funds automatically refunded to payer_account_id
  • No refunds on execution failure (anti-DoS protection)
  • Query estimate_execution_cost() before calling to estimate required deposit

Performance Tips#

GitHub compilation: ~10 seconds for simple projects, up to few minutes for complex ones (full Rust build with dependencies)

Execution time: Depends on your code — from milliseconds to minutes based on complexity and resource limits

Pre-compiled WASM: Skip compilation entirely. Use WasmUrl with FastFS/IPFS for instant ~1s execution.

FastFS Workflow#

For production deployments, use FastFS to store pre-compiled WASM for instant execution:

  1. Compile with store_on_fastfs: Set "params": {"store_on_fastfs": true, "compile_only": true}
  2. Get FastFS URL: Response contains fastfs_url and wasm_hash
  3. Execute via WasmUrl: Use the URL and hash in source for instant execution

Benefits: Instant execution (no compilation), immutable code (hash-verified), works with closed-source WASM, permanent storage on-chain.

TEE Attestation#

Every execution produces a cryptographic attestation from Intel TDX proving:

  • Code integrity — Exact WASM binary that ran (SHA256 hash)
  • Input integrity — Exact input data received
  • Output integrity — Result was produced by that code with that input
  • Worker identity — Registered TEE worker with verified measurements

View attestations at /executions → "View Attestation". Learn more: TEE Attestation Documentation

Related Documentation