From 6219e3bf187cdeac20ab36486a56708960266242 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Mon, 30 Mar 2026 09:37:17 +0700 Subject: [PATCH 01/62] Expand ReadMe with PiRC-AI project details Added project overview and core innovations for PiRC-AI. --- ReadMe.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/ReadMe.md b/ReadMe.md index 4a9dfa39..8d37fb62 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -1 +1,19 @@ -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: Attention-Based Token Economy for Pi Network + +PiRC-AI is an extended implementation of the Pi Request for Comment (PiRC), introducing an attention-centered token economic model designed for the AI era. + +As automation reduces the role of traditional labor, this project explores a new paradigm where verified human attention becomes a core economic resource. + +## Core Innovations +- Attention-based reward system (Attention Mining) +- AI-powered human verification (anti-bot & Sybil resistance) +- Token economy with revenue-backed sinks +- Simulation-driven tokenomics validation + +## Vision +Transitioning from a labor-centered economy to an attention-centered economy within the Pi ecosystem. + +## Status +Experimental design + implementation layer (not official Pi Network code) From 3e6c1778da347d4926441b7a48d93b1810b93499 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Mon, 30 Mar 2026 09:39:05 +0700 Subject: [PATCH 02/62] Add architecture overview to ReadMe.md Added architecture overview for PiRC-AI attention economy model. --- ReadMe.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ReadMe.md b/ReadMe.md index 8d37fb62..f0fc66a4 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -17,3 +17,15 @@ Transitioning from a labor-centered economy to an attention-centered economy wit ## Status Experimental design + implementation layer (not official Pi Network code) +## Architecture Overview + +PiRC-AI introduces a three-layer attention economy model: + +1. Attention Contribution + Users generate verifiable attention through interaction. + +2. Attention Verification + AI-based systems validate human authenticity and filter bots. + +3. Attention Monetization + Attention is converted into tokenized value backed by real economic sinks (ads, data, AI training). From e3693c9980c0ca71b441ee850c0a4250eb1fcc6f Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Mon, 30 Mar 2026 09:41:42 +0700 Subject: [PATCH 03/62] Expand ReadMe with Token Model and challenges Added sections on Token Model, Simulation, and Risks & Challenges. --- ReadMe.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/ReadMe.md b/ReadMe.md index f0fc66a4..5d53201b 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -29,3 +29,31 @@ PiRC-AI introduces a three-layer attention economy model: 3. Attention Monetization Attention is converted into tokenized value backed by real economic sinks (ads, data, AI training). +## Token Model + +The reward mechanism follows a simple but robust formula: + +R = A × Q × V + +Where: +- A = Attention (time/engagement) +- Q = Quality score (interaction depth) +- V = Verification score (human authenticity) + +This ensures fair distribution and resistance to manipulation. +## Simulation + +The project includes simulation tools to evaluate: +- Token emission dynamics +- Network effects +- Inflation control + +Future work includes AI-driven optimization of token distribution. +## Risks & Challenges + +- Sybil attacks (multi-account abuse) +- Fake attention generation +- Centralization of verification AI +- Token inflation without sufficient sinks + +These risks are actively considered in the design. From 1375d129799b06c55019d0e4c64861a9c9b0b53f Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Mon, 30 Mar 2026 09:43:51 +0700 Subject: [PATCH 04/62] Add Attention Triad framework overview and details Introduced the Attention Triad framework detailing its components: Contribution, Verification, and Monetization. This framework aims to address value extraction imbalances in digital platforms by ensuring fair rewards for user attention. --- design/attention-triad.md | 135 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 design/attention-triad.md diff --git a/design/attention-triad.md b/design/attention-triad.md new file mode 100644 index 00000000..12fcf2e7 --- /dev/null +++ b/design/attention-triad.md @@ -0,0 +1,135 @@ +# Attention Triad + +## Overview + +The Attention Triad is a core conceptual framework in PiRC-AI that decomposes the attention economy into three distinct but interconnected layers: + +1. Attention Contribution +2. Attention Verification +3. Attention Monetization + +This separation makes visible the inefficiencies and value gaps in existing digital platforms, where user attention is often captured but not fairly rewarded. + +--- + +## 1. Attention Contribution + +### Definition +Attention Contribution refers to the measurable input of human attention within the ecosystem. + +### Examples +- Time spent viewing content +- User interactions (clicks, likes, comments) +- Cognitive engagement (scroll depth, dwell time) + +### Key Insight +In traditional platforms, users generate attention but do not directly receive proportional economic value. + +In PiRC-AI: +> Attention becomes a measurable and rewardable resource. + +--- + +## 2. Attention Verification + +### Definition +Attention Verification ensures that contributed attention is authentic, human, and meaningful. + +### Purpose +To prevent: +- Bot activity +- Fake engagement +- Sybil attacks (multi-account abuse) + +### Methods +- Behavioral analysis (interaction patterns) +- AI-based anomaly detection +- Reputation systems +- Optional identity/KYC integration + +### Verification Score (V) +Each attention event is assigned a verification score: + +V ∈ [0, 1] + +Where: +- 0 = invalid (bot/fake) +- 1 = fully verified human attention + +--- + +## 3. Attention Monetization + +### Definition +Attention Monetization converts verified attention into economic value. + +### Mechanisms +- Advertising (attention sold to advertisers) +- AI training data (human-labeled interaction) +- Marketplace exposure +- Data insights (aggregated, privacy-aware) + +### Token Integration +Verified attention is rewarded via tokens: + +Reward ∝ Attention × Quality × Verification + +This ensures that only valuable and authentic attention is monetized. + +--- + +## Attention Flow + +The full lifecycle of attention in PiRC-AI: + +User → Attention Contribution → Verification → Monetization → Token Reward + +--- + +## Contribution Gap (Problem Statement) + +In current digital platforms: +- Users contribute attention +- Platforms monetize it +- Users receive little or no direct compensation + +This creates a **value extraction imbalance**. + +PiRC-AI addresses this by: +- Making attention measurable +- Verifying authenticity +- Redistributing value via token economics + +--- + +## Design Principles + +1. Fairness + Users should receive proportional rewards for their attention. + +2. Verifiability + Only real human attention should be rewarded. + +3. Sustainability + Token rewards must be backed by real economic sinks. + +4. Scalability + The system must function across millions of users. + +--- + +## Implications + +The Attention Triad enables: +- A shift from labor-based to attention-based income +- New forms of participation in digital economies +- Alignment between users, platforms, and value creation + +--- + +## Future Work + +- Advanced AI verification models +- Cross-platform attention aggregation +- Privacy-preserving attention tracking +- Integration with decentralized identity systems From bd7622743db035ed0d2adac713e45c20fa0d4bc3 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Mon, 30 Mar 2026 09:45:09 +0700 Subject: [PATCH 05/62] Implement attention economy simulation model --- simulations/attention_model.py | 102 +++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 simulations/attention_model.py diff --git a/simulations/attention_model.py b/simulations/attention_model.py new file mode 100644 index 00000000..6af12edd --- /dev/null +++ b/simulations/attention_model.py @@ -0,0 +1,102 @@ +# simulations/attention_model.py + +import random +import statistics + +class User: + def __init__(self, is_bot=False): + self.is_bot = is_bot + + def generate_attention(self): + if self.is_bot: + # bot: high activity but low quality + A = random.uniform(5, 15) + Q = random.uniform(0.1, 0.5) + V = random.uniform(0.0, 0.3) + else: + # human: moderate activity, higher quality + A = random.uniform(2, 10) + Q = random.uniform(0.5, 1.5) + V = random.uniform(0.7, 1.0) + + return A, Q, V + + +class AttentionEconomy: + def __init__(self, users=1000, bot_ratio=0.2, max_daily_emission=10000): + self.users = users + self.bot_ratio = bot_ratio + self.max_daily_emission = max_daily_emission + self.population = self._create_population() + + def _create_population(self): + population = [] + for _ in range(self.users): + if random.random() < self.bot_ratio: + population.append(User(is_bot=True)) + else: + population.append(User(is_bot=False)) + return population + + def calculate_reward(self, A, Q, V): + return A * Q * V + + def run_epoch(self): + rewards = [] + raw_rewards = [] + + for user in self.population: + A, Q, V = user.generate_attention() + r = self.calculate_reward(A, Q, V) + raw_rewards.append(r) + + total_raw = sum(raw_rewards) + + # normalize to max emission (anti-inflation control) + if total_raw > 0: + scale = self.max_daily_emission / total_raw + else: + scale = 0 + + for r in raw_rewards: + rewards.append(r * scale) + + return rewards + + def simulate(self, days=30): + history = [] + + for day in range(days): + rewards = self.run_epoch() + total = sum(rewards) + avg = statistics.mean(rewards) + max_r = max(rewards) + + history.append({ + "day": day + 1, + "total_emission": total, + "avg_reward": avg, + "max_reward": max_r + }) + + return history + + +if __name__ == "__main__": + sim = AttentionEconomy( + users=1000, + bot_ratio=0.3, # coba ubah untuk test ketahanan sistem + max_daily_emission=10000 + ) + + results = sim.simulate(days=30) + + print("=== Simulation Results ===\n") + + for day in results: + print( + f"Day {day['day']}: " + f"Total={day['total_emission']:.2f}, " + f"Avg={day['avg_reward']:.4f}, " + f"Max={day['max_reward']:.2f}" + ) From a884fc33c4be0c45da8adef44fd1bafec995b5f0 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Mon, 30 Mar 2026 09:47:35 +0700 Subject: [PATCH 06/62] Initialize Cargo.toml for reward_engine package --- contracts/reward_engine/Cargo.toml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 contracts/reward_engine/Cargo.toml diff --git a/contracts/reward_engine/Cargo.toml b/contracts/reward_engine/Cargo.toml new file mode 100644 index 00000000..d1c18f6c --- /dev/null +++ b/contracts/reward_engine/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "reward_engine" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +soroban-sdk = "20.3.0" From e3f5a94a111d2364d208cae0c79422f3a4c014b7 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Mon, 30 Mar 2026 09:48:56 +0700 Subject: [PATCH 07/62] Add RewardEngine contract with reward calculations Implement core reward calculation and normalization methods. --- contracts/reward_engine/lib.rs | 106 +++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 contracts/reward_engine/lib.rs diff --git a/contracts/reward_engine/lib.rs b/contracts/reward_engine/lib.rs new file mode 100644 index 00000000..0bf01ef7 --- /dev/null +++ b/contracts/reward_engine/lib.rs @@ -0,0 +1,106 @@ +#![no_std] + +use soroban_sdk::{contract, contractimpl, Env, Symbol, symbol_short, Vec}; + +#[contract] +pub struct RewardEngine; + +#[contractimpl] +impl RewardEngine { + + // ========================= + // Core Reward Calculation + // ========================= + pub fn calculate_reward( + _env: Env, + attention: u64, + quality: u64, + verification: u64, + ) -> u64 { + // Simple multiplication model + attention * quality * verification + } + + // ========================= + // Batch Calculation (optional) + // ========================= + pub fn batch_rewards( + env: Env, + attentions: Vec, + qualities: Vec, + verifications: Vec, + ) -> Vec { + + let mut rewards = Vec::new(&env); + + let len = attentions.len(); + + for i in 0..len { + let a = attentions.get(i).unwrap(); + let q = qualities.get(i).unwrap(); + let v = verifications.get(i).unwrap(); + + let r = a * q * v; + rewards.push_back(r); + } + + rewards + } + + // ========================= + // Normalization (anti inflation) + // ========================= + pub fn normalize_rewards( + env: Env, + rewards: Vec, + max_emission: u64, + ) -> Vec { + + let mut total: u64 = 0; + + for r in rewards.iter() { + total += r; + } + + let mut normalized = Vec::new(&env); + + if total == 0 { + return normalized; + } + + for r in rewards.iter() { + let scaled = (r * max_emission) / total; + normalized.push_back(scaled); + } + + normalized + } + + // ========================= + // Simple Anti-Bot Filter + // ========================= + pub fn apply_verification_threshold( + env: Env, + rewards: Vec, + verifications: Vec, + threshold: u64, + ) -> Vec { + + let mut filtered = Vec::new(&env); + + let len = rewards.len(); + + for i in 0..len { + let r = rewards.get(i).unwrap(); + let v = verifications.get(i).unwrap(); + + if v >= threshold { + filtered.push_back(r); + } else { + filtered.push_back(0); + } + } + + filtered + } +} From 8b4060db8d79916c9dea8984b338cc88bb957ef4 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Mon, 30 Mar 2026 09:51:32 +0700 Subject: [PATCH 08/62] Implement RewardEngine contract with reward functions --- contracts/reward_engine/src/lib.rs | 82 ++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 contracts/reward_engine/src/lib.rs diff --git a/contracts/reward_engine/src/lib.rs b/contracts/reward_engine/src/lib.rs new file mode 100644 index 00000000..c37aea9c --- /dev/null +++ b/contracts/reward_engine/src/lib.rs @@ -0,0 +1,82 @@ +#![no_std] + +use soroban_sdk::{ + contract, contractimpl, Env, Address, Vec, Map +}; + +#[contract] +pub struct RewardEngine; + +#[contractimpl] +impl RewardEngine { + + // ========================= + // Storage Keys + // ========================= + fn balances(e: &Env) -> Map { + e.storage().instance().get(&"balances").unwrap_or(Map::new(e)) + } + + fn set_balances(e: &Env, map: Map) { + e.storage().instance().set(&"balances", &map); + } + + // ========================= + // Reward Formula + // ========================= + pub fn calculate_reward( + _env: Env, + attention: u64, + quality: u64, + verification: u64, + ) -> u64 { + attention * quality * verification + } + + // ========================= + // Mint Token (core) + // ========================= + pub fn mint( + env: Env, + user: Address, + reward: u64, + ) { + let mut balances = Self::balances(&env); + + let current = balances.get(user.clone()).unwrap_or(0); + balances.set(user, current + reward); + + Self::set_balances(&env, balances); + } + + // ========================= + // Batch Mint + // ========================= + pub fn distribute_rewards( + env: Env, + users: Vec
, + rewards: Vec, + ) { + let mut balances = Self::balances(&env); + + let len = users.len(); + + for i in 0..len { + let user = users.get(i).unwrap(); + let reward = rewards.get(i).unwrap(); + + let current = balances.get(user.clone()).unwrap_or(0); + balances.set(user, current + reward); + } + + Self::set_balances(&env, balances); + } + + // ========================= + // View Balance + // ========================= + pub fn get_balance(env: Env, user: Address) -> u64 { + let balances = Self::balances(&env); + balances.get(user).unwrap_or(0) + } +} From 517553c7f707457a0e629c34e444047906413529 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Mon, 30 Mar 2026 09:52:22 +0700 Subject: [PATCH 09/62] Implement AI verification and user generation functions --- simulations/ai_verification.py | 44 ++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 simulations/ai_verification.py diff --git a/simulations/ai_verification.py b/simulations/ai_verification.py new file mode 100644 index 00000000..5adcbeaf --- /dev/null +++ b/simulations/ai_verification.py @@ -0,0 +1,44 @@ +import random + +def ai_verification_score(attention, quality, behavior_score): + """ + Simulate AI-based human verification + """ + + # heuristic scoring + score = ( + 0.4 * (attention / 10) + + 0.4 * quality + + 0.2 * behavior_score + ) + + # clamp 0–1 + return max(0, min(1, score)) + + +def detect_bot_pattern(attention, quality): + if attention > 12 and quality < 0.4: + return True + return False + + +def generate_user(): + is_bot = random.random() < 0.3 + + if is_bot: + attention = random.uniform(8, 15) + quality = random.uniform(0.1, 0.5) + behavior = random.uniform(0.1, 0.3) + else: + attention = random.uniform(2, 10) + quality = random.uniform(0.6, 1.2) + behavior = random.uniform(0.6, 1.0) + + verification = ai_verification_score(attention, quality, behavior) + + return { + "attention": attention, + "quality": quality, + "verification": verification, + "is_bot": is_bot + } From 99149d87e773950b7cbd4c6da51ac2ed5673df16 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Mon, 30 Mar 2026 09:53:00 +0700 Subject: [PATCH 10/62] Implement real-time data updates in App component --- dashboard/web-ui/src/App.js | 38 +++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 dashboard/web-ui/src/App.js diff --git a/dashboard/web-ui/src/App.js b/dashboard/web-ui/src/App.js new file mode 100644 index 00000000..0464ddf3 --- /dev/null +++ b/dashboard/web-ui/src/App.js @@ -0,0 +1,38 @@ +import React, { useState, useEffect } from "react"; + +function App() { + const [data, setData] = useState([]); + + useEffect(() => { + const interval = setInterval(() => { + const newData = { + attention: Math.random() * 10, + quality: Math.random(), + verification: Math.random(), + }; + + newData.reward = + newData.attention * + newData.quality * + newData.verification; + + setData((prev) => [...prev.slice(-20), newData]); + }, 1000); + + return () => clearInterval(interval); + }, []); + + return ( +
+

PiRC-AI Dashboard

+ + {data.map((d, i) => ( +
+ Reward: {d.reward.toFixed(2)} +
+ ))} +
+ ); +} + +export default App; From 6b48d6c0f62000fd94fa38e0452cd4cfe81d141e Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Mon, 30 Mar 2026 09:53:39 +0700 Subject: [PATCH 11/62] Implement full simulation for user rewards calculation --- simulations/full_pipeline.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 simulations/full_pipeline.py diff --git a/simulations/full_pipeline.py b/simulations/full_pipeline.py new file mode 100644 index 00000000..d8a20f48 --- /dev/null +++ b/simulations/full_pipeline.py @@ -0,0 +1,27 @@ +from attention_model import AttentionEconomy +from ai_verification import generate_user + +def run_full_simulation(users=1000): + rewards = [] + + for _ in range(users): + u = generate_user() + + reward = ( + u["attention"] * + u["quality"] * + u["verification"] + ) + + rewards.append(reward) + + total = sum(rewards) + + print("Total Rewards:", total) + print("Avg Reward:", total / users) + + return rewards + + +if __name__ == "__main__": + run_full_simulation() From 9bd9fb8831ca69504027b2c5fb3f4217649447ac Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Mon, 30 Mar 2026 09:56:20 +0700 Subject: [PATCH 12/62] Add feature extraction function for user data --- simulations/ai_model/features.py | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 simulations/ai_model/features.py diff --git a/simulations/ai_model/features.py b/simulations/ai_model/features.py new file mode 100644 index 00000000..9363f2e8 --- /dev/null +++ b/simulations/ai_model/features.py @@ -0,0 +1,8 @@ +def extract_features(user): + return [ + user["attention"], + user["quality"], + user["behavior"], + user["session_time"], + user["interaction_rate"], + ] From 2d3e5838f169cb97a14768d5b125554030b375c8 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Mon, 30 Mar 2026 09:56:56 +0700 Subject: [PATCH 13/62] Add training script for AI verification model Implemented a model training script that generates a dataset and trains a Random Forest classifier for AI verification. --- simulations/ai_model/train_model.py | 51 +++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 simulations/ai_model/train_model.py diff --git a/simulations/ai_model/train_model.py b/simulations/ai_model/train_model.py new file mode 100644 index 00000000..d81f93ac --- /dev/null +++ b/simulations/ai_model/train_model.py @@ -0,0 +1,51 @@ +import random +import numpy as np +from sklearn.ensemble import RandomForestClassifier +import joblib + +def generate_dataset(n=5000): + X = [] + y = [] + + for _ in range(n): + is_bot = random.random() < 0.3 + + if is_bot: + attention = random.uniform(8, 15) + quality = random.uniform(0.1, 0.5) + behavior = random.uniform(0.1, 0.3) + session_time = random.uniform(1, 3) + interaction_rate = random.uniform(5, 10) + else: + attention = random.uniform(2, 10) + quality = random.uniform(0.6, 1.2) + behavior = random.uniform(0.6, 1.0) + session_time = random.uniform(5, 15) + interaction_rate = random.uniform(1, 5) + + X.append([ + attention, + quality, + behavior, + session_time, + interaction_rate + ]) + + y.append(0 if is_bot else 1) + + return np.array(X), np.array(y) + + +def train(): + X, y = generate_dataset() + + model = RandomForestClassifier(n_estimators=100) + model.fit(X, y) + + joblib.dump(model, "ai_verification_model.pkl") + + print("Model trained & saved!") + + +if __name__ == "__main__": + train() From 53f1fad008cd37483a0b980a0d3b2330a90e77aa Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Mon, 30 Mar 2026 09:57:31 +0700 Subject: [PATCH 14/62] Add inference script for AI model verification --- simulations/ai_model/inference.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 simulations/ai_model/inference.py diff --git a/simulations/ai_model/inference.py b/simulations/ai_model/inference.py new file mode 100644 index 00000000..405e2a5e --- /dev/null +++ b/simulations/ai_model/inference.py @@ -0,0 +1,17 @@ +import joblib +import numpy as np + +model = joblib.load("ai_verification_model.pkl") + +def predict_verification(user): + features = np.array([[ + user["attention"], + user["quality"], + user["behavior"], + user["session_time"], + user["interaction_rate"] + ]]) + + prob = model.predict_proba(features)[0][1] # probability human + + return prob From 1c1b38fdb169931f2f7a39ce7477d1589dd366e6 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Mon, 30 Mar 2026 09:58:06 +0700 Subject: [PATCH 15/62] Add user simulation with reward calculation Implement a simulation that generates user data and calculates rewards based on predictions. --- simulations/full_pipeline_ai.py | 34 +++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 simulations/full_pipeline_ai.py diff --git a/simulations/full_pipeline_ai.py b/simulations/full_pipeline_ai.py new file mode 100644 index 00000000..774992d3 --- /dev/null +++ b/simulations/full_pipeline_ai.py @@ -0,0 +1,34 @@ +from ai_model.inference import predict_verification +import random + +def generate_user(): + return { + "attention": random.uniform(1, 15), + "quality": random.uniform(0.1, 1.2), + "behavior": random.uniform(0.1, 1.0), + "session_time": random.uniform(1, 15), + "interaction_rate": random.uniform(1, 10), + } + +def run_simulation(n=1000): + rewards = [] + + for _ in range(n): + user = generate_user() + + V = predict_verification(user) + + reward = ( + user["attention"] * + user["quality"] * + V + ) + + rewards.append(reward) + + print("Total:", sum(rewards)) + print("Avg:", sum(rewards) / n) + + +if __name__ == "__main__": + run_simulation() From a113c7ebd24e67ae6609dc715e71e2177dd4a71a Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Mon, 30 Mar 2026 10:00:54 +0700 Subject: [PATCH 16/62] Implement AI verification endpoint with FastAPI --- oracle/ai_oracle_server.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 oracle/ai_oracle_server.py diff --git a/oracle/ai_oracle_server.py b/oracle/ai_oracle_server.py new file mode 100644 index 00000000..a172ac9a --- /dev/null +++ b/oracle/ai_oracle_server.py @@ -0,0 +1,24 @@ +from fastapi import FastAPI +import joblib +import numpy as np + +app = FastAPI() + +model = joblib.load("simulations/ai_model/ai_verification_model.pkl") + + +@app.post("/verify") +def verify(user: dict): + features = np.array([[ + user["attention"], + user["quality"], + user["behavior"], + user["session_time"], + user["interaction_rate"] + ]]) + + prob = model.predict_proba(features)[0][1] + + return { + "verification_score": float(prob) + } From f0d432fe76140ca032ff4538e22906d150380e3d Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Mon, 30 Mar 2026 10:01:29 +0700 Subject: [PATCH 17/62] Implement user verification function in client.py --- oracle/client.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 oracle/client.py diff --git a/oracle/client.py b/oracle/client.py new file mode 100644 index 00000000..20e89fad --- /dev/null +++ b/oracle/client.py @@ -0,0 +1,20 @@ +import requests + +def get_verification(user): + res = requests.post( + "http://localhost:8000/verify", + json=user + ) + return res.json()["verification_score"] + + +if __name__ == "__main__": + user = { + "attention": 8, + "quality": 0.9, + "behavior": 0.8, + "session_time": 10, + "interaction_rate": 3 + } + + print(get_verification(user)) From ffabd550953b103ac4a09b8180dbf09856223e71 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Mon, 30 Mar 2026 10:08:59 +0700 Subject: [PATCH 18/62] Implement user processing and reward minting Added a relayer script to process user data and mint rewards based on verification scores. --- oracle/relayer.py | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 oracle/relayer.py diff --git a/oracle/relayer.py b/oracle/relayer.py new file mode 100644 index 00000000..a8f7ad87 --- /dev/null +++ b/oracle/relayer.py @@ -0,0 +1,47 @@ +import requests + +# dummy contract interface (sementara) +class ContractClient: + def mint(self, user_address, reward): + print(f"[CONTRACT] Mint {reward} to {user_address}") + +contract = ContractClient() + + +def process_user(user, user_address): + # 1. Call AI Oracle + res = requests.post( + "http://localhost:8000/verify", + json=user + ) + + V = res.json()["verification_score"] + + # 2. Calculate reward + reward = user["attention"] * user["quality"] * V + + # 3. Send to contract + contract.mint(user_address, reward) + + return { + "verification": V, + "reward": reward + } + + +if __name__ == "__main__": + user = { + "attention": 8, + "quality": 0.9, + "behavior": 0.8, + "session_time": 10, + "interaction_rate": 3 + } + + result = process_user(user, "USER_1") + print(result) + balances = {} + +def update_balance(user_address, reward): + balances[user_address] = balances.get(user_address, 0) + reward + return balances[user_address] From 37f42b76b3e36bb84e8bc76834a823315474c77c Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Mon, 30 Mar 2026 10:09:45 +0700 Subject: [PATCH 19/62] Implement FastAPI endpoint for user processing --- oracle/api.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 oracle/api.py diff --git a/oracle/api.py b/oracle/api.py new file mode 100644 index 00000000..6f5b3629 --- /dev/null +++ b/oracle/api.py @@ -0,0 +1,13 @@ +from fastapi import FastAPI +from relayer import process_user + +app = FastAPI() + +@app.post("/process") +def process(data: dict): + user = data["user"] + address = data["address"] + + result = process_user(user, address) + + return result From 180fa7986affc9f690584d29e77da5d1118548b2 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Mon, 30 Mar 2026 10:12:13 +0700 Subject: [PATCH 20/62] Refactor App component to send user data and display result --- dashboard/web-ui/src/App.js | 62 +++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/dashboard/web-ui/src/App.js b/dashboard/web-ui/src/App.js index 0464ddf3..185e9f6e 100644 --- a/dashboard/web-ui/src/App.js +++ b/dashboard/web-ui/src/App.js @@ -1,36 +1,46 @@ -import React, { useState, useEffect } from "react"; +import React, { useState } from "react"; function App() { - const [data, setData] = useState([]); - - useEffect(() => { - const interval = setInterval(() => { - const newData = { - attention: Math.random() * 10, - quality: Math.random(), - verification: Math.random(), - }; - - newData.reward = - newData.attention * - newData.quality * - newData.verification; - - setData((prev) => [...prev.slice(-20), newData]); - }, 1000); - - return () => clearInterval(interval); - }, []); + const [result, setResult] = useState(null); + + const sendData = async () => { + const user = { + attention: Math.random() * 10, + quality: Math.random(), + behavior: Math.random(), + session_time: Math.random() * 10, + interaction_rate: Math.random() * 5, + }; + + const res = await fetch("http://localhost:8000/process", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + user: user, + address: "USER_1", + }), + }); + + const data = await res.json(); + setResult(data); + }; return (
-

PiRC-AI Dashboard

+

PiRC-AI Live Dashboard

+ + - {data.map((d, i) => ( -
- Reward: {d.reward.toFixed(2)} + {result && ( +
+

Verification: {result.verification.toFixed(3)}

+

Reward: {result.reward.toFixed(3)}

- ))} + )}
); } From e09e36d3998bdc211ec37a1f318530ca1582a8b1 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Mon, 30 Mar 2026 10:14:15 +0700 Subject: [PATCH 21/62] Add connectWallet function to handle wallet connection --- dashboard/web-ui/src/wallet.js | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 dashboard/web-ui/src/wallet.js diff --git a/dashboard/web-ui/src/wallet.js b/dashboard/web-ui/src/wallet.js new file mode 100644 index 00000000..da19d352 --- /dev/null +++ b/dashboard/web-ui/src/wallet.js @@ -0,0 +1,9 @@ +export async function connectWallet() { + if (!window.freighterApi) { + alert("Install Freighter Wallet"); + return null; + } + + const publicKey = await window.freighterApi.getPublicKey(); + return publicKey; +} From 683e8707560689955b8468ab819dfcda10c67427 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Mon, 30 Mar 2026 10:15:48 +0700 Subject: [PATCH 22/62] Add wallet connection and data submission functionality --- App.js | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 App.js diff --git a/App.js b/App.js new file mode 100644 index 00000000..85ec68c2 --- /dev/null +++ b/App.js @@ -0,0 +1,73 @@ +import React, { useState } from "react"; +import { connectWallet, signMessage } from "./wallet"; + +function App() { + const [wallet, setWallet] = useState(null); + const [result, setResult] = useState(null); + + const handleConnect = async () => { + const addr = await connectWallet(); + setWallet(addr); + }; + + const sendData = async () => { + if (!wallet) { + alert("Connect wallet first"); + return; + } + + const user = { + attention: Math.random() * 10, + quality: Math.random(), + behavior: Math.random(), + session_time: Math.random() * 10, + interaction_rate: Math.random() * 5, + }; + + const message = JSON.stringify(user); + const signature = await signMessage(message); + + const res = await fetch("http://localhost:8000/process", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + user, + address: wallet, + signature + }), + }); + + const data = await res.json(); + setResult(data); + }; + + return ( +
+

PiRC-AI Wallet Dashboard

+ + {!wallet ? ( + + ) : ( +

Wallet: {wallet}

+ )} + + + + {result && ( +
+

Verification: {result.verification.toFixed(3)}

+

Reward: {result.reward.toFixed(3)}

+

Balance: {result.balance.toFixed(3)}

+
+ )} +
+ ); +} + +export default App; From b955c99dcf82d50ff85e5f1a0a8deec206e628f8 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Mon, 30 Mar 2026 10:16:40 +0700 Subject: [PATCH 23/62] Add signature verification function --- oracle/api.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/oracle/api.py b/oracle/api.py index 6f5b3629..901b80d6 100644 --- a/oracle/api.py +++ b/oracle/api.py @@ -11,3 +11,15 @@ def process(data: dict): result = process_user(user, address) return result + + +from nacl.signing import VerifyKey +import base64 + +def verify_signature(address, message, signature): + try: + verify_key = VerifyKey(bytes.fromhex(address)) + verify_key.verify(message.encode(), base64.b64decode(signature)) + return True + except: + return False From 9b1d3d0a87fad35b4e81057ebb7922c67e88272b Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Wed, 1 Apr 2026 09:42:58 +0700 Subject: [PATCH 24/62] Add RPC call implementation in test.js Implement RPC call functionality to interact with the API. --- test.js | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 test.js diff --git a/test.js b/test.js new file mode 100644 index 00000000..bbbd32ea --- /dev/null +++ b/test.js @@ -0,0 +1,42 @@ +import fetch from "node-fetch"; + +const RPC_URL = "https://rpc.testnet.minepi.com"; + +async function callRPC(method, params = []) { + try { + const res = await fetch(RPC_URL, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: Date.now(), + method, + params, + }), + }); + + const data = await res.json(); + return data.result; + } catch (err) { + console.error("Error:", err.message); + } +} + +const methods = [ + "getHealth", + "getLatestLedger", + "getVersion" +]; + +async function main() { + for (const m of methods) { + const res = await callRPC(m); + console.log("Method:", m); + console.log("Result:", res); + console.log("------------"); + } +} + +main(); From 971e16e4f6f727fe56ed5bd79d7d39410102857d Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Wed, 1 Apr 2026 10:56:40 +0700 Subject: [PATCH 25/62] Rename test.js to backend/test.js --- test.js => backend/test.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test.js => backend/test.js (100%) diff --git a/test.js b/backend/test.js similarity index 100% rename from test.js rename to backend/test.js From 9b0808788f2b90a4e862d66198bd21cb0e889945 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Wed, 1 Apr 2026 11:32:53 +0700 Subject: [PATCH 26/62] Implement RPC client for Pi network --- backend/piClient.js | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 backend/piClient.js diff --git a/backend/piClient.js b/backend/piClient.js new file mode 100644 index 00000000..cb4976f2 --- /dev/null +++ b/backend/piClient.js @@ -0,0 +1,43 @@ +const axios = require("axios"); + +const RPC_URL = "https://rpc.testnet.minepi.com"; + +async function callRPC(method, params = {}) { + try { + const response = await axios.post( + RPC_URL, + { + jsonrpc: "2.0", + id: 1, + method, + params + }, + { + headers: { + "Content-Type": "application/json" + } + } + ); + + return response.data; + } catch (error) { + console.error("RPC Error:", error.message); + throw error; + } +} + +// ===== FUNCTIONS ===== + +async function getHealth() { + return callRPC("getHealth"); +} + +async function getLatestLedger() { + const health = await getHealth(); + return health.result.latestLedger; +} + +module.exports = { + getHealth, + getLatestLedger +}; From 46823c11c4d5ea9f0cf291128a421964c7dda57f Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Wed, 1 Apr 2026 11:33:27 +0700 Subject: [PATCH 27/62] Initialize Express server with API endpoints Set up Express server with health and latest ledger endpoints. --- backend/server.js | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 backend/server.js diff --git a/backend/server.js b/backend/server.js new file mode 100644 index 00000000..c7e49b75 --- /dev/null +++ b/backend/server.js @@ -0,0 +1,34 @@ +const express = require("express"); +const { getHealth, getLatestLedger } = require("./piClient"); + +const app = express(); +const PORT = 3000; + +// root test +app.get("/", (req, res) => { + res.send("Pi Backend API Running 🚀"); +}); + +// health endpoint +app.get("/health", async (req, res) => { + try { + const data = await getHealth(); + res.json(data); + } catch (err) { + res.status(500).json({ error: err.message }); + } +}); + +// latest ledger +app.get("/ledger/latest", async (req, res) => { + try { + const ledger = await getLatestLedger(); + res.json({ latestLedger: ledger }); + } catch (err) { + res.status(500).json({ error: err.message }); + } +}); + +app.listen(PORT, () => { + console.log(`🚀 Server running at http://localhost:${PORT}`); +}); From 60b0dfe5c745cfa622f2e3d602a32882a435e480 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Wed, 1 Apr 2026 11:47:35 +0700 Subject: [PATCH 28/62] Create server.js --- server.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 server.js diff --git a/server.js b/server.js new file mode 100644 index 00000000..acaa78ab --- /dev/null +++ b/server.js @@ -0,0 +1,12 @@ +const express = require("express"); + +const app = express(); +const PORT = 3000; + +app.get("/", (req, res) => { + res.send("Backend aktif 🚀"); +}); + +app.listen(PORT, () => { + console.log("Server jalan di port " + PORT); +}); From 3c2ac96bd32a5ddaca60d156e8e27ca7ddea03ad Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Wed, 1 Apr 2026 12:18:44 +0700 Subject: [PATCH 29/62] Add endpoint for AIOracle anomaly analysis --- backend/server.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/backend/server.js b/backend/server.js index c7e49b75..5407fef1 100644 --- a/backend/server.js +++ b/backend/server.js @@ -32,3 +32,13 @@ app.get("/ledger/latest", async (req, res) => { app.listen(PORT, () => { console.log(`🚀 Server running at http://localhost:${PORT}`); }); +app.get("/oracle/anomaly", async (req, res) => { + const data = await AIOracle.analyzeNetwork(); + res.json({ + risk: data.anomaly.risk, + score: data.anomaly.score, + ledger: data.ledger, + txCount: data.txCount, + insight: data.insight + }); +}); From 8092bf9458f71907bd8de793c9be43e78a7e5fe2 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Wed, 1 Apr 2026 12:21:03 +0700 Subject: [PATCH 30/62] Implement AIOracle class for network analysis --- oracle/aiOracle.js | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 oracle/aiOracle.js diff --git a/oracle/aiOracle.js b/oracle/aiOracle.js new file mode 100644 index 00000000..57c82c41 --- /dev/null +++ b/oracle/aiOracle.js @@ -0,0 +1,34 @@ +import PiRPC from "../sdk/piRpc.js"; +import detector from "./anomalyDetector.js"; + +const rpc = new PiRPC(); + +class AIOracle { + + async analyzeNetwork() { + const health = await rpc.getHealth(); + const ledger = await rpc.getLedger(); + + // fake tx counter (kalau RPC belum ada tx endpoint) + const txCount = Math.floor(Math.random() * 100); + + const anomaly = detector.detect({ + ledger: ledger || 0, + txCount + }); + + return { + status: health?.status || "unknown", + ledger, + txCount, + anomaly, + insight: + anomaly.risk === "HIGH" + ? "⚠️ Suspicious network activity detected" + : "✅ Network stable", + timestamp: Date.now() + }; + } +} + +export default new AIOracle(); From f88ae30b0c24ca2ddbcc86a55203ed37a24bbf30 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Wed, 1 Apr 2026 12:21:43 +0700 Subject: [PATCH 31/62] Implement AnomalyDetector class for risk assessment --- oracle/anomalyDetector.js | 64 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 oracle/anomalyDetector.js diff --git a/oracle/anomalyDetector.js b/oracle/anomalyDetector.js new file mode 100644 index 00000000..2b29446d --- /dev/null +++ b/oracle/anomalyDetector.js @@ -0,0 +1,64 @@ +class AnomalyDetector { + constructor() { + this.history = []; + this.maxHistory = 50; + } + + // simpan data snapshot + addSample(sample) { + this.history.push(sample); + + if (this.history.length > this.maxHistory) { + this.history.shift(); + } + } + + // hitung rata-rata sederhana + getAverage(key) { + const values = this.history.map(h => h[key] || 0); + const sum = values.reduce((a, b) => a + b, 0); + return values.length ? sum / values.length : 0; + } + + // deteksi anomaly utama + detect(sample) { + this.addSample(sample); + + const ledgerAvg = this.getAverage("ledger"); + const txAvg = this.getAverage("txCount"); + + let risk = "LOW"; + let score = 0; + + // 🔥 RULE 1: spike ledger + if (sample.ledger > ledgerAvg * 1.8) { + risk = "HIGH"; + score += 40; + } + + // 🔥 RULE 2: spike transaksi + if (sample.txCount > txAvg * 2) { + risk = "HIGH"; + score += 40; + } + + // 🔥 RULE 3: empty / freeze pattern + if (sample.ledger === 0) { + risk = "MEDIUM"; + score += 20; + } + + // clamp score + if (score > 100) score = 100; + + return { + risk, + score, + ledgerAvg, + txAvg, + sample + }; + } +} + +export default new AnomalyDetector(); From 1ac92b8d26ff83a5d840668100bb12952e01a1f1 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Wed, 1 Apr 2026 12:22:27 +0700 Subject: [PATCH 32/62] Initialize package.json with project details --- package.json | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 package.json diff --git a/package.json b/package.json new file mode 100644 index 00000000..be225cc8 --- /dev/null +++ b/package.json @@ -0,0 +1,9 @@ +{ + "name": "pirc-core", + "type": "module", + "version": "1.0.0", + "dependencies": { + "express": "^4.18.2", + "node-fetch": "^3.3.2" + } +} From ab300f28ccb3d83f4ce6962a5ece29745b081825 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Wed, 1 Apr 2026 12:26:54 +0700 Subject: [PATCH 33/62] Implement PiRPC class for JSON-RPC calls --- sdk/piRpc.js | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 sdk/piRpc.js diff --git a/sdk/piRpc.js b/sdk/piRpc.js new file mode 100644 index 00000000..d139c90a --- /dev/null +++ b/sdk/piRpc.js @@ -0,0 +1,43 @@ +import fetch from "node-fetch"; + +class PiRPC { + constructor(url = "https://rpc.testnet.minepi.com") { + this.url = url; + } + + async call(method, params = []) { + try { + const res = await fetch(this.url, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: Date.now(), + method, + params, + }), + }); + + const data = await res.json(); + return data.result; + } catch (err) { + console.error("RPC ERROR:", err.message); + return null; + } + } + + // helper level dewa + getHealth() { + return this.call("getHealth"); + } + + getLedger() { + return this.call("getLatestLedger"); + } + + getAccount(address) { + return this.call("getAccount", [address]); + } +} + +export default PiRPC; From e9b85404b48b93d6fb64d9d80c9e5708190291c6 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Wed, 1 Apr 2026 12:32:02 +0700 Subject: [PATCH 34/62] Refactor server.js to use ES modules and update endpoints --- backend/server.js | 59 +++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 33 deletions(-) diff --git a/backend/server.js b/backend/server.js index 5407fef1..d736f984 100644 --- a/backend/server.js +++ b/backend/server.js @@ -1,44 +1,37 @@ -const express = require("express"); -const { getHealth, getLatestLedger } = require("./piClient"); +import express from "express"; +import PiRPC from "../sdk/piRpc.js"; +import AIOracle from "../oracle/aiOracle.js"; const app = express(); -const PORT = 3000; +const rpc = new PiRPC(); -// root test -app.get("/", (req, res) => { - res.send("Pi Backend API Running 🚀"); -}); +app.use(express.json()); -// health endpoint +// HEALTH app.get("/health", async (req, res) => { - try { - const data = await getHealth(); - res.json(data); - } catch (err) { - res.status(500).json({ error: err.message }); - } + const data = await rpc.getHealth(); + res.json(data); }); -// latest ledger -app.get("/ledger/latest", async (req, res) => { - try { - const ledger = await getLatestLedger(); - res.json({ latestLedger: ledger }); - } catch (err) { - res.status(500).json({ error: err.message }); - } +// LEDGER +app.get("/ledger", async (req, res) => { + const data = await rpc.getLedger(); + res.json(data); }); -app.listen(PORT, () => { - console.log(`🚀 Server running at http://localhost:${PORT}`); -}); -app.get("/oracle/anomaly", async (req, res) => { +// AI INSIGHT +app.get("/oracle/analysis", async (req, res) => { const data = await AIOracle.analyzeNetwork(); - res.json({ - risk: data.anomaly.risk, - score: data.anomaly.score, - ledger: data.ledger, - txCount: data.txCount, - insight: data.insight - }); + res.json(data); +}); + +// SIMULASI TX +app.post("/simulate", async (req, res) => { + const { from, to, amount } = req.body; + const result = await AIOracle.simulateTransaction(from, to, amount); + res.json(result); +}); + +app.listen(3000, () => { + console.log("🔥 PiRC API running on http://localhost:3000"); }); From a81ae87257e2f508b9bfbecb607bb8445e79c89e Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Wed, 1 Apr 2026 20:48:03 +0700 Subject: [PATCH 35/62] Update package.json --- package.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index be225cc8..f0032ee1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,10 @@ { "name": "pirc-core", - "type": "module", "version": "1.0.0", + "main": "server.js", + "scripts": { + "start": "node server.js" + }, "dependencies": { "express": "^4.18.2", "node-fetch": "^3.3.2" From 052b025750b0cf9feb6087dcc50e8c3ee0f4d773 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Wed, 1 Apr 2026 20:50:46 +0700 Subject: [PATCH 36/62] Update package.json From 8448926bb06748c585ab72e50b5b7165f1ba7d02 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Wed, 1 Apr 2026 20:56:08 +0700 Subject: [PATCH 37/62] Update piRpc.js --- sdk/piRpc.js | 49 ++++++++++++++++++++++--------------------------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/sdk/piRpc.js b/sdk/piRpc.js index d139c90a..70698013 100644 --- a/sdk/piRpc.js +++ b/sdk/piRpc.js @@ -1,43 +1,38 @@ import fetch from "node-fetch"; -class PiRPC { +export default class PiRPC { constructor(url = "https://rpc.testnet.minepi.com") { this.url = url; } async call(method, params = []) { - try { - const res = await fetch(this.url, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - jsonrpc: "2.0", - id: Date.now(), - method, - params, - }), - }); + const body = { + jsonrpc: "2.0", + id: 1, + method, + params + }; - const data = await res.json(); - return data.result; - } catch (err) { - console.error("RPC ERROR:", err.message); - return null; - } + const res = await fetch(this.url, { + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify(body) + }); + + return await res.json(); } - // helper level dewa - getHealth() { - return this.call("getHealth"); + getNetwork() { + return this.call("getNetwork"); } - getLedger() { - return this.call("getLatestLedger"); + getHealth() { + return this.call("getHealth"); } - getAccount(address) { - return this.call("getAccount", [address]); + getVersionInfo() { + return this.call("getVersionInfo"); } } - -export default PiRPC; From 977ad5915ffacc634222d572792ac177ed320102 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Wed, 1 Apr 2026 20:57:25 +0700 Subject: [PATCH 38/62] Update server.js --- backend/server.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/backend/server.js b/backend/server.js index d736f984..2c397678 100644 --- a/backend/server.js +++ b/backend/server.js @@ -35,3 +35,29 @@ app.post("/simulate", async (req, res) => { app.listen(3000, () => { console.log("🔥 PiRC API running on http://localhost:3000"); }); +app.get("/rpc/health", async (req, res) => { + try { + const data = await rpc.getHealth(); + res.json(data); + } catch (err) { + res.status(500).json({ error: err.message }); + } +}); + +app.get("/rpc/network", async (req, res) => { + try { + const data = await rpc.getNetwork(); + res.json(data); + } catch (err) { + res.status(500).json({ error: err.message }); + } +}); + +app.get("/rpc/version", async (req, res) => { + try { + const data = await rpc.getVersionInfo(); + res.json(data); + } catch (err) { + res.status(500).json({ error: err.message }); + } +}); From 3cd0f8e9c2f7e4662855fb75fc27497cc532e250 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Wed, 1 Apr 2026 21:03:51 +0700 Subject: [PATCH 39/62] Update package.json From 84cacb050f4d0c1f64de273cba9c4d891bbfc777 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 01:10:26 +0700 Subject: [PATCH 40/62] Create piHealth.js --- services/piHealth.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 services/piHealth.js diff --git a/services/piHealth.js b/services/piHealth.js new file mode 100644 index 00000000..2206332a --- /dev/null +++ b/services/piHealth.js @@ -0,0 +1,18 @@ +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 bcc74e1ed23d1bebffc25b2f7bd6229dccba3aea Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 01:12:18 +0700 Subject: [PATCH 41/62] Create actionEngine.js --- engine/actionEngine.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 engine/actionEngine.js diff --git a/engine/actionEngine.js b/engine/actionEngine.js new file mode 100644 index 00000000..3367e548 --- /dev/null +++ b/engine/actionEngine.js @@ -0,0 +1,20 @@ +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 c42467cded26a2b8ea05a507fb56f65388e73328 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 01:12:53 +0700 Subject: [PATCH 42/62] 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 5618310e3f72aa92e21c2375be46c07478b0bb28 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 01:13:32 +0700 Subject: [PATCH 43/62] Create app.js --- app.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 app.js diff --git a/app.js b/app.js new file mode 100644 index 00000000..7f6ae575 --- /dev/null +++ b/app.js @@ -0,0 +1,13 @@ +import express from "express"; +import healthRoute from "./routes/healthRoute.js"; + +const app = express(); +app.use(express.json()); + +app.use("/api", healthRoute); + +const PORT = process.env.PORT || 3000; + +app.listen(PORT, () => { + console.log(`🚀 PiRC AI Oracle running on port ${PORT}`); +}); From 2444f1897ef8c910f3bf18001e5c9e68210544dc Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 08:31:37 +0700 Subject: [PATCH 44/62] Create piInvoke.js --- backend/blockchain/piInvoke.js | 93 ++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 backend/blockchain/piInvoke.js diff --git a/backend/blockchain/piInvoke.js b/backend/blockchain/piInvoke.js new file mode 100644 index 00000000..15e18c19 --- /dev/null +++ b/backend/blockchain/piInvoke.js @@ -0,0 +1,93 @@ +import { + SorobanRpc, + TransactionBuilder, + Networks, + BASE_FEE, + Keypair +} from "@stellar/stellar-sdk"; + +const server = new SorobanRpc.Server( + "https://rpc.testnet.minepi.com" +); + +// ambil dari env (WAJIB) +const SECRET = process.env.PI_SECRET; +const CONTRACT_ID = process.env.CONTRACT_ID; + +if (!SECRET) { + throw new Error("❌ PI_SECRET belum diset di .env"); +} + +const source = Keypair.fromSecret(SECRET); + +// 🔍 cek koneksi + akun +export async function checkAccount() { + try { + const account = await server.getAccount(source.publicKey()); + + return { + success: true, + publicKey: source.publicKey(), + sequence: account.sequence, + }; + } catch (err) { + return { + success: false, + error: err.message, + }; + } +} + +// 🚀 invoke contract (core function) +export async function invokePi(method, args = []) { + try { + if (!CONTRACT_ID) { + throw new Error("❌ CONTRACT_ID belum diset di .env"); + } + + const account = await server.getAccount(source.publicKey()); + + const tx = new TransactionBuilder(account, { + fee: BASE_FEE, + networkPassphrase: Networks.TESTNET, + }) + .addOperation( + SorobanRpc.Operation.invokeContract({ + contract: CONTRACT_ID, + function: method, + args: args, + }) + ) + .setTimeout(30) + .build(); + + tx.sign(source); + + // 🔍 simulate dulu (WAJIB di Soroban) + const simulation = await server.simulateTransaction(tx); + + if (simulation.error) { + return { + success: false, + stage: "SIMULATION", + error: simulation.error, + }; + } + + // 🚀 kirim transaksi + const send = await server.sendTransaction(tx); + + return { + success: true, + hash: send.hash, + status: send.status, + }; + + } catch (err) { + return { + success: false, + stage: "EXECUTION", + error: err.message, + }; + } +} From 22006aad67e38837b87ad7f8e1b86794df2e8945 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 08:35:42 +0700 Subject: [PATCH 45/62] Create .env --- .env | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .env diff --git a/.env b/.env new file mode 100644 index 00000000..b493493b --- /dev/null +++ b/.env @@ -0,0 +1,2 @@ +PI_SECRET=SXXXXXXXXXXXXXXXXXXXXXXXX +CONTRACT_ID=XXXXXXXXXXXXXXXXXXXXXXX From a7df343ec9cd18fa8bd8e50783899e0724ed3e71 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 08:42:09 +0700 Subject: [PATCH 46/62] Update .env --- .env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env b/.env index b493493b..6755eaab 100644 --- a/.env +++ b/.env @@ -1,2 +1,2 @@ PI_SECRET=SXXXXXXXXXXXXXXXXXXXXXXXX -CONTRACT_ID=XXXXXXXXXXXXXXXXXXXXXXX +CONTRACT_ID=TEST123 From f352f3f2687c97af1e26b72979e06288947606d9 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 09:06:39 +0700 Subject: [PATCH 47/62] Update server.js --- server.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/server.js b/server.js index acaa78ab..348e7f4b 100644 --- a/server.js +++ b/server.js @@ -10,3 +10,15 @@ app.get("/", (req, res) => { app.listen(PORT, () => { console.log("Server jalan di port " + PORT); }); +app.get("/pi/account", async (req, res) => { + try { + const result = await rpc.getAccount?.() || { + status: "not_implemented", + message: "rpc.getAccount belum tersedia" + }; + + res.json(result); + } catch (err) { + res.status(500).json({ error: err.message }); + } +}); From 75cee9ee83fae793adcbd035a99ab664bf0a9a3b Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 09:10:28 +0700 Subject: [PATCH 48/62] Update server.js --- server.js | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/server.js b/server.js index 348e7f4b..78d6709e 100644 --- a/server.js +++ b/server.js @@ -3,17 +3,18 @@ const express = require("express"); const app = express(); const PORT = 3000; +app.use(express.json()); + +// HOME app.get("/", (req, res) => { - res.send("Backend aktif 🚀"); + res.send("Backend aktif"); }); -app.listen(PORT, () => { - console.log("Server jalan di port " + PORT); -}); +// PI ACCOUNT app.get("/pi/account", async (req, res) => { try { - const result = await rpc.getAccount?.() || { - status: "not_implemented", + const result = { + status: "not implemented", message: "rpc.getAccount belum tersedia" }; @@ -22,3 +23,8 @@ app.get("/pi/account", async (req, res) => { res.status(500).json({ error: err.message }); } }); + +// START SERVER +app.listen(PORT, () => { + console.log(`Server jalan di port ${PORT}`); +}); From 26d20a425f717b94070a5516164168a0aa62f9b5 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 09:16:46 +0700 Subject: [PATCH 49/62] Update server.js From 9aa0bb18e102428da06c14cc543ffa73baae6fa3 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 09:24:32 +0700 Subject: [PATCH 50/62] Update server.js --- server.js | 60 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 12 deletions(-) diff --git a/server.js b/server.js index 78d6709e..5ef35a0f 100644 --- a/server.js +++ b/server.js @@ -1,23 +1,59 @@ -const express = require("express"); +import "dotenv/config"; +import express from "express"; +import PiRPC from "./sdk/piRpc.js"; +import AIOracle from "./oracle/aiOracle.js"; +import { checkAccount } from "./blockchain/piInvoke.js"; const app = express(); -const PORT = 3000; +const rpc = new PiRPC(); app.use(express.json()); -// HOME -app.get("/", (req, res) => { - res.send("Backend aktif"); +// HEALTH +app.get("/health", async (req, res) => { + try { + const data = await rpc.getHealth(); + res.json(data); + } catch (err) { + res.status(500).json({ error: err.message }); + } +}); + +// LEDGER +app.get("/ledger", async (req, res) => { + try { + const data = await rpc.getLedger(); + res.json(data); + } catch (err) { + res.status(500).json({ error: err.message }); + } +}); + +// AI INSIGHT +app.get("/oracle/analysis", async (req, res) => { + try { + const data = await AIOracle.analyzeNetwork(); + res.json(data); + } catch (err) { + res.status(500).json({ error: err.message }); + } +}); + +// SIMULATE TX +app.post("/simulate", async (req, res) => { + try { + const { from, to, amount } = req.body; + const result = await AIOracle.simulateTransaction({ from, to, amount }); + res.json(result); + } catch (err) { + res.status(500).json({ error: err.message }); + } }); // PI ACCOUNT app.get("/pi/account", async (req, res) => { try { - const result = { - status: "not implemented", - message: "rpc.getAccount belum tersedia" - }; - + const result = await checkAccount(); res.json(result); } catch (err) { res.status(500).json({ error: err.message }); @@ -25,6 +61,6 @@ app.get("/pi/account", async (req, res) => { }); // START SERVER -app.listen(PORT, () => { - console.log(`Server jalan di port ${PORT}`); +app.listen(3000, () => { + console.log("🔥 PiRC API running on http://localhost:3000"); }); From ec93237483ed1fc72300e58c386549289ed68fab Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 09:27:10 +0700 Subject: [PATCH 51/62] Update package.json --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index f0032ee1..63a1b1d1 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,12 @@ { "name": "pirc-core", "version": "1.0.0", - "main": "server.js", + "type": "module", + "main": "backend/server.js", "scripts": { - "start": "node server.js" + "start": "node backend/server.js" }, "dependencies": { - "express": "^4.18.2", - "node-fetch": "^3.3.2" + "express": "^4.18.2" } } From c466ab28f24abfe03f8a8f850d724e2b1196cea0 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 09:31:47 +0700 Subject: [PATCH 52/62] Update server.js From e6e6e54758df1069e15bfd3f646f3705b70a236d Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 09:36:18 +0700 Subject: [PATCH 53/62] Update server.js --- server.js | 48 +++++++++++------------------------------------- 1 file changed, 11 insertions(+), 37 deletions(-) diff --git a/server.js b/server.js index 5ef35a0f..bf62d951 100644 --- a/server.js +++ b/server.js @@ -9,58 +9,32 @@ const rpc = new PiRPC(); app.use(express.json()); -// HEALTH app.get("/health", async (req, res) => { - try { - const data = await rpc.getHealth(); - res.json(data); - } catch (err) { - res.status(500).json({ error: err.message }); - } + const data = await rpc.getHealth(); + res.json(data); }); -// LEDGER app.get("/ledger", async (req, res) => { - try { - const data = await rpc.getLedger(); - res.json(data); - } catch (err) { - res.status(500).json({ error: err.message }); - } + const data = await rpc.getLedger(); + res.json(data); }); -// AI INSIGHT app.get("/oracle/analysis", async (req, res) => { - try { - const data = await AIOracle.analyzeNetwork(); - res.json(data); - } catch (err) { - res.status(500).json({ error: err.message }); - } + const data = await AIOracle.analyzeNetwork(); + res.json(data); }); -// SIMULATE TX app.post("/simulate", async (req, res) => { - try { - const { from, to, amount } = req.body; - const result = await AIOracle.simulateTransaction({ from, to, amount }); - res.json(result); - } catch (err) { - res.status(500).json({ error: err.message }); - } + const { from, to, amount } = req.body; + const result = await AIOracle.simulateTransaction({ from, to, amount }); + res.json(result); }); -// PI ACCOUNT app.get("/pi/account", async (req, res) => { - try { - const result = await checkAccount(); - res.json(result); - } catch (err) { - res.status(500).json({ error: err.message }); - } + const result = await checkAccount(); + res.json(result); }); -// START SERVER app.listen(3000, () => { console.log("🔥 PiRC API running on http://localhost:3000"); }); From 09f7e535f5f889b124206f290d821894765f2c7e Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 09:39:42 +0700 Subject: [PATCH 54/62] Update server.js --- server.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/server.js b/server.js index bf62d951..ade7bbc2 100644 --- a/server.js +++ b/server.js @@ -1,7 +1,5 @@ -import "dotenv/config"; import express from "express"; -import PiRPC from "./sdk/piRpc.js"; -import AIOracle from "./oracle/aiOracle.js"; +import "dotenv/config"; import { checkAccount } from "./blockchain/piInvoke.js"; const app = express(); @@ -9,27 +7,32 @@ const rpc = new PiRPC(); app.use(express.json()); +// HEALTH app.get("/health", async (req, res) => { const data = await rpc.getHealth(); res.json(data); }); +// LEDGER app.get("/ledger", async (req, res) => { const data = await rpc.getLedger(); res.json(data); }); +// AI INSIGHT app.get("/oracle/analysis", async (req, res) => { const data = await AIOracle.analyzeNetwork(); res.json(data); }); +// SIMULASI TX app.post("/simulate", async (req, res) => { const { from, to, amount } = req.body; - const result = await AIOracle.simulateTransaction({ from, to, amount }); + const result = await AIOracle.simulateTransaction(from, to, amount); res.json(result); }); +// PI ACCOUNT app.get("/pi/account", async (req, res) => { const result = await checkAccount(); res.json(result); From 878fde6bfb25fc3879f33628947cc29ca0ef94ed Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 09:45:51 +0700 Subject: [PATCH 55/62] Update server.js --- server.js | 38 +++----------------------------------- 1 file changed, 3 insertions(+), 35 deletions(-) diff --git a/server.js b/server.js index ade7bbc2..9f242064 100644 --- a/server.js +++ b/server.js @@ -1,43 +1,11 @@ import express from "express"; -import "dotenv/config"; -import { checkAccount } from "./blockchain/piInvoke.js"; const app = express(); -const rpc = new PiRPC(); -app.use(express.json()); - -// HEALTH -app.get("/health", async (req, res) => { - const data = await rpc.getHealth(); - res.json(data); -}); - -// LEDGER -app.get("/ledger", async (req, res) => { - const data = await rpc.getLedger(); - res.json(data); -}); - -// AI INSIGHT -app.get("/oracle/analysis", async (req, res) => { - const data = await AIOracle.analyzeNetwork(); - res.json(data); -}); - -// SIMULASI TX -app.post("/simulate", async (req, res) => { - const { from, to, amount } = req.body; - const result = await AIOracle.simulateTransaction(from, to, amount); - res.json(result); -}); - -// PI ACCOUNT -app.get("/pi/account", async (req, res) => { - const result = await checkAccount(); - res.json(result); +app.get("/", (req, res) => { + res.send("API OK"); }); app.listen(3000, () => { - console.log("🔥 PiRC API running on http://localhost:3000"); + console.log("Server running"); }); From 38bd2ca8f30051d7c89e9f02a9a8b61675b283d8 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 09:49:35 +0700 Subject: [PATCH 56/62] Update server.js --- server.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/server.js b/server.js index 9f242064..6752312f 100644 --- a/server.js +++ b/server.js @@ -2,10 +2,15 @@ import express from "express"; const app = express(); +app.use(express.json()); + app.get("/", (req, res) => { - res.send("API OK"); + res.json({ + status: "OK", + message: "server live" + }); }); app.listen(3000, () => { - console.log("Server running"); + console.log("🔥 Server running on http://localhost:3000"); }); From d669b8bb9c59c5fab763b8f987a96e891af06055 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 09:55:16 +0700 Subject: [PATCH 57/62] Update server.js --- backend/server.js | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/backend/server.js b/backend/server.js index 2c397678..a9e4d283 100644 --- a/backend/server.js +++ b/backend/server.js @@ -9,32 +9,46 @@ app.use(express.json()); // HEALTH app.get("/health", async (req, res) => { - const data = await rpc.getHealth(); - res.json(data); + try { + const data = await rpc.getHealth(); + res.json(data); + } catch (err) { + res.status(500).json({ error: err.message }); + } }); // LEDGER app.get("/ledger", async (req, res) => { - const data = await rpc.getLedger(); - res.json(data); + try { + const data = await rpc.getLedger(); + res.json(data); + } catch (err) { + res.status(500).json({ error: err.message }); + } }); // AI INSIGHT app.get("/oracle/analysis", async (req, res) => { - const data = await AIOracle.analyzeNetwork(); - res.json(data); + try { + const data = await AIOracle.analyzeNetwork(); + res.json(data); + } catch (err) { + res.status(500).json({ error: err.message }); + } }); // SIMULASI TX app.post("/simulate", async (req, res) => { - const { from, to, amount } = req.body; - const result = await AIOracle.simulateTransaction(from, to, amount); - res.json(result); + try { + const { from, to, amount } = req.body; + const result = await AIOracle.simulateTransaction(from, to, amount); + res.json(result); + } catch (err) { + res.status(500).json({ error: err.message }); + } }); -app.listen(3000, () => { - console.log("🔥 PiRC API running on http://localhost:3000"); -}); +// RPC HEALTH app.get("/rpc/health", async (req, res) => { try { const data = await rpc.getHealth(); @@ -44,6 +58,7 @@ app.get("/rpc/health", async (req, res) => { } }); +// RPC NETWORK app.get("/rpc/network", async (req, res) => { try { const data = await rpc.getNetwork(); @@ -53,6 +68,7 @@ app.get("/rpc/network", async (req, res) => { } }); +// RPC VERSION app.get("/rpc/version", async (req, res) => { try { const data = await rpc.getVersionInfo(); @@ -61,3 +77,7 @@ app.get("/rpc/version", async (req, res) => { res.status(500).json({ error: err.message }); } }); + +app.listen(3000, () => { + console.log("🔥 PiRC API running on http://localhost:3000"); +}); From 240a36348eae3eaa2fc4b256ce07629051f5d391 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 09:58:03 +0700 Subject: [PATCH 58/62] Update server.js --- server.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/server.js b/server.js index 6752312f..14fe530b 100644 --- a/server.js +++ b/server.js @@ -1,14 +1,12 @@ import express from "express"; +import "dotenv/config"; const app = express(); app.use(express.json()); app.get("/", (req, res) => { - res.json({ - status: "OK", - message: "server live" - }); + res.json({ status: "OK", message: "server live" }); }); app.listen(3000, () => { From 0d8f38b4f4dfbdcf00d55a6fcfd9f42585bcba72 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 10:01:59 +0700 Subject: [PATCH 59/62] Update server.js --- server.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server.js b/server.js index 14fe530b..bbae6f10 100644 --- a/server.js +++ b/server.js @@ -6,7 +6,10 @@ const app = express(); app.use(express.json()); app.get("/", (req, res) => { - res.json({ status: "OK", message: "server live" }); + res.json({ + status: "OK", + message: "server live" + }); }); app.listen(3000, () => { From 80cf3847bfce07d391e6770da6cd204696d3e10f Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 10:05:23 +0700 Subject: [PATCH 60/62] Update server.js --- server.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server.js b/server.js index bbae6f10..02477d75 100644 --- a/server.js +++ b/server.js @@ -1,7 +1,7 @@ import express from "express"; -import "dotenv/config"; const app = express(); +const PORT = 3000; app.use(express.json()); @@ -12,6 +12,6 @@ app.get("/", (req, res) => { }); }); -app.listen(3000, () => { - console.log("🔥 Server running on http://localhost:3000"); +app.listen(PORT, () => { + console.log(`🔥 Server running on http://localhost:${PORT}`); }); From 6c3dd0fc35a2a8dd8cd462a684982ac4e21c68e9 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 10:10:54 +0700 Subject: [PATCH 61/62] Update server.js --- server.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/server.js b/server.js index 02477d75..58350dc8 100644 --- a/server.js +++ b/server.js @@ -3,15 +3,10 @@ import express from "express"; const app = express(); const PORT = 3000; -app.use(express.json()); - app.get("/", (req, res) => { - res.json({ - status: "OK", - message: "server live" - }); + res.send("Backend aktif 🚀"); }); app.listen(PORT, () => { - console.log(`🔥 Server running on http://localhost:${PORT}`); + console.log("Server jalan di port " + PORT); }); From acc51c164e5c01ab5911525cd9e9b18bcbc0e275 Mon Sep 17 00:00:00 2001 From: Kapten boneng Date: Thu, 2 Apr 2026 10:17:56 +0700 Subject: [PATCH 62/62] Update server.js --- server.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server.js b/server.js index 58350dc8..428e3e52 100644 --- a/server.js +++ b/server.js @@ -3,6 +3,8 @@ import express from "express"; const app = express(); const PORT = 3000; +app.use(express.json()); + app.get("/", (req, res) => { res.send("Backend aktif 🚀"); });