Ink Explorer is an open source project for the Ink community. You can use it to look up blocks, transactions, wallets, tokens and contracts on Ink Mainnet or Sepolia. The site gets historical data from public indexes and checks live chain status against local OP-Reth and OP Node instances when those are available.
The code is MIT licensed. You can run your own instance, fix a bug or adapt the explorer for another chain. See the fork guide before changing networks: some Ink and OP Stack behaviour is built into the source. This project is independent and is not an official Ink explorer.
Contract pages support ABI-based reads and wallet-confirmed writes, including proxy implementations and custom ABIs. The server does not hold keys or submit transactions on a user's behalf.
The interface uses English as its source language and provides translated page content, navigation and entity terminology in Chinese, Hindi, Spanish, French, Arabic, Bengali, Portuguese, Russian and Japanese. Project documentation is in English. Arabic uses a right-to-left layout. Locale-aware numbers, dates, canonical links and language alternatives are generated without a translation service.
- Browse recent blocks and transactions with cursor pagination. Wallet addresses use deterministic pixel identicons; transaction pages show fees, transfers, logs and traces.
- Inspect addresses, verified contracts, proxy implementations, tokens and NFT instances. Contract calls use an ABI and stay under the user's wallet control.
- Search DEX pools by token, exchange, fee tier, liquidity or volume. Market figures come from a third-party data source and are labelled as estimates.
- Follow Optimism bridge activity and ERC-4337 user operations, or export analytics as CSV.
- Compare indexed history with local execution and rollup node status. The live view uses WebSocket updates and shows when a node is unavailable or behind.
- Share route-specific pages with canonical URLs, social metadata and a multilingual sitemap.
- Node.js 22.12 or newer
- npm
- Google Chrome at
/usr/bin/google-chromefor the browser suites - optional local Ink OP-Reth and OP Node JSON-RPC for independent live verification
npm ci --include=dev
cp .env.example .env
npm run build
npm startOpen http://127.0.0.1:4188. The historical explorer works with the public defaults. If local nodes are absent, their health signals are shown as unavailable instead of being substituted with public data.
For PM2:
pm2 start ecosystem.config.cjs
pm2 saveSet PUBLIC_URL to the public HTTPS origin before production deployment. Keep local RPC ports bound to loopback or a private service network.
For the Sepolia worker, copy .env.sepolia.example to .env.sepolia before starting PM2. The two processes read separate environment files. See the deployment and fork guide for the exact settings and the changes needed for another chain.
| Variable | Default | Purpose |
|---|---|---|
PORT |
4188 |
HTTP/WebSocket listen port |
INK_TESTNET_PORT |
4190 |
Loopback Sepolia worker port for the main proxy |
HOST |
0.0.0.0 |
HTTP bind address; testnet worker uses loopback |
INK_NETWORK |
mainnet | sepolia selects chain 763373 and its upstreams |
PUBLIC_URL |
request origin | Canonical, sitemap and Open Graph origin |
EXPLORER_BROWSER_ORIGIN |
empty | Exact HTTPS origin allowed to read the API from a separate browser site |
INK_PUBLIC_API_ORIGIN |
empty | Public HTTPS API gateway, used only by the static hosting function |
VITE_PUBLIC_API_ORIGIN |
empty | Optional public API for other static hosts; default uses same-origin requests |
WALLETCONNECT_PROJECT_ID |
empty | Public Reown project ID returned by the API at runtime |
VITE_WALLETCONNECT_PROJECT_ID |
empty | Optional frontend build override for the same public project ID |
INK_GATEWAY_PORT |
4186 |
Optional API-only loopback gateway |
INK_GATEWAY_UPSTREAM |
http://127.0.0.1:4188 |
Loopback explorer upstream for that gateway |
BLOCKSCOUT_API |
Ink Blockscout v2 | Indexed chain history |
BLOCKSCOUT_STATS_API |
Ink Stats Service | Counters and time series |
CONTRACT_INFO_API |
Blockscout Contract Info for chain 57073 | DEX pool market metadata |
INK_RPC |
http://127.0.0.1:8545 |
Local OP-Reth JSON-RPC |
INK_OP_NODE_RPC |
http://127.0.0.1:9545 |
Local OP Node JSON-RPC |
INK_PUBLIC_RPC |
Ink public RPC | Contract read/simulation fallback |
INK_METRICS_URL |
http://127.0.0.1:9001/metrics |
Local execution metrics endpoint |
INK_NODE_DATA_DIR |
empty | Optional local node storage path for disk usage |
INK_L1_FAILOVER_STATUS |
http://127.0.0.1:18545/readyz |
Optional local L1 relay health |
A static frontend does not run server/server.mjs. On Vercel, /api/* and /testnet/api/* use api/gateway.mjs, which forwards to INK_PUBLIC_API_ORIGIN. Configure a public HTTPS reverse proxy (or Tailscale Funnel, not tailnet-only Serve) to the loopback server/public-gateway.mjs. Its fixed destination exposes explorer API routes and the live WebSocket; node RPC, metrics and static filesystem routes remain private. Set EXPLORER_BROWSER_ORIGIN on both workers to the exact site origin so explicit simulations and submissions pass their origin checks. The browser uses same-origin HTTP without a VPN or local-network permission. The WebSocket is discovered through /api/live/config; public HTTP snapshots keep live data updating if WebSockets are blocked.
Existing deployments with a server-side VITE_API_ORIGIN pointing to a .ts.net:4189 Serve origin migrate through the public port 8443 and /ink mount. New installations should set INK_PUBLIC_API_ORIGIN explicitly. Never put credentials or local node URLs in VITE_* variables. API requests must be tested through public DNS from outside the tailnet; successful tests on a VPN-connected machine are insufficient. Static hosting limits apply to source uploads (the proxy accepts up to 4 MiB). Deep links continue to use the single-page interface.
Browser wallets connect directly through EIP-6963 discovery, with a legacy EIP-1193 fallback. When several wallets are installed, users choose the provider explicitly; duplicate and late announcements are handled without requesting accounts during discovery. This path requires no connection-service account, project ID, relay or message signature. On mobile, use the wallet's built-in browser.
WalletConnect QR is optional: its button is offered only when a valid project ID is configured. WalletConnect's core wallet connections are free, and require a public project ID from the WalletConnect Dashboard. Configure WALLETCONNECT_PROJECT_ID on both API workers (or VITE_WALLETCONNECT_PROJECT_ID before building) and authorize the site's actual domains. Runtime configuration does not require another frontend build. Relay preparation times out after 30 seconds; an unauthorized origin shows a localized error immediately. Once the QR appears, users have three minutes to confirm or can cancel at any time. The QR contains a temporary pairing URI and is never logged. Connections request transaction permission only; the explorer does not request message signatures or private keys. The SDK is pinned to the Apache-2.0 release, with security fixes pinned in transitive dependencies; dependency upgrades must recheck licensing and advisories.
/approvals and the address Approvals section discover standard ERC-20/ERC-721 Approval and ERC-721/ERC-1155 ApprovalForAll events, then reread current permissions on a ready RPC at a canonical block. Saturated index ranges are split without skipping boundary events. Failed or cancelled scans remain explicitly incomplete. Only the owner on the selected chain can simulate and confirm a zero-value revoke; receipt success is followed by a fresh state read. Non-standard contracts, missing indexed events and Permit2 permissions are outside this discovery scope.
Ink Blockscout API v2 and Stats Service provide network-wide indexed history. Blockscout Contract Info supplies pool discovery and market estimates. OP-Reth and OP Node provide only the operator's independent live checks.
Public JSON responses are cached in memory and on disk. A verified disk response can be served for up to 24 hours when the public index rate-limits or becomes unavailable. NFT images are downloaded on first display into data/media-cache and then served from the same origin. Private-network targets, non-HTTPS sources, unsupported image types and files over 8 MB are rejected. Background pruning removes old files and aims to keep upstream snapshots under 256 MB and media under 512 MB; active writes can briefly exceed those limits. Cache folders are excluded from version control.
Pool prices, liquidity, market capitalisation and volume are third-party estimates. NFT metadata can be mutable. The UI labels both risks and never presents them as investment advice.
The complete release protocol is documented in docs/TEST_PROTOCOL.md. The final findings and scope are documented in docs/EXPLORER_AUDIT.md. Run npm run test:release against an isolated review instance for a logged campaign across all suites. Partial runs cannot certify a release.
With the production server running on port 4188:
npm run check
npm run build
npm run test:data
npm run test:integrity
npm run test:activity
npm run test:activity-server
npm run test:activity-live
npm run test:ws
npm run test:network-live
npm run test:ui
npm run test:a11y
npm run test:i18n
npm run test:security
npm run test:identicons
npm run test:content
npm run test:performance
npm run test:lighthouse
npm run test:loading
npm run test:address-loading
npm run test:chain-reconciliation
npm run test:contracts
npm run test:approvals
npm run test:public-proxy
npm run test:networks
npm run test:node-testnet
npm run test:node-readiness
npm run test:upstream-cache
npm run test:layout
npm run test:responsive
npm run test:space
npm run test:styleThe browser tests cover routes at desktop, tablet and mobile widths, plus menus, tabs, pagination, media, contract source, pools, analytics and localization. test:layout checks 20 route states at 12 widths, including long NFT lists. test:responsive checks each CSS breakpoint at nearby widths, keyboard and touch interactions, and empty or failed network responses. test:style compares rendered surfaces and controls with the shared design rules. test:content checks copy, metadata and labels; test:a11y checks serious and critical Axe findings. Browser tests need Chrome and a running production server.
Lighthouse runs mobile and desktop audits on six representative routes and writes reports under reports/lighthouse/. Set BASE_URL, LIGHTHOUSE_DIR, LIGHTHOUSE_ROUTES or LIGHTHOUSE_PROFILES to change the run. Its scores are lab measurements on your machine. test:loading delays API responses to check the loading state.
CI runs the dependency audit, TypeScript check, production build, deterministic chain-data/filter/node-readiness tests and HTTP security checks. Browser suites need Chrome and live upstream APIs; WebSocket and node-health assertions need synced Ink nodes. Run those suites against the release build before deployment.
On Transactions → Advanced filters, combine activity type, method selector, sender/recipient, token contract, dates and decimal amounts. Amount filters use ETH or token units; CSV keeps raw values and exports the displayed page. Criteria survive reload and pagination. Dates follow your device’s time zone.
GET /api/health— service and WebSocket healthGET /api/live/status— current stream stateWS /api/live—ink-observer.live.v1welcome, network and block framesGET /api/overviewand/api/network— composed overview and local node statusGET /api/explorer/*— allow-listed Blockscout-compatible readsGET /api/stats/*— statistics catalogue, counters and chart readsGET /api/names/*— name protocols, domains and registration eventsGET /api/dapps— selected network’s application cataloguePOST /api/verification/submitandGET /api/verification/status/:ticket— explicit contract-source publication and progressPOST /api/public-tags/submit— private proposals for operator reviewGET /api/contract-info/pools[/:address[/check]]— pool list/detail/cross-link dataGET /api/media?url=…— validated same-origin NFT/token image cachePOST /api/contract-rpc— restrictedeth_call,eth_estimateGas, chain/head/code/receipt reads; signing and broadcast remain in the user's wallet
The network selector opens /testnet/ for Ink Sepolia. The main server proxies this prefix to an isolated worker at 127.0.0.1:4190; the worker uses Sepolia Blockscout, statistics and contract metadata. Its local node ports are 8645 (execution) and 9645 (rollup). Mainnet remains on 8545/9545. The PM2 ecosystem file starts both explorer workers. Use pm2 startOrReload ecosystem.config.cjs --update-env; avoid importing an unrelated shell's PORT through a bare pm2 restart --update-env.
All testnet API and WebSocket paths carry the /testnet prefix. Network changes reload the page to discard state from the previous chain. Indexed history remains usable during node sync; network health and live blocks only represent the local node. Contract reads explicitly identify the public RPC fallback when the local node is not ready. The server never forwards signing, admin or transaction-broadcast methods.
On a contract address, open Read contract or Write contract. Select its ABI, an indexed proxy implementation, or paste a custom JSON ABI. Proxy calls target the proxy address. Writes require a browser wallet or WalletConnect, a successful simulation and confirmation inside that wallet. Large integers in JSON arrays must be quoted; payable amounts use ETH and other integer arguments use raw base units. Source verification runs inside the explorer and supports the Solidity/Vyper methods enabled by the index. WalletConnect QR requires a configured public project ID and an authorized site origin.
npm run test:contracts starts an isolated Anvil chain and explorer on ports 18546, 18547 and 4192, compiles the Solidity fixtures and verifies actual EVM state changes through the browser workflow. It never submits to public mainnet/testnet. It requires the development dependencies and Chrome. npm run test:networks audits both real networks with Chromium, Firefox and WebKit; install engines with npx playwright install firefox webkit and their OS dependencies. If your host needs a custom library path for those browsers, set INK_BROWSER_LIBS.
See docs/ARCHITECTURE.md for source boundaries and security decisions. See docs/API.md for endpoint shapes, errors and the WebSocket protocol. Use docs/FORKING.md to deploy the explorer elsewhere or adapt it to another chain.
Want to help? Start with the contributor guide. Documentation fixes, translations, accessibility improvements and reproducible bug reports are welcome; local Ink nodes are optional. Check issues labelled good first issue or help wanted when available. Use GitHub Discussions for questions and early ideas, and an issue for a specific change. Contributors follow the Code of Conduct. Report vulnerabilities as described in SECURITY.md, without posting exploit details publicly.
Ink Explorer is not affiliated with or endorsed by Ink, Kraken, Blockscout, GeckoTerminal or any listed protocol. “Ink” and third-party marks belong to their respective owners.
See third-party notices for the Ink mark, bundled fonts and external data sources.
Licensed under the MIT License.
Accounts, internal transactions, token transfers, deposits, withdrawals, batches, dispute games, user operations, names, gas, Dapps and the full statistics catalogue are available from Advanced → Explorer tools. Detail destinations and wallet receipts stay inside this explorer. The public index remains a data source.
Source verification requires consent to publish the submitted contract sources. No wallet signature or transaction is required. Standard compiler JSON preserves optimizer, libraries and compilation settings. Single-file and multipart inputs also expose these settings. Never upload confidential contract sources.
Public-label proposals are stored privately until an operator approves them.
Use npm run tags:review -- 57073 list (or 763373) on the server, then
npm run tags:review -- 57073 approve <request-id> or reject. The list includes
private contact details: keep it on the operator’s machine. Approval publishes
only labels and their chosen public metadata; it does not verify contract code.
The queue belongs to this explorer, independently of Blockscout’s moderation.