Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/landing/.env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Sentrix Chain mainnet RPC — used by Stats section to fetch live block data.
# Defaults to the public production endpoint if unset.
NEXT_PUBLIC_MAINNET_RPC=https://sentrix-rpc.sentriscloud.com/rpc
NEXT_PUBLIC_MAINNET_RPC=https://rpc.sentrixchain.com
NEXT_PUBLIC_MAINNET_CHAIN_ID=7119
4 changes: 2 additions & 2 deletions apps/scan/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
# ── Chain endpoints (public) ────────────────────────────────────────────────
# Mainnet
NEXT_PUBLIC_MAINNET_CHAIN_ID=7119
NEXT_PUBLIC_MAINNET_RPC=https://rpc.sentrixchain.com/rpc
NEXT_PUBLIC_MAINNET_RPC=https://rpc.sentrixchain.com
NEXT_PUBLIC_MAINNET_API=https://api.sentrixchain.com

# Testnet
NEXT_PUBLIC_TESTNET_CHAIN_ID=7120
NEXT_PUBLIC_TESTNET_RPC=https://testnet-rpc.sentrixchain.com/rpc
NEXT_PUBLIC_TESTNET_RPC=https://testnet-rpc.sentrixchain.com
NEXT_PUBLIC_TESTNET_API=https://testnet-api.sentrixchain.com

# Which network users land on by default (mainnet | testnet).
Expand Down
22 changes: 11 additions & 11 deletions apps/scan/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,11 @@ Open http://localhost:3000

| Variable | Description | Default |
|---|---|---|
| NEXT_PUBLIC_MAINNET_RPC | Mainnet JSON-RPC | sentrix-rpc.sentriscloud.com/rpc |
| NEXT_PUBLIC_MAINNET_API | Mainnet REST API | sentrix-api.sentriscloud.com |
| NEXT_PUBLIC_MAINNET_RPC | Mainnet JSON-RPC | https://rpc.sentrixchain.com |
| NEXT_PUBLIC_MAINNET_API | Mainnet REST API | https://api.sentrixchain.com |
| NEXT_PUBLIC_MAINNET_CHAIN_ID | Mainnet chain ID | 7119 |
| NEXT_PUBLIC_TESTNET_RPC | Testnet JSON-RPC | testnet-rpc.sentriscloud.com/rpc |
| NEXT_PUBLIC_TESTNET_API | Testnet REST API | testnet-api.sentriscloud.com |
| NEXT_PUBLIC_TESTNET_RPC | Testnet JSON-RPC | https://testnet-rpc.sentrixchain.com |
| NEXT_PUBLIC_TESTNET_API | Testnet REST API | https://testnet-api.sentrixchain.com |
| NEXT_PUBLIC_TESTNET_CHAIN_ID | Testnet chain ID | 7120 |
| NEXT_PUBLIC_DEFAULT_NETWORK | Default network | mainnet |

Expand All @@ -90,14 +90,14 @@ pnpm build

### Systemd

```
Port 3006 (mainnet), Port 3007 (testnet)
HOSTNAME=127.0.0.1 (bind localhost only, Nginx reverse proxy)
```
A single `sentrix-scan.service` runs `pnpm start` from this directory on
port 3005. Both networks are served by the same process; the network is
selected per-request via the cookie / `?network=` query / dedicated
subdomain (Caddy routes both subdomains to the same upstream).

### Nginx
### Caddy

```
sentrixscan.sentriscloud.com → 127.0.0.1:3006
testnet-scan.sentriscloud.com → 127.0.0.1:3007
scan.sentrixchain.com → 127.0.0.1:3005
scan-testnet.sentrixchain.com → 127.0.0.1:3005
```
5 changes: 4 additions & 1 deletion apps/scan/app/[locale]/blocks/[height]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ export default function BlockDetailPage({ params }: { params: Promise<{ height:
// often a hit on the other. Without this the user dead-ends instead of
// getting a one-click switch.
const otherNetwork = network === "mainnet" ? "testnet" : "mainnet";
const { data: blockOther, loading: loadingOther } = useBlock(otherNetwork, blockHeight);
// Tight 2.5s timeout: this is a "is the same height also on the other
// chain?" side-probe. If the peer network is slow or down, we'd
// rather skip the cross-network indicator than block the page render.
const { data: blockOther, loading: loadingOther } = useBlock(otherNetwork, blockHeight, 2500);
const [txPage, setTxPage] = useState(1);
const [railFilter, setRailFilter] = useState<RailFilter>("all");

Expand Down
4 changes: 3 additions & 1 deletion apps/scan/app/[locale]/tokens/[addr]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ export default function TokenDetailPage({ params }: { params: Promise<{ addr: st

useEffect(() => {
setLoadingOther(true);
fetchToken(otherNetwork, addr).then((t) => {
// Tight 2.5s timeout: cross-network side-probe shouldn't block the
// primary render past a couple of seconds even if the peer is slow.
fetchToken(otherNetwork, addr, 2500).then((t) => {
setTokenOther(t);
setLoadingOther(false);
});
Expand Down
4 changes: 3 additions & 1 deletion apps/scan/app/[locale]/tx/[hash]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ export default function TxDetailPage({ params }: { params: Promise<{ hash: strin
// "lives on Testnet, click to switch" wall.
const { data: tx, loading } = useTransaction(network, hash);
const otherNetwork = network === "mainnet" ? "testnet" : "mainnet";
const { data: txOther, loading: loadingOther } = useTransaction(otherNetwork, hash);
// Tight 2.5s timeout for the cross-network side-probe — see
// blocks/[height]/page.tsx for the same rationale.
const { data: txOther, loading: loadingOther } = useTransaction(otherNetwork, hash, 2500);
const autoSwitched = useRef(false);
useEffect(() => {
if (autoSwitched.current) return;
Expand Down
23 changes: 17 additions & 6 deletions apps/scan/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -316,8 +316,13 @@ function normalizeBlockTransactions(block: BlockData | null): BlockData | null {
return block;
}

export async function fetchBlock(network: NetworkId, index: number) {
const res = await apiFetch<BlockData>(network, `/chain/blocks/${index}`);
// timeoutMs lets callers tighten the budget for cross-network probes
// (block/tx detail pages fire a parallel "is this also on the other
// chain?" query — that side-probe shouldn't be allowed to delay the
// primary render past a couple of seconds even if the other network
// is slow or down).
export async function fetchBlock(network: NetworkId, index: number, timeoutMs?: number) {
const res = await apiFetch<BlockData>(network, `/chain/blocks/${index}`, timeoutMs);
return normalizeBlockTransactions(res);
}

Expand Down Expand Up @@ -391,8 +396,10 @@ function normalizeTx(raw: RawTxDetail): TransactionData | null {
};
}

export async function fetchTransaction(network: NetworkId, txId: string): Promise<TransactionData | null> {
const res = await apiFetch<RawTxDetail>(network, `/transactions/${normalizeTxHash(txId)}`);
// timeoutMs lets callers tighten the budget for cross-network probes
// (see fetchBlock above for the same rationale).
export async function fetchTransaction(network: NetworkId, txId: string, timeoutMs?: number): Promise<TransactionData | null> {
const res = await apiFetch<RawTxDetail>(network, `/transactions/${normalizeTxHash(txId)}`, timeoutMs);
if (!res) return null;
return normalizeTx(res);
}
Expand Down Expand Up @@ -813,14 +820,18 @@ function isPrintable(s: string): boolean {
return true;
}

export async function fetchToken(network: NetworkId, address: string): Promise<TokenData | null> {
// timeoutMs lets callers tighten the budget for cross-network probes.
export async function fetchToken(network: NetworkId, address: string, timeoutMs?: number): Promise<TokenData | null> {
const addr = normalizeAddress(address);
// Native first — `/tokens/{addr}` only resolves for native TokenOp.
const native = await apiFetch<TokenData>(network, `/tokens/${addr}`);
const native = await apiFetch<TokenData>(network, `/tokens/${addr}`, timeoutMs);
if (native) return { ...native, standard: "tokenop" };
// Fall back to ERC-20 read-via-RPC for EVM contracts (TokenFactory-deployed
// or any other ERC-20). Multicall would be tighter, but per-field calls
// keep this readable + work without Multicall3 ABI in this file.
// The EVM RPC path has its own internal 8s timeout that callers can't
// override yet; this is fine because the cross-network probe falls
// through to it only when the native lookup fails fast.
return await fetchEvmTokenFromChain(network, addr);
}

Expand Down
12 changes: 6 additions & 6 deletions apps/scan/lib/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,11 @@ export function useBlocks(network: NetworkId, count = 10, initial: BlockData[] |
);
}

export function useBlock(network: NetworkId, height: number) {
export function useBlock(network: NetworkId, height: number, timeoutMs?: number) {
return usePolling<BlockData>(
() => fetchBlock(network, height),
() => fetchBlock(network, height, timeoutMs),
0,
[network, height]
[network, height, timeoutMs ?? 0]
);
}

Expand All @@ -188,11 +188,11 @@ export function useTransactions(network: NetworkId, count = 10, initial: Transac
);
}

export function useTransaction(network: NetworkId, hash: string) {
export function useTransaction(network: NetworkId, hash: string, timeoutMs?: number) {
return usePolling<TransactionData>(
() => fetchTransaction(network, hash),
() => fetchTransaction(network, hash, timeoutMs),
0,
[network, hash]
[network, hash, timeoutMs ?? 0]
);
}

Expand Down
Loading