From 9d418c571f2407a33256e96228b0063eff97ab10 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 01:22:46 +0700 Subject: [PATCH 01/27] Create piHealth.js --- services/piHealth.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 services/piHealth.js diff --git a/services/piHealth.js b/services/piHealth.js new file mode 100644 index 00000000..055a602f --- /dev/null +++ b/services/piHealth.js @@ -0,0 +1,19 @@ +// services/piHealth.js +import fetch from "node-fetch"; + +export async function getPiHealth() { + const res = await fetch("https://rpc.testnet.minepi.com", { + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: 1, + method: "getHealth" + }) + }); + + const data = await res.json(); + return data.result || data; +} From 401c20fd856d8221659c49477c02a08ef6cb4ad2 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 01:24:01 +0700 Subject: [PATCH 02/27] Create aiOracle.js --- oracle/aiOracle.js | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 oracle/aiOracle.js diff --git a/oracle/aiOracle.js b/oracle/aiOracle.js new file mode 100644 index 00000000..caeaeb9d --- /dev/null +++ b/oracle/aiOracle.js @@ -0,0 +1,38 @@ +// oracle/aiOracle.js +export function analyzeHealth(health) { + let riskScore = 0; + let status = "SAFE"; + + if (health.status !== "healthy") { + riskScore += 40; + } + + if (health.txCount && health.txCount > 1000) { + riskScore += 30; + } + + if (health.ledger && health.ledger < 10000) { + riskScore += 20; + } + + // AI-style classification + if (riskScore > 70) status = "HIGH"; + else if (riskScore > 40) status = "MEDIUM"; + + return { + risk: status, + score: riskScore, + insight: generateInsight(status) + }; +} + +function generateInsight(status) { + switch (status) { + case "HIGH": + return "⚠️ Network anomaly detected"; + case "MEDIUM": + return "⚡ Moderate load detected"; + default: + return "✅ Network stable"; + } +} From 81f755466371bec1212a8470e3393f031b728204 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 01:24:46 +0700 Subject: [PATCH 03/27] Create actionEngine.js --- engine/actionEngine.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 engine/actionEngine.js diff --git a/engine/actionEngine.js b/engine/actionEngine.js new file mode 100644 index 00000000..83818607 --- /dev/null +++ b/engine/actionEngine.js @@ -0,0 +1,21 @@ +// engine/actionEngine.js +export function takeAction(analysis) { + if (analysis.risk === "HIGH") { + return { + action: "SWITCH_RPC", + message: "Switching to backup node..." + }; + } + + if (analysis.risk === "MEDIUM") { + return { + action: "THROTTLE", + message: "Reducing request rate..." + }; + } + + return { + action: "NORMAL", + message: "All systems stable" + }; +} From e667e64196df382d7dde146a90c2501f0e8891c2 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 01:26:48 +0700 Subject: [PATCH 04/27] Create app.js --- src/app.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/app.js diff --git a/src/app.js b/src/app.js new file mode 100644 index 00000000..b9487d41 --- /dev/null +++ b/src/app.js @@ -0,0 +1,20 @@ +import express from "express"; +import { getPiHealth } from "./services/piHealth.js"; +import { analyzeHealth } from "./oracle/aiOracle.js"; +import { takeAction } from "./engine/actionEngine.js"; + +const app = express(); + +app.get("/health-check", async (req, res) => { + try { + const health = await getPiHealth(); + const analysis = analyzeHealth(health); + const action = takeAction(analysis); + + res.json({ health, analysis, action }); + } catch { + res.status(500).json({ error: "Failed to fetch health" }); + } +}); + +export default app; From 6fa6465ea13e3de7f418b8925982044bfb55ffe0 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 01:27:23 +0700 Subject: [PATCH 05/27] Create server.js --- src/server.js | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/server.js diff --git a/src/server.js b/src/server.js new file mode 100644 index 00000000..be4333c8 --- /dev/null +++ b/src/server.js @@ -0,0 +1,7 @@ +import app from "./app.js"; + +const PORT = process.env.PORT || 3000; + +app.listen(PORT, () => { + console.log(`🚀 PiRC AI Oracle running on port ${PORT}`); +}); From d3532cb0aa1ae625efd69edc66b9ff847019e311 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 01:30:10 +0700 Subject: [PATCH 06/27] Create package.json --- package.json | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 package.json diff --git a/package.json b/package.json new file mode 100644 index 00000000..19cea033 --- /dev/null +++ b/package.json @@ -0,0 +1,16 @@ +{ + "health": { + "status": "degraded", + "txCount": 1200, + "ledger": 9500 + }, + "analysis": { + "risk": "HIGH", + "score": 80, + "insight": "⚠️ Network anomaly detected" + }, + "action": { + "action": "SWITCH_RPC", + "message": "Switching to backup node..." + } +} From 78a7fde8991cac8119bf5a81fd74a45a6a42a5d2 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 01:33:51 +0700 Subject: [PATCH 07/27] Create healthRoute.js --- routes/healthRoute.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 routes/healthRoute.js diff --git a/routes/healthRoute.js b/routes/healthRoute.js new file mode 100644 index 00000000..ef3194cf --- /dev/null +++ b/routes/healthRoute.js @@ -0,0 +1,22 @@ +import express from "express"; +import { getPiHealth } from "../services/piHealth.js"; +import { analyzeHealth } from "../oracle/aiOracle.js"; +import { takeAction } from "../engine/actionEngine.js"; + +const router = express.Router(); + +router.get("/health-check", async (req, res) => { + try { + const health = await getPiHealth(); + const analysis = analyzeHealth(health); + const action = takeAction(analysis); + + res.json({ health, analysis, action }); + } catch (err) { + res.status(500).json({ + error: "Failed to fetch health" + }); + } +}); + +export default router; From d784699e51017e8169a446f473a2a0e3b360f61a Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 01:35:08 +0700 Subject: [PATCH 08/27] Update actionEngine.js --- engine/actionEngine.js | 1 - 1 file changed, 1 deletion(-) diff --git a/engine/actionEngine.js b/engine/actionEngine.js index 83818607..3367e548 100644 --- a/engine/actionEngine.js +++ b/engine/actionEngine.js @@ -1,4 +1,3 @@ -// engine/actionEngine.js export function takeAction(analysis) { if (analysis.risk === "HIGH") { return { From dec0d419a7e3db2ea4975b33cb5fff906dcd1984 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 01:36:52 +0700 Subject: [PATCH 09/27] Update aiOracle.js --- oracle/aiOracle.js | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/oracle/aiOracle.js b/oracle/aiOracle.js index caeaeb9d..b0edb069 100644 --- a/oracle/aiOracle.js +++ b/oracle/aiOracle.js @@ -1,21 +1,11 @@ -// oracle/aiOracle.js export function analyzeHealth(health) { let riskScore = 0; let status = "SAFE"; - if (health.status !== "healthy") { - riskScore += 40; - } - - if (health.txCount && health.txCount > 1000) { - riskScore += 30; - } - - if (health.ledger && health.ledger < 10000) { - riskScore += 20; - } + if (health.status !== "healthy") riskScore += 40; + if (health.txCount > 1000) riskScore += 30; + if (health.ledger < 10000) riskScore += 20; - // AI-style classification if (riskScore > 70) status = "HIGH"; else if (riskScore > 40) status = "MEDIUM"; From 327093f6b7fc146dadcb1fce1ca889ec24e7c3a2 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 01:38:35 +0700 Subject: [PATCH 10/27] Update piHealth.js --- services/piHealth.js | 1 - 1 file changed, 1 deletion(-) diff --git a/services/piHealth.js b/services/piHealth.js index 055a602f..2206332a 100644 --- a/services/piHealth.js +++ b/services/piHealth.js @@ -1,4 +1,3 @@ -// services/piHealth.js import fetch from "node-fetch"; export async function getPiHealth() { From 5744e8bbc5d5a15d20cf8bd08ab0810c2b84c857 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 01:39:30 +0700 Subject: [PATCH 11/27] Update package.json --- package.json | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 19cea033..debdb201 100644 --- a/package.json +++ b/package.json @@ -1,16 +1,14 @@ { - "health": { - "status": "degraded", - "txCount": 1200, - "ledger": 9500 + "name": "pirc-ai-oracle", + "version": "1.0.0", + "description": "AI-powered health monitoring for Pi Testnet RPC", + "main": "src/app.js", + "type": "module", + "scripts": { + "start": "node src/app.js" }, - "analysis": { - "risk": "HIGH", - "score": 80, - "insight": "⚠️ Network anomaly detected" - }, - "action": { - "action": "SWITCH_RPC", - "message": "Switching to backup node..." + "dependencies": { + "express": "^4.18.2", + "node-fetch": "^3.3.2" } } From d69c38f52bb63d6f1799367fa9d624ef186da684 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 01:41:15 +0700 Subject: [PATCH 12/27] Update app.js --- src/app.js | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/app.js b/src/app.js index b9487d41..7f6ae575 100644 --- a/src/app.js +++ b/src/app.js @@ -1,20 +1,13 @@ import express from "express"; -import { getPiHealth } from "./services/piHealth.js"; -import { analyzeHealth } from "./oracle/aiOracle.js"; -import { takeAction } from "./engine/actionEngine.js"; +import healthRoute from "./routes/healthRoute.js"; const app = express(); +app.use(express.json()); -app.get("/health-check", async (req, res) => { - try { - const health = await getPiHealth(); - const analysis = analyzeHealth(health); - const action = takeAction(analysis); +app.use("/api", healthRoute); - res.json({ health, analysis, action }); - } catch { - res.status(500).json({ error: "Failed to fetch health" }); - } -}); +const PORT = process.env.PORT || 3000; -export default app; +app.listen(PORT, () => { + console.log(`🚀 PiRC AI Oracle running on port ${PORT}`); +}); From 88d459ceaac6c25dde60de2766efa4b506ec2a1c Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 01:42:30 +0700 Subject: [PATCH 13/27] Update ReadMe.md --- ReadMe.md | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/ReadMe.md b/ReadMe.md index 4a9dfa39..f3adc0cf 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -1 +1,56 @@ -See [PiRC1: Pi Ecosystem Token Design](./PiRC1/ReadMe.md) \ No newline at end of file +See [PiRC1: Pi Ecosystem Token Design](./PiRC1/ReadMe.md) + + +🚀 PiRC AI Oracle – Health Monitoring Engine + +Overview + +PiRC AI Oracle is an intelligent monitoring system for Pi Testnet RPC nodes. +It analyzes network health and automatically determines risk levels and system actions. + +Features + +- 🔍 Real-time RPC health monitoring ("getHealth") +- 🧠 AI-based risk analysis engine +- ⚡ Automated decision system (failover, throttling) +- 🌐 REST API integration + +Architecture + +Pi RPC → AI Oracle → Risk Engine → Action Engine → API + +API Endpoint + +GET /api/health-check + +Example Response + +{ + "health": { + "status": "degraded", + "txCount": 1200, + "ledger": 9500 + }, + "analysis": { + "risk": "HIGH", + "score": 80, + "insight": "⚠️ Network anomaly detected" + }, + "action": { + "action": "SWITCH_RPC", + "message": "Switching to backup node..." + } +} + +Installation + +npm install +npm start + +Vision + +To build a self-adaptive AI-powered monitoring layer for decentralized infrastructure. + +--- + +🔥 Built for Pi Network ecosystem developers From 0e0d3494bda72fd16ffb0c44941afde117f4abeb Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 01:45:58 +0700 Subject: [PATCH 14/27] Create rpcList.js --- src/config/rpcList.js | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/config/rpcList.js diff --git a/src/config/rpcList.js b/src/config/rpcList.js new file mode 100644 index 00000000..3b555d61 --- /dev/null +++ b/src/config/rpcList.js @@ -0,0 +1,5 @@ +export const RPC_ENDPOINTS = [ + "https://rpc.testnet.minepi.com", + "https://rpc-backup1.minepi.com", + "https://rpc-backup2.minepi.com" +]; From 2128abac90afb3b6cfb4b4fb1f8e6d6e2aac418e Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 01:46:54 +0700 Subject: [PATCH 15/27] Create rpcManager.js --- src/services/rpcManager.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/services/rpcManager.js diff --git a/src/services/rpcManager.js b/src/services/rpcManager.js new file mode 100644 index 00000000..8af76327 --- /dev/null +++ b/src/services/rpcManager.js @@ -0,0 +1,12 @@ +import { RPC_ENDPOINTS } from "../config/rpcList.js"; + +let currentIndex = 0; + +export function getCurrentRPC() { + return RPC_ENDPOINTS[currentIndex]; +} + +export function switchRPC() { + currentIndex = (currentIndex + 1) % RPC_ENDPOINTS.length; + return getCurrentRPC(); +} From cd02021eb9841164e0b52cd9db33eb6358181376 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 01:48:49 +0700 Subject: [PATCH 16/27] Update piHealth.js --- services/piHealth.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/services/piHealth.js b/services/piHealth.js index 2206332a..4221a352 100644 --- a/services/piHealth.js +++ b/services/piHealth.js @@ -1,7 +1,10 @@ import fetch from "node-fetch"; +import { getCurrentRPC } from "./rpcManager.js"; export async function getPiHealth() { - const res = await fetch("https://rpc.testnet.minepi.com", { + const rpc = getCurrentRPC(); + + const res = await fetch(rpc, { method: "POST", headers: { "Content-Type": "application/json" @@ -13,6 +16,5 @@ export async function getPiHealth() { }) }); - const data = await res.json(); - return data.result || data; + return res.json(); } From e368edb866c4e63852ae2ed8a3d04dcae3aafed1 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 01:49:49 +0700 Subject: [PATCH 17/27] Create anomalyModel.js --- src/ml/anomalyModel.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/ml/anomalyModel.js diff --git a/src/ml/anomalyModel.js b/src/ml/anomalyModel.js new file mode 100644 index 00000000..5d8f709b --- /dev/null +++ b/src/ml/anomalyModel.js @@ -0,0 +1,23 @@ +import * as tf from "@tensorflow/tfjs"; + +let model; + +export async function loadModel() { + model = tf.sequential(); + model.add(tf.layers.dense({ units: 8, inputShape: [2], activation: "relu" })); + model.add(tf.layers.dense({ units: 1, activation: "sigmoid" })); + + model.compile({ + optimizer: "adam", + loss: "binaryCrossentropy" + }); +} + +export function predictAnomaly(txCount, ledger) { + if (!model) return 0; + + const input = tf.tensor2d([[txCount, ledger]]); + const output = model.predict(input); + + return output.dataSync()[0]; +} From 1d8eb142ab7dbec29c5f9c04dda6e89d5b3df0fc Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 01:50:36 +0700 Subject: [PATCH 18/27] Create contractTrigger.js --- src/blockchain/contractTrigger.js | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/blockchain/contractTrigger.js diff --git a/src/blockchain/contractTrigger.js b/src/blockchain/contractTrigger.js new file mode 100644 index 00000000..26f56c46 --- /dev/null +++ b/src/blockchain/contractTrigger.js @@ -0,0 +1,10 @@ +import { triggerProtection } from "../blockchain/contractTrigger.js"; + +if (analysis.risk === "HIGH") { + await triggerProtection("PAUSE"); + + return { + action: "PAUSE_NETWORK", + message: "Smart contract paused" + }; +} From 6dd69c064182b5e0c21cee5adbcf8c709c004ec2 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 01:54:26 +0700 Subject: [PATCH 19/27] Create Dockerfile --- Dockerfile | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..06dbd449 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,17 @@ +# Base image +FROM node:18-alpine + +# Set working directory +WORKDIR /app + +# Copy files +COPY package*.json ./ +RUN npm install + +COPY . . + +# Expose port +EXPOSE 3000 + +# Start app +CMD ["npm", "start"] From 99a4b3952ae8178da27a177b152508e73fbeed81 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 01:56:02 +0700 Subject: [PATCH 20/27] Create deployment.yaml --- k8s/deployment.yaml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 k8s/deployment.yaml diff --git a/k8s/deployment.yaml b/k8s/deployment.yaml new file mode 100644 index 00000000..b27bce18 --- /dev/null +++ b/k8s/deployment.yaml @@ -0,0 +1,19 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: pirc-ai-oracle +spec: + replicas: 2 + selector: + matchLabels: + app: pirc-ai-oracle + template: + metadata: + labels: + app: pirc-ai-oracle + spec: + containers: + - name: pirc-ai-oracle + image: pirc-ai-oracle:latest + ports: + - containerPort: 3000 From 9c81f3884ce66f078acdd490a075206fd36f94b1 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 01:56:35 +0700 Subject: [PATCH 21/27] Create service.yaml --- k8s/service.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 k8s/service.yaml diff --git a/k8s/service.yaml b/k8s/service.yaml new file mode 100644 index 00000000..cf92120b --- /dev/null +++ b/k8s/service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: pirc-service +spec: + type: NodePort + selector: + app: pirc-ai-oracle + ports: + - port: 80 + targetPort: 3000 + nodePort: 30007 From 1aec46794992cb56d63e14888c71614fd5eb3848 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 01:57:41 +0700 Subject: [PATCH 22/27] Create oracleBridge.js --- src/blockchain/oracleBridge.js | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/blockchain/oracleBridge.js diff --git a/src/blockchain/oracleBridge.js b/src/blockchain/oracleBridge.js new file mode 100644 index 00000000..0415f958 --- /dev/null +++ b/src/blockchain/oracleBridge.js @@ -0,0 +1,9 @@ +export async function sendToBlockchain(data) { + console.log("📡 Sending AI result to blockchain..."); + + // pseudo-call + return { + txHash: "0xORACLE123", + data + }; +} From 5be085870675d537d301f2e3ee3f9a37eb305c2f Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 01:58:24 +0700 Subject: [PATCH 23/27] Create piContract.js --- src/blockchain/piContract.js | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/blockchain/piContract.js diff --git a/src/blockchain/piContract.js b/src/blockchain/piContract.js new file mode 100644 index 00000000..d0d47092 --- /dev/null +++ b/src/blockchain/piContract.js @@ -0,0 +1,8 @@ +export async function pauseNetwork() { + console.log("⛔ Pausing network via smart contract..."); + + return { + txHash: "0xPAUSE", + status: "success" + }; +} From 0b903edc66317365e00bc0b39b71f8d194b041e6 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 02:00:50 +0700 Subject: [PATCH 24/27] Create metrics.js --- src/routes/metrics.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/routes/metrics.js diff --git a/src/routes/metrics.js b/src/routes/metrics.js new file mode 100644 index 00000000..37961944 --- /dev/null +++ b/src/routes/metrics.js @@ -0,0 +1,15 @@ +import express from "express"; + +const router = express.Router(); + +let latestData = {}; + +export function updateMetrics(data) { + latestData = data; +} + +router.get("/metrics", (req, res) => { + res.json(latestData); +}); + +export default router; From 92273be0fd55c03be24979dc2cdd4d7008124c44 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 02:03:14 +0700 Subject: [PATCH 25/27] Update app.js --- src/app.js | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/src/app.js b/src/app.js index 7f6ae575..2b082c6f 100644 --- a/src/app.js +++ b/src/app.js @@ -1,13 +1,38 @@ import express from "express"; -import healthRoute from "./routes/healthRoute.js"; +import { getPiHealth } from "./services/piHealth.js"; +import { analyzeHealth } from "./oracle/aiOracle.js"; +import { takeAction } from "./engine/actionEngine.js"; + +// import metrics +import metricsRoute, { updateMetrics } from "./routes/metrics.js"; const app = express(); + app.use(express.json()); -app.use("/api", healthRoute); +// register endpoint metrics +app.use("/metrics", metricsRoute); -const PORT = process.env.PORT || 3000; +// endpoint utama +app.get("/health-check", async (req, res) => { + try { + const health = await getPiHealth(); + const analysis = analyzeHealth(health); + const action = await takeAction(analysis); -app.listen(PORT, () => { - console.log(`🚀 PiRC AI Oracle running on port ${PORT}`); + // update metrics DI SINI (bukan di luar) + updateMetrics({ health, analysis, action }); + + res.json({ + health, + analysis, + action + }); + } catch (err) { + res.status(500).json({ + error: "Failed to fetch health" + }); + } }); + +export default app; From 3f6099988012ff4bf901a2f5496ff9df4a3ed378 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 02:08:52 +0700 Subject: [PATCH 26/27] Create telegramAlert.js --- src/alerts/telegramAlert.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/alerts/telegramAlert.js diff --git a/src/alerts/telegramAlert.js b/src/alerts/telegramAlert.js new file mode 100644 index 00000000..f87dd13c --- /dev/null +++ b/src/alerts/telegramAlert.js @@ -0,0 +1,22 @@ +import fetch from "node-fetch"; + +const BOT_TOKEN = process.env.TELEGRAM_BOT_TOKEN; +const CHAT_ID = process.env.TELEGRAM_CHAT_ID; + +export async function sendTelegramAlert(message) { + if (!BOT_TOKEN || !CHAT_ID) return; + + const url = `https://api.telegram.org/bot${BOT_TOKEN}/sendMessage`; + + await fetch(url, { + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify({ + chat_id: CHAT_ID, + text: message, + parse_mode: "Markdown" + }) + }); +} From c1b4c2c6e542b977ad7f09e590a4e98e1f8eb66e Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 02:13:16 +0700 Subject: [PATCH 27/27] Update actionEngine.js --- engine/actionEngine.js | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/engine/actionEngine.js b/engine/actionEngine.js index 3367e548..966f9418 100644 --- a/engine/actionEngine.js +++ b/engine/actionEngine.js @@ -1,11 +1,30 @@ -export function takeAction(analysis) { +import { sendTelegramAlert } from "../alerts/telegramAlert.js"; +import { switchRPC } from "../services/rpcManager.js"; +import { triggerProtection } from "../blockchain/contractTrigger.js"; + +export async function takeAction(analysis) { + // HIGH RISK if (analysis.risk === "HIGH") { + // kirim alert + await sendTelegramAlert( + ` *Pi Network Alert*\nRisk: HIGH\nScore: ${analysis.score}\n${analysis.insight}` + ); + + // switch RPC + const newRpc = switchRPC(); + + // trigger protection (optional) + await triggerProtection("PAUSE"); + return { - action: "SWITCH_RPC", - message: "Switching to backup node..." + action: "EMERGENCY_MODE", + rpc: newRpc, + protection: "ENABLED", + message: "High risk detected: RPC switched & protection activated" }; } + // MEDIUM RISK if (analysis.risk === "MEDIUM") { return { action: "THROTTLE", @@ -13,6 +32,7 @@ export function takeAction(analysis) { }; } + // SAFE return { action: "NORMAL", message: "All systems stable"