Building AI dApps on Ettios
This guide shows you how to build an AI-powered decentralized application on Ettios β the first blockchain with AI at its core in Latin America. We will build a complete example: an AI Signal Oracle, where an off-chain AI agent analyzes market data and publishes its signals on-chain so any smart contract can consume them in a verifiable way.
Architecture Overview
AI models run off-chain (inference requires heavy computation), while results, decisions, and actions are recorded on-chain. This hybrid pattern gives you the best of both worlds:
1. AI Agent (off-chain)
A Node.js service that fetches data, runs inference with your preferred AI model, and signs transactions.
2. Ettios Mainnet
Settles the agent's transactions with 2-second blocks, low fees, and NPoS security.
3. Smart Contract
Stores the AI signals on-chain with access control, making them auditable and composable.
Prerequisites
- Node.js (v18 or later) and npm installed
- A wallet with ETTIA on the Ettios Mainnet for transaction fees
- A Hardhat project set up as described in Deploying Your First Smart Contract
- An API key from your AI provider (any OpenAI-compatible API works)
Step 1: The Smart Contract
Create contracts/AISignalOracle.sol. This contract stores the latest AI signal (a score from -100 to +100) and only accepts updates from the authorized AI agent address:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
/// @title AISignalOracle
/// @notice Stores AI-generated signals on Ettios so other contracts can consume them on-chain.
contract AISignalOracle {
address public aiAgent;
int256 public latestSignal; // -100 (very bearish) to +100 (very bullish)
uint256 public updatedAt;
event SignalUpdated(int256 signal, uint256 timestamp);
constructor() {
aiAgent = msg.sender;
}
modifier onlyAgent() {
require(msg.sender == aiAgent, "AISignalOracle: not authorized");
_;
}
/// @notice Rotate the authorized AI agent address.
function setAgent(address _agent) external onlyAgent {
require(_agent != address(0), "AISignalOracle: zero address");
aiAgent = _agent;
}
/// @notice Called by the AI agent to publish a new signal.
function submitSignal(int256 _signal) external onlyAgent {
require(_signal >= -100 && _signal <= 100, "AISignalOracle: out of range");
latestSignal = _signal;
updatedAt = block.timestamp;
emit SignalUpdated(_signal, block.timestamp);
}
}Step 2: Deploy to Ettios Mainnet
Compile and deploy using the Hardhat configuration from the previous guide:
npx hardhat compile npx hardhat run scripts/deploy.ts --network ettiosMainnet
Save the deployed contract address in your .env file:
PRIVATE_KEY=your_ai_agent_private_key ORACLE_ADDRESS=0xYourDeployedContractAddress AI_API_KEY=your_ai_provider_api_key
Step 3: The AI Agent Script
Create scripts/ai-agent.ts. This script fetches market data, asks the AI model for a signal, and submits it on-chain. Install the dependencies first:
npm install ethers@5 dotenv
import { ethers } from "ethers";
import * as dotenv from "dotenv";
dotenv.config();
// Connect to the Ettios Mainnet
const provider = new ethers.providers.JsonRpcProvider("https://rpc.ettiosblockchain.io");
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY || "", provider);
const ORACLE_ABI = [
"function submitSignal(int256 _signal) external",
"function latestSignal() view returns (int256)"
];
const oracle = new ethers.Contract(
process.env.ORACLE_ADDRESS || "",
ORACLE_ABI,
wallet
);
// 1. Fetch the data your AI model will analyze
async function fetchMarketData(): Promise<string> {
// Replace with your own data source (prices, news, on-chain metrics...)
return "ETTIA price: 1.25 USD, 24h change: +3.2%, volume rising";
}
// 2. Run inference with any OpenAI-compatible AI API
async function getAISignal(marketData: string): Promise<number> {
const response = await fetch("https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer " + process.env.AI_API_KEY
},
body: JSON.stringify({
model: "gpt-4o-mini",
messages: [
{
role: "system",
content: "You are a market analysis engine. Reply with a single integer from -100 (very bearish) to +100 (very bullish). No text, only the number."
},
{ role: "user", content: marketData }
]
})
});
const data = await response.json();
const signal = parseInt(data.choices[0].message.content.trim(), 10);
if (isNaN(signal) || signal < -100 || signal > 100) {
throw new Error("Invalid signal returned by the AI model");
}
return signal;
}
// 3. Submit the AI signal on-chain
async function main() {
const marketData = await fetchMarketData();
const signal = await getAISignal(marketData);
console.log("AI signal:", signal);
const tx = await oracle.submitSignal(signal);
console.log("Transaction sent:", tx.hash);
await tx.wait();
console.log("Signal confirmed on-chain. View it on https://scan.ettiosblockchain.io");
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});Run the agent manually, or schedule it to publish signals periodically:
npx hardhat run scripts/ai-agent.ts --network ettiosMainnet
Step 4: Consume the Signal On-Chain
Any contract can now read the AI signal. For example, a DeFi strategy contract can react to it:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
interface IAISignalOracle {
function latestSignal() external view returns (int256);
function updatedAt() external view returns (uint256);
}
contract AIStrategy {
IAISignalOracle public oracle;
uint256 public maxSignalAge = 1 hours;
constructor(address _oracle) {
oracle = IAISignalOracle(_oracle);
}
/// @notice Example: only allow "buy" actions when the AI is bullish and the signal is fresh.
function canBuy() public view returns (bool) {
require(block.timestamp - oracle.updatedAt() <= maxSignalAge, "Signal too old");
return oracle.latestSignal() > 50;
}
}Security Best Practices
Before going to production
- Never hardcode private keys β always use environment variables or a key management service.
- Keep the agent address restricted with
onlyAgent-style access control, and rotate keys periodically. - Validate every AI output on-chain (ranges, formats, freshness) β models can hallucinate or be manipulated.
- Consider a confidence threshold: ignore signals when the model is uncertain.
- Monitor the agent's wallet balance so it never runs out of ETTIA for gas.