diff --git a/src/App.css b/src/App.css
index c3c5f27..a2030a1 100644
--- a/src/App.css
+++ b/src/App.css
@@ -158,3 +158,64 @@ canvas {
height: 30px;
border:none;
}
+
+/* Reality Tunnel — trust threshold slider */
+.header-center {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 6px;
+}
+
+.trust-threshold {
+ display: inline-flex;
+ align-items: center;
+ gap: 8px;
+ background: rgba(34, 197, 94, 0.08);
+ border: 1px solid rgba(34, 197, 94, 0.28);
+ padding: 5px 10px;
+ border-radius: 999px;
+}
+
+.trust-slider {
+ -webkit-appearance: none;
+ appearance: none;
+ width: 90px;
+ height: 4px;
+ border-radius: 2px;
+ background: rgba(255,255,255,0.15);
+ outline: none;
+ cursor: pointer;
+}
+
+.trust-slider::-webkit-slider-thumb {
+ -webkit-appearance: none;
+ appearance: none;
+ width: 14px;
+ height: 14px;
+ border-radius: 50%;
+ background: #22c55e;
+ box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.25);
+ cursor: pointer;
+ transition: box-shadow 0.15s;
+}
+
+.trust-slider::-webkit-slider-thumb:hover {
+ box-shadow: 0 0 0 5px rgba(34, 197, 94, 0.35);
+}
+
+.trust-slider::-moz-range-thumb {
+ width: 14px;
+ height: 14px;
+ border-radius: 50%;
+ background: #22c55e;
+ border: none;
+ cursor: pointer;
+}
+
+.trust-value {
+ font-size: 11px;
+ color: #22c55e;
+ min-width: 28px;
+ font-variant-numeric: tabular-nums;
+}
diff --git a/src/App.js b/src/App.js
index b5b557a..a8fb520 100644
--- a/src/App.js
+++ b/src/App.js
@@ -12,6 +12,7 @@ import EndpointSelector from "./EndpointSelector";
function App() {
const [endpoint, setEndpoint] = useState("base");
const [userFilterAddress, setUserFilterAddress] = useState(null);
+ const [trustThreshold, setTrustThreshold] = useState(0);
const { address, isConnected } = useAccount();
const [accountLabel, setAccountLabel] = useState("");
@@ -56,8 +57,8 @@ function App() {
connectedLabel={accountLabel}
/>
-
- Intuition Testnet
+
+ Intuition Mainnet
{({ account, openConnectModal, openAccountModal, mounted }) => {
@@ -85,6 +86,8 @@ function App() {
diff --git a/src/GraphVisualization.js b/src/GraphVisualization.js
index 2fa45b5..697f2db 100644
--- a/src/GraphVisualization.js
+++ b/src/GraphVisualization.js
@@ -1,4 +1,4 @@
-import React, { useEffect, useState, useCallback, useRef } from "react";
+import React, { useEffect, useState, useCallback, useRef, useMemo } from "react";
import { ForceGraph2D, ForceGraph3D } from "react-force-graph";
import SpriteText from "three-spritetext";
import { fetchTriples, fetchTriplesForNode, searchTriples, createClient } from "./api";
@@ -9,8 +9,9 @@ import GraphLegend from "./GraphLegend";
import GraphVR from "./GraphVR";
import NodeDetailsSidebar from "./NodeDetailsSidebar";
import LoadingAnimation from "./LoadingAnimation";
+import { filterGraphByTrust } from "./RealityTunnel";
-const GraphVisualization = ({ endpoint, userFilterAddress }) => {
+const GraphVisualization = ({ endpoint, userFilterAddress, trustThreshold = 0 }) => {
const [graphData, setGraphData] = useState({ nodes: [], links: [] });
const [initialGraphData, setInitialGraphData] = useState(null);
const [isInitialLoad, setIsInitialLoad] = useState(true);
@@ -331,6 +332,12 @@ const GraphVisualization = ({ endpoint, userFilterAddress }) => {
}, 500);
}, []);
+ // Apply trust threshold filter as a derived view — does not mutate base graphData
+ const displayGraphData = useMemo(
+ () => filterGraphByTrust(graphData, trustThreshold),
+ [graphData, trustThreshold]
+ );
+
// Effect for handling search
useEffect(() => {
if (shouldSearch) {
@@ -475,7 +482,7 @@ const GraphVisualization = ({ endpoint, userFilterAddress }) => {
{viewMode === "2D" && (
(fgRef.current = el)}
- graphData={graphData}
+ graphData={displayGraphData}
nodeCanvasObject={(node, ctx, globalScale) => {
const label = node.label || "";
const fontSize = 12 / globalScale;
@@ -548,7 +555,7 @@ const GraphVisualization = ({ endpoint, userFilterAddress }) => {
{viewMode === "3D" && (
(fgRef.current = el)}
- graphData={graphData}
+ graphData={displayGraphData}
controlType="fly"
nodeLabel="label"
onNodeClick={handleNodeClick}
diff --git a/src/RealityTunnel.js b/src/RealityTunnel.js
index a93512d..77a505c 100644
--- a/src/RealityTunnel.js
+++ b/src/RealityTunnel.js
@@ -7,8 +7,32 @@ const EyeIcon = ({ size = 14 }) => (
);
-// A centered control to pick which address' positions to visualize
-export default function RealityTunnel({ value, onChange, connectedAddress, connectedLabel }) {
+const TrustIcon = ({ size = 13 }) => (
+
+);
+
+/**
+ * Reality Tunnel — trust-weighted graph filter.
+ *
+ * Props:
+ * value {string|null} - currently selected address filter
+ * onChange {fn} - called with address string or null
+ * connectedAddress {string|null} - wallet address from wagmi
+ * connectedLabel {string} - human-readable wallet label
+ * trustThreshold {number} - current trust threshold (0–100, % of max vault shares)
+ * onTrustThresholdChange {fn} - called with new threshold value (number)
+ */
+export default function RealityTunnel({
+ value,
+ onChange,
+ connectedAddress,
+ connectedLabel,
+ trustThreshold = 0,
+ onTrustThresholdChange,
+}) {
const options = React.useMemo(() => {
const list = [];
if (connectedAddress) {
@@ -23,8 +47,14 @@ export default function RealityTunnel({ value, onChange, connectedAddress, conne
return list;
}, [connectedAddress, connectedLabel]);
+ const handleThresholdChange = React.useCallback((e) => {
+ const val = Number(e.target.value);
+ if (onTrustThresholdChange) onTrustThresholdChange(val);
+ }, [onTrustThresholdChange]);
+
return (
-
+
+ {/* Address selector */}
Reality Tunnel
@@ -39,7 +69,75 @@ export default function RealityTunnel({ value, onChange, connectedAddress, conne
))}
+
+ {/* Trust Threshold slider */}
+
+
+ Trust ≥
+
+ {trustThreshold}%
+
);
}
+/**
+ * filterGraphByTrust — pure helper for GraphVisualization to consume.
+ *
+ * Filters nodes and links so only those with vault share weight >= threshold
+ * (expressed as a % of the max observed total_shares) survive.
+ *
+ * @param {{ nodes: Array, links: Array }} graphData
+ * @param {number} thresholdPct 0 = show all, 100 = only max-weight edges
+ * @returns {{ nodes: Array, links: Array }}
+ */
+export function filterGraphByTrust(graphData, thresholdPct = 0) {
+ if (!graphData || thresholdPct === 0) return graphData;
+
+ const { nodes, links } = graphData;
+
+ // Find the max vault shares across all nodes
+ const maxShares = nodes.reduce((max, n) => {
+ const s = n.vault?.total_shares ?? n.totalShares ?? 0;
+ return Math.max(max, Number(s));
+ }, 0);
+
+ if (maxShares === 0) return graphData;
+
+ const minShares = (thresholdPct / 100) * maxShares;
+
+ // Filter nodes that meet the trust threshold
+ const acceptedIds = new Set(
+ nodes
+ .filter((n) => {
+ const s = n.vault?.total_shares ?? n.totalShares ?? 0;
+ return Number(s) >= minShares;
+ })
+ .map((n) => n.id)
+ );
+
+ // Filter links where both endpoints survive
+ const filteredLinks = links.filter(
+ (l) => acceptedIds.has(l.source?.id ?? l.source) && acceptedIds.has(l.target?.id ?? l.target)
+ );
+
+ // Re-filter nodes to only those still referenced by surviving links
+ const linkedIds = new Set();
+ filteredLinks.forEach((l) => {
+ linkedIds.add(l.source?.id ?? l.source);
+ linkedIds.add(l.target?.id ?? l.target);
+ });
+
+ const filteredNodes = nodes.filter((n) => linkedIds.has(n.id));
+
+ return { nodes: filteredNodes, links: filteredLinks };
+}
diff --git a/src/api.js b/src/api.js
index 817e76e..d3d24c7 100644
--- a/src/api.js
+++ b/src/api.js
@@ -15,8 +15,8 @@ export const ENDPOINTS = {
module: BaseSepolia,
},
base: {
- url: "https://testnet.intuition.sh/v1/graphql",
- displayName: "Intuition Testnet",
+ url: "https://mainnet.intuition.sh/v1/graphql",
+ displayName: "Intuition Mainnet",
module: Base,
},
};
diff --git a/src/api/Base.js b/src/api/Base.js
index 1506400..6917bff 100644
--- a/src/api/Base.js
+++ b/src/api/Base.js
@@ -6,8 +6,8 @@ import {
export const ENDPOINTS = {
base: {
- url: "https://testnet.intuition.sh/v1/graphql",
- displayName: "Intuition Testnet",
+ url: "https://mainnet.intuition.sh/v1/graphql",
+ displayName: "Intuition Mainnet",
},
};
// Create GraphQL client based on endpoint