OutLayer Documentation
Example Projects
Production-ready examples demonstrating different WASI patterns and use cases. All examples are open-source and ready to deploy.
random-arkWASI P1Beginner#
Generate cryptographically secure random numbers inside TEE (Trusted Execution Environment) using WASI's random_get interface.
Use Cases:
- Fair lottery systems requiring verifiable randomness
- Gaming applications needing unpredictable outcomes
- Cryptographic key generation
- Random sampling for statistical analysis
Key Features:
- Uses
getrandomcrate for secure randomness - TEE environment ensures entropy source cannot be manipulated
- Simple JSON input/output interface
- Perfect starter example for WASI development
Input Format:
{
"count": 5,
"min": 1,
"max": 100
}Request 5 random numbers between 1 and 100
Output Format:
{
"numbers": [42, 17, 93, 8, 55]
}How It Works
- WASM calls
random_getWASI function - Worker runtime requests entropy from TEE hardware
- Random bytes are generated using CPU's secure random number generator
- Numbers are scaled to requested range (min-max)
- Result returned as JSON
Technical Details:
- WASI Version: Preview 1 (
wasm32-wasip1) - Language: Rust with
getrandomcrate - Entry Point:
main()reads stdin, writes stdout - Dependencies:
serde_jsonfor JSON parsing - Build:
cargo build --target wasm32-wasip1 --release - Size: ~200KB compiled WASM
Learn More
echo-arkWASI P1Beginner#
Simple echo service that accepts JSON input and returns it with a timestamp. Demonstrates basic WASI I/O and data processing.
Use Cases:
- Testing WASI input/output pipeline
- Verifying data serialization/deserialization
- Template for building more complex data processing tasks
- Learning WASI development fundamentals
Key Features:
- JSON input validation
- Timestamp generation using WASI clock interface
- Error handling and structured responses
- Minimal dependencies - great learning example
Input Format:
{
"message": "Hello, OutLayer!",
"metadata": {
"user_id": "alice.near"
}
}Output Format:
{
"echo": {
"message": "Hello, OutLayer!",
"metadata": {
"user_id": "alice.near"
}
},
"timestamp": "2025-01-15T12:34:56Z",
"processed_by": "echo-ark v1.0"
}How It Works
- WASM reads JSON from stdin
- Deserializes input using serde_json
- Generates timestamp using WASI clock_time_get
- Constructs response object with original data + metadata
- Serializes and writes to stdout
Technical Details:
- WASI Version: Preview 1 (
wasm32-wasip1) - Language: Rust
- Entry Point:
main() - Dependencies:
serde,serde_json,chrono - Build:
cargo build --target wasm32-wasip1 --release - Size: ~180KB compiled WASM
Learn More
ai-arkWASI P2SecretsIntermediate#
Integrate OpenAI GPT models into your NEAR smart contracts. Send prompts from on-chain and receive AI-generated responses securely.
Use Cases:
- AI-powered smart contract decision making
- Natural language processing for on-chain data
- Content generation triggered by blockchain events
- Intelligent chatbots with verifiable responses
Key Features:
- HTTP client using
reqwestwith WASI sockets - Encrypted API key storage using OutLayer secrets
- Support for GPT-4, GPT-3.5-turbo models
- Configurable temperature, max tokens, system prompts
Input Format:
{
"prompt": "Explain NEAR Protocol in one sentence",
"model": "gpt-4",
"temperature": 0.7,
"max_tokens": 100
}Output Format:
{
"response": "NEAR Protocol is a scalable, developer-friendly blockchain platform...",
"model": "gpt-4",
"tokens_used": 28,
"finish_reason": "stop"
}How It Works
- WASM reads
OPENAI_API_KEYfrom encrypted secrets (env var) - Constructs HTTP POST request to OpenAI API
- Sends request via WASI HTTP interface
- Receives and parses JSON response
- Extracts AI-generated text and metadata
- Returns structured result to NEAR contract
Technical Details:
- WASI Version: Preview 2 (component model)
- Language: Rust
- HTTP Client:
reqwestwithwasi-preview2feature - Secrets: Required (
OPENAI_API_KEY) - Network: Required (outbound HTTPS to api.openai.com)
- Build:
cargo component build --release - Size: ~2.5MB compiled WASM
Setting Up Secrets
- Navigate to Secrets Management
- Create new secret with key
OPENAI_API_KEYand your OpenAI API key as value - Set repo to your GitHub project (e.g.,
github.com/alice/ai-ark) - Choose access condition (e.g., AllowAll for testing, Whitelist for production)
- Worker will automatically decrypt and inject into WASM environment
Important Security Notes
- ✅ API keys stored encrypted on-chain, decrypted only in TEE
- ✅ Keys never exposed to worker logs or external parties
- ⚠️ Monitor OpenAI API usage to prevent unexpected costs
- ⚠️ Set token limits to control response sizes
weather-arkWASI P2SecretsIntermediate#
Fetch real-world weather data from OpenWeatherMap API and bring it on-chain. Perfect for parametric insurance, prediction markets, and climate-dependent DeFi.
Use Cases:
- Weather-based parametric insurance (crop insurance, travel insurance)
- Prediction markets requiring real-world weather data
- Climate data for carbon credit verification
- Event cancellation triggers based on weather conditions
Key Features:
- Fetches temperature, humidity, pressure, wind speed
- Supports city name or coordinates lookup
- Returns structured weather data with timestamps
- Encrypted API key via OutLayer secrets (
OPENWEATHER_API_KEY)
Input Format (by city):
{
"city": "London",
"country_code": "UK"
}Input Format (by coordinates):
{
"lat": 51.5074,
"lon": -0.1278
}Output Format:
{
"location": "London, UK",
"temperature_celsius": 12.5,
"humidity_percent": 76,
"pressure_hpa": 1013,
"wind_speed_mps": 3.2,
"description": "partly cloudy",
"timestamp": "2025-01-15T12:34:56Z"
}How It Works
- WASM reads
OPENWEATHER_API_KEYfrom encrypted secrets - Constructs HTTP request to OpenWeatherMap API
- Sends GET request via WASI HTTP interface
- Parses JSON response with serde
- Converts units (Kelvin → Celsius, etc.)
- Returns normalized weather data to NEAR contract
Technical Details:
- WASI Version: Preview 2 (component model)
- Language: Rust
- HTTP Client:
reqwestwith WASI sockets - Secrets: Required (
OPENWEATHER_API_KEY) - Network: Required (outbound HTTPS to api.openweathermap.org)
- API: OpenWeatherMap Current Weather API
- Build:
cargo component build --release - Size: ~2.2MB compiled WASM
Setting Up Secrets
- Get free API key from OpenWeatherMap
- Navigate to Secrets Management
- Create secret: key =
OPENWEATHER_API_KEY, value = your API key - Set repo to your GitHub project
- Choose access condition (AllowAll for public data, Whitelist for production)
Important Security Notes
- ✅ Free tier: 60 calls/minute, 1M calls/month
- ⚠️ Monitor API usage to stay within limits
- ✅ API keys encrypted and only decrypted in TEE
- ⚠️ Weather data typically updates every 10 minutes - avoid excessive calls
oracle-arkWASI P2Advanced#
Multi-source price oracle with aggregation and validation. Production-ready decentralized oracle for cryptocurrency and commodity prices.
Key Features:
- Multiple API sources: CoinGecko, CoinMarketCap, TwelveData
- Price aggregation methods: average, median, weighted
- Deviation validation and error handling
- Batch requests for multiple tokens (up to 10)
- API key management via encrypted secrets
- Comprehensive error reporting per source
Supported Assets:
- Cryptocurrencies: Bitcoin, Ethereum, NEAR, SOL, etc.
- Commodities: Gold (XAU/USD), Oil (BRENT/USD)
- Forex: EUR/USD, GBP/USD, etc.
Input Example (Multi-token):
{
"tokens": [
{
"token_id": "bitcoin",
"sources": [
{"name": "coingecko", "token_id": null},
{"name": "coinmarketcap", "token_id": "BTC"}
],
"aggregation_method": "median",
"min_sources_num": 2
}
],
"max_price_deviation_percent": 5.0
}Output Example:
{
"tokens": [
{
"token": "bitcoin",
"data": {
"price": 110836.0,
"timestamp": 1729447200,
"sources": ["coingecko", "coinmarketcap"]
},
"message": null
}
]
}How to Use:
# 1. Get API keys (optional but recommended):
# - CoinMarketCap: https://coinmarketcap.com/api/
# - TwelveData: https://twelvedata.com/apikey
# - CoinGecko: Free tier (no key needed) or Pro
# 2. Store API keys as encrypted secrets via Dashboard
# Open https://outlayer.fastnear.com/secrets:
# - Secrets JSON: {"CMC_API_KEY":"...", "TWELVE_DATA_KEY":"..."}
# 3. Clone and build
git clone https://github.com/zavodil/oracle-ark.git
cd oracle-ark
cargo build --target wasm32-wasip2 --release
# 4. Request price data
near call outlayer.testnet request_execution '{
"source": {
"GitHub": {
"repo": "https://github.com/YOUR_USERNAME/oracle-ark",
"commit": "main",
"build_target": "wasm32-wasip2"
}
},
"secrets_ref": {
"profile": "production",
"account_id": "your-account.testnet"
},
"resource_limits": {
"max_instructions": 100000000,
"max_memory_mb": 128,
"max_execution_seconds": 60
},
"input_data": "{\"tokens\":[{\"token_id\":\"bitcoin\",\"sources\":[{\"name\":\"coingecko\"},{\"name\":\"coinmarketcap\",\"token_id\":\"BTC\"}],\"aggregation_method\":\"median\",\"min_sources_num\":2}],\"max_price_deviation_percent\":5.0}"
}' --accountId your-account.testnet --deposit 0.1 --gas 300000000000000
# Result will contain median price from multiple sourcesTechnical Details:
- WASI Version: Preview 2 (component model)
- Language: Rust
- HTTP Client:
reqwestwith WASI sockets - Secrets: Optional (API keys for higher rate limits)
- Network: Required (outbound HTTPS to multiple APIs)
- Build:
cargo component build --release - Size: ~3.5MB compiled WASM
Ethereum API OracleWASI P2Advanced#
Query Ethereum blockchain data via JSON-RPC (balances, smart contracts, transactions). Similar to the previous oracle example but configured for Ethereum node providers like Alchemy. Bridge NEAR with Ethereum data for cross-chain applications.
Key Features:
- Ethereum JSON-RPC API integration (eth_getBalance, eth_call, etc.)
- Support for Alchemy, Infura, and other Ethereum node providers
- Custom request structure with JSON path extraction
- Cross-chain data oracle for NEAR ↔ Ethereum bridges
- Encrypted API key storage (Alchemy secrets profile)
- Production-ready on testnet and mainnet
Input Example (Check ETH Balance):
{
"requests": [
{
"id": "alchemy",
"sources": [
{
"name": "custom",
"custom": {
"url": "https://eth-mainnet.g.alchemy.com/v2",
"method": "POST",
"body": {
"method": "eth_getBalance",
"params": ["0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "latest"],
"id": 1,
"jsonrpc": "2.0"
},
"json_path": "result",
"value_type": "string"
}
}
]
}
],
"max_price_deviation_percent": 10.0
}Output Example:
{
"results": [
{
"id": "alchemy",
"value": "0x1bc16d674ec80000",
"sources_used": 1
}
]
}Quick Start (Testnet):
# Using pre-configured Alchemy secrets on testnet
near contract call-function as-transaction outlayer.testnet request_execution \
json-args '{
"source": {
"GitHub": {
"repo": "https://github.com/zavodil/oracle-ark",
"commit": "main",
"build_target": "wasm32-wasip2"
}
},
"secrets_ref": {
"profile": "alchemy",
"account_id": "zavodil2.testnet"
},
"resource_limits": {
"max_instructions": 100000000,
"max_memory_mb": 128,
"max_execution_seconds": 60
},
"input_data": "{\"requests\":[{\"id\":\"alchemy\",\"sources\":[{\"name\":\"custom\",\"custom\":{\"url\":\"https://eth-mainnet.g.alchemy.com/v2\",\"method\":\"POST\",\"body\":{\"method\":\"eth_getBalance\",\"params\":[\"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045\",\"latest\"],\"id\":1,\"jsonrpc\":\"2.0\"},\"json_path\":\"result\",\"value_type\":\"string\"}}]}],\"max_price_deviation_percent\":10.0}"
}' \
prepaid-gas '300.0 Tgas' \
attached-deposit '0.1 NEAR' \
sign-as your-account.testnet \
network-config testnet \
sign-with-keychain sendUse Cases:
- Cross-Chain Bridges: Verify Ethereum transactions on NEAR
- DeFi Integration: Monitor Ethereum token balances from NEAR contracts
- Multi-Chain Wallets: Display ETH balances in NEAR apps
- Smart Contract State: Read Ethereum contract data (ERC20, NFTs)
- Block Explorer: Query Ethereum transaction history
Notes:
- Same codebase as
oracle-ark, different secrets configuration - Requires Alchemy API key (free tier: 300M compute units/month)
- Supports any Ethereum JSON-RPC method (eth_call, eth_getTransactionReceipt, etc.)
- Pre-configured secrets available on testnet:
zavodil2.testnet - Mainnet secrets:
zavodil.near
Technical Details:
- WASI Version: Preview 2 (component model)
- Language: Rust
- HTTP Client:
reqwestwith WASI sockets - Secrets: Required (
ALCHEMY_API_KEY) - Network: Required (outbound HTTPS to Alchemy/Infura)
- Build:
cargo component build --release - Size: ~3.5MB compiled WASM
botfather-arkWASI P2Host FunctionsAdvanced#
Account factory pattern for NEAR - create and manage multiple NEAR accounts with AI-generated names using hierarchical key derivation. Demonstrates advanced host function usage with call() and transfer(), providing access to private NEAR RPC endpoints (powered by Fastnear).
Use Cases:
- Account Factory: Generate multiple NEAR accounts programmatically
- Batch Operations: Execute contract calls on multiple accounts simultaneously (e.g., buy tokens, delegate to staking pool)
- Onboarding Platform: Create named accounts for users via Telegram bots or web apps
- Sub-Account Management: Manage hierarchical account structures with deterministic key derivation
Key Features:
- AI-powered account name generation (GPT integration)
- Deterministic key derivation from master seed using SHA-256
- Account discovery via Fastnear API
- Batch contract calls with template variables (
{{account_id}}) - Fund distribution across multiple accounts
- Uses
near:rpc/[email protected]host functions:call(),transfer()
Actions:
1. Create Accounts:
{
"action": "create_accounts",
"prompt": "space exploration theme",
"count": 3,
"deposit_per_account": "1000000000000000000000000"
}Creates accounts like mars-rover.testnet, moon-base.testnet
2. Fund Accounts:
{
"action": "fund_accounts",
"total_amount": "30000000000000000000000000",
"indices": []
}Empty indices = fund all accounts equally (30 NEAR ÷ 3 accounts = 10 NEAR each)
3. Batch Contract Calls:
{
"action": "batch_call",
"contract_id": "token.near",
"method_name": "transfer",
"args": {"receiver_id": "{{account_id}}", "amount": "1000"},
"deposit": "1",
"gas": "30000000000000",
"indices": [0, 2]
}Execute on accounts at indices 0 and 2. Use {{account_id}} placeholder for dynamic account ID
4. List Accounts:
{
"action": "list_accounts"
}Returns all created accounts with balances and public keys
Output Example:
{
"success": true,
"accounts": [
{
"index": 0,
"account_id": "mars_rover.testnet",
"public_key": "ed25519:...",
"balance": "1000000000000000000000000",
"balance_near": "1.0000"
}
],
"transactions": [
{
"account_id": "mars_rover.testnet",
"tx_hash": "Abc123...",
"success": true
}
]
}How It Works
- Key Derivation in TEE: Derivation key (
PROTECTED_MASTER_KEY) is generated inside TEE (nobody ever sees it). Derived keys are created using SHA-256:SHA256(derivation_key + sender_id + index)- each derived key controls one account - Account Discovery: Queries Fastnear API to find existing accounts by derived public keys (stateless operation)
- AI Name Generation: Calls OpenAI API to generate creative account names based on theme prompt
- Account Creation: Uses NEAR RPC
call()host function to create accounts viacreate_accountaction - Batch Execution: Iterates through account indices and executes operations using
call()ortransfer()
Setting Up Secrets
⚠️ This example is not available in Playground because it requires creating a secret with NEAR_SENDER_PRIVATE_KEY - your NEAR account's private key (with NEAR tokens) to pay for account creation and funding.
To use this example, create a secret in the Secrets page with the following configuration:
Manual Secrets:
{
"NEAR_SENDER_PRIVATE_KEY": "ed25519:your_private_key",
"OPENAI_API_KEY": "sk-...",
"OPENAI_ENDPOINT": "https://api.openai.com/v1/chat/completions",
"OPENAI_MODEL": "gpt-3.5-turbo"
}Generated Secret (created in TEE):
- Click "Generate Secret" button
- Secret name:
PROTECTED_MASTER_KEY - Type:
ED25519(generates ed25519 key pair in TEE) - This key is created inside TEE and never exposed - used to derive all account keys
Access Control:
Set 👥 Whitelist with your account ID (the one that will manage created accounts)
Technical Details:
- WASI Version: Preview 2 (component model)
- Language: Rust
- WIT Interface:
near:rpc/[email protected](call, transfer, view) - Secrets: Required (
NEAR_SENDER_PRIVATE_KEY,OPENAI_API_KEY,PROTECTED_MASTER_KEY) - Network: Required (Fastnear API, OpenAI API, NEAR RPC via host functions)
Important Security Notes
- ✅ WASM provides signer: User's NEAR private key is passed via secrets (not worker's key)
- ✅ Keys created in TEE: Derivation key (
PROTECTED_MASTER_KEY) is generated inside TEE and never leaves it. Derived keys are created using deterministic SHA-256 derivation from derivation key. - ✅ Accounts managed only in TEE: All derived accounts are controlled exclusively by keys that exist only inside TEE - nobody can export or see the private keys
- ✅ Deterministic keys: Same derivation key + sender + index always generates same account key
- ✅ Derivation key isolation: Each
NEAR_SENDER_IDhas isolated account space - ⚠️ Store derivation key safely: Loss of derivation key = loss of access to all derived accounts
intents-arkWASI P2Advanced#
DEX token swaps via NEAR Intents protocol. User's FT transfer transaction pauses, WASI performs swap off-chain, then resolves by sending swapped tokens back - all within single transaction.
Key Features:
- FT transfer pauses during off-chain swap execution
- NEAR Intents API integration (quote → publish → settle)
- NEP-413 message signing with ed25519
- Automatic token withdrawal to user upon completion
- Private key management via encrypted secrets
- Storage deposit handling for fungible tokens
Transaction Flow:
- User calls
ft_transfer_callto swap contract - Contract receives tokens and calls OutLayer
- Transaction pauses - contract enters yield state
- WASI worker performs swap via NEAR Intents API
- Worker withdraws swapped tokens to user
- Transaction resumes - contract completes with callback
How to Use:
# 1. Create operator account on NEAR mainnet
near create-account operator.near --useFaucet
# 2. Store operator private key as encrypted secret
# Open https://outlayer.fastnear.com/secrets:
# - Secrets JSON: {"OPERATOR_PRIVATE_KEY":"ed25519:..."}
# 3. Clone and deploy swap contract
git clone https://github.com/zavodil/intents-ark.git
cd intents-ark/contract
cargo near build
near deploy swap-contract.near res/swap_contract.wasm
# 4. Initialize contract
near call swap-contract.near new '{
"operator_account_id": "operator.near"
}' --accountId swap-contract.near
# 5. User swaps 1 WNEAR for USDC
near call wrap.near ft_transfer_call '{
"receiver_id": "swap-contract.near",
"amount": "1000000000000000000000000",
"msg": "{\"Swap\":{\"token_out\":\"usdc.token\",\"min_amount_out\":\"900000\"}}"
}' --accountId user.near --depositYocto 1 --gas 300000000000000
# Transaction will:
# - Pause after receiving WNEAR
# - Execute swap off-chain via NEAR Intents
# - Resume and send swapped USDC to userNote: NEAR Intents works on mainnet only. For testnet testing, use mock swap implementation.
Technical Details:
- WASI Version: Preview 2 (component model)
- Language: Rust
- HTTP Client:
reqwestfor NEAR Intents API - Secrets: Required (
OPERATOR_PRIVATE_KEY) - Network: Required (NEAR Intents API, mainnet only)
- Signing: NEP-413 message signing with ed25519
- Build:
cargo component build --release - Size: ~3.8MB compiled WASM
private-dao-arkWASI P1Advanced#
Anonymous, verifiable DAO voting with cryptographic privacy. Heavy cryptography (ECIES encryption, HKDF key derivation, merkle tree proofs) executed off-chain in TEE. Each user's vote is encrypted on-chain, tallying happens in secure enclave, only aggregate counts are revealed.
🔐 Privacy Guarantees:
- Individual votes remain secret - only aggregate counts revealed
- DAO members can send encrypted noise instead of real votes to hide voting activity from observers
- Merkle proofs allow voters to verify their vote was counted without revealing how they voted
Key Features:
- ECIES encryption for private votes (secp256k1)
- HKDF-SHA256 deterministic key derivation from single master secret
- Merkle tree construction for vote inclusion proofs
- Dummy messages: Send encrypted noise to hide whether you voted (indistinguishable from real votes on-chain)
- Vote changes: Vote multiple times, timestamp-based deduplication (latest vote wins)
- TEE attestation for execution integrity
- Full-stack React frontend with NEAR Wallet integration
Architecture:
1. Generate master secret:
OutLayer → TEE generates random master secret (stored encrypted)
2. User joins DAO:
Contract → OutLayer → TEE derives pubkey from master secret
3. User votes:
Frontend encrypts vote with pubkey → Contract stores encrypted vote
4. Finalize proposal:
Contract → OutLayer → TEE decrypts votes + tallies + builds merkle tree
Returns aggregate counts + merkle proofs (individual votes never exposed)
5. Verify vote:
User computes vote hash → Verifies merkle proof against root
Privacy Features:
- Individual votes never revealed (only aggregate counts)
- Dummy messages: Send encrypted noise to hide voting activity
- Vote changes: Vote multiple times, only latest counts (timestamped)
- Merkle proofs: Verify inclusion without revealing vote content
Cost: Heavy cryptography off-chain = ~$0.001 per voteCryptographic Components:
// Single master secret → unique key per user
let info = format!("user:{}:{}", dao_account, user_account);
let user_privkey = hkdf_sha256(&master_secret, info.as_bytes());
let user_pubkey = secp256k1::derive_public_key(&user_privkey);import { encrypt } from 'eciesjs';
const vote = "yes"; // or "no"
const pubkeyHex = await contract.get_user_pubkey({ user });
const encrypted = encrypt(pubkeyHex, Buffer.from(vote));
await contract.cast_vote({ proposal_id, encrypted_vote: encrypted.toString('hex') });// Must preserve u64 precision - use BigInt!
const timestamp = result.receipts_outcome[0].outcome.status.SuccessValue;
const timestampStr = atob(timestamp).trim(); // Keep as string
const timestampBigInt = BigInt(timestampStr);
// Convert to 8-byte little-endian
const buffer = new ArrayBuffer(8);
new DataView(buffer).setBigUint64(0, timestampBigInt, true);
// SHA256(user + timestamp_le + encrypted)
const combined = concat(
textEncoder.encode(accountId),
new Uint8Array(buffer),
textEncoder.encode(encrypted)
);
const voteHash = hex(await crypto.subtle.digest('SHA-256', combined));// Try all possible paths (2^depth combinations)
async function verifyProof(voteHash, proofPath, merkleRoot) {
async function tryPaths(hash, remaining) {
if (!remaining.length) return hash === merkleRoot;
const [sibling, ...rest] = remaining;
// Try both orderings
if (await tryPaths(await sha256(hash + sibling), rest)) return true;
if (await tryPaths(await sha256(sibling + hash), rest)) return true;
return false;
}
return await tryPaths(voteHash, proofPath);
}How to Deploy:
# 1. Generate DAO master secret in TEE
# (Alternatively: generate locally and store encrypted)
openssl rand -hex 32 > dao_master_secret.txt
# 2. Store master secret via Dashboard (encrypted in keystore)
# Open https://outlayer.fastnear.com/secrets:
# - Repo: github.com/YOUR_USERNAME/private-dao-ark
# - Profile: production
# - Secrets JSON: {"DAO_MASTER_SECRET":"<paste hex from file>"}
# - Access: AllowAll (or Whitelist for DAO admin only)
# 3. Clone and build WASI module
git clone https://github.com/zavodil/private-dao-ark.git
cd private-dao-ark
cargo build --target wasm32-wasip1 --release
git push origin main
# 4. Deploy DAO contract
cd dao-contract
cargo near build
near deploy privatedao.testnet \
use-file res/private_dao_contract.wasm \
with-init-call new \
json-args '{
"owner_id":"owner.testnet",
"name":"My Private DAO",
"outlayer_contract":"outlayer.testnet",
"wasi_repo":"https://github.com/YOUR_USERNAME/private-dao-ark",
"wasi_commit":"main",
"secrets_profile":"production",
"secrets_owner":"your.testnet",
"membership_mode":"Public"
}' \
prepaid-gas '100.0 Tgas' \
attached-deposit '0 NEAR'
# 5. Deploy frontend
cd ../dao-frontend
npm install
cat > .env <<EOF
REACT_APP_CONTRACT_ID=privatedao.testnet
REACT_APP_NEAR_NETWORK=testnet
EOF
npm run build
# Deploy build/ to Vercel/Netlify/Cloudflare Pages
# 6. Users can now:
# - Join DAO (get encrypted pubkey derived from master secret)
# - Create proposals with quorum requirements
# - Vote privately (votes encrypted with their pubkey)
# - Finalize proposals (OutLayer decrypts in TEE and tallies)
# - Verify their vote was counted (merkle proof verification)Use Cases:
- Anonymous Governance: Board elections where individual votes should remain secret
- Whistleblower Protection: Report issues without revealing identity
- Salary Decisions: Vote on compensation without peer pressure
- Grant Allocation: Fund projects while preventing vote buying
- Conflict Resolution: Vote on sensitive matters privately
Technical Highlights:
Heavy cryptography off-chain: ~$0.001/vote
ECIES + HKDF + Merkle trees feasible with OutLayer
Encrypted votes on-chain
Dummy messages hide voting activity
Vote changes allowed (latest wins)
Decryption in secure enclave
Merkle proofs: Voters verify inclusion
TEE attestation: Verify execution integrity
Master secret in TEE → unlimited users
No storage overhead for keys
Important Security Notes
- Master secret must be highly secured (hardware wallet, multi-sig, etc.)
- TEE attestation uses Intel TDX via Phala Network
- Frontend must correctly compute vote hash (BigInt for u64 precision!)
- Vote hash saved by user is CRITICAL for later verification
Technical Details:
- WASI Version: Preview 1 (
wasm32-wasip1) - Language: Rust
- Cryptography: ECIES (secp256k1), HKDF-SHA256, Merkle trees
- Secrets: Required (
DAO_MASTER_SECRET) - Frontend: React with NEAR Wallet integration
- Build:
cargo build --target wasm32-wasip1 --release - Size: ~1.2MB compiled WASM
captcha-arkWASI P2Full Stack#
Token sale with mandatory CAPTCHA verification. Transaction won't complete until user solves CAPTCHA. WASI worker receives session ID from backend and waits for verification signal. Example implementation demonstrating async human verification pattern.
Key Features:
- Transaction blocking until CAPTCHA solved
- WASI worker requests CAPTCHA challenge from backend
- Backend sends CAPTCHA to user via WebSocket
- Worker waits for verification signal (long-polling)
- hCaptcha integration for human verification
- React frontend with NEAR Wallet Selector
- Node.js backend with Express + WebSocket server
Architecture:
User Browser → Token Sale Contract → OutLayer → WASI Worker
↑ ↓
└────── Launchpad Backend (WebSocket) ←────────┘
Flow:
1. User clicks "Buy Tokens" with session_id
2. Contract calls OutLayer, transaction pauses
3. WASI worker → backend: "I received payment from session_id X.
Verify this is a real user, not a bot. Send CAPTCHA and notify
me when user completes it."
4. Backend sends CAPTCHA to user's browser via WebSocket
5. User solves CAPTCHA in modal
6. Backend verifies solution and marks session as verified
7. Worker receives "verified" signal, returns success to contract
8. Transaction resumes - user receives tokensComponents:
- WASI Worker: Rust WASM that verifies CAPTCHA (wasm32-wasip2)
- Smart Contract: Token sale logic with OutLayer integration
- Backend: Node.js Express server with WebSocket support
- Frontend: React app with hCaptcha widget
How to Use:
# 1. Get hCaptcha account (free at hcaptcha.com)
# - Create site and get Site Key + Secret Key
# 2. Clone repository
git clone https://github.com/zavodil/captcha-ark.git
cd captcha-ark
# 3. Setup backend
cd launchpad-backend
npm install
cat > .env <<EOF
PORT=3181
HCAPTCHA_SITE_KEY=your_site_key
HCAPTCHA_SECRET=your_secret_key
WORKER_API_KEY=$(openssl rand -hex 32)
EOF
npm start
# 4. Setup frontend
cd ../launchpad-app
npm install
cat > .env <<EOF
REACT_APP_CONTRACT_ID=tokensale.testnet
REACT_APP_NEAR_NETWORK=testnet
REACT_APP_HCAPTCHA_SITE_KEY=your_site_key
EOF
npm run build
# Deploy build/ to your web server
# 5. Build WASI worker
cd ../captcha-ark
cargo build --target wasm32-wasip2 --release
git push origin main
# 6. Deploy token sale contract
cd ../token-sale-contract
cargo near build
near deploy tokensale.testnet \
use-file res/token_sale_contract.wasm \
with-init-call new \
json-args '{"owner":"owner.testnet","total_supply":"10000","launchpad_url":"https://api.yourdomain.com"}' \
prepaid-gas '100.0 Tgas' \
attached-deposit '0 NEAR'
# 7. Users can now buy tokens - CAPTCHA required!
# Visit https://launchpad.yourdomain.com and click "Buy Tokens"Production Setup: Requires SSL certificates for both frontend and backend domains. See CONFIGURATION.md for complete deployment guide.
Important Security Notes
- Backend must implement worker authentication to prevent spam attacks
- Unauthorized requests to create CAPTCHA challenges should be rejected
- Use HTTPS for both frontend and backend in production
- Implement rate limiting on CAPTCHA challenge creation
Technical Details:
- WASI Version: Preview 2 (component model)
- Language: Rust (WASM), TypeScript (Frontend/Backend)
- HTTP Client:
reqwestfor backend communication - Backend: Node.js + Express + WebSocket
- Frontend: React with NEAR Wallet Selector
- CAPTCHA: hCaptcha integration
- Build:
cargo component build --release - Size: ~2.8MB compiled WASM